diff options
Diffstat (limited to 'drivers/media/dvb/frontends/tda10023.c')
-rw-r--r-- | drivers/media/dvb/frontends/tda10023.c | 197 |
1 files changed, 116 insertions, 81 deletions
diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb/frontends/tda10023.c index c6ff5b82ff80..a3c34eecdee9 100644 --- a/drivers/media/dvb/frontends/tda10023.c +++ b/drivers/media/dvb/frontends/tda10023.c | |||
@@ -38,75 +38,29 @@ | |||
38 | #include "dvb_frontend.h" | 38 | #include "dvb_frontend.h" |
39 | #include "tda1002x.h" | 39 | #include "tda1002x.h" |
40 | 40 | ||
41 | #define REG0_INIT_VAL 0x23 | ||
41 | 42 | ||
42 | struct tda10023_state { | 43 | struct tda10023_state { |
43 | struct i2c_adapter* i2c; | 44 | struct i2c_adapter* i2c; |
44 | /* configuration settings */ | 45 | /* configuration settings */ |
45 | const struct tda1002x_config* config; | 46 | const struct tda10023_config *config; |
46 | struct dvb_frontend frontend; | 47 | struct dvb_frontend frontend; |
47 | 48 | ||
48 | u8 pwm; | 49 | u8 pwm; |
49 | u8 reg0; | 50 | u8 reg0; |
50 | }; | ||
51 | 51 | ||
52 | /* clock settings */ | ||
53 | u32 xtal; | ||
54 | u8 pll_m; | ||
55 | u8 pll_p; | ||
56 | u8 pll_n; | ||
57 | u32 sysclk; | ||
58 | }; | ||
52 | 59 | ||
53 | #define dprintk(x...) | 60 | #define dprintk(x...) |
54 | 61 | ||
55 | static int verbose; | 62 | static int verbose; |
56 | 63 | ||
57 | #define XTAL 28920000UL | ||
58 | #define PLL_M 8UL | ||
59 | #define PLL_P 4UL | ||
60 | #define PLL_N 1UL | ||
61 | #define SYSCLK (XTAL*PLL_M/(PLL_N*PLL_P)) // -> 57840000 | ||
62 | |||
63 | static u8 tda10023_inittab[]={ | ||
64 | // reg mask val | ||
65 | 0x2a,0xff,0x02, // PLL3, Bypass, Power Down | ||
66 | 0xff,0x64,0x00, // Sleep 100ms | ||
67 | 0x2a,0xff,0x03, // PLL3, Bypass, Power Down | ||
68 | 0xff,0x64,0x00, // Sleep 100ms | ||
69 | 0x28,0xff,PLL_M-1, // PLL1 M=8 | ||
70 | 0x29,0xff,((PLL_P-1)<<6)|(PLL_N-1), // PLL2 | ||
71 | 0x00,0xff,0x23, // GPR FSAMPLING=1 | ||
72 | 0x2a,0xff,0x08, // PLL3 PSACLK=1 | ||
73 | 0xff,0x64,0x00, // Sleep 100ms | ||
74 | 0x1f,0xff,0x00, // RESET | ||
75 | 0xff,0x64,0x00, // Sleep 100ms | ||
76 | 0xe6,0x0c,0x04, // RSCFG_IND | ||
77 | 0x10,0xc0,0x80, // DECDVBCFG1 PBER=1 | ||
78 | |||
79 | 0x0e,0xff,0x82, // GAIN1 | ||
80 | 0x03,0x08,0x08, // CLKCONF DYN=1 | ||
81 | 0x2e,0xbf,0x30, // AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1 PPWMTUN=0 PPWMIF=0 | ||
82 | 0x01,0xff,0x30, // AGCREF | ||
83 | 0x1e,0x84,0x84, // CONTROL SACLK_ON=1 | ||
84 | 0x1b,0xff,0xc8, // ADC TWOS=1 | ||
85 | 0x3b,0xff,0xff, // IFMAX | ||
86 | 0x3c,0xff,0x00, // IFMIN | ||
87 | 0x34,0xff,0x00, // PWMREF | ||
88 | 0x35,0xff,0xff, // TUNMAX | ||
89 | 0x36,0xff,0x00, // TUNMIN | ||
90 | 0x06,0xff,0x7f, // EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1 // 0x77 | ||
91 | 0x1c,0x30,0x30, // EQCONF2 STEPALGO=SGNALGO=1 | ||
92 | 0x37,0xff,0xf6, // DELTAF_LSB | ||
93 | 0x38,0xff,0xff, // DELTAF_MSB | ||
94 | 0x02,0xff,0x93, // AGCCONF1 IFS=1 KAGCIF=2 KAGCTUN=3 | ||
95 | 0x2d,0xff,0xf6, // SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2 | ||
96 | 0x04,0x10,0x00, // SWRAMP=1 | ||
97 | 0x12,0xff,0xa1, // INTP1 POCLKP=1 FEL=1 MFS=0 | ||
98 | 0x2b,0x01,0xa1, // INTS1 | ||
99 | 0x20,0xff,0x04, // INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=? | ||
100 | 0x2c,0xff,0x0d, // INTP/S TRIP=0 TRIS=0 | ||
101 | 0xc4,0xff,0x00, | ||
102 | 0xc3,0x30,0x00, | ||
103 | 0xb5,0xff,0x19, // ERAGC_THD | ||
104 | 0x00,0x03,0x01, // GPR, CLBS soft reset | ||
105 | 0x00,0x03,0x03, // GPR, CLBS soft reset | ||
106 | 0xff,0x64,0x00, // Sleep 100ms | ||
107 | 0xff,0xff,0xff | ||
108 | }; | ||
109 | |||
110 | static u8 tda10023_readreg (struct tda10023_state* state, u8 reg) | 64 | static u8 tda10023_readreg (struct tda10023_state* state, u8 reg) |
111 | { | 65 | { |
112 | u8 b0 [] = { reg }; | 66 | u8 b0 [] = { reg }; |
@@ -219,30 +173,34 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr) | |||
219 | s16 SFIL=0; | 173 | s16 SFIL=0; |
220 | u16 NDEC = 0; | 174 | u16 NDEC = 0; |
221 | 175 | ||
222 | if (sr < (u32)(SYSCLK/98.40)) { | 176 | /* avoid floating point operations multiplying syscloc and divider |
177 | by 10 */ | ||
178 | u32 sysclk_x_10 = state->sysclk * 10; | ||
179 | |||
180 | if (sr < (u32)(sysclk_x_10/984)) { | ||
223 | NDEC=3; | 181 | NDEC=3; |
224 | SFIL=1; | 182 | SFIL=1; |
225 | } else if (sr<(u32)(SYSCLK/64.0)) { | 183 | } else if (sr < (u32)(sysclk_x_10/640)) { |
226 | NDEC=3; | 184 | NDEC=3; |
227 | SFIL=0; | 185 | SFIL=0; |
228 | } else if (sr<(u32)(SYSCLK/49.2)) { | 186 | } else if (sr < (u32)(sysclk_x_10/492)) { |
229 | NDEC=2; | 187 | NDEC=2; |
230 | SFIL=1; | 188 | SFIL=1; |
231 | } else if (sr<(u32)(SYSCLK/32.0)) { | 189 | } else if (sr < (u32)(sysclk_x_10/320)) { |
232 | NDEC=2; | 190 | NDEC=2; |
233 | SFIL=0; | 191 | SFIL=0; |
234 | } else if (sr<(u32)(SYSCLK/24.6)) { | 192 | } else if (sr < (u32)(sysclk_x_10/246)) { |
235 | NDEC=1; | 193 | NDEC=1; |
236 | SFIL=1; | 194 | SFIL=1; |
237 | } else if (sr<(u32)(SYSCLK/16.0)) { | 195 | } else if (sr < (u32)(sysclk_x_10/160)) { |
238 | NDEC=1; | 196 | NDEC=1; |
239 | SFIL=0; | 197 | SFIL=0; |
240 | } else if (sr<(u32)(SYSCLK/12.3)) { | 198 | } else if (sr < (u32)(sysclk_x_10/123)) { |
241 | NDEC=0; | 199 | NDEC=0; |
242 | SFIL=1; | 200 | SFIL=1; |
243 | } | 201 | } |
244 | 202 | ||
245 | BDRI=SYSCLK*16; | 203 | BDRI = (state->sysclk)*16; |
246 | BDRI>>=NDEC; | 204 | BDRI>>=NDEC; |
247 | BDRI +=sr/2; | 205 | BDRI +=sr/2; |
248 | BDRI /=sr; | 206 | BDRI /=sr; |
@@ -255,11 +213,12 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr) | |||
255 | 213 | ||
256 | BDRX=1<<(24+NDEC); | 214 | BDRX=1<<(24+NDEC); |
257 | BDRX*=sr; | 215 | BDRX*=sr; |
258 | do_div(BDRX,SYSCLK); // BDRX/=SYSCLK; | 216 | do_div(BDRX, state->sysclk); /* BDRX/=SYSCLK; */ |
259 | 217 | ||
260 | BDR=(s32)BDRX; | 218 | BDR=(s32)BDRX; |
261 | } | 219 | } |
262 | // printk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n",sr,BDR,BDRI,NDEC); | 220 | dprintk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n", |
221 | sr, BDR, BDRI, NDEC); | ||
263 | tda10023_writebit (state, 0x03, 0xc0, NDEC<<6); | 222 | tda10023_writebit (state, 0x03, 0xc0, NDEC<<6); |
264 | tda10023_writereg (state, 0x0a, BDR&255); | 223 | tda10023_writereg (state, 0x0a, BDR&255); |
265 | tda10023_writereg (state, 0x0b, (BDR>>8)&255); | 224 | tda10023_writereg (state, 0x0b, (BDR>>8)&255); |
@@ -272,8 +231,67 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr) | |||
272 | static int tda10023_init (struct dvb_frontend *fe) | 231 | static int tda10023_init (struct dvb_frontend *fe) |
273 | { | 232 | { |
274 | struct tda10023_state* state = fe->demodulator_priv; | 233 | struct tda10023_state* state = fe->demodulator_priv; |
234 | u8 tda10023_inittab[] = { | ||
235 | /* reg mask val */ | ||
236 | /* 000 */ 0x2a, 0xff, 0x02, /* PLL3, Bypass, Power Down */ | ||
237 | /* 003 */ 0xff, 0x64, 0x00, /* Sleep 100ms */ | ||
238 | /* 006 */ 0x2a, 0xff, 0x03, /* PLL3, Bypass, Power Down */ | ||
239 | /* 009 */ 0xff, 0x64, 0x00, /* Sleep 100ms */ | ||
240 | /* PLL1 */ | ||
241 | /* 012 */ 0x28, 0xff, (state->pll_m-1), | ||
242 | /* PLL2 */ | ||
243 | /* 015 */ 0x29, 0xff, ((state->pll_p-1)<<6)|(state->pll_n-1), | ||
244 | /* GPR FSAMPLING=1 */ | ||
245 | /* 018 */ 0x00, 0xff, REG0_INIT_VAL, | ||
246 | /* 021 */ 0x2a, 0xff, 0x08, /* PLL3 PSACLK=1 */ | ||
247 | /* 024 */ 0xff, 0x64, 0x00, /* Sleep 100ms */ | ||
248 | /* 027 */ 0x1f, 0xff, 0x00, /* RESET */ | ||
249 | /* 030 */ 0xff, 0x64, 0x00, /* Sleep 100ms */ | ||
250 | /* 033 */ 0xe6, 0x0c, 0x04, /* RSCFG_IND */ | ||
251 | /* 036 */ 0x10, 0xc0, 0x80, /* DECDVBCFG1 PBER=1 */ | ||
252 | |||
253 | /* 039 */ 0x0e, 0xff, 0x82, /* GAIN1 */ | ||
254 | /* 042 */ 0x03, 0x08, 0x08, /* CLKCONF DYN=1 */ | ||
255 | /* 045 */ 0x2e, 0xbf, 0x30, /* AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1 | ||
256 | PPWMTUN=0 PPWMIF=0 */ | ||
257 | /* 048 */ 0x01, 0xff, 0x30, /* AGCREF */ | ||
258 | /* 051 */ 0x1e, 0x84, 0x84, /* CONTROL SACLK_ON=1 */ | ||
259 | /* 054 */ 0x1b, 0xff, 0xc8, /* ADC TWOS=1 */ | ||
260 | /* 057 */ 0x3b, 0xff, 0xff, /* IFMAX */ | ||
261 | /* 060 */ 0x3c, 0xff, 0x00, /* IFMIN */ | ||
262 | /* 063 */ 0x34, 0xff, 0x00, /* PWMREF */ | ||
263 | /* 066 */ 0x35, 0xff, 0xff, /* TUNMAX */ | ||
264 | /* 069 */ 0x36, 0xff, 0x00, /* TUNMIN */ | ||
265 | /* 072 */ 0x06, 0xff, 0x7f, /* EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1 */ | ||
266 | /* 075 */ 0x1c, 0x30, 0x30, /* EQCONF2 STEPALGO=SGNALGO=1 */ | ||
267 | /* 078 */ 0x37, 0xff, 0xf6, /* DELTAF_LSB */ | ||
268 | /* 081 */ 0x38, 0xff, 0xff, /* DELTAF_MSB */ | ||
269 | /* 084 */ 0x02, 0xff, 0x93, /* AGCCONF1 IFS=1 KAGCIF=2 KAGCTUN=3 */ | ||
270 | /* 087 */ 0x2d, 0xff, 0xf6, /* SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2 */ | ||
271 | /* 090 */ 0x04, 0x10, 0x00, /* SWRAMP=1 */ | ||
272 | /* 093 */ 0x12, 0xff, TDA10023_OUTPUT_MODE_PARALLEL_B, /* | ||
273 | INTP1 POCLKP=1 FEL=1 MFS=0 */ | ||
274 | /* 096 */ 0x2b, 0x01, 0xa1, /* INTS1 */ | ||
275 | /* 099 */ 0x20, 0xff, 0x04, /* INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=? */ | ||
276 | /* 102 */ 0x2c, 0xff, 0x0d, /* INTP/S TRIP=0 TRIS=0 */ | ||
277 | /* 105 */ 0xc4, 0xff, 0x00, | ||
278 | /* 108 */ 0xc3, 0x30, 0x00, | ||
279 | /* 111 */ 0xb5, 0xff, 0x19, /* ERAGC_THD */ | ||
280 | /* 114 */ 0x00, 0x03, 0x01, /* GPR, CLBS soft reset */ | ||
281 | /* 117 */ 0x00, 0x03, 0x03, /* GPR, CLBS soft reset */ | ||
282 | /* 120 */ 0xff, 0x64, 0x00, /* Sleep 100ms */ | ||
283 | /* 123 */ 0xff, 0xff, 0xff | ||
284 | }; | ||
285 | dprintk("DVB: TDA10023(%d): init chip\n", fe->dvb->num); | ||
286 | |||
287 | /* override default values if set in config */ | ||
288 | if (state->config->deltaf) { | ||
289 | tda10023_inittab[80] = (state->config->deltaf & 0xff); | ||
290 | tda10023_inittab[83] = (state->config->deltaf >> 8); | ||
291 | } | ||
275 | 292 | ||
276 | dprintk("DVB: TDA10023(%d): init chip\n", fe->adapter->num); | 293 | if (state->config->output_mode) |
294 | tda10023_inittab[95] = state->config->output_mode; | ||
277 | 295 | ||
278 | tda10023_writetab(state, tda10023_inittab); | 296 | tda10023_writetab(state, tda10023_inittab); |
279 | 297 | ||
@@ -460,12 +478,11 @@ static void tda10023_release(struct dvb_frontend* fe) | |||
460 | 478 | ||
461 | static struct dvb_frontend_ops tda10023_ops; | 479 | static struct dvb_frontend_ops tda10023_ops; |
462 | 480 | ||
463 | struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config, | 481 | struct dvb_frontend *tda10023_attach(const struct tda10023_config *config, |
464 | struct i2c_adapter* i2c, | 482 | struct i2c_adapter *i2c, |
465 | u8 pwm) | 483 | u8 pwm) |
466 | { | 484 | { |
467 | struct tda10023_state* state = NULL; | 485 | struct tda10023_state* state = NULL; |
468 | int i; | ||
469 | 486 | ||
470 | /* allocate memory for the internal state */ | 487 | /* allocate memory for the internal state */ |
471 | state = kzalloc(sizeof(struct tda10023_state), GFP_KERNEL); | 488 | state = kzalloc(sizeof(struct tda10023_state), GFP_KERNEL); |
@@ -474,22 +491,40 @@ struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config, | |||
474 | /* setup the state */ | 491 | /* setup the state */ |
475 | state->config = config; | 492 | state->config = config; |
476 | state->i2c = i2c; | 493 | state->i2c = i2c; |
477 | memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops)); | ||
478 | state->pwm = pwm; | ||
479 | for (i=0; i < ARRAY_SIZE(tda10023_inittab);i+=3) { | ||
480 | if (tda10023_inittab[i] == 0x00) { | ||
481 | state->reg0 = tda10023_inittab[i+2]; | ||
482 | break; | ||
483 | } | ||
484 | } | ||
485 | 494 | ||
486 | // Wakeup if in standby | 495 | /* wakeup if in standby */ |
487 | tda10023_writereg (state, 0x00, 0x33); | 496 | tda10023_writereg (state, 0x00, 0x33); |
488 | /* check if the demod is there */ | 497 | /* check if the demod is there */ |
489 | if ((tda10023_readreg(state, 0x1a) & 0xf0) != 0x70) goto error; | 498 | if ((tda10023_readreg(state, 0x1a) & 0xf0) != 0x70) goto error; |
490 | 499 | ||
491 | /* create dvb_frontend */ | 500 | /* create dvb_frontend */ |
492 | memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops)); | 501 | memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops)); |
502 | state->pwm = pwm; | ||
503 | state->reg0 = REG0_INIT_VAL; | ||
504 | if (state->config->xtal) { | ||
505 | state->xtal = state->config->xtal; | ||
506 | state->pll_m = state->config->pll_m; | ||
507 | state->pll_p = state->config->pll_p; | ||
508 | state->pll_n = state->config->pll_n; | ||
509 | } else { | ||
510 | /* set default values if not defined in config */ | ||
511 | state->xtal = 28920000; | ||
512 | state->pll_m = 8; | ||
513 | state->pll_p = 4; | ||
514 | state->pll_n = 1; | ||
515 | } | ||
516 | |||
517 | /* calc sysclk */ | ||
518 | state->sysclk = (state->xtal * state->pll_m / \ | ||
519 | (state->pll_n * state->pll_p)); | ||
520 | |||
521 | state->frontend.ops.info.symbol_rate_min = (state->sysclk/2)/64; | ||
522 | state->frontend.ops.info.symbol_rate_max = (state->sysclk/2)/4; | ||
523 | |||
524 | dprintk("DVB: TDA10023 %s: xtal:%d pll_m:%d pll_p:%d pll_n:%d\n", | ||
525 | __func__, state->xtal, state->pll_m, state->pll_p, | ||
526 | state->pll_n); | ||
527 | |||
493 | state->frontend.demodulator_priv = state; | 528 | state->frontend.demodulator_priv = state; |
494 | return &state->frontend; | 529 | return &state->frontend; |
495 | 530 | ||
@@ -504,10 +539,10 @@ static struct dvb_frontend_ops tda10023_ops = { | |||
504 | .name = "Philips TDA10023 DVB-C", | 539 | .name = "Philips TDA10023 DVB-C", |
505 | .type = FE_QAM, | 540 | .type = FE_QAM, |
506 | .frequency_stepsize = 62500, | 541 | .frequency_stepsize = 62500, |
507 | .frequency_min = 47000000, | 542 | .frequency_min = 47000000, |
508 | .frequency_max = 862000000, | 543 | .frequency_max = 862000000, |
509 | .symbol_rate_min = (SYSCLK/2)/64, /* SACLK/64 == (SYSCLK/2)/64 */ | 544 | .symbol_rate_min = 0, /* set in tda10023_attach */ |
510 | .symbol_rate_max = (SYSCLK/2)/4, /* SACLK/4 */ | 545 | .symbol_rate_max = 0, /* set in tda10023_attach */ |
511 | .caps = 0x400 | //FE_CAN_QAM_4 | 546 | .caps = 0x400 | //FE_CAN_QAM_4 |
512 | FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | | 547 | FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | |
513 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | | 548 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | |