+++ /dev/null
-/*
- * drivers/amlogic/media/video_processor/ionvideo/ion_priv.h
- *
- * Copyright (C) 2017 Amlogic, Inc. 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
- */
-
-#ifndef _ION_PRIV_H
-#define _ION_PRIV_H
-
-#include <ion.h>
-#include <linux/kref.h>
-#include <linux/mm_types.h>
-#include <linux/mutex.h>
-#include <linux/rbtree.h>
-#include <linux/sched.h>
-#include <linux/shrinker.h>
-#include <linux/types.h>
-
-struct ion_buffer *ion_handle_buffer(struct ion_handle *handle);
-
-/**
- * struct ion_buffer - metadata for a particular buffer
- * @ref: refernce count
- * @node: node in the ion_device buffers tree
- * @dev: back pointer to the ion_device
- * @heap: back pointer to the heap the buffer came from
- * @flags: buffer specific flags
- * @size: size of the buffer
- * @priv_virt: private data to the buffer representable as
- * a void *
- * @priv_phys: private data to the buffer representable as
- * an ion_phys_addr_t (and someday a phys_addr_t)
- * @lock: protects the buffers cnt fields
- * @kmap_cnt: number of times the buffer is mapped to the kernel
- * @vaddr: the kenrel mapping if kmap_cnt is not zero
- * @dmap_cnt: number of times the buffer is mapped for dma
- * @sg_table: the sg table for the buffer if dmap_cnt is not zero
- * @dirty: bitmask representing which pages of this buffer have
- * been dirtied by the cpu and need cache maintenance
- * before dma
- * @vmas: list of vma's mapping this buffer
- * @handle_count: count of handles referencing this buffer
- * @task_comm: taskcomm of last client to reference this buffer in a
- * handle, used for debugging
- * @pid: pid of last client to reference this buffer in a
- * handle, used for debugging
- */
-struct ion_buffer {
- struct kref ref;
- struct rb_node node;
- struct ion_device *dev;
- struct ion_heap *heap;
- unsigned long flags;
- size_t size;
- union {
- void *priv_virt;
- ion_phys_addr_t priv_phys;
- };
- struct mutex lock;
- int kmap_cnt;
- void *vaddr;
- int dmap_cnt;
- struct sg_table *sg_table;
- unsigned long *dirty;
- struct list_head vmas;
- /* used to track orphaned buffers */
- int handle_count;
- char task_comm[TASK_COMM_LEN];
- pid_t pid;
-};
-
-/**
- * struct ion_heap_ops - ops to operate on a given heap
- * @allocate: allocate memory
- * @free: free memory
- * @phys get physical address of a buffer (only define on
- * physically contiguous heaps)
- * @map_dma map the memory for dma to a scatterlist
- * @unmap_dma unmap the memory for dma
- * @map_kernel map memory to the kernel
- * @unmap_kernel unmap memory to the kernel
- * @map_user map memory to userspace
- */
-struct ion_heap_ops {
- int (*allocate)(struct ion_heap *heap,
- struct ion_buffer *buffer, unsigned long len,
- unsigned long align, unsigned long flags);
- void (*free)(struct ion_buffer *buffer);
- int (*phys)(struct ion_heap *heap, struct ion_buffer *buffer,
- ion_phys_addr_t *addr, size_t *len);
- struct sg_table * (*map_dma)(struct ion_heap *heap,
- struct ion_buffer *buffer);
- void (*unmap_dma)(struct ion_heap *heap, struct ion_buffer *buffer);
- void * (*map_kernel)(struct ion_heap *heap, struct ion_buffer *buffer);
- void (*unmap_kernel)(struct ion_heap *heap, struct ion_buffer *buffer);
- int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer,
- struct vm_area_struct *vma);
-};
-
-/**
- * struct ion_heap - represents a heap in the system
- * @node: rb node to put the heap on the device's tree of heaps
- * @dev: back pointer to the ion_device
- * @type: type of heap
- * @ops: ops struct as above
- * @id: id of heap, also indicates priority of this heap when
- * allocating. These are specified by platform data and
- * MUST be unique
- * @name: used for debugging
- * @debug_show: called when heap debug file is read to add any
- * heap specific debug info to output
- *
- * Represents a pool of memory from which buffers can be made. In some
- * systems the only heap is regular system memory allocated via vmalloc.
- * On others, some blocks might require large physically contiguous buffers
- * that are allocated from a specially reserved heap.
- */
-struct ion_heap {
- struct plist_node node;
- struct ion_device *dev;
- enum ion_heap_type type;
- struct ion_heap_ops *ops;
- unsigned int id;
- const char *name;
- int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *);
-};
-
-/**
- * ion_buffer_cached - this ion buffer is cached
- * @buffer: buffer
- *
- * indicates whether this ion buffer is cached
- */
-bool ion_buffer_cached(struct ion_buffer *buffer);
-
-/**
- * ion_buffer_fault_user_mappings - fault in user mappings of this buffer
- * @buffer: buffer
- *
- * indicates whether userspace mappings of this buffer will be faulted
- * in, this can affect how buffers are allocated from the heap.
- */
-bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer);
-
-/**
- * ion_device_create - allocates and returns an ion device
- * @custom_ioctl: arch specific ioctl function if applicable
- *
- * returns a valid device or -PTR_ERR
- */
-struct ion_device *ion_device_create(long (*custom_ioctl)
- (struct ion_client *client,
- unsigned int cmd,
- unsigned long arg));
-
-/**
- * ion_device_destroy - free and device and it's resource
- * @dev: the device
- */
-void ion_device_destroy(struct ion_device *dev);
-
-/**
- * ion_device_add_heap - adds a heap to the ion device
- * @dev: the device
- * @heap: the heap to add
- */
-void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap);
-
-/**
- * some helpers for common operations on buffers using the sg_table
- * and vaddr fields
- */
-void *ion_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer);
-void ion_heap_unmap_kernel(struct ion_heap *heap, struct ion_buffer *buffer);
-int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
- struct vm_area_struct *area);
-int ion_heap_buffer_zero(struct ion_buffer *buffer);
-
-
-/**
- * functions for creating and destroying the built in ion heaps.
- * architectures can add their own custom architecture specific
- * heaps as appropriate.
- */
-
-struct ion_heap *ion_heap_create(struct ion_platform_heap *platform_heap);
-void ion_heap_destroy(struct ion_heap *heap);
-
-struct ion_heap *
- ion_system_heap_create(struct ion_platform_heap *platform_heap);
-
-void ion_system_heap_destroy(struct ion_heap *heap);
-
-struct ion_heap *
- ion_system_contig_heap_create(struct ion_platform_heap *platform_heap);
-
-void ion_system_contig_heap_destroy(struct ion_heap *heap);
-
-struct ion_heap *
- ion_carveout_heap_create(struct ion_platform_heap *platform_heap);
-
-void ion_carveout_heap_destroy(struct ion_heap *heap);
-
-struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *platform_heap);
-void ion_chunk_heap_destroy(struct ion_heap *heap);
-/**
- * kernel api to allocate/free from carveout -- used when carveout is
- * used to back an architecture specific custom heap
- */
-ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, unsigned long size,
- unsigned long align);
-void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
- unsigned long size);
-/**
- * The carveout heap returns physical addresses, since 0 may be a valid
- * physical address, this is used to indicate allocation failed
- */
-#define ION_CARVEOUT_ALLOCATE_FAIL -1
-
-/**
- * functions for creating and destroying a heap pool -- allows you
- * to keep a pool of pre allocated memory to use from your heap. Keeping
- * a pool of memory that is ready for dma, ie any cached mapping have been
- * invalidated from the cache, provides a significant performance benefit on
- * many systems
- */
-
-/**
- * struct ion_page_pool - pagepool struct
- * @high_count: number of highmem items in the pool
- * @low_count: number of lowmem items in the pool
- * @high_items: list of highmem items
- * @low_items: list of lowmem items
- * @shrinker: a shrinker for the items
- * @mutex: lock protecting this struct and especially the count
- * item list
- * @alloc: function to be used to allocate pageory when the pool
- * is empty
- * @free: function to be used to free pageory back to the system
- * when the shrinker fires
- * @gfp_mask: gfp_mask to use from alloc
- * @order: order of pages in the pool
- * @list: plist node for list of pools
- *
- * Allows you to keep a pool of pre allocated pages to use from your heap.
- * Keeping a pool of pages that is ready for dma, ie any cached mapping have
- * been invalidated from the cache, provides a significant performance benefit
- * on many systems
- */
-struct ion_page_pool {
- int high_count;
- int low_count;
- struct list_head high_items;
- struct list_head low_items;
- struct mutex mutex;
- void * (*alloc)(struct ion_page_pool *pool);
- void (*free)(struct ion_page_pool *pool, struct page *page);
- gfp_t gfp_mask;
- unsigned int order;
- struct plist_node list;
-};
-
-struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order);
-void ion_page_pool_destroy(struct ion_page_pool *pool);
-void *ion_page_pool_alloc(struct ion_page_pool *pool);
-void ion_page_pool_free(struct ion_page_pool *pool, struct page *page);
-
-#endif /* _ION_PRIV_H */
#include <media/videobuf2-core.h>
#include <media/videobuf2-v4l2.h>
#include <linux/platform_device.h>
+#include <linux/amlogic/major.h>
#define IONVIDEO_MODULE_NAME "ionvideo"
#define IONVIDEO_VERSION "1.0"
#define RECEIVER_NAME "ionvideo"
+#define IONVIDEO_DEVICE_NAME "ionvideo"
#define V4L2_CID_USER_AMLOGIC_IONVIDEO_BASE (V4L2_CID_USER_BASE + 0x1100)
-
+#define SCALE_4K_TO_1080P 1
static struct mutex ppmgr2_ge2d_canvas_mutex;
static unsigned int video_nr_base = 13;
#endif
static int ionvideo_fillbuff(struct ionvideo_dev *dev,
- struct ionvideo_buffer *buf)
+ struct v4l2_buffer *buf)
{
struct vframe_s *vf;
-#ifdef IONVIDEO_DEBUG
- struct vb2_buffer *vb = &(buf->vb);
-#endif
int ret = 0;
/* ------------------------------------------------------- */
#if 0
}
if (dev->freerun_mode == 0) {
- if ((vf->type & 0x1) == VIDTYPE_INTERLACE) {
- if ((dev->ppmgr2_dev.bottom_first
- && (vf->type & 0x2)) || (dev
- ->ppmgr2_dev
- .bottom_first
- == 0
- && ((vf
- ->type
- & 0x2)
- == 0))) {
- buf->pts = vf->pts;
- buf->duration = vf->duration;
- }
- } else {
- buf->pts = vf->pts;
- buf->duration = vf->duration;
- }
-#ifdef IONVIDEO_DEBUG
- ret = ppmgr2_process(vf, &dev->ppmgr2_dev, vb->v4l2_buf.index);
-#endif
+ ret = ppmgr2_process(vf, &dev->ppmgr2_dev, buf->index);
if (ret) {
vf_put(vf, dev->vf_receiver_name);
return ret;
dev->ppmgr2_dev.dst_width = vf->width;
if (vf->height <= dev->height)
dev->ppmgr2_dev.dst_height = vf->height;
-
+#if SCALE_4K_TO_1080P
+ if (vf->width > dev->width || vf->height > dev->height) {
+ if (vf->width*dev->height >= dev->width*vf->height) {
+ dev->ppmgr2_dev.dst_width = dev->width;
+ dev->ppmgr2_dev.dst_height = vf->height
+ * dev->width / vf->width;
+ } else {
+ dev->ppmgr2_dev.dst_width = vf->width
+ * dev->height / vf->height;
+ dev->ppmgr2_dev.dst_height = dev->height;
+ }
+ }
+#endif
if ((dev->ppmgr2_dev.dst_width >= 1920) && (dev->ppmgr2_dev
.dst_height
>= 1080)
* scaling_rate
/ 100;
}
-#ifdef IONVIDEO_DEBUG
- ret = ppmgr2_process(vf, &dev->ppmgr2_dev, vb->v4l2_buf.index);
-#endif
+ ret = ppmgr2_process(vf, &dev->ppmgr2_dev, buf->index);
if (ret) {
vf_put(vf, dev->vf_receiver_name);
return ret;
}
videoc_omx_compute_pts(dev, vf);
+ buf->timecode.frames = 0;
+ if (vf->flag & VFRAME_FLAG_ERROR_RECOVERY)
+ buf->timecode.frames |= 1;
+ if (vf->flag & VFRAME_FLAG_SYNCFRAME)
+ buf->timecode.frames |= 2;
vf_put(vf, dev->vf_receiver_name);
-#ifdef IONVIDEO_DEBUG
- buf->vb.v4l2_buf.timestamp.tv_sec = dev->pts >> 32;
- buf->vb.v4l2_buf.timestamp.tv_usec = dev->pts & 0xFFFFFFFF;
- buf->vb.v4l2_buf.timecode.type = dev->ppmgr2_dev.dst_width;
- buf->vb.v4l2_buf.timecode.flags = dev->ppmgr2_dev.dst_height;
-#endif
+ buf->timestamp.tv_sec = dev->pts >> 32;
+ buf->timestamp.tv_usec = dev->pts & 0xFFFFFFFF;
+ buf->timecode.type = dev->ppmgr2_dev.dst_width;
+ buf->timecode.flags = dev->ppmgr2_dev.dst_height;
}
/* ------------------------------------------------------- */
return 0;
static void ionvideo_thread_tick(struct ionvideo_dev *dev)
{
struct ionvideo_dmaqueue *dma_q = &dev->vidq;
- struct ionvideo_buffer *buf;
- unsigned long flags = 0;
+ struct v4l2_buffer *buf;
struct vframe_s *vf;
int w, h;
if (!dev)
return;
+ if (dev->active_state == ION_INACTIVE_REQ) {
+ dev->active_state = ION_INACTIVE;
+ complete(&dev->inactive_done);
+ }
+
+ if (dev->active_state == ION_INACTIVE)
+ return;
+
vf = vf_peek(dev->vf_receiver_name);
if (!vf) {
dev->vf_wait_cnt++;
usleep_range(4000, 5000);
return;
}
- spin_lock_irqsave(&dev->slock, flags);
- if (list_empty(&dma_q->active)) {
+ mutex_lock(&dev->mutex_input);
+ if (v4l2q_empty(&dev->input_queue)) {
dprintk(dev, 3, "No active queue to serve\n");
- spin_unlock_irqrestore(&dev->slock, flags);
+ mutex_unlock(&dev->mutex_input);
schedule_timeout_interruptible(msecs_to_jiffies(20));
return;
}
- buf = list_entry(dma_q->active.next, struct ionvideo_buffer, list);
- spin_unlock_irqrestore(&dev->slock, flags);
+ buf = v4l2q_pop(&dev->input_queue);
+ mutex_unlock(&dev->mutex_input);
/* Fill buffer */
if (ionvideo_fillbuff(dev, buf))
return;
dev->vf_wait_cnt = 0;
- spin_lock_irqsave(&dev->slock, flags);
- list_del(&buf->list);
- spin_unlock_irqrestore(&dev->slock, flags);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ mutex_lock(&dev->mutex_output);
+ v4l2q_push(&dev->output_queue, buf);
dma_q->vb_ready++;
-#ifdef IONVIDEO_DEBUG
- dprintk(dev, 4, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
-#endif
+ mutex_unlock(&dev->mutex_output);
+ dprintk(dev, 4, "[%p/%d] done\n", buf, buf->index);
}
#define frames_to_ms(frames) \
return 0;
}
-static int ionvideo_start_generating(struct ionvideo_dev *dev)
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
{
+ struct ionvideo_dev *dev = video_drvdata(file);
struct ionvideo_dmaqueue *dma_q = &dev->vidq;
dev->is_omx_video_started = 1;
+ dma_q->vb_ready = 0;
dprintk(dev, 2, "%s\n", __func__);
return 0;
}
-static void ionvideo_stop_generating(struct ionvideo_dev *dev)
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
{
+ struct ionvideo_dev *dev = video_drvdata(file);
struct ionvideo_dmaqueue *dma_q = &dev->vidq;
dprintk(dev, 2, "%s\n", __func__);
* Typical driver might need to wait here until dma engine stops.
* In this case we can abort imiedetly, so it's just a noop.
*/
-
- /* Release all active buffers */
- while (!list_empty(&dma_q->active)) {
- struct ionvideo_buffer *buf;
-
- buf = list_entry(dma_q->active.next, struct ionvideo_buffer,
- list);
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-#ifdef IONVIDEO_DEBUG
- dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
-#endif
- }
-}
-/* ------------------------------------------------------------------
- * Videobuf operations
- * ------------------------------------------------------------------
- */
-#ifdef IONVIDEO_DEBUG
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
- unsigned int *nbuffers, unsigned int *nplanes,
- unsigned int sizes[], void *alloc_ctxs[])
-{
- struct ionvideo_dev *dev = vb2_get_drv_priv(vq);
- unsigned long size;
-
- if (fmt)
- size = fmt->fmt.pix.sizeimage;
- else
- size = (dev->width * dev->height * dev->pixelsize) >> 3;
-
- if (size == 0)
- return -EINVAL;
-
- if (*nbuffers == 0)
- *nbuffers = 32;
-
- while (size * *nbuffers > vid_limit * MAX_WIDTH * MAX_HEIGHT)
- (*nbuffers)--;
-
- *nplanes = 1;
-
- sizes[0] = size;
-
- /*
- * videobuf2-vmalloc allocator is context-less so no need to set
- * alloc_ctxs array.
- */
-
- dprintk(dev, 2, "%s, count=%d, size=%ld\n", __func__, *nbuffers, size);
-
- return 0;
-}
-#endif
-
-static int buffer_prepare(struct vb2_buffer *vb)
-{
- struct ionvideo_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct ionvideo_buffer *buf = container_of(vb, struct ionvideo_buffer,
- vb);
- unsigned long size;
-#ifdef IONVIDEO_DEBUG
- dprintk(dev, 2, "%s, field=%d\n", __func__, vb->v4l2_buf.field);
-#endif
- WARN_ON(dev->fmt == NULL);
-
- /*
- * Theses properties only change when queue is idle, see s_fmt.
- * The below checks should not be performed here, on each
- * buffer_prepare (i.e. on each qbuf). Most of the code in this function
- * should thus be moved to buffer_init and s_fmt.
- */
- if (dev->width < 48 || dev->width > MAX_WIDTH
- || dev->height < 32 || dev->height > MAX_HEIGHT)
- return -EINVAL;
-
- size = (dev->width * dev->height * dev->pixelsize) >> 3;
- if (vb2_plane_size(vb, 0) < size) {
- dprintk(dev, 1, "%s data will not fit into plane (%lu < %lu)\n",
- __func__, vb2_plane_size(vb, 0), size);
- return -EINVAL;
- }
-
- vb2_set_plane_payload(&buf->vb, 0, size);
-
- buf->fmt = dev->fmt;
-
return 0;
}
-static void buffer_queue(struct vb2_buffer *vb)
-{
- struct ionvideo_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct ionvideo_buffer *buf = container_of(vb, struct ionvideo_buffer,
- vb);
- struct ionvideo_dmaqueue *vidq = &dev->vidq;
- unsigned long flags = 0;
-
- dprintk(dev, 2, "%s\n", __func__);
-
- spin_lock_irqsave(&dev->slock, flags);
- list_add_tail(&buf->list, &vidq->active);
- spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-static int start_streaming(struct vb2_queue *vq, unsigned int count)
-{
- struct ionvideo_dev *dev = vb2_get_drv_priv(vq);
- struct ionvideo_dmaqueue *dma_q = &dev->vidq;
-
- dev->is_actived = 1;
- dma_q->vb_ready = 0;
- dprintk(dev, 2, "%s\n", __func__);
- return ionvideo_start_generating(dev);
-}
-
-/* abort streaming and wait for last buffer */
-static void stop_streaming(struct vb2_queue *vq)
-{
- struct ionvideo_dev *dev = vb2_get_drv_priv(vq);
-
- dev->is_actived = 0;
- dprintk(dev, 2, "%s\n", __func__);
- ionvideo_stop_generating(dev);
-}
-
-static void ionvideo_lock(struct vb2_queue *vq)
-{
- struct ionvideo_dev *dev = vb2_get_drv_priv(vq);
-
- mutex_lock(&dev->mutex);
-}
-
-static void ionvideo_unlock(struct vb2_queue *vq)
-{
- struct ionvideo_dev *dev = vb2_get_drv_priv(vq);
-
- mutex_unlock(&dev->mutex);
-}
-
-static const struct vb2_ops ionvideo_video_qops = {
-#ifdef IONVIDEO_DEBUG
- .queue_setup = queue_setup,
-#endif
- .buf_prepare = buffer_prepare,
- .buf_queue = buffer_queue,
- .start_streaming = start_streaming,
- .stop_streaming = stop_streaming,
- .wait_prepare = ionvideo_unlock,
- .wait_finish = ionvideo_lock,
-};
-
/* ------------------------------------------------------------------
* IOCTL vidioc handling
* ------------------------------------------------------------------
dprintk(dev, 2, "vidioc_open\n");
IONVID_INFO("ionvideo open\n");
init_waitqueue_head(&dev->wq);
- return v4l2_fh_open(file);
+ return 0;
}
-static int vidioc_release(struct file *file)
+static int vidioc_close(struct file *file)
{
struct ionvideo_dev *dev = video_drvdata(file);
- ionvideo_stop_generating(dev);
- IONVID_INFO("ionvideo_stop_generating!!!!\n");
+ IONVID_INFO("vidioc_close!!!!\n");
ppmgr2_release(&(dev->ppmgr2_dev));
- dprintk(dev, 2, "vidioc_release\n");
- IONVID_INFO("ionvideo release\n");
+ dprintk(dev, 2, "vidioc_close\n");
+ IONVID_INFO("vidioc_close\n");
if (dev->fd_num > 0)
dev->fd_num--;
dev->once_record = 0;
- return vb2_fop_release(file);
+ return 0;
}
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct ionvideo_dev *dev = video_drvdata(file);
- struct vb2_queue *q = &dev->vb_vidq;
- int ret = 0;
- unsigned long flags;
if (dev->freerun_mode == 0) {
if (dev->c_width == 0 || dev->c_height == 0)
f->fmt.pix.width = dev->c_width;
f->fmt.pix.height = dev->c_height;
- spin_lock_irqsave(&q->done_lock, flags);
- ret = list_empty(&q->done_list);
- spin_unlock_irqrestore(&q->done_lock, flags);
- if (!ret)
- return -EAGAIN;
} else {
f->fmt.pix.width = dev->width;
struct v4l2_format *f)
{
struct ionvideo_dev *dev = video_drvdata(file);
- struct vb2_queue *q = &dev->vb_vidq;
int ret = vidioc_try_fmt_vid_cap(file, priv, f);
if (ret < 0)
return ret;
- if (vb2_is_busy(q)) {
- dprintk(dev, 1, "%s device busy\n", __func__);
- return -EBUSY;
- }
dev->fmt = get_format(f);
dev->pixelsize = dev->fmt->depth;
dev->width = f->fmt.pix.width;
return 0;
}
-static int vidioc_enum_framesizes(struct file *file, void *fh,
- struct v4l2_frmsizeenum *fsize)
-{
- static const struct v4l2_frmsize_stepwise sizes = {
- 48, MAX_WIDTH, 4, 32, MAX_HEIGHT, 1};
- int i;
-
- if (fsize->index)
- return -EINVAL;
- for (i = 0; i < ARRAY_SIZE(formats); i++)
- if (formats[i].fourcc == fsize->pixel_format)
- break;
- if (i == ARRAY_SIZE(formats))
- return -EINVAL;
- fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
- fsize->stepwise = sizes;
- return 0;
-}
-
static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
{
struct ionvideo_dev *dev = video_drvdata(file);
struct ionvideo_dmaqueue *dma_q = &dev->vidq;
struct ppmgr2_device *ppmgr2_dev = &(dev->ppmgr2_dev);
- int ret = 0;
+ struct dma_buf *dbuf = NULL;
+ struct ion_buffer *buffer = NULL;
+ struct sg_table *table = NULL;
+ struct page *page = NULL;
+ void *phy_addr = NULL;
- p->length = 0;
- ret = vb2_ioctl_qbuf(file, priv, p);
- if (ret != 0)
- return ret;
+ dev->ionvideo_input[p->index] = *p;
+ mutex_lock(&dev->mutex_input);
+ v4l2q_push(&dev->input_queue, &(dev->ionvideo_input[p->index]));
+ mutex_unlock(&dev->mutex_input);
if (!ppmgr2_dev->phy_addr[p->index]) {
- struct vb2_buffer *vb;
- struct vb2_queue *q;
- void *phy_addr = NULL;
+ dbuf = dma_buf_get(p->m.fd);
+ buffer = dbuf->priv;
+ table = buffer->sg_table;
+ page = sg_page(table->sgl);
+ phy_addr = (void *)PFN_PHYS(page_to_pfn(page));
+ dma_buf_put(dbuf);
- q = dev->vdev.queue;
- vb = q->bufs[p->index];
- phy_addr = vb2_plane_cookie(vb, 0);
ppmgr2_dev->phy_addr[p->index] = phy_addr;
ppmgr2_dev->dst_buffer_width = ALIGN(dev->width, 32);
ppmgr2_dev->dst_buffer_height = dev->height;
}
}
wake_up_interruptible(&dma_q->wq);
- return ret;
+ return 0;
}
+/*
static int vidioc_synchronization_dqbuf(struct file *file, void *priv,
struct v4l2_buffer *p)
{
q = dev->vdev.queue;
if (dev->receiver_register) {
- /* clear the frame buffer queue */
while (!list_empty(&q->done_list)) {
ret = vb2_ioctl_dqbuf(file, priv, p);
if (ret)
return 0;
}
+*/
static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
{
struct ionvideo_dev *dev = video_drvdata(file);
struct ionvideo_dmaqueue *dma_q = &dev->vidq;
- int ret = 0;
+ struct v4l2_buffer *out_put = NULL;
+/*
if (dev->freerun_mode == 0)
return vidioc_synchronization_dqbuf(file, priv, p);
+*/
- ret = vb2_ioctl_dqbuf(file, priv, p);
- if (ret == 0)
- dma_q->vb_ready--;
- return ret;
-}
-
-#define NUM_INPUTS 10
-/* only one input in this sample driver */
-static int vidioc_enum_input(struct file *file, void *priv,
- struct v4l2_input *inp)
-{
- if (inp->index >= NUM_INPUTS)
- return -EINVAL;
-
- inp->type = V4L2_INPUT_TYPE_CAMERA;
- sprintf(inp->name, "Camera %u", inp->index);
- return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
- struct ionvideo_dev *dev = video_drvdata(file);
+ mutex_lock(&dev->mutex_output);
+ out_put = v4l2q_pop(&dev->output_queue);
- *i = dev->input;
+ if (out_put != NULL) {
+ dma_q->vb_ready--;
+ *p = *out_put;
+ } else {
+ mutex_unlock(&dev->mutex_output);
+ return -EAGAIN;
+ }
+ mutex_unlock(&dev->mutex_output);
return 0;
}
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
- struct ionvideo_dev *dev = video_drvdata(file);
-
- if (i >= NUM_INPUTS)
- return -EINVAL;
-
- if (i == dev->input)
- return 0;
-
- dev->input = i;
- return 0;
-}
+#define NUM_INPUTS 10
/* ------------------------------------------------------------------
* File operations for the device
* ------------------------------------------------------------------
*/
-static const struct v4l2_file_operations ionvideo_fops = {
+static const struct v4l2_file_operations ionvideo_v4l2_fops = {
.owner = THIS_MODULE,
.open = vidioc_open,
- .release = vidioc_release,
+ .release = vidioc_close,
.read = vb2_fop_read,
.poll = vb2_fop_poll,
.unlocked_ioctl = video_ioctl2,/* V4L2 ioctl handler */
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
- .vidioc_enum_framesizes = vidioc_enum_framesizes,
- .vidioc_reqbufs = vb2_ioctl_reqbufs,
- .vidioc_create_bufs = vb2_ioctl_create_bufs,
- .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
- .vidioc_querybuf = vb2_ioctl_querybuf,
.vidioc_qbuf = vidioc_qbuf,
.vidioc_dqbuf = vidioc_dqbuf,
- .vidioc_enum_input = vidioc_enum_input,
- .vidioc_g_input = vidioc_g_input,
- .vidioc_s_input = vidioc_s_input,
- .vidioc_streamon = vb2_ioctl_streamon,
- .vidioc_streamoff = vb2_ioctl_streamoff,
- .vidioc_log_status = v4l2_ctrl_log_status,
- .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
.vidioc_s_ctrl = vidioc_s_ctrl,
};
static const struct video_device ionvideo_template = {
.name = "ionvideo",
- .fops = &ionvideo_fops,
+ .fops = &ionvideo_v4l2_fops,
.ioctl_ops = &ionvideo_ioctl_ops,
- .release = video_device_release_empty,
+ .release = video_device_release,
};
/* -----------------------------------------------------------------
* -----------------------------------------------------------------
*/
/* struct vb2_dc_conf * ionvideo_dma_ctx = NULL; */
-static int ionvideo_release(void)
+static int ionvideo_v4l2_release(void)
{
struct ionvideo_dev *dev;
struct list_head *list;
static int video_receiver_event_fun(int type, void *data, void *private_data)
{
-#ifdef CONFIG_AM_VOUT
- char *configured[2];
- char framerate[20] = {0};
-#endif
struct ionvideo_dev *dev = (struct ionvideo_dev *)private_data;
if (type == VFRAME_EVENT_PROVIDER_UNREG) {
dev->receiver_register = 0;
dev->is_omx_video_started = 0;
+ if (dev->active_state == ION_ACTIVE) {
+ /*if player killed thread may have exit.*/
+ dev->active_state = ION_INACTIVE_REQ;
+ wait_for_completion_timeout(&dev->inactive_done,
+ msecs_to_jiffies(100));
+ }
+
/*tsync_avevent(VIDEO_STOP, 0);*/
IONVID_INFO("unreg:ionvideo\n");
} else if (type == VFRAME_EVENT_PROVIDER_REG) {
dev->receiver_register = 1;
dev->is_omx_video_started = 1;
dev->ppmgr2_dev.interlaced_num = 0;
+ dev->active_state = ION_ACTIVE;
+ init_completion(&dev->inactive_done);
+
+ v4l2q_init(&dev->input_queue, IONVIDEO_POOL_SIZE + 1,
+ &dev->ionvideo_input_queue[0]);
+ v4l2q_init(&dev->output_queue, IONVIDEO_POOL_SIZE + 1,
+ &dev->ionvideo_output_queue[0]);
IONVID_INFO("reg:ionvideo\n");
} else if (type == VFRAME_EVENT_PROVIDER_QUREY_STATE) {
if (dev->vf_wait_cnt > 1)
return RECEIVER_INACTIVE;
return RECEIVER_ACTIVE;
} else if (type == VFRAME_EVENT_PROVIDER_FR_HINT) {
- if ((data != NULL) && (ionvideo_seek_flag == 0)) {
#ifdef CONFIG_AM_VOUT
- /*set_vframe_rate_hint((unsigned long)(data));*/
- sprintf(framerate, "FRAME_RATE_HINT=%lu",
- (unsigned long)data);
- configured[0] = framerate;
- configured[1] = NULL;
- kobject_uevent_env(&(dev->vdev.dev.kobj),
- KOBJ_CHANGE, configured);
- pr_info("%s: sent uevent %s\n",
- __func__, configured[0]);
+ if ((data != NULL) && (ionvideo_seek_flag == 0))
+ set_vframe_rate_hint((unsigned long)(data));
#endif
- }
} else if (type == VFRAME_EVENT_PROVIDER_FR_END_HINT) {
#ifdef CONFIG_AM_VOUT
if (ionvideo_seek_flag == 0) {
- configured[0] = "FRAME_RATE_END_HINT";
- configured[1] = NULL;
- kobject_uevent_env(&(dev->vdev.dev.kobj),
- KOBJ_CHANGE, configured);
- pr_info("%s: sent uevent %s\n",
- __func__, configured[0]);
+ set_vframe_rate_end_hint();
}
#endif
}
{
struct ionvideo_dev *dev;
struct video_device *vfd;
- struct vb2_queue *q;
int ret;
unsigned long flags;
/* initialize locks */
spin_lock_init(&dev->slock);
- /* initialize queue */
- q = &dev->vb_vidq;
- q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
- q->drv_priv = dev;
- q->buf_struct_size = sizeof(struct ionvideo_buffer);
- q->ops = &ionvideo_video_qops;
- q->mem_ops = &vb2_ion_memops;
-#ifdef IONVIDEO_DEBUG
- q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-#else
- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-#endif
-
-#ifdef IONVIDEO_DEBUG
- ret = vb2_queue_init(q);
- if (ret)
- goto unreg_dev;
-#endif
-
mutex_init(&dev->mutex);
/* init video dma queues */
*vfd = ionvideo_template;
vfd->dev_debug = debug;
vfd->v4l2_dev = &dev->v4l2_dev;
- vfd->queue = q;
-#ifdef IONVIDEO_DEBUG
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
-#endif
/*
* Provide a mutex to v4l2 core. It will be used to protect
* all fops and v4l2 ioctls.
*/
- vfd->lock = &dev->mutex;
- video_set_drvdata(vfd, dev);
ret = video_register_device(vfd, VFL_TYPE_GRABBER,
inst + video_nr_base);
if (ret < 0)
goto unreg_dev;
+ video_set_drvdata(vfd, dev);
+
dev->inst = inst;
snprintf(dev->vf_receiver_name, ION_VF_RECEIVER_NAME_SIZE,
(inst == 0) ? RECEIVER_NAME : RECEIVER_NAME ".%x",
list_add_tail(&dev->ionvideo_devlist, &ionvideo_devlist);
ionvideo_devlist_unlock(flags);
+ mutex_init(&dev->mutex_input);
+ mutex_init(&dev->mutex_output);
+
return 0;
unreg_dev:
list_for_each(p, &ionvideo_devlist) {
dev = list_entry(p, struct ionvideo_dev, ionvideo_devlist);
- if ((dev->inst == *inst) && (!dev->mapped)) {
- dev->mapped = true;
- *inst = dev->inst;
+ if (dev->inst == *inst) {
*receiver_name = dev->vf_receiver_name;
ionvideo_devlist_unlock(flags);
return 0;
return -ENODEV;
}
+EXPORT_SYMBOL(ionvideo_assign_map);
-int ionvideo_alloc_map(char **receiver_name, int *inst)
+int ionvideo_alloc_map(int *inst)
{
unsigned long flags;
struct ionvideo_dev *dev = NULL;
if ((dev->inst >= 0) && (!dev->mapped)) {
dev->mapped = true;
*inst = dev->inst;
- *receiver_name = dev->vf_receiver_name;
ionvideo_devlist_unlock(flags);
return 0;
}
static struct class ionvideo_class = {.name = "ionvideo", .class_attrs =
ion_video_class_attrs, };
+static int ionvideo_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int ionvideo_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static long ionvideo_ioctl(struct file *file,
+ unsigned int cmd,
+ ulong arg)
+{
+ long ret = 0;
+ void __user *argp = (void __user *)arg;
+
+ switch (cmd) {
+ case IONVIDEO_IOCTL_ALLOC_ID:{
+ u32 ionvideo_id = 0;
+
+ ret = ionvideo_alloc_map(&ionvideo_id);
+ if (ret != 0)
+ break;
+ put_user(ionvideo_id, (u32 __user *)argp);
+ }
+ break;
+ case IONVIDEO_IOCTL_FREE_ID:{
+ u32 ionvideo_id;
+
+ get_user(ionvideo_id, (u32 __user *)argp);
+ ionvideo_release_map(ionvideo_id);
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+#ifdef CONFIG_COMPAT
+static long ionvideo_compat_ioctl(struct file *file,
+ unsigned int cmd,
+ ulong arg)
+{
+ long ret = 0;
+
+ ret = ionvideo_ioctl(file, cmd, (ulong)compat_ptr(arg));
+ return ret;
+}
+#endif
+static const struct file_operations ionvideo_fops = {
+ .owner = THIS_MODULE,
+ .open = ionvideo_open,
+ .release = ionvideo_release,
+ .unlocked_ioctl = ionvideo_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = ionvideo_compat_ioctl,
+#endif
+ .poll = NULL,
+};
/* This routine allocates from 1 to n_devs virtual drivers.
* The real maximum number of virtual drivers will depend on how many drivers
* will succeed. This is limited to the maximum number of devices that
{
int ret = 0, i;
- ret = class_register(&ionvideo_class);
- if (ret < 0)
- return ret;
if (n_devs <= 0)
n_devs = 1;
static int ionvideo_drv_remove(struct platform_device *pdev)
{
- ionvideo_release();
- class_unregister(&ionvideo_class);
+ ionvideo_v4l2_release();
return 0;
}
static int __init ionvideo_init(void)
{
+ int ret = -1;
+ struct device *devp;
+
+ ret = class_register(&ionvideo_class);
+ if (ret < 0)
+ return ret;
+
+ ret = register_chrdev(IONVIDEO_MAJOR, "ionvideo", &ionvideo_fops);
+ if (ret < 0) {
+ pr_err("Can't allocate major for ionvideo device\n");
+ goto error1;
+ }
+
+ devp = device_create(&ionvideo_class,
+ NULL,
+ MKDEV(IONVIDEO_MAJOR, 0),
+ NULL,
+ IONVIDEO_DEVICE_NAME);
+ if (IS_ERR(devp)) {
+ pr_err("failed to create ionvideo device node\n");
+ ret = PTR_ERR(devp);
+ return ret;
+ }
+
if (platform_driver_register(&ionvideo_drv)) {
pr_err("Failed to register ionvideo driver\n");
return -ENODEV;
}
-
return 0;
+
+error1:
+ unregister_chrdev(IONVIDEO_MAJOR, "ionvideo");
+ class_unregister(&ionvideo_class);
+ return ret;
+
}
static void __exit ionvideo_exit(void)
{
platform_driver_unregister(&ionvideo_drv);
+ device_destroy(&ionvideo_class, MKDEV(IONVIDEO_MAJOR, 0));
+ unregister_chrdev(IONVIDEO_MAJOR, IONVIDEO_DEVICE_NAME);
+ class_unregister(&ionvideo_class);
}
MODULE_DESCRIPTION("Video Technology Magazine Ion Video Capture Board");
+++ /dev/null
-/*
- * drivers/amlogic/media/video_processor/ionvideo/videobuf2-ion.c
- *
- * Copyright (C) 2017 Amlogic, Inc. 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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/io.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-#include <media/videobuf2-core.h>
-#include <media/videobuf2-memops.h>
-
-/*#include <asm/mach/map.h>*/
-#include <ion.h>
-#include "ion_priv.h"
-#include "videobuf2-ion.h"
-
-struct vb2_ion_buf {
- void *vaddr;
- struct page **pages;
- struct vm_area_struct *vma;
- int write;
- unsigned long size;
- unsigned int n_pages;
- atomic_t refcount;
- struct vb2_vmarea_handler handler;
- struct dma_buf *dbuf;
-};
-
-static void vb2_ion_put(void *buf_priv);
-
-#ifdef IONVIDEO_DEBUG
-static void *vb2_ion_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
-{
- struct vb2_ion_buf *buf;
-
- buf = kzalloc(sizeof(*buf), GFP_KERNEL | gfp_flags);
- if (!buf)
- return NULL;
-
- buf->size = size;
- buf->vaddr = vmalloc_user(buf->size);
- buf->handler.refcount = &buf->refcount;
- buf->handler.put = vb2_ion_put;
- buf->handler.arg = buf;
-
- if (!buf->vaddr) {
- pr_debug("ion of size %ld failed\n", buf->size);
- kfree(buf);
- return NULL;
- }
-
- atomic_inc(&buf->refcount);
- return buf;
-}
-#endif
-
-static void vb2_ion_put(void *buf_priv)
-{
- struct vb2_ion_buf *buf = buf_priv;
-
- if (atomic_dec_and_test(&buf->refcount)) {
- vfree(buf->vaddr);
- kfree(buf);
- }
-}
-
-#ifdef IONVIDEO_DEBUG
-static void *vb2_ion_get_userptr(void *alloc_ctx, unsigned long vaddr,
- unsigned long size, int write)
-{
- struct vb2_ion_buf *buf;
- unsigned long first, last;
- int n_pages, offset;
- struct vm_area_struct *vma;
- dma_addr_t physp;
-
- buf = kzalloc(sizeof(*buf), GFP_KERNEL);
- if (!buf)
- return NULL;
-
- buf->write = write;
- offset = vaddr & ~PAGE_MASK;
- buf->size = size;
-
- vma = find_vma(current->mm, vaddr);
- if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) {
-#ifdef IONVIDEO_DEBUG
- if (vb2_get_contig_userptr(vaddr, size, &vma, &physp))
- goto fail_pages_array_alloc;
-#endif
- buf->vma = vma;
- buf->vaddr = ioremap_nocache(physp, size);
- if (!buf->vaddr)
- goto fail_pages_array_alloc;
- } else {
- first = vaddr >> PAGE_SHIFT;
- last = (vaddr + size - 1) >> PAGE_SHIFT;
- buf->n_pages = last - first + 1;
- buf->pages = kcalloc(buf->n_pages, sizeof(struct page *),
- GFP_KERNEL);
- if (!buf->pages)
- goto fail_pages_array_alloc;
-
- /* current->mm->mmap_sem is taken by videobuf2 core */
-#ifdef IONVIDEO_DEBUG
- n_pages = get_user_pages(current, current->mm,
- vaddr & PAGE_MASK, buf->n_pages,
- write, 1, /* force */
- buf->pages, NULL);
-#endif
- if (n_pages != buf->n_pages)
- goto fail_get_user_pages;
-
- buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1,
- PAGE_KERNEL);
- if (!buf->vaddr)
- goto fail_get_user_pages;
- }
-
- buf->vaddr += offset;
- return buf;
-
-fail_get_user_pages:
- pr_debug("get_user_pages requested/got: %d/%d]\n", n_pages,
- buf->n_pages);
- while (--n_pages >= 0)
- put_page(buf->pages[n_pages]);
- kfree(buf->pages);
-
-fail_pages_array_alloc: kfree(buf);
-
- return NULL;
-}
-#endif
-
-static void vb2_ion_put_userptr(void *buf_priv)
-{
- struct vb2_ion_buf *buf = buf_priv;
- unsigned long vaddr = (unsigned long)buf->vaddr & PAGE_MASK;
- unsigned int i;
-
- if (buf->pages) {
- if (vaddr)
- vm_unmap_ram((void *)vaddr, buf->n_pages);
- for (i = 0; i < buf->n_pages; ++i) {
- if (buf->write)
- set_page_dirty_lock(buf->pages[i]);
- put_page(buf->pages[i]);
- }
- kfree(buf->pages);
- } else {
-#ifdef IONVIDEO_DEBUG
- if (buf->vma)
- vb2_put_vma(buf->vma);
-#endif
- iounmap(buf->vaddr);
- }
- kfree(buf);
-}
-
-static void *vb2_ion_vaddr(void *buf_priv)
-{
- struct vb2_ion_buf *buf = buf_priv;
-
- if (!buf->vaddr) {
- pr_err("Address of an unallocated plane requested");
- pr_err("or cannot map user pointer\n");
- return NULL;
- }
-
- return buf->vaddr;
-}
-
-static unsigned int vb2_ion_num_users(void *buf_priv)
-{
- struct vb2_ion_buf *buf = buf_priv;
-
- return atomic_read(&buf->refcount);
-}
-
-static int vb2_ion_mmap(void *buf_priv, struct vm_area_struct *vma)
-{
- struct vb2_ion_buf *buf = buf_priv;
- int ret;
-
- pr_info("11vb2_ion_mmap\n");
- if (!buf) {
- pr_err("No memory to map\n");
- return -EINVAL;
- }
-
- ret = remap_vmalloc_range(vma, buf->vaddr, 0);
- if (ret) {
- pr_err("Remapping ion memory, error: %d\n", ret);
- return ret;
- }
-
- /*
- * Make sure that vm_areas for 2 buffers won't be merged together
- */
- vma->vm_flags |= VM_DONTEXPAND;
-
- /*
- * Use common vm_area operations to track buffer refcount.
- */
- vma->vm_private_data = &buf->handler;
- vma->vm_ops = &vb2_common_vm_ops;
-
- vma->vm_ops->open(vma);
- pr_info("22vb2_ion_mmap\n");
- return 0;
-}
-
-/*********************************************/
-/* callbacks for DMABUF buffers */
-/*********************************************/
-
-static int vb2_ion_map_dmabuf(void *mem_priv)
-{
- /* struct vb2_ion_buf *buf = mem_priv; */
- /* */
- /* struct ion_buffer *buffer = buf->dbuf->priv; */
- /* int mtype = MT_MEMORY_NONCACHED; */
- /* */
- /* if (buffer->flags & ION_FLAG_CACHED) */
- /* mtype = MT_MEMORY; */
-#if 0
- buf->vaddr = __arm_ioremap(buffer->priv_phys, buffer->size, mtype);
-
- return buf->vaddr ? 0 : -EFAULT;
-#else
- return 0;
-#endif
-}
-
-static void vb2_ion_unmap_dmabuf(void *mem_priv)
-{
- /* struct vb2_ion_buf *buf = mem_priv; */
-
-#if 0
- __arm_iounmap(buf->vaddr);
-
- buf->vaddr = NULL;
-#endif
-}
-
-static void vb2_ion_detach_dmabuf(void *mem_priv)
-{
- struct vb2_ion_buf *buf = mem_priv;
-
- if (buf->vaddr)
- dma_buf_vunmap(buf->dbuf, buf->vaddr);
-
- kfree(buf);
-}
-
-#ifdef IONVIDEO_DEBUG
-static void *vb2_ion_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
- unsigned long size, int write)
-{
- struct vb2_ion_buf *buf;
-
- if (dbuf->size < size)
- return ERR_PTR(-EFAULT);
-
- buf = kzalloc(sizeof(*buf), GFP_KERNEL);
- if (!buf)
- return ERR_PTR(-ENOMEM);
-
- buf->dbuf = dbuf;
- buf->write = write;
- buf->size = size;
-
- return buf;
-}
-#endif
-
-static void *vb2_ion_cookie(void *buf_priv)
-{
- struct vb2_ion_buf *buf = buf_priv;
-
- struct ion_buffer *buffer = buf->dbuf->priv;
-#if 0
- return (void *)buffer->priv_phys;
-#endif
- struct sg_table *table = buffer->priv_virt;
- struct page *page = sg_page(table->sgl);
-
- ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page));
-
- return (void *)paddr;
-}
-
-const struct vb2_mem_ops vb2_ion_memops = {
-#ifdef IONVIDEO_DEBUG
- .alloc = vb2_ion_alloc,
-#endif
- .put = vb2_ion_put,
-#ifdef IONVIDEO_DEBUG
- .get_userptr = vb2_ion_get_userptr,
-#endif
- .put_userptr = vb2_ion_put_userptr,
- .map_dmabuf = vb2_ion_map_dmabuf,
- .unmap_dmabuf = vb2_ion_unmap_dmabuf,
-#ifdef IONVIDEO_DEBUG
- .attach_dmabuf = vb2_ion_attach_dmabuf,
-#endif
- .detach_dmabuf = vb2_ion_detach_dmabuf,
- .vaddr = vb2_ion_vaddr,
- .mmap = vb2_ion_mmap,
- .num_users = vb2_ion_num_users,
- .cookie = vb2_ion_cookie,
-};
-EXPORT_SYMBOL_GPL(vb2_ion_memops);
-
-MODULE_DESCRIPTION("ion memory handling routines for videobuf2");
-MODULE_AUTHOR("Shuai Cao <shuai.cao@amlogic.com>");
-MODULE_LICENSE("GPL");