2019-05-27 08:55:06 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
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 .
*/
# include "af9015.h"
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 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 ) ;
2017-06-21 16:55:54 -04:00
struct usb_interface * intf = d - > intf ;
2012-06-07 20:36:35 -03:00
int ret , wlen , rlen ;
2008-09-15 17:18:09 -03:00
u8 write = 1 ;
2013-02-26 13:25:19 -03:00
mutex_lock ( & d - > usb_mutex ) ;
state - > buf [ 0 ] = req - > cmd ;
state - > buf [ 1 ] = state - > seq + + ;
2017-02-05 18:09:38 -02:00
state - > buf [ 2 ] = req - > i2c_addr < < 1 ;
2013-02-26 13:25:19 -03:00
state - > buf [ 3 ] = req - > addr > > 8 ;
state - > buf [ 4 ] = req - > addr & 0xff ;
state - > buf [ 5 ] = req - > mbox ;
state - > buf [ 6 ] = req - > addr_len ;
state - > buf [ 7 ] = req - > data_len ;
2008-09-15 17:18:09 -03:00
switch ( req - > cmd ) {
case GET_CONFIG :
case READ_MEMORY :
case RECONNECT_USB :
write = 0 ;
break ;
case READ_I2C :
write = 0 ;
2013-02-26 13:25:19 -03:00
state - > buf [ 2 ] | = 0x01 ; /* set I2C direction */
2017-05-18 08:13:28 -03:00
/* fall through */
2008-09-15 17:18:09 -03:00
case WRITE_I2C :
2013-02-26 13:25:19 -03:00
state - > buf [ 0 ] = READ_WRITE_I2C ;
2008-09-15 17:18:09 -03:00
break ;
case WRITE_MEMORY :
if ( ( ( req - > addr & 0xff00 ) = = 0xff00 ) | |
2009-09-12 21:25:59 -03:00
( ( req - > addr & 0xff00 ) = = 0xae00 ) )
2013-02-26 13:25:19 -03:00
state - > buf [ 0 ] = WRITE_VIRTUAL_MEMORY ;
2008-09-15 17:18:09 -03:00
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 :
2017-06-21 16:55:54 -04:00
dev_err ( & intf - > dev , " unknown cmd %d \n " , req - > cmd ) ;
2012-09-12 20:23:52 -03:00
ret = - EIO ;
2012-06-07 20:36:35 -03:00
goto error ;
2008-09-15 17:18:09 -03:00
}
2018-03-13 19:27:57 -04:00
/* Buffer overflow check */
2009-09-12 20:46:30 -03:00
if ( ( write & & ( req - > data_len > BUF_LEN - REQ_HDR_LEN ) ) | |
2018-03-13 19:27:57 -04:00
( ! write & & ( req - > data_len > BUF_LEN - ACK_HDR_LEN ) ) ) {
2017-06-21 16:55:54 -04:00
dev_err ( & intf - > dev , " too much data, cmd %u, len %u \n " ,
req - > cmd , req - > data_len ) ;
2009-09-12 20:46:30 -03:00
ret = - EINVAL ;
2012-06-07 20:36:35 -03:00
goto error ;
2009-09-12 20:46:30 -03:00
}
2018-03-13 19:27:57 -04:00
/*
* Write receives seq + status = 2 bytes
* Read receives seq + status + data = 2 + N bytes
*/
2012-06-07 20:36:35 -03:00
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 ;
2013-02-26 13:25:19 -03:00
memcpy ( & state - > 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
2018-03-13 19:27:57 -04:00
ret = dvb_usbv2_generic_rw_locked ( d , state - > buf , wlen ,
state - > buf , rlen ) ;
2012-06-07 20:36:35 -03:00
if ( ret )
goto error ;
2008-09-15 17:18:09 -03:00
/* check status */
2013-02-26 13:25:19 -03:00
if ( rlen & & state - > buf [ 1 ] ) {
2017-06-21 16:55:54 -04:00
dev_err ( & intf - > dev , " cmd failed %u \n " , state - > buf [ 1 ] ) ;
2012-09-12 20:23:52 -03:00
ret = - EIO ;
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 )
2013-02-26 13:25:19 -03:00
memcpy ( req - > data , & state - > buf [ ACK_HDR_LEN ] , req - > data_len ) ;
2012-06-07 20:36:35 -03:00
error :
2013-02-26 13:25:19 -03:00
mutex_unlock ( & d - > usb_mutex ) ;
2008-09-15 17:18:09 -03:00
return ret ;
}
static int af9015_write_reg_i2c ( struct dvb_usb_device * d , u8 addr , u16 reg ,
2018-03-13 19:27:57 -04:00
u8 val )
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
struct req_t req = { WRITE_I2C , addr , reg , 1 , 1 , 1 , & val } ;
2017-06-23 05:17:00 -04:00
if ( addr = = state - > af9013_i2c_addr [ 0 ] | |
addr = = state - > af9013_i2c_addr [ 1 ] )
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 ,
2018-03-13 19:27:57 -04:00
u8 * val )
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
struct req_t req = { READ_I2C , addr , reg , 0 , 1 , 1 , val } ;
2017-06-23 05:17:00 -04:00
if ( addr = = state - > af9013_i2c_addr [ 0 ] | |
addr = = state - > af9013_i2c_addr [ 1 ] )
2008-09-15 17:18:09 -03:00
req . addr_len = 3 ;
return af9015_ctrl_msg ( d , & req ) ;
}
static int af9015_i2c_xfer ( struct i2c_adapter * adap , struct i2c_msg msg [ ] ,
2018-03-13 19:27:57 -04:00
int num )
2008-09-15 17:18:09 -03:00
{
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 ) ;
2017-06-21 16:55:54 -04:00
struct usb_interface * intf = d - > intf ;
2017-06-12 17:06:19 -03:00
int ret ;
2008-09-15 17:18:09 -03:00
u16 addr ;
2017-06-12 17:06:19 -03:00
u8 mbox , addr_len ;
2008-09-15 17:18:09 -03:00
struct req_t req ;
2018-03-13 19:27:57 -04:00
/*
* I2C multiplexing :
* There could be two tuners , both using same I2C address . Demodulator
* I2C - gate is only possibility to select correct tuner .
*
* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
* . AF9015 integrates AF9013 demodulator .
* . ____________ ____________ . ____________
* . | USB IF | | demod | . | tuner |
* . | - - - - - - - - - - - - | | - - - - - - - - - - - - | . | - - - - - - - - - - - - |
* . | AF9015 | | AF9013 | . | MXL5003 |
* . | | - - + - - I2C - - - - - | - - - - - / - - - - - | . - - - - I2C - - - - - | |
* . | | | | addr 0x1c | . | addr 0x63 |
* . | ____________ | | | ____________ | . | ____________ |
* . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . . . . . .
* | ____________ ____________
* | | demod | | tuner |
* | | - - - - - - - - - - - - | | - - - - - - - - - - - - |
* | | AF9013 | | MXL5003 |
* + - - I2C - - - - - | - - - - - / - - - - - | - - - - - I2C - - - - - | |
* | addr 0x1d | | addr 0x63 |
* | ____________ | | ____________ |
*/
2008-09-15 17:18:09 -03:00
2017-06-12 17:06:19 -03:00
if ( msg [ 0 ] . len = = 0 | | msg [ 0 ] . flags & I2C_M_RD ) {
addr = 0x0000 ;
mbox = 0 ;
addr_len = 0 ;
} else if ( msg [ 0 ] . len = = 1 ) {
addr = msg [ 0 ] . buf [ 0 ] ;
mbox = 0 ;
addr_len = 1 ;
} else if ( msg [ 0 ] . len = = 2 ) {
2018-03-13 19:27:57 -04:00
addr = msg [ 0 ] . buf [ 0 ] < < 8 | msg [ 0 ] . buf [ 1 ] < < 0 ;
2017-06-12 17:06:19 -03:00
mbox = 0 ;
addr_len = 2 ;
} else {
2018-03-13 19:27:57 -04:00
addr = msg [ 0 ] . buf [ 0 ] < < 8 | msg [ 0 ] . buf [ 1 ] < < 0 ;
2017-06-12 17:06:19 -03:00
mbox = msg [ 0 ] . buf [ 2 ] ;
addr_len = 3 ;
}
if ( num = = 1 & & ! ( msg [ 0 ] . flags & I2C_M_RD ) ) {
/* i2c write */
if ( msg [ 0 ] . len > 21 ) {
ret = - EOPNOTSUPP ;
goto err ;
}
2017-06-23 05:17:00 -04:00
if ( msg [ 0 ] . addr = = state - > af9013_i2c_addr [ 0 ] )
2017-06-12 17:06:19 -03:00
req . cmd = WRITE_MEMORY ;
else
req . cmd = WRITE_I2C ;
req . i2c_addr = msg [ 0 ] . addr ;
req . addr = addr ;
req . mbox = mbox ;
req . addr_len = addr_len ;
2018-03-13 19:27:57 -04:00
req . data_len = msg [ 0 ] . len - addr_len ;
2017-06-12 17:06:19 -03:00
req . data = & msg [ 0 ] . buf [ addr_len ] ;
ret = af9015_ctrl_msg ( d , & req ) ;
} else if ( num = = 2 & & ! ( msg [ 0 ] . flags & I2C_M_RD ) & &
( msg [ 1 ] . flags & I2C_M_RD ) ) {
/* i2c write + read */
if ( msg [ 0 ] . len > 3 | | msg [ 1 ] . len > 61 ) {
ret = - EOPNOTSUPP ;
goto err ;
}
2017-06-23 05:17:00 -04:00
if ( msg [ 0 ] . addr = = state - > af9013_i2c_addr [ 0 ] )
2017-06-12 17:06:19 -03:00
req . cmd = READ_MEMORY ;
else
2011-06-16 20:02:41 -03:00
req . cmd = READ_I2C ;
2017-06-12 17:06:19 -03:00
req . i2c_addr = msg [ 0 ] . addr ;
req . addr = addr ;
req . mbox = mbox ;
req . addr_len = addr_len ;
req . data_len = msg [ 1 ] . len ;
req . data = & msg [ 1 ] . buf [ 0 ] ;
ret = af9015_ctrl_msg ( d , & req ) ;
} else if ( num = = 1 & & ( msg [ 0 ] . flags & I2C_M_RD ) ) {
/* i2c read */
if ( msg [ 0 ] . len > 61 ) {
ret = - EOPNOTSUPP ;
goto err ;
2008-09-15 17:18:09 -03:00
}
2017-06-23 05:17:00 -04:00
if ( msg [ 0 ] . addr = = state - > af9013_i2c_addr [ 0 ] ) {
2017-06-12 17:06:19 -03:00
ret = - EINVAL ;
goto err ;
}
req . cmd = READ_I2C ;
req . i2c_addr = msg [ 0 ] . addr ;
req . addr = addr ;
req . mbox = mbox ;
req . addr_len = addr_len ;
req . data_len = msg [ 0 ] . len ;
req . data = & msg [ 0 ] . buf [ 0 ] ;
ret = af9015_ctrl_msg ( d , & req ) ;
} else {
ret = - EOPNOTSUPP ;
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " unknown msg, num %u \n " , num ) ;
2008-09-15 17:18:09 -03:00
}
2017-06-12 17:06:19 -03:00
if ( ret )
goto err ;
2008-09-15 17:18:09 -03:00
2017-06-12 17:06:19 -03:00
return num ;
err :
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " failed %d \n " , ret ) ;
2008-09-15 17:18:09 -03:00
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
{
2017-06-21 16:55:54 -04:00
struct usb_interface * intf = d - > intf ;
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 ;
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " reply %02x \n " , reply ) ;
2012-09-12 20:23:50 -03:00
2012-06-07 20:36:35 -03:00
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 ,
2017-06-26 06:02:59 -04:00
const struct firmware * firmware )
2008-09-15 17:18:09 -03:00
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = d_to_priv ( d ) ;
2017-06-21 16:55:54 -04:00
struct usb_interface * intf = d - > intf ;
2017-06-26 06:02:59 -04:00
int ret , i , rem ;
2012-06-07 20:36:35 -03:00
struct req_t req = { DOWNLOAD_FIRMWARE , 0 , 0 , 0 , 0 , 0 , NULL } ;
2017-06-26 06:02:59 -04:00
u16 checksum ;
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " \n " ) ;
2008-09-15 17:18:09 -03:00
2017-06-26 06:02:59 -04:00
/* Calc checksum, we need it when copy firmware to slave demod */
for ( i = 0 , checksum = 0 ; i < firmware - > size ; i + + )
checksum + = firmware - > data [ i ] ;
2008-09-15 17:18:09 -03:00
2017-06-26 06:02:59 -04:00
state - > firmware_size = firmware - > size ;
2012-06-07 20:36:35 -03:00
state - > firmware_checksum = checksum ;
2008-09-15 17:18:09 -03:00
2017-06-26 06:02:59 -04:00
# define LEN_MAX (BUF_LEN - REQ_HDR_LEN) /* Max payload size */
for ( rem = firmware - > size ; rem > 0 ; rem - = LEN_MAX ) {
req . data_len = min ( LEN_MAX , rem ) ;
2018-03-13 19:27:57 -04:00
req . data = ( u8 * ) & firmware - > data [ firmware - > size - rem ] ;
2017-06-26 06:02:59 -04:00
req . addr = 0x5100 + firmware - > size - rem ;
2012-06-07 20:36:35 -03:00
ret = af9015_ctrl_msg ( d , & req ) ;
if ( ret ) {
2017-06-21 16:55:54 -04:00
dev_err ( & intf - > dev , " firmware download failed %d \n " ,
ret ) ;
2017-06-26 06:02:59 -04:00
goto err ;
2012-06-07 20:36:35 -03:00
}
2008-09-15 17:18:09 -03:00
}
2012-06-07 20:36:35 -03:00
req . cmd = BOOT ;
req . data_len = 0 ;
ret = af9015_ctrl_msg ( d , & req ) ;
if ( ret ) {
2017-06-21 16:55:54 -04:00
dev_err ( & intf - > dev , " firmware boot failed %d \n " , ret ) ;
2017-06-26 06:02:59 -04:00
goto err ;
2008-09-15 17:18:09 -03:00
}
2012-06-07 20:36:35 -03:00
2017-06-26 06:02:59 -04:00
return 0 ;
err :
dev_dbg ( & intf - > dev , " failed %d \n " , ret ) ;
2012-06-07 20:36:35 -03:00
return ret ;
}
2013-11-02 07:52:04 -03:00
# define AF9015_EEPROM_SIZE 256
2016-05-26 23:00:23 -04:00
/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
# define GOLDEN_RATIO_PRIME_32 0x9e370001UL
2013-11-02 07:52:04 -03:00
2012-06-07 20:36:35 -03:00
/* 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 ) ;
2017-06-21 16:55:54 -04:00
struct usb_interface * intf = d - > intf ;
2012-09-12 20:23:51 -03:00
int ret , i ;
u8 buf [ AF9015_EEPROM_SIZE ] ;
struct req_t req = { READ_I2C , AF9015_I2C_EEPROM , 0 , 0 , 1 , 1 , NULL } ;
/* read eeprom */
for ( i = 0 ; i < AF9015_EEPROM_SIZE ; i + + ) {
req . addr = i ;
req . data = & buf [ i ] ;
2012-06-07 20:36:35 -03:00
ret = af9015_ctrl_msg ( d , & req ) ;
2012-09-12 20:23:51 -03:00
if ( ret < 0 )
goto err ;
2008-09-15 17:18:09 -03:00
}
2012-06-07 20:36:35 -03:00
2012-09-12 20:23:51 -03:00
/* calculate checksum */
for ( i = 0 ; i < AF9015_EEPROM_SIZE / sizeof ( u32 ) ; i + + ) {
2012-06-07 20:36:35 -03:00
state - > eeprom_sum * = GOLDEN_RATIO_PRIME_32 ;
2014-08-20 16:34:27 -03:00
state - > eeprom_sum + = le32_to_cpu ( ( ( __le32 * ) buf ) [ i ] ) ;
2008-09-15 17:18:09 -03:00
}
2012-09-12 20:23:51 -03:00
for ( i = 0 ; i < AF9015_EEPROM_SIZE ; i + = 16 )
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " %*ph \n " , 16 , buf + i ) ;
2012-09-12 20:23:51 -03:00
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " eeprom sum %.8x \n " , state - > eeprom_sum ) ;
2012-09-12 20:23:51 -03:00
return 0 ;
err :
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " failed %d \n " , ret ) ;
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 ) ;
2017-06-21 16:55:54 -04:00
struct usb_interface * intf = d - > intf ;
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
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " \n " ) ;
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
state - > ir_mode = val ;
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " ir mode %02x \n " , 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 ;
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " ts mode %02x \n " , state - > dual_mode ) ;
2010-01-22 12:10:52 -03:00
2017-06-23 05:17:00 -04:00
state - > af9013_i2c_addr [ 0 ] = AF9015_I2C_DEMOD ;
2017-02-05 18:09:38 -02: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 ;
2017-06-23 05:17:00 -04:00
state - > af9013_i2c_addr [ 1 ] = val > > 1 ;
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 :
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ i ] . clk = 28800000 ;
2008-09-15 17:18:09 -03:00
break ;
case 1 :
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ i ] . clk = 20480000 ;
2008-09-15 17:18:09 -03:00
break ;
case 2 :
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ i ] . clk = 28000000 ;
2008-09-15 17:18:09 -03:00
break ;
case 3 :
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ i ] . clk = 25000000 ;
2008-09-15 17:18:09 -03:00
break ;
2012-09-28 05:37:22 -03:00
}
2017-06-23 05:17:00 -04:00
dev_dbg ( & intf - > dev , " [%d] xtal %02x, clk %u \n " ,
i , val , state - > af9013_pdata [ i ] . clk ) ;
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
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ 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
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ i ] . if_frequency + = val ;
state - > af9013_pdata [ i ] . if_frequency * = 1000 ;
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " [%d] if frequency %u \n " ,
2017-06-23 05:17:00 -04:00
i , state - > af9013_pdata [ 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 ;
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " [%d] MT2060 IF1 %u \n " ,
i , 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 :
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ 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 :
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ 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 :
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ i ] . gpio [ 1 ] = AF9013_GPIO_LO ;
state - > af9013_pdata [ i ] . spec_inv = 1 ;
2009-02-02 14:59:50 -03:00
break ;
2008-09-15 17:18:09 -03:00
default :
2017-06-21 16:55:54 -04:00
dev_err ( & intf - > dev ,
" tuner id %02x not supported, please report! \n " ,
val ) ;
2008-09-15 17:18:09 -03:00
return - ENODEV ;
2012-09-28 05:37:22 -03:00
}
2008-09-15 17:18:09 -03:00
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ i ] . tuner = val ;
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " [%d] tuner id %02x \n " , i , val ) ;
2008-09-15 17:18:09 -03:00
}
error :
if ( ret )
2017-06-21 16:55:54 -04:00
dev_err ( & intf - > dev , " eeprom read failed %d \n " , ret ) ;
2008-09-15 17:18:09 -03:00
2018-03-13 19:27:57 -04:00
/*
* AverMedia AVerTV Volar Black HD ( A850 ) device have bad EEPROM
* 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 & &
2018-03-13 19:27:57 -04:00
( ( le16_to_cpu ( d - > udev - > descriptor . idProduct ) = = USB_PID_AVERMEDIA_A850 ) | |
( le16_to_cpu ( d - > udev - > descriptor . idProduct ) = = USB_PID_AVERMEDIA_A850T ) ) ) {
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " AverMedia A850: overriding config \n " ) ;
2009-03-31 17:01:02 -03:00
/* 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 */
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ 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 ,
2018-03-13 19:27:57 -04:00
struct usb_data_stream_properties * stream )
2008-09-15 17:18:09 -03:00
{
2012-09-12 20:23:50 -03:00
struct dvb_usb_device * d = fe_to_d ( fe ) ;
2017-06-21 16:55:54 -04:00
struct usb_interface * intf = d - > intf ;
dev_dbg ( & intf - > dev , " adap %u \n " , fe_to_adap ( fe ) - > id ) ;
2010-09-12 13:31:56 -03:00
2012-09-12 20:23:50 -03:00
if ( d - > udev - > speed = = USB_SPEED_FULL )
2017-07-13 01:56:41 -04:00
stream - > u . bulk . buffersize = 5 * 188 ;
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
2017-07-13 01:56:41 -04:00
static int af9015_streaming_ctrl ( struct dvb_frontend * fe , int onoff )
{
struct dvb_usb_device * d = fe_to_d ( fe ) ;
struct af9015_state * state = d_to_priv ( d ) ;
struct usb_interface * intf = d - > intf ;
int ret ;
unsigned int utmp1 , utmp2 , reg1 , reg2 ;
u8 buf [ 2 ] ;
const unsigned int adap_id = fe_to_adap ( fe ) - > id ;
dev_dbg ( & intf - > dev , " adap id %d, onoff %d \n " , adap_id , onoff ) ;
2018-03-13 19:27:57 -04:00
if ( ! state - > usb_ts_if_configured [ adap_id ] ) {
2017-07-13 01:56:41 -04:00
dev_dbg ( & intf - > dev , " set usb and ts interface \n " ) ;
/* USB IF stream settings */
utmp1 = ( d - > udev - > speed = = USB_SPEED_FULL ? 5 : 87 ) * 188 / 4 ;
utmp2 = ( d - > udev - > speed = = USB_SPEED_FULL ? 64 : 512 ) / 4 ;
buf [ 0 ] = ( utmp1 > > 0 ) & 0xff ;
buf [ 1 ] = ( utmp1 > > 8 ) & 0xff ;
if ( adap_id = = 0 ) {
/* 1st USB IF (EP4) stream settings */
reg1 = 0xdd88 ;
reg2 = 0xdd0c ;
} else {
/* 2nd USB IF (EP5) stream settings */
reg1 = 0xdd8a ;
reg2 = 0xdd0d ;
}
2017-07-13 02:42:52 -04:00
ret = regmap_bulk_write ( state - > regmap , reg1 , buf , 2 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
2017-07-13 02:42:52 -04:00
ret = regmap_write ( state - > regmap , reg2 , utmp2 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
/* TS IF settings */
if ( state - > dual_mode ) {
2017-07-13 02:42:52 -04:00
utmp1 = 0x01 ;
utmp2 = 0x10 ;
2017-07-13 01:56:41 -04:00
} else {
2017-07-13 02:42:52 -04:00
utmp1 = 0x00 ;
utmp2 = 0x00 ;
2017-07-13 01:56:41 -04:00
}
2017-07-13 02:42:52 -04:00
ret = regmap_update_bits ( state - > regmap , 0xd50b , 0x01 , utmp1 ) ;
if ( ret )
goto err ;
ret = regmap_update_bits ( state - > regmap , 0xd520 , 0x10 , utmp2 ) ;
if ( ret )
goto err ;
2017-07-13 01:56:41 -04:00
state - > usb_ts_if_configured [ adap_id ] = true ;
}
if ( adap_id = = 0 & & onoff ) {
/* Adapter 0 stream on. EP4: clear NAK, enable, clear reset */
2017-07-13 02:42:52 -04:00
ret = regmap_update_bits ( state - > regmap , 0xdd13 , 0x20 , 0x00 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
2017-07-13 02:42:52 -04:00
ret = regmap_update_bits ( state - > regmap , 0xdd11 , 0x20 , 0x20 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
2017-07-13 02:42:52 -04:00
ret = regmap_update_bits ( state - > regmap , 0xd507 , 0x04 , 0x00 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
} else if ( adap_id = = 1 & & onoff ) {
/* Adapter 1 stream on. EP5: clear NAK, enable, clear reset */
2017-07-13 02:42:52 -04:00
ret = regmap_update_bits ( state - > regmap , 0xdd13 , 0x40 , 0x00 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
2017-07-13 02:42:52 -04:00
ret = regmap_update_bits ( state - > regmap , 0xdd11 , 0x40 , 0x40 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
2017-07-13 02:42:52 -04:00
ret = regmap_update_bits ( state - > regmap , 0xd50b , 0x02 , 0x00 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
} else if ( adap_id = = 0 & & ! onoff ) {
/* Adapter 0 stream off. EP4: set reset, disable, set NAK */
2017-07-13 02:42:52 -04:00
ret = regmap_update_bits ( state - > regmap , 0xd507 , 0x04 , 0x04 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
2017-07-13 02:42:52 -04:00
ret = regmap_update_bits ( state - > regmap , 0xdd11 , 0x20 , 0x00 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
2017-07-13 02:42:52 -04:00
ret = regmap_update_bits ( state - > regmap , 0xdd13 , 0x20 , 0x20 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
} else if ( adap_id = = 1 & & ! onoff ) {
/* Adapter 1 stream off. EP5: set reset, disable, set NAK */
2017-07-13 02:42:52 -04:00
ret = regmap_update_bits ( state - > regmap , 0xd50b , 0x02 , 0x02 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
2017-07-13 02:42:52 -04:00
ret = regmap_update_bits ( state - > regmap , 0xdd11 , 0x40 , 0x00 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
2017-07-13 02:42:52 -04:00
ret = regmap_update_bits ( state - > regmap , 0xdd13 , 0x40 , 0x40 ) ;
2017-07-13 01:56:41 -04:00
if ( ret )
goto err ;
}
return 0 ;
err :
dev_dbg ( & intf - > dev , " failed %d \n " , ret ) ;
return ret ;
}
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 ) ;
2018-03-13 19:27:57 -04:00
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 ,
2018-03-13 19:27:57 -04:00
enum fe_status * status )
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 - > 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 ) ;
2017-06-21 16:55:54 -04:00
struct usb_interface * intf = d - > intf ;
2012-06-07 20:36:35 -03:00
int ret ;
2017-06-26 07:15:27 -04:00
unsigned long timeout ;
u8 val , firmware_info [ 4 ] ;
struct req_t req = { COPY_FIRMWARE , 0 , 0x5100 , 0 , 0 , 4 , firmware_info } ;
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " \n " ) ;
2012-06-07 20:36:35 -03:00
2017-06-26 07:15:27 -04:00
firmware_info [ 0 ] = ( state - > firmware_size > > 8 ) & 0xff ;
firmware_info [ 1 ] = ( state - > firmware_size > > 0 ) & 0xff ;
firmware_info [ 2 ] = ( state - > firmware_checksum > > 8 ) & 0xff ;
firmware_info [ 3 ] = ( state - > firmware_checksum > > 0 ) & 0xff ;
2012-06-07 20:36:35 -03:00
2017-06-26 07:15:27 -04:00
/* Check whether firmware is already running */
ret = af9015_read_reg_i2c ( d , state - > af9013_i2c_addr [ 1 ] , 0x98be , & val ) ;
2012-06-07 20:36:35 -03:00
if ( ret )
2017-06-26 07:15:27 -04:00
goto err ;
2012-06-07 20:36:35 -03:00
2017-06-26 07:15:27 -04:00
dev_dbg ( & intf - > dev , " firmware status %02x \n " , val ) ;
2012-06-07 20:36:35 -03:00
2017-06-26 07:15:27 -04:00
if ( val = = 0x0c )
return 0 ;
2012-06-07 20:36:35 -03:00
2017-06-26 07:15:27 -04:00
/* Set i2c clock to 625kHz to speed up firmware copy */
2017-07-13 02:42:52 -04:00
ret = regmap_write ( state - > regmap , 0xd416 , 0x04 ) ;
2017-06-26 07:15:27 -04:00
if ( ret )
goto err ;
2012-06-07 20:36:35 -03:00
2017-06-26 07:15:27 -04:00
/* Copy firmware from master demod to slave demod */
2012-06-07 20:36:35 -03:00
ret = af9015_ctrl_msg ( d , & req ) ;
2017-06-26 07:15:27 -04:00
if ( ret ) {
2017-06-21 16:55:54 -04:00
dev_err ( & intf - > dev , " firmware copy cmd failed %d \n " , ret ) ;
2017-06-26 07:15:27 -04:00
goto err ;
}
2012-09-12 20:23:50 -03:00
2017-06-26 07:15:27 -04:00
/* Set i2c clock to 125kHz */
2017-07-13 02:42:52 -04:00
ret = regmap_write ( state - > regmap , 0xd416 , 0x14 ) ;
2012-06-07 20:36:35 -03:00
if ( ret )
2017-06-26 07:15:27 -04:00
goto err ;
2012-06-07 20:36:35 -03:00
2017-06-26 07:15:27 -04:00
/* Boot firmware */
ret = af9015_write_reg_i2c ( d , state - > af9013_i2c_addr [ 1 ] , 0xe205 , 0x01 ) ;
2012-06-07 20:36:35 -03:00
if ( ret )
2017-06-26 07:15:27 -04:00
goto err ;
2012-06-07 20:36:35 -03:00
2017-06-26 07:15:27 -04:00
/* Poll firmware ready */
for ( val = 0x00 , timeout = jiffies + msecs_to_jiffies ( 1000 ) ;
! time_after ( jiffies , timeout ) & & val ! = 0x0c & & val ! = 0x04 ; ) {
msleep ( 20 ) ;
2012-03-14 10:27:31 -03:00
2017-06-26 07:15:27 -04:00
/* Check firmware status. 0c=OK, 04=fail */
2017-06-23 05:17:00 -04:00
ret = af9015_read_reg_i2c ( d , state - > af9013_i2c_addr [ 1 ] ,
2017-06-26 07:15:27 -04:00
0x98be , & val ) ;
2012-06-07 20:36:35 -03:00
if ( ret )
2017-06-26 07:15:27 -04:00
goto err ;
2012-03-14 10:27:31 -03:00
2017-06-26 07:15:27 -04:00
dev_dbg ( & intf - > dev , " firmware status %02x \n " , val ) ;
2012-06-07 20:36:35 -03:00
}
2017-06-26 07:15:27 -04:00
dev_dbg ( & intf - > dev , " firmware boot took %u ms \n " ,
jiffies_to_msecs ( jiffies ) - ( jiffies_to_msecs ( timeout ) - 1000 ) ) ;
2012-06-07 20:36:35 -03:00
if ( val = = 0x04 ) {
2017-06-26 07:15:27 -04:00
ret = - ENODEV ;
2017-06-21 16:55:54 -04:00
dev_err ( & intf - > dev , " firmware did not run \n " ) ;
2017-06-26 07:15:27 -04:00
goto err ;
2012-06-07 20:36:35 -03:00
} else if ( val ! = 0x0c ) {
2012-09-12 20:23:52 -03:00
ret = - ETIMEDOUT ;
2017-06-21 16:55:54 -04:00
dev_err ( & intf - > dev , " firmware boot timeout \n " ) ;
2017-06-26 07:15:27 -04:00
goto err ;
2012-06-07 20:36:35 -03:00
}
2017-06-26 07:15:27 -04:00
return 0 ;
err :
dev_dbg ( & intf - > dev , " failed %d \n " , ret ) ;
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 )
{
2012-06-16 18:13:06 -03:00
struct af9015_state * state = adap_to_priv ( adap ) ;
2017-06-21 16:55:54 -04:00
struct dvb_usb_device * d = adap_to_d ( adap ) ;
struct usb_interface * intf = d - > intf ;
2017-06-23 05:17:00 -04:00
struct i2c_client * client ;
2017-06-21 16:55:54 -04:00
int ret ;
2008-09-15 17:18:09 -03:00
2017-06-23 05:17:00 -04:00
dev_dbg ( & intf - > dev , " adap id %u \n " , adap - > id ) ;
2012-06-07 20:36:35 -03:00
if ( adap - > id = = 0 ) {
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ 0 ] . ts_mode = AF9013_TS_MODE_USB ;
memcpy ( state - > af9013_pdata [ 0 ] . api_version , " \ x0 \ x1 \ x9 \ x0 " , 4 ) ;
state - > af9013_pdata [ 0 ] . gpio [ 0 ] = AF9013_GPIO_HI ;
state - > af9013_pdata [ 0 ] . gpio [ 3 ] = AF9013_GPIO_TUNER_ON ;
2012-06-07 20:36:35 -03:00
} else if ( adap - > id = = 1 ) {
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ 1 ] . ts_mode = AF9013_TS_MODE_SERIAL ;
state - > af9013_pdata [ 1 ] . ts_output_pin = 7 ;
memcpy ( state - > af9013_pdata [ 1 ] . api_version , " \ x0 \ x1 \ x9 \ x0 " , 4 ) ;
state - > af9013_pdata [ 1 ] . gpio [ 0 ] = AF9013_GPIO_TUNER_ON ;
state - > af9013_pdata [ 1 ] . gpio [ 1 ] = AF9013_GPIO_LO ;
2012-06-07 20:36:35 -03:00
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 ) {
2017-06-13 21:32:08 -03:00
/* Wait 2nd demodulator ready */
msleep ( 100 ) ;
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 ) {
2017-06-21 16:55:54 -04:00
dev_err ( & intf - > dev ,
" firmware copy to 2nd frontend failed, will disable it \n " ) ;
2012-06-07 20:36:35 -03:00
state - > dual_mode = 0 ;
2017-06-23 05:17:00 -04:00
goto err ;
2008-09-15 17:18:09 -03:00
}
} else {
2017-06-23 05:17:00 -04:00
ret = - ENODEV ;
goto err ;
2008-09-15 17:18:09 -03:00
}
}
2017-06-23 05:17:00 -04:00
/* Add I2C demod */
client = dvb_module_probe ( " af9013 " , NULL , & d - > i2c_adap ,
state - > af9013_i2c_addr [ adap - > id ] ,
& state - > af9013_pdata [ adap - > id ] ) ;
if ( ! client ) {
ret = - ENODEV ;
goto err ;
}
adap - > fe [ 0 ] = state - > af9013_pdata [ adap - > id ] . get_dvb_frontend ( client ) ;
state - > demod_i2c_client [ adap - > id ] = client ;
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 ] ) {
2018-03-13 19:27:57 -04:00
state - > set_frontend [ adap - > id ] = adap - > fe [ 0 ] - > ops . set_frontend ;
adap - > fe [ 0 ] - > ops . set_frontend = af9015_af9013_set_frontend ;
state - > read_status [ adap - > id ] = adap - > fe [ 0 ] - > ops . read_status ;
adap - > fe [ 0 ] - > ops . read_status = 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 ;
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
}
2017-06-23 05:17:00 -04:00
return 0 ;
err :
dev_dbg ( & intf - > dev , " failed %d \n " , ret ) ;
return ret ;
}
static int af9015_frontend_detach ( struct dvb_usb_adapter * adap )
{
struct af9015_state * state = adap_to_priv ( adap ) ;
struct dvb_usb_device * d = adap_to_d ( adap ) ;
struct usb_interface * intf = d - > intf ;
struct i2c_client * client ;
dev_dbg ( & intf - > dev , " adap id %u \n " , adap - > id ) ;
/* Remove I2C demod */
client = state - > demod_i2c_client [ adap - > id ] ;
dvb_module_release ( client ) ;
return 0 ;
2008-09-15 17:18:09 -03:00
}
static struct mt2060_config af9015_mt2060_config = {
2017-02-05 18:09:38 -02:00
. i2c_address = 0x60 ,
2008-09-15 17:18:09 -03:00
. clock_out = 0 ,
} ;
static struct qt1010_config af9015_qt1010_config = {
2017-02-05 18:09:38 -02:00
. i2c_address = 0x62 ,
2008-09-15 17:18:09 -03:00
} ;
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 = {
2017-02-05 18:09:38 -02:00
. i2c_address = 0x63 ,
2008-09-15 17:18:09 -03:00
. 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 = {
2017-02-05 18:09:38 -02:00
. i2c_address = 0x63 ,
2008-09-15 17:18:09 -03:00
. 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 = {
2017-02-05 18:09:38 -02:00
. i2c_address = 0x60 ,
2009-02-02 14:59:50 -03:00
. dig_out = 1 ,
} ;
2010-08-13 03:51:26 -03:00
static struct tda18218_config af9015_tda18218_config = {
2017-02-05 18:09:38 -02:00
. i2c_address = 0x60 ,
2010-08-13 03:51:26 -03:00
. 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-09-12 20:23:50 -03:00
struct dvb_usb_device * d = adap_to_d ( adap ) ;
struct af9015_state * state = d_to_priv ( d ) ;
2017-06-21 16:55:54 -04:00
struct usb_interface * intf = d - > intf ;
2017-06-23 05:17:00 -04:00
struct i2c_client * client ;
struct i2c_adapter * adapter ;
2012-06-07 20:36:35 -03:00
int ret ;
2017-06-21 16:55:54 -04:00
2017-06-23 05:17:00 -04:00
dev_dbg ( & intf - > dev , " adap id %u \n " , adap - > id ) ;
client = state - > demod_i2c_client [ adap - > id ] ;
adapter = state - > af9013_pdata [ adap - > id ] . get_i2c_adapter ( client ) ;
2008-09-15 17:18:09 -03:00
2017-06-23 05:17:00 -04:00
switch ( state - > af9013_pdata [ adap - > id ] . tuner ) {
2008-09-15 17:18:09 -03:00
case AF9013_TUNER_MT2060 :
case AF9013_TUNER_MT2060_2 :
2017-06-23 05:17:00 -04:00
ret = dvb_attach ( mt2060_attach , adap - > fe [ 0 ] , adapter ,
2018-03-13 19:27:57 -04:00
& af9015_mt2060_config ,
state - > mt2060_if1 [ adap - > id ] ) = = NULL ? - ENODEV : 0 ;
2008-09-15 17:18:09 -03:00
break ;
case AF9013_TUNER_QT1010 :
case AF9013_TUNER_QT1010A :
2017-06-23 05:17:00 -04:00
ret = dvb_attach ( qt1010_attach , adap - > fe [ 0 ] , adapter ,
2018-03-13 19:27:57 -04:00
& af9015_qt1010_config ) = = NULL ? - ENODEV : 0 ;
2008-09-15 17:18:09 -03:00
break ;
case AF9013_TUNER_TDA18271 :
2017-06-23 05:17:00 -04:00
ret = dvb_attach ( tda18271_attach , adap - > fe [ 0 ] , 0x60 , adapter ,
2018-03-13 19:27:57 -04:00
& af9015_tda18271_config ) = = NULL ? - ENODEV : 0 ;
2008-09-15 17:18:09 -03:00
break ;
2010-08-13 03:51:26 -03:00
case AF9013_TUNER_TDA18218 :
2017-06-23 05:17:00 -04:00
ret = dvb_attach ( tda18218_attach , adap - > fe [ 0 ] , adapter ,
2018-03-13 19:27:57 -04:00
& af9015_tda18218_config ) = = NULL ? - ENODEV : 0 ;
2010-08-13 03:51:26 -03:00
break ;
2008-09-15 17:18:09 -03:00
case AF9013_TUNER_MXL5003D :
2017-06-23 05:17:00 -04:00
ret = dvb_attach ( mxl5005s_attach , adap - > fe [ 0 ] , adapter ,
2018-03-13 19:27:57 -04:00
& af9015_mxl5003_config ) = = NULL ? - ENODEV : 0 ;
2008-09-15 17:18:09 -03:00
break ;
case AF9013_TUNER_MXL5005D :
case AF9013_TUNER_MXL5005R :
2017-06-23 05:17:00 -04:00
ret = dvb_attach ( mxl5005s_attach , adap - > fe [ 0 ] , adapter ,
2018-03-13 19:27:57 -04:00
& af9015_mxl5005_config ) = = NULL ? - ENODEV : 0 ;
2008-09-15 17:18:09 -03:00
break ;
case AF9013_TUNER_ENV77H11D5 :
2017-06-23 05:17:00 -04:00
ret = dvb_attach ( dvb_pll_attach , adap - > fe [ 0 ] , 0x60 , adapter ,
2018-03-13 19:27:57 -04:00
DVB_PLL_TDA665X ) = = NULL ? - ENODEV : 0 ;
2008-09-15 17:18:09 -03:00
break ;
case AF9013_TUNER_MC44S803 :
2017-06-23 05:17:00 -04:00
ret = dvb_attach ( mc44s803_attach , adap - > fe [ 0 ] , adapter ,
2018-03-13 19:27:57 -04: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 :
2017-06-23 05:17:00 -04:00
ret = dvb_attach ( mxl5007t_attach , adap - > fe [ 0 ] , adapter ,
2018-03-13 19:27:57 -04:00
0x60 , & af9015_mxl5007t_config ) = = NULL ? - ENODEV : 0 ;
2010-09-09 14:59:10 -03:00
break ;
2008-09-15 17:18:09 -03:00
case AF9013_TUNER_UNKNOWN :
default :
2017-06-21 16:55:54 -04:00
dev_err ( & intf - > dev , " unknown tuner, tuner id %02x \n " ,
2017-06-23 05:17:00 -04:00
state - > af9013_pdata [ adap - > id ] . tuner ) ;
2008-09-15 17:18:09 -03:00
ret = - ENODEV ;
}
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 )
{
2017-06-26 05:02:50 -04:00
struct af9015_state * state = adap_to_priv ( adap ) ;
struct af9013_platform_data * pdata = & state - > af9013_pdata [ adap - > id ] ;
2012-06-07 20:36:35 -03:00
int ret ;
2017-06-21 16:55:54 -04:00
2017-06-26 05:02:50 -04:00
mutex_lock ( & state - > fe_mutex ) ;
ret = pdata - > pid_filter_ctrl ( adap - > fe [ 0 ] , onoff ) ;
mutex_unlock ( & state - > fe_mutex ) ;
2012-06-07 20:36:35 -03:00
return ret ;
}
2017-06-26 05:02:50 -04:00
static int af9015_pid_filter ( struct dvb_usb_adapter * adap , int index ,
u16 pid , int onoff )
2012-06-07 20:36:35 -03:00
{
2017-06-26 05:02:50 -04:00
struct af9015_state * state = adap_to_priv ( adap ) ;
struct af9013_platform_data * pdata = & state - > af9013_pdata [ adap - > id ] ;
2012-06-07 20:36:35 -03:00
int ret ;
2017-06-26 05:02:50 -04:00
mutex_lock ( & state - > fe_mutex ) ;
ret = pdata - > pid_filter ( adap - > fe [ 0 ] , index , pid , onoff ) ;
mutex_unlock ( & state - > fe_mutex ) ;
2012-06-07 20:36:35 -03:00
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 ) ;
2017-06-21 16:55:54 -04:00
struct usb_interface * intf = d - > intf ;
2012-06-07 20:36:35 -03:00
int ret ;
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " \n " ) ;
2012-06-07 20:36:35 -03:00
mutex_init ( & state - > fe_mutex ) ;
/* init RC canary */
2017-07-13 02:42:52 -04:00
ret = regmap_write ( state - > regmap , 0x98e9 , 0xff ) ;
2012-06-07 20:36:35 -03:00
if ( ret )
goto error ;
error :
2008-09-15 17:18:09 -03:00
return ret ;
}
2013-01-04 15:21:26 -03:00
# if IS_ENABLED(CONFIG_RC_CORE)
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 ,
2018-03-13 19:27:57 -04:00
const struct af9015_rc_setup * table )
2012-06-07 20:36:35 -03:00
{
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 ) ;
2017-06-21 16:55:54 -04:00
struct usb_interface * intf = d - > intf ;
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
/* read registers needed to detect remote controller code */
2017-07-13 02:42:52 -04:00
ret = regmap_bulk_read ( state - > regmap , 0x98d9 , buf , sizeof ( buf ) ) ;
2012-06-07 20:36:35 -03:00
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 */
2012-09-12 20:23:50 -03:00
if ( buf [ 1 ] | | buf [ 2 ] | | buf [ 3 ] ) {
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " invalid data \n " ) ;
2012-06-07 20:36:35 -03:00
return ret ;
2012-09-12 20:23:50 -03:00
}
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 ] ) & &
2018-03-13 19:27:57 -04:00
! memcmp ( & buf [ 12 ] , state - > rc_last , 4 ) ) {
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " key repeated \n " ) ;
2014-04-03 20:31:30 -03:00
rc_repeat ( d - > rc_dev ) ;
2012-06-07 20:36:35 -03:00
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 ) {
2017-08-07 16:20:58 -04:00
enum rc_proto proto ;
2018-03-13 19:27:57 -04:00
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " key pressed %*ph \n " , 4 , buf + 12 ) ;
2009-04-09 09:16:12 -03:00
2012-06-07 20:36:35 -03:00
/* Reset the canary */
2017-07-13 02:42:52 -04:00
ret = regmap_write ( state - > regmap , 0x98e9 , 0xff ) ;
2012-06-07 20:36:35 -03:00
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 ) ;
2018-03-13 19:27:57 -04:00
if ( buf [ 14 ] = = ( u8 ) ~ buf [ 15 ] ) {
if ( buf [ 12 ] = = ( u8 ) ~ buf [ 13 ] ) {
2012-06-07 20:36:35 -03:00
/* NEC */
2014-04-03 20:31:30 -03:00
state - > rc_keycode = RC_SCANCODE_NEC ( buf [ 12 ] ,
buf [ 14 ] ) ;
2017-08-07 16:20:58 -04:00
proto = RC_PROTO_NEC ;
2012-06-07 20:36:35 -03:00
} else {
/* NEC extended*/
2014-04-03 20:31:30 -03:00
state - > rc_keycode = RC_SCANCODE_NECX ( buf [ 12 ] < < 8 |
buf [ 13 ] ,
buf [ 14 ] ) ;
2017-08-07 16:20:58 -04:00
proto = RC_PROTO_NECX ;
2012-06-07 20:36:35 -03:00
}
} else {
/* 32 bit NEC */
2014-04-03 20:31:30 -03:00
state - > rc_keycode = RC_SCANCODE_NEC32 ( buf [ 12 ] < < 24 |
buf [ 13 ] < < 16 |
buf [ 14 ] < < 8 |
buf [ 15 ] ) ;
2017-08-07 16:20:58 -04:00
proto = RC_PROTO_NEC32 ;
2009-04-09 09:16:12 -03:00
}
2016-09-21 06:54:19 -03:00
rc_keydown ( d - > rc_dev , proto , state - > rc_keycode , 0 ) ;
2012-06-07 20:36:35 -03:00
} else {
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " no key press \n " ) ;
2012-06-07 20:36:35 -03:00
/* Invalidate last keypress */
/* Not really needed, but helps with debug */
state - > rc_last [ 2 ] = state - > rc_last [ 3 ] ;
}
state - > rc_repeat = buf [ 6 ] ;
2012-07-24 21:21:04 -03:00
state - > rc_failed = false ;
2012-06-07 20:36:35 -03:00
error :
2012-07-24 21:21:04 -03:00
if ( ret ) {
2017-06-21 16:55:54 -04:00
dev_warn ( & intf - > dev , " rc query failed %d \n " , ret ) ;
2012-06-07 20:36:35 -03:00
2012-07-24 21:21:04 -03:00
/* allow random errors as dvb-usb will stop polling on error */
if ( ! state - > rc_failed )
ret = 0 ;
state - > rc_failed = true ;
}
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_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 */
2012-07-24 21:21:04 -03:00
if ( ! rc - > map_name )
rc - > map_name = af9015_rc_setup_match ( dvb_usb_af9015_remote ,
2018-03-13 19:27:57 -04:00
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 ,
2018-03-13 19:27:57 -04:00
af9015_rc_setup_hashes ) ;
2012-06-07 20:36:35 -03:00
/* try to load remote based USB iManufacturer string */
if ( ! rc - > map_name & & vid = = USB_VID_AFATECH ) {
2018-03-13 19:27:57 -04:00
/*
* 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 .
*/
2012-06-07 20:36:35 -03:00
char manufacturer [ 10 ] ;
2018-03-13 19:27:57 -04:00
2012-06-07 20:36:35 -03:00
memset ( manufacturer , 0 , sizeof ( manufacturer ) ) ;
usb_string ( d - > udev , d - > udev - > descriptor . iManufacturer ,
2018-03-13 19:27:57 -04:00
manufacturer , sizeof ( manufacturer ) ) ;
2012-06-07 20:36:35 -03:00
if ( ! strcmp ( " MSI " , manufacturer ) ) {
2018-03-13 19:27:57 -04:00
/*
* 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 ) ;
2012-06-07 20:36:35 -03:00
}
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 ;
2017-08-07 16:20:58 -04:00
rc - > allowed_protos = RC_PROTO_BIT_NEC | RC_PROTO_BIT_NECX |
RC_PROTO_BIT_NEC32 ;
2012-06-07 20:36:35 -03:00
rc - > query = af9015_rc_query ;
rc - > interval = 500 ;
return 0 ;
2008-09-15 17:18:09 -03:00
}
2012-12-09 20:15:47 -03:00
# else
# define af9015_get_rc_config NULL
# endif
2008-09-15 17:18:09 -03:00
2017-07-13 02:42:52 -04:00
static int af9015_regmap_write ( void * context , const void * data , size_t count )
{
struct dvb_usb_device * d = context ;
struct usb_interface * intf = d - > intf ;
int ret ;
u16 reg = ( ( u8 * ) data ) [ 0 ] < < 8 | ( ( u8 * ) data ) [ 1 ] < < 0 ;
u8 * val = & ( ( u8 * ) data ) [ 2 ] ;
const unsigned int len = count - 2 ;
struct req_t req = { WRITE_MEMORY , 0 , reg , 0 , 0 , len , val } ;
ret = af9015_ctrl_msg ( d , & req ) ;
if ( ret )
goto err ;
return 0 ;
err :
dev_dbg ( & intf - > dev , " failed %d \n " , ret ) ;
return ret ;
}
static int af9015_regmap_read ( void * context , const void * reg_buf ,
size_t reg_size , void * val_buf , size_t val_size )
{
struct dvb_usb_device * d = context ;
struct usb_interface * intf = d - > intf ;
int ret ;
u16 reg = ( ( u8 * ) reg_buf ) [ 0 ] < < 8 | ( ( u8 * ) reg_buf ) [ 1 ] < < 0 ;
u8 * val = & ( ( u8 * ) val_buf ) [ 0 ] ;
const unsigned int len = val_size ;
struct req_t req = { READ_MEMORY , 0 , reg , 0 , 0 , len , val } ;
ret = af9015_ctrl_msg ( d , & req ) ;
if ( ret )
goto err ;
return 0 ;
err :
dev_dbg ( & intf - > dev , " failed %d \n " , ret ) ;
return ret ;
}
static int af9015_probe ( struct dvb_usb_device * d )
2013-01-07 16:29:13 -03:00
{
2017-07-13 02:42:52 -04:00
struct af9015_state * state = d_to_priv ( d ) ;
struct usb_interface * intf = d - > intf ;
2013-01-07 16:29:13 -03:00
struct usb_device * udev = interface_to_usbdev ( intf ) ;
2017-07-13 02:42:52 -04:00
int ret ;
2013-01-07 16:29:13 -03:00
char manufacturer [ sizeof ( " ITE Technologies, Inc. " ) ] ;
2017-07-13 02:42:52 -04:00
static const struct regmap_config regmap_config = {
. reg_bits = 16 ,
. val_bits = 8 ,
} ;
static const struct regmap_bus regmap_bus = {
. read = af9015_regmap_read ,
. write = af9015_regmap_write ,
} ;
dev_dbg ( & intf - > dev , " \n " ) ;
2013-01-07 16:29:13 -03:00
memset ( manufacturer , 0 , sizeof ( manufacturer ) ) ;
usb_string ( udev , udev - > descriptor . iManufacturer ,
2017-07-13 02:42:52 -04:00
manufacturer , sizeof ( manufacturer ) ) ;
2013-01-07 16:29:13 -03:00
/*
* There is two devices having same ID but different chipset . One uses
* AF9015 and the other IT9135 chipset . Only difference seen on lsusb
* is iManufacturer string .
*
* idVendor 0x0ccd TerraTec Electronic GmbH
* idProduct 0x0099
* bcdDevice 2.00
* iManufacturer 1 Afatech
* iProduct 2 DVB - T 2
*
* idVendor 0x0ccd TerraTec Electronic GmbH
* idProduct 0x0099
* bcdDevice 2.00
* iManufacturer 1 ITE Technologies , Inc .
* iProduct 2 DVB - T TV Stick
*/
if ( ( le16_to_cpu ( udev - > descriptor . idVendor ) = = USB_VID_TERRATEC ) & &
2017-07-13 02:42:52 -04:00
( le16_to_cpu ( udev - > descriptor . idProduct ) = = 0x0099 ) ) {
2013-01-07 16:29:13 -03:00
if ( ! strcmp ( " ITE Technologies, Inc. " , manufacturer ) ) {
2017-07-13 02:42:52 -04:00
ret = - ENODEV ;
2017-06-21 16:55:54 -04:00
dev_dbg ( & intf - > dev , " rejecting device \n " ) ;
2017-07-13 02:42:52 -04:00
goto err ;
2013-01-07 16:29:13 -03:00
}
}
2017-07-13 02:42:52 -04:00
state - > regmap = regmap_init ( & intf - > dev , & regmap_bus , d , & regmap_config ) ;
if ( IS_ERR ( state - > regmap ) ) {
ret = PTR_ERR ( state - > regmap ) ;
goto err ;
}
return 0 ;
err :
dev_dbg ( & intf - > dev , " failed %d \n " , ret ) ;
return ret ;
}
static void af9015_disconnect ( struct dvb_usb_device * d )
{
struct af9015_state * state = d_to_priv ( d ) ;
struct usb_interface * intf = d - > intf ;
dev_dbg ( & intf - > dev , " \n " ) ;
regmap_exit ( state - > regmap ) ;
2013-01-07 16:29:13 -03:00
}
2018-03-13 19:27:57 -04:00
/*
* Interface 0 is used by DVB - T receiver and
* interface 1 is for remote controller ( HID )
*/
2017-07-13 02:42:52 -04:00
static const struct dvb_usb_device_properties af9015_props = {
2012-06-07 20:36:35 -03:00
. 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 ,
2017-07-13 02:42:52 -04:00
. probe = af9015_probe ,
. disconnect = af9015_disconnect ,
2012-06-07 20:36:35 -03:00
. identify_state = af9015_identify_state ,
2012-09-12 11:37:25 -03:00
. firmware = AF9015_FIRMWARE ,
2012-06-07 20:36:35 -03:00
. 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 ,
2017-06-23 05:17:00 -04:00
. frontend_detach = af9015_frontend_detach ,
2012-06-12 01:05:20 -03:00
. 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 ,
2017-07-13 01:56:41 -04:00
. streaming_ctrl = af9015_streaming_ctrl ,
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
2017-07-13 01:56:41 -04:00
. stream = DVB_USB_STREAM_BULK ( 0x84 , 6 , 87 * 188 ) ,
2012-06-16 16:25:22 -03:00
} , {
2017-06-26 05:02:50 -04:00
. 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 ,
2017-07-13 01:56:41 -04:00
. stream = DVB_USB_STREAM_BULK ( 0x85 , 6 , 87 * 188 ) ,
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 ,
2016-09-17 23:44:17 +09:00
& af9015_props , " KWorld Digital MC-810 " , NULL ) } ,
2012-06-07 20:36:35 -03:00
{ 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 ) } ,
2013-01-07 16:29:13 -03:00
/* XXX: that same ID [0ccd:0099] is used by af9035 driver too */
2012-06-07 20:36:35 -03:00
{ 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 ,
2017-07-13 02:42:52 -04:00
. probe = dvb_usbv2_probe ,
2012-06-07 20:36:35 -03:00
. disconnect = dvb_usbv2_disconnect ,
2012-06-12 02:20:01 -03:00
. suspend = dvb_usbv2_suspend ,
. resume = dvb_usbv2_resume ,
2012-08-14 22:21:08 -03:00
. reset_resume = dvb_usbv2_reset_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 " ) ;
2012-09-12 11:37:25 -03:00
MODULE_FIRMWARE ( AF9015_FIRMWARE ) ;