From patchwork Fri Jul 20 20:42:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Paul X-Patchwork-Id: 10538297 X-Patchwork-Delegate: agross@codeaurora.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B2B9E604D3 for ; Fri, 20 Jul 2018 20:43:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9DF8E28E92 for ; Fri, 20 Jul 2018 20:43:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9150B28ECC; Fri, 20 Jul 2018 20:43:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B385328EA5 for ; Fri, 20 Jul 2018 20:43:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728706AbeGTVdx (ORCPT ); Fri, 20 Jul 2018 17:33:53 -0400 Received: from mail-yw0-f195.google.com ([209.85.161.195]:35838 "EHLO mail-yw0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727736AbeGTVdw (ORCPT ); Fri, 20 Jul 2018 17:33:52 -0400 Received: by mail-yw0-f195.google.com with SMTP id t18-v6so4816954ywg.2 for ; Fri, 20 Jul 2018 13:43:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=0qOhF7GMrvFkVtbp8et0ly5/qyIp84jEc8rznsjk4T8=; b=H3I04TsWvINFCyAQptK7bSdOd4gBc/qN8FfqeBU3dTdRi7a8P5sYT16qG0slfGR8N1 0KlyVQXUJgBOcAQ33LGoPTu2YG/NPkH9bA2n2yOpdTgOHWaKsqWKezJx3IQn7tStxe1o ZAzPXTQGFCfoezZ6XhnmjoZWZue60MvQWcEIE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=0qOhF7GMrvFkVtbp8et0ly5/qyIp84jEc8rznsjk4T8=; b=bghFQlGBAjB5+A5G/gHse0RiK84KgcWfV0jOqQ1z27u5OpUxMRbuWr8rOIClMSHvDx j6+VOulfpRmNW4oQAfAtAvJdRKa9JVQclurDSSe24MxTm6bsjeemwVoBbklX4eJReyzv JuyhUhVhCEeYee5S4ZsSbVR6KZc2X5fMAUMKYJ+9mxRFWUNlKiMmQRQs8nwY6VheywO7 k7BYHNNPRyf0aOscjQ5J0MzBFdDqtGQXGz3WpSGzoSiUpWNKnAWWWak0viqUEdJt+klI ALn4CN34SiajKPJ2r/LAGmpfV8itk6MxHivXuYRq6vQXQPCoZHRLNCVgdBpqSQ0Vmvif uC9w== X-Gm-Message-State: AOUpUlEXp/3rLS7JOTzMsUmyBug0UJblsrPceb0kzvWLVeKQkCjwkQJC 2rzvMUSNfkq74LF2Wau5HEi88A== X-Google-Smtp-Source: AAOMgpf8eTJy+njao2UITOJyD2bBi3sobve+xQOaprxJdZnUh382ORrePhg67tYYUqNM8vPp4WPLaQ== X-Received: by 2002:a81:f208:: with SMTP id i8-v6mr1794420ywm.72.1532119435304; Fri, 20 Jul 2018 13:43:55 -0700 (PDT) Received: from rosewood.cam.corp.google.com ([2620:0:1013:11:ad55:b1db:adfe:3b9f]) by smtp.gmail.com with ESMTPSA id a2-v6sm2453831ywm.7.2018.07.20.13.43.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 20 Jul 2018 13:43:54 -0700 (PDT) From: Sean Paul To: abhinavk@codeaurora.org, architt@codeaurora.org, chandanu@codeaurora.org, jsanka@codeaurora.org, jcrouse@codeaurora.org, ryadav@codeaurora.org, seanpaul@chromium.org, skolluku@codeaurora.org, dri-devel@lists.freedesktop.org, robdclark@gmail.com, airlied@linux.ie, freedreno@lists.freedesktop.org, linux-arm-msm@vger.kernel.org, nganji@codeaurora.org, hoegsberg@chromium.org, dovizu@chromium.org, robh+dt@kernel.org Cc: Sibi Sankar , Stefan Agner , Daniel Mack , Neil Armstrong , Lloyd Atkinson , Daniel Vetter Subject: [PATCH v3 04/19] drm/msm/dsi: adjust dsi timing for dual dsi mode Date: Fri, 20 Jul 2018 16:42:55 -0400 Message-Id: <20180720204315.19054-5-seanpaul@chromium.org> X-Mailer: git-send-email 2.18.0.233.g985f88cf7e-goog In-Reply-To: <20180720204315.19054-1-seanpaul@chromium.org> References: <20180720204315.19054-1-seanpaul@chromium.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Chandan Uddaraju 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. Changes in v3: - Added Archit's R-b - Rebase on dsi cleanup set in msm-next Cc: Sibi Sankar Reviewed-by: Archit Taneja Signed-off-by: Chandan Uddaraju Signed-off-by: Sean Paul --- drivers/gpu/drm/msm/dsi/dsi.h | 10 +++-- drivers/gpu/drm/msm/dsi/dsi_cfg.h | 2 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 65 ++++++++++++++++++++++----- drivers/gpu/drm/msm/dsi/dsi_manager.c | 7 +-- 4 files changed, 64 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index dfa049d876bd..d3f613c76ffa 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -163,7 +163,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); @@ -176,7 +177,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); @@ -196,8 +198,8 @@ int dsi_dma_base_get_6g(struct msm_dsi_host *msm_host, uint64_t *iova); int dsi_dma_base_get_v2(struct msm_dsi_host *msm_host, uint64_t *iova); int dsi_clk_init_v2(struct msm_dsi_host *msm_host); int dsi_clk_init_6g_v2(struct msm_dsi_host *msm_host); -int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host); -int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host); +int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_dual_dsi); +int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_dual_dsi); /* dsi phy */ struct msm_dsi_phy; diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h b/drivers/gpu/drm/msm/dsi/dsi_cfg.h index a795a062b779..16c507911110 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h @@ -48,7 +48,7 @@ struct msm_dsi_host_cfg_ops { void* (*tx_buf_get)(struct msm_dsi_host *msm_host); void (*tx_buf_put)(struct msm_dsi_host *msm_host); int (*dma_base_get)(struct msm_dsi_host *msm_host, uint64_t *iova); - int (*calc_clk_rate)(struct msm_dsi_host *msm_host); + int (*calc_clk_rate)(struct msm_dsi_host *msm_host, bool is_dual_dsi); }; struct msm_dsi_cfg_handler { diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index bb00e0f150cb..f6c6eddbcec7 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 */ @@ -523,7 +524,7 @@ 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; @@ -604,7 +605,7 @@ 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; @@ -663,7 +664,7 @@ void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host) clk_disable_unprepare(msm_host->byte_clk); } -int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host) +int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_dual_dsi) { struct drm_display_mode *mode = msm_host->mode; u8 lanes = msm_host->lanes; @@ -671,6 +672,16 @@ int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host) u32 pclk_rate; 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, + * theclock 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 { @@ -685,7 +696,7 @@ int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host) return 0; } -int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host) +int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_dual_dsi) { struct drm_display_mode *mode = msm_host->mode; u8 lanes = msm_host->lanes; @@ -695,14 +706,26 @@ int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host) unsigned long byte_mhz; 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, + * theclock 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->src_clk_rate = (pclk_rate * bpp) / 8; @@ -897,7 +920,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 */ @@ -909,10 +932,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) | @@ -933,7 +972,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) | @@ -943,7 +982,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)); } } @@ -2217,13 +2256,14 @@ 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); const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; int ret; - ret = cfg_hnd->ops->calc_clk_rate(msm_host); + ret = cfg_hnd->ops->calc_clk_rate(msm_host, is_dual_dsi); if (ret) { pr_err("%s: unable to calc clk rate, %d\n", __func__, ret); return; @@ -2285,7 +2325,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); const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; @@ -2321,7 +2362,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);