| /* 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; |
| } |