2019-05-20 10:19:02 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2009-12-04 10:42:22 +03:00
/*
Mantis VP - 2040 driver
Copyright ( C ) Manu Abraham ( abraham . manu @ gmail . com )
*/
2009-12-04 11:41:11 +03:00
# include <linux/signal.h>
# include <linux/sched.h>
# include <linux/interrupt.h>
2017-12-28 21:03:51 +03:00
# include <media/dmxdev.h>
# include <media/dvbdev.h>
# include <media/dvb_demux.h>
# include <media/dvb_frontend.h>
# include <media/dvb_net.h>
2009-12-04 11:41:11 +03:00
# include "tda1002x.h"
2009-12-04 10:42:22 +03:00
# include "mantis_common.h"
2009-12-04 11:57:28 +03:00
# include "mantis_ioc.h"
# include "mantis_dvb.h"
2009-12-04 10:42:22 +03:00
# include "mantis_vp2040.h"
# define MANTIS_MODEL_NAME "VP-2040"
# define MANTIS_DEV_TYPE "DVB-C"
2014-08-21 01:26:40 +04:00
static struct tda1002x_config vp2040_tda1002x_cu1216_config = {
2009-12-04 11:41:11 +03:00
. demod_address = 0x18 > > 1 ,
. invert = 1 ,
} ;
2014-08-21 01:26:40 +04:00
static struct tda10023_config vp2040_tda10023_cu1216_config = {
2009-12-04 11:41:11 +03:00
. demod_address = 0x18 > > 1 ,
. invert = 1 ,
} ;
2011-12-24 19:24:33 +04:00
static int tda1002x_cu1216_tuner_set ( struct dvb_frontend * fe )
2009-12-04 11:41:11 +03:00
{
2011-12-23 14:18:04 +04:00
struct dtv_frontend_properties * p = & fe - > dtv_property_cache ;
2009-12-04 11:41:11 +03:00
struct mantis_pci * mantis = fe - > dvb - > priv ;
struct i2c_adapter * adapter = & mantis - > adapter ;
u8 buf [ 6 ] ;
2009-12-15 14:47:21 +03:00
struct i2c_msg msg = { . addr = 0x60 , . flags = 0 , . buf = buf , . len = sizeof ( buf ) } ;
2009-12-04 11:41:11 +03:00
int i ;
# define CU1216_IF 36125000
# define TUNER_MUL 62500
2011-12-23 14:18:04 +04:00
u32 div = ( p - > frequency + CU1216_IF + TUNER_MUL / 2 ) / TUNER_MUL ;
2009-12-04 11:41:11 +03:00
buf [ 0 ] = ( div > > 8 ) & 0x7f ;
buf [ 1 ] = div & 0xff ;
buf [ 2 ] = 0xce ;
2011-12-23 14:18:04 +04:00
buf [ 3 ] = ( p - > frequency < 150000000 ? 0x01 :
p - > frequency < 445000000 ? 0x02 : 0x04 ) ;
2009-12-04 11:41:11 +03:00
buf [ 4 ] = 0xde ;
buf [ 5 ] = 0x20 ;
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 1 ) ;
if ( i2c_transfer ( adapter , & msg , 1 ) ! = 1 )
return - EIO ;
/* wait for the pll lock */
msg . flags = I2C_M_RD ;
msg . len = 1 ;
for ( i = 0 ; i < 20 ; i + + ) {
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 1 ) ;
if ( i2c_transfer ( adapter , & msg , 1 ) = = 1 & & ( buf [ 0 ] & 0x40 ) )
break ;
msleep ( 10 ) ;
}
/* switch the charge pump to the lower current */
msg . flags = 0 ;
msg . len = 2 ;
msg . buf = & buf [ 2 ] ;
buf [ 2 ] & = ~ 0x40 ;
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 1 ) ;
if ( i2c_transfer ( adapter , & msg , 1 ) ! = 1 )
return - EIO ;
return 0 ;
}
static u8 read_pwm ( struct mantis_pci * mantis )
{
struct i2c_adapter * adapter = & mantis - > adapter ;
u8 b = 0xff ;
u8 pwm ;
struct i2c_msg msg [ ] = {
{ . addr = 0x50 , . flags = 0 , . buf = & b , . len = 1 } ,
{ . addr = 0x50 , . flags = I2C_M_RD , . buf = & pwm , . len = 1 }
} ;
if ( ( i2c_transfer ( adapter , msg , 2 ) ! = 2 )
| | ( pwm = = 0xff ) )
pwm = 0x48 ;
return pwm ;
}
static int vp2040_frontend_init ( struct mantis_pci * mantis , struct dvb_frontend * fe )
{
struct i2c_adapter * adapter = & mantis - > adapter ;
2009-12-04 11:57:28 +03:00
int err = 0 ;
2009-12-04 11:41:11 +03:00
2009-12-04 11:57:28 +03:00
err = mantis_frontend_power ( mantis , POWER_ON ) ;
if ( err = = 0 ) {
mantis_frontend_soft_reset ( mantis ) ;
msleep ( 250 ) ;
dprintk ( MANTIS_ERROR , 1 , " Probing for CU1216 (DVB-C) " ) ;
2010-11-14 20:24:36 +03:00
fe = dvb_attach ( tda10021_attach , & vp2040_tda1002x_cu1216_config ,
2009-12-04 11:41:11 +03:00
adapter ,
read_pwm ( mantis ) ) ;
if ( fe ) {
dprintk ( MANTIS_ERROR , 1 ,
2009-12-04 11:57:28 +03:00
" found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x " ,
2009-12-04 11:41:11 +03:00
vp2040_tda1002x_cu1216_config . demod_address ) ;
2009-12-04 11:57:28 +03:00
} else {
2010-11-14 20:24:36 +03:00
fe = dvb_attach ( tda10023_attach , & vp2040_tda10023_cu1216_config ,
2009-12-04 11:57:28 +03:00
adapter ,
read_pwm ( mantis ) ) ;
if ( fe ) {
dprintk ( MANTIS_ERROR , 1 ,
" found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x " ,
vp2040_tda1002x_cu1216_config . demod_address ) ;
}
2009-12-04 11:41:11 +03:00
}
2009-12-04 11:57:28 +03:00
if ( fe ) {
fe - > ops . tuner_ops . set_params = tda1002x_cu1216_tuner_set ;
dprintk ( MANTIS_ERROR , 1 , " Mantis DVB-C Philips CU1216 frontend attach success " ) ;
} else {
return - 1 ;
}
2009-12-04 11:41:11 +03:00
} else {
2009-12-04 11:57:28 +03:00
dprintk ( MANTIS_ERROR , 1 , " Frontend on <%s> POWER ON failed! <%d> " ,
adapter - > name ,
err ) ;
2009-12-04 11:41:11 +03:00
2009-12-04 11:57:28 +03:00
return - EIO ;
}
2009-12-04 11:41:11 +03:00
mantis - > fe = fe ;
dprintk ( MANTIS_DEBUG , 1 , " Done! " ) ;
return 0 ;
}
struct mantis_hwconfig vp2040_config = {
2009-12-04 10:42:22 +03:00
. model_name = MANTIS_MODEL_NAME ,
. dev_type = MANTIS_DEV_TYPE ,
. ts_size = MANTIS_TS_204 ,
2009-12-04 11:41:11 +03:00
2009-12-04 11:39:57 +03:00
. baud_rate = MANTIS_BAUD_9600 ,
. parity = MANTIS_PARITY_NONE ,
. bytes = 0 ,
2009-12-04 10:42:22 +03:00
2009-12-04 11:41:11 +03:00
. frontend_init = vp2040_frontend_init ,
2009-12-04 11:57:28 +03:00
. power = GPIF_A12 ,
. reset = GPIF_A13 ,
2009-12-04 10:42:22 +03:00
} ;