diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-04-26 10:19:38 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-07-03 11:24:44 -0400 |
| commit | e5d9ddfbb79667fb4b16db07c3282a2304fbf3ff (patch) | |
| tree | c598e1843a7a5ab2efc03405c44038cb4b05a62a /drivers/gpu/drm/armada | |
| parent | 4c834452aad01531db949414f94f817a86348d59 (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.c | 36 | ||||
| -rw-r--r-- | drivers/gpu/drm/armada/armada_crtc.h | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/armada/armada_drv.c | 68 |
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 | ||
| 352 | void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) | 352 | static 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 | ||
| 413 | static 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 */ |
| 414 | void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask) | 435 | void 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 | ||
| 1030 | int armada_drm_crtc_create(struct drm_device *dev, unsigned num, | 1053 | int 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 | ||
| 75 | int armada_drm_crtc_create(struct drm_device *, unsigned, struct resource *); | 75 | int armada_drm_crtc_create(struct drm_device *, unsigned, struct resource *, |
| 76 | int); | ||
| 76 | void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); | 77 | void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); |
| 77 | void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); | 78 | void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); |
| 78 | void armada_drm_crtc_irq(struct armada_crtc *, u32); | ||
| 79 | void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); | 79 | void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); |
| 80 | void armada_drm_crtc_enable_irq(struct armada_crtc *, u32); | 80 | void armada_drm_crtc_enable_irq(struct armada_crtc *, u32); |
| 81 | void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *); | 81 | void 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 | ||
| 262 | static 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 | |||
| 287 | static 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 | |||
| 300 | static 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 | |||
| 308 | static struct drm_ioctl_desc armada_ioctls[] = { | 261 | static 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 | }; |
