Merge branch 'akpm' (patches from Andrew)
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / arm / hdlcd_drv.c
index 81ae923..479c242 100644 (file)
@@ -29,7 +29,6 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_irq.h>
 #include <drm/drm_modeset_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
 #include "hdlcd_drv.h"
 #include "hdlcd_regs.h"
 
+static irqreturn_t hdlcd_irq(int irq, void *arg)
+{
+       struct drm_device *drm = arg;
+       struct hdlcd_drm_private *hdlcd = drm->dev_private;
+       unsigned long irq_status;
+
+       irq_status = hdlcd_read(hdlcd, HDLCD_REG_INT_STATUS);
+
+#ifdef CONFIG_DEBUG_FS
+       if (irq_status & HDLCD_INTERRUPT_UNDERRUN)
+               atomic_inc(&hdlcd->buffer_underrun_count);
+
+       if (irq_status & HDLCD_INTERRUPT_DMA_END)
+               atomic_inc(&hdlcd->dma_end_count);
+
+       if (irq_status & HDLCD_INTERRUPT_BUS_ERROR)
+               atomic_inc(&hdlcd->bus_error_count);
+
+       if (irq_status & HDLCD_INTERRUPT_VSYNC)
+               atomic_inc(&hdlcd->vsync_count);
+
+#endif
+       if (irq_status & HDLCD_INTERRUPT_VSYNC)
+               drm_crtc_handle_vblank(&hdlcd->crtc);
+
+       /* acknowledge interrupt(s) */
+       hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);
+
+       return IRQ_HANDLED;
+}
+
+static void hdlcd_irq_preinstall(struct drm_device *drm)
+{
+       struct hdlcd_drm_private *hdlcd = drm->dev_private;
+       /* Ensure interrupts are disabled */
+       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
+       hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0);
+}
+
+static void hdlcd_irq_postinstall(struct drm_device *drm)
+{
+#ifdef CONFIG_DEBUG_FS
+       struct hdlcd_drm_private *hdlcd = drm->dev_private;
+       unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
+
+       /* enable debug interrupts */
+       irq_mask |= HDLCD_DEBUG_INT_MASK;
+
+       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
+#endif
+}
+
+static int hdlcd_irq_install(struct drm_device *drm, int irq)
+{
+       int ret;
+
+       if (irq == IRQ_NOTCONNECTED)
+               return -ENOTCONN;
+
+       hdlcd_irq_preinstall(drm);
+
+       ret = request_irq(irq, hdlcd_irq, 0, drm->driver->name, drm);
+       if (ret)
+               return ret;
+
+       hdlcd_irq_postinstall(drm);
+
+       return 0;
+}
+
+static void hdlcd_irq_uninstall(struct drm_device *drm)
+{
+       struct hdlcd_drm_private *hdlcd = drm->dev_private;
+       /* disable all the interrupts that we might have enabled */
+       unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
+
+#ifdef CONFIG_DEBUG_FS
+       /* disable debug interrupts */
+       irq_mask &= ~HDLCD_DEBUG_INT_MASK;
+#endif
+
+       /* disable vsync interrupts */
+       irq_mask &= ~HDLCD_INTERRUPT_VSYNC;
+       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
+
+       free_irq(hdlcd->irq, drm);
+}
+
 static int hdlcd_load(struct drm_device *drm, unsigned long flags)
 {
        struct hdlcd_drm_private *hdlcd = drm->dev_private;
@@ -90,7 +177,12 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
                goto setup_fail;
        }
 
-       ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0)
+               goto irq_fail;
+       hdlcd->irq = ret;
+
+       ret = hdlcd_irq_install(drm, hdlcd->irq);
        if (ret < 0) {
                DRM_ERROR("failed to install IRQ handler\n");
                goto irq_fail;
@@ -122,76 +214,6 @@ static void hdlcd_setup_mode_config(struct drm_device *drm)
        drm->mode_config.funcs = &hdlcd_mode_config_funcs;
 }
 
-static irqreturn_t hdlcd_irq(int irq, void *arg)
-{
-       struct drm_device *drm = arg;
-       struct hdlcd_drm_private *hdlcd = drm->dev_private;
-       unsigned long irq_status;
-
-       irq_status = hdlcd_read(hdlcd, HDLCD_REG_INT_STATUS);
-
-#ifdef CONFIG_DEBUG_FS
-       if (irq_status & HDLCD_INTERRUPT_UNDERRUN)
-               atomic_inc(&hdlcd->buffer_underrun_count);
-
-       if (irq_status & HDLCD_INTERRUPT_DMA_END)
-               atomic_inc(&hdlcd->dma_end_count);
-
-       if (irq_status & HDLCD_INTERRUPT_BUS_ERROR)
-               atomic_inc(&hdlcd->bus_error_count);
-
-       if (irq_status & HDLCD_INTERRUPT_VSYNC)
-               atomic_inc(&hdlcd->vsync_count);
-
-#endif
-       if (irq_status & HDLCD_INTERRUPT_VSYNC)
-               drm_crtc_handle_vblank(&hdlcd->crtc);
-
-       /* acknowledge interrupt(s) */
-       hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);
-
-       return IRQ_HANDLED;
-}
-
-static void hdlcd_irq_preinstall(struct drm_device *drm)
-{
-       struct hdlcd_drm_private *hdlcd = drm->dev_private;
-       /* Ensure interrupts are disabled */
-       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
-       hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0);
-}
-
-static int hdlcd_irq_postinstall(struct drm_device *drm)
-{
-#ifdef CONFIG_DEBUG_FS
-       struct hdlcd_drm_private *hdlcd = drm->dev_private;
-       unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
-
-       /* enable debug interrupts */
-       irq_mask |= HDLCD_DEBUG_INT_MASK;
-
-       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
-#endif
-       return 0;
-}
-
-static void hdlcd_irq_uninstall(struct drm_device *drm)
-{
-       struct hdlcd_drm_private *hdlcd = drm->dev_private;
-       /* disable all the interrupts that we might have enabled */
-       unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
-
-#ifdef CONFIG_DEBUG_FS
-       /* disable debug interrupts */
-       irq_mask &= ~HDLCD_DEBUG_INT_MASK;
-#endif
-
-       /* disable vsync interrupts */
-       irq_mask &= ~HDLCD_INTERRUPT_VSYNC;
-
-       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
-}
-
 #ifdef CONFIG_DEBUG_FS
 static int hdlcd_show_underrun_count(struct seq_file *m, void *arg)
 {
@@ -236,10 +258,6 @@ DEFINE_DRM_GEM_CMA_FOPS(fops);
 
 static const struct drm_driver hdlcd_driver = {
        .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
-       .irq_handler = hdlcd_irq,
-       .irq_preinstall = hdlcd_irq_preinstall,
-       .irq_postinstall = hdlcd_irq_postinstall,
-       .irq_uninstall = hdlcd_irq_uninstall,
        DRM_GEM_CMA_DRIVER_OPS,
 #ifdef CONFIG_DEBUG_FS
        .debugfs_init = hdlcd_debugfs_init,
@@ -316,7 +334,7 @@ err_pm_active:
 err_unload:
        of_node_put(hdlcd->crtc.port);
        hdlcd->crtc.port = NULL;
-       drm_irq_uninstall(drm);
+       hdlcd_irq_uninstall(drm);
        of_reserved_mem_device_release(drm->dev);
 err_free:
        drm_mode_config_cleanup(drm);
@@ -338,7 +356,7 @@ static void hdlcd_drm_unbind(struct device *dev)
        hdlcd->crtc.port = NULL;
        pm_runtime_get_sync(dev);
        drm_atomic_helper_shutdown(drm);
-       drm_irq_uninstall(drm);
+       hdlcd_irq_uninstall(drm);
        pm_runtime_put(dev);
        if (pm_runtime_enabled(dev))
                pm_runtime_disable(dev);