video: rockchip: rga3: RGA2 support OSD

Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
Change-Id: Ib649bbdf4b7b41b9bb93323b9004ca5e17577ec5
This commit is contained in:
Yu Qiaowei
2022-03-02 16:14:40 +08:00
committed by Tao Huang
parent 4bb8b324f2
commit 43375c377b
4 changed files with 258 additions and 7 deletions

View File

@@ -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 {

View File

@@ -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

View File

@@ -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 */

View File

@@ -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;