Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/i915/dp: Read/ack sink count and sink IRQs for SST as it's done for MST

Read and ack the sink count, sink device and link service IRQs for SST
the same way this is done for MST, the read/ack happening in separate
steps via an ESI (Event Status Indicator) vector.

The above way is more efficient, since on newer (DPCD_REV >= 1.2) sinks
the DP_SINK_COUNT_ESI..DP_LINK_SERVICE_IRQ_VECTOR_ESI0 registers can be
read out in one AUX transaction - and the 3 last one written in one
transaction. Also this allows sharing more of the SST and MST IRQ
handling code (done as a follow-up).

For now keep the current behavior of always reading the legacy
DP_SINK_COUNT, DP_DEVICE_SERVICE_IRQ_VECTOR registers and not reading
the DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1 register.

v2: Document the ESI vector get/ack helper fnuctions' return value.
(Jani, Luca)

Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Luca Coelho <luciano.coelho@intel.com>
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://patch.msgid.link/20260225164618.1261368-16-imre.deak@intel.com

Imre Deak a4e50c53 7b056551

+79 -63
+79 -63
drivers/gpu/drm/i915/display/intel_dp.c
··· 4965 4965 return false; 4966 4966 } 4967 4967 4968 + /* Return %true if reading the ESI vector succeeded, %false otherwise. */ 4969 + static bool intel_dp_get_sink_irq_esi_sst(struct intel_dp *intel_dp, u8 esi[4]) 4970 + { 4971 + memset(esi, 0, 4); 4972 + 4973 + /* 4974 + * TODO: For DP_DPCD_REV >= 0x12 read 4975 + * DP_SINK_COUNT_ESI and DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0. 4976 + */ 4977 + if (drm_dp_dpcd_read_data(&intel_dp->aux, DP_SINK_COUNT, esi, 2) != 0) 4978 + return false; 4979 + 4980 + if (intel_dp->dpcd[DP_DPCD_REV] < DP_DPCD_REV_12) 4981 + return true; 4982 + 4983 + /* TODO: Read DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1 as well */ 4984 + if (drm_dp_dpcd_read_byte(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, &esi[3]) != 0) 4985 + return false; 4986 + 4987 + return true; 4988 + } 4989 + 4990 + /* Return %true if acking the ESI vector IRQ events succeeded, %false otherwise. */ 4991 + static bool intel_dp_ack_sink_irq_esi_sst(struct intel_dp *intel_dp, u8 esi[4]) 4992 + { 4993 + /* 4994 + * TODO: For DP_DPCD_REV >= 0x12 write 4995 + * DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 4996 + */ 4997 + if (drm_dp_dpcd_write_byte(&intel_dp->aux, DP_DEVICE_SERVICE_IRQ_VECTOR, esi[1]) != 0) 4998 + return false; 4999 + 5000 + if (intel_dp->dpcd[DP_DPCD_REV] < DP_DPCD_REV_12) 5001 + return true; 5002 + 5003 + /* TODO: Read DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1 as well */ 5004 + if (drm_dp_dpcd_write_byte(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, esi[3]) != 0) 5005 + return false; 5006 + 5007 + return true; 5008 + } 5009 + 5010 + /* 5011 + * Return %true if reading the ESI vector and acking the ESI IRQ events succeeded, 5012 + * %false otherwise. 5013 + */ 5014 + static bool intel_dp_get_and_ack_sink_irq_esi_sst(struct intel_dp *intel_dp, u8 esi[4]) 5015 + { 5016 + struct intel_display *display = to_intel_display(intel_dp); 5017 + struct intel_connector *connector = intel_dp->attached_connector; 5018 + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; 5019 + 5020 + if (!intel_dp_get_sink_irq_esi_sst(intel_dp, esi)) 5021 + return false; 5022 + 5023 + drm_dbg_kms(display->drm, 5024 + "[CONNECTOR:%d:%s][ENCODER:%d:%s] DPRX ESI: %4ph\n", 5025 + connector->base.base.id, connector->base.name, 5026 + encoder->base.base.id, encoder->base.name, 5027 + esi); 5028 + 5029 + if (mem_is_zero(&esi[1], 3)) 5030 + return true; 5031 + 5032 + if (!intel_dp_ack_sink_irq_esi_sst(intel_dp, esi)) 5033 + return false; 5034 + 5035 + return true; 5036 + } 5037 + 4968 5038 bool 4969 5039 intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state, 4970 5040 const struct drm_connector_state *conn_state) ··· 5855 5785 intel_encoder_link_check_queue_work(encoder, 0); 5856 5786 } 5857 5787 5858 - /* 5859 - * Return %true if a full connector reprobe is required due to a failure while 5860 - * reading or acking the device service IRQs. 5861 - */ 5862 - static bool intel_dp_get_and_ack_device_service_irq(struct intel_dp *intel_dp, u8 *irq_mask) 5863 - { 5864 - u8 val; 5865 - 5866 - *irq_mask = 0; 5867 - 5868 - if (drm_dp_dpcd_readb(&intel_dp->aux, 5869 - DP_DEVICE_SERVICE_IRQ_VECTOR, &val) != 1) 5870 - return false; 5871 - 5872 - if (!val) 5873 - return true; 5874 - 5875 - if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_DEVICE_SERVICE_IRQ_VECTOR, val) != 1) 5876 - return false; 5877 - 5878 - *irq_mask = val; 5879 - 5880 - return true; 5881 - } 5882 - 5883 5788 static void intel_dp_handle_device_service_irq(struct intel_dp *intel_dp, u8 irq_mask) 5884 5789 { 5885 5790 struct intel_display *display = to_intel_display(intel_dp); ··· 5869 5824 drm_dbg_kms(display->drm, "Sink specific irq unhandled\n"); 5870 5825 } 5871 5826 5872 - /* Return %true if reading and acking the link service IRQs succeeded. */ 5873 - static bool intel_dp_get_and_ack_link_service_irq(struct intel_dp *intel_dp, u8 *irq_mask) 5874 - { 5875 - u8 val; 5876 - 5877 - *irq_mask = 0; 5878 - 5879 - if (intel_dp->dpcd[DP_DPCD_REV] < DP_DPCD_REV_12) 5880 - return true; 5881 - 5882 - if (drm_dp_dpcd_readb(&intel_dp->aux, 5883 - DP_LINK_SERVICE_IRQ_VECTOR_ESI0, &val) != 1) 5884 - return false; 5885 - 5886 - if (!val) 5887 - return true; 5888 - 5889 - if (drm_dp_dpcd_writeb(&intel_dp->aux, 5890 - DP_LINK_SERVICE_IRQ_VECTOR_ESI0, val) != 1) 5891 - return false; 5892 - 5893 - *irq_mask = val; 5894 - 5895 - return true; 5896 - } 5897 5827 5898 5828 /* 5899 5829 * Return %true if a full connector reprobe is required after handling a link ··· 5910 5890 intel_dp_short_pulse(struct intel_dp *intel_dp) 5911 5891 { 5912 5892 bool reprobe_needed = false; 5913 - u8 irq_mask; 5893 + u8 esi[4] = {}; 5914 5894 5915 5895 intel_dp_test_reset(intel_dp); 5916 5896 5897 + if (!intel_dp_get_and_ack_sink_irq_esi_sst(intel_dp, esi)) 5898 + return false; 5899 + 5917 5900 /* 5918 - * Now read the DPCD to see if it's actually running 5919 5901 * If the current value of sink count doesn't match with 5920 - * the value that was stored earlier or dpcd read failed 5921 - * we need to do full detection 5902 + * the value that was stored earlier we need to do full 5903 + * detection. 5922 5904 */ 5923 5905 if (intel_dp_has_sink_count(intel_dp) && 5924 - drm_dp_read_sink_count(&intel_dp->aux) != intel_dp->sink_count) 5906 + DP_GET_SINK_COUNT(esi[0]) != intel_dp->sink_count) 5925 5907 /* No need to proceed if we are going to do full detect */ 5926 5908 return false; 5927 5909 5928 - if (!intel_dp_get_and_ack_device_service_irq(intel_dp, &irq_mask)) 5929 - return false; 5910 + intel_dp_handle_device_service_irq(intel_dp, esi[1]); 5930 5911 5931 - intel_dp_handle_device_service_irq(intel_dp, irq_mask); 5932 - 5933 - if (!intel_dp_get_and_ack_link_service_irq(intel_dp, &irq_mask)) 5934 - return false; 5935 - 5936 - if (intel_dp_handle_link_service_irq(intel_dp, irq_mask)) 5912 + if (intel_dp_handle_link_service_irq(intel_dp, esi[3])) 5937 5913 reprobe_needed = true; 5938 5914 5939 5915 /* Handle CEC interrupts, if any */