diff --git a/drivers/video/rockchip/rga3/include/rga.h b/drivers/video/rockchip/rga3/include/rga.h index 6783c06e16ad..7d99f00c6fa4 100644 --- a/drivers/video/rockchip/rga3/include/rga.h +++ b/drivers/video/rockchip/rga3/include/rga.h @@ -177,6 +177,8 @@ enum rga_surf_format { RGA_FORMAT_ABGR_5551 = 0x2e, RGA_FORMAT_ABGR_4444 = 0x2f, + RGA_FORMAT_RGBA_2BPP = 0x30, + RGA_FORMAT_UNKNOWN = 0x100, }; @@ -311,6 +313,99 @@ struct rga_mosaic_info { uint8_t mode; }; +/* MAX(min, (max - channel_value)) */ +struct rga_osd_invert_factor { + uint8_t alpha_max; + uint8_t alpha_min; + uint8_t yg_max; + uint8_t yg_min; + uint8_t crb_max; + uint8_t crb_min; +}; + +struct rga_color { + union { + struct { + uint8_t red; + uint8_t green; + uint8_t blue; + uint8_t alpha; + }; + uint32_t value; + }; +}; + +struct rga_osd_bpp2 { + uint8_t ac_swap; // ac swap flag + // 0: CA + // 1: AC + uint8_t endian_swap; // rgba2bpp endian swap + // 0: Big endian + // 1: Little endian + struct rga_color color0; + struct rga_color color1; +}; + +struct rga_osd_mode_ctrl { + uint8_t mode; // OSD cal mode: + // 0b'1: statistics mode + // 1b'1: auto inversion overlap mode + uint8_t direction_mode; // horizontal or vertical + // 0: horizontal + // 1: vertical + uint8_t width_mode; // using @fix_width or LUT width + // 0: fix width + // 1: LUT width + uint16_t block_fix_width; // OSD block fixed width + // real width = (fix_width + 1) * 2 + uint8_t block_num; // OSD block num + uint16_t flags_index; // auto invert flags index + + /* invertion config */ + uint8_t color_mode; // selete color + // 0: src1 color + // 1: config data color + uint8_t invert_flags_mode; // invert flag selete + // 0: use RAM flag + // 1: usr last result + uint8_t default_color_sel; // default color mode + // 0: default is bright + // 1: default is dark + uint8_t invert_enable; // invert channel enable + // 1 << 0: alpha enable + // 1 << 1: Y/G disable + // 1 << 3: C/RB disable + uint8_t invert_mode; // invert cal mode + // 0: normal(max-data) + // 1: swap + uint8_t invert_thresh; // if luma > thresh, osd_flag to be 1 + uint8_t unfix_index; // OSD width config index +}; + +struct rga_osd_info { + uint8_t enable; + + struct rga_osd_mode_ctrl mode_ctrl; + struct rga_osd_invert_factor cal_factor; + struct rga_osd_bpp2 bpp2_info; + + union { + struct { + uint32_t last_flags0; + uint32_t last_flags1; + }; + uint64_t last_flags; + }; + + union { + struct { + uint32_t cur_flags0; + uint32_t cur_flags1; + }; + uint64_t cur_flags; + }; +}; + struct rga_win_info_t { /* yrgb mem addr */ unsigned long yrgb_addr; @@ -492,7 +587,9 @@ struct rga_req { uint8_t uvhds_mode; uint8_t uvvds_mode; - uint8_t reservr[123]; + struct rga_osd_info osd_info; + + uint8_t reservr[75]; }; struct rga2_req { @@ -632,6 +729,8 @@ struct rga2_req { uint8_t uvhds_mode; uint8_t uvvds_mode; + + struct rga_osd_info osd_info; }; 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 682d42f8e459..964289c72ebb 100644 --- a/drivers/video/rockchip/rga3/include/rga2_reg_info.h +++ b/drivers/video/rockchip/rga3/include/rga2_reg_info.h @@ -90,7 +90,7 @@ #define m_RGA2_SRC_INFO_SW_SW_SRC_RB_SWAP (0x1 << 4) #define m_RGA2_SRC_INFO_SW_SW_SRC_ALPHA_SWAP (0x1 << 5) #define m_RGA2_SRC_INFO_SW_SW_SRC_UV_SWAP (0x1 << 6) -#define m_RGA2_SRC_INFO_SW_SW_CP_ENDAIN (0x1 << 7) +#define m_RGA2_SRC_INFO_SW_SW_CP_ENDIAN (0x1 << 7) #define m_RGA2_SRC_INFO_SW_SW_SRC_CSC_MODE (0x3 << 8) #define m_RGA2_SRC_INFO_SW_SW_SRC_ROT_MODE (0x3 << 10) #define m_RGA2_SRC_INFO_SW_SW_SRC_MIR_MODE (0x3 << 12) @@ -139,6 +139,43 @@ #define s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH(x) ((x & 0x1fff) << 0) #define s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT(x) ((x & 0x1fff) << 16) +/* RGA2_OSD_CTRL0 */ +#define m_RGA2_OSD_CTRL0_SW_OSD_MODE (0x3 << 0) +#define m_RGA2_OSD_CTRL0_SW_OSD_VER_MODE (0x1 << 2) +#define m_RGA2_OSD_CTRL0_SW_OSD_WIDTH_MODE (0x1 << 3) +#define m_RGA2_OSD_CTRL0_SW_OSD_BLK_NUM (0x1f << 4) +#define m_RGA2_OSD_CTRL0_SW_OSD_FLAGS_INDEX (0x3f << 10) +#define m_RGA2_OSD_CTRL0_SW_OSD_FIX_WIDTH (0x3f << 20) +#define m_RGA2_OSD_CTRL0_SW_OSD_2BPP_MODE (0x1 << 30) + +#define s_RGA2_OSD_CTRL0_SW_OSD_MODE(x) ((x & 0x3) << 0) +#define s_RGA2_OSD_CTRL0_SW_OSD_VER_MODE(x) ((x & 0x1) << 2) +#define s_RGA2_OSD_CTRL0_SW_OSD_WIDTH_MODE(x) ((x & 0x1) << 3) +#define s_RGA2_OSD_CTRL0_SW_OSD_BLK_NUM(x) ((x & 0x1f) << 4) +#define s_RGA2_OSD_CTRL0_SW_OSD_FLAGS_INDEX(x) ((x & 0x3f) << 10) +#define s_RGA2_OSD_CTRL0_SW_OSD_FIX_WIDTH(x) ((x & 0x3f) << 20) +#define s_RGA2_OSD_CTRL0_SW_OSD_2BPP_MODE(x) ((x & 0x1) << 30) + +/* 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) +#define m_RGA2_OSD_CTRL1_SW_OSD_DEFAULT_COLOR (0x1 << 2) +#define m_RGA2_OSD_CTRL1_SW_OSD_AUTO_INVERST_MODE (0x1 << 3) +#define m_RGA2_OSD_CTRL1_SW_OSD_THRESH (0xff << 4) +#define m_RGA2_OSD_CTRL1_SW_OSD_INVERT_A_EN (0x1 << 12) +#define m_RGA2_OSD_CTRL1_SW_OSD_INVERT_Y_DIS (0x1 << 13) +#define m_RGA2_OSD_CTRL1_SW_OSD_INVERT_C_DIS (0x1 << 14) +#define m_RGA2_OSD_CTRL1_SW_OSD_UNFIX_INDEX (0xf << 16) + +#define s_RGA2_OSD_CTRL1_SW_OSD_COLOR_SEL(x) ((x & 0x1) << 0) +#define s_RGA2_OSD_CTRL1_SW_OSD_FLAG_SEL(x) ((x & 0x1) << 1) +#define s_RGA2_OSD_CTRL1_SW_OSD_DEFAULT_COLOR(x) ((x & 0x1) << 2) +#define s_RGA2_OSD_CTRL1_SW_OSD_AUTO_INVERST_MODE(x) ((x & 0x1) << 3) +#define s_RGA2_OSD_CTRL1_SW_OSD_THRESH(x) ((x & 0xff) << 4) +#define s_RGA2_OSD_CTRL1_SW_OSD_INVERT_A_EN(x) ((x & 0x1) << 12) +#define s_RGA2_OSD_CTRL1_SW_OSD_INVERT_Y_DIS(x) ((x & 0x1) << 13) +#define s_RGA2_OSD_CTRL1_SW_OSD_INVERT_C_DIS(x) ((x & 0x1) << 14) +#define s_RGA2_OSD_CTRL1_SW_OSD_UNFIX_INDEX(x) ((x & 0xf) << 16) /* RGA_DST_INFO */ #define m_RGA2_DST_INFO_SW_DST_FMT (0xf << 0) @@ -285,8 +322,8 @@ #define RGA2_WRITE_LINE_CNT_OFFSET 0x34 #define RGA2_LINE_CNT_OFFSET 0x38 #define RGA2_PERF_CTRL0_OFFSET 0x40 -#define RGA2_OSD_CUR_FLAGS0 0x90 -#define RGA2_OSD_CUR_FLAGS1 0x9c +#define RGA2_OSD_CUR_FLAGS0_OFFSET 0x90 +#define RGA2_OSD_CUR_FLAGS1_OFFSET 0x9c /* dst full csc */ #define RGA2_DST_CSC_00_OFFSET 0x0 diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index c5c845dc9375..e90523656618 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -193,6 +193,9 @@ static void RGA2_set_mode_ctrl(u8 *base, struct rga2_req *msg) reg = ((reg & (~m_RGA2_MODE_CTRL_SW_YIN_YOUT_EN)) | (s_RGA2_MODE_CTRL_SW_YIN_YOUT_EN(msg->yin_yout_en))); + reg = ((reg & (~m_RGA2_MODE_CTRL_SW_OSD_E)) | + (s_RGA2_MODE_CTRL_SW_OSD_E(msg->osd_info.enable))); + *bRGA_MODE_CTL = reg; } @@ -519,6 +522,11 @@ static void RGA2_set_reg_src_info(u8 *base, struct rga2_req *msg) reg = ((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_UV_SWAP)) | (s_RGA2_SRC_INFO_SW_SW_SRC_UV_SWAP(src0_cbcr_swp))); + + if (msg->src1.format == RGA_FORMAT_RGBA_2BPP) + reg = ((reg & (~m_RGA2_SRC_INFO_SW_SW_CP_ENDIAN)) | + (s_RGA2_SRC_INFO_SW_SW_CP_ENDAIN(msg->osd_info.bpp2_info.endian_swap & 1))); + reg = ((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_CSC_MODE)) | (s_RGA2_SRC_INFO_SW_SW_SRC_CSC_MODE(msg->yuv2rgb_mode))); @@ -646,6 +654,7 @@ static void RGA2_set_reg_dst_info(u8 *base, struct rga2_req *msg) u32 reg = 0; u8 spw, dpw; + u8 bbp_shift = 0; u32 s_stride, d_stride; u32 x_mirr, y_mirr, rot_90_flag; u32 yrgb_addr, u_addr, v_addr, s_yrgb_addr; @@ -777,6 +786,13 @@ static void RGA2_set_reg_dst_info(u8 *base, struct rga2_req *msg) src1_alpha_swp = 1; src1_rb_swp = 0x1; break; + case RGA_FORMAT_RGBA_2BPP: + src1_format = 0x0; + spw = 1; + /* 2BPP = 8 >> 2 = 2bit */ + bbp_shift = 2; + src1_alpha_swp = msg->osd_info.bpp2_info.ac_swap; + break; default: spw = 4; break; @@ -1054,7 +1070,7 @@ static void RGA2_set_reg_dst_info(u8 *base, struct rga2_req *msg) *bRGA_DST_INFO = reg; - s_stride = ((msg->src1.vir_w * spw + 3) & ~3) >> 2; + s_stride = (((msg->src1.vir_w * spw >> bbp_shift) + 3) & ~3) >> 2; d_stride = ((msg->dst.vir_w * dpw + 3) & ~3) >> 2; if (dst_fmt_y4_en) { @@ -1122,7 +1138,7 @@ static void RGA2_set_reg_dst_info(u8 *base, struct rga2_req *msg) s_yrgb_addr = (u32) msg->src1.yrgb_addr + (msg->src1.y_offset * s_stride) + - (msg->src1.x_offset * spw); + (msg->src1.x_offset * spw >> bbp_shift); *bRGA_SRC_BASE3 = s_yrgb_addr; @@ -1403,6 +1419,96 @@ static void RGA_set_reg_mosaic(u8 *base, struct rga2_req *msg) *bRGA_MOSAIC_MODE = (u32)(msg->mosaic_info.mode & 0x7); } +static void RGA2_set_reg_osd(u8 *base, struct rga2_req *msg) +{ + u32 *bRGA_OSD_CTRL0; + u32 *bRGA_OSD_CTRL1; + u32 *bRGA_OSD_INVERTSION_CAL0; + u32 *bRGA_OSD_INVERTSION_CAL1; + u32 *bRGA_OSD_COLOR0; + u32 *bRGA_OSD_COLOR1; + u32 *bRGA_OSD_LAST_FLAGS0; + u32 *bRGA_OSD_LAST_FLAGS1; + u32 reg; + u8 rgba2bpp_en = 0; + u8 block_num; + u16 fix_width; + + + bRGA_OSD_CTRL0 = (u32 *)(base + RGA2_OSD_CTRL0_OFFSET); + bRGA_OSD_CTRL1 = (u32 *)(base + RGA2_OSD_CTRL1_OFFSET); + bRGA_OSD_INVERTSION_CAL0 = (u32 *)(base + RGA2_OSD_INVERTSION_CAL0_OFFSET); + bRGA_OSD_INVERTSION_CAL1 = (u32 *)(base + RGA2_OSD_INVERTSION_CAL1_OFFSET); + bRGA_OSD_COLOR0 = (u32 *)(base + RGA2_OSD_COLOR0_OFFSET); + bRGA_OSD_COLOR1 = (u32 *)(base + RGA2_OSD_COLOR1_OFFSET); + bRGA_OSD_LAST_FLAGS0 = (u32 *)(base + RGA2_OSD_LAST_FLAGS0_OFFSET); + bRGA_OSD_LAST_FLAGS1 = (u32 *)(base + RGA2_OSD_LAST_FLAGS1_OFFSET); + + /* To save the number of register bits. */ + fix_width = msg->osd_info.mode_ctrl.block_fix_width / 2 - 1; + + /* The register is '0' as the first. */ + block_num = msg->osd_info.mode_ctrl.block_num - 1; + + reg = 0; + reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_MODE)) | + (s_RGA2_OSD_CTRL0_SW_OSD_MODE(msg->osd_info.mode_ctrl.mode))); + reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_VER_MODE)) | + (s_RGA2_OSD_CTRL0_SW_OSD_VER_MODE(msg->osd_info.mode_ctrl.direction_mode))); + reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_WIDTH_MODE)) | + (s_RGA2_OSD_CTRL0_SW_OSD_WIDTH_MODE(msg->osd_info.mode_ctrl.width_mode))); + reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_BLK_NUM)) | + (s_RGA2_OSD_CTRL0_SW_OSD_BLK_NUM(block_num))); + reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_FLAGS_INDEX)) | + (s_RGA2_OSD_CTRL0_SW_OSD_FLAGS_INDEX(msg->osd_info.mode_ctrl.flags_index))); + reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_FIX_WIDTH)) | + (s_RGA2_OSD_CTRL0_SW_OSD_FIX_WIDTH(fix_width))); + reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_2BPP_MODE)) | + (s_RGA2_OSD_CTRL0_SW_OSD_2BPP_MODE(rgba2bpp_en))); + *bRGA_OSD_CTRL0 = reg; + + reg = 0; + reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_COLOR_SEL)) | + (s_RGA2_OSD_CTRL1_SW_OSD_COLOR_SEL(msg->osd_info.mode_ctrl.color_mode))); + reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_FLAG_SEL)) | + (s_RGA2_OSD_CTRL1_SW_OSD_FLAG_SEL(msg->osd_info.mode_ctrl.invert_flags_mode))); + reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_DEFAULT_COLOR)) | + (s_RGA2_OSD_CTRL1_SW_OSD_DEFAULT_COLOR(msg->osd_info.mode_ctrl.default_color_sel))); + reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_AUTO_INVERST_MODE)) | + (s_RGA2_OSD_CTRL1_SW_OSD_AUTO_INVERST_MODE(msg->osd_info.mode_ctrl.invert_mode))); + reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_THRESH)) | + (s_RGA2_OSD_CTRL1_SW_OSD_THRESH(msg->osd_info.mode_ctrl.invert_thresh))); + reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_INVERT_A_EN)) | + (s_RGA2_OSD_CTRL1_SW_OSD_INVERT_A_EN(msg->osd_info.mode_ctrl.invert_enable))); + reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_INVERT_Y_DIS)) | + (s_RGA2_OSD_CTRL1_SW_OSD_INVERT_Y_DIS(msg->osd_info.mode_ctrl.invert_enable >> 1))); + reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_INVERT_C_DIS)) | + (s_RGA2_OSD_CTRL1_SW_OSD_INVERT_C_DIS(msg->osd_info.mode_ctrl.invert_enable >> 2))); + reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_UNFIX_INDEX)) | + (s_RGA2_OSD_CTRL1_SW_OSD_UNFIX_INDEX(msg->osd_info.mode_ctrl.unfix_index))); + *bRGA_OSD_CTRL1 = reg; + + *bRGA_OSD_INVERTSION_CAL0 = ((msg->osd_info.cal_factor.crb_max) << 24) | + ((msg->osd_info.cal_factor.crb_min) << 16) | + ((msg->osd_info.cal_factor.yg_max) << 8) | + ((msg->osd_info.cal_factor.yg_min) << 0); + *bRGA_OSD_INVERTSION_CAL1 = ((msg->osd_info.cal_factor.alpha_max) << 8) | + ((msg->osd_info.cal_factor.alpha_min) << 0); + + *bRGA_OSD_LAST_FLAGS0 = (msg->osd_info.last_flags0); + *bRGA_OSD_LAST_FLAGS1 = (msg->osd_info.last_flags1); + + if (msg->osd_info.mode_ctrl.color_mode == 1) { + *bRGA_OSD_COLOR0 = (msg->osd_info.bpp2_info.color0.value & 0xffffff); + *bRGA_OSD_COLOR1 = (msg->osd_info.bpp2_info.color1.value & 0xffffff); + } + + if (rgba2bpp_en) { + *bRGA_OSD_COLOR0 = msg->osd_info.bpp2_info.color0.value; + *bRGA_OSD_COLOR1 = msg->osd_info.bpp2_info.color1.value; + } +} + static void RGA2_set_reg_full_csc(u8 *base, struct rga2_req *msg) { u32 *bRGA2_DST_CSC_00; @@ -1494,7 +1600,7 @@ static void RGA2_set_reg_color_palette(u8 *base, struct rga2_req *msg) ((reg & (~m_RGA2_SRC_INFO_SW_SRC_FMT)) | (s_RGA2_SRC_INFO_SW_SRC_FMT((msg->palette_mode | 0xc)))); reg = - ((reg & (~m_RGA2_SRC_INFO_SW_SW_CP_ENDAIN)) | + ((reg & (~m_RGA2_SRC_INFO_SW_SW_CP_ENDIAN)) | (s_RGA2_SRC_INFO_SW_SW_CP_ENDAIN(msg->endian_mode & 1))); *bRGA_SRC_VIR_INFO = src_stride >> 2; *bRGA_SRC_ACT_INFO = @@ -1677,6 +1783,8 @@ int rga2_gen_reg_info(u8 *base, u8 *csc_base, struct rga2_req *msg) } if (msg->mosaic_info.enable) RGA_set_reg_mosaic(base, msg); + if (msg->osd_info.enable) + RGA2_set_reg_osd(base, msg); break; case COLOR_FILL_MODE: @@ -1849,6 +1957,8 @@ static void rga_cmd_to_rga2_cmd(struct rga_scheduler_t *scheduler, req->uvhds_mode = req_rga->uvhds_mode; req->uvvds_mode = req_rga->uvvds_mode; + memcpy(&req->osd_info, &req_rga->osd_info, sizeof(req_rga->osd_info)); + if (((req_rga->alpha_rop_flag) & 1)) { if ((req_rga->alpha_rop_flag >> 3) & 1) { /* porter duff alpha enable */ diff --git a/drivers/video/rockchip/rga3/rga_drv.c b/drivers/video/rockchip/rga3/rga_drv.c index be9ace18251e..6507c13be577 100644 --- a/drivers/video/rockchip/rga3/rga_drv.c +++ b/drivers/video/rockchip/rga3/rga_drv.c @@ -792,6 +792,11 @@ static irqreturn_t rga2_irq_thread(int irq, void *data) rga_read(RGA2_INT, rga_scheduler), rga_read(RGA2_STATUS, rga_scheduler)); + job->rga_command_base.osd_info.cur_flags0 = rga_read(RGA2_OSD_CUR_FLAGS0_OFFSET, + rga_scheduler); + job->rga_command_base.osd_info.cur_flags1 = rga_read(RGA2_OSD_CUR_FLAGS1_OFFSET, + rga_scheduler); + rga_job_done(rga_scheduler, 0); return IRQ_HANDLED;