xref: /netbsd-src/sys/dev/i2c/nxt2k.c (revision 13cf28f27de6527817385b2f6c373c0faddaf31a)
1*13cf28f2Sthorpej /* $NetBSD: nxt2k.c,v 1.7 2019/12/31 14:27:50 thorpej Exp $ */
2ea0121ebSjakllsch 
3ea0121ebSjakllsch /*
4ea0121ebSjakllsch  * Copyright (c) 2008, 2011 Jonathan A. Kollasch
5ea0121ebSjakllsch  * All rights reserved.
6ea0121ebSjakllsch  *
7ea0121ebSjakllsch  * Redistribution and use in source and binary forms, with or without
8ea0121ebSjakllsch  * modification, are permitted provided that the following conditions
9ea0121ebSjakllsch  * are met:
10ea0121ebSjakllsch  * 1. Redistributions of source code must retain the above copyright
11ea0121ebSjakllsch  *    notice, this list of conditions and the following disclaimer.
12ea0121ebSjakllsch  * 2. Redistributions in binary form must reproduce the above copyright
13ea0121ebSjakllsch  *    notice, this list of conditions and the following disclaimer in the
14ea0121ebSjakllsch  *    documentation and/or other materials provided with the distribution.
15ea0121ebSjakllsch  *
16ea0121ebSjakllsch  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17ea0121ebSjakllsch  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18ea0121ebSjakllsch  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19ea0121ebSjakllsch  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20ea0121ebSjakllsch  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21ea0121ebSjakllsch  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22ea0121ebSjakllsch  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23ea0121ebSjakllsch  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24ea0121ebSjakllsch  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25ea0121ebSjakllsch  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26ea0121ebSjakllsch  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27ea0121ebSjakllsch  */
28ea0121ebSjakllsch 
29ea0121ebSjakllsch #include <sys/cdefs.h>
30*13cf28f2Sthorpej __KERNEL_RCSID(0, "$NetBSD: nxt2k.c,v 1.7 2019/12/31 14:27:50 thorpej Exp $");
31ea0121ebSjakllsch 
32ea0121ebSjakllsch #include <sys/param.h>
33ea0121ebSjakllsch #include <sys/kernel.h>
34ea0121ebSjakllsch #include <sys/systm.h>
35ea0121ebSjakllsch #include <sys/device.h>
36ea0121ebSjakllsch #include <sys/kmem.h>
37ea0121ebSjakllsch #include <sys/condvar.h>
38ea0121ebSjakllsch #include <sys/mutex.h>
39a0f539c0Sjmcneill #include <sys/module.h>
40ea0121ebSjakllsch 
41ea0121ebSjakllsch #include <dev/firmload.h>
42ea0121ebSjakllsch 
43ea0121ebSjakllsch #include <dev/i2c/nxt2kvar.h>
44ea0121ebSjakllsch 
45ea0121ebSjakllsch struct nxt2k {
46ea0121ebSjakllsch 	device_t        parent;
47ea0121ebSjakllsch 	i2c_tag_t       tag;
48ea0121ebSjakllsch 	i2c_addr_t      addr;
49ea0121ebSjakllsch 	kcondvar_t      cv;
50ea0121ebSjakllsch 	kmutex_t        mtx;
51ea0121ebSjakllsch 	bool            loaded; /* firmware is loaded? */
52ea0121ebSjakllsch };
53ea0121ebSjakllsch 
54ea0121ebSjakllsch static int nxt2k_init(struct nxt2k *);
55ea0121ebSjakllsch 
56ea0121ebSjakllsch static int nxt2k_writedata(struct nxt2k *, uint8_t, uint8_t *, size_t);
57ea0121ebSjakllsch static int nxt2k_readdata(struct nxt2k *, uint8_t, uint8_t *, size_t);
58ea0121ebSjakllsch static int nxt2k_writereg(struct nxt2k *, uint8_t, uint8_t *, size_t);
59ea0121ebSjakllsch static int nxt2k_readreg(struct nxt2k*, uint8_t, uint8_t *, size_t);
60ea0121ebSjakllsch 
61ea0121ebSjakllsch static int nxt2k4_init(struct nxt2k *);
62ea0121ebSjakllsch static bool nxt2k4_load_firmware(struct nxt2k *);
63ea0121ebSjakllsch static void nxt2k4_mc_init(struct nxt2k *);
64ea0121ebSjakllsch static void nxt2k_mc_start(struct nxt2k *);
65ea0121ebSjakllsch static void nxt2k_mc_stop(struct nxt2k *);
66ea0121ebSjakllsch static void nxt2k_agc_reset(struct nxt2k *);
67ea0121ebSjakllsch static uint16_t nxt2k_crc_ccit(uint16_t, uint8_t);
68ea0121ebSjakllsch 
69ea0121ebSjakllsch static int
nxt2k_writedata(struct nxt2k * nxt,uint8_t reg,uint8_t * data,size_t len)70ea0121ebSjakllsch nxt2k_writedata(struct nxt2k *nxt, uint8_t reg, uint8_t *data, size_t len)
71ea0121ebSjakllsch {
72ea0121ebSjakllsch 	uint8_t buffer[384];
73ea0121ebSjakllsch 	int error;
74ea0121ebSjakllsch 
75ea0121ebSjakllsch 	KASSERT((len + 1) <= 384);
76ea0121ebSjakllsch 
77*13cf28f2Sthorpej 	if ((error = iic_acquire_bus(nxt->tag, 0)) != 0)
78184d0520Sthorpej 		return error;
79ea0121ebSjakllsch 
80ea0121ebSjakllsch 	buffer[0] = reg;
81ea0121ebSjakllsch 	memcpy(&buffer[1], data, len);
82ea0121ebSjakllsch 
83ea0121ebSjakllsch 	error = iic_exec(nxt->tag, I2C_OP_WRITE_WITH_STOP, nxt->addr,
84184d0520Sthorpej 			 buffer, len + 1, NULL, 0, 0);
85ea0121ebSjakllsch 
86184d0520Sthorpej 	iic_release_bus(nxt->tag, 0);
87ea0121ebSjakllsch 
88ea0121ebSjakllsch 	return error;
89ea0121ebSjakllsch }
90ea0121ebSjakllsch 
91ea0121ebSjakllsch static int
nxt2k_readdata(struct nxt2k * nxt,uint8_t reg,uint8_t * data,size_t len)92ea0121ebSjakllsch nxt2k_readdata(struct nxt2k *nxt, uint8_t reg, uint8_t *data, size_t len)
93ea0121ebSjakllsch {
94ea0121ebSjakllsch 	int error;
95ea0121ebSjakllsch 
96*13cf28f2Sthorpej 	if ((error = iic_acquire_bus(nxt->tag, 0)) != 0)
97184d0520Sthorpej 		return error;
98ea0121ebSjakllsch 
99ea0121ebSjakllsch 	error = iic_exec(nxt->tag, I2C_OP_READ_WITH_STOP, nxt->addr,
100184d0520Sthorpej 			 &reg, 1, data, len, 0);
101ea0121ebSjakllsch 
102184d0520Sthorpej 	iic_release_bus(nxt->tag, 0);
103ea0121ebSjakllsch 
104ea0121ebSjakllsch 	return error;
105ea0121ebSjakllsch }
106ea0121ebSjakllsch 
107ea0121ebSjakllsch static int
nxt2k_writereg(struct nxt2k * nxt,uint8_t reg,uint8_t * data,size_t len)108ea0121ebSjakllsch nxt2k_writereg(struct nxt2k *nxt, uint8_t reg, uint8_t *data, size_t len)
109ea0121ebSjakllsch {
110ea0121ebSjakllsch 	uint8_t attr, len2, buf;
111ea0121ebSjakllsch 
112ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x35, &reg, 1);
113ea0121ebSjakllsch 
114ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x36, data, len);
115ea0121ebSjakllsch 
116ea0121ebSjakllsch 	attr = 0x02;
117ea0121ebSjakllsch 	if (reg & 0x80) {
118ea0121ebSjakllsch 		attr = attr << 1;
119ea0121ebSjakllsch 		if (reg & 0x04)
120ea0121ebSjakllsch 			attr = attr >> 1;
121ea0121ebSjakllsch 	}
122ea0121ebSjakllsch 	len2 = ((attr << 4) | 0x10) | len;
123ea0121ebSjakllsch 	buf = 0x80;
124ea0121ebSjakllsch 
125ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x34, &len2, 1);
126ea0121ebSjakllsch 
127ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x21, &buf, 1);
128ea0121ebSjakllsch 
129ea0121ebSjakllsch 	nxt2k_readdata(nxt, 0x21, &buf, 1);
130ea0121ebSjakllsch 
131ea0121ebSjakllsch 	if (buf == 0)
132ea0121ebSjakllsch 		return 0;
133ea0121ebSjakllsch 
134ea0121ebSjakllsch 	return -1;
135ea0121ebSjakllsch }
136ea0121ebSjakllsch 
137ea0121ebSjakllsch static int
nxt2k_readreg(struct nxt2k * nxt,uint8_t reg,uint8_t * data,size_t len)138ea0121ebSjakllsch nxt2k_readreg(struct nxt2k *nxt, uint8_t reg, uint8_t *data, size_t len)
139ea0121ebSjakllsch {
140ea0121ebSjakllsch 	uint8_t buf, len2, attr;
141a0f539c0Sjmcneill 	unsigned int i;
142ea0121ebSjakllsch 
143ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x35, &reg, 1);
144ea0121ebSjakllsch 
145ea0121ebSjakllsch 	attr = 0x02;
146ea0121ebSjakllsch 	if (reg & 0x80) {
147ea0121ebSjakllsch 		attr = attr << 1;
148ea0121ebSjakllsch 		if (reg & 0x04)
149ea0121ebSjakllsch 			attr = attr >> 1;
150ea0121ebSjakllsch 	}
151ea0121ebSjakllsch 
152ea0121ebSjakllsch 	len2 = (attr << 4) | len;
153ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x34, &len2, 1);
154ea0121ebSjakllsch 
155ea0121ebSjakllsch 	buf = 0x80;
156ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x21, &buf, 1);
157ea0121ebSjakllsch 
158ea0121ebSjakllsch 	for(i = 0; i < len; i++) {
159ea0121ebSjakllsch 		nxt2k_readdata(nxt, 0x36+i, &data[i], 1);
160ea0121ebSjakllsch 	}
161ea0121ebSjakllsch 
162ea0121ebSjakllsch 	return 0;
163ea0121ebSjakllsch }
164ea0121ebSjakllsch 
165ea0121ebSjakllsch static void
nxt2k_agc_reset(struct nxt2k * nxt)166ea0121ebSjakllsch nxt2k_agc_reset(struct nxt2k *nxt)
167ea0121ebSjakllsch {
168ea0121ebSjakllsch 	uint8_t byte;
169ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x08, &byte, 1);
170ea0121ebSjakllsch 	byte = 0x08;
171ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x08, &byte, 1);
172ea0121ebSjakllsch 	byte = 0x00;
173ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x08, &byte, 1);
174ea0121ebSjakllsch 	return;
175ea0121ebSjakllsch }
176ea0121ebSjakllsch 
177ea0121ebSjakllsch static void
nxt2k_mc_stop(struct nxt2k * nxt)178ea0121ebSjakllsch nxt2k_mc_stop(struct nxt2k *nxt)
179ea0121ebSjakllsch {
180ea0121ebSjakllsch 	int counter;
181ea0121ebSjakllsch 	uint8_t stopval, buf;
182ea0121ebSjakllsch 
183ea0121ebSjakllsch 	/* 2k4 */
184ea0121ebSjakllsch 	stopval = 0x10;
185ea0121ebSjakllsch 
186ea0121ebSjakllsch 	buf = 0x80;
187ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x22, &buf, 1);
188ea0121ebSjakllsch 
189ea0121ebSjakllsch 	for(counter = 0; counter < 20; counter++) {
190ea0121ebSjakllsch 		nxt2k_readdata(nxt, 0x31, &buf, 1);
191ea0121ebSjakllsch 		if (buf & stopval)
192ea0121ebSjakllsch 			return;
193ea0121ebSjakllsch 		mutex_enter(&nxt->mtx);
194ea0121ebSjakllsch 		cv_timedwait(&nxt->cv, &nxt->mtx, mstohz(10));
195ea0121ebSjakllsch 		mutex_exit(&nxt->mtx);
196ea0121ebSjakllsch 	}
197ea0121ebSjakllsch 
198ea0121ebSjakllsch 	printf("%s timeout\n", __func__);
199ea0121ebSjakllsch 
200ea0121ebSjakllsch 	return;
201ea0121ebSjakllsch }
202ea0121ebSjakllsch 
203ea0121ebSjakllsch static void
nxt2k_mc_start(struct nxt2k * nxt)204ea0121ebSjakllsch nxt2k_mc_start(struct nxt2k *nxt)
205ea0121ebSjakllsch {
206ea0121ebSjakllsch 	uint8_t buf;
207ea0121ebSjakllsch 
208ea0121ebSjakllsch 	buf = 0x00;
209ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x22, &buf, 1);
210ea0121ebSjakllsch }
211ea0121ebSjakllsch 
212ea0121ebSjakllsch static void
nxt2k4_mc_init(struct nxt2k * nxt)213ea0121ebSjakllsch nxt2k4_mc_init(struct nxt2k *nxt)
214ea0121ebSjakllsch {
215ea0121ebSjakllsch 	uint8_t byte;
216ea0121ebSjakllsch 	uint8_t data[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xC0};
217ea0121ebSjakllsch 	int counter;
218ea0121ebSjakllsch 
219ea0121ebSjakllsch 	byte = 0x00;
220ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x2b, &byte, 1);
221ea0121ebSjakllsch 	byte = 0x70;
222ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x34, &byte, 1);
223ea0121ebSjakllsch 	byte = 0x04;
224ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x35, &byte, 1);
225ea0121ebSjakllsch 
226ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x36, data, 9);
227ea0121ebSjakllsch 
228ea0121ebSjakllsch 	byte = 0x80;
229ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x21, &byte, 1);
230ea0121ebSjakllsch 
231ea0121ebSjakllsch 	for(counter = 0; counter < 20; counter++) {
232ea0121ebSjakllsch 		nxt2k_readdata(nxt, 0x21, &byte, 1);
233ea0121ebSjakllsch 		if ( byte == 0 )
234ea0121ebSjakllsch 			return;
235ea0121ebSjakllsch 		mutex_enter(&nxt->mtx);
236ea0121ebSjakllsch 		cv_timedwait(&nxt->cv, &nxt->mtx, mstohz(25));
237ea0121ebSjakllsch 		mutex_exit(&nxt->mtx);
238ea0121ebSjakllsch 	}
239ea0121ebSjakllsch 
240ea0121ebSjakllsch 	printf("%s timeout\n", __func__);
241ea0121ebSjakllsch 
242ea0121ebSjakllsch 	return;
243ea0121ebSjakllsch }
244ea0121ebSjakllsch 
245ea0121ebSjakllsch /* CRC-CCIT */
246ea0121ebSjakllsch static uint16_t
nxt2k_crc_ccit(uint16_t crc,uint8_t byte)247ea0121ebSjakllsch nxt2k_crc_ccit(uint16_t crc, uint8_t byte)
248ea0121ebSjakllsch {
249ea0121ebSjakllsch 	int i;
250ea0121ebSjakllsch 	uint16_t input;
251ea0121ebSjakllsch 
252ea0121ebSjakllsch 	input = byte << 8;
253ea0121ebSjakllsch 
254ea0121ebSjakllsch 	for(i = 0; i < 8; i++) {
255ea0121ebSjakllsch 		if ((crc ^ input) & 0x8000)
256ea0121ebSjakllsch 			crc = (crc << 1) ^ 0x1021;
257ea0121ebSjakllsch 		else
258ea0121ebSjakllsch 			crc = (crc << 1);
259ea0121ebSjakllsch 		input = input << 1;
260ea0121ebSjakllsch 	}
261ea0121ebSjakllsch 	return crc;
262ea0121ebSjakllsch }
263ea0121ebSjakllsch 
264ea0121ebSjakllsch static bool
nxt2k4_load_firmware(struct nxt2k * nxt)265ea0121ebSjakllsch nxt2k4_load_firmware(struct nxt2k *nxt)
266ea0121ebSjakllsch {
267ea0121ebSjakllsch 	firmware_handle_t fh;
268ea0121ebSjakllsch 	uint8_t *blob;
269ea0121ebSjakllsch 	size_t fwsize;
270ea0121ebSjakllsch 	size_t position;
271ea0121ebSjakllsch 	int error;
272ea0121ebSjakllsch 	uint16_t crc;
273ea0121ebSjakllsch 
274ea0121ebSjakllsch 	error = firmware_open("nxt2k", "dvb-fe-nxt2004.fw", &fh);
275ea0121ebSjakllsch 	if (error != 0) {
276ea0121ebSjakllsch 		printf("nxt2k firmware_open fail %d\n", error);
277ea0121ebSjakllsch 		return 0;
278ea0121ebSjakllsch 	}
279ea0121ebSjakllsch 
280ea0121ebSjakllsch 	fwsize = firmware_get_size(fh);
281ea0121ebSjakllsch 	printf("fwsize %zd\n", fwsize);
282ea0121ebSjakllsch 	blob = firmware_malloc(fwsize);
283ea0121ebSjakllsch 	if ( blob == NULL ) {
284ea0121ebSjakllsch 		printf("nxt2k firmware_malloc fail\n");
285ea0121ebSjakllsch 		firmware_close(fh);
286ea0121ebSjakllsch 		return -1;
287ea0121ebSjakllsch 	}
288ea0121ebSjakllsch 
289ea0121ebSjakllsch 	error = firmware_read(fh, 0, blob, fwsize);
290ea0121ebSjakllsch 	if (error != 0) {
291ea0121ebSjakllsch 		printf("nxt2k firmware_read fail %d\n", error);
292ea0121ebSjakllsch 		firmware_free(blob, fwsize);
293ea0121ebSjakllsch 		firmware_close(fh);
294ea0121ebSjakllsch 		return -1;
295ea0121ebSjakllsch 	}
296ea0121ebSjakllsch 
297ea0121ebSjakllsch 	/* calculate CRC */
298ea0121ebSjakllsch 	crc = 0;
299ea0121ebSjakllsch 	for(position = 0; position < fwsize; position++) {
300ea0121ebSjakllsch 		crc = nxt2k_crc_ccit(crc, blob[position]);
301ea0121ebSjakllsch 	}
302ea0121ebSjakllsch 	printf("nxt2k firmware crc is %02x\n", crc);
303ea0121ebSjakllsch 
304ea0121ebSjakllsch 	uint16_t rambase;
305ea0121ebSjakllsch 	uint8_t buf[3];
306ea0121ebSjakllsch 
307ea0121ebSjakllsch 	rambase = 0x1000;
308ea0121ebSjakllsch 
309ea0121ebSjakllsch 	/* hold the micro in reset while loading firmware */
310ea0121ebSjakllsch 	buf[0] = 0x80;
311ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x2b, buf, 1);
312ea0121ebSjakllsch 
313ea0121ebSjakllsch 	buf[0] = rambase >> 8;
314ea0121ebSjakllsch 	buf[1] = rambase & 0xFF;
315ea0121ebSjakllsch 	buf[2] = 0x81;
316ea0121ebSjakllsch 	/* write starting address */
317ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x29, buf, 3);
318ea0121ebSjakllsch 
319ea0121ebSjakllsch 	position = 0;
320ea0121ebSjakllsch 
321ea0121ebSjakllsch 	size_t xfercnt;
322ea0121ebSjakllsch 
323ea0121ebSjakllsch 	while ( position < fwsize ) {
324ea0121ebSjakllsch 		xfercnt = fwsize - position > 255 ? 255 : fwsize - position;
325ea0121ebSjakllsch 		nxt2k_writedata(nxt, 0x2c, &blob[position], xfercnt);
326ea0121ebSjakllsch 		position += xfercnt;
327ea0121ebSjakllsch 	}
328ea0121ebSjakllsch 
329ea0121ebSjakllsch 	/* write crc */
330ea0121ebSjakllsch         buf[0] = crc >> 8;
331ea0121ebSjakllsch         buf[1] = crc & 0xFF;
332ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x2c, buf, 2);
333ea0121ebSjakllsch 
334ea0121ebSjakllsch 	/* do a read to stop things */
335ea0121ebSjakllsch 	nxt2k_readdata(nxt, 0x2c, buf, 1);
336ea0121ebSjakllsch 
337ea0121ebSjakllsch 	/* set transfer mode to complete */
338ea0121ebSjakllsch 	buf[0] = 0x80;
339ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x2b, buf, 1);
340ea0121ebSjakllsch 
341ea0121ebSjakllsch 	firmware_free(blob, fwsize);
342ea0121ebSjakllsch 	firmware_close(fh);
343ea0121ebSjakllsch 
344ea0121ebSjakllsch 	return 1;
345ea0121ebSjakllsch }
346ea0121ebSjakllsch 
347ea0121ebSjakllsch static int
nxt2k4_init(struct nxt2k * nxt)348ea0121ebSjakllsch nxt2k4_init(struct nxt2k *nxt)
349ea0121ebSjakllsch {
350ea0121ebSjakllsch 	int success;
351ea0121ebSjakllsch 	uint8_t buf[3];
352ea0121ebSjakllsch 
353ea0121ebSjakllsch 	buf[0] = 0x00;
354ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x1e, buf, 1);
355ea0121ebSjakllsch 
356ea0121ebSjakllsch 	/* try to load firmware */
357ea0121ebSjakllsch 	nxt->loaded = nxt2k4_load_firmware(nxt);
358ea0121ebSjakllsch 	if (nxt->loaded == false)
359ea0121ebSjakllsch 		return ECANCELED;
360ea0121ebSjakllsch 
361ea0121ebSjakllsch 	/* ensure transfer is complete */
362ea0121ebSjakllsch 	buf[0] = 0x01;
363ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x19, buf, 1);
364ea0121ebSjakllsch 
365ea0121ebSjakllsch 	nxt2k4_mc_init(nxt);
366ea0121ebSjakllsch 	nxt2k_mc_stop(nxt);
367ea0121ebSjakllsch 	nxt2k_mc_stop(nxt);
368ea0121ebSjakllsch 	nxt2k4_mc_init(nxt);
369ea0121ebSjakllsch 	nxt2k_mc_stop(nxt);
370ea0121ebSjakllsch 
371ea0121ebSjakllsch 	buf[0] = 0xff;
372ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x08, buf, 1);
373ea0121ebSjakllsch 	buf[0] = 0x00;
374ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x08, buf, 1);
375ea0121ebSjakllsch 
376ea0121ebSjakllsch 	buf[0] = 0xD7;
377ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0xd7, buf, 1);
378ea0121ebSjakllsch 
379ea0121ebSjakllsch 	buf[0] = 0x07;
380ea0121ebSjakllsch 	buf[1] = 0xfe;
381ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x35, buf, 2);
382ea0121ebSjakllsch 	buf[0] = 0x12;
383ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x34, buf, 1);
384ea0121ebSjakllsch 	buf[0] = 0x80;
385ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x21, buf, 1);
386ea0121ebSjakllsch 
387ea0121ebSjakllsch 	buf[0] = 0x21;
388ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x0a, buf, 1);
389ea0121ebSjakllsch 
390ea0121ebSjakllsch 	buf[0] = 0x01;
391ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x80, buf, 1);
392ea0121ebSjakllsch 
393ea0121ebSjakllsch 	/* fec mpeg mode */
394ea0121ebSjakllsch 	buf[0] = 0x7E;
395ea0121ebSjakllsch 	buf[1] = 0x00;
396ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0xe9, buf, 2);
397ea0121ebSjakllsch 
398ea0121ebSjakllsch 	/* mux selection */
399ea0121ebSjakllsch 	buf[0] = 0x00;
400ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0xcc, buf, 1);
401ea0121ebSjakllsch 
402ea0121ebSjakllsch 	/* */
403ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x80, buf, 1);
404ea0121ebSjakllsch 	buf[0] = 0x00;
405ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x80, buf, 1);
406ea0121ebSjakllsch 
407ea0121ebSjakllsch 	/* soft reset? */
408ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x08, buf, 1);
409ea0121ebSjakllsch 	buf[0] = 0x10;
410ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x08, buf, 1);
411ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x08, buf, 1);
412ea0121ebSjakllsch 	buf[0] = 0x00;
413ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x08, buf, 1);
414ea0121ebSjakllsch 
415ea0121ebSjakllsch 	/* */
416ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x80, buf, 1);
417ea0121ebSjakllsch 	buf[0] = 0x01;
418ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x80, buf, 1);
419ea0121ebSjakllsch 	buf[0] = 0x70;
420ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x81, buf, 1);
421ea0121ebSjakllsch 	buf[0] = 0x31; buf[1] = 0x5E; buf[2] = 0x66;
422ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x82, buf, 3);
423ea0121ebSjakllsch 
424ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x88, buf, 1);
425ea0121ebSjakllsch 	buf[0] = 0x11;
426ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x88, buf, 1);
427ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x80, buf, 1);
428ea0121ebSjakllsch 	buf[0] = 0x40;
429ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x80, buf, 1);
430ea0121ebSjakllsch 
431ea0121ebSjakllsch 	nxt2k_readdata(nxt, 0x10, buf, 1);
432ea0121ebSjakllsch 	buf[0] = 0x10;
433ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x10, buf, 1);
434ea0121ebSjakllsch 	nxt2k_readdata(nxt, 0x0a, buf, 1);
435ea0121ebSjakllsch 	buf[0] = 0x21;
436ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x0a, buf, 1);
437ea0121ebSjakllsch 
438ea0121ebSjakllsch 	nxt2k4_mc_init(nxt);
439ea0121ebSjakllsch 
440ea0121ebSjakllsch 	buf[0] = 0x21;
441ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x0a, buf, 1);
442ea0121ebSjakllsch 	buf[0] = 0x7e;
443ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0xe9, buf, 1);
444ea0121ebSjakllsch 	buf[0] = 0x00;
445ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0xea, buf, 1);
446ea0121ebSjakllsch 
447ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x80, buf, 1);
448ea0121ebSjakllsch 	buf[0] = 0x00;
449ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x80, buf, 1);
450ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x80, buf, 1);
451ea0121ebSjakllsch 	buf[0] = 0x00;
452ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x80, buf, 1);
453ea0121ebSjakllsch 
454ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x08, buf, 1);
455ea0121ebSjakllsch 	buf[0] = 0x10;
456ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x08, buf, 1);
457ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x08, buf, 1);
458ea0121ebSjakllsch 	buf[0] = 0x00;
459ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x08, buf, 1);
460ea0121ebSjakllsch 
461ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x80, buf, 1);
462ea0121ebSjakllsch 	buf[0] = 0x04;
463ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x80, buf, 1);
464ea0121ebSjakllsch 	buf[0] = 0x00;
465ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x81, buf, 1);
466ea0121ebSjakllsch 	buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;
467ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x82, buf, 3);
468ea0121ebSjakllsch 
469ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x88, buf, 1);
470ea0121ebSjakllsch 	buf[0] = 0x11;
471ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x88, buf, 1);
472ea0121ebSjakllsch 
473ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x80, buf, 1);
474ea0121ebSjakllsch 	buf[0] = 0x44;
475ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x80, buf, 1);
476ea0121ebSjakllsch 
477ea0121ebSjakllsch 	/* init tuner */
478ea0121ebSjakllsch 	nxt2k_readdata(nxt, 0x10, buf, 1);
479ea0121ebSjakllsch 	buf[0] = 0x12;
480ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x10, buf,1);
481ea0121ebSjakllsch 	buf[0] = 0x04;
482ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x13, buf,1);
483ea0121ebSjakllsch 	buf[0] = 0x00;
484ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x16, buf,1);
485ea0121ebSjakllsch 	buf[0] = 0x04;
486ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x14, buf,1);
487ea0121ebSjakllsch 	buf[0] = 0x00;
488ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x14, buf,1);
489ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x17, buf,1);
490ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x14, buf,1);
491ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x17, buf,1);
492ea0121ebSjakllsch 
493ea0121ebSjakllsch 	success = 1;
494ea0121ebSjakllsch 	return success;
495ea0121ebSjakllsch }
496ea0121ebSjakllsch 
497ea0121ebSjakllsch uint16_t
nxt2k_get_signal(struct nxt2k * nxt)498ea0121ebSjakllsch nxt2k_get_signal(struct nxt2k *nxt)
499ea0121ebSjakllsch {
500ea0121ebSjakllsch 	uint16_t temp;
501ea0121ebSjakllsch 	uint8_t b[2];
502ea0121ebSjakllsch 
503ea0121ebSjakllsch 	b[0] = 0x00;
504ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0xa1, b, 1);
505ea0121ebSjakllsch 
506ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0xa6, b, 2);
507ea0121ebSjakllsch 
508ea0121ebSjakllsch 	temp = (b[0] << 8) | b[1];
509ea0121ebSjakllsch 
510ea0121ebSjakllsch 	printf("a6: %04hx\n", temp);
511ea0121ebSjakllsch 
512ea0121ebSjakllsch 	return 0x7fff - temp * 16;
513ea0121ebSjakllsch }
514ea0121ebSjakllsch 
515ea0121ebSjakllsch uint16_t
nxt2k_get_snr(struct nxt2k * nxt)516ea0121ebSjakllsch nxt2k_get_snr(struct nxt2k *nxt)
517ea0121ebSjakllsch {
518ea0121ebSjakllsch 	uint32_t tsnr;
519ea0121ebSjakllsch 	uint16_t temp, temp2;
520ea0121ebSjakllsch 	uint8_t b[2];
521ea0121ebSjakllsch 
522ea0121ebSjakllsch 	b[0] = 0x00;
523ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0xa1, b, 1);
524ea0121ebSjakllsch 
525ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0xa6, b, 2);
526ea0121ebSjakllsch 
527ea0121ebSjakllsch 	temp = (b[0] << 8) | b[1];
528ea0121ebSjakllsch 
529ea0121ebSjakllsch 	temp2 = 0x7fff - temp;
530ea0121ebSjakllsch 
531ea0121ebSjakllsch 	printf("snr temp2: %04hx\n", temp2);
532ea0121ebSjakllsch 
533ea0121ebSjakllsch 	if (temp2 > 0x7f00)
534ea0121ebSjakllsch 		tsnr = 1000*24+(1000*(30-24)*(temp2-0x7f00)/(0x7fff-0x7f00));
535ea0121ebSjakllsch 	else if ( temp2 > 0x7ec0)
536ea0121ebSjakllsch 		tsnr = 1000*18+(1000*(24-18)*(temp2-0x7ec0)/(0x7f00-0x7ec0));
537ea0121ebSjakllsch 	else if ( temp2 > 0x7c00)
538ea0121ebSjakllsch 		tsnr = 1000*12+(1000*(18-12)*(temp2-0x7c00)/(0x7ec0-0x7c00));
539ea0121ebSjakllsch 	else
540ea0121ebSjakllsch 		tsnr = 1000*0+(1000*(12-0)*(temp2-0)/(0x7c00-0));
541ea0121ebSjakllsch 
542ea0121ebSjakllsch 	printf("snr tsnr: %08x\n", tsnr);
543ea0121ebSjakllsch 
544ea0121ebSjakllsch 	return ((tsnr * 0xffff)/32000);
545ea0121ebSjakllsch }
546ea0121ebSjakllsch 
547ea0121ebSjakllsch fe_status_t
nxt2k_get_dtv_status(struct nxt2k * nxt)548ea0121ebSjakllsch nxt2k_get_dtv_status(struct nxt2k *nxt)
549ea0121ebSjakllsch {
550ea0121ebSjakllsch 	uint8_t reg;
551ea0121ebSjakllsch 	fe_status_t status = 0;
552ea0121ebSjakllsch 
553ea0121ebSjakllsch 	nxt2k_readdata(nxt, 0x31, &reg, 1);
554ea0121ebSjakllsch 	if (reg & 0x20) {
555ea0121ebSjakllsch 		status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
556ea0121ebSjakllsch 		    FE_HAS_SYNC | FE_HAS_LOCK;
557ea0121ebSjakllsch 	}
558ea0121ebSjakllsch 
559ea0121ebSjakllsch 	return status;
560ea0121ebSjakllsch }
561ea0121ebSjakllsch 
562ea0121ebSjakllsch #if notyet
563ea0121ebSjakllsch int
nxt2k_fe_read_ucblocks(struct nxt2k * nxt,uint32_t * ucblk)564ea0121ebSjakllsch nxt2k_fe_read_ucblocks(struct nxt2k *nxt, uint32_t *ucblk)
565ea0121ebSjakllsch {
566ea0121ebSjakllsch 	uint8_t reg[3];
567ea0121ebSjakllsch 
568ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0xe6, reg, 3);
569ea0121ebSjakllsch 	*ucblk = reg[2];
570ea0121ebSjakllsch 
571ea0121ebSjakllsch 	return 0;
572ea0121ebSjakllsch }
573ea0121ebSjakllsch 
574ea0121ebSjakllsch int
nxt2k_fe_read_ber(struct nxt2k * nxt,uint32_t * ber)575ea0121ebSjakllsch nxt2k_fe_read_ber(struct nxt2k *nxt, uint32_t *ber)
576ea0121ebSjakllsch {
577ea0121ebSjakllsch 	uint8_t reg[3];
578ea0121ebSjakllsch 
579ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0xe6, reg, 3);
580ea0121ebSjakllsch 
581ea0121ebSjakllsch 	*ber = ((reg[0] << 8) + reg[1]) * 8;
582ea0121ebSjakllsch 
583ea0121ebSjakllsch 	return 0;
584ea0121ebSjakllsch }
585ea0121ebSjakllsch #endif
586ea0121ebSjakllsch 
587ea0121ebSjakllsch static int
nxt2k_fe_set_frontend(struct nxt2k * nxt,fe_modulation_t modulation)588ea0121ebSjakllsch nxt2k_fe_set_frontend(struct nxt2k *nxt, fe_modulation_t modulation)
589ea0121ebSjakllsch {
590ea0121ebSjakllsch 	uint8_t buf[5];
591ea0121ebSjakllsch 
592ea0121ebSjakllsch 	if (nxt->loaded != true)
593ea0121ebSjakllsch 		nxt2k4_init(nxt);
594ea0121ebSjakllsch 
595ea0121ebSjakllsch 	nxt2k_mc_stop(nxt);
596ea0121ebSjakllsch 
597ea0121ebSjakllsch 	{ /* 2k4 */
598ea0121ebSjakllsch 	/* make sure demod is set to digital */
599ea0121ebSjakllsch 	buf[0] = 0x04;
600ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x14, buf, 1);
601ea0121ebSjakllsch 	buf[0] = 0x00;
602ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x17, buf, 1);
603ea0121ebSjakllsch 	}
604ea0121ebSjakllsch 
605ea0121ebSjakllsch 	/* QAM/VSB punctured/non-punctured goes here */
606ea0121ebSjakllsch 
607ea0121ebSjakllsch 	/* tune in */
608ea0121ebSjakllsch 	/* maybe ensure tuner managed to tune in? */
609ea0121ebSjakllsch 
610ea0121ebSjakllsch 	/* tuning done, reset agc */
611ea0121ebSjakllsch 	nxt2k_agc_reset(nxt);
612ea0121ebSjakllsch 
613ea0121ebSjakllsch 	/* set target power level */
614ea0121ebSjakllsch 	switch (modulation) {
615ea0121ebSjakllsch 	case VSB_8:
616ea0121ebSjakllsch 		buf[0] = 0x70;
617ea0121ebSjakllsch 		break;
618ea0121ebSjakllsch 	case QAM_256:
619ea0121ebSjakllsch 	case QAM_64:
620ea0121ebSjakllsch 		buf[0] = 0x74;
621ea0121ebSjakllsch 		break;
622ea0121ebSjakllsch 	default:
623ea0121ebSjakllsch 		return EINVAL;
624ea0121ebSjakllsch 		/* NOTREACHED */
625ea0121ebSjakllsch 	}
626ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x42, buf, 1);
627ea0121ebSjakllsch 
628ea0121ebSjakllsch 	/* configure sdm */
629ea0121ebSjakllsch 	buf[0] = 0x07; /* 2k4 */
630ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x57, buf, 1);
631ea0121ebSjakllsch 
632ea0121ebSjakllsch 	/* write sdm1 input */
633ea0121ebSjakllsch         buf[0] = 0x10;
634ea0121ebSjakllsch         buf[1] = 0x00;
635ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x58, buf, 2); /* 2k4 */
636ea0121ebSjakllsch 
637ea0121ebSjakllsch 	/* write sdmx input */
638ea0121ebSjakllsch 	switch (modulation) {
639ea0121ebSjakllsch 	case VSB_8:
640ea0121ebSjakllsch 		buf[0] = 0x60;
641ea0121ebSjakllsch 		break;
642ea0121ebSjakllsch 	case QAM_256:
643ea0121ebSjakllsch 		buf[0] = 0x64;
644ea0121ebSjakllsch 		break;
645ea0121ebSjakllsch 	case QAM_64:
646ea0121ebSjakllsch 		buf[0] = 0x68;
647ea0121ebSjakllsch 		break;
648ea0121ebSjakllsch 	default:
649ea0121ebSjakllsch 		return EINVAL;
650ea0121ebSjakllsch 		/* NOTREACHED */
651ea0121ebSjakllsch 	}
652ea0121ebSjakllsch         buf[1] = 0x00;
653ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x5c, buf, 2); /* 2k4 */
654ea0121ebSjakllsch 
655ea0121ebSjakllsch 	/* write adc power lpf fc */
656ea0121ebSjakllsch 	buf[0] = 0x05;
657ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x43, buf, 1);
658ea0121ebSjakllsch 
659ea0121ebSjakllsch 	{ /* 2k4 */
660ea0121ebSjakllsch 	buf[0] = 0x00;
661ea0121ebSjakllsch 	buf[1] = 0x00;
662ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x46, buf, 2);
663ea0121ebSjakllsch 	}
664ea0121ebSjakllsch 
665ea0121ebSjakllsch 	/* write accumulator2 input */
666ea0121ebSjakllsch 	buf[0] = 0x80;
667ea0121ebSjakllsch 	buf[1] = 0x00;
668ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x4b, buf, 2); /* 2k4 */
669ea0121ebSjakllsch 
670ea0121ebSjakllsch 	/* write kg1 */
671ea0121ebSjakllsch 	buf[0] = 0x00;
672ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x4d, buf, 1);
673ea0121ebSjakllsch 
674ea0121ebSjakllsch 	/* write sdm12 lpf fc */
675ea0121ebSjakllsch 	buf[0] = 0x44;
676ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x55, buf, 1);
677ea0121ebSjakllsch 
678ea0121ebSjakllsch 	/* write agc control reg */
679ea0121ebSjakllsch 	buf[0] = 0x04;
680ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x41, buf, 1);
681ea0121ebSjakllsch 
682ea0121ebSjakllsch 	{ /* 2k4 */
683ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x80, buf, 1);
684ea0121ebSjakllsch 	buf[0] = 0x24;
685ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x80, buf, 1);
686ea0121ebSjakllsch 
687ea0121ebSjakllsch 	/* soft reset? */
688ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x08, buf, 1);
689ea0121ebSjakllsch 	buf[0] = 0x10;
690ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x08, buf, 1);
691ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x08, buf, 1);
692ea0121ebSjakllsch 	buf[0] = 0x00;
693ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x08, buf, 1);
694ea0121ebSjakllsch 
695ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x80, buf, 1);
696ea0121ebSjakllsch 	buf[0] = 0x04;
697ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x80, buf, 1);
698ea0121ebSjakllsch 
699ea0121ebSjakllsch 	buf[0] = 0x00;
700ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x81, buf, 1);
701ea0121ebSjakllsch 
702ea0121ebSjakllsch 	buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;
703ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x82, buf, 3);
704ea0121ebSjakllsch 
705ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x88, buf, 1);
706ea0121ebSjakllsch 	buf[0] = 0x11;
707ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x88, buf, 1);
708ea0121ebSjakllsch 
709ea0121ebSjakllsch 	nxt2k_readreg(nxt, 0x80, buf, 1);
710ea0121ebSjakllsch 	buf[0] = 0x44;
711ea0121ebSjakllsch 	nxt2k_writereg(nxt, 0x80, buf, 1);
712ea0121ebSjakllsch 	}
713ea0121ebSjakllsch 
714ea0121ebSjakllsch 	/* write agc ucgp0 */
715ea0121ebSjakllsch 	switch (modulation) {
716ea0121ebSjakllsch 	case VSB_8:
717ea0121ebSjakllsch 		buf[0] = 0x00;
718ea0121ebSjakllsch 		break;
719ea0121ebSjakllsch 	case QAM_64:
720ea0121ebSjakllsch 		buf[0] = 0x02;
721ea0121ebSjakllsch 		break;
722ea0121ebSjakllsch 	case QAM_256:
723ea0121ebSjakllsch 		buf[0] = 0x03;
724ea0121ebSjakllsch 		break;
725ea0121ebSjakllsch 	default:
726ea0121ebSjakllsch 		return EINVAL;
727ea0121ebSjakllsch 		/* NOTREACHED */
728ea0121ebSjakllsch 	}
729ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x30, buf, 1);
730ea0121ebSjakllsch 
731ea0121ebSjakllsch 	/* write agc control reg */
732ea0121ebSjakllsch 	buf[0] = 0x00;
733ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x41, buf, 1);
734ea0121ebSjakllsch 
735ea0121ebSjakllsch 	/* write accumulator2 input */
736ea0121ebSjakllsch 	buf[0] = 0x80;
737ea0121ebSjakllsch 	buf[1] = 0x00;
738ea0121ebSjakllsch 	{ /* 2k4 */
739ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x49, buf, 2);
740ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x4b, buf, 2);
741ea0121ebSjakllsch 	}
742ea0121ebSjakllsch 
743ea0121ebSjakllsch 	/* write agc control reg */
744ea0121ebSjakllsch 	buf[0] = 0x04;
745ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x41, buf, 1);
746ea0121ebSjakllsch 
747ea0121ebSjakllsch 	nxt2k_mc_start(nxt);
748ea0121ebSjakllsch 
749ea0121ebSjakllsch 	{ /* 2k4 */
750ea0121ebSjakllsch 	nxt2k4_mc_init(nxt);
751ea0121ebSjakllsch 	buf[0] = 0xf0;
752ea0121ebSjakllsch 	buf[1] = 0x00;
753ea0121ebSjakllsch 	nxt2k_writedata(nxt, 0x5c, buf, 2);
754ea0121ebSjakllsch 	}
755ea0121ebSjakllsch 
756ea0121ebSjakllsch 	/* "adjacent channel detection" code would go here */
757ea0121ebSjakllsch 
758ea0121ebSjakllsch 	return 0;
759ea0121ebSjakllsch }
760ea0121ebSjakllsch 
761ea0121ebSjakllsch static int
nxt2k_init(struct nxt2k * nxt)762ea0121ebSjakllsch nxt2k_init(struct nxt2k *nxt)
763ea0121ebSjakllsch {
764ea0121ebSjakllsch 	int ret = 0;
765ea0121ebSjakllsch 
766ea0121ebSjakllsch 	printf("%s\n", __func__);
767ea0121ebSjakllsch 
768ea0121ebSjakllsch 	if (nxt->loaded != 1)
769ea0121ebSjakllsch 		ret = nxt2k4_init(nxt);
770ea0121ebSjakllsch 
771ea0121ebSjakllsch 	return ret;
772ea0121ebSjakllsch }
773ea0121ebSjakllsch 
774ea0121ebSjakllsch 
775ea0121ebSjakllsch struct nxt2k *
nxt2k_open(device_t parent,i2c_tag_t tag,i2c_addr_t addr,unsigned int if_freq)776ea0121ebSjakllsch nxt2k_open(device_t parent, i2c_tag_t tag, i2c_addr_t addr, unsigned int if_freq)
777ea0121ebSjakllsch {
778ea0121ebSjakllsch 	struct nxt2k *nxt;
779ea0121ebSjakllsch 	int e;
780ea0121ebSjakllsch 	uint8_t b[5];
781ea0121ebSjakllsch 
782ea0121ebSjakllsch 	nxt = kmem_alloc(sizeof(*nxt), KM_SLEEP);
783ea0121ebSjakllsch 	nxt->parent = parent;
784ea0121ebSjakllsch 	nxt->tag = tag;
785ea0121ebSjakllsch 	nxt->addr = addr;
786ea0121ebSjakllsch 
787ea0121ebSjakllsch 	/* read chip ids */
788ea0121ebSjakllsch 	e = nxt2k_readdata(nxt, 0x00, b, 5);
789ea0121ebSjakllsch 
790ea0121ebSjakllsch 	if (e) {
791ea0121ebSjakllsch 		printf("%s read failed %d\n", __func__, e);
792ea0121ebSjakllsch 		kmem_free(nxt, sizeof(*nxt));
793ea0121ebSjakllsch 		return NULL;
794ea0121ebSjakllsch 	}
795ea0121ebSjakllsch 
796ea0121ebSjakllsch 	if (b[0] != 0x05) {
797ea0121ebSjakllsch 		printf("%s unsupported %02x %02x %02x %02x %02x\n",
798ea0121ebSjakllsch 		    __func__, b[0], b[1], b[2], b[3], b[4]);
799ea0121ebSjakllsch 		kmem_free(nxt, sizeof(*nxt));
800ea0121ebSjakllsch 		return NULL;
801ea0121ebSjakllsch 	}
802ea0121ebSjakllsch 
803ea0121ebSjakllsch 	mutex_init(&nxt->mtx, MUTEX_DEFAULT, IPL_NONE);
804ea0121ebSjakllsch 	cv_init(&nxt->cv, "nxtpl");
805ea0121ebSjakllsch 
806ea0121ebSjakllsch 	nxt->loaded = false;
807ea0121ebSjakllsch 
808ea0121ebSjakllsch 	return nxt;
809ea0121ebSjakllsch }
810ea0121ebSjakllsch 
811ea0121ebSjakllsch void
nxt2k_close(struct nxt2k * nxt)812ea0121ebSjakllsch nxt2k_close(struct nxt2k *nxt)
813ea0121ebSjakllsch {
814ea0121ebSjakllsch 	kmem_free(nxt, sizeof(*nxt));
815ea0121ebSjakllsch }
816ea0121ebSjakllsch 
817ea0121ebSjakllsch void
nxt2k_enable(struct nxt2k * nxt,bool enable)818ea0121ebSjakllsch nxt2k_enable(struct nxt2k *nxt, bool enable)
819ea0121ebSjakllsch {
820ea0121ebSjakllsch 	if (enable == true)
821ea0121ebSjakllsch 		nxt2k_init(nxt);
822ea0121ebSjakllsch }
823ea0121ebSjakllsch 
824ea0121ebSjakllsch int
nxt2k_set_modulation(struct nxt2k * nxt,fe_modulation_t modulation)825ea0121ebSjakllsch nxt2k_set_modulation(struct nxt2k *nxt, fe_modulation_t modulation)
826ea0121ebSjakllsch {
827ea0121ebSjakllsch 	return nxt2k_fe_set_frontend(nxt, modulation);
828ea0121ebSjakllsch }
829a0f539c0Sjmcneill 
83022ca8619Sjmcneill MODULE(MODULE_CLASS_DRIVER, nxt2k, "i2cexec");
831a0f539c0Sjmcneill 
832a0f539c0Sjmcneill static int
nxt2k_modcmd(modcmd_t cmd,void * opaque)833a0f539c0Sjmcneill nxt2k_modcmd(modcmd_t cmd, void *opaque)
834a0f539c0Sjmcneill {
835a0f539c0Sjmcneill 	if (cmd == MODULE_CMD_INIT || cmd == MODULE_CMD_FINI)
836a0f539c0Sjmcneill 		return 0;
837a0f539c0Sjmcneill 	return ENOTTY;
838a0f539c0Sjmcneill }
839