[Freedreno] [PATCH 05/21] drm/msm/dsi: adjust dsi timing for dual dsi mode
Archit Taneja
architt at codeaurora.org
Mon Jul 16 14:17:40 UTC 2018
On Monday 09 July 2018 11:01 PM, Sean Paul wrote:
> From: Chandan Uddaraju <chandanu at 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 at 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 at codeaurora.org>
> Signed-off-by: Sean Paul <seanpaul at 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);
>
More information about the Freedreno
mailing list