All of lore.kernel.org
 help / color / mirror / Atom feed
* [DPU PATCH v3 0/2] Connector virtualization for Dual-DSI
@ 2018-04-18 19:45 Chandan Uddaraju
       [not found] ` <1524080715-23228-1-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  0 siblings, 1 reply; 8+ messages in thread
From: Chandan Uddaraju @ 2018-04-18 19:45 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, nganji-sgV2jX0FEOL9JmXXK+q4OQ,
	hoegsberg-hpIqsD4AKlfQT0dZR+AlfA,
	seanpaul-F7+t8E8rja9g9hUCZPvPmw, jsanka-sgV2jX0FEOL9JmXXK+q4OQ,
	Chandan Uddaraju

This patch series adds support to DSI connector
virtualization for Dual-DSI configuration.

These changes have been tested using dual-dsi truly panel on sdm845 platform.

Additional changes that will be needed to have end-to-end functionality:
     --> DSI6G-v2 changes: https://patchwork.kernel.org/patch/10294605/
     --> truly panel patches: https://patchwork.kernel.org/patch/10327749/
     --> DPU changes that will be uploaded soon.

Changes in V2:
  Addressed Sean's review comments:
    -Removed Change-Id from the commit text tags.
    -Remove extra parentheses

Changes in V3:
  Addressed Sean's review comments:
    --Instead of updating the DRM mode structure, divide
      the clocks and horizontal timings in DSI host just
      before configuring the values.

Chandan Uddaraju (2):
  drm/msm/dsi: adjust dsi timing for dual dsi mode
  drm/msm/dsi: Use one connector for dual DSI mode

 drivers/gpu/drm/msm/dsi/dsi.c         |   3 +
 drivers/gpu/drm/msm/dsi/dsi.h         |   7 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c    |  55 ++++++++++++----
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 117 +++++++++-------------------------
 4 files changed, 81 insertions(+), 101 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [DPU PATCH v3 1/2] drm/msm/dsi: adjust dsi timing for dual dsi mode
       [not found] ` <1524080715-23228-1-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2018-04-18 19:45   ` Chandan Uddaraju
  2018-04-19 16:01     ` Sean Paul
       [not found]     ` <1524080715-23228-2-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  2018-04-18 19:45   ` [DPU PATCH v3 2/2] drm/msm/dsi: Use one connector for dual DSI mode Chandan Uddaraju
  1 sibling, 2 replies; 8+ messages in thread
From: Chandan Uddaraju @ 2018-04-18 19:45 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, nganji-sgV2jX0FEOL9JmXXK+q4OQ,
	hoegsberg-hpIqsD4AKlfQT0dZR+AlfA,
	seanpaul-F7+t8E8rja9g9hUCZPvPmw, jsanka-sgV2jX0FEOL9JmXXK+q4OQ,
	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 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>
---
 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 70d9a9a..01c38f6 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 7a03a94..75d527e 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 */
@@ -510,7 +511,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;
@@ -591,7 +592,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;
@@ -661,7 +662,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;
@@ -675,14 +676,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);
 
@@ -884,7 +899,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 */
@@ -896,10 +911,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) |
@@ -920,7 +951,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) |
@@ -930,7 +961,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));
 	}
 }
@@ -2172,12 +2203,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;
@@ -2238,7 +2270,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;
@@ -2273,7 +2306,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 4cb1cb6..3bb506b 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);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [DPU PATCH v3 2/2] drm/msm/dsi: Use one connector for dual DSI mode
       [not found] ` <1524080715-23228-1-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  2018-04-18 19:45   ` [DPU PATCH v3 1/2] drm/msm/dsi: adjust dsi timing for dual dsi mode Chandan Uddaraju
@ 2018-04-18 19:45   ` Chandan Uddaraju
       [not found]     ` <1524080715-23228-3-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  1 sibling, 1 reply; 8+ messages in thread
From: Chandan Uddaraju @ 2018-04-18 19:45 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, nganji-sgV2jX0FEOL9JmXXK+q4OQ,
	hoegsberg-hpIqsD4AKlfQT0dZR+AlfA,
	seanpaul-F7+t8E8rja9g9hUCZPvPmw, jsanka-sgV2jX0FEOL9JmXXK+q4OQ,
	Chandan Uddaraju

Current DSI driver uses two connectors for dual DSI case even
though we only have one panel. Fix this by implementing one
connector/bridge for dual DSI use case. Use master DSI
controllers to register one connector/bridge.

Changes in V2:
    -Removed Change-Id from the commit text tags.
    -Remove extra parentheses

Changes in V3:
    -None

Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org>
---
 drivers/gpu/drm/msm/dsi/dsi.c         |   3 +
 drivers/gpu/drm/msm/dsi/dsi.h         |   1 +
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 110 ++++++++--------------------------
 3 files changed, 29 insertions(+), 85 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index b744bcc..ff8164c 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -208,6 +208,9 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
 		goto fail;
 	}
 
+	if (!msm_dsi_manager_validate_current_config(msm_dsi->id))
+		goto fail;
+
 	msm_dsi->encoder = encoder;
 
 	msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id);
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 01c38f6..c858e8e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -100,6 +100,7 @@ struct msm_dsi {
 void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags);
 int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
 void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
+bool msm_dsi_manager_validate_current_config(u8 id);
 
 /* msm dsi */
 static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi)
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 3bb506b..2a11f82 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -306,67 +306,6 @@ static void dsi_mgr_connector_destroy(struct drm_connector *connector)
 	kfree(dsi_connector);
 }
 
-static void dsi_dual_connector_fix_modes(struct drm_connector *connector)
-{
-	struct drm_display_mode *mode, *m;
-
-	/* Only support left-right mode */
-	list_for_each_entry_safe(mode, m, &connector->probed_modes, head) {
-		mode->clock >>= 1;
-		mode->hdisplay >>= 1;
-		mode->hsync_start >>= 1;
-		mode->hsync_end >>= 1;
-		mode->htotal >>= 1;
-		drm_mode_set_name(mode);
-	}
-}
-
-static int dsi_dual_connector_tile_init(
-			struct drm_connector *connector, int id)
-{
-	struct drm_display_mode *mode;
-	/* Fake topology id */
-	char topo_id[8] = {'M', 'S', 'M', 'D', 'U', 'D', 'S', 'I'};
-
-	if (connector->tile_group) {
-		DBG("Tile property has been initialized");
-		return 0;
-	}
-
-	/* Use the first mode only for now */
-	mode = list_first_entry(&connector->probed_modes,
-				struct drm_display_mode,
-				head);
-	if (!mode)
-		return -EINVAL;
-
-	connector->tile_group = drm_mode_get_tile_group(
-					connector->dev, topo_id);
-	if (!connector->tile_group)
-		connector->tile_group = drm_mode_create_tile_group(
-					connector->dev, topo_id);
-	if (!connector->tile_group) {
-		pr_err("%s: failed to create tile group\n", __func__);
-		return -ENOMEM;
-	}
-
-	connector->has_tile = true;
-	connector->tile_is_single_monitor = true;
-
-	/* mode has been fixed */
-	connector->tile_h_size = mode->hdisplay;
-	connector->tile_v_size = mode->vdisplay;
-
-	/* Only support left-right mode */
-	connector->num_h_tile = 2;
-	connector->num_v_tile = 1;
-
-	connector->tile_v_loc = 0;
-	connector->tile_h_loc = (id == DSI_RIGHT) ? 1 : 0;
-
-	return 0;
-}
-
 static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
 {
 	int id = dsi_mgr_connector_get_id(connector);
@@ -377,31 +316,15 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
 	if (!panel)
 		return 0;
 
-	/* Since we have 2 connectors, but only 1 drm_panel in dual DSI mode,
-	 * panel should not attach to any connector.
-	 * Only temporarily attach panel to the current connector here,
-	 * to let panel set mode to this connector.
+	/*
+	 * In dual DSI mode, we have one connector that can be
+	 * attached to the drm_panel.
 	 */
 	drm_panel_attach(panel, connector);
 	num = drm_panel_get_modes(panel);
-	drm_panel_detach(panel);
 	if (!num)
 		return 0;
 
-	if (IS_DUAL_DSI()) {
-		/* report half resolution to user */
-		dsi_dual_connector_fix_modes(connector);
-		ret = dsi_dual_connector_tile_init(connector, id);
-		if (ret)
-			return ret;
-		ret = drm_mode_connector_set_tile_property(connector);
-		if (ret) {
-			pr_err("%s: set tile property failed, %d\n",
-					__func__, ret);
-			return ret;
-		}
-	}
-
 	return num;
 }
 
@@ -455,8 +378,8 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
 	if (ret)
 		goto phy_en_fail;
 
-	/* Do nothing with the host if it is DSI 1 in case of dual DSI */
-	if (is_dual_dsi && (DSI_1 == id))
+	/* Do nothing with the host if it is slave-DSI in case of dual DSI */
+	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
 		return;
 
 	ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_dual_dsi);
@@ -557,11 +480,11 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
 		return;
 
 	/*
-	 * Do nothing with the host if it is DSI 1 in case of dual DSI.
+	 * Do nothing with the host if it is slave-DSI in case of dual DSI.
 	 * It is safe to call dsi_mgr_phy_disable() here because a single PHY
 	 * won't be diabled until both PHYs request disable.
 	 */
-	if (is_dual_dsi && (DSI_1 == id))
+	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
 		goto disable_phy;
 
 	if (panel) {
@@ -622,7 +545,7 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
 			mode->vsync_end, mode->vtotal,
 			mode->type, mode->flags);
 
-	if (is_dual_dsi && (DSI_1 == id))
+	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
 		return;
 
 	msm_dsi_host_set_display_mode(host, adjusted_mode);
@@ -690,6 +613,23 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
 	return connector;
 }
 
+bool msm_dsi_manager_validate_current_config(u8 id)
+{
+	bool is_dual_dsi = IS_DUAL_DSI();
+
+	/*
+	 * For dual DSI, we only have one drm panel. For this
+	 * use case, we register only one bridge/connector.
+	 * Skip bridge/connector initialisation if it is
+	 * slave-DSI for dual DSI configuration.
+	 */
+	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id)) {
+		DBG("Skip bridge registration for slave DSI->id: %d\n", id);
+		return false;
+	}
+	return true;
+}
+
 /* initialize bridge */
 struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
 {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [DPU PATCH v3 1/2] drm/msm/dsi: adjust dsi timing for dual dsi mode
  2018-04-18 19:45   ` [DPU PATCH v3 1/2] drm/msm/dsi: adjust dsi timing for dual dsi mode Chandan Uddaraju
@ 2018-04-19 16:01     ` Sean Paul
       [not found]     ` <1524080715-23228-2-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  1 sibling, 0 replies; 8+ messages in thread
From: Sean Paul @ 2018-04-19 16:01 UTC (permalink / raw)
  To: Chandan Uddaraju; +Cc: linux-arm-msm, dri-devel, hoegsberg, freedreno

On Wed, Apr 18, 2018 at 12:45:14PM -0700, Chandan Uddaraju wrote:
> 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 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>

Reviewed-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 70d9a9a..01c38f6 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 7a03a94..75d527e 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 */
> @@ -510,7 +511,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;
> @@ -591,7 +592,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;
> @@ -661,7 +662,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;
> @@ -675,14 +676,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);
>  
> @@ -884,7 +899,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 */
> @@ -896,10 +911,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) |
> @@ -920,7 +951,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) |
> @@ -930,7 +961,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));
>  	}
>  }
> @@ -2172,12 +2203,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;
> @@ -2238,7 +2270,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;
> @@ -2273,7 +2306,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 4cb1cb6..3bb506b 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);
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
> 

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [DPU PATCH v3 2/2] drm/msm/dsi: Use one connector for dual DSI mode
       [not found]     ` <1524080715-23228-3-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2018-04-19 16:03       ` Sean Paul
  2018-04-19 16:06       ` Sean Paul
  2018-04-19 17:07       ` Archit Taneja
  2 siblings, 0 replies; 8+ messages in thread
From: Sean Paul @ 2018-04-19 16:03 UTC (permalink / raw)
  To: Chandan Uddaraju
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, nganji-sgV2jX0FEOL9JmXXK+q4OQ,
	seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	hoegsberg-hpIqsD4AKlfQT0dZR+AlfA, jsanka-sgV2jX0FEOL9JmXXK+q4OQ,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On Wed, Apr 18, 2018 at 12:45:15PM -0700, Chandan Uddaraju wrote:
> Current DSI driver uses two connectors for dual DSI case even
> though we only have one panel. Fix this by implementing one
> connector/bridge for dual DSI use case. Use master DSI
> controllers to register one connector/bridge.
> 
> Changes in V2:
>     -Removed Change-Id from the commit text tags.
>     -Remove extra parentheses
> 
> Changes in V3:
>     -None
> 
> Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> ---
>  drivers/gpu/drm/msm/dsi/dsi.c         |   3 +
>  drivers/gpu/drm/msm/dsi/dsi.h         |   1 +
>  drivers/gpu/drm/msm/dsi/dsi_manager.c | 110 ++++++++--------------------------
>  3 files changed, 29 insertions(+), 85 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
> index b744bcc..ff8164c 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi.c
> @@ -208,6 +208,9 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
>  		goto fail;
>  	}
>  
> +	if (!msm_dsi_manager_validate_current_config(msm_dsi->id))
> +		goto fail;
> +
>  	msm_dsi->encoder = encoder;
>  
>  	msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id);
> diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
> index 01c38f6..c858e8e 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi.h
> +++ b/drivers/gpu/drm/msm/dsi/dsi.h
> @@ -100,6 +100,7 @@ struct msm_dsi {
>  void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags);
>  int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
>  void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
> +bool msm_dsi_manager_validate_current_config(u8 id);
>  
>  /* msm dsi */
>  static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi)
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index 3bb506b..2a11f82 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -306,67 +306,6 @@ static void dsi_mgr_connector_destroy(struct drm_connector *connector)
>  	kfree(dsi_connector);
>  }
>  
> -static void dsi_dual_connector_fix_modes(struct drm_connector *connector)
> -{
> -	struct drm_display_mode *mode, *m;
> -
> -	/* Only support left-right mode */
> -	list_for_each_entry_safe(mode, m, &connector->probed_modes, head) {
> -		mode->clock >>= 1;
> -		mode->hdisplay >>= 1;
> -		mode->hsync_start >>= 1;
> -		mode->hsync_end >>= 1;
> -		mode->htotal >>= 1;
> -		drm_mode_set_name(mode);
> -	}
> -}
> -
> -static int dsi_dual_connector_tile_init(
> -			struct drm_connector *connector, int id)
> -{
> -	struct drm_display_mode *mode;
> -	/* Fake topology id */
> -	char topo_id[8] = {'M', 'S', 'M', 'D', 'U', 'D', 'S', 'I'};
> -
> -	if (connector->tile_group) {
> -		DBG("Tile property has been initialized");
> -		return 0;
> -	}
> -
> -	/* Use the first mode only for now */
> -	mode = list_first_entry(&connector->probed_modes,
> -				struct drm_display_mode,
> -				head);
> -	if (!mode)
> -		return -EINVAL;
> -
> -	connector->tile_group = drm_mode_get_tile_group(
> -					connector->dev, topo_id);
> -	if (!connector->tile_group)
> -		connector->tile_group = drm_mode_create_tile_group(
> -					connector->dev, topo_id);
> -	if (!connector->tile_group) {
> -		pr_err("%s: failed to create tile group\n", __func__);
> -		return -ENOMEM;
> -	}
> -
> -	connector->has_tile = true;
> -	connector->tile_is_single_monitor = true;
> -
> -	/* mode has been fixed */
> -	connector->tile_h_size = mode->hdisplay;
> -	connector->tile_v_size = mode->vdisplay;
> -
> -	/* Only support left-right mode */
> -	connector->num_h_tile = 2;
> -	connector->num_v_tile = 1;
> -
> -	connector->tile_v_loc = 0;
> -	connector->tile_h_loc = (id == DSI_RIGHT) ? 1 : 0;
> -
> -	return 0;
> -}
> -
>  static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
>  {
>  	int id = dsi_mgr_connector_get_id(connector);
> @@ -377,31 +316,15 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
>  	if (!panel)
>  		return 0;
>  
> -	/* Since we have 2 connectors, but only 1 drm_panel in dual DSI mode,
> -	 * panel should not attach to any connector.
> -	 * Only temporarily attach panel to the current connector here,
> -	 * to let panel set mode to this connector.
> +	/*
> +	 * In dual DSI mode, we have one connector that can be
> +	 * attached to the drm_panel.
>  	 */
>  	drm_panel_attach(panel, connector);
>  	num = drm_panel_get_modes(panel);
> -	drm_panel_detach(panel);
>  	if (!num)
>  		return 0;
>  
> -	if (IS_DUAL_DSI()) {
> -		/* report half resolution to user */
> -		dsi_dual_connector_fix_modes(connector);
> -		ret = dsi_dual_connector_tile_init(connector, id);
> -		if (ret)
> -			return ret;
> -		ret = drm_mode_connector_set_tile_property(connector);
> -		if (ret) {
> -			pr_err("%s: set tile property failed, %d\n",
> -					__func__, ret);
> -			return ret;
> -		}
> -	}
> -
>  	return num;
>  }
>  
> @@ -455,8 +378,8 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
>  	if (ret)
>  		goto phy_en_fail;
>  
> -	/* Do nothing with the host if it is DSI 1 in case of dual DSI */
> -	if (is_dual_dsi && (DSI_1 == id))
> +	/* Do nothing with the host if it is slave-DSI in case of dual DSI */
> +	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
>  		return;
>  
>  	ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_dual_dsi);
> @@ -557,11 +480,11 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
>  		return;
>  
>  	/*
> -	 * Do nothing with the host if it is DSI 1 in case of dual DSI.
> +	 * Do nothing with the host if it is slave-DSI in case of dual DSI.
>  	 * It is safe to call dsi_mgr_phy_disable() here because a single PHY
>  	 * won't be diabled until both PHYs request disable.
>  	 */
> -	if (is_dual_dsi && (DSI_1 == id))
> +	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
>  		goto disable_phy;
>  
>  	if (panel) {
> @@ -622,7 +545,7 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
>  			mode->vsync_end, mode->vtotal,
>  			mode->type, mode->flags);
>  
> -	if (is_dual_dsi && (DSI_1 == id))
> +	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
>  		return;
>  
>  	msm_dsi_host_set_display_mode(host, adjusted_mode);
> @@ -690,6 +613,23 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
>  	return connector;
>  }
>  
> +bool msm_dsi_manager_validate_current_config(u8 id)
> +{
> +	bool is_dual_dsi = IS_DUAL_DSI();
> +
> +	/*
> +	 * For dual DSI, we only have one drm panel. For this
> +	 * use case, we register only one bridge/connector.
> +	 * Skip bridge/connector initialisation if it is
> +	 * slave-DSI for dual DSI configuration.
> +	 */
> +	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id)) {
> +		DBG("Skip bridge registration for slave DSI->id: %d\n", id);
> +		return false;
> +	}
> +	return true;
> +}
> +
>  /* initialize bridge */
>  struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  {
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
> 

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [DPU PATCH v3 2/2] drm/msm/dsi: Use one connector for dual DSI mode
       [not found]     ` <1524080715-23228-3-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  2018-04-19 16:03       ` Sean Paul
@ 2018-04-19 16:06       ` Sean Paul
  2018-04-19 17:07       ` Archit Taneja
  2 siblings, 0 replies; 8+ messages in thread
From: Sean Paul @ 2018-04-19 16:06 UTC (permalink / raw)
  To: Chandan Uddaraju
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, nganji-sgV2jX0FEOL9JmXXK+q4OQ,
	seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	hoegsberg-hpIqsD4AKlfQT0dZR+AlfA, jsanka-sgV2jX0FEOL9JmXXK+q4OQ,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On Wed, Apr 18, 2018 at 12:45:15PM -0700, Chandan Uddaraju wrote:
> Current DSI driver uses two connectors for dual DSI case even
> though we only have one panel. Fix this by implementing one
> connector/bridge for dual DSI use case. Use master DSI
> controllers to register one connector/bridge.
> 
> Changes in V2:
>     -Removed Change-Id from the commit text tags.
>     -Remove extra parentheses
> 
> Changes in V3:
>     -None
> 
> Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> ---
>  drivers/gpu/drm/msm/dsi/dsi.c         |   3 +
>  drivers/gpu/drm/msm/dsi/dsi.h         |   1 +
>  drivers/gpu/drm/msm/dsi/dsi_manager.c | 110 ++++++++--------------------------
>  3 files changed, 29 insertions(+), 85 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
> index b744bcc..ff8164c 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi.c
> @@ -208,6 +208,9 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
>  		goto fail;
>  	}
>  
> +	if (!msm_dsi_manager_validate_current_config(msm_dsi->id))
> +		goto fail;
> +
>  	msm_dsi->encoder = encoder;
>  
>  	msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id);
> diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
> index 01c38f6..c858e8e 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi.h
> +++ b/drivers/gpu/drm/msm/dsi/dsi.h
> @@ -100,6 +100,7 @@ struct msm_dsi {
>  void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags);
>  int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
>  void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
> +bool msm_dsi_manager_validate_current_config(u8 id);
>  
>  /* msm dsi */
>  static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi)
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index 3bb506b..2a11f82 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -306,67 +306,6 @@ static void dsi_mgr_connector_destroy(struct drm_connector *connector)
>  	kfree(dsi_connector);
>  }
>  
> -static void dsi_dual_connector_fix_modes(struct drm_connector *connector)
> -{
> -	struct drm_display_mode *mode, *m;
> -
> -	/* Only support left-right mode */
> -	list_for_each_entry_safe(mode, m, &connector->probed_modes, head) {
> -		mode->clock >>= 1;
> -		mode->hdisplay >>= 1;
> -		mode->hsync_start >>= 1;
> -		mode->hsync_end >>= 1;
> -		mode->htotal >>= 1;
> -		drm_mode_set_name(mode);
> -	}
> -}
> -
> -static int dsi_dual_connector_tile_init(
> -			struct drm_connector *connector, int id)
> -{
> -	struct drm_display_mode *mode;
> -	/* Fake topology id */
> -	char topo_id[8] = {'M', 'S', 'M', 'D', 'U', 'D', 'S', 'I'};
> -
> -	if (connector->tile_group) {
> -		DBG("Tile property has been initialized");
> -		return 0;
> -	}
> -
> -	/* Use the first mode only for now */
> -	mode = list_first_entry(&connector->probed_modes,
> -				struct drm_display_mode,
> -				head);
> -	if (!mode)
> -		return -EINVAL;
> -
> -	connector->tile_group = drm_mode_get_tile_group(
> -					connector->dev, topo_id);
> -	if (!connector->tile_group)
> -		connector->tile_group = drm_mode_create_tile_group(
> -					connector->dev, topo_id);
> -	if (!connector->tile_group) {
> -		pr_err("%s: failed to create tile group\n", __func__);
> -		return -ENOMEM;
> -	}
> -
> -	connector->has_tile = true;
> -	connector->tile_is_single_monitor = true;
> -
> -	/* mode has been fixed */
> -	connector->tile_h_size = mode->hdisplay;
> -	connector->tile_v_size = mode->vdisplay;
> -
> -	/* Only support left-right mode */
> -	connector->num_h_tile = 2;
> -	connector->num_v_tile = 1;
> -
> -	connector->tile_v_loc = 0;
> -	connector->tile_h_loc = (id == DSI_RIGHT) ? 1 : 0;
> -
> -	return 0;
> -}
> -
>  static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
>  {
>  	int id = dsi_mgr_connector_get_id(connector);
> @@ -377,31 +316,15 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
>  	if (!panel)
>  		return 0;
>  
> -	/* Since we have 2 connectors, but only 1 drm_panel in dual DSI mode,
> -	 * panel should not attach to any connector.
> -	 * Only temporarily attach panel to the current connector here,
> -	 * to let panel set mode to this connector.
> +	/*
> +	 * In dual DSI mode, we have one connector that can be
> +	 * attached to the drm_panel.
>  	 */
>  	drm_panel_attach(panel, connector);
>  	num = drm_panel_get_modes(panel);
> -	drm_panel_detach(panel);
>  	if (!num)
>  		return 0;
>  
> -	if (IS_DUAL_DSI()) {
> -		/* report half resolution to user */
> -		dsi_dual_connector_fix_modes(connector);
> -		ret = dsi_dual_connector_tile_init(connector, id);
> -		if (ret)
> -			return ret;
> -		ret = drm_mode_connector_set_tile_property(connector);
> -		if (ret) {
> -			pr_err("%s: set tile property failed, %d\n",
> -					__func__, ret);
> -			return ret;
> -		}
> -	}
> -
>  	return num;
>  }
>  
> @@ -455,8 +378,8 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
>  	if (ret)
>  		goto phy_en_fail;
>  
> -	/* Do nothing with the host if it is DSI 1 in case of dual DSI */
> -	if (is_dual_dsi && (DSI_1 == id))
> +	/* Do nothing with the host if it is slave-DSI in case of dual DSI */
> +	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
>  		return;
>  
>  	ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_dual_dsi);
> @@ -557,11 +480,11 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
>  		return;
>  
>  	/*
> -	 * Do nothing with the host if it is DSI 1 in case of dual DSI.
> +	 * Do nothing with the host if it is slave-DSI in case of dual DSI.
>  	 * It is safe to call dsi_mgr_phy_disable() here because a single PHY
>  	 * won't be diabled until both PHYs request disable.
>  	 */
> -	if (is_dual_dsi && (DSI_1 == id))
> +	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
>  		goto disable_phy;
>  
>  	if (panel) {
> @@ -622,7 +545,7 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
>  			mode->vsync_end, mode->vtotal,
>  			mode->type, mode->flags);
>  
> -	if (is_dual_dsi && (DSI_1 == id))
> +	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
>  		return;
>  
>  	msm_dsi_host_set_display_mode(host, adjusted_mode);
> @@ -690,6 +613,23 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
>  	return connector;
>  }
>  
> +bool msm_dsi_manager_validate_current_config(u8 id)
> +{
> +	bool is_dual_dsi = IS_DUAL_DSI();
> +
> +	/*
> +	 * For dual DSI, we only have one drm panel. For this
> +	 * use case, we register only one bridge/connector.
> +	 * Skip bridge/connector initialisation if it is
> +	 * slave-DSI for dual DSI configuration.
> +	 */
> +	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id)) {
> +		DBG("Skip bridge registration for slave DSI->id: %d\n", id);
> +		return false;
> +	}
> +	return true;
> +}
> +
>  /* initialize bridge */
>  struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  {
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
> 

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [DPU PATCH v3 1/2] drm/msm/dsi: adjust dsi timing for dual dsi mode
       [not found]     ` <1524080715-23228-2-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2018-04-19 17:05       ` Archit Taneja
  0 siblings, 0 replies; 8+ messages in thread
From: Archit Taneja @ 2018-04-19 17:05 UTC (permalink / raw)
  To: Chandan Uddaraju, freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, nganji-sgV2jX0FEOL9JmXXK+q4OQ,
	seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	hoegsberg-hpIqsD4AKlfQT0dZR+AlfA, jsanka-sgV2jX0FEOL9JmXXK+q4OQ



On Thursday 19 April 2018 01:15 AM, Chandan Uddaraju wrote:
> 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>
> ---
>   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 70d9a9a..01c38f6 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 7a03a94..75d527e 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 */
> @@ -510,7 +511,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;
> @@ -591,7 +592,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;
> @@ -661,7 +662,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;
> @@ -675,14 +676,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);
>   
> @@ -884,7 +899,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 */
> @@ -896,10 +911,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) |
> @@ -920,7 +951,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) |
> @@ -930,7 +961,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));
>   	}
>   }
> @@ -2172,12 +2203,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;
> @@ -2238,7 +2270,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;
> @@ -2273,7 +2306,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 4cb1cb6..3bb506b 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);
> 
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [DPU PATCH v3 2/2] drm/msm/dsi: Use one connector for dual DSI mode
       [not found]     ` <1524080715-23228-3-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  2018-04-19 16:03       ` Sean Paul
  2018-04-19 16:06       ` Sean Paul
@ 2018-04-19 17:07       ` Archit Taneja
  2 siblings, 0 replies; 8+ messages in thread
From: Archit Taneja @ 2018-04-19 17:07 UTC (permalink / raw)
  To: Chandan Uddaraju, freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, nganji-sgV2jX0FEOL9JmXXK+q4OQ,
	hoegsberg-hpIqsD4AKlfQT0dZR+AlfA,
	seanpaul-F7+t8E8rja9g9hUCZPvPmw, jsanka-sgV2jX0FEOL9JmXXK+q4OQ



On Thursday 19 April 2018 01:15 AM, Chandan Uddaraju wrote:
> Current DSI driver uses two connectors for dual DSI case even
> though we only have one panel. Fix this by implementing one
> connector/bridge for dual DSI use case. Use master DSI
> controllers to register one connector/bridge.
> 
> Changes in V2:
>      -Removed Change-Id from the commit text tags.
>      -Remove extra parentheses
> 
> Changes in V3:
>      -None

Reviewed-by: Archit Taneja <architt@codeaurora.org>

> 
> Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org>
> ---
>   drivers/gpu/drm/msm/dsi/dsi.c         |   3 +
>   drivers/gpu/drm/msm/dsi/dsi.h         |   1 +
>   drivers/gpu/drm/msm/dsi/dsi_manager.c | 110 ++++++++--------------------------
>   3 files changed, 29 insertions(+), 85 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
> index b744bcc..ff8164c 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi.c
> @@ -208,6 +208,9 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
>   		goto fail;
>   	}
>   
> +	if (!msm_dsi_manager_validate_current_config(msm_dsi->id))
> +		goto fail;
> +
>   	msm_dsi->encoder = encoder;
>   
>   	msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id);
> diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
> index 01c38f6..c858e8e 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi.h
> +++ b/drivers/gpu/drm/msm/dsi/dsi.h
> @@ -100,6 +100,7 @@ struct msm_dsi {
>   void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags);
>   int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
>   void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
> +bool msm_dsi_manager_validate_current_config(u8 id);
>   
>   /* msm dsi */
>   static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi)
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index 3bb506b..2a11f82 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -306,67 +306,6 @@ static void dsi_mgr_connector_destroy(struct drm_connector *connector)
>   	kfree(dsi_connector);
>   }
>   
> -static void dsi_dual_connector_fix_modes(struct drm_connector *connector)
> -{
> -	struct drm_display_mode *mode, *m;
> -
> -	/* Only support left-right mode */
> -	list_for_each_entry_safe(mode, m, &connector->probed_modes, head) {
> -		mode->clock >>= 1;
> -		mode->hdisplay >>= 1;
> -		mode->hsync_start >>= 1;
> -		mode->hsync_end >>= 1;
> -		mode->htotal >>= 1;
> -		drm_mode_set_name(mode);
> -	}
> -}
> -
> -static int dsi_dual_connector_tile_init(
> -			struct drm_connector *connector, int id)
> -{
> -	struct drm_display_mode *mode;
> -	/* Fake topology id */
> -	char topo_id[8] = {'M', 'S', 'M', 'D', 'U', 'D', 'S', 'I'};
> -
> -	if (connector->tile_group) {
> -		DBG("Tile property has been initialized");
> -		return 0;
> -	}
> -
> -	/* Use the first mode only for now */
> -	mode = list_first_entry(&connector->probed_modes,
> -				struct drm_display_mode,
> -				head);
> -	if (!mode)
> -		return -EINVAL;
> -
> -	connector->tile_group = drm_mode_get_tile_group(
> -					connector->dev, topo_id);
> -	if (!connector->tile_group)
> -		connector->tile_group = drm_mode_create_tile_group(
> -					connector->dev, topo_id);
> -	if (!connector->tile_group) {
> -		pr_err("%s: failed to create tile group\n", __func__);
> -		return -ENOMEM;
> -	}
> -
> -	connector->has_tile = true;
> -	connector->tile_is_single_monitor = true;
> -
> -	/* mode has been fixed */
> -	connector->tile_h_size = mode->hdisplay;
> -	connector->tile_v_size = mode->vdisplay;
> -
> -	/* Only support left-right mode */
> -	connector->num_h_tile = 2;
> -	connector->num_v_tile = 1;
> -
> -	connector->tile_v_loc = 0;
> -	connector->tile_h_loc = (id == DSI_RIGHT) ? 1 : 0;
> -
> -	return 0;
> -}
> -
>   static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
>   {
>   	int id = dsi_mgr_connector_get_id(connector);
> @@ -377,31 +316,15 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
>   	if (!panel)
>   		return 0;
>   
> -	/* Since we have 2 connectors, but only 1 drm_panel in dual DSI mode,
> -	 * panel should not attach to any connector.
> -	 * Only temporarily attach panel to the current connector here,
> -	 * to let panel set mode to this connector.
> +	/*
> +	 * In dual DSI mode, we have one connector that can be
> +	 * attached to the drm_panel.
>   	 */
>   	drm_panel_attach(panel, connector);
>   	num = drm_panel_get_modes(panel);
> -	drm_panel_detach(panel);
>   	if (!num)
>   		return 0;
>   
> -	if (IS_DUAL_DSI()) {
> -		/* report half resolution to user */
> -		dsi_dual_connector_fix_modes(connector);
> -		ret = dsi_dual_connector_tile_init(connector, id);
> -		if (ret)
> -			return ret;
> -		ret = drm_mode_connector_set_tile_property(connector);
> -		if (ret) {
> -			pr_err("%s: set tile property failed, %d\n",
> -					__func__, ret);
> -			return ret;
> -		}
> -	}
> -
>   	return num;
>   }
>   
> @@ -455,8 +378,8 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
>   	if (ret)
>   		goto phy_en_fail;
>   
> -	/* Do nothing with the host if it is DSI 1 in case of dual DSI */
> -	if (is_dual_dsi && (DSI_1 == id))
> +	/* Do nothing with the host if it is slave-DSI in case of dual DSI */
> +	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
>   		return;
>   
>   	ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_dual_dsi);
> @@ -557,11 +480,11 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
>   		return;
>   
>   	/*
> -	 * Do nothing with the host if it is DSI 1 in case of dual DSI.
> +	 * Do nothing with the host if it is slave-DSI in case of dual DSI.
>   	 * It is safe to call dsi_mgr_phy_disable() here because a single PHY
>   	 * won't be diabled until both PHYs request disable.
>   	 */
> -	if (is_dual_dsi && (DSI_1 == id))
> +	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
>   		goto disable_phy;
>   
>   	if (panel) {
> @@ -622,7 +545,7 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
>   			mode->vsync_end, mode->vtotal,
>   			mode->type, mode->flags);
>   
> -	if (is_dual_dsi && (DSI_1 == id))
> +	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
>   		return;
>   
>   	msm_dsi_host_set_display_mode(host, adjusted_mode);
> @@ -690,6 +613,23 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
>   	return connector;
>   }
>   
> +bool msm_dsi_manager_validate_current_config(u8 id)
> +{
> +	bool is_dual_dsi = IS_DUAL_DSI();
> +
> +	/*
> +	 * For dual DSI, we only have one drm panel. For this
> +	 * use case, we register only one bridge/connector.
> +	 * Skip bridge/connector initialisation if it is
> +	 * slave-DSI for dual DSI configuration.
> +	 */
> +	if (is_dual_dsi && !IS_MASTER_DSI_LINK(id)) {
> +		DBG("Skip bridge registration for slave DSI->id: %d\n", id);
> +		return false;
> +	}
> +	return true;
> +}
> +
>   /* initialize bridge */
>   struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>   {
> 
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2018-04-19 17:07 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-18 19:45 [DPU PATCH v3 0/2] Connector virtualization for Dual-DSI Chandan Uddaraju
     [not found] ` <1524080715-23228-1-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-04-18 19:45   ` [DPU PATCH v3 1/2] drm/msm/dsi: adjust dsi timing for dual dsi mode Chandan Uddaraju
2018-04-19 16:01     ` Sean Paul
     [not found]     ` <1524080715-23228-2-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-04-19 17:05       ` Archit Taneja
2018-04-18 19:45   ` [DPU PATCH v3 2/2] drm/msm/dsi: Use one connector for dual DSI mode Chandan Uddaraju
     [not found]     ` <1524080715-23228-3-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-04-19 16:03       ` Sean Paul
2018-04-19 16:06       ` Sean Paul
2018-04-19 17:07       ` Archit Taneja

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.