mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user