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