aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb
diff options
context:
space:
mode:
authorPatrick Boettcher <Patrick.Boettcher@dibcom.fr>2009-08-03 12:43:40 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-18 23:14:27 -0400
commit7e5ce6515d0deb76a49dcb4112a6dff5d950bfb6 (patch)
treeb83f9dfd22cdd5e421715d86946f50eef2ec6ba6 /drivers/media/dvb
parente7b7949a95441affe937fa25f4d6d8f3df0ca271 (diff)
V4L/DVB (12898): DiB0070: Update to latest internal release
General update of the dib0070-driver based on DiBcom's latest release. New driver features can enable better performance in some reception situations. Signed-off-by: Patrick Boettcher <Patrick.Boettcher@dibcom.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c7
-rw-r--r--drivers/media/dvb/frontends/dib0070.c673
-rw-r--r--drivers/media/dvb/frontends/dib0070.h11
3 files changed, 407 insertions, 284 deletions
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 10a89b0e5189..10ade261b0ab 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -1098,11 +1098,13 @@ static struct dibx000_agc_config dib7070_agc_config = {
1098 1098
1099static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) 1099static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
1100{ 1100{
1101 deb_info("reset: %d", onoff);
1101 return dib7000p_set_gpio(fe, 8, 0, !onoff); 1102 return dib7000p_set_gpio(fe, 8, 0, !onoff);
1102} 1103}
1103 1104
1104static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) 1105static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
1105{ 1106{
1107 deb_info("sleep: %d", onoff);
1106 return dib7000p_set_gpio(fe, 9, 0, onoff); 1108 return dib7000p_set_gpio(fe, 9, 0, onoff);
1107} 1109}
1108 1110
@@ -1112,13 +1114,14 @@ static struct dib0070_config dib7070p_dib0070_config[2] = {
1112 .reset = dib7070_tuner_reset, 1114 .reset = dib7070_tuner_reset,
1113 .sleep = dib7070_tuner_sleep, 1115 .sleep = dib7070_tuner_sleep,
1114 .clock_khz = 12000, 1116 .clock_khz = 12000,
1115 .clock_pad_drive = 4 1117 .clock_pad_drive = 4,
1118 .charge_pump = 2,
1116 }, { 1119 }, {
1117 .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, 1120 .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
1118 .reset = dib7070_tuner_reset, 1121 .reset = dib7070_tuner_reset,
1119 .sleep = dib7070_tuner_sleep, 1122 .sleep = dib7070_tuner_sleep,
1120 .clock_khz = 12000, 1123 .clock_khz = 12000,
1121 1124 .charge_pump = 2,
1122 } 1125 }
1123}; 1126};
1124 1127
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c
index da92cbe1b8ea..2eb9bdb4dbb3 100644
--- a/drivers/media/dvb/frontends/dib0070.c
+++ b/drivers/media/dvb/frontends/dib0070.c
@@ -1,12 +1,29 @@
1/* 1/*
2 * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner. 2 * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
3 * 3 *
4 * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/) 4 * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 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 7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2. 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 *
9 */ 25 */
26
10#include <linux/kernel.h> 27#include <linux/kernel.h>
11#include <linux/i2c.h> 28#include <linux/i2c.h>
12 29
@@ -19,19 +36,57 @@ static int debug;
19module_param(debug, int, 0644); 36module_param(debug, int, 0644);
20MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); 37MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
21 38
22#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB0070: "); printk(args); printk("\n"); } } while (0) 39#define dprintk(args...) do { \
40 if (debug) { \
41 printk(KERN_DEBUG "DiB0070: "); \
42 printk(args); \
43 printk("\n"); \
44 } \
45} while (0)
23 46
24#define DIB0070_P1D 0x00 47#define DIB0070_P1D 0x00
25#define DIB0070_P1F 0x01 48#define DIB0070_P1F 0x01
26#define DIB0070_P1G 0x03 49#define DIB0070_P1G 0x03
27#define DIB0070S_P1A 0x02 50#define DIB0070S_P1A 0x02
28 51
52enum frontend_tune_state {
53 CT_TUNER_START = 10,
54 CT_TUNER_STEP_0,
55 CT_TUNER_STEP_1,
56 CT_TUNER_STEP_2,
57 CT_TUNER_STEP_3,
58 CT_TUNER_STEP_4,
59 CT_TUNER_STEP_5,
60 CT_TUNER_STEP_6,
61 CT_TUNER_STEP_7,
62 CT_TUNER_STOP,
63};
64
65#define FE_CALLBACK_TIME_NEVER 0xffffffff
66
29struct dib0070_state { 67struct dib0070_state {
30 struct i2c_adapter *i2c; 68 struct i2c_adapter *i2c;
31 struct dvb_frontend *fe; 69 struct dvb_frontend *fe;
32 const struct dib0070_config *cfg; 70 const struct dib0070_config *cfg;
33 u16 wbd_ff_offset; 71 u16 wbd_ff_offset;
34 u8 revision; 72 u8 revision;
73
74 enum frontend_tune_state tune_state;
75 u32 current_rf;
76
77 /* for the captrim binary search */
78 s8 step;
79 u16 adc_diff;
80
81 s8 captrim;
82 s8 fcaptrim;
83 u16 lo4;
84
85 const struct dib0070_tuning *current_tune_table_index;
86 const struct dib0070_lna_match *lna_match;
87
88 u8 wbd_gain_current;
89 u16 wbd_offset_3_3[2];
35}; 90};
36 91
37static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) 92static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
@@ -59,55 +114,71 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
59 return 0; 114 return 0;
60} 115}
61 116
62#define HARD_RESET(state) do { if (state->cfg->reset) { state->cfg->reset(state->fe,1); msleep(10); state->cfg->reset(state->fe,0); msleep(10); } } while (0) 117#define HARD_RESET(state) do { \
118 state->cfg->sleep(state->fe, 0); \
119 if (state->cfg->reset) { \
120 state->cfg->reset(state->fe,1); msleep(10); \
121 state->cfg->reset(state->fe,0); msleep(10); \
122 } \
123} while (0)
63 124
64static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) 125static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
65{ 126{
66 struct dib0070_state *st = fe->tuner_priv; 127 struct dib0070_state *st = fe->tuner_priv;
67 u16 tmp = 0; 128 u16 tmp = dib0070_read_reg(st, 0x02) & 0x3fff;
68 tmp = dib0070_read_reg(st, 0x02) & 0x3fff; 129
69 130 if (fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
70 switch(BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)) { 131 tmp |= (0 << 14);
71 case 8000: 132 else if (fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
72 tmp |= (0 << 14); 133 tmp |= (1 << 14);
73 break; 134 else if (fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
74 case 7000: 135 tmp |= (2 << 14);
75 tmp |= (1 << 14); 136 else
76 break; 137 tmp |= (3 << 14);
77 case 6000: 138
78 tmp |= (2 << 14); 139 dib0070_write_reg(st, 0x02, tmp);
79 break; 140
80 case 5000: 141 /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
81 default: 142 if (fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
82 tmp |= (3 << 14); 143 u16 value = dib0070_read_reg(st, 0x17);
83 break; 144
84 } 145 dib0070_write_reg(st, 0x17, value & 0xfffc);
85 dib0070_write_reg(st, 0x02, tmp); 146 tmp = dib0070_read_reg(st, 0x01) & 0x01ff;
147 dib0070_write_reg(st, 0x01, tmp | (60 << 9));
148
149 dib0070_write_reg(st, 0x17, value);
150 }
86 return 0; 151 return 0;
87} 152}
88 153
89static void dib0070_captrim(struct dib0070_state *st, u16 LO4) 154static int dib0070_captrim(struct dib0070_state *st, enum frontend_tune_state *tune_state)
90{ 155{
91 int8_t captrim, fcaptrim, step_sign, step; 156 int8_t step_sign;
92 u16 adc, adc_diff = 3000; 157 u16 adc;
158 int ret = 0;
93 159
160 if (*tune_state == CT_TUNER_STEP_0) {
94 161
162 dib0070_write_reg(st, 0x0f, 0xed10);
163 dib0070_write_reg(st, 0x17, 0x0034);
95 164
96 dib0070_write_reg(st, 0x0f, 0xed10); 165 dib0070_write_reg(st, 0x18, 0x0032);
97 dib0070_write_reg(st, 0x17, 0x0034); 166 st->step = st->captrim = st->fcaptrim = 64;
167 st->adc_diff = 3000;
168 ret = 20;
98 169
99 dib0070_write_reg(st, 0x18, 0x0032); 170 *tune_state = CT_TUNER_STEP_1;
100 msleep(2); 171 } else if (*tune_state == CT_TUNER_STEP_1) {
172 st->step /= 2;
173 dib0070_write_reg(st, 0x14, st->lo4 | st->captrim);
174 ret = 15;
101 175
102 step = captrim = fcaptrim = 64; 176 *tune_state = CT_TUNER_STEP_2;
177 } else if (*tune_state == CT_TUNER_STEP_2) {
103 178
104 do {
105 step /= 2;
106 dib0070_write_reg(st, 0x14, LO4 | captrim);
107 msleep(1);
108 adc = dib0070_read_reg(st, 0x19); 179 adc = dib0070_read_reg(st, 0x19);
109 180
110 dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", captrim, adc, (u32) adc*(u32)1800/(u32)1024); 181 dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", st->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
111 182
112 if (adc >= 400) { 183 if (adc >= 400) {
113 adc -= 400; 184 adc -= 400;
@@ -117,266 +188,305 @@ static void dib0070_captrim(struct dib0070_state *st, u16 LO4)
117 step_sign = 1; 188 step_sign = 1;
118 } 189 }
119 190
120 if (adc < adc_diff) { 191 if (adc < st->adc_diff) {
121 dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", captrim, adc, adc_diff); 192 dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", st->captrim, adc, st->adc_diff);
122 adc_diff = adc; 193 st->adc_diff = adc;
123 fcaptrim = captrim; 194 st->fcaptrim = st->captrim;
124 195
125 196
126 197
127 } 198 }
128 captrim += (step_sign * step); 199 st->captrim += (step_sign * st->step);
129 } while (step >= 1); 200
201 if (st->step >= 1)
202 *tune_state = CT_TUNER_STEP_1;
203 else
204 *tune_state = CT_TUNER_STEP_3;
205
206 } else if (*tune_state == CT_TUNER_STEP_3) {
207 dib0070_write_reg(st, 0x14, st->lo4 | st->fcaptrim);
208 dib0070_write_reg(st, 0x18, 0x07ff);
209 *tune_state = CT_TUNER_STEP_4;
210 }
130 211
131 dib0070_write_reg(st, 0x14, LO4 | fcaptrim); 212 return ret;
132 dib0070_write_reg(st, 0x18, 0x07ff);
133} 213}
134 214
135#define LPF 100 // define for the loop filter 100kHz by default 16-07-06 215static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
136#define LO4_SET_VCO_HFDIV(l, v, h) l |= ((v) << 11) | ((h) << 7)
137#define LO4_SET_SD(l, s) l |= ((s) << 14) | ((s) << 12)
138#define LO4_SET_CTRIM(l, c) l |= (c) << 10
139static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
140{ 216{
141 struct dib0070_state *st = fe->tuner_priv; 217 struct dib0070_state *state = fe->tuner_priv;
142 u32 freq = ch->frequency/1000 + (BAND_OF_FREQUENCY(ch->frequency/1000) == BAND_VHF ? st->cfg->freq_offset_khz_vhf : st->cfg->freq_offset_khz_uhf); 218 u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
219 dprintk( "CTRL_LO5: 0x%x", lo5);
220 return dib0070_write_reg(state, 0x15, lo5);
221}
143 222
144 u8 band = BAND_OF_FREQUENCY(freq), c; 223struct dib0070_tuning
224{
225 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
226 u8 switch_trim;
227 u8 vco_band;
228 u8 hfdiv;
229 u8 vco_multi;
230 u8 presc;
231 u8 wbdmux;
232 u16 tuner_enable;
233};
145 234
146 /*******************VCO***********************************/ 235struct dib0070_lna_match
147 u16 lo4 = 0; 236{
237 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
238 u8 lna_band;
239};
148 240
149 u8 REFDIV, PRESC = 2; 241static const struct dib0070_tuning dib0070s_tuning_table[] =
150 u32 FBDiv, Rest, FREF, VCOF_kHz;
151 u16 Num, Den;
152 /*******************FrontEnd******************************/
153 u16 value = 0;
154 242
155 dprintk( "Tuning for Band: %hd (%d kHz)", band, freq); 243{
244 { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
245 { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
246 { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
247 { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
248 { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
249 { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
250 { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
251};
156 252
253static const struct dib0070_tuning dib0070_tuning_table[] =
157 254
158 dib0070_write_reg(st, 0x17, 0x30); 255{
256 { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
257 { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
258 { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
259 { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
260 { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
261 { 699999, 2, 0 ,1, 4, 2, 2, 0x4000 | 0x0800 },
262 { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 },
263 { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
264};
159 265
160 dib0070_set_bandwidth(fe, ch); /* c is used as HF */ 266static const struct dib0070_lna_match dib0070_lna_flip_chip[] =
161 switch (st->revision) {
162 case DIB0070S_P1A:
163 switch (band) {
164 case BAND_LBAND:
165 LO4_SET_VCO_HFDIV(lo4, 1, 1);
166 c = 2;
167 break;
168 case BAND_SBAND:
169 LO4_SET_VCO_HFDIV(lo4, 0, 0);
170 LO4_SET_CTRIM(lo4, 1);
171 c = 1;
172 break;
173 case BAND_UHF:
174 default:
175 if (freq < 570000) {
176 LO4_SET_VCO_HFDIV(lo4, 1, 3);
177 PRESC = 6; c = 6;
178 } else if (freq < 680000) {
179 LO4_SET_VCO_HFDIV(lo4, 0, 2);
180 c = 4;
181 } else {
182 LO4_SET_VCO_HFDIV(lo4, 1, 2);
183 c = 4;
184 }
185 break;
186 } break;
187
188 case DIB0070_P1G:
189 case DIB0070_P1F:
190 default:
191 switch (band) {
192 case BAND_FM:
193 LO4_SET_VCO_HFDIV(lo4, 0, 7);
194 c = 24;
195 break;
196 case BAND_LBAND:
197 LO4_SET_VCO_HFDIV(lo4, 1, 0);
198 c = 2;
199 break;
200 case BAND_VHF:
201 if (freq < 180000) {
202 LO4_SET_VCO_HFDIV(lo4, 0, 3);
203 c = 16;
204 } else if (freq < 190000) {
205 LO4_SET_VCO_HFDIV(lo4, 1, 3);
206 c = 16;
207 } else {
208 LO4_SET_VCO_HFDIV(lo4, 0, 6);
209 c = 12;
210 }
211 break;
212
213 case BAND_UHF:
214 default:
215 if (freq < 570000) {
216 LO4_SET_VCO_HFDIV(lo4, 1, 5);
217 c = 6;
218 } else if (freq < 700000) {
219 LO4_SET_VCO_HFDIV(lo4, 0, 1);
220 c = 4;
221 } else {
222 LO4_SET_VCO_HFDIV(lo4, 1, 1);
223 c = 4;
224 }
225 break;
226 }
227 break;
228 }
229 267
230 dprintk( "HFDIV code: %hd", (lo4 >> 7) & 0xf); 268{
231 dprintk( "VCO = %hd", (lo4 >> 11) & 0x3); 269 { 180000, 0 }, /* VHF */
270 { 188000, 1 },
271 { 196400, 2 },
272 { 250000, 3 },
273 { 550000, 0 }, /* UHF */
274 { 590000, 1 },
275 { 666000, 3 },
276 { 864000, 5 },
277 { 1500000, 0 }, /* LBAND or everything higher than UHF */
278 { 1600000, 1 },
279 { 2000000, 3 },
280 { 0xffffffff, 7 },
281};
232 282
283static const struct dib0070_lna_match dib0070_lna[] =
233 284
234 VCOF_kHz = (c * freq) * 2; 285{
235 dprintk( "VCOF in kHz: %d ((%hd*%d) << 1))",VCOF_kHz, c, freq); 286 { 180000, 0 }, /* VHF */
287 { 188000, 1 },
288 { 196400, 2 },
289 { 250000, 3 },
290 { 550000, 2 }, /* UHF */
291 { 650000, 3 },
292 { 750000, 5 },
293 { 850000, 6 },
294 { 864000, 7 },
295 { 1500000, 0 }, /* LBAND or everything higher than UHF */
296 { 1600000, 1 },
297 { 2000000, 3 },
298 { 0xffffffff, 7 },
299};
236 300
237 switch (band) { 301#define LPF 100 // define for the loop filter 100kHz by default 16-07-06
238 case BAND_VHF: 302static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
239 REFDIV = (u8) ((st->cfg->clock_khz + 9999) / 10000); 303{
240 break; 304 struct dib0070_state *st = fe->tuner_priv;
241 case BAND_FM: 305
242 REFDIV = (u8) ((st->cfg->clock_khz) / 1000); 306 const struct dib0070_tuning *tune;
243 break; 307 const struct dib0070_lna_match *lna_match;
244 default: 308
245 REFDIV = (u8) ( st->cfg->clock_khz / 10000); 309 enum frontend_tune_state *tune_state = &st->tune_state;
246 break; 310 int ret = 10; /* 1ms is the default delay most of the time */
247 }
248 FREF = st->cfg->clock_khz / REFDIV;
249 311
250 dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF); 312 u8 band = (u8)BAND_OF_FREQUENCY(ch->frequency/1000);
313 u32 freq = ch->frequency/1000 + (band == BAND_VHF ? st->cfg->freq_offset_khz_vhf : st->cfg->freq_offset_khz_uhf);
251 314
252 315
253 316
317
318
319#ifdef CONFIG_STANDARD_ISDBT
320 if (fe->dtv_property_cache.delivery_system == SYS_ISDBT && ch->u.isdbt.sb_mode == 1)
321 if ( ( (ch->u.isdbt.sb_conn_total_seg % 2) && (ch->u.isdbt.sb_wanted_seg == ((ch->u.isdbt.sb_conn_total_seg/2) + 1) ) ) ||
322 ( ( (ch->u.isdbt.sb_conn_total_seg % 2) == 0) && (ch->u.isdbt.sb_wanted_seg == (ch->u.isdbt.sb_conn_total_seg/2) ) ) ||
323 ( ( (ch->u.isdbt.sb_conn_total_seg % 2) == 0) && (ch->u.isdbt.sb_wanted_seg == ((ch->u.isdbt.sb_conn_total_seg/2)+1))) )
324 freq += 850;
325#endif
326 if (st->current_rf != freq) {
327
254 switch (st->revision) { 328 switch (st->revision) {
255 case DIB0070S_P1A: 329 case DIB0070S_P1A:
256 FBDiv = (VCOF_kHz / PRESC / FREF); 330 tune = dib0070s_tuning_table;
257 Rest = (VCOF_kHz / PRESC) - FBDiv * FREF; 331 lna_match = dib0070_lna;
258 break; 332 break;
259 333 default:
260 case DIB0070_P1G: 334 tune = dib0070_tuning_table;
261 case DIB0070_P1F: 335 if (st->cfg->flip_chip)
262 default: 336 lna_match = dib0070_lna_flip_chip;
263 FBDiv = (freq / (FREF / 2)); 337 else
264 Rest = 2 * freq - FBDiv * FREF; 338 lna_match = dib0070_lna;
265 break; 339 break;
266 } 340 }
341 while (freq > tune->max_freq) /* find the right one */
342 tune++;
343 while (freq > lna_match->max_freq) /* find the right one */
344 lna_match++;
267 345
346 st->current_tune_table_index = tune;
347 st->lna_match = lna_match;
348 }
268 349
269 if (Rest < LPF) Rest = 0; 350 if (*tune_state == CT_TUNER_START) {
270 else if (Rest < 2 * LPF) Rest = 2 * LPF; 351 dprintk( "Tuning for Band: %hd (%d kHz)", band, freq);
271 else if (Rest > (FREF - LPF)) { Rest = 0 ; FBDiv += 1; } 352 if (st->current_rf != freq) {
272 else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF; 353 u8 REFDIV;
273 Rest = (Rest * 6528) / (FREF / 10); 354 u32 FBDiv, Rest, FREF, VCOF_kHz;
274 dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest); 355 u8 Den;
275 356
276 Num = 0; 357 st->current_rf = freq;
277 Den = 1; 358 st->lo4 = (st->current_tune_table_index->vco_band << 11) | (st->current_tune_table_index->hfdiv << 7);
278 359
279 if (Rest > 0) {
280 LO4_SET_SD(lo4, 1);
281 Den = 255;
282 Num = (u16)Rest;
283 }
284 dprintk( "Num: %hd, Den: %hd, SD: %hd",Num, Den, (lo4 >> 12) & 0x1);
285 360
361 dib0070_write_reg(st, 0x17, 0x30);
286 362
287 363
288 dib0070_write_reg(st, 0x11, (u16)FBDiv); 364 VCOF_kHz = st->current_tune_table_index->vco_multi * freq * 2;
289 365
366 switch (band) {
367 case BAND_VHF:
368 REFDIV = (u8) ((st->cfg->clock_khz + 9999) / 10000);
369 break;
370 case BAND_FM:
371 REFDIV = (u8) ((st->cfg->clock_khz) / 1000);
372 break;
373 default:
374 REFDIV = (u8) ( st->cfg->clock_khz / 10000);
375 break;
376 }
377 FREF = st->cfg->clock_khz / REFDIV;
290 378
291 dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV);
292 379
293 380
294 dib0070_write_reg(st, 0x13, Num); 381 switch (st->revision) {
382 case DIB0070S_P1A:
383 FBDiv = (VCOF_kHz / st->current_tune_table_index->presc / FREF);
384 Rest = (VCOF_kHz / st->current_tune_table_index->presc) - FBDiv * FREF;
385 break;
295 386
387 case DIB0070_P1G:
388 case DIB0070_P1F:
389 default:
390 FBDiv = (freq / (FREF / 2));
391 Rest = 2 * freq - FBDiv * FREF;
392 break;
393 }
296 394
297 value = 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001;
298 395
299 switch (band) { 396 if (Rest < LPF) Rest = 0;
300 case BAND_UHF: value |= 0x4000 | 0x0800; break; 397 else if (Rest < 2 * LPF) Rest = 2 * LPF;
301 case BAND_LBAND: value |= 0x2000 | 0x0400; break; 398 else if (Rest > (FREF - LPF)) { Rest = 0 ; FBDiv += 1; }
302 default: value |= 0x8000 | 0x1000; break; 399 else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF;
303 } 400 Rest = (Rest * 6528) / (FREF / 10);
304 dib0070_write_reg(st, 0x20, value);
305 401
306 dib0070_captrim(st, lo4); 402 Den = 1;
307 if (st->revision == DIB0070S_P1A) { 403 if (Rest > 0) {
308 if (band == BAND_SBAND) 404 st->lo4 |= (1 << 14) | (1 << 12);
309 dib0070_write_reg(st, 0x15, 0x16e2); 405 Den = 255;
310 else 406 }
311 dib0070_write_reg(st, 0x15, 0x56e5);
312 }
313 407
314 408
409 dib0070_write_reg(st, 0x11, (u16)FBDiv);
410 dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV);
411 dib0070_write_reg(st, 0x13, (u16) Rest);
315 412
316 switch (band) { 413 if (st->revision == DIB0070S_P1A) {
317 case BAND_UHF: value = 0x7c82; break;
318 case BAND_LBAND: value = 0x7c84; break;
319 default: value = 0x7c81; break;
320 }
321 dib0070_write_reg(st, 0x0f, value);
322 dib0070_write_reg(st, 0x06, 0x3fff);
323 414
324 /* Front End */ 415 if (band == BAND_SBAND) {
325 /* c == TUNE, value = SWITCH */ 416 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
326 c = 0; 417 dib0070_write_reg(st, 0x1d,0xFFFF);
327 value = 0; 418 } else
328 switch (band) { 419 dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
329 case BAND_FM: 420 }
330 c = 0; value = 1;
331 break;
332 421
333 case BAND_VHF:
334 if (freq <= 180000) c = 0;
335 else if (freq <= 188200) c = 1;
336 else if (freq <= 196400) c = 2;
337 else c = 3;
338 value = 1;
339 break;
340 422
341 case BAND_LBAND: 423 dib0070_write_reg(st, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | st->current_tune_table_index->tuner_enable);
342 if (freq <= 1500000) c = 0;
343 else if (freq <= 1600000) c = 1;
344 else c = 3;
345 break;
346 424
347 case BAND_SBAND: 425 dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF);
348 c = 7; 426 dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest);
349 dib0070_write_reg(st, 0x1d,0xFFFF); 427 dprintk( "Num: %hd, Den: %hd, SD: %hd",(u16) Rest, Den, (st->lo4 >> 12) & 0x1);
350 break; 428 dprintk( "HFDIV code: %hd", st->current_tune_table_index->hfdiv);
429 dprintk( "VCO = %hd", st->current_tune_table_index->vco_band);
430 dprintk( "VCOF: ((%hd*%d) << 1))", st->current_tune_table_index->vco_multi, freq);
351 431
352 case BAND_UHF: 432 *tune_state = CT_TUNER_STEP_0;
353 default: 433 } else { /* we are already tuned to this frequency - the configuration is correct */
354 if (st->cfg->flip_chip) { 434 ret = 50; /* wakeup time */
355 if (freq <= 550000) c = 0; 435 *tune_state = CT_TUNER_STEP_5;
356 else if (freq <= 590000) c = 1; 436 }
357 else if (freq <= 666000) c = 3; 437 } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
358 else c = 5; 438
359 } else { 439 ret = dib0070_captrim(st, tune_state);
360 if (freq <= 550000) c = 2; 440
361 else if (freq <= 650000) c = 3; 441 } else if (*tune_state == CT_TUNER_STEP_4) {
362 else if (freq <= 750000) c = 5; 442 const struct dib0070_wbd_gain_cfg *tmp = st->cfg->wbd_gain;
363 else if (freq <= 850000) c = 6; 443 if (tmp != NULL) {
364 else c = 7; 444 while (freq/1000 > tmp->freq) /* find the right one */
365 } 445 tmp++;
366 value = 2; 446 dib0070_write_reg(st, 0x0f, (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (st->current_tune_table_index->wbdmux << 0));
367 break; 447 st->wbd_gain_current = tmp->wbd_gain_val;
448 } else {
449 dib0070_write_reg(st, 0x0f, (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (st->current_tune_table_index->wbdmux << 0));
450 st->wbd_gain_current = 6;
368 } 451 }
369 452
370 /* default: LNA_MATCH=7, BIAS=3 */ 453 dib0070_write_reg(st, 0x06, 0x3fff);
371 dib0070_write_reg(st, 0x07, (value << 11) | (7 << 8) | (c << 3) | (3 << 0)); 454 dib0070_write_reg(st, 0x07, (st->current_tune_table_index->switch_trim << 11) | (7 << 8) | (st->lna_match->lna_band << 3) | (3 << 0));
372 dib0070_write_reg(st, 0x08, (c << 10) | (3 << 7) | (127)); 455 dib0070_write_reg(st, 0x08, (st->lna_match->lna_band << 10) | (3 << 7) | (127));
373 dib0070_write_reg(st, 0x0d, 0x0d80); 456 dib0070_write_reg(st, 0x0d, 0x0d80);
374 457
375 458
376 dib0070_write_reg(st, 0x18, 0x07ff); 459 dib0070_write_reg(st, 0x18, 0x07ff);
377 dib0070_write_reg(st, 0x17, 0x0033); 460 dib0070_write_reg(st, 0x17, 0x0033);
378 461
379 return 0; 462
463 *tune_state = CT_TUNER_STEP_5;
464 } else if (*tune_state == CT_TUNER_STEP_5) {
465 dib0070_set_bandwidth(fe, ch);
466 *tune_state = CT_TUNER_STOP;
467 } else {
468 ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
469 }
470 return ret;
471}
472
473
474static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
475{
476 struct dib0070_state *state = fe->tuner_priv;
477 uint32_t ret;
478
479 state->tune_state = CT_TUNER_START;
480
481 do {
482 ret = dib0070_tune_digital(fe, p);
483 if (ret != FE_CALLBACK_TIME_NEVER)
484 msleep(ret/10);
485 else
486 break;
487 } while (state->tune_state != CT_TUNER_STOP);
488
489 return 0;
380} 490}
381 491
382static int dib0070_wakeup(struct dvb_frontend *fe) 492static int dib0070_wakeup(struct dvb_frontend *fe)
@@ -395,7 +505,7 @@ static int dib0070_sleep(struct dvb_frontend *fe)
395 return 0; 505 return 0;
396} 506}
397 507
398static u16 dib0070_p1f_defaults[] = 508static const u16 dib0070_p1f_defaults[] =
399 509
400{ 510{
401 7, 0x02, 511 7, 0x02,
@@ -434,45 +544,40 @@ static u16 dib0070_p1f_defaults[] =
434 0, 544 0,
435}; 545};
436 546
437static void dib0070_wbd_calibration(struct dvb_frontend *fe) 547static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
438{ 548{
439 u16 wbd_offs; 549 u16 tuner_en = dib0070_read_reg(state, 0x20);
440 struct dib0070_state *state = fe->tuner_priv; 550 u16 offset;
441 551
442 if (state->cfg->sleep) 552 dib0070_write_reg(state, 0x18, 0x07ff);
443 state->cfg->sleep(fe, 0); 553 dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
444 554 dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
445 dib0070_write_reg(state, 0x0f, 0x6d81); 555 msleep(9);
446 dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); 556 offset = dib0070_read_reg(state, 0x19);
447 msleep(9); 557 dib0070_write_reg(state, 0x20, tuner_en);
448 wbd_offs = dib0070_read_reg(state, 0x19); 558 return offset;
449 dib0070_write_reg(state, 0x20, 0); 559}
450 state->wbd_ff_offset = ((wbd_offs * 8 * 18 / 33 + 1) / 2);
451 dprintk( "WBDStart = %d (Vargen) - FF = %hd", (u32) wbd_offs * 1800/1024, state->wbd_ff_offset);
452
453 if (state->cfg->sleep)
454 state->cfg->sleep(fe, 1);
455 560
561static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
562{
563 u8 gain;
564 for (gain = 6; gain < 8; gain++) {
565 state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
566 dprintk( "Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]);
567 }
456} 568}
457 569
458u16 dib0070_wbd_offset(struct dvb_frontend *fe) 570u16 dib0070_wbd_offset(struct dvb_frontend *fe)
459{ 571{
460 struct dib0070_state *st = fe->tuner_priv; 572 struct dib0070_state *st = fe->tuner_priv;
461 return st->wbd_ff_offset; 573 return st->wbd_offset_3_3[st->wbd_gain_current - 6];
462} 574}
463 575
464EXPORT_SYMBOL(dib0070_wbd_offset); 576EXPORT_SYMBOL(dib0070_wbd_offset);
465static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
466{
467 struct dib0070_state *state = fe->tuner_priv;
468 u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
469 dprintk( "CTRL_LO5: 0x%x", lo5);
470 return dib0070_write_reg(state, 0x15, lo5);
471}
472
473#define pgm_read_word(w) (*w) 577#define pgm_read_word(w) (*w)
474static int dib0070_reset(struct dib0070_state *state) 578static int dib0070_reset(struct dvb_frontend *fe)
475{ 579{
580 struct dib0070_state *state = fe->tuner_priv;
476 u16 l, r, *n; 581 u16 l, r, *n;
477 582
478 HARD_RESET(state); 583 HARD_RESET(state);
@@ -482,6 +587,8 @@ static int dib0070_reset(struct dib0070_state *state)
482 if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) 587 if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
483 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; 588 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
484 else 589 else
590#else
591#warning forcing SBAND
485#endif 592#endif
486 state->revision = DIB0070S_P1A; 593 state->revision = DIB0070S_P1A;
487 594
@@ -511,24 +618,27 @@ static int dib0070_reset(struct dib0070_state *state)
511 else 618 else
512 r = 2; 619 r = 2;
513 620
621
514 r |= state->cfg->osc_buffer_state << 3; 622 r |= state->cfg->osc_buffer_state << 3;
515 623
516 dib0070_write_reg(state, 0x10, r); 624 dib0070_write_reg(state, 0x10, r);
517 dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 4)); 625 dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
518 626
519 if (state->cfg->invert_iq) { 627 if (state->cfg->invert_iq) {
520 r = dib0070_read_reg(state, 0x02) & 0xffdf; 628 r = dib0070_read_reg(state, 0x02) & 0xffdf;
521 dib0070_write_reg(state, 0x02, r | (1 << 5)); 629 dib0070_write_reg(state, 0x02, r | (1 << 5));
522 } 630 }
523 631
524 632 if (state->revision == DIB0070S_P1A)
525 if (state->revision == DIB0070S_P1A) 633 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
526 dib0070_set_ctrl_lo5(state->fe, 4, 7, 3, 1); 634 else
527 else 635 dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter);
528 dib0070_set_ctrl_lo5(state->fe, 4, 4, 2, 0);
529 636
530 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); 637 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
531 return 0; 638
639 dib0070_wbd_offset_calibration(state);
640
641 return 0;
532} 642}
533 643
534 644
@@ -539,7 +649,7 @@ static int dib0070_release(struct dvb_frontend *fe)
539 return 0; 649 return 0;
540} 650}
541 651
542static struct dvb_tuner_ops dib0070_ops = { 652static const struct dvb_tuner_ops dib0070_ops = {
543 .info = { 653 .info = {
544 .name = "DiBcom DiB0070", 654 .name = "DiBcom DiB0070",
545 .frequency_min = 45000000, 655 .frequency_min = 45000000,
@@ -550,7 +660,8 @@ static struct dvb_tuner_ops dib0070_ops = {
550 660
551 .init = dib0070_wakeup, 661 .init = dib0070_wakeup,
552 .sleep = dib0070_sleep, 662 .sleep = dib0070_sleep,
553 .set_params = dib0070_tune_digital, 663 .set_params = dib0070_tune,
664
554// .get_frequency = dib0070_get_frequency, 665// .get_frequency = dib0070_get_frequency,
555// .get_bandwidth = dib0070_get_bandwidth 666// .get_bandwidth = dib0070_get_bandwidth
556}; 667};
@@ -566,11 +677,9 @@ struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter
566 state->fe = fe; 677 state->fe = fe;
567 fe->tuner_priv = state; 678 fe->tuner_priv = state;
568 679
569 if (dib0070_reset(state) != 0) 680 if (dib0070_reset(fe) != 0)
570 goto free_mem; 681 goto free_mem;
571 682
572 dib0070_wbd_calibration(fe);
573
574 printk(KERN_INFO "DiB0070: successfully identified\n"); 683 printk(KERN_INFO "DiB0070: successfully identified\n");
575 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops)); 684 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
576 685
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h
index 9670f5d20cfb..8c1c51cfaff1 100644
--- a/drivers/media/dvb/frontends/dib0070.h
+++ b/drivers/media/dvb/frontends/dib0070.h
@@ -15,6 +15,11 @@ struct i2c_adapter;
15 15
16#define DEFAULT_DIB0070_I2C_ADDRESS 0x60 16#define DEFAULT_DIB0070_I2C_ADDRESS 0x60
17 17
18struct dib0070_wbd_gain_cfg {
19 u16 freq;
20 u16 wbd_gain_val;
21};
22
18struct dib0070_config { 23struct dib0070_config {
19 u8 i2c_address; 24 u8 i2c_address;
20 25
@@ -35,6 +40,12 @@ struct dib0070_config {
35 u8 force_crystal_mode; /* if == 0 -> decision is made in the driver default: <24 -> 2, >=24 -> 1 */ 40 u8 force_crystal_mode; /* if == 0 -> decision is made in the driver default: <24 -> 2, >=24 -> 1 */
36 41
37 u8 flip_chip; 42 u8 flip_chip;
43 u8 enable_third_order_filter;
44 u8 charge_pump;
45
46 const struct dib0070_wbd_gain_cfg * wbd_gain;
47
48 u8 vga_filter;
38}; 49};
39 50
40#if defined(CONFIG_DVB_TUNER_DIB0070) || (defined(CONFIG_DVB_TUNER_DIB0070_MODULE) && defined(MODULE)) 51#if defined(CONFIG_DVB_TUNER_DIB0070) || (defined(CONFIG_DVB_TUNER_DIB0070_MODULE) && defined(MODULE))