aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c94
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
152static void omap_disconnect_dssdevs(void) 152static 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
160static int omap_connect_dssdevs(void) 168static 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 */
338static void omap_modeset_enable_external_hpd(void) 350static 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 */
351static void omap_modeset_disable_external_hpd(void) 366static 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
592err_cleanup_helpers: 610err_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:
600err_gem_deinit: 618err_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);
604err_crtc_uninit: 622err_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
677static int omap_drm_suspend_all_displays(void) 695static 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
696static int omap_drm_resume_all_displays(void) 717static 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);