linux/drivers/media/dvb/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, fe_bandwidth_t 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 BANDWIDTH_6_MHZ:
 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 BANDWIDTH_7_MHZ:
 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 BANDWIDTH_8_MHZ:
 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        memset(&state->fw_version, '\0', 8);
 934        memcpy(&state->fw_version, &state->rxbuffer, 8);
 935        dprintk(verbose, DST_ERROR, 1, "Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x",
 936                state->fw_version[0] >> 4, state->fw_version[0] & 0x0f,
 937                state->fw_version[1],
 938                state->fw_version[5], state->fw_version[6],
 939                state->fw_version[4], state->fw_version[3], state->fw_version[2]);
 940
 941        return 0;
 942}
 943
 944static int dst_card_type(struct dst_state *state)
 945{
 946        int j;
 947        struct tuner_types *p_tuner_list = NULL;
 948
 949        u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 950        get_type[7] = dst_check_sum(get_type, 7);
 951        if (dst_command(state, get_type, 8) < 0) {
 952                dprintk(verbose, DST_INFO, 1, "Unsupported Command");
 953                return -1;
 954        }
 955        memset(&state->card_info, '\0', 8);
 956        memcpy(&state->card_info, &state->rxbuffer, 7);
 957        dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
 958
 959        for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
 960                if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) {
 961                        state->tuner_type = p_tuner_list->tuner_type;
 962                        dprintk(verbose, DST_ERROR, 1, "DST has [%s] tuner, tuner type=[%d]",
 963                                p_tuner_list->tuner_name, p_tuner_list->tuner_type);
 964                }
 965        }
 966
 967        return 0;
 968}
 969
 970static int dst_get_vendor(struct dst_state *state)
 971{
 972        u8 get_vendor[] = { 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 973        get_vendor[7] = dst_check_sum(get_vendor, 7);
 974        if (dst_command(state, get_vendor, 8) < 0) {
 975                dprintk(verbose, DST_INFO, 1, "Unsupported Command");
 976                return -1;
 977        }
 978        memset(&state->vendor, '\0', 8);
 979        memcpy(&state->vendor, &state->rxbuffer, 7);
 980        dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
 981
 982        return 0;
 983}
 984
 985static void debug_dst_buffer(struct dst_state *state)
 986{
 987        int i;
 988
 989        if (verbose > 2) {
 990                printk("%s: [", __func__);
 991                for (i = 0; i < 8; i++)
 992                        printk(" %02x", state->rxbuffer[i]);
 993                printk("]\n");
 994        }
 995}
 996
 997static int dst_check_stv0299(struct dst_state *state)
 998{
 999        u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1000
1001        check_stv0299[7] = dst_check_sum(check_stv0299, 7);
1002        if (dst_command(state, check_stv0299, 8) < 0) {
1003                dprintk(verbose, DST_ERROR, 1, "Cmd=[0x04] failed");
1004                return -1;
1005        }
1006        debug_dst_buffer(state);
1007
1008        if (memcmp(&check_stv0299, &state->rxbuffer, 8)) {
1009                dprintk(verbose, DST_ERROR, 1, "Found a STV0299 NIM");
1010                state->tuner_type = TUNER_TYPE_STV0299;
1011                return 0;
1012        }
1013
1014        return -1;
1015}
1016
1017static int dst_check_mb86a15(struct dst_state *state)
1018{
1019        u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1020
1021        check_mb86a15[7] = dst_check_sum(check_mb86a15, 7);
1022        if (dst_command(state, check_mb86a15, 8) < 0) {
1023                dprintk(verbose, DST_ERROR, 1, "Cmd=[0x10], failed");
1024                return -1;
1025        }
1026        debug_dst_buffer(state);
1027
1028        if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) {
1029                dprintk(verbose, DST_ERROR, 1, "Found a MB86A15 NIM");
1030                state->tuner_type = TUNER_TYPE_MB86A15;
1031                return 0;
1032        }
1033
1034        return -1;
1035}
1036
1037static int dst_get_tuner_info(struct dst_state *state)
1038{
1039        u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1040        u8 get_tuner_2[] = { 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1041
1042        get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
1043        get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
1044        dprintk(verbose, DST_ERROR, 1, "DST TYpe = MULTI FE");
1045        if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
1046                if (dst_command(state, get_tuner_1, 8) < 0) {
1047                        dprintk(verbose, DST_INFO, 1, "Cmd=[0x13], Unsupported");
1048                        goto force;
1049                }
1050        } else {
1051                if (dst_command(state, get_tuner_2, 8) < 0) {
1052                        dprintk(verbose, DST_INFO, 1, "Cmd=[0xb], Unsupported");
1053                        goto force;
1054                }
1055        }
1056        memset(&state->board_info, '\0', 8);
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_CABLE) &&
1356                !(state->dst_type == DST_TYPE_IS_ATSC)) {
1357
1358                if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
1359                        dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
1360                        return -EIO;
1361                }
1362        } else {
1363                if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) {
1364                        dprintk(verbose, DST_INFO, 1, "checksum failure? ");
1365                        return -EIO;
1366                }
1367        }
1368        if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0)
1369                return 0;
1370        if (state->dst_type == DST_TYPE_IS_SAT) {
1371                state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3];
1372        } else {
1373                state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 16) + (state->rx_tuna[3] << 8) + state->rx_tuna[4];
1374        }
1375        state->decode_freq = state->decode_freq * 1000;
1376        state->decode_lock = 1;
1377        state->diseq_flags |= HAS_LOCK;
1378
1379        return 1;
1380}
1381
1382static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t 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, fe_sec_voltage_t 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, fe_sec_tone_mode_t 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, fe_sec_mini_cmd_t 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 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 = BANDWIDTH_7_MHZ;
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, fe_status_t *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, struct dvb_frontend_parameters *p)
1616{
1617        int retval = -EINVAL;
1618        struct dst_state *state = fe->demodulator_priv;
1619
1620        if (p != NULL) {
1621                retval = dst_set_freq(state, p->frequency);
1622                if(retval != 0)
1623                        return retval;
1624                dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
1625
1626                if (state->dst_type == DST_TYPE_IS_SAT) {
1627                        if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
1628                                dst_set_inversion(state, p->inversion);
1629                        dst_set_fec(state, p->u.qpsk.fec_inner);
1630                        dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
1631                        dst_set_polarization(state);
1632                        dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
1633
1634                } else if (state->dst_type == DST_TYPE_IS_TERR)
1635                        dst_set_bandwidth(state, p->u.ofdm.bandwidth);
1636                else if (state->dst_type == DST_TYPE_IS_CABLE) {
1637                        dst_set_fec(state, p->u.qam.fec_inner);
1638                        dst_set_symbolrate(state, p->u.qam.symbol_rate);
1639                        dst_set_modulation(state, p->u.qam.modulation);
1640                }
1641                retval = dst_write_tuna(fe);
1642        }
1643
1644        return retval;
1645}
1646
1647static int dst_tune_frontend(struct dvb_frontend* fe,
1648                            struct dvb_frontend_parameters* p,
1649                            unsigned int mode_flags,
1650                            unsigned int *delay,
1651                            fe_status_t *status)
1652{
1653        struct dst_state *state = fe->demodulator_priv;
1654
1655        if (p != NULL) {
1656                dst_set_freq(state, p->frequency);
1657                dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
1658
1659                if (state->dst_type == DST_TYPE_IS_SAT) {
1660                        if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
1661                                dst_set_inversion(state, p->inversion);
1662                        dst_set_fec(state, p->u.qpsk.fec_inner);
1663                        dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
1664                        dst_set_polarization(state);
1665                        dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
1666
1667                } else if (state->dst_type == DST_TYPE_IS_TERR)
1668                        dst_set_bandwidth(state, p->u.ofdm.bandwidth);
1669                else if (state->dst_type == DST_TYPE_IS_CABLE) {
1670                        dst_set_fec(state, p->u.qam.fec_inner);
1671                        dst_set_symbolrate(state, p->u.qam.symbol_rate);
1672                        dst_set_modulation(state, p->u.qam.modulation);
1673                }
1674                dst_write_tuna(fe);
1675        }
1676
1677        if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
1678                dst_read_status(fe, status);
1679
1680        *delay = HZ/10;
1681        return 0;
1682}
1683
1684static int dst_get_tuning_algo(struct dvb_frontend *fe)
1685{
1686        return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW;
1687}
1688
1689static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
1690{
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->u.qpsk.symbol_rate = state->symbol_rate;
1698                p->u.qpsk.fec_inner = dst_get_fec(state);
1699        } else if (state->dst_type == DST_TYPE_IS_TERR) {
1700                p->u.ofdm.bandwidth = state->bandwidth;
1701        } else if (state->dst_type == DST_TYPE_IS_CABLE) {
1702                p->u.qam.symbol_rate = state->symbol_rate;
1703                p->u.qam.fec_inner = dst_get_fec(state);
1704                p->u.qam.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
1763        .info = {
1764                .name = "DST DVB-T",
1765                .type = FE_OFDM,
1766                .frequency_min = 137000000,
1767                .frequency_max = 858000000,
1768                .frequency_stepsize = 166667,
1769                .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO
1770        },
1771
1772        .release = dst_release,
1773        .init = dst_init,
1774        .tune = dst_tune_frontend,
1775        .set_frontend = dst_set_frontend,
1776        .get_frontend = dst_get_frontend,
1777        .get_frontend_algo = dst_get_tuning_algo,
1778        .read_status = dst_read_status,
1779        .read_signal_strength = dst_read_signal_strength,
1780        .read_snr = dst_read_snr,
1781};
1782
1783static struct dvb_frontend_ops dst_dvbs_ops = {
1784
1785        .info = {
1786                .name = "DST DVB-S",
1787                .type = FE_QPSK,
1788                .frequency_min = 950000,
1789                .frequency_max = 2150000,
1790                .frequency_stepsize = 1000,     /* kHz for QPSK frontends */
1791                .frequency_tolerance = 29500,
1792                .symbol_rate_min = 1000000,
1793                .symbol_rate_max = 45000000,
1794        /*     . symbol_rate_tolerance  =       ???,*/
1795                .caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK
1796        },
1797
1798        .release = dst_release,
1799        .init = dst_init,
1800        .tune = dst_tune_frontend,
1801        .set_frontend = dst_set_frontend,
1802        .get_frontend = dst_get_frontend,
1803        .get_frontend_algo = dst_get_tuning_algo,
1804        .read_status = dst_read_status,
1805        .read_signal_strength = dst_read_signal_strength,
1806        .read_snr = dst_read_snr,
1807        .diseqc_send_burst = dst_send_burst,
1808        .diseqc_send_master_cmd = dst_set_diseqc,
1809        .set_voltage = dst_set_voltage,
1810        .set_tone = dst_set_tone,
1811};
1812
1813static struct dvb_frontend_ops dst_dvbc_ops = {
1814
1815        .info = {
1816                .name = "DST DVB-C",
1817                .type = FE_QAM,
1818                .frequency_stepsize = 62500,
1819                .frequency_min = 51000000,
1820                .frequency_max = 858000000,
1821                .symbol_rate_min = 1000000,
1822                .symbol_rate_max = 45000000,
1823        /*     . symbol_rate_tolerance  =       ???,*/
1824                .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO
1825        },
1826
1827        .release = dst_release,
1828        .init = dst_init,
1829        .tune = dst_tune_frontend,
1830        .set_frontend = dst_set_frontend,
1831        .get_frontend = dst_get_frontend,
1832        .get_frontend_algo = dst_get_tuning_algo,
1833        .read_status = dst_read_status,
1834        .read_signal_strength = dst_read_signal_strength,
1835        .read_snr = dst_read_snr,
1836};
1837
1838static struct dvb_frontend_ops dst_atsc_ops = {
1839        .info = {
1840                .name = "DST ATSC",
1841                .type = FE_ATSC,
1842                .frequency_stepsize = 62500,
1843                .frequency_min = 510000000,
1844                .frequency_max = 858000000,
1845                .symbol_rate_min = 1000000,
1846                .symbol_rate_max = 45000000,
1847                .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
1848        },
1849
1850        .release = dst_release,
1851        .init = dst_init,
1852        .tune = dst_tune_frontend,
1853        .set_frontend = dst_set_frontend,
1854        .get_frontend = dst_get_frontend,
1855        .get_frontend_algo = dst_get_tuning_algo,
1856        .read_status = dst_read_status,
1857        .read_signal_strength = dst_read_signal_strength,
1858        .read_snr = dst_read_snr,
1859};
1860
1861MODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver");
1862MODULE_AUTHOR("Jamie Honan, Manu Abraham");
1863MODULE_LICENSE("GPL");
1864