RT-AC56 3.0.0.4.374.37 core
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / media / dvb / frontends / lgs8gxx.c
blob8701762369c3d2ee9bedc2d9c29dff2c9db214de
1 /*
2 * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator
3 * LGS8913, LGS8GL5, LGS8G75
4 * experimental support LGS8G42, LGS8G52
6 * Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com>
7 * Copyright (C) 2008 Sirius International (Hong Kong) Limited
8 * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <asm/div64.h>
27 #include <linux/firmware.h>
29 #include "dvb_frontend.h"
31 #include "lgs8gxx.h"
32 #include "lgs8gxx_priv.h"
34 #define dprintk(args...) \
35 do { \
36 if (debug) \
37 printk(KERN_DEBUG "lgs8gxx: " args); \
38 } while (0)
40 static int debug;
41 static int fake_signal_str = 1;
43 module_param(debug, int, 0644);
44 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
46 module_param(fake_signal_str, int, 0644);
47 MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913."
48 "Signal strength calculation is slow.(default:on).");
50 /* LGS8GXX internal helper functions */
52 static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data)
54 int ret;
55 u8 buf[] = { reg, data };
56 struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
58 msg.addr = priv->config->demod_address;
59 if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0)
60 msg.addr += 0x02;
62 if (debug >= 2)
63 printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
64 __func__, reg, data);
66 ret = i2c_transfer(priv->i2c, &msg, 1);
68 if (ret != 1)
69 dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n",
70 __func__, reg, data, ret);
72 return (ret != 1) ? -1 : 0;
75 static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data)
77 int ret;
78 u8 dev_addr;
80 u8 b0[] = { reg };
81 u8 b1[] = { 0 };
82 struct i2c_msg msg[] = {
83 { .flags = 0, .buf = b0, .len = 1 },
84 { .flags = I2C_M_RD, .buf = b1, .len = 1 },
87 dev_addr = priv->config->demod_address;
88 if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0)
89 dev_addr += 0x02;
90 msg[1].addr = msg[0].addr = dev_addr;
92 ret = i2c_transfer(priv->i2c, msg, 2);
93 if (ret != 2) {
94 dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n",
95 __func__, reg, ret);
96 return -1;
99 *p_data = b1[0];
100 if (debug >= 2)
101 printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
102 __func__, reg, b1[0]);
103 return 0;
106 static int lgs8gxx_soft_reset(struct lgs8gxx_state *priv)
108 lgs8gxx_write_reg(priv, 0x02, 0x00);
109 msleep(1);
110 lgs8gxx_write_reg(priv, 0x02, 0x01);
111 msleep(100);
113 return 0;
116 static int wait_reg_mask(struct lgs8gxx_state *priv, u8 reg, u8 mask,
117 u8 val, u8 delay, u8 tries)
119 u8 t;
120 int i;
122 for (i = 0; i < tries; i++) {
123 lgs8gxx_read_reg(priv, reg, &t);
125 if ((t & mask) == val)
126 return 0;
127 msleep(delay);
130 return 1;
133 static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv)
135 const struct lgs8gxx_config *config = priv->config;
136 u8 if_conf;
138 if_conf = 0x10; /* AGC output on, RF_AGC output off; */
140 if_conf |=
141 ((config->ext_adc) ? 0x80 : 0x00) |
142 ((config->if_neg_center) ? 0x04 : 0x00) |
143 ((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */
144 ((config->adc_signed) ? 0x02 : 0x00) |
145 ((config->if_neg_edge) ? 0x01 : 0x00);
147 if (config->ext_adc &&
148 (config->prod == LGS8GXX_PROD_LGS8G52)) {
149 lgs8gxx_write_reg(priv, 0xBA, 0x40);
152 lgs8gxx_write_reg(priv, 0x07, if_conf);
154 return 0;
157 static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/)
159 u64 val;
160 u32 v32;
161 u32 if_clk;
163 if_clk = priv->config->if_clk_freq;
165 val = freq;
166 if (freq != 0) {
167 val <<= 32;
168 if (if_clk != 0)
169 do_div(val, if_clk);
170 v32 = val & 0xFFFFFFFF;
171 dprintk("Set IF Freq to %dkHz\n", freq);
172 } else {
173 v32 = 0;
174 dprintk("Set IF Freq to baseband\n");
176 dprintk("AFC_INIT_FREQ = 0x%08X\n", v32);
178 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
179 lgs8gxx_write_reg(priv, 0x08, 0xFF & (v32));
180 lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32 >> 8));
181 lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 16));
182 lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 24));
183 } else {
184 lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32));
185 lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8));
186 lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16));
187 lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24));
190 return 0;
193 static int lgs8gxx_get_afc_phase(struct lgs8gxx_state *priv)
195 u64 val;
196 u32 v32 = 0;
197 u8 reg_addr, t;
198 int i;
200 if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
201 reg_addr = 0x23;
202 else
203 reg_addr = 0x48;
205 for (i = 0; i < 4; i++) {
206 lgs8gxx_read_reg(priv, reg_addr, &t);
207 v32 <<= 8;
208 v32 |= t;
209 reg_addr--;
212 val = v32;
213 val *= priv->config->if_clk_freq;
214 val >>= 32;
215 dprintk("AFC = %u kHz\n", (u32)val);
216 return 0;
219 static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv)
221 u8 t;
222 u8 prod = priv->config->prod;
224 if (prod == LGS8GXX_PROD_LGS8913)
225 lgs8gxx_write_reg(priv, 0xC6, 0x01);
227 if (prod == LGS8GXX_PROD_LGS8G75) {
228 lgs8gxx_read_reg(priv, 0x0C, &t);
229 t &= (~0x04);
230 lgs8gxx_write_reg(priv, 0x0C, t | 0x80);
231 lgs8gxx_write_reg(priv, 0x39, 0x00);
232 lgs8gxx_write_reg(priv, 0x3D, 0x04);
233 } else if (prod == LGS8GXX_PROD_LGS8913 ||
234 prod == LGS8GXX_PROD_LGS8GL5 ||
235 prod == LGS8GXX_PROD_LGS8G42 ||
236 prod == LGS8GXX_PROD_LGS8G52 ||
237 prod == LGS8GXX_PROD_LGS8G54) {
238 lgs8gxx_read_reg(priv, 0x7E, &t);
239 lgs8gxx_write_reg(priv, 0x7E, t | 0x01);
241 /* clear FEC self reset */
242 lgs8gxx_read_reg(priv, 0xC5, &t);
243 lgs8gxx_write_reg(priv, 0xC5, t & 0xE0);
246 if (prod == LGS8GXX_PROD_LGS8913) {
247 /* FEC auto detect */
248 lgs8gxx_write_reg(priv, 0xC1, 0x03);
250 lgs8gxx_read_reg(priv, 0x7C, &t);
251 t = (t & 0x8C) | 0x03;
252 lgs8gxx_write_reg(priv, 0x7C, t);
254 /* BER test mode */
255 lgs8gxx_read_reg(priv, 0xC3, &t);
256 t = (t & 0xEF) | 0x10;
257 lgs8gxx_write_reg(priv, 0xC3, t);
260 if (priv->config->prod == LGS8GXX_PROD_LGS8G52)
261 lgs8gxx_write_reg(priv, 0xD9, 0x40);
263 return 0;
266 static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv)
268 int ret = 0;
269 u8 t;
271 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
272 u8 t2;
273 lgs8gxx_read_reg(priv, 0x0C, &t);
274 t &= (~0x80);
275 lgs8gxx_write_reg(priv, 0x0C, t);
277 lgs8gxx_read_reg(priv, 0x0C, &t);
278 lgs8gxx_read_reg(priv, 0x19, &t2);
280 if (((t&0x03) == 0x01) && (t2&0x01)) {
281 lgs8gxx_write_reg(priv, 0x6E, 0x05);
282 lgs8gxx_write_reg(priv, 0x39, 0x02);
283 lgs8gxx_write_reg(priv, 0x39, 0x03);
284 lgs8gxx_write_reg(priv, 0x3D, 0x05);
285 lgs8gxx_write_reg(priv, 0x3E, 0x28);
286 lgs8gxx_write_reg(priv, 0x53, 0x80);
287 } else {
288 lgs8gxx_write_reg(priv, 0x6E, 0x3F);
289 lgs8gxx_write_reg(priv, 0x39, 0x00);
290 lgs8gxx_write_reg(priv, 0x3D, 0x04);
293 lgs8gxx_soft_reset(priv);
294 return 0;
297 /* turn off auto-detect; manual settings */
298 lgs8gxx_write_reg(priv, 0x7E, 0);
299 if (priv->config->prod == LGS8GXX_PROD_LGS8913)
300 lgs8gxx_write_reg(priv, 0xC1, 0);
302 ret = lgs8gxx_read_reg(priv, 0xC5, &t);
303 t = (t & 0xE0) | 0x06;
304 lgs8gxx_write_reg(priv, 0xC5, t);
306 lgs8gxx_soft_reset(priv);
308 return 0;
311 static int lgs8gxx_is_locked(struct lgs8gxx_state *priv, u8 *locked)
313 int ret = 0;
314 u8 t;
316 if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
317 ret = lgs8gxx_read_reg(priv, 0x13, &t);
318 else
319 ret = lgs8gxx_read_reg(priv, 0x4B, &t);
320 if (ret != 0)
321 return ret;
323 if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
324 *locked = ((t & 0x80) == 0x80) ? 1 : 0;
325 else
326 *locked = ((t & 0xC0) == 0xC0) ? 1 : 0;
327 return 0;
330 /* Wait for Code Acquisition Lock */
331 static int lgs8gxx_wait_ca_lock(struct lgs8gxx_state *priv, u8 *locked)
333 int ret = 0;
334 u8 reg, mask, val;
336 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
337 reg = 0x13;
338 mask = 0x80;
339 val = 0x80;
340 } else {
341 reg = 0x4B;
342 mask = 0xC0;
343 val = 0xC0;
346 ret = wait_reg_mask(priv, reg, mask, val, 50, 40);
347 *locked = (ret == 0) ? 1 : 0;
349 return 0;
352 static int lgs8gxx_is_autodetect_finished(struct lgs8gxx_state *priv,
353 u8 *finished)
355 int ret = 0;
356 u8 reg, mask, val;
358 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
359 reg = 0x1f;
360 mask = 0xC0;
361 val = 0x80;
362 } else {
363 reg = 0xA4;
364 mask = 0x03;
365 val = 0x01;
368 ret = wait_reg_mask(priv, reg, mask, val, 10, 20);
369 *finished = (ret == 0) ? 1 : 0;
371 return 0;
374 static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 cpn,
375 u8 *locked)
377 int err = 0;
378 u8 ad_fini = 0;
379 u8 t1, t2;
381 if (gi == GI_945)
382 dprintk("try GI 945\n");
383 else if (gi == GI_595)
384 dprintk("try GI 595\n");
385 else if (gi == GI_420)
386 dprintk("try GI 420\n");
387 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
388 lgs8gxx_read_reg(priv, 0x0C, &t1);
389 lgs8gxx_read_reg(priv, 0x18, &t2);
390 t1 &= ~(GI_MASK);
391 t1 |= gi;
392 t2 &= 0xFE;
393 t2 |= cpn ? 0x01 : 0x00;
394 lgs8gxx_write_reg(priv, 0x0C, t1);
395 lgs8gxx_write_reg(priv, 0x18, t2);
396 } else {
397 lgs8gxx_write_reg(priv, 0x04, gi);
399 lgs8gxx_soft_reset(priv);
400 err = lgs8gxx_wait_ca_lock(priv, locked);
401 if (err || !(*locked))
402 return err;
403 err = lgs8gxx_is_autodetect_finished(priv, &ad_fini);
404 if (err != 0)
405 return err;
406 if (ad_fini) {
407 dprintk("auto detect finished\n");
408 } else
409 *locked = 0;
411 return 0;
414 static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv,
415 u8 *detected_param, u8 *gi)
417 int i, j;
418 int err = 0;
419 u8 locked = 0, tmp_gi;
421 dprintk("%s\n", __func__);
423 lgs8gxx_set_mode_auto(priv);
424 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
425 lgs8gxx_write_reg(priv, 0x67, 0xAA);
426 lgs8gxx_write_reg(priv, 0x6E, 0x3F);
427 } else {
428 /* Guard Interval */
429 lgs8gxx_write_reg(priv, 0x03, 00);
432 for (i = 0; i < 2; i++) {
433 for (j = 0; j < 2; j++) {
434 tmp_gi = GI_945;
435 err = lgs8gxx_autolock_gi(priv, GI_945, j, &locked);
436 if (err)
437 goto out;
438 if (locked)
439 goto locked;
441 for (j = 0; j < 2; j++) {
442 tmp_gi = GI_420;
443 err = lgs8gxx_autolock_gi(priv, GI_420, j, &locked);
444 if (err)
445 goto out;
446 if (locked)
447 goto locked;
449 tmp_gi = GI_595;
450 err = lgs8gxx_autolock_gi(priv, GI_595, 1, &locked);
451 if (err)
452 goto out;
453 if (locked)
454 goto locked;
457 locked:
458 if ((err == 0) && (locked == 1)) {
459 u8 t;
461 if (priv->config->prod != LGS8GXX_PROD_LGS8G75) {
462 lgs8gxx_read_reg(priv, 0xA2, &t);
463 *detected_param = t;
464 } else {
465 lgs8gxx_read_reg(priv, 0x1F, &t);
466 *detected_param = t & 0x3F;
469 if (tmp_gi == GI_945)
470 dprintk("GI 945 locked\n");
471 else if (tmp_gi == GI_595)
472 dprintk("GI 595 locked\n");
473 else if (tmp_gi == GI_420)
474 dprintk("GI 420 locked\n");
475 *gi = tmp_gi;
477 if (!locked)
478 err = -1;
480 out:
481 return err;
484 static void lgs8gxx_auto_lock(struct lgs8gxx_state *priv)
486 s8 err;
487 u8 gi = 0x2;
488 u8 detected_param = 0;
490 err = lgs8gxx_auto_detect(priv, &detected_param, &gi);
492 if (err != 0) {
493 dprintk("lgs8gxx_auto_detect failed\n");
494 } else
495 dprintk("detected param = 0x%02X\n", detected_param);
497 /* Apply detected parameters */
498 if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
499 u8 inter_leave_len = detected_param & TIM_MASK ;
500 /* Fix 8913 time interleaver detection bug */
501 inter_leave_len = (inter_leave_len == TIM_MIDDLE) ? 0x60 : 0x40;
502 detected_param &= CF_MASK | SC_MASK | LGS_FEC_MASK;
503 detected_param |= inter_leave_len;
505 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
506 u8 t;
507 lgs8gxx_read_reg(priv, 0x19, &t);
508 t &= 0x81;
509 t |= detected_param << 1;
510 lgs8gxx_write_reg(priv, 0x19, t);
511 } else {
512 lgs8gxx_write_reg(priv, 0x7D, detected_param);
513 if (priv->config->prod == LGS8GXX_PROD_LGS8913)
514 lgs8gxx_write_reg(priv, 0xC0, detected_param);
516 /* lgs8gxx_soft_reset(priv); */
518 /* Enter manual mode */
519 lgs8gxx_set_mode_manual(priv);
521 switch (gi) {
522 case GI_945:
523 priv->curr_gi = 945; break;
524 case GI_595:
525 priv->curr_gi = 595; break;
526 case GI_420:
527 priv->curr_gi = 420; break;
528 default:
529 priv->curr_gi = 945; break;
533 static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv,
534 u8 serial, u8 clk_pol, u8 clk_gated)
536 int ret = 0;
537 u8 t, reg_addr;
539 reg_addr = (priv->config->prod == LGS8GXX_PROD_LGS8G75) ? 0x30 : 0xC2;
540 ret = lgs8gxx_read_reg(priv, reg_addr, &t);
541 if (ret != 0)
542 return ret;
544 t &= 0xF8;
545 t |= serial ? TS_SERIAL : TS_PARALLEL;
546 t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL;
547 t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN;
549 ret = lgs8gxx_write_reg(priv, reg_addr, t);
550 if (ret != 0)
551 return ret;
553 return 0;
556 /* A/D input peak-to-peak voltage range */
557 static int lgs8g75_set_adc_vpp(struct lgs8gxx_state *priv,
558 u8 sel)
560 u8 r26 = 0x73, r27 = 0x90;
562 if (priv->config->prod != LGS8GXX_PROD_LGS8G75)
563 return 0;
565 r26 |= (sel & 0x01) << 7;
566 r27 |= (sel & 0x02) >> 1;
567 lgs8gxx_write_reg(priv, 0x26, r26);
568 lgs8gxx_write_reg(priv, 0x27, r27);
570 return 0;
573 /* LGS8913 demod frontend functions */
575 static int lgs8913_init(struct lgs8gxx_state *priv)
577 u8 t;
579 /* LGS8913 specific */
580 lgs8gxx_write_reg(priv, 0xc1, 0x3);
582 lgs8gxx_read_reg(priv, 0x7c, &t);
583 lgs8gxx_write_reg(priv, 0x7c, (t&0x8c) | 0x3);
585 /* LGS8913 specific */
586 lgs8gxx_read_reg(priv, 0xc3, &t);
587 lgs8gxx_write_reg(priv, 0xc3, t&0x10);
590 return 0;
593 static int lgs8g75_init_data(struct lgs8gxx_state *priv)
595 const struct firmware *fw;
596 int rc;
597 int i;
599 rc = request_firmware(&fw, "lgs8g75.fw", &priv->i2c->dev);
600 if (rc)
601 return rc;
603 lgs8gxx_write_reg(priv, 0xC6, 0x40);
605 lgs8gxx_write_reg(priv, 0x3D, 0x04);
606 lgs8gxx_write_reg(priv, 0x39, 0x00);
608 lgs8gxx_write_reg(priv, 0x3A, 0x00);
609 lgs8gxx_write_reg(priv, 0x38, 0x00);
610 lgs8gxx_write_reg(priv, 0x3B, 0x00);
611 lgs8gxx_write_reg(priv, 0x38, 0x00);
613 for (i = 0; i < fw->size; i++) {
614 lgs8gxx_write_reg(priv, 0x38, 0x00);
615 lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff));
616 lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8));
617 lgs8gxx_write_reg(priv, 0x3C, fw->data[i]);
620 lgs8gxx_write_reg(priv, 0x38, 0x00);
622 release_firmware(fw);
623 return 0;
626 static int lgs8gxx_init(struct dvb_frontend *fe)
628 struct lgs8gxx_state *priv =
629 (struct lgs8gxx_state *)fe->demodulator_priv;
630 const struct lgs8gxx_config *config = priv->config;
631 u8 data = 0;
632 s8 err;
633 dprintk("%s\n", __func__);
635 lgs8gxx_read_reg(priv, 0, &data);
636 dprintk("reg 0 = 0x%02X\n", data);
638 if (config->prod == LGS8GXX_PROD_LGS8G75)
639 lgs8g75_set_adc_vpp(priv, config->adc_vpp);
641 /* Setup MPEG output format */
642 err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts,
643 config->ts_clk_pol,
644 config->ts_clk_gated);
645 if (err != 0)
646 return -EIO;
648 if (config->prod == LGS8GXX_PROD_LGS8913)
649 lgs8913_init(priv);
650 lgs8gxx_set_if_freq(priv, priv->config->if_freq);
651 lgs8gxx_set_ad_mode(priv);
653 return 0;
656 static void lgs8gxx_release(struct dvb_frontend *fe)
658 struct lgs8gxx_state *state = fe->demodulator_priv;
659 dprintk("%s\n", __func__);
661 kfree(state);
665 static int lgs8gxx_write(struct dvb_frontend *fe, u8 *buf, int len)
667 struct lgs8gxx_state *priv = fe->demodulator_priv;
669 if (len != 2)
670 return -EINVAL;
672 return lgs8gxx_write_reg(priv, buf[0], buf[1]);
675 static int lgs8gxx_set_fe(struct dvb_frontend *fe,
676 struct dvb_frontend_parameters *fe_params)
678 struct lgs8gxx_state *priv = fe->demodulator_priv;
680 dprintk("%s\n", __func__);
682 /* set frequency */
683 if (fe->ops.tuner_ops.set_params) {
684 fe->ops.tuner_ops.set_params(fe, fe_params);
685 if (fe->ops.i2c_gate_ctrl)
686 fe->ops.i2c_gate_ctrl(fe, 0);
689 /* start auto lock */
690 lgs8gxx_auto_lock(priv);
692 msleep(10);
694 return 0;
697 static int lgs8gxx_get_fe(struct dvb_frontend *fe,
698 struct dvb_frontend_parameters *fe_params)
700 dprintk("%s\n", __func__);
702 /* TODO: get real readings from device */
703 /* inversion status */
704 fe_params->inversion = INVERSION_OFF;
706 /* bandwidth */
707 fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
709 fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
710 fe_params->u.ofdm.code_rate_LP = FEC_AUTO;
712 fe_params->u.ofdm.constellation = QAM_AUTO;
714 /* transmission mode */
715 fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
717 /* guard interval */
718 fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
720 /* hierarchy */
721 fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE;
723 return 0;
726 static
727 int lgs8gxx_get_tune_settings(struct dvb_frontend *fe,
728 struct dvb_frontend_tune_settings *fesettings)
730 fesettings->min_delay_ms = 800;
731 fesettings->step_size = 0;
732 fesettings->max_drift = 0;
733 return 0;
736 static int lgs8gxx_read_status(struct dvb_frontend *fe, fe_status_t *fe_status)
738 struct lgs8gxx_state *priv = fe->demodulator_priv;
739 s8 ret;
740 u8 t, locked = 0;
742 dprintk("%s\n", __func__);
743 *fe_status = 0;
745 lgs8gxx_get_afc_phase(priv);
746 lgs8gxx_is_locked(priv, &locked);
747 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
748 if (locked)
749 *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
750 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
751 return 0;
754 ret = lgs8gxx_read_reg(priv, 0x4B, &t);
755 if (ret != 0)
756 return -EIO;
758 dprintk("Reg 0x4B: 0x%02X\n", t);
760 *fe_status = 0;
761 if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
762 if ((t & 0x40) == 0x40)
763 *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
764 if ((t & 0x80) == 0x80)
765 *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC |
766 FE_HAS_LOCK;
767 } else {
768 if ((t & 0x80) == 0x80)
769 *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
770 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
773 /* success */
774 dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
775 return 0;
778 static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal)
780 u16 v;
781 u8 agc_lvl[2], cat;
783 dprintk("%s()\n", __func__);
784 lgs8gxx_read_reg(priv, 0x3F, &agc_lvl[0]);
785 lgs8gxx_read_reg(priv, 0x3E, &agc_lvl[1]);
787 v = agc_lvl[0];
788 v <<= 8;
789 v |= agc_lvl[1];
791 dprintk("agc_lvl: 0x%04X\n", v);
793 if (v < 0x100)
794 cat = 0;
795 else if (v < 0x190)
796 cat = 5;
797 else if (v < 0x2A8)
798 cat = 4;
799 else if (v < 0x381)
800 cat = 3;
801 else if (v < 0x400)
802 cat = 2;
803 else if (v == 0x400)
804 cat = 1;
805 else
806 cat = 0;
808 *signal = cat * 65535 / 5;
810 return 0;
813 static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
815 u8 t; s8 ret;
816 s16 max_strength = 0;
817 u8 str;
818 u16 i, gi = priv->curr_gi;
820 dprintk("%s\n", __func__);
822 ret = lgs8gxx_read_reg(priv, 0x4B, &t);
823 if (ret != 0)
824 return -EIO;
826 if (fake_signal_str) {
827 if ((t & 0xC0) == 0xC0) {
828 dprintk("Fake signal strength\n");
829 *signal = 0x7FFF;
830 } else
831 *signal = 0;
832 return 0;
835 dprintk("gi = %d\n", gi);
836 for (i = 0; i < gi; i++) {
838 if ((i & 0xFF) == 0)
839 lgs8gxx_write_reg(priv, 0x84, 0x03 & (i >> 8));
840 lgs8gxx_write_reg(priv, 0x83, i & 0xFF);
842 lgs8gxx_read_reg(priv, 0x94, &str);
843 if (max_strength < str)
844 max_strength = str;
847 *signal = max_strength;
848 dprintk("%s: signal=0x%02X\n", __func__, *signal);
850 lgs8gxx_read_reg(priv, 0x95, &t);
851 dprintk("%s: AVG Noise=0x%02X\n", __func__, t);
853 return 0;
856 static int lgs8g75_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
858 u8 t;
859 s16 v = 0;
861 dprintk("%s\n", __func__);
863 lgs8gxx_read_reg(priv, 0xB1, &t);
864 v |= t;
865 v <<= 8;
866 lgs8gxx_read_reg(priv, 0xB0, &t);
867 v |= t;
869 *signal = v;
870 dprintk("%s: signal=0x%02X\n", __func__, *signal);
872 return 0;
875 static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal)
877 struct lgs8gxx_state *priv = fe->demodulator_priv;
879 if (priv->config->prod == LGS8GXX_PROD_LGS8913)
880 return lgs8913_read_signal_strength(priv, signal);
881 else if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
882 return lgs8g75_read_signal_strength(priv, signal);
883 else
884 return lgs8gxx_read_signal_agc(priv, signal);
887 static int lgs8gxx_read_snr(struct dvb_frontend *fe, u16 *snr)
889 struct lgs8gxx_state *priv = fe->demodulator_priv;
890 u8 t;
891 *snr = 0;
893 if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
894 lgs8gxx_read_reg(priv, 0x34, &t);
895 else
896 lgs8gxx_read_reg(priv, 0x95, &t);
897 dprintk("AVG Noise=0x%02X\n", t);
898 *snr = 256 - t;
899 *snr <<= 8;
900 dprintk("snr=0x%x\n", *snr);
902 return 0;
905 static int lgs8gxx_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
907 *ucblocks = 0;
908 dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
909 return 0;
912 static void packet_counter_start(struct lgs8gxx_state *priv)
914 u8 orig, t;
916 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
917 lgs8gxx_read_reg(priv, 0x30, &orig);
918 orig &= 0xE7;
919 t = orig | 0x10;
920 lgs8gxx_write_reg(priv, 0x30, t);
921 t = orig | 0x18;
922 lgs8gxx_write_reg(priv, 0x30, t);
923 t = orig | 0x10;
924 lgs8gxx_write_reg(priv, 0x30, t);
925 } else {
926 lgs8gxx_write_reg(priv, 0xC6, 0x01);
927 lgs8gxx_write_reg(priv, 0xC6, 0x41);
928 lgs8gxx_write_reg(priv, 0xC6, 0x01);
932 static void packet_counter_stop(struct lgs8gxx_state *priv)
934 u8 t;
936 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
937 lgs8gxx_read_reg(priv, 0x30, &t);
938 t &= 0xE7;
939 lgs8gxx_write_reg(priv, 0x30, t);
940 } else {
941 lgs8gxx_write_reg(priv, 0xC6, 0x81);
945 static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber)
947 struct lgs8gxx_state *priv = fe->demodulator_priv;
948 u8 reg_err, reg_total, t;
949 u32 total_cnt = 0, err_cnt = 0;
950 int i;
952 dprintk("%s\n", __func__);
954 packet_counter_start(priv);
955 msleep(200);
956 packet_counter_stop(priv);
958 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
959 reg_total = 0x28; reg_err = 0x2C;
960 } else {
961 reg_total = 0xD0; reg_err = 0xD4;
964 for (i = 0; i < 4; i++) {
965 total_cnt <<= 8;
966 lgs8gxx_read_reg(priv, reg_total+3-i, &t);
967 total_cnt |= t;
969 for (i = 0; i < 4; i++) {
970 err_cnt <<= 8;
971 lgs8gxx_read_reg(priv, reg_err+3-i, &t);
972 err_cnt |= t;
974 dprintk("error=%d total=%d\n", err_cnt, total_cnt);
976 if (total_cnt == 0)
977 *ber = 0;
978 else
979 *ber = err_cnt * 100 / total_cnt;
981 dprintk("%s: ber=0x%x\n", __func__, *ber);
982 return 0;
985 static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
987 struct lgs8gxx_state *priv = fe->demodulator_priv;
989 if (priv->config->tuner_address == 0)
990 return 0;
991 if (enable) {
992 u8 v = 0x80 | priv->config->tuner_address;
993 return lgs8gxx_write_reg(priv, 0x01, v);
995 return lgs8gxx_write_reg(priv, 0x01, 0);
998 static struct dvb_frontend_ops lgs8gxx_ops = {
999 .info = {
1000 .name = "Legend Silicon LGS8913/LGS8GXX DMB-TH",
1001 .type = FE_OFDM,
1002 .frequency_min = 474000000,
1003 .frequency_max = 858000000,
1004 .frequency_stepsize = 10000,
1005 .caps =
1006 FE_CAN_FEC_AUTO |
1007 FE_CAN_QAM_AUTO |
1008 FE_CAN_TRANSMISSION_MODE_AUTO |
1009 FE_CAN_GUARD_INTERVAL_AUTO
1012 .release = lgs8gxx_release,
1014 .init = lgs8gxx_init,
1015 .write = lgs8gxx_write,
1016 .i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl,
1018 .set_frontend = lgs8gxx_set_fe,
1019 .get_frontend = lgs8gxx_get_fe,
1020 .get_tune_settings = lgs8gxx_get_tune_settings,
1022 .read_status = lgs8gxx_read_status,
1023 .read_ber = lgs8gxx_read_ber,
1024 .read_signal_strength = lgs8gxx_read_signal_strength,
1025 .read_snr = lgs8gxx_read_snr,
1026 .read_ucblocks = lgs8gxx_read_ucblocks,
1029 struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
1030 struct i2c_adapter *i2c)
1032 struct lgs8gxx_state *priv = NULL;
1033 u8 data = 0;
1035 dprintk("%s()\n", __func__);
1037 if (config == NULL || i2c == NULL)
1038 return NULL;
1040 priv = kzalloc(sizeof(struct lgs8gxx_state), GFP_KERNEL);
1041 if (priv == NULL)
1042 goto error_out;
1044 priv->config = config;
1045 priv->i2c = i2c;
1047 /* check if the demod is there */
1048 if (lgs8gxx_read_reg(priv, 0, &data) != 0) {
1049 dprintk("%s lgs8gxx not found at i2c addr 0x%02X\n",
1050 __func__, priv->config->demod_address);
1051 goto error_out;
1054 lgs8gxx_read_reg(priv, 1, &data);
1056 memcpy(&priv->frontend.ops, &lgs8gxx_ops,
1057 sizeof(struct dvb_frontend_ops));
1058 priv->frontend.demodulator_priv = priv;
1060 if (config->prod == LGS8GXX_PROD_LGS8G75)
1061 lgs8g75_init_data(priv);
1063 return &priv->frontend;
1065 error_out:
1066 dprintk("%s() error_out\n", __func__);
1067 kfree(priv);
1068 return NULL;
1071 EXPORT_SYMBOL(lgs8gxx_attach);
1073 MODULE_DESCRIPTION("Legend Silicon LGS8913/LGS8GXX DMB-TH demodulator driver");
1074 MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>");
1075 MODULE_LICENSE("GPL");