summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/dsi/dsi_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c')
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c124
1 files changed, 57 insertions, 67 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index af2a287cb3bd..ca400924d4ee 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -74,17 +74,35 @@ static int dsi_mgr_setup_components(int id)
int ret;
if (!IS_BONDED_DSI()) {
+ /*
+ * Set the usecase before calling msm_dsi_host_register(), which would
+ * already program the PLL source mux based on a default usecase.
+ */
+ msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE);
+ msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy);
+
ret = msm_dsi_host_register(msm_dsi->host);
if (ret)
return ret;
-
- msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE);
- msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy);
} else if (other_dsi) {
struct msm_dsi *master_link_dsi = IS_MASTER_DSI_LINK(id) ?
msm_dsi : other_dsi;
struct msm_dsi *slave_link_dsi = IS_MASTER_DSI_LINK(id) ?
other_dsi : msm_dsi;
+
+ /*
+ * PLL0 is to drive both DSI link clocks in bonded DSI mode.
+ *
+ * Set the usecase before calling msm_dsi_host_register(), which would
+ * already program the PLL source mux based on a default usecase.
+ */
+ msm_dsi_phy_set_usecase(clk_master_dsi->phy,
+ MSM_DSI_PHY_MASTER);
+ msm_dsi_phy_set_usecase(clk_slave_dsi->phy,
+ MSM_DSI_PHY_SLAVE);
+ msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy);
+ msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy);
+
/* Register slave host first, so that slave DSI device
* has a chance to probe, and do not block the master
* DSI device's probe.
@@ -98,14 +116,6 @@ static int dsi_mgr_setup_components(int id)
ret = msm_dsi_host_register(master_link_dsi->host);
if (ret)
return ret;
-
- /* PLL0 is to drive both 2 DSI link clocks in bonded DSI mode. */
- msm_dsi_phy_set_usecase(clk_master_dsi->phy,
- MSM_DSI_PHY_MASTER);
- msm_dsi_phy_set_usecase(clk_slave_dsi->phy,
- MSM_DSI_PHY_SLAVE);
- msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy);
- msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy);
}
return 0;
@@ -423,7 +433,19 @@ static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge *bridge,
return msm_dsi_host_check_dsc(host, mode);
}
+static int dsi_mgr_bridge_attach(struct drm_bridge *bridge,
+ struct drm_encoder *encoder,
+ enum drm_bridge_attach_flags flags)
+{
+ int id = dsi_mgr_bridge_get_id(bridge);
+ struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+
+ return drm_bridge_attach(encoder, msm_dsi->next_bridge,
+ bridge, flags);
+}
+
static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = {
+ .attach = dsi_mgr_bridge_attach,
.pre_enable = dsi_mgr_bridge_pre_enable,
.post_disable = dsi_mgr_bridge_post_disable,
.mode_set = dsi_mgr_bridge_mode_set,
@@ -431,79 +453,42 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = {
};
/* initialize bridge */
-struct drm_bridge *msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi,
- struct drm_encoder *encoder)
+int msm_dsi_manager_connector_init(struct msm_dsi *msm_dsi,
+ struct drm_encoder *encoder)
{
+ struct drm_device *dev = msm_dsi->dev;
struct drm_bridge *bridge;
struct dsi_bridge *dsi_bridge;
+ struct drm_connector *connector;
int ret;
- dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
- sizeof(*dsi_bridge), GFP_KERNEL);
- if (!dsi_bridge)
- return ERR_PTR(-ENOMEM);
+ dsi_bridge = devm_drm_bridge_alloc(msm_dsi->dev->dev, struct dsi_bridge, base,
+ &dsi_mgr_bridge_funcs);
+ if (IS_ERR(dsi_bridge))
+ return PTR_ERR(dsi_bridge);
dsi_bridge->id = msm_dsi->id;
bridge = &dsi_bridge->base;
- bridge->funcs = &dsi_mgr_bridge_funcs;
ret = devm_drm_bridge_add(msm_dsi->dev->dev, bridge);
if (ret)
- return ERR_PTR(ret);
+ return ret;
- ret = drm_bridge_attach(encoder, bridge, NULL, 0);
+ ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret)
- return ERR_PTR(ret);
-
- return bridge;
-}
-
-int msm_dsi_manager_ext_bridge_init(u8 id, struct drm_bridge *int_bridge)
-{
- struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
- struct drm_device *dev = msm_dsi->dev;
- struct drm_encoder *encoder;
- struct drm_bridge *ext_bridge;
- int ret;
+ return ret;
- ext_bridge = devm_drm_of_get_bridge(&msm_dsi->pdev->dev,
- msm_dsi->pdev->dev.of_node, 1, 0);
- if (IS_ERR(ext_bridge))
- return PTR_ERR(ext_bridge);
-
- encoder = int_bridge->encoder;
-
- /*
- * Try first to create the bridge without it creating its own
- * connector.. currently some bridges support this, and others
- * do not (and some support both modes)
- */
- ret = drm_bridge_attach(encoder, ext_bridge, int_bridge,
- DRM_BRIDGE_ATTACH_NO_CONNECTOR);
- if (ret == -EINVAL) {
- /*
- * link the internal dsi bridge to the external bridge,
- * connector is created by the next bridge.
- */
- ret = drm_bridge_attach(encoder, ext_bridge, int_bridge, 0);
- if (ret < 0)
- return ret;
- } else {
- struct drm_connector *connector;
-
- /* We are in charge of the connector, create one now. */
- connector = drm_bridge_connector_init(dev, encoder);
- if (IS_ERR(connector)) {
- DRM_ERROR("Unable to create bridge connector\n");
- return PTR_ERR(connector);
- }
-
- ret = drm_connector_attach_encoder(connector, encoder);
- if (ret < 0)
- return ret;
+ connector = drm_bridge_connector_init(dev, encoder);
+ if (IS_ERR(connector)) {
+ DRM_ERROR("Unable to create bridge connector\n");
+ return PTR_ERR(connector);
}
+ ret = drm_connector_attach_encoder(connector, encoder);
+ if (ret < 0)
+ return ret;
+
return 0;
}
@@ -628,3 +613,8 @@ bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi)
{
return IS_MASTER_DSI_LINK(msm_dsi->id);
}
+
+const char *msm_dsi_get_te_source(struct msm_dsi *msm_dsi)
+{
+ return msm_dsi->te_source;
+}