summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/arm/hdlcd_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/arm/hdlcd_drv.c')
-rw-r--r--drivers/gpu/drm/arm/hdlcd_drv.c70
1 files changed, 25 insertions, 45 deletions
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index e89ae0ec60eb..350ca4e4eaa6 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_debugfs.h>
@@ -40,8 +41,7 @@
static irqreturn_t hdlcd_irq(int irq, void *arg)
{
- struct drm_device *drm = arg;
- struct hdlcd_drm_private *hdlcd = drm->dev_private;
+ struct hdlcd_drm_private *hdlcd = arg;
unsigned long irq_status;
irq_status = hdlcd_read(hdlcd, HDLCD_REG_INT_STATUS);
@@ -69,61 +69,32 @@ static irqreturn_t hdlcd_irq(int irq, void *arg)
return IRQ_HANDLED;
}
-static void hdlcd_irq_preinstall(struct drm_device *drm)
+static int hdlcd_irq_install(struct hdlcd_drm_private *hdlcd)
{
- struct hdlcd_drm_private *hdlcd = drm->dev_private;
+ int ret;
+
/* 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);
+ ret = request_irq(hdlcd->irq, hdlcd_irq, 0, "hdlcd", hdlcd);
if (ret)
return ret;
- hdlcd_irq_postinstall(drm);
+#ifdef CONFIG_DEBUG_FS
+ /* enable debug interrupts */
+ hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, HDLCD_DEBUG_INT_MASK);
+#endif
return 0;
}
-static void hdlcd_irq_uninstall(struct drm_device *drm)
+static void hdlcd_irq_uninstall(struct hdlcd_drm_private *hdlcd)
{
- 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);
+ hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
- free_irq(hdlcd->irq, drm);
+ free_irq(hdlcd->irq, hdlcd);
}
static int hdlcd_load(struct drm_device *drm, unsigned long flags)
@@ -183,7 +154,7 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
goto irq_fail;
hdlcd->irq = ret;
- ret = hdlcd_irq_install(drm, hdlcd->irq);
+ ret = hdlcd_irq_install(hdlcd);
if (ret < 0) {
DRM_ERROR("failed to install IRQ handler\n");
goto irq_fail;
@@ -314,6 +285,15 @@ static int hdlcd_drm_bind(struct device *dev)
goto err_vblank;
}
+ /*
+ * If EFI left us running, take over from simple framebuffer
+ * drivers. Read HDLCD_REG_COMMAND to see if we are enabled.
+ */
+ if (hdlcd_read(hdlcd, HDLCD_REG_COMMAND)) {
+ hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
+ drm_aperture_remove_framebuffers(false, &hdlcd_driver);
+ }
+
drm_mode_config_reset(drm);
drm_kms_helper_poll_init(drm);
@@ -335,7 +315,7 @@ err_pm_active:
err_unload:
of_node_put(hdlcd->crtc.port);
hdlcd->crtc.port = NULL;
- hdlcd_irq_uninstall(drm);
+ hdlcd_irq_uninstall(hdlcd);
of_reserved_mem_device_release(drm->dev);
err_free:
drm_mode_config_cleanup(drm);
@@ -357,7 +337,7 @@ static void hdlcd_drm_unbind(struct device *dev)
hdlcd->crtc.port = NULL;
pm_runtime_get_sync(dev);
drm_atomic_helper_shutdown(drm);
- hdlcd_irq_uninstall(drm);
+ hdlcd_irq_uninstall(hdlcd);
pm_runtime_put(dev);
if (pm_runtime_enabled(dev))
pm_runtime_disable(dev);