diff --git a/drivers/video/rockchip/rga2/rga2.h b/drivers/video/rockchip/rga2/rga2.h index 5c51f92220c9..bd2b560bebfe 100755 --- a/drivers/video/rockchip/rga2/rga2.h +++ b/drivers/video/rockchip/rga2/rga2.h @@ -3,7 +3,7 @@ #include #include - +#include #define RGA_BLIT_SYNC 0x5017 @@ -32,6 +32,9 @@ #define rgaNO_ERROR(status) (status >= 0) #define rgaIS_SUCCESS(status) (status == 0) +#define RGA_BUF_GEM_TYPE_MASK 0xC0 +#define RGA_BUF_GEM_TYPE_DMA 0x80 + /* RGA2 process mode enum */ enum { @@ -278,6 +281,7 @@ typedef struct rga_img_info_t unsigned short alpha_swap; } rga_img_info_t; + typedef struct rga_img_info_32_t { uint32_t yrgb_addr; /* yrgb mem addr */ @@ -522,10 +526,14 @@ struct rga2_req u8 rgb2yuv_mode; - struct sg_table *sg_src0; - struct sg_table *sg_src1; - struct sg_table *sg_dst; - struct sg_table *sg_els; + u8 buf_type; + struct sg_table *sg_src0; + struct sg_table *sg_src1; + struct sg_table *sg_dst; + struct sg_table *sg_els; + struct dma_buf_attachment *attach_src0; + struct dma_buf_attachment *attach_src1; + struct dma_buf_attachment *attach_dst; }; struct rga2_mmu_buf_t { @@ -645,22 +653,25 @@ typedef struct rga2_session { atomic_t num_done; } rga2_session; -struct rga2_reg { - rga2_session *session; - struct list_head session_link; /* link to rga service session */ - struct list_head status_link; /* link to register set list */ - uint32_t sys_reg[8]; - uint32_t cmd_reg[32]; - - uint32_t *MMU_base; - uint32_t MMU_len; - //atomic_t int_enable; - - //struct rga_req req; -}; - - - +struct rga2_reg { + rga2_session *session; + struct list_head session_link; + struct list_head status_link; + uint32_t sys_reg[8]; + uint32_t cmd_reg[32]; + + uint32_t *MMU_base; + uint32_t MMU_len; + + struct sg_table *sg_src0; + struct sg_table *sg_src1; + struct sg_table *sg_dst; + + struct dma_buf_attachment *attach_src0; + struct dma_buf_attachment *attach_src1; + struct dma_buf_attachment *attach_dst; +}; + struct rga2_service_info { struct mutex lock; struct timer_list timer; /* timer for power off */ diff --git a/drivers/video/rockchip/rga2/rga2_drv.c b/drivers/video/rockchip/rga2/rga2_drv.c index 0e9e427538e6..009681854fee 100644 --- a/drivers/video/rockchip/rga2/rga2_drv.c +++ b/drivers/video/rockchip/rga2/rga2_drv.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "rga2.h" #include "rga2_reg_info.h" @@ -426,6 +427,13 @@ static struct rga2_reg * rga2_reg_init(rga2_session *session, struct rga2_req *r return NULL; } + reg->sg_src0 = req->sg_src0; + reg->sg_dst = req->sg_dst; + reg->sg_src1 = req->sg_src1; + reg->attach_src0 = req->attach_src0; + reg->attach_dst = req->attach_dst; + reg->attach_src1 = req->attach_src1; + mutex_lock(&rga2_service.lock); list_add_tail(®->status_link, &rga2_service.waiting); list_add_tail(®->session_link, &session->waiting); @@ -538,6 +546,48 @@ static void rga2_try_set_reg(void) } } +static int rga2_put_dma_buf(struct rga2_req *req, struct rga2_reg *reg) +{ + struct dma_buf_attachment *attach = NULL; + struct sg_table *sgt = NULL; + struct dma_buf *dma_buf = NULL; + + if (!req && !reg) + return -EINVAL; + + attach = (!reg) ? req->attach_src0 : reg->attach_src0; + sgt = (!reg) ? req->sg_src0 : reg->sg_src0; + if (attach && sgt) + dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); + if (attach) { + dma_buf = attach->dmabuf; + dma_buf_detach(dma_buf, attach); + dma_buf_put(dma_buf); + } + + attach = (!reg) ? req->attach_dst : reg->attach_dst; + sgt = (!reg) ? req->sg_dst : reg->sg_dst; + if (attach && sgt) + dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); + if (attach) { + dma_buf = attach->dmabuf; + dma_buf_detach(dma_buf, attach); + dma_buf_put(dma_buf); + } + + attach = (!reg) ? req->attach_src1 : reg->attach_src1; + sgt = (!reg) ? req->sg_src1 : reg->sg_src1; + if (attach && sgt) + dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); + if (attach) { + dma_buf = attach->dmabuf; + dma_buf_detach(dma_buf, attach); + dma_buf_put(dma_buf); + } + + return 0; +} + static void rga2_del_running_list(void) { struct rga2_mmu_buf_t *tbuf = &rga2_mmu_buf; @@ -552,6 +602,9 @@ static void rga2_del_running_list(void) else tbuf->back += reg->MMU_len; } + + rga2_put_dma_buf(NULL, reg); + atomic_sub(1, ®->session->task_running); atomic_sub(1, &rga2_service.total_running); @@ -580,6 +633,9 @@ static void rga2_del_running_list_timeout(void) else tbuf->back += reg->MMU_len; } + + rga2_put_dma_buf(NULL, reg); + atomic_sub(1, ®->session->task_running); atomic_sub(1, &rga2_service.total_running); rga2_soft_reset(); @@ -592,125 +648,172 @@ static void rga2_del_running_list_timeout(void) return; } -static int rga2_convert_dma_buf(struct rga2_req *req) +static int rga2_get_img_info(rga_img_info_t *img, + u8 mmu_flag, + u8 buf_gem_type_dma, + struct sg_table **psgt, + struct dma_buf_attachment **pattach) { - struct ion_handle *hdl; + struct dma_buf_attachment *attach = NULL; + struct ion_client *ion_client = NULL; + struct ion_handle *hdl = NULL; + struct device *rga_dev = NULL; + struct sg_table *sgt = NULL; + struct dma_buf *dma_buf = NULL; + u32 vir_w, vir_h; ion_phys_addr_t phy_addr; - size_t len; - int ret; - uint32_t src_vir_w, dst_vir_w; + size_t len = 0; + int yrgb_addr = -1; + int ret = 0; - src_vir_w = req->src.vir_w; - dst_vir_w = req->dst.vir_w; + ion_client = rga2_drvdata->ion_client; + rga_dev = rga2_drvdata->dev; + yrgb_addr = (int)img->yrgb_addr; + vir_w = img->vir_w; + vir_h = img->vir_h; + if (yrgb_addr > 0) { + if (buf_gem_type_dma) { + dma_buf = dma_buf_get(img->yrgb_addr); + if (IS_ERR(dma_buf)) { + ret = -EINVAL; + pr_err("dma_buf_get fail fd[%d]\n", yrgb_addr); + return ret; + } + + attach = dma_buf_attach(dma_buf, rga_dev); + if (IS_ERR(attach)) { + dma_buf_put(dma_buf); + ret = -EINVAL; + pr_err("Failed to attach dma_buf\n"); + return ret; + } + + *pattach = attach; + sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + ret = -EINVAL; + pr_err("Failed to map src attachment\n"); + goto err_get_sg; + } + if (!mmu_flag) { + ret = -EINVAL; + pr_err("Fix it please enable iommu flag\n"); + goto err_get_sg; + } + } else { + hdl = ion_import_dma_buf(ion_client, img->yrgb_addr); + if (IS_ERR(hdl)) { + ret = -EINVAL; + pr_err("RGA2 ERROR ion buf handle\n"); + return ret; + } + if (mmu_flag) { + sgt = ion_sg_table(ion_client, hdl); + if (IS_ERR(sgt)) { + ret = -EINVAL; + pr_err("Fail map src attachment\n"); + goto err_get_sg; + } + } + } + + if (mmu_flag) { + *psgt = sgt; + img->yrgb_addr = img->uv_addr; + img->uv_addr = img->yrgb_addr + (vir_w * vir_h); + img->v_addr = img->uv_addr + (vir_w * vir_h) / 4; + } else { + ion_phys(ion_client, hdl, &phy_addr, &len); + img->yrgb_addr = phy_addr; + img->uv_addr = img->yrgb_addr + (vir_w * vir_h); + img->v_addr = img->uv_addr + (vir_w * vir_h) / 4; + } + } else { + img->yrgb_addr = img->uv_addr; + img->uv_addr = img->yrgb_addr + (vir_w * vir_h); + img->v_addr = img->uv_addr + (vir_w * vir_h) / 4; + } + + if (hdl) + ion_free(ion_client, hdl); + + return ret; + +err_get_sg: + if (hdl) + ion_free(ion_client, hdl); + if (sgt && buf_gem_type_dma) + dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); + if (attach) { + dma_buf = attach->dmabuf; + dma_buf_detach(dma_buf, attach); + *pattach = NULL; + dma_buf_put(dma_buf); + } + return ret; +} + +static int rga2_get_dma_buf(struct rga2_req *req) +{ + struct dma_buf *dma_buf = NULL; + u8 buf_gem_type_dma = 0; + u8 mmu_flag = 0; + int ret = 0; + + buf_gem_type_dma = req->buf_type & RGA_BUF_GEM_TYPE_DMA; 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 (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->src.yrgb_addr = req->src.uv_addr; - 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 - + (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 { - req->src.yrgb_addr = req->src.uv_addr; - 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; + req->sg_dst = NULL; + req->sg_els = NULL; + req->attach_src0 = NULL; + req->attach_dst = NULL; + req->attach_src1 = NULL; + mmu_flag = req->mmu_info.src0_mmu_flag; + ret = rga2_get_img_info(&req->src, mmu_flag, buf_gem_type_dma, + &req->sg_src0, &req->attach_src0); + if (ret) { + pr_err("src:rga2_get_img_info fail\n"); + goto err_src; } - 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->dst.yrgb_addr = req->dst.uv_addr; - 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 - + (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 { - req->dst.yrgb_addr = req->dst.uv_addr; - 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; + mmu_flag = req->mmu_info.dst_mmu_flag; + ret = rga2_get_img_info(&req->dst, mmu_flag, buf_gem_type_dma, + &req->sg_dst, &req->attach_dst); + if (ret) { + pr_err("dst:rga2_get_img_info fail\n"); + goto err_dst; } - 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 = 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->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->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; + mmu_flag = req->mmu_info.src1_mmu_flag; + ret = rga2_get_img_info(&req->src1, mmu_flag, buf_gem_type_dma, + &req->sg_src1, &req->attach_src1); + if (ret) { + pr_err("src1:rga2_get_img_info fail\n"); + goto err_src1; } - return 0; + return ret; + +err_src1: + if (buf_gem_type_dma && req->sg_dst && req->attach_dst) { + dma_buf_unmap_attachment(req->attach_dst, + req->sg_dst, DMA_BIDIRECTIONAL); + dma_buf = req->attach_dst->dmabuf; + dma_buf_detach(dma_buf, req->attach_dst); + dma_buf_put(dma_buf); + } +err_dst: + if (buf_gem_type_dma && req->sg_src0 && req->attach_src0) { + dma_buf_unmap_attachment(req->attach_src0, + req->sg_src0, DMA_BIDIRECTIONAL); + dma_buf = req->attach_src0->dmabuf; + dma_buf_detach(dma_buf, req->attach_src0); + dma_buf_put(dma_buf); + } +err_src: + + return ret; } static int rga2_blit(rga2_session *session, struct rga2_req *req) @@ -719,8 +822,8 @@ static int rga2_blit(rga2_session *session, struct rga2_req *req) int num = 0; struct rga2_reg *reg; - if(rga2_convert_dma_buf(req)) { - printk("RGA2 : DMA buf copy error\n"); + if (rga2_get_dma_buf(req)) { + pr_err("RGA2 : DMA buf copy error\n"); return -EFAULT; } @@ -728,16 +831,17 @@ static int rga2_blit(rga2_session *session, struct rga2_req *req) /* check value if legal */ ret = rga2_check_param(req); if(ret == -EINVAL) { - printk("req argument is inval\n"); - break; + pr_err("req argument is inval\n"); + goto err_put_dma_buf; } reg = rga2_reg_init(session, req); if(reg == NULL) { - break; + pr_err("init reg fail\n"); + goto err_put_dma_buf; } - num = 1; + num = 1; mutex_lock(&rga2_service.lock); atomic_add(num, &rga2_service.total_running); rga2_try_set_reg(); @@ -747,6 +851,9 @@ static int rga2_blit(rga2_session *session, struct rga2_req *req) } while(0); +err_put_dma_buf: + rga2_put_dma_buf(req, NULL); + return -EFAULT; } diff --git a/drivers/video/rockchip/rga2/rga2_reg_info.c b/drivers/video/rockchip/rga2/rga2_reg_info.c index d1a9db5dffb9..81b94569ef23 100755 --- a/drivers/video/rockchip/rga2/rga2_reg_info.c +++ b/drivers/video/rockchip/rga2/rga2_reg_info.c @@ -980,9 +980,14 @@ void format_name_convert(uint32_t *df, uint32_t sf) } void RGA_MSG_2_RGA2_MSG(struct rga_req *req_rga, struct rga2_req *req) -{ - u16 alpha_mode_0, alpha_mode_1; - +{ + u16 alpha_mode_0, alpha_mode_1; + + if (req_rga->render_mode & RGA_BUF_GEM_TYPE_MASK) + req->buf_type = RGA_BUF_GEM_TYPE_MASK & RGA_BUF_GEM_TYPE_DMA; + + req_rga->render_mode &= (~RGA_BUF_GEM_TYPE_MASK); + if (req_rga->render_mode == 6) req->render_mode = update_palette_table_mode; else if (req_rga->render_mode == 7) @@ -1197,8 +1202,14 @@ void memcpy_img_info(struct rga_img_info_t *dst, struct rga_img_info_32_t *src) dst->alpha_swap = src->alpha_swap; } void RGA_MSG_2_RGA2_MSG_32(struct rga_req_32 *req_rga, struct rga2_req *req) -{ - u16 alpha_mode_0, alpha_mode_1; +{ + u16 alpha_mode_0, alpha_mode_1; + + if (req_rga->render_mode & RGA_BUF_GEM_TYPE_MASK) + req->buf_type = RGA_BUF_GEM_TYPE_MASK & RGA_BUF_GEM_TYPE_DMA; + + req_rga->render_mode &= (~RGA_BUF_GEM_TYPE_MASK); + if (req_rga->render_mode == 6) req->render_mode = update_palette_table_mode; else if (req_rga->render_mode == 7)