Modes above the TMDS limits can still be driven over FRL. When the
TMDS check fails, fall back to an FRL check that runs the non-DSC FRL DFM
at the best case (min bpc, max FRL rate, min audio) to confirm the mode
fits.

The fallback is gated on intel_hdmi_can_support_frl(), added here as a
placeholder returning false, so the FRL path stays inactive until FRL
support is completed in a later change.

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

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c 
b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 67228b538e81..b82c636b46f9 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -62,6 +62,7 @@
 #include "intel_hdcp_regs.h"
 #include "intel_hdcp_shim.h"
 #include "intel_hdmi.h"
+#include "intel_hdmi_frl_dfm.h"
 #include "intel_link_bw.h"
 #include "intel_lspcon.h"
 #include "intel_panel.h"
@@ -2021,6 +2022,51 @@ intel_hdmi_tmds_mode_clock_valid(struct drm_connector 
*_connector, int clock,
        return status;
 }
 
+static u32
+get_drm_color_format(enum intel_output_format output_format)
+{
+       switch (output_format) {
+       case INTEL_OUTPUT_FORMAT_RGB:
+               return DRM_OUTPUT_COLOR_FORMAT_RGB444;
+       case INTEL_OUTPUT_FORMAT_YCBCR420:
+               return DRM_OUTPUT_COLOR_FORMAT_YCBCR420;
+       case INTEL_OUTPUT_FORMAT_YCBCR444:
+               return DRM_OUTPUT_COLOR_FORMAT_YCBCR444;
+       default:
+               return DRM_OUTPUT_COLOR_FORMAT_RGB444;
+       }
+}
+
+static enum drm_mode_status
+intel_hdmi_frl_mode_clock_valid(struct intel_connector *connector,
+                               const struct drm_display_mode *mode,
+                               enum intel_output_format output_format)
+{
+       struct intel_hdmi *hdmi = intel_attached_hdmi(connector);
+       struct intel_hdmi_frl_dfm frl_dfm = {};
+       int max_rate = hdmi->max_frl_rate;
+       int lanes = max_rate < 24 ? 3 : 4;
+
+       frl_dfm.config.pixel_clock_nominal_khz = mode->clock;
+       frl_dfm.config.hactive = mode->hdisplay;
+       frl_dfm.config.hblank = mode->htotal - mode->hdisplay;
+
+       /* Use min bpc to check if mode can be supported */
+       frl_dfm.config.bpc = 8;
+       frl_dfm.config.color_format = get_drm_color_format(output_format);
+       frl_dfm.config.lanes = lanes;
+       frl_dfm.config.bit_rate_kbps = (max_rate * 1000000) / lanes;
+
+       /* min audio */
+       frl_dfm.config.audio_channels = 2;
+       frl_dfm.config.audio_hz = 48000;
+
+       if (!intel_hdmi_frl_dfm_nondsc_requirement_met(&frl_dfm))
+               return MODE_CLOCK_HIGH;
+
+       return MODE_OK;
+}
+
 static enum drm_mode_status
 intel_hdmi_sink_format_valid(struct intel_connector *connector,
                             const struct drm_display_mode *mode,
@@ -2045,6 +2091,13 @@ intel_hdmi_sink_format_valid(struct intel_connector 
*connector,
        }
 }
 
+static bool
+intel_hdmi_can_support_frl(struct intel_hdmi *intel_hdmi)
+{
+       /* TODO check for FRL support */
+       return false;
+}
+
 static enum drm_mode_status
 intel_hdmi_mode_valid_format(struct intel_connector *connector,
                             const struct drm_display_mode *mode,
@@ -2052,6 +2105,7 @@ intel_hdmi_mode_valid_format(struct intel_connector 
*connector,
                             enum intel_output_format sink_format)
 {
        struct intel_display *display = to_intel_display(connector);
+       struct intel_hdmi *hdmi = intel_attached_hdmi(connector);
        enum drm_mode_status status;
 
        status = intel_hdmi_sink_format_valid(connector, mode,
@@ -2063,7 +2117,12 @@ intel_hdmi_mode_valid_format(struct intel_connector 
*connector,
        if (status != MODE_OK)
                return status;
 
-       return intel_hdmi_tmds_mode_clock_valid(&connector->base, clock, 
has_hdmi_sink, sink_format);
+       status = intel_hdmi_tmds_mode_clock_valid(&connector->base, clock, 
has_hdmi_sink, sink_format);
+
+       if (status != MODE_OK && intel_hdmi_can_support_frl(hdmi))
+               status = intel_hdmi_frl_mode_clock_valid(connector, mode, 
sink_format);
+
+       return status;
 }
 
 static enum drm_mode_status
-- 
2.50.1

Reply via email to