ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / media / dvb / frontends / nxt6000.c
1 /* 
2
3         NxtWave Communications - NXT6000 demodulator driver
4         
5         This driver currently supports:
6         
7         Alps TDME7 (Tuner: MITEL SP5659)
8         Alps TDED4 (Tuner: TI ALP510, external Nxt6000)
9         Comtech DVBT-6k07 (PLL IC: SP5730)
10
11     Copyright (C) 2002-2003 Florian Schirmer <jolt@tuxbox.org>
12     Copyright (C) 2003 Paul Andreassen <paul@andreassen.com.au>
13
14     This program is free software; you can redistribute it and/or modify
15     it under the terms of the GNU General Public License as published by
16     the Free Software Foundation; either version 2 of the License, or
17     (at your option) any later version.
18
19     This program is distributed in the hope that it will be useful,
20     but WITHOUT ANY WARRANTY; without even the implied warranty of
21     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22     GNU General Public License for more details.
23
24     You should have received a copy of the GNU General Public License
25     along with this program; if not, write to the Free Software
26     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27
28 */    
29
30 #include <linux/init.h>
31 #include <linux/kernel.h>
32 #include <linux/module.h>
33 #include <linux/string.h>
34 #include <linux/slab.h>
35
36 #include "dvb_frontend.h"
37 #include "nxt6000.h"
38
39 static int debug = 0;
40
41 MODULE_DESCRIPTION("NxtWave NXT6000 DVB demodulator driver");
42 MODULE_AUTHOR("Florian Schirmer");
43 MODULE_LICENSE("GPL");
44 MODULE_PARM(debug, "i");
45
46 static struct dvb_frontend_info nxt6000_info = {
47
48         .name = "NxtWave NXT6000",
49         .type = FE_OFDM,
50         .frequency_min = 0,
51         .frequency_max = 863250000,
52         .frequency_stepsize = 62500,
53         /*.frequency_tolerance = */     /* FIXME: 12% of SR */
54         .symbol_rate_min = 0,           /* FIXME */
55         .symbol_rate_max = 9360000,     /* FIXME */
56         .symbol_rate_tolerance = 4000,
57         .notifier_delay = 0,
58         .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 
59                 FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | 
60                 FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | 
61                 FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | 
62                 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | 
63                 FE_CAN_HIERARCHY_AUTO,
64 };
65
66 struct nxt6000_config {
67         u8 demod_addr;
68         u8 tuner_addr;
69         u8 tuner_type;
70         u8 clock_inversion;
71 };
72
73 #define TUNER_TYPE_ALP510       0
74 #define TUNER_TYPE_SP5659       1
75 #define TUNER_TYPE_SP5730       2
76
77 #define FE2NXT(fe) ((struct nxt6000_config *)((fe)->data))
78 #define FREQ2DIV(freq) ((freq + 36166667) / 166667)
79
80 #define dprintk if (debug) printk
81
82 static int nxt6000_write(struct dvb_i2c_bus *i2c, u8 addr, u8 reg, u8 data)
83 {
84
85         u8 buf[] = {reg, data};
86         struct i2c_msg msg = {.addr = addr >> 1, .flags = 0, .buf = buf, .len = 2};
87         int ret;
88         
89         if ((ret = i2c->xfer(i2c, &msg, 1)) != 1)
90                 dprintk("nxt6000: nxt6000_write error (.addr = 0x%02X, reg: 0x%02X, data: 0x%02X, ret: %d)\n", addr, reg, data, ret);
91
92         return (ret != 1) ? -EFAULT : 0;
93         
94 }
95
96 static u8 nxt6000_writereg(struct dvb_frontend *fe, u8 reg, u8 data)
97 {
98
99         struct nxt6000_config *nxt = FE2NXT(fe);
100
101         return nxt6000_write(fe->i2c, nxt->demod_addr, reg, data);
102
103 }
104
105 static u8 nxt6000_read(struct dvb_i2c_bus *i2c, u8 addr, u8 reg)
106 {
107
108         int ret;
109         u8 b0[] = {reg};
110         u8 b1[] = {0};
111         struct i2c_msg msgs[] = {
112                 {.addr = addr >> 1,.flags = 0,.buf = b0,.len = 1},
113                 {.addr = addr >> 1,.flags = I2C_M_RD,.buf = b1,.len = 1}
114         };
115
116         ret = i2c->xfer(i2c, msgs, 2);
117         
118         if (ret != 2)
119                 dprintk("nxt6000: nxt6000_read error (.addr = 0x%02X, reg: 0x%02X, ret: %d)\n", addr, reg, ret);
120         
121         return b1[0];
122
123 }
124
125 static u8 nxt6000_readreg(struct dvb_frontend *fe, u8 reg)
126 {
127
128         struct nxt6000_config *nxt = FE2NXT(fe);
129
130         return nxt6000_read(fe->i2c, nxt->demod_addr, reg);
131 }
132
133 static int pll_test(struct dvb_i2c_bus *i2c, u8 demod_addr, u8 tuner_addr)
134 {
135         u8 buf [1];
136         struct i2c_msg msg = {.addr = tuner_addr >> 1,.flags = I2C_M_RD,.buf = buf,.len = 1 };
137         int ret;
138
139         nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */
140         ret = i2c->xfer(i2c, &msg, 1);
141         nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */
142
143         return (ret != 1) ? -EFAULT : 0;
144 }
145
146 static int pll_write(struct dvb_i2c_bus *i2c, u8 demod_addr, u8 tuner_addr, u8 *buf, u8 len)
147 {
148
149         struct i2c_msg msg = {.addr = tuner_addr >> 1, .flags = 0, .buf = buf, .len = len};
150         int ret;
151                                 
152         nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x01);         /* open i2c bus switch */
153         ret = i2c->xfer(i2c, &msg, 1);
154         nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x00);         /* close i2c bus switch */
155                                                                                 
156         if (ret != 1)
157                 dprintk("nxt6000: pll_write error %d\n", ret);
158                                                                                                                                 
159         return (ret != 1) ? -EFAULT : 0;
160
161 }
162
163 static int sp5659_set_tv_freq(struct dvb_frontend *fe, u32 freq)
164 {
165
166         u8 buf[4];
167         struct nxt6000_config *nxt = FE2NXT(fe);
168
169         buf[0] = (FREQ2DIV(freq) >> 8) & 0x7F;
170         buf[1] = FREQ2DIV(freq) & 0xFF;
171         buf[2] = (((FREQ2DIV(freq) >> 15) & 0x03) << 5) | 0x85;
172
173         if ((freq >= 174000000) && (freq < 230000000))
174                 buf[3] = 0x82;
175         else if ((freq >= 470000000) && (freq < 782000000))
176                 buf[3] = 0x85;
177         else if ((freq >= 782000000) && (freq < 863000000))
178                 buf[3] = 0xC5;
179         else
180                 return -EINVAL;
181
182         return pll_write(fe->i2c, nxt->demod_addr, nxt->tuner_addr, buf, 4);
183         
184 }
185
186 static int alp510_set_tv_freq(struct dvb_frontend *fe, u32 freq)
187 {
188
189         u8 buf[4];
190         struct nxt6000_config *nxt = FE2NXT(fe);
191
192         buf[0] = (FREQ2DIV(freq) >> 8) & 0x7F;
193         buf[1] = FREQ2DIV(freq) & 0xFF;
194         buf[2] = 0x85;
195
196 #if 0
197         if ((freq >= 47000000) && (freq < 153000000))
198                 buf[3] = 0x01;
199         else if ((freq >= 153000000) && (freq < 430000000))
200                 buf[3] = 0x02;
201         else if ((freq >= 430000000) && (freq < 824000000))
202                 buf[3] = 0x08;
203         else if ((freq >= 824000000) && (freq < 863000000))
204                 buf[3] = 0x88;
205         else
206                 return -EINVAL;
207 #else
208         if ((freq >= 47000000) && (freq < 153000000))
209                 buf[3] = 0x01;
210         else if ((freq >= 153000000) && (freq < 430000000))
211                 buf[3] = 0x02;
212         else if ((freq >= 430000000) && (freq < 824000000))
213                 buf[3] = 0x0C;
214         else if ((freq >= 824000000) && (freq < 863000000))
215                 buf[3] = 0x8C;
216         else
217                 return -EINVAL;
218 #endif
219
220         return pll_write(fe->i2c, nxt->demod_addr, nxt->tuner_addr, buf, 4);
221         
222 }
223
224 static int sp5730_set_tv_freq(struct dvb_frontend *fe, u32 freq)
225 {
226
227         u8 buf[4];
228         struct nxt6000_config *nxt = FE2NXT(fe);
229
230         buf[0] = (FREQ2DIV(freq) >> 8) & 0x7F;
231         buf[1] = FREQ2DIV(freq) & 0xFF;
232         buf[2] = 0x93;
233
234         if ((freq >= 51000000) && (freq < 132100000))
235                 buf[3] = 0x05;
236         else if ((freq >= 132100000) && (freq < 143000000))
237                 buf[3] = 0x45;
238         else if ((freq >= 146000000) && (freq < 349100000))
239                 buf[3] = 0x06;
240         else if ((freq >= 349100000) && (freq < 397100000))
241                 buf[3] = 0x46;
242         else if ((freq >= 397100000) && (freq < 426000000))
243                 buf[3] = 0x86;
244         else if ((freq >= 430000000) && (freq < 659100000))
245                 buf[3] = 0x03;
246         else if ((freq >= 659100000) && (freq < 759100000))
247                 buf[3] = 0x43;
248         else if ((freq >= 759100000) && (freq < 858000000))
249                 buf[3] = 0x83;
250         else
251                 return -EINVAL;
252
253         return pll_write(fe->i2c, nxt->demod_addr, nxt->tuner_addr, buf, 4);
254         
255 }
256
257 static void nxt6000_reset(struct dvb_frontend *fe)
258 {
259
260         u8 val;
261
262         val = nxt6000_readreg(fe, OFDM_COR_CTL);
263         
264         nxt6000_writereg(fe, OFDM_COR_CTL, val & ~COREACT);
265         nxt6000_writereg(fe, OFDM_COR_CTL, val | COREACT);
266         
267 }
268
269 static int nxt6000_set_bandwidth(struct dvb_frontend *fe, fe_bandwidth_t bandwidth)
270 {
271
272         u16 nominal_rate;
273         int result;
274
275         switch(bandwidth) {
276         
277                 case BANDWIDTH_6_MHZ:
278                 
279                         nominal_rate = 0x55B7;
280                         
281                         break;
282
283                 case BANDWIDTH_7_MHZ:
284
285                         nominal_rate = 0x6400;
286                         
287                         break;
288
289                 case BANDWIDTH_8_MHZ:
290
291                         nominal_rate = 0x7249;
292                         
293                         break;
294
295                 default:
296                         
297                         return -EINVAL;
298                         
299         }
300
301         if ((result = nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_1, nominal_rate & 0xFF)) < 0)
302                 return result;
303                 
304         return nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_2, (nominal_rate >> 8) & 0xFF);
305                 
306 }
307
308 static int nxt6000_set_guard_interval(struct dvb_frontend *fe, fe_guard_interval_t guard_interval)
309 {
310
311         switch(guard_interval) {
312         
313                 case GUARD_INTERVAL_1_32:
314
315                         return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, 0x00 | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x03));
316
317                 case GUARD_INTERVAL_1_16:
318
319                         return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, 0x01 | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x03));
320
321                 case GUARD_INTERVAL_AUTO:
322                 case GUARD_INTERVAL_1_8:
323
324                         return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, 0x02 | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x03));
325
326                 case GUARD_INTERVAL_1_4:
327
328                         return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, 0x03 | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x03));
329                         
330                 default:
331                 
332                         return -EINVAL;
333
334         }
335
336 }
337
338 static int nxt6000_set_inversion(struct dvb_frontend *fe, fe_spectral_inversion_t inversion)
339 {
340
341         switch(inversion) {
342         
343                 case INVERSION_OFF:
344                 
345                         return nxt6000_writereg(fe, OFDM_ITB_CTL, 0x00);
346                         
347                 case INVERSION_ON:
348                 
349                         return nxt6000_writereg(fe, OFDM_ITB_CTL, ITBINV);
350
351                 default:
352                 
353                         return -EINVAL; 
354         
355         }
356
357 }
358
359 static int nxt6000_set_transmission_mode(struct dvb_frontend *fe, fe_transmit_mode_t transmission_mode)
360 {
361
362         int result;
363
364         switch(transmission_mode) {
365
366                 case TRANSMISSION_MODE_2K:      
367
368                         if ((result = nxt6000_writereg(fe, EN_DMD_RACQ, 0x00 | (nxt6000_readreg(fe, EN_DMD_RACQ) & ~0x03))) < 0)
369                                 return result;
370                                 
371                         return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, (0x00 << 2) | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x04));
372
373                 case TRANSMISSION_MODE_8K:      
374                 case TRANSMISSION_MODE_AUTO:    
375
376                         if ((result = nxt6000_writereg(fe, EN_DMD_RACQ, 0x02 | (nxt6000_readreg(fe, EN_DMD_RACQ) & ~0x03))) < 0)
377                                 return result;
378
379                         return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, (0x01 << 2) | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x04));
380
381                 default:
382                         
383                         return -EINVAL;
384         
385         }
386
387 }
388
389 static void nxt6000_setup(struct dvb_frontend *fe)
390 {
391
392         struct nxt6000_config *nxt = FE2NXT(fe);
393
394         nxt6000_writereg(fe, RS_COR_SYNC_PARAM, SYNC_PARAM);
395         nxt6000_writereg(fe, BER_CTRL, /*(1 << 2) |*/ (0x01 << 1) | 0x01);
396         nxt6000_writereg(fe, VIT_COR_CTL, VIT_COR_RESYNC);
397         nxt6000_writereg(fe, OFDM_COR_CTL, (0x01 << 5) | (nxt6000_readreg(fe, OFDM_COR_CTL) & 0x0F));
398         nxt6000_writereg(fe, OFDM_COR_MODEGUARD, FORCEMODE8K | 0x02);
399         nxt6000_writereg(fe, OFDM_AGC_CTL, AGCLAST | INITIAL_AGC_BW);
400         nxt6000_writereg(fe, OFDM_ITB_FREQ_1, 0x06);
401         nxt6000_writereg(fe, OFDM_ITB_FREQ_2, 0x31);
402         nxt6000_writereg(fe, OFDM_CAS_CTL, (0x01 << 7) | (0x02 << 3) | 0x04);
403         nxt6000_writereg(fe, CAS_FREQ, 0xBB);   /* CHECKME */
404         nxt6000_writereg(fe, OFDM_SYR_CTL, 1 << 2);
405         nxt6000_writereg(fe, OFDM_PPM_CTL_1, PPM256);
406         nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_1, 0x49);
407         nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_2, 0x72);
408         nxt6000_writereg(fe, ANALOG_CONTROL_0, 1 << 5);
409         nxt6000_writereg(fe, EN_DMD_RACQ, (1 << 7) | (3 << 4) | 2);
410         nxt6000_writereg(fe, DIAG_CONFIG, TB_SET);
411         
412         if (nxt->clock_inversion)
413                 nxt6000_writereg(fe, SUB_DIAG_MODE_SEL, CLKINVERSION);
414         else
415                 nxt6000_writereg(fe, SUB_DIAG_MODE_SEL, 0);
416                 
417         nxt6000_writereg(fe, TS_FORMAT, 0);
418
419 }
420
421 static void nxt6000_dump_status(struct dvb_frontend *fe)
422 {
423         u8 val;
424
425 /*
426         printk("RS_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, RS_COR_STAT));
427         printk("VIT_SYNC_STATUS: 0x%02X\n", nxt6000_readreg(fe, VIT_SYNC_STATUS));
428         printk("OFDM_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_COR_STAT));
429         printk("OFDM_SYR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_SYR_STAT));
430         printk("OFDM_TPS_RCVD_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_1));
431         printk("OFDM_TPS_RCVD_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_2));
432         printk("OFDM_TPS_RCVD_3: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_3));
433         printk("OFDM_TPS_RCVD_4: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_4));
434         printk("OFDM_TPS_RESERVED_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_1));
435         printk("OFDM_TPS_RESERVED_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_2));
436 */
437         printk("NXT6000 status:");
438
439         val = nxt6000_readreg(fe, RS_COR_STAT);
440         
441         printk(" DATA DESCR LOCK: %d,", val & 0x01);
442         printk(" DATA SYNC LOCK: %d,", (val >> 1) & 0x01);
443
444         val = nxt6000_readreg(fe, VIT_SYNC_STATUS);
445
446         printk(" VITERBI LOCK: %d,", (val >> 7) & 0x01);
447
448         switch((val >> 4) & 0x07) {
449         
450                 case 0x00: 
451                 
452                         printk(" VITERBI CODERATE: 1/2,");
453                         
454                         break;
455         
456                 case 0x01: 
457                 
458                         printk(" VITERBI CODERATE: 2/3,");
459                         
460                         break;
461         
462                 case 0x02: 
463                 
464                         printk(" VITERBI CODERATE: 3/4,");
465                         
466                         break;
467         
468                 case 0x03: 
469                         printk(" VITERBI CODERATE: 5/6,");
470                 break;
471
472                 case 0x04: 
473                         printk(" VITERBI CODERATE: 7/8,");
474                         break;
475
476                 default: 
477                 
478                         printk(" VITERBI CODERATE: Reserved,");
479                         
480         }
481
482         val = nxt6000_readreg(fe, OFDM_COR_STAT);
483         
484         printk(" CHCTrack: %d,", (val >> 7) & 0x01);
485         printk(" TPSLock: %d,", (val >> 6) & 0x01);
486         printk(" SYRLock: %d,", (val >> 5) & 0x01);
487         printk(" AGCLock: %d,", (val >> 4) & 0x01);
488
489         switch(val & 0x0F) {
490         
491                 case 0x00:
492                 
493                         printk(" CoreState: IDLE,");
494                         
495                         break;
496         
497                 case 0x02:
498                 
499                         printk(" CoreState: WAIT_AGC,");
500                         
501                         break;
502         
503                 case 0x03:
504                 
505                         printk(" CoreState: WAIT_SYR,");
506                         
507                         break;
508         
509                 case 0x04:
510                         printk(" CoreState: WAIT_PPM,");
511                 break;
512
513                 case 0x01:
514                         printk(" CoreState: WAIT_TRL,");
515                         break;
516
517                 case 0x05:
518                 
519                         printk(" CoreState: WAIT_TPS,");
520                         
521                         break;
522
523                 case 0x06:
524                 
525                         printk(" CoreState: MONITOR_TPS,");
526                         
527                         break;
528
529                 default: 
530                 
531                         printk(" CoreState: Reserved,");
532                         
533         }
534
535         val = nxt6000_readreg(fe, OFDM_SYR_STAT);
536
537         printk(" SYRLock: %d,", (val >> 4) & 0x01);
538         printk(" SYRMode: %s,", (val >> 2) & 0x01 ? "8K" : "2K");
539
540         switch((val >> 4) & 0x03) {
541         
542                 case 0x00: 
543                 
544                         printk(" SYRGuard: 1/32,");
545                         
546                         break;
547         
548                 case 0x01: 
549                 
550                         printk(" SYRGuard: 1/16,");
551                         
552                         break;
553         
554                 case 0x02: 
555                 
556                         printk(" SYRGuard: 1/8,");
557                         
558                         break;
559         
560                 case 0x03: 
561                 
562                         printk(" SYRGuard: 1/4,");
563                         
564                         break;
565                         
566         }
567
568         val = nxt6000_readreg(fe, OFDM_TPS_RCVD_3);
569         
570         switch((val >> 4) & 0x07) {
571         
572                 case 0x00: 
573                 
574                         printk(" TPSLP: 1/2,");
575                         
576                         break;
577         
578                 case 0x01: 
579                 
580                         printk(" TPSLP: 2/3,");
581                         
582                         break;
583         
584                 case 0x02: 
585                 
586                         printk(" TPSLP: 3/4,");
587                         
588                         break;
589         
590                 case 0x03: 
591                         printk(" TPSLP: 5/6,");
592                 break;
593
594                 case 0x04: 
595                         printk(" TPSLP: 7/8,");
596                         break;
597
598                 default: 
599                 
600                         printk(" TPSLP: Reserved,");
601                         
602         }
603
604         switch(val & 0x07) {
605         
606                 case 0x00: 
607                 
608                         printk(" TPSHP: 1/2,");
609                         
610                         break;
611         
612                 case 0x01: 
613                 
614                         printk(" TPSHP: 2/3,");
615                         
616                         break;
617         
618                 case 0x02: 
619                 
620                         printk(" TPSHP: 3/4,");
621                         
622                         break;
623         
624                 case 0x03: 
625                         printk(" TPSHP: 5/6,");
626                 break;
627
628                 case 0x04: 
629                         printk(" TPSHP: 7/8,");
630                         break;
631
632                 default: 
633                 
634                         printk(" TPSHP: Reserved,");
635                         
636         }
637
638         val = nxt6000_readreg(fe, OFDM_TPS_RCVD_4);
639         
640         printk(" TPSMode: %s,", val & 0x01 ? "8K" : "2K");
641         
642         switch((val >> 4) & 0x03) {
643         
644                 case 0x00: 
645                 
646                         printk(" TPSGuard: 1/32,");
647                         
648                         break;
649         
650                 case 0x01: 
651                 
652                         printk(" TPSGuard: 1/16,");
653                         
654                         break;
655         
656                 case 0x02: 
657                 
658                         printk(" TPSGuard: 1/8,");
659                         
660                         break;
661         
662                 case 0x03: 
663                 
664                         printk(" TPSGuard: 1/4,");
665                         
666                         break;
667                         
668         }
669         
670         /* Strange magic required to gain access to RF_AGC_STATUS */
671         nxt6000_readreg(fe, RF_AGC_VAL_1);
672         val = nxt6000_readreg(fe, RF_AGC_STATUS);
673         val = nxt6000_readreg(fe, RF_AGC_STATUS);
674
675         printk(" RF AGC LOCK: %d,", (val >> 4) & 0x01);
676
677         printk("\n");
678         
679 }
680
681 static int nxt6000_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
682 {
683
684         switch (cmd) {
685
686                 case FE_GET_INFO:
687
688                         memcpy(arg, &nxt6000_info, sizeof (struct dvb_frontend_info));
689
690                         return 0;
691
692                 case FE_READ_STATUS:
693                 {
694                         fe_status_t *status = (fe_status_t *)arg;
695
696                         u8 core_status;
697
698                         *status = 0;
699                         
700                         core_status = nxt6000_readreg(fe, OFDM_COR_STAT);
701
702                         if (core_status & AGCLOCKED)
703                                 *status |= FE_HAS_SIGNAL;
704
705                         if (nxt6000_readreg(fe, OFDM_SYR_STAT) & GI14_SYR_LOCK)
706                                 *status |= FE_HAS_CARRIER;
707
708                         if (nxt6000_readreg(fe, VIT_SYNC_STATUS) & VITINSYNC)
709                                 *status |= FE_HAS_VITERBI;
710
711                         if (nxt6000_readreg(fe, RS_COR_STAT) & RSCORESTATUS)
712                                 *status |= FE_HAS_SYNC;
713                                 
714                         if ((core_status & TPSLOCKED) && (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)))
715                                 *status |= FE_HAS_LOCK;
716                                 
717                         if (debug)
718                                 nxt6000_dump_status(fe);
719
720                         return 0;
721                         
722                 }
723         
724                 case FE_READ_BER:
725                 {
726                         u32 *ber = (u32 *)arg;
727
728                         *ber=0;
729
730                         return 0;
731                         
732                 }
733         
734                 case FE_READ_SIGNAL_STRENGTH:
735                 {
736                         s16 *signal = (s16 *) arg;
737 /*
738                         *signal=(((signed char)readreg(client, 0x16))+128)<<8;
739 */
740                         *signal = 0;
741                         return 0;
742                         
743                 }
744         
745                 case FE_READ_SNR:
746                 {
747                         s16 *snr = (s16 *) arg;
748 /*
749                         *snr=readreg(client, 0x24)<<8;
750                         *snr|=readreg(client, 0x25);
751 */
752                         *snr = 0;
753                         break;
754                 }
755         
756                 case FE_READ_UNCORRECTED_BLOCKS: 
757                 {
758                         u32 *ublocks = (u32 *)arg;
759
760                         *ublocks = 0;
761
762                         break;
763                 }
764         
765                 case FE_INIT:
766                         nxt6000_reset(fe);
767                         nxt6000_setup(fe);
768                 break;
769
770                 case FE_SET_FRONTEND:
771                 {
772                         struct nxt6000_config *nxt = FE2NXT(fe);
773                         struct dvb_frontend_parameters *param = (struct dvb_frontend_parameters *)arg;
774                         int result;
775
776                         switch(nxt->tuner_type) {
777                         
778                                 case TUNER_TYPE_ALP510:
779
780                                         if ((result = alp510_set_tv_freq(fe, param->frequency)) < 0)
781                                                 return result;
782                                                 
783                                         break;
784
785                                 case TUNER_TYPE_SP5659:
786
787                                         if ((result = sp5659_set_tv_freq(fe, param->frequency)) < 0)
788                                                 return result;
789                                                 
790                                         break;
791                                         
792                                 case TUNER_TYPE_SP5730:
793
794                                         if ((result = sp5730_set_tv_freq(fe, param->frequency)) < 0)
795                                                 return result;
796
797                                         break;
798
799                                 default:
800                                 
801                                         return -EFAULT;
802                                         
803                         }
804
805                         if ((result = nxt6000_set_bandwidth(fe, param->u.ofdm.bandwidth)) < 0)
806                                 return result;
807                         if ((result = nxt6000_set_guard_interval(fe, param->u.ofdm.guard_interval)) < 0)
808                                 return result;
809                         if ((result = nxt6000_set_transmission_mode(fe, param->u.ofdm.transmission_mode)) < 0)
810                                 return result;
811                         if ((result = nxt6000_set_inversion(fe, param->inversion)) < 0)
812                                 return result;
813                         
814                         break;
815                 }
816
817                 default:
818
819                         return -EOPNOTSUPP;
820
821         }
822
823         return 0;
824         
825
826
827 static u8 demod_addr_tbl[] = {0x14, 0x18, 0x24, 0x28};
828
829 static int nxt6000_attach(struct dvb_i2c_bus *i2c, void **data)
830 {
831         u8 addr_nr;
832         u8 fe_count = 0;
833         struct nxt6000_config *pnxt;
834
835         dprintk("nxt6000: attach\n");
836         
837         pnxt = kmalloc(sizeof(demod_addr_tbl)*sizeof(struct nxt6000_config), GFP_KERNEL);
838         if (NULL == pnxt) {
839                 dprintk("nxt6000: no memory for private data.\n");
840                 return -ENOMEM;
841         }
842         *data = pnxt;
843
844         for (addr_nr = 0; addr_nr < sizeof(demod_addr_tbl); addr_nr++) {
845                 struct nxt6000_config *nxt = &pnxt[addr_nr];
846         
847                 if (nxt6000_read(i2c, demod_addr_tbl[addr_nr], OFDM_MSC_REV) != NXT6000ASICDEVICE)
848                         continue;
849
850                 if (pll_test(i2c, demod_addr_tbl[addr_nr], 0xC0) == 0) {
851                         nxt->tuner_addr = 0xC0;
852                         nxt->tuner_type = TUNER_TYPE_ALP510;
853                         nxt->clock_inversion = 1;
854         
855                         dprintk("nxt6000: detected TI ALP510 tuner at 0x%02X\n", nxt->tuner_addr);
856                 
857                 } else if (pll_test(i2c, demod_addr_tbl[addr_nr], 0xC2) == 0) {
858                         nxt->tuner_addr = 0xC2;
859                         nxt->tuner_type = TUNER_TYPE_SP5659;
860                         nxt->clock_inversion = 0;
861
862                         dprintk("nxt6000: detected MITEL SP5659 tuner at 0x%02X\n", nxt->tuner_addr);
863                 
864                 } else if (pll_test(i2c, demod_addr_tbl[addr_nr], 0xC0) == 0) {
865                         nxt->tuner_addr = 0xC0;
866                         nxt->tuner_type = TUNER_TYPE_SP5730;
867                         nxt->clock_inversion = 0;
868
869                         dprintk("nxt6000: detected SP5730 tuner at 0x%02X\n", nxt->tuner_addr);
870                 
871                 } else {
872                         printk("nxt6000: unable to detect tuner\n");
873                         continue;       
874                 }
875                 
876                 nxt->demod_addr = demod_addr_tbl[addr_nr];
877           
878                 dprintk("nxt6000: attached at %d:%d\n", i2c->adapter->num, i2c->id);
879         
880                 dvb_register_frontend(nxt6000_ioctl, i2c, (void *)nxt, &nxt6000_info);
881                 
882                 fe_count++;
883         }
884         
885         if (fe_count == 0) {
886                 kfree(pnxt);
887                 return -ENODEV;
888         }
889         
890         return 0;
891 }
892
893 static void nxt6000_detach(struct dvb_i2c_bus *i2c, void *data)
894 {
895         struct nxt6000_config *pnxt = (struct nxt6000_config *)data;
896         dprintk("nxt6000: detach\n");
897         dvb_unregister_frontend(nxt6000_ioctl, i2c);
898         kfree(pnxt);
899 }
900
901 static __init int nxt6000_init(void)
902 {
903
904         dprintk("nxt6000: init\n");
905         
906         return dvb_register_i2c_device(THIS_MODULE, nxt6000_attach, nxt6000_detach);
907         
908 }
909
910 static __exit void nxt6000_exit(void)
911 {
912
913         dprintk("nxt6000: cleanup\n");
914
915         dvb_unregister_i2c_device(nxt6000_attach);
916
917 }
918
919 module_init(nxt6000_init);
920 module_exit(nxt6000_exit);