From 11dc8266de91c6887384208d5fbdbf274f7fad7d Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Mon, 31 May 2021 14:41:59 +0800 Subject: [PATCH] video/rockchip: rga2: Add support for full csc (RGB2YUV/YUV2YUV). Signed-off-by: Yu Qiaowei Change-Id: I72fcbc85a5bc24357d64579dd56b8a20715e59bc --- drivers/video/rockchip/rga2/rga2.h | 30 +++++++++- drivers/video/rockchip/rga2/rga2_drv.c | 27 ++++++++- drivers/video/rockchip/rga2/rga2_reg_info.c | 62 ++++++++++++++++++++- drivers/video/rockchip/rga2/rga2_reg_info.h | 17 +++++- 4 files changed, 129 insertions(+), 7 deletions(-) diff --git a/drivers/video/rockchip/rga2/rga2.h b/drivers/video/rockchip/rga2/rga2.h index 01b461233d72..9fe990a1ac9e 100644 --- a/drivers/video/rockchip/rga2/rga2.h +++ b/drivers/video/rockchip/rga2/rga2.h @@ -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 diff --git a/drivers/video/rockchip/rga2/rga2_drv.c b/drivers/video/rockchip/rga2/rga2_drv.c index a86f0d4ef893..b635f23688ea 100644 --- a/drivers/video/rockchip/rga2/rga2_drv.c +++ b/drivers/video/rockchip/rga2/rga2_drv.c @@ -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)); } } diff --git a/drivers/video/rockchip/rga2/rga2_reg_info.c b/drivers/video/rockchip/rga2/rga2_reg_info.c index 1514c92ab5c4..51231e80d9cb 100644 --- a/drivers/video/rockchip/rga2/rga2_reg_info.c +++ b/drivers/video/rockchip/rga2/rga2_reg_info.c @@ -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; diff --git a/drivers/video/rockchip/rga2/rga2_reg_info.h b/drivers/video/rockchip/rga2/rga2_reg_info.h index 3f51652bbde8..7aaac7d3502b 100644 --- a/drivers/video/rockchip/rga2/rga2_reg_info.h +++ b/drivers/video/rockchip/rga2/rga2_reg_info.h @@ -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);