2005-04-16 15:20:36 -07:00
/*
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
*
* ( c ) 2001 - 03 Gerd Knorr < kraxel @ bytesex . org > [ SuSE Labs ]
*
* 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 .
*/
# include <linux/init.h>
# include <linux/list.h>
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/slab.h>
2007-04-27 12:31:18 -03:00
# include <linux/sort.h>
2005-04-16 15:20:36 -07:00
# include "saa7134-reg.h"
# include "saa7134.h"
2006-01-09 15:32:31 -02:00
# include <media/v4l2-common.h>
2010-12-27 12:22:46 -03:00
# include <media/saa6588.h>
2005-04-16 15:20:36 -07:00
/* ------------------------------------------------------------------ */
2007-12-07 17:34:48 -03:00
unsigned int video_debug ;
2005-04-16 15:20:36 -07:00
static unsigned int gbuffers = 8 ;
2008-04-22 14:41:48 -03:00
static unsigned int noninterlaced ; /* 0 */
2005-04-16 15:20:36 -07:00
static unsigned int gbufsize = 720 * 576 * 4 ;
static unsigned int gbufsize_max = 720 * 576 * 4 ;
2006-10-02 19:55:07 -03:00
static char secam [ ] = " -- " ;
2005-04-16 15:20:36 -07:00
module_param ( video_debug , int , 0644 ) ;
MODULE_PARM_DESC ( video_debug , " enable debug messages [video] " ) ;
module_param ( gbuffers , int , 0444 ) ;
MODULE_PARM_DESC ( gbuffers , " number of capture buffers, range 2-32 " ) ;
module_param ( noninterlaced , int , 0644 ) ;
2006-07-15 09:45:34 -03:00
MODULE_PARM_DESC ( noninterlaced , " capture non interlaced video " ) ;
2006-10-02 19:55:07 -03:00
module_param_string ( secam , secam , sizeof ( secam ) , 0644 ) ;
MODULE_PARM_DESC ( secam , " force SECAM variant, either DK,L or Lc " ) ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:34:48 -03:00
# define dprintk(fmt, arg...) if (video_debug&0x04) \
2005-04-16 15:20:36 -07:00
printk ( KERN_DEBUG " %s/video: " fmt , dev - > name , # # arg )
2005-11-08 21:37:10 -08:00
/* ------------------------------------------------------------------ */
/* Defines for Video Output Port Register at address 0x191 */
/* Bit 0: VIP code T bit polarity */
# define VP_T_CODE_P_NON_INVERTED 0x00
# define VP_T_CODE_P_INVERTED 0x01
/* ------------------------------------------------------------------ */
/* Defines for Video Output Port Register at address 0x195 */
/* Bit 2: Video output clock delay control */
# define VP_CLK_CTRL2_NOT_DELAYED 0x00
# define VP_CLK_CTRL2_DELAYED 0x04
/* Bit 1: Video output clock invert control */
# define VP_CLK_CTRL1_NON_INVERTED 0x00
# define VP_CLK_CTRL1_INVERTED 0x02
/* ------------------------------------------------------------------ */
/* Defines for Video Output Port Register at address 0x196 */
/* Bits 2 to 0: VSYNC pin video vertical sync type */
# define VP_VS_TYPE_MASK 0x07
# define VP_VS_TYPE_OFF 0x00
# define VP_VS_TYPE_V123 0x01
# define VP_VS_TYPE_V_ITU 0x02
# define VP_VS_TYPE_VGATE_L 0x03
# define VP_VS_TYPE_RESERVED1 0x04
# define VP_VS_TYPE_RESERVED2 0x05
# define VP_VS_TYPE_F_ITU 0x06
# define VP_VS_TYPE_SC_FID 0x07
2005-04-16 15:20:36 -07:00
/* ------------------------------------------------------------------ */
/* data structs for video */
static int video_out [ ] [ 9 ] = {
[ CCIR656 ] = { 0x00 , 0xb1 , 0x00 , 0xa1 , 0x00 , 0x04 , 0x06 , 0x00 , 0x00 } ,
} ;
static struct saa7134_format formats [ ] = {
{
. name = " 8 bpp gray " ,
. fourcc = V4L2_PIX_FMT_GREY ,
. depth = 8 ,
. pm = 0x06 ,
} , {
. name = " 15 bpp RGB, le " ,
. fourcc = V4L2_PIX_FMT_RGB555 ,
. depth = 16 ,
. pm = 0x13 | 0x80 ,
} , {
. name = " 15 bpp RGB, be " ,
. fourcc = V4L2_PIX_FMT_RGB555X ,
. depth = 16 ,
. pm = 0x13 | 0x80 ,
. bswap = 1 ,
} , {
. name = " 16 bpp RGB, le " ,
. fourcc = V4L2_PIX_FMT_RGB565 ,
. depth = 16 ,
. pm = 0x10 | 0x80 ,
} , {
. name = " 16 bpp RGB, be " ,
. fourcc = V4L2_PIX_FMT_RGB565X ,
. depth = 16 ,
. pm = 0x10 | 0x80 ,
. bswap = 1 ,
} , {
. name = " 24 bpp RGB, le " ,
. fourcc = V4L2_PIX_FMT_BGR24 ,
. depth = 24 ,
. pm = 0x11 ,
} , {
. name = " 24 bpp RGB, be " ,
. fourcc = V4L2_PIX_FMT_RGB24 ,
. depth = 24 ,
. pm = 0x11 ,
. bswap = 1 ,
} , {
. name = " 32 bpp RGB, le " ,
. fourcc = V4L2_PIX_FMT_BGR32 ,
. depth = 32 ,
. pm = 0x12 ,
} , {
. name = " 32 bpp RGB, be " ,
. fourcc = V4L2_PIX_FMT_RGB32 ,
. depth = 32 ,
. pm = 0x12 ,
. bswap = 1 ,
. wswap = 1 ,
} , {
. name = " 4:2:2 packed, YUYV " ,
. fourcc = V4L2_PIX_FMT_YUYV ,
. depth = 16 ,
. pm = 0x00 ,
. bswap = 1 ,
. yuv = 1 ,
} , {
. name = " 4:2:2 packed, UYVY " ,
. fourcc = V4L2_PIX_FMT_UYVY ,
. depth = 16 ,
. pm = 0x00 ,
. yuv = 1 ,
} , {
. name = " 4:2:2 planar, Y-Cb-Cr " ,
. fourcc = V4L2_PIX_FMT_YUV422P ,
. depth = 16 ,
. pm = 0x09 ,
. yuv = 1 ,
. planar = 1 ,
. hshift = 1 ,
. vshift = 0 ,
} , {
. name = " 4:2:0 planar, Y-Cb-Cr " ,
. fourcc = V4L2_PIX_FMT_YUV420 ,
. depth = 12 ,
. pm = 0x0a ,
. yuv = 1 ,
. planar = 1 ,
. hshift = 1 ,
. vshift = 1 ,
} , {
. name = " 4:2:0 planar, Y-Cb-Cr " ,
. fourcc = V4L2_PIX_FMT_YVU420 ,
. depth = 12 ,
. pm = 0x0a ,
. yuv = 1 ,
. planar = 1 ,
. uvswap = 1 ,
. hshift = 1 ,
. vshift = 1 ,
}
} ;
# define FORMATS ARRAY_SIZE(formats)
# define NORM_625_50 \
. h_start = 0 , \
. h_stop = 719 , \
. video_v_start = 24 , \
. video_v_stop = 311 , \
2005-06-23 22:04:47 -07:00
. vbi_v_start_0 = 7 , \
. vbi_v_stop_0 = 22 , \
. vbi_v_start_1 = 319 , \
2005-04-16 15:20:36 -07:00
. src_timing = 4
# define NORM_525_60 \
. h_start = 0 , \
2010-02-06 10:58:41 -03:00
. h_stop = 719 , \
2005-06-23 22:04:47 -07:00
. video_v_start = 23 , \
. video_v_stop = 262 , \
. vbi_v_start_0 = 10 , \
. vbi_v_stop_0 = 21 , \
. vbi_v_start_1 = 273 , \
. src_timing = 7
2005-04-16 15:20:36 -07:00
static struct saa7134_tvnorm tvnorms [ ] = {
{
. name = " PAL " , /* autodetect */
. id = V4L2_STD_PAL ,
NORM_625_50 ,
. sync_control = 0x18 ,
. luma_control = 0x40 ,
. chroma_ctrl1 = 0x81 ,
. chroma_gain = 0x2a ,
. chroma_ctrl2 = 0x06 ,
. vgate_misc = 0x1c ,
} , {
. name = " PAL-BG " ,
. id = V4L2_STD_PAL_BG ,
NORM_625_50 ,
. sync_control = 0x18 ,
. luma_control = 0x40 ,
. chroma_ctrl1 = 0x81 ,
. chroma_gain = 0x2a ,
. chroma_ctrl2 = 0x06 ,
. vgate_misc = 0x1c ,
} , {
. name = " PAL-I " ,
. id = V4L2_STD_PAL_I ,
NORM_625_50 ,
. sync_control = 0x18 ,
. luma_control = 0x40 ,
. chroma_ctrl1 = 0x81 ,
. chroma_gain = 0x2a ,
. chroma_ctrl2 = 0x06 ,
. vgate_misc = 0x1c ,
} , {
. name = " PAL-DK " ,
. id = V4L2_STD_PAL_DK ,
NORM_625_50 ,
. sync_control = 0x18 ,
. luma_control = 0x40 ,
. chroma_ctrl1 = 0x81 ,
. chroma_gain = 0x2a ,
. chroma_ctrl2 = 0x06 ,
. vgate_misc = 0x1c ,
} , {
. name = " NTSC " ,
. id = V4L2_STD_NTSC ,
NORM_525_60 ,
. sync_control = 0x59 ,
. luma_control = 0x40 ,
. chroma_ctrl1 = 0x89 ,
. chroma_gain = 0x2a ,
. chroma_ctrl2 = 0x0e ,
. vgate_misc = 0x18 ,
} , {
. name = " SECAM " ,
. id = V4L2_STD_SECAM ,
NORM_625_50 ,
2006-10-02 19:55:07 -03:00
. sync_control = 0x18 ,
. luma_control = 0x1b ,
. chroma_ctrl1 = 0xd1 ,
. chroma_gain = 0x80 ,
. chroma_ctrl2 = 0x00 ,
. vgate_misc = 0x1c ,
} , {
. name = " SECAM-DK " ,
. id = V4L2_STD_SECAM_DK ,
NORM_625_50 ,
. sync_control = 0x18 ,
. luma_control = 0x1b ,
. chroma_ctrl1 = 0xd1 ,
. chroma_gain = 0x80 ,
. chroma_ctrl2 = 0x00 ,
. vgate_misc = 0x1c ,
} , {
. name = " SECAM-L " ,
. id = V4L2_STD_SECAM_L ,
NORM_625_50 ,
. sync_control = 0x18 ,
. luma_control = 0x1b ,
. chroma_ctrl1 = 0xd1 ,
. chroma_gain = 0x80 ,
. chroma_ctrl2 = 0x00 ,
. vgate_misc = 0x1c ,
} , {
. name = " SECAM-Lc " ,
. id = V4L2_STD_SECAM_LC ,
NORM_625_50 ,
. sync_control = 0x18 ,
2005-04-16 15:20:36 -07:00
. luma_control = 0x1b ,
. chroma_ctrl1 = 0xd1 ,
. chroma_gain = 0x80 ,
. chroma_ctrl2 = 0x00 ,
. vgate_misc = 0x1c ,
} , {
. name = " PAL-M " ,
. id = V4L2_STD_PAL_M ,
NORM_525_60 ,
. sync_control = 0x59 ,
. luma_control = 0x40 ,
. chroma_ctrl1 = 0xb9 ,
. chroma_gain = 0x2a ,
. chroma_ctrl2 = 0x0e ,
. vgate_misc = 0x18 ,
} , {
. name = " PAL-Nc " ,
. id = V4L2_STD_PAL_Nc ,
NORM_625_50 ,
. sync_control = 0x18 ,
. luma_control = 0x40 ,
. chroma_ctrl1 = 0xa1 ,
. chroma_gain = 0x2a ,
. chroma_ctrl2 = 0x06 ,
. vgate_misc = 0x1c ,
} , {
. name = " PAL-60 " ,
. id = V4L2_STD_PAL_60 ,
. h_start = 0 ,
. h_stop = 719 ,
2005-11-08 21:37:43 -08:00
. video_v_start = 23 ,
. video_v_stop = 262 ,
. vbi_v_start_0 = 10 ,
. vbi_v_stop_0 = 21 ,
. vbi_v_start_1 = 273 ,
. src_timing = 7 ,
2005-04-16 15:20:36 -07:00
. sync_control = 0x18 ,
. luma_control = 0x40 ,
. chroma_ctrl1 = 0x81 ,
. chroma_gain = 0x2a ,
. chroma_ctrl2 = 0x06 ,
. vgate_misc = 0x1c ,
}
} ;
# define TVNORMS ARRAY_SIZE(tvnorms)
# define V4L2_CID_PRIVATE_INVERT (V4L2_CID_PRIVATE_BASE + 0)
# define V4L2_CID_PRIVATE_Y_ODD (V4L2_CID_PRIVATE_BASE + 1)
# define V4L2_CID_PRIVATE_Y_EVEN (V4L2_CID_PRIVATE_BASE + 2)
# define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_PRIVATE_BASE + 3)
# define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 4)
static const struct v4l2_queryctrl no_ctrl = {
. name = " 42 " ,
. flags = V4L2_CTRL_FLAG_DISABLED ,
} ;
static const struct v4l2_queryctrl video_ctrls [ ] = {
/* --- video --- */
{
. id = V4L2_CID_BRIGHTNESS ,
. name = " Brightness " ,
. minimum = 0 ,
. maximum = 255 ,
. step = 1 ,
. default_value = 128 ,
. type = V4L2_CTRL_TYPE_INTEGER ,
} , {
. id = V4L2_CID_CONTRAST ,
. name = " Contrast " ,
. minimum = 0 ,
. maximum = 127 ,
. step = 1 ,
. default_value = 68 ,
. type = V4L2_CTRL_TYPE_INTEGER ,
} , {
. id = V4L2_CID_SATURATION ,
. name = " Saturation " ,
. minimum = 0 ,
. maximum = 127 ,
. step = 1 ,
. default_value = 64 ,
. type = V4L2_CTRL_TYPE_INTEGER ,
} , {
. id = V4L2_CID_HUE ,
. name = " Hue " ,
. minimum = - 128 ,
. maximum = 127 ,
. step = 1 ,
. default_value = 0 ,
. type = V4L2_CTRL_TYPE_INTEGER ,
} , {
2005-06-23 22:04:47 -07:00
. id = V4L2_CID_HFLIP ,
. name = " Mirror " ,
2005-04-16 15:20:36 -07:00
. minimum = 0 ,
. maximum = 1 ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
} ,
/* --- audio --- */
{
. id = V4L2_CID_AUDIO_MUTE ,
. name = " Mute " ,
. minimum = 0 ,
. maximum = 1 ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
} , {
. id = V4L2_CID_AUDIO_VOLUME ,
. name = " Volume " ,
. minimum = - 15 ,
. maximum = 15 ,
. step = 1 ,
. default_value = 0 ,
. type = V4L2_CTRL_TYPE_INTEGER ,
} ,
/* --- private --- */
{
. id = V4L2_CID_PRIVATE_INVERT ,
. name = " Invert " ,
. minimum = 0 ,
. maximum = 1 ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
} , {
. id = V4L2_CID_PRIVATE_Y_ODD ,
. name = " y offset odd field " ,
. minimum = 0 ,
. maximum = 128 ,
2009-02-09 05:33:54 -03:00
. step = 1 ,
2005-04-16 15:20:36 -07:00
. default_value = 0 ,
. type = V4L2_CTRL_TYPE_INTEGER ,
} , {
. id = V4L2_CID_PRIVATE_Y_EVEN ,
. name = " y offset even field " ,
. minimum = 0 ,
. maximum = 128 ,
2009-02-09 05:33:54 -03:00
. step = 1 ,
2005-04-16 15:20:36 -07:00
. default_value = 0 ,
. type = V4L2_CTRL_TYPE_INTEGER ,
} , {
. id = V4L2_CID_PRIVATE_AUTOMUTE ,
. name = " automute " ,
. minimum = 0 ,
. maximum = 1 ,
. default_value = 1 ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
}
} ;
static const unsigned int CTRLS = ARRAY_SIZE ( video_ctrls ) ;
static const struct v4l2_queryctrl * ctrl_by_id ( unsigned int id )
{
unsigned int i ;
for ( i = 0 ; i < CTRLS ; i + + )
if ( video_ctrls [ i ] . id = = id )
return video_ctrls + i ;
return NULL ;
}
static struct saa7134_format * format_by_fourcc ( unsigned int fourcc )
{
unsigned int i ;
for ( i = 0 ; i < FORMATS ; i + + )
if ( formats [ i ] . fourcc = = fourcc )
return formats + i ;
return NULL ;
}
/* ----------------------------------------------------------------------- */
/* resource management */
static int res_get ( struct saa7134_dev * dev , struct saa7134_fh * fh , unsigned int bit )
{
if ( fh - > resources & bit )
/* have it already allocated */
return 1 ;
/* is it free? */
2006-02-07 06:49:14 -02:00
mutex_lock ( & dev - > lock ) ;
2005-04-16 15:20:36 -07:00
if ( dev - > resources & bit ) {
/* no, someone else uses it */
2006-02-07 06:49:14 -02:00
mutex_unlock ( & dev - > lock ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
/* it's free, grab it */
fh - > resources | = bit ;
dev - > resources | = bit ;
dprintk ( " res: get %d \n " , bit ) ;
2006-02-07 06:49:14 -02:00
mutex_unlock ( & dev - > lock ) ;
2005-04-16 15:20:36 -07:00
return 1 ;
}
2007-04-27 12:31:18 -03:00
static int res_check ( struct saa7134_fh * fh , unsigned int bit )
2005-04-16 15:20:36 -07:00
{
return ( fh - > resources & bit ) ;
}
2007-04-27 12:31:18 -03:00
static int res_locked ( struct saa7134_dev * dev , unsigned int bit )
2005-04-16 15:20:36 -07:00
{
return ( dev - > resources & bit ) ;
}
static
void res_free ( struct saa7134_dev * dev , struct saa7134_fh * fh , unsigned int bits )
{
2006-03-13 13:17:11 -03:00
BUG_ON ( ( fh - > resources & bits ) ! = bits ) ;
2005-04-16 15:20:36 -07:00
2006-02-07 06:49:14 -02:00
mutex_lock ( & dev - > lock ) ;
2005-04-16 15:20:36 -07:00
fh - > resources & = ~ bits ;
dev - > resources & = ~ bits ;
dprintk ( " res: put %d \n " , bits ) ;
2006-02-07 06:49:14 -02:00
mutex_unlock ( & dev - > lock ) ;
2005-04-16 15:20:36 -07:00
}
/* ------------------------------------------------------------------ */
2007-10-24 13:23:14 -03:00
static void set_tvnorm ( struct saa7134_dev * dev , struct saa7134_tvnorm * norm )
2005-04-16 15:20:36 -07:00
{
dprintk ( " set tv norm = %s \n " , norm - > name ) ;
dev - > tvnorm = norm ;
/* setup cropping */
dev - > crop_bounds . left = norm - > h_start ;
dev - > crop_defrect . left = norm - > h_start ;
dev - > crop_bounds . width = norm - > h_stop - norm - > h_start + 1 ;
dev - > crop_defrect . width = norm - > h_stop - norm - > h_start + 1 ;
2005-06-23 22:04:47 -07:00
dev - > crop_bounds . top = ( norm - > vbi_v_stop_0 + 1 ) * 2 ;
2005-04-16 15:20:36 -07:00
dev - > crop_defrect . top = norm - > video_v_start * 2 ;
dev - > crop_bounds . height = ( ( norm - > id & V4L2_STD_525_60 ) ? 524 : 624 )
- dev - > crop_bounds . top ;
dev - > crop_defrect . height = ( norm - > video_v_stop - norm - > video_v_start + 1 ) * 2 ;
dev - > crop_current = dev - > crop_defrect ;
2007-10-12 00:57:15 -03:00
saa7134_set_tvnorm_hw ( dev ) ;
2007-09-27 20:34:25 -03:00
}
static void video_mux ( struct saa7134_dev * dev , int input )
{
dprintk ( " video input = %d [%s] \n " , input , card_in ( dev , input ) . name ) ;
dev - > ctl_input = input ;
set_tvnorm ( dev , dev - > tvnorm ) ;
saa7134_tvaudio_setinput ( dev , & card_in ( dev , input ) ) ;
}
2007-10-12 00:57:15 -03:00
static void saa7134_set_decoder ( struct saa7134_dev * dev )
2007-09-27 20:34:25 -03:00
{
int luma_control , sync_control , mux ;
struct saa7134_tvnorm * norm = dev - > tvnorm ;
mux = card_in ( dev , dev - > ctl_input ) . vmux ;
luma_control = norm - > luma_control ;
sync_control = norm - > sync_control ;
if ( mux > 5 )
luma_control | = 0x80 ; /* svideo */
if ( noninterlaced | | dev - > nosignal )
sync_control | = 0x20 ;
2005-04-16 15:20:36 -07:00
/* setup video decoder */
saa_writeb ( SAA7134_INCR_DELAY , 0x08 ) ;
saa_writeb ( SAA7134_ANALOG_IN_CTRL1 , 0xc0 | mux ) ;
saa_writeb ( SAA7134_ANALOG_IN_CTRL2 , 0x00 ) ;
saa_writeb ( SAA7134_ANALOG_IN_CTRL3 , 0x90 ) ;
saa_writeb ( SAA7134_ANALOG_IN_CTRL4 , 0x90 ) ;
saa_writeb ( SAA7134_HSYNC_START , 0xeb ) ;
saa_writeb ( SAA7134_HSYNC_STOP , 0xe0 ) ;
saa_writeb ( SAA7134_SOURCE_TIMING1 , norm - > src_timing ) ;
saa_writeb ( SAA7134_SYNC_CTRL , sync_control ) ;
saa_writeb ( SAA7134_LUMA_CTRL , luma_control ) ;
saa_writeb ( SAA7134_DEC_LUMA_BRIGHT , dev - > ctl_bright ) ;
2007-09-27 20:34:20 -03:00
saa_writeb ( SAA7134_DEC_LUMA_CONTRAST ,
dev - > ctl_invert ? - dev - > ctl_contrast : dev - > ctl_contrast ) ;
saa_writeb ( SAA7134_DEC_CHROMA_SATURATION ,
dev - > ctl_invert ? - dev - > ctl_saturation : dev - > ctl_saturation ) ;
2005-04-16 15:20:36 -07:00
saa_writeb ( SAA7134_DEC_CHROMA_HUE , dev - > ctl_hue ) ;
saa_writeb ( SAA7134_CHROMA_CTRL1 , norm - > chroma_ctrl1 ) ;
saa_writeb ( SAA7134_CHROMA_GAIN , norm - > chroma_gain ) ;
saa_writeb ( SAA7134_CHROMA_CTRL2 , norm - > chroma_ctrl2 ) ;
saa_writeb ( SAA7134_MODE_DELAY_CTRL , 0x00 ) ;
saa_writeb ( SAA7134_ANALOG_ADC , 0x01 ) ;
saa_writeb ( SAA7134_VGATE_START , 0x11 ) ;
saa_writeb ( SAA7134_VGATE_STOP , 0xfe ) ;
saa_writeb ( SAA7134_MISC_VGATE_MSB , norm - > vgate_misc ) ;
saa_writeb ( SAA7134_RAW_DATA_GAIN , 0x40 ) ;
saa_writeb ( SAA7134_RAW_DATA_OFFSET , 0x80 ) ;
}
2007-10-12 00:57:15 -03:00
void saa7134_set_tvnorm_hw ( struct saa7134_dev * dev )
{
saa7134_set_decoder ( dev ) ;
2008-04-22 14:46:08 -03:00
if ( card_in ( dev , dev - > ctl_input ) . tv )
2009-04-01 03:52:39 -03:00
saa_call_all ( dev , core , s_std , dev - > tvnorm - > id ) ;
2008-09-06 06:34:44 -03:00
/* Set the correct norm for the saa6752hs. This function
does nothing if there is no saa6752hs . */
2009-04-01 03:52:39 -03:00
saa_call_empress ( dev , core , s_std , dev - > tvnorm - > id ) ;
2007-10-12 00:57:15 -03:00
}
2005-04-16 15:20:36 -07:00
static void set_h_prescale ( struct saa7134_dev * dev , int task , int prescale )
{
static const struct {
int xpsc ;
int xacl ;
int xc2_1 ;
int xdcg ;
int vpfy ;
} vals [ ] = {
/* XPSC XACL XC2_1 XDCG VPFY */
{ 1 , 0 , 0 , 0 , 0 } ,
{ 2 , 2 , 1 , 2 , 2 } ,
{ 3 , 4 , 1 , 3 , 2 } ,
{ 4 , 8 , 1 , 4 , 2 } ,
{ 5 , 8 , 1 , 4 , 2 } ,
{ 6 , 8 , 1 , 4 , 3 } ,
{ 7 , 8 , 1 , 4 , 3 } ,
{ 8 , 15 , 0 , 4 , 3 } ,
{ 9 , 15 , 0 , 4 , 3 } ,
{ 10 , 16 , 1 , 5 , 3 } ,
} ;
static const int count = ARRAY_SIZE ( vals ) ;
int i ;
for ( i = 0 ; i < count ; i + + )
if ( vals [ i ] . xpsc = = prescale )
break ;
if ( i = = count )
return ;
saa_writeb ( SAA7134_H_PRESCALE ( task ) , vals [ i ] . xpsc ) ;
saa_writeb ( SAA7134_ACC_LENGTH ( task ) , vals [ i ] . xacl ) ;
saa_writeb ( SAA7134_LEVEL_CTRL ( task ) ,
( vals [ i ] . xc2_1 < < 3 ) | ( vals [ i ] . xdcg ) ) ;
saa_andorb ( SAA7134_FIR_PREFILTER_CTRL ( task ) , 0x0f ,
( vals [ i ] . vpfy < < 2 ) | vals [ i ] . vpfy ) ;
}
static void set_v_scale ( struct saa7134_dev * dev , int task , int yscale )
{
int val , mirror ;
saa_writeb ( SAA7134_V_SCALE_RATIO1 ( task ) , yscale & 0xff ) ;
saa_writeb ( SAA7134_V_SCALE_RATIO2 ( task ) , yscale > > 8 ) ;
mirror = ( dev - > ctl_mirror ) ? 0x02 : 0x00 ;
if ( yscale < 2048 ) {
/* LPI */
dprintk ( " yscale LPI yscale=%d \n " , yscale ) ;
saa_writeb ( SAA7134_V_FILTER ( task ) , 0x00 | mirror ) ;
saa_writeb ( SAA7134_LUMA_CONTRAST ( task ) , 0x40 ) ;
saa_writeb ( SAA7134_CHROMA_SATURATION ( task ) , 0x40 ) ;
} else {
/* ACM */
val = 0x40 * 1024 / yscale ;
dprintk ( " yscale ACM yscale=%d val=0x%x \n " , yscale , val ) ;
saa_writeb ( SAA7134_V_FILTER ( task ) , 0x01 | mirror ) ;
saa_writeb ( SAA7134_LUMA_CONTRAST ( task ) , val ) ;
saa_writeb ( SAA7134_CHROMA_SATURATION ( task ) , val ) ;
}
saa_writeb ( SAA7134_LUMA_BRIGHT ( task ) , 0x80 ) ;
}
static void set_size ( struct saa7134_dev * dev , int task ,
int width , int height , int interlace )
{
int prescale , xscale , yscale , y_even , y_odd ;
int h_start , h_stop , v_start , v_stop ;
int div = interlace ? 2 : 1 ;
/* setup video scaler */
h_start = dev - > crop_current . left ;
v_start = dev - > crop_current . top / 2 ;
h_stop = ( dev - > crop_current . left + dev - > crop_current . width - 1 ) ;
v_stop = ( dev - > crop_current . top + dev - > crop_current . height - 1 ) / 2 ;
saa_writeb ( SAA7134_VIDEO_H_START1 ( task ) , h_start & 0xff ) ;
saa_writeb ( SAA7134_VIDEO_H_START2 ( task ) , h_start > > 8 ) ;
saa_writeb ( SAA7134_VIDEO_H_STOP1 ( task ) , h_stop & 0xff ) ;
saa_writeb ( SAA7134_VIDEO_H_STOP2 ( task ) , h_stop > > 8 ) ;
saa_writeb ( SAA7134_VIDEO_V_START1 ( task ) , v_start & 0xff ) ;
saa_writeb ( SAA7134_VIDEO_V_START2 ( task ) , v_start > > 8 ) ;
saa_writeb ( SAA7134_VIDEO_V_STOP1 ( task ) , v_stop & 0xff ) ;
saa_writeb ( SAA7134_VIDEO_V_STOP2 ( task ) , v_stop > > 8 ) ;
prescale = dev - > crop_current . width / width ;
if ( 0 = = prescale )
prescale = 1 ;
xscale = 1024 * dev - > crop_current . width / prescale / width ;
yscale = 512 * div * dev - > crop_current . height / height ;
2005-11-08 21:37:43 -08:00
dprintk ( " prescale=%d xscale=%d yscale=%d \n " , prescale , xscale , yscale ) ;
2005-04-16 15:20:36 -07:00
set_h_prescale ( dev , task , prescale ) ;
saa_writeb ( SAA7134_H_SCALE_INC1 ( task ) , xscale & 0xff ) ;
saa_writeb ( SAA7134_H_SCALE_INC2 ( task ) , xscale > > 8 ) ;
set_v_scale ( dev , task , yscale ) ;
saa_writeb ( SAA7134_VIDEO_PIXELS1 ( task ) , width & 0xff ) ;
saa_writeb ( SAA7134_VIDEO_PIXELS2 ( task ) , width > > 8 ) ;
saa_writeb ( SAA7134_VIDEO_LINES1 ( task ) , height / div & 0xff ) ;
saa_writeb ( SAA7134_VIDEO_LINES2 ( task ) , height / div > > 8 ) ;
/* deinterlace y offsets */
y_odd = dev - > ctl_y_odd ;
y_even = dev - > ctl_y_even ;
saa_writeb ( SAA7134_V_PHASE_OFFSET0 ( task ) , y_odd ) ;
saa_writeb ( SAA7134_V_PHASE_OFFSET1 ( task ) , y_even ) ;
saa_writeb ( SAA7134_V_PHASE_OFFSET2 ( task ) , y_odd ) ;
saa_writeb ( SAA7134_V_PHASE_OFFSET3 ( task ) , y_even ) ;
}
/* ------------------------------------------------------------------ */
struct cliplist {
__u16 position ;
__u8 enable ;
__u8 disable ;
} ;
static void set_cliplist ( struct saa7134_dev * dev , int reg ,
struct cliplist * cl , int entries , char * name )
{
__u8 winbits = 0 ;
int i ;
for ( i = 0 ; i < entries ; i + + ) {
winbits | = cl [ i ] . enable ;
winbits & = ~ cl [ i ] . disable ;
if ( i < 15 & & cl [ i ] . position = = cl [ i + 1 ] . position )
continue ;
saa_writeb ( reg + 0 , winbits ) ;
saa_writeb ( reg + 2 , cl [ i ] . position & 0xff ) ;
saa_writeb ( reg + 3 , cl [ i ] . position > > 8 ) ;
dprintk ( " clip: %s winbits=%02x pos=%d \n " ,
name , winbits , cl [ i ] . position ) ;
reg + = 8 ;
}
for ( ; reg < 0x400 ; reg + = 8 ) {
saa_writeb ( reg + 0 , 0 ) ;
saa_writeb ( reg + 1 , 0 ) ;
saa_writeb ( reg + 2 , 0 ) ;
saa_writeb ( reg + 3 , 0 ) ;
}
}
static int clip_range ( int val )
{
if ( val < 0 )
val = 0 ;
return val ;
}
2007-04-27 12:31:18 -03:00
/* Sort into smallest position first order */
static int cliplist_cmp ( const void * a , const void * b )
{
const struct cliplist * cla = a ;
const struct cliplist * clb = b ;
if ( cla - > position < clb - > position )
return - 1 ;
if ( cla - > position > clb - > position )
return 1 ;
return 0 ;
}
2005-04-16 15:20:36 -07:00
static int setup_clipping ( struct saa7134_dev * dev , struct v4l2_clip * clips ,
int nclips , int interlace )
{
struct cliplist col [ 16 ] , row [ 16 ] ;
2007-04-27 12:31:18 -03:00
int cols = 0 , rows = 0 , i ;
2005-04-16 15:20:36 -07:00
int div = interlace ? 2 : 1 ;
2007-04-27 12:31:18 -03:00
memset ( col , 0 , sizeof ( col ) ) ;
memset ( row , 0 , sizeof ( row ) ) ;
2005-04-16 15:20:36 -07:00
for ( i = 0 ; i < nclips & & i < 8 ; i + + ) {
col [ cols ] . position = clip_range ( clips [ i ] . c . left ) ;
col [ cols ] . enable = ( 1 < < i ) ;
cols + + ;
col [ cols ] . position = clip_range ( clips [ i ] . c . left + clips [ i ] . c . width ) ;
col [ cols ] . disable = ( 1 < < i ) ;
cols + + ;
row [ rows ] . position = clip_range ( clips [ i ] . c . top / div ) ;
row [ rows ] . enable = ( 1 < < i ) ;
rows + + ;
row [ rows ] . position = clip_range ( ( clips [ i ] . c . top + clips [ i ] . c . height )
/ div ) ;
row [ rows ] . disable = ( 1 < < i ) ;
rows + + ;
}
2007-04-27 12:31:18 -03:00
sort ( col , cols , sizeof col [ 0 ] , cliplist_cmp , NULL ) ;
sort ( row , rows , sizeof row [ 0 ] , cliplist_cmp , NULL ) ;
2005-04-16 15:20:36 -07:00
set_cliplist ( dev , 0x380 , col , cols , " cols " ) ;
set_cliplist ( dev , 0x384 , row , rows , " rows " ) ;
return 0 ;
}
static int verify_preview ( struct saa7134_dev * dev , struct v4l2_window * win )
{
enum v4l2_field field ;
int maxw , maxh ;
if ( NULL = = dev - > ovbuf . base )
return - EINVAL ;
if ( NULL = = dev - > ovfmt )
return - EINVAL ;
if ( win - > w . width < 48 | | win - > w . height < 32 )
return - EINVAL ;
if ( win - > clipcount > 2048 )
return - EINVAL ;
field = win - > field ;
maxw = dev - > crop_current . width ;
maxh = dev - > crop_current . height ;
if ( V4L2_FIELD_ANY = = field ) {
2005-11-08 21:37:43 -08:00
field = ( win - > w . height > maxh / 2 )
? V4L2_FIELD_INTERLACED
: V4L2_FIELD_TOP ;
}
switch ( field ) {
case V4L2_FIELD_TOP :
case V4L2_FIELD_BOTTOM :
maxh = maxh / 2 ;
break ;
case V4L2_FIELD_INTERLACED :
break ;
default :
return - EINVAL ;
}
2005-04-16 15:20:36 -07:00
win - > field = field ;
if ( win - > w . width > maxw )
win - > w . width = maxw ;
if ( win - > w . height > maxh )
win - > w . height = maxh ;
return 0 ;
}
static int start_preview ( struct saa7134_dev * dev , struct saa7134_fh * fh )
{
unsigned long base , control , bpl ;
int err ;
err = verify_preview ( dev , & fh - > win ) ;
if ( 0 ! = err )
return err ;
dev - > ovfield = fh - > win . field ;
dprintk ( " start_preview %dx%d+%d+%d %s field=%s \n " ,
fh - > win . w . width , fh - > win . w . height ,
fh - > win . w . left , fh - > win . w . top ,
dev - > ovfmt - > name , v4l2_field_names [ dev - > ovfield ] ) ;
/* setup window + clipping */
set_size ( dev , TASK_B , fh - > win . w . width , fh - > win . w . height ,
V4L2_FIELD_HAS_BOTH ( dev - > ovfield ) ) ;
setup_clipping ( dev , fh - > clips , fh - > nclips ,
V4L2_FIELD_HAS_BOTH ( dev - > ovfield ) ) ;
if ( dev - > ovfmt - > yuv )
saa_andorb ( SAA7134_DATA_PATH ( TASK_B ) , 0x3f , 0x03 ) ;
else
saa_andorb ( SAA7134_DATA_PATH ( TASK_B ) , 0x3f , 0x01 ) ;
saa_writeb ( SAA7134_OFMT_VIDEO_B , dev - > ovfmt - > pm | 0x20 ) ;
/* dma: setup channel 1 (= Video Task B) */
base = ( unsigned long ) dev - > ovbuf . base ;
base + = dev - > ovbuf . fmt . bytesperline * fh - > win . w . top ;
base + = dev - > ovfmt - > depth / 8 * fh - > win . w . left ;
bpl = dev - > ovbuf . fmt . bytesperline ;
control = SAA7134_RS_CONTROL_BURST_16 ;
if ( dev - > ovfmt - > bswap )
control | = SAA7134_RS_CONTROL_BSWAP ;
if ( dev - > ovfmt - > wswap )
control | = SAA7134_RS_CONTROL_WSWAP ;
if ( V4L2_FIELD_HAS_BOTH ( dev - > ovfield ) ) {
saa_writel ( SAA7134_RS_BA1 ( 1 ) , base ) ;
saa_writel ( SAA7134_RS_BA2 ( 1 ) , base + bpl ) ;
saa_writel ( SAA7134_RS_PITCH ( 1 ) , bpl * 2 ) ;
saa_writel ( SAA7134_RS_CONTROL ( 1 ) , control ) ;
} else {
saa_writel ( SAA7134_RS_BA1 ( 1 ) , base ) ;
saa_writel ( SAA7134_RS_BA2 ( 1 ) , base ) ;
saa_writel ( SAA7134_RS_PITCH ( 1 ) , bpl ) ;
saa_writel ( SAA7134_RS_CONTROL ( 1 ) , control ) ;
}
/* start dma */
dev - > ovenable = 1 ;
saa7134_set_dmabits ( dev ) ;
return 0 ;
}
static int stop_preview ( struct saa7134_dev * dev , struct saa7134_fh * fh )
{
dev - > ovenable = 0 ;
saa7134_set_dmabits ( dev ) ;
return 0 ;
}
/* ------------------------------------------------------------------ */
static int buffer_activate ( struct saa7134_dev * dev ,
struct saa7134_buf * buf ,
struct saa7134_buf * next )
{
unsigned long base , control , bpl ;
unsigned long bpl_uv , lines_uv , base2 , base3 , tmp ; /* planar */
dprintk ( " buffer_activate buf=%p \n " , buf ) ;
2007-11-06 20:02:36 -03:00
buf - > vb . state = VIDEOBUF_ACTIVE ;
2005-04-16 15:20:36 -07:00
buf - > top_seen = 0 ;
set_size ( dev , TASK_A , buf - > vb . width , buf - > vb . height ,
V4L2_FIELD_HAS_BOTH ( buf - > vb . field ) ) ;
if ( buf - > fmt - > yuv )
saa_andorb ( SAA7134_DATA_PATH ( TASK_A ) , 0x3f , 0x03 ) ;
else
saa_andorb ( SAA7134_DATA_PATH ( TASK_A ) , 0x3f , 0x01 ) ;
saa_writeb ( SAA7134_OFMT_VIDEO_A , buf - > fmt - > pm ) ;
/* DMA: setup channel 0 (= Video Task A0) */
base = saa7134_buffer_base ( buf ) ;
if ( buf - > fmt - > planar )
bpl = buf - > vb . width ;
else
bpl = ( buf - > vb . width * buf - > fmt - > depth ) / 8 ;
control = SAA7134_RS_CONTROL_BURST_16 |
SAA7134_RS_CONTROL_ME |
( buf - > pt - > dma > > 12 ) ;
if ( buf - > fmt - > bswap )
control | = SAA7134_RS_CONTROL_BSWAP ;
if ( buf - > fmt - > wswap )
control | = SAA7134_RS_CONTROL_WSWAP ;
if ( V4L2_FIELD_HAS_BOTH ( buf - > vb . field ) ) {
/* interlaced */
saa_writel ( SAA7134_RS_BA1 ( 0 ) , base ) ;
saa_writel ( SAA7134_RS_BA2 ( 0 ) , base + bpl ) ;
saa_writel ( SAA7134_RS_PITCH ( 0 ) , bpl * 2 ) ;
} else {
/* non-interlaced */
saa_writel ( SAA7134_RS_BA1 ( 0 ) , base ) ;
saa_writel ( SAA7134_RS_BA2 ( 0 ) , base ) ;
saa_writel ( SAA7134_RS_PITCH ( 0 ) , bpl ) ;
}
saa_writel ( SAA7134_RS_CONTROL ( 0 ) , control ) ;
if ( buf - > fmt - > planar ) {
/* DMA: setup channel 4+5 (= planar task A) */
bpl_uv = bpl > > buf - > fmt - > hshift ;
lines_uv = buf - > vb . height > > buf - > fmt - > vshift ;
base2 = base + bpl * buf - > vb . height ;
base3 = base2 + bpl_uv * lines_uv ;
if ( buf - > fmt - > uvswap )
tmp = base2 , base2 = base3 , base3 = tmp ;
dprintk ( " uv: bpl=%ld lines=%ld base2/3=%ld/%ld \n " ,
bpl_uv , lines_uv , base2 , base3 ) ;
if ( V4L2_FIELD_HAS_BOTH ( buf - > vb . field ) ) {
/* interlaced */
saa_writel ( SAA7134_RS_BA1 ( 4 ) , base2 ) ;
saa_writel ( SAA7134_RS_BA2 ( 4 ) , base2 + bpl_uv ) ;
saa_writel ( SAA7134_RS_PITCH ( 4 ) , bpl_uv * 2 ) ;
saa_writel ( SAA7134_RS_BA1 ( 5 ) , base3 ) ;
saa_writel ( SAA7134_RS_BA2 ( 5 ) , base3 + bpl_uv ) ;
saa_writel ( SAA7134_RS_PITCH ( 5 ) , bpl_uv * 2 ) ;
} else {
/* non-interlaced */
saa_writel ( SAA7134_RS_BA1 ( 4 ) , base2 ) ;
saa_writel ( SAA7134_RS_BA2 ( 4 ) , base2 ) ;
saa_writel ( SAA7134_RS_PITCH ( 4 ) , bpl_uv ) ;
saa_writel ( SAA7134_RS_BA1 ( 5 ) , base3 ) ;
saa_writel ( SAA7134_RS_BA2 ( 5 ) , base3 ) ;
saa_writel ( SAA7134_RS_PITCH ( 5 ) , bpl_uv ) ;
}
saa_writel ( SAA7134_RS_CONTROL ( 4 ) , control ) ;
saa_writel ( SAA7134_RS_CONTROL ( 5 ) , control ) ;
}
/* start DMA */
saa7134_set_dmabits ( dev ) ;
mod_timer ( & dev - > video_q . timeout , jiffies + BUFFER_TIMEOUT ) ;
return 0 ;
}
static int buffer_prepare ( struct videobuf_queue * q ,
struct videobuf_buffer * vb ,
enum v4l2_field field )
{
struct saa7134_fh * fh = q - > priv_data ;
struct saa7134_dev * dev = fh - > dev ;
struct saa7134_buf * buf = container_of ( vb , struct saa7134_buf , vb ) ;
unsigned int size ;
int err ;
/* sanity checks */
if ( NULL = = fh - > fmt )
return - EINVAL ;
if ( fh - > width < 48 | |
fh - > height < 32 | |
fh - > width / 4 > dev - > crop_current . width | |
fh - > height / 4 > dev - > crop_current . height | |
fh - > width > dev - > crop_bounds . width | |
fh - > height > dev - > crop_bounds . height )
return - EINVAL ;
size = ( fh - > width * fh - > height * fh - > fmt - > depth ) > > 3 ;
if ( 0 ! = buf - > vb . baddr & & buf - > vb . bsize < size )
return - EINVAL ;
dprintk ( " buffer_prepare [%d,size=%dx%d,bytes=%d,fields=%s,%s] \n " ,
vb - > i , fh - > width , fh - > height , size , v4l2_field_names [ field ] ,
fh - > fmt - > name ) ;
if ( buf - > vb . width ! = fh - > width | |
buf - > vb . height ! = fh - > height | |
buf - > vb . size ! = size | |
buf - > vb . field ! = field | |
buf - > fmt ! = fh - > fmt ) {
2006-03-10 12:29:15 -03:00
saa7134_dma_free ( q , buf ) ;
2005-04-16 15:20:36 -07:00
}
2007-11-06 20:02:36 -03:00
if ( VIDEOBUF_NEEDS_INIT = = buf - > vb . state ) {
2007-08-23 16:37:49 -03:00
struct videobuf_dmabuf * dma = videobuf_to_dma ( & buf - > vb ) ;
2005-04-16 15:20:36 -07:00
buf - > vb . width = fh - > width ;
buf - > vb . height = fh - > height ;
buf - > vb . size = size ;
buf - > vb . field = field ;
buf - > fmt = fh - > fmt ;
buf - > pt = & fh - > pt_cap ;
2009-05-07 23:31:02 -03:00
dev - > video_q . curr = NULL ;
2005-04-16 15:20:36 -07:00
2006-03-10 12:29:15 -03:00
err = videobuf_iolock ( q , & buf - > vb , & dev - > ovbuf ) ;
2005-04-16 15:20:36 -07:00
if ( err )
goto oops ;
err = saa7134_pgtable_build ( dev - > pci , buf - > pt ,
2007-08-23 16:37:49 -03:00
dma - > sglist ,
dma - > sglen ,
2005-04-16 15:20:36 -07:00
saa7134_buffer_startpage ( buf ) ) ;
if ( err )
goto oops ;
}
2007-11-06 20:02:36 -03:00
buf - > vb . state = VIDEOBUF_PREPARED ;
2005-04-16 15:20:36 -07:00
buf - > activate = buffer_activate ;
return 0 ;
oops :
2006-03-10 12:29:15 -03:00
saa7134_dma_free ( q , buf ) ;
2005-04-16 15:20:36 -07:00
return err ;
}
static int
buffer_setup ( struct videobuf_queue * q , unsigned int * count , unsigned int * size )
{
struct saa7134_fh * fh = q - > priv_data ;
* size = fh - > fmt - > depth * fh - > width * fh - > height > > 3 ;
if ( 0 = = * count )
* count = gbuffers ;
* count = saa7134_buffer_count ( * size , * count ) ;
return 0 ;
}
static void buffer_queue ( struct videobuf_queue * q , struct videobuf_buffer * vb )
{
struct saa7134_fh * fh = q - > priv_data ;
struct saa7134_buf * buf = container_of ( vb , struct saa7134_buf , vb ) ;
saa7134_buffer_queue ( fh - > dev , & fh - > dev - > video_q , buf ) ;
}
static void buffer_release ( struct videobuf_queue * q , struct videobuf_buffer * vb )
{
struct saa7134_buf * buf = container_of ( vb , struct saa7134_buf , vb ) ;
2006-03-10 12:29:15 -03:00
saa7134_dma_free ( q , buf ) ;
2005-04-16 15:20:36 -07:00
}
static struct videobuf_queue_ops video_qops = {
. buf_setup = buffer_setup ,
. buf_prepare = buffer_prepare ,
. buf_queue = buffer_queue ,
. buf_release = buffer_release ,
} ;
/* ------------------------------------------------------------------ */
2008-07-26 09:04:06 -03:00
int saa7134_g_ctrl_internal ( struct saa7134_dev * dev , struct saa7134_fh * fh , struct v4l2_control * c )
2005-04-16 15:20:36 -07:00
{
const struct v4l2_queryctrl * ctrl ;
ctrl = ctrl_by_id ( c - > id ) ;
if ( NULL = = ctrl )
return - EINVAL ;
switch ( c - > id ) {
case V4L2_CID_BRIGHTNESS :
c - > value = dev - > ctl_bright ;
break ;
case V4L2_CID_HUE :
c - > value = dev - > ctl_hue ;
break ;
case V4L2_CID_CONTRAST :
c - > value = dev - > ctl_contrast ;
break ;
case V4L2_CID_SATURATION :
c - > value = dev - > ctl_saturation ;
break ;
case V4L2_CID_AUDIO_MUTE :
c - > value = dev - > ctl_mute ;
break ;
case V4L2_CID_AUDIO_VOLUME :
c - > value = dev - > ctl_volume ;
break ;
case V4L2_CID_PRIVATE_INVERT :
c - > value = dev - > ctl_invert ;
break ;
2005-06-23 22:04:47 -07:00
case V4L2_CID_HFLIP :
2005-04-16 15:20:36 -07:00
c - > value = dev - > ctl_mirror ;
break ;
case V4L2_CID_PRIVATE_Y_EVEN :
c - > value = dev - > ctl_y_even ;
break ;
case V4L2_CID_PRIVATE_Y_ODD :
c - > value = dev - > ctl_y_odd ;
break ;
case V4L2_CID_PRIVATE_AUTOMUTE :
c - > value = dev - > ctl_automute ;
break ;
default :
return - EINVAL ;
}
return 0 ;
}
2008-07-26 09:04:06 -03:00
EXPORT_SYMBOL_GPL ( saa7134_g_ctrl_internal ) ;
2005-04-16 15:20:36 -07:00
2008-07-26 09:04:06 -03:00
static int saa7134_g_ctrl ( struct file * file , void * priv , struct v4l2_control * c )
{
struct saa7134_fh * fh = priv ;
return saa7134_g_ctrl_internal ( fh - > dev , fh , c ) ;
}
int saa7134_s_ctrl_internal ( struct saa7134_dev * dev , struct saa7134_fh * fh , struct v4l2_control * c )
2005-04-16 15:20:36 -07:00
{
const struct v4l2_queryctrl * ctrl ;
unsigned long flags ;
int restart_overlay = 0 ;
2008-07-26 09:04:06 -03:00
int err ;
2007-12-07 17:34:48 -03:00
2008-07-26 09:04:06 -03:00
/* When called from the empress code fh == NULL.
That needs to be fixed somehow , but for now this is
good enough . */
if ( fh ) {
2010-05-01 08:03:24 -03:00
err = v4l2_prio_check ( & dev - > prio , fh - > prio ) ;
2008-07-26 09:04:06 -03:00
if ( 0 ! = err )
return err ;
}
err = - EINVAL ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
mutex_lock ( & dev - > lock ) ;
2007-12-07 17:34:48 -03:00
2005-04-16 15:20:36 -07:00
ctrl = ctrl_by_id ( c - > id ) ;
if ( NULL = = ctrl )
2007-12-07 17:34:48 -03:00
goto error ;
2005-04-16 15:20:36 -07:00
dprintk ( " set_control name=%s val=%d \n " , ctrl - > name , c - > value ) ;
switch ( ctrl - > type ) {
case V4L2_CTRL_TYPE_BOOLEAN :
case V4L2_CTRL_TYPE_MENU :
case V4L2_CTRL_TYPE_INTEGER :
if ( c - > value < ctrl - > minimum )
c - > value = ctrl - > minimum ;
if ( c - > value > ctrl - > maximum )
c - > value = ctrl - > maximum ;
break ;
default :
/* nothing */ ;
} ;
switch ( c - > id ) {
case V4L2_CID_BRIGHTNESS :
dev - > ctl_bright = c - > value ;
saa_writeb ( SAA7134_DEC_LUMA_BRIGHT , dev - > ctl_bright ) ;
break ;
case V4L2_CID_HUE :
dev - > ctl_hue = c - > value ;
saa_writeb ( SAA7134_DEC_CHROMA_HUE , dev - > ctl_hue ) ;
break ;
case V4L2_CID_CONTRAST :
dev - > ctl_contrast = c - > value ;
saa_writeb ( SAA7134_DEC_LUMA_CONTRAST ,
dev - > ctl_invert ? - dev - > ctl_contrast : dev - > ctl_contrast ) ;
break ;
case V4L2_CID_SATURATION :
dev - > ctl_saturation = c - > value ;
saa_writeb ( SAA7134_DEC_CHROMA_SATURATION ,
dev - > ctl_invert ? - dev - > ctl_saturation : dev - > ctl_saturation ) ;
break ;
case V4L2_CID_AUDIO_MUTE :
dev - > ctl_mute = c - > value ;
saa7134_tvaudio_setmute ( dev ) ;
break ;
case V4L2_CID_AUDIO_VOLUME :
dev - > ctl_volume = c - > value ;
saa7134_tvaudio_setvolume ( dev , dev - > ctl_volume ) ;
break ;
case V4L2_CID_PRIVATE_INVERT :
dev - > ctl_invert = c - > value ;
saa_writeb ( SAA7134_DEC_LUMA_CONTRAST ,
dev - > ctl_invert ? - dev - > ctl_contrast : dev - > ctl_contrast ) ;
saa_writeb ( SAA7134_DEC_CHROMA_SATURATION ,
dev - > ctl_invert ? - dev - > ctl_saturation : dev - > ctl_saturation ) ;
break ;
2005-06-23 22:04:47 -07:00
case V4L2_CID_HFLIP :
2005-04-16 15:20:36 -07:00
dev - > ctl_mirror = c - > value ;
restart_overlay = 1 ;
break ;
case V4L2_CID_PRIVATE_Y_EVEN :
dev - > ctl_y_even = c - > value ;
restart_overlay = 1 ;
break ;
case V4L2_CID_PRIVATE_Y_ODD :
dev - > ctl_y_odd = c - > value ;
restart_overlay = 1 ;
break ;
case V4L2_CID_PRIVATE_AUTOMUTE :
2007-10-18 19:56:47 -03:00
{
struct v4l2_priv_tun_config tda9887_cfg ;
tda9887_cfg . tuner = TUNER_TDA9887 ;
tda9887_cfg . priv = & dev - > tda9887_conf ;
2005-04-16 15:20:36 -07:00
dev - > ctl_automute = c - > value ;
if ( dev - > tda9887_conf ) {
if ( dev - > ctl_automute )
dev - > tda9887_conf | = TDA9887_AUTOMUTE ;
else
dev - > tda9887_conf & = ~ TDA9887_AUTOMUTE ;
2007-10-18 19:56:47 -03:00
2009-01-17 12:17:14 -03:00
saa_call_all ( dev , tuner , s_config , & tda9887_cfg ) ;
2005-04-16 15:20:36 -07:00
}
break ;
2007-10-18 19:56:47 -03:00
}
2005-04-16 15:20:36 -07:00
default :
2007-12-07 17:34:48 -03:00
goto error ;
2005-04-16 15:20:36 -07:00
}
if ( restart_overlay & & fh & & res_check ( fh , RESOURCE_OVERLAY ) ) {
spin_lock_irqsave ( & dev - > slock , flags ) ;
stop_preview ( dev , fh ) ;
start_preview ( dev , fh ) ;
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
}
2007-12-07 17:34:48 -03:00
err = 0 ;
error :
2007-12-07 17:09:53 -03:00
mutex_unlock ( & dev - > lock ) ;
2007-12-07 17:34:48 -03:00
return err ;
2005-04-16 15:20:36 -07:00
}
2008-07-26 09:04:06 -03:00
EXPORT_SYMBOL_GPL ( saa7134_s_ctrl_internal ) ;
static int saa7134_s_ctrl ( struct file * file , void * f , struct v4l2_control * c )
{
struct saa7134_fh * fh = f ;
return saa7134_s_ctrl_internal ( fh - > dev , fh , c ) ;
}
2005-04-16 15:20:36 -07:00
/* ------------------------------------------------------------------ */
static struct videobuf_queue * saa7134_queue ( struct saa7134_fh * fh )
{
struct videobuf_queue * q = NULL ;
switch ( fh - > type ) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
q = & fh - > cap ;
break ;
case V4L2_BUF_TYPE_VBI_CAPTURE :
q = & fh - > vbi ;
break ;
default :
BUG ( ) ;
}
return q ;
}
static int saa7134_resource ( struct saa7134_fh * fh )
{
2007-04-27 12:31:18 -03:00
if ( fh - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE )
return RESOURCE_VIDEO ;
2005-04-16 15:20:36 -07:00
2007-04-27 12:31:18 -03:00
if ( fh - > type = = V4L2_BUF_TYPE_VBI_CAPTURE )
return RESOURCE_VBI ;
BUG ( ) ;
return 0 ;
2005-04-16 15:20:36 -07:00
}
2008-12-30 06:58:20 -03:00
static int video_open ( struct file * file )
2005-04-16 15:20:36 -07:00
{
2009-12-10 11:44:04 -02:00
struct video_device * vdev = video_devdata ( file ) ;
struct saa7134_dev * dev = video_drvdata ( file ) ;
2005-04-16 15:20:36 -07:00
struct saa7134_fh * fh ;
2009-12-10 11:44:04 -02:00
enum v4l2_buf_type type = 0 ;
2005-04-16 15:20:36 -07:00
int radio = 0 ;
2008-07-30 08:43:36 -03:00
2009-12-10 11:44:04 -02:00
switch ( vdev - > vfl_type ) {
case VFL_TYPE_GRABBER :
type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
break ;
case VFL_TYPE_VBI :
type = V4L2_BUF_TYPE_VBI_CAPTURE ;
break ;
case VFL_TYPE_RADIO :
radio = 1 ;
break ;
2005-04-16 15:20:36 -07:00
}
2009-12-10 11:47:13 -02:00
dprintk ( " open dev=%s radio=%d type=%s \n " , video_device_node_name ( vdev ) ,
radio , v4l2_type_names [ type ] ) ;
2005-04-16 15:20:36 -07:00
/* allocate + initialize per filehandle data */
2006-01-11 19:40:56 -02:00
fh = kzalloc ( sizeof ( * fh ) , GFP_KERNEL ) ;
2009-02-09 12:27:03 -03:00
if ( NULL = = fh )
2005-04-16 15:20:36 -07:00
return - ENOMEM ;
2009-02-09 12:27:03 -03:00
2005-04-16 15:20:36 -07:00
file - > private_data = fh ;
fh - > dev = dev ;
fh - > radio = radio ;
fh - > type = type ;
fh - > fmt = format_by_fourcc ( V4L2_PIX_FMT_BGR24 ) ;
fh - > width = 720 ;
fh - > height = 576 ;
2010-05-01 08:03:24 -03:00
v4l2_prio_open ( & dev - > prio , & fh - > prio ) ;
2005-04-16 15:20:36 -07:00
2008-04-22 14:42:13 -03:00
videobuf_queue_sg_init ( & fh - > cap , & video_qops ,
& dev - > pci - > dev , & dev - > slock ,
2005-04-16 15:20:36 -07:00
V4L2_BUF_TYPE_VIDEO_CAPTURE ,
V4L2_FIELD_INTERLACED ,
sizeof ( struct saa7134_buf ) ,
2010-09-20 17:39:46 -03:00
fh , NULL ) ;
2008-04-22 14:42:13 -03:00
videobuf_queue_sg_init ( & fh - > vbi , & saa7134_vbi_qops ,
& dev - > pci - > dev , & dev - > slock ,
2005-04-16 15:20:36 -07:00
V4L2_BUF_TYPE_VBI_CAPTURE ,
V4L2_FIELD_SEQ_TB ,
sizeof ( struct saa7134_buf ) ,
2010-09-20 17:39:46 -03:00
fh , NULL ) ;
2005-04-16 15:20:36 -07:00
saa7134_pgtable_alloc ( dev - > pci , & fh - > pt_cap ) ;
saa7134_pgtable_alloc ( dev - > pci , & fh - > pt_vbi ) ;
if ( fh - > radio ) {
/* switch to radio mode */
saa7134_tvaudio_setinput ( dev , & card ( dev ) . radio ) ;
2009-01-17 12:17:14 -03:00
saa_call_all ( dev , tuner , s_radio ) ;
2005-04-16 15:20:36 -07:00
} else {
/* switch to video/vbi mode */
video_mux ( dev , dev - > ctl_input ) ;
}
2005-07-12 13:59:01 -07:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
static ssize_t
video_read ( struct file * file , char __user * data , size_t count , loff_t * ppos )
{
struct saa7134_fh * fh = file - > private_data ;
switch ( fh - > type ) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
if ( res_locked ( fh - > dev , RESOURCE_VIDEO ) )
return - EBUSY ;
return videobuf_read_one ( saa7134_queue ( fh ) ,
data , count , ppos ,
file - > f_flags & O_NONBLOCK ) ;
case V4L2_BUF_TYPE_VBI_CAPTURE :
if ( ! res_get ( fh - > dev , fh , RESOURCE_VBI ) )
return - EBUSY ;
return videobuf_read_stream ( saa7134_queue ( fh ) ,
data , count , ppos , 1 ,
file - > f_flags & O_NONBLOCK ) ;
break ;
default :
BUG ( ) ;
return 0 ;
}
}
static unsigned int
video_poll ( struct file * file , struct poll_table_struct * wait )
{
struct saa7134_fh * fh = file - > private_data ;
struct videobuf_buffer * buf = NULL ;
2009-05-17 23:13:13 -03:00
unsigned int rc = 0 ;
2005-04-16 15:20:36 -07:00
if ( V4L2_BUF_TYPE_VBI_CAPTURE = = fh - > type )
return videobuf_poll_stream ( file , & fh - > vbi , wait ) ;
if ( res_check ( fh , RESOURCE_VIDEO ) ) {
2009-05-17 23:13:13 -03:00
mutex_lock ( & fh - > cap . vb_lock ) ;
2005-04-16 15:20:36 -07:00
if ( ! list_empty ( & fh - > cap . stream ) )
buf = list_entry ( fh - > cap . stream . next , struct videobuf_buffer , stream ) ;
} else {
2008-01-31 13:57:53 -03:00
mutex_lock ( & fh - > cap . vb_lock ) ;
2005-04-16 15:20:36 -07:00
if ( UNSET = = fh - > cap . read_off ) {
2005-07-12 13:59:01 -07:00
/* need to capture a new frame */
2008-01-31 13:57:53 -03:00
if ( res_locked ( fh - > dev , RESOURCE_VIDEO ) )
goto err ;
if ( 0 ! = fh - > cap . ops - > buf_prepare ( & fh - > cap , fh - > cap . read_buf , fh - > cap . field ) )
goto err ;
2005-11-08 21:37:43 -08:00
fh - > cap . ops - > buf_queue ( & fh - > cap , fh - > cap . read_buf ) ;
fh - > cap . read_off = 0 ;
2005-04-16 15:20:36 -07:00
}
buf = fh - > cap . read_buf ;
}
if ( ! buf )
2009-05-17 23:13:13 -03:00
goto err ;
2005-04-16 15:20:36 -07:00
poll_wait ( file , & buf - > done , wait ) ;
2007-11-06 20:02:36 -03:00
if ( buf - > state = = VIDEOBUF_DONE | |
buf - > state = = VIDEOBUF_ERROR )
2009-05-17 23:13:13 -03:00
rc = POLLIN | POLLRDNORM ;
mutex_unlock ( & fh - > cap . vb_lock ) ;
return rc ;
2008-01-31 13:57:53 -03:00
err :
mutex_unlock ( & fh - > cap . vb_lock ) ;
return POLLERR ;
2005-04-16 15:20:36 -07:00
}
2008-12-30 06:58:20 -03:00
static int video_release ( struct file * file )
2005-04-16 15:20:36 -07:00
{
struct saa7134_fh * fh = file - > private_data ;
struct saa7134_dev * dev = fh - > dev ;
2010-12-27 12:22:46 -03:00
struct saa6588_command cmd ;
2005-04-16 15:20:36 -07:00
unsigned long flags ;
2011-12-03 16:40:45 -03:00
saa7134_tvaudio_close ( dev ) ;
2005-04-16 15:20:36 -07:00
/* turn off overlay */
if ( res_check ( fh , RESOURCE_OVERLAY ) ) {
spin_lock_irqsave ( & dev - > slock , flags ) ;
stop_preview ( dev , fh ) ;
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
res_free ( dev , fh , RESOURCE_OVERLAY ) ;
}
/* stop video capture */
if ( res_check ( fh , RESOURCE_VIDEO ) ) {
videobuf_streamoff ( & fh - > cap ) ;
res_free ( dev , fh , RESOURCE_VIDEO ) ;
}
if ( fh - > cap . read_buf ) {
buffer_release ( & fh - > cap , fh - > cap . read_buf ) ;
kfree ( fh - > cap . read_buf ) ;
}
/* stop vbi capture */
if ( res_check ( fh , RESOURCE_VBI ) ) {
2007-11-13 20:11:26 -03:00
videobuf_stop ( & fh - > vbi ) ;
2005-04-16 15:20:36 -07:00
res_free ( dev , fh , RESOURCE_VBI ) ;
}
2005-07-12 13:59:01 -07:00
/* ts-capture will not work in planar mode, so turn it off Hac: 04.05*/
saa_andorb ( SAA7134_OFMT_VIDEO_A , 0x1f , 0 ) ;
saa_andorb ( SAA7134_OFMT_VIDEO_B , 0x1f , 0 ) ;
saa_andorb ( SAA7134_OFMT_DATA_A , 0x1f , 0 ) ;
saa_andorb ( SAA7134_OFMT_DATA_B , 0x1f , 0 ) ;
2009-10-05 10:48:17 -03:00
saa_call_all ( dev , core , s_power , 0 ) ;
2009-03-29 06:26:27 -03:00
if ( fh - > radio )
2010-12-27 12:22:46 -03:00
saa_call_all ( dev , core , ioctl , SAA6588_CMD_CLOSE , & cmd ) ;
2005-07-12 13:59:01 -07:00
2005-04-16 15:20:36 -07:00
/* free stuff */
videobuf_mmap_free ( & fh - > cap ) ;
videobuf_mmap_free ( & fh - > vbi ) ;
saa7134_pgtable_free ( dev - > pci , & fh - > pt_cap ) ;
saa7134_pgtable_free ( dev - > pci , & fh - > pt_vbi ) ;
2010-05-01 08:03:24 -03:00
v4l2_prio_close ( & dev - > prio , fh - > prio ) ;
2005-04-16 15:20:36 -07:00
file - > private_data = NULL ;
kfree ( fh ) ;
return 0 ;
}
2007-04-27 12:31:18 -03:00
static int video_mmap ( struct file * file , struct vm_area_struct * vma )
2005-04-16 15:20:36 -07:00
{
struct saa7134_fh * fh = file - > private_data ;
return videobuf_mmap_mapper ( saa7134_queue ( fh ) , vma ) ;
}
2009-03-29 06:26:27 -03:00
static ssize_t radio_read ( struct file * file , char __user * data ,
size_t count , loff_t * ppos )
{
struct saa7134_fh * fh = file - > private_data ;
struct saa7134_dev * dev = fh - > dev ;
2010-12-27 12:22:46 -03:00
struct saa6588_command cmd ;
2009-03-29 06:26:27 -03:00
cmd . block_count = count / 3 ;
cmd . buffer = data ;
cmd . instance = file ;
cmd . result = - ENODEV ;
2010-12-27 12:22:46 -03:00
saa_call_all ( dev , core , ioctl , SAA6588_CMD_READ , & cmd ) ;
2009-03-29 06:26:27 -03:00
return cmd . result ;
}
static unsigned int radio_poll ( struct file * file , poll_table * wait )
{
struct saa7134_fh * fh = file - > private_data ;
struct saa7134_dev * dev = fh - > dev ;
2010-12-27 12:22:46 -03:00
struct saa6588_command cmd ;
2009-03-29 06:26:27 -03:00
cmd . instance = file ;
cmd . event_list = wait ;
cmd . result = - ENODEV ;
2010-12-27 12:22:46 -03:00
saa_call_all ( dev , core , ioctl , SAA6588_CMD_POLL , & cmd ) ;
2009-03-29 06:26:27 -03:00
return cmd . result ;
}
2005-04-16 15:20:36 -07:00
/* ------------------------------------------------------------------ */
2008-05-28 12:16:41 -03:00
static int saa7134_try_get_set_fmt_vbi_cap ( struct file * file , void * priv ,
2007-12-07 17:34:48 -03:00
struct v4l2_format * f )
2005-04-16 15:20:36 -07:00
{
2007-12-07 17:34:48 -03:00
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
2005-04-16 15:20:36 -07:00
struct saa7134_tvnorm * norm = dev - > tvnorm ;
f - > fmt . vbi . sampling_rate = 6750000 * 4 ;
f - > fmt . vbi . samples_per_line = 2048 /* VBI_LINE_LENGTH */ ;
f - > fmt . vbi . sample_format = V4L2_PIX_FMT_GREY ;
f - > fmt . vbi . offset = 64 * 4 ;
2005-06-23 22:04:47 -07:00
f - > fmt . vbi . start [ 0 ] = norm - > vbi_v_start_0 ;
f - > fmt . vbi . count [ 0 ] = norm - > vbi_v_stop_0 - norm - > vbi_v_start_0 + 1 ;
f - > fmt . vbi . start [ 1 ] = norm - > vbi_v_start_1 ;
2005-04-16 15:20:36 -07:00
f - > fmt . vbi . count [ 1 ] = f - > fmt . vbi . count [ 0 ] ;
f - > fmt . vbi . flags = 0 ; /* VBI_UNSYNC VBI_INTERLACED */
2007-12-07 17:34:48 -03:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2008-05-28 12:16:41 -03:00
static int saa7134_g_fmt_vid_cap ( struct file * file , void * priv ,
2007-12-07 17:09:53 -03:00
struct v4l2_format * f )
2005-04-16 15:20:36 -07:00
{
2007-12-07 17:09:53 -03:00
struct saa7134_fh * fh = priv ;
2007-12-07 17:34:48 -03:00
f - > fmt . pix . width = fh - > width ;
f - > fmt . pix . height = fh - > height ;
f - > fmt . pix . field = fh - > cap . field ;
f - > fmt . pix . pixelformat = fh - > fmt - > fourcc ;
f - > fmt . pix . bytesperline =
( f - > fmt . pix . width * fh - > fmt - > depth ) > > 3 ;
f - > fmt . pix . sizeimage =
f - > fmt . pix . height * f - > fmt . pix . bytesperline ;
return 0 ;
}
2008-05-28 12:16:41 -03:00
static int saa7134_g_fmt_vid_overlay ( struct file * file , void * priv ,
2007-12-07 17:34:48 -03:00
struct v4l2_format * f )
{
struct saa7134_fh * fh = priv ;
if ( saa7134_no_overlay > 0 ) {
printk ( KERN_ERR " V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay \n " ) ;
2005-04-16 15:20:36 -07:00
return - EINVAL ;
}
2007-12-07 17:34:48 -03:00
f - > fmt . win = fh - > win ;
return 0 ;
2005-04-16 15:20:36 -07:00
}
2008-05-28 12:16:41 -03:00
static int saa7134_try_fmt_vid_cap ( struct file * file , void * priv ,
2007-12-07 17:09:53 -03:00
struct v4l2_format * f )
2005-04-16 15:20:36 -07:00
{
2007-12-07 17:09:53 -03:00
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
2007-12-07 17:34:48 -03:00
struct saa7134_format * fmt ;
enum v4l2_field field ;
unsigned int maxw , maxh ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:34:48 -03:00
fmt = format_by_fourcc ( f - > fmt . pix . pixelformat ) ;
if ( NULL = = fmt )
return - EINVAL ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:34:48 -03:00
field = f - > fmt . pix . field ;
maxw = min ( dev - > crop_current . width * 4 , dev - > crop_bounds . width ) ;
maxh = min ( dev - > crop_current . height * 4 , dev - > crop_bounds . height ) ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:34:48 -03:00
if ( V4L2_FIELD_ANY = = field ) {
field = ( f - > fmt . pix . height > maxh / 2 )
? V4L2_FIELD_INTERLACED
: V4L2_FIELD_BOTTOM ;
}
switch ( field ) {
case V4L2_FIELD_TOP :
case V4L2_FIELD_BOTTOM :
maxh = maxh / 2 ;
break ;
case V4L2_FIELD_INTERLACED :
break ;
default :
return - EINVAL ;
}
2005-04-16 15:20:36 -07:00
2007-12-07 17:34:48 -03:00
f - > fmt . pix . field = field ;
2010-03-19 14:58:23 -03:00
if ( f - > fmt . pix . width < 48 )
f - > fmt . pix . width = 48 ;
if ( f - > fmt . pix . height < 32 )
f - > fmt . pix . height = 32 ;
if ( f - > fmt . pix . width > maxw )
f - > fmt . pix . width = maxw ;
if ( f - > fmt . pix . height > maxh )
f - > fmt . pix . height = maxh ;
f - > fmt . pix . width & = ~ 0x03 ;
2007-12-07 17:34:48 -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 ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:34:48 -03:00
return 0 ;
}
2005-04-16 15:20:36 -07:00
2008-05-28 12:16:41 -03:00
static int saa7134_try_fmt_vid_overlay ( struct file * file , void * priv ,
2007-12-07 17:34:48 -03:00
struct v4l2_format * f )
{
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
if ( saa7134_no_overlay > 0 ) {
printk ( KERN_ERR " V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay \n " ) ;
2005-04-16 15:20:36 -07:00
return - EINVAL ;
}
2007-12-07 17:34:48 -03:00
return verify_preview ( dev , & f - > fmt . win ) ;
2005-04-16 15:20:36 -07:00
}
2008-05-28 12:16:41 -03:00
static int saa7134_s_fmt_vid_cap ( struct file * file , void * priv ,
2007-12-07 17:09:53 -03:00
struct v4l2_format * f )
2007-12-07 17:34:48 -03:00
{
struct saa7134_fh * fh = priv ;
int err ;
2008-05-28 12:16:41 -03:00
err = saa7134_try_fmt_vid_cap ( file , priv , f ) ;
2007-12-07 17:34:48 -03:00
if ( 0 ! = err )
return err ;
fh - > fmt = format_by_fourcc ( f - > fmt . pix . pixelformat ) ;
fh - > width = f - > fmt . pix . width ;
fh - > height = f - > fmt . pix . height ;
fh - > cap . field = f - > fmt . pix . field ;
return 0 ;
}
2008-05-28 12:16:41 -03:00
static int saa7134_s_fmt_vid_overlay ( struct file * file , void * priv ,
2007-12-07 17:34:48 -03:00
struct v4l2_format * f )
2005-04-16 15:20:36 -07:00
{
2007-12-07 17:09:53 -03:00
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
2005-04-16 15:20:36 -07:00
int err ;
2008-05-06 20:42:29 -07:00
unsigned long flags ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:34:48 -03:00
if ( saa7134_no_overlay > 0 ) {
printk ( KERN_ERR " V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay \n " ) ;
return - EINVAL ;
}
err = verify_preview ( dev , & f - > fmt . win ) ;
if ( 0 ! = err )
return err ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:34:48 -03:00
mutex_lock ( & dev - > lock ) ;
fh - > win = f - > fmt . win ;
fh - > nclips = f - > fmt . win . clipcount ;
if ( fh - > nclips > 8 )
fh - > nclips = 8 ;
if ( copy_from_user ( fh - > clips , f - > fmt . win . clips ,
sizeof ( struct v4l2_clip ) * fh - > nclips ) ) {
2006-02-07 06:49:14 -02:00
mutex_unlock ( & dev - > lock ) ;
2007-12-07 17:34:48 -03:00
return - EFAULT ;
2005-04-16 15:20:36 -07:00
}
2007-12-07 17:34:48 -03:00
if ( res_check ( fh , RESOURCE_OVERLAY ) ) {
spin_lock_irqsave ( & dev - > slock , flags ) ;
stop_preview ( dev , fh ) ;
start_preview ( dev , fh ) ;
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
}
mutex_unlock ( & dev - > lock ) ;
return 0 ;
2005-04-16 15:20:36 -07:00
}
2007-12-11 12:56:23 -03:00
int saa7134_queryctrl ( struct file * file , void * priv , struct v4l2_queryctrl * c )
2007-12-07 17:09:53 -03:00
{
const struct v4l2_queryctrl * ctrl ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
if ( ( c - > id < V4L2_CID_BASE | |
c - > id > = V4L2_CID_LASTP1 ) & &
( c - > id < V4L2_CID_PRIVATE_BASE | |
c - > id > = V4L2_CID_PRIVATE_LASTP1 ) )
return - EINVAL ;
ctrl = ctrl_by_id ( c - > id ) ;
* c = ( NULL ! = ctrl ) ? * ctrl : no_ctrl ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2007-12-11 15:01:57 -03:00
EXPORT_SYMBOL_GPL ( saa7134_queryctrl ) ;
2005-04-16 15:20:36 -07:00
2007-12-11 11:51:53 -03:00
static int saa7134_enum_input ( struct file * file , void * priv ,
2007-12-07 17:09:53 -03:00
struct v4l2_input * i )
2005-04-16 15:20:36 -07:00
{
2007-12-07 17:09:53 -03:00
struct saa7134_fh * fh = priv ;
2005-04-16 15:20:36 -07:00
struct saa7134_dev * dev = fh - > dev ;
2007-12-07 17:09:53 -03:00
unsigned int n ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
n = i - > index ;
if ( n > = SAA7134_INPUT_MAX )
return - EINVAL ;
if ( NULL = = card_in ( dev , i - > index ) . name )
return - EINVAL ;
i - > index = n ;
i - > type = V4L2_INPUT_TYPE_CAMERA ;
strcpy ( i - > name , card_in ( dev , n ) . name ) ;
if ( card_in ( dev , n ) . tv )
i - > type = V4L2_INPUT_TYPE_TUNER ;
i - > audioset = 1 ;
if ( n = = dev - > ctl_input ) {
int v1 = saa_readb ( SAA7134_STATUS_VIDEO1 ) ;
int v2 = saa_readb ( SAA7134_STATUS_VIDEO2 ) ;
if ( 0 ! = ( v1 & 0x40 ) )
i - > status | = V4L2_IN_ST_NO_H_LOCK ;
if ( 0 ! = ( v2 & 0x40 ) )
i - > status | = V4L2_IN_ST_NO_SYNC ;
if ( 0 ! = ( v2 & 0x0e ) )
i - > status | = V4L2_IN_ST_MACROVISION ;
}
2007-12-07 17:34:48 -03:00
i - > std = SAA7134_NORMS ;
2007-12-07 17:09:53 -03:00
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-11 11:51:53 -03:00
static int saa7134_g_input ( struct file * file , void * priv , unsigned int * i )
2007-12-07 17:23:38 -03:00
{
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
* i = dev - > ctl_input ;
return 0 ;
}
2007-12-11 11:51:53 -03:00
static int saa7134_s_input ( struct file * file , void * priv , unsigned int i )
2007-12-07 17:23:38 -03:00
{
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
2007-12-07 17:34:48 -03:00
int err ;
2010-05-01 08:03:24 -03:00
err = v4l2_prio_check ( & dev - > prio , fh - > prio ) ;
2007-12-07 17:34:48 -03:00
if ( 0 ! = err )
return err ;
2007-12-07 17:23:38 -03:00
2009-07-02 16:09:25 -03:00
if ( i > = SAA7134_INPUT_MAX )
2007-12-07 17:23:38 -03:00
return - EINVAL ;
if ( NULL = = card_in ( dev , i ) . name )
return - EINVAL ;
mutex_lock ( & dev - > lock ) ;
video_mux ( dev , i ) ;
mutex_unlock ( & dev - > lock ) ;
return 0 ;
}
2007-12-11 11:51:53 -03:00
static int saa7134_querycap ( struct file * file , void * priv ,
2007-12-07 17:09:53 -03:00
struct v4l2_capability * cap )
{
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
unsigned int tuner_type = dev - > tuner_type ;
strcpy ( cap - > driver , " saa7134 " ) ;
strlcpy ( cap - > card , saa7134_boards [ dev - > board ] . name ,
sizeof ( cap - > card ) ) ;
sprintf ( cap - > bus_info , " PCI:%s " , pci_name ( dev - > pci ) ) ;
cap - > capabilities =
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
V4L2_CAP_TUNER ;
2009-06-20 06:09:52 -03:00
if ( dev - > has_rds )
cap - > capabilities | = V4L2_CAP_RDS_CAPTURE ;
2007-12-07 17:09:53 -03:00
if ( saa7134_no_overlay < = 0 )
cap - > capabilities | = V4L2_CAP_VIDEO_OVERLAY ;
if ( ( tuner_type = = TUNER_ABSENT ) | | ( tuner_type = = UNSET ) )
cap - > capabilities & = ~ V4L2_CAP_TUNER ;
2010-08-05 17:22:44 -03:00
return 0 ;
2007-12-07 17:09:53 -03:00
}
2005-11-08 21:36:35 -08:00
2008-09-06 06:34:44 -03:00
int saa7134_s_std_internal ( struct saa7134_dev * dev , struct saa7134_fh * fh , v4l2_std_id * id )
2007-12-07 17:09:53 -03:00
{
unsigned long flags ;
unsigned int i ;
v4l2_std_id fixup ;
2007-12-07 17:34:48 -03:00
int err ;
2008-09-06 06:34:44 -03:00
/* When called from the empress code fh == NULL.
That needs to be fixed somehow , but for now this is
good enough . */
if ( fh ) {
2010-05-01 08:03:24 -03:00
err = v4l2_prio_check ( & dev - > prio , fh - > prio ) ;
2008-09-06 06:34:44 -03:00
if ( 0 ! = err )
return err ;
} else if ( res_locked ( dev , RESOURCE_OVERLAY ) ) {
/* Don't change the std from the mpeg device
if overlay is active . */
return - EBUSY ;
}
2005-11-08 21:36:35 -08:00
2007-12-07 17:09:53 -03:00
for ( i = 0 ; i < TVNORMS ; i + + )
if ( * id = = tvnorms [ i ] . id )
break ;
2007-12-07 17:34:48 -03:00
2007-12-07 17:09:53 -03:00
if ( i = = TVNORMS )
for ( i = 0 ; i < TVNORMS ; i + + )
if ( * id & tvnorms [ i ] . id )
break ;
if ( i = = TVNORMS )
return - EINVAL ;
2007-12-07 17:34:48 -03:00
2007-12-07 17:09:53 -03:00
if ( ( * id & V4L2_STD_SECAM ) & & ( secam [ 0 ] ! = ' - ' ) ) {
if ( secam [ 0 ] = = ' L ' | | secam [ 0 ] = = ' l ' ) {
if ( secam [ 1 ] = = ' C ' | | secam [ 1 ] = = ' c ' )
fixup = V4L2_STD_SECAM_LC ;
else
fixup = V4L2_STD_SECAM_L ;
} else {
if ( secam [ 0 ] = = ' D ' | | secam [ 0 ] = = ' d ' )
fixup = V4L2_STD_SECAM_DK ;
else
fixup = V4L2_STD_SECAM ;
}
2010-10-04 16:28:01 -03:00
for ( i = 0 ; i < TVNORMS ; i + + ) {
2007-12-07 17:09:53 -03:00
if ( fixup = = tvnorms [ i ] . id )
break ;
2010-10-04 16:28:01 -03:00
}
if ( i = = TVNORMS )
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
2007-12-07 17:34:48 -03:00
* id = tvnorms [ i ] . id ;
2007-12-07 17:09:53 -03:00
mutex_lock ( & dev - > lock ) ;
2008-09-06 06:34:44 -03:00
if ( fh & & res_check ( fh , RESOURCE_OVERLAY ) ) {
2007-12-07 17:09:53 -03:00
spin_lock_irqsave ( & dev - > slock , flags ) ;
stop_preview ( dev , fh ) ;
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
set_tvnorm ( dev , & tvnorms [ i ] ) ;
spin_lock_irqsave ( & dev - > slock , flags ) ;
start_preview ( dev , fh ) ;
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
} else
set_tvnorm ( dev , & tvnorms [ i ] ) ;
2007-12-07 17:34:48 -03:00
2007-12-07 17:09:53 -03:00
saa7134_tvaudio_do_scan ( dev ) ;
mutex_unlock ( & dev - > lock ) ;
return 0 ;
}
2008-09-06 06:34:44 -03:00
EXPORT_SYMBOL_GPL ( saa7134_s_std_internal ) ;
static int saa7134_s_std ( struct file * file , void * priv , v4l2_std_id * id )
{
struct saa7134_fh * fh = priv ;
return saa7134_s_std_internal ( fh - > dev , fh , id ) ;
}
static int saa7134_g_std ( struct file * file , void * priv , v4l2_std_id * id )
{
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
* id = dev - > tvnorm - > id ;
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-11 11:51:53 -03:00
static int saa7134_cropcap ( struct file * file , void * priv ,
2007-12-07 17:09:53 -03:00
struct v4l2_cropcap * cap )
{
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
if ( cap - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE & &
cap - > type ! = V4L2_BUF_TYPE_VIDEO_OVERLAY )
return - EINVAL ;
cap - > bounds = dev - > crop_bounds ;
cap - > defrect = dev - > crop_defrect ;
cap - > pixelaspect . numerator = 1 ;
cap - > pixelaspect . denominator = 1 ;
if ( dev - > tvnorm - > id & V4L2_STD_525_60 ) {
cap - > pixelaspect . numerator = 11 ;
cap - > pixelaspect . denominator = 10 ;
}
if ( dev - > tvnorm - > id & V4L2_STD_625_50 ) {
cap - > pixelaspect . numerator = 54 ;
cap - > pixelaspect . denominator = 59 ;
2005-04-16 15:20:36 -07:00
}
2007-12-07 17:09:53 -03:00
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-11 11:51:53 -03:00
static int saa7134_g_crop ( struct file * file , void * f , struct v4l2_crop * crop )
2007-12-07 17:23:38 -03:00
{
struct saa7134_fh * fh = f ;
struct saa7134_dev * dev = fh - > dev ;
if ( crop - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE & &
crop - > type ! = V4L2_BUF_TYPE_VIDEO_OVERLAY )
return - EINVAL ;
crop - > c = dev - > crop_current ;
return 0 ;
}
2007-12-11 11:51:53 -03:00
static int saa7134_s_crop ( struct file * file , void * f , struct v4l2_crop * crop )
2007-12-07 17:23:38 -03:00
{
struct saa7134_fh * fh = f ;
struct saa7134_dev * dev = fh - > dev ;
struct v4l2_rect * b = & dev - > crop_bounds ;
if ( crop - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE & &
crop - > type ! = V4L2_BUF_TYPE_VIDEO_OVERLAY )
return - EINVAL ;
if ( crop - > c . height < 0 )
return - EINVAL ;
if ( crop - > c . width < 0 )
return - EINVAL ;
if ( res_locked ( fh - > dev , RESOURCE_OVERLAY ) )
return - EBUSY ;
if ( res_locked ( fh - > dev , RESOURCE_VIDEO ) )
return - EBUSY ;
if ( crop - > c . top < b - > top )
crop - > c . top = b - > top ;
if ( crop - > c . top > b - > top + b - > height )
crop - > c . top = b - > top + b - > height ;
if ( crop - > c . height > b - > top - crop - > c . top + b - > height )
crop - > c . height = b - > top - crop - > c . top + b - > height ;
if ( crop - > c . left < b - > left )
crop - > c . left = b - > left ;
if ( crop - > c . left > b - > left + b - > width )
crop - > c . left = b - > left + b - > width ;
if ( crop - > c . width > b - > left - crop - > c . left + b - > width )
crop - > c . width = b - > left - crop - > c . left + b - > width ;
dev - > crop_current = crop - > c ;
return 0 ;
}
2007-12-11 11:51:53 -03:00
static int saa7134_g_tuner ( struct file * file , void * priv ,
2007-12-07 17:09:53 -03:00
struct v4l2_tuner * t )
{
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
int n ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
if ( 0 ! = t - > index )
return - EINVAL ;
memset ( t , 0 , sizeof ( * t ) ) ;
2010-10-04 16:28:01 -03:00
for ( n = 0 ; n < SAA7134_INPUT_MAX ; n + + ) {
2007-12-07 17:09:53 -03:00
if ( card_in ( dev , n ) . tv )
break ;
2010-10-04 16:28:01 -03:00
}
if ( n = = SAA7134_INPUT_MAX )
return - EINVAL ;
2007-12-07 17:09:53 -03:00
if ( NULL ! = card_in ( dev , n ) . name ) {
strcpy ( t - > name , " Television " ) ;
t - > type = V4L2_TUNER_ANALOG_TV ;
t - > capability = V4L2_TUNER_CAP_NORM |
V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_LANG1 |
V4L2_TUNER_CAP_LANG2 ;
t - > rangehigh = 0xffffffffUL ;
t - > rxsubchans = saa7134_tvaudio_getstereo ( dev ) ;
t - > audmode = saa7134_tvaudio_rx2mode ( t - > rxsubchans ) ;
}
if ( 0 ! = ( saa_readb ( SAA7134_STATUS_VIDEO1 ) & 0x03 ) )
t - > signal = 0xffff ;
return 0 ;
}
2007-09-27 20:34:15 -03:00
2007-12-11 11:51:53 -03:00
static int saa7134_s_tuner ( struct file * file , void * priv ,
2007-12-07 17:09:53 -03:00
struct v4l2_tuner * t )
{
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
2007-12-07 17:34:48 -03:00
int rx , mode , err ;
2010-05-01 08:03:24 -03:00
err = v4l2_prio_check ( & dev - > prio , fh - > prio ) ;
2007-12-07 17:34:48 -03:00
if ( 0 ! = err )
return err ;
2007-09-27 20:34:15 -03:00
2007-12-07 17:09:53 -03:00
mode = dev - > thread . mode ;
if ( UNSET = = mode ) {
rx = saa7134_tvaudio_getstereo ( dev ) ;
2012-05-14 10:17:35 -03:00
mode = saa7134_tvaudio_rx2mode ( rx ) ;
2005-04-16 15:20:36 -07:00
}
2007-12-07 17:09:53 -03:00
if ( mode ! = t - > audmode )
dev - > thread . mode = t - > audmode ;
2007-12-07 17:34:48 -03:00
2007-12-07 17:09:53 -03:00
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-11 11:51:53 -03:00
static int saa7134_g_frequency ( struct file * file , void * priv ,
2007-12-07 17:09:53 -03:00
struct v4l2_frequency * f )
{
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
f - > type = fh - > radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV ;
f - > frequency = dev - > ctl_freq ;
2007-12-07 17:34:48 -03:00
2007-12-07 17:09:53 -03:00
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-11 11:51:53 -03:00
static int saa7134_s_frequency ( struct file * file , void * priv ,
2007-12-07 17:09:53 -03:00
struct v4l2_frequency * f )
{
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
2007-12-07 17:34:48 -03:00
int err ;
2010-05-01 08:03:24 -03:00
err = v4l2_prio_check ( & dev - > prio , fh - > prio ) ;
2007-12-07 17:34:48 -03:00
if ( 0 ! = err )
return err ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
if ( 0 ! = f - > tuner )
return - EINVAL ;
if ( 0 = = fh - > radio & & V4L2_TUNER_ANALOG_TV ! = f - > type )
return - EINVAL ;
if ( 1 = = fh - > radio & & V4L2_TUNER_RADIO ! = f - > type )
return - EINVAL ;
mutex_lock ( & dev - > lock ) ;
dev - > ctl_freq = f - > frequency ;
2005-04-16 15:20:36 -07:00
2009-01-17 12:17:14 -03:00
saa_call_all ( dev , tuner , s_frequency , f ) ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
saa7134_tvaudio_do_scan ( dev ) ;
mutex_unlock ( & dev - > lock ) ;
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-11 11:51:53 -03:00
static int saa7134_g_audio ( struct file * file , void * priv , struct v4l2_audio * a )
2007-12-07 17:09:53 -03:00
{
strcpy ( a - > name , " audio " ) ;
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-11 11:51:53 -03:00
static int saa7134_s_audio ( struct file * file , void * priv , struct v4l2_audio * a )
2007-12-07 17:09:53 -03:00
{
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-11 11:51:53 -03:00
static int saa7134_g_priority ( struct file * file , void * f , enum v4l2_priority * p )
2007-12-07 17:09:53 -03:00
{
struct saa7134_fh * fh = f ;
struct saa7134_dev * dev = fh - > dev ;
2007-12-07 17:23:38 -03:00
* p = v4l2_prio_max ( & dev - > prio ) ;
2007-12-07 17:09:53 -03:00
return 0 ;
}
2005-11-08 21:37:43 -08:00
2007-12-11 11:51:53 -03:00
static int saa7134_s_priority ( struct file * file , void * f ,
2007-12-07 17:23:38 -03:00
enum v4l2_priority prio )
2007-12-07 17:09:53 -03:00
{
struct saa7134_fh * fh = f ;
struct saa7134_dev * dev = fh - > dev ;
2005-11-08 21:37:43 -08:00
2007-12-07 17:23:38 -03:00
return v4l2_prio_change ( & dev - > prio , & fh - > prio , prio ) ;
2007-12-07 17:09:53 -03:00
}
2005-04-16 15:20:36 -07:00
2008-05-28 12:16:41 -03:00
static int saa7134_enum_fmt_vid_cap ( struct file * file , void * priv ,
2007-12-07 17:23:38 -03:00
struct v4l2_fmtdesc * f )
2007-12-07 17:09:53 -03:00
{
2007-12-07 17:34:48 -03:00
if ( f - > index > = FORMATS )
return - EINVAL ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:34:48 -03:00
strlcpy ( f - > description , formats [ f - > index ] . name ,
sizeof ( f - > description ) ) ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:34:48 -03:00
f - > pixelformat = formats [ f - > index ] . fourcc ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:34:48 -03:00
return 0 ;
}
2008-05-28 12:16:41 -03:00
static int saa7134_enum_fmt_vid_overlay ( struct file * file , void * priv ,
2007-12-07 17:34:48 -03:00
struct v4l2_fmtdesc * f )
{
if ( saa7134_no_overlay > 0 ) {
printk ( KERN_ERR " V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay \n " ) ;
2007-12-07 17:23:38 -03:00
return - EINVAL ;
}
2007-12-07 17:34:48 -03:00
if ( ( f - > index > = FORMATS ) | | formats [ f - > index ] . planar )
return - EINVAL ;
strlcpy ( f - > description , formats [ f - > index ] . name ,
sizeof ( f - > description ) ) ;
f - > pixelformat = formats [ f - > index ] . fourcc ;
return 0 ;
}
2007-12-11 11:51:53 -03:00
static int saa7134_g_fbuf ( struct file * file , void * f ,
2007-12-07 17:09:53 -03:00
struct v4l2_framebuffer * fb )
{
struct saa7134_fh * fh = f ;
struct saa7134_dev * dev = fh - > dev ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
* fb = dev - > ovbuf ;
fb - > capability = V4L2_FBUF_CAP_LIST_CLIPPING ;
2006-03-17 20:54:32 -03:00
2007-12-07 17:09:53 -03:00
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-11 11:51:53 -03:00
static int saa7134_s_fbuf ( struct file * file , void * f ,
2007-12-07 17:09:53 -03:00
struct v4l2_framebuffer * fb )
{
struct saa7134_fh * fh = f ;
struct saa7134_dev * dev = fh - > dev ;
struct saa7134_format * fmt ;
if ( ! capable ( CAP_SYS_ADMIN ) & &
! capable ( CAP_SYS_RAWIO ) )
return - EPERM ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
/* check args */
fmt = format_by_fourcc ( fb - > fmt . pixelformat ) ;
if ( NULL = = fmt )
return - EINVAL ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
/* ok, accept it */
dev - > ovbuf = * fb ;
dev - > ovfmt = fmt ;
if ( 0 = = dev - > ovbuf . fmt . bytesperline )
dev - > ovbuf . fmt . bytesperline =
dev - > ovbuf . fmt . width * fmt - > depth / 8 ;
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-11 11:51:53 -03:00
static int saa7134_overlay ( struct file * file , void * f , unsigned int on )
2007-12-07 17:09:53 -03:00
{
struct saa7134_fh * fh = f ;
struct saa7134_dev * dev = fh - > dev ;
unsigned long flags ;
if ( on ) {
if ( saa7134_no_overlay > 0 ) {
dprintk ( " no_overlay \n " ) ;
return - EINVAL ;
}
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
if ( ! res_get ( dev , fh , RESOURCE_OVERLAY ) )
2005-04-16 15:20:36 -07:00
return - EBUSY ;
2007-12-07 17:09:53 -03:00
spin_lock_irqsave ( & dev - > slock , flags ) ;
start_preview ( dev , fh ) ;
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
2005-04-16 15:20:36 -07:00
}
2007-12-07 17:09:53 -03:00
if ( ! on ) {
if ( ! res_check ( fh , RESOURCE_OVERLAY ) )
return - EINVAL ;
spin_lock_irqsave ( & dev - > slock , flags ) ;
stop_preview ( dev , fh ) ;
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
res_free ( dev , fh , RESOURCE_OVERLAY ) ;
2005-04-16 15:20:36 -07:00
}
2007-12-07 17:09:53 -03:00
return 0 ;
}
2007-12-11 11:51:53 -03:00
static int saa7134_reqbufs ( struct file * file , void * priv ,
2007-12-07 17:23:38 -03:00
struct v4l2_requestbuffers * p )
{
struct saa7134_fh * fh = priv ;
return videobuf_reqbufs ( saa7134_queue ( fh ) , p ) ;
}
2007-12-07 17:09:53 -03:00
2007-12-11 11:51:53 -03:00
static int saa7134_querybuf ( struct file * file , void * priv ,
2007-12-07 17:23:38 -03:00
struct v4l2_buffer * b )
{
struct saa7134_fh * fh = priv ;
return videobuf_querybuf ( saa7134_queue ( fh ) , b ) ;
}
2007-12-07 17:09:53 -03:00
2007-12-11 11:51:53 -03:00
static int saa7134_qbuf ( struct file * file , void * priv , struct v4l2_buffer * b )
2007-12-07 17:23:38 -03:00
{
struct saa7134_fh * fh = priv ;
return videobuf_qbuf ( saa7134_queue ( fh ) , b ) ;
}
2007-12-11 11:51:53 -03:00
static int saa7134_dqbuf ( struct file * file , void * priv , struct v4l2_buffer * b )
2007-12-07 17:23:38 -03:00
{
struct saa7134_fh * fh = priv ;
return videobuf_dqbuf ( saa7134_queue ( fh ) , b ,
file - > f_flags & O_NONBLOCK ) ;
}
2007-12-11 11:51:53 -03:00
static int saa7134_streamon ( struct file * file , void * priv ,
2007-12-07 17:23:38 -03:00
enum v4l2_buf_type type )
{
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
int res = saa7134_resource ( fh ) ;
if ( ! res_get ( dev , fh , res ) )
return - EBUSY ;
return videobuf_streamon ( saa7134_queue ( fh ) ) ;
}
2007-12-11 11:51:53 -03:00
static int saa7134_streamoff ( struct file * file , void * priv ,
2007-12-07 17:23:38 -03:00
enum v4l2_buf_type type )
{
int err ;
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
int res = saa7134_resource ( fh ) ;
err = videobuf_streamoff ( saa7134_queue ( fh ) ) ;
if ( err < 0 )
return err ;
res_free ( dev , fh , res ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2007-12-11 11:51:53 -03:00
static int saa7134_g_parm ( struct file * file , void * fh ,
2007-12-07 17:23:38 -03:00
struct v4l2_streamparm * parm )
2005-04-16 15:20:36 -07:00
{
2007-12-07 17:23:38 -03:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2008-06-16 12:31:57 -03:00
# ifdef CONFIG_VIDEO_ADV_DEBUG
static int vidioc_g_register ( struct file * file , void * priv ,
2008-12-30 07:14:19 -03:00
struct v4l2_dbg_register * reg )
2008-06-16 12:31:57 -03:00
{
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
2008-12-30 07:14:19 -03:00
if ( ! v4l2_chip_match_host ( & reg - > match ) )
2008-06-16 12:31:57 -03:00
return - EINVAL ;
reg - > val = saa_readb ( reg - > reg ) ;
2008-12-30 07:14:19 -03:00
reg - > size = 1 ;
2008-06-16 12:31:57 -03:00
return 0 ;
}
static int vidioc_s_register ( struct file * file , void * priv ,
2008-12-30 07:14:19 -03:00
struct v4l2_dbg_register * reg )
2008-06-16 12:31:57 -03:00
{
struct saa7134_fh * fh = priv ;
struct saa7134_dev * dev = fh - > dev ;
2008-12-30 07:14:19 -03:00
if ( ! v4l2_chip_match_host ( & reg - > match ) )
2008-06-16 12:31:57 -03:00
return - EINVAL ;
saa_writeb ( reg - > reg & 0xffffff , reg - > val ) ;
return 0 ;
}
# endif
2007-12-07 17:09:53 -03:00
static int radio_querycap ( struct file * file , void * priv ,
struct v4l2_capability * cap )
2005-04-16 15:20:36 -07:00
{
struct saa7134_fh * fh = file - > private_data ;
struct saa7134_dev * dev = fh - > dev ;
2007-12-07 17:09:53 -03:00
strcpy ( cap - > driver , " saa7134 " ) ;
strlcpy ( cap - > card , saa7134_boards [ dev - > board ] . name , sizeof ( cap - > card ) ) ;
sprintf ( cap - > bus_info , " PCI:%s " , pci_name ( dev - > pci ) ) ;
cap - > capabilities = V4L2_CAP_TUNER ;
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
static int radio_g_tuner ( struct file * file , void * priv ,
struct v4l2_tuner * t )
{
struct saa7134_fh * fh = file - > private_data ;
struct saa7134_dev * dev = fh - > dev ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
if ( 0 ! = t - > index )
return - EINVAL ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
memset ( t , 0 , sizeof ( * t ) ) ;
strcpy ( t - > name , " Radio " ) ;
t - > type = V4L2_TUNER_RADIO ;
2009-01-17 12:17:14 -03:00
saa_call_all ( dev , tuner , g_tuner , t ) ;
2007-12-07 17:09:53 -03:00
if ( dev - > input - > amux = = TV ) {
t - > signal = 0xf800 - ( ( saa_readb ( 0x581 ) & 0x1f ) < < 11 ) ;
t - > rxsubchans = ( saa_readb ( 0x529 ) & 0x08 ) ?
V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO ;
2005-06-23 22:05:09 -07:00
}
2007-12-07 17:09:53 -03:00
return 0 ;
}
static int radio_s_tuner ( struct file * file , void * priv ,
struct v4l2_tuner * t )
{
struct saa7134_fh * fh = file - > private_data ;
struct saa7134_dev * dev = fh - > dev ;
2005-06-23 22:05:09 -07:00
2007-12-07 17:09:53 -03:00
if ( 0 ! = t - > index )
return - EINVAL ;
2009-01-17 12:17:14 -03:00
saa_call_all ( dev , tuner , s_tuner , t ) ;
2007-12-07 17:09:53 -03:00
return 0 ;
}
2005-06-23 22:05:09 -07:00
2007-12-07 17:09:53 -03:00
static int radio_enum_input ( struct file * file , void * priv ,
struct v4l2_input * i )
{
if ( i - > index ! = 0 )
return - EINVAL ;
2005-06-23 22:05:09 -07:00
2007-12-07 17:09:53 -03:00
strcpy ( i - > name , " Radio " ) ;
i - > type = V4L2_INPUT_TYPE_TUNER ;
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
static int radio_g_input ( struct file * filp , void * priv , unsigned int * i )
{
* i = 0 ;
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
static int radio_g_audio ( struct file * file , void * priv ,
struct v4l2_audio * a )
{
memset ( a , 0 , sizeof ( * a ) ) ;
strcpy ( a - > name , " Radio " ) ;
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
static int radio_s_audio ( struct file * file , void * priv ,
struct v4l2_audio * a )
{
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
static int radio_s_input ( struct file * filp , void * priv , unsigned int i )
{
return 0 ;
}
2005-04-16 15:20:36 -07:00
2007-12-07 17:09:53 -03:00
static int radio_s_std ( struct file * file , void * fh , v4l2_std_id * norm )
{
2005-04-16 15:20:36 -07:00
return 0 ;
}
2007-12-07 17:09:53 -03:00
static int radio_queryctrl ( struct file * file , void * priv ,
struct v4l2_queryctrl * c )
2005-04-16 15:20:36 -07:00
{
2007-12-07 17:09:53 -03:00
const struct v4l2_queryctrl * ctrl ;
if ( c - > id < V4L2_CID_BASE | |
c - > id > = V4L2_CID_LASTP1 )
return - EINVAL ;
if ( c - > id = = V4L2_CID_AUDIO_MUTE ) {
ctrl = ctrl_by_id ( c - > id ) ;
* c = * ctrl ;
} else
* c = no_ctrl ;
return 0 ;
2005-04-16 15:20:36 -07:00
}
2008-12-30 06:58:20 -03:00
static const struct v4l2_file_operations video_fops =
2005-04-16 15:20:36 -07:00
{
. owner = THIS_MODULE ,
. open = video_open ,
. release = video_release ,
. read = video_read ,
. poll = video_poll ,
. mmap = video_mmap ,
2007-12-07 17:09:53 -03:00
. ioctl = video_ioctl2 ,
2005-04-16 15:20:36 -07:00
} ;
2008-07-21 02:57:38 -03:00
static const struct v4l2_ioctl_ops video_ioctl_ops = {
2007-12-11 11:51:53 -03:00
. vidioc_querycap = saa7134_querycap ,
2008-05-28 12:16:41 -03:00
. vidioc_enum_fmt_vid_cap = saa7134_enum_fmt_vid_cap ,
. vidioc_g_fmt_vid_cap = saa7134_g_fmt_vid_cap ,
. vidioc_try_fmt_vid_cap = saa7134_try_fmt_vid_cap ,
. vidioc_s_fmt_vid_cap = saa7134_s_fmt_vid_cap ,
. vidioc_enum_fmt_vid_overlay = saa7134_enum_fmt_vid_overlay ,
. vidioc_g_fmt_vid_overlay = saa7134_g_fmt_vid_overlay ,
. vidioc_try_fmt_vid_overlay = saa7134_try_fmt_vid_overlay ,
. vidioc_s_fmt_vid_overlay = saa7134_s_fmt_vid_overlay ,
. vidioc_g_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap ,
. vidioc_try_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap ,
. vidioc_s_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap ,
2007-12-11 11:51:53 -03:00
. vidioc_g_audio = saa7134_g_audio ,
. vidioc_s_audio = saa7134_s_audio ,
. vidioc_cropcap = saa7134_cropcap ,
. vidioc_reqbufs = saa7134_reqbufs ,
. vidioc_querybuf = saa7134_querybuf ,
. vidioc_qbuf = saa7134_qbuf ,
. vidioc_dqbuf = saa7134_dqbuf ,
. vidioc_s_std = saa7134_s_std ,
2008-09-06 06:34:44 -03:00
. vidioc_g_std = saa7134_g_std ,
2007-12-11 11:51:53 -03:00
. vidioc_enum_input = saa7134_enum_input ,
. vidioc_g_input = saa7134_g_input ,
. vidioc_s_input = saa7134_s_input ,
. vidioc_queryctrl = saa7134_queryctrl ,
. vidioc_g_ctrl = saa7134_g_ctrl ,
. vidioc_s_ctrl = saa7134_s_ctrl ,
. vidioc_streamon = saa7134_streamon ,
. vidioc_streamoff = saa7134_streamoff ,
. vidioc_g_tuner = saa7134_g_tuner ,
. vidioc_s_tuner = saa7134_s_tuner ,
. vidioc_g_crop = saa7134_g_crop ,
. vidioc_s_crop = saa7134_s_crop ,
. vidioc_g_fbuf = saa7134_g_fbuf ,
. vidioc_s_fbuf = saa7134_s_fbuf ,
. vidioc_overlay = saa7134_overlay ,
. vidioc_g_priority = saa7134_g_priority ,
. vidioc_s_priority = saa7134_s_priority ,
. vidioc_g_parm = saa7134_g_parm ,
. vidioc_g_frequency = saa7134_g_frequency ,
. vidioc_s_frequency = saa7134_s_frequency ,
2008-06-16 12:31:57 -03:00
# ifdef CONFIG_VIDEO_ADV_DEBUG
. vidioc_g_register = vidioc_g_register ,
. vidioc_s_register = vidioc_s_register ,
# endif
2005-04-16 15:20:36 -07:00
} ;
2008-12-30 06:58:20 -03:00
static const struct v4l2_file_operations radio_fops = {
2008-07-21 02:57:38 -03:00
. owner = THIS_MODULE ,
. open = video_open ,
2009-03-29 06:26:27 -03:00
. read = radio_read ,
2008-07-21 02:57:38 -03:00
. release = video_release ,
. ioctl = video_ioctl2 ,
2009-03-29 06:26:27 -03:00
. poll = radio_poll ,
2008-07-21 02:57:38 -03:00
} ;
static const struct v4l2_ioctl_ops radio_ioctl_ops = {
2007-12-07 17:09:53 -03:00
. vidioc_querycap = radio_querycap ,
. vidioc_g_tuner = radio_g_tuner ,
. vidioc_enum_input = radio_enum_input ,
. vidioc_g_audio = radio_g_audio ,
. vidioc_s_tuner = radio_s_tuner ,
. vidioc_s_audio = radio_s_audio ,
. vidioc_s_input = radio_s_input ,
. vidioc_s_std = radio_s_std ,
. vidioc_queryctrl = radio_queryctrl ,
. vidioc_g_input = radio_g_input ,
2007-12-11 11:51:53 -03:00
. vidioc_g_ctrl = saa7134_g_ctrl ,
. vidioc_s_ctrl = saa7134_s_ctrl ,
. vidioc_g_frequency = saa7134_g_frequency ,
. vidioc_s_frequency = saa7134_s_frequency ,
2005-04-16 15:20:36 -07:00
} ;
2008-07-21 02:57:38 -03:00
/* ----------------------------------------------------------- */
/* exported stuff */
struct video_device saa7134_video_template = {
. name = " saa7134-video " ,
. fops = & video_fops ,
. ioctl_ops = & video_ioctl_ops ,
. tvnorms = SAA7134_NORMS ,
. current_norm = V4L2_STD_PAL ,
} ;
struct video_device saa7134_radio_template = {
. name = " saa7134-radio " ,
. fops = & radio_fops ,
. ioctl_ops = & radio_ioctl_ops ,
} ;
2005-04-16 15:20:36 -07:00
int saa7134_video_init1 ( struct saa7134_dev * dev )
{
/* sanitycheck insmod options */
if ( gbuffers < 2 | | gbuffers > VIDEO_MAX_FRAME )
gbuffers = 2 ;
if ( gbufsize < 0 | | gbufsize > gbufsize_max )
gbufsize = gbufsize_max ;
gbufsize = ( gbufsize + PAGE_SIZE - 1 ) & PAGE_MASK ;
/* put some sensible defaults into the data structures ... */
dev - > ctl_bright = ctrl_by_id ( V4L2_CID_BRIGHTNESS ) - > default_value ;
dev - > ctl_contrast = ctrl_by_id ( V4L2_CID_CONTRAST ) - > default_value ;
dev - > ctl_hue = ctrl_by_id ( V4L2_CID_HUE ) - > default_value ;
dev - > ctl_saturation = ctrl_by_id ( V4L2_CID_SATURATION ) - > default_value ;
dev - > ctl_volume = ctrl_by_id ( V4L2_CID_AUDIO_VOLUME ) - > default_value ;
dev - > ctl_mute = 1 ; // ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value;
dev - > ctl_invert = ctrl_by_id ( V4L2_CID_PRIVATE_INVERT ) - > default_value ;
dev - > ctl_automute = ctrl_by_id ( V4L2_CID_PRIVATE_AUTOMUTE ) - > default_value ;
if ( dev - > tda9887_conf & & dev - > ctl_automute )
dev - > tda9887_conf | = TDA9887_AUTOMUTE ;
dev - > automute = 0 ;
2005-11-08 21:37:43 -08:00
INIT_LIST_HEAD ( & dev - > video_q . queue ) ;
2005-04-16 15:20:36 -07:00
init_timer ( & dev - > video_q . timeout ) ;
dev - > video_q . timeout . function = saa7134_buffer_timeout ;
dev - > video_q . timeout . data = ( unsigned long ) ( & dev - > video_q ) ;
dev - > video_q . dev = dev ;
2007-09-27 20:34:25 -03:00
if ( saa7134_boards [ dev - > board ] . video_out )
saa7134_videoport_init ( dev ) ;
return 0 ;
}
int saa7134_videoport_init ( struct saa7134_dev * dev )
{
/* enable video output */
int vo = saa7134_boards [ dev - > board ] . video_out ;
int video_reg ;
unsigned int vid_port_opts = saa7134_boards [ dev - > board ] . vid_port_opts ;
2008-06-10 12:43:58 -03:00
/* Configure videoport */
2007-09-27 20:34:25 -03:00
saa_writeb ( SAA7134_VIDEO_PORT_CTRL0 , video_out [ vo ] [ 0 ] ) ;
video_reg = video_out [ vo ] [ 1 ] ;
if ( vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED )
video_reg & = ~ VP_T_CODE_P_INVERTED ;
saa_writeb ( SAA7134_VIDEO_PORT_CTRL1 , video_reg ) ;
saa_writeb ( SAA7134_VIDEO_PORT_CTRL2 , video_out [ vo ] [ 2 ] ) ;
saa_writeb ( SAA7134_VIDEO_PORT_CTRL4 , video_out [ vo ] [ 4 ] ) ;
video_reg = video_out [ vo ] [ 5 ] ;
if ( vid_port_opts & SET_CLOCK_NOT_DELAYED )
video_reg & = ~ VP_CLK_CTRL2_DELAYED ;
if ( vid_port_opts & SET_CLOCK_INVERTED )
video_reg | = VP_CLK_CTRL1_INVERTED ;
saa_writeb ( SAA7134_VIDEO_PORT_CTRL5 , video_reg ) ;
video_reg = video_out [ vo ] [ 6 ] ;
if ( vid_port_opts & SET_VSYNC_OFF ) {
video_reg & = ~ VP_VS_TYPE_MASK ;
video_reg | = VP_VS_TYPE_OFF ;
}
saa_writeb ( SAA7134_VIDEO_PORT_CTRL6 , video_reg ) ;
saa_writeb ( SAA7134_VIDEO_PORT_CTRL7 , video_out [ vo ] [ 7 ] ) ;
saa_writeb ( SAA7134_VIDEO_PORT_CTRL8 , video_out [ vo ] [ 8 ] ) ;
2005-04-16 15:20:36 -07:00
2008-06-10 12:43:58 -03:00
/* Start videoport */
saa_writeb ( SAA7134_VIDEO_PORT_CTRL3 , video_out [ vo ] [ 3 ] ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
int saa7134_video_init2 ( struct saa7134_dev * dev )
{
/* init video hw */
set_tvnorm ( dev , & tvnorms [ 0 ] ) ;
video_mux ( dev , 0 ) ;
saa7134_tvaudio_setmute ( dev ) ;
saa7134_tvaudio_setvolume ( dev , dev - > ctl_volume ) ;
return 0 ;
}
2007-09-27 20:44:39 -03:00
void saa7134_irq_video_signalchange ( struct saa7134_dev * dev )
2005-04-16 15:20:36 -07:00
{
static const char * st [ ] = {
" (no signal) " , " NTSC " , " PAL " , " SECAM " } ;
u32 st1 , st2 ;
st1 = saa_readb ( SAA7134_STATUS_VIDEO1 ) ;
st2 = saa_readb ( SAA7134_STATUS_VIDEO2 ) ;
dprintk ( " DCSDT: pll: %s, sync: %s, norm: %s \n " ,
( st1 & 0x40 ) ? " not locked " : " locked " ,
( st2 & 0x40 ) ? " no " : " yes " ,
st [ st1 & 0x03 ] ) ;
2007-09-27 20:44:39 -03:00
dev - > nosignal = ( st1 & 0x40 ) | | ( st2 & 0x40 ) | | ! ( st2 & 0x1 ) ;
2005-04-16 15:20:36 -07:00
if ( dev - > nosignal ) {
/* no video signal -> mute audio */
if ( dev - > ctl_automute )
dev - > automute = 1 ;
saa7134_tvaudio_setmute ( dev ) ;
} else {
/* wake up tvaudio audio carrier scan thread */
saa7134_tvaudio_do_scan ( dev ) ;
}
2007-09-27 20:44:39 -03:00
if ( ( st2 & 0x80 ) & & ! noninterlaced & & ! dev - > nosignal )
saa_clearb ( SAA7134_SYNC_CTRL , 0x20 ) ;
else
saa_setb ( SAA7134_SYNC_CTRL , 0x20 ) ;
2005-04-16 15:20:36 -07:00
if ( dev - > mops & & dev - > mops - > signal_change )
dev - > mops - > signal_change ( dev ) ;
}
2007-09-27 20:44:39 -03:00
2005-04-16 15:20:36 -07:00
void saa7134_irq_video_done ( struct saa7134_dev * dev , unsigned long status )
{
enum v4l2_field field ;
spin_lock ( & dev - > slock ) ;
if ( dev - > video_q . curr ) {
dev - > video_fieldcount + + ;
field = dev - > video_q . curr - > vb . field ;
if ( V4L2_FIELD_HAS_BOTH ( field ) ) {
/* make sure we have seen both fields */
if ( ( status & 0x10 ) = = 0x00 ) {
dev - > video_q . curr - > top_seen = 1 ;
goto done ;
}
if ( ! dev - > video_q . curr - > top_seen )
goto done ;
} else if ( field = = V4L2_FIELD_TOP ) {
if ( ( status & 0x10 ) ! = 0x10 )
goto done ;
} else if ( field = = V4L2_FIELD_BOTTOM ) {
if ( ( status & 0x10 ) ! = 0x00 )
goto done ;
}
dev - > video_q . curr - > vb . field_count = dev - > video_fieldcount ;
2007-11-06 20:02:36 -03:00
saa7134_buffer_finish ( dev , & dev - > video_q , VIDEOBUF_DONE ) ;
2005-04-16 15:20:36 -07:00
}
saa7134_buffer_next ( dev , & dev - > video_q ) ;
done :
spin_unlock ( & dev - > slock ) ;
}
/* ----------------------------------------------------------- */
/*
* Local variables :
* c - basic - offset : 8
* End :
*/