2009-09-14 09:42:41 -03:00
/*
2010-10-20 06:35:54 -03:00
* tm6000 . h - driver for TM5600 / TM6000 / TM6010 USB video capture devices
*
* Copyright ( C ) 2006 - 2007 Mauro Carvalho Chehab < mchehab @ infradead . org >
*
* Copyright ( C ) 2007 Michel Ludwig < michel . ludwig @ gmail . com >
* - DVB - T support
*
* 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 version 2
*
* 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 .
2009-09-14 09:42:41 -03:00
*/
# include <linux/videodev2.h>
# include <media/v4l2-common.h>
# include <media/videobuf-vmalloc.h>
# include "tm6000-usb-isoc.h"
# include <linux/i2c.h>
# include <linux/mutex.h>
2009-09-14 16:37:13 -03:00
# include <media/v4l2-device.h>
2011-08-04 04:14:01 -03:00
2007-08-21 17:37:22 -03:00
# include <linux/dvb/frontend.h>
# include "dvb_demux.h"
# include "dvb_frontend.h"
# include "dmxdev.h"
2009-09-14 09:42:41 -03:00
/* Inputs */
2007-07-19 11:09:58 -03:00
enum tm6000_itype {
2011-05-09 16:53:51 -03:00
TM6000_INPUT_TV = 1 ,
TM6000_INPUT_COMPOSITE1 ,
TM6000_INPUT_COMPOSITE2 ,
2007-07-19 11:09:58 -03:00
TM6000_INPUT_SVIDEO ,
2011-05-09 16:53:51 -03:00
TM6000_INPUT_DVB ,
TM6000_INPUT_RADIO ,
} ;
enum tm6000_mux {
TM6000_VMUX_VIDEO_A = 1 ,
TM6000_VMUX_VIDEO_B ,
TM6000_VMUX_VIDEO_AB ,
TM6000_AMUX_ADC1 ,
TM6000_AMUX_ADC2 ,
TM6000_AMUX_SIF1 ,
TM6000_AMUX_SIF2 ,
TM6000_AMUX_I2S ,
2007-07-19 11:09:58 -03:00
} ;
2008-01-08 11:19:22 -03:00
enum tm6000_devtype {
TM6000 = 0 ,
TM5600 ,
TM6010 ,
} ;
2009-09-14 09:42:41 -03:00
2011-05-09 16:53:51 -03:00
struct tm6000_input {
enum tm6000_itype type ;
enum tm6000_mux vmux ;
enum tm6000_mux amux ;
unsigned int v_gpio ;
unsigned int a_gpio ;
2011-02-17 22:11:05 -03:00
} ;
2009-09-14 09:42:41 -03:00
/* ------------------------------------------------------------------
2010-10-20 06:35:34 -03:00
* Basic structures
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2009-09-14 09:42:41 -03:00
struct tm6000_fmt {
char * name ;
u32 fourcc ; /* v4l2 format id */
int depth ;
} ;
/* buffer for one video frame */
struct tm6000_buffer {
/* common v4l buffer stuff -- must be first */
struct videobuf_buffer vb ;
struct tm6000_fmt * fmt ;
} ;
struct tm6000_dmaqueue {
struct list_head active ;
struct list_head queued ;
/* thread for generating video stream*/
struct task_struct * kthread ;
wait_queue_head_t wq ;
/* Counters to control fps rate */
int frame ;
int ini_jiffies ;
} ;
/* device states */
enum tm6000_core_state {
DEV_INITIALIZED = 0x01 ,
DEV_DISCONNECTED = 0x02 ,
DEV_MISCONFIGURED = 0x04 ,
} ;
/* io methods */
enum tm6000_io_method {
IO_NONE ,
IO_READ ,
IO_MMAP ,
} ;
enum tm6000_mode {
2010-05-29 13:52:46 -03:00
TM6000_MODE_UNKNOWN = 0 ,
2009-09-14 09:42:41 -03:00
TM6000_MODE_ANALOG ,
TM6000_MODE_DIGITAL ,
} ;
2010-03-29 13:51:10 -03:00
struct tm6000_gpio {
int tuner_reset ;
int tuner_on ;
int demod_reset ;
int demod_on ;
int power_led ;
int dvb_led ;
int ir ;
2010-04-09 01:57:21 -03:00
} ;
2010-03-29 13:51:10 -03:00
2009-09-14 09:42:41 -03:00
struct tm6000_capabilities {
unsigned int has_tuner : 1 ;
unsigned int has_tda9874 : 1 ;
unsigned int has_dvb : 1 ;
unsigned int has_zl10353 : 1 ;
unsigned int has_eeprom : 1 ;
2007-09-24 17:01:49 -03:00
unsigned int has_remote : 1 ;
2011-05-09 16:53:49 -03:00
unsigned int has_radio : 1 ;
2009-09-14 09:42:41 -03:00
} ;
2007-08-21 17:37:22 -03:00
struct tm6000_dvb {
struct dvb_adapter adapter ;
struct dvb_demux demux ;
struct dvb_frontend * frontend ;
struct dmxdev dmxdev ;
unsigned int streams ;
2010-05-29 13:52:46 -03:00
struct urb * bulk_urb ;
2007-08-21 17:37:22 -03:00
struct mutex mutex ;
} ;
2010-05-30 09:19:02 -03:00
struct snd_tm6000_card {
struct snd_card * card ;
spinlock_t reg_lock ;
struct tm6000_core * core ;
struct snd_pcm_substream * substream ;
2010-06-05 15:10:36 -03:00
/* temporary data for buffer fill processing */
unsigned buf_pos ;
unsigned period_pos ;
2010-05-30 09:19:02 -03:00
} ;
2010-04-26 11:24:18 -03:00
struct tm6000_endpoint {
struct usb_host_endpoint * endp ;
__u8 bInterfaceNumber ;
__u8 bAlternateSetting ;
unsigned maxsize ;
} ;
2011-09-01 02:43:03 -03:00
# define TM6000_QUIRK_NO_USB_DELAY (1 << 0)
2009-09-14 09:42:41 -03:00
struct tm6000_core {
/* generic device properties */
char name [ 30 ] ; /* name (including minor) of the device */
int model ; /* index in the device_data struct */
int devno ; /* marks the number of this device */
2008-01-08 11:19:22 -03:00
enum tm6000_devtype dev_type ; /* type of device */
2011-04-20 18:43:24 -03:00
unsigned char eedata [ 256 ] ; /* Eeprom data */
unsigned eedata_size ; /* Size of the eeprom info */
2007-08-21 17:37:22 -03:00
v4l2_std_id norm ; /* Current norm */
2010-05-29 13:52:46 -03:00
int width , height ; /* Selected resolution */
2009-09-14 09:42:41 -03:00
enum tm6000_core_state state ;
/* Device Capabilities*/
struct tm6000_capabilities caps ;
2011-11-30 14:54:05 -03:00
/* Used to load alsa/dvb */
struct work_struct request_module_wk ;
2009-09-14 09:42:41 -03:00
/* Tuner configuration */
2007-07-24 08:06:45 -03:00
int tuner_type ; /* type of the tuner */
int tuner_addr ; /* tuner address */
2010-03-29 13:51:10 -03:00
struct tm6000_gpio gpio ;
2007-07-24 08:06:45 -03:00
2010-06-20 17:16:52 -03:00
char * ir_codes ;
2011-02-17 22:11:05 -03:00
__u8 radio ;
2007-07-24 08:06:45 -03:00
/* Demodulator configuration */
int demod_addr ; /* demodulator address */
2009-09-14 09:42:41 -03:00
2007-09-19 07:36:34 -03:00
int audio_bitrate ;
2009-09-14 09:42:41 -03:00
/* i2c i/o */
struct i2c_adapter i2c_adap ;
struct i2c_client i2c_client ;
2010-05-10 13:22:51 -03:00
/* extension */
struct list_head devlist ;
2009-09-14 09:42:41 -03:00
/* video for linux */
int users ;
/* various device info */
2010-10-11 10:48:11 -03:00
struct tm6000_fh * resources ; /* Points to fh that is streaming */
bool is_res_read ;
2007-06-16 23:21:48 -03:00
struct video_device * vfd ;
2011-02-17 22:11:05 -03:00
struct video_device * radio_dev ;
2009-09-14 09:42:41 -03:00
struct tm6000_dmaqueue vidq ;
2009-09-14 16:37:13 -03:00
struct v4l2_device v4l2_dev ;
2009-09-14 09:42:41 -03:00
int input ;
2011-05-09 16:53:51 -03:00
struct tm6000_input vinput [ 3 ] ; /* video input */
struct tm6000_input rinput ; /* radio input */
2009-09-14 09:42:41 -03:00
int freq ;
unsigned int fourcc ;
enum tm6000_mode mode ;
2011-02-17 22:11:05 -03:00
int ctl_mute ; /* audio */
int ctl_volume ;
2011-05-09 16:53:50 -03:00
int amode ;
2011-02-17 22:11:05 -03:00
2007-08-21 17:37:22 -03:00
/* DVB-T support */
struct tm6000_dvb * dvb ;
2010-05-30 09:19:02 -03:00
/* audio support */
struct snd_tm6000_card * adev ;
2010-10-09 21:15:33 -03:00
struct work_struct wq_trigger ; /* Trigger to start/stop audio for alsa module */
atomic_t stream_started ; /* stream should be running if true */
2010-05-30 09:19:02 -03:00
2010-06-20 17:16:52 -03:00
struct tm6000_IR * ir ;
2009-09-14 09:42:41 -03:00
/* locks */
struct mutex lock ;
2011-08-04 04:14:10 -03:00
struct mutex usb_lock ;
2009-09-14 09:42:41 -03:00
/* usb transfer */
struct usb_device * udev ; /* the usb device */
2010-04-26 11:24:18 -03:00
struct tm6000_endpoint bulk_in , bulk_out , isoc_in , isoc_out ;
2010-06-20 17:16:52 -03:00
struct tm6000_endpoint int_in , int_out ;
2009-09-14 09:42:41 -03:00
/* scaler!=0 if scaler is active*/
int scaler ;
/* Isoc control struct */
struct usb_isoc_ctl isoc_ctl ;
spinlock_t slock ;
2011-09-01 02:43:03 -03:00
unsigned long quirks ;
2009-09-14 09:42:41 -03:00
} ;
2010-06-03 16:31:20 -03:00
enum tm6000_ops_type {
TM6000_AUDIO = 0x10 ,
TM6000_DVB = 0x20 ,
} ;
2010-05-10 13:22:51 -03:00
struct tm6000_ops {
struct list_head next ;
char * name ;
2010-06-03 16:31:20 -03:00
enum tm6000_ops_type type ;
2010-05-10 13:22:51 -03:00
int ( * init ) ( struct tm6000_core * ) ;
int ( * fini ) ( struct tm6000_core * ) ;
2010-06-03 17:16:28 -03:00
int ( * fillbuf ) ( struct tm6000_core * , char * buf , int size ) ;
2010-05-10 13:22:51 -03:00
} ;
2009-09-14 09:42:41 -03:00
struct tm6000_fh {
struct tm6000_core * dev ;
2011-02-17 22:11:05 -03:00
unsigned int radio ;
2009-09-14 09:42:41 -03:00
/* video capture */
struct tm6000_fmt * fmt ;
2010-05-29 13:52:46 -03:00
unsigned int width , height ;
2009-09-14 09:42:41 -03:00
struct videobuf_queue vb_vidq ;
enum v4l2_buf_type type ;
} ;
2010-10-20 06:35:34 -03:00
# define TM6000_STD (V4L2_STD_PAL|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc| \
2009-09-14 09:42:41 -03:00
V4L2_STD_PAL_M | V4L2_STD_PAL_60 | V4L2_STD_NTSC_M | \
2010-10-20 06:35:34 -03:00
V4L2_STD_NTSC_M_JP | V4L2_STD_SECAM )
2009-09-14 09:42:41 -03:00
2010-02-05 19:57:06 -03:00
/* In tm6000-cards.c */
2010-05-29 13:52:46 -03:00
int tm6000_tuner_callback ( void * ptr , int component , int command , int arg ) ;
int tm6000_xc5000_callback ( void * ptr , int component , int command , int arg ) ;
2010-02-08 08:43:41 -02:00
int tm6000_cards_setup ( struct tm6000_core * dev ) ;
2010-12-22 05:57:46 -03:00
void tm6000_flash_led ( struct tm6000_core * dev , u8 state ) ;
2010-02-08 08:43:41 -02:00
2009-09-14 09:42:41 -03:00
/* In tm6000-core.c */
2010-05-29 13:52:46 -03:00
int tm6000_read_write_usb ( struct tm6000_core * dev , u8 reqtype , u8 req ,
2009-09-14 09:42:41 -03:00
u16 value , u16 index , u8 * buf , u16 len ) ;
2010-05-29 13:52:46 -03:00
int tm6000_get_reg ( struct tm6000_core * dev , u8 req , u16 value , u16 index ) ;
2010-02-08 08:43:41 -02:00
int tm6000_get_reg16 ( struct tm6000_core * dev , u8 req , u16 value , u16 index ) ;
2010-04-02 13:52:49 -03:00
int tm6000_get_reg32 ( struct tm6000_core * dev , u8 req , u16 value , u16 index ) ;
2010-05-29 13:52:46 -03:00
int tm6000_set_reg ( struct tm6000_core * dev , u8 req , u16 value , u16 index ) ;
2011-02-17 22:11:05 -03:00
int tm6000_set_reg_mask ( struct tm6000_core * dev , u8 req , u16 value ,
u16 index , u16 mask ) ;
2010-05-18 04:23:29 -03:00
int tm6000_i2c_reset ( struct tm6000_core * dev , u16 tsleep ) ;
2010-05-29 13:52:46 -03:00
int tm6000_init ( struct tm6000_core * dev ) ;
2011-08-04 04:14:13 -03:00
int tm6000_reset ( struct tm6000_core * dev ) ;
2010-05-18 04:23:29 -03:00
2010-05-29 13:52:46 -03:00
int tm6000_init_analog_mode ( struct tm6000_core * dev ) ;
int tm6000_init_digital_mode ( struct tm6000_core * dev ) ;
int tm6000_set_audio_bitrate ( struct tm6000_core * dev , int bitrate ) ;
2011-05-09 16:53:53 -03:00
int tm6000_set_audio_rinput ( struct tm6000_core * dev ) ;
2011-02-17 22:11:05 -03:00
int tm6000_tvaudio_set_mute ( struct tm6000_core * dev , u8 mute ) ;
void tm6000_set_volume ( struct tm6000_core * dev , int vol ) ;
2009-09-14 09:42:41 -03:00
int tm6000_v4l2_register ( struct tm6000_core * dev ) ;
int tm6000_v4l2_unregister ( struct tm6000_core * dev ) ;
int tm6000_v4l2_exit ( void ) ;
void tm6000_set_fourcc_format ( struct tm6000_core * dev ) ;
2010-05-10 13:22:51 -03:00
void tm6000_remove_from_devlist ( struct tm6000_core * dev ) ;
void tm6000_add_into_devlist ( struct tm6000_core * dev ) ;
int tm6000_register_extension ( struct tm6000_ops * ops ) ;
void tm6000_unregister_extension ( struct tm6000_ops * ops ) ;
void tm6000_init_extension ( struct tm6000_core * dev ) ;
void tm6000_close_extension ( struct tm6000_core * dev ) ;
2010-06-03 17:16:28 -03:00
int tm6000_call_fillbuf ( struct tm6000_core * dev , enum tm6000_ops_type type ,
char * buf , int size ) ;
2010-05-10 13:22:51 -03:00
2007-11-02 09:51:13 -03:00
/* In tm6000-stds.c */
void tm6000_get_std_res ( struct tm6000_core * dev ) ;
2011-05-09 16:53:53 -03:00
int tm6000_set_standard ( struct tm6000_core * dev ) ;
2007-11-02 09:51:13 -03:00
2009-09-14 09:42:41 -03:00
/* In tm6000-i2c.c */
int tm6000_i2c_register ( struct tm6000_core * dev ) ;
int tm6000_i2c_unregister ( struct tm6000_core * dev ) ;
/* In tm6000-queue.c */
int tm6000_v4l2_mmap ( struct file * filp , struct vm_area_struct * vma ) ;
int tm6000_vidioc_streamon ( struct file * file , void * priv ,
enum v4l2_buf_type i ) ;
int tm6000_vidioc_streamoff ( struct file * file , void * priv ,
enum v4l2_buf_type i ) ;
2010-05-29 13:52:46 -03:00
int tm6000_vidioc_reqbufs ( struct file * file , void * priv ,
struct v4l2_requestbuffers * rb ) ;
int tm6000_vidioc_querybuf ( struct file * file , void * priv ,
struct v4l2_buffer * b ) ;
int tm6000_vidioc_qbuf ( struct file * file , void * priv , struct v4l2_buffer * b ) ;
int tm6000_vidioc_dqbuf ( struct file * file , void * priv , struct v4l2_buffer * b ) ;
2009-09-14 09:42:41 -03:00
ssize_t tm6000_v4l2_read ( struct file * filp , char __user * buf , size_t count ,
2010-05-29 13:52:46 -03:00
loff_t * f_pos ) ;
2009-09-14 09:42:41 -03:00
unsigned int tm6000_v4l2_poll ( struct file * file ,
struct poll_table_struct * wait ) ;
int tm6000_queue_init ( struct tm6000_core * dev ) ;
2008-01-11 13:55:45 -03:00
/* In tm6000-alsa.c */
2010-05-10 13:22:51 -03:00
/*int tm6000_audio_init(struct tm6000_core *dev, int idx);*/
2008-01-11 13:55:45 -03:00
2010-06-20 17:16:52 -03:00
/* In tm6000-input.c */
int tm6000_ir_init ( struct tm6000_core * dev ) ;
int tm6000_ir_fini ( struct tm6000_core * dev ) ;
void tm6000_ir_wait ( struct tm6000_core * dev , u8 state ) ;
2010-12-22 05:57:46 -03:00
int tm6000_ir_int_start ( struct tm6000_core * dev ) ;
void tm6000_ir_int_stop ( struct tm6000_core * dev ) ;
2008-01-11 13:55:45 -03:00
2009-09-14 09:42:41 -03:00
/* Debug stuff */
extern int tm6000_debug ;
# define dprintk(dev, level, fmt, arg...) do {\
if ( tm6000_debug & level ) \
2010-05-29 13:52:46 -03:00
printk ( KERN_INFO " (%lu) %s %s : " fmt , jiffies , \
2011-09-23 09:26:22 -03:00
dev - > name , __func__ , # # arg ) ; } while ( 0 )
2009-09-14 09:42:41 -03:00
# define V4L2_DEBUG_REG 0x0004
# define V4L2_DEBUG_I2C 0x0008
# define V4L2_DEBUG_QUEUE 0x0010
# define V4L2_DEBUG_ISOC 0x0020
# define V4L2_DEBUG_RES_LOCK 0x0040 /* Resource locking */
# define V4L2_DEBUG_OPEN 0x0080 /* video open/close debug */
# define tm6000_err(fmt, arg...) do {\
printk ( KERN_ERR " tm6000 %s : " fmt , \
2011-09-23 09:26:22 -03:00
__func__ , # # arg ) ; } while ( 0 )