diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index c7df6a48f10a..97a3d0de7968 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -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: diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index b5fa6f67078d..0ead76c1ac89 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -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; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 427643e37948..0793b7cad774 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -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, }; diff --git a/drivers/nvmem/rockchip-secure-otp.c b/drivers/nvmem/rockchip-secure-otp.c index e8df65c3736b..0cd8d0205347 100644 --- a/drivers/nvmem/rockchip-secure-otp.c +++ b/drivers/nvmem/rockchip-secure-otp.c @@ -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; } diff --git a/drivers/soc/rockchip/rockchip_decompress.c b/drivers/soc/rockchip/rockchip_decompress.c index 335ebefb02d7..15b4f6601a8e 100644 --- a/drivers/soc/rockchip/rockchip_decompress.c +++ b/drivers/soc/rockchip/rockchip_decompress.c @@ -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, ®); + 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(®); + 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, ®); - 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(®); - 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");