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