Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/dvb/frontends/dib0090.c
15112 views
1
/*
2
* Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
3
*
4
* Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License as
8
* published by the Free Software Foundation; either version 2 of the
9
* License, or (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful, but
12
* WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
*
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
*
21
*
22
* This code is more or less generated from another driver, please
23
* excuse some codingstyle oddities.
24
*
25
*/
26
27
#include <linux/kernel.h>
28
#include <linux/slab.h>
29
#include <linux/i2c.h>
30
31
#include "dvb_frontend.h"
32
33
#include "dib0090.h"
34
#include "dibx000_common.h"
35
36
static int debug;
37
module_param(debug, int, 0644);
38
MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
39
40
#define dprintk(args...) do { \
41
if (debug) { \
42
printk(KERN_DEBUG "DiB0090: "); \
43
printk(args); \
44
printk("\n"); \
45
} \
46
} while (0)
47
48
#define CONFIG_SYS_DVBT
49
#define CONFIG_SYS_ISDBT
50
#define CONFIG_BAND_CBAND
51
#define CONFIG_BAND_VHF
52
#define CONFIG_BAND_UHF
53
#define CONFIG_DIB0090_USE_PWM_AGC
54
55
#define EN_LNA0 0x8000
56
#define EN_LNA1 0x4000
57
#define EN_LNA2 0x2000
58
#define EN_LNA3 0x1000
59
#define EN_MIX0 0x0800
60
#define EN_MIX1 0x0400
61
#define EN_MIX2 0x0200
62
#define EN_MIX3 0x0100
63
#define EN_IQADC 0x0040
64
#define EN_PLL 0x0020
65
#define EN_TX 0x0010
66
#define EN_BB 0x0008
67
#define EN_LO 0x0004
68
#define EN_BIAS 0x0001
69
70
#define EN_IQANA 0x0002
71
#define EN_DIGCLK 0x0080 /* not in the 0x24 reg, only in 0x1b */
72
#define EN_CRYSTAL 0x0002
73
74
#define EN_UHF 0x22E9
75
#define EN_VHF 0x44E9
76
#define EN_LBD 0x11E9
77
#define EN_SBD 0x44E9
78
#define EN_CAB 0x88E9
79
80
/* Calibration defines */
81
#define DC_CAL 0x1
82
#define WBD_CAL 0x2
83
#define TEMP_CAL 0x4
84
#define CAPTRIM_CAL 0x8
85
86
#define KROSUS_PLL_LOCKED 0x800
87
#define KROSUS 0x2
88
89
/* Use those defines to identify SOC version */
90
#define SOC 0x02
91
#define SOC_7090_P1G_11R1 0x82
92
#define SOC_7090_P1G_21R1 0x8a
93
#define SOC_8090_P1G_11R1 0x86
94
#define SOC_8090_P1G_21R1 0x8e
95
96
/* else use thos ones to check */
97
#define P1A_B 0x0
98
#define P1C 0x1
99
#define P1D_E_F 0x3
100
#define P1G 0x7
101
#define P1G_21R2 0xf
102
103
#define MP001 0x1 /* Single 9090/8096 */
104
#define MP005 0x4 /* Single Sband */
105
#define MP008 0x6 /* Dual diversity VHF-UHF-LBAND */
106
#define MP009 0x7 /* Dual diversity 29098 CBAND-UHF-LBAND-SBAND */
107
108
#define pgm_read_word(w) (*w)
109
110
struct dc_calibration;
111
112
struct dib0090_tuning {
113
u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
114
u8 switch_trim;
115
u8 lna_tune;
116
u16 lna_bias;
117
u16 v2i;
118
u16 mix;
119
u16 load;
120
u16 tuner_enable;
121
};
122
123
struct dib0090_pll {
124
u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
125
u8 vco_band;
126
u8 hfdiv_code;
127
u8 hfdiv;
128
u8 topresc;
129
};
130
131
struct dib0090_identity {
132
u8 version;
133
u8 product;
134
u8 p1g;
135
u8 in_soc;
136
};
137
138
struct dib0090_state {
139
struct i2c_adapter *i2c;
140
struct dvb_frontend *fe;
141
const struct dib0090_config *config;
142
143
u8 current_band;
144
enum frontend_tune_state tune_state;
145
u32 current_rf;
146
147
u16 wbd_offset;
148
s16 wbd_target; /* in dB */
149
150
s16 rf_gain_limit; /* take-over-point: where to split between bb and rf gain */
151
s16 current_gain; /* keeps the currently programmed gain */
152
u8 agc_step; /* new binary search */
153
154
u16 gain[2]; /* for channel monitoring */
155
156
const u16 *rf_ramp;
157
const u16 *bb_ramp;
158
159
/* for the software AGC ramps */
160
u16 bb_1_def;
161
u16 rf_lt_def;
162
u16 gain_reg[4];
163
164
/* for the captrim/dc-offset search */
165
s8 step;
166
s16 adc_diff;
167
s16 min_adc_diff;
168
169
s8 captrim;
170
s8 fcaptrim;
171
172
const struct dc_calibration *dc;
173
u16 bb6, bb7;
174
175
const struct dib0090_tuning *current_tune_table_index;
176
const struct dib0090_pll *current_pll_table_index;
177
178
u8 tuner_is_tuned;
179
u8 agc_freeze;
180
181
struct dib0090_identity identity;
182
183
u32 rf_request;
184
u8 current_standard;
185
186
u8 calibrate;
187
u32 rest;
188
u16 bias;
189
s16 temperature;
190
191
u8 wbd_calibration_gain;
192
const struct dib0090_wbd_slope *current_wbd_table;
193
u16 wbdmux;
194
195
/* for the I2C transfer */
196
struct i2c_msg msg[2];
197
u8 i2c_write_buffer[3];
198
u8 i2c_read_buffer[2];
199
};
200
201
struct dib0090_fw_state {
202
struct i2c_adapter *i2c;
203
struct dvb_frontend *fe;
204
struct dib0090_identity identity;
205
const struct dib0090_config *config;
206
207
/* for the I2C transfer */
208
struct i2c_msg msg;
209
u8 i2c_write_buffer[2];
210
u8 i2c_read_buffer[2];
211
};
212
213
static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
214
{
215
state->i2c_write_buffer[0] = reg;
216
217
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
218
state->msg[0].addr = state->config->i2c_address;
219
state->msg[0].flags = 0;
220
state->msg[0].buf = state->i2c_write_buffer;
221
state->msg[0].len = 1;
222
state->msg[1].addr = state->config->i2c_address;
223
state->msg[1].flags = I2C_M_RD;
224
state->msg[1].buf = state->i2c_read_buffer;
225
state->msg[1].len = 2;
226
227
if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
228
printk(KERN_WARNING "DiB0090 I2C read failed\n");
229
return 0;
230
}
231
232
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
233
}
234
235
static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
236
{
237
state->i2c_write_buffer[0] = reg & 0xff;
238
state->i2c_write_buffer[1] = val >> 8;
239
state->i2c_write_buffer[2] = val & 0xff;
240
241
memset(state->msg, 0, sizeof(struct i2c_msg));
242
state->msg[0].addr = state->config->i2c_address;
243
state->msg[0].flags = 0;
244
state->msg[0].buf = state->i2c_write_buffer;
245
state->msg[0].len = 3;
246
247
if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
248
printk(KERN_WARNING "DiB0090 I2C write failed\n");
249
return -EREMOTEIO;
250
}
251
return 0;
252
}
253
254
static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
255
{
256
state->i2c_write_buffer[0] = reg;
257
258
memset(&state->msg, 0, sizeof(struct i2c_msg));
259
state->msg.addr = reg;
260
state->msg.flags = I2C_M_RD;
261
state->msg.buf = state->i2c_read_buffer;
262
state->msg.len = 2;
263
if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
264
printk(KERN_WARNING "DiB0090 I2C read failed\n");
265
return 0;
266
}
267
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
268
}
269
270
static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
271
{
272
state->i2c_write_buffer[0] = val >> 8;
273
state->i2c_write_buffer[1] = val & 0xff;
274
275
memset(&state->msg, 0, sizeof(struct i2c_msg));
276
state->msg.addr = reg;
277
state->msg.flags = 0;
278
state->msg.buf = state->i2c_write_buffer;
279
state->msg.len = 2;
280
if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
281
printk(KERN_WARNING "DiB0090 I2C write failed\n");
282
return -EREMOTEIO;
283
}
284
return 0;
285
}
286
287
#define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0)
288
#define ADC_TARGET -220
289
#define GAIN_ALPHA 5
290
#define WBD_ALPHA 6
291
#define LPF 100
292
static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
293
{
294
do {
295
dib0090_write_reg(state, r++, *b++);
296
} while (--c);
297
}
298
299
static int dib0090_identify(struct dvb_frontend *fe)
300
{
301
struct dib0090_state *state = fe->tuner_priv;
302
u16 v;
303
struct dib0090_identity *identity = &state->identity;
304
305
v = dib0090_read_reg(state, 0x1a);
306
307
identity->p1g = 0;
308
identity->in_soc = 0;
309
310
dprintk("Tuner identification (Version = 0x%04x)", v);
311
312
/* without PLL lock info */
313
v &= ~KROSUS_PLL_LOCKED;
314
315
identity->version = v & 0xff;
316
identity->product = (v >> 8) & 0xf;
317
318
if (identity->product != KROSUS)
319
goto identification_error;
320
321
if ((identity->version & 0x3) == SOC) {
322
identity->in_soc = 1;
323
switch (identity->version) {
324
case SOC_8090_P1G_11R1:
325
dprintk("SOC 8090 P1-G11R1 Has been detected");
326
identity->p1g = 1;
327
break;
328
case SOC_8090_P1G_21R1:
329
dprintk("SOC 8090 P1-G21R1 Has been detected");
330
identity->p1g = 1;
331
break;
332
case SOC_7090_P1G_11R1:
333
dprintk("SOC 7090 P1-G11R1 Has been detected");
334
identity->p1g = 1;
335
break;
336
case SOC_7090_P1G_21R1:
337
dprintk("SOC 7090 P1-G21R1 Has been detected");
338
identity->p1g = 1;
339
break;
340
default:
341
goto identification_error;
342
}
343
} else {
344
switch ((identity->version >> 5) & 0x7) {
345
case MP001:
346
dprintk("MP001 : 9090/8096");
347
break;
348
case MP005:
349
dprintk("MP005 : Single Sband");
350
break;
351
case MP008:
352
dprintk("MP008 : diversity VHF-UHF-LBAND");
353
break;
354
case MP009:
355
dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
356
break;
357
default:
358
goto identification_error;
359
}
360
361
switch (identity->version & 0x1f) {
362
case P1G_21R2:
363
dprintk("P1G_21R2 detected");
364
identity->p1g = 1;
365
break;
366
case P1G:
367
dprintk("P1G detected");
368
identity->p1g = 1;
369
break;
370
case P1D_E_F:
371
dprintk("P1D/E/F detected");
372
break;
373
case P1C:
374
dprintk("P1C detected");
375
break;
376
case P1A_B:
377
dprintk("P1-A/B detected: driver is deactivated - not available");
378
goto identification_error;
379
break;
380
default:
381
goto identification_error;
382
}
383
}
384
385
return 0;
386
387
identification_error:
388
return -EIO;
389
}
390
391
static int dib0090_fw_identify(struct dvb_frontend *fe)
392
{
393
struct dib0090_fw_state *state = fe->tuner_priv;
394
struct dib0090_identity *identity = &state->identity;
395
396
u16 v = dib0090_fw_read_reg(state, 0x1a);
397
identity->p1g = 0;
398
identity->in_soc = 0;
399
400
dprintk("FE: Tuner identification (Version = 0x%04x)", v);
401
402
/* without PLL lock info */
403
v &= ~KROSUS_PLL_LOCKED;
404
405
identity->version = v & 0xff;
406
identity->product = (v >> 8) & 0xf;
407
408
if (identity->product != KROSUS)
409
goto identification_error;
410
411
if ((identity->version & 0x3) == SOC) {
412
identity->in_soc = 1;
413
switch (identity->version) {
414
case SOC_8090_P1G_11R1:
415
dprintk("SOC 8090 P1-G11R1 Has been detected");
416
identity->p1g = 1;
417
break;
418
case SOC_8090_P1G_21R1:
419
dprintk("SOC 8090 P1-G21R1 Has been detected");
420
identity->p1g = 1;
421
break;
422
case SOC_7090_P1G_11R1:
423
dprintk("SOC 7090 P1-G11R1 Has been detected");
424
identity->p1g = 1;
425
break;
426
case SOC_7090_P1G_21R1:
427
dprintk("SOC 7090 P1-G21R1 Has been detected");
428
identity->p1g = 1;
429
break;
430
default:
431
goto identification_error;
432
}
433
} else {
434
switch ((identity->version >> 5) & 0x7) {
435
case MP001:
436
dprintk("MP001 : 9090/8096");
437
break;
438
case MP005:
439
dprintk("MP005 : Single Sband");
440
break;
441
case MP008:
442
dprintk("MP008 : diversity VHF-UHF-LBAND");
443
break;
444
case MP009:
445
dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
446
break;
447
default:
448
goto identification_error;
449
}
450
451
switch (identity->version & 0x1f) {
452
case P1G_21R2:
453
dprintk("P1G_21R2 detected");
454
identity->p1g = 1;
455
break;
456
case P1G:
457
dprintk("P1G detected");
458
identity->p1g = 1;
459
break;
460
case P1D_E_F:
461
dprintk("P1D/E/F detected");
462
break;
463
case P1C:
464
dprintk("P1C detected");
465
break;
466
case P1A_B:
467
dprintk("P1-A/B detected: driver is deactivated - not available");
468
goto identification_error;
469
break;
470
default:
471
goto identification_error;
472
}
473
}
474
475
return 0;
476
477
identification_error:
478
return -EIO;;
479
}
480
481
static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
482
{
483
struct dib0090_state *state = fe->tuner_priv;
484
u16 PllCfg, i, v;
485
486
HARD_RESET(state);
487
488
dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
489
dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
490
491
if (!cfg->in_soc) {
492
/* adcClkOutRatio=8->7, release reset */
493
dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
494
if (cfg->clkoutdrive != 0)
495
dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
496
| (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
497
else
498
dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
499
| (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
500
}
501
502
/* Read Pll current config * */
503
PllCfg = dib0090_read_reg(state, 0x21);
504
505
/** Reconfigure PLL if current setting is different from default setting **/
506
if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && (!cfg->in_soc)
507
&& !cfg->io.pll_bypass) {
508
509
/* Set Bypass mode */
510
PllCfg |= (1 << 15);
511
dib0090_write_reg(state, 0x21, PllCfg);
512
513
/* Set Reset Pll */
514
PllCfg &= ~(1 << 13);
515
dib0090_write_reg(state, 0x21, PllCfg);
516
517
/*** Set new Pll configuration in bypass and reset state ***/
518
PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
519
dib0090_write_reg(state, 0x21, PllCfg);
520
521
/* Remove Reset Pll */
522
PllCfg |= (1 << 13);
523
dib0090_write_reg(state, 0x21, PllCfg);
524
525
/*** Wait for PLL lock ***/
526
i = 100;
527
do {
528
v = !!(dib0090_read_reg(state, 0x1a) & 0x800);
529
if (v)
530
break;
531
} while (--i);
532
533
if (i == 0) {
534
dprintk("Pll: Unable to lock Pll");
535
return;
536
}
537
538
/* Finally Remove Bypass mode */
539
PllCfg &= ~(1 << 15);
540
dib0090_write_reg(state, 0x21, PllCfg);
541
}
542
543
if (cfg->io.pll_bypass) {
544
PllCfg |= (cfg->io.pll_bypass << 15);
545
dib0090_write_reg(state, 0x21, PllCfg);
546
}
547
}
548
549
static int dib0090_fw_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
550
{
551
struct dib0090_fw_state *state = fe->tuner_priv;
552
u16 PllCfg;
553
u16 v;
554
int i;
555
556
dprintk("fw reset digital");
557
HARD_RESET(state);
558
559
dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
560
dib0090_fw_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
561
562
dib0090_fw_write_reg(state, 0x20,
563
((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (cfg->data_tx_drv << 4) | cfg->ls_cfg_pad_drv);
564
565
v = (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 9) | (0 << 8) | (cfg->clkouttobamse << 4) | (0 << 2) | (0);
566
if (cfg->clkoutdrive != 0)
567
v |= cfg->clkoutdrive << 5;
568
else
569
v |= 7 << 5;
570
571
v |= 2 << 10;
572
dib0090_fw_write_reg(state, 0x23, v);
573
574
/* Read Pll current config * */
575
PllCfg = dib0090_fw_read_reg(state, 0x21);
576
577
/** Reconfigure PLL if current setting is different from default setting **/
578
if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && !cfg->io.pll_bypass) {
579
580
/* Set Bypass mode */
581
PllCfg |= (1 << 15);
582
dib0090_fw_write_reg(state, 0x21, PllCfg);
583
584
/* Set Reset Pll */
585
PllCfg &= ~(1 << 13);
586
dib0090_fw_write_reg(state, 0x21, PllCfg);
587
588
/*** Set new Pll configuration in bypass and reset state ***/
589
PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
590
dib0090_fw_write_reg(state, 0x21, PllCfg);
591
592
/* Remove Reset Pll */
593
PllCfg |= (1 << 13);
594
dib0090_fw_write_reg(state, 0x21, PllCfg);
595
596
/*** Wait for PLL lock ***/
597
i = 100;
598
do {
599
v = !!(dib0090_fw_read_reg(state, 0x1a) & 0x800);
600
if (v)
601
break;
602
} while (--i);
603
604
if (i == 0) {
605
dprintk("Pll: Unable to lock Pll");
606
return -EIO;
607
}
608
609
/* Finally Remove Bypass mode */
610
PllCfg &= ~(1 << 15);
611
dib0090_fw_write_reg(state, 0x21, PllCfg);
612
}
613
614
if (cfg->io.pll_bypass) {
615
PllCfg |= (cfg->io.pll_bypass << 15);
616
dib0090_fw_write_reg(state, 0x21, PllCfg);
617
}
618
619
return dib0090_fw_identify(fe);
620
}
621
622
static int dib0090_wakeup(struct dvb_frontend *fe)
623
{
624
struct dib0090_state *state = fe->tuner_priv;
625
if (state->config->sleep)
626
state->config->sleep(fe, 0);
627
628
/* enable dataTX in case we have been restarted in the wrong moment */
629
dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
630
return 0;
631
}
632
633
static int dib0090_sleep(struct dvb_frontend *fe)
634
{
635
struct dib0090_state *state = fe->tuner_priv;
636
if (state->config->sleep)
637
state->config->sleep(fe, 1);
638
return 0;
639
}
640
641
void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
642
{
643
struct dib0090_state *state = fe->tuner_priv;
644
if (fast)
645
dib0090_write_reg(state, 0x04, 0);
646
else
647
dib0090_write_reg(state, 0x04, 1);
648
}
649
650
EXPORT_SYMBOL(dib0090_dcc_freq);
651
652
static const u16 bb_ramp_pwm_normal_socs[] = {
653
550, /* max BB gain in 10th of dB */
654
(1 << 9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
655
440,
656
(4 << 9) | 0, /* BB_RAMP3 = 26dB */
657
(0 << 9) | 208, /* BB_RAMP4 */
658
(4 << 9) | 208, /* BB_RAMP5 = 29dB */
659
(0 << 9) | 440, /* BB_RAMP6 */
660
};
661
662
static const u16 rf_ramp_pwm_cband_7090[] = {
663
280, /* max RF gain in 10th of dB */
664
18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
665
504, /* ramp_max = maximum X used on the ramp */
666
(29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */
667
(0 << 10) | 504, /* RF_RAMP6, LNA 1 */
668
(60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */
669
(0 << 10) | 364, /* RF_RAMP8, LNA 2 */
670
(34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */
671
(0 << 10) | 228, /* GAIN_4_2, LNA 3 */
672
(37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */
673
(0 << 10) | 109, /* RF_RAMP4, LNA 4 */
674
};
675
676
static const u16 rf_ramp_pwm_cband_8090[] = {
677
345, /* max RF gain in 10th of dB */
678
29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
679
1000, /* ramp_max = maximum X used on the ramp */
680
(35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */
681
(0 << 10) | 1000, /* RF_RAMP4, LNA 1 */
682
(58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */
683
(0 << 10) | 772, /* RF_RAMP6, LNA 2 */
684
(27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */
685
(0 << 10) | 496, /* RF_RAMP8, LNA 3 */
686
(40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */
687
(0 << 10) | 200, /* GAIN_4_2, LNA 4 */
688
};
689
690
static const u16 rf_ramp_pwm_uhf_7090[] = {
691
407, /* max RF gain in 10th of dB */
692
13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
693
529, /* ramp_max = maximum X used on the ramp */
694
(23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
695
(0 << 10) | 176, /* RF_RAMP4, LNA 1 */
696
(63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */
697
(0 << 10) | 529, /* RF_RAMP6, LNA 2 */
698
(48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */
699
(0 << 10) | 400, /* RF_RAMP8, LNA 3 */
700
(29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */
701
(0 << 10) | 316, /* GAIN_4_2, LNA 4 */
702
};
703
704
static const u16 rf_ramp_pwm_uhf_8090[] = {
705
388, /* max RF gain in 10th of dB */
706
26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
707
1008, /* ramp_max = maximum X used on the ramp */
708
(11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
709
(0 << 10) | 369, /* RF_RAMP4, LNA 1 */
710
(41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */
711
(0 << 10) | 1008, /* RF_RAMP6, LNA 2 */
712
(27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */
713
(0 << 10) | 809, /* RF_RAMP8, LNA 3 */
714
(14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */
715
(0 << 10) | 659, /* GAIN_4_2, LNA 4 */
716
};
717
718
static const u16 rf_ramp_pwm_cband[] = {
719
0, /* max RF gain in 10th of dB */
720
0, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
721
0, /* ramp_max = maximum X used on the ramp */
722
(0 << 10) | 0, /* 0x2c, LNA 1 = 0dB */
723
(0 << 10) | 0, /* 0x2d, LNA 1 */
724
(0 << 10) | 0, /* 0x2e, LNA 2 = 0dB */
725
(0 << 10) | 0, /* 0x2f, LNA 2 */
726
(0 << 10) | 0, /* 0x30, LNA 3 = 0dB */
727
(0 << 10) | 0, /* 0x31, LNA 3 */
728
(0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
729
(0 << 10) | 0, /* GAIN_4_2, LNA 4 */
730
};
731
732
static const u16 rf_ramp_vhf[] = {
733
412, /* max RF gain in 10th of dB */
734
132, 307, 127, /* LNA1, 13.2dB */
735
105, 412, 255, /* LNA2, 10.5dB */
736
50, 50, 127, /* LNA3, 5dB */
737
125, 175, 127, /* LNA4, 12.5dB */
738
0, 0, 127, /* CBAND, 0dB */
739
};
740
741
static const u16 rf_ramp_uhf[] = {
742
412, /* max RF gain in 10th of dB */
743
132, 307, 127, /* LNA1 : total gain = 13.2dB, point on the ramp where this amp is full gain, value to write to get full gain */
744
105, 412, 255, /* LNA2 : 10.5 dB */
745
50, 50, 127, /* LNA3 : 5.0 dB */
746
125, 175, 127, /* LNA4 : 12.5 dB */
747
0, 0, 127, /* CBAND : 0.0 dB */
748
};
749
750
static const u16 rf_ramp_cband_broadmatching[] = /* for p1G only */
751
{
752
314, /* Calibrated at 200MHz order has been changed g4-g3-g2-g1 */
753
84, 314, 127, /* LNA1 */
754
80, 230, 255, /* LNA2 */
755
80, 150, 127, /* LNA3 It was measured 12dB, do not lock if 120 */
756
70, 70, 127, /* LNA4 */
757
0, 0, 127, /* CBAND */
758
};
759
760
static const u16 rf_ramp_cband[] = {
761
332, /* max RF gain in 10th of dB */
762
132, 252, 127, /* LNA1, dB */
763
80, 332, 255, /* LNA2, dB */
764
0, 0, 127, /* LNA3, dB */
765
0, 0, 127, /* LNA4, dB */
766
120, 120, 127, /* LT1 CBAND */
767
};
768
769
static const u16 rf_ramp_pwm_vhf[] = {
770
404, /* max RF gain in 10th of dB */
771
25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
772
1011, /* ramp_max = maximum X used on the ramp */
773
(6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
774
(0 << 10) | 756, /* 0x2d, LNA 1 */
775
(16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
776
(0 << 10) | 1011, /* 0x2f, LNA 2 */
777
(16 << 10) | 290, /* 0x30, LNA 3 = 5dB */
778
(0 << 10) | 417, /* 0x31, LNA 3 */
779
(7 << 10) | 0, /* GAIN_4_1, LNA 4 = 12.5dB */
780
(0 << 10) | 290, /* GAIN_4_2, LNA 4 */
781
};
782
783
static const u16 rf_ramp_pwm_uhf[] = {
784
404, /* max RF gain in 10th of dB */
785
25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
786
1011, /* ramp_max = maximum X used on the ramp */
787
(6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
788
(0 << 10) | 756, /* 0x2d, LNA 1 */
789
(16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
790
(0 << 10) | 1011, /* 0x2f, LNA 2 */
791
(16 << 10) | 0, /* 0x30, LNA 3 = 5dB */
792
(0 << 10) | 127, /* 0x31, LNA 3 */
793
(7 << 10) | 127, /* GAIN_4_1, LNA 4 = 12.5dB */
794
(0 << 10) | 417, /* GAIN_4_2, LNA 4 */
795
};
796
797
static const u16 bb_ramp_boost[] = {
798
550, /* max BB gain in 10th of dB */
799
260, 260, 26, /* BB1, 26dB */
800
290, 550, 29, /* BB2, 29dB */
801
};
802
803
static const u16 bb_ramp_pwm_normal[] = {
804
500, /* max RF gain in 10th of dB */
805
8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */
806
400,
807
(2 << 9) | 0, /* 0x35 = 21dB */
808
(0 << 9) | 168, /* 0x36 */
809
(2 << 9) | 168, /* 0x37 = 29dB */
810
(0 << 9) | 400, /* 0x38 */
811
};
812
813
struct slope {
814
s16 range;
815
s16 slope;
816
};
817
static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
818
{
819
u8 i;
820
u16 rest;
821
u16 ret = 0;
822
for (i = 0; i < num; i++) {
823
if (val > slopes[i].range)
824
rest = slopes[i].range;
825
else
826
rest = val;
827
ret += (rest * slopes[i].slope) / slopes[i].range;
828
val -= rest;
829
}
830
return ret;
831
}
832
833
static const struct slope dib0090_wbd_slopes[3] = {
834
{66, 120}, /* -64,-52: offset - 65 */
835
{600, 170}, /* -52,-35: 65 - 665 */
836
{170, 250}, /* -45,-10: 665 - 835 */
837
};
838
839
static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
840
{
841
wbd &= 0x3ff;
842
if (wbd < state->wbd_offset)
843
wbd = 0;
844
else
845
wbd -= state->wbd_offset;
846
/* -64dB is the floor */
847
return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
848
}
849
850
static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
851
{
852
u16 offset = 250;
853
854
/* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
855
856
if (state->current_band == BAND_VHF)
857
offset = 650;
858
#ifndef FIRMWARE_FIREFLY
859
if (state->current_band == BAND_VHF)
860
offset = state->config->wbd_vhf_offset;
861
if (state->current_band == BAND_CBAND)
862
offset = state->config->wbd_cband_offset;
863
#endif
864
865
state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
866
dprintk("wbd-target: %d dB", (u32) state->wbd_target);
867
}
868
869
static const int gain_reg_addr[4] = {
870
0x08, 0x0a, 0x0f, 0x01
871
};
872
873
static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
874
{
875
u16 rf, bb, ref;
876
u16 i, v, gain_reg[4] = { 0 }, gain;
877
const u16 *g;
878
879
if (top_delta < -511)
880
top_delta = -511;
881
if (top_delta > 511)
882
top_delta = 511;
883
884
if (force) {
885
top_delta *= (1 << WBD_ALPHA);
886
gain_delta *= (1 << GAIN_ALPHA);
887
}
888
889
if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit)) /* overflow */
890
state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
891
else
892
state->rf_gain_limit += top_delta;
893
894
if (state->rf_gain_limit < 0) /*underflow */
895
state->rf_gain_limit = 0;
896
897
/* use gain as a temporary variable and correct current_gain */
898
gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
899
if (gain_delta >= ((s16) gain - state->current_gain)) /* overflow */
900
state->current_gain = gain;
901
else
902
state->current_gain += gain_delta;
903
/* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
904
if (state->current_gain < 0)
905
state->current_gain = 0;
906
907
/* now split total gain to rf and bb gain */
908
gain = state->current_gain >> GAIN_ALPHA;
909
910
/* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
911
if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
912
rf = state->rf_gain_limit >> WBD_ALPHA;
913
bb = gain - rf;
914
if (bb > state->bb_ramp[0])
915
bb = state->bb_ramp[0];
916
} else { /* high signal level -> all gains put on RF */
917
rf = gain;
918
bb = 0;
919
}
920
921
state->gain[0] = rf;
922
state->gain[1] = bb;
923
924
/* software ramp */
925
/* Start with RF gains */
926
g = state->rf_ramp + 1; /* point on RF LNA1 max gain */
927
ref = rf;
928
for (i = 0; i < 7; i++) { /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
929
if (g[0] == 0 || ref < (g[1] - g[0])) /* if total gain of the current amp is null or this amp is not concerned because it starts to work from an higher gain value */
930
v = 0; /* force the gain to write for the current amp to be null */
931
else if (ref >= g[1]) /* Gain to set is higher than the high working point of this amp */
932
v = g[2]; /* force this amp to be full gain */
933
else /* compute the value to set to this amp because we are somewhere in his range */
934
v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
935
936
if (i == 0) /* LNA 1 reg mapping */
937
gain_reg[0] = v;
938
else if (i == 1) /* LNA 2 reg mapping */
939
gain_reg[0] |= v << 7;
940
else if (i == 2) /* LNA 3 reg mapping */
941
gain_reg[1] = v;
942
else if (i == 3) /* LNA 4 reg mapping */
943
gain_reg[1] |= v << 7;
944
else if (i == 4) /* CBAND LNA reg mapping */
945
gain_reg[2] = v | state->rf_lt_def;
946
else if (i == 5) /* BB gain 1 reg mapping */
947
gain_reg[3] = v << 3;
948
else if (i == 6) /* BB gain 2 reg mapping */
949
gain_reg[3] |= v << 8;
950
951
g += 3; /* go to next gain bloc */
952
953
/* When RF is finished, start with BB */
954
if (i == 4) {
955
g = state->bb_ramp + 1; /* point on BB gain 1 max gain */
956
ref = bb;
957
}
958
}
959
gain_reg[3] |= state->bb_1_def;
960
gain_reg[3] |= ((bb % 10) * 100) / 125;
961
962
#ifdef DEBUG_AGC
963
dprintk("GA CALC: DB: %3d(rf) + %3d(bb) = %3d gain_reg[0]=%04x gain_reg[1]=%04x gain_reg[2]=%04x gain_reg[0]=%04x", rf, bb, rf + bb,
964
gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
965
#endif
966
967
/* Write the amplifier regs */
968
for (i = 0; i < 4; i++) {
969
v = gain_reg[i];
970
if (force || state->gain_reg[i] != v) {
971
state->gain_reg[i] = v;
972
dib0090_write_reg(state, gain_reg_addr[i], v);
973
}
974
}
975
}
976
977
static void dib0090_set_boost(struct dib0090_state *state, int onoff)
978
{
979
state->bb_1_def &= 0xdfff;
980
state->bb_1_def |= onoff << 13;
981
}
982
983
static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
984
{
985
state->rf_ramp = cfg;
986
}
987
988
static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
989
{
990
state->rf_ramp = cfg;
991
992
dib0090_write_reg(state, 0x2a, 0xffff);
993
994
dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
995
996
dib0090_write_regs(state, 0x2c, cfg + 3, 6);
997
dib0090_write_regs(state, 0x3e, cfg + 9, 2);
998
}
999
1000
static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
1001
{
1002
state->bb_ramp = cfg;
1003
dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1004
}
1005
1006
static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
1007
{
1008
state->bb_ramp = cfg;
1009
1010
dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1011
1012
dib0090_write_reg(state, 0x33, 0xffff);
1013
dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33));
1014
dib0090_write_regs(state, 0x35, cfg + 3, 4);
1015
}
1016
1017
void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
1018
{
1019
struct dib0090_state *state = fe->tuner_priv;
1020
/* reset the AGC */
1021
1022
if (state->config->use_pwm_agc) {
1023
#ifdef CONFIG_BAND_SBAND
1024
if (state->current_band == BAND_SBAND) {
1025
dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband);
1026
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost);
1027
} else
1028
#endif
1029
#ifdef CONFIG_BAND_CBAND
1030
if (state->current_band == BAND_CBAND) {
1031
if (state->identity.in_soc) {
1032
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
1033
if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1034
dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_8090);
1035
else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1036
dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090);
1037
} else {
1038
dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
1039
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
1040
}
1041
} else
1042
#endif
1043
#ifdef CONFIG_BAND_VHF
1044
if (state->current_band == BAND_VHF) {
1045
if (state->identity.in_soc) {
1046
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
1047
} else {
1048
dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf);
1049
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
1050
}
1051
} else
1052
#endif
1053
{
1054
if (state->identity.in_soc) {
1055
if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1056
dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_8090);
1057
else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1058
dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_7090);
1059
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
1060
} else {
1061
dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
1062
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
1063
}
1064
}
1065
1066
if (state->rf_ramp[0] != 0)
1067
dib0090_write_reg(state, 0x32, (3 << 11));
1068
else
1069
dib0090_write_reg(state, 0x32, (0 << 11));
1070
1071
dib0090_write_reg(state, 0x04, 0x01);
1072
dib0090_write_reg(state, 0x39, (1 << 10));
1073
}
1074
}
1075
1076
EXPORT_SYMBOL(dib0090_pwm_gain_reset);
1077
1078
static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
1079
{
1080
u16 adc_val = dib0090_read_reg(state, 0x1d);
1081
if (state->identity.in_soc)
1082
adc_val >>= 2;
1083
return adc_val;
1084
}
1085
1086
int dib0090_gain_control(struct dvb_frontend *fe)
1087
{
1088
struct dib0090_state *state = fe->tuner_priv;
1089
enum frontend_tune_state *tune_state = &state->tune_state;
1090
int ret = 10;
1091
1092
u16 wbd_val = 0;
1093
u8 apply_gain_immediatly = 1;
1094
s16 wbd_error = 0, adc_error = 0;
1095
1096
if (*tune_state == CT_AGC_START) {
1097
state->agc_freeze = 0;
1098
dib0090_write_reg(state, 0x04, 0x0);
1099
1100
#ifdef CONFIG_BAND_SBAND
1101
if (state->current_band == BAND_SBAND) {
1102
dib0090_set_rframp(state, rf_ramp_sband);
1103
dib0090_set_bbramp(state, bb_ramp_boost);
1104
} else
1105
#endif
1106
#ifdef CONFIG_BAND_VHF
1107
if (state->current_band == BAND_VHF && !state->identity.p1g) {
1108
dib0090_set_rframp(state, rf_ramp_vhf);
1109
dib0090_set_bbramp(state, bb_ramp_boost);
1110
} else
1111
#endif
1112
#ifdef CONFIG_BAND_CBAND
1113
if (state->current_band == BAND_CBAND && !state->identity.p1g) {
1114
dib0090_set_rframp(state, rf_ramp_cband);
1115
dib0090_set_bbramp(state, bb_ramp_boost);
1116
} else
1117
#endif
1118
if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
1119
dib0090_set_rframp(state, rf_ramp_cband_broadmatching);
1120
dib0090_set_bbramp(state, bb_ramp_boost);
1121
} else {
1122
dib0090_set_rframp(state, rf_ramp_uhf);
1123
dib0090_set_bbramp(state, bb_ramp_boost);
1124
}
1125
1126
dib0090_write_reg(state, 0x32, 0);
1127
dib0090_write_reg(state, 0x39, 0);
1128
1129
dib0090_wbd_target(state, state->current_rf);
1130
1131
state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
1132
state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
1133
1134
*tune_state = CT_AGC_STEP_0;
1135
} else if (!state->agc_freeze) {
1136
s16 wbd = 0, i, cnt;
1137
1138
int adc;
1139
wbd_val = dib0090_get_slow_adc_val(state);
1140
1141
if (*tune_state == CT_AGC_STEP_0)
1142
cnt = 5;
1143
else
1144
cnt = 1;
1145
1146
for (i = 0; i < cnt; i++) {
1147
wbd_val = dib0090_get_slow_adc_val(state);
1148
wbd += dib0090_wbd_to_db(state, wbd_val);
1149
}
1150
wbd /= cnt;
1151
wbd_error = state->wbd_target - wbd;
1152
1153
if (*tune_state == CT_AGC_STEP_0) {
1154
if (wbd_error < 0 && state->rf_gain_limit > 0 && !state->identity.p1g) {
1155
#ifdef CONFIG_BAND_CBAND
1156
/* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
1157
u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
1158
if (state->current_band == BAND_CBAND && ltg2) {
1159
ltg2 >>= 1;
1160
state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */
1161
}
1162
#endif
1163
} else {
1164
state->agc_step = 0;
1165
*tune_state = CT_AGC_STEP_1;
1166
}
1167
} else {
1168
/* calc the adc power */
1169
adc = state->config->get_adc_power(fe);
1170
adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */
1171
1172
adc_error = (s16) (((s32) ADC_TARGET) - adc);
1173
#ifdef CONFIG_STANDARD_DAB
1174
if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
1175
adc_error -= 10;
1176
#endif
1177
#ifdef CONFIG_STANDARD_DVBT
1178
if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
1179
(state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
1180
adc_error += 60;
1181
#endif
1182
#ifdef CONFIG_SYS_ISDBT
1183
if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
1184
0)
1185
&&
1186
((state->fe->dtv_property_cache.layer[0].modulation ==
1187
QAM_64)
1188
|| (state->fe->dtv_property_cache.
1189
layer[0].modulation == QAM_16)))
1190
||
1191
((state->fe->dtv_property_cache.layer[1].segment_count >
1192
0)
1193
&&
1194
((state->fe->dtv_property_cache.layer[1].modulation ==
1195
QAM_64)
1196
|| (state->fe->dtv_property_cache.
1197
layer[1].modulation == QAM_16)))
1198
||
1199
((state->fe->dtv_property_cache.layer[2].segment_count >
1200
0)
1201
&&
1202
((state->fe->dtv_property_cache.layer[2].modulation ==
1203
QAM_64)
1204
|| (state->fe->dtv_property_cache.
1205
layer[2].modulation == QAM_16)))
1206
)
1207
)
1208
adc_error += 60;
1209
#endif
1210
1211
if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */
1212
if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
1213
1214
#ifdef CONFIG_STANDARD_DAB
1215
if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
1216
dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63)); /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
1217
dib0090_write_reg(state, 0x04, 0x0);
1218
} else
1219
#endif
1220
{
1221
dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
1222
dib0090_write_reg(state, 0x04, 0x01); /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
1223
}
1224
1225
*tune_state = CT_AGC_STOP;
1226
}
1227
} else {
1228
/* everything higher than or equal to CT_AGC_STOP means tracking */
1229
ret = 100; /* 10ms interval */
1230
apply_gain_immediatly = 0;
1231
}
1232
}
1233
#ifdef DEBUG_AGC
1234
dprintk
1235
("tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
1236
(u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
1237
(u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
1238
#endif
1239
}
1240
1241
/* apply gain */
1242
if (!state->agc_freeze)
1243
dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
1244
return ret;
1245
}
1246
1247
EXPORT_SYMBOL(dib0090_gain_control);
1248
1249
void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
1250
{
1251
struct dib0090_state *state = fe->tuner_priv;
1252
if (rf)
1253
*rf = state->gain[0];
1254
if (bb)
1255
*bb = state->gain[1];
1256
if (rf_gain_limit)
1257
*rf_gain_limit = state->rf_gain_limit;
1258
if (rflt)
1259
*rflt = (state->rf_lt_def >> 10) & 0x7;
1260
}
1261
1262
EXPORT_SYMBOL(dib0090_get_current_gain);
1263
1264
u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
1265
{
1266
struct dib0090_state *state = fe->tuner_priv;
1267
u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
1268
s32 current_temp = state->temperature;
1269
s32 wbd_thot, wbd_tcold;
1270
const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1271
1272
while (f_MHz > wbd->max_freq)
1273
wbd++;
1274
1275
dprintk("using wbd-table-entry with max freq %d", wbd->max_freq);
1276
1277
if (current_temp < 0)
1278
current_temp = 0;
1279
if (current_temp > 128)
1280
current_temp = 128;
1281
1282
state->wbdmux &= ~(7 << 13);
1283
if (wbd->wbd_gain != 0)
1284
state->wbdmux |= (wbd->wbd_gain << 13);
1285
else
1286
state->wbdmux |= (4 << 13);
1287
1288
dib0090_write_reg(state, 0x10, state->wbdmux);
1289
1290
wbd_thot = wbd->offset_hot - (((u32) wbd->slope_hot * f_MHz) >> 6);
1291
wbd_tcold = wbd->offset_cold - (((u32) wbd->slope_cold * f_MHz) >> 6);
1292
1293
wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7;
1294
1295
state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold);
1296
dprintk("wbd-target: %d dB", (u32) state->wbd_target);
1297
dprintk("wbd offset applied is %d", wbd_tcold);
1298
1299
return state->wbd_offset + wbd_tcold;
1300
}
1301
1302
EXPORT_SYMBOL(dib0090_get_wbd_offset);
1303
1304
static const u16 dib0090_defaults[] = {
1305
1306
25, 0x01,
1307
0x0000,
1308
0x99a0,
1309
0x6008,
1310
0x0000,
1311
0x8bcb,
1312
0x0000,
1313
0x0405,
1314
0x0000,
1315
0x0000,
1316
0x0000,
1317
0xb802,
1318
0x0300,
1319
0x2d12,
1320
0xbac0,
1321
0x7c00,
1322
0xdbb9,
1323
0x0954,
1324
0x0743,
1325
0x8000,
1326
0x0001,
1327
0x0040,
1328
0x0100,
1329
0x0000,
1330
0xe910,
1331
0x149e,
1332
1333
1, 0x1c,
1334
0xff2d,
1335
1336
1, 0x39,
1337
0x0000,
1338
1339
2, 0x1e,
1340
0x07FF,
1341
0x0007,
1342
1343
1, 0x24,
1344
EN_UHF | EN_CRYSTAL,
1345
1346
2, 0x3c,
1347
0x3ff,
1348
0x111,
1349
0
1350
};
1351
1352
static const u16 dib0090_p1g_additionnal_defaults[] = {
1353
1, 0x05,
1354
0xabcd,
1355
1356
1, 0x11,
1357
0x00b4,
1358
1359
1, 0x1c,
1360
0xfffd,
1361
1362
1, 0x40,
1363
0x108,
1364
0
1365
};
1366
1367
static void dib0090_set_default_config(struct dib0090_state *state, const u16 * n)
1368
{
1369
u16 l, r;
1370
1371
l = pgm_read_word(n++);
1372
while (l) {
1373
r = pgm_read_word(n++);
1374
do {
1375
dib0090_write_reg(state, r, pgm_read_word(n++));
1376
r++;
1377
} while (--l);
1378
l = pgm_read_word(n++);
1379
}
1380
}
1381
1382
#define CAP_VALUE_MIN (u8) 9
1383
#define CAP_VALUE_MAX (u8) 40
1384
#define HR_MIN (u8) 25
1385
#define HR_MAX (u8) 40
1386
#define POLY_MIN (u8) 0
1387
#define POLY_MAX (u8) 8
1388
1389
void dib0090_set_EFUSE(struct dib0090_state *state)
1390
{
1391
u8 c, h, n;
1392
u16 e2, e4;
1393
u16 cal;
1394
1395
e2 = dib0090_read_reg(state, 0x26);
1396
e4 = dib0090_read_reg(state, 0x28);
1397
1398
if ((state->identity.version == P1D_E_F) ||
1399
(state->identity.version == P1G) || (e2 == 0xffff)) {
1400
1401
dib0090_write_reg(state, 0x22, 0x10);
1402
cal = (dib0090_read_reg(state, 0x22) >> 6) & 0x3ff;
1403
1404
if ((cal < 670) || (cal == 1023))
1405
cal = 850;
1406
n = 165 - ((cal * 10)>>6) ;
1407
e2 = e4 = (3<<12) | (34<<6) | (n);
1408
}
1409
1410
if (e2 != e4)
1411
e2 &= e4; /* Remove the redundancy */
1412
1413
if (e2 != 0xffff) {
1414
c = e2 & 0x3f;
1415
n = (e2 >> 12) & 0xf;
1416
h = (e2 >> 6) & 0x3f;
1417
1418
if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
1419
c = 32;
1420
if ((h >= HR_MAX) || (h <= HR_MIN))
1421
h = 34;
1422
if ((n >= POLY_MAX) || (n <= POLY_MIN))
1423
n = 3;
1424
1425
dib0090_write_reg(state, 0x13, (h << 10)) ;
1426
e2 = (n<<11) | ((h>>2)<<6) | (c);
1427
dib0090_write_reg(state, 0x2, e2) ; /* Load the BB_2 */
1428
}
1429
}
1430
1431
static int dib0090_reset(struct dvb_frontend *fe)
1432
{
1433
struct dib0090_state *state = fe->tuner_priv;
1434
1435
dib0090_reset_digital(fe, state->config);
1436
if (dib0090_identify(fe) < 0)
1437
return -EIO;
1438
1439
#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
1440
if (!(state->identity.version & 0x1)) /* it is P1B - reset is already done */
1441
return 0;
1442
#endif
1443
1444
if (!state->identity.in_soc) {
1445
if ((dib0090_read_reg(state, 0x1a) >> 5) & 0x2)
1446
dib0090_write_reg(state, 0x1b, (EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1447
else
1448
dib0090_write_reg(state, 0x1b, (EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1449
}
1450
1451
dib0090_set_default_config(state, dib0090_defaults);
1452
1453
if (state->identity.in_soc)
1454
dib0090_write_reg(state, 0x18, 0x2910); /* charge pump current = 0 */
1455
1456
if (state->identity.p1g)
1457
dib0090_set_default_config(state, dib0090_p1g_additionnal_defaults);
1458
1459
/* Update the efuse : Only available for KROSUS > P1C and SOC as well*/
1460
if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
1461
dib0090_set_EFUSE(state);
1462
1463
/* Congigure in function of the crystal */
1464
if (state->config->io.clock_khz >= 24000)
1465
dib0090_write_reg(state, 0x14, 1);
1466
else
1467
dib0090_write_reg(state, 0x14, 2);
1468
dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
1469
1470
state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL; /* enable iq-offset-calibration and wbd-calibration when tuning next time */
1471
1472
return 0;
1473
}
1474
1475
#define steps(u) (((u) > 15) ? ((u)-16) : (u))
1476
#define INTERN_WAIT 10
1477
static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1478
{
1479
int ret = INTERN_WAIT * 10;
1480
1481
switch (*tune_state) {
1482
case CT_TUNER_STEP_2:
1483
/* Turns to positive */
1484
dib0090_write_reg(state, 0x1f, 0x7);
1485
*tune_state = CT_TUNER_STEP_3;
1486
break;
1487
1488
case CT_TUNER_STEP_3:
1489
state->adc_diff = dib0090_read_reg(state, 0x1d);
1490
1491
/* Turns to negative */
1492
dib0090_write_reg(state, 0x1f, 0x4);
1493
*tune_state = CT_TUNER_STEP_4;
1494
break;
1495
1496
case CT_TUNER_STEP_4:
1497
state->adc_diff -= dib0090_read_reg(state, 0x1d);
1498
*tune_state = CT_TUNER_STEP_5;
1499
ret = 0;
1500
break;
1501
1502
default:
1503
break;
1504
}
1505
1506
return ret;
1507
}
1508
1509
struct dc_calibration {
1510
u8 addr;
1511
u8 offset;
1512
u8 pga:1;
1513
u16 bb1;
1514
u8 i:1;
1515
};
1516
1517
static const struct dc_calibration dc_table[] = {
1518
/* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1519
{0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
1520
{0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
1521
/* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1522
{0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
1523
{0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
1524
{0},
1525
};
1526
1527
static const struct dc_calibration dc_p1g_table[] = {
1528
/* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1529
/* addr ; trim reg offset ; pga ; CTRL_BB1 value ; i or q */
1530
{0x06, 5, 1, (1 << 13) | (0 << 8) | (15 << 3), 1},
1531
{0x07, 11, 1, (1 << 13) | (0 << 8) | (15 << 3), 0},
1532
/* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1533
{0x06, 0, 0, (1 << 13) | (29 << 8) | (15 << 3), 1},
1534
{0x06, 10, 0, (1 << 13) | (29 << 8) | (15 << 3), 0},
1535
{0},
1536
};
1537
1538
static void dib0090_set_trim(struct dib0090_state *state)
1539
{
1540
u16 *val;
1541
1542
if (state->dc->addr == 0x07)
1543
val = &state->bb7;
1544
else
1545
val = &state->bb6;
1546
1547
*val &= ~(0x1f << state->dc->offset);
1548
*val |= state->step << state->dc->offset;
1549
1550
dib0090_write_reg(state, state->dc->addr, *val);
1551
}
1552
1553
static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1554
{
1555
int ret = 0;
1556
u16 reg;
1557
1558
switch (*tune_state) {
1559
case CT_TUNER_START:
1560
dprintk("Start DC offset calibration");
1561
1562
/* force vcm2 = 0.8V */
1563
state->bb6 = 0;
1564
state->bb7 = 0x040d;
1565
1566
/* the LNA AND LO are off */
1567
reg = dib0090_read_reg(state, 0x24) & 0x0ffb; /* shutdown lna and lo */
1568
dib0090_write_reg(state, 0x24, reg);
1569
1570
state->wbdmux = dib0090_read_reg(state, 0x10);
1571
dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x7 << 3) | 0x3);
1572
dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
1573
1574
state->dc = dc_table;
1575
1576
if (state->identity.p1g)
1577
state->dc = dc_p1g_table;
1578
*tune_state = CT_TUNER_STEP_0;
1579
1580
/* fall through */
1581
1582
case CT_TUNER_STEP_0:
1583
dprintk("Sart/continue DC calibration for %s path", (state->dc->i == 1) ? "I" : "Q");
1584
dib0090_write_reg(state, 0x01, state->dc->bb1);
1585
dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
1586
1587
state->step = 0;
1588
state->min_adc_diff = 1023;
1589
*tune_state = CT_TUNER_STEP_1;
1590
ret = 50;
1591
break;
1592
1593
case CT_TUNER_STEP_1:
1594
dib0090_set_trim(state);
1595
*tune_state = CT_TUNER_STEP_2;
1596
break;
1597
1598
case CT_TUNER_STEP_2:
1599
case CT_TUNER_STEP_3:
1600
case CT_TUNER_STEP_4:
1601
ret = dib0090_get_offset(state, tune_state);
1602
break;
1603
1604
case CT_TUNER_STEP_5: /* found an offset */
1605
dprintk("adc_diff = %d, current step= %d", (u32) state->adc_diff, state->step);
1606
if (state->step == 0 && state->adc_diff < 0) {
1607
state->min_adc_diff = -1023;
1608
dprintk("Change of sign of the minimum adc diff");
1609
}
1610
1611
dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d", state->adc_diff, state->min_adc_diff, state->step);
1612
1613
/* first turn for this frequency */
1614
if (state->step == 0) {
1615
if (state->dc->pga && state->adc_diff < 0)
1616
state->step = 0x10;
1617
if (state->dc->pga == 0 && state->adc_diff > 0)
1618
state->step = 0x10;
1619
}
1620
1621
/* Look for a change of Sign in the Adc_diff.min_adc_diff is used to STORE the setp N-1 */
1622
if ((state->adc_diff & 0x8000) == (state->min_adc_diff & 0x8000) && steps(state->step) < 15) {
1623
/* stop search when the delta the sign is changing and Steps =15 and Step=0 is force for continuance */
1624
state->step++;
1625
state->min_adc_diff = state->adc_diff;
1626
*tune_state = CT_TUNER_STEP_1;
1627
} else {
1628
/* the minimum was what we have seen in the step before */
1629
if (ABS(state->adc_diff) > ABS(state->min_adc_diff)) {
1630
dprintk("Since adc_diff N = %d > adc_diff step N-1 = %d, Come back one step", state->adc_diff, state->min_adc_diff);
1631
state->step--;
1632
}
1633
1634
dib0090_set_trim(state);
1635
dprintk("BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->dc->addr, state->adc_diff, state->step);
1636
1637
state->dc++;
1638
if (state->dc->addr == 0) /* done */
1639
*tune_state = CT_TUNER_STEP_6;
1640
else
1641
*tune_state = CT_TUNER_STEP_0;
1642
1643
}
1644
break;
1645
1646
case CT_TUNER_STEP_6:
1647
dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
1648
dib0090_write_reg(state, 0x1f, 0x7);
1649
*tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1650
state->calibrate &= ~DC_CAL;
1651
default:
1652
break;
1653
}
1654
return ret;
1655
}
1656
1657
static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1658
{
1659
u8 wbd_gain;
1660
const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1661
1662
switch (*tune_state) {
1663
case CT_TUNER_START:
1664
while (state->current_rf / 1000 > wbd->max_freq)
1665
wbd++;
1666
if (wbd->wbd_gain != 0)
1667
wbd_gain = wbd->wbd_gain;
1668
else {
1669
wbd_gain = 4;
1670
#if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
1671
if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND))
1672
wbd_gain = 2;
1673
#endif
1674
}
1675
1676
if (wbd_gain == state->wbd_calibration_gain) { /* the WBD calibration has already been done */
1677
*tune_state = CT_TUNER_START;
1678
state->calibrate &= ~WBD_CAL;
1679
return 0;
1680
}
1681
1682
dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3));
1683
1684
dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1)));
1685
*tune_state = CT_TUNER_STEP_0;
1686
state->wbd_calibration_gain = wbd_gain;
1687
return 90; /* wait for the WBDMUX to switch and for the ADC to sample */
1688
1689
case CT_TUNER_STEP_0:
1690
state->wbd_offset = dib0090_get_slow_adc_val(state);
1691
dprintk("WBD calibration offset = %d", state->wbd_offset);
1692
*tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1693
state->calibrate &= ~WBD_CAL;
1694
break;
1695
1696
default:
1697
break;
1698
}
1699
return 0;
1700
}
1701
1702
static void dib0090_set_bandwidth(struct dib0090_state *state)
1703
{
1704
u16 tmp;
1705
1706
if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
1707
tmp = (3 << 14);
1708
else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
1709
tmp = (2 << 14);
1710
else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
1711
tmp = (1 << 14);
1712
else
1713
tmp = (0 << 14);
1714
1715
state->bb_1_def &= 0x3fff;
1716
state->bb_1_def |= tmp;
1717
1718
dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */
1719
1720
dib0090_write_reg(state, 0x03, 0x6008); /* = 0x6008 : vcm3_trim = 1 ; filter2_gm1_trim = 8 ; filter2_cutoff_freq = 0 */
1721
dib0090_write_reg(state, 0x04, 0x1); /* 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast */
1722
if (state->identity.in_soc) {
1723
dib0090_write_reg(state, 0x05, 0x9bcf); /* attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 1 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 15 */
1724
} else {
1725
dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f)); /* 22 = cap_value */
1726
dib0090_write_reg(state, 0x05, 0xabcd); /* = 0xabcd : attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 2 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 13 */
1727
}
1728
}
1729
1730
static const struct dib0090_pll dib0090_pll_table[] = {
1731
#ifdef CONFIG_BAND_CBAND
1732
{56000, 0, 9, 48, 6},
1733
{70000, 1, 9, 48, 6},
1734
{87000, 0, 8, 32, 4},
1735
{105000, 1, 8, 32, 4},
1736
{115000, 0, 7, 24, 6},
1737
{140000, 1, 7, 24, 6},
1738
{170000, 0, 6, 16, 4},
1739
#endif
1740
#ifdef CONFIG_BAND_VHF
1741
{200000, 1, 6, 16, 4},
1742
{230000, 0, 5, 12, 6},
1743
{280000, 1, 5, 12, 6},
1744
{340000, 0, 4, 8, 4},
1745
{380000, 1, 4, 8, 4},
1746
{450000, 0, 3, 6, 6},
1747
#endif
1748
#ifdef CONFIG_BAND_UHF
1749
{580000, 1, 3, 6, 6},
1750
{700000, 0, 2, 4, 4},
1751
{860000, 1, 2, 4, 4},
1752
#endif
1753
#ifdef CONFIG_BAND_LBAND
1754
{1800000, 1, 0, 2, 4},
1755
#endif
1756
#ifdef CONFIG_BAND_SBAND
1757
{2900000, 0, 14, 1, 4},
1758
#endif
1759
};
1760
1761
static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1762
1763
#ifdef CONFIG_BAND_CBAND
1764
{184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1765
{227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1766
{380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1767
#endif
1768
#ifdef CONFIG_BAND_UHF
1769
{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1770
{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1771
{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1772
{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1773
{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1774
{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1775
#endif
1776
#ifdef CONFIG_BAND_LBAND
1777
{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1778
{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1779
{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1780
#endif
1781
#ifdef CONFIG_BAND_SBAND
1782
{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1783
{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1784
#endif
1785
};
1786
1787
static const struct dib0090_tuning dib0090_tuning_table[] = {
1788
1789
#ifdef CONFIG_BAND_CBAND
1790
{170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1791
#endif
1792
#ifdef CONFIG_BAND_VHF
1793
{184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1794
{227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1795
{380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1796
#endif
1797
#ifdef CONFIG_BAND_UHF
1798
{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1799
{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1800
{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1801
{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1802
{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1803
{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1804
#endif
1805
#ifdef CONFIG_BAND_LBAND
1806
{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1807
{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1808
{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1809
#endif
1810
#ifdef CONFIG_BAND_SBAND
1811
{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1812
{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1813
#endif
1814
};
1815
1816
static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {
1817
#ifdef CONFIG_BAND_CBAND
1818
{170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},
1819
#endif
1820
#ifdef CONFIG_BAND_VHF
1821
{184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1822
{227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1823
{380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1824
#endif
1825
#ifdef CONFIG_BAND_UHF
1826
{510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1827
{540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1828
{600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1829
{630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1830
{680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1831
{720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1832
{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1833
#endif
1834
#ifdef CONFIG_BAND_LBAND
1835
{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1836
{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1837
{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1838
#endif
1839
#ifdef CONFIG_BAND_SBAND
1840
{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1841
{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1842
#endif
1843
};
1844
1845
static const struct dib0090_pll dib0090_p1g_pll_table[] = {
1846
#ifdef CONFIG_BAND_CBAND
1847
{57000, 0, 11, 48, 6},
1848
{70000, 1, 11, 48, 6},
1849
{86000, 0, 10, 32, 4},
1850
{105000, 1, 10, 32, 4},
1851
{115000, 0, 9, 24, 6},
1852
{140000, 1, 9, 24, 6},
1853
{170000, 0, 8, 16, 4},
1854
#endif
1855
#ifdef CONFIG_BAND_VHF
1856
{200000, 1, 8, 16, 4},
1857
{230000, 0, 7, 12, 6},
1858
{280000, 1, 7, 12, 6},
1859
{340000, 0, 6, 8, 4},
1860
{380000, 1, 6, 8, 4},
1861
{455000, 0, 5, 6, 6},
1862
#endif
1863
#ifdef CONFIG_BAND_UHF
1864
{580000, 1, 5, 6, 6},
1865
{680000, 0, 4, 4, 4},
1866
{860000, 1, 4, 4, 4},
1867
#endif
1868
#ifdef CONFIG_BAND_LBAND
1869
{1800000, 1, 2, 2, 4},
1870
#endif
1871
#ifdef CONFIG_BAND_SBAND
1872
{2900000, 0, 1, 1, 6},
1873
#endif
1874
};
1875
1876
static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {
1877
#ifdef CONFIG_BAND_CBAND
1878
{184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1879
{227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1880
{380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1881
#endif
1882
#ifdef CONFIG_BAND_UHF
1883
{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1884
{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1885
{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1886
{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1887
{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1888
{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1889
#endif
1890
#ifdef CONFIG_BAND_LBAND
1891
{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1892
{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1893
{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1894
#endif
1895
#ifdef CONFIG_BAND_SBAND
1896
{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1897
{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1898
#endif
1899
};
1900
1901
static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
1902
#ifdef CONFIG_BAND_CBAND
1903
{300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
1904
{380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
1905
{570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
1906
{858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
1907
#endif
1908
};
1909
1910
static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1911
{
1912
int ret = 0;
1913
u16 lo4 = 0xe900;
1914
1915
s16 adc_target;
1916
u16 adc;
1917
s8 step_sign;
1918
u8 force_soft_search = 0;
1919
1920
if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1921
force_soft_search = 1;
1922
1923
if (*tune_state == CT_TUNER_START) {
1924
dprintk("Start Captrim search : %s", (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
1925
dib0090_write_reg(state, 0x10, 0x2B1);
1926
dib0090_write_reg(state, 0x1e, 0x0032);
1927
1928
if (!state->tuner_is_tuned) {
1929
/* prepare a complete captrim */
1930
if (!state->identity.p1g || force_soft_search)
1931
state->step = state->captrim = state->fcaptrim = 64;
1932
1933
state->current_rf = state->rf_request;
1934
} else { /* we are already tuned to this frequency - the configuration is correct */
1935
if (!state->identity.p1g || force_soft_search) {
1936
/* do a minimal captrim even if the frequency has not changed */
1937
state->step = 4;
1938
state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
1939
}
1940
}
1941
state->adc_diff = 3000;
1942
*tune_state = CT_TUNER_STEP_0;
1943
1944
} else if (*tune_state == CT_TUNER_STEP_0) {
1945
if (state->identity.p1g && !force_soft_search) {
1946
u8 ratio = 31;
1947
1948
dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1);
1949
dib0090_read_reg(state, 0x40);
1950
ret = 50;
1951
} else {
1952
state->step /= 2;
1953
dib0090_write_reg(state, 0x18, lo4 | state->captrim);
1954
1955
if (state->identity.in_soc)
1956
ret = 25;
1957
}
1958
*tune_state = CT_TUNER_STEP_1;
1959
1960
} else if (*tune_state == CT_TUNER_STEP_1) {
1961
if (state->identity.p1g && !force_soft_search) {
1962
dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0);
1963
dib0090_read_reg(state, 0x40);
1964
1965
state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
1966
dprintk("***Final Captrim= 0x%x", state->fcaptrim);
1967
*tune_state = CT_TUNER_STEP_3;
1968
1969
} else {
1970
/* MERGE for all krosus before P1G */
1971
adc = dib0090_get_slow_adc_val(state);
1972
dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
1973
1974
if (state->rest == 0 || state->identity.in_soc) { /* Just for 8090P SOCS where auto captrim HW bug : TO CHECK IN ACI for SOCS !!! if 400 for 8090p SOC => tune issue !!! */
1975
adc_target = 200;
1976
} else
1977
adc_target = 400;
1978
1979
if (adc >= adc_target) {
1980
adc -= adc_target;
1981
step_sign = -1;
1982
} else {
1983
adc = adc_target - adc;
1984
step_sign = 1;
1985
}
1986
1987
if (adc < state->adc_diff) {
1988
dprintk("CAPTRIM=%d is closer to target (%d/%d)", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
1989
state->adc_diff = adc;
1990
state->fcaptrim = state->captrim;
1991
}
1992
1993
state->captrim += step_sign * state->step;
1994
if (state->step >= 1)
1995
*tune_state = CT_TUNER_STEP_0;
1996
else
1997
*tune_state = CT_TUNER_STEP_2;
1998
1999
ret = 25;
2000
}
2001
} else if (*tune_state == CT_TUNER_STEP_2) { /* this step is only used by krosus < P1G */
2002
/*write the final cptrim config */
2003
dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
2004
2005
*tune_state = CT_TUNER_STEP_3;
2006
2007
} else if (*tune_state == CT_TUNER_STEP_3) {
2008
state->calibrate &= ~CAPTRIM_CAL;
2009
*tune_state = CT_TUNER_STEP_0;
2010
}
2011
2012
return ret;
2013
}
2014
2015
static int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2016
{
2017
int ret = 15;
2018
s16 val;
2019
2020
switch (*tune_state) {
2021
case CT_TUNER_START:
2022
state->wbdmux = dib0090_read_reg(state, 0x10);
2023
dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3));
2024
2025
state->bias = dib0090_read_reg(state, 0x13);
2026
dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8));
2027
2028
*tune_state = CT_TUNER_STEP_0;
2029
/* wait for the WBDMUX to switch and for the ADC to sample */
2030
break;
2031
2032
case CT_TUNER_STEP_0:
2033
state->adc_diff = dib0090_get_slow_adc_val(state);
2034
dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8));
2035
*tune_state = CT_TUNER_STEP_1;
2036
break;
2037
2038
case CT_TUNER_STEP_1:
2039
val = dib0090_get_slow_adc_val(state);
2040
state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
2041
2042
dprintk("temperature: %d C", state->temperature - 30);
2043
2044
*tune_state = CT_TUNER_STEP_2;
2045
break;
2046
2047
case CT_TUNER_STEP_2:
2048
dib0090_write_reg(state, 0x13, state->bias);
2049
dib0090_write_reg(state, 0x10, state->wbdmux); /* write back original WBDMUX */
2050
2051
*tune_state = CT_TUNER_START;
2052
state->calibrate &= ~TEMP_CAL;
2053
if (state->config->analog_output == 0)
2054
dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2055
2056
break;
2057
2058
default:
2059
ret = 0;
2060
break;
2061
}
2062
return ret;
2063
}
2064
2065
#define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
2066
static int dib0090_tune(struct dvb_frontend *fe)
2067
{
2068
struct dib0090_state *state = fe->tuner_priv;
2069
const struct dib0090_tuning *tune = state->current_tune_table_index;
2070
const struct dib0090_pll *pll = state->current_pll_table_index;
2071
enum frontend_tune_state *tune_state = &state->tune_state;
2072
2073
u16 lo5, lo6, Den, tmp;
2074
u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
2075
int ret = 10; /* 1ms is the default delay most of the time */
2076
u8 c, i;
2077
2078
/************************* VCO ***************************/
2079
/* Default values for FG */
2080
/* from these are needed : */
2081
/* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */
2082
2083
/* in any case we first need to do a calibration if needed */
2084
if (*tune_state == CT_TUNER_START) {
2085
/* deactivate DataTX before some calibrations */
2086
if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL))
2087
dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
2088
else
2089
/* Activate DataTX in case a calibration has been done before */
2090
if (state->config->analog_output == 0)
2091
dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2092
}
2093
2094
if (state->calibrate & DC_CAL)
2095
return dib0090_dc_offset_calibration(state, tune_state);
2096
else if (state->calibrate & WBD_CAL) {
2097
if (state->current_rf == 0)
2098
state->current_rf = state->fe->dtv_property_cache.frequency / 1000;
2099
return dib0090_wbd_calibration(state, tune_state);
2100
} else if (state->calibrate & TEMP_CAL)
2101
return dib0090_get_temperature(state, tune_state);
2102
else if (state->calibrate & CAPTRIM_CAL)
2103
return dib0090_captrim_search(state, tune_state);
2104
2105
if (*tune_state == CT_TUNER_START) {
2106
/* if soc and AGC pwm control, disengage mux to be able to R/W access to 0x01 register to set the right filter (cutoff_freq_select) during the tune sequence, otherwise, SOC SERPAR error when accessing to 0x01 */
2107
if (state->config->use_pwm_agc && state->identity.in_soc) {
2108
tmp = dib0090_read_reg(state, 0x39);
2109
if ((tmp >> 10) & 0x1)
2110
dib0090_write_reg(state, 0x39, tmp & ~(1 << 10));
2111
}
2112
2113
state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000);
2114
state->rf_request =
2115
state->fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
2116
BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->
2117
freq_offset_khz_vhf);
2118
2119
/* in ISDB-T 1seg we shift tuning frequency */
2120
if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1
2121
&& state->fe->dtv_property_cache.isdbt_partial_reception == 0)) {
2122
const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if;
2123
u8 found_offset = 0;
2124
u32 margin_khz = 100;
2125
2126
if (LUT_offset != NULL) {
2127
while (LUT_offset->RF_freq != 0xffff) {
2128
if (((state->rf_request > (LUT_offset->RF_freq - margin_khz))
2129
&& (state->rf_request < (LUT_offset->RF_freq + margin_khz)))
2130
&& LUT_offset->std == state->fe->dtv_property_cache.delivery_system) {
2131
state->rf_request += LUT_offset->offset_khz;
2132
found_offset = 1;
2133
break;
2134
}
2135
LUT_offset++;
2136
}
2137
}
2138
2139
if (found_offset == 0)
2140
state->rf_request += 400;
2141
}
2142
if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) {
2143
state->tuner_is_tuned = 0;
2144
state->current_rf = 0;
2145
state->current_standard = 0;
2146
2147
tune = dib0090_tuning_table;
2148
if (state->identity.p1g)
2149
tune = dib0090_p1g_tuning_table;
2150
2151
tmp = (state->identity.version >> 5) & 0x7;
2152
2153
if (state->identity.in_soc) {
2154
if (state->config->force_cband_input) { /* Use the CBAND input for all band */
2155
if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
2156
|| state->current_band & BAND_UHF) {
2157
state->current_band = BAND_CBAND;
2158
tune = dib0090_tuning_table_cband_7090;
2159
}
2160
} else { /* Use the CBAND input for all band under UHF */
2161
if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
2162
state->current_band = BAND_CBAND;
2163
tune = dib0090_tuning_table_cband_7090;
2164
}
2165
}
2166
} else
2167
if (tmp == 0x4 || tmp == 0x7) {
2168
/* CBAND tuner version for VHF */
2169
if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) {
2170
state->current_band = BAND_CBAND; /* Force CBAND */
2171
2172
tune = dib0090_tuning_table_fm_vhf_on_cband;
2173
if (state->identity.p1g)
2174
tune = dib0090_p1g_tuning_table_fm_vhf_on_cband;
2175
}
2176
}
2177
2178
pll = dib0090_pll_table;
2179
if (state->identity.p1g)
2180
pll = dib0090_p1g_pll_table;
2181
2182
/* Look for the interval */
2183
while (state->rf_request > tune->max_freq)
2184
tune++;
2185
while (state->rf_request > pll->max_freq)
2186
pll++;
2187
2188
state->current_tune_table_index = tune;
2189
state->current_pll_table_index = pll;
2190
2191
dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
2192
2193
VCOF_kHz = (pll->hfdiv * state->rf_request) * 2;
2194
2195
FREF = state->config->io.clock_khz;
2196
if (state->config->fref_clock_ratio != 0)
2197
FREF /= state->config->fref_clock_ratio;
2198
2199
FBDiv = (VCOF_kHz / pll->topresc / FREF);
2200
Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
2201
2202
if (Rest < LPF)
2203
Rest = 0;
2204
else if (Rest < 2 * LPF)
2205
Rest = 2 * LPF;
2206
else if (Rest > (FREF - LPF)) {
2207
Rest = 0;
2208
FBDiv += 1;
2209
} else if (Rest > (FREF - 2 * LPF))
2210
Rest = FREF - 2 * LPF;
2211
Rest = (Rest * 6528) / (FREF / 10);
2212
state->rest = Rest;
2213
2214
/* external loop filter, otherwise:
2215
* lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
2216
* lo6 = 0x0e34 */
2217
2218
if (Rest == 0) {
2219
if (pll->vco_band)
2220
lo5 = 0x049f;
2221
else
2222
lo5 = 0x041f;
2223
} else {
2224
if (pll->vco_band)
2225
lo5 = 0x049e;
2226
else if (state->config->analog_output)
2227
lo5 = 0x041d;
2228
else
2229
lo5 = 0x041c;
2230
}
2231
2232
if (state->identity.p1g) { /* Bias is done automatically in P1G */
2233
if (state->identity.in_soc) {
2234
if (state->identity.version == SOC_8090_P1G_11R1)
2235
lo5 = 0x46f;
2236
else
2237
lo5 = 0x42f;
2238
} else
2239
lo5 = 0x42c;
2240
}
2241
2242
lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */
2243
2244
if (!state->config->io.pll_int_loop_filt) {
2245
if (state->identity.in_soc)
2246
lo6 = 0xff98;
2247
else if (state->identity.p1g || (Rest == 0))
2248
lo6 = 0xfff8;
2249
else
2250
lo6 = 0xff28;
2251
} else
2252
lo6 = (state->config->io.pll_int_loop_filt << 3);
2253
2254
Den = 1;
2255
2256
if (Rest > 0) {
2257
if (state->config->analog_output)
2258
lo6 |= (1 << 2) | 2;
2259
else {
2260
if (state->identity.in_soc)
2261
lo6 |= (1 << 2) | 2;
2262
else
2263
lo6 |= (1 << 2) | 2;
2264
}
2265
Den = 255;
2266
}
2267
dib0090_write_reg(state, 0x15, (u16) FBDiv);
2268
if (state->config->fref_clock_ratio != 0)
2269
dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio);
2270
else
2271
dib0090_write_reg(state, 0x16, (Den << 8) | 1);
2272
dib0090_write_reg(state, 0x17, (u16) Rest);
2273
dib0090_write_reg(state, 0x19, lo5);
2274
dib0090_write_reg(state, 0x1c, lo6);
2275
2276
lo6 = tune->tuner_enable;
2277
if (state->config->analog_output)
2278
lo6 = (lo6 & 0xff9f) | 0x2;
2279
2280
dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL);
2281
2282
}
2283
2284
state->current_rf = state->rf_request;
2285
state->current_standard = state->fe->dtv_property_cache.delivery_system;
2286
2287
ret = 20;
2288
state->calibrate = CAPTRIM_CAL; /* captrim serach now */
2289
}
2290
2291
else if (*tune_state == CT_TUNER_STEP_0) { /* Warning : because of captrim cal, if you change this step, change it also in _cal.c file because it is the step following captrim cal state machine */
2292
const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
2293
2294
while (state->current_rf / 1000 > wbd->max_freq)
2295
wbd++;
2296
2297
dib0090_write_reg(state, 0x1e, 0x07ff);
2298
dprintk("Final Captrim: %d", (u32) state->fcaptrim);
2299
dprintk("HFDIV code: %d", (u32) pll->hfdiv_code);
2300
dprintk("VCO = %d", (u32) pll->vco_band);
2301
dprintk("VCOF in kHz: %d ((%d*%d) << 1))", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
2302
dprintk("REFDIV: %d, FREF: %d", (u32) 1, (u32) state->config->io.clock_khz);
2303
dprintk("FBDIV: %d, Rest: %d", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
2304
dprintk("Num: %d, Den: %d, SD: %d", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
2305
(u32) dib0090_read_reg(state, 0x1c) & 0x3);
2306
2307
#define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
2308
c = 4;
2309
i = 3;
2310
2311
if (wbd->wbd_gain != 0)
2312
c = wbd->wbd_gain;
2313
2314
state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1));
2315
dib0090_write_reg(state, 0x10, state->wbdmux);
2316
2317
if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
2318
dprintk("P1G : The cable band is selected and lna_tune = %d", tune->lna_tune);
2319
dib0090_write_reg(state, 0x09, tune->lna_bias);
2320
dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
2321
} else
2322
dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias);
2323
2324
dib0090_write_reg(state, 0x0c, tune->v2i);
2325
dib0090_write_reg(state, 0x0d, tune->mix);
2326
dib0090_write_reg(state, 0x0e, tune->load);
2327
*tune_state = CT_TUNER_STEP_1;
2328
2329
} else if (*tune_state == CT_TUNER_STEP_1) {
2330
/* initialize the lt gain register */
2331
state->rf_lt_def = 0x7c00;
2332
2333
dib0090_set_bandwidth(state);
2334
state->tuner_is_tuned = 1;
2335
2336
state->calibrate |= WBD_CAL;
2337
state->calibrate |= TEMP_CAL;
2338
*tune_state = CT_TUNER_STOP;
2339
} else
2340
ret = FE_CALLBACK_TIME_NEVER;
2341
return ret;
2342
}
2343
2344
static int dib0090_release(struct dvb_frontend *fe)
2345
{
2346
kfree(fe->tuner_priv);
2347
fe->tuner_priv = NULL;
2348
return 0;
2349
}
2350
2351
enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
2352
{
2353
struct dib0090_state *state = fe->tuner_priv;
2354
2355
return state->tune_state;
2356
}
2357
2358
EXPORT_SYMBOL(dib0090_get_tune_state);
2359
2360
int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
2361
{
2362
struct dib0090_state *state = fe->tuner_priv;
2363
2364
state->tune_state = tune_state;
2365
return 0;
2366
}
2367
2368
EXPORT_SYMBOL(dib0090_set_tune_state);
2369
2370
static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
2371
{
2372
struct dib0090_state *state = fe->tuner_priv;
2373
2374
*frequency = 1000 * state->current_rf;
2375
return 0;
2376
}
2377
2378
static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
2379
{
2380
struct dib0090_state *state = fe->tuner_priv;
2381
u32 ret;
2382
2383
state->tune_state = CT_TUNER_START;
2384
2385
do {
2386
ret = dib0090_tune(fe);
2387
if (ret != FE_CALLBACK_TIME_NEVER)
2388
msleep(ret / 10);
2389
else
2390
break;
2391
} while (state->tune_state != CT_TUNER_STOP);
2392
2393
return 0;
2394
}
2395
2396
static const struct dvb_tuner_ops dib0090_ops = {
2397
.info = {
2398
.name = "DiBcom DiB0090",
2399
.frequency_min = 45000000,
2400
.frequency_max = 860000000,
2401
.frequency_step = 1000,
2402
},
2403
.release = dib0090_release,
2404
2405
.init = dib0090_wakeup,
2406
.sleep = dib0090_sleep,
2407
.set_params = dib0090_set_params,
2408
.get_frequency = dib0090_get_frequency,
2409
};
2410
2411
static const struct dvb_tuner_ops dib0090_fw_ops = {
2412
.info = {
2413
.name = "DiBcom DiB0090",
2414
.frequency_min = 45000000,
2415
.frequency_max = 860000000,
2416
.frequency_step = 1000,
2417
},
2418
.release = dib0090_release,
2419
2420
.init = NULL,
2421
.sleep = NULL,
2422
.set_params = NULL,
2423
.get_frequency = NULL,
2424
};
2425
2426
static const struct dib0090_wbd_slope dib0090_wbd_table_default[] = {
2427
{470, 0, 250, 0, 100, 4},
2428
{860, 51, 866, 21, 375, 4},
2429
{1700, 0, 800, 0, 850, 4},
2430
{2900, 0, 250, 0, 100, 6},
2431
{0xFFFF, 0, 0, 0, 0, 0},
2432
};
2433
2434
struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2435
{
2436
struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
2437
if (st == NULL)
2438
return NULL;
2439
2440
st->config = config;
2441
st->i2c = i2c;
2442
st->fe = fe;
2443
fe->tuner_priv = st;
2444
2445
if (config->wbd == NULL)
2446
st->current_wbd_table = dib0090_wbd_table_default;
2447
else
2448
st->current_wbd_table = config->wbd;
2449
2450
if (dib0090_reset(fe) != 0)
2451
goto free_mem;
2452
2453
printk(KERN_INFO "DiB0090: successfully identified\n");
2454
memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
2455
2456
return fe;
2457
free_mem:
2458
kfree(st);
2459
fe->tuner_priv = NULL;
2460
return NULL;
2461
}
2462
2463
EXPORT_SYMBOL(dib0090_register);
2464
2465
struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2466
{
2467
struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);
2468
if (st == NULL)
2469
return NULL;
2470
2471
st->config = config;
2472
st->i2c = i2c;
2473
st->fe = fe;
2474
fe->tuner_priv = st;
2475
2476
if (dib0090_fw_reset_digital(fe, st->config) != 0)
2477
goto free_mem;
2478
2479
dprintk("DiB0090 FW: successfully identified");
2480
memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
2481
2482
return fe;
2483
free_mem:
2484
kfree(st);
2485
fe->tuner_priv = NULL;
2486
return NULL;
2487
}
2488
EXPORT_SYMBOL(dib0090_fw_register);
2489
2490
MODULE_AUTHOR("Patrick Boettcher <[email protected]>");
2491
MODULE_AUTHOR("Olivier Grenie <[email protected]>");
2492
MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
2493
MODULE_LICENSE("GPL");
2494
2495