video: rockchip: rga3: Support using handle

It will be used by finding the memory corresponding to the handle
in rga_mm.

Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
Change-Id: I6bd09a3641671c69aa903010c0aa4e518cf9b5af
This commit is contained in:
Yu Qiaowei
2022-01-10 20:57:11 +08:00
committed by Tao Huang
parent 11b10c87c3
commit cb6eb4a53f
7 changed files with 540 additions and 137 deletions

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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__,

View File

@@ -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) {

View File

@@ -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);