Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / drivers / media / dvb / frontends / nxt6000.c
1 /*
2         NxtWave Communications - NXT6000 demodulator driver
3
4     Copyright (C) 2002-2003 Florian Schirmer <jolt@tuxbox.org>
5     Copyright (C) 2003 Paul Andreassen <paul@andreassen.com.au>
6
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <linux/init.h>
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/string.h>
26 #include <linux/slab.h>
27
28 #include "dvb_frontend.h"
29 #include "nxt6000_priv.h"
30 #include "nxt6000.h"
31
32
33
34 struct nxt6000_state {
35         struct i2c_adapter* i2c;
36         struct dvb_frontend_ops ops;
37         /* configuration settings */
38         const struct nxt6000_config* config;
39         struct dvb_frontend frontend;
40 };
41
42 static int debug = 0;
43 #define dprintk if (debug) printk
44
45 static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data)
46 {
47         u8 buf[] = { reg, data };
48         struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 2 };
49         int ret;
50
51         if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
52                 dprintk("nxt6000: nxt6000_write error (reg: 0x%02X, data: 0x%02X, ret: %d)\n", reg, data, ret);
53
54         return (ret != 1) ? -EFAULT : 0;
55 }
56
57 static u8 nxt6000_readreg(struct nxt6000_state* state, u8 reg)
58 {
59         int ret;
60         u8 b0[] = { reg };
61         u8 b1[] = { 0 };
62         struct i2c_msg msgs[] = {
63                 {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 1},
64                 {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
65         };
66
67         ret = i2c_transfer(state->i2c, msgs, 2);
68
69         if (ret != 2)
70                 dprintk("nxt6000: nxt6000_read error (reg: 0x%02X, ret: %d)\n", reg, ret);
71
72         return b1[0];
73 }
74
75 static void nxt6000_reset(struct nxt6000_state* state)
76 {
77         u8 val;
78
79         val = nxt6000_readreg(state, OFDM_COR_CTL);
80
81         nxt6000_writereg(state, OFDM_COR_CTL, val & ~COREACT);
82         nxt6000_writereg(state, OFDM_COR_CTL, val | COREACT);
83 }
84
85 static int nxt6000_set_bandwidth(struct nxt6000_state* state, fe_bandwidth_t bandwidth)
86 {
87         u16 nominal_rate;
88         int result;
89
90         switch (bandwidth) {
91
92         case BANDWIDTH_6_MHZ:
93                 nominal_rate = 0x55B7;
94                 break;
95
96         case BANDWIDTH_7_MHZ:
97                 nominal_rate = 0x6400;
98                 break;
99
100         case BANDWIDTH_8_MHZ:
101                 nominal_rate = 0x7249;
102                 break;
103
104         default:
105                 return -EINVAL;
106         }
107
108         if ((result = nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, nominal_rate & 0xFF)) < 0)
109                 return result;
110
111         return nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, (nominal_rate >> 8) & 0xFF);
112 }
113
114 static int nxt6000_set_guard_interval(struct nxt6000_state* state, fe_guard_interval_t guard_interval)
115 {
116         switch (guard_interval) {
117
118         case GUARD_INTERVAL_1_32:
119                 return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x00 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
120
121         case GUARD_INTERVAL_1_16:
122                 return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x01 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
123
124         case GUARD_INTERVAL_AUTO:
125         case GUARD_INTERVAL_1_8:
126                 return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x02 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
127
128         case GUARD_INTERVAL_1_4:
129                 return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x03 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
130
131         default:
132                 return -EINVAL;
133         }
134 }
135
136 static int nxt6000_set_inversion(struct nxt6000_state* state, fe_spectral_inversion_t inversion)
137 {
138         switch (inversion) {
139
140         case INVERSION_OFF:
141                 return nxt6000_writereg(state, OFDM_ITB_CTL, 0x00);
142
143         case INVERSION_ON:
144                 return nxt6000_writereg(state, OFDM_ITB_CTL, ITBINV);
145
146         default:
147                 return -EINVAL;
148
149         }
150 }
151
152 static int nxt6000_set_transmission_mode(struct nxt6000_state* state, fe_transmit_mode_t transmission_mode)
153 {
154         int result;
155
156         switch (transmission_mode) {
157
158         case TRANSMISSION_MODE_2K:
159                 if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x00 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0)
160                         return result;
161
162                 return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x00 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04));
163
164         case TRANSMISSION_MODE_8K:
165         case TRANSMISSION_MODE_AUTO:
166                 if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x02 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0)
167                         return result;
168
169                 return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x01 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04));
170
171         default:
172                 return -EINVAL;
173
174         }
175 }
176
177 static void nxt6000_setup(struct dvb_frontend* fe)
178 {
179         struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
180
181         nxt6000_writereg(state, RS_COR_SYNC_PARAM, SYNC_PARAM);
182         nxt6000_writereg(state, BER_CTRL, /*(1 << 2) | */ (0x01 << 1) | 0x01);
183         nxt6000_writereg(state, VIT_COR_CTL, VIT_COR_RESYNC);
184         nxt6000_writereg(state, OFDM_COR_CTL, (0x01 << 5) | (nxt6000_readreg(state, OFDM_COR_CTL) & 0x0F));
185         nxt6000_writereg(state, OFDM_COR_MODEGUARD, FORCEMODE8K | 0x02);
186         nxt6000_writereg(state, OFDM_AGC_CTL, AGCLAST | INITIAL_AGC_BW);
187         nxt6000_writereg(state, OFDM_ITB_FREQ_1, 0x06);
188         nxt6000_writereg(state, OFDM_ITB_FREQ_2, 0x31);
189         nxt6000_writereg(state, OFDM_CAS_CTL, (0x01 << 7) | (0x02 << 3) | 0x04);
190         nxt6000_writereg(state, CAS_FREQ, 0xBB);        /* CHECKME */
191         nxt6000_writereg(state, OFDM_SYR_CTL, 1 << 2);
192         nxt6000_writereg(state, OFDM_PPM_CTL_1, PPM256);
193         nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, 0x49);
194         nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, 0x72);
195         nxt6000_writereg(state, ANALOG_CONTROL_0, 1 << 5);
196         nxt6000_writereg(state, EN_DMD_RACQ, (1 << 7) | (3 << 4) | 2);
197         nxt6000_writereg(state, DIAG_CONFIG, TB_SET);
198
199         if (state->config->clock_inversion)
200                 nxt6000_writereg(state, SUB_DIAG_MODE_SEL, CLKINVERSION);
201         else
202                 nxt6000_writereg(state, SUB_DIAG_MODE_SEL, 0);
203
204         nxt6000_writereg(state, TS_FORMAT, 0);
205
206         if (state->config->pll_init) {
207                 nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01);        /* open i2c bus switch */
208                 state->config->pll_init(fe);
209                 nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00);        /* close i2c bus switch */
210         }
211 }
212
213 static void nxt6000_dump_status(struct nxt6000_state *state)
214 {
215         u8 val;
216
217 /*
218         printk("RS_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, RS_COR_STAT));
219         printk("VIT_SYNC_STATUS: 0x%02X\n", nxt6000_readreg(fe, VIT_SYNC_STATUS));
220         printk("OFDM_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_COR_STAT));
221         printk("OFDM_SYR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_SYR_STAT));
222         printk("OFDM_TPS_RCVD_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_1));
223         printk("OFDM_TPS_RCVD_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_2));
224         printk("OFDM_TPS_RCVD_3: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_3));
225         printk("OFDM_TPS_RCVD_4: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_4));
226         printk("OFDM_TPS_RESERVED_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_1));
227         printk("OFDM_TPS_RESERVED_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_2));
228 */
229         printk("NXT6000 status:");
230
231         val = nxt6000_readreg(state, RS_COR_STAT);
232
233         printk(" DATA DESCR LOCK: %d,", val & 0x01);
234         printk(" DATA SYNC LOCK: %d,", (val >> 1) & 0x01);
235
236         val = nxt6000_readreg(state, VIT_SYNC_STATUS);
237
238         printk(" VITERBI LOCK: %d,", (val >> 7) & 0x01);
239
240         switch ((val >> 4) & 0x07) {
241
242         case 0x00:
243                 printk(" VITERBI CODERATE: 1/2,");
244                 break;
245
246         case 0x01:
247                 printk(" VITERBI CODERATE: 2/3,");
248                 break;
249
250         case 0x02:
251                 printk(" VITERBI CODERATE: 3/4,");
252                 break;
253
254         case 0x03:
255                 printk(" VITERBI CODERATE: 5/6,");
256                 break;
257
258         case 0x04:
259                 printk(" VITERBI CODERATE: 7/8,");
260                 break;
261
262         default:
263                 printk(" VITERBI CODERATE: Reserved,");
264
265         }
266
267         val = nxt6000_readreg(state, OFDM_COR_STAT);
268
269         printk(" CHCTrack: %d,", (val >> 7) & 0x01);
270         printk(" TPSLock: %d,", (val >> 6) & 0x01);
271         printk(" SYRLock: %d,", (val >> 5) & 0x01);
272         printk(" AGCLock: %d,", (val >> 4) & 0x01);
273
274         switch (val & 0x0F) {
275
276         case 0x00:
277                 printk(" CoreState: IDLE,");
278                 break;
279
280         case 0x02:
281                 printk(" CoreState: WAIT_AGC,");
282                 break;
283
284         case 0x03:
285                 printk(" CoreState: WAIT_SYR,");
286                 break;
287
288         case 0x04:
289                 printk(" CoreState: WAIT_PPM,");
290                 break;
291
292         case 0x01:
293                 printk(" CoreState: WAIT_TRL,");
294                 break;
295
296         case 0x05:
297                 printk(" CoreState: WAIT_TPS,");
298                 break;
299
300         case 0x06:
301                 printk(" CoreState: MONITOR_TPS,");
302                 break;
303
304         default:
305                 printk(" CoreState: Reserved,");
306
307         }
308
309         val = nxt6000_readreg(state, OFDM_SYR_STAT);
310
311         printk(" SYRLock: %d,", (val >> 4) & 0x01);
312         printk(" SYRMode: %s,", (val >> 2) & 0x01 ? "8K" : "2K");
313
314         switch ((val >> 4) & 0x03) {
315
316         case 0x00:
317                 printk(" SYRGuard: 1/32,");
318                 break;
319
320         case 0x01:
321                 printk(" SYRGuard: 1/16,");
322                 break;
323
324         case 0x02:
325                 printk(" SYRGuard: 1/8,");
326                 break;
327
328         case 0x03:
329                 printk(" SYRGuard: 1/4,");
330                 break;
331         }
332
333         val = nxt6000_readreg(state, OFDM_TPS_RCVD_3);
334
335         switch ((val >> 4) & 0x07) {
336
337         case 0x00:
338                 printk(" TPSLP: 1/2,");
339                 break;
340
341         case 0x01:
342                 printk(" TPSLP: 2/3,");
343                 break;
344
345         case 0x02:
346                 printk(" TPSLP: 3/4,");
347                 break;
348
349         case 0x03:
350                 printk(" TPSLP: 5/6,");
351                 break;
352
353         case 0x04:
354                 printk(" TPSLP: 7/8,");
355                 break;
356
357         default:
358                 printk(" TPSLP: Reserved,");
359
360         }
361
362         switch (val & 0x07) {
363
364         case 0x00:
365                 printk(" TPSHP: 1/2,");
366                 break;
367
368         case 0x01:
369                 printk(" TPSHP: 2/3,");
370                 break;
371
372         case 0x02:
373                 printk(" TPSHP: 3/4,");
374                 break;
375
376         case 0x03:
377                 printk(" TPSHP: 5/6,");
378                 break;
379
380         case 0x04:
381                 printk(" TPSHP: 7/8,");
382                 break;
383
384         default:
385                 printk(" TPSHP: Reserved,");
386
387         }
388
389         val = nxt6000_readreg(state, OFDM_TPS_RCVD_4);
390
391         printk(" TPSMode: %s,", val & 0x01 ? "8K" : "2K");
392
393         switch ((val >> 4) & 0x03) {
394
395         case 0x00:
396                 printk(" TPSGuard: 1/32,");
397                 break;
398
399         case 0x01:
400                 printk(" TPSGuard: 1/16,");
401                 break;
402
403         case 0x02:
404                 printk(" TPSGuard: 1/8,");
405                 break;
406
407         case 0x03:
408                 printk(" TPSGuard: 1/4,");
409                 break;
410
411         }
412
413         /* Strange magic required to gain access to RF_AGC_STATUS */
414         nxt6000_readreg(state, RF_AGC_VAL_1);
415         val = nxt6000_readreg(state, RF_AGC_STATUS);
416         val = nxt6000_readreg(state, RF_AGC_STATUS);
417
418         printk(" RF AGC LOCK: %d,", (val >> 4) & 0x01);
419         printk("\n");
420 }
421
422 static int nxt6000_read_status(struct dvb_frontend* fe, fe_status_t* status)
423 {
424         u8 core_status;
425         struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
426
427         *status = 0;
428
429         core_status = nxt6000_readreg(state, OFDM_COR_STAT);
430
431         if (core_status & AGCLOCKED)
432                 *status |= FE_HAS_SIGNAL;
433
434         if (nxt6000_readreg(state, OFDM_SYR_STAT) & GI14_SYR_LOCK)
435                 *status |= FE_HAS_CARRIER;
436
437         if (nxt6000_readreg(state, VIT_SYNC_STATUS) & VITINSYNC)
438                 *status |= FE_HAS_VITERBI;
439
440         if (nxt6000_readreg(state, RS_COR_STAT) & RSCORESTATUS)
441                 *status |= FE_HAS_SYNC;
442
443         if ((core_status & TPSLOCKED) && (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)))
444                 *status |= FE_HAS_LOCK;
445
446         if (debug)
447                 nxt6000_dump_status(state);
448
449         return 0;
450 }
451
452 static int nxt6000_init(struct dvb_frontend* fe)
453 {
454         struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
455
456         nxt6000_reset(state);
457         nxt6000_setup(fe);
458
459         return 0;
460 }
461
462 static int nxt6000_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *param)
463 {
464         struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
465         int result;
466
467         nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01);        /* open i2c bus switch */
468         state->config->pll_set(fe, param);
469         nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00);        /* close i2c bus switch */
470
471         if ((result = nxt6000_set_bandwidth(state, param->u.ofdm.bandwidth)) < 0)
472                 return result;
473         if ((result = nxt6000_set_guard_interval(state, param->u.ofdm.guard_interval)) < 0)
474                 return result;
475         if ((result = nxt6000_set_transmission_mode(state, param->u.ofdm.transmission_mode)) < 0)
476                 return result;
477         if ((result = nxt6000_set_inversion(state, param->inversion)) < 0)
478                 return result;
479
480         return 0;
481 }
482
483 static void nxt6000_release(struct dvb_frontend* fe)
484 {
485         struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
486         kfree(state);
487 }
488
489 static struct dvb_frontend_ops nxt6000_ops;
490
491 struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
492                                     struct i2c_adapter* i2c)
493 {
494         struct nxt6000_state* state = NULL;
495
496         /* allocate memory for the internal state */
497         state = (struct nxt6000_state*) kmalloc(sizeof(struct nxt6000_state), GFP_KERNEL);
498         if (state == NULL) goto error;
499
500         /* setup the state */
501         state->config = config;
502         state->i2c = i2c;
503         memcpy(&state->ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops));
504
505         /* check if the demod is there */
506         if (nxt6000_readreg(state, OFDM_MSC_REV) != NXT6000ASICDEVICE) goto error;
507
508         /* create dvb_frontend */
509         state->frontend.ops = &state->ops;
510         state->frontend.demodulator_priv = state;
511         return &state->frontend;
512
513 error:
514         kfree(state);
515         return NULL;
516 }
517
518 static struct dvb_frontend_ops nxt6000_ops = {
519
520         .info = {
521                 .name = "NxtWave NXT6000 DVB-T",
522                 .type = FE_OFDM,
523                 .frequency_min = 0,
524                 .frequency_max = 863250000,
525                 .frequency_stepsize = 62500,
526                 /*.frequency_tolerance = *//* FIXME: 12% of SR */
527                 .symbol_rate_min = 0,   /* FIXME */
528                 .symbol_rate_max = 9360000,     /* FIXME */
529                 .symbol_rate_tolerance = 4000,
530                 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
531                         FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
532                         FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
533                         FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
534                         FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
535                         FE_CAN_HIERARCHY_AUTO,
536         },
537
538         .release = nxt6000_release,
539
540         .init = nxt6000_init,
541
542         .set_frontend = nxt6000_set_frontend,
543
544         .read_status = nxt6000_read_status,
545 };
546
547 module_param(debug, int, 0644);
548 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
549
550 MODULE_DESCRIPTION("NxtWave NXT6000 DVB-T demodulator driver");
551 MODULE_AUTHOR("Florian Schirmer");
552 MODULE_LICENSE("GPL");
553
554 EXPORT_SYMBOL(nxt6000_attach);