diff --git a/drivers/video/rockchip/rga3/include/rga.h b/drivers/video/rockchip/rga3/include/rga.h index 7f8e5e6c01bc..91efb7b8a9a2 100644 --- a/drivers/video/rockchip/rga3/include/rga.h +++ b/drivers/video/rockchip/rga3/include/rga.h @@ -421,6 +421,11 @@ struct rga_mosaic_info { uint8_t mode; }; +struct rga_gauss_config { + uint32_t size; + uint64_t coe_ptr; +}; + /* MAX(min, (max - channel_value)) */ struct rga_osd_invert_factor { uint8_t alpha_max; @@ -745,7 +750,9 @@ struct rga_req { struct rga_rgba5551_alpha rgba5551_alpha; - uint8_t reservr[39]; + struct rga_gauss_config gauss_config; + + uint8_t reservr[27]; }; struct rga_alpha_config { @@ -878,6 +885,8 @@ struct rga2_req { struct rga_iommu_prefetch iommu_prefetch; struct rga_rgba5551_alpha rgba5551_alpha; + + struct rga_gauss_config gauss_config; }; struct rga3_req { diff --git a/drivers/video/rockchip/rga3/include/rga2_reg_info.h b/drivers/video/rockchip/rga3/include/rga2_reg_info.h index dcb4da13cd79..cca8a20b16b2 100644 --- a/drivers/video/rockchip/rga3/include/rga2_reg_info.h +++ b/drivers/video/rockchip/rga3/include/rga2_reg_info.h @@ -61,6 +61,7 @@ #define RGA2_OSD_CTRL1_OFFSET 0x024 // repeat #define RGA2_SRC_BG_COLOR_OFFSET 0x028 #define RGA2_OSD_COLOR0_OFFSET 0x028 // repeat +#define RGA2_GAUSS_COE_OFFSET 0x028 // repeat #define RGA2_SRC_FG_COLOR_OFFSET 0x02c #define RGA2_OSD_COLOR1_OFFSET 0x02c // repeat #define RGA2_SRC_TR_COLOR0_OFFSET 0x030 @@ -209,6 +210,7 @@ #define m_RGA2_MODE_CTRL_SW_TILE4x4_IN_EN (0x1 << 12) #define m_RGA2_MODE_CTRL_SW_TILE4x4_OUT_EN (0x1 << 13) #define m_RGA2_MODE_CTRL_SW_FBC_IN_EN (0x1 << 16) +#define m_RGA2_MODE_CTRL_SW_SRC_GAUSS_EN (0x1 << 17) #define m_RGA2_MODE_CTRL_SW_FBC_BSP_DIS (0x1 << 18) #define m_RGA2_MODE_CTRL_SW_TABLE_PRE_FETCH_DIS (0x1 << 19) #define m_RGA2_MODE_CTRL_SW_AXI_WR128_DIS (0x1 << 20) @@ -226,6 +228,7 @@ #define s_RGA2_MODE_CTRL_SW_TILE4x4_IN_EN(x) ((x & 0x1) << 12) #define s_RGA2_MODE_CTRL_SW_TILE4x4_OUT_EN(x) ((x & 0x1) << 13) #define s_RGA2_MODE_CTRL_SW_FBC_IN_EN(x) ((x & 0x1) << 16) +#define s_RGA2_MODE_CTRL_SW_SRC_GAUSS_EN(x) ((x & 0x1) << 17) #define s_RGA2_MODE_CTRL_SW_FBC_BSP_DIS(x) ((x & 0x1) << 18) #define s_RGA2_MODE_CTRL_SW_TABLE_PRE_FETCH_DIS(x) ((x & 0x1) << 19) #define s_RGA2_MODE_CTRL_SW_AXI_WR128_DIS(x) ((x & 0x1) << 20) @@ -312,6 +315,15 @@ #define s_RGA2_OSD_CTRL0_SW_OSD_FIX_WIDTH(x) ((x & 0x3ff) << 20) #define s_RGA2_OSD_CTRL0_SW_OSD_2BPP_MODE(x) ((x & 0x1) << 30) +/* RGA2_GAUSS_COE */ +#define m_RGA2_GAUSS_COE_SW_COE0 (0x3f << 0) +#define m_RGA2_GAUSS_COE_SW_COE1 (0x3f << 8) +#define m_RGA2_GAUSS_COE_SW_COE2 (0xff << 16) + +#define s_RGA2_GAUSS_COE_SW_COE0(x) ((x & 0x3f) << 0) +#define s_RGA2_GAUSS_COE_SW_COE1(x) ((x & 0x3f) << 8) +#define s_RGA2_GAUSS_COE_SW_COE2(x) ((x & 0xff) << 16) + /* RGA2_OSD_CTRL1 */ #define m_RGA2_OSD_CTRL1_SW_OSD_COLOR_SEL (0x1 << 0) #define m_RGA2_OSD_CTRL1_SW_OSD_FLAG_SEL (0x1 << 1) diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index 531401e45054..5995e60879f0 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -225,6 +225,10 @@ static void RGA2_set_mode_ctrl(u8 *base, struct rga2_req *msg) reg = ((reg & (~m_RGA2_MODE_CTRL_SW_OSD_E)) | (s_RGA2_MODE_CTRL_SW_OSD_E(msg->osd_info.enable))); + if (msg->gauss_config.size > 0) + reg = ((reg & (~m_RGA2_MODE_CTRL_SW_SRC_GAUSS_EN)) | + (s_RGA2_MODE_CTRL_SW_SRC_GAUSS_EN(1))); + *bRGA_MODE_CTL = reg; } @@ -1905,6 +1909,50 @@ static void RGA_set_reg_mosaic(u8 *base, struct rga2_req *msg) *bRGA_MOSAIC_MODE = (u32)(msg->mosaic_info.mode & 0x7); } +static int RGA_set_reg_gauss(u8 *base, struct rga2_req *msg) +{ + uint32_t *bRGA_GAUSS_COE; + uint32_t reg = 0; + uint32_t *coe; + + bRGA_GAUSS_COE = (u32 *)(base + RGA2_GAUSS_COE_OFFSET); + + if (msg->gauss_config.size != 3) { + pr_err("Gaussian blur only support 3x3\n"); + return -EINVAL; + } + + coe = kmalloc(sizeof(uint32_t) * msg->gauss_config.size, GFP_KERNEL); + if (coe == NULL) { + pr_err("Gaussian blur alloc coe buffer error!\n"); + return -ENOMEM; + } + + if (unlikely(copy_from_user(coe, + u64_to_user_ptr(msg->gauss_config.coe_ptr), + sizeof(uint32_t) * msg->gauss_config.size))) { + pr_err("Gaussian blur coe copy_from_user failed\n"); + + kfree(coe); + return -EFAULT; + } + + reg = ((reg & (~m_RGA2_GAUSS_COE_SW_COE0)) | + (s_RGA2_GAUSS_COE_SW_COE0(coe[0]))); + + reg = ((reg & (~m_RGA2_GAUSS_COE_SW_COE1)) | + (s_RGA2_GAUSS_COE_SW_COE1(coe[1]))); + + reg = ((reg & (~m_RGA2_GAUSS_COE_SW_COE2)) | + (s_RGA2_GAUSS_COE_SW_COE2(coe[2]))); + + *bRGA_GAUSS_COE = reg; + + kfree(coe); + + return 0; +} + static void RGA2_set_reg_osd(u8 *base, struct rga2_req *msg) { u32 *bRGA_OSD_CTRL0; @@ -2213,6 +2261,7 @@ static void RGA2_set_mmu_reg_info(struct rga_scheduler_t *scheduler, u8 *base, s static int rga2_gen_reg_info(struct rga_scheduler_t *scheduler, u8 *base, struct rga2_req *msg) { + int ret; u8 dst_nn_quantize_en = 0; RGA2_set_mode_ctrl(base, msg); @@ -2236,6 +2285,11 @@ static int rga2_gen_reg_info(struct rga_scheduler_t *scheduler, u8 *base, struct RGA_set_reg_mosaic(base, msg); if (msg->osd_info.enable) RGA2_set_reg_osd(base, msg); + if (msg->gauss_config.size > 0) { + ret = RGA_set_reg_gauss(base, msg); + if (ret < 0) + return ret; + } break; case COLOR_FILL_MODE: @@ -2266,7 +2320,7 @@ static int rga2_gen_reg_info(struct rga_scheduler_t *scheduler, u8 *base, struct break; default: pr_err("ERROR msg render mode %d\n", msg->render_mode); - break; + return -EINVAL; } RGA2_set_mmu_reg_info(scheduler, base, msg); @@ -2428,6 +2482,8 @@ static void rga_cmd_to_rga2_cmd(struct rga_scheduler_t *scheduler, /* RGA2 1106 add */ memcpy(&req->mosaic_info, &req_rga->mosaic_info, sizeof(req_rga->mosaic_info)); + memcpy(&req->gauss_config, &req_rga->gauss_config, sizeof(req_rga->gauss_config)); + if ((scheduler->data->feature & RGA_YIN_YOUT) && rga_is_only_y_format(req->src.format) && rga_is_only_y_format(req->dst.format)) @@ -2767,7 +2823,8 @@ static int rga2_init_reg(struct rga_job *job) if (scheduler->data->mmu == RGA_IOMMU) req.CMD_fin_int_enable = 1; - if (rga2_gen_reg_info(scheduler, (uint8_t *)job->cmd_buf->vaddr, &req) == -1) { + ret = rga2_gen_reg_info(scheduler, (uint8_t *)job->cmd_buf->vaddr, &req); + if (ret < 0) { pr_err("gen reg info error\n"); return -EINVAL; }