blob: fde8c59700fbee05d63b6b6433adedd7ec9499a9 [file] [log] [blame]
Michael Krufkycae78ed2009-01-13 04:40:36 -03001/*
2 * Support for LGDT3305 - VSB/QAM
3 *
4 * Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org>
5 *
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
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 */
21
Michael Krufky511da452009-05-28 13:50:36 -030022#include <asm/div64.h>
Michael Krufkycae78ed2009-01-13 04:40:36 -030023#include <linux/dvb/frontend.h>
24#include "dvb_math.h"
25#include "lgdt3305.h"
26
27static int debug;
28module_param(debug, int, 0644);
29MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))");
30
31#define DBG_INFO 1
32#define DBG_REG 2
33
34#define lg_printk(kern, fmt, arg...) \
35 printk(kern "%s: " fmt, __func__, ##arg)
36
37#define lg_info(fmt, arg...) printk(KERN_INFO "lgdt3305: " fmt, ##arg)
38#define lg_warn(fmt, arg...) lg_printk(KERN_WARNING, fmt, ##arg)
39#define lg_err(fmt, arg...) lg_printk(KERN_ERR, fmt, ##arg)
40#define lg_dbg(fmt, arg...) if (debug & DBG_INFO) \
41 lg_printk(KERN_DEBUG, fmt, ##arg)
42#define lg_reg(fmt, arg...) if (debug & DBG_REG) \
43 lg_printk(KERN_DEBUG, fmt, ##arg)
44
45#define lg_fail(ret) \
46({ \
47 int __ret; \
48 __ret = (ret < 0); \
49 if (__ret) \
50 lg_err("error %d on line %d\n", ret, __LINE__); \
51 __ret; \
52})
53
54struct lgdt3305_state {
55 struct i2c_adapter *i2c_adap;
56 const struct lgdt3305_config *cfg;
57
58 struct dvb_frontend frontend;
59
60 fe_modulation_t current_modulation;
61 u32 current_frequency;
62 u32 snr;
63};
64
65/* ------------------------------------------------------------------------ */
66
67#define LGDT3305_GEN_CTRL_1 0x0000
68#define LGDT3305_GEN_CTRL_2 0x0001
69#define LGDT3305_GEN_CTRL_3 0x0002
70#define LGDT3305_GEN_STATUS 0x0003
71#define LGDT3305_GEN_CONTROL 0x0007
72#define LGDT3305_GEN_CTRL_4 0x000a
73#define LGDT3305_DGTL_AGC_REF_1 0x0012
74#define LGDT3305_DGTL_AGC_REF_2 0x0013
75#define LGDT3305_CR_CTR_FREQ_1 0x0106
76#define LGDT3305_CR_CTR_FREQ_2 0x0107
77#define LGDT3305_CR_CTR_FREQ_3 0x0108
78#define LGDT3305_CR_CTR_FREQ_4 0x0109
79#define LGDT3305_CR_MSE_1 0x011b
80#define LGDT3305_CR_MSE_2 0x011c
81#define LGDT3305_CR_LOCK_STATUS 0x011d
82#define LGDT3305_CR_CTRL_7 0x0126
83#define LGDT3305_AGC_POWER_REF_1 0x0300
84#define LGDT3305_AGC_POWER_REF_2 0x0301
85#define LGDT3305_AGC_DELAY_PT_1 0x0302
86#define LGDT3305_AGC_DELAY_PT_2 0x0303
87#define LGDT3305_RFAGC_LOOP_FLTR_BW_1 0x0306
88#define LGDT3305_RFAGC_LOOP_FLTR_BW_2 0x0307
89#define LGDT3305_IFBW_1 0x0308
90#define LGDT3305_IFBW_2 0x0309
91#define LGDT3305_AGC_CTRL_1 0x030c
92#define LGDT3305_AGC_CTRL_4 0x0314
93#define LGDT3305_EQ_MSE_1 0x0413
94#define LGDT3305_EQ_MSE_2 0x0414
95#define LGDT3305_EQ_MSE_3 0x0415
96#define LGDT3305_PT_MSE_1 0x0417
97#define LGDT3305_PT_MSE_2 0x0418
98#define LGDT3305_PT_MSE_3 0x0419
99#define LGDT3305_FEC_BLOCK_CTRL 0x0504
100#define LGDT3305_FEC_LOCK_STATUS 0x050a
101#define LGDT3305_FEC_PKT_ERR_1 0x050c
102#define LGDT3305_FEC_PKT_ERR_2 0x050d
103#define LGDT3305_TP_CTRL_1 0x050e
104#define LGDT3305_BERT_PERIOD 0x0801
105#define LGDT3305_BERT_ERROR_COUNT_1 0x080a
106#define LGDT3305_BERT_ERROR_COUNT_2 0x080b
107#define LGDT3305_BERT_ERROR_COUNT_3 0x080c
108#define LGDT3305_BERT_ERROR_COUNT_4 0x080d
109
110static int lgdt3305_write_reg(struct lgdt3305_state *state, u16 reg, u8 val)
111{
112 int ret;
113 u8 buf[] = { reg >> 8, reg & 0xff, val };
114 struct i2c_msg msg = {
115 .addr = state->cfg->i2c_addr, .flags = 0,
116 .buf = buf, .len = 3,
117 };
118
119 lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);
120
121 ret = i2c_transfer(state->i2c_adap, &msg, 1);
122
123 if (ret != 1) {
124 lg_err("error (addr %02x %02x <- %02x, err = %i)\n",
125 msg.buf[0], msg.buf[1], msg.buf[2], ret);
126 if (ret < 0)
127 return ret;
128 else
129 return -EREMOTEIO;
130 }
131 return 0;
132}
133
134static int lgdt3305_read_reg(struct lgdt3305_state *state, u16 reg, u8 *val)
135{
136 int ret;
137 u8 reg_buf[] = { reg >> 8, reg & 0xff };
138 struct i2c_msg msg[] = {
139 { .addr = state->cfg->i2c_addr,
140 .flags = 0, .buf = reg_buf, .len = 2 },
141 { .addr = state->cfg->i2c_addr,
142 .flags = I2C_M_RD, .buf = val, .len = 1 },
143 };
144
145 lg_reg("reg: 0x%04x\n", reg);
146
147 ret = i2c_transfer(state->i2c_adap, msg, 2);
148
149 if (ret != 2) {
150 lg_err("error (addr %02x reg %04x error (ret == %i)\n",
151 state->cfg->i2c_addr, reg, ret);
152 if (ret < 0)
153 return ret;
154 else
155 return -EREMOTEIO;
156 }
157 return 0;
158}
159
160#define read_reg(state, reg) \
161({ \
162 u8 __val; \
163 int ret = lgdt3305_read_reg(state, reg, &__val); \
164 if (lg_fail(ret)) \
165 __val = 0; \
166 __val; \
167})
168
169static int lgdt3305_set_reg_bit(struct lgdt3305_state *state,
170 u16 reg, int bit, int onoff)
171{
172 u8 val;
173 int ret;
174
175 lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff);
176
177 ret = lgdt3305_read_reg(state, reg, &val);
178 if (lg_fail(ret))
179 goto fail;
180
181 val &= ~(1 << bit);
182 val |= (onoff & 1) << bit;
183
184 ret = lgdt3305_write_reg(state, reg, val);
185fail:
186 return ret;
187}
188
189struct lgdt3305_reg {
190 u16 reg;
191 u8 val;
192};
193
194static int lgdt3305_write_regs(struct lgdt3305_state *state,
195 struct lgdt3305_reg *regs, int len)
196{
197 int i, ret;
198
199 lg_reg("writing %d registers...\n", len);
200
201 for (i = 0; i < len - 1; i++) {
202 ret = lgdt3305_write_reg(state, regs[i].reg, regs[i].val);
203 if (lg_fail(ret))
204 return ret;
205 }
206 return 0;
207}
208
209/* ------------------------------------------------------------------------ */
210
211static int lgdt3305_soft_reset(struct lgdt3305_state *state)
212{
213 int ret;
214
215 lg_dbg("\n");
216
217 ret = lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_3, 0, 0);
218 if (lg_fail(ret))
219 goto fail;
220
221 msleep(20);
222 ret = lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_3, 0, 1);
223fail:
224 return ret;
225}
226
227static inline int lgdt3305_mpeg_mode(struct lgdt3305_state *state,
228 enum lgdt3305_mpeg_mode mode)
229{
230 lg_dbg("(%d)\n", mode);
231 return lgdt3305_set_reg_bit(state, LGDT3305_TP_CTRL_1, 5, mode);
232}
233
234static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state,
235 enum lgdt3305_tp_clock_edge edge,
236 enum lgdt3305_tp_valid_polarity valid)
237{
238 u8 val;
239 int ret;
240
241 lg_dbg("edge = %d, valid = %d\n", edge, valid);
242
243 ret = lgdt3305_read_reg(state, LGDT3305_TP_CTRL_1, &val);
244 if (lg_fail(ret))
245 goto fail;
246
247 val &= ~0x09;
248
249 if (edge)
250 val |= 0x08;
251 if (valid)
252 val |= 0x01;
253
254 ret = lgdt3305_write_reg(state, LGDT3305_TP_CTRL_1, val);
255 if (lg_fail(ret))
256 goto fail;
257
258 ret = lgdt3305_soft_reset(state);
259fail:
260 return ret;
261}
262
263static int lgdt3305_set_modulation(struct lgdt3305_state *state,
264 struct dvb_frontend_parameters *param)
265{
266 u8 opermode;
267 int ret;
268
269 lg_dbg("\n");
270
271 ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_1, &opermode);
272 if (lg_fail(ret))
273 goto fail;
274
275 opermode &= ~0x03;
276
277 switch (param->u.vsb.modulation) {
278 case VSB_8:
279 opermode |= 0x03;
280 break;
281 case QAM_64:
282 opermode |= 0x00;
283 break;
284 case QAM_256:
285 opermode |= 0x01;
286 break;
287 default:
288 return -EINVAL;
289 }
290 ret = lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_1, opermode);
291fail:
292 return ret;
293}
294
295static int lgdt3305_set_filter_extension(struct lgdt3305_state *state,
296 struct dvb_frontend_parameters *param)
297{
298 int val;
299
300 switch (param->u.vsb.modulation) {
301 case VSB_8:
302 val = 0;
303 break;
304 case QAM_64:
305 case QAM_256:
306 val = 1;
307 break;
308 default:
309 return -EINVAL;
310 }
311 lg_dbg("val = %d\n", val);
312
313 return lgdt3305_set_reg_bit(state, 0x043f, 2, val);
314}
315
316/* ------------------------------------------------------------------------ */
317
318static int lgdt3305_passband_digital_agc(struct lgdt3305_state *state,
319 struct dvb_frontend_parameters *param)
320{
321 u16 agc_ref;
322
323 switch (param->u.vsb.modulation) {
324 case VSB_8:
325 agc_ref = 0x32c4;
326 break;
327 case QAM_64:
328 agc_ref = 0x2a00;
329 break;
330 case QAM_256:
331 agc_ref = 0x2a80;
332 break;
333 default:
334 return -EINVAL;
335 }
336
337 lg_dbg("agc ref: 0x%04x\n", agc_ref);
338
339 lgdt3305_write_reg(state, LGDT3305_DGTL_AGC_REF_1, agc_ref >> 8);
340 lgdt3305_write_reg(state, LGDT3305_DGTL_AGC_REF_2, agc_ref & 0xff);
341
342 return 0;
343}
344
345static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,
346 struct dvb_frontend_parameters *param)
347{
348 u16 ifbw, rfbw, agcdelay;
349
350 switch (param->u.vsb.modulation) {
351 case VSB_8:
352 agcdelay = 0x04c0;
353 rfbw = 0x8000;
354 ifbw = 0x8000;
355 break;
356 case QAM_64:
357 case QAM_256:
358 agcdelay = 0x046b;
359 rfbw = 0x8889;
360 ifbw = 0x8888;
361 break;
362 default:
363 return -EINVAL;
364 }
365
366 if (state->cfg->rf_agc_loop) {
367 lg_dbg("agcdelay: 0x%04x, rfbw: 0x%04x\n", agcdelay, rfbw);
368
369 /* rf agc loop filter bandwidth */
370 lgdt3305_write_reg(state, LGDT3305_AGC_DELAY_PT_1,
371 agcdelay >> 8);
372 lgdt3305_write_reg(state, LGDT3305_AGC_DELAY_PT_2,
373 agcdelay & 0xff);
374
375 lgdt3305_write_reg(state, LGDT3305_RFAGC_LOOP_FLTR_BW_1,
376 rfbw >> 8);
377 lgdt3305_write_reg(state, LGDT3305_RFAGC_LOOP_FLTR_BW_2,
378 rfbw & 0xff);
379 } else {
380 lg_dbg("ifbw: 0x%04x\n", ifbw);
381
382 /* if agc loop filter bandwidth */
383 lgdt3305_write_reg(state, LGDT3305_IFBW_1, ifbw >> 8);
384 lgdt3305_write_reg(state, LGDT3305_IFBW_2, ifbw & 0xff);
385 }
386
387 return 0;
388}
389
390static int lgdt3305_agc_setup(struct lgdt3305_state *state,
391 struct dvb_frontend_parameters *param)
392{
393 int lockdten, acqen;
394
395 switch (param->u.vsb.modulation) {
396 case VSB_8:
397 lockdten = 0;
398 acqen = 0;
399 break;
400 case QAM_64:
401 case QAM_256:
402 lockdten = 1;
403 acqen = 1;
404 break;
405 default:
406 return -EINVAL;
407 }
408
409 lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen);
410
411 /* control agc function */
412 lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
413 lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
414
415 return lgdt3305_rfagc_loop(state, param);
416}
417
418static int lgdt3305_set_agc_power_ref(struct lgdt3305_state *state,
419 struct dvb_frontend_parameters *param)
420{
421 u16 usref = 0;
422
423 switch (param->u.vsb.modulation) {
424 case VSB_8:
425 if (state->cfg->usref_8vsb)
426 usref = state->cfg->usref_8vsb;
427 break;
428 case QAM_64:
429 if (state->cfg->usref_qam64)
430 usref = state->cfg->usref_qam64;
431 break;
432 case QAM_256:
433 if (state->cfg->usref_qam256)
434 usref = state->cfg->usref_qam256;
435 break;
436 default:
437 return -EINVAL;
438 }
439
440 if (usref) {
441 lg_dbg("set manual mode: 0x%04x\n", usref);
442
443 lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 3, 1);
444
445 lgdt3305_write_reg(state, LGDT3305_AGC_POWER_REF_1,
446 0xff & (usref >> 8));
447 lgdt3305_write_reg(state, LGDT3305_AGC_POWER_REF_2,
448 0xff & (usref >> 0));
449 }
450 return 0;
451}
452
453/* ------------------------------------------------------------------------ */
454
455static int lgdt3305_spectral_inversion(struct lgdt3305_state *state,
456 struct dvb_frontend_parameters *param,
457 int inversion)
458{
459 int ret;
460
461 lg_dbg("(%d)\n", inversion);
462
463 switch (param->u.vsb.modulation) {
464 case VSB_8:
465 ret = lgdt3305_write_reg(state, LGDT3305_CR_CTRL_7,
466 inversion ? 0xf9 : 0x79);
467 break;
468 case QAM_64:
469 case QAM_256:
470 ret = lgdt3305_write_reg(state, LGDT3305_FEC_BLOCK_CTRL,
471 inversion ? 0xfd : 0xff);
472 break;
473 default:
474 ret = -EINVAL;
475 }
476 return ret;
477}
478
479static int lgdt3305_set_if(struct lgdt3305_state *state,
480 struct dvb_frontend_parameters *param)
481{
482 u16 if_freq_khz;
483 u8 nco1, nco2, nco3, nco4;
484 u64 nco;
485
486 switch (param->u.vsb.modulation) {
487 case VSB_8:
488 if_freq_khz = state->cfg->vsb_if_khz;
489 break;
490 case QAM_64:
491 case QAM_256:
492 if_freq_khz = state->cfg->qam_if_khz;
493 break;
494 default:
495 return -EINVAL;
496 }
497
498 nco = if_freq_khz / 10;
499
Michael Krufkycae78ed2009-01-13 04:40:36 -0300500 switch (param->u.vsb.modulation) {
501 case VSB_8:
Michael Krufkycae78ed2009-01-13 04:40:36 -0300502 nco <<= 24;
Michael Krufky511da452009-05-28 13:50:36 -0300503 do_div(nco, 625);
Michael Krufkycae78ed2009-01-13 04:40:36 -0300504 break;
505 case QAM_64:
506 case QAM_256:
Michael Krufkycae78ed2009-01-13 04:40:36 -0300507 nco <<= 28;
Michael Krufky511da452009-05-28 13:50:36 -0300508 do_div(nco, 625);
Michael Krufkycae78ed2009-01-13 04:40:36 -0300509 break;
510 default:
511 return -EINVAL;
512 }
513
514 nco1 = (nco >> 24) & 0x3f;
515 nco1 |= 0x40;
516 nco2 = (nco >> 16) & 0xff;
517 nco3 = (nco >> 8) & 0xff;
518 nco4 = nco & 0xff;
519
520 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, nco1);
521 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, nco2);
522 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, nco3);
523 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, nco4);
524
525 lg_dbg("%d KHz -> [%02x%02x%02x%02x]\n",
526 if_freq_khz, nco1, nco2, nco3, nco4);
527
528 return 0;
529}
530
531/* ------------------------------------------------------------------------ */
532
533static int lgdt3305_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
534{
535 struct lgdt3305_state *state = fe->demodulator_priv;
536
537 if (state->cfg->deny_i2c_rptr)
538 return 0;
539
540 lg_dbg("(%d)\n", enable);
541
542 return lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_2, 5,
543 enable ? 0 : 1);
544}
545
546static int lgdt3305_sleep(struct dvb_frontend *fe)
547{
548 struct lgdt3305_state *state = fe->demodulator_priv;
549 u8 gen_ctrl_3, gen_ctrl_4;
550
551 lg_dbg("\n");
552
553 gen_ctrl_3 = read_reg(state, LGDT3305_GEN_CTRL_3);
554 gen_ctrl_4 = read_reg(state, LGDT3305_GEN_CTRL_4);
555
556 /* hold in software reset while sleeping */
557 gen_ctrl_3 &= ~0x01;
558 /* tristate the IF-AGC pin */
559 gen_ctrl_3 |= 0x02;
560 /* tristate the RF-AGC pin */
561 gen_ctrl_3 |= 0x04;
562
563 /* disable vsb/qam module */
564 gen_ctrl_4 &= ~0x01;
565 /* disable adc module */
566 gen_ctrl_4 &= ~0x02;
567
568 lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_3, gen_ctrl_3);
569 lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_4, gen_ctrl_4);
570
571 return 0;
572}
573
574static int lgdt3305_init(struct dvb_frontend *fe)
575{
576 struct lgdt3305_state *state = fe->demodulator_priv;
577 int ret;
578
579 static struct lgdt3305_reg lgdt3305_init_data[] = {
580 { .reg = LGDT3305_GEN_CTRL_1,
581 .val = 0x03, },
582 { .reg = LGDT3305_GEN_CTRL_2,
583 .val = 0xb0, },
584 { .reg = LGDT3305_GEN_CTRL_3,
585 .val = 0x01, },
586 { .reg = LGDT3305_GEN_CONTROL,
587 .val = 0x6f, },
588 { .reg = LGDT3305_GEN_CTRL_4,
589 .val = 0x03, },
590 { .reg = LGDT3305_DGTL_AGC_REF_1,
591 .val = 0x32, },
592 { .reg = LGDT3305_DGTL_AGC_REF_2,
593 .val = 0xc4, },
594 { .reg = LGDT3305_CR_CTR_FREQ_1,
595 .val = 0x00, },
596 { .reg = LGDT3305_CR_CTR_FREQ_2,
597 .val = 0x00, },
598 { .reg = LGDT3305_CR_CTR_FREQ_3,
599 .val = 0x00, },
600 { .reg = LGDT3305_CR_CTR_FREQ_4,
601 .val = 0x00, },
602 { .reg = LGDT3305_CR_CTRL_7,
603 .val = 0x79, },
604 { .reg = LGDT3305_AGC_POWER_REF_1,
605 .val = 0x32, },
606 { .reg = LGDT3305_AGC_POWER_REF_2,
607 .val = 0xc4, },
608 { .reg = LGDT3305_AGC_DELAY_PT_1,
609 .val = 0x0d, },
610 { .reg = LGDT3305_AGC_DELAY_PT_2,
611 .val = 0x30, },
612 { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1,
613 .val = 0x80, },
614 { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2,
615 .val = 0x00, },
616 { .reg = LGDT3305_IFBW_1,
617 .val = 0x80, },
618 { .reg = LGDT3305_IFBW_2,
619 .val = 0x00, },
620 { .reg = LGDT3305_AGC_CTRL_1,
621 .val = 0x30, },
622 { .reg = LGDT3305_AGC_CTRL_4,
623 .val = 0x61, },
624 { .reg = LGDT3305_FEC_BLOCK_CTRL,
625 .val = 0xff, },
626 { .reg = LGDT3305_TP_CTRL_1,
627 .val = 0x1b, },
628 };
629
630 lg_dbg("\n");
631
632 ret = lgdt3305_write_regs(state, lgdt3305_init_data,
633 ARRAY_SIZE(lgdt3305_init_data));
634 if (lg_fail(ret))
635 goto fail;
636
637 ret = lgdt3305_soft_reset(state);
638fail:
639 return ret;
640}
641
642static int lgdt3305_set_parameters(struct dvb_frontend *fe,
643 struct dvb_frontend_parameters *param)
644{
645 struct lgdt3305_state *state = fe->demodulator_priv;
646 int ret;
647
648 lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation);
649
650 if (fe->ops.tuner_ops.set_params) {
651 ret = fe->ops.tuner_ops.set_params(fe, param);
652 if (fe->ops.i2c_gate_ctrl)
653 fe->ops.i2c_gate_ctrl(fe, 0);
654 if (lg_fail(ret))
655 goto fail;
656 state->current_frequency = param->frequency;
657 }
658
659 ret = lgdt3305_set_modulation(state, param);
660 if (lg_fail(ret))
661 goto fail;
662
663 ret = lgdt3305_passband_digital_agc(state, param);
664 if (lg_fail(ret))
665 goto fail;
666 ret = lgdt3305_set_agc_power_ref(state, param);
667 if (lg_fail(ret))
668 goto fail;
669 ret = lgdt3305_agc_setup(state, param);
670 if (lg_fail(ret))
671 goto fail;
672
673 /* low if */
674 ret = lgdt3305_write_reg(state, LGDT3305_GEN_CONTROL, 0x2f);
675 if (lg_fail(ret))
676 goto fail;
677 ret = lgdt3305_set_reg_bit(state, LGDT3305_CR_CTR_FREQ_1, 6, 1);
678 if (lg_fail(ret))
679 goto fail;
680
681 ret = lgdt3305_set_if(state, param);
682 if (lg_fail(ret))
683 goto fail;
684 ret = lgdt3305_spectral_inversion(state, param,
685 state->cfg->spectral_inversion
686 ? 1 : 0);
687 if (lg_fail(ret))
688 goto fail;
689
690 ret = lgdt3305_set_filter_extension(state, param);
691 if (lg_fail(ret))
692 goto fail;
693
694 state->current_modulation = param->u.vsb.modulation;
695
696 ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
697 if (lg_fail(ret))
698 goto fail;
699
700 /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
701 ret = lgdt3305_mpeg_mode_polarity(state,
702 state->cfg->tpclk_edge,
703 state->cfg->tpvalid_polarity);
704fail:
705 return ret;
706}
707
708static int lgdt3305_get_frontend(struct dvb_frontend *fe,
709 struct dvb_frontend_parameters *param)
710{
711 struct lgdt3305_state *state = fe->demodulator_priv;
712
713 lg_dbg("\n");
714
715 param->u.vsb.modulation = state->current_modulation;
716 param->frequency = state->current_frequency;
717 return 0;
718}
719
720/* ------------------------------------------------------------------------ */
721
722static int lgdt3305_read_cr_lock_status(struct lgdt3305_state *state,
723 int *locked)
724{
725 u8 val;
726 int ret;
727 char *cr_lock_state = "";
728
729 *locked = 0;
730
731 ret = lgdt3305_read_reg(state, LGDT3305_CR_LOCK_STATUS, &val);
732 if (lg_fail(ret))
733 goto fail;
734
735 switch (state->current_modulation) {
736 case QAM_256:
737 case QAM_64:
738 if (val & (1 << 1))
739 *locked = 1;
740
741 switch (val & 0x07) {
742 case 0:
743 cr_lock_state = "QAM UNLOCK";
744 break;
745 case 4:
746 cr_lock_state = "QAM 1stLock";
747 break;
748 case 6:
749 cr_lock_state = "QAM 2ndLock";
750 break;
751 case 7:
752 cr_lock_state = "QAM FinalLock";
753 break;
754 default:
755 cr_lock_state = "CLOCKQAM-INVALID!";
756 break;
757 }
758 break;
759 case VSB_8:
760 if (val & (1 << 7)) {
761 *locked = 1;
762 cr_lock_state = "CLOCKVSB";
763 }
764 break;
765 default:
766 ret = -EINVAL;
767 }
768 lg_dbg("(%d) %s\n", *locked, cr_lock_state);
769fail:
770 return ret;
771}
772
773static int lgdt3305_read_fec_lock_status(struct lgdt3305_state *state,
774 int *locked)
775{
776 u8 val;
777 int ret, mpeg_lock, fec_lock, viterbi_lock;
778
779 *locked = 0;
780
781 switch (state->current_modulation) {
782 case QAM_256:
783 case QAM_64:
784 ret = lgdt3305_read_reg(state,
785 LGDT3305_FEC_LOCK_STATUS, &val);
786 if (lg_fail(ret))
787 goto fail;
788
789 mpeg_lock = (val & (1 << 0)) ? 1 : 0;
790 fec_lock = (val & (1 << 2)) ? 1 : 0;
791 viterbi_lock = (val & (1 << 3)) ? 1 : 0;
792
793 *locked = mpeg_lock && fec_lock && viterbi_lock;
794
795 lg_dbg("(%d) %s%s%s\n", *locked,
796 mpeg_lock ? "mpeg lock " : "",
797 fec_lock ? "fec lock " : "",
798 viterbi_lock ? "viterbi lock" : "");
799 break;
800 case VSB_8:
801 default:
802 ret = -EINVAL;
803 }
804fail:
805 return ret;
806}
807
808static int lgdt3305_read_status(struct dvb_frontend *fe, fe_status_t *status)
809{
810 struct lgdt3305_state *state = fe->demodulator_priv;
811 u8 val;
812 int ret, signal, inlock, nofecerr, snrgood,
813 cr_lock, fec_lock, sync_lock;
814
815 *status = 0;
816
817 ret = lgdt3305_read_reg(state, LGDT3305_GEN_STATUS, &val);
818 if (lg_fail(ret))
819 goto fail;
820
821 signal = (val & (1 << 4)) ? 1 : 0;
822 inlock = (val & (1 << 3)) ? 0 : 1;
823 sync_lock = (val & (1 << 2)) ? 1 : 0;
824 nofecerr = (val & (1 << 1)) ? 1 : 0;
825 snrgood = (val & (1 << 0)) ? 1 : 0;
826
827 lg_dbg("%s%s%s%s%s\n",
828 signal ? "SIGNALEXIST " : "",
829 inlock ? "INLOCK " : "",
830 sync_lock ? "SYNCLOCK " : "",
831 nofecerr ? "NOFECERR " : "",
832 snrgood ? "SNRGOOD " : "");
833
834 ret = lgdt3305_read_cr_lock_status(state, &cr_lock);
835 if (lg_fail(ret))
836 goto fail;
837
838 if (signal)
839 *status |= FE_HAS_SIGNAL;
840 if (cr_lock)
841 *status |= FE_HAS_CARRIER;
842 if (nofecerr)
843 *status |= FE_HAS_VITERBI;
844 if (sync_lock)
845 *status |= FE_HAS_SYNC;
846
847 switch (state->current_modulation) {
848 case QAM_256:
849 case QAM_64:
850 ret = lgdt3305_read_fec_lock_status(state, &fec_lock);
851 if (lg_fail(ret))
852 goto fail;
853
854 if (fec_lock)
855 *status |= FE_HAS_LOCK;
856 break;
857 case VSB_8:
858 if (inlock)
859 *status |= FE_HAS_LOCK;
860 break;
861 default:
862 ret = -EINVAL;
863 }
864fail:
865 return ret;
866}
867
868/* ------------------------------------------------------------------------ */
869
870/* borrowed from lgdt330x.c */
871static u32 calculate_snr(u32 mse, u32 c)
872{
873 if (mse == 0) /* no signal */
874 return 0;
875
876 mse = intlog10(mse);
877 if (mse > c) {
878 /* Negative SNR, which is possible, but realisticly the
879 demod will lose lock before the signal gets this bad. The
880 API only allows for unsigned values, so just return 0 */
881 return 0;
882 }
883 return 10*(c - mse);
884}
885
886static int lgdt3305_read_snr(struct dvb_frontend *fe, u16 *snr)
887{
888 struct lgdt3305_state *state = fe->demodulator_priv;
889 u32 noise; /* noise value */
890 u32 c; /* per-modulation SNR calculation constant */
891
892 switch (state->current_modulation) {
893 case VSB_8:
894#ifdef USE_PTMSE
895 /* Use Phase Tracker Mean-Square Error Register */
896 /* SNR for ranges from -13.11 to +44.08 */
897 noise = ((read_reg(state, LGDT3305_PT_MSE_1) & 0x07) << 16) |
898 (read_reg(state, LGDT3305_PT_MSE_2) << 8) |
899 (read_reg(state, LGDT3305_PT_MSE_3) & 0xff);
900 c = 73957994; /* log10(25*32^2)*2^24 */
901#else
902 /* Use Equalizer Mean-Square Error Register */
903 /* SNR for ranges from -16.12 to +44.08 */
904 noise = ((read_reg(state, LGDT3305_EQ_MSE_1) & 0x0f) << 16) |
905 (read_reg(state, LGDT3305_EQ_MSE_2) << 8) |
906 (read_reg(state, LGDT3305_EQ_MSE_3) & 0xff);
907 c = 73957994; /* log10(25*32^2)*2^24 */
908#endif
909 break;
910 case QAM_64:
911 case QAM_256:
912 noise = (read_reg(state, LGDT3305_CR_MSE_1) << 8) |
913 (read_reg(state, LGDT3305_CR_MSE_2) & 0xff);
914
915 c = (state->current_modulation == QAM_64) ?
916 97939837 : 98026066;
917 /* log10(688128)*2^24 and log10(696320)*2^24 */
918 break;
919 default:
920 return -EINVAL;
921 }
922 state->snr = calculate_snr(noise, c);
Michael Krufky60ce3c42009-03-11 01:47:53 -0300923 /* report SNR in dB * 10 */
Michael Krufkycae78ed2009-01-13 04:40:36 -0300924 *snr = (state->snr / ((1 << 24) / 10));
925 lg_dbg("noise = 0x%08x, snr = %d.%02d dB\n", noise,
926 state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
927
928 return 0;
929}
930
931static int lgdt3305_read_signal_strength(struct dvb_frontend *fe,
932 u16 *strength)
933{
934 /* borrowed from lgdt330x.c
935 *
936 * Calculate strength from SNR up to 35dB
937 * Even though the SNR can go higher than 35dB,
938 * there is some comfort factor in having a range of
939 * strong signals that can show at 100%
940 */
941 struct lgdt3305_state *state = fe->demodulator_priv;
942 u16 snr;
943 int ret;
944
945 *strength = 0;
946
947 ret = fe->ops.read_snr(fe, &snr);
948 if (lg_fail(ret))
949 goto fail;
950 /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
951 /* scale the range 0 - 35*2^24 into 0 - 65535 */
952 if (state->snr >= 8960 * 0x10000)
953 *strength = 0xffff;
954 else
955 *strength = state->snr / 8960;
956fail:
957 return ret;
958}
959
960/* ------------------------------------------------------------------------ */
961
962static int lgdt3305_read_ber(struct dvb_frontend *fe, u32 *ber)
963{
964 *ber = 0;
965 return 0;
966}
967
968static int lgdt3305_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
969{
970 struct lgdt3305_state *state = fe->demodulator_priv;
971
972 *ucblocks =
973 (read_reg(state, LGDT3305_FEC_PKT_ERR_1) << 8) |
974 (read_reg(state, LGDT3305_FEC_PKT_ERR_2) & 0xff);
975
976 return 0;
977}
978
979static int lgdt3305_get_tune_settings(struct dvb_frontend *fe,
980 struct dvb_frontend_tune_settings
981 *fe_tune_settings)
982{
983 fe_tune_settings->min_delay_ms = 500;
984 lg_dbg("\n");
985 return 0;
986}
987
988static void lgdt3305_release(struct dvb_frontend *fe)
989{
990 struct lgdt3305_state *state = fe->demodulator_priv;
991 lg_dbg("\n");
992 kfree(state);
993}
994
995static struct dvb_frontend_ops lgdt3305_ops;
996
997struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
998 struct i2c_adapter *i2c_adap)
999{
1000 struct lgdt3305_state *state = NULL;
1001 int ret;
1002 u8 val;
1003
1004 lg_dbg("(%d-%04x)\n",
1005 i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
1006 config ? config->i2c_addr : 0);
1007
1008 state = kzalloc(sizeof(struct lgdt3305_state), GFP_KERNEL);
1009 if (state == NULL)
1010 goto fail;
1011
1012 state->cfg = config;
1013 state->i2c_adap = i2c_adap;
1014
1015 memcpy(&state->frontend.ops, &lgdt3305_ops,
1016 sizeof(struct dvb_frontend_ops));
1017 state->frontend.demodulator_priv = state;
1018
1019 /* verify that we're talking to a lg dt3305 */
1020 ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val);
1021 if ((lg_fail(ret)) | (val == 0))
1022 goto fail;
1023 ret = lgdt3305_write_reg(state, 0x0808, 0x80);
1024 if (lg_fail(ret))
1025 goto fail;
1026 ret = lgdt3305_read_reg(state, 0x0808, &val);
1027 if ((lg_fail(ret)) | (val != 0x80))
1028 goto fail;
1029 ret = lgdt3305_write_reg(state, 0x0808, 0x00);
1030 if (lg_fail(ret))
1031 goto fail;
1032
1033 state->current_frequency = -1;
1034 state->current_modulation = -1;
1035
1036 return &state->frontend;
1037fail:
1038 lg_warn("unable to detect LGDT3305 hardware\n");
Michael Krufkycae78ed2009-01-13 04:40:36 -03001039 kfree(state);
1040 return NULL;
1041}
1042EXPORT_SYMBOL(lgdt3305_attach);
1043
1044static struct dvb_frontend_ops lgdt3305_ops = {
1045 .info = {
1046 .name = "LG Electronics LGDT3305 VSB/QAM Frontend",
1047 .type = FE_ATSC,
1048 .frequency_min = 54000000,
1049 .frequency_max = 858000000,
1050 .frequency_stepsize = 62500,
1051 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
1052 },
1053 .i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl,
1054 .init = lgdt3305_init,
1055 .sleep = lgdt3305_sleep,
1056 .set_frontend = lgdt3305_set_parameters,
1057 .get_frontend = lgdt3305_get_frontend,
1058 .get_tune_settings = lgdt3305_get_tune_settings,
1059 .read_status = lgdt3305_read_status,
1060 .read_ber = lgdt3305_read_ber,
1061 .read_signal_strength = lgdt3305_read_signal_strength,
1062 .read_snr = lgdt3305_read_snr,
1063 .read_ucblocks = lgdt3305_read_ucblocks,
1064 .release = lgdt3305_release,
1065};
1066
1067MODULE_DESCRIPTION("LG Electronics LGDT3305 ATSC/QAM-B Demodulator Driver");
Michael Krufky1c121482009-03-11 01:45:44 -03001068MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
Michael Krufkycae78ed2009-01-13 04:40:36 -03001069MODULE_LICENSE("GPL");
Michael Krufky02901522009-03-11 01:46:44 -03001070MODULE_VERSION("0.1");
Michael Krufkycae78ed2009-01-13 04:40:36 -03001071
1072/*
1073 * Local variables:
1074 * c-basic-offset: 8
1075 * End:
1076 */