diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/media/dvb/frontends/stb0899_algo.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'drivers/media/dvb/frontends/stb0899_algo.c')
-rw-r--r-- | drivers/media/dvb/frontends/stb0899_algo.c | 1522 |
1 files changed, 1522 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c new file mode 100644 index 00000000000..d70eee00f33 --- /dev/null +++ b/drivers/media/dvb/frontends/stb0899_algo.c | |||
@@ -0,0 +1,1522 @@ | |||
1 | /* | ||
2 | STB0899 Multistandard Frontend driver | ||
3 | Copyright (C) Manu Abraham (abraham.manu@gmail.com) | ||
4 | |||
5 | Copyright (C) ST Microelectronics | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
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 | #include "stb0899_drv.h" | ||
23 | #include "stb0899_priv.h" | ||
24 | #include "stb0899_reg.h" | ||
25 | |||
26 | static inline u32 stb0899_do_div(u64 n, u32 d) | ||
27 | { | ||
28 | /* wrap do_div() for ease of use */ | ||
29 | |||
30 | do_div(n, d); | ||
31 | return n; | ||
32 | } | ||
33 | |||
34 | #if 0 | ||
35 | /* These functions are currently unused */ | ||
36 | /* | ||
37 | * stb0899_calc_srate | ||
38 | * Compute symbol rate | ||
39 | */ | ||
40 | static u32 stb0899_calc_srate(u32 master_clk, u8 *sfr) | ||
41 | { | ||
42 | u64 tmp; | ||
43 | |||
44 | /* srate = (SFR * master_clk) >> 20 */ | ||
45 | |||
46 | /* sfr is of size 20 bit, stored with an offset of 4 bit */ | ||
47 | tmp = (((u32)sfr[0]) << 16) | (((u32)sfr[1]) << 8) | sfr[2]; | ||
48 | tmp &= ~0xf; | ||
49 | tmp *= master_clk; | ||
50 | tmp >>= 24; | ||
51 | |||
52 | return tmp; | ||
53 | } | ||
54 | |||
55 | /* | ||
56 | * stb0899_get_srate | ||
57 | * Get the current symbol rate | ||
58 | */ | ||
59 | static u32 stb0899_get_srate(struct stb0899_state *state) | ||
60 | { | ||
61 | struct stb0899_internal *internal = &state->internal; | ||
62 | u8 sfr[3]; | ||
63 | |||
64 | stb0899_read_regs(state, STB0899_SFRH, sfr, 3); | ||
65 | |||
66 | return stb0899_calc_srate(internal->master_clk, sfr); | ||
67 | } | ||
68 | #endif | ||
69 | |||
70 | /* | ||
71 | * stb0899_set_srate | ||
72 | * Set symbol frequency | ||
73 | * MasterClock: master clock frequency (hz) | ||
74 | * SymbolRate: symbol rate (bauds) | ||
75 | * return symbol frequency | ||
76 | */ | ||
77 | static u32 stb0899_set_srate(struct stb0899_state *state, u32 master_clk, u32 srate) | ||
78 | { | ||
79 | u32 tmp; | ||
80 | u8 sfr[3]; | ||
81 | |||
82 | dprintk(state->verbose, FE_DEBUG, 1, "-->"); | ||
83 | /* | ||
84 | * in order to have the maximum precision, the symbol rate entered into | ||
85 | * the chip is computed as the closest value of the "true value". | ||
86 | * In this purpose, the symbol rate value is rounded (1 is added on the bit | ||
87 | * below the LSB ) | ||
88 | * | ||
89 | * srate = (SFR * master_clk) >> 20 | ||
90 | * <=> | ||
91 | * SFR = srate << 20 / master_clk | ||
92 | * | ||
93 | * rounded: | ||
94 | * SFR = (srate << 21 + master_clk) / (2 * master_clk) | ||
95 | * | ||
96 | * stored as 20 bit number with an offset of 4 bit: | ||
97 | * sfr = SFR << 4; | ||
98 | */ | ||
99 | |||
100 | tmp = stb0899_do_div((((u64)srate) << 21) + master_clk, 2 * master_clk); | ||
101 | tmp <<= 4; | ||
102 | |||
103 | sfr[0] = tmp >> 16; | ||
104 | sfr[1] = tmp >> 8; | ||
105 | sfr[2] = tmp; | ||
106 | |||
107 | stb0899_write_regs(state, STB0899_SFRH, sfr, 3); | ||
108 | |||
109 | return srate; | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * stb0899_calc_derot_time | ||
114 | * Compute the amount of time needed by the derotator to lock | ||
115 | * SymbolRate: Symbol rate | ||
116 | * return: derotator time constant (ms) | ||
117 | */ | ||
118 | static long stb0899_calc_derot_time(long srate) | ||
119 | { | ||
120 | if (srate > 0) | ||
121 | return (100000 / (srate / 1000)); | ||
122 | else | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * stb0899_carr_width | ||
128 | * Compute the width of the carrier | ||
129 | * return: width of carrier (kHz or Mhz) | ||
130 | */ | ||
131 | long stb0899_carr_width(struct stb0899_state *state) | ||
132 | { | ||
133 | struct stb0899_internal *internal = &state->internal; | ||
134 | |||
135 | return (internal->srate + (internal->srate * internal->rolloff) / 100); | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * stb0899_first_subrange | ||
140 | * Compute the first subrange of the search | ||
141 | */ | ||
142 | static void stb0899_first_subrange(struct stb0899_state *state) | ||
143 | { | ||
144 | struct stb0899_internal *internal = &state->internal; | ||
145 | struct stb0899_params *params = &state->params; | ||
146 | struct stb0899_config *config = state->config; | ||
147 | |||
148 | int range = 0; | ||
149 | u32 bandwidth = 0; | ||
150 | |||
151 | if (config->tuner_get_bandwidth) { | ||
152 | stb0899_i2c_gate_ctrl(&state->frontend, 1); | ||
153 | config->tuner_get_bandwidth(&state->frontend, &bandwidth); | ||
154 | stb0899_i2c_gate_ctrl(&state->frontend, 0); | ||
155 | range = bandwidth - stb0899_carr_width(state) / 2; | ||
156 | } | ||
157 | |||
158 | if (range > 0) | ||
159 | internal->sub_range = min(internal->srch_range, range); | ||
160 | else | ||
161 | internal->sub_range = 0; | ||
162 | |||
163 | internal->freq = params->freq; | ||
164 | internal->tuner_offst = 0L; | ||
165 | internal->sub_dir = 1; | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | * stb0899_check_tmg | ||
170 | * check for timing lock | ||
171 | * internal.Ttiming: time to wait for loop lock | ||
172 | */ | ||
173 | static enum stb0899_status stb0899_check_tmg(struct stb0899_state *state) | ||
174 | { | ||
175 | struct stb0899_internal *internal = &state->internal; | ||
176 | int lock; | ||
177 | u8 reg; | ||
178 | s8 timing; | ||
179 | |||
180 | msleep(internal->t_derot); | ||
181 | |||
182 | stb0899_write_reg(state, STB0899_RTF, 0xf2); | ||
183 | reg = stb0899_read_reg(state, STB0899_TLIR); | ||
184 | lock = STB0899_GETFIELD(TLIR_TMG_LOCK_IND, reg); | ||
185 | timing = stb0899_read_reg(state, STB0899_RTF); | ||
186 | |||
187 | if (lock >= 42) { | ||
188 | if ((lock > 48) && (abs(timing) >= 110)) { | ||
189 | internal->status = ANALOGCARRIER; | ||
190 | dprintk(state->verbose, FE_DEBUG, 1, "-->ANALOG Carrier !"); | ||
191 | } else { | ||
192 | internal->status = TIMINGOK; | ||
193 | dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK !"); | ||
194 | } | ||
195 | } else { | ||
196 | internal->status = NOTIMING; | ||
197 | dprintk(state->verbose, FE_DEBUG, 1, "-->NO TIMING !"); | ||
198 | } | ||
199 | return internal->status; | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * stb0899_search_tmg | ||
204 | * perform a fs/2 zig-zag to find timing | ||
205 | */ | ||
206 | static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) | ||
207 | { | ||
208 | struct stb0899_internal *internal = &state->internal; | ||
209 | struct stb0899_params *params = &state->params; | ||
210 | |||
211 | short int derot_step, derot_freq = 0, derot_limit, next_loop = 3; | ||
212 | int index = 0; | ||
213 | u8 cfr[2]; | ||
214 | |||
215 | internal->status = NOTIMING; | ||
216 | |||
217 | /* timing loop computation & symbol rate optimisation */ | ||
218 | derot_limit = (internal->sub_range / 2L) / internal->mclk; | ||
219 | derot_step = (params->srate / 2L) / internal->mclk; | ||
220 | |||
221 | while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) { | ||
222 | index++; | ||
223 | derot_freq += index * internal->direction * derot_step; /* next derot zig zag position */ | ||
224 | |||
225 | if (abs(derot_freq) > derot_limit) | ||
226 | next_loop--; | ||
227 | |||
228 | if (next_loop) { | ||
229 | STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq)); | ||
230 | STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); | ||
231 | stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ | ||
232 | } | ||
233 | internal->direction = -internal->direction; /* Change zigzag direction */ | ||
234 | } | ||
235 | |||
236 | if (internal->status == TIMINGOK) { | ||
237 | stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ | ||
238 | internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]); | ||
239 | dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK ! Derot Freq = %d", internal->derot_freq); | ||
240 | } | ||
241 | |||
242 | return internal->status; | ||
243 | } | ||
244 | |||
245 | /* | ||
246 | * stb0899_check_carrier | ||
247 | * Check for carrier found | ||
248 | */ | ||
249 | static enum stb0899_status stb0899_check_carrier(struct stb0899_state *state) | ||
250 | { | ||
251 | struct stb0899_internal *internal = &state->internal; | ||
252 | u8 reg; | ||
253 | |||
254 | msleep(internal->t_derot); /* wait for derotator ok */ | ||
255 | |||
256 | reg = stb0899_read_reg(state, STB0899_CFD); | ||
257 | STB0899_SETFIELD_VAL(CFD_ON, reg, 1); | ||
258 | stb0899_write_reg(state, STB0899_CFD, reg); | ||
259 | |||
260 | reg = stb0899_read_reg(state, STB0899_DSTATUS); | ||
261 | dprintk(state->verbose, FE_DEBUG, 1, "--------------------> STB0899_DSTATUS=[0x%02x]", reg); | ||
262 | if (STB0899_GETFIELD(CARRIER_FOUND, reg)) { | ||
263 | internal->status = CARRIEROK; | ||
264 | dprintk(state->verbose, FE_DEBUG, 1, "-------------> CARRIEROK !"); | ||
265 | } else { | ||
266 | internal->status = NOCARRIER; | ||
267 | dprintk(state->verbose, FE_DEBUG, 1, "-------------> NOCARRIER !"); | ||
268 | } | ||
269 | |||
270 | return internal->status; | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * stb0899_search_carrier | ||
275 | * Search for a QPSK carrier with the derotator | ||
276 | */ | ||
277 | static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state) | ||
278 | { | ||
279 | struct stb0899_internal *internal = &state->internal; | ||
280 | |||
281 | short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3; | ||
282 | int index = 0; | ||
283 | u8 cfr[2]; | ||
284 | u8 reg; | ||
285 | |||
286 | internal->status = NOCARRIER; | ||
287 | derot_limit = (internal->sub_range / 2L) / internal->mclk; | ||
288 | derot_freq = internal->derot_freq; | ||
289 | |||
290 | reg = stb0899_read_reg(state, STB0899_CFD); | ||
291 | STB0899_SETFIELD_VAL(CFD_ON, reg, 1); | ||
292 | stb0899_write_reg(state, STB0899_CFD, reg); | ||
293 | |||
294 | do { | ||
295 | dprintk(state->verbose, FE_DEBUG, 1, "Derot Freq=%d, mclk=%d", derot_freq, internal->mclk); | ||
296 | if (stb0899_check_carrier(state) == NOCARRIER) { | ||
297 | index++; | ||
298 | last_derot_freq = derot_freq; | ||
299 | derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */ | ||
300 | |||
301 | if(abs(derot_freq) > derot_limit) | ||
302 | next_loop--; | ||
303 | |||
304 | if (next_loop) { | ||
305 | reg = stb0899_read_reg(state, STB0899_CFD); | ||
306 | STB0899_SETFIELD_VAL(CFD_ON, reg, 1); | ||
307 | stb0899_write_reg(state, STB0899_CFD, reg); | ||
308 | |||
309 | STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq)); | ||
310 | STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); | ||
311 | stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ | ||
312 | } | ||
313 | } | ||
314 | |||
315 | internal->direction = -internal->direction; /* Change zigzag direction */ | ||
316 | } while ((internal->status != CARRIEROK) && next_loop); | ||
317 | |||
318 | if (internal->status == CARRIEROK) { | ||
319 | stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ | ||
320 | internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]); | ||
321 | dprintk(state->verbose, FE_DEBUG, 1, "----> CARRIER OK !, Derot Freq=%d", internal->derot_freq); | ||
322 | } else { | ||
323 | internal->derot_freq = last_derot_freq; | ||
324 | } | ||
325 | |||
326 | return internal->status; | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * stb0899_check_data | ||
331 | * Check for data found | ||
332 | */ | ||
333 | static enum stb0899_status stb0899_check_data(struct stb0899_state *state) | ||
334 | { | ||
335 | struct stb0899_internal *internal = &state->internal; | ||
336 | struct stb0899_params *params = &state->params; | ||
337 | |||
338 | int lock = 0, index = 0, dataTime = 500, loop; | ||
339 | u8 reg; | ||
340 | |||
341 | internal->status = NODATA; | ||
342 | |||
343 | /* RESET FEC */ | ||
344 | reg = stb0899_read_reg(state, STB0899_TSTRES); | ||
345 | STB0899_SETFIELD_VAL(FRESACS, reg, 1); | ||
346 | stb0899_write_reg(state, STB0899_TSTRES, reg); | ||
347 | msleep(1); | ||
348 | reg = stb0899_read_reg(state, STB0899_TSTRES); | ||
349 | STB0899_SETFIELD_VAL(FRESACS, reg, 0); | ||
350 | stb0899_write_reg(state, STB0899_TSTRES, reg); | ||
351 | |||
352 | if (params->srate <= 2000000) | ||
353 | dataTime = 2000; | ||
354 | else if (params->srate <= 5000000) | ||
355 | dataTime = 1500; | ||
356 | else if (params->srate <= 15000000) | ||
357 | dataTime = 1000; | ||
358 | else | ||
359 | dataTime = 500; | ||
360 | |||
361 | stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop */ | ||
362 | while (1) { | ||
363 | /* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP */ | ||
364 | reg = stb0899_read_reg(state, STB0899_VSTATUS); | ||
365 | lock = STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg); | ||
366 | loop = STB0899_GETFIELD(VSTATUS_END_LOOPVIT, reg); | ||
367 | |||
368 | if (lock || loop || (index > dataTime)) | ||
369 | break; | ||
370 | index++; | ||
371 | } | ||
372 | |||
373 | if (lock) { /* DATA LOCK indicator */ | ||
374 | internal->status = DATAOK; | ||
375 | dprintk(state->verbose, FE_DEBUG, 1, "-----------------> DATA OK !"); | ||
376 | } | ||
377 | |||
378 | return internal->status; | ||
379 | } | ||
380 | |||
381 | /* | ||
382 | * stb0899_search_data | ||
383 | * Search for a QPSK carrier with the derotator | ||
384 | */ | ||
385 | static enum stb0899_status stb0899_search_data(struct stb0899_state *state) | ||
386 | { | ||
387 | short int derot_freq, derot_step, derot_limit, next_loop = 3; | ||
388 | u8 cfr[2]; | ||
389 | u8 reg; | ||
390 | int index = 1; | ||
391 | |||
392 | struct stb0899_internal *internal = &state->internal; | ||
393 | struct stb0899_params *params = &state->params; | ||
394 | |||
395 | derot_step = (params->srate / 4L) / internal->mclk; | ||
396 | derot_limit = (internal->sub_range / 2L) / internal->mclk; | ||
397 | derot_freq = internal->derot_freq; | ||
398 | |||
399 | do { | ||
400 | if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) { | ||
401 | |||
402 | derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ | ||
403 | if (abs(derot_freq) > derot_limit) | ||
404 | next_loop--; | ||
405 | |||
406 | if (next_loop) { | ||
407 | dprintk(state->verbose, FE_DEBUG, 1, "Derot freq=%d, mclk=%d", derot_freq, internal->mclk); | ||
408 | reg = stb0899_read_reg(state, STB0899_CFD); | ||
409 | STB0899_SETFIELD_VAL(CFD_ON, reg, 1); | ||
410 | stb0899_write_reg(state, STB0899_CFD, reg); | ||
411 | |||
412 | STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq)); | ||
413 | STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); | ||
414 | stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ | ||
415 | |||
416 | stb0899_check_carrier(state); | ||
417 | index++; | ||
418 | } | ||
419 | } | ||
420 | internal->direction = -internal->direction; /* change zig zag direction */ | ||
421 | } while ((internal->status != DATAOK) && next_loop); | ||
422 | |||
423 | if (internal->status == DATAOK) { | ||
424 | stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ | ||
425 | internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]); | ||
426 | dprintk(state->verbose, FE_DEBUG, 1, "------> DATAOK ! Derot Freq=%d", internal->derot_freq); | ||
427 | } | ||
428 | |||
429 | return internal->status; | ||
430 | } | ||
431 | |||
432 | /* | ||
433 | * stb0899_check_range | ||
434 | * check if the found frequency is in the correct range | ||
435 | */ | ||
436 | static enum stb0899_status stb0899_check_range(struct stb0899_state *state) | ||
437 | { | ||
438 | struct stb0899_internal *internal = &state->internal; | ||
439 | struct stb0899_params *params = &state->params; | ||
440 | |||
441 | int range_offst, tp_freq; | ||
442 | |||
443 | range_offst = internal->srch_range / 2000; | ||
444 | tp_freq = internal->freq + (internal->derot_freq * internal->mclk) / 1000; | ||
445 | |||
446 | if ((tp_freq >= params->freq - range_offst) && (tp_freq <= params->freq + range_offst)) { | ||
447 | internal->status = RANGEOK; | ||
448 | dprintk(state->verbose, FE_DEBUG, 1, "----> RANGEOK !"); | ||
449 | } else { | ||
450 | internal->status = OUTOFRANGE; | ||
451 | dprintk(state->verbose, FE_DEBUG, 1, "----> OUT OF RANGE !"); | ||
452 | } | ||
453 | |||
454 | return internal->status; | ||
455 | } | ||
456 | |||
457 | /* | ||
458 | * NextSubRange | ||
459 | * Compute the next subrange of the search | ||
460 | */ | ||
461 | static void next_sub_range(struct stb0899_state *state) | ||
462 | { | ||
463 | struct stb0899_internal *internal = &state->internal; | ||
464 | struct stb0899_params *params = &state->params; | ||
465 | |||
466 | long old_sub_range; | ||
467 | |||
468 | if (internal->sub_dir > 0) { | ||
469 | old_sub_range = internal->sub_range; | ||
470 | internal->sub_range = min((internal->srch_range / 2) - | ||
471 | (internal->tuner_offst + internal->sub_range / 2), | ||
472 | internal->sub_range); | ||
473 | |||
474 | if (internal->sub_range < 0) | ||
475 | internal->sub_range = 0; | ||
476 | |||
477 | internal->tuner_offst += (old_sub_range + internal->sub_range) / 2; | ||
478 | } | ||
479 | |||
480 | internal->freq = params->freq + (internal->sub_dir * internal->tuner_offst) / 1000; | ||
481 | internal->sub_dir = -internal->sub_dir; | ||
482 | } | ||
483 | |||
484 | /* | ||
485 | * stb0899_dvbs_algo | ||
486 | * Search for a signal, timing, carrier and data for a | ||
487 | * given frequency in a given range | ||
488 | */ | ||
489 | enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state) | ||
490 | { | ||
491 | struct stb0899_params *params = &state->params; | ||
492 | struct stb0899_internal *internal = &state->internal; | ||
493 | struct stb0899_config *config = state->config; | ||
494 | |||
495 | u8 bclc, reg; | ||
496 | u8 cfr[2]; | ||
497 | u8 eq_const[10]; | ||
498 | s32 clnI = 3; | ||
499 | u32 bandwidth = 0; | ||
500 | |||
501 | /* BETA values rated @ 99MHz */ | ||
502 | s32 betaTab[5][4] = { | ||
503 | /* 5 10 20 30MBps */ | ||
504 | { 37, 34, 32, 31 }, /* QPSK 1/2 */ | ||
505 | { 37, 35, 33, 31 }, /* QPSK 2/3 */ | ||
506 | { 37, 35, 33, 31 }, /* QPSK 3/4 */ | ||
507 | { 37, 36, 33, 32 }, /* QPSK 5/6 */ | ||
508 | { 37, 36, 33, 32 } /* QPSK 7/8 */ | ||
509 | }; | ||
510 | |||
511 | internal->direction = 1; | ||
512 | |||
513 | stb0899_set_srate(state, internal->master_clk, params->srate); | ||
514 | /* Carrier loop optimization versus symbol rate for acquisition*/ | ||
515 | if (params->srate <= 5000000) { | ||
516 | stb0899_write_reg(state, STB0899_ACLC, 0x89); | ||
517 | bclc = stb0899_read_reg(state, STB0899_BCLC); | ||
518 | STB0899_SETFIELD_VAL(BETA, bclc, 0x1c); | ||
519 | stb0899_write_reg(state, STB0899_BCLC, bclc); | ||
520 | clnI = 0; | ||
521 | } else if (params->srate <= 15000000) { | ||
522 | stb0899_write_reg(state, STB0899_ACLC, 0xc9); | ||
523 | bclc = stb0899_read_reg(state, STB0899_BCLC); | ||
524 | STB0899_SETFIELD_VAL(BETA, bclc, 0x22); | ||
525 | stb0899_write_reg(state, STB0899_BCLC, bclc); | ||
526 | clnI = 1; | ||
527 | } else if(params->srate <= 25000000) { | ||
528 | stb0899_write_reg(state, STB0899_ACLC, 0x89); | ||
529 | bclc = stb0899_read_reg(state, STB0899_BCLC); | ||
530 | STB0899_SETFIELD_VAL(BETA, bclc, 0x27); | ||
531 | stb0899_write_reg(state, STB0899_BCLC, bclc); | ||
532 | clnI = 2; | ||
533 | } else { | ||
534 | stb0899_write_reg(state, STB0899_ACLC, 0xc8); | ||
535 | bclc = stb0899_read_reg(state, STB0899_BCLC); | ||
536 | STB0899_SETFIELD_VAL(BETA, bclc, 0x29); | ||
537 | stb0899_write_reg(state, STB0899_BCLC, bclc); | ||
538 | clnI = 3; | ||
539 | } | ||
540 | |||
541 | dprintk(state->verbose, FE_DEBUG, 1, "Set the timing loop to acquisition"); | ||
542 | /* Set the timing loop to acquisition */ | ||
543 | stb0899_write_reg(state, STB0899_RTC, 0x46); | ||
544 | stb0899_write_reg(state, STB0899_CFD, 0xee); | ||
545 | |||
546 | /* !! WARNING !! | ||
547 | * Do not read any status variables while acquisition, | ||
548 | * If any needed, read before the acquisition starts | ||
549 | * querying status while acquiring causes the | ||
550 | * acquisition to go bad and hence no locks. | ||
551 | */ | ||
552 | dprintk(state->verbose, FE_DEBUG, 1, "Derot Percent=%d Srate=%d mclk=%d", | ||
553 | internal->derot_percent, params->srate, internal->mclk); | ||
554 | |||
555 | /* Initial calculations */ | ||
556 | internal->derot_step = internal->derot_percent * (params->srate / 1000L) / internal->mclk; /* DerotStep/1000 * Fsymbol */ | ||
557 | internal->t_derot = stb0899_calc_derot_time(params->srate); | ||
558 | internal->t_data = 500; | ||
559 | |||
560 | dprintk(state->verbose, FE_DEBUG, 1, "RESET stream merger"); | ||
561 | /* RESET Stream merger */ | ||
562 | reg = stb0899_read_reg(state, STB0899_TSTRES); | ||
563 | STB0899_SETFIELD_VAL(FRESRS, reg, 1); | ||
564 | stb0899_write_reg(state, STB0899_TSTRES, reg); | ||
565 | |||
566 | /* | ||
567 | * Set KDIVIDER to an intermediate value between | ||
568 | * 1/2 and 7/8 for acquisition | ||
569 | */ | ||
570 | reg = stb0899_read_reg(state, STB0899_DEMAPVIT); | ||
571 | STB0899_SETFIELD_VAL(DEMAPVIT_KDIVIDER, reg, 60); | ||
572 | stb0899_write_reg(state, STB0899_DEMAPVIT, reg); | ||
573 | |||
574 | stb0899_write_reg(state, STB0899_EQON, 0x01); /* Equalizer OFF while acquiring */ | ||
575 | stb0899_write_reg(state, STB0899_VITSYNC, 0x19); | ||
576 | |||
577 | stb0899_first_subrange(state); | ||
578 | do { | ||
579 | /* Initialisations */ | ||
580 | cfr[0] = cfr[1] = 0; | ||
581 | stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* RESET derotator frequency */ | ||
582 | |||
583 | stb0899_write_reg(state, STB0899_RTF, 0); | ||
584 | reg = stb0899_read_reg(state, STB0899_CFD); | ||
585 | STB0899_SETFIELD_VAL(CFD_ON, reg, 1); | ||
586 | stb0899_write_reg(state, STB0899_CFD, reg); | ||
587 | |||
588 | internal->derot_freq = 0; | ||
589 | internal->status = NOAGC1; | ||
590 | |||
591 | /* enable tuner I/O */ | ||
592 | stb0899_i2c_gate_ctrl(&state->frontend, 1); | ||
593 | |||
594 | /* Move tuner to frequency */ | ||
595 | dprintk(state->verbose, FE_DEBUG, 1, "Tuner set frequency"); | ||
596 | if (state->config->tuner_set_frequency) | ||
597 | state->config->tuner_set_frequency(&state->frontend, internal->freq); | ||
598 | |||
599 | if (state->config->tuner_get_frequency) | ||
600 | state->config->tuner_get_frequency(&state->frontend, &internal->freq); | ||
601 | |||
602 | msleep(internal->t_agc1 + internal->t_agc2 + internal->t_derot); /* AGC1, AGC2 and timing loop */ | ||
603 | dprintk(state->verbose, FE_DEBUG, 1, "current derot freq=%d", internal->derot_freq); | ||
604 | internal->status = AGC1OK; | ||
605 | |||
606 | /* There is signal in the band */ | ||
607 | if (config->tuner_get_bandwidth) | ||
608 | config->tuner_get_bandwidth(&state->frontend, &bandwidth); | ||
609 | |||
610 | /* disable tuner I/O */ | ||
611 | stb0899_i2c_gate_ctrl(&state->frontend, 0); | ||
612 | |||
613 | if (params->srate <= bandwidth / 2) | ||
614 | stb0899_search_tmg(state); /* For low rates (SCPC) */ | ||
615 | else | ||
616 | stb0899_check_tmg(state); /* For high rates (MCPC) */ | ||
617 | |||
618 | if (internal->status == TIMINGOK) { | ||
619 | dprintk(state->verbose, FE_DEBUG, 1, | ||
620 | "TIMING OK ! Derot freq=%d, mclk=%d", | ||
621 | internal->derot_freq, internal->mclk); | ||
622 | |||
623 | if (stb0899_search_carrier(state) == CARRIEROK) { /* Search for carrier */ | ||
624 | dprintk(state->verbose, FE_DEBUG, 1, | ||
625 | "CARRIER OK ! Derot freq=%d, mclk=%d", | ||
626 | internal->derot_freq, internal->mclk); | ||
627 | |||
628 | if (stb0899_search_data(state) == DATAOK) { /* Check for data */ | ||
629 | dprintk(state->verbose, FE_DEBUG, 1, | ||
630 | "DATA OK ! Derot freq=%d, mclk=%d", | ||
631 | internal->derot_freq, internal->mclk); | ||
632 | |||
633 | if (stb0899_check_range(state) == RANGEOK) { | ||
634 | dprintk(state->verbose, FE_DEBUG, 1, | ||
635 | "RANGE OK ! derot freq=%d, mclk=%d", | ||
636 | internal->derot_freq, internal->mclk); | ||
637 | |||
638 | internal->freq = params->freq + ((internal->derot_freq * internal->mclk) / 1000); | ||
639 | reg = stb0899_read_reg(state, STB0899_PLPARM); | ||
640 | internal->fecrate = STB0899_GETFIELD(VITCURPUN, reg); | ||
641 | dprintk(state->verbose, FE_DEBUG, 1, | ||
642 | "freq=%d, internal resultant freq=%d", | ||
643 | params->freq, internal->freq); | ||
644 | |||
645 | dprintk(state->verbose, FE_DEBUG, 1, | ||
646 | "internal puncture rate=%d", | ||
647 | internal->fecrate); | ||
648 | } | ||
649 | } | ||
650 | } | ||
651 | } | ||
652 | if (internal->status != RANGEOK) | ||
653 | next_sub_range(state); | ||
654 | |||
655 | } while (internal->sub_range && internal->status != RANGEOK); | ||
656 | |||
657 | /* Set the timing loop to tracking */ | ||
658 | stb0899_write_reg(state, STB0899_RTC, 0x33); | ||
659 | stb0899_write_reg(state, STB0899_CFD, 0xf7); | ||
660 | /* if locked and range ok, set Kdiv */ | ||
661 | if (internal->status == RANGEOK) { | ||
662 | dprintk(state->verbose, FE_DEBUG, 1, "Locked & Range OK !"); | ||
663 | stb0899_write_reg(state, STB0899_EQON, 0x41); /* Equalizer OFF while acquiring */ | ||
664 | stb0899_write_reg(state, STB0899_VITSYNC, 0x39); /* SN to b'11 for acquisition */ | ||
665 | |||
666 | /* | ||
667 | * Carrier loop optimization versus | ||
668 | * symbol Rate/Puncture Rate for Tracking | ||
669 | */ | ||
670 | reg = stb0899_read_reg(state, STB0899_BCLC); | ||
671 | switch (internal->fecrate) { | ||
672 | case STB0899_FEC_1_2: /* 13 */ | ||
673 | stb0899_write_reg(state, STB0899_DEMAPVIT, 0x1a); | ||
674 | STB0899_SETFIELD_VAL(BETA, reg, betaTab[0][clnI]); | ||
675 | stb0899_write_reg(state, STB0899_BCLC, reg); | ||
676 | break; | ||
677 | case STB0899_FEC_2_3: /* 18 */ | ||
678 | stb0899_write_reg(state, STB0899_DEMAPVIT, 44); | ||
679 | STB0899_SETFIELD_VAL(BETA, reg, betaTab[1][clnI]); | ||
680 | stb0899_write_reg(state, STB0899_BCLC, reg); | ||
681 | break; | ||
682 | case STB0899_FEC_3_4: /* 21 */ | ||
683 | stb0899_write_reg(state, STB0899_DEMAPVIT, 60); | ||
684 | STB0899_SETFIELD_VAL(BETA, reg, betaTab[2][clnI]); | ||
685 | stb0899_write_reg(state, STB0899_BCLC, reg); | ||
686 | break; | ||
687 | case STB0899_FEC_5_6: /* 24 */ | ||
688 | stb0899_write_reg(state, STB0899_DEMAPVIT, 75); | ||
689 | STB0899_SETFIELD_VAL(BETA, reg, betaTab[3][clnI]); | ||
690 | stb0899_write_reg(state, STB0899_BCLC, reg); | ||
691 | break; | ||
692 | case STB0899_FEC_6_7: /* 25 */ | ||
693 | stb0899_write_reg(state, STB0899_DEMAPVIT, 88); | ||
694 | stb0899_write_reg(state, STB0899_ACLC, 0x88); | ||
695 | stb0899_write_reg(state, STB0899_BCLC, 0x9a); | ||
696 | break; | ||
697 | case STB0899_FEC_7_8: /* 26 */ | ||
698 | stb0899_write_reg(state, STB0899_DEMAPVIT, 94); | ||
699 | STB0899_SETFIELD_VAL(BETA, reg, betaTab[4][clnI]); | ||
700 | stb0899_write_reg(state, STB0899_BCLC, reg); | ||
701 | break; | ||
702 | default: | ||
703 | dprintk(state->verbose, FE_DEBUG, 1, "Unsupported Puncture Rate"); | ||
704 | break; | ||
705 | } | ||
706 | /* release stream merger RESET */ | ||
707 | reg = stb0899_read_reg(state, STB0899_TSTRES); | ||
708 | STB0899_SETFIELD_VAL(FRESRS, reg, 0); | ||
709 | stb0899_write_reg(state, STB0899_TSTRES, reg); | ||
710 | |||
711 | /* disable carrier detector */ | ||
712 | reg = stb0899_read_reg(state, STB0899_CFD); | ||
713 | STB0899_SETFIELD_VAL(CFD_ON, reg, 0); | ||
714 | stb0899_write_reg(state, STB0899_CFD, reg); | ||
715 | |||
716 | stb0899_read_regs(state, STB0899_EQUAI1, eq_const, 10); | ||
717 | } | ||
718 | |||
719 | return internal->status; | ||
720 | } | ||
721 | |||
722 | /* | ||
723 | * stb0899_dvbs2_config_uwp | ||
724 | * Configure UWP state machine | ||
725 | */ | ||
726 | static void stb0899_dvbs2_config_uwp(struct stb0899_state *state) | ||
727 | { | ||
728 | struct stb0899_internal *internal = &state->internal; | ||
729 | struct stb0899_config *config = state->config; | ||
730 | u32 uwp1, uwp2, uwp3, reg; | ||
731 | |||
732 | uwp1 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL1); | ||
733 | uwp2 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL2); | ||
734 | uwp3 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL3); | ||
735 | |||
736 | STB0899_SETFIELD_VAL(UWP_ESN0_AVE, uwp1, config->esno_ave); | ||
737 | STB0899_SETFIELD_VAL(UWP_ESN0_QUANT, uwp1, config->esno_quant); | ||
738 | STB0899_SETFIELD_VAL(UWP_TH_SOF, uwp1, config->uwp_threshold_sof); | ||
739 | |||
740 | STB0899_SETFIELD_VAL(FE_COARSE_TRK, uwp2, internal->av_frame_coarse); | ||
741 | STB0899_SETFIELD_VAL(FE_FINE_TRK, uwp2, internal->av_frame_fine); | ||
742 | STB0899_SETFIELD_VAL(UWP_MISS_TH, uwp2, config->miss_threshold); | ||
743 | |||
744 | STB0899_SETFIELD_VAL(UWP_TH_ACQ, uwp3, config->uwp_threshold_acq); | ||
745 | STB0899_SETFIELD_VAL(UWP_TH_TRACK, uwp3, config->uwp_threshold_track); | ||
746 | |||
747 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL1, STB0899_OFF0_UWP_CNTRL1, uwp1); | ||
748 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL2, STB0899_OFF0_UWP_CNTRL2, uwp2); | ||
749 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL3, STB0899_OFF0_UWP_CNTRL3, uwp3); | ||
750 | |||
751 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, SOF_SRCH_TO); | ||
752 | STB0899_SETFIELD_VAL(SOF_SEARCH_TIMEOUT, reg, config->sof_search_timeout); | ||
753 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_SOF_SRCH_TO, STB0899_OFF0_SOF_SRCH_TO, reg); | ||
754 | } | ||
755 | |||
756 | /* | ||
757 | * stb0899_dvbs2_config_csm_auto | ||
758 | * Set CSM to AUTO mode | ||
759 | */ | ||
760 | static void stb0899_dvbs2_config_csm_auto(struct stb0899_state *state) | ||
761 | { | ||
762 | u32 reg; | ||
763 | |||
764 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1); | ||
765 | STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, reg, 1); | ||
766 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, reg); | ||
767 | } | ||
768 | |||
769 | static long Log2Int(int number) | ||
770 | { | ||
771 | int i; | ||
772 | |||
773 | i = 0; | ||
774 | while ((1 << i) <= abs(number)) | ||
775 | i++; | ||
776 | |||
777 | if (number == 0) | ||
778 | i = 1; | ||
779 | |||
780 | return i - 1; | ||
781 | } | ||
782 | |||
783 | /* | ||
784 | * stb0899_dvbs2_calc_srate | ||
785 | * compute BTR_NOM_FREQ for the symbol rate | ||
786 | */ | ||
787 | static u32 stb0899_dvbs2_calc_srate(struct stb0899_state *state) | ||
788 | { | ||
789 | struct stb0899_internal *internal = &state->internal; | ||
790 | struct stb0899_config *config = state->config; | ||
791 | |||
792 | u32 dec_ratio, dec_rate, decim, remain, intval, btr_nom_freq; | ||
793 | u32 master_clk, srate; | ||
794 | |||
795 | dec_ratio = (internal->master_clk * 2) / (5 * internal->srate); | ||
796 | dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio; | ||
797 | dec_rate = Log2Int(dec_ratio); | ||
798 | decim = 1 << dec_rate; | ||
799 | master_clk = internal->master_clk / 1000; | ||
800 | srate = internal->srate / 1000; | ||
801 | |||
802 | if (decim <= 4) { | ||
803 | intval = (decim * (1 << (config->btr_nco_bits - 1))) / master_clk; | ||
804 | remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk; | ||
805 | } else { | ||
806 | intval = (1 << (config->btr_nco_bits - 1)) / (master_clk / 100) * decim / 100; | ||
807 | remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk; | ||
808 | } | ||
809 | btr_nom_freq = (intval * srate) + ((remain * srate) / master_clk); | ||
810 | |||
811 | return btr_nom_freq; | ||
812 | } | ||
813 | |||
814 | /* | ||
815 | * stb0899_dvbs2_calc_dev | ||
816 | * compute the correction to be applied to symbol rate | ||
817 | */ | ||
818 | static u32 stb0899_dvbs2_calc_dev(struct stb0899_state *state) | ||
819 | { | ||
820 | struct stb0899_internal *internal = &state->internal; | ||
821 | u32 dec_ratio, correction, master_clk, srate; | ||
822 | |||
823 | dec_ratio = (internal->master_clk * 2) / (5 * internal->srate); | ||
824 | dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio; | ||
825 | |||
826 | master_clk = internal->master_clk / 1000; /* for integer Caculation*/ | ||
827 | srate = internal->srate / 1000; /* for integer Caculation*/ | ||
828 | correction = (512 * master_clk) / (2 * dec_ratio * srate); | ||
829 | |||
830 | return correction; | ||
831 | } | ||
832 | |||
833 | /* | ||
834 | * stb0899_dvbs2_set_srate | ||
835 | * Set DVBS2 symbol rate | ||
836 | */ | ||
837 | static void stb0899_dvbs2_set_srate(struct stb0899_state *state) | ||
838 | { | ||
839 | struct stb0899_internal *internal = &state->internal; | ||
840 | |||
841 | u32 dec_ratio, dec_rate, win_sel, decim, f_sym, btr_nom_freq; | ||
842 | u32 correction, freq_adj, band_lim, decim_cntrl, reg; | ||
843 | u8 anti_alias; | ||
844 | |||
845 | /*set decimation to 1*/ | ||
846 | dec_ratio = (internal->master_clk * 2) / (5 * internal->srate); | ||
847 | dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio; | ||
848 | dec_rate = Log2Int(dec_ratio); | ||
849 | |||
850 | win_sel = 0; | ||
851 | if (dec_rate >= 5) | ||
852 | win_sel = dec_rate - 4; | ||
853 | |||
854 | decim = (1 << dec_rate); | ||
855 | /* (FSamp/Fsymbol *100) for integer Caculation */ | ||
856 | f_sym = internal->master_clk / ((decim * internal->srate) / 1000); | ||
857 | |||
858 | if (f_sym <= 2250) /* don't band limit signal going into btr block*/ | ||
859 | band_lim = 1; | ||
860 | else | ||
861 | band_lim = 0; /* band limit signal going into btr block*/ | ||
862 | |||
863 | decim_cntrl = ((win_sel << 3) & 0x18) + ((band_lim << 5) & 0x20) + (dec_rate & 0x7); | ||
864 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DECIM_CNTRL, STB0899_OFF0_DECIM_CNTRL, decim_cntrl); | ||
865 | |||
866 | if (f_sym <= 3450) | ||
867 | anti_alias = 0; | ||
868 | else if (f_sym <= 4250) | ||
869 | anti_alias = 1; | ||
870 | else | ||
871 | anti_alias = 2; | ||
872 | |||
873 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ANTI_ALIAS_SEL, STB0899_OFF0_ANTI_ALIAS_SEL, anti_alias); | ||
874 | btr_nom_freq = stb0899_dvbs2_calc_srate(state); | ||
875 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_NOM_FREQ, STB0899_OFF0_BTR_NOM_FREQ, btr_nom_freq); | ||
876 | |||
877 | correction = stb0899_dvbs2_calc_dev(state); | ||
878 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL); | ||
879 | STB0899_SETFIELD_VAL(BTR_FREQ_CORR, reg, correction); | ||
880 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg); | ||
881 | |||
882 | /* scale UWP+CSM frequency to sample rate*/ | ||
883 | freq_adj = internal->srate / (internal->master_clk / 4096); | ||
884 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_FREQ_ADJ_SCALE, STB0899_OFF0_FREQ_ADJ_SCALE, freq_adj); | ||
885 | } | ||
886 | |||
887 | /* | ||
888 | * stb0899_dvbs2_set_btr_loopbw | ||
889 | * set bit timing loop bandwidth as a percentage of the symbol rate | ||
890 | */ | ||
891 | static void stb0899_dvbs2_set_btr_loopbw(struct stb0899_state *state) | ||
892 | { | ||
893 | struct stb0899_internal *internal = &state->internal; | ||
894 | struct stb0899_config *config = state->config; | ||
895 | |||
896 | u32 sym_peak = 23, zeta = 707, loopbw_percent = 60; | ||
897 | s32 dec_ratio, dec_rate, k_btr1_rshft, k_btr1, k_btr0_rshft; | ||
898 | s32 k_btr0, k_btr2_rshft, k_direct_shift, k_indirect_shift; | ||
899 | u32 decim, K, wn, k_direct, k_indirect; | ||
900 | u32 reg; | ||
901 | |||
902 | dec_ratio = (internal->master_clk * 2) / (5 * internal->srate); | ||
903 | dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio; | ||
904 | dec_rate = Log2Int(dec_ratio); | ||
905 | decim = (1 << dec_rate); | ||
906 | |||
907 | sym_peak *= 576000; | ||
908 | K = (1 << config->btr_nco_bits) / (internal->master_clk / 1000); | ||
909 | K *= (internal->srate / 1000000) * decim; /*k=k 10^-8*/ | ||
910 | |||
911 | if (K != 0) { | ||
912 | K = sym_peak / K; | ||
913 | wn = (4 * zeta * zeta) + 1000000; | ||
914 | wn = (2 * (loopbw_percent * 1000) * 40 * zeta) /wn; /*wn =wn 10^-8*/ | ||
915 | |||
916 | k_indirect = (wn * wn) / K; | ||
917 | k_indirect = k_indirect; /*kindirect = kindirect 10^-6*/ | ||
918 | k_direct = (2 * wn * zeta) / K; /*kDirect = kDirect 10^-2*/ | ||
919 | k_direct *= 100; | ||
920 | |||
921 | k_direct_shift = Log2Int(k_direct) - Log2Int(10000) - 2; | ||
922 | k_btr1_rshft = (-1 * k_direct_shift) + config->btr_gain_shift_offset; | ||
923 | k_btr1 = k_direct / (1 << k_direct_shift); | ||
924 | k_btr1 /= 10000; | ||
925 | |||
926 | k_indirect_shift = Log2Int(k_indirect + 15) - 20 /*- 2*/; | ||
927 | k_btr0_rshft = (-1 * k_indirect_shift) + config->btr_gain_shift_offset; | ||
928 | k_btr0 = k_indirect * (1 << (-k_indirect_shift)); | ||
929 | k_btr0 /= 1000000; | ||
930 | |||
931 | k_btr2_rshft = 0; | ||
932 | if (k_btr0_rshft > 15) { | ||
933 | k_btr2_rshft = k_btr0_rshft - 15; | ||
934 | k_btr0_rshft = 15; | ||
935 | } | ||
936 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_LOOP_GAIN); | ||
937 | STB0899_SETFIELD_VAL(KBTR0_RSHFT, reg, k_btr0_rshft); | ||
938 | STB0899_SETFIELD_VAL(KBTR0, reg, k_btr0); | ||
939 | STB0899_SETFIELD_VAL(KBTR1_RSHFT, reg, k_btr1_rshft); | ||
940 | STB0899_SETFIELD_VAL(KBTR1, reg, k_btr1); | ||
941 | STB0899_SETFIELD_VAL(KBTR2_RSHFT, reg, k_btr2_rshft); | ||
942 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, reg); | ||
943 | } else | ||
944 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, 0xc4c4f); | ||
945 | } | ||
946 | |||
947 | /* | ||
948 | * stb0899_dvbs2_set_carr_freq | ||
949 | * set nominal frequency for carrier search | ||
950 | */ | ||
951 | static void stb0899_dvbs2_set_carr_freq(struct stb0899_state *state, s32 carr_freq, u32 master_clk) | ||
952 | { | ||
953 | struct stb0899_config *config = state->config; | ||
954 | s32 crl_nom_freq; | ||
955 | u32 reg; | ||
956 | |||
957 | crl_nom_freq = (1 << config->crl_nco_bits) / master_clk; | ||
958 | crl_nom_freq *= carr_freq; | ||
959 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ); | ||
960 | STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, crl_nom_freq); | ||
961 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg); | ||
962 | } | ||
963 | |||
964 | /* | ||
965 | * stb0899_dvbs2_init_calc | ||
966 | * Initialize DVBS2 UWP, CSM, carrier and timing loops | ||
967 | */ | ||
968 | static void stb0899_dvbs2_init_calc(struct stb0899_state *state) | ||
969 | { | ||
970 | struct stb0899_internal *internal = &state->internal; | ||
971 | s32 steps, step_size; | ||
972 | u32 range, reg; | ||
973 | |||
974 | /* config uwp and csm */ | ||
975 | stb0899_dvbs2_config_uwp(state); | ||
976 | stb0899_dvbs2_config_csm_auto(state); | ||
977 | |||
978 | /* initialize BTR */ | ||
979 | stb0899_dvbs2_set_srate(state); | ||
980 | stb0899_dvbs2_set_btr_loopbw(state); | ||
981 | |||
982 | if (internal->srate / 1000000 >= 15) | ||
983 | step_size = (1 << 17) / 5; | ||
984 | else if (internal->srate / 1000000 >= 10) | ||
985 | step_size = (1 << 17) / 7; | ||
986 | else if (internal->srate / 1000000 >= 5) | ||
987 | step_size = (1 << 17) / 10; | ||
988 | else | ||
989 | step_size = (1 << 17) / 4; | ||
990 | |||
991 | range = internal->srch_range / 1000000; | ||
992 | steps = (10 * range * (1 << 17)) / (step_size * (internal->srate / 1000000)); | ||
993 | steps = (steps + 6) / 10; | ||
994 | steps = (steps == 0) ? 1 : steps; | ||
995 | if (steps % 2 == 0) | ||
996 | stb0899_dvbs2_set_carr_freq(state, internal->center_freq - | ||
997 | (internal->step_size * (internal->srate / 20000000)), | ||
998 | (internal->master_clk) / 1000000); | ||
999 | else | ||
1000 | stb0899_dvbs2_set_carr_freq(state, internal->center_freq, (internal->master_clk) / 1000000); | ||
1001 | |||
1002 | /*Set Carrier Search params (zigzag, num steps and freq step size*/ | ||
1003 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, ACQ_CNTRL2); | ||
1004 | STB0899_SETFIELD_VAL(ZIGZAG, reg, 1); | ||
1005 | STB0899_SETFIELD_VAL(NUM_STEPS, reg, steps); | ||
1006 | STB0899_SETFIELD_VAL(FREQ_STEPSIZE, reg, step_size); | ||
1007 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQ_CNTRL2, STB0899_OFF0_ACQ_CNTRL2, reg); | ||
1008 | } | ||
1009 | |||
1010 | /* | ||
1011 | * stb0899_dvbs2_btr_init | ||
1012 | * initialize the timing loop | ||
1013 | */ | ||
1014 | static void stb0899_dvbs2_btr_init(struct stb0899_state *state) | ||
1015 | { | ||
1016 | u32 reg; | ||
1017 | |||
1018 | /* set enable BTR loopback */ | ||
1019 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL); | ||
1020 | STB0899_SETFIELD_VAL(INTRP_PHS_SENSE, reg, 1); | ||
1021 | STB0899_SETFIELD_VAL(BTR_ERR_ENA, reg, 1); | ||
1022 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg); | ||
1023 | |||
1024 | /* fix btr freq accum at 0 */ | ||
1025 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x10000000); | ||
1026 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x00000000); | ||
1027 | |||
1028 | /* fix btr freq accum at 0 */ | ||
1029 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x10000000); | ||
1030 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x00000000); | ||
1031 | } | ||
1032 | |||
1033 | /* | ||
1034 | * stb0899_dvbs2_reacquire | ||
1035 | * trigger a DVB-S2 acquisition | ||
1036 | */ | ||
1037 | static void stb0899_dvbs2_reacquire(struct stb0899_state *state) | ||
1038 | { | ||
1039 | u32 reg = 0; | ||
1040 | |||
1041 | /* demod soft reset */ | ||
1042 | STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 1); | ||
1043 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg); | ||
1044 | |||
1045 | /*Reset Timing Loop */ | ||
1046 | stb0899_dvbs2_btr_init(state); | ||
1047 | |||
1048 | /* reset Carrier loop */ | ||
1049 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, (1 << 30)); | ||
1050 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, 0); | ||
1051 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_LOOP_GAIN, STB0899_OFF0_CRL_LOOP_GAIN, 0); | ||
1052 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, (1 << 30)); | ||
1053 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, 0); | ||
1054 | |||
1055 | /*release demod soft reset */ | ||
1056 | reg = 0; | ||
1057 | STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 0); | ||
1058 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg); | ||
1059 | |||
1060 | /* start acquisition process */ | ||
1061 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQUIRE_TRIG, STB0899_OFF0_ACQUIRE_TRIG, 1); | ||
1062 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_LOCK_LOST, STB0899_OFF0_LOCK_LOST, 0); | ||
1063 | |||
1064 | /* equalizer Init */ | ||
1065 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 1); | ||
1066 | |||
1067 | /*Start equilizer */ | ||
1068 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 0); | ||
1069 | |||
1070 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL); | ||
1071 | STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0); | ||
1072 | STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 0); | ||
1073 | STB0899_SETFIELD_VAL(EQ_DELAY, reg, 0x05); | ||
1074 | STB0899_SETFIELD_VAL(EQ_ADAPT_MODE, reg, 0x01); | ||
1075 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg); | ||
1076 | |||
1077 | /* RESET Packet delineator */ | ||
1078 | stb0899_write_reg(state, STB0899_PDELCTRL, 0x4a); | ||
1079 | } | ||
1080 | |||
1081 | /* | ||
1082 | * stb0899_dvbs2_get_dmd_status | ||
1083 | * get DVB-S2 Demod LOCK status | ||
1084 | */ | ||
1085 | static enum stb0899_status stb0899_dvbs2_get_dmd_status(struct stb0899_state *state, int timeout) | ||
1086 | { | ||
1087 | int time = -10, lock = 0, uwp, csm; | ||
1088 | u32 reg; | ||
1089 | |||
1090 | do { | ||
1091 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STATUS); | ||
1092 | dprintk(state->verbose, FE_DEBUG, 1, "DMD_STATUS=[0x%02x]", reg); | ||
1093 | if (STB0899_GETFIELD(IF_AGC_LOCK, reg)) | ||
1094 | dprintk(state->verbose, FE_DEBUG, 1, "------------->IF AGC LOCKED !"); | ||
1095 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STAT2); | ||
1096 | dprintk(state->verbose, FE_DEBUG, 1, "----------->DMD STAT2=[0x%02x]", reg); | ||
1097 | uwp = STB0899_GETFIELD(UWP_LOCK, reg); | ||
1098 | csm = STB0899_GETFIELD(CSM_LOCK, reg); | ||
1099 | if (uwp && csm) | ||
1100 | lock = 1; | ||
1101 | |||
1102 | time += 10; | ||
1103 | msleep(10); | ||
1104 | |||
1105 | } while ((!lock) && (time <= timeout)); | ||
1106 | |||
1107 | if (lock) { | ||
1108 | dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 LOCK !"); | ||
1109 | return DVBS2_DEMOD_LOCK; | ||
1110 | } else { | ||
1111 | return DVBS2_DEMOD_NOLOCK; | ||
1112 | } | ||
1113 | } | ||
1114 | |||
1115 | /* | ||
1116 | * stb0899_dvbs2_get_data_lock | ||
1117 | * get FEC status | ||
1118 | */ | ||
1119 | static int stb0899_dvbs2_get_data_lock(struct stb0899_state *state, int timeout) | ||
1120 | { | ||
1121 | int time = 0, lock = 0; | ||
1122 | u8 reg; | ||
1123 | |||
1124 | while ((!lock) && (time < timeout)) { | ||
1125 | reg = stb0899_read_reg(state, STB0899_CFGPDELSTATUS1); | ||
1126 | dprintk(state->verbose, FE_DEBUG, 1, "---------> CFGPDELSTATUS=[0x%02x]", reg); | ||
1127 | lock = STB0899_GETFIELD(CFGPDELSTATUS_LOCK, reg); | ||
1128 | time++; | ||
1129 | } | ||
1130 | |||
1131 | return lock; | ||
1132 | } | ||
1133 | |||
1134 | /* | ||
1135 | * stb0899_dvbs2_get_fec_status | ||
1136 | * get DVB-S2 FEC LOCK status | ||
1137 | */ | ||
1138 | static enum stb0899_status stb0899_dvbs2_get_fec_status(struct stb0899_state *state, int timeout) | ||
1139 | { | ||
1140 | int time = 0, Locked; | ||
1141 | |||
1142 | do { | ||
1143 | Locked = stb0899_dvbs2_get_data_lock(state, 1); | ||
1144 | time++; | ||
1145 | msleep(1); | ||
1146 | |||
1147 | } while ((!Locked) && (time < timeout)); | ||
1148 | |||
1149 | if (Locked) { | ||
1150 | dprintk(state->verbose, FE_DEBUG, 1, "---------->DVB-S2 FEC LOCK !"); | ||
1151 | return DVBS2_FEC_LOCK; | ||
1152 | } else { | ||
1153 | return DVBS2_FEC_NOLOCK; | ||
1154 | } | ||
1155 | } | ||
1156 | |||
1157 | |||
1158 | /* | ||
1159 | * stb0899_dvbs2_init_csm | ||
1160 | * set parameters for manual mode | ||
1161 | */ | ||
1162 | static void stb0899_dvbs2_init_csm(struct stb0899_state *state, int pilots, enum stb0899_modcod modcod) | ||
1163 | { | ||
1164 | struct stb0899_internal *internal = &state->internal; | ||
1165 | |||
1166 | s32 dvt_tbl = 1, two_pass = 0, agc_gain = 6, agc_shift = 0, loop_shift = 0, phs_diff_thr = 0x80; | ||
1167 | s32 gamma_acq, gamma_rho_acq, gamma_trk, gamma_rho_trk, lock_count_thr; | ||
1168 | u32 csm1, csm2, csm3, csm4; | ||
1169 | |||
1170 | if (((internal->master_clk / internal->srate) <= 4) && (modcod <= 11) && (pilots == 1)) { | ||
1171 | switch (modcod) { | ||
1172 | case STB0899_QPSK_12: | ||
1173 | gamma_acq = 25; | ||
1174 | gamma_rho_acq = 2700; | ||
1175 | gamma_trk = 12; | ||
1176 | gamma_rho_trk = 180; | ||
1177 | lock_count_thr = 8; | ||
1178 | break; | ||
1179 | case STB0899_QPSK_35: | ||
1180 | gamma_acq = 38; | ||
1181 | gamma_rho_acq = 7182; | ||
1182 | gamma_trk = 14; | ||
1183 | gamma_rho_trk = 308; | ||
1184 | lock_count_thr = 8; | ||
1185 | break; | ||
1186 | case STB0899_QPSK_23: | ||
1187 | gamma_acq = 42; | ||
1188 | gamma_rho_acq = 9408; | ||
1189 | gamma_trk = 17; | ||
1190 | gamma_rho_trk = 476; | ||
1191 | lock_count_thr = 8; | ||
1192 | break; | ||
1193 | case STB0899_QPSK_34: | ||
1194 | gamma_acq = 53; | ||
1195 | gamma_rho_acq = 16642; | ||
1196 | gamma_trk = 19; | ||
1197 | gamma_rho_trk = 646; | ||
1198 | lock_count_thr = 8; | ||
1199 | break; | ||
1200 | case STB0899_QPSK_45: | ||
1201 | gamma_acq = 53; | ||
1202 | gamma_rho_acq = 17119; | ||
1203 | gamma_trk = 22; | ||
1204 | gamma_rho_trk = 880; | ||
1205 | lock_count_thr = 8; | ||
1206 | break; | ||
1207 | case STB0899_QPSK_56: | ||
1208 | gamma_acq = 55; | ||
1209 | gamma_rho_acq = 19250; | ||
1210 | gamma_trk = 23; | ||
1211 | gamma_rho_trk = 989; | ||
1212 | lock_count_thr = 8; | ||
1213 | break; | ||
1214 | case STB0899_QPSK_89: | ||
1215 | gamma_acq = 60; | ||
1216 | gamma_rho_acq = 24240; | ||
1217 | gamma_trk = 24; | ||
1218 | gamma_rho_trk = 1176; | ||
1219 | lock_count_thr = 8; | ||
1220 | break; | ||
1221 | case STB0899_QPSK_910: | ||
1222 | gamma_acq = 66; | ||
1223 | gamma_rho_acq = 29634; | ||
1224 | gamma_trk = 24; | ||
1225 | gamma_rho_trk = 1176; | ||
1226 | lock_count_thr = 8; | ||
1227 | break; | ||
1228 | default: | ||
1229 | gamma_acq = 66; | ||
1230 | gamma_rho_acq = 29634; | ||
1231 | gamma_trk = 24; | ||
1232 | gamma_rho_trk = 1176; | ||
1233 | lock_count_thr = 8; | ||
1234 | break; | ||
1235 | } | ||
1236 | |||
1237 | csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1); | ||
1238 | STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, csm1, 0); | ||
1239 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1); | ||
1240 | |||
1241 | csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1); | ||
1242 | csm2 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL2); | ||
1243 | csm3 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL3); | ||
1244 | csm4 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL4); | ||
1245 | |||
1246 | STB0899_SETFIELD_VAL(CSM_DVT_TABLE, csm1, dvt_tbl); | ||
1247 | STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, two_pass); | ||
1248 | STB0899_SETFIELD_VAL(CSM_AGC_GAIN, csm1, agc_gain); | ||
1249 | STB0899_SETFIELD_VAL(CSM_AGC_SHIFT, csm1, agc_shift); | ||
1250 | STB0899_SETFIELD_VAL(FE_LOOP_SHIFT, csm1, loop_shift); | ||
1251 | STB0899_SETFIELD_VAL(CSM_GAMMA_ACQ, csm2, gamma_acq); | ||
1252 | STB0899_SETFIELD_VAL(CSM_GAMMA_RHOACQ, csm2, gamma_rho_acq); | ||
1253 | STB0899_SETFIELD_VAL(CSM_GAMMA_TRACK, csm3, gamma_trk); | ||
1254 | STB0899_SETFIELD_VAL(CSM_GAMMA_RHOTRACK, csm3, gamma_rho_trk); | ||
1255 | STB0899_SETFIELD_VAL(CSM_LOCKCOUNT_THRESH, csm4, lock_count_thr); | ||
1256 | STB0899_SETFIELD_VAL(CSM_PHASEDIFF_THRESH, csm4, phs_diff_thr); | ||
1257 | |||
1258 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1); | ||
1259 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL2, STB0899_OFF0_CSM_CNTRL2, csm2); | ||
1260 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL3, STB0899_OFF0_CSM_CNTRL3, csm3); | ||
1261 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL4, STB0899_OFF0_CSM_CNTRL4, csm4); | ||
1262 | } | ||
1263 | } | ||
1264 | |||
1265 | /* | ||
1266 | * stb0899_dvbs2_get_srate | ||
1267 | * get DVB-S2 Symbol Rate | ||
1268 | */ | ||
1269 | static u32 stb0899_dvbs2_get_srate(struct stb0899_state *state) | ||
1270 | { | ||
1271 | struct stb0899_internal *internal = &state->internal; | ||
1272 | struct stb0899_config *config = state->config; | ||
1273 | |||
1274 | u32 bTrNomFreq, srate, decimRate, intval1, intval2, reg; | ||
1275 | int div1, div2, rem1, rem2; | ||
1276 | |||
1277 | div1 = config->btr_nco_bits / 2; | ||
1278 | div2 = config->btr_nco_bits - div1 - 1; | ||
1279 | |||
1280 | bTrNomFreq = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_NOM_FREQ); | ||
1281 | |||
1282 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DECIM_CNTRL); | ||
1283 | decimRate = STB0899_GETFIELD(DECIM_RATE, reg); | ||
1284 | decimRate = (1 << decimRate); | ||
1285 | |||
1286 | intval1 = internal->master_clk / (1 << div1); | ||
1287 | intval2 = bTrNomFreq / (1 << div2); | ||
1288 | |||
1289 | rem1 = internal->master_clk % (1 << div1); | ||
1290 | rem2 = bTrNomFreq % (1 << div2); | ||
1291 | /* only for integer calculation */ | ||
1292 | srate = (intval1 * intval2) + ((intval1 * rem2) / (1 << div2)) + ((intval2 * rem1) / (1 << div1)); | ||
1293 | srate /= decimRate; /*symbrate = (btrnomfreq_register_val*MasterClock)/2^(27+decim_rate_field) */ | ||
1294 | |||
1295 | return srate; | ||
1296 | } | ||
1297 | |||
1298 | /* | ||
1299 | * stb0899_dvbs2_algo | ||
1300 | * Search for signal, timing, carrier and data for a given | ||
1301 | * frequency in a given range | ||
1302 | */ | ||
1303 | enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state) | ||
1304 | { | ||
1305 | struct stb0899_internal *internal = &state->internal; | ||
1306 | enum stb0899_modcod modcod; | ||
1307 | |||
1308 | s32 offsetfreq, searchTime, FecLockTime, pilots, iqSpectrum; | ||
1309 | int i = 0; | ||
1310 | u32 reg, csm1; | ||
1311 | |||
1312 | if (internal->srate <= 2000000) { | ||
1313 | searchTime = 5000; /* 5000 ms max time to lock UWP and CSM, SYMB <= 2Mbs */ | ||
1314 | FecLockTime = 350; /* 350 ms max time to lock FEC, SYMB <= 2Mbs */ | ||
1315 | } else if (internal->srate <= 5000000) { | ||
1316 | searchTime = 2500; /* 2500 ms max time to lock UWP and CSM, 2Mbs < SYMB <= 5Mbs */ | ||
1317 | FecLockTime = 170; /* 170 ms max time to lock FEC, 2Mbs< SYMB <= 5Mbs */ | ||
1318 | } else if (internal->srate <= 10000000) { | ||
1319 | searchTime = 1500; /* 1500 ms max time to lock UWP and CSM, 5Mbs <SYMB <= 10Mbs */ | ||
1320 | FecLockTime = 80; /* 80 ms max time to lock FEC, 5Mbs< SYMB <= 10Mbs */ | ||
1321 | } else if (internal->srate <= 15000000) { | ||
1322 | searchTime = 500; /* 500 ms max time to lock UWP and CSM, 10Mbs <SYMB <= 15Mbs */ | ||
1323 | FecLockTime = 50; /* 50 ms max time to lock FEC, 10Mbs< SYMB <= 15Mbs */ | ||
1324 | } else if (internal->srate <= 20000000) { | ||
1325 | searchTime = 300; /* 300 ms max time to lock UWP and CSM, 15Mbs < SYMB <= 20Mbs */ | ||
1326 | FecLockTime = 30; /* 50 ms max time to lock FEC, 15Mbs< SYMB <= 20Mbs */ | ||
1327 | } else if (internal->srate <= 25000000) { | ||
1328 | searchTime = 250; /* 250 ms max time to lock UWP and CSM, 20 Mbs < SYMB <= 25Mbs */ | ||
1329 | FecLockTime = 25; /* 25 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs */ | ||
1330 | } else { | ||
1331 | searchTime = 150; /* 150 ms max time to lock UWP and CSM, SYMB > 25Mbs */ | ||
1332 | FecLockTime = 20; /* 20 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs */ | ||
1333 | } | ||
1334 | |||
1335 | /* Maintain Stream Merger in reset during acquisition */ | ||
1336 | reg = stb0899_read_reg(state, STB0899_TSTRES); | ||
1337 | STB0899_SETFIELD_VAL(FRESRS, reg, 1); | ||
1338 | stb0899_write_reg(state, STB0899_TSTRES, reg); | ||
1339 | |||
1340 | /* enable tuner I/O */ | ||
1341 | stb0899_i2c_gate_ctrl(&state->frontend, 1); | ||
1342 | |||
1343 | /* Move tuner to frequency */ | ||
1344 | if (state->config->tuner_set_frequency) | ||
1345 | state->config->tuner_set_frequency(&state->frontend, internal->freq); | ||
1346 | if (state->config->tuner_get_frequency) | ||
1347 | state->config->tuner_get_frequency(&state->frontend, &internal->freq); | ||
1348 | |||
1349 | /* disable tuner I/O */ | ||
1350 | stb0899_i2c_gate_ctrl(&state->frontend, 0); | ||
1351 | |||
1352 | /* Set IF AGC to acquisition */ | ||
1353 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL); | ||
1354 | STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg, 4); | ||
1355 | STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 32); | ||
1356 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg); | ||
1357 | |||
1358 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2); | ||
1359 | STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 0); | ||
1360 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg); | ||
1361 | |||
1362 | /* Initialisation */ | ||
1363 | stb0899_dvbs2_init_calc(state); | ||
1364 | |||
1365 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); | ||
1366 | switch (internal->inversion) { | ||
1367 | case IQ_SWAP_OFF: | ||
1368 | STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 0); | ||
1369 | break; | ||
1370 | case IQ_SWAP_ON: | ||
1371 | STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1); | ||
1372 | break; | ||
1373 | case IQ_SWAP_AUTO: /* use last successful search first */ | ||
1374 | STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1); | ||
1375 | break; | ||
1376 | } | ||
1377 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg); | ||
1378 | stb0899_dvbs2_reacquire(state); | ||
1379 | |||
1380 | /* Wait for demod lock (UWP and CSM) */ | ||
1381 | internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime); | ||
1382 | |||
1383 | if (internal->status == DVBS2_DEMOD_LOCK) { | ||
1384 | dprintk(state->verbose, FE_DEBUG, 1, "------------> DVB-S2 DEMOD LOCK !"); | ||
1385 | i = 0; | ||
1386 | /* Demod Locked, check FEC status */ | ||
1387 | internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime); | ||
1388 | |||
1389 | /*If false lock (UWP and CSM Locked but no FEC) try 3 time max*/ | ||
1390 | while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) { | ||
1391 | /* Read the frequency offset*/ | ||
1392 | offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); | ||
1393 | |||
1394 | /* Set the Nominal frequency to the found frequency offset for the next reacquire*/ | ||
1395 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ); | ||
1396 | STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq); | ||
1397 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg); | ||
1398 | stb0899_dvbs2_reacquire(state); | ||
1399 | internal->status = stb0899_dvbs2_get_fec_status(state, searchTime); | ||
1400 | i++; | ||
1401 | } | ||
1402 | } | ||
1403 | |||
1404 | if (internal->status != DVBS2_FEC_LOCK) { | ||
1405 | if (internal->inversion == IQ_SWAP_AUTO) { | ||
1406 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); | ||
1407 | iqSpectrum = STB0899_GETFIELD(SPECTRUM_INVERT, reg); | ||
1408 | /* IQ Spectrum Inversion */ | ||
1409 | STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, !iqSpectrum); | ||
1410 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg); | ||
1411 | /* start acquistion process */ | ||
1412 | stb0899_dvbs2_reacquire(state); | ||
1413 | |||
1414 | /* Wait for demod lock (UWP and CSM) */ | ||
1415 | internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime); | ||
1416 | if (internal->status == DVBS2_DEMOD_LOCK) { | ||
1417 | i = 0; | ||
1418 | /* Demod Locked, check FEC */ | ||
1419 | internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime); | ||
1420 | /*try thrice for false locks, (UWP and CSM Locked but no FEC) */ | ||
1421 | while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) { | ||
1422 | /* Read the frequency offset*/ | ||
1423 | offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); | ||
1424 | |||
1425 | /* Set the Nominal frequency to the found frequency offset for the next reacquire*/ | ||
1426 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ); | ||
1427 | STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq); | ||
1428 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg); | ||
1429 | |||
1430 | stb0899_dvbs2_reacquire(state); | ||
1431 | internal->status = stb0899_dvbs2_get_fec_status(state, searchTime); | ||
1432 | i++; | ||
1433 | } | ||
1434 | } | ||
1435 | /* | ||
1436 | if (pParams->DVBS2State == FE_DVBS2_FEC_LOCKED) | ||
1437 | pParams->IQLocked = !iqSpectrum; | ||
1438 | */ | ||
1439 | } | ||
1440 | } | ||
1441 | if (internal->status == DVBS2_FEC_LOCK) { | ||
1442 | dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 FEC Lock !"); | ||
1443 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2); | ||
1444 | modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2; | ||
1445 | pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01; | ||
1446 | |||
1447 | if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) && | ||
1448 | (INRANGE(STB0899_QPSK_23, modcod, STB0899_QPSK_910)) && | ||
1449 | (pilots == 1)) { | ||
1450 | |||
1451 | stb0899_dvbs2_init_csm(state, pilots, modcod); | ||
1452 | /* Wait for UWP,CSM and data LOCK 20ms max */ | ||
1453 | internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime); | ||
1454 | |||
1455 | i = 0; | ||
1456 | while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) { | ||
1457 | csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1); | ||
1458 | STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 1); | ||
1459 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1); | ||
1460 | csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1); | ||
1461 | STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 0); | ||
1462 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1); | ||
1463 | |||
1464 | internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime); | ||
1465 | i++; | ||
1466 | } | ||
1467 | } | ||
1468 | |||
1469 | if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) && | ||
1470 | (INRANGE(STB0899_QPSK_12, modcod, STB0899_QPSK_35)) && | ||
1471 | (pilots == 1)) { | ||
1472 | |||
1473 | /* Equalizer Disable update */ | ||
1474 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL); | ||
1475 | STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 1); | ||
1476 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg); | ||
1477 | } | ||
1478 | |||
1479 | /* slow down the Equalizer once locked */ | ||
1480 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL); | ||
1481 | STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0x02); | ||
1482 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg); | ||
1483 | |||
1484 | /* Store signal parameters */ | ||
1485 | offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); | ||
1486 | |||
1487 | offsetfreq = offsetfreq / ((1 << 30) / 1000); | ||
1488 | offsetfreq *= (internal->master_clk / 1000000); | ||
1489 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); | ||
1490 | if (STB0899_GETFIELD(SPECTRUM_INVERT, reg)) | ||
1491 | offsetfreq *= -1; | ||
1492 | |||
1493 | internal->freq = internal->freq - offsetfreq; | ||
1494 | internal->srate = stb0899_dvbs2_get_srate(state); | ||
1495 | |||
1496 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2); | ||
1497 | internal->modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2; | ||
1498 | internal->pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01; | ||
1499 | internal->frame_length = (STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 1) & 0x01; | ||
1500 | |||
1501 | /* Set IF AGC to tracking */ | ||
1502 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL); | ||
1503 | STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg, 3); | ||
1504 | |||
1505 | /* if QPSK 1/2,QPSK 3/5 or QPSK 2/3 set IF AGC reference to 16 otherwise 32*/ | ||
1506 | if (INRANGE(STB0899_QPSK_12, internal->modcod, STB0899_QPSK_23)) | ||
1507 | STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 16); | ||
1508 | |||
1509 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg); | ||
1510 | |||
1511 | reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2); | ||
1512 | STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 7); | ||
1513 | stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg); | ||
1514 | } | ||
1515 | |||
1516 | /* Release Stream Merger Reset */ | ||
1517 | reg = stb0899_read_reg(state, STB0899_TSTRES); | ||
1518 | STB0899_SETFIELD_VAL(FRESRS, reg, 0); | ||
1519 | stb0899_write_reg(state, STB0899_TSTRES, reg); | ||
1520 | |||
1521 | return internal->status; | ||
1522 | } | ||