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