blob: b2db2084afd4dde0bbe6e25b15f2176101e92423 [file] [log] [blame]
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/list.h>
#include <linux/msm_mdp.h>
#include <media/videobuf2-core.h>
#include "enc-subdev.h"
#include "mdp-subdev.h"
#include "wfd-util.h"
struct mdp_buf_queue {
struct mdp_buf_info mdp_buf_info;
struct list_head node;
};
struct mdp_instance {
struct mdp_buf_queue mdp_bufs;
struct mutex mutex;
};
int mdp_init(struct v4l2_subdev *sd, u32 val)
{
return 0;
}
int mdp_open(struct v4l2_subdev *sd, void *arg)
{
struct mdp_instance *inst = kzalloc(sizeof(struct mdp_instance),
GFP_KERNEL);
void **cookie = (void **)arg;
int rc = 0;
if (!inst) {
WFD_MSG_ERR("Out of memory\n");
return -ENOMEM;
}
INIT_LIST_HEAD(&inst->mdp_bufs.node);
mutex_init(&inst->mutex);
*cookie = inst;
return rc;
}
int mdp_start(struct v4l2_subdev *sd, void *arg)
{
return 0;
}
int mdp_stop(struct v4l2_subdev *sd, void *arg)
{
return 0;
}
int mdp_close(struct v4l2_subdev *sd, void *arg)
{
return 0;
}
int mdp_q_buffer(struct v4l2_subdev *sd, void *arg)
{
static int foo;
int rc = 0;
struct mdp_buf_info *binfo = arg;
struct mdp_instance *inst = NULL;
if (!binfo || !binfo->inst || !binfo->cookie) {
WFD_MSG_ERR("Invalid argument\n");
return -EINVAL;
}
inst = binfo->inst;
if (binfo->kvaddr) {
struct mdp_buf_queue *new_entry = kzalloc(sizeof(*new_entry),
GFP_KERNEL);
memset((void *)binfo->kvaddr, foo++, 1024);
new_entry->mdp_buf_info = *binfo;
mutex_lock(&inst->mutex);
list_add_tail(&new_entry->node, &inst->mdp_bufs.node);
mutex_unlock(&inst->mutex);
WFD_MSG_DBG("Queue %p with cookie %p\n",
(void *)binfo->paddr, (void *)binfo->cookie);
} else {
rc = -EINVAL;
}
return rc;
}
int mdp_dq_buffer(struct v4l2_subdev *sd, void *arg)
{
struct mdp_buf_info *binfo = arg;
struct mdp_buf_queue *head = NULL;
struct mdp_instance *inst = NULL;
inst = binfo->inst;
while (head == NULL) {
mutex_lock(&inst->mutex);
if (!list_empty(&inst->mdp_bufs.node))
head = list_first_entry(&inst->mdp_bufs.node,
struct mdp_buf_queue, node);
mutex_unlock(&inst->mutex);
}
if (head == NULL)
return -ENOBUFS;
mutex_lock(&inst->mutex);
list_del(&head->node);
mutex_unlock(&inst->mutex);
*binfo = head->mdp_buf_info;
WFD_MSG_DBG("Dequeue %p with cookie %p\n",
(void *)binfo->paddr, (void *)binfo->cookie);
return 0;
}
int mdp_set_prop(struct v4l2_subdev *sd, void *arg)
{
return 0;
}
int mdp_mmap(struct v4l2_subdev *sd, void *arg)
{
int rc = 0;
struct mem_region_map *mmap = arg;
struct mem_region *mregion;
mregion = mmap->mregion;
mregion->paddr = mregion->kvaddr;
return rc;
}
int mdp_munmap(struct v4l2_subdev *sd, void *arg)
{
/* Whatever */
return 0;
}
long mdp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
int rc = 0;
if (!sd) {
WFD_MSG_ERR("Invalid arguments\n");
return -EINVAL;
}
switch (cmd) {
case MDP_Q_BUFFER:
rc = mdp_q_buffer(sd, arg);
break;
case MDP_DQ_BUFFER:
rc = mdp_dq_buffer(sd, arg);
break;
case MDP_OPEN:
rc = mdp_open(sd, arg);
break;
case MDP_START:
rc = mdp_start(sd, arg);
break;
case MDP_STOP:
rc = mdp_stop(sd, arg);
break;
case MDP_SET_PROP:
rc = mdp_set_prop(sd, arg);
break;
case MDP_CLOSE:
rc = mdp_close(sd, arg);
break;
case MDP_MMAP:
rc = mdp_mmap(sd, arg);
break;
case MDP_MUNMAP:
rc = mdp_munmap(sd, arg);
break;
default:
WFD_MSG_ERR("IOCTL: %u not supported\n", cmd);
rc = -EINVAL;
break;
}
return rc;
}