2008-01-10 04:25:59 -03:00
/*
* Driver for the Conexant CX23885 PCIe bridge
*
2008-09-03 17:12:12 -03:00
* Copyright ( c ) 2007 Steven Toth < stoth @ linuxtv . org >
2008-01-10 04:25:59 -03:00
*
* 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 .
*/
2016-11-13 09:46:11 -02:00
# include "cx23885.h"
# include "cx23885-video.h"
2008-01-10 04:25:59 -03:00
# include <linux/init.h>
# include <linux/list.h>
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/kmod.h>
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/interrupt.h>
# include <linux/delay.h>
# include <linux/kthread.h>
# include <asm/div64.h>
# include <media/v4l2-common.h>
2008-07-20 08:12:02 -03:00
# include <media/v4l2-ioctl.h>
2014-04-23 06:34:44 -03:00
# include <media/v4l2-event.h>
2009-09-26 22:50:44 -03:00
# include "cx23885-ioctl.h"
2010-01-22 04:55:28 -03:00
# include "tuner-xc2028.h"
2008-01-10 04:25:59 -03:00
2015-11-13 19:40:07 -02:00
# include <media/drv-intf/cx25840.h>
2011-10-10 11:09:53 -03:00
2008-01-10 04:25:59 -03:00
MODULE_DESCRIPTION ( " v4l2 driver module for cx23885 based TV cards " ) ;
2008-09-03 17:12:12 -03:00
MODULE_AUTHOR ( " Steven Toth <stoth@linuxtv.org> " ) ;
2008-01-10 04:25:59 -03:00
MODULE_LICENSE ( " GPL " ) ;
/* ------------------------------------------------------------------ */
static unsigned int video_nr [ ] = { [ 0 . . . ( CX23885_MAXBOARDS - 1 ) ] = UNSET } ;
static unsigned int vbi_nr [ ] = { [ 0 . . . ( CX23885_MAXBOARDS - 1 ) ] = UNSET } ;
module_param_array ( video_nr , int , NULL , 0444 ) ;
module_param_array ( vbi_nr , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( video_nr , " video device numbers " ) ;
MODULE_PARM_DESC ( vbi_nr , " vbi device numbers " ) ;
2008-01-12 11:36:36 -03:00
static unsigned int video_debug ;
2008-01-10 04:25:59 -03:00
module_param ( video_debug , int , 0644 ) ;
MODULE_PARM_DESC ( video_debug , " enable debug messages [video] " ) ;
2008-01-12 11:36:36 -03:00
static unsigned int irq_debug ;
2008-01-10 04:25:59 -03:00
module_param ( irq_debug , int , 0644 ) ;
MODULE_PARM_DESC ( irq_debug , " enable debug messages [IRQ handler] " ) ;
static unsigned int vid_limit = 16 ;
module_param ( vid_limit , int , 0644 ) ;
MODULE_PARM_DESC ( vid_limit , " capture memory limit in megabytes " ) ;
# define dprintk(level, fmt, arg...)\
2008-01-12 11:36:36 -03:00
do { if ( video_debug > = level ) \
2016-11-13 09:46:11 -02:00
printk ( KERN_DEBUG pr_fmt ( " %s: video: " fmt ) , \
__func__ , # # arg ) ; \
2008-01-12 11:36:36 -03:00
} while ( 0 )
2008-01-10 04:25:59 -03:00
/* ------------------------------------------------------------------- */
/* static data */
# define FORMAT_FLAGS_PACKED 0x01
static struct cx23885_fmt formats [ ] = {
{
2011-10-10 11:09:54 -03:00
. name = " 4:2:2, packed, YUYV " ,
. fourcc = V4L2_PIX_FMT_YUYV ,
. depth = 16 ,
. flags = FORMAT_FLAGS_PACKED ,
}
} ;
2008-01-10 04:25:59 -03:00
static struct cx23885_fmt * format_by_fourcc ( unsigned int fourcc )
{
unsigned int i ;
for ( i = 0 ; i < ARRAY_SIZE ( formats ) ; i + + )
if ( formats [ i ] . fourcc = = fourcc )
return formats + i ;
return NULL ;
}
/* ------------------------------------------------------------------- */
2011-10-10 11:09:54 -03:00
void cx23885_video_wakeup ( struct cx23885_dev * dev ,
struct cx23885_dmaqueue * q , u32 count )
2008-01-10 04:25:59 -03:00
{
struct cx23885_buffer * buf ;
2014-08-14 06:43:01 -03:00
2008-10-16 20:18:44 -03:00
if ( list_empty ( & q - > active ) )
2014-08-14 06:43:01 -03:00
return ;
buf = list_entry ( q - > active . next ,
struct cx23885_buffer , queue ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
buf - > vb . sequence = q - > count + + ;
2015-11-03 08:16:37 -02:00
buf - > vb . vb2_buf . timestamp = ktime_get_ns ( ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
dprintk ( 2 , " [%p/%d] wakeup reg=%d buf=%d \n " , buf ,
buf - > vb . vb2_buf . index , count , q - > count ) ;
2014-08-14 06:43:01 -03:00
list_del ( & buf - > queue ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
vb2_buffer_done ( & buf - > vb . vb2_buf , VB2_BUF_STATE_DONE ) ;
2008-01-10 04:25:59 -03:00
}
2012-01-04 21:08:35 -03:00
int cx23885_set_tvnorm ( struct cx23885_dev * dev , v4l2_std_id norm )
2008-01-10 04:25:59 -03:00
{
2015-11-30 09:59:18 -02:00
struct v4l2_subdev_format format = {
. which = V4L2_SUBDEV_FORMAT_ACTIVE ,
. format . code = MEDIA_BUS_FMT_FIXED ,
} ;
2008-01-10 04:25:59 -03:00
dprintk ( 1 , " %s(norm = 0x%08x) name: [%s] \n " ,
2008-04-08 23:20:00 -03:00
__func__ ,
2008-01-10 04:25:59 -03:00
( unsigned int ) norm ,
v4l2_norm_to_name ( norm ) ) ;
2015-11-30 09:59:18 -02:00
if ( dev - > tvnorm = = norm )
return 0 ;
2014-08-14 06:43:36 -03:00
if ( dev - > tvnorm ! = norm ) {
if ( vb2_is_busy ( & dev - > vb2_vidq ) | | vb2_is_busy ( & dev - > vb2_vbiq ) | |
vb2_is_busy ( & dev - > vb2_mpegq ) )
return - EBUSY ;
}
2008-01-10 04:25:59 -03:00
dev - > tvnorm = norm ;
2015-11-30 09:59:18 -02:00
dev - > width = 720 ;
dev - > height = norm_maxh ( norm ) ;
dev - > field = V4L2_FIELD_INTERLACED ;
2008-01-10 04:25:59 -03:00
2014-04-28 16:53:01 -03:00
call_all ( dev , video , s_std , norm ) ;
2008-01-10 04:25:59 -03:00
2015-11-30 09:59:18 -02:00
format . format . width = dev - > width ;
format . format . height = dev - > height ;
format . format . field = dev - > field ;
call_all ( dev , pad , set_fmt , NULL , & format ) ;
2008-01-10 04:25:59 -03:00
return 0 ;
}
2008-09-04 03:33:43 -03:00
static struct video_device * cx23885_vdev_init ( struct cx23885_dev * dev ,
2008-01-10 04:25:59 -03:00
struct pci_dev * pci ,
struct video_device * template ,
char * type )
{
struct video_device * vfd ;
2008-04-08 23:20:00 -03:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2008-01-10 04:25:59 -03:00
vfd = video_device_alloc ( ) ;
if ( NULL = = vfd )
return NULL ;
* vfd = * template ;
2009-03-13 08:02:43 -03:00
vfd - > v4l2_dev = & dev - > v4l2_dev ;
2008-01-10 04:25:59 -03:00
vfd - > release = video_device_release ;
2014-08-09 11:29:55 -03:00
vfd - > lock = & dev - > lock ;
2012-01-04 21:13:26 -03:00
snprintf ( vfd - > name , sizeof ( vfd - > name ) , " %s (%s) " ,
cx23885_boards [ dev - > board ] . name , type ) ;
2009-12-10 11:44:04 -02:00
video_set_drvdata ( vfd , dev ) ;
2008-01-10 04:25:59 -03:00
return vfd ;
}
2013-07-24 09:06:01 -03:00
int cx23885_flatiron_write ( struct cx23885_dev * dev , u8 reg , u8 data )
2011-10-10 11:09:55 -03:00
{
/* 8 bit registers, 8 bit values */
u8 buf [ ] = { reg , data } ;
struct i2c_msg msg = { . addr = 0x98 > > 1 ,
. flags = 0 , . buf = buf , . len = 2 } ;
return i2c_transfer ( & dev - > i2c_bus [ 2 ] . i2c_adap , & msg , 1 ) ;
}
2013-07-24 09:06:01 -03:00
u8 cx23885_flatiron_read ( struct cx23885_dev * dev , u8 reg )
2011-10-10 11:09:55 -03:00
{
/* 8 bit registers, 8 bit values */
int ret ;
u8 b0 [ ] = { reg } ;
u8 b1 [ ] = { 0 } ;
struct i2c_msg msg [ ] = {
{ . addr = 0x98 > > 1 , . flags = 0 , . buf = b0 , . len = 1 } ,
{ . addr = 0x98 > > 1 , . flags = I2C_M_RD , . buf = b1 , . len = 1 }
} ;
ret = i2c_transfer ( & dev - > i2c_bus [ 2 ] . i2c_adap , & msg [ 0 ] , 2 ) ;
if ( ret ! = 2 )
2016-11-13 09:46:11 -02:00
pr_err ( " %s() error \n " , __func__ ) ;
2011-10-10 11:09:55 -03:00
return b1 [ 0 ] ;
}
static void cx23885_flatiron_dump ( struct cx23885_dev * dev )
{
int i ;
dprintk ( 1 , " Flatiron dump \n " ) ;
for ( i = 0 ; i < 0x24 ; i + + ) {
dprintk ( 1 , " FI[%02x] = %02x \n " , i ,
cx23885_flatiron_read ( dev , i ) ) ;
}
}
static int cx23885_flatiron_mux ( struct cx23885_dev * dev , int input )
{
u8 val ;
dprintk ( 1 , " %s(input = %d) \n " , __func__ , input ) ;
if ( input = = 1 )
val = cx23885_flatiron_read ( dev , CH_PWR_CTRL1 ) & ~ FLD_CH_SEL ;
else if ( input = = 2 )
val = cx23885_flatiron_read ( dev , CH_PWR_CTRL1 ) | FLD_CH_SEL ;
else
return - EINVAL ;
val | = 0x20 ; /* Enable clock to delta-sigma and dec filter */
cx23885_flatiron_write ( dev , CH_PWR_CTRL1 , val ) ;
/* Wake up */
cx23885_flatiron_write ( dev , CH_PWR_CTRL2 , 0 ) ;
if ( video_debug )
cx23885_flatiron_dump ( dev ) ;
return 0 ;
}
2008-09-04 03:33:43 -03:00
static int cx23885_video_mux ( struct cx23885_dev * dev , unsigned int input )
2008-01-10 04:25:59 -03:00
{
dprintk ( 1 , " %s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x] \n " ,
2008-04-08 23:20:00 -03:00
__func__ ,
2008-01-10 04:25:59 -03:00
input , INPUT ( input ) - > vmux ,
INPUT ( input ) - > gpio0 , INPUT ( input ) - > gpio1 ,
INPUT ( input ) - > gpio2 , INPUT ( input ) - > gpio3 ) ;
dev - > input = input ;
2009-10-21 13:15:30 -03:00
if ( dev - > board = = CX23885_BOARD_MYGICA_X8506 | |
2011-11-09 15:13:00 -03:00
dev - > board = = CX23885_BOARD_MAGICPRO_PROHDTVE2 | |
dev - > board = = CX23885_BOARD_MYGICA_X8507 ) {
2009-10-21 13:15:30 -03:00
/* Select Analog TV */
if ( INPUT ( input ) - > type = = CX23885_VMUX_TELEVISION )
cx23885_gpio_clear ( dev , GPIO_0 ) ;
}
2008-01-10 04:25:59 -03:00
/* Tell the internal A/V decoder */
2009-04-02 11:26:22 -03:00
v4l2_subdev_call ( dev - > sd_cx25840 , video , s_routing ,
INPUT ( input ) - > vmux , 0 , 0 ) ;
2008-01-10 04:25:59 -03:00
2011-10-10 11:09:55 -03:00
if ( ( dev - > board = = CX23885_BOARD_HAUPPAUGE_HVR1800 ) | |
2012-01-04 21:08:35 -03:00
( dev - > board = = CX23885_BOARD_MPX885 ) | |
2012-07-01 16:15:13 -03:00
( dev - > board = = CX23885_BOARD_HAUPPAUGE_HVR1250 ) | |
2014-06-27 11:15:42 -03:00
( dev - > board = = CX23885_BOARD_HAUPPAUGE_IMPACTVCBE ) | |
2012-07-01 16:15:14 -03:00
( dev - > board = = CX23885_BOARD_HAUPPAUGE_HVR1255 ) | |
( dev - > board = = CX23885_BOARD_HAUPPAUGE_HVR1255_22111 ) | |
2012-09-21 10:33:51 -03:00
( dev - > board = = CX23885_BOARD_HAUPPAUGE_HVR1850 ) | |
2012-12-08 18:20:59 -03:00
( dev - > board = = CX23885_BOARD_MYGICA_X8507 ) | |
2015-11-30 18:08:10 -02:00
( dev - > board = = CX23885_BOARD_AVERMEDIA_HC81R ) | |
( dev - > board = = CX23885_BOARD_VIEWCAST_260E ) | |
( dev - > board = = CX23885_BOARD_VIEWCAST_460E ) ) {
2011-10-10 11:09:55 -03:00
/* Configure audio routing */
v4l2_subdev_call ( dev - > sd_cx25840 , audio , s_routing ,
INPUT ( input ) - > amux , 0 , 0 ) ;
if ( INPUT ( input ) - > amux = = CX25840_AUDIO7 )
cx23885_flatiron_mux ( dev , 1 ) ;
else if ( INPUT ( input ) - > amux = = CX25840_AUDIO6 )
cx23885_flatiron_mux ( dev , 2 ) ;
}
2008-01-10 04:25:59 -03:00
return 0 ;
}
2011-10-10 11:09:56 -03:00
static int cx23885_audio_mux ( struct cx23885_dev * dev , unsigned int input )
{
dprintk ( 1 , " %s(input=%d) \n " , __func__ , input ) ;
2011-10-10 11:09:56 -03:00
/* The baseband video core of the cx23885 has two audio inputs.
* LR1 and LR2 . In almost every single case so far only HVR1xxx
* cards we ' ve only ever supported LR1 . Time to support LR2 ,
* which is available via the optional white breakout header on
* the board .
* We ' ll use a could of existing enums in the card struct to allow
* devs to specify which baseband input they need , or just default
* to what we ' ve always used .
*/
if ( INPUT ( input ) - > amux = = CX25840_AUDIO7 )
cx23885_flatiron_mux ( dev , 1 ) ;
else if ( INPUT ( input ) - > amux = = CX25840_AUDIO6 )
cx23885_flatiron_mux ( dev , 2 ) ;
else {
/* Not specifically defined, assume the default. */
cx23885_flatiron_mux ( dev , 1 ) ;
2011-10-10 11:09:56 -03:00
}
return 0 ;
}
2008-01-10 04:25:59 -03:00
/* ------------------------------------------------------------------ */
static int cx23885_start_video_dma ( struct cx23885_dev * dev ,
struct cx23885_dmaqueue * q ,
struct cx23885_buffer * buf )
{
2008-04-08 23:20:00 -03:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2008-01-10 04:25:59 -03:00
2011-10-10 11:09:56 -03:00
/* Stop the dma/fifo before we tamper with it's risc programs */
cx_clear ( VID_A_DMA_CTL , 0x11 ) ;
2008-01-10 04:25:59 -03:00
/* setup fifo + format */
cx23885_sram_channel_setup ( dev , & dev - > sram_channels [ SRAM_CH01 ] ,
buf - > bpl , buf - > risc . dma ) ;
/* reset counter */
cx_write ( VID_A_GPCNT_CTL , 3 ) ;
2014-08-14 06:43:01 -03:00
q - > count = 0 ;
2008-01-10 04:25:59 -03:00
/* enable irq */
2010-07-19 01:19:43 -03:00
cx23885_irq_add_enable ( dev , 0x01 ) ;
2008-01-10 04:25:59 -03:00
cx_set ( VID_A_INT_MSK , 0x000011 ) ;
/* start dma */
cx_set ( DEV_CNTRL2 , ( 1 < < 5 ) ) ;
cx_set ( VID_A_DMA_CTL , 0x11 ) ; /* FIFO and RISC enable */
return 0 ;
}
2015-10-28 00:50:37 -02:00
static int queue_setup ( struct vb2_queue * q ,
2014-08-14 06:43:01 -03:00
unsigned int * num_buffers , unsigned int * num_planes ,
2016-04-15 09:15:05 -03:00
unsigned int sizes [ ] , struct device * alloc_devs [ ] )
2008-01-10 04:25:59 -03:00
{
2014-08-14 06:43:01 -03:00
struct cx23885_dev * dev = q - > drv_priv ;
2008-01-10 04:25:59 -03:00
2014-08-14 06:43:01 -03:00
* num_planes = 1 ;
sizes [ 0 ] = ( dev - > fmt - > depth * dev - > width * dev - > height ) > > 3 ;
2008-01-10 04:25:59 -03:00
return 0 ;
}
2014-08-14 06:43:01 -03:00
static int buffer_prepare ( struct vb2_buffer * vb )
2008-01-10 04:25:59 -03:00
{
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct vb2_v4l2_buffer * vbuf = to_vb2_v4l2_buffer ( vb ) ;
2014-08-14 06:43:01 -03:00
struct cx23885_dev * dev = vb - > vb2_queue - > drv_priv ;
2008-01-10 04:25:59 -03:00
struct cx23885_buffer * buf =
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
container_of ( vbuf , struct cx23885_buffer , vb ) ;
2008-01-10 04:25:59 -03:00
u32 line0_offset , line1_offset ;
2014-08-14 06:43:01 -03:00
struct sg_table * sgt = vb2_dma_sg_plane_desc ( vb , 0 ) ;
2012-01-04 21:08:35 -03:00
int field_tff ;
2008-01-10 04:25:59 -03:00
2014-08-14 06:43:01 -03:00
buf - > bpl = ( dev - > width * dev - > fmt - > depth ) > > 3 ;
2014-04-23 07:52:07 -03:00
2014-08-14 06:43:01 -03:00
if ( vb2_plane_size ( vb , 0 ) < dev - > height * buf - > bpl )
2008-01-10 04:25:59 -03:00
return - EINVAL ;
2014-08-14 06:43:01 -03:00
vb2_set_plane_payload ( vb , 0 , dev - > height * buf - > bpl ) ;
2008-01-10 04:25:59 -03:00
2014-08-14 06:43:01 -03:00
switch ( dev - > field ) {
case V4L2_FIELD_TOP :
cx23885_risc_buffer ( dev - > pci , & buf - > risc ,
sgt - > sgl , 0 , UNSET ,
buf - > bpl , 0 , dev - > height ) ;
break ;
case V4L2_FIELD_BOTTOM :
cx23885_risc_buffer ( dev - > pci , & buf - > risc ,
sgt - > sgl , UNSET , 0 ,
buf - > bpl , 0 , dev - > height ) ;
break ;
case V4L2_FIELD_INTERLACED :
2014-08-09 18:04:41 -03:00
if ( dev - > tvnorm & V4L2_STD_525_60 )
2014-08-14 06:43:01 -03:00
/* NTSC or */
field_tff = 1 ;
else
field_tff = 0 ;
if ( cx23885_boards [ dev - > board ] . force_bff )
/* PAL / SECAM OR 888 in NTSC MODE */
field_tff = 0 ;
2008-01-10 04:25:59 -03:00
2014-08-14 06:43:01 -03:00
if ( field_tff ) {
/* cx25840 transmits NTSC bottom field first */
dprintk ( 1 , " %s() Creating TFF/NTSC risc \n " ,
2008-04-08 23:20:00 -03:00
__func__ ) ;
2014-08-14 06:43:01 -03:00
line0_offset = buf - > bpl ;
line1_offset = 0 ;
} else {
/* All other formats are top field first */
dprintk ( 1 , " %s() Creating BFF/PAL/SECAM risc \n " ,
2008-04-08 23:20:00 -03:00
__func__ ) ;
2014-08-14 06:43:01 -03:00
line0_offset = 0 ;
line1_offset = buf - > bpl ;
2008-01-10 04:25:59 -03:00
}
2014-08-14 06:43:01 -03:00
cx23885_risc_buffer ( dev - > pci , & buf - > risc ,
sgt - > sgl , line0_offset ,
line1_offset ,
buf - > bpl , buf - > bpl ,
dev - > height > > 1 ) ;
break ;
case V4L2_FIELD_SEQ_TB :
cx23885_risc_buffer ( dev - > pci , & buf - > risc ,
sgt - > sgl ,
0 , buf - > bpl * ( dev - > height > > 1 ) ,
buf - > bpl , 0 ,
dev - > height > > 1 ) ;
break ;
case V4L2_FIELD_SEQ_BT :
cx23885_risc_buffer ( dev - > pci , & buf - > risc ,
sgt - > sgl ,
buf - > bpl * ( dev - > height > > 1 ) , 0 ,
buf - > bpl , 0 ,
dev - > height > > 1 ) ;
break ;
default :
BUG ( ) ;
2008-01-10 04:25:59 -03:00
}
2014-08-14 06:43:01 -03:00
dprintk ( 2 , " [%p/%d] buffer_init - %dx%d %dbpp \" %s \" - dma=0x%08lx \n " ,
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
buf , buf - > vb . vb2_buf . index ,
2014-04-23 07:52:07 -03:00
dev - > width , dev - > height , dev - > fmt - > depth , dev - > fmt - > name ,
2008-01-10 04:25:59 -03:00
( unsigned long ) buf - > risc . dma ) ;
return 0 ;
2014-08-14 06:43:01 -03:00
}
2008-01-10 04:25:59 -03:00
2014-08-14 06:43:01 -03:00
static void buffer_finish ( struct vb2_buffer * vb )
{
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct vb2_v4l2_buffer * vbuf = to_vb2_v4l2_buffer ( vb ) ;
struct cx23885_buffer * buf = container_of ( vbuf ,
2014-08-14 06:43:01 -03:00
struct cx23885_buffer , vb ) ;
cx23885_free_buffer ( vb - > vb2_queue - > drv_priv , buf ) ;
2008-01-10 04:25:59 -03:00
}
2014-08-14 06:43:01 -03:00
/*
* The risc program for each buffer works as follows : it starts with a simple
* ' JUMP to addr + 12 ' , which is effectively a NOP . Then the code to DMA the
* buffer follows and at the end we have a JUMP back to the start + 12 ( skipping
* the initial JUMP ) .
*
* This is the risc program of the first buffer to be queued if the active list
* is empty and it just keeps DMAing this buffer without generating any
* interrupts .
*
* If a new buffer is added then the initial JUMP in the code for that buffer
* will generate an interrupt which signals that the previous buffer has been
* DMAed successfully and that it can be returned to userspace .
*
* It also sets the final jump of the previous buffer to the start of the new
* buffer , thus chaining the new buffer into the DMA chain . This is a single
* atomic u32 write , so there is no race condition .
*
* The end - result of all this that you only get an interrupt when a buffer
* is ready , so the control flow is very easy .
*/
static void buffer_queue ( struct vb2_buffer * vb )
2008-01-10 04:25:59 -03:00
{
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct vb2_v4l2_buffer * vbuf = to_vb2_v4l2_buffer ( vb ) ;
2014-08-14 06:43:01 -03:00
struct cx23885_dev * dev = vb - > vb2_queue - > drv_priv ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct cx23885_buffer * buf = container_of ( vbuf ,
2008-01-10 04:25:59 -03:00
struct cx23885_buffer , vb ) ;
struct cx23885_buffer * prev ;
struct cx23885_dmaqueue * q = & dev - > vidq ;
2014-08-14 06:43:01 -03:00
unsigned long flags ;
2008-01-10 04:25:59 -03:00
2014-08-14 06:43:01 -03:00
/* add jump to start */
buf - > risc . cpu [ 1 ] = cpu_to_le32 ( buf - > risc . dma + 12 ) ;
buf - > risc . jmp [ 0 ] = cpu_to_le32 ( RISC_JUMP | RISC_CNT_INC ) ;
buf - > risc . jmp [ 1 ] = cpu_to_le32 ( buf - > risc . dma + 12 ) ;
2008-01-10 04:25:59 -03:00
buf - > risc . jmp [ 2 ] = cpu_to_le32 ( 0 ) ; /* bits 63-32 */
2014-08-14 06:43:01 -03:00
spin_lock_irqsave ( & dev - > slock , flags ) ;
if ( list_empty ( & q - > active ) ) {
list_add_tail ( & buf - > queue , & q - > active ) ;
2008-01-10 04:25:59 -03:00
dprintk ( 2 , " [%p/%d] buffer_queue - first active \n " ,
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
buf , buf - > vb . vb2_buf . index ) ;
2008-01-10 04:25:59 -03:00
} else {
2014-08-14 06:43:01 -03:00
buf - > risc . cpu [ 0 ] | = cpu_to_le32 ( RISC_IRQ1 ) ;
2008-01-10 04:25:59 -03:00
prev = list_entry ( q - > active . prev , struct cx23885_buffer ,
2014-08-14 06:43:01 -03:00
queue ) ;
list_add_tail ( & buf - > queue , & q - > active ) ;
prev - > risc . jmp [ 1 ] = cpu_to_le32 ( buf - > risc . dma ) ;
dprintk ( 2 , " [%p/%d] buffer_queue - append to active \n " ,
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
buf , buf - > vb . vb2_buf . index ) ;
2008-01-10 04:25:59 -03:00
}
2014-08-14 06:43:01 -03:00
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
2008-01-10 04:25:59 -03:00
}
2014-08-14 06:43:01 -03:00
static int cx23885_start_streaming ( struct vb2_queue * q , unsigned int count )
2008-01-10 04:25:59 -03:00
{
2014-08-14 06:43:01 -03:00
struct cx23885_dev * dev = q - > drv_priv ;
struct cx23885_dmaqueue * dmaq = & dev - > vidq ;
struct cx23885_buffer * buf = list_entry ( dmaq - > active . next ,
struct cx23885_buffer , queue ) ;
2008-01-10 04:25:59 -03:00
2014-08-14 06:43:01 -03:00
cx23885_start_video_dma ( dev , dmaq , buf ) ;
2008-01-10 04:25:59 -03:00
return 0 ;
}
2014-08-14 06:43:01 -03:00
static void cx23885_stop_streaming ( struct vb2_queue * q )
2008-01-10 04:25:59 -03:00
{
2014-08-14 06:43:01 -03:00
struct cx23885_dev * dev = q - > drv_priv ;
struct cx23885_dmaqueue * dmaq = & dev - > vidq ;
unsigned long flags ;
2008-01-10 04:25:59 -03:00
2014-08-14 06:43:01 -03:00
cx_clear ( VID_A_DMA_CTL , 0x11 ) ;
spin_lock_irqsave ( & dev - > slock , flags ) ;
while ( ! list_empty ( & dmaq - > active ) ) {
struct cx23885_buffer * buf = list_entry ( dmaq - > active . next ,
struct cx23885_buffer , queue ) ;
2008-01-10 04:25:59 -03:00
2014-08-14 06:43:01 -03:00
list_del ( & buf - > queue ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
vb2_buffer_done ( & buf - > vb . vb2_buf , VB2_BUF_STATE_ERROR ) ;
2008-01-10 04:25:59 -03:00
}
2014-08-14 06:43:01 -03:00
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
2008-01-10 04:25:59 -03:00
}
2016-09-08 20:59:18 -03:00
static const struct vb2_ops cx23885_video_qops = {
2014-08-14 06:43:01 -03:00
. queue_setup = queue_setup ,
. buf_prepare = buffer_prepare ,
. buf_finish = buffer_finish ,
. buf_queue = buffer_queue ,
. wait_prepare = vb2_ops_wait_prepare ,
. wait_finish = vb2_ops_wait_finish ,
. start_streaming = cx23885_start_streaming ,
. stop_streaming = cx23885_stop_streaming ,
} ;
2008-01-10 04:25:59 -03:00
/* ------------------------------------------------------------------ */
/* VIDEO IOCTLS */
2008-05-28 12:16:41 -03:00
static int vidioc_g_fmt_vid_cap ( struct file * file , void * priv ,
2008-01-10 04:25:59 -03:00
struct v4l2_format * f )
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2008-01-10 04:25:59 -03:00
2014-04-23 07:52:07 -03:00
f - > fmt . pix . width = dev - > width ;
f - > fmt . pix . height = dev - > height ;
2014-08-14 06:43:01 -03:00
f - > fmt . pix . field = dev - > field ;
2014-04-23 07:52:07 -03:00
f - > fmt . pix . pixelformat = dev - > fmt - > fourcc ;
2008-01-10 04:25:59 -03:00
f - > fmt . pix . bytesperline =
2014-04-23 07:52:07 -03:00
( f - > fmt . pix . width * dev - > fmt - > depth ) > > 3 ;
2008-01-10 04:25:59 -03:00
f - > fmt . pix . sizeimage =
f - > fmt . pix . height * f - > fmt . pix . bytesperline ;
2014-04-23 07:11:49 -03:00
f - > fmt . pix . colorspace = V4L2_COLORSPACE_SMPTE170M ;
2008-01-10 04:25:59 -03:00
return 0 ;
}
2008-05-28 12:16:41 -03:00
static int vidioc_try_fmt_vid_cap ( struct file * file , void * priv ,
2008-01-10 04:25:59 -03:00
struct v4l2_format * f )
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2008-01-10 04:25:59 -03:00
struct cx23885_fmt * fmt ;
enum v4l2_field field ;
unsigned int maxw , maxh ;
fmt = format_by_fourcc ( f - > fmt . pix . pixelformat ) ;
if ( NULL = = fmt )
return - EINVAL ;
field = f - > fmt . pix . field ;
2015-11-30 09:59:18 -02:00
maxw = 720 ;
2008-01-10 04:25:59 -03:00
maxh = norm_maxh ( dev - > tvnorm ) ;
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 :
2014-08-09 18:04:41 -03:00
case V4L2_FIELD_SEQ_TB :
case V4L2_FIELD_SEQ_BT :
2008-01-10 04:25:59 -03:00
break ;
default :
2014-04-23 07:18:12 -03:00
field = V4L2_FIELD_INTERLACED ;
break ;
2008-01-10 04:25:59 -03:00
}
f - > fmt . pix . field = field ;
2009-05-30 21:45:46 -03:00
v4l_bound_align_image ( & f - > fmt . pix . width , 48 , maxw , 2 ,
& f - > fmt . pix . height , 32 , maxh , 0 , 0 ) ;
2008-01-10 04:25:59 -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 ;
2014-04-23 07:11:49 -03:00
f - > fmt . pix . colorspace = V4L2_COLORSPACE_SMPTE170M ;
2008-01-10 04:25:59 -03:00
return 0 ;
}
2008-05-28 12:16:41 -03:00
static int vidioc_s_fmt_vid_cap ( struct file * file , void * priv ,
2008-01-10 04:25:59 -03:00
struct v4l2_format * f )
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2015-04-09 04:05:59 -03:00
struct v4l2_subdev_format format = {
. which = V4L2_SUBDEV_FORMAT_ACTIVE ,
} ;
2008-01-10 04:25:59 -03:00
int err ;
2008-04-08 23:20:00 -03:00
dprintk ( 2 , " %s() \n " , __func__ ) ;
2008-05-28 12:16:41 -03:00
err = vidioc_try_fmt_vid_cap ( file , priv , f ) ;
2008-01-10 04:25:59 -03:00
if ( 0 ! = err )
return err ;
2014-08-14 06:43:36 -03:00
if ( vb2_is_busy ( & dev - > vb2_vidq ) | | vb2_is_busy ( & dev - > vb2_vbiq ) | |
vb2_is_busy ( & dev - > vb2_mpegq ) )
return - EBUSY ;
2014-04-23 07:52:07 -03:00
dev - > fmt = format_by_fourcc ( f - > fmt . pix . pixelformat ) ;
dev - > width = f - > fmt . pix . width ;
dev - > height = f - > fmt . pix . height ;
2014-08-14 06:43:01 -03:00
dev - > field = f - > fmt . pix . field ;
2008-04-08 23:20:00 -03:00
dprintk ( 2 , " %s() width=%d height=%d field=%d \n " , __func__ ,
2014-08-14 06:43:01 -03:00
dev - > width , dev - > height , dev - > field ) ;
2015-04-09 04:05:59 -03:00
v4l2_fill_mbus_format ( & format . format , & f - > fmt . pix , MEDIA_BUS_FMT_FIXED ) ;
call_all ( dev , pad , set_fmt , NULL , & format ) ;
v4l2_fill_pix_format ( & f - > fmt . pix , & format . format ) ;
/* set_fmt overwrites f->fmt.pix.field, restore it */
2014-08-09 18:04:41 -03:00
f - > fmt . pix . field = dev - > field ;
2008-01-10 04:25:59 -03:00
return 0 ;
}
static int vidioc_querycap ( struct file * file , void * priv ,
struct v4l2_capability * cap )
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2014-04-23 04:50:14 -03:00
struct video_device * vdev = video_devdata ( file ) ;
2008-01-10 04:25:59 -03:00
strcpy ( cap - > driver , " cx23885 " ) ;
strlcpy ( cap - > card , cx23885_boards [ dev - > board ] . name ,
sizeof ( cap - > card ) ) ;
sprintf ( cap - > bus_info , " PCIe:%s " , pci_name ( dev - > pci ) ) ;
2014-04-23 05:24:58 -03:00
cap - > device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_AUDIO ;
2014-06-27 11:15:41 -03:00
if ( dev - > tuner_type ! = TUNER_ABSENT )
2014-04-23 04:50:14 -03:00
cap - > device_caps | = V4L2_CAP_TUNER ;
if ( vdev - > vfl_type = = VFL_TYPE_VBI )
cap - > device_caps | = V4L2_CAP_VBI_CAPTURE ;
else
cap - > device_caps | = V4L2_CAP_VIDEO_CAPTURE ;
cap - > capabilities = cap - > device_caps | V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_DEVICE_CAPS ;
2008-01-10 04:25:59 -03:00
return 0 ;
}
2008-05-28 12:16:41 -03:00
static int vidioc_enum_fmt_vid_cap ( struct file * file , void * priv ,
2008-01-10 04:25:59 -03:00
struct v4l2_fmtdesc * f )
{
if ( unlikely ( f - > index > = ARRAY_SIZE ( formats ) ) )
return - EINVAL ;
strlcpy ( f - > description , formats [ f - > index ] . name ,
sizeof ( f - > description ) ) ;
f - > pixelformat = formats [ f - > index ] . fourcc ;
return 0 ;
}
2015-11-30 09:59:18 -02:00
static int vidioc_cropcap ( struct file * file , void * priv ,
struct v4l2_cropcap * cc )
{
struct cx23885_dev * dev = video_drvdata ( file ) ;
bool is_50hz = dev - > tvnorm & V4L2_STD_625_50 ;
if ( cc - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE )
return - EINVAL ;
cc - > bounds . left = 0 ;
cc - > bounds . top = 0 ;
cc - > bounds . width = 720 ;
cc - > bounds . height = norm_maxh ( dev - > tvnorm ) ;
cc - > defrect = cc - > bounds ;
cc - > pixelaspect . numerator = is_50hz ? 54 : 11 ;
cc - > pixelaspect . denominator = is_50hz ? 59 : 10 ;
return 0 ;
}
2012-01-04 21:08:35 -03:00
static int vidioc_g_std ( struct file * file , void * priv , v4l2_std_id * id )
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2012-01-04 21:08:35 -03:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2013-06-03 05:36:46 -03:00
* id = dev - > tvnorm ;
2012-01-04 21:08:35 -03:00
return 0 ;
}
2013-03-15 06:10:40 -03:00
static int vidioc_s_std ( struct file * file , void * priv , v4l2_std_id tvnorms )
2008-01-10 04:25:59 -03:00
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2008-04-08 23:20:00 -03:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2008-01-10 04:25:59 -03:00
2014-08-14 06:43:36 -03:00
return cx23885_set_tvnorm ( dev , tvnorms ) ;
2008-01-10 04:25:59 -03:00
}
2012-01-04 21:08:35 -03:00
int cx23885_enum_input ( struct cx23885_dev * dev , struct v4l2_input * i )
2008-01-10 04:25:59 -03:00
{
static const char * iname [ ] = {
[ CX23885_VMUX_COMPOSITE1 ] = " Composite1 " ,
[ CX23885_VMUX_COMPOSITE2 ] = " Composite2 " ,
[ CX23885_VMUX_COMPOSITE3 ] = " Composite3 " ,
[ CX23885_VMUX_COMPOSITE4 ] = " Composite4 " ,
[ CX23885_VMUX_SVIDEO ] = " S-Video " ,
2009-10-21 11:07:24 -03:00
[ CX23885_VMUX_COMPONENT ] = " Component " ,
2008-01-10 04:25:59 -03:00
[ CX23885_VMUX_TELEVISION ] = " Television " ,
[ CX23885_VMUX_CABLE ] = " Cable TV " ,
[ CX23885_VMUX_DVB ] = " DVB " ,
[ CX23885_VMUX_DEBUG ] = " for debug only " ,
} ;
unsigned int n ;
2008-04-08 23:20:00 -03:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2008-01-10 04:25:59 -03:00
n = i - > index ;
2011-10-10 11:09:55 -03:00
if ( n > = MAX_CX23885_INPUT )
2008-01-10 04:25:59 -03:00
return - EINVAL ;
if ( 0 = = INPUT ( n ) - > type )
return - EINVAL ;
i - > index = n ;
i - > type = V4L2_INPUT_TYPE_CAMERA ;
strcpy ( i - > name , iname [ INPUT ( n ) - > type ] ) ;
2014-04-23 05:24:58 -03:00
i - > std = CX23885_NORMS ;
2008-01-10 04:25:59 -03:00
if ( ( CX23885_VMUX_TELEVISION = = INPUT ( n ) - > type ) | |
2010-08-05 17:22:44 -03:00
( CX23885_VMUX_CABLE = = INPUT ( n ) - > type ) ) {
2008-01-10 04:25:59 -03:00
i - > type = V4L2_INPUT_TYPE_TUNER ;
2014-04-23 05:24:58 -03:00
i - > audioset = 4 ;
} else {
/* Two selectable audio inputs for non-tv inputs */
i - > audioset = 3 ;
2010-08-05 17:22:44 -03:00
}
2011-10-10 11:09:56 -03:00
2012-01-06 11:55:32 -03:00
if ( dev - > input = = n ) {
/* enum'd input matches our configured input.
* Ask the video decoder to process the call
* and give it an oppertunity to update the
* status field .
*/
call_all ( dev , video , g_input_status , & i - > status ) ;
}
2008-01-10 04:25:59 -03:00
return 0 ;
}
static int vidioc_enum_input ( struct file * file , void * priv ,
struct v4l2_input * i )
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2008-04-08 23:20:00 -03:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2008-01-10 04:25:59 -03:00
return cx23885_enum_input ( dev , i ) ;
}
2012-01-04 21:08:35 -03:00
int cx23885_get_input ( struct file * file , void * priv , unsigned int * i )
2008-01-10 04:25:59 -03:00
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2008-01-10 04:25:59 -03:00
* i = dev - > input ;
2008-04-08 23:20:00 -03:00
dprintk ( 1 , " %s() returns %d \n " , __func__ , * i ) ;
2008-01-10 04:25:59 -03:00
return 0 ;
}
2012-01-04 21:08:35 -03:00
static int vidioc_g_input ( struct file * file , void * priv , unsigned int * i )
{
return cx23885_get_input ( file , priv , i ) ;
}
int cx23885_set_input ( struct file * file , void * priv , unsigned int i )
2008-01-10 04:25:59 -03:00
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2008-01-10 04:25:59 -03:00
2008-04-08 23:20:00 -03:00
dprintk ( 1 , " %s(%d) \n " , __func__ , i ) ;
2008-01-10 04:25:59 -03:00
2011-10-10 11:09:55 -03:00
if ( i > = MAX_CX23885_INPUT ) {
2008-04-08 23:20:00 -03:00
dprintk ( 1 , " %s() -EINVAL \n " , __func__ ) ;
2008-01-10 04:25:59 -03:00
return - EINVAL ;
}
2011-10-10 11:09:55 -03:00
if ( INPUT ( i ) - > type = = 0 )
return - EINVAL ;
2008-01-10 04:25:59 -03:00
cx23885_video_mux ( dev , i ) ;
2011-10-10 11:09:56 -03:00
/* By default establish the default audio input for the card also */
/* Caller is free to use VIDIOC_S_AUDIO to override afterwards */
cx23885_audio_mux ( dev , i ) ;
2008-01-10 04:25:59 -03:00
return 0 ;
}
2012-01-04 21:08:35 -03:00
static int vidioc_s_input ( struct file * file , void * priv , unsigned int i )
{
return cx23885_set_input ( file , priv , i ) ;
}
2010-07-18 18:18:06 -03:00
static int vidioc_log_status ( struct file * file , void * priv )
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2010-07-18 18:18:06 -03:00
call_all ( dev , core , log_status ) ;
return 0 ;
}
2011-10-10 11:09:56 -03:00
static int cx23885_query_audinput ( struct file * file , void * priv ,
struct v4l2_audio * i )
{
static const char * iname [ ] = {
[ 0 ] = " Baseband L/R 1 " ,
[ 1 ] = " Baseband L/R 2 " ,
2014-04-23 05:24:58 -03:00
[ 2 ] = " TV " ,
2011-10-10 11:09:56 -03:00
} ;
unsigned int n ;
dprintk ( 1 , " %s() \n " , __func__ ) ;
n = i - > index ;
2014-04-23 05:24:58 -03:00
if ( n > = 3 )
2011-10-10 11:09:56 -03:00
return - EINVAL ;
memset ( i , 0 , sizeof ( * i ) ) ;
i - > index = n ;
strcpy ( i - > name , iname [ n ] ) ;
2014-04-23 05:24:58 -03:00
i - > capability = V4L2_AUDCAP_STEREO ;
2011-10-10 11:09:56 -03:00
return 0 ;
}
static int vidioc_enum_audinput ( struct file * file , void * priv ,
struct v4l2_audio * i )
{
return cx23885_query_audinput ( file , priv , i ) ;
}
static int vidioc_g_audinput ( struct file * file , void * priv ,
struct v4l2_audio * i )
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2011-10-10 11:09:56 -03:00
2014-04-23 05:24:58 -03:00
if ( ( CX23885_VMUX_TELEVISION = = INPUT ( dev - > input ) - > type ) | |
( CX23885_VMUX_CABLE = = INPUT ( dev - > input ) - > type ) )
i - > index = 2 ;
else
i - > index = dev - > audinput ;
2011-10-10 11:09:56 -03:00
dprintk ( 1 , " %s(input=%d) \n " , __func__ , i - > index ) ;
return cx23885_query_audinput ( file , priv , i ) ;
}
static int vidioc_s_audinput ( struct file * file , void * priv ,
2012-09-04 11:59:31 -03:00
const struct v4l2_audio * i )
2011-10-10 11:09:56 -03:00
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2014-04-23 05:24:58 -03:00
if ( ( CX23885_VMUX_TELEVISION = = INPUT ( dev - > input ) - > type ) | |
( CX23885_VMUX_CABLE = = INPUT ( dev - > input ) - > type ) ) {
return i - > index ! = 2 ? - EINVAL : 0 ;
}
if ( i - > index > 1 )
2011-10-10 11:09:56 -03:00
return - EINVAL ;
dprintk ( 1 , " %s(%d) \n " , __func__ , i - > index ) ;
dev - > audinput = i - > index ;
2011-10-10 11:09:56 -03:00
/* Skip the audio defaults from the cards struct, caller wants
* directly touch the audio mux hardware . */
cx23885_flatiron_mux ( dev , dev - > audinput + 1 ) ;
2011-10-10 11:09:56 -03:00
return 0 ;
}
2008-01-10 04:25:59 -03:00
static int vidioc_g_tuner ( struct file * file , void * priv ,
struct v4l2_tuner * t )
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2008-01-10 04:25:59 -03:00
2014-06-27 11:15:41 -03:00
if ( dev - > tuner_type = = TUNER_ABSENT )
2008-01-10 04:25:59 -03:00
return - EINVAL ;
if ( 0 ! = t - > index )
return - EINVAL ;
strcpy ( t - > name , " Television " ) ;
2011-10-10 11:09:53 -03:00
2011-10-10 11:09:53 -03:00
call_all ( dev , tuner , g_tuner , t ) ;
2008-01-10 04:25:59 -03:00
return 0 ;
}
static int vidioc_s_tuner ( struct file * file , void * priv ,
2013-03-15 06:10:06 -03:00
const struct v4l2_tuner * t )
2008-01-10 04:25:59 -03:00
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2008-01-10 04:25:59 -03:00
2014-06-27 11:15:41 -03:00
if ( dev - > tuner_type = = TUNER_ABSENT )
2008-01-10 04:25:59 -03:00
return - EINVAL ;
if ( 0 ! = t - > index )
return - EINVAL ;
2011-10-10 11:09:53 -03:00
/* Update the A/V core */
2011-10-10 11:09:53 -03:00
call_all ( dev , tuner , s_tuner , t ) ;
2011-10-10 11:09:53 -03:00
2008-01-10 04:25:59 -03:00
return 0 ;
}
static int vidioc_g_frequency ( struct file * file , void * priv ,
struct v4l2_frequency * f )
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2008-01-10 04:25:59 -03:00
2014-06-27 11:15:41 -03:00
if ( dev - > tuner_type = = TUNER_ABSENT )
2008-01-10 04:25:59 -03:00
return - EINVAL ;
2014-04-23 07:22:06 -03:00
f - > type = V4L2_TUNER_ANALOG_TV ;
2008-01-10 04:25:59 -03:00
f - > frequency = dev - > freq ;
2009-03-29 06:53:29 -03:00
call_all ( dev , tuner , g_frequency , f ) ;
2008-01-10 04:25:59 -03:00
return 0 ;
}
2013-03-19 04:09:26 -03:00
static int cx23885_set_freq ( struct cx23885_dev * dev , const struct v4l2_frequency * f )
2008-01-10 04:25:59 -03:00
{
2014-04-23 06:34:44 -03:00
struct v4l2_ctrl * mute ;
int old_mute_val = 1 ;
2012-01-04 21:08:35 -03:00
2014-06-27 11:15:41 -03:00
if ( dev - > tuner_type = = TUNER_ABSENT )
2008-01-10 04:25:59 -03:00
return - EINVAL ;
if ( unlikely ( f - > tuner ! = 0 ) )
return - EINVAL ;
dev - > freq = f - > frequency ;
2012-01-04 21:08:35 -03:00
/* I need to mute audio here */
2014-04-23 06:34:44 -03:00
mute = v4l2_ctrl_find ( & dev - > ctrl_handler , V4L2_CID_AUDIO_MUTE ) ;
if ( mute ) {
old_mute_val = v4l2_ctrl_g_ctrl ( mute ) ;
if ( ! old_mute_val )
v4l2_ctrl_s_ctrl ( mute , 1 ) ;
}
2012-01-04 21:08:35 -03:00
2009-03-29 06:53:29 -03:00
call_all ( dev , tuner , s_frequency , f ) ;
2008-01-10 04:25:59 -03:00
/* When changing channels it is required to reset TVAUDIO */
2012-01-04 21:08:35 -03:00
msleep ( 100 ) ;
/* I need to unmute audio here */
2014-04-23 06:34:44 -03:00
if ( old_mute_val = = 0 )
v4l2_ctrl_s_ctrl ( mute , old_mute_val ) ;
2008-01-10 04:25:59 -03:00
return 0 ;
}
2012-01-04 21:08:35 -03:00
static int cx23885_set_freq_via_ops ( struct cx23885_dev * dev ,
2013-03-19 04:09:26 -03:00
const struct v4l2_frequency * f )
2012-01-04 21:08:35 -03:00
{
2014-04-23 06:34:44 -03:00
struct v4l2_ctrl * mute ;
int old_mute_val = 1 ;
2014-08-14 06:43:01 -03:00
struct vb2_dvb_frontend * vfe ;
2012-01-04 21:08:35 -03:00
struct dvb_frontend * fe ;
struct analog_parameters params = {
. mode = V4L2_TUNER_ANALOG_TV ,
. audmode = V4L2_TUNER_MODE_STEREO ,
. std = dev - > tvnorm ,
. frequency = f - > frequency
} ;
dev - > freq = f - > frequency ;
/* I need to mute audio here */
2014-04-23 06:34:44 -03:00
mute = v4l2_ctrl_find ( & dev - > ctrl_handler , V4L2_CID_AUDIO_MUTE ) ;
if ( mute ) {
old_mute_val = v4l2_ctrl_g_ctrl ( mute ) ;
if ( ! old_mute_val )
v4l2_ctrl_s_ctrl ( mute , 1 ) ;
}
2012-01-04 21:08:35 -03:00
/* If HVR1850 */
dprintk ( 1 , " %s() frequency=%d tuner=%d std=0x%llx \n " , __func__ ,
params . frequency , f - > tuner , params . std ) ;
2014-08-14 06:43:01 -03:00
vfe = vb2_dvb_get_frontend ( & dev - > ts2 . frontends , 1 ) ;
2012-01-10 05:04:39 -03:00
if ( ! vfe ) {
return - EINVAL ;
}
2012-01-04 21:08:35 -03:00
fe = vfe - > dvb . frontend ;
2012-07-01 16:15:14 -03:00
if ( ( dev - > board = = CX23885_BOARD_HAUPPAUGE_HVR1850 ) | |
( dev - > board = = CX23885_BOARD_HAUPPAUGE_HVR1255 ) | |
( dev - > board = = CX23885_BOARD_HAUPPAUGE_HVR1255_22111 ) )
2012-01-04 21:08:35 -03:00
fe = & dev - > ts1 . analog_fe ;
if ( fe & & fe - > ops . tuner_ops . set_analog_params ) {
2014-04-28 16:53:01 -03:00
call_all ( dev , video , s_std , dev - > tvnorm ) ;
2012-01-04 21:08:35 -03:00
fe - > ops . tuner_ops . set_analog_params ( fe , & params ) ;
}
else
2016-11-13 09:46:11 -02:00
pr_err ( " %s() No analog tuner, aborting \n " , __func__ ) ;
2012-01-04 21:08:35 -03:00
/* When changing channels it is required to reset TVAUDIO */
msleep ( 100 ) ;
/* I need to unmute audio here */
2014-04-23 06:34:44 -03:00
if ( old_mute_val = = 0 )
v4l2_ctrl_s_ctrl ( mute , old_mute_val ) ;
2012-01-04 21:08:35 -03:00
return 0 ;
}
int cx23885_set_frequency ( struct file * file , void * priv ,
2013-03-19 04:09:26 -03:00
const struct v4l2_frequency * f )
2008-01-10 04:25:59 -03:00
{
2014-04-23 08:43:51 -03:00
struct cx23885_dev * dev = video_drvdata ( file ) ;
2012-01-04 21:08:35 -03:00
int ret ;
2008-01-10 04:25:59 -03:00
2012-01-04 21:08:35 -03:00
switch ( dev - > board ) {
2012-07-01 16:15:14 -03:00
case CX23885_BOARD_HAUPPAUGE_HVR1255 :
case CX23885_BOARD_HAUPPAUGE_HVR1255_22111 :
2012-01-04 21:08:35 -03:00
case CX23885_BOARD_HAUPPAUGE_HVR1850 :
ret = cx23885_set_freq_via_ops ( dev , f ) ;
break ;
default :
ret = cx23885_set_freq ( dev , f ) ;
}
2008-01-10 04:25:59 -03:00
2012-01-04 21:08:35 -03:00
return ret ;
}
static int vidioc_s_frequency ( struct file * file , void * priv ,
2013-03-19 04:09:26 -03:00
const struct v4l2_frequency * f )
2012-01-04 21:08:35 -03:00
{
return cx23885_set_frequency ( file , priv , f ) ;
2008-01-10 04:25:59 -03:00
}
/* ----------------------------------------------------------- */
int cx23885_video_irq ( struct cx23885_dev * dev , u32 status )
{
u32 mask , count ;
int handled = 0 ;
mask = cx_read ( VID_A_INT_MSK ) ;
if ( 0 = = ( status & mask ) )
return handled ;
2011-10-10 11:09:54 -03:00
2008-01-10 04:25:59 -03:00
cx_write ( VID_A_INT_STAT , status ) ;
2011-10-10 11:09:56 -03:00
/* risc op code error, fifo overflow or line sync detection error */
2011-10-10 11:09:54 -03:00
if ( ( status & VID_BC_MSK_OPC_ERR ) | |
( status & VID_BC_MSK_SYNC ) | |
( status & VID_BC_MSK_OF ) ) {
2011-10-10 11:09:56 -03:00
if ( status & VID_BC_MSK_OPC_ERR ) {
2011-10-10 11:09:54 -03:00
dprintk ( 7 , " (VID_BC_MSK_OPC_ERR 0x%08x) \n " ,
VID_BC_MSK_OPC_ERR ) ;
2016-11-13 09:46:11 -02:00
pr_warn ( " %s: video risc op code error \n " ,
2011-10-10 11:09:56 -03:00
dev - > name ) ;
cx23885_sram_channel_dump ( dev ,
& dev - > sram_channels [ SRAM_CH01 ] ) ;
}
2011-10-10 11:09:54 -03:00
if ( status & VID_BC_MSK_SYNC )
[media] cx23885: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 17:44:03 -02:00
dprintk ( 7 , " (VID_BC_MSK_SYNC 0x%08x) video lines miss-match \n " ,
2011-10-10 11:09:54 -03:00
VID_BC_MSK_SYNC ) ;
if ( status & VID_BC_MSK_OF )
2011-10-10 11:09:56 -03:00
dprintk ( 7 , " (VID_BC_MSK_OF 0x%08x) fifo overflow \n " ,
2011-10-10 11:09:54 -03:00
VID_BC_MSK_OF ) ;
2008-01-10 04:25:59 -03:00
}
2011-10-10 11:09:54 -03:00
/* Video */
if ( status & VID_BC_MSK_RISCI1 ) {
2008-01-10 04:25:59 -03:00
spin_lock ( & dev - > slock ) ;
count = cx_read ( VID_A_GPCNT ) ;
cx23885_video_wakeup ( dev , & dev - > vidq , count ) ;
spin_unlock ( & dev - > slock ) ;
handled + + ;
}
2011-10-10 11:09:54 -03:00
/* Allow the VBI framework to process it's payload */
handled + = cx23885_vbi_irq ( dev , status ) ;
2008-01-10 04:25:59 -03:00
return handled ;
}
/* ----------------------------------------------------------- */
/* exported stuff */
2008-12-30 06:58:20 -03:00
static const struct v4l2_file_operations video_fops = {
2008-01-10 04:25:59 -03:00
. owner = THIS_MODULE ,
2014-08-14 06:43:01 -03:00
. open = v4l2_fh_open ,
. release = vb2_fop_release ,
. read = vb2_fop_read ,
. poll = vb2_fop_poll ,
2014-08-09 11:29:55 -03:00
. unlocked_ioctl = video_ioctl2 ,
2014-08-14 06:43:01 -03:00
. mmap = vb2_fop_mmap ,
2008-01-10 04:25:59 -03:00
} ;
2008-07-21 02:57:38 -03:00
static const struct v4l2_ioctl_ops video_ioctl_ops = {
2008-01-10 04:25:59 -03:00
. vidioc_querycap = vidioc_querycap ,
2008-05-28 12:16:41 -03:00
. vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap ,
. vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap ,
. vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap ,
. vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap ,
. vidioc_g_fmt_vbi_cap = cx23885_vbi_fmt ,
. vidioc_try_fmt_vbi_cap = cx23885_vbi_fmt ,
. vidioc_s_fmt_vbi_cap = cx23885_vbi_fmt ,
2014-08-14 06:43:01 -03:00
. vidioc_reqbufs = vb2_ioctl_reqbufs ,
. vidioc_prepare_buf = vb2_ioctl_prepare_buf ,
. vidioc_querybuf = vb2_ioctl_querybuf ,
. vidioc_qbuf = vb2_ioctl_qbuf ,
. vidioc_dqbuf = vb2_ioctl_dqbuf ,
. vidioc_streamon = vb2_ioctl_streamon ,
. vidioc_streamoff = vb2_ioctl_streamoff ,
2015-11-30 09:59:18 -02:00
. vidioc_cropcap = vidioc_cropcap ,
2008-01-10 04:25:59 -03:00
. vidioc_s_std = vidioc_s_std ,
2012-01-04 21:08:35 -03:00
. vidioc_g_std = vidioc_g_std ,
2008-01-10 04:25:59 -03:00
. vidioc_enum_input = vidioc_enum_input ,
. vidioc_g_input = vidioc_g_input ,
. vidioc_s_input = vidioc_s_input ,
2010-07-18 18:18:06 -03:00
. vidioc_log_status = vidioc_log_status ,
2008-01-10 04:25:59 -03:00
. vidioc_g_tuner = vidioc_g_tuner ,
. vidioc_s_tuner = vidioc_s_tuner ,
. vidioc_g_frequency = vidioc_g_frequency ,
. vidioc_s_frequency = vidioc_s_frequency ,
# ifdef CONFIG_VIDEO_ADV_DEBUG
2013-05-29 06:59:39 -03:00
. vidioc_g_chip_info = cx23885_g_chip_info ,
2009-09-26 22:50:44 -03:00
. vidioc_g_register = cx23885_g_register ,
. vidioc_s_register = cx23885_s_register ,
2008-01-10 04:25:59 -03:00
# endif
2011-10-10 11:09:56 -03:00
. vidioc_enumaudio = vidioc_enum_audinput ,
. vidioc_g_audio = vidioc_g_audinput ,
. vidioc_s_audio = vidioc_s_audinput ,
2014-04-23 06:34:44 -03:00
. vidioc_subscribe_event = v4l2_ctrl_subscribe_event ,
. vidioc_unsubscribe_event = v4l2_event_unsubscribe ,
2008-07-21 02:57:38 -03:00
} ;
static struct video_device cx23885_vbi_template ;
static struct video_device cx23885_video_template = {
. name = " cx23885-video " ,
. fops = & video_fops ,
. ioctl_ops = & video_ioctl_ops ,
2008-01-10 04:25:59 -03:00
. tvnorms = CX23885_NORMS ,
} ;
void cx23885_video_unregister ( struct cx23885_dev * dev )
{
2008-04-08 23:20:00 -03:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2010-07-19 01:19:43 -03:00
cx23885_irq_remove ( dev , 0x01 ) ;
2008-01-10 04:25:59 -03:00
2011-10-10 11:09:54 -03:00
if ( dev - > vbi_dev ) {
if ( video_is_registered ( dev - > vbi_dev ) )
video_unregister_device ( dev - > vbi_dev ) ;
else
video_device_release ( dev - > vbi_dev ) ;
dev - > vbi_dev = NULL ;
}
2008-01-10 04:25:59 -03:00
if ( dev - > video_dev ) {
2009-11-27 13:57:30 -03:00
if ( video_is_registered ( dev - > video_dev ) )
2008-01-10 04:25:59 -03:00
video_unregister_device ( dev - > video_dev ) ;
else
video_device_release ( dev - > video_dev ) ;
dev - > video_dev = NULL ;
}
2011-10-10 11:09:53 -03:00
if ( dev - > audio_dev )
2011-10-10 11:09:53 -03:00
cx23885_audio_unregister ( dev ) ;
2008-01-10 04:25:59 -03:00
}
int cx23885_video_register ( struct cx23885_dev * dev )
{
2014-08-14 06:43:01 -03:00
struct vb2_queue * q ;
2008-01-10 04:25:59 -03:00
int err ;
2008-04-08 23:20:00 -03:00
dprintk ( 1 , " %s() \n " , __func__ ) ;
2008-01-10 04:25:59 -03:00
/* Initialize VBI template */
2012-10-23 15:57:20 -03:00
cx23885_vbi_template = cx23885_video_template ;
2008-01-10 04:25:59 -03:00
strcpy ( cx23885_vbi_template . name , " cx23885-vbi " ) ;
2013-06-03 05:36:46 -03:00
dev - > tvnorm = V4L2_STD_NTSC_M ;
2014-04-23 07:52:07 -03:00
dev - > fmt = format_by_fourcc ( V4L2_PIX_FMT_YUYV ) ;
2014-08-09 18:04:41 -03:00
dev - > field = V4L2_FIELD_INTERLACED ;
2014-09-20 10:19:33 -03:00
dev - > width = 720 ;
2014-04-23 07:52:07 -03:00
dev - > height = norm_maxh ( dev - > tvnorm ) ;
2008-01-10 04:25:59 -03:00
/* init video dma queues */
INIT_LIST_HEAD ( & dev - > vidq . active ) ;
2011-10-10 11:09:54 -03:00
/* init vbi dma queues */
INIT_LIST_HEAD ( & dev - > vbiq . active ) ;
2010-07-19 01:19:43 -03:00
cx23885_irq_add_enable ( dev , 0x01 ) ;
2008-01-10 04:25:59 -03:00
2011-01-25 17:05:00 -03:00
if ( ( TUNER_ABSENT ! = dev - > tuner_type ) & &
( ( dev - > tuner_bus = = 0 ) | | ( dev - > tuner_bus = = 1 ) ) ) {
2009-03-29 06:53:29 -03:00
struct v4l2_subdev * sd = NULL ;
if ( dev - > tuner_addr )
2009-04-01 03:57:53 -03:00
sd = v4l2_i2c_new_subdev ( & dev - > v4l2_dev ,
2011-01-25 17:05:00 -03:00
& dev - > i2c_bus [ dev - > tuner_bus ] . i2c_adap ,
2010-09-24 10:16:44 -03:00
" tuner " , dev - > tuner_addr , NULL ) ;
2009-03-29 06:53:29 -03:00
else
2009-08-10 02:49:08 -03:00
sd = v4l2_i2c_new_subdev ( & dev - > v4l2_dev ,
2011-01-25 17:05:00 -03:00
& dev - > i2c_bus [ dev - > tuner_bus ] . i2c_adap ,
2010-09-24 07:58:29 -03:00
" tuner " , 0 , v4l2_i2c_tuner_addrs ( ADDRS_TV ) ) ;
2009-03-29 06:53:29 -03:00
if ( sd ) {
struct tuner_setup tun_setup ;
2009-10-21 11:08:30 -03:00
memset ( & tun_setup , 0 , sizeof ( tun_setup ) ) ;
2009-03-29 06:53:29 -03:00
tun_setup . mode_mask = T_ANALOG_TV ;
tun_setup . type = dev - > tuner_type ;
tun_setup . addr = v4l2_i2c_subdev_addr ( sd ) ;
2009-10-21 13:15:30 -03:00
tun_setup . tuner_callback = cx23885_tuner_callback ;
2009-03-29 06:53:29 -03:00
v4l2_subdev_call ( sd , tuner , s_type_addr , & tun_setup ) ;
2010-01-22 04:55:28 -03:00
2013-09-13 11:28:12 -03:00
if ( ( dev - > board = = CX23885_BOARD_LEADTEK_WINFAST_PXTV1200 ) | |
( dev - > board = = CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200 ) ) {
2010-01-22 04:55:28 -03:00
struct xc2028_ctrl ctrl = {
. fname = XC2028_DEFAULT_FIRMWARE ,
. max_len = 64
} ;
struct v4l2_priv_tun_config cfg = {
. tuner = dev - > tuner_type ,
. priv = & ctrl
} ;
v4l2_subdev_call ( sd , tuner , s_config , & cfg ) ;
}
2012-12-08 18:20:59 -03:00
if ( dev - > board = = CX23885_BOARD_AVERMEDIA_HC81R ) {
struct xc2028_ctrl ctrl = {
. fname = " xc3028L-v36.fw " ,
. max_len = 64
} ;
struct v4l2_priv_tun_config cfg = {
. tuner = dev - > tuner_type ,
. priv = & ctrl
} ;
v4l2_subdev_call ( sd , tuner , s_config , & cfg ) ;
}
2009-03-29 06:53:29 -03:00
}
}
2014-08-09 11:29:55 -03:00
/* initial device configuration */
mutex_lock ( & dev - > lock ) ;
cx23885_set_tvnorm ( dev , dev - > tvnorm ) ;
cx23885_video_mux ( dev , 0 ) ;
cx23885_audio_mux ( dev , 0 ) ;
mutex_unlock ( & dev - > lock ) ;
2014-08-14 06:43:01 -03:00
q = & dev - > vb2_vidq ;
q - > type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
q - > io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ ;
q - > gfp_flags = GFP_DMA32 ;
q - > min_buffers_needed = 2 ;
q - > drv_priv = dev ;
q - > buf_struct_size = sizeof ( struct cx23885_buffer ) ;
q - > ops = & cx23885_video_qops ;
q - > mem_ops = & vb2_dma_sg_memops ;
q - > timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC ;
q - > lock = & dev - > lock ;
2016-02-15 12:37:15 -02:00
q - > dev = & dev - > pci - > dev ;
2014-08-14 06:43:01 -03:00
err = vb2_queue_init ( q ) ;
if ( err < 0 )
goto fail_unreg ;
q = & dev - > vb2_vbiq ;
q - > type = V4L2_BUF_TYPE_VBI_CAPTURE ;
q - > io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ ;
q - > gfp_flags = GFP_DMA32 ;
q - > min_buffers_needed = 2 ;
q - > drv_priv = dev ;
q - > buf_struct_size = sizeof ( struct cx23885_buffer ) ;
q - > ops = & cx23885_vbi_qops ;
q - > mem_ops = & vb2_dma_sg_memops ;
q - > timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC ;
q - > lock = & dev - > lock ;
2016-02-15 12:37:15 -02:00
q - > dev = & dev - > pci - > dev ;
2014-08-14 06:43:01 -03:00
err = vb2_queue_init ( q ) ;
if ( err < 0 )
goto fail_unreg ;
2011-10-10 11:09:54 -03:00
/* register Video device */
2008-01-10 04:25:59 -03:00
dev - > video_dev = cx23885_vdev_init ( dev , dev - > pci ,
& cx23885_video_template , " video " ) ;
2014-08-14 06:43:01 -03:00
dev - > video_dev - > queue = & dev - > vb2_vidq ;
2008-01-10 04:25:59 -03:00
err = video_register_device ( dev - > video_dev , VFL_TYPE_GRABBER ,
video_nr [ dev - > nr ] ) ;
if ( err < 0 ) {
2016-11-13 09:46:11 -02:00
pr_info ( " %s: can't register video device \n " ,
2008-01-10 04:25:59 -03:00
dev - > name ) ;
goto fail_unreg ;
}
2016-11-13 09:46:11 -02:00
pr_info ( " %s: registered device %s [v4l2] \n " ,
2009-11-27 13:57:15 -03:00
dev - > name , video_device_node_name ( dev - > video_dev ) ) ;
2011-10-10 11:09:53 -03:00
2011-10-10 11:09:54 -03:00
/* register VBI device */
dev - > vbi_dev = cx23885_vdev_init ( dev , dev - > pci ,
& cx23885_vbi_template , " vbi " ) ;
2014-08-14 06:43:01 -03:00
dev - > vbi_dev - > queue = & dev - > vb2_vbiq ;
2011-10-10 11:09:54 -03:00
err = video_register_device ( dev - > vbi_dev , VFL_TYPE_VBI ,
vbi_nr [ dev - > nr ] ) ;
if ( err < 0 ) {
2016-11-13 09:46:11 -02:00
pr_info ( " %s: can't register vbi device \n " ,
2011-10-10 11:09:54 -03:00
dev - > name ) ;
goto fail_unreg ;
}
2016-11-13 09:46:11 -02:00
pr_info ( " %s: registered device %s \n " ,
2011-10-10 11:09:54 -03:00
dev - > name , video_device_node_name ( dev - > vbi_dev ) ) ;
2011-10-10 11:09:53 -03:00
/* Register ALSA audio device */
2011-10-10 11:09:53 -03:00
dev - > audio_dev = cx23885_audio_register ( dev ) ;
2011-10-10 11:09:53 -03:00
2008-01-10 04:25:59 -03:00
return 0 ;
fail_unreg :
cx23885_video_unregister ( dev ) ;
return err ;
}