diff options
author | Mark Yao <mark.yao@rock-chips.com> | 2015-12-14 19:36:55 -0500 |
---|---|---|
committer | Mark Yao <mark.yao@rock-chips.com> | 2015-12-27 20:01:28 -0500 |
commit | dbb3d94444eaa56cb1a6c9790f2fbe14b14310aa (patch) | |
tree | d1867ca93dc621803c3f344fb0ba753e23a1c095 | |
parent | 0cf33fe33d4e9fdbbdd0b93101b078b03d0ba9b5 (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.c | 81 |
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 | ||
190 | struct 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 | }; | ||
171 | struct vop_scl_regs { | 197 | struct 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 | ||
394 | static const int rk3288_vop_intrs[] = { | ||
395 | DSP_HOLD_VALID_INTR, | ||
396 | FS_INTR, | ||
397 | LINE_FLAG_INTR, | ||
398 | BUS_ERROR_INTR, | ||
399 | }; | ||
400 | |||
401 | static 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 | |||
367 | static const struct vop_data rk3288_vop = { | 409 | static 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 | ||
466 | static 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 | |||
423 | static inline void vop_cfg_done(struct vop *vop) | 480 | static 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 */ |