2012-03-30 09:10:08 -03:00
/*
* Afatech AF9035 DVB USB driver
*
* Copyright ( C ) 2009 Antti Palosaari < crope @ iki . fi >
* Copyright ( C ) 2012 Antti Palosaari < crope @ iki . fi >
*
* 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 . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
# include "af9035.h"
DVB_DEFINE_MOD_OPT_ADAPTER_NR ( adapter_nr ) ;
2012-04-01 16:33:48 -03:00
static u16 af9035_checksum ( const u8 * buf , size_t len )
{
size_t i ;
u16 checksum = 0 ;
for ( i = 1 ; i < len ; i + + ) {
if ( i % 2 )
checksum + = buf [ i ] < < 8 ;
else
checksum + = buf [ i ] ;
}
checksum = ~ checksum ;
return checksum ;
}
2012-06-17 23:15:03 -03:00
static int af9035_ctrl_msg ( struct dvb_usb_device * d , struct usb_req * req )
2012-03-30 09:10:08 -03:00
{
2012-04-06 16:32:30 -03:00
# define BUF_LEN 64
2012-03-30 09:10:08 -03:00
# define REQ_HDR_LEN 4 /* send header size */
# define ACK_HDR_LEN 3 /* rece header size */
# define CHECKSUM_LEN 2
# define USB_TIMEOUT 2000
2012-06-17 23:15:03 -03:00
struct state * state = d_to_priv ( d ) ;
int ret , wlen , rlen ;
2012-03-30 09:10:08 -03:00
u8 buf [ BUF_LEN ] ;
2012-04-06 16:32:30 -03:00
u16 checksum , tmp_checksum ;
2012-03-30 09:10:08 -03:00
/* buffer overflow check */
if ( req - > wlen > ( BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN ) | |
req - > rlen > ( BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN ) ) {
pr_debug ( " %s: too much data wlen=%d rlen=%d \n " , __func__ ,
req - > wlen , req - > rlen ) ;
return - EINVAL ;
}
buf [ 0 ] = REQ_HDR_LEN + req - > wlen + CHECKSUM_LEN - 1 ;
buf [ 1 ] = req - > mbox ;
buf [ 2 ] = req - > cmd ;
2012-06-17 23:15:03 -03:00
buf [ 3 ] = state - > seq + + ;
memcpy ( & buf [ REQ_HDR_LEN ] , req - > wbuf , req - > wlen ) ;
wlen = REQ_HDR_LEN + req - > wlen + CHECKSUM_LEN ;
rlen = ACK_HDR_LEN + req - > rlen + CHECKSUM_LEN ;
2012-03-30 09:10:08 -03:00
/* calc and add checksum */
2012-04-01 16:33:48 -03:00
checksum = af9035_checksum ( buf , buf [ 0 ] - 1 ) ;
2012-04-06 16:32:30 -03:00
buf [ buf [ 0 ] - 1 ] = ( checksum > > 8 ) ;
buf [ buf [ 0 ] - 0 ] = ( checksum & 0xff ) ;
2012-03-30 09:10:08 -03:00
2012-06-17 23:15:03 -03:00
/* no ack for these packets */
if ( req - > cmd = = CMD_FW_DL )
rlen = 0 ;
2012-03-30 09:10:08 -03:00
2012-06-20 20:27:42 -03:00
ret = dvb_usbv2_generic_rw ( d , buf , wlen , buf , rlen ) ;
2012-06-17 23:15:03 -03:00
if ( ret )
goto err ;
2012-03-30 09:10:08 -03:00
/* no ack for those packets */
if ( req - > cmd = = CMD_FW_DL )
2012-06-17 23:15:03 -03:00
goto exit ;
2012-03-30 09:10:08 -03:00
2012-04-01 16:33:48 -03:00
/* verify checksum */
2012-06-17 23:15:03 -03:00
checksum = af9035_checksum ( buf , rlen - 2 ) ;
tmp_checksum = ( buf [ rlen - 2 ] < < 8 ) | buf [ rlen - 1 ] ;
2012-04-06 16:32:30 -03:00
if ( tmp_checksum ! = checksum ) {
2012-06-17 23:15:03 -03:00
pr_err ( " %s: command=%02x checksum mismatch (%04x != %04x) \n " ,
KBUILD_MODNAME , req - > cmd , tmp_checksum ,
checksum ) ;
2012-04-01 16:33:48 -03:00
ret = - EIO ;
2012-06-17 23:15:03 -03:00
goto err ;
2012-04-01 16:33:48 -03:00
}
2012-04-06 16:32:30 -03:00
2012-03-30 09:10:08 -03:00
/* check status */
if ( buf [ 2 ] ) {
pr_debug ( " %s: command=%02x failed fw error=%d \n " , __func__ ,
req - > cmd , buf [ 2 ] ) ;
ret = - EIO ;
2012-06-17 23:15:03 -03:00
goto err ;
2012-03-30 09:10:08 -03:00
}
/* read request, copy returned data to return buf */
if ( req - > rlen )
memcpy ( req - > rbuf , & buf [ ACK_HDR_LEN ] , req - > rlen ) ;
2012-06-17 23:15:03 -03:00
exit :
return 0 ;
err :
pr_debug ( " %s: failed=%d \n " , __func__ , ret ) ;
2012-03-30 09:10:08 -03:00
return ret ;
}
/* write multiple registers */
static int af9035_wr_regs ( struct dvb_usb_device * d , u32 reg , u8 * val , int len )
{
u8 wbuf [ 6 + len ] ;
u8 mbox = ( reg > > 16 ) & 0xff ;
struct usb_req req = { CMD_MEM_WR , mbox , sizeof ( wbuf ) , wbuf , 0 , NULL } ;
wbuf [ 0 ] = len ;
wbuf [ 1 ] = 2 ;
wbuf [ 2 ] = 0 ;
wbuf [ 3 ] = 0 ;
wbuf [ 4 ] = ( reg > > 8 ) & 0xff ;
wbuf [ 5 ] = ( reg > > 0 ) & 0xff ;
memcpy ( & wbuf [ 6 ] , val , len ) ;
2012-06-17 23:15:03 -03:00
return af9035_ctrl_msg ( d , & req ) ;
2012-03-30 09:10:08 -03:00
}
/* read multiple registers */
static int af9035_rd_regs ( struct dvb_usb_device * d , u32 reg , u8 * val , int len )
{
u8 wbuf [ ] = { len , 2 , 0 , 0 , ( reg > > 8 ) & 0xff , reg & 0xff } ;
u8 mbox = ( reg > > 16 ) & 0xff ;
struct usb_req req = { CMD_MEM_RD , mbox , sizeof ( wbuf ) , wbuf , len , val } ;
2012-06-17 23:15:03 -03:00
return af9035_ctrl_msg ( d , & req ) ;
2012-03-30 09:10:08 -03:00
}
/* write single register */
static int af9035_wr_reg ( struct dvb_usb_device * d , u32 reg , u8 val )
{
return af9035_wr_regs ( d , reg , & val , 1 ) ;
}
/* read single register */
static int af9035_rd_reg ( struct dvb_usb_device * d , u32 reg , u8 * val )
{
return af9035_rd_regs ( d , reg , val , 1 ) ;
}
/* write single register with mask */
static int af9035_wr_reg_mask ( struct dvb_usb_device * d , u32 reg , u8 val ,
u8 mask )
{
int ret ;
u8 tmp ;
/* no need for read if whole reg is written */
if ( mask ! = 0xff ) {
ret = af9035_rd_regs ( d , reg , & tmp , 1 ) ;
if ( ret )
return ret ;
val & = mask ;
tmp & = ~ mask ;
val | = tmp ;
}
return af9035_wr_regs ( d , reg , & val , 1 ) ;
}
static int af9035_i2c_master_xfer ( struct i2c_adapter * adap ,
struct i2c_msg msg [ ] , int num )
{
struct dvb_usb_device * d = i2c_get_adapdata ( adap ) ;
2012-06-17 23:15:03 -03:00
struct state * state = d_to_priv ( d ) ;
2012-03-30 09:10:08 -03:00
int ret ;
if ( mutex_lock_interruptible ( & d - > i2c_mutex ) < 0 )
return - EAGAIN ;
2012-04-02 20:18:59 -03:00
/*
* I2C sub header is 5 bytes long . Meaning of those bytes are :
* 0 : data len
* 1 : I2C addr < < 1
* 2 : reg addr len
* byte 3 and 4 can be used as reg addr
* 3 : reg addr MSB
* used when reg addr len is set to 2
* 4 : reg addr LSB
* used when reg addr len is set to 1 or 2
*
* For the simplify we do not use register addr at all .
* NOTE : As a firmware knows tuner type there is very small possibility
* there could be some tuner I2C hacks done by firmware and this may
* lead problems if firmware expects those bytes are used .
*/
2012-03-30 09:10:08 -03:00
if ( num = = 2 & & ! ( msg [ 0 ] . flags & I2C_M_RD ) & &
( msg [ 1 ] . flags & I2C_M_RD ) ) {
if ( msg [ 0 ] . len > 40 | | msg [ 1 ] . len > 40 ) {
/* TODO: correct limits > 40 */
ret = - EOPNOTSUPP ;
2012-05-07 14:50:40 -03:00
} else if ( msg [ 0 ] . addr = = state - > af9033_config [ 0 ] . i2c_addr ) {
2012-03-30 09:10:08 -03:00
/* integrated demod */
u32 reg = msg [ 0 ] . buf [ 0 ] < < 16 | msg [ 0 ] . buf [ 1 ] < < 8 |
msg [ 0 ] . buf [ 2 ] ;
ret = af9035_rd_regs ( d , reg , & msg [ 1 ] . buf [ 0 ] ,
msg [ 1 ] . len ) ;
} else {
/* I2C */
2012-04-02 20:18:59 -03:00
u8 buf [ 5 + msg [ 0 ] . len ] ;
2012-03-30 09:10:08 -03:00
struct usb_req req = { CMD_I2C_RD , 0 , sizeof ( buf ) ,
buf , msg [ 1 ] . len , msg [ 1 ] . buf } ;
2012-04-01 14:11:29 -03:00
buf [ 0 ] = msg [ 1 ] . len ;
2012-03-30 09:10:08 -03:00
buf [ 1 ] = msg [ 0 ] . addr < < 1 ;
2012-04-02 20:18:59 -03:00
buf [ 2 ] = 0x00 ; /* reg addr len */
buf [ 3 ] = 0x00 ; /* reg addr MSB */
buf [ 4 ] = 0x00 ; /* reg addr LSB */
memcpy ( & buf [ 5 ] , msg [ 0 ] . buf , msg [ 0 ] . len ) ;
2012-06-17 23:15:03 -03:00
ret = af9035_ctrl_msg ( d , & req ) ;
2012-03-30 09:10:08 -03:00
}
} else if ( num = = 1 & & ! ( msg [ 0 ] . flags & I2C_M_RD ) ) {
if ( msg [ 0 ] . len > 40 ) {
/* TODO: correct limits > 40 */
ret = - EOPNOTSUPP ;
2012-05-07 14:50:40 -03:00
} else if ( msg [ 0 ] . addr = = state - > af9033_config [ 0 ] . i2c_addr ) {
2012-03-30 09:10:08 -03:00
/* integrated demod */
u32 reg = msg [ 0 ] . buf [ 0 ] < < 16 | msg [ 0 ] . buf [ 1 ] < < 8 |
msg [ 0 ] . buf [ 2 ] ;
ret = af9035_wr_regs ( d , reg , & msg [ 0 ] . buf [ 3 ] ,
msg [ 0 ] . len - 3 ) ;
} else {
/* I2C */
2012-04-02 20:18:59 -03:00
u8 buf [ 5 + msg [ 0 ] . len ] ;
2012-03-30 09:10:08 -03:00
struct usb_req req = { CMD_I2C_WR , 0 , sizeof ( buf ) , buf ,
0 , NULL } ;
buf [ 0 ] = msg [ 0 ] . len ;
buf [ 1 ] = msg [ 0 ] . addr < < 1 ;
2012-04-02 20:18:59 -03:00
buf [ 2 ] = 0x00 ; /* reg addr len */
buf [ 3 ] = 0x00 ; /* reg addr MSB */
buf [ 4 ] = 0x00 ; /* reg addr LSB */
memcpy ( & buf [ 5 ] , msg [ 0 ] . buf , msg [ 0 ] . len ) ;
2012-06-17 23:15:03 -03:00
ret = af9035_ctrl_msg ( d , & req ) ;
2012-03-30 09:10:08 -03:00
}
} else {
/*
* We support only two kind of I2C transactions :
* 1 ) 1 x read + 1 x write
* 2 ) 1 x write
*/
ret = - EOPNOTSUPP ;
}
mutex_unlock ( & d - > i2c_mutex ) ;
if ( ret < 0 )
return ret ;
else
return num ;
}
static u32 af9035_i2c_functionality ( struct i2c_adapter * adapter )
{
return I2C_FUNC_I2C ;
}
static struct i2c_algorithm af9035_i2c_algo = {
. master_xfer = af9035_i2c_master_xfer ,
. functionality = af9035_i2c_functionality ,
} ;
2012-06-18 23:42:53 -03:00
static int af9035_identify_state ( struct dvb_usb_device * d , const char * * name )
2012-03-30 09:10:08 -03:00
{
int ret ;
u8 wbuf [ 1 ] = { 1 } ;
u8 rbuf [ 4 ] ;
struct usb_req req = { CMD_FW_QUERYINFO , 0 , sizeof ( wbuf ) , wbuf ,
sizeof ( rbuf ) , rbuf } ;
2012-06-17 23:15:03 -03:00
ret = af9035_ctrl_msg ( d , & req ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
2012-08-07 18:56:35 -03:00
pr_debug ( " %s: reply=%*ph \n " , __func__ , 4 , rbuf ) ;
2012-03-30 09:10:08 -03:00
if ( rbuf [ 0 ] | | rbuf [ 1 ] | | rbuf [ 2 ] | | rbuf [ 3 ] )
2012-06-17 23:15:03 -03:00
ret = WARM ;
2012-03-30 09:10:08 -03:00
else
2012-06-17 23:15:03 -03:00
ret = COLD ;
2012-03-30 09:10:08 -03:00
2012-06-17 23:15:03 -03:00
return ret ;
2012-03-30 09:10:08 -03:00
err :
pr_debug ( " %s: failed=%d \n " , __func__ , ret ) ;
return ret ;
}
2012-06-17 23:15:03 -03:00
static int af9035_download_firmware ( struct dvb_usb_device * d ,
2012-03-30 09:10:08 -03:00
const struct firmware * fw )
{
2012-04-01 01:32:23 -03:00
int ret , i , j , len ;
2012-03-30 09:10:08 -03:00
u8 wbuf [ 1 ] ;
u8 rbuf [ 4 ] ;
struct usb_req req = { 0 , 0 , 0 , NULL , 0 , NULL } ;
struct usb_req req_fw_dl = { CMD_FW_DL , 0 , 0 , wbuf , 0 , NULL } ;
struct usb_req req_fw_ver = { CMD_FW_QUERYINFO , 0 , 1 , wbuf , 4 , rbuf } ;
2012-04-01 01:32:23 -03:00
u8 hdr_core ;
u16 hdr_addr , hdr_data_len , hdr_checksum ;
2012-04-06 16:32:30 -03:00
# define MAX_DATA 58
2012-04-01 01:32:23 -03:00
# define HDR_SIZE 7
/*
* Thanks to Daniel Glöckner < daniel - gl @ gmx . net > about that info !
*
* byte 0 : MCS 51 core
* There are two inside the AF9035 ( 1 = Link and 2 = OFDM ) with separate
* address spaces
* byte 1 - 2 : Big endian destination address
* byte 3 - 4 : Big endian number of data bytes following the header
* byte 5 - 6 : Big endian header checksum , apparently ignored by the chip
* Calculated as ~ ( h [ 0 ] * 256 + h [ 1 ] + h [ 2 ] * 256 + h [ 3 ] + h [ 4 ] * 256 )
*/
for ( i = fw - > size ; i > HDR_SIZE ; ) {
hdr_core = fw - > data [ fw - > size - i + 0 ] ;
hdr_addr = fw - > data [ fw - > size - i + 1 ] < < 8 ;
hdr_addr | = fw - > data [ fw - > size - i + 2 ] < < 0 ;
hdr_data_len = fw - > data [ fw - > size - i + 3 ] < < 8 ;
hdr_data_len | = fw - > data [ fw - > size - i + 4 ] < < 0 ;
hdr_checksum = fw - > data [ fw - > size - i + 5 ] < < 8 ;
hdr_checksum | = fw - > data [ fw - > size - i + 6 ] < < 0 ;
pr_debug ( " %s: core=%d addr=%04x data_len=%d checksum=%04x \n " ,
__func__ , hdr_core , hdr_addr , hdr_data_len ,
hdr_checksum ) ;
if ( ( ( hdr_core ! = 1 ) & & ( hdr_core ! = 2 ) ) | |
( hdr_data_len > i ) ) {
pr_debug ( " %s: bad firmware \n " , __func__ ) ;
break ;
}
2012-03-30 09:10:08 -03:00
2012-04-01 01:32:23 -03:00
/* download begin packet */
req . cmd = CMD_FW_DL_BEGIN ;
2012-06-17 23:15:03 -03:00
ret = af9035_ctrl_msg ( d , & req ) ;
2012-04-01 11:06:23 -03:00
if ( ret < 0 )
goto err ;
2012-04-01 01:32:23 -03:00
/* download firmware packet(s) */
for ( j = HDR_SIZE + hdr_data_len ; j > 0 ; j - = MAX_DATA ) {
len = j ;
if ( len > MAX_DATA )
len = MAX_DATA ;
req_fw_dl . wlen = len ;
req_fw_dl . wbuf = ( u8 * ) & fw - > data [ fw - > size - i +
HDR_SIZE + hdr_data_len - j ] ;
2012-06-17 23:15:03 -03:00
ret = af9035_ctrl_msg ( d , & req_fw_dl ) ;
2012-04-01 01:32:23 -03:00
if ( ret < 0 )
2012-03-30 09:10:08 -03:00
goto err ;
}
2012-04-01 01:32:23 -03:00
/* download end packet */
req . cmd = CMD_FW_DL_END ;
2012-06-17 23:15:03 -03:00
ret = af9035_ctrl_msg ( d , & req ) ;
2012-04-01 01:32:23 -03:00
if ( ret < 0 )
goto err ;
i - = hdr_data_len + HDR_SIZE ;
2012-04-02 20:32:58 -03:00
pr_debug ( " %s: data uploaded=%zu \n " , __func__ , fw - > size - i ) ;
2012-03-30 09:10:08 -03:00
}
/* firmware loaded, request boot */
req . cmd = CMD_FW_BOOT ;
2012-06-17 23:15:03 -03:00
ret = af9035_ctrl_msg ( d , & req ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
/* ensure firmware starts */
wbuf [ 0 ] = 1 ;
2012-06-17 23:15:03 -03:00
ret = af9035_ctrl_msg ( d , & req_fw_ver ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
if ( ! ( rbuf [ 0 ] | | rbuf [ 1 ] | | rbuf [ 2 ] | | rbuf [ 3 ] ) ) {
2012-06-17 23:15:03 -03:00
pr_err ( " %s: firmware did not run \n " , KBUILD_MODNAME ) ;
2012-03-30 09:10:08 -03:00
ret = - ENODEV ;
goto err ;
}
2012-06-17 23:15:03 -03:00
pr_info ( " %s: firmware version=%d.%d.%d.%d " , KBUILD_MODNAME ,
rbuf [ 0 ] , rbuf [ 1 ] , rbuf [ 2 ] , rbuf [ 3 ] ) ;
2012-04-01 01:32:23 -03:00
2012-03-30 09:10:08 -03:00
return 0 ;
err :
pr_debug ( " %s: failed=%d \n " , __func__ , ret ) ;
return ret ;
}
2012-06-17 23:15:03 -03:00
static int af9035_download_firmware_it9135 ( struct dvb_usb_device * d ,
2012-04-05 20:28:51 -03:00
const struct firmware * fw )
{
int ret , i , i_prev ;
u8 wbuf [ 1 ] ;
u8 rbuf [ 4 ] ;
struct usb_req req = { 0 , 0 , 0 , NULL , 0 , NULL } ;
struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR , 0 , 0 , NULL , 0 , NULL } ;
struct usb_req req_fw_ver = { CMD_FW_QUERYINFO , 0 , 1 , wbuf , 4 , rbuf } ;
# define HDR_SIZE 7
/*
* There seems to be following firmware header . Meaning of bytes 0 - 3
* is unknown .
*
* 0 : 3
* 1 : 0 , 1
* 2 : 0
* 3 : 1 , 2 , 3
* 4 : addr MSB
* 5 : addr LSB
* 6 : count of data bytes ?
*/
for ( i = HDR_SIZE , i_prev = 0 ; i < = fw - > size ; i + + ) {
if ( i = = fw - > size | |
( fw - > data [ i + 0 ] = = 0x03 & &
( fw - > data [ i + 1 ] = = 0x00 | |
fw - > data [ i + 1 ] = = 0x01 ) & &
fw - > data [ i + 2 ] = = 0x00 ) ) {
req_fw_dl . wlen = i - i_prev ;
req_fw_dl . wbuf = ( u8 * ) & fw - > data [ i_prev ] ;
i_prev = i ;
2012-06-17 23:15:03 -03:00
ret = af9035_ctrl_msg ( d , & req_fw_dl ) ;
2012-04-05 20:28:51 -03:00
if ( ret < 0 )
goto err ;
pr_debug ( " %s: data uploaded=%d \n " , __func__ , i ) ;
}
}
/* firmware loaded, request boot */
req . cmd = CMD_FW_BOOT ;
2012-06-17 23:15:03 -03:00
ret = af9035_ctrl_msg ( d , & req ) ;
2012-04-05 20:28:51 -03:00
if ( ret < 0 )
goto err ;
/* ensure firmware starts */
wbuf [ 0 ] = 1 ;
2012-06-17 23:15:03 -03:00
ret = af9035_ctrl_msg ( d , & req_fw_ver ) ;
2012-04-05 20:28:51 -03:00
if ( ret < 0 )
goto err ;
if ( ! ( rbuf [ 0 ] | | rbuf [ 1 ] | | rbuf [ 2 ] | | rbuf [ 3 ] ) ) {
2012-06-17 23:15:03 -03:00
pr_err ( " %s: firmware did not run \n " , KBUILD_MODNAME ) ;
2012-04-05 20:28:51 -03:00
ret = - ENODEV ;
goto err ;
}
2012-06-17 23:15:03 -03:00
pr_info ( " %s: firmware version=%d.%d.%d.%d " , KBUILD_MODNAME ,
rbuf [ 0 ] , rbuf [ 1 ] , rbuf [ 2 ] , rbuf [ 3 ] ) ;
2012-04-05 20:28:51 -03:00
return 0 ;
err :
pr_debug ( " %s: failed=%d \n " , __func__ , ret ) ;
return ret ;
}
2012-06-17 23:15:03 -03:00
static int af9035_read_config ( struct dvb_usb_device * d )
2012-03-30 09:10:08 -03:00
{
2012-06-17 23:15:03 -03:00
struct state * state = d_to_priv ( d ) ;
2012-03-30 09:10:08 -03:00
int ret , i , eeprom_shift = 0 ;
u8 tmp ;
u16 tmp16 ;
/* check if there is dual tuners */
ret = af9035_rd_reg ( d , EEPROM_DUAL_MODE , & tmp ) ;
if ( ret < 0 )
goto err ;
2012-05-07 14:50:40 -03:00
state - > dual_mode = tmp ;
pr_debug ( " %s: dual mode=%d \n " , __func__ , state - > dual_mode ) ;
2012-03-30 09:10:08 -03:00
2012-06-17 23:15:03 -03:00
for ( i = 0 ; i < state - > dual_mode + 1 ; i + + ) {
2012-03-30 09:10:08 -03:00
/* tuner */
ret = af9035_rd_reg ( d , EEPROM_1_TUNER_ID + eeprom_shift , & tmp ) ;
if ( ret < 0 )
goto err ;
2012-05-07 14:50:40 -03:00
state - > af9033_config [ i ] . tuner = tmp ;
2012-03-30 09:10:08 -03:00
pr_debug ( " %s: [%d]tuner=%02x \n " , __func__ , i , tmp ) ;
switch ( tmp ) {
case AF9033_TUNER_TUA9001 :
2012-04-02 12:18:36 -03:00
case AF9033_TUNER_FC0011 :
2012-04-02 14:18:16 -03:00
case AF9033_TUNER_MXL5007T :
2012-04-02 17:25:14 -03:00
case AF9033_TUNER_TDA18218 :
2012-05-07 14:50:40 -03:00
state - > af9033_config [ i ] . spec_inv = 1 ;
2012-03-30 09:10:08 -03:00
break ;
default :
2012-06-17 23:15:03 -03:00
pr_info ( " %s: tuner ID=%02x not supported, please " \
" report! " , KBUILD_MODNAME , tmp ) ;
2012-03-30 09:10:08 -03:00
} ;
/* tuner IF frequency */
ret = af9035_rd_reg ( d , EEPROM_1_IFFREQ_L + eeprom_shift , & tmp ) ;
if ( ret < 0 )
goto err ;
tmp16 = tmp ;
ret = af9035_rd_reg ( d , EEPROM_1_IFFREQ_H + eeprom_shift , & tmp ) ;
if ( ret < 0 )
goto err ;
tmp16 | = tmp < < 8 ;
pr_debug ( " %s: [%d]IF=%d \n " , __func__ , i , tmp16 ) ;
eeprom_shift = 0x10 ; /* shift for the 2nd tuner params */
}
/* get demod clock */
ret = af9035_rd_reg ( d , 0x00d800 , & tmp ) ;
if ( ret < 0 )
goto err ;
tmp = ( tmp > > 0 ) & 0x0f ;
2012-06-17 23:15:03 -03:00
for ( i = 0 ; i < ARRAY_SIZE ( state - > af9033_config ) ; i + + )
2012-05-07 14:50:40 -03:00
state - > af9033_config [ i ] . clock = clock_lut [ tmp ] ;
2012-03-30 09:10:08 -03:00
return 0 ;
err :
pr_debug ( " %s: failed=%d \n " , __func__ , ret ) ;
return ret ;
}
2012-06-17 23:15:03 -03:00
static int af9035_read_config_it9135 ( struct dvb_usb_device * d )
2012-04-05 20:28:51 -03:00
{
2012-06-17 23:15:03 -03:00
struct state * state = d_to_priv ( d ) ;
2012-04-05 20:28:51 -03:00
int ret , i ;
u8 tmp ;
2012-05-07 14:50:40 -03:00
state - > dual_mode = false ;
2012-04-05 20:28:51 -03:00
/* get demod clock */
ret = af9035_rd_reg ( d , 0x00d800 , & tmp ) ;
if ( ret < 0 )
goto err ;
tmp = ( tmp > > 0 ) & 0x0f ;
2012-06-17 23:15:03 -03:00
for ( i = 0 ; i < ARRAY_SIZE ( state - > af9033_config ) ; i + + )
2012-05-07 14:50:40 -03:00
state - > af9033_config [ i ] . clock = clock_lut_it9135 [ tmp ] ;
2012-04-05 20:28:51 -03:00
return 0 ;
err :
pr_debug ( " %s: failed=%d \n " , __func__ , ret ) ;
return ret ;
}
2012-04-02 12:18:36 -03:00
static int af9035_fc0011_tuner_callback ( struct dvb_usb_device * d ,
2012-04-05 21:52:21 -03:00
int cmd , int arg )
2012-04-02 12:18:36 -03:00
{
2012-04-05 21:52:21 -03:00
int ret ;
2012-04-02 12:18:36 -03:00
switch ( cmd ) {
case FC0011_FE_CALLBACK_POWER :
/* Tuner enable */
2012-04-05 21:52:21 -03:00
ret = af9035_wr_reg_mask ( d , 0xd8eb , 1 , 1 ) ;
if ( ret < 0 )
goto err ;
ret = af9035_wr_reg_mask ( d , 0xd8ec , 1 , 1 ) ;
if ( ret < 0 )
goto err ;
ret = af9035_wr_reg_mask ( d , 0xd8ed , 1 , 1 ) ;
if ( ret < 0 )
goto err ;
2012-04-02 12:18:36 -03:00
/* LED */
2012-04-05 21:52:21 -03:00
ret = af9035_wr_reg_mask ( d , 0xd8d0 , 1 , 1 ) ;
if ( ret < 0 )
goto err ;
ret = af9035_wr_reg_mask ( d , 0xd8d1 , 1 , 1 ) ;
if ( ret < 0 )
goto err ;
2012-04-03 05:11:30 -03:00
usleep_range ( 10000 , 50000 ) ;
2012-04-02 12:18:36 -03:00
break ;
case FC0011_FE_CALLBACK_RESET :
2012-04-05 21:52:21 -03:00
ret = af9035_wr_reg ( d , 0xd8e9 , 1 ) ;
if ( ret < 0 )
goto err ;
ret = af9035_wr_reg ( d , 0xd8e8 , 1 ) ;
if ( ret < 0 )
goto err ;
ret = af9035_wr_reg ( d , 0xd8e7 , 1 ) ;
if ( ret < 0 )
goto err ;
2012-04-03 05:11:30 -03:00
usleep_range ( 10000 , 20000 ) ;
2012-04-05 21:52:21 -03:00
ret = af9035_wr_reg ( d , 0xd8e7 , 0 ) ;
if ( ret < 0 )
goto err ;
2012-04-03 05:11:30 -03:00
usleep_range ( 10000 , 20000 ) ;
2012-04-02 12:18:36 -03:00
break ;
default :
2012-04-05 21:52:21 -03:00
ret = - EINVAL ;
goto err ;
2012-04-02 12:18:36 -03:00
}
return 0 ;
2012-04-05 21:52:21 -03:00
err :
pr_debug ( " %s: failed=%d \n " , __func__ , ret ) ;
return ret ;
2012-04-02 12:18:36 -03:00
}
static int af9035_tuner_callback ( struct dvb_usb_device * d , int cmd , int arg )
{
2012-06-17 23:15:03 -03:00
struct state * state = d_to_priv ( d ) ;
2012-05-07 14:50:40 -03:00
switch ( state - > af9033_config [ 0 ] . tuner ) {
2012-04-02 12:18:36 -03:00
case AF9033_TUNER_FC0011 :
return af9035_fc0011_tuner_callback ( d , cmd , arg ) ;
default :
break ;
}
return - ENODEV ;
}
static int af9035_frontend_callback ( void * adapter_priv , int component ,
int cmd , int arg )
{
struct i2c_adapter * adap = adapter_priv ;
struct dvb_usb_device * d = i2c_get_adapdata ( adap ) ;
switch ( component ) {
case DVB_FRONTEND_COMPONENT_TUNER :
return af9035_tuner_callback ( d , cmd , arg ) ;
default :
break ;
}
return - EINVAL ;
}
2012-03-30 09:10:08 -03:00
static int af9035_frontend_attach ( struct dvb_usb_adapter * adap )
{
2012-06-17 23:15:03 -03:00
struct state * state = adap_to_priv ( adap ) ;
struct dvb_usb_device * d = adap_to_d ( adap ) ;
2012-03-30 09:10:08 -03:00
int ret ;
2012-05-07 14:59:55 -03:00
if ( ! state - > af9033_config [ adap - > id ] . tuner ) {
/* unsupported tuner */
2012-03-30 17:15:16 -03:00
ret = - ENODEV ;
goto err ;
}
2012-03-30 09:10:08 -03:00
if ( adap - > id = = 0 ) {
2012-05-07 14:50:40 -03:00
state - > af9033_config [ 0 ] . ts_mode = AF9033_TS_MODE_USB ;
state - > af9033_config [ 1 ] . ts_mode = AF9033_TS_MODE_SERIAL ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg ( d , 0x00417f ,
2012-05-07 14:50:40 -03:00
state - > af9033_config [ 1 ] . i2c_addr ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg ( d , 0x00d81a ,
2012-05-07 14:50:40 -03:00
state - > dual_mode ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
}
/* attach demodulator */
2012-06-17 23:15:03 -03:00
adap - > fe [ 0 ] = dvb_attach ( af9033_attach ,
& state - > af9033_config [ adap - > id ] , & d - > i2c_adap ) ;
if ( adap - > fe [ 0 ] = = NULL ) {
2012-03-30 09:10:08 -03:00
ret = - ENODEV ;
goto err ;
}
2012-04-06 07:09:23 -03:00
/* disable I2C-gate */
2012-06-17 23:15:03 -03:00
adap - > fe [ 0 ] - > ops . i2c_gate_ctrl = NULL ;
adap - > fe [ 0 ] - > callback = af9035_frontend_callback ;
2012-03-30 09:10:08 -03:00
return 0 ;
err :
pr_debug ( " %s: failed=%d \n " , __func__ , ret ) ;
return ret ;
}
static struct tua9001_config af9035_tua9001_config = {
. i2c_addr = 0x60 ,
} ;
2012-04-02 12:18:36 -03:00
static const struct fc0011_config af9035_fc0011_config = {
. i2c_address = 0x60 ,
} ;
2012-04-02 14:18:16 -03:00
static struct mxl5007t_config af9035_mxl5007t_config = {
. xtal_freq_hz = MxL_XTAL_24_MHZ ,
. if_freq_hz = MxL_IF_4_57_MHZ ,
. invert_if = 0 ,
. loop_thru_enable = 0 ,
. clk_out_enable = 0 ,
. clk_out_amp = MxL_CLKOUT_AMP_0_94V ,
} ;
2012-04-02 17:25:14 -03:00
static struct tda18218_config af9035_tda18218_config = {
. i2c_address = 0x60 ,
. i2c_wr_max = 21 ,
} ;
2012-03-30 09:10:08 -03:00
static int af9035_tuner_attach ( struct dvb_usb_adapter * adap )
{
2012-06-17 23:15:03 -03:00
struct state * state = adap_to_priv ( adap ) ;
struct dvb_usb_device * d = adap_to_d ( adap ) ;
2012-03-30 09:10:08 -03:00
int ret ;
struct dvb_frontend * fe ;
2012-05-07 14:50:40 -03:00
switch ( state - > af9033_config [ adap - > id ] . tuner ) {
2012-03-30 09:10:08 -03:00
case AF9033_TUNER_TUA9001 :
/* AF9035 gpiot3 = TUA9001 RESETN
AF9035 gpiot2 = TUA9001 RXEN */
/* configure gpiot2 and gpiot2 as output */
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg_mask ( d , 0x00d8ec , 0x01 , 0x01 ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg_mask ( d , 0x00d8ed , 0x01 , 0x01 ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg_mask ( d , 0x00d8e8 , 0x01 , 0x01 ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg_mask ( d , 0x00d8e9 , 0x01 , 0x01 ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
/* reset tuner */
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg_mask ( d , 0x00d8e7 , 0x00 , 0x01 ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
usleep_range ( 2000 , 20000 ) ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg_mask ( d , 0x00d8e7 , 0x01 , 0x01 ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
/* activate tuner RX */
/* TODO: use callback for TUA9001 RXEN */
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg_mask ( d , 0x00d8eb , 0x01 , 0x01 ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
/* attach tuner */
2012-06-17 23:15:03 -03:00
fe = dvb_attach ( tua9001_attach , adap - > fe [ 0 ] ,
& d - > i2c_adap , & af9035_tua9001_config ) ;
2012-03-30 09:10:08 -03:00
break ;
2012-04-02 12:18:36 -03:00
case AF9033_TUNER_FC0011 :
2012-06-17 23:15:03 -03:00
fe = dvb_attach ( fc0011_attach , adap - > fe [ 0 ] ,
& d - > i2c_adap , & af9035_fc0011_config ) ;
2012-04-02 12:18:36 -03:00
break ;
2012-04-02 14:18:16 -03:00
case AF9033_TUNER_MXL5007T :
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg ( d , 0x00d8e0 , 1 ) ;
2012-04-02 14:18:16 -03:00
if ( ret < 0 )
goto err ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg ( d , 0x00d8e1 , 1 ) ;
2012-04-02 14:18:16 -03:00
if ( ret < 0 )
goto err ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg ( d , 0x00d8df , 0 ) ;
2012-04-02 14:18:16 -03:00
if ( ret < 0 )
goto err ;
msleep ( 30 ) ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg ( d , 0x00d8df , 1 ) ;
2012-04-02 14:18:16 -03:00
if ( ret < 0 )
goto err ;
msleep ( 300 ) ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg ( d , 0x00d8c0 , 1 ) ;
2012-04-02 14:18:16 -03:00
if ( ret < 0 )
goto err ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg ( d , 0x00d8c1 , 1 ) ;
2012-04-02 14:18:16 -03:00
if ( ret < 0 )
goto err ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg ( d , 0x00d8bf , 0 ) ;
2012-04-02 14:18:16 -03:00
if ( ret < 0 )
goto err ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg ( d , 0x00d8b4 , 1 ) ;
2012-04-02 14:18:16 -03:00
if ( ret < 0 )
goto err ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg ( d , 0x00d8b5 , 1 ) ;
2012-04-02 14:18:16 -03:00
if ( ret < 0 )
goto err ;
2012-06-17 23:15:03 -03:00
ret = af9035_wr_reg ( d , 0x00d8b3 , 1 ) ;
2012-04-02 14:18:16 -03:00
if ( ret < 0 )
goto err ;
/* attach tuner */
2012-06-17 23:15:03 -03:00
fe = dvb_attach ( mxl5007t_attach , adap - > fe [ 0 ] ,
& d - > i2c_adap , 0x60 , & af9035_mxl5007t_config ) ;
2012-04-02 14:18:16 -03:00
break ;
2012-04-02 17:25:14 -03:00
case AF9033_TUNER_TDA18218 :
/* attach tuner */
2012-06-17 23:15:03 -03:00
fe = dvb_attach ( tda18218_attach , adap - > fe [ 0 ] ,
& d - > i2c_adap , & af9035_tda18218_config ) ;
2012-04-02 17:25:14 -03:00
break ;
2012-03-30 09:10:08 -03:00
default :
fe = NULL ;
}
if ( fe = = NULL ) {
ret = - ENODEV ;
goto err ;
}
return 0 ;
err :
pr_debug ( " %s: failed=%d \n " , __func__ , ret ) ;
return ret ;
}
2012-06-17 23:15:03 -03:00
static int af9035_init ( struct dvb_usb_device * d )
{
struct state * state = d_to_priv ( d ) ;
int ret , i ;
u16 frame_size = 87 * 188 / 4 ;
u8 packet_size = 512 / 4 ;
struct reg_val_mask tab [ ] = {
{ 0x80f99d , 0x01 , 0x01 } ,
{ 0x80f9a4 , 0x01 , 0x01 } ,
{ 0x00dd11 , 0x00 , 0x20 } ,
{ 0x00dd11 , 0x00 , 0x40 } ,
{ 0x00dd13 , 0x00 , 0x20 } ,
{ 0x00dd13 , 0x00 , 0x40 } ,
{ 0x00dd11 , 0x20 , 0x20 } ,
{ 0x00dd88 , ( frame_size > > 0 ) & 0xff , 0xff } ,
{ 0x00dd89 , ( frame_size > > 8 ) & 0xff , 0xff } ,
{ 0x00dd0c , packet_size , 0xff } ,
{ 0x00dd11 , state - > dual_mode < < 6 , 0x40 } ,
{ 0x00dd8a , ( frame_size > > 0 ) & 0xff , 0xff } ,
{ 0x00dd8b , ( frame_size > > 8 ) & 0xff , 0xff } ,
{ 0x00dd0d , packet_size , 0xff } ,
{ 0x80f9a3 , 0x00 , 0x01 } ,
{ 0x80f9cd , 0x00 , 0x01 } ,
{ 0x80f99d , 0x00 , 0x01 } ,
{ 0x80f9a4 , 0x00 , 0x01 } ,
} ;
2012-03-30 09:10:08 -03:00
2012-06-17 23:15:03 -03:00
pr_debug ( " %s: USB speed=%d frame_size=%04x packet_size=%02x \n " ,
__func__ , d - > udev - > speed , frame_size , packet_size ) ;
2012-03-30 09:10:08 -03:00
2012-06-17 23:15:03 -03:00
/* init endpoints */
for ( i = 0 ; i < ARRAY_SIZE ( tab ) ; i + + ) {
ret = af9035_wr_reg_mask ( d , tab [ i ] . reg , tab [ i ] . val ,
tab [ i ] . mask ) ;
if ( ret < 0 )
goto err ;
}
2012-03-30 09:10:08 -03:00
2012-06-17 23:15:03 -03:00
return 0 ;
2012-03-30 09:10:08 -03:00
2012-06-17 23:15:03 -03:00
err :
pr_debug ( " %s: failed=%d \n " , __func__ , ret ) ;
2012-04-05 20:28:51 -03:00
2012-06-17 23:15:03 -03:00
return ret ;
}
2012-04-05 20:28:51 -03:00
2012-06-17 23:15:03 -03:00
static int af9035_rc_query ( struct dvb_usb_device * d )
{
unsigned int key ;
unsigned char b [ 4 ] ;
int ret ;
struct usb_req req = { CMD_IR_GET , 0 , 0 , NULL , 4 , b } ;
2012-04-05 20:28:51 -03:00
2012-06-17 23:15:03 -03:00
ret = af9035_ctrl_msg ( d , & req ) ;
if ( ret < 0 )
goto err ;
2012-03-30 09:10:08 -03:00
2012-06-17 23:15:03 -03:00
if ( ( b [ 2 ] + b [ 3 ] ) = = 0xff ) {
if ( ( b [ 0 ] + b [ 1 ] ) = = 0xff ) {
/* NEC */
key = b [ 0 ] < < 8 | b [ 2 ] ;
} else {
/* ext. NEC */
key = b [ 0 ] < < 16 | b [ 1 ] < < 8 | b [ 2 ] ;
2012-03-30 09:10:08 -03:00
}
2012-06-17 23:15:03 -03:00
} else {
key = b [ 0 ] < < 24 | b [ 1 ] < < 16 | b [ 2 ] < < 8 | b [ 3 ] ;
2012-03-30 09:10:08 -03:00
}
2012-06-17 23:15:03 -03:00
rc_keydown ( d - > rc_dev , key , 0 ) ;
2012-03-30 09:10:08 -03:00
2012-06-17 23:15:03 -03:00
err :
/* ignore errors */
return 0 ;
}
2012-03-30 09:10:08 -03:00
2012-06-17 23:15:03 -03:00
static int af9035_get_rc_config ( struct dvb_usb_device * d , struct dvb_usb_rc * rc )
{
int ret ;
u8 tmp ;
2012-03-30 09:10:08 -03:00
2012-06-17 23:15:03 -03:00
ret = af9035_rd_reg ( d , EEPROM_IR_MODE , & tmp ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
2012-06-17 23:15:03 -03:00
pr_debug ( " %s: ir_mode=%02x \n " , __func__ , tmp ) ;
/* don't activate rc if in HID mode or if not available */
if ( tmp = = 5 ) {
ret = af9035_rd_reg ( d , EEPROM_IR_TYPE , & tmp ) ;
2012-03-30 09:10:08 -03:00
if ( ret < 0 )
goto err ;
2012-06-17 23:15:03 -03:00
pr_debug ( " %s: ir_type=%02x \n " , __func__ , tmp ) ;
switch ( tmp ) {
case 0 : /* NEC */
default :
rc - > allowed_protos = RC_TYPE_NEC ;
break ;
case 1 : /* RC6 */
rc - > allowed_protos = RC_TYPE_RC6 ;
break ;
}
rc - > query = af9035_rc_query ;
rc - > interval = 500 ;
2012-07-05 19:57:07 -03:00
/* load empty to enable rc */
if ( ! rc - > map_name )
rc - > map_name = RC_MAP_EMPTY ;
2012-03-30 09:10:08 -03:00
}
return 0 ;
err :
pr_debug ( " %s: failed=%d \n " , __func__ , ret ) ;
return ret ;
}
2012-06-17 23:15:03 -03:00
/* interface 0 is used by DVB-T receiver and
interface 1 is for remote controller ( HID ) */
static const struct dvb_usb_device_properties af9035_props = {
. driver_name = KBUILD_MODNAME ,
. owner = THIS_MODULE ,
. adapter_nr = adapter_nr ,
. size_of_priv = sizeof ( struct state ) ,
. generic_bulk_ctrl_endpoint = 0x02 ,
. generic_bulk_ctrl_endpoint_response = 0x81 ,
. identify_state = af9035_identify_state ,
. firmware = " dvb-usb-af9035-02.fw " ,
. download_firmware = af9035_download_firmware ,
. i2c_algo = & af9035_i2c_algo ,
. read_config = af9035_read_config ,
. frontend_attach = af9035_frontend_attach ,
. tuner_attach = af9035_tuner_attach ,
. init = af9035_init ,
. get_rc_config = af9035_get_rc_config ,
. num_adapters = 1 ,
. adapter = {
{
. stream = DVB_USB_STREAM_BULK ( 0x84 , 6 , 87 * 188 ) ,
} , {
. stream = DVB_USB_STREAM_BULK ( 0x85 , 6 , 87 * 188 ) ,
} ,
} ,
} ;
static const struct dvb_usb_device_properties it9135_props = {
. driver_name = KBUILD_MODNAME ,
. owner = THIS_MODULE ,
. adapter_nr = adapter_nr ,
. size_of_priv = sizeof ( struct state ) ,
. generic_bulk_ctrl_endpoint = 0x02 ,
. generic_bulk_ctrl_endpoint_response = 0x81 ,
. identify_state = af9035_identify_state ,
. firmware = " dvb-usb-it9135-01.fw " ,
. download_firmware = af9035_download_firmware_it9135 ,
. i2c_algo = & af9035_i2c_algo ,
. read_config = af9035_read_config_it9135 ,
. frontend_attach = af9035_frontend_attach ,
. tuner_attach = af9035_tuner_attach ,
. init = af9035_init ,
. get_rc_config = af9035_get_rc_config ,
. num_adapters = 1 ,
. adapter = {
{
. stream = DVB_USB_STREAM_BULK ( 0x84 , 6 , 87 * 188 ) ,
} , {
. stream = DVB_USB_STREAM_BULK ( 0x85 , 6 , 87 * 188 ) ,
} ,
} ,
} ;
static const struct usb_device_id af9035_id_table [ ] = {
{ DVB_USB_DEVICE ( USB_VID_AFATECH , USB_PID_AFATECH_AF9035_9035 ,
& af9035_props , " Afatech AF9035 reference design " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AFATECH , USB_PID_AFATECH_AF9035_1000 ,
& af9035_props , " Afatech AF9035 reference design " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AFATECH , USB_PID_AFATECH_AF9035_1001 ,
& af9035_props , " Afatech AF9035 reference design " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AFATECH , USB_PID_AFATECH_AF9035_1002 ,
& af9035_props , " Afatech AF9035 reference design " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AFATECH , USB_PID_AFATECH_AF9035_1003 ,
& af9035_props , " Afatech AF9035 reference design " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_TERRATEC , USB_PID_TERRATEC_CINERGY_T_STICK ,
& af9035_props , " TerraTec Cinergy T Stick " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AVERMEDIA , USB_PID_AVERMEDIA_A835 ,
& af9035_props , " AVerMedia AVerTV Volar HD/PRO (A835) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AVERMEDIA , USB_PID_AVERMEDIA_B835 ,
& af9035_props , " AVerMedia AVerTV Volar HD/PRO (A835) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AVERMEDIA , USB_PID_AVERMEDIA_1867 ,
& af9035_props , " AVerMedia HD Volar (A867) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AVERMEDIA , USB_PID_AVERMEDIA_A867 ,
& af9035_props , " AVerMedia HD Volar (A867) " , NULL ) } ,
{ DVB_USB_DEVICE ( USB_VID_AVERMEDIA , USB_PID_AVERMEDIA_TWINSTAR ,
& af9035_props , " AVerMedia Twinstar (A825) " , NULL ) } ,
{ }
} ;
MODULE_DEVICE_TABLE ( usb , af9035_id_table ) ;
2012-03-30 09:10:08 -03:00
static struct usb_driver af9035_usb_driver = {
2012-06-17 23:15:03 -03:00
. name = KBUILD_MODNAME ,
. id_table = af9035_id_table ,
. probe = dvb_usbv2_probe ,
. disconnect = dvb_usbv2_disconnect ,
. suspend = dvb_usbv2_suspend ,
. resume = dvb_usbv2_resume ,
2012-08-14 22:21:08 -03:00
. reset_resume = dvb_usbv2_reset_resume ,
2012-06-17 23:15:03 -03:00
. no_dynamic_id = 1 ,
. soft_unbind = 1 ,
2012-03-30 09:10:08 -03:00
} ;
2012-04-02 17:25:17 -03:00
module_usb_driver ( af9035_usb_driver ) ;
2012-03-30 09:10:08 -03:00
MODULE_AUTHOR ( " Antti Palosaari <crope@iki.fi> " ) ;
MODULE_DESCRIPTION ( " Afatech AF9035 driver " ) ;
MODULE_LICENSE ( " GPL " ) ;