1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder |
4 | |
5 | Copyright (C) 2003 Andreas Oberritter <obi@linuxtv.org> |
6 | Copyright (C) 2008 Matthias Schwarzott <zzam@gentoo.org> |
7 | |
8 | |
9 | References: |
10 | http://products.zarlink.com/product_profiles/MT312.htm |
11 | http://products.zarlink.com/product_profiles/SL1935.htm |
12 | */ |
13 | |
14 | #include <linux/delay.h> |
15 | #include <linux/errno.h> |
16 | #include <linux/init.h> |
17 | #include <linux/kernel.h> |
18 | #include <linux/module.h> |
19 | #include <linux/string.h> |
20 | #include <linux/slab.h> |
21 | |
22 | #include <media/dvb_frontend.h> |
23 | #include "mt312_priv.h" |
24 | #include "mt312.h" |
25 | |
26 | /* Max transfer size done by I2C transfer functions */ |
27 | #define MAX_XFER_SIZE 64 |
28 | |
29 | struct mt312_state { |
30 | struct i2c_adapter *i2c; |
31 | /* configuration settings */ |
32 | const struct mt312_config *config; |
33 | struct dvb_frontend frontend; |
34 | |
35 | u8 id; |
36 | unsigned long xtal; |
37 | u8 freq_mult; |
38 | }; |
39 | |
40 | static int debug; |
41 | #define dprintk(args...) \ |
42 | do { \ |
43 | if (debug) \ |
44 | printk(KERN_DEBUG "mt312: " args); \ |
45 | } while (0) |
46 | |
47 | #define MT312_PLL_CLK 10000000UL /* 10 MHz */ |
48 | #define MT312_PLL_CLK_10_111 10111000UL /* 10.111 MHz */ |
49 | |
50 | static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, |
51 | u8 *buf, const size_t count) |
52 | { |
53 | int ret; |
54 | struct i2c_msg msg[2]; |
55 | u8 regbuf[1] = { reg }; |
56 | |
57 | msg[0].addr = state->config->demod_address; |
58 | msg[0].flags = 0; |
59 | msg[0].buf = regbuf; |
60 | msg[0].len = 1; |
61 | msg[1].addr = state->config->demod_address; |
62 | msg[1].flags = I2C_M_RD; |
63 | msg[1].buf = buf; |
64 | msg[1].len = count; |
65 | |
66 | ret = i2c_transfer(adap: state->i2c, msgs: msg, num: 2); |
67 | |
68 | if (ret != 2) { |
69 | printk(KERN_DEBUG "%s: ret == %d\n" , __func__, ret); |
70 | return -EREMOTEIO; |
71 | } |
72 | |
73 | if (debug) { |
74 | int i; |
75 | dprintk("R(%d):" , reg & 0x7f); |
76 | for (i = 0; i < count; i++) |
77 | printk(KERN_CONT " %02x" , buf[i]); |
78 | printk("\n" ); |
79 | } |
80 | |
81 | return 0; |
82 | } |
83 | |
84 | static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg, |
85 | const u8 *src, const size_t count) |
86 | { |
87 | int ret; |
88 | u8 buf[MAX_XFER_SIZE]; |
89 | struct i2c_msg msg; |
90 | |
91 | if (1 + count > sizeof(buf)) { |
92 | printk(KERN_WARNING |
93 | "mt312: write: len=%zu is too big!\n" , count); |
94 | return -EINVAL; |
95 | } |
96 | |
97 | if (debug) { |
98 | int i; |
99 | dprintk("W(%d):" , reg & 0x7f); |
100 | for (i = 0; i < count; i++) |
101 | printk(KERN_CONT " %02x" , src[i]); |
102 | printk("\n" ); |
103 | } |
104 | |
105 | buf[0] = reg; |
106 | memcpy(&buf[1], src, count); |
107 | |
108 | msg.addr = state->config->demod_address; |
109 | msg.flags = 0; |
110 | msg.buf = buf; |
111 | msg.len = count + 1; |
112 | |
113 | ret = i2c_transfer(adap: state->i2c, msgs: &msg, num: 1); |
114 | |
115 | if (ret != 1) { |
116 | dprintk("%s: ret == %d\n" , __func__, ret); |
117 | return -EREMOTEIO; |
118 | } |
119 | |
120 | return 0; |
121 | } |
122 | |
123 | static inline int mt312_readreg(struct mt312_state *state, |
124 | const enum mt312_reg_addr reg, u8 *val) |
125 | { |
126 | return mt312_read(state, reg, buf: val, count: 1); |
127 | } |
128 | |
129 | static inline int mt312_writereg(struct mt312_state *state, |
130 | const enum mt312_reg_addr reg, const u8 val) |
131 | { |
132 | u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ |
133 | |
134 | |
135 | return mt312_write(state, reg, src: &tmp, count: 1); |
136 | } |
137 | |
138 | static int mt312_reset(struct mt312_state *state, const u8 full) |
139 | { |
140 | return mt312_writereg(state, reg: RESET, val: full ? 0x80 : 0x40); |
141 | } |
142 | |
143 | static int mt312_get_inversion(struct mt312_state *state, |
144 | enum fe_spectral_inversion *i) |
145 | { |
146 | int ret; |
147 | u8 vit_mode; |
148 | |
149 | ret = mt312_readreg(state, reg: VIT_MODE, val: &vit_mode); |
150 | if (ret < 0) |
151 | return ret; |
152 | |
153 | if (vit_mode & 0x80) /* auto inversion was used */ |
154 | *i = (vit_mode & 0x40) ? INVERSION_ON : INVERSION_OFF; |
155 | |
156 | return 0; |
157 | } |
158 | |
159 | static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr) |
160 | { |
161 | int ret; |
162 | u8 sym_rate_h; |
163 | u8 dec_ratio; |
164 | u16 sym_rat_op; |
165 | u16 monitor; |
166 | u8 buf[2]; |
167 | |
168 | ret = mt312_readreg(state, reg: SYM_RATE_H, val: &sym_rate_h); |
169 | if (ret < 0) |
170 | return ret; |
171 | |
172 | if (sym_rate_h & 0x80) { |
173 | /* symbol rate search was used */ |
174 | ret = mt312_writereg(state, reg: MON_CTRL, val: 0x03); |
175 | if (ret < 0) |
176 | return ret; |
177 | |
178 | ret = mt312_read(state, reg: MONITOR_H, buf, count: sizeof(buf)); |
179 | if (ret < 0) |
180 | return ret; |
181 | |
182 | monitor = (buf[0] << 8) | buf[1]; |
183 | |
184 | dprintk("sr(auto) = %u\n" , |
185 | DIV_ROUND_CLOSEST(monitor * 15625, 4)); |
186 | } else { |
187 | ret = mt312_writereg(state, reg: MON_CTRL, val: 0x05); |
188 | if (ret < 0) |
189 | return ret; |
190 | |
191 | ret = mt312_read(state, reg: MONITOR_H, buf, count: sizeof(buf)); |
192 | if (ret < 0) |
193 | return ret; |
194 | |
195 | dec_ratio = ((buf[0] >> 5) & 0x07) * 32; |
196 | |
197 | ret = mt312_read(state, reg: SYM_RAT_OP_H, buf, count: sizeof(buf)); |
198 | if (ret < 0) |
199 | return ret; |
200 | |
201 | sym_rat_op = (buf[0] << 8) | buf[1]; |
202 | |
203 | dprintk("sym_rat_op=%d dec_ratio=%d\n" , |
204 | sym_rat_op, dec_ratio); |
205 | dprintk("*sr(manual) = %lu\n" , |
206 | (((state->xtal * 8192) / (sym_rat_op + 8192)) * |
207 | 2) - dec_ratio); |
208 | } |
209 | |
210 | return 0; |
211 | } |
212 | |
213 | static int mt312_get_code_rate(struct mt312_state *state, enum fe_code_rate *cr) |
214 | { |
215 | const enum fe_code_rate fec_tab[8] = |
216 | { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_6_7, FEC_7_8, |
217 | FEC_AUTO, FEC_AUTO }; |
218 | |
219 | int ret; |
220 | u8 fec_status; |
221 | |
222 | ret = mt312_readreg(state, reg: FEC_STATUS, val: &fec_status); |
223 | if (ret < 0) |
224 | return ret; |
225 | |
226 | *cr = fec_tab[(fec_status >> 4) & 0x07]; |
227 | |
228 | return 0; |
229 | } |
230 | |
231 | static int mt312_initfe(struct dvb_frontend *fe) |
232 | { |
233 | struct mt312_state *state = fe->demodulator_priv; |
234 | int ret; |
235 | u8 buf[2]; |
236 | |
237 | /* wake up */ |
238 | ret = mt312_writereg(state, reg: CONFIG, |
239 | val: (state->freq_mult == 6 ? 0x88 : 0x8c)); |
240 | if (ret < 0) |
241 | return ret; |
242 | |
243 | /* wait at least 150 usec */ |
244 | udelay(150); |
245 | |
246 | /* full reset */ |
247 | ret = mt312_reset(state, full: 1); |
248 | if (ret < 0) |
249 | return ret; |
250 | |
251 | /* Per datasheet, write correct values. 09/28/03 ACCJr. |
252 | * If we don't do this, we won't get FE_HAS_VITERBI in the VP310. */ |
253 | { |
254 | u8 buf_def[8] = { 0x14, 0x12, 0x03, 0x02, |
255 | 0x01, 0x00, 0x00, 0x00 }; |
256 | |
257 | ret = mt312_write(state, reg: VIT_SETUP, src: buf_def, count: sizeof(buf_def)); |
258 | if (ret < 0) |
259 | return ret; |
260 | } |
261 | |
262 | switch (state->id) { |
263 | case ID_ZL10313: |
264 | /* enable ADC */ |
265 | ret = mt312_writereg(state, reg: GPP_CTRL, val: 0x80); |
266 | if (ret < 0) |
267 | return ret; |
268 | |
269 | /* configure ZL10313 for optimal ADC performance */ |
270 | buf[0] = 0x80; |
271 | buf[1] = 0xB0; |
272 | ret = mt312_write(state, reg: HW_CTRL, src: buf, count: 2); |
273 | if (ret < 0) |
274 | return ret; |
275 | |
276 | /* enable MPEG output and ADCs */ |
277 | ret = mt312_writereg(state, reg: HW_CTRL, val: 0x00); |
278 | if (ret < 0) |
279 | return ret; |
280 | |
281 | ret = mt312_writereg(state, reg: MPEG_CTRL, val: 0x00); |
282 | if (ret < 0) |
283 | return ret; |
284 | |
285 | break; |
286 | } |
287 | |
288 | /* SYS_CLK */ |
289 | buf[0] = DIV_ROUND_CLOSEST(state->xtal * state->freq_mult * 2, 1000000); |
290 | |
291 | /* DISEQC_RATIO */ |
292 | buf[1] = DIV_ROUND_CLOSEST(state->xtal, 22000 * 4); |
293 | |
294 | ret = mt312_write(state, reg: SYS_CLK, src: buf, count: sizeof(buf)); |
295 | if (ret < 0) |
296 | return ret; |
297 | |
298 | ret = mt312_writereg(state, reg: SNR_THS_HIGH, val: 0x32); |
299 | if (ret < 0) |
300 | return ret; |
301 | |
302 | /* different MOCLK polarity */ |
303 | switch (state->id) { |
304 | case ID_ZL10313: |
305 | buf[0] = 0x33; |
306 | break; |
307 | default: |
308 | buf[0] = 0x53; |
309 | break; |
310 | } |
311 | |
312 | ret = mt312_writereg(state, reg: OP_CTRL, val: buf[0]); |
313 | if (ret < 0) |
314 | return ret; |
315 | |
316 | /* TS_SW_LIM */ |
317 | buf[0] = 0x8c; |
318 | buf[1] = 0x98; |
319 | |
320 | ret = mt312_write(state, reg: TS_SW_LIM_L, src: buf, count: sizeof(buf)); |
321 | if (ret < 0) |
322 | return ret; |
323 | |
324 | ret = mt312_writereg(state, reg: CS_SW_LIM, val: 0x69); |
325 | if (ret < 0) |
326 | return ret; |
327 | |
328 | return 0; |
329 | } |
330 | |
331 | static int mt312_send_master_cmd(struct dvb_frontend *fe, |
332 | struct dvb_diseqc_master_cmd *c) |
333 | { |
334 | struct mt312_state *state = fe->demodulator_priv; |
335 | int ret; |
336 | u8 diseqc_mode; |
337 | |
338 | if ((c->msg_len == 0) || (c->msg_len > sizeof(c->msg))) |
339 | return -EINVAL; |
340 | |
341 | ret = mt312_readreg(state, reg: DISEQC_MODE, val: &diseqc_mode); |
342 | if (ret < 0) |
343 | return ret; |
344 | |
345 | ret = mt312_write(state, reg: (0x80 | DISEQC_INSTR), src: c->msg, count: c->msg_len); |
346 | if (ret < 0) |
347 | return ret; |
348 | |
349 | ret = mt312_writereg(state, reg: DISEQC_MODE, |
350 | val: (diseqc_mode & 0x40) | ((c->msg_len - 1) << 3) |
351 | | 0x04); |
352 | if (ret < 0) |
353 | return ret; |
354 | |
355 | /* is there a better way to wait for message to be transmitted */ |
356 | msleep(msecs: 100); |
357 | |
358 | /* set DISEQC_MODE[2:0] to zero if a return message is expected */ |
359 | if (c->msg[0] & 0x02) { |
360 | ret = mt312_writereg(state, reg: DISEQC_MODE, val: (diseqc_mode & 0x40)); |
361 | if (ret < 0) |
362 | return ret; |
363 | } |
364 | |
365 | return 0; |
366 | } |
367 | |
368 | static int mt312_send_burst(struct dvb_frontend *fe, |
369 | const enum fe_sec_mini_cmd c) |
370 | { |
371 | struct mt312_state *state = fe->demodulator_priv; |
372 | const u8 mini_tab[2] = { 0x02, 0x03 }; |
373 | |
374 | int ret; |
375 | u8 diseqc_mode; |
376 | |
377 | if (c > SEC_MINI_B) |
378 | return -EINVAL; |
379 | |
380 | ret = mt312_readreg(state, reg: DISEQC_MODE, val: &diseqc_mode); |
381 | if (ret < 0) |
382 | return ret; |
383 | |
384 | ret = mt312_writereg(state, reg: DISEQC_MODE, |
385 | val: (diseqc_mode & 0x40) | mini_tab[c]); |
386 | if (ret < 0) |
387 | return ret; |
388 | |
389 | return 0; |
390 | } |
391 | |
392 | static int mt312_set_tone(struct dvb_frontend *fe, |
393 | const enum fe_sec_tone_mode t) |
394 | { |
395 | struct mt312_state *state = fe->demodulator_priv; |
396 | const u8 tone_tab[2] = { 0x01, 0x00 }; |
397 | |
398 | int ret; |
399 | u8 diseqc_mode; |
400 | |
401 | if (t > SEC_TONE_OFF) |
402 | return -EINVAL; |
403 | |
404 | ret = mt312_readreg(state, reg: DISEQC_MODE, val: &diseqc_mode); |
405 | if (ret < 0) |
406 | return ret; |
407 | |
408 | ret = mt312_writereg(state, reg: DISEQC_MODE, |
409 | val: (diseqc_mode & 0x40) | tone_tab[t]); |
410 | if (ret < 0) |
411 | return ret; |
412 | |
413 | return 0; |
414 | } |
415 | |
416 | static int mt312_set_voltage(struct dvb_frontend *fe, |
417 | const enum fe_sec_voltage v) |
418 | { |
419 | struct mt312_state *state = fe->demodulator_priv; |
420 | const u8 volt_tab[3] = { 0x00, 0x40, 0x00 }; |
421 | u8 val; |
422 | |
423 | if (v > SEC_VOLTAGE_OFF) |
424 | return -EINVAL; |
425 | |
426 | val = volt_tab[v]; |
427 | if (state->config->voltage_inverted) |
428 | val ^= 0x40; |
429 | |
430 | return mt312_writereg(state, reg: DISEQC_MODE, val); |
431 | } |
432 | |
433 | static int mt312_read_status(struct dvb_frontend *fe, enum fe_status *s) |
434 | { |
435 | struct mt312_state *state = fe->demodulator_priv; |
436 | int ret; |
437 | u8 status[3]; |
438 | |
439 | *s = 0; |
440 | |
441 | ret = mt312_read(state, reg: QPSK_STAT_H, buf: status, count: sizeof(status)); |
442 | if (ret < 0) |
443 | return ret; |
444 | |
445 | dprintk("QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x, FEC_STATUS: 0x%02x\n" , |
446 | status[0], status[1], status[2]); |
447 | |
448 | if (status[0] & 0xc0) |
449 | *s |= FE_HAS_SIGNAL; /* signal noise ratio */ |
450 | if (status[0] & 0x04) |
451 | *s |= FE_HAS_CARRIER; /* qpsk carrier lock */ |
452 | if (status[2] & 0x02) |
453 | *s |= FE_HAS_VITERBI; /* viterbi lock */ |
454 | if (status[2] & 0x04) |
455 | *s |= FE_HAS_SYNC; /* byte align lock */ |
456 | if (status[0] & 0x01) |
457 | *s |= FE_HAS_LOCK; /* qpsk lock */ |
458 | |
459 | return 0; |
460 | } |
461 | |
462 | static int mt312_read_ber(struct dvb_frontend *fe, u32 *ber) |
463 | { |
464 | struct mt312_state *state = fe->demodulator_priv; |
465 | int ret; |
466 | u8 buf[3]; |
467 | |
468 | ret = mt312_read(state, reg: RS_BERCNT_H, buf, count: 3); |
469 | if (ret < 0) |
470 | return ret; |
471 | |
472 | *ber = ((buf[0] << 16) | (buf[1] << 8) | buf[2]) * 64; |
473 | |
474 | return 0; |
475 | } |
476 | |
477 | static int mt312_read_signal_strength(struct dvb_frontend *fe, |
478 | u16 *signal_strength) |
479 | { |
480 | struct mt312_state *state = fe->demodulator_priv; |
481 | int ret; |
482 | u8 buf[3]; |
483 | u16 agc; |
484 | s16 err_db; |
485 | |
486 | ret = mt312_read(state, reg: AGC_H, buf, count: sizeof(buf)); |
487 | if (ret < 0) |
488 | return ret; |
489 | |
490 | agc = (buf[0] << 6) | (buf[1] >> 2); |
491 | err_db = (s16) (((buf[1] & 0x03) << 14) | buf[2] << 6) >> 6; |
492 | |
493 | *signal_strength = agc; |
494 | |
495 | dprintk("agc=%08x err_db=%hd\n" , agc, err_db); |
496 | |
497 | return 0; |
498 | } |
499 | |
500 | static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr) |
501 | { |
502 | struct mt312_state *state = fe->demodulator_priv; |
503 | int ret; |
504 | u8 buf[2]; |
505 | |
506 | ret = mt312_read(state, reg: M_SNR_H, buf, count: sizeof(buf)); |
507 | if (ret < 0) |
508 | return ret; |
509 | |
510 | *snr = 0xFFFF - ((((buf[0] & 0x7f) << 8) | buf[1]) << 1); |
511 | |
512 | return 0; |
513 | } |
514 | |
515 | static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc) |
516 | { |
517 | struct mt312_state *state = fe->demodulator_priv; |
518 | int ret; |
519 | u8 buf[2]; |
520 | |
521 | ret = mt312_read(state, reg: RS_UBC_H, buf, count: sizeof(buf)); |
522 | if (ret < 0) |
523 | return ret; |
524 | |
525 | *ubc = (buf[0] << 8) | buf[1]; |
526 | |
527 | return 0; |
528 | } |
529 | |
530 | static int mt312_set_frontend(struct dvb_frontend *fe) |
531 | { |
532 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
533 | struct mt312_state *state = fe->demodulator_priv; |
534 | int ret; |
535 | u8 buf[5], config_val; |
536 | u16 sr; |
537 | |
538 | const u8 fec_tab[10] = |
539 | { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f }; |
540 | const u8 inv_tab[3] = { 0x00, 0x40, 0x80 }; |
541 | |
542 | dprintk("%s: Freq %d\n" , __func__, p->frequency); |
543 | |
544 | if ((p->frequency < fe->ops.info.frequency_min_hz / kHz) |
545 | || (p->frequency > fe->ops.info.frequency_max_hz / kHz)) |
546 | return -EINVAL; |
547 | |
548 | if (((int)p->inversion < INVERSION_OFF) |
549 | || (p->inversion > INVERSION_ON)) |
550 | return -EINVAL; |
551 | |
552 | if ((p->symbol_rate < fe->ops.info.symbol_rate_min) |
553 | || (p->symbol_rate > fe->ops.info.symbol_rate_max)) |
554 | return -EINVAL; |
555 | |
556 | if (((int)p->fec_inner < FEC_NONE) |
557 | || (p->fec_inner > FEC_AUTO)) |
558 | return -EINVAL; |
559 | |
560 | if ((p->fec_inner == FEC_4_5) |
561 | || (p->fec_inner == FEC_8_9)) |
562 | return -EINVAL; |
563 | |
564 | switch (state->id) { |
565 | case ID_VP310: |
566 | /* For now we will do this only for the VP310. |
567 | * It should be better for the mt312 as well, |
568 | * but tuning will be slower. ACCJr 09/29/03 |
569 | */ |
570 | ret = mt312_readreg(state, reg: CONFIG, val: &config_val); |
571 | if (ret < 0) |
572 | return ret; |
573 | if (p->symbol_rate >= 30000000) { |
574 | /* Note that 30MS/s should use 90MHz */ |
575 | if (state->freq_mult == 6) { |
576 | /* We are running 60MHz */ |
577 | state->freq_mult = 9; |
578 | ret = mt312_initfe(fe); |
579 | if (ret < 0) |
580 | return ret; |
581 | } |
582 | } else { |
583 | if (state->freq_mult == 9) { |
584 | /* We are running 90MHz */ |
585 | state->freq_mult = 6; |
586 | ret = mt312_initfe(fe); |
587 | if (ret < 0) |
588 | return ret; |
589 | } |
590 | } |
591 | break; |
592 | |
593 | case ID_MT312: |
594 | case ID_ZL10313: |
595 | break; |
596 | |
597 | default: |
598 | return -EINVAL; |
599 | } |
600 | |
601 | if (fe->ops.tuner_ops.set_params) { |
602 | fe->ops.tuner_ops.set_params(fe); |
603 | if (fe->ops.i2c_gate_ctrl) |
604 | fe->ops.i2c_gate_ctrl(fe, 0); |
605 | } |
606 | |
607 | /* sr = (u16)(sr * 256.0 / 1000000.0) */ |
608 | sr = DIV_ROUND_CLOSEST(p->symbol_rate * 4, 15625); |
609 | |
610 | /* SYM_RATE */ |
611 | buf[0] = (sr >> 8) & 0x3f; |
612 | buf[1] = (sr >> 0) & 0xff; |
613 | |
614 | /* VIT_MODE */ |
615 | buf[2] = inv_tab[p->inversion] | fec_tab[p->fec_inner]; |
616 | |
617 | /* QPSK_CTRL */ |
618 | buf[3] = 0x40; /* swap I and Q before QPSK demodulation */ |
619 | |
620 | if (p->symbol_rate < 10000000) |
621 | buf[3] |= 0x04; /* use afc mode */ |
622 | |
623 | /* GO */ |
624 | buf[4] = 0x01; |
625 | |
626 | ret = mt312_write(state, reg: SYM_RATE_H, src: buf, count: sizeof(buf)); |
627 | if (ret < 0) |
628 | return ret; |
629 | |
630 | ret = mt312_reset(state, full: 0); |
631 | if (ret < 0) |
632 | return ret; |
633 | |
634 | return 0; |
635 | } |
636 | |
637 | static int mt312_get_frontend(struct dvb_frontend *fe, |
638 | struct dtv_frontend_properties *p) |
639 | { |
640 | struct mt312_state *state = fe->demodulator_priv; |
641 | int ret; |
642 | |
643 | ret = mt312_get_inversion(state, i: &p->inversion); |
644 | if (ret < 0) |
645 | return ret; |
646 | |
647 | ret = mt312_get_symbol_rate(state, sr: &p->symbol_rate); |
648 | if (ret < 0) |
649 | return ret; |
650 | |
651 | ret = mt312_get_code_rate(state, cr: &p->fec_inner); |
652 | if (ret < 0) |
653 | return ret; |
654 | |
655 | return 0; |
656 | } |
657 | |
658 | static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) |
659 | { |
660 | struct mt312_state *state = fe->demodulator_priv; |
661 | |
662 | u8 val = 0x00; |
663 | int ret; |
664 | |
665 | switch (state->id) { |
666 | case ID_ZL10313: |
667 | ret = mt312_readreg(state, reg: GPP_CTRL, val: &val); |
668 | if (ret < 0) |
669 | goto error; |
670 | |
671 | /* preserve this bit to not accidentally shutdown ADC */ |
672 | val &= 0x80; |
673 | break; |
674 | } |
675 | |
676 | if (enable) |
677 | val |= 0x40; |
678 | else |
679 | val &= ~0x40; |
680 | |
681 | ret = mt312_writereg(state, reg: GPP_CTRL, val); |
682 | |
683 | error: |
684 | return ret; |
685 | } |
686 | |
687 | static int mt312_sleep(struct dvb_frontend *fe) |
688 | { |
689 | struct mt312_state *state = fe->demodulator_priv; |
690 | int ret; |
691 | u8 config; |
692 | |
693 | /* reset all registers to defaults */ |
694 | ret = mt312_reset(state, full: 1); |
695 | if (ret < 0) |
696 | return ret; |
697 | |
698 | if (state->id == ID_ZL10313) { |
699 | /* reset ADC */ |
700 | ret = mt312_writereg(state, reg: GPP_CTRL, val: 0x00); |
701 | if (ret < 0) |
702 | return ret; |
703 | |
704 | /* full shutdown of ADCs, mpeg bus tristated */ |
705 | ret = mt312_writereg(state, reg: HW_CTRL, val: 0x0d); |
706 | if (ret < 0) |
707 | return ret; |
708 | } |
709 | |
710 | ret = mt312_readreg(state, reg: CONFIG, val: &config); |
711 | if (ret < 0) |
712 | return ret; |
713 | |
714 | /* enter standby */ |
715 | ret = mt312_writereg(state, reg: CONFIG, val: config & 0x7f); |
716 | if (ret < 0) |
717 | return ret; |
718 | |
719 | return 0; |
720 | } |
721 | |
722 | static int mt312_get_tune_settings(struct dvb_frontend *fe, |
723 | struct dvb_frontend_tune_settings *fesettings) |
724 | { |
725 | fesettings->min_delay_ms = 50; |
726 | fesettings->step_size = 0; |
727 | fesettings->max_drift = 0; |
728 | return 0; |
729 | } |
730 | |
731 | static void mt312_release(struct dvb_frontend *fe) |
732 | { |
733 | struct mt312_state *state = fe->demodulator_priv; |
734 | kfree(objp: state); |
735 | } |
736 | |
737 | #define MT312_SYS_CLK 90000000UL /* 90 MHz */ |
738 | static const struct dvb_frontend_ops mt312_ops = { |
739 | .delsys = { SYS_DVBS }, |
740 | .info = { |
741 | .name = "Zarlink ???? DVB-S" , |
742 | .frequency_min_hz = 950 * MHz, |
743 | .frequency_max_hz = 2150 * MHz, |
744 | /* FIXME: adjust freq to real used xtal */ |
745 | .frequency_stepsize_hz = MT312_PLL_CLK / 128, |
746 | .symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */ |
747 | .symbol_rate_max = MT312_SYS_CLK / 2, |
748 | .caps = |
749 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | |
750 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | |
751 | FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_MUTE_TS | |
752 | FE_CAN_RECOVER |
753 | }, |
754 | |
755 | .release = mt312_release, |
756 | |
757 | .init = mt312_initfe, |
758 | .sleep = mt312_sleep, |
759 | .i2c_gate_ctrl = mt312_i2c_gate_ctrl, |
760 | |
761 | .set_frontend = mt312_set_frontend, |
762 | .get_frontend = mt312_get_frontend, |
763 | .get_tune_settings = mt312_get_tune_settings, |
764 | |
765 | .read_status = mt312_read_status, |
766 | .read_ber = mt312_read_ber, |
767 | .read_signal_strength = mt312_read_signal_strength, |
768 | .read_snr = mt312_read_snr, |
769 | .read_ucblocks = mt312_read_ucblocks, |
770 | |
771 | .diseqc_send_master_cmd = mt312_send_master_cmd, |
772 | .diseqc_send_burst = mt312_send_burst, |
773 | .set_tone = mt312_set_tone, |
774 | .set_voltage = mt312_set_voltage, |
775 | }; |
776 | |
777 | struct dvb_frontend *mt312_attach(const struct mt312_config *config, |
778 | struct i2c_adapter *i2c) |
779 | { |
780 | struct mt312_state *state = NULL; |
781 | |
782 | /* allocate memory for the internal state */ |
783 | state = kzalloc(size: sizeof(struct mt312_state), GFP_KERNEL); |
784 | if (state == NULL) |
785 | goto error; |
786 | |
787 | /* setup the state */ |
788 | state->config = config; |
789 | state->i2c = i2c; |
790 | |
791 | /* check if the demod is there */ |
792 | if (mt312_readreg(state, reg: ID, val: &state->id) < 0) |
793 | goto error; |
794 | |
795 | /* create dvb_frontend */ |
796 | memcpy(&state->frontend.ops, &mt312_ops, |
797 | sizeof(struct dvb_frontend_ops)); |
798 | state->frontend.demodulator_priv = state; |
799 | |
800 | switch (state->id) { |
801 | case ID_VP310: |
802 | strscpy(p: state->frontend.ops.info.name, q: "Zarlink VP310 DVB-S" , |
803 | size: sizeof(state->frontend.ops.info.name)); |
804 | state->xtal = MT312_PLL_CLK; |
805 | state->freq_mult = 9; |
806 | break; |
807 | case ID_MT312: |
808 | strscpy(p: state->frontend.ops.info.name, q: "Zarlink MT312 DVB-S" , |
809 | size: sizeof(state->frontend.ops.info.name)); |
810 | state->xtal = MT312_PLL_CLK; |
811 | state->freq_mult = 6; |
812 | break; |
813 | case ID_ZL10313: |
814 | strscpy(p: state->frontend.ops.info.name, q: "Zarlink ZL10313 DVB-S" , |
815 | size: sizeof(state->frontend.ops.info.name)); |
816 | state->xtal = MT312_PLL_CLK_10_111; |
817 | state->freq_mult = 9; |
818 | break; |
819 | default: |
820 | printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313 are supported chips.\n" ); |
821 | goto error; |
822 | } |
823 | |
824 | return &state->frontend; |
825 | |
826 | error: |
827 | kfree(objp: state); |
828 | return NULL; |
829 | } |
830 | EXPORT_SYMBOL_GPL(mt312_attach); |
831 | |
832 | module_param(debug, int, 0644); |
833 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)." ); |
834 | |
835 | MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver" ); |
836 | MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>" ); |
837 | MODULE_AUTHOR("Matthias Schwarzott <zzam@gentoo.org>" ); |
838 | MODULE_LICENSE("GPL" ); |
839 | |
840 | |