aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/armada/armada_510.c23
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.c65
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.h7
-rw-r--r--drivers/gpu/drm/armada/armada_drm.h13
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c77
5 files changed, 79 insertions, 106 deletions
diff --git a/drivers/gpu/drm/armada/armada_510.c b/drivers/gpu/drm/armada/armada_510.c
index 59948eff6095..1bcf1a8c1915 100644
--- a/drivers/gpu/drm/armada/armada_510.c
+++ b/drivers/gpu/drm/armada/armada_510.c
@@ -15,20 +15,19 @@
15#include "armada_drm.h" 15#include "armada_drm.h"
16#include "armada_hw.h" 16#include "armada_hw.h"
17 17
18static int armada510_init(struct armada_private *priv, struct device *dev) 18static int armada510_crtc_init(struct armada_crtc *dcrtc, struct device *dev)
19{ 19{
20 priv->extclk[0] = devm_clk_get(dev, "ext_ref_clk_1"); 20 struct clk *clk;
21 21
22 if (IS_ERR(priv->extclk[0]) && PTR_ERR(priv->extclk[0]) == -ENOENT) 22 clk = devm_clk_get(dev, "ext_ref_clk_1");
23 priv->extclk[0] = ERR_PTR(-EPROBE_DEFER); 23 if (IS_ERR(clk))
24 return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER : PTR_ERR(clk);
24 25
25 return PTR_RET(priv->extclk[0]); 26 dcrtc->extclk[0] = clk;
26}
27 27
28static int armada510_crtc_init(struct armada_crtc *dcrtc)
29{
30 /* Lower the watermark so to eliminate jitter at higher bandwidths */ 28 /* Lower the watermark so to eliminate jitter at higher bandwidths */
31 armada_updatel(0x20, (1 << 11) | 0xff, dcrtc->base + LCD_CFG_RDREG4F); 29 armada_updatel(0x20, (1 << 11) | 0xff, dcrtc->base + LCD_CFG_RDREG4F);
30
32 return 0; 31 return 0;
33} 32}
34 33
@@ -45,8 +44,7 @@ static int armada510_crtc_init(struct armada_crtc *dcrtc)
45static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc, 44static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
46 const struct drm_display_mode *mode, uint32_t *sclk) 45 const struct drm_display_mode *mode, uint32_t *sclk)
47{ 46{
48 struct armada_private *priv = dcrtc->crtc.dev->dev_private; 47 struct clk *clk = dcrtc->extclk[0];
49 struct clk *clk = priv->extclk[0];
50 int ret; 48 int ret;
51 49
52 if (dcrtc->num == 1) 50 if (dcrtc->num == 1)
@@ -81,7 +79,6 @@ static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
81const struct armada_variant armada510_ops = { 79const struct armada_variant armada510_ops = {
82 .has_spu_adv_reg = true, 80 .has_spu_adv_reg = true,
83 .spu_adv_reg = ADV_HWC32ENABLE | ADV_HWC32ARGB | ADV_HWC32BLEND, 81 .spu_adv_reg = ADV_HWC32ENABLE | ADV_HWC32ARGB | ADV_HWC32BLEND,
84 .init = armada510_init, 82 .init = armada510_crtc_init,
85 .crtc_init = armada510_crtc_init, 83 .compute_clock = armada510_crtc_compute_clock,
86 .crtc_compute_clock = armada510_crtc_compute_clock,
87}; 84};
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 81c34f949dfc..afa497489000 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -332,24 +332,23 @@ static void armada_drm_crtc_commit(struct drm_crtc *crtc)
332static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc, 332static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
333 const struct drm_display_mode *mode, struct drm_display_mode *adj) 333 const struct drm_display_mode *mode, struct drm_display_mode *adj)
334{ 334{
335 struct armada_private *priv = crtc->dev->dev_private;
336 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); 335 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
337 int ret; 336 int ret;
338 337
339 /* We can't do interlaced modes if we don't have the SPU_ADV_REG */ 338 /* We can't do interlaced modes if we don't have the SPU_ADV_REG */
340 if (!priv->variant->has_spu_adv_reg && 339 if (!dcrtc->variant->has_spu_adv_reg &&
341 adj->flags & DRM_MODE_FLAG_INTERLACE) 340 adj->flags & DRM_MODE_FLAG_INTERLACE)
342 return false; 341 return false;
343 342
344 /* Check whether the display mode is possible */ 343 /* Check whether the display mode is possible */
345 ret = priv->variant->crtc_compute_clock(dcrtc, adj, NULL); 344 ret = dcrtc->variant->compute_clock(dcrtc, adj, NULL);
346 if (ret) 345 if (ret)
347 return false; 346 return false;
348 347
349 return true; 348 return true;
350} 349}
351 350
352void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) 351static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
353{ 352{
354 struct armada_vbl_event *e, *n; 353 struct armada_vbl_event *e, *n;
355 void __iomem *base = dcrtc->base; 354 void __iomem *base = dcrtc->base;
@@ -410,6 +409,27 @@ void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
410 } 409 }
411} 410}
412 411
412static irqreturn_t armada_drm_irq(int irq, void *arg)
413{
414 struct armada_crtc *dcrtc = arg;
415 u32 v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
416
417 /*
418 * This is rediculous - rather than writing bits to clear, we
419 * have to set the actual status register value. This is racy.
420 */
421 writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
422
423 /* Mask out those interrupts we haven't enabled */
424 v = stat & dcrtc->irq_ena;
425
426 if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
427 armada_drm_crtc_irq(dcrtc, stat);
428 return IRQ_HANDLED;
429 }
430 return IRQ_NONE;
431}
432
413/* These are locked by dev->vbl_lock */ 433/* These are locked by dev->vbl_lock */
414void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask) 434void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask)
415{ 435{
@@ -470,7 +490,6 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
470 struct drm_display_mode *mode, struct drm_display_mode *adj, 490 struct drm_display_mode *mode, struct drm_display_mode *adj,
471 int x, int y, struct drm_framebuffer *old_fb) 491 int x, int y, struct drm_framebuffer *old_fb)
472{ 492{
473 struct armada_private *priv = crtc->dev->dev_private;
474 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); 493 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
475 struct armada_regs regs[17]; 494 struct armada_regs regs[17];
476 uint32_t lm, rm, tm, bm, val, sclk; 495 uint32_t lm, rm, tm, bm, val, sclk;
@@ -515,7 +534,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
515 } 534 }
516 535
517 /* Now compute the divider for real */ 536 /* Now compute the divider for real */
518 priv->variant->crtc_compute_clock(dcrtc, adj, &sclk); 537 dcrtc->variant->compute_clock(dcrtc, adj, &sclk);
519 538
520 /* Ensure graphic fifo is enabled */ 539 /* Ensure graphic fifo is enabled */
521 armada_reg_queue_mod(regs, i, 0, CFG_PDWN64x66, LCD_SPU_SRAM_PARA1); 540 armada_reg_queue_mod(regs, i, 0, CFG_PDWN64x66, LCD_SPU_SRAM_PARA1);
@@ -537,7 +556,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
537 dcrtc->v[1].spu_v_porch = tm << 16 | bm; 556 dcrtc->v[1].spu_v_porch = tm << 16 | bm;
538 val = adj->crtc_hsync_start; 557 val = adj->crtc_hsync_start;
539 dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN | 558 dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
540 priv->variant->spu_adv_reg; 559 dcrtc->variant->spu_adv_reg;
541 560
542 if (interlaced) { 561 if (interlaced) {
543 /* Odd interlaced frame */ 562 /* Odd interlaced frame */
@@ -546,7 +565,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
546 dcrtc->v[0].spu_v_porch = dcrtc->v[1].spu_v_porch + 1; 565 dcrtc->v[0].spu_v_porch = dcrtc->v[1].spu_v_porch + 1;
547 val = adj->crtc_hsync_start - adj->crtc_htotal / 2; 566 val = adj->crtc_hsync_start - adj->crtc_htotal / 2;
548 dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN | 567 dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
549 priv->variant->spu_adv_reg; 568 dcrtc->variant->spu_adv_reg;
550 } else { 569 } else {
551 dcrtc->v[0] = dcrtc->v[1]; 570 dcrtc->v[0] = dcrtc->v[1];
552 } 571 }
@@ -561,7 +580,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
561 armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total, 580 armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total,
562 LCD_SPUT_V_H_TOTAL); 581 LCD_SPUT_V_H_TOTAL);
563 582
564 if (priv->variant->has_spu_adv_reg) { 583 if (dcrtc->variant->has_spu_adv_reg) {
565 armada_reg_queue_mod(regs, i, dcrtc->v[0].spu_adv_reg, 584 armada_reg_queue_mod(regs, i, dcrtc->v[0].spu_adv_reg,
566 ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF | 585 ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF |
567 ADV_VSYNCOFFEN, LCD_SPU_ADV_REG); 586 ADV_VSYNCOFFEN, LCD_SPU_ADV_REG);
@@ -805,12 +824,11 @@ static int armada_drm_crtc_cursor_set(struct drm_crtc *crtc,
805{ 824{
806 struct drm_device *dev = crtc->dev; 825 struct drm_device *dev = crtc->dev;
807 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); 826 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
808 struct armada_private *priv = crtc->dev->dev_private;
809 struct armada_gem_object *obj = NULL; 827 struct armada_gem_object *obj = NULL;
810 int ret; 828 int ret;
811 829
812 /* If no cursor support, replicate drm's return value */ 830 /* If no cursor support, replicate drm's return value */
813 if (!priv->variant->has_spu_adv_reg) 831 if (!dcrtc->variant->has_spu_adv_reg)
814 return -ENXIO; 832 return -ENXIO;
815 833
816 if (handle && w > 0 && h > 0) { 834 if (handle && w > 0 && h > 0) {
@@ -858,11 +876,10 @@ static int armada_drm_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
858{ 876{
859 struct drm_device *dev = crtc->dev; 877 struct drm_device *dev = crtc->dev;
860 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); 878 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
861 struct armada_private *priv = crtc->dev->dev_private;
862 int ret; 879 int ret;
863 880
864 /* If no cursor support, replicate drm's return value */ 881 /* If no cursor support, replicate drm's return value */
865 if (!priv->variant->has_spu_adv_reg) 882 if (!dcrtc->variant->has_spu_adv_reg)
866 return -EFAULT; 883 return -EFAULT;
867 884
868 mutex_lock(&dev->struct_mutex); 885 mutex_lock(&dev->struct_mutex);
@@ -888,6 +905,8 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
888 if (!IS_ERR(dcrtc->clk)) 905 if (!IS_ERR(dcrtc->clk))
889 clk_disable_unprepare(dcrtc->clk); 906 clk_disable_unprepare(dcrtc->clk);
890 907
908 writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ENA);
909
891 kfree(dcrtc); 910 kfree(dcrtc);
892} 911}
893 912
@@ -1027,8 +1046,8 @@ static int armada_drm_crtc_create_properties(struct drm_device *dev)
1027 return 0; 1046 return 0;
1028} 1047}
1029 1048
1030int armada_drm_crtc_create(struct drm_device *dev, unsigned num, 1049int armada_drm_crtc_create(struct drm_device *dev, struct resource *res,
1031 struct resource *res) 1050 int irq, const struct armada_variant *variant)
1032{ 1051{
1033 struct armada_private *priv = dev->dev_private; 1052 struct armada_private *priv = dev->dev_private;
1034 struct armada_crtc *dcrtc; 1053 struct armada_crtc *dcrtc;
@@ -1051,8 +1070,9 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
1051 return -ENOMEM; 1070 return -ENOMEM;
1052 } 1071 }
1053 1072
1073 dcrtc->variant = variant;
1054 dcrtc->base = base; 1074 dcrtc->base = base;
1055 dcrtc->num = num; 1075 dcrtc->num = dev->mode_config.num_crtc;
1056 dcrtc->clk = ERR_PTR(-EINVAL); 1076 dcrtc->clk = ERR_PTR(-EINVAL);
1057 dcrtc->csc_yuv_mode = CSC_AUTO; 1077 dcrtc->csc_yuv_mode = CSC_AUTO;
1058 dcrtc->csc_rgb_mode = CSC_AUTO; 1078 dcrtc->csc_rgb_mode = CSC_AUTO;
@@ -1074,9 +1094,18 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
1074 CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1); 1094 CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);
1075 writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1); 1095 writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1);
1076 writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN); 1096 writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN);
1097 writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
1098 writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
1099
1100 ret = devm_request_irq(dev, irq, armada_drm_irq, 0, "armada_drm_crtc",
1101 dcrtc);
1102 if (ret < 0) {
1103 kfree(dcrtc);
1104 return ret;
1105 }
1077 1106
1078 if (priv->variant->crtc_init) { 1107 if (dcrtc->variant->init) {
1079 ret = priv->variant->crtc_init(dcrtc); 1108 ret = dcrtc->variant->init(dcrtc, dev->dev);
1080 if (ret) { 1109 if (ret) {
1081 kfree(dcrtc); 1110 kfree(dcrtc);
1082 return ret; 1111 return ret;
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
index 9c10a07e7492..73efcfcdf814 100644
--- a/drivers/gpu/drm/armada/armada_crtc.h
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -32,12 +32,15 @@ struct armada_regs {
32 armada_reg_queue_mod(_r, _i, 0, 0, ~0) 32 armada_reg_queue_mod(_r, _i, 0, 0, ~0)
33 33
34struct armada_frame_work; 34struct armada_frame_work;
35struct armada_variant;
35 36
36struct armada_crtc { 37struct armada_crtc {
37 struct drm_crtc crtc; 38 struct drm_crtc crtc;
39 const struct armada_variant *variant;
38 unsigned num; 40 unsigned num;
39 void __iomem *base; 41 void __iomem *base;
40 struct clk *clk; 42 struct clk *clk;
43 struct clk *extclk[2];
41 struct { 44 struct {
42 uint32_t spu_v_h_total; 45 uint32_t spu_v_h_total;
43 uint32_t spu_v_porch; 46 uint32_t spu_v_porch;
@@ -72,10 +75,10 @@ struct armada_crtc {
72}; 75};
73#define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) 76#define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc)
74 77
75int armada_drm_crtc_create(struct drm_device *, unsigned, struct resource *); 78int armada_drm_crtc_create(struct drm_device *, struct resource *, int,
79 const struct armada_variant *);
76void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); 80void 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); 81void 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); 82void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
80void armada_drm_crtc_enable_irq(struct armada_crtc *, u32); 83void armada_drm_crtc_enable_irq(struct armada_crtc *, u32);
81void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *); 84void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index a72cae03b99b..ea63c6c7c66f 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -59,26 +59,23 @@ void armada_drm_vbl_event_remove_unlocked(struct armada_crtc *,
59struct armada_private; 59struct armada_private;
60 60
61struct armada_variant { 61struct armada_variant {
62 bool has_spu_adv_reg; 62 bool has_spu_adv_reg;
63 uint32_t spu_adv_reg; 63 uint32_t spu_adv_reg;
64 int (*init)(struct armada_private *, struct device *); 64 int (*init)(struct armada_crtc *, struct device *);
65 int (*crtc_init)(struct armada_crtc *); 65 int (*compute_clock)(struct armada_crtc *,
66 int (*crtc_compute_clock)(struct armada_crtc *, 66 const struct drm_display_mode *,
67 const struct drm_display_mode *, 67 uint32_t *);
68 uint32_t *);
69}; 68};
70 69
71/* Variant ops */ 70/* Variant ops */
72extern const struct armada_variant armada510_ops; 71extern const struct armada_variant armada510_ops;
73 72
74struct armada_private { 73struct armada_private {
75 const struct armada_variant *variant;
76 struct work_struct fb_unref_work; 74 struct work_struct fb_unref_work;
77 DECLARE_KFIFO(fb_unref, struct drm_framebuffer *, 8); 75 DECLARE_KFIFO(fb_unref, struct drm_framebuffer *, 8);
78 struct drm_fb_helper *fbdev; 76 struct drm_fb_helper *fbdev;
79 struct armada_crtc *dcrtc[2]; 77 struct armada_crtc *dcrtc[2];
80 struct drm_mm linear; 78 struct drm_mm linear;
81 struct clk *extclk[2];
82 struct drm_property *csc_yuv_prop; 79 struct drm_property *csc_yuv_prop;
83 struct drm_property *csc_rgb_prop; 80 struct drm_property *csc_rgb_prop;
84 struct drm_property *colorkey_prop; 81 struct drm_property *colorkey_prop;
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 8ab3cd1a8cdb..3995be3c686b 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -85,6 +85,7 @@ void armada_drm_queue_unref_work(struct drm_device *dev,
85static int armada_drm_load(struct drm_device *dev, unsigned long flags) 85static int armada_drm_load(struct drm_device *dev, unsigned long flags)
86{ 86{
87 const struct platform_device_id *id; 87 const struct platform_device_id *id;
88 const struct armada_variant *variant;
88 struct armada_private *priv; 89 struct armada_private *priv;
89 struct resource *res[ARRAY_SIZE(priv->dcrtc)]; 90 struct resource *res[ARRAY_SIZE(priv->dcrtc)];
90 struct resource *mem = NULL; 91 struct resource *mem = NULL;
@@ -128,11 +129,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
128 if (!id) 129 if (!id)
129 return -ENXIO; 130 return -ENXIO;
130 131
131 priv->variant = (struct armada_variant *)id->driver_data; 132 variant = (const struct armada_variant *)id->driver_data;
132
133 ret = priv->variant->init(priv, dev->dev);
134 if (ret)
135 return ret;
136 133
137 INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work); 134 INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
138 INIT_KFIFO(priv->fb_unref); 135 INIT_KFIFO(priv->fb_unref);
@@ -155,10 +152,16 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
155 152
156 /* Create all LCD controllers */ 153 /* Create all LCD controllers */
157 for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) { 154 for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
155 int irq;
156
158 if (!res[n]) 157 if (!res[n])
159 break; 158 break;
160 159
161 ret = armada_drm_crtc_create(dev, n, res[n]); 160 irq = platform_get_irq(dev->platformdev, n);
161 if (irq < 0)
162 goto err_kms;
163
164 ret = armada_drm_crtc_create(dev, res[n], irq, variant);
162 if (ret) 165 if (ret)
163 goto err_kms; 166 goto err_kms;
164 } 167 }
@@ -169,11 +172,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
169 goto err_kms; 172 goto err_kms;
170#endif 173#endif
171 174
172 ret = drm_vblank_init(dev, n); 175 ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
173 if (ret)
174 goto err_kms;
175
176 ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
177 if (ret) 176 if (ret)
178 goto err_kms; 177 goto err_kms;
179 178
@@ -181,14 +180,12 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
181 180
182 ret = armada_fbdev_init(dev); 181 ret = armada_fbdev_init(dev);
183 if (ret) 182 if (ret)
184 goto err_irq; 183 goto err_kms;
185 184
186 drm_kms_helper_poll_init(dev); 185 drm_kms_helper_poll_init(dev);
187 186
188 return 0; 187 return 0;
189 188
190 err_irq:
191 drm_irq_uninstall(dev);
192 err_kms: 189 err_kms:
193 drm_mode_config_cleanup(dev); 190 drm_mode_config_cleanup(dev);
194 drm_mm_takedown(&priv->linear); 191 drm_mm_takedown(&priv->linear);
@@ -203,7 +200,6 @@ static int armada_drm_unload(struct drm_device *dev)
203 200
204 drm_kms_helper_poll_fini(dev); 201 drm_kms_helper_poll_fini(dev);
205 armada_fbdev_fini(dev); 202 armada_fbdev_fini(dev);
206 drm_irq_uninstall(dev);
207 drm_mode_config_cleanup(dev); 203 drm_mode_config_cleanup(dev);
208 drm_mm_takedown(&priv->linear); 204 drm_mm_takedown(&priv->linear);
209 flush_work(&priv->fb_unref_work); 205 flush_work(&priv->fb_unref_work);
@@ -259,52 +255,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); 255 armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
260} 256}
261 257
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[] = { 258static struct drm_ioctl_desc armada_ioctls[] = {
309 DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl, 259 DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,
310 DRM_UNLOCKED), 260 DRM_UNLOCKED),
@@ -340,9 +290,6 @@ static struct drm_driver armada_drm_driver = {
340 .get_vblank_counter = drm_vblank_count, 290 .get_vblank_counter = drm_vblank_count,
341 .enable_vblank = armada_drm_enable_vblank, 291 .enable_vblank = armada_drm_enable_vblank,
342 .disable_vblank = armada_drm_disable_vblank, 292 .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 293#ifdef CONFIG_DEBUG_FS
347 .debugfs_init = armada_drm_debugfs_init, 294 .debugfs_init = armada_drm_debugfs_init,
348 .debugfs_cleanup = armada_drm_debugfs_cleanup, 295 .debugfs_cleanup = armada_drm_debugfs_cleanup,
@@ -362,7 +309,7 @@ static struct drm_driver armada_drm_driver = {
362 .desc = "Armada SoC DRM", 309 .desc = "Armada SoC DRM",
363 .date = "20120730", 310 .date = "20120730",
364 .driver_features = DRIVER_GEM | DRIVER_MODESET | 311 .driver_features = DRIVER_GEM | DRIVER_MODESET |
365 DRIVER_HAVE_IRQ | DRIVER_PRIME, 312 DRIVER_PRIME,
366 .ioctls = armada_ioctls, 313 .ioctls = armada_ioctls,
367 .fops = &armada_drm_fops, 314 .fops = &armada_drm_fops,
368}; 315};