video: rockchip: rga3: add fix for hardware issue with RK3576

1. Disable auto_rst to avoid false interrupt generation.
2. Reset core_clk before startup to avoid hardware runaway due to
continuous scaling.
3. Configure auto_clean command count to avoid iommu access exception
after command count from 4095->0.

Update driver version to 1.3.4

Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
Change-Id: I12f312280429996c182952fbe8c8c4a20155dc4f
This commit is contained in:
Yu Qiaowei
2024-06-13 18:04:18 +08:00
committed by Tao Huang
parent 4b6e0305af
commit a2a7ce0bf0
5 changed files with 41 additions and 10 deletions

View File

@@ -123,6 +123,8 @@
#define m_RGA2_CMD_CTRL_INCR_VALID_P (0x1 << 1) #define m_RGA2_CMD_CTRL_INCR_VALID_P (0x1 << 1)
#define m_RGA2_CMD_CTRL_CMD_LINE_ST_P (0x1 << 0) #define m_RGA2_CMD_CTRL_CMD_LINE_ST_P (0x1 << 0)
#define s_RGA2_CMD_CTRL_INCR_NUM(x) ((x & 0x3ff) << 3)
/* RGA_STATUS1 */ /* RGA_STATUS1 */
#define m_RGA2_STATUS1_SW_CMD_TOTAL_NUM (0xfff << 8) #define m_RGA2_STATUS1_SW_CMD_TOTAL_NUM (0xfff << 8)
#define m_RGA2_STATUS1_SW_CMD_CUR_NUM (0xfff << 8) #define m_RGA2_STATUS1_SW_CMD_CUR_NUM (0xfff << 8)

View File

@@ -87,7 +87,7 @@
#define DRIVER_MAJOR_VERISON 1 #define DRIVER_MAJOR_VERISON 1
#define DRIVER_MINOR_VERSION 3 #define DRIVER_MINOR_VERSION 3
#define DRIVER_REVISION_VERSION 3 #define DRIVER_REVISION_VERSION 4
#define DRIVER_PATCH_VERSION #define DRIVER_PATCH_VERSION
#define DRIVER_VERSION (STR(DRIVER_MAJOR_VERISON) "." STR(DRIVER_MINOR_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; struct list_head todo_list;
spinlock_t irq_lock; spinlock_t irq_lock;
wait_queue_head_t job_done_wq; wait_queue_head_t job_done_wq;
const struct rga_backend_ops *ops; const struct rga_backend_ops *ops;
const struct rga_hw_data *data; const struct rga_hw_data *data;
unsigned long hw_issues_mask;
int job_count; int job_count;
int irq; int irq;
struct rga_version_t version; struct rga_version_t version;

View File

@@ -26,6 +26,10 @@ enum rga_hw_support_format_index {
RGA_FORMAT_INDEX_BUTT, RGA_FORMAT_INDEX_BUTT,
}; };
enum rga_hw_issue {
RGA_HW_ISSUE_DIS_AUTO_RST,
};
struct rga_win_data { struct rga_win_data {
const char *name; const char *name;
const uint32_t *formats[RGA_FORMAT_INDEX_BUTT]; 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 rga2e_iommu_data;
extern const struct rga_hw_data rga2p_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 */ /* 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) static inline bool rga_hw_out_of_range(const struct rga_rect_range *range, int width, int height)
{ {

View File

@@ -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) static int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler)
{ {
int i; int i;
int cur_num;
bool master_mode_en; bool master_mode_en;
uint32_t sys_ctrl; uint32_t sys_ctrl;
uint32_t *cmd; 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]); cmd[2 + i * 4], cmd[3 + i * 4]);
} }
spin_lock_irqsave(&scheduler->irq_lock, flags);
/* sys_reg init */ /* sys_reg init */
sys_ctrl = m_RGA2_SYS_CTRL_AUTO_CKG | m_RGA2_SYS_CTRL_AUTO_RST | sys_ctrl = m_RGA2_SYS_CTRL_AUTO_CKG |
m_RGA2_SYS_CTRL_RST_PROTECT_P | m_RGA2_SYS_CTRL_DST_WR_OPT_DIS | m_RGA2_SYS_CTRL_DST_WR_OPT_DIS |
m_RGA2_SYS_CTRL_SRC0YUV420SP_RD_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) if (job->pre_intr_info.enable)
rga2_set_pre_intr_reg(job, scheduler); 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 */ /* set cmd_addr */
rga_write(job->cmd_buf->dma_addr, RGA2_CMD_BASE, scheduler); rga_write(job->cmd_buf->dma_addr, RGA2_CMD_BASE, scheduler);
rga_write(sys_ctrl, RGA2_SYS_CTRL, 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 { } else {
/* slave mode */ /* slave mode */
sys_ctrl |= s_RGA2_SYS_CTRL_CMD_MODE(0) | m_RGA2_SYS_CTRL_CMD_OP_ST_P; 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++) for (i = 0; i <= 32; i++)
rga_write(cmd[i], 0x100 + i * 4, scheduler); 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); rga_write(sys_ctrl, RGA2_SYS_CTRL, scheduler);
} }

View File

@@ -1366,15 +1366,17 @@ static int rga_drv_probe(struct platform_device *pdev)
scheduler->data = &rga3_data; scheduler->data = &rga3_data;
} else if (scheduler->core == RGA2_SCHEDULER_CORE0 || } else if (scheduler->core == RGA2_SCHEDULER_CORE0 ||
scheduler->core == RGA2_SCHEDULER_CORE1) { 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; scheduler->data = &rga2e_1106_data;
else if (!strcmp(scheduler->version.str, "3.6.92812") || } else if (!strcmp(scheduler->version.str, "3.6.92812") ||
!strcmp(scheduler->version.str, "3.7.93215")) !strcmp(scheduler->version.str, "3.7.93215")) {
scheduler->data = &rga2e_iommu_data; 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; scheduler->data = &rga2p_iommu_data;
else rga_hw_set_issue_mask(scheduler, RGA_HW_ISSUE_DIS_AUTO_RST);
} else {
scheduler->data = &rga2e_data; scheduler->data = &rga2e_data;
}
} }
data->scheduler[data->num_of_scheduler] = scheduler; data->scheduler[data->num_of_scheduler] = scheduler;