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