Commit | Line | Data |
---|---|---|
99277b38 IL |
1 | /* |
2 | * stv0900_core.c | |
3 | * | |
4 | * Driver for ST STV0900 satellite demodulator IC. | |
5 | * | |
6 | * Copyright (C) ST Microelectronics. | |
7 | * Copyright (C) 2009 NetUP Inc. | |
8 | * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru> | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation; either version 2 of the License, or | |
13 | * (at your option) any later version. | |
14 | * | |
15 | * This program is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | * | |
19 | * GNU General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License | |
22 | * along with this program; if not, write to the Free Software | |
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
24 | */ | |
25 | ||
26 | #include <linux/kernel.h> | |
27 | #include <linux/module.h> | |
28 | #include <linux/string.h> | |
29 | #include <linux/slab.h> | |
30 | #include <linux/i2c.h> | |
31 | ||
32 | #include "stv0900.h" | |
33 | #include "stv0900_reg.h" | |
34 | #include "stv0900_priv.h" | |
35 | #include "stv0900_init.h" | |
36 | ||
8171c205 | 37 | int stvdebug = 1; |
5a771cb1 | 38 | module_param_named(debug, stvdebug, int, 0644); |
99277b38 IL |
39 | |
40 | /* internal params node */ | |
41 | struct stv0900_inode { | |
42 | /* pointer for internal params, one for each pair of demods */ | |
43 | struct stv0900_internal *internal; | |
44 | struct stv0900_inode *next_inode; | |
45 | }; | |
46 | ||
47 | /* first internal params */ | |
48 | static struct stv0900_inode *stv0900_first_inode; | |
49 | ||
50 | /* find chip by i2c adapter and i2c address */ | |
51 | static struct stv0900_inode *find_inode(struct i2c_adapter *i2c_adap, | |
52 | u8 i2c_addr) | |
53 | { | |
54 | struct stv0900_inode *temp_chip = stv0900_first_inode; | |
55 | ||
56 | if (temp_chip != NULL) { | |
57 | /* | |
58 | Search of the last stv0900 chip or | |
59 | find it by i2c adapter and i2c address */ | |
60 | while ((temp_chip != NULL) && | |
61 | ((temp_chip->internal->i2c_adap != i2c_adap) || | |
78175bf2 | 62 | (temp_chip->internal->i2c_addr != i2c_addr))) |
99277b38 IL |
63 | |
64 | temp_chip = temp_chip->next_inode; | |
78175bf2 | 65 | |
99277b38 IL |
66 | } |
67 | ||
68 | return temp_chip; | |
69 | } | |
70 | ||
71 | /* deallocating chip */ | |
72 | static void remove_inode(struct stv0900_internal *internal) | |
73 | { | |
74 | struct stv0900_inode *prev_node = stv0900_first_inode; | |
75 | struct stv0900_inode *del_node = find_inode(internal->i2c_adap, | |
76 | internal->i2c_addr); | |
77 | ||
78 | if (del_node != NULL) { | |
79 | if (del_node == stv0900_first_inode) { | |
80 | stv0900_first_inode = del_node->next_inode; | |
81 | } else { | |
82 | while (prev_node->next_inode != del_node) | |
83 | prev_node = prev_node->next_inode; | |
84 | ||
85 | if (del_node->next_inode == NULL) | |
86 | prev_node->next_inode = NULL; | |
87 | else | |
88 | prev_node->next_inode = | |
89 | prev_node->next_inode->next_inode; | |
90 | } | |
91 | ||
92 | kfree(del_node); | |
93 | } | |
94 | } | |
95 | ||
96 | /* allocating new chip */ | |
97 | static struct stv0900_inode *append_internal(struct stv0900_internal *internal) | |
98 | { | |
99 | struct stv0900_inode *new_node = stv0900_first_inode; | |
100 | ||
101 | if (new_node == NULL) { | |
102 | new_node = kmalloc(sizeof(struct stv0900_inode), GFP_KERNEL); | |
103 | stv0900_first_inode = new_node; | |
104 | } else { | |
105 | while (new_node->next_inode != NULL) | |
106 | new_node = new_node->next_inode; | |
107 | ||
1e0c397d IL |
108 | new_node->next_inode = kmalloc(sizeof(struct stv0900_inode), |
109 | GFP_KERNEL); | |
99277b38 IL |
110 | if (new_node->next_inode != NULL) |
111 | new_node = new_node->next_inode; | |
112 | else | |
113 | new_node = NULL; | |
114 | } | |
115 | ||
116 | if (new_node != NULL) { | |
117 | new_node->internal = internal; | |
118 | new_node->next_inode = NULL; | |
119 | } | |
120 | ||
121 | return new_node; | |
122 | } | |
123 | ||
124 | s32 ge2comp(s32 a, s32 width) | |
125 | { | |
126 | if (width == 32) | |
127 | return a; | |
128 | else | |
129 | return (a >= (1 << (width - 1))) ? (a - (1 << width)) : a; | |
130 | } | |
131 | ||
1e0c397d | 132 | void stv0900_write_reg(struct stv0900_internal *intp, u16 reg_addr, |
99277b38 IL |
133 | u8 reg_data) |
134 | { | |
135 | u8 data[3]; | |
136 | int ret; | |
137 | struct i2c_msg i2cmsg = { | |
1e0c397d | 138 | .addr = intp->i2c_addr, |
99277b38 IL |
139 | .flags = 0, |
140 | .len = 3, | |
141 | .buf = data, | |
142 | }; | |
143 | ||
144 | data[0] = MSB(reg_addr); | |
145 | data[1] = LSB(reg_addr); | |
146 | data[2] = reg_data; | |
147 | ||
1e0c397d | 148 | ret = i2c_transfer(intp->i2c_adap, &i2cmsg, 1); |
99277b38 | 149 | if (ret != 1) |
8171c205 | 150 | dprintk("%s: i2c error %d\n", __func__, ret); |
99277b38 IL |
151 | } |
152 | ||
1e0c397d | 153 | u8 stv0900_read_reg(struct stv0900_internal *intp, u16 reg) |
99277b38 | 154 | { |
99277b38 | 155 | int ret; |
68191ede AO |
156 | u8 b0[] = { MSB(reg), LSB(reg) }; |
157 | u8 buf = 0; | |
158 | struct i2c_msg msg[] = { | |
159 | { | |
1e0c397d | 160 | .addr = intp->i2c_addr, |
68191ede AO |
161 | .flags = 0, |
162 | .buf = b0, | |
163 | .len = 2, | |
164 | }, { | |
1e0c397d | 165 | .addr = intp->i2c_addr, |
68191ede AO |
166 | .flags = I2C_M_RD, |
167 | .buf = &buf, | |
168 | .len = 1, | |
169 | }, | |
99277b38 IL |
170 | }; |
171 | ||
1e0c397d | 172 | ret = i2c_transfer(intp->i2c_adap, msg, 2); |
68191ede | 173 | if (ret != 2) |
8171c205 | 174 | dprintk("%s: i2c error %d, reg[0x%02x]\n", |
68191ede | 175 | __func__, ret, reg); |
99277b38 | 176 | |
68191ede | 177 | return buf; |
99277b38 IL |
178 | } |
179 | ||
180 | void extract_mask_pos(u32 label, u8 *mask, u8 *pos) | |
181 | { | |
182 | u8 position = 0, i = 0; | |
183 | ||
184 | (*mask) = label & 0xff; | |
185 | ||
186 | while ((position == 0) && (i < 8)) { | |
187 | position = ((*mask) >> i) & 0x01; | |
188 | i++; | |
189 | } | |
190 | ||
191 | (*pos) = (i - 1); | |
192 | } | |
193 | ||
1e0c397d | 194 | void stv0900_write_bits(struct stv0900_internal *intp, u32 label, u8 val) |
99277b38 IL |
195 | { |
196 | u8 reg, mask, pos; | |
197 | ||
1e0c397d | 198 | reg = stv0900_read_reg(intp, (label >> 16) & 0xffff); |
99277b38 IL |
199 | extract_mask_pos(label, &mask, &pos); |
200 | ||
201 | val = mask & (val << pos); | |
202 | ||
203 | reg = (reg & (~mask)) | val; | |
1e0c397d | 204 | stv0900_write_reg(intp, (label >> 16) & 0xffff, reg); |
99277b38 IL |
205 | |
206 | } | |
207 | ||
1e0c397d | 208 | u8 stv0900_get_bits(struct stv0900_internal *intp, u32 label) |
99277b38 IL |
209 | { |
210 | u8 val = 0xff; | |
211 | u8 mask, pos; | |
212 | ||
213 | extract_mask_pos(label, &mask, &pos); | |
214 | ||
1e0c397d | 215 | val = stv0900_read_reg(intp, label >> 16); |
99277b38 IL |
216 | val = (val & mask) >> pos; |
217 | ||
218 | return val; | |
219 | } | |
220 | ||
1e0c397d | 221 | enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp) |
99277b38 IL |
222 | { |
223 | s32 i; | |
99277b38 | 224 | |
1e0c397d IL |
225 | if (intp == NULL) |
226 | return STV0900_INVALID_HANDLE; | |
99277b38 | 227 | |
1e0c397d | 228 | intp->chip_id = stv0900_read_reg(intp, R0900_MID); |
99277b38 | 229 | |
1e0c397d IL |
230 | if (intp->errs != STV0900_NO_ERROR) |
231 | return intp->errs; | |
99277b38 | 232 | |
1e0c397d IL |
233 | /*Startup sequence*/ |
234 | stv0900_write_reg(intp, R0900_P1_DMDISTATE, 0x5c); | |
235 | stv0900_write_reg(intp, R0900_P2_DMDISTATE, 0x5c); | |
236 | msleep(3); | |
237 | stv0900_write_reg(intp, R0900_P1_TNRCFG, 0x6c); | |
238 | stv0900_write_reg(intp, R0900_P2_TNRCFG, 0x6f); | |
239 | stv0900_write_reg(intp, R0900_P1_I2CRPT, 0x20); | |
240 | stv0900_write_reg(intp, R0900_P2_I2CRPT, 0x20); | |
241 | stv0900_write_reg(intp, R0900_NCOARSE, 0x13); | |
242 | msleep(3); | |
243 | stv0900_write_reg(intp, R0900_I2CCFG, 0x08); | |
244 | ||
245 | switch (intp->clkmode) { | |
246 | case 0: | |
247 | case 2: | |
248 | stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 | |
249 | | intp->clkmode); | |
250 | break; | |
251 | default: | |
252 | /* preserve SELOSCI bit */ | |
253 | i = 0x02 & stv0900_read_reg(intp, R0900_SYNTCTRL); | |
254 | stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 | i); | |
255 | break; | |
256 | } | |
257 | ||
258 | msleep(3); | |
259 | for (i = 0; i < 181; i++) | |
260 | stv0900_write_reg(intp, STV0900_InitVal[i][0], | |
261 | STV0900_InitVal[i][1]); | |
99277b38 | 262 | |
1e0c397d IL |
263 | if (stv0900_read_reg(intp, R0900_MID) >= 0x20) { |
264 | stv0900_write_reg(intp, R0900_TSGENERAL, 0x0c); | |
265 | for (i = 0; i < 32; i++) | |
266 | stv0900_write_reg(intp, STV0900_Cut20_AddOnVal[i][0], | |
267 | STV0900_Cut20_AddOnVal[i][1]); | |
268 | } | |
269 | ||
270 | stv0900_write_reg(intp, R0900_P1_FSPYCFG, 0x6c); | |
271 | stv0900_write_reg(intp, R0900_P2_FSPYCFG, 0x6c); | |
272 | ||
273 | stv0900_write_reg(intp, R0900_P1_PDELCTRL2, 0x01); | |
274 | stv0900_write_reg(intp, R0900_P2_PDELCTRL2, 0x21); | |
275 | ||
276 | stv0900_write_reg(intp, R0900_P1_PDELCTRL3, 0x20); | |
277 | stv0900_write_reg(intp, R0900_P2_PDELCTRL3, 0x20); | |
278 | ||
279 | stv0900_write_reg(intp, R0900_TSTRES0, 0x80); | |
280 | stv0900_write_reg(intp, R0900_TSTRES0, 0x00); | |
281 | ||
282 | return STV0900_NO_ERROR; | |
99277b38 IL |
283 | } |
284 | ||
1e0c397d | 285 | u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk) |
99277b38 IL |
286 | { |
287 | u32 mclk = 90000000, div = 0, ad_div = 0; | |
288 | ||
1e0c397d IL |
289 | div = stv0900_get_bits(intp, F0900_M_DIV); |
290 | ad_div = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6); | |
99277b38 IL |
291 | |
292 | mclk = (div + 1) * ext_clk / ad_div; | |
293 | ||
8171c205 | 294 | dprintk("%s: Calculated Mclk = %d\n", __func__, mclk); |
99277b38 IL |
295 | |
296 | return mclk; | |
297 | } | |
298 | ||
1e0c397d | 299 | enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk) |
99277b38 | 300 | { |
99277b38 IL |
301 | u32 m_div, clk_sel; |
302 | ||
8171c205 | 303 | dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk, |
1e0c397d | 304 | intp->quartz); |
99277b38 | 305 | |
1e0c397d IL |
306 | if (intp == NULL) |
307 | return STV0900_INVALID_HANDLE; | |
99277b38 | 308 | |
1e0c397d IL |
309 | if (intp->errs) |
310 | return STV0900_I2C_ERROR; | |
311 | ||
312 | clk_sel = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6); | |
313 | m_div = ((clk_sel * mclk) / intp->quartz) - 1; | |
314 | stv0900_write_bits(intp, F0900_M_DIV, m_div); | |
315 | intp->mclk = stv0900_get_mclk_freq(intp, | |
316 | intp->quartz); | |
317 | ||
318 | /*Set the DiseqC frequency to 22KHz */ | |
319 | /* | |
320 | Formula: | |
321 | DiseqC_TX_Freq= MasterClock/(32*F22TX_Reg) | |
322 | DiseqC_RX_Freq= MasterClock/(32*F22RX_Reg) | |
323 | */ | |
324 | m_div = intp->mclk / 704000; | |
325 | stv0900_write_reg(intp, R0900_P1_F22TX, m_div); | |
326 | stv0900_write_reg(intp, R0900_P1_F22RX, m_div); | |
327 | ||
328 | stv0900_write_reg(intp, R0900_P2_F22TX, m_div); | |
329 | stv0900_write_reg(intp, R0900_P2_F22RX, m_div); | |
330 | ||
331 | if ((intp->errs)) | |
332 | return STV0900_I2C_ERROR; | |
333 | ||
334 | return STV0900_NO_ERROR; | |
99277b38 IL |
335 | } |
336 | ||
1e0c397d | 337 | u32 stv0900_get_err_count(struct stv0900_internal *intp, int cntr, |
99277b38 IL |
338 | enum fe_stv0900_demod_num demod) |
339 | { | |
340 | u32 lsb, msb, hsb, err_val; | |
99277b38 IL |
341 | |
342 | switch (cntr) { | |
343 | case 0: | |
344 | default: | |
1e0c397d IL |
345 | hsb = stv0900_get_bits(intp, ERR_CNT12); |
346 | msb = stv0900_get_bits(intp, ERR_CNT11); | |
347 | lsb = stv0900_get_bits(intp, ERR_CNT10); | |
99277b38 IL |
348 | break; |
349 | case 1: | |
1e0c397d IL |
350 | hsb = stv0900_get_bits(intp, ERR_CNT22); |
351 | msb = stv0900_get_bits(intp, ERR_CNT21); | |
352 | lsb = stv0900_get_bits(intp, ERR_CNT20); | |
99277b38 IL |
353 | break; |
354 | } | |
355 | ||
356 | err_val = (hsb << 16) + (msb << 8) + (lsb); | |
357 | ||
358 | return err_val; | |
359 | } | |
360 | ||
361 | static int stv0900_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | |
362 | { | |
363 | struct stv0900_state *state = fe->demodulator_priv; | |
1e0c397d | 364 | struct stv0900_internal *intp = state->internal; |
99277b38 IL |
365 | enum fe_stv0900_demod_num demod = state->demod; |
366 | ||
1e0c397d | 367 | stv0900_write_bits(intp, I2CT_ON, enable); |
99277b38 IL |
368 | |
369 | return 0; | |
370 | } | |
371 | ||
1e0c397d | 372 | static void stv0900_set_ts_parallel_serial(struct stv0900_internal *intp, |
99277b38 IL |
373 | enum fe_stv0900_clock_type path1_ts, |
374 | enum fe_stv0900_clock_type path2_ts) | |
375 | { | |
376 | ||
8171c205 | 377 | dprintk("%s\n", __func__); |
99277b38 | 378 | |
1e0c397d | 379 | if (intp->chip_id >= 0x20) { |
99277b38 IL |
380 | switch (path1_ts) { |
381 | case STV0900_PARALLEL_PUNCT_CLOCK: | |
382 | case STV0900_DVBCI_CLOCK: | |
383 | switch (path2_ts) { | |
384 | case STV0900_SERIAL_PUNCT_CLOCK: | |
385 | case STV0900_SERIAL_CONT_CLOCK: | |
386 | default: | |
1e0c397d | 387 | stv0900_write_reg(intp, R0900_TSGENERAL, |
99277b38 IL |
388 | 0x00); |
389 | break; | |
390 | case STV0900_PARALLEL_PUNCT_CLOCK: | |
391 | case STV0900_DVBCI_CLOCK: | |
1e0c397d | 392 | stv0900_write_reg(intp, R0900_TSGENERAL, |
99277b38 | 393 | 0x06); |
1e0c397d | 394 | stv0900_write_bits(intp, |
99277b38 | 395 | F0900_P1_TSFIFO_MANSPEED, 3); |
1e0c397d | 396 | stv0900_write_bits(intp, |
99277b38 | 397 | F0900_P2_TSFIFO_MANSPEED, 0); |
1e0c397d | 398 | stv0900_write_reg(intp, |
99277b38 | 399 | R0900_P1_TSSPEED, 0x14); |
1e0c397d | 400 | stv0900_write_reg(intp, |
99277b38 IL |
401 | R0900_P2_TSSPEED, 0x28); |
402 | break; | |
403 | } | |
404 | break; | |
405 | case STV0900_SERIAL_PUNCT_CLOCK: | |
406 | case STV0900_SERIAL_CONT_CLOCK: | |
407 | default: | |
408 | switch (path2_ts) { | |
409 | case STV0900_SERIAL_PUNCT_CLOCK: | |
410 | case STV0900_SERIAL_CONT_CLOCK: | |
411 | default: | |
1e0c397d | 412 | stv0900_write_reg(intp, |
99277b38 IL |
413 | R0900_TSGENERAL, 0x0C); |
414 | break; | |
415 | case STV0900_PARALLEL_PUNCT_CLOCK: | |
416 | case STV0900_DVBCI_CLOCK: | |
1e0c397d | 417 | stv0900_write_reg(intp, |
99277b38 | 418 | R0900_TSGENERAL, 0x0A); |
8171c205 | 419 | dprintk("%s: 0x0a\n", __func__); |
99277b38 IL |
420 | break; |
421 | } | |
422 | break; | |
423 | } | |
424 | } else { | |
425 | switch (path1_ts) { | |
426 | case STV0900_PARALLEL_PUNCT_CLOCK: | |
427 | case STV0900_DVBCI_CLOCK: | |
428 | switch (path2_ts) { | |
429 | case STV0900_SERIAL_PUNCT_CLOCK: | |
430 | case STV0900_SERIAL_CONT_CLOCK: | |
431 | default: | |
1e0c397d | 432 | stv0900_write_reg(intp, R0900_TSGENERAL1X, |
99277b38 IL |
433 | 0x10); |
434 | break; | |
435 | case STV0900_PARALLEL_PUNCT_CLOCK: | |
436 | case STV0900_DVBCI_CLOCK: | |
1e0c397d | 437 | stv0900_write_reg(intp, R0900_TSGENERAL1X, |
99277b38 | 438 | 0x16); |
1e0c397d | 439 | stv0900_write_bits(intp, |
99277b38 | 440 | F0900_P1_TSFIFO_MANSPEED, 3); |
1e0c397d | 441 | stv0900_write_bits(intp, |
99277b38 | 442 | F0900_P2_TSFIFO_MANSPEED, 0); |
1e0c397d | 443 | stv0900_write_reg(intp, R0900_P1_TSSPEED, |
99277b38 | 444 | 0x14); |
1e0c397d | 445 | stv0900_write_reg(intp, R0900_P2_TSSPEED, |
99277b38 IL |
446 | 0x28); |
447 | break; | |
448 | } | |
449 | ||
450 | break; | |
451 | case STV0900_SERIAL_PUNCT_CLOCK: | |
452 | case STV0900_SERIAL_CONT_CLOCK: | |
453 | default: | |
454 | switch (path2_ts) { | |
455 | case STV0900_SERIAL_PUNCT_CLOCK: | |
456 | case STV0900_SERIAL_CONT_CLOCK: | |
457 | default: | |
1e0c397d | 458 | stv0900_write_reg(intp, R0900_TSGENERAL1X, |
99277b38 IL |
459 | 0x14); |
460 | break; | |
461 | case STV0900_PARALLEL_PUNCT_CLOCK: | |
462 | case STV0900_DVBCI_CLOCK: | |
1e0c397d | 463 | stv0900_write_reg(intp, R0900_TSGENERAL1X, |
99277b38 | 464 | 0x12); |
8171c205 | 465 | dprintk("%s: 0x12\n", __func__); |
99277b38 IL |
466 | break; |
467 | } | |
468 | ||
469 | break; | |
470 | } | |
471 | } | |
472 | ||
473 | switch (path1_ts) { | |
474 | case STV0900_PARALLEL_PUNCT_CLOCK: | |
1e0c397d IL |
475 | stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x00); |
476 | stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x00); | |
99277b38 IL |
477 | break; |
478 | case STV0900_DVBCI_CLOCK: | |
1e0c397d IL |
479 | stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x00); |
480 | stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x01); | |
99277b38 IL |
481 | break; |
482 | case STV0900_SERIAL_PUNCT_CLOCK: | |
1e0c397d IL |
483 | stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x01); |
484 | stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x00); | |
99277b38 IL |
485 | break; |
486 | case STV0900_SERIAL_CONT_CLOCK: | |
1e0c397d IL |
487 | stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x01); |
488 | stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x01); | |
99277b38 IL |
489 | break; |
490 | default: | |
491 | break; | |
492 | } | |
493 | ||
494 | switch (path2_ts) { | |
495 | case STV0900_PARALLEL_PUNCT_CLOCK: | |
1e0c397d IL |
496 | stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x00); |
497 | stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x00); | |
99277b38 IL |
498 | break; |
499 | case STV0900_DVBCI_CLOCK: | |
1e0c397d IL |
500 | stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x00); |
501 | stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x01); | |
99277b38 IL |
502 | break; |
503 | case STV0900_SERIAL_PUNCT_CLOCK: | |
1e0c397d IL |
504 | stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x01); |
505 | stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x00); | |
99277b38 IL |
506 | break; |
507 | case STV0900_SERIAL_CONT_CLOCK: | |
1e0c397d IL |
508 | stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x01); |
509 | stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x01); | |
99277b38 IL |
510 | break; |
511 | default: | |
512 | break; | |
513 | } | |
514 | ||
1e0c397d IL |
515 | stv0900_write_bits(intp, F0900_P2_RST_HWARE, 1); |
516 | stv0900_write_bits(intp, F0900_P2_RST_HWARE, 0); | |
517 | stv0900_write_bits(intp, F0900_P1_RST_HWARE, 1); | |
518 | stv0900_write_bits(intp, F0900_P1_RST_HWARE, 0); | |
99277b38 IL |
519 | } |
520 | ||
521 | void stv0900_set_tuner(struct dvb_frontend *fe, u32 frequency, | |
522 | u32 bandwidth) | |
523 | { | |
524 | struct dvb_frontend_ops *frontend_ops = NULL; | |
525 | struct dvb_tuner_ops *tuner_ops = NULL; | |
526 | ||
527 | if (&fe->ops) | |
528 | frontend_ops = &fe->ops; | |
529 | ||
530 | if (&frontend_ops->tuner_ops) | |
531 | tuner_ops = &frontend_ops->tuner_ops; | |
532 | ||
533 | if (tuner_ops->set_frequency) { | |
534 | if ((tuner_ops->set_frequency(fe, frequency)) < 0) | |
535 | dprintk("%s: Invalid parameter\n", __func__); | |
536 | else | |
537 | dprintk("%s: Frequency=%d\n", __func__, frequency); | |
538 | ||
539 | } | |
540 | ||
541 | if (tuner_ops->set_bandwidth) { | |
542 | if ((tuner_ops->set_bandwidth(fe, bandwidth)) < 0) | |
543 | dprintk("%s: Invalid parameter\n", __func__); | |
544 | else | |
545 | dprintk("%s: Bandwidth=%d\n", __func__, bandwidth); | |
546 | ||
547 | } | |
548 | } | |
549 | ||
550 | void stv0900_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) | |
551 | { | |
552 | struct dvb_frontend_ops *frontend_ops = NULL; | |
553 | struct dvb_tuner_ops *tuner_ops = NULL; | |
554 | ||
555 | if (&fe->ops) | |
556 | frontend_ops = &fe->ops; | |
557 | ||
558 | if (&frontend_ops->tuner_ops) | |
559 | tuner_ops = &frontend_ops->tuner_ops; | |
560 | ||
561 | if (tuner_ops->set_bandwidth) { | |
562 | if ((tuner_ops->set_bandwidth(fe, bandwidth)) < 0) | |
563 | dprintk("%s: Invalid parameter\n", __func__); | |
564 | else | |
565 | dprintk("%s: Bandwidth=%d\n", __func__, bandwidth); | |
566 | ||
567 | } | |
568 | } | |
569 | ||
1e0c397d | 570 | static s32 stv0900_get_rf_level(struct stv0900_internal *intp, |
99277b38 IL |
571 | const struct stv0900_table *lookup, |
572 | enum fe_stv0900_demod_num demod) | |
573 | { | |
574 | s32 agc_gain = 0, | |
575 | imin, | |
576 | imax, | |
577 | i, | |
578 | rf_lvl = 0; | |
579 | ||
8171c205 | 580 | dprintk("%s\n", __func__); |
99277b38 | 581 | |
1e0c397d IL |
582 | if ((lookup == NULL) || (lookup->size <= 0)) |
583 | return 0; | |
502cd96d | 584 | |
1e0c397d IL |
585 | agc_gain = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1), |
586 | stv0900_get_bits(intp, AGCIQ_VALUE0)); | |
99277b38 | 587 | |
1e0c397d IL |
588 | imin = 0; |
589 | imax = lookup->size - 1; | |
590 | if (INRANGE(lookup->table[imin].regval, agc_gain, | |
591 | lookup->table[imax].regval)) { | |
592 | while ((imax - imin) > 1) { | |
593 | i = (imax + imin) >> 1; | |
99277b38 | 594 | |
1e0c397d IL |
595 | if (INRANGE(lookup->table[imin].regval, |
596 | agc_gain, | |
597 | lookup->table[i].regval)) | |
598 | imax = i; | |
599 | else | |
600 | imin = i; | |
601 | } | |
99277b38 | 602 | |
1e0c397d IL |
603 | rf_lvl = (s32)agc_gain - lookup->table[imin].regval; |
604 | rf_lvl *= (lookup->table[imax].realval - | |
605 | lookup->table[imin].realval); | |
606 | rf_lvl /= (lookup->table[imax].regval - | |
607 | lookup->table[imin].regval); | |
608 | rf_lvl += lookup->table[imin].realval; | |
609 | } else if (agc_gain > lookup->table[0].regval) | |
610 | rf_lvl = 5; | |
611 | else if (agc_gain < lookup->table[lookup->size-1].regval) | |
612 | rf_lvl = -100; | |
99277b38 | 613 | |
8171c205 | 614 | dprintk("%s: RFLevel = %d\n", __func__, rf_lvl); |
99277b38 IL |
615 | |
616 | return rf_lvl; | |
617 | } | |
618 | ||
619 | static int stv0900_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | |
620 | { | |
621 | struct stv0900_state *state = fe->demodulator_priv; | |
622 | struct stv0900_internal *internal = state->internal; | |
623 | s32 rflevel = stv0900_get_rf_level(internal, &stv0900_rf, | |
624 | state->demod); | |
625 | ||
502cd96d IL |
626 | rflevel = (rflevel + 100) * (65535 / 70); |
627 | if (rflevel < 0) | |
628 | rflevel = 0; | |
629 | ||
630 | if (rflevel > 65535) | |
631 | rflevel = 65535; | |
632 | ||
633 | *strength = rflevel; | |
99277b38 IL |
634 | |
635 | return 0; | |
636 | } | |
637 | ||
99277b38 IL |
638 | static s32 stv0900_carr_get_quality(struct dvb_frontend *fe, |
639 | const struct stv0900_table *lookup) | |
640 | { | |
641 | struct stv0900_state *state = fe->demodulator_priv; | |
1e0c397d | 642 | struct stv0900_internal *intp = state->internal; |
99277b38 IL |
643 | enum fe_stv0900_demod_num demod = state->demod; |
644 | ||
1e0c397d IL |
645 | s32 c_n = -100, |
646 | regval, | |
647 | imin, | |
648 | imax, | |
99277b38 | 649 | i, |
99277b38 IL |
650 | noise_field1, |
651 | noise_field0; | |
652 | ||
8171c205 | 653 | dprintk("%s\n", __func__); |
99277b38 | 654 | |
99277b38 | 655 | if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) { |
1e0c397d IL |
656 | noise_field1 = NOSPLHT_NORMED1; |
657 | noise_field0 = NOSPLHT_NORMED0; | |
99277b38 | 658 | } else { |
1e0c397d IL |
659 | noise_field1 = NOSDATAT_NORMED1; |
660 | noise_field0 = NOSDATAT_NORMED0; | |
99277b38 IL |
661 | } |
662 | ||
1e0c397d | 663 | if (stv0900_get_bits(intp, LOCK_DEFINITIF)) { |
99277b38 IL |
664 | if ((lookup != NULL) && lookup->size) { |
665 | regval = 0; | |
666 | msleep(5); | |
667 | for (i = 0; i < 16; i++) { | |
1e0c397d | 668 | regval += MAKEWORD(stv0900_get_bits(intp, |
11a84143 | 669 | noise_field1), |
1e0c397d | 670 | stv0900_get_bits(intp, |
11a84143 | 671 | noise_field0)); |
99277b38 IL |
672 | msleep(1); |
673 | } | |
674 | ||
675 | regval /= 16; | |
676 | imin = 0; | |
677 | imax = lookup->size - 1; | |
11a84143 IL |
678 | if (INRANGE(lookup->table[imin].regval, |
679 | regval, | |
680 | lookup->table[imax].regval)) { | |
99277b38 IL |
681 | while ((imax - imin) > 1) { |
682 | i = (imax + imin) >> 1; | |
11a84143 IL |
683 | if (INRANGE(lookup->table[imin].regval, |
684 | regval, | |
685 | lookup->table[i].regval)) | |
99277b38 IL |
686 | imax = i; |
687 | else | |
688 | imin = i; | |
689 | } | |
690 | ||
691 | c_n = ((regval - lookup->table[imin].regval) | |
11a84143 IL |
692 | * (lookup->table[imax].realval |
693 | - lookup->table[imin].realval) | |
694 | / (lookup->table[imax].regval | |
695 | - lookup->table[imin].regval)) | |
99277b38 IL |
696 | + lookup->table[imin].realval; |
697 | } else if (regval < lookup->table[imin].regval) | |
698 | c_n = 1000; | |
699 | } | |
700 | } | |
701 | ||
702 | return c_n; | |
703 | } | |
704 | ||
ee1ebcfe AO |
705 | static int stv0900_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) |
706 | { | |
707 | struct stv0900_state *state = fe->demodulator_priv; | |
1e0c397d | 708 | struct stv0900_internal *intp = state->internal; |
ee1ebcfe AO |
709 | enum fe_stv0900_demod_num demod = state->demod; |
710 | u8 err_val1, err_val0; | |
ee1ebcfe AO |
711 | u32 header_err_val = 0; |
712 | ||
713 | *ucblocks = 0x0; | |
714 | if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) { | |
715 | /* DVB-S2 delineator errors count */ | |
716 | ||
717 | /* retreiving number for errnous headers */ | |
1e0c397d IL |
718 | err_val1 = stv0900_read_reg(intp, BBFCRCKO1); |
719 | err_val0 = stv0900_read_reg(intp, BBFCRCKO0); | |
720 | header_err_val = (err_val1 << 8) | err_val0; | |
ee1ebcfe AO |
721 | |
722 | /* retreiving number for errnous packets */ | |
1e0c397d IL |
723 | err_val1 = stv0900_read_reg(intp, UPCRCKO1); |
724 | err_val0 = stv0900_read_reg(intp, UPCRCKO0); | |
725 | *ucblocks = (err_val1 << 8) | err_val0; | |
ee1ebcfe AO |
726 | *ucblocks += header_err_val; |
727 | } | |
728 | ||
729 | return 0; | |
730 | } | |
731 | ||
99277b38 IL |
732 | static int stv0900_read_snr(struct dvb_frontend *fe, u16 *snr) |
733 | { | |
502cd96d | 734 | s32 snrlcl = stv0900_carr_get_quality(fe, |
11a84143 | 735 | (const struct stv0900_table *)&stv0900_s2_cn); |
502cd96d IL |
736 | snrlcl = (snrlcl + 30) * 384; |
737 | if (snrlcl < 0) | |
738 | snrlcl = 0; | |
739 | ||
740 | if (snrlcl > 65535) | |
741 | snrlcl = 65535; | |
742 | ||
743 | *snr = snrlcl; | |
99277b38 IL |
744 | |
745 | return 0; | |
746 | } | |
747 | ||
1e0c397d | 748 | static u32 stv0900_get_ber(struct stv0900_internal *intp, |
99277b38 IL |
749 | enum fe_stv0900_demod_num demod) |
750 | { | |
751 | u32 ber = 10000000, i; | |
99277b38 | 752 | s32 demod_state; |
99277b38 | 753 | |
1e0c397d | 754 | demod_state = stv0900_get_bits(intp, HEADER_MODE); |
99277b38 IL |
755 | |
756 | switch (demod_state) { | |
757 | case STV0900_SEARCH: | |
758 | case STV0900_PLH_DETECTED: | |
759 | default: | |
760 | ber = 10000000; | |
761 | break; | |
762 | case STV0900_DVBS_FOUND: | |
763 | ber = 0; | |
764 | for (i = 0; i < 5; i++) { | |
765 | msleep(5); | |
1e0c397d | 766 | ber += stv0900_get_err_count(intp, 0, demod); |
99277b38 IL |
767 | } |
768 | ||
769 | ber /= 5; | |
1e0c397d | 770 | if (stv0900_get_bits(intp, PRFVIT)) { |
99277b38 IL |
771 | ber *= 9766; |
772 | ber = ber >> 13; | |
773 | } | |
774 | ||
775 | break; | |
776 | case STV0900_DVBS2_FOUND: | |
777 | ber = 0; | |
778 | for (i = 0; i < 5; i++) { | |
779 | msleep(5); | |
1e0c397d | 780 | ber += stv0900_get_err_count(intp, 0, demod); |
99277b38 IL |
781 | } |
782 | ||
783 | ber /= 5; | |
1e0c397d | 784 | if (stv0900_get_bits(intp, PKTDELIN_LOCK)) { |
99277b38 IL |
785 | ber *= 9766; |
786 | ber = ber >> 13; | |
787 | } | |
788 | ||
789 | break; | |
790 | } | |
791 | ||
792 | return ber; | |
793 | } | |
794 | ||
795 | static int stv0900_read_ber(struct dvb_frontend *fe, u32 *ber) | |
796 | { | |
797 | struct stv0900_state *state = fe->demodulator_priv; | |
798 | struct stv0900_internal *internal = state->internal; | |
799 | ||
800 | *ber = stv0900_get_ber(internal, state->demod); | |
801 | ||
802 | return 0; | |
803 | } | |
804 | ||
1e0c397d | 805 | int stv0900_get_demod_lock(struct stv0900_internal *intp, |
99277b38 IL |
806 | enum fe_stv0900_demod_num demod, s32 time_out) |
807 | { | |
808 | s32 timer = 0, | |
1e0c397d | 809 | lock = 0; |
99277b38 IL |
810 | |
811 | enum fe_stv0900_search_state dmd_state; | |
812 | ||
99277b38 | 813 | while ((timer < time_out) && (lock == 0)) { |
1e0c397d | 814 | dmd_state = stv0900_get_bits(intp, HEADER_MODE); |
99277b38 IL |
815 | dprintk("Demod State = %d\n", dmd_state); |
816 | switch (dmd_state) { | |
817 | case STV0900_SEARCH: | |
818 | case STV0900_PLH_DETECTED: | |
819 | default: | |
820 | lock = 0; | |
821 | break; | |
822 | case STV0900_DVBS2_FOUND: | |
823 | case STV0900_DVBS_FOUND: | |
1e0c397d | 824 | lock = stv0900_get_bits(intp, LOCK_DEFINITIF); |
99277b38 IL |
825 | break; |
826 | } | |
827 | ||
828 | if (lock == 0) | |
829 | msleep(10); | |
830 | ||
831 | timer += 10; | |
832 | } | |
833 | ||
834 | if (lock) | |
835 | dprintk("DEMOD LOCK OK\n"); | |
836 | else | |
837 | dprintk("DEMOD LOCK FAIL\n"); | |
838 | ||
839 | return lock; | |
840 | } | |
841 | ||
1e0c397d | 842 | void stv0900_stop_all_s2_modcod(struct stv0900_internal *intp, |
99277b38 IL |
843 | enum fe_stv0900_demod_num demod) |
844 | { | |
845 | s32 regflist, | |
846 | i; | |
847 | ||
8171c205 | 848 | dprintk("%s\n", __func__); |
99277b38 | 849 | |
1e0c397d | 850 | regflist = MODCODLST0; |
99277b38 IL |
851 | |
852 | for (i = 0; i < 16; i++) | |
1e0c397d | 853 | stv0900_write_reg(intp, regflist + i, 0xff); |
99277b38 IL |
854 | } |
855 | ||
1e0c397d | 856 | void stv0900_activate_s2_modcod(struct stv0900_internal *intp, |
99277b38 IL |
857 | enum fe_stv0900_demod_num demod) |
858 | { | |
859 | u32 matype, | |
1e0c397d IL |
860 | mod_code, |
861 | fmod, | |
862 | reg_index, | |
863 | field_index; | |
99277b38 | 864 | |
8171c205 | 865 | dprintk("%s\n", __func__); |
99277b38 | 866 | |
1e0c397d | 867 | if (intp->chip_id <= 0x11) { |
99277b38 IL |
868 | msleep(5); |
869 | ||
1e0c397d IL |
870 | mod_code = stv0900_read_reg(intp, PLHMODCOD); |
871 | matype = mod_code & 0x3; | |
872 | mod_code = (mod_code & 0x7f) >> 2; | |
99277b38 | 873 | |
1e0c397d IL |
874 | reg_index = MODCODLSTF - mod_code / 2; |
875 | field_index = mod_code % 2; | |
99277b38 IL |
876 | |
877 | switch (matype) { | |
878 | case 0: | |
879 | default: | |
880 | fmod = 14; | |
881 | break; | |
882 | case 1: | |
883 | fmod = 13; | |
884 | break; | |
885 | case 2: | |
886 | fmod = 11; | |
887 | break; | |
888 | case 3: | |
889 | fmod = 7; | |
890 | break; | |
891 | } | |
892 | ||
893 | if ((INRANGE(STV0900_QPSK_12, mod_code, STV0900_8PSK_910)) | |
1e0c397d | 894 | && (matype <= 1)) { |
99277b38 | 895 | if (field_index == 0) |
1e0c397d | 896 | stv0900_write_reg(intp, reg_index, |
99277b38 IL |
897 | 0xf0 | fmod); |
898 | else | |
1e0c397d | 899 | stv0900_write_reg(intp, reg_index, |
99277b38 IL |
900 | (fmod << 4) | 0xf); |
901 | } | |
99277b38 | 902 | |
1e0c397d IL |
903 | } else if (intp->chip_id >= 0x12) { |
904 | for (reg_index = 0; reg_index < 7; reg_index++) | |
905 | stv0900_write_reg(intp, MODCODLST0 + reg_index, 0xff); | |
99277b38 | 906 | |
1e0c397d IL |
907 | stv0900_write_reg(intp, MODCODLSTE, 0xff); |
908 | stv0900_write_reg(intp, MODCODLSTF, 0xcf); | |
909 | for (reg_index = 0; reg_index < 8; reg_index++) | |
910 | stv0900_write_reg(intp, MODCODLST7 + reg_index, 0xcc); | |
99277b38 | 911 | |
99277b38 IL |
912 | |
913 | } | |
914 | } | |
915 | ||
1e0c397d | 916 | void stv0900_activate_s2_modcod_single(struct stv0900_internal *intp, |
99277b38 IL |
917 | enum fe_stv0900_demod_num demod) |
918 | { | |
919 | u32 reg_index; | |
920 | ||
8171c205 | 921 | dprintk("%s\n", __func__); |
99277b38 | 922 | |
1e0c397d IL |
923 | stv0900_write_reg(intp, MODCODLST0, 0xff); |
924 | stv0900_write_reg(intp, MODCODLST1, 0xf0); | |
925 | stv0900_write_reg(intp, MODCODLSTF, 0x0f); | |
926 | for (reg_index = 0; reg_index < 13; reg_index++) | |
927 | stv0900_write_reg(intp, MODCODLST2 + reg_index, 0); | |
99277b38 | 928 | |
99277b38 IL |
929 | } |
930 | ||
931 | static enum dvbfe_algo stv0900_frontend_algo(struct dvb_frontend *fe) | |
932 | { | |
933 | return DVBFE_ALGO_CUSTOM; | |
934 | } | |
935 | ||
936 | static int stb0900_set_property(struct dvb_frontend *fe, | |
937 | struct dtv_property *tvp) | |
938 | { | |
8171c205 | 939 | dprintk("%s(..)\n", __func__); |
99277b38 IL |
940 | |
941 | return 0; | |
942 | } | |
943 | ||
944 | static int stb0900_get_property(struct dvb_frontend *fe, | |
945 | struct dtv_property *tvp) | |
946 | { | |
8171c205 | 947 | dprintk("%s(..)\n", __func__); |
99277b38 IL |
948 | |
949 | return 0; | |
950 | } | |
951 | ||
1e0c397d | 952 | void stv0900_start_search(struct stv0900_internal *intp, |
99277b38 IL |
953 | enum fe_stv0900_demod_num demod) |
954 | { | |
1e0c397d IL |
955 | u32 freq; |
956 | s16 freq_s16 ; | |
957 | ||
958 | stv0900_write_bits(intp, DEMOD_MODE, 0x1f); | |
959 | if (intp->chip_id == 0x10) | |
960 | stv0900_write_reg(intp, CORRELEXP, 0xaa); | |
961 | ||
962 | if (intp->chip_id < 0x20) | |
963 | stv0900_write_reg(intp, CARHDR, 0x55); | |
964 | ||
965 | if (intp->chip_id <= 0x20) { | |
966 | if (intp->symbol_rate[0] <= 5000000) { | |
967 | stv0900_write_reg(intp, CARCFG, 0x44); | |
968 | stv0900_write_reg(intp, CFRUP1, 0x0f); | |
969 | stv0900_write_reg(intp, CFRUP0, 0xff); | |
970 | stv0900_write_reg(intp, CFRLOW1, 0xf0); | |
971 | stv0900_write_reg(intp, CFRLOW0, 0x00); | |
972 | stv0900_write_reg(intp, RTCS2, 0x68); | |
99277b38 | 973 | } else { |
1e0c397d IL |
974 | stv0900_write_reg(intp, CARCFG, 0xc4); |
975 | stv0900_write_reg(intp, RTCS2, 0x44); | |
99277b38 IL |
976 | } |
977 | ||
1e0c397d IL |
978 | } else { /*cut 3.0 above*/ |
979 | if (intp->symbol_rate[demod] <= 5000000) | |
980 | stv0900_write_reg(intp, RTCS2, 0x68); | |
981 | else | |
982 | stv0900_write_reg(intp, RTCS2, 0x44); | |
99277b38 | 983 | |
1e0c397d IL |
984 | stv0900_write_reg(intp, CARCFG, 0x46); |
985 | if (intp->srch_algo[demod] == STV0900_WARM_START) { | |
986 | freq = 1000 << 16; | |
987 | freq /= (intp->mclk / 1000); | |
988 | freq_s16 = (s16)freq; | |
99277b38 | 989 | } else { |
1e0c397d IL |
990 | freq = (intp->srch_range[demod] / 2000); |
991 | if (intp->symbol_rate[demod] <= 5000000) | |
992 | freq += 80; | |
99277b38 | 993 | else |
1e0c397d | 994 | freq += 600; |
99277b38 | 995 | |
1e0c397d IL |
996 | freq = freq << 16; |
997 | freq /= (intp->mclk / 1000); | |
998 | freq_s16 = (s16)freq; | |
99277b38 IL |
999 | } |
1000 | ||
1e0c397d IL |
1001 | stv0900_write_bits(intp, CFR_UP1, MSB(freq_s16)); |
1002 | stv0900_write_bits(intp, CFR_UP0, LSB(freq_s16)); | |
1003 | freq_s16 *= (-1); | |
1004 | stv0900_write_bits(intp, CFR_LOW1, MSB(freq_s16)); | |
1005 | stv0900_write_bits(intp, CFR_LOW0, LSB(freq_s16)); | |
1006 | } | |
99277b38 | 1007 | |
1e0c397d IL |
1008 | stv0900_write_reg(intp, CFRINIT1, 0); |
1009 | stv0900_write_reg(intp, CFRINIT0, 0); | |
99277b38 | 1010 | |
1e0c397d IL |
1011 | if (intp->chip_id >= 0x20) { |
1012 | stv0900_write_reg(intp, EQUALCFG, 0x41); | |
1013 | stv0900_write_reg(intp, FFECFG, 0x41); | |
99277b38 | 1014 | |
1e0c397d IL |
1015 | if ((intp->srch_standard[demod] == STV0900_SEARCH_DVBS1) || |
1016 | (intp->srch_standard[demod] == STV0900_SEARCH_DSS) || | |
1017 | (intp->srch_standard[demod] == STV0900_AUTO_SEARCH)) { | |
1018 | stv0900_write_reg(intp, VITSCALE, | |
1019 | 0x82); | |
1020 | stv0900_write_reg(intp, VAVSRVIT, 0x0); | |
1021 | } | |
1022 | } | |
99277b38 | 1023 | |
1e0c397d IL |
1024 | stv0900_write_reg(intp, SFRSTEP, 0x00); |
1025 | stv0900_write_reg(intp, TMGTHRISE, 0xe0); | |
1026 | stv0900_write_reg(intp, TMGTHFALL, 0xc0); | |
1027 | stv0900_write_bits(intp, SCAN_ENABLE, 0); | |
1028 | stv0900_write_bits(intp, CFR_AUTOSCAN, 0); | |
1029 | stv0900_write_bits(intp, S1S2_SEQUENTIAL, 0); | |
1030 | stv0900_write_reg(intp, RTC, 0x88); | |
1031 | if (intp->chip_id >= 0x20) { | |
1032 | if (intp->symbol_rate[demod] < 2000000) { | |
1033 | if (intp->chip_id <= 0x20) | |
1034 | stv0900_write_reg(intp, CARFREQ, 0x39); | |
1035 | else /*cut 3.0*/ | |
1036 | stv0900_write_reg(intp, CARFREQ, 0x89); | |
1037 | ||
1038 | stv0900_write_reg(intp, CARHDR, 0x40); | |
1039 | } else if (intp->symbol_rate[demod] < 10000000) { | |
1040 | stv0900_write_reg(intp, CARFREQ, 0x4c); | |
1041 | stv0900_write_reg(intp, CARHDR, 0x20); | |
99277b38 | 1042 | } else { |
1e0c397d IL |
1043 | stv0900_write_reg(intp, CARFREQ, 0x4b); |
1044 | stv0900_write_reg(intp, CARHDR, 0x20); | |
99277b38 IL |
1045 | } |
1046 | ||
1e0c397d IL |
1047 | } else { |
1048 | if (intp->symbol_rate[demod] < 10000000) | |
1049 | stv0900_write_reg(intp, CARFREQ, 0xef); | |
1050 | else | |
1051 | stv0900_write_reg(intp, CARFREQ, 0xed); | |
1052 | } | |
99277b38 | 1053 | |
1e0c397d IL |
1054 | switch (intp->srch_algo[demod]) { |
1055 | case STV0900_WARM_START: | |
1056 | stv0900_write_reg(intp, DMDISTATE, 0x1f); | |
1057 | stv0900_write_reg(intp, DMDISTATE, 0x18); | |
1058 | break; | |
1059 | case STV0900_COLD_START: | |
1060 | stv0900_write_reg(intp, DMDISTATE, 0x1f); | |
1061 | stv0900_write_reg(intp, DMDISTATE, 0x15); | |
1062 | break; | |
1063 | default: | |
99277b38 IL |
1064 | break; |
1065 | } | |
1066 | } | |
1067 | ||
1068 | u8 stv0900_get_optim_carr_loop(s32 srate, enum fe_stv0900_modcode modcode, | |
1069 | s32 pilot, u8 chip_id) | |
1070 | { | |
1071 | u8 aclc_value = 0x29; | |
1e0c397d IL |
1072 | s32 i; |
1073 | const struct stv0900_car_loop_optim *cls2, *cllqs2, *cllas2; | |
99277b38 | 1074 | |
8171c205 | 1075 | dprintk("%s\n", __func__); |
99277b38 | 1076 | |
1e0c397d IL |
1077 | if (chip_id <= 0x12) { |
1078 | cls2 = FE_STV0900_S2CarLoop; | |
1079 | cllqs2 = FE_STV0900_S2LowQPCarLoopCut30; | |
1080 | cllas2 = FE_STV0900_S2APSKCarLoopCut30; | |
1081 | } else if (chip_id == 0x20) { | |
1082 | cls2 = FE_STV0900_S2CarLoopCut20; | |
1083 | cllqs2 = FE_STV0900_S2LowQPCarLoopCut20; | |
1084 | cllas2 = FE_STV0900_S2APSKCarLoopCut20; | |
1085 | } else { | |
1086 | cls2 = FE_STV0900_S2CarLoopCut30; | |
1087 | cllqs2 = FE_STV0900_S2LowQPCarLoopCut30; | |
1088 | cllas2 = FE_STV0900_S2APSKCarLoopCut30; | |
1089 | } | |
99277b38 IL |
1090 | |
1091 | if (modcode < STV0900_QPSK_12) { | |
1092 | i = 0; | |
1e0c397d | 1093 | while ((i < 3) && (modcode != cllqs2[i].modcode)) |
99277b38 IL |
1094 | i++; |
1095 | ||
1096 | if (i >= 3) | |
1097 | i = 2; | |
1098 | } else { | |
1099 | i = 0; | |
1e0c397d | 1100 | while ((i < 14) && (modcode != cls2[i].modcode)) |
99277b38 IL |
1101 | i++; |
1102 | ||
1103 | if (i >= 14) { | |
1104 | i = 0; | |
1e0c397d | 1105 | while ((i < 11) && (modcode != cllas2[i].modcode)) |
99277b38 IL |
1106 | i++; |
1107 | ||
1108 | if (i >= 11) | |
1109 | i = 10; | |
1110 | } | |
1111 | } | |
1112 | ||
1113 | if (modcode <= STV0900_QPSK_25) { | |
1114 | if (pilot) { | |
1115 | if (srate <= 3000000) | |
1e0c397d | 1116 | aclc_value = cllqs2[i].car_loop_pilots_on_2; |
99277b38 | 1117 | else if (srate <= 7000000) |
1e0c397d | 1118 | aclc_value = cllqs2[i].car_loop_pilots_on_5; |
99277b38 | 1119 | else if (srate <= 15000000) |
1e0c397d | 1120 | aclc_value = cllqs2[i].car_loop_pilots_on_10; |
99277b38 | 1121 | else if (srate <= 25000000) |
1e0c397d | 1122 | aclc_value = cllqs2[i].car_loop_pilots_on_20; |
99277b38 | 1123 | else |
1e0c397d | 1124 | aclc_value = cllqs2[i].car_loop_pilots_on_30; |
99277b38 IL |
1125 | } else { |
1126 | if (srate <= 3000000) | |
1e0c397d | 1127 | aclc_value = cllqs2[i].car_loop_pilots_off_2; |
99277b38 | 1128 | else if (srate <= 7000000) |
1e0c397d | 1129 | aclc_value = cllqs2[i].car_loop_pilots_off_5; |
99277b38 | 1130 | else if (srate <= 15000000) |
1e0c397d | 1131 | aclc_value = cllqs2[i].car_loop_pilots_off_10; |
99277b38 | 1132 | else if (srate <= 25000000) |
1e0c397d | 1133 | aclc_value = cllqs2[i].car_loop_pilots_off_20; |
99277b38 | 1134 | else |
1e0c397d | 1135 | aclc_value = cllqs2[i].car_loop_pilots_off_30; |
99277b38 IL |
1136 | } |
1137 | ||
1138 | } else if (modcode <= STV0900_8PSK_910) { | |
1139 | if (pilot) { | |
1140 | if (srate <= 3000000) | |
1e0c397d | 1141 | aclc_value = cls2[i].car_loop_pilots_on_2; |
99277b38 | 1142 | else if (srate <= 7000000) |
1e0c397d | 1143 | aclc_value = cls2[i].car_loop_pilots_on_5; |
99277b38 | 1144 | else if (srate <= 15000000) |
1e0c397d | 1145 | aclc_value = cls2[i].car_loop_pilots_on_10; |
99277b38 | 1146 | else if (srate <= 25000000) |
1e0c397d | 1147 | aclc_value = cls2[i].car_loop_pilots_on_20; |
99277b38 | 1148 | else |
1e0c397d | 1149 | aclc_value = cls2[i].car_loop_pilots_on_30; |
99277b38 IL |
1150 | } else { |
1151 | if (srate <= 3000000) | |
1e0c397d | 1152 | aclc_value = cls2[i].car_loop_pilots_off_2; |
99277b38 | 1153 | else if (srate <= 7000000) |
1e0c397d | 1154 | aclc_value = cls2[i].car_loop_pilots_off_5; |
99277b38 | 1155 | else if (srate <= 15000000) |
1e0c397d | 1156 | aclc_value = cls2[i].car_loop_pilots_off_10; |
99277b38 | 1157 | else if (srate <= 25000000) |
1e0c397d | 1158 | aclc_value = cls2[i].car_loop_pilots_off_20; |
99277b38 | 1159 | else |
1e0c397d | 1160 | aclc_value = cls2[i].car_loop_pilots_off_30; |
99277b38 IL |
1161 | } |
1162 | ||
1163 | } else { | |
1164 | if (srate <= 3000000) | |
1e0c397d | 1165 | aclc_value = cllas2[i].car_loop_pilots_on_2; |
99277b38 | 1166 | else if (srate <= 7000000) |
1e0c397d | 1167 | aclc_value = cllas2[i].car_loop_pilots_on_5; |
99277b38 | 1168 | else if (srate <= 15000000) |
1e0c397d | 1169 | aclc_value = cllas2[i].car_loop_pilots_on_10; |
99277b38 | 1170 | else if (srate <= 25000000) |
1e0c397d | 1171 | aclc_value = cllas2[i].car_loop_pilots_on_20; |
99277b38 | 1172 | else |
1e0c397d | 1173 | aclc_value = cllas2[i].car_loop_pilots_on_30; |
99277b38 IL |
1174 | } |
1175 | ||
1176 | return aclc_value; | |
1177 | } | |
1178 | ||
1e0c397d IL |
1179 | u8 stv0900_get_optim_short_carr_loop(s32 srate, |
1180 | enum fe_stv0900_modulation modulation, | |
1181 | u8 chip_id) | |
99277b38 | 1182 | { |
1e0c397d IL |
1183 | const struct stv0900_short_frames_car_loop_optim *s2scl; |
1184 | const struct stv0900_short_frames_car_loop_optim_vs_mod *s2sclc30; | |
99277b38 | 1185 | s32 mod_index = 0; |
99277b38 IL |
1186 | u8 aclc_value = 0x0b; |
1187 | ||
8171c205 | 1188 | dprintk("%s\n", __func__); |
99277b38 | 1189 | |
1e0c397d IL |
1190 | s2scl = FE_STV0900_S2ShortCarLoop; |
1191 | s2sclc30 = FE_STV0900_S2ShortCarLoopCut30; | |
1192 | ||
99277b38 IL |
1193 | switch (modulation) { |
1194 | case STV0900_QPSK: | |
1195 | default: | |
1196 | mod_index = 0; | |
1197 | break; | |
1198 | case STV0900_8PSK: | |
1199 | mod_index = 1; | |
1200 | break; | |
1201 | case STV0900_16APSK: | |
1202 | mod_index = 2; | |
1203 | break; | |
1204 | case STV0900_32APSK: | |
1205 | mod_index = 3; | |
1206 | break; | |
1207 | } | |
1208 | ||
1e0c397d | 1209 | if (chip_id >= 0x30) { |
99277b38 | 1210 | if (srate <= 3000000) |
1e0c397d | 1211 | aclc_value = s2sclc30[mod_index].car_loop_2; |
99277b38 | 1212 | else if (srate <= 7000000) |
1e0c397d | 1213 | aclc_value = s2sclc30[mod_index].car_loop_5; |
99277b38 | 1214 | else if (srate <= 15000000) |
1e0c397d | 1215 | aclc_value = s2sclc30[mod_index].car_loop_10; |
99277b38 | 1216 | else if (srate <= 25000000) |
1e0c397d | 1217 | aclc_value = s2sclc30[mod_index].car_loop_20; |
99277b38 | 1218 | else |
1e0c397d | 1219 | aclc_value = s2sclc30[mod_index].car_loop_30; |
99277b38 | 1220 | |
1e0c397d | 1221 | } else if (chip_id >= 0x20) { |
99277b38 | 1222 | if (srate <= 3000000) |
1e0c397d | 1223 | aclc_value = s2scl[mod_index].car_loop_cut20_2; |
99277b38 | 1224 | else if (srate <= 7000000) |
1e0c397d | 1225 | aclc_value = s2scl[mod_index].car_loop_cut20_5; |
99277b38 | 1226 | else if (srate <= 15000000) |
1e0c397d | 1227 | aclc_value = s2scl[mod_index].car_loop_cut20_10; |
99277b38 | 1228 | else if (srate <= 25000000) |
1e0c397d | 1229 | aclc_value = s2scl[mod_index].car_loop_cut20_20; |
99277b38 | 1230 | else |
1e0c397d IL |
1231 | aclc_value = s2scl[mod_index].car_loop_cut20_30; |
1232 | ||
1233 | } else { | |
1234 | if (srate <= 3000000) | |
1235 | aclc_value = s2scl[mod_index].car_loop_cut12_2; | |
1236 | else if (srate <= 7000000) | |
1237 | aclc_value = s2scl[mod_index].car_loop_cut12_5; | |
1238 | else if (srate <= 15000000) | |
1239 | aclc_value = s2scl[mod_index].car_loop_cut12_10; | |
1240 | else if (srate <= 25000000) | |
1241 | aclc_value = s2scl[mod_index].car_loop_cut12_20; | |
1242 | else | |
1243 | aclc_value = s2scl[mod_index].car_loop_cut12_30; | |
99277b38 | 1244 | |
99277b38 IL |
1245 | } |
1246 | ||
1247 | return aclc_value; | |
1248 | } | |
1249 | ||
1e0c397d IL |
1250 | static |
1251 | enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *intp, | |
99277b38 IL |
1252 | enum fe_stv0900_demod_mode LDPC_Mode, |
1253 | enum fe_stv0900_demod_num demod) | |
1254 | { | |
1255 | enum fe_stv0900_error error = STV0900_NO_ERROR; | |
1e0c397d | 1256 | s32 reg_ind; |
99277b38 | 1257 | |
8171c205 | 1258 | dprintk("%s\n", __func__); |
99277b38 IL |
1259 | |
1260 | switch (LDPC_Mode) { | |
1261 | case STV0900_DUAL: | |
1262 | default: | |
1e0c397d IL |
1263 | if ((intp->demod_mode != STV0900_DUAL) |
1264 | || (stv0900_get_bits(intp, F0900_DDEMOD) != 1)) { | |
1265 | stv0900_write_reg(intp, R0900_GENCFG, 0x1d); | |
1266 | ||
1267 | intp->demod_mode = STV0900_DUAL; | |
1268 | ||
1269 | stv0900_write_bits(intp, F0900_FRESFEC, 1); | |
1270 | stv0900_write_bits(intp, F0900_FRESFEC, 0); | |
1271 | ||
1272 | for (reg_ind = 0; reg_ind < 7; reg_ind++) | |
1273 | stv0900_write_reg(intp, | |
1274 | R0900_P1_MODCODLST0 + reg_ind, | |
1275 | 0xff); | |
1276 | for (reg_ind = 0; reg_ind < 8; reg_ind++) | |
1277 | stv0900_write_reg(intp, | |
1278 | R0900_P1_MODCODLST7 + reg_ind, | |
1279 | 0xcc); | |
1280 | ||
1281 | stv0900_write_reg(intp, R0900_P1_MODCODLSTE, 0xff); | |
1282 | stv0900_write_reg(intp, R0900_P1_MODCODLSTF, 0xcf); | |
1283 | ||
1284 | for (reg_ind = 0; reg_ind < 7; reg_ind++) | |
1285 | stv0900_write_reg(intp, | |
1286 | R0900_P2_MODCODLST0 + reg_ind, | |
1287 | 0xff); | |
1288 | for (reg_ind = 0; reg_ind < 8; reg_ind++) | |
1289 | stv0900_write_reg(intp, | |
1290 | R0900_P2_MODCODLST7 + reg_ind, | |
1291 | 0xcc); | |
1292 | ||
1293 | stv0900_write_reg(intp, R0900_P2_MODCODLSTE, 0xff); | |
1294 | stv0900_write_reg(intp, R0900_P2_MODCODLSTF, 0xcf); | |
99277b38 IL |
1295 | } |
1296 | ||
1297 | break; | |
1298 | case STV0900_SINGLE: | |
1e0c397d IL |
1299 | if (demod == STV0900_DEMOD_2) { |
1300 | stv0900_stop_all_s2_modcod(intp, STV0900_DEMOD_1); | |
1301 | stv0900_activate_s2_modcod_single(intp, | |
1302 | STV0900_DEMOD_2); | |
1303 | stv0900_write_reg(intp, R0900_GENCFG, 0x06); | |
1304 | } else { | |
1305 | stv0900_stop_all_s2_modcod(intp, STV0900_DEMOD_2); | |
1306 | stv0900_activate_s2_modcod_single(intp, | |
1307 | STV0900_DEMOD_1); | |
1308 | stv0900_write_reg(intp, R0900_GENCFG, 0x04); | |
1309 | } | |
99277b38 | 1310 | |
1e0c397d | 1311 | intp->demod_mode = STV0900_SINGLE; |
99277b38 | 1312 | |
1e0c397d IL |
1313 | stv0900_write_bits(intp, F0900_FRESFEC, 1); |
1314 | stv0900_write_bits(intp, F0900_FRESFEC, 0); | |
1315 | stv0900_write_bits(intp, F0900_P1_ALGOSWRST, 1); | |
1316 | stv0900_write_bits(intp, F0900_P1_ALGOSWRST, 0); | |
1317 | stv0900_write_bits(intp, F0900_P2_ALGOSWRST, 1); | |
1318 | stv0900_write_bits(intp, F0900_P2_ALGOSWRST, 0); | |
99277b38 IL |
1319 | break; |
1320 | } | |
1321 | ||
1322 | return error; | |
1323 | } | |
1324 | ||
1325 | static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, | |
1326 | struct stv0900_init_params *p_init) | |
1327 | { | |
1328 | struct stv0900_state *state = fe->demodulator_priv; | |
1329 | enum fe_stv0900_error error = STV0900_NO_ERROR; | |
1330 | enum fe_stv0900_error demodError = STV0900_NO_ERROR; | |
1e0c397d IL |
1331 | struct stv0900_internal *intp = NULL; |
1332 | ||
f867c3f4 | 1333 | int selosci, i; |
99277b38 IL |
1334 | |
1335 | struct stv0900_inode *temp_int = find_inode(state->i2c_adap, | |
1336 | state->config->demod_address); | |
1337 | ||
8171c205 | 1338 | dprintk("%s\n", __func__); |
99277b38 | 1339 | |
29372a8d | 1340 | if ((temp_int != NULL) && (p_init->demod_mode == STV0900_DUAL)) { |
99277b38 IL |
1341 | state->internal = temp_int->internal; |
1342 | (state->internal->dmds_used)++; | |
8171c205 | 1343 | dprintk("%s: Find Internal Structure!\n", __func__); |
99277b38 IL |
1344 | return STV0900_NO_ERROR; |
1345 | } else { | |
1e0c397d IL |
1346 | state->internal = kmalloc(sizeof(struct stv0900_internal), |
1347 | GFP_KERNEL); | |
99277b38 IL |
1348 | temp_int = append_internal(state->internal); |
1349 | state->internal->dmds_used = 1; | |
1350 | state->internal->i2c_adap = state->i2c_adap; | |
1351 | state->internal->i2c_addr = state->config->demod_address; | |
1352 | state->internal->clkmode = state->config->clkmode; | |
1353 | state->internal->errs = STV0900_NO_ERROR; | |
8171c205 | 1354 | dprintk("%s: Create New Internal Structure!\n", __func__); |
99277b38 IL |
1355 | } |
1356 | ||
1e0c397d IL |
1357 | if (state->internal == NULL) { |
1358 | error = STV0900_INVALID_HANDLE; | |
1359 | return error; | |
1360 | } | |
99277b38 | 1361 | |
1e0c397d IL |
1362 | demodError = stv0900_initialize(state->internal); |
1363 | if (demodError == STV0900_NO_ERROR) { | |
1364 | error = STV0900_NO_ERROR; | |
1365 | } else { | |
1366 | if (demodError == STV0900_INVALID_HANDLE) | |
1367 | error = STV0900_INVALID_HANDLE; | |
1368 | else | |
1369 | error = STV0900_I2C_ERROR; | |
f867c3f4 | 1370 | |
1e0c397d IL |
1371 | return error; |
1372 | } | |
99277b38 | 1373 | |
1e0c397d IL |
1374 | if (state->internal == NULL) { |
1375 | error = STV0900_INVALID_HANDLE; | |
1376 | return error; | |
1377 | } | |
99277b38 | 1378 | |
1e0c397d | 1379 | intp = state->internal; |
99277b38 | 1380 | |
1e0c397d IL |
1381 | intp->demod_mode = p_init->demod_mode; |
1382 | stv0900_st_dvbs2_single(intp, intp->demod_mode, STV0900_DEMOD_1); | |
1383 | intp->chip_id = stv0900_read_reg(intp, R0900_MID); | |
1384 | intp->rolloff = p_init->rolloff; | |
1385 | intp->quartz = p_init->dmd_ref_clk; | |
1386 | ||
1387 | stv0900_write_bits(intp, F0900_P1_ROLLOFF_CONTROL, p_init->rolloff); | |
1388 | stv0900_write_bits(intp, F0900_P2_ROLLOFF_CONTROL, p_init->rolloff); | |
1389 | ||
1390 | intp->ts_config = p_init->ts_config; | |
1391 | if (intp->ts_config == NULL) | |
1392 | stv0900_set_ts_parallel_serial(intp, | |
1393 | p_init->path1_ts_clock, | |
1394 | p_init->path2_ts_clock); | |
1395 | else { | |
1396 | for (i = 0; intp->ts_config[i].addr != 0xffff; i++) | |
1397 | stv0900_write_reg(intp, | |
1398 | intp->ts_config[i].addr, | |
1399 | intp->ts_config[i].val); | |
1400 | ||
1401 | stv0900_write_bits(intp, F0900_P2_RST_HWARE, 1); | |
1402 | stv0900_write_bits(intp, F0900_P2_RST_HWARE, 0); | |
1403 | stv0900_write_bits(intp, F0900_P1_RST_HWARE, 1); | |
1404 | stv0900_write_bits(intp, F0900_P1_RST_HWARE, 0); | |
1405 | } | |
1406 | ||
1407 | stv0900_write_bits(intp, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress); | |
1408 | switch (p_init->tuner1_adc) { | |
1409 | case 1: | |
1410 | stv0900_write_reg(intp, R0900_TSTTNR1, 0x26); | |
1411 | break; | |
1412 | default: | |
1413 | break; | |
1414 | } | |
1415 | ||
1416 | stv0900_write_bits(intp, F0900_P2_TUN_MADDRESS, p_init->tun2_maddress); | |
1417 | switch (p_init->tuner2_adc) { | |
1418 | case 1: | |
1419 | stv0900_write_reg(intp, R0900_TSTTNR3, 0x26); | |
1420 | break; | |
1421 | default: | |
1422 | break; | |
99277b38 IL |
1423 | } |
1424 | ||
1e0c397d IL |
1425 | stv0900_write_bits(intp, F0900_P1_TUN_IQSWAP, p_init->tun1_iq_inv); |
1426 | stv0900_write_bits(intp, F0900_P2_TUN_IQSWAP, p_init->tun2_iq_inv); | |
1427 | stv0900_set_mclk(intp, 135000000); | |
1428 | msleep(3); | |
1429 | ||
1430 | switch (intp->clkmode) { | |
1431 | case 0: | |
1432 | case 2: | |
1433 | stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 | intp->clkmode); | |
1434 | break; | |
1435 | default: | |
1436 | selosci = 0x02 & stv0900_read_reg(intp, R0900_SYNTCTRL); | |
1437 | stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 | selosci); | |
1438 | break; | |
1439 | } | |
1440 | msleep(3); | |
1441 | ||
1442 | intp->mclk = stv0900_get_mclk_freq(intp, intp->quartz); | |
1443 | if (intp->errs) | |
1444 | error = STV0900_I2C_ERROR; | |
1445 | ||
99277b38 IL |
1446 | return error; |
1447 | } | |
1448 | ||
1e0c397d | 1449 | static int stv0900_status(struct stv0900_internal *intp, |
99277b38 IL |
1450 | enum fe_stv0900_demod_num demod) |
1451 | { | |
1452 | enum fe_stv0900_search_state demod_state; | |
99277b38 IL |
1453 | int locked = FALSE; |
1454 | ||
1e0c397d | 1455 | demod_state = stv0900_get_bits(intp, HEADER_MODE); |
99277b38 IL |
1456 | switch (demod_state) { |
1457 | case STV0900_SEARCH: | |
1458 | case STV0900_PLH_DETECTED: | |
1459 | default: | |
1460 | locked = FALSE; | |
1461 | break; | |
1462 | case STV0900_DVBS2_FOUND: | |
1e0c397d IL |
1463 | locked = stv0900_get_bits(intp, LOCK_DEFINITIF) && |
1464 | stv0900_get_bits(intp, PKTDELIN_LOCK) && | |
1465 | stv0900_get_bits(intp, TSFIFO_LINEOK); | |
99277b38 IL |
1466 | break; |
1467 | case STV0900_DVBS_FOUND: | |
1e0c397d IL |
1468 | locked = stv0900_get_bits(intp, LOCK_DEFINITIF) && |
1469 | stv0900_get_bits(intp, LOCKEDVIT) && | |
1470 | stv0900_get_bits(intp, TSFIFO_LINEOK); | |
99277b38 IL |
1471 | break; |
1472 | } | |
1473 | ||
1e0c397d IL |
1474 | dprintk("%s: locked = %d\n", __func__, locked); |
1475 | ||
99277b38 IL |
1476 | return locked; |
1477 | } | |
1478 | ||
1479 | static enum dvbfe_search stv0900_search(struct dvb_frontend *fe, | |
1480 | struct dvb_frontend_parameters *params) | |
1481 | { | |
1482 | struct stv0900_state *state = fe->demodulator_priv; | |
1e0c397d IL |
1483 | struct stv0900_internal *intp = state->internal; |
1484 | enum fe_stv0900_demod_num demod = state->demod; | |
99277b38 IL |
1485 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1486 | ||
1487 | struct stv0900_search_params p_search; | |
1488 | struct stv0900_signal_info p_result; | |
1489 | ||
1490 | enum fe_stv0900_error error = STV0900_NO_ERROR; | |
1491 | ||
8171c205 | 1492 | dprintk("%s: ", __func__); |
99277b38 | 1493 | |
1e0c397d IL |
1494 | if (!(INRANGE(100000, c->symbol_rate, 70000000))) |
1495 | return DVBFE_ALGO_SEARCH_FAILED; | |
1496 | ||
99277b38 | 1497 | p_result.locked = FALSE; |
1e0c397d | 1498 | p_search.path = demod; |
99277b38 IL |
1499 | p_search.frequency = c->frequency; |
1500 | p_search.symbol_rate = c->symbol_rate; | |
1501 | p_search.search_range = 10000000; | |
1502 | p_search.fec = STV0900_FEC_UNKNOWN; | |
1503 | p_search.standard = STV0900_AUTO_SEARCH; | |
1504 | p_search.iq_inversion = STV0900_IQ_AUTO; | |
1505 | p_search.search_algo = STV0900_BLIND_SEARCH; | |
1506 | ||
1e0c397d IL |
1507 | intp->srch_standard[demod] = p_search.standard; |
1508 | intp->symbol_rate[demod] = p_search.symbol_rate; | |
1509 | intp->srch_range[demod] = p_search.search_range; | |
1510 | intp->freq[demod] = p_search.frequency; | |
1511 | intp->srch_algo[demod] = p_search.search_algo; | |
1512 | intp->srch_iq_inv[demod] = p_search.iq_inversion; | |
1513 | intp->fec[demod] = p_search.fec; | |
1514 | if ((stv0900_algo(fe) == STV0900_RANGEOK) && | |
1515 | (intp->errs == STV0900_NO_ERROR)) { | |
1516 | p_result.locked = intp->result[demod].locked; | |
1517 | p_result.standard = intp->result[demod].standard; | |
1518 | p_result.frequency = intp->result[demod].frequency; | |
1519 | p_result.symbol_rate = intp->result[demod].symbol_rate; | |
1520 | p_result.fec = intp->result[demod].fec; | |
1521 | p_result.modcode = intp->result[demod].modcode; | |
1522 | p_result.pilot = intp->result[demod].pilot; | |
1523 | p_result.frame_len = intp->result[demod].frame_len; | |
1524 | p_result.spectrum = intp->result[demod].spectrum; | |
1525 | p_result.rolloff = intp->result[demod].rolloff; | |
1526 | p_result.modulation = intp->result[demod].modulation; | |
1527 | } else { | |
1528 | p_result.locked = FALSE; | |
1529 | switch (intp->err[demod]) { | |
1530 | case STV0900_I2C_ERROR: | |
1531 | error = STV0900_I2C_ERROR; | |
99277b38 | 1532 | break; |
1e0c397d IL |
1533 | case STV0900_NO_ERROR: |
1534 | default: | |
1535 | error = STV0900_SEARCH_FAILED; | |
99277b38 IL |
1536 | break; |
1537 | } | |
1e0c397d | 1538 | } |
99277b38 IL |
1539 | |
1540 | if ((p_result.locked == TRUE) && (error == STV0900_NO_ERROR)) { | |
8171c205 | 1541 | dprintk("Search Success\n"); |
99277b38 IL |
1542 | return DVBFE_ALGO_SEARCH_SUCCESS; |
1543 | } else { | |
8171c205 | 1544 | dprintk("Search Fail\n"); |
99277b38 IL |
1545 | return DVBFE_ALGO_SEARCH_FAILED; |
1546 | } | |
1547 | ||
99277b38 IL |
1548 | } |
1549 | ||
1550 | static int stv0900_read_status(struct dvb_frontend *fe, enum fe_status *status) | |
1551 | { | |
1552 | struct stv0900_state *state = fe->demodulator_priv; | |
1553 | ||
78175bf2 | 1554 | dprintk("%s: ", __func__); |
99277b38 IL |
1555 | |
1556 | if ((stv0900_status(state->internal, state->demod)) == TRUE) { | |
1557 | dprintk("DEMOD LOCK OK\n"); | |
1558 | *status = FE_HAS_CARRIER | |
1559 | | FE_HAS_VITERBI | |
1560 | | FE_HAS_SYNC | |
1561 | | FE_HAS_LOCK; | |
1562 | } else | |
1563 | dprintk("DEMOD LOCK FAIL\n"); | |
1564 | ||
1565 | return 0; | |
1566 | } | |
1567 | ||
1568 | static int stv0900_track(struct dvb_frontend *fe, | |
1569 | struct dvb_frontend_parameters *p) | |
1570 | { | |
1571 | return 0; | |
1572 | } | |
1573 | ||
1574 | static int stv0900_stop_ts(struct dvb_frontend *fe, int stop_ts) | |
1575 | { | |
1576 | ||
1577 | struct stv0900_state *state = fe->demodulator_priv; | |
1e0c397d | 1578 | struct stv0900_internal *intp = state->internal; |
99277b38 | 1579 | enum fe_stv0900_demod_num demod = state->demod; |
99277b38 IL |
1580 | |
1581 | if (stop_ts == TRUE) | |
1e0c397d | 1582 | stv0900_write_bits(intp, RST_HWARE, 1); |
99277b38 | 1583 | else |
1e0c397d | 1584 | stv0900_write_bits(intp, RST_HWARE, 0); |
99277b38 IL |
1585 | |
1586 | return 0; | |
1587 | } | |
1588 | ||
1589 | static int stv0900_diseqc_init(struct dvb_frontend *fe) | |
1590 | { | |
1591 | struct stv0900_state *state = fe->demodulator_priv; | |
1e0c397d | 1592 | struct stv0900_internal *intp = state->internal; |
99277b38 | 1593 | enum fe_stv0900_demod_num demod = state->demod; |
99277b38 | 1594 | |
1e0c397d IL |
1595 | stv0900_write_bits(intp, DISTX_MODE, state->config->diseqc_mode); |
1596 | stv0900_write_bits(intp, DISEQC_RESET, 1); | |
1597 | stv0900_write_bits(intp, DISEQC_RESET, 0); | |
99277b38 IL |
1598 | |
1599 | return 0; | |
1600 | } | |
1601 | ||
1602 | static int stv0900_init(struct dvb_frontend *fe) | |
1603 | { | |
8171c205 | 1604 | dprintk("%s\n", __func__); |
99277b38 IL |
1605 | |
1606 | stv0900_stop_ts(fe, 1); | |
1607 | stv0900_diseqc_init(fe); | |
1608 | ||
1609 | return 0; | |
1610 | } | |
1611 | ||
1e0c397d | 1612 | static int stv0900_diseqc_send(struct stv0900_internal *intp , u8 *data, |
99277b38 IL |
1613 | u32 NbData, enum fe_stv0900_demod_num demod) |
1614 | { | |
1615 | s32 i = 0; | |
1616 | ||
1e0c397d IL |
1617 | stv0900_write_bits(intp, DIS_PRECHARGE, 1); |
1618 | while (i < NbData) { | |
1619 | while (stv0900_get_bits(intp, FIFO_FULL)) | |
1620 | ;/* checkpatch complains */ | |
1621 | stv0900_write_reg(intp, DISTXDATA, data[i]); | |
1622 | i++; | |
1623 | } | |
99277b38 | 1624 | |
1e0c397d IL |
1625 | stv0900_write_bits(intp, DIS_PRECHARGE, 0); |
1626 | i = 0; | |
1627 | while ((stv0900_get_bits(intp, TX_IDLE) != 1) && (i < 10)) { | |
1628 | msleep(10); | |
1629 | i++; | |
99277b38 IL |
1630 | } |
1631 | ||
1632 | return 0; | |
1633 | } | |
1634 | ||
1635 | static int stv0900_send_master_cmd(struct dvb_frontend *fe, | |
1636 | struct dvb_diseqc_master_cmd *cmd) | |
1637 | { | |
1638 | struct stv0900_state *state = fe->demodulator_priv; | |
1639 | ||
1640 | return stv0900_diseqc_send(state->internal, | |
1641 | cmd->msg, | |
1642 | cmd->msg_len, | |
1643 | state->demod); | |
1644 | } | |
1645 | ||
1646 | static int stv0900_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) | |
1647 | { | |
1648 | struct stv0900_state *state = fe->demodulator_priv; | |
1e0c397d | 1649 | struct stv0900_internal *intp = state->internal; |
99277b38 | 1650 | enum fe_stv0900_demod_num demod = state->demod; |
9329fb5b | 1651 | u8 data; |
99277b38 | 1652 | |
99277b38 IL |
1653 | |
1654 | switch (burst) { | |
1655 | case SEC_MINI_A: | |
1e0c397d | 1656 | stv0900_write_bits(intp, DISTX_MODE, 3);/* Unmodulated */ |
9329fb5b | 1657 | data = 0x00; |
1e0c397d | 1658 | stv0900_diseqc_send(intp, &data, 1, state->demod); |
99277b38 IL |
1659 | break; |
1660 | case SEC_MINI_B: | |
1e0c397d | 1661 | stv0900_write_bits(intp, DISTX_MODE, 2);/* Modulated */ |
9329fb5b | 1662 | data = 0xff; |
1e0c397d | 1663 | stv0900_diseqc_send(intp, &data, 1, state->demod); |
99277b38 IL |
1664 | break; |
1665 | } | |
1666 | ||
1667 | return 0; | |
1668 | } | |
1669 | ||
1670 | static int stv0900_recv_slave_reply(struct dvb_frontend *fe, | |
1671 | struct dvb_diseqc_slave_reply *reply) | |
1672 | { | |
1673 | struct stv0900_state *state = fe->demodulator_priv; | |
1e0c397d IL |
1674 | struct stv0900_internal *intp = state->internal; |
1675 | enum fe_stv0900_demod_num demod = state->demod; | |
99277b38 IL |
1676 | s32 i = 0; |
1677 | ||
1e0c397d | 1678 | reply->msg_len = 0; |
99277b38 | 1679 | |
1e0c397d IL |
1680 | while ((stv0900_get_bits(intp, RX_END) != 1) && (i < 10)) { |
1681 | msleep(10); | |
1682 | i++; | |
1683 | } | |
99277b38 | 1684 | |
1e0c397d IL |
1685 | if (stv0900_get_bits(intp, RX_END)) { |
1686 | reply->msg_len = stv0900_get_bits(intp, FIFO_BYTENBR); | |
99277b38 | 1687 | |
1e0c397d IL |
1688 | for (i = 0; i < reply->msg_len; i++) |
1689 | reply->msg[i] = stv0900_read_reg(intp, DISRXDATA); | |
99277b38 IL |
1690 | } |
1691 | ||
1692 | return 0; | |
1693 | } | |
1694 | ||
9329fb5b | 1695 | static int stv0900_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t toneoff) |
99277b38 IL |
1696 | { |
1697 | struct stv0900_state *state = fe->demodulator_priv; | |
1e0c397d | 1698 | struct stv0900_internal *intp = state->internal; |
99277b38 | 1699 | enum fe_stv0900_demod_num demod = state->demod; |
99277b38 | 1700 | |
9329fb5b | 1701 | dprintk("%s: %s\n", __func__, ((toneoff == 0) ? "On" : "Off")); |
99277b38 | 1702 | |
9329fb5b AO |
1703 | switch (toneoff) { |
1704 | case SEC_TONE_ON: | |
1705 | /*Set the DiseqC mode to 22Khz _continues_ tone*/ | |
1e0c397d IL |
1706 | stv0900_write_bits(intp, DISTX_MODE, 0); |
1707 | stv0900_write_bits(intp, DISEQC_RESET, 1); | |
99277b38 | 1708 | /*release DiseqC reset to enable the 22KHz tone*/ |
1e0c397d | 1709 | stv0900_write_bits(intp, DISEQC_RESET, 0); |
9329fb5b AO |
1710 | break; |
1711 | case SEC_TONE_OFF: | |
1712 | /*return diseqc mode to config->diseqc_mode. | |
1713 | Usually it's without _continues_ tone */ | |
1e0c397d | 1714 | stv0900_write_bits(intp, DISTX_MODE, |
9329fb5b | 1715 | state->config->diseqc_mode); |
99277b38 | 1716 | /*maintain the DiseqC reset to disable the 22KHz tone*/ |
1e0c397d IL |
1717 | stv0900_write_bits(intp, DISEQC_RESET, 1); |
1718 | stv0900_write_bits(intp, DISEQC_RESET, 0); | |
9329fb5b AO |
1719 | break; |
1720 | default: | |
1721 | return -EINVAL; | |
99277b38 IL |
1722 | } |
1723 | ||
1724 | return 0; | |
1725 | } | |
1726 | ||
1727 | static void stv0900_release(struct dvb_frontend *fe) | |
1728 | { | |
1729 | struct stv0900_state *state = fe->demodulator_priv; | |
1730 | ||
8171c205 | 1731 | dprintk("%s\n", __func__); |
99277b38 IL |
1732 | |
1733 | if ((--(state->internal->dmds_used)) <= 0) { | |
1734 | ||
8171c205 | 1735 | dprintk("%s: Actually removing\n", __func__); |
99277b38 IL |
1736 | |
1737 | remove_inode(state->internal); | |
1738 | kfree(state->internal); | |
1739 | } | |
1740 | ||
1741 | kfree(state); | |
1742 | } | |
1743 | ||
1744 | static struct dvb_frontend_ops stv0900_ops = { | |
1745 | ||
1746 | .info = { | |
1747 | .name = "STV0900 frontend", | |
1748 | .type = FE_QPSK, | |
1749 | .frequency_min = 950000, | |
1750 | .frequency_max = 2150000, | |
1751 | .frequency_stepsize = 125, | |
1752 | .frequency_tolerance = 0, | |
1753 | .symbol_rate_min = 1000000, | |
1754 | .symbol_rate_max = 45000000, | |
1755 | .symbol_rate_tolerance = 500, | |
1756 | .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | | |
1757 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | | |
1758 | FE_CAN_FEC_7_8 | FE_CAN_QPSK | | |
1759 | FE_CAN_2G_MODULATION | | |
1760 | FE_CAN_FEC_AUTO | |
1761 | }, | |
1762 | .release = stv0900_release, | |
1763 | .init = stv0900_init, | |
1764 | .get_frontend_algo = stv0900_frontend_algo, | |
1765 | .i2c_gate_ctrl = stv0900_i2c_gate_ctrl, | |
1766 | .diseqc_send_master_cmd = stv0900_send_master_cmd, | |
1767 | .diseqc_send_burst = stv0900_send_burst, | |
1768 | .diseqc_recv_slave_reply = stv0900_recv_slave_reply, | |
1769 | .set_tone = stv0900_set_tone, | |
1770 | .set_property = stb0900_set_property, | |
1771 | .get_property = stb0900_get_property, | |
1772 | .search = stv0900_search, | |
1773 | .track = stv0900_track, | |
1774 | .read_status = stv0900_read_status, | |
1775 | .read_ber = stv0900_read_ber, | |
1776 | .read_signal_strength = stv0900_read_signal_strength, | |
1777 | .read_snr = stv0900_read_snr, | |
ee1ebcfe | 1778 | .read_ucblocks = stv0900_read_ucblocks, |
99277b38 IL |
1779 | }; |
1780 | ||
1781 | struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, | |
1782 | struct i2c_adapter *i2c, | |
1783 | int demod) | |
1784 | { | |
1785 | struct stv0900_state *state = NULL; | |
1786 | struct stv0900_init_params init_params; | |
1787 | enum fe_stv0900_error err_stv0900; | |
1788 | ||
1789 | state = kzalloc(sizeof(struct stv0900_state), GFP_KERNEL); | |
1790 | if (state == NULL) | |
1791 | goto error; | |
1792 | ||
1793 | state->demod = demod; | |
1794 | state->config = config; | |
1795 | state->i2c_adap = i2c; | |
1796 | ||
1797 | memcpy(&state->frontend.ops, &stv0900_ops, | |
1798 | sizeof(struct dvb_frontend_ops)); | |
1799 | state->frontend.demodulator_priv = state; | |
1800 | ||
1801 | switch (demod) { | |
1802 | case 0: | |
1803 | case 1: | |
1804 | init_params.dmd_ref_clk = config->xtal; | |
29372a8d | 1805 | init_params.demod_mode = config->demod_mode; |
99277b38 IL |
1806 | init_params.rolloff = STV0900_35; |
1807 | init_params.path1_ts_clock = config->path1_mode; | |
1808 | init_params.tun1_maddress = config->tun1_maddress; | |
1e0c397d | 1809 | init_params.tun1_iq_inv = STV0900_IQ_NORMAL; |
99277b38 IL |
1810 | init_params.tuner1_adc = config->tun1_adc; |
1811 | init_params.path2_ts_clock = config->path2_mode; | |
f867c3f4 | 1812 | init_params.ts_config = config->ts_config_regs; |
99277b38 IL |
1813 | init_params.tun2_maddress = config->tun2_maddress; |
1814 | init_params.tuner2_adc = config->tun2_adc; | |
1e0c397d | 1815 | init_params.tun2_iq_inv = STV0900_IQ_SWAPPED; |
99277b38 IL |
1816 | |
1817 | err_stv0900 = stv0900_init_internal(&state->frontend, | |
1818 | &init_params); | |
1819 | ||
1820 | if (err_stv0900) | |
1821 | goto error; | |
1822 | ||
99277b38 IL |
1823 | break; |
1824 | default: | |
1825 | goto error; | |
1826 | break; | |
1827 | } | |
1828 | ||
1829 | dprintk("%s: Attaching STV0900 demodulator(%d) \n", __func__, demod); | |
1830 | return &state->frontend; | |
1831 | ||
1832 | error: | |
1833 | dprintk("%s: Failed to attach STV0900 demodulator(%d) \n", | |
1834 | __func__, demod); | |
1835 | kfree(state); | |
1836 | return NULL; | |
1837 | } | |
1838 | EXPORT_SYMBOL(stv0900_attach); | |
1839 | ||
1840 | MODULE_PARM_DESC(debug, "Set debug"); | |
1841 | ||
1842 | MODULE_AUTHOR("Igor M. Liplianin"); | |
1843 | MODULE_DESCRIPTION("ST STV0900 frontend"); | |
1844 | MODULE_LICENSE("GPL"); |