aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/nxt200x.c
diff options
context:
space:
mode:
authorKirk Lapray <kirk.lapray@gmail.com>2005-11-09 00:35:46 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-09 10:56:05 -0500
commit04a45929e7f00ed4fc7b1d375397f808c8a5d0eb (patch)
tree60d4671280834e4b352c41231449ee5acaf4a990 /drivers/media/dvb/frontends/nxt200x.c
parent7f44dcda3f659ce47c1660a705802f12a2403a90 (diff)
[PATCH] dvb: add nxt200x frontend module
* nxt200x.c, nxt200x.h - New frontend module that supports both NXT2002 and NXT2004. So far, only tested on NXT2004. After testing on NXT2002, we should deprecate the nxt2002 module, and implement this one instead on the applicable cards. * get_dvb_firmware: - Added support for the NXT2004 firmware. This firmware works with both the ATI HDTV Wonder and the AVerTVHD MCE a180. This was originally written by Jean-Francois Thibert * dvb-pll.c - Fixed minimum frequency for tuv1236d. It seems that the data sheets are wrong. Signed-off-by: Kirk Lapray <kirk.lapray@gmail.com> Signed-off-by: Michael Krufky <mkrufky@m1k.net> Cc: Johannes Stezenbach <js@linuxtv.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/media/dvb/frontends/nxt200x.c')
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c1203
1 files changed, 1203 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
new file mode 100644
index 000000000000..1d729be9b75c
--- /dev/null
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -0,0 +1,1203 @@
1/*
2 * Support for NXT2002 and NXT2004 - VSB/QAM
3 *
4 * Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com)
5 * based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
6 * and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.com)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22*/
23
24/*
25 * NOTES ABOUT THIS DRIVER
26 *
27 * This Linux driver supports:
28 * B2C2/BBTI Technisat Air2PC - ATSC (NXT2002)
29 * AverTVHD MCE A180 (NXT2004)
30 * ATI HDTV Wonder (NXT2004)
31 *
32 * This driver needs external firmware. Please use the command
33 * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" or
34 * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to
35 * download/extract the appropriate firmware, and then copy it to
36 * /usr/lib/hotplug/firmware/ or /lib/firmware/
37 * (depending on configuration of firmware hotplug).
38 */
39#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
40#define NXT2004_DEFAULT_FIRMWARE "dvb-fe-nxt2004.fw"
41#define CRC_CCIT_MASK 0x1021
42
43#include <linux/kernel.h>
44#include <linux/init.h>
45#include <linux/module.h>
46#include <linux/moduleparam.h>
47
48#include "dvb_frontend.h"
49#include "dvb-pll.h"
50#include "nxt200x.h"
51
52struct nxt200x_state {
53
54 struct i2c_adapter* i2c;
55 struct dvb_frontend_ops ops;
56 const struct nxt200x_config* config;
57 struct dvb_frontend frontend;
58
59 /* demodulator private data */
60 nxt_chip_type demod_chip;
61 u8 initialised:1;
62};
63
64static int debug;
65#define dprintk(args...) \
66 do { \
67 if (debug) printk(KERN_DEBUG "nxt200x: " args); \
68 } while (0)
69
70static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len)
71{
72 int err;
73 struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = len };
74
75 if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
76 printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
77 __FUNCTION__, addr, err);
78 return -EREMOTEIO;
79 }
80 return 0;
81}
82
83static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len)
84{
85 int err;
86 struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len };
87
88 if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
89 printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
90 __FUNCTION__, addr, err);
91 return -EREMOTEIO;
92 }
93 return 0;
94}
95
96static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, u8 *buf, u8 len)
97{
98 u8 buf2 [len+1];
99 int err;
100 struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 };
101
102 buf2[0] = reg;
103 memcpy(&buf2[1], buf, len);
104
105 if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
106 printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
107 __FUNCTION__, state->config->demod_address, err);
108 return -EREMOTEIO;
109 }
110 return 0;
111}
112
113static u8 nxt200x_readbytes (struct nxt200x_state* state, u8 reg, u8* buf, u8 len)
114{
115 u8 reg2 [] = { reg };
116
117 struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 },
118 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };
119
120 int err;
121
122 if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
123 printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
124 __FUNCTION__, state->config->demod_address, err);
125 return -EREMOTEIO;
126 }
127 return 0;
128}
129
130static u16 nxt200x_crc(u16 crc, u8 c)
131{
132 u8 i;
133 u16 input = (u16) c & 0xFF;
134
135 input<<=8;
136 for(i=0; i<8; i++) {
137 if((crc^input) & 0x8000)
138 crc=(crc<<1)^CRC_CCIT_MASK;
139 else
140 crc<<=1;
141 input<<=1;
142 }
143 return crc;
144}
145
146static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
147{
148 u8 attr, len2, buf;
149 dprintk("%s\n", __FUNCTION__);
150
151 /* set mutli register register */
152 nxt200x_writebytes(state, 0x35, &reg, 1);
153
154 /* send the actual data */
155 nxt200x_writebytes(state, 0x36, data, len);
156
157 switch (state->demod_chip) {
158 case NXT2002:
159 len2 = len;
160 buf = 0x02;
161 break;
162 case NXT2004:
163 /* probably not right, but gives correct values */
164 attr = 0x02;
165 if (reg & 0x80) {
166 attr = attr << 1;
167 if (reg & 0x04)
168 attr = attr >> 1;
169 }
170 /* set write bit */
171 len2 = ((attr << 4) | 0x10) | len;
172 buf = 0x80;
173 break;
174 default:
175 return -EINVAL;
176 break;
177 }
178
179 /* set multi register length */
180 nxt200x_writebytes(state, 0x34, &len2, 1);
181
182 /* toggle the multireg write bit */
183 nxt200x_writebytes(state, 0x21, &buf, 1);
184
185 nxt200x_readbytes(state, 0x21, &buf, 1);
186
187 switch (state->demod_chip) {
188 case NXT2002:
189 if ((buf & 0x02) == 0)
190 return 0;
191 break;
192 case NXT2004:
193 if (buf == 0)
194 return 0;
195 break;
196 default:
197 return -EINVAL;
198 break;
199 }
200
201 printk(KERN_WARNING "nxt200x: Error writing multireg register 0x%02X\n",reg);
202
203 return 0;
204}
205
206static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
207{
208 int i;
209 u8 buf, len2, attr;
210 dprintk("%s\n", __FUNCTION__);
211
212 /* set mutli register register */
213 nxt200x_writebytes(state, 0x35, &reg, 1);
214
215 switch (state->demod_chip) {
216 case NXT2002:
217 /* set multi register length */
218 len2 = len & 0x80;
219 nxt200x_writebytes(state, 0x34, &len2, 1);
220
221 /* read the actual data */
222 nxt200x_readbytes(state, reg, data, len);
223 return 0;
224 break;
225 case NXT2004:
226 /* probably not right, but gives correct values */
227 attr = 0x02;
228 if (reg & 0x80) {
229 attr = attr << 1;
230 if (reg & 0x04)
231 attr = attr >> 1;
232 }
233
234 /* set multi register length */
235 len2 = (attr << 4) | len;
236 nxt200x_writebytes(state, 0x34, &len2, 1);
237
238 /* toggle the multireg bit*/
239 buf = 0x80;
240 nxt200x_writebytes(state, 0x21, &buf, 1);
241
242 /* read status */
243 nxt200x_readbytes(state, 0x21, &buf, 1);
244
245 if (buf == 0)
246 {
247 /* read the actual data */
248 for(i = 0; i < len; i++) {
249 nxt200x_readbytes(state, 0x36 + i, &data[i], 1);
250 }
251 return 0;
252 }
253 break;
254 default:
255 return -EINVAL;
256 break;
257 }
258
259 printk(KERN_WARNING "nxt200x: Error reading multireg register 0x%02X\n",reg);
260
261 return 0;
262}
263
264static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
265{
266 u8 buf, stopval, counter = 0;
267 dprintk("%s\n", __FUNCTION__);
268
269 /* set correct stop value */
270 switch (state->demod_chip) {
271 case NXT2002:
272 stopval = 0x40;
273 break;
274 case NXT2004:
275 stopval = 0x10;
276 break;
277 default:
278 stopval = 0;
279 break;
280 }
281
282 buf = 0x80;
283 nxt200x_writebytes(state, 0x22, &buf, 1);
284
285 while (counter < 20) {
286 nxt200x_readbytes(state, 0x31, &buf, 1);
287 if (buf & stopval)
288 return;
289 msleep(10);
290 counter++;
291 }
292
293 printk(KERN_WARNING "nxt200x: Timeout waiting for nxt200x to stop. This is ok after firmware upload.\n");
294 return;
295}
296
297static void nxt200x_microcontroller_start (struct nxt200x_state* state)
298{
299 u8 buf;
300 dprintk("%s\n", __FUNCTION__);
301
302 buf = 0x00;
303 nxt200x_writebytes(state, 0x22, &buf, 1);
304}
305
306static void nxt2004_microcontroller_init (struct nxt200x_state* state)
307{
308 u8 buf[9];
309 u8 counter = 0;
310 dprintk("%s\n", __FUNCTION__);
311
312 buf[0] = 0x00;
313 nxt200x_writebytes(state, 0x2b, buf, 1);
314 buf[0] = 0x70;
315 nxt200x_writebytes(state, 0x34, buf, 1);
316 buf[0] = 0x04;
317 nxt200x_writebytes(state, 0x35, buf, 1);
318 buf[0] = 0x01; buf[1] = 0x23; buf[2] = 0x45; buf[3] = 0x67; buf[4] = 0x89;
319 buf[5] = 0xAB; buf[6] = 0xCD; buf[7] = 0xEF; buf[8] = 0xC0;
320 nxt200x_writebytes(state, 0x36, buf, 9);
321 buf[0] = 0x80;
322 nxt200x_writebytes(state, 0x21, buf, 1);
323
324 while (counter < 20) {
325 nxt200x_readbytes(state, 0x21, buf, 1);
326 if (buf[0] == 0)
327 return;
328 msleep(10);
329 counter++;
330 }
331
332 printk(KERN_WARNING "nxt200x: Timeout waiting for nxt2004 to init.\n");
333
334 return;
335}
336
337static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
338{
339 u8 buf, count = 0;
340
341 dprintk("%s\n", __FUNCTION__);
342
343 dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[0], data[1], data[2], data[3]);
344
345 /* if pll is a Philips TUV1236D then write directly to tuner */
346 if (strcmp(state->config->pll_desc->name, "Philips TUV1236D") == 0) {
347 if (i2c_writebytes(state, state->config->pll_address, data, 4))
348 printk(KERN_WARNING "nxt200x: error writing to tuner\n");
349 /* wait until we have a lock */
350 while (count < 20) {
351 i2c_readbytes(state, state->config->pll_address, &buf, 1);
352 if (buf & 0x40)
353 return 0;
354 msleep(100);
355 count++;
356 }
357 printk("nxt200x: timeout waiting for tuner lock\n");
358 return 0;
359 } else {
360 /* set the i2c transfer speed to the tuner */
361 buf = 0x03;
362 nxt200x_writebytes(state, 0x20, &buf, 1);
363
364 /* setup to transfer 4 bytes via i2c */
365 buf = 0x04;
366 nxt200x_writebytes(state, 0x34, &buf, 1);
367
368 /* write actual tuner bytes */
369 nxt200x_writebytes(state, 0x36, data, 4);
370
371 /* set tuner i2c address */
372 buf = state->config->pll_address;
373 nxt200x_writebytes(state, 0x35, &buf, 1);
374
375 /* write UC Opmode to begin transfer */
376 buf = 0x80;
377 nxt200x_writebytes(state, 0x21, &buf, 1);
378
379 while (count < 20) {
380 nxt200x_readbytes(state, 0x21, &buf, 1);
381 if ((buf & 0x80)== 0x00)
382 return 0;
383 msleep(100);
384 count++;
385 }
386 printk("nxt200x: timeout error writing tuner\n");
387 return 0;
388 }
389}
390
391static void nxt200x_agc_reset(struct nxt200x_state* state)
392{
393 u8 buf;
394 dprintk("%s\n", __FUNCTION__);
395
396 switch (state->demod_chip) {
397 case NXT2002:
398 buf = 0x08;
399 nxt200x_writebytes(state, 0x08, &buf, 1);
400 buf = 0x00;
401 nxt200x_writebytes(state, 0x08, &buf, 1);
402 break;
403 case NXT2004:
404 nxt200x_readreg_multibyte(state, 0x08, &buf, 1);
405 buf = 0x08;
406 nxt200x_writereg_multibyte(state, 0x08, &buf, 1);
407 buf = 0x00;
408 nxt200x_writereg_multibyte(state, 0x08, &buf, 1);
409 break;
410 default:
411 break;
412 }
413 return;
414}
415
416static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
417{
418
419 struct nxt200x_state* state = fe->demodulator_priv;
420 u8 buf[3], written = 0, chunkpos = 0;
421 u16 rambase, position, crc = 0;
422
423 dprintk("%s\n", __FUNCTION__);
424 dprintk("Firmware is %zu bytes\n", fw->size);
425
426 /* Get the RAM base for this nxt2002 */
427 nxt200x_readbytes(state, 0x10, buf, 1);
428
429 if (buf[0] & 0x10)
430 rambase = 0x1000;
431 else
432 rambase = 0x0000;
433
434 dprintk("rambase on this nxt2002 is %04X\n", rambase);
435
436 /* Hold the micro in reset while loading firmware */
437 buf[0] = 0x80;
438 nxt200x_writebytes(state, 0x2B, buf, 1);
439
440 for (position = 0; position < fw->size; position++) {
441 if (written == 0) {
442 crc = 0;
443 chunkpos = 0x28;
444 buf[0] = ((rambase + position) >> 8);
445 buf[1] = (rambase + position) & 0xFF;
446 buf[2] = 0x81;
447 /* write starting address */
448 nxt200x_writebytes(state, 0x29, buf, 3);
449 }
450 written++;
451 chunkpos++;
452
453 if ((written % 4) == 0)
454 nxt200x_writebytes(state, chunkpos, &fw->data[position-3], 4);
455
456 crc = nxt200x_crc(crc, fw->data[position]);
457
458 if ((written == 255) || (position+1 == fw->size)) {
459 /* write remaining bytes of firmware */
460 nxt200x_writebytes(state, chunkpos+4-(written %4),
461 &fw->data[position-(written %4) + 1],
462 written %4);
463 buf[0] = crc << 8;
464 buf[1] = crc & 0xFF;
465
466 /* write crc */
467 nxt200x_writebytes(state, 0x2C, buf, 2);
468
469 /* do a read to stop things */
470 nxt200x_readbytes(state, 0x2A, buf, 1);
471
472 /* set transfer mode to complete */
473 buf[0] = 0x80;
474 nxt200x_writebytes(state, 0x2B, buf, 1);
475
476 written = 0;
477 }
478 }
479
480 return 0;
481};
482
483static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
484{
485
486 struct nxt200x_state* state = fe->demodulator_priv;
487 u8 buf[3];
488 u16 rambase, position, crc=0;
489
490 dprintk("%s\n", __FUNCTION__);
491 dprintk("Firmware is %zu bytes\n", fw->size);
492
493 /* set rambase */
494 rambase = 0x1000;
495
496 /* hold the micro in reset while loading firmware */
497 buf[0] = 0x80;
498 nxt200x_writebytes(state, 0x2B, buf,1);
499
500 /* calculate firmware CRC */
501 for (position = 0; position < fw->size; position++) {
502 crc = nxt200x_crc(crc, fw->data[position]);
503 }
504
505 buf[0] = rambase >> 8;
506 buf[1] = rambase & 0xFF;
507 buf[2] = 0x81;
508 /* write starting address */
509 nxt200x_writebytes(state,0x29,buf,3);
510
511 for (position = 0; position < fw->size;) {
512 nxt200x_writebytes(state, 0x2C, &fw->data[position],
513 fw->size-position > 255 ? 255 : fw->size-position);
514 position += (fw->size-position > 255 ? 255 : fw->size-position);
515 }
516 buf[0] = crc >> 8;
517 buf[1] = crc & 0xFF;
518
519 dprintk("firmware crc is 0x%02X 0x%02X\n", buf[0], buf[1]);
520
521 /* write crc */
522 nxt200x_writebytes(state, 0x2C, buf,2);
523
524 /* do a read to stop things */
525 nxt200x_readbytes(state, 0x2C, buf, 1);
526
527 /* set transfer mode to complete */
528 buf[0] = 0x80;
529 nxt200x_writebytes(state, 0x2B, buf,1);
530
531 return 0;
532};
533
534static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
535 struct dvb_frontend_parameters *p)
536{
537 struct nxt200x_state* state = fe->demodulator_priv;
538 u8 buf[4];
539
540 /* stop the micro first */
541 nxt200x_microcontroller_stop(state);
542
543 if (state->demod_chip == NXT2004) {
544 /* make sure demod is set to digital */
545 buf[0] = 0x04;
546 nxt200x_writebytes(state, 0x14, buf, 1);
547 buf[0] = 0x00;
548 nxt200x_writebytes(state, 0x17, buf, 1);
549 }
550
551 /* get tuning information */
552 dvb_pll_configure(state->config->pll_desc, buf, p->frequency, 0);
553
554 /* set additional params */
555 switch (p->u.vsb.modulation) {
556 case QAM_64:
557 case QAM_256:
558 /* Set punctured clock for QAM */
559 /* This is just a guess since I am unable to test it */
560 state->config->set_ts_params(fe, 1);
561
562 /* set to use cable input */
563 buf[3] |= 0x08;
564 break;
565 case VSB_8:
566 /* Set non-punctured clock for VSB */
567 state->config->set_ts_params(fe, 0);
568 break;
569 default:
570 return -EINVAL;
571 break;
572 }
573
574 /* write frequency information */
575 nxt200x_writetuner(state, buf);
576
577 /* reset the agc now that tuning has been completed */
578 nxt200x_agc_reset(state);
579
580 /* set target power level */
581 switch (p->u.vsb.modulation) {
582 case QAM_64:
583 case QAM_256:
584 buf[0] = 0x74;
585 break;
586 case VSB_8:
587 buf[0] = 0x70;
588 break;
589 default:
590 return -EINVAL;
591 break;
592 }
593 nxt200x_writebytes(state, 0x42, buf, 1);
594
595 /* configure sdm */
596 switch (state->demod_chip) {
597 case NXT2002:
598 buf[0] = 0x87;
599 break;
600 case NXT2004:
601 buf[0] = 0x07;
602 break;
603 default:
604 return -EINVAL;
605 break;
606 }
607 nxt200x_writebytes(state, 0x57, buf, 1);
608
609 /* write sdm1 input */
610 buf[0] = 0x10;
611 buf[1] = 0x00;
612 nxt200x_writebytes(state, 0x58, buf, 2);
613
614 /* write sdmx input */
615 switch (p->u.vsb.modulation) {
616 case QAM_64:
617 buf[0] = 0x68;
618 break;
619 case QAM_256:
620 buf[0] = 0x64;
621 break;
622 case VSB_8:
623 buf[0] = 0x60;
624 break;
625 default:
626 return -EINVAL;
627 break;
628 }
629 buf[1] = 0x00;
630 nxt200x_writebytes(state, 0x5C, buf, 2);
631
632 /* write adc power lpf fc */
633 buf[0] = 0x05;
634 nxt200x_writebytes(state, 0x43, buf, 1);
635
636 if (state->demod_chip == NXT2004) {
637 /* write ??? */
638 buf[0] = 0x00;
639 buf[1] = 0x00;
640 nxt200x_writebytes(state, 0x46, buf, 2);
641 }
642
643 /* write accumulator2 input */
644 buf[0] = 0x80;
645 buf[1] = 0x00;
646 nxt200x_writebytes(state, 0x4B, buf, 2);
647
648 /* write kg1 */
649 buf[0] = 0x00;
650 nxt200x_writebytes(state, 0x4D, buf, 1);
651
652 /* write sdm12 lpf fc */
653 buf[0] = 0x44;
654 nxt200x_writebytes(state, 0x55, buf, 1);
655
656 /* write agc control reg */
657 buf[0] = 0x04;
658 nxt200x_writebytes(state, 0x41, buf, 1);
659
660 if (state->demod_chip == NXT2004) {
661 nxt200x_readreg_multibyte(state, 0x80, buf, 1);
662 buf[0] = 0x24;
663 nxt200x_writereg_multibyte(state, 0x80, buf, 1);
664
665 /* soft reset? */
666 nxt200x_readreg_multibyte(state, 0x08, buf, 1);
667 buf[0] = 0x10;
668 nxt200x_writereg_multibyte(state, 0x08, buf, 1);
669 nxt200x_readreg_multibyte(state, 0x08, buf, 1);
670 buf[0] = 0x00;
671 nxt200x_writereg_multibyte(state, 0x08, buf, 1);
672
673 nxt200x_readreg_multibyte(state, 0x80, buf, 1);
674 buf[0] = 0x04;
675 nxt200x_writereg_multibyte(state, 0x80, buf, 1);
676 buf[0] = 0x00;
677 nxt200x_writereg_multibyte(state, 0x81, buf, 1);
678 buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;
679 nxt200x_writereg_multibyte(state, 0x82, buf, 3);
680 nxt200x_readreg_multibyte(state, 0x88, buf, 1);
681 buf[0] = 0x11;
682 nxt200x_writereg_multibyte(state, 0x88, buf, 1);
683 nxt200x_readreg_multibyte(state, 0x80, buf, 1);
684 buf[0] = 0x44;
685 nxt200x_writereg_multibyte(state, 0x80, buf, 1);
686 }
687
688 /* write agc ucgp0 */
689 switch (p->u.vsb.modulation) {
690 case QAM_64:
691 buf[0] = 0x02;
692 break;
693 case QAM_256:
694 buf[0] = 0x03;
695 break;
696 case VSB_8:
697 buf[0] = 0x00;
698 break;
699 default:
700 return -EINVAL;
701 break;
702 }
703 nxt200x_writebytes(state, 0x30, buf, 1);
704
705 /* write agc control reg */
706 buf[0] = 0x00;
707 nxt200x_writebytes(state, 0x41, buf, 1);
708
709 /* write accumulator2 input */
710 buf[0] = 0x80;
711 buf[1] = 0x00;
712 nxt200x_writebytes(state, 0x49, buf,2);
713 nxt200x_writebytes(state, 0x4B, buf,2);
714
715 /* write agc control reg */
716 buf[0] = 0x04;
717 nxt200x_writebytes(state, 0x41, buf, 1);
718
719 nxt200x_microcontroller_start(state);
720
721 if (state->demod_chip == NXT2004) {
722 nxt2004_microcontroller_init(state);
723
724 /* ???? */
725 buf[0] = 0xF0;
726 buf[1] = 0x00;
727 nxt200x_writebytes(state, 0x5C, buf, 2);
728 }
729
730 /* adjacent channel detection should be done here, but I don't
731 have any stations with this need so I cannot test it */
732
733 return 0;
734}
735
736static int nxt200x_read_status(struct dvb_frontend* fe, fe_status_t* status)
737{
738 struct nxt200x_state* state = fe->demodulator_priv;
739 u8 lock;
740 nxt200x_readbytes(state, 0x31, &lock, 1);
741
742 *status = 0;
743 if (lock & 0x20) {
744 *status |= FE_HAS_SIGNAL;
745 *status |= FE_HAS_CARRIER;
746 *status |= FE_HAS_VITERBI;
747 *status |= FE_HAS_SYNC;
748 *status |= FE_HAS_LOCK;
749 }
750 return 0;
751}
752
753static int nxt200x_read_ber(struct dvb_frontend* fe, u32* ber)
754{
755 struct nxt200x_state* state = fe->demodulator_priv;
756 u8 b[3];
757
758 nxt200x_readreg_multibyte(state, 0xE6, b, 3);
759
760 *ber = ((b[0] << 8) + b[1]) * 8;
761
762 return 0;
763}
764
765static int nxt200x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
766{
767 struct nxt200x_state* state = fe->demodulator_priv;
768 u8 b[2];
769 u16 temp = 0;
770
771 /* setup to read cluster variance */
772 b[0] = 0x00;
773 nxt200x_writebytes(state, 0xA1, b, 1);
774
775 /* get multreg val */
776 nxt200x_readreg_multibyte(state, 0xA6, b, 2);
777
778 temp = (b[0] << 8) | b[1];
779 *strength = ((0x7FFF - temp) & 0x0FFF) * 16;
780
781 return 0;
782}
783
784static int nxt200x_read_snr(struct dvb_frontend* fe, u16* snr)
785{
786
787 struct nxt200x_state* state = fe->demodulator_priv;
788 u8 b[2];
789 u16 temp = 0, temp2;
790 u32 snrdb = 0;
791
792 /* setup to read cluster variance */
793 b[0] = 0x00;
794 nxt200x_writebytes(state, 0xA1, b, 1);
795
796 /* get multreg val from 0xA6 */
797 nxt200x_readreg_multibyte(state, 0xA6, b, 2);
798
799 temp = (b[0] << 8) | b[1];
800 temp2 = 0x7FFF - temp;
801
802 /* snr will be in db */
803 if (temp2 > 0x7F00)
804 snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) );
805 else if (temp2 > 0x7EC0)
806 snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) );
807 else if (temp2 > 0x7C00)
808 snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) );
809 else
810 snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) );
811
812 /* the value reported back from the frontend will be FFFF=32db 0000=0db */
813 *snr = snrdb * (0xFFFF/32000);
814
815 return 0;
816}
817
818static int nxt200x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
819{
820 struct nxt200x_state* state = fe->demodulator_priv;
821 u8 b[3];
822
823 nxt200x_readreg_multibyte(state, 0xE6, b, 3);
824 *ucblocks = b[2];
825
826 return 0;
827}
828
829static int nxt200x_sleep(struct dvb_frontend* fe)
830{
831 return 0;
832}
833
834static int nxt2002_init(struct dvb_frontend* fe)
835{
836 struct nxt200x_state* state = fe->demodulator_priv;
837 const struct firmware *fw;
838 int ret;
839 u8 buf[2];
840
841 /* request the firmware, this will block until someone uploads it */
842 printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE);
843 ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE, &state->i2c->dev);
844 printk("nxt2002: Waiting for firmware upload(2)...\n");
845 if (ret) {
846 printk("nxt2002: No firmware uploaded (timeout or file not found?)\n");
847 return ret;
848 }
849
850 ret = nxt2002_load_firmware(fe, fw);
851 if (ret) {
852 printk("nxt2002: Writing firmware to device failed\n");
853 release_firmware(fw);
854 return ret;
855 }
856 printk("nxt2002: Firmware upload complete\n");
857
858 /* Put the micro into reset */
859 nxt200x_microcontroller_stop(state);
860
861 /* ensure transfer is complete */
862 buf[0]=0x00;
863 nxt200x_writebytes(state, 0x2B, buf, 1);
864
865 /* Put the micro into reset for real this time */
866 nxt200x_microcontroller_stop(state);
867
868 /* soft reset everything (agc,frontend,eq,fec)*/
869 buf[0] = 0x0F;
870 nxt200x_writebytes(state, 0x08, buf, 1);
871 buf[0] = 0x00;
872 nxt200x_writebytes(state, 0x08, buf, 1);
873
874 /* write agc sdm configure */
875 buf[0] = 0xF1;
876 nxt200x_writebytes(state, 0x57, buf, 1);
877
878 /* write mod output format */
879 buf[0] = 0x20;
880 nxt200x_writebytes(state, 0x09, buf, 1);
881
882 /* write fec mpeg mode */
883 buf[0] = 0x7E;
884 buf[1] = 0x00;
885 nxt200x_writebytes(state, 0xE9, buf, 2);
886
887 /* write mux selection */
888 buf[0] = 0x00;
889 nxt200x_writebytes(state, 0xCC, buf, 1);
890
891 return 0;
892}
893
894static int nxt2004_init(struct dvb_frontend* fe)
895{
896 struct nxt200x_state* state = fe->demodulator_priv;
897 const struct firmware *fw;
898 int ret;
899 u8 buf[3];
900
901 /* ??? */
902 buf[0]=0x00;
903 nxt200x_writebytes(state, 0x1E, buf, 1);
904
905 /* request the firmware, this will block until someone uploads it */
906 printk("nxt2004: Waiting for firmware upload (%s)...\n", NXT2004_DEFAULT_FIRMWARE);
907 ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE, &state->i2c->dev);
908 printk("nxt2004: Waiting for firmware upload(2)...\n");
909 if (ret) {
910 printk("nxt2004: No firmware uploaded (timeout or file not found?)\n");
911 return ret;
912 }
913
914 ret = nxt2004_load_firmware(fe, fw);
915 if (ret) {
916 printk("nxt2004: Writing firmware to device failed\n");
917 release_firmware(fw);
918 return ret;
919 }
920 printk("nxt2004: Firmware upload complete\n");
921
922 /* ensure transfer is complete */
923 buf[0] = 0x01;
924 nxt200x_writebytes(state, 0x19, buf, 1);
925
926 nxt2004_microcontroller_init(state);
927 nxt200x_microcontroller_stop(state);
928 nxt200x_microcontroller_stop(state);
929 nxt2004_microcontroller_init(state);
930 nxt200x_microcontroller_stop(state);
931
932 /* soft reset everything (agc,frontend,eq,fec)*/
933 buf[0] = 0xFF;
934 nxt200x_writereg_multibyte(state, 0x08, buf, 1);
935 buf[0] = 0x00;
936 nxt200x_writereg_multibyte(state, 0x08, buf, 1);
937
938 /* write agc sdm configure */
939 buf[0] = 0xD7;
940 nxt200x_writebytes(state, 0x57, buf, 1);
941
942 /* ???*/
943 buf[0] = 0x07;
944 buf[1] = 0xfe;
945 nxt200x_writebytes(state, 0x35, buf, 2);
946 buf[0] = 0x12;
947 nxt200x_writebytes(state, 0x34, buf, 1);
948 buf[0] = 0x80;
949 nxt200x_writebytes(state, 0x21, buf, 1);
950
951 /* ???*/
952 buf[0] = 0x21;
953 nxt200x_writebytes(state, 0x0A, buf, 1);
954
955 /* ???*/
956 buf[0] = 0x01;
957 nxt200x_writereg_multibyte(state, 0x80, buf, 1);
958
959 /* write fec mpeg mode */
960 buf[0] = 0x7E;
961 buf[1] = 0x00;
962 nxt200x_writebytes(state, 0xE9, buf, 2);
963
964 /* write mux selection */
965 buf[0] = 0x00;
966 nxt200x_writebytes(state, 0xCC, buf, 1);
967
968 /* ???*/
969 nxt200x_readreg_multibyte(state, 0x80, buf, 1);
970 buf[0] = 0x00;
971 nxt200x_writereg_multibyte(state, 0x80, buf, 1);
972
973 /* soft reset? */
974 nxt200x_readreg_multibyte(state, 0x08, buf, 1);
975 buf[0] = 0x10;
976 nxt200x_writereg_multibyte(state, 0x08, buf, 1);
977 nxt200x_readreg_multibyte(state, 0x08, buf, 1);
978 buf[0] = 0x00;
979 nxt200x_writereg_multibyte(state, 0x08, buf, 1);
980
981 /* ???*/
982 nxt200x_readreg_multibyte(state, 0x80, buf, 1);
983 buf[0] = 0x01;
984 nxt200x_writereg_multibyte(state, 0x80, buf, 1);
985 buf[0] = 0x70;
986 nxt200x_writereg_multibyte(state, 0x81, buf, 1);
987 buf[0] = 0x31; buf[1] = 0x5E; buf[2] = 0x66;
988 nxt200x_writereg_multibyte(state, 0x82, buf, 3);
989
990 nxt200x_readreg_multibyte(state, 0x88, buf, 1);
991 buf[0] = 0x11;
992 nxt200x_writereg_multibyte(state, 0x88, buf, 1);
993 nxt200x_readreg_multibyte(state, 0x80, buf, 1);
994 buf[0] = 0x40;
995 nxt200x_writereg_multibyte(state, 0x80, buf, 1);
996
997 nxt200x_readbytes(state, 0x10, buf, 1);
998 buf[0] = 0x10;
999 nxt200x_writebytes(state, 0x10, buf, 1);
1000 nxt200x_readbytes(state, 0x0A, buf, 1);
1001 buf[0] = 0x21;
1002 nxt200x_writebytes(state, 0x0A, buf, 1);
1003
1004 nxt2004_microcontroller_init(state);
1005
1006 buf[0] = 0x21;
1007 nxt200x_writebytes(state, 0x0A, buf, 1);
1008 buf[0] = 0x7E;
1009 nxt200x_writebytes(state, 0xE9, buf, 1);
1010 buf[0] = 0x00;
1011 nxt200x_writebytes(state, 0xEA, buf, 1);
1012
1013 nxt200x_readreg_multibyte(state, 0x80, buf, 1);
1014 buf[0] = 0x00;
1015 nxt200x_writereg_multibyte(state, 0x80, buf, 1);
1016 nxt200x_readreg_multibyte(state, 0x80, buf, 1);
1017 buf[0] = 0x00;
1018 nxt200x_writereg_multibyte(state, 0x80, buf, 1);
1019
1020 /* soft reset? */
1021 nxt200x_readreg_multibyte(state, 0x08, buf, 1);
1022 buf[0] = 0x10;
1023 nxt200x_writereg_multibyte(state, 0x08, buf, 1);
1024 nxt200x_readreg_multibyte(state, 0x08, buf, 1);
1025 buf[0] = 0x00;
1026 nxt200x_writereg_multibyte(state, 0x08, buf, 1);
1027
1028 nxt200x_readreg_multibyte(state, 0x80, buf, 1);
1029 buf[0] = 0x04;
1030 nxt200x_writereg_multibyte(state, 0x80, buf, 1);
1031 buf[0] = 0x00;
1032 nxt200x_writereg_multibyte(state, 0x81, buf, 1);
1033 buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;
1034 nxt200x_writereg_multibyte(state, 0x82, buf, 3);
1035
1036 nxt200x_readreg_multibyte(state, 0x88, buf, 1);
1037 buf[0] = 0x11;
1038 nxt200x_writereg_multibyte(state, 0x88, buf, 1);
1039
1040 nxt200x_readreg_multibyte(state, 0x80, buf, 1);
1041 buf[0] = 0x44;
1042 nxt200x_writereg_multibyte(state, 0x80, buf, 1);
1043
1044 /* initialize tuner */
1045 nxt200x_readbytes(state, 0x10, buf, 1);
1046 buf[0] = 0x12;
1047 nxt200x_writebytes(state, 0x10, buf, 1);
1048 buf[0] = 0x04;
1049 nxt200x_writebytes(state, 0x13, buf, 1);
1050 buf[0] = 0x00;
1051 nxt200x_writebytes(state, 0x16, buf, 1);
1052 buf[0] = 0x04;
1053 nxt200x_writebytes(state, 0x14, buf, 1);
1054 buf[0] = 0x00;
1055 nxt200x_writebytes(state, 0x14, buf, 1);
1056 nxt200x_writebytes(state, 0x17, buf, 1);
1057 nxt200x_writebytes(state, 0x14, buf, 1);
1058 nxt200x_writebytes(state, 0x17, buf, 1);
1059
1060 return 0;
1061}
1062
1063static int nxt200x_init(struct dvb_frontend* fe)
1064{
1065 struct nxt200x_state* state = fe->demodulator_priv;
1066 int ret = 0;
1067
1068 if (!state->initialised) {
1069 switch (state->demod_chip) {
1070 case NXT2002:
1071 ret = nxt2002_init(fe);
1072 break;
1073 case NXT2004:
1074 ret = nxt2004_init(fe);
1075 break;
1076 default:
1077 return -EINVAL;
1078 break;
1079 }
1080 state->initialised = 1;
1081 }
1082 return ret;
1083}
1084
1085static int nxt200x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
1086{
1087 fesettings->min_delay_ms = 500;
1088 fesettings->step_size = 0;
1089 fesettings->max_drift = 0;
1090 return 0;
1091}
1092
1093static void nxt200x_release(struct dvb_frontend* fe)
1094{
1095 struct nxt200x_state* state = fe->demodulator_priv;
1096 kfree(state);
1097}
1098
1099static struct dvb_frontend_ops nxt200x_ops;
1100
1101struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
1102 struct i2c_adapter* i2c)
1103{
1104 struct nxt200x_state* state = NULL;
1105 u8 buf [] = {0,0,0,0,0};
1106
1107 /* allocate memory for the internal state */
1108 state = (struct nxt200x_state*) kmalloc(sizeof(struct nxt200x_state), GFP_KERNEL);
1109 if (state == NULL)
1110 goto error;
1111 memset(state,0,sizeof(*state));
1112
1113 /* setup the state */
1114 state->config = config;
1115 state->i2c = i2c;
1116 memcpy(&state->ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops));
1117 state->initialised = 0;
1118
1119 /* read card id */
1120 nxt200x_readbytes(state, 0x00, buf, 5);
1121 dprintk("NXT info: %02X %02X %02X %02X %02X\n",
1122 buf[0], buf[1], buf[2], buf[3], buf[4]);
1123
1124 /* set demod chip */
1125 switch (buf[0]) {
1126 case 0x04:
1127 state->demod_chip = NXT2002;
1128 printk("nxt200x: NXT2002 Detected\n");
1129 break;
1130 case 0x05:
1131 state->demod_chip = NXT2004;
1132 printk("nxt200x: NXT2004 Detected\n");
1133 break;
1134 default:
1135 goto error;
1136 }
1137
1138 /* make sure demod chip is supported */
1139 switch (state->demod_chip) {
1140 case NXT2002:
1141 if (buf[0] != 0x04) goto error; /* device id */
1142 if (buf[1] != 0x02) goto error; /* fab id */
1143 if (buf[2] != 0x11) goto error; /* month */
1144 if (buf[3] != 0x20) goto error; /* year msb */
1145 if (buf[4] != 0x00) goto error; /* year lsb */
1146 break;
1147 case NXT2004:
1148 if (buf[0] != 0x05) goto error; /* device id */
1149 break;
1150 default:
1151 goto error;
1152 }
1153
1154 /* create dvb_frontend */
1155 state->frontend.ops = &state->ops;
1156 state->frontend.demodulator_priv = state;
1157 return &state->frontend;
1158
1159error:
1160 if (state)
1161 kfree(state);
1162 printk("Unknown/Unsupported NXT chip: %02X %02X %02X %02X %02X\n",
1163 buf[0], buf[1], buf[2], buf[3], buf[4]);
1164 return NULL;
1165}
1166
1167static struct dvb_frontend_ops nxt200x_ops = {
1168
1169 .info = {
1170 .name = "Nextwave NXT200X VSB/QAM frontend",
1171 .type = FE_ATSC,
1172 .frequency_min = 54000000,
1173 .frequency_max = 860000000,
1174 .frequency_stepsize = 166666, /* stepsize is just a guess */
1175 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1176 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1177 FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256
1178 },
1179
1180 .release = nxt200x_release,
1181
1182 .init = nxt200x_init,
1183 .sleep = nxt200x_sleep,
1184
1185 .set_frontend = nxt200x_setup_frontend_parameters,
1186 .get_tune_settings = nxt200x_get_tune_settings,
1187
1188 .read_status = nxt200x_read_status,
1189 .read_ber = nxt200x_read_ber,
1190 .read_signal_strength = nxt200x_read_signal_strength,
1191 .read_snr = nxt200x_read_snr,
1192 .read_ucblocks = nxt200x_read_ucblocks,
1193};
1194
1195module_param(debug, int, 0644);
1196MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
1197
1198MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
1199MODULE_AUTHOR("Kirk Lapray, Jean-Francois Thibert, and Taylor Jacob");
1200MODULE_LICENSE("GPL");
1201
1202EXPORT_SYMBOL(nxt200x_attach);
1203