diff --git a/drivers/video/rockchip/rga3/include/rga2_reg_info.h b/drivers/video/rockchip/rga3/include/rga2_reg_info.h index 90d18d443ce8..dcb4da13cd79 100644 --- a/drivers/video/rockchip/rga3/include/rga2_reg_info.h +++ b/drivers/video/rockchip/rga3/include/rga2_reg_info.h @@ -123,6 +123,8 @@ #define m_RGA2_CMD_CTRL_INCR_VALID_P (0x1 << 1) #define m_RGA2_CMD_CTRL_CMD_LINE_ST_P (0x1 << 0) +#define s_RGA2_CMD_CTRL_INCR_NUM(x) ((x & 0x3ff) << 3) + /* RGA_STATUS1 */ #define m_RGA2_STATUS1_SW_CMD_TOTAL_NUM (0xfff << 8) #define m_RGA2_STATUS1_SW_CMD_CUR_NUM (0xfff << 8) diff --git a/drivers/video/rockchip/rga3/include/rga_drv.h b/drivers/video/rockchip/rga3/include/rga_drv.h index 997f4d6e16ca..d19bd8200794 100644 --- a/drivers/video/rockchip/rga3/include/rga_drv.h +++ b/drivers/video/rockchip/rga3/include/rga_drv.h @@ -87,7 +87,7 @@ #define DRIVER_MAJOR_VERISON 1 #define DRIVER_MINOR_VERSION 3 -#define DRIVER_REVISION_VERSION 3 +#define DRIVER_REVISION_VERSION 4 #define DRIVER_PATCH_VERSION #define DRIVER_VERSION (STR(DRIVER_MAJOR_VERISON) "." STR(DRIVER_MINOR_VERSION) \ @@ -337,8 +337,11 @@ struct rga_scheduler_t { struct list_head todo_list; spinlock_t irq_lock; wait_queue_head_t job_done_wq; + const struct rga_backend_ops *ops; const struct rga_hw_data *data; + unsigned long hw_issues_mask; + int job_count; int irq; struct rga_version_t version; diff --git a/drivers/video/rockchip/rga3/include/rga_hw_config.h b/drivers/video/rockchip/rga3/include/rga_hw_config.h index 61dace41447b..6679c599af42 100644 --- a/drivers/video/rockchip/rga3/include/rga_hw_config.h +++ b/drivers/video/rockchip/rga3/include/rga_hw_config.h @@ -26,6 +26,10 @@ enum rga_hw_support_format_index { RGA_FORMAT_INDEX_BUTT, }; +enum rga_hw_issue { + RGA_HW_ISSUE_DIS_AUTO_RST, +}; + struct rga_win_data { const char *name; const uint32_t *formats[RGA_FORMAT_INDEX_BUTT]; @@ -75,6 +79,9 @@ extern const struct rga_hw_data rga2e_1106_data; extern const struct rga_hw_data rga2e_iommu_data; extern const struct rga_hw_data rga2p_iommu_data; +#define rga_hw_has_issue(scheduler, issue) test_bit(issue, &((scheduler)->hw_issues_mask)) +#define rga_hw_set_issue_mask(scheduler, issue) set_bit(issue, &((scheduler)->hw_issues_mask)) + /* Returns false if in range, true otherwise */ static inline bool rga_hw_out_of_range(const struct rga_rect_range *range, int width, int height) { diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index 018bc5cc97cf..c9423729640a 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -2889,6 +2889,7 @@ static void rga2_set_reg_full_csc(struct rga_job *job, struct rga_scheduler_t *s static int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) { int i; + int cur_num; bool master_mode_en; uint32_t sys_ctrl; uint32_t *cmd; @@ -2917,12 +2918,25 @@ static int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) cmd[2 + i * 4], cmd[3 + i * 4]); } + spin_lock_irqsave(&scheduler->irq_lock, flags); + /* sys_reg init */ - sys_ctrl = m_RGA2_SYS_CTRL_AUTO_CKG | m_RGA2_SYS_CTRL_AUTO_RST | - m_RGA2_SYS_CTRL_RST_PROTECT_P | m_RGA2_SYS_CTRL_DST_WR_OPT_DIS | + sys_ctrl = m_RGA2_SYS_CTRL_AUTO_CKG | + m_RGA2_SYS_CTRL_DST_WR_OPT_DIS | m_RGA2_SYS_CTRL_SRC0YUV420SP_RD_OPT_DIS; - spin_lock_irqsave(&scheduler->irq_lock, flags); + if (rga_hw_has_issue(scheduler, RGA_HW_ISSUE_DIS_AUTO_RST)) { + /* + * when RGA is running continuously, disabling auto_rst + * requires resetting core_clk. + */ + cur_num = (rga_read(RGA2_STATUS1, scheduler) & m_RGA2_STATUS1_SW_CMD_CUR_NUM) >> 8; + if (cur_num > 0) + rga_write(m_RGA2_SYS_CTRL_AUTO_CKG | m_RGA2_SYS_CTRL_CCLK_SRESET_P, + RGA2_SYS_CTRL, scheduler); + } else { + sys_ctrl |= m_RGA2_SYS_CTRL_AUTO_RST; + } if (job->pre_intr_info.enable) rga2_set_pre_intr_reg(job, scheduler); @@ -2942,7 +2956,8 @@ static int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) /* set cmd_addr */ rga_write(job->cmd_buf->dma_addr, RGA2_CMD_BASE, scheduler); rga_write(sys_ctrl, RGA2_SYS_CTRL, scheduler); - rga_write(m_RGA2_CMD_CTRL_CMD_LINE_ST_P, RGA2_CMD_CTRL, scheduler); + rga_write(rga_read(RGA2_CMD_CTRL, scheduler) | m_RGA2_CMD_CTRL_CMD_LINE_ST_P, + RGA2_CMD_CTRL, scheduler); } else { /* slave mode */ sys_ctrl |= s_RGA2_SYS_CTRL_CMD_MODE(0) | m_RGA2_SYS_CTRL_CMD_OP_ST_P; @@ -2951,6 +2966,8 @@ static int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) for (i = 0; i <= 32; i++) rga_write(cmd[i], 0x100 + i * 4, scheduler); + rga_write(rga_read(RGA2_CMD_CTRL, scheduler) | m_RGA2_CMD_CTRL_CMD_LINE_ST_P, + RGA2_CMD_CTRL, scheduler); rga_write(sys_ctrl, RGA2_SYS_CTRL, scheduler); } diff --git a/drivers/video/rockchip/rga3/rga_drv.c b/drivers/video/rockchip/rga3/rga_drv.c index 0179da8db9b3..e4e70def194e 100644 --- a/drivers/video/rockchip/rga3/rga_drv.c +++ b/drivers/video/rockchip/rga3/rga_drv.c @@ -1366,15 +1366,17 @@ static int rga_drv_probe(struct platform_device *pdev) scheduler->data = &rga3_data; } else if (scheduler->core == RGA2_SCHEDULER_CORE0 || scheduler->core == RGA2_SCHEDULER_CORE1) { - if (!strcmp(scheduler->version.str, "3.3.87975")) + if (!strcmp(scheduler->version.str, "3.3.87975")) { scheduler->data = &rga2e_1106_data; - else if (!strcmp(scheduler->version.str, "3.6.92812") || - !strcmp(scheduler->version.str, "3.7.93215")) + } else if (!strcmp(scheduler->version.str, "3.6.92812") || + !strcmp(scheduler->version.str, "3.7.93215")) { scheduler->data = &rga2e_iommu_data; - else if (!strcmp(scheduler->version.str, "3.e.19357")) + } else if (!strcmp(scheduler->version.str, "3.e.19357")) { scheduler->data = &rga2p_iommu_data; - else + rga_hw_set_issue_mask(scheduler, RGA_HW_ISSUE_DIS_AUTO_RST); + } else { scheduler->data = &rga2e_data; + } } data->scheduler[data->num_of_scheduler] = scheduler;