diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c')
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 94 |
1 files changed, 59 insertions, 35 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index e5afecb4fd45..d1a1129a3f5d 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c | |||
| @@ -149,18 +149,27 @@ static int get_connector_type(struct omap_dss_device *dssdev) | |||
| 149 | } | 149 | } |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | static void omap_disconnect_dssdevs(void) | 152 | static void omap_disconnect_dssdevs(struct drm_device *ddev) |
| 153 | { | 153 | { |
| 154 | struct omap_dss_device *dssdev = NULL; | 154 | struct omap_drm_private *priv = ddev->dev_private; |
| 155 | unsigned int i; | ||
| 156 | |||
| 157 | for (i = 0; i < priv->num_dssdevs; i++) { | ||
| 158 | struct omap_dss_device *dssdev = priv->dssdevs[i]; | ||
| 155 | 159 | ||
| 156 | for_each_dss_dev(dssdev) | ||
| 157 | dssdev->driver->disconnect(dssdev); | 160 | dssdev->driver->disconnect(dssdev); |
| 161 | priv->dssdevs[i] = NULL; | ||
| 162 | omap_dss_put_device(dssdev); | ||
| 163 | } | ||
| 164 | |||
| 165 | priv->num_dssdevs = 0; | ||
| 158 | } | 166 | } |
| 159 | 167 | ||
| 160 | static int omap_connect_dssdevs(void) | 168 | static int omap_connect_dssdevs(struct drm_device *ddev) |
| 161 | { | 169 | { |
| 162 | int r; | 170 | struct omap_drm_private *priv = ddev->dev_private; |
| 163 | struct omap_dss_device *dssdev = NULL; | 171 | struct omap_dss_device *dssdev = NULL; |
| 172 | int r; | ||
| 164 | 173 | ||
| 165 | if (!omapdss_stack_is_ready()) | 174 | if (!omapdss_stack_is_ready()) |
| 166 | return -EPROBE_DEFER; | 175 | return -EPROBE_DEFER; |
| @@ -173,6 +182,14 @@ static int omap_connect_dssdevs(void) | |||
| 173 | } else if (r) { | 182 | } else if (r) { |
| 174 | dev_warn(dssdev->dev, "could not connect display: %s\n", | 183 | dev_warn(dssdev->dev, "could not connect display: %s\n", |
| 175 | dssdev->name); | 184 | dssdev->name); |
| 185 | } else { | ||
| 186 | omap_dss_get_device(dssdev); | ||
| 187 | priv->dssdevs[priv->num_dssdevs++] = dssdev; | ||
| 188 | if (priv->num_dssdevs == ARRAY_SIZE(priv->dssdevs)) { | ||
| 189 | /* To balance the 'for_each_dss_dev' loop */ | ||
| 190 | omap_dss_put_device(dssdev); | ||
| 191 | break; | ||
| 192 | } | ||
| 176 | } | 193 | } |
| 177 | } | 194 | } |
| 178 | 195 | ||
| @@ -183,7 +200,7 @@ cleanup: | |||
| 183 | * if we are deferring probe, we disconnect the devices we previously | 200 | * if we are deferring probe, we disconnect the devices we previously |
| 184 | * connected | 201 | * connected |
| 185 | */ | 202 | */ |
| 186 | omap_disconnect_dssdevs(); | 203 | omap_disconnect_dssdevs(ddev); |
| 187 | 204 | ||
| 188 | return r; | 205 | return r; |
| 189 | } | 206 | } |
| @@ -208,6 +225,7 @@ static int omap_modeset_init(struct drm_device *dev) | |||
| 208 | int num_ovls = priv->dispc_ops->get_num_ovls(priv->dispc); | 225 | int num_ovls = priv->dispc_ops->get_num_ovls(priv->dispc); |
| 209 | int num_mgrs = priv->dispc_ops->get_num_mgrs(priv->dispc); | 226 | int num_mgrs = priv->dispc_ops->get_num_mgrs(priv->dispc); |
| 210 | int num_crtcs, crtc_idx, plane_idx; | 227 | int num_crtcs, crtc_idx, plane_idx; |
| 228 | unsigned int i; | ||
| 211 | int ret; | 229 | int ret; |
| 212 | u32 plane_crtc_mask; | 230 | u32 plane_crtc_mask; |
| 213 | 231 | ||
| @@ -225,11 +243,7 @@ static int omap_modeset_init(struct drm_device *dev) | |||
| 225 | * configuration does not match the expectations or exceeds | 243 | * configuration does not match the expectations or exceeds |
| 226 | * the available resources, the configuration is rejected. | 244 | * the available resources, the configuration is rejected. |
| 227 | */ | 245 | */ |
| 228 | num_crtcs = 0; | 246 | num_crtcs = priv->num_dssdevs; |
| 229 | for_each_dss_dev(dssdev) | ||
| 230 | if (omapdss_device_is_connected(dssdev)) | ||
| 231 | num_crtcs++; | ||
| 232 | |||
| 233 | if (num_crtcs > num_mgrs || num_crtcs > num_ovls || | 247 | if (num_crtcs > num_mgrs || num_crtcs > num_ovls || |
| 234 | num_crtcs > ARRAY_SIZE(priv->crtcs) || | 248 | num_crtcs > ARRAY_SIZE(priv->crtcs) || |
| 235 | num_crtcs > ARRAY_SIZE(priv->planes) || | 249 | num_crtcs > ARRAY_SIZE(priv->planes) || |
| @@ -247,15 +261,13 @@ static int omap_modeset_init(struct drm_device *dev) | |||
| 247 | 261 | ||
| 248 | crtc_idx = 0; | 262 | crtc_idx = 0; |
| 249 | plane_idx = 0; | 263 | plane_idx = 0; |
| 250 | for_each_dss_dev(dssdev) { | 264 | for (i = 0; i < priv->num_dssdevs; i++) { |
| 265 | struct omap_dss_device *dssdev = priv->dssdevs[i]; | ||
| 251 | struct drm_connector *connector; | 266 | struct drm_connector *connector; |
| 252 | struct drm_encoder *encoder; | 267 | struct drm_encoder *encoder; |
| 253 | struct drm_plane *plane; | 268 | struct drm_plane *plane; |
| 254 | struct drm_crtc *crtc; | 269 | struct drm_crtc *crtc; |
| 255 | 270 | ||
| 256 | if (!omapdss_device_is_connected(dssdev)) | ||
| 257 | continue; | ||
| 258 | |||
| 259 | encoder = omap_encoder_init(dev, dssdev); | 271 | encoder = omap_encoder_init(dev, dssdev); |
| 260 | if (!encoder) | 272 | if (!encoder) |
| 261 | return -ENOMEM; | 273 | return -ENOMEM; |
| @@ -335,11 +347,14 @@ static int omap_modeset_init(struct drm_device *dev) | |||
| 335 | /* | 347 | /* |
| 336 | * Enable the HPD in external components if supported | 348 | * Enable the HPD in external components if supported |
| 337 | */ | 349 | */ |
| 338 | static void omap_modeset_enable_external_hpd(void) | 350 | static void omap_modeset_enable_external_hpd(struct drm_device *ddev) |
| 339 | { | 351 | { |
| 340 | struct omap_dss_device *dssdev = NULL; | 352 | struct omap_drm_private *priv = ddev->dev_private; |
| 353 | int i; | ||
| 354 | |||
| 355 | for (i = 0; i < priv->num_dssdevs; i++) { | ||
| 356 | struct omap_dss_device *dssdev = priv->dssdevs[i]; | ||
| 341 | 357 | ||
| 342 | for_each_dss_dev(dssdev) { | ||
| 343 | if (dssdev->driver->enable_hpd) | 358 | if (dssdev->driver->enable_hpd) |
| 344 | dssdev->driver->enable_hpd(dssdev); | 359 | dssdev->driver->enable_hpd(dssdev); |
| 345 | } | 360 | } |
| @@ -348,11 +363,14 @@ static void omap_modeset_enable_external_hpd(void) | |||
| 348 | /* | 363 | /* |
| 349 | * Disable the HPD in external components if supported | 364 | * Disable the HPD in external components if supported |
| 350 | */ | 365 | */ |
| 351 | static void omap_modeset_disable_external_hpd(void) | 366 | static void omap_modeset_disable_external_hpd(struct drm_device *ddev) |
| 352 | { | 367 | { |
| 353 | struct omap_dss_device *dssdev = NULL; | 368 | struct omap_drm_private *priv = ddev->dev_private; |
| 369 | int i; | ||
| 370 | |||
| 371 | for (i = 0; i < priv->num_dssdevs; i++) { | ||
| 372 | struct omap_dss_device *dssdev = priv->dssdevs[i]; | ||
| 354 | 373 | ||
| 355 | for_each_dss_dev(dssdev) { | ||
| 356 | if (dssdev->driver->disable_hpd) | 374 | if (dssdev->driver->disable_hpd) |
| 357 | dssdev->driver->disable_hpd(dssdev); | 375 | dssdev->driver->disable_hpd(dssdev); |
| 358 | } | 376 | } |
| @@ -540,7 +558,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) | |||
| 540 | 558 | ||
| 541 | omap_crtc_pre_init(priv); | 559 | omap_crtc_pre_init(priv); |
| 542 | 560 | ||
| 543 | ret = omap_connect_dssdevs(); | 561 | ret = omap_connect_dssdevs(ddev); |
| 544 | if (ret) | 562 | if (ret) |
| 545 | goto err_crtc_uninit; | 563 | goto err_crtc_uninit; |
| 546 | 564 | ||
| @@ -577,7 +595,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) | |||
| 577 | omap_fbdev_init(ddev); | 595 | omap_fbdev_init(ddev); |
| 578 | 596 | ||
| 579 | drm_kms_helper_poll_init(ddev); | 597 | drm_kms_helper_poll_init(ddev); |
| 580 | omap_modeset_enable_external_hpd(); | 598 | omap_modeset_enable_external_hpd(ddev); |
| 581 | 599 | ||
| 582 | /* | 600 | /* |
| 583 | * Register the DRM device with the core and the connectors with | 601 | * Register the DRM device with the core and the connectors with |
| @@ -590,7 +608,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) | |||
| 590 | return 0; | 608 | return 0; |
| 591 | 609 | ||
| 592 | err_cleanup_helpers: | 610 | err_cleanup_helpers: |
| 593 | omap_modeset_disable_external_hpd(); | 611 | omap_modeset_disable_external_hpd(ddev); |
| 594 | drm_kms_helper_poll_fini(ddev); | 612 | drm_kms_helper_poll_fini(ddev); |
| 595 | 613 | ||
| 596 | omap_fbdev_fini(ddev); | 614 | omap_fbdev_fini(ddev); |
| @@ -600,7 +618,7 @@ err_cleanup_modeset: | |||
| 600 | err_gem_deinit: | 618 | err_gem_deinit: |
| 601 | omap_gem_deinit(ddev); | 619 | omap_gem_deinit(ddev); |
| 602 | destroy_workqueue(priv->wq); | 620 | destroy_workqueue(priv->wq); |
| 603 | omap_disconnect_dssdevs(); | 621 | omap_disconnect_dssdevs(ddev); |
| 604 | err_crtc_uninit: | 622 | err_crtc_uninit: |
| 605 | omap_crtc_pre_uninit(); | 623 | omap_crtc_pre_uninit(); |
| 606 | drm_dev_unref(ddev); | 624 | drm_dev_unref(ddev); |
| @@ -615,7 +633,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv) | |||
| 615 | 633 | ||
| 616 | drm_dev_unregister(ddev); | 634 | drm_dev_unregister(ddev); |
| 617 | 635 | ||
| 618 | omap_modeset_disable_external_hpd(); | 636 | omap_modeset_disable_external_hpd(ddev); |
| 619 | drm_kms_helper_poll_fini(ddev); | 637 | drm_kms_helper_poll_fini(ddev); |
| 620 | 638 | ||
| 621 | omap_fbdev_fini(ddev); | 639 | omap_fbdev_fini(ddev); |
| @@ -629,7 +647,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv) | |||
| 629 | 647 | ||
| 630 | destroy_workqueue(priv->wq); | 648 | destroy_workqueue(priv->wq); |
| 631 | 649 | ||
| 632 | omap_disconnect_dssdevs(); | 650 | omap_disconnect_dssdevs(ddev); |
| 633 | omap_crtc_pre_uninit(); | 651 | omap_crtc_pre_uninit(); |
| 634 | 652 | ||
| 635 | drm_dev_unref(ddev); | 653 | drm_dev_unref(ddev); |
| @@ -674,11 +692,14 @@ static int pdev_remove(struct platform_device *pdev) | |||
| 674 | } | 692 | } |
| 675 | 693 | ||
| 676 | #ifdef CONFIG_PM_SLEEP | 694 | #ifdef CONFIG_PM_SLEEP |
| 677 | static int omap_drm_suspend_all_displays(void) | 695 | static int omap_drm_suspend_all_displays(struct drm_device *ddev) |
| 678 | { | 696 | { |
| 679 | struct omap_dss_device *dssdev = NULL; | 697 | struct omap_drm_private *priv = ddev->dev_private; |
| 698 | int i; | ||
| 699 | |||
| 700 | for (i = 0; i < priv->num_dssdevs; i++) { | ||
| 701 | struct omap_dss_device *dssdev = priv->dssdevs[i]; | ||
| 680 | 702 | ||
| 681 | for_each_dss_dev(dssdev) { | ||
| 682 | if (!dssdev->driver) | 703 | if (!dssdev->driver) |
| 683 | continue; | 704 | continue; |
| 684 | 705 | ||
| @@ -693,11 +714,14 @@ static int omap_drm_suspend_all_displays(void) | |||
| 693 | return 0; | 714 | return 0; |
| 694 | } | 715 | } |
| 695 | 716 | ||
| 696 | static int omap_drm_resume_all_displays(void) | 717 | static int omap_drm_resume_all_displays(struct drm_device *ddev) |
| 697 | { | 718 | { |
| 698 | struct omap_dss_device *dssdev = NULL; | 719 | struct omap_drm_private *priv = ddev->dev_private; |
| 720 | int i; | ||
| 721 | |||
| 722 | for (i = 0; i < priv->num_dssdevs; i++) { | ||
| 723 | struct omap_dss_device *dssdev = priv->dssdevs[i]; | ||
| 699 | 724 | ||
| 700 | for_each_dss_dev(dssdev) { | ||
| 701 | if (!dssdev->driver) | 725 | if (!dssdev->driver) |
| 702 | continue; | 726 | continue; |
| 703 | 727 | ||
| @@ -718,7 +742,7 @@ static int omap_drm_suspend(struct device *dev) | |||
| 718 | drm_kms_helper_poll_disable(drm_dev); | 742 | drm_kms_helper_poll_disable(drm_dev); |
| 719 | 743 | ||
| 720 | drm_modeset_lock_all(drm_dev); | 744 | drm_modeset_lock_all(drm_dev); |
| 721 | omap_drm_suspend_all_displays(); | 745 | omap_drm_suspend_all_displays(drm_dev); |
| 722 | drm_modeset_unlock_all(drm_dev); | 746 | drm_modeset_unlock_all(drm_dev); |
| 723 | 747 | ||
| 724 | return 0; | 748 | return 0; |
| @@ -730,7 +754,7 @@ static int omap_drm_resume(struct device *dev) | |||
| 730 | struct drm_device *drm_dev = priv->ddev; | 754 | struct drm_device *drm_dev = priv->ddev; |
| 731 | 755 | ||
| 732 | drm_modeset_lock_all(drm_dev); | 756 | drm_modeset_lock_all(drm_dev); |
| 733 | omap_drm_resume_all_displays(); | 757 | omap_drm_resume_all_displays(drm_dev); |
| 734 | drm_modeset_unlock_all(drm_dev); | 758 | drm_modeset_unlock_all(drm_dev); |
| 735 | 759 | ||
| 736 | drm_kms_helper_poll_enable(drm_dev); | 760 | drm_kms_helper_poll_enable(drm_dev); |
