2008-08-11 13:12:19 -03:00
/*
* DVB USB Linux driver for AME DTV - 5100 USB2 .0 DVB - T
*
* Copyright ( C ) 2008 Antoine Jacquet < royale @ zerezo . com >
* http : //royale.zerezo.com/dtv5100/
*
* Inspired by gl861 . c and au6610 . c drivers
*
* 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 .
*/
# include "dtv5100.h"
2008-08-11 19:21:33 -03:00
# include "zl10353.h"
2008-08-11 13:12:19 -03:00
# include "qt1010.h"
/* debug */
static int dvb_usb_dtv5100_debug ;
module_param_named ( debug , dvb_usb_dtv5100_debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " set debugging level " DVB_USB_DEBUG_STATUS ) ;
DVB_DEFINE_MOD_OPT_ADAPTER_NR ( adapter_nr ) ;
2016-10-07 08:51:23 -03:00
struct dtv5100_state {
unsigned char data [ 80 ] ;
} ;
2008-08-11 19:21:33 -03:00
static int dtv5100_i2c_msg ( struct dvb_usb_device * d , u8 addr ,
2008-08-12 16:56:34 -03:00
u8 * wbuf , u16 wlen , u8 * rbuf , u16 rlen )
2008-08-11 13:12:19 -03:00
{
2016-10-07 08:51:23 -03:00
struct dtv5100_state * st = d - > priv ;
2008-08-11 19:21:33 -03:00
u8 request ;
u8 type ;
u16 value ;
u16 index ;
switch ( wlen ) {
case 1 :
/* write { reg }, read { value } */
request = ( addr = = DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_READ :
DTV5100_TUNER_READ ) ;
2008-08-12 16:56:34 -03:00
type = USB_TYPE_VENDOR | USB_DIR_IN ;
2008-08-11 19:21:33 -03:00
value = 0 ;
break ;
case 2 :
/* write { reg, value } */
request = ( addr = = DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_WRITE :
DTV5100_TUNER_WRITE ) ;
2008-08-12 16:56:34 -03:00
type = USB_TYPE_VENDOR | USB_DIR_OUT ;
2008-08-11 19:21:33 -03:00
value = wbuf [ 1 ] ;
break ;
default :
warn ( " wlen = %x, aborting. " , wlen ) ;
return - EINVAL ;
}
index = ( addr < < 8 ) + wbuf [ 0 ] ;
2008-08-11 13:12:19 -03:00
2016-10-07 08:51:23 -03:00
memcpy ( st - > data , rbuf , rlen ) ;
2008-08-11 19:21:33 -03:00
msleep ( 1 ) ; /* avoid I2C errors */
return usb_control_msg ( d - > udev , usb_rcvctrlpipe ( d - > udev , 0 ) , request ,
2016-10-07 08:51:23 -03:00
type , value , index , st - > data , rlen ,
2008-08-11 13:12:19 -03:00
DTV5100_USB_TIMEOUT ) ;
}
/* I2C */
static int dtv5100_i2c_xfer ( struct i2c_adapter * adap , struct i2c_msg msg [ ] ,
2008-08-12 16:56:34 -03:00
int num )
2008-08-11 13:12:19 -03:00
{
struct dvb_usb_device * d = i2c_get_adapdata ( adap ) ;
int i ;
if ( num > 2 )
return - EINVAL ;
if ( mutex_lock_interruptible ( & d - > i2c_mutex ) < 0 )
return - EAGAIN ;
for ( i = 0 ; i < num ; i + + ) {
2008-08-11 19:21:33 -03:00
/* write/read request */
2008-08-11 13:12:19 -03:00
if ( i + 1 < num & & ( msg [ i + 1 ] . flags & I2C_M_RD ) ) {
2008-08-11 19:21:33 -03:00
if ( dtv5100_i2c_msg ( d , msg [ i ] . addr , msg [ i ] . buf ,
msg [ i ] . len , msg [ i + 1 ] . buf ,
msg [ i + 1 ] . len ) < 0 )
2008-08-11 13:12:19 -03:00
break ;
i + + ;
2008-08-11 19:21:33 -03:00
} else if ( dtv5100_i2c_msg ( d , msg [ i ] . addr , msg [ i ] . buf ,
msg [ i ] . len , NULL , 0 ) < 0 )
2008-08-11 13:12:19 -03:00
break ;
}
mutex_unlock ( & d - > i2c_mutex ) ;
return i ;
}
static u32 dtv5100_i2c_func ( struct i2c_adapter * adapter )
{
return I2C_FUNC_I2C ;
}
static struct i2c_algorithm dtv5100_i2c_algo = {
. master_xfer = dtv5100_i2c_xfer ,
. functionality = dtv5100_i2c_func ,
} ;
/* Callbacks for DVB USB */
2008-08-11 19:21:33 -03:00
static struct zl10353_config dtv5100_zl10353_config = {
. demod_address = DTV5100_DEMOD_ADDR ,
. no_tuner = 1 ,
. parallel_ts = 1 ,
} ;
2008-08-11 13:12:19 -03:00
static int dtv5100_frontend_attach ( struct dvb_usb_adapter * adap )
{
2011-09-06 09:31:57 -03:00
adap - > fe_adap [ 0 ] . fe = dvb_attach ( zl10353_attach , & dtv5100_zl10353_config ,
2008-08-12 16:56:34 -03:00
& adap - > dev - > i2c_adap ) ;
2011-09-06 09:31:57 -03:00
if ( adap - > fe_adap [ 0 ] . fe = = NULL )
2008-08-11 19:21:33 -03:00
return - EIO ;
/* disable i2c gate, or it won't work... is this safe? */
2011-09-06 09:31:57 -03:00
adap - > fe_adap [ 0 ] . fe - > ops . i2c_gate_ctrl = NULL ;
2008-08-11 19:21:33 -03:00
2008-08-11 13:12:19 -03:00
return 0 ;
}
static struct qt1010_config dtv5100_qt1010_config = {
2008-08-11 19:21:33 -03:00
. i2c_address = DTV5100_TUNER_ADDR
2008-08-11 13:12:19 -03:00
} ;
static int dtv5100_tuner_attach ( struct dvb_usb_adapter * adap )
{
return dvb_attach ( qt1010_attach ,
2011-09-06 09:31:57 -03:00
adap - > fe_adap [ 0 ] . fe , & adap - > dev - > i2c_adap ,
2008-08-11 13:12:19 -03:00
& dtv5100_qt1010_config ) = = NULL ? - ENODEV : 0 ;
}
/* DVB USB Driver stuff */
static struct dvb_usb_device_properties dtv5100_properties ;
static int dtv5100_probe ( struct usb_interface * intf ,
const struct usb_device_id * id )
{
int i , ret ;
struct usb_device * udev = interface_to_usbdev ( intf ) ;
2008-08-11 19:21:33 -03:00
/* initialize non qt1010/zl10353 part? */
2008-08-12 16:56:34 -03:00
for ( i = 0 ; dtv5100_init [ i ] . request ; i + + ) {
2008-08-11 13:12:19 -03:00
ret = usb_control_msg ( udev , usb_rcvctrlpipe ( udev , 0 ) ,
dtv5100_init [ i ] . request ,
2008-08-12 16:56:34 -03:00
USB_TYPE_VENDOR | USB_DIR_OUT ,
2008-08-11 13:12:19 -03:00
dtv5100_init [ i ] . value ,
dtv5100_init [ i ] . index , NULL , 0 ,
DTV5100_USB_TIMEOUT ) ;
if ( ret )
return ret ;
}
2008-08-11 19:21:33 -03:00
ret = dvb_usb_device_init ( intf , & dtv5100_properties ,
THIS_MODULE , NULL , adapter_nr ) ;
if ( ret )
return ret ;
2008-08-11 13:12:19 -03:00
return 0 ;
}
2008-08-18 18:38:51 -03:00
static struct usb_device_id dtv5100_table [ ] = {
2008-08-11 13:12:19 -03:00
{ USB_DEVICE ( 0x06be , 0xa232 ) } ,
{ } /* Terminating entry */
} ;
MODULE_DEVICE_TABLE ( usb , dtv5100_table ) ;
static struct dvb_usb_device_properties dtv5100_properties = {
. caps = DVB_USB_IS_AN_I2C_ADAPTER ,
. usb_ctrl = DEVICE_SPECIFIC ,
2016-10-07 08:51:23 -03:00
. size_of_priv = sizeof ( struct dtv5100_state ) ,
2008-08-11 13:12:19 -03:00
. num_adapters = 1 ,
. adapter = { {
2011-09-06 09:31:57 -03:00
. num_frontends = 1 ,
. fe = { {
2008-08-11 13:12:19 -03:00
. frontend_attach = dtv5100_frontend_attach ,
. tuner_attach = dtv5100_tuner_attach ,
. stream = {
. type = USB_BULK ,
. count = 8 ,
. endpoint = 0x82 ,
. u = {
. bulk = {
. buffersize = 4096 ,
}
}
} ,
2011-09-06 09:31:57 -03:00
} } ,
2008-08-11 13:12:19 -03:00
} } ,
. i2c_algo = & dtv5100_i2c_algo ,
. num_device_descs = 1 ,
. devices = {
{
. name = " AME DTV-5100 USB2.0 DVB-T " ,
. cold_ids = { NULL } ,
. warm_ids = { & dtv5100_table [ 0 ] , NULL } ,
} ,
}
} ;
static struct usb_driver dtv5100_driver = {
. name = " dvb_usb_dtv5100 " ,
. probe = dtv5100_probe ,
. disconnect = dvb_usb_device_exit ,
. id_table = dtv5100_table ,
} ;
2011-11-18 09:46:12 -08:00
module_usb_driver ( dtv5100_driver ) ;
2008-08-11 13:12:19 -03:00
MODULE_AUTHOR ( DRIVER_AUTHOR ) ;
MODULE_DESCRIPTION ( DRIVER_DESC ) ;
MODULE_LICENSE ( " GPL " ) ;