aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/tda827x.c
diff options
context:
space:
mode:
authorMichael Krufky <mkrufky@linuxtv.org>2007-08-25 18:08:45 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:01:05 -0500
commit746d9732dbd5b95c3ba36230e2814fa2c391a311 (patch)
treebb63bc3eeea67bedd6b92727280ea8a35d5656b5 /drivers/media/dvb/frontends/tda827x.c
parentde3fe21ba2fdc0733ad4e555b95121baeba7fcd5 (diff)
V4L/DVB (6433): Move all tda8275/8275a tuning code from tda8290 module into tda827x module
Add analog tuning support to tda827x dvb_frontend tuner module. Convert tda8290 module back to native tuner interface. The tda8290 analog demodulator will be handled the same way as tda9887. The tuner.ko module (tuner-core) will pass commands to tda8290 via the tuner_operations interface. tda8290 will communicate with tda827x via the dvb_frontend interface, while passing a pointer to a private data structure. Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Reviewed-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/dvb/frontends/tda827x.c')
-rw-r--r--drivers/media/dvb/frontends/tda827x.c307
1 files changed, 293 insertions, 14 deletions
diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c
index 256fc4bf500b..3c71f07a6d2c 100644
--- a/drivers/media/dvb/frontends/tda827x.c
+++ b/drivers/media/dvb/frontends/tda827x.c
@@ -19,12 +19,16 @@
19 */ 19 */
20 20
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/dvb/frontend.h>
23#include <asm/types.h> 22#include <asm/types.h>
23#include <linux/dvb/frontend.h>
24#include <linux/videodev2.h>
24 25
25#include "tda827x.h" 26#include "tda827x.h"
26 27
27static int debug = 0; 28static int debug = 0;
29module_param(debug, int, 0644);
30MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
31
28#define dprintk(args...) \ 32#define dprintk(args...) \
29 do { \ 33 do { \
30 if (debug) printk(KERN_DEBUG "tda827x: " args); \ 34 if (debug) printk(KERN_DEBUG "tda827x: " args); \
@@ -48,7 +52,7 @@ struct tda827x_data {
48 u8 div1p5; 52 u8 div1p5;
49}; 53};
50 54
51static const struct tda827x_data tda827x_dvbt[] = { 55static const struct tda827x_data tda827x_table[] = {
52 { .lomax = 62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, 56 { .lomax = 62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
53 { .lomax = 66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, 57 { .lomax = 66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
54 { .lomax = 76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, 58 { .lomax = 76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
@@ -106,21 +110,22 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
106 tuner_freq = params->frequency + if_freq; 110 tuner_freq = params->frequency + if_freq;
107 111
108 i = 0; 112 i = 0;
109 while (tda827x_dvbt[i].lomax < tuner_freq) { 113 while (tda827x_table[i].lomax < tuner_freq) {
110 if(tda827x_dvbt[i + 1].lomax == 0) 114 if (tda827x_table[i + 1].lomax == 0)
111 break; 115 break;
112 i++; 116 i++;
113 } 117 }
114 118
115 N = ((tuner_freq + 125000) / 250000) << (tda827x_dvbt[i].spd + 2); 119 N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
116 buf[0] = 0; 120 buf[0] = 0;
117 buf[1] = (N>>8) | 0x40; 121 buf[1] = (N>>8) | 0x40;
118 buf[2] = N & 0xff; 122 buf[2] = N & 0xff;
119 buf[3] = 0; 123 buf[3] = 0;
120 buf[4] = 0x52; 124 buf[4] = 0x52;
121 buf[5] = (tda827x_dvbt[i].spd << 6) + (tda827x_dvbt[i].div1p5 << 5) + 125 buf[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) +
122 (tda827x_dvbt[i].bs << 3) + tda827x_dvbt[i].bp; 126 (tda827x_table[i].bs << 3) +
123 buf[6] = (tda827x_dvbt[i].gc3 << 4) + 0x8f; 127 tda827x_table[i].bp;
128 buf[6] = (tda827x_table[i].gc3 << 4) + 0x8f;
124 buf[7] = 0xbf; 129 buf[7] = 0xbf;
125 buf[8] = 0x2a; 130 buf[8] = 0x2a;
126 buf[9] = 0x05; 131 buf[9] = 0x05;
@@ -140,7 +145,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
140 msleep(500); 145 msleep(500);
141 /* correct CP value */ 146 /* correct CP value */
142 buf[0] = 0x30; 147 buf[0] = 0x30;
143 buf[1] = 0x50 + tda827x_dvbt[i].cp; 148 buf[1] = 0x50 + tda827x_table[i].cp;
144 msg.len = 2; 149 msg.len = 2;
145 150
146 if (fe->ops.i2c_gate_ctrl) 151 if (fe->ops.i2c_gate_ctrl)
@@ -173,6 +178,100 @@ static int tda827xo_sleep(struct dvb_frontend *fe)
173 178
174/* ------------------------------------------------------------------ */ 179/* ------------------------------------------------------------------ */
175 180
181static int tda827xo_set_analog_params(struct dvb_frontend *fe,
182 struct analog_parameters *params)
183{
184 unsigned char tuner_reg[8];
185 unsigned char reg2[2];
186 u32 N;
187 int i;
188 struct tda827x_priv *priv = fe->tuner_priv;
189 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 };
190 unsigned int freq = params->frequency;
191
192 if (params->mode == V4L2_TUNER_RADIO)
193 freq = freq / 1000;
194
195 N = freq + priv->cfg->sgIF;
196
197 i = 0;
198 while (tda827x_table[i].lomax < N * 62500) {
199 if (tda827x_table[i + 1].lomax == 0)
200 break;
201 i++;
202 }
203
204 N = N << tda827x_table[i].spd;
205
206 tuner_reg[0] = 0;
207 tuner_reg[1] = (unsigned char)(N>>8);
208 tuner_reg[2] = (unsigned char) N;
209 tuner_reg[3] = 0x40;
210 tuner_reg[4] = 0x52 + (priv->cfg->tda827x_lpsel << 5);
211 tuner_reg[5] = (tda827x_table[i].spd << 6) +
212 (tda827x_table[i].div1p5 << 5) +
213 (tda827x_table[i].bs << 3) + tda827x_table[i].bp;
214 tuner_reg[6] = 0x8f + (tda827x_table[i].gc3 << 4);
215 tuner_reg[7] = 0x8f;
216
217 msg.buf = tuner_reg;
218 msg.len = 8;
219 i2c_transfer(priv->i2c_adap, &msg, 1);
220
221 msg.buf = reg2;
222 msg.len = 2;
223 reg2[0] = 0x80;
224 reg2[1] = 0;
225 i2c_transfer(priv->i2c_adap, &msg, 1);
226
227 reg2[0] = 0x60;
228 reg2[1] = 0xbf;
229 i2c_transfer(priv->i2c_adap, &msg, 1);
230
231 reg2[0] = 0x30;
232 reg2[1] = tuner_reg[4] + 0x80;
233 i2c_transfer(priv->i2c_adap, &msg, 1);
234
235 msleep(1);
236 reg2[0] = 0x30;
237 reg2[1] = tuner_reg[4] + 4;
238 i2c_transfer(priv->i2c_adap, &msg, 1);
239
240 msleep(1);
241 reg2[0] = 0x30;
242 reg2[1] = tuner_reg[4];
243 i2c_transfer(priv->i2c_adap, &msg, 1);
244
245 msleep(550);
246 reg2[0] = 0x30;
247 reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp;
248 i2c_transfer(priv->i2c_adap, &msg, 1);
249
250 reg2[0] = 0x60;
251 reg2[1] = 0x3f;
252 i2c_transfer(priv->i2c_adap, &msg, 1);
253
254 reg2[0] = 0x80;
255 reg2[1] = 0x08; /* Vsync en */
256 i2c_transfer(priv->i2c_adap, &msg, 1);
257
258 priv->frequency = freq * 62500;
259
260 return 0;
261}
262
263static void tda827xo_agcf(struct dvb_frontend *fe)
264{
265 struct tda827x_priv *priv = fe->tuner_priv;
266 unsigned char data[] = { 0x80, 0x0c };
267 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
268 .buf = data, .len = 2};
269
270 i2c_transfer(priv->i2c_adap, &msg, 1);
271}
272
273/* ------------------------------------------------------------------ */
274
176struct tda827xa_data { 275struct tda827xa_data {
177 u32 lomax; 276 u32 lomax;
178 u8 svco; 277 u8 svco;
@@ -212,6 +311,35 @@ static const struct tda827xa_data tda827xa_dvbt[] = {
212 { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} 311 { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
213}; 312};
214 313
314static struct tda827xa_data tda827xa_analog[] = {
315 { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3},
316 { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
317 { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
318 { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
319 { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
320 { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
321 { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
322 { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
323 { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
324 { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
325 { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3},
326 { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3},
327 { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
328 { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
329 { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
330 { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
331 { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
332 { .lomax = 554000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
333 { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
334 { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
335 { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
336 { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
337 { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
338 { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
339 { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
340 { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
341};
342
215static int tda827xa_set_params(struct dvb_frontend *fe, 343static int tda827xa_set_params(struct dvb_frontend *fe,
216 struct dvb_frontend_parameters *params) 344 struct dvb_frontend_parameters *params)
217{ 345{
@@ -368,6 +496,156 @@ static int tda827xa_sleep(struct dvb_frontend *fe)
368 return 0; 496 return 0;
369} 497}
370 498
499/* ------------------------------------------------------------------ */
500
501static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
502 struct analog_parameters *params)
503{
504 struct tda827x_priv *priv = fe->tuner_priv;
505 unsigned char buf[] = {0x22, 0x01};
506 int arg;
507 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
508 .buf = buf, .len = sizeof(buf) };
509
510 if (priv->cfg->config) {
511 if (high)
512 dprintk("setting LNA to high gain\n");
513 else
514 dprintk("setting LNA to low gain\n");
515 }
516 switch (*priv->cfg->config) {
517 case 0: /* no LNA */
518 break;
519 case 1: /* switch is GPIO 0 of tda8290 */
520 case 2:
521 /* turn Vsync on */
522 if (params->std & V4L2_STD_MN)
523 arg = 1;
524 else
525 arg = 0;
526 if (priv->cfg->tuner_callback)
527 priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
528 1, arg);
529 buf[1] = high ? 0 : 1;
530 if (*priv->cfg->config == 2)
531 buf[1] = high ? 1 : 0;
532 i2c_transfer(priv->i2c_adap, &msg, 1);
533 break;
534 case 3: /* switch with GPIO of saa713x */
535 if (priv->cfg->tuner_callback)
536 priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
537 0, high);
538 break;
539 }
540}
541
542static int tda827xa_set_analog_params(struct dvb_frontend *fe,
543 struct analog_parameters *params)
544{
545 unsigned char tuner_reg[11];
546 u32 N;
547 int i;
548 struct tda827x_priv *priv = fe->tuner_priv;
549 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
550 .buf = tuner_reg, .len = sizeof(tuner_reg) };
551 unsigned int freq = params->frequency;
552
553 tda827xa_lna_gain(fe, 1, params);
554 msleep(10);
555
556 if (params->mode == V4L2_TUNER_RADIO)
557 freq = freq / 1000;
558
559 N = freq + priv->cfg->sgIF;
560
561 i = 0;
562 while (tda827xa_analog[i].lomax < N * 62500) {
563 if (tda827xa_analog[i + 1].lomax == 0)
564 break;
565 i++;
566 }
567
568 N = N << tda827xa_analog[i].spd;
569
570 tuner_reg[0] = 0;
571 tuner_reg[1] = (unsigned char)(N>>8);
572 tuner_reg[2] = (unsigned char) N;
573 tuner_reg[3] = 0;
574 tuner_reg[4] = 0x16;
575 tuner_reg[5] = (tda827xa_analog[i].spd << 5) +
576 (tda827xa_analog[i].svco << 3) +
577 tda827xa_analog[i].sbs;
578 tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4);
579 tuner_reg[7] = 0x1c;
580 tuner_reg[8] = 4;
581 tuner_reg[9] = 0x20;
582 tuner_reg[10] = 0x00;
583 msg.len = 11;
584 i2c_transfer(priv->i2c_adap, &msg, 1);
585
586 tuner_reg[0] = 0x90;
587 tuner_reg[1] = 0xff;
588 tuner_reg[2] = 0xe0;
589 tuner_reg[3] = 0;
590 tuner_reg[4] = 0x99 + (priv->cfg->tda827x_lpsel << 1);
591 msg.len = 5;
592 i2c_transfer(priv->i2c_adap, &msg, 1);
593
594 tuner_reg[0] = 0xa0;
595 tuner_reg[1] = 0xc0;
596 msg.len = 2;
597 i2c_transfer(priv->i2c_adap, &msg, 1);
598
599 tuner_reg[0] = 0x30;
600 tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
601 i2c_transfer(priv->i2c_adap, &msg, 1);
602
603 msg.flags = I2C_M_RD;
604 i2c_transfer(priv->i2c_adap, &msg, 1);
605 msg.flags = 0;
606 tuner_reg[1] >>= 4;
607 dprintk("AGC2 gain is: %d\n", tuner_reg[1]);
608 if (tuner_reg[1] < 1)
609 tda827xa_lna_gain(fe, 0, params);
610
611 msleep(100);
612 tuner_reg[0] = 0x60;
613 tuner_reg[1] = 0x3c;
614 i2c_transfer(priv->i2c_adap, &msg, 1);
615
616 msleep(163);
617 tuner_reg[0] = 0x50;
618 tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
619 i2c_transfer(priv->i2c_adap, &msg, 1);
620
621 tuner_reg[0] = 0x80;
622 tuner_reg[1] = 0x28;
623 i2c_transfer(priv->i2c_adap, &msg, 1);
624
625 tuner_reg[0] = 0xb0;
626 tuner_reg[1] = 0x01;
627 i2c_transfer(priv->i2c_adap, &msg, 1);
628
629 tuner_reg[0] = 0xc0;
630 tuner_reg[1] = 0x19 + (priv->cfg->tda827x_lpsel << 1);
631 i2c_transfer(priv->i2c_adap, &msg, 1);
632
633 priv->frequency = freq * 62500;
634
635 return 0;
636}
637
638static void tda827xa_agcf(struct dvb_frontend *fe)
639{
640 struct tda827x_priv *priv = fe->tuner_priv;
641 unsigned char data[] = {0x80, 0x2c};
642 struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
643 .buf = data, .len = 2};
644 i2c_transfer(priv->i2c_adap, &msg, 1);
645}
646
647/* ------------------------------------------------------------------ */
648
371static int tda827x_release(struct dvb_frontend *fe) 649static int tda827x_release(struct dvb_frontend *fe)
372{ 650{
373 kfree(fe->tuner_priv); 651 kfree(fe->tuner_priv);
@@ -430,6 +708,7 @@ static struct dvb_tuner_ops tda827xo_tuner_ops = {
430 .init = tda827x_initial_init, 708 .init = tda827x_initial_init,
431 .sleep = tda827x_initial_sleep, 709 .sleep = tda827x_initial_sleep,
432 .set_params = tda827xo_set_params, 710 .set_params = tda827xo_set_params,
711 .set_analog_params = tda827xo_set_analog_params,
433 .get_frequency = tda827x_get_frequency, 712 .get_frequency = tda827x_get_frequency,
434 .get_bandwidth = tda827x_get_bandwidth, 713 .get_bandwidth = tda827x_get_bandwidth,
435}; 714};
@@ -445,6 +724,7 @@ static struct dvb_tuner_ops tda827xa_tuner_ops = {
445 .init = tda827x_init, 724 .init = tda827x_init,
446 .sleep = tda827xa_sleep, 725 .sleep = tda827xa_sleep,
447 .set_params = tda827xa_set_params, 726 .set_params = tda827xa_set_params,
727 .set_analog_params = tda827xa_set_analog_params,
448 .get_frequency = tda827x_get_frequency, 728 .get_frequency = tda827x_get_frequency,
449 .get_bandwidth = tda827x_get_bandwidth, 729 .get_bandwidth = tda827x_get_bandwidth,
450}; 730};
@@ -465,9 +745,11 @@ static int tda827x_probe_version(struct dvb_frontend *fe)
465 dprintk("tda827x tuner found\n"); 745 dprintk("tda827x tuner found\n");
466 fe->ops.tuner_ops.init = tda827x_init; 746 fe->ops.tuner_ops.init = tda827x_init;
467 fe->ops.tuner_ops.sleep = tda827xo_sleep; 747 fe->ops.tuner_ops.sleep = tda827xo_sleep;
748 priv->cfg->agcf = tda827xo_agcf;
468 } else { 749 } else {
469 dprintk("tda827xa tuner found\n"); 750 dprintk("tda827xa tuner found\n");
470 memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops)); 751 memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops));
752 priv->cfg->agcf = tda827xa_agcf;
471 } 753 }
472 return 0; 754 return 0;
473} 755}
@@ -487,17 +769,14 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
487 priv->i2c_adap = i2c; 769 priv->i2c_adap = i2c;
488 priv->cfg = cfg; 770 priv->cfg = cfg;
489 memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops)); 771 memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops));
490
491 fe->tuner_priv = priv; 772 fe->tuner_priv = priv;
492 773
774 dprintk("type set to %s\n", fe->ops.tuner_ops.info.name);
775
493 return fe; 776 return fe;
494} 777}
495
496EXPORT_SYMBOL(tda827x_attach); 778EXPORT_SYMBOL(tda827x_attach);
497 779
498module_param(debug, int, 0644);
499MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
500
501MODULE_DESCRIPTION("DVB TDA827x driver"); 780MODULE_DESCRIPTION("DVB TDA827x driver");
502MODULE_AUTHOR("Hartmut Hackmann <hartmut.hackmann@t-online.de>"); 781MODULE_AUTHOR("Hartmut Hackmann <hartmut.hackmann@t-online.de>");
503MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); 782MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");