diff --git a/drivers/video/rockchip/rga3/include/rga.h b/drivers/video/rockchip/rga3/include/rga.h index f56181edd6cf..6b19eabc895c 100644 --- a/drivers/video/rockchip/rga3/include/rga.h +++ b/drivers/video/rockchip/rga3/include/rga.h @@ -73,7 +73,8 @@ enum rga_memory_type { RGA_DMA_BUFFER = 0, RGA_VIRTUAL_ADDRESS, - RGA_PHYSICAL_ADDRESS + RGA_PHYSICAL_ADDRESS, + RGA_DMA_BUFFER_PTR, }; enum rga_scale_up_mode { @@ -840,6 +841,7 @@ struct rga_mpi_job_t { struct rga_video_frame_info *src; struct rga_video_frame_info *pat; struct rga_video_frame_info *dst; + struct rga_video_frame_info *output; int ctx_id; }; diff --git a/drivers/video/rockchip/rga3/include/rga_dma_buf.h b/drivers/video/rockchip/rga3/include/rga_dma_buf.h index 9471496f455d..e709b684f827 100644 --- a/drivers/video/rockchip/rga3/include/rga_dma_buf.h +++ b/drivers/video/rockchip/rga3/include/rga_dma_buf.h @@ -24,9 +24,11 @@ int rga_iommu_map_virt_addr(struct rga_memory_parm *memory_parm, struct mm_struct *mm); void rga_iommu_unmap_virt_addr(struct rga_dma_buffer *virt_addr); +int rga_dma_map_buf(struct dma_buf *dma_buf, struct rga_dma_buffer *rga_dma_buffer, + enum dma_data_direction dir, struct device *rga_dev); int rga_dma_map_fd(int fd, struct rga_dma_buffer *rga_dma_buffer, enum dma_data_direction dir, struct device *rga_dev); -void rga_dma_unmap_fd(struct rga_dma_buffer *rga_dma_buffer); +void rga_dma_unmap_buf(struct rga_dma_buffer *rga_dma_buffer); int rga_dma_get_info(struct rga_job *job); void rga_dma_put_info(struct rga_job *job); diff --git a/drivers/video/rockchip/rga3/rga_debugger.c b/drivers/video/rockchip/rga3/rga_debugger.c index ed614acd5ed2..e2f73de3a268 100644 --- a/drivers/video/rockchip/rga3/rga_debugger.c +++ b/drivers/video/rockchip/rga3/rga_debugger.c @@ -226,6 +226,7 @@ static int rga_mm_session_show(struct seq_file *m, void *data) switch (dump_buffer->type) { case RGA_DMA_BUFFER: + case RGA_DMA_BUFFER_PTR: seq_puts(m, "dma_buffer:\n"); for (i = 0; i < dump_buffer->dma_buffer_size; i++) { seq_printf(m, "\t core %d:\n", dump_buffer->dma_buffer[i].core); diff --git a/drivers/video/rockchip/rga3/rga_dma_buf.c b/drivers/video/rockchip/rga3/rga_dma_buf.c index 0e02a22ae4ec..1a091c5ef5db 100644 --- a/drivers/video/rockchip/rga3/rga_dma_buf.c +++ b/drivers/video/rockchip/rga3/rga_dma_buf.c @@ -737,6 +737,53 @@ static int rga_dma_memory_check(struct rga_dma_buffer_t *rga_dma_buffer, return ret; } +int rga_dma_map_buf(struct dma_buf *dma_buf, struct rga_dma_buffer *rga_dma_buffer, + enum dma_data_direction dir, struct device *rga_dev) +{ + struct dma_buf_attachment *attach = NULL; + struct sg_table *sgt = NULL; + int ret = 0; + + if (dma_buf != NULL) { + get_dma_buf(dma_buf); + } else { + pr_err("dma_buf is Invalid[%p]\n", dma_buf); + return -EINVAL; + } + + attach = dma_buf_attach(dma_buf, rga_dev); + if (IS_ERR(attach)) { + pr_err("Failed to attach dma_buf\n"); + ret = -EINVAL; + goto err_get_attach; + } + + sgt = dma_buf_map_attachment(attach, dir); + if (IS_ERR(sgt)) { + pr_err("Failed to map src attachment\n"); + ret = -EINVAL; + goto err_get_sgt; + } + + rga_dma_buffer->dma_buf = dma_buf; + rga_dma_buffer->attach = attach; + rga_dma_buffer->sgt = sgt; + rga_dma_buffer->iova = sg_dma_address(sgt->sgl); + 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; +} + int rga_dma_map_fd(int fd, struct rga_dma_buffer *rga_dma_buffer, enum dma_data_direction dir, struct device *rga_dev) { @@ -785,7 +832,7 @@ err_get_attach: return ret; } -void rga_dma_unmap_fd(struct rga_dma_buffer *rga_dma_buffer) +void rga_dma_unmap_buf(struct rga_dma_buffer *rga_dma_buffer) { if (rga_dma_buffer->attach && rga_dma_buffer->sgt) dma_buf_unmap_attachment(rga_dma_buffer->attach, diff --git a/drivers/video/rockchip/rga3/rga_drv.c b/drivers/video/rockchip/rga3/rga_drv.c index 70d7fa30140f..b652b2ff338e 100644 --- a/drivers/video/rockchip/rga3/rga_drv.c +++ b/drivers/video/rockchip/rga3/rga_drv.c @@ -41,16 +41,33 @@ static const struct rga_backend_ops rga2_ops = { .soft_reset = rga2_soft_reset }; -static int rga_mpi_set_channel_info(uint32_t flags_mask, uint32_t flags, - struct rga_video_frame_info *mpi_frame, - struct rga_img_info_t *channel_info, - struct rga_img_info_t *cache_info) +static int rga_mpi_set_channel_buffer(struct dma_buf *dma_buf, struct rga_img_info_t *channel_info) +{ + struct rga_external_buffer buffer; + + buffer.memory = (unsigned long)dma_buf; + buffer.type = RGA_DMA_BUFFER_PTR; + buffer.memory_parm.width = channel_info->vir_w; + buffer.memory_parm.height = channel_info->vir_h; + buffer.memory_parm.format = channel_info->format; + + buffer.handle = rga_mm_import_buffer(&buffer); + if (buffer.handle == 0) { + pr_err("can not import dma_buf %p\n", dma_buf); + return -EFAULT; + } + channel_info->yrgb_addr = buffer.handle; + + return 0; +} + +static void rga_mpi_set_channel_info(uint32_t flags_mask, uint32_t flags, + struct rga_video_frame_info *mpi_frame, + struct rga_img_info_t *channel_info, + struct rga_img_info_t *cache_info) { uint32_t fix_enable_flag, cache_info_flag; - if (mpi_frame == NULL) - return -EFAULT; - switch (flags_mask) { case RGA_CONTEXT_SRC_MASK: fix_enable_flag = RGA_CONTEXT_SRC_FIX_ENABLE; @@ -65,7 +82,7 @@ static int rga_mpi_set_channel_info(uint32_t flags_mask, uint32_t flags, cache_info_flag = RGA_CONTEXT_DST_CACHE_INFO; break; default: - return -EFAULT; + return; } if (flags & fix_enable_flag) { @@ -91,8 +108,6 @@ static int rga_mpi_set_channel_info(uint32_t flags_mask, uint32_t flags, } } - - return 0; } int rga_mpi_commit(struct rga_mpi_job_t *mpi_job) @@ -114,8 +129,8 @@ int rga_mpi_commit(struct rga_mpi_job_t *mpi_job) spin_lock_irqsave(&ctx->lock, flags); - ctx->sync_mode = RGA_BLIT_SYNC; /* TODO: batch mode need mpi async mode */ + ctx->sync_mode = RGA_BLIT_SYNC; ctx->use_batch_mode = false; cached_cmd = ctx->cached_cmd; @@ -123,37 +138,58 @@ int rga_mpi_commit(struct rga_mpi_job_t *mpi_job) spin_unlock_irqrestore(&ctx->lock, flags); - ret = rga_mpi_set_channel_info(RGA_CONTEXT_SRC_MASK, - ctx->mpi_config_flags, - mpi_job->src, - &mpi_cmd.src, - &cached_cmd->src); - if (ret < 0) { - pr_err("src channel set info error!\n"); - return ret; + /* set channel info */ + if ((mpi_job->src != NULL) && (ctx->flags & RGA_CONTEXT_SRC_MASK)) + rga_mpi_set_channel_info(RGA_CONTEXT_SRC_MASK, + ctx->flags, + mpi_job->src, + &mpi_cmd.src, + &cached_cmd->src); + + if ((mpi_job->pat != NULL) && (ctx->flags & RGA_CONTEXT_PAT_MASK)) + rga_mpi_set_channel_info(RGA_CONTEXT_PAT_MASK, + ctx->flags, + mpi_job->pat, + &mpi_cmd.pat, + &cached_cmd->pat); + + if ((mpi_job->dst != NULL) && (ctx->flags & RGA_CONTEXT_DST_MASK)) + rga_mpi_set_channel_info(RGA_CONTEXT_DST_MASK, + ctx->flags, + mpi_job->dst, + &mpi_cmd.dst, + &cached_cmd->dst); + + /* set buffer handle */ + if (mpi_job->dma_buf_src0 != NULL) { + ret = rga_mpi_set_channel_buffer(mpi_job->dma_buf_src0, &mpi_cmd.src); + if (ret < 0) { + pr_err("src channel set buffer handle failed!\n"); + return ret; + } } - ret = rga_mpi_set_channel_info(RGA_CONTEXT_PAT_MASK, - ctx->mpi_config_flags, - mpi_job->pat, - &mpi_cmd.pat, - &cached_cmd->pat); - if (ret < 0) { - pr_err("src1 channel set info error!\n"); - return ret; + if (mpi_job->dma_buf_src1 != NULL) { + ret = rga_mpi_set_channel_buffer(mpi_job->dma_buf_src1, &mpi_cmd.pat); + if (ret < 0) { + pr_err("src1 channel set buffer handle failed!\n"); + return ret; + } } - ret = rga_mpi_set_channel_info(RGA_CONTEXT_DST_MASK, - ctx->mpi_config_flags, - mpi_job->dst, - &mpi_cmd.dst, - &cached_cmd->dst); - if (ret < 0) { - pr_err("dst channel set info error!\n"); - return ret; + if (mpi_job->dma_buf_dst != NULL) { + ret = rga_mpi_set_channel_buffer(mpi_job->dma_buf_dst, &mpi_cmd.dst); + if (ret < 0) { + pr_err("dst channel set buffer handle failed!\n"); + return ret; + } } + mpi_cmd.handle_flag = 1; + mpi_cmd.mmu_info.mmu_en = 0; + mpi_cmd.mmu_info.mmu_flag = 0; + /* commit job */ if (ctx->cmd_num > 1) { pr_err("Currently ctx does not support multiple tasks!"); /* TODO */ @@ -176,16 +212,23 @@ int rga_mpi_commit(struct rga_mpi_job_t *mpi_job) return ret; } + if ((mpi_job->dma_buf_src0 != NULL) && (mpi_cmd.src.yrgb_addr > 0)) + rga_mm_release_buffer(mpi_cmd.src.yrgb_addr); + if ((mpi_job->dma_buf_src1 != NULL) && (mpi_cmd.pat.yrgb_addr > 0)) + rga_mm_release_buffer(mpi_cmd.pat.yrgb_addr); + if ((mpi_job->dma_buf_dst != NULL) && (mpi_cmd.dst.yrgb_addr > 0)) + rga_mm_release_buffer(mpi_cmd.dst.yrgb_addr); + /* copy dst info to mpi job for next node */ - if (mpi_job->dst != NULL) { - mpi_job->dst->x_offset = mpi_cmd.dst.x_offset; - mpi_job->dst->y_offset = mpi_cmd.dst.y_offset; - mpi_job->dst->width = mpi_cmd.dst.act_w; - mpi_job->dst->height = mpi_cmd.dst.act_h; - mpi_job->dst->vir_w = mpi_cmd.dst.vir_w; - mpi_job->dst->vir_h = mpi_cmd.dst.vir_h; - mpi_job->dst->rd_mode = mpi_cmd.dst.rd_mode; - mpi_job->dst->format = mpi_cmd.dst.format; + if (mpi_job->output != NULL) { + mpi_job->output->x_offset = mpi_cmd.dst.x_offset; + mpi_job->output->y_offset = mpi_cmd.dst.y_offset; + mpi_job->output->width = mpi_cmd.dst.act_w; + mpi_job->output->height = mpi_cmd.dst.act_h; + mpi_job->output->vir_w = mpi_cmd.dst.vir_w; + mpi_job->output->vir_h = mpi_cmd.dst.vir_h; + mpi_job->output->rd_mode = mpi_cmd.dst.rd_mode; + mpi_job->output->format = mpi_cmd.dst.format; } return ret; @@ -358,8 +401,10 @@ static long rga_ioctl_import_buffer(unsigned long arg) for (i = 0; i < buffer_pool.size; i++) { ret = rga_mm_import_buffer(&external_buffer[i]); - if (ret < 0) { - pr_err("buffer[%d] mm import buffer failed!\n", i); + if (ret == 0) { + pr_err("buffer[%d] mm import buffer failed! memory = 0x%lx, type = 0x%x\n", + i, (unsigned long)external_buffer[i].memory, + external_buffer[i].type); goto err_free_external_buffer; } diff --git a/drivers/video/rockchip/rga3/rga_job.c b/drivers/video/rockchip/rga3/rga_job.c index 031525472843..eaeb5ab57f64 100644 --- a/drivers/video/rockchip/rga3/rga_job.c +++ b/drivers/video/rockchip/rga3/rga_job.c @@ -1113,9 +1113,6 @@ int rga_job_mpi_commit(struct rga_req *rga_command_base, job->dma_buf_dst = mpi_job->dma_buf_dst; } - /* Increments the reference count on the dma-buf */ - rga_get_dma_buf(job); - job->ctx_id = ctx->id; if (ctx->sync_mode == RGA_BLIT_ASYNC) { diff --git a/drivers/video/rockchip/rga3/rga_mm.c b/drivers/video/rockchip/rga3/rga_mm.c index 8888111f91f2..801c711991e8 100644 --- a/drivers/video/rockchip/rga3/rga_mm.c +++ b/drivers/video/rockchip/rga3/rga_mm.c @@ -317,7 +317,7 @@ static void rga_mm_unmap_dma_buffer(struct rga_internal_buffer *internal_buffer) int i; for (i = 0; i < internal_buffer->dma_buffer_size; i++) { - rga_dma_unmap_fd(&internal_buffer->dma_buffer[i]); + rga_dma_unmap_buf(&internal_buffer->dma_buffer[i]); if (i == 0 && internal_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS && @@ -351,10 +351,19 @@ static int rga_mm_map_dma_buffer(struct rga_external_buffer *external_buffer, i != 0) continue; - ret = rga_dma_map_fd((int)external_buffer->memory, - &internal_buffer->dma_buffer[i], - DMA_BIDIRECTIONAL, - rga_drvdata->rga_scheduler[i]->dev); + if (external_buffer->type == RGA_DMA_BUFFER) + ret = rga_dma_map_fd((int)external_buffer->memory, + &internal_buffer->dma_buffer[i], + DMA_BIDIRECTIONAL, + rga_drvdata->rga_scheduler[i]->dev); + else if (external_buffer->type == RGA_DMA_BUFFER_PTR) + ret = rga_dma_map_buf((struct dma_buf *) + u64_to_user_ptr(external_buffer->memory), + &internal_buffer->dma_buffer[i], + DMA_BIDIRECTIONAL, + rga_drvdata->rga_scheduler[i]->dev); + else + ret = -EFAULT; if (ret < 0) { pr_err("%s core[%d] map dma buffer error!\n", __func__, rga_drvdata->rga_scheduler[0]->core); @@ -535,6 +544,7 @@ static int rga_mm_unmap_buffer(struct rga_internal_buffer *internal_buffer) { switch (internal_buffer->type) { case RGA_DMA_BUFFER: + case RGA_DMA_BUFFER_PTR: rga_mm_unmap_dma_buffer(internal_buffer); break; case RGA_VIRTUAL_ADDRESS: @@ -561,7 +571,8 @@ static int rga_mm_map_buffer(struct rga_external_buffer *external_buffer, switch (external_buffer->type) { case RGA_DMA_BUFFER: - internal_buffer->type = RGA_DMA_BUFFER; + case RGA_DMA_BUFFER_PTR: + internal_buffer->type = external_buffer->type; ret = rga_mm_map_dma_buffer(external_buffer, internal_buffer); if (ret < 0) { @@ -669,6 +680,20 @@ rga_mm_lookup_external(struct rga_mm *mm_session, } break; + case RGA_DMA_BUFFER_PTR: + idr_for_each_entry(&mm_session->memory_idr, temp_buffer, id) { + if (temp_buffer->dma_buffer == NULL) + continue; + + if ((unsigned long)temp_buffer->dma_buffer[0].dma_buf == + external_buffer->memory) { + output_buffer = temp_buffer; + break; + } + } + + break; + default: pr_err("Illegal external buffer!\n"); return NULL; @@ -742,6 +767,7 @@ void rga_mm_dump_info(struct rga_mm *mm_session) switch (dump_buffer->type) { case RGA_DMA_BUFFER: + case RGA_DMA_BUFFER_PTR: pr_info("dma_buffer:\n"); for (i = 0; i < dump_buffer->dma_buffer_size; i++) { pr_info("\t core %d:\n", dump_buffer->dma_buffer[i].core); @@ -904,6 +930,7 @@ static int rga_mm_get_channel_handle_info(struct rga_mm *mm, switch (internal_buffer->type) { case RGA_DMA_BUFFER: + case RGA_DMA_BUFFER_PTR: if (job->core == RGA3_SCHEDULER_CORE0 || job->core == RGA3_SCHEDULER_CORE1) { img->yrgb_addr = rga_mm_lookup_iova(internal_buffer, job->core); @@ -1071,7 +1098,7 @@ uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer) mm = rga_drvdata->mm; if (mm == NULL) { pr_err("rga mm is null!\n"); - return -EFAULT; + return 0; } mutex_lock(&mm->lock); @@ -1091,7 +1118,7 @@ uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer) pr_err("%s alloc internal_buffer error!\n", __func__); mutex_unlock(&mm->lock); - return -ENOMEM; + return 0; } ret = rga_mm_map_buffer(external_buffer, internal_buffer); @@ -1117,7 +1144,7 @@ FREE_INTERNAL_BUFFER: mutex_unlock(&mm->lock); kfree(internal_buffer); - return ret; + return 0; } int rga_mm_release_buffer(uint32_t handle)