diff mbox

[DPU,2/2] drm/msm/dsi: Use one connector for dual DSI mode

Message ID 1523409368-29750-3-git-send-email-chandanu@codeaurora.org (mailing list archive)
State Not Applicable, archived
Delegated to: Andy Gross
Headers show

Commit Message

Chandan Uddaraju April 11, 2018, 1:16 a.m. UTC
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.

Change-Id: I067b39f3b32eb3aa92d4155d4ca703ca7690645b
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(-)

Comments

Sean Paul April 13, 2018, 8:22 p.m. UTC | #1
On Tue, Apr 10, 2018 at 06:16:08PM -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.
> 
> Change-Id: I067b39f3b32eb3aa92d4155d4ca703ca7690645b

Please strip Change-Id when sending patches upstream.

> 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 4131b47..d487d94 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 8ef1c3d..5817f59 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -305,67 +305,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);
> @@ -376,31 +315,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;
>  }
>  
> @@ -454,8 +377,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)))

You have extra parentheses here and below.

Sean

>  		return;
>  
>  	ret = msm_dsi_host_power_on(host, &phy_shared_timings[id]);
> @@ -556,11 +479,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) {
> @@ -621,7 +544,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);
> @@ -704,6 +627,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
>
diff mbox

Patch

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 4131b47..d487d94 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 8ef1c3d..5817f59 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -305,67 +305,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);
@@ -376,31 +315,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;
 }
 
@@ -454,8 +377,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]);
@@ -556,11 +479,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) {
@@ -621,7 +544,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);
@@ -704,6 +627,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)
 {