diff options
Diffstat (limited to 'drivers/media/dvb/frontends/dib0070.c')
-rw-r--r-- | drivers/media/dvb/frontends/dib0070.c | 803 |
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; | |||
19 | module_param(debug, int, 0644); | 36 | module_param(debug, int, 0644); |
20 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | 37 | MODULE_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 | ||
52 | enum 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 | |||
29 | struct dib0070_state { | 67 | struct 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 | ||
37 | static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) | 92 | static 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 = ®, .len = 1 }, | 96 | {.addr = state->cfg->i2c_address,.flags = 0,.buf = ®,.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) | |||
51 | static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) | 106 | static 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 | ||
64 | static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) | 125 | static 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 | ||
89 | static void dib0070_captrim(struct dib0070_state *st, u16 LO4) | 154 | static 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 | 213 | static 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 | ||
139 | static 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***********************************/ | 221 | void 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); | 238 | EXPORT_SYMBOL(dib0070_ctrl_agc_filter); |
239 | struct 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 | ||
250 | struct 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); | 255 | static 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 */ | 265 | static 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); | 276 | static 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 | ||
291 | static 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); | 308 | static 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 */ | 481 | static 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 | ||
382 | static int dib0070_wakeup(struct dvb_frontend *fe) | 499 | static 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 | ||
390 | static int dib0070_sleep(struct dvb_frontend *fe) | 507 | static 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 | ||
398 | static u16 dib0070_p1f_defaults[] = | 515 | static 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 | ||
437 | static void dib0070_wbd_calibration(struct dvb_frontend *fe) | 552 | static 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 | ||
458 | u16 dib0070_wbd_offset(struct dvb_frontend *fe) | 566 | static 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 | ||
464 | EXPORT_SYMBOL(dib0070_wbd_offset); | 575 | u16 dib0070_wbd_offset(struct dvb_frontend *fe) |
465 | static 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 | ||
591 | EXPORT_SYMBOL(dib0070_wbd_offset); | ||
592 | |||
473 | #define pgm_read_word(w) (*w) | 593 | #define pgm_read_word(w) (*w) |
474 | static int dib0070_reset(struct dib0070_state *state) | 594 | static 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 | |||
535 | static int dib0070_release(struct dvb_frontend *fe) | 658 | static 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 | ||
542 | static struct dvb_tuner_ops dib0070_ops = { | 665 | static 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 | ||
558 | struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) | 682 | struct 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 | ||
580 | free_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 | |||
585 | EXPORT_SYMBOL(dib0070_attach); | 708 | EXPORT_SYMBOL(dib0070_attach); |
586 | 709 | ||
587 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | 710 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); |