1/*	$NetBSD: zl10353.c,v 1.2 2011/08/29 11:16:35 jruoho Exp $ */
2
3/*-
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jukka Ruohonen.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: zl10353.c,v 1.2 2011/08/29 11:16:35 jruoho Exp $");
34
35#include <sys/param.h>
36#include <sys/kmem.h>
37#include <sys/module.h>
38
39#include <dev/dtv/dtvif.h>
40
41#include <dev/i2c/i2cvar.h>
42#include <dev/i2c/zl10353reg.h>
43#include <dev/i2c/zl10353var.h>
44
45/*
46 * Zarlink ZL10353 demodulator (now known as Intel CE623x).
47 *
48 * An incomplete datasheet:
49 *
50 *	Intel Corporation: CE6230 - COFDM demodulator with
51 *	USB interface for PC-TV. Data Sheet, Revision 1.1.
52 *	March 29, 2007.
53 */
54
55static int	zl10353_probe(struct zl10353 *);
56static int	zl10353_read(struct zl10353 *, uint8_t, uint8_t *);
57static int	zl10353_write(struct zl10353 *, uint8_t, uint8_t);
58static int	zl10353_reset(struct zl10353 *, bool);
59static int	zl10353_set_agc(struct zl10353 *,
60			const struct dvb_frontend_parameters *);
61static int	zl10353_set_bw(struct zl10353 *, fe_bandwidth_t);
62static int	zl10353_set_rate(struct zl10353 *);
63static int	zl10353_set_freq(struct zl10353 *);
64static int	zl10353_set_tps(struct zl10353 *,
65			const struct dvb_frontend_parameters *);
66static int	zl10353_get_guard(fe_guard_interval_t, uint16_t *);
67static int	zl10353_get_mode(fe_transmit_mode_t, uint16_t *);
68static int	zl10353_get_fec(fe_code_rate_t, bool, uint16_t *);
69static int	zl10353_get_modulation(fe_modulation_t, uint16_t *);
70static int	zl10353_get_hier(fe_hierarchy_t, uint16_t *);
71
72struct zl10353 *
73zl10353_open(device_t parent, i2c_tag_t i2c, i2c_addr_t addr)
74{
75	struct zl10353 *zl;
76
77	zl = kmem_zalloc(sizeof(*zl), KM_SLEEP);
78
79	if (zl == NULL)
80		return NULL;
81
82	zl->zl_i2c = i2c;
83	zl->zl_i2c_addr = addr;
84	zl->zl_parent = parent;
85
86	zl->zl_freq = ZL10353_DEFAULT_INPUT_FREQ;
87	zl->zl_clock = ZL10353_DEFAULT_CLOCK_MHZ;
88
89	if (zl10353_reset(zl, true) != 0) {
90		zl10353_close(zl);
91		return NULL;
92	}
93
94	if (zl10353_probe(zl) != 0) {
95		zl10353_close(zl);
96		return NULL;
97	}
98
99	return zl;
100}
101
102void
103zl10353_close(struct zl10353 *zl)
104{
105	kmem_free(zl, sizeof(*zl));
106}
107
108static int
109zl10353_probe(struct zl10353 *zl)
110{
111	uint8_t val;
112	int rv;
113
114	if ((rv = zl10353_read(zl, ZL10353_REG_ID, &val)) != 0)
115		return rv;
116
117	switch (val) {
118
119	case ZL10353_ID_CE6230:
120		zl->zl_name = "Intel CE6230";
121		break;
122
123	case ZL10353_ID_CE6231:
124		zl->zl_name = "Intel CE6231";
125		break;
126
127	case ZL10353_ID_ZL10353:
128		zl->zl_name = "Zarlink ZL10353";
129		break;
130
131	default:
132		aprint_error_dev(zl->zl_parent, "unknown chip 0x%02x\n", val);
133		return ENOTSUP;
134	}
135
136	aprint_verbose_dev(zl->zl_parent, "found %s at i2c "
137	    "addr 0x%02x\n",  zl->zl_name, zl->zl_i2c_addr);
138
139	return 0;
140}
141
142static int
143zl10353_read(struct zl10353 *zl, uint8_t reg, uint8_t *valp)
144{
145	static const i2c_op_t op = I2C_OP_READ;
146	int rv;
147
148	if ((rv = iic_acquire_bus(zl->zl_i2c, 0)) != 0)
149		return rv;
150
151	rv = iic_exec(zl->zl_i2c, op, zl->zl_i2c_addr, &reg, 1, valp, 1, 0);
152	iic_release_bus(zl->zl_i2c, 0);
153
154	return rv;
155}
156
157static int
158zl10353_write(struct zl10353 *zl, uint8_t reg, uint8_t val)
159{
160	static const i2c_op_t op = I2C_OP_WRITE;
161	const uint8_t cmd[2] = { reg, val };
162	int rv;
163
164	if ((rv = iic_acquire_bus(zl->zl_i2c, 0)) != 0)
165		return rv;
166
167	rv = iic_exec(zl->zl_i2c, op, zl->zl_i2c_addr, cmd, 2, NULL, 0, 0);
168	iic_release_bus(zl->zl_i2c, 0);
169
170	return rv;
171}
172
173static int
174zl10353_reset(struct zl10353 *zl, bool hard)
175{
176	size_t i = 0, len = 5;
177	int rv;
178
179	static const struct {
180		uint8_t		reg;
181		uint8_t		val;
182	} reset[] = {
183		{ 0x50, 0x03 },	/* Hard */
184		{ 0x03, 0x44 },
185		{ 0x44, 0x46 },
186		{ 0x46, 0x15 },
187		{ 0x15, 0x0f },
188		{ 0x55, 0x80 },	/* Soft */
189		{ 0xea, 0x01 },
190		{ 0xea, 0x00 },
191	};
192
193	if (hard != true) {
194		len = __arraycount(reset);
195		i = 5;
196	}
197
198	while (i < len) {
199
200		if ((rv = zl10353_write(zl, reset[i].reg, reset[i].val)) != 0)
201			return rv;
202		else {
203			delay(100);
204		}
205
206		i++;
207
208	}
209
210	return 0;
211}
212
213void
214zl10353_get_devinfo(struct dvb_frontend_info *fi)
215{
216
217	fi->type = FE_OFDM;
218
219	fi->frequency_min = 174000000;
220	fi->frequency_max = 862000000;
221
222	fi->frequency_tolerance = 0;
223	fi->frequency_stepsize = 166667;
224
225	fi->caps |= FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
226		    FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_QPSK |
227	            FE_CAN_QAM_16  | FE_CAN_QAM_64  | FE_CAN_RECOVER |
228		    FE_CAN_MUTE_TS;
229
230	fi->caps |= FE_CAN_FEC_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
231		    FE_CAN_QAM_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
232		    FE_CAN_HIERARCHY_AUTO;
233}
234
235int
236zl10353_set_params(struct zl10353 *zl,const struct dvb_frontend_parameters *fp)
237{
238	int rv;
239
240	/* 1. Soft reset. */
241	if ((rv = zl10353_reset(zl, false)) != 0)
242		return rv;
243
244	/* 2. Set AGC. */
245	if ((rv = zl10353_set_agc(zl, fp)) != 0)
246		return rv;
247
248	/* 3. Set bandwidth. */
249	if ((rv = zl10353_set_bw(zl, fp->u.ofdm.bandwidth)) != 0)
250		return rv;
251
252	/* 4. Set nominal rate. */
253	if ((rv = zl10353_set_rate(zl)) != 0)
254		return rv;
255
256	/* 5. Set input frequency. */
257	if ((rv = zl10353_set_freq(zl)) != 0)
258		return rv;
259
260	/* 6. Set TPS parameters. */
261	if ((rv = zl10353_set_tps(zl, fp)) != 0)
262		return rv;
263
264	return 0;
265}
266
267int
268zl10353_set_fsm(struct zl10353 *zl)
269{
270	return zl10353_write(zl, ZL10353_REG_FSM, ZL10353_FSM_START);
271}
272
273int
274zl10353_set_gate(void *aux, bool enable)
275{
276	uint8_t val = ZL10353_GATE_DISABLE;
277
278	if (enable != false)
279		val = ZL10353_GATE_ENABLE;
280
281	return zl10353_write(aux, ZL10353_REG_GATE, val);
282}
283
284static int
285zl10353_set_agc(struct zl10353 *zl, const struct dvb_frontend_parameters *fp)
286{
287	const struct dvb_ofdm_parameters *ofdm = &fp->u.ofdm;
288	uint8_t val = ZL10353_AGC_TARGET_DEFAULT;
289	int rv;
290
291	if ((rv = zl10353_write(zl, ZL10353_REG_AGC_TARGET, val)) != 0)
292		return rv;
293	else {
294		val = 0;
295	}
296
297	if (ofdm->guard_interval != GUARD_INTERVAL_AUTO)
298		val |= ZL10353_AGC_CTRL_GUARD_NONAUTO;
299
300	if (ofdm->transmission_mode != TRANSMISSION_MODE_AUTO)
301		val |= ZL10353_AGC_CTRL_MODE_NONAUTO;
302
303	return zl10353_write(zl, ZL10353_REG_AGC_CTRL, val);
304}
305
306static int
307zl10353_set_bw(struct zl10353 *zl, fe_bandwidth_t bw)
308{
309	uint8_t val[3];
310	int rv;
311
312	switch (bw) {
313
314	case BANDWIDTH_6_MHZ:
315		val[0] = ZL10353_BW_1_6_MHZ;
316		val[1] = ZL10353_BW_2_6_MHZ;
317		val[2] = ZL10353_BW_3_6_MHZ;
318		zl->zl_bw = 6;
319		break;
320
321	case BANDWIDTH_7_MHZ:
322		val[0] = ZL10353_BW_1_7_MHZ;
323		val[1] = ZL10353_BW_2_7_MHZ;
324		val[2] = ZL10353_BW_3_7_MHZ;
325		zl->zl_bw = 7;
326		break;
327
328	case BANDWIDTH_8_MHZ:
329		val[0] = ZL10353_BW_1_8_MHZ;
330		val[1] = ZL10353_BW_2_8_MHZ;
331		val[2] = ZL10353_BW_3_8_MHZ;
332		zl->zl_bw = 8;
333		break;
334
335	default:
336		zl->zl_bw = 0;
337		return EINVAL;
338	}
339
340	if ((rv = zl10353_write(zl, ZL10353_REG_BW_1, val[0])) != 0)
341		return rv;
342
343	if ((rv = zl10353_write(zl, ZL10353_REG_BW_2, val[1])) != 0)
344		return rv;
345
346	if ((rv = zl10353_write(zl, ZL10353_REG_BW_3, val[2])) != 0)
347		return rv;
348
349	return 0;
350}
351
352static int
353zl10353_set_rate(struct zl10353 *zl)
354{
355	static const uint64_t c = 1497965625;
356	uint64_t val;
357	int rv;
358
359	KASSERT(zl->zl_bw >= 6 && zl->zl_bw <= 8);
360	KASSERT(zl->zl_clock > 0 && zl->zl_freq > 0);
361
362	val = zl->zl_bw * c;
363	val += zl->zl_clock >> 1;
364	val /= zl->zl_clock;
365	val = val & 0xffff;
366
367	if ((rv = zl10353_write(zl, ZL10353_REG_RATE_1, val >> 8)) != 0)
368		return rv;
369
370	return zl10353_write(zl, ZL10353_REG_RATE_2, val & 0xff);
371}
372
373static int
374zl10353_set_freq(struct zl10353 *zl)
375{
376	const uint16_t val = zl->zl_freq;
377	int rv;
378
379	if ((rv = zl10353_write(zl, ZL10353_REG_FREQ_1, val >> 8)) != 0)
380		return rv;
381
382	return zl10353_write(zl, ZL10353_REG_FREQ_2, val & 0xff);
383}
384
385static int
386zl10353_set_tps(struct zl10353 *zl, const struct dvb_frontend_parameters *fp)
387{
388	const struct dvb_ofdm_parameters *ofdm = &fp->u.ofdm;
389	uint16_t val = 0;
390	int rv;
391
392	if ((rv = zl10353_get_guard(ofdm->guard_interval, &val)) != 0)
393		goto fail;
394
395	if ((rv = zl10353_get_mode(ofdm->transmission_mode, &val)) != 0)
396		goto fail;
397
398	if ((rv = zl10353_get_fec(ofdm->code_rate_HP, true, &val)) != 0)
399		goto fail;
400
401	if ((rv = zl10353_get_fec(ofdm->code_rate_LP, false, &val)) != 0)
402		goto fail;
403
404	if ((rv = zl10353_get_modulation(ofdm->constellation, &val)) != 0)
405		goto fail;
406
407	if ((rv = zl10353_get_hier(ofdm->hierarchy_information, &val)) != 0)
408		goto fail;
409
410	if ((rv = zl10353_write(zl, ZL10353_REG_TPS_1, val >> 8)) != 0)
411		goto fail;
412
413	if ((rv = zl10353_write(zl, ZL10353_REG_TPS_2, val & 0xff)) != 0)
414		goto fail;
415
416	return 0;
417
418fail:
419	aprint_error_dev(zl->zl_parent, "failed to set "
420	    "tps for %s (err %d)\n", zl->zl_name, rv);
421
422	return rv;
423}
424
425static int
426zl10353_get_guard(fe_guard_interval_t fg, uint16_t *valp)
427{
428
429	switch (fg) {
430
431	case GUARD_INTERVAL_1_4:
432		*valp |= ZL10353_TPS_GUARD_1_4;
433		break;
434
435	case GUARD_INTERVAL_1_8:
436		*valp |= ZL10353_TPS_GUARD_1_8;
437		break;
438
439	case GUARD_INTERVAL_1_16:
440		*valp |= ZL10353_TPS_GUARD_1_16;
441		break;
442
443	case GUARD_INTERVAL_1_32:
444		*valp |= ZL10353_TPS_GUARD_1_32;
445		break;
446
447	case GUARD_INTERVAL_AUTO:
448		*valp |= ZL10353_TPS_GUARD_AUTO;
449		break;
450
451	default:
452		return EINVAL;
453	}
454
455	return 0;
456}
457
458static int
459zl10353_get_mode(fe_transmit_mode_t fm, uint16_t *valp)
460{
461
462	switch (fm) {
463
464	case TRANSMISSION_MODE_2K:
465		*valp |= ZL10353_TPS_MODE_2K;
466		break;
467
468	case TRANSMISSION_MODE_8K:
469		*valp |= ZL10353_TPS_MODE_8K;
470		break;
471
472	case TRANSMISSION_MODE_AUTO:
473		*valp |= ZL10353_TPS_MODE_AUTO;
474		break;
475
476	default:
477		return EINVAL;
478	}
479
480	return 0;
481}
482
483static int
484zl10353_get_fec(fe_code_rate_t fc, bool hp, uint16_t *valp)
485{
486	uint16_t hpval = 0, lpval = 0;
487
488	switch (fc) {
489
490	case FEC_1_2:
491		hpval = ZL10353_TPS_HP_FEC_1_2;
492		lpval = ZL10353_TPS_LP_FEC_1_2;
493		break;
494
495	case FEC_2_3:
496		hpval = ZL10353_TPS_HP_FEC_2_3;
497		lpval = ZL10353_TPS_LP_FEC_2_3;
498		break;
499
500	case FEC_3_4:
501		hpval = ZL10353_TPS_HP_FEC_3_4;
502		lpval = ZL10353_TPS_LP_FEC_3_4;
503		break;
504
505	case FEC_5_6:
506		hpval = ZL10353_TPS_HP_FEC_5_6;
507		lpval = ZL10353_TPS_LP_FEC_5_6;
508		break;
509
510	case FEC_7_8:
511		hpval = ZL10353_TPS_HP_FEC_7_8;
512		lpval = ZL10353_TPS_LP_FEC_7_8;
513		break;
514
515	case FEC_AUTO:
516		hpval = ZL10353_TPS_HP_FEC_AUTO;
517		lpval = ZL10353_TPS_LP_FEC_AUTO;
518		break;
519
520	case FEC_NONE:
521		return EOPNOTSUPP;
522
523	default:
524		return EINVAL;
525	}
526
527	*valp |= (hp != false) ? hpval : lpval;
528
529	return 0;
530}
531
532static int
533zl10353_get_modulation(fe_modulation_t fm, uint16_t *valp)
534{
535
536	switch (fm) {
537
538	case QPSK:
539		*valp |= ZL10353_TPS_MODULATION_QPSK;
540		break;
541
542	case QAM_16:
543		*valp |= ZL10353_TPS_MODULATION_QAM_16;
544		break;
545
546	case QAM_64:
547		*valp |= ZL10353_TPS_MODULATION_QAM_64;
548		break;
549
550	case QAM_AUTO:
551		*valp |= ZL10353_TPS_MODULATION_QAM_AUTO;
552		break;
553
554	default:
555		return EINVAL;
556	}
557
558	return 0;
559}
560
561static int
562zl10353_get_hier(fe_hierarchy_t fh, uint16_t *valp)
563{
564
565	switch (fh) {
566
567	case HIERARCHY_1:
568		*valp |= ZL10353_TPS_HIERARCHY_1;
569		break;
570
571	case HIERARCHY_2:
572		*valp |= ZL10353_TPS_HIERARCHY_2;
573		break;
574
575	case HIERARCHY_4:
576		*valp |= ZL10353_TPS_HIERARCHY_4;
577		break;
578
579	case HIERARCHY_NONE:
580		*valp |= ZL10353_TPS_HIERARCHY_NONE;
581		break;
582
583	case HIERARCHY_AUTO:
584		*valp |= ZL10353_TPS_HIERARCHY_AUTO;
585		break;
586
587	default:
588		return EINVAL;
589	}
590
591	return 0;
592}
593
594fe_status_t
595zl10353_get_status(struct zl10353 *zl)
596{
597	const uint8_t lock = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC;
598	fe_status_t fs = 0;
599	uint8_t val;
600
601	if (zl10353_read(zl, ZL10353_REG_STATUS_LOCK, &val) == 0) {
602
603		if ((val & ZL10353_STATUS_LOCK_ON) != 0)
604			fs |= FE_HAS_LOCK;
605
606		if ((val & ZL10353_STATUS_LOCK_CARRIER) != 0)
607			fs |= FE_HAS_CARRIER;
608
609		if ((val & ZL10353_STATUS_LOCK_VITERBI) != 0)
610			fs |= FE_HAS_VITERBI;
611	}
612
613	if (zl10353_read(zl, ZL10353_REG_STATUS_SYNC, &val) == 0) {
614
615		if ((val & ZL10353_STATUS_SYNC_ON) != 0)
616			fs |= FE_HAS_SYNC;
617	}
618
619	if (zl10353_read(zl, ZL10353_REG_STATUS_SIGNAL, &val) == 0) {
620
621		if ((val & ZL10353_STATUS_SIGNAL_ON) != 0)
622			fs |= FE_HAS_SIGNAL;
623	}
624
625	return ((fs & lock) != lock) ? fs & ~FE_HAS_LOCK : fs;
626};
627
628uint16_t
629zl10353_get_signal_strength(struct zl10353 *zl)
630{
631	uint8_t val1, val2;
632
633	if (zl10353_read(zl, ZL10353_REG_SIGSTR_1, &val1) != 0)
634		return 0;
635
636	if (zl10353_read(zl, ZL10353_REG_SIGSTR_2, &val2) != 0)
637		return 0;
638
639	return val1 << 10 | val2 << 2 | 0x03;
640}
641
642uint16_t
643zl10353_get_snr(struct zl10353 *zl)
644{
645	uint8_t val;
646
647	if (zl10353_read(zl, ZL10353_REG_SNR, &val) != 0)
648		return 0;
649
650	return (val << 8) | val;
651}
652
653MODULE(MODULE_CLASS_DRIVER, zl10353, "iic");
654
655static int
656zl10353_modcmd(modcmd_t cmd, void *aux)
657{
658
659	if (cmd != MODULE_CMD_INIT && cmd != MODULE_CMD_FINI)
660		return ENOTTY;
661
662	return 0;
663}
664