If the sink requests a rate change during FRL Link training, reduce
frl.rate_cap to the next lower FRL rate. The next mode compute then
uses this lower rate cap, so we do not attempt the failing rate again.

Signed-off-by: Ankit Nautiyal <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 27 ++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c 
b/drivers/gpu/drm/i915/display/intel_hdmi.c
index fe4923c82463..2b0cdb0719e2 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -3720,6 +3720,18 @@ intel_hdmi_frl_train_lts3(struct intel_encoder *encoder,
        return frl_train_complete_ltsp(encoder, crtc_state);
 }
 
+static int get_next_frl_rate(int curr_rate_gbps)
+{
+       int valid_rate[] = { 48, 40, 32, 24, 18, 9 };
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(valid_rate); i++)
+               if (valid_rate[i] < curr_rate_gbps)
+                       return valid_rate[i];
+
+       return -EINVAL;
+}
+
 static int get_ffe_level(int rate_gbps)
 {
        return 0;
@@ -3736,6 +3748,7 @@ int intel_hdmi_start_frl(struct intel_encoder *encoder,
        int req_rate = crtc_state->frl.required_lanes * 
crtc_state->frl.required_rate;
        int ffe_level = get_ffe_level(req_rate);
        enum frl_lt_status status;
+       int next_rate = -EINVAL;
 
        if (!crtc_state->frl.enable)
                return 0;
@@ -3769,10 +3782,22 @@ int intel_hdmi_start_frl(struct intel_encoder *encoder,
                            connector->base.id, connector->name,
                            intel_hdmi->frl.rate_gbps);
                return 0;
-       default:
+       case FRL_TRAIN_STOP:
+               next_rate = 0;
+               break;
+       case FRL_CHANGE_RATE:
+               next_rate = get_next_frl_rate(req_rate);
                break;
+       case FRL_TRAIN_RETRAIN:
+               fallthrough;
+       default:
+               goto ltsl_tmds_mode;
        }
 
+       if (next_rate >= 0)
+               intel_hdmi->frl.rate_cap = next_rate;
+
+ltsl_tmds_mode:
        if (crtc_state->frl.enable && !intel_hdmi->frl.trained)
                drm_err(display->drm,
                        "[CONNECTOR:%d:%s] FRL Training Failed with rate=%d\n",
-- 
2.50.1

Reply via email to