2008-09-15 17:18:09 -03:00
/*
* DVB USB Linux driver for Afatech AF9015 DVB - T USB2 .0 receiver
*
* Copyright ( C ) 2007 Antti Palosaari < crope @ iki . fi >
*
* Thanks to Afatech who kindly provided information .
*
* 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 "af9015.h"
2008-11-05 16:31:24 -03:00
static int dvb_usb_af9015_debug ;
2008-09-15 17:18:09 -03:00
module_param_named ( debug , dvb_usb_af9015_debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " set debugging level " DVB_USB_DEBUG_STATUS ) ;
2008-11-05 16:31:24 -03:00
static int dvb_usb_af9015_remote ;
2008-09-15 17:18:09 -03:00
module_param_named ( remote , dvb_usb_af9015_remote , int , 0644 ) ;
MODULE_PARM_DESC ( remote , " select remote " ) ;
DVB_DEFINE_MOD_OPT_ADAPTER_NR ( adapter_nr ) ;
2012-06-07 20:36:35 -03:00
static int af9015_ctrl_msg ( struct dvb_usb_device * d , struct req_t * req )
2008-09-15 17:18:09 -03:00
{
2009-09-12 20:46:30 -03:00
# define BUF_LEN 63
# define REQ_HDR_LEN 8 /* send header size */
# define ACK_HDR_LEN 2 /* rece header size */
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2012-06-07 20:36:35 -03:00
int ret , wlen , rlen ;
2009-09-12 20:46:30 -03:00
u8 buf [ BUF_LEN ] ;
2008-09-15 17:18:09 -03:00
u8 write = 1 ;
buf [ 0 ] = req - > cmd ;
2012-06-07 20:36:35 -03:00
buf [ 1 ] = state - > seq + + ;
2008-09-15 17:18:09 -03:00
buf [ 2 ] = req - > i2c_addr ;
buf [ 3 ] = req - > addr > > 8 ;
buf [ 4 ] = req - > addr & 0xff ;
buf [ 5 ] = req - > mbox ;
buf [ 6 ] = req - > addr_len ;
buf [ 7 ] = req - > data_len ;
switch ( req - > cmd ) {
case GET_CONFIG :
case READ_MEMORY :
case RECONNECT_USB :
write = 0 ;
break ;
case READ_I2C :
write = 0 ;
buf [ 2 ] | = 0x01 ; /* set I2C direction */
case WRITE_I2C :
buf [ 0 ] = READ_WRITE_I2C ;
break ;
case WRITE_MEMORY :
if ( ( ( req - > addr & 0xff00 ) = = 0xff00 ) | |
2009-09-12 21:25:59 -03:00
( ( req - > addr & 0xff00 ) = = 0xae00 ) )
2008-09-15 17:18:09 -03:00
buf [ 0 ] = WRITE_VIRTUAL_MEMORY ;
case WRITE_VIRTUAL_MEMORY :
case COPY_FIRMWARE :
case DOWNLOAD_FIRMWARE :
2009-07-28 11:54:52 -03:00
case BOOT :
2008-09-15 17:18:09 -03:00
break ;
default :
err ( " unknown command:%d " , req - > cmd ) ;
ret = - 1 ;
2012-06-07 20:36:35 -03:00
goto error ;
2008-09-15 17:18:09 -03:00
}
2009-09-12 20:46:30 -03:00
/* buffer overflow check */
if ( ( write & & ( req - > data_len > BUF_LEN - REQ_HDR_LEN ) ) | |
( ! write & & ( req - > data_len > BUF_LEN - ACK_HDR_LEN ) ) ) {
err ( " too much data; cmd:%d len:%d " , req - > cmd , req - > data_len ) ;
ret = - EINVAL ;
2012-06-07 20:36:35 -03:00
goto error ;
2009-09-12 20:46:30 -03:00
}
2012-06-07 20:36:35 -03:00
/* write receives seq + status = 2 bytes
read receives seq + status + data = 2 + N bytes */
wlen = REQ_HDR_LEN ;
rlen = ACK_HDR_LEN ;
2008-09-15 17:18:09 -03:00
if ( write ) {
2012-06-07 20:36:35 -03:00
wlen + = req - > data_len ;
2009-09-12 20:46:30 -03:00
memcpy ( & buf [ REQ_HDR_LEN ] , req - > data , req - > data_len ) ;
2012-06-07 20:36:35 -03:00
} else {
rlen + = req - > data_len ;
2008-09-15 17:18:09 -03:00
}
2009-09-12 20:46:30 -03:00
2012-06-07 20:36:35 -03:00
/* no ack for these packets */
2008-09-15 17:18:09 -03:00
if ( req - > cmd = = DOWNLOAD_FIRMWARE | | req - > cmd = = RECONNECT_USB )
2012-06-07 20:36:35 -03:00
rlen = 0 ;
2008-09-15 17:18:09 -03:00
2012-06-20 20:27:42 -03:00
ret = dvb_usbv2_generic_rw ( d , buf , wlen , buf , rlen ) ;
2012-06-07 20:36:35 -03:00
if ( ret )
goto error ;
2008-09-15 17:18:09 -03:00
/* check status */
2012-06-07 20:36:35 -03:00
if ( rlen & & buf [ 1 ] ) {
2008-09-15 17:18:09 -03:00
err ( " command failed:%d " , buf [ 1 ] ) ;
ret = - 1 ;
2012-06-07 20:36:35 -03:00
goto error ;
2008-09-15 17:18:09 -03:00
}
/* read request, copy returned data to return buf */
if ( ! write )
2009-09-12 20:46:30 -03:00
memcpy ( req - > data , & buf [ ACK_HDR_LEN ] , req - > data_len ) ;
2012-06-07 20:36:35 -03:00
error :
2008-09-15 17:18:09 -03:00
return ret ;
}
static int af9015_write_regs ( struct dvb_usb_device * d , u16 addr , u8 * val ,
u8 len )
{
struct req_t req = { WRITE_MEMORY , AF9015_I2C_DEMOD , addr , 0 , 0 , len ,
val } ;
return af9015_ctrl_msg ( d , & req ) ;
}
2010-10-22 18:45:18 -03:00
static int af9015_read_regs ( struct dvb_usb_device * d , u16 addr , u8 * val , u8 len )
2008-09-15 17:18:09 -03:00
{
2010-10-22 18:45:18 -03:00
struct req_t req = { READ_MEMORY , AF9015_I2C_DEMOD , addr , 0 , 0 , len ,
val } ;
2008-09-15 17:18:09 -03:00
return af9015_ctrl_msg ( d , & req ) ;
}
2012-06-07 20:36:35 -03:00
static int af9015_write_reg ( struct dvb_usb_device * d , u16 addr , u8 val )
{
return af9015_write_regs ( d , addr , & val , 1 ) ;
}
2010-10-22 18:45:18 -03:00
static int af9015_read_reg ( struct dvb_usb_device * d , u16 addr , u8 * val )
{
return af9015_read_regs ( d , addr , val , 1 ) ;
}
2008-09-15 17:18:09 -03:00
static int af9015_write_reg_i2c ( struct dvb_usb_device * d , u8 addr , u16 reg ,
u8 val )
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2008-09-15 17:18:09 -03:00
struct req_t req = { WRITE_I2C , addr , reg , 1 , 1 , 1 , & val } ;
2012-06-07 20:36:35 -03:00
if ( addr = = state - > af9013_config [ 0 ] . i2c_addr | |
addr = = state - > af9013_config [ 1 ] . i2c_addr )
2008-09-15 17:18:09 -03:00
req . addr_len = 3 ;
return af9015_ctrl_msg ( d , & req ) ;
}
static int af9015_read_reg_i2c ( struct dvb_usb_device * d , u8 addr , u16 reg ,
u8 * val )
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2008-09-15 17:18:09 -03:00
struct req_t req = { READ_I2C , addr , reg , 0 , 1 , 1 , val } ;
2012-06-07 20:36:35 -03:00
if ( addr = = state - > af9013_config [ 0 ] . i2c_addr | |
addr = = state - > af9013_config [ 1 ] . i2c_addr )
2008-09-15 17:18:09 -03:00
req . addr_len = 3 ;
return af9015_ctrl_msg ( d , & req ) ;
}
2012-06-07 20:36:35 -03:00
static int af9015_do_reg_bit ( struct dvb_usb_device * d , u16 addr , u8 bit , u8 op )
{
int ret ;
u8 val , mask = 0x01 ;
ret = af9015_read_reg ( d , addr , & val ) ;
if ( ret )
return ret ;
mask < < = bit ;
if ( op ) {
/* set bit */
val | = mask ;
} else {
/* clear bit */
mask ^ = 0xff ;
val & = mask ;
}
return af9015_write_reg ( d , addr , val ) ;
}
static int af9015_set_reg_bit ( struct dvb_usb_device * d , u16 addr , u8 bit )
{
return af9015_do_reg_bit ( d , addr , bit , 1 ) ;
}
static int af9015_clear_reg_bit ( struct dvb_usb_device * d , u16 addr , u8 bit )
{
return af9015_do_reg_bit ( d , addr , bit , 0 ) ;
}
2008-09-15 17:18:09 -03:00
static int af9015_i2c_xfer ( struct i2c_adapter * adap , struct i2c_msg msg [ ] ,
int num )
{
struct dvb_usb_device * d = i2c_get_adapdata ( adap ) ;
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2008-09-15 17:18:09 -03:00
int ret = 0 , i = 0 ;
u16 addr ;
2010-10-07 21:46:41 -03:00
u8 uninitialized_var ( mbox ) , addr_len ;
2008-09-15 17:18:09 -03:00
struct req_t req ;
2012-05-08 06:04:24 -03:00
/*
2008-09-15 17:18:09 -03:00
The bus lock is needed because there is two tuners both using same I2C - address .
Due to that the only way to select correct tuner is use demodulator I2C - gate .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. AF9015 includes integrated AF9013 demodulator .
. ____________ ____________ . ____________
. | uC | | demod | . | tuner |
. | - - - - - - - - - - - - | | - - - - - - - - - - - - | . | - - - - - - - - - - - - |
. | AF9015 | | AF9013 / 5 | . | MXL5003 |
. | | - - + - - - - I2C - - - - - - - | - - - - - / - - - - - | - . - - - - - I2C - - - - - - - | |
. | | | | addr 0x38 | . | addr 0xc6 |
. | ____________ | | | ____________ | . | ____________ |
. . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
| ____________ ____________
| | demod | | tuner |
| | - - - - - - - - - - - - | | - - - - - - - - - - - - |
| | AF9013 | | MXL5003 |
+ - - - - I2C - - - - - - - | - - - - - / - - - - - | - - - - - - - I2C - - - - - - - | |
| addr 0x3a | | addr 0xc6 |
| ____________ | | ____________ |
*/
if ( mutex_lock_interruptible ( & d - > i2c_mutex ) < 0 )
return - EAGAIN ;
while ( i < num ) {
2012-06-07 20:36:35 -03:00
if ( msg [ i ] . addr = = state - > af9013_config [ 0 ] . i2c_addr | |
msg [ i ] . addr = = state - > af9013_config [ 1 ] . i2c_addr ) {
2008-09-15 17:18:09 -03:00
addr = msg [ i ] . buf [ 0 ] < < 8 ;
addr + = msg [ i ] . buf [ 1 ] ;
mbox = msg [ i ] . buf [ 2 ] ;
addr_len = 3 ;
} else {
addr = msg [ i ] . buf [ 0 ] ;
addr_len = 1 ;
2010-10-07 21:46:41 -03:00
/* mbox is don't care in that case */
2008-09-15 17:18:09 -03:00
}
if ( num > i + 1 & & ( msg [ i + 1 ] . flags & I2C_M_RD ) ) {
2011-06-17 21:16:38 -03:00
if ( msg [ i ] . len > 3 | | msg [ i + 1 ] . len > 61 ) {
ret = - EOPNOTSUPP ;
goto error ;
}
2012-06-07 20:36:35 -03:00
if ( msg [ i ] . addr = = state - > af9013_config [ 0 ] . i2c_addr )
2008-09-15 17:18:09 -03:00
req . cmd = READ_MEMORY ;
else
req . cmd = READ_I2C ;
req . i2c_addr = msg [ i ] . addr ;
req . addr = addr ;
req . mbox = mbox ;
req . addr_len = addr_len ;
req . data_len = msg [ i + 1 ] . len ;
req . data = & msg [ i + 1 ] . buf [ 0 ] ;
ret = af9015_ctrl_msg ( d , & req ) ;
i + = 2 ;
2009-02-02 14:59:50 -03:00
} else if ( msg [ i ] . flags & I2C_M_RD ) {
2011-06-17 21:16:38 -03:00
if ( msg [ i ] . len > 61 ) {
ret = - EOPNOTSUPP ;
goto error ;
}
2012-06-07 20:36:35 -03:00
if ( msg [ i ] . addr = = state - > af9013_config [ 0 ] . i2c_addr ) {
2011-06-16 20:02:41 -03:00
ret = - EINVAL ;
2009-02-02 14:59:50 -03:00
goto error ;
2011-06-16 20:02:41 -03:00
}
req . cmd = READ_I2C ;
2009-02-02 14:59:50 -03:00
req . i2c_addr = msg [ i ] . addr ;
req . addr = addr ;
req . mbox = mbox ;
req . addr_len = addr_len ;
req . data_len = msg [ i ] . len ;
req . data = & msg [ i ] . buf [ 0 ] ;
ret = af9015_ctrl_msg ( d , & req ) ;
i + = 1 ;
2008-09-15 17:18:09 -03:00
} else {
2011-06-17 21:16:38 -03:00
if ( msg [ i ] . len > 21 ) {
ret = - EOPNOTSUPP ;
goto error ;
}
2012-06-07 20:36:35 -03:00
if ( msg [ i ] . addr = = state - > af9013_config [ 0 ] . i2c_addr )
2008-09-15 17:18:09 -03:00
req . cmd = WRITE_MEMORY ;
else
req . cmd = WRITE_I2C ;
req . i2c_addr = msg [ i ] . addr ;
req . addr = addr ;
req . mbox = mbox ;
req . addr_len = addr_len ;
req . data_len = msg [ i ] . len - addr_len ;
req . data = & msg [ i ] . buf [ addr_len ] ;
ret = af9015_ctrl_msg ( d , & req ) ;
i + = 1 ;
}
if ( ret )
goto error ;
}
ret = i ;
error :
mutex_unlock ( & d - > i2c_mutex ) ;
return ret ;
}
static u32 af9015_i2c_func ( struct i2c_adapter * adapter )
{
return I2C_FUNC_I2C ;
}
static struct i2c_algorithm af9015_i2c_algo = {
. master_xfer = af9015_i2c_xfer ,
. functionality = af9015_i2c_func ,
} ;
2012-06-18 23:42:53 -03:00
static int af9015_identify_state ( struct dvb_usb_device * d , const char * * name )
2008-09-15 17:18:09 -03:00
{
int ret ;
2012-06-07 20:36:35 -03:00
u8 reply ;
struct req_t req = { GET_CONFIG , 0 , 0 , 0 , 0 , 1 , & reply } ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
ret = af9015_ctrl_msg ( d , & req ) ;
2008-09-15 17:18:09 -03:00
if ( ret )
return ret ;
2012-06-07 20:36:35 -03:00
deb_info ( " %s: reply:%02x \n " , __func__ , reply ) ;
if ( reply = = 0x02 )
ret = WARM ;
else
ret = COLD ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
return ret ;
2008-09-15 17:18:09 -03:00
}
2012-06-07 20:36:35 -03:00
static int af9015_download_firmware ( struct dvb_usb_device * d ,
const struct firmware * fw )
2008-09-15 17:18:09 -03:00
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2012-06-07 20:36:35 -03:00
int i , len , remaining , ret ;
struct req_t req = { DOWNLOAD_FIRMWARE , 0 , 0 , 0 , 0 , 0 , NULL } ;
u16 checksum = 0 ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
deb_info ( " %s: \n " , __func__ ) ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
/* calc checksum */
for ( i = 0 ; i < fw - > size ; i + + )
checksum + = fw - > data [ i ] ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
state - > firmware_size = fw - > size ;
state - > firmware_checksum = checksum ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
# define FW_ADDR 0x5100 /* firmware start address */
# define LEN_MAX 55 /* max packet size */
for ( remaining = fw - > size ; remaining > 0 ; remaining - = LEN_MAX ) {
len = remaining ;
if ( len > LEN_MAX )
len = LEN_MAX ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
req . data_len = len ;
req . data = ( u8 * ) & fw - > data [ fw - > size - remaining ] ;
req . addr = FW_ADDR + fw - > size - remaining ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
ret = af9015_ctrl_msg ( d , & req ) ;
if ( ret ) {
err ( " firmware download failed:%d " , ret ) ;
goto error ;
}
2008-09-15 17:18:09 -03:00
}
2012-06-07 20:36:35 -03:00
/* firmware loaded, request boot */
req . cmd = BOOT ;
req . data_len = 0 ;
ret = af9015_ctrl_msg ( d , & req ) ;
if ( ret ) {
err ( " firmware boot failed:%d " , ret ) ;
2008-09-15 17:18:09 -03:00
goto error ;
}
2012-06-07 20:36:35 -03:00
error :
return ret ;
}
/* hash (and dump) eeprom */
static int af9015_eeprom_hash ( struct dvb_usb_device * d )
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2012-06-07 20:36:35 -03:00
int ret ;
static const unsigned int eeprom_size = 256 ;
unsigned int reg ;
u8 val , * eeprom ;
struct req_t req = { READ_I2C , AF9015_I2C_EEPROM , 0 , 0 , 1 , 1 , & val } ;
eeprom = kmalloc ( eeprom_size , GFP_KERNEL ) ;
if ( eeprom = = NULL )
return - ENOMEM ;
for ( reg = 0 ; reg < eeprom_size ; reg + + ) {
req . addr = reg ;
ret = af9015_ctrl_msg ( d , & req ) ;
2008-09-15 17:18:09 -03:00
if ( ret )
2012-06-07 20:36:35 -03:00
goto free ;
eeprom [ reg ] = val ;
2008-09-15 17:18:09 -03:00
}
2012-06-07 20:36:35 -03:00
if ( dvb_usb_af9015_debug & 0x01 )
print_hex_dump_bytes ( " " , DUMP_PREFIX_OFFSET , eeprom ,
eeprom_size ) ;
BUG_ON ( eeprom_size % 4 ) ;
state - > eeprom_sum = 0 ;
for ( reg = 0 ; reg < eeprom_size / sizeof ( u32 ) ; reg + + ) {
state - > eeprom_sum * = GOLDEN_RATIO_PRIME_32 ;
state - > eeprom_sum + = le32_to_cpu ( ( ( u32 * ) eeprom ) [ reg ] ) ;
2008-09-15 17:18:09 -03:00
}
2012-06-07 20:36:35 -03:00
deb_info ( " %s: eeprom sum=%.8x \n " , __func__ , state - > eeprom_sum ) ;
2011-03-18 19:36:42 -03:00
2012-06-07 20:36:35 -03:00
ret = 0 ;
free :
kfree ( eeprom ) ;
2008-09-15 17:18:09 -03:00
return ret ;
}
2012-06-07 20:36:35 -03:00
static int af9015_read_config ( struct dvb_usb_device * d )
2008-09-15 17:18:09 -03:00
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2008-09-15 17:18:09 -03:00
int ret ;
2012-06-07 20:36:35 -03:00
u8 val , i , offset = 0 ;
struct req_t req = { READ_I2C , AF9015_I2C_EEPROM , 0 , 0 , 1 , 1 , & val } ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
deb_info ( " %s: \n " , __func__ ) ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
/* IR remote controller */
req . addr = AF9015_EEPROM_IR_MODE ;
/* first message will timeout often due to possible hw bug */
for ( i = 0 ; i < 4 ; i + + ) {
ret = af9015_ctrl_msg ( d , & req ) ;
if ( ! ret )
break ;
}
if ( ret )
goto error ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
ret = af9015_eeprom_hash ( d ) ;
2008-09-15 17:18:09 -03:00
if ( ret )
goto error ;
2012-06-07 20:36:35 -03:00
deb_info ( " %s: IR mode=%d \n " , __func__ , val ) ;
state - > ir_mode = val ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
/* TS mode - one or two receivers */
req . addr = AF9015_EEPROM_TS_MODE ;
2008-09-15 17:18:09 -03:00
ret = af9015_ctrl_msg ( d , & req ) ;
if ( ret )
goto error ;
2010-01-22 12:10:52 -03:00
2012-06-07 20:36:35 -03:00
state - > dual_mode = val ;
deb_info ( " %s: TS mode=%d \n " , __func__ , state - > dual_mode ) ;
2010-01-22 12:10:52 -03:00
2012-06-07 20:36:35 -03:00
/* disable 2nd adapter because we don't have PID-filters */
if ( d - > udev - > speed = = USB_SPEED_FULL )
state - > dual_mode = 0 ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
if ( state - > dual_mode ) {
2008-09-15 17:18:09 -03:00
/* read 2nd demodulator I2C address */
req . addr = AF9015_EEPROM_DEMOD2_I2C ;
2012-06-07 20:36:35 -03:00
ret = af9015_ctrl_msg ( d , & req ) ;
2008-09-15 17:18:09 -03:00
if ( ret )
goto error ;
2012-06-07 20:36:35 -03:00
state - > af9013_config [ 1 ] . i2c_addr = val ;
2008-09-15 17:18:09 -03:00
}
2012-06-07 20:36:35 -03:00
for ( i = 0 ; i < state - > dual_mode + 1 ; i + + ) {
2008-09-15 17:18:09 -03:00
if ( i = = 1 )
offset = AF9015_EEPROM_OFFSET ;
/* xtal */
req . addr = AF9015_EEPROM_XTAL_TYPE1 + offset ;
2012-06-07 20:36:35 -03:00
ret = af9015_ctrl_msg ( d , & req ) ;
2008-09-15 17:18:09 -03:00
if ( ret )
goto error ;
switch ( val ) {
case 0 :
2012-06-07 20:36:35 -03:00
state - > af9013_config [ i ] . clock = 28800000 ;
2008-09-15 17:18:09 -03:00
break ;
case 1 :
2012-06-07 20:36:35 -03:00
state - > af9013_config [ i ] . clock = 20480000 ;
2008-09-15 17:18:09 -03:00
break ;
case 2 :
2012-06-07 20:36:35 -03:00
state - > af9013_config [ i ] . clock = 28000000 ;
2008-09-15 17:18:09 -03:00
break ;
case 3 :
2012-06-07 20:36:35 -03:00
state - > af9013_config [ i ] . clock = 25000000 ;
2008-09-15 17:18:09 -03:00
break ;
} ;
2011-11-28 20:58:11 -03:00
deb_info ( " %s: [%d] xtal=%d set clock=%d \n " , __func__ , i ,
2012-06-07 20:36:35 -03:00
val , state - > af9013_config [ i ] . clock ) ;
2008-09-15 17:18:09 -03:00
2011-11-28 20:58:11 -03:00
/* IF frequency */
2008-09-15 17:18:09 -03:00
req . addr = AF9015_EEPROM_IF1H + offset ;
2012-06-07 20:36:35 -03:00
ret = af9015_ctrl_msg ( d , & req ) ;
2008-09-15 17:18:09 -03:00
if ( ret )
goto error ;
2011-11-28 20:58:11 -03:00
2012-06-07 20:36:35 -03:00
state - > af9013_config [ i ] . if_frequency = val < < 8 ;
2011-11-28 20:58:11 -03:00
2008-09-15 17:18:09 -03:00
req . addr = AF9015_EEPROM_IF1L + offset ;
2012-06-07 20:36:35 -03:00
ret = af9015_ctrl_msg ( d , & req ) ;
2008-09-15 17:18:09 -03:00
if ( ret )
goto error ;
2011-11-28 20:58:11 -03:00
2012-06-07 20:36:35 -03:00
state - > af9013_config [ i ] . if_frequency + = val ;
state - > af9013_config [ i ] . if_frequency * = 1000 ;
2011-11-28 20:58:11 -03:00
deb_info ( " %s: [%d] IF frequency=%d \n " , __func__ , i ,
2012-06-07 20:36:35 -03:00
state - > af9013_config [ i ] . if_frequency ) ;
2008-09-15 17:18:09 -03:00
/* MT2060 IF1 */
req . addr = AF9015_EEPROM_MT2060_IF1H + offset ;
2012-06-07 20:36:35 -03:00
ret = af9015_ctrl_msg ( d , & req ) ;
2008-09-15 17:18:09 -03:00
if ( ret )
goto error ;
2012-06-07 20:36:35 -03:00
state - > mt2060_if1 [ i ] = val < < 8 ;
2008-09-15 17:18:09 -03:00
req . addr = AF9015_EEPROM_MT2060_IF1L + offset ;
2012-06-07 20:36:35 -03:00
ret = af9015_ctrl_msg ( d , & req ) ;
2008-09-15 17:18:09 -03:00
if ( ret )
goto error ;
2012-06-07 20:36:35 -03:00
state - > mt2060_if1 [ i ] + = val ;
2011-11-28 20:58:11 -03:00
deb_info ( " %s: [%d] MT2060 IF1=%d \n " , __func__ , i ,
2012-06-07 20:36:35 -03:00
state - > mt2060_if1 [ i ] ) ;
2008-09-15 17:18:09 -03:00
/* tuner */
req . addr = AF9015_EEPROM_TUNER_ID1 + offset ;
2012-06-07 20:36:35 -03:00
ret = af9015_ctrl_msg ( d , & req ) ;
2008-09-15 17:18:09 -03:00
if ( ret )
goto error ;
switch ( val ) {
case AF9013_TUNER_ENV77H11D5 :
case AF9013_TUNER_MT2060 :
case AF9013_TUNER_QT1010 :
case AF9013_TUNER_UNKNOWN :
case AF9013_TUNER_MT2060_2 :
case AF9013_TUNER_TDA18271 :
case AF9013_TUNER_QT1010A :
2010-08-13 03:51:26 -03:00
case AF9013_TUNER_TDA18218 :
2012-06-07 20:36:35 -03:00
state - > af9013_config [ i ] . spec_inv = 1 ;
2008-09-15 17:18:09 -03:00
break ;
case AF9013_TUNER_MXL5003D :
case AF9013_TUNER_MXL5005D :
case AF9013_TUNER_MXL5005R :
2010-09-09 14:59:10 -03:00
case AF9013_TUNER_MXL5007T :
2012-06-07 20:36:35 -03:00
state - > af9013_config [ i ] . spec_inv = 0 ;
2008-09-15 17:18:09 -03:00
break ;
2009-02-02 14:59:50 -03:00
case AF9013_TUNER_MC44S803 :
2012-06-07 20:36:35 -03:00
state - > af9013_config [ i ] . gpio [ 1 ] = AF9013_GPIO_LO ;
state - > af9013_config [ i ] . spec_inv = 1 ;
2009-02-02 14:59:50 -03:00
break ;
2008-09-15 17:18:09 -03:00
default :
2011-11-28 20:58:11 -03:00
warn ( " tuner id=%d not supported, please report! " , val ) ;
2008-09-15 17:18:09 -03:00
return - ENODEV ;
} ;
2012-06-07 20:36:35 -03:00
state - > af9013_config [ i ] . tuner = val ;
2011-11-28 20:58:11 -03:00
deb_info ( " %s: [%d] tuner id=%d \n " , __func__ , i , val ) ;
2008-09-15 17:18:09 -03:00
}
error :
if ( ret )
2011-11-28 20:58:11 -03:00
err ( " eeprom read failed=%d " , ret ) ;
2008-09-15 17:18:09 -03:00
2009-03-31 17:01:02 -03:00
/* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM
2010-10-01 16:55:43 -03:00
content : - ( Override some wrong values here . Ditto for the
AVerTV Red HD + ( A850T ) device . */
2012-06-07 20:36:35 -03:00
if ( le16_to_cpu ( d - > udev - > descriptor . idVendor ) = = USB_VID_AVERMEDIA & &
( ( le16_to_cpu ( d - > udev - > descriptor . idProduct ) = =
2010-10-07 21:37:06 -03:00
USB_PID_AVERMEDIA_A850 ) | |
2012-06-07 20:36:35 -03:00
( le16_to_cpu ( d - > udev - > descriptor . idProduct ) = =
2010-10-07 21:37:06 -03:00
USB_PID_AVERMEDIA_A850T ) ) ) {
2009-03-31 17:01:02 -03:00
deb_info ( " %s: AverMedia A850: overriding config \n " , __func__ ) ;
/* disable dual mode */
2012-06-07 20:36:35 -03:00
state - > dual_mode = 0 ;
2009-03-31 17:01:02 -03:00
/* set correct IF */
2012-06-07 20:36:35 -03:00
state - > af9013_config [ 0 ] . if_frequency = 4570000 ;
2009-03-31 17:01:02 -03:00
}
2008-09-15 17:18:09 -03:00
return ret ;
}
2012-06-18 22:54:16 -03:00
static int af9015_get_stream_config ( struct dvb_frontend * fe , u8 * ts_type ,
2012-06-07 20:36:35 -03:00
struct usb_data_stream_properties * stream )
2008-09-15 17:18:09 -03:00
{
2012-06-16 18:13:06 -03:00
deb_info ( " %s: adap=%d \n " , __func__ , fe_to_adap ( fe ) - > id ) ;
2010-09-12 13:31:56 -03:00
2012-06-16 18:13:06 -03:00
if ( fe_to_d ( fe ) - > udev - > speed = = USB_SPEED_FULL )
2012-06-07 20:36:35 -03:00
stream - > u . bulk . buffersize = TS_USB11_FRAME_SIZE ;
2011-03-18 19:36:42 -03:00
2012-06-07 20:36:35 -03:00
return 0 ;
}
2010-09-12 13:31:56 -03:00
2012-06-07 20:36:35 -03:00
static int af9015_get_adapter_count ( struct dvb_usb_device * d )
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2012-06-07 20:36:35 -03:00
return state - > dual_mode + 1 ;
2008-09-15 17:18:09 -03:00
}
2011-11-12 22:33:30 -03:00
/* override demod callbacks for resource locking */
2011-12-31 07:03:36 -03:00
static int af9015_af9013_set_frontend ( struct dvb_frontend * fe )
2011-11-12 22:33:30 -03:00
{
int ret ;
2012-06-16 18:13:06 -03:00
struct af9015_state * state = fe_to_priv ( fe ) ;
2011-11-12 22:33:30 -03:00
2012-06-07 20:36:35 -03:00
if ( mutex_lock_interruptible ( & state - > fe_mutex ) )
2011-11-12 22:33:30 -03:00
return - EAGAIN ;
2012-06-16 18:13:06 -03:00
ret = state - > set_frontend [ fe_to_adap ( fe ) - > id ] ( fe ) ;
2011-11-12 22:33:30 -03:00
2012-06-07 20:36:35 -03:00
mutex_unlock ( & state - > fe_mutex ) ;
2011-11-12 22:33:30 -03:00
return ret ;
}
/* override demod callbacks for resource locking */
static int af9015_af9013_read_status ( struct dvb_frontend * fe ,
fe_status_t * status )
{
int ret ;
2012-06-16 18:13:06 -03:00
struct af9015_state * state = fe_to_priv ( fe ) ;
2011-11-12 22:33:30 -03:00
2012-06-07 20:36:35 -03:00
if ( mutex_lock_interruptible ( & state - > fe_mutex ) )
2011-11-12 22:33:30 -03:00
return - EAGAIN ;
2012-06-16 18:13:06 -03:00
ret = state - > read_status [ fe_to_adap ( fe ) - > id ] ( fe , status ) ;
2011-11-12 22:33:30 -03:00
2012-06-07 20:36:35 -03:00
mutex_unlock ( & state - > fe_mutex ) ;
2011-11-12 22:33:30 -03:00
return ret ;
}
/* override demod callbacks for resource locking */
static int af9015_af9013_init ( struct dvb_frontend * fe )
{
int ret ;
2012-06-16 18:13:06 -03:00
struct af9015_state * state = fe_to_priv ( fe ) ;
2011-11-12 22:33:30 -03:00
2012-06-07 20:36:35 -03:00
if ( mutex_lock_interruptible ( & state - > fe_mutex ) )
2011-11-12 22:33:30 -03:00
return - EAGAIN ;
2012-06-16 18:13:06 -03:00
ret = state - > init [ fe_to_adap ( fe ) - > id ] ( fe ) ;
2011-11-12 22:33:30 -03:00
2012-06-07 20:36:35 -03:00
mutex_unlock ( & state - > fe_mutex ) ;
2011-11-12 22:33:30 -03:00
return ret ;
}
/* override demod callbacks for resource locking */
static int af9015_af9013_sleep ( struct dvb_frontend * fe )
{
int ret ;
2012-06-16 18:13:06 -03:00
struct af9015_state * state = fe_to_priv ( fe ) ;
2011-11-12 22:33:30 -03:00
2012-06-07 20:36:35 -03:00
if ( mutex_lock_interruptible ( & state - > fe_mutex ) )
2011-11-12 22:33:30 -03:00
return - EAGAIN ;
2012-06-16 18:13:06 -03:00
ret = state - > sleep [ fe_to_adap ( fe ) - > id ] ( fe ) ;
2011-11-12 22:33:30 -03:00
2012-06-07 20:36:35 -03:00
mutex_unlock ( & state - > fe_mutex ) ;
2011-11-12 22:33:30 -03:00
return ret ;
}
2012-03-14 10:27:31 -03:00
/* override tuner callbacks for resource locking */
static int af9015_tuner_init ( struct dvb_frontend * fe )
{
int ret ;
2012-06-16 18:13:06 -03:00
struct af9015_state * state = fe_to_priv ( fe ) ;
2012-03-14 10:27:31 -03:00
2012-06-07 20:36:35 -03:00
if ( mutex_lock_interruptible ( & state - > fe_mutex ) )
2012-03-14 10:27:31 -03:00
return - EAGAIN ;
2012-06-16 18:13:06 -03:00
ret = state - > tuner_init [ fe_to_adap ( fe ) - > id ] ( fe ) ;
2012-03-14 10:27:31 -03:00
2012-06-07 20:36:35 -03:00
mutex_unlock ( & state - > fe_mutex ) ;
2012-03-14 10:27:31 -03:00
return ret ;
}
/* override tuner callbacks for resource locking */
static int af9015_tuner_sleep ( struct dvb_frontend * fe )
{
int ret ;
2012-06-16 18:13:06 -03:00
struct af9015_state * state = fe_to_priv ( fe ) ;
2012-03-14 10:27:31 -03:00
2012-06-07 20:36:35 -03:00
if ( mutex_lock_interruptible ( & state - > fe_mutex ) )
2012-03-14 10:27:31 -03:00
return - EAGAIN ;
2012-06-16 18:13:06 -03:00
ret = state - > tuner_sleep [ fe_to_adap ( fe ) - > id ] ( fe ) ;
2012-06-07 20:36:35 -03:00
mutex_unlock ( & state - > fe_mutex ) ;
return ret ;
}
static int af9015_copy_firmware ( struct dvb_usb_device * d )
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2012-06-07 20:36:35 -03:00
int ret ;
u8 fw_params [ 4 ] ;
u8 val , i ;
struct req_t req = { COPY_FIRMWARE , 0 , 0x5100 , 0 , 0 , sizeof ( fw_params ) ,
fw_params } ;
deb_info ( " %s: \n " , __func__ ) ;
fw_params [ 0 ] = state - > firmware_size > > 8 ;
fw_params [ 1 ] = state - > firmware_size & 0xff ;
fw_params [ 2 ] = state - > firmware_checksum > > 8 ;
fw_params [ 3 ] = state - > firmware_checksum & 0xff ;
/* wait 2nd demodulator ready */
msleep ( 100 ) ;
ret = af9015_read_reg_i2c ( d , state - > af9013_config [ 1 ] . i2c_addr ,
0x98be , & val ) ;
if ( ret )
goto error ;
else
deb_info ( " %s: firmware status:%02x \n " , __func__ , val ) ;
if ( val = = 0x0c ) /* fw is running, no need for download */
goto exit ;
/* set I2C master clock to fast (to speed up firmware copy) */
ret = af9015_write_reg ( d , 0xd416 , 0x04 ) ; /* 0x04 * 400ns */
if ( ret )
goto error ;
msleep ( 50 ) ;
/* copy firmware */
ret = af9015_ctrl_msg ( d , & req ) ;
if ( ret )
err ( " firmware copy cmd failed:%d " , ret ) ;
deb_info ( " %s: firmware copy done \n " , __func__ ) ;
/* set I2C master clock back to normal */
ret = af9015_write_reg ( d , 0xd416 , 0x14 ) ; /* 0x14 * 400ns */
if ( ret )
goto error ;
/* request boot firmware */
ret = af9015_write_reg_i2c ( d , state - > af9013_config [ 1 ] . i2c_addr ,
0xe205 , 1 ) ;
deb_info ( " %s: firmware boot cmd status:%d \n " , __func__ , ret ) ;
if ( ret )
goto error ;
for ( i = 0 ; i < 15 ; i + + ) {
msleep ( 100 ) ;
2012-03-14 10:27:31 -03:00
2012-06-07 20:36:35 -03:00
/* check firmware status */
ret = af9015_read_reg_i2c ( d , state - > af9013_config [ 1 ] . i2c_addr ,
0x98be , & val ) ;
deb_info ( " %s: firmware status cmd status:%d fw status:%02x \n " ,
__func__ , ret , val ) ;
if ( ret )
goto error ;
2012-03-14 10:27:31 -03:00
2012-06-07 20:36:35 -03:00
if ( val = = 0x0c | | val = = 0x04 ) /* success or fail */
break ;
}
if ( val = = 0x04 ) {
err ( " firmware did not run " ) ;
ret = - 1 ;
} else if ( val ! = 0x0c ) {
err ( " firmware boot timeout " ) ;
ret = - 1 ;
}
error :
exit :
2012-03-14 10:27:31 -03:00
return ret ;
}
2008-09-15 17:18:09 -03:00
static int af9015_af9013_frontend_attach ( struct dvb_usb_adapter * adap )
{
int ret ;
2012-06-16 18:13:06 -03:00
struct af9015_state * state = adap_to_priv ( adap ) ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
if ( adap - > id = = 0 ) {
state - > af9013_config [ 0 ] . ts_mode = AF9013_TS_USB ;
memcpy ( state - > af9013_config [ 0 ] . api_version , " \ x0 \ x1 \ x9 \ x0 " , 4 ) ;
state - > af9013_config [ 0 ] . gpio [ 0 ] = AF9013_GPIO_HI ;
state - > af9013_config [ 0 ] . gpio [ 3 ] = AF9013_GPIO_TUNER_ON ;
} else if ( adap - > id = = 1 ) {
state - > af9013_config [ 1 ] . ts_mode = AF9013_TS_SERIAL ;
memcpy ( state - > af9013_config [ 1 ] . api_version , " \ x0 \ x1 \ x9 \ x0 " , 4 ) ;
state - > af9013_config [ 1 ] . gpio [ 0 ] = AF9013_GPIO_TUNER_ON ;
state - > af9013_config [ 1 ] . gpio [ 1 ] = AF9013_GPIO_LO ;
2008-09-15 17:18:09 -03:00
/* copy firmware to 2nd demodulator */
2012-06-07 20:36:35 -03:00
if ( state - > dual_mode ) {
2012-06-16 18:13:06 -03:00
ret = af9015_copy_firmware ( adap_to_d ( adap ) ) ;
2008-09-15 17:18:09 -03:00
if ( ret ) {
err ( " firmware copy to 2nd frontend " \
" failed, will disable it " ) ;
2012-06-07 20:36:35 -03:00
state - > dual_mode = 0 ;
2008-09-15 17:18:09 -03:00
return - ENODEV ;
}
} else {
return - ENODEV ;
}
}
/* attach demodulator */
2012-06-07 20:36:35 -03:00
adap - > fe [ 0 ] = dvb_attach ( af9013_attach ,
2012-06-16 18:13:06 -03:00
& state - > af9013_config [ adap - > id ] , & adap_to_d ( adap ) - > i2c_adap ) ;
2008-09-15 17:18:09 -03:00
2011-11-12 22:33:30 -03:00
/*
* AF9015 firmware does not like if it gets interrupted by I2C adapter
* request on some critical phases . During normal operation I2C adapter
* is used only 2 nd demodulator and tuner on dual tuner devices .
* Override demodulator callbacks and use mutex for limit access to
* those " critical " paths to keep AF9015 happy .
*/
2012-06-07 20:36:35 -03:00
if ( adap - > fe [ 0 ] ) {
2011-11-12 22:33:30 -03:00
state - > set_frontend [ adap - > id ] =
2012-06-07 20:36:35 -03:00
adap - > fe [ 0 ] - > ops . set_frontend ;
adap - > fe [ 0 ] - > ops . set_frontend =
2011-11-12 22:33:30 -03:00
af9015_af9013_set_frontend ;
state - > read_status [ adap - > id ] =
2012-06-07 20:36:35 -03:00
adap - > fe [ 0 ] - > ops . read_status ;
adap - > fe [ 0 ] - > ops . read_status =
2011-11-12 22:33:30 -03:00
af9015_af9013_read_status ;
2012-06-07 20:36:35 -03:00
state - > init [ adap - > id ] = adap - > fe [ 0 ] - > ops . init ;
adap - > fe [ 0 ] - > ops . init = af9015_af9013_init ;
2011-11-12 22:33:30 -03:00
2012-06-07 20:36:35 -03:00
state - > sleep [ adap - > id ] = adap - > fe [ 0 ] - > ops . sleep ;
adap - > fe [ 0 ] - > ops . sleep = af9015_af9013_sleep ;
2011-11-12 22:33:30 -03:00
}
2012-06-07 20:36:35 -03:00
return adap - > fe [ 0 ] = = NULL ? - ENODEV : 0 ;
2008-09-15 17:18:09 -03:00
}
static struct mt2060_config af9015_mt2060_config = {
. i2c_address = 0xc0 ,
. clock_out = 0 ,
} ;
static struct qt1010_config af9015_qt1010_config = {
. i2c_address = 0xc4 ,
} ;
static struct tda18271_config af9015_tda18271_config = {
. gate = TDA18271_GATE_DIGITAL ,
2010-10-27 14:55:34 -02:00
. small_i2c = TDA18271_16_BYTE_CHUNK_INIT ,
2008-09-15 17:18:09 -03:00
} ;
static struct mxl5005s_config af9015_mxl5003_config = {
. i2c_address = 0xc6 ,
. if_freq = IF_FREQ_4570000HZ ,
. xtal_freq = CRYSTAL_FREQ_16000000HZ ,
. agc_mode = MXL_SINGLE_AGC ,
. tracking_filter = MXL_TF_DEFAULT ,
2008-09-22 13:59:25 -03:00
. rssi_enable = MXL_RSSI_ENABLE ,
2008-09-15 17:18:09 -03:00
. cap_select = MXL_CAP_SEL_ENABLE ,
. div_out = MXL_DIV_OUT_4 ,
. clock_out = MXL_CLOCK_OUT_DISABLE ,
. output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM ,
. top = MXL5005S_TOP_25P2 ,
. mod_mode = MXL_DIGITAL_MODE ,
. if_mode = MXL_ZERO_IF ,
. AgcMasterByte = 0x00 ,
} ;
static struct mxl5005s_config af9015_mxl5005_config = {
. i2c_address = 0xc6 ,
. if_freq = IF_FREQ_4570000HZ ,
. xtal_freq = CRYSTAL_FREQ_16000000HZ ,
. agc_mode = MXL_SINGLE_AGC ,
. tracking_filter = MXL_TF_OFF ,
2008-09-22 13:59:25 -03:00
. rssi_enable = MXL_RSSI_ENABLE ,
2008-09-15 17:18:09 -03:00
. cap_select = MXL_CAP_SEL_ENABLE ,
. div_out = MXL_DIV_OUT_4 ,
. clock_out = MXL_CLOCK_OUT_DISABLE ,
. output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM ,
. top = MXL5005S_TOP_25P2 ,
. mod_mode = MXL_DIGITAL_MODE ,
. if_mode = MXL_ZERO_IF ,
. AgcMasterByte = 0x00 ,
} ;
2009-02-02 14:59:50 -03:00
static struct mc44s803_config af9015_mc44s803_config = {
. i2c_address = 0xc0 ,
. dig_out = 1 ,
} ;
2010-08-13 03:51:26 -03:00
static struct tda18218_config af9015_tda18218_config = {
. i2c_address = 0xc0 ,
. i2c_wr_max = 21 , /* max wr bytes AF9015 I2C adap can handle at once */
} ;
2010-09-09 14:59:10 -03:00
static struct mxl5007t_config af9015_mxl5007t_config = {
. xtal_freq_hz = MxL_XTAL_24_MHZ ,
. if_freq_hz = MxL_IF_4_57_MHZ ,
} ;
2008-09-15 17:18:09 -03:00
static int af9015_tuner_attach ( struct dvb_usb_adapter * adap )
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = adap_to_priv ( adap ) ;
2012-06-07 20:36:35 -03:00
int ret ;
2010-10-07 21:37:06 -03:00
deb_info ( " %s: \n " , __func__ ) ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
switch ( state - > af9013_config [ adap - > id ] . tuner ) {
2008-09-15 17:18:09 -03:00
case AF9013_TUNER_MT2060 :
case AF9013_TUNER_MT2060_2 :
2012-06-07 20:36:35 -03:00
ret = dvb_attach ( mt2060_attach , adap - > fe [ 0 ] ,
2012-06-16 18:13:06 -03:00
& adap_to_d ( adap ) - > i2c_adap , & af9015_mt2060_config ,
2012-06-07 20:36:35 -03:00
state - > mt2060_if1 [ adap - > id ] )
2008-09-15 17:18:09 -03:00
= = NULL ? - ENODEV : 0 ;
break ;
case AF9013_TUNER_QT1010 :
case AF9013_TUNER_QT1010A :
2012-06-07 20:36:35 -03:00
ret = dvb_attach ( qt1010_attach , adap - > fe [ 0 ] ,
2012-06-16 18:13:06 -03:00
& adap_to_d ( adap ) - > i2c_adap ,
2008-09-15 17:18:09 -03:00
& af9015_qt1010_config ) = = NULL ? - ENODEV : 0 ;
break ;
case AF9013_TUNER_TDA18271 :
2012-06-07 20:36:35 -03:00
ret = dvb_attach ( tda18271_attach , adap - > fe [ 0 ] , 0xc0 ,
2012-06-16 18:13:06 -03:00
& adap_to_d ( adap ) - > i2c_adap ,
2008-09-15 17:18:09 -03:00
& af9015_tda18271_config ) = = NULL ? - ENODEV : 0 ;
break ;
2010-08-13 03:51:26 -03:00
case AF9013_TUNER_TDA18218 :
2012-06-07 20:36:35 -03:00
ret = dvb_attach ( tda18218_attach , adap - > fe [ 0 ] ,
2012-06-16 18:13:06 -03:00
& adap_to_d ( adap ) - > i2c_adap ,
2010-08-13 03:51:26 -03:00
& af9015_tda18218_config ) = = NULL ? - ENODEV : 0 ;
break ;
2008-09-15 17:18:09 -03:00
case AF9013_TUNER_MXL5003D :
2012-06-07 20:36:35 -03:00
ret = dvb_attach ( mxl5005s_attach , adap - > fe [ 0 ] ,
2012-06-16 18:13:06 -03:00
& adap_to_d ( adap ) - > i2c_adap ,
2008-09-15 17:18:09 -03:00
& af9015_mxl5003_config ) = = NULL ? - ENODEV : 0 ;
break ;
case AF9013_TUNER_MXL5005D :
case AF9013_TUNER_MXL5005R :
2012-06-07 20:36:35 -03:00
ret = dvb_attach ( mxl5005s_attach , adap - > fe [ 0 ] ,
2012-06-16 18:13:06 -03:00
& adap_to_d ( adap ) - > i2c_adap ,
2008-09-15 17:18:09 -03:00
& af9015_mxl5005_config ) = = NULL ? - ENODEV : 0 ;
break ;
case AF9013_TUNER_ENV77H11D5 :
2012-06-07 20:36:35 -03:00
ret = dvb_attach ( dvb_pll_attach , adap - > fe [ 0 ] , 0xc0 ,
2012-06-16 18:13:06 -03:00
& adap_to_d ( adap ) - > i2c_adap ,
2008-09-15 17:18:09 -03:00
DVB_PLL_TDA665X ) = = NULL ? - ENODEV : 0 ;
break ;
case AF9013_TUNER_MC44S803 :
2012-06-07 20:36:35 -03:00
ret = dvb_attach ( mc44s803_attach , adap - > fe [ 0 ] ,
2012-06-16 18:13:06 -03:00
& adap_to_d ( adap ) - > i2c_adap ,
2009-02-02 14:59:50 -03:00
& af9015_mc44s803_config ) = = NULL ? - ENODEV : 0 ;
2008-09-15 17:18:09 -03:00
break ;
2010-09-09 14:59:10 -03:00
case AF9013_TUNER_MXL5007T :
2012-06-07 20:36:35 -03:00
ret = dvb_attach ( mxl5007t_attach , adap - > fe [ 0 ] ,
2012-06-16 18:13:06 -03:00
& adap_to_d ( adap ) - > i2c_adap ,
2010-09-09 14:59:10 -03:00
0xc0 , & af9015_mxl5007t_config ) = = NULL ? - ENODEV : 0 ;
break ;
2008-09-15 17:18:09 -03:00
case AF9013_TUNER_UNKNOWN :
default :
ret = - ENODEV ;
err ( " Unknown tuner id:%d " ,
2012-06-07 20:36:35 -03:00
state - > af9013_config [ adap - > id ] . tuner ) ;
2008-09-15 17:18:09 -03:00
}
2012-03-14 10:27:30 -03:00
2012-06-07 20:36:35 -03:00
if ( adap - > fe [ 0 ] - > ops . tuner_ops . init ) {
2012-03-14 10:27:31 -03:00
state - > tuner_init [ adap - > id ] =
2012-06-07 20:36:35 -03:00
adap - > fe [ 0 ] - > ops . tuner_ops . init ;
adap - > fe [ 0 ] - > ops . tuner_ops . init = af9015_tuner_init ;
2012-03-14 10:27:31 -03:00
}
2012-06-07 20:36:35 -03:00
if ( adap - > fe [ 0 ] - > ops . tuner_ops . sleep ) {
2012-03-14 10:27:31 -03:00
state - > tuner_sleep [ adap - > id ] =
2012-06-07 20:36:35 -03:00
adap - > fe [ 0 ] - > ops . tuner_ops . sleep ;
adap - > fe [ 0 ] - > ops . tuner_ops . sleep = af9015_tuner_sleep ;
}
return ret ;
}
static int af9015_pid_filter_ctrl ( struct dvb_usb_adapter * adap , int onoff )
{
int ret ;
deb_info ( " %s: onoff:%d \n " , __func__ , onoff ) ;
if ( onoff )
2012-06-16 18:13:06 -03:00
ret = af9015_set_reg_bit ( adap_to_d ( adap ) , 0xd503 , 0 ) ;
2012-06-07 20:36:35 -03:00
else
2012-06-16 18:13:06 -03:00
ret = af9015_clear_reg_bit ( adap_to_d ( adap ) , 0xd503 , 0 ) ;
2012-06-07 20:36:35 -03:00
return ret ;
}
static int af9015_pid_filter ( struct dvb_usb_adapter * adap , int index , u16 pid ,
int onoff )
{
int ret ;
u8 idx ;
deb_info ( " %s: set pid filter, index %d, pid %x, onoff %d \n " ,
__func__ , index , pid , onoff ) ;
2012-06-16 18:13:06 -03:00
ret = af9015_write_reg ( adap_to_d ( adap ) , 0xd505 , ( pid & 0xff ) ) ;
2012-06-07 20:36:35 -03:00
if ( ret )
goto error ;
2012-06-16 18:13:06 -03:00
ret = af9015_write_reg ( adap_to_d ( adap ) , 0xd506 , ( pid > > 8 ) ) ;
2012-06-07 20:36:35 -03:00
if ( ret )
goto error ;
idx = ( ( index & 0x1f ) | ( 1 < < 5 ) ) ;
2012-06-16 18:13:06 -03:00
ret = af9015_write_reg ( adap_to_d ( adap ) , 0xd504 , idx ) ;
2012-06-07 20:36:35 -03:00
error :
return ret ;
}
static int af9015_init_endpoint ( struct dvb_usb_device * d )
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2012-06-07 20:36:35 -03:00
int ret ;
u16 frame_size ;
u8 packet_size ;
deb_info ( " %s: USB speed:%d \n " , __func__ , d - > udev - > speed ) ;
if ( d - > udev - > speed = = USB_SPEED_FULL ) {
frame_size = TS_USB11_FRAME_SIZE / 4 ;
packet_size = TS_USB11_MAX_PACKET_SIZE / 4 ;
} else {
frame_size = TS_USB20_FRAME_SIZE / 4 ;
packet_size = TS_USB20_MAX_PACKET_SIZE / 4 ;
}
ret = af9015_set_reg_bit ( d , 0xd507 , 2 ) ; /* assert EP4 reset */
if ( ret )
goto error ;
ret = af9015_set_reg_bit ( d , 0xd50b , 1 ) ; /* assert EP5 reset */
if ( ret )
goto error ;
ret = af9015_clear_reg_bit ( d , 0xdd11 , 5 ) ; /* disable EP4 */
if ( ret )
goto error ;
ret = af9015_clear_reg_bit ( d , 0xdd11 , 6 ) ; /* disable EP5 */
if ( ret )
goto error ;
ret = af9015_set_reg_bit ( d , 0xdd11 , 5 ) ; /* enable EP4 */
if ( ret )
goto error ;
if ( state - > dual_mode ) {
ret = af9015_set_reg_bit ( d , 0xdd11 , 6 ) ; /* enable EP5 */
if ( ret )
goto error ;
}
ret = af9015_clear_reg_bit ( d , 0xdd13 , 5 ) ; /* disable EP4 NAK */
if ( ret )
goto error ;
if ( state - > dual_mode ) {
ret = af9015_clear_reg_bit ( d , 0xdd13 , 6 ) ; /* disable EP5 NAK */
if ( ret )
goto error ;
}
/* EP4 xfer length */
ret = af9015_write_reg ( d , 0xdd88 , frame_size & 0xff ) ;
if ( ret )
goto error ;
ret = af9015_write_reg ( d , 0xdd89 , frame_size > > 8 ) ;
if ( ret )
goto error ;
/* EP5 xfer length */
ret = af9015_write_reg ( d , 0xdd8a , frame_size & 0xff ) ;
if ( ret )
goto error ;
ret = af9015_write_reg ( d , 0xdd8b , frame_size > > 8 ) ;
if ( ret )
goto error ;
ret = af9015_write_reg ( d , 0xdd0c , packet_size ) ; /* EP4 packet size */
if ( ret )
goto error ;
ret = af9015_write_reg ( d , 0xdd0d , packet_size ) ; /* EP5 packet size */
if ( ret )
goto error ;
ret = af9015_clear_reg_bit ( d , 0xd507 , 2 ) ; /* negate EP4 reset */
if ( ret )
goto error ;
if ( state - > dual_mode ) {
ret = af9015_clear_reg_bit ( d , 0xd50b , 1 ) ; /* negate EP5 reset */
if ( ret )
goto error ;
2012-03-14 10:27:31 -03:00
}
2012-03-14 10:27:30 -03:00
2012-06-07 20:36:35 -03:00
/* enable / disable mp2if2 */
if ( state - > dual_mode )
ret = af9015_set_reg_bit ( d , 0xd50b , 0 ) ;
else
ret = af9015_clear_reg_bit ( d , 0xd50b , 0 ) ;
error :
if ( ret )
err ( " endpoint init failed:%d " , ret ) ;
return ret ;
}
static int af9015_init ( struct dvb_usb_device * d )
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2012-06-07 20:36:35 -03:00
int ret ;
deb_info ( " %s: \n " , __func__ ) ;
mutex_init ( & state - > fe_mutex ) ;
/* init RC canary */
ret = af9015_write_reg ( d , 0x98e9 , 0xff ) ;
if ( ret )
goto error ;
ret = af9015_init_endpoint ( d ) ;
if ( ret )
goto error ;
error :
2008-09-15 17:18:09 -03:00
return ret ;
}
2012-06-07 20:36:35 -03:00
struct af9015_rc_setup {
unsigned int id ;
char * rc_codes ;
2012-01-07 04:11:27 -03:00
} ;
2012-06-07 20:36:35 -03:00
static char * af9015_rc_setup_match ( unsigned int id ,
const struct af9015_rc_setup * table )
{
for ( ; table - > rc_codes ; table + + )
if ( table - > id = = id )
return table - > rc_codes ;
return NULL ;
}
static const struct af9015_rc_setup af9015_rc_setup_modparam [ ] = {
{ AF9015_REMOTE_A_LINK_DTU_M , RC_MAP_ALINK_DTU_M } ,
{ AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3 , RC_MAP_MSI_DIGIVOX_II } ,
{ AF9015_REMOTE_MYGICTV_U718 , RC_MAP_TOTAL_MEDIA_IN_HAND } ,
{ AF9015_REMOTE_DIGITTRADE_DVB_T , RC_MAP_DIGITTRADE } ,
{ AF9015_REMOTE_AVERMEDIA_KS , RC_MAP_AVERMEDIA_RM_KS } ,
2012-01-07 04:11:27 -03:00
{ }
2008-09-15 17:18:09 -03:00
} ;
2012-06-07 20:36:35 -03:00
static const struct af9015_rc_setup af9015_rc_setup_hashes [ ] = {
{ 0xb8feb708 , RC_MAP_MSI_DIGIVOX_II } ,
{ 0xa3703d00 , RC_MAP_ALINK_DTU_M } ,
{ 0x9b7dc64e , RC_MAP_TOTAL_MEDIA_IN_HAND } , /* MYGICTV U718 */
{ 0x5d49e3db , RC_MAP_DIGITTRADE } , /* LC-Power LC-USB-DVBT */
{ }
} ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
static int af9015_rc_query ( struct dvb_usb_device * d )
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2012-06-07 20:36:35 -03:00
int ret ;
u8 buf [ 17 ] ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
deb_info ( " %s: \n " , __func__ ) ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
/* read registers needed to detect remote controller code */
ret = af9015_read_regs ( d , 0x98d9 , buf , sizeof ( buf ) ) ;
if ( ret )
goto error ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
/* If any of these are non-zero, assume invalid data */
if ( buf [ 1 ] | | buf [ 2 ] | | buf [ 3 ] )
return ret ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
/* Check for repeat of previous code */
if ( ( state - > rc_repeat ! = buf [ 6 ] | | buf [ 0 ] ) & &
! memcmp ( & buf [ 12 ] , state - > rc_last , 4 ) ) {
deb_rc ( " %s: key repeated \n " , __func__ ) ;
rc_keydown ( d - > rc_dev , state - > rc_keycode , 0 ) ;
state - > rc_repeat = buf [ 6 ] ;
return ret ;
}
2009-04-09 09:16:12 -03:00
2012-06-07 20:36:35 -03:00
/* Only process key if canary killed */
if ( buf [ 16 ] ! = 0xff & & buf [ 0 ] ! = 0x01 ) {
deb_rc ( " %s: key pressed %02x %02x %02x %02x \n " , __func__ ,
buf [ 12 ] , buf [ 13 ] , buf [ 14 ] , buf [ 15 ] ) ;
2009-04-09 09:16:12 -03:00
2012-06-07 20:36:35 -03:00
/* Reset the canary */
ret = af9015_write_reg ( d , 0x98e9 , 0xff ) ;
if ( ret )
goto error ;
2009-04-09 09:16:12 -03:00
2012-06-07 20:36:35 -03:00
/* Remember this key */
memcpy ( state - > rc_last , & buf [ 12 ] , 4 ) ;
if ( buf [ 14 ] = = ( u8 ) ~ buf [ 15 ] ) {
if ( buf [ 12 ] = = ( u8 ) ~ buf [ 13 ] ) {
/* NEC */
state - > rc_keycode = buf [ 12 ] < < 8 | buf [ 14 ] ;
} else {
/* NEC extended*/
state - > rc_keycode = buf [ 12 ] < < 16 |
buf [ 13 ] < < 8 | buf [ 14 ] ;
}
} else {
/* 32 bit NEC */
state - > rc_keycode = buf [ 12 ] < < 24 | buf [ 13 ] < < 16 |
buf [ 14 ] < < 8 | buf [ 15 ] ;
2009-04-09 09:16:12 -03:00
}
2012-06-07 20:36:35 -03:00
rc_keydown ( d - > rc_dev , state - > rc_keycode , 0 ) ;
} else {
deb_rc ( " %s: no key press \n " , __func__ ) ;
/* Invalidate last keypress */
/* Not really needed, but helps with debug */
state - > rc_last [ 2 ] = state - > rc_last [ 3 ] ;
}
state - > rc_repeat = buf [ 6 ] ;
error :
if ( ret )
err ( " %s: failed:%d " , __func__ , ret ) ;
return ret ;
}
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
static int af9015_get_rc_config ( struct dvb_usb_device * d , struct dvb_usb_rc * rc )
2008-09-15 17:18:09 -03:00
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2012-06-07 20:36:35 -03:00
u16 vid = le16_to_cpu ( d - > udev - > descriptor . idVendor ) ;
if ( state - > ir_mode = = AF9015_IR_MODE_DISABLED )
return 0 ;
/* try to load remote based module param */
rc - > map_name = af9015_rc_setup_match ( dvb_usb_af9015_remote ,
af9015_rc_setup_modparam ) ;
2008-09-15 17:18:09 -03:00
2012-06-07 20:36:35 -03:00
/* try to load remote based eeprom hash */
if ( ! rc - > map_name )
rc - > map_name = af9015_rc_setup_match ( state - > eeprom_sum ,
af9015_rc_setup_hashes ) ;
/* try to load remote based USB iManufacturer string */
if ( ! rc - > map_name & & vid = = USB_VID_AFATECH ) {
/* Check USB manufacturer and product strings and try
to determine correct remote in case of chip vendor
reference IDs are used .
DO NOT ADD ANYTHING NEW HERE . Use hashes instead . */
char manufacturer [ 10 ] ;
memset ( manufacturer , 0 , sizeof ( manufacturer ) ) ;
usb_string ( d - > udev , d - > udev - > descriptor . iManufacturer ,
manufacturer , sizeof ( manufacturer ) ) ;
if ( ! strcmp ( " MSI " , manufacturer ) ) {
/* iManufacturer 1 MSI
iProduct 2 MSI K - VOX */
rc - > map_name = af9015_rc_setup_match (
AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3 ,
af9015_rc_setup_modparam ) ;
}
2008-09-15 17:18:09 -03:00
}
2012-07-05 19:57:07 -03:00
/* load empty to enable rc */
if ( ! rc - > map_name )
rc - > map_name = RC_MAP_EMPTY ;
2012-06-07 20:36:35 -03:00
rc - > allowed_protos = RC_TYPE_NEC ;
rc - > query = af9015_rc_query ;
rc - > interval = 500 ;
return 0 ;
2008-09-15 17:18:09 -03:00
}
2012-06-07 20:36:35 -03:00
/* interface 0 is used by DVB-T receiver and
interface 1 is for remote controller ( HID ) */
static struct dvb_usb_device_properties af9015_props = {
. driver_name = KBUILD_MODNAME ,
. owner = THIS_MODULE ,
. adapter_nr = adapter_nr ,
. size_of_priv = sizeof ( struct af9015_state ) ,
. generic_bulk_ctrl_endpoint = 0x02 ,
. generic_bulk_ctrl_endpoint_response = 0x81 ,
. identify_state = af9015_identify_state ,
. firmware = " dvb-usb-af9015.fw " ,
. download_firmware = af9015_download_firmware ,
. i2c_algo = & af9015_i2c_algo ,
2012-06-12 01:05:20 -03:00
. read_config = af9015_read_config ,
. frontend_attach = af9015_af9013_frontend_attach ,
. tuner_attach = af9015_tuner_attach ,
2012-06-07 20:36:35 -03:00
. init = af9015_init ,
. get_rc_config = af9015_get_rc_config ,
2012-06-18 22:54:16 -03:00
. get_stream_config = af9015_get_stream_config ,
2012-06-07 20:36:35 -03:00
. get_adapter_count = af9015_get_adapter_count ,
. adapter = {
{
. caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF ,
. pid_filter_count = 32 ,
. pid_filter = af9015_pid_filter ,
. pid_filter_ctrl = af9015_pid_filter_ctrl ,
2012-06-16 16:25:22 -03:00
. stream = DVB_USB_STREAM_BULK ( 0x84 , 8 , TS_USB20_FRAME_SIZE ) ,
} , {
. stream = DVB_USB_STREAM_BULK ( 0x85 , 8 , TS_USB20_FRAME_SIZE ) ,
2012-06-07 20:36:35 -03:00
} ,
} ,
} ;
static const struct usb_device_id af9015_id_table [ ] = {
{ DVB_USB_DEVICE ( USB_VID_AFATECH , USB_PID_AFATECH_AF9015_9015 ,
& af9015_props , " Afatech AF9015 reference design " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AFATECH , USB_PID_AFATECH_AF9015_9016 ,
& af9015_props , " Afatech AF9015 reference design " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_LEADTEK , USB_PID_WINFAST_DTV_DONGLE_GOLD ,
& af9015_props , " Leadtek WinFast DTV Dongle Gold " , RC_MAP_LEADTEK_Y04G0051 ) } ,
{ DVB_USB_DEVICE ( USB_VID_PINNACLE , USB_PID_PINNACLE_PCTV71E ,
& af9015_props , " Pinnacle PCTV 71e " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_KWORLD_399U ,
& af9015_props , " KWorld PlusTV Dual DVB-T Stick (DVB-T 399U) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_VISIONPLUS , USB_PID_TINYTWIN ,
& af9015_props , " DigitalNow TinyTwin " , RC_MAP_AZUREWAVE_AD_TU700 ) } ,
{ DVB_USB_DEVICE ( USB_VID_VISIONPLUS , USB_PID_AZUREWAVE_AD_TU700 ,
& af9015_props , " TwinHan AzureWave AD-TU700(704J) " , RC_MAP_AZUREWAVE_AD_TU700 ) } ,
{ DVB_USB_DEVICE ( USB_VID_TERRATEC , USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 ,
& af9015_props , " TerraTec Cinergy T USB XE " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_KWORLD_PC160_2T ,
& af9015_props , " KWorld PlusTV Dual DVB-T PCI (DVB-T PC160-2T) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AVERMEDIA , USB_PID_AVERMEDIA_VOLAR_X ,
& af9015_props , " AVerMedia AVerTV DVB-T Volar X " , RC_MAP_AVERMEDIA_M135A ) } ,
{ DVB_USB_DEVICE ( USB_VID_XTENSIONS , USB_PID_XTENSIONS_XD_380 ,
& af9015_props , " Xtensions XD-380 " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_MSI_2 , USB_PID_MSI_DIGIVOX_DUO ,
& af9015_props , " MSI DIGIVOX Duo " , RC_MAP_MSI_DIGIVOX_III ) } ,
{ DVB_USB_DEVICE ( USB_VID_AVERMEDIA , USB_PID_AVERMEDIA_VOLAR_X_2 ,
& af9015_props , " Fujitsu-Siemens Slim Mobile USB DVB-T " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_TELESTAR , USB_PID_TELESTAR_STARSTICK_2 ,
& af9015_props , " Telestar Starstick 2 " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AVERMEDIA , USB_PID_AVERMEDIA_A309 ,
& af9015_props , " AVerMedia A309 " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_MSI_2 , USB_PID_MSI_DIGI_VOX_MINI_III ,
& af9015_props , " MSI Digi VOX mini III " , RC_MAP_MSI_DIGIVOX_III ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_KWORLD_395U ,
& af9015_props , " KWorld USB DVB-T TV Stick II (VS-DVB-T 395U) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_KWORLD_395U_2 ,
& af9015_props , " KWorld USB DVB-T TV Stick II (VS-DVB-T 395U) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_KWORLD_395U_3 ,
& af9015_props , " KWorld USB DVB-T TV Stick II (VS-DVB-T 395U) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AFATECH , USB_PID_TREKSTOR_DVBT ,
& af9015_props , " TrekStor DVB-T USB Stick " , RC_MAP_TREKSTOR ) } ,
{ DVB_USB_DEVICE ( USB_VID_AVERMEDIA , USB_PID_AVERMEDIA_A850 ,
& af9015_props , " AverMedia AVerTV Volar Black HD (A850) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AVERMEDIA , USB_PID_AVERMEDIA_A805 ,
& af9015_props , " AverMedia AVerTV Volar GPS 805 (A805) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_CONCEPTRONIC_CTVDIGRCU ,
& af9015_props , " Conceptronic USB2.0 DVB-T CTVDIGRCU V3.0 " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_KWORLD_MC810 ,
& af9015_props , " KWorld Digial MC-810 " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_KYE , USB_PID_GENIUS_TVGO_DVB_T03 ,
& af9015_props , " Genius TVGo DVB-T03 " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_KWORLD_399U_2 ,
& af9015_props , " KWorld PlusTV Dual DVB-T Stick (DVB-T 399U) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_KWORLD_PC160_T ,
& af9015_props , " KWorld PlusTV DVB-T PCI Pro Card (DVB-T PC160-T) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_SVEON_STV20 ,
& af9015_props , " Sveon STV20 Tuner USB DVB-T HDTV " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_TINYTWIN_2 ,
& af9015_props , " DigitalNow TinyTwin v2 " , RC_MAP_DIGITALNOW_TINYTWIN ) } ,
{ DVB_USB_DEVICE ( USB_VID_LEADTEK , USB_PID_WINFAST_DTV2000DS ,
& af9015_props , " Leadtek WinFast DTV2000DS " , RC_MAP_LEADTEK_Y04G0051 ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_KWORLD_UB383_T ,
& af9015_props , " KWorld USB DVB-T Stick Mobile (UB383-T) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_KWORLD_395U_4 ,
& af9015_props , " KWorld USB DVB-T TV Stick II (VS-DVB-T 395U) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AVERMEDIA , USB_PID_AVERMEDIA_A815M ,
& af9015_props , " AverMedia AVerTV Volar M (A815Mac) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_TERRATEC , USB_PID_TERRATEC_CINERGY_T_STICK_RC ,
& af9015_props , " TerraTec Cinergy T Stick RC " , RC_MAP_TERRATEC_SLIM_2 ) } ,
{ DVB_USB_DEVICE ( USB_VID_TERRATEC , USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC ,
& af9015_props , " TerraTec Cinergy T Stick Dual RC " , RC_MAP_TERRATEC_SLIM ) } ,
{ DVB_USB_DEVICE ( USB_VID_AVERMEDIA , USB_PID_AVERMEDIA_A850T ,
& af9015_props , " AverMedia AVerTV Red HD+ (A850T) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_GTEK , USB_PID_TINYTWIN_3 ,
& af9015_props , " DigitalNow TinyTwin v3 " , RC_MAP_DIGITALNOW_TINYTWIN ) } ,
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_SVEON_STV22 ,
& af9015_props , " Sveon STV22 Dual USB DVB-T Tuner HDTV " , RC_MAP_MSI_DIGIVOX_III ) } ,
{ }
} ;
MODULE_DEVICE_TABLE ( usb , af9015_id_table ) ;
2008-09-15 17:18:09 -03:00
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver af9015_usb_driver = {
2012-06-07 20:36:35 -03:00
. name = KBUILD_MODNAME ,
2012-06-12 01:05:20 -03:00
. id_table = af9015_id_table ,
2012-06-07 20:36:35 -03:00
. probe = dvb_usbv2_probe ,
. disconnect = dvb_usbv2_disconnect ,
2012-06-12 02:20:01 -03:00
. suspend = dvb_usbv2_suspend ,
. resume = dvb_usbv2_resume ,
2012-06-07 20:36:35 -03:00
. no_dynamic_id = 1 ,
2012-06-09 21:22:06 -03:00
. soft_unbind = 1 ,
2008-09-15 17:18:09 -03:00
} ;
2011-11-18 09:46:12 -08:00
module_usb_driver ( af9015_usb_driver ) ;
2008-09-15 17:18:09 -03:00
MODULE_AUTHOR ( " Antti Palosaari <crope@iki.fi> " ) ;
2012-05-08 06:04:24 -03:00
MODULE_DESCRIPTION ( " Afatech AF9015 driver " ) ;
2008-09-15 17:18:09 -03:00
MODULE_LICENSE ( " GPL " ) ;