diff options
-rw-r--r-- | drivers/media/dvb/frontends/s5h1420.c | 162 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/s5h1420.h | 3 | ||||
-rw-r--r-- | drivers/media/dvb/ttpci/budget.c | 1 |
3 files changed, 97 insertions, 69 deletions
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c index 4f396ac8de77..c7fe27fd530c 100644 --- a/drivers/media/dvb/frontends/s5h1420.c +++ b/drivers/media/dvb/frontends/s5h1420.c | |||
@@ -48,7 +48,8 @@ struct s5h1420_state { | |||
48 | }; | 48 | }; |
49 | 49 | ||
50 | static u32 s5h1420_getsymbolrate(struct s5h1420_state* state); | 50 | static u32 s5h1420_getsymbolrate(struct s5h1420_state* state); |
51 | static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings); | 51 | static int s5h1420_get_tune_settings(struct dvb_frontend* fe, |
52 | struct dvb_frontend_tune_settings* fesettings); | ||
52 | 53 | ||
53 | 54 | ||
54 | static int debug = 0; | 55 | static int debug = 0; |
@@ -91,7 +92,8 @@ static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag | |||
91 | 92 | ||
92 | switch(voltage) { | 93 | switch(voltage) { |
93 | case SEC_VOLTAGE_13: | 94 | case SEC_VOLTAGE_13: |
94 | s5h1420_writereg(state, 0x3c, (s5h1420_readreg(state, 0x3c) & 0xfe) | 0x02); | 95 | s5h1420_writereg(state, 0x3c, |
96 | (s5h1420_readreg(state, 0x3c) & 0xfe) | 0x02); | ||
95 | break; | 97 | break; |
96 | 98 | ||
97 | case SEC_VOLTAGE_18: | 99 | case SEC_VOLTAGE_18: |
@@ -112,18 +114,21 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | |||
112 | 114 | ||
113 | switch(tone) { | 115 | switch(tone) { |
114 | case SEC_TONE_ON: | 116 | case SEC_TONE_ON: |
115 | s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x74) | 0x08); | 117 | s5h1420_writereg(state, 0x3b, |
118 | (s5h1420_readreg(state, 0x3b) & 0x74) | 0x08); | ||
116 | break; | 119 | break; |
117 | 120 | ||
118 | case SEC_TONE_OFF: | 121 | case SEC_TONE_OFF: |
119 | s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01); | 122 | s5h1420_writereg(state, 0x3b, |
123 | (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01); | ||
120 | break; | 124 | break; |
121 | } | 125 | } |
122 | 126 | ||
123 | return 0; | 127 | return 0; |
124 | } | 128 | } |
125 | 129 | ||
126 | static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) | 130 | static int s5h1420_send_master_cmd (struct dvb_frontend* fe, |
131 | struct dvb_diseqc_master_cmd* cmd) | ||
127 | { | 132 | { |
128 | struct s5h1420_state* state = fe->demodulator_priv; | 133 | struct s5h1420_state* state = fe->demodulator_priv; |
129 | u8 val; | 134 | u8 val; |
@@ -131,6 +136,9 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_m | |||
131 | unsigned long timeout; | 136 | unsigned long timeout; |
132 | int result = 0; | 137 | int result = 0; |
133 | 138 | ||
139 | if (cmd->msg_len > 8) | ||
140 | return -EINVAL; | ||
141 | |||
134 | /* setup for DISEQC */ | 142 | /* setup for DISEQC */ |
135 | val = s5h1420_readreg(state, 0x3b); | 143 | val = s5h1420_readreg(state, 0x3b); |
136 | s5h1420_writereg(state, 0x3b, 0x02); | 144 | s5h1420_writereg(state, 0x3b, 0x02); |
@@ -138,16 +146,17 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_m | |||
138 | 146 | ||
139 | /* write the DISEQC command bytes */ | 147 | /* write the DISEQC command bytes */ |
140 | for(i=0; i< cmd->msg_len; i++) { | 148 | for(i=0; i< cmd->msg_len; i++) { |
141 | s5h1420_writereg(state, 0x3c + i, cmd->msg[i]); | 149 | s5h1420_writereg(state, 0x3d + i, cmd->msg[i]); |
142 | } | 150 | } |
143 | 151 | ||
144 | /* kick off transmission */ | 152 | /* kick off transmission */ |
145 | s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | ((cmd->msg_len-1) << 4) | 0x08); | 153 | s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | |
154 | ((cmd->msg_len-1) << 4) | 0x08); | ||
146 | 155 | ||
147 | /* wait for transmission to complete */ | 156 | /* wait for transmission to complete */ |
148 | timeout = jiffies + ((100*HZ) / 1000); | 157 | timeout = jiffies + ((100*HZ) / 1000); |
149 | while(time_before(jiffies, timeout)) { | 158 | while(time_before(jiffies, timeout)) { |
150 | if (s5h1420_readreg(state, 0x3b) & 0x08) | 159 | if (!(s5h1420_readreg(state, 0x3b) & 0x08)) |
151 | break; | 160 | break; |
152 | 161 | ||
153 | msleep(5); | 162 | msleep(5); |
@@ -161,7 +170,8 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_m | |||
161 | return result; | 170 | return result; |
162 | } | 171 | } |
163 | 172 | ||
164 | static int s5h1420_recv_slave_reply (struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply) | 173 | static int s5h1420_recv_slave_reply (struct dvb_frontend* fe, |
174 | struct dvb_diseqc_slave_reply* reply) | ||
165 | { | 175 | { |
166 | struct s5h1420_state* state = fe->demodulator_priv; | 176 | struct s5h1420_state* state = fe->demodulator_priv; |
167 | u8 val; | 177 | u8 val; |
@@ -205,7 +215,7 @@ static int s5h1420_recv_slave_reply (struct dvb_frontend* fe, struct dvb_diseqc_ | |||
205 | 215 | ||
206 | /* extract data */ | 216 | /* extract data */ |
207 | for(i=0; i< length; i++) { | 217 | for(i=0; i< length; i++) { |
208 | reply->msg[i] = s5h1420_readreg(state, 0x3c + i); | 218 | reply->msg[i] = s5h1420_readreg(state, 0x3d + i); |
209 | } | 219 | } |
210 | 220 | ||
211 | exit: | 221 | exit: |
@@ -236,7 +246,7 @@ static int s5h1420_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicm | |||
236 | s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x08); | 246 | s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x08); |
237 | 247 | ||
238 | /* wait for transmission to complete */ | 248 | /* wait for transmission to complete */ |
239 | timeout = jiffies + ((20*HZ) / 1000); | 249 | timeout = jiffies + ((100*HZ) / 1000); |
240 | while(time_before(jiffies, timeout)) { | 250 | while(time_before(jiffies, timeout)) { |
241 | if (!(s5h1420_readreg(state, 0x3b) & 0x08)) | 251 | if (!(s5h1420_readreg(state, 0x3b) & 0x08)) |
242 | break; | 252 | break; |
@@ -259,9 +269,9 @@ static fe_status_t s5h1420_get_status_bits(struct s5h1420_state* state) | |||
259 | 269 | ||
260 | val = s5h1420_readreg(state, 0x14); | 270 | val = s5h1420_readreg(state, 0x14); |
261 | if (val & 0x02) | 271 | if (val & 0x02) |
262 | status |= FE_HAS_SIGNAL; // FIXME: not sure if this is right | 272 | status |= FE_HAS_SIGNAL; |
263 | if (val & 0x01) | 273 | if (val & 0x01) |
264 | status |= FE_HAS_CARRIER; // FIXME: not sure if this is right | 274 | status |= FE_HAS_CARRIER; |
265 | val = s5h1420_readreg(state, 0x36); | 275 | val = s5h1420_readreg(state, 0x36); |
266 | if (val & 0x01) | 276 | if (val & 0x01) |
267 | status |= FE_HAS_VITERBI; | 277 | status |= FE_HAS_VITERBI; |
@@ -284,8 +294,8 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
284 | /* determine lock state */ | 294 | /* determine lock state */ |
285 | *status = s5h1420_get_status_bits(state); | 295 | *status = s5h1420_get_status_bits(state); |
286 | 296 | ||
287 | /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert the inversion, | 297 | /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert |
288 | wait a bit and check again */ | 298 | the inversion, wait a bit and check again */ |
289 | if (*status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI)) { | 299 | if (*status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI)) { |
290 | val = s5h1420_readreg(state, 0x32); | 300 | val = s5h1420_readreg(state, 0x32); |
291 | if ((val & 0x07) == 0x03) { | 301 | if ((val & 0x07) == 0x03) { |
@@ -330,6 +340,10 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
330 | tmp = (tmp * 2 * 7) / 8; | 340 | tmp = (tmp * 2 * 7) / 8; |
331 | break; | 341 | break; |
332 | } | 342 | } |
343 | if (tmp == 0) { | ||
344 | printk("s5h1420: avoided division by 0\n"); | ||
345 | tmp = 1; | ||
346 | } | ||
333 | tmp = state->fclk / tmp; | 347 | tmp = state->fclk / tmp; |
334 | 348 | ||
335 | /* set the MPEG_CLK_INTL for the calculated data rate */ | 349 | /* set the MPEG_CLK_INTL for the calculated data rate */ |
@@ -368,16 +382,21 @@ static int s5h1420_read_ber(struct dvb_frontend* fe, u32* ber) | |||
368 | 382 | ||
369 | s5h1420_writereg(state, 0x46, 0x1d); | 383 | s5h1420_writereg(state, 0x46, 0x1d); |
370 | mdelay(25); | 384 | mdelay(25); |
371 | return (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47); | 385 | |
386 | *ber = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47); | ||
387 | |||
388 | return 0; | ||
372 | } | 389 | } |
373 | 390 | ||
374 | static int s5h1420_read_signal_strength(struct dvb_frontend* fe, u16* strength) | 391 | static int s5h1420_read_signal_strength(struct dvb_frontend* fe, u16* strength) |
375 | { | 392 | { |
376 | struct s5h1420_state* state = fe->demodulator_priv; | 393 | struct s5h1420_state* state = fe->demodulator_priv; |
377 | 394 | ||
378 | u8 val = 0xff - s5h1420_readreg(state, 0x15); | 395 | u8 val = s5h1420_readreg(state, 0x15); |
379 | 396 | ||
380 | return (int) ((val << 8) | val); | 397 | *strength = (u16) ((val << 8) | val); |
398 | |||
399 | return 0; | ||
381 | } | 400 | } |
382 | 401 | ||
383 | static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | 402 | static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) |
@@ -386,7 +405,10 @@ static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | |||
386 | 405 | ||
387 | s5h1420_writereg(state, 0x46, 0x1f); | 406 | s5h1420_writereg(state, 0x46, 0x1f); |
388 | mdelay(25); | 407 | mdelay(25); |
389 | return (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47); | 408 | |
409 | *ucblocks = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47); | ||
410 | |||
411 | return 0; | ||
390 | } | 412 | } |
391 | 413 | ||
392 | static void s5h1420_reset(struct s5h1420_state* state) | 414 | static void s5h1420_reset(struct s5h1420_state* state) |
@@ -396,11 +418,12 @@ static void s5h1420_reset(struct s5h1420_state* state) | |||
396 | udelay(10); | 418 | udelay(10); |
397 | } | 419 | } |
398 | 420 | ||
399 | static void s5h1420_setsymbolrate(struct s5h1420_state* state, struct dvb_frontend_parameters *p) | 421 | static void s5h1420_setsymbolrate(struct s5h1420_state* state, |
422 | struct dvb_frontend_parameters *p) | ||
400 | { | 423 | { |
401 | u64 val; | 424 | u64 val; |
402 | 425 | ||
403 | val = (p->u.qpsk.symbol_rate / 1000) * (1<<24); | 426 | val = ((u64) p->u.qpsk.symbol_rate / 1000ULL) * (1ULL<<24); |
404 | if (p->u.qpsk.symbol_rate <= 21000000) { | 427 | if (p->u.qpsk.symbol_rate <= 21000000) { |
405 | val *= 2; | 428 | val *= 2; |
406 | } | 429 | } |
@@ -415,7 +438,7 @@ static void s5h1420_setsymbolrate(struct s5h1420_state* state, struct dvb_fronte | |||
415 | 438 | ||
416 | static u32 s5h1420_getsymbolrate(struct s5h1420_state* state) | 439 | static u32 s5h1420_getsymbolrate(struct s5h1420_state* state) |
417 | { | 440 | { |
418 | u64 val; | 441 | u64 val = 0; |
419 | int sampling = 2; | 442 | int sampling = 2; |
420 | 443 | ||
421 | if (s5h1420_readreg(state, 0x05) & 0x2) | 444 | if (s5h1420_readreg(state, 0x05) & 0x2) |
@@ -427,10 +450,10 @@ static u32 s5h1420_getsymbolrate(struct s5h1420_state* state) | |||
427 | val |= s5h1420_readreg(state, 0x13); | 450 | val |= s5h1420_readreg(state, 0x13); |
428 | s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7); | 451 | s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7); |
429 | 452 | ||
430 | val *= (state->fclk / 1000); | 453 | val *= (state->fclk / 1000ULL); |
431 | do_div(val, ((1<<24) * sampling)); | 454 | do_div(val, ((1<<24) * sampling)); |
432 | 455 | ||
433 | return (u32) (val * 1000); | 456 | return (u32) (val * 1000ULL); |
434 | } | 457 | } |
435 | 458 | ||
436 | static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset) | 459 | static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset) |
@@ -463,46 +486,55 @@ static int s5h1420_getfreqoffset(struct s5h1420_state* state) | |||
463 | 486 | ||
464 | /* remember freqoffset is in kHz, but the chip wants the offset in Hz, so | 487 | /* remember freqoffset is in kHz, but the chip wants the offset in Hz, so |
465 | * divide fclk by 1000000 to get the correct value. */ | 488 | * divide fclk by 1000000 to get the correct value. */ |
466 | val = - ((val * (state->fclk/1000000)) / (1<<24)); | 489 | val = (((-val) * (state->fclk/1000000)) / (1<<24)); |
467 | 490 | ||
468 | return val; | 491 | return val; |
469 | } | 492 | } |
470 | 493 | ||
471 | static void s5h1420_setfec(struct s5h1420_state* state, struct dvb_frontend_parameters *p) | 494 | static void s5h1420_setfec_inversion(struct s5h1420_state* state, |
495 | struct dvb_frontend_parameters *p) | ||
472 | { | 496 | { |
497 | u8 inversion = 0; | ||
498 | |||
499 | if (p->inversion == INVERSION_OFF) { | ||
500 | inversion = state->config->invert ? 0x08 : 0; | ||
501 | } else if (p->inversion == INVERSION_ON) { | ||
502 | inversion = state->config->invert ? 0 : 0x08; | ||
503 | } | ||
504 | |||
473 | if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) { | 505 | if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) { |
474 | s5h1420_writereg(state, 0x31, 0x00); | ||
475 | s5h1420_writereg(state, 0x30, 0x3f); | 506 | s5h1420_writereg(state, 0x30, 0x3f); |
507 | s5h1420_writereg(state, 0x31, 0x00 | inversion); | ||
476 | } else { | 508 | } else { |
477 | switch(p->u.qpsk.fec_inner) { | 509 | switch(p->u.qpsk.fec_inner) { |
478 | case FEC_1_2: | 510 | case FEC_1_2: |
479 | s5h1420_writereg(state, 0x31, 0x10); | ||
480 | s5h1420_writereg(state, 0x30, 0x01); | 511 | s5h1420_writereg(state, 0x30, 0x01); |
512 | s5h1420_writereg(state, 0x31, 0x10 | inversion); | ||
481 | break; | 513 | break; |
482 | 514 | ||
483 | case FEC_2_3: | 515 | case FEC_2_3: |
484 | s5h1420_writereg(state, 0x31, 0x11); | ||
485 | s5h1420_writereg(state, 0x30, 0x02); | 516 | s5h1420_writereg(state, 0x30, 0x02); |
517 | s5h1420_writereg(state, 0x31, 0x11 | inversion); | ||
486 | break; | 518 | break; |
487 | 519 | ||
488 | case FEC_3_4: | 520 | case FEC_3_4: |
489 | s5h1420_writereg(state, 0x31, 0x12); | ||
490 | s5h1420_writereg(state, 0x30, 0x04); | 521 | s5h1420_writereg(state, 0x30, 0x04); |
491 | break; | 522 | s5h1420_writereg(state, 0x31, 0x12 | inversion); |
523 | break; | ||
492 | 524 | ||
493 | case FEC_5_6: | 525 | case FEC_5_6: |
494 | s5h1420_writereg(state, 0x31, 0x13); | ||
495 | s5h1420_writereg(state, 0x30, 0x08); | 526 | s5h1420_writereg(state, 0x30, 0x08); |
527 | s5h1420_writereg(state, 0x31, 0x13 | inversion); | ||
496 | break; | 528 | break; |
497 | 529 | ||
498 | case FEC_6_7: | 530 | case FEC_6_7: |
499 | s5h1420_writereg(state, 0x31, 0x14); | ||
500 | s5h1420_writereg(state, 0x30, 0x10); | 531 | s5h1420_writereg(state, 0x30, 0x10); |
532 | s5h1420_writereg(state, 0x31, 0x14 | inversion); | ||
501 | break; | 533 | break; |
502 | 534 | ||
503 | case FEC_7_8: | 535 | case FEC_7_8: |
504 | s5h1420_writereg(state, 0x31, 0x15); | ||
505 | s5h1420_writereg(state, 0x30, 0x20); | 536 | s5h1420_writereg(state, 0x30, 0x20); |
537 | s5h1420_writereg(state, 0x31, 0x15 | inversion); | ||
506 | break; | 538 | break; |
507 | 539 | ||
508 | default: | 540 | default: |
@@ -536,22 +568,6 @@ static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state) | |||
536 | return FEC_NONE; | 568 | return FEC_NONE; |
537 | } | 569 | } |
538 | 570 | ||
539 | static void s5h1420_setinversion(struct s5h1420_state* state, struct dvb_frontend_parameters *p) | ||
540 | { | ||
541 | if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) { | ||
542 | s5h1420_writereg(state, 0x31, 0x00); | ||
543 | s5h1420_writereg(state, 0x30, 0x3f); | ||
544 | } else { | ||
545 | u8 tmp = s5h1420_readreg(state, 0x31) & 0xf7; | ||
546 | tmp |= 0x10; | ||
547 | |||
548 | if (p->inversion == INVERSION_ON) | ||
549 | tmp |= 0x80; | ||
550 | |||
551 | s5h1420_writereg(state, 0x31, tmp); | ||
552 | } | ||
553 | } | ||
554 | |||
555 | static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state) | 571 | static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state) |
556 | { | 572 | { |
557 | if (s5h1420_readreg(state, 0x32) & 0x08) | 573 | if (s5h1420_readreg(state, 0x32) & 0x08) |
@@ -560,35 +576,35 @@ static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state) | |||
560 | return INVERSION_OFF; | 576 | return INVERSION_OFF; |
561 | } | 577 | } |
562 | 578 | ||
563 | static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | 579 | static int s5h1420_set_frontend(struct dvb_frontend* fe, |
580 | struct dvb_frontend_parameters *p) | ||
564 | { | 581 | { |
565 | struct s5h1420_state* state = fe->demodulator_priv; | 582 | struct s5h1420_state* state = fe->demodulator_priv; |
566 | u32 frequency_delta; | 583 | int frequency_delta; |
567 | struct dvb_frontend_tune_settings fesettings; | 584 | struct dvb_frontend_tune_settings fesettings; |
585 | u32 tmp; | ||
568 | 586 | ||
569 | /* check if we should do a fast-tune */ | 587 | /* check if we should do a fast-tune */ |
570 | memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters)); | 588 | memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters)); |
571 | s5h1420_get_tune_settings(fe, &fesettings); | 589 | s5h1420_get_tune_settings(fe, &fesettings); |
572 | frequency_delta = p->frequency - state->tunedfreq; | 590 | frequency_delta = p->frequency - state->tunedfreq; |
573 | if ((frequency_delta > -fesettings.max_drift) && (frequency_delta < fesettings.max_drift) && | 591 | if ((frequency_delta > -fesettings.max_drift) && |
592 | (frequency_delta < fesettings.max_drift) && | ||
574 | (frequency_delta != 0) && | 593 | (frequency_delta != 0) && |
575 | (state->fec_inner == p->u.qpsk.fec_inner) && | 594 | (state->fec_inner == p->u.qpsk.fec_inner) && |
576 | (state->symbol_rate == p->u.qpsk.symbol_rate)) { | 595 | (state->symbol_rate == p->u.qpsk.symbol_rate)) { |
577 | 596 | ||
578 | s5h1420_setfreqoffset(state, frequency_delta); | 597 | if (state->config->pll_set) { |
598 | s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1); | ||
599 | state->config->pll_set(fe, p, &tmp); | ||
600 | s5h1420_setfreqoffset(state, p->frequency - tmp); | ||
601 | } | ||
579 | return 0; | 602 | return 0; |
580 | } | 603 | } |
581 | 604 | ||
582 | /* first of all, software reset */ | 605 | /* first of all, software reset */ |
583 | s5h1420_reset(state); | 606 | s5h1420_reset(state); |
584 | 607 | ||
585 | /* set tuner PLL */ | ||
586 | if (state->config->pll_set) { | ||
587 | s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1); | ||
588 | state->config->pll_set(fe, p, &state->tunedfreq); | ||
589 | s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe); | ||
590 | } | ||
591 | |||
592 | /* set s5h1420 fclk PLL according to desired symbol rate */ | 608 | /* set s5h1420 fclk PLL according to desired symbol rate */ |
593 | if (p->u.qpsk.symbol_rate > 28000000) { | 609 | if (p->u.qpsk.symbol_rate > 28000000) { |
594 | state->fclk = 88000000; | 610 | state->fclk = 88000000; |
@@ -609,8 +625,9 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par | |||
609 | 625 | ||
610 | /* set misc registers */ | 626 | /* set misc registers */ |
611 | s5h1420_writereg(state, 0x02, 0x00); | 627 | s5h1420_writereg(state, 0x02, 0x00); |
628 | s5h1420_writereg(state, 0x06, 0x00); | ||
612 | s5h1420_writereg(state, 0x07, 0xb0); | 629 | s5h1420_writereg(state, 0x07, 0xb0); |
613 | s5h1420_writereg(state, 0x0a, 0x67); | 630 | s5h1420_writereg(state, 0x0a, 0xe7); |
614 | s5h1420_writereg(state, 0x0b, 0x78); | 631 | s5h1420_writereg(state, 0x0b, 0x78); |
615 | s5h1420_writereg(state, 0x0c, 0x48); | 632 | s5h1420_writereg(state, 0x0c, 0x48); |
616 | s5h1420_writereg(state, 0x0d, 0x6b); | 633 | s5h1420_writereg(state, 0x0d, 0x6b); |
@@ -626,21 +643,26 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par | |||
626 | /* start QPSK */ | 643 | /* start QPSK */ |
627 | s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1); | 644 | s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1); |
628 | 645 | ||
629 | /* set the frequency offset to adjust for PLL inaccuracy */ | 646 | /* set tuner PLL */ |
630 | s5h1420_setfreqoffset(state, p->frequency - state->tunedfreq); | 647 | if (state->config->pll_set) { |
648 | s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1); | ||
649 | state->config->pll_set(fe, p, &tmp); | ||
650 | s5h1420_setfreqoffset(state, 0); | ||
651 | } | ||
631 | 652 | ||
632 | /* set the reset of the parameters */ | 653 | /* set the reset of the parameters */ |
633 | s5h1420_setsymbolrate(state, p); | 654 | s5h1420_setsymbolrate(state, p); |
634 | s5h1420_setinversion(state, p); | 655 | s5h1420_setfec_inversion(state, p); |
635 | s5h1420_setfec(state, p); | ||
636 | 656 | ||
637 | state->fec_inner = p->u.qpsk.fec_inner; | 657 | state->fec_inner = p->u.qpsk.fec_inner; |
638 | state->symbol_rate = p->u.qpsk.symbol_rate; | 658 | state->symbol_rate = p->u.qpsk.symbol_rate; |
639 | state->postlocked = 0; | 659 | state->postlocked = 0; |
660 | state->tunedfreq = p->frequency; | ||
640 | return 0; | 661 | return 0; |
641 | } | 662 | } |
642 | 663 | ||
643 | static int s5h1420_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | 664 | static int s5h1420_get_frontend(struct dvb_frontend* fe, |
665 | struct dvb_frontend_parameters *p) | ||
644 | { | 666 | { |
645 | struct s5h1420_state* state = fe->demodulator_priv; | 667 | struct s5h1420_state* state = fe->demodulator_priv; |
646 | 668 | ||
@@ -652,7 +674,8 @@ static int s5h1420_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par | |||
652 | return 0; | 674 | return 0; |
653 | } | 675 | } |
654 | 676 | ||
655 | static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) | 677 | static int s5h1420_get_tune_settings(struct dvb_frontend* fe, |
678 | struct dvb_frontend_tune_settings* fesettings) | ||
656 | { | 679 | { |
657 | if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) { | 680 | if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) { |
658 | fesettings->min_delay_ms = 50; | 681 | fesettings->min_delay_ms = 50; |
@@ -717,7 +740,8 @@ static void s5h1420_release(struct dvb_frontend* fe) | |||
717 | 740 | ||
718 | static struct dvb_frontend_ops s5h1420_ops; | 741 | static struct dvb_frontend_ops s5h1420_ops; |
719 | 742 | ||
720 | struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, struct i2c_adapter* i2c) | 743 | struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, |
744 | struct i2c_adapter* i2c) | ||
721 | { | 745 | { |
722 | struct s5h1420_state* state = NULL; | 746 | struct s5h1420_state* state = NULL; |
723 | u8 identity; | 747 | u8 identity; |
diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h index b687fc77ceb3..872028ddf2a2 100644 --- a/drivers/media/dvb/frontends/s5h1420.h +++ b/drivers/media/dvb/frontends/s5h1420.h | |||
@@ -30,6 +30,9 @@ struct s5h1420_config | |||
30 | /* the demodulator's i2c address */ | 30 | /* the demodulator's i2c address */ |
31 | u8 demod_address; | 31 | u8 demod_address; |
32 | 32 | ||
33 | /* does the inversion require inversion? */ | ||
34 | u8 invert:1; | ||
35 | |||
33 | /* PLL maintenance */ | 36 | /* PLL maintenance */ |
34 | int (*pll_init)(struct dvb_frontend* fe); | 37 | int (*pll_init)(struct dvb_frontend* fe); |
35 | int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout); | 38 | int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout); |
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 5552ef501996..43d6c8268642 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c | |||
@@ -480,6 +480,7 @@ static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete | |||
480 | 480 | ||
481 | static struct s5h1420_config s5h1420_config = { | 481 | static struct s5h1420_config s5h1420_config = { |
482 | .demod_address = 0x53, | 482 | .demod_address = 0x53, |
483 | .invert = 1, | ||
483 | .pll_set = s5h1420_pll_set, | 484 | .pll_set = s5h1420_pll_set, |
484 | }; | 485 | }; |
485 | 486 | ||