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, fe_spectral_inversion_t inversion)
 429{
 430        state->inversion = inversion;
 431        switch (inversion) {
 432        case INVERSION_OFF:     /*      Inversion = Normal      */
 433                state->tx_tuna[8] &= ~0x80;
 434                break;
 435        case INVERSION_ON:
 436                state->tx_tuna[8] |= 0x80;
 437                break;
 438        default:
 439                return -EINVAL;
 440        }
 441
 442        return 0;
 443}
 444
 445static int dst_set_fec(struct dst_state *state, fe_code_rate_t fec)
 446{
 447        state->fec = fec;
 448        return 0;
 449}
 450
 451static fe_code_rate_t dst_get_fec(struct dst_state *state)
 452{
 453        return state->fec;
 454}
 455
 456static int dst_set_symbolrate(struct dst_state *state, u32 srate)
 457{
 458        u32 symcalc;
 459        u64 sval;
 460
 461        state->symbol_rate = srate;
 462        if (state->dst_type == DST_TYPE_IS_TERR) {
 463                return -EOPNOTSUPP;
 464        }
 465        dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
 466        srate /= 1000;
 467        if (state->dst_type == DST_TYPE_IS_SAT) {
 468                if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
 469                        sval = srate;
 470                        sval <<= 20;
 471                        do_div(sval, 88000);
 472                        symcalc = (u32) sval;
 473                        dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
 474                        state->tx_tuna[5] = (u8) (symcalc >> 12);
 475                        state->tx_tuna[6] = (u8) (symcalc >> 4);
 476                        state->tx_tuna[7] = (u8) (symcalc << 4);
 477                } else {
 478                        state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
 479                        state->tx_tuna[6] = (u8) (srate >> 8);
 480                        state->tx_tuna[7] = (u8) srate;
 481                }
 482                state->tx_tuna[8] &= ~0x20;
 483                if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
 484                        if (srate > 8000)
 485                                state->tx_tuna[8] |= 0x20;
 486                }
 487        } else if (state->dst_type == DST_TYPE_IS_CABLE) {
 488                dprintk(verbose, DST_DEBUG, 1, "%s", state->fw_name);
 489                if (!strncmp(state->fw_name, "DCTNEW", 6)) {
 490                        state->tx_tuna[5] = (u8) (srate >> 8);
 491                        state->tx_tuna[6] = (u8) srate;
 492                        state->tx_tuna[7] = 0x00;
 493                } else if (!strncmp(state->fw_name, "DCT-CI", 6)) {
 494                        state->tx_tuna[5] = 0x00;
 495                        state->tx_tuna[6] = (u8) (srate >> 8);
 496                        state->tx_tuna[7] = (u8) srate;
 497                }
 498        }
 499        return 0;
 500}
 501
 502static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
 503{
 504        if (state->dst_type != DST_TYPE_IS_CABLE)
 505                return -EOPNOTSUPP;
 506
 507        state->modulation = modulation;
 508        switch (modulation) {
 509        case QAM_16:
 510                state->tx_tuna[8] = 0x10;
 511                break;
 512        case QAM_32:
 513                state->tx_tuna[8] = 0x20;
 514                break;
 515        case QAM_64:
 516                state->tx_tuna[8] = 0x40;
 517                break;
 518        case QAM_128:
 519                state->tx_tuna[8] = 0x80;
 520                break;
 521        case QAM_256:
 522                if (!strncmp(state->fw_name, "DCTNEW", 6))
 523                        state->tx_tuna[8] = 0xff;
 524                else if (!strncmp(state->fw_name, "DCT-CI", 6))
 525                        state->tx_tuna[8] = 0x00;
 526                break;
 527        case QPSK:
 528        case QAM_AUTO:
 529        case VSB_8:
 530        case VSB_16:
 531        default:
 532                return -EINVAL;
 533
 534        }
 535
 536        return 0;
 537}
 538
 539static fe_modulation_t dst_get_modulation(struct dst_state *state)
 540{
 541        return state->modulation;
 542}
 543
 544
 545u8 dst_check_sum(u8 *buf, u32 len)
 546{
 547        u32 i;
 548        u8 val = 0;
 549        if (!len)
 550                return 0;
 551        for (i = 0; i < len; i++) {
 552                val += buf[i];
 553        }
 554        return ((~val) + 1);
 555}
 556EXPORT_SYMBOL(dst_check_sum);
 557
 558static void dst_type_flags_print(struct dst_state *state)
 559{
 560        u32 type_flags = state->type_flags;
 561
 562        dprintk(verbose, DST_ERROR, 0, "DST type flags :");
 563        if (type_flags & DST_TYPE_HAS_TS188)
 564                dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_TS188);
 565        if (type_flags & DST_TYPE_HAS_NEWTUNE_2)
 566                dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner 2", DST_TYPE_HAS_NEWTUNE_2);
 567        if (type_flags & DST_TYPE_HAS_TS204)
 568                dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
 569        if (type_flags & DST_TYPE_HAS_VLF)
 570                dprintk(verbose, DST_ERROR, 0, " 0x%x VLF", DST_TYPE_HAS_VLF);
 571        if (type_flags & DST_TYPE_HAS_SYMDIV)
 572                dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
 573        if (type_flags & DST_TYPE_HAS_FW_1)
 574                dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
 575        if (type_flags & DST_TYPE_HAS_FW_2)
 576                dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
 577        if (type_flags & DST_TYPE_HAS_FW_3)
 578                dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
 579        dprintk(verbose, DST_ERROR, 0, "\n");
 580}
 581
 582
 583static int dst_type_print(struct dst_state *state, u8 type)
 584{
 585        char *otype;
 586        switch (type) {
 587        case DST_TYPE_IS_SAT:
 588                otype = "satellite";
 589                break;
 590
 591        case DST_TYPE_IS_TERR:
 592                otype = "terrestrial";
 593                break;
 594
 595        case DST_TYPE_IS_CABLE:
 596                otype = "cable";
 597                break;
 598
 599        case DST_TYPE_IS_ATSC:
 600                otype = "atsc";
 601                break;
 602
 603        default:
 604                dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
 605                return -EINVAL;
 606        }
 607        dprintk(verbose, DST_INFO, 1, "DST type: %s", otype);
 608
 609        return 0;
 610}
 611
 612static struct tuner_types tuner_list[] = {
 613        {
 614                .tuner_type = TUNER_TYPE_L64724,
 615                .tuner_name = "L 64724",
 616                .board_name = "UNKNOWN",
 617                .fw_name    = "UNKNOWN"
 618        },
 619
 620        {
 621                .tuner_type = TUNER_TYPE_STV0299,
 622                .tuner_name = "STV 0299",
 623                .board_name = "VP1020",
 624                .fw_name    = "DST-MOT"
 625        },
 626
 627        {
 628                .tuner_type = TUNER_TYPE_STV0299,
 629                .tuner_name = "STV 0299",
 630                .board_name = "VP1020",
 631                .fw_name    = "DST-03T"
 632        },
 633
 634        {
 635                .tuner_type = TUNER_TYPE_MB86A15,
 636                .tuner_name = "MB 86A15",
 637                .board_name = "VP1022",
 638                .fw_name    = "DST-03T"
 639        },
 640
 641        {
 642                .tuner_type = TUNER_TYPE_MB86A15,
 643                .tuner_name = "MB 86A15",
 644                .board_name = "VP1025",
 645                .fw_name    = "DST-03T"
 646        },
 647
 648        {
 649                .tuner_type = TUNER_TYPE_STV0299,
 650                .tuner_name = "STV 0299",
 651                .board_name = "VP1030",
 652                .fw_name    = "DST-CI"
 653        },
 654
 655        {
 656                .tuner_type = TUNER_TYPE_STV0299,
 657                .tuner_name = "STV 0299",
 658                .board_name = "VP1030",
 659                .fw_name    = "DSTMCI"
 660        },
 661
 662        {
 663                .tuner_type = TUNER_TYPE_UNKNOWN,
 664                .tuner_name = "UNKNOWN",
 665                .board_name = "VP2021",
 666                .fw_name    = "DCTNEW"
 667        },
 668
 669        {
 670                .tuner_type = TUNER_TYPE_UNKNOWN,
 671                .tuner_name = "UNKNOWN",
 672                .board_name = "VP2030",
 673                .fw_name    = "DCT-CI"
 674        },
 675
 676        {
 677                .tuner_type = TUNER_TYPE_UNKNOWN,
 678                .tuner_name = "UNKNOWN",
 679                .board_name = "VP2031",
 680                .fw_name    = "DCT-CI"
 681        },
 682
 683        {
 684                .tuner_type = TUNER_TYPE_UNKNOWN,
 685                .tuner_name = "UNKNOWN",
 686                .board_name = "VP2040",
 687                .fw_name    = "DCT-CI"
 688        },
 689
 690        {
 691                .tuner_type = TUNER_TYPE_UNKNOWN,
 692                .tuner_name = "UNKNOWN",
 693                .board_name = "VP3020",
 694                .fw_name    = "DTTFTA"
 695        },
 696
 697        {
 698                .tuner_type = TUNER_TYPE_UNKNOWN,
 699                .tuner_name = "UNKNOWN",
 700                .board_name = "VP3021",
 701                .fw_name    = "DTTFTA"
 702        },
 703
 704        {
 705                .tuner_type = TUNER_TYPE_TDA10046,
 706                .tuner_name = "TDA10046",
 707                .board_name = "VP3040",
 708                .fw_name    = "DTT-CI"
 709        },
 710
 711        {
 712                .tuner_type = TUNER_TYPE_UNKNOWN,
 713                .tuner_name = "UNKNOWN",
 714                .board_name = "VP3051",
 715                .fw_name    = "DTTNXT"
 716        },
 717
 718        {
 719                .tuner_type = TUNER_TYPE_NXT200x,
 720                .tuner_name = "NXT200x",
 721                .board_name = "VP3220",
 722                .fw_name    = "ATSCDI"
 723        },
 724
 725        {
 726                .tuner_type = TUNER_TYPE_NXT200x,
 727                .tuner_name = "NXT200x",
 728                .board_name = "VP3250",
 729                .fw_name    = "ATSCAD"
 730        },
 731};
 732
 733/*
 734        Known cards list
 735        Satellite
 736        -------------------
 737                  200103A
 738        VP-1020   DST-MOT       LG(old), TS=188
 739
 740        VP-1020   DST-03T       LG(new), TS=204
 741        VP-1022   DST-03T       LG(new), TS=204
 742        VP-1025   DST-03T       LG(new), TS=204
 743
 744        VP-1030   DSTMCI,       LG(new), TS=188
 745        VP-1032   DSTMCI,       LG(new), TS=188
 746
 747        Cable
 748        -------------------
 749        VP-2030   DCT-CI,       Samsung, TS=204
 750        VP-2021   DCT-CI,       Unknown, TS=204
 751        VP-2031   DCT-CI,       Philips, TS=188
 752        VP-2040   DCT-CI,       Philips, TS=188, with CA daughter board
 753        VP-2040   DCT-CI,       Philips, TS=204, without CA daughter board
 754
 755        Terrestrial
 756        -------------------
 757        VP-3050  DTTNXT                  TS=188
 758        VP-3040  DTT-CI,        Philips, TS=188
 759        VP-3040  DTT-CI,        Philips, TS=204
 760
 761        ATSC
 762        -------------------
 763        VP-3220  ATSCDI,                 TS=188
 764        VP-3250  ATSCAD,                 TS=188
 765
 766*/
 767
 768static struct dst_types dst_tlist[] = {
 769        {
 770                .device_id = "200103A",
 771                .offset = 0,
 772                .dst_type =  DST_TYPE_IS_SAT,
 773                .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS,
 774                .dst_feature = 0,
 775                .tuner_type = 0
 776        },      /*      obsolete        */
 777
 778        {
 779                .device_id = "DST-020",
 780                .offset = 0,
 781                .dst_type =  DST_TYPE_IS_SAT,
 782                .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
 783                .dst_feature = 0,
 784                .tuner_type = 0
 785        },      /*      obsolete        */
 786
 787        {
 788                .device_id = "DST-030",
 789                .offset =  0,
 790                .dst_type = DST_TYPE_IS_SAT,
 791                .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
 792                .dst_feature = 0,
 793                .tuner_type = 0
 794        },      /*      obsolete        */
 795
 796        {
 797                .device_id = "DST-03T",
 798                .offset = 0,
 799                .dst_type = DST_TYPE_IS_SAT,
 800                .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
 801                .dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
 802                                                         | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO,
 803                .tuner_type = TUNER_TYPE_MULTI
 804         },
 805
 806        {
 807                .device_id = "DST-MOT",
 808                .offset =  0,
 809                .dst_type = DST_TYPE_IS_SAT,
 810                .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
 811                .dst_feature = 0,
 812                .tuner_type = 0
 813        },      /*      obsolete        */
 814
 815        {
 816                .device_id = "DST-CI",
 817                .offset = 1,
 818                .dst_type = DST_TYPE_IS_SAT,
 819                .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1,
 820                .dst_feature = DST_TYPE_HAS_CA,
 821                .tuner_type = 0
 822        },      /*      An OEM board    */
 823
 824        {
 825                .device_id = "DSTMCI",
 826                .offset = 1,
 827                .dst_type = DST_TYPE_IS_SAT,
 828                .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,
 829                .dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
 830                                                        | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC,
 831                .tuner_type = TUNER_TYPE_MULTI
 832        },
 833
 834        {
 835                .device_id = "DSTFCI",
 836                .offset = 1,
 837                .dst_type = DST_TYPE_IS_SAT,
 838                .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
 839                .dst_feature = 0,
 840                .tuner_type = 0
 841        },      /* unknown to vendor    */
 842
 843        {
 844                .device_id = "DCT-CI",
 845                .offset = 1,
 846                .dst_type = DST_TYPE_IS_CABLE,
 847                .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF,
 848                .dst_feature = DST_TYPE_HAS_CA,
 849                .tuner_type = 0
 850        },
 851
 852        {
 853                .device_id = "DCTNEW",
 854                .offset = 1,
 855                .dst_type = DST_TYPE_IS_CABLE,
 856                .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE,
 857                .dst_feature = 0,
 858                .tuner_type = 0
 859        },
 860
 861        {
 862                .device_id = "DTT-CI",
 863                .offset = 1,
 864                .dst_type = DST_TYPE_IS_TERR,
 865                .type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF,
 866                .dst_feature = DST_TYPE_HAS_CA,
 867                .tuner_type = 0
 868        },
 869
 870        {
 871                .device_id = "DTTDIG",
 872                .offset = 1,
 873                .dst_type = DST_TYPE_IS_TERR,
 874                .type_flags = DST_TYPE_HAS_FW_2,
 875                .dst_feature = 0,
 876                .tuner_type = 0
 877        },
 878
 879        {
 880                .device_id = "DTTNXT",
 881                .offset = 1,
 882                .dst_type = DST_TYPE_IS_TERR,
 883                .type_flags = DST_TYPE_HAS_FW_2,
 884                .dst_feature = DST_TYPE_HAS_ANALOG,
 885                .tuner_type = 0
 886        },
 887
 888        {
 889                .device_id = "ATSCDI",
 890                .offset = 1,
 891                .dst_type = DST_TYPE_IS_ATSC,
 892                .type_flags = DST_TYPE_HAS_FW_2,
 893                .dst_feature = 0,
 894                .tuner_type = 0
 895        },
 896
 897        {
 898                .device_id = "ATSCAD",
 899                .offset = 1,
 900                .dst_type = DST_TYPE_IS_ATSC,
 901                .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
 902                .dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG,
 903                .tuner_type = 0
 904        },
 905
 906        { }
 907
 908};
 909
 910static int dst_get_mac(struct dst_state *state)
 911{
 912        u8 get_mac[] = { 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 913        get_mac[7] = dst_check_sum(get_mac, 7);
 914        if (dst_command(state, get_mac, 8) < 0) {
 915                dprintk(verbose, DST_INFO, 1, "Unsupported Command");
 916                return -1;
 917        }
 918        memset(&state->mac_address, '\0', 8);
 919        memcpy(&state->mac_address, &state->rxbuffer, 6);
 920        dprintk(verbose, DST_ERROR, 1, "MAC Address=[%pM]", state->mac_address);
 921
 922        return 0;
 923}
 924
 925static int dst_fw_ver(struct dst_state *state)
 926{
 927        u8 get_ver[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 928        get_ver[7] = dst_check_sum(get_ver, 7);
 929        if (dst_command(state, get_ver, 8) < 0) {
 930                dprintk(verbose, DST_INFO, 1, "Unsupported Command");
 931                return -1;
 932        }
 933        memcpy(&state->fw_version, &state->rxbuffer, 8);
 934        dprintk(verbose, DST_ERROR, 1, "Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x",
 935                state->fw_version[0] >> 4, state->fw_version[0] & 0x0f,
 936                state->fw_version[1],
 937                state->fw_version[5], state->fw_version[6],
 938                state->fw_version[4], state->fw_version[3], state->fw_version[2]);
 939
 940        return 0;
 941}
 942
 943static int dst_card_type(struct dst_state *state)
 944{
 945        int j;
 946        struct tuner_types *p_tuner_list = NULL;
 947
 948        u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 949        get_type[7] = dst_check_sum(get_type, 7);
 950        if (dst_command(state, get_type, 8) < 0) {
 951                dprintk(verbose, DST_INFO, 1, "Unsupported Command");
 952                return -1;
 953        }
 954        memset(&state->card_info, '\0', 8);
 955        memcpy(&state->card_info, &state->rxbuffer, 7);
 956        dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
 957
 958        for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
 959                if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) {
 960                        state->tuner_type = p_tuner_list->tuner_type;
 961                        dprintk(verbose, DST_ERROR, 1, "DST has [%s] tuner, tuner type=[%d]",
 962                                p_tuner_list->tuner_name, p_tuner_list->tuner_type);
 963                }
 964        }
 965
 966        return 0;
 967}
 968
 969static int dst_get_vendor(struct dst_state *state)
 970{
 971        u8 get_vendor[] = { 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 972        get_vendor[7] = dst_check_sum(get_vendor, 7);
 973        if (dst_command(state, get_vendor, 8) < 0) {
 974                dprintk(verbose, DST_INFO, 1, "Unsupported Command");
 975                return -1;
 976        }
 977        memset(&state->vendor, '\0', 8);
 978        memcpy(&state->vendor, &state->rxbuffer, 7);
 979        dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
 980
 981        return 0;
 982}
 983
 984static void debug_dst_buffer(struct dst_state *state)
 985{
 986        int i;
 987
 988        if (verbose > 2) {
 989                printk("%s: [", __func__);
 990                for (i = 0; i < 8; i++)
 991                        printk(" %02x", state->rxbuffer[i]);
 992                printk("]\n");
 993        }
 994}
 995
 996static int dst_check_stv0299(struct dst_state *state)
 997{
 998        u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 999
1000        check_stv0299[7] = dst_check_sum(check_stv0299, 7);
1001        if (dst_command(state, check_stv0299, 8) < 0) {
1002                dprintk(verbose, DST_ERROR, 1, "Cmd=[0x04] failed");
1003                return -1;
1004        }
1005        debug_dst_buffer(state);
1006
1007        if (memcmp(&check_stv0299, &state->rxbuffer, 8)) {
1008                dprintk(verbose, DST_ERROR, 1, "Found a STV0299 NIM");
1009                state->tuner_type = TUNER_TYPE_STV0299;
1010                return 0;
1011        }
1012
1013        return -1;
1014}
1015
1016static int dst_check_mb86a15(struct dst_state *state)
1017{
1018        u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1019
1020        check_mb86a15[7] = dst_check_sum(check_mb86a15, 7);
1021        if (dst_command(state, check_mb86a15, 8) < 0) {
1022                dprintk(verbose, DST_ERROR, 1, "Cmd=[0x10], failed");
1023                return -1;
1024        }
1025        debug_dst_buffer(state);
1026
1027        if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) {
1028                dprintk(verbose, DST_ERROR, 1, "Found a MB86A15 NIM");
1029                state->tuner_type = TUNER_TYPE_MB86A15;
1030                return 0;
1031        }
1032
1033        return -1;
1034}
1035
1036static int dst_get_tuner_info(struct dst_state *state)
1037{
1038        u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1039        u8 get_tuner_2[] = { 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1040
1041        get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
1042        get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
1043        dprintk(verbose, DST_ERROR, 1, "DST TYpe = MULTI FE");
1044        if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
1045                if (dst_command(state, get_tuner_1, 8) < 0) {
1046                        dprintk(verbose, DST_INFO, 1, "Cmd=[0x13], Unsupported");
1047                        goto force;
1048                }
1049        } else {
1050                if (dst_command(state, get_tuner_2, 8) < 0) {
1051                        dprintk(verbose, DST_INFO, 1, "Cmd=[0xb], Unsupported");
1052                        goto force;
1053                }
1054        }
1055        memcpy(&state->board_info, &state->rxbuffer, 8);
1056        if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
1057                dprintk(verbose, DST_ERROR, 1, "DST type has TS=188");
1058        }
1059        if (state->board_info[0] == 0xbc) {
1060                if (state->dst_type != DST_TYPE_IS_ATSC)
1061                        state->type_flags |= DST_TYPE_HAS_TS188;
1062                else
1063                        state->type_flags |= DST_TYPE_HAS_NEWTUNE_2;
1064
1065                if (state->board_info[1] == 0x01) {
1066                        state->dst_hw_cap |= DST_TYPE_HAS_DBOARD;
1067                        dprintk(verbose, DST_ERROR, 1, "DST has Daughterboard");
1068                }
1069        }
1070
1071        return 0;
1072force:
1073        if (!strncmp(state->fw_name, "DCT-CI", 6)) {
1074                state->type_flags |= DST_TYPE_HAS_TS204;
1075                dprintk(verbose, DST_ERROR, 1, "Forcing [%s] to TS188", state->fw_name);
1076        }
1077
1078        return -1;
1079}
1080
1081static int dst_get_device_id(struct dst_state *state)
1082{
1083        u8 reply;
1084
1085        int i, j;
1086        struct dst_types *p_dst_type = NULL;
1087        struct tuner_types *p_tuner_list = NULL;
1088
1089        u8 use_dst_type = 0;
1090        u32 use_type_flags = 0;
1091
1092        static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
1093
1094        state->tuner_type = 0;
1095        device_type[7] = dst_check_sum(device_type, 7);
1096
1097        if (write_dst(state, device_type, FIXED_COMM))
1098                return -1;              /*      Write failed            */
1099        if ((dst_pio_disable(state)) < 0)
1100                return -1;
1101        if (read_dst(state, &reply, GET_ACK))
1102                return -1;              /*      Read failure            */
1103        if (reply != ACK) {
1104                dprintk(verbose, DST_INFO, 1, "Write not Acknowledged! [Reply=0x%02x]", reply);
1105                return -1;              /*      Unack'd write           */
1106        }
1107        if (!dst_wait_dst_ready(state, DEVICE_INIT))
1108                return -1;              /*      DST not ready yet       */
1109        if (read_dst(state, state->rxbuffer, FIXED_COMM))
1110                return -1;
1111
1112        dst_pio_disable(state);
1113        if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
1114                dprintk(verbose, DST_INFO, 1, "Checksum failure!");
1115                return -1;              /*      Checksum failure        */
1116        }
1117        state->rxbuffer[7] = '\0';
1118
1119        for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE(dst_tlist); i++, p_dst_type++) {
1120                if (!strncmp (&state->rxbuffer[p_dst_type->offset], p_dst_type->device_id, strlen (p_dst_type->device_id))) {
1121                        use_type_flags = p_dst_type->type_flags;
1122                        use_dst_type = p_dst_type->dst_type;
1123
1124                        /*      Card capabilities       */
1125                        state->dst_hw_cap = p_dst_type->dst_feature;
1126                        dprintk(verbose, DST_ERROR, 1, "Recognise [%s]", p_dst_type->device_id);
1127                        strncpy(&state->fw_name[0], p_dst_type->device_id, 6);
1128                        /*      Multiple tuners         */
1129                        if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) {
1130                                switch (use_dst_type) {
1131                                case DST_TYPE_IS_SAT:
1132                                        /*      STV0299 check   */
1133                                        if (dst_check_stv0299(state) < 0) {
1134                                                dprintk(verbose, DST_ERROR, 1, "Unsupported");
1135                                                state->tuner_type = TUNER_TYPE_MB86A15;
1136                                        }
1137                                        break;
1138                                default:
1139                                        break;
1140                                }
1141                                if (dst_check_mb86a15(state) < 0)
1142                                        dprintk(verbose, DST_ERROR, 1, "Unsupported");
1143                        /*      Single tuner            */
1144                        } else {
1145                                state->tuner_type = p_dst_type->tuner_type;
1146                        }
1147                        for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
1148                                if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) &&
1149                                        p_tuner_list->tuner_type == state->tuner_type) {
1150                                        dprintk(verbose, DST_ERROR, 1, "[%s] has a [%s]",
1151                                                p_dst_type->device_id, p_tuner_list->tuner_name);
1152                                }
1153                        }
1154                        break;
1155                }
1156        }
1157
1158        if (i >= ARRAY_SIZE(dst_tlist)) {
1159                dprintk(verbose, DST_ERROR, 1, "Unable to recognize %s or %s", &state->rxbuffer[0], &state->rxbuffer[1]);
1160                dprintk(verbose, DST_ERROR, 1, "please email linux-dvb@linuxtv.org with this type in");
1161                use_dst_type = DST_TYPE_IS_SAT;
1162                use_type_flags = DST_TYPE_HAS_SYMDIV;
1163        }
1164        dst_type_print(state, use_dst_type);
1165        state->type_flags = use_type_flags;
1166        state->dst_type = use_dst_type;
1167        dst_type_flags_print(state);
1168
1169        return 0;
1170}
1171
1172static int dst_probe(struct dst_state *state)
1173{
1174        mutex_init(&state->dst_mutex);
1175        if (dst_addons & DST_TYPE_HAS_CA) {
1176                if ((rdc_8820_reset(state)) < 0) {
1177                        dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
1178                        return -1;
1179                }
1180                msleep(4000);
1181        } else {
1182                msleep(100);
1183        }
1184        if ((dst_comm_init(state)) < 0) {
1185                dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
1186                return -1;
1187        }
1188        msleep(100);
1189        if (dst_get_device_id(state) < 0) {
1190                dprintk(verbose, DST_ERROR, 1, "unknown device.");
1191                return -1;
1192        }
1193        if (dst_get_mac(state) < 0) {
1194                dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
1195        }
1196        if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) {
1197                if (dst_get_tuner_info(state) < 0)
1198                        dprintk(verbose, DST_INFO, 1, "Tuner: Unsupported command");
1199        }
1200        if (state->type_flags & DST_TYPE_HAS_TS204) {
1201                dst_packsize(state, 204);
1202        }
1203        if (state->type_flags & DST_TYPE_HAS_FW_BUILD) {
1204                if (dst_fw_ver(state) < 0) {
1205                        dprintk(verbose, DST_INFO, 1, "FW: Unsupported command");
1206                        return 0;
1207                }
1208                if (dst_card_type(state) < 0) {
1209                        dprintk(verbose, DST_INFO, 1, "Card: Unsupported command");
1210                        return 0;
1211                }
1212                if (dst_get_vendor(state) < 0) {
1213                        dprintk(verbose, DST_INFO, 1, "Vendor: Unsupported command");
1214                        return 0;
1215                }
1216        }
1217
1218        return 0;
1219}
1220
1221static int dst_command(struct dst_state *state, u8 *data, u8 len)
1222{
1223        u8 reply;
1224
1225        mutex_lock(&state->dst_mutex);
1226        if ((dst_comm_init(state)) < 0) {
1227                dprintk(verbose, DST_NOTICE, 1, "DST Communication Initialization Failed.");
1228                goto error;
1229        }
1230        if (write_dst(state, data, len)) {
1231                dprintk(verbose, DST_INFO, 1, "Trying to recover.. ");
1232                if ((dst_error_recovery(state)) < 0) {
1233                        dprintk(verbose, DST_ERROR, 1, "Recovery Failed.");
1234                        goto error;
1235                }
1236                goto error;
1237        }
1238        if ((dst_pio_disable(state)) < 0) {
1239                dprintk(verbose, DST_ERROR, 1, "PIO Disable Failed.");
1240                goto error;
1241        }
1242        if (state->type_flags & DST_TYPE_HAS_FW_1)
1243                mdelay(3);
1244        if (read_dst(state, &reply, GET_ACK)) {
1245                dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
1246                if ((dst_error_recovery(state)) < 0) {
1247                        dprintk(verbose, DST_INFO, 1, "Recovery Failed.");
1248                        goto error;
1249                }
1250                goto error;
1251        }
1252        if (reply != ACK) {
1253                dprintk(verbose, DST_INFO, 1, "write not acknowledged 0x%02x ", reply);
1254                goto error;
1255        }
1256        if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
1257                goto error;
1258        if (state->type_flags & DST_TYPE_HAS_FW_1)
1259                mdelay(3);
1260        else
1261                udelay(2000);
1262        if (!dst_wait_dst_ready(state, NO_DELAY))
1263                goto error;
1264        if (read_dst(state, state->rxbuffer, FIXED_COMM)) {
1265                dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
1266                if ((dst_error_recovery(state)) < 0) {
1267                        dprintk(verbose, DST_INFO, 1, "Recovery failed.");
1268                        goto error;
1269                }
1270                goto error;
1271        }
1272        if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
1273                dprintk(verbose, DST_INFO, 1, "checksum failure");
1274                goto error;
1275        }
1276        mutex_unlock(&state->dst_mutex);
1277        return 0;
1278
1279error:
1280        mutex_unlock(&state->dst_mutex);
1281        return -EIO;
1282
1283}
1284
1285static int dst_get_signal(struct dst_state *state)
1286{
1287        int retval;
1288        u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
1289        //dprintk("%s: Getting Signal strength and other parameters\n", __func__);
1290        if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
1291                state->decode_lock = state->decode_strength = state->decode_snr = 0;
1292                return 0;
1293        }
1294        if (0 == (state->diseq_flags & HAS_LOCK)) {
1295                state->decode_lock = state->decode_strength = state->decode_snr = 0;
1296                return 0;
1297        }
1298        if (time_after_eq(jiffies, state->cur_jiff + (HZ / 5))) {
1299                retval = dst_command(state, get_signal, 8);
1300                if (retval < 0)
1301                        return retval;
1302                if (state->dst_type == DST_TYPE_IS_SAT) {
1303                        state->decode_lock = ((state->rxbuffer[6] & 0x10) == 0) ? 1 : 0;
1304                        state->decode_strength = state->rxbuffer[5] << 8;
1305                        state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
1306                } else if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE)) {
1307                        state->decode_lock = (state->rxbuffer[1]) ? 1 : 0;
1308                        state->decode_strength = state->rxbuffer[4] << 8;
1309                        state->decode_snr = state->rxbuffer[3] << 8;
1310                } else if (state->dst_type == DST_TYPE_IS_ATSC) {
1311                        state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0;
1312                        state->decode_strength = state->rxbuffer[4] << 8;
1313                        state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
1314                }
1315                state->cur_jiff = jiffies;
1316        }
1317        return 0;
1318}
1319
1320static int dst_tone_power_cmd(struct dst_state *state)
1321{
1322        u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 };
1323
1324        if (state->dst_type != DST_TYPE_IS_SAT)
1325                return -EOPNOTSUPP;
1326        paket[4] = state->tx_tuna[4];
1327        paket[2] = state->tx_tuna[2];
1328        paket[3] = state->tx_tuna[3];
1329        paket[7] = dst_check_sum (paket, 7);
1330        return dst_command(state, paket, 8);
1331}
1332
1333static int dst_get_tuna(struct dst_state *state)
1334{
1335        int retval;
1336
1337        if ((state->diseq_flags & ATTEMPT_TUNE) == 0)
1338                return 0;
1339        state->diseq_flags &= ~(HAS_LOCK);
1340        if (!dst_wait_dst_ready(state, NO_DELAY))
1341                return -EIO;
1342        if ((state->type_flags & DST_TYPE_HAS_VLF) &&
1343                !(state->dst_type == DST_TYPE_IS_ATSC))
1344
1345                retval = read_dst(state, state->rx_tuna, 10);
1346        else
1347                retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
1348        if (retval < 0) {
1349                dprintk(verbose, DST_DEBUG, 1, "read not successful");
1350                return retval;
1351        }
1352        if ((state->type_flags & DST_TYPE_HAS_VLF) &&
1353           !(state->dst_type == DST_TYPE_IS_ATSC)) {
1354
1355                if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
1356                        dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
1357                        return -EIO;
1358                }
1359        } else {
1360                if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) {
1361                        dprintk(verbose, DST_INFO, 1, "checksum failure? ");
1362                        return -EIO;
1363                }
1364        }
1365        if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0)
1366                return 0;
1367        if (state->dst_type == DST_TYPE_IS_SAT) {
1368                state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3];
1369        } else {
1370                state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 16) + (state->rx_tuna[3] << 8) + state->rx_tuna[4];
1371        }
1372        state->decode_freq = state->decode_freq * 1000;
1373        state->decode_lock = 1;
1374        state->diseq_flags |= HAS_LOCK;
1375
1376        return 1;
1377}
1378
1379static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
1380
1381static int dst_write_tuna(struct dvb_frontend *fe)
1382{
1383        struct dst_state *state = fe->demodulator_priv;
1384        int retval;
1385        u8 reply;
1386
1387        dprintk(verbose, DST_INFO, 1, "type_flags 0x%x ", state->type_flags);
1388        state->decode_freq = 0;
1389        state->decode_lock = state->decode_strength = state->decode_snr = 0;
1390        if (state->dst_type == DST_TYPE_IS_SAT) {
1391                if (!(state->diseq_flags & HAS_POWER))
1392                        dst_set_voltage(fe, SEC_VOLTAGE_13);
1393        }
1394        state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
1395        mutex_lock(&state->dst_mutex);
1396        if ((dst_comm_init(state)) < 0) {
1397                dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
1398                goto error;
1399        }
1400//      if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
1401        if ((state->type_flags & DST_TYPE_HAS_VLF) &&
1402                (!(state->dst_type == DST_TYPE_IS_ATSC))) {
1403
1404                state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
1405                retval = write_dst(state, &state->tx_tuna[0], 10);
1406        } else {
1407                state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7);
1408                retval = write_dst(state, &state->tx_tuna[2], FIXED_COMM);
1409        }
1410        if (retval < 0) {
1411                dst_pio_disable(state);
1412                dprintk(verbose, DST_DEBUG, 1, "write not successful");
1413                goto werr;
1414        }
1415        if ((dst_pio_disable(state)) < 0) {
1416                dprintk(verbose, DST_DEBUG, 1, "DST PIO disable failed !");
1417                goto error;
1418        }
1419        if ((read_dst(state, &reply, GET_ACK) < 0)) {
1420                dprintk(verbose, DST_DEBUG, 1, "read verify not successful.");
1421                goto error;
1422        }
1423        if (reply != ACK) {
1424                dprintk(verbose, DST_DEBUG, 1, "write not acknowledged 0x%02x ", reply);
1425                goto error;
1426        }
1427        state->diseq_flags |= ATTEMPT_TUNE;
1428        retval = dst_get_tuna(state);
1429werr:
1430        mutex_unlock(&state->dst_mutex);
1431        return retval;
1432
1433error:
1434        mutex_unlock(&state->dst_mutex);
1435        return -EIO;
1436}
1437
1438/*
1439 * line22k0    0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00
1440 * line22k1    0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00
1441 * line22k2    0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00
1442 * tone        0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00
1443 * data        0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00
1444 * power_off   0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
1445 * power_on    0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00
1446 * Diseqc 1    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec
1447 * Diseqc 2    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8
1448 * Diseqc 3    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4
1449 * Diseqc 4    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0
1450 */
1451
1452static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
1453{
1454        struct dst_state *state = fe->demodulator_priv;
1455        u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
1456
1457        if (state->dst_type != DST_TYPE_IS_SAT)
1458                return -EOPNOTSUPP;
1459        if (cmd->msg_len > 0 && cmd->msg_len < 5)
1460                memcpy(&paket[3], cmd->msg, cmd->msg_len);
1461        else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
1462                memcpy(&paket[2], cmd->msg, cmd->msg_len);
1463        else
1464                return -EINVAL;
1465        paket[7] = dst_check_sum(&paket[0], 7);
1466        return dst_command(state, paket, 8);
1467}
1468
1469static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
1470{
1471        int need_cmd, retval = 0;
1472        struct dst_state *state = fe->demodulator_priv;
1473
1474        state->voltage = voltage;
1475        if (state->dst_type != DST_TYPE_IS_SAT)
1476                return -EOPNOTSUPP;
1477
1478        need_cmd = 0;
1479
1480        switch (voltage) {
1481        case SEC_VOLTAGE_13:
1482        case SEC_VOLTAGE_18:
1483                if ((state->diseq_flags & HAS_POWER) == 0)
1484                        need_cmd = 1;
1485                state->diseq_flags |= HAS_POWER;
1486                state->tx_tuna[4] = 0x01;
1487                break;
1488        case SEC_VOLTAGE_OFF:
1489                need_cmd = 1;
1490                state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
1491                state->tx_tuna[4] = 0x00;
1492                break;
1493        default:
1494                return -EINVAL;
1495        }
1496
1497        if (need_cmd)
1498                retval = dst_tone_power_cmd(state);
1499
1500        return retval;
1501}
1502
1503static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
1504{
1505        struct dst_state *state = fe->demodulator_priv;
1506
1507        state->tone = tone;
1508        if (state->dst_type != DST_TYPE_IS_SAT)
1509                return -EOPNOTSUPP;
1510
1511        switch (tone) {
1512        case SEC_TONE_OFF:
1513                if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
1514                    state->tx_tuna[2] = 0x00;
1515                else
1516                    state->tx_tuna[2] = 0xff;
1517                break;
1518
1519        case SEC_TONE_ON:
1520                state->tx_tuna[2] = 0x02;
1521                break;
1522        default:
1523                return -EINVAL;
1524        }
1525        return dst_tone_power_cmd(state);
1526}
1527
1528static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
1529{
1530        struct dst_state *state = fe->demodulator_priv;
1531
1532        if (state->dst_type != DST_TYPE_IS_SAT)
1533                return -EOPNOTSUPP;
1534        state->minicmd = minicmd;
1535        switch (minicmd) {
1536        case SEC_MINI_A:
1537                state->tx_tuna[3] = 0x02;
1538                break;
1539        case SEC_MINI_B:
1540                state->tx_tuna[3] = 0xff;
1541                break;
1542        }
1543        return dst_tone_power_cmd(state);
1544}
1545
1546
1547static int dst_init(struct dvb_frontend *fe)
1548{
1549        struct dst_state *state = fe->demodulator_priv;
1550
1551        static u8 sat_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x00, 0x73, 0x21, 0x00, 0x00 };
1552        static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
1553        static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
1554        static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
1555        static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
1556        static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
1557        static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
1558
1559        state->inversion = INVERSION_OFF;
1560        state->voltage = SEC_VOLTAGE_13;
1561        state->tone = SEC_TONE_OFF;
1562        state->diseq_flags = 0;
1563        state->k22 = 0x02;
1564        state->bandwidth = 7000000;
1565        state->cur_jiff = jiffies;
1566        if (state->dst_type == DST_TYPE_IS_SAT)
1567                memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
1568        else if (state->dst_type == DST_TYPE_IS_TERR)
1569                memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
1570        else if (state->dst_type == DST_TYPE_IS_CABLE)
1571                memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
1572        else if (state->dst_type == DST_TYPE_IS_ATSC)
1573                memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner));
1574
1575        return 0;
1576}
1577
1578static int dst_read_status(struct dvb_frontend *fe, fe_status_t *status)
1579{
1580        struct dst_state *state = fe->demodulator_priv;
1581
1582        *status = 0;
1583        if (state->diseq_flags & HAS_LOCK) {
1584//              dst_get_signal(state);  // don't require(?) to ask MCU
1585                if (state->decode_lock)
1586                        *status |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI;
1587        }
1588
1589        return 0;
1590}
1591
1592static int dst_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
1593{
1594        struct dst_state *state = fe->demodulator_priv;
1595
1596        int retval = dst_get_signal(state);
1597        *strength = state->decode_strength;
1598
1599        return retval;
1600}
1601
1602static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
1603{
1604        struct dst_state *state = fe->demodulator_priv;
1605
1606        int retval = dst_get_signal(state);
1607        *snr = state->decode_snr;
1608
1609        return retval;
1610}
1611
1612static int dst_set_frontend(struct dvb_frontend *fe)
1613{
1614        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1615        int retval = -EINVAL;
1616        struct dst_state *state = fe->demodulator_priv;
1617
1618        if (p != NULL) {
1619                retval = dst_set_freq(state, p->frequency);
1620                if(retval != 0)
1621                        return retval;
1622                dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
1623
1624                if (state->dst_type == DST_TYPE_IS_SAT) {
1625                        if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
1626                                dst_set_inversion(state, p->inversion);
1627                        dst_set_fec(state, p->fec_inner);
1628                        dst_set_symbolrate(state, p->symbol_rate);
1629                        dst_set_polarization(state);
1630                        dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
1631
1632                } else if (state->dst_type == DST_TYPE_IS_TERR)
1633                        dst_set_bandwidth(state, p->bandwidth_hz);
1634                else if (state->dst_type == DST_TYPE_IS_CABLE) {
1635                        dst_set_fec(state, p->fec_inner);
1636                        dst_set_symbolrate(state, p->symbol_rate);
1637                        dst_set_modulation(state, p->modulation);
1638                }
1639                retval = dst_write_tuna(fe);
1640        }
1641
1642        return retval;
1643}
1644
1645static int dst_tune_frontend(struct dvb_frontend* fe,
1646                            bool re_tune,
1647                            unsigned int mode_flags,
1648                            unsigned int *delay,
1649                            fe_status_t *status)
1650{
1651        struct dst_state *state = fe->demodulator_priv;
1652        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1653
1654        if (re_tune) {
1655                dst_set_freq(state, p->frequency);
1656                dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
1657
1658                if (state->dst_type == DST_TYPE_IS_SAT) {
1659                        if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
1660                                dst_set_inversion(state, p->inversion);
1661                        dst_set_fec(state, p->fec_inner);
1662                        dst_set_symbolrate(state, p->symbol_rate);
1663                        dst_set_polarization(state);
1664                        dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
1665
1666                } else if (state->dst_type == DST_TYPE_IS_TERR)
1667                        dst_set_bandwidth(state, p->bandwidth_hz);
1668                else if (state->dst_type == DST_TYPE_IS_CABLE) {
1669                        dst_set_fec(state, p->fec_inner);
1670                        dst_set_symbolrate(state, p->symbol_rate);
1671                        dst_set_modulation(state, p->modulation);
1672                }
1673                dst_write_tuna(fe);
1674        }
1675
1676        if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
1677                dst_read_status(fe, status);
1678
1679        *delay = HZ/10;
1680        return 0;
1681}
1682
1683static int dst_get_tuning_algo(struct dvb_frontend *fe)
1684{
1685        return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW;
1686}
1687
1688static int dst_get_frontend(struct dvb_frontend *fe)
1689{
1690        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1691        struct dst_state *state = fe->demodulator_priv;
1692
1693        p->frequency = state->decode_freq;
1694        if (state->dst_type == DST_TYPE_IS_SAT) {
1695                if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
1696                        p->inversion = state->inversion;
1697                p->symbol_rate = state->symbol_rate;
1698                p->fec_inner = dst_get_fec(state);
1699        } else if (state->dst_type == DST_TYPE_IS_TERR) {
1700                p->bandwidth_hz = state->bandwidth;
1701        } else if (state->dst_type == DST_TYPE_IS_CABLE) {
1702                p->symbol_rate = state->symbol_rate;
1703                p->fec_inner = dst_get_fec(state);
1704                p->modulation = dst_get_modulation(state);
1705        }
1706
1707        return 0;
1708}
1709
1710static void dst_release(struct dvb_frontend *fe)
1711{
1712        struct dst_state *state = fe->demodulator_priv;
1713        if (state->dst_ca) {
1714                dvb_unregister_device(state->dst_ca);
1715#ifdef CONFIG_MEDIA_ATTACH
1716                symbol_put(dst_ca_attach);
1717#endif
1718        }
1719        kfree(state);
1720}
1721
1722static struct dvb_frontend_ops dst_dvbt_ops;
1723static struct dvb_frontend_ops dst_dvbs_ops;
1724static struct dvb_frontend_ops dst_dvbc_ops;
1725static struct dvb_frontend_ops dst_atsc_ops;
1726
1727struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
1728{
1729        /* check if the ASIC is there */
1730        if (dst_probe(state) < 0) {
1731                kfree(state);
1732                return NULL;
1733        }
1734        /* determine settings based on type */
1735        /* create dvb_frontend */
1736        switch (state->dst_type) {
1737        case DST_TYPE_IS_TERR:
1738                memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
1739                break;
1740        case DST_TYPE_IS_CABLE:
1741                memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
1742                break;
1743        case DST_TYPE_IS_SAT:
1744                memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
1745                break;
1746        case DST_TYPE_IS_ATSC:
1747                memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops));
1748                break;
1749        default:
1750                dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
1751                kfree(state);
1752                return NULL;
1753        }
1754        state->frontend.demodulator_priv = state;
1755
1756        return state;                           /*      Manu (DST is a card not a frontend)     */
1757}
1758
1759EXPORT_SYMBOL(dst_attach);
1760
1761static struct dvb_frontend_ops dst_dvbt_ops = {
1762        .delsys = { SYS_DVBT },
1763        .info = {
1764                .name = "DST DVB-T",
1765                .frequency_min = 137000000,
1766                .frequency_max = 858000000,
1767                .frequency_stepsize = 166667,
1768                .caps = FE_CAN_FEC_AUTO                 |
1769                        FE_CAN_QAM_AUTO                 |
1770                        FE_CAN_QAM_16                   |
1771                        FE_CAN_QAM_32                   |
1772                        FE_CAN_QAM_64                   |
1773                        FE_CAN_QAM_128                  |
1774                        FE_CAN_QAM_256                  |
1775                        FE_CAN_TRANSMISSION_MODE_AUTO   |
1776                        FE_CAN_GUARD_INTERVAL_AUTO
1777        },
1778
1779        .release = dst_release,
1780        .init = dst_init,
1781        .tune = dst_tune_frontend,
1782        .set_frontend = dst_set_frontend,
1783        .get_frontend = dst_get_frontend,
1784        .get_frontend_algo = dst_get_tuning_algo,
1785        .read_status = dst_read_status,
1786        .read_signal_strength = dst_read_signal_strength,
1787        .read_snr = dst_read_snr,
1788};
1789
1790static struct dvb_frontend_ops dst_dvbs_ops = {
1791        .delsys = { SYS_DVBS },
1792        .info = {
1793                .name = "DST DVB-S",
1794                .frequency_min = 950000,
1795                .frequency_max = 2150000,
1796                .frequency_stepsize = 1000,     /* kHz for QPSK frontends */
1797                .frequency_tolerance = 29500,
1798                .symbol_rate_min = 1000000,
1799                .symbol_rate_max = 45000000,
1800        /*     . symbol_rate_tolerance  =       ???,*/
1801                .caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK
1802        },
1803
1804        .release = dst_release,
1805        .init = dst_init,
1806        .tune = dst_tune_frontend,
1807        .set_frontend = dst_set_frontend,
1808        .get_frontend = dst_get_frontend,
1809        .get_frontend_algo = dst_get_tuning_algo,
1810        .read_status = dst_read_status,
1811        .read_signal_strength = dst_read_signal_strength,
1812        .read_snr = dst_read_snr,
1813        .diseqc_send_burst = dst_send_burst,
1814        .diseqc_send_master_cmd = dst_set_diseqc,
1815        .set_voltage = dst_set_voltage,
1816        .set_tone = dst_set_tone,
1817};
1818
1819static struct dvb_frontend_ops dst_dvbc_ops = {
1820        .delsys = { SYS_DVBC_ANNEX_A },
1821        .info = {
1822                .name = "DST DVB-C",
1823                .frequency_stepsize = 62500,
1824                .frequency_min = 51000000,
1825                .frequency_max = 858000000,
1826                .symbol_rate_min = 1000000,
1827                .symbol_rate_max = 45000000,
1828                .caps = FE_CAN_FEC_AUTO |
1829                        FE_CAN_QAM_AUTO |
1830                        FE_CAN_QAM_16   |
1831                        FE_CAN_QAM_32   |
1832                        FE_CAN_QAM_64   |
1833                        FE_CAN_QAM_128  |
1834                        FE_CAN_QAM_256
1835        },
1836
1837        .release = dst_release,
1838        .init = dst_init,
1839        .tune = dst_tune_frontend,
1840        .set_frontend = dst_set_frontend,
1841        .get_frontend = dst_get_frontend,
1842        .get_frontend_algo = dst_get_tuning_algo,
1843        .read_status = dst_read_status,
1844        .read_signal_strength = dst_read_signal_strength,
1845        .read_snr = dst_read_snr,
1846};
1847
1848static struct dvb_frontend_ops dst_atsc_ops = {
1849        .delsys = { SYS_ATSC },
1850        .info = {
1851                .name = "DST ATSC",
1852                .frequency_stepsize = 62500,
1853                .frequency_min = 510000000,
1854                .frequency_max = 858000000,
1855                .symbol_rate_min = 1000000,
1856                .symbol_rate_max = 45000000,
1857                .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
1858        },
1859
1860        .release = dst_release,
1861        .init = dst_init,
1862        .tune = dst_tune_frontend,
1863        .set_frontend = dst_set_frontend,
1864        .get_frontend = dst_get_frontend,
1865        .get_frontend_algo = dst_get_tuning_algo,
1866        .read_status = dst_read_status,
1867        .read_signal_strength = dst_read_signal_strength,
1868        .read_snr = dst_read_snr,
1869};
1870
1871MODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver");
1872MODULE_AUTHOR("Jamie Honan, Manu Abraham");
1873MODULE_LICENSE("GPL");
1874