2005-04-17 02:20:36 +04:00
/*
*
* i2c tv tuner chip device driver
* controls all those simple 4 - control - bytes style tuners .
*/
# include <linux/delay.h>
# include <linux/i2c.h>
# include <linux/videodev.h>
# include <media/tuner.h>
2006-06-25 22:34:39 +04:00
# include <media/v4l2-common.h>
2005-04-17 02:20:36 +04:00
2006-01-09 20:25:11 +03:00
static int offset = 0 ;
2006-08-13 04:59:19 +04:00
module_param ( offset , int , 0664 ) ;
2006-01-09 20:25:11 +03:00
MODULE_PARM_DESC ( offset , " Allows to specify an offset for tuner " ) ;
2005-04-17 02:20:36 +04:00
/* ---------------------------------------------------------------------- */
/* tv standard selection for Temic 4046 FM5
this value takes the low bits of control byte 2
from datasheet Rev .01 , Feb .00
standard BG I L L2 D
picture IF 38.9 38.9 38.9 33.95 38.9
sound 1 33.4 32.9 32.4 40.45 32.4
sound 2 33.16
NICAM 33.05 32.348 33.05 33.05
*/
# define TEMIC_SET_PAL_I 0x05
# define TEMIC_SET_PAL_DK 0x09
# define TEMIC_SET_PAL_L 0x0a // SECAM ?
# define TEMIC_SET_PAL_L2 0x0b // change IF !
# define TEMIC_SET_PAL_BG 0x0c
/* tv tuner system standard selection for Philips FQ1216ME
this value takes the low bits of control byte 2
from datasheet " 1999 Nov 16 " ( supersedes " 1999 Mar 23 " )
standard BG DK I L L `
picture carrier 38.90 38.90 38.90 38.90 33.95
colour 34.47 34.47 34.47 34.47 38.38
sound 1 33.40 32.40 32.90 32.40 40.45
sound 2 33.16 - - - -
NICAM 33.05 33.05 32.35 33.05 39.80
*/
# define PHILIPS_SET_PAL_I 0x01 /* Bit 2 always zero !*/
# define PHILIPS_SET_PAL_BGDK 0x09
# define PHILIPS_SET_PAL_L2 0x0a
# define PHILIPS_SET_PAL_L 0x0b
/* system switching for Philips FI1216MF MK2
from datasheet " 1996 Jul 09 " ,
standard BG L L '
picture carrier 38.90 38.90 33.95
colour 34.47 34.37 38.38
sound 1 33.40 32.40 40.45
sound 2 33.16 - -
NICAM 33.05 33.05 39.80
*/
# define PHILIPS_MF_SET_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */
# define PHILIPS_MF_SET_PAL_L 0x03 // France
# define PHILIPS_MF_SET_PAL_L2 0x02 // L'
2005-07-13 00:58:55 +04:00
/* Control byte */
# define TUNER_RATIO_MASK 0x06 /* Bit cb1:cb2 */
# define TUNER_RATIO_SELECT_50 0x00
# define TUNER_RATIO_SELECT_32 0x02
# define TUNER_RATIO_SELECT_166 0x04
# define TUNER_RATIO_SELECT_62 0x06
# define TUNER_CHARGE_PUMP 0x40 /* Bit cb6 */
/* Status byte */
# define TUNER_POR 0x80
# define TUNER_FL 0x40
# define TUNER_MODE 0x38
# define TUNER_AFC 0x07
# define TUNER_SIGNAL 0x07
# define TUNER_STEREO 0x10
# define TUNER_PLL_LOCKED 0x40
# define TUNER_STEREO_MK3 0x04
2005-04-17 02:20:36 +04:00
/* ---------------------------------------------------------------------- */
static int tuner_getstatus ( struct i2c_client * c )
{
unsigned char byte ;
if ( 1 ! = i2c_master_recv ( c , & byte , 1 ) )
return 0 ;
2005-06-24 09:05:07 +04:00
2005-04-17 02:20:36 +04:00
return byte ;
}
static int tuner_signal ( struct i2c_client * c )
{
2005-06-24 09:05:07 +04:00
return ( tuner_getstatus ( c ) & TUNER_SIGNAL ) < < 13 ;
2005-04-17 02:20:36 +04:00
}
static int tuner_stereo ( struct i2c_client * c )
{
2005-06-24 09:05:07 +04:00
int stereo , status ;
struct tuner * t = i2c_get_clientdata ( c ) ;
status = tuner_getstatus ( c ) ;
switch ( t - > type ) {
2005-11-09 08:37:43 +03:00
case TUNER_PHILIPS_FM1216ME_MK3 :
2006-06-20 07:30:57 +04:00
case TUNER_PHILIPS_FM1236_MK3 :
2005-06-24 09:05:07 +04:00
case TUNER_PHILIPS_FM1256_IH3 :
2006-12-03 12:45:07 +03:00
case TUNER_LG_NTSC_TAPE :
2005-06-24 09:05:07 +04:00
stereo = ( ( status & TUNER_SIGNAL ) = = TUNER_STEREO_MK3 ) ;
break ;
default :
stereo = status & TUNER_STEREO ;
}
return stereo ;
2005-04-17 02:20:36 +04:00
}
/* ---------------------------------------------------------------------- */
static void default_set_tv_freq ( struct i2c_client * c , unsigned int freq )
{
struct tuner * t = i2c_get_clientdata ( c ) ;
2006-01-23 22:11:11 +03:00
u8 config , cb , tuneraddr ;
2005-04-17 02:20:36 +04:00
u16 div ;
struct tunertype * tun ;
2006-01-15 20:04:52 +03:00
u8 buffer [ 4 ] ;
V4L/DVB (3359): Redesign tuners struct for maximum flexibility
- Tunertype struct redefined to allow one or more tuner_params structs
per tuner definition, one for each video standard.
- Each tuner_params struct has an element containing an arbitrary
amount of tuner_ranges.
(this is needed for dvb tuners - to be handled later)
- A tuner_range may be referenced by multiple tuner_params structs.
There are many duplicates in here. Reusing tuner_range structs,
rather than defining new ones for each tuner, will cut down on
memory usage, and is preferred when possible.
- tunertype struct contains an element, has_tda988x.
We must set this for all tunertypes that contain a tda988x
chip, and then we can remove this setting from the various
card structs.
- Improves tuners array memory usage efficiency.
- Right now, all tuners are using the first tuner_params[] array element
for analog mode. In the future, we will be merging similar tuner
definitions together, such that each tuner definition will have a
tuner_params struct for each available video standard. At that point,
the tuner_params[] array element will be chosen based on the video
standard in use.
Signed-off-by: Michael Krufky <mkrufky@m1k.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
2006-01-13 19:10:25 +03:00
int rc , IFPCoff , i , j ;
2006-02-07 11:25:34 +03:00
enum param_type desired_type ;
2006-06-25 22:34:39 +04:00
struct tuner_params * params ;
2005-04-17 02:20:36 +04:00
tun = & tuners [ t - > type ] ;
V4L/DVB (3359): Redesign tuners struct for maximum flexibility
- Tunertype struct redefined to allow one or more tuner_params structs
per tuner definition, one for each video standard.
- Each tuner_params struct has an element containing an arbitrary
amount of tuner_ranges.
(this is needed for dvb tuners - to be handled later)
- A tuner_range may be referenced by multiple tuner_params structs.
There are many duplicates in here. Reusing tuner_range structs,
rather than defining new ones for each tuner, will cut down on
memory usage, and is preferred when possible.
- tunertype struct contains an element, has_tda988x.
We must set this for all tunertypes that contain a tda988x
chip, and then we can remove this setting from the various
card structs.
- Improves tuners array memory usage efficiency.
- Right now, all tuners are using the first tuner_params[] array element
for analog mode. In the future, we will be merging similar tuner
definitions together, such that each tuner definition will have a
tuner_params struct for each available video standard. At that point,
the tuner_params[] array element will be chosen based on the video
standard in use.
Signed-off-by: Michael Krufky <mkrufky@m1k.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
2006-01-13 19:10:25 +03:00
2006-02-07 11:25:33 +03:00
/* IFPCoff = Video Intermediate Frequency - Vif:
940 = 16 * 58.75 NTSC / J ( Japan )
732 = 16 * 45.75 M / N STD
704 = 16 * 44 ATSC ( at DVB code )
632 = 16 * 39.50 I U . K .
622.4 = 16 * 38.90 B / G D / K I , L STD
592 = 16 * 37.00 D China
590 = 16.36 .875 B Australia
543.2 = 16 * 33.95 L ' STD
171.2 = 16 * 10.70 FM Radio ( at set_radio_freq )
*/
if ( t - > std = = V4L2_STD_NTSC_M_JP ) {
2006-02-07 11:25:34 +03:00
IFPCoff = 940 ;
desired_type = TUNER_PARAM_TYPE_NTSC ;
2006-02-07 11:25:33 +03:00
} else if ( ( t - > std & V4L2_STD_MN ) & &
! ( t - > std & ~ V4L2_STD_MN ) ) {
2006-02-07 11:25:34 +03:00
IFPCoff = 732 ;
desired_type = TUNER_PARAM_TYPE_NTSC ;
2006-02-07 11:25:33 +03:00
} else if ( t - > std = = V4L2_STD_SECAM_LC ) {
2006-02-07 11:25:34 +03:00
IFPCoff = 543 ;
desired_type = TUNER_PARAM_TYPE_SECAM ;
2006-02-07 11:25:33 +03:00
} else {
2006-02-07 11:25:34 +03:00
IFPCoff = 623 ;
desired_type = TUNER_PARAM_TYPE_PAL ;
2006-02-07 11:25:33 +03:00
}
2006-02-07 11:25:34 +03:00
for ( j = 0 ; j < tun - > count - 1 ; j + + ) {
if ( desired_type ! = tun - > params [ j ] . type )
continue ;
break ;
}
2006-02-07 11:25:39 +03:00
/* use default tuner_params if desired_type not available */
2006-02-07 11:25:40 +03:00
if ( desired_type ! = tun - > params [ j ] . type ) {
tuner_dbg ( " IFPCoff = %d: tuner_params undefined for tuner %d \n " ,
IFPCoff , t - > type ) ;
2006-02-07 11:25:39 +03:00
j = 0 ;
2006-02-07 11:25:40 +03:00
}
2006-06-25 22:34:39 +04:00
params = & tun - > params [ j ] ;
2006-02-07 11:25:39 +03:00
2006-06-25 22:34:39 +04:00
for ( i = 0 ; i < params - > count ; i + + ) {
if ( freq > params - > ranges [ i ] . limit )
2006-01-09 20:25:38 +03:00
continue ;
break ;
2005-04-17 02:20:36 +04:00
}
2006-06-25 22:34:39 +04:00
if ( i = = params - > count ) {
2006-01-15 20:04:52 +03:00
tuner_dbg ( " TV frequency out of range (%d > %d) " ,
2006-06-25 22:34:39 +04:00
freq , params - > ranges [ i - 1 ] . limit ) ;
freq = params - > ranges [ - - i ] . limit ;
2006-01-15 20:04:52 +03:00
}
2006-06-25 22:34:39 +04:00
config = params - > ranges [ i ] . config ;
cb = params - > ranges [ i ] . cb ;
2006-02-07 11:25:33 +03:00
/* i == 0 -> VHF_LO
* i = = 1 - > VHF_HI
* i = = 2 - > UHF */
2006-02-07 11:25:35 +03:00
tuner_dbg ( " tv: param %d, range %d \n " , j , i ) ;
2005-04-17 02:20:36 +04:00
2006-02-07 11:25:33 +03:00
div = freq + IFPCoff + offset ;
tuner_dbg ( " Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d \n " ,
freq / 16 , freq % 16 * 100 / 16 ,
IFPCoff / 16 , IFPCoff % 16 * 100 / 16 ,
offset / 16 , offset % 16 * 100 / 16 ,
div ) ;
2005-04-17 02:20:36 +04:00
/* tv norm specific stuff for multi-norm tuners */
switch ( t - > type ) {
case TUNER_PHILIPS_SECAM : // FI1216MF
/* 0x01 -> ??? no change ??? */
/* 0x02 -> PAL BDGHI / SECAM L */
/* 0x04 -> ??? PAL others / SECAM others ??? */
2006-01-23 22:11:11 +03:00
cb & = ~ 0x02 ;
2005-04-17 02:20:36 +04:00
if ( t - > std & V4L2_STD_SECAM )
2006-01-23 22:11:11 +03:00
cb | = 0x02 ;
2005-04-17 02:20:36 +04:00
break ;
case TUNER_TEMIC_4046FM5 :
2006-01-23 22:11:11 +03:00
cb & = ~ 0x0f ;
2005-04-17 02:20:36 +04:00
if ( t - > std & V4L2_STD_PAL_BG ) {
2006-01-23 22:11:11 +03:00
cb | = TEMIC_SET_PAL_BG ;
2005-04-17 02:20:36 +04:00
} else if ( t - > std & V4L2_STD_PAL_I ) {
2006-01-23 22:11:11 +03:00
cb | = TEMIC_SET_PAL_I ;
2005-04-17 02:20:36 +04:00
} else if ( t - > std & V4L2_STD_PAL_DK ) {
2006-01-23 22:11:11 +03:00
cb | = TEMIC_SET_PAL_DK ;
2005-04-17 02:20:36 +04:00
} else if ( t - > std & V4L2_STD_SECAM_L ) {
2006-01-23 22:11:11 +03:00
cb | = TEMIC_SET_PAL_L ;
2005-04-17 02:20:36 +04:00
}
break ;
case TUNER_PHILIPS_FQ1216ME :
2006-01-23 22:11:11 +03:00
cb & = ~ 0x0f ;
2005-04-17 02:20:36 +04:00
if ( t - > std & ( V4L2_STD_PAL_BG | V4L2_STD_PAL_DK ) ) {
2006-01-23 22:11:11 +03:00
cb | = PHILIPS_SET_PAL_BGDK ;
2005-04-17 02:20:36 +04:00
} else if ( t - > std & V4L2_STD_PAL_I ) {
2006-01-23 22:11:11 +03:00
cb | = PHILIPS_SET_PAL_I ;
2005-04-17 02:20:36 +04:00
} else if ( t - > std & V4L2_STD_SECAM_L ) {
2006-01-23 22:11:11 +03:00
cb | = PHILIPS_SET_PAL_L ;
2005-04-17 02:20:36 +04:00
}
break ;
case TUNER_PHILIPS_ATSC :
/* 0x00 -> ATSC antenna input 1 */
/* 0x01 -> ATSC antenna input 2 */
/* 0x02 -> NTSC antenna input 1 */
/* 0x03 -> NTSC antenna input 2 */
2006-01-23 22:11:11 +03:00
cb & = ~ 0x03 ;
2005-04-17 02:20:36 +04:00
if ( ! ( t - > std & V4L2_STD_ATSC ) )
2006-01-23 22:11:11 +03:00
cb | = 2 ;
2005-04-17 02:20:36 +04:00
/* FIXME: input */
break ;
case TUNER_MICROTUNE_4042FI5 :
/* Set the charge pump for fast tuning */
2006-01-23 22:11:11 +03:00
config | = TUNER_CHARGE_PUMP ;
2005-04-17 02:20:36 +04:00
break ;
2005-11-09 08:37:04 +03:00
case TUNER_PHILIPS_TUV1236D :
/* 0x40 -> ATSC antenna input 1 */
/* 0x48 -> ATSC antenna input 2 */
/* 0x00 -> NTSC antenna input 1 */
/* 0x08 -> NTSC antenna input 2 */
2005-11-09 08:38:18 +03:00
buffer [ 0 ] = 0x14 ;
buffer [ 1 ] = 0x00 ;
buffer [ 2 ] = 0x17 ;
buffer [ 3 ] = 0x00 ;
2006-01-23 22:11:11 +03:00
cb & = ~ 0x40 ;
2005-11-09 08:38:18 +03:00
if ( t - > std & V4L2_STD_ATSC ) {
2006-01-23 22:11:11 +03:00
cb | = 0x40 ;
2005-11-09 08:38:18 +03:00
buffer [ 1 ] = 0x04 ;
}
/* set to the correct mode (analog or digital) */
tuneraddr = c - > addr ;
c - > addr = 0x0a ;
if ( 2 ! = ( rc = i2c_master_send ( c , & buffer [ 0 ] , 2 ) ) )
tuner_warn ( " i2c i/o error: rc == %d (should be 2) \n " , rc ) ;
if ( 2 ! = ( rc = i2c_master_send ( c , & buffer [ 2 ] , 2 ) ) )
tuner_warn ( " i2c i/o error: rc == %d (should be 2) \n " , rc ) ;
c - > addr = tuneraddr ;
2005-11-09 08:37:04 +03:00
/* FIXME: input */
break ;
2005-04-17 02:20:36 +04:00
}
2006-06-25 22:34:39 +04:00
if ( params - > cb_first_if_lower_freq & & div < t - > last_div ) {
2006-01-23 22:11:11 +03:00
buffer [ 0 ] = config ;
2006-01-23 22:11:11 +03:00
buffer [ 1 ] = cb ;
2005-04-17 02:20:36 +04:00
buffer [ 2 ] = ( div > > 8 ) & 0x7f ;
buffer [ 3 ] = div & 0xff ;
} else {
buffer [ 0 ] = ( div > > 8 ) & 0x7f ;
buffer [ 1 ] = div & 0xff ;
2006-01-23 22:11:11 +03:00
buffer [ 2 ] = config ;
2006-01-23 22:11:11 +03:00
buffer [ 3 ] = cb ;
2005-04-17 02:20:36 +04:00
}
2006-01-15 20:04:52 +03:00
t - > last_div = div ;
2006-06-25 22:34:39 +04:00
if ( params - > has_tda9887 ) {
int config = 0 ;
int is_secam_l = ( t - > std & ( V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC ) ) & &
! ( t - > std & ~ ( V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC ) ) ;
if ( t - > std = = V4L2_STD_SECAM_LC ) {
if ( params - > port1_active ^ params - > port1_invert_for_secam_lc )
config | = TDA9887_PORT1_ACTIVE ;
if ( params - > port2_active ^ params - > port2_invert_for_secam_lc )
config | = TDA9887_PORT2_ACTIVE ;
}
else {
if ( params - > port1_active )
config | = TDA9887_PORT1_ACTIVE ;
if ( params - > port2_active )
config | = TDA9887_PORT2_ACTIVE ;
}
if ( params - > intercarrier_mode )
config | = TDA9887_INTERCARRIER ;
if ( is_secam_l ) {
if ( i = = 0 & & params - > default_top_secam_low )
config | = TDA9887_TOP ( params - > default_top_secam_low ) ;
else if ( i = = 1 & & params - > default_top_secam_mid )
config | = TDA9887_TOP ( params - > default_top_secam_mid ) ;
else if ( params - > default_top_secam_high )
config | = TDA9887_TOP ( params - > default_top_secam_high ) ;
}
else {
if ( i = = 0 & & params - > default_top_low )
config | = TDA9887_TOP ( params - > default_top_low ) ;
else if ( i = = 1 & & params - > default_top_mid )
config | = TDA9887_TOP ( params - > default_top_mid ) ;
else if ( params - > default_top_high )
config | = TDA9887_TOP ( params - > default_top_high ) ;
}
2006-08-25 05:43:45 +04:00
if ( params - > default_pll_gating_18 )
config | = TDA9887_GATING_18 ;
2006-06-25 22:34:39 +04:00
i2c_clients_command ( c - > adapter , TDA9887_SET_CONFIG , & config ) ;
}
2005-04-17 02:20:36 +04:00
tuner_dbg ( " tv 0x%02x 0x%02x 0x%02x 0x%02x \n " ,
buffer [ 0 ] , buffer [ 1 ] , buffer [ 2 ] , buffer [ 3 ] ) ;
2005-11-09 08:37:43 +03:00
if ( 4 ! = ( rc = i2c_master_send ( c , buffer , 4 ) ) )
2005-04-17 02:20:36 +04:00
tuner_warn ( " i2c i/o error: rc == %d (should be 4) \n " , rc ) ;
2006-07-18 00:15:26 +04:00
switch ( t - > type ) {
case TUNER_LG_TDVS_H06XF :
/* Set the Auxiliary Byte. */
buffer [ 0 ] = buffer [ 2 ] ;
buffer [ 0 ] & = ~ 0x20 ;
buffer [ 0 ] | = 0x18 ;
buffer [ 1 ] = 0x20 ;
tuner_dbg ( " tv 0x%02x 0x%02x \n " , buffer [ 0 ] , buffer [ 1 ] ) ;
if ( 2 ! = ( rc = i2c_master_send ( c , buffer , 2 ) ) )
tuner_warn ( " i2c i/o error: rc == %d (should be 2) \n " , rc ) ;
break ;
case TUNER_MICROTUNE_4042FI5 :
{
2005-04-17 02:20:36 +04:00
// FIXME - this may also work for other tuners
unsigned long timeout = jiffies + msecs_to_jiffies ( 1 ) ;
u8 status_byte = 0 ;
/* Wait until the PLL locks */
for ( ; ; ) {
if ( time_after ( jiffies , timeout ) )
return ;
if ( 1 ! = ( rc = i2c_master_recv ( c , & status_byte , 1 ) ) ) {
tuner_warn ( " i2c i/o read error: rc == %d (should be 1) \n " , rc ) ;
break ;
}
2005-07-13 00:58:55 +04:00
if ( status_byte & TUNER_PLL_LOCKED )
2005-04-17 02:20:36 +04:00
break ;
udelay ( 10 ) ;
}
/* Set the charge pump for optimized phase noise figure */
2006-01-23 22:11:11 +03:00
config & = ~ TUNER_CHARGE_PUMP ;
2005-04-17 02:20:36 +04:00
buffer [ 0 ] = ( div > > 8 ) & 0x7f ;
buffer [ 1 ] = div & 0xff ;
2006-01-23 22:11:11 +03:00
buffer [ 2 ] = config ;
2006-01-23 22:11:11 +03:00
buffer [ 3 ] = cb ;
2005-04-17 02:20:36 +04:00
tuner_dbg ( " tv 0x%02x 0x%02x 0x%02x 0x%02x \n " ,
2006-07-18 00:15:26 +04:00
buffer [ 0 ] , buffer [ 1 ] , buffer [ 2 ] , buffer [ 3 ] ) ;
2005-04-17 02:20:36 +04:00
if ( 4 ! = ( rc = i2c_master_send ( c , buffer , 4 ) ) )
tuner_warn ( " i2c i/o error: rc == %d (should be 4) \n " , rc ) ;
2006-07-18 00:15:26 +04:00
break ;
}
2005-04-17 02:20:36 +04:00
}
}
static void default_set_radio_freq ( struct i2c_client * c , unsigned int freq )
{
struct tunertype * tun ;
struct tuner * t = i2c_get_clientdata ( c ) ;
2006-01-15 20:04:52 +03:00
u8 buffer [ 4 ] ;
u16 div ;
V4L/DVB (3359): Redesign tuners struct for maximum flexibility
- Tunertype struct redefined to allow one or more tuner_params structs
per tuner definition, one for each video standard.
- Each tuner_params struct has an element containing an arbitrary
amount of tuner_ranges.
(this is needed for dvb tuners - to be handled later)
- A tuner_range may be referenced by multiple tuner_params structs.
There are many duplicates in here. Reusing tuner_range structs,
rather than defining new ones for each tuner, will cut down on
memory usage, and is preferred when possible.
- tunertype struct contains an element, has_tda988x.
We must set this for all tunertypes that contain a tda988x
chip, and then we can remove this setting from the various
card structs.
- Improves tuners array memory usage efficiency.
- Right now, all tuners are using the first tuner_params[] array element
for analog mode. In the future, we will be merging similar tuner
definitions together, such that each tuner definition will have a
tuner_params struct for each available video standard. At that point,
the tuner_params[] array element will be chosen based on the video
standard in use.
Signed-off-by: Michael Krufky <mkrufky@m1k.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
2006-01-13 19:10:25 +03:00
int rc , j ;
2006-02-07 11:25:34 +03:00
enum param_type desired_type = TUNER_PARAM_TYPE_RADIO ;
2006-06-25 22:34:39 +04:00
struct tuner_params * params ;
2005-04-17 02:20:36 +04:00
2005-07-13 00:58:55 +04:00
tun = & tuners [ t - > type ] ;
2006-02-07 11:25:34 +03:00
for ( j = 0 ; j < tun - > count - 1 ; j + + ) {
if ( desired_type ! = tun - > params [ j ] . type )
continue ;
break ;
}
2006-02-07 11:25:39 +03:00
/* use default tuner_params if desired_type not available */
if ( desired_type ! = tun - > params [ j ] . type )
j = 0 ;
V4L/DVB (3359): Redesign tuners struct for maximum flexibility
- Tunertype struct redefined to allow one or more tuner_params structs
per tuner definition, one for each video standard.
- Each tuner_params struct has an element containing an arbitrary
amount of tuner_ranges.
(this is needed for dvb tuners - to be handled later)
- A tuner_range may be referenced by multiple tuner_params structs.
There are many duplicates in here. Reusing tuner_range structs,
rather than defining new ones for each tuner, will cut down on
memory usage, and is preferred when possible.
- tunertype struct contains an element, has_tda988x.
We must set this for all tunertypes that contain a tda988x
chip, and then we can remove this setting from the various
card structs.
- Improves tuners array memory usage efficiency.
- Right now, all tuners are using the first tuner_params[] array element
for analog mode. In the future, we will be merging similar tuner
definitions together, such that each tuner definition will have a
tuner_params struct for each available video standard. At that point,
the tuner_params[] array element will be chosen based on the video
standard in use.
Signed-off-by: Michael Krufky <mkrufky@m1k.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
2006-01-13 19:10:25 +03:00
2005-07-13 00:58:55 +04:00
div = ( 20 * freq / 16000 ) + ( int ) ( 20 * 10.7 ) ; /* IF 10.7 MHz */
2006-06-25 22:34:39 +04:00
params = & tun - > params [ j ] ;
buffer [ 2 ] = ( params - > ranges [ 0 ] . config & ~ TUNER_RATIO_MASK ) | TUNER_RATIO_SELECT_50 ; /* 50 kHz step */
2005-04-17 02:20:36 +04:00
switch ( t - > type ) {
2005-06-24 09:05:07 +04:00
case TUNER_TENA_9533_DI :
2005-06-24 09:02:43 +04:00
case TUNER_YMEC_TVF_5533MF :
2005-07-13 00:58:55 +04:00
tuner_dbg ( " This tuner doesn't have FM. Most cards has a TEA5767 for FM \n " ) ;
return ;
2005-04-17 02:20:36 +04:00
case TUNER_PHILIPS_FM1216ME_MK3 :
case TUNER_PHILIPS_FM1236_MK3 :
2005-06-29 07:45:21 +04:00
case TUNER_PHILIPS_FMD1216ME_MK3 :
2006-12-03 12:45:07 +03:00
case TUNER_LG_NTSC_TAPE :
2005-04-17 02:20:36 +04:00
buffer [ 3 ] = 0x19 ;
break ;
2006-03-09 17:17:43 +03:00
case TUNER_TNF_5335MF :
buffer [ 3 ] = 0x11 ;
break ;
2005-04-17 02:20:36 +04:00
case TUNER_PHILIPS_FM1256_IH3 :
2005-07-13 00:58:55 +04:00
div = ( 20 * freq ) / 16000 + ( int ) ( 33.3 * 20 ) ; /* IF 33.3 MHz */
2005-04-17 02:20:36 +04:00
buffer [ 3 ] = 0x19 ;
break ;
case TUNER_LG_PAL_FM :
buffer [ 3 ] = 0xa5 ;
break ;
2005-09-10 00:03:56 +04:00
case TUNER_MICROTUNE_4049FM5 :
div = ( 20 * freq ) / 16000 + ( int ) ( 33.3 * 20 ) ; /* IF 33.3 MHz */
buffer [ 3 ] = 0xa4 ;
break ;
2005-04-17 02:20:36 +04:00
default :
buffer [ 3 ] = 0xa4 ;
break ;
}
2006-06-25 22:34:39 +04:00
if ( params - > cb_first_if_lower_freq & & div < t - > last_div ) {
2006-01-15 20:04:52 +03:00
buffer [ 0 ] = buffer [ 2 ] ;
buffer [ 1 ] = buffer [ 3 ] ;
buffer [ 2 ] = ( div > > 8 ) & 0x7f ;
buffer [ 3 ] = div & 0xff ;
} else {
buffer [ 0 ] = ( div > > 8 ) & 0x7f ;
buffer [ 1 ] = div & 0xff ;
}
2005-04-17 02:20:36 +04:00
tuner_dbg ( " radio 0x%02x 0x%02x 0x%02x 0x%02x \n " ,
buffer [ 0 ] , buffer [ 1 ] , buffer [ 2 ] , buffer [ 3 ] ) ;
2006-01-15 20:04:52 +03:00
t - > last_div = div ;
2005-04-17 02:20:36 +04:00
2006-06-25 22:34:39 +04:00
if ( params - > has_tda9887 ) {
int config = 0 ;
if ( params - > port1_active & & ! params - > port1_fm_high_sensitivity )
config | = TDA9887_PORT1_ACTIVE ;
if ( params - > port2_active & & ! params - > port2_fm_high_sensitivity )
config | = TDA9887_PORT2_ACTIVE ;
if ( params - > intercarrier_mode )
config | = TDA9887_INTERCARRIER ;
/* if (params->port1_set_for_fm_mono)
config & = ~ TDA9887_PORT1_ACTIVE ; */
i2c_clients_command ( c - > adapter , TDA9887_SET_CONFIG , & config ) ;
}
2005-11-09 08:37:43 +03:00
if ( 4 ! = ( rc = i2c_master_send ( c , buffer , 4 ) ) )
2005-04-17 02:20:36 +04:00
tuner_warn ( " i2c i/o error: rc == %d (should be 4) \n " , rc ) ;
}
int default_tuner_init ( struct i2c_client * c )
{
struct tuner * t = i2c_get_clientdata ( c ) ;
tuner_info ( " type set to %d (%s) \n " ,
t - > type , tuners [ t - > type ] . name ) ;
strlcpy ( c - > name , tuners [ t - > type ] . name , sizeof ( c - > name ) ) ;
2006-01-15 20:04:52 +03:00
t - > set_tv_freq = default_set_tv_freq ;
t - > set_radio_freq = default_set_radio_freq ;
2005-04-17 02:20:36 +04:00
t - > has_signal = tuner_signal ;
2006-01-15 20:04:52 +03:00
t - > is_stereo = tuner_stereo ;
2005-09-10 00:03:37 +04:00
t - > standby = NULL ;
2005-06-29 07:45:21 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
}
/*
* Overrides for Emacs so that we follow Linus ' s tabbing style .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Local variables :
* c - basic - offset : 8
* End :
*/