~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/media/dvb/frontends/drx397xD.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Driver for Micronas drx397xD demodulator
3
 
 *
4
 
 * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com>
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
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; If not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#define DEBUG                   /* uncomment if you want debugging output */
21
 
#include <linux/kernel.h>
22
 
#include <linux/module.h>
23
 
#include <linux/moduleparam.h>
24
 
#include <linux/init.h>
25
 
#include <linux/device.h>
26
 
#include <linux/delay.h>
27
 
#include <linux/string.h>
28
 
#include <linux/firmware.h>
29
 
#include <linux/slab.h>
30
 
#include <asm/div64.h>
31
 
 
32
 
#include "dvb_frontend.h"
33
 
#include "drx397xD.h"
34
 
 
35
 
static const char mod_name[] = "drx397xD";
36
 
 
37
 
#define MAX_CLOCK_DRIFT         200     /* maximal 200 PPM allowed */
38
 
 
39
 
#define F_SET_0D0h      1
40
 
#define F_SET_0D4h      2
41
 
 
42
 
enum fw_ix {
43
 
#define _FW_ENTRY(a, b, c)      b
44
 
#include "drx397xD_fw.h"
45
 
};
46
 
 
47
 
/* chip specifics */
48
 
struct drx397xD_state {
49
 
        struct i2c_adapter *i2c;
50
 
        struct dvb_frontend frontend;
51
 
        struct drx397xD_config config;
52
 
        enum fw_ix chip_rev;
53
 
        int flags;
54
 
        u32 bandwidth_parm;     /* internal bandwidth conversions */
55
 
        u32 f_osc;              /* w90: actual osc frequency [Hz] */
56
 
};
57
 
 
58
 
/* Firmware */
59
 
static const char *blob_name[] = {
60
 
#define _BLOB_ENTRY(a, b)               a
61
 
#include "drx397xD_fw.h"
62
 
};
63
 
 
64
 
enum blob_ix {
65
 
#define _BLOB_ENTRY(a, b)               b
66
 
#include "drx397xD_fw.h"
67
 
};
68
 
 
69
 
static struct {
70
 
        const char *name;
71
 
        const struct firmware *file;
72
 
        rwlock_t lock;
73
 
        int refcnt;
74
 
        const u8 *data[ARRAY_SIZE(blob_name)];
75
 
} fw[] = {
76
 
#define _FW_ENTRY(a, b, c)      {                                       \
77
 
                        .name   = a,                                    \
78
 
                        .file   = NULL,                                 \
79
 
                        .lock   = __RW_LOCK_UNLOCKED(fw[c].lock),       \
80
 
                        .refcnt = 0,                                    \
81
 
                        .data   = { }           }
82
 
#include "drx397xD_fw.h"
83
 
};
84
 
 
85
 
/* use only with writer lock acquired */
86
 
static void _drx_release_fw(struct drx397xD_state *s, enum fw_ix ix)
87
 
{
88
 
        memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
89
 
        if (fw[ix].file)
90
 
                release_firmware(fw[ix].file);
91
 
}
92
 
 
93
 
static void drx_release_fw(struct drx397xD_state *s)
94
 
{
95
 
        enum fw_ix ix = s->chip_rev;
96
 
 
97
 
        pr_debug("%s\n", __func__);
98
 
 
99
 
        write_lock(&fw[ix].lock);
100
 
        if (fw[ix].refcnt) {
101
 
                fw[ix].refcnt--;
102
 
                if (fw[ix].refcnt == 0)
103
 
                        _drx_release_fw(s, ix);
104
 
        }
105
 
        write_unlock(&fw[ix].lock);
106
 
}
107
 
 
108
 
static int drx_load_fw(struct drx397xD_state *s, enum fw_ix ix)
109
 
{
110
 
        const u8 *data;
111
 
        size_t size, len;
112
 
        int i = 0, j, rc = -EINVAL;
113
 
 
114
 
        pr_debug("%s\n", __func__);
115
 
 
116
 
        if (ix < 0 || ix >= ARRAY_SIZE(fw))
117
 
                return -EINVAL;
118
 
        s->chip_rev = ix;
119
 
 
120
 
        write_lock(&fw[ix].lock);
121
 
        if (fw[ix].file) {
122
 
                rc = 0;
123
 
                goto exit_ok;
124
 
        }
125
 
        memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
126
 
 
127
 
        rc = request_firmware(&fw[ix].file, fw[ix].name, s->i2c->dev.parent);
128
 
        if (rc != 0) {
129
 
                printk(KERN_ERR "%s: Firmware \"%s\" not available\n",
130
 
                       mod_name, fw[ix].name);
131
 
                goto exit_err;
132
 
        }
133
 
 
134
 
        if (!fw[ix].file->data || fw[ix].file->size < 10)
135
 
                goto exit_corrupt;
136
 
 
137
 
        data = fw[ix].file->data;
138
 
        size = fw[ix].file->size;
139
 
 
140
 
        if (data[i++] != 2)     /* check firmware version */
141
 
                goto exit_corrupt;
142
 
 
143
 
        do {
144
 
                switch (data[i++]) {
145
 
                case 0x00:      /* bytecode */
146
 
                        if (i >= size)
147
 
                                break;
148
 
                        i += data[i];
149
 
                case 0x01:      /* reset */
150
 
                case 0x02:      /* sleep */
151
 
                        i++;
152
 
                        break;
153
 
                case 0xfe:      /* name */
154
 
                        len = strnlen(&data[i], size - i);
155
 
                        if (i + len + 1 >= size)
156
 
                                goto exit_corrupt;
157
 
                        if (data[i + len + 1] != 0)
158
 
                                goto exit_corrupt;
159
 
                        for (j = 0; j < ARRAY_SIZE(blob_name); j++) {
160
 
                                if (strcmp(blob_name[j], &data[i]) == 0) {
161
 
                                        fw[ix].data[j] = &data[i + len + 1];
162
 
                                        pr_debug("Loading %s\n", blob_name[j]);
163
 
                                }
164
 
                        }
165
 
                        i += len + 1;
166
 
                        break;
167
 
                case 0xff:      /* file terminator */
168
 
                        if (i == size) {
169
 
                                rc = 0;
170
 
                                goto exit_ok;
171
 
                        }
172
 
                default:
173
 
                        goto exit_corrupt;
174
 
                }
175
 
        } while (i < size);
176
 
 
177
 
exit_corrupt:
178
 
        printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name);
179
 
exit_err:
180
 
        _drx_release_fw(s, ix);
181
 
        fw[ix].refcnt--;
182
 
exit_ok:
183
 
        fw[ix].refcnt++;
184
 
        write_unlock(&fw[ix].lock);
185
 
 
186
 
        return rc;
187
 
}
188
 
 
189
 
/* i2c bus IO */
190
 
static int write_fw(struct drx397xD_state *s, enum blob_ix ix)
191
 
{
192
 
        const u8 *data;
193
 
        int len, rc = 0, i = 0;
194
 
        struct i2c_msg msg = {
195
 
                .addr = s->config.demod_address,
196
 
                .flags = 0
197
 
        };
198
 
 
199
 
        if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) {
200
 
                pr_debug("%s drx_fw_ix_t out of range\n", __func__);
201
 
                return -EINVAL;
202
 
        }
203
 
        pr_debug("%s %s\n", __func__, blob_name[ix]);
204
 
 
205
 
        read_lock(&fw[s->chip_rev].lock);
206
 
        data = fw[s->chip_rev].data[ix];
207
 
        if (!data) {
208
 
                rc = -EINVAL;
209
 
                goto exit_rc;
210
 
        }
211
 
 
212
 
        for (;;) {
213
 
                switch (data[i++]) {
214
 
                case 0: /* bytecode */
215
 
                        len = data[i++];
216
 
                        msg.len = len;
217
 
                        msg.buf = (__u8 *) &data[i];
218
 
                        if (i2c_transfer(s->i2c, &msg, 1) != 1) {
219
 
                                rc = -EIO;
220
 
                                goto exit_rc;
221
 
                        }
222
 
                        i += len;
223
 
                        break;
224
 
                case 1: /* reset */
225
 
                case 2: /* sleep */
226
 
                        i++;
227
 
                        break;
228
 
                default:
229
 
                        goto exit_rc;
230
 
                }
231
 
        }
232
 
exit_rc:
233
 
        read_unlock(&fw[s->chip_rev].lock);
234
 
 
235
 
        return rc;
236
 
}
237
 
 
238
 
/* Function is not endian safe, use the RD16 wrapper below */
239
 
static int _read16(struct drx397xD_state *s, __le32 i2c_adr)
240
 
{
241
 
        int rc;
242
 
        u8 a[4];
243
 
        __le16 v;
244
 
        struct i2c_msg msg[2] = {
245
 
                {
246
 
                        .addr = s->config.demod_address,
247
 
                        .flags = 0,
248
 
                        .buf = a,
249
 
                        .len = sizeof(a)
250
 
                }, {
251
 
                        .addr = s->config.demod_address,
252
 
                        .flags = I2C_M_RD,
253
 
                        .buf = (u8 *)&v,
254
 
                        .len = sizeof(v)
255
 
                }
256
 
        };
257
 
 
258
 
        *(__le32 *) a = i2c_adr;
259
 
 
260
 
        rc = i2c_transfer(s->i2c, msg, 2);
261
 
        if (rc != 2)
262
 
                return -EIO;
263
 
 
264
 
        return le16_to_cpu(v);
265
 
}
266
 
 
267
 
/* Function is not endian safe, use the WR16.. wrappers below */
268
 
static int _write16(struct drx397xD_state *s, __le32 i2c_adr, __le16 val)
269
 
{
270
 
        u8 a[6];
271
 
        int rc;
272
 
        struct i2c_msg msg = {
273
 
                .addr = s->config.demod_address,
274
 
                .flags = 0,
275
 
                .buf = a,
276
 
                .len = sizeof(a)
277
 
        };
278
 
 
279
 
        *(__le32 *)a = i2c_adr;
280
 
        *(__le16 *)&a[4] = val;
281
 
 
282
 
        rc = i2c_transfer(s->i2c, &msg, 1);
283
 
        if (rc != 1)
284
 
                return -EIO;
285
 
 
286
 
        return 0;
287
 
}
288
 
 
289
 
#define WR16(ss, adr, val) \
290
 
                _write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val))
291
 
#define WR16_E0(ss, adr, val) \
292
 
                _write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val))
293
 
#define RD16(ss, adr) \
294
 
                _read16(ss, I2C_ADR_C0(adr))
295
 
 
296
 
#define EXIT_RC(cmd)    \
297
 
        if ((rc = (cmd)) < 0)   \
298
 
                goto exit_rc
299
 
 
300
 
/* Tuner callback */
301
 
static int PLL_Set(struct drx397xD_state *s,
302
 
                   struct dvb_frontend_parameters *fep, int *df_tuner)
303
 
{
304
 
        struct dvb_frontend *fe = &s->frontend;
305
 
        u32 f_tuner, f = fep->frequency;
306
 
        int rc;
307
 
 
308
 
        pr_debug("%s\n", __func__);
309
 
 
310
 
        if ((f > s->frontend.ops.tuner_ops.info.frequency_max) ||
311
 
            (f < s->frontend.ops.tuner_ops.info.frequency_min))
312
 
                return -EINVAL;
313
 
 
314
 
        *df_tuner = 0;
315
 
        if (!s->frontend.ops.tuner_ops.set_params ||
316
 
            !s->frontend.ops.tuner_ops.get_frequency)
317
 
                return -ENOSYS;
318
 
 
319
 
        rc = s->frontend.ops.tuner_ops.set_params(fe, fep);
320
 
        if (rc < 0)
321
 
                return rc;
322
 
 
323
 
        rc = s->frontend.ops.tuner_ops.get_frequency(fe, &f_tuner);
324
 
        if (rc < 0)
325
 
                return rc;
326
 
 
327
 
        *df_tuner = f_tuner - f;
328
 
        pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __func__, f,
329
 
                 f_tuner);
330
 
 
331
 
        return 0;
332
 
}
333
 
 
334
 
/* Demodulator helper functions */
335
 
static int SC_WaitForReady(struct drx397xD_state *s)
336
 
{
337
 
        int cnt = 1000;
338
 
        int rc;
339
 
 
340
 
        pr_debug("%s\n", __func__);
341
 
 
342
 
        while (cnt--) {
343
 
                rc = RD16(s, 0x820043);
344
 
                if (rc == 0)
345
 
                        return 0;
346
 
        }
347
 
 
348
 
        return -1;
349
 
}
350
 
 
351
 
static int SC_SendCommand(struct drx397xD_state *s, int cmd)
352
 
{
353
 
        int rc;
354
 
 
355
 
        pr_debug("%s\n", __func__);
356
 
 
357
 
        WR16(s, 0x820043, cmd);
358
 
        SC_WaitForReady(s);
359
 
        rc = RD16(s, 0x820042);
360
 
        if ((rc & 0xffff) == 0xffff)
361
 
                return -1;
362
 
 
363
 
        return 0;
364
 
}
365
 
 
366
 
static int HI_Command(struct drx397xD_state *s, u16 cmd)
367
 
{
368
 
        int rc, cnt = 1000;
369
 
 
370
 
        pr_debug("%s\n", __func__);
371
 
 
372
 
        rc = WR16(s, 0x420032, cmd);
373
 
        if (rc < 0)
374
 
                return rc;
375
 
 
376
 
        do {
377
 
                rc = RD16(s, 0x420032);
378
 
                if (rc == 0) {
379
 
                        rc = RD16(s, 0x420031);
380
 
                        return rc;
381
 
                }
382
 
                if (rc < 0)
383
 
                        return rc;
384
 
        } while (--cnt);
385
 
 
386
 
        return rc;
387
 
}
388
 
 
389
 
static int HI_CfgCommand(struct drx397xD_state *s)
390
 
{
391
 
 
392
 
        pr_debug("%s\n", __func__);
393
 
 
394
 
        WR16(s, 0x420033, 0x3973);
395
 
        WR16(s, 0x420034, s->config.w50);       /* code 4, log 4 */
396
 
        WR16(s, 0x420035, s->config.w52);       /* code 15,  log 9 */
397
 
        WR16(s, 0x420036, s->config.demod_address << 1);
398
 
        WR16(s, 0x420037, s->config.w56);       /* code (set_i2c ??  initX 1 ), log 1 */
399
 
        /* WR16(s, 0x420033, 0x3973); */
400
 
        if ((s->config.w56 & 8) == 0)
401
 
                return HI_Command(s, 3);
402
 
 
403
 
        return WR16(s, 0x420032, 0x3);
404
 
}
405
 
 
406
 
static const u8 fastIncrDecLUT_15273[] = {
407
 
        0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14,
408
 
        0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f
409
 
};
410
 
 
411
 
static const u8 slowIncrDecLUT_15272[] = {
412
 
        3, 4, 4, 5, 6
413
 
};
414
 
 
415
 
static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc)
416
 
{
417
 
        u16 w06 = agc->w06;
418
 
        u16 w08 = agc->w08;
419
 
        u16 w0A = agc->w0A;
420
 
        u16 w0C = agc->w0C;
421
 
        int quot, rem, i, rc = -EINVAL;
422
 
 
423
 
        pr_debug("%s\n", __func__);
424
 
 
425
 
        if (agc->w04 > 0x3ff)
426
 
                goto exit_rc;
427
 
 
428
 
        if (agc->d00 == 1) {
429
 
                EXIT_RC(RD16(s, 0x0c20010));
430
 
                rc &= ~0x10;
431
 
                EXIT_RC(WR16(s, 0x0c20010, rc));
432
 
                return WR16(s, 0x0c20030, agc->w04 & 0x7ff);
433
 
        }
434
 
 
435
 
        if (agc->d00 != 0)
436
 
                goto exit_rc;
437
 
        if (w0A < w08)
438
 
                goto exit_rc;
439
 
        if (w0A > 0x3ff)
440
 
                goto exit_rc;
441
 
        if (w0C > 0x3ff)
442
 
                goto exit_rc;
443
 
        if (w06 > 0x3ff)
444
 
                goto exit_rc;
445
 
 
446
 
        EXIT_RC(RD16(s, 0x0c20010));
447
 
        rc |= 0x10;
448
 
        EXIT_RC(WR16(s, 0x0c20010, rc));
449
 
 
450
 
        EXIT_RC(WR16(s, 0x0c20025, (w06 >> 1) & 0x1ff));
451
 
        EXIT_RC(WR16(s, 0x0c20031, (w0A - w08) >> 1));
452
 
        EXIT_RC(WR16(s, 0x0c20032, ((w0A + w08) >> 1) - 0x1ff));
453
 
 
454
 
        quot = w0C / 113;
455
 
        rem = w0C % 113;
456
 
        if (quot <= 8) {
457
 
                quot = 8 - quot;
458
 
        } else {
459
 
                quot = 0;
460
 
                rem += 113;
461
 
        }
462
 
 
463
 
        EXIT_RC(WR16(s, 0x0c20024, quot));
464
 
 
465
 
        i = fastIncrDecLUT_15273[rem / 8];
466
 
        EXIT_RC(WR16(s, 0x0c2002d, i));
467
 
        EXIT_RC(WR16(s, 0x0c2002e, i));
468
 
 
469
 
        i = slowIncrDecLUT_15272[rem / 28];
470
 
        EXIT_RC(WR16(s, 0x0c2002b, i));
471
 
        rc = WR16(s, 0x0c2002c, i);
472
 
exit_rc:
473
 
        return rc;
474
 
}
475
 
 
476
 
static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
477
 
{
478
 
        u16 w04 = agc->w04;
479
 
        u16 w06 = agc->w06;
480
 
        int rc = -1;
481
 
 
482
 
        pr_debug("%s %d 0x%x 0x%x\n", __func__, agc->d00, w04, w06);
483
 
 
484
 
        if (w04 > 0x3ff)
485
 
                goto exit_rc;
486
 
 
487
 
        switch (agc->d00) {
488
 
        case 1:
489
 
                if (w04 == 0x3ff)
490
 
                        w04 = 0x400;
491
 
 
492
 
                EXIT_RC(WR16(s, 0x0c20036, w04));
493
 
                s->config.w9C &= ~2;
494
 
                EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
495
 
                EXIT_RC(RD16(s, 0x0c20010));
496
 
                rc &= 0xbfdf;
497
 
                EXIT_RC(WR16(s, 0x0c20010, rc));
498
 
                EXIT_RC(RD16(s, 0x0c20013));
499
 
                rc &= ~2;
500
 
                break;
501
 
        case 0:
502
 
                /* loc_8000659 */
503
 
                s->config.w9C &= ~2;
504
 
                EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
505
 
                EXIT_RC(RD16(s, 0x0c20010));
506
 
                rc &= 0xbfdf;
507
 
                rc |= 0x4000;
508
 
                EXIT_RC(WR16(s, 0x0c20010, rc));
509
 
                EXIT_RC(WR16(s, 0x0c20051, (w06 >> 4) & 0x3f));
510
 
                EXIT_RC(RD16(s, 0x0c20013));
511
 
                rc &= ~2;
512
 
                break;
513
 
        default:
514
 
                s->config.w9C |= 2;
515
 
                EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
516
 
                EXIT_RC(RD16(s, 0x0c20010));
517
 
                rc &= 0xbfdf;
518
 
                EXIT_RC(WR16(s, 0x0c20010, rc));
519
 
 
520
 
                EXIT_RC(WR16(s, 0x0c20036, 0));
521
 
 
522
 
                EXIT_RC(RD16(s, 0x0c20013));
523
 
                rc |= 2;
524
 
        }
525
 
        rc = WR16(s, 0x0c20013, rc);
526
 
 
527
 
exit_rc:
528
 
        return rc;
529
 
}
530
 
 
531
 
static int GetLockStatus(struct drx397xD_state *s, int *lockstat)
532
 
{
533
 
        int rc;
534
 
 
535
 
        *lockstat = 0;
536
 
 
537
 
        rc = RD16(s, 0x082004b);
538
 
        if (rc < 0)
539
 
                return rc;
540
 
 
541
 
        if (s->config.d60 != 2)
542
 
                return 0;
543
 
 
544
 
        if ((rc & 7) == 7)
545
 
                *lockstat |= 1;
546
 
        if ((rc & 3) == 3)
547
 
                *lockstat |= 2;
548
 
        if (rc & 1)
549
 
                *lockstat |= 4;
550
 
        return 0;
551
 
}
552
 
 
553
 
static int CorrectSysClockDeviation(struct drx397xD_state *s)
554
 
{
555
 
        int rc = -EINVAL;
556
 
        int lockstat;
557
 
        u32 clk, clk_limit;
558
 
 
559
 
        pr_debug("%s\n", __func__);
560
 
 
561
 
        if (s->config.d5C == 0) {
562
 
                EXIT_RC(WR16(s, 0x08200e8, 0x010));
563
 
                EXIT_RC(WR16(s, 0x08200e9, 0x113));
564
 
                s->config.d5C = 1;
565
 
                return rc;
566
 
        }
567
 
        if (s->config.d5C != 1)
568
 
                goto exit_rc;
569
 
 
570
 
        rc = RD16(s, 0x0820048);
571
 
 
572
 
        rc = GetLockStatus(s, &lockstat);
573
 
        if (rc < 0)
574
 
                goto exit_rc;
575
 
        if ((lockstat & 1) == 0)
576
 
                goto exit_rc;
577
 
 
578
 
        EXIT_RC(WR16(s, 0x0420033, 0x200));
579
 
        EXIT_RC(WR16(s, 0x0420034, 0xc5));
580
 
        EXIT_RC(WR16(s, 0x0420035, 0x10));
581
 
        EXIT_RC(WR16(s, 0x0420036, 0x1));
582
 
        EXIT_RC(WR16(s, 0x0420037, 0xa));
583
 
        EXIT_RC(HI_Command(s, 6));
584
 
        EXIT_RC(RD16(s, 0x0420040));
585
 
        clk = rc;
586
 
        EXIT_RC(RD16(s, 0x0420041));
587
 
        clk |= rc << 16;
588
 
 
589
 
        if (clk <= 0x26ffff)
590
 
                goto exit_rc;
591
 
        if (clk > 0x610000)
592
 
                goto exit_rc;
593
 
 
594
 
        if (!s->bandwidth_parm)
595
 
                return -EINVAL;
596
 
 
597
 
        /* round & convert to Hz */
598
 
        clk = ((u64) (clk + 0x800000) * s->bandwidth_parm + (1 << 20)) >> 21;
599
 
        clk_limit = s->config.f_osc * MAX_CLOCK_DRIFT / 1000;
600
 
 
601
 
        if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) {
602
 
                s->f_osc = clk;
603
 
                pr_debug("%s: osc %d %d [Hz]\n", __func__,
604
 
                         s->config.f_osc * 1000, clk - s->config.f_osc * 1000);
605
 
        }
606
 
        rc = WR16(s, 0x08200e8, 0);
607
 
 
608
 
exit_rc:
609
 
        return rc;
610
 
}
611
 
 
612
 
static int ConfigureMPEGOutput(struct drx397xD_state *s, int type)
613
 
{
614
 
        int rc, si, bp;
615
 
 
616
 
        pr_debug("%s\n", __func__);
617
 
 
618
 
        si = s->config.wA0;
619
 
        if (s->config.w98 == 0) {
620
 
                si |= 1;
621
 
                bp = 0;
622
 
        } else {
623
 
                si &= ~1;
624
 
                bp = 0x200;
625
 
        }
626
 
        if (s->config.w9A == 0)
627
 
                si |= 0x80;
628
 
        else
629
 
                si &= ~0x80;
630
 
 
631
 
        EXIT_RC(WR16(s, 0x2150045, 0));
632
 
        EXIT_RC(WR16(s, 0x2150010, si));
633
 
        EXIT_RC(WR16(s, 0x2150011, bp));
634
 
        rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0));
635
 
 
636
 
exit_rc:
637
 
        return rc;
638
 
}
639
 
 
640
 
static int drx_tune(struct drx397xD_state *s,
641
 
                    struct dvb_frontend_parameters *fep)
642
 
{
643
 
        u16 v22 = 0;
644
 
        u16 v1C = 0;
645
 
        u16 v1A = 0;
646
 
        u16 v18 = 0;
647
 
        u32 edi = 0, ebx = 0, ebp = 0, edx = 0;
648
 
        u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0;
649
 
 
650
 
        int rc, df_tuner = 0;
651
 
        int a, b, c, d;
652
 
        pr_debug("%s %d\n", __func__, s->config.d60);
653
 
 
654
 
        if (s->config.d60 != 2)
655
 
                goto set_tuner;
656
 
        rc = CorrectSysClockDeviation(s);
657
 
        if (rc < 0)
658
 
                goto set_tuner;
659
 
 
660
 
        s->config.d60 = 1;
661
 
        rc = ConfigureMPEGOutput(s, 0);
662
 
        if (rc < 0)
663
 
                goto set_tuner;
664
 
set_tuner:
665
 
 
666
 
        rc = PLL_Set(s, fep, &df_tuner);
667
 
        if (rc < 0) {
668
 
                printk(KERN_ERR "Error in pll_set\n");
669
 
                goto exit_rc;
670
 
        }
671
 
        msleep(200);
672
 
 
673
 
        a = rc = RD16(s, 0x2150016);
674
 
        if (rc < 0)
675
 
                goto exit_rc;
676
 
        b = rc = RD16(s, 0x2150010);
677
 
        if (rc < 0)
678
 
                goto exit_rc;
679
 
        c = rc = RD16(s, 0x2150034);
680
 
        if (rc < 0)
681
 
                goto exit_rc;
682
 
        d = rc = RD16(s, 0x2150035);
683
 
        if (rc < 0)
684
 
                goto exit_rc;
685
 
        rc = WR16(s, 0x2150014, c);
686
 
        rc = WR16(s, 0x2150015, d);
687
 
        rc = WR16(s, 0x2150010, 0);
688
 
        rc = WR16(s, 0x2150000, 2);
689
 
        rc = WR16(s, 0x2150036, 0x0fff);
690
 
        rc = WR16(s, 0x2150016, a);
691
 
 
692
 
        rc = WR16(s, 0x2150010, 2);
693
 
        rc = WR16(s, 0x2150007, 0);
694
 
        rc = WR16(s, 0x2150000, 1);
695
 
        rc = WR16(s, 0x2110000, 0);
696
 
        rc = WR16(s, 0x0800000, 0);
697
 
        rc = WR16(s, 0x2800000, 0);
698
 
        rc = WR16(s, 0x2110010, 0x664);
699
 
 
700
 
        rc = write_fw(s, DRXD_ResetECRAM);
701
 
        rc = WR16(s, 0x2110000, 1);
702
 
 
703
 
        rc = write_fw(s, DRXD_InitSC);
704
 
        if (rc < 0)
705
 
                goto exit_rc;
706
 
 
707
 
        rc = SetCfgIfAgc(s, &s->config.ifagc);
708
 
        if (rc < 0)
709
 
                goto exit_rc;
710
 
 
711
 
        rc = SetCfgRfAgc(s, &s->config.rfagc);
712
 
        if (rc < 0)
713
 
                goto exit_rc;
714
 
 
715
 
        if (fep->u.ofdm.transmission_mode != TRANSMISSION_MODE_2K)
716
 
                v22 = 1;
717
 
        switch (fep->u.ofdm.transmission_mode) {
718
 
        case TRANSMISSION_MODE_8K:
719
 
                edi = 1;
720
 
                if (s->chip_rev == DRXD_FW_B1)
721
 
                        break;
722
 
 
723
 
                rc = WR16(s, 0x2010010, 0);
724
 
                if (rc < 0)
725
 
                        break;
726
 
                v1C = 0x63;
727
 
                v1A = 0x53;
728
 
                v18 = 0x43;
729
 
                break;
730
 
        default:
731
 
                edi = 0;
732
 
                if (s->chip_rev == DRXD_FW_B1)
733
 
                        break;
734
 
 
735
 
                rc = WR16(s, 0x2010010, 1);
736
 
                if (rc < 0)
737
 
                        break;
738
 
 
739
 
                v1C = 0x61;
740
 
                v1A = 0x47;
741
 
                v18 = 0x41;
742
 
        }
743
 
 
744
 
        switch (fep->u.ofdm.guard_interval) {
745
 
        case GUARD_INTERVAL_1_4:
746
 
                edi |= 0x0c;
747
 
                break;
748
 
        case GUARD_INTERVAL_1_8:
749
 
                edi |= 0x08;
750
 
                break;
751
 
        case GUARD_INTERVAL_1_16:
752
 
                edi |= 0x04;
753
 
                break;
754
 
        case GUARD_INTERVAL_1_32:
755
 
                break;
756
 
        default:
757
 
                v22 |= 2;
758
 
        }
759
 
 
760
 
        ebx = 0;
761
 
        ebp = 0;
762
 
        v20 = 0;
763
 
        v1E = 0;
764
 
        v16 = 0;
765
 
        v14 = 0;
766
 
        v12 = 0;
767
 
        v10 = 0;
768
 
        v0E = 0;
769
 
 
770
 
        switch (fep->u.ofdm.hierarchy_information) {
771
 
        case HIERARCHY_1:
772
 
                edi |= 0x40;
773
 
                if (s->chip_rev == DRXD_FW_B1)
774
 
                        break;
775
 
                rc = WR16(s, 0x1c10047, 1);
776
 
                if (rc < 0)
777
 
                        goto exit_rc;
778
 
                rc = WR16(s, 0x2010012, 1);
779
 
                if (rc < 0)
780
 
                        goto exit_rc;
781
 
                ebx = 0x19f;
782
 
                ebp = 0x1fb;
783
 
                v20 = 0x0c0;
784
 
                v1E = 0x195;
785
 
                v16 = 0x1d6;
786
 
                v14 = 0x1ef;
787
 
                v12 = 4;
788
 
                v10 = 5;
789
 
                v0E = 5;
790
 
                break;
791
 
        case HIERARCHY_2:
792
 
                edi |= 0x80;
793
 
                if (s->chip_rev == DRXD_FW_B1)
794
 
                        break;
795
 
                rc = WR16(s, 0x1c10047, 2);
796
 
                if (rc < 0)
797
 
                        goto exit_rc;
798
 
                rc = WR16(s, 0x2010012, 2);
799
 
                if (rc < 0)
800
 
                        goto exit_rc;
801
 
                ebx = 0x08f;
802
 
                ebp = 0x12f;
803
 
                v20 = 0x0c0;
804
 
                v1E = 0x11e;
805
 
                v16 = 0x1d6;
806
 
                v14 = 0x15e;
807
 
                v12 = 4;
808
 
                v10 = 5;
809
 
                v0E = 5;
810
 
                break;
811
 
        case HIERARCHY_4:
812
 
                edi |= 0xc0;
813
 
                if (s->chip_rev == DRXD_FW_B1)
814
 
                        break;
815
 
                rc = WR16(s, 0x1c10047, 3);
816
 
                if (rc < 0)
817
 
                        goto exit_rc;
818
 
                rc = WR16(s, 0x2010012, 3);
819
 
                if (rc < 0)
820
 
                        goto exit_rc;
821
 
                ebx = 0x14d;
822
 
                ebp = 0x197;
823
 
                v20 = 0x0c0;
824
 
                v1E = 0x1ce;
825
 
                v16 = 0x1d6;
826
 
                v14 = 0x11a;
827
 
                v12 = 4;
828
 
                v10 = 6;
829
 
                v0E = 5;
830
 
                break;
831
 
        default:
832
 
                v22 |= 8;
833
 
                if (s->chip_rev == DRXD_FW_B1)
834
 
                        break;
835
 
                rc = WR16(s, 0x1c10047, 0);
836
 
                if (rc < 0)
837
 
                        goto exit_rc;
838
 
                rc = WR16(s, 0x2010012, 0);
839
 
                if (rc < 0)
840
 
                        goto exit_rc;
841
 
                                /* QPSK    QAM16  QAM64 */
842
 
                ebx = 0x19f;    /*                 62   */
843
 
                ebp = 0x1fb;    /*                 15   */
844
 
                v20 = 0x16a;    /*  62                  */
845
 
                v1E = 0x195;    /*         62           */
846
 
                v16 = 0x1bb;    /*  15                  */
847
 
                v14 = 0x1ef;    /*         15           */
848
 
                v12 = 5;        /*  16                  */
849
 
                v10 = 5;        /*         16           */
850
 
                v0E = 5;        /*                 16   */
851
 
        }
852
 
 
853
 
        switch (fep->u.ofdm.constellation) {
854
 
        default:
855
 
                v22 |= 4;
856
 
        case QPSK:
857
 
                if (s->chip_rev == DRXD_FW_B1)
858
 
                        break;
859
 
 
860
 
                rc = WR16(s, 0x1c10046, 0);
861
 
                if (rc < 0)
862
 
                        goto exit_rc;
863
 
                rc = WR16(s, 0x2010011, 0);
864
 
                if (rc < 0)
865
 
                        goto exit_rc;
866
 
                rc = WR16(s, 0x201001a, 0x10);
867
 
                if (rc < 0)
868
 
                        goto exit_rc;
869
 
                rc = WR16(s, 0x201001b, 0);
870
 
                if (rc < 0)
871
 
                        goto exit_rc;
872
 
                rc = WR16(s, 0x201001c, 0);
873
 
                if (rc < 0)
874
 
                        goto exit_rc;
875
 
                rc = WR16(s, 0x1c10062, v20);
876
 
                if (rc < 0)
877
 
                        goto exit_rc;
878
 
                rc = WR16(s, 0x1c1002a, v1C);
879
 
                if (rc < 0)
880
 
                        goto exit_rc;
881
 
                rc = WR16(s, 0x1c10015, v16);
882
 
                if (rc < 0)
883
 
                        goto exit_rc;
884
 
                rc = WR16(s, 0x1c10016, v12);
885
 
                if (rc < 0)
886
 
                        goto exit_rc;
887
 
                break;
888
 
        case QAM_16:
889
 
                edi |= 0x10;
890
 
                if (s->chip_rev == DRXD_FW_B1)
891
 
                        break;
892
 
 
893
 
                rc = WR16(s, 0x1c10046, 1);
894
 
                if (rc < 0)
895
 
                        goto exit_rc;
896
 
                rc = WR16(s, 0x2010011, 1);
897
 
                if (rc < 0)
898
 
                        goto exit_rc;
899
 
                rc = WR16(s, 0x201001a, 0x10);
900
 
                if (rc < 0)
901
 
                        goto exit_rc;
902
 
                rc = WR16(s, 0x201001b, 4);
903
 
                if (rc < 0)
904
 
                        goto exit_rc;
905
 
                rc = WR16(s, 0x201001c, 0);
906
 
                if (rc < 0)
907
 
                        goto exit_rc;
908
 
                rc = WR16(s, 0x1c10062, v1E);
909
 
                if (rc < 0)
910
 
                        goto exit_rc;
911
 
                rc = WR16(s, 0x1c1002a, v1A);
912
 
                if (rc < 0)
913
 
                        goto exit_rc;
914
 
                rc = WR16(s, 0x1c10015, v14);
915
 
                if (rc < 0)
916
 
                        goto exit_rc;
917
 
                rc = WR16(s, 0x1c10016, v10);
918
 
                if (rc < 0)
919
 
                        goto exit_rc;
920
 
                break;
921
 
        case QAM_64:
922
 
                edi |= 0x20;
923
 
                rc = WR16(s, 0x1c10046, 2);
924
 
                if (rc < 0)
925
 
                        goto exit_rc;
926
 
                rc = WR16(s, 0x2010011, 2);
927
 
                if (rc < 0)
928
 
                        goto exit_rc;
929
 
                rc = WR16(s, 0x201001a, 0x20);
930
 
                if (rc < 0)
931
 
                        goto exit_rc;
932
 
                rc = WR16(s, 0x201001b, 8);
933
 
                if (rc < 0)
934
 
                        goto exit_rc;
935
 
                rc = WR16(s, 0x201001c, 2);
936
 
                if (rc < 0)
937
 
                        goto exit_rc;
938
 
                rc = WR16(s, 0x1c10062, ebx);
939
 
                if (rc < 0)
940
 
                        goto exit_rc;
941
 
                rc = WR16(s, 0x1c1002a, v18);
942
 
                if (rc < 0)
943
 
                        goto exit_rc;
944
 
                rc = WR16(s, 0x1c10015, ebp);
945
 
                if (rc < 0)
946
 
                        goto exit_rc;
947
 
                rc = WR16(s, 0x1c10016, v0E);
948
 
                if (rc < 0)
949
 
                        goto exit_rc;
950
 
                break;
951
 
        }
952
 
 
953
 
        if (s->config.s20d24 == 1) {
954
 
                rc = WR16(s, 0x2010013, 0);
955
 
        } else {
956
 
                rc = WR16(s, 0x2010013, 1);
957
 
                edi |= 0x1000;
958
 
        }
959
 
 
960
 
        switch (fep->u.ofdm.code_rate_HP) {
961
 
        default:
962
 
                v22 |= 0x10;
963
 
        case FEC_1_2:
964
 
                if (s->chip_rev == DRXD_FW_B1)
965
 
                        break;
966
 
                rc = WR16(s, 0x2090011, 0);
967
 
                break;
968
 
        case FEC_2_3:
969
 
                edi |= 0x200;
970
 
                if (s->chip_rev == DRXD_FW_B1)
971
 
                        break;
972
 
                rc = WR16(s, 0x2090011, 1);
973
 
                break;
974
 
        case FEC_3_4:
975
 
                edi |= 0x400;
976
 
                if (s->chip_rev == DRXD_FW_B1)
977
 
                        break;
978
 
                rc = WR16(s, 0x2090011, 2);
979
 
                break;
980
 
        case FEC_5_6:           /* 5 */
981
 
                edi |= 0x600;
982
 
                if (s->chip_rev == DRXD_FW_B1)
983
 
                        break;
984
 
                rc = WR16(s, 0x2090011, 3);
985
 
                break;
986
 
        case FEC_7_8:           /* 7 */
987
 
                edi |= 0x800;
988
 
                if (s->chip_rev == DRXD_FW_B1)
989
 
                        break;
990
 
                rc = WR16(s, 0x2090011, 4);
991
 
                break;
992
 
        };
993
 
        if (rc < 0)
994
 
                goto exit_rc;
995
 
 
996
 
        switch (fep->u.ofdm.bandwidth) {
997
 
        default:
998
 
                rc = -EINVAL;
999
 
                goto exit_rc;
1000
 
        case BANDWIDTH_8_MHZ:   /* 0 */
1001
 
        case BANDWIDTH_AUTO:
1002
 
                rc = WR16(s, 0x0c2003f, 0x32);
1003
 
                s->bandwidth_parm = ebx = 0x8b8249;
1004
 
                edx = 0;
1005
 
                break;
1006
 
        case BANDWIDTH_7_MHZ:
1007
 
                rc = WR16(s, 0x0c2003f, 0x3b);
1008
 
                s->bandwidth_parm = ebx = 0x7a1200;
1009
 
                edx = 0x4807;
1010
 
                break;
1011
 
        case BANDWIDTH_6_MHZ:
1012
 
                rc = WR16(s, 0x0c2003f, 0x47);
1013
 
                s->bandwidth_parm = ebx = 0x68a1b6;
1014
 
                edx = 0x0f07;
1015
 
                break;
1016
 
        };
1017
 
 
1018
 
        if (rc < 0)
1019
 
                goto exit_rc;
1020
 
 
1021
 
        rc = WR16(s, 0x08200ec, edx);
1022
 
        if (rc < 0)
1023
 
                goto exit_rc;
1024
 
 
1025
 
        rc = RD16(s, 0x0820050);
1026
 
        if (rc < 0)
1027
 
                goto exit_rc;
1028
 
        rc = WR16(s, 0x0820050, rc);
1029
 
 
1030
 
        {
1031
 
                /* Configure bandwidth specific factor */
1032
 
                ebx = div64_u64(((u64) (s->f_osc) << 21) + (ebx >> 1),
1033
 
                                     (u64)ebx) - 0x800000;
1034
 
                EXIT_RC(WR16(s, 0x0c50010, ebx & 0xffff));
1035
 
                EXIT_RC(WR16(s, 0x0c50011, ebx >> 16));
1036
 
 
1037
 
                /* drx397xD oscillator calibration */
1038
 
                ebx = div64_u64(((u64) (s->config.f_if + df_tuner) << 28) +
1039
 
                                     (s->f_osc >> 1), (u64)s->f_osc);
1040
 
        }
1041
 
        ebx &= 0xfffffff;
1042
 
        if (fep->inversion == INVERSION_ON)
1043
 
                ebx = 0x10000000 - ebx;
1044
 
 
1045
 
        EXIT_RC(WR16(s, 0x0c30010, ebx & 0xffff));
1046
 
        EXIT_RC(WR16(s, 0x0c30011, ebx >> 16));
1047
 
 
1048
 
        EXIT_RC(WR16(s, 0x0800000, 1));
1049
 
        EXIT_RC(RD16(s, 0x0800000));
1050
 
 
1051
 
 
1052
 
        EXIT_RC(SC_WaitForReady(s));
1053
 
        EXIT_RC(WR16(s, 0x0820042, 0));
1054
 
        EXIT_RC(WR16(s, 0x0820041, v22));
1055
 
        EXIT_RC(WR16(s, 0x0820040, edi));
1056
 
        EXIT_RC(SC_SendCommand(s, 3));
1057
 
 
1058
 
        rc = RD16(s, 0x0800000);
1059
 
 
1060
 
        SC_WaitForReady(s);
1061
 
        WR16(s, 0x0820042, 0);
1062
 
        WR16(s, 0x0820041, 1);
1063
 
        WR16(s, 0x0820040, 1);
1064
 
        SC_SendCommand(s, 1);
1065
 
 
1066
 
 
1067
 
        rc = WR16(s, 0x2150000, 2);
1068
 
        rc = WR16(s, 0x2150016, a);
1069
 
        rc = WR16(s, 0x2150010, 4);
1070
 
        rc = WR16(s, 0x2150036, 0);
1071
 
        rc = WR16(s, 0x2150000, 1);
1072
 
        s->config.d60 = 2;
1073
 
 
1074
 
exit_rc:
1075
 
        return rc;
1076
 
}
1077
 
 
1078
 
/*******************************************************************************
1079
 
 * DVB interface
1080
 
 ******************************************************************************/
1081
 
 
1082
 
static int drx397x_init(struct dvb_frontend *fe)
1083
 
{
1084
 
        struct drx397xD_state *s = fe->demodulator_priv;
1085
 
        int rc;
1086
 
 
1087
 
        pr_debug("%s\n", __func__);
1088
 
 
1089
 
        s->config.rfagc.d00 = 2;        /* 0x7c */
1090
 
        s->config.rfagc.w04 = 0;
1091
 
        s->config.rfagc.w06 = 0x3ff;
1092
 
 
1093
 
        s->config.ifagc.d00 = 0;        /* 0x68 */
1094
 
        s->config.ifagc.w04 = 0;
1095
 
        s->config.ifagc.w06 = 140;
1096
 
        s->config.ifagc.w08 = 0;
1097
 
        s->config.ifagc.w0A = 0x3ff;
1098
 
        s->config.ifagc.w0C = 0x388;
1099
 
 
1100
 
        /* for signal strenght calculations */
1101
 
        s->config.ss76 = 820;
1102
 
        s->config.ss78 = 2200;
1103
 
        s->config.ss7A = 150;
1104
 
 
1105
 
        /* HI_CfgCommand */
1106
 
        s->config.w50 = 4;
1107
 
        s->config.w52 = 9;
1108
 
 
1109
 
        s->config.f_if = 42800000;      /* d14: intermediate frequency [Hz] */
1110
 
        s->config.f_osc = 48000;        /* s66 : oscillator frequency [kHz] */
1111
 
        s->config.w92 = 12000;
1112
 
 
1113
 
        s->config.w9C = 0x000e;
1114
 
        s->config.w9E = 0x0000;
1115
 
 
1116
 
        /* ConfigureMPEGOutput params */
1117
 
        s->config.wA0 = 4;
1118
 
        s->config.w98 = 1;
1119
 
        s->config.w9A = 1;
1120
 
 
1121
 
        /* get chip revision */
1122
 
        rc = RD16(s, 0x2410019);
1123
 
        if (rc < 0)
1124
 
                return -ENODEV;
1125
 
 
1126
 
        if (rc == 0) {
1127
 
                printk(KERN_INFO "%s: chip revision A2\n", mod_name);
1128
 
                rc = drx_load_fw(s, DRXD_FW_A2);
1129
 
        } else {
1130
 
 
1131
 
                rc = (rc >> 12) - 3;
1132
 
                switch (rc) {
1133
 
                case 1:
1134
 
                        s->flags |= F_SET_0D4h;
1135
 
                case 0:
1136
 
                case 4:
1137
 
                        s->flags |= F_SET_0D0h;
1138
 
                        break;
1139
 
                case 2:
1140
 
                case 5:
1141
 
                        break;
1142
 
                case 3:
1143
 
                        s->flags |= F_SET_0D4h;
1144
 
                        break;
1145
 
                default:
1146
 
                        return -ENODEV;
1147
 
                };
1148
 
                printk(KERN_INFO "%s: chip revision B1.%d\n", mod_name, rc);
1149
 
                rc = drx_load_fw(s, DRXD_FW_B1);
1150
 
        }
1151
 
        if (rc < 0)
1152
 
                goto error;
1153
 
 
1154
 
        rc = WR16(s, 0x0420033, 0x3973);
1155
 
        if (rc < 0)
1156
 
                goto error;
1157
 
 
1158
 
        rc = HI_Command(s, 2);
1159
 
 
1160
 
        msleep(1);
1161
 
 
1162
 
        if (s->chip_rev == DRXD_FW_A2) {
1163
 
                rc = WR16(s, 0x043012d, 0x47F);
1164
 
                if (rc < 0)
1165
 
                        goto error;
1166
 
        }
1167
 
        rc = WR16_E0(s, 0x0400000, 0);
1168
 
        if (rc < 0)
1169
 
                goto error;
1170
 
 
1171
 
        if (s->config.w92 > 20000 || s->config.w92 % 4000) {
1172
 
                printk(KERN_ERR "%s: invalid osc frequency\n", mod_name);
1173
 
                rc = -1;
1174
 
                goto error;
1175
 
        }
1176
 
 
1177
 
        rc = WR16(s, 0x2410010, 1);
1178
 
        if (rc < 0)
1179
 
                goto error;
1180
 
        rc = WR16(s, 0x2410011, 0x15);
1181
 
        if (rc < 0)
1182
 
                goto error;
1183
 
        rc = WR16(s, 0x2410012, s->config.w92 / 4000);
1184
 
        if (rc < 0)
1185
 
                goto error;
1186
 
#ifdef ORIG_FW
1187
 
        rc = WR16(s, 0x2410015, 2);
1188
 
        if (rc < 0)
1189
 
                goto error;
1190
 
#endif
1191
 
        rc = WR16(s, 0x2410017, 0x3973);
1192
 
        if (rc < 0)
1193
 
                goto error;
1194
 
 
1195
 
        s->f_osc = s->config.f_osc * 1000;      /* initial estimator */
1196
 
 
1197
 
        s->config.w56 = 1;
1198
 
 
1199
 
        rc = HI_CfgCommand(s);
1200
 
        if (rc < 0)
1201
 
                goto error;
1202
 
 
1203
 
        rc = write_fw(s, DRXD_InitAtomicRead);
1204
 
        if (rc < 0)
1205
 
                goto error;
1206
 
 
1207
 
        if (s->chip_rev == DRXD_FW_A2) {
1208
 
                rc = WR16(s, 0x2150013, 0);
1209
 
                if (rc < 0)
1210
 
                        goto error;
1211
 
        }
1212
 
 
1213
 
        rc = WR16_E0(s, 0x0400002, 0);
1214
 
        if (rc < 0)
1215
 
                goto error;
1216
 
        rc = WR16(s, 0x0400002, 0);
1217
 
        if (rc < 0)
1218
 
                goto error;
1219
 
 
1220
 
        if (s->chip_rev == DRXD_FW_A2) {
1221
 
                rc = write_fw(s, DRXD_ResetCEFR);
1222
 
                if (rc < 0)
1223
 
                        goto error;
1224
 
        }
1225
 
        rc = write_fw(s, DRXD_microcode);
1226
 
        if (rc < 0)
1227
 
                goto error;
1228
 
 
1229
 
        s->config.w9C = 0x0e;
1230
 
        if (s->flags & F_SET_0D0h) {
1231
 
                s->config.w9C = 0;
1232
 
                rc = RD16(s, 0x0c20010);
1233
 
                if (rc < 0)
1234
 
                        goto write_DRXD_InitFE_1;
1235
 
 
1236
 
                rc &= ~0x1000;
1237
 
                rc = WR16(s, 0x0c20010, rc);
1238
 
                if (rc < 0)
1239
 
                        goto write_DRXD_InitFE_1;
1240
 
 
1241
 
                rc = RD16(s, 0x0c20011);
1242
 
                if (rc < 0)
1243
 
                        goto write_DRXD_InitFE_1;
1244
 
 
1245
 
                rc &= ~0x8;
1246
 
                rc = WR16(s, 0x0c20011, rc);
1247
 
                if (rc < 0)
1248
 
                        goto write_DRXD_InitFE_1;
1249
 
 
1250
 
                rc = WR16(s, 0x0c20012, 1);
1251
 
        }
1252
 
 
1253
 
write_DRXD_InitFE_1:
1254
 
 
1255
 
        rc = write_fw(s, DRXD_InitFE_1);
1256
 
        if (rc < 0)
1257
 
                goto error;
1258
 
 
1259
 
        rc = 1;
1260
 
        if (s->chip_rev == DRXD_FW_B1) {
1261
 
                if (s->flags & F_SET_0D0h)
1262
 
                        rc = 0;
1263
 
        } else {
1264
 
                if (s->flags & F_SET_0D0h)
1265
 
                        rc = 4;
1266
 
        }
1267
 
 
1268
 
        rc = WR16(s, 0x0C20012, rc);
1269
 
        if (rc < 0)
1270
 
                goto error;
1271
 
 
1272
 
        rc = WR16(s, 0x0C20013, s->config.w9E);
1273
 
        if (rc < 0)
1274
 
                goto error;
1275
 
        rc = WR16(s, 0x0C20015, s->config.w9C);
1276
 
        if (rc < 0)
1277
 
                goto error;
1278
 
 
1279
 
        rc = write_fw(s, DRXD_InitFE_2);
1280
 
        if (rc < 0)
1281
 
                goto error;
1282
 
        rc = write_fw(s, DRXD_InitFT);
1283
 
        if (rc < 0)
1284
 
                goto error;
1285
 
        rc = write_fw(s, DRXD_InitCP);
1286
 
        if (rc < 0)
1287
 
                goto error;
1288
 
        rc = write_fw(s, DRXD_InitCE);
1289
 
        if (rc < 0)
1290
 
                goto error;
1291
 
        rc = write_fw(s, DRXD_InitEQ);
1292
 
        if (rc < 0)
1293
 
                goto error;
1294
 
        rc = write_fw(s, DRXD_InitEC);
1295
 
        if (rc < 0)
1296
 
                goto error;
1297
 
        rc = write_fw(s, DRXD_InitSC);
1298
 
        if (rc < 0)
1299
 
                goto error;
1300
 
 
1301
 
        rc = SetCfgIfAgc(s, &s->config.ifagc);
1302
 
        if (rc < 0)
1303
 
                goto error;
1304
 
 
1305
 
        rc = SetCfgRfAgc(s, &s->config.rfagc);
1306
 
        if (rc < 0)
1307
 
                goto error;
1308
 
 
1309
 
        rc = ConfigureMPEGOutput(s, 1);
1310
 
        rc = WR16(s, 0x08201fe, 0x0017);
1311
 
        rc = WR16(s, 0x08201ff, 0x0101);
1312
 
 
1313
 
        s->config.d5C = 0;
1314
 
        s->config.d60 = 1;
1315
 
        s->config.d48 = 1;
1316
 
 
1317
 
error:
1318
 
        return rc;
1319
 
}
1320
 
 
1321
 
static int drx397x_get_frontend(struct dvb_frontend *fe,
1322
 
                                struct dvb_frontend_parameters *params)
1323
 
{
1324
 
        return 0;
1325
 
}
1326
 
 
1327
 
static int drx397x_set_frontend(struct dvb_frontend *fe,
1328
 
                                struct dvb_frontend_parameters *params)
1329
 
{
1330
 
        struct drx397xD_state *s = fe->demodulator_priv;
1331
 
 
1332
 
        s->config.s20d24 = 1;
1333
 
 
1334
 
        return drx_tune(s, params);
1335
 
}
1336
 
 
1337
 
static int drx397x_get_tune_settings(struct dvb_frontend *fe,
1338
 
                                     struct dvb_frontend_tune_settings
1339
 
                                     *fe_tune_settings)
1340
 
{
1341
 
        fe_tune_settings->min_delay_ms = 10000;
1342
 
        fe_tune_settings->step_size = 0;
1343
 
        fe_tune_settings->max_drift = 0;
1344
 
 
1345
 
        return 0;
1346
 
}
1347
 
 
1348
 
static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t *status)
1349
 
{
1350
 
        struct drx397xD_state *s = fe->demodulator_priv;
1351
 
        int lockstat;
1352
 
 
1353
 
        GetLockStatus(s, &lockstat);
1354
 
 
1355
 
        *status = 0;
1356
 
        if (lockstat & 2) {
1357
 
                CorrectSysClockDeviation(s);
1358
 
                ConfigureMPEGOutput(s, 1);
1359
 
                *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;
1360
 
        }
1361
 
        if (lockstat & 4)
1362
 
                *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
1363
 
 
1364
 
        return 0;
1365
 
}
1366
 
 
1367
 
static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber)
1368
 
{
1369
 
        *ber = 0;
1370
 
 
1371
 
        return 0;
1372
 
}
1373
 
 
1374
 
static int drx397x_read_snr(struct dvb_frontend *fe, u16 *snr)
1375
 
{
1376
 
        *snr = 0;
1377
 
 
1378
 
        return 0;
1379
 
}
1380
 
 
1381
 
static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
1382
 
{
1383
 
        struct drx397xD_state *s = fe->demodulator_priv;
1384
 
        int rc;
1385
 
 
1386
 
        if (s->config.ifagc.d00 == 2) {
1387
 
                *strength = 0xffff;
1388
 
                return 0;
1389
 
        }
1390
 
        rc = RD16(s, 0x0c20035);
1391
 
        if (rc < 0) {
1392
 
                *strength = 0;
1393
 
                return 0;
1394
 
        }
1395
 
        rc &= 0x3ff;
1396
 
        /* Signal strength is calculated using the following formula:
1397
 
         *
1398
 
         * a = 2200 * 150 / (2200 + 150);
1399
 
         * a = a * 3300 /  (a + 820);
1400
 
         * b = 2200 * 3300 / (2200 + 820);
1401
 
         * c = (((b-a) * rc) >> 10  + a) << 4;
1402
 
         * strength = ~c & 0xffff;
1403
 
         *
1404
 
         * The following does the same but with less rounding errors:
1405
 
         */
1406
 
        *strength = ~(7720 + (rc * 30744 >> 10));
1407
 
 
1408
 
        return 0;
1409
 
}
1410
 
 
1411
 
static int drx397x_read_ucblocks(struct dvb_frontend *fe,
1412
 
                                 unsigned int *ucblocks)
1413
 
{
1414
 
        *ucblocks = 0;
1415
 
 
1416
 
        return 0;
1417
 
}
1418
 
 
1419
 
static int drx397x_sleep(struct dvb_frontend *fe)
1420
 
{
1421
 
        return 0;
1422
 
}
1423
 
 
1424
 
static void drx397x_release(struct dvb_frontend *fe)
1425
 
{
1426
 
        struct drx397xD_state *s = fe->demodulator_priv;
1427
 
        printk(KERN_INFO "%s: release demodulator\n", mod_name);
1428
 
        if (s) {
1429
 
                drx_release_fw(s);
1430
 
                kfree(s);
1431
 
        }
1432
 
 
1433
 
}
1434
 
 
1435
 
static struct dvb_frontend_ops drx397x_ops = {
1436
 
 
1437
 
        .info = {
1438
 
                 .name                  = "Micronas DRX397xD DVB-T Frontend",
1439
 
                 .type                  = FE_OFDM,
1440
 
                 .frequency_min         = 47125000,
1441
 
                 .frequency_max         = 855250000,
1442
 
                 .frequency_stepsize    = 166667,
1443
 
                 .frequency_tolerance   = 0,
1444
 
                 .caps =                                  /* 0x0C01B2EAE */
1445
 
                         FE_CAN_FEC_1_2                 | /* = 0x2, */
1446
 
                         FE_CAN_FEC_2_3                 | /* = 0x4, */
1447
 
                         FE_CAN_FEC_3_4                 | /* = 0x8, */
1448
 
                         FE_CAN_FEC_5_6                 | /* = 0x20, */
1449
 
                         FE_CAN_FEC_7_8                 | /* = 0x80, */
1450
 
                         FE_CAN_FEC_AUTO                | /* = 0x200, */
1451
 
                         FE_CAN_QPSK                    | /* = 0x400, */
1452
 
                         FE_CAN_QAM_16                  | /* = 0x800, */
1453
 
                         FE_CAN_QAM_64                  | /* = 0x2000, */
1454
 
                         FE_CAN_QAM_AUTO                | /* = 0x10000, */
1455
 
                         FE_CAN_TRANSMISSION_MODE_AUTO  | /* = 0x20000, */
1456
 
                         FE_CAN_GUARD_INTERVAL_AUTO     | /* = 0x80000, */
1457
 
                         FE_CAN_HIERARCHY_AUTO          | /* = 0x100000, */
1458
 
                         FE_CAN_RECOVER                 | /* = 0x40000000, */
1459
 
                         FE_CAN_MUTE_TS                   /* = 0x80000000 */
1460
 
         },
1461
 
 
1462
 
        .release = drx397x_release,
1463
 
        .init = drx397x_init,
1464
 
        .sleep = drx397x_sleep,
1465
 
 
1466
 
        .set_frontend = drx397x_set_frontend,
1467
 
        .get_tune_settings = drx397x_get_tune_settings,
1468
 
        .get_frontend = drx397x_get_frontend,
1469
 
 
1470
 
        .read_status = drx397x_read_status,
1471
 
        .read_snr = drx397x_read_snr,
1472
 
        .read_signal_strength = drx397x_read_signal_strength,
1473
 
        .read_ber = drx397x_read_ber,
1474
 
        .read_ucblocks = drx397x_read_ucblocks,
1475
 
};
1476
 
 
1477
 
struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config,
1478
 
                                     struct i2c_adapter *i2c)
1479
 
{
1480
 
        struct drx397xD_state *state;
1481
 
 
1482
 
        /* allocate memory for the internal state */
1483
 
        state = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL);
1484
 
        if (!state)
1485
 
                goto error;
1486
 
 
1487
 
        /* setup the state */
1488
 
        state->i2c = i2c;
1489
 
        memcpy(&state->config, config, sizeof(struct drx397xD_config));
1490
 
 
1491
 
        /* check if the demod is there */
1492
 
        if (RD16(state, 0x2410019) < 0)
1493
 
                goto error;
1494
 
 
1495
 
        /* create dvb_frontend */
1496
 
        memcpy(&state->frontend.ops, &drx397x_ops,
1497
 
                        sizeof(struct dvb_frontend_ops));
1498
 
        state->frontend.demodulator_priv = state;
1499
 
 
1500
 
        return &state->frontend;
1501
 
error:
1502
 
        kfree(state);
1503
 
 
1504
 
        return NULL;
1505
 
}
1506
 
EXPORT_SYMBOL(drx397xD_attach);
1507
 
 
1508
 
MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend");
1509
 
MODULE_AUTHOR("Henk Vergonet");
1510
 
MODULE_LICENSE("GPL");
1511