From a9f4187bd98f8f57f1a32dc24a585b456bf60868 Mon Sep 17 00:00:00 2001 From: "Zikim,Wei" Date: Wed, 7 Dec 2016 10:21:48 +0800 Subject: [PATCH] video/rockchip: rga2 support dma fd in drm mode ion is not support dma fd, in order to support drm fd rga driver need fix, and user also need set the buf type by the macro Change-Id: I3d0eaf7fbefda5aaf715772649d972b9a9d5c06d Signed-off-by: Zikim,Wei --- drivers/video/rockchip/rga2/rga2.h | 53 ++-- drivers/video/rockchip/rga2/rga2_drv.c | 329 +++++++++++++------- drivers/video/rockchip/rga2/rga2_reg_info.c | 21 +- 3 files changed, 266 insertions(+), 137 deletions(-) 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; + } - 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; + 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 { - 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; + 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; + } + } } - 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; - } - 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; + 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(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_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; } - 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; + 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 ((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; + 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; +} - return 0; +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; + 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; + } + + 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; + } + + 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 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) -- 2.34.1