diff --git a/drivers/video/rockchip/rga3/include/rga.h b/drivers/video/rockchip/rga3/include/rga.h index d9613d12f8ea..27e8eb446f30 100644 --- a/drivers/video/rockchip/rga3/include/rga.h +++ b/drivers/video/rockchip/rga3/include/rga.h @@ -461,7 +461,9 @@ struct rga_req { uint8_t priority; int32_t out_fence_fd; - uint8_t reservr[128]; + uint8_t handle_flag; + + uint8_t reservr[127]; }; struct rga2_req { diff --git a/drivers/video/rockchip/rga3/include/rga_drv.h b/drivers/video/rockchip/rga3/include/rga_drv.h index 5726fcd2e3c9..e7f261c7c5b1 100644 --- a/drivers/video/rockchip/rga3/include/rga_drv.h +++ b/drivers/video/rockchip/rga3/include/rga_drv.h @@ -249,6 +249,12 @@ struct rga_job { /* used by rga2 */ struct rga_dma_buffer_t *rga_dma_buffer_els; + struct rga_internal_buffer *src_buffer; + struct rga_internal_buffer *src1_buffer; + struct rga_internal_buffer *dst_buffer; + /* used by rga2 */ + struct rga_internal_buffer *els_buffer; + struct dma_buf *dma_buf_src0; struct dma_buf *dma_buf_src1; struct dma_buf *dma_buf_dst; diff --git a/drivers/video/rockchip/rga3/include/rga_job.h b/drivers/video/rockchip/rga3/include/rga_job.h index caf89ed5215e..44d3b80367ab 100644 --- a/drivers/video/rockchip/rga3/include/rga_job.h +++ b/drivers/video/rockchip/rga3/include/rga_job.h @@ -13,9 +13,12 @@ #include "rga_drv.h" -#define RGA_JOB_DONE (1 << 0) -#define RGA_JOB_ASYNC (1 << 1) -#define RGA_JOB_SYNC (1 << 2) +enum job_flags { + RGA_JOB_DONE = 1 << 0, + RGA_JOB_ASYNC = 1 << 1, + RGA_JOB_SYNC = 1 << 2, + RGA_JOB_USE_HANDLE = 1 << 3, +}; void rga_job_done(struct rga_scheduler_t *rga_scheduler, int ret); int rga_job_commit(struct rga_req *rga_command_base, int flags); diff --git a/drivers/video/rockchip/rga3/include/rga_mm.h b/drivers/video/rockchip/rga3/include/rga_mm.h index 43cf698518a8..409efc022bc8 100644 --- a/drivers/video/rockchip/rga3/include/rga_mm.h +++ b/drivers/video/rockchip/rga3/include/rga_mm.h @@ -34,9 +34,14 @@ struct rga_mm { }; struct rga_internal_buffer *rga_mm_lookup_handle(struct rga_mm *mm_session, uint32_t handle); +dma_addr_t rga_mm_lookup_iova(struct rga_internal_buffer *buffer, int core); +struct sg_table *rga_mm_lookup_sgt(struct rga_internal_buffer *buffer, int core); void rga_mm_dump_info(struct rga_mm *session); +int rga_mm_get_handle_info(struct rga_job *job); +void rga_mm_put_handle_info(struct rga_job *job); + uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer); int rga_mm_release_buffer(uint32_t handle); diff --git a/drivers/video/rockchip/rga3/rga2_mmu_info.c b/drivers/video/rockchip/rga3/rga2_mmu_info.c index 280eed5ddf7a..a76f22feed6d 100644 --- a/drivers/video/rockchip/rga3/rga2_mmu_info.c +++ b/drivers/video/rockchip/rga3/rga2_mmu_info.c @@ -9,6 +9,8 @@ #include "rga2_mmu_info.h" #include "rga_dma_buf.h" +#include "rga_mm.h" +#include "rga_job.h" #if CONFIG_ROCKCHIP_RGA_DEBUGGER extern int RGA_DEBUG_CHECK_MODE; @@ -511,6 +513,7 @@ static int rga2_mmu_info_BitBlt_mode(struct rga2_mmu_other_t *reg, int status; uint32_t uv_size, v_size; struct page **pages = NULL; + struct sg_table *sgt; struct rga_scheduler_t *scheduler = NULL; @@ -590,24 +593,52 @@ static int rga2_mmu_info_BitBlt_mode(struct rga2_mmu_other_t *reg, mutex_unlock(&rga_drvdata->lock); if (Src0MemSize) { - if (job->rga_dma_buffer_src0) { - ret = rga2_MapION(job->rga_dma_buffer_src0->sgt, - &MMU_Base[0], Src0MemSize); + if (job->src_buffer) { + switch (job->src_buffer->type) { + case RGA_DMA_BUFFER: + sgt = rga_mm_lookup_sgt(job->src_buffer, scheduler->core); + if (sgt == NULL) { + pr_err("rga2 cannot get sgt from handle!\n"); + status = -EFAULT; + goto out; + } + ret = rga2_MapION(sgt, &MMU_Base[0], Src0MemSize); + + break; + case RGA_VIRTUAL_ADDRESS: + ret = rga2_MapUserMemory(&pages[0], &MMU_Base[0], + Src0Start, Src0PageCount, + 0, MMU_MAP_CLEAN, scheduler, + job->src_buffer->current_mm); + /* Save pagetable to unmap. */ + reg->MMU_src0_base = MMU_Base; + reg->MMU_src0_count = Src0PageCount; + + break; + default: + status = -EFAULT; + goto out; + } } else { - ret = rga2_MapUserMemory(&pages[0], &MMU_Base[0], - Src0Start, Src0PageCount, - 0, MMU_MAP_CLEAN, scheduler, job->mm); + if (job->rga_dma_buffer_src0) { + ret = rga2_MapION(job->rga_dma_buffer_src0->sgt, + &MMU_Base[0], Src0MemSize); + } else { + ret = rga2_MapUserMemory(&pages[0], &MMU_Base[0], + Src0Start, Src0PageCount, + 0, MMU_MAP_CLEAN, scheduler, job->mm); #if CONFIG_ROCKCHIP_RGA_DEBUGGER - if (RGA_DEBUG_CHECK_MODE) - /* TODO: */ - rga2_user_memory_check(&pages[0], - req->src.vir_w, - req->src.vir_h, - req->src.format, 1); + if (RGA_DEBUG_CHECK_MODE) + /* TODO: */ + rga2_user_memory_check(&pages[0], + req->src.vir_w, + req->src.vir_h, + req->src.format, 1); #endif - /* Save pagetable to unmap. */ - reg->MMU_src0_base = MMU_Base; - reg->MMU_src0_count = Src0PageCount; + /* Save pagetable to unmap. */ + reg->MMU_src0_base = MMU_Base; + reg->MMU_src0_count = Src0PageCount; + } } if (ret < 0) { @@ -630,18 +661,48 @@ static int rga2_mmu_info_BitBlt_mode(struct rga2_mmu_other_t *reg, } if (Src1MemSize) { - if (job->rga_dma_buffer_src1) { - ret = rga2_MapION(job->rga_dma_buffer_src1->sgt, - MMU_Base + Src0MemSize, Src1MemSize); - } else { - ret = rga2_MapUserMemory(&pages[0], - MMU_Base + Src0MemSize, - Src1Start, Src1PageCount, - 0, MMU_MAP_CLEAN, scheduler, job->mm); + if (job->src1_buffer) { + switch (job->src1_buffer->type) { + case RGA_DMA_BUFFER: + sgt = rga_mm_lookup_sgt(job->src1_buffer, scheduler->core); + if (sgt == NULL) { + pr_err("rga2 cannot get sgt from handle!\n"); + status = -EFAULT; + goto out; + } + ret = rga2_MapION(sgt, MMU_Base + Src0MemSize, Src1MemSize); - /* Save pagetable to unmap. */ - reg->MMU_src1_base = MMU_Base + Src0MemSize; - reg->MMU_src1_count = Src1PageCount; + break; + case RGA_VIRTUAL_ADDRESS: + ret = rga2_MapUserMemory(&pages[0], + MMU_Base + Src0MemSize, + Src1Start, Src1PageCount, + 0, MMU_MAP_CLEAN, scheduler, + job->src1_buffer->current_mm); + + /* Save pagetable to unmap. */ + reg->MMU_src1_base = MMU_Base + Src0MemSize; + reg->MMU_src1_count = Src1PageCount; + + break; + default: + status = -EFAULT; + goto out; + } + } else { + if (job->rga_dma_buffer_src1) { + ret = rga2_MapION(job->rga_dma_buffer_src1->sgt, + MMU_Base + Src0MemSize, Src1MemSize); + } else { + ret = rga2_MapUserMemory(&pages[0], + MMU_Base + Src0MemSize, + Src1Start, Src1PageCount, + 0, MMU_MAP_CLEAN, scheduler, job->mm); + + /* Save pagetable to unmap. */ + reg->MMU_src1_base = MMU_Base + Src0MemSize; + reg->MMU_src1_count = Src1PageCount; + } } if (ret < 0) { @@ -656,48 +717,88 @@ static int rga2_mmu_info_BitBlt_mode(struct rga2_mmu_other_t *reg, } if (DstMemSize) { - if (job->rga_dma_buffer_dst) { - ret = - rga2_MapION(job->rga_dma_buffer_dst->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 - */ - ret = rga2_MapUserMemory(&pages[0], MMU_Base - + Src0MemSize + Src1MemSize, - DstStart, DstPageCount, 1, - MMU_MAP_CLEAN | - MMU_MAP_INVALID, scheduler, job->mm); -#if CONFIG_ROCKCHIP_RGA_DEBUGGER - if (RGA_DEBUG_CHECK_MODE) - rga2_user_memory_check(&pages[0], - req->dst.vir_w, - req->dst.vir_h, - req->dst.format, 2); -#endif - /* Save pagetable to invalid cache and unmap. */ - reg->MMU_dst_base = - MMU_Base + Src0MemSize + Src1MemSize; - reg->MMU_dst_count = DstPageCount; + if (job->dst_buffer) { + switch (job->dst_buffer->type) { + case RGA_DMA_BUFFER: + sgt = rga_mm_lookup_sgt(job->dst_buffer, scheduler->core); + if (sgt == NULL) { + pr_err("rga2 cannot get sgt from handle!\n"); + status = -EFAULT; + goto out; + } + ret = rga2_MapION(sgt, MMU_Base + Src0MemSize + Src1MemSize, + DstMemSize); + + break; + case RGA_VIRTUAL_ADDRESS: + if (req->alpha_mode_0 != 0 && req->bitblt_mode == 0) + ret = rga2_MapUserMemory(&pages[0], MMU_Base + + Src0MemSize + Src1MemSize, + DstStart, DstPageCount, + 1, + MMU_MAP_CLEAN | MMU_MAP_INVALID, + scheduler, + job->dst_buffer->current_mm); + else + ret = rga2_MapUserMemory(&pages[0], MMU_Base + + Src0MemSize + Src1MemSize, + DstStart, DstPageCount, + 1, + MMU_MAP_INVALID, + scheduler, + job->dst_buffer->current_mm); + + /* Save pagetable to invalid cache and unmap. */ + reg->MMU_dst_base = MMU_Base + Src0MemSize + Src1MemSize; + reg->MMU_dst_count = DstPageCount; + + break; + default: + status = -EFAULT; + goto out; + } + } else { - ret = rga2_MapUserMemory(&pages[0], MMU_Base - + Src0MemSize + Src1MemSize, - DstStart, DstPageCount, - 1, MMU_MAP_INVALID, scheduler, job->mm); + if (job->rga_dma_buffer_dst) { + ret = rga2_MapION(job->rga_dma_buffer_dst->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 + */ + ret = rga2_MapUserMemory(&pages[0], MMU_Base + + Src0MemSize + Src1MemSize, + DstStart, DstPageCount, 1, + MMU_MAP_CLEAN | + MMU_MAP_INVALID, scheduler, job->mm); #if CONFIG_ROCKCHIP_RGA_DEBUGGER - if (RGA_DEBUG_CHECK_MODE) - rga2_user_memory_check(&pages[0], - req->dst.vir_w, - req->dst.vir_h, - req->dst.format, 2); + if (RGA_DEBUG_CHECK_MODE) + rga2_user_memory_check(&pages[0], + req->dst.vir_w, + req->dst.vir_h, + req->dst.format, 2); #endif - /* Save pagetable to invalid cache and unmap. */ - reg->MMU_dst_base = - MMU_Base + Src0MemSize + Src1MemSize; - reg->MMU_dst_count = DstPageCount; + /* Save pagetable to invalid cache and unmap. */ + reg->MMU_dst_base = MMU_Base + Src0MemSize + Src1MemSize; + reg->MMU_dst_count = DstPageCount; + } else { + ret = rga2_MapUserMemory(&pages[0], MMU_Base + + Src0MemSize + Src1MemSize, + DstStart, DstPageCount, + 1, MMU_MAP_INVALID, scheduler, job->mm); +#if CONFIG_ROCKCHIP_RGA_DEBUGGER + if (RGA_DEBUG_CHECK_MODE) + rga2_user_memory_check(&pages[0], + req->dst.vir_w, + req->dst.vir_h, + req->dst.format, 2); +#endif + /* Save pagetable to invalid cache and unmap. */ + reg->MMU_dst_base = MMU_Base + Src0MemSize + Src1MemSize; + reg->MMU_dst_count = DstPageCount; + } } if (ret < 0) { @@ -756,6 +857,11 @@ static int rga2_mmu_info_color_palette_mode(struct rga2_mmu_other_t *reg, struct rga_scheduler_t *scheduler = NULL; + if (job->flags & RGA_JOB_USE_HANDLE) { + pr_err("color palette mode can not support handle.\n"); + return -EINVAL; + } + scheduler = get_scheduler(job->core); if (scheduler == NULL) { pr_err("failed to get scheduler, %s(%d)\n", __func__, @@ -920,6 +1026,7 @@ static int rga2_mmu_info_color_fill_mode(struct rga2_mmu_other_t *reg, uint32_t *MMU_Base, *MMU_Base_phys; int ret; int status; + struct sg_table *sgt; struct rga_scheduler_t *scheduler = NULL; @@ -964,13 +1071,46 @@ static int rga2_mmu_info_color_fill_mode(struct rga2_mmu_other_t *reg, mutex_unlock(&rga_drvdata->lock); if (DstMemSize) { - if (job->rga_dma_buffer_dst) { - ret = rga2_MapION(job->rga_dma_buffer_dst->sgt, - &MMU_Base[0], DstMemSize); + if (job->dst_buffer) { + switch (job->src_buffer->type) { + case RGA_DMA_BUFFER: + sgt = rga_mm_lookup_sgt(job->dst_buffer, scheduler->core); + if (sgt == NULL) { + pr_err("rga2 cannot get sgt from handle!\n"); + status = -EFAULT; + goto out; + } + ret = rga2_MapION(sgt, &MMU_Base[0], DstMemSize); + + break; + case RGA_VIRTUAL_ADDRESS: + ret = rga2_MapUserMemory(&pages[0], &MMU_Base[0], + DstStart, DstPageCount, + 1, MMU_MAP_INVALID, + scheduler, + job->dst_buffer->current_mm); + + /* Save pagetable to invalid cache and unmap. */ + reg->MMU_dst_base = MMU_Base; + reg->MMU_dst_count = DstPageCount; + + break; + default: + status = -EFAULT; + goto out; + } + } else { - ret = rga2_MapUserMemory(&pages[0], - &MMU_Base[0], DstStart, DstPageCount, - 1, MMU_MAP_INVALID, scheduler, job->mm); + if (job->rga_dma_buffer_dst) { + ret = rga2_MapION(job->rga_dma_buffer_dst->sgt, + &MMU_Base[0], DstMemSize); + } else { + ret = rga2_MapUserMemory(&pages[0], + &MMU_Base[0], DstStart, + DstPageCount, 1, + MMU_MAP_INVALID, + scheduler, job->mm); + } } if (ret < 0) { pr_err("map dst memory failed\n"); @@ -1002,6 +1142,7 @@ static int rga2_mmu_info_color_fill_mode(struct rga2_mmu_other_t *reg, return 0; } while (0); +out: return status; } @@ -1020,6 +1161,11 @@ static int rga2_mmu_info_update_palette_table_mode(struct rga2_mmu_other_t *reg, struct rga_scheduler_t *scheduler = NULL; + if (job->flags & RGA_JOB_USE_HANDLE) { + pr_err("update palette table mode can not support handle.\n"); + return -EINVAL; + } + scheduler = get_scheduler(job->core); if (scheduler == NULL) { pr_err("failed to get scheduler, %s(%d)\n", __func__, diff --git a/drivers/video/rockchip/rga3/rga_job.c b/drivers/video/rockchip/rga3/rga_job.c index a4cfbc1a485c..cfdbc06e914a 100644 --- a/drivers/video/rockchip/rga3/rga_job.c +++ b/drivers/video/rockchip/rga3/rga_job.c @@ -10,6 +10,7 @@ #include "rga_job.h" #include "rga_fence.h" #include "rga_dma_buf.h" +#include "rga_mm.h" #include "rga2_mmu_info.h" struct rga_job * @@ -62,53 +63,6 @@ static struct rga_scheduler_t *get_scheduler(struct rga_job *job) return scheduler; } -static void rga_job_free(struct rga_job *job) -{ - if (job->out_fence) - dma_fence_put(job->out_fence); - - free_page((unsigned long)job); -} - -static int rga_job_cleanup(struct rga_job *job) -{ - rga_job_free(job); - - return 0; -} - -static struct rga_job *rga_job_alloc(struct rga_req *rga_command_base) -{ - struct rga_job *job = NULL; - - job = (struct rga_job *)get_zeroed_page(GFP_KERNEL | GFP_DMA32); - if (!job) - return NULL; - - spin_lock_init(&job->fence_lock); - INIT_LIST_HEAD(&job->head); - - job->timestamp = ktime_get(); - job->running_time = ktime_get(); - - job->rga_command_base = *rga_command_base; - - if (rga_command_base->priority > 0) { - if (rga_command_base->priority > RGA_SCHED_PRIORITY_MAX) - job->priority = RGA_SCHED_PRIORITY_MAX; - else - job->priority = rga_command_base->priority; - } - - return job; -} - -static void print_job_info(struct rga_job *job) -{ - pr_info("job: priority = %d, core = %d\n", - job->priority, job->core); -} - static int rga_job_get_current_mm(struct rga_job *job) { int mmu_flag; @@ -169,6 +123,61 @@ static void rga_job_put_current_mm(struct rga_job *job) job->mm = NULL; } +static void rga_job_free(struct rga_job *job) +{ + if (job->out_fence) + dma_fence_put(job->out_fence); + + if (~job->flags & RGA_JOB_USE_HANDLE) + rga_job_put_current_mm(job); + + free_page((unsigned long)job); +} + +static int rga_job_cleanup(struct rga_job *job) +{ + rga_job_free(job); + + return 0; +} + +static struct rga_job *rga_job_alloc(struct rga_req *rga_command_base) +{ + struct rga_job *job = NULL; + + job = (struct rga_job *)get_zeroed_page(GFP_KERNEL | GFP_DMA32); + if (!job) + return NULL; + + spin_lock_init(&job->fence_lock); + INIT_LIST_HEAD(&job->head); + + job->timestamp = ktime_get(); + job->running_time = ktime_get(); + + job->rga_command_base = *rga_command_base; + + if (rga_command_base->priority > 0) { + if (rga_command_base->priority > RGA_SCHED_PRIORITY_MAX) + job->priority = RGA_SCHED_PRIORITY_MAX; + else + job->priority = rga_command_base->priority; + } + + if (job->rga_command_base.handle_flag & 1) + job->flags |= RGA_JOB_USE_HANDLE; + else + rga_job_get_current_mm(job); + + return job; +} + +static void print_job_info(struct rga_job *job) +{ + pr_info("job: priority = %d, core = %d\n", + job->priority, job->core); +} + static int rga_job_run(struct rga_job *job, struct rga_scheduler_t *scheduler) { int ret = 0; @@ -180,10 +189,18 @@ static int rga_job_run(struct rga_job *job, struct rga_scheduler_t *scheduler) return ret; } - ret = rga_dma_get_info(job); - if (ret < 0) { - pr_err("dma buf get failed"); - goto failed; + if (job->flags & RGA_JOB_USE_HANDLE) { + ret = rga_mm_get_handle_info(job); + if (ret < 0) { + pr_err("%s: failed to get buffer from handle\n", __func__); + goto failed; + } + } else { + ret = rga_dma_get_info(job); + if (ret < 0) { + pr_err("dma buf get failed"); + goto failed; + } } ret = scheduler->ops->init_reg(job); @@ -247,6 +264,11 @@ next_job: spin_unlock_irqrestore(&rga_scheduler->irq_lock, flags); + if (job->flags & RGA_JOB_USE_HANDLE) + rga_mm_put_handle_info(job); + else + rga_dma_put_info(job); + if (job->out_fence) dma_fence_signal(job->out_fence); @@ -257,8 +279,6 @@ next_job: wake_up(&rga_scheduler->job_done_wq); } - rga_dma_put_info(job); - goto next_job; } } @@ -292,8 +312,10 @@ void rga_job_done(struct rga_scheduler_t *rga_scheduler, int ret) rga2_dma_flush_cache_for_virtual_address(&job->vir_page_table, rga_scheduler); - rga_dma_put_info(job); - rga_job_put_current_mm(job); + if (job->flags & RGA_JOB_USE_HANDLE) + rga_mm_put_handle_info(job); + else + rga_dma_put_info(job); if (job->out_fence) dma_fence_signal(job->out_fence); @@ -325,8 +347,10 @@ static void rga_job_timeout_clean(struct rga_scheduler_t *scheduler) scheduler->ops->soft_reset(scheduler); - rga_dma_put_info(job); - rga_job_put_current_mm(job); + if (job->flags & RGA_JOB_USE_HANDLE) + rga_mm_put_handle_info(job); + else + rga_dma_put_info(job); if (job->out_fence) dma_fence_signal(job->out_fence); @@ -501,8 +525,6 @@ int rga_job_commit(struct rga_req *rga_command_base, int flags) return ret; } - rga_job_get_current_mm(job); - if (flags == RGA_BLIT_ASYNC) { ret = rga_out_fence_alloc(job); if (ret) { diff --git a/drivers/video/rockchip/rga3/rga_mm.c b/drivers/video/rockchip/rga3/rga_mm.c index 05e8be944f5d..199a54344495 100644 --- a/drivers/video/rockchip/rga3/rga_mm.c +++ b/drivers/video/rockchip/rga3/rga_mm.c @@ -12,6 +12,37 @@ #include "rga_dma_buf.h" #include "rga_hw_config.h" +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 void rga_convert_addr(struct rga_img_info_t *img) +{ + if (img->rd_mode != RGA_FBC_MODE) { + img->uv_addr = img->yrgb_addr + (img->vir_w * img->vir_h); + + //warning: rga3 may need /2 for all + if (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; + } else { + img->uv_addr = img->yrgb_addr; + img->v_addr = 0; + } +} + static void rga_current_mm_read_lock(struct mm_struct *mm) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) @@ -524,8 +555,8 @@ static int rga_mm_handle_remove(int id, void *ptr, void *data) } static struct rga_internal_buffer * -rga_mm_internal_buffer_lookup_external(struct rga_mm *mm_session, - struct rga_external_buffer *external_buffer) +rga_mm_lookup_external(struct rga_mm *mm_session, + struct rga_external_buffer *external_buffer) { int id; struct dma_buf *dma_buf = NULL; @@ -592,6 +623,38 @@ struct rga_internal_buffer *rga_mm_lookup_handle(struct rga_mm *mm_session, uint return output_buffer; } +dma_addr_t rga_mm_lookup_iova(struct rga_internal_buffer *buffer, int core) +{ + int i; + + for (i = 0; i < buffer->dma_buffer_size; i++) + if (buffer->dma_buffer[i].core == core) + return buffer->dma_buffer[i].iova; + + return -EFAULT; +} + +struct sg_table *rga_mm_lookup_sgt(struct rga_internal_buffer *buffer, int core) +{ + int i; + + switch (buffer->type) { + case RGA_DMA_BUFFER: + for (i = 0; i < buffer->dma_buffer_size; i++) + if (buffer->dma_buffer[i].core == core) + return buffer->dma_buffer[i].sgt; + break; + case RGA_VIRTUAL_ADDRESS: + return buffer->virt_addr->sgt; + case RGA_PHYSICAL_ADDRESS: + default: + pr_err("Illegal internal buffer, no sgt can be obtained!\n"); + return NULL; + } + + return NULL; +} + void rga_mm_dump_info(struct rga_mm *mm_session) { int id, i; @@ -646,6 +709,162 @@ void rga_mm_dump_info(struct rga_mm *mm_session) } } +static int rga_mm_set_mmu_flag(struct rga_job *job) +{ + struct rga_mmu_t *mmu_info; + int src_mmu_en; + int src1_mmu_en; + int dst_mmu_en; + int els_mmu_en; + + src_mmu_en = job->src_buffer ? job->src_buffer->mm_flag & RGA_MM_NEED_USE_IOMMU : 0; + src1_mmu_en = job->src1_buffer ? job->src1_buffer->mm_flag & RGA_MM_NEED_USE_IOMMU : 0; + dst_mmu_en = job->dst_buffer ? job->dst_buffer->mm_flag & RGA_MM_NEED_USE_IOMMU : 0; + els_mmu_en = job->els_buffer ? job->els_buffer->mm_flag & RGA_MM_NEED_USE_IOMMU : 0; + + mmu_info = &job->rga_command_base.mmu_info; + if (src_mmu_en) + mmu_info->mmu_flag |= (0x1 << 8); + if (src1_mmu_en) + mmu_info->mmu_flag |= (0x1 << 9); + if (dst_mmu_en) + mmu_info->mmu_flag |= (0x1 << 10); + if (els_mmu_en) + mmu_info->mmu_flag |= (0x1 << 11); + + if (mmu_info->mmu_flag & (0xf << 8)) { + mmu_info->mmu_flag |= 1; + mmu_info->mmu_flag |= 1 << 31; + mmu_info->mmu_en = 1; + } + + return 0; +} + +static int rga_mm_get_channel_handle_info(struct rga_mm *mm, + struct rga_job *job, + struct rga_img_info_t *img, + struct rga_internal_buffer **buf) +{ + struct rga_internal_buffer *internal_buffer = NULL; + + if (!(img->yrgb_addr > 0)) { + pr_err("No buffer handle can be used!\n"); + return -EFAULT; + } + + mutex_lock(&mm->lock); + *buf = rga_mm_lookup_handle(mm, img->yrgb_addr); + if (*buf == NULL) { + pr_err("This handle[%ld] is illegal.\n", (unsigned long)img->yrgb_addr); + + mutex_unlock(&mm->lock); + return -EFAULT; + } + + internal_buffer = *buf; + kref_get(&internal_buffer->refcount); + + switch (internal_buffer->type) { + case RGA_DMA_BUFFER: + if (job->core == RGA3_SCHEDULER_CORE0 || + job->core == RGA3_SCHEDULER_CORE1) + img->yrgb_addr = rga_mm_lookup_iova(internal_buffer, job->core); + else + img->yrgb_addr = 0; + break; + case RGA_VIRTUAL_ADDRESS: + if (job->core == RGA3_SCHEDULER_CORE0 || + job->core == RGA3_SCHEDULER_CORE1) + img->yrgb_addr = rga_mm_lookup_iova(internal_buffer, job->core); + else + img->yrgb_addr = internal_buffer->virt_addr->addr; + break; + case RGA_PHYSICAL_ADDRESS: + img->yrgb_addr = internal_buffer->phys_addr; + break; + default: + pr_err("Illegal external buffer!\n"); + + mutex_unlock(&mm->lock); + return -EFAULT; + } + mutex_unlock(&mm->lock); + + rga_convert_addr(img); + + return 0; +} + +static void rga_mm_put_channel_handle_info(struct rga_mm *mm, + struct rga_internal_buffer *internal_buffer) +{ + mutex_lock(&mm->lock); + + kref_put(&internal_buffer->refcount, rga_mm_kref_release_buffer); + + mutex_unlock(&mm->lock); +} + +int rga_mm_get_handle_info(struct rga_job *job) +{ + int ret = 0; + struct rga_req *req = NULL; + struct rga_mm *mm = NULL; + + req = &job->rga_command_base; + mm = rga_drvdata->mm; + + if (likely(req->src.yrgb_addr > 0)) { + ret = rga_mm_get_channel_handle_info(mm, job, &req->src, &job->src_buffer); + if (ret < 0) { + pr_err("Can't get src buffer info!\n"); + return ret; + } + } + + if (likely(req->dst.yrgb_addr > 0)) { + ret = rga_mm_get_channel_handle_info(mm, job, &req->dst, &job->dst_buffer); + if (ret < 0) { + pr_err("Can't get dst buffer info!\n"); + return ret; + } + } + + if (likely(req->pat.yrgb_addr > 0)) { + if (job->rga_command_base.render_mode != UPDATE_PALETTE_TABLE_MODE) + ret = rga_mm_get_channel_handle_info(mm, job, &req->pat, + &job->src1_buffer); + else + ret = rga_mm_get_channel_handle_info(mm, job, &req->pat, + &job->els_buffer); + if (ret < 0) { + pr_err("Can't get pat buffer info!\n"); + return ret; + } + } + + rga_mm_set_mmu_flag(job); + + return 0; +} + +void rga_mm_put_handle_info(struct rga_job *job) +{ + struct rga_mm *mm = NULL; + + mm = rga_drvdata->mm; + + if (job->src_buffer) + rga_mm_put_channel_handle_info(mm, job->src_buffer); + if (job->dst_buffer) + rga_mm_put_channel_handle_info(mm, job->dst_buffer); + if (job->src1_buffer) + rga_mm_put_channel_handle_info(mm, job->src1_buffer); + if (job->els_buffer) + rga_mm_put_channel_handle_info(mm, job->els_buffer); +} + uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer) { int ret = 0; @@ -661,7 +880,7 @@ uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer) mutex_lock(&mm->lock); /* first, Check whether to rga_mm */ - internal_buffer = rga_mm_internal_buffer_lookup_external(mm, external_buffer); + internal_buffer = rga_mm_lookup_external(mm, external_buffer); if (!IS_ERR_OR_NULL(internal_buffer)) { kref_get(&internal_buffer->refcount);