Merge commit 'f854f64c008300f5ae3e75cfc7dec5e848850655'

* commit 'f854f64c008300f5ae3e75cfc7dec5e848850655':
  drm/rockchip: vop: Do not clear wb intr status when commit new wb
  drm/rockchip: vop: Do not commit writeback when all win disabled
  drm/rockchip: vop: Add enabled_win_mask to record enabled win
  drm/rockchip: vop: Enable writeback complete interrupt for rv1126b
  drm/rockchip: vop: Remove redundant writeback cleanup
  drm/rockchip: vop: Fix writeback interrupt process
  soc: rockchip: decompress: support user-space usage
  drm/rockchip: vop2: Remove the flag &vop2->is_iommu_needed
  nvmem: rockchip-secure-otp: Resolve compilation errors

Change-Id: Ie5dbcc90fafc50e3db7092e14b535dc29d26e594
This commit is contained in:
Tao Huang
2025-08-13 19:58:30 +08:00
5 changed files with 84 additions and 94 deletions

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 {
@@ -315,6 +291,11 @@ struct vop {
bool aclk_rate_reset;
unsigned long aclk_rate;
/**
* @enabled_win_mask: Bitmask of enabled wins attached to the VOP
*/
uint32_t enabled_win_mask;
u32 version;
u32 background;
u32 line_flag;
@@ -645,6 +626,7 @@ static bool vop_is_allwin_disabled(struct vop *vop)
static void vop_win_disable(struct vop *vop, struct vop_win *win)
{
vop->enabled_win_mask &= ~BIT(win->win_id);
/*
* FIXUP: some of the vop scale would be abnormal after windows power
* on/off so deinit scale to scale_none mode.
@@ -1791,7 +1773,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,9 +1802,9 @@ 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,17 +1812,26 @@ 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 val;
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)
return 0;
val = VOP_INTR_GET_TYPE2(vop, intr, status, irqs);
ret = val;
/* For RV1126B, it should use VOPL_WB_YRGB_FIFO_FULL_INTR to
* clear all wb interrupt.
*/
if (vop->version == VOP_VERSION_RV1126B)
val |= VOPL_WB_YRGB_FIFO_FULL_INTR;
if (val)
VOP_INTR_SET_TYPE2(vop, intr, clear, val, 1);
return val;
return ret;
}
static void vop_wb_commit(struct drm_crtc *crtc)
@@ -1852,7 +1842,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;
@@ -1869,14 +1858,11 @@ static void vop_wb_commit(struct drm_crtc *crtc)
fb->pitches[0], &wb_state->yrgb_addr);
drm_writeback_queue_job(wb_conn, conn_state);
conn_state->writeback_job = NULL;
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);
if (!vop->enabled_win_mask) {
drm_warn(vop->drm_dev, "Writeback can not work when all plane are disabled!");
drm_writeback_signal_completion(&vop->wb.conn, 0);
return;
}
fifo_throd = fb->pitches[0] >> 4;
if (fifo_throd > vop->data->wb->fifo_depth)
@@ -1916,33 +1902,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);
@@ -2758,6 +2717,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
VOP_WIN_SET(vop, win, gate, 1);
spin_unlock(&vop->reg_lock);
vop->enabled_win_mask |= BIT(win->win_id);
if (rockchip_afbc(plane, fb->modifier))
afbc_en = true;
rockchip_drm_dbg_thread_info(vop->dev, VOP_DEBUG_PLANE,
@@ -3181,6 +3142,7 @@ static int vop_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data)
struct vop *vop = to_vop(crtc);
int sys_status = drm_crtc_index(crtc) ?
SYS_STATUS_LCDC1 : SYS_STATUS_LCDC0;
struct vop_win *win;
if (on == vop->loader_protect)
return 0;
@@ -3202,6 +3164,11 @@ static int vop_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data)
rockchip_set_system_status(sys_status);
vop_initial(crtc);
if (crtc->primary) {
win = to_vop_win(crtc->primary);
if (VOP_WIN_GET(vop, win, enable))
vop->enabled_win_mask |= BIT(win->win_id);
}
drm_crtc_vblank_on(crtc);
vop->loader_protect = true;
} else {
@@ -5327,6 +5294,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;
@@ -5363,7 +5348,7 @@ static irqreturn_t vop_isr(int irq, void *data)
spin_unlock_irqrestore(&vop->irq_lock, flags);
/* This is expected for vop iommu irqs, since the irq is shared */
if (!active_irqs)
if (!active_irqs && !wb_irqs)
goto out_disable;
if (active_irqs & DSP_HOLD_VALID_INTR) {
@@ -5388,7 +5373,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);
@@ -5420,6 +5404,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:

View File

@@ -925,7 +925,6 @@ struct vop2 {
struct drm_prop_enum_list *plane_name_list;
struct vop2_shared_mode_res shared_mode_res;
bool is_iommu_enabled;
bool is_iommu_needed;
bool is_enabled;
bool support_multi_area;
bool disable_afbc_win;
@@ -7241,8 +7240,6 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_atomic_
}
vop2_win_atomic_update(win, &wsrc, &wdst, pstate);
vop2->is_iommu_needed = true;
}
static const struct drm_plane_helper_funcs vop2_plane_helper_funcs = {
@@ -13483,7 +13480,7 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_stat
vop2_cfg_update(crtc, old_cstate);
if (!vop2->is_iommu_enabled && vop2->is_iommu_needed) {
if (!vop2->is_iommu_enabled) {
enum rockchip_drm_vop_aclk_mode aclk_mode = vop2->aclk_mode;
bool enter_vop_aclk_reset_mode = false;

View File

@@ -2039,8 +2039,10 @@ static const struct vop_wb_regs rv1126b_vop_wb_regs = {
};
static const int rv1126_wb_intrs[] = {
VOPL_WB_UV_FIFO_FULL_INTR,
VOPL_WB_YRGB_FIFO_FULL_INTR,
VOPL_WB_UV_FIFO_FULL_INTR,
0,
0,
VOPL_WB_COMPLETE_INTR,
};

View File

@@ -98,10 +98,9 @@ int rockchip_read_oem_non_protected_otp(unsigned int byte_off,
/* Alloc share memory */
shm_size = byte_len;
device_shm = tee_shm_alloc(ctx, shm_size,
TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
device_shm = tee_shm_alloc_kernel_buf(ctx, shm_size);
if (IS_ERR(device_shm)) {
pr_err("tee_shm_alloc failed\n");
pr_err("tee_shm_alloc_kernel_buf failed\n");
rc = PTR_ERR(device_shm);
goto out_sess;
}
@@ -201,10 +200,9 @@ int rockchip_write_oem_non_protected_otp(unsigned int byte_off,
/* Alloc share memory */
shm_size = byte_len;
device_shm = tee_shm_alloc(ctx, shm_size,
TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
device_shm = tee_shm_alloc_kernel_buf(ctx, shm_size);
if (IS_ERR(device_shm)) {
pr_err("tee_shm_alloc failed\n");
pr_err("tee_shm_alloc_kernel_buf failed\n");
rc = PTR_ERR(device_shm);
goto out_sess;
}

View File

@@ -484,25 +484,28 @@ static int __init rockchip_decom_probe(struct platform_device *pdev)
}
mem = of_parse_phandle(np, "memory-region", 0);
if (!mem) {
dev_err(dev, "missing \"memory-region\" property\n");
#ifndef CONFIG_ROCKCHIP_HW_DECOMPRESS_TEST
if (mem) {
ret = of_address_to_resource(mem, 0, &reg);
of_node_put(mem);
if (ret) {
dev_err(dev, "invalid \"memory-region\" property\n");
return -ENODEV;
}
rk_dec->mem_start = reg.start;
rk_dec->mem_size = resource_size(&reg);
dev_info(dev, "Using reserved memory region: start=0x%pa, size=0x%zx\n",
&rk_dec->mem_start, rk_dec->mem_size);
} else {
#ifdef CONFIG_ROCKCHIP_HW_DECOMPRESS_TEST
return -ENODEV;
#endif
/* For user-space usage, memory-region is optional */
rk_dec->mem_start = 0;
rk_dec->mem_size = 0;
dev_info(dev, "No memory-region specified, user-space memory management\n");
}
ret = of_address_to_resource(mem, 0, &reg);
of_node_put(mem);
if (ret) {
dev_err(dev, "missing \"reg\" property\n");
#ifndef CONFIG_ROCKCHIP_HW_DECOMPRESS_TEST
return -ENODEV;
#endif
}
rk_dec->mem_start = reg.start;
rk_dec->mem_size = resource_size(&reg);
rk_dec->num_clocks = devm_clk_bulk_get_all(dev, &rk_dec->clocks);
if (rk_dec->num_clocks < 0) {
dev_err(dev, "failed to get decompress clock\n");