From d31787415cb54e3d06cf62ce862c025c54c01f3d Mon Sep 17 00:00:00 2001 From: Ding Wei Date: Tue, 3 Dec 2019 16:53:44 +0800 Subject: [PATCH] video: rockchip: mpp: add function that trans info can set by user space priority order: 1. MPP_CMD_SET_REG_ADDR_OFFSET define the trans table each task. 2. MPP_CMD_INIT_TRANS_TABLE define once when open session. 3. use default trans table define in each device. Change-Id: I13409fb67d58dfa53295aabe7952d044dc1637d4 Signed-off-by: Ding Wei --- drivers/video/rockchip/mpp/mpp_common.c | 182 +++++++++++++----- drivers/video/rockchip/mpp/mpp_common.h | 35 ++-- drivers/video/rockchip/mpp/mpp_rkvdec.c | 236 ++++++++++++++---------- drivers/video/rockchip/mpp/mpp_vdpu1.c | 177 ++++++++++-------- drivers/video/rockchip/mpp/mpp_vdpu2.c | 190 +++++++++++-------- drivers/video/rockchip/mpp/mpp_vepu1.c | 133 ++++++++----- drivers/video/rockchip/mpp/mpp_vepu2.c | 133 ++++++++----- 7 files changed, 679 insertions(+), 407 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_common.c b/drivers/video/rockchip/mpp/mpp_common.c index 448cd0db93d9..1a662c9dfe86 100644 --- a/drivers/video/rockchip/mpp/mpp_common.c +++ b/drivers/video/rockchip/mpp/mpp_common.c @@ -154,15 +154,20 @@ static int mpp_power_off(struct mpp_dev *mpp) } static void * -mpp_fd_to_mem_region(struct mpp_dev *mpp, - struct mpp_dma_session *dma, int fd) +mpp_fd_to_mem_region(struct mpp_session *session, int fd) { struct mpp_dma_buffer *buffer = NULL; struct mpp_mem_region *mem_region = NULL; + struct mpp_dev *mpp = session->mpp; + struct mpp_dma_session *dma = session->dma; if (fd <= 0 || !dma || !mpp) return ERR_PTR(-EINVAL); + mem_region = kzalloc(sizeof(*mem_region), GFP_KERNEL); + if (!mem_region) + return ERR_PTR(-ENOMEM); + down_read(&mpp->rw_sem); buffer = mpp_dma_import_fd(mpp->iommu_info, dma, fd); up_read(&mpp->rw_sem); @@ -171,14 +176,6 @@ mpp_fd_to_mem_region(struct mpp_dev *mpp, return ERR_PTR(-EINVAL); } - mem_region = kzalloc(sizeof(*mem_region), GFP_KERNEL); - if (!mem_region) { - down_read(&mpp->rw_sem); - mpp_dma_release_fd(dma, fd); - up_read(&mpp->rw_sem); - return ERR_PTR(-ENOMEM); - } - mem_region->hdl = (void *)(long)fd; mem_region->iova = buffer->iova; mem_region->len = buffer->size; @@ -224,7 +221,7 @@ mpp_session_pull_done(struct mpp_session *session) } static int mpp_process_task(struct mpp_session *session, - struct mpp_request *req) + struct mpp_task_msgs *msgs) { struct mpp_task *task = NULL; struct mpp_dev *mpp = session->mpp; @@ -236,7 +233,7 @@ static int mpp_process_task(struct mpp_session *session, } if (mpp->dev_ops->alloc_task) - task = mpp->dev_ops->alloc_task(session, req->data, req->size); + task = mpp->dev_ops->alloc_task(session, msgs); if (!task) { mpp_err("alloc_task failed.\n"); return -ENOMEM; @@ -344,7 +341,7 @@ mpp_reset_control_get(struct mpp_dev *mpp, const char *name) } if (!clk) { rst_clk = devm_kzalloc(dev, sizeof(*rst_clk), - GFP_KERNEL); + GFP_KERNEL); strncpy(rst_clk->name, name, sizeof(rst_clk->name)); rst_clk->clk = devm_reset_control_get(dev, shared_name); @@ -542,7 +539,7 @@ static int mpp_session_clear(struct mpp_dev *mpp, static int mpp_task_result(struct mpp_dev *mpp, struct mpp_task *task, - u32 __user *dst, u32 size) + struct mpp_task_msgs *msgs) { mpp_debug_enter(); @@ -550,7 +547,7 @@ static int mpp_task_result(struct mpp_dev *mpp, return -EINVAL; if (mpp->dev_ops->result) - mpp->dev_ops->result(mpp, task, dst, size); + mpp->dev_ops->result(mpp, task, msgs); mpp_free_task(task->session, task); @@ -560,11 +557,17 @@ static int mpp_task_result(struct mpp_dev *mpp, } static int mpp_wait_result(struct mpp_session *session, - struct mpp_dev *mpp, - struct mpp_request *req) + struct mpp_task_msgs *msgs) { int ret; struct mpp_task *task; + struct mpp_dev *mpp = session->mpp; + + if (!mpp) { + mpp_err("pid %d not find clinet %d\n", + session->pid, session->device_type); + return -EINVAL; + } ret = wait_event_timeout(session->wait, !kfifo_is_empty(&session->done_fifo), @@ -572,9 +575,9 @@ static int mpp_wait_result(struct mpp_session *session, if (ret > 0) { ret = 0; task = mpp_session_pull_done(session); - mpp_task_result(mpp, task, req->data, req->size); + mpp_task_result(mpp, task, msgs); } else { - mpp_err("error: pid %d wait %d task done timeout\n", + mpp_err("pid %d wait %d task done timeout.\n", session->pid, atomic_read(&session->task_running)); ret = -ETIMEDOUT; mpp_dev_abort(mpp); @@ -663,7 +666,7 @@ int mpp_taskqueue_init(struct mpp_taskqueue *queue, } int mpp_reset_group_init(struct mpp_reset_group *group, - struct mpp_service *srv) + struct mpp_service *srv) { init_rwsem(&group->rw_sem); INIT_LIST_HEAD(&group->clk); @@ -786,17 +789,38 @@ static int mpp_process_request(struct mpp_session *session, if (mpp->grf_info->grf) regmap_write(mpp->grf_info->grf, 0x5d8, val); } break; + case MPP_CMD_INIT_TRANS_TABLE: { + if (session && req->size) { + int trans_tbl_size = sizeof(session->trans_table); + + if (req->size > trans_tbl_size) { + mpp_err("init table size %d more than %d\n", + req->size, trans_tbl_size); + return -ENOMEM; + } + + if (copy_from_user(session->trans_table, + req->data, req->size)) { + mpp_err("copy_from_user failed\n"); + return -EINVAL; + } + session->trans_count = + req->size / sizeof(session->trans_table[0]); + } + } break; + case MPP_CMD_SET_REG_ADDR_OFFSET: { + memcpy(&msgs->reg_offset, req, sizeof(*req)); + if (mpp_msg_is_last(req)) + return mpp_process_task(session, msgs); + } break; case MPP_CMD_SET_REG: { - mpp = session->mpp; - if (!mpp) - return -EINVAL; - return mpp_process_task(session, req); + memcpy(&msgs->reg_in, req, sizeof(*req)); + if (mpp_msg_is_last(req)) + return mpp_process_task(session, msgs); } break; case MPP_CMD_GET_REG: { - mpp = session->mpp; - if (!mpp) - return -EINVAL; - return mpp_wait_result(session, mpp, req); + memcpy(&msgs->reg_out, req, sizeof(*req)); + return mpp_wait_result(session, msgs); } break; default: { mpp = session->mpp; @@ -992,8 +1016,7 @@ mpp_task_attach_fd(struct mpp_task *task, int fd) { struct mpp_mem_region *mem_region = NULL; - mem_region = mpp_fd_to_mem_region(task->session->mpp, - task->session->dma, fd); + mem_region = mpp_fd_to_mem_region(task->session, fd); if (IS_ERR(mem_region)) return mem_region; @@ -1005,17 +1028,34 @@ mpp_task_attach_fd(struct mpp_task *task, int fd) return mem_region; } -int mpp_translate_reg_address(struct mpp_dev *mpp, - struct mpp_task *task, - int fmt, u32 *reg) +int mpp_translate_reg_address(struct mpp_session *session, + struct mpp_task *task, int fmt, + u32 *reg, struct reg_offset_info *off_inf) { - struct mpp_trans_info *trans_info = mpp->var->trans_info; - const u8 *tbl = trans_info[fmt].table; - int size = trans_info[fmt].count; int i; + int cnt; + const u16 *tbl; + u16 trans_tbl[MPP_MAX_REG_TRANS_NUM]; mpp_debug_enter(); - for (i = 0; i < size; i++) { + + if (off_inf->cnt > 0) { + cnt = off_inf->cnt; + for (i = 0; i < cnt; i++) + trans_tbl[i] = (u16)off_inf->elem[i].index; + tbl = trans_tbl; + } else if (session->trans_count > 0) { + cnt = session->trans_count; + tbl = session->trans_table; + } else { + struct mpp_dev *mpp = session->mpp; + struct mpp_trans_info *trans_info = mpp->var->trans_info; + + cnt = trans_info[fmt].count; + tbl = trans_info[fmt].table; + } + + for (i = 0; i < cnt; i++) { struct mpp_mem_region *mem_region = NULL; int usr_fd = reg[tbl[i]] & 0x3FF; int offset = reg[tbl[i]] >> 10; @@ -1041,22 +1081,70 @@ int mpp_translate_reg_address(struct mpp_dev *mpp, return 0; } -int mpp_translate_extra_info(struct mpp_task *task, - struct extra_info_for_iommu *ext_inf, - u32 *reg) +int mpp_extract_reg_offset_info(struct mpp_request *msg, + struct reg_offset_info *off_inf) +{ + int ret = 0; + int off_inf_size = sizeof(off_inf->elem); + + if (msg->size > off_inf_size) { + mpp_err("msg->size %d more than %d.\n", + msg->size, off_inf_size); + return -EINVAL; + } + + if (msg->size) { + off_inf->magic = EXTRA_INFO_MAGIC; + off_inf->cnt = msg->size / sizeof(off_inf->elem[0]); + + if (copy_from_user(off_inf->elem, + msg->data, + msg->size)) { + mpp_err("copy_from_user failed\n"); + return -EINVAL; + } + } + + return ret; +} + +int mpp_query_reg_offset_info(struct reg_offset_info *off_inf, + u32 index) { mpp_debug_enter(); - if (ext_inf) { + if (off_inf) { int i; - if (ext_inf->magic != EXTRA_INFO_MAGIC) - return -EINVAL; + if (off_inf->magic != EXTRA_INFO_MAGIC) + return 0; - for (i = 0; i < ext_inf->cnt; i++) { + for (i = 0; i < off_inf->cnt; i++) { + if (off_inf->elem[i].index == index) + return off_inf->elem[i].offset; + } + } + mpp_debug_leave(); + + return 0; +} + +int mpp_translate_reg_offset_info(struct mpp_task *task, + struct reg_offset_info *off_inf, + u32 *reg) +{ + mpp_debug_enter(); + + if (off_inf) { + int i; + + if (off_inf->magic != EXTRA_INFO_MAGIC) + return 0; + + for (i = 0; i < off_inf->cnt; i++) { mpp_debug(DEBUG_IOMMU, "reg[%d] + offset %d\n", - ext_inf->elem[i].index, - ext_inf->elem[i].offset); - reg[ext_inf->elem[i].index] += ext_inf->elem[i].offset; + off_inf->elem[i].index, + off_inf->elem[i].offset); + reg[off_inf->elem[i].index] += off_inf->elem[i].offset; } } mpp_debug_leave(); diff --git a/drivers/video/rockchip/mpp/mpp_common.h b/drivers/video/rockchip/mpp/mpp_common.h index 659e08dd3fc0..299259aa5050 100644 --- a/drivers/video/rockchip/mpp/mpp_common.h +++ b/drivers/video/rockchip/mpp/mpp_common.h @@ -32,6 +32,8 @@ /* define flags for mpp_request */ #define MPP_FLAGS_MULTI_MSG (0x00000001) #define MPP_FLAGS_LAST_MSG (0x00000002) +#define MPP_FLAGS_REG_FD_NO_TRANS (0x00000004) +#define MPP_FLAGS_SCL_FD_NO_TRANS (0x00000008) #define MPP_FLAGS_SECURE_MODE (0x00010000) /** @@ -80,12 +82,14 @@ enum MPP_DEV_COMMAND_TYPE { MPP_CMD_INIT_BASE = 0x100, MPP_CMD_INIT_CLIENT_TYPE = MPP_CMD_INIT_BASE + 0, MPP_CMD_INIT_DRIVER_DATA = MPP_CMD_INIT_BASE + 1, + MPP_CMD_INIT_TRANS_TABLE = MPP_CMD_INIT_BASE + 2, MPP_CMD_SEND_BASE = 0x200, MPP_CMD_SET_REG = MPP_CMD_SEND_BASE + 0, MPP_CMD_SET_VEPU22_CFG = MPP_CMD_SEND_BASE + 1, MPP_CMD_SET_RKVENC_OSD_PLT = MPP_CMD_SEND_BASE + 2, MPP_CMD_SET_RKVENC_L2_REG = MPP_CMD_SEND_BASE + 3, + MPP_CMD_SET_REG_ADDR_OFFSET = MPP_CMD_SEND_BASE + 4, MPP_CMD_POLL_BASE = 0x300, MPP_CMD_GET_REG = MPP_CMD_POLL_BASE + 0, @@ -138,18 +142,18 @@ struct mpp_hw_info { struct mpp_trans_info { const int count; - const char * const table; + const u16 * const table; }; -struct extra_info_elem { +struct reg_offset_elem { u32 index; u32 offset; }; -struct extra_info_for_iommu { +struct reg_offset_info { u32 magic; u32 cnt; - struct extra_info_elem elem[20]; + struct reg_offset_elem elem[MPP_MAX_REG_TRANS_NUM]; }; struct mpp_dev_var { @@ -222,6 +226,9 @@ struct mpp_session { wait_queue_head_t wait; pid_t pid; atomic_t task_running; + /* trans info set by user */ + int trans_count; + u16 trans_table[MPP_MAX_REG_TRANS_NUM]; }; /* The context for the a task */ @@ -328,14 +335,14 @@ struct mpp_hw_ops { */ struct mpp_dev_ops { void *(*alloc_task)(struct mpp_session *session, - void __user *src, u32 size); + struct mpp_task_msgs *msgs); int (*prepare)(struct mpp_dev *mpp, struct mpp_task *task); int (*run)(struct mpp_dev *mpp, struct mpp_task *task); int (*irq)(struct mpp_dev *mpp); int (*isr)(struct mpp_dev *mpp); int (*finish)(struct mpp_dev *mpp, struct mpp_task *task); int (*result)(struct mpp_dev *mpp, struct mpp_task *task, - u32 __user *dst, u32 size); + struct mpp_task_msgs *msgs); int (*free_task)(struct mpp_session *session, struct mpp_task *task); long (*ioctl)(struct mpp_session *session, struct mpp_request *req); @@ -351,13 +358,17 @@ int mpp_reset_group_init(struct mpp_reset_group *group, struct mpp_mem_region * mpp_task_attach_fd(struct mpp_task *task, int fd); -int mpp_translate_reg_address(struct mpp_dev *data, - struct mpp_task *task, - int fmt, u32 *reg); -int mpp_translate_extra_info(struct mpp_task *task, - struct extra_info_for_iommu *ext_inf, - u32 *reg); +int mpp_translate_reg_address(struct mpp_session *session, + struct mpp_task *task, int fmt, + u32 *reg, struct reg_offset_info *off_inf); +int mpp_extract_reg_offset_info(struct mpp_request *msg, + struct reg_offset_info *off_inf); +int mpp_query_reg_offset_info(struct reg_offset_info *off_inf, + u32 index); +int mpp_translate_reg_offset_info(struct mpp_task *task, + struct reg_offset_info *off_inf, + u32 *reg); int mpp_task_init(struct mpp_session *session, struct mpp_task *task); int mpp_task_finish(struct mpp_session *session, diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec.c b/drivers/video/rockchip/mpp/mpp_rkvdec.c index 827b7fb86c9c..070b25a3209d 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec.c @@ -134,6 +134,7 @@ struct rkvdec_task { unsigned long clk_cabac_freq; u32 reg[RKVDEC_V2_REG_NUM]; + struct reg_offset_info off_inf; u32 idx; u32 strm_addr; @@ -207,38 +208,38 @@ static struct mpp_hw_info rkvdec_v1_hw_info = { /* * file handle translate information */ -static const char trans_tbl_h264d[] = { +static const u16 trans_tbl_h264d[] = { 4, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 41, 42, 43, 48, 75 }; -static const char trans_tbl_h265d[] = { +static const u16 trans_tbl_h265d[] = { 4, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 42, 43 }; -static const char trans_tbl_vp9d[] = { +static const u16 trans_tbl_vp9d[] = { 4, 6, 7, 11, 12, 13, 14, 15, 16 }; static struct mpp_trans_info rk_hevcdec_trans[] = { [RKVDEC_FMT_H265D] = { - .count = sizeof(trans_tbl_h265d), + .count = ARRAY_SIZE(trans_tbl_h265d), .table = trans_tbl_h265d, }, }; static struct mpp_trans_info rkvdec_v1_trans[] = { [RKVDEC_FMT_H265D] = { - .count = sizeof(trans_tbl_h265d), + .count = ARRAY_SIZE(trans_tbl_h265d), .table = trans_tbl_h265d, }, [RKVDEC_FMT_H264D] = { - .count = sizeof(trans_tbl_h264d), + .count = ARRAY_SIZE(trans_tbl_h264d), .table = trans_tbl_h264d, }, [RKVDEC_FMT_VP9D] = { - .count = sizeof(trans_tbl_vp9d), + .count = ARRAY_SIZE(trans_tbl_vp9d), .table = trans_tbl_vp9d, }, }; @@ -602,65 +603,17 @@ done: return ret; } -static void *rkvdec_alloc_task(struct mpp_session *session, - void __user *src, u32 size) +static int rkvdec_process_scl_fd(struct mpp_session *session, + struct rkvdec_task *task, + struct mpp_task_msgs *msgs) { - u32 fmt; - int ret; - u32 reg_len; - int pps_fd; - u32 pps_offset; - struct rkvdec_task *task = NULL; - u32 dwsize = size / sizeof(u32); - struct mpp_dev *mpp = session->mpp; + int ret = 0; + int idx = RKVDEC_REG_PPS_BASE_INDEX; + int pps_fd = task->reg[idx] & 0x3ff; + int pps_offset = task->reg[idx] >> 10; + u32 fmt = RKVDEC_GET_FORMAT(task->reg[RKVDEC_REG_SYS_CTRL_INDEX]); - mpp_debug_enter(); - - task = kzalloc(sizeof(*task), GFP_KERNEL); - if (!task) - return NULL; - - mpp_task_init(session, &task->mpp_task); - - task->hw_info = mpp->var->hw_info; - reg_len = min(task->hw_info->reg_num, dwsize); - if (copy_from_user(task->reg, src, reg_len * 4)) { - mpp_err("error: copy_from_user failed in reg_init\n"); - goto fail; - } - - fmt = RKVDEC_GET_FORMAT(task->reg[RKVDEC_REG_SYS_CTRL_INDEX]); - /* - * special offset scale case - * - * This translation is for fd + offset translation. - * One register has 32bits. We need to transfer both buffer file - * handle and the start address offset so we packet file handle - * and offset together using below format. - * - * 0~9 bit for buffer file handle range 0 ~ 1023 - * 10~31 bit for offset range 0 ~ 4M - * - * But on 4K case the offset can be larger the 4M - * So on VP9 4K decoder colmv base we scale the offset by 16 - */ - if (fmt == RKVDEC_FMT_VP9D) { - struct mpp_mem_region *mem_region = NULL; - dma_addr_t iova = 0; - u32 offset = task->reg[RKVDEC_REG_VP9_REFCOLMV_BASE_INDEX]; - int fd = task->reg[RKVDEC_REG_VP9_REFCOLMV_BASE_INDEX] & 0x3ff; - - offset = offset >> 10 << 4; - mem_region = mpp_task_attach_fd(&task->mpp_task, fd); - if (IS_ERR(mem_region)) - goto fail; - - iova = mem_region->iova; - task->reg[RKVDEC_REG_VP9_REFCOLMV_BASE_INDEX] = iova + offset; - } - - pps_fd = task->reg[RKVDEC_REG_PPS_BASE_INDEX] & 0x3ff; - pps_offset = task->reg[RKVDEC_REG_PPS_BASE_INDEX] >> 10; + pps_offset += mpp_query_reg_offset_info(&task->off_inf, idx); if (pps_fd > 0) { int pps_info_offset; int pps_info_count; @@ -713,17 +666,113 @@ static void *rkvdec_alloc_task(struct mpp_session *session, } } - ret = mpp_translate_reg_address(session->mpp, - &task->mpp_task, - fmt, task->reg); +fail: + return ret; +} + +static int rkvdec_process_reg_fd(struct mpp_session *session, + struct rkvdec_task *task, + struct mpp_task_msgs *msgs) +{ + int ret = 0; + u32 fmt = RKVDEC_GET_FORMAT(task->reg[RKVDEC_REG_SYS_CTRL_INDEX]); + + /* copy reg address offset message */ + ret = mpp_extract_reg_offset_info(&msgs->reg_offset, + &task->off_inf); + if (ret) + goto fail; + /* + * special offset scale case + * + * This translation is for fd + offset translation. + * One register has 32bits. We need to transfer both buffer file + * handle and the start address offset so we packet file handle + * and offset together using below format. + * + * 0~9 bit for buffer file handle range 0 ~ 1023 + * 10~31 bit for offset range 0 ~ 4M + * + * But on 4K case the offset can be larger the 4M + * So on VP9 4K decoder colmv base we scale the offset by 16 + */ + if (fmt == RKVDEC_FMT_VP9D) { + int fd; + int idx; + u32 offset; + dma_addr_t iova = 0; + struct mpp_mem_region *mem_region = NULL; + + idx = RKVDEC_REG_VP9_REFCOLMV_BASE_INDEX; + offset = task->reg[idx]; + fd = task->reg[idx] & 0x3ff; + + offset = offset >> 10 << 4; + offset += mpp_query_reg_offset_info(&task->off_inf, idx); + mem_region = mpp_task_attach_fd(&task->mpp_task, fd); + if (IS_ERR(mem_region)) + goto fail; + + iova = mem_region->iova; + task->reg[idx] = iova + offset; + } + + ret = mpp_translate_reg_address(session, &task->mpp_task, + fmt, task->reg, &task->off_inf); if (ret) { - mpp_err("error: translate reg address failed.\n"); + mpp_err("translate reg address failed.\n"); mpp_dump_reg(task->reg, task->hw_info->regidx_start, task->hw_info->regidx_end); goto fail; } + mpp_debug(DEBUG_SET_REG, "extra info cnt %u, magic %08x", + task->off_inf.cnt, task->off_inf.magic); + mpp_translate_reg_offset_info(&task->mpp_task, + &task->off_inf, task->reg); + return 0; +fail: + return -EFAULT; +} + +static void *rkvdec_alloc_task(struct mpp_session *session, + struct mpp_task_msgs *msgs) +{ + int ret; + u32 reg_len; + + struct rkvdec_task *task = NULL; + struct mpp_dev *mpp = session->mpp; + struct mpp_request *msg_reg = &msgs->reg_in; + u32 dwsize = msg_reg->size / sizeof(u32); + + mpp_debug_enter(); + + task = kzalloc(sizeof(*task), GFP_KERNEL); + if (!task) + return NULL; + + mpp_task_init(session, &task->mpp_task); + task->hw_info = mpp->var->hw_info; + reg_len = min(task->hw_info->reg_num, dwsize); + if (copy_from_user(task->reg, msg_reg->data, + reg_len * sizeof(u32))) { + mpp_err("copy_from_user failed in reg_init\n"); + goto fail; + } + /* process fd in pps for 264 and 265 */ + if (!(msg_reg->flags & MPP_FLAGS_SCL_FD_NO_TRANS)) { + ret = rkvdec_process_scl_fd(session, task, msgs); + if (ret) + goto fail; + } + /* process fd in register */ + if (!(msg_reg->flags & MPP_FLAGS_REG_FD_NO_TRANS)) { + ret = rkvdec_process_reg_fd(session, task, msgs); + if (ret) + goto fail; + } task->strm_addr = task->reg[RKVDEC_REG_RLC_BASE_INDEX]; mpp_debug_leave(); @@ -929,12 +978,14 @@ static int rkvdec_finish(struct mpp_dev *mpp, static int rkvdec_result(struct mpp_dev *mpp, struct mpp_task *mpp_task, - u32 __user *dst, u32 size) + struct mpp_task_msgs *msgs) { + struct mpp_request *msg_reg_out = &msgs->reg_out; struct rkvdec_task *task = to_rkvdec_task(mpp_task); /* FIXME may overflow the kernel */ - if (copy_to_user(dst, task->reg, size)) { + if (copy_to_user(msg_reg_out->data, + task->reg, msg_reg_out->size)) { mpp_err("copy_to_user failed\n"); return -EIO; } @@ -1128,6 +1179,7 @@ static int rkvdec_devfreq_remove(struct mpp_dev *mpp) static int rkvdec_devfreq_init(struct mpp_dev *mpp) { int ret = 0; + struct devfreq_dev_status *stat; struct rkvdec_dev *dec = to_rkvdec_dev(mpp); dec->parent_devfreq = devfreq_get_devfreq_by_phandle(mpp->dev, 0); @@ -1157,32 +1209,28 @@ static int rkvdec_devfreq_init(struct mpp_dev *mpp) dev_warn(mpp->dev, "no regulator for vcodec\n"); return 0; - } else { - struct devfreq_dev_status *stat; - - ret = rockchip_init_opp_table(mpp->dev, NULL, - "rkvdec_leakage", "vcodec"); - if (ret) { - dev_err(mpp->dev, "Failed to init_opp_table\n"); - goto done; - } - dec->devfreq = devm_devfreq_add_device(mpp->dev, - &devfreq_profile, - "userspace", - NULL); - if (IS_ERR(dec->devfreq)) { - ret = PTR_ERR(dec->devfreq); - goto done; - } - - stat = &dec->devfreq->last_status; - stat->current_frequency = clk_get_rate(dec->aclk); - - ret = devfreq_register_opp_notifier(mpp->dev, dec->devfreq); - if (ret) - goto done; } + ret = rockchip_init_opp_table(mpp->dev, NULL, + "rkvdec_leakage", "vcodec"); + if (ret) { + dev_err(mpp->dev, "Failed to init_opp_table\n"); + goto done; + } + dec->devfreq = devm_devfreq_add_device(mpp->dev, &devfreq_profile, + "userspace", NULL); + if (IS_ERR(dec->devfreq)) { + ret = PTR_ERR(dec->devfreq); + goto done; + } + + stat = &dec->devfreq->last_status; + stat->current_frequency = clk_get_rate(dec->aclk); + + ret = devfreq_register_opp_notifier(mpp->dev, dec->devfreq); + if (ret) + goto done; + /* power simplle init */ ret = power_model_simple_init(mpp); if (!ret && dec->devfreq) { diff --git a/drivers/video/rockchip/mpp/mpp_vdpu1.c b/drivers/video/rockchip/mpp/mpp_vdpu1.c index 35b000f793cc..1b64222e81c0 100644 --- a/drivers/video/rockchip/mpp/mpp_vdpu1.c +++ b/drivers/video/rockchip/mpp/mpp_vdpu1.c @@ -96,7 +96,7 @@ struct vdpu_task { unsigned long aclk_freq; u32 reg[VDPU1_REG_PP_NUM]; u32 idx; - struct extra_info_for_iommu ext_inf; + struct reg_offset_info off_inf; u32 strm_addr; u32 irq_status; }; @@ -136,66 +136,66 @@ static struct mpp_hw_info vdpu_pp_v1_hw_info = { /* * file handle translate information */ -static const char trans_tbl_avsd[] = { +static const u16 trans_tbl_avsd[] = { 12, 13, 14, 15, 16, 17, 40, 41, 45 }; -static const char trans_tbl_default[] = { +static const u16 trans_tbl_default[] = { 12, 13, 14, 15, 16, 17, 40, 41 }; -static const char trans_tbl_jpegd[] = { +static const u16 trans_tbl_jpegd[] = { 12, 13, 14, 40, 66, 67 }; -static const char trans_tbl_h264d[] = { +static const u16 trans_tbl_h264d[] = { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 40 }; -static const char trans_tbl_vc1d[] = { +static const u16 trans_tbl_vc1d[] = { 12, 13, 14, 15, 16, 17, 27, 41 }; -static const char trans_tbl_vp6d[] = { +static const u16 trans_tbl_vp6d[] = { 12, 13, 14, 18, 27, 40 }; -static const char trans_tbl_vp8d[] = { +static const u16 trans_tbl_vp8d[] = { 10, 12, 13, 14, 18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 40 }; static struct mpp_trans_info vdpu_v1_trans[] = { [VDPU1_FMT_H264D] = { - .count = sizeof(trans_tbl_h264d), + .count = ARRAY_SIZE(trans_tbl_h264d), .table = trans_tbl_h264d, }, [VDPU1_FMT_H263D] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, [VDPU1_FMT_MPEG4D] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, [VDPU1_FMT_JPEGD] = { - .count = sizeof(trans_tbl_jpegd), + .count = ARRAY_SIZE(trans_tbl_jpegd), .table = trans_tbl_jpegd, }, [VDPU1_FMT_VC1D] = { - .count = sizeof(trans_tbl_vc1d), + .count = ARRAY_SIZE(trans_tbl_vc1d), .table = trans_tbl_vc1d, }, [VDPU1_FMT_MPEG2D] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, [VDPU1_FMT_MPEG1D] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, [VDPU1_FMT_VP6D] = { - .count = sizeof(trans_tbl_vp6d), + .count = ARRAY_SIZE(trans_tbl_vp6d), .table = trans_tbl_vp6d, }, [VDPU1_FMT_RESERVED] = { @@ -203,79 +203,59 @@ static struct mpp_trans_info vdpu_v1_trans[] = { .table = NULL, }, [VDPU1_FMT_VP7D] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, [VDPU1_FMT_VP8D] = { - .count = sizeof(trans_tbl_vp8d), + .count = ARRAY_SIZE(trans_tbl_vp8d), .table = trans_tbl_vp8d, }, [VDPU1_FMT_AVSD] = { - .count = sizeof(trans_tbl_avsd), + .count = ARRAY_SIZE(trans_tbl_avsd), .table = trans_tbl_avsd, }, }; -static void *vdpu_alloc_task(struct mpp_session *session, - void __user *src, u32 size) +static int vdpu_process_reg_fd(struct mpp_session *session, + struct vdpu_task *task, + struct mpp_task_msgs *msgs, + u32 extinf_len, + u32 reg_len) { - u32 fmt; - int err; - u32 reg_len; - u32 extinf_len; - struct vdpu_task *task = NULL; - u32 dwsize = size / sizeof(u32); - struct mpp_dev *mpp = session->mpp; + int ret = 0; + struct mpp_request *msg_reg = &msgs->reg_in; + int fmt = VDPU1_GET_FORMAT(task->reg[VDPU1_REG_SYS_CTRL_INDEX]); - mpp_debug_enter(); - - task = kzalloc(sizeof(*task), GFP_KERNEL); - if (!task) - return NULL; - - mpp_task_init(session, &task->mpp_task); - - if (session->device_type == MPP_DEVICE_VDPU1_PP) { - task->pp_enable = true; - task->hw_info = &vdpu_pp_v1_hw_info; - } else { - task->hw_info = mpp->var->hw_info; - } - reg_len = min(task->hw_info->reg_num, dwsize); - extinf_len = dwsize > reg_len ? (dwsize - reg_len) * 4 : 0; - - if (copy_from_user(task->reg, src, reg_len * 4)) { - mpp_err("error: copy_from_user failed in reg_init\n"); - goto fail; - } - - fmt = VDPU1_GET_FORMAT(task->reg[VDPU1_REG_SYS_CTRL_INDEX]); if (extinf_len > 0) { if (likely(fmt == VDPU1_FMT_JPEGD)) { - err = copy_from_user(&task->ext_inf, - (u8 *)src + size + ret = copy_from_user(&task->off_inf, + (u8 *)msg_reg->data + + msg_reg->size - JPEG_IOC_EXTRA_SIZE, JPEG_IOC_EXTRA_SIZE); } else { u32 ext_cpy = min_t(size_t, extinf_len, - sizeof(task->ext_inf)); - err = copy_from_user(&task->ext_inf, - (u32 *)src + reg_len, + sizeof(task->off_inf)); + ret = copy_from_user(&task->off_inf, + (u32 *)msg_reg->data + reg_len, ext_cpy); } - if (err) { + if (ret) { mpp_err("copy_from_user failed when extra info\n"); goto fail; } + } else { + ret = mpp_extract_reg_offset_info(&msgs->reg_offset, + &task->off_inf); + if (ret) + goto fail; } - err = mpp_translate_reg_address(session->mpp, - &task->mpp_task, - fmt, - task->reg); - if (err) { - mpp_err("error: translate reg address failed.\n"); + ret = mpp_translate_reg_address(session, &task->mpp_task, + fmt, task->reg, &task->off_inf); + if (ret) { + mpp_err("translate reg address failed.\n"); mpp_dump_reg(task->reg, task->hw_info->regidx_start, task->hw_info->regidx_end); @@ -295,28 +275,77 @@ static void *vdpu_alloc_task(struct mpp_session *session, * But on 4K case the offset can be larger the 4M */ if (likely(fmt == VDPU1_FMT_H264D)) { + u32 idx = VDPU1_REG_DIR_MV_BASE_INDEX; struct mpp_mem_region *mem_region = NULL; dma_addr_t iova = 0; - u32 offset = task->reg[VDPU1_REG_DIR_MV_BASE_INDEX]; - int fd = task->reg[VDPU1_REG_DIR_MV_BASE_INDEX] & 0x3ff; + u32 offset = task->reg[idx]; + int fd = task->reg[idx] & 0x3ff; offset = offset >> 10 << 4; + offset += mpp_query_reg_offset_info(&task->off_inf, idx); mem_region = mpp_task_attach_fd(&task->mpp_task, fd); if (IS_ERR(mem_region)) goto fail; iova = mem_region->iova; mpp_debug(DEBUG_IOMMU, "DMV[%3d]: %3d => %pad + offset %10d\n", - VDPU1_REG_DIR_MV_BASE_INDEX, fd, &iova, offset); - task->reg[VDPU1_REG_DIR_MV_BASE_INDEX] = iova + offset; + idx, fd, &iova, offset); + task->reg[idx] = iova + offset; + } + mpp_debug(DEBUG_SET_REG, "extra info cnt %u, magic %08x", + task->off_inf.cnt, task->off_inf.magic); + mpp_translate_reg_offset_info(&task->mpp_task, + &task->off_inf, + task->reg); + return 0; +fail: + return -EFAULT; +} + +static void *vdpu_alloc_task(struct mpp_session *session, + struct mpp_task_msgs *msgs) +{ + int ret; + u32 reg_len; + u32 extinf_len; + + struct vdpu_task *task; + struct mpp_dev *mpp = session->mpp; + struct mpp_request *msg_reg = &msgs->reg_in; + u32 dwsize = msg_reg->size / sizeof(u32); + + mpp_debug_enter(); + + task = kzalloc(sizeof(*task), GFP_KERNEL); + if (!task) + return NULL; + + mpp_task_init(session, &task->mpp_task); + + if (session->device_type == MPP_DEVICE_VDPU1_PP) { + task->pp_enable = true; + task->hw_info = &vdpu_pp_v1_hw_info; + } else { + task->hw_info = mpp->var->hw_info; } + reg_len = min(task->hw_info->reg_num, dwsize); + extinf_len = dwsize > reg_len ? + (dwsize - reg_len) * sizeof(u32) : 0; + if (copy_from_user(task->reg, msg_reg->data, + reg_len * sizeof(u32))) { + mpp_err("copy_from_user failed in reg_init\n"); + goto fail; + } + /* process fd in register */ + if (!(msg_reg->flags & MPP_FLAGS_REG_FD_NO_TRANS)) { + ret = vdpu_process_reg_fd(session, task, msgs, + extinf_len, reg_len); + if (ret) + goto fail; + } task->strm_addr = task->reg[VDPU1_REG_STREAM_RLC_BASE_INDEX]; - mpp_debug(DEBUG_SET_REG, "extra info cnt %u, magic %08x", - task->ext_inf.cnt, task->ext_inf.magic); - mpp_translate_extra_info(&task->mpp_task, &task->ext_inf, task->reg); - mpp_debug_leave(); return &task->mpp_task; @@ -404,12 +433,14 @@ static int vdpu_finish(struct mpp_dev *mpp, static int vdpu_result(struct mpp_dev *mpp, struct mpp_task *mpp_task, - u32 __user *dst, u32 size) + struct mpp_task_msgs *msgs) { + struct mpp_request *msg_reg_out = &msgs->reg_out; struct vdpu_task *task = to_vdpu_task(mpp_task); /* FIXME may overflow the kernel */ - if (copy_to_user(dst, task->reg, size)) { + if (copy_to_user(msg_reg_out->data, + task->reg, msg_reg_out->size)) { mpp_err("copy_to_user failed\n"); return -EIO; } diff --git a/drivers/video/rockchip/mpp/mpp_vdpu2.c b/drivers/video/rockchip/mpp/mpp_vdpu2.c index d6200db3602e..25d14ebf1e32 100644 --- a/drivers/video/rockchip/mpp/mpp_vdpu2.c +++ b/drivers/video/rockchip/mpp/mpp_vdpu2.c @@ -89,7 +89,7 @@ struct vdpu_task { unsigned long aclk_freq; u32 reg[VDPU2_REG_NUM]; u32 idx; - struct extra_info_for_iommu ext_inf; + struct reg_offset_info off_inf; u32 strm_addr; u32 irq_status; }; @@ -120,62 +120,62 @@ static struct mpp_hw_info vdpu_v2_hw_info = { /* * file handle translate information */ -static const char trans_tbl_default[] = { +static const u16 trans_tbl_default[] = { 61, 62, 63, 64, 131, 134, 135, 148 }; -static const char trans_tbl_jpegd[] = { +static const u16 trans_tbl_jpegd[] = { 21, 22, 61, 63, 64, 131 }; -static const char trans_tbl_h264d[] = { +static const u16 trans_tbl_h264d[] = { 61, 63, 64, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; -static const char trans_tbl_vc1d[] = { +static const u16 trans_tbl_vc1d[] = { 62, 63, 64, 131, 134, 135, 145, 148 }; -static const char trans_tbl_vp6d[] = { +static const u16 trans_tbl_vp6d[] = { 61, 63, 64, 131, 136, 145 }; -static const char trans_tbl_vp8d[] = { +static const u16 trans_tbl_vp8d[] = { 61, 63, 64, 131, 136, 137, 140, 141, 142, 143, 144, 145, 146, 147, 149 }; static struct mpp_trans_info vdpu_v2_trans[] = { [VDPU2_FMT_H264D] = { - .count = sizeof(trans_tbl_h264d), + .count = ARRAY_SIZE(trans_tbl_h264d), .table = trans_tbl_h264d, }, [VDPU2_FMT_H263D] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, [VDPU2_FMT_MPEG4D] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, [VDPU2_FMT_JPEGD] = { - .count = sizeof(trans_tbl_jpegd), + .count = ARRAY_SIZE(trans_tbl_jpegd), .table = trans_tbl_jpegd, }, [VDPU2_FMT_VC1D] = { - .count = sizeof(trans_tbl_vc1d), + .count = ARRAY_SIZE(trans_tbl_vc1d), .table = trans_tbl_vc1d, }, [VDPU2_FMT_MPEG2D] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, [VDPU2_FMT_MPEG1D] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, [VDPU2_FMT_VP6D] = { - .count = sizeof(trans_tbl_vp6d), + .count = ARRAY_SIZE(trans_tbl_vp6d), .table = trans_tbl_vp6d, }, [VDPU2_FMT_RESERVED] = { @@ -183,29 +183,103 @@ static struct mpp_trans_info vdpu_v2_trans[] = { .table = NULL, }, [VDPU2_FMT_VP7D] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, [VDPU2_FMT_VP8D] = { - .count = sizeof(trans_tbl_vp8d), + .count = ARRAY_SIZE(trans_tbl_vp8d), .table = trans_tbl_vp8d, }, [VDPU2_FMT_AVSD] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, }; -static void *vdpu_alloc_task(struct mpp_session *session, - void __user *src, u32 size) +static int vdpu_process_reg_fd(struct mpp_session *session, + struct vdpu_task *task, + struct mpp_task_msgs *msgs, + u32 extinf_len, + u32 reg_len) { - u32 fmt; - int err; + int ret = 0; + struct mpp_request *msg_reg = &msgs->reg_in; + int fmt = VDPU2_GET_FORMAT(task->reg[VDPU2_REG_SYS_CTRL_INDEX]); + + if (extinf_len > 0) { + if (likely(fmt == VDPU2_FMT_JPEGD)) { + ret = copy_from_user(&task->off_inf, + (u8 *)msg_reg->data + + msg_reg->size + - JPEG_IOC_EXTRA_SIZE, + JPEG_IOC_EXTRA_SIZE); + } else { + u32 ext_cpy = min_t(size_t, extinf_len, + sizeof(task->off_inf)); + ret = copy_from_user(&task->off_inf, + (u32 *)msg_reg->data + reg_len, + ext_cpy); + } + if (ret) { + mpp_err("copy_from_user failed when extra info\n"); + goto fail; + } + } else { + ret = mpp_extract_reg_offset_info(&msgs->reg_offset, + &task->off_inf); + if (ret) + goto fail; + } + + ret = mpp_translate_reg_address(session, &task->mpp_task, + fmt, task->reg, &task->off_inf); + if (ret) { + mpp_err("translate reg address failed.\n"); + mpp_dump_reg(task->reg, + task->hw_info->regidx_start, + task->hw_info->regidx_end); + goto fail; + } + + if (likely(fmt == VDPU2_FMT_H264D)) { + u32 idx = VDPU2_REG_DIR_MV_BASE_INDEX; + struct mpp_mem_region *mem_region = NULL; + dma_addr_t iova = 0; + u32 offset = task->reg[idx]; + int fd = task->reg[idx] & 0x3ff; + + offset = offset >> 10 << 4; + offset += mpp_query_reg_offset_info(&task->off_inf, idx); + mem_region = mpp_task_attach_fd(&task->mpp_task, fd); + if (IS_ERR(mem_region)) + goto fail; + + iova = mem_region->iova; + mpp_debug(DEBUG_IOMMU, "DMV[%3d]: %3d => %pad + offset %10d\n", + idx, fd, &iova, offset); + task->reg[idx] = iova + offset; + } + mpp_debug(DEBUG_SET_REG, "extra info cnt %u, magic %08x", + task->off_inf.cnt, task->off_inf.magic); + mpp_translate_reg_offset_info(&task->mpp_task, + &task->off_inf, + task->reg); + return 0; +fail: + return -EFAULT; +} + +static void *vdpu_alloc_task(struct mpp_session *session, + struct mpp_task_msgs *msgs) +{ + int ret; u32 reg_len; u32 extinf_len; + struct vdpu_task *task = NULL; - u32 dwsize = size / sizeof(u32); struct mpp_dev *mpp = session->mpp; + struct mpp_request *msg_reg = &msgs->reg_in; + u32 dwsize = msg_reg->size / sizeof(u32); mpp_debug_enter(); @@ -217,67 +291,23 @@ static void *vdpu_alloc_task(struct mpp_session *session, task->hw_info = mpp->var->hw_info; reg_len = min(task->hw_info->reg_num, dwsize); - extinf_len = dwsize > reg_len ? (dwsize - reg_len) * 4 : 0; + extinf_len = dwsize > reg_len ? + (dwsize - reg_len) * sizeof(u32) : 0; - if (copy_from_user(task->reg, src, reg_len * 4)) { - mpp_err("error: copy_from_user failed in reg_init\n"); + if (copy_from_user(task->reg, msg_reg->data, + reg_len * sizeof(u32))) { + mpp_err("copy_from_user failed in reg_init\n"); goto fail; } - - fmt = VDPU2_GET_FORMAT(task->reg[VDPU2_REG_SYS_CTRL_INDEX]); - if (extinf_len > 0) { - if (likely(fmt == VDPU2_FMT_JPEGD)) { - err = copy_from_user(&task->ext_inf, - (u8 *)src + size - - JPEG_IOC_EXTRA_SIZE, - JPEG_IOC_EXTRA_SIZE); - } else { - u32 ext_cpy = min_t(size_t, extinf_len, - sizeof(task->ext_inf)); - err = copy_from_user(&task->ext_inf, - (u32 *)src + reg_len, ext_cpy); - } - - if (err) { - mpp_err("copy_from_user failed when extra info\n"); + /* process fd in register */ + if (!(msg_reg->flags & MPP_FLAGS_REG_FD_NO_TRANS)) { + ret = vdpu_process_reg_fd(session, task, msgs, + extinf_len, reg_len); + if (ret) goto fail; - } } - - err = mpp_translate_reg_address(session->mpp, - &task->mpp_task, - fmt, task->reg); - if (err) { - mpp_err("error: translate reg address failed.\n"); - mpp_dump_reg(task->reg, - task->hw_info->regidx_start, - task->hw_info->regidx_end); - goto fail; - } - - if (likely(fmt == VDPU2_FMT_H264D)) { - struct mpp_mem_region *mem_region = NULL; - dma_addr_t iova = 0; - u32 offset = task->reg[VDPU2_REG_DIR_MV_BASE_INDEX]; - int fd = task->reg[VDPU2_REG_DIR_MV_BASE_INDEX] & 0x3ff; - - offset = offset >> 10 << 4; - mem_region = mpp_task_attach_fd(&task->mpp_task, fd); - if (IS_ERR(mem_region)) - goto fail; - - iova = mem_region->iova; - mpp_debug(DEBUG_IOMMU, "DMV[%3d]: %3d => %pad + offset %10d\n", - VDPU2_REG_DIR_MV_BASE_INDEX, fd, &iova, offset); - task->reg[VDPU2_REG_DIR_MV_BASE_INDEX] = iova + offset; - } - task->strm_addr = task->reg[VDPU2_REG_STREAM_RLC_BASE_INDEX]; - mpp_debug(DEBUG_SET_REG, "extra info cnt %u, magic %08x", - task->ext_inf.cnt, task->ext_inf.magic); - mpp_translate_extra_info(&task->mpp_task, &task->ext_inf, task->reg); - mpp_debug_leave(); return &task->mpp_task; @@ -366,12 +396,14 @@ static int vdpu_finish(struct mpp_dev *mpp, static int vdpu_result(struct mpp_dev *mpp, struct mpp_task *mpp_task, - u32 __user *dst, u32 size) + struct mpp_task_msgs *msgs) { + struct mpp_request *reg_out = &msgs->reg_out; struct vdpu_task *task = to_vdpu_task(mpp_task); /* FIXME may overflow the kernel */ - if (copy_to_user(dst, task->reg, size)) { + if (copy_to_user(reg_out->data, + task->reg, reg_out->size)) { mpp_err("copy_to_user failed\n"); return -EIO; } diff --git a/drivers/video/rockchip/mpp/mpp_vepu1.c b/drivers/video/rockchip/mpp/mpp_vepu1.c index acdacf992a4e..1269944760b5 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu1.c +++ b/drivers/video/rockchip/mpp/mpp_vepu1.c @@ -73,7 +73,7 @@ struct vepu_task { unsigned long aclk_freq; u32 reg[VEPU1_REG_NUM]; u32 idx; - struct extra_info_for_iommu ext_inf; + struct reg_offset_info off_inf; u32 irq_status; }; @@ -105,11 +105,11 @@ static struct mpp_hw_info vepu_v1_hw_info = { /* * file handle translate information */ -static const char trans_tbl_default[] = { +static const u16 trans_tbl_default[] = { 5, 6, 7, 8, 9, 10, 11, 12, 13, 51 }; -static const char trans_tbl_vp8e[] = { +static const u16 trans_tbl_vp8e[] = { 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 26, 51, 52, 58, 59 }; @@ -119,30 +119,87 @@ static struct mpp_trans_info trans_rk_vepu1[] = { .table = NULL, }, [VEPU1_FMT_VP8E] = { - .count = sizeof(trans_tbl_vp8e), + .count = ARRAY_SIZE(trans_tbl_vp8e), .table = trans_tbl_vp8e, }, [VEPU1_FMT_JPEGE] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, [VEPU1_FMT_H264E] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, }; -static void *vepu_alloc_task(struct mpp_session *session, - void __user *src, u32 size) +static int vepu_process_reg_fd(struct mpp_session *session, + struct vepu_task *task, + struct mpp_task_msgs *msgs, + u32 extinf_len, + u32 reg_len) { - u32 fmt; - int err; + int ret = 0; + struct mpp_request *msg_reg = &msgs->reg_in; + int fmt = VEPU1_GET_FORMAT(task->reg[VEPU1_REG_ENC_EN_INDEX]); + + if (extinf_len > 0) { + if (likely(fmt == VEPU1_FMT_JPEGE)) { + ret = copy_from_user(&task->off_inf, + (u8 *)msg_reg->data + + msg_reg->size + - JPEG_IOC_EXTRA_SIZE, + JPEG_IOC_EXTRA_SIZE); + } else { + u32 ext_cpy = min_t(size_t, extinf_len, + sizeof(task->off_inf)); + ret = copy_from_user(&task->off_inf, + (u32 *)msg_reg->data + reg_len, + ext_cpy); + } + + if (ret) { + mpp_err("copy_from_user failed when extra info\n"); + goto fail; + } + } else { + ret = mpp_extract_reg_offset_info(&msgs->reg_offset, + &task->off_inf); + if (ret) + goto fail; + } + + ret = mpp_translate_reg_address(session, &task->mpp_task, + fmt, task->reg, &task->off_inf); + if (ret) { + mpp_err("translate reg address failed.\n"); + mpp_dump_reg(task->reg, + task->hw_info->regidx_start, + task->hw_info->regidx_end); + goto fail; + } + + mpp_debug(DEBUG_SET_REG, "extra info cnt %u, magic %08x", + task->off_inf.cnt, task->off_inf.magic); + mpp_translate_reg_offset_info(&task->mpp_task, + &task->off_inf, + task->reg); + + return 0; +fail: + return -EFAULT; +} + +static void *vepu_alloc_task(struct mpp_session *session, + struct mpp_task_msgs *msgs) +{ + int ret; u32 reg_len; u32 extinf_len; struct vepu_task *task = NULL; - u32 dwsize = size / sizeof(u32); struct mpp_dev *mpp = session->mpp; + struct mpp_request *msg_reg = &msgs->reg_in; + u32 dwsize = msg_reg->size / sizeof(u32); mpp_debug_enter(); @@ -154,50 +211,22 @@ static void *vepu_alloc_task(struct mpp_session *session, task->hw_info = mpp->var->hw_info; reg_len = min(task->hw_info->reg_num, dwsize); - extinf_len = dwsize > reg_len ? (dwsize - reg_len) * 4 : 0; - - if (copy_from_user(task->reg, src, reg_len * 4)) { - mpp_err("error: copy_from_user failed in reg_init\n"); + extinf_len = dwsize > reg_len ? + (dwsize - reg_len) * sizeof(u32) : 0; + if (copy_from_user(task->reg, msg_reg->data, + reg_len * sizeof(u32))) { + mpp_err("copy_from_user failed in reg_init\n"); goto fail; } - fmt = VEPU1_GET_FORMAT(task->reg[VEPU1_REG_ENC_EN_INDEX]); - if (extinf_len > 0) { - if (likely(fmt == VEPU1_FMT_JPEGE)) { - err = copy_from_user(&task->ext_inf, - (u8 *)src + size - - JPEG_IOC_EXTRA_SIZE, - JPEG_IOC_EXTRA_SIZE); - } else { - u32 ext_cpy = min_t(size_t, extinf_len, - sizeof(task->ext_inf)); - err = copy_from_user(&task->ext_inf, - (u32 *)src + reg_len, ext_cpy); - } - - if (err) { - mpp_err("copy_from_user failed when extra info\n"); + /* process fd in register */ + if (!(msg_reg->flags & MPP_FLAGS_REG_FD_NO_TRANS)) { + ret = vepu_process_reg_fd(session, task, msgs, + extinf_len, reg_len); + if (ret) goto fail; - } } - err = mpp_translate_reg_address(session->mpp, - &task->mpp_task, - fmt, task->reg); - if (err) { - mpp_err("error: translate reg address failed.\n"); - mpp_dump_reg(task->reg, - task->hw_info->regidx_start, - task->hw_info->regidx_end); - goto fail; - } - - mpp_debug(DEBUG_SET_REG, "extra info cnt %u, magic %08x", - task->ext_inf.cnt, task->ext_inf.magic); - mpp_translate_extra_info(&task->mpp_task, - &task->ext_inf, - task->reg); - mpp_debug_leave(); return &task->mpp_task; @@ -324,12 +353,14 @@ static int vepu_finish(struct mpp_dev *mpp, static int vepu_result(struct mpp_dev *mpp, struct mpp_task *mpp_task, - u32 __user *dst, u32 size) + struct mpp_task_msgs *msgs) { + struct mpp_request *msg_reg_out = &msgs->reg_out; struct vepu_task *task = to_vepu_task(mpp_task); /* FIXME may overflow the kernel */ - if (copy_to_user(dst, task->reg, size)) { + if (copy_to_user(msg_reg_out->data, + task->reg, msg_reg_out->size)) { mpp_err("copy_to_user failed\n"); return -EIO; } diff --git a/drivers/video/rockchip/mpp/mpp_vepu2.c b/drivers/video/rockchip/mpp/mpp_vepu2.c index d277607e893c..226e5046f9b1 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu2.c +++ b/drivers/video/rockchip/mpp/mpp_vepu2.c @@ -80,7 +80,7 @@ struct vepu_task { unsigned long aclk_freq; u32 reg[VEPU2_REG_NUM]; u32 idx; - struct extra_info_for_iommu ext_inf; + struct reg_offset_info off_inf; u32 irq_status; }; @@ -110,11 +110,11 @@ static struct mpp_hw_info vepu_v2_hw_info = { /* * file handle translate information */ -static const char trans_tbl_default[] = { +static const u16 trans_tbl_default[] = { 48, 49, 50, 56, 57, 63, 64, 77, 78, 81 }; -static const char trans_tbl_vp8e[] = { +static const u16 trans_tbl_vp8e[] = { 27, 44, 45, 48, 49, 50, 56, 57, 63, 64, 76, 77, 78, 80, 81, 106, 108, }; @@ -125,30 +125,87 @@ static struct mpp_trans_info trans_rk_vepu2[] = { .table = NULL, }, [VEPU2_FMT_VP8E] = { - .count = sizeof(trans_tbl_vp8e), + .count = ARRAY_SIZE(trans_tbl_vp8e), .table = trans_tbl_vp8e, }, [VEPU2_FMT_JPEGE] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, [VEPU2_FMT_H264E] = { - .count = sizeof(trans_tbl_default), + .count = ARRAY_SIZE(trans_tbl_default), .table = trans_tbl_default, }, }; -static void *vepu_alloc_task(struct mpp_session *session, - void __user *src, u32 size) +static int vepu_process_reg_fd(struct mpp_session *session, + struct vepu_task *task, + struct mpp_task_msgs *msgs, + u32 extinf_len, + u32 reg_len) { - u32 fmt; - int err; + int ret = 0; + struct mpp_request *msg_reg = &msgs->reg_in; + int fmt = VEPU2_GET_FORMAT(task->reg[VEPU2_REG_ENC_EN_INDEX]); + + if (extinf_len > 0) { + if (likely(fmt == VEPU2_FMT_JPEGE)) { + ret = copy_from_user(&task->off_inf, + (u8 *)msg_reg->data + + msg_reg->size + - JPEG_IOC_EXTRA_SIZE, + JPEG_IOC_EXTRA_SIZE); + } else { + u32 ext_cpy = min_t(size_t, extinf_len, + sizeof(task->off_inf)); + ret = copy_from_user(&task->off_inf, + (u32 *)msg_reg->data + reg_len, + ext_cpy); + } + + if (ret) { + mpp_err("copy_from_user failed when extra info\n"); + goto fail; + } + } else { + ret = mpp_extract_reg_offset_info(&msgs->reg_offset, + &task->off_inf); + if (ret) + goto fail; + } + + ret = mpp_translate_reg_address(session, &task->mpp_task, + fmt, task->reg, &task->off_inf); + if (ret) { + mpp_err("translate reg address failed.\n"); + mpp_dump_reg(task->reg, + task->hw_info->regidx_start, + task->hw_info->regidx_end); + goto fail; + } + + mpp_debug(DEBUG_SET_REG, "extra info cnt %u, magic %08x", + task->off_inf.cnt, task->off_inf.magic); + mpp_translate_reg_offset_info(&task->mpp_task, + &task->off_inf, + task->reg); + + return 0; +fail: + return -EFAULT; +} + +static void *vepu_alloc_task(struct mpp_session *session, + struct mpp_task_msgs *msgs) +{ + int ret; u32 reg_len; u32 extinf_len; struct vepu_task *task = NULL; - u32 dwsize = size / sizeof(u32); struct mpp_dev *mpp = session->mpp; + struct mpp_request *msg_reg = &msgs->reg_in; + u32 dwsize = msg_reg->size / sizeof(u32); mpp_debug_enter(); @@ -159,50 +216,22 @@ static void *vepu_alloc_task(struct mpp_session *session, mpp_task_init(session, &task->mpp_task); task->hw_info = mpp->var->hw_info; reg_len = min(task->hw_info->reg_num, dwsize); - extinf_len = dwsize > reg_len ? (dwsize - reg_len) * 4 : 0; + extinf_len = dwsize > reg_len ? + (dwsize - reg_len) * sizeof(u32) : 0; - if (copy_from_user(task->reg, src, reg_len * 4)) { - mpp_err("error: copy_from_user failed in reg_init\n"); + if (copy_from_user(task->reg, msg_reg->data, + reg_len * sizeof(u32))) { + mpp_err("copy_from_user failed in reg_init\n"); goto fail; } - - fmt = VEPU2_GET_FORMAT(task->reg[VEPU2_REG_ENC_EN_INDEX]); - if (extinf_len > 0) { - if (likely(fmt == VEPU2_FMT_JPEGE)) { - err = copy_from_user(&task->ext_inf, - (u8 *)src + size - - JPEG_IOC_EXTRA_SIZE, - JPEG_IOC_EXTRA_SIZE); - } else { - u32 ext_cpy = min_t(size_t, extinf_len, - sizeof(task->ext_inf)); - err = copy_from_user(&task->ext_inf, - (u32 *)src + reg_len, - ext_cpy); - } - - if (err) { - mpp_err("copy_from_user failed when extra info\n"); + /* process fd in register */ + if (!(msg_reg->flags & MPP_FLAGS_REG_FD_NO_TRANS)) { + ret = vepu_process_reg_fd(session, task, msgs, + extinf_len, reg_len); + if (ret) goto fail; - } } - err = mpp_translate_reg_address(session->mpp, - &task->mpp_task, - fmt, task->reg); - if (err) { - mpp_err("error: translate reg address failed.\n"); - mpp_dump_reg(task->reg, - task->hw_info->regidx_start, - task->hw_info->regidx_end); - goto fail; - } - - mpp_debug(DEBUG_SET_REG, "extra info cnt %u, magic %08x", - task->ext_inf.cnt, task->ext_inf.magic); - mpp_translate_extra_info(&task->mpp_task, - &task->ext_inf, task->reg); - mpp_debug_leave(); return &task->mpp_task; @@ -330,12 +359,14 @@ static int vepu_finish(struct mpp_dev *mpp, static int vepu_result(struct mpp_dev *mpp, struct mpp_task *mpp_task, - u32 __user *dst, u32 size) + struct mpp_task_msgs *msgs) { + struct mpp_request *msg_reg_out = &msgs->reg_out; struct vepu_task *task = to_vepu_task(mpp_task); /* FIXME may overflow the kernel */ - if (copy_to_user(dst, task->reg, size)) { + if (copy_to_user(msg_reg_out->data, + task->reg, msg_reg_out->size)) { mpp_err("copy_to_user failed\n"); return -EIO; }