2006-03-10 18:40:10 +03:00
/*
* Virtual Video driver - This code emulates a real video device with v4l2 api
*
* Copyright ( c ) 2006 by :
* Mauro Carvalho Chehab < mchehab - - a . t - - infradead . org >
* Ted Walther < ted - - a . t - - enumera . com >
* John Sokol < sokol - - a . t - - videotechnology . com >
* http : //v4l.videotechnology.com/
*
2011-01-19 18:02:29 +03:00
* Conversion to videobuf2 by Pawel Osciak & Marek Szyprowski
* Copyright ( c ) 2010 Samsung Electronics
*
2006-03-10 18:40:10 +03:00
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the BSD Licence , 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/errno.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/sched.h>
2010-05-07 22:22:26 +04:00
# include <linux/slab.h>
2010-04-10 11:13:53 +04:00
# include <linux/font.h>
2007-07-02 17:19:38 +04:00
# include <linux/mutex.h>
2006-03-10 18:40:10 +03:00
# include <linux/videodev2.h>
# include <linux/kthread.h>
2006-12-07 07:34:23 +03:00
# include <linux/freezer.h>
2011-01-19 18:02:29 +03:00
# include <media/videobuf2-vmalloc.h>
2009-02-14 19:23:12 +03:00
# include <media/v4l2-device.h>
# include <media/v4l2-ioctl.h>
2011-01-23 17:33:16 +03:00
# include <media/v4l2-ctrls.h>
2011-03-12 02:01:54 +03:00
# include <media/v4l2-fh.h>
2011-06-07 17:20:23 +04:00
# include <media/v4l2-event.h>
2010-04-10 11:13:53 +04:00
# include <media/v4l2-common.h>
2006-03-10 18:40:10 +03:00
2008-06-10 22:21:49 +04:00
# define VIVI_MODULE_NAME "vivi"
2008-06-10 07:02:32 +04:00
2006-03-10 18:40:10 +03:00
/* Wake up at about 30 fps */
# define WAKE_NUMERATOR 30
# define WAKE_DENOMINATOR 1001
# define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
2010-04-10 11:13:53 +04:00
# define MAX_WIDTH 1920
# define MAX_HEIGHT 1200
[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
# define VIVI_VERSION "0.8.1"
2006-03-10 18:40:10 +03:00
2009-02-14 19:23:12 +03:00
MODULE_DESCRIPTION ( " Video Technology Magazine Virtual Video Capture Board " ) ;
MODULE_AUTHOR ( " Mauro Carvalho Chehab, Ted Walther and John Sokol " ) ;
MODULE_LICENSE ( " Dual BSD/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 ( VIVI_VERSION ) ;
2009-02-14 19:23:12 +03:00
static unsigned video_nr = - 1 ;
module_param ( video_nr , uint , 0644 ) ;
MODULE_PARM_DESC ( video_nr , " videoX start number, -1 is autodetect " ) ;
static unsigned n_devs = 1 ;
module_param ( n_devs , uint , 0644 ) ;
MODULE_PARM_DESC ( n_devs , " number of video devices to create " ) ;
static unsigned debug ;
module_param ( debug , uint , 0644 ) ;
MODULE_PARM_DESC ( debug , " activates debug info " ) ;
static unsigned int vid_limit = 16 ;
module_param ( vid_limit , uint , 0644 ) ;
MODULE_PARM_DESC ( vid_limit , " capture memory limit in megabytes " ) ;
2010-04-10 11:13:53 +04:00
/* Global font descriptor */
static const u8 * font8x16 ;
2006-03-10 18:40:10 +03:00
2009-02-14 19:23:12 +03:00
# define dprintk(dev, level, fmt, arg...) \
v4l2_dbg ( level , debug , & dev - > v4l2_dev , fmt , # # arg )
2006-03-10 18:40:10 +03:00
/* ------------------------------------------------------------------
Basic structures
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
struct vivi_fmt {
char * name ;
u32 fourcc ; /* v4l2 format id */
int depth ;
} ;
2008-10-14 19:47:09 +04:00
static struct vivi_fmt formats [ ] = {
{
. name = " 4:2:2, packed, YUYV " ,
. fourcc = V4L2_PIX_FMT_YUYV ,
. depth = 16 ,
} ,
2008-10-14 19:47:25 +04:00
{
. name = " 4:2:2, packed, UYVY " ,
. fourcc = V4L2_PIX_FMT_UYVY ,
. depth = 16 ,
} ,
2008-10-14 19:47:35 +04:00
{
. name = " RGB565 (LE) " ,
. fourcc = V4L2_PIX_FMT_RGB565 , /* gggbbbbb rrrrrggg */
. depth = 16 ,
} ,
{
. name = " RGB565 (BE) " ,
. fourcc = V4L2_PIX_FMT_RGB565X , /* rrrrrggg gggbbbbb */
. depth = 16 ,
} ,
2008-10-14 19:47:43 +04:00
{
. name = " RGB555 (LE) " ,
. fourcc = V4L2_PIX_FMT_RGB555 , /* gggbbbbb arrrrrgg */
. depth = 16 ,
} ,
{
. name = " RGB555 (BE) " ,
. fourcc = V4L2_PIX_FMT_RGB555X , /* arrrrrgg gggbbbbb */
. depth = 16 ,
} ,
2006-03-10 18:40:10 +03:00
} ;
2008-10-14 19:47:09 +04:00
static struct vivi_fmt * get_format ( struct v4l2_format * f )
{
struct vivi_fmt * fmt ;
unsigned int k ;
for ( k = 0 ; k < ARRAY_SIZE ( formats ) ; k + + ) {
fmt = & formats [ k ] ;
if ( fmt - > fourcc = = f - > fmt . pix . pixelformat )
break ;
}
if ( k = = ARRAY_SIZE ( formats ) )
return NULL ;
return & formats [ k ] ;
}
2006-03-10 18:40:10 +03:00
/* buffer for one video frame */
struct vivi_buffer {
/* common v4l buffer stuff -- must be first */
2011-01-19 18:02:29 +03:00
struct vb2_buffer vb ;
struct list_head list ;
2006-03-10 18:40:10 +03:00
struct vivi_fmt * fmt ;
} ;
struct vivi_dmaqueue {
struct list_head active ;
/* thread for generating video stream*/
struct task_struct * kthread ;
wait_queue_head_t wq ;
/* Counters to control fps rate */
int frame ;
int ini_jiffies ;
} ;
static LIST_HEAD ( vivi_devlist ) ;
struct vivi_dev {
struct list_head vivi_devlist ;
2009-02-14 19:23:12 +03:00
struct v4l2_device v4l2_dev ;
2011-01-23 17:33:16 +03:00
struct v4l2_ctrl_handler ctrl_handler ;
2006-03-10 18:40:10 +03:00
2010-04-10 11:13:53 +04:00
/* controls */
2011-01-23 17:33:16 +03:00
struct v4l2_ctrl * brightness ;
struct v4l2_ctrl * contrast ;
struct v4l2_ctrl * saturation ;
struct v4l2_ctrl * hue ;
2011-06-07 13:34:41 +04:00
struct {
/* autogain/gain cluster */
struct v4l2_ctrl * autogain ;
struct v4l2_ctrl * gain ;
} ;
2011-01-23 17:33:16 +03:00
struct v4l2_ctrl * volume ;
struct v4l2_ctrl * button ;
struct v4l2_ctrl * boolean ;
struct v4l2_ctrl * int32 ;
struct v4l2_ctrl * int64 ;
struct v4l2_ctrl * menu ;
struct v4l2_ctrl * string ;
2011-03-29 23:33:11 +04:00
struct v4l2_ctrl * bitmask ;
2010-04-10 11:13:53 +04:00
2007-12-13 22:13:37 +03:00
spinlock_t slock ;
2008-04-03 01:10:59 +04:00
struct mutex mutex ;
2006-03-10 18:40:10 +03:00
/* various device info */
2007-12-10 10:07:03 +03:00
struct video_device * vfd ;
2006-03-10 18:40:10 +03:00
struct vivi_dmaqueue vidq ;
/* Several counters */
2010-04-10 11:13:53 +04:00
unsigned ms ;
2008-01-14 01:36:11 +03:00
unsigned long jiffies ;
2011-01-23 17:33:16 +03:00
unsigned button_pressed ;
2007-12-10 10:43:38 +03:00
int mv_count ; /* Controls bars movement */
2009-01-11 16:29:43 +03:00
/* Input Number */
int input ;
2009-02-14 19:43:44 +03:00
2006-03-10 18:40:10 +03:00
/* video capture */
struct vivi_fmt * fmt ;
2007-12-10 15:33:52 +03:00
unsigned int width , height ;
2011-01-19 18:02:29 +03:00
struct vb2_queue vb_vidq ;
enum v4l2_field field ;
unsigned int field_count ;
2006-03-10 18:40:10 +03:00
2010-04-10 11:13:53 +04:00
u8 bars [ 9 ] [ 3 ] ;
u8 line [ MAX_WIDTH * 4 ] ;
2006-03-10 18:40:10 +03:00
} ;
/* ------------------------------------------------------------------
DMA and thread functions
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Bars and Colors should match positions */
enum colors {
WHITE ,
2010-04-10 11:13:53 +04:00
AMBER ,
2006-03-10 18:40:10 +03:00
CYAN ,
GREEN ,
MAGENTA ,
RED ,
2007-12-10 15:33:52 +03:00
BLUE ,
BLACK ,
2010-04-10 11:13:53 +04:00
TEXT_BLACK ,
2006-03-10 18:40:10 +03:00
} ;
2010-04-10 11:13:53 +04:00
/* R G B */
2009-01-11 16:29:43 +03:00
# define COLOR_WHITE {204, 204, 204}
2010-04-10 11:13:53 +04:00
# define COLOR_AMBER {208, 208, 0}
# define COLOR_CYAN { 0, 206, 206}
2009-01-11 16:29:43 +03:00
# define COLOR_GREEN { 0, 239, 0}
# define COLOR_MAGENTA {239, 0, 239}
# define COLOR_RED {205, 0, 0}
# define COLOR_BLUE { 0, 0, 255}
# define COLOR_BLACK { 0, 0, 0}
struct bar_std {
2010-04-10 11:13:53 +04:00
u8 bar [ 9 ] [ 3 ] ;
2009-01-11 16:29:43 +03:00
} ;
/* Maximum number of bars are 10 - otherwise, the input print code
should be modified */
static struct bar_std bars [ ] = {
{ /* Standard ITU-R color bar sequence */
2010-04-10 11:13:53 +04:00
{ COLOR_WHITE , COLOR_AMBER , COLOR_CYAN , COLOR_GREEN ,
COLOR_MAGENTA , COLOR_RED , COLOR_BLUE , COLOR_BLACK , COLOR_BLACK }
2009-01-11 16:29:43 +03:00
} , {
2010-04-10 11:13:53 +04:00
{ COLOR_WHITE , COLOR_AMBER , COLOR_BLACK , COLOR_WHITE ,
COLOR_AMBER , COLOR_BLACK , COLOR_WHITE , COLOR_AMBER , COLOR_BLACK }
2009-01-11 16:29:43 +03:00
} , {
2010-04-10 11:13:53 +04:00
{ COLOR_WHITE , COLOR_CYAN , COLOR_BLACK , COLOR_WHITE ,
COLOR_CYAN , COLOR_BLACK , COLOR_WHITE , COLOR_CYAN , COLOR_BLACK }
2009-01-11 16:29:43 +03:00
} , {
2010-04-10 11:13:53 +04:00
{ COLOR_WHITE , COLOR_GREEN , COLOR_BLACK , COLOR_WHITE ,
COLOR_GREEN , COLOR_BLACK , COLOR_WHITE , COLOR_GREEN , COLOR_BLACK }
2009-01-11 16:29:43 +03:00
} ,
2006-03-10 18:40:10 +03:00
} ;
2009-01-11 16:29:43 +03:00
# define NUM_INPUTS ARRAY_SIZE(bars)
2007-12-10 15:33:52 +03:00
# define TO_Y(r, g, b) \
( ( ( 16829 * r + 33039 * g + 6416 * b + 32768 ) > > 16 ) + 16 )
2006-03-10 18:40:10 +03:00
/* RGB to V(Cr) Color transform */
2007-12-10 15:33:52 +03:00
# define TO_V(r, g, b) \
( ( ( 28784 * r - 24103 * g - 4681 * b + 32768 ) > > 16 ) + 128 )
2006-03-10 18:40:10 +03:00
/* RGB to U(Cb) Color transform */
2007-12-10 15:33:52 +03:00
# define TO_U(r, g, b) \
( ( ( - 9714 * r - 19070 * g + 28784 * b + 32768 ) > > 16 ) + 128 )
2006-03-10 18:40:10 +03:00
2009-06-25 23:28:23 +04:00
/* precalculate color bar values to speed up rendering */
2010-04-10 11:13:53 +04:00
static void precalculate_bars ( struct vivi_dev * dev )
2009-06-25 23:28:23 +04:00
{
2010-04-10 11:13:53 +04:00
u8 r , g , b ;
2009-06-25 23:28:23 +04:00
int k , is_yuv ;
2010-04-10 11:13:53 +04:00
for ( k = 0 ; k < 9 ; k + + ) {
r = bars [ dev - > input ] . bar [ k ] [ 0 ] ;
g = bars [ dev - > input ] . bar [ k ] [ 1 ] ;
b = bars [ dev - > input ] . bar [ k ] [ 2 ] ;
2009-06-25 23:28:23 +04:00
is_yuv = 0 ;
2010-04-10 11:13:53 +04:00
switch ( dev - > fmt - > fourcc ) {
2009-06-25 23:28:23 +04:00
case V4L2_PIX_FMT_YUYV :
case V4L2_PIX_FMT_UYVY :
is_yuv = 1 ;
break ;
case V4L2_PIX_FMT_RGB565 :
case V4L2_PIX_FMT_RGB565X :
r > > = 3 ;
g > > = 2 ;
b > > = 3 ;
break ;
case V4L2_PIX_FMT_RGB555 :
case V4L2_PIX_FMT_RGB555X :
r > > = 3 ;
g > > = 3 ;
b > > = 3 ;
break ;
}
if ( is_yuv ) {
2010-04-10 11:13:53 +04:00
dev - > bars [ k ] [ 0 ] = TO_Y ( r , g , b ) ; /* Luma */
dev - > bars [ k ] [ 1 ] = TO_U ( r , g , b ) ; /* Cb */
dev - > bars [ k ] [ 2 ] = TO_V ( r , g , b ) ; /* Cr */
2009-06-25 23:28:23 +04:00
} else {
2010-04-10 11:13:53 +04:00
dev - > bars [ k ] [ 0 ] = r ;
dev - > bars [ k ] [ 1 ] = g ;
dev - > bars [ k ] [ 2 ] = b ;
2009-06-25 23:28:23 +04:00
}
}
}
2009-01-11 16:29:43 +03:00
# define TSTAMP_MIN_Y 24
# define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
# define TSTAMP_INPUT_X 10
# define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X)
2006-03-10 18:40:10 +03:00
2010-04-10 11:13:53 +04:00
static void gen_twopix ( struct vivi_dev * dev , u8 * buf , int colorpos )
2008-10-14 19:46:59 +04:00
{
2010-04-10 11:13:53 +04:00
u8 r_y , g_u , b_v ;
2008-10-14 19:46:59 +04:00
int color ;
2010-04-10 11:13:53 +04:00
u8 * p ;
2008-10-14 19:46:59 +04:00
2010-04-10 11:13:53 +04:00
r_y = dev - > bars [ colorpos ] [ 0 ] ; /* R or precalculated Y */
g_u = dev - > bars [ colorpos ] [ 1 ] ; /* G or precalculated U */
b_v = dev - > bars [ colorpos ] [ 2 ] ; /* B or precalculated V */
2008-10-14 19:46:59 +04:00
for ( color = 0 ; color < 4 ; color + + ) {
p = buf + color ;
2010-04-10 11:13:53 +04:00
switch ( dev - > fmt - > fourcc ) {
2008-10-14 19:47:09 +04:00
case V4L2_PIX_FMT_YUYV :
switch ( color ) {
case 0 :
case 2 :
* p = r_y ;
break ;
case 1 :
* p = g_u ;
break ;
case 3 :
* p = b_v ;
break ;
}
2008-10-14 19:46:59 +04:00
break ;
2008-10-14 19:47:25 +04:00
case V4L2_PIX_FMT_UYVY :
switch ( color ) {
case 1 :
case 3 :
* p = r_y ;
break ;
case 0 :
* p = g_u ;
break ;
case 2 :
* p = b_v ;
break ;
}
break ;
2008-10-14 19:47:35 +04:00
case V4L2_PIX_FMT_RGB565 :
switch ( color ) {
case 0 :
case 2 :
* p = ( g_u < < 5 ) | b_v ;
break ;
case 1 :
case 3 :
* p = ( r_y < < 3 ) | ( g_u > > 3 ) ;
break ;
}
break ;
case V4L2_PIX_FMT_RGB565X :
switch ( color ) {
case 0 :
case 2 :
* p = ( r_y < < 3 ) | ( g_u > > 3 ) ;
break ;
case 1 :
case 3 :
* p = ( g_u < < 5 ) | b_v ;
break ;
}
break ;
2008-10-14 19:47:43 +04:00
case V4L2_PIX_FMT_RGB555 :
switch ( color ) {
case 0 :
case 2 :
* p = ( g_u < < 5 ) | b_v ;
break ;
case 1 :
case 3 :
* p = ( r_y < < 2 ) | ( g_u > > 3 ) ;
break ;
}
break ;
case V4L2_PIX_FMT_RGB555X :
switch ( color ) {
case 0 :
case 2 :
* p = ( r_y < < 2 ) | ( g_u > > 3 ) ;
break ;
case 1 :
case 3 :
* p = ( g_u < < 5 ) | b_v ;
break ;
}
break ;
2008-10-14 19:46:59 +04:00
}
}
}
2010-04-10 11:13:53 +04:00
static void precalculate_line ( struct vivi_dev * dev )
2006-03-10 18:40:10 +03:00
{
2010-04-10 11:13:53 +04:00
int w ;
2006-03-10 18:40:10 +03:00
2010-04-10 11:13:53 +04:00
for ( w = 0 ; w < dev - > width * 2 ; w + = 2 ) {
int colorpos = ( w / ( dev - > width / 8 ) % 8 ) ;
2008-10-14 19:46:59 +04:00
2010-04-10 11:13:53 +04:00
gen_twopix ( dev , dev - > line + w * 2 , colorpos ) ;
2006-03-10 18:40:10 +03:00
}
2010-04-10 11:13:53 +04:00
}
2006-03-10 18:40:10 +03:00
2010-04-10 11:13:53 +04:00
static void gen_text ( struct vivi_dev * dev , char * basep ,
int y , int x , char * text )
{
int line ;
2009-01-11 16:29:43 +03:00
2010-04-10 11:13:53 +04:00
/* Checks if it is possible to show string */
if ( y + 16 > = dev - > height | | x + strlen ( text ) * 8 > = dev - > width )
return ;
2006-03-10 18:40:10 +03:00
/* Print stream time */
2010-04-10 11:13:53 +04:00
for ( line = y ; line < y + 16 ; line + + ) {
int j = 0 ;
char * pos = basep + line * dev - > width * 2 + x * 2 ;
char * s ;
for ( s = text ; * s ; s + + ) {
u8 chr = font8x16 [ * s * 16 + line - y ] ;
int i ;
for ( i = 0 ; i < 7 ; i + + , j + + ) {
2008-10-14 19:46:59 +04:00
/* Draw white font on black background */
2010-04-10 11:13:53 +04:00
if ( chr & ( 1 < < ( 7 - i ) ) )
gen_twopix ( dev , pos + j * 2 , WHITE ) ;
2008-10-14 19:46:59 +04:00
else
2010-04-10 11:13:53 +04:00
gen_twopix ( dev , pos + j * 2 , TEXT_BLACK ) ;
2006-03-10 18:40:10 +03:00
}
}
}
}
2008-04-03 01:10:59 +04:00
2010-04-10 11:13:53 +04:00
static void vivi_fillbuff ( struct vivi_dev * dev , struct vivi_buffer * buf )
2006-03-10 18:40:10 +03:00
{
2011-01-19 18:02:29 +03:00
int wmax = dev - > width ;
int hmax = dev - > height ;
2006-03-10 18:40:10 +03:00
struct timeval ts ;
2011-01-19 18:02:29 +03:00
void * vbuf = vb2_plane_vaddr ( & buf - > vb , 0 ) ;
2010-04-10 11:13:53 +04:00
unsigned ms ;
char str [ 100 ] ;
int h , line = 1 ;
2011-06-07 13:34:41 +04:00
s32 gain ;
2007-01-25 11:00:01 +03:00
2008-06-22 16:11:40 +04:00
if ( ! vbuf )
2007-08-03 06:31:54 +04:00
return ;
2006-03-10 18:40:10 +03:00
2010-04-10 11:13:53 +04:00
for ( h = 0 ; h < hmax ; h + + )
memcpy ( vbuf + h * wmax * 2 , dev - > line + ( dev - > mv_count % wmax ) * 2 , wmax * 2 ) ;
2007-08-03 06:31:54 +04:00
2006-03-10 18:40:10 +03:00
/* Updates stream time */
2010-04-10 11:13:53 +04:00
dev - > ms + = jiffies_to_msecs ( jiffies - dev - > jiffies ) ;
2007-12-10 15:33:52 +03:00
dev - > jiffies = jiffies ;
2010-04-10 11:13:53 +04:00
ms = dev - > ms ;
snprintf ( str , sizeof ( str ) , " %02d:%02d:%02d:%03d " ,
( ms / ( 60 * 60 * 1000 ) ) % 24 ,
( ms / ( 60 * 1000 ) ) % 60 ,
( ms / 1000 ) % 60 ,
ms % 1000 ) ;
gen_text ( dev , vbuf , line + + * 16 , 16 , str ) ;
snprintf ( str , sizeof ( str ) , " %dx%d, input %d " ,
dev - > width , dev - > height , dev - > input ) ;
gen_text ( dev , vbuf , line + + * 16 , 16 , str ) ;
2011-06-07 13:34:41 +04:00
gain = v4l2_ctrl_g_ctrl ( dev - > gain ) ;
2011-01-23 17:33:16 +03:00
mutex_lock ( & dev - > ctrl_handler . lock ) ;
2010-04-10 11:13:53 +04:00
snprintf ( str , sizeof ( str ) , " brightness %3d, contrast %3d, saturation %3d, hue %d " ,
2011-01-23 17:33:16 +03:00
dev - > brightness - > cur . val ,
dev - > contrast - > cur . val ,
dev - > saturation - > cur . val ,
dev - > hue - > cur . val ) ;
2010-04-10 11:13:53 +04:00
gen_text ( dev , vbuf , line + + * 16 , 16 , str ) ;
2011-06-07 13:34:41 +04:00
snprintf ( str , sizeof ( str ) , " autogain %d, gain %3d, volume %3d " ,
dev - > autogain - > cur . val , gain , dev - > volume - > cur . val ) ;
2010-04-10 11:13:53 +04:00
gen_text ( dev , vbuf , line + + * 16 , 16 , str ) ;
2011-03-29 23:33:11 +04:00
snprintf ( str , sizeof ( str ) , " int32 %d, int64 %lld, bitmask %08x " ,
2011-01-23 17:33:16 +03:00
dev - > int32 - > cur . val ,
2011-03-29 23:33:11 +04:00
dev - > int64 - > cur . val64 ,
dev - > bitmask - > cur . val ) ;
2011-01-23 17:33:16 +03:00
gen_text ( dev , vbuf , line + + * 16 , 16 , str ) ;
snprintf ( str , sizeof ( str ) , " boolean %d, menu %s, string \" %s \" " ,
dev - > boolean - > cur . val ,
dev - > menu - > qmenu [ dev - > menu - > cur . val ] ,
dev - > string - > cur . string ) ;
mutex_unlock ( & dev - > ctrl_handler . lock ) ;
gen_text ( dev , vbuf , line + + * 16 , 16 , str ) ;
if ( dev - > button_pressed ) {
dev - > button_pressed - - ;
snprintf ( str , sizeof ( str ) , " button pressed! " ) ;
gen_text ( dev , vbuf , line + + * 16 , 16 , str ) ;
}
2010-04-10 11:13:53 +04:00
dev - > mv_count + = 2 ;
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
buf - > vb . v4l2_buf . field = dev - > field ;
dev - > field_count + + ;
buf - > vb . v4l2_buf . sequence = dev - > field_count > > 1 ;
2006-03-10 18:40:10 +03:00
do_gettimeofday ( & ts ) ;
2011-01-19 18:02:29 +03:00
buf - > vb . v4l2_buf . timestamp = ts ;
2006-03-10 18:40:10 +03:00
}
2010-04-10 11:13:53 +04:00
static void vivi_thread_tick ( struct vivi_dev * dev )
2006-03-10 18:40:10 +03:00
{
2008-04-03 01:10:59 +04:00
struct vivi_dmaqueue * dma_q = & dev - > vidq ;
2010-04-10 11:13:53 +04:00
struct vivi_buffer * buf ;
2008-04-03 01:10:59 +04:00
unsigned long flags = 0 ;
2006-03-10 18:40:10 +03:00
2008-04-03 01:10:59 +04:00
dprintk ( dev , 1 , " Thread tick \n " ) ;
2006-03-10 18:40:10 +03:00
2008-04-03 01:10:59 +04:00
spin_lock_irqsave ( & dev - > slock , flags ) ;
if ( list_empty ( & dma_q - > active ) ) {
dprintk ( dev , 1 , " No active queue to serve \n " ) ;
2011-07-05 14:19:23 +04:00
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
return ;
2008-04-03 01:10:59 +04:00
}
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
buf = list_entry ( dma_q - > active . next , struct vivi_buffer , list ) ;
list_del ( & buf - > list ) ;
2011-07-05 14:19:23 +04:00
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
do_gettimeofday ( & buf - > vb . v4l2_buf . timestamp ) ;
2008-04-03 01:10:59 +04:00
/* Fill buffer */
2010-04-10 11:13:53 +04:00
vivi_fillbuff ( dev , buf ) ;
2008-04-03 01:10:59 +04:00
dprintk ( dev , 1 , " filled buffer %p \n " , buf ) ;
2011-01-19 18:02:29 +03:00
vb2_buffer_done ( & buf - > vb , VB2_BUF_STATE_DONE ) ;
dprintk ( dev , 2 , " [%p/%d] done \n " , buf , buf - > vb . v4l2_buf . index ) ;
2006-03-10 18:40:10 +03:00
}
2007-12-13 22:15:41 +03:00
# define frames_to_ms(frames) \
( ( frames * WAKE_NUMERATOR * 1000 ) / WAKE_DENOMINATOR )
2010-04-10 11:13:53 +04:00
static void vivi_sleep ( struct vivi_dev * dev )
2006-03-10 18:40:10 +03:00
{
2008-04-03 01:10:59 +04:00
struct vivi_dmaqueue * dma_q = & dev - > vidq ;
int timeout ;
2006-03-10 18:40:10 +03:00
DECLARE_WAITQUEUE ( wait , current ) ;
2008-04-09 06:20:00 +04:00
dprintk ( dev , 1 , " %s dma_q=0x%08lx \n " , __func__ ,
2007-12-13 19:30:14 +03:00
( unsigned long ) dma_q ) ;
2006-03-10 18:40:10 +03:00
add_wait_queue ( & dma_q - > wq , & wait ) ;
2007-12-13 22:15:41 +03:00
if ( kthread_should_stop ( ) )
goto stop_task ;
/* Calculate time to wake up */
2008-04-03 01:10:59 +04:00
timeout = msecs_to_jiffies ( frames_to_ms ( 1 ) ) ;
2007-12-13 22:15:41 +03:00
2010-04-10 11:13:53 +04:00
vivi_thread_tick ( dev ) ;
2007-12-13 22:15:41 +03:00
schedule_timeout_interruptible ( timeout ) ;
2006-03-10 18:40:10 +03:00
2007-12-13 22:15:41 +03:00
stop_task :
2006-03-10 18:40:10 +03:00
remove_wait_queue ( & dma_q - > wq , & wait ) ;
try_to_freeze ( ) ;
}
2006-04-28 04:06:50 +04:00
static int vivi_thread ( void * data )
2006-03-10 18:40:10 +03:00
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = data ;
2006-03-10 18:40:10 +03:00
2007-12-13 19:30:14 +03:00
dprintk ( dev , 1 , " thread started \n " ) ;
2006-03-10 18:40:10 +03:00
2007-07-17 15:03:35 +04:00
set_freezable ( ) ;
2007-01-14 14:33:24 +03:00
2006-03-10 18:40:10 +03:00
for ( ; ; ) {
2010-04-10 11:13:53 +04:00
vivi_sleep ( dev ) ;
2006-03-10 18:40:10 +03:00
if ( kthread_should_stop ( ) )
break ;
}
2007-12-13 19:30:14 +03:00
dprintk ( dev , 1 , " thread: exit \n " ) ;
2006-03-10 18:40:10 +03:00
return 0 ;
}
2011-01-19 18:02:29 +03:00
static int vivi_start_generating ( struct vivi_dev * dev )
2006-03-10 18:40:10 +03:00
{
2008-04-03 01:10:59 +04:00
struct vivi_dmaqueue * dma_q = & dev - > vidq ;
2007-12-13 19:30:14 +03:00
2008-04-09 06:20:00 +04:00
dprintk ( dev , 1 , " %s \n " , __func__ ) ;
2006-03-10 18:40:10 +03:00
2010-04-10 11:13:53 +04:00
/* Resets frame counters */
dev - > ms = 0 ;
dev - > mv_count = 0 ;
dev - > jiffies = jiffies ;
dma_q - > frame = 0 ;
dma_q - > ini_jiffies = jiffies ;
dma_q - > kthread = kthread_run ( vivi_thread , dev , dev - > v4l2_dev . name ) ;
2006-03-10 18:40:10 +03:00
2006-12-20 16:04:00 +03:00
if ( IS_ERR ( dma_q - > kthread ) ) {
2009-02-14 19:23:12 +03:00
v4l2_err ( & dev - > v4l2_dev , " kernel_thread() failed \n " ) ;
2011-01-19 18:02:29 +03:00
return PTR_ERR ( dma_q - > kthread ) ;
2006-03-10 18:40:10 +03:00
}
2007-01-14 14:33:24 +03:00
/* Wakes thread */
wake_up_interruptible ( & dma_q - > wq ) ;
2008-04-09 06:20:00 +04:00
dprintk ( dev , 1 , " returning from %s \n " , __func__ ) ;
2011-01-19 18:02:29 +03:00
return 0 ;
2006-03-10 18:40:10 +03:00
}
2011-01-19 18:02:29 +03:00
static void vivi_stop_generating ( struct vivi_dev * dev )
2006-03-10 18:40:10 +03:00
{
2010-04-10 11:13:53 +04:00
struct vivi_dmaqueue * dma_q = & dev - > vidq ;
2007-12-13 19:30:14 +03:00
2008-04-09 06:20:00 +04:00
dprintk ( dev , 1 , " %s \n " , __func__ ) ;
2010-04-10 11:13:53 +04:00
2006-03-10 18:40:10 +03:00
/* shutdown control thread */
if ( dma_q - > kthread ) {
kthread_stop ( dma_q - > kthread ) ;
2007-12-10 15:33:52 +03:00
dma_q - > kthread = NULL ;
2006-03-10 18:40:10 +03:00
}
2010-04-10 11:13:53 +04:00
2011-01-19 18:02:29 +03:00
/*
* 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 vivi_buffer * buf ;
buf = list_entry ( dma_q - > active . next , struct vivi_buffer , list ) ;
list_del ( & buf - > list ) ;
vb2_buffer_done ( & buf - > vb , VB2_BUF_STATE_ERROR ) ;
dprintk ( dev , 2 , " [%p/%d] done \n " , buf , buf - > vb . v4l2_buf . index ) ;
}
2006-03-10 18:40:10 +03:00
}
/* ------------------------------------------------------------------
Videobuf operations
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2011-08-24 17:30:21 +04:00
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 [ ] )
2006-03-10 18:40:10 +03:00
{
2011-01-19 18:02:29 +03:00
struct vivi_dev * dev = vb2_get_drv_priv ( vq ) ;
unsigned long size ;
size = dev - > width * dev - > height * 2 ;
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
if ( 0 = = * nbuffers )
* nbuffers = 32 ;
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
while ( size * * nbuffers > vid_limit * 1024 * 1024 )
( * nbuffers ) - - ;
2007-08-23 23:41:14 +04:00
2011-01-19 18:02:29 +03:00
* nplanes = 1 ;
2007-08-23 23:41:14 +04:00
2011-01-19 18:02:29 +03:00
sizes [ 0 ] = size ;
/*
* videobuf2 - vmalloc allocator is context - less so no need to set
* alloc_ctxs array .
*/
dprintk ( dev , 1 , " %s, count=%d, size=%ld \n " , __func__ ,
* nbuffers , size ) ;
2007-08-23 23:41:14 +04:00
2006-03-10 18:40:10 +03:00
return 0 ;
}
2011-01-19 18:02:29 +03:00
static int buffer_init ( struct vb2_buffer * vb )
2006-03-10 18:40:10 +03:00
{
2011-01-19 18:02:29 +03:00
struct vivi_dev * dev = vb2_get_drv_priv ( vb - > vb2_queue ) ;
2007-12-13 19:30:14 +03:00
2011-01-19 18:02:29 +03:00
BUG_ON ( NULL = = dev - > fmt ) ;
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
/*
* This callback is called once per buffer , after its allocation .
*
* Vivi does not allow changing format during streaming , but it is
* possible to do so when streaming is paused ( i . e . in streamoff state ) .
* Buffers however are not freed when going into streamoff and so
* buffer size verification has to be done in buffer_prepare , on each
* qbuf .
* It would be best to move verification code here to buf_init and
* s_fmt though .
*/
return 0 ;
2006-03-10 18:40:10 +03:00
}
2011-01-19 18:02:29 +03:00
static int buffer_prepare ( struct vb2_buffer * vb )
2006-03-10 18:40:10 +03:00
{
2011-01-19 18:02:29 +03:00
struct vivi_dev * dev = vb2_get_drv_priv ( vb - > vb2_queue ) ;
2007-12-10 15:33:52 +03:00
struct vivi_buffer * buf = container_of ( vb , struct vivi_buffer , vb ) ;
2011-01-19 18:02:29 +03:00
unsigned long size ;
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
dprintk ( dev , 1 , " %s, field=%d \n " , __func__ , vb - > v4l2_buf . field ) ;
2006-03-10 18:40:10 +03:00
2010-04-10 11:13:53 +04:00
BUG_ON ( NULL = = dev - > fmt ) ;
2008-04-03 01:10:59 +04:00
2011-01-19 18:02:29 +03:00
/*
* 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 .
*/
2010-04-10 11:13:53 +04:00
if ( dev - > width < 48 | | dev - > width > MAX_WIDTH | |
dev - > height < 32 | | dev - > height > MAX_HEIGHT )
2006-03-10 18:40:10 +03:00
return - EINVAL ;
2008-04-03 01:10:59 +04:00
2011-01-19 18:02:29 +03:00
size = dev - > width * dev - > height * 2 ;
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 ) ;
2006-03-10 18:40:10 +03:00
return - EINVAL ;
2011-01-19 18:02:29 +03:00
}
vb2_set_plane_payload ( & buf - > vb , 0 , size ) ;
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
buf - > fmt = dev - > fmt ;
2006-03-10 18:40:10 +03:00
2010-04-10 11:13:53 +04:00
precalculate_bars ( dev ) ;
precalculate_line ( dev ) ;
2009-06-25 23:28:23 +04:00
2011-01-19 18:02:29 +03:00
return 0 ;
}
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
static int buffer_finish ( struct vb2_buffer * vb )
{
struct vivi_dev * dev = vb2_get_drv_priv ( vb - > vb2_queue ) ;
dprintk ( dev , 1 , " %s \n " , __func__ ) ;
2006-03-10 18:40:10 +03:00
return 0 ;
2011-01-19 18:02:29 +03:00
}
static void buffer_cleanup ( struct vb2_buffer * vb )
{
struct vivi_dev * dev = vb2_get_drv_priv ( vb - > vb2_queue ) ;
dprintk ( dev , 1 , " %s \n " , __func__ ) ;
2006-03-10 18:40:10 +03:00
}
2011-01-19 18:02:29 +03:00
static void buffer_queue ( struct vb2_buffer * vb )
2006-03-10 18:40:10 +03:00
{
2011-01-19 18:02:29 +03:00
struct vivi_dev * dev = vb2_get_drv_priv ( vb - > vb2_queue ) ;
2010-04-10 11:13:53 +04:00
struct vivi_buffer * buf = container_of ( vb , struct vivi_buffer , vb ) ;
2008-04-03 01:10:59 +04:00
struct vivi_dmaqueue * vidq = & dev - > vidq ;
2011-01-19 18:02:29 +03:00
unsigned long flags = 0 ;
2008-04-03 01:10:59 +04:00
2008-04-09 06:20:00 +04:00
dprintk ( dev , 1 , " %s \n " , __func__ ) ;
2008-04-03 01:10:59 +04:00
2011-01-19 18:02:29 +03:00
spin_lock_irqsave ( & dev - > slock , flags ) ;
list_add_tail ( & buf - > list , & vidq - > active ) ;
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
2006-03-10 18:40:10 +03:00
}
2011-08-29 15:51:49 +04:00
static int start_streaming ( struct vb2_queue * vq , unsigned int count )
2006-03-10 18:40:10 +03:00
{
2011-01-19 18:02:29 +03:00
struct vivi_dev * dev = vb2_get_drv_priv ( vq ) ;
dprintk ( dev , 1 , " %s \n " , __func__ ) ;
return vivi_start_generating ( dev ) ;
}
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
/* abort streaming and wait for last buffer */
static int stop_streaming ( struct vb2_queue * vq )
{
struct vivi_dev * dev = vb2_get_drv_priv ( vq ) ;
2008-04-09 06:20:00 +04:00
dprintk ( dev , 1 , " %s \n " , __func__ ) ;
2011-01-19 18:02:29 +03:00
vivi_stop_generating ( dev ) ;
return 0 ;
}
static void vivi_lock ( struct vb2_queue * vq )
{
struct vivi_dev * dev = vb2_get_drv_priv ( vq ) ;
mutex_lock ( & dev - > mutex ) ;
}
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
static void vivi_unlock ( struct vb2_queue * vq )
{
struct vivi_dev * dev = vb2_get_drv_priv ( vq ) ;
mutex_unlock ( & dev - > mutex ) ;
2006-03-10 18:40:10 +03:00
}
2011-01-19 18:02:29 +03:00
static struct vb2_ops vivi_video_qops = {
. queue_setup = queue_setup ,
. buf_init = buffer_init ,
. buf_prepare = buffer_prepare ,
. buf_finish = buffer_finish ,
. buf_cleanup = buffer_cleanup ,
. buf_queue = buffer_queue ,
. start_streaming = start_streaming ,
. stop_streaming = stop_streaming ,
. wait_prepare = vivi_unlock ,
. wait_finish = vivi_lock ,
2006-03-10 18:40:10 +03:00
} ;
2006-06-04 17:34:12 +04:00
/* ------------------------------------------------------------------
IOCTL vidioc handling
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2007-12-10 15:33:52 +03:00
static int vidioc_querycap ( struct file * file , void * priv ,
2006-06-04 17:34:12 +04:00
struct v4l2_capability * cap )
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2009-02-14 19:23:12 +03:00
2006-06-04 17:34:12 +04:00
strcpy ( cap - > driver , " vivi " ) ;
strcpy ( cap - > card , " vivi " ) ;
2009-02-14 19:23:12 +03:00
strlcpy ( cap - > bus_info , dev - > v4l2_dev . name , sizeof ( cap - > bus_info ) ) ;
2010-04-10 11:13:53 +04:00
cap - > capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \
V4L2_CAP_READWRITE ;
2006-06-04 17:34:12 +04:00
return 0 ;
}
2008-05-28 19:16:41 +04:00
static int vidioc_enum_fmt_vid_cap ( struct file * file , void * priv ,
2006-06-04 17:34:12 +04:00
struct v4l2_fmtdesc * f )
{
2008-10-14 19:47:09 +04:00
struct vivi_fmt * fmt ;
if ( f - > index > = ARRAY_SIZE ( formats ) )
2006-06-04 17:34:12 +04:00
return - EINVAL ;
2008-10-14 19:47:09 +04:00
fmt = & formats [ f - > index ] ;
strlcpy ( f - > description , fmt - > name , sizeof ( f - > description ) ) ;
f - > pixelformat = fmt - > fourcc ;
2006-06-04 17:34:12 +04:00
return 0 ;
}
2008-05-28 19:16:41 +04:00
static int vidioc_g_fmt_vid_cap ( struct file * file , void * priv ,
2006-06-04 17:34:12 +04:00
struct v4l2_format * f )
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2006-06-04 17:34:12 +04:00
2010-04-10 11:13:53 +04:00
f - > fmt . pix . width = dev - > width ;
f - > fmt . pix . height = dev - > height ;
2011-01-19 18:02:29 +03:00
f - > fmt . pix . field = dev - > field ;
2010-04-10 11:13:53 +04:00
f - > fmt . pix . pixelformat = dev - > fmt - > fourcc ;
2006-06-04 17:34:12 +04:00
f - > fmt . pix . bytesperline =
2010-04-10 11:13:53 +04:00
( f - > fmt . pix . width * dev - > fmt - > depth ) > > 3 ;
2006-06-04 17:34:12 +04:00
f - > fmt . pix . sizeimage =
f - > fmt . pix . height * f - > fmt . pix . bytesperline ;
2011-07-29 14:19:46 +04:00
if ( dev - > fmt - > fourcc = = V4L2_PIX_FMT_YUYV | |
dev - > fmt - > fourcc = = V4L2_PIX_FMT_UYVY )
f - > fmt . pix . colorspace = V4L2_COLORSPACE_SMPTE170M ;
else
f - > fmt . pix . colorspace = V4L2_COLORSPACE_SRGB ;
2010-04-10 11:13:53 +04:00
return 0 ;
2006-06-04 17:34:12 +04:00
}
2008-05-28 19:16:41 +04:00
static int vidioc_try_fmt_vid_cap ( struct file * file , void * priv ,
2006-03-10 18:40:10 +03:00
struct v4l2_format * f )
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2006-03-10 18:40:10 +03:00
struct vivi_fmt * fmt ;
enum v4l2_field field ;
2008-10-14 19:47:09 +04:00
fmt = get_format ( f ) ;
if ( ! fmt ) {
dprintk ( dev , 1 , " Fourcc format (0x%08x) invalid. \n " ,
f - > fmt . pix . pixelformat ) ;
2006-03-10 18:40:10 +03:00
return - EINVAL ;
}
field = f - > fmt . pix . field ;
if ( field = = V4L2_FIELD_ANY ) {
2007-12-10 15:33:52 +03:00
field = V4L2_FIELD_INTERLACED ;
2006-03-10 18:40:10 +03:00
} else if ( V4L2_FIELD_INTERLACED ! = field ) {
2007-12-13 19:30:14 +03:00
dprintk ( dev , 1 , " Field type invalid. \n " ) ;
2006-03-10 18:40:10 +03:00
return - EINVAL ;
}
f - > fmt . pix . field = field ;
2010-04-10 11:13:53 +04:00
v4l_bound_align_image ( & f - > fmt . pix . width , 48 , MAX_WIDTH , 2 ,
& f - > fmt . pix . height , 32 , MAX_HEIGHT , 0 , 0 ) ;
2006-03-10 18:40:10 +03:00
f - > fmt . pix . bytesperline =
( f - > fmt . pix . width * fmt - > depth ) > > 3 ;
f - > fmt . pix . sizeimage =
f - > fmt . pix . height * f - > fmt . pix . bytesperline ;
2011-07-29 14:19:46 +04:00
if ( fmt - > fourcc = = V4L2_PIX_FMT_YUYV | |
fmt - > fourcc = = V4L2_PIX_FMT_UYVY )
f - > fmt . pix . colorspace = V4L2_COLORSPACE_SMPTE170M ;
else
f - > fmt . pix . colorspace = V4L2_COLORSPACE_SRGB ;
2006-03-10 18:40:10 +03:00
return 0 ;
}
2009-01-11 16:29:43 +03:00
static int vidioc_s_fmt_vid_cap ( struct file * file , void * priv ,
struct v4l2_format * f )
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2011-01-19 18:02:29 +03:00
struct vb2_queue * q = & dev - > vb_vidq ;
2009-01-11 16:29:43 +03:00
2010-04-10 11:13:53 +04:00
int ret = vidioc_try_fmt_vid_cap ( file , priv , f ) ;
2009-01-11 16:29:43 +03:00
if ( ret < 0 )
return ret ;
2011-01-19 18:02:29 +03:00
if ( vb2_is_streaming ( q ) ) {
2010-04-10 11:13:53 +04:00
dprintk ( dev , 1 , " %s device busy \n " , __func__ ) ;
2011-01-19 18:02:29 +03:00
return - EBUSY ;
2009-01-11 16:29:43 +03:00
}
2010-04-10 11:13:53 +04:00
dev - > fmt = get_format ( f ) ;
dev - > width = f - > fmt . pix . width ;
dev - > height = f - > fmt . pix . height ;
2011-01-19 18:02:29 +03:00
dev - > field = f - > fmt . pix . field ;
return 0 ;
2006-03-10 18:40:10 +03:00
}
2007-12-10 15:33:52 +03:00
static int vidioc_reqbufs ( struct file * file , void * priv ,
struct v4l2_requestbuffers * p )
2006-03-10 18:40:10 +03:00
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2011-01-19 18:02:29 +03:00
return vb2_reqbufs ( & dev - > vb_vidq , p ) ;
2006-03-10 18:40:10 +03:00
}
2007-12-10 15:33:52 +03:00
static int vidioc_querybuf ( struct file * file , void * priv , struct v4l2_buffer * p )
2006-03-10 18:40:10 +03:00
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2011-01-19 18:02:29 +03:00
return vb2_querybuf ( & dev - > vb_vidq , p ) ;
2006-06-04 17:34:12 +04:00
}
2006-03-10 18:40:10 +03:00
2007-12-10 15:33:52 +03:00
static int vidioc_qbuf ( struct file * file , void * priv , struct v4l2_buffer * p )
2006-06-04 17:34:12 +04:00
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2011-01-19 18:02:29 +03:00
return vb2_qbuf ( & dev - > vb_vidq , p ) ;
2006-06-04 17:34:12 +04:00
}
2006-03-10 18:40:10 +03:00
2007-12-10 15:33:52 +03:00
static int vidioc_dqbuf ( struct file * file , void * priv , struct v4l2_buffer * p )
2006-06-04 17:34:12 +04:00
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2011-01-19 18:02:29 +03:00
return vb2_dqbuf ( & dev - > vb_vidq , p , file - > f_flags & O_NONBLOCK ) ;
2006-06-04 17:34:12 +04:00
}
2006-03-10 18:40:10 +03:00
2006-06-23 13:42:44 +04:00
static int vidioc_streamon ( struct file * file , void * priv , enum v4l2_buf_type i )
2006-06-04 17:34:12 +04:00
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2011-01-19 18:02:29 +03:00
return vb2_streamon ( & dev - > vb_vidq , i ) ;
2006-06-04 17:34:12 +04:00
}
2006-03-10 18:40:10 +03:00
2006-06-23 13:42:44 +04:00
static int vidioc_streamoff ( struct file * file , void * priv , enum v4l2_buf_type i )
2006-06-04 17:34:12 +04:00
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2011-01-19 18:02:29 +03:00
return vb2_streamoff ( & dev - > vb_vidq , i ) ;
2006-06-04 17:34:12 +04:00
}
2011-08-26 15:45:38 +04:00
static int vidioc_log_status ( struct file * file , void * priv )
{
struct vivi_dev * dev = video_drvdata ( file ) ;
v4l2_ctrl_handler_log_status ( & dev - > ctrl_handler , dev - > v4l2_dev . name ) ;
return 0 ;
}
2007-12-10 15:33:52 +03:00
static int vidioc_s_std ( struct file * file , void * priv , v4l2_std_id * i )
2006-06-04 17:34:12 +04:00
{
return 0 ;
}
2006-03-10 18:40:10 +03:00
2006-06-04 17:34:12 +04:00
/* only one input in this sample driver */
2007-12-10 15:33:52 +03:00
static int vidioc_enum_input ( struct file * file , void * priv ,
2006-06-04 17:34:12 +04:00
struct v4l2_input * inp )
{
2009-01-11 16:29:43 +03:00
if ( inp - > index > = NUM_INPUTS )
2006-06-04 17:34:12 +04:00
return - EINVAL ;
2006-03-10 18:40:10 +03:00
2006-06-04 17:34:12 +04:00
inp - > type = V4L2_INPUT_TYPE_CAMERA ;
2007-12-13 12:35:26 +03:00
inp - > std = V4L2_STD_525_60 ;
2009-01-11 16:29:43 +03:00
sprintf ( inp - > name , " Camera %u " , inp - > index ) ;
2010-04-10 11:13:53 +04:00
return 0 ;
2006-06-04 17:34:12 +04:00
}
2006-03-10 18:40:10 +03:00
2007-12-10 15:33:52 +03:00
static int vidioc_g_input ( struct file * file , void * priv , unsigned int * i )
2006-06-04 17:34:12 +04:00
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2009-01-11 16:29:43 +03:00
* i = dev - > input ;
2010-04-10 11:13:53 +04:00
return 0 ;
2006-06-04 17:34:12 +04:00
}
2010-04-10 11:13:53 +04:00
2007-12-10 15:33:52 +03:00
static int vidioc_s_input ( struct file * file , void * priv , unsigned int i )
2006-06-04 17:34:12 +04:00
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2009-01-11 16:29:43 +03:00
if ( i > = NUM_INPUTS )
2006-06-04 17:34:12 +04:00
return - EINVAL ;
2006-03-10 18:40:10 +03:00
2011-06-07 17:20:23 +04:00
if ( i = = dev - > input )
return 0 ;
2009-01-11 16:29:43 +03:00
dev - > input = i ;
2010-04-10 11:13:53 +04:00
precalculate_bars ( dev ) ;
precalculate_line ( dev ) ;
return 0 ;
2006-06-04 17:34:12 +04:00
}
2006-03-10 18:40:10 +03:00
2011-06-07 17:20:23 +04:00
static int vidioc_subscribe_event ( struct v4l2_fh * fh ,
struct v4l2_event_subscription * sub )
{
switch ( sub - > type ) {
case V4L2_EVENT_CTRL :
2011-06-14 02:24:17 +04:00
return v4l2_event_subscribe ( fh , sub , 0 ) ;
2011-06-07 17:20:23 +04:00
default :
return - EINVAL ;
}
}
2010-04-10 11:13:53 +04:00
/* --- controls ---------------------------------------------- */
2006-03-10 18:40:10 +03:00
2011-06-07 13:34:41 +04:00
static int vivi_g_volatile_ctrl ( struct v4l2_ctrl * ctrl )
{
struct vivi_dev * dev = container_of ( ctrl - > handler , struct vivi_dev , ctrl_handler ) ;
if ( ctrl = = dev - > autogain )
dev - > gain - > val = jiffies & 0xff ;
return 0 ;
}
2011-01-23 17:33:16 +03:00
static int vivi_s_ctrl ( struct v4l2_ctrl * ctrl )
2006-06-04 17:34:12 +04:00
{
2011-01-23 17:33:16 +03:00
struct vivi_dev * dev = container_of ( ctrl - > handler , struct vivi_dev , ctrl_handler ) ;
2006-03-10 18:40:10 +03:00
2011-01-23 17:33:16 +03:00
if ( ctrl = = dev - > button )
dev - > button_pressed = 30 ;
return 0 ;
2006-03-10 18:40:10 +03:00
}
/* ------------------------------------------------------------------
File operations for the device
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static ssize_t
vivi_read ( struct file * file , char __user * data , size_t count , loff_t * ppos )
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
dprintk ( dev , 1 , " read called \n " ) ;
return vb2_read ( & dev - > vb_vidq , data , count , ppos ,
file - > f_flags & O_NONBLOCK ) ;
2006-03-10 18:40:10 +03:00
}
static unsigned int
vivi_poll ( struct file * file , struct poll_table_struct * wait )
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2011-06-07 17:20:23 +04:00
struct v4l2_fh * fh = file - > private_data ;
2011-01-19 18:02:29 +03:00
struct vb2_queue * q = & dev - > vb_vidq ;
2011-06-07 17:20:23 +04:00
unsigned int res ;
2006-03-10 18:40:10 +03:00
2008-04-09 06:20:00 +04:00
dprintk ( dev , 1 , " %s \n " , __func__ ) ;
2011-06-07 17:20:23 +04:00
res = vb2_poll ( q , file , wait ) ;
if ( v4l2_event_pending ( fh ) )
res | = POLLPRI ;
else
2011-06-14 00:44:42 +04:00
poll_wait ( file , & fh - > wait , wait ) ;
2011-06-07 17:20:23 +04:00
return res ;
2006-03-10 18:40:10 +03:00
}
2008-12-30 12:58:20 +03:00
static int vivi_close ( struct file * file )
2006-03-10 18:40:10 +03:00
{
2009-12-10 16:47:13 +03:00
struct video_device * vdev = video_devdata ( file ) ;
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
dprintk ( dev , 1 , " close called (dev=%s), file %p \n " ,
video_device_node_name ( vdev ) , file ) ;
2006-03-10 18:40:10 +03:00
2011-03-12 02:01:54 +03:00
if ( v4l2_fh_is_singular_file ( file ) )
2011-01-19 18:02:29 +03:00
vb2_queue_release ( & dev - > vb_vidq ) ;
2011-03-12 02:01:54 +03:00
return v4l2_fh_release ( file ) ;
2006-03-10 18:40:10 +03:00
}
2007-12-10 15:33:52 +03:00
static int vivi_mmap ( struct file * file , struct vm_area_struct * vma )
2006-03-10 18:40:10 +03:00
{
2010-04-10 11:13:53 +04:00
struct vivi_dev * dev = video_drvdata ( file ) ;
2006-03-10 18:40:10 +03:00
int ret ;
2007-12-13 19:30:14 +03:00
dprintk ( dev , 1 , " mmap called, vma=0x%08lx \n " , ( unsigned long ) vma ) ;
2006-03-10 18:40:10 +03:00
2011-01-19 18:02:29 +03:00
ret = vb2_mmap ( & dev - > vb_vidq , vma ) ;
2007-12-13 19:30:14 +03:00
dprintk ( dev , 1 , " vma start=0x%08lx, size=%ld, ret=%d \n " ,
2006-03-10 18:40:10 +03:00
( unsigned long ) vma - > vm_start ,
2010-04-10 11:13:53 +04:00
( unsigned long ) vma - > vm_end - ( unsigned long ) vma - > vm_start ,
2006-03-10 18:40:10 +03:00
ret ) ;
return ret ;
}
2011-01-23 17:33:16 +03:00
static const struct v4l2_ctrl_ops vivi_ctrl_ops = {
2011-06-07 13:34:41 +04:00
. g_volatile_ctrl = vivi_g_volatile_ctrl ,
2011-01-23 17:33:16 +03:00
. s_ctrl = vivi_s_ctrl ,
} ;
# define VIVI_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
static const struct v4l2_ctrl_config vivi_ctrl_button = {
. ops = & vivi_ctrl_ops ,
. id = VIVI_CID_CUSTOM_BASE + 0 ,
. name = " Button " ,
. type = V4L2_CTRL_TYPE_BUTTON ,
} ;
static const struct v4l2_ctrl_config vivi_ctrl_boolean = {
. ops = & vivi_ctrl_ops ,
. id = VIVI_CID_CUSTOM_BASE + 1 ,
. name = " Boolean " ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
. min = 0 ,
. max = 1 ,
. step = 1 ,
. def = 1 ,
} ;
static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
. ops = & vivi_ctrl_ops ,
. id = VIVI_CID_CUSTOM_BASE + 2 ,
. name = " Integer 32 Bits " ,
. type = V4L2_CTRL_TYPE_INTEGER ,
2011-01-11 23:32:28 +03:00
. min = 0x80000000 ,
. max = 0x7fffffff ,
2011-01-23 17:33:16 +03:00
. step = 1 ,
} ;
static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
. ops = & vivi_ctrl_ops ,
. id = VIVI_CID_CUSTOM_BASE + 3 ,
. name = " Integer 64 Bits " ,
. type = V4L2_CTRL_TYPE_INTEGER64 ,
} ;
static const char * const vivi_ctrl_menu_strings [ ] = {
" Menu Item 0 (Skipped) " ,
" Menu Item 1 " ,
" Menu Item 2 (Skipped) " ,
" Menu Item 3 " ,
" Menu Item 4 " ,
" Menu Item 5 (Skipped) " ,
NULL ,
} ;
static const struct v4l2_ctrl_config vivi_ctrl_menu = {
. ops = & vivi_ctrl_ops ,
. id = VIVI_CID_CUSTOM_BASE + 4 ,
. name = " Menu " ,
. type = V4L2_CTRL_TYPE_MENU ,
. min = 1 ,
. max = 4 ,
. def = 3 ,
. menu_skip_mask = 0x04 ,
. qmenu = vivi_ctrl_menu_strings ,
} ;
static const struct v4l2_ctrl_config vivi_ctrl_string = {
. ops = & vivi_ctrl_ops ,
. id = VIVI_CID_CUSTOM_BASE + 5 ,
. name = " String " ,
. type = V4L2_CTRL_TYPE_STRING ,
. min = 2 ,
. max = 4 ,
. step = 1 ,
} ;
2011-03-29 23:33:11 +04:00
static const struct v4l2_ctrl_config vivi_ctrl_bitmask = {
. ops = & vivi_ctrl_ops ,
. id = VIVI_CID_CUSTOM_BASE + 6 ,
. name = " Bitmask " ,
. type = V4L2_CTRL_TYPE_BITMASK ,
. def = 0x80002000 ,
. min = 0 ,
. max = 0x80402010 ,
. step = 0 ,
} ;
2008-12-30 12:58:20 +03:00
static const struct v4l2_file_operations vivi_fops = {
2006-03-10 18:40:10 +03:00
. owner = THIS_MODULE ,
2011-06-07 17:20:23 +04:00
. open = v4l2_fh_open ,
2007-12-10 10:07:03 +03:00
. release = vivi_close ,
2006-03-10 18:40:10 +03:00
. read = vivi_read ,
. poll = vivi_poll ,
2010-09-21 01:25:55 +04:00
. unlocked_ioctl = video_ioctl2 , /* V4L2 ioctl handler */
2007-08-03 06:31:54 +04:00
. mmap = vivi_mmap ,
2006-03-10 18:40:10 +03:00
} ;
2008-07-21 09:57:38 +04:00
static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
2006-06-04 17:34:12 +04:00
. vidioc_querycap = vidioc_querycap ,
2008-05-28 19:16:41 +04:00
. 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 ,
2006-06-04 17:34:12 +04:00
. vidioc_reqbufs = vidioc_reqbufs ,
. vidioc_querybuf = vidioc_querybuf ,
. vidioc_qbuf = vidioc_qbuf ,
. vidioc_dqbuf = vidioc_dqbuf ,
. vidioc_s_std = vidioc_s_std ,
. vidioc_enum_input = vidioc_enum_input ,
. vidioc_g_input = vidioc_g_input ,
. vidioc_s_input = vidioc_s_input ,
2010-04-10 11:13:53 +04:00
. vidioc_streamon = vidioc_streamon ,
. vidioc_streamoff = vidioc_streamoff ,
2011-08-26 15:45:38 +04:00
. vidioc_log_status = vidioc_log_status ,
2011-06-07 17:20:23 +04:00
. vidioc_subscribe_event = vidioc_subscribe_event ,
. vidioc_unsubscribe_event = v4l2_event_unsubscribe ,
2008-07-21 09:57:38 +04:00
} ;
static struct video_device vivi_template = {
. name = " vivi " ,
. fops = & vivi_fops ,
. ioctl_ops = & vivi_ioctl_ops ,
. release = video_device_release ,
2007-12-13 12:35:26 +03:00
. tvnorms = V4L2_STD_525_60 ,
2006-11-20 19:19:20 +03:00
. current_norm = V4L2_STD_NTSC_M ,
2006-03-10 18:40:10 +03:00
} ;
2009-02-14 19:23:12 +03:00
2006-06-04 17:34:12 +04:00
/* -----------------------------------------------------------------
2006-03-10 18:40:10 +03:00
Initialization and module stuff
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2009-02-14 19:23:12 +03:00
static int vivi_release ( void )
{
struct vivi_dev * dev ;
struct list_head * list ;
2008-09-04 00:11:53 +04:00
2009-02-14 19:23:12 +03:00
while ( ! list_empty ( & vivi_devlist ) ) {
list = vivi_devlist . next ;
list_del ( list ) ;
dev = list_entry ( list , struct vivi_dev , vivi_devlist ) ;
2009-11-27 19:57:15 +03:00
v4l2_info ( & dev - > v4l2_dev , " unregistering %s \n " ,
video_device_node_name ( dev - > vfd ) ) ;
2009-02-14 19:23:12 +03:00
video_unregister_device ( dev - > vfd ) ;
v4l2_device_unregister ( & dev - > v4l2_dev ) ;
2011-01-23 17:33:16 +03:00
v4l2_ctrl_handler_free ( & dev - > ctrl_handler ) ;
2009-02-14 19:23:12 +03:00
kfree ( dev ) ;
}
return 0 ;
}
2009-02-14 19:43:44 +03:00
static int __init vivi_create_instance ( int inst )
2006-03-10 18:40:10 +03:00
{
struct vivi_dev * dev ;
2007-12-10 10:07:03 +03:00
struct video_device * vfd ;
2011-01-23 17:33:16 +03:00
struct v4l2_ctrl_handler * hdl ;
2011-01-19 18:02:29 +03:00
struct vb2_queue * q ;
2010-04-10 11:13:53 +04:00
int ret ;
2006-03-10 18:40:10 +03:00
2009-02-14 19:23:12 +03:00
dev = kzalloc ( sizeof ( * dev ) , GFP_KERNEL ) ;
if ( ! dev )
return - ENOMEM ;
2008-09-04 00:11:53 +04:00
2009-02-14 19:23:12 +03:00
snprintf ( dev - > v4l2_dev . name , sizeof ( dev - > v4l2_dev . name ) ,
2009-02-14 19:43:44 +03:00
" %s-%03d " , VIVI_MODULE_NAME , inst ) ;
2009-02-14 19:23:12 +03:00
ret = v4l2_device_register ( NULL , & dev - > v4l2_dev ) ;
if ( ret )
goto free_dev ;
2006-03-10 18:40:10 +03:00
2010-04-10 11:13:53 +04:00
dev - > fmt = & formats [ 0 ] ;
dev - > width = 640 ;
dev - > height = 480 ;
2011-01-23 17:33:16 +03:00
hdl = & dev - > ctrl_handler ;
v4l2_ctrl_handler_init ( hdl , 11 ) ;
dev - > volume = v4l2_ctrl_new_std ( hdl , & vivi_ctrl_ops ,
V4L2_CID_AUDIO_VOLUME , 0 , 255 , 1 , 200 ) ;
dev - > brightness = v4l2_ctrl_new_std ( hdl , & vivi_ctrl_ops ,
V4L2_CID_BRIGHTNESS , 0 , 255 , 1 , 127 ) ;
dev - > contrast = v4l2_ctrl_new_std ( hdl , & vivi_ctrl_ops ,
V4L2_CID_CONTRAST , 0 , 255 , 1 , 16 ) ;
dev - > saturation = v4l2_ctrl_new_std ( hdl , & vivi_ctrl_ops ,
V4L2_CID_SATURATION , 0 , 255 , 1 , 127 ) ;
dev - > hue = v4l2_ctrl_new_std ( hdl , & vivi_ctrl_ops ,
V4L2_CID_HUE , - 128 , 127 , 1 , 0 ) ;
2011-06-07 13:34:41 +04:00
dev - > autogain = v4l2_ctrl_new_std ( hdl , & vivi_ctrl_ops ,
V4L2_CID_AUTOGAIN , 0 , 1 , 1 , 1 ) ;
dev - > gain = v4l2_ctrl_new_std ( hdl , & vivi_ctrl_ops ,
V4L2_CID_GAIN , 0 , 255 , 1 , 100 ) ;
2011-01-23 17:33:16 +03:00
dev - > button = v4l2_ctrl_new_custom ( hdl , & vivi_ctrl_button , NULL ) ;
dev - > int32 = v4l2_ctrl_new_custom ( hdl , & vivi_ctrl_int32 , NULL ) ;
dev - > int64 = v4l2_ctrl_new_custom ( hdl , & vivi_ctrl_int64 , NULL ) ;
dev - > boolean = v4l2_ctrl_new_custom ( hdl , & vivi_ctrl_boolean , NULL ) ;
dev - > menu = v4l2_ctrl_new_custom ( hdl , & vivi_ctrl_menu , NULL ) ;
dev - > string = v4l2_ctrl_new_custom ( hdl , & vivi_ctrl_string , NULL ) ;
2011-03-29 23:33:11 +04:00
dev - > bitmask = v4l2_ctrl_new_custom ( hdl , & vivi_ctrl_bitmask , NULL ) ;
2011-01-23 17:33:16 +03:00
if ( hdl - > error ) {
ret = hdl - > error ;
goto unreg_dev ;
}
2011-06-07 13:34:41 +04:00
v4l2_ctrl_auto_cluster ( 2 , & dev - > autogain , 0 , true ) ;
2011-01-23 17:33:16 +03:00
dev - > v4l2_dev . ctrl_handler = hdl ;
2010-04-10 11:13:53 +04:00
2010-09-21 01:25:55 +04:00
/* initialize locks */
spin_lock_init ( & dev - > slock ) ;
2011-01-19 18:02:29 +03:00
/* initialize queue */
q = & dev - > vb_vidq ;
memset ( q , 0 , sizeof ( dev - > vb_vidq ) ) ;
q - > type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
q - > io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ ;
q - > drv_priv = dev ;
q - > buf_struct_size = sizeof ( struct vivi_buffer ) ;
q - > ops = & vivi_video_qops ;
q - > mem_ops = & vb2_vmalloc_memops ;
vb2_queue_init ( q ) ;
mutex_init ( & dev - > mutex ) ;
2010-04-10 11:13:53 +04:00
2009-02-14 19:23:12 +03:00
/* init video dma queues */
INIT_LIST_HEAD ( & dev - > vidq . active ) ;
init_waitqueue_head ( & dev - > vidq . wq ) ;
2006-03-10 18:40:10 +03:00
2009-02-14 19:23:12 +03:00
ret = - ENOMEM ;
vfd = video_device_alloc ( ) ;
if ( ! vfd )
goto unreg_dev ;
2007-12-10 10:38:11 +03:00
2009-02-14 19:23:12 +03:00
* vfd = vivi_template ;
2009-06-25 23:28:23 +04:00
vfd - > debug = debug ;
2010-04-10 11:13:53 +04:00
vfd - > v4l2_dev = & dev - > v4l2_dev ;
2011-03-22 16:14:07 +03:00
set_bit ( V4L2_FL_USE_FH_PRIO , & vfd - > flags ) ;
2011-01-19 18:02:29 +03:00
/*
* Provide a mutex to v4l2 core . It will be used to protect
* all fops and v4l2 ioctls .
*/
2010-09-21 01:25:55 +04:00
vfd - > lock = & dev - > mutex ;
2007-12-10 10:38:11 +03:00
2009-02-14 19:23:12 +03:00
ret = video_register_device ( vfd , VFL_TYPE_GRABBER , video_nr ) ;
if ( ret < 0 )
goto rel_vdev ;
2008-09-04 00:11:53 +04:00
2009-02-14 19:23:12 +03:00
video_set_drvdata ( vfd , dev ) ;
2008-09-04 00:11:53 +04:00
2009-02-14 19:23:12 +03:00
/* Now that everything is fine, let's add it to device list */
list_add_tail ( & dev - > vivi_devlist , & vivi_devlist ) ;
2008-09-04 00:11:53 +04:00
2009-12-16 19:06:33 +03:00
if ( video_nr ! = - 1 )
2009-02-14 19:23:12 +03:00
video_nr + + ;
2007-12-10 10:07:03 +03:00
2009-02-14 19:23:12 +03:00
dev - > vfd = vfd ;
2009-11-27 19:57:15 +03:00
v4l2_info ( & dev - > v4l2_dev , " V4L2 device registered as %s \n " ,
video_device_node_name ( vfd ) ) ;
2009-02-14 19:23:12 +03:00
return 0 ;
rel_vdev :
video_device_release ( vfd ) ;
unreg_dev :
2011-01-23 17:33:16 +03:00
v4l2_ctrl_handler_free ( hdl ) ;
2009-02-14 19:23:12 +03:00
v4l2_device_unregister ( & dev - > v4l2_dev ) ;
free_dev :
kfree ( dev ) ;
return ret ;
}
2007-12-10 10:07:03 +03:00
2009-02-14 19:23:12 +03:00
/* 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
videodev supports , which is equal to VIDEO_NUM_DEVICES .
*/
static int __init vivi_init ( void )
{
2010-04-10 11:13:53 +04:00
const struct font_desc * font = find_font ( " VGA8x16 " ) ;
2009-03-06 15:58:12 +03:00
int ret = 0 , i ;
2009-02-14 19:23:12 +03:00
2010-04-10 11:13:53 +04:00
if ( font = = NULL ) {
printk ( KERN_ERR " vivi: could not find font \n " ) ;
return - ENODEV ;
}
font8x16 = font - > data ;
2009-02-14 19:23:12 +03:00
if ( n_devs < = 0 )
n_devs = 1 ;
for ( i = 0 ; i < n_devs ; i + + ) {
ret = vivi_create_instance ( i ) ;
if ( ret ) {
/* If some instantiations succeeded, keep driver */
if ( i )
ret = 0 ;
break ;
}
2007-12-10 10:38:11 +03:00
}
2007-12-10 10:07:03 +03:00
2007-12-10 10:38:11 +03:00
if ( ret < 0 ) {
2010-04-10 11:13:53 +04:00
printk ( KERN_ERR " vivi: error %d while loading driver \n " , ret ) ;
2009-02-14 19:23:12 +03:00
return ret ;
}
printk ( KERN_INFO " Video Technology Magazine Virtual Video "
[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
" Capture Board ver %s successfully loaded. \n " ,
VIVI_VERSION ) ;
2008-09-04 00:11:53 +04:00
2009-02-14 19:23:12 +03:00
/* n_devs will reflect the actual number of allocated devices */
n_devs = i ;
2008-09-04 00:11:53 +04:00
2006-03-10 18:40:10 +03:00
return ret ;
}
static void __exit vivi_exit ( void )
{
2007-12-10 10:38:11 +03:00
vivi_release ( ) ;
2006-03-10 18:40:10 +03:00
}
module_init ( vivi_init ) ;
module_exit ( vivi_exit ) ;