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.c86
1 files changed, 59 insertions, 27 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index e7fa3cd96743..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)
return false;
}
+static void omap_disconnect_dssdevs(void)
+{
+ struct omap_dss_device *dssdev = NULL;
+
+ for_each_dss_dev(dssdev)
+ dssdev->driver->disconnect(dssdev);
+}
+
+static int omap_connect_dssdevs(void)
+{
+ int r;
+ struct omap_dss_device *dssdev = NULL;
+ bool no_displays = true;
+
+ for_each_dss_dev(dssdev) {
+ r = dssdev->driver->connect(dssdev);
+ if (r == -EPROBE_DEFER) {
+ omap_dss_put_device(dssdev);
+ goto cleanup;
+ } else if (r) {
+ dev_warn(dssdev->dev, "could not connect display: %s\n",
+ dssdev->name);
+ } else {
+ no_displays = false;
+ }
+ }
+
+ if (no_displays)
+ return -EPROBE_DEFER;
+
+ return 0;
+
+cleanup:
+ /*
+ * if we are deferring probe, we disconnect the devices we previously
+ * connected
+ */
+ omap_disconnect_dssdevs();
+
+ return r;
+}
static int omap_modeset_init(struct drm_device *dev)
{
@@ -95,9 +136,6 @@ static int omap_modeset_init(struct drm_device *dev)
int num_mgrs = dss_feat_get_num_mgrs();
int num_crtcs;
int i, id = 0;
- int r;
-
- omap_crtc_pre_init();
drm_mode_config_init(dev);
@@ -119,26 +157,8 @@ static int omap_modeset_init(struct drm_device *dev)
enum omap_channel channel;
struct omap_overlay_manager *mgr;
- if (!dssdev->driver) {
- dev_warn(dev->dev, "%s has no driver.. skipping it\n",
- dssdev->name);
- continue;
- }
-
- if (!(dssdev->driver->get_timings ||
- dssdev->driver->read_edid)) {
- dev_warn(dev->dev, "%s driver does not support "
- "get_timings or read_edid.. skipping it!\n",
- dssdev->name);
- continue;
- }
-
- r = dssdev->driver->connect(dssdev);
- if (r) {
- dev_err(dev->dev, "could not connect display: %s\n",
- dssdev->name);
+ if (!omapdss_device_is_connected(dssdev))
continue;
- }
encoder = omap_encoder_init(dev, dssdev);
@@ -497,16 +517,16 @@ static int dev_unload(struct drm_device *dev)
DBG("unload: dev=%p", dev);
drm_kms_helper_poll_fini(dev);
- drm_vblank_cleanup(dev);
- omap_drm_irq_uninstall(dev);
omap_fbdev_free(dev);
omap_modeset_free(dev);
omap_gem_deinit(dev);
- flush_workqueue(priv->wq);
destroy_workqueue(priv->wq);
+ drm_vblank_cleanup(dev);
+ omap_drm_irq_uninstall(dev);
+
kfree(dev->dev_private);
dev->dev_private = NULL;
@@ -655,9 +675,19 @@ static void pdev_shutdown(struct platform_device *device)
static int pdev_probe(struct platform_device *device)
{
+ int r;
+
if (omapdss_is_initialized() == false)
return -EPROBE_DEFER;
+ omap_crtc_pre_init();
+
+ r = omap_connect_dssdevs();
+ if (r) {
+ omap_crtc_pre_uninit();
+ return r;
+ }
+
DBG("%s", device->name);
return drm_platform_init(&omap_drm_driver, device);
}
@@ -665,9 +695,11 @@ static int pdev_probe(struct platform_device *device)
static int pdev_remove(struct platform_device *device)
{
DBG("");
- drm_platform_exit(&omap_drm_driver, device);
- platform_driver_unregister(&omap_dmm_driver);
+ omap_disconnect_dssdevs();
+ omap_crtc_pre_uninit();
+
+ drm_put_dev(platform_get_drvdata(device));
return 0;
}