drm/display/dp: Define function to setup Extended wake time
authorSuraj Kandpal <suraj.kandpal@intel.com>
Wed, 22 Jan 2025 05:33:57 +0000 (11:03 +0530)
committerSuraj Kandpal <suraj.kandpal@intel.com>
Tue, 4 Feb 2025 12:27:31 +0000 (17:57 +0530)
Extended wake timeout request helps to give additional
time by reading the DPCD register through which sink requests the
minimal amount of time required to wake the sink up.
Source  device shall keep retying the AUX tansaction till the
extended timeout that is being granted for LTTPRs from the
sink device.

--v2
-Add documentation [Dmitry]

Spec: DP v2.1 Section 3.6.12.3
Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20250122053358.1545039-3-suraj.kandpal@intel.com
drivers/gpu/drm/display/drm_dp_helper.c
include/drm/display/drm_dp_helper.h

index da3c8521a7fa7d3c9761377363cdd4b44ab1106e..c488d160a3c1fa2a394afd86ee63784cc5b13f68 100644 (file)
@@ -459,6 +459,64 @@ void drm_dp_lttpr_link_train_channel_eq_delay(const struct drm_dp_aux *aux,
 }
 EXPORT_SYMBOL(drm_dp_lttpr_link_train_channel_eq_delay);
 
+/**
+ * drm_dp_lttpr_wake_timeout_setup() - Grant extended time for sink to wake up
+ * @aux: The DP AUX channel to use
+ * @transparent_mode: This is true if lttpr is in transparent mode
+ *
+ * This function checks if the sink needs any extended wake time, if it does
+ * it grants this request. Post this setup the source device can keep trying
+ * the Aux transaction till the granted wake timeout.
+ * If this function is not called all Aux transactions are expected to take
+ * a default of 1ms before they throw an error.
+ */
+void drm_dp_lttpr_wake_timeout_setup(struct drm_dp_aux *aux, bool transparent_mode)
+{
+       u8 val = 1;
+       int ret;
+
+       if (transparent_mode) {
+               static const u8 timeout_mapping[] = {
+                       [DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_1_MS] = 1,
+                       [DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_20_MS] = 20,
+                       [DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_40_MS] = 40,
+                       [DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_60_MS] = 60,
+                       [DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_80_MS] = 80,
+                       [DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_100_MS] = 100,
+               };
+
+               ret = drm_dp_dpcd_readb(aux, DP_EXTENDED_DPRX_SLEEP_WAKE_TIMEOUT_REQUEST, &val);
+               if (ret != 1) {
+                       drm_dbg_kms(aux->drm_dev,
+                                   "Failed to read Extended sleep wake timeout request\n");
+                       return;
+               }
+
+               val = (val < sizeof(timeout_mapping) && timeout_mapping[val]) ?
+                       timeout_mapping[val] : 1;
+
+               if (val > 1)
+                       drm_dp_dpcd_writeb(aux,
+                                          DP_EXTENDED_DPRX_SLEEP_WAKE_TIMEOUT_GRANT,
+                                          DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_GRANTED);
+       } else {
+               ret = drm_dp_dpcd_readb(aux, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &val);
+               if (ret != 1) {
+                       drm_dbg_kms(aux->drm_dev,
+                                   "Failed to read Extended sleep wake timeout request\n");
+                       return;
+               }
+
+               val = (val & DP_EXTENDED_WAKE_TIMEOUT_REQUEST_MASK) ?
+                       (val & DP_EXTENDED_WAKE_TIMEOUT_REQUEST_MASK) * 10 : 1;
+
+               if (val > 1)
+                       drm_dp_dpcd_writeb(aux, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT,
+                                          DP_EXTENDED_WAKE_TIMEOUT_GRANT);
+       }
+}
+EXPORT_SYMBOL(drm_dp_lttpr_wake_timeout_setup);
+
 u8 drm_dp_link_rate_to_bw_code(int link_rate)
 {
        switch (link_rate) {
index 8f4054a560396a43750570a8c2e95624039ab8ad..89a34dff85a4e27065a8f5d7b64407debc11c778 100644 (file)
@@ -633,6 +633,7 @@ int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
 int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
 bool drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
 bool drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
+void drm_dp_lttpr_wake_timeout_setup(struct drm_dp_aux *aux, bool transparent_mode);
 
 void drm_dp_remote_aux_init(struct drm_dp_aux *aux);
 void drm_dp_aux_init(struct drm_dp_aux *aux);