aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/armada
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2014-04-26 10:19:38 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2014-07-03 11:24:44 -0400
commite5d9ddfbb79667fb4b16db07c3282a2304fbf3ff (patch)
treec598e1843a7a5ab2efc03405c44038cb4b05a62a /drivers/gpu/drm/armada
parent4c834452aad01531db949414f94f817a86348d59 (diff)
drm/armada: move IRQ handling into CRTC
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/gpu/drm/armada')
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.c36
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.h4
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c68
3 files changed, 45 insertions, 63 deletions
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 81c34f949dfc..9341a94cc906 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -349,7 +349,7 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
349 return true; 349 return true;
350} 350}
351 351
352void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) 352static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
353{ 353{
354 struct armada_vbl_event *e, *n; 354 struct armada_vbl_event *e, *n;
355 void __iomem *base = dcrtc->base; 355 void __iomem *base = dcrtc->base;
@@ -410,6 +410,27 @@ void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
410 } 410 }
411} 411}
412 412
413static irqreturn_t armada_drm_irq(int irq, void *arg)
414{
415 struct armada_crtc *dcrtc = arg;
416 u32 v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
417
418 /*
419 * This is rediculous - rather than writing bits to clear, we
420 * have to set the actual status register value. This is racy.
421 */
422 writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
423
424 /* Mask out those interrupts we haven't enabled */
425 v = stat & dcrtc->irq_ena;
426
427 if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
428 armada_drm_crtc_irq(dcrtc, stat);
429 return IRQ_HANDLED;
430 }
431 return IRQ_NONE;
432}
433
413/* These are locked by dev->vbl_lock */ 434/* These are locked by dev->vbl_lock */
414void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask) 435void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask)
415{ 436{
@@ -888,6 +909,8 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
888 if (!IS_ERR(dcrtc->clk)) 909 if (!IS_ERR(dcrtc->clk))
889 clk_disable_unprepare(dcrtc->clk); 910 clk_disable_unprepare(dcrtc->clk);
890 911
912 writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ENA);
913
891 kfree(dcrtc); 914 kfree(dcrtc);
892} 915}
893 916
@@ -1028,7 +1051,7 @@ static int armada_drm_crtc_create_properties(struct drm_device *dev)
1028} 1051}
1029 1052
1030int armada_drm_crtc_create(struct drm_device *dev, unsigned num, 1053int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
1031 struct resource *res) 1054 struct resource *res, int irq)
1032{ 1055{
1033 struct armada_private *priv = dev->dev_private; 1056 struct armada_private *priv = dev->dev_private;
1034 struct armada_crtc *dcrtc; 1057 struct armada_crtc *dcrtc;
@@ -1074,6 +1097,15 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
1074 CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1); 1097 CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);
1075 writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1); 1098 writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1);
1076 writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN); 1099 writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN);
1100 writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
1101 writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
1102
1103 ret = devm_request_irq(dev, irq, armada_drm_irq, 0, "armada_drm_crtc",
1104 dcrtc);
1105 if (ret < 0) {
1106 kfree(dcrtc);
1107 return ret;
1108 }
1077 1109
1078 if (priv->variant->crtc_init) { 1110 if (priv->variant->crtc_init) {
1079 ret = priv->variant->crtc_init(dcrtc); 1111 ret = priv->variant->crtc_init(dcrtc);
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
index 9c10a07e7492..0e952b271212 100644
--- a/drivers/gpu/drm/armada/armada_crtc.h
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -72,10 +72,10 @@ struct armada_crtc {
72}; 72};
73#define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) 73#define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc)
74 74
75int armada_drm_crtc_create(struct drm_device *, unsigned, struct resource *); 75int armada_drm_crtc_create(struct drm_device *, unsigned, struct resource *,
76 int);
76void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); 77void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
77void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); 78void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
78void armada_drm_crtc_irq(struct armada_crtc *, u32);
79void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); 79void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
80void armada_drm_crtc_enable_irq(struct armada_crtc *, u32); 80void armada_drm_crtc_enable_irq(struct armada_crtc *, u32);
81void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *); 81void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 8ab3cd1a8cdb..58884d807e6c 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -155,10 +155,16 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
155 155
156 /* Create all LCD controllers */ 156 /* Create all LCD controllers */
157 for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) { 157 for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
158 int irq;
159
158 if (!res[n]) 160 if (!res[n])
159 break; 161 break;
160 162
161 ret = armada_drm_crtc_create(dev, n, res[n]); 163 irq = platform_get_irq(dev->platformdev, n);
164 if (irq < 0)
165 goto err_kms;
166
167 ret = armada_drm_crtc_create(dev, n, res[n], irq);
162 if (ret) 168 if (ret)
163 goto err_kms; 169 goto err_kms;
164 } 170 }
@@ -173,22 +179,16 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
173 if (ret) 179 if (ret)
174 goto err_kms; 180 goto err_kms;
175 181
176 ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
177 if (ret)
178 goto err_kms;
179
180 dev->vblank_disable_allowed = 1; 182 dev->vblank_disable_allowed = 1;
181 183
182 ret = armada_fbdev_init(dev); 184 ret = armada_fbdev_init(dev);
183 if (ret) 185 if (ret)
184 goto err_irq; 186 goto err_kms;
185 187
186 drm_kms_helper_poll_init(dev); 188 drm_kms_helper_poll_init(dev);
187 189
188 return 0; 190 return 0;
189 191
190 err_irq:
191 drm_irq_uninstall(dev);
192 err_kms: 192 err_kms:
193 drm_mode_config_cleanup(dev); 193 drm_mode_config_cleanup(dev);
194 drm_mm_takedown(&priv->linear); 194 drm_mm_takedown(&priv->linear);
@@ -203,7 +203,6 @@ static int armada_drm_unload(struct drm_device *dev)
203 203
204 drm_kms_helper_poll_fini(dev); 204 drm_kms_helper_poll_fini(dev);
205 armada_fbdev_fini(dev); 205 armada_fbdev_fini(dev);
206 drm_irq_uninstall(dev);
207 drm_mode_config_cleanup(dev); 206 drm_mode_config_cleanup(dev);
208 drm_mm_takedown(&priv->linear); 207 drm_mm_takedown(&priv->linear);
209 flush_work(&priv->fb_unref_work); 208 flush_work(&priv->fb_unref_work);
@@ -259,52 +258,6 @@ static void armada_drm_disable_vblank(struct drm_device *dev, int crtc)
259 armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA); 258 armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
260} 259}
261 260
262static irqreturn_t armada_drm_irq_handler(int irq, void *arg)
263{
264 struct drm_device *dev = arg;
265 struct armada_private *priv = dev->dev_private;
266 struct armada_crtc *dcrtc = priv->dcrtc[0];
267 uint32_t v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
268 irqreturn_t handled = IRQ_NONE;
269
270 /*
271 * This is rediculous - rather than writing bits to clear, we
272 * have to set the actual status register value. This is racy.
273 */
274 writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
275
276 /* Mask out those interrupts we haven't enabled */
277 v = stat & dcrtc->irq_ena;
278
279 if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
280 armada_drm_crtc_irq(dcrtc, stat);
281 handled = IRQ_HANDLED;
282 }
283
284 return handled;
285}
286
287static int armada_drm_irq_postinstall(struct drm_device *dev)
288{
289 struct armada_private *priv = dev->dev_private;
290 struct armada_crtc *dcrtc = priv->dcrtc[0];
291
292 spin_lock_irq(&dev->vbl_lock);
293 writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
294 writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);
295 spin_unlock_irq(&dev->vbl_lock);
296
297 return 0;
298}
299
300static void armada_drm_irq_uninstall(struct drm_device *dev)
301{
302 struct armada_private *priv = dev->dev_private;
303 struct armada_crtc *dcrtc = priv->dcrtc[0];
304
305 writel(0, dcrtc->base + LCD_SPU_IRQ_ENA);
306}
307
308static struct drm_ioctl_desc armada_ioctls[] = { 261static struct drm_ioctl_desc armada_ioctls[] = {
309 DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl, 262 DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,
310 DRM_UNLOCKED), 263 DRM_UNLOCKED),
@@ -340,9 +293,6 @@ static struct drm_driver armada_drm_driver = {
340 .get_vblank_counter = drm_vblank_count, 293 .get_vblank_counter = drm_vblank_count,
341 .enable_vblank = armada_drm_enable_vblank, 294 .enable_vblank = armada_drm_enable_vblank,
342 .disable_vblank = armada_drm_disable_vblank, 295 .disable_vblank = armada_drm_disable_vblank,
343 .irq_handler = armada_drm_irq_handler,
344 .irq_postinstall = armada_drm_irq_postinstall,
345 .irq_uninstall = armada_drm_irq_uninstall,
346#ifdef CONFIG_DEBUG_FS 296#ifdef CONFIG_DEBUG_FS
347 .debugfs_init = armada_drm_debugfs_init, 297 .debugfs_init = armada_drm_debugfs_init,
348 .debugfs_cleanup = armada_drm_debugfs_cleanup, 298 .debugfs_cleanup = armada_drm_debugfs_cleanup,
@@ -362,7 +312,7 @@ static struct drm_driver armada_drm_driver = {
362 .desc = "Armada SoC DRM", 312 .desc = "Armada SoC DRM",
363 .date = "20120730", 313 .date = "20120730",
364 .driver_features = DRIVER_GEM | DRIVER_MODESET | 314 .driver_features = DRIVER_GEM | DRIVER_MODESET |
365 DRIVER_HAVE_IRQ | DRIVER_PRIME, 315 DRIVER_PRIME,
366 .ioctls = armada_ioctls, 316 .ioctls = armada_ioctls,
367 .fops = &armada_drm_fops, 317 .fops = &armada_drm_fops,
368}; 318};