blob: d1a914de4180af3b99e60217c3a960a8c604c9c1 [file] [log] [blame]
Fred Richterb63b36f2014-03-24 19:56:00 -03001/*
2 * Support for LGDT3306A - 8VSB/QAM-B
3 *
4 * Copyright (C) 2013 Fred Richter <frichter@hauppauge.com>
5 * - driver structure based on lgdt3305.[ch] by Michael Krufky
6 * - code based on LG3306_V0.35 API by LG Electronics Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23
24#include <asm/div64.h>
25#include <linux/dvb/frontend.h>
26#include "dvb_math.h"
27#include "lgdt3306a.h"
28
29
30static int debug;
31module_param(debug, int, 0644);
32MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))");
33
34#define DBG_INFO 1
35#define DBG_REG 2
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -030036#define DBG_DUMP 4 /* FGR - comment out to remove dump code */
Fred Richterb63b36f2014-03-24 19:56:00 -030037
38#define lg_printk(kern, fmt, arg...) \
39 printk(kern "%s(): " fmt, __func__, ##arg)
40
41#define lg_info(fmt, arg...) printk(KERN_INFO "lgdt3306a: " fmt, ##arg)
42#define lg_warn(fmt, arg...) lg_printk(KERN_WARNING, fmt, ##arg)
43#define lg_err(fmt, arg...) lg_printk(KERN_ERR, fmt, ##arg)
44#define lg_dbg(fmt, arg...) if (debug & DBG_INFO) \
45 lg_printk(KERN_DEBUG, fmt, ##arg)
46#define lg_reg(fmt, arg...) if (debug & DBG_REG) \
47 lg_printk(KERN_DEBUG, fmt, ##arg)
48
49#define lg_chkerr(ret) \
50({ \
51 int __ret; \
52 __ret = (ret < 0); \
53 if (__ret) \
54 lg_err("error %d on line %d\n", ret, __LINE__); \
55 __ret; \
56})
57
58struct lgdt3306a_state {
59 struct i2c_adapter *i2c_adap;
60 const struct lgdt3306a_config *cfg;
61
62 struct dvb_frontend frontend;
63
64 fe_modulation_t current_modulation;
65 u32 current_frequency;
66 u32 snr;
67};
68
69/* -----------------------------------------------
70 LG3306A Register Usage
71 (LG does not really name the registers, so this code does not either)
72 0000 -> 00FF Common control and status
73 1000 -> 10FF Synchronizer control and status
74 1F00 -> 1FFF Smart Antenna control and status
75 2100 -> 21FF VSB Equalizer control and status
76 2800 -> 28FF QAM Equalizer control and status
77 3000 -> 30FF FEC control and status
78 ---------------------------------------------- */
79
Michael Ira Krufkyf883d602014-08-03 15:29:04 -030080enum lgdt3306a_lock_status {
81 LG3306_UNLOCK = 0x00,
82 LG3306_LOCK = 0x01,
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -020083 LG3306_UNKNOWN_LOCK = 0xff
Michael Ira Krufkyf883d602014-08-03 15:29:04 -030084};
Fred Richterb63b36f2014-03-24 19:56:00 -030085
Michael Ira Krufkyf883d602014-08-03 15:29:04 -030086enum lgdt3306a_neverlock_status {
Fred Richterb63b36f2014-03-24 19:56:00 -030087 LG3306_NL_INIT = 0x00,
88 LG3306_NL_PROCESS = 0x01,
89 LG3306_NL_LOCK = 0x02,
90 LG3306_NL_FAIL = 0x03,
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -020091 LG3306_NL_UNKNOWN = 0xff
Michael Ira Krufkyf883d602014-08-03 15:29:04 -030092};
Fred Richterb63b36f2014-03-24 19:56:00 -030093
Michael Ira Krufkyf883d602014-08-03 15:29:04 -030094enum lgdt3306a_modulation {
95 LG3306_VSB = 0x00,
96 LG3306_QAM64 = 0x01,
97 LG3306_QAM256 = 0x02,
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -020098 LG3306_UNKNOWN_MODE = 0xff
Michael Ira Krufkyf883d602014-08-03 15:29:04 -030099};
Fred Richterb63b36f2014-03-24 19:56:00 -0300100
Michael Ira Krufkyf883d602014-08-03 15:29:04 -0300101enum lgdt3306a_lock_check {
Fred Richterb63b36f2014-03-24 19:56:00 -0300102 LG3306_SYNC_LOCK,
103 LG3306_FEC_LOCK,
104 LG3306_TR_LOCK,
105 LG3306_AGC_LOCK,
Michael Ira Krufkyf883d602014-08-03 15:29:04 -0300106};
Fred Richterb63b36f2014-03-24 19:56:00 -0300107
108
109#ifdef DBG_DUMP
110static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state);
111static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state);
112#endif
113
114
115static int lgdt3306a_write_reg(struct lgdt3306a_state *state, u16 reg, u8 val)
116{
117 int ret;
118 u8 buf[] = { reg >> 8, reg & 0xff, val };
119 struct i2c_msg msg = {
120 .addr = state->cfg->i2c_addr, .flags = 0,
121 .buf = buf, .len = 3,
122 };
123
124 lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);
125
126 ret = i2c_transfer(state->i2c_adap, &msg, 1);
127
128 if (ret != 1) {
129 lg_err("error (addr %02x %02x <- %02x, err = %i)\n",
130 msg.buf[0], msg.buf[1], msg.buf[2], ret);
131 if (ret < 0)
132 return ret;
133 else
134 return -EREMOTEIO;
135 }
136 return 0;
137}
138
139static int lgdt3306a_read_reg(struct lgdt3306a_state *state, u16 reg, u8 *val)
140{
141 int ret;
142 u8 reg_buf[] = { reg >> 8, reg & 0xff };
143 struct i2c_msg msg[] = {
144 { .addr = state->cfg->i2c_addr,
145 .flags = 0, .buf = reg_buf, .len = 2 },
146 { .addr = state->cfg->i2c_addr,
147 .flags = I2C_M_RD, .buf = val, .len = 1 },
148 };
149
150 ret = i2c_transfer(state->i2c_adap, msg, 2);
151
152 if (ret != 2) {
153 lg_err("error (addr %02x reg %04x error (ret == %i)\n",
154 state->cfg->i2c_addr, reg, ret);
155 if (ret < 0)
156 return ret;
157 else
158 return -EREMOTEIO;
159 }
160 lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, *val);
161
162 return 0;
163}
164
165#define read_reg(state, reg) \
166({ \
167 u8 __val; \
168 int ret = lgdt3306a_read_reg(state, reg, &__val); \
169 if (lg_chkerr(ret)) \
170 __val = 0; \
171 __val; \
172})
173
174static int lgdt3306a_set_reg_bit(struct lgdt3306a_state *state,
175 u16 reg, int bit, int onoff)
176{
177 u8 val;
178 int ret;
179
180 lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff);
181
182 ret = lgdt3306a_read_reg(state, reg, &val);
183 if (lg_chkerr(ret))
184 goto fail;
185
186 val &= ~(1 << bit);
187 val |= (onoff & 1) << bit;
188
189 ret = lgdt3306a_write_reg(state, reg, val);
190 lg_chkerr(ret);
191fail:
192 return ret;
193}
194
195/* ------------------------------------------------------------------------ */
196
197static int lgdt3306a_soft_reset(struct lgdt3306a_state *state)
198{
199 int ret;
200
201 lg_dbg("\n");
202
203 ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0);
204 if (lg_chkerr(ret))
205 goto fail;
206
207 msleep(20);
208 ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1);
209 lg_chkerr(ret);
210
211fail:
212 return ret;
213}
214
215static int lgdt3306a_mpeg_mode(struct lgdt3306a_state *state,
216 enum lgdt3306a_mpeg_mode mode)
217{
218 u8 val;
219 int ret;
220
221 lg_dbg("(%d)\n", mode);
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300222 /* transport packet format */
223 ret = lgdt3306a_set_reg_bit(state, 0x0071, 7, mode == LGDT3306A_MPEG_PARALLEL?1:0); /* TPSENB=0x80 */
Fred Richterb63b36f2014-03-24 19:56:00 -0300224 if (lg_chkerr(ret))
225 goto fail;
226
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300227 /* start of packet signal duration */
228 ret = lgdt3306a_set_reg_bit(state, 0x0071, 6, 0); /* TPSSOPBITEN=0x40; 0=byte duration, 1=bit duration */
Fred Richterb63b36f2014-03-24 19:56:00 -0300229 if (lg_chkerr(ret))
230 goto fail;
231
232 ret = lgdt3306a_read_reg(state, 0x0070, &val);
233 if (lg_chkerr(ret))
234 goto fail;
235
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300236 val |= 0x10; /* TPCLKSUPB=0x10 */
Fred Richterb63b36f2014-03-24 19:56:00 -0300237
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300238 if (mode == LGDT3306A_MPEG_PARALLEL)
Fred Richterb63b36f2014-03-24 19:56:00 -0300239 val &= ~0x10;
240
241 ret = lgdt3306a_write_reg(state, 0x0070, val);
242 lg_chkerr(ret);
243
244fail:
245 return ret;
246}
247
248static int lgdt3306a_mpeg_mode_polarity(struct lgdt3306a_state *state,
249 enum lgdt3306a_tp_clock_edge edge,
250 enum lgdt3306a_tp_valid_polarity valid)
251{
252 u8 val;
253 int ret;
254
255 lg_dbg("edge=%d, valid=%d\n", edge, valid);
256
257 ret = lgdt3306a_read_reg(state, 0x0070, &val);
258 if (lg_chkerr(ret))
259 goto fail;
260
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300261 val &= ~0x06; /* TPCLKPOL=0x04, TPVALPOL=0x02 */
Fred Richterb63b36f2014-03-24 19:56:00 -0300262
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300263 if (edge == LGDT3306A_TPCLK_RISING_EDGE)
Fred Richterb63b36f2014-03-24 19:56:00 -0300264 val |= 0x04;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300265 if (valid == LGDT3306A_TP_VALID_HIGH)
Fred Richterb63b36f2014-03-24 19:56:00 -0300266 val |= 0x02;
267
268 ret = lgdt3306a_write_reg(state, 0x0070, val);
269 lg_chkerr(ret);
270
271fail:
272 return ret;
273}
274
275static int lgdt3306a_mpeg_tristate(struct lgdt3306a_state *state,
276 int mode)
277{
278 u8 val;
279 int ret;
280
281 lg_dbg("(%d)\n", mode);
282
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300283 if (mode) {
Fred Richterb63b36f2014-03-24 19:56:00 -0300284 ret = lgdt3306a_read_reg(state, 0x0070, &val);
285 if (lg_chkerr(ret))
286 goto fail;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200287 val &= ~0xa8; /* Tristate bus; TPOUTEN=0x80, TPCLKOUTEN=0x20, TPDATAOUTEN=0x08 */
Fred Richterb63b36f2014-03-24 19:56:00 -0300288 ret = lgdt3306a_write_reg(state, 0x0070, val);
289 if (lg_chkerr(ret))
290 goto fail;
291
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300292 ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 1); /* AGCIFOUTENB=0x40; 1=Disable IFAGC pin */
Fred Richterb63b36f2014-03-24 19:56:00 -0300293 if (lg_chkerr(ret))
294 goto fail;
295
296 } else {
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300297 ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 0); /* enable IFAGC pin */
Fred Richterb63b36f2014-03-24 19:56:00 -0300298 if (lg_chkerr(ret))
299 goto fail;
300
301 ret = lgdt3306a_read_reg(state, 0x0070, &val);
302 if (lg_chkerr(ret))
303 goto fail;
304
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200305 val |= 0xa8; /* enable bus */
Fred Richterb63b36f2014-03-24 19:56:00 -0300306 ret = lgdt3306a_write_reg(state, 0x0070, val);
307 if (lg_chkerr(ret))
308 goto fail;
309 }
310
311fail:
312 return ret;
313}
314
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300315static int lgdt3306a_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
Fred Richterb63b36f2014-03-24 19:56:00 -0300316{
317 struct lgdt3306a_state *state = fe->demodulator_priv;
318
319 lg_dbg("acquire=%d\n", acquire);
320
321 return lgdt3306a_mpeg_tristate(state, acquire ? 0 : 1);
322
323}
324
325static int lgdt3306a_power(struct lgdt3306a_state *state,
326 int mode)
327{
328 int ret;
329
330 lg_dbg("(%d)\n", mode);
331
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300332 if (mode == 0) {
333 ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0); /* into reset */
Fred Richterb63b36f2014-03-24 19:56:00 -0300334 if (lg_chkerr(ret))
335 goto fail;
336
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300337 ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 0); /* power down */
Fred Richterb63b36f2014-03-24 19:56:00 -0300338 if (lg_chkerr(ret))
339 goto fail;
340
341 } else {
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300342 ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1); /* out of reset */
Fred Richterb63b36f2014-03-24 19:56:00 -0300343 if (lg_chkerr(ret))
344 goto fail;
345
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300346 ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 1); /* power up */
Fred Richterb63b36f2014-03-24 19:56:00 -0300347 if (lg_chkerr(ret))
348 goto fail;
349 }
350
351#ifdef DBG_DUMP
352 lgdt3306a_DumpAllRegs(state);
353#endif
354fail:
355 return ret;
356}
357
358
359static int lgdt3306a_set_vsb(struct lgdt3306a_state *state)
360{
361 u8 val;
362 int ret;
363
364 lg_dbg("\n");
365
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300366 /* 0. Spectrum inversion detection manual; spectrum inverted */
Fred Richterb63b36f2014-03-24 19:56:00 -0300367 ret = lgdt3306a_read_reg(state, 0x0002, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200368 val &= 0xf7; /* SPECINVAUTO Off */
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300369 val |= 0x04; /* SPECINV On */
Fred Richterb63b36f2014-03-24 19:56:00 -0300370 ret = lgdt3306a_write_reg(state, 0x0002, val);
371 if (lg_chkerr(ret))
372 goto fail;
373
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300374 /* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */
Fred Richterb63b36f2014-03-24 19:56:00 -0300375 ret = lgdt3306a_write_reg(state, 0x0008, 0x80);
376 if (lg_chkerr(ret))
377 goto fail;
378
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300379 /* 2. Bandwidth mode for VSB(6MHz) */
Fred Richterb63b36f2014-03-24 19:56:00 -0300380 ret = lgdt3306a_read_reg(state, 0x0009, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200381 val &= 0xe3;
382 val |= 0x0c; /* STDOPDETTMODE[2:0]=3 */
Fred Richterb63b36f2014-03-24 19:56:00 -0300383 ret = lgdt3306a_write_reg(state, 0x0009, val);
384 if (lg_chkerr(ret))
385 goto fail;
386
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300387 /* 3. QAM mode detection mode(None) */
Fred Richterb63b36f2014-03-24 19:56:00 -0300388 ret = lgdt3306a_read_reg(state, 0x0009, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200389 val &= 0xfc; /* STDOPDETCMODE[1:0]=0 */
Fred Richterb63b36f2014-03-24 19:56:00 -0300390 ret = lgdt3306a_write_reg(state, 0x0009, val);
391 if (lg_chkerr(ret))
392 goto fail;
393
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300394 /* 4. ADC sampling frequency rate(2x sampling) */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200395 ret = lgdt3306a_read_reg(state, 0x000d, &val);
396 val &= 0xbf; /* SAMPLING4XFEN=0 */
397 ret = lgdt3306a_write_reg(state, 0x000d, val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300398 if (lg_chkerr(ret))
399 goto fail;
400
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300401#if 0
402 /* FGR - disable any AICC filtering, testing only */
403
Fred Richterb63b36f2014-03-24 19:56:00 -0300404 ret = lgdt3306a_write_reg(state, 0x0024, 0x00);
405 if (lg_chkerr(ret))
406 goto fail;
407
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300408 /* AICCFIXFREQ0 NT N-1(Video rejection) */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200409 ret = lgdt3306a_write_reg(state, 0x002e, 0x00);
410 ret = lgdt3306a_write_reg(state, 0x002f, 0x00);
Fred Richterb63b36f2014-03-24 19:56:00 -0300411 ret = lgdt3306a_write_reg(state, 0x0030, 0x00);
412
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300413 /* AICCFIXFREQ1 NT N-1(Audio rejection) */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200414 ret = lgdt3306a_write_reg(state, 0x002b, 0x00);
415 ret = lgdt3306a_write_reg(state, 0x002c, 0x00);
416 ret = lgdt3306a_write_reg(state, 0x002d, 0x00);
Fred Richterb63b36f2014-03-24 19:56:00 -0300417
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300418 /* AICCFIXFREQ2 NT Co-Channel(Video rejection) */
Fred Richterb63b36f2014-03-24 19:56:00 -0300419 ret = lgdt3306a_write_reg(state, 0x0028, 0x00);
420 ret = lgdt3306a_write_reg(state, 0x0029, 0x00);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200421 ret = lgdt3306a_write_reg(state, 0x002a, 0x00);
Fred Richterb63b36f2014-03-24 19:56:00 -0300422
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300423 /* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */
Fred Richterb63b36f2014-03-24 19:56:00 -0300424 ret = lgdt3306a_write_reg(state, 0x0025, 0x00);
425 ret = lgdt3306a_write_reg(state, 0x0026, 0x00);
426 ret = lgdt3306a_write_reg(state, 0x0027, 0x00);
427
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300428#else
429 /* FGR - this works well for HVR-1955,1975 */
430
431 /* 5. AICCOPMODE NT N-1 Adj. */
Fred Richterb63b36f2014-03-24 19:56:00 -0300432 ret = lgdt3306a_write_reg(state, 0x0024, 0x5A);
433 if (lg_chkerr(ret))
434 goto fail;
435
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300436 /* AICCFIXFREQ0 NT N-1(Video rejection) */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200437 ret = lgdt3306a_write_reg(state, 0x002e, 0x5A);
438 ret = lgdt3306a_write_reg(state, 0x002f, 0x00);
Fred Richterb63b36f2014-03-24 19:56:00 -0300439 ret = lgdt3306a_write_reg(state, 0x0030, 0x00);
440
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300441 /* AICCFIXFREQ1 NT N-1(Audio rejection) */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200442 ret = lgdt3306a_write_reg(state, 0x002b, 0x36);
443 ret = lgdt3306a_write_reg(state, 0x002c, 0x00);
444 ret = lgdt3306a_write_reg(state, 0x002d, 0x00);
Fred Richterb63b36f2014-03-24 19:56:00 -0300445
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300446 /* AICCFIXFREQ2 NT Co-Channel(Video rejection) */
Fred Richterb63b36f2014-03-24 19:56:00 -0300447 ret = lgdt3306a_write_reg(state, 0x0028, 0x2A);
448 ret = lgdt3306a_write_reg(state, 0x0029, 0x00);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200449 ret = lgdt3306a_write_reg(state, 0x002a, 0x00);
Fred Richterb63b36f2014-03-24 19:56:00 -0300450
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300451 /* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */
Fred Richterb63b36f2014-03-24 19:56:00 -0300452 ret = lgdt3306a_write_reg(state, 0x0025, 0x06);
453 ret = lgdt3306a_write_reg(state, 0x0026, 0x00);
454 ret = lgdt3306a_write_reg(state, 0x0027, 0x00);
455#endif
456
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200457 ret = lgdt3306a_read_reg(state, 0x001e, &val);
458 val &= 0x0f;
459 val |= 0xa0;
460 ret = lgdt3306a_write_reg(state, 0x001e, val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300461
462 ret = lgdt3306a_write_reg(state, 0x0022, 0x08);
463
464 ret = lgdt3306a_write_reg(state, 0x0023, 0xFF);
465
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200466 ret = lgdt3306a_read_reg(state, 0x211f, &val);
467 val &= 0xef;
468 ret = lgdt3306a_write_reg(state, 0x211f, val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300469
470 ret = lgdt3306a_write_reg(state, 0x2173, 0x01);
471
472 ret = lgdt3306a_read_reg(state, 0x1061, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200473 val &= 0xf8;
Fred Richterb63b36f2014-03-24 19:56:00 -0300474 val |= 0x04;
475 ret = lgdt3306a_write_reg(state, 0x1061, val);
476
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200477 ret = lgdt3306a_read_reg(state, 0x103d, &val);
478 val &= 0xcf;
479 ret = lgdt3306a_write_reg(state, 0x103d, val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300480
481 ret = lgdt3306a_write_reg(state, 0x2122, 0x40);
482
483 ret = lgdt3306a_read_reg(state, 0x2141, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200484 val &= 0x3f;
Fred Richterb63b36f2014-03-24 19:56:00 -0300485 ret = lgdt3306a_write_reg(state, 0x2141, val);
486
487 ret = lgdt3306a_read_reg(state, 0x2135, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200488 val &= 0x0f;
Fred Richterb63b36f2014-03-24 19:56:00 -0300489 val |= 0x70;
490 ret = lgdt3306a_write_reg(state, 0x2135, val);
491
492 ret = lgdt3306a_read_reg(state, 0x0003, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200493 val &= 0xf7;
Fred Richterb63b36f2014-03-24 19:56:00 -0300494 ret = lgdt3306a_write_reg(state, 0x0003, val);
495
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200496 ret = lgdt3306a_read_reg(state, 0x001c, &val);
497 val &= 0x7f;
498 ret = lgdt3306a_write_reg(state, 0x001c, val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300499
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300500 /* 6. EQ step size */
Fred Richterb63b36f2014-03-24 19:56:00 -0300501 ret = lgdt3306a_read_reg(state, 0x2179, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200502 val &= 0xf8;
Fred Richterb63b36f2014-03-24 19:56:00 -0300503 ret = lgdt3306a_write_reg(state, 0x2179, val);
504
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200505 ret = lgdt3306a_read_reg(state, 0x217a, &val);
506 val &= 0xf8;
507 ret = lgdt3306a_write_reg(state, 0x217a, val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300508
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300509 /* 7. Reset */
Fred Richterb63b36f2014-03-24 19:56:00 -0300510 ret = lgdt3306a_soft_reset(state);
511 if (lg_chkerr(ret))
512 goto fail;
513
514 lg_dbg("complete\n");
515fail:
516 return ret;
517}
518
519static int lgdt3306a_set_qam(struct lgdt3306a_state *state, int modulation)
520{
521 u8 val;
522 int ret;
523
524 lg_dbg("modulation=%d\n", modulation);
525
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300526 /* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */
Fred Richterb63b36f2014-03-24 19:56:00 -0300527 ret = lgdt3306a_write_reg(state, 0x0008, 0x08);
528 if (lg_chkerr(ret))
529 goto fail;
530
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300531 /* 1a. Spectrum inversion detection to Auto */
Fred Richterb63b36f2014-03-24 19:56:00 -0300532 ret = lgdt3306a_read_reg(state, 0x0002, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200533 val &= 0xfb; /* SPECINV Off */
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300534 val |= 0x08; /* SPECINVAUTO On */
Fred Richterb63b36f2014-03-24 19:56:00 -0300535 ret = lgdt3306a_write_reg(state, 0x0002, val);
536 if (lg_chkerr(ret))
537 goto fail;
538
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300539 /* 2. Bandwidth mode for QAM */
Fred Richterb63b36f2014-03-24 19:56:00 -0300540 ret = lgdt3306a_read_reg(state, 0x0009, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200541 val &= 0xe3; /* STDOPDETTMODE[2:0]=0 VSB Off */
Fred Richterb63b36f2014-03-24 19:56:00 -0300542 ret = lgdt3306a_write_reg(state, 0x0009, val);
543 if (lg_chkerr(ret))
544 goto fail;
545
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300546 /* 3. : 64QAM/256QAM detection(manual, auto) */
Fred Richterb63b36f2014-03-24 19:56:00 -0300547 ret = lgdt3306a_read_reg(state, 0x0009, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200548 val &= 0xfc;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300549 val |= 0x02; /* STDOPDETCMODE[1:0]=1=Manual 2=Auto */
Fred Richterb63b36f2014-03-24 19:56:00 -0300550 ret = lgdt3306a_write_reg(state, 0x0009, val);
551 if (lg_chkerr(ret))
552 goto fail;
553
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300554 /* 3a. : 64QAM/256QAM selection for manual */
Fred Richterb63b36f2014-03-24 19:56:00 -0300555 ret = lgdt3306a_read_reg(state, 0x101a, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200556 val &= 0xf8;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300557 if (modulation == QAM_64)
558 val |= 0x02; /* QMDQMODE[2:0]=2=QAM64 */
559 else
560 val |= 0x04; /* QMDQMODE[2:0]=4=QAM256 */
561
Fred Richterb63b36f2014-03-24 19:56:00 -0300562 ret = lgdt3306a_write_reg(state, 0x101a, val);
563 if (lg_chkerr(ret))
564 goto fail;
565
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300566 /* 4. ADC sampling frequency rate(4x sampling) */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200567 ret = lgdt3306a_read_reg(state, 0x000d, &val);
568 val &= 0xbf;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300569 val |= 0x40; /* SAMPLING4XFEN=1 */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200570 ret = lgdt3306a_write_reg(state, 0x000d, val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300571 if (lg_chkerr(ret))
572 goto fail;
573
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300574 /* 5. No AICC operation in QAM mode */
Fred Richterb63b36f2014-03-24 19:56:00 -0300575 ret = lgdt3306a_read_reg(state, 0x0024, &val);
576 val &= 0x00;
577 ret = lgdt3306a_write_reg(state, 0x0024, val);
578 if (lg_chkerr(ret))
579 goto fail;
580
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300581 /* 6. Reset */
Fred Richterb63b36f2014-03-24 19:56:00 -0300582 ret = lgdt3306a_soft_reset(state);
583 if (lg_chkerr(ret))
584 goto fail;
585
586 lg_dbg("complete\n");
587fail:
588 return ret;
589}
590
591static int lgdt3306a_set_modulation(struct lgdt3306a_state *state,
592 struct dtv_frontend_properties *p)
593{
594 int ret;
595
596 lg_dbg("\n");
597
598 switch (p->modulation) {
599 case VSB_8:
600 ret = lgdt3306a_set_vsb(state);
601 break;
602 case QAM_64:
603 ret = lgdt3306a_set_qam(state, QAM_64);
604 break;
605 case QAM_256:
606 ret = lgdt3306a_set_qam(state, QAM_256);
607 break;
608 default:
609 return -EINVAL;
610 }
611 if (lg_chkerr(ret))
612 goto fail;
613
614 state->current_modulation = p->modulation;
615
616fail:
617 return ret;
618}
619
620/* ------------------------------------------------------------------------ */
621
622static int lgdt3306a_agc_setup(struct lgdt3306a_state *state,
623 struct dtv_frontend_properties *p)
624{
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300625 /* TODO: anything we want to do here??? */
Fred Richterb63b36f2014-03-24 19:56:00 -0300626 lg_dbg("\n");
627
628 switch (p->modulation) {
629 case VSB_8:
630 break;
631 case QAM_64:
632 case QAM_256:
633 break;
634 default:
635 return -EINVAL;
636 }
637 return 0;
638}
639
640/* ------------------------------------------------------------------------ */
641
642static int lgdt3306a_set_inversion(struct lgdt3306a_state *state,
643 int inversion)
644{
645 int ret;
646
647 lg_dbg("(%d)\n", inversion);
648
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300649 ret = lgdt3306a_set_reg_bit(state, 0x0002, 2, inversion ? 1 : 0);
Fred Richterb63b36f2014-03-24 19:56:00 -0300650 return ret;
651}
652
653static int lgdt3306a_set_inversion_auto(struct lgdt3306a_state *state,
654 int enabled)
655{
656 int ret;
657
658 lg_dbg("(%d)\n", enabled);
659
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300660 /* 0=Manual 1=Auto(QAM only) */
661 ret = lgdt3306a_set_reg_bit(state, 0x0002, 3, enabled);/* SPECINVAUTO=0x04 */
Fred Richterb63b36f2014-03-24 19:56:00 -0300662 return ret;
663}
664
665static int lgdt3306a_spectral_inversion(struct lgdt3306a_state *state,
666 struct dtv_frontend_properties *p,
667 int inversion)
668{
669 int ret = 0;
670
671 lg_dbg("(%d)\n", inversion);
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300672#if 0
673/* FGR - spectral_inversion defaults already set for VSB and QAM; can enable later if desired */
Fred Richterb63b36f2014-03-24 19:56:00 -0300674
675 ret = lgdt3306a_set_inversion(state, inversion);
676
677 switch (p->modulation) {
678 case VSB_8:
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300679 ret = lgdt3306a_set_inversion_auto(state, 0); /* Manual only for VSB */
Fred Richterb63b36f2014-03-24 19:56:00 -0300680 break;
681 case QAM_64:
682 case QAM_256:
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300683 ret = lgdt3306a_set_inversion_auto(state, 1); /* Auto ok for QAM */
Fred Richterb63b36f2014-03-24 19:56:00 -0300684 break;
685 default:
686 ret = -EINVAL;
687 }
688#endif
689 return ret;
690}
691
692static int lgdt3306a_set_if(struct lgdt3306a_state *state,
693 struct dtv_frontend_properties *p)
694{
695 int ret;
696 u16 if_freq_khz;
697 u8 nco1, nco2;
698
699 switch (p->modulation) {
700 case VSB_8:
701 if_freq_khz = state->cfg->vsb_if_khz;
702 break;
703 case QAM_64:
704 case QAM_256:
705 if_freq_khz = state->cfg->qam_if_khz;
706 break;
707 default:
708 return -EINVAL;
709 }
710
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300711 switch (if_freq_khz) {
Fred Richterb63b36f2014-03-24 19:56:00 -0300712 default:
713 lg_warn("IF=%d KHz is not supportted, 3250 assumed\n", if_freq_khz);
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300714 /* fallthrough */
Michael Ira Krufky34a5a2f2014-10-25 11:26:15 -0300715 case 3250: /* 3.25Mhz */
Fred Richterb63b36f2014-03-24 19:56:00 -0300716 nco1 = 0x34;
717 nco2 = 0x00;
718 break;
Michael Ira Krufky34a5a2f2014-10-25 11:26:15 -0300719 case 3500: /* 3.50Mhz */
Fred Richterb63b36f2014-03-24 19:56:00 -0300720 nco1 = 0x38;
721 nco2 = 0x00;
722 break;
Michael Ira Krufky34a5a2f2014-10-25 11:26:15 -0300723 case 4000: /* 4.00Mhz */
Fred Richterb63b36f2014-03-24 19:56:00 -0300724 nco1 = 0x40;
725 nco2 = 0x00;
726 break;
Michael Ira Krufky34a5a2f2014-10-25 11:26:15 -0300727 case 5000: /* 5.00Mhz */
Fred Richterb63b36f2014-03-24 19:56:00 -0300728 nco1 = 0x50;
729 nco2 = 0x00;
730 break;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300731 case 5380: /* 5.38Mhz */
Fred Richterb63b36f2014-03-24 19:56:00 -0300732 nco1 = 0x56;
733 nco2 = 0x14;
734 break;
735 }
736 ret = lgdt3306a_write_reg(state, 0x0010, nco1);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -0200737 if (ret)
738 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -0300739 ret = lgdt3306a_write_reg(state, 0x0011, nco2);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -0200740 if (ret)
741 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -0300742
743 lg_dbg("if_freq=%d KHz->[%04x]\n", if_freq_khz, nco1<<8 | nco2);
744
745 return 0;
746}
747
748/* ------------------------------------------------------------------------ */
749
750static int lgdt3306a_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
751{
752 struct lgdt3306a_state *state = fe->demodulator_priv;
753
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300754 if (state->cfg->deny_i2c_rptr) {
Fred Richterb63b36f2014-03-24 19:56:00 -0300755 lg_dbg("deny_i2c_rptr=%d\n", state->cfg->deny_i2c_rptr);
756 return 0;
757 }
758 lg_dbg("(%d)\n", enable);
759
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300760 return lgdt3306a_set_reg_bit(state, 0x0002, 7, enable ? 0 : 1); /* NI2CRPTEN=0x80 */
Fred Richterb63b36f2014-03-24 19:56:00 -0300761}
762
763static int lgdt3306a_sleep(struct lgdt3306a_state *state)
764{
765 int ret;
766
767 lg_dbg("\n");
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300768 state->current_frequency = -1; /* force re-tune, when we wake */
Fred Richterb63b36f2014-03-24 19:56:00 -0300769
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300770 ret = lgdt3306a_mpeg_tristate(state, 1); /* disable data bus */
Fred Richterb63b36f2014-03-24 19:56:00 -0300771 if (lg_chkerr(ret))
772 goto fail;
773
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300774 ret = lgdt3306a_power(state, 0); /* power down */
Fred Richterb63b36f2014-03-24 19:56:00 -0300775 lg_chkerr(ret);
776
777fail:
778 return 0;
779}
780
781static int lgdt3306a_fe_sleep(struct dvb_frontend *fe)
782{
783 struct lgdt3306a_state *state = fe->demodulator_priv;
784
785 return lgdt3306a_sleep(state);
786}
787
788static int lgdt3306a_init(struct dvb_frontend *fe)
789{
790 struct lgdt3306a_state *state = fe->demodulator_priv;
791 u8 val;
792 int ret;
793
794 lg_dbg("\n");
795
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300796 /* 1. Normal operation mode */
797 ret = lgdt3306a_set_reg_bit(state, 0x0001, 0, 1); /* SIMFASTENB=0x01 */
Fred Richterb63b36f2014-03-24 19:56:00 -0300798 if (lg_chkerr(ret))
799 goto fail;
800
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300801 /* 2. Spectrum inversion auto detection (Not valid for VSB) */
Fred Richterb63b36f2014-03-24 19:56:00 -0300802 ret = lgdt3306a_set_inversion_auto(state, 0);
803 if (lg_chkerr(ret))
804 goto fail;
805
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300806 /* 3. Spectrum inversion(According to the tuner configuration) */
Fred Richterb63b36f2014-03-24 19:56:00 -0300807 ret = lgdt3306a_set_inversion(state, 1);
808 if (lg_chkerr(ret))
809 goto fail;
810
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300811 /* 4. Peak-to-peak voltage of ADC input signal */
812 ret = lgdt3306a_set_reg_bit(state, 0x0004, 7, 1); /* ADCSEL1V=0x80=1Vpp; 0x00=2Vpp */
Fred Richterb63b36f2014-03-24 19:56:00 -0300813 if (lg_chkerr(ret))
814 goto fail;
815
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300816 /* 5. ADC output data capture clock phase */
817 ret = lgdt3306a_set_reg_bit(state, 0x0004, 2, 0); /* 0=same phase as ADC clock */
Fred Richterb63b36f2014-03-24 19:56:00 -0300818 if (lg_chkerr(ret))
819 goto fail;
820
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300821 /* 5a. ADC sampling clock source */
822 ret = lgdt3306a_set_reg_bit(state, 0x0004, 3, 0); /* ADCCLKPLLSEL=0x08; 0=use ext clock, not PLL */
Fred Richterb63b36f2014-03-24 19:56:00 -0300823 if (lg_chkerr(ret))
824 goto fail;
825
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300826 /* 6. Automatic PLL set */
827 ret = lgdt3306a_set_reg_bit(state, 0x0005, 6, 0); /* PLLSETAUTO=0x40; 0=off */
Fred Richterb63b36f2014-03-24 19:56:00 -0300828 if (lg_chkerr(ret))
829 goto fail;
830
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300831 if (state->cfg->xtalMHz == 24) { /* 24MHz */
832 /* 7. Frequency for PLL output(0x2564 for 192MHz for 24MHz) */
Fred Richterb63b36f2014-03-24 19:56:00 -0300833 ret = lgdt3306a_read_reg(state, 0x0005, &val);
834 if (lg_chkerr(ret))
835 goto fail;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200836 val &= 0xc0;
Fred Richterb63b36f2014-03-24 19:56:00 -0300837 val |= 0x25;
838 ret = lgdt3306a_write_reg(state, 0x0005, val);
839 if (lg_chkerr(ret))
840 goto fail;
841 ret = lgdt3306a_write_reg(state, 0x0006, 0x64);
842 if (lg_chkerr(ret))
843 goto fail;
844
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300845 /* 8. ADC sampling frequency(0x180000 for 24MHz sampling) */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200846 ret = lgdt3306a_read_reg(state, 0x000d, &val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300847 if (lg_chkerr(ret))
848 goto fail;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200849 val &= 0xc0;
Fred Richterb63b36f2014-03-24 19:56:00 -0300850 val |= 0x18;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200851 ret = lgdt3306a_write_reg(state, 0x000d, val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300852 if (lg_chkerr(ret))
853 goto fail;
854
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300855 } else if (state->cfg->xtalMHz == 25) { /* 25MHz */
856 /* 7. Frequency for PLL output */
Fred Richterb63b36f2014-03-24 19:56:00 -0300857 ret = lgdt3306a_read_reg(state, 0x0005, &val);
858 if (lg_chkerr(ret))
859 goto fail;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200860 val &= 0xc0;
Fred Richterb63b36f2014-03-24 19:56:00 -0300861 val |= 0x25;
862 ret = lgdt3306a_write_reg(state, 0x0005, val);
863 if (lg_chkerr(ret))
864 goto fail;
865 ret = lgdt3306a_write_reg(state, 0x0006, 0x64);
866 if (lg_chkerr(ret))
867 goto fail;
868
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300869 /* 8. ADC sampling frequency(0x190000 for 25MHz sampling) */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200870 ret = lgdt3306a_read_reg(state, 0x000d, &val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300871 if (lg_chkerr(ret))
872 goto fail;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200873 val &= 0xc0;
Fred Richterb63b36f2014-03-24 19:56:00 -0300874 val |= 0x19;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200875 ret = lgdt3306a_write_reg(state, 0x000d, val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300876 if (lg_chkerr(ret))
877 goto fail;
878 } else {
879 lg_err("Bad xtalMHz=%d\n", state->cfg->xtalMHz);
880 }
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300881#if 0
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200882 ret = lgdt3306a_write_reg(state, 0x000e, 0x00);
883 ret = lgdt3306a_write_reg(state, 0x000f, 0x00);
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300884#endif
Fred Richterb63b36f2014-03-24 19:56:00 -0300885
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300886 /* 9. Center frequency of input signal of ADC */
887 ret = lgdt3306a_write_reg(state, 0x0010, 0x34); /* 3.25MHz */
888 ret = lgdt3306a_write_reg(state, 0x0011, 0x00);
Fred Richterb63b36f2014-03-24 19:56:00 -0300889
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300890 /* 10. Fixed gain error value */
891 ret = lgdt3306a_write_reg(state, 0x0014, 0); /* gain error=0 */
Fred Richterb63b36f2014-03-24 19:56:00 -0300892
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300893 /* 10a. VSB TR BW gear shift initial step */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200894 ret = lgdt3306a_read_reg(state, 0x103c, &val);
895 val &= 0x0f;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300896 val |= 0x20; /* SAMGSAUTOSTL_V[3:0] = 2 */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200897 ret = lgdt3306a_write_reg(state, 0x103c, val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300898
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300899 /* 10b. Timing offset calibration in low temperature for VSB */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200900 ret = lgdt3306a_read_reg(state, 0x103d, &val);
901 val &= 0xfc;
Fred Richterb63b36f2014-03-24 19:56:00 -0300902 val |= 0x03;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200903 ret = lgdt3306a_write_reg(state, 0x103d, val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300904
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300905 /* 10c. Timing offset calibration in low temperature for QAM */
Fred Richterb63b36f2014-03-24 19:56:00 -0300906 ret = lgdt3306a_read_reg(state, 0x1036, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200907 val &= 0xf0;
908 val |= 0x0c;
Fred Richterb63b36f2014-03-24 19:56:00 -0300909 ret = lgdt3306a_write_reg(state, 0x1036, val);
910
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300911 /* 11. Using the imaginary part of CIR in CIR loading */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200912 ret = lgdt3306a_read_reg(state, 0x211f, &val);
913 val &= 0xef; /* do not use imaginary of CIR */
914 ret = lgdt3306a_write_reg(state, 0x211f, val);
Fred Richterb63b36f2014-03-24 19:56:00 -0300915
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300916 /* 12. Control of no signal detector function */
Fred Richterb63b36f2014-03-24 19:56:00 -0300917 ret = lgdt3306a_read_reg(state, 0x2849, &val);
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -0200918 val &= 0xef; /* NOUSENOSIGDET=0, enable no signal detector */
Fred Richterb63b36f2014-03-24 19:56:00 -0300919 ret = lgdt3306a_write_reg(state, 0x2849, val);
920
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300921 /* FGR - put demod in some known mode */
Fred Richterb63b36f2014-03-24 19:56:00 -0300922 ret = lgdt3306a_set_vsb(state);
923
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300924 /* 13. TP stream format */
Fred Richterb63b36f2014-03-24 19:56:00 -0300925 ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode);
926
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300927 /* 14. disable output buses */
Fred Richterb63b36f2014-03-24 19:56:00 -0300928 ret = lgdt3306a_mpeg_tristate(state, 1);
929
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300930 /* 15. Sleep (in reset) */
Fred Richterb63b36f2014-03-24 19:56:00 -0300931 ret = lgdt3306a_sleep(state);
932 lg_chkerr(ret);
933
934fail:
935 return ret;
936}
937
938static int lgdt3306a_set_parameters(struct dvb_frontend *fe)
939{
940 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
941 struct lgdt3306a_state *state = fe->demodulator_priv;
942 int ret;
943
944 lg_dbg("(%d, %d)\n", p->frequency, p->modulation);
945
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300946 if (state->current_frequency == p->frequency &&
947 state->current_modulation == p->modulation) {
Fred Richterb63b36f2014-03-24 19:56:00 -0300948 lg_dbg(" (already set, skipping ...)\n");
949 return 0;
950 }
951 state->current_frequency = -1;
952 state->current_modulation = -1;
953
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300954 ret = lgdt3306a_power(state, 1); /* power up */
Fred Richterb63b36f2014-03-24 19:56:00 -0300955 if (lg_chkerr(ret))
956 goto fail;
957
958 if (fe->ops.tuner_ops.set_params) {
959 ret = fe->ops.tuner_ops.set_params(fe);
960 if (fe->ops.i2c_gate_ctrl)
961 fe->ops.i2c_gate_ctrl(fe, 0);
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300962#if 0
963 if (lg_chkerr(ret))
964 goto fail;
965 state->current_frequency = p->frequency;
966#endif
Fred Richterb63b36f2014-03-24 19:56:00 -0300967 }
968
969 ret = lgdt3306a_set_modulation(state, p);
970 if (lg_chkerr(ret))
971 goto fail;
972
973 ret = lgdt3306a_agc_setup(state, p);
974 if (lg_chkerr(ret))
975 goto fail;
976
977 ret = lgdt3306a_set_if(state, p);
978 if (lg_chkerr(ret))
979 goto fail;
980
981 ret = lgdt3306a_spectral_inversion(state, p,
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300982 state->cfg->spectral_inversion ? 1 : 0);
Fred Richterb63b36f2014-03-24 19:56:00 -0300983 if (lg_chkerr(ret))
984 goto fail;
985
986 ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode);
987 if (lg_chkerr(ret))
988 goto fail;
989
990 ret = lgdt3306a_mpeg_mode_polarity(state,
991 state->cfg->tpclk_edge,
992 state->cfg->tpvalid_polarity);
993 if (lg_chkerr(ret))
994 goto fail;
995
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -0300996 ret = lgdt3306a_mpeg_tristate(state, 0); /* enable data bus */
Fred Richterb63b36f2014-03-24 19:56:00 -0300997 if (lg_chkerr(ret))
998 goto fail;
999
1000 ret = lgdt3306a_soft_reset(state);
1001 if (lg_chkerr(ret))
1002 goto fail;
1003
1004#ifdef DBG_DUMP
1005 lgdt3306a_DumpAllRegs(state);
1006#endif
1007 state->current_frequency = p->frequency;
1008fail:
1009 return ret;
1010}
1011
1012static int lgdt3306a_get_frontend(struct dvb_frontend *fe)
1013{
1014 struct lgdt3306a_state *state = fe->demodulator_priv;
1015 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1016
1017 lg_dbg("(%u, %d)\n", state->current_frequency, state->current_modulation);
1018
1019 p->modulation = state->current_modulation;
1020 p->frequency = state->current_frequency;
1021 return 0;
1022}
1023
1024static enum dvbfe_algo lgdt3306a_get_frontend_algo(struct dvb_frontend *fe)
1025{
1026#if 1
1027 return DVBFE_ALGO_CUSTOM;
1028#else
1029 return DVBFE_ALGO_HW;
1030#endif
1031}
1032
1033/* ------------------------------------------------------------------------ */
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001034static int lgdt3306a_monitor_vsb(struct lgdt3306a_state *state)
Fred Richterb63b36f2014-03-24 19:56:00 -03001035{
1036 u8 val;
1037 int ret;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001038 u8 snrRef, maxPowerMan, nCombDet;
1039 u16 fbDlyCir;
Fred Richterb63b36f2014-03-24 19:56:00 -03001040
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001041 ret = lgdt3306a_read_reg(state, 0x21a1, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001042 if (ret)
1043 return ret;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001044 snrRef = val & 0x3f;
Fred Richterb63b36f2014-03-24 19:56:00 -03001045
1046 ret = lgdt3306a_read_reg(state, 0x2185, &maxPowerMan);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001047 if (ret)
1048 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001049
1050 ret = lgdt3306a_read_reg(state, 0x2191, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001051 if (ret)
1052 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001053 nCombDet = (val & 0x80) >> 7;
1054
1055 ret = lgdt3306a_read_reg(state, 0x2180, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001056 if (ret)
1057 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001058 fbDlyCir = (val & 0x03) << 8;
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001059
Fred Richterb63b36f2014-03-24 19:56:00 -03001060 ret = lgdt3306a_read_reg(state, 0x2181, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001061 if (ret)
1062 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001063 fbDlyCir |= val;
1064
1065 lg_dbg("snrRef=%d maxPowerMan=0x%x nCombDet=%d fbDlyCir=0x%x\n",
1066 snrRef, maxPowerMan, nCombDet, fbDlyCir);
1067
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001068 /* Carrier offset sub loop bandwidth */
Fred Richterb63b36f2014-03-24 19:56:00 -03001069 ret = lgdt3306a_read_reg(state, 0x1061, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001070 if (ret)
1071 return ret;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001072 val &= 0xf8;
Fred Richterb63b36f2014-03-24 19:56:00 -03001073 if ((snrRef > 18) && (maxPowerMan > 0x68) && (nCombDet == 0x01) && ((fbDlyCir == 0x03FF) || (fbDlyCir < 0x6C))) {
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001074 /* SNR is over 18dB and no ghosting */
1075 val |= 0x00; /* final bandwidth = 0 */
Fred Richterb63b36f2014-03-24 19:56:00 -03001076 } else {
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001077 val |= 0x04; /* final bandwidth = 4 */
Fred Richterb63b36f2014-03-24 19:56:00 -03001078 }
1079 ret = lgdt3306a_write_reg(state, 0x1061, val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001080 if (ret)
1081 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001082
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001083 /* Adjust Notch Filter */
Fred Richterb63b36f2014-03-24 19:56:00 -03001084 ret = lgdt3306a_read_reg(state, 0x0024, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001085 if (ret)
1086 return ret;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001087 val &= 0x0f;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001088 if (nCombDet == 0) { /* Turn on the Notch Filter */
Fred Richterb63b36f2014-03-24 19:56:00 -03001089 val |= 0x50;
1090 }
1091 ret = lgdt3306a_write_reg(state, 0x0024, val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001092 if (ret)
1093 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001094
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001095 /* VSB Timing Recovery output normalization */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001096 ret = lgdt3306a_read_reg(state, 0x103d, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001097 if (ret)
1098 return ret;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001099 val &= 0xcf;
Fred Richterb63b36f2014-03-24 19:56:00 -03001100 val |= 0x20;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001101 ret = lgdt3306a_write_reg(state, 0x103d, val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001102
1103 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001104}
1105
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001106static enum lgdt3306a_modulation lgdt3306a_check_oper_mode(struct lgdt3306a_state *state)
Fred Richterb63b36f2014-03-24 19:56:00 -03001107{
1108 u8 val = 0;
1109 int ret;
1110
1111 ret = lgdt3306a_read_reg(state, 0x0081, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001112 if (ret)
1113 goto err;
Fred Richterb63b36f2014-03-24 19:56:00 -03001114
1115 if (val & 0x80) {
1116 lg_dbg("VSB\n");
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001117 return LG3306_VSB;
Fred Richterb63b36f2014-03-24 19:56:00 -03001118 }
Michael Ira Krufkyc714efe2014-08-03 14:51:49 -03001119 if (val & 0x08) {
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001120 ret = lgdt3306a_read_reg(state, 0x00a6, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001121 if (ret)
1122 goto err;
Fred Richterb63b36f2014-03-24 19:56:00 -03001123 val = val >> 2;
1124 if (val & 0x01) {
1125 lg_dbg("QAM256\n");
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001126 return LG3306_QAM256;
Fred Richterb63b36f2014-03-24 19:56:00 -03001127 } else {
1128 lg_dbg("QAM64\n");
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001129 return LG3306_QAM64;
Fred Richterb63b36f2014-03-24 19:56:00 -03001130 }
1131 }
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001132err:
Fred Richterb63b36f2014-03-24 19:56:00 -03001133 lg_warn("UNKNOWN\n");
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001134 return LG3306_UNKNOWN_MODE;
Fred Richterb63b36f2014-03-24 19:56:00 -03001135}
1136
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001137static enum lgdt3306a_lock_status lgdt3306a_check_lock_status(struct lgdt3306a_state *state,
1138 enum lgdt3306a_lock_check whatLock)
Fred Richterb63b36f2014-03-24 19:56:00 -03001139{
1140 u8 val = 0;
1141 int ret;
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001142 enum lgdt3306a_modulation modeOper;
1143 enum lgdt3306a_lock_status lockStatus;
Fred Richterb63b36f2014-03-24 19:56:00 -03001144
1145 modeOper = LG3306_UNKNOWN_MODE;
1146
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001147 switch (whatLock) {
1148 case LG3306_SYNC_LOCK:
Fred Richterb63b36f2014-03-24 19:56:00 -03001149 {
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001150 ret = lgdt3306a_read_reg(state, 0x00a6, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001151 if (ret)
1152 return ret;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001153
1154 if ((val & 0x80) == 0x80)
1155 lockStatus = LG3306_LOCK;
1156 else
1157 lockStatus = LG3306_UNLOCK;
1158
1159 lg_dbg("SYNC_LOCK=%x\n", lockStatus);
1160 break;
1161 }
1162 case LG3306_AGC_LOCK:
1163 {
1164 ret = lgdt3306a_read_reg(state, 0x0080, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001165 if (ret)
1166 return ret;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001167
1168 if ((val & 0x40) == 0x40)
1169 lockStatus = LG3306_LOCK;
1170 else
1171 lockStatus = LG3306_UNLOCK;
1172
1173 lg_dbg("AGC_LOCK=%x\n", lockStatus);
1174 break;
1175 }
1176 case LG3306_TR_LOCK:
1177 {
1178 modeOper = lgdt3306a_check_oper_mode(state);
1179 if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) {
1180 ret = lgdt3306a_read_reg(state, 0x1094, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001181 if (ret)
1182 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001183
1184 if ((val & 0x80) == 0x80)
1185 lockStatus = LG3306_LOCK;
1186 else
1187 lockStatus = LG3306_UNLOCK;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001188 } else
1189 lockStatus = LG3306_UNKNOWN_LOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001190
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001191 lg_dbg("TR_LOCK=%x\n", lockStatus);
1192 break;
1193 }
1194 case LG3306_FEC_LOCK:
1195 {
1196 modeOper = lgdt3306a_check_oper_mode(state);
1197 if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) {
Fred Richterb63b36f2014-03-24 19:56:00 -03001198 ret = lgdt3306a_read_reg(state, 0x0080, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001199 if (ret)
1200 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001201
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001202 if ((val & 0x10) == 0x10)
Fred Richterb63b36f2014-03-24 19:56:00 -03001203 lockStatus = LG3306_LOCK;
1204 else
1205 lockStatus = LG3306_UNLOCK;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001206 } else
Fred Richterb63b36f2014-03-24 19:56:00 -03001207 lockStatus = LG3306_UNKNOWN_LOCK;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001208
1209 lg_dbg("FEC_LOCK=%x\n", lockStatus);
1210 break;
Fred Richterb63b36f2014-03-24 19:56:00 -03001211 }
1212
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001213 default:
1214 lockStatus = LG3306_UNKNOWN_LOCK;
1215 lg_warn("UNKNOWN whatLock=%d\n", whatLock);
1216 break;
1217 }
1218
1219 return lockStatus;
Fred Richterb63b36f2014-03-24 19:56:00 -03001220}
1221
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001222static enum lgdt3306a_neverlock_status lgdt3306a_check_neverlock_status(struct lgdt3306a_state *state)
Fred Richterb63b36f2014-03-24 19:56:00 -03001223{
1224 u8 val = 0;
1225 int ret;
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001226 enum lgdt3306a_neverlock_status lockStatus;
Fred Richterb63b36f2014-03-24 19:56:00 -03001227
1228 ret = lgdt3306a_read_reg(state, 0x0080, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001229 if (ret)
1230 return ret;
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001231 lockStatus = (enum lgdt3306a_neverlock_status)(val & 0x03);
Fred Richterb63b36f2014-03-24 19:56:00 -03001232
1233 lg_dbg("NeverLock=%d", lockStatus);
1234
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001235 return lockStatus;
Fred Richterb63b36f2014-03-24 19:56:00 -03001236}
1237
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001238static int lgdt3306a_pre_monitoring(struct lgdt3306a_state *state)
Fred Richterb63b36f2014-03-24 19:56:00 -03001239{
1240 u8 val = 0;
1241 int ret;
1242 u8 currChDiffACQ, snrRef, mainStrong, aiccrejStatus;
1243
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001244 /* Channel variation */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001245 ret = lgdt3306a_read_reg(state, 0x21bc, &currChDiffACQ);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001246 if (ret)
1247 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001248
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001249 /* SNR of Frame sync */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001250 ret = lgdt3306a_read_reg(state, 0x21a1, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001251 if (ret)
1252 return ret;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001253 snrRef = val & 0x3f;
Fred Richterb63b36f2014-03-24 19:56:00 -03001254
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001255 /* Strong Main CIR */
Fred Richterb63b36f2014-03-24 19:56:00 -03001256 ret = lgdt3306a_read_reg(state, 0x2199, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001257 if (ret)
1258 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001259 mainStrong = (val & 0x40) >> 6;
1260
1261 ret = lgdt3306a_read_reg(state, 0x0090, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001262 if (ret)
1263 return ret;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001264 aiccrejStatus = (val & 0xf0) >> 4;
Fred Richterb63b36f2014-03-24 19:56:00 -03001265
1266 lg_dbg("snrRef=%d mainStrong=%d aiccrejStatus=%d currChDiffACQ=0x%x\n",
1267 snrRef, mainStrong, aiccrejStatus, currChDiffACQ);
1268
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001269#if 0
1270 if ((mainStrong == 0) && (currChDiffACQ > 0x70)) /* Dynamic ghost exists */
1271#endif
1272 if (mainStrong == 0) {
Fred Richterb63b36f2014-03-24 19:56:00 -03001273 ret = lgdt3306a_read_reg(state, 0x2135, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001274 if (ret)
1275 return ret;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001276 val &= 0x0f;
1277 val |= 0xa0;
Fred Richterb63b36f2014-03-24 19:56:00 -03001278 ret = lgdt3306a_write_reg(state, 0x2135, val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001279 if (ret)
1280 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001281
1282 ret = lgdt3306a_read_reg(state, 0x2141, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001283 if (ret)
1284 return ret;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001285 val &= 0x3f;
Fred Richterb63b36f2014-03-24 19:56:00 -03001286 val |= 0x80;
1287 ret = lgdt3306a_write_reg(state, 0x2141, val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001288 if (ret)
1289 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001290
1291 ret = lgdt3306a_write_reg(state, 0x2122, 0x70);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001292 if (ret)
1293 return ret;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001294 } else { /* Weak ghost or static channel */
Fred Richterb63b36f2014-03-24 19:56:00 -03001295 ret = lgdt3306a_read_reg(state, 0x2135, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001296 if (ret)
1297 return ret;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001298 val &= 0x0f;
Fred Richterb63b36f2014-03-24 19:56:00 -03001299 val |= 0x70;
1300 ret = lgdt3306a_write_reg(state, 0x2135, val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001301 if (ret)
1302 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001303
1304 ret = lgdt3306a_read_reg(state, 0x2141, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001305 if (ret)
1306 return ret;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001307 val &= 0x3f;
Fred Richterb63b36f2014-03-24 19:56:00 -03001308 val |= 0x40;
1309 ret = lgdt3306a_write_reg(state, 0x2141, val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001310 if (ret)
1311 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001312
1313 ret = lgdt3306a_write_reg(state, 0x2122, 0x40);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001314 if (ret)
1315 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001316 }
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001317 return 0;
Fred Richterb63b36f2014-03-24 19:56:00 -03001318}
1319
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001320static enum lgdt3306a_lock_status lgdt3306a_sync_lock_poll(struct lgdt3306a_state *state)
Fred Richterb63b36f2014-03-24 19:56:00 -03001321{
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001322 enum lgdt3306a_lock_status syncLockStatus = LG3306_UNLOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001323 int i;
1324
1325 for (i = 0; i < 2; i++) {
1326 msleep(30);
1327
1328 syncLockStatus = lgdt3306a_check_lock_status(state, LG3306_SYNC_LOCK);
1329
1330 if (syncLockStatus == LG3306_LOCK) {
1331 lg_dbg("locked(%d)\n", i);
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001332 return LG3306_LOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001333 }
1334 }
1335 lg_dbg("not locked\n");
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001336 return LG3306_UNLOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001337}
1338
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001339static enum lgdt3306a_lock_status lgdt3306a_fec_lock_poll(struct lgdt3306a_state *state)
Fred Richterb63b36f2014-03-24 19:56:00 -03001340{
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001341 enum lgdt3306a_lock_status FECLockStatus = LG3306_UNLOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001342 int i;
1343
1344 for (i = 0; i < 2; i++) {
1345 msleep(30);
1346
1347 FECLockStatus = lgdt3306a_check_lock_status(state, LG3306_FEC_LOCK);
1348
1349 if (FECLockStatus == LG3306_LOCK) {
1350 lg_dbg("locked(%d)\n", i);
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001351 return FECLockStatus;
Fred Richterb63b36f2014-03-24 19:56:00 -03001352 }
1353 }
1354 lg_dbg("not locked\n");
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001355 return FECLockStatus;
Fred Richterb63b36f2014-03-24 19:56:00 -03001356}
1357
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001358static enum lgdt3306a_neverlock_status lgdt3306a_neverlock_poll(struct lgdt3306a_state *state)
Fred Richterb63b36f2014-03-24 19:56:00 -03001359{
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001360 enum lgdt3306a_neverlock_status NLLockStatus = LG3306_NL_FAIL;
Fred Richterb63b36f2014-03-24 19:56:00 -03001361 int i;
1362
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001363 for (i = 0; i < 5; i++) {
Fred Richterb63b36f2014-03-24 19:56:00 -03001364 msleep(30);
1365
1366 NLLockStatus = lgdt3306a_check_neverlock_status(state);
1367
1368 if (NLLockStatus == LG3306_NL_LOCK) {
1369 lg_dbg("NL_LOCK(%d)\n", i);
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001370 return NLLockStatus;
Fred Richterb63b36f2014-03-24 19:56:00 -03001371 }
1372 }
1373 lg_dbg("NLLockStatus=%d\n", NLLockStatus);
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001374 return NLLockStatus;
Fred Richterb63b36f2014-03-24 19:56:00 -03001375}
1376
1377static u8 lgdt3306a_get_packet_error(struct lgdt3306a_state *state)
1378{
1379 u8 val;
1380 int ret;
1381
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001382 ret = lgdt3306a_read_reg(state, 0x00fa, &val);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001383 if (ret)
1384 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001385
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001386 return val;
Fred Richterb63b36f2014-03-24 19:56:00 -03001387}
1388
1389static u32 log10_x1000(u32 x)
1390{
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001391 static u32 valx_x10[] = { 10, 11, 13, 15, 17, 20, 25, 33, 41, 50, 59, 73, 87, 100 };
1392 static u32 log10x_x1000[] = { 0, 41, 114, 176, 230, 301, 398, 518, 613, 699, 771, 863, 939, 1000 };
1393 static u32 nelems = sizeof(valx_x10)/sizeof(valx_x10[0]);
Mauro Carvalho Chehaba132fef2014-10-28 11:07:03 -02001394 u32 diff_val, step_val, step_log10;
Fred Richterb63b36f2014-03-24 19:56:00 -03001395 u32 log_val = 0;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001396 u32 i;
Fred Richterb63b36f2014-03-24 19:56:00 -03001397
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001398 if (x <= 0)
1399 return -1000000; /* signal error */
Fred Richterb63b36f2014-03-24 19:56:00 -03001400
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001401 if (x < 10) {
1402 while (x < 10) {
1403 x = x * 10;
Fred Richterb63b36f2014-03-24 19:56:00 -03001404 log_val--;
1405 }
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001406 } else if (x == 10) {
1407 return 0; /* log(1)=0 */
Fred Richterb63b36f2014-03-24 19:56:00 -03001408 } else {
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001409 while (x >= 100) {
1410 x = x / 10;
Fred Richterb63b36f2014-03-24 19:56:00 -03001411 log_val++;
1412 }
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001413 }
Fred Richterb63b36f2014-03-24 19:56:00 -03001414 log_val *= 1000;
1415
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001416 if (x == 10) /* was our input an exact multiple of 10 */
1417 return log_val; /* don't need to interpolate */
Fred Richterb63b36f2014-03-24 19:56:00 -03001418
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001419 /* find our place on the log curve */
1420 for (i = 1; i < nelems; i++) {
1421 if (valx_x10[i] >= x)
1422 break;
Fred Richterb63b36f2014-03-24 19:56:00 -03001423 }
Mauro Carvalho Chehaba132fef2014-10-28 11:07:03 -02001424 if (i == nelems)
1425 return log_val + log10x_x1000[i - 1];
Fred Richterb63b36f2014-03-24 19:56:00 -03001426
Mauro Carvalho Chehaba132fef2014-10-28 11:07:03 -02001427 diff_val = x - valx_x10[i-1];
1428 step_val = valx_x10[i] - valx_x10[i - 1];
1429 step_log10 = log10x_x1000[i] - log10x_x1000[i - 1];
1430
1431 /* do a linear interpolation to get in-between values */
1432 return log_val + log10x_x1000[i - 1] +
1433 ((diff_val*step_log10) / step_val);
Fred Richterb63b36f2014-03-24 19:56:00 -03001434}
1435
1436static u32 lgdt3306a_calculate_snr_x100(struct lgdt3306a_state *state)
1437{
Michael Ira Krufky34a5a2f2014-10-25 11:26:15 -03001438 u32 mse; /* Mean-Square Error */
1439 u32 pwr; /* Constelation power */
Fred Richterb63b36f2014-03-24 19:56:00 -03001440 u32 snr_x100;
1441
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001442 mse = (read_reg(state, 0x00ec) << 8) |
1443 (read_reg(state, 0x00ed));
1444 pwr = (read_reg(state, 0x00e8) << 8) |
1445 (read_reg(state, 0x00e9));
Fred Richterb63b36f2014-03-24 19:56:00 -03001446
1447 if (mse == 0) /* no signal */
1448 return 0;
1449
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001450 snr_x100 = log10_x1000((pwr * 10000) / mse) - 3000;
Fred Richterb63b36f2014-03-24 19:56:00 -03001451 lg_dbg("mse=%u, pwr=%u, snr_x100=%d\n", mse, pwr, snr_x100);
1452
1453 return snr_x100;
1454}
1455
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001456static enum lgdt3306a_lock_status lgdt3306a_vsb_lock_poll(struct lgdt3306a_state *state)
Fred Richterb63b36f2014-03-24 19:56:00 -03001457{
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001458 u8 cnt = 0;
1459 u8 packet_error;
1460 u32 snr;
Fred Richterb63b36f2014-03-24 19:56:00 -03001461
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001462 while (1) {
Fred Richterb63b36f2014-03-24 19:56:00 -03001463 if (lgdt3306a_sync_lock_poll(state) == LG3306_UNLOCK) {
1464 lg_dbg("no sync lock!\n");
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001465 return LG3306_UNLOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001466 } else {
1467 msleep(20);
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001468 ret = lgdt3306a_pre_monitoring(state);
1469 if (ret)
1470 return LG3306_UNLOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001471
1472 packet_error = lgdt3306a_get_packet_error(state);
1473 snr = lgdt3306a_calculate_snr_x100(state);
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001474 lg_dbg("cnt=%d errors=%d snr=%d\n",
1475 cnt, packet_error, snr);
Fred Richterb63b36f2014-03-24 19:56:00 -03001476
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001477 if ((snr < 1500) || (packet_error >= 0xff))
Fred Richterb63b36f2014-03-24 19:56:00 -03001478 cnt++;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001479 else
1480 return LG3306_LOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001481
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001482 if (cnt >= 10) {
Fred Richterb63b36f2014-03-24 19:56:00 -03001483 lg_dbg("not locked!\n");
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001484 return LG3306_UNLOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001485 }
1486 }
1487 }
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001488 return LG3306_UNLOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001489}
1490
Michael Ira Krufkyf883d602014-08-03 15:29:04 -03001491static enum lgdt3306a_lock_status lgdt3306a_qam_lock_poll(struct lgdt3306a_state *state)
Fred Richterb63b36f2014-03-24 19:56:00 -03001492{
1493 u8 cnt = 0;
1494 u8 packet_error;
1495 u32 snr;
1496
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001497 while (1) {
1498 if (lgdt3306a_fec_lock_poll(state) == LG3306_UNLOCK) {
Fred Richterb63b36f2014-03-24 19:56:00 -03001499 lg_dbg("no fec lock!\n");
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001500 return LG3306_UNLOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001501 } else {
1502 msleep(20);
1503
1504 packet_error = lgdt3306a_get_packet_error(state);
1505 snr = lgdt3306a_calculate_snr_x100(state);
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001506 lg_dbg("cnt=%d errors=%d snr=%d\n",
1507 cnt, packet_error, snr);
Fred Richterb63b36f2014-03-24 19:56:00 -03001508
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001509 if ((snr < 1500) || (packet_error >= 0xff))
Fred Richterb63b36f2014-03-24 19:56:00 -03001510 cnt++;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001511 else
1512 return LG3306_LOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001513
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001514 if (cnt >= 10) {
Fred Richterb63b36f2014-03-24 19:56:00 -03001515 lg_dbg("not locked!\n");
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001516 return LG3306_UNLOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001517 }
1518 }
1519 }
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001520 return LG3306_UNLOCK;
Fred Richterb63b36f2014-03-24 19:56:00 -03001521}
1522
1523static int lgdt3306a_read_status(struct dvb_frontend *fe, fe_status_t *status)
1524{
Fred Richterb63b36f2014-03-24 19:56:00 -03001525 struct lgdt3306a_state *state = fe->demodulator_priv;
Fred Richterb63b36f2014-03-24 19:56:00 -03001526 u16 strength = 0;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001527 int ret = 0;
1528
Fred Richterb63b36f2014-03-24 19:56:00 -03001529 if (fe->ops.tuner_ops.get_rf_strength) {
1530 ret = fe->ops.tuner_ops.get_rf_strength(fe, &strength);
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001531 if (ret == 0) {
Fred Richterb63b36f2014-03-24 19:56:00 -03001532 lg_dbg("strength=%d\n", strength);
1533 } else {
1534 lg_dbg("fe->ops.tuner_ops.get_rf_strength() failed\n");
1535 }
1536 }
1537
1538 *status = 0;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001539 if (lgdt3306a_neverlock_poll(state) == LG3306_NL_LOCK) {
Fred Richterb63b36f2014-03-24 19:56:00 -03001540 *status |= FE_HAS_SIGNAL;
1541 *status |= FE_HAS_CARRIER;
1542
1543 switch (state->current_modulation) {
1544 case QAM_256:
1545 case QAM_64:
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001546 if (lgdt3306a_qam_lock_poll(state) == LG3306_LOCK) {
Fred Richterb63b36f2014-03-24 19:56:00 -03001547 *status |= FE_HAS_VITERBI;
1548 *status |= FE_HAS_SYNC;
1549
1550 *status |= FE_HAS_LOCK;
1551 }
1552 break;
1553 case VSB_8:
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001554 if (lgdt3306a_vsb_lock_poll(state) == LG3306_LOCK) {
Fred Richterb63b36f2014-03-24 19:56:00 -03001555 *status |= FE_HAS_VITERBI;
1556 *status |= FE_HAS_SYNC;
1557
1558 *status |= FE_HAS_LOCK;
1559
Mauro Carvalho Chehabee0133e2014-10-28 11:21:48 -02001560 ret = lgdt3306a_monitor_vsb(state);
Fred Richterb63b36f2014-03-24 19:56:00 -03001561 }
1562 break;
1563 default:
1564 ret = -EINVAL;
1565 }
1566 }
1567 return ret;
1568}
1569
1570
1571static int lgdt3306a_read_snr(struct dvb_frontend *fe, u16 *snr)
1572{
1573 struct lgdt3306a_state *state = fe->demodulator_priv;
1574
1575 state->snr = lgdt3306a_calculate_snr_x100(state);
1576 /* report SNR in dB * 10 */
1577 *snr = state->snr/10;
1578
1579 return 0;
1580}
1581
1582static int lgdt3306a_read_signal_strength(struct dvb_frontend *fe,
1583 u16 *strength)
1584{
1585 /*
1586 * Calculate some sort of "strength" from SNR
1587 */
1588 struct lgdt3306a_state *state = fe->demodulator_priv;
Michael Ira Krufky34a5a2f2014-10-25 11:26:15 -03001589 u16 snr; /* snr_x10 */
Fred Richterb63b36f2014-03-24 19:56:00 -03001590 int ret;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001591 u32 ref_snr; /* snr*100 */
Fred Richterb63b36f2014-03-24 19:56:00 -03001592 u32 str;
1593
1594 *strength = 0;
1595
1596 switch (state->current_modulation) {
1597 case VSB_8:
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001598 ref_snr = 1600; /* 16dB */
Fred Richterb63b36f2014-03-24 19:56:00 -03001599 break;
1600 case QAM_64:
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001601 ref_snr = 2200; /* 22dB */
Fred Richterb63b36f2014-03-24 19:56:00 -03001602 break;
1603 case QAM_256:
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001604 ref_snr = 2800; /* 28dB */
Fred Richterb63b36f2014-03-24 19:56:00 -03001605 break;
1606 default:
1607 return -EINVAL;
1608 }
1609
1610 ret = fe->ops.read_snr(fe, &snr);
1611 if (lg_chkerr(ret))
1612 goto fail;
1613
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001614 if (state->snr <= (ref_snr - 100))
Fred Richterb63b36f2014-03-24 19:56:00 -03001615 str = 0;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001616 else if (state->snr <= ref_snr)
1617 str = (0xffff * 65) / 100; /* 65% */
Fred Richterb63b36f2014-03-24 19:56:00 -03001618 else {
1619 str = state->snr - ref_snr;
1620 str /= 50;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001621 str += 78; /* 78%-100% */
1622 if (str > 100)
Fred Richterb63b36f2014-03-24 19:56:00 -03001623 str = 100;
1624 str = (0xffff * str) / 100;
1625 }
1626 *strength = (u16)str;
1627 lg_dbg("strength=%u\n", *strength);
1628
1629fail:
1630 return ret;
1631}
1632
1633/* ------------------------------------------------------------------------ */
1634
1635static int lgdt3306a_read_ber(struct dvb_frontend *fe, u32 *ber)
1636{
1637 struct lgdt3306a_state *state = fe->demodulator_priv;
1638 u32 tmp;
1639
1640 *ber = 0;
1641#if 1
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001642 /* FGR - BUGBUG - I don't know what value is expected by dvb_core
1643 * what is the scale of the value?? */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001644 tmp = read_reg(state, 0x00fc); /* NBERVALUE[24-31] */
1645 tmp = (tmp << 8) | read_reg(state, 0x00fd); /* NBERVALUE[16-23] */
1646 tmp = (tmp << 8) | read_reg(state, 0x00fe); /* NBERVALUE[8-15] */
1647 tmp = (tmp << 8) | read_reg(state, 0x00ff); /* NBERVALUE[0-7] */
Fred Richterb63b36f2014-03-24 19:56:00 -03001648 *ber = tmp;
1649 lg_dbg("ber=%u\n", tmp);
1650#endif
1651 return 0;
1652}
1653
1654static int lgdt3306a_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
1655{
1656 struct lgdt3306a_state *state = fe->demodulator_priv;
1657
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001658 *ucblocks = 0;
Fred Richterb63b36f2014-03-24 19:56:00 -03001659#if 1
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001660 /* FGR - BUGBUG - I don't know what value is expected by dvb_core
1661 * what happens when value wraps? */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001662 *ucblocks = read_reg(state, 0x00f4); /* TPIFTPERRCNT[0-7] */
Fred Richterb63b36f2014-03-24 19:56:00 -03001663 lg_dbg("ucblocks=%u\n", *ucblocks);
1664#endif
1665
1666 return 0;
1667}
1668
1669static int lgdt3306a_tune(struct dvb_frontend *fe, bool re_tune, unsigned int mode_flags, unsigned int *delay, fe_status_t *status)
1670{
1671 int ret = 0;
1672 struct lgdt3306a_state *state = fe->demodulator_priv;
1673
1674 lg_dbg("re_tune=%u\n", re_tune);
1675
1676 if (re_tune) {
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001677 state->current_frequency = -1; /* force re-tune */
Michael Ira Krufkyae21e442014-08-03 15:18:23 -03001678 ret = lgdt3306a_set_parameters(fe);
1679 if (ret != 0)
Fred Richterb63b36f2014-03-24 19:56:00 -03001680 return ret;
Fred Richterb63b36f2014-03-24 19:56:00 -03001681 }
1682 *delay = 125;
1683 ret = lgdt3306a_read_status(fe, status);
1684
1685 return ret;
1686}
1687
1688static int lgdt3306a_get_tune_settings(struct dvb_frontend *fe,
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001689 struct dvb_frontend_tune_settings
1690 *fe_tune_settings)
Fred Richterb63b36f2014-03-24 19:56:00 -03001691{
1692 fe_tune_settings->min_delay_ms = 100;
1693 lg_dbg("\n");
1694 return 0;
1695}
1696
1697static int lgdt3306a_search(struct dvb_frontend *fe)
1698{
1699 fe_status_t status = 0;
1700 int i, ret;
1701
1702 /* set frontend */
1703 ret = lgdt3306a_set_parameters(fe);
1704 if (ret)
1705 goto error;
1706
1707 /* wait frontend lock */
1708 for (i = 20; i > 0; i--) {
1709 lg_dbg(": loop=%d\n", i);
1710 msleep(50);
1711 ret = lgdt3306a_read_status(fe, &status);
1712 if (ret)
1713 goto error;
1714
1715 if (status & FE_HAS_LOCK)
1716 break;
1717 }
1718
1719 /* check if we have a valid signal */
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001720 if (status & FE_HAS_LOCK)
Fred Richterb63b36f2014-03-24 19:56:00 -03001721 return DVBFE_ALGO_SEARCH_SUCCESS;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001722 else
Fred Richterb63b36f2014-03-24 19:56:00 -03001723 return DVBFE_ALGO_SEARCH_AGAIN;
Fred Richterb63b36f2014-03-24 19:56:00 -03001724
1725error:
1726 lg_dbg("failed (%d)\n", ret);
1727 return DVBFE_ALGO_SEARCH_ERROR;
1728}
1729
1730static void lgdt3306a_release(struct dvb_frontend *fe)
1731{
1732 struct lgdt3306a_state *state = fe->demodulator_priv;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001733
Fred Richterb63b36f2014-03-24 19:56:00 -03001734 lg_dbg("\n");
1735 kfree(state);
1736}
1737
1738static struct dvb_frontend_ops lgdt3306a_ops;
1739
1740struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config,
Mauro Carvalho Chehabc43e6512014-10-28 10:56:10 -02001741 struct i2c_adapter *i2c_adap)
Fred Richterb63b36f2014-03-24 19:56:00 -03001742{
1743 struct lgdt3306a_state *state = NULL;
1744 int ret;
1745 u8 val;
1746
1747 lg_dbg("(%d-%04x)\n",
1748 i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
1749 config ? config->i2c_addr : 0);
1750
1751 state = kzalloc(sizeof(struct lgdt3306a_state), GFP_KERNEL);
1752 if (state == NULL)
1753 goto fail;
1754
1755 state->cfg = config;
1756 state->i2c_adap = i2c_adap;
1757
1758 memcpy(&state->frontend.ops, &lgdt3306a_ops,
1759 sizeof(struct dvb_frontend_ops));
1760 state->frontend.demodulator_priv = state;
1761
1762 /* verify that we're talking to a lg3306a */
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001763 /* FGR - NOTE - there is no obvious ChipId to check; we check
1764 * some "known" bits after reset, but it's still just a guess */
Fred Richterb63b36f2014-03-24 19:56:00 -03001765 ret = lgdt3306a_read_reg(state, 0x0000, &val);
1766 if (lg_chkerr(ret))
1767 goto fail;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001768 if ((val & 0x74) != 0x74) {
Fred Richterb63b36f2014-03-24 19:56:00 -03001769 lg_warn("expected 0x74, got 0x%x\n", (val & 0x74));
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001770#if 0
1771 goto fail; /* BUGBUG - re-enable when we know this is right */
1772#endif
Fred Richterb63b36f2014-03-24 19:56:00 -03001773 }
1774 ret = lgdt3306a_read_reg(state, 0x0001, &val);
1775 if (lg_chkerr(ret))
1776 goto fail;
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001777 if ((val & 0xf6) != 0xc6) {
1778 lg_warn("expected 0xc6, got 0x%x\n", (val & 0xf6));
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001779#if 0
1780 goto fail; /* BUGBUG - re-enable when we know this is right */
1781#endif
Fred Richterb63b36f2014-03-24 19:56:00 -03001782 }
1783 ret = lgdt3306a_read_reg(state, 0x0002, &val);
1784 if (lg_chkerr(ret))
1785 goto fail;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001786 if ((val & 0x73) != 0x03) {
Fred Richterb63b36f2014-03-24 19:56:00 -03001787 lg_warn("expected 0x03, got 0x%x\n", (val & 0x73));
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03001788#if 0
1789 goto fail; /* BUGBUG - re-enable when we know this is right */
1790#endif
Fred Richterb63b36f2014-03-24 19:56:00 -03001791 }
1792
1793 state->current_frequency = -1;
1794 state->current_modulation = -1;
1795
1796 lgdt3306a_sleep(state);
1797
1798 return &state->frontend;
1799
1800fail:
1801 lg_warn("unable to detect LGDT3306A hardware\n");
1802 kfree(state);
1803 return NULL;
1804}
Michael Ira Krufkyebd91752014-08-03 15:05:59 -03001805EXPORT_SYMBOL(lgdt3306a_attach);
Fred Richterb63b36f2014-03-24 19:56:00 -03001806
1807#ifdef DBG_DUMP
1808
1809static const short regtab[] = {
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03001810 0x0000, /* SOFTRSTB 1'b1 1'b1 1'b1 ADCPDB 1'b1 PLLPDB GBBPDB 11111111 */
1811 0x0001, /* 1'b1 1'b1 1'b0 1'b0 AUTORPTRS */
1812 0x0002, /* NI2CRPTEN 1'b0 1'b0 1'b0 SPECINVAUT */
1813 0x0003, /* AGCRFOUT */
1814 0x0004, /* ADCSEL1V ADCCNT ADCCNF ADCCNS ADCCLKPLL */
1815 0x0005, /* PLLINDIVSE */
1816 0x0006, /* PLLCTRL[7:0] 11100001 */
1817 0x0007, /* SYSINITWAITTIME[7:0] (msec) 00001000 */
1818 0x0008, /* STDOPMODE[7:0] 10000000 */
1819 0x0009, /* 1'b0 1'b0 1'b0 STDOPDETTMODE[2:0] STDOPDETCMODE[1:0] 00011110 */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001820 0x000a, /* DAFTEN 1'b1 x x SCSYSLOCK */
1821 0x000b, /* SCSYSLOCKCHKTIME[7:0] (10msec) 01100100 */
1822 0x000d, /* x SAMPLING4 */
1823 0x000e, /* SAMFREQ[15:8] 00000000 */
1824 0x000f, /* SAMFREQ[7:0] 00000000 */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03001825 0x0010, /* IFFREQ[15:8] 01100000 */
1826 0x0011, /* IFFREQ[7:0] 00000000 */
1827 0x0012, /* AGCEN AGCREFMO */
1828 0x0013, /* AGCRFFIXB AGCIFFIXB AGCLOCKDETRNGSEL[1:0] 1'b1 1'b0 1'b0 1'b0 11101000 */
1829 0x0014, /* AGCFIXVALUE[7:0] 01111111 */
1830 0x0015, /* AGCREF[15:8] 00001010 */
1831 0x0016, /* AGCREF[7:0] 11100100 */
1832 0x0017, /* AGCDELAY[7:0] 00100000 */
1833 0x0018, /* AGCRFBW[3:0] AGCIFBW[3:0] 10001000 */
1834 0x0019, /* AGCUDOUTMODE[1:0] AGCUDCTRLLEN[1:0] AGCUDCTRL */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001835 0x001c, /* 1'b1 PFEN MFEN AICCVSYNC */
1836 0x001d, /* 1'b0 1'b1 1'b0 1'b1 AICCVSYNC */
1837 0x001e, /* AICCALPHA[3:0] 1'b1 1'b0 1'b1 1'b0 01111010 */
1838 0x001f, /* AICCDETTH[19:16] AICCOFFTH[19:16] 00000000 */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03001839 0x0020, /* AICCDETTH[15:8] 01111100 */
1840 0x0021, /* AICCDETTH[7:0] 00000000 */
1841 0x0022, /* AICCOFFTH[15:8] 00000101 */
1842 0x0023, /* AICCOFFTH[7:0] 11100000 */
1843 0x0024, /* AICCOPMODE3[1:0] AICCOPMODE2[1:0] AICCOPMODE1[1:0] AICCOPMODE0[1:0] 00000000 */
1844 0x0025, /* AICCFIXFREQ3[23:16] 00000000 */
1845 0x0026, /* AICCFIXFREQ3[15:8] 00000000 */
1846 0x0027, /* AICCFIXFREQ3[7:0] 00000000 */
1847 0x0028, /* AICCFIXFREQ2[23:16] 00000000 */
1848 0x0029, /* AICCFIXFREQ2[15:8] 00000000 */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001849 0x002a, /* AICCFIXFREQ2[7:0] 00000000 */
1850 0x002b, /* AICCFIXFREQ1[23:16] 00000000 */
1851 0x002c, /* AICCFIXFREQ1[15:8] 00000000 */
1852 0x002d, /* AICCFIXFREQ1[7:0] 00000000 */
1853 0x002e, /* AICCFIXFREQ0[23:16] 00000000 */
1854 0x002f, /* AICCFIXFREQ0[15:8] 00000000 */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03001855 0x0030, /* AICCFIXFREQ0[7:0] 00000000 */
1856 0x0031, /* 1'b0 1'b1 1'b0 1'b0 x DAGC1STER */
1857 0x0032, /* DAGC1STEN DAGC1STER */
1858 0x0033, /* DAGC1STREF[15:8] 00001010 */
1859 0x0034, /* DAGC1STREF[7:0] 11100100 */
1860 0x0035, /* DAGC2NDE */
1861 0x0036, /* DAGC2NDREF[15:8] 00001010 */
1862 0x0037, /* DAGC2NDREF[7:0] 10000000 */
1863 0x0038, /* DAGC2NDLOCKDETRNGSEL[1:0] */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001864 0x003d, /* 1'b1 SAMGEARS */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03001865 0x0040, /* SAMLFGMA */
1866 0x0041, /* SAMLFBWM */
1867 0x0044, /* 1'b1 CRGEARSHE */
1868 0x0045, /* CRLFGMAN */
1869 0x0046, /* CFLFBWMA */
1870 0x0047, /* CRLFGMAN */
1871 0x0048, /* x x x x CRLFGSTEP_VS[3:0] xxxx1001 */
1872 0x0049, /* CRLFBWMA */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001873 0x004a, /* CRLFBWMA */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03001874 0x0050, /* 1'b0 1'b1 1'b1 1'b0 MSECALCDA */
1875 0x0070, /* TPOUTEN TPIFEN TPCLKOUTE */
1876 0x0071, /* TPSENB TPSSOPBITE */
1877 0x0073, /* TP47HINS x x CHBERINT PERMODE[1:0] PERINT[1:0] 1xx11100 */
1878 0x0075, /* x x x x x IQSWAPCTRL[2:0] xxxxx000 */
1879 0x0076, /* NBERCON NBERST NBERPOL NBERWSYN */
1880 0x0077, /* x NBERLOSTTH[2:0] NBERACQTH[3:0] x0000000 */
1881 0x0078, /* NBERPOLY[31:24] 00000000 */
1882 0x0079, /* NBERPOLY[23:16] 00000000 */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001883 0x007a, /* NBERPOLY[15:8] 00000000 */
1884 0x007b, /* NBERPOLY[7:0] 00000000 */
1885 0x007c, /* NBERPED[31:24] 00000000 */
1886 0x007d, /* NBERPED[23:16] 00000000 */
1887 0x007e, /* NBERPED[15:8] 00000000 */
1888 0x007f, /* NBERPED[7:0] 00000000 */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03001889 0x0080, /* x AGCLOCK DAGCLOCK SYSLOCK x x NEVERLOCK[1:0] */
1890 0x0085, /* SPECINVST */
1891 0x0088, /* SYSLOCKTIME[15:8] */
1892 0x0089, /* SYSLOCKTIME[7:0] */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001893 0x008c, /* FECLOCKTIME[15:8] */
1894 0x008d, /* FECLOCKTIME[7:0] */
1895 0x008e, /* AGCACCOUT[15:8] */
1896 0x008f, /* AGCACCOUT[7:0] */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03001897 0x0090, /* AICCREJSTATUS[3:0] AICCREJBUSY[3:0] */
1898 0x0091, /* AICCVSYNC */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001899 0x009c, /* CARRFREQOFFSET[15:8] */
1900 0x009d, /* CARRFREQOFFSET[7:0] */
1901 0x00a1, /* SAMFREQOFFSET[23:16] */
1902 0x00a2, /* SAMFREQOFFSET[15:8] */
1903 0x00a3, /* SAMFREQOFFSET[7:0] */
1904 0x00a6, /* SYNCLOCK SYNCLOCKH */
Michael Ira Krufky6da7ac92014-10-25 11:05:05 -03001905#if 0 /* covered elsewhere */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001906 0x00e8, /* CONSTPWR[15:8] */
1907 0x00e9, /* CONSTPWR[7:0] */
1908 0x00ea, /* BMSE[15:8] */
1909 0x00eb, /* BMSE[7:0] */
1910 0x00ec, /* MSE[15:8] */
1911 0x00ed, /* MSE[7:0] */
1912 0x00ee, /* CONSTI[7:0] */
1913 0x00ef, /* CONSTQ[7:0] */
Fred Richterb63b36f2014-03-24 19:56:00 -03001914#endif
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001915 0x00f4, /* TPIFTPERRCNT[7:0] */
1916 0x00f5, /* TPCORREC */
1917 0x00f6, /* VBBER[15:8] */
1918 0x00f7, /* VBBER[7:0] */
1919 0x00f8, /* VABER[15:8] */
1920 0x00f9, /* VABER[7:0] */
1921 0x00fa, /* TPERRCNT[7:0] */
1922 0x00fb, /* NBERLOCK x x x x x x x */
1923 0x00fc, /* NBERVALUE[31:24] */
1924 0x00fd, /* NBERVALUE[23:16] */
1925 0x00fe, /* NBERVALUE[15:8] */
1926 0x00ff, /* NBERVALUE[7:0] */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03001927 0x1000, /* 1'b0 WODAGCOU */
1928 0x1005, /* x x 1'b1 1'b1 x SRD_Q_QM */
1929 0x1009, /* SRDWAITTIME[7:0] (10msec) 00100011 */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001930 0x100a, /* SRDWAITTIME_CQS[7:0] (msec) 01100100 */
1931 0x101a, /* x 1'b1 1'b0 1'b0 x QMDQAMMODE[2:0] x100x010 */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03001932 0x1036, /* 1'b0 1'b1 1'b0 1'b0 SAMGSEND_CQS[3:0] 01001110 */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001933 0x103c, /* SAMGSAUTOSTL_V[3:0] SAMGSAUTOEDL_V[3:0] 01000110 */
1934 0x103d, /* 1'b1 1'b1 SAMCNORMBP_V[1:0] 1'b0 1'b0 SAMMODESEL_V[1:0] 11100001 */
1935 0x103f, /* SAMZTEDSE */
1936 0x105d, /* EQSTATUSE */
1937 0x105f, /* x PMAPG2_V[2:0] x DMAPG2_V[2:0] x001x011 */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03001938 0x1060, /* 1'b1 EQSTATUSE */
1939 0x1061, /* CRMAPBWSTL_V[3:0] CRMAPBWEDL_V[3:0] 00000100 */
1940 0x1065, /* 1'b0 x CRMODE_V[1:0] 1'b1 x 1'b1 x 0x111x1x */
1941 0x1066, /* 1'b0 1'b0 1'b1 1'b0 1'b1 PNBOOSTSE */
1942 0x1068, /* CREPHNGAIN2_V[3:0] CREPHNPBW_V[3:0] 10010001 */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001943 0x106e, /* x x x x x CREPHNEN_ */
1944 0x106f, /* CREPHNTH_V[7:0] 00010101 */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03001945 0x1072, /* CRSWEEPN */
1946 0x1073, /* CRPGAIN_V[3:0] x x 1'b1 1'b1 1001xx11 */
1947 0x1074, /* CRPBW_V[3:0] x x 1'b1 1'b1 0001xx11 */
1948 0x1080, /* DAFTSTATUS[1:0] x x x x x x */
1949 0x1081, /* SRDSTATUS[1:0] x x x x x SRDLOCK */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001950 0x10a9, /* EQSTATUS_CQS[1:0] x x x x x x */
1951 0x10b7, /* EQSTATUS_V[1:0] x x x x x x */
Michael Ira Krufky6da7ac92014-10-25 11:05:05 -03001952#if 0 /* SMART_ANT */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02001953 0x1f00, /* MODEDETE */
1954 0x1f01, /* x x x x x x x SFNRST xxxxxxx0 */
1955 0x1f03, /* NUMOFANT[7:0] 10000000 */
1956 0x1f04, /* x SELMASK[6:0] x0000000 */
1957 0x1f05, /* x SETMASK[6:0] x0000000 */
1958 0x1f06, /* x TXDATA[6:0] x0000000 */
1959 0x1f07, /* x CHNUMBER[6:0] x0000000 */
1960 0x1f09, /* AGCTIME[23:16] 10011000 */
1961 0x1f0a, /* AGCTIME[15:8] 10010110 */
1962 0x1f0b, /* AGCTIME[7:0] 10000000 */
1963 0x1f0c, /* ANTTIME[31:24] 00000000 */
1964 0x1f0d, /* ANTTIME[23:16] 00000011 */
1965 0x1f0e, /* ANTTIME[15:8] 10010000 */
1966 0x1f0f, /* ANTTIME[7:0] 10010000 */
1967 0x1f11, /* SYNCTIME[23:16] 10011000 */
1968 0x1f12, /* SYNCTIME[15:8] 10010110 */
1969 0x1f13, /* SYNCTIME[7:0] 10000000 */
1970 0x1f14, /* SNRTIME[31:24] 00000001 */
1971 0x1f15, /* SNRTIME[23:16] 01111101 */
1972 0x1f16, /* SNRTIME[15:8] 01111000 */
1973 0x1f17, /* SNRTIME[7:0] 01000000 */
1974 0x1f19, /* FECTIME[23:16] 00000000 */
1975 0x1f1a, /* FECTIME[15:8] 01110010 */
1976 0x1f1b, /* FECTIME[7:0] 01110000 */
1977 0x1f1d, /* FECTHD[7:0] 00000011 */
1978 0x1f1f, /* SNRTHD[23:16] 00001000 */
1979 0x1f20, /* SNRTHD[15:8] 01111111 */
1980 0x1f21, /* SNRTHD[7:0] 10000101 */
1981 0x1f80, /* IRQFLG x x SFSDRFLG MODEBFLG SAVEFLG SCANFLG TRACKFLG */
1982 0x1f81, /* x SYNCCON SNRCON FECCON x STDBUSY SYNCRST AGCFZCO */
1983 0x1f82, /* x x x SCANOPCD[4:0] */
1984 0x1f83, /* x x x x MAINOPCD[3:0] */
1985 0x1f84, /* x x RXDATA[13:8] */
1986 0x1f85, /* RXDATA[7:0] */
1987 0x1f86, /* x x SDTDATA[13:8] */
1988 0x1f87, /* SDTDATA[7:0] */
1989 0x1f89, /* ANTSNR[23:16] */
1990 0x1f8a, /* ANTSNR[15:8] */
1991 0x1f8b, /* ANTSNR[7:0] */
1992 0x1f8c, /* x x x x ANTFEC[13:8] */
1993 0x1f8d, /* ANTFEC[7:0] */
1994 0x1f8e, /* MAXCNT[7:0] */
1995 0x1f8f, /* SCANCNT[7:0] */
1996 0x1f91, /* MAXPW[23:16] */
1997 0x1f92, /* MAXPW[15:8] */
1998 0x1f93, /* MAXPW[7:0] */
1999 0x1f95, /* CURPWMSE[23:16] */
2000 0x1f96, /* CURPWMSE[15:8] */
2001 0x1f97, /* CURPWMSE[7:0] */
Michael Ira Krufky6da7ac92014-10-25 11:05:05 -03002002#endif /* SMART_ANT */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02002003 0x211f, /* 1'b1 1'b1 1'b1 CIRQEN x x 1'b0 1'b0 1111xx00 */
2004 0x212a, /* EQAUTOST */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03002005 0x2122, /* CHFAST[7:0] 01100000 */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02002006 0x212b, /* FFFSTEP_V[3:0] x FBFSTEP_V[2:0] 0001x001 */
2007 0x212c, /* PHDEROTBWSEL[3:0] 1'b1 1'b1 1'b1 1'b0 10001110 */
2008 0x212d, /* 1'b1 1'b1 1'b1 1'b1 x x TPIFLOCKS */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03002009 0x2135, /* DYNTRACKFDEQ[3:0] x 1'b0 1'b0 1'b0 1010x000 */
2010 0x2141, /* TRMODE[1:0] 1'b1 1'b1 1'b0 1'b1 1'b1 1'b1 01110111 */
2011 0x2162, /* AICCCTRLE */
2012 0x2173, /* PHNCNFCNT[7:0] 00000100 */
2013 0x2179, /* 1'b0 1'b0 1'b0 1'b1 x BADSINGLEDYNTRACKFBF[2:0] 0001x001 */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02002014 0x217a, /* 1'b0 1'b0 1'b0 1'b1 x BADSLOWSINGLEDYNTRACKFBF[2:0] 0001x001 */
2015 0x217e, /* CNFCNTTPIF[7:0] 00001000 */
2016 0x217f, /* TPERRCNTTPIF[7:0] 00000001 */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03002017 0x2180, /* x x x x x x FBDLYCIR[9:8] */
2018 0x2181, /* FBDLYCIR[7:0] */
2019 0x2185, /* MAXPWRMAIN[7:0] */
2020 0x2191, /* NCOMBDET x x x x x x x */
2021 0x2199, /* x MAINSTRON */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02002022 0x219a, /* FFFEQSTEPOUT_V[3:0] FBFSTEPOUT_V[2:0] */
2023 0x21a1, /* x x SNRREF[5:0] */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03002024 0x2845, /* 1'b0 1'b1 x x FFFSTEP_CQS[1:0] FFFCENTERTAP[1:0] 01xx1110 */
2025 0x2846, /* 1'b0 x 1'b0 1'b1 FBFSTEP_CQS[1:0] 1'b1 1'b0 0x011110 */
2026 0x2847, /* ENNOSIGDE */
2027 0x2849, /* 1'b1 1'b1 NOUSENOSI */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02002028 0x284a, /* EQINITWAITTIME[7:0] 01100100 */
Michael Ira Krufkycb4671c2014-10-25 11:12:25 -03002029 0x3000, /* 1'b1 1'b1 1'b1 x x x 1'b0 RPTRSTM */
2030 0x3001, /* RPTRSTWAITTIME[7:0] (100msec) 00110010 */
2031 0x3031, /* FRAMELOC */
2032 0x3032, /* 1'b1 1'b0 1'b0 1'b0 x x FRAMELOCKMODE_CQS[1:0] 1000xx11 */
Mauro Carvalho Chehab4937ba92014-10-28 10:50:36 -02002033 0x30a9, /* VDLOCK_Q FRAMELOCK */
2034 0x30aa, /* MPEGLOCK */
Fred Richterb63b36f2014-03-24 19:56:00 -03002035};
2036
Michael Ira Krufky34a5a2f2014-10-25 11:26:15 -03002037#define numDumpRegs (sizeof(regtab)/sizeof(regtab[0]))
Fred Richterb63b36f2014-03-24 19:56:00 -03002038static u8 regval1[numDumpRegs] = {0, };
2039static u8 regval2[numDumpRegs] = {0, };
2040
2041static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state)
2042{
2043 memset(regval2, 0xff, sizeof(regval2));
2044 lgdt3306a_DumpRegs(state);
2045}
2046
2047static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state)
2048{
2049 int i;
2050 int sav_debug = debug;
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03002051
Fred Richterb63b36f2014-03-24 19:56:00 -03002052 if ((debug & DBG_DUMP) == 0)
2053 return;
Michael Ira Krufky831a9112014-10-25 11:20:57 -03002054 debug &= ~DBG_REG; /* suppress DBG_REG during reg dump */
Fred Richterb63b36f2014-03-24 19:56:00 -03002055
2056 lg_info("\n");
2057
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03002058 for (i = 0; i < numDumpRegs; i++) {
Fred Richterb63b36f2014-03-24 19:56:00 -03002059 lgdt3306a_read_reg(state, regtab[i], &regval1[i]);
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03002060 if (regval1[i] != regval2[i]) {
2061 lg_info(" %04X = %02X\n", regtab[i], regval1[i]);
2062 regval2[i] = regval1[i];
Fred Richterb63b36f2014-03-24 19:56:00 -03002063 }
2064 }
2065 debug = sav_debug;
2066}
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03002067#endif /* DBG_DUMP */
Fred Richterb63b36f2014-03-24 19:56:00 -03002068
2069
2070
Fred Richterb63b36f2014-03-24 19:56:00 -03002071static struct dvb_frontend_ops lgdt3306a_ops = {
2072 .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
2073 .info = {
2074 .name = "LG Electronics LGDT3306A VSB/QAM Frontend",
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03002075#if 0
2076 .type = FE_ATSC,
2077#endif
Fred Richterb63b36f2014-03-24 19:56:00 -03002078 .frequency_min = 54000000,
Michael Ira Krufky8e8cd342014-07-27 19:24:24 -03002079 .frequency_max = 858000000,
Fred Richterb63b36f2014-03-24 19:56:00 -03002080 .frequency_stepsize = 62500,
2081 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
2082 },
2083 .i2c_gate_ctrl = lgdt3306a_i2c_gate_ctrl,
2084 .init = lgdt3306a_init,
2085 .sleep = lgdt3306a_fe_sleep,
2086 /* if this is set, it overrides the default swzigzag */
2087 .tune = lgdt3306a_tune,
2088 .set_frontend = lgdt3306a_set_parameters,
2089 .get_frontend = lgdt3306a_get_frontend,
2090 .get_frontend_algo = lgdt3306a_get_frontend_algo,
2091 .get_tune_settings = lgdt3306a_get_tune_settings,
2092 .read_status = lgdt3306a_read_status,
2093 .read_ber = lgdt3306a_read_ber,
2094 .read_signal_strength = lgdt3306a_read_signal_strength,
2095 .read_snr = lgdt3306a_read_snr,
2096 .read_ucblocks = lgdt3306a_read_ucblocks,
2097 .release = lgdt3306a_release,
2098 .ts_bus_ctrl = lgdt3306a_ts_bus_ctrl,
2099 .search = lgdt3306a_search,
2100};
2101
2102MODULE_DESCRIPTION("LG Electronics LGDT3306A ATSC/QAM-B Demodulator Driver");
2103MODULE_AUTHOR("Fred Richter <frichter@hauppauge.com>");
2104MODULE_LICENSE("GPL");
2105MODULE_VERSION("0.2");
2106
2107/*
2108 * Local variables:
2109 * c-basic-offset: 8
2110 * End:
2111 */