aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/dib0070.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/frontends/dib0070.c')
-rw-r--r--drivers/media/dvb/frontends/dib0070.c803
1 files changed, 463 insertions, 340 deletions
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c
index da92cbe1b8ea..2be17b93e0bd 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,27 +36,65 @@ 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)
38{ 93{
39 u8 b[2]; 94 u8 b[2];
40 struct i2c_msg msg[2] = { 95 struct i2c_msg msg[2] = {
41 { .addr = state->cfg->i2c_address, .flags = 0, .buf = &reg, .len = 1 }, 96 {.addr = state->cfg->i2c_address,.flags = 0,.buf = &reg,.len = 1},
42 { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 }, 97 {.addr = state->cfg->i2c_address,.flags = I2C_M_RD,.buf = b,.len = 2},
43 }; 98 };
44 if (i2c_transfer(state->i2c, msg, 2) != 2) { 99 if (i2c_transfer(state->i2c, msg, 2) != 2) {
45 printk(KERN_WARNING "DiB0070 I2C read failed\n"); 100 printk(KERN_WARNING "DiB0070 I2C read failed\n");
@@ -51,7 +106,7 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
51static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) 106static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
52{ 107{
53 u8 b[3] = { reg, val >> 8, val & 0xff }; 108 u8 b[3] = { reg, val >> 8, val & 0xff };
54 struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 }; 109 struct i2c_msg msg = {.addr = state->cfg->i2c_address,.flags = 0,.buf = b,.len = 3 };
55 if (i2c_transfer(state->i2c, &msg, 1) != 1) { 110 if (i2c_transfer(state->i2c, &msg, 1) != 1) {
56 printk(KERN_WARNING "DiB0070 I2C write failed\n"); 111 printk(KERN_WARNING "DiB0070 I2C write failed\n");
57 return -EREMOTEIO; 112 return -EREMOTEIO;
@@ -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 *state = fe->tuner_priv;
67 u16 tmp = 0; 128 u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
68 tmp = dib0070_read_reg(st, 0x02) & 0x3fff; 129
130 if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 7000)
131 tmp |= (0 << 14);
132 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 6000)
133 tmp |= (1 << 14);
134 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 5000)
135 tmp |= (2 << 14);
136 else
137 tmp |= (3 << 14);
69 138
70 switch(BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)) { 139 dib0070_write_reg(state, 0x02, tmp);
71 case 8000: 140
72 tmp |= (0 << 14); 141 /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
73 break; 142 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
74 case 7000: 143 u16 value = dib0070_read_reg(state, 0x17);
75 tmp |= (1 << 14); 144
76 break; 145 dib0070_write_reg(state, 0x17, value & 0xfffc);
77 case 6000: 146 tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
78 tmp |= (2 << 14); 147 dib0070_write_reg(state, 0x01, tmp | (60 << 9));
79 break; 148
80 case 5000: 149 dib0070_write_reg(state, 0x17, value);
81 default:
82 tmp |= (3 << 14);
83 break;
84 } 150 }
85 dib0070_write_reg(st, 0x02, tmp);
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 *state, 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(state, 0x0f, 0xed10);
163 dib0070_write_reg(state, 0x17, 0x0034);
95 164
96 dib0070_write_reg(st, 0x0f, 0xed10); 165 dib0070_write_reg(state, 0x18, 0x0032);
97 dib0070_write_reg(st, 0x17, 0x0034); 166 state->step = state->captrim = state->fcaptrim = 64;
167 state->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 state->step /= 2;
173 dib0070_write_reg(state, 0x14, state->lo4 | state->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 { 179 adc = dib0070_read_reg(state, 0x19);
105 step /= 2;
106 dib0070_write_reg(st, 0x14, LO4 | captrim);
107 msleep(1);
108 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", state->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,379 +188,430 @@ 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 < state->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)", state->captrim, adc, state->adc_diff);
122 adc_diff = adc; 193 state->adc_diff = adc;
123 fcaptrim = captrim; 194 state->fcaptrim = state->captrim;
124 195
196 }
197 state->captrim += (step_sign * state->step);
125 198
199 if (state->step >= 1)
200 *tune_state = CT_TUNER_STEP_1;
201 else
202 *tune_state = CT_TUNER_STEP_3;
126 203
127 } 204 } else if (*tune_state == CT_TUNER_STEP_3) {
128 captrim += (step_sign * step); 205 dib0070_write_reg(state, 0x14, state->lo4 | state->fcaptrim);
129 } while (step >= 1); 206 dib0070_write_reg(state, 0x18, 0x07ff);
207 *tune_state = CT_TUNER_STEP_4;
208 }
130 209
131 dib0070_write_reg(st, 0x14, LO4 | fcaptrim); 210 return ret;
132 dib0070_write_reg(st, 0x18, 0x07ff);
133} 211}
134 212
135#define LPF 100 // define for the loop filter 100kHz by default 16-07-06 213static 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{ 214{
141 struct dib0070_state *st = fe->tuner_priv; 215 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); 216 u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
143 217 dprintk("CTRL_LO5: 0x%x", lo5);
144 u8 band = BAND_OF_FREQUENCY(freq), c; 218 return dib0070_write_reg(state, 0x15, lo5);
219}
145 220
146 /*******************VCO***********************************/ 221void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
147 u16 lo4 = 0; 222{
223 struct dib0070_state *state = fe->tuner_priv;
148 224
149 u8 REFDIV, PRESC = 2; 225 if (open) {
150 u32 FBDiv, Rest, FREF, VCOF_kHz; 226 dib0070_write_reg(state, 0x1b, 0xff00);
151 u16 Num, Den; 227 dib0070_write_reg(state, 0x1a, 0x0000);
152 /*******************FrontEnd******************************/ 228 } else {
153 u16 value = 0; 229 dib0070_write_reg(state, 0x1b, 0x4112);
230 if (state->cfg->vga_filter != 0) {
231 dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
232 dprintk("vga filter register is set to %x", state->cfg->vga_filter);
233 } else
234 dib0070_write_reg(state, 0x1a, 0x0009);
235 }
236}
154 237
155 dprintk( "Tuning for Band: %hd (%d kHz)", band, freq); 238EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
239struct dib0070_tuning {
240 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
241 u8 switch_trim;
242 u8 vco_band;
243 u8 hfdiv;
244 u8 vco_multi;
245 u8 presc;
246 u8 wbdmux;
247 u16 tuner_enable;
248};
156 249
250struct dib0070_lna_match {
251 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
252 u8 lna_band;
253};
157 254
158 dib0070_write_reg(st, 0x17, 0x30); 255static const struct dib0070_tuning dib0070s_tuning_table[] = {
256 {570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800}, /* UHF */
257 {700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800},
258 {863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800},
259 {1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND */
260 {1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400},
261 {2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400},
262 {0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000}, /* SBAND */
263};
159 264
160 dib0070_set_bandwidth(fe, ch); /* c is used as HF */ 265static const struct dib0070_tuning dib0070_tuning_table[] = {
161 switch (st->revision) { 266 {115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000}, /* FM below 92MHz cannot be tuned */
162 case DIB0070S_P1A: 267 {179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000}, /* VHF */
163 switch (band) { 268 {189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000},
164 case BAND_LBAND: 269 {250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000},
165 LO4_SET_VCO_HFDIV(lo4, 1, 1); 270 {569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800}, /* UHF */
166 c = 2; 271 {699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800},
167 break; 272 {863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800},
168 case BAND_SBAND: 273 {0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND or everything higher than UHF */
169 LO4_SET_VCO_HFDIV(lo4, 0, 0); 274};
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 275
230 dprintk( "HFDIV code: %hd", (lo4 >> 7) & 0xf); 276static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
231 dprintk( "VCO = %hd", (lo4 >> 11) & 0x3); 277 {180000, 0}, /* VHF */
278 {188000, 1},
279 {196400, 2},
280 {250000, 3},
281 {550000, 0}, /* UHF */
282 {590000, 1},
283 {666000, 3},
284 {864000, 5},
285 {1500000, 0}, /* LBAND or everything higher than UHF */
286 {1600000, 1},
287 {2000000, 3},
288 {0xffffffff, 7},
289};
232 290
291static const struct dib0070_lna_match dib0070_lna[] = {
292 {180000, 0}, /* VHF */
293 {188000, 1},
294 {196400, 2},
295 {250000, 3},
296 {550000, 2}, /* UHF */
297 {650000, 3},
298 {750000, 5},
299 {850000, 6},
300 {864000, 7},
301 {1500000, 0}, /* LBAND or everything higher than UHF */
302 {1600000, 1},
303 {2000000, 3},
304 {0xffffffff, 7},
305};
233 306
234 VCOF_kHz = (c * freq) * 2; 307#define LPF 100 // define for the loop filter 100kHz by default 16-07-06
235 dprintk( "VCOF in kHz: %d ((%hd*%d) << 1))",VCOF_kHz, c, freq); 308static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
309{
310 struct dib0070_state *state = fe->tuner_priv;
236 311
237 switch (band) { 312 const struct dib0070_tuning *tune;
238 case BAND_VHF: 313 const struct dib0070_lna_match *lna_match;
239 REFDIV = (u8) ((st->cfg->clock_khz + 9999) / 10000);
240 break;
241 case BAND_FM:
242 REFDIV = (u8) ((st->cfg->clock_khz) / 1000);
243 break;
244 default:
245 REFDIV = (u8) ( st->cfg->clock_khz / 10000);
246 break;
247 }
248 FREF = st->cfg->clock_khz / REFDIV;
249 314
250 dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF); 315 enum frontend_tune_state *tune_state = &state->tune_state;
316 int ret = 10; /* 1ms is the default delay most of the time */
251 317
318 u8 band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000);
319 u32 freq = fe->dtv_property_cache.frequency / 1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
252 320
321#ifdef CONFIG_SYS_ISDBT
322 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
323 if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
324 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
325 || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
326 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
327 || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
328 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
329 freq += 850;
330#endif
331 if (state->current_rf != freq) {
253 332
254 switch (st->revision) { 333 switch (state->revision) {
255 case DIB0070S_P1A: 334 case DIB0070S_P1A:
256 FBDiv = (VCOF_kHz / PRESC / FREF); 335 tune = dib0070s_tuning_table;
257 Rest = (VCOF_kHz / PRESC) - FBDiv * FREF; 336 lna_match = dib0070_lna;
258 break; 337 break;
259
260 case DIB0070_P1G:
261 case DIB0070_P1F:
262 default: 338 default:
263 FBDiv = (freq / (FREF / 2)); 339 tune = dib0070_tuning_table;
264 Rest = 2 * freq - FBDiv * FREF; 340 if (state->cfg->flip_chip)
341 lna_match = dib0070_lna_flip_chip;
342 else
343 lna_match = dib0070_lna;
265 break; 344 break;
266 } 345 }
267 346 while (freq > tune->max_freq) /* find the right one */
268 347 tune++;
269 if (Rest < LPF) Rest = 0; 348 while (freq > lna_match->max_freq) /* find the right one */
270 else if (Rest < 2 * LPF) Rest = 2 * LPF; 349 lna_match++;
271 else if (Rest > (FREF - LPF)) { Rest = 0 ; FBDiv += 1; }
272 else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF;
273 Rest = (Rest * 6528) / (FREF / 10);
274 dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest);
275
276 Num = 0;
277 Den = 1;
278 350
279 if (Rest > 0) { 351 state->current_tune_table_index = tune;
280 LO4_SET_SD(lo4, 1); 352 state->lna_match = lna_match;
281 Den = 255;
282 Num = (u16)Rest;
283 } 353 }
284 dprintk( "Num: %hd, Den: %hd, SD: %hd",Num, Den, (lo4 >> 12) & 0x1);
285 354
355 if (*tune_state == CT_TUNER_START) {
356 dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
357 if (state->current_rf != freq) {
358 u8 REFDIV;
359 u32 FBDiv, Rest, FREF, VCOF_kHz;
360 u8 Den;
286 361
362 state->current_rf = freq;
363 state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
287 364
288 dib0070_write_reg(st, 0x11, (u16)FBDiv); 365 dib0070_write_reg(state, 0x17, 0x30);
289 366
367 VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
290 368
291 dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV); 369 switch (band) {
292 370 case BAND_VHF:
371 REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
372 break;
373 case BAND_FM:
374 REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
375 break;
376 default:
377 REFDIV = (u8) (state->cfg->clock_khz / 10000);
378 break;
379 }
380 FREF = state->cfg->clock_khz / REFDIV;
381
382 switch (state->revision) {
383 case DIB0070S_P1A:
384 FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
385 Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
386 break;
387
388 case DIB0070_P1G:
389 case DIB0070_P1F:
390 default:
391 FBDiv = (freq / (FREF / 2));
392 Rest = 2 * freq - FBDiv * FREF;
393 break;
394 }
293 395
294 dib0070_write_reg(st, 0x13, Num); 396 if (Rest < LPF)
397 Rest = 0;
398 else if (Rest < 2 * LPF)
399 Rest = 2 * LPF;
400 else if (Rest > (FREF - LPF)) {
401 Rest = 0;
402 FBDiv += 1;
403 } else if (Rest > (FREF - 2 * LPF))
404 Rest = FREF - 2 * LPF;
405 Rest = (Rest * 6528) / (FREF / 10);
406
407 Den = 1;
408 if (Rest > 0) {
409 state->lo4 |= (1 << 14) | (1 << 12);
410 Den = 255;
411 }
295 412
413 dib0070_write_reg(state, 0x11, (u16) FBDiv);
414 dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
415 dib0070_write_reg(state, 0x13, (u16) Rest);
296 416
297 value = 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001; 417 if (state->revision == DIB0070S_P1A) {
298 418
299 switch (band) { 419 if (band == BAND_SBAND) {
300 case BAND_UHF: value |= 0x4000 | 0x0800; break; 420 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
301 case BAND_LBAND: value |= 0x2000 | 0x0400; break; 421 dib0070_write_reg(state, 0x1d, 0xFFFF);
302 default: value |= 0x8000 | 0x1000; break; 422 } else
303 } 423 dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
304 dib0070_write_reg(st, 0x20, value); 424 }
305 425
306 dib0070_captrim(st, lo4); 426 dib0070_write_reg(state, 0x20,
307 if (st->revision == DIB0070S_P1A) { 427 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
308 if (band == BAND_SBAND)
309 dib0070_write_reg(st, 0x15, 0x16e2);
310 else
311 dib0070_write_reg(st, 0x15, 0x56e5);
312 }
313 428
429 dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF);
430 dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest);
431 dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
432 dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv);
433 dprintk("VCO = %hd", state->current_tune_table_index->vco_band);
434 dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
314 435
436 *tune_state = CT_TUNER_STEP_0;
437 } else { /* we are already tuned to this frequency - the configuration is correct */
438 ret = 50; /* wakeup time */
439 *tune_state = CT_TUNER_STEP_5;
440 }
441 } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
442
443 ret = dib0070_captrim(state, tune_state);
444
445 } else if (*tune_state == CT_TUNER_STEP_4) {
446 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
447 if (tmp != NULL) {
448 while (freq / 1000 > tmp->freq) /* find the right one */
449 tmp++;
450 dib0070_write_reg(state, 0x0f,
451 (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (state->
452 current_tune_table_index->
453 wbdmux << 0));
454 state->wbd_gain_current = tmp->wbd_gain_val;
455 } else {
456 dib0070_write_reg(state, 0x0f,
457 (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index->
458 wbdmux << 0));
459 state->wbd_gain_current = 6;
460 }
315 461
316 switch (band) { 462 dib0070_write_reg(state, 0x06, 0x3fff);
317 case BAND_UHF: value = 0x7c82; break; 463 dib0070_write_reg(state, 0x07,
318 case BAND_LBAND: value = 0x7c84; break; 464 (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
319 default: value = 0x7c81; break; 465 dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
320 } 466 dib0070_write_reg(state, 0x0d, 0x0d80);
321 dib0070_write_reg(st, 0x0f, value); 467
322 dib0070_write_reg(st, 0x06, 0x3fff); 468 dib0070_write_reg(state, 0x18, 0x07ff);
323 469 dib0070_write_reg(state, 0x17, 0x0033);
324 /* Front End */ 470
325 /* c == TUNE, value = SWITCH */ 471 *tune_state = CT_TUNER_STEP_5;
326 c = 0; 472 } else if (*tune_state == CT_TUNER_STEP_5) {
327 value = 0; 473 dib0070_set_bandwidth(fe, ch);
328 switch (band) { 474 *tune_state = CT_TUNER_STOP;
329 case BAND_FM: 475 } else {
330 c = 0; value = 1; 476 ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
331 break;
332
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
341 case BAND_LBAND:
342 if (freq <= 1500000) c = 0;
343 else if (freq <= 1600000) c = 1;
344 else c = 3;
345 break;
346
347 case BAND_SBAND:
348 c = 7;
349 dib0070_write_reg(st, 0x1d,0xFFFF);
350 break;
351
352 case BAND_UHF:
353 default:
354 if (st->cfg->flip_chip) {
355 if (freq <= 550000) c = 0;
356 else if (freq <= 590000) c = 1;
357 else if (freq <= 666000) c = 3;
358 else c = 5;
359 } else {
360 if (freq <= 550000) c = 2;
361 else if (freq <= 650000) c = 3;
362 else if (freq <= 750000) c = 5;
363 else if (freq <= 850000) c = 6;
364 else c = 7;
365 }
366 value = 2;
367 break;
368 } 477 }
478 return ret;
479}
369 480
370 /* default: LNA_MATCH=7, BIAS=3 */ 481static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
371 dib0070_write_reg(st, 0x07, (value << 11) | (7 << 8) | (c << 3) | (3 << 0)); 482{
372 dib0070_write_reg(st, 0x08, (c << 10) | (3 << 7) | (127)); 483 struct dib0070_state *state = fe->tuner_priv;
373 dib0070_write_reg(st, 0x0d, 0x0d80); 484 uint32_t ret;
374 485
486 state->tune_state = CT_TUNER_START;
375 487
376 dib0070_write_reg(st, 0x18, 0x07ff); 488 do {
377 dib0070_write_reg(st, 0x17, 0x0033); 489 ret = dib0070_tune_digital(fe, p);
490 if (ret != FE_CALLBACK_TIME_NEVER)
491 msleep(ret / 10);
492 else
493 break;
494 } while (state->tune_state != CT_TUNER_STOP);
378 495
379 return 0; 496 return 0;
380} 497}
381 498
382static int dib0070_wakeup(struct dvb_frontend *fe) 499static int dib0070_wakeup(struct dvb_frontend *fe)
383{ 500{
384 struct dib0070_state *st = fe->tuner_priv; 501 struct dib0070_state *state = fe->tuner_priv;
385 if (st->cfg->sleep) 502 if (state->cfg->sleep)
386 st->cfg->sleep(fe, 0); 503 state->cfg->sleep(fe, 0);
387 return 0; 504 return 0;
388} 505}
389 506
390static int dib0070_sleep(struct dvb_frontend *fe) 507static int dib0070_sleep(struct dvb_frontend *fe)
391{ 508{
392 struct dib0070_state *st = fe->tuner_priv; 509 struct dib0070_state *state = fe->tuner_priv;
393 if (st->cfg->sleep) 510 if (state->cfg->sleep)
394 st->cfg->sleep(fe, 1); 511 state->cfg->sleep(fe, 1);
395 return 0; 512 return 0;
396} 513}
397 514
398static u16 dib0070_p1f_defaults[] = 515static const u16 dib0070_p1f_defaults[] = {
399
400{
401 7, 0x02, 516 7, 0x02,
402 0x0008, 517 0x0008,
403 0x0000, 518 0x0000,
404 0x0000, 519 0x0000,
405 0x0000, 520 0x0000,
406 0x0000, 521 0x0000,
407 0x0002, 522 0x0002,
408 0x0100, 523 0x0100,
409 524
410 3, 0x0d, 525 3, 0x0d,
411 0x0d80, 526 0x0d80,
412 0x0001, 527 0x0001,
413 0x0000, 528 0x0000,
414 529
415 4, 0x11, 530 4, 0x11,
416 0x0000, 531 0x0000,
417 0x0103, 532 0x0103,
418 0x0000, 533 0x0000,
419 0x0000, 534 0x0000,
420 535
421 3, 0x16, 536 3, 0x16,
422 0x0004 | 0x0040, 537 0x0004 | 0x0040,
423 0x0030, 538 0x0030,
424 0x07ff, 539 0x07ff,
425 540
426 6, 0x1b, 541 6, 0x1b,
427 0x4112, 542 0x4112,
428 0xff00, 543 0xff00,
429 0xc07f, 544 0xc07f,
430 0x0000, 545 0x0000,
431 0x0180, 546 0x0180,
432 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001, 547 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
433 548
434 0, 549 0,
435}; 550};
436 551
437static void dib0070_wbd_calibration(struct dvb_frontend *fe) 552static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
438{ 553{
439 u16 wbd_offs; 554 u16 tuner_en = dib0070_read_reg(state, 0x20);
440 struct dib0070_state *state = fe->tuner_priv; 555 u16 offset;
441
442 if (state->cfg->sleep)
443 state->cfg->sleep(fe, 0);
444 556
445 dib0070_write_reg(state, 0x0f, 0x6d81); 557 dib0070_write_reg(state, 0x18, 0x07ff);
446 dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); 558 dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
559 dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
447 msleep(9); 560 msleep(9);
448 wbd_offs = dib0070_read_reg(state, 0x19); 561 offset = dib0070_read_reg(state, 0x19);
449 dib0070_write_reg(state, 0x20, 0); 562 dib0070_write_reg(state, 0x20, tuner_en);
450 state->wbd_ff_offset = ((wbd_offs * 8 * 18 / 33 + 1) / 2); 563 return offset;
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
456} 564}
457 565
458u16 dib0070_wbd_offset(struct dvb_frontend *fe) 566static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
459{ 567{
460 struct dib0070_state *st = fe->tuner_priv; 568 u8 gain;
461 return st->wbd_ff_offset; 569 for (gain = 6; gain < 8; gain++) {
570 state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
571 dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain - 6]);
572 }
462} 573}
463 574
464EXPORT_SYMBOL(dib0070_wbd_offset); 575u16 dib0070_wbd_offset(struct dvb_frontend *fe)
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{ 576{
467 struct dib0070_state *state = fe->tuner_priv; 577 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); 578 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
469 dprintk( "CTRL_LO5: 0x%x", lo5); 579 u32 freq = fe->dtv_property_cache.frequency / 1000;
470 return dib0070_write_reg(state, 0x15, lo5); 580
581 if (tmp != NULL) {
582 while (freq / 1000 > tmp->freq) /* find the right one */
583 tmp++;
584 state->wbd_gain_current = tmp->wbd_gain_val;
585 } else
586 state->wbd_gain_current = 6;
587
588 return state->wbd_offset_3_3[state->wbd_gain_current - 6];
471} 589}
472 590
591EXPORT_SYMBOL(dib0070_wbd_offset);
592
473#define pgm_read_word(w) (*w) 593#define pgm_read_word(w) (*w)
474static int dib0070_reset(struct dib0070_state *state) 594static int dib0070_reset(struct dvb_frontend *fe)
475{ 595{
596 struct dib0070_state *state = fe->tuner_priv;
476 u16 l, r, *n; 597 u16 l, r, *n;
477 598
478 HARD_RESET(state); 599 HARD_RESET(state);
479 600
480
481#ifndef FORCE_SBAND_TUNER 601#ifndef FORCE_SBAND_TUNER
482 if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) 602 if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
483 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; 603 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
484 else 604 else
605#else
606#warning forcing SBAND
485#endif 607#endif
486 state->revision = DIB0070S_P1A; 608 state->revision = DIB0070S_P1A;
487 609
488 /* P1F or not */ 610 /* P1F or not */
489 dprintk( "Revision: %x", state->revision); 611 dprintk("Revision: %x", state->revision);
490 612
491 if (state->revision == DIB0070_P1D) { 613 if (state->revision == DIB0070_P1D) {
492 dprintk( "Error: this driver is not to be used meant for P1D or earlier"); 614 dprintk("Error: this driver is not to be used meant for P1D or earlier");
493 return -EINVAL; 615 return -EINVAL;
494 } 616 }
495 617
@@ -498,7 +620,7 @@ static int dib0070_reset(struct dib0070_state *state)
498 while (l) { 620 while (l) {
499 r = pgm_read_word(n++); 621 r = pgm_read_word(n++);
500 do { 622 do {
501 dib0070_write_reg(state, (u8)r, pgm_read_word(n++)); 623 dib0070_write_reg(state, (u8) r, pgm_read_word(n++));
502 r++; 624 r++;
503 } while (--l); 625 } while (--l);
504 l = pgm_read_word(n++); 626 l = pgm_read_word(n++);
@@ -514,24 +636,25 @@ static int dib0070_reset(struct dib0070_state *state)
514 r |= state->cfg->osc_buffer_state << 3; 636 r |= state->cfg->osc_buffer_state << 3;
515 637
516 dib0070_write_reg(state, 0x10, r); 638 dib0070_write_reg(state, 0x10, r);
517 dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 4)); 639 dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
518 640
519 if (state->cfg->invert_iq) { 641 if (state->cfg->invert_iq) {
520 r = dib0070_read_reg(state, 0x02) & 0xffdf; 642 r = dib0070_read_reg(state, 0x02) & 0xffdf;
521 dib0070_write_reg(state, 0x02, r | (1 << 5)); 643 dib0070_write_reg(state, 0x02, r | (1 << 5));
522 } 644 }
523 645
524
525 if (state->revision == DIB0070S_P1A) 646 if (state->revision == DIB0070S_P1A)
526 dib0070_set_ctrl_lo5(state->fe, 4, 7, 3, 1); 647 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
527 else 648 else
528 dib0070_set_ctrl_lo5(state->fe, 4, 4, 2, 0); 649 dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter);
529 650
530 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); 651 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
652
653 dib0070_wbd_offset_calibration(state);
654
531 return 0; 655 return 0;
532} 656}
533 657
534
535static int dib0070_release(struct dvb_frontend *fe) 658static int dib0070_release(struct dvb_frontend *fe)
536{ 659{
537 kfree(fe->tuner_priv); 660 kfree(fe->tuner_priv);
@@ -539,23 +662,24 @@ static int dib0070_release(struct dvb_frontend *fe)
539 return 0; 662 return 0;
540} 663}
541 664
542static struct dvb_tuner_ops dib0070_ops = { 665static const struct dvb_tuner_ops dib0070_ops = {
543 .info = { 666 .info = {
544 .name = "DiBcom DiB0070", 667 .name = "DiBcom DiB0070",
545 .frequency_min = 45000000, 668 .frequency_min = 45000000,
546 .frequency_max = 860000000, 669 .frequency_max = 860000000,
547 .frequency_step = 1000, 670 .frequency_step = 1000,
548 }, 671 },
549 .release = dib0070_release, 672 .release = dib0070_release,
550 673
551 .init = dib0070_wakeup, 674 .init = dib0070_wakeup,
552 .sleep = dib0070_sleep, 675 .sleep = dib0070_sleep,
553 .set_params = dib0070_tune_digital, 676 .set_params = dib0070_tune,
554// .get_frequency = dib0070_get_frequency, 677
555// .get_bandwidth = dib0070_get_bandwidth 678// .get_frequency = dib0070_get_frequency,
679// .get_bandwidth = dib0070_get_bandwidth
556}; 680};
557 681
558struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) 682struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
559{ 683{
560 struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL); 684 struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
561 if (state == NULL) 685 if (state == NULL)
@@ -563,25 +687,24 @@ struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter
563 687
564 state->cfg = cfg; 688 state->cfg = cfg;
565 state->i2c = i2c; 689 state->i2c = i2c;
566 state->fe = fe; 690 state->fe = fe;
567 fe->tuner_priv = state; 691 fe->tuner_priv = state;
568 692
569 if (dib0070_reset(state) != 0) 693 if (dib0070_reset(fe) != 0)
570 goto free_mem; 694 goto free_mem;
571 695
572 dib0070_wbd_calibration(fe);
573
574 printk(KERN_INFO "DiB0070: successfully identified\n"); 696 printk(KERN_INFO "DiB0070: successfully identified\n");
575 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops)); 697 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
576 698
577 fe->tuner_priv = state; 699 fe->tuner_priv = state;
578 return fe; 700 return fe;
579 701
580free_mem: 702 free_mem:
581 kfree(state); 703 kfree(state);
582 fe->tuner_priv = NULL; 704 fe->tuner_priv = NULL;
583 return NULL; 705 return NULL;
584} 706}
707
585EXPORT_SYMBOL(dib0070_attach); 708EXPORT_SYMBOL(dib0070_attach);
586 709
587MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); 710MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");