Merge branch 'release' of git://lm-sensors.org/kernel/mhoffman/hwmon-2.6
[linux-2.6] / drivers / media / dvb / frontends / s5h1420.c
1 /*
2  * Driver for
3  *    Samsung S5H1420 and
4  *    PnpNetwork PN1010 QPSK Demodulator
5  *
6  * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
7  * Copyright (C) 2005-8 Patrick Boettcher <pb@linuxtv.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/init.h>
28 #include <linux/string.h>
29 #include <linux/slab.h>
30 #include <linux/delay.h>
31 #include <linux/jiffies.h>
32 #include <asm/div64.h>
33
34 #include <linux/i2c.h>
35
36
37 #include "dvb_frontend.h"
38 #include "s5h1420.h"
39 #include "s5h1420_priv.h"
40
41 #define TONE_FREQ 22000
42
43 struct s5h1420_state {
44         struct i2c_adapter* i2c;
45         const struct s5h1420_config* config;
46
47         struct dvb_frontend frontend;
48         struct i2c_adapter tuner_i2c_adapter;
49
50         u8 CON_1_val;
51
52         u8 postlocked:1;
53         u32 fclk;
54         u32 tunedfreq;
55         fe_code_rate_t fec_inner;
56         u32 symbol_rate;
57
58         /* FIXME: ugly workaround for flexcop's incapable i2c-controller
59          * it does not support repeated-start, workaround: write addr-1
60          * and then read
61          */
62         u8 shadow[255];
63 };
64
65 static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
66 static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
67                                      struct dvb_frontend_tune_settings* fesettings);
68
69
70 static int debug;
71 module_param(debug, int, 0644);
72 MODULE_PARM_DESC(debug, "enable debugging");
73
74 #define dprintk(x...) do { \
75         if (debug) \
76                 printk(KERN_DEBUG "S5H1420: " x); \
77 } while (0)
78
79 static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)
80 {
81         int ret;
82         u8 b[2];
83         struct i2c_msg msg[] = {
84                 { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = 2 },
85                 { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
86                 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = 1 },
87         };
88
89         b[0] = (reg - 1) & 0xff;
90         b[1] = state->shadow[(reg - 1) & 0xff];
91
92         if (state->config->repeated_start_workaround) {
93                 ret = i2c_transfer(state->i2c, msg, 3);
94                 if (ret != 3)
95                         return ret;
96         } else {
97                 ret = i2c_transfer(state->i2c, &msg[1], 2);
98                 if (ret != 2)
99                         return ret;
100         }
101
102         /* dprintk("rd(%02x): %02x %02x\n", state->config->demod_address, reg, b[0]); */
103
104         return b[0];
105 }
106
107 static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data)
108 {
109         u8 buf[] = { reg, data };
110         struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
111         int err;
112
113         /* dprintk("wr(%02x): %02x %02x\n", state->config->demod_address, reg, data); */
114         err = i2c_transfer(state->i2c, &msg, 1);
115         if (err != 1) {
116                 dprintk("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
117                 return -EREMOTEIO;
118         }
119         state->shadow[reg] = data;
120
121         return 0;
122 }
123
124 static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
125 {
126         struct s5h1420_state* state = fe->demodulator_priv;
127
128         dprintk("enter %s\n", __func__);
129
130         switch(voltage) {
131         case SEC_VOLTAGE_13:
132                 s5h1420_writereg(state, 0x3c,
133                                  (s5h1420_readreg(state, 0x3c) & 0xfe) | 0x02);
134                 break;
135
136         case SEC_VOLTAGE_18:
137                 s5h1420_writereg(state, 0x3c, s5h1420_readreg(state, 0x3c) | 0x03);
138                 break;
139
140         case SEC_VOLTAGE_OFF:
141                 s5h1420_writereg(state, 0x3c, s5h1420_readreg(state, 0x3c) & 0xfd);
142                 break;
143         }
144
145         dprintk("leave %s\n", __func__);
146         return 0;
147 }
148
149 static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
150 {
151         struct s5h1420_state* state = fe->demodulator_priv;
152
153         dprintk("enter %s\n", __func__);
154         switch(tone) {
155         case SEC_TONE_ON:
156                 s5h1420_writereg(state, 0x3b,
157                                  (s5h1420_readreg(state, 0x3b) & 0x74) | 0x08);
158                 break;
159
160         case SEC_TONE_OFF:
161                 s5h1420_writereg(state, 0x3b,
162                                  (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
163                 break;
164         }
165         dprintk("leave %s\n", __func__);
166
167         return 0;
168 }
169
170 static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
171                                     struct dvb_diseqc_master_cmd* cmd)
172 {
173         struct s5h1420_state* state = fe->demodulator_priv;
174         u8 val;
175         int i;
176         unsigned long timeout;
177         int result = 0;
178
179         dprintk("enter %s\n", __func__);
180         if (cmd->msg_len > 8)
181                 return -EINVAL;
182
183         /* setup for DISEQC */
184         val = s5h1420_readreg(state, 0x3b);
185         s5h1420_writereg(state, 0x3b, 0x02);
186         msleep(15);
187
188         /* write the DISEQC command bytes */
189         for(i=0; i< cmd->msg_len; i++) {
190                 s5h1420_writereg(state, 0x3d + i, cmd->msg[i]);
191         }
192
193         /* kick off transmission */
194         s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) |
195                                       ((cmd->msg_len-1) << 4) | 0x08);
196
197         /* wait for transmission to complete */
198         timeout = jiffies + ((100*HZ) / 1000);
199         while(time_before(jiffies, timeout)) {
200                 if (!(s5h1420_readreg(state, 0x3b) & 0x08))
201                         break;
202
203                 msleep(5);
204         }
205         if (time_after(jiffies, timeout))
206                 result = -ETIMEDOUT;
207
208         /* restore original settings */
209         s5h1420_writereg(state, 0x3b, val);
210         msleep(15);
211         dprintk("leave %s\n", __func__);
212         return result;
213 }
214
215 static int s5h1420_recv_slave_reply (struct dvb_frontend* fe,
216                                      struct dvb_diseqc_slave_reply* reply)
217 {
218         struct s5h1420_state* state = fe->demodulator_priv;
219         u8 val;
220         int i;
221         int length;
222         unsigned long timeout;
223         int result = 0;
224
225         /* setup for DISEQC recieve */
226         val = s5h1420_readreg(state, 0x3b);
227         s5h1420_writereg(state, 0x3b, 0x82); /* FIXME: guess - do we need to set DIS_RDY(0x08) in receive mode? */
228         msleep(15);
229
230         /* wait for reception to complete */
231         timeout = jiffies + ((reply->timeout*HZ) / 1000);
232         while(time_before(jiffies, timeout)) {
233                 if (!(s5h1420_readreg(state, 0x3b) & 0x80)) /* FIXME: do we test DIS_RDY(0x08) or RCV_EN(0x80)? */
234                         break;
235
236                 msleep(5);
237         }
238         if (time_after(jiffies, timeout)) {
239                 result = -ETIMEDOUT;
240                 goto exit;
241         }
242
243         /* check error flag - FIXME: not sure what this does - docs do not describe
244          * beyond "error flag for diseqc receive data :( */
245         if (s5h1420_readreg(state, 0x49)) {
246                 result = -EIO;
247                 goto exit;
248         }
249
250         /* check length */
251         length = (s5h1420_readreg(state, 0x3b) & 0x70) >> 4;
252         if (length > sizeof(reply->msg)) {
253                 result = -EOVERFLOW;
254                 goto exit;
255         }
256         reply->msg_len = length;
257
258         /* extract data */
259         for(i=0; i< length; i++) {
260                 reply->msg[i] = s5h1420_readreg(state, 0x3d + i);
261         }
262
263 exit:
264         /* restore original settings */
265         s5h1420_writereg(state, 0x3b, val);
266         msleep(15);
267         return result;
268 }
269
270 static int s5h1420_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
271 {
272         struct s5h1420_state* state = fe->demodulator_priv;
273         u8 val;
274         int result = 0;
275         unsigned long timeout;
276
277         /* setup for tone burst */
278         val = s5h1420_readreg(state, 0x3b);
279         s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x70) | 0x01);
280
281         /* set value for B position if requested */
282         if (minicmd == SEC_MINI_B) {
283                 s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x04);
284         }
285         msleep(15);
286
287         /* start transmission */
288         s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x08);
289
290         /* wait for transmission to complete */
291         timeout = jiffies + ((100*HZ) / 1000);
292         while(time_before(jiffies, timeout)) {
293                 if (!(s5h1420_readreg(state, 0x3b) & 0x08))
294                         break;
295
296                 msleep(5);
297         }
298         if (time_after(jiffies, timeout))
299                 result = -ETIMEDOUT;
300
301         /* restore original settings */
302         s5h1420_writereg(state, 0x3b, val);
303         msleep(15);
304         return result;
305 }
306
307 static fe_status_t s5h1420_get_status_bits(struct s5h1420_state* state)
308 {
309         u8 val;
310         fe_status_t status = 0;
311
312         val = s5h1420_readreg(state, 0x14);
313         if (val & 0x02)
314                 status |=  FE_HAS_SIGNAL;
315         if (val & 0x01)
316                 status |=  FE_HAS_CARRIER;
317         val = s5h1420_readreg(state, 0x36);
318         if (val & 0x01)
319                 status |=  FE_HAS_VITERBI;
320         if (val & 0x20)
321                 status |=  FE_HAS_SYNC;
322         if (status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|FE_HAS_SYNC))
323                 status |=  FE_HAS_LOCK;
324
325         return status;
326 }
327
328 static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
329 {
330         struct s5h1420_state* state = fe->demodulator_priv;
331         u8 val;
332
333         dprintk("enter %s\n", __func__);
334
335         if (status == NULL)
336                 return -EINVAL;
337
338         /* determine lock state */
339         *status = s5h1420_get_status_bits(state);
340
341         /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert
342         the inversion, wait a bit and check again */
343         if (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI)) {
344                 val = s5h1420_readreg(state, Vit10);
345                 if ((val & 0x07) == 0x03) {
346                         if (val & 0x08)
347                                 s5h1420_writereg(state, Vit09, 0x13);
348                         else
349                                 s5h1420_writereg(state, Vit09, 0x1b);
350
351                         /* wait a bit then update lock status */
352                         mdelay(200);
353                         *status = s5h1420_get_status_bits(state);
354                 }
355         }
356
357         /* perform post lock setup */
358         if ((*status & FE_HAS_LOCK) && !state->postlocked) {
359
360                 /* calculate the data rate */
361                 u32 tmp = s5h1420_getsymbolrate(state);
362                 switch (s5h1420_readreg(state, Vit10) & 0x07) {
363                 case 0: tmp = (tmp * 2 * 1) / 2; break;
364                 case 1: tmp = (tmp * 2 * 2) / 3; break;
365                 case 2: tmp = (tmp * 2 * 3) / 4; break;
366                 case 3: tmp = (tmp * 2 * 5) / 6; break;
367                 case 4: tmp = (tmp * 2 * 6) / 7; break;
368                 case 5: tmp = (tmp * 2 * 7) / 8; break;
369                 }
370
371                 if (tmp == 0) {
372                         printk(KERN_ERR "s5h1420: avoided division by 0\n");
373                         tmp = 1;
374                 }
375                 tmp = state->fclk / tmp;
376
377
378                 /* set the MPEG_CLK_INTL for the calculated data rate */
379                 if (tmp < 2)
380                         val = 0x00;
381                 else if (tmp < 5)
382                         val = 0x01;
383                 else if (tmp < 9)
384                         val = 0x02;
385                 else if (tmp < 13)
386                         val = 0x03;
387                 else if (tmp < 17)
388                         val = 0x04;
389                 else if (tmp < 25)
390                         val = 0x05;
391                 else if (tmp < 33)
392                         val = 0x06;
393                 else
394                         val = 0x07;
395                 dprintk("for MPEG_CLK_INTL %d %x\n", tmp, val);
396
397                 s5h1420_writereg(state, FEC01, 0x18);
398                 s5h1420_writereg(state, FEC01, 0x10);
399                 s5h1420_writereg(state, FEC01, val);
400
401                 /* Enable "MPEG_Out" */
402                 val = s5h1420_readreg(state, Mpeg02);
403                 s5h1420_writereg(state, Mpeg02, val | (1 << 6));
404
405                 /* kicker disable */
406                 val = s5h1420_readreg(state, QPSK01) & 0x7f;
407                 s5h1420_writereg(state, QPSK01, val);
408
409                 /* DC freeze TODO it was never activated by default or it can stay activated */
410
411                 if (s5h1420_getsymbolrate(state) >= 20000000) {
412                         s5h1420_writereg(state, Loop04, 0x8a);
413                         s5h1420_writereg(state, Loop05, 0x6a);
414                 } else {
415                         s5h1420_writereg(state, Loop04, 0x58);
416                         s5h1420_writereg(state, Loop05, 0x27);
417                 }
418
419                 /* post-lock processing has been done! */
420                 state->postlocked = 1;
421         }
422
423         dprintk("leave %s\n", __func__);
424
425         return 0;
426 }
427
428 static int s5h1420_read_ber(struct dvb_frontend* fe, u32* ber)
429 {
430         struct s5h1420_state* state = fe->demodulator_priv;
431
432         s5h1420_writereg(state, 0x46, 0x1d);
433         mdelay(25);
434
435         *ber = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
436
437         return 0;
438 }
439
440 static int s5h1420_read_signal_strength(struct dvb_frontend* fe, u16* strength)
441 {
442         struct s5h1420_state* state = fe->demodulator_priv;
443
444         u8 val = s5h1420_readreg(state, 0x15);
445
446         *strength =  (u16) ((val << 8) | val);
447
448         return 0;
449 }
450
451 static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
452 {
453         struct s5h1420_state* state = fe->demodulator_priv;
454
455         s5h1420_writereg(state, 0x46, 0x1f);
456         mdelay(25);
457
458         *ucblocks = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
459
460         return 0;
461 }
462
463 static void s5h1420_reset(struct s5h1420_state* state)
464 {
465         dprintk("%s\n", __func__);
466         s5h1420_writereg (state, 0x01, 0x08);
467         s5h1420_writereg (state, 0x01, 0x00);
468         udelay(10);
469 }
470
471 static void s5h1420_setsymbolrate(struct s5h1420_state* state,
472                                   struct dvb_frontend_parameters *p)
473 {
474         u8 v;
475         u64 val;
476
477         dprintk("enter %s\n", __func__);
478
479         val = ((u64) p->u.qpsk.symbol_rate / 1000ULL) * (1ULL<<24);
480         if (p->u.qpsk.symbol_rate < 29000000)
481                 val *= 2;
482         do_div(val, (state->fclk / 1000));
483
484         dprintk("symbol rate register: %06llx\n", (unsigned long long)val);
485
486         v = s5h1420_readreg(state, Loop01);
487         s5h1420_writereg(state, Loop01, v & 0x7f);
488         s5h1420_writereg(state, Tnco01, val >> 16);
489         s5h1420_writereg(state, Tnco02, val >> 8);
490         s5h1420_writereg(state, Tnco03, val & 0xff);
491         s5h1420_writereg(state, Loop01,  v | 0x80);
492         dprintk("leave %s\n", __func__);
493 }
494
495 static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
496 {
497         return state->symbol_rate;
498 }
499
500 static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
501 {
502         int val;
503         u8 v;
504
505         dprintk("enter %s\n", __func__);
506
507         /* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
508          * divide fclk by 1000000 to get the correct value. */
509         val = -(int) ((freqoffset * (1<<24)) / (state->fclk / 1000000));
510
511         dprintk("phase rotator/freqoffset: %d %06x\n", freqoffset, val);
512
513         v = s5h1420_readreg(state, Loop01);
514         s5h1420_writereg(state, Loop01, v & 0xbf);
515         s5h1420_writereg(state, Pnco01, val >> 16);
516         s5h1420_writereg(state, Pnco02, val >> 8);
517         s5h1420_writereg(state, Pnco03, val & 0xff);
518         s5h1420_writereg(state, Loop01, v | 0x40);
519         dprintk("leave %s\n", __func__);
520 }
521
522 static int s5h1420_getfreqoffset(struct s5h1420_state* state)
523 {
524         int val;
525
526         s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) | 0x08);
527         val  = s5h1420_readreg(state, 0x0e) << 16;
528         val |= s5h1420_readreg(state, 0x0f) << 8;
529         val |= s5h1420_readreg(state, 0x10);
530         s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
531
532         if (val & 0x800000)
533                 val |= 0xff000000;
534
535         /* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
536          * divide fclk by 1000000 to get the correct value. */
537         val = (((-val) * (state->fclk/1000000)) / (1<<24));
538
539         return val;
540 }
541
542 static void s5h1420_setfec_inversion(struct s5h1420_state* state,
543                                      struct dvb_frontend_parameters *p)
544 {
545         u8 inversion = 0;
546         u8 vit08, vit09;
547
548         dprintk("enter %s\n", __func__);
549
550         if (p->inversion == INVERSION_OFF)
551                 inversion = state->config->invert ? 0x08 : 0;
552         else if (p->inversion == INVERSION_ON)
553                 inversion = state->config->invert ? 0 : 0x08;
554
555         if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
556                 vit08 = 0x3f;
557                 vit09 = 0;
558         } else {
559                 switch(p->u.qpsk.fec_inner) {
560                 case FEC_1_2:
561                         vit08 = 0x01; vit09 = 0x10;
562                         break;
563
564                 case FEC_2_3:
565                         vit08 = 0x02; vit09 = 0x11;
566                         break;
567
568                 case FEC_3_4:
569                         vit08 = 0x04; vit09 = 0x12;
570                         break;
571
572                 case FEC_5_6:
573                         vit08 = 0x08; vit09 = 0x13;
574                         break;
575
576                 case FEC_6_7:
577                         vit08 = 0x10; vit09 = 0x14;
578                         break;
579
580                 case FEC_7_8:
581                         vit08 = 0x20; vit09 = 0x15;
582                         break;
583
584                 default:
585                         return;
586                 }
587         }
588         vit09 |= inversion;
589         dprintk("fec: %02x %02x\n", vit08, vit09);
590         s5h1420_writereg(state, Vit08, vit08);
591         s5h1420_writereg(state, Vit09, vit09);
592         dprintk("leave %s\n", __func__);
593 }
594
595 static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
596 {
597         switch(s5h1420_readreg(state, 0x32) & 0x07) {
598         case 0:
599                 return FEC_1_2;
600
601         case 1:
602                 return FEC_2_3;
603
604         case 2:
605                 return FEC_3_4;
606
607         case 3:
608                 return FEC_5_6;
609
610         case 4:
611                 return FEC_6_7;
612
613         case 5:
614                 return FEC_7_8;
615         }
616
617         return FEC_NONE;
618 }
619
620 static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
621 {
622         if (s5h1420_readreg(state, 0x32) & 0x08)
623                 return INVERSION_ON;
624
625         return INVERSION_OFF;
626 }
627
628 static int s5h1420_set_frontend(struct dvb_frontend* fe,
629                                 struct dvb_frontend_parameters *p)
630 {
631         struct s5h1420_state* state = fe->demodulator_priv;
632         int frequency_delta;
633         struct dvb_frontend_tune_settings fesettings;
634         uint8_t clock_settting;
635
636         dprintk("enter %s\n", __func__);
637
638         /* check if we should do a fast-tune */
639         memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
640         s5h1420_get_tune_settings(fe, &fesettings);
641         frequency_delta = p->frequency - state->tunedfreq;
642         if ((frequency_delta > -fesettings.max_drift) &&
643                         (frequency_delta < fesettings.max_drift) &&
644                         (frequency_delta != 0) &&
645                         (state->fec_inner == p->u.qpsk.fec_inner) &&
646                         (state->symbol_rate == p->u.qpsk.symbol_rate)) {
647
648                 if (fe->ops.tuner_ops.set_params) {
649                         fe->ops.tuner_ops.set_params(fe, p);
650                         if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
651                 }
652                 if (fe->ops.tuner_ops.get_frequency) {
653                         u32 tmp;
654                         fe->ops.tuner_ops.get_frequency(fe, &tmp);
655                         if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
656                         s5h1420_setfreqoffset(state, p->frequency - tmp);
657                 } else {
658                         s5h1420_setfreqoffset(state, 0);
659                 }
660                 dprintk("simple tune\n");
661                 return 0;
662         }
663         dprintk("tuning demod\n");
664
665         /* first of all, software reset */
666         s5h1420_reset(state);
667
668         /* set s5h1420 fclk PLL according to desired symbol rate */
669         if (p->u.qpsk.symbol_rate > 33000000)
670                 state->fclk = 80000000;
671         else if (p->u.qpsk.symbol_rate > 28500000)
672                 state->fclk = 59000000;
673         else if (p->u.qpsk.symbol_rate > 25000000)
674                 state->fclk = 86000000;
675         else if (p->u.qpsk.symbol_rate > 1900000)
676                 state->fclk = 88000000;
677         else
678                 state->fclk = 44000000;
679
680         /* Clock */
681         switch (state->fclk) {
682         default:
683         case 88000000:
684                 clock_settting = 80;
685                 break;
686         case 86000000:
687                 clock_settting = 78;
688                 break;
689         case 80000000:
690                 clock_settting = 72;
691                 break;
692         case 59000000:
693                 clock_settting = 51;
694                 break;
695         case 44000000:
696                 clock_settting = 36;
697                 break;
698         }
699         dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
700         s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8);
701         s5h1420_writereg(state, PLL02, 0x40);
702         s5h1420_writereg(state, DiS01, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
703
704         /* TODO DC offset removal, config parameter ? */
705         if (p->u.qpsk.symbol_rate > 29000000)
706                 s5h1420_writereg(state, QPSK01, 0xae | 0x10);
707         else
708                 s5h1420_writereg(state, QPSK01, 0xac | 0x10);
709
710         /* set misc registers */
711         s5h1420_writereg(state, CON_1, 0x00);
712         s5h1420_writereg(state, QPSK02, 0x00);
713         s5h1420_writereg(state, Pre01, 0xb0);
714
715         s5h1420_writereg(state, Loop01, 0xF0);
716         s5h1420_writereg(state, Loop02, 0x2a); /* e7 for s5h1420 */
717         s5h1420_writereg(state, Loop03, 0x79); /* 78 for s5h1420 */
718         if (p->u.qpsk.symbol_rate > 20000000)
719                 s5h1420_writereg(state, Loop04, 0x79);
720         else
721                 s5h1420_writereg(state, Loop04, 0x58);
722         s5h1420_writereg(state, Loop05, 0x6b);
723
724         if (p->u.qpsk.symbol_rate >= 8000000)
725                 s5h1420_writereg(state, Post01, (0 << 6) | 0x10);
726         else if (p->u.qpsk.symbol_rate >= 4000000)
727                 s5h1420_writereg(state, Post01, (1 << 6) | 0x10);
728         else
729                 s5h1420_writereg(state, Post01, (3 << 6) | 0x10);
730
731         s5h1420_writereg(state, Monitor12, 0x00); /* unfreeze DC compensation */
732
733         s5h1420_writereg(state, Sync01, 0x33);
734         s5h1420_writereg(state, Mpeg01, state->config->cdclk_polarity);
735         s5h1420_writereg(state, Mpeg02, 0x3d); /* Parallel output more, disabled -> enabled later */
736         s5h1420_writereg(state, Err01, 0x03); /* 0x1d for s5h1420 */
737
738         s5h1420_writereg(state, Vit06, 0x6e); /* 0x8e for s5h1420 */
739         s5h1420_writereg(state, DiS03, 0x00);
740         s5h1420_writereg(state, Rf01, 0x61); /* Tuner i2c address - for the gate controller */
741
742         /* set tuner PLL */
743         if (fe->ops.tuner_ops.set_params) {
744                 fe->ops.tuner_ops.set_params(fe, p);
745                 if (fe->ops.i2c_gate_ctrl)
746                         fe->ops.i2c_gate_ctrl(fe, 0);
747                 s5h1420_setfreqoffset(state, 0);
748         }
749
750         /* set the reset of the parameters */
751         s5h1420_setsymbolrate(state, p);
752         s5h1420_setfec_inversion(state, p);
753
754         /* start QPSK */
755         s5h1420_writereg(state, QPSK01, s5h1420_readreg(state, QPSK01) | 1);
756
757         state->fec_inner = p->u.qpsk.fec_inner;
758         state->symbol_rate = p->u.qpsk.symbol_rate;
759         state->postlocked = 0;
760         state->tunedfreq = p->frequency;
761
762         dprintk("leave %s\n", __func__);
763         return 0;
764 }
765
766 static int s5h1420_get_frontend(struct dvb_frontend* fe,
767                                 struct dvb_frontend_parameters *p)
768 {
769         struct s5h1420_state* state = fe->demodulator_priv;
770
771         p->frequency = state->tunedfreq + s5h1420_getfreqoffset(state);
772         p->inversion = s5h1420_getinversion(state);
773         p->u.qpsk.symbol_rate = s5h1420_getsymbolrate(state);
774         p->u.qpsk.fec_inner = s5h1420_getfec(state);
775
776         return 0;
777 }
778
779 static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
780                                      struct dvb_frontend_tune_settings* fesettings)
781 {
782         if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {
783                 fesettings->min_delay_ms = 50;
784                 fesettings->step_size = 2000;
785                 fesettings->max_drift = 8000;
786         } else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) {
787                 fesettings->min_delay_ms = 100;
788                 fesettings->step_size = 1500;
789                 fesettings->max_drift = 9000;
790         } else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) {
791                 fesettings->min_delay_ms = 100;
792                 fesettings->step_size = 1000;
793                 fesettings->max_drift = 8000;
794         } else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) {
795                 fesettings->min_delay_ms = 100;
796                 fesettings->step_size = 500;
797                 fesettings->max_drift = 7000;
798         } else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) {
799                 fesettings->min_delay_ms = 200;
800                 fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
801                 fesettings->max_drift = 14 * fesettings->step_size;
802         } else {
803                 fesettings->min_delay_ms = 200;
804                 fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
805                 fesettings->max_drift = 18 * fesettings->step_size;
806         }
807
808         return 0;
809 }
810
811 static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
812 {
813         struct s5h1420_state* state = fe->demodulator_priv;
814
815         if (enable)
816                 return s5h1420_writereg(state, 0x02, state->CON_1_val | 1);
817         else
818                 return s5h1420_writereg(state, 0x02, state->CON_1_val & 0xfe);
819 }
820
821 static int s5h1420_init (struct dvb_frontend* fe)
822 {
823         struct s5h1420_state* state = fe->demodulator_priv;
824
825         /* disable power down and do reset */
826         state->CON_1_val = 0x10;
827         s5h1420_writereg(state, 0x02, state->CON_1_val);
828         msleep(10);
829         s5h1420_reset(state);
830
831         return 0;
832 }
833
834 static int s5h1420_sleep(struct dvb_frontend* fe)
835 {
836         struct s5h1420_state* state = fe->demodulator_priv;
837         state->CON_1_val = 0x12;
838         return s5h1420_writereg(state, 0x02, state->CON_1_val);
839 }
840
841 static void s5h1420_release(struct dvb_frontend* fe)
842 {
843         struct s5h1420_state* state = fe->demodulator_priv;
844         i2c_del_adapter(&state->tuner_i2c_adapter);
845         kfree(state);
846 }
847
848 static u32 s5h1420_tuner_i2c_func(struct i2c_adapter *adapter)
849 {
850         return I2C_FUNC_I2C;
851 }
852
853 static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
854 {
855         struct s5h1420_state *state = i2c_get_adapdata(i2c_adap);
856         struct i2c_msg m[1 + num];
857         u8 tx_open[2] = { CON_1, state->CON_1_val | 1 }; /* repeater stops once there was a stop condition */
858
859         memset(m, 0, sizeof(struct i2c_msg) * (1 + num));
860
861         m[0].addr = state->config->demod_address;
862         m[0].buf  = tx_open;
863         m[0].len  = 2;
864
865         memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
866
867         return i2c_transfer(state->i2c, m, 1+num) == 1 + num ? num : -EIO;
868 }
869
870 static struct i2c_algorithm s5h1420_tuner_i2c_algo = {
871         .master_xfer   = s5h1420_tuner_i2c_tuner_xfer,
872         .functionality = s5h1420_tuner_i2c_func,
873 };
874
875 struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
876 {
877         struct s5h1420_state *state = fe->demodulator_priv;
878         return &state->tuner_i2c_adapter;
879 }
880 EXPORT_SYMBOL(s5h1420_get_tuner_i2c_adapter);
881
882 static struct dvb_frontend_ops s5h1420_ops;
883
884 struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
885                                     struct i2c_adapter *i2c)
886 {
887         /* allocate memory for the internal state */
888         struct s5h1420_state *state = kzalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
889         u8 i;
890
891         if (state == NULL)
892                 goto error;
893
894         /* setup the state */
895         state->config = config;
896         state->i2c = i2c;
897         state->postlocked = 0;
898         state->fclk = 88000000;
899         state->tunedfreq = 0;
900         state->fec_inner = FEC_NONE;
901         state->symbol_rate = 0;
902
903         /* check if the demod is there + identify it */
904         i = s5h1420_readreg(state, ID01);
905         if (i != 0x03)
906                 goto error;
907
908         memset(state->shadow, 0xff, sizeof(state->shadow));
909
910         for (i = 0; i < 0x50; i++)
911                 state->shadow[i] = s5h1420_readreg(state, i);
912
913         /* create dvb_frontend */
914         memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
915         state->frontend.demodulator_priv = state;
916
917         /* create tuner i2c adapter */
918         strncpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus", I2C_NAME_SIZE);
919         state->tuner_i2c_adapter.class     = I2C_CLASS_TV_DIGITAL,
920         state->tuner_i2c_adapter.algo      = &s5h1420_tuner_i2c_algo;
921         state->tuner_i2c_adapter.algo_data = NULL;
922         i2c_set_adapdata(&state->tuner_i2c_adapter, state);
923         if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
924                 printk(KERN_ERR "S5H1420/PN1010: tuner i2c bus could not be initialized\n");
925                 goto error;
926         }
927
928         return &state->frontend;
929
930 error:
931         kfree(state);
932         return NULL;
933 }
934 EXPORT_SYMBOL(s5h1420_attach);
935
936 static struct dvb_frontend_ops s5h1420_ops = {
937
938         .info = {
939                 .name     = "Samsung S5H1420/PnpNetwork PN1010 DVB-S",
940                 .type     = FE_QPSK,
941                 .frequency_min    = 950000,
942                 .frequency_max    = 2150000,
943                 .frequency_stepsize = 125,     /* kHz for QPSK frontends */
944                 .frequency_tolerance  = 29500,
945                 .symbol_rate_min  = 1000000,
946                 .symbol_rate_max  = 45000000,
947                 /*  .symbol_rate_tolerance  = ???,*/
948                 .caps = FE_CAN_INVERSION_AUTO |
949                 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
950                 FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
951                 FE_CAN_QPSK
952         },
953
954         .release = s5h1420_release,
955
956         .init = s5h1420_init,
957         .sleep = s5h1420_sleep,
958         .i2c_gate_ctrl = s5h1420_i2c_gate_ctrl,
959
960         .set_frontend = s5h1420_set_frontend,
961         .get_frontend = s5h1420_get_frontend,
962         .get_tune_settings = s5h1420_get_tune_settings,
963
964         .read_status = s5h1420_read_status,
965         .read_ber = s5h1420_read_ber,
966         .read_signal_strength = s5h1420_read_signal_strength,
967         .read_ucblocks = s5h1420_read_ucblocks,
968
969         .diseqc_send_master_cmd = s5h1420_send_master_cmd,
970         .diseqc_recv_slave_reply = s5h1420_recv_slave_reply,
971         .diseqc_send_burst = s5h1420_send_burst,
972         .set_tone = s5h1420_set_tone,
973         .set_voltage = s5h1420_set_voltage,
974 };
975
976 MODULE_DESCRIPTION("Samsung S5H1420/PnpNetwork PN1010 DVB-S Demodulator driver");
977 MODULE_AUTHOR("Andrew de Quincey, Patrick Boettcher");
978 MODULE_LICENSE("GPL");