From 3f291e5ffb1c6e8bdd9a14f697d1cbbe7464456e Mon Sep 17 00:00:00 2001 From: Ding Wei Date: Thu, 9 Jan 2020 20:36:26 +0800 Subject: [PATCH] video: rockchip: mpp: update dev_command merge cmd: MPP_CMD_SET_REG --> MPP_CMD_SET_VEPU22_CFG --> MPP_CMD_SET_RKVENC_OSD_PLT --> MPP_CMD_SET_REG_WRITE MPP_CMD_SET_RKVENC_L2_REG --> change cmd: MPP_CMD_GET_REG --> MPP_CMD_SET_REG_READ tips: 1. the xx_WRITE cmd is to write register, while xx_READ cmd is to read register. 2. move MPP_CMD_GET_REG to MPP_CMD_SET_REG_READ, then it can set output when input. Change-Id: Iee1d5c6aafdfea5e0d02d1865cd06079ef5f716b Signed-off-by: Ding Wei --- drivers/video/rockchip/mpp/mpp_common.c | 180 +++++++++---------- drivers/video/rockchip/mpp/mpp_common.h | 63 ++++--- drivers/video/rockchip/mpp/mpp_rkvdec.c | 197 +++++++++++++-------- drivers/video/rockchip/mpp/mpp_vdpu1.c | 220 ++++++++++++++---------- drivers/video/rockchip/mpp/mpp_vdpu2.c | 210 ++++++++++++---------- drivers/video/rockchip/mpp/mpp_vepu1.c | 211 +++++++++++++---------- drivers/video/rockchip/mpp/mpp_vepu2.c | 205 ++++++++++++---------- 7 files changed, 723 insertions(+), 563 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_common.c b/drivers/video/rockchip/mpp/mpp_common.c index da62ac6f93be..656c5ed96b95 100644 --- a/drivers/video/rockchip/mpp/mpp_common.c +++ b/drivers/video/rockchip/mpp/mpp_common.c @@ -548,15 +548,14 @@ static int mpp_session_clear(struct mpp_dev *mpp, static int mpp_task_result(struct mpp_dev *mpp, struct mpp_task *task, - struct mpp_task_msgs *msgs, - u32 no_result) + struct mpp_task_msgs *msgs) { mpp_debug_enter(); if (!mpp || !task) return -EINVAL; - if (mpp->dev_ops->result && !no_result) + if (mpp->dev_ops->result) mpp->dev_ops->result(mpp, task, msgs); mpp_free_task(task->session, task); @@ -567,8 +566,7 @@ static int mpp_task_result(struct mpp_dev *mpp, } static int mpp_wait_result(struct mpp_session *session, - struct mpp_task_msgs *msgs, - u32 no_result) + struct mpp_task_msgs *msgs) { int ret; struct mpp_task *task; @@ -585,7 +583,7 @@ static int mpp_wait_result(struct mpp_session *session, msecs_to_jiffies(MPP_TIMEOUT_DELAY)); if (ret > 0) { task = mpp_session_pull_done(session); - ret = mpp_task_result(mpp, task, msgs, no_result); + ret = mpp_task_result(mpp, task, msgs); } else { mpp_err("pid %d wait %d task done timeout.\n", session->pid, atomic_read(&session->task_running)); @@ -716,12 +714,12 @@ static int mpp_parse_msg_v1(struct mpp_msg_v1 *msg, req->offset = msg->offset; req->data = (void __user *)(unsigned long)msg->data_ptr; - mpp_debug(DEBUG_IOCTL, "cmd %d, flags 0x%08x, size %d, offset %d\n", + mpp_debug(DEBUG_IOCTL, "cmd %x, flags %08x, size %d, offset %x\n", req->cmd, req->flags, req->size, req->offset); ret = mpp_check_cmd_v1(req->cmd); if (ret) - mpp_err("mpp cmd %d is not supprot.\n", req->cmd); + mpp_err("mpp cmd %x is not supproted.\n", req->cmd); return ret; } @@ -743,9 +741,10 @@ static int mpp_process_request(struct mpp_session *session, struct mpp_request *req, struct mpp_task_msgs *msgs) { + int ret; struct mpp_dev *mpp; - mpp_debug(DEBUG_IOCTL, "req->cmd %d\n", req->cmd); + mpp_debug(DEBUG_IOCTL, "req->cmd %x\n", req->cmd); switch (req->cmd) { case MPP_CMD_QUERY_HW_SUPPORT: { u32 hw_support = srv->hw_support; @@ -784,9 +783,12 @@ static int mpp_process_request(struct mpp_session *session, session->device_type = (enum MPP_DEVICE_TYPE)client_type; session->dma = mpp_dma_session_create(mpp->dev); session->dma->max_buffers = mpp->session_max_buffers; - if (mpp->dev_ops->init_session) - mpp->dev_ops->init_session(mpp); session->mpp = mpp; + if (mpp->dev_ops->init_session) { + ret = mpp->dev_ops->init_session(session); + if (ret) + return ret; + } } break; case MPP_CMD_INIT_DRIVER_DATA: { u32 val; @@ -818,15 +820,15 @@ static int mpp_process_request(struct mpp_session *session, req->size / sizeof(session->trans_table[0]); } } break; + case MPP_CMD_SET_REG_WRITE: + case MPP_CMD_SET_REG_READ: case MPP_CMD_SET_REG_ADDR_OFFSET: { - memcpy(&msgs->reg_offset, req, sizeof(*req)); + msgs->flags |= req->flags; + msgs->set_cnt++; } break; - case MPP_CMD_SET_REG: { - memcpy(&msgs->reg_in, req, sizeof(*req)); - } break; - case MPP_CMD_GET_REG: case MPP_CMD_POLL_HW_FINISH: { - memcpy(&msgs->reg_out, req, sizeof(*req)); + msgs->flags |= req->flags; + msgs->poll_cnt++; } break; case MPP_CMD_RESET_SESSION: { int ret; @@ -931,38 +933,14 @@ static int mpp_process_request(struct mpp_session *session, return 0; } -static int mpp_process_message(struct mpp_session *session, - struct mpp_task_msgs *msgs) -{ - int ret = 0; - struct mpp_request *task_msg; - - /* process message register in */ - task_msg = &msgs->reg_in; - if (task_msg->cmd == MPP_CMD_SET_REG && task_msg->size > 0) { - ret = mpp_process_task(session, msgs); - if (ret) - return ret; - } - /* process message register out */ - task_msg = &msgs->reg_out; - if (task_msg->cmd == MPP_CMD_POLL_HW_FINISH) - ret = mpp_wait_result(session, msgs, 1); - else if (task_msg->cmd == MPP_CMD_GET_REG) - ret = mpp_wait_result(session, msgs, 0); - - return ret; -} - static long mpp_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int ret = 0; - int msg_count = 0; struct mpp_service *srv; void __user *msg; - struct mpp_request req; + struct mpp_request *req; struct mpp_task_msgs task_msgs; struct mpp_session *session = (struct mpp_session *)filp->private_data; @@ -982,8 +960,8 @@ static long mpp_dev_ioctl(struct file *filp, msg = (void __user *)arg; memset(&task_msgs, 0, sizeof(task_msgs)); do { + req = &task_msgs.reqs[task_msgs.req_cnt]; /* first, parse to fixed struct */ - memset(&req, 0, sizeof(req)); switch (cmd) { case MPP_IOC_CFG_V1: { struct mpp_msg_v1 msg_v1; @@ -991,7 +969,7 @@ static long mpp_dev_ioctl(struct file *filp, memset(&msg_v1, 0, sizeof(msg_v1)); if (copy_from_user(&msg_v1, msg, sizeof(msg_v1))) return -EFAULT; - ret = mpp_parse_msg_v1(&msg_v1, &req); + ret = mpp_parse_msg_v1(&msg_v1, req); if (ret) return -EFAULT; @@ -1001,24 +979,31 @@ static long mpp_dev_ioctl(struct file *filp, mpp_err("unknown ioctl cmd %x\n", cmd); return -EINVAL; } - msg_count++; + task_msgs.req_cnt++; /* check loop times */ - if (msg_count > MPP_MAX_MSG_NUM) { + if (task_msgs.req_cnt > MPP_MAX_MSG_NUM) { mpp_err("fail, message count %d more than %d.\n", - msg_count, MPP_MAX_MSG_NUM); + task_msgs.req_cnt, MPP_MAX_MSG_NUM); return -EINVAL; } /* second, process request */ - ret = mpp_process_request(session, srv, &req, &task_msgs); + ret = mpp_process_request(session, srv, req, &task_msgs); if (ret) return -EFAULT; /* last, process task message */ - if (mpp_msg_is_last(&req)) { - ret = mpp_process_message(session, &task_msgs); - if (ret) - return -EFAULT; + if (mpp_msg_is_last(req)) { + if (task_msgs.set_cnt > 0) { + ret = mpp_process_task(session, &task_msgs); + if (ret) + return ret; + } + if (task_msgs.poll_cnt > 0) { + ret = mpp_wait_result(session, &task_msgs); + if (ret) + return ret; + } } - } while (!mpp_msg_is_last(&req)); + } while (!mpp_msg_is_last(req)); mpp_debug_leave(); @@ -1088,8 +1073,8 @@ static int mpp_dev_release(struct inode *inode, struct file *filp) /* release device resource */ mpp = session->mpp; if (mpp) { - if (mpp->dev_ops->release_session) - mpp->dev_ops->release_session(session); + if (mpp->dev_ops->free_session) + mpp->dev_ops->free_session(session); /* remove this filp from the asynchronusly notified filp's */ mpp_session_clear(mpp, session); @@ -1155,16 +1140,10 @@ int mpp_translate_reg_address(struct mpp_session *session, int i; int cnt; const u16 *tbl; - u16 trans_tbl[MPP_MAX_REG_TRANS_NUM]; mpp_debug_enter(); - 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) { + if (session->trans_count > 0) { cnt = session->trans_count; tbl = session->trans_table; } else { @@ -1201,31 +1180,39 @@ int mpp_translate_reg_address(struct mpp_session *session, return 0; } -int mpp_extract_reg_offset_info(struct mpp_request *msg, - struct reg_offset_info *off_inf) +int mpp_check_req(struct mpp_request *req, int base, + int max_size, u32 off_s, u32 off_e) { - int ret = 0; - int off_inf_size = sizeof(off_inf->elem); + int req_off; - if (msg->size > off_inf_size) { - mpp_err("msg->size %d more than %d.\n", - msg->size, off_inf_size); + if (req->offset < base) { + mpp_err("error: base %x, offset %x\n", + base, req->offset); 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; - } + req_off = req->offset - base; + if ((req_off + req->size) < off_s) { + mpp_err("error: req_off %x, req_size %x, off_s %x\n", + req_off, req->size, off_s); + return -EINVAL; + } + if (max_size < off_e) { + mpp_err("error: off_e %x, max_size %x\n", + off_e, max_size); + return -EINVAL; + } + if (req_off > max_size) { + mpp_err("error: req_off %x, max_size %x\n", + req_off, max_size); + return -EINVAL; + } + if ((req_off + req->size) > max_size) { + mpp_err("error: req_off %x, req_size %x, max_size %x\n", + req_off, req->size, max_size); + req->size = req_off + req->size - max_size; } - return ret; + return 0; } int mpp_query_reg_offset_info(struct reg_offset_info *off_inf, @@ -1235,9 +1222,6 @@ int mpp_query_reg_offset_info(struct reg_offset_info *off_inf, if (off_inf) { int i; - if (off_inf->magic != EXTRA_INFO_MAGIC) - return 0; - for (i = 0; i < off_inf->cnt; i++) { if (off_inf->elem[i].index == index) return off_inf->elem[i].offset; @@ -1257,9 +1241,6 @@ int mpp_translate_reg_offset_info(struct mpp_task *task, 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", off_inf->elem[i].index, @@ -1510,16 +1491,27 @@ int mpp_time_diff(struct mpp_task *task) return 0; } -int mpp_dump_reg(u32 *regs, u32 start_idx, u32 end_idx) +int mpp_write_req(struct mpp_dev *mpp, u32 *regs, + u32 start_idx, u32 end_idx, u32 en_idx) { - u32 i; + int i; - if (mpp_debug_unlikely(DEBUG_DUMP_ERR_REG)) { - pr_info("Dumping registers: %p\n", regs); - - for (i = start_idx; i < end_idx; i++) - pr_info("reg[%03d]: %08x\n", i, regs[i]); + for (i = start_idx; i < end_idx; i++) { + if (i == en_idx) + continue; + mpp_write_relaxed(mpp, i * sizeof(u32), regs[i]); } return 0; } + +int mpp_read_req(struct mpp_dev *mpp, u32 *regs, + u32 start_idx, u32 end_idx) +{ + int i; + + for (i = start_idx; i < end_idx; i++) + regs[i] = mpp_read_relaxed(mpp, i * sizeof(u32)); + + return 0; +} diff --git a/drivers/video/rockchip/mpp/mpp_common.h b/drivers/video/rockchip/mpp/mpp_common.h index c651f1750a61..58271b8eb29b 100644 --- a/drivers/video/rockchip/mpp/mpp_common.h +++ b/drivers/video/rockchip/mpp/mpp_common.h @@ -24,9 +24,6 @@ #define MHZ (1000 * 1000) -#define EXTRA_INFO_MAGIC (0x4C4A46) -#define JPEG_IOC_EXTRA_SIZE (48) - #define MPP_MAX_MSG_NUM (16) #define MPP_MAX_REG_TRANS_NUM (60) /* define flags for mpp_request */ @@ -85,15 +82,12 @@ enum MPP_DEV_COMMAND_TYPE { 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_SET_REG_WRITE = MPP_CMD_SEND_BASE + 0, + MPP_CMD_SET_REG_READ = MPP_CMD_SEND_BASE + 1, + MPP_CMD_SET_REG_ADDR_OFFSET = MPP_CMD_SEND_BASE + 2, MPP_CMD_POLL_BASE = 0x300, - MPP_CMD_GET_REG = MPP_CMD_POLL_BASE + 0, - MPP_CMD_POLL_HW_FINISH = MPP_CMD_POLL_BASE + 1, + MPP_CMD_POLL_HW_FINISH = MPP_CMD_POLL_BASE + 0, MPP_CMD_CONTROL_BASE = 0x400, MPP_CMD_RESET_SESSION = MPP_CMD_CONTROL_BASE + 0, @@ -112,13 +106,13 @@ struct mpp_request { void __user *data; }; -/* struct use to collect task input and output message */ +/* struct use to collect task set and poll message */ struct mpp_task_msgs { - /* for task input */ - struct mpp_request reg_in; - struct mpp_request reg_offset; - /* for task output */ - struct mpp_request reg_out; + u32 flags; + u32 req_cnt; + struct mpp_request reqs[MPP_MAX_MSG_NUM]; + u32 set_cnt; + u32 poll_cnt; }; struct mpp_grf_info { @@ -134,14 +128,14 @@ struct mpp_hw_info { /* register number */ u32 reg_num; /* hardware id */ - u32 regidx_id; + u32 reg_id; u32 hw_id; /* start index of register */ - u32 regidx_start; + u32 reg_start; /* end index of register */ - u32 regidx_end; + u32 reg_end; /* register of enable hardware */ - int regidx_en; + int reg_en; }; struct mpp_trans_info { @@ -155,7 +149,6 @@ struct reg_offset_elem { }; struct reg_offset_info { - u32 magic; u32 cnt; struct reg_offset_elem elem[MPP_MAX_REG_TRANS_NUM]; }; @@ -348,13 +341,12 @@ struct mpp_dev_ops { int (*free_task)(struct mpp_session *session, struct mpp_task *task); long (*ioctl)(struct mpp_session *session, struct mpp_request *req); - int (*init_session)(struct mpp_dev *mpp); - int (*release_session)(struct mpp_session *session); + int (*init_session)(struct mpp_session *session); + int (*free_session)(struct mpp_session *session); }; int mpp_taskqueue_init(struct mpp_taskqueue *queue, struct mpp_service *srv); - int mpp_reset_group_init(struct mpp_reset_group *group, struct mpp_service *srv); @@ -364,8 +356,8 @@ 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_check_req(struct mpp_request *req, int base, + int max_size, u32 off_s, u32 off_e); int mpp_query_reg_offset_info(struct reg_offset_info *off_inf, u32 index); int mpp_translate_reg_offset_info(struct mpp_task *task, @@ -396,13 +388,16 @@ int mpp_set_grf(struct mpp_grf_info *grf_info); int mpp_time_record(struct mpp_task *task); int mpp_time_diff(struct mpp_task *task); -int mpp_dump_reg(u32 *regs, u32 start_idx, u32 end_idx); +int mpp_write_req(struct mpp_dev *mpp, u32 *regs, + u32 start_idx, u32 end_idx, u32 en_idx); +int mpp_read_req(struct mpp_dev *mpp, u32 *regs, + u32 start_idx, u32 end_idx); static inline int mpp_write(struct mpp_dev *mpp, u32 reg, u32 val) { int idx = reg / sizeof(u32); - mpp_debug(DEBUG_SET_REG, "write reg[%d]: %08x\n", idx, val); + mpp_debug(DEBUG_SET_REG, "write reg[%3d]: %08x: %08x\n", idx, reg, val); writel(val, mpp->reg_base + reg); return 0; @@ -412,7 +407,7 @@ static inline int mpp_write_relaxed(struct mpp_dev *mpp, u32 reg, u32 val) { int idx = reg / sizeof(u32); - mpp_debug(DEBUG_SET_REG, "write reg[%d]: %08x\n", idx, val); + mpp_debug(DEBUG_SET_REG, "write reg[%3d]: %08x: %08x\n", idx, reg, val); writel_relaxed(val, mpp->reg_base + reg); return 0; @@ -420,20 +415,22 @@ static inline int mpp_write_relaxed(struct mpp_dev *mpp, u32 reg, u32 val) static inline u32 mpp_read(struct mpp_dev *mpp, u32 reg) { + u32 val = 0; int idx = reg / sizeof(u32); - u32 val = readl(mpp->reg_base + reg); - mpp_debug(DEBUG_GET_REG, "read reg[%d] 0x%x: %08x\n", idx, reg, val); + val = readl(mpp->reg_base + reg); + mpp_debug(DEBUG_GET_REG, "read reg[%3d]: %08x: %08x\n", idx, reg, val); return val; } static inline u32 mpp_read_relaxed(struct mpp_dev *mpp, u32 reg) { + u32 val = 0; int idx = reg / sizeof(u32); - u32 val = readl_relaxed(mpp->reg_base + reg); - mpp_debug(DEBUG_GET_REG, "read reg[%d] 0x%x: %08x\n", idx, reg, val); + val = readl_relaxed(mpp->reg_base + reg); + mpp_debug(DEBUG_GET_REG, "read reg[%3d] %08x: %08x\n", idx, reg, val); return val; } diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec.c b/drivers/video/rockchip/mpp/mpp_rkvdec.c index 070b25a3209d..5c3eec4fea66 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec.c @@ -135,10 +135,14 @@ struct rkvdec_task { u32 reg[RKVDEC_V2_REG_NUM]; struct reg_offset_info off_inf; - u32 idx; u32 strm_addr; u32 irq_status; + /* req for current task */ + u32 w_req_cnt; + struct mpp_request w_reqs[MPP_MAX_MSG_NUM]; + u32 r_req_cnt; + struct mpp_request r_reqs[MPP_MAX_MSG_NUM]; }; struct rkvdec_dev { @@ -191,18 +195,18 @@ struct rkvdec_dev { */ static struct mpp_hw_info rk_hevcdec_hw_info = { .reg_num = HEVC_DEC_REG_NUM, - .regidx_id = HEVC_DEC_REG_HW_ID_INDEX, - .regidx_start = HEVC_DEC_REG_START_INDEX, - .regidx_end = HEVC_DEC_REG_END_INDEX, - .regidx_en = RKVDEC_REG_INT_EN_INDEX, + .reg_id = HEVC_DEC_REG_HW_ID_INDEX, + .reg_start = HEVC_DEC_REG_START_INDEX, + .reg_end = HEVC_DEC_REG_END_INDEX, + .reg_en = RKVDEC_REG_INT_EN_INDEX, }; static struct mpp_hw_info rkvdec_v1_hw_info = { .reg_num = RKVDEC_V1_REG_NUM, - .regidx_id = RKVDEC_V1_REG_HW_ID_INDEX, - .regidx_start = RKVDEC_V1_REG_START_INDEX, - .regidx_end = RKVDEC_V1_REG_END_INDEX, - .regidx_en = RKVDEC_REG_INT_EN_INDEX, + .reg_id = RKVDEC_V1_REG_HW_ID_INDEX, + .reg_start = RKVDEC_V1_REG_START_INDEX, + .reg_end = RKVDEC_V1_REG_END_INDEX, + .reg_en = RKVDEC_REG_INT_EN_INDEX, }; /* @@ -677,11 +681,6 @@ static int rkvdec_process_reg_fd(struct mpp_session *session, 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 * @@ -711,7 +710,7 @@ static int rkvdec_process_reg_fd(struct mpp_session *session, 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; + return -EFAULT; iova = mem_region->iova; task->reg[idx] = iova + offset; @@ -719,33 +718,86 @@ static int rkvdec_process_reg_fd(struct mpp_session *session, 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 (ret) + return ret; - 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 int rkvdec_extract_task_msg(struct rkvdec_task *task, + struct mpp_task_msgs *msgs) +{ + u32 i; + int ret; + struct mpp_request *req; + struct reg_offset_info *off_inf = &task->off_inf; + + for (i = 0; i < msgs->req_cnt; i++) { + u32 off_s, off_e; + + req = &msgs->reqs[i]; + if (!req->size) + continue; + + switch (req->cmd) { + case MPP_CMD_SET_REG_WRITE: { + off_s = task->hw_info->reg_start * sizeof(u32); + off_e = task->hw_info->reg_end * sizeof(u32); + ret = mpp_check_req(req, 0, sizeof(task->reg), + off_s, off_e); + if (ret) + continue; + if (copy_from_user((u8 *)task->reg + req->offset, + req->data, req->size)) { + mpp_err("copy_from_user reg failed\n"); + return -EIO; + } + memcpy(&task->w_reqs[task->w_req_cnt++], + req, sizeof(*req)); + } break; + case MPP_CMD_SET_REG_READ: { + off_s = task->hw_info->reg_start * sizeof(u32); + off_e = task->hw_info->reg_end * sizeof(u32); + ret = mpp_check_req(req, 0, sizeof(task->reg), + off_s, off_e); + if (ret) + continue; + memcpy(&task->r_reqs[task->r_req_cnt++], + req, sizeof(*req)); + } break; + case MPP_CMD_SET_REG_ADDR_OFFSET: { + int off = off_inf->cnt * sizeof(off_inf->elem[0]); + + ret = mpp_check_req(req, off, sizeof(off_inf->elem), + 0, sizeof(off_inf->elem)); + if (ret) + continue; + if (copy_from_user(&off_inf->elem[off_inf->cnt], + req->data, + req->size)) { + mpp_err("copy_from_user failed\n"); + return -EINVAL; + } + off_inf->cnt += req->size / sizeof(off_inf->elem[0]); + } break; + default: + break; + } + } + mpp_debug(DEBUG_TASK_INFO, "w_req_cnt %d, r_req_cnt %d\n", + task->w_req_cnt, task->r_req_cnt); + + return 0; } 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(); @@ -755,20 +807,18 @@ static void *rkvdec_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); - if (copy_from_user(task->reg, msg_reg->data, - reg_len * sizeof(u32))) { - mpp_err("copy_from_user failed in reg_init\n"); + /* extract reqs for current task */ + ret = rkvdec_extract_task_msg(task, msgs); + if (ret) goto fail; - } /* process fd in pps for 264 and 265 */ - if (!(msg_reg->flags & MPP_FLAGS_SCL_FD_NO_TRANS)) { + if (!(msgs->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)) { + if (!(msgs->flags & MPP_FLAGS_REG_FD_NO_TRANS)) { ret = rkvdec_process_reg_fd(session, task, msgs); if (ret) goto fail; @@ -803,11 +853,8 @@ static int rkvdec_prepare(struct mpp_dev *mpp, static int rkvdec_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) { - u32 i; - u32 regidx_start; - u32 regidx_end; - u32 regidx_en; - u32 reg = 0; + int i; + u32 reg_en; struct rkvdec_dev *dec = NULL; struct rkvdec_task *task = NULL; @@ -815,11 +862,10 @@ static int rkvdec_run(struct mpp_dev *mpp, dec = to_rkvdec_dev(mpp); task = to_rkvdec_task(mpp_task); - + reg_en = task->hw_info->reg_en; switch (dec->state) { - case RKVDEC_STATE_NORMAL: - /* FIXME: spin lock here */ - dec->current_task = task; + case RKVDEC_STATE_NORMAL: { + u32 reg; /* set cache size */ reg = RKVDEC_CACHE_PERMIT_CACHEABLE_ACCESS @@ -833,19 +879,21 @@ static int rkvdec_run(struct mpp_dev *mpp, mpp_write_relaxed(mpp, RKVDEC_REG_CLR_CACHE0_BASE, 1); mpp_write_relaxed(mpp, RKVDEC_REG_CLR_CACHE1_BASE, 1); /* set registers for hardware */ - regidx_start = task->hw_info->regidx_start; - regidx_end = task->hw_info->regidx_end; - regidx_en = task->hw_info->regidx_en; - for (i = regidx_start; i <= regidx_end; i++) { - if (i == regidx_en) - continue; - mpp_write_relaxed(mpp, i * sizeof(u32), task->reg[i]); + for (i = 0; i < task->w_req_cnt; i++) { + int s, e; + struct mpp_request *req = &task->w_reqs[i]; + + s = req->offset / sizeof(u32); + e = s + req->size / sizeof(u32); + mpp_write_req(mpp, task->reg, s, e, reg_en); } + /* init current task */ + dec->current_task = task; /* Flush the register before the start the device */ wmb(); mpp_write(mpp, RKVDEC_REG_INT_EN, - task->reg[regidx_en] | RKVDEC_DEC_START); - break; + task->reg[reg_en] | RKVDEC_DEC_START); + } break; default: break; } @@ -942,8 +990,6 @@ static int rkvdec_finish(struct mpp_dev *mpp, struct mpp_task *mpp_task) { u32 i; - u32 regidx_start; - u32 regidx_end; u32 dec_get; s32 dec_length; struct rkvdec_dev *dec = to_rkvdec_dev(mpp); @@ -953,19 +999,24 @@ static int rkvdec_finish(struct mpp_dev *mpp, switch (dec->state) { case RKVDEC_STATE_NORMAL: { + u32 s, e; + struct mpp_request *req; + /* read register after running */ - regidx_start = 2;//task->hw_info->regidx_start; - regidx_end = task->hw_info->regidx_end; - for (i = regidx_start; i <= regidx_end; i++) - task->reg[i] = mpp_read_relaxed(mpp, i * sizeof(u32)); + for (i = 0; i < task->r_req_cnt; i++) { + req = &task->r_reqs[i]; + s = req->offset / sizeof(u32); + e = s + req->size / sizeof(u32); + mpp_read_req(mpp, task->reg, s, e); + } + /* revert hack for irq status */ task->reg[RKVDEC_REG_INT_EN_INDEX] = task->irq_status; /* revert hack for decoded length */ - dec_get = task->reg[RKVDEC_REG_RLC_BASE_INDEX]; + dec_get = mpp_read_relaxed(mpp, RKVDEC_REG_RLC_BASE); dec_length = dec_get - task->strm_addr; task->reg[RKVDEC_REG_RLC_BASE_INDEX] = dec_length << 10; mpp_debug(DEBUG_REGISTER, - "dec_get %08x dec_length %d\n", - dec_get, dec_length); + "dec_get %08x dec_length %d\n", dec_get, dec_length); } break; default: break; @@ -980,14 +1031,20 @@ static int rkvdec_result(struct mpp_dev *mpp, struct mpp_task *mpp_task, struct mpp_task_msgs *msgs) { - struct mpp_request *msg_reg_out = &msgs->reg_out; + u32 i; + struct mpp_request *req; struct rkvdec_task *task = to_rkvdec_task(mpp_task); /* FIXME may overflow the kernel */ - if (copy_to_user(msg_reg_out->data, - task->reg, msg_reg_out->size)) { - mpp_err("copy_to_user failed\n"); - return -EIO; + for (i = 0; i < task->r_req_cnt; i++) { + req = &task->r_reqs[i]; + + if (copy_to_user(req->data, + (u8 *)task->reg + req->offset, + req->size)) { + mpp_err("copy_to_user reg fail\n"); + return -EIO; + } } return 0; @@ -1109,7 +1166,7 @@ static int rkvdec_init(struct mpp_dev *mpp) /* read hardware id*/ hw_info = mpp->var->hw_info; - hw_info->hw_id = mpp_read(mpp, hw_info->regidx_id); + hw_info->hw_id = mpp_read(mpp, hw_info->reg_id); return 0; } diff --git a/drivers/video/rockchip/mpp/mpp_vdpu1.c b/drivers/video/rockchip/mpp/mpp_vdpu1.c index 1b64222e81c0..6aa6506bf104 100644 --- a/drivers/video/rockchip/mpp/mpp_vdpu1.c +++ b/drivers/video/rockchip/mpp/mpp_vdpu1.c @@ -95,10 +95,15 @@ struct vdpu_task { unsigned long aclk_freq; u32 reg[VDPU1_REG_PP_NUM]; - u32 idx; + struct reg_offset_info off_inf; u32 strm_addr; u32 irq_status; + /* req for current task */ + u32 w_req_cnt; + struct mpp_request w_reqs[MPP_MAX_MSG_NUM]; + u32 r_req_cnt; + struct mpp_request r_reqs[MPP_MAX_MSG_NUM]; }; struct vdpu_dev { @@ -119,18 +124,18 @@ struct vdpu_dev { static struct mpp_hw_info vdpu_v1_hw_info = { .reg_num = VDPU1_REG_NUM, - .regidx_id = VDPU1_REG_HW_ID_INDEX, - .regidx_start = VDPU1_REG_START_INDEX, - .regidx_end = VDPU1_REG_END_INDEX, - .regidx_en = VDPU1_REG_DEC_INT_EN_INDEX, + .reg_id = VDPU1_REG_HW_ID_INDEX, + .reg_start = VDPU1_REG_START_INDEX, + .reg_end = VDPU1_REG_END_INDEX, + .reg_en = VDPU1_REG_DEC_INT_EN_INDEX, }; static struct mpp_hw_info vdpu_pp_v1_hw_info = { .reg_num = VDPU1_REG_PP_NUM, - .regidx_id = VDPU1_REG_HW_ID_INDEX, - .regidx_start = VDPU1_REG_PP_START_INDEX, - .regidx_end = VDPU1_REG_PP_END_INDEX, - .regidx_en = VDPU1_REG_DEC_INT_EN_INDEX, + .reg_id = VDPU1_REG_HW_ID_INDEX, + .reg_start = VDPU1_REG_PP_START_INDEX, + .reg_end = VDPU1_REG_PP_END_INDEX, + .reg_en = VDPU1_REG_DEC_INT_EN_INDEX, }; /* @@ -218,49 +223,15 @@ static struct mpp_trans_info vdpu_v1_trans[] = { 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) + struct mpp_task_msgs *msgs) { int ret = 0; - struct mpp_request *msg_reg = &msgs->reg_in; int fmt = VDPU1_GET_FORMAT(task->reg[VDPU1_REG_SYS_CTRL_INDEX]); - if (extinf_len > 0) { - if (likely(fmt == VDPU1_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 (ret) + return ret; /* * special offset scale case * @@ -292,27 +263,86 @@ static int vdpu_process_reg_fd(struct mpp_session *session, 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); + &task->off_inf, task->reg); return 0; fail: return -EFAULT; } +static int vdpu_extract_task_msg(struct vdpu_task *task, + struct mpp_task_msgs *msgs) +{ + u32 i; + int ret; + struct mpp_request *req; + struct reg_offset_info *off_inf = &task->off_inf; + + for (i = 0; i < msgs->req_cnt; i++) { + u32 off_s, off_e; + + req = &msgs->reqs[i]; + if (!req->size) + continue; + + switch (req->cmd) { + case MPP_CMD_SET_REG_WRITE: { + off_s = task->hw_info->reg_start * sizeof(u32); + off_e = task->hw_info->reg_end * sizeof(u32); + ret = mpp_check_req(req, 0, sizeof(task->reg), + off_s, off_e); + if (ret) + continue; + if (copy_from_user((u8 *)task->reg + req->offset, + req->data, req->size)) { + mpp_err("copy_from_user reg failed\n"); + return -EIO; + } + memcpy(&task->w_reqs[task->w_req_cnt++], + req, sizeof(*req)); + } break; + case MPP_CMD_SET_REG_READ: { + off_s = task->hw_info->reg_start * sizeof(u32); + off_e = task->hw_info->reg_end * sizeof(u32); + ret = mpp_check_req(req, 0, sizeof(task->reg), + off_s, off_e); + if (ret) + continue; + memcpy(&task->r_reqs[task->r_req_cnt++], + req, sizeof(*req)); + } break; + case MPP_CMD_SET_REG_ADDR_OFFSET: { + int off = off_inf->cnt * sizeof(off_inf->elem[0]); + + ret = mpp_check_req(req, off, sizeof(off_inf->elem), + 0, sizeof(off_inf->elem)); + if (ret) + continue; + if (copy_from_user(&off_inf->elem[off_inf->cnt], + req->data, + req->size)) { + mpp_err("copy_from_user failed\n"); + return -EINVAL; + } + off_inf->cnt += req->size / sizeof(off_inf->elem[0]); + } break; + default: + break; + } + } + mpp_debug(DEBUG_TASK_INFO, "w_req_cnt %d, r_req_cnt %d\n", + task->w_req_cnt, task->r_req_cnt); + + return 0; +} + 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(); @@ -328,19 +358,13 @@ static void *vdpu_alloc_task(struct mpp_session *session, } 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"); + /* extract reqs for current task */ + ret = vdpu_extract_task_msg(task, msgs); + if (ret) 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 (!(msgs->flags & MPP_FLAGS_REG_FD_NO_TRANS)) { + ret = vdpu_process_reg_fd(session, task, msgs); if (ret) goto fail; } @@ -366,9 +390,7 @@ static int vdpu_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) { u32 i; - u32 regidx_start; - u32 regidx_end; - u32 regidx_en; + u32 reg_en; struct vdpu_task *task = NULL; struct vdpu_dev *dec = NULL; @@ -377,23 +399,23 @@ static int vdpu_run(struct mpp_dev *mpp, task = to_vdpu_task(mpp_task); dec = to_vdpu_dev(mpp); - /* FIXME: spin lock here */ - dec->current_task = task; /* clear cache */ mpp_write_relaxed(mpp, VDPU1_REG_CLR_CACHE_BASE, 1); /* set registers for hardware */ - regidx_start = task->hw_info->regidx_start; - regidx_end = task->hw_info->regidx_end; - regidx_en = task->hw_info->regidx_en; - for (i = regidx_start; i <= regidx_end; i++) { - if (i == regidx_en) - continue; - mpp_write_relaxed(mpp, i * sizeof(u32), task->reg[i]); + reg_en = task->hw_info->reg_en; + for (i = 0; i < task->w_req_cnt; i++) { + struct mpp_request *req = &task->w_reqs[i]; + int s = req->offset / sizeof(u32); + int e = s + req->size / sizeof(u32); + + mpp_write_req(mpp, task->reg, s, e, reg_en); } - /* Flush the registers */ + /* init current task */ + dec->current_task = task; + /* Flush the register before the start the device */ wmb(); mpp_write(mpp, VDPU1_REG_DEC_INT_EN, - task->reg[regidx_en] | VDPU1_DEC_START); + task->reg[reg_en] | VDPU1_DEC_START); mpp_debug_leave(); @@ -404,27 +426,29 @@ static int vdpu_finish(struct mpp_dev *mpp, struct mpp_task *mpp_task) { u32 i; - u32 regidx_start; - u32 regidx_end; + u32 s, e; u32 dec_get; s32 dec_length; + struct mpp_request *req; struct vdpu_task *task = to_vdpu_task(mpp_task); mpp_debug_enter(); /* read register after running */ - regidx_start = task->hw_info->regidx_start; - regidx_end = task->hw_info->regidx_end; - for (i = regidx_start; i <= regidx_end; i++) - task->reg[i] = mpp_read_relaxed(mpp, i * sizeof(u32)); + for (i = 0; i < task->r_req_cnt; i++) { + req = &task->r_reqs[i]; + s = req->offset / sizeof(u32); + e = s + req->size / sizeof(u32); + mpp_read_req(mpp, task->reg, s, e); + } + /* revert hack for irq status */ task->reg[VDPU1_REG_DEC_INT_EN_INDEX] = task->irq_status; /* revert hack for decoded length */ - dec_get = task->reg[VDPU1_REG_STREAM_RLC_BASE_INDEX]; + dec_get = mpp_read_relaxed(mpp, VDPU1_REG_STREAM_RLC_BASE); dec_length = dec_get - task->strm_addr; task->reg[VDPU1_REG_STREAM_RLC_BASE_INDEX] = dec_length << 10; mpp_debug(DEBUG_REGISTER, - "dec_get %08x dec_length %d\n", - dec_get, dec_length); + "dec_get %08x dec_length %d\n", dec_get, dec_length); mpp_debug_leave(); @@ -435,14 +459,20 @@ static int vdpu_result(struct mpp_dev *mpp, struct mpp_task *mpp_task, struct mpp_task_msgs *msgs) { - struct mpp_request *msg_reg_out = &msgs->reg_out; + u32 i; + struct mpp_request *req; struct vdpu_task *task = to_vdpu_task(mpp_task); /* FIXME may overflow the kernel */ - if (copy_to_user(msg_reg_out->data, - task->reg, msg_reg_out->size)) { - mpp_err("copy_to_user failed\n"); - return -EIO; + for (i = 0; i < task->r_req_cnt; i++) { + req = &task->r_reqs[i]; + + if (copy_to_user(req->data, + (u8 *)task->reg + req->offset, + req->size)) { + mpp_err("copy_to_user reg fail\n"); + return -EIO; + } } return 0; @@ -526,7 +556,7 @@ static int vdpu_init(struct mpp_dev *mpp) /* read hardware id*/ hw_info = mpp->var->hw_info; - hw_info->hw_id = mpp_read(mpp, hw_info->regidx_id); + hw_info->hw_id = mpp_read(mpp, hw_info->reg_id); return 0; } diff --git a/drivers/video/rockchip/mpp/mpp_vdpu2.c b/drivers/video/rockchip/mpp/mpp_vdpu2.c index 25d14ebf1e32..8e2f616d9539 100644 --- a/drivers/video/rockchip/mpp/mpp_vdpu2.c +++ b/drivers/video/rockchip/mpp/mpp_vdpu2.c @@ -88,10 +88,15 @@ struct vdpu_task { unsigned long aclk_freq; u32 reg[VDPU2_REG_NUM]; - u32 idx; + struct reg_offset_info off_inf; u32 strm_addr; u32 irq_status; + /* req for current task */ + u32 w_req_cnt; + struct mpp_request w_reqs[MPP_MAX_MSG_NUM]; + u32 r_req_cnt; + struct mpp_request r_reqs[MPP_MAX_MSG_NUM]; }; struct vdpu_dev { @@ -112,9 +117,9 @@ struct vdpu_dev { static struct mpp_hw_info vdpu_v2_hw_info = { .reg_num = VDPU2_REG_NUM, - .regidx_start = VDPU2_REG_START_INDEX, - .regidx_end = VDPU2_REG_END_INDEX, - .regidx_en = VDPU2_REG_DEC_EN_INDEX, + .reg_start = VDPU2_REG_START_INDEX, + .reg_end = VDPU2_REG_END_INDEX, + .reg_en = VDPU2_REG_DEC_EN_INDEX, }; /* @@ -198,48 +203,15 @@ static struct mpp_trans_info vdpu_v2_trans[] = { 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) + struct mpp_task_msgs *msgs) { 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 (ret) + return ret; if (likely(fmt == VDPU2_FMT_H264D)) { u32 idx = VDPU2_REG_DIR_MV_BASE_INDEX; @@ -252,34 +224,90 @@ static int vdpu_process_reg_fd(struct mpp_session *session, 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; + return -EFAULT; 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); + &task->off_inf, task->reg); + return 0; +} + +static int vdpu_extract_task_msg(struct vdpu_task *task, + struct mpp_task_msgs *msgs) +{ + u32 i; + int ret; + struct mpp_request *req; + struct reg_offset_info *off_inf = &task->off_inf; + + for (i = 0; i < msgs->req_cnt; i++) { + u32 off_s, off_e; + + req = &msgs->reqs[i]; + if (!req->size) + continue; + + switch (req->cmd) { + case MPP_CMD_SET_REG_WRITE: { + off_s = task->hw_info->reg_start * sizeof(u32); + off_e = task->hw_info->reg_end * sizeof(u32); + ret = mpp_check_req(req, 0, sizeof(task->reg), + off_s, off_e); + if (ret) + continue; + if (copy_from_user((u8 *)task->reg + req->offset, + req->data, req->size)) { + mpp_err("copy_from_user reg failed\n"); + return -EIO; + } + memcpy(&task->w_reqs[task->w_req_cnt++], + req, sizeof(*req)); + } break; + case MPP_CMD_SET_REG_READ: { + off_s = task->hw_info->reg_start * sizeof(u32); + off_e = task->hw_info->reg_end * sizeof(u32); + ret = mpp_check_req(req, 0, sizeof(task->reg), + off_s, off_e); + if (ret) + continue; + memcpy(&task->r_reqs[task->r_req_cnt++], + req, sizeof(*req)); + } break; + case MPP_CMD_SET_REG_ADDR_OFFSET: { + int off = off_inf->cnt * sizeof(off_inf->elem[0]); + + ret = mpp_check_req(req, off, sizeof(off_inf->elem), + 0, sizeof(off_inf->elem)); + if (ret) + continue; + if (copy_from_user(&off_inf->elem[off_inf->cnt], + req->data, + req->size)) { + mpp_err("copy_from_user failed\n"); + return -EINVAL; + } + off_inf->cnt += req->size / sizeof(off_inf->elem[0]); + } break; + default: + break; + } + } + mpp_debug(DEBUG_TASK_INFO, "w_req_cnt %d, r_req_cnt %d\n", + task->w_req_cnt, task->r_req_cnt); + 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; struct mpp_dev *mpp = session->mpp; - struct mpp_request *msg_reg = &msgs->reg_in; - u32 dwsize = msg_reg->size / sizeof(u32); mpp_debug_enter(); @@ -288,21 +316,14 @@ static void *vdpu_alloc_task(struct mpp_session *session, 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); - 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"); + /* extract reqs for current task */ + ret = vdpu_extract_task_msg(task, msgs); + if (ret) 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 (!(msgs->flags & MPP_FLAGS_REG_FD_NO_TRANS)) { + ret = vdpu_process_reg_fd(session, task, msgs); if (ret) goto fail; } @@ -328,9 +349,7 @@ static int vdpu_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) { u32 i; - u32 regidx_start; - u32 regidx_end; - u32 regidx_en; + u32 reg_en; struct vdpu_task *task = NULL; struct vdpu_dev *dec = NULL; @@ -339,24 +358,23 @@ static int vdpu_run(struct mpp_dev *mpp, task = to_vdpu_task(mpp_task); dec = to_vdpu_dev(mpp); - /* FIXME: spin lock here */ - dec->current_task = task; - /* clear cache */ mpp_write_relaxed(mpp, VDPU2_REG_CLR_CACHE_BASE, 1); /* set registers for hardware */ - regidx_start = task->hw_info->regidx_start; - regidx_end = task->hw_info->regidx_end; - regidx_en = task->hw_info->regidx_en; - for (i = regidx_start; i <= regidx_end; i++) { - if (i == regidx_en) - continue; - mpp_write_relaxed(mpp, i * sizeof(u32), task->reg[i]); + reg_en = task->hw_info->reg_en; + for (i = 0; i < task->w_req_cnt; i++) { + struct mpp_request *req = &task->w_reqs[i]; + int s = req->offset / sizeof(u32); + int e = s + req->size / sizeof(u32); + + mpp_write_req(mpp, task->reg, s, e, reg_en); } + /* init current task */ + dec->current_task = task; /* Flush the registers */ wmb(); mpp_write(mpp, VDPU2_REG_DEC_EN, - task->reg[regidx_en] | VDPU2_DEC_START); + task->reg[reg_en] | VDPU2_DEC_START); mpp_debug_leave(); @@ -367,27 +385,29 @@ static int vdpu_finish(struct mpp_dev *mpp, struct mpp_task *mpp_task) { u32 i; - u32 regidx_start; - u32 regidx_end; + u32 s, e; u32 dec_get; s32 dec_length; + struct mpp_request *req; struct vdpu_task *task = to_vdpu_task(mpp_task); mpp_debug_enter(); /* read register after running */ - regidx_start = task->hw_info->regidx_start; - regidx_end = task->hw_info->regidx_end; - for (i = regidx_start; i <= regidx_end; i++) - task->reg[i] = mpp_read_relaxed(mpp, i * sizeof(u32)); + for (i = 0; i < task->r_req_cnt; i++) { + req = &task->r_reqs[i]; + s = req->offset / sizeof(u32); + e = s + req->size / sizeof(u32); + mpp_read_req(mpp, task->reg, s, e); + } + /* revert hack for irq status */ task->reg[VDPU2_REG_DEC_INT_INDEX] = task->irq_status; /* revert hack for decoded length */ - dec_get = task->reg[VDPU2_REG_STREAM_RLC_BASE_INDEX]; + dec_get = mpp_read_relaxed(mpp, VDPU2_REG_STREAM_RLC_BASE); dec_length = dec_get - task->strm_addr; task->reg[VDPU2_REG_STREAM_RLC_BASE_INDEX] = dec_length << 10; mpp_debug(DEBUG_REGISTER, - "dec_get %08x dec_length %d\n", - dec_get, dec_length); + "dec_get %08x dec_length %d\n", dec_get, dec_length); mpp_debug_leave(); @@ -398,14 +418,20 @@ static int vdpu_result(struct mpp_dev *mpp, struct mpp_task *mpp_task, struct mpp_task_msgs *msgs) { - struct mpp_request *reg_out = &msgs->reg_out; + u32 i; + struct mpp_request *req; struct vdpu_task *task = to_vdpu_task(mpp_task); /* FIXME may overflow the kernel */ - if (copy_to_user(reg_out->data, - task->reg, reg_out->size)) { - mpp_err("copy_to_user failed\n"); - return -EIO; + for (i = 0; i < task->r_req_cnt; i++) { + req = &task->r_reqs[i]; + + if (copy_to_user(req->data, + (u8 *)task->reg + req->offset, + req->size)) { + mpp_err("copy_to_user reg fail\n"); + return -EIO; + } } return 0; diff --git a/drivers/video/rockchip/mpp/mpp_vepu1.c b/drivers/video/rockchip/mpp/mpp_vepu1.c index 1269944760b5..7268f9df2066 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu1.c +++ b/drivers/video/rockchip/mpp/mpp_vepu1.c @@ -72,9 +72,14 @@ struct vepu_task { unsigned long aclk_freq; u32 reg[VEPU1_REG_NUM]; - u32 idx; + struct reg_offset_info off_inf; u32 irq_status; + /* req for current task */ + u32 w_req_cnt; + struct mpp_request w_reqs[MPP_MAX_MSG_NUM]; + u32 r_req_cnt; + struct mpp_request r_reqs[MPP_MAX_MSG_NUM]; }; struct vepu_dev { @@ -96,10 +101,10 @@ struct vepu_dev { static struct mpp_hw_info vepu_v1_hw_info = { .reg_num = VEPU1_REG_NUM, - .regidx_id = VEPU1_REG_HW_ID_INDEX, - .regidx_start = VEPU1_REG_START_INDEX, - .regidx_end = VEPU1_REG_END_INDEX, - .regidx_en = VEPU1_REG_ENC_EN_INDEX, + .reg_id = VEPU1_REG_HW_ID_INDEX, + .reg_start = VEPU1_REG_START_INDEX, + .reg_end = VEPU1_REG_END_INDEX, + .reg_en = VEPU1_REG_ENC_EN_INDEX, }; /* @@ -134,72 +139,94 @@ static struct mpp_trans_info trans_rk_vepu1[] = { 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) + struct mpp_task_msgs *msgs) { 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; - } + if (ret) + return ret; - 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); + &task->off_inf, task->reg); + + return 0; +} + +static int vepu_extract_task_msg(struct vepu_task *task, + struct mpp_task_msgs *msgs) +{ + u32 i; + int ret; + struct mpp_request *req; + struct reg_offset_info *off_inf = &task->off_inf; + + for (i = 0; i < msgs->req_cnt; i++) { + u32 off_s, off_e; + + req = &msgs->reqs[i]; + if (!req->size) + continue; + + switch (req->cmd) { + case MPP_CMD_SET_REG_WRITE: { + off_s = task->hw_info->reg_start * sizeof(u32); + off_e = task->hw_info->reg_end * sizeof(u32); + ret = mpp_check_req(req, 0, sizeof(task->reg), + off_s, off_e); + if (ret) + continue; + if (copy_from_user((u8 *)task->reg + req->offset, + req->data, req->size)) { + mpp_err("copy_from_user reg failed\n"); + return -EIO; + } + memcpy(&task->w_reqs[task->w_req_cnt++], + req, sizeof(*req)); + } break; + case MPP_CMD_SET_REG_READ: { + off_s = task->hw_info->reg_start * sizeof(u32); + off_e = task->hw_info->reg_end * sizeof(u32); + ret = mpp_check_req(req, 0, sizeof(task->reg), + off_s, off_e); + if (ret) + continue; + memcpy(&task->r_reqs[task->r_req_cnt++], + req, sizeof(*req)); + } break; + case MPP_CMD_SET_REG_ADDR_OFFSET: { + int off = off_inf->cnt * sizeof(off_inf->elem[0]); + + ret = mpp_check_req(req, off, sizeof(off_inf->elem), + 0, sizeof(off_inf->elem)); + if (ret) + continue; + if (copy_from_user(&off_inf->elem[off_inf->cnt], + req->data, + req->size)) { + mpp_err("copy_from_user failed\n"); + return -EINVAL; + } + off_inf->cnt += req->size / sizeof(off_inf->elem[0]); + } break; + default: + break; + } + } + mpp_debug(DEBUG_TASK_INFO, "w_req_cnt %d, r_req_cnt %d\n", + task->w_req_cnt, task->r_req_cnt); 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; struct mpp_dev *mpp = session->mpp; - struct mpp_request *msg_reg = &msgs->reg_in; - u32 dwsize = msg_reg->size / sizeof(u32); mpp_debug_enter(); @@ -208,21 +235,14 @@ static void *vepu_alloc_task(struct mpp_session *session, 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); - 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"); + /* extract reqs for current task */ + ret = vepu_extract_task_msg(task, msgs); + if (ret) goto fail; - } - /* 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 (!(msgs->flags & MPP_FLAGS_REG_FD_NO_TRANS)) { + ret = vepu_process_reg_fd(session, task, msgs); if (ret) goto fail; } @@ -247,9 +267,7 @@ static int vepu_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) { u32 i; - u32 regidx_start; - u32 regidx_end; - u32 regidx_en; + u32 reg_en; struct vepu_task *task = NULL; struct vepu_dev *enc = NULL; @@ -258,27 +276,27 @@ static int vepu_run(struct mpp_dev *mpp, task = to_vepu_task(mpp_task); enc = to_vepu_dev(mpp); - /* FIXME: spin lock here */ - enc->current_task = task; /* clear cache */ mpp_write_relaxed(mpp, VEPU1_REG_CLR_CACHE_BASE, 1); /* set registers for hardware */ - regidx_start = task->hw_info->regidx_start; - regidx_end = task->hw_info->regidx_end; - regidx_en = task->hw_info->regidx_en; + reg_en = task->hw_info->reg_en; /* First, flush correct encoder format */ mpp_write_relaxed(mpp, VEPU1_REG_ENC_EN, - task->reg[regidx_en] & VEPU1_FORMAT_MASK); + task->reg[reg_en] & VEPU1_FORMAT_MASK); /* Second, flush others register */ - for (i = regidx_start; i <= regidx_end; i++) { - if (i == regidx_en) - continue; - mpp_write_relaxed(mpp, i * sizeof(u32), task->reg[i]); + for (i = 0; i < task->w_req_cnt; i++) { + struct mpp_request *req = &task->w_reqs[i]; + int s = req->offset / sizeof(u32); + int e = s + req->size / sizeof(u32); + + mpp_write_req(mpp, task->reg, s, e, reg_en); } + /* init current task */ + enc->current_task = task; /* Last, flush start registers */ wmb(); mpp_write(mpp, VEPU1_REG_ENC_EN, - task->reg[regidx_en] | VEPU1_ENC_START); + task->reg[reg_en] | VEPU1_ENC_START); mpp_debug_leave(); @@ -334,16 +352,20 @@ static int vepu_finish(struct mpp_dev *mpp, struct mpp_task *mpp_task) { u32 i; - u32 regidx_start; - u32 regidx_end; + u32 s, e; + struct mpp_request *req; struct vepu_task *task = to_vepu_task(mpp_task); mpp_debug_enter(); + /* read register after running */ - regidx_start = task->hw_info->regidx_start; - regidx_end = task->hw_info->regidx_end; - for (i = regidx_start; i <= regidx_end; i++) - task->reg[i] = mpp_read_relaxed(mpp, i * sizeof(u32)); + for (i = 0; i < task->r_req_cnt; i++) { + req = &task->r_reqs[i]; + s = req->offset / sizeof(u32); + e = s + req->size / sizeof(u32); + mpp_read_req(mpp, task->reg, s, e); + } + /* revert hack for irq status */ task->reg[VEPU1_REG_INT_INDEX] = task->irq_status; mpp_debug_leave(); @@ -355,16 +377,21 @@ static int vepu_result(struct mpp_dev *mpp, struct mpp_task *mpp_task, struct mpp_task_msgs *msgs) { - struct mpp_request *msg_reg_out = &msgs->reg_out; + u32 i; + struct mpp_request *req; struct vepu_task *task = to_vepu_task(mpp_task); /* FIXME may overflow the kernel */ - if (copy_to_user(msg_reg_out->data, - task->reg, msg_reg_out->size)) { - mpp_err("copy_to_user failed\n"); - return -EIO; - } + for (i = 0; i < task->r_req_cnt; i++) { + req = &task->r_reqs[i]; + if (copy_to_user(req->data, + (u8 *)task->reg + req->offset, + req->size)) { + mpp_err("copy_to_user reg fail\n"); + return -EIO; + } + } return 0; } @@ -445,7 +472,7 @@ static int vepu_init(struct mpp_dev *mpp) /* read hardware id*/ hw_info = mpp->var->hw_info; - hw_info->hw_id = mpp_read(mpp, hw_info->regidx_id); + hw_info->hw_id = mpp_read(mpp, hw_info->reg_id); return 0; } diff --git a/drivers/video/rockchip/mpp/mpp_vepu2.c b/drivers/video/rockchip/mpp/mpp_vepu2.c index 226e5046f9b1..b2874ef4f203 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu2.c +++ b/drivers/video/rockchip/mpp/mpp_vepu2.c @@ -79,9 +79,14 @@ struct vepu_task { struct mpp_hw_info *hw_info; unsigned long aclk_freq; u32 reg[VEPU2_REG_NUM]; - u32 idx; + struct reg_offset_info off_inf; u32 irq_status; + /* req for current task */ + u32 w_req_cnt; + struct mpp_request w_reqs[MPP_MAX_MSG_NUM]; + u32 r_req_cnt; + struct mpp_request r_reqs[MPP_MAX_MSG_NUM]; }; struct vepu_dev { @@ -102,9 +107,9 @@ struct vepu_dev { static struct mpp_hw_info vepu_v2_hw_info = { .reg_num = VEPU2_REG_NUM, - .regidx_start = VEPU2_REG_START_INDEX, - .regidx_end = VEPU2_REG_END_INDEX, - .regidx_en = VEPU2_REG_ENC_EN_INDEX, + .reg_start = VEPU2_REG_START_INDEX, + .reg_end = VEPU2_REG_END_INDEX, + .reg_en = VEPU2_REG_ENC_EN_INDEX, }; /* @@ -140,72 +145,94 @@ static struct mpp_trans_info trans_rk_vepu2[] = { 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) + struct mpp_task_msgs *msgs) { - int ret = 0; - struct mpp_request *msg_reg = &msgs->reg_in; + int ret; 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; - } + if (ret) + return ret; - 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); + &task->off_inf, task->reg); + + return 0; +} + +static int vepu_extract_task_msg(struct vepu_task *task, + struct mpp_task_msgs *msgs) +{ + u32 i; + int ret; + struct mpp_request *req; + struct reg_offset_info *off_inf = &task->off_inf; + + for (i = 0; i < msgs->req_cnt; i++) { + u32 off_s, off_e; + + req = &msgs->reqs[i]; + if (!req->size) + continue; + + switch (req->cmd) { + case MPP_CMD_SET_REG_WRITE: { + off_s = task->hw_info->reg_start * sizeof(u32); + off_e = task->hw_info->reg_end * sizeof(u32); + ret = mpp_check_req(req, 0, sizeof(task->reg), + off_s, off_e); + if (ret) + continue; + if (copy_from_user((u8 *)task->reg + req->offset, + req->data, req->size)) { + mpp_err("copy_from_user reg failed\n"); + return -EIO; + } + memcpy(&task->w_reqs[task->w_req_cnt++], + req, sizeof(*req)); + } break; + case MPP_CMD_SET_REG_READ: { + off_s = task->hw_info->reg_start * sizeof(u32); + off_e = task->hw_info->reg_end * sizeof(u32); + ret = mpp_check_req(req, 0, sizeof(task->reg), + off_s, off_e); + if (ret) + continue; + memcpy(&task->r_reqs[task->r_req_cnt++], + req, sizeof(*req)); + } break; + case MPP_CMD_SET_REG_ADDR_OFFSET: { + int off = off_inf->cnt * sizeof(off_inf->elem[0]); + + ret = mpp_check_req(req, off, sizeof(off_inf->elem), + 0, sizeof(off_inf->elem)); + if (ret) + continue; + if (copy_from_user(&off_inf->elem[off_inf->cnt], + req->data, + req->size)) { + mpp_err("copy_from_user failed\n"); + return -EINVAL; + } + off_inf->cnt += req->size / sizeof(off_inf->elem[0]); + } break; + default: + break; + } + } + mpp_debug(DEBUG_TASK_INFO, "w_req_cnt %d, r_req_cnt %d\n", + task->w_req_cnt, task->r_req_cnt); 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; struct mpp_dev *mpp = session->mpp; - struct mpp_request *msg_reg = &msgs->reg_in; - u32 dwsize = msg_reg->size / sizeof(u32); mpp_debug_enter(); @@ -215,19 +242,13 @@ 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) * 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"); + /* extract reqs for current task */ + ret = vepu_extract_task_msg(task, msgs); + if (ret) goto fail; - } /* 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 (!(msgs->flags & MPP_FLAGS_REG_FD_NO_TRANS)) { + ret = vepu_process_reg_fd(session, task, msgs); if (ret) goto fail; } @@ -252,9 +273,7 @@ static int vepu_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) { u32 i; - u32 regidx_start; - u32 regidx_end; - u32 regidx_en; + u32 reg_en; struct vepu_task *task = NULL; struct vepu_dev *enc = NULL; @@ -268,22 +287,24 @@ static int vepu_run(struct mpp_dev *mpp, /* clear cache */ mpp_write_relaxed(mpp, VEPU2_REG_CLR_CACHE_BASE, 1); - regidx_start = task->hw_info->regidx_start; - regidx_end = task->hw_info->regidx_end; - regidx_en = task->hw_info->regidx_en; + reg_en = task->hw_info->reg_en; /* First, flush correct encoder format */ mpp_write_relaxed(mpp, VEPU2_REG_ENC_EN, - task->reg[regidx_en] & VEPU2_FORMAT_MASK); + task->reg[reg_en] & VEPU2_FORMAT_MASK); /* Second, flush others register */ - for (i = regidx_start; i <= regidx_end; i++) { - if (i == regidx_en) - continue; - mpp_write_relaxed(mpp, i * sizeof(u32), task->reg[i]); + for (i = 0; i < task->w_req_cnt; i++) { + struct mpp_request *req = &task->w_reqs[i]; + int s = req->offset / sizeof(u32); + int e = s + req->size / sizeof(u32); + + mpp_write_req(mpp, task->reg, s, e, reg_en); } + /* init current task */ + enc->current_task = task; /* Last, flush the registers */ wmb(); mpp_write(mpp, VEPU2_REG_ENC_EN, - task->reg[regidx_en] | VEPU2_ENC_START); + task->reg[reg_en] | VEPU2_ENC_START); mpp_debug_leave(); @@ -340,16 +361,20 @@ static int vepu_finish(struct mpp_dev *mpp, struct mpp_task *mpp_task) { u32 i; - u32 regidx_start; - u32 regidx_end; + u32 s, e; + struct mpp_request *req; struct vepu_task *task = to_vepu_task(mpp_task); mpp_debug_enter(); + /* read register after running */ - regidx_start = task->hw_info->regidx_start; - regidx_end = task->hw_info->regidx_end; - for (i = regidx_start; i <= regidx_end; i++) - task->reg[i] = mpp_read_relaxed(mpp, i * sizeof(u32)); + for (i = 0; i < task->r_req_cnt; i++) { + req = &task->r_reqs[i]; + s = req->offset / sizeof(u32); + e = s + req->size / sizeof(u32); + mpp_read_req(mpp, task->reg, s, e); + } + /* revert hack for irq status */ task->reg[VEPU2_REG_INT_INDEX] = task->irq_status; mpp_debug_leave(); @@ -361,14 +386,20 @@ static int vepu_result(struct mpp_dev *mpp, struct mpp_task *mpp_task, struct mpp_task_msgs *msgs) { - struct mpp_request *msg_reg_out = &msgs->reg_out; + u32 i; + struct mpp_request *req; struct vepu_task *task = to_vepu_task(mpp_task); /* FIXME may overflow the kernel */ - if (copy_to_user(msg_reg_out->data, - task->reg, msg_reg_out->size)) { - mpp_err("copy_to_user failed\n"); - return -EIO; + for (i = 0; i < task->r_req_cnt; i++) { + req = &task->r_reqs[i]; + + if (copy_to_user(req->data, + (u8 *)task->reg + req->offset, + req->size)) { + mpp_err("copy_to_user reg fail\n"); + return -EIO; + } } return 0;