<div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_extra"><br><div class="gmail_quote">On 23 August 2017 at 02:42, John Stultz <span dir="ltr"><<a href="mailto:john.stultz@linaro.org" target="_blank">john.stultz@linaro.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Currently the hikey dsi logic cannot generate accurate byte<br>
clocks values for all pixel clock values. Thus if a mode clock<br>
is selected that cannot match the calculated byte clock, the<br>
device will boot with a blank screen.<br>
<br>
This patch uses the new mode_valid callback (many thanks to<br>
Jose Abreu for upstreaming it!) to ensure we don't select<br>
modes we cannot generate.<br>
<br>
Also, since the ade crtc code will adjust the mode in mode_set,<br>
this patch also adds a mode_fixup callback which we use to make<br>
sure we are validating the mode clock that will eventually be<br>
used.<br>
<br>
Cc: Daniel Vetter <<a href="mailto:daniel.vetter@intel.com">daniel.vetter@intel.com</a>><br>
Cc: Jani Nikula <<a href="mailto:jani.nikula@linux.intel.com">jani.nikula@linux.intel.com</a>><br>
Cc: Sean Paul <<a href="mailto:seanpaul@chromium.org">seanpaul@chromium.org</a>><br>
Cc: David Airlie <<a href="mailto:airlied@linux.ie">airlied@linux.ie</a>><br>
Cc: Rob Clark <<a href="mailto:robdclark@gmail.com">robdclark@gmail.com</a>><br>
Cc: Xinliang Liu <<a href="mailto:xinliang.liu@linaro.org">xinliang.liu@linaro.org</a>><br>
Cc: Xinliang Liu <<a href="mailto:z.liuxinliang@hisilicon.com">z.liuxinliang@hisilicon.com</a>><br>
Cc: Rongrong Zou <<a href="mailto:zourongrong@gmail.com">zourongrong@gmail.com</a>><br>
Cc: Xinwei Kong <<a href="mailto:kong.kongxinwei@hisilicon.com">kong.kongxinwei@hisilicon.com</a><wbr>><br>
Cc: Chen Feng <<a href="mailto:puck.chen@hisilicon.com">puck.chen@hisilicon.com</a>><br>
Cc: Jose Abreu <<a href="mailto:Jose.Abreu@synopsys.com">Jose.Abreu@synopsys.com</a>><br>
Cc: Archit Taneja <<a href="mailto:architt@codeaurora.org">architt@codeaurora.org</a>><br>
Cc: <a href="mailto:dri-devel@lists.freedesktop.org">dri-devel@lists.freedesktop.<wbr>org</a><br>
Reviewed-by: Sean Paul <<a href="mailto:seanpaul@chromium.org">seanpaul@chromium.org</a>><br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">​Thanks John,</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">This patch looks good to me.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><span class="gmail-il" style="font-family:arial,sans-serif;font-size:12.8px;background-color:rgb(255,255,255)">Reviewed-by: Xinliang</span><span style="font-family:arial,sans-serif;font-size:12.8px"> Liu <</span><a href="mailto:xinliang.liu@linaro.org" style="font-family:arial,sans-serif;font-size:12.8px"><span class="gmail-il">xinliang</span>.liu@linaro.org</a><span style="font-family:arial,sans-serif;font-size:12.8px">></span>​</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Thanks,</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Xinliang</div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Signed-off-by: John Stultz <<a href="mailto:john.stultz@linaro.org">john.stultz@linaro.org</a>><br>
---<br>
v2: Reworked to calculate if modeclock matches the phy's<br>
    byteclock, rather then using a whitelist of known modes.<br>
<br>
v3: Reworked to check across all possible crtcs (even though for<br>
    us there is only one), and use mode_fixup instead of a custom<br>
    function, as suggested by Jose and Daniel.<br>
<br>
v4: Fixes and improved error handling as suggested by Jose.<br>
<br>
v5: Small typo fix noted by Sean<br>
---<br>
 drivers/gpu/drm/hisilicon/<wbr>kirin/dw_drm_dsi.c    | 67 +++++++++++++++++++++++++<br>
 drivers/gpu/drm/hisilicon/<wbr>kirin/kirin_drm_ade.c | 14 ++++++<br>
 2 files changed, 81 insertions(+)<br>
<br>
diff --git a/drivers/gpu/drm/hisilicon/<wbr>kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/<wbr>kirin/dw_drm_dsi.c<br>
index f77dcfa..b4c7af3 100644<br>
--- a/drivers/gpu/drm/hisilicon/<wbr>kirin/dw_drm_dsi.c<br>
+++ b/drivers/gpu/drm/hisilicon/<wbr>kirin/dw_drm_dsi.c<br>
@@ -603,6 +603,72 @@ static void dsi_encoder_enable(struct drm_encoder *encoder)<br>
        dsi->enable = true;<br>
 }<br>
<br>
+static enum drm_mode_status dsi_encoder_phy_mode_valid(<br>
+                                       struct drm_encoder *encoder,<br>
+                                       const struct drm_display_mode *mode)<br>
+{<br>
+       struct dw_dsi *dsi = encoder_to_dsi(encoder);<br>
+       struct mipi_phy_params phy;<br>
+       u32 bpp = mipi_dsi_pixel_format_to_bpp(<wbr>dsi->format);<br>
+       u32 req_kHz, act_kHz, lane_byte_clk_kHz;<br>
+<br>
+       /* Calculate the lane byte clk using the adjusted mode clk */<br>
+       memset(&phy, 0, sizeof(phy));<br>
+       req_kHz = mode->clock * bpp / dsi->lanes;<br>
+       act_kHz = dsi_calc_phy_rate(req_kHz, &phy);<br>
+       lane_byte_clk_kHz = act_kHz / 8;<br>
+<br>
+       DRM_DEBUG_DRIVER("Checking mode %ix%i-%i@%i clock: %i...",<br>
+                       mode->hdisplay, mode->vdisplay, bpp,<br>
+                       drm_mode_vrefresh(mode), mode->clock);<br>
+<br>
+       /*<br>
+        * Make sure the adjusted mode clock and the lane byte clk<br>
+        * have a common denominator base frequency<br>
+        */<br>
+       if (mode->clock/dsi->lanes == lane_byte_clk_kHz/3) {<br>
+               DRM_DEBUG_DRIVER("OK!\n");<br>
+               return MODE_OK;<br>
+       }<br>
+<br>
+       DRM_DEBUG_DRIVER("BAD!\n");<br>
+       return MODE_BAD;<br>
+}<br>
+<br>
+static enum drm_mode_status dsi_encoder_mode_valid(struct drm_encoder *encoder,<br>
+                                       const struct drm_display_mode *mode)<br>
+<br>
+{<br>
+       const struct drm_crtc_helper_funcs *crtc_funcs = NULL;<br>
+       struct drm_crtc *crtc = NULL;<br>
+       struct drm_display_mode adj_mode;<br>
+       enum drm_mode_status ret;<br>
+<br>
+       /*<br>
+        * The crtc might adjust the mode, so go through the<br>
+        * possible crtcs (technically just one) and call<br>
+        * mode_fixup to figure out the adjusted mode before we<br>
+        * validate it.<br>
+        */<br>
+       drm_for_each_crtc(crtc, encoder->dev) {<br>
+               /*<br>
+                * reset adj_mode to the mode value each time,<br>
+                * so we don't adjust the mode twice<br>
+                */<br>
+               drm_mode_copy(&adj_mode, mode);<br>
+<br>
+               crtc_funcs = crtc->helper_private;<br>
+               if (crtc_funcs && crtc_funcs->mode_fixup)<br>
+                       if (!crtc_funcs->mode_fixup(crtc, mode, &adj_mode))<br>
+                               return MODE_BAD;<br>
+<br>
+               ret = dsi_encoder_phy_mode_valid(<wbr>encoder, &adj_mode);<br>
+               if (ret != MODE_OK)<br>
+                       return ret;<br>
+       }<br>
+       return MODE_OK;<br>
+}<br>
+<br>
 static void dsi_encoder_mode_set(struct drm_encoder *encoder,<br>
                                 struct drm_display_mode *mode,<br>
                                 struct drm_display_mode *adj_mode)<br>
@@ -622,6 +688,7 @@ static int dsi_encoder_atomic_check(<wbr>struct drm_encoder *encoder,<br>
<br>
 static const struct drm_encoder_helper_funcs dw_encoder_helper_funcs = {<br>
        .atomic_check   = dsi_encoder_atomic_check,<br>
+       .mode_valid     = dsi_encoder_mode_valid,<br>
        .mode_set       = dsi_encoder_mode_set,<br>
        .enable         = dsi_encoder_enable,<br>
        .disable        = dsi_encoder_disable<br>
diff --git a/drivers/gpu/drm/hisilicon/<wbr>kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/<wbr>kirin/kirin_drm_ade.c<br>
index c96c228..dec7f4e 100644<br>
--- a/drivers/gpu/drm/hisilicon/<wbr>kirin/kirin_drm_ade.c<br>
+++ b/drivers/gpu/drm/hisilicon/<wbr>kirin/kirin_drm_ade.c<br>
@@ -178,6 +178,19 @@ static void ade_init(struct ade_hw_ctx *ctx)<br>
                        FRM_END_START_MASK, REG_EFFECTIVE_IN_ADEEN_FRMEND)<wbr>;<br>
 }<br>
<br>
+static bool ade_crtc_mode_fixup(struct drm_crtc *crtc,<br>
+                               const struct drm_display_mode *mode,<br>
+                               struct drm_display_mode *adjusted_mode)<br>
+{<br>
+       struct ade_crtc *acrtc = to_ade_crtc(crtc);<br>
+       struct ade_hw_ctx *ctx = acrtc->ctx;<br>
+<br>
+       adjusted_mode->clock =<br>
+               clk_round_rate(ctx->ade_pix_<wbr>clk, mode->clock * 1000) / 1000;<br>
+       return true;<br>
+}<br>
+<br>
+<br>
 static void ade_set_pix_clk(struct ade_hw_ctx *ctx,<br>
                            struct drm_display_mode *mode,<br>
                            struct drm_display_mode *adj_mode)<br>
@@ -555,6 +568,7 @@ static void ade_crtc_atomic_flush(struct drm_crtc *crtc,<br>
 static const struct drm_crtc_helper_funcs ade_crtc_helper_funcs = {<br>
        .enable         = ade_crtc_enable,<br>
        .disable        = ade_crtc_disable,<br>
+       .mode_fixup     = ade_crtc_mode_fixup,<br>
        .mode_set_nofb  = ade_crtc_mode_set_nofb,<br>
        .atomic_begin   = ade_crtc_atomic_begin,<br>
        .atomic_flush   = ade_crtc_atomic_flush,<br>
<span class="gmail-HOEnZb"><font color="#888888">--<br>
2.7.4<br>
<br>
</font></span></blockquote></div><br></div></div>