diff options
Diffstat (limited to 'drivers/media/dvb/bt8xx/dst.c')
-rw-r--r-- | drivers/media/dvb/bt8xx/dst.c | 1089 |
1 files changed, 1089 insertions, 0 deletions
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c new file mode 100644 index 000000000000..eac83768dfd0 --- /dev/null +++ b/drivers/media/dvb/bt8xx/dst.c | |||
@@ -0,0 +1,1089 @@ | |||
1 | /* | ||
2 | Frontend-driver for TwinHan DST Frontend | ||
3 | |||
4 | Copyright (C) 2003 Jamie Honan | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | |||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/string.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/vmalloc.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <asm/div64.h> | ||
31 | |||
32 | #include "dvb_frontend.h" | ||
33 | #include "dst_priv.h" | ||
34 | #include "dst.h" | ||
35 | |||
36 | struct dst_state { | ||
37 | |||
38 | struct i2c_adapter* i2c; | ||
39 | |||
40 | struct bt878* bt; | ||
41 | |||
42 | struct dvb_frontend_ops ops; | ||
43 | |||
44 | /* configuration settings */ | ||
45 | const struct dst_config* config; | ||
46 | |||
47 | struct dvb_frontend frontend; | ||
48 | |||
49 | /* private demodulator data */ | ||
50 | u8 tx_tuna[10]; | ||
51 | u8 rx_tuna[10]; | ||
52 | u8 rxbuffer[10]; | ||
53 | u8 diseq_flags; | ||
54 | u8 dst_type; | ||
55 | u32 type_flags; | ||
56 | u32 frequency; /* intermediate frequency in kHz for QPSK */ | ||
57 | fe_spectral_inversion_t inversion; | ||
58 | u32 symbol_rate; /* symbol rate in Symbols per second */ | ||
59 | fe_code_rate_t fec; | ||
60 | fe_sec_voltage_t voltage; | ||
61 | fe_sec_tone_mode_t tone; | ||
62 | u32 decode_freq; | ||
63 | u8 decode_lock; | ||
64 | u16 decode_strength; | ||
65 | u16 decode_snr; | ||
66 | unsigned long cur_jiff; | ||
67 | u8 k22; | ||
68 | fe_bandwidth_t bandwidth; | ||
69 | }; | ||
70 | |||
71 | static unsigned int dst_verbose = 0; | ||
72 | module_param(dst_verbose, int, 0644); | ||
73 | MODULE_PARM_DESC(dst_verbose, "verbose startup messages, default is 1 (yes)"); | ||
74 | static unsigned int dst_debug = 0; | ||
75 | module_param(dst_debug, int, 0644); | ||
76 | MODULE_PARM_DESC(dst_debug, "debug messages, default is 0 (no)"); | ||
77 | |||
78 | #define dprintk if (dst_debug) printk | ||
79 | |||
80 | #define DST_TYPE_IS_SAT 0 | ||
81 | #define DST_TYPE_IS_TERR 1 | ||
82 | #define DST_TYPE_IS_CABLE 2 | ||
83 | |||
84 | #define DST_TYPE_HAS_NEWTUNE 1 | ||
85 | #define DST_TYPE_HAS_TS204 2 | ||
86 | #define DST_TYPE_HAS_SYMDIV 4 | ||
87 | |||
88 | #define HAS_LOCK 1 | ||
89 | #define ATTEMPT_TUNE 2 | ||
90 | #define HAS_POWER 4 | ||
91 | |||
92 | static void dst_packsize(struct dst_state* state, int psize) | ||
93 | { | ||
94 | union dst_gpio_packet bits; | ||
95 | |||
96 | bits.psize = psize; | ||
97 | bt878_device_control(state->bt, DST_IG_TS, &bits); | ||
98 | } | ||
99 | |||
100 | static int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh) | ||
101 | { | ||
102 | union dst_gpio_packet enb; | ||
103 | union dst_gpio_packet bits; | ||
104 | int err; | ||
105 | |||
106 | enb.enb.mask = mask; | ||
107 | enb.enb.enable = enbb; | ||
108 | if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) { | ||
109 | dprintk("%s: dst_gpio_enb error (err == %i, mask == 0x%02x, enb == 0x%02x)\n", __FUNCTION__, err, mask, enbb); | ||
110 | return -EREMOTEIO; | ||
111 | } | ||
112 | |||
113 | /* because complete disabling means no output, no need to do output packet */ | ||
114 | if (enbb == 0) | ||
115 | return 0; | ||
116 | |||
117 | bits.outp.mask = enbb; | ||
118 | bits.outp.highvals = outhigh; | ||
119 | |||
120 | if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) { | ||
121 | dprintk("%s: dst_gpio_outb error (err == %i, enbb == 0x%02x, outhigh == 0x%02x)\n", __FUNCTION__, err, enbb, outhigh); | ||
122 | return -EREMOTEIO; | ||
123 | } | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static int dst_gpio_inb(struct dst_state *state, u8 * result) | ||
128 | { | ||
129 | union dst_gpio_packet rd_packet; | ||
130 | int err; | ||
131 | |||
132 | *result = 0; | ||
133 | |||
134 | if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) { | ||
135 | dprintk("%s: dst_gpio_inb error (err == %i)\n", __FUNCTION__, err); | ||
136 | return -EREMOTEIO; | ||
137 | } | ||
138 | |||
139 | *result = (u8) rd_packet.rd.value; | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | #define DST_I2C_ENABLE 1 | ||
144 | #define DST_8820 2 | ||
145 | |||
146 | static int dst_reset8820(struct dst_state *state) | ||
147 | { | ||
148 | int retval; | ||
149 | /* pull 8820 gpio pin low, wait, high, wait, then low */ | ||
150 | // dprintk ("%s: reset 8820\n", __FUNCTION__); | ||
151 | retval = dst_gpio_outb(state, DST_8820, DST_8820, 0); | ||
152 | if (retval < 0) | ||
153 | return retval; | ||
154 | msleep(10); | ||
155 | retval = dst_gpio_outb(state, DST_8820, DST_8820, DST_8820); | ||
156 | if (retval < 0) | ||
157 | return retval; | ||
158 | /* wait for more feedback on what works here * | ||
159 | msleep(10); | ||
160 | retval = dst_gpio_outb(dst, DST_8820, DST_8820, 0); | ||
161 | if (retval < 0) | ||
162 | return retval; | ||
163 | */ | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static int dst_i2c_enable(struct dst_state *state) | ||
168 | { | ||
169 | int retval; | ||
170 | /* pull I2C enable gpio pin low, wait */ | ||
171 | // dprintk ("%s: i2c enable\n", __FUNCTION__); | ||
172 | retval = dst_gpio_outb(state, ~0, DST_I2C_ENABLE, 0); | ||
173 | if (retval < 0) | ||
174 | return retval; | ||
175 | // dprintk ("%s: i2c enable delay\n", __FUNCTION__); | ||
176 | msleep(33); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int dst_i2c_disable(struct dst_state *state) | ||
181 | { | ||
182 | int retval; | ||
183 | /* release I2C enable gpio pin, wait */ | ||
184 | // dprintk ("%s: i2c disable\n", __FUNCTION__); | ||
185 | retval = dst_gpio_outb(state, ~0, 0, 0); | ||
186 | if (retval < 0) | ||
187 | return retval; | ||
188 | // dprintk ("%s: i2c disable delay\n", __FUNCTION__); | ||
189 | msleep(33); | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int dst_wait_dst_ready(struct dst_state *state) | ||
194 | { | ||
195 | u8 reply; | ||
196 | int retval; | ||
197 | int i; | ||
198 | for (i = 0; i < 200; i++) { | ||
199 | retval = dst_gpio_inb(state, &reply); | ||
200 | if (retval < 0) | ||
201 | return retval; | ||
202 | if ((reply & DST_I2C_ENABLE) == 0) { | ||
203 | dprintk("%s: dst wait ready after %d\n", __FUNCTION__, i); | ||
204 | return 1; | ||
205 | } | ||
206 | msleep(10); | ||
207 | } | ||
208 | dprintk("%s: dst wait NOT ready after %d\n", __FUNCTION__, i); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int write_dst(struct dst_state *state, u8 * data, u8 len) | ||
213 | { | ||
214 | struct i2c_msg msg = { | ||
215 | .addr = state->config->demod_address,.flags = 0,.buf = data,.len = len | ||
216 | }; | ||
217 | int err; | ||
218 | int cnt; | ||
219 | |||
220 | if (dst_debug && dst_verbose) { | ||
221 | u8 i; | ||
222 | dprintk("%s writing", __FUNCTION__); | ||
223 | for (i = 0; i < len; i++) { | ||
224 | dprintk(" 0x%02x", data[i]); | ||
225 | } | ||
226 | dprintk("\n"); | ||
227 | } | ||
228 | msleep(30); | ||
229 | for (cnt = 0; cnt < 4; cnt++) { | ||
230 | if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) { | ||
231 | dprintk("%s: write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, data[0]); | ||
232 | dst_i2c_disable(state); | ||
233 | msleep(500); | ||
234 | dst_i2c_enable(state); | ||
235 | msleep(500); | ||
236 | continue; | ||
237 | } else | ||
238 | break; | ||
239 | } | ||
240 | if (cnt >= 4) | ||
241 | return -EREMOTEIO; | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static int read_dst(struct dst_state *state, u8 * ret, u8 len) | ||
246 | { | ||
247 | struct i2c_msg msg = {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = ret,.len = len }; | ||
248 | int err; | ||
249 | int cnt; | ||
250 | |||
251 | for (cnt = 0; cnt < 4; cnt++) { | ||
252 | if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) { | ||
253 | dprintk("%s: read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, ret[0]); | ||
254 | dst_i2c_disable(state); | ||
255 | dst_i2c_enable(state); | ||
256 | continue; | ||
257 | } else | ||
258 | break; | ||
259 | } | ||
260 | if (cnt >= 4) | ||
261 | return -EREMOTEIO; | ||
262 | dprintk("%s reply is 0x%x\n", __FUNCTION__, ret[0]); | ||
263 | if (dst_debug && dst_verbose) { | ||
264 | for (err = 1; err < len; err++) | ||
265 | dprintk(" 0x%x", ret[err]); | ||
266 | if (err > 1) | ||
267 | dprintk("\n"); | ||
268 | } | ||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int dst_set_freq(struct dst_state *state, u32 freq) | ||
273 | { | ||
274 | u8 *val; | ||
275 | |||
276 | state->frequency = freq; | ||
277 | |||
278 | // dprintk("%s: set frequency %u\n", __FUNCTION__, freq); | ||
279 | if (state->dst_type == DST_TYPE_IS_SAT) { | ||
280 | freq = freq / 1000; | ||
281 | if (freq < 950 || freq > 2150) | ||
282 | return -EINVAL; | ||
283 | val = &state->tx_tuna[0]; | ||
284 | val[2] = (freq >> 8) & 0x7f; | ||
285 | val[3] = (u8) freq; | ||
286 | val[4] = 1; | ||
287 | val[8] &= ~4; | ||
288 | if (freq < 1531) | ||
289 | val[8] |= 4; | ||
290 | } else if (state->dst_type == DST_TYPE_IS_TERR) { | ||
291 | freq = freq / 1000; | ||
292 | if (freq < 137000 || freq > 858000) | ||
293 | return -EINVAL; | ||
294 | val = &state->tx_tuna[0]; | ||
295 | val[2] = (freq >> 16) & 0xff; | ||
296 | val[3] = (freq >> 8) & 0xff; | ||
297 | val[4] = (u8) freq; | ||
298 | val[5] = 0; | ||
299 | switch (state->bandwidth) { | ||
300 | case BANDWIDTH_6_MHZ: | ||
301 | val[6] = 6; | ||
302 | break; | ||
303 | |||
304 | case BANDWIDTH_7_MHZ: | ||
305 | case BANDWIDTH_AUTO: | ||
306 | val[6] = 7; | ||
307 | break; | ||
308 | |||
309 | case BANDWIDTH_8_MHZ: | ||
310 | val[6] = 8; | ||
311 | break; | ||
312 | } | ||
313 | |||
314 | val[7] = 0; | ||
315 | val[8] = 0; | ||
316 | } else if (state->dst_type == DST_TYPE_IS_CABLE) { | ||
317 | /* guess till will get one */ | ||
318 | freq = freq / 1000; | ||
319 | val = &state->tx_tuna[0]; | ||
320 | val[2] = (freq >> 16) & 0xff; | ||
321 | val[3] = (freq >> 8) & 0xff; | ||
322 | val[4] = (u8) freq; | ||
323 | } else | ||
324 | return -EINVAL; | ||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int dst_set_bandwidth(struct dst_state* state, fe_bandwidth_t bandwidth) | ||
329 | { | ||
330 | u8 *val; | ||
331 | |||
332 | state->bandwidth = bandwidth; | ||
333 | |||
334 | if (state->dst_type != DST_TYPE_IS_TERR) | ||
335 | return 0; | ||
336 | |||
337 | val = &state->tx_tuna[0]; | ||
338 | switch (bandwidth) { | ||
339 | case BANDWIDTH_6_MHZ: | ||
340 | val[6] = 6; | ||
341 | break; | ||
342 | |||
343 | case BANDWIDTH_7_MHZ: | ||
344 | val[6] = 7; | ||
345 | break; | ||
346 | |||
347 | case BANDWIDTH_8_MHZ: | ||
348 | val[6] = 8; | ||
349 | break; | ||
350 | |||
351 | default: | ||
352 | return -EINVAL; | ||
353 | } | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static int dst_set_inversion(struct dst_state* state, fe_spectral_inversion_t inversion) | ||
358 | { | ||
359 | u8 *val; | ||
360 | |||
361 | state->inversion = inversion; | ||
362 | |||
363 | val = &state->tx_tuna[0]; | ||
364 | |||
365 | val[8] &= ~0x80; | ||
366 | |||
367 | switch (inversion) { | ||
368 | case INVERSION_OFF: | ||
369 | break; | ||
370 | case INVERSION_ON: | ||
371 | val[8] |= 0x80; | ||
372 | break; | ||
373 | default: | ||
374 | return -EINVAL; | ||
375 | } | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static int dst_set_fec(struct dst_state* state, fe_code_rate_t fec) | ||
380 | { | ||
381 | state->fec = fec; | ||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | static fe_code_rate_t dst_get_fec(struct dst_state* state) | ||
386 | { | ||
387 | return state->fec; | ||
388 | } | ||
389 | |||
390 | static int dst_set_symbolrate(struct dst_state* state, u32 srate) | ||
391 | { | ||
392 | u8 *val; | ||
393 | u32 symcalc; | ||
394 | u64 sval; | ||
395 | |||
396 | state->symbol_rate = srate; | ||
397 | |||
398 | if (state->dst_type == DST_TYPE_IS_TERR) { | ||
399 | return 0; | ||
400 | } | ||
401 | // dprintk("%s: set srate %u\n", __FUNCTION__, srate); | ||
402 | srate /= 1000; | ||
403 | val = &state->tx_tuna[0]; | ||
404 | |||
405 | if (state->type_flags & DST_TYPE_HAS_SYMDIV) { | ||
406 | sval = srate; | ||
407 | sval <<= 20; | ||
408 | do_div(sval, 88000); | ||
409 | symcalc = (u32) sval; | ||
410 | // dprintk("%s: set symcalc %u\n", __FUNCTION__, symcalc); | ||
411 | val[5] = (u8) (symcalc >> 12); | ||
412 | val[6] = (u8) (symcalc >> 4); | ||
413 | val[7] = (u8) (symcalc << 4); | ||
414 | } else { | ||
415 | val[5] = (u8) (srate >> 16) & 0x7f; | ||
416 | val[6] = (u8) (srate >> 8); | ||
417 | val[7] = (u8) srate; | ||
418 | } | ||
419 | val[8] &= ~0x20; | ||
420 | if (srate > 8000) | ||
421 | val[8] |= 0x20; | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static u8 dst_check_sum(u8 * buf, u32 len) | ||
426 | { | ||
427 | u32 i; | ||
428 | u8 val = 0; | ||
429 | if (!len) | ||
430 | return 0; | ||
431 | for (i = 0; i < len; i++) { | ||
432 | val += buf[i]; | ||
433 | } | ||
434 | return ((~val) + 1); | ||
435 | } | ||
436 | |||
437 | struct dst_types { | ||
438 | char *mstr; | ||
439 | int offs; | ||
440 | u8 dst_type; | ||
441 | u32 type_flags; | ||
442 | }; | ||
443 | |||
444 | static struct dst_types dst_tlist[] = { | ||
445 | {"DST-020", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_SYMDIV}, | ||
446 | {"DST-030", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE}, | ||
447 | {"DST-03T", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204}, | ||
448 | {"DST-MOT", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_SYMDIV}, | ||
449 | {"DST-CI", 1, DST_TYPE_IS_SAT, DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE}, | ||
450 | {"DSTMCI", 1, DST_TYPE_IS_SAT, DST_TYPE_HAS_NEWTUNE}, | ||
451 | {"DSTFCI", 1, DST_TYPE_IS_SAT, DST_TYPE_HAS_NEWTUNE}, | ||
452 | {"DCTNEW", 1, DST_TYPE_IS_CABLE, DST_TYPE_HAS_NEWTUNE}, | ||
453 | {"DCT-CI", 1, DST_TYPE_IS_CABLE, DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_TS204}, | ||
454 | {"DTTDIG", 1, DST_TYPE_IS_TERR, 0} | ||
455 | }; | ||
456 | |||
457 | /* DCTNEW and DCT-CI are guesses */ | ||
458 | |||
459 | static void dst_type_flags_print(u32 type_flags) | ||
460 | { | ||
461 | printk("DST type flags :"); | ||
462 | if (type_flags & DST_TYPE_HAS_NEWTUNE) | ||
463 | printk(" 0x%x newtuner", DST_TYPE_HAS_NEWTUNE); | ||
464 | if (type_flags & DST_TYPE_HAS_TS204) | ||
465 | printk(" 0x%x ts204", DST_TYPE_HAS_TS204); | ||
466 | if (type_flags & DST_TYPE_HAS_SYMDIV) | ||
467 | printk(" 0x%x symdiv", DST_TYPE_HAS_SYMDIV); | ||
468 | printk("\n"); | ||
469 | } | ||
470 | |||
471 | static int dst_type_print(u8 type) | ||
472 | { | ||
473 | char *otype; | ||
474 | switch (type) { | ||
475 | case DST_TYPE_IS_SAT: | ||
476 | otype = "satellite"; | ||
477 | break; | ||
478 | case DST_TYPE_IS_TERR: | ||
479 | otype = "terrestrial"; | ||
480 | break; | ||
481 | case DST_TYPE_IS_CABLE: | ||
482 | otype = "cable"; | ||
483 | break; | ||
484 | default: | ||
485 | printk("%s: invalid dst type %d\n", __FUNCTION__, type); | ||
486 | return -EINVAL; | ||
487 | } | ||
488 | printk("DST type : %s\n", otype); | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static int dst_check_ci(struct dst_state *state) | ||
493 | { | ||
494 | u8 txbuf[8]; | ||
495 | u8 rxbuf[8]; | ||
496 | int retval; | ||
497 | int i; | ||
498 | struct dst_types *dsp; | ||
499 | u8 use_dst_type; | ||
500 | u32 use_type_flags; | ||
501 | |||
502 | memset(txbuf, 0, sizeof(txbuf)); | ||
503 | txbuf[1] = 6; | ||
504 | txbuf[7] = dst_check_sum(txbuf, 7); | ||
505 | |||
506 | dst_i2c_enable(state); | ||
507 | dst_reset8820(state); | ||
508 | retval = write_dst(state, txbuf, 8); | ||
509 | if (retval < 0) { | ||
510 | dst_i2c_disable(state); | ||
511 | dprintk("%s: write not successful, maybe no card?\n", __FUNCTION__); | ||
512 | return retval; | ||
513 | } | ||
514 | msleep(3); | ||
515 | retval = read_dst(state, rxbuf, 1); | ||
516 | dst_i2c_disable(state); | ||
517 | if (retval < 0) { | ||
518 | dprintk("%s: read not successful, maybe no card?\n", __FUNCTION__); | ||
519 | return retval; | ||
520 | } | ||
521 | if (rxbuf[0] != 0xff) { | ||
522 | dprintk("%s: write reply not 0xff, not ci (%02x)\n", __FUNCTION__, rxbuf[0]); | ||
523 | return retval; | ||
524 | } | ||
525 | if (!dst_wait_dst_ready(state)) | ||
526 | return 0; | ||
527 | // dst_i2c_enable(i2c); Dimitri | ||
528 | retval = read_dst(state, rxbuf, 8); | ||
529 | dst_i2c_disable(state); | ||
530 | if (retval < 0) { | ||
531 | dprintk("%s: read not successful\n", __FUNCTION__); | ||
532 | return retval; | ||
533 | } | ||
534 | if (rxbuf[7] != dst_check_sum(rxbuf, 7)) { | ||
535 | dprintk("%s: checksum failure\n", __FUNCTION__); | ||
536 | return retval; | ||
537 | } | ||
538 | rxbuf[7] = '\0'; | ||
539 | for (i = 0, dsp = &dst_tlist[0]; i < sizeof(dst_tlist) / sizeof(dst_tlist[0]); i++, dsp++) { | ||
540 | if (!strncmp(&rxbuf[dsp->offs], dsp->mstr, strlen(dsp->mstr))) { | ||
541 | use_type_flags = dsp->type_flags; | ||
542 | use_dst_type = dsp->dst_type; | ||
543 | printk("%s: recognize %s\n", __FUNCTION__, dsp->mstr); | ||
544 | break; | ||
545 | } | ||
546 | } | ||
547 | if (i >= sizeof(dst_tlist) / sizeof(dst_tlist[0])) { | ||
548 | printk("%s: unable to recognize %s or %s\n", __FUNCTION__, &rxbuf[0], &rxbuf[1]); | ||
549 | printk("%s please email linux-dvb@linuxtv.org with this type in\n", __FUNCTION__); | ||
550 | use_dst_type = DST_TYPE_IS_SAT; | ||
551 | use_type_flags = DST_TYPE_HAS_SYMDIV; | ||
552 | } | ||
553 | dst_type_print(use_dst_type); | ||
554 | |||
555 | state->type_flags = use_type_flags; | ||
556 | state->dst_type = use_dst_type; | ||
557 | dst_type_flags_print(state->type_flags); | ||
558 | |||
559 | if (state->type_flags & DST_TYPE_HAS_TS204) { | ||
560 | dst_packsize(state, 204); | ||
561 | } | ||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | static int dst_command(struct dst_state* state, u8 * data, u8 len) | ||
566 | { | ||
567 | int retval; | ||
568 | u8 reply; | ||
569 | |||
570 | dst_i2c_enable(state); | ||
571 | dst_reset8820(state); | ||
572 | retval = write_dst(state, data, len); | ||
573 | if (retval < 0) { | ||
574 | dst_i2c_disable(state); | ||
575 | dprintk("%s: write not successful\n", __FUNCTION__); | ||
576 | return retval; | ||
577 | } | ||
578 | msleep(33); | ||
579 | retval = read_dst(state, &reply, 1); | ||
580 | dst_i2c_disable(state); | ||
581 | if (retval < 0) { | ||
582 | dprintk("%s: read verify not successful\n", __FUNCTION__); | ||
583 | return retval; | ||
584 | } | ||
585 | if (reply != 0xff) { | ||
586 | dprintk("%s: write reply not 0xff 0x%02x \n", __FUNCTION__, reply); | ||
587 | return 0; | ||
588 | } | ||
589 | if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3)) | ||
590 | return 0; | ||
591 | if (!dst_wait_dst_ready(state)) | ||
592 | return 0; | ||
593 | // dst_i2c_enable(i2c); Per dimitri | ||
594 | retval = read_dst(state, state->rxbuffer, 8); | ||
595 | dst_i2c_disable(state); | ||
596 | if (retval < 0) { | ||
597 | dprintk("%s: read not successful\n", __FUNCTION__); | ||
598 | return 0; | ||
599 | } | ||
600 | if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) { | ||
601 | dprintk("%s: checksum failure\n", __FUNCTION__); | ||
602 | return 0; | ||
603 | } | ||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | static int dst_get_signal(struct dst_state* state) | ||
608 | { | ||
609 | int retval; | ||
610 | u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb }; | ||
611 | |||
612 | if ((state->diseq_flags & ATTEMPT_TUNE) == 0) { | ||
613 | state->decode_lock = state->decode_strength = state->decode_snr = 0; | ||
614 | return 0; | ||
615 | } | ||
616 | if (0 == (state->diseq_flags & HAS_LOCK)) { | ||
617 | state->decode_lock = state->decode_strength = state->decode_snr = 0; | ||
618 | return 0; | ||
619 | } | ||
620 | if (time_after_eq(jiffies, state->cur_jiff + (HZ / 5))) { | ||
621 | retval = dst_command(state, get_signal, 8); | ||
622 | if (retval < 0) | ||
623 | return retval; | ||
624 | if (state->dst_type == DST_TYPE_IS_SAT) { | ||
625 | state->decode_lock = ((state->rxbuffer[6] & 0x10) == 0) ? 1 : 0; | ||
626 | state->decode_strength = state->rxbuffer[5] << 8; | ||
627 | state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3]; | ||
628 | } else if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE)) { | ||
629 | state->decode_lock = (state->rxbuffer[1]) ? 1 : 0; | ||
630 | state->decode_strength = state->rxbuffer[4] << 8; | ||
631 | state->decode_snr = state->rxbuffer[3] << 8; | ||
632 | } | ||
633 | state->cur_jiff = jiffies; | ||
634 | } | ||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | static int dst_tone_power_cmd(struct dst_state* state) | ||
639 | { | ||
640 | u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 }; | ||
641 | |||
642 | if (state->dst_type == DST_TYPE_IS_TERR) | ||
643 | return 0; | ||
644 | |||
645 | if (state->voltage == SEC_VOLTAGE_OFF) | ||
646 | paket[4] = 0; | ||
647 | else | ||
648 | paket[4] = 1; | ||
649 | if (state->tone == SEC_TONE_ON) | ||
650 | paket[2] = state->k22; | ||
651 | else | ||
652 | paket[2] = 0; | ||
653 | paket[7] = dst_check_sum(&paket[0], 7); | ||
654 | dst_command(state, paket, 8); | ||
655 | return 0; | ||
656 | } | ||
657 | |||
658 | static int dst_get_tuna(struct dst_state* state) | ||
659 | { | ||
660 | int retval; | ||
661 | if ((state->diseq_flags & ATTEMPT_TUNE) == 0) | ||
662 | return 0; | ||
663 | state->diseq_flags &= ~(HAS_LOCK); | ||
664 | if (!dst_wait_dst_ready(state)) | ||
665 | return 0; | ||
666 | if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { | ||
667 | /* how to get variable length reply ???? */ | ||
668 | retval = read_dst(state, state->rx_tuna, 10); | ||
669 | } else { | ||
670 | retval = read_dst(state, &state->rx_tuna[2], 8); | ||
671 | } | ||
672 | if (retval < 0) { | ||
673 | dprintk("%s: read not successful\n", __FUNCTION__); | ||
674 | return 0; | ||
675 | } | ||
676 | if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { | ||
677 | if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) { | ||
678 | dprintk("%s: checksum failure?\n", __FUNCTION__); | ||
679 | return 0; | ||
680 | } | ||
681 | } else { | ||
682 | if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) { | ||
683 | dprintk("%s: checksum failure?\n", __FUNCTION__); | ||
684 | return 0; | ||
685 | } | ||
686 | } | ||
687 | if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0) | ||
688 | return 0; | ||
689 | state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3]; | ||
690 | |||
691 | state->decode_lock = 1; | ||
692 | /* | ||
693 | dst->decode_n1 = (dst->rx_tuna[4] << 8) + | ||
694 | (dst->rx_tuna[5]); | ||
695 | |||
696 | dst->decode_n2 = (dst->rx_tuna[8] << 8) + | ||
697 | (dst->rx_tuna[7]); | ||
698 | */ | ||
699 | state->diseq_flags |= HAS_LOCK; | ||
700 | /* dst->cur_jiff = jiffies; */ | ||
701 | return 1; | ||
702 | } | ||
703 | |||
704 | static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage); | ||
705 | |||
706 | static int dst_write_tuna(struct dvb_frontend* fe) | ||
707 | { | ||
708 | struct dst_state* state = (struct dst_state*) fe->demodulator_priv; | ||
709 | int retval; | ||
710 | u8 reply; | ||
711 | |||
712 | dprintk("%s: type_flags 0x%x \n", __FUNCTION__, state->type_flags); | ||
713 | state->decode_freq = 0; | ||
714 | state->decode_lock = state->decode_strength = state->decode_snr = 0; | ||
715 | if (state->dst_type == DST_TYPE_IS_SAT) { | ||
716 | if (!(state->diseq_flags & HAS_POWER)) | ||
717 | dst_set_voltage(fe, SEC_VOLTAGE_13); | ||
718 | } | ||
719 | state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE); | ||
720 | dst_i2c_enable(state); | ||
721 | if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { | ||
722 | dst_reset8820(state); | ||
723 | state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9); | ||
724 | retval = write_dst(state, &state->tx_tuna[0], 10); | ||
725 | } else { | ||
726 | state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7); | ||
727 | retval = write_dst(state, &state->tx_tuna[2], 8); | ||
728 | } | ||
729 | if (retval < 0) { | ||
730 | dst_i2c_disable(state); | ||
731 | dprintk("%s: write not successful\n", __FUNCTION__); | ||
732 | return retval; | ||
733 | } | ||
734 | msleep(3); | ||
735 | retval = read_dst(state, &reply, 1); | ||
736 | dst_i2c_disable(state); | ||
737 | if (retval < 0) { | ||
738 | dprintk("%s: read verify not successful\n", __FUNCTION__); | ||
739 | return retval; | ||
740 | } | ||
741 | if (reply != 0xff) { | ||
742 | dprintk("%s: write reply not 0xff 0x%02x \n", __FUNCTION__, reply); | ||
743 | return 0; | ||
744 | } | ||
745 | state->diseq_flags |= ATTEMPT_TUNE; | ||
746 | return dst_get_tuna(state); | ||
747 | } | ||
748 | |||
749 | /* | ||
750 | * line22k0 0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00 | ||
751 | * line22k1 0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00 | ||
752 | * line22k2 0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00 | ||
753 | * tone 0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00 | ||
754 | * data 0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00 | ||
755 | * power_off 0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 | ||
756 | * power_on 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 | ||
757 | * Diseqc 1 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec | ||
758 | * Diseqc 2 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8 | ||
759 | * Diseqc 3 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4 | ||
760 | * Diseqc 4 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0 | ||
761 | */ | ||
762 | |||
763 | static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) | ||
764 | { | ||
765 | struct dst_state* state = (struct dst_state*) fe->demodulator_priv; | ||
766 | u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec }; | ||
767 | |||
768 | if (state->dst_type == DST_TYPE_IS_TERR) | ||
769 | return 0; | ||
770 | |||
771 | if (cmd->msg_len == 0 || cmd->msg_len > 4) | ||
772 | return -EINVAL; | ||
773 | memcpy(&paket[3], cmd->msg, cmd->msg_len); | ||
774 | paket[7] = dst_check_sum(&paket[0], 7); | ||
775 | dst_command(state, paket, 8); | ||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) | ||
780 | { | ||
781 | u8 *val; | ||
782 | int need_cmd; | ||
783 | struct dst_state* state = (struct dst_state*) fe->demodulator_priv; | ||
784 | |||
785 | state->voltage = voltage; | ||
786 | |||
787 | if (state->dst_type == DST_TYPE_IS_TERR) | ||
788 | return 0; | ||
789 | |||
790 | need_cmd = 0; | ||
791 | val = &state->tx_tuna[0]; | ||
792 | val[8] &= ~0x40; | ||
793 | switch (voltage) { | ||
794 | case SEC_VOLTAGE_13: | ||
795 | if ((state->diseq_flags & HAS_POWER) == 0) | ||
796 | need_cmd = 1; | ||
797 | state->diseq_flags |= HAS_POWER; | ||
798 | break; | ||
799 | case SEC_VOLTAGE_18: | ||
800 | if ((state->diseq_flags & HAS_POWER) == 0) | ||
801 | need_cmd = 1; | ||
802 | state->diseq_flags |= HAS_POWER; | ||
803 | val[8] |= 0x40; | ||
804 | break; | ||
805 | case SEC_VOLTAGE_OFF: | ||
806 | need_cmd = 1; | ||
807 | state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE); | ||
808 | break; | ||
809 | default: | ||
810 | return -EINVAL; | ||
811 | } | ||
812 | if (need_cmd) { | ||
813 | dst_tone_power_cmd(state); | ||
814 | } | ||
815 | return 0; | ||
816 | } | ||
817 | |||
818 | static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | ||
819 | { | ||
820 | u8 *val; | ||
821 | struct dst_state* state = (struct dst_state*) fe->demodulator_priv; | ||
822 | |||
823 | state->tone = tone; | ||
824 | |||
825 | if (state->dst_type == DST_TYPE_IS_TERR) | ||
826 | return 0; | ||
827 | |||
828 | val = &state->tx_tuna[0]; | ||
829 | |||
830 | val[8] &= ~0x1; | ||
831 | |||
832 | switch (tone) { | ||
833 | case SEC_TONE_OFF: | ||
834 | break; | ||
835 | case SEC_TONE_ON: | ||
836 | val[8] |= 1; | ||
837 | break; | ||
838 | default: | ||
839 | return -EINVAL; | ||
840 | } | ||
841 | dst_tone_power_cmd(state); | ||
842 | return 0; | ||
843 | } | ||
844 | |||
845 | static int dst_init(struct dvb_frontend* fe) | ||
846 | { | ||
847 | struct dst_state* state = (struct dst_state*) fe->demodulator_priv; | ||
848 | static u8 ini_satci_tuna[] = { 9, 0, 3, 0xb6, 1, 0, 0x73, 0x21, 0, 0 }; | ||
849 | static u8 ini_satfta_tuna[] = { 0, 0, 3, 0xb6, 1, 0x55, 0xbd, 0x50, 0, 0 }; | ||
850 | static u8 ini_tvfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; | ||
851 | static u8 ini_tvci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; | ||
852 | static u8 ini_cabfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; | ||
853 | static u8 ini_cabci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; | ||
854 | state->inversion = INVERSION_ON; | ||
855 | state->voltage = SEC_VOLTAGE_13; | ||
856 | state->tone = SEC_TONE_OFF; | ||
857 | state->symbol_rate = 29473000; | ||
858 | state->fec = FEC_AUTO; | ||
859 | state->diseq_flags = 0; | ||
860 | state->k22 = 0x02; | ||
861 | state->bandwidth = BANDWIDTH_7_MHZ; | ||
862 | state->cur_jiff = jiffies; | ||
863 | if (state->dst_type == DST_TYPE_IS_SAT) { | ||
864 | state->frequency = 950000; | ||
865 | memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_satci_tuna : ini_satfta_tuna), sizeof(ini_satfta_tuna)); | ||
866 | } else if (state->dst_type == DST_TYPE_IS_TERR) { | ||
867 | state->frequency = 137000000; | ||
868 | memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_tvci_tuna : ini_tvfta_tuna), sizeof(ini_tvfta_tuna)); | ||
869 | } else if (state->dst_type == DST_TYPE_IS_CABLE) { | ||
870 | state->frequency = 51000000; | ||
871 | memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_cabci_tuna : ini_cabfta_tuna), sizeof(ini_cabfta_tuna)); | ||
872 | } | ||
873 | |||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status) | ||
878 | { | ||
879 | struct dst_state* state = (struct dst_state*) fe->demodulator_priv; | ||
880 | |||
881 | *status = 0; | ||
882 | if (state->diseq_flags & HAS_LOCK) { | ||
883 | dst_get_signal(state); | ||
884 | if (state->decode_lock) | ||
885 | *status |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI; | ||
886 | } | ||
887 | |||
888 | return 0; | ||
889 | } | ||
890 | |||
891 | static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength) | ||
892 | { | ||
893 | struct dst_state* state = (struct dst_state*) fe->demodulator_priv; | ||
894 | |||
895 | dst_get_signal(state); | ||
896 | *strength = state->decode_strength; | ||
897 | |||
898 | return 0; | ||
899 | } | ||
900 | |||
901 | static int dst_read_snr(struct dvb_frontend* fe, u16* snr) | ||
902 | { | ||
903 | struct dst_state* state = (struct dst_state*) fe->demodulator_priv; | ||
904 | |||
905 | dst_get_signal(state); | ||
906 | *snr = state->decode_snr; | ||
907 | |||
908 | return 0; | ||
909 | } | ||
910 | |||
911 | static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | ||
912 | { | ||
913 | struct dst_state* state = (struct dst_state*) fe->demodulator_priv; | ||
914 | |||
915 | dst_set_freq(state, p->frequency); | ||
916 | dst_set_inversion(state, p->inversion); | ||
917 | if (state->dst_type == DST_TYPE_IS_SAT) { | ||
918 | dst_set_fec(state, p->u.qpsk.fec_inner); | ||
919 | dst_set_symbolrate(state, p->u.qpsk.symbol_rate); | ||
920 | } else if (state->dst_type == DST_TYPE_IS_TERR) { | ||
921 | dst_set_bandwidth(state, p->u.ofdm.bandwidth); | ||
922 | } else if (state->dst_type == DST_TYPE_IS_CABLE) { | ||
923 | dst_set_fec(state, p->u.qam.fec_inner); | ||
924 | dst_set_symbolrate(state, p->u.qam.symbol_rate); | ||
925 | } | ||
926 | dst_write_tuna(fe); | ||
927 | |||
928 | return 0; | ||
929 | } | ||
930 | |||
931 | static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | ||
932 | { | ||
933 | struct dst_state* state = (struct dst_state*) fe->demodulator_priv; | ||
934 | |||
935 | p->frequency = state->decode_freq; | ||
936 | p->inversion = state->inversion; | ||
937 | if (state->dst_type == DST_TYPE_IS_SAT) { | ||
938 | p->u.qpsk.symbol_rate = state->symbol_rate; | ||
939 | p->u.qpsk.fec_inner = dst_get_fec(state); | ||
940 | } else if (state->dst_type == DST_TYPE_IS_TERR) { | ||
941 | p->u.ofdm.bandwidth = state->bandwidth; | ||
942 | } else if (state->dst_type == DST_TYPE_IS_CABLE) { | ||
943 | p->u.qam.symbol_rate = state->symbol_rate; | ||
944 | p->u.qam.fec_inner = dst_get_fec(state); | ||
945 | p->u.qam.modulation = QAM_AUTO; | ||
946 | } | ||
947 | |||
948 | return 0; | ||
949 | } | ||
950 | |||
951 | static void dst_release(struct dvb_frontend* fe) | ||
952 | { | ||
953 | struct dst_state* state = (struct dst_state*) fe->demodulator_priv; | ||
954 | kfree(state); | ||
955 | } | ||
956 | |||
957 | static struct dvb_frontend_ops dst_dvbt_ops; | ||
958 | static struct dvb_frontend_ops dst_dvbs_ops; | ||
959 | static struct dvb_frontend_ops dst_dvbc_ops; | ||
960 | |||
961 | struct dvb_frontend* dst_attach(const struct dst_config* config, | ||
962 | struct i2c_adapter* i2c, | ||
963 | struct bt878 *bt) | ||
964 | { | ||
965 | struct dst_state* state = NULL; | ||
966 | |||
967 | /* allocate memory for the internal state */ | ||
968 | state = (struct dst_state*) kmalloc(sizeof(struct dst_state), GFP_KERNEL); | ||
969 | if (state == NULL) goto error; | ||
970 | |||
971 | /* setup the state */ | ||
972 | state->config = config; | ||
973 | state->i2c = i2c; | ||
974 | state->bt = bt; | ||
975 | |||
976 | /* check if the demod is there */ | ||
977 | if (dst_check_ci(state) < 0) goto error; | ||
978 | |||
979 | /* determine settings based on type */ | ||
980 | switch (state->dst_type) { | ||
981 | case DST_TYPE_IS_TERR: | ||
982 | memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops)); | ||
983 | break; | ||
984 | case DST_TYPE_IS_CABLE: | ||
985 | memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops)); | ||
986 | break; | ||
987 | case DST_TYPE_IS_SAT: | ||
988 | memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops)); | ||
989 | break; | ||
990 | default: | ||
991 | printk("dst: unknown frontend type. please report to the LinuxTV.org DVB mailinglist.\n"); | ||
992 | goto error; | ||
993 | } | ||
994 | |||
995 | /* create dvb_frontend */ | ||
996 | state->frontend.ops = &state->ops; | ||
997 | state->frontend.demodulator_priv = state; | ||
998 | return &state->frontend; | ||
999 | |||
1000 | error: | ||
1001 | kfree(state); | ||
1002 | return NULL; | ||
1003 | } | ||
1004 | |||
1005 | static struct dvb_frontend_ops dst_dvbt_ops = { | ||
1006 | |||
1007 | .info = { | ||
1008 | .name = "DST DVB-T", | ||
1009 | .type = FE_OFDM, | ||
1010 | .frequency_min = 137000000, | ||
1011 | .frequency_max = 858000000, | ||
1012 | .frequency_stepsize = 166667, | ||
1013 | .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | ||
1014 | }, | ||
1015 | |||
1016 | .release = dst_release, | ||
1017 | |||
1018 | .init = dst_init, | ||
1019 | |||
1020 | .set_frontend = dst_set_frontend, | ||
1021 | .get_frontend = dst_get_frontend, | ||
1022 | |||
1023 | .read_status = dst_read_status, | ||
1024 | .read_signal_strength = dst_read_signal_strength, | ||
1025 | .read_snr = dst_read_snr, | ||
1026 | }; | ||
1027 | |||
1028 | static struct dvb_frontend_ops dst_dvbs_ops = { | ||
1029 | |||
1030 | .info = { | ||
1031 | .name = "DST DVB-S", | ||
1032 | .type = FE_QPSK, | ||
1033 | .frequency_min = 950000, | ||
1034 | .frequency_max = 2150000, | ||
1035 | .frequency_stepsize = 1000, /* kHz for QPSK frontends */ | ||
1036 | .frequency_tolerance = 29500, | ||
1037 | .symbol_rate_min = 1000000, | ||
1038 | .symbol_rate_max = 45000000, | ||
1039 | /* . symbol_rate_tolerance = ???,*/ | ||
1040 | .caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK | ||
1041 | }, | ||
1042 | |||
1043 | .release = dst_release, | ||
1044 | |||
1045 | .init = dst_init, | ||
1046 | |||
1047 | .set_frontend = dst_set_frontend, | ||
1048 | .get_frontend = dst_get_frontend, | ||
1049 | |||
1050 | .read_status = dst_read_status, | ||
1051 | .read_signal_strength = dst_read_signal_strength, | ||
1052 | .read_snr = dst_read_snr, | ||
1053 | |||
1054 | .diseqc_send_master_cmd = dst_set_diseqc, | ||
1055 | .set_voltage = dst_set_voltage, | ||
1056 | .set_tone = dst_set_tone, | ||
1057 | }; | ||
1058 | |||
1059 | static struct dvb_frontend_ops dst_dvbc_ops = { | ||
1060 | |||
1061 | .info = { | ||
1062 | .name = "DST DVB-C", | ||
1063 | .type = FE_QAM, | ||
1064 | .frequency_stepsize = 62500, | ||
1065 | .frequency_min = 51000000, | ||
1066 | .frequency_max = 858000000, | ||
1067 | .symbol_rate_min = 1000000, | ||
1068 | .symbol_rate_max = 45000000, | ||
1069 | /* . symbol_rate_tolerance = ???,*/ | ||
1070 | .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | ||
1071 | }, | ||
1072 | |||
1073 | .release = dst_release, | ||
1074 | |||
1075 | .init = dst_init, | ||
1076 | |||
1077 | .set_frontend = dst_set_frontend, | ||
1078 | .get_frontend = dst_get_frontend, | ||
1079 | |||
1080 | .read_status = dst_read_status, | ||
1081 | .read_signal_strength = dst_read_signal_strength, | ||
1082 | .read_snr = dst_read_snr, | ||
1083 | }; | ||
1084 | |||
1085 | MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver"); | ||
1086 | MODULE_AUTHOR("Jamie Honan"); | ||
1087 | MODULE_LICENSE("GPL"); | ||
1088 | |||
1089 | EXPORT_SYMBOL(dst_attach); | ||