aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorInki Dae <inki.dae@samsung.com>2014-05-29 05:28:02 -0400
committerInki Dae <inki.dae@samsung.com>2014-06-02 01:29:39 -0400
commitdf5225bc9a87f1589a17797ee8e193608e4f3a9e (patch)
tree6958bf8ac68f4f3f8cbc19d5526adc3155846c80
parent2e1ce1a1dd7c110faa8b99f0b76d1382e5de61f1 (diff)
drm/exynos: consider deferred probe case
This patch makes sure that exynos drm framework handles deferred probe case correctly. Sub drivers could be probed before resources, clock, regulator, phy or panel, are ready for them so we should make sure that exynos drm core waits until all resources are ready and sub drivers are probed correctly. Chagelog v2: - Make sure that exynos drm core tries to bind sub drivers only in case that they have a pair: crtc and encoder/connector components should be a pair. - Remove unnecessary patch: drm/exynos: mipi-dsi: consider panel driver-deferred probe - Return error type correctly. Signed-off-by: Inki Dae <inki.dae@samsung.com> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp_core.c18
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dpi.c22
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c138
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h13
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c41
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c51
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c78
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c17
8 files changed, 303 insertions, 75 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
index 8b67f4141e78..5e05dbc60082 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.c
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
@@ -1325,12 +1325,26 @@ static const struct component_ops exynos_dp_ops = {
1325 1325
1326static int exynos_dp_probe(struct platform_device *pdev) 1326static int exynos_dp_probe(struct platform_device *pdev)
1327{ 1327{
1328 return exynos_drm_component_add(&pdev->dev, &exynos_dp_ops); 1328 int ret;
1329
1330 ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
1331 exynos_dp_display.type);
1332 if (ret)
1333 return ret;
1334
1335 ret = component_add(&pdev->dev, &exynos_dp_ops);
1336 if (ret)
1337 exynos_drm_component_del(&pdev->dev,
1338 EXYNOS_DEVICE_TYPE_CONNECTOR);
1339
1340 return ret;
1329} 1341}
1330 1342
1331static int exynos_dp_remove(struct platform_device *pdev) 1343static int exynos_dp_remove(struct platform_device *pdev)
1332{ 1344{
1333 exynos_drm_component_del(&pdev->dev, &exynos_dp_ops); 1345 component_del(&pdev->dev, &exynos_dp_ops);
1346 exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
1347
1334 return 0; 1348 return 0;
1335} 1349}
1336 1350
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
index a832364358a7..f1b8587cc63d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
@@ -295,9 +295,15 @@ struct exynos_drm_display *exynos_dpi_probe(struct device *dev)
295 struct exynos_dpi *ctx; 295 struct exynos_dpi *ctx;
296 int ret; 296 int ret;
297 297
298 ret = exynos_drm_component_add(dev,
299 EXYNOS_DEVICE_TYPE_CONNECTOR,
300 exynos_dpi_display.type);
301 if (ret)
302 return ERR_PTR(ret);
303
298 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 304 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
299 if (!ctx) 305 if (!ctx)
300 return NULL; 306 goto err_del_component;
301 307
302 ctx->dev = dev; 308 ctx->dev = dev;
303 exynos_dpi_display.ctx = ctx; 309 exynos_dpi_display.ctx = ctx;
@@ -306,16 +312,24 @@ struct exynos_drm_display *exynos_dpi_probe(struct device *dev)
306 ret = exynos_dpi_parse_dt(ctx); 312 ret = exynos_dpi_parse_dt(ctx);
307 if (ret < 0) { 313 if (ret < 0) {
308 devm_kfree(dev, ctx); 314 devm_kfree(dev, ctx);
309 return NULL; 315 goto err_del_component;
310 } 316 }
311 317
312 if (ctx->panel_node) { 318 if (ctx->panel_node) {
313 ctx->panel = of_drm_find_panel(ctx->panel_node); 319 ctx->panel = of_drm_find_panel(ctx->panel_node);
314 if (!ctx->panel) 320 if (!ctx->panel) {
321 exynos_drm_component_del(dev,
322 EXYNOS_DEVICE_TYPE_CONNECTOR);
315 return ERR_PTR(-EPROBE_DEFER); 323 return ERR_PTR(-EPROBE_DEFER);
324 }
316 } 325 }
317 326
318 return &exynos_dpi_display; 327 return &exynos_dpi_display;
328
329err_del_component:
330 exynos_drm_component_del(dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
331
332 return NULL;
319} 333}
320 334
321int exynos_dpi_remove(struct device *dev) 335int exynos_dpi_remove(struct device *dev)
@@ -327,5 +341,7 @@ int exynos_dpi_remove(struct device *dev)
327 encoder->funcs->destroy(encoder); 341 encoder->funcs->destroy(encoder);
328 drm_connector_cleanup(&ctx->connector); 342 drm_connector_cleanup(&ctx->connector);
329 343
344 exynos_drm_component_del(dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
345
330 return 0; 346 return 0;
331} 347}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index c5a401ae4de5..5d225dd58a87 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -48,7 +48,10 @@ static LIST_HEAD(drm_component_list);
48 48
49struct component_dev { 49struct component_dev {
50 struct list_head list; 50 struct list_head list;
51 struct device *dev; 51 struct device *crtc_dev;
52 struct device *conn_dev;
53 enum exynos_drm_output_type out_type;
54 unsigned int dev_type_flag;
52}; 55};
53 56
54static int exynos_drm_load(struct drm_device *dev, unsigned long flags) 57static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
@@ -382,22 +385,65 @@ static const struct dev_pm_ops exynos_drm_pm_ops = {
382}; 385};
383 386
384int exynos_drm_component_add(struct device *dev, 387int exynos_drm_component_add(struct device *dev,
385 const struct component_ops *ops) 388 enum exynos_drm_device_type dev_type,
389 enum exynos_drm_output_type out_type)
386{ 390{
387 struct component_dev *cdev; 391 struct component_dev *cdev;
388 int ret; 392
393 if (dev_type != EXYNOS_DEVICE_TYPE_CRTC &&
394 dev_type != EXYNOS_DEVICE_TYPE_CONNECTOR) {
395 DRM_ERROR("invalid device type.\n");
396 return -EINVAL;
397 }
398
399 mutex_lock(&drm_component_lock);
400
401 /*
402 * Make sure to check if there is a component which has two device
403 * objects, for connector and for encoder/connector.
404 * It should make sure that crtc and encoder/connector drivers are
405 * ready before exynos drm core binds them.
406 */
407 list_for_each_entry(cdev, &drm_component_list, list) {
408 if (cdev->out_type == out_type) {
409 /*
410 * If crtc and encoder/connector device objects are
411 * added already just return.
412 */
413 if (cdev->dev_type_flag == (EXYNOS_DEVICE_TYPE_CRTC |
414 EXYNOS_DEVICE_TYPE_CONNECTOR)) {
415 mutex_unlock(&drm_component_lock);
416 return 0;
417 }
418
419 if (dev_type == EXYNOS_DEVICE_TYPE_CRTC) {
420 cdev->crtc_dev = dev;
421 cdev->dev_type_flag |= dev_type;
422 }
423
424 if (dev_type == EXYNOS_DEVICE_TYPE_CONNECTOR) {
425 cdev->conn_dev = dev;
426 cdev->dev_type_flag |= dev_type;
427 }
428
429 mutex_unlock(&drm_component_lock);
430 return 0;
431 }
432 }
433
434 mutex_unlock(&drm_component_lock);