From 51e65247a4ec40f2669aa61f8abaa5d85c76fcbb Mon Sep 17 00:00:00 2001 From: Zhiqin Wei Date: Sun, 12 Jun 2016 18:17:47 +0800 Subject: [PATCH] rockchip/rga: add rga support yuv 10 bit Change-Id: Id7bd3ea75831b671f9739337c457f59c38fde4c3 Signed-off-by: Zhiqin Wei --- drivers/video/rockchip/rga/rga.h | 2 + drivers/video/rockchip/rga2/rga2.h | 4 + drivers/video/rockchip/rga2/rga2_drv.c | 196 +++++++++++++------- drivers/video/rockchip/rga2/rga2_mmu_info.c | 12 ++ drivers/video/rockchip/rga2/rga2_reg_info.c | 21 ++- drivers/video/rockchip/rga2/rga2_reg_info.h | 7 +- 6 files changed, 168 insertions(+), 74 deletions(-) diff --git a/drivers/video/rockchip/rga/rga.h b/drivers/video/rockchip/rga/rga.h index 0a66dbe5996d..454986e07e8e 100755 --- a/drivers/video/rockchip/rga/rga.h +++ b/drivers/video/rockchip/rga/rga.h @@ -112,6 +112,8 @@ enum RK_FORMAT_BPP2 = 0x11, RK_FORMAT_BPP4 = 0x12, RK_FORMAT_BPP8 = 0x13, + RK_FORMAT_YCbCr_420_SP_10B = 0x20, + RK_FORMAT_YCrCb_420_SP_10B = 0x21, }; diff --git a/drivers/video/rockchip/rga2/rga2.h b/drivers/video/rockchip/rga2/rga2.h index 48ed517c20f9..5c51f92220c9 100755 --- a/drivers/video/rockchip/rga2/rga2.h +++ b/drivers/video/rockchip/rga2/rga2.h @@ -95,6 +95,10 @@ enum RGA2_FORMAT_YCrCb_422_P = 0x15, RGA2_FORMAT_YCrCb_420_SP = 0x16, RGA2_FORMAT_YCrCb_420_P = 0x17, + RGA2_FORMAT_YCbCr_420_SP_10B = 0x20, + RGA2_FORMAT_YCrCb_420_SP_10B = 0x21, + RGA2_FORMAT_YCbCr_422_SP_10B = 0x22, + RGA2_FORMAT_YCrCb_422_SP_10B = 0x23, }; typedef struct mdp_img diff --git a/drivers/video/rockchip/rga2/rga2_drv.c b/drivers/video/rockchip/rga2/rga2_drv.c index 26423579e440..34f0c6085fbc 100644 --- a/drivers/video/rockchip/rga2/rga2_drv.c +++ b/drivers/video/rockchip/rga2/rga2_drv.c @@ -602,91 +602,116 @@ static int rga2_convert_dma_buf(struct rga2_req *req) ion_phys_addr_t phy_addr; size_t len; int ret; + uint32_t src_vir_w, dst_vir_w; + + src_vir_w = req->src.vir_w; + dst_vir_w = req->dst.vir_w; req->sg_src0 = NULL; req->sg_src1 = NULL; req->sg_dst = NULL; req->sg_els = NULL; - if((int)req->src.yrgb_addr > 0) { - hdl = ion_import_dma_buf(rga2_drvdata->ion_client, req->src.yrgb_addr); + if ((int)req->src.yrgb_addr > 0) { + hdl = ion_import_dma_buf(rga2_drvdata->ion_client, + req->src.yrgb_addr); if (IS_ERR(hdl)) { ret = PTR_ERR(hdl); printk("RGA2 SRC ERROR ion buf handle\n"); return ret; } if (req->mmu_info.src0_mmu_flag) { - req->sg_src0 = ion_sg_table(rga2_drvdata->ion_client, hdl); + req->sg_src0 = ion_sg_table(rga2_drvdata->ion_client, + hdl); req->src.yrgb_addr = req->src.uv_addr; - req->src.uv_addr = req->src.yrgb_addr + (req->src.vir_w * req->src.vir_h); - req->src.v_addr = req->src.uv_addr + (req->src.vir_w * req->src.vir_h)/4; - } - else { - ion_phys(rga2_drvdata->ion_client, hdl, &phy_addr, &len); + req->src.uv_addr = req->src.yrgb_addr + + (src_vir_w * req->src.vir_h); + req->src.v_addr = req->src.uv_addr + + (src_vir_w * req->src.vir_h) / 4; + } else { + ion_phys(rga2_drvdata->ion_client, hdl, &phy_addr, + &len); req->src.yrgb_addr = phy_addr; - req->src.uv_addr = req->src.yrgb_addr + (req->src.vir_w * req->src.vir_h); - req->src.v_addr = req->src.uv_addr + (req->src.vir_w * req->src.vir_h)/4; + req->src.uv_addr = req->src.yrgb_addr + + (src_vir_w * req->src.vir_h); + req->src.v_addr = req->src.uv_addr + + (src_vir_w * req->src.vir_h) / 4; } ion_free(rga2_drvdata->ion_client, hdl); - } - else { + } else { req->src.yrgb_addr = req->src.uv_addr; - req->src.uv_addr = req->src.yrgb_addr + (req->src.vir_w * req->src.vir_h); - req->src.v_addr = req->src.uv_addr + (req->src.vir_w * req->src.vir_h)/4; + req->src.uv_addr = req->src.yrgb_addr + + (src_vir_w * req->src.vir_h); + req->src.v_addr = req->src.uv_addr + + (src_vir_w * req->src.vir_h) / 4; } - if((int)req->dst.yrgb_addr > 0) { - hdl = ion_import_dma_buf(rga2_drvdata->ion_client, req->dst.yrgb_addr); + if ((int)req->dst.yrgb_addr > 0) { + hdl = ion_import_dma_buf(rga2_drvdata->ion_client, + req->dst.yrgb_addr); if (IS_ERR(hdl)) { ret = PTR_ERR(hdl); printk("RGA2 DST ERROR ion buf handle\n"); return ret; } if (req->mmu_info.dst_mmu_flag) { - req->sg_dst = ion_sg_table(rga2_drvdata->ion_client, hdl); + req->sg_dst = ion_sg_table(rga2_drvdata->ion_client, + hdl); req->dst.yrgb_addr = req->dst.uv_addr; - req->dst.uv_addr = req->dst.yrgb_addr + (req->dst.vir_w * req->dst.vir_h); - req->dst.v_addr = req->dst.uv_addr + (req->dst.vir_w * req->dst.vir_h)/4; - } - else { - ion_phys(rga2_drvdata->ion_client, hdl, &phy_addr, &len); + req->dst.uv_addr = req->dst.yrgb_addr + + (dst_vir_w * req->dst.vir_h); + req->dst.v_addr = req->dst.uv_addr + + (dst_vir_w * req->dst.vir_h) / 4; + } else { + ion_phys(rga2_drvdata->ion_client, hdl, &phy_addr, + &len); req->dst.yrgb_addr = phy_addr; - req->dst.uv_addr = req->dst.yrgb_addr + (req->dst.vir_w * req->dst.vir_h); - req->dst.v_addr = req->dst.uv_addr + (req->dst.vir_w * req->dst.vir_h)/4; + req->dst.uv_addr = req->dst.yrgb_addr + + (dst_vir_w * req->dst.vir_h); + req->dst.v_addr = req->dst.uv_addr + + (dst_vir_w * req->dst.vir_h) / 4; } ion_free(rga2_drvdata->ion_client, hdl); - } - else { + } else { req->dst.yrgb_addr = req->dst.uv_addr; - req->dst.uv_addr = req->dst.yrgb_addr + (req->dst.vir_w * req->dst.vir_h); - req->dst.v_addr = req->dst.uv_addr + (req->dst.vir_w * req->dst.vir_h)/4; + req->dst.uv_addr = req->dst.yrgb_addr + + (dst_vir_w * req->dst.vir_h); + req->dst.v_addr = req->dst.uv_addr + + (dst_vir_w * req->dst.vir_h) / 4; } - if((int)req->src1.yrgb_addr > 0) { - hdl = ion_import_dma_buf(rga2_drvdata->ion_client, req->src1.yrgb_addr); + if ((int)req->src1.yrgb_addr > 0) { + hdl = ion_import_dma_buf(rga2_drvdata->ion_client, + req->src1.yrgb_addr); if (IS_ERR(hdl)) { ret = PTR_ERR(hdl); printk("RGA2 ERROR ion buf handle\n"); return ret; } if (req->mmu_info.dst_mmu_flag) { - req->sg_src1 = ion_sg_table(rga2_drvdata->ion_client, hdl); - req->src1.yrgb_addr = 0; - req->src1.uv_addr = req->dst.yrgb_addr + (req->dst.vir_w * req->dst.vir_h); - req->src1.v_addr = req->dst.uv_addr + (req->dst.vir_w * req->dst.vir_h)/4; - } - else { - ion_phys(rga2_drvdata->ion_client, hdl, &phy_addr, &len); + req->sg_src1 = ion_sg_table(rga2_drvdata->ion_client, + hdl); + req->src1.yrgb_addr = req->src1.uv_addr; + req->src1.uv_addr = req->src1.yrgb_addr + + (req->src1.vir_w * req->src1.vir_h); + req->src1.v_addr = req->src1.uv_addr + + (req->src1.vir_w * req->src1.vir_h) / 4; + } else { + ion_phys(rga2_drvdata->ion_client, hdl, &phy_addr, + &len); req->src1.yrgb_addr = phy_addr; - req->src1.uv_addr = req->dst.yrgb_addr + (req->dst.vir_w * req->dst.vir_h); - req->src1.v_addr = req->dst.uv_addr + (req->dst.vir_w * req->dst.vir_h)/4; + req->src1.uv_addr = req->src1.yrgb_addr + + (req->src1.vir_w * req->src1.vir_h); + req->src1.v_addr = req->src1.uv_addr + + (req->src1.vir_w * req->src1.vir_h) / 4; } ion_free(rga2_drvdata->ion_client, hdl); - } - else { - req->src1.yrgb_addr = req->dst.uv_addr; - req->src1.uv_addr = req->dst.yrgb_addr + (req->dst.vir_w * req->dst.vir_h); - req->src1.v_addr = req->dst.uv_addr + (req->dst.vir_w * req->dst.vir_h)/4; + } else { + req->src1.yrgb_addr = req->src1.uv_addr; + req->src1.uv_addr = req->src1.yrgb_addr + + (req->src1.vir_w * req->src1.vir_h); + req->src1.v_addr = req->src1.uv_addr + + (req->src1.vir_w * req->src1.vir_h) / 4; } return 0; @@ -1320,8 +1345,8 @@ static int __init rga2_init(void) rga2_mmu_buf.pages = kmalloc(32768 * sizeof(struct page *), GFP_KERNEL); - if ((ret = platform_driver_register(&rga2_driver)) != 0) - { + ret = platform_driver_register(&rga2_driver); + if (ret != 0) { printk(KERN_ERR "Platform device register failed (%d).\n", ret); return ret; } @@ -1369,8 +1394,6 @@ void rga2_test_0(void) struct rga2_req req; rga2_session session; unsigned int *src, *dst; - uint32_t i, j; - uint32_t *dst0; session.pid = current->pid; INIT_LIST_HEAD(&session.waiting); @@ -1381,9 +1404,6 @@ void rga2_test_0(void) list_add_tail(&session.list_session, &rga2_service.session); atomic_set(&session.task_running, 0); atomic_set(&session.num_done, 0); - //file->private_data = (void *)session; - - //fb = rk_get_fb(0); memset(&req, 0, sizeof(struct rga2_req)); src = kmalloc(800*480*4, GFP_KERNEL); @@ -1393,22 +1413,18 @@ void rga2_test_0(void) printk("************ RGA2_TEST ************\n"); printk("********************************\n\n"); - memset(src, 0x80, 800*480*4); - memset(dst, 0x0, 800*480*4); - - //dmac_flush_range(&src, &src[800*480*4]); - //outer_flush_range(virt_to_phys(&src),virt_to_phys(&src[800*480*4])); - +#if 1 + memset(src, 0x80, 800 * 480 * 4); + memset(dst, 0xcc, 800 * 480 * 4); +#endif #if 0 - memset(src_buf, 0x80, 800*480*4); - memset(dst_buf, 0xcc, 800*480*4); + dmac_flush_range(src, &src[800 * 480]); + outer_flush_range(virt_to_phys(src), virt_to_phys(&src[800 * 480])); - dmac_flush_range(&dst_buf[0], &dst_buf[800*480]); - outer_flush_range(virt_to_phys(&dst_buf[0]),virt_to_phys(&dst_buf[800*480])); + dmac_flush_range(dst, &dst[800 * 480]); + outer_flush_range(virt_to_phys(dst), virt_to_phys(&dst[800 * 480])); #endif - dst0 = (uint32_t *)&dst; - i = j = 0; #if 0 req.pat.act_w = 16; req.pat.act_h = 16; @@ -1418,16 +1434,39 @@ void rga2_test_0(void) req.render_mode = 0; rga2_blit_sync(&session, &req); #endif - - req.src.act_w = 320; + { + uint32_t i, j; + uint8_t *sp; + + sp = (uint8_t *)src; + for (j = 0; j < 240; j++) { + sp = (uint8_t *)src + j * 320 * 10 / 8; + for (i = 0; i < 320; i++) { + if ((i & 3) == 0) { + sp[i * 5 / 4] = 0; + sp[i * 5 / 4+1] = 0x1; + } else if ((i & 3) == 1) { + sp[i * 5 / 4+1] = 0x4; + } else if ((i & 3) == 2) { + sp[i * 5 / 4+1] = 0x10; + } else if ((i & 3) == 3) { + sp[i * 5 / 4+1] = 0x40; + } + } + } + sp = (uint8_t *)src; + for (j = 0; j < 100; j++) + printk("src %.2x\n", sp[j]); + } + req.src.act_w = 320; req.src.act_h = 240; - req.src.vir_w = 320; + req.src.vir_w = 320; req.src.vir_h = 240; req.src.yrgb_addr = 0;//(uint32_t)virt_to_phys(src); req.src.uv_addr = (unsigned long)virt_to_phys(src); req.src.v_addr = 0; - req.src.format = RGA2_FORMAT_RGBA_8888; + req.src.format = RGA2_FORMAT_YCbCr_420_SP_10B; req.dst.act_w = 320; req.dst.act_h = 240; @@ -1439,7 +1478,7 @@ void rga2_test_0(void) req.dst.yrgb_addr = 0;//((uint32_t)virt_to_phys(dst)); req.dst.uv_addr = (unsigned long)virt_to_phys(dst); - req.dst.format = RGA2_FORMAT_RGBA_8888; + req.dst.format = RGA2_FORMAT_YCbCr_420_SP; //dst = dst0; @@ -1449,6 +1488,7 @@ void rga2_test_0(void) req.rotate_mode = 0; req.scale_bicu_mode = 2; +#if 0 //req.alpha_rop_flag = 0; //req.alpha_rop_mode = 0x19; //req.PD_mode = 3; @@ -1459,12 +1499,28 @@ void rga2_test_0(void) //printk("src = %.8x\n", req.src.yrgb_addr); //printk("src = %.8x\n", req.src.uv_addr); //printk("dst = %.8x\n", req.dst.yrgb_addr); +#endif rga2_blit_sync(&session, &req); - for(j=0; j<100; j++) { - printk("%.8x\n", dst[j]); +#if 0 + uint32_t j; + for (j = 0; j < 320 * 240 * 10 / 8; j++) { + if (src[j] != dst[j]) + printk("error value dst not equal src j %d, s %.2x d %.2x\n", + j, src[j], dst[j]); } +#endif + +#if 1 + { + uint32_t j; + uint8_t *dp = (uint8_t *)dst; + + for (j = 0; j < 100; j++) + printk("%d %.2x\n", j, dp[j]); + } +#endif if(src) kfree(src); diff --git a/drivers/video/rockchip/rga2/rga2_mmu_info.c b/drivers/video/rockchip/rga2/rga2_mmu_info.c index b1cacd74e5d5..1b88c067ebfe 100644 --- a/drivers/video/rockchip/rga2/rga2_mmu_info.c +++ b/drivers/video/rockchip/rga2/rga2_mmu_info.c @@ -222,6 +222,18 @@ static int rga2_buf_size_cal(unsigned long yrgb_addr, unsigned long uv_addr, uns case RK_FORMAT_BPP8 : break; #endif + case RGA2_FORMAT_YCbCr_420_SP_10B: + case RGA2_FORMAT_YCrCb_420_SP_10B: + stride = (w + 3) & (~3); + stride = stride; + size_yrgb = stride * h; + size_uv = (stride * (h >> 1)); + start = MIN(yrgb_addr, uv_addr); + start >>= PAGE_SHIFT; + end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)); + end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + pageCount = end - start; + break; default : pageCount = 0; start = 0; diff --git a/drivers/video/rockchip/rga2/rga2_reg_info.c b/drivers/video/rockchip/rga2/rga2_reg_info.c index 91667416f340..7d8a4d676f7f 100755 --- a/drivers/video/rockchip/rga2/rga2_reg_info.c +++ b/drivers/video/rockchip/rga2/rga2_reg_info.c @@ -171,6 +171,7 @@ RGA2_set_reg_src_info(RK_U8 *base, struct rga2_req *msg) RK_U32 uv_stride = 0; RK_U32 mask_stride = 0; RK_U32 ydiv = 1, xdiv = 2; + RK_U8 yuv10 = 0; RK_U32 sw, sh; RK_U32 dw, dh; @@ -191,6 +192,14 @@ RGA2_set_reg_src_info(RK_U8 *base, struct rga2_req *msg) bRGA_SRC_TR_COLOR0 = (RK_U32 *)(base + RGA2_SRC_TR_COLOR0_OFFSET); bRGA_SRC_TR_COLOR1 = (RK_U32 *)(base + RGA2_SRC_TR_COLOR1_OFFSET); + if (msg->src.format == RGA2_FORMAT_YCbCr_420_SP_10B || + msg->src.format == RGA2_FORMAT_YCrCb_420_SP_10B) { + if ((msg->src.act_w == msg->dst.act_w) && + (msg->src.act_h == msg->dst.act_h) && + (msg->rotate_mode == 0)) + msg->rotate_mode = 1 << 6; + } + { rotate_mode = msg->rotate_mode & 0x3; @@ -252,6 +261,8 @@ RGA2_set_reg_src_info(RK_U8 *base, struct rga2_req *msg) case RGA2_FORMAT_YCrCb_422_P : src0_format = 0x9; xdiv = 2; ydiv = 1; src0_cbcr_swp = 1; break; case RGA2_FORMAT_YCrCb_420_SP : src0_format = 0xa; xdiv = 1; ydiv = 2; src0_cbcr_swp = 1; break; case RGA2_FORMAT_YCrCb_420_P : src0_format = 0xb; xdiv = 2; ydiv = 2; src0_cbcr_swp = 1; break; + case RGA2_FORMAT_YCbCr_420_SP_10B : src0_format = 0xa; xdiv = 1; ydiv = 2; yuv10 = 1; break; + case RGA2_FORMAT_YCrCb_420_SP_10B : src0_format = 0xa; xdiv = 1; ydiv = 2; src0_cbcr_swp = 1; yuv10 = 1; break; }; reg = ((reg & (~m_RGA2_SRC_INFO_SW_SRC_FMT)) | (s_RGA2_SRC_INFO_SW_SRC_FMT(src0_format))); @@ -275,10 +286,11 @@ RGA2_set_reg_src_info(RK_U8 *base, struct rga2_req *msg) reg = ((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_TRANS_E)) | (s_RGA2_SRC_INFO_SW_SW_SRC_TRANS_E(msg->src_trans_mode >> 1))); reg = ((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_DITHER_UP_E)) | (s_RGA2_SRC_INFO_SW_SW_SRC_DITHER_UP_E((msg->alpha_rop_flag >> 4) & 0x1))); reg = ((reg & (~m_RGA2_SRC_INFO_SW_SW_VSP_MODE_SEL)) | (s_RGA2_SRC_INFO_SW_SW_VSP_MODE_SEL((msg->scale_bicu_mode>>4)))); + reg = ((reg & (~m_RGA2_SRC_INFO_SW_SW_YUV10_E)) | (s_RGA2_SRC_INFO_SW_SW_YUV10_E((yuv10)))); + reg = ((reg & (~m_RGA2_SRC_INFO_SW_SW_YUV10_ROUND_E)) | (s_RGA2_SRC_INFO_SW_SW_YUV10_ROUND_E((yuv10)))); RGA2_reg_get_param(base, msg); stride = (((msg->src.vir_w * pixel_width) + 3) & ~3) >> 2; - uv_stride = ((msg->src.vir_w / xdiv + 3) & ~3); *bRGA_SRC_BASE0 = (RK_U32)(msg->src.yrgb_addr + msg->src.y_offset * (stride<<2) + msg->src.x_offset * pixel_width); @@ -961,6 +973,9 @@ void format_name_convert(uint32_t *df, uint32_t sf) case 0xd: *df = RGA2_FORMAT_YCrCb_422_P; break; case 0xe: *df = RGA2_FORMAT_YCrCb_420_SP; break; case 0xf: *df = RGA2_FORMAT_YCrCb_420_P; break; + + case 0x20:*df = RGA2_FORMAT_YCbCr_420_SP_10B; break; + case 0x21:*df = RGA2_FORMAT_YCrCb_420_SP_10B; break; } } @@ -1014,12 +1029,12 @@ void RGA_MSG_2_RGA2_MSG(struct rga_req *req_rga, struct rga2_req *req) else if (req_rga->rotate_mode == 2) { //x_mirror - req->rotate_mode = (1 << 4); + req->rotate_mode |= (1 << 4); } else if (req_rga->rotate_mode == 3) { //y_mirror - req->rotate_mode = (2 << 4); + req->rotate_mode |= (2 << 4); } else { req->rotate_mode = 0; diff --git a/drivers/video/rockchip/rga2/rga2_reg_info.h b/drivers/video/rockchip/rga2/rga2_reg_info.h index b27046b462c9..29ba3c686cbd 100755 --- a/drivers/video/rockchip/rga2/rga2_reg_info.h +++ b/drivers/video/rockchip/rga2/rga2_reg_info.h @@ -86,6 +86,10 @@ #define m_RGA2_SRC_INFO_SW_SW_SRC_DITHER_UP_E ( 0x1<<23 ) #define m_RGA2_SRC_INFO_SW_SW_SRC_SCL_FILTER ( 0x3<<24 ) #define m_RGA2_SRC_INFO_SW_SW_VSP_MODE_SEL ( 0x1<<26 ) +#define m_RGA2_SRC_INFO_SW_SW_YUV10_E ( 0x1<<27 ) +#define m_RGA2_SRC_INFO_SW_SW_YUV10_ROUND_E ( 0x1<<28 ) + + @@ -105,7 +109,8 @@ #define s_RGA2_SRC_INFO_SW_SW_SRC_DITHER_UP_E(x) ( (x&0x1)<<23 ) #define s_RGA2_SRC_INFO_SW_SW_SRC_SCL_FILTER(x) ( (x&0x3)<<24 ) #define s_RGA2_SRC_INFO_SW_SW_VSP_MODE_SEL(x) ( (x&0x1)<<26 ) - +#define s_RGA2_SRC_INFO_SW_SW_YUV10_E(x) ( (x&0x1)<<27 ) +#define s_RGA2_SRC_INFO_SW_SW_YUV10_ROUND_E(x) ( (x&0x1)<<28 ) /* RGA_SRC_VIR_INFO */ #define m_RGA2_SRC_VIR_INFO_SW_SRC_VIR_STRIDE ( 0x7fff<<0 ) //modify -- 2.34.1