]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/media/dvb/bt8xx/dst.c
[PATCH] dvb: Fix 22k tone control
[mirror_ubuntu-hirsute-kernel.git] / drivers / media / dvb / bt8xx / dst.c
CommitLineData
1da177e4 1/*
1da177e4 2
50b215a0
JS
3 Frontend/Card driver for TwinHan DST Frontend
4 Copyright (C) 2003 Jamie Honan
5 Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
1da177e4 6
50b215a0
JS
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
1da177e4 11
50b215a0
JS
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
1da177e4 16
50b215a0
JS
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.
1da177e4
LT
20*/
21
50b215a0 22
1da177e4
LT
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"
50b215a0
JS
34#include "dst_common.h"
35
36
37static unsigned int verbose = 1;
38module_param(verbose, int, 0644);
39MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
40
41static unsigned int debug = 1;
42module_param(debug, int, 0644);
43MODULE_PARM_DESC(debug, "debug messages, default is 0 (yes)");
44
45static unsigned int dst_addons;
46module_param(dst_addons, int, 0644);
4a2cc126 47MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
1da177e4 48
50b215a0 49#define dprintk if (debug) printk
1da177e4
LT
50
51#define HAS_LOCK 1
52#define ATTEMPT_TUNE 2
53#define HAS_POWER 4
54
55static void dst_packsize(struct dst_state* state, int psize)
56{
57 union dst_gpio_packet bits;
58
59 bits.psize = psize;
60 bt878_device_control(state->bt, DST_IG_TS, &bits);
61}
62
50b215a0 63int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int delay)
1da177e4
LT
64{
65 union dst_gpio_packet enb;
66 union dst_gpio_packet bits;
67 int err;
68
69 enb.enb.mask = mask;
70 enb.enb.enable = enbb;
50b215a0
JS
71 if (verbose > 4)
72 dprintk("%s: mask=[%04x], enbb=[%04x], outhigh=[%04x]\n", __FUNCTION__, mask, enbb, outhigh);
73
1da177e4 74 if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) {
50b215a0 75 dprintk("%s: dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)\n", __FUNCTION__, err, mask, enbb);
1da177e4
LT
76 return -EREMOTEIO;
77 }
8385e46f 78 udelay(1000);
1da177e4
LT
79 /* because complete disabling means no output, no need to do output packet */
80 if (enbb == 0)
81 return 0;
82
50b215a0
JS
83 if (delay)
84 msleep(10);
85
1da177e4
LT
86 bits.outp.mask = enbb;
87 bits.outp.highvals = outhigh;
88
89 if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) {
50b215a0 90 dprintk("%s: dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)\n", __FUNCTION__, err, enbb, outhigh);
1da177e4
LT
91 return -EREMOTEIO;
92 }
93 return 0;
94}
50b215a0 95EXPORT_SYMBOL(dst_gpio_outb);
1da177e4 96
50b215a0 97int dst_gpio_inb(struct dst_state *state, u8 * result)
1da177e4
LT
98{
99 union dst_gpio_packet rd_packet;
100 int err;
101
102 *result = 0;
103
104 if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
105 dprintk("%s: dst_gpio_inb error (err == %i)\n", __FUNCTION__, err);
106 return -EREMOTEIO;
107 }
108
109 *result = (u8) rd_packet.rd.value;
110 return 0;
111}
50b215a0 112EXPORT_SYMBOL(dst_gpio_inb);
1da177e4 113
50b215a0 114int rdc_reset_state(struct dst_state *state)
1da177e4 115{
50b215a0
JS
116 if (verbose > 1)
117 dprintk("%s: Resetting state machine\n", __FUNCTION__);
118
119 if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) {
120 dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
121 return -1;
122 }
123
1da177e4 124 msleep(10);
50b215a0
JS
125
126 if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, NO_DELAY) < 0) {
127 dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
128 msleep(10);
129 return -1;
130 }
131
1da177e4
LT
132 return 0;
133}
50b215a0 134EXPORT_SYMBOL(rdc_reset_state);
1da177e4 135
50b215a0 136int rdc_8820_reset(struct dst_state *state)
1da177e4 137{
50b215a0
JS
138 if (verbose > 1)
139 dprintk("%s: Resetting DST\n", __FUNCTION__);
140
141 if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) {
142 dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
143 return -1;
144 }
8385e46f 145 udelay(1000);
50b215a0
JS
146 if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, RDC_8820_RESET, DELAY) < 0) {
147 dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
148 return -1;
149 }
150
1da177e4
LT
151 return 0;
152}
50b215a0 153EXPORT_SYMBOL(rdc_8820_reset);
1da177e4 154
50b215a0 155int dst_pio_enable(struct dst_state *state)
1da177e4 156{
50b215a0
JS
157 if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {
158 dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
159 return -1;
160 }
8385e46f 161 udelay(1000);
50b215a0
JS
162 return 0;
163}
164EXPORT_SYMBOL(dst_pio_enable);
165
166int dst_pio_disable(struct dst_state *state)
167{
168 if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) {
169 dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
170 return -1;
171 }
8385e46f
JS
172 if (state->type_flags & DST_TYPE_HAS_FW_1)
173 udelay(1000);
50b215a0 174
1da177e4
LT
175 return 0;
176}
50b215a0 177EXPORT_SYMBOL(dst_pio_disable);
1da177e4 178
50b215a0 179int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode)
1da177e4
LT
180{
181 u8 reply;
1da177e4 182 int i;
50b215a0 183
1da177e4 184 for (i = 0; i < 200; i++) {
50b215a0
JS
185 if (dst_gpio_inb(state, &reply) < 0) {
186 dprintk("%s: dst_gpio_inb ERROR !\n", __FUNCTION__);
187 return -1;
188 }
189
190 if ((reply & RDC_8820_PIO_0_ENABLE) == 0) {
191 if (verbose > 4)
192 dprintk("%s: dst wait ready after %d\n", __FUNCTION__, i);
1da177e4
LT
193 return 1;
194 }
b46dd445 195 msleep(10);
50b215a0
JS
196 }
197 if (verbose > 1)
198 dprintk("%s: dst wait NOT ready after %d\n", __FUNCTION__, i);
199
200 return 0;
201}
202EXPORT_SYMBOL(dst_wait_dst_ready);
203
204int dst_error_recovery(struct dst_state *state)
205{
206 dprintk("%s: Trying to return from previous errors...\n", __FUNCTION__);
207 dst_pio_disable(state);
208 msleep(10);
209 dst_pio_enable(state);
210 msleep(10);
211
212 return 0;
213}
214EXPORT_SYMBOL(dst_error_recovery);
215
216int dst_error_bailout(struct dst_state *state)
217{
218 dprintk("%s: Trying to bailout from previous error...\n", __FUNCTION__);
219 rdc_8820_reset(state);
220 dst_pio_disable(state);
221 msleep(10);
222
223 return 0;
224}
225EXPORT_SYMBOL(dst_error_bailout);
226
227
228int dst_comm_init(struct dst_state* state)
229{
230 if (verbose > 1)
231 dprintk ("%s: Initializing DST..\n", __FUNCTION__);
232 if ((dst_pio_enable(state)) < 0) {
233 dprintk("%s: PIO Enable Failed.\n", __FUNCTION__);
234 return -1;
235 }
236 if ((rdc_reset_state(state)) < 0) {
237 dprintk("%s: RDC 8820 State RESET Failed.\n", __FUNCTION__);
238 return -1;
1da177e4 239 }
8385e46f
JS
240 if (state->type_flags & DST_TYPE_HAS_FW_1)
241 msleep(100);
242 else
243 msleep(5);
244
1da177e4
LT
245 return 0;
246}
50b215a0 247EXPORT_SYMBOL(dst_comm_init);
1da177e4 248
50b215a0
JS
249
250int write_dst(struct dst_state *state, u8 *data, u8 len)
1da177e4
LT
251{
252 struct i2c_msg msg = {
253 .addr = state->config->demod_address,.flags = 0,.buf = data,.len = len
254 };
50b215a0 255
1da177e4
LT
256 int err;
257 int cnt;
50b215a0 258 if (debug && (verbose > 4)) {
1da177e4 259 u8 i;
50b215a0
JS
260 if (verbose > 4) {
261 dprintk("%s writing", __FUNCTION__);
262 for (i = 0; i < len; i++)
263 dprintk(" %02x", data[i]);
264 dprintk("\n");
1da177e4 265 }
1da177e4 266 }
50b215a0 267 for (cnt = 0; cnt < 2; cnt++) {
1da177e4 268 if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
50b215a0
JS
269 dprintk("%s: _write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, data[0]);
270 dst_error_recovery(state);
1da177e4
LT
271 continue;
272 } else
273 break;
274 }
50b215a0
JS
275
276 if (cnt >= 2) {
277 if (verbose > 1)
278 printk("%s: RDC 8820 RESET...\n", __FUNCTION__);
279 dst_error_bailout(state);
280
281 return -1;
282 }
283
1da177e4
LT
284 return 0;
285}
50b215a0 286EXPORT_SYMBOL(write_dst);
1da177e4 287
50b215a0 288int read_dst(struct dst_state *state, u8 * ret, u8 len)
1da177e4
LT
289{
290 struct i2c_msg msg = {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = ret,.len = len };
291 int err;
292 int cnt;
293
50b215a0 294 for (cnt = 0; cnt < 2; cnt++) {
1da177e4 295 if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
50b215a0 296
1da177e4 297 dprintk("%s: read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, ret[0]);
50b215a0
JS
298 dst_error_recovery(state);
299
1da177e4
LT
300 continue;
301 } else
302 break;
303 }
50b215a0
JS
304 if (cnt >= 2) {
305 if (verbose > 1)
306 printk("%s: RDC 8820 RESET...\n", __FUNCTION__);
307 dst_error_bailout(state);
308
309 return -1;
310 }
311 if (debug && (verbose > 4)) {
312 dprintk("%s reply is 0x%x\n", __FUNCTION__, ret[0]);
1da177e4
LT
313 for (err = 1; err < len; err++)
314 dprintk(" 0x%x", ret[err]);
315 if (err > 1)
316 dprintk("\n");
317 }
50b215a0 318
1da177e4
LT
319 return 0;
320}
50b215a0 321EXPORT_SYMBOL(read_dst);
1da177e4
LT
322
323static int dst_set_freq(struct dst_state *state, u32 freq)
324{
325 u8 *val;
326
327 state->frequency = freq;
8385e46f
JS
328 if (debug > 4)
329 dprintk("%s: set Frequency %u\n", __FUNCTION__, freq);
1da177e4 330
1da177e4
LT
331 if (state->dst_type == DST_TYPE_IS_SAT) {
332 freq = freq / 1000;
333 if (freq < 950 || freq > 2150)
334 return -EINVAL;
335 val = &state->tx_tuna[0];
336 val[2] = (freq >> 8) & 0x7f;
337 val[3] = (u8) freq;
338 val[4] = 1;
339 val[8] &= ~4;
340 if (freq < 1531)
341 val[8] |= 4;
342 } else if (state->dst_type == DST_TYPE_IS_TERR) {
343 freq = freq / 1000;
344 if (freq < 137000 || freq > 858000)
345 return -EINVAL;
346 val = &state->tx_tuna[0];
347 val[2] = (freq >> 16) & 0xff;
348 val[3] = (freq >> 8) & 0xff;
349 val[4] = (u8) freq;
350 val[5] = 0;
351 switch (state->bandwidth) {
352 case BANDWIDTH_6_MHZ:
353 val[6] = 6;
354 break;
355
356 case BANDWIDTH_7_MHZ:
357 case BANDWIDTH_AUTO:
358 val[6] = 7;
359 break;
360
361 case BANDWIDTH_8_MHZ:
362 val[6] = 8;
363 break;
364 }
365
366 val[7] = 0;
367 val[8] = 0;
368 } else if (state->dst_type == DST_TYPE_IS_CABLE) {
369 /* guess till will get one */
370 freq = freq / 1000;
371 val = &state->tx_tuna[0];
372 val[2] = (freq >> 16) & 0xff;
373 val[3] = (freq >> 8) & 0xff;
374 val[4] = (u8) freq;
375 } else
376 return -EINVAL;
377 return 0;
378}
379
380static int dst_set_bandwidth(struct dst_state* state, fe_bandwidth_t bandwidth)
381{
382 u8 *val;
383
384 state->bandwidth = bandwidth;
385
386 if (state->dst_type != DST_TYPE_IS_TERR)
387 return 0;
388
389 val = &state->tx_tuna[0];
390 switch (bandwidth) {
391 case BANDWIDTH_6_MHZ:
392 val[6] = 6;
393 break;
394
395 case BANDWIDTH_7_MHZ:
396 val[6] = 7;
397 break;
398
399 case BANDWIDTH_8_MHZ:
400 val[6] = 8;
401 break;
402
403 default:
404 return -EINVAL;
405 }
406 return 0;
407}
408
409static int dst_set_inversion(struct dst_state* state, fe_spectral_inversion_t inversion)
410{
411 u8 *val;
412
413 state->inversion = inversion;
414
415 val = &state->tx_tuna[0];
416
417 val[8] &= ~0x80;
418
419 switch (inversion) {
420 case INVERSION_OFF:
421 break;
422 case INVERSION_ON:
423 val[8] |= 0x80;
424 break;
425 default:
426 return -EINVAL;
427 }
428 return 0;
429}
430
431static int dst_set_fec(struct dst_state* state, fe_code_rate_t fec)
432{
433 state->fec = fec;
434 return 0;
435}
436
437static fe_code_rate_t dst_get_fec(struct dst_state* state)
438{
439 return state->fec;
440}
441
442static int dst_set_symbolrate(struct dst_state* state, u32 srate)
443{
444 u8 *val;
445 u32 symcalc;
446 u64 sval;
447
448 state->symbol_rate = srate;
449
450 if (state->dst_type == DST_TYPE_IS_TERR) {
451 return 0;
452 }
8385e46f
JS
453 if (debug > 4)
454 dprintk("%s: set symrate %u\n", __FUNCTION__, srate);
1da177e4
LT
455 srate /= 1000;
456 val = &state->tx_tuna[0];
457
458 if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
459 sval = srate;
460 sval <<= 20;
461 do_div(sval, 88000);
462 symcalc = (u32) sval;
8385e46f
JS
463
464 if (debug > 4)
465 dprintk("%s: set symcalc %u\n", __FUNCTION__, symcalc);
466
1da177e4
LT
467 val[5] = (u8) (symcalc >> 12);
468 val[6] = (u8) (symcalc >> 4);
469 val[7] = (u8) (symcalc << 4);
470 } else {
471 val[5] = (u8) (srate >> 16) & 0x7f;
472 val[6] = (u8) (srate >> 8);
473 val[7] = (u8) srate;
474 }
475 val[8] &= ~0x20;
476 if (srate > 8000)
477 val[8] |= 0x20;
478 return 0;
479}
480
50b215a0 481u8 dst_check_sum(u8 * buf, u32 len)
1da177e4
LT
482{
483 u32 i;
484 u8 val = 0;
485 if (!len)
486 return 0;
487 for (i = 0; i < len; i++) {
488 val += buf[i];
489 }
490 return ((~val) + 1);
491}
50b215a0 492EXPORT_SYMBOL(dst_check_sum);
1da177e4
LT
493
494static void dst_type_flags_print(u32 type_flags)
495{
496 printk("DST type flags :");
497 if (type_flags & DST_TYPE_HAS_NEWTUNE)
498 printk(" 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
499 if (type_flags & DST_TYPE_HAS_TS204)
500 printk(" 0x%x ts204", DST_TYPE_HAS_TS204);
501 if (type_flags & DST_TYPE_HAS_SYMDIV)
502 printk(" 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
50b215a0
JS
503 if (type_flags & DST_TYPE_HAS_FW_1)
504 printk(" 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
505 if (type_flags & DST_TYPE_HAS_FW_2)
506 printk(" 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
507 if (type_flags & DST_TYPE_HAS_FW_3)
508 printk(" 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
8385e46f 509// if ((type_flags & DST_TYPE_HAS_FW_BUILD) && new_fw)
50b215a0 510
1da177e4
LT
511 printk("\n");
512}
513
50b215a0
JS
514
515static int dst_type_print (u8 type)
1da177e4
LT
516{
517 char *otype;
518 switch (type) {
519 case DST_TYPE_IS_SAT:
520 otype = "satellite";
521 break;
50b215a0 522
1da177e4
LT
523 case DST_TYPE_IS_TERR:
524 otype = "terrestrial";
525 break;
50b215a0 526
1da177e4
LT
527 case DST_TYPE_IS_CABLE:
528 otype = "cable";
529 break;
50b215a0 530
1da177e4
LT
531 default:
532 printk("%s: invalid dst type %d\n", __FUNCTION__, type);
533 return -EINVAL;
534 }
535 printk("DST type : %s\n", otype);
50b215a0 536
1da177e4
LT
537 return 0;
538}
539
50b215a0
JS
540/*
541 Known cards list
542 Satellite
543 -------------------
e6ac699a 544 200103A
50b215a0
JS
545 VP-1020 DST-MOT LG(old), TS=188
546
547 VP-1020 DST-03T LG(new), TS=204
548 VP-1022 DST-03T LG(new), TS=204
549 VP-1025 DST-03T LG(new), TS=204
550
551 VP-1030 DSTMCI, LG(new), TS=188
552 VP-1032 DSTMCI, LG(new), TS=188
553
554 Cable
555 -------------------
556 VP-2030 DCT-CI, Samsung, TS=204
557 VP-2021 DCT-CI, Unknown, TS=204
558 VP-2031 DCT-CI, Philips, TS=188
559 VP-2040 DCT-CI, Philips, TS=188, with CA daughter board
560 VP-2040 DCT-CI, Philips, TS=204, without CA daughter board
561
562 Terrestrial
563 -------------------
564 VP-3050 DTTNXT TS=188
565 VP-3040 DTT-CI, Philips, TS=188
566 VP-3040 DTT-CI, Philips, TS=204
567
568 ATSC
569 -------------------
570 VP-3220 ATSCDI, TS=188
571 VP-3250 ATSCAD, TS=188
572
573*/
574
575struct dst_types dst_tlist[] = {
e6ac699a
JS
576 {
577 .device_id = "200103A",
578 .offset = 0,
579 .dst_type = DST_TYPE_IS_SAT,
580 .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
581 .dst_feature = 0
582 }, /* obsolete */
583
50b215a0
JS
584 {
585 .device_id = "DST-020",
586 .offset = 0,
587 .dst_type = DST_TYPE_IS_SAT,
588 .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
589 .dst_feature = 0
590 }, /* obsolete */
591
592 {
593 .device_id = "DST-030",
594 .offset = 0,
595 .dst_type = DST_TYPE_IS_SAT,
596 .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
597 .dst_feature = 0
598 }, /* obsolete */
599
600 {
601 .device_id = "DST-03T",
602 .offset = 0,
603 .dst_type = DST_TYPE_IS_SAT,
604 .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
605 .dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
606 | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO
607 },
608
609 {
610 .device_id = "DST-MOT",
611 .offset = 0,
612 .dst_type = DST_TYPE_IS_SAT,
613 .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
614 .dst_feature = 0
615 }, /* obsolete */
616
617 {
618 .device_id = "DST-CI",
619 .offset = 1,
620 .dst_type = DST_TYPE_IS_SAT,
621 .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
622 .dst_feature = DST_TYPE_HAS_CA
8385e46f 623 }, /* An OEM board */
50b215a0
JS
624
625 {
626 .device_id = "DSTMCI",
627 .offset = 1,
628 .dst_type = DST_TYPE_IS_SAT,
8385e46f 629 .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
50b215a0
JS
630 .dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
631 | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC
632 },
633
634 {
635 .device_id = "DSTFCI",
636 .offset = 1,
637 .dst_type = DST_TYPE_IS_SAT,
638 .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
639 .dst_feature = 0
640 }, /* unknown to vendor */
641
642 {
643 .device_id = "DCT-CI",
644 .offset = 1,
645 .dst_type = DST_TYPE_IS_CABLE,
8385e46f
JS
646 .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1
647 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
50b215a0
JS
648 .dst_feature = DST_TYPE_HAS_CA
649 },
650
651 {
652 .device_id = "DCTNEW",
653 .offset = 1,
654 .dst_type = DST_TYPE_IS_CABLE,
655 .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3,
656 .dst_feature = 0
657 },
658
659 {
660 .device_id = "DTT-CI",
661 .offset = 1,
662 .dst_type = DST_TYPE_IS_TERR,
8385e46f 663 .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
50b215a0
JS
664 .dst_feature = 0
665 },
666
667 {
668 .device_id = "DTTDIG",
669 .offset = 1,
670 .dst_type = DST_TYPE_IS_TERR,
671 .type_flags = DST_TYPE_HAS_FW_2,
672 .dst_feature = 0
673 },
674
675 {
676 .device_id = "DTTNXT",
677 .offset = 1,
678 .dst_type = DST_TYPE_IS_TERR,
679 .type_flags = DST_TYPE_HAS_FW_2,
680 .dst_feature = DST_TYPE_HAS_ANALOG
681 },
682
683 {
684 .device_id = "ATSCDI",
685 .offset = 1,
686 .dst_type = DST_TYPE_IS_ATSC,
687 .type_flags = DST_TYPE_HAS_FW_2,
688 .dst_feature = 0
689 },
690
691 {
692 .device_id = "ATSCAD",
693 .offset = 1,
694 .dst_type = DST_TYPE_IS_ATSC,
695 .type_flags = DST_TYPE_HAS_FW_2,
696 .dst_feature = 0
697 },
698
699 { }
700
701};
702
703
704static int dst_get_device_id(struct dst_state *state)
1da177e4 705{
50b215a0
JS
706 u8 reply;
707
1da177e4 708 int i;
50b215a0
JS
709 struct dst_types *p_dst_type;
710 u8 use_dst_type = 0;
711 u32 use_type_flags = 0;
1da177e4 712
50b215a0 713 static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
1da177e4 714
50b215a0
JS
715 device_type[7] = dst_check_sum(device_type, 7);
716
717 if (write_dst(state, device_type, FIXED_COMM))
718 return -1; /* Write failed */
719
720 if ((dst_pio_disable(state)) < 0)
721 return -1;
722
723 if (read_dst(state, &reply, GET_ACK))
724 return -1; /* Read failure */
725
726 if (reply != ACK) {
727 dprintk("%s: Write not Acknowledged! [Reply=0x%02x]\n", __FUNCTION__, reply);
728 return -1; /* Unack'd write */
1da177e4 729 }
50b215a0
JS
730
731 if (!dst_wait_dst_ready(state, DEVICE_INIT))
732 return -1; /* DST not ready yet */
733
734 if (read_dst(state, state->rxbuffer, FIXED_COMM))
735 return -1;
736
737 dst_pio_disable(state);
738
739 if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
740 dprintk("%s: Checksum failure! \n", __FUNCTION__);
741 return -1; /* Checksum failure */
1da177e4 742 }
50b215a0
JS
743
744 state->rxbuffer[7] = '\0';
745
746 for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE (dst_tlist); i++, p_dst_type++) {
747 if (!strncmp (&state->rxbuffer[p_dst_type->offset], p_dst_type->device_id, strlen (p_dst_type->device_id))) {
748 use_type_flags = p_dst_type->type_flags;
749 use_dst_type = p_dst_type->dst_type;
750
751 /* Card capabilities */
752 state->dst_hw_cap = p_dst_type->dst_feature;
753 printk ("%s: Recognise [%s]\n", __FUNCTION__, p_dst_type->device_id);
754
1da177e4
LT
755 break;
756 }
757 }
50b215a0
JS
758
759 if (i >= sizeof (dst_tlist) / sizeof (dst_tlist [0])) {
760 printk("%s: Unable to recognize %s or %s\n", __FUNCTION__, &state->rxbuffer[0], &state->rxbuffer[1]);
761 printk("%s: please email linux-dvb@linuxtv.org with this type in\n", __FUNCTION__);
1da177e4
LT
762 use_dst_type = DST_TYPE_IS_SAT;
763 use_type_flags = DST_TYPE_HAS_SYMDIV;
764 }
1da177e4 765
50b215a0 766 dst_type_print(use_dst_type);
1da177e4
LT
767 state->type_flags = use_type_flags;
768 state->dst_type = use_dst_type;
769 dst_type_flags_print(state->type_flags);
770
771 if (state->type_flags & DST_TYPE_HAS_TS204) {
772 dst_packsize(state, 204);
773 }
50b215a0 774
1da177e4
LT
775 return 0;
776}
777
50b215a0
JS
778static int dst_probe(struct dst_state *state)
779{
780 if ((rdc_8820_reset(state)) < 0) {
781 dprintk("%s: RDC 8820 RESET Failed.\n", __FUNCTION__);
782 return -1;
783 }
4a2cc126
JS
784 if (dst_addons & DST_TYPE_HAS_CA)
785 msleep(4000);
786 else
787 msleep(100);
788
50b215a0
JS
789 if ((dst_comm_init(state)) < 0) {
790 dprintk("%s: DST Initialization Failed.\n", __FUNCTION__);
791 return -1;
792 }
8385e46f 793 msleep(100);
50b215a0
JS
794 if (dst_get_device_id(state) < 0) {
795 dprintk("%s: unknown device.\n", __FUNCTION__);
796 return -1;
797 }
798
799 return 0;
800}
801
802int dst_command(struct dst_state* state, u8 * data, u8 len)
1da177e4 803{
1da177e4 804 u8 reply;
50b215a0
JS
805 if ((dst_comm_init(state)) < 0) {
806 dprintk("%s: DST Communication Initialization Failed.\n", __FUNCTION__);
807 return -1;
808 }
1da177e4 809
50b215a0
JS
810 if (write_dst(state, data, len)) {
811 if (verbose > 1)
812 dprintk("%s: Tring to recover.. \n", __FUNCTION__);
813 if ((dst_error_recovery(state)) < 0) {
814 dprintk("%s: Recovery Failed.\n", __FUNCTION__);
815 return -1;
816 }
817 return -1;
1da177e4 818 }
50b215a0
JS
819 if ((dst_pio_disable(state)) < 0) {
820 dprintk("%s: PIO Disable Failed.\n", __FUNCTION__);
821 return -1;
1da177e4 822 }
8385e46f
JS
823 if (state->type_flags & DST_TYPE_HAS_FW_1)
824 udelay(3000);
50b215a0
JS
825
826 if (read_dst(state, &reply, GET_ACK)) {
827 if (verbose > 1)
828 dprintk("%s: Trying to recover.. \n", __FUNCTION__);
829 if ((dst_error_recovery(state)) < 0) {
830 dprintk("%s: Recovery Failed.\n", __FUNCTION__);
831 return -1;
832 }
833 return -1;
834 }
835
836 if (reply != ACK) {
837 dprintk("%s: write not acknowledged 0x%02x \n", __FUNCTION__, reply);
838 return -1;
1da177e4
LT
839 }
840 if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
841 return 0;
8385e46f
JS
842
843// udelay(3000);
844 if (state->type_flags & DST_TYPE_HAS_FW_1)
845 udelay(3000);
846 else
847 udelay(2000);
848
50b215a0
JS
849 if (!dst_wait_dst_ready(state, NO_DELAY))
850 return -1;
851
852 if (read_dst(state, state->rxbuffer, FIXED_COMM)) {
853 if (verbose > 1)
854 dprintk("%s: Trying to recover.. \n", __FUNCTION__);
855 if ((dst_error_recovery(state)) < 0) {
856 dprintk("%s: Recovery failed.\n", __FUNCTION__);
857 return -1;
858 }
859 return -1;
1da177e4 860 }
50b215a0 861
1da177e4
LT
862 if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
863 dprintk("%s: checksum failure\n", __FUNCTION__);
50b215a0 864 return -1;
1da177e4 865 }
50b215a0 866
1da177e4
LT
867 return 0;
868}
50b215a0 869EXPORT_SYMBOL(dst_command);
1da177e4
LT
870
871static int dst_get_signal(struct dst_state* state)
872{
873 int retval;
874 u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
875
876 if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
877 state->decode_lock = state->decode_strength = state->decode_snr = 0;
878 return 0;
879 }
880 if (0 == (state->diseq_flags & HAS_LOCK)) {
881 state->decode_lock = state->decode_strength = state->decode_snr = 0;
882 return 0;
883 }
884 if (time_after_eq(jiffies, state->cur_jiff + (HZ / 5))) {
885 retval = dst_command(state, get_signal, 8);
886 if (retval < 0)
887 return retval;
888 if (state->dst_type == DST_TYPE_IS_SAT) {
889 state->decode_lock = ((state->rxbuffer[6] & 0x10) == 0) ? 1 : 0;
890 state->decode_strength = state->rxbuffer[5] << 8;
891 state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
892 } else if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE)) {
893 state->decode_lock = (state->rxbuffer[1]) ? 1 : 0;
894 state->decode_strength = state->rxbuffer[4] << 8;
895 state->decode_snr = state->rxbuffer[3] << 8;
896 }
897 state->cur_jiff = jiffies;
898 }
899 return 0;
900}
901
902static int dst_tone_power_cmd(struct dst_state* state)
903{
904 u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 };
905
906 if (state->dst_type == DST_TYPE_IS_TERR)
907 return 0;
908
8f6da8f1 909 paket[4] = state->tx_tuna[4];
86360a3e 910 paket[2] = state->tx_tuna[2];
203fe8b3 911 paket[3] = state->tx_tuna[3];
50b215a0 912 paket[7] = dst_check_sum (paket, 7);
1da177e4 913 dst_command(state, paket, 8);
203fe8b3 914
1da177e4
LT
915 return 0;
916}
917
918static int dst_get_tuna(struct dst_state* state)
919{
920 int retval;
50b215a0 921
1da177e4
LT
922 if ((state->diseq_flags & ATTEMPT_TUNE) == 0)
923 return 0;
50b215a0 924
1da177e4 925 state->diseq_flags &= ~(HAS_LOCK);
50b215a0 926 if (!dst_wait_dst_ready(state, NO_DELAY))
1da177e4 927 return 0;
50b215a0 928
1da177e4
LT
929 if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
930 /* how to get variable length reply ???? */
931 retval = read_dst(state, state->rx_tuna, 10);
932 } else {
50b215a0 933 retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
1da177e4 934 }
50b215a0 935
1da177e4
LT
936 if (retval < 0) {
937 dprintk("%s: read not successful\n", __FUNCTION__);
938 return 0;
939 }
50b215a0 940
1da177e4
LT
941 if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
942 if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
943 dprintk("%s: checksum failure?\n", __FUNCTION__);
944 return 0;
945 }
946 } else {
947 if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) {
948 dprintk("%s: checksum failure?\n", __FUNCTION__);
949 return 0;
950 }
951 }
952 if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0)
953 return 0;
954 state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3];
955
956 state->decode_lock = 1;
957 /*
958 dst->decode_n1 = (dst->rx_tuna[4] << 8) +
959 (dst->rx_tuna[5]);
960
961 dst->decode_n2 = (dst->rx_tuna[8] << 8) +
962 (dst->rx_tuna[7]);
963 */
964 state->diseq_flags |= HAS_LOCK;
965 /* dst->cur_jiff = jiffies; */
966 return 1;
967}
968
969static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
970
971static int dst_write_tuna(struct dvb_frontend* fe)
972{
0eac3e48 973 struct dst_state* state = fe->demodulator_priv;
1da177e4
LT
974 int retval;
975 u8 reply;
976
8385e46f
JS
977 if (debug > 4)
978 dprintk("%s: type_flags 0x%x \n", __FUNCTION__, state->type_flags);
979
1da177e4
LT
980 state->decode_freq = 0;
981 state->decode_lock = state->decode_strength = state->decode_snr = 0;
982 if (state->dst_type == DST_TYPE_IS_SAT) {
983 if (!(state->diseq_flags & HAS_POWER))
984 dst_set_voltage(fe, SEC_VOLTAGE_13);
985 }
986 state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
50b215a0
JS
987
988 if ((dst_comm_init(state)) < 0) {
989 dprintk("%s: DST Communication initialization failed.\n", __FUNCTION__);
990 return -1;
991 }
992
1da177e4 993 if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
1da177e4
LT
994 state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
995 retval = write_dst(state, &state->tx_tuna[0], 10);
50b215a0 996
1da177e4
LT
997 } else {
998 state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7);
50b215a0 999 retval = write_dst(state, &state->tx_tuna[2], FIXED_COMM);
1da177e4
LT
1000 }
1001 if (retval < 0) {
50b215a0 1002 dst_pio_disable(state);
1da177e4
LT
1003 dprintk("%s: write not successful\n", __FUNCTION__);
1004 return retval;
1005 }
50b215a0
JS
1006
1007 if ((dst_pio_disable(state)) < 0) {
1008 dprintk("%s: DST PIO disable failed !\n", __FUNCTION__);
1009 return -1;
1010 }
1011
1012 if ((read_dst(state, &reply, GET_ACK) < 0)) {
1013 dprintk("%s: read verify not successful.\n", __FUNCTION__);
1014 return -1;
1da177e4 1015 }
50b215a0
JS
1016 if (reply != ACK) {
1017 dprintk("%s: write not acknowledged 0x%02x \n", __FUNCTION__, reply);
1da177e4
LT
1018 return 0;
1019 }
1020 state->diseq_flags |= ATTEMPT_TUNE;
50b215a0 1021
1da177e4
LT
1022 return dst_get_tuna(state);
1023}
1024
1025/*
1026 * line22k0 0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00
1027 * line22k1 0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00
1028 * line22k2 0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00
1029 * tone 0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00
1030 * data 0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00
1031 * power_off 0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
1032 * power_on 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00
1033 * Diseqc 1 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec
1034 * Diseqc 2 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8
1035 * Diseqc 3 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4
1036 * Diseqc 4 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0
1037 */
1038
1039static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
1040{
0eac3e48 1041 struct dst_state* state = fe->demodulator_priv;
1da177e4
LT
1042 u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
1043
1044 if (state->dst_type == DST_TYPE_IS_TERR)
1045 return 0;
1046
1047 if (cmd->msg_len == 0 || cmd->msg_len > 4)
1048 return -EINVAL;
1049 memcpy(&paket[3], cmd->msg, cmd->msg_len);
1050 paket[7] = dst_check_sum(&paket[0], 7);
1051 dst_command(state, paket, 8);
1052 return 0;
1053}
1054
1055static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
1056{
1da177e4 1057 int need_cmd;
0eac3e48 1058 struct dst_state* state = fe->demodulator_priv;
1da177e4
LT
1059
1060 state->voltage = voltage;
1061
1062 if (state->dst_type == DST_TYPE_IS_TERR)
1063 return 0;
1064
1065 need_cmd = 0;
1da177e4 1066 switch (voltage) {
8f6da8f1
MA
1067 case SEC_VOLTAGE_13:
1068 case SEC_VOLTAGE_18:
1069 if ((state->diseq_flags & HAS_POWER) == 0)
1070 need_cmd = 1;
1071 state->diseq_flags |= HAS_POWER;
1072 state->tx_tuna[4] = 0x01;
1073 break;
50b215a0 1074
8f6da8f1 1075 case SEC_VOLTAGE_OFF:
1da177e4 1076 need_cmd = 1;
8f6da8f1
MA
1077 state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
1078 state->tx_tuna[4] = 0x00;
1079 break;
50b215a0 1080
8f6da8f1
MA
1081 default:
1082 return -EINVAL;
1da177e4 1083 }
50b215a0 1084 if (need_cmd)
1da177e4 1085 dst_tone_power_cmd(state);
50b215a0 1086
1da177e4
LT
1087 return 0;
1088}
1089
1090static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1091{
0eac3e48 1092 struct dst_state* state = fe->demodulator_priv;
1da177e4
LT
1093
1094 state->tone = tone;
1095
1096 if (state->dst_type == DST_TYPE_IS_TERR)
1097 return 0;
1098
1da177e4 1099 switch (tone) {
86360a3e
MA
1100 case SEC_TONE_OFF:
1101 state->tx_tuna[2] = 0xff;
1102 break;
50b215a0 1103
86360a3e
MA
1104 case SEC_TONE_ON:
1105 state->tx_tuna[2] = 0x02;
1106 break;
50b215a0 1107
86360a3e
MA
1108 default:
1109 return -EINVAL;
1da177e4
LT
1110 }
1111 dst_tone_power_cmd(state);
50b215a0 1112
1da177e4
LT
1113 return 0;
1114}
1115
203fe8b3
MA
1116static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
1117{
1118 struct dst_state *state = fe->demodulator_priv;
1119
1120 if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE))
1121 return 0;
1122
1123 state->minicmd = minicmd;
1124
1125 switch (minicmd) {
1126 case SEC_MINI_A:
1127 state->tx_tuna[3] = 0x02;
1128 break;
1129 case SEC_MINI_B:
1130 state->tx_tuna[3] = 0xff;
1131 break;
1132 }
1133 dst_tone_power_cmd(state);
1134
1135 return 0;
1136}
1137
1138
1da177e4
LT
1139static int dst_init(struct dvb_frontend* fe)
1140{
0eac3e48 1141 struct dst_state* state = fe->demodulator_priv;
1da177e4
LT
1142 static u8 ini_satci_tuna[] = { 9, 0, 3, 0xb6, 1, 0, 0x73, 0x21, 0, 0 };
1143 static u8 ini_satfta_tuna[] = { 0, 0, 3, 0xb6, 1, 0x55, 0xbd, 0x50, 0, 0 };
1144 static u8 ini_tvfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
1145 static u8 ini_tvci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
1146 static u8 ini_cabfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
1147 static u8 ini_cabci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
1148 state->inversion = INVERSION_ON;
1149 state->voltage = SEC_VOLTAGE_13;
1150 state->tone = SEC_TONE_OFF;
1151 state->symbol_rate = 29473000;
1152 state->fec = FEC_AUTO;
1153 state->diseq_flags = 0;
1154 state->k22 = 0x02;
1155 state->bandwidth = BANDWIDTH_7_MHZ;
1156 state->cur_jiff = jiffies;
1157 if (state->dst_type == DST_TYPE_IS_SAT) {
1158 state->frequency = 950000;
1159 memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_satci_tuna : ini_satfta_tuna), sizeof(ini_satfta_tuna));
1160 } else if (state->dst_type == DST_TYPE_IS_TERR) {
1161 state->frequency = 137000000;
1162 memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_tvci_tuna : ini_tvfta_tuna), sizeof(ini_tvfta_tuna));
1163 } else if (state->dst_type == DST_TYPE_IS_CABLE) {
1164 state->frequency = 51000000;
1165 memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_cabci_tuna : ini_cabfta_tuna), sizeof(ini_cabfta_tuna));
1166 }
1167
1168 return 0;
1169}
1170
1171static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status)
1172{
0eac3e48 1173 struct dst_state* state = fe->demodulator_priv;
1da177e4
LT
1174
1175 *status = 0;
1176 if (state->diseq_flags & HAS_LOCK) {
1177 dst_get_signal(state);
1178 if (state->decode_lock)
1179 *status |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI;
1180 }
1181
1182 return 0;
1183}
1184
1185static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength)
1186{
0eac3e48 1187 struct dst_state* state = fe->demodulator_priv;
1da177e4
LT
1188
1189 dst_get_signal(state);
1190 *strength = state->decode_strength;
1191
1192 return 0;
1193}
1194
1195static int dst_read_snr(struct dvb_frontend* fe, u16* snr)
1196{
0eac3e48 1197 struct dst_state* state = fe->demodulator_priv;
1da177e4
LT
1198
1199 dst_get_signal(state);
1200 *snr = state->decode_snr;
1201
1202 return 0;
1203}
1204
1205static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
1206{
0eac3e48 1207 struct dst_state* state = fe->demodulator_priv;
1da177e4
LT
1208
1209 dst_set_freq(state, p->frequency);
50b215a0
JS
1210 if (verbose > 4)
1211 dprintk("Set Frequency = [%d]\n", p->frequency);
1212
1da177e4
LT
1213 dst_set_inversion(state, p->inversion);
1214 if (state->dst_type == DST_TYPE_IS_SAT) {
1215 dst_set_fec(state, p->u.qpsk.fec_inner);
1216 dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
50b215a0
JS
1217 if (verbose > 4)
1218 dprintk("Set Symbolrate = [%d]\n", p->u.qpsk.symbol_rate);
1219
1da177e4
LT
1220 } else if (state->dst_type == DST_TYPE_IS_TERR) {
1221 dst_set_bandwidth(state, p->u.ofdm.bandwidth);
1222 } else if (state->dst_type == DST_TYPE_IS_CABLE) {
1223 dst_set_fec(state, p->u.qam.fec_inner);
1224 dst_set_symbolrate(state, p->u.qam.symbol_rate);
1225 }
1226 dst_write_tuna(fe);
1227
1228 return 0;
1229}
1230
1231static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
1232{
0eac3e48 1233 struct dst_state* state = fe->demodulator_priv;
1da177e4
LT
1234
1235 p->frequency = state->decode_freq;
1236 p->inversion = state->inversion;
1237 if (state->dst_type == DST_TYPE_IS_SAT) {
1238 p->u.qpsk.symbol_rate = state->symbol_rate;
1239 p->u.qpsk.fec_inner = dst_get_fec(state);
1240 } else if (state->dst_type == DST_TYPE_IS_TERR) {
1241 p->u.ofdm.bandwidth = state->bandwidth;
1242 } else if (state->dst_type == DST_TYPE_IS_CABLE) {
1243 p->u.qam.symbol_rate = state->symbol_rate;
1244 p->u.qam.fec_inner = dst_get_fec(state);
1245 p->u.qam.modulation = QAM_AUTO;
1246 }
1247
1248 return 0;
1249}
1250
1251static void dst_release(struct dvb_frontend* fe)
1252{
0eac3e48 1253 struct dst_state* state = fe->demodulator_priv;
1da177e4
LT
1254 kfree(state);
1255}
1256
1257static struct dvb_frontend_ops dst_dvbt_ops;
1258static struct dvb_frontend_ops dst_dvbs_ops;
1259static struct dvb_frontend_ops dst_dvbc_ops;
1260
50b215a0 1261struct dst_state* dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
1da177e4 1262{
1da177e4 1263
50b215a0
JS
1264 /* check if the ASIC is there */
1265 if (dst_probe(state) < 0) {
1266 if (state)
1267 kfree(state);
1da177e4 1268
50b215a0
JS
1269 return NULL;
1270 }
1da177e4
LT
1271 /* determine settings based on type */
1272 switch (state->dst_type) {
1273 case DST_TYPE_IS_TERR:
1274 memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
1275 break;
50b215a0 1276
1da177e4
LT
1277 case DST_TYPE_IS_CABLE:
1278 memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
1279 break;
50b215a0 1280
1da177e4
LT
1281 case DST_TYPE_IS_SAT:
1282 memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
1283 break;
50b215a0 1284
1da177e4 1285 default:
50b215a0
JS
1286 printk("%s: unknown DST type. please report to the LinuxTV.org DVB mailinglist.\n", __FUNCTION__);
1287 if (state)
1288 kfree(state);
1289
1290 return NULL;
1da177e4
LT
1291 }
1292
1293 /* create dvb_frontend */
1294 state->frontend.ops = &state->ops;
1295 state->frontend.demodulator_priv = state;
1da177e4 1296
50b215a0 1297 return state; /* Manu (DST is a card not a frontend) */
1da177e4
LT
1298}
1299
50b215a0
JS
1300EXPORT_SYMBOL(dst_attach);
1301
1da177e4
LT
1302static struct dvb_frontend_ops dst_dvbt_ops = {
1303
1304 .info = {
1305 .name = "DST DVB-T",
1306 .type = FE_OFDM,
1307 .frequency_min = 137000000,
1308 .frequency_max = 858000000,
1309 .frequency_stepsize = 166667,
1310 .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO
1311 },
1312
1313 .release = dst_release,
1314
1315 .init = dst_init,
1316
1317 .set_frontend = dst_set_frontend,
1318 .get_frontend = dst_get_frontend,
1319
1320 .read_status = dst_read_status,
1321 .read_signal_strength = dst_read_signal_strength,
1322 .read_snr = dst_read_snr,
1323};
1324
1325static struct dvb_frontend_ops dst_dvbs_ops = {
1326
1327 .info = {
1328 .name = "DST DVB-S",
1329 .type = FE_QPSK,
1330 .frequency_min = 950000,
1331 .frequency_max = 2150000,
1332 .frequency_stepsize = 1000, /* kHz for QPSK frontends */
1333 .frequency_tolerance = 29500,
1334 .symbol_rate_min = 1000000,
1335 .symbol_rate_max = 45000000,
1336 /* . symbol_rate_tolerance = ???,*/
1337 .caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK
1338 },
1339
1340 .release = dst_release,
1341
1342 .init = dst_init,
1343
1344 .set_frontend = dst_set_frontend,
1345 .get_frontend = dst_get_frontend,
1346
1347 .read_status = dst_read_status,
1348 .read_signal_strength = dst_read_signal_strength,
1349 .read_snr = dst_read_snr,
1350
203fe8b3 1351 .diseqc_send_burst = dst_send_burst,
1da177e4
LT
1352 .diseqc_send_master_cmd = dst_set_diseqc,
1353 .set_voltage = dst_set_voltage,
1354 .set_tone = dst_set_tone,
1355};
1356
1357static struct dvb_frontend_ops dst_dvbc_ops = {
1358
1359 .info = {
1360 .name = "DST DVB-C",
1361 .type = FE_QAM,
1362 .frequency_stepsize = 62500,
1363 .frequency_min = 51000000,
1364 .frequency_max = 858000000,
1365 .symbol_rate_min = 1000000,
1366 .symbol_rate_max = 45000000,
1367 /* . symbol_rate_tolerance = ???,*/
1368 .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO
1369 },
1370
1371 .release = dst_release,
1372
1373 .init = dst_init,
1374
1375 .set_frontend = dst_set_frontend,
1376 .get_frontend = dst_get_frontend,
1377
1378 .read_status = dst_read_status,
1379 .read_signal_strength = dst_read_signal_strength,
1380 .read_snr = dst_read_snr,
1381};
1382
50b215a0 1383
1da177e4 1384MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver");
50b215a0 1385MODULE_AUTHOR("Jamie Honan, Manu Abraham");
1da177e4 1386MODULE_LICENSE("GPL");