xref: /linux/drivers/media/dvb-frontends/lgdt3306a.c (revision 8e8cd34eaaf96c4bfc472ec0b4d6f7d3951c051f)
1b63b36faSFred Richter /*
2b63b36faSFred Richter  *    Support for LGDT3306A - 8VSB/QAM-B
3b63b36faSFred Richter  *
4b63b36faSFred Richter  *    Copyright (C) 2013 Fred Richter <frichter@hauppauge.com>
5b63b36faSFred Richter  *    - driver structure based on lgdt3305.[ch] by Michael Krufky
6b63b36faSFred Richter  *    - code based on LG3306_V0.35 API by LG Electronics Inc.
7b63b36faSFred Richter  *
8b63b36faSFred Richter  *    This program is free software; you can redistribute it and/or modify
9b63b36faSFred Richter  *    it under the terms of the GNU General Public License as published by
10b63b36faSFred Richter  *    the Free Software Foundation; either version 2 of the License, or
11b63b36faSFred Richter  *    (at your option) any later version.
12b63b36faSFred Richter  *
13b63b36faSFred Richter  *    This program is distributed in the hope that it will be useful,
14b63b36faSFred Richter  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
15b63b36faSFred Richter  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16b63b36faSFred Richter  *    GNU General Public License for more details.
17b63b36faSFred Richter  *
18b63b36faSFred Richter  *    You should have received a copy of the GNU General Public License
19b63b36faSFred Richter  *    along with this program; if not, write to the Free Software
20b63b36faSFred Richter  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21b63b36faSFred Richter  *
22b63b36faSFred Richter  */
23b63b36faSFred Richter 
24b63b36faSFred Richter #include <asm/div64.h>
25b63b36faSFred Richter #include <linux/dvb/frontend.h>
26b63b36faSFred Richter #include "dvb_math.h"
27b63b36faSFred Richter #include "lgdt3306a.h"
28b63b36faSFred Richter 
29b63b36faSFred Richter 
30b63b36faSFred Richter static int debug;
31b63b36faSFred Richter module_param(debug, int, 0644);
32b63b36faSFred Richter MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))");
33b63b36faSFred Richter 
34b63b36faSFred Richter #define DBG_INFO 1
35b63b36faSFred Richter #define DBG_REG  2
36*8e8cd34eSMichael Ira Krufky #define DBG_DUMP 4 /* FGR - comment out to remove dump code */
37b63b36faSFred Richter 
38b63b36faSFred Richter #define lg_printk(kern, fmt, arg...)					\
39b63b36faSFred Richter 	printk(kern "%s(): " fmt, __func__, ##arg)
40b63b36faSFred Richter 
41b63b36faSFred Richter #define lg_info(fmt, arg...)	printk(KERN_INFO "lgdt3306a: " fmt, ##arg)
42b63b36faSFred Richter #define lg_warn(fmt, arg...)	lg_printk(KERN_WARNING,       fmt, ##arg)
43b63b36faSFred Richter #define lg_err(fmt, arg...)	lg_printk(KERN_ERR,           fmt, ##arg)
44b63b36faSFred Richter #define lg_dbg(fmt, arg...) if (debug & DBG_INFO)			\
45b63b36faSFred Richter 				lg_printk(KERN_DEBUG,         fmt, ##arg)
46b63b36faSFred Richter #define lg_reg(fmt, arg...) if (debug & DBG_REG)			\
47b63b36faSFred Richter 				lg_printk(KERN_DEBUG,         fmt, ##arg)
48b63b36faSFred Richter 
49b63b36faSFred Richter #define lg_chkerr(ret)							\
50b63b36faSFred Richter ({									\
51b63b36faSFred Richter 	int __ret;							\
52b63b36faSFred Richter 	__ret = (ret < 0);						\
53b63b36faSFred Richter 	if (__ret)							\
54b63b36faSFred Richter 		lg_err("error %d on line %d\n",	ret, __LINE__);		\
55b63b36faSFred Richter 	__ret;								\
56b63b36faSFred Richter })
57b63b36faSFred Richter 
58b63b36faSFred Richter struct lgdt3306a_state {
59b63b36faSFred Richter 	struct i2c_adapter *i2c_adap;
60b63b36faSFred Richter 	const struct lgdt3306a_config *cfg;
61b63b36faSFred Richter 
62b63b36faSFred Richter 	struct dvb_frontend frontend;
63b63b36faSFred Richter 
64b63b36faSFred Richter 	fe_modulation_t current_modulation;
65b63b36faSFred Richter 	u32 current_frequency;
66b63b36faSFred Richter 	u32 snr;
67b63b36faSFred Richter };
68b63b36faSFred Richter 
69b63b36faSFred Richter /* -----------------------------------------------
70b63b36faSFred Richter  LG3306A Register Usage
71b63b36faSFred Richter    (LG does not really name the registers, so this code does not either)
72b63b36faSFred Richter  0000 -> 00FF Common control and status
73b63b36faSFred Richter  1000 -> 10FF Synchronizer control and status
74b63b36faSFred Richter  1F00 -> 1FFF Smart Antenna control and status
75b63b36faSFred Richter  2100 -> 21FF VSB Equalizer control and status
76b63b36faSFred Richter  2800 -> 28FF QAM Equalizer control and status
77b63b36faSFred Richter  3000 -> 30FF FEC control and status
78b63b36faSFred Richter  ---------------------------------------------- */
79b63b36faSFred Richter 
80b63b36faSFred Richter typedef enum{
81b63b36faSFred Richter 	LG3306_UNLOCK	    = 0x00,
82b63b36faSFred Richter 	LG3306_LOCK	        = 0x01,
83b63b36faSFred Richter 	LG3306_UNKNOWN_LOCK	= 0xFF
84b63b36faSFred Richter }LG3306_LOCK_STATUS;
85b63b36faSFred Richter 
86b63b36faSFred Richter typedef enum{
87b63b36faSFred Richter 	LG3306_NL_INIT    = 0x00,
88b63b36faSFred Richter 	LG3306_NL_PROCESS = 0x01,
89b63b36faSFred Richter 	LG3306_NL_LOCK    = 0x02,
90b63b36faSFred Richter 	LG3306_NL_FAIL    = 0x03,
91b63b36faSFred Richter 	LG3306_NL_UNKNOWN = 0xFF
92b63b36faSFred Richter }LG3306_NEVERLOCK_STATUS;
93b63b36faSFred Richter 
94b63b36faSFred Richter typedef enum{
95b63b36faSFred Richter 	LG3306_VSB	        = 0x00,
96b63b36faSFred Richter 	LG3306_QAM64	    = 0x01,
97b63b36faSFred Richter 	LG3306_QAM256	    = 0x02,
98b63b36faSFred Richter 	LG3306_UNKNOWN_MODE	= 0xFF
99b63b36faSFred Richter }LG3306_MODULATION;
100b63b36faSFred Richter 
101b63b36faSFred Richter typedef enum
102b63b36faSFred Richter {
103b63b36faSFred Richter 	LG3306_SYNC_LOCK,
104b63b36faSFred Richter 	LG3306_FEC_LOCK,
105b63b36faSFred Richter 	LG3306_TR_LOCK,
106b63b36faSFred Richter 	LG3306_AGC_LOCK,
107b63b36faSFred Richter } LG3306_LOCK_CHECK;
108b63b36faSFred Richter 
109b63b36faSFred Richter 
110b63b36faSFred Richter #ifdef DBG_DUMP
111b63b36faSFred Richter static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state);
112b63b36faSFred Richter static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state);
113b63b36faSFred Richter #endif
114b63b36faSFred Richter 
115b63b36faSFred Richter 
116b63b36faSFred Richter static int lgdt3306a_write_reg(struct lgdt3306a_state *state, u16 reg, u8 val)
117b63b36faSFred Richter {
118b63b36faSFred Richter 	int ret;
119b63b36faSFred Richter 	u8 buf[] = { reg >> 8, reg & 0xff, val };
120b63b36faSFred Richter 	struct i2c_msg msg = {
121b63b36faSFred Richter 		.addr = state->cfg->i2c_addr, .flags = 0,
122b63b36faSFred Richter 		.buf = buf, .len = 3,
123b63b36faSFred Richter 	};
124b63b36faSFred Richter 
125b63b36faSFred Richter 	lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);
126b63b36faSFred Richter 
127b63b36faSFred Richter 	ret = i2c_transfer(state->i2c_adap, &msg, 1);
128b63b36faSFred Richter 
129b63b36faSFred Richter 	if (ret != 1) {
130b63b36faSFred Richter 		lg_err("error (addr %02x %02x <- %02x, err = %i)\n",
131b63b36faSFred Richter 		       msg.buf[0], msg.buf[1], msg.buf[2], ret);
132b63b36faSFred Richter 		if (ret < 0)
133b63b36faSFred Richter 			return ret;
134b63b36faSFred Richter 		else
135b63b36faSFred Richter 			return -EREMOTEIO;
136b63b36faSFred Richter 	}
137b63b36faSFred Richter 	return 0;
138b63b36faSFred Richter }
139b63b36faSFred Richter 
140b63b36faSFred Richter static int lgdt3306a_read_reg(struct lgdt3306a_state *state, u16 reg, u8 *val)
141b63b36faSFred Richter {
142b63b36faSFred Richter 	int ret;
143b63b36faSFred Richter 	u8 reg_buf[] = { reg >> 8, reg & 0xff };
144b63b36faSFred Richter 	struct i2c_msg msg[] = {
145b63b36faSFred Richter 		{ .addr = state->cfg->i2c_addr,
146b63b36faSFred Richter 		  .flags = 0, .buf = reg_buf, .len = 2 },
147b63b36faSFred Richter 		{ .addr = state->cfg->i2c_addr,
148b63b36faSFred Richter 		  .flags = I2C_M_RD, .buf = val, .len = 1 },
149b63b36faSFred Richter 	};
150b63b36faSFred Richter 
151b63b36faSFred Richter 	ret = i2c_transfer(state->i2c_adap, msg, 2);
152b63b36faSFred Richter 
153b63b36faSFred Richter 	if (ret != 2) {
154b63b36faSFred Richter 		lg_err("error (addr %02x reg %04x error (ret == %i)\n",
155b63b36faSFred Richter 		       state->cfg->i2c_addr, reg, ret);
156b63b36faSFred Richter 		if (ret < 0)
157b63b36faSFred Richter 			return ret;
158b63b36faSFred Richter 		else
159b63b36faSFred Richter 			return -EREMOTEIO;
160b63b36faSFred Richter 	}
161b63b36faSFred Richter 	lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, *val);
162b63b36faSFred Richter 
163b63b36faSFred Richter 	return 0;
164b63b36faSFred Richter }
165b63b36faSFred Richter 
166b63b36faSFred Richter #define read_reg(state, reg)						\
167b63b36faSFred Richter ({									\
168b63b36faSFred Richter 	u8 __val;							\
169b63b36faSFred Richter 	int ret = lgdt3306a_read_reg(state, reg, &__val);		\
170b63b36faSFred Richter 	if (lg_chkerr(ret))						\
171b63b36faSFred Richter 		__val = 0;						\
172b63b36faSFred Richter 	__val;								\
173b63b36faSFred Richter })
174b63b36faSFred Richter 
175b63b36faSFred Richter static int lgdt3306a_set_reg_bit(struct lgdt3306a_state *state,
176b63b36faSFred Richter 				u16 reg, int bit, int onoff)
177b63b36faSFred Richter {
178b63b36faSFred Richter 	u8 val;
179b63b36faSFred Richter 	int ret;
180b63b36faSFred Richter 
181b63b36faSFred Richter 	lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff);
182b63b36faSFred Richter 
183b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, reg, &val);
184b63b36faSFred Richter 	if (lg_chkerr(ret))
185b63b36faSFred Richter 		goto fail;
186b63b36faSFred Richter 
187b63b36faSFred Richter 	val &= ~(1 << bit);
188b63b36faSFred Richter 	val |= (onoff & 1) << bit;
189b63b36faSFred Richter 
190b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, reg, val);
191b63b36faSFred Richter 	lg_chkerr(ret);
192b63b36faSFred Richter fail:
193b63b36faSFred Richter 	return ret;
194b63b36faSFred Richter }
195b63b36faSFred Richter 
196b63b36faSFred Richter /* ------------------------------------------------------------------------ */
197b63b36faSFred Richter 
198b63b36faSFred Richter static int lgdt3306a_soft_reset(struct lgdt3306a_state *state)
199b63b36faSFred Richter {
200b63b36faSFred Richter 	int ret;
201b63b36faSFred Richter 
202b63b36faSFred Richter 	lg_dbg("\n");
203b63b36faSFred Richter 
204b63b36faSFred Richter 	ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0);
205b63b36faSFred Richter 	if (lg_chkerr(ret))
206b63b36faSFred Richter 		goto fail;
207b63b36faSFred Richter 
208b63b36faSFred Richter 	msleep(20);
209b63b36faSFred Richter 	ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1);
210b63b36faSFred Richter 	lg_chkerr(ret);
211b63b36faSFred Richter 
212b63b36faSFred Richter fail:
213b63b36faSFred Richter 	return ret;
214b63b36faSFred Richter }
215b63b36faSFred Richter 
216b63b36faSFred Richter static int lgdt3306a_mpeg_mode(struct lgdt3306a_state *state,
217b63b36faSFred Richter 				     enum lgdt3306a_mpeg_mode mode)
218b63b36faSFred Richter {
219b63b36faSFred Richter 	u8 val;
220b63b36faSFred Richter 	int ret;
221b63b36faSFred Richter 
222b63b36faSFred Richter 	lg_dbg("(%d)\n", mode);
223*8e8cd34eSMichael Ira Krufky 	/* transport packet format */
224*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_set_reg_bit(state, 0x0071, 7, mode == LGDT3306A_MPEG_PARALLEL?1:0); /* TPSENB=0x80 */
225b63b36faSFred Richter 	if (lg_chkerr(ret))
226b63b36faSFred Richter 		goto fail;
227b63b36faSFred Richter 
228*8e8cd34eSMichael Ira Krufky 	/* start of packet signal duration */
229*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_set_reg_bit(state, 0x0071, 6, 0); /* TPSSOPBITEN=0x40; 0=byte duration, 1=bit duration */
230b63b36faSFred Richter 	if (lg_chkerr(ret))
231b63b36faSFred Richter 		goto fail;
232b63b36faSFred Richter 
233b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0070, &val);
234b63b36faSFred Richter 	if (lg_chkerr(ret))
235b63b36faSFred Richter 		goto fail;
236b63b36faSFred Richter 
237*8e8cd34eSMichael Ira Krufky 	val |= 0x10; /* TPCLKSUPB=0x10 */
238b63b36faSFred Richter 
239b63b36faSFred Richter 	if (mode == LGDT3306A_MPEG_PARALLEL)
240b63b36faSFred Richter 		val &= ~0x10;
241b63b36faSFred Richter 
242b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0070, val);
243b63b36faSFred Richter 	lg_chkerr(ret);
244b63b36faSFred Richter 
245b63b36faSFred Richter fail:
246b63b36faSFred Richter 	return ret;
247b63b36faSFred Richter }
248b63b36faSFred Richter 
249b63b36faSFred Richter static int lgdt3306a_mpeg_mode_polarity(struct lgdt3306a_state *state,
250b63b36faSFred Richter 				       enum lgdt3306a_tp_clock_edge edge,
251b63b36faSFred Richter 				       enum lgdt3306a_tp_valid_polarity valid)
252b63b36faSFred Richter {
253b63b36faSFred Richter 	u8 val;
254b63b36faSFred Richter 	int ret;
255b63b36faSFred Richter 
256b63b36faSFred Richter 	lg_dbg("edge=%d, valid=%d\n", edge, valid);
257b63b36faSFred Richter 
258b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0070, &val);
259b63b36faSFred Richter 	if (lg_chkerr(ret))
260b63b36faSFred Richter 		goto fail;
261b63b36faSFred Richter 
262*8e8cd34eSMichael Ira Krufky 	val &= ~0x06; /* TPCLKPOL=0x04, TPVALPOL=0x02 */
263b63b36faSFred Richter 
264b63b36faSFred Richter 	if (edge == LGDT3306A_TPCLK_RISING_EDGE)
265b63b36faSFred Richter 		val |= 0x04;
266b63b36faSFred Richter 	if (valid == LGDT3306A_TP_VALID_HIGH)
267b63b36faSFred Richter 		val |= 0x02;
268b63b36faSFred Richter 
269b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0070, val);
270b63b36faSFred Richter 	lg_chkerr(ret);
271b63b36faSFred Richter 
272b63b36faSFred Richter fail:
273b63b36faSFred Richter 	return ret;
274b63b36faSFred Richter }
275b63b36faSFred Richter 
276b63b36faSFred Richter static int lgdt3306a_mpeg_tristate(struct lgdt3306a_state *state,
277b63b36faSFred Richter 				     int mode)
278b63b36faSFred Richter {
279b63b36faSFred Richter 	u8 val;
280b63b36faSFred Richter 	int ret;
281b63b36faSFred Richter 
282b63b36faSFred Richter 	lg_dbg("(%d)\n", mode);
283b63b36faSFred Richter 
284b63b36faSFred Richter 	if (mode) {
285b63b36faSFred Richter 		ret = lgdt3306a_read_reg(state, 0x0070, &val);
286b63b36faSFred Richter 		if (lg_chkerr(ret))
287b63b36faSFred Richter 			goto fail;
288*8e8cd34eSMichael Ira Krufky 		val &= ~0xA8; /* Tristate bus; TPOUTEN=0x80, TPCLKOUTEN=0x20, TPDATAOUTEN=0x08 */
289b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x0070, val);
290b63b36faSFred Richter 		if (lg_chkerr(ret))
291b63b36faSFred Richter 			goto fail;
292b63b36faSFred Richter 
293*8e8cd34eSMichael Ira Krufky 		ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 1); /* AGCIFOUTENB=0x40; 1=Disable IFAGC pin */
294b63b36faSFred Richter 		if (lg_chkerr(ret))
295b63b36faSFred Richter 			goto fail;
296b63b36faSFred Richter 
297b63b36faSFred Richter 	} else {
298*8e8cd34eSMichael Ira Krufky 		ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 0); /* enable IFAGC pin */
299b63b36faSFred Richter 		if (lg_chkerr(ret))
300b63b36faSFred Richter 			goto fail;
301b63b36faSFred Richter 
302b63b36faSFred Richter 		ret = lgdt3306a_read_reg(state, 0x0070, &val);
303b63b36faSFred Richter 		if (lg_chkerr(ret))
304b63b36faSFred Richter 			goto fail;
305b63b36faSFred Richter 
306*8e8cd34eSMichael Ira Krufky 		val |= 0xA8; /* enable bus */
307b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x0070, val);
308b63b36faSFred Richter 		if (lg_chkerr(ret))
309b63b36faSFred Richter 			goto fail;
310b63b36faSFred Richter 	}
311b63b36faSFred Richter 
312b63b36faSFred Richter fail:
313b63b36faSFred Richter 	return ret;
314b63b36faSFred Richter }
315b63b36faSFred Richter 
316b63b36faSFred Richter static int lgdt3306a_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
317b63b36faSFred Richter {
318b63b36faSFred Richter 	struct lgdt3306a_state *state = fe->demodulator_priv;
319b63b36faSFred Richter 
320b63b36faSFred Richter 	lg_dbg("acquire=%d\n", acquire);
321b63b36faSFred Richter 
322b63b36faSFred Richter 	return lgdt3306a_mpeg_tristate(state, acquire ? 0 : 1);
323b63b36faSFred Richter 
324b63b36faSFred Richter }
325b63b36faSFred Richter 
326b63b36faSFred Richter static int lgdt3306a_power(struct lgdt3306a_state *state,
327b63b36faSFred Richter 				     int mode)
328b63b36faSFred Richter {
329b63b36faSFred Richter 	int ret;
330b63b36faSFred Richter 
331b63b36faSFred Richter 	lg_dbg("(%d)\n", mode);
332b63b36faSFred Richter 
333b63b36faSFred Richter 	if (mode == 0) {
334*8e8cd34eSMichael Ira Krufky 		ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0); /* into reset */
335b63b36faSFred Richter 		if (lg_chkerr(ret))
336b63b36faSFred Richter 			goto fail;
337b63b36faSFred Richter 
338*8e8cd34eSMichael Ira Krufky 		ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 0); /* power down */
339b63b36faSFred Richter 		if (lg_chkerr(ret))
340b63b36faSFred Richter 			goto fail;
341b63b36faSFred Richter 
342b63b36faSFred Richter 	} else {
343*8e8cd34eSMichael Ira Krufky 		ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1); /* out of reset */
344b63b36faSFred Richter 		if (lg_chkerr(ret))
345b63b36faSFred Richter 			goto fail;
346b63b36faSFred Richter 
347*8e8cd34eSMichael Ira Krufky 		ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 1); /* power up */
348b63b36faSFred Richter 		if (lg_chkerr(ret))
349b63b36faSFred Richter 			goto fail;
350b63b36faSFred Richter 	}
351b63b36faSFred Richter 
352b63b36faSFred Richter #ifdef DBG_DUMP
353b63b36faSFred Richter 	lgdt3306a_DumpAllRegs(state);
354b63b36faSFred Richter #endif
355b63b36faSFred Richter fail:
356b63b36faSFred Richter 	return ret;
357b63b36faSFred Richter }
358b63b36faSFred Richter 
359b63b36faSFred Richter 
360b63b36faSFred Richter static int lgdt3306a_set_vsb(struct lgdt3306a_state *state)
361b63b36faSFred Richter {
362b63b36faSFred Richter 	u8 val;
363b63b36faSFred Richter 	int ret;
364b63b36faSFred Richter 
365b63b36faSFred Richter 	lg_dbg("\n");
366b63b36faSFred Richter 
367*8e8cd34eSMichael Ira Krufky 	/* 0. Spectrum inversion detection manual; spectrum inverted */
368b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0002, &val);
369*8e8cd34eSMichael Ira Krufky 	val &= 0xF7; /* SPECINVAUTO Off */
370*8e8cd34eSMichael Ira Krufky 	val |= 0x04; /* SPECINV On */
371b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0002, val);
372b63b36faSFred Richter 	if (lg_chkerr(ret))
373b63b36faSFred Richter 		goto fail;
374b63b36faSFred Richter 
375*8e8cd34eSMichael Ira Krufky 	/* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */
376b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0008, 0x80);
377b63b36faSFred Richter 	if (lg_chkerr(ret))
378b63b36faSFred Richter 		goto fail;
379b63b36faSFred Richter 
380*8e8cd34eSMichael Ira Krufky 	/* 2. Bandwidth mode for VSB(6MHz) */
381b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0009, &val);
382b63b36faSFred Richter 	val &= 0xE3;
383*8e8cd34eSMichael Ira Krufky 	val |= 0x0C; /* STDOPDETTMODE[2:0]=3 */
384b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0009, val);
385b63b36faSFred Richter 	if (lg_chkerr(ret))
386b63b36faSFred Richter 		goto fail;
387b63b36faSFred Richter 
388*8e8cd34eSMichael Ira Krufky 	/* 3. QAM mode detection mode(None) */
389b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0009, &val);
390*8e8cd34eSMichael Ira Krufky 	val &= 0xFC; /* STDOPDETCMODE[1:0]=0 */
391b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0009, val);
392b63b36faSFred Richter 	if (lg_chkerr(ret))
393b63b36faSFred Richter 		goto fail;
394b63b36faSFred Richter 
395*8e8cd34eSMichael Ira Krufky 	/* 4. ADC sampling frequency rate(2x sampling) */
396b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x000D, &val);
397*8e8cd34eSMichael Ira Krufky 	val &= 0xBF; /* SAMPLING4XFEN=0 */
398b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x000D, val);
399b63b36faSFred Richter 	if (lg_chkerr(ret))
400b63b36faSFred Richter 		goto fail;
401b63b36faSFred Richter 
402*8e8cd34eSMichael Ira Krufky #if 0
403*8e8cd34eSMichael Ira Krufky 	/* FGR - disable any AICC filtering, testing only */
404*8e8cd34eSMichael Ira Krufky 
405b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0024, 0x00);
406b63b36faSFred Richter 	if (lg_chkerr(ret))
407b63b36faSFred Richter 		goto fail;
408b63b36faSFred Richter 
409*8e8cd34eSMichael Ira Krufky 	/* AICCFIXFREQ0 NT N-1(Video rejection) */
410b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x002E, 0x00);
411b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x002F, 0x00);
412b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0030, 0x00);
413b63b36faSFred Richter 
414*8e8cd34eSMichael Ira Krufky 	/* AICCFIXFREQ1 NT N-1(Audio rejection) */
415b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x002B, 0x00);
416b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x002C, 0x00);
417b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x002D, 0x00);
418b63b36faSFred Richter 
419*8e8cd34eSMichael Ira Krufky 	/* AICCFIXFREQ2 NT Co-Channel(Video rejection) */
420b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0028, 0x00);
421b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0029, 0x00);
422b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x002A, 0x00);
423b63b36faSFred Richter 
424*8e8cd34eSMichael Ira Krufky 	/* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */
425b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0025, 0x00);
426b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0026, 0x00);
427b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0027, 0x00);
428b63b36faSFred Richter 
429*8e8cd34eSMichael Ira Krufky #else
430*8e8cd34eSMichael Ira Krufky 	/* FGR - this works well for HVR-1955,1975 */
431*8e8cd34eSMichael Ira Krufky 
432*8e8cd34eSMichael Ira Krufky 	/* 5. AICCOPMODE  NT N-1 Adj. */
433b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0024, 0x5A);
434b63b36faSFred Richter 	if (lg_chkerr(ret))
435b63b36faSFred Richter 		goto fail;
436b63b36faSFred Richter 
437*8e8cd34eSMichael Ira Krufky 	/* AICCFIXFREQ0 NT N-1(Video rejection) */
438b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x002E, 0x5A);
439b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x002F, 0x00);
440b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0030, 0x00);
441b63b36faSFred Richter 
442*8e8cd34eSMichael Ira Krufky 	/* AICCFIXFREQ1 NT N-1(Audio rejection) */
443b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x002B, 0x36);
444b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x002C, 0x00);
445b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x002D, 0x00);
446b63b36faSFred Richter 
447*8e8cd34eSMichael Ira Krufky 	/* AICCFIXFREQ2 NT Co-Channel(Video rejection) */
448b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0028, 0x2A);
449b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0029, 0x00);
450b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x002A, 0x00);
451b63b36faSFred Richter 
452*8e8cd34eSMichael Ira Krufky 	/* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */
453b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0025, 0x06);
454b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0026, 0x00);
455b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0027, 0x00);
456b63b36faSFred Richter #endif
457b63b36faSFred Richter 
458b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x001E, &val);
459b63b36faSFred Richter 	val &= 0x0F;
460b63b36faSFred Richter 	val |= 0xA0;
461b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x001E, val);
462b63b36faSFred Richter 
463b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0022, 0x08);
464b63b36faSFred Richter 
465b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0023, 0xFF);
466b63b36faSFred Richter 
467b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x211F, &val);
468b63b36faSFred Richter 	val &= 0xEF;
469b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x211F, val);
470b63b36faSFred Richter 
471b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x2173, 0x01);
472b63b36faSFred Richter 
473b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x1061, &val);
474b63b36faSFred Richter 	val &= 0xF8;
475b63b36faSFred Richter 	val |= 0x04;
476b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x1061, val);
477b63b36faSFred Richter 
478b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x103D, &val);
479b63b36faSFred Richter 	val &= 0xCF;
480b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x103D, val);
481b63b36faSFred Richter 
482b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x2122, 0x40);
483b63b36faSFred Richter 
484b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x2141, &val);
485b63b36faSFred Richter 	val &= 0x3F;
486b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x2141, val);
487b63b36faSFred Richter 
488b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x2135, &val);
489b63b36faSFred Richter 	val &= 0x0F;
490b63b36faSFred Richter 	val |= 0x70;
491b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x2135, val);
492b63b36faSFred Richter 
493b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0003, &val);
494b63b36faSFred Richter 	val &= 0xF7;
495b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0003, val);
496b63b36faSFred Richter 
497b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x001C, &val);
498b63b36faSFred Richter 	val &= 0x7F;
499b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x001C, val);
500b63b36faSFred Richter 
501*8e8cd34eSMichael Ira Krufky 	/* 6. EQ step size */
502b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x2179, &val);
503b63b36faSFred Richter 	val &= 0xF8;
504b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x2179, val);
505b63b36faSFred Richter 
506b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x217A, &val);
507b63b36faSFred Richter 	val &= 0xF8;
508b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x217A, val);
509b63b36faSFred Richter 
510*8e8cd34eSMichael Ira Krufky 	/* 7. Reset */
511b63b36faSFred Richter 	ret = lgdt3306a_soft_reset(state);
512b63b36faSFred Richter 	if (lg_chkerr(ret))
513b63b36faSFred Richter 		goto fail;
514b63b36faSFred Richter 
515b63b36faSFred Richter 	lg_dbg("complete\n");
516b63b36faSFred Richter fail:
517b63b36faSFred Richter 	return ret;
518b63b36faSFred Richter }
519b63b36faSFred Richter 
520b63b36faSFred Richter static int lgdt3306a_set_qam(struct lgdt3306a_state *state, int modulation)
521b63b36faSFred Richter {
522b63b36faSFred Richter 	u8 val;
523b63b36faSFred Richter 	int ret;
524b63b36faSFred Richter 
525b63b36faSFred Richter 	lg_dbg("modulation=%d\n", modulation);
526b63b36faSFred Richter 
527*8e8cd34eSMichael Ira Krufky 	/* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */
528b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0008, 0x08);
529b63b36faSFred Richter 	if (lg_chkerr(ret))
530b63b36faSFred Richter 		goto fail;
531b63b36faSFred Richter 
532*8e8cd34eSMichael Ira Krufky 	/* 1a. Spectrum inversion detection to Auto */
533b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0002, &val);
534*8e8cd34eSMichael Ira Krufky 	val &= 0xFB; /* SPECINV Off */
535*8e8cd34eSMichael Ira Krufky 	val |= 0x08; /* SPECINVAUTO On */
536b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0002, val);
537b63b36faSFred Richter 	if (lg_chkerr(ret))
538b63b36faSFred Richter 		goto fail;
539b63b36faSFred Richter 
540*8e8cd34eSMichael Ira Krufky 	/* 2. Bandwidth mode for QAM */
541b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0009, &val);
542*8e8cd34eSMichael Ira Krufky 	val &= 0xE3; /* STDOPDETTMODE[2:0]=0 VSB Off */
543b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0009, val);
544b63b36faSFred Richter 	if (lg_chkerr(ret))
545b63b36faSFred Richter 		goto fail;
546b63b36faSFred Richter 
547*8e8cd34eSMichael Ira Krufky 	/* 3. : 64QAM/256QAM detection(manual, auto) */
548b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0009, &val);
549b63b36faSFred Richter 	val &= 0xFC;
550*8e8cd34eSMichael Ira Krufky 	val |= 0x02; /* STDOPDETCMODE[1:0]=1=Manual 2=Auto */
551b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0009, val);
552b63b36faSFred Richter 	if (lg_chkerr(ret))
553b63b36faSFred Richter 		goto fail;
554b63b36faSFred Richter 
555*8e8cd34eSMichael Ira Krufky 	/* 3a. : 64QAM/256QAM selection for manual */
556b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x101a, &val);
557b63b36faSFred Richter 	val &= 0xF8;
558*8e8cd34eSMichael Ira Krufky 	if (modulation == QAM_64)
559*8e8cd34eSMichael Ira Krufky 		val |= 0x02; /* QMDQMODE[2:0]=2=QAM64 */
560*8e8cd34eSMichael Ira Krufky 	else
561*8e8cd34eSMichael Ira Krufky 		val |= 0x04; /* QMDQMODE[2:0]=4=QAM256 */
562*8e8cd34eSMichael Ira Krufky 
563b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x101a, val);
564b63b36faSFred Richter 	if (lg_chkerr(ret))
565b63b36faSFred Richter 		goto fail;
566b63b36faSFred Richter 
567*8e8cd34eSMichael Ira Krufky 	/* 4. ADC sampling frequency rate(4x sampling) */
568b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x000D, &val);
569b63b36faSFred Richter 	val &= 0xBF;
570*8e8cd34eSMichael Ira Krufky 	val |= 0x40; /* SAMPLING4XFEN=1 */
571b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x000D, val);
572b63b36faSFred Richter 	if (lg_chkerr(ret))
573b63b36faSFred Richter 		goto fail;
574b63b36faSFred Richter 
575*8e8cd34eSMichael Ira Krufky 	/* 5. No AICC operation in QAM mode */
576b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0024, &val);
577b63b36faSFred Richter 	val &= 0x00;
578b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0024, val);
579b63b36faSFred Richter 	if (lg_chkerr(ret))
580b63b36faSFred Richter 		goto fail;
581b63b36faSFred Richter 
582*8e8cd34eSMichael Ira Krufky 	/* 6. Reset */
583b63b36faSFred Richter 	ret = lgdt3306a_soft_reset(state);
584b63b36faSFred Richter 	if (lg_chkerr(ret))
585b63b36faSFred Richter 		goto fail;
586b63b36faSFred Richter 
587b63b36faSFred Richter 	lg_dbg("complete\n");
588b63b36faSFred Richter fail:
589b63b36faSFred Richter 	return ret;
590b63b36faSFred Richter }
591b63b36faSFred Richter 
592b63b36faSFred Richter static int lgdt3306a_set_modulation(struct lgdt3306a_state *state,
593b63b36faSFred Richter 				   struct dtv_frontend_properties *p)
594b63b36faSFred Richter {
595b63b36faSFred Richter 	int ret;
596b63b36faSFred Richter 
597b63b36faSFred Richter 	lg_dbg("\n");
598b63b36faSFred Richter 
599b63b36faSFred Richter 	switch (p->modulation) {
600b63b36faSFred Richter 	case VSB_8:
601b63b36faSFred Richter 		ret = lgdt3306a_set_vsb(state);
602b63b36faSFred Richter 		break;
603b63b36faSFred Richter 	case QAM_64:
604b63b36faSFred Richter 		ret = lgdt3306a_set_qam(state, QAM_64);
605b63b36faSFred Richter 		break;
606b63b36faSFred Richter 	case QAM_256:
607b63b36faSFred Richter 		ret = lgdt3306a_set_qam(state, QAM_256);
608b63b36faSFred Richter 		break;
609b63b36faSFred Richter 	default:
610b63b36faSFred Richter 		return -EINVAL;
611b63b36faSFred Richter 	}
612b63b36faSFred Richter 	if (lg_chkerr(ret))
613b63b36faSFred Richter 		goto fail;
614b63b36faSFred Richter 
615b63b36faSFred Richter 	state->current_modulation = p->modulation;
616b63b36faSFred Richter 
617b63b36faSFred Richter fail:
618b63b36faSFred Richter 	return ret;
619b63b36faSFred Richter }
620b63b36faSFred Richter 
621b63b36faSFred Richter /* ------------------------------------------------------------------------ */
622b63b36faSFred Richter 
623b63b36faSFred Richter static int lgdt3306a_agc_setup(struct lgdt3306a_state *state,
624b63b36faSFred Richter 			      struct dtv_frontend_properties *p)
625b63b36faSFred Richter {
626*8e8cd34eSMichael Ira Krufky 	/* TODO: anything we want to do here??? */
627b63b36faSFred Richter 	lg_dbg("\n");
628b63b36faSFred Richter 
629b63b36faSFred Richter 	switch (p->modulation) {
630b63b36faSFred Richter 	case VSB_8:
631b63b36faSFred Richter 		break;
632b63b36faSFred Richter 	case QAM_64:
633b63b36faSFred Richter 	case QAM_256:
634b63b36faSFred Richter 		break;
635b63b36faSFred Richter 	default:
636b63b36faSFred Richter 		return -EINVAL;
637b63b36faSFred Richter 	}
638b63b36faSFred Richter 	return 0;
639b63b36faSFred Richter }
640b63b36faSFred Richter 
641b63b36faSFred Richter /* ------------------------------------------------------------------------ */
642b63b36faSFred Richter 
643b63b36faSFred Richter static int lgdt3306a_set_inversion(struct lgdt3306a_state *state,
644b63b36faSFred Richter 				       int inversion)
645b63b36faSFred Richter {
646b63b36faSFred Richter 	int ret;
647b63b36faSFred Richter 
648b63b36faSFred Richter 	lg_dbg("(%d)\n", inversion);
649b63b36faSFred Richter 
650b63b36faSFred Richter 	ret = lgdt3306a_set_reg_bit(state, 0x0002, 2, inversion ? 1 : 0);
651b63b36faSFred Richter 	return ret;
652b63b36faSFred Richter }
653b63b36faSFred Richter 
654b63b36faSFred Richter static int lgdt3306a_set_inversion_auto(struct lgdt3306a_state *state,
655b63b36faSFred Richter 				       int enabled)
656b63b36faSFred Richter {
657b63b36faSFred Richter 	int ret;
658b63b36faSFred Richter 
659b63b36faSFred Richter 	lg_dbg("(%d)\n", enabled);
660b63b36faSFred Richter 
661*8e8cd34eSMichael Ira Krufky 	/* 0=Manual 1=Auto(QAM only) */
662*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_set_reg_bit(state, 0x0002, 3, enabled);/* SPECINVAUTO=0x04 */
663b63b36faSFred Richter 	return ret;
664b63b36faSFred Richter }
665b63b36faSFred Richter 
666b63b36faSFred Richter static int lgdt3306a_spectral_inversion(struct lgdt3306a_state *state,
667b63b36faSFred Richter 				       struct dtv_frontend_properties *p,
668b63b36faSFred Richter 				       int inversion)
669b63b36faSFred Richter {
670b63b36faSFred Richter 	int ret = 0;
671b63b36faSFred Richter 
672b63b36faSFred Richter 	lg_dbg("(%d)\n", inversion);
673*8e8cd34eSMichael Ira Krufky #if 0
674*8e8cd34eSMichael Ira Krufky /* FGR - spectral_inversion defaults already set for VSB and QAM; can enable later if desired */
675b63b36faSFred Richter 
676b63b36faSFred Richter 	ret = lgdt3306a_set_inversion(state, inversion);
677b63b36faSFred Richter 
678b63b36faSFred Richter 	switch (p->modulation) {
679b63b36faSFred Richter 	case VSB_8:
680*8e8cd34eSMichael Ira Krufky 		ret = lgdt3306a_set_inversion_auto(state, 0); /* Manual only for VSB */
681b63b36faSFred Richter 		break;
682b63b36faSFred Richter 	case QAM_64:
683b63b36faSFred Richter 	case QAM_256:
684*8e8cd34eSMichael Ira Krufky 		ret = lgdt3306a_set_inversion_auto(state, 1); /* Auto ok for QAM */
685b63b36faSFred Richter 		break;
686b63b36faSFred Richter 	default:
687b63b36faSFred Richter 		ret = -EINVAL;
688b63b36faSFred Richter 	}
689b63b36faSFred Richter #endif
690b63b36faSFred Richter 	return ret;
691b63b36faSFred Richter }
692b63b36faSFred Richter 
693b63b36faSFred Richter static int lgdt3306a_set_if(struct lgdt3306a_state *state,
694b63b36faSFred Richter 			   struct dtv_frontend_properties *p)
695b63b36faSFred Richter {
696b63b36faSFred Richter 	int ret;
697b63b36faSFred Richter 	u16 if_freq_khz;
698b63b36faSFred Richter 	u8 nco1, nco2;
699b63b36faSFred Richter 
700b63b36faSFred Richter 	switch (p->modulation) {
701b63b36faSFred Richter 	case VSB_8:
702b63b36faSFred Richter 		if_freq_khz = state->cfg->vsb_if_khz;
703b63b36faSFred Richter 		break;
704b63b36faSFred Richter 	case QAM_64:
705b63b36faSFred Richter 	case QAM_256:
706b63b36faSFred Richter 		if_freq_khz = state->cfg->qam_if_khz;
707b63b36faSFred Richter 		break;
708b63b36faSFred Richter 	default:
709b63b36faSFred Richter 		return -EINVAL;
710b63b36faSFred Richter 	}
711b63b36faSFred Richter 
712b63b36faSFred Richter 	switch (if_freq_khz) {
713b63b36faSFred Richter 	default:
714b63b36faSFred Richter 	    lg_warn("IF=%d KHz is not supportted, 3250 assumed\n", if_freq_khz);
715*8e8cd34eSMichael Ira Krufky 		/* fallthrough */
716*8e8cd34eSMichael Ira Krufky 	case 3250:  /* 3.25Mhz */
717b63b36faSFred Richter 		nco1 = 0x34;
718b63b36faSFred Richter 		nco2 = 0x00;
719b63b36faSFred Richter 		break;
720*8e8cd34eSMichael Ira Krufky 	case 3500:  /* 3.50Mhz */
721b63b36faSFred Richter 		nco1 = 0x38;
722b63b36faSFred Richter 		nco2 = 0x00;
723b63b36faSFred Richter 		break;
724*8e8cd34eSMichael Ira Krufky 	case 4000:  /* 4.00Mhz */
725b63b36faSFred Richter 		nco1 = 0x40;
726b63b36faSFred Richter 		nco2 = 0x00;
727b63b36faSFred Richter 		break;
728*8e8cd34eSMichael Ira Krufky 	case 5000:  /* 5.00Mhz */
729b63b36faSFred Richter 		nco1 = 0x50;
730b63b36faSFred Richter 		nco2 = 0x00;
731b63b36faSFred Richter 		break;
732*8e8cd34eSMichael Ira Krufky 	case 5380: /* 5.38Mhz */
733b63b36faSFred Richter 		nco1 = 0x56;
734b63b36faSFred Richter 		nco2 = 0x14;
735b63b36faSFred Richter 		break;
736b63b36faSFred Richter 	}
737b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0010, nco1);
738b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0011, nco2);
739b63b36faSFred Richter 
740b63b36faSFred Richter 	lg_dbg("if_freq=%d KHz->[%04x]\n", if_freq_khz, nco1<<8 | nco2);
741b63b36faSFred Richter 
742b63b36faSFred Richter 	return 0;
743b63b36faSFred Richter }
744b63b36faSFred Richter 
745b63b36faSFred Richter /* ------------------------------------------------------------------------ */
746b63b36faSFred Richter 
747b63b36faSFred Richter static int lgdt3306a_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
748b63b36faSFred Richter {
749b63b36faSFred Richter 	struct lgdt3306a_state *state = fe->demodulator_priv;
750b63b36faSFred Richter 
751b63b36faSFred Richter 	if (state->cfg->deny_i2c_rptr) {
752b63b36faSFred Richter 		lg_dbg("deny_i2c_rptr=%d\n", state->cfg->deny_i2c_rptr);
753b63b36faSFred Richter 		return 0;
754b63b36faSFred Richter 	}
755b63b36faSFred Richter 	lg_dbg("(%d)\n", enable);
756b63b36faSFred Richter 
757*8e8cd34eSMichael Ira Krufky 	return lgdt3306a_set_reg_bit(state, 0x0002, 7, enable ? 0 : 1); /* NI2CRPTEN=0x80 */
758b63b36faSFred Richter }
759b63b36faSFred Richter 
760b63b36faSFred Richter static int lgdt3306a_sleep(struct lgdt3306a_state *state)
761b63b36faSFred Richter {
762b63b36faSFred Richter 	int ret;
763b63b36faSFred Richter 
764b63b36faSFred Richter 	lg_dbg("\n");
765*8e8cd34eSMichael Ira Krufky 	state->current_frequency = -1; /* force re-tune, when we wake */
766b63b36faSFred Richter 
767*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_mpeg_tristate(state, 1); /* disable data bus */
768b63b36faSFred Richter 	if (lg_chkerr(ret))
769b63b36faSFred Richter 		goto fail;
770b63b36faSFred Richter 
771*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_power(state, 0); /* power down */
772b63b36faSFred Richter 	lg_chkerr(ret);
773b63b36faSFred Richter 
774b63b36faSFred Richter fail:
775b63b36faSFred Richter 	return 0;
776b63b36faSFred Richter }
777b63b36faSFred Richter 
778b63b36faSFred Richter static int lgdt3306a_fe_sleep(struct dvb_frontend *fe)
779b63b36faSFred Richter {
780b63b36faSFred Richter 	struct lgdt3306a_state *state = fe->demodulator_priv;
781b63b36faSFred Richter 
782b63b36faSFred Richter 	return lgdt3306a_sleep(state);
783b63b36faSFred Richter }
784b63b36faSFred Richter 
785b63b36faSFred Richter static int lgdt3306a_init(struct dvb_frontend *fe)
786b63b36faSFred Richter {
787b63b36faSFred Richter 	struct lgdt3306a_state *state = fe->demodulator_priv;
788b63b36faSFred Richter 	u8 val;
789b63b36faSFred Richter 	int ret;
790b63b36faSFred Richter 
791b63b36faSFred Richter 	lg_dbg("\n");
792b63b36faSFred Richter 
793*8e8cd34eSMichael Ira Krufky 	/* 1. Normal operation mode */
794*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_set_reg_bit(state, 0x0001, 0, 1); /* SIMFASTENB=0x01 */
795b63b36faSFred Richter 	if (lg_chkerr(ret))
796b63b36faSFred Richter 		goto fail;
797b63b36faSFred Richter 
798*8e8cd34eSMichael Ira Krufky 	/* 2. Spectrum inversion auto detection (Not valid for VSB) */
799b63b36faSFred Richter 	ret = lgdt3306a_set_inversion_auto(state, 0);
800b63b36faSFred Richter 	if (lg_chkerr(ret))
801b63b36faSFred Richter 		goto fail;
802b63b36faSFred Richter 
803*8e8cd34eSMichael Ira Krufky 	/* 3. Spectrum inversion(According to the tuner configuration) */
804b63b36faSFred Richter 	ret = lgdt3306a_set_inversion(state, 1);
805b63b36faSFred Richter 	if (lg_chkerr(ret))
806b63b36faSFred Richter 		goto fail;
807b63b36faSFred Richter 
808*8e8cd34eSMichael Ira Krufky 	/* 4. Peak-to-peak voltage of ADC input signal */
809*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_set_reg_bit(state, 0x0004, 7, 1); /* ADCSEL1V=0x80=1Vpp; 0x00=2Vpp */
810b63b36faSFred Richter 	if (lg_chkerr(ret))
811b63b36faSFred Richter 		goto fail;
812b63b36faSFred Richter 
813*8e8cd34eSMichael Ira Krufky 	/* 5. ADC output data capture clock phase */
814*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_set_reg_bit(state, 0x0004, 2, 0); /* 0=same phase as ADC clock */
815b63b36faSFred Richter 	if (lg_chkerr(ret))
816b63b36faSFred Richter 		goto fail;
817b63b36faSFred Richter 
818*8e8cd34eSMichael Ira Krufky 	/* 5a. ADC sampling clock source */
819*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_set_reg_bit(state, 0x0004, 3, 0); /* ADCCLKPLLSEL=0x08; 0=use ext clock, not PLL */
820b63b36faSFred Richter 	if (lg_chkerr(ret))
821b63b36faSFred Richter 		goto fail;
822b63b36faSFred Richter 
823*8e8cd34eSMichael Ira Krufky 	/* 6. Automatic PLL set */
824*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_set_reg_bit(state, 0x0005, 6, 0); /* PLLSETAUTO=0x40; 0=off */
825b63b36faSFred Richter 	if (lg_chkerr(ret))
826b63b36faSFred Richter 		goto fail;
827b63b36faSFred Richter 
828*8e8cd34eSMichael Ira Krufky 	if (state->cfg->xtalMHz == 24) {	/* 24MHz */
829*8e8cd34eSMichael Ira Krufky 		/* 7. Frequency for PLL output(0x2564 for 192MHz for 24MHz) */
830b63b36faSFred Richter 		ret = lgdt3306a_read_reg(state, 0x0005, &val);
831b63b36faSFred Richter 		if (lg_chkerr(ret))
832b63b36faSFred Richter 			goto fail;
833b63b36faSFred Richter 		val &= 0xC0;
834b63b36faSFred Richter 		val |= 0x25;
835b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x0005, val);
836b63b36faSFred Richter 		if (lg_chkerr(ret))
837b63b36faSFred Richter 			goto fail;
838b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x0006, 0x64);
839b63b36faSFred Richter 		if (lg_chkerr(ret))
840b63b36faSFred Richter 			goto fail;
841b63b36faSFred Richter 
842*8e8cd34eSMichael Ira Krufky 		/* 8. ADC sampling frequency(0x180000 for 24MHz sampling) */
843b63b36faSFred Richter 		ret = lgdt3306a_read_reg(state, 0x000D, &val);
844b63b36faSFred Richter 		if (lg_chkerr(ret))
845b63b36faSFred Richter 			goto fail;
846b63b36faSFred Richter 		val &= 0xC0;
847b63b36faSFred Richter 		val |= 0x18;
848b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x000D, val);
849b63b36faSFred Richter 		if (lg_chkerr(ret))
850b63b36faSFred Richter 			goto fail;
851b63b36faSFred Richter 
852*8e8cd34eSMichael Ira Krufky 	} else if (state->cfg->xtalMHz == 25) { /* 25MHz */
853*8e8cd34eSMichael Ira Krufky 		/* 7. Frequency for PLL output */
854b63b36faSFred Richter 		ret = lgdt3306a_read_reg(state, 0x0005, &val);
855b63b36faSFred Richter 		if (lg_chkerr(ret))
856b63b36faSFred Richter 			goto fail;
857b63b36faSFred Richter 		val &= 0xC0;
858b63b36faSFred Richter 		val |= 0x25;
859b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x0005, val);
860b63b36faSFred Richter 		if (lg_chkerr(ret))
861b63b36faSFred Richter 			goto fail;
862b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x0006, 0x64);
863b63b36faSFred Richter 		if (lg_chkerr(ret))
864b63b36faSFred Richter 			goto fail;
865b63b36faSFred Richter 
866*8e8cd34eSMichael Ira Krufky 		/* 8. ADC sampling frequency(0x190000 for 25MHz sampling) */
867b63b36faSFred Richter 		ret = lgdt3306a_read_reg(state, 0x000D, &val);
868b63b36faSFred Richter 		if (lg_chkerr(ret))
869b63b36faSFred Richter 			goto fail;
870b63b36faSFred Richter 		val &= 0xC0;
871b63b36faSFred Richter 		val |= 0x19;
872b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x000D, val);
873b63b36faSFred Richter 		if (lg_chkerr(ret))
874b63b36faSFred Richter 			goto fail;
875b63b36faSFred Richter 	} else {
876b63b36faSFred Richter 		lg_err("Bad xtalMHz=%d\n", state->cfg->xtalMHz);
877b63b36faSFred Richter 	}
878*8e8cd34eSMichael Ira Krufky #if 0
879*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_write_reg(state, 0x000E, 0x00);
880*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_write_reg(state, 0x000F, 0x00);
881*8e8cd34eSMichael Ira Krufky #endif
882b63b36faSFred Richter 
883*8e8cd34eSMichael Ira Krufky 	/* 9. Center frequency of input signal of ADC */
884*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_write_reg(state, 0x0010, 0x34); /* 3.25MHz */
885b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0011, 0x00);
886b63b36faSFred Richter 
887*8e8cd34eSMichael Ira Krufky 	/* 10. Fixed gain error value */
888*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_write_reg(state, 0x0014, 0); /* gain error=0 */
889b63b36faSFred Richter 
890*8e8cd34eSMichael Ira Krufky 	/* 10a. VSB TR BW gear shift initial step */
891b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x103C, &val);
892b63b36faSFred Richter 	val &= 0x0F;
893*8e8cd34eSMichael Ira Krufky 	val |= 0x20; /* SAMGSAUTOSTL_V[3:0] = 2 */
894b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x103C, val);
895b63b36faSFred Richter 
896*8e8cd34eSMichael Ira Krufky 	/* 10b. Timing offset calibration in low temperature for VSB */
897b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x103D, &val);
898b63b36faSFred Richter 	val &= 0xFC;
899b63b36faSFred Richter 	val |= 0x03;
900b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x103D, val);
901b63b36faSFred Richter 
902*8e8cd34eSMichael Ira Krufky 	/* 10c. Timing offset calibration in low temperature for QAM */
903b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x1036, &val);
904b63b36faSFred Richter 	val &= 0xF0;
905b63b36faSFred Richter 	val |= 0x0C;
906b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x1036, val);
907b63b36faSFred Richter 
908*8e8cd34eSMichael Ira Krufky 	/* 11. Using the imaginary part of CIR in CIR loading */
909b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x211F, &val);
910*8e8cd34eSMichael Ira Krufky 	val &= 0xEF; /* do not use imaginary of CIR */
911b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x211F, val);
912b63b36faSFred Richter 
913*8e8cd34eSMichael Ira Krufky 	/* 12. Control of no signal detector function */
914b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x2849, &val);
915*8e8cd34eSMichael Ira Krufky 	val &= 0xEF; /* NOUSENOSIGDET=0, enable no signal detector */
916b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x2849, val);
917b63b36faSFred Richter 
918*8e8cd34eSMichael Ira Krufky 	/* FGR - put demod in some known mode */
919b63b36faSFred Richter 	ret = lgdt3306a_set_vsb(state);
920b63b36faSFred Richter 
921*8e8cd34eSMichael Ira Krufky 	/* 13. TP stream format */
922b63b36faSFred Richter 	ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode);
923b63b36faSFred Richter 
924*8e8cd34eSMichael Ira Krufky 	/* 14. disable output buses */
925b63b36faSFred Richter 	ret = lgdt3306a_mpeg_tristate(state, 1);
926b63b36faSFred Richter 
927*8e8cd34eSMichael Ira Krufky 	/* 15. Sleep (in reset) */
928b63b36faSFred Richter 	ret = lgdt3306a_sleep(state);
929b63b36faSFred Richter 	lg_chkerr(ret);
930b63b36faSFred Richter 
931b63b36faSFred Richter fail:
932b63b36faSFred Richter 	return ret;
933b63b36faSFred Richter }
934b63b36faSFred Richter 
935b63b36faSFred Richter static int lgdt3306a_set_parameters(struct dvb_frontend *fe)
936b63b36faSFred Richter {
937b63b36faSFred Richter 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
938b63b36faSFred Richter 	struct lgdt3306a_state *state = fe->demodulator_priv;
939b63b36faSFred Richter 	int ret;
940b63b36faSFred Richter 
941b63b36faSFred Richter 	lg_dbg("(%d, %d)\n", p->frequency, p->modulation);
942b63b36faSFred Richter 
943b63b36faSFred Richter 	if (state->current_frequency  == p->frequency &&
944b63b36faSFred Richter 	   state->current_modulation == p->modulation) {
945b63b36faSFred Richter 		lg_dbg(" (already set, skipping ...)\n");
946b63b36faSFred Richter 		return 0;
947b63b36faSFred Richter 	}
948b63b36faSFred Richter 	state->current_frequency = -1;
949b63b36faSFred Richter 	state->current_modulation = -1;
950b63b36faSFred Richter 
951*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_power(state, 1); /* power up */
952b63b36faSFred Richter 	if (lg_chkerr(ret))
953b63b36faSFred Richter 		goto fail;
954b63b36faSFred Richter 
955b63b36faSFred Richter 	if (fe->ops.tuner_ops.set_params) {
956b63b36faSFred Richter 		ret = fe->ops.tuner_ops.set_params(fe);
957b63b36faSFred Richter 		if (fe->ops.i2c_gate_ctrl)
958b63b36faSFred Richter 			fe->ops.i2c_gate_ctrl(fe, 0);
959*8e8cd34eSMichael Ira Krufky #if 0
960*8e8cd34eSMichael Ira Krufky 		if (lg_chkerr(ret))
961*8e8cd34eSMichael Ira Krufky 			goto fail;
962*8e8cd34eSMichael Ira Krufky 		state->current_frequency = p->frequency;
963*8e8cd34eSMichael Ira Krufky #endif
964b63b36faSFred Richter 	}
965b63b36faSFred Richter 
966b63b36faSFred Richter 	ret = lgdt3306a_set_modulation(state, p);
967b63b36faSFred Richter 	if (lg_chkerr(ret))
968b63b36faSFred Richter 		goto fail;
969b63b36faSFred Richter 
970b63b36faSFred Richter 	ret = lgdt3306a_agc_setup(state, p);
971b63b36faSFred Richter 	if (lg_chkerr(ret))
972b63b36faSFred Richter 		goto fail;
973b63b36faSFred Richter 
974b63b36faSFred Richter 	ret = lgdt3306a_set_if(state, p);
975b63b36faSFred Richter 	if (lg_chkerr(ret))
976b63b36faSFred Richter 		goto fail;
977b63b36faSFred Richter 
978b63b36faSFred Richter 	ret = lgdt3306a_spectral_inversion(state, p,
979b63b36faSFred Richter 					  state->cfg->spectral_inversion ? 1 : 0);
980b63b36faSFred Richter 	if (lg_chkerr(ret))
981b63b36faSFred Richter 		goto fail;
982b63b36faSFred Richter 
983b63b36faSFred Richter 	ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode);
984b63b36faSFred Richter 	if (lg_chkerr(ret))
985b63b36faSFred Richter 		goto fail;
986b63b36faSFred Richter 
987b63b36faSFred Richter 	ret = lgdt3306a_mpeg_mode_polarity(state,
988b63b36faSFred Richter 					  state->cfg->tpclk_edge,
989b63b36faSFred Richter 					  state->cfg->tpvalid_polarity);
990b63b36faSFred Richter 	if (lg_chkerr(ret))
991b63b36faSFred Richter 		goto fail;
992b63b36faSFred Richter 
993*8e8cd34eSMichael Ira Krufky 	ret = lgdt3306a_mpeg_tristate(state, 0); /* enable data bus */
994b63b36faSFred Richter 	if (lg_chkerr(ret))
995b63b36faSFred Richter 		goto fail;
996b63b36faSFred Richter 
997b63b36faSFred Richter 	ret = lgdt3306a_soft_reset(state);
998b63b36faSFred Richter 	if (lg_chkerr(ret))
999b63b36faSFred Richter 		goto fail;
1000b63b36faSFred Richter 
1001b63b36faSFred Richter #ifdef DBG_DUMP
1002b63b36faSFred Richter 	lgdt3306a_DumpAllRegs(state);
1003b63b36faSFred Richter #endif
1004b63b36faSFred Richter 	state->current_frequency = p->frequency;
1005b63b36faSFred Richter fail:
1006b63b36faSFred Richter 	return ret;
1007b63b36faSFred Richter }
1008b63b36faSFred Richter 
1009b63b36faSFred Richter static int lgdt3306a_get_frontend(struct dvb_frontend *fe)
1010b63b36faSFred Richter {
1011b63b36faSFred Richter 	struct lgdt3306a_state *state = fe->demodulator_priv;
1012b63b36faSFred Richter 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1013b63b36faSFred Richter 
1014b63b36faSFred Richter 	lg_dbg("(%u, %d)\n", state->current_frequency, state->current_modulation);
1015b63b36faSFred Richter 
1016b63b36faSFred Richter 	p->modulation = state->current_modulation;
1017b63b36faSFred Richter 	p->frequency = state->current_frequency;
1018b63b36faSFred Richter 	return 0;
1019b63b36faSFred Richter }
1020b63b36faSFred Richter 
1021b63b36faSFred Richter static enum dvbfe_algo lgdt3306a_get_frontend_algo(struct dvb_frontend *fe)
1022b63b36faSFred Richter {
1023b63b36faSFred Richter #if 1
1024b63b36faSFred Richter 	return DVBFE_ALGO_CUSTOM;
1025b63b36faSFred Richter #else
1026b63b36faSFred Richter 	return DVBFE_ALGO_HW;
1027b63b36faSFred Richter #endif
1028b63b36faSFred Richter }
1029b63b36faSFred Richter 
1030b63b36faSFred Richter /* ------------------------------------------------------------------------ */
1031b63b36faSFred Richter static void lgdt3306a_monitor_vsb(struct lgdt3306a_state *state)
1032b63b36faSFred Richter {
1033b63b36faSFred Richter 	u8 val;
1034b63b36faSFred Richter 	int ret;
1035b63b36faSFred Richter 	u8 snrRef, maxPowerMan, nCombDet;
1036b63b36faSFred Richter 	u16 fbDlyCir;
1037b63b36faSFred Richter 
1038b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x21A1, &val);
1039b63b36faSFred Richter 	snrRef = val & 0x3F;
1040b63b36faSFred Richter 
1041b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x2185, &maxPowerMan);
1042b63b36faSFred Richter 
1043b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x2191, &val);
1044b63b36faSFred Richter 	nCombDet = (val & 0x80) >> 7;
1045b63b36faSFred Richter 
1046b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x2180, &val);
1047b63b36faSFred Richter 	fbDlyCir = (val & 0x03) << 8;
1048b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x2181, &val);
1049b63b36faSFred Richter 	fbDlyCir |= val;
1050b63b36faSFred Richter 
1051b63b36faSFred Richter 	lg_dbg("snrRef=%d maxPowerMan=0x%x nCombDet=%d fbDlyCir=0x%x\n",
1052b63b36faSFred Richter 		snrRef, maxPowerMan, nCombDet, fbDlyCir);
1053b63b36faSFred Richter 
1054*8e8cd34eSMichael Ira Krufky 	/* Carrier offset sub loop bandwidth */
1055b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x1061, &val);
1056b63b36faSFred Richter 	val &= 0xF8;
1057b63b36faSFred Richter 	if ((snrRef > 18) && (maxPowerMan > 0x68) && (nCombDet == 0x01) && ((fbDlyCir == 0x03FF) || (fbDlyCir < 0x6C)))	{
1058*8e8cd34eSMichael Ira Krufky 		/* SNR is over 18dB and no ghosting */
1059*8e8cd34eSMichael Ira Krufky 		val |= 0x00; /* final bandwidth = 0 */
1060b63b36faSFred Richter 	} else {
1061*8e8cd34eSMichael Ira Krufky 		val |= 0x04; /* final bandwidth = 4 */
1062b63b36faSFred Richter 	}
1063b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x1061, val);
1064b63b36faSFred Richter 
1065*8e8cd34eSMichael Ira Krufky 	/* Adjust Notch Filter */
1066b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0024, &val);
1067b63b36faSFred Richter 	val &= 0x0F;
1068*8e8cd34eSMichael Ira Krufky 	if (nCombDet == 0) { /* Turn on the Notch Filter */
1069b63b36faSFred Richter 		val |= 0x50;
1070b63b36faSFred Richter 	}
1071b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x0024, val);
1072b63b36faSFred Richter 
1073*8e8cd34eSMichael Ira Krufky 	/* VSB Timing Recovery output normalization */
1074b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x103D, &val);
1075b63b36faSFred Richter 	val &= 0xCF;
1076b63b36faSFred Richter 	val |= 0x20;
1077b63b36faSFred Richter 	ret = lgdt3306a_write_reg(state, 0x103D, val);
1078b63b36faSFred Richter }
1079b63b36faSFred Richter 
1080b63b36faSFred Richter static LG3306_MODULATION lgdt3306a_check_oper_mode(struct lgdt3306a_state *state)
1081b63b36faSFred Richter {
1082b63b36faSFred Richter 	u8 val = 0;
1083b63b36faSFred Richter 	int ret;
1084b63b36faSFred Richter 
1085b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0081, &val);
1086b63b36faSFred Richter 
1087b63b36faSFred Richter 	if (val & 0x80)	{
1088b63b36faSFred Richter 		lg_dbg("VSB\n");
1089*8e8cd34eSMichael Ira Krufky 		return LG3306_VSB;
1090b63b36faSFred Richter 	}
1091b63b36faSFred Richter 	else if (val & 0x08) {
1092b63b36faSFred Richter 		ret = lgdt3306a_read_reg(state, 0x00A6, &val);
1093b63b36faSFred Richter 		val = val >> 2;
1094b63b36faSFred Richter 		if (val & 0x01) {
1095b63b36faSFred Richter 			lg_dbg("QAM256\n");
1096*8e8cd34eSMichael Ira Krufky 			return LG3306_QAM256;
1097b63b36faSFred Richter 		} else {
1098b63b36faSFred Richter 			lg_dbg("QAM64\n");
1099*8e8cd34eSMichael Ira Krufky 			return LG3306_QAM64;
1100b63b36faSFred Richter 		}
1101b63b36faSFred Richter 	}
1102b63b36faSFred Richter 	lg_warn("UNKNOWN\n");
1103*8e8cd34eSMichael Ira Krufky 	return LG3306_UNKNOWN_MODE;
1104b63b36faSFred Richter }
1105b63b36faSFred Richter 
1106b63b36faSFred Richter static LG3306_LOCK_STATUS lgdt3306a_check_lock_status(struct lgdt3306a_state *state,
1107b63b36faSFred Richter 			LG3306_LOCK_CHECK whatLock)
1108b63b36faSFred Richter {
1109b63b36faSFred Richter 	u8 val = 0;
1110b63b36faSFred Richter 	int ret;
1111b63b36faSFred Richter 	LG3306_MODULATION	modeOper;
1112b63b36faSFred Richter 	LG3306_LOCK_STATUS lockStatus;
1113b63b36faSFred Richter 
1114b63b36faSFred Richter 	modeOper = LG3306_UNKNOWN_MODE;
1115b63b36faSFred Richter 
1116*8e8cd34eSMichael Ira Krufky 	switch (whatLock) {
1117b63b36faSFred Richter 	case LG3306_SYNC_LOCK:
1118b63b36faSFred Richter 	{
1119b63b36faSFred Richter 		ret = lgdt3306a_read_reg(state, 0x00A6, &val);
1120b63b36faSFred Richter 
1121b63b36faSFred Richter 		if ((val & 0x80) == 0x80)
1122b63b36faSFred Richter 			lockStatus = LG3306_LOCK;
1123b63b36faSFred Richter 		else
1124b63b36faSFred Richter 			lockStatus = LG3306_UNLOCK;
1125b63b36faSFred Richter 
1126b63b36faSFred Richter 		lg_dbg("SYNC_LOCK=%x\n", lockStatus);
1127b63b36faSFred Richter 		break;
1128b63b36faSFred Richter 	}
1129b63b36faSFred Richter 	case LG3306_AGC_LOCK:
1130b63b36faSFred Richter 	{
1131b63b36faSFred Richter 		ret = lgdt3306a_read_reg(state, 0x0080, &val);
1132b63b36faSFred Richter 
1133b63b36faSFred Richter 		if ((val & 0x40) == 0x40)
1134b63b36faSFred Richter 			lockStatus = LG3306_LOCK;
1135b63b36faSFred Richter 		else
1136b63b36faSFred Richter 			lockStatus = LG3306_UNLOCK;
1137b63b36faSFred Richter 
1138b63b36faSFred Richter 		lg_dbg("AGC_LOCK=%x\n", lockStatus);
1139b63b36faSFred Richter 		break;
1140b63b36faSFred Richter 	}
1141b63b36faSFred Richter 	case LG3306_TR_LOCK:
1142b63b36faSFred Richter 	{
1143b63b36faSFred Richter 		modeOper = lgdt3306a_check_oper_mode(state);
1144*8e8cd34eSMichael Ira Krufky 		if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) {
1145b63b36faSFred Richter 			ret = lgdt3306a_read_reg(state, 0x1094, &val);
1146b63b36faSFred Richter 
1147b63b36faSFred Richter 			if ((val & 0x80) == 0x80)
1148b63b36faSFred Richter 				lockStatus = LG3306_LOCK;
1149b63b36faSFred Richter 			else
1150b63b36faSFred Richter 				lockStatus = LG3306_UNLOCK;
1151*8e8cd34eSMichael Ira Krufky 		} else
1152b63b36faSFred Richter 			lockStatus = LG3306_UNKNOWN_LOCK;
1153b63b36faSFred Richter 
1154b63b36faSFred Richter 		lg_dbg("TR_LOCK=%x\n", lockStatus);
1155b63b36faSFred Richter 		break;
1156b63b36faSFred Richter 	}
1157b63b36faSFred Richter 	case LG3306_FEC_LOCK:
1158b63b36faSFred Richter 	{
1159b63b36faSFred Richter 		modeOper = lgdt3306a_check_oper_mode(state);
1160*8e8cd34eSMichael Ira Krufky 		if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) {
1161b63b36faSFred Richter 			ret = lgdt3306a_read_reg(state, 0x0080, &val);
1162b63b36faSFred Richter 
1163b63b36faSFred Richter 			if ((val & 0x10) == 0x10)
1164b63b36faSFred Richter 				lockStatus = LG3306_LOCK;
1165b63b36faSFred Richter 			else
1166b63b36faSFred Richter 				lockStatus = LG3306_UNLOCK;
1167*8e8cd34eSMichael Ira Krufky 		} else
1168b63b36faSFred Richter 			lockStatus = LG3306_UNKNOWN_LOCK;
1169b63b36faSFred Richter 
1170b63b36faSFred Richter 		lg_dbg("FEC_LOCK=%x\n", lockStatus);
1171b63b36faSFred Richter 		break;
1172b63b36faSFred Richter 	}
1173b63b36faSFred Richter 
1174b63b36faSFred Richter 	default:
1175b63b36faSFred Richter 		lockStatus = LG3306_UNKNOWN_LOCK;
1176b63b36faSFred Richter 		lg_warn("UNKNOWN whatLock=%d\n", whatLock);
1177b63b36faSFred Richter 		break;
1178b63b36faSFred Richter 	}
1179b63b36faSFred Richter 
1180*8e8cd34eSMichael Ira Krufky 	return lockStatus;
1181b63b36faSFred Richter }
1182b63b36faSFred Richter 
1183b63b36faSFred Richter static LG3306_NEVERLOCK_STATUS lgdt3306a_check_neverlock_status(struct lgdt3306a_state *state)
1184b63b36faSFred Richter {
1185b63b36faSFred Richter 	u8 val = 0;
1186b63b36faSFred Richter 	int ret;
1187b63b36faSFred Richter 	LG3306_NEVERLOCK_STATUS lockStatus;
1188b63b36faSFred Richter 
1189b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0080, &val);
1190b63b36faSFred Richter 	lockStatus = (LG3306_NEVERLOCK_STATUS)(val & 0x03);
1191b63b36faSFred Richter 
1192b63b36faSFred Richter 	lg_dbg("NeverLock=%d", lockStatus);
1193b63b36faSFred Richter 
1194*8e8cd34eSMichael Ira Krufky 	return lockStatus;
1195b63b36faSFred Richter }
1196b63b36faSFred Richter 
1197b63b36faSFred Richter static void lgdt3306a_pre_monitoring(struct lgdt3306a_state *state)
1198b63b36faSFred Richter {
1199b63b36faSFred Richter 	u8 val = 0;
1200b63b36faSFred Richter 	int ret;
1201b63b36faSFred Richter 	u8 currChDiffACQ, snrRef, mainStrong, aiccrejStatus;
1202b63b36faSFred Richter 
1203*8e8cd34eSMichael Ira Krufky 	/* Channel variation */
1204b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x21BC, &currChDiffACQ);
1205b63b36faSFred Richter 
1206*8e8cd34eSMichael Ira Krufky 	/* SNR of Frame sync */
1207b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x21A1, &val);
1208b63b36faSFred Richter 	snrRef = val & 0x3F;
1209b63b36faSFred Richter 
1210*8e8cd34eSMichael Ira Krufky 	/* Strong Main CIR */
1211b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x2199, &val);
1212b63b36faSFred Richter 	mainStrong = (val & 0x40) >> 6;
1213b63b36faSFred Richter 
1214b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0090, &val);
1215b63b36faSFred Richter 	aiccrejStatus = (val & 0xF0) >> 4;
1216b63b36faSFred Richter 
1217b63b36faSFred Richter 	lg_dbg("snrRef=%d mainStrong=%d aiccrejStatus=%d currChDiffACQ=0x%x\n",
1218b63b36faSFred Richter 		snrRef, mainStrong, aiccrejStatus, currChDiffACQ);
1219b63b36faSFred Richter 
1220*8e8cd34eSMichael Ira Krufky #if 0
1221*8e8cd34eSMichael Ira Krufky 	if ((mainStrong == 0) && (currChDiffACQ > 0x70)) /* Dynamic ghost exists */
1222*8e8cd34eSMichael Ira Krufky #endif
1223*8e8cd34eSMichael Ira Krufky 	if (mainStrong == 0) {
1224b63b36faSFred Richter 		ret = lgdt3306a_read_reg(state, 0x2135, &val);
1225b63b36faSFred Richter 		val &= 0x0F;
1226b63b36faSFred Richter 		val |= 0xA0;
1227b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x2135, val);
1228b63b36faSFred Richter 
1229b63b36faSFred Richter 		ret = lgdt3306a_read_reg(state, 0x2141, &val);
1230b63b36faSFred Richter 		val &= 0x3F;
1231b63b36faSFred Richter 		val |= 0x80;
1232b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x2141, val);
1233b63b36faSFred Richter 
1234b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x2122, 0x70);
1235*8e8cd34eSMichael Ira Krufky 	} else { /* Weak ghost or static channel */
1236b63b36faSFred Richter 		ret = lgdt3306a_read_reg(state, 0x2135, &val);
1237b63b36faSFred Richter 		val &= 0x0F;
1238b63b36faSFred Richter 		val |= 0x70;
1239b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x2135, val);
1240b63b36faSFred Richter 
1241b63b36faSFred Richter 		ret = lgdt3306a_read_reg(state, 0x2141, &val);
1242b63b36faSFred Richter 		val &= 0x3F;
1243b63b36faSFred Richter 		val |= 0x40;
1244b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x2141, val);
1245b63b36faSFred Richter 
1246b63b36faSFred Richter 		ret = lgdt3306a_write_reg(state, 0x2122, 0x40);
1247b63b36faSFred Richter 	}
1248b63b36faSFred Richter 
1249b63b36faSFred Richter }
1250b63b36faSFred Richter 
1251b63b36faSFred Richter static LG3306_LOCK_STATUS lgdt3306a_sync_lock_poll(struct lgdt3306a_state *state)
1252b63b36faSFred Richter {
1253b63b36faSFred Richter 	LG3306_LOCK_STATUS syncLockStatus = LG3306_UNLOCK;
1254b63b36faSFred Richter 	int	i;
1255b63b36faSFred Richter 
1256b63b36faSFred Richter 	for (i = 0; i < 2; i++)	{
1257b63b36faSFred Richter 		msleep(30);
1258b63b36faSFred Richter 
1259b63b36faSFred Richter 		syncLockStatus = lgdt3306a_check_lock_status(state, LG3306_SYNC_LOCK);
1260b63b36faSFred Richter 
1261b63b36faSFred Richter 		if (syncLockStatus == LG3306_LOCK) {
1262b63b36faSFred Richter 			lg_dbg("locked(%d)\n", i);
1263*8e8cd34eSMichael Ira Krufky 			return LG3306_LOCK;
1264b63b36faSFred Richter 		}
1265b63b36faSFred Richter 	}
1266b63b36faSFred Richter 	lg_dbg("not locked\n");
1267*8e8cd34eSMichael Ira Krufky 	return LG3306_UNLOCK;
1268b63b36faSFred Richter }
1269b63b36faSFred Richter 
1270b63b36faSFred Richter static LG3306_LOCK_STATUS lgdt3306a_fec_lock_poll(struct lgdt3306a_state *state)
1271b63b36faSFred Richter {
1272b63b36faSFred Richter 	LG3306_LOCK_STATUS FECLockStatus = LG3306_UNLOCK;
1273b63b36faSFred Richter 	int	i;
1274b63b36faSFred Richter 
1275b63b36faSFred Richter 	for (i = 0; i < 2; i++)	{
1276b63b36faSFred Richter 		msleep(30);
1277b63b36faSFred Richter 
1278b63b36faSFred Richter 		FECLockStatus = lgdt3306a_check_lock_status(state, LG3306_FEC_LOCK);
1279b63b36faSFred Richter 
1280b63b36faSFred Richter 		if (FECLockStatus == LG3306_LOCK) {
1281b63b36faSFred Richter 			lg_dbg("locked(%d)\n", i);
1282*8e8cd34eSMichael Ira Krufky 			return FECLockStatus;
1283b63b36faSFred Richter 		}
1284b63b36faSFred Richter 	}
1285b63b36faSFred Richter 	lg_dbg("not locked\n");
1286*8e8cd34eSMichael Ira Krufky 	return FECLockStatus;
1287b63b36faSFred Richter }
1288b63b36faSFred Richter 
1289b63b36faSFred Richter static LG3306_NEVERLOCK_STATUS lgdt3306a_neverlock_poll(struct lgdt3306a_state *state)
1290b63b36faSFred Richter {
1291b63b36faSFred Richter 	LG3306_NEVERLOCK_STATUS NLLockStatus = LG3306_NL_FAIL;
1292b63b36faSFred Richter 	int	i;
1293b63b36faSFred Richter 
1294b63b36faSFred Richter 	for (i = 0; i < 5; i++) {
1295b63b36faSFred Richter 		msleep(30);
1296b63b36faSFred Richter 
1297b63b36faSFred Richter 		NLLockStatus = lgdt3306a_check_neverlock_status(state);
1298b63b36faSFred Richter 
1299b63b36faSFred Richter 		if (NLLockStatus == LG3306_NL_LOCK) {
1300b63b36faSFred Richter 			lg_dbg("NL_LOCK(%d)\n", i);
1301*8e8cd34eSMichael Ira Krufky 			return NLLockStatus;
1302b63b36faSFred Richter 		}
1303b63b36faSFred Richter 	}
1304b63b36faSFred Richter 	lg_dbg("NLLockStatus=%d\n", NLLockStatus);
1305*8e8cd34eSMichael Ira Krufky 	return NLLockStatus;
1306b63b36faSFred Richter }
1307b63b36faSFred Richter 
1308b63b36faSFred Richter static u8 lgdt3306a_get_packet_error(struct lgdt3306a_state *state)
1309b63b36faSFred Richter {
1310b63b36faSFred Richter 	u8 val;
1311b63b36faSFred Richter 	int ret;
1312b63b36faSFred Richter 
1313b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x00FA, &val);
1314b63b36faSFred Richter 
1315*8e8cd34eSMichael Ira Krufky 	return val;
1316b63b36faSFred Richter }
1317b63b36faSFred Richter 
1318b63b36faSFred Richter static u32 log10_x1000(u32 x)
1319b63b36faSFred Richter {
1320b63b36faSFred Richter 	static u32 valx_x10[]     = {  10,  11,  13,  15,  17,  20,  25,  33,  41,  50,  59,  73,  87,  100 };
1321b63b36faSFred Richter 	static u32 log10x_x1000[] = {   0,  41, 114, 176, 230, 301, 398, 518, 613, 699, 771, 863, 939, 1000 };
1322b63b36faSFred Richter 	static u32 nelems = sizeof(valx_x10)/sizeof(valx_x10[0]);
1323b63b36faSFred Richter 	u32 log_val = 0;
1324b63b36faSFred Richter 	u32 i;
1325b63b36faSFred Richter 
1326b63b36faSFred Richter 	if (x <= 0)
1327*8e8cd34eSMichael Ira Krufky 		return -1000000; /* signal error */
1328b63b36faSFred Richter 
1329b63b36faSFred Richter 	if (x < 10) {
1330b63b36faSFred Richter 		while (x < 10) {
1331b63b36faSFred Richter 			x = x * 10;
1332b63b36faSFred Richter 			log_val--;
1333b63b36faSFred Richter 		}
1334b63b36faSFred Richter 	} else if (x == 10) {
1335*8e8cd34eSMichael Ira Krufky 		return 0; /* log(1)=0 */
1336b63b36faSFred Richter 	} else {
1337b63b36faSFred Richter 		while (x >= 100) {
1338b63b36faSFred Richter 			x = x / 10;
1339b63b36faSFred Richter 			log_val++;
1340b63b36faSFred Richter 		}
1341b63b36faSFred Richter 	}
1342b63b36faSFred Richter 	log_val *= 1000;
1343b63b36faSFred Richter 
1344*8e8cd34eSMichael Ira Krufky 	if (x == 10) /* was our input an exact multiple of 10 */
1345*8e8cd34eSMichael Ira Krufky 		return log_val;	/* don't need to interpolate */
1346b63b36faSFred Richter 
1347*8e8cd34eSMichael Ira Krufky 	/* find our place on the log curve */
1348b63b36faSFred Richter 	for (i = 1; i < nelems; i++) {
1349*8e8cd34eSMichael Ira Krufky 		if (valx_x10[i] >= x)
1350*8e8cd34eSMichael Ira Krufky 			break;
1351b63b36faSFred Richter 	}
1352b63b36faSFred Richter 
1353b63b36faSFred Richter 	{
1354b63b36faSFred Richter 		u32 diff_val   = x - valx_x10[i-1];
1355b63b36faSFred Richter 		u32 step_val   = valx_x10[i] - valx_x10[i-1];
1356b63b36faSFred Richter 		u32 step_log10 = log10x_x1000[i] - log10x_x1000[i-1];
1357*8e8cd34eSMichael Ira Krufky 		/* do a linear interpolation to get in-between values */
1358*8e8cd34eSMichael Ira Krufky 		return log_val + log10x_x1000[i-1] +
1359*8e8cd34eSMichael Ira Krufky 			((diff_val*step_log10) / step_val);
1360b63b36faSFred Richter 	}
1361b63b36faSFred Richter }
1362b63b36faSFred Richter 
1363b63b36faSFred Richter static u32 lgdt3306a_calculate_snr_x100(struct lgdt3306a_state *state)
1364b63b36faSFred Richter {
1365b63b36faSFred Richter 	u32 mse;  /* Mean-Square Error */
1366b63b36faSFred Richter 	u32 pwr;  /* Constelation power */
1367b63b36faSFred Richter 	u32 snr_x100;
1368b63b36faSFred Richter 
1369b63b36faSFred Richter 	mse = (read_reg(state, 0x00EC) << 8) |
1370b63b36faSFred Richter 	      (read_reg(state, 0x00ED));
1371b63b36faSFred Richter 	pwr = (read_reg(state, 0x00E8) << 8) |
1372b63b36faSFred Richter 	      (read_reg(state, 0x00E9));
1373b63b36faSFred Richter 
1374b63b36faSFred Richter 	if (mse == 0) /* no signal */
1375b63b36faSFred Richter 		return 0;
1376b63b36faSFred Richter 
1377b63b36faSFred Richter 	snr_x100 = log10_x1000((pwr * 10000) / mse) - 3000;
1378b63b36faSFred Richter 	lg_dbg("mse=%u, pwr=%u, snr_x100=%d\n", mse, pwr, snr_x100);
1379b63b36faSFred Richter 
1380b63b36faSFred Richter 	return snr_x100;
1381b63b36faSFred Richter }
1382b63b36faSFred Richter 
1383b63b36faSFred Richter static LG3306_LOCK_STATUS lgdt3306a_vsb_lock_poll(struct lgdt3306a_state *state)
1384b63b36faSFred Richter {
1385b63b36faSFred Richter 	u8 cnt = 0;
1386b63b36faSFred Richter 	u8 packet_error;
1387b63b36faSFred Richter 	u32 snr;
1388b63b36faSFred Richter 
1389b63b36faSFred Richter 	while (1) {
1390b63b36faSFred Richter 		if (lgdt3306a_sync_lock_poll(state) == LG3306_UNLOCK) {
1391b63b36faSFred Richter 			lg_dbg("no sync lock!\n");
1392*8e8cd34eSMichael Ira Krufky 			return LG3306_UNLOCK;
1393b63b36faSFred Richter 		} else {
1394b63b36faSFred Richter 			msleep(20);
1395b63b36faSFred Richter 			lgdt3306a_pre_monitoring(state);
1396b63b36faSFred Richter 
1397b63b36faSFred Richter 			packet_error = lgdt3306a_get_packet_error(state);
1398b63b36faSFred Richter 			snr = lgdt3306a_calculate_snr_x100(state);
1399*8e8cd34eSMichael Ira Krufky 			lg_dbg("cnt=%d errors=%d snr=%d\n",
1400*8e8cd34eSMichael Ira Krufky 			       cnt, packet_error, snr);
1401b63b36faSFred Richter 
1402*8e8cd34eSMichael Ira Krufky 			if ((snr < 1500) || (packet_error >= 0xff))
1403b63b36faSFred Richter 				cnt++;
1404*8e8cd34eSMichael Ira Krufky 			else
1405*8e8cd34eSMichael Ira Krufky 				return LG3306_LOCK;
1406b63b36faSFred Richter 
1407b63b36faSFred Richter 			if (cnt >= 10) {
1408b63b36faSFred Richter 				lg_dbg("not locked!\n");
1409*8e8cd34eSMichael Ira Krufky 				return LG3306_UNLOCK;
1410b63b36faSFred Richter 			}
1411b63b36faSFred Richter 		}
1412b63b36faSFred Richter 	}
1413*8e8cd34eSMichael Ira Krufky 	return LG3306_UNLOCK;
1414b63b36faSFred Richter }
1415b63b36faSFred Richter 
1416b63b36faSFred Richter static LG3306_LOCK_STATUS lgdt3306a_qam_lock_poll(struct lgdt3306a_state *state)
1417b63b36faSFred Richter {
1418b63b36faSFred Richter 	u8 cnt = 0;
1419b63b36faSFred Richter 	u8 packet_error;
1420b63b36faSFred Richter 	u32	snr;
1421b63b36faSFred Richter 
1422b63b36faSFred Richter 	while (1) {
1423b63b36faSFred Richter 		if (lgdt3306a_fec_lock_poll(state) == LG3306_UNLOCK) {
1424b63b36faSFred Richter 			lg_dbg("no fec lock!\n");
1425*8e8cd34eSMichael Ira Krufky 			return LG3306_UNLOCK;
1426b63b36faSFred Richter 		} else {
1427b63b36faSFred Richter 			msleep(20);
1428b63b36faSFred Richter 
1429b63b36faSFred Richter 			packet_error = lgdt3306a_get_packet_error(state);
1430b63b36faSFred Richter 			snr = lgdt3306a_calculate_snr_x100(state);
1431*8e8cd34eSMichael Ira Krufky 			lg_dbg("cnt=%d errors=%d snr=%d\n",
1432*8e8cd34eSMichael Ira Krufky 			       cnt, packet_error, snr);
1433b63b36faSFred Richter 
1434*8e8cd34eSMichael Ira Krufky 			if ((snr < 1500) || (packet_error >= 0xff))
1435b63b36faSFred Richter 				cnt++;
1436*8e8cd34eSMichael Ira Krufky 			else
1437*8e8cd34eSMichael Ira Krufky 				return LG3306_LOCK;
1438b63b36faSFred Richter 
1439b63b36faSFred Richter 			if (cnt >= 10) {
1440b63b36faSFred Richter 				lg_dbg("not locked!\n");
1441*8e8cd34eSMichael Ira Krufky 				return LG3306_UNLOCK;
1442b63b36faSFred Richter 			}
1443b63b36faSFred Richter 		}
1444b63b36faSFred Richter 	}
1445*8e8cd34eSMichael Ira Krufky 	return LG3306_UNLOCK;
1446b63b36faSFred Richter }
1447b63b36faSFred Richter 
1448b63b36faSFred Richter static int lgdt3306a_read_status(struct dvb_frontend *fe, fe_status_t *status)
1449b63b36faSFred Richter {
1450b63b36faSFred Richter 	struct lgdt3306a_state *state = fe->demodulator_priv;
1451b63b36faSFred Richter 	u16 strength = 0;
1452*8e8cd34eSMichael Ira Krufky 	int ret = 0;
1453*8e8cd34eSMichael Ira Krufky 
1454b63b36faSFred Richter 	if (fe->ops.tuner_ops.get_rf_strength) {
1455b63b36faSFred Richter 		ret = fe->ops.tuner_ops.get_rf_strength(fe, &strength);
1456b63b36faSFred Richter 		if (ret == 0) {
1457b63b36faSFred Richter 			lg_dbg("strength=%d\n", strength);
1458b63b36faSFred Richter 		} else {
1459b63b36faSFred Richter 			lg_dbg("fe->ops.tuner_ops.get_rf_strength() failed\n");
1460b63b36faSFred Richter 		}
1461b63b36faSFred Richter 	}
1462b63b36faSFred Richter 
1463b63b36faSFred Richter 	*status = 0;
1464b63b36faSFred Richter 	if (lgdt3306a_neverlock_poll(state) == LG3306_NL_LOCK) {
1465b63b36faSFred Richter 		*status |= FE_HAS_SIGNAL;
1466b63b36faSFred Richter 		*status |= FE_HAS_CARRIER;
1467b63b36faSFred Richter 
1468b63b36faSFred Richter 		switch (state->current_modulation) {
1469b63b36faSFred Richter 		case QAM_256:
1470b63b36faSFred Richter 		case QAM_64:
1471b63b36faSFred Richter 			if (lgdt3306a_qam_lock_poll(state) == LG3306_LOCK) {
1472b63b36faSFred Richter 				*status |= FE_HAS_VITERBI;
1473b63b36faSFred Richter 				*status |= FE_HAS_SYNC;
1474b63b36faSFred Richter 
1475b63b36faSFred Richter 				*status |= FE_HAS_LOCK;
1476b63b36faSFred Richter 			}
1477b63b36faSFred Richter 			break;
1478b63b36faSFred Richter 		case VSB_8:
1479b63b36faSFred Richter 			if (lgdt3306a_vsb_lock_poll(state) == LG3306_LOCK) {
1480b63b36faSFred Richter 				*status |= FE_HAS_VITERBI;
1481b63b36faSFred Richter 				*status |= FE_HAS_SYNC;
1482b63b36faSFred Richter 
1483b63b36faSFred Richter 				*status |= FE_HAS_LOCK;
1484b63b36faSFred Richter 
1485b63b36faSFred Richter 				lgdt3306a_monitor_vsb(state);
1486b63b36faSFred Richter 			}
1487b63b36faSFred Richter 			break;
1488b63b36faSFred Richter 		default:
1489b63b36faSFred Richter 			ret = -EINVAL;
1490b63b36faSFred Richter 		}
1491b63b36faSFred Richter 	}
1492b63b36faSFred Richter 	return ret;
1493b63b36faSFred Richter }
1494b63b36faSFred Richter 
1495b63b36faSFred Richter 
1496b63b36faSFred Richter static int lgdt3306a_read_snr(struct dvb_frontend *fe, u16 *snr)
1497b63b36faSFred Richter {
1498b63b36faSFred Richter 	struct lgdt3306a_state *state = fe->demodulator_priv;
1499b63b36faSFred Richter 
1500b63b36faSFred Richter 	state->snr = lgdt3306a_calculate_snr_x100(state);
1501b63b36faSFred Richter 	/* report SNR in dB * 10 */
1502b63b36faSFred Richter 	*snr = state->snr/10;
1503b63b36faSFred Richter 
1504b63b36faSFred Richter 	return 0;
1505b63b36faSFred Richter }
1506b63b36faSFred Richter 
1507b63b36faSFred Richter static int lgdt3306a_read_signal_strength(struct dvb_frontend *fe,
1508b63b36faSFred Richter 					 u16 *strength)
1509b63b36faSFred Richter {
1510b63b36faSFred Richter 	/*
1511b63b36faSFred Richter 	 * Calculate some sort of "strength" from SNR
1512b63b36faSFred Richter 	 */
1513b63b36faSFred Richter 	struct lgdt3306a_state *state = fe->demodulator_priv;
1514*8e8cd34eSMichael Ira Krufky 	u16 snr;  /* snr_x10 */
1515b63b36faSFred Richter 	int ret;
1516*8e8cd34eSMichael Ira Krufky 	u32 ref_snr; /* snr*100 */
1517b63b36faSFred Richter 	u32 str;
1518b63b36faSFred Richter 
1519b63b36faSFred Richter 	*strength = 0;
1520b63b36faSFred Richter 
1521b63b36faSFred Richter 	switch (state->current_modulation) {
1522b63b36faSFred Richter 	case VSB_8:
1523*8e8cd34eSMichael Ira Krufky 		 ref_snr = 1600; /* 16dB */
1524b63b36faSFred Richter 		 break;
1525b63b36faSFred Richter 	case QAM_64:
1526*8e8cd34eSMichael Ira Krufky 		 ref_snr = 2200; /* 22dB */
1527b63b36faSFred Richter 		 break;
1528b63b36faSFred Richter 	case QAM_256:
1529*8e8cd34eSMichael Ira Krufky 		 ref_snr = 2800; /* 28dB */
1530b63b36faSFred Richter 		 break;
1531b63b36faSFred Richter 	default:
1532b63b36faSFred Richter 		return -EINVAL;
1533b63b36faSFred Richter 	}
1534b63b36faSFred Richter 
1535b63b36faSFred Richter 	ret = fe->ops.read_snr(fe, &snr);
1536b63b36faSFred Richter 	if (lg_chkerr(ret))
1537b63b36faSFred Richter 		goto fail;
1538b63b36faSFred Richter 
1539b63b36faSFred Richter 	if (state->snr <= (ref_snr - 100))
1540b63b36faSFred Richter 		str = 0;
1541b63b36faSFred Richter 	else if (state->snr <= ref_snr)
1542*8e8cd34eSMichael Ira Krufky 		str = (0xffff * 65) / 100; /* 65% */
1543b63b36faSFred Richter 	else {
1544b63b36faSFred Richter 		str = state->snr - ref_snr;
1545b63b36faSFred Richter 		str /= 50;
1546*8e8cd34eSMichael Ira Krufky 		str += 78; /* 78%-100% */
1547b63b36faSFred Richter 		if (str > 100)
1548b63b36faSFred Richter 			str = 100;
1549b63b36faSFred Richter 		str = (0xffff * str) / 100;
1550b63b36faSFred Richter 	}
1551b63b36faSFred Richter 	*strength = (u16)str;
1552b63b36faSFred Richter 	lg_dbg("strength=%u\n", *strength);
1553b63b36faSFred Richter 
1554b63b36faSFred Richter fail:
1555b63b36faSFred Richter 	return ret;
1556b63b36faSFred Richter }
1557b63b36faSFred Richter 
1558b63b36faSFred Richter /* ------------------------------------------------------------------------ */
1559b63b36faSFred Richter 
1560b63b36faSFred Richter static int lgdt3306a_read_ber(struct dvb_frontend *fe, u32 *ber)
1561b63b36faSFred Richter {
1562b63b36faSFred Richter 	struct lgdt3306a_state *state = fe->demodulator_priv;
1563b63b36faSFred Richter 	u32 tmp;
1564b63b36faSFred Richter 
1565b63b36faSFred Richter 	*ber = 0;
1566b63b36faSFred Richter #if 1
1567*8e8cd34eSMichael Ira Krufky 	/* FGR - BUGBUG - I don't know what value is expected by dvb_core
1568*8e8cd34eSMichael Ira Krufky 	 * what is the scale of the value?? */
1569*8e8cd34eSMichael Ira Krufky 	tmp =              read_reg(state, 0x00FC); /* NBERVALUE[24-31] */
1570*8e8cd34eSMichael Ira Krufky 	tmp = (tmp << 8) | read_reg(state, 0x00FD); /* NBERVALUE[16-23] */
1571*8e8cd34eSMichael Ira Krufky 	tmp = (tmp << 8) | read_reg(state, 0x00FE); /* NBERVALUE[8-15] */
1572*8e8cd34eSMichael Ira Krufky 	tmp = (tmp << 8) | read_reg(state, 0x00FF); /* NBERVALUE[0-7] */
1573b63b36faSFred Richter 	*ber = tmp;
1574b63b36faSFred Richter 	lg_dbg("ber=%u\n", tmp);
1575b63b36faSFred Richter #endif
1576b63b36faSFred Richter 	return 0;
1577b63b36faSFred Richter }
1578b63b36faSFred Richter 
1579b63b36faSFred Richter static int lgdt3306a_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
1580b63b36faSFred Richter {
1581b63b36faSFred Richter 	struct lgdt3306a_state *state = fe->demodulator_priv;
1582b63b36faSFred Richter 
1583b63b36faSFred Richter 	*ucblocks = 0;
1584b63b36faSFred Richter #if 1
1585*8e8cd34eSMichael Ira Krufky 	/* FGR - BUGBUG - I don't know what value is expected by dvb_core
1586*8e8cd34eSMichael Ira Krufky 	 * what happens when value wraps? */
1587*8e8cd34eSMichael Ira Krufky 	*ucblocks = read_reg(state, 0x00F4); /* TPIFTPERRCNT[0-7] */
1588b63b36faSFred Richter 	lg_dbg("ucblocks=%u\n", *ucblocks);
1589b63b36faSFred Richter #endif
1590b63b36faSFred Richter 
1591b63b36faSFred Richter 	return 0;
1592b63b36faSFred Richter }
1593b63b36faSFred Richter 
1594b63b36faSFred Richter static int lgdt3306a_tune(struct dvb_frontend *fe, bool re_tune, unsigned int mode_flags, unsigned int *delay, fe_status_t *status)
1595b63b36faSFred Richter {
1596b63b36faSFred Richter 	int ret = 0;
1597b63b36faSFred Richter 	struct lgdt3306a_state *state = fe->demodulator_priv;
1598b63b36faSFred Richter 
1599b63b36faSFred Richter 	lg_dbg("re_tune=%u\n", re_tune);
1600b63b36faSFred Richter 
1601b63b36faSFred Richter 	if (re_tune) {
1602*8e8cd34eSMichael Ira Krufky 		state->current_frequency = -1; /* force re-tune */
1603*8e8cd34eSMichael Ira Krufky 		if ((ret = lgdt3306a_set_parameters(fe)) != 0)
1604b63b36faSFred Richter 			return ret;
1605b63b36faSFred Richter 	}
1606b63b36faSFred Richter 	*delay = 125;
1607b63b36faSFred Richter 	ret = lgdt3306a_read_status(fe, status);
1608b63b36faSFred Richter 
1609b63b36faSFred Richter 	return ret;
1610b63b36faSFred Richter }
1611b63b36faSFred Richter 
1612b63b36faSFred Richter static int lgdt3306a_get_tune_settings(struct dvb_frontend *fe,
1613b63b36faSFred Richter 				       struct dvb_frontend_tune_settings
1614b63b36faSFred Richter 				       *fe_tune_settings)
1615b63b36faSFred Richter {
1616b63b36faSFred Richter 	fe_tune_settings->min_delay_ms = 100;
1617b63b36faSFred Richter 	lg_dbg("\n");
1618b63b36faSFred Richter 	return 0;
1619b63b36faSFred Richter }
1620b63b36faSFred Richter 
1621b63b36faSFred Richter static int lgdt3306a_search(struct dvb_frontend *fe)
1622b63b36faSFred Richter {
1623b63b36faSFred Richter 	fe_status_t status = 0;
1624b63b36faSFred Richter 	int i, ret;
1625b63b36faSFred Richter 
1626b63b36faSFred Richter 	/* set frontend */
1627b63b36faSFred Richter 	ret = lgdt3306a_set_parameters(fe);
1628b63b36faSFred Richter 	if (ret)
1629b63b36faSFred Richter 		goto error;
1630b63b36faSFred Richter 
1631b63b36faSFred Richter 	/* wait frontend lock */
1632b63b36faSFred Richter 	for (i = 20; i > 0; i--) {
1633b63b36faSFred Richter 		lg_dbg(": loop=%d\n", i);
1634b63b36faSFred Richter 		msleep(50);
1635b63b36faSFred Richter 		ret = lgdt3306a_read_status(fe, &status);
1636b63b36faSFred Richter 		if (ret)
1637b63b36faSFred Richter 			goto error;
1638b63b36faSFred Richter 
1639b63b36faSFred Richter 		if (status & FE_HAS_LOCK)
1640b63b36faSFred Richter 			break;
1641b63b36faSFred Richter 	}
1642b63b36faSFred Richter 
1643b63b36faSFred Richter 	/* check if we have a valid signal */
1644*8e8cd34eSMichael Ira Krufky 	if (status & FE_HAS_LOCK)
1645b63b36faSFred Richter 		return DVBFE_ALGO_SEARCH_SUCCESS;
1646*8e8cd34eSMichael Ira Krufky 	else
1647b63b36faSFred Richter 		return DVBFE_ALGO_SEARCH_AGAIN;
1648b63b36faSFred Richter 
1649b63b36faSFred Richter error:
1650b63b36faSFred Richter 	lg_dbg("failed (%d)\n", ret);
1651b63b36faSFred Richter 	return DVBFE_ALGO_SEARCH_ERROR;
1652b63b36faSFred Richter }
1653b63b36faSFred Richter 
1654b63b36faSFred Richter static void lgdt3306a_release(struct dvb_frontend *fe)
1655b63b36faSFred Richter {
1656b63b36faSFred Richter 	struct lgdt3306a_state *state = fe->demodulator_priv;
1657*8e8cd34eSMichael Ira Krufky 
1658b63b36faSFred Richter 	lg_dbg("\n");
1659b63b36faSFred Richter 	kfree(state);
1660b63b36faSFred Richter }
1661b63b36faSFred Richter 
1662b63b36faSFred Richter static struct dvb_frontend_ops lgdt3306a_ops;
1663b63b36faSFred Richter 
1664b63b36faSFred Richter struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config,
1665b63b36faSFred Richter 				     struct i2c_adapter *i2c_adap)
1666b63b36faSFred Richter {
1667b63b36faSFred Richter 	struct lgdt3306a_state *state = NULL;
1668b63b36faSFred Richter 	int ret;
1669b63b36faSFred Richter 	u8 val;
1670b63b36faSFred Richter 
1671b63b36faSFred Richter 	lg_dbg("(%d-%04x)\n",
1672b63b36faSFred Richter 	       i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
1673b63b36faSFred Richter 	       config ? config->i2c_addr : 0);
1674b63b36faSFred Richter 
1675b63b36faSFred Richter 	state = kzalloc(sizeof(struct lgdt3306a_state), GFP_KERNEL);
1676b63b36faSFred Richter 	if (state == NULL)
1677b63b36faSFred Richter 		goto fail;
1678b63b36faSFred Richter 
1679b63b36faSFred Richter 	state->cfg = config;
1680b63b36faSFred Richter 	state->i2c_adap = i2c_adap;
1681b63b36faSFred Richter 
1682b63b36faSFred Richter 	memcpy(&state->frontend.ops, &lgdt3306a_ops,
1683b63b36faSFred Richter 	       sizeof(struct dvb_frontend_ops));
1684b63b36faSFred Richter 	state->frontend.demodulator_priv = state;
1685b63b36faSFred Richter 
1686b63b36faSFred Richter 	/* verify that we're talking to a lg3306a */
1687*8e8cd34eSMichael Ira Krufky 	/* FGR - NOTE - there is no obvious ChipId to check; we check
1688*8e8cd34eSMichael Ira Krufky 	 * some "known" bits after reset, but it's still just a guess */
1689b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0000, &val);
1690b63b36faSFred Richter 	if (lg_chkerr(ret))
1691b63b36faSFred Richter 		goto fail;
1692b63b36faSFred Richter 	if ((val & 0x74) != 0x74) {
1693b63b36faSFred Richter 		lg_warn("expected 0x74, got 0x%x\n", (val & 0x74));
1694*8e8cd34eSMichael Ira Krufky #if 0
1695*8e8cd34eSMichael Ira Krufky 		goto fail;	/* BUGBUG - re-enable when we know this is right */
1696*8e8cd34eSMichael Ira Krufky #endif
1697b63b36faSFred Richter 	}
1698b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0001, &val);
1699b63b36faSFred Richter 	if (lg_chkerr(ret))
1700b63b36faSFred Richter 		goto fail;
1701b63b36faSFred Richter 	if ((val & 0xF6) != 0xC6) {
1702b63b36faSFred Richter 		lg_warn("expected 0xC6, got 0x%x\n", (val & 0xF6));
1703*8e8cd34eSMichael Ira Krufky #if 0
1704*8e8cd34eSMichael Ira Krufky 		goto fail;	/* BUGBUG - re-enable when we know this is right */
1705*8e8cd34eSMichael Ira Krufky #endif
1706b63b36faSFred Richter 	}
1707b63b36faSFred Richter 	ret = lgdt3306a_read_reg(state, 0x0002, &val);
1708b63b36faSFred Richter 	if (lg_chkerr(ret))
1709b63b36faSFred Richter 		goto fail;
1710b63b36faSFred Richter 	if ((val & 0x73) != 0x03) {
1711b63b36faSFred Richter 		lg_warn("expected 0x03, got 0x%x\n", (val & 0x73));
1712*8e8cd34eSMichael Ira Krufky #if 0
1713*8e8cd34eSMichael Ira Krufky 		goto fail;	/* BUGBUG - re-enable when we know this is right */
1714*8e8cd34eSMichael Ira Krufky #endif
1715b63b36faSFred Richter 	}
1716b63b36faSFred Richter 
1717b63b36faSFred Richter 	state->current_frequency = -1;
1718b63b36faSFred Richter 	state->current_modulation = -1;
1719b63b36faSFred Richter 
1720b63b36faSFred Richter 	lgdt3306a_sleep(state);
1721b63b36faSFred Richter 
1722b63b36faSFred Richter 	return &state->frontend;
1723b63b36faSFred Richter 
1724b63b36faSFred Richter fail:
1725b63b36faSFred Richter 	lg_warn("unable to detect LGDT3306A hardware\n");
1726b63b36faSFred Richter 	kfree(state);
1727b63b36faSFred Richter 	return NULL;
1728b63b36faSFred Richter }
1729b63b36faSFred Richter 
1730b63b36faSFred Richter #ifdef DBG_DUMP
1731b63b36faSFred Richter 
1732b63b36faSFred Richter static const short regtab[] = {
1733b63b36faSFred Richter   0x0000, //SOFTRSTB 1'b1 1'b1 1'b1 ADCPDB 1'b1 PLLPDB GBBPDB 11111111
1734b63b36faSFred Richter   0x0001, //1'b1 1'b1 1'b0 1'b0 AUTORPTRS
1735b63b36faSFred Richter   0x0002, //NI2CRPTEN 1'b0 1'b0 1'b0 SPECINVAUT
1736b63b36faSFred Richter   0x0003, //AGCRFOUT
1737b63b36faSFred Richter   0x0004, //ADCSEL1V ADCCNT ADCCNF ADCCNS ADCCLKPLL
1738b63b36faSFred Richter   0x0005, //PLLINDIVSE
1739b63b36faSFred Richter   0x0006, //PLLCTRL[7:0] 11100001
1740b63b36faSFred Richter   0x0007, //SYSINITWAITTIME[7:0] (msec) 00001000
1741b63b36faSFred Richter   0x0008, //STDOPMODE[7:0] 10000000
1742b63b36faSFred Richter   0x0009, //1'b0 1'b0 1'b0 STDOPDETTMODE[2:0] STDOPDETCMODE[1:0] 00011110
1743b63b36faSFred Richter   0x000A, //DAFTEN 1'b1 x x SCSYSLOCK
1744b63b36faSFred Richter   0x000B, //SCSYSLOCKCHKTIME[7:0] (10msec) 01100100
1745b63b36faSFred Richter   0x000D, //x SAMPLING4
1746b63b36faSFred Richter   0x000E, //SAMFREQ[15:8] 00000000
1747b63b36faSFred Richter   0x000F, //SAMFREQ[7:0] 00000000
1748b63b36faSFred Richter   0x0010, //IFFREQ[15:8] 01100000
1749b63b36faSFred Richter   0x0011, //IFFREQ[7:0] 00000000
1750b63b36faSFred Richter   0x0012, //AGCEN AGCREFMO
1751b63b36faSFred Richter   0x0013, //AGCRFFIXB AGCIFFIXB AGCLOCKDETRNGSEL[1:0] 1'b1 1'b0 1'b0 1'b0 11101000
1752b63b36faSFred Richter   0x0014, //AGCFIXVALUE[7:0] 01111111
1753b63b36faSFred Richter   0x0015, //AGCREF[15:8] 00001010
1754b63b36faSFred Richter   0x0016, //AGCREF[7:0] 11100100
1755b63b36faSFred Richter   0x0017, //AGCDELAY[7:0] 00100000
1756b63b36faSFred Richter   0x0018, //AGCRFBW[3:0] AGCIFBW[3:0] 10001000
1757b63b36faSFred Richter   0x0019, //AGCUDOUTMODE[1:0] AGCUDCTRLLEN[1:0] AGCUDCTRL
1758b63b36faSFred Richter   0x001C, //1'b1 PFEN MFEN AICCVSYNC
1759b63b36faSFred Richter   0x001D, //1'b0 1'b1 1'b0 1'b1 AICCVSYNC
1760b63b36faSFred Richter   0x001E, //AICCALPHA[3:0] 1'b1 1'b0 1'b1 1'b0 01111010
1761b63b36faSFred Richter   0x001F, //AICCDETTH[19:16] AICCOFFTH[19:16] 00000000
1762b63b36faSFred Richter   0x0020, //AICCDETTH[15:8] 01111100
1763b63b36faSFred Richter   0x0021, //AICCDETTH[7:0] 00000000
1764b63b36faSFred Richter   0x0022, //AICCOFFTH[15:8] 00000101
1765b63b36faSFred Richter   0x0023, //AICCOFFTH[7:0] 11100000
1766b63b36faSFred Richter   0x0024, //AICCOPMODE3[1:0] AICCOPMODE2[1:0] AICCOPMODE1[1:0] AICCOPMODE0[1:0] 00000000
1767b63b36faSFred Richter   0x0025, //AICCFIXFREQ3[23:16] 00000000
1768b63b36faSFred Richter   0x0026, //AICCFIXFREQ3[15:8] 00000000
1769b63b36faSFred Richter   0x0027, //AICCFIXFREQ3[7:0] 00000000
1770b63b36faSFred Richter   0x0028, //AICCFIXFREQ2[23:16] 00000000
1771b63b36faSFred Richter   0x0029, //AICCFIXFREQ2[15:8] 00000000
1772b63b36faSFred Richter   0x002A, //AICCFIXFREQ2[7:0] 00000000
1773b63b36faSFred Richter   0x002B, //AICCFIXFREQ1[23:16] 00000000
1774b63b36faSFred Richter   0x002C, //AICCFIXFREQ1[15:8] 00000000
1775b63b36faSFred Richter   0x002D, //AICCFIXFREQ1[7:0] 00000000
1776b63b36faSFred Richter   0x002E, //AICCFIXFREQ0[23:16] 00000000
1777b63b36faSFred Richter   0x002F, //AICCFIXFREQ0[15:8] 00000000
1778b63b36faSFred Richter   0x0030, //AICCFIXFREQ0[7:0] 00000000
1779b63b36faSFred Richter   0x0031, //1'b0 1'b1 1'b0 1'b0 x DAGC1STER
1780b63b36faSFred Richter   0x0032, //DAGC1STEN DAGC1STER
1781b63b36faSFred Richter   0x0033, //DAGC1STREF[15:8] 00001010
1782b63b36faSFred Richter   0x0034, //DAGC1STREF[7:0] 11100100
1783b63b36faSFred Richter   0x0035, //DAGC2NDE
1784b63b36faSFred Richter   0x0036, //DAGC2NDREF[15:8] 00001010
1785b63b36faSFred Richter   0x0037, //DAGC2NDREF[7:0] 10000000
1786b63b36faSFred Richter   0x0038, //DAGC2NDLOCKDETRNGSEL[1:0]
1787b63b36faSFred Richter   0x003D, //1'b1 SAMGEARS
1788b63b36faSFred Richter   0x0040, //SAMLFGMA
1789b63b36faSFred Richter   0x0041, //SAMLFBWM
1790b63b36faSFred Richter   0x0044, //1'b1 CRGEARSHE
1791b63b36faSFred Richter   0x0045, //CRLFGMAN
1792b63b36faSFred Richter   0x0046, //CFLFBWMA
1793b63b36faSFred Richter   0x0047, //CRLFGMAN
1794b63b36faSFred Richter   0x0048, //x x x x CRLFGSTEP_VS[3:0] xxxx1001
1795b63b36faSFred Richter   0x0049, //CRLFBWMA
1796b63b36faSFred Richter   0x004A, //CRLFBWMA
1797b63b36faSFred Richter   0x0050, //1'b0 1'b1 1'b1 1'b0 MSECALCDA
1798b63b36faSFred Richter   0x0070, //TPOUTEN TPIFEN TPCLKOUTE
1799b63b36faSFred Richter   0x0071, //TPSENB TPSSOPBITE
1800b63b36faSFred Richter   0x0073, //TP47HINS x x CHBERINT PERMODE[1:0] PERINT[1:0] 1xx11100
1801b63b36faSFred Richter   0x0075, //x x x x x IQSWAPCTRL[2:0] xxxxx000
1802b63b36faSFred Richter   0x0076, //NBERCON NBERST NBERPOL NBERWSYN
1803b63b36faSFred Richter   0x0077, //x NBERLOSTTH[2:0] NBERACQTH[3:0] x0000000
1804b63b36faSFred Richter   0x0078, //NBERPOLY[31:24] 00000000
1805b63b36faSFred Richter   0x0079, //NBERPOLY[23:16] 00000000
1806b63b36faSFred Richter   0x007A, //NBERPOLY[15:8] 00000000
1807b63b36faSFred Richter   0x007B, //NBERPOLY[7:0] 00000000
1808b63b36faSFred Richter   0x007C, //NBERPED[31:24] 00000000
1809b63b36faSFred Richter   0x007D, //NBERPED[23:16] 00000000
1810b63b36faSFred Richter   0x007E, //NBERPED[15:8] 00000000
1811b63b36faSFred Richter   0x007F, //NBERPED[7:0] 00000000
1812b63b36faSFred Richter   0x0080, //x AGCLOCK DAGCLOCK SYSLOCK x x NEVERLOCK[1:0]
1813b63b36faSFred Richter   0x0085, //SPECINVST
1814b63b36faSFred Richter   0x0088, //SYSLOCKTIME[15:8]
1815b63b36faSFred Richter   0x0089, //SYSLOCKTIME[7:0]
1816b63b36faSFred Richter   0x008C, //FECLOCKTIME[15:8]
1817b63b36faSFred Richter   0x008D, //FECLOCKTIME[7:0]
1818b63b36faSFred Richter   0x008E, //AGCACCOUT[15:8]
1819b63b36faSFred Richter   0x008F, //AGCACCOUT[7:0]
1820b63b36faSFred Richter   0x0090, //AICCREJSTATUS[3:0] AICCREJBUSY[3:0]
1821b63b36faSFred Richter   0x0091, //AICCVSYNC
1822b63b36faSFred Richter   0x009C, //CARRFREQOFFSET[15:8]
1823b63b36faSFred Richter   0x009D, //CARRFREQOFFSET[7:0]
1824b63b36faSFred Richter   0x00A1, //SAMFREQOFFSET[23:16]
1825b63b36faSFred Richter   0x00A2, //SAMFREQOFFSET[15:8]
1826b63b36faSFred Richter   0x00A3, //SAMFREQOFFSET[7:0]
1827b63b36faSFred Richter   0x00A6, //SYNCLOCK SYNCLOCKH
1828b63b36faSFred Richter #if 0//covered elsewhere
1829b63b36faSFred Richter   0x00E8, //CONSTPWR[15:8]
1830b63b36faSFred Richter   0x00E9, //CONSTPWR[7:0]
1831b63b36faSFred Richter   0x00EA, //BMSE[15:8]
1832b63b36faSFred Richter   0x00EB, //BMSE[7:0]
1833b63b36faSFred Richter   0x00EC, //MSE[15:8]
1834b63b36faSFred Richter   0x00ED, //MSE[7:0]
1835b63b36faSFred Richter   0x00EE, //CONSTI[7:0]
1836b63b36faSFred Richter   0x00EF, //CONSTQ[7:0]
1837b63b36faSFred Richter #endif
1838b63b36faSFred Richter   0x00F4, //TPIFTPERRCNT[7:0]
1839b63b36faSFred Richter   0x00F5, //TPCORREC
1840b63b36faSFred Richter   0x00F6, //VBBER[15:8]
1841b63b36faSFred Richter   0x00F7, //VBBER[7:0]
1842b63b36faSFred Richter   0x00F8, //VABER[15:8]
1843b63b36faSFred Richter   0x00F9, //VABER[7:0]
1844b63b36faSFred Richter   0x00FA, //TPERRCNT[7:0]
1845b63b36faSFred Richter   0x00FB, //NBERLOCK x x x x x x x
1846b63b36faSFred Richter   0x00FC, //NBERVALUE[31:24]
1847b63b36faSFred Richter   0x00FD, //NBERVALUE[23:16]
1848b63b36faSFred Richter   0x00FE, //NBERVALUE[15:8]
1849b63b36faSFred Richter   0x00FF, //NBERVALUE[7:0]
1850b63b36faSFred Richter   0x1000, //1'b0 WODAGCOU
1851b63b36faSFred Richter   0x1005, //x x 1'b1 1'b1 x SRD_Q_QM
1852b63b36faSFred Richter   0x1009, //SRDWAITTIME[7:0] (10msec) 00100011
1853b63b36faSFred Richter   0x100A, //SRDWAITTIME_CQS[7:0] (msec) 01100100
1854b63b36faSFred Richter   0x101A, //x 1'b1 1'b0 1'b0 x QMDQAMMODE[2:0] x100x010
1855b63b36faSFred Richter   0x1036, //1'b0 1'b1 1'b0 1'b0 SAMGSEND_CQS[3:0] 01001110
1856b63b36faSFred Richter   0x103C, //SAMGSAUTOSTL_V[3:0] SAMGSAUTOEDL_V[3:0] 01000110
1857b63b36faSFred Richter   0x103D, //1'b1 1'b1 SAMCNORMBP_V[1:0] 1'b0 1'b0 SAMMODESEL_V[1:0] 11100001
1858b63b36faSFred Richter   0x103F, //SAMZTEDSE
1859b63b36faSFred Richter   0x105D, //EQSTATUSE
1860b63b36faSFred Richter   0x105F, //x PMAPG2_V[2:0] x DMAPG2_V[2:0] x001x011
1861b63b36faSFred Richter   0x1060, //1'b1 EQSTATUSE
1862b63b36faSFred Richter   0x1061, //CRMAPBWSTL_V[3:0] CRMAPBWEDL_V[3:0] 00000100
1863b63b36faSFred Richter   0x1065, //1'b0 x CRMODE_V[1:0] 1'b1 x 1'b1 x 0x111x1x
1864b63b36faSFred Richter   0x1066, //1'b0 1'b0 1'b1 1'b0 1'b1 PNBOOSTSE
1865b63b36faSFred Richter   0x1068, //CREPHNGAIN2_V[3:0] CREPHNPBW_V[3:0] 10010001
1866b63b36faSFred Richter   0x106E, //x x x x x CREPHNEN_
1867b63b36faSFred Richter   0x106F, //CREPHNTH_V[7:0] 00010101
1868b63b36faSFred Richter   0x1072, //CRSWEEPN
1869b63b36faSFred Richter   0x1073, //CRPGAIN_V[3:0] x x 1'b1 1'b1 1001xx11
1870b63b36faSFred Richter   0x1074, //CRPBW_V[3:0] x x 1'b1 1'b1 0001xx11
1871b63b36faSFred Richter   0x1080, //DAFTSTATUS[1:0] x x x x x x
1872b63b36faSFred Richter   0x1081, //SRDSTATUS[1:0] x x x x x SRDLOCK
1873b63b36faSFred Richter   0x10A9, //EQSTATUS_CQS[1:0] x x x x x x
1874b63b36faSFred Richter   0x10B7, //EQSTATUS_V[1:0] x x x x x x
1875b63b36faSFred Richter #if 0//SMART_ANT
1876b63b36faSFred Richter   0x1F00, //MODEDETE
1877b63b36faSFred Richter   0x1F01, //x x x x x x x SFNRST xxxxxxx0
1878b63b36faSFred Richter   0x1F03, //NUMOFANT[7:0] 10000000
1879b63b36faSFred Richter   0x1F04, //x SELMASK[6:0] x0000000
1880b63b36faSFred Richter   0x1F05, //x SETMASK[6:0] x0000000
1881b63b36faSFred Richter   0x1F06, //x TXDATA[6:0] x0000000
1882b63b36faSFred Richter   0x1F07, //x CHNUMBER[6:0] x0000000
1883b63b36faSFred Richter   0x1F09, //AGCTIME[23:16] 10011000
1884b63b36faSFred Richter   0x1F0A, //AGCTIME[15:8] 10010110
1885b63b36faSFred Richter   0x1F0B, //AGCTIME[7:0] 10000000
1886b63b36faSFred Richter   0x1F0C, //ANTTIME[31:24] 00000000
1887b63b36faSFred Richter   0x1F0D, //ANTTIME[23:16] 00000011
1888b63b36faSFred Richter   0x1F0E, //ANTTIME[15:8] 10010000
1889b63b36faSFred Richter   0x1F0F, //ANTTIME[7:0] 10010000
1890b63b36faSFred Richter   0x1F11, //SYNCTIME[23:16] 10011000
1891b63b36faSFred Richter   0x1F12, //SYNCTIME[15:8] 10010110
1892b63b36faSFred Richter   0x1F13, //SYNCTIME[7:0] 10000000
1893b63b36faSFred Richter   0x1F14, //SNRTIME[31:24] 00000001
1894b63b36faSFred Richter   0x1F15, //SNRTIME[23:16] 01111101
1895b63b36faSFred Richter   0x1F16, //SNRTIME[15:8] 01111000
1896b63b36faSFred Richter   0x1F17, //SNRTIME[7:0] 01000000
1897b63b36faSFred Richter   0x1F19, //FECTIME[23:16] 00000000
1898b63b36faSFred Richter   0x1F1A, //FECTIME[15:8] 01110010
1899b63b36faSFred Richter   0x1F1B, //FECTIME[7:0] 01110000
1900b63b36faSFred Richter   0x1F1D, //FECTHD[7:0] 00000011
1901b63b36faSFred Richter   0x1F1F, //SNRTHD[23:16] 00001000
1902b63b36faSFred Richter   0x1F20, //SNRTHD[15:8] 01111111
1903b63b36faSFred Richter   0x1F21, //SNRTHD[7:0] 10000101
1904b63b36faSFred Richter   0x1F80, //IRQFLG x x SFSDRFLG MODEBFLG SAVEFLG SCANFLG TRACKFLG
1905b63b36faSFred Richter   0x1F81, //x SYNCCON SNRCON FECCON x STDBUSY SYNCRST AGCFZCO
1906b63b36faSFred Richter   0x1F82, //x x x SCANOPCD[4:0]
1907b63b36faSFred Richter   0x1F83, //x x x x MAINOPCD[3:0]
1908b63b36faSFred Richter   0x1F84, //x x RXDATA[13:8]
1909b63b36faSFred Richter   0x1F85, //RXDATA[7:0]
1910b63b36faSFred Richter   0x1F86, //x x SDTDATA[13:8]
1911b63b36faSFred Richter   0x1F87, //SDTDATA[7:0]
1912b63b36faSFred Richter   0x1F89, //ANTSNR[23:16]
1913b63b36faSFred Richter   0x1F8A, //ANTSNR[15:8]
1914b63b36faSFred Richter   0x1F8B, //ANTSNR[7:0]
1915b63b36faSFred Richter   0x1F8C, //x x x x ANTFEC[13:8]
1916b63b36faSFred Richter   0x1F8D, //ANTFEC[7:0]
1917b63b36faSFred Richter   0x1F8E, //MAXCNT[7:0]
1918b63b36faSFred Richter   0x1F8F, //SCANCNT[7:0]
1919b63b36faSFred Richter   0x1F91, //MAXPW[23:16]
1920b63b36faSFred Richter   0x1F92, //MAXPW[15:8]
1921b63b36faSFred Richter   0x1F93, //MAXPW[7:0]
1922b63b36faSFred Richter   0x1F95, //CURPWMSE[23:16]
1923b63b36faSFred Richter   0x1F96, //CURPWMSE[15:8]
1924b63b36faSFred Richter   0x1F97, //CURPWMSE[7:0]
1925b63b36faSFred Richter #endif//SMART_ANT
1926b63b36faSFred Richter   0x211F, //1'b1 1'b1 1'b1 CIRQEN x x 1'b0 1'b0 1111xx00
1927b63b36faSFred Richter   0x212A, //EQAUTOST
1928b63b36faSFred Richter   0x2122, //CHFAST[7:0] 01100000
1929b63b36faSFred Richter   0x212B, //FFFSTEP_V[3:0] x FBFSTEP_V[2:0] 0001x001
1930b63b36faSFred Richter   0x212C, //PHDEROTBWSEL[3:0] 1'b1 1'b1 1'b1 1'b0 10001110
1931b63b36faSFred Richter   0x212D, //1'b1 1'b1 1'b1 1'b1 x x TPIFLOCKS
1932b63b36faSFred Richter   0x2135, //DYNTRACKFDEQ[3:0] x 1'b0 1'b0 1'b0 1010x000
1933b63b36faSFred Richter   0x2141, //TRMODE[1:0] 1'b1 1'b1 1'b0 1'b1 1'b1 1'b1 01110111
1934b63b36faSFred Richter   0x2162, //AICCCTRLE
1935b63b36faSFred Richter   0x2173, //PHNCNFCNT[7:0] 00000100
1936b63b36faSFred Richter   0x2179, //1'b0 1'b0 1'b0 1'b1 x BADSINGLEDYNTRACKFBF[2:0] 0001x001
1937b63b36faSFred Richter   0x217A, //1'b0 1'b0 1'b0 1'b1 x BADSLOWSINGLEDYNTRACKFBF[2:0] 0001x001
1938b63b36faSFred Richter   0x217E, //CNFCNTTPIF[7:0] 00001000
1939b63b36faSFred Richter   0x217F, //TPERRCNTTPIF[7:0] 00000001
1940b63b36faSFred Richter   0x2180, //x x x x x x FBDLYCIR[9:8]
1941b63b36faSFred Richter   0x2181, //FBDLYCIR[7:0]
1942b63b36faSFred Richter   0x2185, //MAXPWRMAIN[7:0]
1943b63b36faSFred Richter   0x2191, //NCOMBDET x x x x x x x
1944b63b36faSFred Richter   0x2199, //x MAINSTRON
1945b63b36faSFred Richter   0x219A, //FFFEQSTEPOUT_V[3:0] FBFSTEPOUT_V[2:0]
1946b63b36faSFred Richter   0x21A1, //x x SNRREF[5:0]
1947b63b36faSFred Richter   0x2845, //1'b0 1'b1 x x FFFSTEP_CQS[1:0] FFFCENTERTAP[1:0] 01xx1110
1948b63b36faSFred Richter   0x2846, //1'b0 x 1'b0 1'b1 FBFSTEP_CQS[1:0] 1'b1 1'b0 0x011110
1949b63b36faSFred Richter   0x2847, //ENNOSIGDE
1950b63b36faSFred Richter   0x2849, //1'b1 1'b1 NOUSENOSI
1951b63b36faSFred Richter   0x284A, //EQINITWAITTIME[7:0] 01100100
1952b63b36faSFred Richter   0x3000, //1'b1 1'b1 1'b1 x x x 1'b0 RPTRSTM
1953b63b36faSFred Richter   0x3001, //RPTRSTWAITTIME[7:0] (100msec) 00110010
1954b63b36faSFred Richter   0x3031, //FRAMELOC
1955b63b36faSFred Richter   0x3032, //1'b1 1'b0 1'b0 1'b0 x x FRAMELOCKMODE_CQS[1:0] 1000xx11
1956b63b36faSFred Richter   0x30A9, //VDLOCK_Q FRAMELOCK
1957b63b36faSFred Richter   0x30AA, //MPEGLOCK
1958b63b36faSFred Richter };
1959b63b36faSFred Richter 
1960b63b36faSFred Richter #define numDumpRegs  (sizeof(regtab)/sizeof(regtab[0]))
1961b63b36faSFred Richter static u8 regval1[numDumpRegs] = {0, };
1962b63b36faSFred Richter static u8 regval2[numDumpRegs] = {0, };
1963b63b36faSFred Richter 
1964b63b36faSFred Richter static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state)
1965b63b36faSFred Richter {
1966b63b36faSFred Richter 		memset(regval2, 0xff, sizeof(regval2));
1967b63b36faSFred Richter 		lgdt3306a_DumpRegs(state);
1968b63b36faSFred Richter }
1969b63b36faSFred Richter 
1970b63b36faSFred Richter static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state)
1971b63b36faSFred Richter {
1972b63b36faSFred Richter 	int i;
1973b63b36faSFred Richter 	int sav_debug = debug;
1974*8e8cd34eSMichael Ira Krufky 
1975b63b36faSFred Richter 	if ((debug & DBG_DUMP) == 0)
1976b63b36faSFred Richter 		return;
1977*8e8cd34eSMichael Ira Krufky 	debug &= ~DBG_REG; /* supress DBG_REG during reg dump */
1978b63b36faSFred Richter 
1979b63b36faSFred Richter 	lg_info("\n");
1980b63b36faSFred Richter 
1981b63b36faSFred Richter 	for (i = 0; i < numDumpRegs; i++) {
1982b63b36faSFred Richter 		lgdt3306a_read_reg(state, regtab[i], &regval1[i]);
1983b63b36faSFred Richter 		if (regval1[i] != regval2[i]) {
1984b63b36faSFred Richter 			lg_info(" %04X = %02X\n", regtab[i], regval1[i]);
1985b63b36faSFred Richter 				regval2[i] = regval1[i];
1986b63b36faSFred Richter 		}
1987b63b36faSFred Richter 	}
1988b63b36faSFred Richter 	debug = sav_debug;
1989b63b36faSFred Richter }
1990*8e8cd34eSMichael Ira Krufky #endif /* DBG_DUMP */
1991b63b36faSFred Richter 
1992b63b36faSFred Richter 
1993b63b36faSFred Richter 
1994b63b36faSFred Richter EXPORT_SYMBOL(lgdt3306a_attach);
1995b63b36faSFred Richter 
1996b63b36faSFred Richter static struct dvb_frontend_ops lgdt3306a_ops = {
1997b63b36faSFred Richter 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
1998b63b36faSFred Richter 	.info = {
1999b63b36faSFred Richter 		.name = "LG Electronics LGDT3306A VSB/QAM Frontend",
2000*8e8cd34eSMichael Ira Krufky #if 0
2001*8e8cd34eSMichael Ira Krufky 		.type               = FE_ATSC,
2002*8e8cd34eSMichael Ira Krufky #endif
2003b63b36faSFred Richter 		.frequency_min      = 54000000,
2004*8e8cd34eSMichael Ira Krufky 		.frequency_max      = 858000000,
2005b63b36faSFred Richter 		.frequency_stepsize = 62500,
2006b63b36faSFred Richter 		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
2007b63b36faSFred Richter 	},
2008b63b36faSFred Richter 	.i2c_gate_ctrl        = lgdt3306a_i2c_gate_ctrl,
2009b63b36faSFred Richter 	.init                 = lgdt3306a_init,
2010b63b36faSFred Richter 	.sleep                = lgdt3306a_fe_sleep,
2011b63b36faSFred Richter 	/* if this is set, it overrides the default swzigzag */
2012b63b36faSFred Richter 	.tune                 = lgdt3306a_tune,
2013b63b36faSFred Richter 	.set_frontend         = lgdt3306a_set_parameters,
2014b63b36faSFred Richter 	.get_frontend         = lgdt3306a_get_frontend,
2015b63b36faSFred Richter 	.get_frontend_algo    = lgdt3306a_get_frontend_algo,
2016b63b36faSFred Richter 	.get_tune_settings    = lgdt3306a_get_tune_settings,
2017b63b36faSFred Richter 	.read_status          = lgdt3306a_read_status,
2018b63b36faSFred Richter 	.read_ber             = lgdt3306a_read_ber,
2019b63b36faSFred Richter 	.read_signal_strength = lgdt3306a_read_signal_strength,
2020b63b36faSFred Richter 	.read_snr             = lgdt3306a_read_snr,
2021b63b36faSFred Richter 	.read_ucblocks        = lgdt3306a_read_ucblocks,
2022b63b36faSFred Richter 	.release              = lgdt3306a_release,
2023b63b36faSFred Richter 	.ts_bus_ctrl          = lgdt3306a_ts_bus_ctrl,
2024b63b36faSFred Richter 	.search               = lgdt3306a_search,
2025b63b36faSFred Richter };
2026b63b36faSFred Richter 
2027b63b36faSFred Richter MODULE_DESCRIPTION("LG Electronics LGDT3306A ATSC/QAM-B Demodulator Driver");
2028b63b36faSFred Richter MODULE_AUTHOR("Fred Richter <frichter@hauppauge.com>");
2029b63b36faSFred Richter MODULE_LICENSE("GPL");
2030b63b36faSFred Richter MODULE_VERSION("0.2");
2031b63b36faSFred Richter 
2032b63b36faSFred Richter /*
2033b63b36faSFred Richter  * Local variables:
2034b63b36faSFred Richter  * c-basic-offset: 8
2035b63b36faSFred Richter  * End:
2036b63b36faSFred Richter  */
2037