diff options
Diffstat (limited to 'drivers/media/dvb/frontends/tda10048.c')
-rw-r--r-- | drivers/media/dvb/frontends/tda10048.c | 312 |
1 files changed, 298 insertions, 14 deletions
diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c index 2a8bbcd44cd0..4302c563a6b8 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 |
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/string.h> | 25 | #include <linux/string.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <asm/div64.h> | ||
28 | #include "dvb_frontend.h" | 29 | #include "dvb_frontend.h" |
29 | #include "dvb_math.h" | 30 | #include "dvb_math.h" |
30 | #include "tda10048.h" | 31 | #include "tda10048.h" |
@@ -138,11 +139,20 @@ struct tda10048_state { | |||
138 | 139 | ||
139 | struct i2c_adapter *i2c; | 140 | struct i2c_adapter *i2c; |
140 | 141 | ||
141 | /* configuration settings */ | 142 | /* We'll cache and update the attach config settings */ |
142 | const struct tda10048_config *config; | 143 | struct tda10048_config config; |
143 | struct dvb_frontend frontend; | 144 | struct dvb_frontend frontend; |
144 | 145 | ||
145 | int fwloaded; | 146 | int fwloaded; |
147 | |||
148 | u32 freq_if_hz; | ||
149 | u32 xtal_hz; | ||
150 | u32 pll_mfactor; | ||
151 | u32 pll_nfactor; | ||
152 | u32 pll_pfactor; | ||
153 | u32 sample_freq; | ||
154 | |||
155 | enum fe_bandwidth bandwidth; | ||
146 | }; | 156 | }; |
147 | 157 | ||
148 | static struct init_tab { | 158 | static struct init_tab { |
@@ -192,12 +202,26 @@ static struct init_tab { | |||
192 | { TDA10048_CONF_C4_2, 0x04 }, | 202 | { TDA10048_CONF_C4_2, 0x04 }, |
193 | }; | 203 | }; |
194 | 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_3300, 10, 3, 0 }, | ||
212 | { TDA10048_CLK_16000, TDA10048_IF_3500, 10, 3, 0 }, | ||
213 | { TDA10048_CLK_16000, TDA10048_IF_4000, 10, 3, 0 }, | ||
214 | { TDA10048_CLK_16000, TDA10048_IF_4300, 10, 3, 0 }, | ||
215 | { TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 }, | ||
216 | }; | ||
217 | |||
195 | static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data) | 218 | static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data) |
196 | { | 219 | { |
220 | struct tda10048_config *config = &state->config; | ||
197 | int ret; | 221 | int ret; |
198 | u8 buf[] = { reg, data }; | 222 | u8 buf[] = { reg, data }; |
199 | struct i2c_msg msg = { | 223 | struct i2c_msg msg = { |
200 | .addr = state->config->demod_address, | 224 | .addr = config->demod_address, |
201 | .flags = 0, .buf = buf, .len = 2 }; | 225 | .flags = 0, .buf = buf, .len = 2 }; |
202 | 226 | ||
203 | dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data); | 227 | dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data); |
@@ -212,13 +236,14 @@ static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data) | |||
212 | 236 | ||
213 | static u8 tda10048_readreg(struct tda10048_state *state, u8 reg) | 237 | static u8 tda10048_readreg(struct tda10048_state *state, u8 reg) |
214 | { | 238 | { |
239 | struct tda10048_config *config = &state->config; | ||
215 | int ret; | 240 | int ret; |
216 | u8 b0[] = { reg }; | 241 | u8 b0[] = { reg }; |
217 | u8 b1[] = { 0 }; | 242 | u8 b1[] = { 0 }; |
218 | struct i2c_msg msg[] = { | 243 | struct i2c_msg msg[] = { |
219 | { .addr = state->config->demod_address, | 244 | { .addr = config->demod_address, |
220 | .flags = 0, .buf = b0, .len = 1 }, | 245 | .flags = 0, .buf = b0, .len = 1 }, |
221 | { .addr = state->config->demod_address, | 246 | { .addr = config->demod_address, |
222 | .flags = I2C_M_RD, .buf = b1, .len = 1 } }; | 247 | .flags = I2C_M_RD, .buf = b1, .len = 1 } }; |
223 | 248 | ||
224 | dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg); | 249 | dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg); |
@@ -235,6 +260,7 @@ static u8 tda10048_readreg(struct tda10048_state *state, u8 reg) | |||
235 | static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg, | 260 | static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg, |
236 | const u8 *data, u16 len) | 261 | const u8 *data, u16 len) |
237 | { | 262 | { |
263 | struct tda10048_config *config = &state->config; | ||
238 | int ret = -EREMOTEIO; | 264 | int ret = -EREMOTEIO; |
239 | struct i2c_msg msg; | 265 | struct i2c_msg msg; |
240 | u8 *buf; | 266 | u8 *buf; |
@@ -250,7 +276,7 @@ static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg, | |||
250 | *buf = reg; | 276 | *buf = reg; |
251 | memcpy(buf + 1, data, len); | 277 | memcpy(buf + 1, data, len); |
252 | 278 | ||
253 | msg.addr = state->config->demod_address; | 279 | msg.addr = config->demod_address; |
254 | msg.flags = 0; | 280 | msg.flags = 0; |
255 | msg.buf = buf; | 281 | msg.buf = buf; |
256 | msg.len = len + 1; | 282 | msg.len = len + 1; |
@@ -271,14 +297,206 @@ error: | |||
271 | return ret; | 297 | return ret; |
272 | } | 298 | } |
273 | 299 | ||
300 | static int tda10048_set_phy2(struct dvb_frontend *fe, u32 sample_freq_hz, | ||
301 | u32 if_hz) | ||
302 | { | ||
303 | struct tda10048_state *state = fe->demodulator_priv; | ||
304 | u64 t; | ||
305 | |||
306 | dprintk(1, "%s()\n", __func__); | ||
307 | |||
308 | if (sample_freq_hz == 0) | ||
309 | return -EINVAL; | ||
310 | |||
311 | if (if_hz < (sample_freq_hz / 2)) { | ||
312 | /* PHY2 = (if2/fs) * 2^15 */ | ||
313 | t = if_hz; | ||
314 | t *= 10; | ||
315 | t *= 32768; | ||
316 | do_div(t, sample_freq_hz); | ||
317 | t += 5; | ||
318 | do_div(t, 10); | ||
319 | } else { | ||
320 | /* PHY2 = ((IF1-fs)/fs) * 2^15 */ | ||
321 | t = sample_freq_hz - if_hz; | ||
322 | t *= 10; | ||
323 | t *= 32768; | ||
324 | do_div(t, sample_freq_hz); | ||
325 | t += 5; | ||
326 | do_div(t, 10); | ||
327 | t = ~t + 1; | ||
328 | } | ||
329 | |||
330 | tda10048_writereg(state, TDA10048_FREQ_PHY2_LSB, (u8)t); | ||
331 | tda10048_writereg(state, TDA10048_FREQ_PHY2_MSB, (u8)(t >> 8)); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int tda10048_set_wref(struct dvb_frontend *fe, u32 sample_freq_hz, | ||
337 | u32 bw) | ||
338 | { | ||
339 | struct tda10048_state *state = fe->demodulator_priv; | ||
340 | u64 t, z; | ||
341 | u32 b = 8000000; | ||
342 | |||
343 | dprintk(1, "%s()\n", __func__); | ||
344 | |||
345 | if (sample_freq_hz == 0) | ||
346 | return -EINVAL; | ||
347 | |||
348 | if (bw == BANDWIDTH_6_MHZ) | ||
349 | b = 6000000; | ||
350 | else | ||
351 | if (bw == BANDWIDTH_7_MHZ) | ||
352 | b = 7000000; | ||
353 | |||
354 | /* WREF = (B / (7 * fs)) * 2^31 */ | ||
355 | t = b * 10; | ||
356 | /* avoid warning: this decimal constant is unsigned only in ISO C90 */ | ||
357 | /* t *= 2147483648 on 32bit platforms */ | ||
358 | t *= (2048 * 1024); | ||
359 | t *= 1024; | ||
360 | z = 7 * sample_freq_hz; | ||
361 | do_div(t, z); | ||
362 | t += 5; | ||
363 | do_div(t, 10); | ||
364 | |||
365 | tda10048_writereg(state, TDA10048_TIME_WREF_LSB, (u8)t); | ||
366 | tda10048_writereg(state, TDA10048_TIME_WREF_MID1, (u8)(t >> 8)); | ||
367 | tda10048_writereg(state, TDA10048_TIME_WREF_MID2, (u8)(t >> 16)); | ||
368 | tda10048_writereg(state, TDA10048_TIME_WREF_MSB, (u8)(t >> 24)); | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int tda10048_set_invwref(struct dvb_frontend *fe, u32 sample_freq_hz, | ||
374 | u32 bw) | ||
375 | { | ||
376 | struct tda10048_state *state = fe->demodulator_priv; | ||
377 | u64 t; | ||
378 | u32 b = 8000000; | ||
379 | |||
380 | dprintk(1, "%s()\n", __func__); | ||
381 | |||
382 | if (sample_freq_hz == 0) | ||
383 | return -EINVAL; | ||
384 | |||
385 | if (bw == BANDWIDTH_6_MHZ) | ||
386 | b = 6000000; | ||
387 | else | ||
388 | if (bw == BANDWIDTH_7_MHZ) | ||
389 | b = 7000000; | ||
390 | |||
391 | /* INVWREF = ((7 * fs) / B) * 2^5 */ | ||
392 | t = sample_freq_hz; | ||
393 | t *= 7; | ||
394 | t *= 32; | ||
395 | t *= 10; | ||
396 | do_div(t, b); | ||
397 | t += 5; | ||
398 | do_div(t, 10); | ||
399 | |||
400 | tda10048_writereg(state, TDA10048_TIME_INVWREF_LSB, (u8)t); | ||
401 | tda10048_writereg(state, TDA10048_TIME_INVWREF_MSB, (u8)(t >> 8)); | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static int tda10048_set_bandwidth(struct dvb_frontend *fe, | ||
407 | enum fe_bandwidth bw) | ||
408 | { | ||
409 | struct tda10048_state *state = fe->demodulator_priv; | ||
410 | dprintk(1, "%s(bw=%d)\n", __func__, bw); | ||
411 | |||
412 | /* Bandwidth setting may need to be adjusted */ | ||
413 | switch (bw) { | ||
414 | case BANDWIDTH_6_MHZ: | ||
415 | case BANDWIDTH_7_MHZ: | ||
416 | case BANDWIDTH_8_MHZ: | ||
417 | tda10048_set_wref(fe, state->sample_freq, bw); | ||
418 | tda10048_set_invwref(fe, state->sample_freq, bw); | ||
419 | break; | ||
420 | default: | ||
421 | printk(KERN_ERR "%s() invalid bandwidth\n", __func__); | ||
422 | return -EINVAL; | ||
423 | } | ||
424 | |||
425 | state->bandwidth = bw; | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static int tda10048_set_if(struct dvb_frontend *fe, enum fe_bandwidth bw) | ||
431 | { | ||
432 | struct tda10048_state *state = fe->demodulator_priv; | ||
433 | struct tda10048_config *config = &state->config; | ||
434 | int i; | ||
435 | u32 if_freq_khz; | ||
436 | |||
437 | dprintk(1, "%s(bw = %d)\n", __func__, bw); | ||
438 | |||
439 | /* based on target bandwidth and clk we calculate pll factors */ | ||
440 | switch (bw) { | ||
441 | case BANDWIDTH_6_MHZ: | ||
442 | if_freq_khz = config->dtv6_if_freq_khz; | ||
443 | break; | ||
444 | case BANDWIDTH_7_MHZ: | ||
445 | if_freq_khz = config->dtv7_if_freq_khz; | ||
446 | break; | ||
447 | case BANDWIDTH_8_MHZ: | ||
448 | if_freq_khz = config->dtv8_if_freq_khz; | ||
449 | break; | ||
450 | default: | ||
451 | printk(KERN_ERR "%s() no default\n", __func__); | ||
452 | return -EINVAL; | ||
453 | } | ||
454 | |||
455 | for (i = 0; i < ARRAY_SIZE(pll_tab); i++) { | ||
456 | if ((pll_tab[i].clk_freq_khz == config->clk_freq_khz) && | ||
457 | (pll_tab[i].if_freq_khz == if_freq_khz)) { | ||
458 | |||
459 | state->freq_if_hz = pll_tab[i].if_freq_khz * 1000; | ||
460 | state->xtal_hz = pll_tab[i].clk_freq_khz * 1000; | ||
461 | state->pll_mfactor = pll_tab[i].m; | ||
462 | state->pll_nfactor = pll_tab[i].n; | ||
463 | state->pll_pfactor = pll_tab[i].p; | ||
464 | break; | ||
465 | } | ||
466 | } | ||
467 | if (i == ARRAY_SIZE(pll_tab)) { | ||
468 | printk(KERN_ERR "%s() Incorrect attach settings\n", | ||
469 | __func__); | ||
470 | return -EINVAL; | ||
471 | } | ||
472 | |||
473 | dprintk(1, "- freq_if_hz = %d\n", state->freq_if_hz); | ||
474 | dprintk(1, "- xtal_hz = %d\n", state->xtal_hz); | ||
475 | dprintk(1, "- pll_mfactor = %d\n", state->pll_mfactor); | ||
476 | dprintk(1, "- pll_nfactor = %d\n", state->pll_nfactor); | ||
477 | dprintk(1, "- pll_pfactor = %d\n", state->pll_pfactor); | ||
478 | |||
479 | /* Calculate the sample frequency */ | ||
480 | state->sample_freq = state->xtal_hz * (state->pll_mfactor + 45); | ||
481 | state->sample_freq /= (state->pll_nfactor + 1); | ||
482 | state->sample_freq /= (state->pll_pfactor + 4); | ||
483 | dprintk(1, "- sample_freq = %d\n", state->sample_freq); | ||
484 | |||
485 | /* Update the I/F */ | ||
486 | tda10048_set_phy2(fe, state->sample_freq, state->freq_if_hz); | ||
487 | |||
488 | return 0; | ||
489 | } | ||
490 | |||
274 | static int tda10048_firmware_upload(struct dvb_frontend *fe) | 491 | static int tda10048_firmware_upload(struct dvb_frontend *fe) |
275 | { | 492 | { |
276 | struct tda10048_state *state = fe->demodulator_priv; | 493 | struct tda10048_state *state = fe->demodulator_priv; |
494 | struct tda10048_config *config = &state->config; | ||
277 | const struct firmware *fw; | 495 | const struct firmware *fw; |
278 | int ret; | 496 | int ret; |
279 | int pos = 0; | 497 | int pos = 0; |
280 | int cnt; | 498 | int cnt; |
281 | u8 wlen = state->config->fwbulkwritelen; | 499 | u8 wlen = config->fwbulkwritelen; |
282 | 500 | ||
283 | if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50)) | 501 | if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50)) |
284 | wlen = TDA10048_BULKWRITE_200; | 502 | wlen = TDA10048_BULKWRITE_200; |
@@ -289,7 +507,7 @@ static int tda10048_firmware_upload(struct dvb_frontend *fe) | |||
289 | TDA10048_DEFAULT_FIRMWARE); | 507 | TDA10048_DEFAULT_FIRMWARE); |
290 | 508 | ||
291 | ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE, | 509 | ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE, |
292 | &state->i2c->dev); | 510 | state->i2c->dev.parent); |
293 | if (ret) { | 511 | if (ret) { |
294 | printk(KERN_ERR "%s: Upload failed. (file not found?)\n", | 512 | printk(KERN_ERR "%s: Upload failed. (file not found?)\n", |
295 | __func__); | 513 | __func__); |
@@ -484,8 +702,12 @@ static int tda10048_get_tps(struct tda10048_state *state, | |||
484 | static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | 702 | static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) |
485 | { | 703 | { |
486 | struct tda10048_state *state = fe->demodulator_priv; | 704 | struct tda10048_state *state = fe->demodulator_priv; |
705 | struct tda10048_config *config = &state->config; | ||
487 | dprintk(1, "%s(%d)\n", __func__, enable); | 706 | dprintk(1, "%s(%d)\n", __func__, enable); |
488 | 707 | ||
708 | if (config->disable_gate_access) | ||
709 | return 0; | ||
710 | |||
489 | if (enable) | 711 | if (enable) |
490 | return tda10048_writereg(state, TDA10048_CONF_C4_1, | 712 | return tda10048_writereg(state, TDA10048_CONF_C4_1, |
491 | tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02); | 713 | tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02); |
@@ -523,6 +745,12 @@ static int tda10048_set_frontend(struct dvb_frontend *fe, | |||
523 | 745 | ||
524 | dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency); | 746 | dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency); |
525 | 747 | ||
748 | /* Update the I/F pll's if the bandwidth changes */ | ||
749 | if (p->u.ofdm.bandwidth != state->bandwidth) { | ||
750 | tda10048_set_if(fe, p->u.ofdm.bandwidth); | ||
751 | tda10048_set_bandwidth(fe, p->u.ofdm.bandwidth); | ||
752 | } | ||
753 | |||
526 | if (fe->ops.tuner_ops.set_params) { | 754 | if (fe->ops.tuner_ops.set_params) { |
527 | 755 | ||
528 | if (fe->ops.i2c_gate_ctrl) | 756 | if (fe->ops.i2c_gate_ctrl) |
@@ -544,6 +772,7 @@ static int tda10048_set_frontend(struct dvb_frontend *fe, | |||
544 | static int tda10048_init(struct dvb_frontend *fe) | 772 | static int tda10048_init(struct dvb_frontend *fe) |
545 | { | 773 | { |
546 | struct tda10048_state *state = fe->demodulator_priv; | 774 | struct tda10048_state *state = fe->demodulator_priv; |
775 | struct tda10048_config *config = &state->config; | ||
547 | int ret = 0, i; | 776 | int ret = 0, i; |
548 | 777 | ||
549 | dprintk(1, "%s()\n", __func__); | 778 | dprintk(1, "%s()\n", __func__); |
@@ -556,10 +785,14 @@ static int tda10048_init(struct dvb_frontend *fe) | |||
556 | ret = tda10048_firmware_upload(fe); | 785 | ret = tda10048_firmware_upload(fe); |
557 | 786 | ||
558 | /* Set either serial or parallel */ | 787 | /* Set either serial or parallel */ |
559 | tda10048_output_mode(fe, state->config->output_mode); | 788 | tda10048_output_mode(fe, config->output_mode); |
789 | |||
790 | /* Set inversion */ | ||
791 | tda10048_set_inversion(fe, config->inversion); | ||
560 | 792 | ||
561 | /* set inversion */ | 793 | /* Establish default RF values */ |
562 | tda10048_set_inversion(fe, state->config->inversion); | 794 | tda10048_set_if(fe, BANDWIDTH_8_MHZ); |
795 | tda10048_set_bandwidth(fe, BANDWIDTH_8_MHZ); | ||
563 | 796 | ||
564 | /* Ensure we leave the gate closed */ | 797 | /* Ensure we leave the gate closed */ |
565 | tda10048_i2c_gate_ctrl(fe, 0); | 798 | tda10048_i2c_gate_ctrl(fe, 0); |
@@ -812,6 +1045,45 @@ static void tda10048_release(struct dvb_frontend *fe) | |||
812 | kfree(state); | 1045 | kfree(state); |
813 | } | 1046 | } |
814 | 1047 | ||
1048 | static void tda10048_establish_defaults(struct dvb_frontend *fe) | ||
1049 | { | ||
1050 | struct tda10048_state *state = fe->demodulator_priv; | ||
1051 | struct tda10048_config *config = &state->config; | ||
1052 | |||
1053 | /* Validate/default the config */ | ||
1054 | if (config->dtv6_if_freq_khz == 0) { | ||
1055 | config->dtv6_if_freq_khz = TDA10048_IF_4300; | ||
1056 | printk(KERN_WARNING "%s() tda10048_config.dtv6_if_freq_khz " | ||
1057 | "is not set (defaulting to %d)\n", | ||
1058 | __func__, | ||
1059 | config->dtv6_if_freq_khz); | ||
1060 | } | ||
1061 | |||
1062 | if (config->dtv7_if_freq_khz == 0) { | ||
1063 | config->dtv7_if_freq_khz = TDA10048_IF_4300; | ||
1064 | printk(KERN_WARNING "%s() tda10048_config.dtv7_if_freq_khz " | ||
1065 | "is not set (defaulting to %d)\n", | ||
1066 | __func__, | ||
1067 | config->dtv7_if_freq_khz); | ||
1068 | } | ||
1069 | |||
1070 | if (config->dtv8_if_freq_khz == 0) { | ||
1071 | config->dtv8_if_freq_khz = TDA10048_IF_4300; | ||
1072 | printk(KERN_WARNING "%s() tda10048_config.dtv8_if_freq_khz " | ||
1073 | "is not set (defaulting to %d)\n", | ||
1074 | __func__, | ||
1075 | config->dtv8_if_freq_khz); | ||
1076 | } | ||
1077 | |||
1078 | if (config->clk_freq_khz == 0) { | ||
1079 | config->clk_freq_khz = TDA10048_CLK_16000; | ||
1080 | printk(KERN_WARNING "%s() tda10048_config.clk_freq_khz " | ||
1081 | "is not set (defaulting to %d)\n", | ||
1082 | __func__, | ||
1083 | config->clk_freq_khz); | ||
1084 | } | ||
1085 | } | ||
1086 | |||
815 | static struct dvb_frontend_ops tda10048_ops; | 1087 | static struct dvb_frontend_ops tda10048_ops; |
816 | 1088 | ||
817 | struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, | 1089 | struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, |
@@ -826,10 +1098,11 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, | |||
826 | if (state == NULL) | 1098 | if (state == NULL) |
827 | goto error; | 1099 | goto error; |
828 | 1100 | ||
829 | /* setup the state */ | 1101 | /* setup the state and clone the config */ |
830 | state->config = config; | 1102 | memcpy(&state->config, config, sizeof(*config)); |
831 | state->i2c = i2c; | 1103 | state->i2c = i2c; |
832 | state->fwloaded = 0; | 1104 | state->fwloaded = 0; |
1105 | state->bandwidth = BANDWIDTH_8_MHZ; | ||
833 | 1106 | ||
834 | /* check if the demod is present */ | 1107 | /* check if the demod is present */ |
835 | if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048) | 1108 | if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048) |
@@ -840,6 +1113,17 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, | |||
840 | sizeof(struct dvb_frontend_ops)); | 1113 | sizeof(struct dvb_frontend_ops)); |
841 | state->frontend.demodulator_priv = state; | 1114 | state->frontend.demodulator_priv = state; |
842 | 1115 | ||
1116 | /* Establish any defaults the the user didn't pass */ | ||
1117 | tda10048_establish_defaults(&state->frontend); | ||
1118 | |||
1119 | /* Set the xtal and freq defaults */ | ||
1120 | if (tda10048_set_if(&state->frontend, BANDWIDTH_8_MHZ) != 0) | ||
1121 | goto error; | ||
1122 | |||
1123 | /* Default bandwidth */ | ||
1124 | if (tda10048_set_bandwidth(&state->frontend, BANDWIDTH_8_MHZ) != 0) | ||
1125 | goto error; | ||
1126 | |||
843 | /* Leave the gate closed */ | 1127 | /* Leave the gate closed */ |
844 | tda10048_i2c_gate_ctrl(&state->frontend, 0); | 1128 | tda10048_i2c_gate_ctrl(&state->frontend, 0); |
845 | 1129 | ||