diff options
| author | Inki Dae <inki.dae@samsung.com> | 2014-05-29 05:28:02 -0400 |
|---|---|---|
| committer | Inki Dae <inki.dae@samsung.com> | 2014-06-02 01:29:39 -0400 |
| commit | df5225bc9a87f1589a17797ee8e193608e4f3a9e (patch) | |
| tree | 6958bf8ac68f4f3f8cbc19d5526adc3155846c80 | |
| parent | 2e1ce1a1dd7c110faa8b99f0b76d1382e5de61f1 (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.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_dpi.c | 22 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.c | 138 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.h | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_dsi.c | 41 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fimd.c | 51 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_hdmi.c | 78 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_mixer.c | 17 |
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 | ||
| 1326 | static int exynos_dp_probe(struct platform_device *pdev) | 1326 | static 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 | ||
| 1331 | static int exynos_dp_remove(struct platform_device *pdev) | 1343 | static 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 | |||
| 329 | err_del_component: | ||
| 330 | exynos_drm_component_del(dev, EXYNOS_DEVICE_TYPE_CONNECTOR); | ||
| 331 | |||
| 332 | return NULL; | ||
| 319 | } | 333 | } |
| 320 | 334 | ||
| 321 | int exynos_dpi_remove(struct device *dev) | 335 | int 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 | ||
| 49 | struct component_dev { | 49 | struct 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 | ||
| 54 | static int exynos_drm_load(struct drm_device *dev, unsigned long flags) | 57 | static 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 | ||
| 384 | int exynos_drm_component_add(struct device *dev, | 387 | int 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); | ||
