2007-03-11 20:44:05 -03:00
/*
* Driver for the Conexant CX23885 PCIe bridge
*
* Copyright ( c ) 2006 Steven Toth < stoth @ hauppauge . com >
*
* 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/module.h>
# include <linux/init.h>
# include <linux/device.h>
# include <linux/fs.h>
# include <linux/kthread.h>
# include <linux/file.h>
# include <linux/suspend.h>
# include "cx23885.h"
# include <media/v4l2-common.h>
# include "s5h1409.h"
# include "mt2131.h"
2007-12-07 01:40:36 -03:00
# include "tda8290.h"
2007-12-24 04:52:08 -03:00
# include "tda18271.h"
2007-09-08 15:17:13 -03:00
# include "lgdt330x.h"
2007-12-18 01:57:06 -03:00
# include "xc5000.h"
2007-09-08 15:17:13 -03:00
# include "dvb-pll.h"
2007-12-18 01:09:11 -03:00
# include "tuner-xc2028.h"
# include "tuner-xc2028-types.h"
2007-03-11 20:44:05 -03:00
2007-09-04 21:32:41 -03:00
static unsigned int debug = 0 ;
2007-03-11 20:44:05 -03:00
# define dprintk(level,fmt, arg...) if (debug >= level) \
printk ( KERN_DEBUG " %s: " fmt , dev - > name , # # arg )
/* ------------------------------------------------------------------ */
2007-12-07 01:40:36 -03:00
static unsigned int alt_tuner ;
module_param ( alt_tuner , int , 0644 ) ;
MODULE_PARM_DESC ( alt_tuner , " Enable alternate tuner configuration " ) ;
/* ------------------------------------------------------------------ */
2007-03-11 20:44:05 -03:00
static int dvb_buf_setup ( struct videobuf_queue * q ,
unsigned int * count , unsigned int * size )
{
struct cx23885_tsport * port = q - > priv_data ;
port - > ts_packet_size = 188 * 4 ;
port - > ts_packet_count = 32 ;
* size = port - > ts_packet_size * port - > ts_packet_count ;
* count = 32 ;
return 0 ;
}
2007-03-20 23:00:18 -03:00
static int dvb_buf_prepare ( struct videobuf_queue * q ,
struct videobuf_buffer * vb , enum v4l2_field field )
2007-03-11 20:44:05 -03:00
{
struct cx23885_tsport * port = q - > priv_data ;
2007-03-20 23:00:18 -03:00
return cx23885_buf_prepare ( q , port , ( struct cx23885_buffer * ) vb , field ) ;
2007-03-11 20:44:05 -03:00
}
static void dvb_buf_queue ( struct videobuf_queue * q , struct videobuf_buffer * vb )
{
struct cx23885_tsport * port = q - > priv_data ;
cx23885_buf_queue ( port , ( struct cx23885_buffer * ) vb ) ;
}
2007-03-20 23:00:18 -03:00
static void dvb_buf_release ( struct videobuf_queue * q ,
struct videobuf_buffer * vb )
2007-03-11 20:44:05 -03:00
{
cx23885_free_buffer ( q , ( struct cx23885_buffer * ) vb ) ;
}
2007-12-18 01:57:06 -03:00
static int cx23885_request_firmware ( struct dvb_frontend * fe ,
const struct firmware * * fw , char * name )
{
struct cx23885_tsport * port = fe - > dvb - > priv ;
struct cx23885_dev * dev = port - > dev ;
dprintk ( 1 , " %s(?,?,%s) \n " , __FUNCTION__ , name ) ;
return request_firmware ( fw , name , & dev - > pci - > dev ) ;
}
static int hauppauge_hvr1500q_tuner_reset ( struct dvb_frontend * fe )
{
struct cx23885_tsport * port = fe - > dvb - > priv ;
struct cx23885_dev * dev = port - > dev ;
dprintk ( 1 , " %s() \n " , __FUNCTION__ ) ;
/* Drive the tuner into reset back back */
cx_clear ( GP0_IO , 0x00000004 ) ;
mdelay ( 200 ) ;
cx_set ( GP0_IO , 0x00000004 ) ;
return 0 ;
}
2007-03-11 20:44:05 -03:00
static struct videobuf_queue_ops dvb_qops = {
. buf_setup = dvb_buf_setup ,
. buf_prepare = dvb_buf_prepare ,
. buf_queue = dvb_buf_queue ,
. buf_release = dvb_buf_release ,
} ;
2007-09-04 21:40:47 -03:00
static struct s5h1409_config hauppauge_generic_config = {
2007-09-08 19:08:17 -03:00
. demod_address = 0x32 > > 1 ,
. output_mode = S5H1409_SERIAL_OUTPUT ,
. gpio = S5H1409_GPIO_ON ,
2007-12-13 10:04:10 -03:00
. qam_if = 44000 ,
2007-09-08 19:08:17 -03:00
. inversion = S5H1409_INVERSION_OFF ,
. status_mode = S5H1409_DEMODLOCKING
} ;
2007-12-07 01:40:36 -03:00
static struct s5h1409_config hauppauge_ezqam_config = {
. demod_address = 0x32 > > 1 ,
. output_mode = S5H1409_SERIAL_OUTPUT ,
. gpio = S5H1409_GPIO_OFF ,
. qam_if = 4000 ,
. inversion = S5H1409_INVERSION_ON ,
. status_mode = S5H1409_DEMODLOCKING
} ;
2007-09-08 19:08:17 -03:00
static struct s5h1409_config hauppauge_hvr1800lp_config = {
2007-03-11 20:44:05 -03:00
. demod_address = 0x32 > > 1 ,
. output_mode = S5H1409_SERIAL_OUTPUT ,
. gpio = S5H1409_GPIO_OFF ,
2007-12-13 10:04:10 -03:00
. qam_if = 44000 ,
2007-03-20 15:27:53 -03:00
. inversion = S5H1409_INVERSION_OFF ,
. status_mode = S5H1409_DEMODLOCKING
2007-03-11 20:44:05 -03:00
} ;
2007-12-18 01:09:11 -03:00
static struct s5h1409_config hauppauge_hvr1500_config = {
. demod_address = 0x32 > > 1 ,
. output_mode = S5H1409_SERIAL_OUTPUT ,
. gpio = S5H1409_GPIO_OFF ,
. inversion = S5H1409_INVERSION_OFF ,
. status_mode = S5H1409_DEMODLOCKING
} ;
2007-09-04 21:40:47 -03:00
static struct mt2131_config hauppauge_generic_tunerconfig = {
2007-08-22 21:01:20 -03:00
0x61
} ;
2007-09-08 15:17:13 -03:00
static struct lgdt330x_config fusionhdtv_5_express = {
. demod_address = 0x0e ,
. demod_chip = LGDT3303 ,
. serial_mpeg = 0x40 ,
} ;
2007-12-18 01:57:06 -03:00
static struct s5h1409_config hauppauge_hvr1500q_config = {
. demod_address = 0x32 > > 1 ,
. output_mode = S5H1409_SERIAL_OUTPUT ,
. gpio = S5H1409_GPIO_ON ,
. qam_if = 44000 ,
. inversion = S5H1409_INVERSION_OFF ,
. status_mode = S5H1409_DEMODLOCKING
} ;
static struct xc5000_config hauppauge_hvr1500q_tunerconfig = {
2007-12-20 01:14:43 -03:00
. i2c_address = 0x61 ,
. if_khz = 5380 ,
2007-12-18 01:57:06 -03:00
. request_firmware = cx23885_request_firmware ,
2007-12-20 01:14:43 -03:00
. tuner_reset = hauppauge_hvr1500q_tuner_reset
2007-12-18 01:57:06 -03:00
} ;
2007-12-24 04:52:08 -03:00
static struct tda829x_config tda829x_no_probe = {
. probe_tuner = TDA829X_DONT_PROBE ,
} ;
2007-12-18 01:09:11 -03:00
static int cx23885_hvr1500_xc3028_callback ( void * ptr , int command , int arg )
{
struct cx23885_tsport * port = ptr ;
struct cx23885_dev * dev = port - > dev ;
switch ( command ) {
case XC2028_TUNER_RESET :
/* Send the tuner in then out of reset */
/* GPIO-2 xc3028 tuner */
dprintk ( 1 , " %s: XC2028_TUNER_RESET %d \n " , __FUNCTION__ , arg ) ;
cx_set ( GP0_IO , 0x00040000 ) ;
cx_clear ( GP0_IO , 0x00000004 ) ;
msleep ( 5 ) ;
cx_set ( GP0_IO , 0x00040004 ) ;
msleep ( 5 ) ;
break ;
case XC2028_RESET_CLK :
dprintk ( 1 , " %s: XC2028_RESET_CLK %d \n " , __FUNCTION__ , arg ) ;
break ;
default :
dprintk ( 1 , " %s: unknown command %d, arg %d \n " , __FUNCTION__ ,
command , arg ) ;
return - EINVAL ;
}
return 0 ;
}
2007-03-11 20:44:05 -03:00
static int dvb_register ( struct cx23885_tsport * port )
{
struct cx23885_dev * dev = port - > dev ;
2007-09-09 03:55:34 -03:00
struct cx23885_i2c * i2c_bus = NULL ;
2007-03-11 20:44:05 -03:00
/* init struct videobuf_dvb */
port - > dvb . name = dev - > name ;
/* init frontend */
switch ( dev - > board ) {
2007-08-22 21:01:20 -03:00
case CX23885_BOARD_HAUPPAUGE_HVR1250 :
2007-09-09 03:55:34 -03:00
i2c_bus = & dev - > i2c_bus [ 0 ] ;
2007-03-11 20:44:05 -03:00
port - > dvb . frontend = dvb_attach ( s5h1409_attach ,
2007-09-04 21:40:47 -03:00
& hauppauge_generic_config ,
2007-09-09 03:55:34 -03:00
& i2c_bus - > i2c_adap ) ;
2007-03-11 20:44:05 -03:00
if ( port - > dvb . frontend ! = NULL ) {
2007-03-20 23:00:18 -03:00
dvb_attach ( mt2131_attach , port - > dvb . frontend ,
2007-09-09 03:55:34 -03:00
& i2c_bus - > i2c_adap ,
2007-09-04 21:40:47 -03:00
& hauppauge_generic_tunerconfig , 0 ) ;
2007-03-11 20:44:05 -03:00
}
break ;
2007-12-07 01:40:36 -03:00
case CX23885_BOARD_HAUPPAUGE_HVR1800 :
i2c_bus = & dev - > i2c_bus [ 0 ] ;
switch ( alt_tuner ) {
case 1 :
port - > dvb . frontend =
dvb_attach ( s5h1409_attach ,
& hauppauge_ezqam_config ,
& i2c_bus - > i2c_adap ) ;
if ( port - > dvb . frontend ! = NULL ) {
dvb_attach ( tda829x_attach , port - > dvb . frontend ,
& dev - > i2c_bus [ 1 ] . i2c_adap , 0x42 ,
2007-12-24 04:52:08 -03:00
& tda829x_no_probe ) ;
dvb_attach ( tda18271_attach , port - > dvb . frontend ,
0x60 , & dev - > i2c_bus [ 1 ] . i2c_adap ,
TDA18271_GATE_ANALOG ) ;
2007-12-07 01:40:36 -03:00
}
break ;
case 0 :
default :
port - > dvb . frontend =
dvb_attach ( s5h1409_attach ,
& hauppauge_generic_config ,
& i2c_bus - > i2c_adap ) ;
if ( port - > dvb . frontend ! = NULL )
dvb_attach ( mt2131_attach , port - > dvb . frontend ,
& i2c_bus - > i2c_adap ,
& hauppauge_generic_tunerconfig , 0 ) ;
break ;
}
break ;
2007-09-08 19:08:17 -03:00
case CX23885_BOARD_HAUPPAUGE_HVR1800lp :
2007-09-09 03:55:34 -03:00
i2c_bus = & dev - > i2c_bus [ 0 ] ;
2007-09-08 19:08:17 -03:00
port - > dvb . frontend = dvb_attach ( s5h1409_attach ,
& hauppauge_hvr1800lp_config ,
2007-09-09 03:55:34 -03:00
& i2c_bus - > i2c_adap ) ;
2007-09-08 19:08:17 -03:00
if ( port - > dvb . frontend ! = NULL ) {
dvb_attach ( mt2131_attach , port - > dvb . frontend ,
2007-09-09 03:55:34 -03:00
& i2c_bus - > i2c_adap ,
2007-09-08 19:08:17 -03:00
& hauppauge_generic_tunerconfig , 0 ) ;
}
break ;
2007-09-08 15:17:13 -03:00
case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP :
2007-09-09 03:55:34 -03:00
i2c_bus = & dev - > i2c_bus [ 0 ] ;
2007-09-08 15:17:13 -03:00
port - > dvb . frontend = dvb_attach ( lgdt330x_attach ,
& fusionhdtv_5_express ,
2007-09-09 03:55:34 -03:00
& i2c_bus - > i2c_adap ) ;
2007-09-08 15:17:13 -03:00
if ( port - > dvb . frontend ! = NULL ) {
2007-09-09 03:55:34 -03:00
dvb_attach ( dvb_pll_attach , port - > dvb . frontend , 0x61 ,
& i2c_bus - > i2c_adap , DVB_PLL_LG_TDVS_H06XF ) ;
2007-09-08 15:17:13 -03:00
}
break ;
2007-12-18 01:57:06 -03:00
case CX23885_BOARD_HAUPPAUGE_HVR1500Q :
i2c_bus = & dev - > i2c_bus [ 1 ] ;
port - > dvb . frontend = dvb_attach ( s5h1409_attach ,
& hauppauge_hvr1500q_config ,
& dev - > i2c_bus [ 0 ] . i2c_adap ) ;
if ( port - > dvb . frontend ! = NULL ) {
dvb_attach ( xc5000_attach , port - > dvb . frontend ,
& i2c_bus - > i2c_adap ,
& hauppauge_hvr1500q_tunerconfig ) ;
}
break ;
2007-12-18 01:09:11 -03:00
case CX23885_BOARD_HAUPPAUGE_HVR1500 :
i2c_bus = & dev - > i2c_bus [ 1 ] ;
port - > dvb . frontend = dvb_attach ( s5h1409_attach ,
& hauppauge_hvr1500_config ,
& dev - > i2c_bus [ 0 ] . i2c_adap ) ;
if ( port - > dvb . frontend ! = NULL ) {
struct dvb_frontend * fe ;
struct xc2028_config cfg = {
. i2c_adap = & i2c_bus - > i2c_adap ,
. i2c_addr = 0x61 ,
. video_dev = port ,
. callback = cx23885_hvr1500_xc3028_callback ,
} ;
static struct xc2028_ctrl ctl = {
. fname = " xc3028-v27.fw " ,
. max_len = 64 ,
. scode_table = OREN538 ,
} ;
fe = dvb_attach ( xc2028_attach ,
port - > dvb . frontend , & cfg ) ;
if ( fe ! = NULL & & fe - > ops . tuner_ops . set_config ! = NULL )
fe - > ops . tuner_ops . set_config ( fe , & ctl ) ;
}
break ;
2007-03-11 20:44:05 -03:00
default :
printk ( " %s: The frontend of your DVB/ATSC card isn't supported yet \n " ,
dev - > name ) ;
break ;
}
if ( NULL = = port - > dvb . frontend ) {
printk ( " %s: frontend initialization failed \n " , dev - > name ) ;
return - 1 ;
}
/* Put the analog decoder in standby to keep it quiet */
2007-09-09 03:55:34 -03:00
cx23885_call_i2c_clients ( i2c_bus , TUNER_SET_STANDBY , NULL ) ;
2007-03-11 20:44:05 -03:00
2007-12-07 01:40:36 -03:00
if ( port - > dvb . frontend - > ops . analog_ops . standby )
port - > dvb . frontend - > ops . analog_ops . standby ( port - > dvb . frontend ) ;
2007-03-11 20:44:05 -03:00
/* register everything */
2007-03-20 23:00:18 -03:00
return videobuf_dvb_register ( & port - > dvb , THIS_MODULE , port ,
& dev - > pci - > dev ) ;
2007-03-11 20:44:05 -03:00
}
int cx23885_dvb_register ( struct cx23885_tsport * port )
{
struct cx23885_dev * dev = port - > dev ;
int err ;
2007-03-20 23:00:18 -03:00
dprintk ( 1 , " %s \n " , __FUNCTION__ ) ;
dprintk ( 1 , " ->being probed by Card=%d Name=%s, PCI %02x:%02x \n " ,
2007-03-11 20:44:05 -03:00
dev - > board ,
dev - > name ,
dev - > pci_bus ,
dev - > pci_slot ) ;
err = - ENODEV ;
/* dvb stuff */
printk ( " %s: cx23885 based dvb card \n " , dev - > name ) ;
2007-10-08 09:04:09 -03:00
videobuf_queue_pci_init ( & port - > dvb . dvbq , & dvb_qops , dev - > pci , & port - > slock ,
2007-03-20 23:00:18 -03:00
V4L2_BUF_TYPE_VIDEO_CAPTURE , V4L2_FIELD_TOP ,
sizeof ( struct cx23885_buffer ) , port ) ;
2007-03-11 20:44:05 -03:00
err = dvb_register ( port ) ;
if ( err ! = 0 )
printk ( " %s() dvb_register failed err = %d \n " , __FUNCTION__ , err ) ;
return err ;
}
int cx23885_dvb_unregister ( struct cx23885_tsport * port )
{
/* dvb */
if ( port - > dvb . frontend )
videobuf_dvb_unregister ( & port - > dvb ) ;
return 0 ;
}
2007-03-20 23:00:18 -03:00
/*
* Local variables :
* c - basic - offset : 8
* End :
* kate : eol " unix " ; indent - width 3 ; remove - trailing - space on ; replace - trailing - space - save on ; tab - width 8 ; replace - tabs off ; space - indent off ; mixed - indent off
*/