2010-04-23 12:38:38 +04:00
/*
* A virtual v4l2 - mem2mem example device .
*
* This is a virtual device driver for testing mem - to - mem videobuf framework .
* It simulates a device that uses memory buffers for both source and
* destination , processes the data and issues an " irq " ( simulated by a timer ) .
* The device is capable of multi - instance , multi - buffer - per - transaction
* operation ( via the mem2mem framework ) .
*
* Copyright ( c ) 2009 - 2010 Samsung Electronics Co . , Ltd .
2011-03-13 21:23:32 +03:00
* Pawel Osciak , < pawel @ osciak . com >
2010-04-23 12:38:38 +04:00
* Marek Szyprowski , < m . szyprowski @ samsung . com >
*
* 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
*/
# include <linux/module.h>
# include <linux/delay.h>
# include <linux/fs.h>
# include <linux/timer.h>
# include <linux/sched.h>
2010-05-07 22:22:26 +04:00
# include <linux/slab.h>
2010-04-23 12:38:38 +04:00
# include <linux/platform_device.h>
# include <media/v4l2-mem2mem.h>
# include <media/v4l2-device.h>
# include <media/v4l2-ioctl.h>
2012-07-18 17:35:37 +04:00
# include <media/v4l2-ctrls.h>
2012-07-18 17:54:59 +04:00
# include <media/v4l2-event.h>
2011-01-12 12:50:55 +03:00
# include <media/videobuf2-vmalloc.h>
2010-04-23 12:38:38 +04:00
MODULE_DESCRIPTION ( " Virtual device for mem2mem framework testing " ) ;
2011-03-13 21:23:32 +03:00
MODULE_AUTHOR ( " Pawel Osciak, <pawel@osciak.com> " ) ;
2010-04-23 12:38:38 +04:00
MODULE_LICENSE ( " GPL " ) ;
[media] Stop using linux/version.h on most video drivers
All the modified drivers didn't have any version increment since
Jan, 1 2011. Several of them didn't have any version increment
for a long time, even having new features and important bug fixes
happening.
As we're now filling the QUERYCAP version with the current Kernel
Release, we don't need to maintain a per-driver version control
anymore. So, let's just use the default.
In order to preserve the Kernel module version history, a
KERNEL_VERSION() macro were added to all modified drivers, and
the extraver number were incremented.
I opted to preserve the per-driver version control to a few
pwc, pvrusb2, s2255, s5p-fimc and sh_vou.
A few drivers are still using the legacy way to handle ioctl's.
So, we can't do such change on them, otherwise, they'll break.
Those are: uvc, et61x251 and sn9c102.
The rationale is that the per-driver version control seems to be
actively maintained on those.
Yet, I think that the better for them would be to just use the
default version numbering, instead of doing that by themselves.
While here, removed a few uneeded include linux/version.h
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2011-06-24 21:45:49 +04:00
MODULE_VERSION ( " 0.1.1 " ) ;
2014-09-22 16:27:17 +04:00
MODULE_ALIAS ( " mem2mem_testdev " ) ;
2010-04-23 12:38:38 +04:00
2013-04-17 10:04:10 +04:00
static unsigned debug ;
module_param ( debug , uint , 0644 ) ;
MODULE_PARM_DESC ( debug , " activates debug info " ) ;
2010-04-23 12:38:38 +04:00
# define MIN_W 32
# define MIN_H 32
# define MAX_W 640
# define MAX_H 480
2012-04-27 11:16:46 +04:00
# define DIM_ALIGN_MASK 7 /* 8-byte alignment for line length */
2010-04-23 12:38:38 +04:00
/* Flags that indicate a format can be used for capture/output */
# define MEM2MEM_CAPTURE (1 << 0)
# define MEM2MEM_OUTPUT (1 << 1)
2014-09-22 16:27:17 +04:00
# define MEM2MEM_NAME "vim2m"
2010-04-23 12:38:38 +04:00
/* Per queue */
# define MEM2MEM_DEF_NUM_BUFS VIDEO_MAX_FRAME
/* In bytes, per queue */
# define MEM2MEM_VID_MEM_LIMIT (16 * 1024 * 1024)
/* Default transaction time in msec */
2014-03-10 17:58:23 +04:00
# define MEM2MEM_DEF_TRANSTIME 40
2010-04-23 12:38:38 +04:00
# define MEM2MEM_COLOR_STEP (0xff >> 4)
# define MEM2MEM_NUM_TILES 8
2012-06-12 13:43:49 +04:00
/* Flags that indicate processing mode */
# define MEM2MEM_HFLIP (1 << 0)
# define MEM2MEM_VFLIP (1 << 1)
2010-04-23 12:38:38 +04:00
# define dprintk(dev, fmt, arg...) \
2013-04-17 10:04:10 +04:00
v4l2_dbg ( 1 , debug , & dev - > v4l2_dev , " %s: " fmt , __func__ , # # arg )
2010-04-23 12:38:38 +04:00
2014-09-22 16:27:17 +04:00
static void vim2m_dev_release ( struct device * dev )
2010-04-23 12:38:38 +04:00
{ }
2014-09-22 16:27:17 +04:00
static struct platform_device vim2m_pdev = {
2010-04-23 12:38:38 +04:00
. name = MEM2MEM_NAME ,
2014-09-22 16:27:17 +04:00
. dev . release = vim2m_dev_release ,
2010-04-23 12:38:38 +04:00
} ;
2014-09-22 16:27:17 +04:00
struct vim2m_fmt {
2010-04-23 12:38:38 +04:00
u32 fourcc ;
int depth ;
/* Types the format can be used for */
u32 types ;
} ;
2014-09-22 16:27:17 +04:00
static struct vim2m_fmt formats [ ] = {
2010-04-23 12:38:38 +04:00
{
. fourcc = V4L2_PIX_FMT_RGB565X , /* rrrrrggg gggbbbbb */
. depth = 16 ,
/* Both capture and output format */
. types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT ,
} ,
{
. fourcc = V4L2_PIX_FMT_YUYV ,
. depth = 16 ,
/* Output-only format */
. types = MEM2MEM_OUTPUT ,
} ,
} ;
2012-07-18 17:35:37 +04:00
# define NUM_FORMATS ARRAY_SIZE(formats)
2010-04-23 12:38:38 +04:00
/* Per-queue, driver-specific private data */
2014-09-22 16:27:17 +04:00
struct vim2m_q_data {
2010-04-23 12:38:38 +04:00
unsigned int width ;
unsigned int height ;
unsigned int sizeimage ;
2014-03-10 17:58:28 +04:00
unsigned int sequence ;
2014-09-22 16:27:17 +04:00
struct vim2m_fmt * fmt ;
2010-04-23 12:38:38 +04:00
} ;
enum {
V4L2_M2M_SRC = 0 ,
V4L2_M2M_DST = 1 ,
} ;
2012-07-18 17:35:37 +04:00
# define V4L2_CID_TRANS_TIME_MSEC (V4L2_CID_USER_BASE + 0x1000)
# define V4L2_CID_TRANS_NUM_BUFS (V4L2_CID_USER_BASE + 0x1001)
2010-04-23 12:38:38 +04:00
2014-09-22 16:27:17 +04:00
static struct vim2m_fmt * find_format ( struct v4l2_format * f )
2010-04-23 12:38:38 +04:00
{
2014-09-22 16:27:17 +04:00
struct vim2m_fmt * fmt ;
2010-04-23 12:38:38 +04:00
unsigned int k ;
for ( k = 0 ; k < NUM_FORMATS ; k + + ) {
fmt = & formats [ k ] ;
if ( fmt - > fourcc = = f - > fmt . pix . pixelformat )
break ;
}
if ( k = = NUM_FORMATS )
return NULL ;
return & formats [ k ] ;
}
2014-09-22 16:27:17 +04:00
struct vim2m_dev {
2010-04-23 12:38:38 +04:00
struct v4l2_device v4l2_dev ;
2015-03-09 19:33:56 +03:00
struct video_device vfd ;
2010-04-23 12:38:38 +04:00
atomic_t num_inst ;
struct mutex dev_mutex ;
spinlock_t irqlock ;
struct timer_list timer ;
struct v4l2_m2m_dev * m2m_dev ;
} ;
2014-09-22 16:27:17 +04:00
struct vim2m_ctx {
2012-07-18 17:35:37 +04:00
struct v4l2_fh fh ;
2014-09-22 16:27:17 +04:00
struct vim2m_dev * dev ;
2010-04-23 12:38:38 +04:00
2012-07-18 17:35:37 +04:00
struct v4l2_ctrl_handler hdl ;
2010-04-23 12:38:38 +04:00
/* Processed buffers in this transaction */
u8 num_processed ;
/* Transaction length (i.e. how many buffers per transaction) */
u32 translen ;
/* Transaction time (i.e. simulated processing time) in milliseconds */
u32 transtime ;
/* Abort requested by m2m */
int aborting ;
2012-06-12 13:43:49 +04:00
/* Processing mode */
int mode ;
2012-07-18 18:33:22 +04:00
enum v4l2_colorspace colorspace ;
2012-06-08 11:47:34 +04:00
/* Source and destination queue data */
2014-09-22 16:27:17 +04:00
struct vim2m_q_data q_data [ 2 ] ;
2010-04-23 12:38:38 +04:00
} ;
2014-09-22 16:27:17 +04:00
static inline struct vim2m_ctx * file2ctx ( struct file * file )
2012-07-18 17:35:37 +04:00
{
2014-09-22 16:27:17 +04:00
return container_of ( file - > private_data , struct vim2m_ctx , fh ) ;
2012-07-18 17:35:37 +04:00
}
2014-09-22 16:27:17 +04:00
static struct vim2m_q_data * get_q_data ( struct vim2m_ctx * ctx ,
2012-06-08 11:47:34 +04:00
enum v4l2_buf_type type )
{
switch ( type ) {
case V4L2_BUF_TYPE_VIDEO_OUTPUT :
return & ctx - > q_data [ V4L2_M2M_SRC ] ;
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
return & ctx - > q_data [ V4L2_M2M_DST ] ;
default :
BUG ( ) ;
}
return NULL ;
}
2014-09-22 16:27:17 +04:00
static int device_process ( struct vim2m_ctx * ctx ,
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
struct vb2_v4l2_buffer * in_vb ,
struct vb2_v4l2_buffer * out_vb )
2010-04-23 12:38:38 +04:00
{
2014-09-22 16:27:17 +04:00
struct vim2m_dev * dev = ctx - > dev ;
struct vim2m_q_data * q_data ;
2010-04-23 12:38:38 +04:00
u8 * p_in , * p_out ;
int x , y , t , w ;
int tile_w , bytes_left ;
2011-01-12 12:50:55 +03:00
int width , height , bytesperline ;
2010-04-23 12:38:38 +04:00
2012-06-08 11:47:34 +04:00
q_data = get_q_data ( ctx , V4L2_BUF_TYPE_VIDEO_OUTPUT ) ;
2011-01-12 12:50:55 +03:00
width = q_data - > width ;
height = q_data - > height ;
bytesperline = ( q_data - > width * q_data - > fmt - > depth ) > > 3 ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
p_in = vb2_plane_vaddr ( & in_vb - > vb2_buf , 0 ) ;
p_out = vb2_plane_vaddr ( & out_vb - > vb2_buf , 0 ) ;
2010-04-23 12:38:38 +04:00
if ( ! p_in | | ! p_out ) {
v4l2_err ( & dev - > v4l2_dev ,
" Acquiring kernel pointers to buffers failed \n " ) ;
return - EFAULT ;
}
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
if ( vb2_plane_size ( & in_vb - > vb2_buf , 0 ) >
vb2_plane_size ( & out_vb - > vb2_buf , 0 ) ) {
2010-04-23 12:38:38 +04:00
v4l2_err ( & dev - > v4l2_dev , " Output buffer is too small \n " ) ;
return - EINVAL ;
}
2011-01-12 12:50:55 +03:00
tile_w = ( width * ( q_data [ V4L2_M2M_DST ] . fmt - > depth > > 3 ) )
2010-04-23 12:38:38 +04:00
/ MEM2MEM_NUM_TILES ;
2011-01-12 12:50:55 +03:00
bytes_left = bytesperline - tile_w * MEM2MEM_NUM_TILES ;
2010-04-23 12:38:38 +04:00
w = 0 ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
out_vb - > sequence =
get_q_data ( ctx , V4L2_BUF_TYPE_VIDEO_CAPTURE ) - > sequence + + ;
in_vb - > sequence = q_data - > sequence + + ;
2015-11-03 13:16:37 +03:00
out_vb - > vb2_buf . timestamp = in_vb - > vb2_buf . timestamp ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
if ( in_vb - > flags & V4L2_BUF_FLAG_TIMECODE )
out_vb - > timecode = in_vb - > timecode ;
out_vb - > field = in_vb - > field ;
out_vb - > flags = in_vb - > flags &
2014-03-10 17:58:28 +04:00
( V4L2_BUF_FLAG_TIMECODE |
V4L2_BUF_FLAG_KEYFRAME |
V4L2_BUF_FLAG_PFRAME |
V4L2_BUF_FLAG_BFRAME |
V4L2_BUF_FLAG_TSTAMP_SRC_MASK ) ;
2013-04-17 10:04:10 +04:00
2012-06-12 13:43:49 +04:00
switch ( ctx - > mode ) {
case MEM2MEM_HFLIP | MEM2MEM_VFLIP :
p_out + = bytesperline * height - bytes_left ;
for ( y = 0 ; y < height ; + + y ) {
for ( t = 0 ; t < MEM2MEM_NUM_TILES ; + + t ) {
if ( w & 0x1 ) {
for ( x = 0 ; x < tile_w ; + + x )
* - - p_out = * p_in + + +
MEM2MEM_COLOR_STEP ;
} else {
for ( x = 0 ; x < tile_w ; + + x )
* - - p_out = * p_in + + -
MEM2MEM_COLOR_STEP ;
}
+ + w ;
2010-04-23 12:38:38 +04:00
}
2012-06-12 13:43:49 +04:00
p_in + = bytes_left ;
p_out - = bytes_left ;
}
break ;
case MEM2MEM_HFLIP :
for ( y = 0 ; y < height ; + + y ) {
p_out + = MEM2MEM_NUM_TILES * tile_w ;
for ( t = 0 ; t < MEM2MEM_NUM_TILES ; + + t ) {
if ( w & 0x01 ) {
for ( x = 0 ; x < tile_w ; + + x )
* - - p_out = * p_in + + +
MEM2MEM_COLOR_STEP ;
} else {
for ( x = 0 ; x < tile_w ; + + x )
* - - p_out = * p_in + + -
MEM2MEM_COLOR_STEP ;
}
+ + w ;
}
p_in + = bytes_left ;
p_out + = bytesperline ;
}
break ;
case MEM2MEM_VFLIP :
p_out + = bytesperline * ( height - 1 ) ;
for ( y = 0 ; y < height ; + + y ) {
for ( t = 0 ; t < MEM2MEM_NUM_TILES ; + + t ) {
if ( w & 0x1 ) {
for ( x = 0 ; x < tile_w ; + + x )
* p_out + + = * p_in + + +
MEM2MEM_COLOR_STEP ;
} else {
for ( x = 0 ; x < tile_w ; + + x )
* p_out + + = * p_in + + -
MEM2MEM_COLOR_STEP ;
}
+ + w ;
}
p_in + = bytes_left ;
p_out + = bytes_left - 2 * bytesperline ;
}
break ;
default :
for ( y = 0 ; y < height ; + + y ) {
for ( t = 0 ; t < MEM2MEM_NUM_TILES ; + + t ) {
if ( w & 0x1 ) {
for ( x = 0 ; x < tile_w ; + + x )
* p_out + + = * p_in + + +
MEM2MEM_COLOR_STEP ;
} else {
for ( x = 0 ; x < tile_w ; + + x )
* p_out + + = * p_in + + -
MEM2MEM_COLOR_STEP ;
}
+ + w ;
}
p_in + = bytes_left ;
p_out + = bytes_left ;
2010-04-23 12:38:38 +04:00
}
}
return 0 ;
}
2014-09-22 16:27:17 +04:00
static void schedule_irq ( struct vim2m_dev * dev , int msec_timeout )
2010-04-23 12:38:38 +04:00
{
dprintk ( dev , " Scheduling a simulated irq \n " ) ;
mod_timer ( & dev - > timer , jiffies + msecs_to_jiffies ( msec_timeout ) ) ;
}
/*
* mem2mem callbacks
*/
/**
* job_ready ( ) - check whether an instance is ready to be scheduled to run
*/
static int job_ready ( void * priv )
{
2014-09-22 16:27:17 +04:00
struct vim2m_ctx * ctx = priv ;
2010-04-23 12:38:38 +04:00
2013-08-26 00:27:45 +04:00
if ( v4l2_m2m_num_src_bufs_ready ( ctx - > fh . m2m_ctx ) < ctx - > translen
| | v4l2_m2m_num_dst_bufs_ready ( ctx - > fh . m2m_ctx ) < ctx - > translen ) {
2010-04-23 12:38:38 +04:00
dprintk ( ctx - > dev , " Not enough buffers available \n " ) ;
return 0 ;
}
return 1 ;
}
static void job_abort ( void * priv )
{
2014-09-22 16:27:17 +04:00
struct vim2m_ctx * ctx = priv ;
2010-04-23 12:38:38 +04:00
/* Will cancel the transaction in the next interrupt handler */
ctx - > aborting = 1 ;
}
/* device_run() - prepares and starts the device
*
* This simulates all the immediate preparations required before starting
* a device . This will be called by the framework when it decides to schedule
* a particular instance .
*/
static void device_run ( void * priv )
{
2014-09-22 16:27:17 +04:00
struct vim2m_ctx * ctx = priv ;
struct vim2m_dev * dev = ctx - > dev ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
struct vb2_v4l2_buffer * src_buf , * dst_buf ;
2010-04-23 12:38:38 +04:00
2013-08-26 00:27:45 +04:00
src_buf = v4l2_m2m_next_src_buf ( ctx - > fh . m2m_ctx ) ;
dst_buf = v4l2_m2m_next_dst_buf ( ctx - > fh . m2m_ctx ) ;
2010-04-23 12:38:38 +04:00
device_process ( ctx , src_buf , dst_buf ) ;
/* Run a timer, which simulates a hardware irq */
schedule_irq ( dev , ctx - > transtime ) ;
}
static void device_isr ( unsigned long priv )
{
2014-09-22 16:27:17 +04:00
struct vim2m_dev * vim2m_dev = ( struct vim2m_dev * ) priv ;
struct vim2m_ctx * curr_ctx ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
struct vb2_v4l2_buffer * src_vb , * dst_vb ;
2010-04-23 12:38:38 +04:00
unsigned long flags ;
2014-09-22 16:27:17 +04:00
curr_ctx = v4l2_m2m_get_curr_priv ( vim2m_dev - > m2m_dev ) ;
2010-04-23 12:38:38 +04:00
if ( NULL = = curr_ctx ) {
2012-09-24 09:17:47 +04:00
pr_err ( " Instance released before the end of transaction \n " ) ;
2010-04-23 12:38:38 +04:00
return ;
}
2013-08-26 00:27:45 +04:00
src_vb = v4l2_m2m_src_buf_remove ( curr_ctx - > fh . m2m_ctx ) ;
dst_vb = v4l2_m2m_dst_buf_remove ( curr_ctx - > fh . m2m_ctx ) ;
2011-01-12 12:50:55 +03:00
2010-04-23 12:38:38 +04:00
curr_ctx - > num_processed + + ;
2014-09-22 16:27:17 +04:00
spin_lock_irqsave ( & vim2m_dev - > irqlock , flags ) ;
2011-01-12 12:50:55 +03:00
v4l2_m2m_buf_done ( src_vb , VB2_BUF_STATE_DONE ) ;
v4l2_m2m_buf_done ( dst_vb , VB2_BUF_STATE_DONE ) ;
2014-09-22 16:27:17 +04:00
spin_unlock_irqrestore ( & vim2m_dev - > irqlock , flags ) ;
2011-01-12 12:50:55 +03:00
2010-04-23 12:38:38 +04:00
if ( curr_ctx - > num_processed = = curr_ctx - > translen
| | curr_ctx - > aborting ) {
dprintk ( curr_ctx - > dev , " Finishing transaction \n " ) ;
curr_ctx - > num_processed = 0 ;
2014-09-22 16:27:17 +04:00
v4l2_m2m_job_finish ( vim2m_dev - > m2m_dev , curr_ctx - > fh . m2m_ctx ) ;
2010-04-23 12:38:38 +04:00
} else {
device_run ( curr_ctx ) ;
}
}
/*
* video ioctls
*/
static int vidioc_querycap ( struct file * file , void * priv ,
struct v4l2_capability * cap )
{
strncpy ( cap - > driver , MEM2MEM_NAME , sizeof ( cap - > driver ) - 1 ) ;
strncpy ( cap - > card , MEM2MEM_NAME , sizeof ( cap - > card ) - 1 ) ;
2012-09-14 13:23:12 +04:00
snprintf ( cap - > bus_info , sizeof ( cap - > bus_info ) ,
" platform:%s " , MEM2MEM_NAME ) ;
2012-08-01 10:32:33 +04:00
cap - > device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING ;
2012-07-18 17:46:01 +04:00
cap - > capabilities = cap - > device_caps | V4L2_CAP_DEVICE_CAPS ;
2010-04-23 12:38:38 +04:00
return 0 ;
}
static int enum_fmt ( struct v4l2_fmtdesc * f , u32 type )
{
int i , num ;
2014-09-22 16:27:17 +04:00
struct vim2m_fmt * fmt ;
2010-04-23 12:38:38 +04:00
num = 0 ;
for ( i = 0 ; i < NUM_FORMATS ; + + i ) {
if ( formats [ i ] . types & type ) {
/* index-th format of type type found ? */
if ( num = = f - > index )
break ;
/* Correct type but haven't reached our index yet,
* just increment per - type index */
+ + num ;
}
}
if ( i < NUM_FORMATS ) {
/* Format found */
fmt = & formats [ i ] ;
f - > pixelformat = fmt - > fourcc ;
return 0 ;
}
/* Format not found */
return - EINVAL ;
}
static int vidioc_enum_fmt_vid_cap ( struct file * file , void * priv ,
struct v4l2_fmtdesc * f )
{
return enum_fmt ( f , MEM2MEM_CAPTURE ) ;
}
static int vidioc_enum_fmt_vid_out ( struct file * file , void * priv ,
struct v4l2_fmtdesc * f )
{
return enum_fmt ( f , MEM2MEM_OUTPUT ) ;
}
2014-09-22 16:27:17 +04:00
static int vidioc_g_fmt ( struct vim2m_ctx * ctx , struct v4l2_format * f )
2010-04-23 12:38:38 +04:00
{
2011-01-12 12:50:55 +03:00
struct vb2_queue * vq ;
2014-09-22 16:27:17 +04:00
struct vim2m_q_data * q_data ;
2010-04-23 12:38:38 +04:00
2013-08-26 00:27:45 +04:00
vq = v4l2_m2m_get_vq ( ctx - > fh . m2m_ctx , f - > type ) ;
2010-04-23 12:38:38 +04:00
if ( ! vq )
return - EINVAL ;
2012-06-08 11:47:34 +04:00
q_data = get_q_data ( ctx , f - > type ) ;
2010-04-23 12:38:38 +04:00
f - > fmt . pix . width = q_data - > width ;
f - > fmt . pix . height = q_data - > height ;
2011-01-12 12:50:55 +03:00
f - > fmt . pix . field = V4L2_FIELD_NONE ;
2010-04-23 12:38:38 +04:00
f - > fmt . pix . pixelformat = q_data - > fmt - > fourcc ;
f - > fmt . pix . bytesperline = ( q_data - > width * q_data - > fmt - > depth ) > > 3 ;
f - > fmt . pix . sizeimage = q_data - > sizeimage ;
2012-07-18 18:33:22 +04:00
f - > fmt . pix . colorspace = ctx - > colorspace ;
2010-04-23 12:38:38 +04:00
return 0 ;
}
static int vidioc_g_fmt_vid_out ( struct file * file , void * priv ,
struct v4l2_format * f )
{
2012-07-18 17:35:37 +04:00
return vidioc_g_fmt ( file2ctx ( file ) , f ) ;
2010-04-23 12:38:38 +04:00
}
static int vidioc_g_fmt_vid_cap ( struct file * file , void * priv ,
struct v4l2_format * f )
{
2012-07-18 17:35:37 +04:00
return vidioc_g_fmt ( file2ctx ( file ) , f ) ;
2010-04-23 12:38:38 +04:00
}
2014-09-22 16:27:17 +04:00
static int vidioc_try_fmt ( struct v4l2_format * f , struct vim2m_fmt * fmt )
2010-04-23 12:38:38 +04:00
{
/* V4L2 specification suggests the driver corrects the format struct
* if any of the dimensions is unsupported */
if ( f - > fmt . pix . height < MIN_H )
f - > fmt . pix . height = MIN_H ;
else if ( f - > fmt . pix . height > MAX_H )
f - > fmt . pix . height = MAX_H ;
if ( f - > fmt . pix . width < MIN_W )
f - > fmt . pix . width = MIN_W ;
else if ( f - > fmt . pix . width > MAX_W )
f - > fmt . pix . width = MAX_W ;
f - > fmt . pix . width & = ~ DIM_ALIGN_MASK ;
f - > fmt . pix . bytesperline = ( f - > fmt . pix . width * fmt - > depth ) > > 3 ;
f - > fmt . pix . sizeimage = f - > fmt . pix . height * f - > fmt . pix . bytesperline ;
2014-03-10 17:58:29 +04:00
f - > fmt . pix . field = V4L2_FIELD_NONE ;
2010-04-23 12:38:38 +04:00
return 0 ;
}
static int vidioc_try_fmt_vid_cap ( struct file * file , void * priv ,
struct v4l2_format * f )
{
2014-09-22 16:27:17 +04:00
struct vim2m_fmt * fmt ;
struct vim2m_ctx * ctx = file2ctx ( file ) ;
2010-04-23 12:38:38 +04:00
fmt = find_format ( f ) ;
2014-03-10 17:58:24 +04:00
if ( ! fmt ) {
f - > fmt . pix . pixelformat = formats [ 0 ] . fourcc ;
fmt = find_format ( f ) ;
}
if ( ! ( fmt - > types & MEM2MEM_CAPTURE ) ) {
2010-04-23 12:38:38 +04:00
v4l2_err ( & ctx - > dev - > v4l2_dev ,
" Fourcc format (0x%08x) invalid. \n " ,
f - > fmt . pix . pixelformat ) ;
return - EINVAL ;
}
2012-07-18 18:33:22 +04:00
f - > fmt . pix . colorspace = ctx - > colorspace ;
2010-04-23 12:38:38 +04:00
return vidioc_try_fmt ( f , fmt ) ;
}
static int vidioc_try_fmt_vid_out ( struct file * file , void * priv ,
struct v4l2_format * f )
{
2014-09-22 16:27:17 +04:00
struct vim2m_fmt * fmt ;
struct vim2m_ctx * ctx = file2ctx ( file ) ;
2010-04-23 12:38:38 +04:00
fmt = find_format ( f ) ;
2014-03-10 17:58:24 +04:00
if ( ! fmt ) {
f - > fmt . pix . pixelformat = formats [ 0 ] . fourcc ;
fmt = find_format ( f ) ;
}
if ( ! ( fmt - > types & MEM2MEM_OUTPUT ) ) {
2010-04-23 12:38:38 +04:00
v4l2_err ( & ctx - > dev - > v4l2_dev ,
" Fourcc format (0x%08x) invalid. \n " ,
f - > fmt . pix . pixelformat ) ;
return - EINVAL ;
}
2012-07-18 18:33:22 +04:00
if ( ! f - > fmt . pix . colorspace )
f - > fmt . pix . colorspace = V4L2_COLORSPACE_REC709 ;
2010-04-23 12:38:38 +04:00
return vidioc_try_fmt ( f , fmt ) ;
}
2014-09-22 16:27:17 +04:00
static int vidioc_s_fmt ( struct vim2m_ctx * ctx , struct v4l2_format * f )
2010-04-23 12:38:38 +04:00
{
2014-09-22 16:27:17 +04:00
struct vim2m_q_data * q_data ;
2011-01-12 12:50:55 +03:00
struct vb2_queue * vq ;
2010-04-23 12:38:38 +04:00
2013-08-26 00:27:45 +04:00
vq = v4l2_m2m_get_vq ( ctx - > fh . m2m_ctx , f - > type ) ;
2010-04-23 12:38:38 +04:00
if ( ! vq )
return - EINVAL ;
2012-06-08 11:47:34 +04:00
q_data = get_q_data ( ctx , f - > type ) ;
2010-04-23 12:38:38 +04:00
if ( ! q_data )
return - EINVAL ;
2011-01-12 12:50:55 +03:00
if ( vb2_is_busy ( vq ) ) {
2010-04-23 12:38:38 +04:00
v4l2_err ( & ctx - > dev - > v4l2_dev , " %s queue busy \n " , __func__ ) ;
2010-12-20 20:39:25 +03:00
return - EBUSY ;
2010-04-23 12:38:38 +04:00
}
q_data - > fmt = find_format ( f ) ;
q_data - > width = f - > fmt . pix . width ;
q_data - > height = f - > fmt . pix . height ;
q_data - > sizeimage = q_data - > width * q_data - > height
* q_data - > fmt - > depth > > 3 ;
dprintk ( ctx - > dev ,
" Setting format for type %d, wxh: %dx%d, fmt: %d \n " ,
f - > type , q_data - > width , q_data - > height , q_data - > fmt - > fourcc ) ;
2010-12-20 20:39:25 +03:00
return 0 ;
2010-04-23 12:38:38 +04:00
}
static int vidioc_s_fmt_vid_cap ( struct file * file , void * priv ,
struct v4l2_format * f )
{
int ret ;
ret = vidioc_try_fmt_vid_cap ( file , priv , f ) ;
if ( ret )
return ret ;
2012-07-18 17:35:37 +04:00
return vidioc_s_fmt ( file2ctx ( file ) , f ) ;
2010-04-23 12:38:38 +04:00
}
static int vidioc_s_fmt_vid_out ( struct file * file , void * priv ,
struct v4l2_format * f )
{
2014-09-22 16:27:17 +04:00
struct vim2m_ctx * ctx = file2ctx ( file ) ;
2010-04-23 12:38:38 +04:00
int ret ;
ret = vidioc_try_fmt_vid_out ( file , priv , f ) ;
if ( ret )
return ret ;
2012-07-18 18:33:22 +04:00
ret = vidioc_s_fmt ( file2ctx ( file ) , f ) ;
if ( ! ret )
ctx - > colorspace = f - > fmt . pix . colorspace ;
return ret ;
2010-04-23 12:38:38 +04:00
}
2014-09-22 16:27:17 +04:00
static int vim2m_s_ctrl ( struct v4l2_ctrl * ctrl )
2010-04-23 12:38:38 +04:00
{
2014-09-22 16:27:17 +04:00
struct vim2m_ctx * ctx =
container_of ( ctrl - > handler , struct vim2m_ctx , hdl ) ;
2010-04-23 12:38:38 +04:00
switch ( ctrl - > id ) {
2012-06-12 13:43:49 +04:00
case V4L2_CID_HFLIP :
2012-07-18 17:35:37 +04:00
if ( ctrl - > val )
2012-06-12 13:43:49 +04:00
ctx - > mode | = MEM2MEM_HFLIP ;
else
ctx - > mode & = ~ MEM2MEM_HFLIP ;
break ;
case V4L2_CID_VFLIP :
2012-07-18 17:35:37 +04:00
if ( ctrl - > val )
2012-06-12 13:43:49 +04:00
ctx - > mode | = MEM2MEM_VFLIP ;
else
ctx - > mode & = ~ MEM2MEM_VFLIP ;
break ;
2010-04-23 12:38:38 +04:00
case V4L2_CID_TRANS_TIME_MSEC :
2012-07-18 17:35:37 +04:00
ctx - > transtime = ctrl - > val ;
2010-04-23 12:38:38 +04:00
break ;
case V4L2_CID_TRANS_NUM_BUFS :
2012-07-18 17:35:37 +04:00
ctx - > translen = ctrl - > val ;
2010-04-23 12:38:38 +04:00
break ;
default :
v4l2_err ( & ctx - > dev - > v4l2_dev , " Invalid control \n " ) ;
return - EINVAL ;
}
return 0 ;
}
2014-09-22 16:27:17 +04:00
static const struct v4l2_ctrl_ops vim2m_ctrl_ops = {
. s_ctrl = vim2m_s_ctrl ,
2012-07-18 17:35:37 +04:00
} ;
2010-04-23 12:38:38 +04:00
2014-09-22 16:27:17 +04:00
static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
2010-04-23 12:38:38 +04:00
. vidioc_querycap = vidioc_querycap ,
. vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap ,
. 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_fmt_vid_out = vidioc_enum_fmt_vid_out ,
. vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out ,
. vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out ,
. vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out ,
2013-08-26 00:27:45 +04:00
. vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs ,
. vidioc_querybuf = v4l2_m2m_ioctl_querybuf ,
. vidioc_qbuf = v4l2_m2m_ioctl_qbuf ,
. vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf ,
2015-06-05 17:28:52 +03:00
. vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf ,
. vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs ,
2014-11-18 15:51:07 +03:00
. vidioc_expbuf = v4l2_m2m_ioctl_expbuf ,
2010-04-23 12:38:38 +04:00
2013-08-26 00:27:45 +04:00
. vidioc_streamon = v4l2_m2m_ioctl_streamon ,
. vidioc_streamoff = v4l2_m2m_ioctl_streamoff ,
2010-04-23 12:38:38 +04:00
2012-07-18 17:54:59 +04:00
. vidioc_subscribe_event = v4l2_ctrl_subscribe_event ,
. vidioc_unsubscribe_event = v4l2_event_unsubscribe ,
2010-04-23 12:38:38 +04:00
} ;
/*
* Queue operations
*/
2014-09-22 16:27:17 +04:00
static int vim2m_queue_setup ( struct vb2_queue * vq ,
2011-08-24 17:30:21 +04:00
unsigned int * nbuffers , unsigned int * nplanes ,
unsigned int sizes [ ] , void * alloc_ctxs [ ] )
2010-04-23 12:38:38 +04:00
{
2014-09-22 16:27:17 +04:00
struct vim2m_ctx * ctx = vb2_get_drv_priv ( vq ) ;
struct vim2m_q_data * q_data ;
2011-01-12 12:50:55 +03:00
unsigned int size , count = * nbuffers ;
2010-04-23 12:38:38 +04:00
2012-06-08 11:47:34 +04:00
q_data = get_q_data ( ctx , vq - > type ) ;
2010-04-23 12:38:38 +04:00
2011-01-12 12:50:55 +03:00
size = q_data - > width * q_data - > height * q_data - > fmt - > depth > > 3 ;
while ( size * count > MEM2MEM_VID_MEM_LIMIT )
( count ) - - ;
2015-10-28 05:50:37 +03:00
* nbuffers = count ;
if ( * nplanes )
return sizes [ 0 ] < size ? - EINVAL : 0 ;
2010-04-23 12:38:38 +04:00
2011-01-12 12:50:55 +03:00
* nplanes = 1 ;
sizes [ 0 ] = size ;
2010-04-23 12:38:38 +04:00
2011-01-12 12:50:55 +03:00
/*
* videobuf2 - vmalloc allocator is context - less so no need to set
* alloc_ctxs array .
*/
2010-04-23 12:38:38 +04:00
2011-01-12 12:50:55 +03:00
dprintk ( ctx - > dev , " get %d buffer(s) of size %d each. \n " , count , size ) ;
2010-04-23 12:38:38 +04:00
return 0 ;
}
2014-09-22 16:27:17 +04:00
static int vim2m_buf_prepare ( struct vb2_buffer * vb )
2010-04-23 12:38:38 +04:00
{
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
struct vb2_v4l2_buffer * vbuf = to_vb2_v4l2_buffer ( vb ) ;
2014-09-22 16:27:17 +04:00
struct vim2m_ctx * ctx = vb2_get_drv_priv ( vb - > vb2_queue ) ;
struct vim2m_q_data * q_data ;
2010-04-23 12:38:38 +04:00
2011-01-12 12:50:55 +03:00
dprintk ( ctx - > dev , " type: %d \n " , vb - > vb2_queue - > type ) ;
2010-04-23 12:38:38 +04:00
2012-06-08 11:47:34 +04:00
q_data = get_q_data ( ctx , vb - > vb2_queue - > type ) ;
2014-03-10 17:58:29 +04:00
if ( V4L2_TYPE_IS_OUTPUT ( vb - > vb2_queue - > type ) ) {
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
if ( vbuf - > field = = V4L2_FIELD_ANY )
vbuf - > field = V4L2_FIELD_NONE ;
if ( vbuf - > field ! = V4L2_FIELD_NONE ) {
2014-03-10 17:58:29 +04:00
dprintk ( ctx - > dev , " %s field isn't supported \n " ,
__func__ ) ;
return - EINVAL ;
}
}
2010-04-23 12:38:38 +04:00
2011-01-12 12:50:55 +03:00
if ( vb2_plane_size ( vb , 0 ) < q_data - > sizeimage ) {
dprintk ( ctx - > dev , " %s data will not fit into plane (%lu < %lu) \n " ,
__func__ , vb2_plane_size ( vb , 0 ) , ( long ) q_data - > sizeimage ) ;
2010-04-23 12:38:38 +04:00
return - EINVAL ;
}
2011-01-12 12:50:55 +03:00
vb2_set_plane_payload ( vb , 0 , q_data - > sizeimage ) ;
2010-04-23 12:38:38 +04:00
return 0 ;
}
2014-09-22 16:27:17 +04:00
static void vim2m_buf_queue ( struct vb2_buffer * vb )
2010-04-23 12:38:38 +04:00
{
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
struct vb2_v4l2_buffer * vbuf = to_vb2_v4l2_buffer ( vb ) ;
2014-09-22 16:27:17 +04:00
struct vim2m_ctx * ctx = vb2_get_drv_priv ( vb - > vb2_queue ) ;
2014-03-10 17:58:28 +04:00
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
v4l2_m2m_buf_queue ( ctx - > fh . m2m_ctx , vbuf ) ;
2011-07-12 16:46:44 +04:00
}
2014-09-22 16:27:17 +04:00
static int vim2m_start_streaming ( struct vb2_queue * q , unsigned count )
2014-03-10 17:58:28 +04:00
{
2014-09-22 16:27:17 +04:00
struct vim2m_ctx * ctx = vb2_get_drv_priv ( q ) ;
struct vim2m_q_data * q_data = get_q_data ( ctx , q - > type ) ;
2014-03-10 17:58:28 +04:00
q_data - > sequence = 0 ;
return 0 ;
}
2014-09-22 16:27:17 +04:00
static void vim2m_stop_streaming ( struct vb2_queue * q )
2014-03-10 17:58:27 +04:00
{
2014-09-22 16:27:17 +04:00
struct vim2m_ctx * ctx = vb2_get_drv_priv ( q ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
struct vb2_v4l2_buffer * vbuf ;
2014-03-10 17:58:27 +04:00
unsigned long flags ;
for ( ; ; ) {
if ( V4L2_TYPE_IS_OUTPUT ( q - > type ) )
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
vbuf = v4l2_m2m_src_buf_remove ( ctx - > fh . m2m_ctx ) ;
2014-03-10 17:58:27 +04:00
else
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
vbuf = v4l2_m2m_dst_buf_remove ( ctx - > fh . m2m_ctx ) ;
if ( vbuf = = NULL )
2014-04-17 09:47:21 +04:00
return ;
2014-03-10 17:58:27 +04:00
spin_lock_irqsave ( & ctx - > dev - > irqlock , flags ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 16:30:30 +03:00
v4l2_m2m_buf_done ( vbuf , VB2_BUF_STATE_ERROR ) ;
2014-03-10 17:58:27 +04:00
spin_unlock_irqrestore ( & ctx - > dev - > irqlock , flags ) ;
}
}
2014-09-22 16:27:17 +04:00
static struct vb2_ops vim2m_qops = {
. queue_setup = vim2m_queue_setup ,
. buf_prepare = vim2m_buf_prepare ,
. buf_queue = vim2m_buf_queue ,
. start_streaming = vim2m_start_streaming ,
. stop_streaming = vim2m_stop_streaming ,
2013-08-26 00:27:45 +04:00
. wait_prepare = vb2_ops_wait_prepare ,
. wait_finish = vb2_ops_wait_finish ,
2010-04-23 12:38:38 +04:00
} ;
2011-01-12 12:50:55 +03:00
static int queue_init ( void * priv , struct vb2_queue * src_vq , struct vb2_queue * dst_vq )
2010-04-23 12:38:38 +04:00
{
2014-09-22 16:27:17 +04:00
struct vim2m_ctx * ctx = priv ;
2011-01-12 12:50:55 +03:00
int ret ;
2010-04-23 12:38:38 +04:00
2011-01-12 12:50:55 +03:00
src_vq - > type = V4L2_BUF_TYPE_VIDEO_OUTPUT ;
2014-03-10 17:58:26 +04:00
src_vq - > io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF ;
2011-01-12 12:50:55 +03:00
src_vq - > drv_priv = ctx ;
src_vq - > buf_struct_size = sizeof ( struct v4l2_m2m_buffer ) ;
2014-09-22 16:27:17 +04:00
src_vq - > ops = & vim2m_qops ;
2011-01-12 12:50:55 +03:00
src_vq - > mem_ops = & vb2_vmalloc_memops ;
2014-02-26 02:12:19 +04:00
src_vq - > timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY ;
2013-08-26 00:27:45 +04:00
src_vq - > lock = & ctx - > dev - > dev_mutex ;
2011-01-12 12:50:55 +03:00
ret = vb2_queue_init ( src_vq ) ;
if ( ret )
return ret ;
2010-04-23 12:38:38 +04:00
2011-01-12 12:50:55 +03:00
dst_vq - > type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
2014-03-10 17:58:26 +04:00
dst_vq - > io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF ;
2011-01-12 12:50:55 +03:00
dst_vq - > drv_priv = ctx ;
dst_vq - > buf_struct_size = sizeof ( struct v4l2_m2m_buffer ) ;
2014-09-22 16:27:17 +04:00
dst_vq - > ops = & vim2m_qops ;
2011-01-12 12:50:55 +03:00
dst_vq - > mem_ops = & vb2_vmalloc_memops ;
2014-02-26 02:12:19 +04:00
dst_vq - > timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY ;
2013-08-26 00:27:45 +04:00
dst_vq - > lock = & ctx - > dev - > dev_mutex ;
2011-01-12 12:50:55 +03:00
return vb2_queue_init ( dst_vq ) ;
}
2010-04-23 12:38:38 +04:00
2014-09-22 16:27:17 +04:00
static const struct v4l2_ctrl_config vim2m_ctrl_trans_time_msec = {
. ops = & vim2m_ctrl_ops ,
2012-07-18 17:35:37 +04:00
. id = V4L2_CID_TRANS_TIME_MSEC ,
. name = " Transaction Time (msec) " ,
. type = V4L2_CTRL_TYPE_INTEGER ,
2014-03-10 17:58:23 +04:00
. def = MEM2MEM_DEF_TRANSTIME ,
2012-07-18 17:35:37 +04:00
. min = 1 ,
. max = 10001 ,
2014-03-10 17:58:23 +04:00
. step = 1 ,
2012-07-18 17:35:37 +04:00
} ;
2014-09-22 16:27:17 +04:00
static const struct v4l2_ctrl_config vim2m_ctrl_trans_num_bufs = {
. ops = & vim2m_ctrl_ops ,
2012-07-18 17:35:37 +04:00
. id = V4L2_CID_TRANS_NUM_BUFS ,
. name = " Buffers Per Transaction " ,
. type = V4L2_CTRL_TYPE_INTEGER ,
. def = 1 ,
. min = 1 ,
. max = MEM2MEM_DEF_NUM_BUFS ,
. step = 1 ,
} ;
2010-04-23 12:38:38 +04:00
/*
* File operations
*/
2014-09-22 16:27:17 +04:00
static int vim2m_open ( struct file * file )
2010-04-23 12:38:38 +04:00
{
2014-09-22 16:27:17 +04:00
struct vim2m_dev * dev = video_drvdata ( file ) ;
struct vim2m_ctx * ctx = NULL ;
2012-07-18 17:35:37 +04:00
struct v4l2_ctrl_handler * hdl ;
2012-07-31 10:51:25 +04:00
int rc = 0 ;
2010-04-23 12:38:38 +04:00
2012-07-31 10:51:25 +04:00
if ( mutex_lock_interruptible ( & dev - > dev_mutex ) )
return - ERESTARTSYS ;
2012-09-24 09:17:46 +04:00
ctx = kzalloc ( sizeof ( * ctx ) , GFP_KERNEL ) ;
2012-07-31 10:51:25 +04:00
if ( ! ctx ) {
rc = - ENOMEM ;
goto open_unlock ;
}
2010-04-23 12:38:38 +04:00
2012-07-18 17:35:37 +04:00
v4l2_fh_init ( & ctx - > fh , video_devdata ( file ) ) ;
file - > private_data = & ctx - > fh ;
2010-04-23 12:38:38 +04:00
ctx - > dev = dev ;
2012-07-18 17:35:37 +04:00
hdl = & ctx - > hdl ;
v4l2_ctrl_handler_init ( hdl , 4 ) ;
2014-09-22 16:27:17 +04:00
v4l2_ctrl_new_std ( hdl , & vim2m_ctrl_ops , V4L2_CID_HFLIP , 0 , 1 , 1 , 0 ) ;
v4l2_ctrl_new_std ( hdl , & vim2m_ctrl_ops , V4L2_CID_VFLIP , 0 , 1 , 1 , 0 ) ;
v4l2_ctrl_new_custom ( hdl , & vim2m_ctrl_trans_time_msec , NULL ) ;
v4l2_ctrl_new_custom ( hdl , & vim2m_ctrl_trans_num_bufs , NULL ) ;
2012-07-18 17:35:37 +04:00
if ( hdl - > error ) {
2012-08-14 09:58:56 +04:00
rc = hdl - > error ;
2012-07-18 17:35:37 +04:00
v4l2_ctrl_handler_free ( hdl ) ;
2012-08-14 09:58:56 +04:00
goto open_unlock ;
2012-07-18 17:35:37 +04:00
}
ctx - > fh . ctrl_handler = hdl ;
v4l2_ctrl_handler_setup ( hdl ) ;
2010-04-23 12:38:38 +04:00
2012-06-08 11:47:34 +04:00
ctx - > q_data [ V4L2_M2M_SRC ] . fmt = & formats [ 0 ] ;
2012-07-18 18:33:22 +04:00
ctx - > q_data [ V4L2_M2M_SRC ] . width = 640 ;
ctx - > q_data [ V4L2_M2M_SRC ] . height = 480 ;
ctx - > q_data [ V4L2_M2M_SRC ] . sizeimage =
ctx - > q_data [ V4L2_M2M_SRC ] . width *
ctx - > q_data [ V4L2_M2M_SRC ] . height *
( ctx - > q_data [ V4L2_M2M_SRC ] . fmt - > depth > > 3 ) ;
ctx - > q_data [ V4L2_M2M_DST ] = ctx - > q_data [ V4L2_M2M_SRC ] ;
ctx - > colorspace = V4L2_COLORSPACE_REC709 ;
2012-06-08 11:47:34 +04:00
2013-08-26 00:27:45 +04:00
ctx - > fh . m2m_ctx = v4l2_m2m_ctx_init ( dev - > m2m_dev , ctx , & queue_init ) ;
2011-01-12 12:50:55 +03:00
2013-08-26 00:27:45 +04:00
if ( IS_ERR ( ctx - > fh . m2m_ctx ) ) {
rc = PTR_ERR ( ctx - > fh . m2m_ctx ) ;
2010-05-05 09:58:57 +04:00
2012-07-18 17:35:37 +04:00
v4l2_ctrl_handler_free ( hdl ) ;
2010-04-23 12:38:38 +04:00
kfree ( ctx ) ;
2012-07-31 10:51:25 +04:00
goto open_unlock ;
2010-04-23 12:38:38 +04:00
}
2012-07-18 17:35:37 +04:00
v4l2_fh_add ( & ctx - > fh ) ;
2010-04-23 12:38:38 +04:00
atomic_inc ( & dev - > num_inst ) ;
2013-08-26 00:27:45 +04:00
dprintk ( dev , " Created instance: %p, m2m_ctx: %p \n " ,
ctx , ctx - > fh . m2m_ctx ) ;
2010-04-23 12:38:38 +04:00
2012-07-31 10:51:25 +04:00
open_unlock :
mutex_unlock ( & dev - > dev_mutex ) ;
2012-08-14 09:58:56 +04:00
return rc ;
2010-04-23 12:38:38 +04:00
}
2014-09-22 16:27:17 +04:00
static int vim2m_release ( struct file * file )
2010-04-23 12:38:38 +04:00
{
2014-09-22 16:27:17 +04:00
struct vim2m_dev * dev = video_drvdata ( file ) ;
struct vim2m_ctx * ctx = file2ctx ( file ) ;
2010-04-23 12:38:38 +04:00
dprintk ( dev , " Releasing instance %p \n " , ctx ) ;
2012-07-18 17:35:37 +04:00
v4l2_fh_del ( & ctx - > fh ) ;
v4l2_fh_exit ( & ctx - > fh ) ;
v4l2_ctrl_handler_free ( & ctx - > hdl ) ;
2012-07-31 10:51:25 +04:00
mutex_lock ( & dev - > dev_mutex ) ;
2013-08-26 00:27:45 +04:00
v4l2_m2m_ctx_release ( ctx - > fh . m2m_ctx ) ;
2012-07-31 10:51:25 +04:00
mutex_unlock ( & dev - > dev_mutex ) ;
2010-04-23 12:38:38 +04:00
kfree ( ctx ) ;
atomic_dec ( & dev - > num_inst ) ;
return 0 ;
}
2014-09-22 16:27:17 +04:00
static const struct v4l2_file_operations vim2m_fops = {
2010-04-23 12:38:38 +04:00
. owner = THIS_MODULE ,
2014-09-22 16:27:17 +04:00
. open = vim2m_open ,
. release = vim2m_release ,
2013-08-26 00:27:45 +04:00
. poll = v4l2_m2m_fop_poll ,
2010-12-20 20:39:25 +03:00
. unlocked_ioctl = video_ioctl2 ,
2013-08-26 00:27:45 +04:00
. mmap = v4l2_m2m_fop_mmap ,
2010-04-23 12:38:38 +04:00
} ;
2014-09-22 16:27:17 +04:00
static struct video_device vim2m_videodev = {
2010-04-23 12:38:38 +04:00
. name = MEM2MEM_NAME ,
2012-09-05 13:05:50 +04:00
. vfl_dir = VFL_DIR_M2M ,
2014-09-22 16:27:17 +04:00
. fops = & vim2m_fops ,
. ioctl_ops = & vim2m_ioctl_ops ,
2010-04-23 12:38:38 +04:00
. minor = - 1 ,
2015-03-09 19:33:56 +03:00
. release = video_device_release_empty ,
2010-04-23 12:38:38 +04:00
} ;
static struct v4l2_m2m_ops m2m_ops = {
. device_run = device_run ,
. job_ready = job_ready ,
. job_abort = job_abort ,
} ;
2014-09-22 16:27:17 +04:00
static int vim2m_probe ( struct platform_device * pdev )
2010-04-23 12:38:38 +04:00
{
2014-09-22 16:27:17 +04:00
struct vim2m_dev * dev ;
2010-04-23 12:38:38 +04:00
struct video_device * vfd ;
int ret ;
2012-09-24 09:17:48 +04:00
dev = devm_kzalloc ( & pdev - > dev , sizeof ( * dev ) , GFP_KERNEL ) ;
2010-04-23 12:38:38 +04:00
if ( ! dev )
return - ENOMEM ;
spin_lock_init ( & dev - > irqlock ) ;
ret = v4l2_device_register ( & pdev - > dev , & dev - > v4l2_dev ) ;
if ( ret )
2012-09-24 09:17:48 +04:00
return ret ;
2010-04-23 12:38:38 +04:00
atomic_set ( & dev - > num_inst , 0 ) ;
mutex_init ( & dev - > dev_mutex ) ;
2015-03-09 19:33:56 +03:00
dev - > vfd = vim2m_videodev ;
vfd = & dev - > vfd ;
2010-12-20 20:39:25 +03:00
vfd - > lock = & dev - > dev_mutex ;
2013-06-27 09:44:04 +04:00
vfd - > v4l2_dev = & dev - > v4l2_dev ;
2010-04-23 12:38:38 +04:00
ret = video_register_device ( vfd , VFL_TYPE_GRABBER , 0 ) ;
if ( ret ) {
v4l2_err ( & dev - > v4l2_dev , " Failed to register video device \n " ) ;
2015-03-09 19:33:56 +03:00
goto unreg_dev ;
2010-04-23 12:38:38 +04:00
}
video_set_drvdata ( vfd , dev ) ;
2014-09-22 16:27:17 +04:00
snprintf ( vfd - > name , sizeof ( vfd - > name ) , " %s " , vim2m_videodev . name ) ;
2013-06-27 09:44:04 +04:00
v4l2_info ( & dev - > v4l2_dev ,
2010-04-23 12:38:38 +04:00
" Device registered as /dev/video%d \n " , vfd - > num ) ;
setup_timer ( & dev - > timer , device_isr , ( long ) dev ) ;
platform_set_drvdata ( pdev , dev ) ;
dev - > m2m_dev = v4l2_m2m_init ( & m2m_ops ) ;
if ( IS_ERR ( dev - > m2m_dev ) ) {
v4l2_err ( & dev - > v4l2_dev , " Failed to init mem2mem device \n " ) ;
ret = PTR_ERR ( dev - > m2m_dev ) ;
goto err_m2m ;
}
return 0 ;
err_m2m :
2012-09-24 09:17:45 +04:00
v4l2_m2m_release ( dev - > m2m_dev ) ;
2015-03-09 19:33:56 +03:00
video_unregister_device ( & dev - > vfd ) ;
2010-04-23 12:38:38 +04:00
unreg_dev :
v4l2_device_unregister ( & dev - > v4l2_dev ) ;
return ret ;
}
2014-09-22 16:27:17 +04:00
static int vim2m_remove ( struct platform_device * pdev )
2010-04-23 12:38:38 +04:00
{
2014-09-22 16:27:17 +04:00
struct vim2m_dev * dev = platform_get_drvdata ( pdev ) ;
2010-04-23 12:38:38 +04:00
2014-09-22 16:27:17 +04:00
v4l2_info ( & dev - > v4l2_dev , " Removing " MEM2MEM_NAME ) ;
2010-04-23 12:38:38 +04:00
v4l2_m2m_release ( dev - > m2m_dev ) ;
del_timer_sync ( & dev - > timer ) ;
2015-03-09 19:33:56 +03:00
video_unregister_device ( & dev - > vfd ) ;
2010-04-23 12:38:38 +04:00
v4l2_device_unregister ( & dev - > v4l2_dev ) ;
return 0 ;
}
2014-09-22 16:27:17 +04:00
static struct platform_driver vim2m_pdrv = {
. probe = vim2m_probe ,
. remove = vim2m_remove ,
2010-04-23 12:38:38 +04:00
. driver = {
. name = MEM2MEM_NAME ,
} ,
} ;
2014-09-22 16:27:17 +04:00
static void __exit vim2m_exit ( void )
2010-04-23 12:38:38 +04:00
{
2014-09-22 16:27:17 +04:00
platform_driver_unregister ( & vim2m_pdrv ) ;
platform_device_unregister ( & vim2m_pdev ) ;
2010-04-23 12:38:38 +04:00
}
2014-09-22 16:27:17 +04:00
static int __init vim2m_init ( void )
2010-04-23 12:38:38 +04:00
{
int ret ;
2014-09-22 16:27:17 +04:00
ret = platform_device_register ( & vim2m_pdev ) ;
2010-04-23 12:38:38 +04:00
if ( ret )
return ret ;
2014-09-22 16:27:17 +04:00
ret = platform_driver_register ( & vim2m_pdrv ) ;
2010-04-23 12:38:38 +04:00
if ( ret )
2014-09-22 16:27:17 +04:00
platform_device_unregister ( & vim2m_pdev ) ;
2010-04-23 12:38:38 +04:00
2015-12-25 20:25:16 +03:00
return ret ;
2010-04-23 12:38:38 +04:00
}
2014-09-22 16:27:17 +04:00
module_init ( vim2m_init ) ;
module_exit ( vim2m_exit ) ;