diff options
author | Steven Toth <stoth@kernellabs.com> | 2009-05-15 20:01:57 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-06-16 17:21:13 -0400 |
commit | 9e08199770f28b92e5a85052e8c16cde94f9a2c9 (patch) | |
tree | 326535e36ede6c96f0e23466975f8db3915e726e /drivers/media/dvb/frontends/tda10048.c | |
parent | 6ecdf92d211fb37a905fce5d0a8668c831764abc (diff) |
V4L/DVB (11854): TDA10048: Ensure the I/F changes during DVB-T 6/7/8 bandwidth changes.
TDA10048: Ensure the I/F changes during DVB-T 6/7/8 bandwidth changes.
Signed-off-by: Steven Toth <stoth@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/frontends/tda10048.c')
-rw-r--r-- | drivers/media/dvb/frontends/tda10048.c | 184 |
1 files changed, 123 insertions, 61 deletions
diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c index 11be4697cb3d..6707832bdcab 100644 --- a/drivers/media/dvb/frontends/tda10048.c +++ b/drivers/media/dvb/frontends/tda10048.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | NXP TDA10048HN DVB OFDM demodulator driver | 2 | NXP TDA10048HN DVB OFDM demodulator driver |
3 | 3 | ||
4 | Copyright (C) 2008 Steven Toth <stoth@linuxtv.org> | 4 | Copyright (C) 2009 Steven Toth <stoth@kernellabs.com> |
5 | 5 | ||
6 | This program is free software; you can redistribute it and/or modify | 6 | 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 | 7 | it under the terms of the GNU General Public License as published by |
@@ -139,8 +139,8 @@ struct tda10048_state { | |||
139 | 139 | ||
140 | struct i2c_adapter *i2c; | 140 | struct i2c_adapter *i2c; |
141 | 141 | ||
142 | /* configuration settings */ | 142 | /* We'll cache and update the attach config settings */ |
143 | const struct tda10048_config *config; | 143 | struct tda10048_config config; |
144 | struct dvb_frontend frontend; | 144 | struct dvb_frontend frontend; |
145 | 145 | ||
146 | int fwloaded; | 146 | int fwloaded; |
@@ -202,12 +202,24 @@ static struct init_tab { | |||
202 | { TDA10048_CONF_C4_2, 0x04 }, | 202 | { TDA10048_CONF_C4_2, 0x04 }, |
203 | }; | 203 | }; |
204 | 204 | ||
205 | static struct pll_tab { | ||
206 | u32 clk_freq_khz; | ||
207 | u32 if_freq_khz; | ||
208 | u8 m, n, p; | ||
209 | } pll_tab[] = { | ||
210 | { TDA10048_CLK_4000, TDA10048_IF_36130, 10, 0, 0 }, | ||
211 | { TDA10048_CLK_16000, TDA10048_IF_4300, 10, 3, 0 }, | ||
212 | { TDA10048_CLK_16000, TDA10048_IF_4000, 10, 3, 0 }, | ||
213 | { TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 }, | ||
214 | }; | ||
215 | |||
205 | static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data) | 216 | static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data) |
206 | { | 217 | { |
218 | struct tda10048_config *config = &state->config; | ||
207 | int ret; | 219 | int ret; |
208 | u8 buf[] = { reg, data }; | 220 | u8 buf[] = { reg, data }; |
209 | struct i2c_msg msg = { | 221 | struct i2c_msg msg = { |
210 | .addr = state->config->demod_address, | 222 | .addr = config->demod_address, |
211 | .flags = 0, .buf = buf, .len = 2 }; | 223 | .flags = 0, .buf = buf, .len = 2 }; |
212 | 224 | ||
213 | dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data); | 225 | dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data); |
@@ -222,13 +234,14 @@ static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data) | |||
222 | 234 | ||
223 | static u8 tda10048_readreg(struct tda10048_state *state, u8 reg) | 235 | static u8 tda10048_readreg(struct tda10048_state *state, u8 reg) |
224 | { | 236 | { |
237 | struct tda10048_config *config = &state->config; | ||
225 | int ret; | 238 | int ret; |
226 | u8 b0[] = { reg }; | 239 | u8 b0[] = { reg }; |
227 | u8 b1[] = { 0 }; | 240 | u8 b1[] = { 0 }; |
228 | struct i2c_msg msg[] = { | 241 | struct i2c_msg msg[] = { |
229 | { .addr = state->config->demod_address, | 242 | { .addr = config->demod_address, |
230 | .flags = 0, .buf = b0, .len = 1 }, | 243 | .flags = 0, .buf = b0, .len = 1 }, |
231 | { .addr = state->config->demod_address, | 244 | { .addr = config->demod_address, |
232 | .flags = I2C_M_RD, .buf = b1, .len = 1 } }; | 245 | .flags = I2C_M_RD, .buf = b1, .len = 1 } }; |
233 | 246 | ||
234 | dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg); | 247 | dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg); |
@@ -245,6 +258,7 @@ static u8 tda10048_readreg(struct tda10048_state *state, u8 reg) | |||
245 | static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg, | 258 | static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg, |
246 | const u8 *data, u16 len) | 259 | const u8 *data, u16 len) |
247 | { | 260 | { |
261 | struct tda10048_config *config = &state->config; | ||
248 | int ret = -EREMOTEIO; | 262 | int ret = -EREMOTEIO; |
249 | struct i2c_msg msg; | 263 | struct i2c_msg msg; |
250 | u8 *buf; | 264 | u8 *buf; |
@@ -260,7 +274,7 @@ static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg, | |||
260 | *buf = reg; | 274 | *buf = reg; |
261 | memcpy(buf + 1, data, len); | 275 | memcpy(buf + 1, data, len); |
262 | 276 | ||
263 | msg.addr = state->config->demod_address; | 277 | msg.addr = config->demod_address; |
264 | msg.flags = 0; | 278 | msg.flags = 0; |
265 | msg.buf = buf; | 279 | msg.buf = buf; |
266 | msg.len = len + 1; | 280 | msg.len = len + 1; |
@@ -411,47 +425,47 @@ static int tda10048_set_bandwidth(struct dvb_frontend *fe, | |||
411 | return 0; | 425 | return 0; |
412 | } | 426 | } |
413 | 427 | ||
414 | static int tda10048_set_pll(struct dvb_frontend *fe) | 428 | static int tda10048_set_if(struct dvb_frontend *fe, enum fe_bandwidth bw) |
415 | { | 429 | { |
416 | struct tda10048_state *state = fe->demodulator_priv; | 430 | struct tda10048_state *state = fe->demodulator_priv; |
417 | int ret = 0; | 431 | struct tda10048_config *config = &state->config; |
432 | int i; | ||
433 | u32 if_freq_khz; | ||
418 | 434 | ||
419 | dprintk(1, "%s()\n", __func__); | 435 | dprintk(1, "%s(bw = %d)\n", __func__, bw); |
420 | 436 | ||
421 | if ((state->config->clk_freq_khz == TDA10048_CLK_4000) && | 437 | /* based on target bandwidth and clk we calculate pll factors */ |
422 | (state->config->if_freq_khz == TDA10048_IF_36130)) { | 438 | switch (bw) { |
423 | state->freq_if_hz = TDA10048_IF_36130 * 1000; | 439 | case BANDWIDTH_6_MHZ: |
424 | state->xtal_hz = TDA10048_CLK_4000 * 1000; | 440 | if_freq_khz = config->dtv6_if_freq_khz; |
425 | state->pll_mfactor = 10; | 441 | break; |
426 | state->pll_nfactor = 0; | 442 | case BANDWIDTH_7_MHZ: |
427 | state->pll_pfactor = 0; | 443 | if_freq_khz = config->dtv7_if_freq_khz; |
428 | } else | 444 | break; |
429 | if ((state->config->clk_freq_khz == TDA10048_CLK_16000) && | 445 | case BANDWIDTH_8_MHZ: |
430 | (state->config->if_freq_khz == TDA10048_IF_4300)) { | 446 | if_freq_khz = config->dtv8_if_freq_khz; |
431 | state->freq_if_hz = TDA10048_IF_4300 * 1000; | 447 | break; |
432 | state->xtal_hz = TDA10048_CLK_16000 * 1000; | 448 | default: |
433 | state->pll_mfactor = 10; | 449 | printk(KERN_ERR "%s() no default\n", __func__); |
434 | state->pll_nfactor = 3; | 450 | return -EINVAL; |
435 | state->pll_pfactor = 0; | 451 | } |
436 | } else | 452 | |
437 | if ((state->config->clk_freq_khz == TDA10048_CLK_16000) && | 453 | for (i = 0; i < ARRAY_SIZE(pll_tab); i++) { |
438 | (state->config->if_freq_khz == TDA10048_IF_4000)) { | 454 | if ((pll_tab[i].clk_freq_khz == config->clk_freq_khz) && |
439 | state->freq_if_hz = TDA10048_IF_4000 * 1000; | 455 | (pll_tab[i].if_freq_khz == if_freq_khz)) { |
440 | state->xtal_hz = TDA10048_CLK_16000 * 1000; | 456 | |
441 | state->pll_mfactor = 10; | 457 | state->freq_if_hz = pll_tab[i].if_freq_khz * 1000; |
442 | state->pll_nfactor = 3; | 458 | state->xtal_hz = pll_tab[i].clk_freq_khz * 1000; |
443 | state->pll_pfactor = 0; | 459 | state->pll_mfactor = pll_tab[i].m; |
444 | } else | 460 | state->pll_nfactor = pll_tab[i].n; |
445 | if ((state->config->clk_freq_khz == TDA10048_CLK_16000) && | 461 | state->pll_pfactor = pll_tab[i].p; |
446 | (state->config->if_freq_khz == TDA10048_IF_36130)) { | 462 | break; |
447 | state->freq_if_hz = TDA10048_IF_36130 * 1000; | 463 | } |
448 | state->xtal_hz = TDA10048_CLK_16000 * 1000; | 464 | } |
449 | state->pll_mfactor = 10; | 465 | if (i == ARRAY_SIZE(pll_tab)) { |
450 | state->pll_nfactor = 3; | 466 | printk(KERN_ERR "%s() Incorrect attach settings\n", |
451 | state->pll_pfactor = 0; | 467 | __func__); |
452 | } else { | 468 | return -EINVAL; |
453 | printk(KERN_ERR "%s() Incorrect attach settings\n", __func__); | ||
454 | ret = -EINVAL; | ||
455 | } | 469 | } |
456 | 470 | ||
457 | dprintk(1, "- freq_if_hz = %d\n", state->freq_if_hz); | 471 | dprintk(1, "- freq_if_hz = %d\n", state->freq_if_hz); |
@@ -466,22 +480,21 @@ static int tda10048_set_pll(struct dvb_frontend *fe) | |||
466 | state->sample_freq /= (state->pll_pfactor + 4); | 480 | state->sample_freq /= (state->pll_pfactor + 4); |
467 | dprintk(1, "- sample_freq = %d\n", state->sample_freq); | 481 | dprintk(1, "- sample_freq = %d\n", state->sample_freq); |
468 | 482 | ||
469 | tda10048_set_phy2(fe, state->sample_freq, | 483 | /* Update the I/F */ |
470 | state->config->if_freq_khz * 1000); | 484 | tda10048_set_phy2(fe, state->sample_freq, state->freq_if_hz); |
471 | tda10048_set_wref(fe, state->sample_freq, state->bandwidth); | ||
472 | tda10048_set_invwref(fe, state->sample_freq, state->bandwidth); | ||
473 | 485 | ||
474 | return ret; | 486 | return 0; |
475 | } | 487 | } |
476 | 488 | ||
477 | static int tda10048_firmware_upload(struct dvb_frontend *fe) | 489 | static int tda10048_firmware_upload(struct dvb_frontend *fe) |
478 | { | 490 | { |
479 | struct tda10048_state *state = fe->demodulator_priv; | 491 | struct tda10048_state *state = fe->demodulator_priv; |
492 | struct tda10048_config *config = &state->config; | ||
480 | const struct firmware *fw; | 493 | const struct firmware *fw; |
481 | int ret; | 494 | int ret; |
482 | int pos = 0; | 495 | int pos = 0; |
483 | int cnt; | 496 | int cnt; |
484 | u8 wlen = state->config->fwbulkwritelen; | 497 | u8 wlen = config->fwbulkwritelen; |
485 | 498 | ||
486 | if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50)) | 499 | if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50)) |
487 | wlen = TDA10048_BULKWRITE_200; | 500 | wlen = TDA10048_BULKWRITE_200; |
@@ -687,9 +700,10 @@ static int tda10048_get_tps(struct tda10048_state *state, | |||
687 | static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | 700 | static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) |
688 | { | 701 | { |
689 | struct tda10048_state *state = fe->demodulator_priv; | 702 | struct tda10048_state *state = fe->demodulator_priv; |
703 | struct tda10048_config *config = &state->config; | ||
690 | dprintk(1, "%s(%d)\n", __func__, enable); | 704 | dprintk(1, "%s(%d)\n", __func__, enable); |
691 | 705 | ||
692 | if (state->config->disable_gate_access) | 706 | if (config->disable_gate_access) |
693 | return 0; | 707 | return 0; |
694 | 708 | ||
695 | if (enable) | 709 | if (enable) |
@@ -729,8 +743,11 @@ static int tda10048_set_frontend(struct dvb_frontend *fe, | |||
729 | 743 | ||
730 | dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency); | 744 | dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency); |
731 | 745 | ||
732 | if (p->u.ofdm.bandwidth != state->bandwidth) | 746 | /* Update the I/F pll's if the bandwidth changes */ |
747 | if (p->u.ofdm.bandwidth != state->bandwidth) { | ||
748 | tda10048_set_if(fe, p->u.ofdm.bandwidth); | ||
733 | tda10048_set_bandwidth(fe, p->u.ofdm.bandwidth); | 749 | tda10048_set_bandwidth(fe, p->u.ofdm.bandwidth); |
750 | } | ||
734 | 751 | ||
735 | if (fe->ops.tuner_ops.set_params) { | 752 | if (fe->ops.tuner_ops.set_params) { |
736 | 753 | ||
@@ -753,6 +770,7 @@ static int tda10048_set_frontend(struct dvb_frontend *fe, | |||
753 | static int tda10048_init(struct dvb_frontend *fe) | 770 | static int tda10048_init(struct dvb_frontend *fe) |
754 | { | 771 | { |
755 | struct tda10048_state *state = fe->demodulator_priv; | 772 | struct tda10048_state *state = fe->demodulator_priv; |
773 | struct tda10048_config *config = &state->config; | ||
756 | int ret = 0, i; | 774 | int ret = 0, i; |
757 | 775 | ||
758 | dprintk(1, "%s()\n", __func__); | 776 | dprintk(1, "%s()\n", __func__); |
@@ -765,15 +783,13 @@ static int tda10048_init(struct dvb_frontend *fe) | |||
765 | ret = tda10048_firmware_upload(fe); | 783 | ret = tda10048_firmware_upload(fe); |
766 | 784 | ||
767 | /* Set either serial or parallel */ | 785 | /* Set either serial or parallel */ |
768 | tda10048_output_mode(fe, state->config->output_mode); | 786 | tda10048_output_mode(fe, config->output_mode); |
769 | 787 | ||
770 | /* Set inversion */ | 788 | /* Set inversion */ |
771 | tda10048_set_inversion(fe, state->config->inversion); | 789 | tda10048_set_inversion(fe, config->inversion); |
772 | 790 | ||
773 | /* Establish default PLL values */ | 791 | /* Establish default RF values */ |
774 | tda10048_set_pll(fe); | 792 | tda10048_set_if(fe, BANDWIDTH_8_MHZ); |
775 | |||
776 | /* Establish default bandwidth */ | ||
777 | tda10048_set_bandwidth(fe, BANDWIDTH_8_MHZ); | 793 | tda10048_set_bandwidth(fe, BANDWIDTH_8_MHZ); |
778 | 794 | ||
779 | /* Ensure we leave the gate closed */ | 795 | /* Ensure we leave the gate closed */ |
@@ -1027,6 +1043,45 @@ static void tda10048_release(struct dvb_frontend *fe) | |||
1027 | kfree(state); | 1043 | kfree(state); |
1028 | } | 1044 | } |
1029 | 1045 | ||
1046 | static void tda10048_establish_defaults(struct dvb_frontend *fe) | ||
1047 | { | ||
1048 | struct tda10048_state *state = fe->demodulator_priv; | ||
1049 | struct tda10048_config *config = &state->config; | ||
1050 | |||
1051 | /* Validate/default the config */ | ||
1052 | if (config->dtv6_if_freq_khz == 0) { | ||
1053 | config->dtv6_if_freq_khz = TDA10048_IF_4300; | ||
1054 | printk(KERN_WARNING "%s() tda10048_config.dtv6_if_freq_khz " | ||
1055 | "is not set (defaulting to %d)\n", | ||
1056 | __func__, | ||
1057 | config->dtv6_if_freq_khz); | ||
1058 | } | ||
1059 | |||
1060 | if (config->dtv7_if_freq_khz == 0) { | ||
1061 | config->dtv7_if_freq_khz = TDA10048_IF_4300; | ||
1062 | printk(KERN_WARNING "%s() tda10048_config.dtv7_if_freq_khz " | ||
1063 | "is not set (defaulting to %d)\n", | ||
1064 | __func__, | ||
1065 | config->dtv7_if_freq_khz); | ||
1066 | } | ||
1067 | |||
1068 | if (config->dtv8_if_freq_khz == 0) { | ||
1069 | config->dtv8_if_freq_khz = TDA10048_IF_4300; | ||
1070 | printk(KERN_WARNING "%s() tda10048_config.dtv8_if_freq_khz " | ||
1071 | "is not set (defaulting to %d)\n", | ||
1072 | __func__, | ||
1073 | config->dtv8_if_freq_khz); | ||
1074 | } | ||
1075 | |||
1076 | if (config->clk_freq_khz == 0) { | ||
1077 | config->clk_freq_khz = TDA10048_CLK_16000; | ||
1078 | printk(KERN_WARNING "%s() tda10048_config.clk_freq_khz " | ||
1079 | "is not set (defaulting to %d)\n", | ||
1080 | __func__, | ||
1081 | config->clk_freq_khz); | ||
1082 | } | ||
1083 | } | ||
1084 | |||
1030 | static struct dvb_frontend_ops tda10048_ops; | 1085 | static struct dvb_frontend_ops tda10048_ops; |
1031 | 1086 | ||
1032 | struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, | 1087 | struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, |
@@ -1041,8 +1096,8 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, | |||
1041 | if (state == NULL) | 1096 | if (state == NULL) |
1042 | goto error; | 1097 | goto error; |
1043 | 1098 | ||
1044 | /* setup the state */ | 1099 | /* setup the state and clone the config */ |
1045 | state->config = config; | 1100 | memcpy(&state->config, config, sizeof(*config)); |
1046 | state->i2c = i2c; | 1101 | state->i2c = i2c; |
1047 | state->fwloaded = 0; | 1102 | state->fwloaded = 0; |
1048 | state->bandwidth = BANDWIDTH_8_MHZ; | 1103 | state->bandwidth = BANDWIDTH_8_MHZ; |
@@ -1056,8 +1111,15 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, | |||
1056 | sizeof(struct dvb_frontend_ops)); | 1111 | sizeof(struct dvb_frontend_ops)); |
1057 | state->frontend.demodulator_priv = state; | 1112 | state->frontend.demodulator_priv = state; |
1058 | 1113 | ||
1114 | /* Establish any defaults the the user didn't pass */ | ||
1115 | tda10048_establish_defaults(&state->frontend); | ||
1116 | |||
1059 | /* Set the xtal and freq defaults */ | 1117 | /* Set the xtal and freq defaults */ |
1060 | if (tda10048_set_pll(&state->frontend) != 0) | 1118 | if (tda10048_set_if(&state->frontend, BANDWIDTH_8_MHZ) != 0) |
1119 | goto error; | ||
1120 | |||
1121 | /* Default bandwidth */ | ||
1122 | if (tda10048_set_bandwidth(&state->frontend, BANDWIDTH_8_MHZ) != 0) | ||
1061 | goto error; | 1123 | goto error; |
1062 | 1124 | ||
1063 | /* Leave the gate closed */ | 1125 | /* Leave the gate closed */ |