Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[sfrench/cifs-2.6.git] / drivers / media / dvb / frontends / mb86a20s.c
1 /*
2  *   Fujitu mb86a20s ISDB-T/ISDB-Tsb Module driver
3  *
4  *   Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com>
5  *   Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com>
6  *
7  *   FIXME: Need to port to DVB v5.2 API
8  *
9  *   This program is free software; you can redistribute it and/or
10  *   modify it under the terms of the GNU General Public License as
11  *   published by the Free Software Foundation version 2.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *   General Public License for more details.
17  */
18
19 #include <linux/kernel.h>
20 #include <asm/div64.h>
21
22 #include "dvb_frontend.h"
23 #include "mb86a20s.h"
24
25 static int debug = 1;
26 module_param(debug, int, 0644);
27 MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
28
29 #define rc(args...)  do {                                               \
30         printk(KERN_ERR  "mb86a20s: " args);                            \
31 } while (0)
32
33 #define dprintk(args...)                                                \
34         do {                                                            \
35                 if (debug) {                                            \
36                         printk(KERN_DEBUG "mb86a20s: %s: ", __func__);  \
37                         printk(args);                                   \
38                 }                                                       \
39         } while (0)
40
41 struct mb86a20s_state {
42         struct i2c_adapter *i2c;
43         const struct mb86a20s_config *config;
44
45         struct dvb_frontend frontend;
46
47         bool need_init;
48 };
49
50 struct regdata {
51         u8 reg;
52         u8 data;
53 };
54
55 /*
56  * Initialization sequence: Use whatevere default values that PV SBTVD
57  * does on its initialisation, obtained via USB snoop
58  */
59 static struct regdata mb86a20s_init[] = {
60         { 0x70, 0x0f },
61         { 0x70, 0xff },
62         { 0x08, 0x01 },
63         { 0x09, 0x3e },
64         { 0x50, 0xd1 }, { 0x51, 0x22 },
65         { 0x39, 0x01 },
66         { 0x71, 0x00 },
67         { 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 },
68         { 0x28, 0x20 }, { 0x29, 0x33 }, { 0x2a, 0xdf }, { 0x2b, 0xa9 },
69         { 0x28, 0x22 }, { 0x29, 0x00 }, { 0x2a, 0x1f }, { 0x2b, 0xf0 },
70         { 0x3b, 0x21 },
71         { 0x3c, 0x3a },
72         { 0x01, 0x0d },
73         { 0x04, 0x08 }, { 0x05, 0x05 },
74         { 0x04, 0x0e }, { 0x05, 0x00 },
75         { 0x04, 0x0f }, { 0x05, 0x14 },
76         { 0x04, 0x0b }, { 0x05, 0x8c },
77         { 0x04, 0x00 }, { 0x05, 0x00 },
78         { 0x04, 0x01 }, { 0x05, 0x07 },
79         { 0x04, 0x02 }, { 0x05, 0x0f },
80         { 0x04, 0x03 }, { 0x05, 0xa0 },
81         { 0x04, 0x09 }, { 0x05, 0x00 },
82         { 0x04, 0x0a }, { 0x05, 0xff },
83         { 0x04, 0x27 }, { 0x05, 0x64 },
84         { 0x04, 0x28 }, { 0x05, 0x00 },
85         { 0x04, 0x1e }, { 0x05, 0xff },
86         { 0x04, 0x29 }, { 0x05, 0x0a },
87         { 0x04, 0x32 }, { 0x05, 0x0a },
88         { 0x04, 0x14 }, { 0x05, 0x02 },
89         { 0x04, 0x04 }, { 0x05, 0x00 },
90         { 0x04, 0x05 }, { 0x05, 0x22 },
91         { 0x04, 0x06 }, { 0x05, 0x0e },
92         { 0x04, 0x07 }, { 0x05, 0xd8 },
93         { 0x04, 0x12 }, { 0x05, 0x00 },
94         { 0x04, 0x13 }, { 0x05, 0xff },
95         { 0x04, 0x15 }, { 0x05, 0x4e },
96         { 0x04, 0x16 }, { 0x05, 0x20 },
97         { 0x52, 0x01 },
98         { 0x50, 0xa7 }, { 0x51, 0xff },
99         { 0x50, 0xa8 }, { 0x51, 0xff },
100         { 0x50, 0xa9 }, { 0x51, 0xff },
101         { 0x50, 0xaa }, { 0x51, 0xff },
102         { 0x50, 0xab }, { 0x51, 0xff },
103         { 0x50, 0xac }, { 0x51, 0xff },
104         { 0x50, 0xad }, { 0x51, 0xff },
105         { 0x50, 0xae }, { 0x51, 0xff },
106         { 0x50, 0xaf }, { 0x51, 0xff },
107         { 0x5e, 0x07 },
108         { 0x50, 0xdc }, { 0x51, 0x01 },
109         { 0x50, 0xdd }, { 0x51, 0xf4 },
110         { 0x50, 0xde }, { 0x51, 0x01 },
111         { 0x50, 0xdf }, { 0x51, 0xf4 },
112         { 0x50, 0xe0 }, { 0x51, 0x01 },
113         { 0x50, 0xe1 }, { 0x51, 0xf4 },
114         { 0x50, 0xb0 }, { 0x51, 0x07 },
115         { 0x50, 0xb2 }, { 0x51, 0xff },
116         { 0x50, 0xb3 }, { 0x51, 0xff },
117         { 0x50, 0xb4 }, { 0x51, 0xff },
118         { 0x50, 0xb5 }, { 0x51, 0xff },
119         { 0x50, 0xb6 }, { 0x51, 0xff },
120         { 0x50, 0xb7 }, { 0x51, 0xff },
121         { 0x50, 0x50 }, { 0x51, 0x02 },
122         { 0x50, 0x51 }, { 0x51, 0x04 },
123         { 0x45, 0x04 },
124         { 0x48, 0x04 },
125         { 0x50, 0xd5 }, { 0x51, 0x01 },         /* Serial */
126         { 0x50, 0xd6 }, { 0x51, 0x1f },
127         { 0x50, 0xd2 }, { 0x51, 0x03 },
128         { 0x50, 0xd7 }, { 0x51, 0x3f },
129         { 0x28, 0x74 }, { 0x29, 0x00 }, { 0x28, 0x74 }, { 0x29, 0x40 },
130         { 0x28, 0x46 }, { 0x29, 0x2c }, { 0x28, 0x46 }, { 0x29, 0x0c },
131         { 0x04, 0x40 }, { 0x05, 0x01 },
132         { 0x28, 0x00 }, { 0x29, 0x10 },
133         { 0x28, 0x05 }, { 0x29, 0x02 },
134         { 0x1c, 0x01 },
135         { 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x03 },
136         { 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0d },
137         { 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 },
138         { 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x01 },
139         { 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x21 },
140         { 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x29 },
141         { 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 },
142         { 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x31 },
143         { 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0e },
144         { 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x4e },
145         { 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x46 },
146         { 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f },
147         { 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x56 },
148         { 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x35 },
149         { 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbe },
150         { 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0x84 },
151         { 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x03 }, { 0x2b, 0xee },
152         { 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x98 },
153         { 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x9f },
154         { 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xb2 },
155         { 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0xc2 },
156         { 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0x4a },
157         { 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbc },
158         { 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x04 }, { 0x2b, 0xba },
159         { 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0x14 },
160         { 0x50, 0x1e }, { 0x51, 0x5d },
161         { 0x50, 0x22 }, { 0x51, 0x00 },
162         { 0x50, 0x23 }, { 0x51, 0xc8 },
163         { 0x50, 0x24 }, { 0x51, 0x00 },
164         { 0x50, 0x25 }, { 0x51, 0xf0 },
165         { 0x50, 0x26 }, { 0x51, 0x00 },
166         { 0x50, 0x27 }, { 0x51, 0xc3 },
167         { 0x50, 0x39 }, { 0x51, 0x02 },
168         { 0x28, 0x6a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 },
169         { 0xd0, 0x00 },
170 };
171
172 static struct regdata mb86a20s_reset_reception[] = {
173         { 0x70, 0xf0 },
174         { 0x70, 0xff },
175         { 0x08, 0x01 },
176         { 0x08, 0x00 },
177 };
178
179 static int mb86a20s_i2c_writereg(struct mb86a20s_state *state,
180                              u8 i2c_addr, int reg, int data)
181 {
182         u8 buf[] = { reg, data };
183         struct i2c_msg msg = {
184                 .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
185         };
186         int rc;
187
188         rc = i2c_transfer(state->i2c, &msg, 1);
189         if (rc != 1) {
190                 printk("%s: writereg error (rc == %i, reg == 0x%02x,"
191                          " data == 0x%02x)\n", __func__, rc, reg, data);
192                 return rc;
193         }
194
195         return 0;
196 }
197
198 static int mb86a20s_i2c_writeregdata(struct mb86a20s_state *state,
199                                      u8 i2c_addr, struct regdata *rd, int size)
200 {
201         int i, rc;
202
203         for (i = 0; i < size; i++) {
204                 rc = mb86a20s_i2c_writereg(state, i2c_addr, rd[i].reg,
205                                            rd[i].data);
206                 if (rc < 0)
207                         return rc;
208         }
209         return 0;
210 }
211
212 static int mb86a20s_i2c_readreg(struct mb86a20s_state *state,
213                                 u8 i2c_addr, u8 reg)
214 {
215         u8 val;
216         int rc;
217         struct i2c_msg msg[] = {
218                 { .addr = i2c_addr, .flags = 0, .buf = &reg, .len = 1 },
219                 { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
220         };
221
222         rc = i2c_transfer(state->i2c, msg, 2);
223
224         if (rc != 2) {
225                 rc("%s: reg=0x%x (error=%d)\n", __func__, reg, rc);
226                 return rc;
227         }
228
229         return val;
230 }
231
232 #define mb86a20s_readreg(state, reg) \
233         mb86a20s_i2c_readreg(state, state->config->demod_address, reg)
234 #define mb86a20s_writereg(state, reg, val) \
235         mb86a20s_i2c_writereg(state, state->config->demod_address, reg, val)
236 #define mb86a20s_writeregdata(state, regdata) \
237         mb86a20s_i2c_writeregdata(state, state->config->demod_address, \
238         regdata, ARRAY_SIZE(regdata))
239
240 static int mb86a20s_initfe(struct dvb_frontend *fe)
241 {
242         struct mb86a20s_state *state = fe->demodulator_priv;
243         int rc;
244         u8  regD5 = 1;
245
246         dprintk("\n");
247
248         if (fe->ops.i2c_gate_ctrl)
249                 fe->ops.i2c_gate_ctrl(fe, 0);
250
251         /* Initialize the frontend */
252         rc = mb86a20s_writeregdata(state, mb86a20s_init);
253         if (rc < 0)
254                 goto err;
255
256         if (!state->config->is_serial) {
257                 regD5 &= ~1;
258
259                 rc = mb86a20s_writereg(state, 0x50, 0xd5);
260                 if (rc < 0)
261                         goto err;
262                 rc = mb86a20s_writereg(state, 0x51, regD5);
263                 if (rc < 0)
264                         goto err;
265         }
266
267         if (fe->ops.i2c_gate_ctrl)
268                 fe->ops.i2c_gate_ctrl(fe, 1);
269
270 err:
271         if (rc < 0) {
272                 state->need_init = true;
273                 printk(KERN_INFO "mb86a20s: Init failed. Will try again later\n");
274         } else {
275                 state->need_init = false;
276                 dprintk("Initialization succeeded.\n");
277         }
278         return rc;
279 }
280
281 static int mb86a20s_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
282 {
283         struct mb86a20s_state *state = fe->demodulator_priv;
284         unsigned rf_max, rf_min, rf;
285         u8       val;
286
287         dprintk("\n");
288
289         if (fe->ops.i2c_gate_ctrl)
290                 fe->ops.i2c_gate_ctrl(fe, 0);
291
292         /* Does a binary search to get RF strength */
293         rf_max = 0xfff;
294         rf_min = 0;
295         do {
296                 rf = (rf_max + rf_min) / 2;
297                 mb86a20s_writereg(state, 0x04, 0x1f);
298                 mb86a20s_writereg(state, 0x05, rf >> 8);
299                 mb86a20s_writereg(state, 0x04, 0x20);
300                 mb86a20s_writereg(state, 0x04, rf);
301
302                 val = mb86a20s_readreg(state, 0x02);
303                 if (val & 0x08)
304                         rf_min = (rf_max + rf_min) / 2;
305                 else
306                         rf_max = (rf_max + rf_min) / 2;
307                 if (rf_max - rf_min < 4) {
308                         *strength = (((rf_max + rf_min) / 2) * 65535) / 4095;
309                         break;
310                 }
311         } while (1);
312
313         dprintk("signal strength = %d\n", *strength);
314
315         if (fe->ops.i2c_gate_ctrl)
316                 fe->ops.i2c_gate_ctrl(fe, 1);
317
318         return 0;
319 }
320
321 static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status)
322 {
323         struct mb86a20s_state *state = fe->demodulator_priv;
324         u8 val;
325
326         dprintk("\n");
327         *status = 0;
328
329         if (fe->ops.i2c_gate_ctrl)
330                 fe->ops.i2c_gate_ctrl(fe, 0);
331         val = mb86a20s_readreg(state, 0x0a) & 0xf;
332         if (fe->ops.i2c_gate_ctrl)
333                 fe->ops.i2c_gate_ctrl(fe, 1);
334
335         if (val >= 2)
336                 *status |= FE_HAS_SIGNAL;
337
338         if (val >= 4)
339                 *status |= FE_HAS_CARRIER;
340
341         if (val >= 5)
342                 *status |= FE_HAS_VITERBI;
343
344         if (val >= 7)
345                 *status |= FE_HAS_SYNC;
346
347         if (val >= 8)                           /* Maybe 9? */
348                 *status |= FE_HAS_LOCK;
349
350         dprintk("val = %d, status = 0x%02x\n", val, *status);
351
352         return 0;
353 }
354
355 static int mb86a20s_set_frontend(struct dvb_frontend *fe)
356 {
357         struct mb86a20s_state *state = fe->demodulator_priv;
358         int rc;
359 #if 0
360         /*
361          * FIXME: Properly implement the set frontend properties
362          */
363         struct dtv_frontend_properties *p = &fe->dtv_property_cache;
364 #endif
365
366         dprintk("\n");
367
368         if (fe->ops.i2c_gate_ctrl)
369                 fe->ops.i2c_gate_ctrl(fe, 1);
370         dprintk("Calling tuner set parameters\n");
371         fe->ops.tuner_ops.set_params(fe);
372
373         /*
374          * Make it more reliable: if, for some reason, the initial
375          * device initialization doesn't happen, initialize it when
376          * a SBTVD parameters are adjusted.
377          *
378          * Unfortunately, due to a hard to track bug at tda829x/tda18271,
379          * the agc callback logic is not called during DVB attach time,
380          * causing mb86a20s to not be initialized with Kworld SBTVD.
381          * So, this hack is needed, in order to make Kworld SBTVD to work.
382          */
383         if (state->need_init)
384                 mb86a20s_initfe(fe);
385
386         if (fe->ops.i2c_gate_ctrl)
387                 fe->ops.i2c_gate_ctrl(fe, 0);
388         rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception);
389         if (fe->ops.i2c_gate_ctrl)
390                 fe->ops.i2c_gate_ctrl(fe, 1);
391
392         return rc;
393 }
394
395 static int mb86a20s_get_modulation(struct mb86a20s_state *state,
396                                    unsigned layer)
397 {
398         int rc;
399         static unsigned char reg[] = {
400                 [0] = 0x86,     /* Layer A */
401                 [1] = 0x8a,     /* Layer B */
402                 [2] = 0x8e,     /* Layer C */
403         };
404
405         if (layer >= ARRAY_SIZE(reg))
406                 return -EINVAL;
407         rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
408         if (rc < 0)
409                 return rc;
410         rc = mb86a20s_readreg(state, 0x6e);
411         if (rc < 0)
412                 return rc;
413         switch ((rc & 0x70) >> 4) {
414         case 0:
415                 return DQPSK;
416         case 1:
417                 return QPSK;
418         case 2:
419                 return QAM_16;
420         case 3:
421                 return QAM_64;
422         default:
423                 return QAM_AUTO;
424         }
425 }
426
427 static int mb86a20s_get_fec(struct mb86a20s_state *state,
428                             unsigned layer)
429 {
430         int rc;
431
432         static unsigned char reg[] = {
433                 [0] = 0x87,     /* Layer A */
434                 [1] = 0x8b,     /* Layer B */
435                 [2] = 0x8f,     /* Layer C */
436         };
437
438         if (layer >= ARRAY_SIZE(reg))
439                 return -EINVAL;
440         rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
441         if (rc < 0)
442                 return rc;
443         rc = mb86a20s_readreg(state, 0x6e);
444         if (rc < 0)
445                 return rc;
446         switch (rc) {
447         case 0:
448                 return FEC_1_2;
449         case 1:
450                 return FEC_2_3;
451         case 2:
452                 return FEC_3_4;
453         case 3:
454                 return FEC_5_6;
455         case 4:
456                 return FEC_7_8;
457         default:
458                 return FEC_AUTO;
459         }
460 }
461
462 static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
463                                      unsigned layer)
464 {
465         int rc;
466
467         static unsigned char reg[] = {
468                 [0] = 0x88,     /* Layer A */
469                 [1] = 0x8c,     /* Layer B */
470                 [2] = 0x90,     /* Layer C */
471         };
472
473         if (layer >= ARRAY_SIZE(reg))
474                 return -EINVAL;
475         rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
476         if (rc < 0)
477                 return rc;
478         rc = mb86a20s_readreg(state, 0x6e);
479         if (rc < 0)
480                 return rc;
481         if (rc > 3)
482                 return -EINVAL; /* Not used */
483         return rc;
484 }
485
486 static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
487                                       unsigned layer)
488 {
489         int rc, count;
490
491         static unsigned char reg[] = {
492                 [0] = 0x89,     /* Layer A */
493                 [1] = 0x8d,     /* Layer B */
494                 [2] = 0x91,     /* Layer C */
495         };
496
497         if (layer >= ARRAY_SIZE(reg))
498                 return -EINVAL;
499         rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
500         if (rc < 0)
501                 return rc;
502         rc = mb86a20s_readreg(state, 0x6e);
503         if (rc < 0)
504                 return rc;
505         count = (rc >> 4) & 0x0f;
506
507         return count;
508 }
509
510 static int mb86a20s_get_frontend(struct dvb_frontend *fe)
511 {
512         struct mb86a20s_state *state = fe->demodulator_priv;
513         struct dtv_frontend_properties *p = &fe->dtv_property_cache;
514         int i, rc;
515
516         /* Fixed parameters */
517         p->delivery_system = SYS_ISDBT;
518         p->bandwidth_hz = 6000000;
519
520         if (fe->ops.i2c_gate_ctrl)
521                 fe->ops.i2c_gate_ctrl(fe, 0);
522
523         /* Check for partial reception */
524         rc = mb86a20s_writereg(state, 0x6d, 0x85);
525         if (rc >= 0)
526                 rc = mb86a20s_readreg(state, 0x6e);
527         if (rc >= 0)
528                 p->isdbt_partial_reception = (rc & 0x10) ? 1 : 0;
529
530         /* Get per-layer data */
531         p->isdbt_layer_enabled = 0;
532         for (i = 0; i < 3; i++) {
533                 rc = mb86a20s_get_segment_count(state, i);
534                         if (rc >= 0 && rc < 14)
535                                 p->layer[i].segment_count = rc;
536                 if (rc == 0x0f)
537                         continue;
538                 p->isdbt_layer_enabled |= 1 << i;
539                 rc = mb86a20s_get_modulation(state, i);
540                         if (rc >= 0)
541                                 p->layer[i].modulation = rc;
542                 rc = mb86a20s_get_fec(state, i);
543                         if (rc >= 0)
544                                 p->layer[i].fec = rc;
545                 rc = mb86a20s_get_interleaving(state, i);
546                         if (rc >= 0)
547                                 p->layer[i].interleaving = rc;
548         }
549
550         p->isdbt_sb_mode = 0;
551         rc = mb86a20s_writereg(state, 0x6d, 0x84);
552         if ((rc >= 0) && ((rc & 0x60) == 0x20)) {
553                 p->isdbt_sb_mode = 1;
554                 /* At least, one segment should exist */
555                 if (!p->isdbt_sb_segment_count)
556                         p->isdbt_sb_segment_count = 1;
557         } else
558                 p->isdbt_sb_segment_count = 0;
559
560         /* Get transmission mode and guard interval */
561         p->transmission_mode = TRANSMISSION_MODE_AUTO;
562         p->guard_interval = GUARD_INTERVAL_AUTO;
563         rc = mb86a20s_readreg(state, 0x07);
564         if (rc >= 0) {
565                 if ((rc & 0x60) == 0x20) {
566                         switch (rc & 0x0c >> 2) {
567                         case 0:
568                                 p->transmission_mode = TRANSMISSION_MODE_2K;
569                                 break;
570                         case 1:
571                                 p->transmission_mode = TRANSMISSION_MODE_4K;
572                                 break;
573                         case 2:
574                                 p->transmission_mode = TRANSMISSION_MODE_8K;
575                                 break;
576                         }
577                 }
578                 if (!(rc & 0x10)) {
579                         switch (rc & 0x3) {
580                         case 0:
581                                 p->guard_interval = GUARD_INTERVAL_1_4;
582                                 break;
583                         case 1:
584                                 p->guard_interval = GUARD_INTERVAL_1_8;
585                                 break;
586                         case 2:
587                                 p->guard_interval = GUARD_INTERVAL_1_16;
588                                 break;
589                         }
590                 }
591         }
592
593         if (fe->ops.i2c_gate_ctrl)
594                 fe->ops.i2c_gate_ctrl(fe, 1);
595
596         return 0;
597 }
598
599 static int mb86a20s_tune(struct dvb_frontend *fe,
600                         bool re_tune,
601                         unsigned int mode_flags,
602                         unsigned int *delay,
603                         fe_status_t *status)
604 {
605         int rc = 0;
606
607         dprintk("\n");
608
609         if (re_tune)
610                 rc = mb86a20s_set_frontend(fe);
611
612         if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
613                 mb86a20s_read_status(fe, status);
614
615         return rc;
616 }
617
618 static void mb86a20s_release(struct dvb_frontend *fe)
619 {
620         struct mb86a20s_state *state = fe->demodulator_priv;
621
622         dprintk("\n");
623
624         kfree(state);
625 }
626
627 static struct dvb_frontend_ops mb86a20s_ops;
628
629 struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
630                                     struct i2c_adapter *i2c)
631 {
632         u8      rev;
633
634         /* allocate memory for the internal state */
635         struct mb86a20s_state *state =
636                 kzalloc(sizeof(struct mb86a20s_state), GFP_KERNEL);
637
638         dprintk("\n");
639         if (state == NULL) {
640                 rc("Unable to kzalloc\n");
641                 goto error;
642         }
643
644         /* setup the state */
645         state->config = config;
646         state->i2c = i2c;
647
648         /* create dvb_frontend */
649         memcpy(&state->frontend.ops, &mb86a20s_ops,
650                 sizeof(struct dvb_frontend_ops));
651         state->frontend.demodulator_priv = state;
652
653         /* Check if it is a mb86a20s frontend */
654         rev = mb86a20s_readreg(state, 0);
655
656         if (rev == 0x13) {
657                 printk(KERN_INFO "Detected a Fujitsu mb86a20s frontend\n");
658         } else {
659                 printk(KERN_ERR "Frontend revision %d is unknown - aborting.\n",
660                        rev);
661                 goto error;
662         }
663
664         return &state->frontend;
665
666 error:
667         kfree(state);
668         return NULL;
669 }
670 EXPORT_SYMBOL(mb86a20s_attach);
671
672 static struct dvb_frontend_ops mb86a20s_ops = {
673         .delsys = { SYS_ISDBT },
674         /* Use dib8000 values per default */
675         .info = {
676                 .name = "Fujitsu mb86A20s",
677                 .caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER |
678                         FE_CAN_FEC_1_2  | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
679                         FE_CAN_FEC_5_6  | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
680                         FE_CAN_QPSK     | FE_CAN_QAM_16  | FE_CAN_QAM_64 |
681                         FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_QAM_AUTO |
682                         FE_CAN_GUARD_INTERVAL_AUTO    | FE_CAN_HIERARCHY_AUTO,
683                 /* Actually, those values depend on the used tuner */
684                 .frequency_min = 45000000,
685                 .frequency_max = 864000000,
686                 .frequency_stepsize = 62500,
687         },
688
689         .release = mb86a20s_release,
690
691         .init = mb86a20s_initfe,
692         .set_frontend = mb86a20s_set_frontend,
693         .get_frontend = mb86a20s_get_frontend,
694         .read_status = mb86a20s_read_status,
695         .read_signal_strength = mb86a20s_read_signal_strength,
696         .tune = mb86a20s_tune,
697 };
698
699 MODULE_DESCRIPTION("DVB Frontend module for Fujitsu mb86A20s hardware");
700 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
701 MODULE_LICENSE("GPL");