Commit e5d9ddfb authored by Russell King's avatar Russell King

drm/armada: move IRQ handling into CRTC

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 4c834452
...@@ -349,7 +349,7 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc, ...@@ -349,7 +349,7 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
return true; return true;
} }
void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
{ {
struct armada_vbl_event *e, *n; struct armada_vbl_event *e, *n;
void __iomem *base = dcrtc->base; void __iomem *base = dcrtc->base;
...@@ -410,6 +410,27 @@ void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) ...@@ -410,6 +410,27 @@ void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
} }
} }
static irqreturn_t armada_drm_irq(int irq, void *arg)
{
struct armada_crtc *dcrtc = arg;
u32 v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
/*
* This is rediculous - rather than writing bits to clear, we
* have to set the actual status register value. This is racy.
*/
writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
/* Mask out those interrupts we haven't enabled */
v = stat & dcrtc->irq_ena;
if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
armada_drm_crtc_irq(dcrtc, stat);
return IRQ_HANDLED;
}
return IRQ_NONE;
}
/* These are locked by dev->vbl_lock */ /* These are locked by dev->vbl_lock */
void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask) void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask)
{ {
...@@ -888,6 +909,8 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc) ...@@ -888,6 +909,8 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
if (!IS_ERR(dcrtc->clk)) if (!IS_ERR(dcrtc->clk))
clk_disable_unprepare(dcrtc->clk); clk_disable_unprepare(dcrtc->clk);
writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ENA);
kfree(dcrtc); kfree(dcrtc);
} }
...@@ -1028,7 +1051,7 @@ static int armada_drm_crtc_create_properties(struct drm_device *dev) ...@@ -1028,7 +1051,7 @@ static int armada_drm_crtc_create_properties(struct drm_device *dev)
} }
int armada_drm_crtc_create(struct drm_device *dev, unsigned num, int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
struct resource *res) struct resource *res, int irq)
{ {
struct armada_private *priv = dev->dev_private; struct armada_private *priv = dev->dev_private;
struct armada_crtc *dcrtc; struct armada_crtc *dcrtc;
...@@ -1074,6 +1097,15 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num, ...@@ -1074,6 +1097,15 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1); CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);
writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1); writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1);
writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN); writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN);
writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
ret = devm_request_irq(dev, irq, armada_drm_irq, 0, "armada_drm_crtc",
dcrtc);
if (ret < 0) {
kfree(dcrtc);
return ret;
}
if (priv->variant->crtc_init) { if (priv->variant->crtc_init) {
ret = priv->variant->crtc_init(dcrtc); ret = priv->variant->crtc_init(dcrtc);
......
...@@ -72,10 +72,10 @@ struct armada_crtc { ...@@ -72,10 +72,10 @@ struct armada_crtc {
}; };
#define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc)
int armada_drm_crtc_create(struct drm_device *, unsigned, struct resource *); int armada_drm_crtc_create(struct drm_device *, unsigned, struct resource *,
int);
void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
void armada_drm_crtc_irq(struct armada_crtc *, u32);
void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
void armada_drm_crtc_enable_irq(struct armada_crtc *, u32); void armada_drm_crtc_enable_irq(struct armada_crtc *, u32);
void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *); void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
......
...@@ -155,10 +155,16 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) ...@@ -155,10 +155,16 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
/* Create all LCD controllers */ /* Create all LCD controllers */
for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) { for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
int irq;
if (!res[n]) if (!res[n])
break; break;
ret = armada_drm_crtc_create(dev, n, res[n]); irq = platform_get_irq(dev->platformdev, n);
if (irq < 0)
goto err_kms;
ret = armada_drm_crtc_create(dev, n, res[n], irq);
if (ret) if (ret)
goto err_kms; goto err_kms;
} }
...@@ -173,22 +179,16 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) ...@@ -173,22 +179,16 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
if (ret) if (ret)
goto err_kms; goto err_kms;
ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
if (ret)
goto err_kms;
dev->vblank_disable_allowed = 1; dev->vblank_disable_allowed = 1;
ret = armada_fbdev_init(dev); ret = armada_fbdev_init(dev);
if (ret) if (ret)
goto err_irq; goto err_kms;
drm_kms_helper_poll_init(dev); drm_kms_helper_poll_init(dev);
return 0; return 0;
err_irq:
drm_irq_uninstall(dev);
err_kms: err_kms:
drm_mode_config_cleanup(dev); drm_mode_config_cleanup(dev);
drm_mm_takedown(&priv->linear); drm_mm_takedown(&priv->linear);
...@@ -203,7 +203,6 @@ static int armada_drm_unload(struct drm_device *dev) ...@@ -203,7 +203,6 @@ static int armada_drm_unload(struct drm_device *dev)
drm_kms_helper_poll_fini(dev); drm_kms_helper_poll_fini(dev);
armada_fbdev_fini(dev); armada_fbdev_fini(dev);
drm_irq_uninstall(dev);
drm_mode_config_cleanup(dev); drm_mode_config_cleanup(dev);
drm_mm_takedown(&priv->linear); drm_mm_takedown(&priv->linear);
flush_work(&priv->fb_unref_work); flush_work(&priv->fb_unref_work);
...@@ -259,52 +258,6 @@ static void armada_drm_disable_vblank(struct drm_device *dev, int crtc) ...@@ -259,52 +258,6 @@ static void armada_drm_disable_vblank(struct drm_device *dev, int crtc)
armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA); armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
} }
static irqreturn_t armada_drm_irq_handler(int irq, void *arg)
{
struct drm_device *dev = arg;
struct armada_private *priv = dev->dev_private;
struct armada_crtc *dcrtc = priv->dcrtc[0];
uint32_t v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
irqreturn_t handled = IRQ_NONE;
/*
* This is rediculous - rather than writing bits to clear, we
* have to set the actual status register value. This is racy.
*/
writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
/* Mask out those interrupts we haven't enabled */
v = stat & dcrtc->irq_ena;
if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
armada_drm_crtc_irq(dcrtc, stat);
handled = IRQ_HANDLED;
}
return handled;
}
static int armada_drm_irq_postinstall(struct drm_device *dev)
{
struct armada_private *priv = dev->dev_private;
struct armada_crtc *dcrtc = priv->dcrtc[0];
spin_lock_irq(&dev->vbl_lock);
writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);
spin_unlock_irq(&dev->vbl_lock);
return 0;
}
static void armada_drm_irq_uninstall(struct drm_device *dev)
{
struct armada_private *priv = dev->dev_private;
struct armada_crtc *dcrtc = priv->dcrtc[0];
writel(0, dcrtc->base + LCD_SPU_IRQ_ENA);
}
static struct drm_ioctl_desc armada_ioctls[] = { static struct drm_ioctl_desc armada_ioctls[] = {
DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl, DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,
DRM_UNLOCKED), DRM_UNLOCKED),
...@@ -340,9 +293,6 @@ static struct drm_driver armada_drm_driver = { ...@@ -340,9 +293,6 @@ static struct drm_driver armada_drm_driver = {
.get_vblank_counter = drm_vblank_count, .get_vblank_counter = drm_vblank_count,
.enable_vblank = armada_drm_enable_vblank, .enable_vblank = armada_drm_enable_vblank,
.disable_vblank = armada_drm_disable_vblank, .disable_vblank = armada_drm_disable_vblank,
.irq_handler = armada_drm_irq_handler,
.irq_postinstall = armada_drm_irq_postinstall,
.irq_uninstall = armada_drm_irq_uninstall,
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
.debugfs_init = armada_drm_debugfs_init, .debugfs_init = armada_drm_debugfs_init,
.debugfs_cleanup = armada_drm_debugfs_cleanup, .debugfs_cleanup = armada_drm_debugfs_cleanup,
...@@ -362,7 +312,7 @@ static struct drm_driver armada_drm_driver = { ...@@ -362,7 +312,7 @@ static struct drm_driver armada_drm_driver = {
.desc = "Armada SoC DRM", .desc = "Armada SoC DRM",
.date = "20120730", .date = "20120730",
.driver_features = DRIVER_GEM | DRIVER_MODESET | .driver_features = DRIVER_GEM | DRIVER_MODESET |
DRIVER_HAVE_IRQ | DRIVER_PRIME, DRIVER_PRIME,
.ioctls = armada_ioctls, .ioctls = armada_ioctls,
.fops = &armada_drm_fops, .fops = &armada_drm_fops,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment