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 <leo.ding@rock-chips.com>
This commit is contained in:
Ding Wei
2020-01-09 20:36:26 +08:00
committed by Tao Huang
parent e4f54461e6
commit 3f291e5ffb
7 changed files with 723 additions and 563 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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