2006-02-27 00:09:05 -03:00
/****************************************************************************
*
* Filename : cpia2_v4l . c
*
* Copyright 2001 , STMicrolectronics , Inc .
* Contact : steve . miller @ st . com
* Copyright 2001 , 2005 , Scott J . Bertin < scottbertin @ yahoo . com >
*
* Description :
* This is a USB driver for CPia2 based video cameras .
* The infrastructure of this driver is based on the cpia usb driver by
* Jochen Scharrlach and Johannes Erdfeldt .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*
* Stripped of 2.4 stuff ready for main kernel submit by
2008-10-27 15:13:47 -03:00
* Alan Cox < alan @ lxorguk . ukuu . org . uk >
2006-02-27 00:09:05 -03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
[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 14:45:49 -03:00
# define CPIA_VERSION "3.0.1"
2006-02-27 00:09:05 -03:00
# include <linux/module.h>
# include <linux/time.h>
# include <linux/sched.h>
# include <linux/slab.h>
# include <linux/init.h>
2010-09-19 06:00:54 -03:00
# include <linux/videodev2.h>
2009-12-10 16:40:50 -03:00
# include <linux/stringify.h>
2008-07-20 08:12:02 -03:00
# include <media/v4l2-ioctl.h>
2012-04-29 08:44:44 -03:00
# include <media/v4l2-event.h>
2006-02-27 00:09:05 -03:00
# include "cpia2.h"
static int video_nr = - 1 ;
module_param ( video_nr , int , 0 ) ;
2012-04-29 08:44:44 -03:00
MODULE_PARM_DESC ( video_nr , " video device to register (0=/dev/video0, etc) " ) ;
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
static int buffer_size = 68 * 1024 ;
2006-02-27 00:09:05 -03:00
module_param ( buffer_size , int , 0 ) ;
MODULE_PARM_DESC ( buffer_size , " Size for each frame buffer in bytes (default 68k) " ) ;
static int num_buffers = 3 ;
module_param ( num_buffers , int , 0 ) ;
MODULE_PARM_DESC ( num_buffers , " Number of frame buffers (1- "
2009-12-10 16:40:50 -03:00
__stringify ( VIDEO_MAX_FRAME ) " , default 3) " ) ;
2006-02-27 00:09:05 -03:00
static int alternate = DEFAULT_ALT ;
module_param ( alternate , int , 0 ) ;
2009-12-10 16:40:50 -03:00
MODULE_PARM_DESC ( alternate , " USB Alternate ( " __stringify ( USBIF_ISO_1 ) " - "
__stringify ( USBIF_ISO_6 ) " , default "
__stringify ( DEFAULT_ALT ) " ) " ) ;
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
static int flicker_mode ;
2006-02-27 00:09:05 -03:00
module_param ( flicker_mode , int , 0 ) ;
2012-04-29 08:44:44 -03:00
MODULE_PARM_DESC ( flicker_mode , " Flicker frequency (0 (disabled), " __stringify ( 50 ) " or "
__stringify ( 60 ) " , default 0) " ) ;
2006-02-27 00:09:05 -03:00
MODULE_AUTHOR ( " Steve Miller (STMicroelectronics) <steve.miller@st.com> " ) ;
MODULE_DESCRIPTION ( " V4L-driver for STMicroelectronics CPiA2 based cameras " ) ;
MODULE_SUPPORTED_DEVICE ( " video " ) ;
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 14:45:49 -03:00
MODULE_VERSION ( CPIA_VERSION ) ;
2006-02-27 00:09:05 -03:00
# define ABOUT "V4L-Driver for Vision CPiA2 based cameras"
2012-04-29 08:44:44 -03:00
# define CPIA2_CID_USB_ALT (V4L2_CID_USER_BASE | 0xf000)
2006-02-27 00:09:05 -03:00
/******************************************************************************
*
* cpia2_open
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-12-30 06:58:20 -03:00
static int cpia2_open ( struct file * file )
2006-02-27 00:09:05 -03:00
{
2008-08-23 08:32:09 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2012-06-23 07:56:21 -03:00
int retval ;
2006-02-27 00:09:05 -03:00
2012-06-23 07:56:21 -03:00
if ( mutex_lock_interruptible ( & cam - > v4l2_lock ) )
return - ERESTARTSYS ;
retval = v4l2_fh_open ( file ) ;
2012-04-29 08:44:44 -03:00
if ( retval )
2012-06-23 07:56:21 -03:00
goto open_unlock ;
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
if ( v4l2_fh_is_singular_file ( file ) ) {
if ( cpia2_allocate_buffers ( cam ) ) {
v4l2_fh_release ( file ) ;
2012-06-23 07:56:21 -03:00
retval = - ENOMEM ;
goto open_unlock ;
2012-04-29 08:44:44 -03:00
}
2006-02-27 00:09:05 -03:00
2010-12-18 09:50:43 -03:00
/* reset the camera */
2012-04-29 08:44:44 -03:00
if ( cpia2_reset_camera ( cam ) < 0 ) {
v4l2_fh_release ( file ) ;
2012-06-23 07:56:21 -03:00
retval = - EIO ;
goto open_unlock ;
2012-04-29 08:44:44 -03:00
}
2006-02-27 00:09:05 -03:00
2010-12-18 09:50:43 -03:00
cam - > APP_len = 0 ;
cam - > COM_len = 0 ;
2006-02-27 00:09:05 -03:00
}
cpia2_dbg_dump_registers ( cam ) ;
2012-06-23 07:56:21 -03:00
open_unlock :
mutex_unlock ( & cam - > v4l2_lock ) ;
return retval ;
2006-02-27 00:09:05 -03:00
}
/******************************************************************************
*
* cpia2_close
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-12-30 06:58:20 -03:00
static int cpia2_close ( struct file * file )
2006-02-27 00:09:05 -03:00
{
struct video_device * dev = video_devdata ( file ) ;
struct camera_data * cam = video_get_drvdata ( dev ) ;
2012-06-23 07:56:21 -03:00
mutex_lock ( & cam - > v4l2_lock ) ;
2012-04-29 08:44:44 -03:00
if ( video_is_registered ( & cam - > vdev ) & & v4l2_fh_is_singular_file ( file ) ) {
2006-02-27 00:09:05 -03:00
cpia2_usb_stream_stop ( cam ) ;
2012-04-29 08:44:44 -03:00
/* save camera state for later open */
cpia2_save_camera_state ( cam ) ;
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
cpia2_set_low_power ( cam ) ;
cpia2_free_buffers ( cam ) ;
2006-02-27 00:09:05 -03:00
}
2012-04-29 08:44:44 -03:00
if ( cam - > stream_fh = = file - > private_data ) {
cam - > stream_fh = NULL ;
2010-12-18 09:50:43 -03:00
cam - > mmapped = 0 ;
2006-02-27 00:09:05 -03:00
}
2012-06-23 07:56:21 -03:00
mutex_unlock ( & cam - > v4l2_lock ) ;
2012-04-29 08:44:44 -03:00
return v4l2_fh_release ( file ) ;
2006-02-27 00:09:05 -03:00
}
/******************************************************************************
*
* cpia2_v4l_read
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ssize_t cpia2_v4l_read ( struct file * file , char __user * buf , size_t count ,
loff_t * off )
{
2008-08-23 08:32:09 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2006-02-27 00:09:05 -03:00
int noblock = file - > f_flags & O_NONBLOCK ;
2012-06-23 07:56:21 -03:00
ssize_t ret ;
2006-02-27 00:09:05 -03:00
if ( ! cam )
return - EINVAL ;
2012-06-23 07:56:21 -03:00
if ( mutex_lock_interruptible ( & cam - > v4l2_lock ) )
return - ERESTARTSYS ;
ret = cpia2_read ( cam , buf , count , noblock ) ;
mutex_unlock ( & cam - > v4l2_lock ) ;
return ret ;
2006-02-27 00:09:05 -03:00
}
/******************************************************************************
*
* cpia2_v4l_poll
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static unsigned int cpia2_v4l_poll ( struct file * filp , struct poll_table_struct * wait )
{
2008-08-23 08:32:09 -03:00
struct camera_data * cam = video_drvdata ( filp ) ;
2012-06-23 07:56:21 -03:00
unsigned int res ;
2006-02-27 00:09:05 -03:00
2012-06-23 07:56:21 -03:00
mutex_lock ( & cam - > v4l2_lock ) ;
res = cpia2_poll ( cam , filp , wait ) ;
mutex_unlock ( & cam - > v4l2_lock ) ;
return res ;
2006-02-27 00:09:05 -03:00
}
static int sync ( struct camera_data * cam , int frame_nr )
{
struct framebuf * frame = & cam - > buffers [ frame_nr ] ;
while ( 1 ) {
if ( frame - > status = = FRAME_READY )
return 0 ;
if ( ! cam - > streaming ) {
frame - > status = FRAME_READY ;
frame - > length = 0 ;
return 0 ;
}
2010-12-18 09:50:43 -03:00
mutex_unlock ( & cam - > v4l2_lock ) ;
2006-02-27 00:09:05 -03:00
wait_event_interruptible ( cam - > wq_stream ,
! cam - > streaming | |
frame - > status = = FRAME_READY ) ;
2010-12-18 09:50:43 -03:00
mutex_lock ( & cam - > v4l2_lock ) ;
2006-02-27 00:09:05 -03:00
if ( signal_pending ( current ) )
return - ERESTARTSYS ;
2012-04-29 08:44:44 -03:00
if ( ! video_is_registered ( & cam - > vdev ) )
2006-02-27 00:09:05 -03:00
return - ENOTTY ;
}
}
/******************************************************************************
*
* ioctl_querycap
*
* V4L2 device capabilities
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-01-22 06:36:02 -03:00
static int cpia2_querycap ( struct file * file , void * fh , struct v4l2_capability * vc )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2006-02-27 00:09:05 -03:00
strcpy ( vc - > driver , " cpia2 " ) ;
if ( cam - > params . pnp_id . product = = 0x151 )
strcpy ( vc - > card , " QX5 Microscope " ) ;
else
strcpy ( vc - > card , " CPiA2 Camera " ) ;
switch ( cam - > params . pnp_id . device_type ) {
case DEVICE_STV_672 :
strcat ( vc - > card , " (672/ " ) ;
break ;
case DEVICE_STV_676 :
strcat ( vc - > card , " (676/ " ) ;
break ;
default :
2011-05-23 07:59:37 -03:00
strcat ( vc - > card , " (XXX/ " ) ;
2006-02-27 00:09:05 -03:00
break ;
}
switch ( cam - > params . version . sensor_flags ) {
case CPIA2_VP_SENSOR_FLAGS_404 :
strcat ( vc - > card , " 404) " ) ;
break ;
case CPIA2_VP_SENSOR_FLAGS_407 :
strcat ( vc - > card , " 407) " ) ;
break ;
case CPIA2_VP_SENSOR_FLAGS_409 :
strcat ( vc - > card , " 409) " ) ;
break ;
case CPIA2_VP_SENSOR_FLAGS_410 :
strcat ( vc - > card , " 410) " ) ;
break ;
case CPIA2_VP_SENSOR_FLAGS_500 :
strcat ( vc - > card , " 500) " ) ;
break ;
default :
2011-05-23 07:59:37 -03:00
strcat ( vc - > card , " XXX) " ) ;
2006-02-27 00:09:05 -03:00
break ;
}
if ( usb_make_path ( cam - > dev , vc - > bus_info , sizeof ( vc - > bus_info ) ) < 0 )
memset ( vc - > bus_info , 0 , sizeof ( vc - > bus_info ) ) ;
2012-04-29 08:44:44 -03:00
vc - > device_caps = V4L2_CAP_VIDEO_CAPTURE |
2006-02-27 00:09:05 -03:00
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING ;
2012-04-29 08:44:44 -03:00
vc - > capabilities = vc - > device_caps |
V4L2_CAP_DEVICE_CAPS ;
2006-02-27 00:09:05 -03:00
return 0 ;
}
/******************************************************************************
*
* ioctl_input
*
* V4L2 input get / set / enumerate
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-01-22 06:36:02 -03:00
static int cpia2_enum_input ( struct file * file , void * fh , struct v4l2_input * i )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
if ( i - > index )
return - EINVAL ;
2006-02-27 00:09:05 -03:00
strcpy ( i - > name , " Camera " ) ;
i - > type = V4L2_INPUT_TYPE_CAMERA ;
2011-01-22 06:36:02 -03:00
return 0 ;
}
2006-02-27 00:09:05 -03:00
2011-01-22 06:36:02 -03:00
static int cpia2_g_input ( struct file * file , void * fh , unsigned int * i )
{
* i = 0 ;
2006-02-27 00:09:05 -03:00
return 0 ;
}
2011-01-22 06:36:02 -03:00
static int cpia2_s_input ( struct file * file , void * fh , unsigned int i )
{
return i ? - EINVAL : 0 ;
}
2006-02-27 00:09:05 -03:00
/******************************************************************************
*
* ioctl_enum_fmt
*
* V4L2 format enumerate
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-01-22 06:36:02 -03:00
static int cpia2_enum_fmt_vid_cap ( struct file * file , void * fh ,
struct v4l2_fmtdesc * f )
2006-02-27 00:09:05 -03:00
{
int index = f - > index ;
if ( index < 0 | | index > 1 )
return - EINVAL ;
memset ( f , 0 , sizeof ( * f ) ) ;
f - > index = index ;
f - > type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
f - > flags = V4L2_FMT_FLAG_COMPRESSED ;
switch ( index ) {
case 0 :
strcpy ( f - > description , " MJPEG " ) ;
f - > pixelformat = V4L2_PIX_FMT_MJPEG ;
break ;
case 1 :
strcpy ( f - > description , " JPEG " ) ;
f - > pixelformat = V4L2_PIX_FMT_JPEG ;
break ;
default :
return - EINVAL ;
}
return 0 ;
}
/******************************************************************************
*
* ioctl_try_fmt
*
* V4L2 format try
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-01-22 06:36:02 -03:00
static int cpia2_try_fmt_vid_cap ( struct file * file , void * fh ,
struct v4l2_format * f )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2006-02-27 00:09:05 -03:00
if ( f - > fmt . pix . pixelformat ! = V4L2_PIX_FMT_MJPEG & &
f - > fmt . pix . pixelformat ! = V4L2_PIX_FMT_JPEG )
return - EINVAL ;
f - > fmt . pix . field = V4L2_FIELD_NONE ;
f - > fmt . pix . bytesperline = 0 ;
f - > fmt . pix . sizeimage = cam - > frame_size ;
f - > fmt . pix . colorspace = V4L2_COLORSPACE_JPEG ;
f - > fmt . pix . priv = 0 ;
switch ( cpia2_match_video_size ( f - > fmt . pix . width , f - > fmt . pix . height ) ) {
case VIDEOSIZE_VGA :
f - > fmt . pix . width = 640 ;
f - > fmt . pix . height = 480 ;
break ;
case VIDEOSIZE_CIF :
f - > fmt . pix . width = 352 ;
f - > fmt . pix . height = 288 ;
break ;
case VIDEOSIZE_QVGA :
f - > fmt . pix . width = 320 ;
f - > fmt . pix . height = 240 ;
break ;
case VIDEOSIZE_288_216 :
f - > fmt . pix . width = 288 ;
f - > fmt . pix . height = 216 ;
break ;
case VIDEOSIZE_256_192 :
f - > fmt . pix . width = 256 ;
f - > fmt . pix . height = 192 ;
break ;
case VIDEOSIZE_224_168 :
f - > fmt . pix . width = 224 ;
f - > fmt . pix . height = 168 ;
break ;
case VIDEOSIZE_192_144 :
f - > fmt . pix . width = 192 ;
f - > fmt . pix . height = 144 ;
break ;
case VIDEOSIZE_QCIF :
default :
f - > fmt . pix . width = 176 ;
f - > fmt . pix . height = 144 ;
break ;
}
return 0 ;
}
/******************************************************************************
*
* ioctl_set_fmt
*
* V4L2 format set
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-01-22 06:36:02 -03:00
static int cpia2_s_fmt_vid_cap ( struct file * file , void * _fh ,
struct v4l2_format * f )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2006-02-27 00:09:05 -03:00
int err , frame ;
2011-01-22 06:36:02 -03:00
err = cpia2_try_fmt_vid_cap ( file , _fh , f ) ;
2006-02-27 00:09:05 -03:00
if ( err ! = 0 )
return err ;
cam - > pixelformat = f - > fmt . pix . pixelformat ;
/* NOTE: This should be set to 1 for MJPEG, but some apps don't handle
* the missing Huffman table properly . */
cam - > params . compression . inhibit_htables = 0 ;
/*f->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG;*/
/* we set the video window to something smaller or equal to what
* is requested by the user ? ? ?
*/
DBG ( " Requested width = %d, height = %d \n " ,
f - > fmt . pix . width , f - > fmt . pix . height ) ;
2010-09-19 06:00:54 -03:00
if ( f - > fmt . pix . width ! = cam - > width | |
f - > fmt . pix . height ! = cam - > height ) {
cam - > width = f - > fmt . pix . width ;
cam - > height = f - > fmt . pix . height ;
2006-02-27 00:09:05 -03:00
cam - > params . roi . width = f - > fmt . pix . width ;
cam - > params . roi . height = f - > fmt . pix . height ;
cpia2_set_format ( cam ) ;
}
for ( frame = 0 ; frame < cam - > num_frames ; + + frame ) {
if ( cam - > buffers [ frame ] . status = = FRAME_READING )
if ( ( err = sync ( cam , frame ) ) < 0 )
return err ;
cam - > buffers [ frame ] . status = FRAME_EMPTY ;
}
return 0 ;
}
/******************************************************************************
*
* ioctl_get_fmt
*
* V4L2 format get
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-01-22 06:36:02 -03:00
static int cpia2_g_fmt_vid_cap ( struct file * file , void * fh ,
struct v4l2_format * f )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2006-02-27 00:09:05 -03:00
2010-09-19 06:00:54 -03:00
f - > fmt . pix . width = cam - > width ;
f - > fmt . pix . height = cam - > height ;
2006-02-27 00:09:05 -03:00
f - > fmt . pix . pixelformat = cam - > pixelformat ;
f - > fmt . pix . field = V4L2_FIELD_NONE ;
f - > fmt . pix . bytesperline = 0 ;
f - > fmt . pix . sizeimage = cam - > frame_size ;
f - > fmt . pix . colorspace = V4L2_COLORSPACE_JPEG ;
f - > fmt . pix . priv = 0 ;
return 0 ;
}
/******************************************************************************
*
* ioctl_cropcap
*
* V4L2 query cropping capabilities
* NOTE : cropping is currently disabled
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-01-22 06:36:02 -03:00
static int cpia2_cropcap ( struct file * file , void * fh , struct v4l2_cropcap * c )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2006-02-27 00:09:05 -03:00
if ( c - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE )
return - EINVAL ;
c - > bounds . left = 0 ;
c - > bounds . top = 0 ;
2010-09-19 06:00:54 -03:00
c - > bounds . width = cam - > width ;
c - > bounds . height = cam - > height ;
2006-02-27 00:09:05 -03:00
c - > defrect . left = 0 ;
c - > defrect . top = 0 ;
2010-09-19 06:00:54 -03:00
c - > defrect . width = cam - > width ;
c - > defrect . height = cam - > height ;
2006-02-27 00:09:05 -03:00
c - > pixelaspect . numerator = 1 ;
c - > pixelaspect . denominator = 1 ;
return 0 ;
}
2012-04-29 08:44:44 -03:00
struct framerate_info {
int value ;
struct v4l2_fract period ;
} ;
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
static const struct framerate_info framerate_controls [ ] = {
{ CPIA2_VP_FRAMERATE_6_25 , { 4 , 25 } } ,
{ CPIA2_VP_FRAMERATE_7_5 , { 2 , 15 } } ,
{ CPIA2_VP_FRAMERATE_12_5 , { 2 , 25 } } ,
{ CPIA2_VP_FRAMERATE_15 , { 1 , 15 } } ,
{ CPIA2_VP_FRAMERATE_25 , { 1 , 25 } } ,
{ CPIA2_VP_FRAMERATE_30 , { 1 , 30 } } ,
} ;
static int cpia2_g_parm ( struct file * file , void * fh , struct v4l2_streamparm * p )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2012-04-29 08:44:44 -03:00
struct v4l2_captureparm * cap = & p - > parm . capture ;
2006-02-27 00:09:05 -03:00
int i ;
2012-04-29 08:44:44 -03:00
if ( p - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE )
2006-02-27 00:09:05 -03:00
return - EINVAL ;
2012-04-29 08:44:44 -03:00
cap - > capability = V4L2_CAP_TIMEPERFRAME ;
cap - > readbuffers = cam - > num_frames ;
for ( i = 0 ; i < ARRAY_SIZE ( framerate_controls ) ; i + + )
if ( cam - > params . vp_params . frame_rate = = framerate_controls [ i ] . value ) {
cap - > timeperframe = framerate_controls [ i ] . period ;
break ;
2006-02-27 00:09:05 -03:00
}
return 0 ;
}
2012-04-29 08:44:44 -03:00
static int cpia2_s_parm ( struct file * file , void * fh , struct v4l2_streamparm * p )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2012-04-29 08:44:44 -03:00
struct v4l2_captureparm * cap = & p - > parm . capture ;
struct v4l2_fract tpf = cap - > timeperframe ;
int max = ARRAY_SIZE ( framerate_controls ) - 1 ;
int ret ;
int i ;
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
ret = cpia2_g_parm ( file , fh , p ) ;
if ( ret | | ! tpf . denominator | | ! tpf . numerator )
return ret ;
/* Maximum 15 fps for this model */
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 & &
cam - > params . version . sensor_flags = = CPIA2_VP_SENSOR_FLAGS_500 )
max - = 2 ;
for ( i = 0 ; i < = max ; i + + ) {
struct v4l2_fract f1 = tpf ;
struct v4l2_fract f2 = framerate_controls [ i ] . period ;
f1 . numerator * = f2 . denominator ;
f2 . numerator * = f1 . denominator ;
if ( f1 . numerator > = f2 . numerator )
break ;
}
if ( i > max )
i = max ;
cap - > timeperframe = framerate_controls [ i ] . period ;
return cpia2_set_fps ( cam , framerate_controls [ i ] . value ) ;
}
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
static const struct {
u32 width ;
u32 height ;
} cpia2_framesizes [ ] = {
{ 640 , 480 } ,
{ 352 , 288 } ,
{ 320 , 240 } ,
{ 288 , 216 } ,
{ 256 , 192 } ,
{ 224 , 168 } ,
{ 192 , 144 } ,
{ 176 , 144 } ,
} ;
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
static int cpia2_enum_framesizes ( struct file * file , void * fh ,
struct v4l2_frmsizeenum * fsize )
{
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
if ( fsize - > pixel_format ! = V4L2_PIX_FMT_MJPEG & &
fsize - > pixel_format ! = V4L2_PIX_FMT_JPEG )
2006-02-27 00:09:05 -03:00
return - EINVAL ;
2012-04-29 08:44:44 -03:00
if ( fsize - > index > = ARRAY_SIZE ( cpia2_framesizes ) )
return - EINVAL ;
fsize - > type = V4L2_FRMSIZE_TYPE_DISCRETE ;
fsize - > discrete . width = cpia2_framesizes [ fsize - > index ] . width ;
fsize - > discrete . height = cpia2_framesizes [ fsize - > index ] . height ;
2006-02-27 00:09:05 -03:00
return 0 ;
}
2012-04-29 08:44:44 -03:00
static int cpia2_enum_frameintervals ( struct file * file , void * fh ,
struct v4l2_frmivalenum * fival )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2012-04-29 08:44:44 -03:00
int max = ARRAY_SIZE ( framerate_controls ) - 1 ;
int i ;
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
if ( fival - > pixel_format ! = V4L2_PIX_FMT_MJPEG & &
fival - > pixel_format ! = V4L2_PIX_FMT_JPEG )
2006-02-27 00:09:05 -03:00
return - EINVAL ;
2012-04-29 08:44:44 -03:00
/* Maximum 15 fps for this model */
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 & &
cam - > params . version . sensor_flags = = CPIA2_VP_SENSOR_FLAGS_500 )
max - = 2 ;
if ( fival - > index > max )
return - EINVAL ;
for ( i = 0 ; i < ARRAY_SIZE ( cpia2_framesizes ) ; i + + )
if ( fival - > width = = cpia2_framesizes [ i ] . width & &
fival - > height = = cpia2_framesizes [ i ] . height )
break ;
if ( i = = ARRAY_SIZE ( cpia2_framesizes ) )
return - EINVAL ;
fival - > type = V4L2_FRMIVAL_TYPE_DISCRETE ;
fival - > discrete = framerate_controls [ fival - > index ] . period ;
2006-02-27 00:09:05 -03:00
return 0 ;
}
/******************************************************************************
*
* ioctl_s_ctrl
*
* V4L2 set the value of a control variable
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-04-29 08:44:44 -03:00
static int cpia2_s_ctrl ( struct v4l2_ctrl * ctrl )
2006-02-27 00:09:05 -03:00
{
2012-04-29 08:44:44 -03:00
struct camera_data * cam =
container_of ( ctrl - > handler , struct camera_data , hdl ) ;
static const int flicker_table [ ] = {
NEVER_FLICKER ,
FLICKER_50 ,
FLICKER_60 ,
} ;
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
DBG ( " Set control id:%d, value:%d \n " , ctrl - > id , ctrl - > val ) ;
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
switch ( ctrl - > id ) {
2006-02-27 00:09:05 -03:00
case V4L2_CID_BRIGHTNESS :
2012-04-29 08:44:44 -03:00
cpia2_set_brightness ( cam , ctrl - > val ) ;
2006-02-27 00:09:05 -03:00
break ;
case V4L2_CID_CONTRAST :
2012-04-29 08:44:44 -03:00
cpia2_set_contrast ( cam , ctrl - > val ) ;
2006-02-27 00:09:05 -03:00
break ;
case V4L2_CID_SATURATION :
2012-04-29 08:44:44 -03:00
cpia2_set_saturation ( cam , ctrl - > val ) ;
2006-02-27 00:09:05 -03:00
break ;
case V4L2_CID_HFLIP :
2012-04-29 08:44:44 -03:00
cpia2_set_property_mirror ( cam , ctrl - > val ) ;
2006-02-27 00:09:05 -03:00
break ;
case V4L2_CID_VFLIP :
2012-04-29 08:44:44 -03:00
cpia2_set_property_flip ( cam , ctrl - > val ) ;
2006-02-27 00:09:05 -03:00
break ;
2012-04-29 08:44:44 -03:00
case V4L2_CID_POWER_LINE_FREQUENCY :
return cpia2_set_flicker_mode ( cam , flicker_table [ ctrl - > val ] ) ;
case V4L2_CID_ILLUMINATORS_1 :
return cpia2_set_gpio ( cam , ( cam - > top_light - > val < < 6 ) |
( cam - > bottom_light - > val < < 7 ) ) ;
case V4L2_CID_JPEG_ACTIVE_MARKER :
cam - > params . compression . inhibit_htables =
! ( ctrl - > val & V4L2_JPEG_ACTIVE_MARKER_DHT ) ;
2006-02-27 00:09:05 -03:00
break ;
2012-04-29 08:44:44 -03:00
case V4L2_CID_JPEG_COMPRESSION_QUALITY :
cam - > params . vc_params . quality = ctrl - > val ;
2006-02-27 00:09:05 -03:00
break ;
case CPIA2_CID_USB_ALT :
2012-04-29 08:44:44 -03:00
cam - > params . camera_state . stream_mode = ctrl - > val ;
2006-02-27 00:09:05 -03:00
break ;
default :
2012-04-29 08:44:44 -03:00
return - EINVAL ;
2006-02-27 00:09:05 -03:00
}
2012-04-29 08:44:44 -03:00
return 0 ;
2006-02-27 00:09:05 -03:00
}
/******************************************************************************
*
* ioctl_g_jpegcomp
*
* V4L2 get the JPEG compression parameters
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-01-22 06:36:02 -03:00
static int cpia2_g_jpegcomp ( struct file * file , void * fh , struct v4l2_jpegcompression * parms )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2006-02-27 00:09:05 -03:00
memset ( parms , 0 , sizeof ( * parms ) ) ;
parms - > quality = 80 ; // TODO: Can this be made meaningful?
parms - > jpeg_markers = V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI ;
if ( ! cam - > params . compression . inhibit_htables ) {
parms - > jpeg_markers | = V4L2_JPEG_MARKER_DHT ;
}
parms - > APPn = cam - > APPn ;
parms - > APP_len = cam - > APP_len ;
if ( cam - > APP_len > 0 ) {
memcpy ( parms - > APP_data , cam - > APP_data , cam - > APP_len ) ;
parms - > jpeg_markers | = V4L2_JPEG_MARKER_APP ;
}
parms - > COM_len = cam - > COM_len ;
if ( cam - > COM_len > 0 ) {
memcpy ( parms - > COM_data , cam - > COM_data , cam - > COM_len ) ;
parms - > jpeg_markers | = JPEG_MARKER_COM ;
}
DBG ( " G_JPEGCOMP APP_len:%d COM_len:%d \n " ,
parms - > APP_len , parms - > COM_len ) ;
return 0 ;
}
/******************************************************************************
*
* ioctl_s_jpegcomp
*
* V4L2 set the JPEG compression parameters
* NOTE : quality and some jpeg_markers are ignored .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-09-17 05:05:25 -03:00
static int cpia2_s_jpegcomp ( struct file * file , void * fh ,
const struct v4l2_jpegcompression * parms )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2006-02-27 00:09:05 -03:00
DBG ( " S_JPEGCOMP APP_len:%d COM_len:%d \n " ,
parms - > APP_len , parms - > COM_len ) ;
cam - > params . compression . inhibit_htables =
! ( parms - > jpeg_markers & V4L2_JPEG_MARKER_DHT ) ;
if ( parms - > APP_len ! = 0 ) {
if ( parms - > APP_len > 0 & &
parms - > APP_len < = sizeof ( cam - > APP_data ) & &
parms - > APPn > = 0 & & parms - > APPn < = 15 ) {
cam - > APPn = parms - > APPn ;
cam - > APP_len = parms - > APP_len ;
memcpy ( cam - > APP_data , parms - > APP_data , parms - > APP_len ) ;
} else {
LOG ( " Bad APPn Params n=%d len=%d \n " ,
parms - > APPn , parms - > APP_len ) ;
return - EINVAL ;
}
} else {
cam - > APP_len = 0 ;
}
if ( parms - > COM_len ! = 0 ) {
if ( parms - > COM_len > 0 & &
parms - > COM_len < = sizeof ( cam - > COM_data ) ) {
cam - > COM_len = parms - > COM_len ;
memcpy ( cam - > COM_data , parms - > COM_data , parms - > COM_len ) ;
} else {
LOG ( " Bad COM_len=%d \n " , parms - > COM_len ) ;
return - EINVAL ;
}
}
return 0 ;
}
/******************************************************************************
*
* ioctl_reqbufs
*
* V4L2 Initiate memory mapping .
* NOTE : The user ' s request is ignored . For now the buffers are fixed .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-01-22 06:36:02 -03:00
static int cpia2_reqbufs ( struct file * file , void * fh , struct v4l2_requestbuffers * req )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2006-02-27 00:09:05 -03:00
if ( req - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE | |
req - > memory ! = V4L2_MEMORY_MMAP )
return - EINVAL ;
DBG ( " REQBUFS requested:%d returning:%d \n " , req - > count , cam - > num_frames ) ;
req - > count = cam - > num_frames ;
memset ( & req - > reserved , 0 , sizeof ( req - > reserved ) ) ;
return 0 ;
}
/******************************************************************************
*
* ioctl_querybuf
*
* V4L2 Query memory buffer status .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-01-22 06:36:02 -03:00
static int cpia2_querybuf ( struct file * file , void * fh , struct v4l2_buffer * buf )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2006-02-27 00:09:05 -03:00
if ( buf - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE | |
buf - > index > cam - > num_frames )
return - EINVAL ;
buf - > m . offset = cam - > buffers [ buf - > index ] . data - cam - > frame_buffer ;
buf - > length = cam - > frame_size ;
buf - > memory = V4L2_MEMORY_MMAP ;
if ( cam - > mmapped )
buf - > flags = V4L2_BUF_FLAG_MAPPED ;
else
buf - > flags = 0 ;
switch ( cam - > buffers [ buf - > index ] . status ) {
case FRAME_EMPTY :
case FRAME_ERROR :
case FRAME_READING :
buf - > bytesused = 0 ;
buf - > flags = V4L2_BUF_FLAG_QUEUED ;
break ;
case FRAME_READY :
buf - > bytesused = cam - > buffers [ buf - > index ] . length ;
buf - > timestamp = cam - > buffers [ buf - > index ] . timestamp ;
buf - > sequence = cam - > buffers [ buf - > index ] . seq ;
buf - > flags = V4L2_BUF_FLAG_DONE ;
break ;
}
DBG ( " QUERYBUF index:%d offset:%d flags:%d seq:%d bytesused:%d \n " ,
buf - > index , buf - > m . offset , buf - > flags , buf - > sequence ,
buf - > bytesused ) ;
return 0 ;
}
/******************************************************************************
*
* ioctl_qbuf
*
* V4L2 User is freeing buffer
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-01-22 06:36:02 -03:00
static int cpia2_qbuf ( struct file * file , void * fh , struct v4l2_buffer * buf )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2006-02-27 00:09:05 -03:00
if ( buf - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE | |
buf - > memory ! = V4L2_MEMORY_MMAP | |
buf - > index > cam - > num_frames )
return - EINVAL ;
DBG ( " QBUF #%d \n " , buf - > index ) ;
if ( cam - > buffers [ buf - > index ] . status = = FRAME_READY )
cam - > buffers [ buf - > index ] . status = FRAME_EMPTY ;
return 0 ;
}
/******************************************************************************
*
* find_earliest_filled_buffer
*
* Helper for ioctl_dqbuf . Find the next ready buffer .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int find_earliest_filled_buffer ( struct camera_data * cam )
{
int i ;
int found = - 1 ;
for ( i = 0 ; i < cam - > num_frames ; i + + ) {
if ( cam - > buffers [ i ] . status = = FRAME_READY ) {
if ( found < 0 ) {
found = i ;
} else {
/* find which buffer is earlier */
struct timeval * tv1 , * tv2 ;
tv1 = & cam - > buffers [ i ] . timestamp ;
tv2 = & cam - > buffers [ found ] . timestamp ;
if ( tv1 - > tv_sec < tv2 - > tv_sec | |
( tv1 - > tv_sec = = tv2 - > tv_sec & &
tv1 - > tv_usec < tv2 - > tv_usec ) )
found = i ;
}
}
}
return found ;
}
/******************************************************************************
*
* ioctl_dqbuf
*
* V4L2 User is asking for a filled buffer .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-01-22 06:36:02 -03:00
static int cpia2_dqbuf ( struct file * file , void * fh , struct v4l2_buffer * buf )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2006-02-27 00:09:05 -03:00
int frame ;
if ( buf - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE | |
buf - > memory ! = V4L2_MEMORY_MMAP )
return - EINVAL ;
frame = find_earliest_filled_buffer ( cam ) ;
if ( frame < 0 & & file - > f_flags & O_NONBLOCK )
return - EAGAIN ;
if ( frame < 0 ) {
/* Wait for a frame to become available */
struct framebuf * cb = cam - > curbuff ;
2010-12-18 09:50:43 -03:00
mutex_unlock ( & cam - > v4l2_lock ) ;
2006-02-27 00:09:05 -03:00
wait_event_interruptible ( cam - > wq_stream ,
2012-04-29 08:44:44 -03:00
! video_is_registered ( & cam - > vdev ) | |
2006-02-27 00:09:05 -03:00
( cb = cam - > curbuff ) - > status = = FRAME_READY ) ;
2010-12-18 09:50:43 -03:00
mutex_lock ( & cam - > v4l2_lock ) ;
2006-02-27 00:09:05 -03:00
if ( signal_pending ( current ) )
return - ERESTARTSYS ;
2012-04-29 08:44:44 -03:00
if ( ! video_is_registered ( & cam - > vdev ) )
2006-02-27 00:09:05 -03:00
return - ENOTTY ;
frame = cb - > num ;
}
buf - > index = frame ;
buf - > bytesused = cam - > buffers [ buf - > index ] . length ;
buf - > flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE ;
buf - > field = V4L2_FIELD_NONE ;
buf - > timestamp = cam - > buffers [ buf - > index ] . timestamp ;
buf - > sequence = cam - > buffers [ buf - > index ] . seq ;
buf - > m . offset = cam - > buffers [ buf - > index ] . data - cam - > frame_buffer ;
buf - > length = cam - > frame_size ;
2012-05-02 09:40:03 -03:00
buf - > reserved2 = 0 ;
2006-02-27 00:09:05 -03:00
buf - > reserved = 0 ;
memset ( & buf - > timecode , 0 , sizeof ( buf - > timecode ) ) ;
DBG ( " DQBUF #%d status:%d seq:%d length:%d \n " , buf - > index ,
cam - > buffers [ buf - > index ] . status , buf - > sequence , buf - > bytesused ) ;
return 0 ;
}
2011-01-22 06:36:02 -03:00
static int cpia2_streamon ( struct file * file , void * fh , enum v4l2_buf_type type )
{
struct camera_data * cam = video_drvdata ( file ) ;
2012-04-29 08:44:44 -03:00
int ret = - EINVAL ;
2006-02-27 00:09:05 -03:00
2011-01-22 06:36:02 -03:00
DBG ( " VIDIOC_STREAMON, streaming=%d \n " , cam - > streaming ) ;
if ( ! cam - > mmapped | | type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE )
return - EINVAL ;
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
if ( ! cam - > streaming ) {
ret = cpia2_usb_stream_start ( cam ,
2011-01-22 06:36:02 -03:00
cam - > params . camera_state . stream_mode ) ;
2012-04-29 08:44:44 -03:00
if ( ! ret )
v4l2_ctrl_grab ( cam - > usb_alt , true ) ;
}
return ret ;
2006-02-27 00:09:05 -03:00
}
2011-01-22 06:36:02 -03:00
static int cpia2_streamoff ( struct file * file , void * fh , enum v4l2_buf_type type )
2006-02-27 00:09:05 -03:00
{
2011-01-22 06:36:02 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2012-04-29 08:44:44 -03:00
int ret = - EINVAL ;
2011-01-22 06:36:02 -03:00
DBG ( " VIDIOC_STREAMOFF, streaming=%d \n " , cam - > streaming ) ;
if ( ! cam - > mmapped | | type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE )
return - EINVAL ;
2012-04-29 08:44:44 -03:00
if ( cam - > streaming ) {
ret = cpia2_usb_stream_stop ( cam ) ;
if ( ! ret )
v4l2_ctrl_grab ( cam - > usb_alt , false ) ;
}
return ret ;
2006-02-27 00:09:05 -03:00
}
/******************************************************************************
*
* cpia2_mmap
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int cpia2_mmap ( struct file * file , struct vm_area_struct * area )
{
2008-08-23 08:32:09 -03:00
struct camera_data * cam = video_drvdata ( file ) ;
2006-02-27 00:09:05 -03:00
int retval ;
2012-06-23 07:56:21 -03:00
if ( mutex_lock_interruptible ( & cam - > v4l2_lock ) )
return - ERESTARTSYS ;
2006-02-27 00:09:05 -03:00
retval = cpia2_remap_buffer ( cam , area ) ;
if ( ! retval )
2012-04-29 08:44:44 -03:00
cam - > stream_fh = file - > private_data ;
2012-06-23 07:56:21 -03:00
mutex_unlock ( & cam - > v4l2_lock ) ;
2006-02-27 00:09:05 -03:00
return retval ;
}
/******************************************************************************
*
* reset_camera_struct_v4l
*
* Sets all values to the defaults
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void reset_camera_struct_v4l ( struct camera_data * cam )
{
2010-09-19 06:00:54 -03:00
cam - > width = cam - > params . roi . width ;
cam - > height = cam - > params . roi . height ;
2006-02-27 00:09:05 -03:00
cam - > frame_size = buffer_size ;
cam - > num_frames = num_buffers ;
2012-04-29 08:44:44 -03:00
/* Flicker modes */
2006-02-27 00:09:05 -03:00
cam - > params . flicker_control . flicker_mode_req = flicker_mode ;
2012-04-29 08:44:44 -03:00
/* stream modes */
2006-02-27 00:09:05 -03:00
cam - > params . camera_state . stream_mode = alternate ;
cam - > pixelformat = V4L2_PIX_FMT_JPEG ;
}
2011-01-22 06:36:02 -03:00
static const struct v4l2_ioctl_ops cpia2_ioctl_ops = {
. vidioc_querycap = cpia2_querycap ,
. vidioc_enum_input = cpia2_enum_input ,
. vidioc_g_input = cpia2_g_input ,
. vidioc_s_input = cpia2_s_input ,
. vidioc_enum_fmt_vid_cap = cpia2_enum_fmt_vid_cap ,
. vidioc_g_fmt_vid_cap = cpia2_g_fmt_vid_cap ,
. vidioc_s_fmt_vid_cap = cpia2_s_fmt_vid_cap ,
. vidioc_try_fmt_vid_cap = cpia2_try_fmt_vid_cap ,
. vidioc_g_jpegcomp = cpia2_g_jpegcomp ,
. vidioc_s_jpegcomp = cpia2_s_jpegcomp ,
. vidioc_cropcap = cpia2_cropcap ,
. vidioc_reqbufs = cpia2_reqbufs ,
. vidioc_querybuf = cpia2_querybuf ,
. vidioc_qbuf = cpia2_qbuf ,
. vidioc_dqbuf = cpia2_dqbuf ,
. vidioc_streamon = cpia2_streamon ,
. vidioc_streamoff = cpia2_streamoff ,
2012-04-29 08:44:44 -03:00
. vidioc_s_parm = cpia2_s_parm ,
. vidioc_g_parm = cpia2_g_parm ,
. vidioc_enum_framesizes = cpia2_enum_framesizes ,
. vidioc_enum_frameintervals = cpia2_enum_frameintervals ,
. vidioc_subscribe_event = v4l2_ctrl_subscribe_event ,
. vidioc_unsubscribe_event = v4l2_event_unsubscribe ,
2011-01-22 06:36:02 -03:00
} ;
2006-02-27 00:09:05 -03:00
/***
* The v4l video device structure initialized for this device
* * */
2010-09-19 06:00:54 -03:00
static const struct v4l2_file_operations cpia2_fops = {
2006-03-20 13:59:42 -03:00
. owner = THIS_MODULE ,
. open = cpia2_open ,
. release = cpia2_close ,
. read = cpia2_v4l_read ,
. poll = cpia2_v4l_poll ,
2011-01-22 06:36:02 -03:00
. unlocked_ioctl = video_ioctl2 ,
2006-03-20 13:59:42 -03:00
. mmap = cpia2_mmap ,
2006-02-27 00:09:05 -03:00
} ;
static struct video_device cpia2_template = {
/* I could not find any place for the old .initialize initializer?? */
2010-09-19 06:00:54 -03:00
. name = " CPiA2 Camera " ,
. fops = & cpia2_fops ,
2011-01-22 06:36:02 -03:00
. ioctl_ops = & cpia2_ioctl_ops ,
2012-04-29 08:44:44 -03:00
. release = video_device_release_empty ,
} ;
void cpia2_camera_release ( struct v4l2_device * v4l2_dev )
{
struct camera_data * cam =
container_of ( v4l2_dev , struct camera_data , v4l2_dev ) ;
v4l2_ctrl_handler_free ( & cam - > hdl ) ;
v4l2_device_unregister ( & cam - > v4l2_dev ) ;
kfree ( cam ) ;
}
static const struct v4l2_ctrl_ops cpia2_ctrl_ops = {
. s_ctrl = cpia2_s_ctrl ,
2006-02-27 00:09:05 -03:00
} ;
/******************************************************************************
*
* cpia2_register_camera
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cpia2_register_camera ( struct camera_data * cam )
{
2012-04-29 08:44:44 -03:00
struct v4l2_ctrl_handler * hdl = & cam - > hdl ;
struct v4l2_ctrl_config cpia2_usb_alt = {
. ops = & cpia2_ctrl_ops ,
. id = CPIA2_CID_USB_ALT ,
. name = " USB Alternate " ,
. type = V4L2_CTRL_TYPE_INTEGER ,
. min = USBIF_ISO_1 ,
. max = USBIF_ISO_6 ,
. step = 1 ,
} ;
int ret ;
v4l2_ctrl_handler_init ( hdl , 12 ) ;
v4l2_ctrl_new_std ( hdl , & cpia2_ctrl_ops ,
V4L2_CID_BRIGHTNESS ,
cam - > params . pnp_id . device_type = = DEVICE_STV_672 ? 1 : 0 ,
255 , 1 , DEFAULT_BRIGHTNESS ) ;
v4l2_ctrl_new_std ( hdl , & cpia2_ctrl_ops ,
V4L2_CID_CONTRAST , 0 , 255 , 1 , DEFAULT_CONTRAST ) ;
v4l2_ctrl_new_std ( hdl , & cpia2_ctrl_ops ,
V4L2_CID_SATURATION , 0 , 255 , 1 , DEFAULT_SATURATION ) ;
v4l2_ctrl_new_std ( hdl , & cpia2_ctrl_ops ,
V4L2_CID_HFLIP , 0 , 1 , 1 , 0 ) ;
v4l2_ctrl_new_std ( hdl , & cpia2_ctrl_ops ,
V4L2_CID_JPEG_ACTIVE_MARKER , 0 ,
V4L2_JPEG_ACTIVE_MARKER_DHT , 0 ,
V4L2_JPEG_ACTIVE_MARKER_DHT ) ;
v4l2_ctrl_new_std ( hdl , & cpia2_ctrl_ops ,
V4L2_CID_JPEG_COMPRESSION_QUALITY , 1 ,
100 , 1 , 100 ) ;
cpia2_usb_alt . def = alternate ;
cam - > usb_alt = v4l2_ctrl_new_custom ( hdl , & cpia2_usb_alt , NULL ) ;
/* VP5 Only */
if ( cam - > params . pnp_id . device_type ! = DEVICE_STV_672 )
v4l2_ctrl_new_std ( hdl , & cpia2_ctrl_ops ,
V4L2_CID_VFLIP , 0 , 1 , 1 , 0 ) ;
/* Flicker control only valid for 672 */
if ( cam - > params . pnp_id . device_type = = DEVICE_STV_672 )
v4l2_ctrl_new_std_menu ( hdl , & cpia2_ctrl_ops ,
V4L2_CID_POWER_LINE_FREQUENCY ,
V4L2_CID_POWER_LINE_FREQUENCY_60HZ , 0 , 0 ) ;
/* Light control only valid for the QX5 Microscope */
if ( cam - > params . pnp_id . product = = 0x151 ) {
cam - > top_light = v4l2_ctrl_new_std ( hdl , & cpia2_ctrl_ops ,
V4L2_CID_ILLUMINATORS_1 , 0 , 1 , 1 , 0 ) ;
cam - > bottom_light = v4l2_ctrl_new_std ( hdl , & cpia2_ctrl_ops ,
V4L2_CID_ILLUMINATORS_2 , 0 , 1 , 1 , 0 ) ;
v4l2_ctrl_cluster ( 2 , & cam - > top_light ) ;
}
2006-02-27 00:09:05 -03:00
2012-04-29 08:44:44 -03:00
if ( hdl - > error ) {
ret = hdl - > error ;
v4l2_ctrl_handler_free ( hdl ) ;
return ret ;
}
cam - > vdev = cpia2_template ;
video_set_drvdata ( & cam - > vdev , cam ) ;
cam - > vdev . lock = & cam - > v4l2_lock ;
cam - > vdev . ctrl_handler = hdl ;
cam - > vdev . v4l2_dev = & cam - > v4l2_dev ;
set_bit ( V4L2_FL_USE_FH_PRIO , & cam - > vdev . flags ) ;
2006-02-27 00:09:05 -03:00
reset_camera_struct_v4l ( cam ) ;
/* register v4l device */
2012-04-29 08:44:44 -03:00
if ( video_register_device ( & cam - > vdev , VFL_TYPE_GRABBER , video_nr ) < 0 ) {
2006-02-27 00:09:05 -03:00
ERR ( " video_register_device failed \n " ) ;
return - ENODEV ;
}
return 0 ;
}
/******************************************************************************
*
* cpia2_unregister_camera
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cpia2_unregister_camera ( struct camera_data * cam )
{
2012-04-29 08:44:44 -03:00
video_unregister_device ( & cam - > vdev ) ;
2006-02-27 00:09:05 -03:00
}
/******************************************************************************
*
* check_parameters
*
* Make sure that all user - supplied parameters are sensible
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void __init check_parameters ( void )
{
if ( buffer_size < PAGE_SIZE ) {
buffer_size = PAGE_SIZE ;
LOG ( " buffer_size too small, setting to %d \n " , buffer_size ) ;
} else if ( buffer_size > 1024 * 1024 ) {
/* arbitrary upper limiit */
buffer_size = 1024 * 1024 ;
LOG ( " buffer_size ridiculously large, setting to %d \n " ,
buffer_size ) ;
} else {
buffer_size + = PAGE_SIZE - 1 ;
buffer_size & = ~ ( PAGE_SIZE - 1 ) ;
}
if ( num_buffers < 1 ) {
num_buffers = 1 ;
LOG ( " num_buffers too small, setting to %d \n " , num_buffers ) ;
} else if ( num_buffers > VIDEO_MAX_FRAME ) {
num_buffers = VIDEO_MAX_FRAME ;
LOG ( " num_buffers too large, setting to %d \n " , num_buffers ) ;
}
if ( alternate < USBIF_ISO_1 | | alternate > USBIF_ISO_6 ) {
alternate = DEFAULT_ALT ;
LOG ( " alternate specified is invalid, using %d \n " , alternate ) ;
}
2012-04-29 08:44:44 -03:00
if ( flicker_mode ! = 0 & & flicker_mode ! = FLICKER_50 & & flicker_mode ! = FLICKER_60 ) {
flicker_mode = 0 ;
2006-02-27 00:09:05 -03:00
LOG ( " Flicker mode specified is invalid, using %d \n " ,
flicker_mode ) ;
}
DBG ( " Using %d buffers, each %d bytes, alternate=%d \n " ,
num_buffers , buffer_size , alternate ) ;
}
/************ Module Stuff ***************/
/******************************************************************************
*
* cpia2_init / module_init
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-28 04:40:51 -03:00
static int __init cpia2_init ( void )
2006-02-27 00:09:05 -03:00
{
[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 14:45:49 -03:00
LOG ( " %s v%s \n " ,
ABOUT , CPIA_VERSION ) ;
2006-02-27 00:09:05 -03:00
check_parameters ( ) ;
cpia2_usb_init ( ) ;
return 0 ;
}
/******************************************************************************
*
* cpia2_exit / module_exit
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-28 04:40:51 -03:00
static void __exit cpia2_exit ( void )
2006-02-27 00:09:05 -03:00
{
cpia2_usb_cleanup ( ) ;
schedule_timeout ( 2 * HZ ) ;
}
module_init ( cpia2_init ) ;
module_exit ( cpia2_exit ) ;