aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Yao <mark.yao@rock-chips.com>2015-12-14 19:36:55 -0500
committerMark Yao <mark.yao@rock-chips.com>2015-12-27 20:01:28 -0500
commitdbb3d94444eaa56cb1a6c9790f2fbe14b14310aa (patch)
treed1867ca93dc621803c3f344fb0ba753e23a1c095
parent0cf33fe33d4e9fdbbdd0b93101b078b03d0ba9b5 (diff)
drm/rockchip: vop: move interrupt registers into vop_data
Move interrupt registers into vop_data, so it can use at multi-vop driver Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c81
1 files changed, 69 insertions, 12 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index dcb1396a4133..7674bdcad39d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -48,6 +48,8 @@
48 48
49#define REG_SET(x, base, reg, v, mode) \ 49#define REG_SET(x, base, reg, v, mode) \
50 __REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v) 50 __REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v)
51#define REG_SET_MASK(x, base, reg, v, mode) \
52 __REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v)
51 53
52#define VOP_WIN_SET(x, win, name, v) \ 54#define VOP_WIN_SET(x, win, name, v) \
53 REG_SET(x, win->base, win->phy->name, v, RELAXED) 55 REG_SET(x, win->base, win->phy->name, v, RELAXED)
@@ -56,6 +58,23 @@
56#define VOP_CTRL_SET(x, name, v) \ 58#define VOP_CTRL_SET(x, name, v) \
57 REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL) 59 REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL)
58 60
61#define VOP_INTR_GET(vop, name) \
62 vop_read_reg(vop, 0, &vop->data->ctrl->name)
63
64#define VOP_INTR_SET(vop, name, v) \
65 REG_SET(vop, 0, vop->data->intr->name, v, NORMAL)
66#define VOP_INTR_SET_TYPE(vop, name, type, v) \
67 do { \
68 int i, reg = 0; \
69 for (i = 0; i < vop->data->intr->nintrs; i++) { \
70 if (vop->data->intr->intrs[i] & type) \
71 reg |= (v) << i; \
72 } \
73 VOP_INTR_SET(vop, name, reg); \
74 } while (0)
75#define VOP_INTR_GET_TYPE(vop, name, type) \
76 vop_get_intr_type(vop, &vop->data->intr->name, type)
77
59#define VOP_WIN_GET(x, win, name) \ 78#define VOP_WIN_GET(x, win, name) \
60 vop_read_reg(x, win->base, &win->phy->name) 79 vop_read_reg(x, win->base, &win->phy->name)
61 80
@@ -168,6 +187,13 @@ struct vop_ctrl {
168 struct vop_reg cfg_done; 187 struct vop_reg cfg_done;
169}; 188};
170 189
190struct vop_intr {
191 const int *intrs;
192 uint32_t nintrs;
193 struct vop_reg enable;
194 struct vop_reg clear;
195 struct vop_reg status;
196};
171struct vop_scl_regs { 197struct vop_scl_regs {
172 struct vop_reg cbcr_vsd_mode; 198 struct vop_reg cbcr_vsd_mode;
173 struct vop_reg cbcr_vsu_mode; 199 struct vop_reg cbcr_vsu_mode;
@@ -227,6 +253,7 @@ struct vop_data {
227 const struct vop_reg_data *init_table; 253 const struct vop_reg_data *init_table;
228 unsigned int table_size; 254 unsigned int table_size;
229 const struct vop_ctrl *ctrl; 255 const struct vop_ctrl *ctrl;
256 const struct vop_intr *intr;
230 const struct vop_win_data *win; 257 const struct vop_win_data *win;
231 unsigned int win_size; 258 unsigned int win_size;
232}; 259};
@@ -364,8 +391,24 @@ static const struct vop_win_data rk3288_vop_win_data[] = {
364 { .base = 0x50, .phy = &win23_data, .type = DRM_PLANE_TYPE_CURSOR }, 391 { .base = 0x50, .phy = &win23_data, .type = DRM_PLANE_TYPE_CURSOR },
365}; 392};
366 393
394static const int rk3288_vop_intrs[] = {
395 DSP_HOLD_VALID_INTR,
396 FS_INTR,
397 LINE_FLAG_INTR,
398 BUS_ERROR_INTR,
399};
400
401static const struct vop_intr rk3288_vop_intr = {
402 .intrs = rk3288_vop_intrs,
403 .nintrs = ARRAY_SIZE(rk3288_vop_intrs),
404 .status = VOP_REG(INTR_CTRL0, 0xf, 0),
405 .enable = VOP_REG(INTR_CTRL0, 0xf, 4),
406 .clear = VOP_REG(INTR_CTRL0, 0xf, 8),
407};
408
367static const struct vop_data rk3288_vop = { 409static const struct vop_data rk3288_vop = {
368 .init_table = vop_init_reg_table, 410 .init_table = vop_init_reg_table,
411 .intr = &rk3288_vop_intr,
369 .table_size = ARRAY_SIZE(vop_init_reg_table), 412 .table_size = ARRAY_SIZE(vop_init_reg_table),
370 .ctrl = &ctrl_data, 413 .ctrl = &ctrl_data,
371 .win = rk3288_vop_win_data, 414 .win = rk3288_vop_win_data,
@@ -420,6 +463,20 @@ static inline void vop_mask_write_relaxed(struct vop *vop, uint32_t offset,
420 } 463 }
421} 464}
422 465
466static inline uint32_t vop_get_intr_type(struct vop *vop,
467 const struct vop_reg *reg, int type)
468{
469 uint32_t i, ret = 0;
470 uint32_t regs = vop_read_reg(vop, 0, reg);
471
472 for (i = 0; i < vop->data->intr->nintrs; i++) {
473 if ((type & vop->data->intr->intrs[i]) && (regs & 1 << i))
474 ret |= vop->data->intr->intrs[i];
475 }
476
477 return ret;
478}
479
423static inline void vop_cfg_done(struct vop *vop) 480static inline void vop_cfg_done(struct vop *vop)
424{ 481{
425 VOP_CTRL_SET(vop, cfg_done, 1); 482 VOP_CTRL_SET(vop, cfg_done, 1);
@@ -616,8 +673,7 @@ static void vop_dsp_hold_valid_irq_enable(struct vop *vop)
616 673
617 spin_lock_irqsave(&vop->irq_lock, flags); 674 spin_lock_irqsave(&vop->irq_lock, flags);
618 675
619 vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK, 676 VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 1);
620 DSP_HOLD_VALID_INTR_EN(1));
621 677
622 spin_unlock_irqrestore(&vop->irq_lock, flags); 678 spin_unlock_irqrestore(&vop->irq_lock, flags);
623} 679}
@@ -631,8 +687,7 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
631 687
632 spin_lock_irqsave(&vop->irq_lock, flags); 688 spin_lock_irqsave(&vop->irq_lock, flags);
633 689
634 vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK, 690 VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 0);
635 DSP_HOLD_VALID_INTR_EN(0));
636 691
637 spin_unlock_irqrestore(&vop->irq_lock, flags); 692 spin_unlock_irqrestore(&vop->irq_lock, flags);
638} 693}
@@ -1051,7 +1106,7 @@ static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
1051 1106
1052 spin_lock_irqsave(&vop->irq_lock, flags); 1107 spin_lock_irqsave(&vop->irq_lock, flags);
1053 1108
1054 vop_mask_write(vop, INTR_CTRL0, FS_INTR_MASK, FS_INTR_EN(1)); 1109 VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 1);
1055 1110
1056 spin_unlock_irqrestore(&vop->irq_lock, flags); 1111 spin_unlock_irqrestore(&vop->irq_lock, flags);
1057 1112
@@ -1067,7 +1122,9 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
1067 return; 1122 return;
1068 1123
1069 spin_lock_irqsave(&vop->irq_lock, flags); 1124 spin_lock_irqsave(&vop->irq_lock, flags);
1070 vop_mask_write(vop, INTR_CTRL0, FS_INTR_MASK, FS_INTR_EN(0)); 1125
1126 VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0);
1127
1071 spin_unlock_irqrestore(&vop->irq_lock, flags); 1128 spin_unlock_irqrestore(&vop->irq_lock, flags);
1072} 1129}
1073 1130
@@ -1263,21 +1320,21 @@ static irqreturn_t vop_isr(int irq, void *data)
1263{ 1320{
1264 struct vop *vop = data; 1321 struct vop *vop = data;
1265 struct drm_crtc *crtc = &vop->crtc; 1322 struct drm_crtc *crtc = &vop->crtc;
1266 uint32_t intr0_reg, active_irqs; 1323 uint32_t active_irqs;
1267 unsigned long flags; 1324 unsigned long flags;
1268 int ret = IRQ_NONE; 1325 int ret = IRQ_NONE;
1269 1326
1270 /* 1327 /*
1271 * INTR_CTRL0 register has interrupt status, enable and clear bits, we 1328 * interrupt register has interrupt status, enable and clear bits, we
1272 * must hold irq_lock to avoid a race with enable/disable_vblank(). 1329 * must hold irq_lock to avoid a race with enable/disable_vblank().
1273 */ 1330 */
1274 spin_lock_irqsave(&vop->irq_lock, flags); 1331 spin_lock_irqsave(&vop->irq_lock, flags);
1275 intr0_reg = vop_readl(vop, INTR_CTRL0); 1332
1276 active_irqs = intr0_reg & INTR_MASK; 1333 active_irqs = VOP_INTR_GET_TYPE(vop, status, INTR_MASK);
1277 /* Clear all active interrupt sources */ 1334 /* Clear all active interrupt sources */
1278 if (active_irqs) 1335 if (active_irqs)
1279 vop_writel(vop, INTR_CTRL0, 1336 VOP_INTR_SET_TYPE(vop, clear, active_irqs, 1);
1280 intr0_reg | (active_irqs << INTR_CLR_SHIFT)); 1337
1281 spin_unlock_irqrestore(&vop->irq_lock, flags); 1338 spin_unlock_irqrestore(&vop->irq_lock, flags);
1282 1339
1283 /* This is expected for vop iommu irqs, since the irq is shared */ 1340 /* This is expected for vop iommu irqs, since the irq is shared */