mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
video: rockchip: mpp: modify ioctl style
It is a new structure for compat_ioctl and unlock_ioctl.
The target is adpat to kinds of ioctl data.
Data structure as:
cmd_type | flag | size | offset | data
a) each fixed at 32bit.
b) size is the length of following data.
c) In kernel space, first parse this header, then read
the following data according to the cmd_type and data_size.
Change-Id: If3d08d54f42606ec71fbca402e5b330f7f37438d
Signed-off-by: Ding Wei <leo.ding@rock-chips.com>
This commit is contained in:
@@ -30,15 +30,29 @@
|
||||
#include "mpp_iommu.h"
|
||||
|
||||
#define MPP_TIMEOUT_DELAY (2000)
|
||||
|
||||
#define MPP_SESSION_MAX_DONE_TASK (20)
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct compat_mpp_request {
|
||||
compat_uptr_t req;
|
||||
u32 size;
|
||||
/* Use 'v' as magic number */
|
||||
#define MPP_IOC_MAGIC 'v'
|
||||
|
||||
#define MPP_IOC_CFG_V1 _IOW(MPP_IOC_MAGIC, 1, unsigned int)
|
||||
#define MPP_IOC_CFG_V2 _IOW(MPP_IOC_MAGIC, 2, unsigned int)
|
||||
|
||||
/* cmd support for version 1 */
|
||||
#define MPP_CMD_QUERY_SUPPORT_MASK_V1 (0x00000003)
|
||||
#define MPP_CMD_INIT_SUPPORT_MASK_V1 (0x00000007)
|
||||
#define MPP_CMD_SEND_SUPPORT_MASK_V1 (0x0000001F)
|
||||
#define MPP_CMD_POLL_SUPPORT_MASK_V1 (0x00000001)
|
||||
#define MPP_CMD_CONTROL_SUPPORT_MASK_V1 (0x00000007)
|
||||
|
||||
/* input parmater structure for version 1 */
|
||||
struct mpp_msg_v1 {
|
||||
__u32 cmd;
|
||||
__u32 flags;
|
||||
__u32 size;
|
||||
__u32 offset;
|
||||
__u64 data_ptr;
|
||||
};
|
||||
#endif
|
||||
|
||||
static void mpp_task_try_run(struct work_struct *work_s);
|
||||
|
||||
@@ -209,20 +223,39 @@ mpp_session_pull_done(struct mpp_session *session)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct mpp_task *
|
||||
mpp_alloc_task(struct mpp_dev *mpp,
|
||||
struct mpp_session *session,
|
||||
void __user *src, u32 size)
|
||||
static int mpp_process_task(struct mpp_session *session,
|
||||
struct mpp_request *req)
|
||||
{
|
||||
struct mpp_task *task = NULL;
|
||||
struct mpp_dev *mpp = session->mpp;
|
||||
|
||||
if (!mpp) {
|
||||
mpp_err("pid %d not find clinet %d\n",
|
||||
session->pid, session->device_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mpp->dev_ops->alloc_task)
|
||||
task = mpp->dev_ops->alloc_task(session, src, size);
|
||||
task = mpp->dev_ops->alloc_task(session, req->data, req->size);
|
||||
if (!task) {
|
||||
mpp_err("alloc_task failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (task && mpp->hw_ops->get_freq)
|
||||
if (mpp->hw_ops->get_freq)
|
||||
mpp->hw_ops->get_freq(mpp, task);
|
||||
|
||||
return task;
|
||||
/* push current task to queue */
|
||||
mpp_taskqueue_push_pending(mpp->queue, task);
|
||||
mpp_session_push_pending(session, task);
|
||||
atomic_inc(&session->task_running);
|
||||
atomic_inc(&mpp->total_running);
|
||||
/* trigger current queue to run task */
|
||||
mutex_lock(&mpp->queue->lock);
|
||||
queue_work(mpp->workq, &mpp->queue->work);
|
||||
mutex_unlock(&mpp->queue->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -442,7 +475,7 @@ 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_request *req)
|
||||
{
|
||||
int ret;
|
||||
struct mpp_task *task;
|
||||
@@ -453,7 +486,7 @@ 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.req, req.size);
|
||||
mpp_task_result(mpp, task, req->data, req->size);
|
||||
} else {
|
||||
mpp_err("error: pid %d wait %d task done timeout\n",
|
||||
session->pid, atomic_read(&session->task_running));
|
||||
@@ -502,6 +535,7 @@ static int mpp_attach_service(struct mpp_dev *mpp, struct device *dev)
|
||||
mpp->srv->sub_devices[mpp->var->device_type] = mpp;
|
||||
/* set taskqueue which set in dtsi */
|
||||
mpp->queue = mpp->srv->task_queues[node];
|
||||
mpp->srv->hw_support |= BIT(mpp->var->device_type);
|
||||
} else {
|
||||
dev_err(&pdev->dev, "failed attach service\n");
|
||||
return -EINVAL;
|
||||
@@ -529,236 +563,206 @@ int mpp_taskqueue_init(struct mpp_taskqueue *queue,
|
||||
return 0;
|
||||
}
|
||||
|
||||
long mpp_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
static int mpp_check_cmd_v1(__u32 cmd)
|
||||
{
|
||||
int ret;
|
||||
__u64 mask = 0;
|
||||
|
||||
if (cmd >= MPP_CMD_CONTROL_BASE)
|
||||
mask = MPP_CMD_CONTROL_SUPPORT_MASK_V1;
|
||||
else if (cmd >= MPP_CMD_POLL_BASE)
|
||||
mask = MPP_CMD_POLL_SUPPORT_MASK_V1;
|
||||
else if (cmd >= MPP_CMD_SEND_BASE)
|
||||
mask = MPP_CMD_SEND_SUPPORT_MASK_V1;
|
||||
else if (cmd >= MPP_CMD_INIT_BASE)
|
||||
mask = MPP_CMD_INIT_SUPPORT_MASK_V1;
|
||||
else
|
||||
mask = MPP_CMD_QUERY_SUPPORT_MASK_V1;
|
||||
|
||||
cmd &= 0x3F;
|
||||
ret = ((mask >> cmd) & 0x1) ? 0 : (-EINVAL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mpp_parse_msg_v1(struct mpp_msg_v1 *msg,
|
||||
struct mpp_request *req)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
req->cmd = msg->cmd;
|
||||
req->flags = msg->flags;
|
||||
req->size = msg->size;
|
||||
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",
|
||||
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);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int mpp_msg_is_last(struct mpp_request *req)
|
||||
{
|
||||
int flag;
|
||||
|
||||
if (req->flags & MPP_FLAGS_MULTI_MSG)
|
||||
flag = (req->flags & MPP_FLAGS_LAST_MSG) ? 1 : 0;
|
||||
else
|
||||
flag = 1;
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
static int mpp_process_request(struct mpp_session *session,
|
||||
struct mpp_service *srv,
|
||||
struct mpp_request *req,
|
||||
struct mpp_task_msgs *msgs)
|
||||
{
|
||||
struct mpp_dev *mpp;
|
||||
struct mpp_service *srv;
|
||||
struct mpp_session *session =
|
||||
(struct mpp_session *)filp->private_data;
|
||||
|
||||
mpp_debug_enter();
|
||||
if (!session)
|
||||
return -EINVAL;
|
||||
mpp_debug(DEBUG_IOCTL, "req->cmd %d\n", req->cmd);
|
||||
switch (req->cmd) {
|
||||
case MPP_CMD_QUERY_HW_SUPPORT: {
|
||||
u32 hw_support = srv->hw_support;
|
||||
|
||||
srv = session->srv;
|
||||
if (!srv)
|
||||
return -EINVAL;
|
||||
mpp_debug(DEBUG_IOCTL, "hw_support %08x\n", hw_support);
|
||||
if (put_user(hw_support, (u32 __user *)req->data))
|
||||
return -EFAULT;
|
||||
} break;
|
||||
case MPP_CMD_INIT_CLIENT_TYPE: {
|
||||
u32 client_type;
|
||||
|
||||
if (atomic_read(&srv->shutdown_request) > 0)
|
||||
return -EBUSY;
|
||||
if (get_user(client_type, (u32 __user *)req->data))
|
||||
return -EFAULT;
|
||||
|
||||
mpp_debug(DEBUG_IOCTL, "cmd=%x\n", cmd);
|
||||
switch (cmd) {
|
||||
case MPP_IOC_SET_CLIENT_TYPE:
|
||||
session->device_type = (enum MPP_DEVICE_TYPE)(arg);
|
||||
mpp_debug(DEBUG_IOCTL, "pid %d set client type %d\n",
|
||||
session->pid, session->device_type);
|
||||
|
||||
mpp = srv->sub_devices[session->device_type];
|
||||
if (IS_ERR_OR_NULL(mpp)) {
|
||||
mpp_err("pid %d set client type %d failed\n",
|
||||
session->pid, session->device_type);
|
||||
mpp_debug(DEBUG_IOCTL, "client %d\n", client_type);
|
||||
if (client_type >= MPP_DEVICE_BUTT) {
|
||||
mpp_err("client_type must less than %d\n",
|
||||
MPP_DEVICE_BUTT);
|
||||
return -EINVAL;
|
||||
}
|
||||
mpp = srv->sub_devices[client_type];
|
||||
if (!mpp)
|
||||
return -EINVAL;
|
||||
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;
|
||||
break;
|
||||
case MPP_IOC_SET_REG: {
|
||||
struct mpp_request req;
|
||||
struct mpp_task *task;
|
||||
|
||||
mpp = session->mpp;
|
||||
if (IS_ERR_OR_NULL(mpp)) {
|
||||
mpp_err("pid %d not find clinet %d\n",
|
||||
session->pid, session->device_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
mpp_debug(DEBUG_IOCTL, "pid %d set reg, client type %d\n",
|
||||
session->pid, session->device_type);
|
||||
if (copy_from_user(&req, (void __user *)arg,
|
||||
sizeof(req))) {
|
||||
mpp_err("error: set reg copy_from_user failed\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
task = mpp_alloc_task(mpp, session,
|
||||
(void __user *)req.req,
|
||||
req.size);
|
||||
if (IS_ERR_OR_NULL(task))
|
||||
return -EFAULT;
|
||||
mpp_taskqueue_push_pending(mpp->queue, task);
|
||||
mpp_session_push_pending(session, task);
|
||||
atomic_inc(&session->task_running);
|
||||
atomic_inc(&mpp->total_running);
|
||||
/* trigger current queue to run task */
|
||||
mutex_lock(&mpp->queue->lock);
|
||||
queue_work(mpp->workq, &mpp->queue->work);
|
||||
mutex_unlock(&mpp->queue->lock);
|
||||
} break;
|
||||
case MPP_IOC_GET_REG: {
|
||||
struct mpp_request req;
|
||||
|
||||
mpp = session->mpp;
|
||||
if (IS_ERR_OR_NULL(mpp)) {
|
||||
mpp_err("pid %d not find clinet %d\n",
|
||||
session->pid, session->device_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
mpp_debug(DEBUG_IOCTL, "pid %d get reg, client type %d\n",
|
||||
session->pid, session->device_type);
|
||||
if (copy_from_user(&req, (void __user *)arg,
|
||||
sizeof(req))) {
|
||||
mpp_err("get reg copy_from_user failed\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return mpp_wait_result(session, mpp, req);
|
||||
} break;
|
||||
case MPP_IOC_PROBE_IOMMU_STATUS: {
|
||||
int iommu_enable = 1;
|
||||
|
||||
mpp_debug(DEBUG_IOCTL, "MPP_IOC_PROBE_IOMMU_STATUS\n");
|
||||
|
||||
if (put_user(iommu_enable, ((u32 __user *)arg))) {
|
||||
mpp_err("iommu status copy_to_user fail\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MPP_IOC_SET_DRIVER_DATA: {
|
||||
case MPP_CMD_INIT_DRIVER_DATA: {
|
||||
u32 val;
|
||||
|
||||
mpp = session->mpp;
|
||||
if (IS_ERR_OR_NULL(mpp)) {
|
||||
mpp_err("pid %d not find clinet %d\n",
|
||||
session->pid, session->device_type);
|
||||
if (!mpp)
|
||||
return -EINVAL;
|
||||
}
|
||||
if (copy_from_user(&val, (void __user *)arg,
|
||||
sizeof(val))) {
|
||||
mpp_err("MPP_IOC_SET_DRIVER_DATA copy_from_user fail\n");
|
||||
if (get_user(val, (u32 __user *)req->data))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (mpp->grf_info->grf)
|
||||
regmap_write(mpp->grf_info->grf, 0x5d8, val);
|
||||
} break;
|
||||
case MPP_CMD_SET_REG: {
|
||||
mpp = session->mpp;
|
||||
if (!mpp)
|
||||
return -EINVAL;
|
||||
return mpp_process_task(session, req);
|
||||
} break;
|
||||
case MPP_CMD_GET_REG: {
|
||||
mpp = session->mpp;
|
||||
if (!mpp)
|
||||
return -EINVAL;
|
||||
return mpp_wait_result(session, mpp, req);
|
||||
} break;
|
||||
default: {
|
||||
mpp = session->mpp;
|
||||
if (IS_ERR_OR_NULL(mpp)) {
|
||||
if (!mpp) {
|
||||
mpp_err("pid %d not find clinet %d\n",
|
||||
session->pid, session->device_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mpp->dev_ops->ioctl)
|
||||
return mpp->dev_ops->ioctl(session, cmd, arg);
|
||||
return mpp->dev_ops->ioctl(session, req);
|
||||
|
||||
mpp_err("unknown mpp ioctl cmd %x\n", cmd);
|
||||
mpp_err("unknown mpp ioctl cmd %x\n", req->cmd);
|
||||
return -ENOIOCTLCMD;
|
||||
} break;
|
||||
}
|
||||
|
||||
mpp_debug_leave();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
#define MPP_IOC_SET_CLIENT_TYPE32 _IOW(MPP_IOC_MAGIC, 1, u32)
|
||||
#define MPP_IOC_GET_HW_FUSE_STATUS32 _IOW(MPP_IOC_MAGIC, 2, \
|
||||
compat_ulong_t)
|
||||
#define MPP_IOC_SET_REG32 _IOW(MPP_IOC_MAGIC, 3, \
|
||||
compat_ulong_t)
|
||||
#define MPP_IOC_GET_REG32 _IOW(MPP_IOC_MAGIC, 4, \
|
||||
compat_ulong_t)
|
||||
#define MPP_IOC_PROBE_IOMMU_STATUS32 _IOR(MPP_IOC_MAGIC, 5, u32)
|
||||
#define MPP_IOC_SET_DRIVER_DATA32 _IOW(MPP_IOC_MAGIC, 64, u32)
|
||||
|
||||
static long native_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
static long mpp_dev_ioctl(struct file *filp,
|
||||
unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
long ret = -ENOIOCTLCMD;
|
||||
int ret = 0;
|
||||
int msg_count = 0;
|
||||
struct mpp_service *srv;
|
||||
void __user *msg;
|
||||
struct mpp_request req;
|
||||
struct mpp_task_msgs task_msgs;
|
||||
struct mpp_session *session =
|
||||
(struct mpp_session *)filp->private_data;
|
||||
|
||||
if (file->f_op->unlocked_ioctl)
|
||||
ret = file->f_op->unlocked_ioctl(file, cmd, arg);
|
||||
mpp_debug_enter();
|
||||
|
||||
if (!session || !session->srv) {
|
||||
mpp_err("session %p\n", session);
|
||||
return -EINVAL;
|
||||
}
|
||||
srv = session->srv;
|
||||
if (atomic_read(&srv->shutdown_request) > 0) {
|
||||
mpp_debug(DEBUG_IOCTL, "shutdown had request\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
msg = (void __user *)arg;
|
||||
memset(&task_msgs, 0, sizeof(task_msgs));
|
||||
do {
|
||||
/* first, parse to fixed struct */
|
||||
memset(&req, 0, sizeof(req));
|
||||
switch (cmd) {
|
||||
case MPP_IOC_CFG_V1: {
|
||||
struct mpp_msg_v1 msg_v1;
|
||||
|
||||
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);
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
|
||||
msg += sizeof(msg_v1);
|
||||
} break;
|
||||
default:
|
||||
mpp_err("unknown ioctl cmd %x\n", cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
msg_count++;
|
||||
/* check loop times */
|
||||
if (msg_count > MPP_MAX_MSG_NUM) {
|
||||
mpp_err("fail, message count %d more than %d.\n",
|
||||
msg_count, MPP_MAX_MSG_NUM);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* second, process request */
|
||||
ret = mpp_process_request(session, srv, &req, &task_msgs);
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
} while (!mpp_msg_is_last(&req));
|
||||
|
||||
mpp_debug_leave();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
long mpp_dev_compat_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct mpp_request req;
|
||||
void __user *up = compat_ptr(arg);
|
||||
int compatible_arg = 1;
|
||||
long err = 0;
|
||||
|
||||
mpp_debug_enter();
|
||||
mpp_debug(DEBUG_IOCTL, "cmd %x, MPP_IOC_SET_CLIENT_TYPE32 %x\n",
|
||||
cmd, (u32)MPP_IOC_SET_CLIENT_TYPE32);
|
||||
/* First, convert the command. */
|
||||
switch (cmd) {
|
||||
case MPP_IOC_SET_CLIENT_TYPE32:
|
||||
cmd = MPP_IOC_SET_CLIENT_TYPE;
|
||||
break;
|
||||
case MPP_IOC_GET_HW_FUSE_STATUS32:
|
||||
cmd = MPP_IOC_GET_HW_FUSE_STATUS;
|
||||
break;
|
||||
case MPP_IOC_SET_REG32:
|
||||
cmd = MPP_IOC_SET_REG;
|
||||
break;
|
||||
case MPP_IOC_GET_REG32:
|
||||
cmd = MPP_IOC_GET_REG;
|
||||
break;
|
||||
case MPP_IOC_PROBE_IOMMU_STATUS32:
|
||||
cmd = MPP_IOC_PROBE_IOMMU_STATUS;
|
||||
break;
|
||||
case MPP_IOC_SET_DRIVER_DATA32:
|
||||
cmd = MPP_IOC_SET_DRIVER_DATA;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (cmd) {
|
||||
case MPP_IOC_SET_REG:
|
||||
case MPP_IOC_GET_REG:
|
||||
case MPP_IOC_GET_HW_FUSE_STATUS: {
|
||||
compat_uptr_t req_ptr;
|
||||
struct compat_mpp_request __user *req32 = NULL;
|
||||
|
||||
req32 = (struct compat_mpp_request __user *)up;
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
||||
if (get_user(req_ptr, &req32->req) ||
|
||||
get_user(req.size, &req32->size)) {
|
||||
mpp_err("compat get hw status copy_from_user failed\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
req.req = compat_ptr(req_ptr);
|
||||
compatible_arg = 0;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (compatible_arg) {
|
||||
err = native_ioctl(file, cmd, (unsigned long)up);
|
||||
} else {
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
err = native_ioctl(file, cmd, (unsigned long)&req);
|
||||
set_fs(old_fs);
|
||||
}
|
||||
|
||||
mpp_debug_leave();
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
int mpp_dev_open(struct inode *inode, struct file *filp)
|
||||
static int mpp_dev_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
int ret;
|
||||
struct mpp_session *session = NULL;
|
||||
@@ -797,7 +801,7 @@ failed_kfifo:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mpp_dev_release(struct inode *inode, struct file *filp)
|
||||
static int mpp_dev_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
int task_running;
|
||||
struct mpp_dev *mpp;
|
||||
@@ -840,7 +844,8 @@ int mpp_dev_release(struct inode *inode, struct file *filp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int mpp_dev_poll(struct file *filp, poll_table *wait)
|
||||
static unsigned int
|
||||
mpp_dev_poll(struct file *filp, poll_table *wait)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
struct mpp_session *session =
|
||||
@@ -853,6 +858,16 @@ unsigned int mpp_dev_poll(struct file *filp, poll_table *wait)
|
||||
return mask;
|
||||
}
|
||||
|
||||
const struct file_operations rockchip_mpp_fops = {
|
||||
.open = mpp_dev_open,
|
||||
.release = mpp_dev_release,
|
||||
.poll = mpp_dev_poll,
|
||||
.unlocked_ioctl = mpp_dev_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = mpp_dev_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct mpp_mem_region *
|
||||
mpp_task_attach_fd(struct mpp_task *task, int fd)
|
||||
{
|
||||
|
||||
@@ -27,19 +27,12 @@
|
||||
#define EXTRA_INFO_MAGIC (0x4C4A46)
|
||||
#define JPEG_IOC_EXTRA_SIZE (48)
|
||||
|
||||
/* Use 'l' as magic number */
|
||||
#define MPP_IOC_MAGIC 'l'
|
||||
|
||||
#define MPP_IOC_SET_CLIENT_TYPE _IOW(MPP_IOC_MAGIC, 1, __u32)
|
||||
#define MPP_IOC_GET_HW_FUSE_STATUS _IOW(MPP_IOC_MAGIC, 2, unsigned long)
|
||||
|
||||
#define MPP_IOC_SET_REG _IOW(MPP_IOC_MAGIC, 3, unsigned long)
|
||||
#define MPP_IOC_GET_REG _IOW(MPP_IOC_MAGIC, 4, unsigned long)
|
||||
|
||||
#define MPP_IOC_PROBE_IOMMU_STATUS _IOR(MPP_IOC_MAGIC, 5, __u32)
|
||||
#define MPP_IOC_SET_DRIVER_DATA _IOW(MPP_IOC_MAGIC, 64, u32)
|
||||
|
||||
#define MPP_IOC_CUSTOM_BASE (0x1000)
|
||||
#define MPP_MAX_MSG_NUM (16)
|
||||
#define MPP_MAX_REG_TRANS_NUM (60)
|
||||
/* define flags for mpp_request */
|
||||
#define MPP_FLAGS_MULTI_MSG (0x00000001)
|
||||
#define MPP_FLAGS_LAST_MSG (0x00000002)
|
||||
#define MPP_FLAGS_SECURE_MODE (0x00010000)
|
||||
|
||||
/**
|
||||
* Device type: classified by hardware feature
|
||||
@@ -76,9 +69,47 @@ enum MPP_DRIVER_TYPE {
|
||||
MPP_DRIVER_BUTT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Command type: keep the same as user space
|
||||
*/
|
||||
enum MPP_DEV_COMMAND_TYPE {
|
||||
MPP_CMD_QUERY_BASE = 0,
|
||||
MPP_CMD_QUERY_HW_SUPPORT = MPP_CMD_QUERY_BASE + 0,
|
||||
|
||||
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_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_POLL_BASE = 0x300,
|
||||
MPP_CMD_GET_REG = MPP_CMD_POLL_BASE + 0,
|
||||
|
||||
MPP_CMD_CONTROL_BASE = 0x400,
|
||||
|
||||
MPP_CMD_BUTT,
|
||||
};
|
||||
|
||||
/* data common struct for parse out */
|
||||
struct mpp_request {
|
||||
__u32 *req;
|
||||
__u32 cmd;
|
||||
__u32 flags;
|
||||
__u32 size;
|
||||
__u32 offset;
|
||||
void __user *data;
|
||||
};
|
||||
|
||||
/* struct use to collect task input and output 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;
|
||||
};
|
||||
|
||||
struct mpp_grf_info {
|
||||
@@ -228,6 +259,7 @@ struct mpp_service {
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs;
|
||||
#endif
|
||||
u32 hw_support;
|
||||
atomic_t shutdown_request;
|
||||
/* follows for device probe */
|
||||
struct mpp_grf_info grf_infos[MPP_DRIVER_BUTT];
|
||||
@@ -288,26 +320,14 @@ struct mpp_dev_ops {
|
||||
u32 __user *dst, u32 size);
|
||||
int (*free_task)(struct mpp_session *session,
|
||||
struct mpp_task *task);
|
||||
long (*ioctl)(struct mpp_session *isession,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
struct mpp_session *(*init_session)(struct mpp_dev *mpp);
|
||||
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 mpp_taskqueue_init(struct mpp_taskqueue *queue,
|
||||
struct mpp_service *srv);
|
||||
|
||||
/* It can handle the default ioctl */
|
||||
long mpp_dev_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
#ifdef CONFIG_COMPAT
|
||||
long mpp_dev_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
#endif
|
||||
int mpp_dev_open(struct inode *inode, struct file *filp);
|
||||
int mpp_dev_release(struct inode *inode, struct file *filp);
|
||||
unsigned int mpp_dev_poll(struct file *filp, poll_table *wait);
|
||||
|
||||
struct mpp_mem_region *
|
||||
mpp_task_attach_fd(struct mpp_task *task, int fd);
|
||||
int mpp_translate_reg_address(struct mpp_dev *data,
|
||||
@@ -381,6 +401,8 @@ static inline u32 mpp_read_relaxed(struct mpp_dev *mpp, u32 reg)
|
||||
return val;
|
||||
}
|
||||
|
||||
extern const struct file_operations rockchip_mpp_fops;
|
||||
|
||||
extern struct platform_driver rockchip_rkvdec_driver;
|
||||
extern struct platform_driver rockchip_rkvenc_driver;
|
||||
extern struct platform_driver rockchip_vdpu1_driver;
|
||||
|
||||
@@ -76,16 +76,6 @@ static int mpp_init_grf(struct device_node *np,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations mpp_dev_fops = {
|
||||
.unlocked_ioctl = mpp_dev_ioctl,
|
||||
.open = mpp_dev_open,
|
||||
.release = mpp_dev_release,
|
||||
.poll = mpp_dev_poll,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = mpp_dev_compat_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int mpp_register_service(struct mpp_service *srv,
|
||||
const char *service_name)
|
||||
{
|
||||
@@ -99,9 +89,9 @@ static int mpp_register_service(struct mpp_service *srv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
cdev_init(&srv->mpp_cdev, &mpp_dev_fops);
|
||||
cdev_init(&srv->mpp_cdev, &rockchip_mpp_fops);
|
||||
srv->mpp_cdev.owner = THIS_MODULE;
|
||||
srv->mpp_cdev.ops = &mpp_dev_fops;
|
||||
srv->mpp_cdev.ops = &rockchip_mpp_fops;
|
||||
|
||||
ret = cdev_add(&srv->mpp_cdev, srv->dev_id, 1);
|
||||
if (ret) {
|
||||
|
||||
@@ -710,8 +710,10 @@ static int vdpu_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mpp->var->device_type == MPP_DEVICE_VDPU1)
|
||||
if (mpp->var->device_type == MPP_DEVICE_VDPU1) {
|
||||
mpp->srv->sub_devices[MPP_DEVICE_VDPU1_PP] = mpp;
|
||||
mpp->srv->hw_support |= BIT(MPP_DEVICE_VDPU1_PP);
|
||||
}
|
||||
|
||||
mpp->session_max_buffers = VDPU1_SESSION_MAX_BUFFERS;
|
||||
vdpu_debugfs_init(mpp);
|
||||
|
||||
@@ -661,8 +661,10 @@ static int vdpu_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mpp->var->device_type == MPP_DEVICE_VDPU2)
|
||||
if (mpp->var->device_type == MPP_DEVICE_VDPU2) {
|
||||
mpp->srv->sub_devices[MPP_DEVICE_VDPU2_PP] = mpp;
|
||||
mpp->srv->hw_support |= BIT(MPP_DEVICE_VDPU2_PP);
|
||||
}
|
||||
|
||||
mpp->session_max_buffers = VDPU2_SESSION_MAX_BUFFERS;
|
||||
vdpu_debugfs_init(mpp);
|
||||
|
||||
Reference in New Issue
Block a user