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

Signed-off-by: Chandan Uddaraju <chand...@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..157df42 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)
 {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to