#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;
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;
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)
{
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,
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);
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);