diff options
Diffstat (limited to 'drivers/media/dvb/frontends/mt312.c')
-rw-r--r-- | drivers/media/dvb/frontends/mt312.c | 151 |
1 files changed, 117 insertions, 34 deletions
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index 1638301fbd6e..081ca3398c76 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | Driver for Zarlink VP310/MT312 Satellite Channel Decoder | 2 | Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder |
3 | 3 | ||
4 | Copyright (C) 2003 Andreas Oberritter <obi@linuxtv.org> | 4 | Copyright (C) 2003 Andreas Oberritter <obi@linuxtv.org> |
5 | Copyright (C) 2008 Matthias Schwarzott <zzam@gentoo.org> | ||
5 | 6 | ||
6 | This program is free software; you can redistribute it and/or modify | 7 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by | 8 | it under the terms of the GNU General Public License as published by |
@@ -43,7 +44,8 @@ struct mt312_state { | |||
43 | struct dvb_frontend frontend; | 44 | struct dvb_frontend frontend; |
44 | 45 | ||
45 | u8 id; | 46 | u8 id; |
46 | u8 frequency; | 47 | unsigned long xtal; |
48 | u8 freq_mult; | ||
47 | }; | 49 | }; |
48 | 50 | ||
49 | static int debug; | 51 | static int debug; |
@@ -53,12 +55,11 @@ static int debug; | |||
53 | printk(KERN_DEBUG "mt312: " args); \ | 55 | printk(KERN_DEBUG "mt312: " args); \ |
54 | } while (0) | 56 | } while (0) |
55 | 57 | ||
56 | #define MT312_SYS_CLK 90000000UL /* 90 MHz */ | ||
57 | #define MT312_LPOWER_SYS_CLK 60000000UL /* 60 MHz */ | ||
58 | #define MT312_PLL_CLK 10000000UL /* 10 MHz */ | 58 | #define MT312_PLL_CLK 10000000UL /* 10 MHz */ |
59 | #define MT312_PLL_CLK_10_111 10111000UL /* 10.111 MHz */ | ||
59 | 60 | ||
60 | static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, | 61 | static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, |
61 | void *buf, const size_t count) | 62 | u8 *buf, const size_t count) |
62 | { | 63 | { |
63 | int ret; | 64 | int ret; |
64 | struct i2c_msg msg[2]; | 65 | struct i2c_msg msg[2]; |
@@ -76,7 +77,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, | |||
76 | ret = i2c_transfer(state->i2c, msg, 2); | 77 | ret = i2c_transfer(state->i2c, msg, 2); |
77 | 78 | ||
78 | if (ret != 2) { | 79 | if (ret != 2) { |
79 | printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret); | 80 | printk(KERN_ERR "%s: ret == %d\n", __func__, ret); |
80 | return -EREMOTEIO; | 81 | return -EREMOTEIO; |
81 | } | 82 | } |
82 | 83 | ||
@@ -84,7 +85,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, | |||
84 | int i; | 85 | int i; |
85 | dprintk("R(%d):", reg & 0x7f); | 86 | dprintk("R(%d):", reg & 0x7f); |
86 | for (i = 0; i < count; i++) | 87 | for (i = 0; i < count; i++) |
87 | printk(" %02x", ((const u8 *) buf)[i]); | 88 | printk(" %02x", buf[i]); |
88 | printk("\n"); | 89 | printk("\n"); |
89 | } | 90 | } |
90 | 91 | ||
@@ -92,7 +93,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, | |||
92 | } | 93 | } |
93 | 94 | ||
94 | static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg, | 95 | static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg, |
95 | const void *src, const size_t count) | 96 | const u8 *src, const size_t count) |
96 | { | 97 | { |
97 | int ret; | 98 | int ret; |
98 | u8 buf[count + 1]; | 99 | u8 buf[count + 1]; |
@@ -102,7 +103,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg, | |||
102 | int i; | 103 | int i; |
103 | dprintk("W(%d):", reg & 0x7f); | 104 | dprintk("W(%d):", reg & 0x7f); |
104 | for (i = 0; i < count; i++) | 105 | for (i = 0; i < count; i++) |
105 | printk(" %02x", ((const u8 *) src)[i]); | 106 | printk(" %02x", src[i]); |
106 | printk("\n"); | 107 | printk("\n"); |
107 | } | 108 | } |
108 | 109 | ||
@@ -117,7 +118,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg, | |||
117 | ret = i2c_transfer(state->i2c, &msg, 1); | 118 | ret = i2c_transfer(state->i2c, &msg, 1); |
118 | 119 | ||
119 | if (ret != 1) { | 120 | if (ret != 1) { |
120 | dprintk("%s: ret == %d\n", __FUNCTION__, ret); | 121 | dprintk("%s: ret == %d\n", __func__, ret); |
121 | return -EREMOTEIO; | 122 | return -EREMOTEIO; |
122 | } | 123 | } |
123 | 124 | ||
@@ -209,7 +210,7 @@ static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr) | |||
209 | dprintk("sym_rat_op=%d dec_ratio=%d\n", | 210 | dprintk("sym_rat_op=%d dec_ratio=%d\n", |
210 | sym_rat_op, dec_ratio); | 211 | sym_rat_op, dec_ratio); |
211 | dprintk("*sr(manual) = %lu\n", | 212 | dprintk("*sr(manual) = %lu\n", |
212 | (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) * | 213 | (((state->xtal * 8192) / (sym_rat_op + 8192)) * |
213 | 2) - dec_ratio); | 214 | 2) - dec_ratio); |
214 | } | 215 | } |
215 | 216 | ||
@@ -242,7 +243,7 @@ static int mt312_initfe(struct dvb_frontend *fe) | |||
242 | 243 | ||
243 | /* wake up */ | 244 | /* wake up */ |
244 | ret = mt312_writereg(state, CONFIG, | 245 | ret = mt312_writereg(state, CONFIG, |
245 | (state->frequency == 60 ? 0x88 : 0x8c)); | 246 | (state->freq_mult == 6 ? 0x88 : 0x8c)); |
246 | if (ret < 0) | 247 | if (ret < 0) |
247 | return ret; | 248 | return ret; |
248 | 249 | ||
@@ -265,12 +266,37 @@ static int mt312_initfe(struct dvb_frontend *fe) | |||
265 | return ret; | 266 | return ret; |
266 | } | 267 | } |
267 | 268 | ||
269 | switch (state->id) { | ||
270 | case ID_ZL10313: | ||
271 | /* enable ADC */ | ||
272 | ret = mt312_writereg(state, GPP_CTRL, 0x80); | ||
273 | if (ret < 0) | ||
274 | return ret; | ||
275 | |||
276 | /* configure ZL10313 for optimal ADC performance */ | ||
277 | buf[0] = 0x80; | ||
278 | buf[1] = 0xB0; | ||
279 | ret = mt312_write(state, HW_CTRL, buf, 2); | ||
280 | if (ret < 0) | ||
281 | return ret; | ||
282 | |||
283 | /* enable MPEG output and ADCs */ | ||
284 | ret = mt312_writereg(state, HW_CTRL, 0x00); | ||
285 | if (ret < 0) | ||
286 | return ret; | ||
287 | |||
288 | ret = mt312_writereg(state, MPEG_CTRL, 0x00); | ||
289 | if (ret < 0) | ||
290 | return ret; | ||
291 | |||
292 | break; | ||
293 | } | ||
294 | |||
268 | /* SYS_CLK */ | 295 | /* SYS_CLK */ |
269 | buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK : | 296 | buf[0] = mt312_div(state->xtal * state->freq_mult * 2, 1000000); |
270 | MT312_SYS_CLK) * 2, 1000000); | ||
271 | 297 | ||
272 | /* DISEQC_RATIO */ | 298 | /* DISEQC_RATIO */ |
273 | buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4); | 299 | buf[1] = mt312_div(state->xtal, 22000 * 4); |
274 | 300 | ||
275 | ret = mt312_write(state, SYS_CLK, buf, sizeof(buf)); | 301 | ret = mt312_write(state, SYS_CLK, buf, sizeof(buf)); |
276 | if (ret < 0) | 302 | if (ret < 0) |
@@ -280,7 +306,17 @@ static int mt312_initfe(struct dvb_frontend *fe) | |||
280 | if (ret < 0) | 306 | if (ret < 0) |
281 | return ret; | 307 | return ret; |
282 | 308 | ||
283 | ret = mt312_writereg(state, OP_CTRL, 0x53); | 309 | /* different MOCLK polarity */ |
310 | switch (state->id) { | ||
311 | case ID_ZL10313: | ||
312 | buf[0] = 0x33; | ||
313 | break; | ||
314 | default: | ||
315 | buf[0] = 0x53; | ||
316 | break; | ||
317 | } | ||
318 | |||
319 | ret = mt312_writereg(state, OP_CTRL, buf[0]); | ||
284 | if (ret < 0) | 320 | if (ret < 0) |
285 | return ret; | 321 | return ret; |
286 | 322 | ||
@@ -323,6 +359,9 @@ static int mt312_send_master_cmd(struct dvb_frontend *fe, | |||
323 | if (ret < 0) | 359 | if (ret < 0) |
324 | return ret; | 360 | return ret; |
325 | 361 | ||
362 | /* is there a better way to wait for message to be transmitted */ | ||
363 | msleep(100); | ||
364 | |||
326 | /* set DISEQC_MODE[2:0] to zero if a return message is expected */ | 365 | /* set DISEQC_MODE[2:0] to zero if a return message is expected */ |
327 | if (c->msg[0] & 0x02) { | 366 | if (c->msg[0] & 0x02) { |
328 | ret = mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40)); | 367 | ret = mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40)); |
@@ -383,11 +422,16 @@ static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v) | |||
383 | { | 422 | { |
384 | struct mt312_state *state = fe->demodulator_priv; | 423 | struct mt312_state *state = fe->demodulator_priv; |
385 | const u8 volt_tab[3] = { 0x00, 0x40, 0x00 }; | 424 | const u8 volt_tab[3] = { 0x00, 0x40, 0x00 }; |
425 | u8 val; | ||
386 | 426 | ||
387 | if (v > SEC_VOLTAGE_OFF) | 427 | if (v > SEC_VOLTAGE_OFF) |
388 | return -EINVAL; | 428 | return -EINVAL; |
389 | 429 | ||
390 | return mt312_writereg(state, DISEQC_MODE, volt_tab[v]); | 430 | val = volt_tab[v]; |
431 | if (state->config->voltage_inverted) | ||
432 | val ^= 0x40; | ||
433 | |||
434 | return mt312_writereg(state, DISEQC_MODE, val); | ||
391 | } | 435 | } |
392 | 436 | ||
393 | static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s) | 437 | static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s) |
@@ -463,7 +507,7 @@ static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr) | |||
463 | int ret; | 507 | int ret; |
464 | u8 buf[2]; | 508 | u8 buf[2]; |
465 | 509 | ||
466 | ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf)); | 510 | ret = mt312_read(state, M_SNR_H, buf, sizeof(buf)); |
467 | if (ret < 0) | 511 | if (ret < 0) |
468 | return ret; | 512 | return ret; |
469 | 513 | ||
@@ -478,7 +522,7 @@ static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc) | |||
478 | int ret; | 522 | int ret; |
479 | u8 buf[2]; | 523 | u8 buf[2]; |
480 | 524 | ||
481 | ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf)); | 525 | ret = mt312_read(state, RS_UBC_H, buf, sizeof(buf)); |
482 | if (ret < 0) | 526 | if (ret < 0) |
483 | return ret; | 527 | return ret; |
484 | 528 | ||
@@ -499,7 +543,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe, | |||
499 | { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f }; | 543 | { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f }; |
500 | const u8 inv_tab[3] = { 0x00, 0x40, 0x80 }; | 544 | const u8 inv_tab[3] = { 0x00, 0x40, 0x80 }; |
501 | 545 | ||
502 | dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency); | 546 | dprintk("%s: Freq %d\n", __func__, p->frequency); |
503 | 547 | ||
504 | if ((p->frequency < fe->ops.info.frequency_min) | 548 | if ((p->frequency < fe->ops.info.frequency_min) |
505 | || (p->frequency > fe->ops.info.frequency_max)) | 549 | || (p->frequency > fe->ops.info.frequency_max)) |
@@ -532,17 +576,17 @@ static int mt312_set_frontend(struct dvb_frontend *fe, | |||
532 | return ret; | 576 | return ret; |
533 | if (p->u.qpsk.symbol_rate >= 30000000) { | 577 | if (p->u.qpsk.symbol_rate >= 30000000) { |
534 | /* Note that 30MS/s should use 90MHz */ | 578 | /* Note that 30MS/s should use 90MHz */ |
535 | if ((config_val & 0x0c) == 0x08) { | 579 | if (state->freq_mult == 6) { |
536 | /* We are running 60MHz */ | 580 | /* We are running 60MHz */ |
537 | state->frequency = 90; | 581 | state->freq_mult = 9; |
538 | ret = mt312_initfe(fe); | 582 | ret = mt312_initfe(fe); |
539 | if (ret < 0) | 583 | if (ret < 0) |
540 | return ret; | 584 | return ret; |
541 | } | 585 | } |
542 | } else { | 586 | } else { |
543 | if ((config_val & 0x0c) == 0x0C) { | 587 | if (state->freq_mult == 9) { |
544 | /* We are running 90MHz */ | 588 | /* We are running 90MHz */ |
545 | state->frequency = 60; | 589 | state->freq_mult = 6; |
546 | ret = mt312_initfe(fe); | 590 | ret = mt312_initfe(fe); |
547 | if (ret < 0) | 591 | if (ret < 0) |
548 | return ret; | 592 | return ret; |
@@ -551,6 +595,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe, | |||
551 | break; | 595 | break; |
552 | 596 | ||
553 | case ID_MT312: | 597 | case ID_MT312: |
598 | case ID_ZL10313: | ||
554 | break; | 599 | break; |
555 | 600 | ||
556 | default: | 601 | default: |
@@ -616,11 +661,29 @@ static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | |||
616 | { | 661 | { |
617 | struct mt312_state *state = fe->demodulator_priv; | 662 | struct mt312_state *state = fe->demodulator_priv; |
618 | 663 | ||
619 | if (enable) { | 664 | u8 val = 0x00; |
620 | return mt312_writereg(state, GPP_CTRL, 0x40); | 665 | int ret; |
621 | } else { | 666 | |
622 | return mt312_writereg(state, GPP_CTRL, 0x00); | 667 | switch (state->id) { |
668 | case ID_ZL10313: | ||
669 | ret = mt312_readreg(state, GPP_CTRL, &val); | ||
670 | if (ret < 0) | ||
671 | goto error; | ||
672 | |||
673 | /* preserve this bit to not accidently shutdown ADC */ | ||
674 | val &= 0x80; | ||
675 | break; | ||
623 | } | 676 | } |
677 | |||
678 | if (enable) | ||
679 | val |= 0x40; | ||
680 | else | ||
681 | val &= ~0x40; | ||
682 | |||
683 | ret = mt312_writereg(state, GPP_CTRL, val); | ||
684 | |||
685 | error: | ||
686 | return ret; | ||
624 | } | 687 | } |
625 | 688 | ||
626 | static int mt312_sleep(struct dvb_frontend *fe) | 689 | static int mt312_sleep(struct dvb_frontend *fe) |
@@ -634,6 +697,18 @@ static int mt312_sleep(struct dvb_frontend *fe) | |||
634 | if (ret < 0) | 697 | if (ret < 0) |
635 | return ret; | 698 | return ret; |
636 | 699 | ||
700 | if (state->id == ID_ZL10313) { | ||
701 | /* reset ADC */ | ||
702 | ret = mt312_writereg(state, GPP_CTRL, 0x00); | ||
703 | if (ret < 0) | ||
704 | return ret; | ||
705 | |||
706 | /* full shutdown of ADCs, mpeg bus tristated */ | ||
707 | ret = mt312_writereg(state, HW_CTRL, 0x0d); | ||
708 | if (ret < 0) | ||
709 | return ret; | ||
710 | } | ||
711 | |||
637 | ret = mt312_readreg(state, CONFIG, &config); | 712 | ret = mt312_readreg(state, CONFIG, &config); |
638 | if (ret < 0) | 713 | if (ret < 0) |
639 | return ret; | 714 | return ret; |
@@ -661,6 +736,7 @@ static void mt312_release(struct dvb_frontend *fe) | |||
661 | kfree(state); | 736 | kfree(state); |
662 | } | 737 | } |
663 | 738 | ||
739 | #define MT312_SYS_CLK 90000000UL /* 90 MHz */ | ||
664 | static struct dvb_frontend_ops vp310_mt312_ops = { | 740 | static struct dvb_frontend_ops vp310_mt312_ops = { |
665 | 741 | ||
666 | .info = { | 742 | .info = { |
@@ -668,8 +744,8 @@ static struct dvb_frontend_ops vp310_mt312_ops = { | |||
668 | .type = FE_QPSK, | 744 | .type = FE_QPSK, |
669 | .frequency_min = 950000, | 745 | .frequency_min = 950000, |
670 | .frequency_max = 2150000, | 746 | .frequency_max = 2150000, |
671 | .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, | 747 | .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, /* FIXME: adjust freq to real used xtal */ |
672 | .symbol_rate_min = MT312_SYS_CLK / 128, | 748 | .symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */ |
673 | .symbol_rate_max = MT312_SYS_CLK / 2, | 749 | .symbol_rate_max = MT312_SYS_CLK / 2, |
674 | .caps = | 750 | .caps = |
675 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | | 751 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | |
@@ -726,14 +802,21 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config, | |||
726 | switch (state->id) { | 802 | switch (state->id) { |
727 | case ID_VP310: | 803 | case ID_VP310: |
728 | strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S"); | 804 | strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S"); |
729 | state->frequency = 90; | 805 | state->xtal = MT312_PLL_CLK; |
806 | state->freq_mult = 9; | ||
730 | break; | 807 | break; |
731 | case ID_MT312: | 808 | case ID_MT312: |
732 | strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S"); | 809 | strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S"); |
733 | state->frequency = 60; | 810 | state->xtal = MT312_PLL_CLK; |
811 | state->freq_mult = 6; | ||
812 | break; | ||
813 | case ID_ZL10313: | ||
814 | strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S"); | ||
815 | state->xtal = MT312_PLL_CLK_10_111; | ||
816 | state->freq_mult = 9; | ||
734 | break; | 817 | break; |
735 | default: | 818 | default: |
736 | printk(KERN_WARNING "Only Zarlink VP310/MT312" | 819 | printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313" |
737 | " are supported chips.\n"); | 820 | " are supported chips.\n"); |
738 | goto error; | 821 | goto error; |
739 | } | 822 | } |
@@ -749,7 +832,7 @@ EXPORT_SYMBOL(vp310_mt312_attach); | |||
749 | module_param(debug, int, 0644); | 832 | module_param(debug, int, 0644); |
750 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | 833 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); |
751 | 834 | ||
752 | MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver"); | 835 | MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver"); |
753 | MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>"); | 836 | MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>"); |
754 | MODULE_LICENSE("GPL"); | 837 | MODULE_LICENSE("GPL"); |
755 | 838 | ||