When I connected my cubieboard running 4.15-rc1 to my 4k display I got no 
picture. Some
digging found that there is no check against the upper pixelclock limit of the 
HDMI
output, so X selects a 4kp60 format at 594 MHz, which obviously won't work.

The patch below adds a check for the upper bound of what this hardware can do, 
and
it checks if the requested tmds clock can be obtained.

It also allows for the ± 0.5% pixel clock variation that the HDMI spec permits.

That code is based on commit 22d0be2a557e53a22feb484e8fce255fe09e6ad5 from
Jose Abreu for drm/arc.

Signed-off-by: Hans Verkuil <hans.verk...@cisco.com>
---
Changes since v3:
- Move the mode_valid callback to struct drm_encoder_helper_funcs.
  I'm assuming this is the correct struct, since this check is specific to the
  hdmi encoder.
Changes since v2:
- Allow for the 0.5% variation.
---
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c 
b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index dda904ec0534..500b6fb3e028 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -175,11 +175,31 @@ static void sun4i_hdmi_mode_set(struct drm_encoder 
*encoder,
        writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG);
 }

+static enum drm_mode_status sun4i_hdmi_mode_valid(struct drm_encoder *encoder,
+                                       const struct drm_display_mode *mode)
+{
+       struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
+       unsigned long rate = mode->clock * 1000;
+       unsigned long diff = rate / 200; /* +-0.5% allowed by HDMI spec */
+       long rounded_rate;
+
+       /* 165 MHz is the typical max pixelclock frequency for HDMI <= 1.2 */
+       if (rate > 165000000)
+               return MODE_CLOCK_HIGH;
+       rounded_rate = clk_round_rate(hdmi->tmds_clk, rate);
+       if (rounded_rate > 0 &&
+           max_t(unsigned long, rounded_rate, rate) -
+           min_t(unsigned long, rounded_rate, rate) < diff)
+               return MODE_OK;
+       return MODE_NOCLOCK;
+}
+
 static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = {
        .atomic_check   = sun4i_hdmi_atomic_check,
        .disable        = sun4i_hdmi_disable,
        .enable         = sun4i_hdmi_enable,
        .mode_set       = sun4i_hdmi_mode_set,
+       .mode_valid     = sun4i_hdmi_mode_valid,
 };

 static const struct drm_encoder_funcs sun4i_hdmi_funcs = {
-- 
2.15.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to