diff options
Diffstat (limited to 'drivers/gpu/drm/msm/dsi/dsi.c')
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi.c | 58 |
1 files changed, 35 insertions, 23 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 1f2561e2ff71..6edcd6f57e70 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c | |||
@@ -15,10 +15,10 @@ | |||
15 | 15 | ||
16 | struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi) | 16 | struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi) |
17 | { | 17 | { |
18 | if (!msm_dsi || !msm_dsi->panel) | 18 | if (!msm_dsi || !msm_dsi_device_connected(msm_dsi)) |
19 | return NULL; | 19 | return NULL; |
20 | 20 | ||
21 | return (msm_dsi->panel_flags & MIPI_DSI_MODE_VIDEO) ? | 21 | return (msm_dsi->device_flags & MIPI_DSI_MODE_VIDEO) ? |
22 | msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID] : | 22 | msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID] : |
23 | msm_dsi->encoders[MSM_DSI_CMD_ENCODER_ID]; | 23 | msm_dsi->encoders[MSM_DSI_CMD_ENCODER_ID]; |
24 | } | 24 | } |
@@ -74,19 +74,15 @@ static void dsi_destroy(struct msm_dsi *msm_dsi) | |||
74 | 74 | ||
75 | static struct msm_dsi *dsi_init(struct platform_device *pdev) | 75 | static struct msm_dsi *dsi_init(struct platform_device *pdev) |
76 | { | 76 | { |
77 | struct msm_dsi *msm_dsi = NULL; | 77 | struct msm_dsi *msm_dsi; |
78 | int ret; | 78 | int ret; |
79 | 79 | ||
80 | if (!pdev) { | 80 | if (!pdev) |
81 | ret = -ENXIO; | 81 | return ERR_PTR(-ENXIO); |
82 | goto fail; | ||
83 | } | ||
84 | 82 | ||
85 | msm_dsi = devm_kzalloc(&pdev->dev, sizeof(*msm_dsi), GFP_KERNEL); | 83 | msm_dsi = devm_kzalloc(&pdev->dev, sizeof(*msm_dsi), GFP_KERNEL); |
86 | if (!msm_dsi) { | 84 | if (!msm_dsi) |
87 | ret = -ENOMEM; | 85 | return ERR_PTR(-ENOMEM); |
88 | goto fail; | ||
89 | } | ||
90 | DBG("dsi probed=%p", msm_dsi); | 86 | DBG("dsi probed=%p", msm_dsi); |
91 | 87 | ||
92 | msm_dsi->pdev = pdev; | 88 | msm_dsi->pdev = pdev; |
@@ -95,24 +91,22 @@ static struct msm_dsi *dsi_init(struct platform_device *pdev) | |||
95 | /* Init dsi host */ | 91 | /* Init dsi host */ |
96 | ret = msm_dsi_host_init(msm_dsi); | 92 | ret = msm_dsi_host_init(msm_dsi); |
97 | if (ret) | 93 | if (ret) |
98 | goto fail; | 94 | goto destroy_dsi; |
99 | 95 | ||
100 | /* GET dsi PHY */ | 96 | /* GET dsi PHY */ |
101 | ret = dsi_get_phy(msm_dsi); | 97 | ret = dsi_get_phy(msm_dsi); |
102 | if (ret) | 98 | if (ret) |
103 | goto fail; | 99 | goto destroy_dsi; |
104 | 100 | ||
105 | /* Register to dsi manager */ | 101 | /* Register to dsi manager */ |
106 | ret = msm_dsi_manager_register(msm_dsi); | 102 | ret = msm_dsi_manager_register(msm_dsi); |
107 | if (ret) | 103 | if (ret) |
108 | goto fail; | 104 | goto destroy_dsi; |
109 | 105 | ||
110 | return msm_dsi; | 106 | return msm_dsi; |
111 | 107 | ||
112 | fail: | 108 | destroy_dsi: |
113 | if (msm_dsi) | 109 | dsi_destroy(msm_dsi); |
114 | dsi_destroy(msm_dsi); | ||
115 | |||
116 | return ERR_PTR(ret); | 110 | return ERR_PTR(ret); |
117 | } | 111 | } |
118 | 112 | ||
@@ -196,6 +190,7 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, | |||
196 | struct drm_encoder *encoders[MSM_DSI_ENCODER_NUM]) | 190 | struct drm_encoder *encoders[MSM_DSI_ENCODER_NUM]) |
197 | { | 191 | { |
198 | struct msm_drm_private *priv = dev->dev_private; | 192 | struct msm_drm_private *priv = dev->dev_private; |
193 | struct drm_bridge *ext_bridge; | ||
199 | int ret, i; | 194 | int ret, i; |
200 | 195 | ||
201 | if (WARN_ON(!encoders[MSM_DSI_VIDEO_ENCODER_ID] || | 196 | if (WARN_ON(!encoders[MSM_DSI_VIDEO_ENCODER_ID] || |
@@ -223,10 +218,25 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, | |||
223 | msm_dsi->encoders[i] = encoders[i]; | 218 | msm_dsi->encoders[i] = encoders[i]; |
224 | } | 219 | } |
225 | 220 | ||
226 | msm_dsi->connector = msm_dsi_manager_connector_init(msm_dsi->id); | 221 | /* |
222 | * check if the dsi encoder output is connected to a panel or an | ||
223 | * external bridge. We create a connector only if we're connected to a | ||
224 | * drm_panel device. When we're connected to an external bridge, we | ||
225 | * assume that the drm_bridge driver will create the connector itself. | ||
226 | */ | ||
227 | ext_bridge = msm_dsi_host_get_bridge(msm_dsi->host); | ||
228 | |||
229 | if (ext_bridge) | ||
230 | msm_dsi->connector = | ||
231 | msm_dsi_manager_ext_bridge_init(msm_dsi->id); | ||
232 | else | ||
233 | msm_dsi->connector = | ||
234 | msm_dsi_manager_connector_init(msm_dsi->id); | ||
235 | |||
227 | if (IS_ERR(msm_dsi->connector)) { | 236 | if (IS_ERR(msm_dsi->connector)) { |
228 | ret = PTR_ERR(msm_dsi->connector); | 237 | ret = PTR_ERR(msm_dsi->connector); |
229 | dev_err(dev->dev, "failed to create dsi connector: %d\n", ret); | 238 | dev_err(dev->dev, |
239 | "failed to create dsi connector: %d\n", ret); | ||
230 | msm_dsi->connector = NULL; | 240 | msm_dsi->connector = NULL; |
231 | goto fail; | 241 | goto fail; |
232 | } | 242 | } |
@@ -242,10 +252,12 @@ fail: | |||
242 | msm_dsi_manager_bridge_destroy(msm_dsi->bridge); | 252 | msm_dsi_manager_bridge_destroy(msm_dsi->bridge); |
243 | msm_dsi->bridge = NULL; | 253 | msm_dsi->bridge = NULL; |
244 | } | 254 | } |
245 | if (msm_dsi->connector) { | 255 | |
256 | /* don't destroy connector if we didn't make it */ | ||
257 | if (msm_dsi->connector && !msm_dsi->external_bridge) | ||
246 | msm_dsi->connector->funcs->destroy(msm_dsi->connector); | 258 | msm_dsi->connector->funcs->destroy(msm_dsi->connector); |
247 | msm_dsi->connector = NULL; | 259 | |
248 | } | 260 | msm_dsi->connector = NULL; |
249 | } | 261 | } |
250 | 262 | ||
251 | return ret; | 263 | return ret; |