video/rockchip: rga2: Optimize the process of mapping dma.

Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
Change-Id: Ie8d140d8fc102c9a3677b266ac7848c4c3ade78e
This commit is contained in:
Yu Qiaowei
2021-09-16 15:38:10 +08:00
committed by Tao Huang
parent c15fbd9827
commit 50ec41b5c2
4 changed files with 516 additions and 543 deletions

View File

@@ -337,6 +337,18 @@ typedef struct rga_img_info_32_t
}
rga_img_info_32_t;
struct rga_dma_buffer_t {
/* DMABUF information */
struct dma_buf *dma_buf;
struct dma_buf_attachment *attach;
struct sg_table *sgt;
dma_addr_t iova;
unsigned long size;
void *vaddr;
enum dma_data_direction dir;
};
struct rga_req {
uint8_t render_mode; /* (enum) process mode sel */
@@ -578,14 +590,6 @@ struct rga2_req
u8 rgb2yuv_mode;
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 dma_buf_attachment *attach_els;
};
struct rga2_mmu_buf_t {
@@ -726,15 +730,10 @@ struct rga2_reg {
uint32_t MMU_len;
bool MMU_map;
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 dma_buf_attachment *attach_els;
struct rga_dma_buffer_t dma_buffer_src0;
struct rga_dma_buffer_t dma_buffer_src1;
struct rga_dma_buffer_t dma_buffer_dst;
struct rga_dma_buffer_t dma_buffer_els;
};
struct rga2_service_info {

View File

@@ -367,71 +367,6 @@ static int rga2_align_check(struct rga2_req *req)
return 0;
}
static int rga2_memory_check(void *vaddr, u32 w, u32 h, u32 format, int fd)
{
int bits = 32;
int temp_data = 0;
void *one_line = kzalloc(w * 4, GFP_KERNEL);
if (!one_line) {
ERR("kzalloc fail %s[%d]\n", __func__, __LINE__);
return 0;
}
switch (format) {
case RGA2_FORMAT_RGBA_8888:
case RGA2_FORMAT_RGBX_8888:
case RGA2_FORMAT_BGRA_8888:
case RGA2_FORMAT_BGRX_8888:
bits = 32;
break;
case RGA2_FORMAT_RGB_888:
case RGA2_FORMAT_BGR_888:
bits = 24;
break;
case RGA2_FORMAT_RGB_565:
case RGA2_FORMAT_RGBA_5551:
case RGA2_FORMAT_RGBA_4444:
case RGA2_FORMAT_BGR_565:
case RGA2_FORMAT_YCbCr_422_SP:
case RGA2_FORMAT_YCbCr_422_P:
case RGA2_FORMAT_YCrCb_422_SP:
case RGA2_FORMAT_YCrCb_422_P:
case RGA2_FORMAT_BGRA_5551:
case RGA2_FORMAT_BGRA_4444:
bits = 16;
break;
case RGA2_FORMAT_YCbCr_420_SP:
case RGA2_FORMAT_YCbCr_420_P:
case RGA2_FORMAT_YCrCb_420_SP:
case RGA2_FORMAT_YCrCb_420_P:
bits = 12;
break;
case RGA2_FORMAT_YCbCr_420_SP_10B:
case RGA2_FORMAT_YCrCb_420_SP_10B:
case RGA2_FORMAT_YCbCr_422_SP_10B:
case RGA2_FORMAT_YCrCb_422_SP_10B:
bits = 15;
break;
default:
INFO("un know format\n");
kfree(one_line);
return -1;
}
temp_data = w * (h - 1) * bits >> 3;
if (fd > 0) {
INFO("vaddr is%p, bits is %d, fd check\n", vaddr, bits);
memcpy(one_line, (char *)vaddr + temp_data, w * bits >> 3);
INFO("fd check ok\n");
} else {
INFO("vir addr memory check.\n");
memcpy((void *)((char *)vaddr + temp_data), one_line,
w * bits >> 3);
INFO("vir addr check ok.\n");
}
kfree(one_line);
return 0;
}
int rga2_scale_check(struct rga2_req *req)
{
u32 saw, sah, daw, dah;
@@ -486,19 +421,6 @@ static void rga2_printf_cmd_buf(u32 *cmd_buf)
dst_aw, dst_ah, dst_stride, dst_format);
}
static bool is_yuv422p_format(u32 format)
{
bool ret = false;
switch (format) {
case RGA2_FORMAT_YCbCr_422_P:
case RGA2_FORMAT_YCrCb_422_P:
ret = true;
break;
}
return ret;
}
static inline void rga2_write(u32 b, u32 r)
{
*((volatile unsigned int *)(rga2_drvdata->rga_base + r)) = b;
@@ -843,6 +765,14 @@ static struct rga2_reg * rga2_reg_init(rga2_session *session, struct rga2_req *r
INIT_LIST_HEAD(&reg->session_link);
INIT_LIST_HEAD(&reg->status_link);
ret = rga2_get_dma_info(reg, req);
if (ret < 0) {
pr_err("fail to get dma buffer info!\n");
free_page((unsigned long)reg);
return NULL;
}
if ((req->mmu_info.src0_mmu_flag & 1) || (req->mmu_info.src1_mmu_flag & 1)
|| (req->mmu_info.dst_mmu_flag & 1) || (req->mmu_info.els_mmu_flag & 1))
{
@@ -861,16 +791,6 @@ static struct rga2_reg * rga2_reg_init(rga2_session *session, struct rga2_req *r
return NULL;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
reg->sg_src0 = req->sg_src0;
reg->sg_dst = req->sg_dst;
reg->sg_src1 = req->sg_src1;
reg->sg_els = req->sg_els;
reg->attach_src0 = req->attach_src0;
reg->attach_dst = req->attach_dst;
reg->attach_src1 = req->attach_src1;
reg->attach_els = req->attach_els;
#endif
mutex_lock(&rga2_service.lock);
list_add_tail(&reg->status_link, &rga2_service.waiting);
@@ -1009,59 +929,6 @@ static void rga2_try_set_reg(void)
}
}
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
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 ? reg->attach_src0 : req->attach_src0;
sgt = reg ? reg->sg_src0 : req->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 ? reg->attach_dst : req->attach_dst;
sgt = reg ? reg->sg_dst : req->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 ? reg->attach_src1 : req->attach_src1;
sgt = reg ? reg->sg_src1 : req->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);
}
attach = reg ? reg->attach_els : req->attach_els;
sgt = reg ? reg->sg_els : req->sg_els;
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;
}
#endif
static void rga2_del_running_list(void)
{
@@ -1077,9 +944,7 @@ static void rga2_del_running_list(void)
else
tbuf->back += reg->MMU_len;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
rga2_put_dma_buf(NULL, reg);
#endif
rga2_put_dma_info(reg);
atomic_sub(1, &reg->session->task_running);
atomic_sub(1, &rga2_service.total_running);
@@ -1110,9 +975,7 @@ static void rga2_del_running_list_timeout(void)
else
tbuf->back += reg->MMU_len;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
rga2_put_dma_buf(NULL, reg);
#endif
rga2_put_dma_info(reg);
atomic_sub(1, &reg->session->task_running);
atomic_sub(1, &rga2_service.total_running);
rga2_soft_reset();
@@ -1124,315 +987,6 @@ static void rga2_del_running_list_timeout(void)
}
return;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
static int rga2_get_img_info(rga_img_info_t *img,
u8 mmu_flag,
struct sg_table **psgt,
struct dma_buf_attachment **pattach)
{
struct dma_buf_attachment *attach = NULL;
struct device *rga_dev = NULL;
struct sg_table *sgt = NULL;
struct dma_buf *dma_buf = NULL;
u32 vir_w, vir_h;
int yrgb_addr = -1;
int ret = 0;
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) {
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;
}
#ifdef CONFIG_ROCKCHIP_RGA2_DEBUGGER
if (RGA2_CHECK_MODE) {
void *vaddr = dma_buf_vmap(dma_buf);
if (vaddr)
rga2_memory_check(vaddr, img->vir_w, img->vir_h,
img->format, img->yrgb_addr);
dma_buf_vunmap(dma_buf, vaddr);
}
#endif
*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;
}
if (mmu_flag) {
*psgt = sgt;
img->yrgb_addr = img->uv_addr;
img->uv_addr = img->yrgb_addr + (vir_w * vir_h);
if (is_yuv422p_format(img->format))
img->v_addr = img->uv_addr + (vir_w * vir_h) / 2;
else
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);
if (is_yuv422p_format(img->format))
img->v_addr = img->uv_addr + (vir_w * vir_h) / 2;
else
img->v_addr = img->uv_addr + (vir_w * vir_h) / 4;
}
return ret;
err_get_sg:
if (!IS_ERR(sgt) && sgt)
dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
if (!IS_ERR(attach) && 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 mmu_flag = 0;
int ret = 0;
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;
req->attach_els = NULL;
mmu_flag = req->mmu_info.src0_mmu_flag;
ret = rga2_get_img_info(&req->src, mmu_flag, &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, &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, &req->sg_src1,
&req->attach_src1);
if (ret) {
pr_err("src1:rga2_get_img_info fail\n");
goto err_src1;
}
mmu_flag = req->mmu_info.els_mmu_flag;
ret = rga2_get_img_info(&req->pat, mmu_flag, &req->sg_els,
&req->attach_els);
if (ret) {
pr_err("els:rga2_get_img_info fail\n");
goto err_els;
}
return ret;
err_els:
if (req->sg_src1 && req->attach_src1) {
dma_buf_unmap_attachment(req->attach_src1,
req->sg_src1, DMA_BIDIRECTIONAL);
dma_buf = req->attach_src1->dmabuf;
dma_buf_detach(dma_buf, req->attach_src1);
dma_buf_put(dma_buf);
}
err_src1:
if (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 (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;
}
#else
static int rga2_convert_dma_buf(struct rga2_req *req)
{
struct ion_handle *hdl;
ion_phys_addr_t phy_addr;
size_t len;
int ret;
u32 src_vir_w, dst_vir_w;
void *vaddr = NULL;
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 (IS_ERR(hdl)) {
ret = PTR_ERR(hdl);
pr_err("RGA2 SRC ERROR ion buf handle\n");
return ret;
}
#ifdef CONFIG_ROCKCHIP_RGA2_DEBUGGER
if (RGA2_CHECK_MODE) {
vaddr = ion_map_kernel(rga2_drvdata->ion_client, hdl);
if (vaddr)
rga2_memory_check(vaddr, req->src.vir_w, req->src.vir_h,
req->src.format, req->src.yrgb_addr);
ion_unmap_kernel(rga2_drvdata->ion_client, hdl);
}
#endif
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;
}
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);
pr_err("RGA2 DST ERROR ion buf handle\n");
return ret;
}
#ifdef CONFIG_ROCKCHIP_RGA2_DEBUGGER
if (RGA2_CHECK_MODE) {
vaddr = ion_map_kernel(rga2_drvdata->ion_client, hdl);
if (vaddr)
rga2_memory_check(vaddr, req->dst.vir_w, req->dst.vir_h,
req->dst.format, req->dst.yrgb_addr);
ion_unmap_kernel(rga2_drvdata->ion_client, hdl);
}
#endif
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;
}
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);
pr_err("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 (is_yuv422p_format(req->src.format))
req->src.v_addr = req->src.uv_addr + (req->src.vir_w * req->src.vir_h) / 2;
if (is_yuv422p_format(req->dst.format))
req->dst.v_addr = req->dst.uv_addr + (req->dst.vir_w * req->dst.vir_h) / 2;
if (is_yuv422p_format(req->src1.format))
req->src1.v_addr = req->src1.uv_addr + (req->src1.vir_w * req->dst.vir_h) / 2;
return 0;
}
#endif
static int rga2_blit_flush_cache(rga2_session *session, struct rga2_req *req)
{
@@ -1446,19 +1000,13 @@ static int rga2_blit_flush_cache(rga2_session *session, struct rga2_req *req)
ret = -ENOMEM;
goto err_free_reg;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
if (rga2_get_dma_buf(req)) {
pr_err("RGA2 : DMA buf copy error\n");
ret = -EFAULT;
ret = rga2_get_dma_info(reg, req);
if (ret < 0) {
pr_err("fail to get dma buffer info!\n");
goto err_free_reg;
}
#else
if (rga2_convert_dma_buf(req)) {
pr_err("RGA2 : DMA buf copy error\n");
ret = -EFAULT;
goto err_free_reg;
}
#endif
if ((req->mmu_info.src0_mmu_flag & 1) || (req->mmu_info.src1_mmu_flag & 1) ||
(req->mmu_info.dst_mmu_flag & 1) || (req->mmu_info.els_mmu_flag & 1)) {
reg->MMU_map = true;
@@ -1487,54 +1035,26 @@ static int rga2_blit(rga2_session *session, struct rga2_req *req)
int num = 0;
struct rga2_reg *reg;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
if (rga2_get_dma_buf(req)) {
pr_err("RGA2 : DMA buf copy error\n");
/* check value if legal */
ret = rga2_check_param(req);
if (ret == -EINVAL) {
pr_err("req argument is inval\n");
return ret;
}
reg = rga2_reg_init(session, req);
if (reg == NULL) {
pr_err("init reg fail\n");
return -EFAULT;
}
#else
if (rga2_convert_dma_buf(req)) {
pr_err("RGA2 : DMA buf copy error\n");
return -EFAULT;
}
#endif
do {
/* check value if legal */
ret = rga2_check_param(req);
if(ret == -EINVAL) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
pr_err("req argument is inval\n");
goto err_put_dma_buf;
#else
pr_err("req argument is inval\n");
break;
#endif
}
reg = rga2_reg_init(session, req);
if(reg == NULL) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
pr_err("init reg fail\n");
goto err_put_dma_buf;
#else
break;
#endif
}
num = 1;
mutex_lock(&rga2_service.lock);
atomic_add(num, &rga2_service.total_running);
rga2_try_set_reg();
mutex_unlock(&rga2_service.lock);
num = 1;
mutex_lock(&rga2_service.lock);
atomic_add(num, &rga2_service.total_running);
rga2_try_set_reg();
mutex_unlock(&rga2_service.lock);
return 0;
}
while(0);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
err_put_dma_buf:
rga2_put_dma_buf(req, NULL);
#endif
return -EFAULT;
return 0;
}
static int rga2_blit_async(rga2_session *session, struct rga2_req *req)

View File

@@ -19,11 +19,15 @@
#include <asm/memory.h>
#include <asm/atomic.h>
#include <asm/cacheflush.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
#include <linux/rockchip_ion.h>
#endif
#include "rga2_mmu_info.h"
#include "rga2_debugger.h"
extern struct rga2_service_info rga2_service;
extern struct rga2_mmu_buf_t rga2_mmu_buf;
extern struct rga2_drvdata_t *rga2_drvdata;
//extern int mmu_buff_temp[1024];
@@ -118,6 +122,431 @@ static unsigned int armv7_va_to_pa(unsigned int v_addr)
}
#endif
static bool rga2_is_yuv422p_format(u32 format)
{
bool ret = false;
switch (format) {
case RGA2_FORMAT_YCbCr_422_P:
case RGA2_FORMAT_YCrCb_422_P:
ret = true;
break;
}
return ret;
}
#ifdef CONFIG_ROCKCHIP_RGA2_DEBUGGER
static int rga2_memory_check(void *vaddr, u32 w, u32 h, u32 format, int fd)
{
int bits = 32;
int temp_data = 0;
void *one_line = kzalloc(w * 4, GFP_KERNEL);
if (!one_line) {
ERR("kzalloc fail %s[%d]\n", __func__, __LINE__);
return 0;
}
switch (format) {
case RGA2_FORMAT_RGBA_8888:
case RGA2_FORMAT_RGBX_8888:
case RGA2_FORMAT_BGRA_8888:
case RGA2_FORMAT_BGRX_8888:
bits = 32;
break;
case RGA2_FORMAT_RGB_888:
case RGA2_FORMAT_BGR_888:
bits = 24;
break;
case RGA2_FORMAT_RGB_565:
case RGA2_FORMAT_RGBA_5551:
case RGA2_FORMAT_RGBA_4444:
case RGA2_FORMAT_BGR_565:
case RGA2_FORMAT_YCbCr_422_SP:
case RGA2_FORMAT_YCbCr_422_P:
case RGA2_FORMAT_YCrCb_422_SP:
case RGA2_FORMAT_YCrCb_422_P:
case RGA2_FORMAT_BGRA_5551:
case RGA2_FORMAT_BGRA_4444:
bits = 16;
break;
case RGA2_FORMAT_YCbCr_420_SP:
case RGA2_FORMAT_YCbCr_420_P:
case RGA2_FORMAT_YCrCb_420_SP:
case RGA2_FORMAT_YCrCb_420_P:
bits = 12;
break;
case RGA2_FORMAT_YCbCr_420_SP_10B:
case RGA2_FORMAT_YCrCb_420_SP_10B:
case RGA2_FORMAT_YCbCr_422_SP_10B:
case RGA2_FORMAT_YCrCb_422_SP_10B:
bits = 15;
break;
default:
INFO("un know format\n");
kfree(one_line);
return -1;
}
temp_data = w * (h - 1) * bits >> 3;
if (fd > 0) {
INFO("vaddr is%p, bits is %d, fd check\n", vaddr, bits);
memcpy(one_line, (char *)vaddr + temp_data, w * bits >> 3);
INFO("fd check ok\n");
} else {
INFO("vir addr memory check.\n");
memcpy((void *)((char *)vaddr + temp_data), one_line,
w * bits >> 3);
INFO("vir addr check ok.\n");
}
kfree(one_line);
return 0;
}
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
static int rga2_map_dma_buffer(struct rga_img_info_t *img,
struct rga_dma_buffer_t *rga_dma_buffer,
enum dma_data_direction dir)
{
struct device *rga_dev = NULL;
struct dma_buf *dma_buf = NULL;
struct dma_buf_attachment *attach = NULL;
struct sg_table *sgt = NULL;
u32 vir_w, vir_h;
int fd = -1;
int ret = 0;
rga_dev = rga2_drvdata->dev;
fd = (int)img->yrgb_addr;
vir_w = img->vir_w;
vir_h = img->vir_h;
dma_buf = dma_buf_get(fd);
if (IS_ERR(dma_buf)) {
ret = -EINVAL;
pr_err("dma_buf_get fail fd[%d]\n", fd);
return ret;
}
attach = dma_buf_attach(dma_buf, rga_dev);
if (IS_ERR(attach)) {
ret = -EINVAL;
pr_err("Failed to attach dma_buf\n");
goto err_get_attach;
}
#ifdef CONFIG_ROCKCHIP_RGA2_DEBUGGER
if (RGA2_CHECK_MODE) {
void *vaddr = dma_buf_vmap(dma_buf);
if (vaddr)
rga2_memory_check(vaddr, img->vir_w, img->vir_h,
img->format, img->yrgb_addr);
dma_buf_vunmap(dma_buf, vaddr);
}
#endif
sgt = dma_buf_map_attachment(attach, dir);
if (IS_ERR(sgt)) {
ret = -EINVAL;
pr_err("Failed to map src attachment\n");
goto err_get_sgt;
}
rga_dma_buffer->dma_buf = dma_buf;
rga_dma_buffer->attach = attach;
rga_dma_buffer->sgt = sgt;
rga_dma_buffer->size = sg_dma_len(sgt->sgl);
rga_dma_buffer->dir = dir;
return ret;
err_get_sgt:
if (attach)
dma_buf_detach(dma_buf, attach);
err_get_attach:
if (dma_buf)
dma_buf_put(dma_buf);
return ret;
}
static void rga2_unmap_dma_buffer(struct rga_dma_buffer_t *rga_dma_buffer)
{
if (rga_dma_buffer->attach && rga_dma_buffer->sgt)
dma_buf_unmap_attachment(rga_dma_buffer->attach,
rga_dma_buffer->sgt,
rga_dma_buffer->dir);
if (rga_dma_buffer->attach) {
dma_buf_detach(rga_dma_buffer->dma_buf, rga_dma_buffer->attach);
dma_buf_put(rga_dma_buffer->dma_buf);
}
}
static void rga2_convert_addr(struct rga_img_info_t *img)
{
/*
* If it is not using dma fd, the virtual/phyical address is assigned
* to the address of the corresponding channel.
*/
img->yrgb_addr = img->uv_addr;
img->uv_addr = img->yrgb_addr + (img->vir_w * img->vir_h);
if (rga2_is_yuv422p_format(img->format))
img->v_addr = img->uv_addr + (img->vir_w * img->vir_h) / 2;
else
img->v_addr = img->uv_addr + (img->vir_w * img->vir_h) / 4;
}
int rga2_get_dma_info(struct rga2_reg *reg, struct rga2_req *req)
{
uint32_t mmu_flag;
int ret;
struct rga_dma_buffer_t *buffer_src0, *buffer_src1, *buffer_dst, *buffer_els;
struct rga_img_info_t *src0, *src1, *dst, *els;
/*
* Since the life cycle of rga2_req cannot satisfy the release of
* dmabuffer after the task is over, the mapped dmabuffer is saved
* in rga2_reg.
*/
buffer_src0 = &reg->dma_buffer_src0;
buffer_src1 = &reg->dma_buffer_src1;
buffer_dst = &reg->dma_buffer_dst;
buffer_els = &reg->dma_buffer_els;
src0 = &req->src;
src1 = &req->src1;
dst = &req->dst;
els = &req->pat;
/* src0 chanel */
mmu_flag = req->mmu_info.src0_mmu_flag;
if (unlikely(!mmu_flag && src0->yrgb_addr)) {
pr_err("Fix it please enable src0 mmu\n");
return -EINVAL;
} else if (mmu_flag && src0->yrgb_addr) {
ret = rga2_map_dma_buffer(src0, buffer_src0, DMA_BIDIRECTIONAL);
if (ret < 0) {
pr_err("src0: can't map dma-buf\n");
return ret;
}
}
rga2_convert_addr(src0);
/* src1 chanel */
mmu_flag = req->mmu_info.src1_mmu_flag;
if (unlikely(!mmu_flag && src1->yrgb_addr)) {
pr_err("Fix it please enable src1 mmu\n");
ret = -EINVAL;
goto err_src1_channel;
} else if (mmu_flag && src1->yrgb_addr) {
ret = rga2_map_dma_buffer(src1, buffer_src1, DMA_BIDIRECTIONAL);
if (ret < 0) {
pr_err("src1: can't map dma-buf\n");
goto err_src1_channel;
}
}
rga2_convert_addr(src1);
/* dst chanel */
mmu_flag = req->mmu_info.dst_mmu_flag;
if (unlikely(!mmu_flag && dst->yrgb_addr)) {
pr_err("Fix it please enable dst mmu\n");
ret = -EINVAL;
goto err_dst_channel;
} else if (mmu_flag && dst->yrgb_addr) {
ret = rga2_map_dma_buffer(dst, buffer_dst, DMA_BIDIRECTIONAL);
if (ret < 0) {
pr_err("dst: can't map dma-buf\n");
goto err_dst_channel;
}
}
rga2_convert_addr(dst);
/* els chanel */
mmu_flag = req->mmu_info.els_mmu_flag;
if (unlikely(!mmu_flag && els->yrgb_addr)) {
pr_err("Fix it please enable els mmu\n");
ret = -EINVAL;
goto err_els_channel;
} else if (mmu_flag && els->yrgb_addr) {
ret = rga2_map_dma_buffer(els, buffer_els, DMA_BIDIRECTIONAL);
if (ret < 0) {
pr_err("els: can't map dma-buf\n");
goto err_els_channel;
}
}
rga2_convert_addr(els);
return 0;
err_els_channel:
rga2_unmap_dma_buffer(buffer_dst);
err_dst_channel:
rga2_unmap_dma_buffer(buffer_src1);
err_src1_channel:
rga2_unmap_dma_buffer(buffer_src0);
return ret;
}
void rga2_put_dma_info(struct rga2_reg *reg)
{
rga2_unmap_dma_buffer(&reg->dma_buffer_src0);
rga2_unmap_dma_buffer(&reg->dma_buffer_src1);
rga2_unmap_dma_buffer(&reg->dma_buffer_dst);
rga2_unmap_dma_buffer(&reg->dma_buffer_els);
}
#else
static int rga2_get_dma_info(struct rga2_reg *reg, struct rga2_req *req)
{
struct ion_handle *hdl;
ion_phys_addr_t phy_addr;
size_t len;
int ret;
u32 src_vir_w, dst_vir_w;
void *vaddr = NULL;
struct rga_dma_buffer_t *buffer_src0, *buffer_src1, *buffer_dst, *buffer_els;
src_vir_w = req->src.vir_w;
dst_vir_w = req->dst.vir_w;
buffer_src0 = &reg->dma_buffer_src0;
buffer_src1 = &reg->dma_buffer_src1;
buffer_dst = &reg->dma_buffer_dst;
buffer_els = &reg->dma_buffer_els;
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);
pr_err("RGA2 SRC ERROR ion buf handle\n");
return ret;
}
#ifdef CONFIG_ROCKCHIP_RGA2_DEBUGGER
if (RGA2_CHECK_MODE) {
vaddr = ion_map_kernel(rga2_drvdata->ion_client, hdl);
if (vaddr)
rga2_memory_check(vaddr, req->src.vir_w, req->src.vir_h,
req->src.format, req->src.yrgb_addr);
ion_unmap_kernel(rga2_drvdata->ion_client, hdl);
}
#endif
if (req->mmu_info.src0_mmu_flag) {
buffer_src0.sgt =
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;
}
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);
pr_err("RGA2 DST ERROR ion buf handle\n");
return ret;
}
#ifdef CONFIG_ROCKCHIP_RGA2_DEBUGGER
if (RGA2_CHECK_MODE) {
vaddr = ion_map_kernel(rga2_drvdata->ion_client, hdl);
if (vaddr)
rga2_memory_check(vaddr, req->dst.vir_w, req->dst.vir_h,
req->dst.format, req->dst.yrgb_addr);
ion_unmap_kernel(rga2_drvdata->ion_client, hdl);
}
#endif
if (req->mmu_info.dst_mmu_flag) {
buffer_dst.sgt =
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;
}
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);
pr_err("RGA2 ERROR ion buf handle\n");
return ret;
}
if (req->mmu_info.dst_mmu_flag) {
buffer_src1.sgt =
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 (rga2_is_yuv422p_format(req->src.format))
req->src.v_addr = req->src.uv_addr + (req->src.vir_w * req->src.vir_h) / 2;
if (rga2_is_yuv422p_format(req->dst.format))
req->dst.v_addr = req->dst.uv_addr + (req->dst.vir_w * req->dst.vir_h) / 2;
if (rga2_is_yuv422p_format(req->src1.format))
req->src1.v_addr = req->src1.uv_addr + (req->src1.vir_w * req->dst.vir_h) / 2;
return 0;
}
/* When the kernel version is lower than 4.4, no put buffer operation is required. */
void rga2_put_dma_info(struct rga2_reg *reg) {}
#endif
static int rga2_mmu_buf_get(struct rga2_mmu_buf_t *t, uint32_t size)
{
mutex_lock(&rga2_service.lock);
@@ -597,6 +1026,7 @@ static int rga2_mmu_flush_cache(struct rga2_reg *reg, struct rga2_req *req)
int ret;
int status;
struct page **pages = NULL;
struct rga_dma_buffer_t *dma_buffer = NULL;
MMU_Base = NULL;
DstMemSize = 0;
@@ -637,7 +1067,8 @@ static int rga2_mmu_flush_cache(struct rga2_reg *reg, struct rga2_req *req)
mutex_unlock(&rga2_service.lock);
if (DstMemSize) {
if (req->sg_dst) {
dma_buffer = &reg->dma_buffer_dst;
if (dma_buffer->sgt) {
status = -EINVAL;
goto out;
} else {
@@ -678,6 +1109,8 @@ static int rga2_mmu_info_BitBlt_mode(struct rga2_reg *reg, struct rga2_req *req)
int status;
uint32_t uv_size, v_size;
struct page **pages = NULL;
struct rga_dma_buffer_t *dma_buffer = NULL;
MMU_Base = NULL;
Src0MemSize = 0;
Src1MemSize = 0;
@@ -749,8 +1182,10 @@ static int rga2_mmu_info_BitBlt_mode(struct rga2_reg *reg, struct rga2_req *req)
mutex_unlock(&rga2_service.lock);
if (Src0MemSize) {
if (req->sg_src0) {
ret = rga2_MapION(req->sg_src0,
dma_buffer = &reg->dma_buffer_src0;
if (dma_buffer->sgt) {
ret = rga2_MapION(dma_buffer->sgt,
&MMU_Base[0], Src0MemSize);
} else {
ret = rga2_MapUserMemory(&pages[0], &MMU_Base[0],
@@ -788,9 +1223,12 @@ static int rga2_mmu_info_BitBlt_mode(struct rga2_reg *reg, struct rga2_req *req)
req->src.v_addr = (req->src.v_addr & (~PAGE_MASK)) |
(v_size << PAGE_SHIFT);
}
if (Src1MemSize) {
if (req->sg_src1) {
ret = rga2_MapION(req->sg_src1,
dma_buffer = &reg->dma_buffer_src1;
if (dma_buffer->sgt) {
ret = rga2_MapION(dma_buffer->sgt,
MMU_Base + Src0MemSize, Src1MemSize);
} else {
ret = rga2_MapUserMemory(&pages[0],
@@ -813,8 +1251,10 @@ static int rga2_mmu_info_BitBlt_mode(struct rga2_reg *reg, struct rga2_req *req)
req->src1.yrgb_addr = (req->src1.yrgb_addr & (~PAGE_MASK));
}
if (DstMemSize) {
if (req->sg_dst) {
ret = rga2_MapION(req->sg_dst, MMU_Base + Src0MemSize
dma_buffer = &reg->dma_buffer_dst;
if (dma_buffer->sgt) {
ret = rga2_MapION(dma_buffer->sgt, MMU_Base + Src0MemSize
+ Src1MemSize, DstMemSize);
} else if (req->alpha_mode_0 != 0 && req->bitblt_mode == 0) {
/* The blend mode of src + dst => dst requires clean and invalidate */
@@ -900,6 +1340,7 @@ static int rga2_mmu_info_color_palette_mode(struct rga2_reg *reg, struct rga2_re
uint8_t shift;
uint32_t sw, byte_num;
struct rga_dma_buffer_t *dma_buffer = NULL;
shift = 3 - (req->palette_mode & 3);
sw = req->src.vir_w*req->src.vir_h;
@@ -961,8 +1402,10 @@ static int rga2_mmu_info_color_palette_mode(struct rga2_reg *reg, struct rga2_re
mutex_unlock(&rga2_service.lock);
if(SrcMemSize) {
if (req->sg_src0) {
ret = rga2_MapION(req->sg_src0,
dma_buffer = &reg->dma_buffer_src0;
if (dma_buffer->sgt) {
ret = rga2_MapION(dma_buffer->sgt,
&MMU_Base[0], SrcMemSize);
} else {
ret = rga2_MapUserMemory(&pages[0], &MMU_Base[0],
@@ -990,8 +1433,10 @@ static int rga2_mmu_info_color_palette_mode(struct rga2_reg *reg, struct rga2_re
}
if(DstMemSize) {
if (req->sg_dst) {
ret = rga2_MapION(req->sg_dst,
dma_buffer = &reg->dma_buffer_dst;
if (dma_buffer->sgt) {
ret = rga2_MapION(dma_buffer->sgt,
MMU_Base + SrcMemSize, DstMemSize);
} else {
ret = rga2_MapUserMemory(&pages[0], MMU_Base + SrcMemSize,
@@ -1045,6 +1490,7 @@ static int rga2_mmu_info_color_fill_mode(struct rga2_reg *reg, struct rga2_req *
uint32_t *MMU_Base, *MMU_Base_phys;
int ret;
int status;
struct rga_dma_buffer_t *dma_buffer = NULL;
DstMemSize = 0;
DstPageCount = 0;
@@ -1082,8 +1528,10 @@ static int rga2_mmu_info_color_fill_mode(struct rga2_reg *reg, struct rga2_req *
mutex_unlock(&rga2_service.lock);
if (DstMemSize) {
if (req->sg_dst) {
ret = rga2_MapION(req->sg_dst, &MMU_Base[0], DstMemSize);
dma_buffer = &reg->dma_buffer_dst;
if (dma_buffer->sgt) {
ret = rga2_MapION(dma_buffer->sgt, &MMU_Base[0], DstMemSize);
}
else {
ret = rga2_MapUserMemory(&pages[0], &MMU_Base[0],
@@ -1133,6 +1581,7 @@ static int rga2_mmu_info_update_palette_table_mode(struct rga2_reg *reg, struct
uint32_t AllSize;
uint32_t *MMU_Base, *MMU_Base_phys;
int ret, status;
struct rga_dma_buffer_t *dma_buffer = NULL;
MMU_Base = NULL;
LutPageCount = 0;
@@ -1175,8 +1624,10 @@ static int rga2_mmu_info_update_palette_table_mode(struct rga2_reg *reg, struct
mutex_unlock(&rga2_service.lock);
if (LutMemSize) {
if (req->sg_els) {
ret = rga2_MapION(req->sg_els,
dma_buffer = &reg->dma_buffer_els;
if (dma_buffer->sgt) {
ret = rga2_MapION(dma_buffer->sgt,
&MMU_Base[0], LutMemSize);
} else {
ret = rga2_MapUserMemory(&pages[0], &MMU_Base[0],

View File

@@ -28,5 +28,8 @@ int rga2_set_mmu_info(struct rga2_reg *reg, struct rga2_req *req);
void rga2_dma_flush_range(void *pstart, void *pend);
dma_addr_t rga2_dma_flush_page(struct page *page, int map);
int rga2_get_dma_info(struct rga2_reg *reg, struct rga2_req *req);
void rga2_put_dma_info(struct rga2_reg *reg);
#endif