video/rockchip: rga2 support dma fd
authorZikim,Wei <wzq@rock-chips.com>
Wed, 7 Dec 2016 02:21:48 +0000 (10:21 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 8 Dec 2016 12:51:42 +0000 (20:51 +0800)
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 <wzq@rock-chips.com>
drivers/video/rockchip/rga2/rga2.h
drivers/video/rockchip/rga2/rga2_drv.c
drivers/video/rockchip/rga2/rga2_reg_info.c

index 5c51f92220c9a7d0fe0bf174277cc76a388bdce8..bd2b560bebfe42cad51ba83032130f374c4693bd 100755 (executable)
@@ -3,7 +3,7 @@
 \r
 #include <linux/mutex.h>\r
 #include <linux/scatterlist.h>\r
-\r
+#include <linux/dma-buf.h>
 \r
 \r
 #define RGA_BLIT_SYNC  0x5017\r
@@ -32,6 +32,9 @@
 #define rgaNO_ERROR(status)                    (status >= 0)\r
 #define rgaIS_SUCCESS(status)          (status == 0)\r
 \r
+#define RGA_BUF_GEM_TYPE_MASK      0xC0
+#define RGA_BUF_GEM_TYPE_DMA       0x80
+
 /* RGA2 process mode enum */\r
 enum\r
 {\r
@@ -278,6 +281,7 @@ typedef struct rga_img_info_t
     unsigned short alpha_swap;\r
 }\r
 rga_img_info_t;\r
+
 typedef struct rga_img_info_32_t\r
 {\r
     uint32_t yrgb_addr;      /* yrgb    mem addr         */\r
@@ -522,10 +526,14 @@ struct rga2_req
 \r
     u8 rgb2yuv_mode;\r
 \r
-    struct sg_table *sg_src0;\r
-    struct sg_table *sg_src1;\r
-    struct sg_table *sg_dst;\r
-    struct sg_table *sg_els;\r
+       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;
 };\r
 \r
 struct rga2_mmu_buf_t {\r
@@ -645,22 +653,25 @@ typedef struct rga2_session {
     atomic_t        num_done;\r
 } rga2_session;\r
 \r
-struct rga2_reg {\r
-    rga2_session               *session;\r
-       struct list_head        session_link;           /* link to rga service session */\r
-       struct list_head        status_link;            /* link to register set list */\r
-       uint32_t  sys_reg[8];\r
-    uint32_t  cmd_reg[32];\r
-\r
-    uint32_t *MMU_base;\r
-    uint32_t MMU_len;\r
-    //atomic_t int_enable;\r
-\r
-    //struct rga_req      req;\r
-};\r
-\r
-\r
-\r
+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 {\r
     struct mutex       lock;\r
     struct timer_list  timer;                  /* timer for power off */\r
index 0e9e427538e64d7e37bb42f45a8d87f505dba970..009681854fee5ee77bc0889a9f42cabd4a7b1091 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/rockchip_ion.h>
 #include <linux/version.h>
 #include <linux/pm_runtime.h>
+#include <linux/dma-buf.h>
 
 #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(&reg->status_link, &rga2_service.waiting);
        list_add_tail(&reg->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, &reg->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, &reg->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;
 }
 
index d1a9db5dffb9ee9971cdb2ad40285b3c85d5c763..81b94569ef236307dd3d5fa1176ebb1a5d8d55bb 100755 (executable)
@@ -980,9 +980,14 @@ void format_name_convert(uint32_t *df, uint32_t sf)
 }\r
 \r
 void RGA_MSG_2_RGA2_MSG(struct rga_req *req_rga, struct rga2_req *req)\r
-{\r
-    u16 alpha_mode_0, alpha_mode_1;\r
-\r
+{
+       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)\r
         req->render_mode = update_palette_table_mode;\r
     else if (req_rga->render_mode == 7)\r
@@ -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;\r
 }\r
 void RGA_MSG_2_RGA2_MSG_32(struct rga_req_32 *req_rga, struct rga2_req *req)\r
-{\r
-    u16 alpha_mode_0, alpha_mode_1;\r
+{
+       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)\r
         req->render_mode = update_palette_table_mode;\r
     else if (req_rga->render_mode == 7)\r