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