2005-04-16 15:20:36 -07:00
/*
* descriptions + helper functions for simple dvb plls .
*
* ( c ) 2004 Gerd Knorr < kraxel @ bytesex . org > [ SuSE Labs ]
*
* 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 .
*/
# include <linux/module.h>
# include <linux/dvb/frontend.h>
# include <asm/types.h>
# include "dvb-pll.h"
2007-09-07 18:19:57 -03:00
struct dvb_pll_priv {
/* pll number */
int nr ;
/* i2c details */
int pll_i2c_address ;
struct i2c_adapter * i2c ;
/* the PLL descriptor */
struct dvb_pll_desc * pll_desc ;
/* cached frequency/bandwidth */
u32 frequency ;
u32 bandwidth ;
} ;
2007-09-09 13:00:45 -03:00
# define DVB_PLL_MAX 64
2007-09-07 18:19:57 -03:00
static unsigned int dvb_pll_devcount ;
2008-04-22 14:41:48 -03:00
static int debug ;
2007-09-07 18:19:57 -03:00
module_param ( debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " enable verbose debug messages " ) ;
2007-09-07 18:27:43 -03:00
static unsigned int id [ DVB_PLL_MAX ] =
{ [ 0 . . . ( DVB_PLL_MAX - 1 ) ] = DVB_PLL_UNDEFINED } ;
module_param_array ( id , int , NULL , 0644 ) ;
MODULE_PARM_DESC ( id , " force pll id to use (DEBUG ONLY) " ) ;
2007-09-07 18:19:57 -03:00
/* ----------------------------------------------------------- */
2007-06-12 16:10:51 -03:00
struct dvb_pll_desc {
char * name ;
u32 min ;
u32 max ;
u32 iffreq ;
2007-09-07 18:03:58 -03:00
void ( * set ) ( struct dvb_frontend * fe , u8 * buf ,
const struct dvb_frontend_parameters * params ) ;
2007-06-12 16:10:51 -03:00
u8 * initdata ;
u8 * sleepdata ;
int count ;
struct {
u32 limit ;
u32 stepsize ;
u8 config ;
u8 cb ;
} entries [ 12 ] ;
} ;
2005-04-16 15:20:36 -07:00
/* ----------------------------------------------------------- */
/* descriptions */
2007-06-12 16:10:51 -03:00
static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
2005-04-16 15:20:36 -07:00
. name = " Thomson dtt7579 " ,
. min = 177000000 ,
. max = 858000000 ,
2007-03-19 02:24:04 -03:00
. iffreq = 36166667 ,
2007-03-19 02:24:09 -03:00
. sleepdata = ( u8 [ ] ) { 2 , 0xb4 , 0x03 } ,
. count = 4 ,
2005-04-16 15:20:36 -07:00
. entries = {
2007-03-19 02:24:04 -03:00
{ 443250000 , 166667 , 0xb4 , 0x02 } ,
{ 542000000 , 166667 , 0xb4 , 0x08 } ,
{ 771000000 , 166667 , 0xbc , 0x08 } ,
{ 999999999 , 166667 , 0xf4 , 0x08 } ,
2005-04-16 15:20:36 -07:00
} ,
} ;
2007-09-07 18:03:58 -03:00
static void thomson_dtt759x_bw ( struct dvb_frontend * fe , u8 * buf ,
2007-05-05 12:05:39 -03:00
const struct dvb_frontend_parameters * params )
2005-04-16 15:20:36 -07:00
{
2007-05-05 12:05:39 -03:00
if ( BANDWIDTH_7_MHZ = = params - > u . ofdm . bandwidth )
2005-04-16 15:20:36 -07:00
buf [ 3 ] | = 0x10 ;
}
2007-06-12 16:10:51 -03:00
static struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
2005-04-16 15:20:36 -07:00
. name = " Thomson dtt759x " ,
. min = 177000000 ,
. max = 896000000 ,
2007-05-05 12:05:39 -03:00
. set = thomson_dtt759x_bw ,
2007-03-19 02:24:04 -03:00
. iffreq = 36166667 ,
2007-03-19 02:24:09 -03:00
. sleepdata = ( u8 [ ] ) { 2 , 0x84 , 0x03 } ,
. count = 5 ,
2005-04-16 15:20:36 -07:00
. entries = {
2007-03-19 02:24:04 -03:00
{ 264000000 , 166667 , 0xb4 , 0x02 } ,
{ 470000000 , 166667 , 0xbc , 0x02 } ,
{ 735000000 , 166667 , 0xbc , 0x08 } ,
{ 835000000 , 166667 , 0xf4 , 0x08 } ,
{ 999999999 , 166667 , 0xfc , 0x08 } ,
2005-04-16 15:20:36 -07:00
} ,
} ;
2007-06-12 16:10:51 -03:00
static struct dvb_pll_desc dvb_pll_lg_z201 = {
2005-04-16 15:20:36 -07:00
. name = " LG z201 " ,
. min = 174000000 ,
. max = 862000000 ,
2007-03-19 02:24:04 -03:00
. iffreq = 36166667 ,
2007-03-19 02:24:09 -03:00
. sleepdata = ( u8 [ ] ) { 2 , 0xbc , 0x03 } ,
. count = 5 ,
2005-04-16 15:20:36 -07:00
. entries = {
2007-03-19 02:24:04 -03:00
{ 157500000 , 166667 , 0xbc , 0x01 } ,
{ 443250000 , 166667 , 0xbc , 0x02 } ,
{ 542000000 , 166667 , 0xbc , 0x04 } ,
{ 830000000 , 166667 , 0xf4 , 0x04 } ,
{ 999999999 , 166667 , 0xfc , 0x04 } ,
2005-04-16 15:20:36 -07:00
} ,
} ;
2007-06-12 16:10:51 -03:00
static struct dvb_pll_desc dvb_pll_unknown_1 = {
2005-04-16 15:20:36 -07:00
. name = " unknown 1 " , /* used by dntv live dvb-t */
. min = 174000000 ,
. max = 862000000 ,
2007-03-19 02:24:04 -03:00
. iffreq = 36166667 ,
2005-04-16 15:20:36 -07:00
. count = 9 ,
. entries = {
2007-03-19 02:24:04 -03:00
{ 150000000 , 166667 , 0xb4 , 0x01 } ,
{ 173000000 , 166667 , 0xbc , 0x01 } ,
{ 250000000 , 166667 , 0xb4 , 0x02 } ,
{ 400000000 , 166667 , 0xbc , 0x02 } ,
{ 420000000 , 166667 , 0xf4 , 0x02 } ,
{ 470000000 , 166667 , 0xfc , 0x02 } ,
{ 600000000 , 166667 , 0xbc , 0x08 } ,
{ 730000000 , 166667 , 0xf4 , 0x08 } ,
{ 999999999 , 166667 , 0xfc , 0x08 } ,
2005-04-16 15:20:36 -07:00
} ,
} ;
2005-06-23 22:02:35 -07:00
/* Infineon TUA6010XS
* used in Thomson Cable Tuner
*/
2007-06-12 16:10:51 -03:00
static struct dvb_pll_desc dvb_pll_tua6010xs = {
2005-06-23 22:02:35 -07:00
. name = " Infineon TUA6010XS " ,
. min = 44250000 ,
. max = 858000000 ,
2007-03-19 02:24:04 -03:00
. iffreq = 36125000 ,
2005-06-23 22:02:35 -07:00
. count = 3 ,
. entries = {
2007-03-19 02:24:04 -03:00
{ 115750000 , 62500 , 0x8e , 0x03 } ,
{ 403250000 , 62500 , 0x8e , 0x06 } ,
{ 999999999 , 62500 , 0x8e , 0x85 } ,
2005-06-23 22:02:35 -07:00
} ,
} ;
/* Panasonic env57h1xd5 (some Philips PLL ?) */
2007-06-12 16:10:51 -03:00
static struct dvb_pll_desc dvb_pll_env57h1xd5 = {
2005-06-23 22:02:35 -07:00
. name = " Panasonic ENV57H1XD5 " ,
. min = 44250000 ,
. max = 858000000 ,
2007-03-19 02:24:04 -03:00
. iffreq = 36125000 ,
2005-06-23 22:02:35 -07:00
. count = 4 ,
. entries = {
2007-03-19 02:24:04 -03:00
{ 153000000 , 166667 , 0xc2 , 0x41 } ,
{ 470000000 , 166667 , 0xc2 , 0x42 } ,
{ 526000000 , 166667 , 0xc2 , 0x84 } ,
{ 999999999 , 166667 , 0xc2 , 0xa4 } ,
2005-06-23 22:02:35 -07:00
} ,
} ;
/* Philips TDA6650/TDA6651
* used in Panasonic ENV77H11D5
*/
2007-09-07 18:03:58 -03:00
static void tda665x_bw ( struct dvb_frontend * fe , u8 * buf ,
const struct dvb_frontend_parameters * params )
2005-06-23 22:02:35 -07:00
{
2007-05-05 12:05:39 -03:00
if ( params - > u . ofdm . bandwidth = = BANDWIDTH_8_MHZ )
2005-06-23 22:02:35 -07:00
buf [ 3 ] | = 0x08 ;
}
2007-06-12 16:10:51 -03:00
static struct dvb_pll_desc dvb_pll_tda665x = {
2005-06-23 22:02:35 -07:00
. name = " Philips TDA6650/TDA6651 " ,
. min = 44250000 ,
. max = 858000000 ,
2007-05-05 12:05:39 -03:00
. set = tda665x_bw ,
2007-03-19 02:24:04 -03:00
. iffreq = 36166667 ,
2007-05-09 15:58:17 -03:00
. initdata = ( u8 [ ] ) { 4 , 0x0b , 0xf5 , 0x85 , 0xab } ,
2005-06-23 22:02:35 -07:00
. count = 12 ,
. entries = {
2007-03-19 02:24:04 -03:00
{ 93834000 , 166667 , 0xca , 0x61 /* 011 0 0 0 01 */ } ,
{ 123834000 , 166667 , 0xca , 0xa1 /* 101 0 0 0 01 */ } ,
{ 161000000 , 166667 , 0xca , 0xa1 /* 101 0 0 0 01 */ } ,
{ 163834000 , 166667 , 0xca , 0xc2 /* 110 0 0 0 10 */ } ,
{ 253834000 , 166667 , 0xca , 0x62 /* 011 0 0 0 10 */ } ,
{ 383834000 , 166667 , 0xca , 0xa2 /* 101 0 0 0 10 */ } ,
{ 443834000 , 166667 , 0xca , 0xc2 /* 110 0 0 0 10 */ } ,
{ 444000000 , 166667 , 0xca , 0xc4 /* 110 0 0 1 00 */ } ,
{ 583834000 , 166667 , 0xca , 0x64 /* 011 0 0 1 00 */ } ,
{ 793834000 , 166667 , 0xca , 0xa4 /* 101 0 0 1 00 */ } ,
{ 444834000 , 166667 , 0xca , 0xc4 /* 110 0 0 1 00 */ } ,
{ 861000000 , 166667 , 0xca , 0xe4 /* 111 0 0 1 00 */ } ,
2005-06-23 22:02:35 -07:00
}
} ;
/* Infineon TUA6034
* used in LG TDTP E102P
*/
2007-09-07 18:03:58 -03:00
static void tua6034_bw ( struct dvb_frontend * fe , u8 * buf ,
const struct dvb_frontend_parameters * params )
2005-06-23 22:02:35 -07:00
{
2007-05-05 12:05:39 -03:00
if ( BANDWIDTH_7_MHZ ! = params - > u . ofdm . bandwidth )
2005-06-23 22:02:35 -07:00
buf [ 3 ] | = 0x08 ;
}
2007-06-12 16:10:51 -03:00
static struct dvb_pll_desc dvb_pll_tua6034 = {
2005-06-23 22:02:35 -07:00
. name = " Infineon TUA6034 " ,
. min = 44250000 ,
. max = 858000000 ,
2007-03-19 02:24:04 -03:00
. iffreq = 36166667 ,
2005-06-23 22:02:35 -07:00
. count = 3 ,
2007-05-05 12:05:39 -03:00
. set = tua6034_bw ,
2005-06-23 22:02:35 -07:00
. entries = {
2007-03-19 02:24:04 -03:00
{ 174500000 , 62500 , 0xce , 0x01 } ,
{ 230000000 , 62500 , 0xce , 0x02 } ,
{ 999999999 , 62500 , 0xce , 0x04 } ,
2005-06-23 22:02:35 -07:00
} ,
} ;
2005-07-07 17:58:12 -07:00
/* ALPS TDED4
* used in Nebula - Cards and USB boxes
*/
2007-09-07 18:03:58 -03:00
static void tded4_bw ( struct dvb_frontend * fe , u8 * buf ,
const struct dvb_frontend_parameters * params )
2005-07-07 17:58:12 -07:00
{
2007-05-05 12:05:39 -03:00
if ( params - > u . ofdm . bandwidth = = BANDWIDTH_8_MHZ )
2005-07-07 17:58:12 -07:00
buf [ 3 ] | = 0x04 ;
}
2007-06-12 16:10:51 -03:00
static struct dvb_pll_desc dvb_pll_tded4 = {
2005-07-07 17:58:12 -07:00
. name = " ALPS TDED4 " ,
. min = 47000000 ,
. max = 863000000 ,
2007-03-19 02:24:04 -03:00
. iffreq = 36166667 ,
2007-05-05 12:05:39 -03:00
. set = tded4_bw ,
2005-07-07 17:58:12 -07:00
. count = 4 ,
. entries = {
2007-03-19 02:24:04 -03:00
{ 153000000 , 166667 , 0x85 , 0x01 } ,
{ 470000000 , 166667 , 0x85 , 0x02 } ,
{ 823000000 , 166667 , 0x85 , 0x08 } ,
{ 999999999 , 166667 , 0x85 , 0x88 } ,
2005-07-07 17:58:12 -07:00
}
} ;
2005-11-08 21:35:39 -08:00
/* ALPS TDHU2
* used in AverTVHD MCE A180
*/
2007-06-12 16:10:51 -03:00
static struct dvb_pll_desc dvb_pll_tdhu2 = {
2005-11-08 21:35:39 -08:00
. name = " ALPS TDHU2 " ,
. min = 54000000 ,
. max = 864000000 ,
2007-03-19 02:24:04 -03:00
. iffreq = 44000000 ,
2005-11-08 21:35:39 -08:00
. count = 4 ,
. entries = {
2007-03-19 02:24:04 -03:00
{ 162000000 , 62500 , 0x85 , 0x01 } ,
{ 426000000 , 62500 , 0x85 , 0x02 } ,
{ 782000000 , 62500 , 0x85 , 0x08 } ,
{ 999999999 , 62500 , 0x85 , 0x88 } ,
2005-11-08 21:35:39 -08:00
}
} ;
2006-01-23 17:11:06 -02:00
/* Samsung TBMV30111IN / TBMV30712IN1
2005-11-08 21:35:39 -08:00
* used in Air2PC ATSC - 2 nd generation ( nxt2002 )
*/
2007-06-12 16:10:51 -03:00
static struct dvb_pll_desc dvb_pll_samsung_tbmv = {
2006-01-23 17:11:07 -02:00
. name = " Samsung TBMV30111IN / TBMV30712IN1 " ,
2005-11-08 21:35:39 -08:00
. min = 54000000 ,
. max = 860000000 ,
2007-03-19 02:24:04 -03:00
. iffreq = 44000000 ,
2006-01-15 19:04:04 -02:00
. count = 6 ,
2005-11-08 21:35:39 -08:00
. entries = {
2007-03-19 02:24:04 -03:00
{ 172000000 , 166667 , 0xb4 , 0x01 } ,
{ 214000000 , 166667 , 0xb4 , 0x02 } ,
{ 467000000 , 166667 , 0xbc , 0x02 } ,
{ 721000000 , 166667 , 0xbc , 0x08 } ,
{ 841000000 , 166667 , 0xf4 , 0x08 } ,
{ 999999999 , 166667 , 0xfc , 0x02 } ,
2005-11-08 21:35:39 -08:00
}
} ;
2006-01-11 23:31:53 -02:00
/*
* Philips SD1878 Tuner .
*/
2007-06-12 16:10:51 -03:00
static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
2006-01-11 23:31:53 -02:00
. name = " Philips SD1878 " ,
. min = 950000 ,
. max = 2150000 ,
2007-03-19 02:24:04 -03:00
. iffreq = 249 , /* zero-IF, offset 249 is to round up */
2006-01-11 23:31:53 -02:00
. count = 4 ,
. entries = {
2007-03-19 02:24:04 -03:00
{ 1250000 , 500 , 0xc4 , 0x00 } ,
{ 1550000 , 500 , 0xc4 , 0x40 } ,
{ 2050000 , 500 , 0xc4 , 0x80 } ,
{ 2150000 , 500 , 0xc4 , 0xc0 } ,
2006-01-11 23:31:53 -02:00
} ,
} ;
2007-09-07 18:03:58 -03:00
static void opera1_bw ( struct dvb_frontend * fe , u8 * buf ,
const struct dvb_frontend_parameters * params )
2007-04-19 11:26:47 -03:00
{
2007-05-05 12:05:39 -03:00
if ( params - > u . ofdm . bandwidth = = BANDWIDTH_8_MHZ )
2007-04-19 11:26:47 -03:00
buf [ 2 ] | = 0x08 ;
}
2007-06-12 16:10:51 -03:00
static struct dvb_pll_desc dvb_pll_opera1 = {
2007-04-19 11:26:47 -03:00
. name = " Opera Tuner " ,
. min = 900000 ,
. max = 2250000 ,
. iffreq = 0 ,
2007-05-05 12:05:39 -03:00
. set = opera1_bw ,
2007-04-19 11:26:47 -03:00
. count = 8 ,
. entries = {
{ 1064000 , 500 , 0xe5 , 0xc6 } ,
{ 1169000 , 500 , 0xe5 , 0xe6 } ,
{ 1299000 , 500 , 0xe5 , 0x24 } ,
{ 1444000 , 500 , 0xe5 , 0x44 } ,
{ 1606000 , 500 , 0xe5 , 0x64 } ,
{ 1777000 , 500 , 0xe5 , 0x84 } ,
{ 1941000 , 500 , 0xe5 , 0xa4 } ,
{ 2250000 , 500 , 0xe5 , 0xc4 } ,
}
} ;
2007-06-12 16:10:51 -03:00
/* ----------------------------------------------------------- */
static struct dvb_pll_desc * pll_list [ ] = {
[ DVB_PLL_UNDEFINED ] = NULL ,
[ DVB_PLL_THOMSON_DTT7579 ] = & dvb_pll_thomson_dtt7579 ,
[ DVB_PLL_THOMSON_DTT759X ] = & dvb_pll_thomson_dtt759x ,
[ DVB_PLL_LG_Z201 ] = & dvb_pll_lg_z201 ,
[ DVB_PLL_UNKNOWN_1 ] = & dvb_pll_unknown_1 ,
[ DVB_PLL_TUA6010XS ] = & dvb_pll_tua6010xs ,
[ DVB_PLL_ENV57H1XD5 ] = & dvb_pll_env57h1xd5 ,
[ DVB_PLL_TUA6034 ] = & dvb_pll_tua6034 ,
[ DVB_PLL_TDA665X ] = & dvb_pll_tda665x ,
[ DVB_PLL_TDED4 ] = & dvb_pll_tded4 ,
[ DVB_PLL_TDHU2 ] = & dvb_pll_tdhu2 ,
[ DVB_PLL_SAMSUNG_TBMV ] = & dvb_pll_samsung_tbmv ,
[ DVB_PLL_PHILIPS_SD1878_TDA8261 ] = & dvb_pll_philips_sd1878_tda8261 ,
[ DVB_PLL_OPERA1 ] = & dvb_pll_opera1 ,
} ;
2005-04-16 15:20:36 -07:00
/* ----------------------------------------------------------- */
/* code */
2007-09-07 18:03:58 -03:00
static int dvb_pll_configure ( struct dvb_frontend * fe , u8 * buf ,
2007-06-02 16:30:46 -03:00
const struct dvb_frontend_parameters * params )
2005-04-16 15:20:36 -07:00
{
2007-09-07 18:03:58 -03:00
struct dvb_pll_priv * priv = fe - > tuner_priv ;
struct dvb_pll_desc * desc = priv - > pll_desc ;
2005-04-16 15:20:36 -07:00
u32 div ;
int i ;
2007-05-05 12:05:39 -03:00
if ( params - > frequency ! = 0 & & ( params - > frequency < desc - > min | |
params - > frequency > desc - > max ) )
return - EINVAL ;
2005-04-16 15:20:36 -07:00
for ( i = 0 ; i < desc - > count ; i + + ) {
2007-05-05 12:05:39 -03:00
if ( params - > frequency > desc - > entries [ i ] . limit )
2005-04-16 15:20:36 -07:00
continue ;
break ;
}
2007-05-05 12:05:39 -03:00
2005-04-16 15:20:36 -07:00
if ( debug )
2007-05-05 12:05:39 -03:00
printk ( " pll: %s: freq=%d | i=%d/%d \n " , desc - > name ,
params - > frequency , i , desc - > count ) ;
2006-04-18 17:47:12 -03:00
if ( i = = desc - > count )
return - EINVAL ;
2005-04-16 15:20:36 -07:00
2007-05-05 12:05:39 -03:00
div = ( params - > frequency + desc - > iffreq +
desc - > entries [ i ] . stepsize / 2 ) / desc - > entries [ i ] . stepsize ;
2005-04-16 15:20:36 -07:00
buf [ 0 ] = div > > 8 ;
buf [ 1 ] = div & 0xff ;
2006-01-23 17:11:11 -02:00
buf [ 2 ] = desc - > entries [ i ] . config ;
buf [ 3 ] = desc - > entries [ i ] . cb ;
2005-04-16 15:20:36 -07:00
2007-05-05 12:05:39 -03:00
if ( desc - > set )
2007-09-07 18:03:58 -03:00
desc - > set ( fe , buf , params ) ;
2005-04-16 15:20:36 -07:00
if ( debug )
printk ( " pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x \n " ,
desc - > name , div , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] , buf [ 3 ] ) ;
2006-11-20 16:45:29 -03:00
// calculate the frequency we set it to
2007-03-19 02:24:04 -03:00
return ( div * desc - > entries [ i ] . stepsize ) - desc - > iffreq ;
2005-04-16 15:20:36 -07:00
}
2006-04-18 17:47:12 -03:00
static int dvb_pll_release ( struct dvb_frontend * fe )
{
2006-11-19 19:49:11 -03:00
kfree ( fe - > tuner_priv ) ;
2006-04-18 17:47:12 -03:00
fe - > tuner_priv = NULL ;
return 0 ;
}
static int dvb_pll_sleep ( struct dvb_frontend * fe )
{
struct dvb_pll_priv * priv = fe - > tuner_priv ;
2006-08-08 15:48:08 -03:00
if ( priv - > i2c = = NULL )
return - EINVAL ;
2007-03-19 02:24:09 -03:00
if ( priv - > pll_desc - > sleepdata ) {
struct i2c_msg msg = { . flags = 0 ,
. addr = priv - > pll_i2c_address ,
. buf = priv - > pll_desc - > sleepdata + 1 ,
. len = priv - > pll_desc - > sleepdata [ 0 ] } ;
2006-04-18 17:47:12 -03:00
2007-03-19 02:24:09 -03:00
int result ;
2006-04-18 17:47:12 -03:00
2007-03-19 02:24:09 -03:00
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 1 ) ;
if ( ( result = i2c_transfer ( priv - > i2c , & msg , 1 ) ) ! = 1 ) {
return result ;
}
return 0 ;
2006-04-18 17:47:12 -03:00
}
2007-03-19 02:24:09 -03:00
/* Shouldn't be called when initdata is NULL, maybe BUG()? */
return - EINVAL ;
2006-04-18 17:47:12 -03:00
}
2006-11-20 16:38:42 -03:00
static int dvb_pll_set_params ( struct dvb_frontend * fe ,
struct dvb_frontend_parameters * params )
2006-04-18 17:47:12 -03:00
{
struct dvb_pll_priv * priv = fe - > tuner_priv ;
u8 buf [ 4 ] ;
struct i2c_msg msg =
2006-11-20 16:38:42 -03:00
{ . addr = priv - > pll_i2c_address , . flags = 0 ,
. buf = buf , . len = sizeof ( buf ) } ;
2006-04-18 17:47:12 -03:00
int result ;
2007-05-05 12:05:39 -03:00
u32 frequency = 0 ;
2006-04-18 17:47:12 -03:00
if ( priv - > i2c = = NULL )
return - EINVAL ;
2007-09-07 18:03:58 -03:00
if ( ( result = dvb_pll_configure ( fe , buf , params ) ) < 0 )
2006-04-18 17:47:12 -03:00
return result ;
2006-11-20 16:45:29 -03:00
else
frequency = result ;
2006-04-18 17:47:12 -03:00
2006-05-14 05:01:31 -03:00
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 1 ) ;
2006-04-18 17:47:12 -03:00
if ( ( result = i2c_transfer ( priv - > i2c , & msg , 1 ) ) ! = 1 ) {
return result ;
}
2006-11-20 16:45:29 -03:00
priv - > frequency = frequency ;
2007-05-05 12:05:39 -03:00
priv - > bandwidth = ( fe - > ops . info . type = = FE_OFDM ) ? params - > u . ofdm . bandwidth : 0 ;
2006-04-18 17:47:12 -03:00
return 0 ;
}
2006-11-20 16:38:42 -03:00
static int dvb_pll_calc_regs ( struct dvb_frontend * fe ,
struct dvb_frontend_parameters * params ,
u8 * buf , int buf_len )
2006-04-18 17:47:12 -03:00
{
struct dvb_pll_priv * priv = fe - > tuner_priv ;
int result ;
2007-05-05 12:05:39 -03:00
u32 frequency = 0 ;
2006-04-18 17:47:12 -03:00
if ( buf_len < 5 )
return - EINVAL ;
2007-09-07 18:03:58 -03:00
if ( ( result = dvb_pll_configure ( fe , buf + 1 , params ) ) < 0 )
2006-04-18 17:47:12 -03:00
return result ;
2006-11-20 16:45:29 -03:00
else
frequency = result ;
2006-04-18 17:47:12 -03:00
buf [ 0 ] = priv - > pll_i2c_address ;
2006-11-20 16:45:29 -03:00
priv - > frequency = frequency ;
2007-05-05 12:05:39 -03:00
priv - > bandwidth = ( fe - > ops . info . type = = FE_OFDM ) ? params - > u . ofdm . bandwidth : 0 ;
2006-04-18 17:47:12 -03:00
return 5 ;
}
static int dvb_pll_get_frequency ( struct dvb_frontend * fe , u32 * frequency )
{
struct dvb_pll_priv * priv = fe - > tuner_priv ;
* frequency = priv - > frequency ;
return 0 ;
}
static int dvb_pll_get_bandwidth ( struct dvb_frontend * fe , u32 * bandwidth )
{
struct dvb_pll_priv * priv = fe - > tuner_priv ;
* bandwidth = priv - > bandwidth ;
return 0 ;
}
2007-04-27 12:31:29 -03:00
static int dvb_pll_init ( struct dvb_frontend * fe )
{
struct dvb_pll_priv * priv = fe - > tuner_priv ;
if ( priv - > i2c = = NULL )
return - EINVAL ;
if ( priv - > pll_desc - > initdata ) {
struct i2c_msg msg = { . flags = 0 ,
. addr = priv - > pll_i2c_address ,
. buf = priv - > pll_desc - > initdata + 1 ,
. len = priv - > pll_desc - > initdata [ 0 ] } ;
int result ;
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 1 ) ;
if ( ( result = i2c_transfer ( priv - > i2c , & msg , 1 ) ) ! = 1 ) {
return result ;
}
return 0 ;
}
/* Shouldn't be called when initdata is NULL, maybe BUG()? */
return - EINVAL ;
}
2006-04-18 17:47:12 -03:00
static struct dvb_tuner_ops dvb_pll_tuner_ops = {
. release = dvb_pll_release ,
. sleep = dvb_pll_sleep ,
2007-03-19 02:24:09 -03:00
. init = dvb_pll_init ,
2006-04-18 17:47:12 -03:00
. set_params = dvb_pll_set_params ,
2006-04-18 21:38:49 -03:00
. calc_regs = dvb_pll_calc_regs ,
2006-04-18 17:47:12 -03:00
. get_frequency = dvb_pll_get_frequency ,
. get_bandwidth = dvb_pll_get_bandwidth ,
} ;
2006-11-20 16:38:42 -03:00
struct dvb_frontend * dvb_pll_attach ( struct dvb_frontend * fe , int pll_addr ,
struct i2c_adapter * i2c ,
2007-06-12 16:10:51 -03:00
unsigned int pll_desc_id )
2006-04-18 17:47:12 -03:00
{
2006-07-10 03:34:14 -03:00
u8 b1 [ ] = { 0 } ;
2006-11-20 16:38:42 -03:00
struct i2c_msg msg = { . addr = pll_addr , . flags = I2C_M_RD ,
. buf = b1 , . len = 1 } ;
2006-04-18 17:47:12 -03:00
struct dvb_pll_priv * priv = NULL ;
2006-07-10 03:34:14 -03:00
int ret ;
2007-06-12 16:10:51 -03:00
struct dvb_pll_desc * desc ;
2007-09-07 18:27:43 -03:00
if ( ( id [ dvb_pll_devcount ] > DVB_PLL_UNDEFINED ) & &
( id [ dvb_pll_devcount ] < ARRAY_SIZE ( pll_list ) ) )
pll_desc_id = id [ dvb_pll_devcount ] ;
2007-06-12 16:10:51 -03:00
BUG_ON ( pll_desc_id < 1 | | pll_desc_id > = ARRAY_SIZE ( pll_list ) ) ;
desc = pll_list [ pll_desc_id ] ;
2006-07-10 03:34:14 -03:00
2006-07-16 19:41:41 -03:00
if ( i2c ! = NULL ) {
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 1 ) ;
2006-07-18 16:37:13 -03:00
ret = i2c_transfer ( i2c , & msg , 1 ) ;
if ( ret ! = 1 )
2006-08-08 09:10:08 -03:00
return NULL ;
2006-07-16 19:41:41 -03:00
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 0 ) ;
}
2006-04-18 17:47:12 -03:00
priv = kzalloc ( sizeof ( struct dvb_pll_priv ) , GFP_KERNEL ) ;
if ( priv = = NULL )
2006-08-08 09:10:08 -03:00
return NULL ;
2006-04-18 17:47:12 -03:00
priv - > pll_i2c_address = pll_addr ;
priv - > i2c = i2c ;
priv - > pll_desc = desc ;
2007-09-07 18:11:15 -03:00
priv - > nr = dvb_pll_devcount + + ;
2006-04-18 17:47:12 -03:00
2006-11-20 16:38:42 -03:00
memcpy ( & fe - > ops . tuner_ops , & dvb_pll_tuner_ops ,
sizeof ( struct dvb_tuner_ops ) ) ;
2007-04-27 12:31:27 -03:00
strncpy ( fe - > ops . tuner_ops . info . name , desc - > name ,
sizeof ( fe - > ops . tuner_ops . info . name ) ) ;
2006-05-14 05:01:31 -03:00
fe - > ops . tuner_ops . info . frequency_min = desc - > min ;
2007-08-17 18:36:44 -03:00
fe - > ops . tuner_ops . info . frequency_max = desc - > max ;
2007-03-19 02:24:09 -03:00
if ( ! desc - > initdata )
fe - > ops . tuner_ops . init = NULL ;
if ( ! desc - > sleepdata )
fe - > ops . tuner_ops . sleep = NULL ;
2006-04-18 17:47:12 -03:00
fe - > tuner_priv = priv ;
2007-09-07 18:11:15 -03:00
2007-09-09 05:08:30 -03:00
if ( ( debug ) | | ( id [ priv - > nr ] = = pll_desc_id ) ) {
2007-09-07 18:11:15 -03:00
printk ( " dvb-pll[%d] " , priv - > nr ) ;
if ( i2c ! = NULL )
printk ( " %d-%04x " , i2c_adapter_id ( i2c ) , pll_addr ) ;
2007-09-07 18:27:43 -03:00
printk ( " : id# %d (%s) attached, %s \n " , pll_desc_id , desc - > name ,
id [ priv - > nr ] = = pll_desc_id ?
" insmod option " : " autodetected " ) ;
2007-09-09 05:16:34 -03:00
}
2007-09-07 18:11:15 -03:00
2006-08-08 09:10:08 -03:00
return fe ;
2006-04-18 17:47:12 -03:00
}
EXPORT_SYMBOL ( dvb_pll_attach ) ;
2005-04-16 15:20:36 -07:00
MODULE_DESCRIPTION ( " dvb pll library " ) ;
MODULE_AUTHOR ( " Gerd Knorr " ) ;
MODULE_LICENSE ( " GPL " ) ;