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