drm/rockchip: vop: Enable writeback complete interrupt for rv1126b

Change-Id: Ib070e905f644989f5e3a27fc53632257454560e9
Signed-off-by: Chaoyi Chen <chaoyi.chen@rock-chips.com>
This commit is contained in:
Chaoyi Chen
2024-11-14 13:59:27 +00:00
committed by Tao Huang
parent 1791848c0d
commit 8749235106

View File

@@ -248,33 +248,9 @@ struct vop_win {
struct drm_property *name_prop;
};
/*
* max two jobs a time, one is running(writing back),
* another one will run in next frame.
*/
#define VOP_WB_JOB_MAX 2
struct vop_wb_job {
bool pending;
/**
* @fs_vsync_cnt: frame start vysnc counter,
* used to get the write back complete event;
*/
uint32_t fs_vsync_cnt;
};
struct vop_wb {
struct drm_writeback_connector conn;
const struct vop_wb_regs *regs;
struct vop_wb_job jobs[VOP_WB_JOB_MAX];
uint8_t job_index;
/**
* @job_lock:
*
* spinlock to protect the job between vop_wb_commit and vop_wb_handler in isr.
*/
spinlock_t job_lock;
};
enum vop_wb_format {
@@ -1791,7 +1767,6 @@ static int vop_wb_connector_init(struct vop *vop)
vop->wb.regs = vop_data->wb->regs;
vop->wb.conn.encoder.possible_crtcs = drm_crtc_mask(crtc);
spin_lock_init(&vop->wb.job_lock);
drm_connector_helper_add(&vop->wb.conn.base, &vop_wb_connector_helper_funcs);
ret = drm_writeback_connector_init(vop->drm_dev, &vop->wb.conn,
@@ -1821,7 +1796,8 @@ static void vop_wb_irqs_enable(struct vop *vop)
{
const struct vop_data *vop_data = vop->data;
const struct vop_intr *intr = vop_data->wb_intr;
uint32_t irqs = VOPL_WB_UV_FIFO_FULL_INTR | VOPL_WB_YRGB_FIFO_FULL_INTR;
uint32_t irqs = VOPL_WB_UV_FIFO_FULL_INTR | VOPL_WB_YRGB_FIFO_FULL_INTR |
VOPL_WB_COMPLETE_INTR;
VOP_INTR_SET_TYPE2(vop, intr, clear, irqs, 1);
VOP_INTR_SET_TYPE2(vop, intr, enable, irqs, 1);
@@ -1831,7 +1807,8 @@ static uint32_t vop_read_and_clear_wb_irqs(struct vop *vop)
{
const struct vop_data *vop_data = vop->data;
const struct vop_intr *intr = vop_data->wb_intr;
uint32_t irqs = VOPL_WB_UV_FIFO_FULL_INTR | VOPL_WB_YRGB_FIFO_FULL_INTR;
uint32_t irqs = VOPL_WB_UV_FIFO_FULL_INTR | VOPL_WB_YRGB_FIFO_FULL_INTR |
VOPL_WB_COMPLETE_INTR;
uint32_t val, ret;
if (!intr)
@@ -1860,7 +1837,6 @@ static void vop_wb_commit(struct drm_crtc *crtc)
struct drm_writeback_connector *wb_conn = &wb->conn;
struct drm_connector_state *conn_state = wb_conn->base.state;
struct vop_wb_connector_state *wb_state;
unsigned long flags;
uint32_t fifo_throd;
uint8_t r2y;
@@ -1878,13 +1854,6 @@ static void vop_wb_commit(struct drm_crtc *crtc)
drm_writeback_queue_job(wb_conn, conn_state);
spin_lock_irqsave(&wb->job_lock, flags);
wb->jobs[wb->job_index].pending = true;
wb->job_index++;
if (wb->job_index >= VOP_WB_JOB_MAX)
wb->job_index = 0;
spin_unlock_irqrestore(&wb->job_lock, flags);
fifo_throd = fb->pitches[0] >> 4;
if (fifo_throd > vop->data->wb->fifo_depth)
fifo_throd = vop->data->wb->fifo_depth;
@@ -1923,33 +1892,6 @@ static void __maybe_unused vop_wb_disable(struct vop *vop)
vop_wb_cfg_done(vop);
}
static void vop_wb_handler(struct vop *vop)
{
struct vop_wb *wb = &vop->wb;
struct vop_wb_job *job;
unsigned long flags;
uint8_t i;
if (!wb->regs)
return;
/* In one shot mode, wb_en is auto disable */
spin_lock_irqsave(&wb->job_lock, flags);
for (i = 0; i < VOP_WB_JOB_MAX; i++) {
job = &wb->jobs[i];
if (job->pending) {
job->fs_vsync_cnt++;
if (job->fs_vsync_cnt == 2) {
job->pending = false;
job->fs_vsync_cnt = 0;
drm_writeback_signal_completion(&vop->wb.conn, 0);
}
}
}
spin_unlock_irqrestore(&wb->job_lock, flags);
}
static void vop_crtc_load_lut(struct drm_crtc *crtc)
{
struct vop *vop = to_vop(crtc);
@@ -5334,6 +5276,24 @@ static void vop_handle_vblank(struct vop *vop)
drm_flip_work_commit(&vop->fb_unref_work, system_unbound_wq);
}
static void vop_wb_complete(struct vop *vop)
{
struct vop_wb *wb = &vop->wb;
bool wb_oneframe_mode;
bool wb_en;
wb_en = VOP_CTRL_GET2(vop, wb, enable);
wb_oneframe_mode = VOP_CTRL_GET2(vop, wb, one_frame_mode);
/*
* The write back should work in one shot mode,
* stop when write back complete in next vsync.
*/
if (wb_en && !wb_oneframe_mode)
vop_wb_disable(vop);
drm_writeback_signal_completion(&vop->wb.conn, 0);
}
static irqreturn_t vop_isr(int irq, void *data)
{
struct vop *vop = data;
@@ -5395,7 +5355,6 @@ static irqreturn_t vop_isr(int irq, void *data)
VOP_CTRL_SET(vop, level2_overlay_en, vop->pre_overlay);
VOP_CTRL_SET(vop, alpha_hard_calc, vop->pre_overlay);
spin_unlock_irqrestore(&vop->irq_lock, flags);
vop_wb_handler(vop);
drm_crtc_handle_vblank(crtc);
vop_handle_vblank(vop);
active_irqs &= ~(FS_INTR | FS_FIELD_INTR);
@@ -5427,6 +5386,12 @@ static irqreturn_t vop_isr(int irq, void *data)
active_irqs = wb_irqs;
ERROR_HANDLER(VOPL_WB_UV_FIFO_FULL);
ERROR_HANDLER(VOPL_WB_YRGB_FIFO_FULL);
if (active_irqs & VOPL_WB_COMPLETE_INTR) {
active_irqs &= ~VOPL_WB_COMPLETE_INTR;
vop_wb_complete(vop);
}
if (active_irqs)
DRM_ERROR("Unknown writeback IRQs: %02x\n", active_irqs);
}
out_disable: