xref: /linux/drivers/media/dvb-frontends/lg2160.c (revision 4f6b838c378a52ea3ae0b15f12ca8a20849072fa)
1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2e26f2ae4SMichael Krufky /*
3e26f2ae4SMichael Krufky  *    Support for LG2160 - ATSC/MH
4e26f2ae4SMichael Krufky  *
5e26f2ae4SMichael Krufky  *    Copyright (C) 2010 Michael Krufky <mkrufky@linuxtv.org>
6e26f2ae4SMichael Krufky  */
7e26f2ae4SMichael Krufky 
8e26f2ae4SMichael Krufky #include <linux/jiffies.h>
9e26f2ae4SMichael Krufky #include <linux/dvb/frontend.h>
10e26f2ae4SMichael Krufky #include "lg2160.h"
11e26f2ae4SMichael Krufky 
12e26f2ae4SMichael Krufky static int debug;
13e26f2ae4SMichael Krufky module_param(debug, int, 0644);
14e26f2ae4SMichael Krufky MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))");
15e26f2ae4SMichael Krufky 
16e26f2ae4SMichael Krufky #define DBG_INFO 1
17e26f2ae4SMichael Krufky #define DBG_REG  2
18e26f2ae4SMichael Krufky 
19e26f2ae4SMichael Krufky #define lg_printk(kern, fmt, arg...)					\
20e26f2ae4SMichael Krufky 	printk(kern "%s: " fmt, __func__, ##arg)
21e26f2ae4SMichael Krufky 
22e26f2ae4SMichael Krufky #define lg_info(fmt, arg...)	printk(KERN_INFO "lg2160: " fmt, ##arg)
23e26f2ae4SMichael Krufky #define lg_warn(fmt, arg...)	lg_printk(KERN_WARNING,       fmt, ##arg)
24e26f2ae4SMichael Krufky #define lg_err(fmt, arg...)	lg_printk(KERN_ERR,           fmt, ##arg)
25e26f2ae4SMichael Krufky #define lg_dbg(fmt, arg...) if (debug & DBG_INFO)			\
26e26f2ae4SMichael Krufky 				lg_printk(KERN_DEBUG,         fmt, ##arg)
27e26f2ae4SMichael Krufky #define lg_reg(fmt, arg...) if (debug & DBG_REG)			\
28e26f2ae4SMichael Krufky 				lg_printk(KERN_DEBUG,         fmt, ##arg)
29e26f2ae4SMichael Krufky 
30e26f2ae4SMichael Krufky #define lg_fail(ret)							\
31e26f2ae4SMichael Krufky ({									\
32e26f2ae4SMichael Krufky 	int __ret;							\
33e26f2ae4SMichael Krufky 	__ret = (ret < 0);						\
34e26f2ae4SMichael Krufky 	if (__ret)							\
35e26f2ae4SMichael Krufky 		lg_err("error %d on line %d\n",	ret, __LINE__);		\
36e26f2ae4SMichael Krufky 	__ret;								\
37e26f2ae4SMichael Krufky })
38e26f2ae4SMichael Krufky 
39e26f2ae4SMichael Krufky struct lg216x_state {
40e26f2ae4SMichael Krufky 	struct i2c_adapter *i2c_adap;
41e26f2ae4SMichael Krufky 	const struct lg2160_config *cfg;
42e26f2ae4SMichael Krufky 
43e26f2ae4SMichael Krufky 	struct dvb_frontend frontend;
44e26f2ae4SMichael Krufky 
45e26f2ae4SMichael Krufky 	u32 current_frequency;
46e26f2ae4SMichael Krufky 	u8 parade_id;
47e26f2ae4SMichael Krufky 	u8 fic_ver;
48e26f2ae4SMichael Krufky 	unsigned int last_reset;
49e26f2ae4SMichael Krufky };
50e26f2ae4SMichael Krufky 
51e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */
52e26f2ae4SMichael Krufky 
53e26f2ae4SMichael Krufky static int lg216x_write_reg(struct lg216x_state *state, u16 reg, u8 val)
54e26f2ae4SMichael Krufky {
55e26f2ae4SMichael Krufky 	int ret;
56e26f2ae4SMichael Krufky 	u8 buf[] = { reg >> 8, reg & 0xff, val };
57e26f2ae4SMichael Krufky 	struct i2c_msg msg = {
58e26f2ae4SMichael Krufky 		.addr = state->cfg->i2c_addr, .flags = 0,
59e26f2ae4SMichael Krufky 		.buf = buf, .len = 3,
60e26f2ae4SMichael Krufky 	};
61e26f2ae4SMichael Krufky 
62e26f2ae4SMichael Krufky 	lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);
63e26f2ae4SMichael Krufky 
64e26f2ae4SMichael Krufky 	ret = i2c_transfer(state->i2c_adap, &msg, 1);
65e26f2ae4SMichael Krufky 
66e26f2ae4SMichael Krufky 	if (ret != 1) {
67e26f2ae4SMichael Krufky 		lg_err("error (addr %02x %02x <- %02x, err = %i)\n",
68e26f2ae4SMichael Krufky 		       msg.buf[0], msg.buf[1], msg.buf[2], ret);
69e26f2ae4SMichael Krufky 		if (ret < 0)
70e26f2ae4SMichael Krufky 			return ret;
71e26f2ae4SMichael Krufky 		else
72e26f2ae4SMichael Krufky 			return -EREMOTEIO;
73e26f2ae4SMichael Krufky 	}
74e26f2ae4SMichael Krufky 	return 0;
75e26f2ae4SMichael Krufky }
76e26f2ae4SMichael Krufky 
77e26f2ae4SMichael Krufky static int lg216x_read_reg(struct lg216x_state *state, u16 reg, u8 *val)
78e26f2ae4SMichael Krufky {
79e26f2ae4SMichael Krufky 	int ret;
80e26f2ae4SMichael Krufky 	u8 reg_buf[] = { reg >> 8, reg & 0xff };
81e26f2ae4SMichael Krufky 	struct i2c_msg msg[] = {
82e26f2ae4SMichael Krufky 		{ .addr = state->cfg->i2c_addr,
83e26f2ae4SMichael Krufky 		  .flags = 0, .buf = reg_buf, .len = 2 },
84e26f2ae4SMichael Krufky 		{ .addr = state->cfg->i2c_addr,
85e26f2ae4SMichael Krufky 		  .flags = I2C_M_RD, .buf = val, .len = 1 },
86e26f2ae4SMichael Krufky 	};
87e26f2ae4SMichael Krufky 
88e26f2ae4SMichael Krufky 	lg_reg("reg: 0x%04x\n", reg);
89e26f2ae4SMichael Krufky 
90e26f2ae4SMichael Krufky 	ret = i2c_transfer(state->i2c_adap, msg, 2);
91e26f2ae4SMichael Krufky 
92e26f2ae4SMichael Krufky 	if (ret != 2) {
93e26f2ae4SMichael Krufky 		lg_err("error (addr %02x reg %04x error (ret == %i)\n",
94e26f2ae4SMichael Krufky 		       state->cfg->i2c_addr, reg, ret);
95e26f2ae4SMichael Krufky 		if (ret < 0)
96e26f2ae4SMichael Krufky 			return ret;
97e26f2ae4SMichael Krufky 		else
98e26f2ae4SMichael Krufky 			return -EREMOTEIO;
99e26f2ae4SMichael Krufky 	}
100e26f2ae4SMichael Krufky 	return 0;
101e26f2ae4SMichael Krufky }
102e26f2ae4SMichael Krufky 
103e26f2ae4SMichael Krufky struct lg216x_reg {
104e26f2ae4SMichael Krufky 	u16 reg;
105e26f2ae4SMichael Krufky 	u8 val;
106e26f2ae4SMichael Krufky };
107e26f2ae4SMichael Krufky 
108e26f2ae4SMichael Krufky static int lg216x_write_regs(struct lg216x_state *state,
109e26f2ae4SMichael Krufky 			     struct lg216x_reg *regs, int len)
110e26f2ae4SMichael Krufky {
111e26f2ae4SMichael Krufky 	int i, ret;
112e26f2ae4SMichael Krufky 
113e26f2ae4SMichael Krufky 	lg_reg("writing %d registers...\n", len);
114e26f2ae4SMichael Krufky 
115bffaecc7SMichael Krufky 	for (i = 0; i < len; i++) {
116e26f2ae4SMichael Krufky 		ret = lg216x_write_reg(state, regs[i].reg, regs[i].val);
117e26f2ae4SMichael Krufky 		if (lg_fail(ret))
118e26f2ae4SMichael Krufky 			return ret;
119e26f2ae4SMichael Krufky 	}
120e26f2ae4SMichael Krufky 	return 0;
121e26f2ae4SMichael Krufky }
122e26f2ae4SMichael Krufky 
123e26f2ae4SMichael Krufky static int lg216x_set_reg_bit(struct lg216x_state *state,
124e26f2ae4SMichael Krufky 			      u16 reg, int bit, int onoff)
125e26f2ae4SMichael Krufky {
126e26f2ae4SMichael Krufky 	u8 val;
127e26f2ae4SMichael Krufky 	int ret;
128e26f2ae4SMichael Krufky 
129e26f2ae4SMichael Krufky 	lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff);
130e26f2ae4SMichael Krufky 
131e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, reg, &val);
132e26f2ae4SMichael Krufky 	if (lg_fail(ret))
133e26f2ae4SMichael Krufky 		goto fail;
134e26f2ae4SMichael Krufky 
135e26f2ae4SMichael Krufky 	val &= ~(1 << bit);
136e26f2ae4SMichael Krufky 	val |= (onoff & 1) << bit;
137e26f2ae4SMichael Krufky 
138e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, reg, val);
139e26f2ae4SMichael Krufky 	lg_fail(ret);
140e26f2ae4SMichael Krufky fail:
141e26f2ae4SMichael Krufky 	return ret;
142e26f2ae4SMichael Krufky }
143e26f2ae4SMichael Krufky 
144e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */
145e26f2ae4SMichael Krufky 
146e26f2ae4SMichael Krufky static int lg216x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
147e26f2ae4SMichael Krufky {
148e26f2ae4SMichael Krufky 	struct lg216x_state *state = fe->demodulator_priv;
149e26f2ae4SMichael Krufky 	int ret;
150e26f2ae4SMichael Krufky 
151e26f2ae4SMichael Krufky 	if (state->cfg->deny_i2c_rptr)
152e26f2ae4SMichael Krufky 		return 0;
153e26f2ae4SMichael Krufky 
154e26f2ae4SMichael Krufky 	lg_dbg("(%d)\n", enable);
155e26f2ae4SMichael Krufky 
156e26f2ae4SMichael Krufky 	ret = lg216x_set_reg_bit(state, 0x0000, 0, enable ? 0 : 1);
157e26f2ae4SMichael Krufky 
158e26f2ae4SMichael Krufky 	msleep(1);
159e26f2ae4SMichael Krufky 
160e26f2ae4SMichael Krufky 	return ret;
161e26f2ae4SMichael Krufky }
162e26f2ae4SMichael Krufky 
163e26f2ae4SMichael Krufky static int lg216x_soft_reset(struct lg216x_state *state)
164e26f2ae4SMichael Krufky {
165e26f2ae4SMichael Krufky 	int ret;
166e26f2ae4SMichael Krufky 
167e26f2ae4SMichael Krufky 	lg_dbg("\n");
168e26f2ae4SMichael Krufky 
169e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x0002, 0x00);
170e26f2ae4SMichael Krufky 	if (lg_fail(ret))
171e26f2ae4SMichael Krufky 		goto fail;
172e26f2ae4SMichael Krufky 
173e26f2ae4SMichael Krufky 	msleep(20);
174e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x0002, 0x01);
175e26f2ae4SMichael Krufky 	if (lg_fail(ret))
176e26f2ae4SMichael Krufky 		goto fail;
177e26f2ae4SMichael Krufky 
178e26f2ae4SMichael Krufky 	state->last_reset = jiffies_to_msecs(jiffies);
179e26f2ae4SMichael Krufky fail:
180e26f2ae4SMichael Krufky 	return ret;
181e26f2ae4SMichael Krufky }
182e26f2ae4SMichael Krufky 
183e26f2ae4SMichael Krufky static int lg216x_initialize(struct lg216x_state *state)
184e26f2ae4SMichael Krufky {
185e26f2ae4SMichael Krufky 	int ret;
186e26f2ae4SMichael Krufky 
187e26f2ae4SMichael Krufky 	static struct lg216x_reg lg2160_init[] = {
188e26f2ae4SMichael Krufky #if 0
189e26f2ae4SMichael Krufky 		{ .reg = 0x0015, .val = 0xe6 },
190e26f2ae4SMichael Krufky #else
191e26f2ae4SMichael Krufky 		{ .reg = 0x0015, .val = 0xf7 },
192e26f2ae4SMichael Krufky 		{ .reg = 0x001b, .val = 0x52 },
193e26f2ae4SMichael Krufky 		{ .reg = 0x0208, .val = 0x00 },
194e26f2ae4SMichael Krufky 		{ .reg = 0x0209, .val = 0x82 },
195e26f2ae4SMichael Krufky 		{ .reg = 0x0210, .val = 0xf9 },
196e26f2ae4SMichael Krufky 		{ .reg = 0x020a, .val = 0x00 },
197e26f2ae4SMichael Krufky 		{ .reg = 0x020b, .val = 0x82 },
198e26f2ae4SMichael Krufky 		{ .reg = 0x020d, .val = 0x28 },
199e26f2ae4SMichael Krufky 		{ .reg = 0x020f, .val = 0x14 },
200e26f2ae4SMichael Krufky #endif
201e26f2ae4SMichael Krufky 	};
202e26f2ae4SMichael Krufky 
203e26f2ae4SMichael Krufky 	static struct lg216x_reg lg2161_init[] = {
204e26f2ae4SMichael Krufky 		{ .reg = 0x0000, .val = 0x41 },
205e26f2ae4SMichael Krufky 		{ .reg = 0x0001, .val = 0xfb },
206e26f2ae4SMichael Krufky 		{ .reg = 0x0216, .val = 0x00 },
207e26f2ae4SMichael Krufky 		{ .reg = 0x0219, .val = 0x00 },
208e26f2ae4SMichael Krufky 		{ .reg = 0x021b, .val = 0x55 },
209e26f2ae4SMichael Krufky 		{ .reg = 0x0606, .val = 0x0a },
210e26f2ae4SMichael Krufky 	};
211e26f2ae4SMichael Krufky 
212e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
213e26f2ae4SMichael Krufky 	case LG2160:
214e26f2ae4SMichael Krufky 		ret = lg216x_write_regs(state,
215e26f2ae4SMichael Krufky 					lg2160_init, ARRAY_SIZE(lg2160_init));
216e26f2ae4SMichael Krufky 		break;
217e26f2ae4SMichael Krufky 	case LG2161:
218e26f2ae4SMichael Krufky 		ret = lg216x_write_regs(state,
219e26f2ae4SMichael Krufky 					lg2161_init, ARRAY_SIZE(lg2161_init));
220e26f2ae4SMichael Krufky 		break;
221e26f2ae4SMichael Krufky 	default:
222e26f2ae4SMichael Krufky 		ret = -EINVAL;
223e26f2ae4SMichael Krufky 		break;
224e26f2ae4SMichael Krufky 	}
225e26f2ae4SMichael Krufky 	if (lg_fail(ret))
226e26f2ae4SMichael Krufky 		goto fail;
227e26f2ae4SMichael Krufky 
228e26f2ae4SMichael Krufky 	ret = lg216x_soft_reset(state);
229e26f2ae4SMichael Krufky 	lg_fail(ret);
230e26f2ae4SMichael Krufky fail:
231e26f2ae4SMichael Krufky 	return ret;
232e26f2ae4SMichael Krufky }
233e26f2ae4SMichael Krufky 
234e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */
235e26f2ae4SMichael Krufky 
236e26f2ae4SMichael Krufky static int lg216x_set_if(struct lg216x_state *state)
237e26f2ae4SMichael Krufky {
238e26f2ae4SMichael Krufky 	u8 val;
239e26f2ae4SMichael Krufky 	int ret;
240e26f2ae4SMichael Krufky 
241e26f2ae4SMichael Krufky 	lg_dbg("%d KHz\n", state->cfg->if_khz);
242e26f2ae4SMichael Krufky 
243e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0132, &val);
244e26f2ae4SMichael Krufky 	if (lg_fail(ret))
245e26f2ae4SMichael Krufky 		goto fail;
246e26f2ae4SMichael Krufky 
247e26f2ae4SMichael Krufky 	val &= 0xfb;
248e26f2ae4SMichael Krufky 	val |= (0 == state->cfg->if_khz) ? 0x04 : 0x00;
249e26f2ae4SMichael Krufky 
250e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x0132, val);
251e26f2ae4SMichael Krufky 	lg_fail(ret);
252e26f2ae4SMichael Krufky 
253e26f2ae4SMichael Krufky 	/* if NOT zero IF, 6 MHz is the default */
254e26f2ae4SMichael Krufky fail:
255e26f2ae4SMichael Krufky 	return ret;
256e26f2ae4SMichael Krufky }
257e26f2ae4SMichael Krufky 
258e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */
259e26f2ae4SMichael Krufky 
260e26f2ae4SMichael Krufky static int lg2160_agc_fix(struct lg216x_state *state,
261e26f2ae4SMichael Krufky 			  int if_agc_fix, int rf_agc_fix)
262e26f2ae4SMichael Krufky {
263e26f2ae4SMichael Krufky 	u8 val;
264e26f2ae4SMichael Krufky 	int ret;
265e26f2ae4SMichael Krufky 
266e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0100, &val);
267e26f2ae4SMichael Krufky 	if (lg_fail(ret))
268e26f2ae4SMichael Krufky 		goto fail;
269e26f2ae4SMichael Krufky 
270e26f2ae4SMichael Krufky 	val &= 0xf3;
271e26f2ae4SMichael Krufky 	val |= (if_agc_fix) ? 0x08 : 0x00;
272e26f2ae4SMichael Krufky 	val |= (rf_agc_fix) ? 0x04 : 0x00;
273e26f2ae4SMichael Krufky 
274e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x0100, val);
275e26f2ae4SMichael Krufky 	lg_fail(ret);
276e26f2ae4SMichael Krufky fail:
277e26f2ae4SMichael Krufky 	return ret;
278e26f2ae4SMichael Krufky }
279e26f2ae4SMichael Krufky 
280e26f2ae4SMichael Krufky #if 0
281e26f2ae4SMichael Krufky static int lg2160_agc_freeze(struct lg216x_state *state,
282e26f2ae4SMichael Krufky 			     int if_agc_freeze, int rf_agc_freeze)
283e26f2ae4SMichael Krufky {
284e26f2ae4SMichael Krufky 	u8 val;
285e26f2ae4SMichael Krufky 	int ret;
286e26f2ae4SMichael Krufky 
287e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0100, &val);
288e26f2ae4SMichael Krufky 	if (lg_fail(ret))
289e26f2ae4SMichael Krufky 		goto fail;
290e26f2ae4SMichael Krufky 
291e26f2ae4SMichael Krufky 	val &= 0xcf;
292e26f2ae4SMichael Krufky 	val |= (if_agc_freeze) ? 0x20 : 0x00;
293e26f2ae4SMichael Krufky 	val |= (rf_agc_freeze) ? 0x10 : 0x00;
294e26f2ae4SMichael Krufky 
295e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x0100, val);
296e26f2ae4SMichael Krufky 	lg_fail(ret);
297e26f2ae4SMichael Krufky fail:
298e26f2ae4SMichael Krufky 	return ret;
299e26f2ae4SMichael Krufky }
300e26f2ae4SMichael Krufky #endif
301e26f2ae4SMichael Krufky 
302e26f2ae4SMichael Krufky static int lg2160_agc_polarity(struct lg216x_state *state,
303e26f2ae4SMichael Krufky 			       int if_agc_polarity, int rf_agc_polarity)
304e26f2ae4SMichael Krufky {
305e26f2ae4SMichael Krufky 	u8 val;
306e26f2ae4SMichael Krufky 	int ret;
307e26f2ae4SMichael Krufky 
308e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0100, &val);
309e26f2ae4SMichael Krufky 	if (lg_fail(ret))
310e26f2ae4SMichael Krufky 		goto fail;
311e26f2ae4SMichael Krufky 
312e26f2ae4SMichael Krufky 	val &= 0xfc;
313e26f2ae4SMichael Krufky 	val |= (if_agc_polarity) ? 0x02 : 0x00;
314e26f2ae4SMichael Krufky 	val |= (rf_agc_polarity) ? 0x01 : 0x00;
315e26f2ae4SMichael Krufky 
316e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x0100, val);
317e26f2ae4SMichael Krufky 	lg_fail(ret);
318e26f2ae4SMichael Krufky fail:
319e26f2ae4SMichael Krufky 	return ret;
320e26f2ae4SMichael Krufky }
321e26f2ae4SMichael Krufky 
322e26f2ae4SMichael Krufky static int lg2160_tuner_pwr_save_polarity(struct lg216x_state *state,
323e26f2ae4SMichael Krufky 					  int polarity)
324e26f2ae4SMichael Krufky {
325e26f2ae4SMichael Krufky 	u8 val;
326e26f2ae4SMichael Krufky 	int ret;
327e26f2ae4SMichael Krufky 
328e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0008, &val);
329e26f2ae4SMichael Krufky 	if (lg_fail(ret))
330e26f2ae4SMichael Krufky 		goto fail;
331e26f2ae4SMichael Krufky 
332e26f2ae4SMichael Krufky 	val &= 0xfe;
333e26f2ae4SMichael Krufky 	val |= (polarity) ? 0x01 : 0x00;
334e26f2ae4SMichael Krufky 
335e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x0008, val);
336e26f2ae4SMichael Krufky 	lg_fail(ret);
337e26f2ae4SMichael Krufky fail:
338e26f2ae4SMichael Krufky 	return ret;
339e26f2ae4SMichael Krufky }
340e26f2ae4SMichael Krufky 
341e26f2ae4SMichael Krufky static int lg2160_spectrum_polarity(struct lg216x_state *state,
342e26f2ae4SMichael Krufky 				    int inverted)
343e26f2ae4SMichael Krufky {
344e26f2ae4SMichael Krufky 	u8 val;
345e26f2ae4SMichael Krufky 	int ret;
346e26f2ae4SMichael Krufky 
347e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0132, &val);
348e26f2ae4SMichael Krufky 	if (lg_fail(ret))
349e26f2ae4SMichael Krufky 		goto fail;
350e26f2ae4SMichael Krufky 
351e26f2ae4SMichael Krufky 	val &= 0xfd;
352e26f2ae4SMichael Krufky 	val |= (inverted) ? 0x02 : 0x00;
353e26f2ae4SMichael Krufky 
354e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x0132, val);
355e26f2ae4SMichael Krufky 	lg_fail(ret);
356e26f2ae4SMichael Krufky fail:
357e26f2ae4SMichael Krufky 	return lg216x_soft_reset(state);
358e26f2ae4SMichael Krufky }
359e26f2ae4SMichael Krufky 
360e26f2ae4SMichael Krufky static int lg2160_tuner_pwr_save(struct lg216x_state *state, int onoff)
361e26f2ae4SMichael Krufky {
362e26f2ae4SMichael Krufky 	u8 val;
363e26f2ae4SMichael Krufky 	int ret;
364e26f2ae4SMichael Krufky 
365e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0007, &val);
366e26f2ae4SMichael Krufky 	if (lg_fail(ret))
367e26f2ae4SMichael Krufky 		goto fail;
368e26f2ae4SMichael Krufky 
369e26f2ae4SMichael Krufky 	val &= 0xbf;
370e26f2ae4SMichael Krufky 	val |= (onoff) ? 0x40 : 0x00;
371e26f2ae4SMichael Krufky 
372e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x0007, val);
373e26f2ae4SMichael Krufky 	lg_fail(ret);
374e26f2ae4SMichael Krufky fail:
375e26f2ae4SMichael Krufky 	return ret;
376e26f2ae4SMichael Krufky }
377e26f2ae4SMichael Krufky 
378e26f2ae4SMichael Krufky static int lg216x_set_parade(struct lg216x_state *state, int id)
379e26f2ae4SMichael Krufky {
380e26f2ae4SMichael Krufky 	int ret;
381e26f2ae4SMichael Krufky 
382e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x013e, id & 0x7f);
383e26f2ae4SMichael Krufky 	if (lg_fail(ret))
384e26f2ae4SMichael Krufky 		goto fail;
385e26f2ae4SMichael Krufky 
386e26f2ae4SMichael Krufky 	state->parade_id = id & 0x7f;
387e26f2ae4SMichael Krufky fail:
388e26f2ae4SMichael Krufky 	return ret;
389e26f2ae4SMichael Krufky }
390e26f2ae4SMichael Krufky 
391e26f2ae4SMichael Krufky static int lg216x_set_ensemble(struct lg216x_state *state, int id)
392e26f2ae4SMichael Krufky {
393e26f2ae4SMichael Krufky 	int ret;
394e26f2ae4SMichael Krufky 	u16 reg;
395e26f2ae4SMichael Krufky 	u8 val;
396e26f2ae4SMichael Krufky 
397e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
398e26f2ae4SMichael Krufky 	case LG2160:
399e26f2ae4SMichael Krufky 		reg = 0x0400;
400e26f2ae4SMichael Krufky 		break;
401e26f2ae4SMichael Krufky 	case LG2161:
4025444a1b7SMauro Carvalho Chehab 	default:
403e26f2ae4SMichael Krufky 		reg = 0x0500;
404e26f2ae4SMichael Krufky 		break;
405e26f2ae4SMichael Krufky 	}
406e26f2ae4SMichael Krufky 
407e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, reg, &val);
408e26f2ae4SMichael Krufky 	if (lg_fail(ret))
409e26f2ae4SMichael Krufky 		goto fail;
410e26f2ae4SMichael Krufky 
411e26f2ae4SMichael Krufky 	val &= 0xfe;
412e26f2ae4SMichael Krufky 	val |= (id) ? 0x01 : 0x00;
413e26f2ae4SMichael Krufky 
414e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, reg, val);
415e26f2ae4SMichael Krufky 	lg_fail(ret);
416e26f2ae4SMichael Krufky fail:
417e26f2ae4SMichael Krufky 	return ret;
418e26f2ae4SMichael Krufky }
419e26f2ae4SMichael Krufky 
420e26f2ae4SMichael Krufky static int lg2160_set_spi_clock(struct lg216x_state *state)
421e26f2ae4SMichael Krufky {
422e26f2ae4SMichael Krufky 	u8 val;
423e26f2ae4SMichael Krufky 	int ret;
424e26f2ae4SMichael Krufky 
425e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0014, &val);
426e26f2ae4SMichael Krufky 	if (lg_fail(ret))
427e26f2ae4SMichael Krufky 		goto fail;
428e26f2ae4SMichael Krufky 
429e26f2ae4SMichael Krufky 	val &= 0xf3;
430e26f2ae4SMichael Krufky 	val |= (state->cfg->spi_clock << 2);
431e26f2ae4SMichael Krufky 
432e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x0014, val);
433e26f2ae4SMichael Krufky 	lg_fail(ret);
434e26f2ae4SMichael Krufky fail:
435e26f2ae4SMichael Krufky 	return ret;
436e26f2ae4SMichael Krufky }
437e26f2ae4SMichael Krufky 
438e26f2ae4SMichael Krufky static int lg2161_set_output_interface(struct lg216x_state *state)
439e26f2ae4SMichael Krufky {
440e26f2ae4SMichael Krufky 	u8 val;
441e26f2ae4SMichael Krufky 	int ret;
442e26f2ae4SMichael Krufky 
443e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0014, &val);
444e26f2ae4SMichael Krufky 	if (lg_fail(ret))
445e26f2ae4SMichael Krufky 		goto fail;
446e26f2ae4SMichael Krufky 
447e26f2ae4SMichael Krufky 	val &= ~0x07;
448e26f2ae4SMichael Krufky 	val |= state->cfg->output_if; /* FIXME: needs sanity check */
449e26f2ae4SMichael Krufky 
450e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x0014, val);
451e26f2ae4SMichael Krufky 	lg_fail(ret);
452e26f2ae4SMichael Krufky fail:
453e26f2ae4SMichael Krufky 	return ret;
454e26f2ae4SMichael Krufky }
455e26f2ae4SMichael Krufky 
456e26f2ae4SMichael Krufky static int lg216x_enable_fic(struct lg216x_state *state, int onoff)
457e26f2ae4SMichael Krufky {
458e26f2ae4SMichael Krufky 	int ret;
459e26f2ae4SMichael Krufky 
460e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x0017, 0x23);
461e26f2ae4SMichael Krufky 	if (lg_fail(ret))
462e26f2ae4SMichael Krufky 		goto fail;
463e26f2ae4SMichael Krufky 
464e26f2ae4SMichael Krufky 	ret = lg216x_write_reg(state, 0x0016, 0xfc);
465e26f2ae4SMichael Krufky 	if (lg_fail(ret))
466e26f2ae4SMichael Krufky 		goto fail;
467e26f2ae4SMichael Krufky 
468e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
469e26f2ae4SMichael Krufky 	case LG2160:
470e26f2ae4SMichael Krufky 		ret = lg216x_write_reg(state, 0x0016,
471e26f2ae4SMichael Krufky 				       0xfc | ((onoff) ? 0x02 : 0x00));
472e26f2ae4SMichael Krufky 		break;
473e26f2ae4SMichael Krufky 	case LG2161:
474e26f2ae4SMichael Krufky 		ret = lg216x_write_reg(state, 0x0016, (onoff) ? 0x10 : 0x00);
475e26f2ae4SMichael Krufky 		break;
476e26f2ae4SMichael Krufky 	}
477e26f2ae4SMichael Krufky 	if (lg_fail(ret))
478e26f2ae4SMichael Krufky 		goto fail;
479e26f2ae4SMichael Krufky 
480e26f2ae4SMichael Krufky 	ret = lg216x_initialize(state);
481e26f2ae4SMichael Krufky 	if (lg_fail(ret))
482e26f2ae4SMichael Krufky 		goto fail;
483e26f2ae4SMichael Krufky 
484e26f2ae4SMichael Krufky 	if (onoff) {
485e26f2ae4SMichael Krufky 		ret = lg216x_write_reg(state, 0x0017, 0x03);
486e26f2ae4SMichael Krufky 		lg_fail(ret);
487e26f2ae4SMichael Krufky 	}
488e26f2ae4SMichael Krufky fail:
489e26f2ae4SMichael Krufky 	return ret;
490e26f2ae4SMichael Krufky }
491e26f2ae4SMichael Krufky 
492e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */
493e26f2ae4SMichael Krufky 
494e26f2ae4SMichael Krufky static int lg216x_get_fic_version(struct lg216x_state *state, u8 *ficver)
495e26f2ae4SMichael Krufky {
496e26f2ae4SMichael Krufky 	u8 val;
497e26f2ae4SMichael Krufky 	int ret;
498e26f2ae4SMichael Krufky 
499e26f2ae4SMichael Krufky 	*ficver = 0xff; /* invalid value */
500e26f2ae4SMichael Krufky 
501e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0128, &val);
502e26f2ae4SMichael Krufky 	if (lg_fail(ret))
503e26f2ae4SMichael Krufky 		goto fail;
504e26f2ae4SMichael Krufky 
505e26f2ae4SMichael Krufky 	*ficver = (val >> 3) & 0x1f;
506e26f2ae4SMichael Krufky fail:
507e26f2ae4SMichael Krufky 	return ret;
508e26f2ae4SMichael Krufky }
509e26f2ae4SMichael Krufky 
510e26f2ae4SMichael Krufky #if 0
511e26f2ae4SMichael Krufky static int lg2160_get_parade_id(struct lg216x_state *state, u8 *id)
512e26f2ae4SMichael Krufky {
513e26f2ae4SMichael Krufky 	u8 val;
514e26f2ae4SMichael Krufky 	int ret;
515e26f2ae4SMichael Krufky 
516e26f2ae4SMichael Krufky 	*id = 0xff; /* invalid value */
517e26f2ae4SMichael Krufky 
518e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0123, &val);
519e26f2ae4SMichael Krufky 	if (lg_fail(ret))
520e26f2ae4SMichael Krufky 		goto fail;
521e26f2ae4SMichael Krufky 
522e26f2ae4SMichael Krufky 	*id = val & 0x7f;
523e26f2ae4SMichael Krufky fail:
524e26f2ae4SMichael Krufky 	return ret;
525e26f2ae4SMichael Krufky }
526e26f2ae4SMichael Krufky #endif
527e26f2ae4SMichael Krufky 
528e26f2ae4SMichael Krufky static int lg216x_get_nog(struct lg216x_state *state, u8 *nog)
529e26f2ae4SMichael Krufky {
530e26f2ae4SMichael Krufky 	u8 val;
531e26f2ae4SMichael Krufky 	int ret;
532e26f2ae4SMichael Krufky 
533e26f2ae4SMichael Krufky 	*nog = 0xff; /* invalid value */
534e26f2ae4SMichael Krufky 
535e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0124, &val);
536e26f2ae4SMichael Krufky 	if (lg_fail(ret))
537e26f2ae4SMichael Krufky 		goto fail;
538e26f2ae4SMichael Krufky 
539e26f2ae4SMichael Krufky 	*nog = ((val >> 4) & 0x07) + 1;
540e26f2ae4SMichael Krufky fail:
541e26f2ae4SMichael Krufky 	return ret;
542e26f2ae4SMichael Krufky }
543e26f2ae4SMichael Krufky 
544e26f2ae4SMichael Krufky static int lg216x_get_tnog(struct lg216x_state *state, u8 *tnog)
545e26f2ae4SMichael Krufky {
546e26f2ae4SMichael Krufky 	u8 val;
547e26f2ae4SMichael Krufky 	int ret;
548e26f2ae4SMichael Krufky 
549e26f2ae4SMichael Krufky 	*tnog = 0xff; /* invalid value */
550e26f2ae4SMichael Krufky 
551e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0125, &val);
552e26f2ae4SMichael Krufky 	if (lg_fail(ret))
553e26f2ae4SMichael Krufky 		goto fail;
554e26f2ae4SMichael Krufky 
555e26f2ae4SMichael Krufky 	*tnog = val & 0x1f;
556e26f2ae4SMichael Krufky fail:
557e26f2ae4SMichael Krufky 	return ret;
558e26f2ae4SMichael Krufky }
559e26f2ae4SMichael Krufky 
560e26f2ae4SMichael Krufky static int lg216x_get_sgn(struct lg216x_state *state, u8 *sgn)
561e26f2ae4SMichael Krufky {
562e26f2ae4SMichael Krufky 	u8 val;
563e26f2ae4SMichael Krufky 	int ret;
564e26f2ae4SMichael Krufky 
565e26f2ae4SMichael Krufky 	*sgn = 0xff; /* invalid value */
566e26f2ae4SMichael Krufky 
567e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0124, &val);
568e26f2ae4SMichael Krufky 	if (lg_fail(ret))
569e26f2ae4SMichael Krufky 		goto fail;
570e26f2ae4SMichael Krufky 
571e26f2ae4SMichael Krufky 	*sgn = val & 0x0f;
572e26f2ae4SMichael Krufky fail:
573e26f2ae4SMichael Krufky 	return ret;
574e26f2ae4SMichael Krufky }
575e26f2ae4SMichael Krufky 
576e26f2ae4SMichael Krufky static int lg216x_get_prc(struct lg216x_state *state, u8 *prc)
577e26f2ae4SMichael Krufky {
578e26f2ae4SMichael Krufky 	u8 val;
579e26f2ae4SMichael Krufky 	int ret;
580e26f2ae4SMichael Krufky 
581e26f2ae4SMichael Krufky 	*prc = 0xff; /* invalid value */
582e26f2ae4SMichael Krufky 
583e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0125, &val);
584e26f2ae4SMichael Krufky 	if (lg_fail(ret))
585e26f2ae4SMichael Krufky 		goto fail;
586e26f2ae4SMichael Krufky 
587e26f2ae4SMichael Krufky 	*prc = ((val >> 5) & 0x07) + 1;
588e26f2ae4SMichael Krufky fail:
589e26f2ae4SMichael Krufky 	return ret;
590e26f2ae4SMichael Krufky }
591e26f2ae4SMichael Krufky 
592e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */
593e26f2ae4SMichael Krufky 
594e26f2ae4SMichael Krufky static int lg216x_get_rs_frame_mode(struct lg216x_state *state,
595e26f2ae4SMichael Krufky 				    enum atscmh_rs_frame_mode *rs_framemode)
596e26f2ae4SMichael Krufky {
597e26f2ae4SMichael Krufky 	u8 val;
598e26f2ae4SMichael Krufky 	int ret;
599e26f2ae4SMichael Krufky 
600e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
601e26f2ae4SMichael Krufky 	case LG2160:
602e26f2ae4SMichael Krufky 		ret = lg216x_read_reg(state, 0x0410, &val);
603e26f2ae4SMichael Krufky 		break;
604e26f2ae4SMichael Krufky 	case LG2161:
605e26f2ae4SMichael Krufky 		ret = lg216x_read_reg(state, 0x0513, &val);
606e26f2ae4SMichael Krufky 		break;
607e26f2ae4SMichael Krufky 	default:
608e26f2ae4SMichael Krufky 		ret = -EINVAL;
609e26f2ae4SMichael Krufky 	}
610e26f2ae4SMichael Krufky 	if (lg_fail(ret))
611e26f2ae4SMichael Krufky 		goto fail;
612e26f2ae4SMichael Krufky 
613e26f2ae4SMichael Krufky 	switch ((val >> 4) & 0x03) {
614e26f2ae4SMichael Krufky #if 1
615e26f2ae4SMichael Krufky 	default:
616e26f2ae4SMichael Krufky #endif
617e26f2ae4SMichael Krufky 	case 0x00:
618e26f2ae4SMichael Krufky 		*rs_framemode = ATSCMH_RSFRAME_PRI_ONLY;
619e26f2ae4SMichael Krufky 		break;
620e26f2ae4SMichael Krufky 	case 0x01:
621e26f2ae4SMichael Krufky 		*rs_framemode = ATSCMH_RSFRAME_PRI_SEC;
622e26f2ae4SMichael Krufky 		break;
623e26f2ae4SMichael Krufky #if 0
624e26f2ae4SMichael Krufky 	default:
625e26f2ae4SMichael Krufky 		*rs_framemode = ATSCMH_RSFRAME_RES;
626e26f2ae4SMichael Krufky 		break;
627e26f2ae4SMichael Krufky #endif
628e26f2ae4SMichael Krufky 	}
629e26f2ae4SMichael Krufky fail:
630e26f2ae4SMichael Krufky 	return ret;
631e26f2ae4SMichael Krufky }
632e26f2ae4SMichael Krufky 
633e26f2ae4SMichael Krufky static
634e26f2ae4SMichael Krufky int lg216x_get_rs_frame_ensemble(struct lg216x_state *state,
635e26f2ae4SMichael Krufky 				 enum atscmh_rs_frame_ensemble *rs_frame_ens)
636e26f2ae4SMichael Krufky {
637e26f2ae4SMichael Krufky 	u8 val;
638e26f2ae4SMichael Krufky 	int ret;
639e26f2ae4SMichael Krufky 
640e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
641e26f2ae4SMichael Krufky 	case LG2160:
642e26f2ae4SMichael Krufky 		ret = lg216x_read_reg(state, 0x0400, &val);
643e26f2ae4SMichael Krufky 		break;
644e26f2ae4SMichael Krufky 	case LG2161:
645e26f2ae4SMichael Krufky 		ret = lg216x_read_reg(state, 0x0500, &val);
646e26f2ae4SMichael Krufky 		break;
647e26f2ae4SMichael Krufky 	default:
648e26f2ae4SMichael Krufky 		ret = -EINVAL;
649e26f2ae4SMichael Krufky 	}
650e26f2ae4SMichael Krufky 	if (lg_fail(ret))
651e26f2ae4SMichael Krufky 		goto fail;
652e26f2ae4SMichael Krufky 
653e26f2ae4SMichael Krufky 	val &= 0x01;
654e26f2ae4SMichael Krufky 	*rs_frame_ens = (enum atscmh_rs_frame_ensemble) val;
655e26f2ae4SMichael Krufky fail:
656e26f2ae4SMichael Krufky 	return ret;
657e26f2ae4SMichael Krufky }
658e26f2ae4SMichael Krufky 
659e26f2ae4SMichael Krufky static int lg216x_get_rs_code_mode(struct lg216x_state *state,
660e26f2ae4SMichael Krufky 				   enum atscmh_rs_code_mode *rs_code_pri,
661e26f2ae4SMichael Krufky 				   enum atscmh_rs_code_mode *rs_code_sec)
662e26f2ae4SMichael Krufky {
663e26f2ae4SMichael Krufky 	u8 val;
664e26f2ae4SMichael Krufky 	int ret;
665e26f2ae4SMichael Krufky 
666e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
667e26f2ae4SMichael Krufky 	case LG2160:
668e26f2ae4SMichael Krufky 		ret = lg216x_read_reg(state, 0x0410, &val);
669e26f2ae4SMichael Krufky 		break;
670e26f2ae4SMichael Krufky 	case LG2161:
671e26f2ae4SMichael Krufky 		ret = lg216x_read_reg(state, 0x0513, &val);
672e26f2ae4SMichael Krufky 		break;
673e26f2ae4SMichael Krufky 	default:
674e26f2ae4SMichael Krufky 		ret = -EINVAL;
675e26f2ae4SMichael Krufky 	}
676e26f2ae4SMichael Krufky 	if (lg_fail(ret))
677e26f2ae4SMichael Krufky 		goto fail;
678e26f2ae4SMichael Krufky 
679e26f2ae4SMichael Krufky 	*rs_code_pri = (enum atscmh_rs_code_mode) ((val >> 2) & 0x03);
680e26f2ae4SMichael Krufky 	*rs_code_sec = (enum atscmh_rs_code_mode) (val & 0x03);
681e26f2ae4SMichael Krufky fail:
682e26f2ae4SMichael Krufky 	return ret;
683e26f2ae4SMichael Krufky }
684e26f2ae4SMichael Krufky 
685e26f2ae4SMichael Krufky static int lg216x_get_sccc_block_mode(struct lg216x_state *state,
686e26f2ae4SMichael Krufky 				      enum atscmh_sccc_block_mode *sccc_block)
687e26f2ae4SMichael Krufky {
688e26f2ae4SMichael Krufky 	u8 val;
689e26f2ae4SMichael Krufky 	int ret;
690e26f2ae4SMichael Krufky 
691e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
692e26f2ae4SMichael Krufky 	case LG2160:
693e26f2ae4SMichael Krufky 		ret = lg216x_read_reg(state, 0x0315, &val);
694e26f2ae4SMichael Krufky 		break;
695e26f2ae4SMichael Krufky 	case LG2161:
696e26f2ae4SMichael Krufky 		ret = lg216x_read_reg(state, 0x0511, &val);
697e26f2ae4SMichael Krufky 		break;
698e26f2ae4SMichael Krufky 	default:
699e26f2ae4SMichael Krufky 		ret = -EINVAL;
700e26f2ae4SMichael Krufky 	}
701e26f2ae4SMichael Krufky 	if (lg_fail(ret))
702e26f2ae4SMichael Krufky 		goto fail;
703e26f2ae4SMichael Krufky 
704e26f2ae4SMichael Krufky 	switch (val & 0x03) {
705e26f2ae4SMichael Krufky 	case 0x00:
706e26f2ae4SMichael Krufky 		*sccc_block = ATSCMH_SCCC_BLK_SEP;
707e26f2ae4SMichael Krufky 		break;
708e26f2ae4SMichael Krufky 	case 0x01:
709e26f2ae4SMichael Krufky 		*sccc_block = ATSCMH_SCCC_BLK_COMB;
710e26f2ae4SMichael Krufky 		break;
711e26f2ae4SMichael Krufky 	default:
712e26f2ae4SMichael Krufky 		*sccc_block = ATSCMH_SCCC_BLK_RES;
713e26f2ae4SMichael Krufky 		break;
714e26f2ae4SMichael Krufky 	}
715e26f2ae4SMichael Krufky fail:
716e26f2ae4SMichael Krufky 	return ret;
717e26f2ae4SMichael Krufky }
718e26f2ae4SMichael Krufky 
719e26f2ae4SMichael Krufky static int lg216x_get_sccc_code_mode(struct lg216x_state *state,
720e26f2ae4SMichael Krufky 				     enum atscmh_sccc_code_mode *mode_a,
721e26f2ae4SMichael Krufky 				     enum atscmh_sccc_code_mode *mode_b,
722e26f2ae4SMichael Krufky 				     enum atscmh_sccc_code_mode *mode_c,
723e26f2ae4SMichael Krufky 				     enum atscmh_sccc_code_mode *mode_d)
724e26f2ae4SMichael Krufky {
725e26f2ae4SMichael Krufky 	u8 val;
726e26f2ae4SMichael Krufky 	int ret;
727e26f2ae4SMichael Krufky 
728e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
729e26f2ae4SMichael Krufky 	case LG2160:
730e26f2ae4SMichael Krufky 		ret = lg216x_read_reg(state, 0x0316, &val);
731e26f2ae4SMichael Krufky 		break;
732e26f2ae4SMichael Krufky 	case LG2161:
733e26f2ae4SMichael Krufky 		ret = lg216x_read_reg(state, 0x0512, &val);
734e26f2ae4SMichael Krufky 		break;
735e26f2ae4SMichael Krufky 	default:
736e26f2ae4SMichael Krufky 		ret = -EINVAL;
737e26f2ae4SMichael Krufky 	}
738e26f2ae4SMichael Krufky 	if (lg_fail(ret))
739e26f2ae4SMichael Krufky 		goto fail;
740e26f2ae4SMichael Krufky 
741e26f2ae4SMichael Krufky 	switch ((val >> 6) & 0x03) {
742e26f2ae4SMichael Krufky 	case 0x00:
743e26f2ae4SMichael Krufky 		*mode_a = ATSCMH_SCCC_CODE_HLF;
744e26f2ae4SMichael Krufky 		break;
745e26f2ae4SMichael Krufky 	case 0x01:
746e26f2ae4SMichael Krufky 		*mode_a = ATSCMH_SCCC_CODE_QTR;
747e26f2ae4SMichael Krufky 		break;
748e26f2ae4SMichael Krufky 	default:
749e26f2ae4SMichael Krufky 		*mode_a = ATSCMH_SCCC_CODE_RES;
750e26f2ae4SMichael Krufky 		break;
751e26f2ae4SMichael Krufky 	}
752e26f2ae4SMichael Krufky 
753e26f2ae4SMichael Krufky 	switch ((val >> 4) & 0x03) {
754e26f2ae4SMichael Krufky 	case 0x00:
755e26f2ae4SMichael Krufky 		*mode_b = ATSCMH_SCCC_CODE_HLF;
756e26f2ae4SMichael Krufky 		break;
757e26f2ae4SMichael Krufky 	case 0x01:
758e26f2ae4SMichael Krufky 		*mode_b = ATSCMH_SCCC_CODE_QTR;
759e26f2ae4SMichael Krufky 		break;
760e26f2ae4SMichael Krufky 	default:
761e26f2ae4SMichael Krufky 		*mode_b = ATSCMH_SCCC_CODE_RES;
762e26f2ae4SMichael Krufky 		break;
763e26f2ae4SMichael Krufky 	}
764e26f2ae4SMichael Krufky 
765e26f2ae4SMichael Krufky 	switch ((val >> 2) & 0x03) {
766e26f2ae4SMichael Krufky 	case 0x00:
767e26f2ae4SMichael Krufky 		*mode_c = ATSCMH_SCCC_CODE_HLF;
768e26f2ae4SMichael Krufky 		break;
769e26f2ae4SMichael Krufky 	case 0x01:
770e26f2ae4SMichael Krufky 		*mode_c = ATSCMH_SCCC_CODE_QTR;
771e26f2ae4SMichael Krufky 		break;
772e26f2ae4SMichael Krufky 	default:
773e26f2ae4SMichael Krufky 		*mode_c = ATSCMH_SCCC_CODE_RES;
774e26f2ae4SMichael Krufky 		break;
775e26f2ae4SMichael Krufky 	}
776e26f2ae4SMichael Krufky 
777e26f2ae4SMichael Krufky 	switch (val & 0x03) {
778e26f2ae4SMichael Krufky 	case 0x00:
779e26f2ae4SMichael Krufky 		*mode_d = ATSCMH_SCCC_CODE_HLF;
780e26f2ae4SMichael Krufky 		break;
781e26f2ae4SMichael Krufky 	case 0x01:
782e26f2ae4SMichael Krufky 		*mode_d = ATSCMH_SCCC_CODE_QTR;
783e26f2ae4SMichael Krufky 		break;
784e26f2ae4SMichael Krufky 	default:
785e26f2ae4SMichael Krufky 		*mode_d = ATSCMH_SCCC_CODE_RES;
786e26f2ae4SMichael Krufky 		break;
787e26f2ae4SMichael Krufky 	}
788e26f2ae4SMichael Krufky fail:
789e26f2ae4SMichael Krufky 	return ret;
790e26f2ae4SMichael Krufky }
791e26f2ae4SMichael Krufky 
792e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */
793e26f2ae4SMichael Krufky 
79410d67371SMichael Krufky #if 0
795e26f2ae4SMichael Krufky static int lg216x_read_fic_err_count(struct lg216x_state *state, u8 *err)
796e26f2ae4SMichael Krufky {
797e26f2ae4SMichael Krufky 	u8 fic_err;
798e26f2ae4SMichael Krufky 	int ret;
799e26f2ae4SMichael Krufky 
800e26f2ae4SMichael Krufky 	*err = 0;
801e26f2ae4SMichael Krufky 
802e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
803e26f2ae4SMichael Krufky 	case LG2160:
804e26f2ae4SMichael Krufky 		ret = lg216x_read_reg(state, 0x0012, &fic_err);
805e26f2ae4SMichael Krufky 		break;
806e26f2ae4SMichael Krufky 	case LG2161:
807e26f2ae4SMichael Krufky 		ret = lg216x_read_reg(state, 0x001e, &fic_err);
808e26f2ae4SMichael Krufky 		break;
809e26f2ae4SMichael Krufky 	}
810e26f2ae4SMichael Krufky 	if (lg_fail(ret))
811e26f2ae4SMichael Krufky 		goto fail;
812e26f2ae4SMichael Krufky 
813e26f2ae4SMichael Krufky 	*err = fic_err;
814e26f2ae4SMichael Krufky fail:
815e26f2ae4SMichael Krufky 	return ret;
816e26f2ae4SMichael Krufky }
817e26f2ae4SMichael Krufky 
818e26f2ae4SMichael Krufky static int lg2160_read_crc_err_count(struct lg216x_state *state, u16 *err)
819e26f2ae4SMichael Krufky {
820e26f2ae4SMichael Krufky 	u8 crc_err1, crc_err2;
821e26f2ae4SMichael Krufky 	int ret;
822e26f2ae4SMichael Krufky 
823e26f2ae4SMichael Krufky 	*err = 0;
824e26f2ae4SMichael Krufky 
825e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0411, &crc_err1);
826e26f2ae4SMichael Krufky 	if (lg_fail(ret))
827e26f2ae4SMichael Krufky 		goto fail;
828e26f2ae4SMichael Krufky 
829e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0412, &crc_err2);
830e26f2ae4SMichael Krufky 	if (lg_fail(ret))
831e26f2ae4SMichael Krufky 		goto fail;
832e26f2ae4SMichael Krufky 
833e26f2ae4SMichael Krufky 	*err = (u16)(((crc_err2 & 0x0f) << 8) | crc_err1);
834e26f2ae4SMichael Krufky fail:
835e26f2ae4SMichael Krufky 	return ret;
836e26f2ae4SMichael Krufky }
837e26f2ae4SMichael Krufky 
838e26f2ae4SMichael Krufky static int lg2161_read_crc_err_count(struct lg216x_state *state, u16 *err)
839e26f2ae4SMichael Krufky {
840e26f2ae4SMichael Krufky 	u8 crc_err;
841e26f2ae4SMichael Krufky 	int ret;
842e26f2ae4SMichael Krufky 
843e26f2ae4SMichael Krufky 	*err = 0;
844e26f2ae4SMichael Krufky 
845e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0612, &crc_err);
846e26f2ae4SMichael Krufky 	if (lg_fail(ret))
847e26f2ae4SMichael Krufky 		goto fail;
848e26f2ae4SMichael Krufky 
849e26f2ae4SMichael Krufky 	*err = (u16)crc_err;
850e26f2ae4SMichael Krufky fail:
851e26f2ae4SMichael Krufky 	return ret;
852e26f2ae4SMichael Krufky }
853e26f2ae4SMichael Krufky 
854e26f2ae4SMichael Krufky static int lg216x_read_crc_err_count(struct lg216x_state *state, u16 *err)
855e26f2ae4SMichael Krufky {
856e26f2ae4SMichael Krufky 	int ret;
857e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
858e26f2ae4SMichael Krufky 	case LG2160:
859e26f2ae4SMichael Krufky 		ret = lg2160_read_crc_err_count(state, err);
860e26f2ae4SMichael Krufky 		break;
861e26f2ae4SMichael Krufky 	case LG2161:
862e26f2ae4SMichael Krufky 		ret = lg2161_read_crc_err_count(state, err);
863e26f2ae4SMichael Krufky 		break;
864e26f2ae4SMichael Krufky 	default:
865e26f2ae4SMichael Krufky 		ret = -EINVAL;
866e26f2ae4SMichael Krufky 		break;
867e26f2ae4SMichael Krufky 	}
868e26f2ae4SMichael Krufky 	return ret;
869e26f2ae4SMichael Krufky }
870e26f2ae4SMichael Krufky 
871e26f2ae4SMichael Krufky static int lg2160_read_rs_err_count(struct lg216x_state *state, u16 *err)
872e26f2ae4SMichael Krufky {
873e26f2ae4SMichael Krufky 	u8 rs_err1, rs_err2;
874e26f2ae4SMichael Krufky 	int ret;
875e26f2ae4SMichael Krufky 
876e26f2ae4SMichael Krufky 	*err = 0;
877e26f2ae4SMichael Krufky 
878e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0413, &rs_err1);
879e26f2ae4SMichael Krufky 	if (lg_fail(ret))
880e26f2ae4SMichael Krufky 		goto fail;
881e26f2ae4SMichael Krufky 
882e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0414, &rs_err2);
883e26f2ae4SMichael Krufky 	if (lg_fail(ret))
884e26f2ae4SMichael Krufky 		goto fail;
885e26f2ae4SMichael Krufky 
886e26f2ae4SMichael Krufky 	*err = (u16)(((rs_err2 & 0x0f) << 8) | rs_err1);
887e26f2ae4SMichael Krufky fail:
888e26f2ae4SMichael Krufky 	return ret;
889e26f2ae4SMichael Krufky }
890e26f2ae4SMichael Krufky 
891e26f2ae4SMichael Krufky static int lg2161_read_rs_err_count(struct lg216x_state *state, u16 *err)
892e26f2ae4SMichael Krufky {
893e26f2ae4SMichael Krufky 	u8 rs_err1, rs_err2;
894e26f2ae4SMichael Krufky 	int ret;
895e26f2ae4SMichael Krufky 
896e26f2ae4SMichael Krufky 	*err = 0;
897e26f2ae4SMichael Krufky 
898e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0613, &rs_err1);
899e26f2ae4SMichael Krufky 	if (lg_fail(ret))
900e26f2ae4SMichael Krufky 		goto fail;
901e26f2ae4SMichael Krufky 
902e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0614, &rs_err2);
903e26f2ae4SMichael Krufky 	if (lg_fail(ret))
904e26f2ae4SMichael Krufky 		goto fail;
905e26f2ae4SMichael Krufky 
906e26f2ae4SMichael Krufky 	*err = (u16)((rs_err1 << 8) | rs_err2);
907e26f2ae4SMichael Krufky fail:
908e26f2ae4SMichael Krufky 	return ret;
909e26f2ae4SMichael Krufky }
910e26f2ae4SMichael Krufky 
911e26f2ae4SMichael Krufky static int lg216x_read_rs_err_count(struct lg216x_state *state, u16 *err)
912e26f2ae4SMichael Krufky {
913e26f2ae4SMichael Krufky 	int ret;
914e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
915e26f2ae4SMichael Krufky 	case LG2160:
916e26f2ae4SMichael Krufky 		ret = lg2160_read_rs_err_count(state, err);
917e26f2ae4SMichael Krufky 		break;
918e26f2ae4SMichael Krufky 	case LG2161:
919e26f2ae4SMichael Krufky 		ret = lg2161_read_rs_err_count(state, err);
920e26f2ae4SMichael Krufky 		break;
921e26f2ae4SMichael Krufky 	default:
922e26f2ae4SMichael Krufky 		ret = -EINVAL;
923e26f2ae4SMichael Krufky 		break;
924e26f2ae4SMichael Krufky 	}
925e26f2ae4SMichael Krufky 	return ret;
926e26f2ae4SMichael Krufky }
92710d67371SMichael Krufky #endif
928e26f2ae4SMichael Krufky 
929e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */
930e26f2ae4SMichael Krufky 
9317e3e68bcSMauro Carvalho Chehab static int lg216x_get_frontend(struct dvb_frontend *fe,
9327e3e68bcSMauro Carvalho Chehab 			       struct dtv_frontend_properties *c)
933e26f2ae4SMichael Krufky {
934e26f2ae4SMichael Krufky 	struct lg216x_state *state = fe->demodulator_priv;
935e26f2ae4SMichael Krufky 	int ret;
936e26f2ae4SMichael Krufky 
937e26f2ae4SMichael Krufky 	lg_dbg("\n");
938e26f2ae4SMichael Krufky 
9397e3e68bcSMauro Carvalho Chehab 	c->modulation = VSB_8;
9407e3e68bcSMauro Carvalho Chehab 	c->frequency = state->current_frequency;
9417e3e68bcSMauro Carvalho Chehab 	c->delivery_system = SYS_ATSCMH;
942e26f2ae4SMichael Krufky 
943e26f2ae4SMichael Krufky 	ret = lg216x_get_fic_version(state,
9447e3e68bcSMauro Carvalho Chehab 				     &c->atscmh_fic_ver);
945e26f2ae4SMichael Krufky 	if (lg_fail(ret))
946e26f2ae4SMichael Krufky 		goto fail;
9477e3e68bcSMauro Carvalho Chehab 	if (state->fic_ver != c->atscmh_fic_ver) {
9487e3e68bcSMauro Carvalho Chehab 		state->fic_ver = c->atscmh_fic_ver;
949e26f2ae4SMichael Krufky 
950e26f2ae4SMichael Krufky #if 0
951e26f2ae4SMichael Krufky 		ret = lg2160_get_parade_id(state,
9527e3e68bcSMauro Carvalho Chehab 				&c->atscmh_parade_id);
953e26f2ae4SMichael Krufky 		if (lg_fail(ret))
954e26f2ae4SMichael Krufky 			goto fail;
955e26f2ae4SMichael Krufky /* #else */
9567e3e68bcSMauro Carvalho Chehab 		c->atscmh_parade_id = state->parade_id;
957e26f2ae4SMichael Krufky #endif
958e26f2ae4SMichael Krufky 		ret = lg216x_get_nog(state,
9597e3e68bcSMauro Carvalho Chehab 				     &c->atscmh_nog);
960e26f2ae4SMichael Krufky 		if (lg_fail(ret))
961e26f2ae4SMichael Krufky 			goto fail;
962e26f2ae4SMichael Krufky 		ret = lg216x_get_tnog(state,
9637e3e68bcSMauro Carvalho Chehab 				      &c->atscmh_tnog);
964e26f2ae4SMichael Krufky 		if (lg_fail(ret))
965e26f2ae4SMichael Krufky 			goto fail;
966e26f2ae4SMichael Krufky 		ret = lg216x_get_sgn(state,
9677e3e68bcSMauro Carvalho Chehab 				     &c->atscmh_sgn);
968e26f2ae4SMichael Krufky 		if (lg_fail(ret))
969e26f2ae4SMichael Krufky 			goto fail;
970e26f2ae4SMichael Krufky 		ret = lg216x_get_prc(state,
9717e3e68bcSMauro Carvalho Chehab 				     &c->atscmh_prc);
972e26f2ae4SMichael Krufky 		if (lg_fail(ret))
973e26f2ae4SMichael Krufky 			goto fail;
974e26f2ae4SMichael Krufky 
975e26f2ae4SMichael Krufky 		ret = lg216x_get_rs_frame_mode(state,
976e26f2ae4SMichael Krufky 			(enum atscmh_rs_frame_mode *)
9777e3e68bcSMauro Carvalho Chehab 			&c->atscmh_rs_frame_mode);
978e26f2ae4SMichael Krufky 		if (lg_fail(ret))
979e26f2ae4SMichael Krufky 			goto fail;
980e26f2ae4SMichael Krufky 		ret = lg216x_get_rs_frame_ensemble(state,
981e26f2ae4SMichael Krufky 			(enum atscmh_rs_frame_ensemble *)
9827e3e68bcSMauro Carvalho Chehab 			&c->atscmh_rs_frame_ensemble);
983e26f2ae4SMichael Krufky 		if (lg_fail(ret))
984e26f2ae4SMichael Krufky 			goto fail;
985e26f2ae4SMichael Krufky 		ret = lg216x_get_rs_code_mode(state,
986e26f2ae4SMichael Krufky 			(enum atscmh_rs_code_mode *)
9877e3e68bcSMauro Carvalho Chehab 			&c->atscmh_rs_code_mode_pri,
988e26f2ae4SMichael Krufky 			(enum atscmh_rs_code_mode *)
9897e3e68bcSMauro Carvalho Chehab 			&c->atscmh_rs_code_mode_sec);
990e26f2ae4SMichael Krufky 		if (lg_fail(ret))
991e26f2ae4SMichael Krufky 			goto fail;
992e26f2ae4SMichael Krufky 		ret = lg216x_get_sccc_block_mode(state,
993e26f2ae4SMichael Krufky 			(enum atscmh_sccc_block_mode *)
9947e3e68bcSMauro Carvalho Chehab 			&c->atscmh_sccc_block_mode);
995e26f2ae4SMichael Krufky 		if (lg_fail(ret))
996e26f2ae4SMichael Krufky 			goto fail;
997e26f2ae4SMichael Krufky 		ret = lg216x_get_sccc_code_mode(state,
998e26f2ae4SMichael Krufky 			(enum atscmh_sccc_code_mode *)
9997e3e68bcSMauro Carvalho Chehab 			&c->atscmh_sccc_code_mode_a,
1000e26f2ae4SMichael Krufky 			(enum atscmh_sccc_code_mode *)
10017e3e68bcSMauro Carvalho Chehab 			&c->atscmh_sccc_code_mode_b,
1002e26f2ae4SMichael Krufky 			(enum atscmh_sccc_code_mode *)
10037e3e68bcSMauro Carvalho Chehab 			&c->atscmh_sccc_code_mode_c,
1004e26f2ae4SMichael Krufky 			(enum atscmh_sccc_code_mode *)
10057e3e68bcSMauro Carvalho Chehab 			&c->atscmh_sccc_code_mode_d);
1006e26f2ae4SMichael Krufky 		if (lg_fail(ret))
1007e26f2ae4SMichael Krufky 			goto fail;
1008e26f2ae4SMichael Krufky 	}
100910d67371SMichael Krufky #if 0
1010e26f2ae4SMichael Krufky 	ret = lg216x_read_fic_err_count(state,
10117e3e68bcSMauro Carvalho Chehab 				(u8 *)&c->atscmh_fic_err);
1012e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1013e26f2ae4SMichael Krufky 		goto fail;
1014e26f2ae4SMichael Krufky 	ret = lg216x_read_crc_err_count(state,
10157e3e68bcSMauro Carvalho Chehab 				&c->atscmh_crc_err);
1016e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1017e26f2ae4SMichael Krufky 		goto fail;
1018e26f2ae4SMichael Krufky 	ret = lg216x_read_rs_err_count(state,
10197e3e68bcSMauro Carvalho Chehab 				&c->atscmh_rs_err);
1020e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1021e26f2ae4SMichael Krufky 		goto fail;
1022e26f2ae4SMichael Krufky 
1023e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
1024e26f2ae4SMichael Krufky 	case LG2160:
10257e3e68bcSMauro Carvalho Chehab 		if (((c->atscmh_rs_err >= 240) &&
10267e3e68bcSMauro Carvalho Chehab 		     (c->atscmh_crc_err >= 240)) &&
1027e26f2ae4SMichael Krufky 		    ((jiffies_to_msecs(jiffies) - state->last_reset) > 6000))
1028e26f2ae4SMichael Krufky 			ret = lg216x_soft_reset(state);
1029e26f2ae4SMichael Krufky 		break;
1030e26f2ae4SMichael Krufky 	case LG2161:
1031e26f2ae4SMichael Krufky 		/* no fix needed here (as far as we know) */
1032e26f2ae4SMichael Krufky 		ret = 0;
1033e26f2ae4SMichael Krufky 		break;
1034e26f2ae4SMichael Krufky 	}
1035e26f2ae4SMichael Krufky 	lg_fail(ret);
103610d67371SMichael Krufky #endif
1037e26f2ae4SMichael Krufky fail:
1038e26f2ae4SMichael Krufky 	return ret;
1039e26f2ae4SMichael Krufky }
1040e26f2ae4SMichael Krufky 
1041e26f2ae4SMichael Krufky static int lg2160_set_frontend(struct dvb_frontend *fe)
1042e26f2ae4SMichael Krufky {
1043e26f2ae4SMichael Krufky 	struct lg216x_state *state = fe->demodulator_priv;
10447e3e68bcSMauro Carvalho Chehab 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1045e26f2ae4SMichael Krufky 	int ret;
1046e26f2ae4SMichael Krufky 
1047e26f2ae4SMichael Krufky 	lg_dbg("(%d)\n", fe->dtv_property_cache.frequency);
1048e26f2ae4SMichael Krufky 
1049e26f2ae4SMichael Krufky 	if (fe->ops.tuner_ops.set_params) {
1050e26f2ae4SMichael Krufky 		ret = fe->ops.tuner_ops.set_params(fe);
1051e26f2ae4SMichael Krufky 		if (fe->ops.i2c_gate_ctrl)
1052e26f2ae4SMichael Krufky 			fe->ops.i2c_gate_ctrl(fe, 0);
1053e26f2ae4SMichael Krufky 		if (lg_fail(ret))
1054e26f2ae4SMichael Krufky 			goto fail;
1055e26f2ae4SMichael Krufky 		state->current_frequency = fe->dtv_property_cache.frequency;
1056e26f2ae4SMichael Krufky 	}
1057e26f2ae4SMichael Krufky 
1058e26f2ae4SMichael Krufky 	ret = lg2160_agc_fix(state, 0, 0);
1059e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1060e26f2ae4SMichael Krufky 		goto fail;
1061e26f2ae4SMichael Krufky 	ret = lg2160_agc_polarity(state, 0, 0);
1062e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1063e26f2ae4SMichael Krufky 		goto fail;
1064e26f2ae4SMichael Krufky 	ret = lg2160_tuner_pwr_save_polarity(state, 1);
1065e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1066e26f2ae4SMichael Krufky 		goto fail;
1067e26f2ae4SMichael Krufky 	ret = lg216x_set_if(state);
1068e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1069e26f2ae4SMichael Krufky 		goto fail;
1070e26f2ae4SMichael Krufky 	ret = lg2160_spectrum_polarity(state, state->cfg->spectral_inversion);
1071e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1072e26f2ae4SMichael Krufky 		goto fail;
1073e26f2ae4SMichael Krufky 
1074e26f2ae4SMichael Krufky 	/* be tuned before this point */
1075e26f2ae4SMichael Krufky 	ret = lg216x_soft_reset(state);
1076e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1077e26f2ae4SMichael Krufky 		goto fail;
1078e26f2ae4SMichael Krufky 
1079e26f2ae4SMichael Krufky 	ret = lg2160_tuner_pwr_save(state, 0);
1080e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1081e26f2ae4SMichael Krufky 		goto fail;
1082e26f2ae4SMichael Krufky 
1083e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
1084e26f2ae4SMichael Krufky 	case LG2160:
1085e26f2ae4SMichael Krufky 		ret = lg2160_set_spi_clock(state);
1086e26f2ae4SMichael Krufky 		if (lg_fail(ret))
1087e26f2ae4SMichael Krufky 			goto fail;
1088e26f2ae4SMichael Krufky 		break;
1089e26f2ae4SMichael Krufky 	case LG2161:
1090e26f2ae4SMichael Krufky 		ret = lg2161_set_output_interface(state);
1091e26f2ae4SMichael Krufky 		if (lg_fail(ret))
1092e26f2ae4SMichael Krufky 			goto fail;
1093e26f2ae4SMichael Krufky 		break;
1094e26f2ae4SMichael Krufky 	}
1095e26f2ae4SMichael Krufky 
1096e26f2ae4SMichael Krufky 	ret = lg216x_set_parade(state, fe->dtv_property_cache.atscmh_parade_id);
1097e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1098e26f2ae4SMichael Krufky 		goto fail;
1099e26f2ae4SMichael Krufky 
1100e26f2ae4SMichael Krufky 	ret = lg216x_set_ensemble(state,
1101e26f2ae4SMichael Krufky 			fe->dtv_property_cache.atscmh_rs_frame_ensemble);
1102e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1103e26f2ae4SMichael Krufky 		goto fail;
1104e26f2ae4SMichael Krufky 
1105e26f2ae4SMichael Krufky 	ret = lg216x_initialize(state);
1106e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1107e26f2ae4SMichael Krufky 		goto fail;
1108e26f2ae4SMichael Krufky 
1109e26f2ae4SMichael Krufky 	ret = lg216x_enable_fic(state, 1);
1110e26f2ae4SMichael Krufky 	lg_fail(ret);
1111e26f2ae4SMichael Krufky 
11127e3e68bcSMauro Carvalho Chehab 	lg216x_get_frontend(fe, c);
1113e26f2ae4SMichael Krufky fail:
1114e26f2ae4SMichael Krufky 	return ret;
1115e26f2ae4SMichael Krufky }
1116e26f2ae4SMichael Krufky 
1117e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */
1118e26f2ae4SMichael Krufky 
1119e26f2ae4SMichael Krufky static int lg2160_read_lock_status(struct lg216x_state *state,
1120e26f2ae4SMichael Krufky 				   int *acq_lock, int *sync_lock)
1121e26f2ae4SMichael Krufky {
1122e26f2ae4SMichael Krufky 	u8 val;
1123e26f2ae4SMichael Krufky 	int ret;
1124e26f2ae4SMichael Krufky 
1125e26f2ae4SMichael Krufky 	*acq_lock = 0;
1126e26f2ae4SMichael Krufky 	*sync_lock = 0;
1127e26f2ae4SMichael Krufky 
1128e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x011b, &val);
1129e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1130e26f2ae4SMichael Krufky 		goto fail;
1131e26f2ae4SMichael Krufky 
1132e26f2ae4SMichael Krufky 	*sync_lock = (val & 0x20) ? 0 : 1;
1133e26f2ae4SMichael Krufky 	*acq_lock  = (val & 0x40) ? 0 : 1;
1134e26f2ae4SMichael Krufky fail:
1135e26f2ae4SMichael Krufky 	return ret;
1136e26f2ae4SMichael Krufky }
1137e26f2ae4SMichael Krufky 
1138e26f2ae4SMichael Krufky #ifdef USE_LG2161_LOCK_BITS
1139e26f2ae4SMichael Krufky static int lg2161_read_lock_status(struct lg216x_state *state,
1140e26f2ae4SMichael Krufky 				   int *acq_lock, int *sync_lock)
1141e26f2ae4SMichael Krufky {
1142e26f2ae4SMichael Krufky 	u8 val;
1143e26f2ae4SMichael Krufky 	int ret;
1144e26f2ae4SMichael Krufky 
1145e26f2ae4SMichael Krufky 	*acq_lock = 0;
1146e26f2ae4SMichael Krufky 	*sync_lock = 0;
1147e26f2ae4SMichael Krufky 
1148e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0304, &val);
1149e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1150e26f2ae4SMichael Krufky 		goto fail;
1151e26f2ae4SMichael Krufky 
1152e26f2ae4SMichael Krufky 	*sync_lock = (val & 0x80) ? 0 : 1;
1153e26f2ae4SMichael Krufky 
1154e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x011b, &val);
1155e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1156e26f2ae4SMichael Krufky 		goto fail;
1157e26f2ae4SMichael Krufky 
1158e26f2ae4SMichael Krufky 	*acq_lock  = (val & 0x40) ? 0 : 1;
1159e26f2ae4SMichael Krufky fail:
1160e26f2ae4SMichael Krufky 	return ret;
1161e26f2ae4SMichael Krufky }
1162e26f2ae4SMichael Krufky #endif
1163e26f2ae4SMichael Krufky 
1164e26f2ae4SMichael Krufky static int lg216x_read_lock_status(struct lg216x_state *state,
1165e26f2ae4SMichael Krufky 				   int *acq_lock, int *sync_lock)
1166e26f2ae4SMichael Krufky {
1167e26f2ae4SMichael Krufky #ifdef USE_LG2161_LOCK_BITS
1168e26f2ae4SMichael Krufky 	int ret;
1169e26f2ae4SMichael Krufky 	switch (state->cfg->lg_chip) {
1170e26f2ae4SMichael Krufky 	case LG2160:
1171e26f2ae4SMichael Krufky 		ret = lg2160_read_lock_status(state, acq_lock, sync_lock);
1172e26f2ae4SMichael Krufky 		break;
1173e26f2ae4SMichael Krufky 	case LG2161:
1174e26f2ae4SMichael Krufky 		ret = lg2161_read_lock_status(state, acq_lock, sync_lock);
1175e26f2ae4SMichael Krufky 		break;
1176e26f2ae4SMichael Krufky 	default:
1177e26f2ae4SMichael Krufky 		ret = -EINVAL;
1178e26f2ae4SMichael Krufky 		break;
1179e26f2ae4SMichael Krufky 	}
1180e26f2ae4SMichael Krufky 	return ret;
1181e26f2ae4SMichael Krufky #else
1182e26f2ae4SMichael Krufky 	return lg2160_read_lock_status(state, acq_lock, sync_lock);
1183e26f2ae4SMichael Krufky #endif
1184e26f2ae4SMichael Krufky }
1185e26f2ae4SMichael Krufky 
11860df289a2SMauro Carvalho Chehab static int lg216x_read_status(struct dvb_frontend *fe, enum fe_status *status)
1187e26f2ae4SMichael Krufky {
1188e26f2ae4SMichael Krufky 	struct lg216x_state *state = fe->demodulator_priv;
1189e26f2ae4SMichael Krufky 	int ret, acq_lock, sync_lock;
1190e26f2ae4SMichael Krufky 
1191e26f2ae4SMichael Krufky 	*status = 0;
1192e26f2ae4SMichael Krufky 
1193e26f2ae4SMichael Krufky 	ret = lg216x_read_lock_status(state, &acq_lock, &sync_lock);
1194e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1195e26f2ae4SMichael Krufky 		goto fail;
1196e26f2ae4SMichael Krufky 
1197e26f2ae4SMichael Krufky 	lg_dbg("%s%s\n",
1198e26f2ae4SMichael Krufky 	       acq_lock  ? "SIGNALEXIST " : "",
1199e26f2ae4SMichael Krufky 	       sync_lock ? "SYNCLOCK"     : "");
1200e26f2ae4SMichael Krufky 
1201e26f2ae4SMichael Krufky 	if (acq_lock)
1202e26f2ae4SMichael Krufky 		*status |= FE_HAS_SIGNAL;
1203e26f2ae4SMichael Krufky 	if (sync_lock)
1204e26f2ae4SMichael Krufky 		*status |= FE_HAS_SYNC;
1205e26f2ae4SMichael Krufky 
1206e26f2ae4SMichael Krufky 	if (*status)
1207e26f2ae4SMichael Krufky 		*status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK;
1208e26f2ae4SMichael Krufky 
1209e26f2ae4SMichael Krufky fail:
1210e26f2ae4SMichael Krufky 	return ret;
1211e26f2ae4SMichael Krufky }
1212e26f2ae4SMichael Krufky 
1213e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */
1214e26f2ae4SMichael Krufky 
1215e26f2ae4SMichael Krufky static int lg2160_read_snr(struct dvb_frontend *fe, u16 *snr)
1216e26f2ae4SMichael Krufky {
1217e26f2ae4SMichael Krufky 	struct lg216x_state *state = fe->demodulator_priv;
1218e26f2ae4SMichael Krufky 	u8 snr1, snr2;
1219e26f2ae4SMichael Krufky 	int ret;
1220e26f2ae4SMichael Krufky 
1221e26f2ae4SMichael Krufky 	*snr = 0;
1222e26f2ae4SMichael Krufky 
1223e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0202, &snr1);
1224e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1225e26f2ae4SMichael Krufky 		goto fail;
1226e26f2ae4SMichael Krufky 
1227e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0203, &snr2);
1228e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1229e26f2ae4SMichael Krufky 		goto fail;
1230e26f2ae4SMichael Krufky 
1231e26f2ae4SMichael Krufky 	if ((snr1 == 0xba) || (snr2 == 0xdf))
1232e26f2ae4SMichael Krufky 		*snr = 0;
1233e26f2ae4SMichael Krufky 	else
1234e26f2ae4SMichael Krufky #if 1
1235e26f2ae4SMichael Krufky 	*snr =  ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 >> 4);
1236e26f2ae4SMichael Krufky #else /* BCD */
1237e26f2ae4SMichael Krufky 	*snr =  (snr2 | (snr1 << 8));
1238e26f2ae4SMichael Krufky #endif
1239e26f2ae4SMichael Krufky fail:
1240e26f2ae4SMichael Krufky 	return ret;
1241e26f2ae4SMichael Krufky }
1242e26f2ae4SMichael Krufky 
1243e26f2ae4SMichael Krufky static int lg2161_read_snr(struct dvb_frontend *fe, u16 *snr)
1244e26f2ae4SMichael Krufky {
1245e26f2ae4SMichael Krufky 	struct lg216x_state *state = fe->demodulator_priv;
1246e26f2ae4SMichael Krufky 	u8 snr1, snr2;
1247e26f2ae4SMichael Krufky 	int ret;
1248e26f2ae4SMichael Krufky 
1249e26f2ae4SMichael Krufky 	*snr = 0;
1250e26f2ae4SMichael Krufky 
1251e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0302, &snr1);
1252e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1253e26f2ae4SMichael Krufky 		goto fail;
1254e26f2ae4SMichael Krufky 
1255e26f2ae4SMichael Krufky 	ret = lg216x_read_reg(state, 0x0303, &snr2);
1256e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1257e26f2ae4SMichael Krufky 		goto fail;
1258e26f2ae4SMichael Krufky 
1259e26f2ae4SMichael Krufky 	if ((snr1 == 0xba) || (snr2 == 0xfd))
1260e26f2ae4SMichael Krufky 		*snr = 0;
1261e26f2ae4SMichael Krufky 	else
1262e26f2ae4SMichael Krufky 
1263e26f2ae4SMichael Krufky 	*snr =  ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 & 0x0f);
1264e26f2ae4SMichael Krufky fail:
1265e26f2ae4SMichael Krufky 	return ret;
1266e26f2ae4SMichael Krufky }
1267e26f2ae4SMichael Krufky 
1268e26f2ae4SMichael Krufky static int lg216x_read_signal_strength(struct dvb_frontend *fe,
1269e26f2ae4SMichael Krufky 				       u16 *strength)
1270e26f2ae4SMichael Krufky {
1271e26f2ae4SMichael Krufky #if 0
1272e26f2ae4SMichael Krufky 	/* borrowed from lgdt330x.c
1273e26f2ae4SMichael Krufky 	 *
1274e26f2ae4SMichael Krufky 	 * Calculate strength from SNR up to 35dB
1275e26f2ae4SMichael Krufky 	 * Even though the SNR can go higher than 35dB,
1276e26f2ae4SMichael Krufky 	 * there is some comfort factor in having a range of
1277e26f2ae4SMichael Krufky 	 * strong signals that can show at 100%
1278e26f2ae4SMichael Krufky 	 */
1279e26f2ae4SMichael Krufky 	struct lg216x_state *state = fe->demodulator_priv;
1280e26f2ae4SMichael Krufky 	u16 snr;
1281e26f2ae4SMichael Krufky 	int ret;
1282e26f2ae4SMichael Krufky #endif
1283e26f2ae4SMichael Krufky 	*strength = 0;
1284e26f2ae4SMichael Krufky #if 0
1285e26f2ae4SMichael Krufky 	ret = fe->ops.read_snr(fe, &snr);
1286e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1287e26f2ae4SMichael Krufky 		goto fail;
1288e26f2ae4SMichael Krufky 	/* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
1289e26f2ae4SMichael Krufky 	/* scale the range 0 - 35*2^24 into 0 - 65535 */
1290e26f2ae4SMichael Krufky 	if (state->snr >= 8960 * 0x10000)
1291e26f2ae4SMichael Krufky 		*strength = 0xffff;
1292e26f2ae4SMichael Krufky 	else
1293e26f2ae4SMichael Krufky 		*strength = state->snr / 8960;
1294e26f2ae4SMichael Krufky fail:
1295e26f2ae4SMichael Krufky 	return ret;
1296e26f2ae4SMichael Krufky #else
1297e26f2ae4SMichael Krufky 	return 0;
1298e26f2ae4SMichael Krufky #endif
1299e26f2ae4SMichael Krufky }
1300e26f2ae4SMichael Krufky 
1301e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */
1302e26f2ae4SMichael Krufky 
1303e26f2ae4SMichael Krufky static int lg216x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
1304e26f2ae4SMichael Krufky {
13055444a1b7SMauro Carvalho Chehab #if 0
1306e26f2ae4SMichael Krufky 	struct lg216x_state *state = fe->demodulator_priv;
1307e26f2ae4SMichael Krufky 	int ret;
13085444a1b7SMauro Carvalho Chehab 
1309e26f2ae4SMichael Krufky 	ret = lg216x_read_rs_err_count(state,
1310e26f2ae4SMichael Krufky 				       &fe->dtv_property_cache.atscmh_rs_err);
1311e26f2ae4SMichael Krufky 	if (lg_fail(ret))
1312e26f2ae4SMichael Krufky 		goto fail;
1313e26f2ae4SMichael Krufky 
1314e26f2ae4SMichael Krufky 	*ucblocks = fe->dtv_property_cache.atscmh_rs_err;
13155444a1b7SMauro Carvalho Chehab fail:
131610d67371SMichael Krufky #else
131710d67371SMichael Krufky 	*ucblocks = 0;
131810d67371SMichael Krufky #endif
1319e26f2ae4SMichael Krufky 	return 0;
1320e26f2ae4SMichael Krufky }
1321e26f2ae4SMichael Krufky 
1322e26f2ae4SMichael Krufky static int lg216x_get_tune_settings(struct dvb_frontend *fe,
1323e26f2ae4SMichael Krufky 				    struct dvb_frontend_tune_settings
1324e26f2ae4SMichael Krufky 				    *fe_tune_settings)
1325e26f2ae4SMichael Krufky {
1326e26f2ae4SMichael Krufky 	fe_tune_settings->min_delay_ms = 500;
1327e26f2ae4SMichael Krufky 	lg_dbg("\n");
1328e26f2ae4SMichael Krufky 	return 0;
1329e26f2ae4SMichael Krufky }
1330e26f2ae4SMichael Krufky 
1331e26f2ae4SMichael Krufky static void lg216x_release(struct dvb_frontend *fe)
1332e26f2ae4SMichael Krufky {
1333e26f2ae4SMichael Krufky 	struct lg216x_state *state = fe->demodulator_priv;
1334e26f2ae4SMichael Krufky 	lg_dbg("\n");
1335e26f2ae4SMichael Krufky 	kfree(state);
1336e26f2ae4SMichael Krufky }
1337e26f2ae4SMichael Krufky 
1338bd336e63SMax Kellermann static const struct dvb_frontend_ops lg2160_ops = {
1339e26f2ae4SMichael Krufky 	.delsys = { SYS_ATSCMH },
1340e26f2ae4SMichael Krufky 	.info = {
1341e26f2ae4SMichael Krufky 		.name = "LG Electronics LG2160 ATSC/MH Frontend",
1342f1b1eabfSMauro Carvalho Chehab 		.frequency_min_hz      =  54 * MHz,
1343f1b1eabfSMauro Carvalho Chehab 		.frequency_max_hz      = 858 * MHz,
1344f1b1eabfSMauro Carvalho Chehab 		.frequency_stepsize_hz = 62500,
1345e26f2ae4SMichael Krufky 	},
1346e26f2ae4SMichael Krufky 	.i2c_gate_ctrl        = lg216x_i2c_gate_ctrl,
1347e26f2ae4SMichael Krufky #if 0
1348e26f2ae4SMichael Krufky 	.init                 = lg216x_init,
1349e26f2ae4SMichael Krufky 	.sleep                = lg216x_sleep,
1350e26f2ae4SMichael Krufky #endif
1351e26f2ae4SMichael Krufky 	.set_frontend         = lg2160_set_frontend,
1352e26f2ae4SMichael Krufky 	.get_frontend         = lg216x_get_frontend,
1353e26f2ae4SMichael Krufky 	.get_tune_settings    = lg216x_get_tune_settings,
1354e26f2ae4SMichael Krufky 	.read_status          = lg216x_read_status,
1355e26f2ae4SMichael Krufky #if 0
1356e26f2ae4SMichael Krufky 	.read_ber             = lg216x_read_ber,
1357e26f2ae4SMichael Krufky #endif
1358e26f2ae4SMichael Krufky 	.read_signal_strength = lg216x_read_signal_strength,
1359e26f2ae4SMichael Krufky 	.read_snr             = lg2160_read_snr,
1360e26f2ae4SMichael Krufky 	.read_ucblocks        = lg216x_read_ucblocks,
1361e26f2ae4SMichael Krufky 	.release              = lg216x_release,
1362e26f2ae4SMichael Krufky };
1363e26f2ae4SMichael Krufky 
1364bd336e63SMax Kellermann static const struct dvb_frontend_ops lg2161_ops = {
1365e26f2ae4SMichael Krufky 	.delsys = { SYS_ATSCMH },
1366e26f2ae4SMichael Krufky 	.info = {
1367e26f2ae4SMichael Krufky 		.name = "LG Electronics LG2161 ATSC/MH Frontend",
1368f1b1eabfSMauro Carvalho Chehab 		.frequency_min_hz      =  54 * MHz,
1369f1b1eabfSMauro Carvalho Chehab 		.frequency_max_hz      = 858 * MHz,
1370f1b1eabfSMauro Carvalho Chehab 		.frequency_stepsize_hz = 62500,
1371e26f2ae4SMichael Krufky 	},
1372e26f2ae4SMichael Krufky 	.i2c_gate_ctrl        = lg216x_i2c_gate_ctrl,
1373e26f2ae4SMichael Krufky #if 0
1374e26f2ae4SMichael Krufky 	.init                 = lg216x_init,
1375e26f2ae4SMichael Krufky 	.sleep                = lg216x_sleep,
1376e26f2ae4SMichael Krufky #endif
1377e26f2ae4SMichael Krufky 	.set_frontend         = lg2160_set_frontend,
1378e26f2ae4SMichael Krufky 	.get_frontend         = lg216x_get_frontend,
1379e26f2ae4SMichael Krufky 	.get_tune_settings    = lg216x_get_tune_settings,
1380e26f2ae4SMichael Krufky 	.read_status          = lg216x_read_status,
1381e26f2ae4SMichael Krufky #if 0
1382e26f2ae4SMichael Krufky 	.read_ber             = lg216x_read_ber,
1383e26f2ae4SMichael Krufky #endif
1384e26f2ae4SMichael Krufky 	.read_signal_strength = lg216x_read_signal_strength,
1385e26f2ae4SMichael Krufky 	.read_snr             = lg2161_read_snr,
1386e26f2ae4SMichael Krufky 	.read_ucblocks        = lg216x_read_ucblocks,
1387e26f2ae4SMichael Krufky 	.release              = lg216x_release,
1388e26f2ae4SMichael Krufky };
1389e26f2ae4SMichael Krufky 
1390e26f2ae4SMichael Krufky struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
1391e26f2ae4SMichael Krufky 				   struct i2c_adapter *i2c_adap)
1392e26f2ae4SMichael Krufky {
1393e26f2ae4SMichael Krufky 	struct lg216x_state *state = NULL;
1394e26f2ae4SMichael Krufky 
1395e26f2ae4SMichael Krufky 	lg_dbg("(%d-%04x)\n",
1396e26f2ae4SMichael Krufky 	       i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
1397e26f2ae4SMichael Krufky 	       config ? config->i2c_addr : 0);
1398e26f2ae4SMichael Krufky 
1399e26f2ae4SMichael Krufky 	state = kzalloc(sizeof(struct lg216x_state), GFP_KERNEL);
14001a5d2da1SPeter Senna Tschudin 	if (!state)
14011a5d2da1SPeter Senna Tschudin 		return NULL;
1402e26f2ae4SMichael Krufky 
1403e26f2ae4SMichael Krufky 	state->cfg = config;
1404e26f2ae4SMichael Krufky 	state->i2c_adap = i2c_adap;
1405e26f2ae4SMichael Krufky 	state->fic_ver = 0xff;
1406e26f2ae4SMichael Krufky 	state->parade_id = 0xff;
1407e26f2ae4SMichael Krufky 
1408e26f2ae4SMichael Krufky 	switch (config->lg_chip) {
1409e26f2ae4SMichael Krufky 	default:
1410e26f2ae4SMichael Krufky 		lg_warn("invalid chip requested, defaulting to LG2160");
1411*1771e9fbSGustavo A. R. Silva 		fallthrough;
1412e26f2ae4SMichael Krufky 	case LG2160:
1413e26f2ae4SMichael Krufky 		memcpy(&state->frontend.ops, &lg2160_ops,
1414e26f2ae4SMichael Krufky 		       sizeof(struct dvb_frontend_ops));
1415e26f2ae4SMichael Krufky 		break;
1416e26f2ae4SMichael Krufky 	case LG2161:
1417e26f2ae4SMichael Krufky 		memcpy(&state->frontend.ops, &lg2161_ops,
1418e26f2ae4SMichael Krufky 		       sizeof(struct dvb_frontend_ops));
1419e26f2ae4SMichael Krufky 		break;
1420e26f2ae4SMichael Krufky 	}
1421e26f2ae4SMichael Krufky 
1422e26f2ae4SMichael Krufky 	state->frontend.demodulator_priv = state;
1423e26f2ae4SMichael Krufky 	state->current_frequency = -1;
1424e26f2ae4SMichael Krufky 	/* parade 1 by default */
1425e26f2ae4SMichael Krufky 	state->frontend.dtv_property_cache.atscmh_parade_id = 1;
1426e26f2ae4SMichael Krufky 
1427e26f2ae4SMichael Krufky 	return &state->frontend;
1428e26f2ae4SMichael Krufky }
1429e26f2ae4SMichael Krufky EXPORT_SYMBOL(lg2160_attach);
1430e26f2ae4SMichael Krufky 
1431e26f2ae4SMichael Krufky MODULE_DESCRIPTION("LG Electronics LG216x ATSC/MH Demodulator Driver");
1432e26f2ae4SMichael Krufky MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
1433e26f2ae4SMichael Krufky MODULE_LICENSE("GPL");
1434e26f2ae4SMichael Krufky MODULE_VERSION("0.3");
1435