1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | Driver for STV0297 demodulator |
4 | |
5 | Copyright (C) 2004 Andrew de Quincey <adq_dvb@lidskialf.net> |
6 | Copyright (C) 2003-2004 Dennis Noermann <dennis.noermann@noernet.de> |
7 | |
8 | */ |
9 | |
10 | #include <linux/init.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/module.h> |
13 | #include <linux/string.h> |
14 | #include <linux/delay.h> |
15 | #include <linux/jiffies.h> |
16 | #include <linux/slab.h> |
17 | |
18 | #include <media/dvb_frontend.h> |
19 | #include "stv0297.h" |
20 | |
21 | struct stv0297_state { |
22 | struct i2c_adapter *i2c; |
23 | const struct stv0297_config *config; |
24 | struct dvb_frontend frontend; |
25 | |
26 | unsigned long last_ber; |
27 | unsigned long base_freq; |
28 | }; |
29 | |
30 | #if 1 |
31 | #define dprintk(x...) printk(x) |
32 | #else |
33 | #define dprintk(x...) |
34 | #endif |
35 | |
36 | #define STV0297_CLOCK_KHZ 28900 |
37 | |
38 | |
39 | static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data) |
40 | { |
41 | int ret; |
42 | u8 buf[] = { reg, data }; |
43 | struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 2 }; |
44 | |
45 | ret = i2c_transfer(adap: state->i2c, msgs: &msg, num: 1); |
46 | |
47 | if (ret != 1) |
48 | dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n" , |
49 | __func__, reg, data, ret); |
50 | |
51 | return (ret != 1) ? -1 : 0; |
52 | } |
53 | |
54 | static int stv0297_readreg(struct stv0297_state *state, u8 reg) |
55 | { |
56 | int ret; |
57 | u8 b0[] = { reg }; |
58 | u8 b1[] = { 0 }; |
59 | struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 1}, |
60 | {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1} |
61 | }; |
62 | |
63 | // this device needs a STOP between the register and data |
64 | if (state->config->stop_during_read) { |
65 | if ((ret = i2c_transfer(adap: state->i2c, msgs: &msg[0], num: 1)) != 1) { |
66 | dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n" , __func__, reg, ret); |
67 | return -1; |
68 | } |
69 | if ((ret = i2c_transfer(adap: state->i2c, msgs: &msg[1], num: 1)) != 1) { |
70 | dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n" , __func__, reg, ret); |
71 | return -1; |
72 | } |
73 | } else { |
74 | if ((ret = i2c_transfer(adap: state->i2c, msgs: msg, num: 2)) != 2) { |
75 | dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n" , __func__, reg, ret); |
76 | return -1; |
77 | } |
78 | } |
79 | |
80 | return b1[0]; |
81 | } |
82 | |
83 | static int stv0297_writereg_mask(struct stv0297_state *state, u8 reg, u8 mask, u8 data) |
84 | { |
85 | int val; |
86 | |
87 | val = stv0297_readreg(state, reg); |
88 | val &= ~mask; |
89 | val |= (data & mask); |
90 | stv0297_writereg(state, reg, data: val); |
91 | |
92 | return 0; |
93 | } |
94 | |
95 | static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len) |
96 | { |
97 | int ret; |
98 | struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = |
99 | ®1,.len = 1}, |
100 | {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b,.len = len} |
101 | }; |
102 | |
103 | // this device needs a STOP between the register and data |
104 | if (state->config->stop_during_read) { |
105 | if ((ret = i2c_transfer(adap: state->i2c, msgs: &msg[0], num: 1)) != 1) { |
106 | dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n" , __func__, reg1, ret); |
107 | return -1; |
108 | } |
109 | if ((ret = i2c_transfer(adap: state->i2c, msgs: &msg[1], num: 1)) != 1) { |
110 | dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n" , __func__, reg1, ret); |
111 | return -1; |
112 | } |
113 | } else { |
114 | if ((ret = i2c_transfer(adap: state->i2c, msgs: msg, num: 2)) != 2) { |
115 | dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n" , __func__, reg1, ret); |
116 | return -1; |
117 | } |
118 | } |
119 | |
120 | return 0; |
121 | } |
122 | |
123 | static u32 stv0297_get_symbolrate(struct stv0297_state *state) |
124 | { |
125 | u64 tmp; |
126 | |
127 | tmp = (u64)(stv0297_readreg(state, reg: 0x55) |
128 | | (stv0297_readreg(state, reg: 0x56) << 8) |
129 | | (stv0297_readreg(state, reg: 0x57) << 16) |
130 | | (stv0297_readreg(state, reg: 0x58) << 24)); |
131 | |
132 | tmp *= STV0297_CLOCK_KHZ; |
133 | tmp >>= 32; |
134 | |
135 | return (u32) tmp; |
136 | } |
137 | |
138 | static void stv0297_set_symbolrate(struct stv0297_state *state, u32 srate) |
139 | { |
140 | long tmp; |
141 | |
142 | tmp = 131072L * srate; /* 131072 = 2^17 */ |
143 | tmp = tmp / (STV0297_CLOCK_KHZ / 4); /* 1/4 = 2^-2 */ |
144 | tmp = tmp * 8192L; /* 8192 = 2^13 */ |
145 | |
146 | stv0297_writereg(state, reg: 0x55, data: (unsigned char) (tmp & 0xFF)); |
147 | stv0297_writereg(state, reg: 0x56, data: (unsigned char) (tmp >> 8)); |
148 | stv0297_writereg(state, reg: 0x57, data: (unsigned char) (tmp >> 16)); |
149 | stv0297_writereg(state, reg: 0x58, data: (unsigned char) (tmp >> 24)); |
150 | } |
151 | |
152 | static void stv0297_set_sweeprate(struct stv0297_state *state, short fshift, long symrate) |
153 | { |
154 | long tmp; |
155 | |
156 | tmp = (long) fshift *262144L; /* 262144 = 2*18 */ |
157 | tmp /= symrate; |
158 | tmp *= 1024; /* 1024 = 2*10 */ |
159 | |
160 | // adjust |
161 | if (tmp >= 0) { |
162 | tmp += 500000; |
163 | } else { |
164 | tmp -= 500000; |
165 | } |
166 | tmp /= 1000000; |
167 | |
168 | stv0297_writereg(state, reg: 0x60, data: tmp & 0xFF); |
169 | stv0297_writereg_mask(state, reg: 0x69, mask: 0xF0, data: (tmp >> 4) & 0xf0); |
170 | } |
171 | |
172 | static void stv0297_set_carrieroffset(struct stv0297_state *state, long offset) |
173 | { |
174 | long tmp; |
175 | |
176 | /* symrate is hardcoded to 10000 */ |
177 | tmp = offset * 26844L; /* (2**28)/10000 */ |
178 | if (tmp < 0) |
179 | tmp += 0x10000000; |
180 | tmp &= 0x0FFFFFFF; |
181 | |
182 | stv0297_writereg(state, reg: 0x66, data: (unsigned char) (tmp & 0xFF)); |
183 | stv0297_writereg(state, reg: 0x67, data: (unsigned char) (tmp >> 8)); |
184 | stv0297_writereg(state, reg: 0x68, data: (unsigned char) (tmp >> 16)); |
185 | stv0297_writereg_mask(state, reg: 0x69, mask: 0x0F, data: (tmp >> 24) & 0x0f); |
186 | } |
187 | |
188 | /* |
189 | static long stv0297_get_carrieroffset(struct stv0297_state *state) |
190 | { |
191 | s64 tmp; |
192 | |
193 | stv0297_writereg(state, 0x6B, 0x00); |
194 | |
195 | tmp = stv0297_readreg(state, 0x66); |
196 | tmp |= (stv0297_readreg(state, 0x67) << 8); |
197 | tmp |= (stv0297_readreg(state, 0x68) << 16); |
198 | tmp |= (stv0297_readreg(state, 0x69) & 0x0F) << 24; |
199 | |
200 | tmp *= stv0297_get_symbolrate(state); |
201 | tmp >>= 28; |
202 | |
203 | return (s32) tmp; |
204 | } |
205 | */ |
206 | |
207 | static void stv0297_set_initialdemodfreq(struct stv0297_state *state, long freq) |
208 | { |
209 | s32 tmp; |
210 | |
211 | if (freq > 10000) |
212 | freq -= STV0297_CLOCK_KHZ; |
213 | |
214 | tmp = (STV0297_CLOCK_KHZ * 1000) / (1 << 16); |
215 | tmp = (freq * 1000) / tmp; |
216 | if (tmp > 0xffff) |
217 | tmp = 0xffff; |
218 | |
219 | stv0297_writereg_mask(state, reg: 0x25, mask: 0x80, data: 0x80); |
220 | stv0297_writereg(state, reg: 0x21, data: tmp >> 8); |
221 | stv0297_writereg(state, reg: 0x20, data: tmp); |
222 | } |
223 | |
224 | static int stv0297_set_qam(struct stv0297_state *state, |
225 | enum fe_modulation modulation) |
226 | { |
227 | int val = 0; |
228 | |
229 | switch (modulation) { |
230 | case QAM_16: |
231 | val = 0; |
232 | break; |
233 | |
234 | case QAM_32: |
235 | val = 1; |
236 | break; |
237 | |
238 | case QAM_64: |
239 | val = 4; |
240 | break; |
241 | |
242 | case QAM_128: |
243 | val = 2; |
244 | break; |
245 | |
246 | case QAM_256: |
247 | val = 3; |
248 | break; |
249 | |
250 | default: |
251 | return -EINVAL; |
252 | } |
253 | |
254 | stv0297_writereg_mask(state, reg: 0x00, mask: 0x70, data: val << 4); |
255 | |
256 | return 0; |
257 | } |
258 | |
259 | static int stv0297_set_inversion(struct stv0297_state *state, |
260 | enum fe_spectral_inversion inversion) |
261 | { |
262 | int val = 0; |
263 | |
264 | switch (inversion) { |
265 | case INVERSION_OFF: |
266 | val = 0; |
267 | break; |
268 | |
269 | case INVERSION_ON: |
270 | val = 1; |
271 | break; |
272 | |
273 | default: |
274 | return -EINVAL; |
275 | } |
276 | |
277 | stv0297_writereg_mask(state, reg: 0x83, mask: 0x08, data: val << 3); |
278 | |
279 | return 0; |
280 | } |
281 | |
282 | static int stv0297_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) |
283 | { |
284 | struct stv0297_state *state = fe->demodulator_priv; |
285 | |
286 | if (enable) { |
287 | stv0297_writereg(state, reg: 0x87, data: 0x78); |
288 | stv0297_writereg(state, reg: 0x86, data: 0xc8); |
289 | } |
290 | |
291 | return 0; |
292 | } |
293 | |
294 | static int stv0297_init(struct dvb_frontend *fe) |
295 | { |
296 | struct stv0297_state *state = fe->demodulator_priv; |
297 | int i; |
298 | |
299 | /* load init table */ |
300 | for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2) |
301 | stv0297_writereg(state, reg: state->config->inittab[i], data: state->config->inittab[i+1]); |
302 | msleep(msecs: 200); |
303 | |
304 | state->last_ber = 0; |
305 | |
306 | return 0; |
307 | } |
308 | |
309 | static int stv0297_sleep(struct dvb_frontend *fe) |
310 | { |
311 | struct stv0297_state *state = fe->demodulator_priv; |
312 | |
313 | stv0297_writereg_mask(state, reg: 0x80, mask: 1, data: 1); |
314 | |
315 | return 0; |
316 | } |
317 | |
318 | static int stv0297_read_status(struct dvb_frontend *fe, |
319 | enum fe_status *status) |
320 | { |
321 | struct stv0297_state *state = fe->demodulator_priv; |
322 | |
323 | u8 sync = stv0297_readreg(state, reg: 0xDF); |
324 | |
325 | *status = 0; |
326 | if (sync & 0x80) |
327 | *status |= |
328 | FE_HAS_SYNC | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK; |
329 | return 0; |
330 | } |
331 | |
332 | static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber) |
333 | { |
334 | struct stv0297_state *state = fe->demodulator_priv; |
335 | u8 BER[3]; |
336 | |
337 | stv0297_readregs(state, reg1: 0xA0, b: BER, len: 3); |
338 | if (!(BER[0] & 0x80)) { |
339 | state->last_ber = BER[2] << 8 | BER[1]; |
340 | stv0297_writereg_mask(state, reg: 0xA0, mask: 0x80, data: 0x80); |
341 | } |
342 | |
343 | *ber = state->last_ber; |
344 | |
345 | return 0; |
346 | } |
347 | |
348 | |
349 | static int stv0297_read_signal_strength(struct dvb_frontend *fe, u16 * strength) |
350 | { |
351 | struct stv0297_state *state = fe->demodulator_priv; |
352 | u8 STRENGTH[3]; |
353 | u16 tmp; |
354 | |
355 | stv0297_readregs(state, reg1: 0x41, b: STRENGTH, len: 3); |
356 | tmp = (STRENGTH[1] & 0x03) << 8 | STRENGTH[0]; |
357 | if (STRENGTH[2] & 0x20) { |
358 | if (tmp < 0x200) |
359 | tmp = 0; |
360 | else |
361 | tmp = tmp - 0x200; |
362 | } else { |
363 | if (tmp > 0x1ff) |
364 | tmp = 0; |
365 | else |
366 | tmp = 0x1ff - tmp; |
367 | } |
368 | *strength = (tmp << 7) | (tmp >> 2); |
369 | return 0; |
370 | } |
371 | |
372 | static int stv0297_read_snr(struct dvb_frontend *fe, u16 * snr) |
373 | { |
374 | struct stv0297_state *state = fe->demodulator_priv; |
375 | u8 SNR[2]; |
376 | |
377 | stv0297_readregs(state, reg1: 0x07, b: SNR, len: 2); |
378 | *snr = SNR[1] << 8 | SNR[0]; |
379 | |
380 | return 0; |
381 | } |
382 | |
383 | static int stv0297_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) |
384 | { |
385 | struct stv0297_state *state = fe->demodulator_priv; |
386 | |
387 | stv0297_writereg_mask(state, reg: 0xDF, mask: 0x03, data: 0x03); /* freeze the counters */ |
388 | |
389 | *ucblocks = (stv0297_readreg(state, reg: 0xD5) << 8) |
390 | | stv0297_readreg(state, reg: 0xD4); |
391 | |
392 | stv0297_writereg_mask(state, reg: 0xDF, mask: 0x03, data: 0x02); /* clear the counters */ |
393 | stv0297_writereg_mask(state, reg: 0xDF, mask: 0x03, data: 0x01); /* re-enable the counters */ |
394 | |
395 | return 0; |
396 | } |
397 | |
398 | static int stv0297_set_frontend(struct dvb_frontend *fe) |
399 | { |
400 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
401 | struct stv0297_state *state = fe->demodulator_priv; |
402 | int u_threshold; |
403 | int initial_u; |
404 | int blind_u; |
405 | int delay; |
406 | int sweeprate; |
407 | int carrieroffset; |
408 | unsigned long timeout; |
409 | enum fe_spectral_inversion inversion; |
410 | |
411 | switch (p->modulation) { |
412 | case QAM_16: |
413 | case QAM_32: |
414 | case QAM_64: |
415 | delay = 100; |
416 | sweeprate = 1000; |
417 | break; |
418 | |
419 | case QAM_128: |
420 | case QAM_256: |
421 | delay = 200; |
422 | sweeprate = 500; |
423 | break; |
424 | |
425 | default: |
426 | return -EINVAL; |
427 | } |
428 | |
429 | // determine inversion dependent parameters |
430 | inversion = p->inversion; |
431 | if (state->config->invert) |
432 | inversion = (inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON; |
433 | carrieroffset = -330; |
434 | switch (inversion) { |
435 | case INVERSION_OFF: |
436 | break; |
437 | |
438 | case INVERSION_ON: |
439 | sweeprate = -sweeprate; |
440 | carrieroffset = -carrieroffset; |
441 | break; |
442 | |
443 | default: |
444 | return -EINVAL; |
445 | } |
446 | |
447 | stv0297_init(fe); |
448 | if (fe->ops.tuner_ops.set_params) { |
449 | fe->ops.tuner_ops.set_params(fe); |
450 | if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); |
451 | } |
452 | |
453 | /* clear software interrupts */ |
454 | stv0297_writereg(state, reg: 0x82, data: 0x0); |
455 | |
456 | /* set initial demodulation frequency */ |
457 | stv0297_set_initialdemodfreq(state, freq: 7250); |
458 | |
459 | /* setup AGC */ |
460 | stv0297_writereg_mask(state, reg: 0x43, mask: 0x10, data: 0x00); |
461 | stv0297_writereg(state, reg: 0x41, data: 0x00); |
462 | stv0297_writereg_mask(state, reg: 0x42, mask: 0x03, data: 0x01); |
463 | stv0297_writereg_mask(state, reg: 0x36, mask: 0x60, data: 0x00); |
464 | stv0297_writereg_mask(state, reg: 0x36, mask: 0x18, data: 0x00); |
465 | stv0297_writereg_mask(state, reg: 0x71, mask: 0x80, data: 0x80); |
466 | stv0297_writereg(state, reg: 0x72, data: 0x00); |
467 | stv0297_writereg(state, reg: 0x73, data: 0x00); |
468 | stv0297_writereg_mask(state, reg: 0x74, mask: 0x0F, data: 0x00); |
469 | stv0297_writereg_mask(state, reg: 0x43, mask: 0x08, data: 0x00); |
470 | stv0297_writereg_mask(state, reg: 0x71, mask: 0x80, data: 0x00); |
471 | |
472 | /* setup STL */ |
473 | stv0297_writereg_mask(state, reg: 0x5a, mask: 0x20, data: 0x20); |
474 | stv0297_writereg_mask(state, reg: 0x5b, mask: 0x02, data: 0x02); |
475 | stv0297_writereg_mask(state, reg: 0x5b, mask: 0x02, data: 0x00); |
476 | stv0297_writereg_mask(state, reg: 0x5b, mask: 0x01, data: 0x00); |
477 | stv0297_writereg_mask(state, reg: 0x5a, mask: 0x40, data: 0x40); |
478 | |
479 | /* disable frequency sweep */ |
480 | stv0297_writereg_mask(state, reg: 0x6a, mask: 0x01, data: 0x00); |
481 | |
482 | /* reset deinterleaver */ |
483 | stv0297_writereg_mask(state, reg: 0x81, mask: 0x01, data: 0x01); |
484 | stv0297_writereg_mask(state, reg: 0x81, mask: 0x01, data: 0x00); |
485 | |
486 | /* ??? */ |
487 | stv0297_writereg_mask(state, reg: 0x83, mask: 0x20, data: 0x20); |
488 | stv0297_writereg_mask(state, reg: 0x83, mask: 0x20, data: 0x00); |
489 | |
490 | /* reset equaliser */ |
491 | u_threshold = stv0297_readreg(state, reg: 0x00) & 0xf; |
492 | initial_u = stv0297_readreg(state, reg: 0x01) >> 4; |
493 | blind_u = stv0297_readreg(state, reg: 0x01) & 0xf; |
494 | stv0297_writereg_mask(state, reg: 0x84, mask: 0x01, data: 0x01); |
495 | stv0297_writereg_mask(state, reg: 0x84, mask: 0x01, data: 0x00); |
496 | stv0297_writereg_mask(state, reg: 0x00, mask: 0x0f, data: u_threshold); |
497 | stv0297_writereg_mask(state, reg: 0x01, mask: 0xf0, data: initial_u << 4); |
498 | stv0297_writereg_mask(state, reg: 0x01, mask: 0x0f, data: blind_u); |
499 | |
500 | /* data comes from internal A/D */ |
501 | stv0297_writereg_mask(state, reg: 0x87, mask: 0x80, data: 0x00); |
502 | |
503 | /* clear phase registers */ |
504 | stv0297_writereg(state, reg: 0x63, data: 0x00); |
505 | stv0297_writereg(state, reg: 0x64, data: 0x00); |
506 | stv0297_writereg(state, reg: 0x65, data: 0x00); |
507 | stv0297_writereg(state, reg: 0x66, data: 0x00); |
508 | stv0297_writereg(state, reg: 0x67, data: 0x00); |
509 | stv0297_writereg(state, reg: 0x68, data: 0x00); |
510 | stv0297_writereg_mask(state, reg: 0x69, mask: 0x0f, data: 0x00); |
511 | |
512 | /* set parameters */ |
513 | stv0297_set_qam(state, modulation: p->modulation); |
514 | stv0297_set_symbolrate(state, srate: p->symbol_rate / 1000); |
515 | stv0297_set_sweeprate(state, fshift: sweeprate, symrate: p->symbol_rate / 1000); |
516 | stv0297_set_carrieroffset(state, offset: carrieroffset); |
517 | stv0297_set_inversion(state, inversion); |
518 | |
519 | /* kick off lock */ |
520 | /* Disable corner detection for higher QAMs */ |
521 | if (p->modulation == QAM_128 || |
522 | p->modulation == QAM_256) |
523 | stv0297_writereg_mask(state, reg: 0x88, mask: 0x08, data: 0x00); |
524 | else |
525 | stv0297_writereg_mask(state, reg: 0x88, mask: 0x08, data: 0x08); |
526 | |
527 | stv0297_writereg_mask(state, reg: 0x5a, mask: 0x20, data: 0x00); |
528 | stv0297_writereg_mask(state, reg: 0x6a, mask: 0x01, data: 0x01); |
529 | stv0297_writereg_mask(state, reg: 0x43, mask: 0x40, data: 0x40); |
530 | stv0297_writereg_mask(state, reg: 0x5b, mask: 0x30, data: 0x00); |
531 | stv0297_writereg_mask(state, reg: 0x03, mask: 0x0c, data: 0x0c); |
532 | stv0297_writereg_mask(state, reg: 0x03, mask: 0x03, data: 0x03); |
533 | stv0297_writereg_mask(state, reg: 0x43, mask: 0x10, data: 0x10); |
534 | |
535 | /* wait for WGAGC lock */ |
536 | timeout = jiffies + msecs_to_jiffies(m: 2000); |
537 | while (time_before(jiffies, timeout)) { |
538 | msleep(msecs: 10); |
539 | if (stv0297_readreg(state, reg: 0x43) & 0x08) |
540 | break; |
541 | } |
542 | if (time_after(jiffies, timeout)) { |
543 | goto timeout; |
544 | } |
545 | msleep(msecs: 20); |
546 | |
547 | /* wait for equaliser partial convergence */ |
548 | timeout = jiffies + msecs_to_jiffies(m: 500); |
549 | while (time_before(jiffies, timeout)) { |
550 | msleep(msecs: 10); |
551 | |
552 | if (stv0297_readreg(state, reg: 0x82) & 0x04) { |
553 | break; |
554 | } |
555 | } |
556 | if (time_after(jiffies, timeout)) { |
557 | goto timeout; |
558 | } |
559 | |
560 | /* wait for equaliser full convergence */ |
561 | timeout = jiffies + msecs_to_jiffies(m: delay); |
562 | while (time_before(jiffies, timeout)) { |
563 | msleep(msecs: 10); |
564 | |
565 | if (stv0297_readreg(state, reg: 0x82) & 0x08) { |
566 | break; |
567 | } |
568 | } |
569 | if (time_after(jiffies, timeout)) { |
570 | goto timeout; |
571 | } |
572 | |
573 | /* disable sweep */ |
574 | stv0297_writereg_mask(state, reg: 0x6a, mask: 1, data: 0); |
575 | stv0297_writereg_mask(state, reg: 0x88, mask: 8, data: 0); |
576 | |
577 | /* wait for main lock */ |
578 | timeout = jiffies + msecs_to_jiffies(m: 20); |
579 | while (time_before(jiffies, timeout)) { |
580 | msleep(msecs: 10); |
581 | |
582 | if (stv0297_readreg(state, reg: 0xDF) & 0x80) { |
583 | break; |
584 | } |
585 | } |
586 | if (time_after(jiffies, timeout)) { |
587 | goto timeout; |
588 | } |
589 | msleep(msecs: 100); |
590 | |
591 | /* is it still locked after that delay? */ |
592 | if (!(stv0297_readreg(state, reg: 0xDF) & 0x80)) { |
593 | goto timeout; |
594 | } |
595 | |
596 | /* success!! */ |
597 | stv0297_writereg_mask(state, reg: 0x5a, mask: 0x40, data: 0x00); |
598 | state->base_freq = p->frequency; |
599 | return 0; |
600 | |
601 | timeout: |
602 | stv0297_writereg_mask(state, reg: 0x6a, mask: 0x01, data: 0x00); |
603 | return 0; |
604 | } |
605 | |
606 | static int stv0297_get_frontend(struct dvb_frontend *fe, |
607 | struct dtv_frontend_properties *p) |
608 | { |
609 | struct stv0297_state *state = fe->demodulator_priv; |
610 | int reg_00, reg_83; |
611 | |
612 | reg_00 = stv0297_readreg(state, reg: 0x00); |
613 | reg_83 = stv0297_readreg(state, reg: 0x83); |
614 | |
615 | p->frequency = state->base_freq; |
616 | p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF; |
617 | if (state->config->invert) |
618 | p->inversion = (p->inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON; |
619 | p->symbol_rate = stv0297_get_symbolrate(state) * 1000; |
620 | p->fec_inner = FEC_NONE; |
621 | |
622 | switch ((reg_00 >> 4) & 0x7) { |
623 | case 0: |
624 | p->modulation = QAM_16; |
625 | break; |
626 | case 1: |
627 | p->modulation = QAM_32; |
628 | break; |
629 | case 2: |
630 | p->modulation = QAM_128; |
631 | break; |
632 | case 3: |
633 | p->modulation = QAM_256; |
634 | break; |
635 | case 4: |
636 | p->modulation = QAM_64; |
637 | break; |
638 | } |
639 | |
640 | return 0; |
641 | } |
642 | |
643 | static void stv0297_release(struct dvb_frontend *fe) |
644 | { |
645 | struct stv0297_state *state = fe->demodulator_priv; |
646 | kfree(objp: state); |
647 | } |
648 | |
649 | static const struct dvb_frontend_ops stv0297_ops; |
650 | |
651 | struct dvb_frontend *stv0297_attach(const struct stv0297_config *config, |
652 | struct i2c_adapter *i2c) |
653 | { |
654 | struct stv0297_state *state = NULL; |
655 | |
656 | /* allocate memory for the internal state */ |
657 | state = kzalloc(size: sizeof(struct stv0297_state), GFP_KERNEL); |
658 | if (state == NULL) |
659 | goto error; |
660 | |
661 | /* setup the state */ |
662 | state->config = config; |
663 | state->i2c = i2c; |
664 | state->last_ber = 0; |
665 | state->base_freq = 0; |
666 | |
667 | /* check if the demod is there */ |
668 | if ((stv0297_readreg(state, reg: 0x80) & 0x70) != 0x20) |
669 | goto error; |
670 | |
671 | /* create dvb_frontend */ |
672 | memcpy(&state->frontend.ops, &stv0297_ops, sizeof(struct dvb_frontend_ops)); |
673 | state->frontend.demodulator_priv = state; |
674 | return &state->frontend; |
675 | |
676 | error: |
677 | kfree(objp: state); |
678 | return NULL; |
679 | } |
680 | |
681 | static const struct dvb_frontend_ops stv0297_ops = { |
682 | .delsys = { SYS_DVBC_ANNEX_A }, |
683 | .info = { |
684 | .name = "ST STV0297 DVB-C" , |
685 | .frequency_min_hz = 47 * MHz, |
686 | .frequency_max_hz = 862 * MHz, |
687 | .frequency_stepsize_hz = 62500, |
688 | .symbol_rate_min = 870000, |
689 | .symbol_rate_max = 11700000, |
690 | .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | |
691 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO}, |
692 | |
693 | .release = stv0297_release, |
694 | |
695 | .init = stv0297_init, |
696 | .sleep = stv0297_sleep, |
697 | .i2c_gate_ctrl = stv0297_i2c_gate_ctrl, |
698 | |
699 | .set_frontend = stv0297_set_frontend, |
700 | .get_frontend = stv0297_get_frontend, |
701 | |
702 | .read_status = stv0297_read_status, |
703 | .read_ber = stv0297_read_ber, |
704 | .read_signal_strength = stv0297_read_signal_strength, |
705 | .read_snr = stv0297_read_snr, |
706 | .read_ucblocks = stv0297_read_ucblocks, |
707 | }; |
708 | |
709 | MODULE_DESCRIPTION("ST STV0297 DVB-C Demodulator driver" ); |
710 | MODULE_AUTHOR("Dennis Noermann and Andrew de Quincey" ); |
711 | MODULE_LICENSE("GPL" ); |
712 | |
713 | EXPORT_SYMBOL_GPL(stv0297_attach); |
714 | |