video/rockchip: rga2: Add support for full csc (RGB2YUV/YUV2YUV).

Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
Change-Id: I72fcbc85a5bc24357d64579dd56b8a20715e59bc
This commit is contained in:
Yu Qiaowei
2021-05-31 14:41:59 +08:00
committed by Tao Huang
parent fd4c04f35d
commit 11dc8266de
4 changed files with 129 additions and 7 deletions

View File

@@ -284,6 +284,21 @@ typedef struct line_draw_t
}
line_draw_t;
/* color space convert coefficient. */
typedef struct csc_coe_t {
int16_t r_v;
int16_t g_y;
int16_t b_u;
int32_t off;
} csc_coe_t;
typedef struct full_csc_t {
unsigned char flag;
csc_coe_t coe_y;
csc_coe_t coe_u;
csc_coe_t coe_v;
} full_csc_t;
typedef struct rga_img_info_t
{
unsigned long yrgb_addr; /* yrgb mem addr */
@@ -394,6 +409,8 @@ struct rga_req {
uint8_t src_trans_mode;
uint8_t dither_mode;
full_csc_t full_csc; /* full color space convert */
};
struct rga_req_32
{
@@ -446,6 +463,8 @@ struct rga_req_32
uint8_t src_trans_mode;
uint8_t dither_mode;
full_csc_t full_csc; /* full color space convert */
};
@@ -530,13 +549,18 @@ struct rga2_req
u8 src_a_global_val; /* src global alpha value */
u8 dst_a_global_val; /* dst global alpha value */
u8 rop_mode; /* rop mode select 0 : rop2 1 : rop3 2 : rop4 */
u16 rop_code; /* rop2/3/4 code */
u8 palette_mode; /* (enum) color palatte 0/1bpp, 1/2bpp 2/4bpp 3/8bpp*/
u8 yuv2rgb_mode; /* (enum) BT.601 MPEG / BT.601 JPEG / BT.709 */
/* [1:0] src0 csc mode */
/* [3:2] dst csc mode */
/* [4] dst csc clip enable */
/* [6:5] src1 csc mdoe */
/* [7] src1 csc clip enable */
full_csc_t full_csc; /* full color space convert */
u8 endian_mode; /* 0/little endian 1/big endian */
@@ -688,6 +712,7 @@ struct rga2_reg {
struct list_head session_link;
struct list_head status_link;
uint32_t sys_reg[8];
uint32_t csc_reg[12];
uint32_t cmd_reg[32];
uint32_t *MMU_src0_base;
@@ -749,6 +774,9 @@ struct rga2_service_info {
#define RGA2_MMU_CTRL0 0x018
#define RGA2_MMU_CMD_BASE 0x01c
//Full Csc Coefficient
#define RGA2_CSC_COE_BASE 0x60
//Command code start
#define RGA2_MODE_CTRL 0x100
#define RGA_BLIT_COMPLETE_EVENT 1

View File

@@ -871,7 +871,7 @@ static struct rga2_reg * rga2_reg_init(rga2_session *session, struct rga2_req *r
}
}
if(RGA2_gen_reg_info((uint8_t *)reg->cmd_reg, req) == -1) {
if (RGA2_gen_reg_info((uint8_t *)reg->cmd_reg, (uint8_t *)reg->csc_reg, req) == -1) {
printk("gen reg info error\n");
free_page((unsigned long)reg);
@@ -934,6 +934,7 @@ static void rga2_service_session_clear(rga2_session *session)
/* Caller must hold rga_service.lock */
static void rga2_try_set_reg(void)
{
int i;
struct rga2_reg *reg ;
if (list_empty(&rga2_service.running))
@@ -958,16 +959,29 @@ static void rga2_try_set_reg(void)
/* CMD buff */
rga2_write(virt_to_phys(reg->cmd_reg), RGA2_CMD_BASE);
/* full csc reg */
for (i = 0; i < 12; i++) {
rga2_write(reg->csc_reg[i], RGA2_CSC_COE_BASE + i * 4);
}
#if RGA2_DEBUGFS
if (RGA2_TEST_REG) {
if (rga2_flag) {
int32_t i, *p;
int32_t *p;
p = rga2_service.cmd_buff;
INFO("CMD_REG\n");
for (i=0; i<8; i++)
INFO("%.8x %.8x %.8x %.8x\n",
p[0 + i * 4], p[1 + i * 4],
p[2 + i * 4], p[3 + i * 4]);
p = reg->csc_reg;
INFO("CSC_REG\n");
for (i = 0; i < 3; i++)
INFO("%.8x %.8x %.8x %.8x\n",
p[0 + i * 4], p[1 + i * 4],
p[2 + i * 4], p[3 + i * 4]);
}
}
#endif
@@ -989,7 +1003,6 @@ static void rga2_try_set_reg(void)
#if RGA2_DEBUGFS
if (RGA2_TEST_REG) {
if (rga2_flag) {
uint32_t i;
INFO("CMD_READ_BACK_REG\n");
for (i=0; i<8; i++)
INFO("%.8x %.8x %.8x %.8x\n",
@@ -997,6 +1010,14 @@ static void rga2_try_set_reg(void)
rga2_read(0x100 + i * 16 + 4),
rga2_read(0x100 + i * 16 + 8),
rga2_read(0x100 + i * 16 + 12));
INFO("CSC_READ_BACK_REG\n");
for (i = 0; i < 3; i++)
INFO("%.8x %.8x %.8x %.8x\n",
rga2_read(RGA2_CSC_COE_BASE + i * 16 + 0),
rga2_read(RGA2_CSC_COE_BASE + i * 16 + 4),
rga2_read(RGA2_CSC_COE_BASE + i * 16 + 8),
rga2_read(RGA2_CSC_COE_BASE + i * 16 + 12));
}
}

View File

@@ -476,6 +476,8 @@ static void RGA2_set_reg_dst_info(u8 *base, struct rga2_req *msg)
reg = ((reg & (~m_RGA2_DST_INFO_SW_DITHER_MODE)) | (s_RGA2_DST_INFO_SW_DITHER_MODE(msg->dither_mode)));
reg = ((reg & (~m_RGA2_DST_INFO_SW_DST_CSC_MODE)) | (s_RGA2_DST_INFO_SW_DST_CSC_MODE(msg->yuv2rgb_mode >> 2)));
reg = ((reg & (~m_RGA2_DST_INFO_SW_CSC_CLIP_MODE)) | (s_RGA2_DST_INFO_SW_CSC_CLIP_MODE(msg->yuv2rgb_mode >> 4)));
/* full csc enable */
reg = ((reg & (~m_RGA2_DST_INFO_SW_DST_CSC_MODE_2)) | (s_RGA2_DST_INFO_SW_DST_CSC_MODE_2(msg->full_csc.flag)));
/* Some older chips do not support src1 csc mode, they do not have these two registers. */
reg = ((reg & (~m_RGA2_DST_INFO_SW_SRC1_CSC_MODE)) | (s_RGA2_DST_INFO_SW_SRC1_CSC_MODE(msg->yuv2rgb_mode >> 5)));
reg = ((reg & (~m_RGA2_DST_INFO_SW_SRC1_CSC_CLIP_MODE)) | (s_RGA2_DST_INFO_SW_SRC1_CSC_CLIP_MODE(msg->yuv2rgb_mode >> 7)));
@@ -790,6 +792,56 @@ static void RGA2_set_reg_rop_info(u8 *base, struct rga2_req *msg)
}
static void RGA2_set_reg_full_csc(u8 *base, struct rga2_req *msg)
{
RK_U32 *bRGA2_DST_CSC_00;
RK_U32 *bRGA2_DST_CSC_01;
RK_U32 *bRGA2_DST_CSC_02;
RK_U32 *bRGA2_DST_CSC_OFF0;
RK_U32 *bRGA2_DST_CSC_10;
RK_U32 *bRGA2_DST_CSC_11;
RK_U32 *bRGA2_DST_CSC_12;
RK_U32 *bRGA2_DST_CSC_OFF1;
RK_U32 *bRGA2_DST_CSC_20;
RK_U32 *bRGA2_DST_CSC_21;
RK_U32 *bRGA2_DST_CSC_22;
RK_U32 *bRGA2_DST_CSC_OFF2;
bRGA2_DST_CSC_00 = (RK_U32 *)(base + RGA2_DST_CSC_00_OFFSET);
bRGA2_DST_CSC_01 = (RK_U32 *)(base + RGA2_DST_CSC_01_OFFSET);
bRGA2_DST_CSC_02 = (RK_U32 *)(base + RGA2_DST_CSC_02_OFFSET);
bRGA2_DST_CSC_OFF0 = (RK_U32 *)(base + RGA2_DST_CSC_OFF0_OFFSET);
bRGA2_DST_CSC_10 = (RK_U32 *)(base + RGA2_DST_CSC_10_OFFSET);
bRGA2_DST_CSC_11 = (RK_U32 *)(base + RGA2_DST_CSC_11_OFFSET);
bRGA2_DST_CSC_12 = (RK_U32 *)(base + RGA2_DST_CSC_12_OFFSET);
bRGA2_DST_CSC_OFF1 = (RK_U32 *)(base + RGA2_DST_CSC_OFF1_OFFSET);
bRGA2_DST_CSC_20 = (RK_U32 *)(base + RGA2_DST_CSC_20_OFFSET);
bRGA2_DST_CSC_21 = (RK_U32 *)(base + RGA2_DST_CSC_21_OFFSET);
bRGA2_DST_CSC_22 = (RK_U32 *)(base + RGA2_DST_CSC_22_OFFSET);
bRGA2_DST_CSC_OFF2 = (RK_U32 *)(base + RGA2_DST_CSC_OFF2_OFFSET);
/* full csc coefficient */
/* Y coefficient */
*bRGA2_DST_CSC_00 = msg->full_csc.coe_y.r_v;
*bRGA2_DST_CSC_01 = msg->full_csc.coe_y.g_y;
*bRGA2_DST_CSC_02 = msg->full_csc.coe_y.b_u;
*bRGA2_DST_CSC_OFF0 = msg->full_csc.coe_y.off;
/* U coefficient */
*bRGA2_DST_CSC_10 = msg->full_csc.coe_u.r_v;
*bRGA2_DST_CSC_11 = msg->full_csc.coe_u.g_y;
*bRGA2_DST_CSC_12 = msg->full_csc.coe_u.b_u;
*bRGA2_DST_CSC_OFF1 = msg->full_csc.coe_u.off;
/* V coefficient */
*bRGA2_DST_CSC_20 = msg->full_csc.coe_v.r_v;
*bRGA2_DST_CSC_21 = msg->full_csc.coe_v.g_y;
*bRGA2_DST_CSC_22 = msg->full_csc.coe_v.b_u;
*bRGA2_DST_CSC_OFF2 = msg->full_csc.coe_v.off;
}
static void RGA2_set_reg_color_palette(RK_U8 *base, struct rga2_req *msg)
{
RK_U32 *bRGA_SRC_BASE0, *bRGA_SRC_INFO, *bRGA_SRC_VIR_INFO, *bRGA_SRC_ACT_INFO, *bRGA_SRC_FG_COLOR, *bRGA_SRC_BG_COLOR;
@@ -989,9 +1041,8 @@ static void RGA2_set_mmu_info(RK_U8 *base, struct rga2_req *msg)
*bRGA_MMU_ELS_BASE = (RK_U32)(msg->mmu_info.els_base_addr) >> 4;
}
int
RGA2_gen_reg_info(RK_U8 *base , struct rga2_req *msg)
RGA2_gen_reg_info(RK_U8 *base, RK_U8 *csc_base, struct rga2_req *msg)
{
RK_U8 dst_nn_quantize_en = 0;
@@ -1011,6 +1062,10 @@ RGA2_gen_reg_info(RK_U8 *base , struct rga2_req *msg)
RGA2_set_reg_rop_info(base, msg);
}
}
if (msg->full_csc.flag) {
RGA2_set_reg_full_csc(csc_base, msg);
}
break;
case color_fill_mode :
RGA2_set_reg_color_fill(base, msg);
@@ -1195,6 +1250,7 @@ void RGA_MSG_2_RGA2_MSG(struct rga_req *req_rga, struct rga2_req *req)
req->fg_color = req_rga->fg_color;
req->bg_color = req_rga->bg_color;
memcpy(&req->gr_color, &req_rga->gr_color, sizeof(req_rga->gr_color));
memcpy(&req->full_csc, &req_rga->full_csc, sizeof(req_rga->full_csc));
req->palette_mode = req_rga->palette_mode;
req->yuv2rgb_mode = req_rga->yuv2rgb_mode;
@@ -1455,6 +1511,8 @@ void RGA_MSG_2_RGA2_MSG_32(struct rga_req_32 *req_rga, struct rga2_req *req)
req->fg_color = req_rga->fg_color;
req->bg_color = req_rga->bg_color;
memcpy(&req->gr_color, &req_rga->gr_color, sizeof(req_rga->gr_color));
memcpy(&req->full_csc, &req_rga->full_csc, sizeof(req_rga->full_csc));
req->palette_mode = req_rga->palette_mode;
req->yuv2rgb_mode = req_rga->yuv2rgb_mode;
req->endian_mode = req_rga->endian_mode;

View File

@@ -142,6 +142,7 @@
#define m_RGA2_DST_INFO_SW_DITHER_MODE ( 0x3<<14)
#define m_RGA2_DST_INFO_SW_DST_CSC_MODE ( 0x3<<16) //add
#define m_RGA2_DST_INFO_SW_CSC_CLIP_MODE ( 0x1<<18)
#define m_RGA2_DST_INFO_SW_DST_CSC_MODE_2 ( 0x1<<19) //add
#define m_RGA2_DST_INFO_SW_DST_FMT_YUV400_EN ( 0x1<<24)
#define m_RGA2_DST_INFO_SW_DST_FMT_Y4_EN ( 0x1<<25)
#define m_RGA2_DST_INFO_SW_DST_NN_QUANTIZE_EN ( 0x1<<26)
@@ -160,6 +161,7 @@
#define s_RGA2_DST_INFO_SW_DITHER_MODE(x) ( (x&0x3)<<14)
#define s_RGA2_DST_INFO_SW_DST_CSC_MODE(x) ( (x&0x3)<<16) //add
#define s_RGA2_DST_INFO_SW_CSC_CLIP_MODE(x) ( (x&0x1)<<18)
#define s_RGA2_DST_INFO_SW_DST_CSC_MODE_2(x) ( (x&0x1)<<19) //add
#define s_RGA2_DST_INFO_SW_DST_FMT_YUV400_EN(x) ( (x&0x1)<<24)
#define s_RGA2_DST_INFO_SW_DST_FMT_Y4_EN(x) ( (x&0x1)<<25)
#define s_RGA2_DST_INFO_SW_DST_NN_QUANTIZE_EN(x) ( (x&0x1)<<26)
@@ -264,6 +266,19 @@
#define RGA2_INT_OFFSET 0x10
#define RGA2_MMU_CTRL0_OFFSET 0x14
#define RGA2_MMU_CMD_BASE_OFFSET 0x18
/* dst full csc */
#define RGA2_DST_CSC_00_OFFSET 0x0
#define RGA2_DST_CSC_01_OFFSET 0x4
#define RGA2_DST_CSC_02_OFFSET 0x8
#define RGA2_DST_CSC_OFF0_OFFSET 0xc
#define RGA2_DST_CSC_10_OFFSET 0x10
#define RGA2_DST_CSC_11_OFFSET 0x14
#define RGA2_DST_CSC_12_OFFSET 0x18
#define RGA2_DST_CSC_OFF1_OFFSET 0x1c
#define RGA2_DST_CSC_20_OFFSET 0x20
#define RGA2_DST_CSC_21_OFFSET 0x24
#define RGA2_DST_CSC_22_OFFSET 0x28
#define RGA2_DST_CSC_OFF2_OFFSET 0x2c
#define RGA2_MODE_CTRL_OFFSET 0x00
#define RGA2_SRC_INFO_OFFSET 0x04
@@ -306,7 +321,7 @@
#define RGA2_MMU_DST_BASE_OFFSET 0x78
#define RGA2_MMU_ELS_BASE_OFFSET 0x7c
int RGA2_gen_reg_info(unsigned char *base, struct rga2_req *msg);
int RGA2_gen_reg_info(unsigned char *base, unsigned char *csc_base, struct rga2_req *msg);
void RGA_MSG_2_RGA2_MSG(struct rga_req *req_rga, struct rga2_req *req);
void RGA_MSG_2_RGA2_MSG_32(struct rga_req_32 *req_rga, struct rga2_req *req);