drm/armada: move IRQ handling into CRTC
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Esse commit está contido em:
@@ -349,7 +349,7 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
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;
|
||||
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 */
|
||||
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))
|
||||
clk_disable_unprepare(dcrtc->clk);
|
||||
|
||||
writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ENA);
|
||||
|
||||
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,
|
||||
struct resource *res)
|
||||
struct resource *res, int irq)
|
||||
{
|
||||
struct armada_private *priv = dev->dev_private;
|
||||
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);
|
||||
writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1);
|
||||
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) {
|
||||
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)
|
||||
|
||||
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_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_enable_irq(struct armada_crtc *, u32);
|
||||
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 */
|
||||
for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
|
||||
int irq;
|
||||
|
||||
if (!res[n])
|
||||
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)
|
||||
goto err_kms;
|
||||
}
|
||||
@@ -173,22 +179,16 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
|
||||
if (ret)
|
||||
goto err_kms;
|
||||
|
||||
ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
|
||||
if (ret)
|
||||
goto err_kms;
|
||||
|
||||
dev->vblank_disable_allowed = 1;
|
||||
|
||||
ret = armada_fbdev_init(dev);
|
||||
if (ret)
|
||||
goto err_irq;
|
||||
goto err_kms;
|
||||
|
||||
drm_kms_helper_poll_init(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_irq:
|
||||
drm_irq_uninstall(dev);
|
||||
err_kms:
|
||||
drm_mode_config_cleanup(dev);
|
||||
drm_mm_takedown(&priv->linear);
|
||||
@@ -203,7 +203,6 @@ static int armada_drm_unload(struct drm_device *dev)
|
||||
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
armada_fbdev_fini(dev);
|
||||
drm_irq_uninstall(dev);
|
||||
drm_mode_config_cleanup(dev);
|
||||
drm_mm_takedown(&priv->linear);
|
||||
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);
|
||||
}
|
||||
|
||||
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[] = {
|
||||
DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,
|
||||
DRM_UNLOCKED),
|
||||
@@ -340,9 +293,6 @@ static struct drm_driver armada_drm_driver = {
|
||||
.get_vblank_counter = drm_vblank_count,
|
||||
.enable_vblank = armada_drm_enable_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
|
||||
.debugfs_init = armada_drm_debugfs_init,
|
||||
.debugfs_cleanup = armada_drm_debugfs_cleanup,
|
||||
@@ -362,7 +312,7 @@ static struct drm_driver armada_drm_driver = {
|
||||
.desc = "Armada SoC DRM",
|
||||
.date = "20120730",
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET |
|
||||
DRIVER_HAVE_IRQ | DRIVER_PRIME,
|
||||
DRIVER_PRIME,
|
||||
.ioctls = armada_ioctls,
|
||||
.fops = &armada_drm_fops,
|
||||
};
|
||||
|
Referência em uma nova issue
Block a user