Message ID | 20180709173200.238457-6-seanpaul@chromium.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Monday 09 July 2018 11:01 PM, Sean Paul wrote: > From: Chandan Uddaraju <chandanu@codeaurora.org> > > For dual dsi mode, the horizontal timing needs > to be divided by half since both the dsi controllers > will be driving this panel. Adjust the pixel clock and > DSI timing accordingly. Reviewed-by: Archit Taneja <architt@codeaurora.org> > > Changes in V2: > --Removed Change-Id from the commit text tags. > > Changes in V3: > --Instead of adjusting the DRM mode structure, divide > the clocks and horizontal timings in DSI host just > before configuring the values. > > Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org> > Signed-off-by: Sean Paul <seanpaul@chromium.org> > --- > drivers/gpu/drm/msm/dsi/dsi.h | 6 ++- > drivers/gpu/drm/msm/dsi/dsi_host.c | 55 +++++++++++++++++++++------ > drivers/gpu/drm/msm/dsi/dsi_manager.c | 7 ++-- > 3 files changed, 52 insertions(+), 16 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h > index 70d9a9a47acd..01c38f67d699 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi.h > +++ b/drivers/gpu/drm/msm/dsi/dsi.h > @@ -162,7 +162,8 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, > int msm_dsi_host_enable(struct mipi_dsi_host *host); > int msm_dsi_host_disable(struct mipi_dsi_host *host); > int msm_dsi_host_power_on(struct mipi_dsi_host *host, > - struct msm_dsi_phy_shared_timings *phy_shared_timings); > + struct msm_dsi_phy_shared_timings *phy_shared_timings, > + bool is_dual_dsi); > int msm_dsi_host_power_off(struct mipi_dsi_host *host); > int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host, > struct drm_display_mode *mode); > @@ -175,7 +176,8 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, > struct msm_dsi_pll *src_pll); > void msm_dsi_host_reset_phy(struct mipi_dsi_host *host); > void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host, > - struct msm_dsi_phy_clk_request *clk_req); > + struct msm_dsi_phy_clk_request *clk_req, > + bool is_dual_dsi); > void msm_dsi_host_destroy(struct mipi_dsi_host *host); > int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, > struct drm_device *dev); > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c > index 2f1a2780658a..671039b7b75b 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c > @@ -118,6 +118,7 @@ struct msm_dsi_host { > struct clk *byte_intf_clk; > > u32 byte_clk_rate; > + u32 pixel_clk_rate; > u32 esc_clk_rate; > > /* DSI v2 specific clocks */ > @@ -511,7 +512,7 @@ static int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host) > goto error; > } > > - ret = clk_set_rate(msm_host->pixel_clk, msm_host->mode->clock * 1000); > + ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate); > if (ret) { > pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret); > goto error; > @@ -592,7 +593,7 @@ static int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host) > goto error; > } > > - ret = clk_set_rate(msm_host->pixel_clk, msm_host->mode->clock * 1000); > + ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate); > if (ret) { > pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret); > goto error; > @@ -662,7 +663,7 @@ static void dsi_link_clk_disable(struct msm_dsi_host *msm_host) > } > } > > -static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host) > +static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host, bool is_dual_dsi) > { > struct drm_display_mode *mode = msm_host->mode; > const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; > @@ -676,14 +677,28 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host) > } > > pclk_rate = mode->clock * 1000; > + > + /* > + * For dual DSI mode, the current DRM mode has > + * the complete width of the panel. Since, the complete > + * panel is driven by two DSI controllers, the > + * the clock rates have to be split between > + * the two dsi controllers. Adjust the byte and > + * pixel clock rates for each dsi host accordingly. > + */ > + if (is_dual_dsi) > + pclk_rate /= 2; > + > if (lanes > 0) { > msm_host->byte_clk_rate = (pclk_rate * bpp) / (8 * lanes); > } else { > pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__); > msm_host->byte_clk_rate = (pclk_rate * bpp) / 8; > } > + msm_host->pixel_clk_rate = pclk_rate; > > - DBG("pclk=%d, bclk=%d", pclk_rate, msm_host->byte_clk_rate); > + DBG("pclk=%d, bclk=%d", msm_host->pixel_clk_rate, > + msm_host->byte_clk_rate); > > msm_host->esc_clk_rate = clk_get_rate(msm_host->esc_clk); > > @@ -885,7 +900,7 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, > dsi_write(msm_host, REG_DSI_CTRL, data); > } > > -static void dsi_timing_setup(struct msm_dsi_host *msm_host) > +static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) > { > struct drm_display_mode *mode = msm_host->mode; > u32 hs_start = 0, vs_start = 0; /* take sync start as 0 */ > @@ -897,10 +912,26 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host) > u32 ha_end = ha_start + mode->hdisplay; > u32 va_start = v_total - mode->vsync_start; > u32 va_end = va_start + mode->vdisplay; > + u32 hdisplay = mode->hdisplay; > u32 wc; > > DBG(""); > > + /* > + * For dual DSI mode, the current DRM mode has > + * the complete width of the panel. Since, the complete > + * panel is driven by two DSI controllers, the horizontal > + * timings have to be split between the two dsi controllers. > + * Adjust the DSI host timing values accordingly. > + */ > + if (is_dual_dsi) { > + h_total /= 2; > + hs_end /= 2; > + ha_start /= 2; > + ha_end /= 2; > + hdisplay /= 2; > + } > + > if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) { > dsi_write(msm_host, REG_DSI_ACTIVE_H, > DSI_ACTIVE_H_START(ha_start) | > @@ -921,7 +952,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host) > DSI_ACTIVE_VSYNC_VPOS_END(vs_end)); > } else { /* command mode */ > /* image data and 1 byte write_memory_start cmd */ > - wc = mode->hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1; > + wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1; > > dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM_CTRL, > DSI_CMD_MDP_STREAM_CTRL_WORD_COUNT(wc) | > @@ -931,7 +962,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host) > MIPI_DSI_DCS_LONG_WRITE)); > > dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM_TOTAL, > - DSI_CMD_MDP_STREAM_TOTAL_H_TOTAL(mode->hdisplay) | > + DSI_CMD_MDP_STREAM_TOTAL_H_TOTAL(hdisplay) | > DSI_CMD_MDP_STREAM_TOTAL_V_TOTAL(mode->vdisplay)); > } > } > @@ -2189,12 +2220,13 @@ void msm_dsi_host_reset_phy(struct mipi_dsi_host *host) > } > > void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host, > - struct msm_dsi_phy_clk_request *clk_req) > + struct msm_dsi_phy_clk_request *clk_req, > + bool is_dual_dsi) > { > struct msm_dsi_host *msm_host = to_msm_dsi_host(host); > int ret; > > - ret = dsi_calc_clk_rate(msm_host); > + ret = dsi_calc_clk_rate(msm_host, is_dual_dsi); > if (ret) { > pr_err("%s: unable to calc clk rate, %d\n", __func__, ret); > return; > @@ -2256,7 +2288,8 @@ static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable) > } > > int msm_dsi_host_power_on(struct mipi_dsi_host *host, > - struct msm_dsi_phy_shared_timings *phy_shared_timings) > + struct msm_dsi_phy_shared_timings *phy_shared_timings, > + bool is_dual_dsi) > { > struct msm_dsi_host *msm_host = to_msm_dsi_host(host); > int ret = 0; > @@ -2291,7 +2324,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, > goto fail_disable_clk; > } > > - dsi_timing_setup(msm_host); > + dsi_timing_setup(msm_host, is_dual_dsi); > dsi_sw_reset(msm_host); > dsi_ctrl_config(msm_host, true, phy_shared_timings); > > diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c > index 4cb1cb68878b..3bb506b44a4b 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c > +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c > @@ -134,8 +134,9 @@ static int enable_phy(struct msm_dsi *msm_dsi, int src_pll_id, > { > struct msm_dsi_phy_clk_request clk_req; > int ret; > + bool is_dual_dsi = IS_DUAL_DSI(); > > - msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req); > + msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req, is_dual_dsi); > > ret = msm_dsi_phy_enable(msm_dsi->phy, src_pll_id, &clk_req); > msm_dsi_phy_get_shared_timings(msm_dsi->phy, shared_timings); > @@ -458,7 +459,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) > if (is_dual_dsi && (DSI_1 == id)) > return; > > - ret = msm_dsi_host_power_on(host, &phy_shared_timings[id]); > + ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_dual_dsi); > if (ret) { > pr_err("%s: power on host %d failed, %d\n", __func__, id, ret); > goto host_on_fail; > @@ -466,7 +467,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) > > if (is_dual_dsi && msm_dsi1) { > ret = msm_dsi_host_power_on(msm_dsi1->host, > - &phy_shared_timings[DSI_1]); > + &phy_shared_timings[DSI_1], is_dual_dsi); > if (ret) { > pr_err("%s: power on host1 failed, %d\n", > __func__, ret); >
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 70d9a9a47acd..01c38f67d699 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -162,7 +162,8 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, int msm_dsi_host_enable(struct mipi_dsi_host *host); int msm_dsi_host_disable(struct mipi_dsi_host *host); int msm_dsi_host_power_on(struct mipi_dsi_host *host, - struct msm_dsi_phy_shared_timings *phy_shared_timings); + struct msm_dsi_phy_shared_timings *phy_shared_timings, + bool is_dual_dsi); int msm_dsi_host_power_off(struct mipi_dsi_host *host); int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host, struct drm_display_mode *mode); @@ -175,7 +176,8 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, struct msm_dsi_pll *src_pll); void msm_dsi_host_reset_phy(struct mipi_dsi_host *host); void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host, - struct msm_dsi_phy_clk_request *clk_req); + struct msm_dsi_phy_clk_request *clk_req, + bool is_dual_dsi); void msm_dsi_host_destroy(struct mipi_dsi_host *host); int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, struct drm_device *dev); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 2f1a2780658a..671039b7b75b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -118,6 +118,7 @@ struct msm_dsi_host { struct clk *byte_intf_clk; u32 byte_clk_rate; + u32 pixel_clk_rate; u32 esc_clk_rate; /* DSI v2 specific clocks */ @@ -511,7 +512,7 @@ static int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host) goto error; } - ret = clk_set_rate(msm_host->pixel_clk, msm_host->mode->clock * 1000); + ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate); if (ret) { pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret); goto error; @@ -592,7 +593,7 @@ static int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host) goto error; } - ret = clk_set_rate(msm_host->pixel_clk, msm_host->mode->clock * 1000); + ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate); if (ret) { pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret); goto error; @@ -662,7 +663,7 @@ static void dsi_link_clk_disable(struct msm_dsi_host *msm_host) } } -static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host) +static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host, bool is_dual_dsi) { struct drm_display_mode *mode = msm_host->mode; const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; @@ -676,14 +677,28 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host) } pclk_rate = mode->clock * 1000; + + /* + * For dual DSI mode, the current DRM mode has + * the complete width of the panel. Since, the complete + * panel is driven by two DSI controllers, the + * the clock rates have to be split between + * the two dsi controllers. Adjust the byte and + * pixel clock rates for each dsi host accordingly. + */ + if (is_dual_dsi) + pclk_rate /= 2; + if (lanes > 0) { msm_host->byte_clk_rate = (pclk_rate * bpp) / (8 * lanes); } else { pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__); msm_host->byte_clk_rate = (pclk_rate * bpp) / 8; } + msm_host->pixel_clk_rate = pclk_rate; - DBG("pclk=%d, bclk=%d", pclk_rate, msm_host->byte_clk_rate); + DBG("pclk=%d, bclk=%d", msm_host->pixel_clk_rate, + msm_host->byte_clk_rate); msm_host->esc_clk_rate = clk_get_rate(msm_host->esc_clk); @@ -885,7 +900,7 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, dsi_write(msm_host, REG_DSI_CTRL, data); } -static void dsi_timing_setup(struct msm_dsi_host *msm_host) +static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) { struct drm_display_mode *mode = msm_host->mode; u32 hs_start = 0, vs_start = 0; /* take sync start as 0 */ @@ -897,10 +912,26 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host) u32 ha_end = ha_start + mode->hdisplay; u32 va_start = v_total - mode->vsync_start; u32 va_end = va_start + mode->vdisplay; + u32 hdisplay = mode->hdisplay; u32 wc; DBG(""); + /* + * For dual DSI mode, the current DRM mode has + * the complete width of the panel. Since, the complete + * panel is driven by two DSI controllers, the horizontal + * timings have to be split between the two dsi controllers. + * Adjust the DSI host timing values accordingly. + */ + if (is_dual_dsi) { + h_total /= 2; + hs_end /= 2; + ha_start /= 2; + ha_end /= 2; + hdisplay /= 2; + } + if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) { dsi_write(msm_host, REG_DSI_ACTIVE_H, DSI_ACTIVE_H_START(ha_start) | @@ -921,7 +952,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host) DSI_ACTIVE_VSYNC_VPOS_END(vs_end)); } else { /* command mode */ /* image data and 1 byte write_memory_start cmd */ - wc = mode->hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1; + wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1; dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM_CTRL, DSI_CMD_MDP_STREAM_CTRL_WORD_COUNT(wc) | @@ -931,7 +962,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host) MIPI_DSI_DCS_LONG_WRITE)); dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM_TOTAL, - DSI_CMD_MDP_STREAM_TOTAL_H_TOTAL(mode->hdisplay) | + DSI_CMD_MDP_STREAM_TOTAL_H_TOTAL(hdisplay) | DSI_CMD_MDP_STREAM_TOTAL_V_TOTAL(mode->vdisplay)); } } @@ -2189,12 +2220,13 @@ void msm_dsi_host_reset_phy(struct mipi_dsi_host *host) } void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host, - struct msm_dsi_phy_clk_request *clk_req) + struct msm_dsi_phy_clk_request *clk_req, + bool is_dual_dsi) { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); int ret; - ret = dsi_calc_clk_rate(msm_host); + ret = dsi_calc_clk_rate(msm_host, is_dual_dsi); if (ret) { pr_err("%s: unable to calc clk rate, %d\n", __func__, ret); return; @@ -2256,7 +2288,8 @@ static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable) } int msm_dsi_host_power_on(struct mipi_dsi_host *host, - struct msm_dsi_phy_shared_timings *phy_shared_timings) + struct msm_dsi_phy_shared_timings *phy_shared_timings, + bool is_dual_dsi) { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); int ret = 0; @@ -2291,7 +2324,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, goto fail_disable_clk; } - dsi_timing_setup(msm_host); + dsi_timing_setup(msm_host, is_dual_dsi); dsi_sw_reset(msm_host); dsi_ctrl_config(msm_host, true, phy_shared_timings); diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 4cb1cb68878b..3bb506b44a4b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -134,8 +134,9 @@ static int enable_phy(struct msm_dsi *msm_dsi, int src_pll_id, { struct msm_dsi_phy_clk_request clk_req; int ret; + bool is_dual_dsi = IS_DUAL_DSI(); - msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req); + msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req, is_dual_dsi); ret = msm_dsi_phy_enable(msm_dsi->phy, src_pll_id, &clk_req); msm_dsi_phy_get_shared_timings(msm_dsi->phy, shared_timings); @@ -458,7 +459,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) if (is_dual_dsi && (DSI_1 == id)) return; - ret = msm_dsi_host_power_on(host, &phy_shared_timings[id]); + ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_dual_dsi); if (ret) { pr_err("%s: power on host %d failed, %d\n", __func__, id, ret); goto host_on_fail; @@ -466,7 +467,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) if (is_dual_dsi && msm_dsi1) { ret = msm_dsi_host_power_on(msm_dsi1->host, - &phy_shared_timings[DSI_1]); + &phy_shared_timings[DSI_1], is_dual_dsi); if (ret) { pr_err("%s: power on host1 failed, %d\n", __func__, ret);