#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"
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);
}
}
+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;
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);
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();
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)
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;
}
/* 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();
}
while(0);
+err_put_dma_buf:
+ rga2_put_dma_buf(req, NULL);
+
return -EFAULT;
}