Currently the hikey dsi logic cannot generate accurate byte
clocks values for all pixel clock values. Thus if a mode clock
is selected that cannot match the calculated byte clock, the
device will boot with a blank screen.

This patch uses the new mode_valid callback to enforces known
good mode clocks for well known resolutions, which should allow
the display to work from given EDID options, and ensures for a
given resolution & refresh, the right mode clock is selected.

Cc: Daniel Vetter <daniel.vet...@intel.com>
Cc: Jani Nikula <jani.nik...@linux.intel.com>
Cc: Sean Paul <seanp...@chromium.org>
Cc: David Airlie <airl...@linux.ie>
Cc: Rob Clark <robdcl...@gmail.com>
Cc: Xinliang Liu <xinliang....@linaro.org>
Cc: Xinliang Liu <z.liuxinli...@hisilicon.com>
Cc: Rongrong Zou <zourongr...@gmail.com>
Cc: Xinwei Kong <kong.kongxin...@hisilicon.com>
Cc: Chen Feng <puck.c...@hisilicon.com>
Cc: Archit Taneja <arch...@codeaurora.org>
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz <john.stu...@linaro.org>
---
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 38 +++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c 
b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
index afc2b5d..9161633 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
@@ -504,6 +504,43 @@ static void ade_crtc_disable(struct drm_crtc *crtc)
        acrtc->enable = false;
 }
 
+static enum drm_mode_status ade_crtc_mode_valid(struct drm_crtc *crtc,
+                                               struct drm_display_mode *mode)
+{
+       /*
+        * kirin_ade cannot generate all modes, so use the whitelist below
+        */
+       DRM_DEBUG("Checking mode %ix%i@%i clock: %i...",
+                 mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), 
mode->clock);
+       if ((mode->hdisplay == 1920 && mode->vdisplay == 1080 && mode->clock == 
148500) ||
+           (mode->hdisplay == 1920 && mode->vdisplay == 1080 && mode->clock == 
80192)  ||
+           (mode->hdisplay == 1920 && mode->vdisplay == 1080 && mode->clock == 
74250)  ||
+           (mode->hdisplay == 1920 && mode->vdisplay == 1080 && mode->clock == 
61855)  ||
+           (mode->hdisplay == 1680 && mode->vdisplay == 1050 && mode->clock == 
147116) ||
+           (mode->hdisplay == 1680 && mode->vdisplay == 1050 && mode->clock == 
146250) ||
+           (mode->hdisplay == 1680 && mode->vdisplay == 1050 && mode->clock == 
144589) ||
+           (mode->hdisplay == 1600 && mode->vdisplay == 1200 && mode->clock == 
160961) ||
+           (mode->hdisplay == 1600 && mode->vdisplay == 900  && mode->clock == 
118963) ||
+           (mode->hdisplay == 1440 && mode->vdisplay == 900  && mode->clock == 
126991) ||
+           (mode->hdisplay == 1280 && mode->vdisplay == 1024 && mode->clock == 
128946) ||
+           (mode->hdisplay == 1280 && mode->vdisplay == 1024 && mode->clock == 
98619)  ||
+           (mode->hdisplay == 1280 && mode->vdisplay == 960  && mode->clock == 
102081) ||
+           (mode->hdisplay == 1280 && mode->vdisplay == 800  && mode->clock == 
83496)  ||
+           (mode->hdisplay == 1280 && mode->vdisplay == 720  && mode->clock == 
74440)  ||
+           (mode->hdisplay == 1280 && mode->vdisplay == 720  && mode->clock == 
74250)  ||
+           (mode->hdisplay == 1024 && mode->vdisplay == 768  && mode->clock == 
78800)  ||
+           (mode->hdisplay == 1024 && mode->vdisplay == 768  && mode->clock == 
75000)  ||
+           (mode->hdisplay == 1024 && mode->vdisplay == 768  && mode->clock == 
81833)  ||
+           (mode->hdisplay == 800  && mode->vdisplay == 600  && mode->clock == 
48907)  ||
+           (mode->hdisplay == 800  && mode->vdisplay == 600  && mode->clock == 
40000)) {
+               mode->type |= DRM_MODE_TYPE_PREFERRED;
+               DRM_DEBUG("OK\n");
+               return MODE_OK;
+       }
+       DRM_DEBUG("BAD\n");
+       return MODE_BAD;
+}
+
 static void ade_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
        struct ade_crtc *acrtc = to_ade_crtc(crtc);
@@ -557,6 +594,7 @@ static void ade_crtc_atomic_flush(struct drm_crtc *crtc,
 static const struct drm_crtc_helper_funcs ade_crtc_helper_funcs = {
        .enable         = ade_crtc_enable,
        .disable        = ade_crtc_disable,
+       .mode_valid     = ade_crtc_mode_valid,
        .mode_set_nofb  = ade_crtc_mode_set_nofb,
        .atomic_begin   = ade_crtc_atomic_begin,
        .atomic_flush   = ade_crtc_atomic_flush,
-- 
2.7.4

Reply via email to