OSDN Git Service

Merge tag 'omapdrm-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux...
[android-x86/kernel.git] / drivers / gpu / drm / omapdrm / omap_drv.c
index 2603d90..bf39fcc 100644 (file)
@@ -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;
 
@@ -620,7 +640,6 @@ static struct drm_driver omap_drm_driver = {
                .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
                .gem_prime_export = omap_gem_prime_export,
                .gem_prime_import = omap_gem_prime_import,
-               .gem_init_object = omap_gem_init_object,
                .gem_free_object = omap_gem_free_object,
                .gem_vm_ops = &omap_gem_vm_ops,
                .dumb_create = omap_gem_dumb_create,
@@ -656,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);
 }
@@ -666,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;
 }