linux/drivers/media/pci/bt8xx/dst.c
<<
>>
Prefs
   1/*
   2        Frontend/Card driver for TwinHan DST Frontend
   3        Copyright (C) 2003 Jamie Honan
   4        Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
   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        GNU General Public License for more details.
  15
  16        You should have received a copy of the GNU General Public License
  17        along with this program; if not, write to the Free Software
  18        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19*/
  20
  21#include <linux/kernel.h>
  22#include <linux/module.h>
  23#include <linux/init.h>
  24#include <linux/string.h>
  25#include <linux/slab.h>
  26#include <linux/vmalloc.h>
  27#include <linux/delay.h>
  28#include <asm/div64.h>
  29#include "dvb_frontend.h"
  30#include "dst_priv.h"
  31#include "dst_common.h"
  32
  33static unsigned int verbose = 1;
  34module_param(verbose, int, 0644);
  35MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
  36
  37static unsigned int dst_addons;
  38module_param(dst_addons, int, 0644);
  39MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
  40
  41static unsigned int dst_algo;
  42module_param(dst_algo, int, 0644);
  43MODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)");
  44
  45#define HAS_LOCK                1
  46#define ATTEMPT_TUNE            2
  47#define HAS_POWER               4
  48
  49#define DST_ERROR               0
  50#define DST_NOTICE              1
  51#define DST_INFO                2
  52#define DST_DEBUG               3
  53
  54#define dprintk(x, y, z, format, arg...) do {                           \
  55        if (z) {                                                        \
  56                if      ((x > DST_ERROR) && (x > y))                    \
  57                        printk(KERN_ERR "dst(%d) %s: " format "\n",     \
  58                                state->bt->nr, __func__ , ##arg);       \
  59                else if ((x > DST_NOTICE) && (x > y))                   \
  60                        printk(KERN_NOTICE "dst(%d) %s: " format "\n",  \
  61                                state->bt->nr, __func__ , ##arg);       \
  62                else if ((x > DST_INFO) && (x > y))                     \
  63                        printk(KERN_INFO "dst(%d) %s: " format "\n",    \
  64                                state->bt->nr, __func__ , ##arg);       \
  65                else if ((x > DST_DEBUG) && (x > y))                    \
  66                        printk(KERN_DEBUG "dst(%d) %s: " format "\n",   \
  67                                state->bt->nr,  __func__ , ##arg);      \
  68        } else {                                                        \
  69                if (x > y)                                              \
  70                        printk(format, ##arg);                          \
  71        }                                                               \
  72} while(0)
  73
  74static int dst_command(struct dst_state *state, u8 *data, u8 len);
  75
  76static void dst_packsize(struct dst_state *state, int psize)
  77{
  78        union dst_gpio_packet bits;
  79
  80        bits.psize = psize;
  81        bt878_device_control(state->bt, DST_IG_TS, &bits);
  82}
  83
  84static int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb,
  85                         u32 outhigh, int delay)
  86{
  87        union dst_gpio_packet enb;
  88        union dst_gpio_packet bits;
  89        int err;
  90
  91        enb.enb.mask = mask;
  92        enb.enb.enable = enbb;
  93
  94        dprintk(verbose, DST_INFO, 1, "mask=[%04x], enbb=[%04x], outhigh=[%04x]", mask, enbb, outhigh);
  95        if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) {
  96                dprintk(verbose, DST_INFO, 1, "dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)", err, mask, enbb);
  97                return -EREMOTEIO;
  98        }
  99        udelay(1000);
 100        /* because complete disabling means no output, no need to do output packet */
 101        if (enbb == 0)
 102                return 0;
 103        if (delay)
 104                msleep(10);
 105        bits.outp.mask = enbb;
 106        bits.outp.highvals = outhigh;
 107        if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) {
 108                dprintk(verbose, DST_INFO, 1, "dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)", err, enbb, outhigh);
 109                return -EREMOTEIO;
 110        }
 111
 112        return 0;
 113}
 114
 115static int dst_gpio_inb(struct dst_state *state, u8 *result)
 116{
 117        union dst_gpio_packet rd_packet;
 118        int err;
 119
 120        *result = 0;
 121        if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
 122                dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)", err);
 123                return -EREMOTEIO;
 124        }
 125        *result = (u8) rd_packet.rd.value;
 126
 127        return 0;
 128}
 129
 130int rdc_reset_state(struct dst_state *state)
 131{
 132        dprintk(verbose, DST_INFO, 1, "Resetting state machine");
 133        if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) {
 134                dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
 135                return -1;
 136        }
 137        msleep(10);
 138        if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, NO_DELAY) < 0) {
 139                dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
 140                msleep(10);
 141                return -1;
 142        }
 143
 144        return 0;
 145}
 146EXPORT_SYMBOL(rdc_reset_state);
 147
 148static int rdc_8820_reset(struct dst_state *state)
 149{
 150        dprintk(verbose, DST_DEBUG, 1, "Resetting DST");
 151        if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) {
 152                dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
 153                return -1;
 154        }
 155        udelay(1000);
 156        if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, RDC_8820_RESET, DELAY) < 0) {
 157                dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
 158                return -1;
 159        }
 160
 161        return 0;
 162}
 163
 164static int dst_pio_enable(struct dst_state *state)
 165{
 166        if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {
 167                dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
 168                return -1;
 169        }
 170        udelay(1000);
 171
 172        return 0;
 173}
 174
 175int dst_pio_disable(struct dst_state *state)
 176{
 177        if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) {
 178                dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
 179                return -1;
 180        }
 181        if (state->type_flags & DST_TYPE_HAS_FW_1)
 182                udelay(1000);
 183
 184        return 0;
 185}
 186EXPORT_SYMBOL(dst_pio_disable);
 187
 188int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode)
 189{
 190        u8 reply;
 191        int i;
 192
 193        for (i = 0; i < 200; i++) {
 194                if (dst_gpio_inb(state, &reply) < 0) {
 195                        dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb ERROR !");
 196                        return -1;
 197                }
 198                if ((reply & RDC_8820_PIO_0_ENABLE) == 0) {
 199                        dprintk(verbose, DST_INFO, 1, "dst wait ready after %d", i);
 200                        return 1;
 201                }
 202                msleep(10);
 203        }
 204        dprintk(verbose, DST_NOTICE, 1, "dst wait NOT ready after %d", i);
 205
 206        return 0;
 207}
 208EXPORT_SYMBOL(dst_wait_dst_ready);
 209
 210int dst_error_recovery(struct dst_state *state)
 211{
 212        dprintk(verbose, DST_NOTICE, 1, "Trying to return from previous errors.");
 213        dst_pio_disable(state);
 214        msleep(10);
 215        dst_pio_enable(state);
 216        msleep(10);
 217
 218        return 0;
 219}
 220EXPORT_SYMBOL(dst_error_recovery);
 221
 222int dst_error_bailout(struct dst_state *state)
 223{
 224        dprintk(verbose, DST_INFO, 1, "Trying to bailout from previous error.");
 225        rdc_8820_reset(state);
 226        dst_pio_disable(state);
 227        msleep(10);
 228
 229        return 0;
 230}
 231EXPORT_SYMBOL(dst_error_bailout);
 232
 233int dst_comm_init(struct dst_state *state)
 234{
 235        dprintk(verbose, DST_INFO, 1, "Initializing DST.");
 236        if ((dst_pio_enable(state)) < 0) {
 237                dprintk(verbose, DST_ERROR, 1, "PIO Enable Failed");
 238                return -1;
 239        }
 240        if ((rdc_reset_state(state)) < 0) {
 241                dprintk(verbose, DST_ERROR, 1, "RDC 8820 State RESET Failed.");
 242                return -1;
 243        }
 244        if (state->type_flags & DST_TYPE_HAS_FW_1)
 245                msleep(100);
 246        else
 247                msleep(5);
 248
 249        return 0;
 250}
 251EXPORT_SYMBOL(dst_comm_init);
 252
 253int write_dst(struct dst_state *state, u8 *data, u8 len)
 254{
 255        struct i2c_msg msg = {
 256                .addr = state->config->demod_address,
 257                .flags = 0,
 258                .buf = data,
 259                .len = len
 260        };
 261
 262        int err;
 263        u8 cnt, i;
 264
 265        dprintk(verbose, DST_NOTICE, 0, "writing [ ");
 266        for (i = 0; i < len; i++)
 267                dprintk(verbose, DST_NOTICE, 0, "%02x ", data[i]);
 268        dprintk(verbose, DST_NOTICE, 0, "]\n");
 269
 270        for (cnt = 0; cnt < 2; cnt++) {
 271                if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
 272                        dprintk(verbose, DST_INFO, 1, "_write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, data[0]);
 273                        dst_error_recovery(state);
 274                        continue;
 275                } else
 276                        break;
 277        }
 278        if (cnt >= 2) {
 279                dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
 280                dst_error_bailout(state);
 281
 282                return -1;
 283        }
 284
 285        return 0;
 286}
 287EXPORT_SYMBOL(write_dst);
 288
 289int read_dst(struct dst_state *state, u8 *ret, u8 len)
 290{
 291        struct i2c_msg msg = {
 292                .addr = state->config->demod_address,
 293                .flags = I2C_M_RD,
 294                .buf = ret,
 295                .len = len
 296        };
 297
 298        int err;
 299        int cnt;
 300
 301        for (cnt = 0; cnt < 2; cnt++) {
 302                if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
 303                        dprintk(verbose, DST_INFO, 1, "read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, ret[0]);
 304                        dst_error_recovery(state);
 305                        continue;
 306                } else
 307                        break;
 308        }
 309        if (cnt >= 2) {
 310                dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
 311                dst_error_bailout(state);
 312
 313                return -1;
 314        }
 315        dprintk(verbose, DST_DEBUG, 1, "reply is 0x%x", ret[0]);
 316        for (err = 1; err < len; err++)
 317                dprintk(verbose, DST_DEBUG, 0, " 0x%x", ret[err]);
 318        if (err > 1)
 319                dprintk(verbose, DST_DEBUG, 0, "\n");
 320
 321        return 0;
 322}
 323EXPORT_SYMBOL(read_dst);
 324
 325static int dst_set_polarization(struct dst_state *state)
 326{
 327        switch (state->voltage) {
 328        case SEC_VOLTAGE_13:    /*      Vertical        */
 329                dprintk(verbose, DST_INFO, 1, "Polarization=[Vertical]");
 330                state->tx_tuna[8] &= ~0x40;
 331                break;
 332        case SEC_VOLTAGE_18:    /*      Horizontal      */
 333                dprintk(verbose, DST_INFO, 1, "Polarization=[Horizontal]");
 334                state->tx_tuna[8] |= 0x40;
 335                break;
 336        case SEC_VOLTAGE_OFF:
 337                break;
 338        }
 339
 340        return 0;
 341}
 342
 343static int dst_set_freq(struct dst_state *state, u32 freq)
 344{
 345        state->frequency = freq;
 346        dprintk(verbose, DST_INFO, 1, "set Frequency %u", freq);
 347
 348        if (state->dst_type == DST_TYPE_IS_SAT) {
 349                freq = freq / 1000;
 350                if (freq < 950 || freq > 2150)
 351                        return -EINVAL;
 352                state->tx_tuna[2] = (freq >> 8);
 353                state->tx_tuna[3] = (u8) freq;
 354                state->tx_tuna[4] = 0x01;
 355                state->tx_tuna[8] &= ~0x04;
 356                if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
 357                        if (freq < 1531)
 358                                state->tx_tuna[8] |= 0x04;
 359                }
 360        } else if (state->dst_type == DST_TYPE_IS_TERR) {
 361                freq = freq / 1000;
 362                if (freq < 137000 || freq > 858000)
 363                        return -EINVAL;
 364                state->tx_tuna[2] = (freq >> 16) & 0xff;
 365                state->tx_tuna[3] = (freq >> 8) & 0xff;
 366                state->tx_tuna[4] = (u8) freq;
 367        } else if (state->dst_type == DST_TYPE_IS_CABLE) {
 368                freq = freq / 1000;
 369                state->tx_tuna[2] = (freq >> 16) & 0xff;
 370                state->tx_tuna[3] = (freq >> 8) & 0xff;
 371                state->tx_tuna[4] = (u8) freq;
 372        } else if (state->dst_type == DST_TYPE_IS_ATSC) {
 373                freq = freq / 1000;
 374                if (freq < 51000 || freq > 858000)
 375                        return -EINVAL;
 376                state->tx_tuna[2] = (freq >> 16) & 0xff;
 377                state->tx_tuna[3] = (freq >>  8) & 0xff;
 378                state->tx_tuna[4] = (u8) freq;
 379                state->tx_tuna[5] = 0x00;               /*      ATSC    */
 380                state->tx_tuna[6] = 0x00;
 381                if (state->dst_hw_cap & DST_TYPE_HAS_ANALOG)
 382                        state->tx_tuna[7] = 0x00;       /*      Digital */
 383        } else
 384                return -EINVAL;
 385
 386        return 0;
 387}
 388
 389static int dst_set_bandwidth(struct dst_state *state, u32 bandwidth)
 390{
 391        state->bandwidth = bandwidth;
 392
 393        if (state->dst_type != DST_TYPE_IS_TERR)
 394                return -EOPNOTSUPP;
 395
 396        switch (bandwidth) {
 397        case 6000000:
 398                if (state->dst_hw_cap & DST_TYPE_HAS_CA)
 399                        state->tx_tuna[7] = 0x06;
 400                else {
 401                        state->tx_tuna[6] = 0x06;
 402                        state->tx_tuna[7] = 0x00;
 403                }
 404                break;
 405        case 7000000:
 406                if (state->dst_hw_cap & DST_TYPE_HAS_CA)
 407                        state->tx_tuna[7] = 0x07;
 408                else {
 409                        state->tx_tuna[6] = 0x07;
 410                        state->tx_tuna[7] = 0x00;
 411                }
 412                break;
 413        case 8000000:
 414                if (state->dst_hw_cap & DST_TYPE_HAS_CA)
 415                        state->tx_tuna[7] = 0x08;
 416                else {
 417                        state->tx_tuna[6] = 0x08;
 418                        state->tx_tuna[7] = 0x00;
 419                }
 420                break;
 421        default:
 422                return -EINVAL;
 423        }
 424
 425        return 0;
 426}
 427
 428static int dst_set_inversion(struct dst_state *state,
 429                             enum fe_spectral_inversion inversion)
 430{
 431        state->inversion = inversion;
 432        switch (inversion) {
 433        case INVERSION_OFF:     /*      Inversion = Normal      */
 434                state->tx_tuna[8] &= ~0x80;
 435                break;
 436        case INVERSION_ON:
 437                state->tx_tuna[8] |= 0x80;
 438                break;
 439        default:
 440                return -EINVAL;
 441        }
 442
 443        return 0;
 444}
 445
 446static int dst_set_fec(struct dst_state *state, enum fe_code_rate fec)
 447{
 448        state->fec = fec;
 449        return 0;
 450}
 451
 452static enum fe_code_rate dst_get_fec(struct dst_state *state)
 453{
 454        return state->fec;
 455}
 456
 457static int dst_set_symbolrate(struct dst_state *state, u32 srate)
 458{
 459        u32 symcalc;
 460        u64 sval;
 461
 462        state->symbol_rate = srate;
 463        if (state->dst_type == DST_TYPE_IS_TERR) {
 464                return -EOPNOTSUPP;
 465        }
 466        dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
 467        srate /= 1000;
 468        if (state->dst_type == DST_TYPE_IS_SAT) {
 469                if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
 470                        sval = srate;
 471                        sval <<= 20;
 472                        do_div(sval, 88000);
 473                        symcalc = (u32) sval;
 474                        dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
 475                        state->tx_tuna[5] = (u8) (symcalc >> 12);
 476                        state->tx_tuna[6] = (u8) (symcalc >> 4);
 477                        state->tx_tuna[7] = (u8) (symcalc << 4);
 478                } else {
 479                        state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
 480                        state->tx_tuna[6] = (u8) (srate >> 8);
 481                        state->tx_tuna[7] = (u8) srate;
 482                }
 483                state->tx_tuna[8] &= ~0x20;
 484                if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
 485                        if (srate > 8000)
 486                                state->tx_tuna[8] |= 0x20;
 487                }
 488        } else if (state->dst_type == DST_TYPE_IS_CABLE) {
 489                dprintk(verbose, DST_DEBUG, 1, "%s", state->fw_name);
 490                if (!strncmp(state->fw_name, "DCTNEW", 6)) {
 491                        state->tx_tuna[5] = (u8) (srate >> 8);
 492                        state->tx_tuna[6] = (u8) srate;
 493                        state->tx_tuna[7] = 0x00;
 494                } else if (!strncmp(state->fw_name, "DCT-CI", 6)) {
 495                        state->tx_tuna[5] = 0x00;
 496                        state->tx_tuna[6] = (u8) (srate >> 8);
 497                        state->tx_tuna[7] = (u8) srate;
 498                }
 499        }
 500        return 0;
 501}
 502
 503static int dst_set_modulation(struct dst_state *state,
 504                              enum fe_modulation modulation)
 505{
 506        if (state->dst_type != DST_TYPE_IS_CABLE)
 507                return -EOPNOTSUPP;
 508
 509        state->modulation = modulation;
 510        switch (modulation) {
 511        case QAM_16:
 512                state->tx_tuna[8] = 0x10;
 513                break;
 514        case QAM_32:
 515                state->tx_tuna[8] = 0x20;
 516                break;
 517        case QAM_64:
 518                state->tx_tuna[8] = 0x40;
 519                break;
 520        case QAM_128:
 521                state->tx_tuna[8] = 0x80;
 522                break;
 523        case QAM_256:
 524                if (!strncmp(state->fw_name, "DCTNEW", 6))
 525                        state->tx_tuna[8] = 0xff;
 526                else if (!strncmp(state->fw_name, "DCT-CI", 6))
 527                        state->tx_tuna[8] = 0x00;
 528                break;
 529        case QPSK:
 530        case QAM_AUTO:
 531        case VSB_8:
 532        case VSB_16:
 533        default:
 534                return -EINVAL;
 535
 536        }
 537
 538        return 0;
 539}
 540
 541static enum fe_modulation dst_get_modulation(struct dst_state *state)
 542{
 543        return state->modulation;
 544}
 545
 546
 547u8 dst_check_sum(u8 *buf, u32 len)
 548{
 549        u32 i;
 550        u8 val = 0;
 551        if (!len)
 552                return 0;
 553        for (i = 0; i < len; i++) {
 554                val += buf[i];
 555        }
 556        return ((~val) + 1);
 557}
 558EXPORT_SYMBOL(dst_check_sum);
 559
 560static void dst_type_flags_print(struct dst_state *state)
 561{
 562        u32 type_flags = state->type_flags;
 563
 564        dprintk(verbose, DST_ERROR, 0, "DST type flags :");
 565        if (type_flags & DST_TYPE_HAS_TS188)
 566                dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_TS188);
 567        if (type_flags & DST_TYPE_HAS_NEWTUNE_2)
 568                dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner 2", DST_TYPE_HAS_NEWTUNE_2);
 569        if (type_flags & DST_TYPE_HAS_TS204)
 570                dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
 571        if (type_flags & DST_TYPE_HAS_VLF)
 572                dprintk(verbose, DST_ERROR, 0, " 0x%x VLF", DST_TYPE_HAS_VLF);
 573        if (type_flags & DST_TYPE_HAS_SYMDIV)
 574                dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
 575        if (type_flags & DST_TYPE_HAS_FW_1)
 576                dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
 577        if (type_flags & DST_TYPE_HAS_FW_2)
 578                dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
 579        if (type_flags & DST_TYPE_HAS_FW_3)
 580                dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
 581        dprintk(verbose, DST_ERROR, 0, "\n");
 582}
 583
 584
 585static int dst_type_print(struct dst_state *state, u8 type)
 586{
 587        char *otype;
 588        switch (type) {
 589        case DST_TYPE_IS_SAT:
 590                otype = "satellite";
 591                break;
 592
 593        case DST_TYPE_IS_TERR:
 594                otype = "terrestrial";
 595                break;
 596
 597        case DST_TYPE_IS_CABLE:
 598                otype = "cable";
 599                break;
 600
 601        case DST_TYPE_IS_ATSC:
 602                otype = "atsc";
 603                break;
 604
 605        default:
 606                dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
 607                return -EINVAL;
 608        }
 609        dprintk(verbose, DST_INFO, 1, "DST type: %s", otype);
 610
 611        return 0;
 612}
 613
 614static struct tuner_types tuner_list[] = {
 615        {
 616                .tuner_type = TUNER_TYPE_L64724,
 617                .tuner_name = "L 64724",
 618                .board_name = "UNKNOWN",
 619                .fw_name    = "UNKNOWN"
 620        },
 621
 622        {
 623                .tuner_type = TUNER_TYPE_STV0299,
 624                .tuner_name = "STV 0299",
 625                .board_name = "VP1020",
 626                .fw_name    = "DST-MOT"
 627        },
 628
 629        {
 630                .tuner_type = TUNER_TYPE_STV0299,
 631                .tuner_name = "STV 0299",
 632                .board_name = "VP1020",
 633                .fw_name    = "DST-03T"
 634        },
 635
 636        {
 637                .tuner_type = TUNER_TYPE_MB86A15,
 638                .tuner_name = "MB 86A15",
 639                .board_name = "VP1022",
 640                .fw_name    = "DST-03T"
 641        },
 642
 643        {
 644                .tuner_type = TUNER_TYPE_MB86A15,
 645                .tuner_name = "MB 86A15",
 646                .board_name = "VP1025",
 647                .fw_name    = "DST-03T"
 648        },
 649
 650        {
 651                .tuner_type = TUNER_TYPE_STV0299,
 652                .tuner_name = "STV 0299",
 653                .board_name = "VP1030",
 654                .fw_name    = "DST-CI"
 655        },
 656
 657        {
 658                .tuner_type = TUNER_TYPE_STV0299,
 659                .tuner_name = "STV 0299",
 660                .board_name = "VP1030",
 661                .fw_name    = "DSTMCI"
 662        },
 663
 664        {
 665                .tuner_type = TUNER_TYPE_UNKNOWN,
 666                .tuner_name = "UNKNOWN",
 667                .board_name = "VP2021",
 668                .fw_name    = "DCTNEW"
 669        },
 670
 671        {
 672                .tuner_type = TUNER_TYPE_UNKNOWN,
 673                .tuner_name = "UNKNOWN",
 674                .board_name = "VP2030",
 675                .fw_name    = "DCT-CI"
 676        },
 677
 678        {
 679                .tuner_type = TUNER_TYPE_UNKNOWN,
 680                .tuner_name = "UNKNOWN",
 681                .board_name = "VP2031",
 682                .fw_name    = "DCT-CI"
 683        },
 684
 685        {
 686                .tuner_type = TUNER_TYPE_UNKNOWN,
 687                .tuner_name = "UNKNOWN",
 688                .board_name = "VP2040",
 689                .fw_name    = "DCT-CI"
 690        },
 691
 692        {
 693                .tuner_type = TUNER_TYPE_UNKNOWN,
 694                .tuner_name = "UNKNOWN",
 695                .board_name = "VP3020",
 696                .fw_name    = "DTTFTA"
 697        },
 698
 699        {
 700                .tuner_type = TUNER_TYPE_UNKNOWN,
 701                .tuner_name = "UNKNOWN",
 702                .board_name = "VP3021",
 703                .fw_name    = "DTTFTA"
 704        },
 705
 706        {
 707                .tuner_type = TUNER_TYPE_TDA10046,
 708                .tuner_name = "TDA10046",
 709                .board_name = "VP3040",
 710                .fw_name    = "DTT-CI"
 711        },
 712
 713        {
 714                .tuner_type = TUNER_TYPE_UNKNOWN,
 715                .tuner_name = "UNKNOWN",
 716                .board_name = "VP3051",
 717                .fw_name    = "DTTNXT"
 718        },
 719
 720        {
 721                .tuner_type = TUNER_TYPE_NXT200x,
 722                .tuner_name = "NXT200x",
 723                .board_name = "VP3220",
 724                .fw_name    = "ATSCDI"
 725        },
 726
 727        {
 728                .tuner_type = TUNER_TYPE_NXT200x,
 729                .tuner_name = "NXT200x",
 730                .board_name = "VP3250",
 731                .fw_name    = "ATSCAD"
 732        },
 733};
 734
 735/*
 736        Known cards list
 737        Satellite
 738        -------------------
 739                  200103A
 740        VP-1020   DST-MOT       LG(old), TS=188
 741
 742        VP-1020   DST-03T       LG(new), TS=204
 743        VP-1022   DST-03T       LG(new), TS=204
 744        VP-1025   DST-03T       LG(new), TS=204
 745
 746        VP-1030   DSTMCI,       LG(new), TS=188
 747        VP-1032   DSTMCI,       LG(new), TS=188
 748
 749        Cable
 750        -------------------
 751        VP-2030   DCT-CI,       Samsung, TS=204
 752        VP-2021   DCT-CI,       Unknown, TS=204
 753        VP-2031   DCT-CI,       Philips, TS=188
 754        VP-2040   DCT-CI,       Philips, TS=188, with CA daughter board
 755        VP-2040   DCT-CI,       Philips, TS=204, without CA daughter board
 756
 757        Terrestrial
 758        -------------------
 759        VP-3050  DTTNXT                  TS=188
 760        VP-3040  DTT-CI,        Philips, TS=188
 761        VP-3040  DTT-CI,        Philips, TS=204
 762
 763        ATSC
 764        -------------------
 765        VP-3220  ATSCDI,                 TS=188
 766        VP-3250  ATSCAD,                 TS=188
 767
 768*/
 769
 770static struct dst_types dst_tlist[] = {
 771        {
 772                .device_id = "200103A",
 773                .offset = 0,
 774                .dst_type =  DST_TYPE_IS_SAT,
 775                .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS,
 776                .dst_feature = 0,
 777                .tuner_type = 0
 778        },      /*      obsolete        */
 779
 780        {
 781                .device_id = "DST-020",
 782                .offset = 0,
 783                .dst_type =  DST_TYPE_IS_SAT,
 784                .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
 785                .dst_feature = 0,
 786                .tuner_type = 0
 787        },      /*      obsolete        */
 788
 789        {
 790                .device_id = "DST-030",
 791                .offset =  0,
 792                .dst_type = DST_TYPE_IS_SAT,
 793                .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
 794                .dst_feature = 0,
 795                .tuner_type = 0
 796        },      /*      obsolete        */
 797
 798        {
 799                .device_id = "DST-03T",
 800                .offset = 0,
 801                .dst_type = DST_TYPE_IS_SAT,
 802                .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
 803                .dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
 804                                                         | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO,
 805                .tuner_type = TUNER_TYPE_MULTI
 806         },
 807
 808        {
 809                .device_id = "DST-MOT",
 810                .offset =  0,
 811                .dst_type = DST_TYPE_IS_SAT,
 812                .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
 813                .dst_feature = 0,
 814                .tuner_type = 0
 815        },      /*      obsolete        */
 816
 817        {
 818                .device_id = "DST-CI",
 819                .offset = 1,
 820                .dst_type = DST_TYPE_IS_SAT,
 821                .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1,
 822                .dst_feature = DST_TYPE_HAS_CA,
 823                .tuner_type = 0
 824        },      /*      An OEM board    */
 825
 826        {
 827                .device_id = "DSTMCI",
 828                .offset = 1,
 829                .dst_type = DST_TYPE_IS_SAT,
 830                .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT | DST_TYPE_HAS_VLF,
 831                .dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
 832                                                        | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC,
 833                .tuner_type = TUNER_TYPE_MULTI
 834        },
 835
 836        {
 837                .device_id = "DSTFCI",
 838                .offset = 1,
 839                .dst_type = DST_TYPE_IS_SAT,
 840                .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
 841                .dst_feature = 0,
 842                .tuner_type = 0
 843        },      /* unknown to vendor    */
 844
 845        {
 846                .device_id = "DCT-CI",
 847                .offset = 1,
 848                .dst_type = DST_TYPE_IS_CABLE,
 849                .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF,
 850                .dst_feature = DST_TYPE_HAS_CA,
 851                .tuner_type = 0
 852        },
 853
 854        {
 855                .device_id = "DCTNEW",
 856                .offset = 1,
 857                .dst_type = DST_TYPE_IS_CABLE,
 858                .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE,
 859                .dst_feature = 0,
 860                .tuner_type = 0
 861        },
 862
 863        {
 864                .device_id = "DTT-CI",
 865                .offset = 1,
 866                .dst_type = DST_TYPE_IS_TERR,
 867                .type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF,
 868                .dst_feature = DST_TYPE_HAS_CA,
 869                .tuner_type = 0
 870        },
 871
 872        {
 873                .device_id = "DTTDIG",
 874                .offset = 1,
 875                .dst_type = DST_TYPE_IS_TERR,
 876                .type_flags = DST_TYPE_HAS_FW_2,
 877                .dst_feature = 0,
 878                .tuner_type = 0
 879        },
 880
 881        {
 882                .device_id = "DTTNXT",
 883                .offset = 1,
 884                .dst_type = DST_TYPE_IS_TERR,
 885                .type_flags = DST_TYPE_HAS_FW_2,
 886                .dst_feature = DST_TYPE_HAS_ANALOG,
 887                .tuner_type = 0
 888        },
 889
 890        {
 891                .device_id = "ATSCDI",
 892                .offset = 1,
 893                .dst_type = DST_TYPE_IS_ATSC,
 894                .type_flags = DST_TYPE_HAS_FW_2,
 895                .dst_feature = 0,
 896                .tuner_type = 0
 897        },
 898
 899        {
 900                .device_id = "ATSCAD",
 901                .offset = 1,
 902                .dst_type = DST_TYPE_IS_ATSC,
 903                .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
 904                .dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG,
 905                .tuner_type = 0
 906        },
 907
 908        { }
 909
 910};
 911
 912static int dst_get_mac(struct dst_state *state)
 913{
 914        u8 get_mac[] = { 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 915        get_mac[7] = dst_check_sum(get_mac, 7);
 916        if (dst_command(state, get_mac, 8) < 0) {
 917                dprintk(verbose, DST_INFO, 1, "Unsupported Command");
 918                return -1;
 919        }
 920        memset(&state->mac_address, '\0', 8);
 921        memcpy(&state->mac_address, &state->rxbuffer, 6);
 922        dprintk(verbose, DST_ERROR, 1, "MAC Address=[%pM]", state->mac_address);
 923
 924        return 0;
 925}
 926
 927static int dst_fw_ver(struct dst_state *state)
 928{
 929        u8 get_ver[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 930        get_ver[7] = dst_check_sum(get_ver, 7);
 931        if (dst_command(state, get_ver, 8) < 0) {
 932                dprintk(verbose, DST_INFO, 1, "Unsupported Command");
 933                return -1;
 934        }
 935        memcpy(&state->fw_version, &state->rxbuffer, 8);
 936        dprintk(verbose, DST_ERROR, 1, "Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x",
 937                state->fw_version[0] >> 4, state->fw_version[0] & 0x0f,
 938                state->fw_version[1],
 939                state->fw_version[5], state->fw_version[6],
 940                state->fw_version[4], state->fw_version[3], state->fw_version[2]);
 941
 942        return 0;
 943}
 944
 945static int dst_card_type(struct dst_state *state)
 946{
 947        int j;
 948        struct tuner_types *p_tuner_list = NULL;
 949
 950        u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 951        get_type[7] = dst_check_sum(get_type, 7);
 952        if (dst_command(state, get_type, 8) < 0) {
 953                dprintk(verbose, DST_INFO, 1, "Unsupported Command");
 954                return -1;
 955        }
 956        memset(&state->card_info, '\0', 8);
 957        memcpy(&state->card_info, &state->rxbuffer, 7);
 958        dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
 959
 960        for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
 961                if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) {
 962                        state->tuner_type = p_tuner_list->tuner_type;
 963                        dprintk(verbose, DST_ERROR, 1, "DST has [%s] tuner, tuner type=[%d]",
 964                                p_tuner_list->tuner_name, p_tuner_list->tuner_type);
 965                }
 966        }
 967
 968        return 0;
 969}
 970
 971static int dst_get_vendor(struct dst_state *state)
 972{
 973        u8 get_vendor[] = { 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 974        get_vendor[7] = dst_check_sum(get_vendor, 7);
 975        if (dst_command(state, get_vendor, 8) < 0) {
 976                dprintk(verbose, DST_INFO, 1, "Unsupported Command");
 977                return -1;
 978        }
 979        memset(&state->vendor, '\0', 8);
 980        memcpy(&state->vendor, &state->rxbuffer, 7);
 981        dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
 982
 983        return 0;
 984}
 985
 986static void debug_dst_buffer(struct dst_state *state)
 987{
 988        int i;
 989
 990        if (verbose > 2) {
 991                printk("%s: [", __func__);
 992                for (i = 0; i < 8; i++)
 993                        printk(" %02x", state->rxbuffer[i]);
 994                printk("]\n");
 995        }
 996}
 997
 998static int dst_check_stv0299(struct dst_state *state)
 999{
1000        u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1001
1002        check_stv0299[7] = dst_check_sum(check_stv0299, 7);
1003        if (dst_command(state, check_stv0299, 8) < 0) {
1004                dprintk(verbose, DST_ERROR, 1, "Cmd=[0x04] failed");
1005                return -1;
1006        }
1007        debug_dst_buffer(state);
1008
1009        if (memcmp(&check_stv0299, &state->rxbuffer, 8)) {
1010                dprintk(verbose, DST_ERROR, 1, "Found a STV0299 NIM");
1011                state->tuner_type = TUNER_TYPE_STV0299;
1012                return 0;
1013        }
1014
1015        return -1;
1016}
1017
1018static int dst_check_mb86a15(struct dst_state *state)
1019{
1020        u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1021
1022        check_mb86a15[7] = dst_check_sum(check_mb86a15, 7);
1023        if (dst_command(state, check_mb86a15, 8) < 0) {
1024                dprintk(verbose, DST_ERROR, 1, "Cmd=[0x10], failed");
1025                return -1;
1026        }
1027        debug_dst_buffer(state);
1028
1029        if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) {
1030                dprintk(verbose, DST_ERROR, 1, "Found a MB86A15 NIM");
1031                state->tuner_type = TUNER_TYPE_MB86A15;
1032                return 0;
1033        }
1034
1035        return -1;
1036}
1037
1038static int dst_get_tuner_info(struct dst_state *state)
1039{
1040        u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1041        u8 get_tuner_2[] = { 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1042
1043        get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
1044        get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
1045        dprintk(verbose, DST_ERROR, 1, "DST TYpe = MULTI FE");
1046        if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
1047                if (dst_command(state, get_tuner_1, 8) < 0) {
1048                        dprintk(verbose, DST_INFO, 1, "Cmd=[0x13], Unsupported");
1049                        goto force;
1050                }
1051        } else {
1052                if (dst_command(state, get_tuner_2, 8) < 0) {
1053                        dprintk(verbose, DST_INFO, 1, "Cmd=[0xb], Unsupported");
1054                        goto force;
1055                }
1056        }
1057        memcpy(&state->board_info, &state->rxbuffer, 8);
1058        if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
1059                dprintk(verbose, DST_ERROR, 1, "DST type has TS=188");
1060        }
1061        if (state->board_info[0] == 0xbc) {
1062                if (state->dst_type != DST_TYPE_IS_ATSC)
1063                        state->type_flags |= DST_TYPE_HAS_TS188;
1064                else
1065                        state->type_flags |= DST_TYPE_HAS_NEWTUNE_2;
1066
1067                if (state->board_info[1] == 0x01) {
1068                        state->dst_hw_cap |= DST_TYPE_HAS_DBOARD;
1069                        dprintk(verbose, DST_ERROR, 1, "DST has Daughterboard");
1070                }
1071        }
1072
1073        return 0;
1074force:
1075        if (!strncmp(state->fw_name, "DCT-CI", 6)) {
1076                state->type_flags |= DST_TYPE_HAS_TS204;
1077                dprintk(verbose, DST_ERROR, 1, "Forcing [%s] to TS188", state->fw_name);
1078        }
1079
1080        return -1;
1081}
1082
1083static int dst_get_device_id(struct dst_state *state)
1084{
1085        u8 reply;
1086
1087        int i, j;
1088        struct dst_types *p_dst_type = NULL;
1089        struct tuner_types *p_tuner_list = NULL;
1090
1091        u8 use_dst_type = 0;
1092        u32 use_type_flags = 0;
1093
1094        static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
1095
1096        state->tuner_type = 0;
1097        device_type[7] = dst_check_sum(device_type, 7);
1098
1099        if (write_dst(state, device_type, FIXED_COMM))
1100                return -1;              /*      Write failed            */
1101        if ((dst_pio_disable(state)) < 0)
1102                return -1;
1103        if (read_dst(state, &reply, GET_ACK))
1104                return -1;              /*      Read failure            */
1105        if (reply != ACK) {
1106                dprintk(verbose, DST_INFO, 1, "Write not Acknowledged! [Reply=0x%02x]", reply);
1107                return -1;              /*      Unack'd write           */
1108        }
1109        if (!dst_wait_dst_ready(state, DEVICE_INIT))
1110                return -1;              /*      DST not ready yet       */
1111        if (read_dst(state, state->rxbuffer, FIXED_COMM))
1112                return -1;
1113
1114        dst_pio_disable(state);
1115        if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
1116                dprintk(verbose, DST_INFO, 1, "Checksum failure!");
1117                return -1;              /*      Checksum failure        */
1118        }
1119        state->rxbuffer[7] = '\0';
1120
1121        for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE(dst_tlist); i++, p_dst_type++) {
1122                if (!strncmp (&state->rxbuffer[p_dst_type->offset], p_dst_type->device_id, strlen (p_dst_type->device_id))) {
1123                        use_type_flags = p_dst_type->type_flags;
1124                        use_dst_type = p_dst_type->dst_type;
1125
1126                        /*      Card capabilities       */
1127                        state->dst_hw_cap = p_dst_type->dst_feature;
1128                        dprintk(verbose, DST_ERROR, 1, "Recognise [%s]", p_dst_type->device_id);
1129                        strncpy(&state->fw_name[0], p_dst_type->device_id, 6);
1130                        /*      Multiple tuners         */
1131                        if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) {
1132                                switch (use_dst_type) {
1133                                case DST_TYPE_IS_SAT:
1134                                        /*      STV0299 check   */
1135                                        if (dst_check_stv0299(state) < 0) {
1136                                                dprintk(verbose, DST_ERROR, 1, "Unsupported");
1137                                                state->tuner_type = TUNER_TYPE_MB86A15;
1138                                        }
1139                                        break;
1140                                default:
1141                                        break;
1142                                }
1143                                if (dst_check_mb86a15(state) < 0)
1144                                        dprintk(verbose, DST_ERROR, 1, "Unsupported");
1145                        /*      Single tuner            */
1146                        } else {
1147                                state->tuner_type = p_dst_type->tuner_type;
1148                        }
1149                        for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
1150                                if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) &&
1151                                        p_tuner_list->tuner_type == state->tuner_type) {
1152                                        dprintk(verbose, DST_ERROR, 1, "[%s] has a [%s]",
1153                                                p_dst_type->device_id, p_tuner_list->tuner_name);
1154                                }
1155                        }
1156                        break;
1157                }
1158        }
1159
1160        if (i >= ARRAY_SIZE(dst_tlist)) {
1161                dprintk(verbose, DST_ERROR, 1, "Unable to recognize %s or %s", &state->rxbuffer[0], &state->rxbuffer[1]);
1162                dprintk(verbose, DST_ERROR, 1, "please email linux-dvb@linuxtv.org with this type in");
1163                use_dst_type = DST_TYPE_IS_SAT;
1164                use_type_flags = DST_TYPE_HAS_SYMDIV;
1165        }
1166        dst_type_print(state, use_dst_type);
1167        state->type_flags = use_type_flags;
1168        state->dst_type = use_dst_type;
1169        dst_type_flags_print(state);
1170
1171        return 0;
1172}
1173
1174static int dst_probe(struct dst_state *state)
1175{
1176        mutex_init(&state->dst_mutex);
1177        if (dst_addons & DST_TYPE_HAS_CA) {
1178                if ((rdc_8820_reset(state)) < 0) {
1179                        dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
1180                        return -1;
1181                }
1182                msleep(4000);
1183        } else {
1184                msleep(100);
1185        }
1186        if ((dst_comm_init(state)) < 0) {
1187                dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
1188                return -1;
1189        }
1190        msleep(100);
1191        if (dst_get_device_id(state) < 0) {
1192                dprintk(verbose, DST_ERROR, 1, "unknown device.");
1193                return -1;
1194        }
1195        if (dst_get_mac(state) < 0) {
1196                dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
1197        }
1198        if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) {
1199                if (dst_get_tuner_info(state) < 0)
1200                        dprintk(verbose, DST_INFO, 1, "Tuner: Unsupported command");
1201        }
1202        if (state->type_flags & DST_TYPE_HAS_TS204) {
1203                dst_packsize(state, 204);
1204        }
1205        if (state->type_flags & DST_TYPE_HAS_FW_BUILD) {
1206                if (dst_fw_ver(state) < 0) {
1207                        dprintk(verbose, DST_INFO, 1, "FW: Unsupported command");
1208                        return 0;
1209                }
1210                if (dst_card_type(state) < 0) {
1211                        dprintk(verbose, DST_INFO, 1, "Card: Unsupported command");
1212                        return 0;
1213                }
1214                if (dst_get_vendor(state) < 0) {
1215                        dprintk(verbose, DST_INFO, 1, "Vendor: Unsupported command");
1216                        return 0;
1217                }
1218        }
1219
1220        return 0;
1221}
1222
1223static int dst_command(struct dst_state *state, u8 *data, u8 len)
1224{
1225        u8 reply;
1226
1227        mutex_lock(&state->dst_mutex);
1228        if ((dst_comm_init(state)) < 0) {
1229                dprintk(verbose, DST_NOTICE, 1, "DST Communication Initialization Failed.");
1230                goto error;
1231        }
1232        if (write_dst(state, data, len)) {
1233                dprintk(verbose, DST_INFO, 1, "Trying to recover.. ");
1234                if ((dst_error_recovery(state)) < 0) {
1235                        dprintk(verbose, DST_ERROR, 1, "Recovery Failed.");
1236                        goto error;
1237                }
1238                goto error;
1239        }
1240        if ((dst_pio_disable(state)) < 0) {
1241                dprintk(verbose, DST_ERROR, 1, "PIO Disable Failed.");
1242                goto error;
1243        }
1244        if (state->type_flags & DST_TYPE_HAS_FW_1)
1245                mdelay(3);
1246        if (read_dst(state, &reply, GET_ACK)) {
1247                dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
1248                if ((dst_error_recovery(state)) < 0) {
1249                        dprintk(verbose, DST_INFO, 1, "Recovery Failed.");
1250                        goto error;
1251                }
1252                goto error;
1253        }
1254        if (reply != ACK) {
1255                dprintk(verbose, DST_INFO, 1, "write not acknowledged 0x%02x ", reply);
1256                goto error;
1257        }
1258        if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
1259                goto error;
1260        if (state->type_flags & DST_TYPE_HAS_FW_1)
1261                mdelay(3);
1262        else
1263                udelay(2000);
1264        if (!dst_wait_dst_ready(state, NO_DELAY))
1265                goto error;
1266        if (read_dst(state, state->rxbuffer, FIXED_COMM)) {
1267                dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
1268                if ((dst_error_recovery(state)) < 0) {
1269                        dprintk(verbose, DST_INFO, 1, "Recovery failed.");
1270                        goto error;
1271                }
1272                goto error;
1273        }
1274        if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
1275                dprintk(verbose, DST_INFO, 1, "checksum failure");
1276                goto error;
1277        }
1278        mutex_unlock(&state->dst_mutex);
1279        return 0;
1280
1281error:
1282        mutex_unlock(&state->dst_mutex);
1283        return -EIO;
1284
1285}
1286
1287static int dst_get_signal(struct dst_state *state)
1288{
1289        int retval;
1290        u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
1291        //dprintk("%s: Getting Signal strength and other parameters\n", __func__);
1292        if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
1293                state->decode_lock = state->decode_strength = state->decode_snr = 0;
1294                return 0;
1295        }
1296        if (0 == (state->diseq_flags & HAS_LOCK)) {
1297                state->decode_lock = state->decode_strength = state->decode_snr = 0;
1298                return 0;
1299        }
1300        if (time_after_eq(jiffies, state->cur_jiff + (HZ / 5))) {
1301                retval = dst_command(state, get_signal, 8);
1302                if (retval < 0)
1303                        return retval;
1304                if (state->dst_type == DST_TYPE_IS_SAT) {
1305                        state->decode_lock = ((state->rxbuffer[6] & 0x10) == 0) ? 1 : 0;
1306                        state->decode_strength = state->rxbuffer[5] << 8;
1307                        state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
1308                } else if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE)) {
1309                        state->decode_lock = (state->rxbuffer[1]) ? 1 : 0;
1310                        state->decode_strength = state->rxbuffer[4] << 8;
1311                        state->decode_snr = state->rxbuffer[3] << 8;
1312                } else if (state->dst_type == DST_TYPE_IS_ATSC) {
1313                        state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0;
1314                        state->decode_strength = state->rxbuffer[4] << 8;
1315                        state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
1316                }
1317                state->cur_jiff = jiffies;
1318        }
1319        return 0;
1320}
1321
1322static int dst_tone_power_cmd(struct dst_state *state)
1323{
1324        u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 };
1325
1326        if (state->dst_type != DST_TYPE_IS_SAT)
1327                return -EOPNOTSUPP;
1328        paket[4] = state->tx_tuna[4];
1329        paket[2] = state->tx_tuna[2];
1330        paket[3] = state->tx_tuna[3];
1331        paket[7] = dst_check_sum (paket, 7);
1332        return dst_command(state, paket, 8);
1333}
1334
1335static int dst_get_tuna(struct dst_state *state)
1336{
1337        int retval;
1338
1339        if ((state->diseq_flags & ATTEMPT_TUNE) == 0)
1340                return 0;
1341        state->diseq_flags &= ~(HAS_LOCK);
1342        if (!dst_wait_dst_ready(state, NO_DELAY))
1343                return -EIO;
1344        if ((state->type_flags & DST_TYPE_HAS_VLF) &&
1345                !(state->dst_type == DST_TYPE_IS_ATSC))
1346
1347                retval = read_dst(state, state->rx_tuna, 10);
1348        else
1349                retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
1350        if (retval < 0) {
1351                dprintk(verbose, DST_DEBUG, 1, "read not successful");
1352                return retval;
1353        }
1354        if ((state->type_flags & DST_TYPE_HAS_VLF) &&
1355           !(state->dst_type == DST_TYPE_IS_ATSC)) {
1356
1357                if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
1358                        dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
1359                        return -EIO;
1360                }
1361        } else {
1362                if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) {
1363                        dprintk(verbose, DST_INFO, 1, "checksum failure? ");
1364                        return -EIO;
1365                }
1366        }
1367        if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0)
1368                return 0;
1369        if (state->dst_type == DST_TYPE_IS_SAT) {
1370                state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3];
1371        } else {
1372                state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 16) + (state->rx_tuna[3] << 8) + state->rx_tuna[4];
1373        }
1374        state->decode_freq = state->decode_freq * 1000;
1375        state->decode_lock = 1;
1376        state->diseq_flags |= HAS_LOCK;
1377
1378        return 1;
1379}
1380
1381static int dst_set_voltage(struct dvb_frontend *fe,
1382                           enum fe_sec_voltage voltage);
1383
1384static int dst_write_tuna(struct dvb_frontend *fe)
1385{
1386        struct dst_state *state = fe->demodulator_priv;
1387        int retval;
1388        u8 reply;
1389
1390        dprintk(verbose, DST_INFO, 1, "type_flags 0x%x ", state->type_flags);
1391        state->decode_freq = 0;
1392        state->decode_lock = state->decode_strength = state->decode_snr = 0;
1393        if (state->dst_type == DST_TYPE_IS_SAT) {
1394                if (!(state->diseq_flags & HAS_POWER))
1395                        dst_set_voltage(fe, SEC_VOLTAGE_13);
1396        }
1397        state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
1398        mutex_lock(&state->dst_mutex);
1399        if ((dst_comm_init(state)) < 0) {
1400                dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
1401                goto error;
1402        }
1403//      if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
1404        if ((state->type_flags & DST_TYPE_HAS_VLF) &&
1405                (!(state->dst_type == DST_TYPE_IS_ATSC))) {
1406
1407                state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
1408                retval = write_dst(state, &state->tx_tuna[0], 10);
1409        } else {
1410                state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7);
1411                retval = write_dst(state, &state->tx_tuna[2], FIXED_COMM);
1412        }
1413        if (retval < 0) {
1414                dst_pio_disable(state);
1415                dprintk(verbose, DST_DEBUG, 1, "write not successful");
1416                goto werr;
1417        }
1418        if ((dst_pio_disable(state)) < 0) {
1419                dprintk(verbose, DST_DEBUG, 1, "DST PIO disable failed !");
1420                goto error;
1421        }
1422        if ((read_dst(state, &reply, GET_ACK) < 0)) {
1423                dprintk(verbose, DST_DEBUG, 1, "read verify not successful.");
1424                goto error;
1425        }
1426        if (reply != ACK) {
1427                dprintk(verbose, DST_DEBUG, 1, "write not acknowledged 0x%02x ", reply);
1428                goto error;
1429        }
1430        state->diseq_flags |= ATTEMPT_TUNE;
1431        retval = dst_get_tuna(state);
1432werr:
1433        mutex_unlock(&state->dst_mutex);
1434        return retval;
1435
1436error:
1437        mutex_unlock(&state->dst_mutex);
1438        return -EIO;
1439}
1440
1441/*
1442 * line22k0    0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00
1443 * line22k1    0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00
1444 * line22k2    0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00
1445 * tone        0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00
1446 * data        0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00
1447 * power_off   0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
1448 * power_on    0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00
1449 * Diseqc 1    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec
1450 * Diseqc 2    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8
1451 * Diseqc 3    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4
1452 * Diseqc 4    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0
1453 */
1454
1455static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
1456{
1457        struct dst_state *state = fe->demodulator_priv;
1458        u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
1459
1460        if (state->dst_type != DST_TYPE_IS_SAT)
1461                return -EOPNOTSUPP;
1462        if (cmd->msg_len > 0 && cmd->msg_len < 5)
1463                memcpy(&paket[3], cmd->msg, cmd->msg_len);
1464        else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
1465                memcpy(&paket[2], cmd->msg, cmd->msg_len);
1466        else
1467                return -EINVAL;
1468        paket[7] = dst_check_sum(&paket[0], 7);
1469        return dst_command(state, paket, 8);
1470}
1471
1472static int dst_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
1473{
1474        int need_cmd, retval = 0;
1475        struct dst_state *state = fe->demodulator_priv;
1476
1477        state->voltage = voltage;
1478        if (state->dst_type != DST_TYPE_IS_SAT)
1479                return -EOPNOTSUPP;
1480
1481        need_cmd = 0;
1482
1483        switch (voltage) {
1484        case SEC_VOLTAGE_13:
1485        case SEC_VOLTAGE_18:
1486                if ((state->diseq_flags & HAS_POWER) == 0)
1487                        need_cmd = 1;
1488                state->diseq_flags |= HAS_POWER;
1489                state->tx_tuna[4] = 0x01;
1490                break;
1491        case SEC_VOLTAGE_OFF:
1492                need_cmd = 1;
1493                state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
1494                state->tx_tuna[4] = 0x00;
1495                break;
1496        default:
1497                return -EINVAL;
1498        }
1499
1500        if (need_cmd)
1501                retval = dst_tone_power_cmd(state);
1502
1503        return retval;
1504}
1505
1506static int dst_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
1507{
1508        struct dst_state *state = fe->demodulator_priv;
1509
1510        state->tone = tone;
1511        if (state->dst_type != DST_TYPE_IS_SAT)
1512                return -EOPNOTSUPP;
1513
1514        switch (tone) {
1515        case SEC_TONE_OFF:
1516                if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
1517                    state->tx_tuna[2] = 0x00;
1518                else
1519                    state->tx_tuna[2] = 0xff;
1520                break;
1521
1522        case SEC_TONE_ON:
1523                state->tx_tuna[2] = 0x02;
1524                break;
1525        default:
1526                return -EINVAL;
1527        }
1528        return dst_tone_power_cmd(state);
1529}
1530
1531static int dst_send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd minicmd)
1532{
1533        struct dst_state *state = fe->demodulator_priv;
1534
1535        if (state->dst_type != DST_TYPE_IS_SAT)
1536                return -EOPNOTSUPP;
1537        state->minicmd = minicmd;
1538        switch (minicmd) {
1539        case SEC_MINI_A:
1540                state->tx_tuna[3] = 0x02;
1541                break;
1542        case SEC_MINI_B:
1543                state->tx_tuna[3] = 0xff;
1544                break;
1545        }
1546        return dst_tone_power_cmd(state);
1547}
1548
1549
1550static int bt8xx_dst_init(struct dvb_frontend *fe)
1551{
1552        struct dst_state *state = fe->demodulator_priv;
1553
1554        static u8 sat_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x00, 0x73, 0x21, 0x00, 0x00 };
1555        static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
1556        static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
1557        static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
1558        static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
1559        static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
1560        static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
1561
1562        state->inversion = INVERSION_OFF;
1563        state->voltage = SEC_VOLTAGE_13;
1564        state->tone = SEC_TONE_OFF;
1565        state->diseq_flags = 0;
1566        state->k22 = 0x02;
1567        state->bandwidth = 7000000;
1568        state->cur_jiff = jiffies;
1569        if (state->dst_type == DST_TYPE_IS_SAT)
1570                memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
1571        else if (state->dst_type == DST_TYPE_IS_TERR)
1572                memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
1573        else if (state->dst_type == DST_TYPE_IS_CABLE)
1574                memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
1575        else if (state->dst_type == DST_TYPE_IS_ATSC)
1576                memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner));
1577
1578        return 0;
1579}
1580
1581static int dst_read_status(struct dvb_frontend *fe, enum fe_status *status)
1582{
1583        struct dst_state *state = fe->demodulator_priv;
1584
1585        *status = 0;
1586        if (state->diseq_flags & HAS_LOCK) {
1587//              dst_get_signal(state);  // don't require(?) to ask MCU
1588                if (state->decode_lock)
1589                        *status |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI;
1590        }
1591
1592        return 0;
1593}
1594
1595static int dst_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
1596{
1597        struct dst_state *state = fe->demodulator_priv;
1598
1599        int retval = dst_get_signal(state);
1600        *strength = state->decode_strength;
1601
1602        return retval;
1603}
1604
1605static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
1606{
1607        struct dst_state *state = fe->demodulator_priv;
1608
1609        int retval = dst_get_signal(state);
1610        *snr = state->decode_snr;
1611
1612        return retval;
1613}
1614
1615static int dst_set_frontend(struct dvb_frontend *fe)
1616{
1617        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1618        int retval = -EINVAL;
1619        struct dst_state *state = fe->demodulator_priv;
1620
1621        if (p != NULL) {
1622                retval = dst_set_freq(state, p->frequency);
1623                if(retval != 0)
1624                        return retval;
1625                dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
1626
1627                if (state->dst_type == DST_TYPE_IS_SAT) {
1628                        if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
1629                                dst_set_inversion(state, p->inversion);
1630                        dst_set_fec(state, p->fec_inner);
1631                        dst_set_symbolrate(state, p->symbol_rate);
1632                        dst_set_polarization(state);
1633                        dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
1634
1635                } else if (state->dst_type == DST_TYPE_IS_TERR)
1636                        dst_set_bandwidth(state, p->bandwidth_hz);
1637                else if (state->dst_type == DST_TYPE_IS_CABLE) {
1638                        dst_set_fec(state, p->fec_inner);
1639                        dst_set_symbolrate(state, p->symbol_rate);
1640                        dst_set_modulation(state, p->modulation);
1641                }
1642                retval = dst_write_tuna(fe);
1643        }
1644
1645        return retval;
1646}
1647
1648static int dst_tune_frontend(struct dvb_frontend* fe,
1649                            bool re_tune,
1650                            unsigned int mode_flags,
1651                            unsigned int *delay,
1652                            enum fe_status *status)
1653{
1654        struct dst_state *state = fe->demodulator_priv;
1655        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1656
1657        if (re_tune) {
1658                dst_set_freq(state, p->frequency);
1659                dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
1660
1661                if (state->dst_type == DST_TYPE_IS_SAT) {
1662                        if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
1663                                dst_set_inversion(state, p->inversion);
1664                        dst_set_fec(state, p->fec_inner);
1665                        dst_set_symbolrate(state, p->symbol_rate);
1666                        dst_set_polarization(state);
1667                        dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
1668
1669                } else if (state->dst_type == DST_TYPE_IS_TERR)
1670                        dst_set_bandwidth(state, p->bandwidth_hz);
1671                else if (state->dst_type == DST_TYPE_IS_CABLE) {
1672                        dst_set_fec(state, p->fec_inner);
1673                        dst_set_symbolrate(state, p->symbol_rate);
1674                        dst_set_modulation(state, p->modulation);
1675                }
1676                dst_write_tuna(fe);
1677        }
1678
1679        if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
1680                dst_read_status(fe, status);
1681
1682        *delay = HZ/10;
1683        return 0;
1684}
1685
1686static int dst_get_tuning_algo(struct dvb_frontend *fe)
1687{
1688        return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW;
1689}
1690
1691static int dst_get_frontend(struct dvb_frontend *fe)
1692{
1693        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1694        struct dst_state *state = fe->demodulator_priv;
1695
1696        p->frequency = state->decode_freq;
1697        if (state->dst_type == DST_TYPE_IS_SAT) {
1698                if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
1699                        p->inversion = state->inversion;
1700                p->symbol_rate = state->symbol_rate;
1701                p->fec_inner = dst_get_fec(state);
1702        } else if (state->dst_type == DST_TYPE_IS_TERR) {
1703                p->bandwidth_hz = state->bandwidth;
1704        } else if (state->dst_type == DST_TYPE_IS_CABLE) {
1705                p->symbol_rate = state->symbol_rate;
1706                p->fec_inner = dst_get_fec(state);
1707                p->modulation = dst_get_modulation(state);
1708        }
1709
1710        return 0;
1711}
1712
1713static void bt8xx_dst_release(struct dvb_frontend *fe)
1714{
1715        struct dst_state *state = fe->demodulator_priv;
1716        if (state->dst_ca) {
1717                dvb_unregister_device(state->dst_ca);
1718#ifdef CONFIG_MEDIA_ATTACH
1719                symbol_put(dst_ca_attach);
1720#endif
1721        }
1722        kfree(state);
1723}
1724
1725static struct dvb_frontend_ops dst_dvbt_ops;
1726static struct dvb_frontend_ops dst_dvbs_ops;
1727static struct dvb_frontend_ops dst_dvbc_ops;
1728static struct dvb_frontend_ops dst_atsc_ops;
1729
1730struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
1731{
1732        /* check if the ASIC is there */
1733        if (dst_probe(state) < 0) {
1734                kfree(state);
1735                return NULL;
1736        }
1737        /* determine settings based on type */
1738        /* create dvb_frontend */
1739        switch (state->dst_type) {
1740        case DST_TYPE_IS_TERR:
1741                memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
1742                break;
1743        case DST_TYPE_IS_CABLE:
1744                memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
1745                break;
1746        case DST_TYPE_IS_SAT:
1747                memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
1748                break;
1749        case DST_TYPE_IS_ATSC:
1750                memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops));
1751                break;
1752        default:
1753                dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
1754                kfree(state);
1755                return NULL;
1756        }
1757        state->frontend.demodulator_priv = state;
1758
1759        return state;                           /*      Manu (DST is a card not a frontend)     */
1760}
1761
1762EXPORT_SYMBOL(dst_attach);
1763
1764static struct dvb_frontend_ops dst_dvbt_ops = {
1765        .delsys = { SYS_DVBT },
1766        .info = {
1767                .name = "DST DVB-T",
1768                .frequency_min = 137000000,
1769                .frequency_max = 858000000,
1770                .frequency_stepsize = 166667,
1771                .caps = FE_CAN_FEC_AUTO                 |
1772                        FE_CAN_QAM_AUTO                 |
1773                        FE_CAN_QAM_16                   |
1774                        FE_CAN_QAM_32                   |
1775                        FE_CAN_QAM_64                   |
1776                        FE_CAN_QAM_128                  |
1777                        FE_CAN_QAM_256                  |
1778                        FE_CAN_TRANSMISSION_MODE_AUTO   |
1779                        FE_CAN_GUARD_INTERVAL_AUTO
1780        },
1781
1782        .release = bt8xx_dst_release,
1783        .init = bt8xx_dst_init,
1784        .tune = dst_tune_frontend,
1785        .set_frontend = dst_set_frontend,
1786        .get_frontend = dst_get_frontend,
1787        .get_frontend_algo = dst_get_tuning_algo,
1788        .read_status = dst_read_status,
1789        .read_signal_strength = dst_read_signal_strength,
1790        .read_snr = dst_read_snr,
1791};
1792
1793static struct dvb_frontend_ops dst_dvbs_ops = {
1794        .delsys = { SYS_DVBS },
1795        .info = {
1796                .name = "DST DVB-S",
1797                .frequency_min = 950000,
1798                .frequency_max = 2150000,
1799                .frequency_stepsize = 1000,     /* kHz for QPSK frontends */
1800                .frequency_tolerance = 29500,
1801                .symbol_rate_min = 1000000,
1802                .symbol_rate_max = 45000000,
1803        /*     . symbol_rate_tolerance  =       ???,*/
1804                .caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK
1805        },
1806
1807        .release = bt8xx_dst_release,
1808        .init = bt8xx_dst_init,
1809        .tune = dst_tune_frontend,
1810        .set_frontend = dst_set_frontend,
1811        .get_frontend = dst_get_frontend,
1812        .get_frontend_algo = dst_get_tuning_algo,
1813        .read_status = dst_read_status,
1814        .read_signal_strength = dst_read_signal_strength,
1815        .read_snr = dst_read_snr,
1816        .diseqc_send_burst = dst_send_burst,
1817        .diseqc_send_master_cmd = dst_set_diseqc,
1818        .set_voltage = dst_set_voltage,
1819        .set_tone = dst_set_tone,
1820};
1821
1822static struct dvb_frontend_ops dst_dvbc_ops = {
1823        .delsys = { SYS_DVBC_ANNEX_A },
1824        .info = {
1825                .name = "DST DVB-C",
1826                .frequency_stepsize = 62500,
1827                .frequency_min = 51000000,
1828                .frequency_max = 858000000,
1829                .symbol_rate_min = 1000000,
1830                .symbol_rate_max = 45000000,
1831                .caps = FE_CAN_FEC_AUTO |
1832                        FE_CAN_QAM_AUTO |
1833                        FE_CAN_QAM_16   |
1834                        FE_CAN_QAM_32   |
1835                        FE_CAN_QAM_64   |
1836                        FE_CAN_QAM_128  |
1837                        FE_CAN_QAM_256
1838        },
1839
1840        .release = bt8xx_dst_release,
1841        .init = bt8xx_dst_init,
1842        .tune = dst_tune_frontend,
1843        .set_frontend = dst_set_frontend,
1844        .get_frontend = dst_get_frontend,
1845        .get_frontend_algo = dst_get_tuning_algo,
1846        .read_status = dst_read_status,
1847        .read_signal_strength = dst_read_signal_strength,
1848        .read_snr = dst_read_snr,
1849};
1850
1851static struct dvb_frontend_ops dst_atsc_ops = {
1852        .delsys = { SYS_ATSC },
1853        .info = {
1854                .name = "DST ATSC",
1855                .frequency_stepsize = 62500,
1856                .frequency_min = 510000000,
1857                .frequency_max = 858000000,
1858                .symbol_rate_min = 1000000,
1859                .symbol_rate_max = 45000000,
1860                .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
1861        },
1862
1863        .release = bt8xx_dst_release,
1864        .init = bt8xx_dst_init,
1865        .tune = dst_tune_frontend,
1866        .set_frontend = dst_set_frontend,
1867        .get_frontend = dst_get_frontend,
1868        .get_frontend_algo = dst_get_tuning_algo,
1869        .read_status = dst_read_status,
1870        .read_signal_strength = dst_read_signal_strength,
1871        .read_snr = dst_read_snr,
1872};
1873
1874MODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver");
1875MODULE_AUTHOR("Jamie Honan, Manu Abraham");
1876MODULE_LICENSE("GPL");
1877