Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/dvb/frontends/dib7000m.c
15112 views
1
/*
2
* Linux-DVB Driver for DiBcom's DiB7000M and
3
* first generation DiB7000P-demodulator-family.
4
*
5
* Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
6
*
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License as
9
* published by the Free Software Foundation, version 2.
10
*/
11
#include <linux/kernel.h>
12
#include <linux/slab.h>
13
#include <linux/i2c.h>
14
15
#include "dvb_frontend.h"
16
17
#include "dib7000m.h"
18
19
static int debug;
20
module_param(debug, int, 0644);
21
MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
22
23
#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M: "); printk(args); printk("\n"); } } while (0)
24
25
struct dib7000m_state {
26
struct dvb_frontend demod;
27
struct dib7000m_config cfg;
28
29
u8 i2c_addr;
30
struct i2c_adapter *i2c_adap;
31
32
struct dibx000_i2c_master i2c_master;
33
34
/* offset is 1 in case of the 7000MC */
35
u8 reg_offs;
36
37
u16 wbd_ref;
38
39
u8 current_band;
40
fe_bandwidth_t current_bandwidth;
41
struct dibx000_agc_config *current_agc;
42
u32 timf;
43
u32 timf_default;
44
u32 internal_clk;
45
46
u8 div_force_off : 1;
47
u8 div_state : 1;
48
u16 div_sync_wait;
49
50
u16 revision;
51
52
u8 agc_state;
53
54
/* for the I2C transfer */
55
struct i2c_msg msg[2];
56
u8 i2c_write_buffer[4];
57
u8 i2c_read_buffer[2];
58
};
59
60
enum dib7000m_power_mode {
61
DIB7000M_POWER_ALL = 0,
62
63
DIB7000M_POWER_NO,
64
DIB7000M_POWER_INTERF_ANALOG_AGC,
65
DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
66
DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD,
67
DIB7000M_POWER_INTERFACE_ONLY,
68
};
69
70
static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
71
{
72
state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
73
state->i2c_write_buffer[1] = reg & 0xff;
74
75
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
76
state->msg[0].addr = state->i2c_addr >> 1;
77
state->msg[0].flags = 0;
78
state->msg[0].buf = state->i2c_write_buffer;
79
state->msg[0].len = 2;
80
state->msg[1].addr = state->i2c_addr >> 1;
81
state->msg[1].flags = I2C_M_RD;
82
state->msg[1].buf = state->i2c_read_buffer;
83
state->msg[1].len = 2;
84
85
if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
86
dprintk("i2c read error on %d",reg);
87
88
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
89
}
90
91
static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
92
{
93
state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
94
state->i2c_write_buffer[1] = reg & 0xff;
95
state->i2c_write_buffer[2] = (val >> 8) & 0xff;
96
state->i2c_write_buffer[3] = val & 0xff;
97
98
memset(&state->msg[0], 0, sizeof(struct i2c_msg));
99
state->msg[0].addr = state->i2c_addr >> 1;
100
state->msg[0].flags = 0;
101
state->msg[0].buf = state->i2c_write_buffer;
102
state->msg[0].len = 4;
103
104
return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
105
}
106
static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
107
{
108
u16 l = 0, r, *n;
109
n = buf;
110
l = *n++;
111
while (l) {
112
r = *n++;
113
114
if (state->reg_offs && (r >= 112 && r <= 331)) // compensate for 7000MC
115
r++;
116
117
do {
118
dib7000m_write_word(state, r, *n++);
119
r++;
120
} while (--l);
121
l = *n++;
122
}
123
}
124
125
static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
126
{
127
int ret = 0;
128
u16 outreg, fifo_threshold, smo_mode,
129
sram = 0x0005; /* by default SRAM output is disabled */
130
131
outreg = 0;
132
fifo_threshold = 1792;
133
smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1);
134
135
dprintk( "setting output mode for demod %p to %d", &state->demod, mode);
136
137
switch (mode) {
138
case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
139
outreg = (1 << 10); /* 0x0400 */
140
break;
141
case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
142
outreg = (1 << 10) | (1 << 6); /* 0x0440 */
143
break;
144
case OUTMODE_MPEG2_SERIAL: // STBs with serial input
145
outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
146
break;
147
case OUTMODE_DIVERSITY:
148
if (state->cfg.hostbus_diversity)
149
outreg = (1 << 10) | (4 << 6); /* 0x0500 */
150
else
151
sram |= 0x0c00;
152
break;
153
case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
154
smo_mode |= (3 << 1);
155
fifo_threshold = 512;
156
outreg = (1 << 10) | (5 << 6);
157
break;
158
case OUTMODE_HIGH_Z: // disable
159
outreg = 0;
160
break;
161
default:
162
dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
163
break;
164
}
165
166
if (state->cfg.output_mpeg2_in_188_bytes)
167
smo_mode |= (1 << 5) ;
168
169
ret |= dib7000m_write_word(state, 294 + state->reg_offs, smo_mode);
170
ret |= dib7000m_write_word(state, 295 + state->reg_offs, fifo_threshold); /* synchronous fread */
171
ret |= dib7000m_write_word(state, 1795, outreg);
172
ret |= dib7000m_write_word(state, 1805, sram);
173
174
if (state->revision == 0x4003) {
175
u16 clk_cfg1 = dib7000m_read_word(state, 909) & 0xfffd;
176
if (mode == OUTMODE_DIVERSITY)
177
clk_cfg1 |= (1 << 1); // P_O_CLK_en
178
dib7000m_write_word(state, 909, clk_cfg1);
179
}
180
return ret;
181
}
182
183
static void dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode)
184
{
185
/* by default everything is going to be powered off */
186
u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff;
187
u8 offset = 0;
188
189
/* now, depending on the requested mode, we power on */
190
switch (mode) {
191
/* power up everything in the demod */
192
case DIB7000M_POWER_ALL:
193
reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000;
194
break;
195
196
/* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
197
case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */
198
reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
199
break;
200
201
case DIB7000M_POWER_INTERF_ANALOG_AGC:
202
reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
203
reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
204
reg_906 &= ~((1 << 0));
205
break;
206
207
case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
208
reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000;
209
break;
210
211
case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD:
212
reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000;
213
break;
214
case DIB7000M_POWER_NO:
215
break;
216
}
217
218
/* always power down unused parts */
219
if (!state->cfg.mobile_mode)
220
reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
221
222
/* P_sdio_select_clk = 0 on MC and after*/
223
if (state->revision != 0x4000)
224
reg_906 <<= 1;
225
226
if (state->revision == 0x4003)
227
offset = 1;
228
229
dib7000m_write_word(state, 903 + offset, reg_903);
230
dib7000m_write_word(state, 904 + offset, reg_904);
231
dib7000m_write_word(state, 905 + offset, reg_905);
232
dib7000m_write_word(state, 906 + offset, reg_906);
233
}
234
235
static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no)
236
{
237
int ret = 0;
238
u16 reg_913 = dib7000m_read_word(state, 913),
239
reg_914 = dib7000m_read_word(state, 914);
240
241
switch (no) {
242
case DIBX000_SLOW_ADC_ON:
243
reg_914 |= (1 << 1) | (1 << 0);
244
ret |= dib7000m_write_word(state, 914, reg_914);
245
reg_914 &= ~(1 << 1);
246
break;
247
248
case DIBX000_SLOW_ADC_OFF:
249
reg_914 |= (1 << 1) | (1 << 0);
250
break;
251
252
case DIBX000_ADC_ON:
253
if (state->revision == 0x4000) { // workaround for PA/MA
254
// power-up ADC
255
dib7000m_write_word(state, 913, 0);
256
dib7000m_write_word(state, 914, reg_914 & 0x3);
257
// power-down bandgag
258
dib7000m_write_word(state, 913, (1 << 15));
259
dib7000m_write_word(state, 914, reg_914 & 0x3);
260
}
261
262
reg_913 &= 0x0fff;
263
reg_914 &= 0x0003;
264
break;
265
266
case DIBX000_ADC_OFF: // leave the VBG voltage on
267
reg_913 |= (1 << 14) | (1 << 13) | (1 << 12);
268
reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
269
break;
270
271
case DIBX000_VBG_ENABLE:
272
reg_913 &= ~(1 << 15);
273
break;
274
275
case DIBX000_VBG_DISABLE:
276
reg_913 |= (1 << 15);
277
break;
278
279
default:
280
break;
281
}
282
283
// dprintk( "913: %x, 914: %x", reg_913, reg_914);
284
ret |= dib7000m_write_word(state, 913, reg_913);
285
ret |= dib7000m_write_word(state, 914, reg_914);
286
287
return ret;
288
}
289
290
static int dib7000m_set_bandwidth(struct dib7000m_state *state, u32 bw)
291
{
292
u32 timf;
293
294
// store the current bandwidth for later use
295
state->current_bandwidth = bw;
296
297
if (state->timf == 0) {
298
dprintk( "using default timf");
299
timf = state->timf_default;
300
} else {
301
dprintk( "using updated timf");
302
timf = state->timf;
303
}
304
305
timf = timf * (bw / 50) / 160;
306
307
dib7000m_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
308
dib7000m_write_word(state, 24, (u16) ((timf ) & 0xffff));
309
310
return 0;
311
}
312
313
static int dib7000m_set_diversity_in(struct dvb_frontend *demod, int onoff)
314
{
315
struct dib7000m_state *state = demod->demodulator_priv;
316
317
if (state->div_force_off) {
318
dprintk( "diversity combination deactivated - forced by COFDM parameters");
319
onoff = 0;
320
}
321
state->div_state = (u8)onoff;
322
323
if (onoff) {
324
dib7000m_write_word(state, 263 + state->reg_offs, 6);
325
dib7000m_write_word(state, 264 + state->reg_offs, 6);
326
dib7000m_write_word(state, 266 + state->reg_offs, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
327
} else {
328
dib7000m_write_word(state, 263 + state->reg_offs, 1);
329
dib7000m_write_word(state, 264 + state->reg_offs, 0);
330
dib7000m_write_word(state, 266 + state->reg_offs, 0);
331
}
332
333
return 0;
334
}
335
336
static int dib7000m_sad_calib(struct dib7000m_state *state)
337
{
338
339
/* internal */
340
// dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
341
dib7000m_write_word(state, 929, (0 << 1) | (0 << 0));
342
dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096
343
344
/* do the calibration */
345
dib7000m_write_word(state, 929, (1 << 0));
346
dib7000m_write_word(state, 929, (0 << 0));
347
348
msleep(1);
349
350
return 0;
351
}
352
353
static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw)
354
{
355
dib7000m_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
356
dib7000m_write_word(state, 19, (u16) ( (bw->internal*1000) & 0xffff));
357
dib7000m_write_word(state, 21, (u16) ( (bw->ifreq >> 16) & 0xffff));
358
dib7000m_write_word(state, 22, (u16) ( bw->ifreq & 0xffff));
359
360
dib7000m_write_word(state, 928, bw->sad_cfg);
361
}
362
363
static void dib7000m_reset_pll(struct dib7000m_state *state)
364
{
365
const struct dibx000_bandwidth_config *bw = state->cfg.bw;
366
u16 reg_907,reg_910;
367
368
/* default */
369
reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) |
370
(bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) |
371
(bw->enable_refdiv << 1) | (0 << 0);
372
reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset;
373
374
// for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value)
375
// this is only working only for 30 MHz crystals
376
if (!state->cfg.quartz_direct) {
377
reg_910 |= (1 << 5); // forcing the predivider to 1
378
379
// if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2)
380
if(state->cfg.input_clk_is_div_2)
381
reg_907 |= (16 << 9);
382
else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary
383
reg_907 |= (8 << 9);
384
} else {
385
reg_907 |= (bw->pll_ratio & 0x3f) << 9;
386
reg_910 |= (bw->pll_prediv << 5);
387
}
388
389
dib7000m_write_word(state, 910, reg_910); // pll cfg
390
dib7000m_write_word(state, 907, reg_907); // clk cfg0
391
dib7000m_write_word(state, 908, 0x0006); // clk_cfg1
392
393
dib7000m_reset_pll_common(state, bw);
394
}
395
396
static void dib7000mc_reset_pll(struct dib7000m_state *state)
397
{
398
const struct dibx000_bandwidth_config *bw = state->cfg.bw;
399
u16 clk_cfg1;
400
401
// clk_cfg0
402
dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0));
403
404
// clk_cfg1
405
//dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) |
406
clk_cfg1 = (0 << 14) | (3 << 12) |(0 << 11) |
407
(bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) |
408
(1 << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0);
409
dib7000m_write_word(state, 908, clk_cfg1);
410
clk_cfg1 = (clk_cfg1 & 0xfff7) | (bw->pll_bypass << 3);
411
dib7000m_write_word(state, 908, clk_cfg1);
412
413
// smpl_cfg
414
dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7));
415
416
dib7000m_reset_pll_common(state, bw);
417
}
418
419
static int dib7000m_reset_gpio(struct dib7000m_state *st)
420
{
421
/* reset the GPIOs */
422
dib7000m_write_word(st, 773, st->cfg.gpio_dir);
423
dib7000m_write_word(st, 774, st->cfg.gpio_val);
424
425
/* TODO 782 is P_gpio_od */
426
427
dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos);
428
429
dib7000m_write_word(st, 780, st->cfg.pwm_freq_div);
430
return 0;
431
}
432
433
static u16 dib7000m_defaults_common[] =
434
435
{
436
// auto search configuration
437
3, 2,
438
0x0004,
439
0x1000,
440
0x0814,
441
442
12, 6,
443
0x001b,
444
0x7740,
445
0x005b,
446
0x8d80,
447
0x01c9,
448
0xc380,
449
0x0000,
450
0x0080,
451
0x0000,
452
0x0090,
453
0x0001,
454
0xd4c0,
455
456
1, 26,
457
0x6680, // P_corm_thres Lock algorithms configuration
458
459
1, 170,
460
0x0410, // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on
461
462
8, 173,
463
0,
464
0,
465
0,
466
0,
467
0,
468
0,
469
0,
470
0,
471
472
1, 182,
473
8192, // P_fft_nb_to_cut
474
475
2, 195,
476
0x0ccd, // P_pha3_thres
477
0, // P_cti_use_cpe, P_cti_use_prog
478
479
1, 205,
480
0x200f, // P_cspu_regul, P_cspu_win_cut
481
482
5, 214,
483
0x023d, // P_adp_regul_cnt
484
0x00a4, // P_adp_noise_cnt
485
0x00a4, // P_adp_regul_ext
486
0x7ff0, // P_adp_noise_ext
487
0x3ccc, // P_adp_fil
488
489
1, 226,
490
0, // P_2d_byp_ti_num
491
492
1, 255,
493
0x800, // P_equal_thres_wgn
494
495
1, 263,
496
0x0001,
497
498
1, 281,
499
0x0010, // P_fec_*
500
501
1, 294,
502
0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
503
504
0
505
};
506
507
static u16 dib7000m_defaults[] =
508
509
{
510
/* set ADC level to -16 */
511
11, 76,
512
(1 << 13) - 825 - 117,
513
(1 << 13) - 837 - 117,
514
(1 << 13) - 811 - 117,
515
(1 << 13) - 766 - 117,
516
(1 << 13) - 737 - 117,
517
(1 << 13) - 693 - 117,
518
(1 << 13) - 648 - 117,
519
(1 << 13) - 619 - 117,
520
(1 << 13) - 575 - 117,
521
(1 << 13) - 531 - 117,
522
(1 << 13) - 501 - 117,
523
524
// Tuner IO bank: max drive (14mA)
525
1, 912,
526
0x2c8a,
527
528
1, 1817,
529
1,
530
531
0,
532
};
533
534
static int dib7000m_demod_reset(struct dib7000m_state *state)
535
{
536
dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
537
538
/* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
539
dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE);
540
541
/* restart all parts */
542
dib7000m_write_word(state, 898, 0xffff);
543
dib7000m_write_word(state, 899, 0xffff);
544
dib7000m_write_word(state, 900, 0xff0f);
545
dib7000m_write_word(state, 901, 0xfffc);
546
547
dib7000m_write_word(state, 898, 0);
548
dib7000m_write_word(state, 899, 0);
549
dib7000m_write_word(state, 900, 0);
550
dib7000m_write_word(state, 901, 0);
551
552
if (state->revision == 0x4000)
553
dib7000m_reset_pll(state);
554
else
555
dib7000mc_reset_pll(state);
556
557
if (dib7000m_reset_gpio(state) != 0)
558
dprintk( "GPIO reset was not successful.");
559
560
if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
561
dprintk( "OUTPUT_MODE could not be reset.");
562
563
/* unforce divstr regardless whether i2c enumeration was done or not */
564
dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) );
565
566
dib7000m_set_bandwidth(state, 8000);
567
568
dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON);
569
dib7000m_sad_calib(state);
570
dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
571
572
if (state->cfg.dvbt_mode)
573
dib7000m_write_word(state, 1796, 0x0); // select DVB-T output
574
575
if (state->cfg.mobile_mode)
576
dib7000m_write_word(state, 261 + state->reg_offs, 2);
577
else
578
dib7000m_write_word(state, 224 + state->reg_offs, 1);
579
580
// P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
581
if(state->cfg.tuner_is_baseband)
582
dib7000m_write_word(state, 36, 0x0755);
583
else
584
dib7000m_write_word(state, 36, 0x1f55);
585
586
// P_divclksel=3 P_divbitsel=1
587
if (state->revision == 0x4000)
588
dib7000m_write_word(state, 909, (3 << 10) | (1 << 6));
589
else
590
dib7000m_write_word(state, 909, (3 << 4) | 1);
591
592
dib7000m_write_tab(state, dib7000m_defaults_common);
593
dib7000m_write_tab(state, dib7000m_defaults);
594
595
dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY);
596
597
state->internal_clk = state->cfg.bw->internal;
598
599
return 0;
600
}
601
602
static void dib7000m_restart_agc(struct dib7000m_state *state)
603
{
604
// P_restart_iqc & P_restart_agc
605
dib7000m_write_word(state, 898, 0x0c00);
606
dib7000m_write_word(state, 898, 0x0000);
607
}
608
609
static int dib7000m_agc_soft_split(struct dib7000m_state *state)
610
{
611
u16 agc,split_offset;
612
613
if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
614
return 0;
615
616
// n_agc_global
617
agc = dib7000m_read_word(state, 390);
618
619
if (agc > state->current_agc->split.min_thres)
620
split_offset = state->current_agc->split.min;
621
else if (agc < state->current_agc->split.max_thres)
622
split_offset = state->current_agc->split.max;
623
else
624
split_offset = state->current_agc->split.max *
625
(agc - state->current_agc->split.min_thres) /
626
(state->current_agc->split.max_thres - state->current_agc->split.min_thres);
627
628
dprintk( "AGC split_offset: %d",split_offset);
629
630
// P_agc_force_split and P_agc_split_offset
631
return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset);
632
}
633
634
static int dib7000m_update_lna(struct dib7000m_state *state)
635
{
636
u16 dyn_gain;
637
638
if (state->cfg.update_lna) {
639
// read dyn_gain here (because it is demod-dependent and not fe)
640
dyn_gain = dib7000m_read_word(state, 390);
641
642
if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
643
dib7000m_restart_agc(state);
644
return 1;
645
}
646
}
647
return 0;
648
}
649
650
static int dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
651
{
652
struct dibx000_agc_config *agc = NULL;
653
int i;
654
if (state->current_band == band && state->current_agc != NULL)
655
return 0;
656
state->current_band = band;
657
658
for (i = 0; i < state->cfg.agc_config_count; i++)
659
if (state->cfg.agc[i].band_caps & band) {
660
agc = &state->cfg.agc[i];
661
break;
662
}
663
664
if (agc == NULL) {
665
dprintk( "no valid AGC configuration found for band 0x%02x",band);
666
return -EINVAL;
667
}
668
669
state->current_agc = agc;
670
671
/* AGC */
672
dib7000m_write_word(state, 72 , agc->setup);
673
dib7000m_write_word(state, 73 , agc->inv_gain);
674
dib7000m_write_word(state, 74 , agc->time_stabiliz);
675
dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock);
676
677
// Demod AGC loop configuration
678
dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp);
679
dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp);
680
681
dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
682
state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
683
684
/* AGC continued */
685
if (state->wbd_ref != 0)
686
dib7000m_write_word(state, 102, state->wbd_ref);
687
else // use default
688
dib7000m_write_word(state, 102, agc->wbd_ref);
689
690
dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) );
691
dib7000m_write_word(state, 104, agc->agc1_max);
692
dib7000m_write_word(state, 105, agc->agc1_min);
693
dib7000m_write_word(state, 106, agc->agc2_max);
694
dib7000m_write_word(state, 107, agc->agc2_min);
695
dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 );
696
dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
697
dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
698
dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
699
700
if (state->revision > 0x4000) { // settings for the MC
701
dib7000m_write_word(state, 71, agc->agc1_pt3);
702
// dprintk( "929: %x %d %d",
703
// (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel);
704
dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
705
} else {
706
// wrong default values
707
u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 };
708
for (i = 0; i < 9; i++)
709
dib7000m_write_word(state, 88 + i, b[i]);
710
}
711
return 0;
712
}
713
714
static void dib7000m_update_timf(struct dib7000m_state *state)
715
{
716
u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437);
717
state->timf = timf * 160 / (state->current_bandwidth / 50);
718
dib7000m_write_word(state, 23, (u16) (timf >> 16));
719
dib7000m_write_word(state, 24, (u16) (timf & 0xffff));
720
dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->timf_default);
721
}
722
723
static int dib7000m_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
724
{
725
struct dib7000m_state *state = demod->demodulator_priv;
726
u16 cfg_72 = dib7000m_read_word(state, 72);
727
int ret = -1;
728
u8 *agc_state = &state->agc_state;
729
u8 agc_split;
730
731
switch (state->agc_state) {
732
case 0:
733
// set power-up level: interf+analog+AGC
734
dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC);
735
dib7000m_set_adc_state(state, DIBX000_ADC_ON);
736
737
if (dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
738
return -1;
739
740
ret = 7; /* ADC power up */
741
(*agc_state)++;
742
break;
743
744
case 1:
745
/* AGC initialization */
746
if (state->cfg.agc_control)
747
state->cfg.agc_control(&state->demod, 1);
748
749
dib7000m_write_word(state, 75, 32768);
750
if (!state->current_agc->perform_agc_softsplit) {
751
/* we are using the wbd - so slow AGC startup */
752
dib7000m_write_word(state, 103, 1 << 8); /* force 0 split on WBD and restart AGC */
753
(*agc_state)++;
754
ret = 5;
755
} else {
756
/* default AGC startup */
757
(*agc_state) = 4;
758
/* wait AGC rough lock time */
759
ret = 7;
760
}
761
762
dib7000m_restart_agc(state);
763
break;
764
765
case 2: /* fast split search path after 5sec */
766
dib7000m_write_word(state, 72, cfg_72 | (1 << 4)); /* freeze AGC loop */
767
dib7000m_write_word(state, 103, 2 << 9); /* fast split search 0.25kHz */
768
(*agc_state)++;
769
ret = 14;
770
break;
771
772
case 3: /* split search ended */
773
agc_split = (u8)dib7000m_read_word(state, 392); /* store the split value for the next time */
774
dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */
775
776
dib7000m_write_word(state, 72, cfg_72 & ~(1 << 4)); /* std AGC loop */
777
dib7000m_write_word(state, 103, (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
778
779
dib7000m_restart_agc(state);
780
781
dprintk( "SPLIT %p: %hd", demod, agc_split);
782
783
(*agc_state)++;
784
ret = 5;
785
break;
786
787
case 4: /* LNA startup */
788
/* wait AGC accurate lock time */
789
ret = 7;
790
791
if (dib7000m_update_lna(state))
792
// wait only AGC rough lock time
793
ret = 5;
794
else
795
(*agc_state)++;
796
break;
797
798
case 5:
799
dib7000m_agc_soft_split(state);
800
801
if (state->cfg.agc_control)
802
state->cfg.agc_control(&state->demod, 0);
803
804
(*agc_state)++;
805
break;
806
807
default:
808
break;
809
}
810
return ret;
811
}
812
813
static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_frontend_parameters *ch, u8 seq)
814
{
815
u16 value, est[4];
816
817
dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
818
819
/* nfft, guard, qam, alpha */
820
value = 0;
821
switch (ch->u.ofdm.transmission_mode) {
822
case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
823
case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
824
default:
825
case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
826
}
827
switch (ch->u.ofdm.guard_interval) {
828
case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
829
case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
830
case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
831
default:
832
case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
833
}
834
switch (ch->u.ofdm.constellation) {
835
case QPSK: value |= (0 << 3); break;
836
case QAM_16: value |= (1 << 3); break;
837
default:
838
case QAM_64: value |= (2 << 3); break;
839
}
840
switch (HIERARCHY_1) {
841
case HIERARCHY_2: value |= 2; break;
842
case HIERARCHY_4: value |= 4; break;
843
default:
844
case HIERARCHY_1: value |= 1; break;
845
}
846
dib7000m_write_word(state, 0, value);
847
dib7000m_write_word(state, 5, (seq << 4));
848
849
/* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
850
value = 0;
851
if (1 != 0)
852
value |= (1 << 6);
853
if (ch->u.ofdm.hierarchy_information == 1)
854
value |= (1 << 4);
855
if (1 == 1)
856
value |= 1;
857
switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
858
case FEC_2_3: value |= (2 << 1); break;
859
case FEC_3_4: value |= (3 << 1); break;
860
case FEC_5_6: value |= (5 << 1); break;
861
case FEC_7_8: value |= (7 << 1); break;
862
default:
863
case FEC_1_2: value |= (1 << 1); break;
864
}
865
dib7000m_write_word(state, 267 + state->reg_offs, value);
866
867
/* offset loop parameters */
868
869
/* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */
870
dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80);
871
872
/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
873
dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3));
874
875
/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */
876
dib7000m_write_word(state, 32, (0 << 4) | 0x3);
877
878
/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */
879
dib7000m_write_word(state, 33, (0 << 4) | 0x5);
880
881
/* P_dvsy_sync_wait */
882
switch (ch->u.ofdm.transmission_mode) {
883
case TRANSMISSION_MODE_8K: value = 256; break;
884
case TRANSMISSION_MODE_4K: value = 128; break;
885
case TRANSMISSION_MODE_2K:
886
default: value = 64; break;
887
}
888
switch (ch->u.ofdm.guard_interval) {
889
case GUARD_INTERVAL_1_16: value *= 2; break;
890
case GUARD_INTERVAL_1_8: value *= 4; break;
891
case GUARD_INTERVAL_1_4: value *= 8; break;
892
default:
893
case GUARD_INTERVAL_1_32: value *= 1; break;
894
}
895
state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO
896
897
/* deactive the possibility of diversity reception if extended interleave - not for 7000MC */
898
/* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
899
if (1 == 1 || state->revision > 0x4000)
900
state->div_force_off = 0;
901
else
902
state->div_force_off = 1;
903
dib7000m_set_diversity_in(&state->demod, state->div_state);
904
905
/* channel estimation fine configuration */
906
switch (ch->u.ofdm.constellation) {
907
case QAM_64:
908
est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
909
est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
910
est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
911
est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
912
break;
913
case QAM_16:
914
est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
915
est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
916
est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
917
est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */
918
break;
919
default:
920
est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */
921
est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */
922
est[2] = 0x0333; /* P_adp_regul_ext 0.1 */
923
est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
924
break;
925
}
926
for (value = 0; value < 4; value++)
927
dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]);
928
929
// set power-up level: autosearch
930
dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);
931
}
932
933
static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
934
{
935
struct dib7000m_state *state = demod->demodulator_priv;
936
struct dvb_frontend_parameters schan;
937
int ret = 0;
938
u32 value, factor;
939
940
schan = *ch;
941
942
schan.u.ofdm.constellation = QAM_64;
943
schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
944
schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
945
schan.u.ofdm.code_rate_HP = FEC_2_3;
946
schan.u.ofdm.code_rate_LP = FEC_3_4;
947
schan.u.ofdm.hierarchy_information = 0;
948
949
dib7000m_set_channel(state, &schan, 7);
950
951
factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
952
if (factor >= 5000)
953
factor = 1;
954
else
955
factor = 6;
956
957
// always use the setting for 8MHz here lock_time for 7,6 MHz are longer
958
value = 30 * state->internal_clk * factor;
959
ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time
960
ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time
961
value = 100 * state->internal_clk * factor;
962
ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time
963
ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time
964
value = 500 * state->internal_clk * factor;
965
ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
966
ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time
967
968
// start search
969
value = dib7000m_read_word(state, 0);
970
ret |= dib7000m_write_word(state, 0, (u16) (value | (1 << 9)));
971
972
/* clear n_irq_pending */
973
if (state->revision == 0x4000)
974
dib7000m_write_word(state, 1793, 0);
975
else
976
dib7000m_read_word(state, 537);
977
978
ret |= dib7000m_write_word(state, 0, (u16) value);
979
980
return ret;
981
}
982
983
static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg)
984
{
985
u16 irq_pending = dib7000m_read_word(state, reg);
986
987
if (irq_pending & 0x1) { // failed
988
dprintk( "autosearch failed");
989
return 1;
990
}
991
992
if (irq_pending & 0x2) { // succeeded
993
dprintk( "autosearch succeeded");
994
return 2;
995
}
996
return 0; // still pending
997
}
998
999
static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod)
1000
{
1001
struct dib7000m_state *state = demod->demodulator_priv;
1002
if (state->revision == 0x4000)
1003
return dib7000m_autosearch_irq(state, 1793);
1004
else
1005
return dib7000m_autosearch_irq(state, 537);
1006
}
1007
1008
static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
1009
{
1010
struct dib7000m_state *state = demod->demodulator_priv;
1011
int ret = 0;
1012
u16 value;
1013
1014
// we are already tuned - just resuming from suspend
1015
if (ch != NULL)
1016
dib7000m_set_channel(state, ch, 0);
1017
else
1018
return -EINVAL;
1019
1020
// restart demod
1021
ret |= dib7000m_write_word(state, 898, 0x4000);
1022
ret |= dib7000m_write_word(state, 898, 0x0000);
1023
msleep(45);
1024
1025
dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD);
1026
/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
1027
ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
1028
1029
// never achieved a lock before - wait for timfreq to update
1030
if (state->timf == 0)
1031
msleep(200);
1032
1033
//dump_reg(state);
1034
/* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
1035
value = (6 << 8) | 0x80;
1036
switch (ch->u.ofdm.transmission_mode) {
1037
case TRANSMISSION_MODE_2K: value |= (7 << 12); break;
1038
case TRANSMISSION_MODE_4K: value |= (8 << 12); break;
1039
default:
1040
case TRANSMISSION_MODE_8K: value |= (9 << 12); break;
1041
}
1042
ret |= dib7000m_write_word(state, 26, value);
1043
1044
/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
1045
value = (0 << 4);
1046
switch (ch->u.ofdm.transmission_mode) {
1047
case TRANSMISSION_MODE_2K: value |= 0x6; break;
1048
case TRANSMISSION_MODE_4K: value |= 0x7; break;
1049
default:
1050
case TRANSMISSION_MODE_8K: value |= 0x8; break;
1051
}
1052
ret |= dib7000m_write_word(state, 32, value);
1053
1054
/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
1055
value = (0 << 4);
1056
switch (ch->u.ofdm.transmission_mode) {
1057
case TRANSMISSION_MODE_2K: value |= 0x6; break;
1058
case TRANSMISSION_MODE_4K: value |= 0x7; break;
1059
default:
1060
case TRANSMISSION_MODE_8K: value |= 0x8; break;
1061
}
1062
ret |= dib7000m_write_word(state, 33, value);
1063
1064
// we achieved a lock - it's time to update the timf freq
1065
if ((dib7000m_read_word(state, 535) >> 6) & 0x1)
1066
dib7000m_update_timf(state);
1067
1068
dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
1069
return ret;
1070
}
1071
1072
static int dib7000m_wakeup(struct dvb_frontend *demod)
1073
{
1074
struct dib7000m_state *state = demod->demodulator_priv;
1075
1076
dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
1077
1078
if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
1079
dprintk( "could not start Slow ADC");
1080
1081
return 0;
1082
}
1083
1084
static int dib7000m_sleep(struct dvb_frontend *demod)
1085
{
1086
struct dib7000m_state *st = demod->demodulator_priv;
1087
dib7000m_set_output_mode(st, OUTMODE_HIGH_Z);
1088
dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY);
1089
return dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) |
1090
dib7000m_set_adc_state(st, DIBX000_ADC_OFF);
1091
}
1092
1093
static int dib7000m_identify(struct dib7000m_state *state)
1094
{
1095
u16 value;
1096
1097
if ((value = dib7000m_read_word(state, 896)) != 0x01b3) {
1098
dprintk( "wrong Vendor ID (0x%x)",value);
1099
return -EREMOTEIO;
1100
}
1101
1102
state->revision = dib7000m_read_word(state, 897);
1103
if (state->revision != 0x4000 &&
1104
state->revision != 0x4001 &&
1105
state->revision != 0x4002 &&
1106
state->revision != 0x4003) {
1107
dprintk( "wrong Device ID (0x%x)",value);
1108
return -EREMOTEIO;
1109
}
1110
1111
/* protect this driver to be used with 7000PC */
1112
if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) {
1113
dprintk( "this driver does not work with DiB7000PC");
1114
return -EREMOTEIO;
1115
}
1116
1117
switch (state->revision) {
1118
case 0x4000: dprintk( "found DiB7000MA/PA/MB/PB"); break;
1119
case 0x4001: state->reg_offs = 1; dprintk( "found DiB7000HC"); break;
1120
case 0x4002: state->reg_offs = 1; dprintk( "found DiB7000MC"); break;
1121
case 0x4003: state->reg_offs = 1; dprintk( "found DiB9000"); break;
1122
}
1123
1124
return 0;
1125
}
1126
1127
1128
static int dib7000m_get_frontend(struct dvb_frontend* fe,
1129
struct dvb_frontend_parameters *fep)
1130
{
1131
struct dib7000m_state *state = fe->demodulator_priv;
1132
u16 tps = dib7000m_read_word(state,480);
1133
1134
fep->inversion = INVERSION_AUTO;
1135
1136
fep->u.ofdm.bandwidth = state->current_bandwidth;
1137
1138
switch ((tps >> 8) & 0x3) {
1139
case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
1140
case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
1141
/* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
1142
}
1143
1144
switch (tps & 0x3) {
1145
case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
1146
case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
1147
case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
1148
case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
1149
}
1150
1151
switch ((tps >> 14) & 0x3) {
1152
case 0: fep->u.ofdm.constellation = QPSK; break;
1153
case 1: fep->u.ofdm.constellation = QAM_16; break;
1154
case 2:
1155
default: fep->u.ofdm.constellation = QAM_64; break;
1156
}
1157
1158
/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
1159
/* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
1160
1161
fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
1162
switch ((tps >> 5) & 0x7) {
1163
case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
1164
case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
1165
case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
1166
case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
1167
case 7:
1168
default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
1169
1170
}
1171
1172
switch ((tps >> 2) & 0x7) {
1173
case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
1174
case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
1175
case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
1176
case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
1177
case 7:
1178
default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
1179
}
1180
1181
/* native interleaver: (dib7000m_read_word(state, 481) >> 5) & 0x1 */
1182
1183
return 0;
1184
}
1185
1186
static int dib7000m_set_frontend(struct dvb_frontend* fe,
1187
struct dvb_frontend_parameters *fep)
1188
{
1189
struct dib7000m_state *state = fe->demodulator_priv;
1190
int time, ret;
1191
1192
dib7000m_set_output_mode(state, OUTMODE_HIGH_Z);
1193
1194
state->current_bandwidth = fep->u.ofdm.bandwidth;
1195
dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
1196
1197
if (fe->ops.tuner_ops.set_params)
1198
fe->ops.tuner_ops.set_params(fe, fep);
1199
1200
/* start up the AGC */
1201
state->agc_state = 0;
1202
do {
1203
time = dib7000m_agc_startup(fe, fep);
1204
if (time != -1)
1205
msleep(time);
1206
} while (time != -1);
1207
1208
if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
1209
fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
1210
fep->u.ofdm.constellation == QAM_AUTO ||
1211
fep->u.ofdm.code_rate_HP == FEC_AUTO) {
1212
int i = 800, found;
1213
1214
dib7000m_autosearch_start(fe, fep);
1215
do {
1216
msleep(1);
1217
found = dib7000m_autosearch_is_irq(fe);
1218
} while (found == 0 && i--);
1219
1220
dprintk("autosearch returns: %d",found);
1221
if (found == 0 || found == 1)
1222
return 0; // no channel found
1223
1224
dib7000m_get_frontend(fe, fep);
1225
}
1226
1227
ret = dib7000m_tune(fe, fep);
1228
1229
/* make this a config parameter */
1230
dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
1231
return ret;
1232
}
1233
1234
static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)
1235
{
1236
struct dib7000m_state *state = fe->demodulator_priv;
1237
u16 lock = dib7000m_read_word(state, 535);
1238
1239
*stat = 0;
1240
1241
if (lock & 0x8000)
1242
*stat |= FE_HAS_SIGNAL;
1243
if (lock & 0x3000)
1244
*stat |= FE_HAS_CARRIER;
1245
if (lock & 0x0100)
1246
*stat |= FE_HAS_VITERBI;
1247
if (lock & 0x0010)
1248
*stat |= FE_HAS_SYNC;
1249
if (lock & 0x0008)
1250
*stat |= FE_HAS_LOCK;
1251
1252
return 0;
1253
}
1254
1255
static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber)
1256
{
1257
struct dib7000m_state *state = fe->demodulator_priv;
1258
*ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527);
1259
return 0;
1260
}
1261
1262
static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
1263
{
1264
struct dib7000m_state *state = fe->demodulator_priv;
1265
*unc = dib7000m_read_word(state, 534);
1266
return 0;
1267
}
1268
1269
static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
1270
{
1271
struct dib7000m_state *state = fe->demodulator_priv;
1272
u16 val = dib7000m_read_word(state, 390);
1273
*strength = 65535 - val;
1274
return 0;
1275
}
1276
1277
static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr)
1278
{
1279
*snr = 0x0000;
1280
return 0;
1281
}
1282
1283
static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
1284
{
1285
tune->min_delay_ms = 1000;
1286
return 0;
1287
}
1288
1289
static void dib7000m_release(struct dvb_frontend *demod)
1290
{
1291
struct dib7000m_state *st = demod->demodulator_priv;
1292
dibx000_exit_i2c_master(&st->i2c_master);
1293
kfree(st);
1294
}
1295
1296
struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
1297
{
1298
struct dib7000m_state *st = demod->demodulator_priv;
1299
return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
1300
}
1301
EXPORT_SYMBOL(dib7000m_get_i2c_master);
1302
1303
int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
1304
{
1305
struct dib7000m_state *state = fe->demodulator_priv;
1306
u16 val = dib7000m_read_word(state, 294 + state->reg_offs) & 0xffef;
1307
val |= (onoff & 0x1) << 4;
1308
dprintk("PID filter enabled %d", onoff);
1309
return dib7000m_write_word(state, 294 + state->reg_offs, val);
1310
}
1311
EXPORT_SYMBOL(dib7000m_pid_filter_ctrl);
1312
1313
int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
1314
{
1315
struct dib7000m_state *state = fe->demodulator_priv;
1316
dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
1317
return dib7000m_write_word(state, 300 + state->reg_offs + id,
1318
onoff ? (1 << 13) | pid : 0);
1319
}
1320
EXPORT_SYMBOL(dib7000m_pid_filter);
1321
1322
#if 0
1323
/* used with some prototype boards */
1324
int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods,
1325
u8 default_addr, struct dib7000m_config cfg[])
1326
{
1327
struct dib7000m_state st = { .i2c_adap = i2c };
1328
int k = 0;
1329
u8 new_addr = 0;
1330
1331
for (k = no_of_demods-1; k >= 0; k--) {
1332
st.cfg = cfg[k];
1333
1334
/* designated i2c address */
1335
new_addr = (0x40 + k) << 1;
1336
st.i2c_addr = new_addr;
1337
if (dib7000m_identify(&st) != 0) {
1338
st.i2c_addr = default_addr;
1339
if (dib7000m_identify(&st) != 0) {
1340
dprintk("DiB7000M #%d: not identified", k);
1341
return -EIO;
1342
}
1343
}
1344
1345
/* start diversity to pull_down div_str - just for i2c-enumeration */
1346
dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY);
1347
1348
dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output
1349
1350
/* set new i2c address and force divstart */
1351
dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2);
1352
1353
dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
1354
}
1355
1356
for (k = 0; k < no_of_demods; k++) {
1357
st.cfg = cfg[k];
1358
st.i2c_addr = (0x40 + k) << 1;
1359
1360
// unforce divstr
1361
dib7000m_write_word(&st,1794, st.i2c_addr << 2);
1362
1363
/* deactivate div - it was just for i2c-enumeration */
1364
dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z);
1365
}
1366
1367
return 0;
1368
}
1369
EXPORT_SYMBOL(dib7000m_i2c_enumeration);
1370
#endif
1371
1372
static struct dvb_frontend_ops dib7000m_ops;
1373
struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg)
1374
{
1375
struct dvb_frontend *demod;
1376
struct dib7000m_state *st;
1377
st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL);
1378
if (st == NULL)
1379
return NULL;
1380
1381
memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config));
1382
st->i2c_adap = i2c_adap;
1383
st->i2c_addr = i2c_addr;
1384
1385
demod = &st->demod;
1386
demod->demodulator_priv = st;
1387
memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
1388
1389
st->timf_default = cfg->bw->timf;
1390
1391
if (dib7000m_identify(st) != 0)
1392
goto error;
1393
1394
if (st->revision == 0x4000)
1395
dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr);
1396
else
1397
dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr);
1398
1399
dib7000m_demod_reset(st);
1400
1401
return demod;
1402
1403
error:
1404
kfree(st);
1405
return NULL;
1406
}
1407
EXPORT_SYMBOL(dib7000m_attach);
1408
1409
static struct dvb_frontend_ops dib7000m_ops = {
1410
.info = {
1411
.name = "DiBcom 7000MA/MB/PA/PB/MC",
1412
.type = FE_OFDM,
1413
.frequency_min = 44250000,
1414
.frequency_max = 867250000,
1415
.frequency_stepsize = 62500,
1416
.caps = FE_CAN_INVERSION_AUTO |
1417
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1418
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1419
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
1420
FE_CAN_TRANSMISSION_MODE_AUTO |
1421
FE_CAN_GUARD_INTERVAL_AUTO |
1422
FE_CAN_RECOVER |
1423
FE_CAN_HIERARCHY_AUTO,
1424
},
1425
1426
.release = dib7000m_release,
1427
1428
.init = dib7000m_wakeup,
1429
.sleep = dib7000m_sleep,
1430
1431
.set_frontend = dib7000m_set_frontend,
1432
.get_tune_settings = dib7000m_fe_get_tune_settings,
1433
.get_frontend = dib7000m_get_frontend,
1434
1435
.read_status = dib7000m_read_status,
1436
.read_ber = dib7000m_read_ber,
1437
.read_signal_strength = dib7000m_read_signal_strength,
1438
.read_snr = dib7000m_read_snr,
1439
.read_ucblocks = dib7000m_read_unc_blocks,
1440
};
1441
1442
MODULE_AUTHOR("Patrick Boettcher <[email protected]>");
1443
MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator");
1444
MODULE_LICENSE("GPL");
1445
1446