Merge tag 'omapdrm-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux...
authorDave Airlie <airlied@redhat.com>
Tue, 28 Jan 2014 23:37:47 +0000 (09:37 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 28 Jan 2014 23:37:47 +0000 (09:37 +1000)
omapdrm patches for 3.14

* tag 'omapdrm-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux:
  drm/omap: Enable DT support for DMM
  drm/omap: fix: change dev_unload order
  drm/omap: fix: disable encoder before destroying it
  drm/omap: fix: disconnect devices when omapdrm module is removed
  drm/omap: fix: Defer probe if an omapdss device requests for it at connect
  drm/omap: fix (un)registering irqs inside an irq handler

Conflicts:
drivers/gpu/drm/omapdrm/omap_drv.c

drivers/gpu/drm/omapdrm/omap_crtc.c
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/omapdrm/omap_drv.h
drivers/gpu/drm/omapdrm/omap_encoder.c
drivers/gpu/drm/omapdrm/omap_irq.c
drivers/video/omap2/dss/dispc.c

index 0fd2eb139f6e402cd6856d5996ee4faf6affa950..4313bb0a49a62a70039e1bd952a402e2ac54221e 100644 (file)
@@ -411,7 +411,7 @@ static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
        struct drm_crtc *crtc = &omap_crtc->base;
        DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus);
        /* avoid getting in a flood, unregister the irq until next vblank */
-       omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
+       __omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
 }
 
 static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
@@ -421,13 +421,13 @@ static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
        struct drm_crtc *crtc = &omap_crtc->base;
 
        if (!omap_crtc->error_irq.registered)
-               omap_irq_register(crtc->dev, &omap_crtc->error_irq);
+               __omap_irq_register(crtc->dev, &omap_crtc->error_irq);
 
        if (!dispc_mgr_go_busy(omap_crtc->channel)) {
                struct omap_drm_private *priv =
                                crtc->dev->dev_private;
                DBG("%s: apply done", omap_crtc->name);
-               omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
+               __omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
                queue_work(priv->wq, &omap_crtc->apply_work);
        }
 }
@@ -623,6 +623,11 @@ void omap_crtc_pre_init(void)
        dss_install_mgr_ops(&mgr_ops);
 }
 
+void omap_crtc_pre_uninit(void)
+{
+       dss_uninstall_mgr_ops();
+}
+
 /* initialize crtc */
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
                struct drm_plane *plane, enum omap_channel channel, int id)
index 701c4c10e08b5858a5e083d05329af23c076669e..f926b4caf44989be904451c277049152cfc9b9ad 100644 (file)
@@ -969,12 +969,21 @@ static const struct dev_pm_ops omap_dmm_pm_ops = {
 };
 #endif
 
+#if defined(CONFIG_OF)
+static const struct of_device_id dmm_of_match[] = {
+       { .compatible = "ti,omap4-dmm", },
+       { .compatible = "ti,omap5-dmm", },
+       {},
+};
+#endif
+
 struct platform_driver omap_dmm_driver = {
        .probe = omap_dmm_probe,
        .remove = omap_dmm_remove,
        .driver = {
                .owner = THIS_MODULE,
                .name = DMM_DRIVER_NAME,
+               .of_match_table = of_match_ptr(dmm_of_match),
 #ifdef CONFIG_PM
                .pm = &omap_dmm_pm_ops,
 #endif
index 13f294aeaefd2e1a6b63a660c256407d25832e03..bf39fcc49e0f181ddcbf340632fa4f77c8b1bb10 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);
+               if (!omapdss_device_is_connected(dssdev))
                        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);
-                       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);
 }
@@ -666,8 +696,10 @@ static int pdev_remove(struct platform_device *device)
 {
        DBG("");
 
-       drm_put_dev(platform_get_drvdata(device));
+       omap_disconnect_dssdevs();
+       omap_crtc_pre_uninit();
 
+       drm_put_dev(platform_get_drvdata(device));
        return 0;
 }
 
index c88fea32dbf670e1a4477ce75a1b9e3ff8c135f2..428b2981fd685f3e42b3ec4d0a63021a94fdaf15 100644 (file)
@@ -145,6 +145,8 @@ irqreturn_t omap_irq_handler(int irq, void *arg);
 void omap_irq_preinstall(struct drm_device *dev);
 int omap_irq_postinstall(struct drm_device *dev);
 void omap_irq_uninstall(struct drm_device *dev);
+void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
+void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
 void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
 void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
 int omap_drm_irq_uninstall(struct drm_device *dev);
@@ -158,6 +160,7 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
 int omap_crtc_apply(struct drm_crtc *crtc,
                struct omap_drm_apply *apply);
 void omap_crtc_pre_init(void);
+void omap_crtc_pre_uninit(void);
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
                struct drm_plane *plane, enum omap_channel channel, int id);
 
index 6a12e899235bfe480dda3fd1bf80876bc6c805aa..5290a88c681db3e6cd2d4a9e4fa32c0e50230153 100644 (file)
@@ -51,6 +51,9 @@ struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder)
 static void omap_encoder_destroy(struct drm_encoder *encoder)
 {
        struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+
+       omap_encoder_set_enabled(encoder, false);
+
        drm_encoder_cleanup(encoder);
        kfree(omap_encoder);
 }
index 0e5336e5a79155a090b28941d45aa356320b6239..f035d2bceae7db358427c689b3a1fdd6cde28334 100644 (file)
@@ -45,12 +45,11 @@ static void omap_irq_update(struct drm_device *dev)
        dispc_read_irqenable();        /* flush posted write */
 }
 
-void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
+void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
 {
        struct omap_drm_private *priv = dev->dev_private;
        unsigned long flags;
 
-       dispc_runtime_get();
        spin_lock_irqsave(&list_lock, flags);
 
        if (!WARN_ON(irq->registered)) {
@@ -60,14 +59,21 @@ void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
        }
 
        spin_unlock_irqrestore(&list_lock, flags);
+}
+
+void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
+{
+       dispc_runtime_get();
+
+       __omap_irq_register(dev, irq);
+
        dispc_runtime_put();
 }
 
-void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
+void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
 {
        unsigned long flags;
 
-       dispc_runtime_get();
        spin_lock_irqsave(&list_lock, flags);
 
        if (!WARN_ON(!irq->registered)) {
@@ -77,6 +83,14 @@ void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
        }
 
        spin_unlock_irqrestore(&list_lock, flags);
+}
+
+void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
+{
+       dispc_runtime_get();
+
+       __omap_irq_unregister(dev, irq);
+
        dispc_runtime_put();
 }
 
index 4ec59ca72e5d0392518b2437483cea24533a2355..91c687fd002e5447d466b6e8e75f9c0c03dac32c 100644 (file)
@@ -3691,7 +3691,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
        }
 
        pm_runtime_enable(&pdev->dev);
-       pm_runtime_irq_safe(&pdev->dev);
 
        r = dispc_runtime_get();
        if (r)