2005-04-16 15:20:36 -07:00
/*
2005-11-08 21:37:48 -08:00
i2c tv tuner chip device driver
controls the philips tda8290 + 75 tuner chip combo .
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
2007-08-27 21:22:20 -03:00
This " tda8290 " module was split apart from the original " tuner " module .
2005-11-08 21:37:48 -08:00
*/
2005-04-16 15:20:36 -07:00
# include <linux/i2c.h>
# include <linux/delay.h>
2007-08-21 01:14:12 -03:00
# include <linux/videodev.h>
2007-12-09 02:26:48 -03:00
# include "tuner-i2c.h"
2007-08-27 21:22:20 -03:00
# include "tda8290.h"
2007-08-25 19:08:45 -03:00
# include "tda827x.h"
2007-10-22 09:56:38 -03:00
# include "tda18271.h"
2007-08-27 21:22:20 -03:00
2007-12-09 02:26:48 -03:00
static int debug ;
module_param ( debug , int , 0644 ) ;
2007-08-27 21:22:20 -03:00
MODULE_PARM_DESC ( debug , " enable verbose debug messages " ) ;
2007-11-04 11:03:36 -03:00
# define PREFIX "tda8290"
2005-04-16 15:20:36 -07:00
/* ---------------------------------------------------------------------- */
2007-05-29 22:54:06 -03:00
struct tda8290_priv {
2007-08-21 01:24:42 -03:00
struct tuner_i2c_props i2c_props ;
2007-05-29 22:54:06 -03:00
unsigned char tda8290_easy_mode ;
2007-08-25 19:08:45 -03:00
2007-05-29 22:54:06 -03:00
unsigned char tda827x_addr ;
2007-10-27 02:00:57 -03:00
unsigned char ver ;
# define TDA8290 1
# define TDA8295 2
# define TDA8275 4
# define TDA8275A 8
# define TDA18271 16
2005-04-16 15:20:36 -07:00
2007-08-25 19:08:45 -03:00
struct tda827x_config cfg ;
2005-04-16 15:20:36 -07:00
} ;
2005-11-08 21:37:48 -08:00
/*---------------------------------------------------------------------*/
2005-04-16 15:20:36 -07:00
2007-10-24 09:30:17 -03:00
static int tda8290_i2c_bridge ( struct dvb_frontend * fe , int close )
2005-11-08 21:37:48 -08:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2007-08-21 01:24:42 -03:00
2005-11-08 21:37:48 -08:00
unsigned char enable [ 2 ] = { 0x21 , 0xC0 } ;
2006-02-07 06:49:09 -02:00
unsigned char disable [ 2 ] = { 0x21 , 0x00 } ;
2005-11-08 21:37:48 -08:00
unsigned char * msg ;
2007-10-24 09:30:17 -03:00
if ( close ) {
2005-11-08 21:37:48 -08:00
msg = enable ;
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , msg , 2 ) ;
2005-11-08 21:37:48 -08:00
/* let the bridge stabilize */
msleep ( 20 ) ;
} else {
msg = disable ;
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , msg , 2 ) ;
2005-11-08 21:37:48 -08:00
}
2007-10-24 09:30:17 -03:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2007-10-24 09:30:17 -03:00
static int tda8295_i2c_bridge ( struct dvb_frontend * fe , int close )
2007-10-22 09:56:38 -03:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2007-10-22 09:56:38 -03:00
unsigned char enable [ 2 ] = { 0x45 , 0xc1 } ;
unsigned char disable [ 2 ] = { 0x46 , 0x00 } ;
unsigned char buf [ 3 ] = { 0x45 , 0x01 , 0x00 } ;
unsigned char * msg ;
2007-10-24 09:30:17 -03:00
2007-10-22 09:56:38 -03:00
if ( close ) {
msg = enable ;
tuner_i2c_xfer_send ( & priv - > i2c_props , msg , 2 ) ;
/* let the bridge stabilize */
msleep ( 20 ) ;
} else {
msg = disable ;
tuner_i2c_xfer_send ( & priv - > i2c_props , msg , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & msg [ 1 ] , 1 ) ;
buf [ 2 ] = msg [ 1 ] ;
buf [ 2 ] & = ~ 0x04 ;
tuner_i2c_xfer_send ( & priv - > i2c_props , buf , 3 ) ;
msleep ( 5 ) ;
msg [ 1 ] | = 0x04 ;
tuner_i2c_xfer_send ( & priv - > i2c_props , msg , 2 ) ;
}
2007-10-24 09:30:17 -03:00
return 0 ;
2007-10-22 09:56:38 -03:00
}
2005-11-08 21:37:48 -08:00
/*---------------------------------------------------------------------*/
2007-12-08 17:06:30 -03:00
static void set_audio ( struct dvb_frontend * fe ,
struct analog_parameters * params )
2005-04-16 15:20:36 -07:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2007-08-27 21:22:20 -03:00
char * mode ;
2007-12-08 17:06:30 -03:00
if ( params - > std & V4L2_STD_MN ) {
2007-08-27 21:22:20 -03:00
priv - > tda8290_easy_mode = 0x01 ;
mode = " MN " ;
2007-12-08 17:06:30 -03:00
} else if ( params - > std & V4L2_STD_B ) {
2007-08-27 21:22:20 -03:00
priv - > tda8290_easy_mode = 0x02 ;
mode = " B " ;
2007-12-08 17:06:30 -03:00
} else if ( params - > std & V4L2_STD_GH ) {
2007-08-27 21:22:20 -03:00
priv - > tda8290_easy_mode = 0x04 ;
mode = " GH " ;
2007-12-08 17:06:30 -03:00
} else if ( params - > std & V4L2_STD_PAL_I ) {
2007-08-27 21:22:20 -03:00
priv - > tda8290_easy_mode = 0x08 ;
mode = " I " ;
2007-12-08 17:06:30 -03:00
} else if ( params - > std & V4L2_STD_DK ) {
2007-08-27 21:22:20 -03:00
priv - > tda8290_easy_mode = 0x10 ;
mode = " DK " ;
2007-12-08 17:06:30 -03:00
} else if ( params - > std & V4L2_STD_SECAM_L ) {
2007-08-27 21:22:20 -03:00
priv - > tda8290_easy_mode = 0x20 ;
mode = " L " ;
2007-12-08 17:06:30 -03:00
} else if ( params - > std & V4L2_STD_SECAM_LC ) {
2007-08-27 21:22:20 -03:00
priv - > tda8290_easy_mode = 0x40 ;
mode = " LC " ;
} else {
priv - > tda8290_easy_mode = 0x10 ;
mode = " xx " ;
}
2007-10-27 02:00:57 -03:00
tuner_dbg ( " setting tda829x to system %s \n " , mode ) ;
2007-08-27 21:22:20 -03:00
}
2007-12-08 17:06:30 -03:00
static void tda8290_set_params ( struct dvb_frontend * fe ,
struct analog_parameters * params )
2007-08-27 21:22:20 -03:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2005-11-08 21:37:48 -08:00
unsigned char soft_reset [ ] = { 0x00 , 0x00 } ;
2007-05-29 22:54:06 -03:00
unsigned char easy_mode [ ] = { 0x01 , priv - > tda8290_easy_mode } ;
2005-11-08 21:37:48 -08:00
unsigned char expert_mode [ ] = { 0x01 , 0x80 } ;
2006-02-07 06:49:09 -02:00
unsigned char agc_out_on [ ] = { 0x02 , 0x00 } ;
2005-11-08 21:37:48 -08:00
unsigned char gainset_off [ ] = { 0x28 , 0x14 } ;
unsigned char if_agc_spd [ ] = { 0x0f , 0x88 } ;
unsigned char adc_head_6 [ ] = { 0x05 , 0x04 } ;
unsigned char adc_head_9 [ ] = { 0x05 , 0x02 } ;
unsigned char adc_head_12 [ ] = { 0x05 , 0x01 } ;
unsigned char pll_bw_nom [ ] = { 0x0d , 0x47 } ;
unsigned char pll_bw_low [ ] = { 0x0d , 0x27 } ;
unsigned char gainset_2 [ ] = { 0x28 , 0x64 } ;
unsigned char agc_rst_on [ ] = { 0x0e , 0x0b } ;
unsigned char agc_rst_off [ ] = { 0x0e , 0x09 } ;
unsigned char if_agc_set [ ] = { 0x0f , 0x81 } ;
unsigned char addr_adc_sat = 0x1a ;
unsigned char addr_agc_stat = 0x1d ;
unsigned char addr_pll_stat = 0x1b ;
unsigned char adc_sat , agc_stat ,
2005-11-08 21:37:50 -08:00
pll_stat ;
2007-04-27 12:31:12 -03:00
int i ;
2005-11-08 21:37:48 -08:00
2007-12-08 17:06:30 -03:00
set_audio ( fe , params ) ;
2007-08-27 21:22:20 -03:00
2007-12-09 02:26:48 -03:00
if ( priv - > cfg . config )
tuner_dbg ( " tda827xa config is 0x%02x \n " , * priv - > cfg . config ) ;
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , easy_mode , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , agc_out_on , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , soft_reset , 2 ) ;
2005-11-08 21:37:48 -08:00
msleep ( 1 ) ;
2007-05-29 22:54:06 -03:00
expert_mode [ 1 ] = priv - > tda8290_easy_mode + 0x80 ;
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , expert_mode , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , gainset_off , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , if_agc_spd , 2 ) ;
2007-05-29 22:54:06 -03:00
if ( priv - > tda8290_easy_mode & 0x60 )
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , adc_head_9 , 2 ) ;
2005-11-08 21:37:48 -08:00
else
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , adc_head_6 , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , pll_bw_nom , 2 ) ;
2005-11-08 21:37:48 -08:00
2007-10-21 19:39:50 -03:00
tda8290_i2c_bridge ( fe , 1 ) ;
2007-08-25 19:08:45 -03:00
2007-10-21 19:39:50 -03:00
if ( fe - > ops . tuner_ops . set_analog_params )
2007-12-08 17:06:30 -03:00
fe - > ops . tuner_ops . set_analog_params ( fe , params ) ;
2007-08-25 19:08:45 -03:00
2007-04-27 12:31:12 -03:00
for ( i = 0 ; i < 3 ; i + + ) {
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , & addr_pll_stat , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & pll_stat , 1 ) ;
2007-04-27 12:31:12 -03:00
if ( pll_stat & 0x80 ) {
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , & addr_adc_sat , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & adc_sat , 1 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , & addr_agc_stat , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & agc_stat , 1 ) ;
2007-04-27 12:31:12 -03:00
tuner_dbg ( " tda8290 is locked, AGC: %d \n " , agc_stat ) ;
break ;
} else {
tuner_dbg ( " tda8290 not locked, no signal? \n " ) ;
msleep ( 100 ) ;
}
}
2005-11-08 21:37:48 -08:00
/* adjust headroom resp. gain */
2005-11-08 21:38:38 -08:00
if ( ( agc_stat > 115 ) | | ( ! ( pll_stat & 0x80 ) & & ( adc_sat < 20 ) ) ) {
tuner_dbg ( " adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d \n " ,
agc_stat , adc_sat , pll_stat & 0x80 ) ;
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , gainset_2 , 2 ) ;
2005-11-08 21:37:48 -08:00
msleep ( 100 ) ;
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , & addr_agc_stat , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & agc_stat , 1 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , & addr_pll_stat , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & pll_stat , 1 ) ;
2005-11-08 21:37:48 -08:00
if ( ( agc_stat > 115 ) | | ! ( pll_stat & 0x80 ) ) {
2005-11-08 21:38:38 -08:00
tuner_dbg ( " adjust gain, step 2. Agc: %d, lock: %d \n " ,
agc_stat , pll_stat & 0x80 ) ;
2007-08-25 19:08:45 -03:00
if ( priv - > cfg . agcf )
2007-10-21 19:39:50 -03:00
priv - > cfg . agcf ( fe ) ;
2005-11-08 21:37:48 -08:00
msleep ( 100 ) ;
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , & addr_agc_stat , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & agc_stat , 1 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , & addr_pll_stat , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & pll_stat , 1 ) ;
2005-11-08 21:37:48 -08:00
if ( ( agc_stat > 115 ) | | ! ( pll_stat & 0x80 ) ) {
tuner_dbg ( " adjust gain, step 3. Agc: %d \n " , agc_stat ) ;
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , adc_head_12 , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , pll_bw_low , 2 ) ;
2005-11-08 21:37:48 -08:00
msleep ( 100 ) ;
}
}
}
2005-04-16 15:20:36 -07:00
2005-11-08 21:37:48 -08:00
/* l/ l' deadlock? */
2007-05-29 22:54:06 -03:00
if ( priv - > tda8290_easy_mode & 0x60 ) {
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , & addr_adc_sat , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & adc_sat , 1 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , & addr_pll_stat , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & pll_stat , 1 ) ;
2005-11-08 21:37:48 -08:00
if ( ( adc_sat > 20 ) | | ! ( pll_stat & 0x80 ) ) {
2005-11-08 21:38:38 -08:00
tuner_dbg ( " trying to resolve SECAM L deadlock \n " ) ;
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , agc_rst_on , 2 ) ;
2005-11-08 21:37:48 -08:00
msleep ( 40 ) ;
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , agc_rst_off , 2 ) ;
2005-11-08 21:37:48 -08:00
}
}
2005-06-28 20:45:21 -07:00
2007-10-21 19:39:50 -03:00
tda8290_i2c_bridge ( fe , 0 ) ;
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , if_agc_set , 2 ) ;
2005-04-16 15:20:36 -07:00
}
2005-11-08 21:37:48 -08:00
/*---------------------------------------------------------------------*/
2007-10-21 19:39:50 -03:00
static void tda8295_power ( struct dvb_frontend * fe , int enable )
2007-10-22 09:56:38 -03:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2007-10-22 09:56:38 -03:00
unsigned char buf [ ] = { 0x30 , 0x00 } ; /* clb_stdbt */
tuner_i2c_xfer_send ( & priv - > i2c_props , & buf [ 0 ] , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & buf [ 1 ] , 1 ) ;
if ( enable )
buf [ 1 ] = 0x01 ;
else
buf [ 1 ] = 0x03 ;
tuner_i2c_xfer_send ( & priv - > i2c_props , buf , 2 ) ;
}
2007-10-21 19:39:50 -03:00
static void tda8295_set_easy_mode ( struct dvb_frontend * fe , int enable )
2007-10-22 09:56:38 -03:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2007-10-22 09:56:38 -03:00
unsigned char buf [ ] = { 0x01 , 0x00 } ;
tuner_i2c_xfer_send ( & priv - > i2c_props , & buf [ 0 ] , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & buf [ 1 ] , 1 ) ;
if ( enable )
buf [ 1 ] = 0x01 ; /* rising edge sets regs 0x02 - 0x23 */
else
buf [ 1 ] = 0x00 ; /* reset active bit */
tuner_i2c_xfer_send ( & priv - > i2c_props , buf , 2 ) ;
}
2007-10-21 19:39:50 -03:00
static void tda8295_set_video_std ( struct dvb_frontend * fe )
2007-10-22 09:56:38 -03:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2007-10-22 09:56:38 -03:00
unsigned char buf [ ] = { 0x00 , priv - > tda8290_easy_mode } ;
tuner_i2c_xfer_send ( & priv - > i2c_props , buf , 2 ) ;
2007-10-21 19:39:50 -03:00
tda8295_set_easy_mode ( fe , 1 ) ;
2007-10-22 09:56:38 -03:00
msleep ( 20 ) ;
2007-10-21 19:39:50 -03:00
tda8295_set_easy_mode ( fe , 0 ) ;
2007-10-22 09:56:38 -03:00
}
/*---------------------------------------------------------------------*/
2007-10-21 19:39:50 -03:00
static void tda8295_agc1_out ( struct dvb_frontend * fe , int enable )
2007-10-22 09:56:38 -03:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2007-10-22 09:56:38 -03:00
unsigned char buf [ ] = { 0x02 , 0x00 } ; /* DIV_FUNC */
tuner_i2c_xfer_send ( & priv - > i2c_props , & buf [ 0 ] , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & buf [ 1 ] , 1 ) ;
if ( enable )
buf [ 1 ] & = ~ 0x40 ;
else
buf [ 1 ] | = 0x40 ;
tuner_i2c_xfer_send ( & priv - > i2c_props , buf , 2 ) ;
}
2007-10-21 19:39:50 -03:00
static void tda8295_agc2_out ( struct dvb_frontend * fe , int enable )
2007-10-22 09:56:38 -03:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2007-10-22 09:56:38 -03:00
unsigned char set_gpio_cf [ ] = { 0x44 , 0x00 } ;
unsigned char set_gpio_val [ ] = { 0x46 , 0x00 } ;
tuner_i2c_xfer_send ( & priv - > i2c_props , & set_gpio_cf [ 0 ] , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & set_gpio_cf [ 1 ] , 1 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , & set_gpio_val [ 0 ] , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & set_gpio_val [ 1 ] , 1 ) ;
set_gpio_cf [ 1 ] & = 0xf0 ; /* clear GPIO_0 bits 3-0 */
if ( enable ) {
set_gpio_cf [ 1 ] | = 0x01 ; /* config GPIO_0 as Open Drain Out */
set_gpio_val [ 1 ] & = 0xfe ; /* set GPIO_0 pin low */
}
tuner_i2c_xfer_send ( & priv - > i2c_props , set_gpio_cf , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , set_gpio_val , 2 ) ;
}
2007-10-21 19:39:50 -03:00
static int tda8295_has_signal ( struct dvb_frontend * fe )
2007-10-22 09:56:38 -03:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2007-10-22 09:56:38 -03:00
unsigned char hvpll_stat = 0x26 ;
unsigned char ret ;
tuner_i2c_xfer_send ( & priv - > i2c_props , & hvpll_stat , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & ret , 1 ) ;
return ( ret & 0x01 ) ? 65535 : 0 ;
}
/*---------------------------------------------------------------------*/
2007-12-08 17:06:30 -03:00
static void tda8295_set_params ( struct dvb_frontend * fe ,
struct analog_parameters * params )
2007-10-22 09:56:38 -03:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2007-10-22 09:56:38 -03:00
unsigned char blanking_mode [ ] = { 0x1d , 0x00 } ;
2007-12-08 17:06:30 -03:00
set_audio ( fe , params ) ;
2007-10-22 09:56:38 -03:00
2007-12-08 17:06:30 -03:00
tuner_dbg ( " %s: freq = %d \n " , __FUNCTION__ , params - > frequency ) ;
2007-10-22 09:56:38 -03:00
2007-10-21 19:39:50 -03:00
tda8295_power ( fe , 1 ) ;
tda8295_agc1_out ( fe , 1 ) ;
2007-10-22 09:56:38 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , & blanking_mode [ 0 ] , 1 ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & blanking_mode [ 1 ] , 1 ) ;
2007-10-21 19:39:50 -03:00
tda8295_set_video_std ( fe ) ;
2007-10-22 09:56:38 -03:00
blanking_mode [ 1 ] = 0x03 ;
tuner_i2c_xfer_send ( & priv - > i2c_props , blanking_mode , 2 ) ;
msleep ( 20 ) ;
2007-10-21 19:39:50 -03:00
tda8295_i2c_bridge ( fe , 1 ) ;
2007-10-22 09:56:38 -03:00
2007-10-21 19:39:50 -03:00
if ( fe - > ops . tuner_ops . set_analog_params )
2007-12-08 17:06:30 -03:00
fe - > ops . tuner_ops . set_analog_params ( fe , params ) ;
2007-10-22 09:56:38 -03:00
if ( priv - > cfg . agcf )
2007-10-21 19:39:50 -03:00
priv - > cfg . agcf ( fe ) ;
2007-10-22 09:56:38 -03:00
2007-10-21 19:39:50 -03:00
if ( tda8295_has_signal ( fe ) )
2007-10-22 09:56:38 -03:00
tuner_dbg ( " tda8295 is locked \n " ) ;
else
tuner_dbg ( " tda8295 not locked, no signal? \n " ) ;
2007-10-21 19:39:50 -03:00
tda8295_i2c_bridge ( fe , 0 ) ;
2007-10-22 09:56:38 -03:00
}
/*---------------------------------------------------------------------*/
2007-10-21 19:39:50 -03:00
static int tda8290_has_signal ( struct dvb_frontend * fe )
2005-04-16 15:20:36 -07:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2005-04-16 15:20:36 -07:00
2007-08-27 21:22:20 -03:00
unsigned char i2c_get_afc [ 1 ] = { 0x1B } ;
unsigned char afc = 0 ;
2005-04-16 15:20:36 -07:00
2007-08-27 21:22:20 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , i2c_get_afc , ARRAY_SIZE ( i2c_get_afc ) ) ;
tuner_i2c_xfer_recv ( & priv - > i2c_props , & afc , 1 ) ;
2007-08-25 19:08:45 -03:00
return ( afc & 0x80 ) ? 65535 : 0 ;
2005-04-16 15:20:36 -07:00
}
2005-11-08 21:37:48 -08:00
/*---------------------------------------------------------------------*/
2007-10-21 19:39:50 -03:00
static void tda8290_standby ( struct dvb_frontend * fe )
2005-09-09 13:03:37 -07:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2005-11-08 21:37:48 -08:00
unsigned char cb1 [ ] = { 0x30 , 0xD0 } ;
unsigned char tda8290_standby [ ] = { 0x00 , 0x02 } ;
2006-02-07 06:49:09 -02:00
unsigned char tda8290_agc_tri [ ] = { 0x02 , 0x20 } ;
2007-05-29 22:54:06 -03:00
struct i2c_msg msg = { . addr = priv - > tda827x_addr , . flags = 0 , . buf = cb1 , . len = 2 } ;
2005-11-08 21:37:48 -08:00
2007-10-21 19:39:50 -03:00
tda8290_i2c_bridge ( fe , 1 ) ;
2007-10-27 02:00:57 -03:00
if ( priv - > ver & TDA8275A )
2005-11-08 21:37:48 -08:00
cb1 [ 1 ] = 0x90 ;
2007-08-21 01:24:42 -03:00
i2c_transfer ( priv - > i2c_props . adap , & msg , 1 ) ;
2007-10-21 19:39:50 -03:00
tda8290_i2c_bridge ( fe , 0 ) ;
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , tda8290_agc_tri , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , tda8290_standby , 2 ) ;
2005-09-09 13:03:37 -07:00
}
2007-10-21 19:39:50 -03:00
static void tda8295_standby ( struct dvb_frontend * fe )
2007-10-22 09:56:38 -03:00
{
2007-10-21 19:39:50 -03:00
tda8295_agc1_out ( fe , 0 ) ; /* Put AGC in tri-state */
2007-10-22 09:56:38 -03:00
2007-10-21 19:39:50 -03:00
tda8295_power ( fe , 0 ) ;
2007-10-22 09:56:38 -03:00
}
2007-10-21 19:39:50 -03:00
static void tda8290_init_if ( struct dvb_frontend * fe )
2005-11-08 21:37:48 -08:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2007-08-21 01:24:42 -03:00
2005-11-08 21:37:48 -08:00
unsigned char set_VS [ ] = { 0x30 , 0x6F } ;
2007-04-27 12:31:12 -03:00
unsigned char set_GP00_CF [ ] = { 0x20 , 0x01 } ;
2005-11-08 21:37:48 -08:00
unsigned char set_GP01_CF [ ] = { 0x20 , 0x0B } ;
2007-12-09 02:26:48 -03:00
if ( ( priv - > cfg . config ) & &
( ( * priv - > cfg . config = = 1 ) | | ( * priv - > cfg . config = = 2 ) ) )
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , set_GP00_CF , 2 ) ;
2007-04-27 12:31:12 -03:00
else
2007-08-21 01:24:42 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , set_GP01_CF , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , set_VS , 2 ) ;
2005-11-08 21:37:48 -08:00
}
2007-10-21 19:39:50 -03:00
static void tda8295_init_if ( struct dvb_frontend * fe )
2007-10-22 09:56:38 -03:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2007-10-22 09:56:38 -03:00
static unsigned char set_adc_ctl [ ] = { 0x33 , 0x14 } ;
static unsigned char set_adc_ctl2 [ ] = { 0x34 , 0x00 } ;
static unsigned char set_pll_reg6 [ ] = { 0x3e , 0x63 } ;
static unsigned char set_pll_reg0 [ ] = { 0x38 , 0x23 } ;
static unsigned char set_pll_reg7 [ ] = { 0x3f , 0x01 } ;
static unsigned char set_pll_reg10 [ ] = { 0x42 , 0x61 } ;
static unsigned char set_gpio_reg0 [ ] = { 0x44 , 0x0b } ;
2007-10-21 19:39:50 -03:00
tda8295_power ( fe , 1 ) ;
2007-10-22 09:56:38 -03:00
2007-10-21 19:39:50 -03:00
tda8295_set_easy_mode ( fe , 0 ) ;
tda8295_set_video_std ( fe ) ;
2007-10-22 09:56:38 -03:00
tuner_i2c_xfer_send ( & priv - > i2c_props , set_adc_ctl , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , set_adc_ctl2 , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , set_pll_reg6 , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , set_pll_reg0 , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , set_pll_reg7 , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , set_pll_reg10 , 2 ) ;
tuner_i2c_xfer_send ( & priv - > i2c_props , set_gpio_reg0 , 2 ) ;
2007-10-21 19:39:50 -03:00
tda8295_agc1_out ( fe , 0 ) ;
tda8295_agc2_out ( fe , 0 ) ;
2007-10-22 09:56:38 -03:00
}
2007-10-21 19:39:50 -03:00
static void tda8290_init_tuner ( struct dvb_frontend * fe )
2005-04-16 15:20:36 -07:00
{
2007-10-21 19:39:50 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2005-11-08 21:37:48 -08:00
unsigned char tda8275_init [ ] = { 0x00 , 0x00 , 0x00 , 0x40 , 0xdC , 0x04 , 0xAf ,
2005-11-08 21:37:50 -08:00
0x3F , 0x2A , 0x04 , 0xFF , 0x00 , 0x00 , 0x40 } ;
2005-11-08 21:37:48 -08:00
unsigned char tda8275a_init [ ] = { 0x00 , 0x00 , 0x00 , 0x00 , 0xdC , 0x05 , 0x8b ,
2005-11-08 21:37:50 -08:00
0x0c , 0x04 , 0x20 , 0xFF , 0x00 , 0x00 , 0x4b } ;
2007-05-29 22:54:06 -03:00
struct i2c_msg msg = { . addr = priv - > tda827x_addr , . flags = 0 ,
2005-11-08 21:37:51 -08:00
. buf = tda8275_init , . len = 14 } ;
2007-10-27 02:00:57 -03:00
if ( priv - > ver & TDA8275A )
2005-11-08 21:37:48 -08:00
msg . buf = tda8275a_init ;
2007-10-21 19:39:50 -03:00
tda8290_i2c_bridge ( fe , 1 ) ;
2007-08-21 01:24:42 -03:00
i2c_transfer ( priv - > i2c_props . adap , & msg , 1 ) ;
2007-10-21 19:39:50 -03:00
tda8290_i2c_bridge ( fe , 0 ) ;
2005-11-08 21:37:48 -08:00
}
/*---------------------------------------------------------------------*/
2005-04-16 15:20:36 -07:00
2007-10-21 19:39:50 -03:00
static void tda829x_release ( struct dvb_frontend * fe )
2007-06-04 15:20:11 -03:00
{
2008-01-06 15:52:56 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2008-01-09 10:44:27 -03:00
/* only try to release the tuner if we've
* attached it from within this module */
if ( priv - > ver & ( TDA18271 | TDA8275 | TDA8275A ) )
2008-01-06 15:52:56 -03:00
if ( fe - > ops . tuner_ops . release )
fe - > ops . tuner_ops . release ( fe ) ;
2007-06-04 15:20:11 -03:00
2007-10-21 19:39:50 -03:00
kfree ( fe - > analog_demod_priv ) ;
fe - > analog_demod_priv = NULL ;
2007-08-27 21:22:20 -03:00
}
2008-01-02 03:01:54 -03:00
static struct tda18271_config tda829x_tda18271_config = {
. gate = TDA18271_GATE_ANALOG ,
} ;
2007-10-27 02:00:57 -03:00
static int tda829x_find_tuner ( struct dvb_frontend * fe )
2005-11-08 21:37:48 -08:00
{
2007-10-27 02:00:57 -03:00
struct tda8290_priv * priv = fe - > analog_demod_priv ;
2007-12-21 11:18:32 -03:00
struct analog_demod_ops * analog_ops = & fe - > ops . analog_ops ;
2005-11-08 21:37:48 -08:00
int i , ret , tuners_found ;
u32 tuner_addrs ;
2007-10-27 02:00:57 -03:00
u8 data ;
struct i2c_msg msg = { . flags = I2C_M_RD , . buf = & data , . len = 1 } ;
2005-11-08 21:37:48 -08:00
2007-12-21 11:18:32 -03:00
if ( NULL = = analog_ops - > i2c_gate_ctrl )
2007-10-27 02:00:57 -03:00
return - EINVAL ;
2007-08-25 19:08:45 -03:00
2007-12-21 11:18:32 -03:00
analog_ops - > i2c_gate_ctrl ( fe , 1 ) ;
2007-08-21 01:24:42 -03:00
2005-11-08 21:37:48 -08:00
/* probe for tuner chip */
tuners_found = 0 ;
tuner_addrs = 0 ;
2007-10-27 02:00:57 -03:00
for ( i = 0x60 ; i < = 0x63 ; i + + ) {
2005-11-08 21:37:48 -08:00
msg . addr = i ;
2007-08-21 01:24:42 -03:00
ret = i2c_transfer ( priv - > i2c_props . adap , & msg , 1 ) ;
2005-11-08 21:37:48 -08:00
if ( ret = = 1 ) {
tuners_found + + ;
tuner_addrs = ( tuner_addrs < < 8 ) + i ;
}
}
/* if there is more than one tuner, we expect the right one is
behind the bridge and we choose the highest address that doesn ' t
give a response now
*/
2007-10-27 02:00:57 -03:00
2007-12-21 11:18:32 -03:00
analog_ops - > i2c_gate_ctrl ( fe , 0 ) ;
2007-10-27 02:00:57 -03:00
if ( tuners_found > 1 )
2005-11-08 21:37:48 -08:00
for ( i = 0 ; i < tuners_found ; i + + ) {
msg . addr = tuner_addrs & 0xff ;
2007-08-21 01:24:42 -03:00
ret = i2c_transfer ( priv - > i2c_props . adap , & msg , 1 ) ;
2007-10-27 02:00:57 -03:00
if ( ret = = 1 )
2005-11-08 21:37:48 -08:00
tuner_addrs = tuner_addrs > > 8 ;
else
break ;
}
2007-10-27 02:00:57 -03:00
2005-11-08 21:37:48 -08:00
if ( tuner_addrs = = 0 ) {
2007-10-27 02:00:57 -03:00
tuner_addrs = 0x60 ;
tuner_info ( " could not clearly identify tuner address, "
" defaulting to %x \n " , tuner_addrs ) ;
2005-11-08 21:37:48 -08:00
} else {
tuner_addrs = tuner_addrs & 0xff ;
2007-08-27 21:22:20 -03:00
tuner_info ( " setting tuner address to %x \n " , tuner_addrs ) ;
2005-11-08 21:37:48 -08:00
}
2007-05-29 22:54:06 -03:00
priv - > tda827x_addr = tuner_addrs ;
2005-11-08 21:37:48 -08:00
msg . addr = tuner_addrs ;
2007-12-21 11:18:32 -03:00
analog_ops - > i2c_gate_ctrl ( fe , 1 ) ;
2007-08-21 01:24:42 -03:00
ret = i2c_transfer ( priv - > i2c_props . adap , & msg , 1 ) ;
2007-08-27 21:22:20 -03:00
2007-10-27 02:00:57 -03:00
if ( ret ! = 1 ) {
tuner_warn ( " tuner access failed! \n " ) ;
return - EREMOTEIO ;
2005-11-08 21:37:48 -08:00
}
2007-08-25 19:08:45 -03:00
2008-01-01 22:52:09 -03:00
if ( ( data = = 0x83 ) | | ( data = = 0x84 ) ) {
2007-10-27 02:00:57 -03:00
priv - > ver | = TDA18271 ;
2007-12-08 16:25:41 -03:00
tda18271_attach ( fe , priv - > tda827x_addr ,
2007-12-09 22:23:30 -03:00
priv - > i2c_props . adap ,
2008-01-02 03:01:54 -03:00
& tda829x_tda18271_config ) ;
2007-10-27 02:00:57 -03:00
} else {
if ( ( data & 0x3c ) = = 0 )
priv - > ver | = TDA8275 ;
else
priv - > ver | = TDA8275A ;
2007-06-06 16:15:15 -03:00
2007-12-08 16:25:41 -03:00
tda827x_attach ( fe , priv - > tda827x_addr ,
2007-10-27 02:00:57 -03:00
priv - > i2c_props . adap , & priv - > cfg ) ;
}
2007-12-08 16:25:41 -03:00
if ( fe - > ops . tuner_ops . init )
fe - > ops . tuner_ops . init ( fe ) ;
2007-11-23 15:08:11 -03:00
2007-12-08 16:25:41 -03:00
if ( fe - > ops . tuner_ops . sleep )
fe - > ops . tuner_ops . sleep ( fe ) ;
2007-11-23 15:08:11 -03:00
2007-12-21 11:18:32 -03:00
analog_ops - > i2c_gate_ctrl ( fe , 0 ) ;
2007-08-25 19:08:45 -03:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2007-10-22 09:56:38 -03:00
2007-11-03 22:14:54 -03:00
static int tda8290_probe ( struct tuner_i2c_props * i2c_props )
{
# define TDA8290_ID 0x89
unsigned char tda8290_id [ ] = { 0x1f , 0x00 } ;
/* detect tda8290 */
tuner_i2c_xfer_send ( i2c_props , & tda8290_id [ 0 ] , 1 ) ;
tuner_i2c_xfer_recv ( i2c_props , & tda8290_id [ 1 ] , 1 ) ;
if ( tda8290_id [ 1 ] = = TDA8290_ID ) {
2007-12-09 02:26:48 -03:00
if ( debug )
2007-11-03 22:14:54 -03:00
printk ( KERN_DEBUG " %s: tda8290 detected @ %d-%04x \n " ,
__FUNCTION__ , i2c_adapter_id ( i2c_props - > adap ) ,
i2c_props - > addr ) ;
return 0 ;
}
2007-11-04 10:51:28 -03:00
return - ENODEV ;
2007-11-03 22:14:54 -03:00
}
static int tda8295_probe ( struct tuner_i2c_props * i2c_props )
{
# define TDA8295_ID 0x8a
unsigned char tda8295_id [ ] = { 0x2f , 0x00 } ;
/* detect tda8295 */
tuner_i2c_xfer_send ( i2c_props , & tda8295_id [ 0 ] , 1 ) ;
tuner_i2c_xfer_recv ( i2c_props , & tda8295_id [ 1 ] , 1 ) ;
if ( tda8295_id [ 1 ] = = TDA8295_ID ) {
2007-12-09 02:26:48 -03:00
if ( debug )
2007-11-03 22:14:54 -03:00
printk ( KERN_DEBUG " %s: tda8295 detected @ %d-%04x \n " ,
__FUNCTION__ , i2c_adapter_id ( i2c_props - > adap ) ,
i2c_props - > addr ) ;
return 0 ;
}
2007-11-04 10:51:28 -03:00
return - ENODEV ;
2007-11-03 22:14:54 -03:00
}
2007-12-21 11:18:32 -03:00
static struct analog_demod_ops tda8290_ops = {
2007-12-09 13:52:51 -03:00
. info = {
. name = " TDA8290 " ,
} ,
2007-12-08 17:06:30 -03:00
. set_params = tda8290_set_params ,
2007-10-27 02:00:57 -03:00
. has_signal = tda8290_has_signal ,
. standby = tda8290_standby ,
. release = tda829x_release ,
. i2c_gate_ctrl = tda8290_i2c_bridge ,
} ;
2007-12-21 11:18:32 -03:00
static struct analog_demod_ops tda8295_ops = {
2007-12-09 13:52:51 -03:00
. info = {
. name = " TDA8295 " ,
} ,
2007-12-08 17:06:30 -03:00
. set_params = tda8295_set_params ,
2007-10-27 02:00:57 -03:00
. has_signal = tda8295_has_signal ,
. standby = tda8295_standby ,
. release = tda829x_release ,
. i2c_gate_ctrl = tda8295_i2c_bridge ,
} ;
2007-12-09 02:26:48 -03:00
struct dvb_frontend * tda829x_attach ( struct dvb_frontend * fe ,
struct i2c_adapter * i2c_adap , u8 i2c_addr ,
struct tda829x_config * cfg )
2007-10-22 09:56:38 -03:00
{
struct tda8290_priv * priv = NULL ;
2007-12-09 02:26:48 -03:00
char * name ;
2007-10-27 02:00:57 -03:00
2007-10-22 09:56:38 -03:00
priv = kzalloc ( sizeof ( struct tda8290_priv ) , GFP_KERNEL ) ;
if ( priv = = NULL )
2007-12-09 02:26:48 -03:00
return NULL ;
2007-10-27 02:00:57 -03:00
fe - > analog_demod_priv = priv ;
2007-10-22 09:56:38 -03:00
2007-12-09 02:26:48 -03:00
priv - > i2c_props . addr = i2c_addr ;
priv - > i2c_props . adap = i2c_adap ;
if ( cfg ) {
priv - > cfg . config = cfg - > lna_cfg ;
priv - > cfg . tuner_callback = cfg - > tuner_callback ;
}
2007-10-22 09:56:38 -03:00
2007-11-03 22:14:54 -03:00
if ( tda8290_probe ( & priv - > i2c_props ) = = 0 ) {
2007-10-27 02:00:57 -03:00
priv - > ver = TDA8290 ;
2007-12-21 11:18:32 -03:00
memcpy ( & fe - > ops . analog_ops , & tda8290_ops ,
sizeof ( struct analog_demod_ops ) ) ;
2007-10-22 09:56:38 -03:00
}
2007-10-27 02:00:57 -03:00
2007-11-03 22:14:54 -03:00
if ( tda8295_probe ( & priv - > i2c_props ) = = 0 ) {
2007-10-27 02:00:57 -03:00
priv - > ver = TDA8295 ;
2007-12-21 11:18:32 -03:00
memcpy ( & fe - > ops . analog_ops , & tda8295_ops ,
sizeof ( struct analog_demod_ops ) ) ;
2007-10-22 09:56:38 -03:00
}
2007-12-24 04:36:14 -03:00
if ( ( ! ( cfg ) | | ( TDA829X_PROBE_TUNER = = cfg - > probe_tuner ) ) & &
( tda829x_find_tuner ( fe ) < 0 ) )
2007-12-09 05:16:10 -03:00
goto fail ;
2007-10-22 09:56:38 -03:00
2007-12-09 02:26:48 -03:00
switch ( priv - > ver ) {
2007-12-24 04:36:14 -03:00
case TDA8290 :
name = " tda8290 " ;
break ;
case TDA8295 :
name = " tda8295 " ;
break ;
2007-12-09 02:26:48 -03:00
case TDA8290 | TDA8275 :
name = " tda8290+75 " ;
break ;
case TDA8295 | TDA8275 :
name = " tda8295+75 " ;
break ;
case TDA8290 | TDA8275A :
name = " tda8290+75a " ;
break ;
case TDA8295 | TDA8275A :
name = " tda8295+75a " ;
break ;
case TDA8290 | TDA18271 :
name = " tda8290+18271 " ;
break ;
case TDA8295 | TDA18271 :
name = " tda8295+18271 " ;
break ;
default :
goto fail ;
}
tuner_info ( " type set to %s \n " , name ) ;
2007-10-27 02:00:57 -03:00
if ( priv - > ver & TDA8290 ) {
tda8290_init_tuner ( fe ) ;
tda8290_init_if ( fe ) ;
} else if ( priv - > ver & TDA8295 )
tda8295_init_if ( fe ) ;
2007-10-22 09:56:38 -03:00
2007-12-09 02:26:48 -03:00
return fe ;
2007-12-09 05:16:10 -03:00
fail :
tda829x_release ( fe ) ;
2007-12-09 02:26:48 -03:00
return NULL ;
2007-10-22 09:56:38 -03:00
}
2007-10-27 02:00:57 -03:00
EXPORT_SYMBOL_GPL ( tda829x_attach ) ;
2005-04-16 15:20:36 -07:00
2007-12-09 02:26:48 -03:00
int tda829x_probe ( struct i2c_adapter * i2c_adap , u8 i2c_addr )
2005-11-08 21:38:00 -08:00
{
2007-08-27 21:22:20 -03:00
struct tuner_i2c_props i2c_props = {
2007-12-09 02:26:48 -03:00
. adap = i2c_adap ,
. addr = i2c_addr ,
2007-08-27 21:22:20 -03:00
} ;
2007-08-21 01:24:42 -03:00
2006-02-27 00:09:11 -03:00
unsigned char soft_reset [ ] = { 0x00 , 0x00 } ;
unsigned char easy_mode_b [ ] = { 0x01 , 0x02 } ;
unsigned char easy_mode_g [ ] = { 0x01 , 0x04 } ;
unsigned char restore_9886 [ ] = { 0x00 , 0xd6 , 0x30 } ;
2005-11-08 21:38:00 -08:00
unsigned char addr_dto_lsb = 0x07 ;
unsigned char data ;
2007-11-04 11:03:22 -03:00
# define PROBE_BUFFER_SIZE 8
unsigned char buf [ PROBE_BUFFER_SIZE ] ;
int i ;
/* rule out tda9887, which would return the same byte repeatedly */
tuner_i2c_xfer_send ( & i2c_props , soft_reset , 1 ) ;
tuner_i2c_xfer_recv ( & i2c_props , buf , PROBE_BUFFER_SIZE ) ;
for ( i = 1 ; i < PROBE_BUFFER_SIZE ; i + + ) {
2007-11-05 09:54:42 -03:00
if ( buf [ i ] ! = buf [ 0 ] )
break ;
2007-11-04 11:03:22 -03:00
}
/* all bytes are equal, not a tda829x - probably a tda9887 */
if ( i = = PROBE_BUFFER_SIZE )
return - ENODEV ;
2005-11-08 21:38:00 -08:00
2007-11-03 22:14:54 -03:00
if ( ( tda8290_probe ( & i2c_props ) = = 0 ) | |
( tda8295_probe ( & i2c_props ) = = 0 ) )
return 0 ;
/* fall back to old probing method */
2007-08-27 21:22:20 -03:00
tuner_i2c_xfer_send ( & i2c_props , easy_mode_b , 2 ) ;
tuner_i2c_xfer_send ( & i2c_props , soft_reset , 2 ) ;
tuner_i2c_xfer_send ( & i2c_props , & addr_dto_lsb , 1 ) ;
tuner_i2c_xfer_recv ( & i2c_props , & data , 1 ) ;
2005-11-08 21:38:00 -08:00
if ( data = = 0 ) {
2007-08-27 21:22:20 -03:00
tuner_i2c_xfer_send ( & i2c_props , easy_mode_g , 2 ) ;
tuner_i2c_xfer_send ( & i2c_props , soft_reset , 2 ) ;
tuner_i2c_xfer_send ( & i2c_props , & addr_dto_lsb , 1 ) ;
tuner_i2c_xfer_recv ( & i2c_props , & data , 1 ) ;
2005-11-08 21:38:00 -08:00
if ( data = = 0x7b ) {
return 0 ;
}
}
2007-08-27 21:22:20 -03:00
tuner_i2c_xfer_send ( & i2c_props , restore_9886 , 3 ) ;
2007-11-04 10:51:28 -03:00
return - ENODEV ;
2005-11-08 21:38:00 -08:00
}
2007-11-03 22:14:54 -03:00
EXPORT_SYMBOL_GPL ( tda829x_probe ) ;
2007-08-27 21:22:20 -03:00
2007-10-27 02:00:57 -03:00
MODULE_DESCRIPTION ( " Philips/NXP TDA8290/TDA8295 analog IF demodulator driver " ) ;
2007-10-22 09:56:38 -03:00
MODULE_AUTHOR ( " Gerd Knorr, Hartmut Hackmann, Michael Krufky " ) ;
2007-08-27 21:22:20 -03:00
MODULE_LICENSE ( " GPL " ) ;
2005-04-16 15:20:36 -07:00
/*
* Overrides for Emacs so that we follow Linus ' s tabbing style .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Local variables :
* c - basic - offset : 8
* End :
*/