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