Commit dbb3d944 authored by Mark Yao's avatar Mark Yao

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: default avatarMark Yao <mark.yao@rock-chips.com>
parent 0cf33fe3
...@@ -48,6 +48,8 @@ ...@@ -48,6 +48,8 @@
#define REG_SET(x, base, reg, v, mode) \ #define REG_SET(x, base, reg, v, mode) \
__REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v) __REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v)
#define REG_SET_MASK(x, base, reg, v, mode) \
__REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v)
#define VOP_WIN_SET(x, win, name, v) \ #define VOP_WIN_SET(x, win, name, v) \
REG_SET(x, win->base, win->phy->name, v, RELAXED) REG_SET(x, win->base, win->phy->name, v, RELAXED)
...@@ -56,6 +58,23 @@ ...@@ -56,6 +58,23 @@
#define VOP_CTRL_SET(x, name, v) \ #define VOP_CTRL_SET(x, name, v) \
REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL) REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL)
#define VOP_INTR_GET(vop, name) \
vop_read_reg(vop, 0, &vop->data->ctrl->name)
#define VOP_INTR_SET(vop, name, v) \
REG_SET(vop, 0, vop->data->intr->name, v, NORMAL)
#define VOP_INTR_SET_TYPE(vop, name, type, v) \
do { \
int i, reg = 0; \
for (i = 0; i < vop->data->intr->nintrs; i++) { \
if (vop->data->intr->intrs[i] & type) \
reg |= (v) << i; \
} \
VOP_INTR_SET(vop, name, reg); \
} while (0)
#define VOP_INTR_GET_TYPE(vop, name, type) \
vop_get_intr_type(vop, &vop->data->intr->name, type)
#define VOP_WIN_GET(x, win, name) \ #define VOP_WIN_GET(x, win, name) \
vop_read_reg(x, win->base, &win->phy->name) vop_read_reg(x, win->base, &win->phy->name)
...@@ -168,6 +187,13 @@ struct vop_ctrl { ...@@ -168,6 +187,13 @@ struct vop_ctrl {
struct vop_reg cfg_done; struct vop_reg cfg_done;
}; };
struct vop_intr {
const int *intrs;
uint32_t nintrs;
struct vop_reg enable;
struct vop_reg clear;
struct vop_reg status;
};
struct vop_scl_regs { struct vop_scl_regs {
struct vop_reg cbcr_vsd_mode; struct vop_reg cbcr_vsd_mode;
struct vop_reg cbcr_vsu_mode; struct vop_reg cbcr_vsu_mode;
...@@ -227,6 +253,7 @@ struct vop_data { ...@@ -227,6 +253,7 @@ struct vop_data {
const struct vop_reg_data *init_table; const struct vop_reg_data *init_table;
unsigned int table_size; unsigned int table_size;
const struct vop_ctrl *ctrl; const struct vop_ctrl *ctrl;
const struct vop_intr *intr;
const struct vop_win_data *win; const struct vop_win_data *win;
unsigned int win_size; unsigned int win_size;
}; };
...@@ -364,8 +391,24 @@ static const struct vop_win_data rk3288_vop_win_data[] = { ...@@ -364,8 +391,24 @@ static const struct vop_win_data rk3288_vop_win_data[] = {
{ .base = 0x50, .phy = &win23_data, .type = DRM_PLANE_TYPE_CURSOR }, { .base = 0x50, .phy = &win23_data, .type = DRM_PLANE_TYPE_CURSOR },
}; };
static const int rk3288_vop_intrs[] = {
DSP_HOLD_VALID_INTR,
FS_INTR,
LINE_FLAG_INTR,
BUS_ERROR_INTR,
};
static const struct vop_intr rk3288_vop_intr = {
.intrs = rk3288_vop_intrs,
.nintrs = ARRAY_SIZE(rk3288_vop_intrs),
.status = VOP_REG(INTR_CTRL0, 0xf, 0),
.enable = VOP_REG(INTR_CTRL0, 0xf, 4),
.clear = VOP_REG(INTR_CTRL0, 0xf, 8),
};
static const struct vop_data rk3288_vop = { static const struct vop_data rk3288_vop = {
.init_table = vop_init_reg_table, .init_table = vop_init_reg_table,
.intr = &rk3288_vop_intr,
.table_size = ARRAY_SIZE(vop_init_reg_table), .table_size = ARRAY_SIZE(vop_init_reg_table),
.ctrl = &ctrl_data, .ctrl = &ctrl_data,
.win = rk3288_vop_win_data, .win = rk3288_vop_win_data,
...@@ -420,6 +463,20 @@ static inline void vop_mask_write_relaxed(struct vop *vop, uint32_t offset, ...@@ -420,6 +463,20 @@ static inline void vop_mask_write_relaxed(struct vop *vop, uint32_t offset,
} }
} }
static inline uint32_t vop_get_intr_type(struct vop *vop,
const struct vop_reg *reg, int type)
{
uint32_t i, ret = 0;
uint32_t regs = vop_read_reg(vop, 0, reg);
for (i = 0; i < vop->data->intr->nintrs; i++) {
if ((type & vop->data->intr->intrs[i]) && (regs & 1 << i))
ret |= vop->data->intr->intrs[i];
}
return ret;
}
static inline void vop_cfg_done(struct vop *vop) static inline void vop_cfg_done(struct vop *vop)
{ {
VOP_CTRL_SET(vop, cfg_done, 1); VOP_CTRL_SET(vop, cfg_done, 1);
...@@ -616,8 +673,7 @@ static void vop_dsp_hold_valid_irq_enable(struct vop *vop) ...@@ -616,8 +673,7 @@ static void vop_dsp_hold_valid_irq_enable(struct vop *vop)
spin_lock_irqsave(&vop->irq_lock, flags); spin_lock_irqsave(&vop->irq_lock, flags);
vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK, VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 1);
DSP_HOLD_VALID_INTR_EN(1));
spin_unlock_irqrestore(&vop->irq_lock, flags); spin_unlock_irqrestore(&vop->irq_lock, flags);
} }
...@@ -631,8 +687,7 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop) ...@@ -631,8 +687,7 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
spin_lock_irqsave(&vop->irq_lock, flags); spin_lock_irqsave(&vop->irq_lock, flags);
vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK, VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 0);
DSP_HOLD_VALID_INTR_EN(0));
spin_unlock_irqrestore(&vop->irq_lock, flags); spin_unlock_irqrestore(&vop->irq_lock, flags);
} }
...@@ -1051,7 +1106,7 @@ static int vop_crtc_enable_vblank(struct drm_crtc *crtc) ...@@ -1051,7 +1106,7 @@ static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
spin_lock_irqsave(&vop->irq_lock, flags); spin_lock_irqsave(&vop->irq_lock, flags);
vop_mask_write(vop, INTR_CTRL0, FS_INTR_MASK, FS_INTR_EN(1)); VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 1);
spin_unlock_irqrestore(&vop->irq_lock, flags); spin_unlock_irqrestore(&vop->irq_lock, flags);
...@@ -1067,7 +1122,9 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc) ...@@ -1067,7 +1122,9 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
return; return;
spin_lock_irqsave(&vop->irq_lock, flags); spin_lock_irqsave(&vop->irq_lock, flags);
vop_mask_write(vop, INTR_CTRL0, FS_INTR_MASK, FS_INTR_EN(0));
VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0);
spin_unlock_irqrestore(&vop->irq_lock, flags); spin_unlock_irqrestore(&vop->irq_lock, flags);
} }
...@@ -1263,21 +1320,21 @@ static irqreturn_t vop_isr(int irq, void *data) ...@@ -1263,21 +1320,21 @@ static irqreturn_t vop_isr(int irq, void *data)
{ {
struct vop *vop = data; struct vop *vop = data;
struct drm_crtc *crtc = &vop->crtc; struct drm_crtc *crtc = &vop->crtc;
uint32_t intr0_reg, active_irqs; uint32_t active_irqs;
unsigned long flags; unsigned long flags;
int ret = IRQ_NONE; int ret = IRQ_NONE;
/* /*
* INTR_CTRL0 register has interrupt status, enable and clear bits, we * interrupt register has interrupt status, enable and clear bits, we
* must hold irq_lock to avoid a race with enable/disable_vblank(). * must hold irq_lock to avoid a race with enable/disable_vblank().
*/ */
spin_lock_irqsave(&vop->irq_lock, flags); spin_lock_irqsave(&vop->irq_lock, flags);
intr0_reg = vop_readl(vop, INTR_CTRL0);
active_irqs = intr0_reg & INTR_MASK; active_irqs = VOP_INTR_GET_TYPE(vop, status, INTR_MASK);
/* Clear all active interrupt sources */ /* Clear all active interrupt sources */
if (active_irqs) if (active_irqs)
vop_writel(vop, INTR_CTRL0, VOP_INTR_SET_TYPE(vop, clear, active_irqs, 1);
intr0_reg | (active_irqs << INTR_CLR_SHIFT));
spin_unlock_irqrestore(&vop->irq_lock, flags); spin_unlock_irqrestore(&vop->irq_lock, flags);
/* This is expected for vop iommu irqs, since the irq is shared */ /* This is expected for vop iommu irqs, since the irq is shared */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment