ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / media / dvb / frontends / alps_tdlb7.c
1 /*
2     Driver for Alps TDLB7 Frontend
3
4     Copyright (C) 1999 Juergen Peitz
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
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
23
24 /* 
25     This driver needs a copy of the firmware file 'Sc_main.mc' from the Haupauge
26     windows driver in the '/usr/lib/DVB/driver/frontends' directory.
27     You can also pass the complete file name with the module parameter 'firmware_file'.
28     
29 */  
30
31
32 #define __KERNEL_SYSCALLS__
33 #include <linux/module.h>
34 #include <linux/init.h>
35 #include <linux/vmalloc.h>
36 #include <linux/fs.h>
37 #include <linux/unistd.h>
38 #include <linux/delay.h>
39 #include <linux/syscalls.h>
40
41 #include "dvb_frontend.h"
42 #include "dvb_functions.h"
43
44 #ifndef CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION
45 #define CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION "/usr/lib/DVB/driver/frontends/Sc_main.mc"
46 #endif
47
48 static char * firmware_file = CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION;
49 static int debug = 0;
50
51 #define dprintk if (debug) printk
52
53 /* firmware size for sp8870 */
54 #define SP8870_FIRMWARE_SIZE 16382
55
56 /* starting point for firmware in file 'Sc_main.mc' */
57 #define SP8870_FIRMWARE_OFFSET 0x0A
58
59
60 static int errno;
61
62 static struct dvb_frontend_info tdlb7_info = {
63         .name                   = "Alps TDLB7",
64         .type                   = FE_OFDM,
65         .frequency_min          = 470000000,
66         .frequency_max          = 860000000,
67         .frequency_stepsize     = 166666,
68         .caps                   = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
69                                   FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
70                                   FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
71                                   FE_CAN_QPSK | FE_CAN_QAM_16 |
72                                   FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
73                                   FE_CAN_HIERARCHY_AUTO |  FE_CAN_RECOVER
74 };
75
76
77 static int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data)
78 {
79         u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };
80         struct i2c_msg msg = { .addr = 0x71, .flags = 0, .buf = buf, .len = 4 };
81         int err;
82
83         if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {
84                 dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
85                 return -EREMOTEIO;
86         }
87
88         return 0;
89 }
90
91
92 static u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg)
93 {
94         int ret;
95         u8 b0 [] = { reg >> 8 , reg & 0xff };
96         u8 b1 [] = { 0, 0 };
97         struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 },
98                            { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
99
100         ret = i2c->xfer (i2c, msg, 2);
101
102         if (ret != 2) {
103                 dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
104                 return -1;
105         }
106
107         return (b1[0] << 8 | b1[1]);
108 }
109
110
111 static int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4])
112 {
113         int ret;
114         struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = 4 };
115
116         ret = i2c->xfer (i2c, &msg, 1);
117
118         if (ret != 1)
119                 printk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret);
120
121         return (ret != 1) ? -1 : 0;
122 }
123
124
125 static void sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq)
126 {
127         u32 div = (freq + 36200000) / 166666;
128         u8 buf [4];
129         int pwr;
130
131         if (freq <= 782000000)
132                 pwr = 1;
133         else 
134                 pwr = 2;
135
136         buf[0] = (div >> 8) & 0x7f;
137         buf[1] = div & 0xff;
138         buf[2] = 0x85;
139         buf[3] = pwr << 6;
140
141         /* open i2c gate for PLL message transmission... */
142         sp8870_writereg(i2c, 0x206, 0x001);
143         sp5659_write (i2c, buf);
144         sp8870_writereg(i2c, 0x206, 0x000);
145 }
146
147
148 static int sp8870_read_firmware_file (const char *fn, char **fp)
149 {
150         int fd;
151         loff_t filesize;
152         char *dp;
153
154         fd = open(fn, 0, 0);
155         if (fd == -1) {
156                 printk("%s: unable to open '%s'.\n", __FUNCTION__, fn);
157                 return -EIO;
158         }
159
160         filesize = lseek(fd, 0L, 2);
161         if (filesize <= 0 || filesize < SP8870_FIRMWARE_OFFSET + SP8870_FIRMWARE_SIZE) {
162                 printk("%s: firmware filesize to small '%s'\n", __FUNCTION__, fn);
163                 sys_close(fd);
164                 return -EIO;
165         }
166
167         *fp= dp = vmalloc(SP8870_FIRMWARE_SIZE);
168         if (dp == NULL) {
169                 printk("%s: out of memory loading '%s'.\n", __FUNCTION__, fn);
170                 sys_close(fd);
171                 return -EIO;
172         }
173
174         lseek(fd, SP8870_FIRMWARE_OFFSET, 0);
175         if (read(fd, dp, SP8870_FIRMWARE_SIZE) != SP8870_FIRMWARE_SIZE) {
176                 printk("%s: failed to read '%s'.\n",__FUNCTION__, fn);
177                 vfree(dp);
178                 sys_close(fd);
179                 return -EIO;
180         }
181
182         sys_close(fd);
183         *fp = dp;
184
185         return 0;
186 }
187
188
189 static int sp8870_firmware_upload (struct dvb_i2c_bus *i2c)
190 {
191         struct i2c_msg msg;
192         char *fw_buf = NULL;
193         int fw_pos;
194         u8 tx_buf[255];
195         int tx_len;
196         int err = 0;
197         mm_segment_t fs = get_fs();
198
199         dprintk ("%s: ...\n", __FUNCTION__);
200
201         // system controller stop 
202         sp8870_writereg(i2c,0x0F00,0x0000);
203
204         // instruction RAM register hiword
205         sp8870_writereg(i2c, 0x8F08, ((SP8870_FIRMWARE_SIZE / 2) & 0xFFFF));
206
207         // instruction RAM MWR
208         sp8870_writereg(i2c, 0x8F0A, ((SP8870_FIRMWARE_SIZE / 2) >> 16));
209
210         // reading firmware file to buffer
211         set_fs(get_ds());
212         err = sp8870_read_firmware_file(firmware_file, (char**) &fw_buf);
213         set_fs(fs);
214         if (err != 0) {
215                 printk("%s: reading firmware file failed!\n", __FUNCTION__);
216                 return err;
217         }
218
219         // do firmware upload
220         fw_pos = 0;
221         while (fw_pos < SP8870_FIRMWARE_SIZE){
222                 tx_len = (fw_pos <= SP8870_FIRMWARE_SIZE - 252) ? 252 : SP8870_FIRMWARE_SIZE - fw_pos;
223                 // write register 0xCF0A
224                 tx_buf[0] = 0xCF;
225                 tx_buf[1] = 0x0A;
226                 memcpy(&tx_buf[2], fw_buf + fw_pos, tx_len);
227                 msg.addr=0x71;
228                 msg.flags=0;
229                 msg.buf = tx_buf;
230                 msg.len = tx_len + 2;
231                 if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {
232                         printk("%s: firmware upload failed!\n", __FUNCTION__);
233                         printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
234                         vfree(fw_buf);
235                         return err;
236                 }
237                 fw_pos += tx_len;
238         }
239
240         vfree(fw_buf);
241
242         dprintk ("%s: done!\n", __FUNCTION__);
243         return 0;
244 };
245
246
247 static void sp8870_microcontroller_stop (struct dvb_i2c_bus *i2c)
248 {
249         sp8870_writereg(i2c, 0x0F08, 0x000);
250         sp8870_writereg(i2c, 0x0F09, 0x000);
251
252         // microcontroller STOP
253         sp8870_writereg(i2c, 0x0F00, 0x000);
254 }
255
256
257 static void sp8870_microcontroller_start (struct dvb_i2c_bus *i2c)
258 {
259         sp8870_writereg(i2c, 0x0F08, 0x000);
260         sp8870_writereg(i2c, 0x0F09, 0x000);
261
262         // microcontroller START
263         sp8870_writereg(i2c, 0x0F00, 0x001);
264         // not documented but if we don't read 0x0D01 out here
265         // we don't get a correct data valid signal
266         sp8870_readreg(i2c, 0x0D01);
267 }
268
269
270 static int sp8870_init (struct dvb_i2c_bus *i2c)
271 {
272         dprintk ("%s\n", __FUNCTION__);
273
274         /* enable TS output and interface pins */
275         sp8870_writereg(i2c, 0xc18, 0x00d);
276
277         // system controller stop 
278         sp8870_microcontroller_stop(i2c);
279
280         // ADC mode
281         sp8870_writereg(i2c,0x0301,0x0003);
282
283         // Reed Solomon parity bytes passed to output
284         sp8870_writereg(i2c,0x0C13,0x0001);
285
286         // MPEG clock is suppressed if no valid data
287         sp8870_writereg(i2c,0x0C14,0x0001);
288
289         /* bit 0x010: enable data valid signal */
290         sp8870_writereg(i2c, 0x0D00, 0x010);
291         sp8870_writereg(i2c, 0x0D01, 0x000);
292
293         return 0;
294 }
295
296
297 static int sp8870_read_status (struct dvb_i2c_bus *i2c,  fe_status_t * fe_status)
298 {
299         int status;
300         int signal;
301
302         *fe_status = 0;
303
304         status = sp8870_readreg (i2c, 0x0200);
305         if (status < 0)
306                 return -EIO;
307
308         signal = sp8870_readreg (i2c, 0x0303);
309         if (signal < 0)
310                 return -EIO;
311
312         if (signal > 0x0F)
313                 *fe_status |= FE_HAS_SIGNAL;
314         if (status & 0x08)
315                 *fe_status |= FE_HAS_SYNC;
316         if (status & 0x04)
317                 *fe_status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_VITERBI;
318
319         return 0;
320 }
321
322
323 static int sp8870_read_ber (struct dvb_i2c_bus *i2c, u32 * ber)
324 {
325         int ret;
326         u32 tmp;
327
328         *ber = 0;
329
330         ret = sp8870_readreg(i2c, 0xC08);
331         if (ret < 0)
332                 return -EIO;
333
334         tmp = ret & 0x3F;
335
336         ret = sp8870_readreg(i2c, 0xC07);
337         if (ret < 0)
338                 return -EIO;
339
340          tmp = ret << 6;
341
342         if (tmp >= 0x3FFF0)
343                 tmp = ~0;
344
345         *ber = tmp;
346
347         return 0;
348         }
349
350
351 static int sp8870_read_signal_strength (struct dvb_i2c_bus *i2c,  u16 * signal)
352         {
353         int ret;
354         u16 tmp;
355
356         *signal = 0;
357
358         ret = sp8870_readreg (i2c, 0x306);
359         if (ret < 0)
360                 return -EIO;
361
362         tmp = ret << 8;
363
364         ret = sp8870_readreg (i2c, 0x303);
365         if (ret < 0)
366                 return -EIO;
367
368         tmp |= ret;
369
370         if (tmp)
371                 *signal = 0xFFFF - tmp;
372
373         return 0;
374         }
375
376
377 static int sp8870_read_snr(struct dvb_i2c_bus *i2c, u32* snr)
378         {
379                 *snr=0;  
380                 return -EOPNOTSUPP;
381         }
382
383
384 static int sp8870_read_uncorrected_blocks (struct dvb_i2c_bus *i2c, u32* ublocks)
385         {
386                 int ret;
387
388                 *ublocks=0;  
389
390                 ret = sp8870_readreg(i2c, 0xC0C);
391                 if (ret < 0)
392                         return -EIO;
393
394                 if (ret == 0xFFFF)
395                         ret = ~0;
396
397                 *ublocks = ret;
398
399                 return 0;
400         }
401
402
403 static int sp8870_read_data_valid_signal(struct dvb_i2c_bus *i2c)
404 {
405         return (sp8870_readreg(i2c, 0x0D02) > 0);
406 }
407
408
409 static
410 int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
411 {
412         int known_parameters = 1;
413
414         *reg0xc05 = 0x000;
415
416         switch (p->u.ofdm.constellation) {
417         case QPSK:
418                 break;
419         case QAM_16:
420                 *reg0xc05 |= (1 << 10);
421                 break;
422         case QAM_64:
423                 *reg0xc05 |= (2 << 10);
424                 break;
425         case QAM_AUTO:
426                 known_parameters = 0;
427                 break;
428         default:
429                 return -EINVAL;
430         };
431
432         switch (p->u.ofdm.hierarchy_information) {
433         case HIERARCHY_NONE:
434                 break;
435         case HIERARCHY_1:
436                 *reg0xc05 |= (1 << 7);
437                 break;
438         case HIERARCHY_2:
439                 *reg0xc05 |= (2 << 7);
440                 break;
441         case HIERARCHY_4:
442                 *reg0xc05 |= (3 << 7);
443                 break;
444         case HIERARCHY_AUTO:
445                 known_parameters = 0;
446                 break;
447         default:
448                 return -EINVAL;
449         };
450
451         switch (p->u.ofdm.code_rate_HP) {
452         case FEC_1_2:
453                 break;
454         case FEC_2_3:
455                 *reg0xc05 |= (1 << 3);
456                 break;
457         case FEC_3_4:
458                 *reg0xc05 |= (2 << 3);
459                 break;
460         case FEC_5_6:
461                 *reg0xc05 |= (3 << 3);
462                 break;
463         case FEC_7_8:
464                 *reg0xc05 |= (4 << 3);
465                 break;
466         case FEC_AUTO:
467                 known_parameters = 0;
468                 break;
469         default:
470                 return -EINVAL;
471         };
472
473         if (known_parameters)
474                 *reg0xc05 |= (2 << 1);  /* use specified parameters */
475         else
476                 *reg0xc05 |= (1 << 1);  /* enable autoprobing */
477
478         return 0;
479 }
480
481
482 static int sp8870_set_frontend_parameters (struct dvb_i2c_bus *i2c,
483                                       struct dvb_frontend_parameters *p)
484         {
485         int  err;
486         u16 reg0xc05;
487
488         if ((err = configure_reg0xc05(p, &reg0xc05)))
489                 return err;
490
491                 // system controller stop 
492         sp8870_microcontroller_stop(i2c);
493
494         // set tuner parameters
495                 sp5659_set_tv_freq (i2c, p->frequency);
496
497                 // sample rate correction bit [23..17]
498                 sp8870_writereg(i2c,0x0319,0x000A);
499                 
500                 // sample rate correction bit [16..0]
501                 sp8870_writereg(i2c,0x031A,0x0AAB);
502
503                 // integer carrier offset 
504                 sp8870_writereg(i2c,0x0309,0x0400);
505
506                 // fractional carrier offset
507                 sp8870_writereg(i2c,0x030A,0x0000);
508
509                 // filter for 6/7/8 Mhz channel
510                 if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
511                         sp8870_writereg(i2c,0x0311,0x0002);
512                 else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
513                         sp8870_writereg(i2c,0x0311,0x0001);
514                 else
515                         sp8870_writereg(i2c,0x0311,0x0000);
516
517                 // scan order: 2k first = 0x0000, 8k first = 0x0001 
518                 if (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_2K)
519                         sp8870_writereg(i2c,0x0338,0x0000);
520                 else
521                         sp8870_writereg(i2c,0x0338,0x0001);
522
523         sp8870_writereg(i2c, 0xc05, reg0xc05);
524
525         // read status reg in order to clear pending irqs
526         sp8870_readreg(i2c, 0x200);
527
528                 // system controller start
529         sp8870_microcontroller_start(i2c);
530
531         return 0;
532         }
533
534
535 // number of trials to recover from lockup
536 #define MAXTRIALS 5
537 // maximum checks for data valid signal
538 #define MAXCHECKS 100
539
540 // only for debugging: counter for detected lockups
541 static int lockups = 0;
542 // only for debugging: counter for channel switches
543 static int switches = 0;
544
545 static int sp8870_set_frontend (struct dvb_i2c_bus *i2c, struct dvb_frontend_parameters *p)
546         {
547         /*
548             The firmware of the sp8870 sometimes locks up after setting frontend parameters.
549             We try to detect this by checking the data valid signal.
550             If it is not set after MAXCHECKS we try to recover the lockup by setting
551             the frontend parameters again.
552         */
553
554         int err = 0;
555         int valid = 0;
556         int trials = 0;
557         int check_count = 0;
558
559         dprintk("%s: frequency = %i\n", __FUNCTION__, p->frequency);
560
561         for (trials = 1; trials <= MAXTRIALS; trials++) {
562
563                 if ((err = sp8870_set_frontend_parameters(i2c, p)))
564                         return err;
565
566                 for (check_count = 0; check_count < MAXCHECKS; check_count++) {
567 //                      valid = ((sp8870_readreg(i2c, 0x0200) & 4) == 0);
568                         valid = sp8870_read_data_valid_signal(i2c);
569                         if (valid) {
570                                 dprintk("%s: delay = %i usec\n",
571                                         __FUNCTION__, check_count * 10);
572                                 break;
573                         }
574                         udelay(10);
575                 }
576                 if (valid)
577                 break;
578         }
579
580         if (!valid) {
581                 printk("%s: firmware crash!!!!!!\n", __FUNCTION__);
582                 return -EIO;
583         }
584
585         if (debug) {
586                 if (valid) {
587                         if (trials > 1) {
588                                 printk("%s: firmware lockup!!!\n", __FUNCTION__);
589                                 printk("%s: recovered after %i trial(s))\n",  __FUNCTION__, trials - 1);
590                                 lockups++;
591                         }
592                 }
593                 switches++;
594                 printk("%s: switches = %i lockups = %i\n", __FUNCTION__, switches, lockups);
595         }
596
597         return 0;
598 }
599
600
601 static int sp8870_sleep(struct dvb_i2c_bus *i2c)
602 {
603         // tristate TS output and disable interface pins
604         return sp8870_writereg(i2c, 0xC18, 0x000);
605 }
606
607
608 static int sp8870_wake_up(struct dvb_i2c_bus *i2c)
609 {
610         // enable TS output and interface pins
611         return sp8870_writereg(i2c, 0xC18, 0x00D);
612 }
613
614
615 static int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
616 {
617         struct dvb_i2c_bus *i2c = fe->i2c;
618
619         switch (cmd) {
620         case FE_GET_INFO:
621                 memcpy (arg, &tdlb7_info, sizeof(struct dvb_frontend_info));
622                 break;
623
624         case FE_READ_STATUS:
625                 return sp8870_read_status(i2c, (fe_status_t *) arg);
626
627         case FE_READ_BER:
628                 return sp8870_read_ber(i2c, (u32 *) arg);
629
630         case FE_READ_SIGNAL_STRENGTH:
631                 return sp8870_read_signal_strength(i2c, (u16 *) arg);
632
633         case FE_READ_SNR:                               // not supported by hardware?
634                 return sp8870_read_snr(i2c, (u32 *) arg);
635
636         case FE_READ_UNCORRECTED_BLOCKS:
637                 return sp8870_read_uncorrected_blocks(i2c, (u32 *) arg);
638
639         case FE_SET_FRONTEND:
640                 return sp8870_set_frontend(i2c, (struct dvb_frontend_parameters*) arg);
641
642         case FE_GET_FRONTEND:                    // FIXME: read known values back from Hardware...
643                 return -EOPNOTSUPP;
644
645         case FE_SLEEP:
646                 return sp8870_sleep(i2c);
647
648         case FE_INIT:
649                 sp8870_wake_up(i2c);
650                 if (fe->data == NULL) {         // first time initialisation...
651                         fe->data = (void*) ~0;
652                         sp8870_init (i2c);
653                 }
654                 break;
655
656         case FE_GET_TUNE_SETTINGS:
657         {
658                 struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
659                 fesettings->min_delay_ms = 150;
660                 fesettings->step_size = 166667;
661                 fesettings->max_drift = 166667*2;
662                 return 0;
663         }           
664             
665         default:
666                 return -EOPNOTSUPP;
667         };
668
669         return 0;
670 }
671
672
673 static int tdlb7_attach (struct dvb_i2c_bus *i2c, void **data)
674 {
675         u8 b0 [] = { 0x02 , 0x00 };
676         u8 b1 [] = { 0, 0 };
677         struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 },
678                                   { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
679
680         dprintk ("%s\n", __FUNCTION__);
681
682         if (i2c->xfer (i2c, msg, 2) != 2)
683                 return -ENODEV;
684
685         sp8870_firmware_upload(i2c);
686
687         return dvb_register_frontend (tdlb7_ioctl, i2c, NULL, &tdlb7_info);
688 }
689
690
691 static void tdlb7_detach (struct dvb_i2c_bus *i2c, void *data)
692 {
693         dprintk ("%s\n", __FUNCTION__);
694
695         dvb_unregister_frontend (tdlb7_ioctl, i2c);
696 }
697
698
699 static int __init init_tdlb7 (void)
700 {
701         dprintk ("%s\n", __FUNCTION__);
702
703         return dvb_register_i2c_device (THIS_MODULE, tdlb7_attach, tdlb7_detach);
704 }
705
706
707 static void __exit exit_tdlb7 (void)
708 {
709         dprintk ("%s\n", __FUNCTION__);
710
711         dvb_unregister_i2c_device (tdlb7_attach);
712 }
713
714
715 module_init(init_tdlb7);
716 module_exit(exit_tdlb7);
717
718
719 MODULE_PARM(debug,"i");
720 MODULE_PARM_DESC(debug, "enable verbose debug messages");
721
722 MODULE_PARM(firmware_file,"s");
723 MODULE_PARM_DESC(firmware_file, "where to find the firmware file");
724
725 MODULE_DESCRIPTION("TDLB7 DVB-T Frontend");
726 MODULE_AUTHOR("Juergen Peitz");
727 MODULE_LICENSE("GPL");
728
729