drm/armada: move IRQ handling into CRTC
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
4c834452aa
commit
e5d9ddfbb7
3 changed files with 45 additions and 63 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
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 {
|
||||||
};
|
};
|
||||||
#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)
|
||||||
|
|
||||||
/* 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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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 = {
|
||||||
.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 = {
|
||||||
.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,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue