2011-07-08 23:36:07 -03:00
/*
* Realtek RTL28xxU DVB USB driver
*
* Copyright ( C ) 2009 Antti Palosaari < crope @ iki . fi >
* Copyright ( C ) 2011 Antti Palosaari < crope @ iki . fi >
2012-05-18 14:47:41 -03:00
* Copyright ( C ) 2012 Thomas Mair < thomas . mair86 @ googlemail . com >
2011-07-08 23:36:07 -03:00
*
* 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 "rtl28xxu.h"
2013-11-22 14:20:14 -03:00
static int rtl28xxu_disable_rc ;
module_param_named ( disable_rc , rtl28xxu_disable_rc , int , 0644 ) ;
MODULE_PARM_DESC ( disable_rc , " disable RTL2832U remote controller " ) ;
2011-07-08 23:36:07 -03:00
DVB_DEFINE_MOD_OPT_ADAPTER_NR ( adapter_nr ) ;
static int rtl28xxu_ctrl_msg ( struct dvb_usb_device * d , struct rtl28xxu_req * req )
{
2014-12-21 18:33:14 -03:00
struct rtl28xxu_dev * dev = d - > priv ;
2011-07-08 23:36:07 -03:00
int ret ;
unsigned int pipe ;
u8 requesttype ;
2015-10-06 00:22:23 -03:00
mutex_lock ( & d - > usb_mutex ) ;
if ( req - > size > sizeof ( dev - > buf ) ) {
dev_err ( & d - > intf - > dev , " too large message %u \n " , req - > size ) ;
ret = - EINVAL ;
goto err_mutex_unlock ;
}
2011-07-08 23:36:07 -03:00
if ( req - > index & CMD_WR_FLAG ) {
/* write */
2014-12-21 18:33:14 -03:00
memcpy ( dev - > buf , req - > data , req - > size ) ;
2011-07-08 23:36:07 -03:00
requesttype = ( USB_TYPE_VENDOR | USB_DIR_OUT ) ;
pipe = usb_sndctrlpipe ( d - > udev , 0 ) ;
} else {
/* read */
requesttype = ( USB_TYPE_VENDOR | USB_DIR_IN ) ;
pipe = usb_rcvctrlpipe ( d - > udev , 0 ) ;
}
ret = usb_control_msg ( d - > udev , pipe , 0 , requesttype , req - > value ,
2014-12-21 18:33:14 -03:00
req - > index , dev - > buf , req - > size , 1000 ) ;
2012-08-22 19:42:00 -03:00
dvb_usb_dbg_usb_control_msg ( d - > udev , 0 , requesttype , req - > value ,
2014-12-21 18:33:14 -03:00
req - > index , dev - > buf , req - > size ) ;
if ( ret < 0 )
2015-10-06 00:22:23 -03:00
goto err_mutex_unlock ;
2011-07-08 23:36:07 -03:00
/* read request, copy returned data to return buf */
2014-12-21 18:33:14 -03:00
if ( requesttype = = ( USB_TYPE_VENDOR | USB_DIR_IN ) )
memcpy ( req - > data , dev - > buf , req - > size ) ;
2011-07-08 23:36:07 -03:00
2015-10-06 00:22:23 -03:00
mutex_unlock ( & d - > usb_mutex ) ;
2014-12-21 18:33:14 -03:00
return 0 ;
2015-10-06 00:22:23 -03:00
err_mutex_unlock :
mutex_unlock ( & d - > usb_mutex ) ;
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2011-07-08 23:36:07 -03:00
return ret ;
}
2014-12-23 14:32:35 -03:00
static int rtl28xxu_wr_regs ( struct dvb_usb_device * d , u16 reg , u8 * val , int len )
2011-07-08 23:36:07 -03:00
{
struct rtl28xxu_req req ;
if ( reg < 0x3000 )
req . index = CMD_USB_WR ;
2011-08-04 13:26:10 -03:00
else if ( reg < 0x4000 )
2011-07-08 23:36:07 -03:00
req . index = CMD_SYS_WR ;
2011-08-04 13:26:10 -03:00
else
req . index = CMD_IR_WR ;
2011-07-08 23:36:07 -03:00
req . value = reg ;
req . size = len ;
req . data = val ;
return rtl28xxu_ctrl_msg ( d , & req ) ;
}
2014-12-23 14:32:35 -03:00
static int rtl28xxu_rd_regs ( struct dvb_usb_device * d , u16 reg , u8 * val , int len )
2011-07-08 23:36:07 -03:00
{
struct rtl28xxu_req req ;
if ( reg < 0x3000 )
req . index = CMD_USB_RD ;
2011-08-04 13:26:10 -03:00
else if ( reg < 0x4000 )
2011-07-08 23:36:07 -03:00
req . index = CMD_SYS_RD ;
2011-08-04 13:26:10 -03:00
else
req . index = CMD_IR_RD ;
2011-07-08 23:36:07 -03:00
req . value = reg ;
req . size = len ;
req . data = val ;
return rtl28xxu_ctrl_msg ( d , & req ) ;
}
2014-12-23 14:32:35 -03:00
static int rtl28xxu_wr_reg ( struct dvb_usb_device * d , u16 reg , u8 val )
2011-07-08 23:36:07 -03:00
{
2014-12-23 14:32:35 -03:00
return rtl28xxu_wr_regs ( d , reg , & val , 1 ) ;
2011-07-08 23:36:07 -03:00
}
2014-12-23 14:32:35 -03:00
static int rtl28xxu_rd_reg ( struct dvb_usb_device * d , u16 reg , u8 * val )
2011-07-08 23:36:07 -03:00
{
2014-12-23 14:32:35 -03:00
return rtl28xxu_rd_regs ( d , reg , val , 1 ) ;
2011-07-08 23:36:07 -03:00
}
2014-12-23 14:32:35 -03:00
static int rtl28xxu_wr_reg_mask ( struct dvb_usb_device * d , u16 reg , u8 val ,
2012-09-17 15:43:57 -03:00
u8 mask )
{
int ret ;
u8 tmp ;
/* no need for read if whole reg is written */
if ( mask ! = 0xff ) {
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_rd_reg ( d , reg , & tmp ) ;
2012-09-17 15:43:57 -03:00
if ( ret )
return ret ;
val & = mask ;
tmp & = ~ mask ;
val | = tmp ;
}
2014-12-23 14:32:35 -03:00
return rtl28xxu_wr_reg ( d , reg , val ) ;
2012-09-17 15:43:57 -03:00
}
2011-07-08 23:36:07 -03:00
/* I2C */
static int rtl28xxu_i2c_xfer ( struct i2c_adapter * adap , struct i2c_msg msg [ ] ,
int num )
{
int ret ;
struct dvb_usb_device * d = i2c_get_adapdata ( adap ) ;
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev = d - > priv ;
2011-07-08 23:36:07 -03:00
struct rtl28xxu_req req ;
/*
* It is not known which are real I2C bus xfer limits , but testing
* with RTL2831U + MT2060 gives max RD 24 and max WR 22 bytes .
2011-08-04 20:21:16 -03:00
* TODO : find out RTL2832U lens
*/
/*
* I2C adapter logic looks rather complicated due to fact it handles
* three different access methods . Those methods are ;
* 1 ) integrated demod access
* 2 ) old I2C access
* 3 ) new I2C access
*
* Used method is selected in order 1 , 2 , 3. Method 3 can handle all
* requests but there is two reasons why not use it always ;
* 1 ) It is most expensive , usually two USB messages are needed
* 2 ) At least RTL2831U does not support it
*
* Method 3 is needed in case of I2C write + read ( typical register read )
* where write is more than one byte .
2011-07-08 23:36:07 -03:00
*/
if ( mutex_lock_interruptible ( & d - > i2c_mutex ) < 0 )
return - EAGAIN ;
if ( num = = 2 & & ! ( msg [ 0 ] . flags & I2C_M_RD ) & &
( msg [ 1 ] . flags & I2C_M_RD ) ) {
2011-08-04 20:21:16 -03:00
if ( msg [ 0 ] . len > 24 | | msg [ 1 ] . len > 24 ) {
/* TODO: check msg[0].len max */
2011-07-08 23:36:07 -03:00
ret = - EOPNOTSUPP ;
2012-01-21 22:26:52 -03:00
goto err_mutex_unlock ;
2011-08-04 20:21:16 -03:00
} else if ( msg [ 0 ] . addr = = 0x10 ) {
/* method 1 - integrated demod */
2015-10-05 20:46:37 -03:00
if ( msg [ 0 ] . buf [ 0 ] = = 0x00 ) {
/* return demod page from driver cache */
msg [ 1 ] . buf [ 0 ] = dev - > page ;
ret = 0 ;
} else {
req . value = ( msg [ 0 ] . buf [ 0 ] < < 8 ) | ( msg [ 0 ] . addr < < 1 ) ;
req . index = CMD_DEMOD_RD | dev - > page ;
req . size = msg [ 1 ] . len ;
req . data = & msg [ 1 ] . buf [ 0 ] ;
ret = rtl28xxu_ctrl_msg ( d , & req ) ;
}
2011-08-04 20:21:16 -03:00
} else if ( msg [ 0 ] . len < 2 ) {
/* method 2 - old I2C */
2011-07-08 23:36:07 -03:00
req . value = ( msg [ 0 ] . buf [ 0 ] < < 8 ) | ( msg [ 0 ] . addr < < 1 ) ;
req . index = CMD_I2C_RD ;
req . size = msg [ 1 ] . len ;
req . data = & msg [ 1 ] . buf [ 0 ] ;
ret = rtl28xxu_ctrl_msg ( d , & req ) ;
2011-08-04 20:21:16 -03:00
} else {
/* method 3 - new I2C */
req . value = ( msg [ 0 ] . addr < < 1 ) ;
req . index = CMD_I2C_DA_WR ;
req . size = msg [ 0 ] . len ;
req . data = msg [ 0 ] . buf ;
ret = rtl28xxu_ctrl_msg ( d , & req ) ;
if ( ret )
2012-01-21 22:26:52 -03:00
goto err_mutex_unlock ;
2011-08-04 20:21:16 -03:00
req . value = ( msg [ 0 ] . addr < < 1 ) ;
req . index = CMD_I2C_DA_RD ;
req . size = msg [ 1 ] . len ;
req . data = msg [ 1 ] . buf ;
ret = rtl28xxu_ctrl_msg ( d , & req ) ;
2011-07-08 23:36:07 -03:00
}
} else if ( num = = 1 & & ! ( msg [ 0 ] . flags & I2C_M_RD ) ) {
if ( msg [ 0 ] . len > 22 ) {
2011-08-04 20:21:16 -03:00
/* TODO: check msg[0].len max */
2011-07-08 23:36:07 -03:00
ret = - EOPNOTSUPP ;
2012-01-21 22:26:52 -03:00
goto err_mutex_unlock ;
2011-08-04 20:21:16 -03:00
} else if ( msg [ 0 ] . addr = = 0x10 ) {
/* method 1 - integrated demod */
if ( msg [ 0 ] . buf [ 0 ] = = 0x00 ) {
/* save demod page for later demod access */
2014-12-18 08:05:23 -03:00
dev - > page = msg [ 0 ] . buf [ 1 ] ;
2011-08-04 20:21:16 -03:00
ret = 0 ;
} else {
req . value = ( msg [ 0 ] . buf [ 0 ] < < 8 ) |
( msg [ 0 ] . addr < < 1 ) ;
2014-12-18 08:05:23 -03:00
req . index = CMD_DEMOD_WR | dev - > page ;
2011-08-04 20:21:16 -03:00
req . size = msg [ 0 ] . len - 1 ;
req . data = & msg [ 0 ] . buf [ 1 ] ;
ret = rtl28xxu_ctrl_msg ( d , & req ) ;
}
2015-05-05 13:54:19 -03:00
} else if ( ( msg [ 0 ] . len < 23 ) & & ( ! dev - > new_i2c_write ) ) {
2011-08-04 20:21:16 -03:00
/* method 2 - old I2C */
2011-07-08 23:36:07 -03:00
req . value = ( msg [ 0 ] . buf [ 0 ] < < 8 ) | ( msg [ 0 ] . addr < < 1 ) ;
req . index = CMD_I2C_WR ;
req . size = msg [ 0 ] . len - 1 ;
req . data = & msg [ 0 ] . buf [ 1 ] ;
ret = rtl28xxu_ctrl_msg ( d , & req ) ;
2011-08-04 20:21:16 -03:00
} else {
/* method 3 - new I2C */
req . value = ( msg [ 0 ] . addr < < 1 ) ;
req . index = CMD_I2C_DA_WR ;
req . size = msg [ 0 ] . len ;
req . data = msg [ 0 ] . buf ;
ret = rtl28xxu_ctrl_msg ( d , & req ) ;
2011-07-08 23:36:07 -03:00
}
2015-05-05 13:54:18 -03:00
} else if ( num = = 1 & & ( msg [ 0 ] . flags & I2C_M_RD ) ) {
req . value = ( msg [ 0 ] . addr < < 1 ) ;
req . index = CMD_I2C_DA_RD ;
req . size = msg [ 0 ] . len ;
req . data = msg [ 0 ] . buf ;
ret = rtl28xxu_ctrl_msg ( d , & req ) ;
2011-07-08 23:36:07 -03:00
} else {
2015-05-05 13:54:18 -03:00
ret = - EOPNOTSUPP ;
2011-07-08 23:36:07 -03:00
}
2012-01-21 22:26:52 -03:00
err_mutex_unlock :
2011-07-08 23:36:07 -03:00
mutex_unlock ( & d - > i2c_mutex ) ;
return ret ? ret : num ;
}
static u32 rtl28xxu_i2c_func ( struct i2c_adapter * adapter )
{
return I2C_FUNC_I2C ;
}
static struct i2c_algorithm rtl28xxu_i2c_algo = {
. master_xfer = rtl28xxu_i2c_xfer ,
. functionality = rtl28xxu_i2c_func ,
} ;
2012-09-17 16:50:36 -03:00
static int rtl2831u_read_config ( struct dvb_usb_device * d )
{
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev = d_to_priv ( d ) ;
2012-09-17 16:50:36 -03:00
int ret ;
u8 buf [ 1 ] ;
/* open RTL2831U/RTL2830 I2C gate */
struct rtl28xxu_req req_gate_open = { 0x0120 , 0x0011 , 0x0001 , " \x08 " } ;
/* tuner probes */
struct rtl28xxu_req req_mt2060 = { 0x00c0 , CMD_I2C_RD , 1 , buf } ;
struct rtl28xxu_req req_qt1010 = { 0x0fc4 , CMD_I2C_RD , 1 , buf } ;
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " \n " ) ;
2012-09-17 16:50:36 -03:00
/*
* RTL2831U GPIOs
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* GPIO0 | tuner # 0 | 0 off | 1 on | MXL5005S ( ? )
* GPIO2 | LED | 0 off | 1 on |
* GPIO4 | tuner # 1 | 0 on | 1 off | MT2060
*/
/* GPIO direction */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg ( d , SYS_GPIO_DIR , 0x0a ) ;
2012-09-17 16:50:36 -03:00
if ( ret )
goto err ;
/* enable as output GPIO0, GPIO2, GPIO4 */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg ( d , SYS_GPIO_OUT_EN , 0x15 ) ;
2012-09-17 16:50:36 -03:00
if ( ret )
goto err ;
/*
* Probe used tuner . We need to know used tuner before demod attach
* since there is some demod params needed to set according to tuner .
*/
/* demod needs some time to wake up */
msleep ( 20 ) ;
2014-12-18 08:05:23 -03:00
dev - > tuner_name = " NONE " ;
2012-09-17 16:50:36 -03:00
/* open demod I2C gate */
ret = rtl28xxu_ctrl_msg ( d , & req_gate_open ) ;
if ( ret )
goto err ;
/* check QT1010 ID(?) register; reg=0f val=2c */
ret = rtl28xxu_ctrl_msg ( d , & req_qt1010 ) ;
if ( ret = = 0 & & buf [ 0 ] = = 0x2c ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2830_QT1010 ;
dev - > tuner_name = " QT1010 " ;
2012-09-17 16:50:36 -03:00
goto found ;
}
/* open demod I2C gate */
ret = rtl28xxu_ctrl_msg ( d , & req_gate_open ) ;
if ( ret )
goto err ;
/* check MT2060 ID register; reg=00 val=63 */
ret = rtl28xxu_ctrl_msg ( d , & req_mt2060 ) ;
if ( ret = = 0 & & buf [ 0 ] = = 0x63 ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2830_MT2060 ;
dev - > tuner_name = " MT2060 " ;
2012-09-17 16:50:36 -03:00
goto found ;
}
/* assume MXL5005S */
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2830_MXL5005S ;
dev - > tuner_name = " MXL5005S " ;
2012-09-17 16:50:36 -03:00
goto found ;
found :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " tuner=%s \n " , dev - > tuner_name ) ;
2012-09-17 16:50:36 -03:00
return 0 ;
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2012-09-17 16:50:36 -03:00
return ret ;
}
2012-09-17 14:01:35 -03:00
static int rtl2832u_read_config ( struct dvb_usb_device * d )
{
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev = d_to_priv ( d ) ;
2012-09-17 14:01:35 -03:00
int ret ;
2012-09-17 15:43:57 -03:00
u8 buf [ 2 ] ;
2012-09-17 14:01:35 -03:00
/* open RTL2832U/RTL2832 I2C gate */
struct rtl28xxu_req req_gate_open = { 0x0120 , 0x0011 , 0x0001 , " \x18 " } ;
/* close RTL2832U/RTL2832 I2C gate */
struct rtl28xxu_req req_gate_close = { 0x0120 , 0x0011 , 0x0001 , " \x10 " } ;
/* tuner probes */
struct rtl28xxu_req req_fc0012 = { 0x00c6 , CMD_I2C_RD , 1 , buf } ;
struct rtl28xxu_req req_fc0013 = { 0x00c6 , CMD_I2C_RD , 1 , buf } ;
struct rtl28xxu_req req_mt2266 = { 0x00c0 , CMD_I2C_RD , 1 , buf } ;
struct rtl28xxu_req req_fc2580 = { 0x01ac , CMD_I2C_RD , 1 , buf } ;
struct rtl28xxu_req req_mt2063 = { 0x00c0 , CMD_I2C_RD , 1 , buf } ;
struct rtl28xxu_req req_max3543 = { 0x00c0 , CMD_I2C_RD , 1 , buf } ;
struct rtl28xxu_req req_tua9001 = { 0x7ec0 , CMD_I2C_RD , 2 , buf } ;
struct rtl28xxu_req req_mxl5007t = { 0xd9c0 , CMD_I2C_RD , 1 , buf } ;
struct rtl28xxu_req req_e4000 = { 0x02c8 , CMD_I2C_RD , 1 , buf } ;
struct rtl28xxu_req req_tda18272 = { 0x00c0 , CMD_I2C_RD , 2 , buf } ;
2013-06-02 17:24:24 -03:00
struct rtl28xxu_req req_r820t = { 0x0034 , CMD_I2C_RD , 1 , buf } ;
2013-10-30 00:45:38 -03:00
struct rtl28xxu_req req_r828d = { 0x0074 , CMD_I2C_RD , 1 , buf } ;
2013-12-01 13:44:23 -03:00
struct rtl28xxu_req req_mn88472 = { 0xff38 , CMD_I2C_RD , 1 , buf } ;
2014-09-30 01:03:04 -03:00
struct rtl28xxu_req req_mn88473 = { 0xff38 , CMD_I2C_RD , 1 , buf } ;
2015-05-05 13:54:19 -03:00
struct rtl28xxu_req req_si2157 = { 0x00c0 , CMD_I2C_RD , 1 , buf } ;
struct rtl28xxu_req req_si2168 = { 0x00c8 , CMD_I2C_RD , 1 , buf } ;
2012-09-17 14:01:35 -03:00
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " \n " ) ;
2012-09-17 14:01:35 -03:00
2012-09-17 15:43:57 -03:00
/* enable GPIO3 and GPIO6 as output */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_DIR , 0x00 , 0x40 ) ;
2012-09-17 14:01:35 -03:00
if ( ret )
goto err ;
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_OUT_EN , 0x48 , 0x48 ) ;
2012-09-17 14:01:35 -03:00
if ( ret )
goto err ;
/*
* Probe used tuner . We need to know used tuner before demod attach
* since there is some demod params needed to set according to tuner .
*/
/* open demod I2C gate */
ret = rtl28xxu_ctrl_msg ( d , & req_gate_open ) ;
if ( ret )
goto err ;
2014-12-18 08:05:23 -03:00
dev - > tuner_name = " NONE " ;
2012-09-17 14:01:35 -03:00
/* check FC0012 ID register; reg=00 val=a1 */
ret = rtl28xxu_ctrl_msg ( d , & req_fc0012 ) ;
if ( ret = = 0 & & buf [ 0 ] = = 0xa1 ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2832_FC0012 ;
dev - > tuner_name = " FC0012 " ;
2013-12-01 13:44:23 -03:00
goto tuner_found ;
2012-09-17 14:01:35 -03:00
}
/* check FC0013 ID register; reg=00 val=a3 */
ret = rtl28xxu_ctrl_msg ( d , & req_fc0013 ) ;
if ( ret = = 0 & & buf [ 0 ] = = 0xa3 ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2832_FC0013 ;
dev - > tuner_name = " FC0013 " ;
2013-12-01 13:44:23 -03:00
goto tuner_found ;
2012-09-17 14:01:35 -03:00
}
/* check MT2266 ID register; reg=00 val=85 */
ret = rtl28xxu_ctrl_msg ( d , & req_mt2266 ) ;
if ( ret = = 0 & & buf [ 0 ] = = 0x85 ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2832_MT2266 ;
dev - > tuner_name = " MT2266 " ;
2013-12-01 13:44:23 -03:00
goto tuner_found ;
2012-09-17 14:01:35 -03:00
}
/* check FC2580 ID register; reg=01 val=56 */
ret = rtl28xxu_ctrl_msg ( d , & req_fc2580 ) ;
if ( ret = = 0 & & buf [ 0 ] = = 0x56 ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2832_FC2580 ;
dev - > tuner_name = " FC2580 " ;
2013-12-01 13:44:23 -03:00
goto tuner_found ;
2012-09-17 14:01:35 -03:00
}
/* check MT2063 ID register; reg=00 val=9e || 9c */
ret = rtl28xxu_ctrl_msg ( d , & req_mt2063 ) ;
if ( ret = = 0 & & ( buf [ 0 ] = = 0x9e | | buf [ 0 ] = = 0x9c ) ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2832_MT2063 ;
dev - > tuner_name = " MT2063 " ;
2013-12-01 13:44:23 -03:00
goto tuner_found ;
2012-09-17 14:01:35 -03:00
}
/* check MAX3543 ID register; reg=00 val=38 */
ret = rtl28xxu_ctrl_msg ( d , & req_max3543 ) ;
if ( ret = = 0 & & buf [ 0 ] = = 0x38 ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2832_MAX3543 ;
dev - > tuner_name = " MAX3543 " ;
2013-12-01 13:44:23 -03:00
goto tuner_found ;
2012-09-17 14:01:35 -03:00
}
/* check TUA9001 ID register; reg=7e val=2328 */
ret = rtl28xxu_ctrl_msg ( d , & req_tua9001 ) ;
if ( ret = = 0 & & buf [ 0 ] = = 0x23 & & buf [ 1 ] = = 0x28 ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2832_TUA9001 ;
dev - > tuner_name = " TUA9001 " ;
2013-12-01 13:44:23 -03:00
goto tuner_found ;
2012-09-17 14:01:35 -03:00
}
/* check MXL5007R ID register; reg=d9 val=14 */
ret = rtl28xxu_ctrl_msg ( d , & req_mxl5007t ) ;
if ( ret = = 0 & & buf [ 0 ] = = 0x14 ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2832_MXL5007T ;
dev - > tuner_name = " MXL5007T " ;
2013-12-01 13:44:23 -03:00
goto tuner_found ;
2012-09-17 14:01:35 -03:00
}
/* check E4000 ID register; reg=02 val=40 */
ret = rtl28xxu_ctrl_msg ( d , & req_e4000 ) ;
if ( ret = = 0 & & buf [ 0 ] = = 0x40 ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2832_E4000 ;
dev - > tuner_name = " E4000 " ;
2013-12-01 13:44:23 -03:00
goto tuner_found ;
2012-09-17 14:01:35 -03:00
}
/* check TDA18272 ID register; reg=00 val=c760 */
ret = rtl28xxu_ctrl_msg ( d , & req_tda18272 ) ;
if ( ret = = 0 & & ( buf [ 0 ] = = 0xc7 | | buf [ 1 ] = = 0x60 ) ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2832_TDA18272 ;
dev - > tuner_name = " TDA18272 " ;
2013-12-01 13:44:23 -03:00
goto tuner_found ;
2012-09-17 14:01:35 -03:00
}
2013-06-02 17:24:24 -03:00
/* check R820T ID register; reg=00 val=69 */
2013-04-06 09:40:11 -03:00
ret = rtl28xxu_ctrl_msg ( d , & req_r820t ) ;
2013-06-02 17:24:24 -03:00
if ( ret = = 0 & & buf [ 0 ] = = 0x69 ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2832_R820T ;
dev - > tuner_name = " R820T " ;
2013-12-01 13:44:23 -03:00
goto tuner_found ;
2013-04-06 09:40:11 -03:00
}
2013-10-30 00:45:38 -03:00
/* check R828D ID register; reg=00 val=69 */
ret = rtl28xxu_ctrl_msg ( d , & req_r828d ) ;
if ( ret = = 0 & & buf [ 0 ] = = 0x69 ) {
2014-12-18 08:05:23 -03:00
dev - > tuner = TUNER_RTL2832_R828D ;
dev - > tuner_name = " R828D " ;
2013-12-01 13:44:23 -03:00
goto tuner_found ;
2013-10-30 00:45:38 -03:00
}
2015-05-05 13:54:19 -03:00
/* GPIO0 and GPIO5 to reset Si2157/Si2168 tuner and demod */
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_OUT_VAL , 0x00 , 0x21 ) ;
if ( ret )
goto err ;
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_OUT_EN , 0x00 , 0x21 ) ;
if ( ret )
goto err ;
msleep ( 50 ) ;
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_OUT_VAL , 0x21 , 0x21 ) ;
if ( ret )
goto err ;
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_OUT_EN , 0x21 , 0x21 ) ;
if ( ret )
goto err ;
msleep ( 50 ) ;
/* check Si2157 ID register; reg=c0 val=80 */
ret = rtl28xxu_ctrl_msg ( d , & req_si2157 ) ;
if ( ret = = 0 & & ( ( buf [ 0 ] & 0x80 ) = = 0x80 ) ) {
dev - > tuner = TUNER_RTL2832_SI2157 ;
dev - > tuner_name = " SI2157 " ;
goto tuner_found ;
}
2013-12-01 13:44:23 -03:00
tuner_found :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " tuner=%s \n " , dev - > tuner_name ) ;
2012-09-17 14:01:35 -03:00
2013-12-01 13:44:23 -03:00
/* probe slave demod */
2014-12-18 08:05:23 -03:00
if ( dev - > tuner = = TUNER_RTL2832_R828D ) {
2013-12-01 13:44:23 -03:00
/* power on MN88472 demod on GPIO0 */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_OUT_VAL , 0x01 , 0x01 ) ;
2013-12-01 13:44:23 -03:00
if ( ret )
goto err ;
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_DIR , 0x00 , 0x01 ) ;
2013-12-01 13:44:23 -03:00
if ( ret )
goto err ;
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_OUT_EN , 0x01 , 0x01 ) ;
2013-12-01 13:44:23 -03:00
if ( ret )
goto err ;
/* check MN88472 answers */
ret = rtl28xxu_ctrl_msg ( d , & req_mn88472 ) ;
if ( ret = = 0 & & buf [ 0 ] = = 0x02 ) {
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " MN88472 found \n " ) ;
2014-12-18 08:05:23 -03:00
dev - > slave_demod = SLAVE_DEMOD_MN88472 ;
2013-12-01 13:44:23 -03:00
goto demod_found ;
}
2014-09-30 01:03:04 -03:00
ret = rtl28xxu_ctrl_msg ( d , & req_mn88473 ) ;
if ( ret = = 0 & & buf [ 0 ] = = 0x03 ) {
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " MN88473 found \n " ) ;
2014-12-18 08:05:23 -03:00
dev - > slave_demod = SLAVE_DEMOD_MN88473 ;
2014-09-30 01:03:04 -03:00
goto demod_found ;
}
2013-12-01 13:44:23 -03:00
}
2015-05-05 13:54:19 -03:00
if ( dev - > tuner = = TUNER_RTL2832_SI2157 ) {
/* check Si2168 ID register; reg=c8 val=80 */
ret = rtl28xxu_ctrl_msg ( d , & req_si2168 ) ;
if ( ret = = 0 & & ( ( buf [ 0 ] & 0x80 ) = = 0x80 ) ) {
dev_dbg ( & d - > intf - > dev , " Si2168 found \n " ) ;
dev - > slave_demod = SLAVE_DEMOD_SI2168 ;
goto demod_found ;
}
}
2013-12-01 13:44:23 -03:00
demod_found :
2012-09-17 14:01:35 -03:00
/* close demod I2C gate */
ret = rtl28xxu_ctrl_msg ( d , & req_gate_close ) ;
if ( ret < 0 )
goto err ;
return 0 ;
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2012-09-17 14:01:35 -03:00
return ret ;
}
2014-12-23 14:09:13 -03:00
static int rtl28xxu_read_config ( struct dvb_usb_device * d )
{
struct rtl28xxu_dev * dev = d_to_priv ( d ) ;
if ( dev - > chip_id = = CHIP_ID_RTL2831U )
return rtl2831u_read_config ( d ) ;
else
return rtl2832u_read_config ( d ) ;
}
2014-12-23 13:14:36 -03:00
static int rtl28xxu_identify_state ( struct dvb_usb_device * d , const char * * name )
{
struct rtl28xxu_dev * dev = d_to_priv ( d ) ;
int ret ;
struct rtl28xxu_req req_demod_i2c = { 0x0020 , CMD_I2C_DA_RD , 0 , NULL } ;
dev_dbg ( & d - > intf - > dev , " \n " ) ;
/*
* Detect chip type using I2C command that is not supported
* by old RTL2831U .
*/
ret = rtl28xxu_ctrl_msg ( d , & req_demod_i2c ) ;
if ( ret = = - EPIPE ) {
dev - > chip_id = CHIP_ID_RTL2831U ;
} else if ( ret = = 0 ) {
dev - > chip_id = CHIP_ID_RTL2832U ;
} else {
dev_err ( & d - > intf - > dev , " chip type detection failed %d \n " , ret ) ;
goto err ;
}
dev_dbg ( & d - > intf - > dev , " chip_id=%u \n " , dev - > chip_id ) ;
return WARM ;
err :
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
return ret ;
}
2014-12-07 22:02:23 -03:00
static const struct rtl2830_platform_data rtl2830_mt2060_platform_data = {
. clk = 28800000 ,
2011-07-08 23:36:07 -03:00
. spec_inv = 1 ,
. vtop = 0x20 ,
. krf = 0x04 ,
. agc_targ_val = 0x2d ,
} ;
2014-12-07 22:02:23 -03:00
static const struct rtl2830_platform_data rtl2830_qt1010_platform_data = {
. clk = 28800000 ,
2011-07-08 23:36:07 -03:00
. spec_inv = 1 ,
. vtop = 0x20 ,
. krf = 0x04 ,
. agc_targ_val = 0x2d ,
} ;
2014-12-07 22:02:23 -03:00
static const struct rtl2830_platform_data rtl2830_mxl5005s_platform_data = {
. clk = 28800000 ,
2011-07-08 23:36:07 -03:00
. spec_inv = 0 ,
. vtop = 0x3f ,
. krf = 0x04 ,
. agc_targ_val = 0x3e ,
} ;
2011-08-04 13:26:10 -03:00
static int rtl2831u_frontend_attach ( struct dvb_usb_adapter * adap )
2011-07-08 23:36:07 -03:00
{
2012-08-12 22:27:07 -03:00
struct dvb_usb_device * d = adap_to_d ( adap ) ;
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev = d_to_priv ( d ) ;
struct rtl2830_platform_data * pdata = & dev - > rtl2830_platform_data ;
2014-12-07 22:02:23 -03:00
struct i2c_board_info board_info ;
struct i2c_client * client ;
2012-09-17 16:50:36 -03:00
int ret ;
2011-07-08 23:36:07 -03:00
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " \n " ) ;
2011-07-08 23:36:07 -03:00
2014-12-18 08:05:23 -03:00
switch ( dev - > tuner ) {
2012-09-17 16:50:36 -03:00
case TUNER_RTL2830_QT1010 :
2014-12-07 22:02:23 -03:00
* pdata = rtl2830_qt1010_platform_data ;
2012-09-17 16:50:36 -03:00
break ;
case TUNER_RTL2830_MT2060 :
2014-12-07 22:02:23 -03:00
* pdata = rtl2830_mt2060_platform_data ;
2012-09-17 16:50:36 -03:00
break ;
case TUNER_RTL2830_MXL5005S :
2014-12-07 22:02:23 -03:00
* pdata = rtl2830_mxl5005s_platform_data ;
2012-09-17 16:50:36 -03:00
break ;
default :
2014-12-21 11:25:57 -03:00
dev_err ( & d - > intf - > dev , " unknown tuner %s \n " , dev - > tuner_name ) ;
2012-09-17 16:50:36 -03:00
ret = - ENODEV ;
goto err ;
2011-07-08 23:36:07 -03:00
}
/* attach demodulator */
2014-12-07 22:02:23 -03:00
memset ( & board_info , 0 , sizeof ( board_info ) ) ;
strlcpy ( board_info . type , " rtl2830 " , I2C_NAME_SIZE ) ;
board_info . addr = 0x10 ;
board_info . platform_data = pdata ;
request_module ( " %s " , board_info . type ) ;
client = i2c_new_device ( & d - > i2c_adap , & board_info ) ;
if ( client = = NULL | | client - > dev . driver = = NULL ) {
2011-07-08 23:36:07 -03:00
ret = - ENODEV ;
goto err ;
}
2014-12-07 22:02:23 -03:00
if ( ! try_module_get ( client - > dev . driver - > owner ) ) {
i2c_unregister_device ( client ) ;
ret = - ENODEV ;
goto err ;
}
adap - > fe [ 0 ] = pdata - > get_dvb_frontend ( client ) ;
2014-12-18 08:05:23 -03:00
dev - > demod_i2c_adapter = pdata - > get_i2c_adapter ( client ) ;
2014-12-07 22:02:23 -03:00
2014-12-18 08:05:23 -03:00
dev - > i2c_client_demod = client ;
2014-12-07 22:02:23 -03:00
2012-09-17 16:50:36 -03:00
return 0 ;
2011-07-08 23:36:07 -03:00
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2011-07-08 23:36:07 -03:00
return ret ;
}
2015-04-23 22:54:03 -03:00
static const struct rtl2832_platform_data rtl2832_fc2580_platform_data = {
. clk = 28800000 ,
. tuner = TUNER_RTL2832_FC2580 ,
} ;
2014-12-13 05:44:05 -03:00
static const struct rtl2832_platform_data rtl2832_fc0012_platform_data = {
. clk = 28800000 ,
. tuner = TUNER_RTL2832_FC0012
} ;
static const struct rtl2832_platform_data rtl2832_fc0013_platform_data = {
. clk = 28800000 ,
. tuner = TUNER_RTL2832_FC0013
} ;
static const struct rtl2832_platform_data rtl2832_tua9001_platform_data = {
. clk = 28800000 ,
. tuner = TUNER_RTL2832_TUA9001 ,
} ;
static const struct rtl2832_platform_data rtl2832_e4000_platform_data = {
. clk = 28800000 ,
. tuner = TUNER_RTL2832_E4000 ,
} ;
static const struct rtl2832_platform_data rtl2832_r820t_platform_data = {
. clk = 28800000 ,
. tuner = TUNER_RTL2832_R820T ,
} ;
2015-05-05 13:54:19 -03:00
static const struct rtl2832_platform_data rtl2832_si2157_platform_data = {
. clk = 28800000 ,
. tuner = TUNER_RTL2832_SI2157 ,
} ;
2012-05-18 14:47:41 -03:00
static int rtl2832u_fc0012_tuner_callback ( struct dvb_usb_device * d ,
int cmd , int arg )
{
int ret ;
u8 val ;
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " cmd=%d arg=%d \n " , cmd , arg ) ;
2012-08-12 22:27:07 -03:00
2012-05-18 14:47:41 -03:00
switch ( cmd ) {
case FC_FE_CALLBACK_VHF_ENABLE :
/* set output values */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_rd_reg ( d , SYS_GPIO_OUT_VAL , & val ) ;
2012-05-18 14:47:41 -03:00
if ( ret )
goto err ;
if ( arg )
val & = 0xbf ; /* set GPIO6 low */
else
val | = 0x40 ; /* set GPIO6 high */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg ( d , SYS_GPIO_OUT_VAL , val ) ;
2012-05-18 14:47:41 -03:00
if ( ret )
goto err ;
break ;
default :
ret = - EINVAL ;
goto err ;
}
return 0 ;
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2012-05-18 14:47:41 -03:00
return ret ;
}
2012-09-11 22:27:09 -03:00
static int rtl2832u_tua9001_tuner_callback ( struct dvb_usb_device * d ,
int cmd , int arg )
{
int ret ;
u8 val ;
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " cmd=%d arg=%d \n " , cmd , arg ) ;
2012-09-11 22:27:09 -03:00
/*
* CEN always enabled by hardware wiring
* RESETN GPIO4
* RXEN GPIO1
*/
switch ( cmd ) {
case TUA9001_CMD_RESETN :
if ( arg )
2012-09-17 15:43:57 -03:00
val = ( 1 < < 4 ) ;
2012-09-11 22:27:09 -03:00
else
2012-09-17 15:43:57 -03:00
val = ( 0 < < 4 ) ;
2012-09-11 22:27:09 -03:00
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_OUT_VAL , val , 0x10 ) ;
2012-09-17 15:43:57 -03:00
if ( ret )
2012-09-11 22:27:09 -03:00
goto err ;
break ;
case TUA9001_CMD_RXEN :
if ( arg )
2012-09-17 15:43:57 -03:00
val = ( 1 < < 1 ) ;
2012-09-11 22:27:09 -03:00
else
2012-09-17 15:43:57 -03:00
val = ( 0 < < 1 ) ;
2012-09-11 22:27:09 -03:00
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_OUT_VAL , val , 0x02 ) ;
2012-09-17 15:43:57 -03:00
if ( ret )
2012-09-11 22:27:09 -03:00
goto err ;
break ;
}
return 0 ;
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2012-09-11 22:27:09 -03:00
return ret ;
}
2012-05-18 14:47:41 -03:00
static int rtl2832u_frontend_callback ( void * adapter_priv , int component ,
2012-09-17 16:55:39 -03:00
int cmd , int arg )
2012-05-18 14:47:41 -03:00
{
2014-12-17 02:55:41 -03:00
struct i2c_adapter * adapter = adapter_priv ;
struct device * parent = adapter - > dev . parent ;
struct i2c_adapter * parent_adapter ;
struct dvb_usb_device * d ;
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev ;
2014-12-17 02:55:41 -03:00
/*
* All tuners are connected to demod muxed I2C adapter . We have to
* resolve its parent adapter in order to get handle for this driver
* private data . That is a bit hackish solution , GPIO or direct driver
* callback would be better . . .
*/
if ( parent ! = NULL & & parent - > type = = & i2c_adapter_type )
parent_adapter = to_i2c_adapter ( parent ) ;
else
return - EINVAL ;
d = i2c_get_adapdata ( parent_adapter ) ;
2014-12-18 08:05:23 -03:00
dev = d - > priv ;
2012-05-18 14:47:41 -03:00
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " component=%d cmd=%d arg=%d \n " ,
component , cmd , arg ) ;
2012-09-17 16:55:39 -03:00
2012-05-18 14:47:41 -03:00
switch ( component ) {
case DVB_FRONTEND_COMPONENT_TUNER :
2014-12-18 08:05:23 -03:00
switch ( dev - > tuner ) {
2014-12-17 03:09:32 -03:00
case TUNER_RTL2832_FC0012 :
return rtl2832u_fc0012_tuner_callback ( d , cmd , arg ) ;
case TUNER_RTL2832_TUA9001 :
return rtl2832u_tua9001_tuner_callback ( d , cmd , arg ) ;
}
2012-05-18 14:47:41 -03:00
}
2012-09-17 15:49:54 -03:00
return 0 ;
2012-05-18 14:47:41 -03:00
}
2011-08-04 13:26:10 -03:00
static int rtl2832u_frontend_attach ( struct dvb_usb_adapter * adap )
{
2012-08-12 22:27:07 -03:00
struct dvb_usb_device * d = adap_to_d ( adap ) ;
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev = d_to_priv ( d ) ;
struct rtl2832_platform_data * pdata = & dev - > rtl2832_platform_data ;
2014-12-13 00:09:57 -03:00
struct i2c_board_info board_info ;
2014-12-02 11:00:23 -03:00
struct i2c_client * client ;
2014-12-13 00:09:57 -03:00
int ret ;
2011-08-04 13:26:10 -03:00
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " \n " ) ;
2011-08-04 13:26:10 -03:00
2014-12-18 08:05:23 -03:00
switch ( dev - > tuner ) {
2012-09-17 14:01:35 -03:00
case TUNER_RTL2832_FC0012 :
2014-12-13 05:44:05 -03:00
* pdata = rtl2832_fc0012_platform_data ;
2012-09-17 14:01:35 -03:00
break ;
case TUNER_RTL2832_FC0013 :
2014-12-13 05:44:05 -03:00
* pdata = rtl2832_fc0013_platform_data ;
2012-09-17 14:01:35 -03:00
break ;
case TUNER_RTL2832_FC2580 :
2015-04-23 22:54:03 -03:00
* pdata = rtl2832_fc2580_platform_data ;
2012-09-17 14:01:35 -03:00
break ;
case TUNER_RTL2832_TUA9001 :
2014-12-13 05:44:05 -03:00
* pdata = rtl2832_tua9001_platform_data ;
2012-09-17 14:01:35 -03:00
break ;
case TUNER_RTL2832_E4000 :
2014-12-13 05:44:05 -03:00
* pdata = rtl2832_e4000_platform_data ;
2012-09-17 14:01:35 -03:00
break ;
2013-04-06 09:40:11 -03:00
case TUNER_RTL2832_R820T :
2013-10-30 00:45:38 -03:00
case TUNER_RTL2832_R828D :
2014-12-13 05:44:05 -03:00
* pdata = rtl2832_r820t_platform_data ;
2013-04-06 09:40:11 -03:00
break ;
2015-05-05 13:54:19 -03:00
case TUNER_RTL2832_SI2157 :
* pdata = rtl2832_si2157_platform_data ;
break ;
2012-09-17 14:01:35 -03:00
default :
2014-12-21 11:25:57 -03:00
dev_err ( & d - > intf - > dev , " unknown tuner %s \n " , dev - > tuner_name ) ;
2012-09-17 14:01:35 -03:00
ret = - ENODEV ;
2011-08-04 13:26:10 -03:00
goto err ;
2012-09-17 14:01:35 -03:00
}
2011-08-04 13:26:10 -03:00
/* attach demodulator */
2014-12-13 00:09:57 -03:00
memset ( & board_info , 0 , sizeof ( board_info ) ) ;
2014-12-02 11:00:23 -03:00
strlcpy ( board_info . type , " rtl2832 " , I2C_NAME_SIZE ) ;
board_info . addr = 0x10 ;
2014-12-13 00:09:57 -03:00
board_info . platform_data = pdata ;
2014-12-02 11:00:23 -03:00
request_module ( " %s " , board_info . type ) ;
client = i2c_new_device ( & d - > i2c_adap , & board_info ) ;
if ( client = = NULL | | client - > dev . driver = = NULL ) {
ret = - ENODEV ;
goto err ;
}
if ( ! try_module_get ( client - > dev . driver - > owner ) ) {
i2c_unregister_device ( client ) ;
2012-09-17 14:01:35 -03:00
ret = - ENODEV ;
goto err ;
}
2012-05-18 14:47:41 -03:00
2014-12-13 00:09:57 -03:00
adap - > fe [ 0 ] = pdata - > get_dvb_frontend ( client ) ;
2014-12-18 08:05:23 -03:00
dev - > demod_i2c_adapter = pdata - > get_i2c_adapter ( client ) ;
2014-12-02 11:00:23 -03:00
2014-12-18 08:05:23 -03:00
dev - > i2c_client_demod = client ;
2014-02-08 04:03:57 -03:00
2012-09-17 14:01:35 -03:00
/* set fe callback */
2012-08-12 22:27:07 -03:00
adap - > fe [ 0 ] - > callback = rtl2832u_frontend_callback ;
2011-08-04 13:26:10 -03:00
2014-12-18 08:05:23 -03:00
if ( dev - > slave_demod ) {
2013-12-01 13:44:23 -03:00
struct i2c_board_info info = { } ;
/*
* We continue on reduced mode , without DVB - T2 / C , using master
* demod , when slave demod fails .
*/
ret = 0 ;
/* attach slave demodulator */
2014-12-18 08:05:23 -03:00
if ( dev - > slave_demod = = SLAVE_DEMOD_MN88472 ) {
2013-12-01 13:44:23 -03:00
struct mn88472_config mn88472_config = { } ;
mn88472_config . fe = & adap - > fe [ 1 ] ;
mn88472_config . i2c_wr_max = 22 ,
strlcpy ( info . type , " mn88472 " , I2C_NAME_SIZE ) ;
2014-11-26 18:51:46 -03:00
mn88472_config . xtal = 20500000 ;
2014-12-05 21:25:33 -03:00
mn88472_config . ts_mode = SERIAL_TS_MODE ;
mn88472_config . ts_clock = VARIABLE_TS_CLOCK ;
2013-12-01 13:44:23 -03:00
info . addr = 0x18 ;
info . platform_data = & mn88472_config ;
request_module ( info . type ) ;
2014-12-16 11:05:08 -03:00
client = i2c_new_device ( & d - > i2c_adap , & info ) ;
2013-12-01 13:44:23 -03:00
if ( client = = NULL | | client - > dev . driver = = NULL ) {
2014-12-18 08:05:23 -03:00
dev - > slave_demod = SLAVE_DEMOD_NONE ;
2013-12-01 13:44:23 -03:00
goto err_slave_demod_failed ;
}
if ( ! try_module_get ( client - > dev . driver - > owner ) ) {
i2c_unregister_device ( client ) ;
2014-12-18 08:05:23 -03:00
dev - > slave_demod = SLAVE_DEMOD_NONE ;
2013-12-01 13:44:23 -03:00
goto err_slave_demod_failed ;
}
2014-12-18 08:05:23 -03:00
dev - > i2c_client_slave_demod = client ;
2015-05-05 13:54:19 -03:00
} else if ( dev - > slave_demod = = SLAVE_DEMOD_MN88473 ) {
2014-09-30 01:03:04 -03:00
struct mn88473_config mn88473_config = { } ;
mn88473_config . fe = & adap - > fe [ 1 ] ;
mn88473_config . i2c_wr_max = 22 ,
strlcpy ( info . type , " mn88473 " , I2C_NAME_SIZE ) ;
info . addr = 0x18 ;
info . platform_data = & mn88473_config ;
request_module ( info . type ) ;
2014-12-16 11:05:08 -03:00
client = i2c_new_device ( & d - > i2c_adap , & info ) ;
2014-09-30 01:03:04 -03:00
if ( client = = NULL | | client - > dev . driver = = NULL ) {
2014-12-18 08:05:23 -03:00
dev - > slave_demod = SLAVE_DEMOD_NONE ;
2014-09-30 01:03:04 -03:00
goto err_slave_demod_failed ;
}
if ( ! try_module_get ( client - > dev . driver - > owner ) ) {
i2c_unregister_device ( client ) ;
2014-12-18 08:05:23 -03:00
dev - > slave_demod = SLAVE_DEMOD_NONE ;
2014-09-30 01:03:04 -03:00
goto err_slave_demod_failed ;
}
2014-12-18 08:05:23 -03:00
dev - > i2c_client_slave_demod = client ;
2015-05-05 13:54:19 -03:00
} else {
struct si2168_config si2168_config = { } ;
struct i2c_adapter * adapter ;
si2168_config . i2c_adapter = & adapter ;
si2168_config . fe = & adap - > fe [ 1 ] ;
si2168_config . ts_mode = SI2168_TS_SERIAL ;
si2168_config . ts_clock_inv = false ;
si2168_config . ts_clock_gapped = true ;
strlcpy ( info . type , " si2168 " , I2C_NAME_SIZE ) ;
info . addr = 0x64 ;
info . platform_data = & si2168_config ;
request_module ( info . type ) ;
client = i2c_new_device ( & d - > i2c_adap , & info ) ;
if ( client = = NULL | | client - > dev . driver = = NULL ) {
dev - > slave_demod = SLAVE_DEMOD_NONE ;
goto err_slave_demod_failed ;
}
if ( ! try_module_get ( client - > dev . driver - > owner ) ) {
i2c_unregister_device ( client ) ;
dev - > slave_demod = SLAVE_DEMOD_NONE ;
goto err_slave_demod_failed ;
}
dev - > i2c_client_slave_demod = client ;
/* for Si2168 devices use only new I2C write method */
dev - > new_i2c_write = true ;
2013-12-01 13:44:23 -03:00
}
}
2012-09-17 14:01:35 -03:00
return 0 ;
2013-12-01 13:44:23 -03:00
err_slave_demod_failed :
2011-08-04 13:26:10 -03:00
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2011-08-04 13:26:10 -03:00
return ret ;
}
2014-12-23 14:09:13 -03:00
static int rtl28xxu_frontend_attach ( struct dvb_usb_adapter * adap )
{
struct rtl28xxu_dev * dev = adap_to_priv ( adap ) ;
if ( dev - > chip_id = = CHIP_ID_RTL2831U )
return rtl2831u_frontend_attach ( adap ) ;
else
return rtl2832u_frontend_attach ( adap ) ;
}
static int rtl28xxu_frontend_detach ( struct dvb_usb_adapter * adap )
2014-12-02 11:23:49 -03:00
{
struct dvb_usb_device * d = adap_to_d ( adap ) ;
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev = d_to_priv ( d ) ;
2014-12-02 11:23:49 -03:00
struct i2c_client * client ;
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " \n " ) ;
2014-12-02 11:23:49 -03:00
/* remove I2C slave demod */
2014-12-18 08:05:23 -03:00
client = dev - > i2c_client_slave_demod ;
2014-12-02 11:23:49 -03:00
if ( client ) {
module_put ( client - > dev . driver - > owner ) ;
i2c_unregister_device ( client ) ;
}
/* remove I2C demod */
2014-12-18 08:05:23 -03:00
client = dev - > i2c_client_demod ;
2014-12-02 11:23:49 -03:00
if ( client ) {
module_put ( client - > dev . driver - > owner ) ;
i2c_unregister_device ( client ) ;
}
return 0 ;
}
2011-07-08 23:36:07 -03:00
static struct qt1010_config rtl28xxu_qt1010_config = {
. i2c_address = 0x62 , /* 0xc4 */
} ;
static struct mt2060_config rtl28xxu_mt2060_config = {
. i2c_address = 0x60 , /* 0xc0 */
. clock_out = 0 ,
} ;
static struct mxl5005s_config rtl28xxu_mxl5005s_config = {
. i2c_address = 0x63 , /* 0xc6 */
. if_freq = IF_FREQ_4570000HZ ,
. xtal_freq = CRYSTAL_FREQ_16000000HZ ,
. agc_mode = MXL_SINGLE_AGC ,
. tracking_filter = MXL_TF_C_H ,
. rssi_enable = MXL_RSSI_ENABLE ,
. 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 ,
} ;
2011-08-04 13:26:10 -03:00
static int rtl2831u_tuner_attach ( struct dvb_usb_adapter * adap )
2011-07-08 23:36:07 -03:00
{
int ret ;
2012-08-12 22:27:07 -03:00
struct dvb_usb_device * d = adap_to_d ( adap ) ;
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev = d_to_priv ( d ) ;
2012-01-21 22:26:52 -03:00
struct dvb_frontend * fe ;
2011-07-08 23:36:07 -03:00
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " \n " ) ;
2011-07-08 23:36:07 -03:00
2014-12-18 08:05:23 -03:00
switch ( dev - > tuner ) {
2011-07-08 23:36:07 -03:00
case TUNER_RTL2830_QT1010 :
2012-08-12 22:27:07 -03:00
fe = dvb_attach ( qt1010_attach , adap - > fe [ 0 ] ,
2014-12-18 08:05:23 -03:00
dev - > demod_i2c_adapter ,
2014-12-07 22:02:23 -03:00
& rtl28xxu_qt1010_config ) ;
2011-07-08 23:36:07 -03:00
break ;
case TUNER_RTL2830_MT2060 :
2012-08-12 22:27:07 -03:00
fe = dvb_attach ( mt2060_attach , adap - > fe [ 0 ] ,
2014-12-18 08:05:23 -03:00
dev - > demod_i2c_adapter ,
2014-12-07 22:02:23 -03:00
& rtl28xxu_mt2060_config , 1220 ) ;
2011-07-08 23:36:07 -03:00
break ;
case TUNER_RTL2830_MXL5005S :
2012-08-12 22:27:07 -03:00
fe = dvb_attach ( mxl5005s_attach , adap - > fe [ 0 ] ,
2014-12-18 08:05:23 -03:00
dev - > demod_i2c_adapter ,
2014-12-07 22:02:23 -03:00
& rtl28xxu_mxl5005s_config ) ;
2011-07-08 23:36:07 -03:00
break ;
default :
2012-01-21 22:26:52 -03:00
fe = NULL ;
2014-12-21 11:25:57 -03:00
dev_err ( & d - > intf - > dev , " unknown tuner %d \n " , dev - > tuner ) ;
2011-07-08 23:36:07 -03:00
}
if ( fe = = NULL ) {
ret = - ENODEV ;
goto err ;
}
return 0 ;
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2011-07-08 23:36:07 -03:00
return ret ;
}
2012-12-08 23:27:49 -03:00
static const struct fc0012_config rtl2832u_fc0012_config = {
. i2c_address = 0x63 , /* 0xc6 >> 1 */
. xtal_freq = FC_XTAL_28_8_MHZ ,
} ;
2013-04-06 09:40:11 -03:00
static const struct r820t_config rtl2832u_r820t_config = {
. i2c_addr = 0x1a ,
. xtal = 28800000 ,
. max_i2c_msg_len = 2 ,
. rafael_chip = CHIP_R820T ,
} ;
2013-10-30 00:45:38 -03:00
static const struct r820t_config rtl2832u_r828d_config = {
. i2c_addr = 0x3a ,
. xtal = 16000000 ,
. max_i2c_msg_len = 2 ,
. rafael_chip = CHIP_R828D ,
} ;
2011-08-04 13:26:10 -03:00
static int rtl2832u_tuner_attach ( struct dvb_usb_adapter * adap )
{
int ret ;
2012-08-12 22:27:07 -03:00
struct dvb_usb_device * d = adap_to_d ( adap ) ;
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev = d_to_priv ( d ) ;
2013-10-15 19:22:45 -03:00
struct dvb_frontend * fe = NULL ;
struct i2c_board_info info ;
struct i2c_client * client ;
2014-12-16 10:50:54 -03:00
struct v4l2_subdev * subdev = NULL ;
2015-02-03 16:36:28 -02:00
struct platform_device * pdev ;
struct rtl2832_sdr_platform_data pdata ;
2011-08-04 13:26:10 -03:00
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " \n " ) ;
2011-08-04 13:26:10 -03:00
2013-10-15 19:22:45 -03:00
memset ( & info , 0 , sizeof ( struct i2c_board_info ) ) ;
2015-02-03 16:36:28 -02:00
memset ( & pdata , 0 , sizeof ( pdata ) ) ;
2013-10-15 19:22:45 -03:00
2014-12-18 08:05:23 -03:00
switch ( dev - > tuner ) {
2012-05-18 14:47:41 -03:00
case TUNER_RTL2832_FC0012 :
2012-08-12 22:27:07 -03:00
fe = dvb_attach ( fc0012_attach , adap - > fe [ 0 ] ,
2014-12-18 08:05:23 -03:00
dev - > demod_i2c_adapter , & rtl2832u_fc0012_config ) ;
2012-05-18 14:47:41 -03:00
/* since fc0012 includs reading the signal strength delegate
* that to the tuner driver */
2012-08-12 22:27:07 -03:00
adap - > fe [ 0 ] - > ops . read_signal_strength =
adap - > fe [ 0 ] - > ops . tuner_ops . get_rf_strength ;
2011-08-04 13:26:10 -03:00
break ;
2012-05-18 14:47:41 -03:00
case TUNER_RTL2832_FC0013 :
2012-08-12 22:27:07 -03:00
fe = dvb_attach ( fc0013_attach , adap - > fe [ 0 ] ,
2014-12-18 08:05:23 -03:00
dev - > demod_i2c_adapter , 0xc6 > > 1 , 0 , FC_XTAL_28_8_MHZ ) ;
2012-05-18 14:47:41 -03:00
/* fc0013 also supports signal strength reading */
2012-08-12 22:27:07 -03:00
adap - > fe [ 0 ] - > ops . read_signal_strength =
adap - > fe [ 0 ] - > ops . tuner_ops . get_rf_strength ;
2014-02-03 23:07:21 -03:00
break ;
2013-10-15 19:22:45 -03:00
case TUNER_RTL2832_E4000 : {
struct e4000_config e4000_config = {
. fe = adap - > fe [ 0 ] ,
. clock = 28800000 ,
} ;
strlcpy ( info . type , " e4000 " , I2C_NAME_SIZE ) ;
info . addr = 0x64 ;
info . platform_data = & e4000_config ;
request_module ( info . type ) ;
2014-12-18 08:05:23 -03:00
client = i2c_new_device ( dev - > demod_i2c_adapter , & info ) ;
2013-10-15 19:22:45 -03:00
if ( client = = NULL | | client - > dev . driver = = NULL )
break ;
if ( ! try_module_get ( client - > dev . driver - > owner ) ) {
i2c_unregister_device ( client ) ;
break ;
}
2014-12-18 08:05:23 -03:00
dev - > i2c_client_tuner = client ;
2014-12-16 10:50:54 -03:00
subdev = i2c_get_clientdata ( client ) ;
2013-10-15 19:22:45 -03:00
}
2012-09-01 21:09:22 -03:00
break ;
2015-04-14 19:55:51 -03:00
case TUNER_RTL2832_FC2580 : {
struct fc2580_platform_data fc2580_pdata = {
. dvb_frontend = adap - > fe [ 0 ] ,
} ;
struct i2c_board_info board_info = { } ;
strlcpy ( board_info . type , " fc2580 " , I2C_NAME_SIZE ) ;
board_info . addr = 0x56 ;
board_info . platform_data = & fc2580_pdata ;
request_module ( " fc2580 " ) ;
client = i2c_new_device ( dev - > demod_i2c_adapter ,
& board_info ) ;
if ( client = = NULL | | client - > dev . driver = = NULL )
break ;
if ( ! try_module_get ( client - > dev . driver - > owner ) ) {
i2c_unregister_device ( client ) ;
break ;
}
dev - > i2c_client_tuner = client ;
2015-05-03 21:48:47 -03:00
subdev = fc2580_pdata . get_v4l2_subdev ( client ) ;
2015-04-14 19:55:51 -03:00
}
2012-09-08 22:07:25 -03:00
break ;
2015-04-15 19:25:32 -03:00
case TUNER_RTL2832_TUA9001 : {
struct tua9001_platform_data tua9001_pdata = {
. dvb_frontend = adap - > fe [ 0 ] ,
} ;
struct i2c_board_info board_info = { } ;
2012-09-11 22:27:09 -03:00
/* enable GPIO1 and GPIO4 as output */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_DIR , 0x00 , 0x12 ) ;
2012-09-17 15:43:57 -03:00
if ( ret )
2012-09-11 22:27:09 -03:00
goto err ;
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_OUT_EN , 0x12 , 0x12 ) ;
2012-09-17 15:43:57 -03:00
if ( ret )
2012-09-11 22:27:09 -03:00
goto err ;
2015-04-15 19:25:32 -03:00
strlcpy ( board_info . type , " tua9001 " , I2C_NAME_SIZE ) ;
board_info . addr = 0x60 ;
board_info . platform_data = & tua9001_pdata ;
request_module ( " tua9001 " ) ;
client = i2c_new_device ( dev - > demod_i2c_adapter , & board_info ) ;
if ( client = = NULL | | client - > dev . driver = = NULL )
break ;
if ( ! try_module_get ( client - > dev . driver - > owner ) ) {
i2c_unregister_device ( client ) ;
break ;
}
dev - > i2c_client_tuner = client ;
2012-09-11 22:27:09 -03:00
break ;
2015-04-15 19:25:32 -03:00
}
2013-04-06 09:40:11 -03:00
case TUNER_RTL2832_R820T :
2014-12-14 11:45:55 -03:00
fe = dvb_attach ( r820t_attach , adap - > fe [ 0 ] ,
2014-12-18 08:05:23 -03:00
dev - > demod_i2c_adapter ,
2013-04-06 09:40:11 -03:00
& rtl2832u_r820t_config ) ;
2013-04-07 18:57:15 -03:00
2013-10-30 00:45:38 -03:00
/* Use tuner to get the signal strength */
adap - > fe [ 0 ] - > ops . read_signal_strength =
adap - > fe [ 0 ] - > ops . tuner_ops . get_rf_strength ;
break ;
case TUNER_RTL2832_R828D :
2013-12-01 13:44:23 -03:00
fe = dvb_attach ( r820t_attach , adap - > fe [ 0 ] ,
2014-12-18 08:05:23 -03:00
dev - > demod_i2c_adapter ,
2013-10-30 00:45:38 -03:00
& rtl2832u_r828d_config ) ;
2013-04-07 18:57:15 -03:00
adap - > fe [ 0 ] - > ops . read_signal_strength =
adap - > fe [ 0 ] - > ops . tuner_ops . get_rf_strength ;
2013-12-01 13:44:23 -03:00
if ( adap - > fe [ 1 ] ) {
fe = dvb_attach ( r820t_attach , adap - > fe [ 1 ] ,
2014-12-18 08:05:23 -03:00
dev - > demod_i2c_adapter ,
2013-12-01 13:44:23 -03:00
& rtl2832u_r828d_config ) ;
adap - > fe [ 1 ] - > ops . read_signal_strength =
adap - > fe [ 1 ] - > ops . tuner_ops . get_rf_strength ;
}
2013-04-06 09:40:11 -03:00
break ;
2015-05-05 13:54:19 -03:00
case TUNER_RTL2832_SI2157 : {
struct si2157_config si2157_config = {
. fe = adap - > fe [ 0 ] ,
. if_port = 0 ,
. inversion = false ,
} ;
strlcpy ( info . type , " si2157 " , I2C_NAME_SIZE ) ;
info . addr = 0x60 ;
info . platform_data = & si2157_config ;
request_module ( info . type ) ;
client = i2c_new_device ( & d - > i2c_adap , & info ) ;
if ( client = = NULL | | client - > dev . driver = = NULL )
break ;
if ( ! try_module_get ( client - > dev . driver - > owner ) ) {
i2c_unregister_device ( client ) ;
break ;
}
dev - > i2c_client_tuner = client ;
subdev = i2c_get_clientdata ( client ) ;
/* copy tuner ops for 2nd FE as tuner is shared */
if ( adap - > fe [ 1 ] ) {
adap - > fe [ 1 ] - > tuner_priv =
adap - > fe [ 0 ] - > tuner_priv ;
memcpy ( & adap - > fe [ 1 ] - > ops . tuner_ops ,
& adap - > fe [ 0 ] - > ops . tuner_ops ,
sizeof ( struct dvb_tuner_ops ) ) ;
}
}
break ;
2011-08-04 13:26:10 -03:00
default :
2014-12-21 11:25:57 -03:00
dev_err ( & d - > intf - > dev , " unknown tuner %d \n " , dev - > tuner ) ;
2011-08-04 13:26:10 -03:00
}
2014-12-18 08:05:23 -03:00
if ( fe = = NULL & & dev - > i2c_client_tuner = = NULL ) {
2011-08-04 13:26:10 -03:00
ret = - ENODEV ;
goto err ;
}
2014-12-16 10:50:54 -03:00
/* register SDR */
2014-12-18 08:05:23 -03:00
switch ( dev - > tuner ) {
2015-05-03 21:48:47 -03:00
case TUNER_RTL2832_FC2580 :
2014-12-16 10:50:54 -03:00
case TUNER_RTL2832_FC0012 :
case TUNER_RTL2832_FC0013 :
case TUNER_RTL2832_E4000 :
case TUNER_RTL2832_R820T :
case TUNER_RTL2832_R828D :
2014-12-18 08:05:23 -03:00
pdata . clk = dev - > rtl2832_platform_data . clk ;
pdata . tuner = dev - > tuner ;
pdata . i2c_client = dev - > i2c_client_demod ;
pdata . bulk_read = dev - > rtl2832_platform_data . bulk_read ;
pdata . bulk_write = dev - > rtl2832_platform_data . bulk_write ;
pdata . update_bits = dev - > rtl2832_platform_data . update_bits ;
2014-12-16 10:50:54 -03:00
pdata . dvb_frontend = adap - > fe [ 0 ] ;
pdata . dvb_usb_device = d ;
pdata . v4l2_subdev = subdev ;
request_module ( " %s " , " rtl2832_sdr " ) ;
2014-12-17 08:16:10 -03:00
pdev = platform_device_register_data ( & d - > intf - > dev ,
2014-12-16 10:50:54 -03:00
" rtl2832_sdr " ,
PLATFORM_DEVID_AUTO ,
& pdata , sizeof ( pdata ) ) ;
2015-04-16 09:22:46 -03:00
if ( IS_ERR ( pdev ) | | pdev - > dev . driver = = NULL )
2014-12-16 10:50:54 -03:00
break ;
2014-12-18 08:05:23 -03:00
dev - > platform_device_sdr = pdev ;
2014-12-16 10:50:54 -03:00
break ;
default :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " no SDR for tuner=%d \n " , dev - > tuner ) ;
2014-12-16 10:50:54 -03:00
}
2011-08-04 13:26:10 -03:00
return 0 ;
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2011-08-04 13:26:10 -03:00
return ret ;
}
2014-12-23 14:09:13 -03:00
static int rtl28xxu_tuner_attach ( struct dvb_usb_adapter * adap )
{
struct rtl28xxu_dev * dev = adap_to_priv ( adap ) ;
if ( dev - > chip_id = = CHIP_ID_RTL2831U )
return rtl2831u_tuner_attach ( adap ) ;
else
return rtl2832u_tuner_attach ( adap ) ;
}
static int rtl28xxu_tuner_detach ( struct dvb_usb_adapter * adap )
2014-12-02 11:23:49 -03:00
{
struct dvb_usb_device * d = adap_to_d ( adap ) ;
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev = d_to_priv ( d ) ;
2014-12-02 11:23:49 -03:00
struct i2c_client * client ;
2014-12-16 10:50:54 -03:00
struct platform_device * pdev ;
2014-12-02 11:23:49 -03:00
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " \n " ) ;
2014-12-02 11:23:49 -03:00
2014-12-16 10:50:54 -03:00
/* remove platform SDR */
2014-12-18 08:05:23 -03:00
pdev = dev - > platform_device_sdr ;
2014-12-17 08:16:10 -03:00
if ( pdev )
2014-12-16 10:50:54 -03:00
platform_device_unregister ( pdev ) ;
2014-12-02 11:23:49 -03:00
/* remove I2C tuner */
2014-12-18 08:05:23 -03:00
client = dev - > i2c_client_tuner ;
2014-12-02 11:23:49 -03:00
if ( client ) {
module_put ( client - > dev . driver - > owner ) ;
i2c_unregister_device ( client ) ;
}
return 0 ;
}
2012-08-12 22:27:07 -03:00
static int rtl28xxu_init ( struct dvb_usb_device * d )
{
int ret ;
u8 val ;
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " \n " ) ;
2012-08-12 22:27:07 -03:00
/* init USB endpoints */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_rd_reg ( d , USB_SYSCTL_0 , & val ) ;
2012-08-12 22:27:07 -03:00
if ( ret )
goto err ;
/* enable DMA and Full Packet Mode*/
val | = 0x09 ;
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg ( d , USB_SYSCTL_0 , val ) ;
2012-08-12 22:27:07 -03:00
if ( ret )
goto err ;
/* set EPA maximum packet size to 0x0200 */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_regs ( d , USB_EPA_MAXPKT , " \x00 \x02 \x00 \x00 " , 4 ) ;
2012-08-12 22:27:07 -03:00
if ( ret )
goto err ;
/* change EPA FIFO length */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_regs ( d , USB_EPA_FIFO_CFG , " \x14 \x00 \x00 \x00 " , 4 ) ;
2012-08-12 22:27:07 -03:00
if ( ret )
goto err ;
return ret ;
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2012-08-12 22:27:07 -03:00
return ret ;
}
2012-05-18 14:47:41 -03:00
static int rtl2831u_power_ctrl ( struct dvb_usb_device * d , int onoff )
2011-07-08 23:36:07 -03:00
{
int ret ;
2012-09-01 09:54:43 -03:00
u8 gpio , sys0 , epa_ctl [ 2 ] ;
2011-07-08 23:36:07 -03:00
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " onoff=%d \n " , onoff ) ;
2011-07-08 23:36:07 -03:00
/* demod adc */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_rd_reg ( d , SYS_SYS0 , & sys0 ) ;
2011-07-08 23:36:07 -03:00
if ( ret )
goto err ;
/* tuner power, read GPIOs */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_rd_reg ( d , SYS_GPIO_OUT_VAL , & gpio ) ;
2011-07-08 23:36:07 -03:00
if ( ret )
goto err ;
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " RD SYS0=%02x GPIO_OUT_VAL=%02x \n " , sys0 , gpio ) ;
2011-07-08 23:36:07 -03:00
if ( onoff ) {
gpio | = 0x01 ; /* GPIO0 = 1 */
gpio & = ( ~ 0x10 ) ; /* GPIO4 = 0 */
2012-08-12 22:27:08 -03:00
gpio | = 0x04 ; /* GPIO2 = 1, LED on */
2011-07-08 23:36:07 -03:00
sys0 = sys0 & 0x0f ;
sys0 | = 0xe0 ;
2012-09-01 09:54:43 -03:00
epa_ctl [ 0 ] = 0x00 ; /* clear stall */
epa_ctl [ 1 ] = 0x00 ; /* clear reset */
2011-07-08 23:36:07 -03:00
} else {
gpio & = ( ~ 0x01 ) ; /* GPIO0 = 0 */
gpio | = 0x10 ; /* GPIO4 = 1 */
2012-08-12 22:27:08 -03:00
gpio & = ( ~ 0x04 ) ; /* GPIO2 = 1, LED off */
2011-07-08 23:36:07 -03:00
sys0 = sys0 & ( ~ 0xc0 ) ;
2012-09-01 09:54:43 -03:00
epa_ctl [ 0 ] = 0x10 ; /* set stall */
epa_ctl [ 1 ] = 0x02 ; /* set reset */
2011-07-08 23:36:07 -03:00
}
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " WR SYS0=%02x GPIO_OUT_VAL=%02x \n " , sys0 , gpio ) ;
2011-07-08 23:36:07 -03:00
/* demod adc */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg ( d , SYS_SYS0 , sys0 ) ;
2011-07-08 23:36:07 -03:00
if ( ret )
goto err ;
/* tuner power, write GPIOs */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg ( d , SYS_GPIO_OUT_VAL , gpio ) ;
2011-07-08 23:36:07 -03:00
if ( ret )
goto err ;
2012-09-01 09:54:43 -03:00
/* streaming EP: stall & reset */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_regs ( d , USB_EPA_CTL , epa_ctl , 2 ) ;
2012-09-01 09:54:43 -03:00
if ( ret )
goto err ;
if ( onoff )
usb_clear_halt ( d - > udev , usb_rcvbulkpipe ( d - > udev , 0x81 ) ) ;
2011-07-08 23:36:07 -03:00
return ret ;
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2011-07-08 23:36:07 -03:00
return ret ;
}
2012-05-18 14:47:41 -03:00
static int rtl2832u_power_ctrl ( struct dvb_usb_device * d , int onoff )
{
int ret ;
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " onoff=%d \n " , onoff ) ;
2012-05-18 14:47:41 -03:00
if ( onoff ) {
2013-06-04 18:26:54 -03:00
/* GPIO3=1, GPIO4=0 */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_OUT_VAL , 0x08 , 0x18 ) ;
2012-05-18 14:47:41 -03:00
if ( ret )
goto err ;
2013-06-04 18:26:54 -03:00
/* suspend? */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_DEMOD_CTL1 , 0x00 , 0x10 ) ;
2012-05-18 14:47:41 -03:00
if ( ret )
goto err ;
2013-06-04 18:26:54 -03:00
/* enable PLL */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_DEMOD_CTL , 0x80 , 0x80 ) ;
2012-05-18 14:47:41 -03:00
if ( ret )
goto err ;
2013-06-04 18:26:54 -03:00
/* disable reset */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_DEMOD_CTL , 0x20 , 0x20 ) ;
2012-05-18 14:47:41 -03:00
if ( ret )
goto err ;
2012-09-01 09:54:43 -03:00
/* streaming EP: clear stall & reset */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_regs ( d , USB_EPA_CTL , " \x00 \x00 " , 2 ) ;
2012-09-01 09:54:43 -03:00
if ( ret )
goto err ;
ret = usb_clear_halt ( d - > udev , usb_rcvbulkpipe ( d - > udev , 0x81 ) ) ;
if ( ret )
goto err ;
2012-05-18 14:47:41 -03:00
} else {
2013-06-04 18:26:54 -03:00
/* GPIO4=1 */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_GPIO_OUT_VAL , 0x10 , 0x10 ) ;
2012-05-18 14:47:41 -03:00
if ( ret )
goto err ;
2013-06-04 18:26:54 -03:00
/* disable PLL */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_DEMOD_CTL , 0x00 , 0x80 ) ;
2012-05-18 14:47:41 -03:00
if ( ret )
goto err ;
2012-09-01 09:54:43 -03:00
/* streaming EP: set stall & reset */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_regs ( d , USB_EPA_CTL , " \x10 \x02 " , 2 ) ;
2012-09-01 09:54:43 -03:00
if ( ret )
goto err ;
2012-05-18 14:47:41 -03:00
}
return ret ;
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2012-05-18 14:47:41 -03:00
return ret ;
}
2014-12-23 14:09:13 -03:00
static int rtl28xxu_power_ctrl ( struct dvb_usb_device * d , int onoff )
{
struct rtl28xxu_dev * dev = d_to_priv ( d ) ;
if ( dev - > chip_id = = CHIP_ID_RTL2831U )
return rtl2831u_power_ctrl ( d , onoff ) ;
else
return rtl2832u_power_ctrl ( d , onoff ) ;
}
static int rtl28xxu_frontend_ctrl ( struct dvb_frontend * fe , int onoff )
2014-09-27 01:22:45 -03:00
{
struct dvb_usb_device * d = fe_to_d ( fe ) ;
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev = fe_to_priv ( fe ) ;
struct rtl2832_platform_data * pdata = & dev - > rtl2832_platform_data ;
2014-09-27 01:22:45 -03:00
int ret ;
u8 val ;
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " fe=%d onoff=%d \n " , fe - > id , onoff ) ;
2014-09-27 01:22:45 -03:00
2014-12-23 14:09:13 -03:00
if ( dev - > chip_id = = CHIP_ID_RTL2831U )
return 0 ;
2014-09-27 01:22:45 -03:00
/* control internal demod ADC */
if ( fe - > id = = 0 & & onoff )
val = 0x48 ; /* enable ADC */
else
val = 0x00 ; /* disable ADC */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , SYS_DEMOD_CTL , val , 0x48 ) ;
2014-09-27 01:22:45 -03:00
if ( ret )
goto err ;
2013-12-01 13:44:23 -03:00
/* bypass slave demod TS through master demod */
if ( fe - > id = = 1 & & onoff ) {
2014-12-18 08:05:23 -03:00
ret = pdata - > enable_slave_ts ( dev - > i2c_client_demod ) ;
2013-12-01 13:44:23 -03:00
if ( ret )
goto err ;
}
2014-09-27 01:22:45 -03:00
return 0 ;
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2014-09-27 01:22:45 -03:00
return ret ;
}
2013-01-04 15:21:26 -03:00
# if IS_ENABLED(CONFIG_RC_CORE)
2011-08-04 13:26:10 -03:00
static int rtl2831u_rc_query ( struct dvb_usb_device * d )
2011-07-08 23:36:07 -03:00
{
2011-08-04 13:26:10 -03:00
int ret , i ;
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev = d - > priv ;
2011-07-08 23:36:07 -03:00
u8 buf [ 5 ] ;
u32 rc_code ;
2011-08-04 13:26:10 -03:00
struct rtl28xxu_reg_val rc_nec_tab [ ] = {
{ 0x3033 , 0x80 } ,
{ 0x3020 , 0x43 } ,
{ 0x3021 , 0x16 } ,
{ 0x3022 , 0x16 } ,
{ 0x3023 , 0x5a } ,
{ 0x3024 , 0x2d } ,
{ 0x3025 , 0x16 } ,
{ 0x3026 , 0x01 } ,
{ 0x3028 , 0xb0 } ,
{ 0x3029 , 0x04 } ,
{ 0x302c , 0x88 } ,
{ 0x302e , 0x13 } ,
{ 0x3030 , 0xdf } ,
{ 0x3031 , 0x05 } ,
} ;
/* init remote controller */
2014-12-18 08:05:23 -03:00
if ( ! dev - > rc_active ) {
2011-08-04 13:26:10 -03:00
for ( i = 0 ; i < ARRAY_SIZE ( rc_nec_tab ) ; i + + ) {
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg ( d , rc_nec_tab [ i ] . reg ,
2012-01-21 22:26:52 -03:00
rc_nec_tab [ i ] . val ) ;
2011-08-04 13:26:10 -03:00
if ( ret )
goto err ;
}
2014-12-18 08:05:23 -03:00
dev - > rc_active = true ;
2011-08-04 13:26:10 -03:00
}
2011-07-08 23:36:07 -03:00
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_rd_regs ( d , SYS_IRRC_RP , buf , 5 ) ;
2011-07-08 23:36:07 -03:00
if ( ret )
goto err ;
if ( buf [ 4 ] & 0x01 ) {
if ( buf [ 2 ] = = ( u8 ) ~ buf [ 3 ] ) {
if ( buf [ 0 ] = = ( u8 ) ~ buf [ 1 ] ) {
/* NEC standard (16 bit) */
2014-04-03 20:31:30 -03:00
rc_code = RC_SCANCODE_NEC ( buf [ 0 ] , buf [ 2 ] ) ;
2011-07-08 23:36:07 -03:00
} else {
/* NEC extended (24 bit) */
2014-04-03 20:31:30 -03:00
rc_code = RC_SCANCODE_NECX ( buf [ 0 ] < < 8 | buf [ 1 ] ,
buf [ 2 ] ) ;
2011-07-08 23:36:07 -03:00
}
} else {
/* NEC full (32 bit) */
2014-04-03 20:31:30 -03:00
rc_code = RC_SCANCODE_NEC32 ( buf [ 0 ] < < 24 | buf [ 1 ] < < 16 |
buf [ 2 ] < < 8 | buf [ 3 ] ) ;
2011-07-08 23:36:07 -03:00
}
2014-04-03 20:31:30 -03:00
rc_keydown ( d - > rc_dev , RC_TYPE_NEC , rc_code , 0 ) ;
2011-07-08 23:36:07 -03:00
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg ( d , SYS_IRRC_SR , 1 ) ;
2011-07-08 23:36:07 -03:00
if ( ret )
goto err ;
/* repeated intentionally to avoid extra keypress */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg ( d , SYS_IRRC_SR , 1 ) ;
2011-07-08 23:36:07 -03:00
if ( ret )
goto err ;
}
return ret ;
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2011-07-08 23:36:07 -03:00
return ret ;
}
2012-08-12 22:27:07 -03:00
static int rtl2831u_get_rc_config ( struct dvb_usb_device * d ,
struct dvb_usb_rc * rc )
{
rc - > map_name = RC_MAP_EMPTY ;
2012-10-11 19:11:54 -03:00
rc - > allowed_protos = RC_BIT_NEC ;
2012-08-12 22:27:07 -03:00
rc - > query = rtl2831u_rc_query ;
rc - > interval = 400 ;
return 0 ;
}
2011-08-04 13:26:10 -03:00
static int rtl2832u_rc_query ( struct dvb_usb_device * d )
{
2013-06-04 09:17:03 -03:00
int ret , i , len ;
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev = d - > priv ;
2013-06-04 09:17:03 -03:00
struct ir_raw_event ev ;
2011-08-04 13:26:10 -03:00
u8 buf [ 128 ] ;
2013-06-04 09:17:03 -03:00
static const struct rtl28xxu_reg_val_mask refresh_tab [ ] = {
{ IR_RX_IF , 0x03 , 0xff } ,
{ IR_RX_BUF_CTRL , 0x80 , 0xff } ,
{ IR_RX_CTRL , 0x80 , 0xff } ,
} ;
2011-08-04 13:26:10 -03:00
/* init remote controller */
2014-12-18 08:05:23 -03:00
if ( ! dev - > rc_active ) {
2013-06-04 09:17:03 -03:00
static const struct rtl28xxu_reg_val_mask init_tab [ ] = {
{ SYS_DEMOD_CTL1 , 0x00 , 0x04 } ,
{ SYS_DEMOD_CTL1 , 0x00 , 0x08 } ,
{ USB_CTRL , 0x20 , 0x20 } ,
{ SYS_GPIO_DIR , 0x00 , 0x08 } ,
{ SYS_GPIO_OUT_EN , 0x08 , 0x08 } ,
{ SYS_GPIO_OUT_VAL , 0x08 , 0x08 } ,
{ IR_MAX_DURATION0 , 0xd0 , 0xff } ,
{ IR_MAX_DURATION1 , 0x07 , 0xff } ,
{ IR_IDLE_LEN0 , 0xc0 , 0xff } ,
{ IR_IDLE_LEN1 , 0x00 , 0xff } ,
{ IR_GLITCH_LEN , 0x03 , 0xff } ,
{ IR_RX_CLK , 0x09 , 0xff } ,
{ IR_RX_CFG , 0x1c , 0xff } ,
{ IR_MAX_H_TOL_LEN , 0x1e , 0xff } ,
{ IR_MAX_L_TOL_LEN , 0x1e , 0xff } ,
{ IR_RX_CTRL , 0x80 , 0xff } ,
} ;
for ( i = 0 ; i < ARRAY_SIZE ( init_tab ) ; i + + ) {
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , init_tab [ i ] . reg ,
2013-06-04 09:17:03 -03:00
init_tab [ i ] . val , init_tab [ i ] . mask ) ;
2011-08-04 13:26:10 -03:00
if ( ret )
goto err ;
}
2013-06-04 09:17:03 -03:00
2014-12-18 08:05:23 -03:00
dev - > rc_active = true ;
2011-08-04 13:26:10 -03:00
}
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_rd_reg ( d , IR_RX_IF , & buf [ 0 ] ) ;
2011-08-04 13:26:10 -03:00
if ( ret )
goto err ;
if ( buf [ 0 ] ! = 0x83 )
2013-06-04 09:17:03 -03:00
goto exit ;
2011-08-04 13:26:10 -03:00
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_rd_reg ( d , IR_RX_BC , & buf [ 0 ] ) ;
2011-08-04 13:26:10 -03:00
if ( ret )
goto err ;
len = buf [ 0 ] ;
2013-06-04 09:17:03 -03:00
/* read raw code from hw */
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_rd_regs ( d , IR_RX_BUF , buf , len ) ;
2013-06-04 09:17:03 -03:00
if ( ret )
goto err ;
2011-08-04 13:26:10 -03:00
2013-06-04 09:17:03 -03:00
/* let hw receive new code */
for ( i = 0 ; i < ARRAY_SIZE ( refresh_tab ) ; i + + ) {
2014-12-23 14:32:35 -03:00
ret = rtl28xxu_wr_reg_mask ( d , refresh_tab [ i ] . reg ,
2013-06-04 09:17:03 -03:00
refresh_tab [ i ] . val , refresh_tab [ i ] . mask ) ;
2013-04-20 20:02:12 -03:00
if ( ret )
goto err ;
}
2011-08-04 13:26:10 -03:00
2013-06-04 09:17:03 -03:00
/* pass data to Kernel IR decoder */
init_ir_raw_event ( & ev ) ;
for ( i = 0 ; i < len ; i + + ) {
ev . pulse = buf [ i ] > > 7 ;
ev . duration = 50800 * ( buf [ i ] & 0x7f ) ;
ir_raw_event_store_with_filter ( d - > rc_dev , & ev ) ;
}
/* 'flush' ir_raw_event_store_with_filter() */
ir_raw_event_set_idle ( d - > rc_dev , true ) ;
ir_raw_event_handle ( d - > rc_dev ) ;
exit :
2011-08-04 13:26:10 -03:00
return ret ;
err :
2014-12-21 11:25:57 -03:00
dev_dbg ( & d - > intf - > dev , " failed=%d \n " , ret ) ;
2011-08-04 13:26:10 -03:00
return ret ;
}
2012-08-12 22:27:07 -03:00
static int rtl2832u_get_rc_config ( struct dvb_usb_device * d ,
struct dvb_usb_rc * rc )
{
2013-11-22 14:20:14 -03:00
/* disable IR interrupts in order to avoid SDR sample loss */
if ( rtl28xxu_disable_rc )
2014-12-23 14:32:35 -03:00
return rtl28xxu_wr_reg ( d , IR_RX_IE , 0x00 ) ;
2013-11-22 14:20:14 -03:00
2013-06-04 09:17:03 -03:00
/* load empty to enable rc */
if ( ! rc - > map_name )
rc - > map_name = RC_MAP_EMPTY ;
2013-04-20 20:02:12 -03:00
rc - > allowed_protos = RC_BIT_ALL ;
2013-06-04 09:17:03 -03:00
rc - > driver_type = RC_DRIVER_IR_RAW ;
2012-08-12 22:27:07 -03:00
rc - > query = rtl2832u_rc_query ;
2015-03-15 19:57:48 -03:00
rc - > interval = 200 ;
2011-07-08 23:36:07 -03:00
2012-08-12 22:27:07 -03:00
return 0 ;
}
2011-07-08 23:36:07 -03:00
2014-12-23 14:09:13 -03:00
static int rtl28xxu_get_rc_config ( struct dvb_usb_device * d ,
struct dvb_usb_rc * rc )
2014-12-09 16:10:14 -03:00
{
2014-12-18 08:05:23 -03:00
struct rtl28xxu_dev * dev = d_to_priv ( d ) ;
2014-12-09 16:10:14 -03:00
2014-12-23 14:09:13 -03:00
if ( dev - > chip_id = = CHIP_ID_RTL2831U )
return rtl2831u_get_rc_config ( d , rc ) ;
else
return rtl2832u_get_rc_config ( d , rc ) ;
2014-12-09 16:10:14 -03:00
}
2014-12-23 14:09:13 -03:00
# else
# define rtl28xxu_get_rc_config NULL
# endif
2014-12-09 16:10:14 -03:00
2014-12-23 14:09:13 -03:00
static int rtl28xxu_pid_filter_ctrl ( struct dvb_usb_adapter * adap , int onoff )
2014-12-14 14:10:47 -03:00
{
2014-12-23 14:09:13 -03:00
struct rtl28xxu_dev * dev = adap_to_priv ( adap ) ;
2014-12-14 14:10:47 -03:00
2014-12-23 14:09:13 -03:00
if ( dev - > chip_id = = CHIP_ID_RTL2831U ) {
struct rtl2830_platform_data * pdata = & dev - > rtl2830_platform_data ;
2014-12-14 14:10:47 -03:00
2014-12-23 14:09:13 -03:00
return pdata - > pid_filter_ctrl ( adap - > fe [ 0 ] , onoff ) ;
} else {
struct rtl2832_platform_data * pdata = & dev - > rtl2832_platform_data ;
2014-12-09 16:10:14 -03:00
2014-12-23 14:09:13 -03:00
return pdata - > pid_filter_ctrl ( adap - > fe [ 0 ] , onoff ) ;
}
2014-12-09 16:10:14 -03:00
}
2014-12-23 14:09:13 -03:00
static int rtl28xxu_pid_filter ( struct dvb_usb_adapter * adap , int index ,
u16 pid , int onoff )
2014-12-14 14:10:47 -03:00
{
2014-12-23 14:09:13 -03:00
struct rtl28xxu_dev * dev = adap_to_priv ( adap ) ;
if ( dev - > chip_id = = CHIP_ID_RTL2831U ) {
struct rtl2830_platform_data * pdata = & dev - > rtl2830_platform_data ;
2014-12-14 14:10:47 -03:00
2014-12-23 14:09:13 -03:00
return pdata - > pid_filter ( adap - > fe [ 0 ] , index , pid , onoff ) ;
} else {
struct rtl2832_platform_data * pdata = & dev - > rtl2832_platform_data ;
return pdata - > pid_filter ( adap - > fe [ 0 ] , index , pid , onoff ) ;
}
2014-12-14 14:10:47 -03:00
}
2014-12-23 14:21:10 -03:00
static const struct dvb_usb_device_properties rtl28xxu_props = {
2012-08-12 22:27:07 -03:00
. driver_name = KBUILD_MODNAME ,
. owner = THIS_MODULE ,
. adapter_nr = adapter_nr ,
2014-12-18 08:05:23 -03:00
. size_of_priv = sizeof ( struct rtl28xxu_dev ) ,
2012-08-12 22:27:07 -03:00
2014-12-23 13:14:36 -03:00
. identify_state = rtl28xxu_identify_state ,
2014-12-23 14:09:13 -03:00
. power_ctrl = rtl28xxu_power_ctrl ,
. frontend_ctrl = rtl28xxu_frontend_ctrl ,
2012-08-12 22:27:07 -03:00
. i2c_algo = & rtl28xxu_i2c_algo ,
2014-12-23 14:09:13 -03:00
. read_config = rtl28xxu_read_config ,
. frontend_attach = rtl28xxu_frontend_attach ,
. frontend_detach = rtl28xxu_frontend_detach ,
. tuner_attach = rtl28xxu_tuner_attach ,
. tuner_detach = rtl28xxu_tuner_detach ,
2012-08-12 22:27:07 -03:00
. init = rtl28xxu_init ,
2014-12-23 14:09:13 -03:00
. get_rc_config = rtl28xxu_get_rc_config ,
2012-08-12 22:27:07 -03:00
. num_adapters = 1 ,
. adapter = {
{
2014-12-14 14:10:47 -03:00
. caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF ,
. pid_filter_count = 32 ,
2014-12-23 14:09:13 -03:00
. pid_filter_ctrl = rtl28xxu_pid_filter_ctrl ,
. pid_filter = rtl28xxu_pid_filter ,
2014-12-14 14:10:47 -03:00
2012-08-12 22:27:07 -03:00
. stream = DVB_USB_STREAM_BULK ( 0x81 , 6 , 8 * 512 ) ,
2011-08-04 13:26:10 -03:00
} ,
} ,
2011-07-08 23:36:07 -03:00
} ;
2012-08-12 22:27:07 -03:00
static const struct usb_device_id rtl28xxu_id_table [ ] = {
2014-02-26 15:33:40 -03:00
/* RTL2831U devices: */
2012-08-12 22:27:07 -03:00
{ DVB_USB_DEVICE ( USB_VID_REALTEK , USB_PID_REALTEK_RTL2831U ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Realtek RTL2831U reference design " , NULL ) } ,
2012-08-12 22:27:07 -03:00
{ DVB_USB_DEVICE ( USB_VID_WIDEVIEW , USB_PID_FREECOM_DVBT ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Freecom USB2.0 DVB-T " , NULL ) } ,
2012-08-12 22:27:07 -03:00
{ DVB_USB_DEVICE ( USB_VID_WIDEVIEW , USB_PID_FREECOM_DVBT_2 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Freecom USB2.0 DVB-T " , NULL ) } ,
2012-08-12 22:27:07 -03:00
2014-02-26 15:33:40 -03:00
/* RTL2832U devices: */
2012-09-18 10:27:05 -03:00
{ DVB_USB_DEVICE ( USB_VID_REALTEK , 0x2832 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Realtek RTL2832U reference design " , NULL ) } ,
2012-09-18 10:27:05 -03:00
{ DVB_USB_DEVICE ( USB_VID_REALTEK , 0x2838 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Realtek RTL2832U reference design " , NULL ) } ,
2012-08-12 22:27:07 -03:00
{ DVB_USB_DEVICE ( USB_VID_TERRATEC , USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " TerraTec Cinergy T Stick Black " , RC_MAP_TERRATEC_SLIM ) } ,
2012-08-12 22:27:07 -03:00
{ DVB_USB_DEVICE ( USB_VID_GTEK , USB_PID_DELOCK_USB2_DVBT ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " G-Tek Electronics Group Lifeview LV5TDLX DVB-T " , NULL ) } ,
2012-08-12 22:27:07 -03:00
{ DVB_USB_DEVICE ( USB_VID_TERRATEC , USB_PID_NOXON_DAB_STICK ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " TerraTec NOXON DAB Stick " , NULL ) } ,
2012-11-13 14:09:28 -03:00
{ DVB_USB_DEVICE ( USB_VID_TERRATEC , USB_PID_NOXON_DAB_STICK_REV2 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " TerraTec NOXON DAB Stick (rev 2) " , NULL ) } ,
2014-02-11 17:27:57 -03:00
{ DVB_USB_DEVICE ( USB_VID_TERRATEC , USB_PID_NOXON_DAB_STICK_REV3 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " TerraTec NOXON DAB Stick (rev 3) " , NULL ) } ,
2012-09-02 19:30:54 -03:00
{ DVB_USB_DEVICE ( USB_VID_GTEK , USB_PID_TREKSTOR_TERRES_2_0 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Trekstor DVB-T Stick Terres 2.0 " , NULL ) } ,
2012-09-08 22:07:26 -03:00
{ DVB_USB_DEVICE ( USB_VID_DEXATEK , 0x1101 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Dexatek DK DVB-T Dongle " , NULL ) } ,
2012-09-20 18:34:50 -03:00
{ DVB_USB_DEVICE ( USB_VID_LEADTEK , 0x6680 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " DigitalNow Quad DVB-T Receiver " , NULL ) } ,
2013-12-13 09:59:10 -03:00
{ DVB_USB_DEVICE ( USB_VID_LEADTEK , USB_PID_WINFAST_DTV_DONGLE_MINID ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Leadtek Winfast DTV Dongle Mini D " , NULL ) } ,
2015-03-09 02:19:01 -03:00
{ DVB_USB_DEVICE ( USB_VID_LEADTEK , USB_PID_WINFAST_DTV2000DS_PLUS ,
& rtl28xxu_props , " Leadtek WinFast DTV2000DS Plus " , RC_MAP_LEADTEK_Y04G0051 ) } ,
2012-09-29 15:28:56 -03:00
{ DVB_USB_DEVICE ( USB_VID_TERRATEC , 0x00d3 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " TerraTec Cinergy T Stick RC (Rev. 3) " , NULL ) } ,
2012-11-06 16:03:35 -03:00
{ DVB_USB_DEVICE ( USB_VID_DEXATEK , 0x1102 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Dexatek DK mini DVB-T Dongle " , NULL ) } ,
2012-11-06 20:01:16 -03:00
{ DVB_USB_DEVICE ( USB_VID_TERRATEC , 0x00d7 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " TerraTec Cinergy T Stick+ " , NULL ) } ,
2012-12-16 11:47:07 -03:00
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , 0xd3a8 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " ASUS My Cinema-U3100Mini Plus V2 " , NULL ) } ,
2013-01-04 18:19:02 -03:00
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , 0xd393 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " GIGABYTE U7300 " , NULL ) } ,
2013-01-14 18:21:32 -03:00
{ DVB_USB_DEVICE ( USB_VID_DEXATEK , 0x1104 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " MSI DIGIVOX Micro HD " , NULL ) } ,
2013-02-12 21:58:47 -03:00
{ DVB_USB_DEVICE ( USB_VID_COMPRO , 0x0620 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Compro VideoMate U620F " , NULL ) } ,
2015-08-09 11:38:07 -03:00
{ DVB_USB_DEVICE ( USB_VID_COMPRO , 0x0650 ,
& rtl28xxu_props , " Compro VideoMate U650F " , NULL ) } ,
2013-02-15 18:54:54 -03:00
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , 0xd394 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " MaxMedia HU394-T " , NULL ) } ,
2013-05-14 19:42:11 -03:00
{ DVB_USB_DEVICE ( USB_VID_LEADTEK , 0x6a03 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Leadtek WinFast DTV Dongle mini " , NULL ) } ,
2013-06-04 16:10:34 -03:00
{ DVB_USB_DEVICE ( USB_VID_GTEK , USB_PID_CPYTO_REDI_PC50A ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Crypto ReDi PC 50 A " , NULL ) } ,
2014-02-26 15:33:39 -03:00
{ DVB_USB_DEVICE ( USB_VID_KYE , 0x707f ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Genius TVGo DVB-T03 " , NULL ) } ,
2014-05-04 18:43:39 -03:00
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , 0xd395 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Peak DVB-T USB " , NULL ) } ,
2014-05-04 07:37:15 -03:00
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_SVEON_STV20_RTL2832U ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Sveon STV20 " , NULL ) } ,
2014-06-12 03:22:45 -03:00
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_SVEON_STV21 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Sveon STV21 " , NULL ) } ,
2014-05-04 07:50:31 -03:00
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_SVEON_STV27 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Sveon STV27 " , NULL ) } ,
2015-02-14 11:11:34 -03:00
{ DVB_USB_DEVICE ( USB_VID_KWORLD_2 , USB_PID_TURBOX_DTT_2000 ,
& rtl28xxu_props , " TURBO-X Pure TV Tuner DTT-2000 " , NULL ) } ,
2013-10-30 02:33:42 -03:00
2014-02-26 15:33:40 -03:00
/* RTL2832P devices: */
2013-10-30 02:33:42 -03:00
{ DVB_USB_DEVICE ( USB_VID_HANFTEK , 0x0131 ,
2014-12-23 14:21:10 -03:00
& rtl28xxu_props , " Astrometa DVB-T2 " , NULL ) } ,
2015-05-05 13:54:19 -03:00
{ DVB_USB_DEVICE ( 0x5654 , 0xca42 ,
& rtl28xxu_props , " GoTView MasterHD 3 " , NULL ) } ,
2012-08-12 22:27:07 -03:00
{ }
} ;
MODULE_DEVICE_TABLE ( usb , rtl28xxu_id_table ) ;
static struct usb_driver rtl28xxu_usb_driver = {
. name = KBUILD_MODNAME ,
. id_table = rtl28xxu_id_table ,
. probe = dvb_usbv2_probe ,
. disconnect = dvb_usbv2_disconnect ,
. suspend = dvb_usbv2_suspend ,
. resume = dvb_usbv2_resume ,
2012-08-14 22:21:09 -03:00
. reset_resume = dvb_usbv2_reset_resume ,
2012-08-12 22:27:07 -03:00
. no_dynamic_id = 1 ,
. soft_unbind = 1 ,
2011-07-08 23:36:07 -03:00
} ;
2012-08-12 22:27:07 -03:00
module_usb_driver ( rtl28xxu_usb_driver ) ;
2011-07-08 23:36:07 -03:00
MODULE_DESCRIPTION ( " Realtek RTL28xxU DVB USB driver " ) ;
MODULE_AUTHOR ( " Antti Palosaari <crope@iki.fi> " ) ;
2012-05-18 14:47:41 -03:00
MODULE_AUTHOR ( " Thomas Mair <thomas.mair86@googlemail.com> " ) ;
2011-07-08 23:36:07 -03:00
MODULE_LICENSE ( " GPL " ) ;