diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 13f294aeaefd..bf39fcc49e0f 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c | |||
@@ -86,6 +86,47 @@ static bool channel_used(struct drm_device *dev, enum omap_channel channel) | |||
86 | 86 | ||
87 | return false; | 87 | return false; |
88 | } | 88 | } |
89 | static void omap_disconnect_dssdevs(void) | ||
90 | { | ||
91 | struct omap_dss_device *dssdev = NULL; | ||
92 | |||
93 | for_each_dss_dev(dssdev) | ||
94 | dssdev->driver->disconnect(dssdev); | ||
95 | } | ||
96 | |||
97 | static int omap_connect_dssdevs(void) | ||
98 | { | ||
99 | int r; | ||
100 | struct omap_dss_device *dssdev = NULL; | ||
101 | bool no_displays = true; | ||
102 | |||
103 | for_each_dss_dev(dssdev) { | ||
104 | r = dssdev->driver->connect(dssdev); | ||
105 | if (r == -EPROBE_DEFER) { | ||
106 | omap_dss_put_device(dssdev); | ||
107 | goto cleanup; | ||
108 | } else if (r) { | ||
109 | dev_warn(dssdev->dev, "could not connect display: %s\n", | ||
110 | dssdev->name); | ||
111 | } else { | ||
112 | no_displays = false; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | if (no_displays) | ||
117 | return -EPROBE_DEFER; | ||
118 | |||
119 | return 0; | ||
120 | |||
121 | cleanup: | ||
122 | /* | ||
123 | * if we are deferring probe, we disconnect the devices we previously | ||
124 | * connected | ||
125 | */ | ||
126 | omap_disconnect_dssdevs(); | ||
127 | |||
128 | return r; | ||
129 | } | ||
89 | 130 | ||
90 | static int omap_modeset_init(struct drm_device *dev) | 131 | static int omap_modeset_init(struct drm_device *dev) |
91 | { | 132 | { |
@@ -95,9 +136,6 @@ static int omap_modeset_init(struct drm_device *dev) | |||
95 | int num_mgrs = dss_feat_get_num_mgrs(); | 136 | int num_mgrs = dss_feat_get_num_mgrs(); |
96 | int num_crtcs; | 137 | int num_crtcs; |
97 | int i, id = 0; | 138 | int i, id = 0; |
98 | int r; | ||
99 | |||
100 | omap_crtc_pre_init(); | ||
101 | 139 | ||
102 | drm_mode_config_init(dev); | 140 | drm_mode_config_init(dev); |
103 | 141 | ||
@@ -119,26 +157,8 @@ static int omap_modeset_init(struct drm_device *dev) | |||
119 | enum omap_channel channel; | 157 | enum omap_channel channel; |
120 | struct omap_overlay_manager *mgr; | 158 | struct omap_overlay_manager *mgr; |
121 | 159 | ||
122 | if (!dssdev->driver) { | 160 | if (!omapdss_device_is_connected(dssdev)) |
123 | dev_warn(dev->dev, "%s has no driver.. skipping it\n", | ||
124 | dssdev->name); | ||
125 | continue; | 161 | continue; |
126 | } | ||
127 | |||
128 | if (!(dssdev->driver->get_timings || | ||
129 | dssdev->driver->read_edid)) { | ||
130 | dev_warn(dev->dev, "%s driver does not support " | ||
131 | "get_timings or read_edid.. skipping it!\n", | ||
132 | dssdev->name); | ||
133 | continue; | ||
134 | } | ||
135 | |||
136 | r = dssdev->driver->connect(dssdev); | ||
137 | if (r) { | ||
138 | dev_err(dev->dev, "could not connect display: %s\n", | ||
139 | dssdev->name); | ||
140 | continue; | ||
141 | } | ||
142 | 162 | ||
143 | encoder = omap_encoder_init(dev, dssdev); | 163 | encoder = omap_encoder_init(dev, dssdev); |
144 | 164 | ||
@@ -497,16 +517,16 @@ static int dev_unload(struct drm_device *dev) | |||
497 | DBG("unload: dev=%p", dev); | 517 | DBG("unload: dev=%p", dev); |
498 | 518 | ||
499 | drm_kms_helper_poll_fini(dev); | 519 | drm_kms_helper_poll_fini(dev); |
500 | drm_vblank_cleanup(dev); | ||
501 | omap_drm_irq_uninstall(dev); | ||
502 | 520 | ||
503 | omap_fbdev_free(dev); | 521 | omap_fbdev_free(dev); |
504 | omap_modeset_free(dev); | 522 | omap_modeset_free(dev); |
505 | omap_gem_deinit(dev); | 523 | omap_gem_deinit(dev); |
506 | 524 | ||
507 | flush_workqueue(priv->wq); | ||
508 | destroy_workqueue(priv->wq); | 525 | destroy_workqueue(priv->wq); |
509 | 526 | ||
527 | drm_vblank_cleanup(dev); | ||
528 | omap_drm_irq_uninstall(dev); | ||
529 | |||
510 | kfree(dev->dev_private); | 530 | kfree(dev->dev_private); |
511 | dev->dev_private = NULL; | 531 | dev->dev_private = NULL; |
512 | 532 | ||
@@ -655,9 +675,19 @@ static void pdev_shutdown(struct platform_device *device) | |||
655 | 675 | ||
656 | static int pdev_probe(struct platform_device *device) | 676 | static int pdev_probe(struct platform_device *device) |
657 | { | 677 | { |
678 | int r; | ||
679 | |||
658 | if (omapdss_is_initialized() == false) | 680 | if (omapdss_is_initialized() == false) |
659 | return -EPROBE_DEFER; | 681 | return -EPROBE_DEFER; |
660 | 682 | ||
683 | omap_crtc_pre_init(); | ||
684 | |||
685 | r = omap_connect_dssdevs(); | ||
686 | if (r) { | ||
687 | omap_crtc_pre_uninit(); | ||
688 | return r; | ||
689 | } | ||
690 | |||
661 | DBG("%s", device->name); | 691 | DBG("%s", device->name); |
662 | return drm_platform_init(&omap_drm_driver, device); | 692 | return drm_platform_init(&omap_drm_driver, device); |
663 | } | 693 | } |
@@ -666,8 +696,10 @@ static int pdev_remove(struct platform_device *device) | |||
666 | { | 696 | { |
667 | DBG(""); | 697 | DBG(""); |
668 | 698 | ||
669 | drm_put_dev(platform_get_drvdata(device)); | 699 | omap_disconnect_dssdevs(); |
700 | omap_crtc_pre_uninit(); | ||
670 | 701 | ||
702 | drm_put_dev(platform_get_drvdata(device)); | ||
671 | return 0; | 703 | return 0; |
672 | } | 704 | } |
673 | 705 | ||