1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/kernel.h>
28#include <linux/slab.h>
29#include <linux/i2c.h>
30#include <linux/mutex.h>
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
49#define CONFIG_SYS_DVBT
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
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
81
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
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
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
105#define MP005 0x4
106#define MP008 0x6
107#define MP009 0x7
108
109#define pgm_read_word(w) (*w)
110
111struct dc_calibration;
112
113struct dib0090_tuning {
114 u32 max_freq;
115 u8 switch_trim;
116 u8 lna_tune;
117 u16 lna_bias;
118 u16 v2i;
119 u16 mix;
120 u16 load;
121 u16 tuner_enable;
122};
123
124struct dib0090_pll {
125 u32 max_freq;
126 u8 vco_band;
127 u8 hfdiv_code;
128 u8 hfdiv;
129 u8 topresc;
130};
131
132struct dib0090_identity {
133 u8 version;
134 u8 product;
135 u8 p1g;
136 u8 in_soc;
137};
138
139struct dib0090_state {
140 struct i2c_adapter *i2c;
141 struct dvb_frontend *fe;
142 const struct dib0090_config *config;
143
144 u8 current_band;
145 enum frontend_tune_state tune_state;
146 u32 current_rf;
147
148 u16 wbd_offset;
149 s16 wbd_target;
150
151 s16 rf_gain_limit;
152 s16 current_gain;
153 u8 agc_step;
154
155 u16 gain[2];
156
157 const u16 *rf_ramp;
158 const u16 *bb_ramp;
159
160
161 u16 bb_1_def;
162 u16 rf_lt_def;
163 u16 gain_reg[4];
164
165
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
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;
195
196
197 struct i2c_msg msg[2];
198 u8 i2c_write_buffer[3];
199 u8 i2c_read_buffer[2];
200 struct mutex i2c_buffer_lock;
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;
208
209
210 struct i2c_msg msg;
211 u8 i2c_write_buffer[2];
212 u8 i2c_read_buffer[2];
213 struct mutex i2c_buffer_lock;
214};
215
216static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
217{
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
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) {
238 printk(KERN_WARNING "DiB0090 I2C read failed\n");
239 ret = 0;
240 } else
241 ret = (state->i2c_read_buffer[0] << 8)
242 | state->i2c_read_buffer[1];
243
244 mutex_unlock(&state->i2c_buffer_lock);
245 return ret;
246}
247
248static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
249{
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
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) {
268 printk(KERN_WARNING "DiB0090 I2C write failed\n");
269 ret = -EREMOTEIO;
270 } else
271 ret = 0;
272
273 mutex_unlock(&state->i2c_buffer_lock);
274 return ret;
275}
276
277static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
278{
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
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) {
294 printk(KERN_WARNING "DiB0090 I2C read failed\n");
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;
302}
303
304static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
305{
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
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) {
322 printk(KERN_WARNING "DiB0090 I2C write failed\n");
323 ret = -EREMOTEIO;
324 } else
325 ret = 0;
326
327 mutex_unlock(&state->i2c_buffer_lock);
328 return ret;
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
343static int dib0090_identify(struct dvb_frontend *fe)
344{
345 struct dib0090_state *state = fe->tuner_priv;
346 u16 v;
347 struct dib0090_identity *identity = &state->identity;
348
349 v = dib0090_read_reg(state, 0x1a);
350
351 identity->p1g = 0;
352 identity->in_soc = 0;
353
354 dprintk("Tuner identification (Version = 0x%04x)", v);
355
356
357 v &= ~KROSUS_PLL_LOCKED;
358
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 }
427 }
428
429 return 0;
430
431identification_error:
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
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
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
521identification_error:
522 return -EIO;
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;
528 u16 PllCfg, i, v;
529
530 HARD_RESET(state);
531 dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
532 if (cfg->in_soc)
533 return;
534
535 dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);
536
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 PllCfg = dib0090_read_reg(state, 0x21);
547
548
549 if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && (!cfg->in_soc)
550 && !cfg->io.pll_bypass) {
551
552
553 PllCfg |= (1 << 15);
554 dib0090_write_reg(state, 0x21, PllCfg);
555
556
557 PllCfg &= ~(1 << 13);
558 dib0090_write_reg(state, 0x21, PllCfg);
559
560
561 PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
562 dib0090_write_reg(state, 0x21, PllCfg);
563
564
565 PllCfg |= (1 << 13);
566 dib0090_write_reg(state, 0x21, PllCfg);
567
568
569 i = 100;
570 do {
571 v = !!(dib0090_read_reg(state, 0x1a) & 0x800);
572 if (v)
573 break;
574 } while (--i);
575
576 if (i == 0) {
577 dprintk("Pll: Unable to lock Pll");
578 return;
579 }
580
581
582 PllCfg &= ~(1 << 15);
583 dib0090_write_reg(state, 0x21, PllCfg);
584 }
585
586 if (cfg->io.pll_bypass) {
587 PllCfg |= (cfg->io.pll_bypass << 15);
588 dib0090_write_reg(state, 0x21, PllCfg);
589 }
590}
591
592static int dib0090_fw_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
593{
594 struct dib0090_fw_state *state = fe->tuner_priv;
595 u16 PllCfg;
596 u16 v;
597 int i;
598
599 dprintk("fw reset digital");
600 HARD_RESET(state);
601
602 dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
603 dib0090_fw_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);
604
605 dib0090_fw_write_reg(state, 0x20,
606 ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (cfg->data_tx_drv << 4) | cfg->ls_cfg_pad_drv);
607
608 v = (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 9) | (0 << 8) | (cfg->clkouttobamse << 4) | (0 << 2) | (0);
609 if (cfg->clkoutdrive != 0)
610 v |= cfg->clkoutdrive << 5;
611 else
612 v |= 7 << 5;
613
614 v |= 2 << 10;
615 dib0090_fw_write_reg(state, 0x23, v);
616
617
618 PllCfg = dib0090_fw_read_reg(state, 0x21);
619
620
621 if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && !cfg->io.pll_bypass) {
622
623
624 PllCfg |= (1 << 15);
625 dib0090_fw_write_reg(state, 0x21, PllCfg);
626
627
628 PllCfg &= ~(1 << 13);
629 dib0090_fw_write_reg(state, 0x21, PllCfg);
630
631
632 PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
633 dib0090_fw_write_reg(state, 0x21, PllCfg);
634
635
636 PllCfg |= (1 << 13);
637 dib0090_fw_write_reg(state, 0x21, PllCfg);
638
639
640 i = 100;
641 do {
642 v = !!(dib0090_fw_read_reg(state, 0x1a) & 0x800);
643 if (v)
644 break;
645 } while (--i);
646
647 if (i == 0) {
648 dprintk("Pll: Unable to lock Pll");
649 return -EIO;
650 }
651
652
653 PllCfg &= ~(1 << 15);
654 dib0090_fw_write_reg(state, 0x21, PllCfg);
655 }
656
657 if (cfg->io.pll_bypass) {
658 PllCfg |= (cfg->io.pll_bypass << 15);
659 dib0090_fw_write_reg(state, 0x21, PllCfg);
660 }
661
662 return dib0090_fw_identify(fe);
663}
664
665static int dib0090_wakeup(struct dvb_frontend *fe)
666{
667 struct dib0090_state *state = fe->tuner_priv;
668 if (state->config->sleep)
669 state->config->sleep(fe, 0);
670
671
672 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
673 return 0;
674}
675
676static int dib0090_sleep(struct dvb_frontend *fe)
677{
678 struct dib0090_state *state = fe->tuner_priv;
679 if (state->config->sleep)
680 state->config->sleep(fe, 1);
681 return 0;
682}
683
684void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
685{
686 struct dib0090_state *state = fe->tuner_priv;
687 if (fast)
688 dib0090_write_reg(state, 0x04, 0);
689 else
690 dib0090_write_reg(state, 0x04, 1);
691}
692
693EXPORT_SYMBOL(dib0090_dcc_freq);
694
695static const u16 bb_ramp_pwm_normal_socs[] = {
696 550,
697 (1<<9) | 8,
698 440,
699 (4 << 9) | 0,
700 (0 << 9) | 208,
701 (4 << 9) | 208,
702 (0 << 9) | 440,
703};
704
705static const u16 rf_ramp_pwm_cband_7090p[] = {
706 280,
707 18,
708 504,
709 (29 << 10) | 364,
710 (0 << 10) | 504,
711 (60 << 10) | 228,
712 (0 << 10) | 364,
713 (34 << 10) | 109,
714 (0 << 10) | 228,
715 (37 << 10) | 0,
716 (0 << 10) | 109,
717};
718
719static const u16 rf_ramp_pwm_cband_7090e_sensitivity[] = {
720 186,
721 40,
722 746,
723 (10 << 10) | 345,
724 (0 << 10) | 746,
725 (0 << 10) | 0,
726 (0 << 10) | 0,
727 (28 << 10) | 200,
728 (0 << 10) | 345,
729 (20 << 10) | 0,
730 (0 << 10) | 200,
731};
732
733static const u16 rf_ramp_pwm_cband_7090e_aci[] = {
734 86,
735 40,
736 345,
737 (0 << 10) | 0,
738 (0 << 10) | 0,
739 (0 << 10) | 0,
740 (0 << 10) | 0,
741 (28 << 10) | 200,
742 (0 << 10) | 345,
743 (20 << 10) | 0,
744 (0 << 10) | 200,
745};
746
747static const u16 rf_ramp_pwm_cband_8090[] = {
748 345,
749 29,
750 1000,
751 (35 << 10) | 772,
752 (0 << 10) | 1000,
753 (58 << 10) | 496,
754 (0 << 10) | 772,
755 (27 << 10) | 200,
756 (0 << 10) | 496,
757 (40 << 10) | 0,
758 (0 << 10) | 200,
759};
760
761static const u16 rf_ramp_pwm_uhf_7090[] = {
762 407,
763 13,
764 529,
765 (23 << 10) | 0,
766 (0 << 10) | 176,
767 (63 << 10) | 400,
768 (0 << 10) | 529,
769 (48 << 10) | 316,
770 (0 << 10) | 400,
771 (29 << 10) | 176,
772 (0 << 10) | 316,
773};
774
775static const u16 rf_ramp_pwm_uhf_8090[] = {
776 388,
777 26,
778 1008,
779 (11 << 10) | 0,
780 (0 << 10) | 369,
781 (41 << 10) | 809,
782 (0 << 10) | 1008,
783 (27 << 10) | 659,
784 (0 << 10) | 809,
785 (14 << 10) | 369,
786 (0 << 10) | 659,
787};
788
789
790static const u16 bb_ramp_pwm_normal[] = {
791 500,
792 8,
793 400,
794 (2 << 9) | 0,
795 (0 << 9) | 168,
796 (2 << 9) | 168,
797 (0 << 9) | 400,
798};
799
800static const u16 bb_ramp_pwm_boost[] = {
801 550,
802 8,
803 440,
804 (2 << 9) | 0,
805 (0 << 9) | 208,
806 (2 << 9) | 208,
807 (0 << 9) | 440,
808};
809
810static const u16 rf_ramp_pwm_cband[] = {
811 314,
812 33,
813 1023,
814 (8 << 10) | 743,
815 (0 << 10) | 1023,
816 (15 << 10) | 469,
817 (0 << 10) | 742,
818 (9 << 10) | 234,
819 (0 << 10) | 468,
820 (9 << 10) | 0,
821 (0 << 10) | 233,
822};
823
824static const u16 rf_ramp_pwm_vhf[] = {
825 398,
826 24,
827 954,
828 (7 << 10) | 0,
829 (0 << 10) | 290,
830 (16 << 10) | 699,
831 (0 << 10) | 954,
832 (17 << 10) | 580,
833 (0 << 10) | 699,
834 (7 << 10) | 290,
835 (0 << 10) | 580,
836};
837
838static const u16 rf_ramp_pwm_uhf[] = {
839 398,
840 24,
841 954,
842 (7 << 10) | 0,
843 (0 << 10) | 290,
844 (16 << 10) | 699,
845 (0 << 10) | 954,
846 (17 << 10) | 580,
847 (0 << 10) | 699,
848 (7 << 10) | 290,
849 (0 << 10) | 580,
850};
851
852static const u16 rf_ramp_pwm_sband[] = {
853 253,
854 38,
855 961,
856 (4 << 10) | 0,
857 (0 << 10) | 508,
858 (9 << 10) | 508,
859 (0 << 10) | 961,
860 (0 << 10) | 0,
861 (0 << 10) | 0,
862 (0 << 10) | 0,
863 (0 << 10) | 0,
864};
865
866struct slope {
867 s16 range;
868 s16 slope;
869};
870static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
871{
872 u8 i;
873 u16 rest;
874 u16 ret = 0;
875 for (i = 0; i < num; i++) {
876 if (val > slopes[i].range)
877 rest = slopes[i].range;
878 else
879 rest = val;
880 ret += (rest * slopes[i].slope) / slopes[i].range;
881 val -= rest;
882 }
883 return ret;
884}
885
886static const struct slope dib0090_wbd_slopes[3] = {
887 {66, 120},
888 {600, 170},
889 {170, 250},
890};
891
892static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
893{
894 wbd &= 0x3ff;
895 if (wbd < state->wbd_offset)
896 wbd = 0;
897 else
898 wbd -= state->wbd_offset;
899
900 return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
901}
902
903static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
904{
905 u16 offset = 250;
906
907
908
909 if (state->current_band == BAND_VHF)
910 offset = 650;
911#ifndef FIRMWARE_FIREFLY
912 if (state->current_band == BAND_VHF)
913 offset = state->config->wbd_vhf_offset;
914 if (state->current_band == BAND_CBAND)
915 offset = state->config->wbd_cband_offset;
916#endif
917
918 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
919 dprintk("wbd-target: %d dB", (u32) state->wbd_target);
920}
921
922static const int gain_reg_addr[4] = {
923 0x08, 0x0a, 0x0f, 0x01
924};
925
926static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
927{
928 u16 rf, bb, ref;
929 u16 i, v, gain_reg[4] = { 0 }, gain;
930 const u16 *g;
931
932 if (top_delta < -511)
933 top_delta = -511;
934 if (top_delta > 511)
935 top_delta = 511;
936
937 if (force) {
938 top_delta *= (1 << WBD_ALPHA);
939 gain_delta *= (1 << GAIN_ALPHA);
940 }
941
942 if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit))
943 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
944 else
945 state->rf_gain_limit += top_delta;
946
947 if (state->rf_gain_limit < 0)
948 state->rf_gain_limit = 0;
949
950
951 gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
952 if (gain_delta >= ((s16) gain - state->current_gain))
953 state->current_gain = gain;
954 else
955 state->current_gain += gain_delta;
956
957 if (state->current_gain < 0)
958 state->current_gain = 0;
959
960
961 gain = state->current_gain >> GAIN_ALPHA;
962
963
964 if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
965 rf = state->rf_gain_limit >> WBD_ALPHA;
966 bb = gain - rf;
967 if (bb > state->bb_ramp[0])
968 bb = state->bb_ramp[0];
969 } else {
970 rf = gain;
971 bb = 0;
972 }
973
974 state->gain[0] = rf;
975 state->gain[1] = bb;
976
977
978
979 g = state->rf_ramp + 1;
980 ref = rf;
981 for (i = 0; i < 7; i++) {
982 if (g[0] == 0 || ref < (g[1] - g[0]))
983 v = 0;
984 else if (ref >= g[1])
985 v = g[2];
986 else
987 v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
988
989 if (i == 0)
990 gain_reg[0] = v;
991 else if (i == 1)
992 gain_reg[0] |= v << 7;
993 else if (i == 2)
994 gain_reg[1] = v;
995 else if (i == 3)
996 gain_reg[1] |= v << 7;
997 else if (i == 4)
998 gain_reg[2] = v | state->rf_lt_def;
999 else if (i == 5)
1000 gain_reg[3] = v << 3;
1001 else if (i == 6)
1002 gain_reg[3] |= v << 8;
1003
1004 g += 3;
1005
1006
1007 if (i == 4) {
1008 g = state->bb_ramp + 1;
1009 ref = bb;
1010 }
1011 }
1012 gain_reg[3] |= state->bb_1_def;
1013 gain_reg[3] |= ((bb % 10) * 100) / 125;
1014
1015#ifdef DEBUG_AGC
1016 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,
1017 gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
1018#endif
1019
1020
1021 for (i = 0; i < 4; i++) {
1022 v = gain_reg[i];
1023 if (force || state->gain_reg[i] != v) {
1024 state->gain_reg[i] = v;
1025 dib0090_write_reg(state, gain_reg_addr[i], v);
1026 }
1027 }
1028}
1029
1030static void dib0090_set_boost(struct dib0090_state *state, int onoff)
1031{
1032 state->bb_1_def &= 0xdfff;
1033 state->bb_1_def |= onoff << 13;
1034}
1035
1036static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
1037{
1038 state->rf_ramp = cfg;
1039}
1040
1041static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
1042{
1043 state->rf_ramp = cfg;
1044
1045 dib0090_write_reg(state, 0x2a, 0xffff);
1046
1047 dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
1048
1049 dib0090_write_regs(state, 0x2c, cfg + 3, 6);
1050 dib0090_write_regs(state, 0x3e, cfg + 9, 2);
1051}
1052
1053static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
1054{
1055 state->bb_ramp = cfg;
1056 dib0090_set_boost(state, cfg[0] > 500);
1057}
1058
1059static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
1060{
1061 state->bb_ramp = cfg;
1062
1063 dib0090_set_boost(state, cfg[0] > 500);
1064
1065 dib0090_write_reg(state, 0x33, 0xffff);
1066 dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33));
1067 dib0090_write_regs(state, 0x35, cfg + 3, 4);
1068}
1069
1070void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
1071{
1072 struct dib0090_state *state = fe->tuner_priv;
1073 u16 *bb_ramp = (u16 *)&bb_ramp_pwm_normal;
1074 u16 *rf_ramp = NULL;
1075 u8 en_pwm_rf_mux = 1;
1076
1077
1078 if (state->config->use_pwm_agc) {
1079 if (state->current_band == BAND_CBAND) {
1080 if (state->identity.in_soc) {
1081 bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1082 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1083 rf_ramp = (u16 *)&rf_ramp_pwm_cband_8090;
1084 else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) {
1085 if (state->config->is_dib7090e) {
1086 if (state->rf_ramp == NULL)
1087 rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
1088 else
1089 rf_ramp = (u16 *)state->rf_ramp;
1090 } else
1091 rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090p;
1092 }
1093 } else
1094 rf_ramp = (u16 *)&rf_ramp_pwm_cband;
1095 } else
1096
1097 if (state->current_band == BAND_VHF) {
1098 if (state->identity.in_soc) {
1099 bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1100
1101 } else
1102 rf_ramp = (u16 *)&rf_ramp_pwm_vhf;
1103 } else if (state->current_band == BAND_UHF) {
1104 if (state->identity.in_soc) {
1105 bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1106 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1107 rf_ramp = (u16 *)&rf_ramp_pwm_uhf_8090;
1108 else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1109 rf_ramp = (u16 *)&rf_ramp_pwm_uhf_7090;
1110 } else
1111 rf_ramp = (u16 *)&rf_ramp_pwm_uhf;
1112 }
1113 if (rf_ramp)
1114 dib0090_set_rframp_pwm(state, rf_ramp);
1115 dib0090_set_bbramp_pwm(state, bb_ramp);
1116
1117
1118 dprintk("ramp RF gain = %d BAND = %s version = %d", state->rf_ramp[0], (state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND", state->identity.version & 0x1f);
1119
1120 if ((state->rf_ramp[0] == 0) || (state->current_band == BAND_CBAND && (state->identity.version & 0x1f) <= P1D_E_F)) {
1121 dprintk("DE-Engage mux for direct gain reg control");
1122 en_pwm_rf_mux = 0;
1123 } else
1124 dprintk("Engage mux for PWM control");
1125
1126 dib0090_write_reg(state, 0x32, (en_pwm_rf_mux << 12) | (en_pwm_rf_mux << 11));
1127
1128
1129 if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1130 dib0090_write_reg(state, 0x04, 3);
1131 else
1132 dib0090_write_reg(state, 0x04, 1);
1133 dib0090_write_reg(state, 0x39, (1 << 10));
1134 }
1135}
1136EXPORT_SYMBOL(dib0090_pwm_gain_reset);
1137
1138void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
1139{
1140 struct dib0090_state *state = fe->tuner_priv;
1141 if (DC_servo_cutoff < 4)
1142 dib0090_write_reg(state, 0x04, DC_servo_cutoff);
1143}
1144EXPORT_SYMBOL(dib0090_set_dc_servo);
1145
1146static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
1147{
1148 u16 adc_val = dib0090_read_reg(state, 0x1d);
1149 if (state->identity.in_soc)
1150 adc_val >>= 2;
1151 return adc_val;
1152}
1153
1154int dib0090_gain_control(struct dvb_frontend *fe)
1155{
1156 struct dib0090_state *state = fe->tuner_priv;
1157 enum frontend_tune_state *tune_state = &state->tune_state;
1158 int ret = 10;
1159
1160 u16 wbd_val = 0;
1161 u8 apply_gain_immediatly = 1;
1162 s16 wbd_error = 0, adc_error = 0;
1163
1164 if (*tune_state == CT_AGC_START) {
1165 state->agc_freeze = 0;
1166 dib0090_write_reg(state, 0x04, 0x0);
1167
1168#ifdef CONFIG_BAND_SBAND
1169 if (state->current_band == BAND_SBAND) {
1170 dib0090_set_rframp(state, rf_ramp_sband);
1171 dib0090_set_bbramp(state, bb_ramp_boost);
1172 } else
1173#endif
1174#ifdef CONFIG_BAND_VHF
1175 if (state->current_band == BAND_VHF && !state->identity.p1g) {
1176 dib0090_set_rframp(state, rf_ramp_pwm_vhf);
1177 dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1178 } else
1179#endif
1180#ifdef CONFIG_BAND_CBAND
1181 if (state->current_band == BAND_CBAND && !state->identity.p1g) {
1182 dib0090_set_rframp(state, rf_ramp_pwm_cband);
1183 dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1184 } else
1185#endif
1186 if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
1187 dib0090_set_rframp(state, rf_ramp_pwm_cband_7090p);
1188 dib0090_set_bbramp(state, bb_ramp_pwm_normal_socs);
1189 } else {
1190 dib0090_set_rframp(state, rf_ramp_pwm_uhf);
1191 dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1192 }
1193
1194 dib0090_write_reg(state, 0x32, 0);
1195 dib0090_write_reg(state, 0x39, 0);
1196
1197 dib0090_wbd_target(state, state->current_rf);
1198
1199 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
1200 state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
1201
1202 *tune_state = CT_AGC_STEP_0;
1203 } else if (!state->agc_freeze) {
1204 s16 wbd = 0, i, cnt;
1205
1206 int adc;
1207 wbd_val = dib0090_get_slow_adc_val(state);
1208
1209 if (*tune_state == CT_AGC_STEP_0)
1210 cnt = 5;
1211 else
1212 cnt = 1;
1213
1214 for (i = 0; i < cnt; i++) {
1215 wbd_val = dib0090_get_slow_adc_val(state);
1216 wbd += dib0090_wbd_to_db(state, wbd_val);
1217 }
1218 wbd /= cnt;
1219 wbd_error = state->wbd_target - wbd;
1220
1221 if (*tune_state == CT_AGC_STEP_0) {
1222 if (wbd_error < 0 && state->rf_gain_limit > 0 && !state->identity.p1g) {
1223#ifdef CONFIG_BAND_CBAND
1224
1225 u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
1226 if (state->current_band == BAND_CBAND && ltg2) {
1227 ltg2 >>= 1;
1228 state->rf_lt_def &= ltg2 << 10;
1229 }
1230#endif
1231 } else {
1232 state->agc_step = 0;
1233 *tune_state = CT_AGC_STEP_1;
1234 }
1235 } else {
1236
1237 adc = state->config->get_adc_power(fe);
1238 adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21;
1239
1240 adc_error = (s16) (((s32) ADC_TARGET) - adc);
1241#ifdef CONFIG_STANDARD_DAB
1242 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
1243 adc_error -= 10;
1244#endif
1245#ifdef CONFIG_STANDARD_DVBT
1246 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
1247 (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
1248 adc_error += 60;
1249#endif
1250#ifdef CONFIG_SYS_ISDBT
1251 if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
1252 0)
1253 &&
1254 ((state->fe->dtv_property_cache.layer[0].modulation ==
1255 QAM_64)
1256 || (state->fe->dtv_property_cache.
1257 layer[0].modulation == QAM_16)))
1258 ||
1259 ((state->fe->dtv_property_cache.layer[1].segment_count >
1260 0)
1261 &&
1262 ((state->fe->dtv_property_cache.layer[1].modulation ==
1263 QAM_64)
1264 || (state->fe->dtv_property_cache.
1265 layer[1].modulation == QAM_16)))
1266 ||
1267 ((state->fe->dtv_property_cache.layer[2].segment_count >
1268 0)
1269 &&
1270 ((state->fe->dtv_property_cache.layer[2].modulation ==
1271 QAM_64)
1272 || (state->fe->dtv_property_cache.
1273 layer[2].modulation == QAM_16)))
1274 )
1275 )
1276 adc_error += 60;
1277#endif
1278
1279 if (*tune_state == CT_AGC_STEP_1) {
1280 if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
1281
1282#ifdef CONFIG_STANDARD_DAB
1283 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
1284 dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63));
1285 dib0090_write_reg(state, 0x04, 0x0);
1286 } else
1287#endif
1288 {
1289 dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
1290 dib0090_write_reg(state, 0x04, 0x01);
1291 }
1292
1293 *tune_state = CT_AGC_STOP;
1294 }
1295 } else {
1296
1297 ret = 100;
1298 apply_gain_immediatly = 0;
1299 }
1300 }
1301#ifdef DEBUG_AGC
1302 dprintk
1303 ("tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
1304 (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
1305 (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
1306#endif
1307 }
1308
1309
1310 if (!state->agc_freeze)
1311 dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
1312 return ret;
1313}
1314
1315EXPORT_SYMBOL(dib0090_gain_control);
1316
1317void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
1318{
1319 struct dib0090_state *state = fe->tuner_priv;
1320 if (rf)
1321 *rf = state->gain[0];
1322 if (bb)
1323 *bb = state->gain[1];
1324 if (rf_gain_limit)
1325 *rf_gain_limit = state->rf_gain_limit;
1326 if (rflt)
1327 *rflt = (state->rf_lt_def >> 10) & 0x7;
1328}
1329
1330EXPORT_SYMBOL(dib0090_get_current_gain);
1331
1332u16 dib0090_get_wbd_target(struct dvb_frontend *fe)
1333{
1334 struct dib0090_state *state = fe->tuner_priv;
1335 u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
1336 s32 current_temp = state->temperature;
1337 s32 wbd_thot, wbd_tcold;
1338 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1339
1340 while (f_MHz > wbd->max_freq)
1341 wbd++;
1342
1343 dprintk("using wbd-table-entry with max freq %d", wbd->max_freq);
1344
1345 if (current_temp < 0)
1346 current_temp = 0;
1347 if (current_temp > 128)
1348 current_temp = 128;
1349
1350 state->wbdmux &= ~(7 << 13);
1351 if (wbd->wbd_gain != 0)
1352 state->wbdmux |= (wbd->wbd_gain << 13);
1353 else
1354 state->wbdmux |= (4 << 13);
1355
1356 dib0090_write_reg(state, 0x10, state->wbdmux);
1357
1358 wbd_thot = wbd->offset_hot - (((u32) wbd->slope_hot * f_MHz) >> 6);
1359 wbd_tcold = wbd->offset_cold - (((u32) wbd->slope_cold * f_MHz) >> 6);
1360
1361 wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7;
1362
1363 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold);
1364 dprintk("wbd-target: %d dB", (u32) state->wbd_target);
1365 dprintk("wbd offset applied is %d", wbd_tcold);
1366
1367 return state->wbd_offset + wbd_tcold;
1368}
1369EXPORT_SYMBOL(dib0090_get_wbd_target);
1370
1371u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
1372{
1373 struct dib0090_state *state = fe->tuner_priv;
1374 return state->wbd_offset;
1375}
1376EXPORT_SYMBOL(dib0090_get_wbd_offset);
1377
1378int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3)
1379{
1380 struct dib0090_state *state = fe->tuner_priv;
1381
1382 dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xfff8)
1383 | ((sw3 & 1) << 2) | ((sw2 & 1) << 1) | (sw1 & 1));
1384
1385 return 0;
1386}
1387EXPORT_SYMBOL(dib0090_set_switch);
1388
1389int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
1390{
1391 struct dib0090_state *state = fe->tuner_priv;
1392
1393 dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x7fff)
1394 | ((onoff & 1) << 15));
1395 return 0;
1396}
1397EXPORT_SYMBOL(dib0090_set_vga);
1398
1399int dib0090_update_rframp_7090(struct dvb_frontend *fe, u8 cfg_sensitivity)
1400{
1401 struct dib0090_state *state = fe->tuner_priv;
1402
1403 if ((!state->identity.p1g) || (!state->identity.in_soc)
1404 || ((state->identity.version != SOC_7090_P1G_21R1)
1405 && (state->identity.version != SOC_7090_P1G_11R1))) {
1406 dprintk("%s() function can only be used for dib7090P", __func__);
1407 return -ENODEV;
1408 }
1409
1410 if (cfg_sensitivity)
1411 state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
1412 else
1413 state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_aci;
1414 dib0090_pwm_gain_reset(fe);
1415
1416 return 0;
1417}
1418EXPORT_SYMBOL(dib0090_update_rframp_7090);
1419
1420static const u16 dib0090_defaults[] = {
1421
1422 25, 0x01,
1423 0x0000,
1424 0x99a0,
1425 0x6008,
1426 0x0000,
1427 0x8bcb,
1428 0x0000,
1429 0x0405,
1430 0x0000,
1431 0x0000,
1432 0x0000,
1433 0xb802,
1434 0x0300,
1435 0x2d12,
1436 0xbac0,
1437 0x7c00,
1438 0xdbb9,
1439 0x0954,
1440 0x0743,
1441 0x8000,
1442 0x0001,
1443 0x0040,
1444 0x0100,
1445 0x0000,
1446 0xe910,
1447 0x149e,
1448
1449 1, 0x1c,
1450 0xff2d,
1451
1452 1, 0x39,
1453 0x0000,
1454
1455 2, 0x1e,
1456 0x07FF,
1457 0x0007,
1458
1459 1, 0x24,
1460 EN_UHF | EN_CRYSTAL,
1461
1462 2, 0x3c,
1463 0x3ff,
1464 0x111,
1465 0
1466};
1467
1468static const u16 dib0090_p1g_additionnal_defaults[] = {
1469 1, 0x05,
1470 0xabcd,
1471
1472 1, 0x11,
1473 0x00b4,
1474
1475 1, 0x1c,
1476 0xfffd,
1477
1478 1, 0x40,
1479 0x108,
1480 0
1481};
1482
1483static void dib0090_set_default_config(struct dib0090_state *state, const u16 * n)
1484{
1485 u16 l, r;
1486
1487 l = pgm_read_word(n++);
1488 while (l) {
1489 r = pgm_read_word(n++);
1490 do {
1491 dib0090_write_reg(state, r, pgm_read_word(n++));
1492 r++;
1493 } while (--l);
1494 l = pgm_read_word(n++);
1495 }
1496}
1497
1498#define CAP_VALUE_MIN (u8) 9
1499#define CAP_VALUE_MAX (u8) 40
1500#define HR_MIN (u8) 25
1501#define HR_MAX (u8) 40
1502#define POLY_MIN (u8) 0
1503#define POLY_MAX (u8) 8
1504
1505static void dib0090_set_EFUSE(struct dib0090_state *state)
1506{
1507 u8 c, h, n;
1508 u16 e2, e4;
1509 u16 cal;
1510
1511 e2 = dib0090_read_reg(state, 0x26);
1512 e4 = dib0090_read_reg(state, 0x28);
1513
1514 if ((state->identity.version == P1D_E_F) ||
1515 (state->identity.version == P1G) || (e2 == 0xffff)) {
1516
1517 dib0090_write_reg(state, 0x22, 0x10);
1518 cal = (dib0090_read_reg(state, 0x22) >> 6) & 0x3ff;
1519
1520 if ((cal < 670) || (cal == 1023))
1521 cal = 850;
1522 n = 165 - ((cal * 10)>>6) ;
1523 e2 = e4 = (3<<12) | (34<<6) | (n);
1524 }
1525
1526 if (e2 != e4)
1527 e2 &= e4;
1528
1529 if (e2 != 0xffff) {
1530 c = e2 & 0x3f;
1531 n = (e2 >> 12) & 0xf;
1532 h = (e2 >> 6) & 0x3f;
1533
1534 if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
1535 c = 32;
1536 else
1537 c += 14;
1538 if ((h >= HR_MAX) || (h <= HR_MIN))
1539 h = 34;
1540 if ((n >= POLY_MAX) || (n <= POLY_MIN))
1541 n = 3;
1542
1543 dib0090_write_reg(state, 0x13, (h << 10));
1544 e2 = (n << 11) | ((h >> 2)<<6) | c;
1545 dib0090_write_reg(state, 0x2, e2);
1546 }
1547}
1548
1549static int dib0090_reset(struct dvb_frontend *fe)
1550{
1551 struct dib0090_state *state = fe->tuner_priv;
1552
1553 dib0090_reset_digital(fe, state->config);
1554 if (dib0090_identify(fe) < 0)
1555 return -EIO;
1556
1557#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
1558 if (!(state->identity.version & 0x1))
1559 return 0;
1560#endif
1561
1562 if (!state->identity.in_soc) {
1563 if ((dib0090_read_reg(state, 0x1a) >> 5) & 0x2)
1564 dib0090_write_reg(state, 0x1b, (EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1565 else
1566 dib0090_write_reg(state, 0x1b, (EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1567 }
1568
1569 dib0090_set_default_config(state, dib0090_defaults);
1570
1571 if (state->identity.in_soc)
1572 dib0090_write_reg(state, 0x18, 0x2910);
1573
1574 if (state->identity.p1g)
1575 dib0090_set_default_config(state, dib0090_p1g_additionnal_defaults);
1576
1577
1578 if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
1579 dib0090_set_EFUSE(state);
1580
1581
1582 if (state->config->force_crystal_mode != 0)
1583 dib0090_write_reg(state, 0x14,
1584 state->config->force_crystal_mode & 3);
1585 else if (state->config->io.clock_khz >= 24000)
1586 dib0090_write_reg(state, 0x14, 1);
1587 else
1588 dib0090_write_reg(state, 0x14, 2);
1589 dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
1590
1591 state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL;
1592
1593 return 0;
1594}
1595
1596#define steps(u) (((u) > 15) ? ((u)-16) : (u))
1597#define INTERN_WAIT 10
1598static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1599{
1600 int ret = INTERN_WAIT * 10;
1601
1602 switch (*tune_state) {
1603 case CT_TUNER_STEP_2:
1604
1605 dib0090_write_reg(state, 0x1f, 0x7);
1606 *tune_state = CT_TUNER_STEP_3;
1607 break;
1608
1609 case CT_TUNER_STEP_3:
1610 state->adc_diff = dib0090_read_reg(state, 0x1d);
1611
1612
1613 dib0090_write_reg(state, 0x1f, 0x4);
1614 *tune_state = CT_TUNER_STEP_4;
1615 break;
1616
1617 case CT_TUNER_STEP_4:
1618 state->adc_diff -= dib0090_read_reg(state, 0x1d);
1619 *tune_state = CT_TUNER_STEP_5;
1620 ret = 0;
1621 break;
1622
1623 default:
1624 break;
1625 }
1626
1627 return ret;
1628}
1629
1630struct dc_calibration {
1631 u8 addr;
1632 u8 offset;
1633 u8 pga:1;
1634 u16 bb1;
1635 u8 i:1;
1636};
1637
1638static const struct dc_calibration dc_table[] = {
1639
1640 {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
1641 {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
1642
1643 {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
1644 {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
1645 {0},
1646};
1647
1648static const struct dc_calibration dc_p1g_table[] = {
1649
1650
1651 {0x06, 5, 1, (1 << 13) | (0 << 8) | (15 << 3), 1},
1652 {0x07, 11, 1, (1 << 13) | (0 << 8) | (15 << 3), 0},
1653
1654 {0x06, 0, 0, (1 << 13) | (29 << 8) | (15 << 3), 1},
1655 {0x06, 10, 0, (1 << 13) | (29 << 8) | (15 << 3), 0},
1656 {0},
1657};
1658
1659static void dib0090_set_trim(struct dib0090_state *state)
1660{
1661 u16 *val;
1662
1663 if (state->dc->addr == 0x07)
1664 val = &state->bb7;
1665 else
1666 val = &state->bb6;
1667
1668 *val &= ~(0x1f << state->dc->offset);
1669 *val |= state->step << state->dc->offset;
1670
1671 dib0090_write_reg(state, state->dc->addr, *val);
1672}
1673
1674static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1675{
1676 int ret = 0;
1677 u16 reg;
1678
1679 switch (*tune_state) {
1680 case CT_TUNER_START:
1681 dprintk("Start DC offset calibration");
1682
1683
1684 state->bb6 = 0;
1685 state->bb7 = 0x040d;
1686
1687
1688 reg = dib0090_read_reg(state, 0x24) & 0x0ffb;
1689 dib0090_write_reg(state, 0x24, reg);
1690
1691 state->wbdmux = dib0090_read_reg(state, 0x10);
1692 dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x7 << 3) | 0x3);
1693 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
1694
1695 state->dc = dc_table;
1696
1697 if (state->identity.p1g)
1698 state->dc = dc_p1g_table;
1699 *tune_state = CT_TUNER_STEP_0;
1700
1701
1702
1703 case CT_TUNER_STEP_0:
1704 dprintk("Sart/continue DC calibration for %s path", (state->dc->i == 1) ? "I" : "Q");
1705 dib0090_write_reg(state, 0x01, state->dc->bb1);
1706 dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
1707
1708 state->step = 0;
1709 state->min_adc_diff = 1023;
1710 *tune_state = CT_TUNER_STEP_1;
1711 ret = 50;
1712 break;
1713
1714 case CT_TUNER_STEP_1:
1715 dib0090_set_trim(state);
1716 *tune_state = CT_TUNER_STEP_2;
1717 break;
1718
1719 case CT_TUNER_STEP_2:
1720 case CT_TUNER_STEP_3:
1721 case CT_TUNER_STEP_4:
1722 ret = dib0090_get_offset(state, tune_state);
1723 break;
1724
1725 case CT_TUNER_STEP_5:
1726 dprintk("adc_diff = %d, current step= %d", (u32) state->adc_diff, state->step);
1727 if (state->step == 0 && state->adc_diff < 0) {
1728 state->min_adc_diff = -1023;
1729 dprintk("Change of sign of the minimum adc diff");
1730 }
1731
1732 dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d", state->adc_diff, state->min_adc_diff, state->step);
1733
1734
1735 if (state->step == 0) {
1736 if (state->dc->pga && state->adc_diff < 0)
1737 state->step = 0x10;
1738 if (state->dc->pga == 0 && state->adc_diff > 0)
1739 state->step = 0x10;
1740 }
1741
1742
1743 if ((state->adc_diff & 0x8000) == (state->min_adc_diff & 0x8000) && steps(state->step) < 15) {
1744
1745 state->step++;
1746 state->min_adc_diff = state->adc_diff;
1747 *tune_state = CT_TUNER_STEP_1;
1748 } else {
1749
1750 if (ABS(state->adc_diff) > ABS(state->min_adc_diff)) {
1751 dprintk("Since adc_diff N = %d > adc_diff step N-1 = %d, Come back one step", state->adc_diff, state->min_adc_diff);
1752 state->step--;
1753 }
1754
1755 dib0090_set_trim(state);
1756 dprintk("BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->dc->addr, state->adc_diff, state->step);
1757
1758 state->dc++;
1759 if (state->dc->addr == 0)
1760 *tune_state = CT_TUNER_STEP_6;
1761 else
1762 *tune_state = CT_TUNER_STEP_0;
1763
1764 }
1765 break;
1766
1767 case CT_TUNER_STEP_6:
1768 dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
1769 dib0090_write_reg(state, 0x1f, 0x7);
1770 *tune_state = CT_TUNER_START;
1771 state->calibrate &= ~DC_CAL;
1772 default:
1773 break;
1774 }
1775 return ret;
1776}
1777
1778static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1779{
1780 u8 wbd_gain;
1781 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1782
1783 switch (*tune_state) {
1784 case CT_TUNER_START:
1785 while (state->current_rf / 1000 > wbd->max_freq)
1786 wbd++;
1787 if (wbd->wbd_gain != 0)
1788 wbd_gain = wbd->wbd_gain;
1789 else {
1790 wbd_gain = 4;
1791#if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
1792 if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND))
1793 wbd_gain = 2;
1794#endif
1795 }
1796
1797 if (wbd_gain == state->wbd_calibration_gain) {
1798 *tune_state = CT_TUNER_START;
1799 state->calibrate &= ~WBD_CAL;
1800 return 0;
1801 }
1802
1803 dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3));
1804
1805 dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1)));
1806 *tune_state = CT_TUNER_STEP_0;
1807 state->wbd_calibration_gain = wbd_gain;
1808 return 90;
1809
1810 case CT_TUNER_STEP_0:
1811 state->wbd_offset = dib0090_get_slow_adc_val(state);
1812 dprintk("WBD calibration offset = %d", state->wbd_offset);
1813 *tune_state = CT_TUNER_START;
1814 state->calibrate &= ~WBD_CAL;
1815 break;
1816
1817 default:
1818 break;
1819 }
1820 return 0;
1821}
1822
1823static void dib0090_set_bandwidth(struct dib0090_state *state)
1824{
1825 u16 tmp;
1826
1827 if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
1828 tmp = (3 << 14);
1829 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
1830 tmp = (2 << 14);
1831 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
1832 tmp = (1 << 14);
1833 else
1834 tmp = (0 << 14);
1835
1836 state->bb_1_def &= 0x3fff;
1837 state->bb_1_def |= tmp;
1838
1839 dib0090_write_reg(state, 0x01, state->bb_1_def);
1840
1841 dib0090_write_reg(state, 0x03, 0x6008);
1842 dib0090_write_reg(state, 0x04, 0x1);
1843 if (state->identity.in_soc) {
1844 dib0090_write_reg(state, 0x05, 0x9bcf);
1845 } else {
1846 dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f));
1847 dib0090_write_reg(state, 0x05, 0xabcd);
1848 }
1849}
1850
1851static const struct dib0090_pll dib0090_pll_table[] = {
1852#ifdef CONFIG_BAND_CBAND
1853 {56000, 0, 9, 48, 6},
1854 {70000, 1, 9, 48, 6},
1855 {87000, 0, 8, 32, 4},
1856 {105000, 1, 8, 32, 4},
1857 {115000, 0, 7, 24, 6},
1858 {140000, 1, 7, 24, 6},
1859 {170000, 0, 6, 16, 4},
1860#endif
1861#ifdef CONFIG_BAND_VHF
1862 {200000, 1, 6, 16, 4},
1863 {230000, 0, 5, 12, 6},
1864 {280000, 1, 5, 12, 6},
1865 {340000, 0, 4, 8, 4},
1866 {380000, 1, 4, 8, 4},
1867 {450000, 0, 3, 6, 6},
1868#endif
1869#ifdef CONFIG_BAND_UHF
1870 {580000, 1, 3, 6, 6},
1871 {700000, 0, 2, 4, 4},
1872 {860000, 1, 2, 4, 4},
1873#endif
1874#ifdef CONFIG_BAND_LBAND
1875 {1800000, 1, 0, 2, 4},
1876#endif
1877#ifdef CONFIG_BAND_SBAND
1878 {2900000, 0, 14, 1, 4},
1879#endif
1880};
1881
1882static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1883
1884#ifdef CONFIG_BAND_CBAND
1885 {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1886 {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1887 {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1888#endif
1889#ifdef CONFIG_BAND_UHF
1890 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1891 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1892 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1893 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1894 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1895 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1896#endif
1897#ifdef CONFIG_BAND_LBAND
1898 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1899 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1900 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1901#endif
1902#ifdef CONFIG_BAND_SBAND
1903 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1904 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1905#endif
1906};
1907
1908static const struct dib0090_tuning dib0090_tuning_table[] = {
1909
1910#ifdef CONFIG_BAND_CBAND
1911 {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1912#endif
1913#ifdef CONFIG_BAND_VHF
1914 {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1915 {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1916 {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1917#endif
1918#ifdef CONFIG_BAND_UHF
1919 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1920 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1921 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1922 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1923 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1924 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1925#endif
1926#ifdef CONFIG_BAND_LBAND
1927 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1928 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1929 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1930#endif
1931#ifdef CONFIG_BAND_SBAND
1932 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1933 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1934#endif
1935};
1936
1937static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {
1938#ifdef CONFIG_BAND_CBAND
1939 {170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},
1940#endif
1941#ifdef CONFIG_BAND_VHF
1942 {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1943 {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1944 {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1945#endif
1946#ifdef CONFIG_BAND_UHF
1947 {510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1948 {540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1949 {600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1950 {630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1951 {680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1952 {720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1953 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1954#endif
1955#ifdef CONFIG_BAND_LBAND
1956 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1957 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1958 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1959#endif
1960#ifdef CONFIG_BAND_SBAND
1961 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1962 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1963#endif
1964};
1965
1966static const struct dib0090_pll dib0090_p1g_pll_table[] = {
1967#ifdef CONFIG_BAND_CBAND
1968 {57000, 0, 11, 48, 6},
1969 {70000, 1, 11, 48, 6},
1970 {86000, 0, 10, 32, 4},
1971 {105000, 1, 10, 32, 4},
1972 {115000, 0, 9, 24, 6},
1973 {140000, 1, 9, 24, 6},
1974 {170000, 0, 8, 16, 4},
1975#endif
1976#ifdef CONFIG_BAND_VHF
1977 {200000, 1, 8, 16, 4},
1978 {230000, 0, 7, 12, 6},
1979 {280000, 1, 7, 12, 6},
1980 {340000, 0, 6, 8, 4},
1981 {380000, 1, 6, 8, 4},
1982 {455000, 0, 5, 6, 6},
1983#endif
1984#ifdef CONFIG_BAND_UHF
1985 {580000, 1, 5, 6, 6},
1986 {680000, 0, 4, 4, 4},
1987 {860000, 1, 4, 4, 4},
1988#endif
1989#ifdef CONFIG_BAND_LBAND
1990 {1800000, 1, 2, 2, 4},
1991#endif
1992#ifdef CONFIG_BAND_SBAND
1993 {2900000, 0, 1, 1, 6},
1994#endif
1995};
1996
1997static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {
1998#ifdef CONFIG_BAND_CBAND
1999 {184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2000 {227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2001 {380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2002#endif
2003#ifdef CONFIG_BAND_UHF
2004 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2005 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2006 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2007 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2008 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2009 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2010#endif
2011#ifdef CONFIG_BAND_LBAND
2012 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2013 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2014 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2015#endif
2016#ifdef CONFIG_BAND_SBAND
2017 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
2018 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
2019#endif
2020};
2021
2022static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
2023#ifdef CONFIG_BAND_CBAND
2024 {300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2025 {380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2026 {570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2027 {858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2028#endif
2029};
2030
2031static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = {
2032#ifdef CONFIG_BAND_CBAND
2033 { 300000, 0 , 3, 0x8105, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2034 { 380000, 0 , 10, 0x810F, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2035 { 600000, 0 , 10, 0x815E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2036 { 660000, 0 , 5, 0x85E3, 0x280, 0x2d12, 0xb84e, EN_CAB },
2037 { 720000, 0 , 5, 0x852E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2038 { 860000, 0 , 4, 0x85E5, 0x280, 0x2d12, 0xb84e, EN_CAB },
2039#endif
2040};
2041
2042int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
2043 u8 cfg_sensitivity)
2044{
2045 struct dib0090_state *state = fe->tuner_priv;
2046 const struct dib0090_tuning *tune =
2047 dib0090_tuning_table_cband_7090e_sensitivity;
2048 const struct dib0090_tuning dib0090_tuning_table_cband_7090e_aci[] = {
2049 { 300000, 0 , 3, 0x8165, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2050 { 650000, 0 , 4, 0x815B, 0x280, 0x2d12, 0xb84e, EN_CAB },
2051 { 860000, 0 , 5, 0x84EF, 0x280, 0x2d12, 0xb84e, EN_CAB },
2052 };
2053
2054 if ((!state->identity.p1g) || (!state->identity.in_soc)
2055 || ((state->identity.version != SOC_7090_P1G_21R1)
2056 && (state->identity.version != SOC_7090_P1G_11R1))) {
2057 dprintk("%s() function can only be used for dib7090", __func__);
2058 return -ENODEV;
2059 }
2060
2061 if (cfg_sensitivity)
2062 tune = dib0090_tuning_table_cband_7090e_sensitivity;
2063 else
2064 tune = dib0090_tuning_table_cband_7090e_aci;
2065
2066 while (state->rf_request > tune->max_freq)
2067 tune++;
2068
2069 dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x8000)
2070 | (tune->lna_bias & 0x7fff));
2071 dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xf83f)
2072 | ((tune->lna_tune << 6) & 0x07c0));
2073 return 0;
2074}
2075EXPORT_SYMBOL(dib0090_update_tuning_table_7090);
2076
2077static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2078{
2079 int ret = 0;
2080 u16 lo4 = 0xe900;
2081
2082 s16 adc_target;
2083 u16 adc;
2084 s8 step_sign;
2085 u8 force_soft_search = 0;
2086
2087 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
2088 force_soft_search = 1;
2089
2090 if (*tune_state == CT_TUNER_START) {
2091 dprintk("Start Captrim search : %s", (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
2092 dib0090_write_reg(state, 0x10, 0x2B1);
2093 dib0090_write_reg(state, 0x1e, 0x0032);
2094
2095 if (!state->tuner_is_tuned) {
2096
2097 if (!state->identity.p1g || force_soft_search)
2098 state->step = state->captrim = state->fcaptrim = 64;
2099
2100 state->current_rf = state->rf_request;
2101 } else {
2102 if (!state->identity.p1g || force_soft_search) {
2103
2104 state->step = 4;
2105 state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
2106 }
2107 }
2108 state->adc_diff = 3000;
2109 *tune_state = CT_TUNER_STEP_0;
2110
2111 } else if (*tune_state == CT_TUNER_STEP_0) {
2112 if (state->identity.p1g && !force_soft_search) {
2113 u8 ratio = 31;
2114
2115 dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1);
2116 dib0090_read_reg(state, 0x40);
2117 ret = 50;
2118 } else {
2119 state->step /= 2;
2120 dib0090_write_reg(state, 0x18, lo4 | state->captrim);
2121
2122 if (state->identity.in_soc)
2123 ret = 25;
2124 }
2125 *tune_state = CT_TUNER_STEP_1;
2126
2127 } else if (*tune_state == CT_TUNER_STEP_1) {
2128 if (state->identity.p1g && !force_soft_search) {
2129 dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0);
2130 dib0090_read_reg(state, 0x40);
2131
2132 state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
2133 dprintk("***Final Captrim= 0x%x", state->fcaptrim);
2134 *tune_state = CT_TUNER_STEP_3;
2135
2136 } else {
2137
2138 adc = dib0090_get_slow_adc_val(state);
2139 dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
2140
2141 if (state->rest == 0 || state->identity.in_soc) {
2142 adc_target = 200;
2143 } else
2144 adc_target = 400;
2145
2146 if (adc >= adc_target) {
2147 adc -= adc_target;
2148 step_sign = -1;
2149 } else {
2150 adc = adc_target - adc;
2151 step_sign = 1;
2152 }
2153
2154 if (adc < state->adc_diff) {
2155 dprintk("CAPTRIM=%d is closer to target (%d/%d)", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
2156 state->adc_diff = adc;
2157 state->fcaptrim = state->captrim;
2158 }
2159
2160 state->captrim += step_sign * state->step;
2161 if (state->step >= 1)
2162 *tune_state = CT_TUNER_STEP_0;
2163 else
2164 *tune_state = CT_TUNER_STEP_2;
2165
2166 ret = 25;
2167 }
2168 } else if (*tune_state == CT_TUNER_STEP_2) {
2169
2170 dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
2171
2172 *tune_state = CT_TUNER_STEP_3;
2173
2174 } else if (*tune_state == CT_TUNER_STEP_3) {
2175 state->calibrate &= ~CAPTRIM_CAL;
2176 *tune_state = CT_TUNER_STEP_0;
2177 }
2178
2179 return ret;
2180}
2181
2182static int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2183{
2184 int ret = 15;
2185 s16 val;
2186
2187 switch (*tune_state) {
2188 case CT_TUNER_START:
2189 state->wbdmux = dib0090_read_reg(state, 0x10);
2190 dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3));
2191
2192 state->bias = dib0090_read_reg(state, 0x13);
2193 dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8));
2194
2195 *tune_state = CT_TUNER_STEP_0;
2196
2197 break;
2198
2199 case CT_TUNER_STEP_0:
2200 state->adc_diff = dib0090_get_slow_adc_val(state);
2201 dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8));
2202 *tune_state = CT_TUNER_STEP_1;
2203 break;
2204
2205 case CT_TUNER_STEP_1:
2206 val = dib0090_get_slow_adc_val(state);
2207 state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
2208
2209 dprintk("temperature: %d C", state->temperature - 30);
2210
2211 *tune_state = CT_TUNER_STEP_2;
2212 break;
2213
2214 case CT_TUNER_STEP_2:
2215 dib0090_write_reg(state, 0x13, state->bias);
2216 dib0090_write_reg(state, 0x10, state->wbdmux);
2217
2218 *tune_state = CT_TUNER_START;
2219 state->calibrate &= ~TEMP_CAL;
2220 if (state->config->analog_output == 0)
2221 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2222
2223 break;
2224
2225 default:
2226 ret = 0;
2227 break;
2228 }
2229 return ret;
2230}
2231
2232#define WBD 0x781
2233static int dib0090_tune(struct dvb_frontend *fe)
2234{
2235 struct dib0090_state *state = fe->tuner_priv;
2236 const struct dib0090_tuning *tune = state->current_tune_table_index;
2237 const struct dib0090_pll *pll = state->current_pll_table_index;
2238 enum frontend_tune_state *tune_state = &state->tune_state;
2239
2240 u16 lo5, lo6, Den, tmp;
2241 u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
2242 int ret = 10;
2243 u8 c, i;
2244
2245
2246
2247
2248
2249
2250
2251 if (*tune_state == CT_TUNER_START) {
2252
2253 if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL))
2254 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
2255 else
2256
2257 if (state->config->analog_output == 0)
2258 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2259 }
2260
2261 if (state->calibrate & DC_CAL)
2262 return dib0090_dc_offset_calibration(state, tune_state);
2263 else if (state->calibrate & WBD_CAL) {
2264 if (state->current_rf == 0)
2265 state->current_rf = state->fe->dtv_property_cache.frequency / 1000;
2266 return dib0090_wbd_calibration(state, tune_state);
2267 } else if (state->calibrate & TEMP_CAL)
2268 return dib0090_get_temperature(state, tune_state);
2269 else if (state->calibrate & CAPTRIM_CAL)
2270 return dib0090_captrim_search(state, tune_state);
2271
2272 if (*tune_state == CT_TUNER_START) {
2273
2274 if (state->config->use_pwm_agc && state->identity.in_soc) {
2275 tmp = dib0090_read_reg(state, 0x39);
2276 if ((tmp >> 10) & 0x1)
2277 dib0090_write_reg(state, 0x39, tmp & ~(1 << 10));
2278 }
2279
2280 state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000);
2281 state->rf_request =
2282 state->fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
2283 BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->
2284 freq_offset_khz_vhf);
2285
2286
2287 if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1
2288 && state->fe->dtv_property_cache.isdbt_partial_reception == 0)) {
2289 const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if;
2290 u8 found_offset = 0;
2291 u32 margin_khz = 100;
2292
2293 if (LUT_offset != NULL) {
2294 while (LUT_offset->RF_freq != 0xffff) {
2295 if (((state->rf_request > (LUT_offset->RF_freq - margin_khz))
2296 && (state->rf_request < (LUT_offset->RF_freq + margin_khz)))
2297 && LUT_offset->std == state->fe->dtv_property_cache.delivery_system) {
2298 state->rf_request += LUT_offset->offset_khz;
2299 found_offset = 1;
2300 break;
2301 }
2302 LUT_offset++;
2303 }
2304 }
2305
2306 if (found_offset == 0)
2307 state->rf_request += 400;
2308 }
2309 if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) {
2310 state->tuner_is_tuned = 0;
2311 state->current_rf = 0;
2312 state->current_standard = 0;
2313
2314 tune = dib0090_tuning_table;
2315 if (state->identity.p1g)
2316 tune = dib0090_p1g_tuning_table;
2317
2318 tmp = (state->identity.version >> 5) & 0x7;
2319
2320 if (state->identity.in_soc) {
2321 if (state->config->force_cband_input) {
2322 if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
2323 || state->current_band & BAND_UHF) {
2324 state->current_band = BAND_CBAND;
2325 if (state->config->is_dib7090e)
2326 tune = dib0090_tuning_table_cband_7090e_sensitivity;
2327 else
2328 tune = dib0090_tuning_table_cband_7090;
2329 }
2330 } else {
2331 if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
2332 state->current_band = BAND_CBAND;
2333 if (state->config->is_dib7090e)
2334 tune = dib0090_tuning_table_cband_7090e_sensitivity;
2335 else
2336 tune = dib0090_tuning_table_cband_7090;
2337 }
2338 }
2339 } else
2340 if (tmp == 0x4 || tmp == 0x7) {
2341
2342 if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) {
2343 state->current_band = BAND_CBAND;
2344
2345 tune = dib0090_tuning_table_fm_vhf_on_cband;
2346 if (state->identity.p1g)
2347 tune = dib0090_p1g_tuning_table_fm_vhf_on_cband;
2348 }
2349 }
2350
2351 pll = dib0090_pll_table;
2352 if (state->identity.p1g)
2353 pll = dib0090_p1g_pll_table;
2354
2355
2356 while (state->rf_request > tune->max_freq)
2357 tune++;
2358 while (state->rf_request > pll->max_freq)
2359 pll++;
2360
2361 state->current_tune_table_index = tune;
2362 state->current_pll_table_index = pll;
2363
2364 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
2365
2366 VCOF_kHz = (pll->hfdiv * state->rf_request) * 2;
2367
2368 FREF = state->config->io.clock_khz;
2369 if (state->config->fref_clock_ratio != 0)
2370 FREF /= state->config->fref_clock_ratio;
2371
2372 FBDiv = (VCOF_kHz / pll->topresc / FREF);
2373 Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
2374
2375 if (Rest < LPF)
2376 Rest = 0;
2377 else if (Rest < 2 * LPF)
2378 Rest = 2 * LPF;
2379 else if (Rest > (FREF - LPF)) {
2380 Rest = 0;
2381 FBDiv += 1;
2382 } else if (Rest > (FREF - 2 * LPF))
2383 Rest = FREF - 2 * LPF;
2384 Rest = (Rest * 6528) / (FREF / 10);
2385 state->rest = Rest;
2386
2387
2388
2389
2390
2391 if (Rest == 0) {
2392 if (pll->vco_band)
2393 lo5 = 0x049f;
2394 else
2395 lo5 = 0x041f;
2396 } else {
2397 if (pll->vco_band)
2398 lo5 = 0x049e;
2399 else if (state->config->analog_output)
2400 lo5 = 0x041d;
2401 else
2402 lo5 = 0x041c;
2403 }
2404
2405 if (state->identity.p1g) {
2406 if (state->identity.in_soc) {
2407 if (state->identity.version == SOC_8090_P1G_11R1)
2408 lo5 = 0x46f;
2409 else
2410 lo5 = 0x42f;
2411 } else
2412 lo5 = 0x42c;
2413 }
2414
2415 lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7);
2416
2417 if (!state->config->io.pll_int_loop_filt) {
2418 if (state->identity.in_soc)
2419 lo6 = 0xff98;
2420 else if (state->identity.p1g || (Rest == 0))
2421 lo6 = 0xfff8;
2422 else
2423 lo6 = 0xff28;
2424 } else
2425 lo6 = (state->config->io.pll_int_loop_filt << 3);
2426
2427 Den = 1;
2428
2429 if (Rest > 0) {
2430 if (state->config->analog_output)
2431 lo6 |= (1 << 2) | 2;
2432 else {
2433 if (state->identity.in_soc)
2434 lo6 |= (1 << 2) | 2;
2435 else
2436 lo6 |= (1 << 2) | 2;
2437 }
2438 Den = 255;
2439 }
2440 dib0090_write_reg(state, 0x15, (u16) FBDiv);
2441 if (state->config->fref_clock_ratio != 0)
2442 dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio);
2443 else
2444 dib0090_write_reg(state, 0x16, (Den << 8) | 1);
2445 dib0090_write_reg(state, 0x17, (u16) Rest);
2446 dib0090_write_reg(state, 0x19, lo5);
2447 dib0090_write_reg(state, 0x1c, lo6);
2448
2449 lo6 = tune->tuner_enable;
2450 if (state->config->analog_output)
2451 lo6 = (lo6 & 0xff9f) | 0x2;
2452
2453 dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL);
2454
2455 }
2456
2457 state->current_rf = state->rf_request;
2458 state->current_standard = state->fe->dtv_property_cache.delivery_system;
2459
2460 ret = 20;
2461 state->calibrate = CAPTRIM_CAL;
2462 }
2463
2464 else if (*tune_state == CT_TUNER_STEP_0) {
2465 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
2466
2467 while (state->current_rf / 1000 > wbd->max_freq)
2468 wbd++;
2469
2470 dib0090_write_reg(state, 0x1e, 0x07ff);
2471 dprintk("Final Captrim: %d", (u32) state->fcaptrim);
2472 dprintk("HFDIV code: %d", (u32) pll->hfdiv_code);
2473 dprintk("VCO = %d", (u32) pll->vco_band);
2474 dprintk("VCOF in kHz: %d ((%d*%d) << 1))", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
2475 dprintk("REFDIV: %d, FREF: %d", (u32) 1, (u32) state->config->io.clock_khz);
2476 dprintk("FBDIV: %d, Rest: %d", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
2477 dprintk("Num: %d, Den: %d, SD: %d", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
2478 (u32) dib0090_read_reg(state, 0x1c) & 0x3);
2479
2480#define WBD 0x781
2481 c = 4;
2482 i = 3;
2483
2484 if (wbd->wbd_gain != 0)
2485 c = wbd->wbd_gain;
2486
2487 state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1));
2488 dib0090_write_reg(state, 0x10, state->wbdmux);
2489
2490 if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
2491 dprintk("P1G : The cable band is selected and lna_tune = %d", tune->lna_tune);
2492 dib0090_write_reg(state, 0x09, tune->lna_bias);
2493 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
2494 } else
2495 dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias);
2496
2497 dib0090_write_reg(state, 0x0c, tune->v2i);
2498 dib0090_write_reg(state, 0x0d, tune->mix);
2499 dib0090_write_reg(state, 0x0e, tune->load);
2500 *tune_state = CT_TUNER_STEP_1;
2501
2502 } else if (*tune_state == CT_TUNER_STEP_1) {
2503
2504 state->rf_lt_def = 0x7c00;
2505
2506 dib0090_set_bandwidth(state);
2507 state->tuner_is_tuned = 1;
2508
2509 state->calibrate |= WBD_CAL;
2510 state->calibrate |= TEMP_CAL;
2511 *tune_state = CT_TUNER_STOP;
2512 } else
2513 ret = FE_CALLBACK_TIME_NEVER;
2514 return ret;
2515}
2516
2517static int dib0090_release(struct dvb_frontend *fe)
2518{
2519 kfree(fe->tuner_priv);
2520 fe->tuner_priv = NULL;
2521 return 0;
2522}
2523
2524enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
2525{
2526 struct dib0090_state *state = fe->tuner_priv;
2527
2528 return state->tune_state;
2529}
2530
2531EXPORT_SYMBOL(dib0090_get_tune_state);
2532
2533int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
2534{
2535 struct dib0090_state *state = fe->tuner_priv;
2536
2537 state->tune_state = tune_state;
2538 return 0;
2539}
2540
2541EXPORT_SYMBOL(dib0090_set_tune_state);
2542
2543static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
2544{
2545 struct dib0090_state *state = fe->tuner_priv;
2546
2547 *frequency = 1000 * state->current_rf;
2548 return 0;
2549}
2550
2551static int dib0090_set_params(struct dvb_frontend *fe)
2552{
2553 struct dib0090_state *state = fe->tuner_priv;
2554 u32 ret;
2555
2556 state->tune_state = CT_TUNER_START;
2557
2558 do {
2559 ret = dib0090_tune(fe);
2560 if (ret != FE_CALLBACK_TIME_NEVER)
2561 msleep(ret / 10);
2562 else
2563 break;
2564 } while (state->tune_state != CT_TUNER_STOP);
2565
2566 return 0;
2567}
2568
2569static const struct dvb_tuner_ops dib0090_ops = {
2570 .info = {
2571 .name = "DiBcom DiB0090",
2572 .frequency_min = 45000000,
2573 .frequency_max = 860000000,
2574 .frequency_step = 1000,
2575 },
2576 .release = dib0090_release,
2577
2578 .init = dib0090_wakeup,
2579 .sleep = dib0090_sleep,
2580 .set_params = dib0090_set_params,
2581 .get_frequency = dib0090_get_frequency,
2582};
2583
2584static const struct dvb_tuner_ops dib0090_fw_ops = {
2585 .info = {
2586 .name = "DiBcom DiB0090",
2587 .frequency_min = 45000000,
2588 .frequency_max = 860000000,
2589 .frequency_step = 1000,
2590 },
2591 .release = dib0090_release,
2592
2593 .init = NULL,
2594 .sleep = NULL,
2595 .set_params = NULL,
2596 .get_frequency = NULL,
2597};
2598
2599static const struct dib0090_wbd_slope dib0090_wbd_table_default[] = {
2600 {470, 0, 250, 0, 100, 4},
2601 {860, 51, 866, 21, 375, 4},
2602 {1700, 0, 800, 0, 850, 4},
2603 {2900, 0, 250, 0, 100, 6},
2604 {0xFFFF, 0, 0, 0, 0, 0},
2605};
2606
2607struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2608{
2609 struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
2610 if (st == NULL)
2611 return NULL;
2612
2613 st->config = config;
2614 st->i2c = i2c;
2615 st->fe = fe;
2616 mutex_init(&st->i2c_buffer_lock);
2617 fe->tuner_priv = st;
2618
2619 if (config->wbd == NULL)
2620 st->current_wbd_table = dib0090_wbd_table_default;
2621 else
2622 st->current_wbd_table = config->wbd;
2623
2624 if (dib0090_reset(fe) != 0)
2625 goto free_mem;
2626
2627 printk(KERN_INFO "DiB0090: successfully identified\n");
2628 memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
2629
2630 return fe;
2631 free_mem:
2632 kfree(st);
2633 fe->tuner_priv = NULL;
2634 return NULL;
2635}
2636
2637EXPORT_SYMBOL(dib0090_register);
2638
2639struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2640{
2641 struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);
2642 if (st == NULL)
2643 return NULL;
2644
2645 st->config = config;
2646 st->i2c = i2c;
2647 st->fe = fe;
2648 mutex_init(&st->i2c_buffer_lock);
2649 fe->tuner_priv = st;
2650
2651 if (dib0090_fw_reset_digital(fe, st->config) != 0)
2652 goto free_mem;
2653
2654 dprintk("DiB0090 FW: successfully identified");
2655 memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
2656
2657 return fe;
2658free_mem:
2659 kfree(st);
2660 fe->tuner_priv = NULL;
2661 return NULL;
2662}
2663EXPORT_SYMBOL(dib0090_fw_register);
2664
2665MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
2666MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
2667MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
2668MODULE_LICENSE("GPL");
2669