linux/drivers/media/pci/ngene/ngene-cards.c
<<
>>
Prefs
   1/*
   2 * ngene-cards.c: nGene PCIe bridge driver - card specific info
   3 *
   4 * Copyright (C) 2005-2007 Micronas
   5 *
   6 * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
   7 *                         Modifications for new nGene firmware,
   8 *                         support for EEPROM-copying,
   9 *                         support for new dual DVB-S2 card prototype
  10 *
  11 *
  12 * This program is free software; you can redistribute it and/or
  13 * modify it under the terms of the GNU General Public License
  14 * version 2 only, as published by the Free Software Foundation.
  15 *
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 *
  22 *
  23 * You should have received a copy of the GNU General Public License
  24 * along with this program; if not, write to the Free Software
  25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  26 * 02110-1301, USA
  27 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
  28 */
  29
  30#include <linux/module.h>
  31#include <linux/init.h>
  32#include <linux/pci.h>
  33#include <linux/pci_ids.h>
  34
  35#include "ngene.h"
  36
  37/* demods/tuners */
  38#include "stv6110x.h"
  39#include "stv090x.h"
  40#include "lnbh24.h"
  41#include "lgdt330x.h"
  42#include "mt2131.h"
  43#include "tda18271c2dd.h"
  44#include "drxk.h"
  45#include "drxd.h"
  46#include "dvb-pll.h"
  47
  48
  49/****************************************************************************/
  50/* Demod/tuner attachment ***************************************************/
  51/****************************************************************************/
  52
  53static int tuner_attach_stv6110(struct ngene_channel *chan)
  54{
  55        struct i2c_adapter *i2c;
  56        struct stv090x_config *feconf = (struct stv090x_config *)
  57                chan->dev->card_info->fe_config[chan->number];
  58        struct stv6110x_config *tunerconf = (struct stv6110x_config *)
  59                chan->dev->card_info->tuner_config[chan->number];
  60        const struct stv6110x_devctl *ctl;
  61
  62        /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
  63        if (chan->number < 2)
  64                i2c = &chan->dev->channel[0].i2c_adapter;
  65        else
  66                i2c = &chan->dev->channel[1].i2c_adapter;
  67
  68        ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, i2c);
  69        if (ctl == NULL) {
  70                printk(KERN_ERR DEVICE_NAME ": No STV6110X found!\n");
  71                return -ENODEV;
  72        }
  73
  74        feconf->tuner_init          = ctl->tuner_init;
  75        feconf->tuner_sleep         = ctl->tuner_sleep;
  76        feconf->tuner_set_mode      = ctl->tuner_set_mode;
  77        feconf->tuner_set_frequency = ctl->tuner_set_frequency;
  78        feconf->tuner_get_frequency = ctl->tuner_get_frequency;
  79        feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth;
  80        feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth;
  81        feconf->tuner_set_bbgain    = ctl->tuner_set_bbgain;
  82        feconf->tuner_get_bbgain    = ctl->tuner_get_bbgain;
  83        feconf->tuner_set_refclk    = ctl->tuner_set_refclk;
  84        feconf->tuner_get_status    = ctl->tuner_get_status;
  85
  86        return 0;
  87}
  88
  89
  90static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
  91{
  92        struct ngene_channel *chan = fe->sec_priv;
  93        int status;
  94
  95        if (enable) {
  96                down(&chan->dev->pll_mutex);
  97                status = chan->gate_ctrl(fe, 1);
  98        } else {
  99                status = chan->gate_ctrl(fe, 0);
 100                up(&chan->dev->pll_mutex);
 101        }
 102        return status;
 103}
 104
 105static int tuner_attach_tda18271(struct ngene_channel *chan)
 106{
 107        struct i2c_adapter *i2c;
 108        struct dvb_frontend *fe;
 109
 110        i2c = &chan->dev->channel[0].i2c_adapter;
 111        if (chan->fe->ops.i2c_gate_ctrl)
 112                chan->fe->ops.i2c_gate_ctrl(chan->fe, 1);
 113        fe = dvb_attach(tda18271c2dd_attach, chan->fe, i2c, 0x60);
 114        if (chan->fe->ops.i2c_gate_ctrl)
 115                chan->fe->ops.i2c_gate_ctrl(chan->fe, 0);
 116        if (!fe) {
 117                printk(KERN_ERR "No TDA18271 found!\n");
 118                return -ENODEV;
 119        }
 120
 121        return 0;
 122}
 123
 124static int tuner_attach_probe(struct ngene_channel *chan)
 125{
 126        if (chan->demod_type == 0)
 127                return tuner_attach_stv6110(chan);
 128        if (chan->demod_type == 1)
 129                return tuner_attach_tda18271(chan);
 130        return -EINVAL;
 131}
 132
 133static int demod_attach_stv0900(struct ngene_channel *chan)
 134{
 135        struct i2c_adapter *i2c;
 136        struct stv090x_config *feconf = (struct stv090x_config *)
 137                chan->dev->card_info->fe_config[chan->number];
 138
 139        /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
 140        /* Note: Both adapters share the same i2c bus, but the demod     */
 141        /*       driver requires that each demod has its own i2c adapter */
 142        if (chan->number < 2)
 143                i2c = &chan->dev->channel[0].i2c_adapter;
 144        else
 145                i2c = &chan->dev->channel[1].i2c_adapter;
 146
 147        chan->fe = dvb_attach(stv090x_attach, feconf, i2c,
 148                        (chan->number & 1) == 0 ? STV090x_DEMODULATOR_0
 149                                                : STV090x_DEMODULATOR_1);
 150        if (chan->fe == NULL) {
 151                printk(KERN_ERR DEVICE_NAME ": No STV0900 found!\n");
 152                return -ENODEV;
 153        }
 154
 155        /* store channel info */
 156        if (feconf->tuner_i2c_lock)
 157                chan->fe->analog_demod_priv = chan;
 158
 159        if (!dvb_attach(lnbh24_attach, chan->fe, i2c, 0,
 160                        0, chan->dev->card_info->lnb[chan->number])) {
 161                printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n");
 162                dvb_frontend_detach(chan->fe);
 163                chan->fe = NULL;
 164                return -ENODEV;
 165        }
 166
 167        return 0;
 168}
 169
 170static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock)
 171{
 172        struct ngene_channel *chan = fe->analog_demod_priv;
 173
 174        if (lock)
 175                down(&chan->dev->pll_mutex);
 176        else
 177                up(&chan->dev->pll_mutex);
 178}
 179
 180static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
 181{
 182        struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
 183                                   .buf  = val,  .len   = 1 } };
 184        return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
 185}
 186
 187static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
 188                          u16 reg, u8 *val)
 189{
 190        u8 msg[2] = {reg>>8, reg&0xff};
 191        struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
 192                                   .buf  = msg, .len   = 2},
 193                                  {.addr = adr, .flags = I2C_M_RD,
 194                                   .buf  = val, .len   = 1} };
 195        return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
 196}
 197
 198static int port_has_stv0900(struct i2c_adapter *i2c, int port)
 199{
 200        u8 val;
 201        if (i2c_read_reg16(i2c, 0x68+port/2, 0xf100, &val) < 0)
 202                return 0;
 203        return 1;
 204}
 205
 206static int port_has_drxk(struct i2c_adapter *i2c, int port)
 207{
 208        u8 val;
 209
 210        if (i2c_read(i2c, 0x29+port, &val) < 0)
 211                return 0;
 212        return 1;
 213}
 214
 215static int demod_attach_drxk(struct ngene_channel *chan,
 216                             struct i2c_adapter *i2c)
 217{
 218        struct drxk_config config;
 219
 220        memset(&config, 0, sizeof(config));
 221        config.microcode_name = "drxk_a3.mc";
 222        config.qam_demod_parameter_count = 4;
 223        config.adr = 0x29 + (chan->number ^ 2);
 224
 225        chan->fe = dvb_attach(drxk_attach, &config, i2c);
 226        if (!chan->fe) {
 227                printk(KERN_ERR "No DRXK found!\n");
 228                return -ENODEV;
 229        }
 230        chan->fe->sec_priv = chan;
 231        chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl;
 232        chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
 233        return 0;
 234}
 235
 236static int cineS2_probe(struct ngene_channel *chan)
 237{
 238        struct i2c_adapter *i2c;
 239        struct stv090x_config *fe_conf;
 240        u8 buf[3];
 241        struct i2c_msg i2c_msg = { .flags = 0, .buf = buf };
 242        int rc;
 243
 244        /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
 245        if (chan->number < 2)
 246                i2c = &chan->dev->channel[0].i2c_adapter;
 247        else
 248                i2c = &chan->dev->channel[1].i2c_adapter;
 249
 250        if (port_has_stv0900(i2c, chan->number)) {
 251                chan->demod_type = 0;
 252                fe_conf = chan->dev->card_info->fe_config[chan->number];
 253                /* demod found, attach it */
 254                rc = demod_attach_stv0900(chan);
 255                if (rc < 0 || chan->number < 2)
 256                        return rc;
 257
 258                /* demod #2: reprogram outputs DPN1 & DPN2 */
 259                i2c_msg.addr = fe_conf->address;
 260                i2c_msg.len = 3;
 261                buf[0] = 0xf1;
 262                switch (chan->number) {
 263                case 2:
 264                        buf[1] = 0x5c;
 265                        buf[2] = 0xc2;
 266                        break;
 267                case 3:
 268                        buf[1] = 0x61;
 269                        buf[2] = 0xcc;
 270                        break;
 271                default:
 272                        return -ENODEV;
 273                }
 274                rc = i2c_transfer(i2c, &i2c_msg, 1);
 275                if (rc != 1) {
 276                        printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
 277                        return -EIO;
 278                }
 279        } else if (port_has_drxk(i2c, chan->number^2)) {
 280                chan->demod_type = 1;
 281                demod_attach_drxk(chan, i2c);
 282        } else {
 283                printk(KERN_ERR "No demod found on chan %d\n", chan->number);
 284                return -ENODEV;
 285        }
 286        return 0;
 287}
 288
 289
 290static struct lgdt330x_config aver_m780 = {
 291        .demod_address = 0xb2 >> 1,
 292        .demod_chip    = LGDT3303,
 293        .serial_mpeg   = 0x00, /* PARALLEL */
 294        .clock_polarity_flip = 1,
 295};
 296
 297static struct mt2131_config m780_tunerconfig = {
 298        0xc0 >> 1
 299};
 300
 301/* A single func to attach the demo and tuner, rather than
 302 * use two sep funcs like the current design mandates.
 303 */
 304static int demod_attach_lg330x(struct ngene_channel *chan)
 305{
 306        chan->fe = dvb_attach(lgdt330x_attach, &aver_m780, &chan->i2c_adapter);
 307        if (chan->fe == NULL) {
 308                printk(KERN_ERR DEVICE_NAME ": No LGDT330x found!\n");
 309                return -ENODEV;
 310        }
 311
 312        dvb_attach(mt2131_attach, chan->fe, &chan->i2c_adapter,
 313                   &m780_tunerconfig, 0);
 314
 315        return (chan->fe) ? 0 : -ENODEV;
 316}
 317
 318static int demod_attach_drxd(struct ngene_channel *chan)
 319{
 320        struct drxd_config *feconf;
 321
 322        feconf = chan->dev->card_info->fe_config[chan->number];
 323
 324        chan->fe = dvb_attach(drxd_attach, feconf, chan,
 325                        &chan->i2c_adapter, &chan->dev->pci_dev->dev);
 326        if (!chan->fe) {
 327                pr_err("No DRXD found!\n");
 328                return -ENODEV;
 329        }
 330        return 0;
 331}
 332
 333static int tuner_attach_dtt7520x(struct ngene_channel *chan)
 334{
 335        struct drxd_config *feconf;
 336
 337        feconf = chan->dev->card_info->fe_config[chan->number];
 338
 339        if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address,
 340                        &chan->i2c_adapter,
 341                        feconf->pll_type)) {
 342                pr_err("No pll(%d) found!\n", feconf->pll_type);
 343                return -ENODEV;
 344        }
 345        return 0;
 346}
 347
 348/****************************************************************************/
 349/* EEPROM TAGS **************************************************************/
 350/****************************************************************************/
 351
 352#define MICNG_EE_START      0x0100
 353#define MICNG_EE_END        0x0FF0
 354
 355#define MICNG_EETAG_END0    0x0000
 356#define MICNG_EETAG_END1    0xFFFF
 357
 358/* 0x0001 - 0x000F reserved for housekeeping */
 359/* 0xFFFF - 0xFFFE reserved for housekeeping */
 360
 361/* Micronas assigned tags
 362   EEProm tags for hardware support */
 363
 364#define MICNG_EETAG_DRXD1_OSCDEVIATION  0x1000  /* 2 Bytes data */
 365#define MICNG_EETAG_DRXD2_OSCDEVIATION  0x1001  /* 2 Bytes data */
 366
 367#define MICNG_EETAG_MT2060_1_1STIF      0x1100  /* 2 Bytes data */
 368#define MICNG_EETAG_MT2060_2_1STIF      0x1101  /* 2 Bytes data */
 369
 370/* Tag range for OEMs */
 371
 372#define MICNG_EETAG_OEM_FIRST  0xC000
 373#define MICNG_EETAG_OEM_LAST   0xFFEF
 374
 375static int i2c_write_eeprom(struct i2c_adapter *adapter,
 376                            u8 adr, u16 reg, u8 data)
 377{
 378        u8 m[3] = {(reg >> 8), (reg & 0xff), data};
 379        struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m,
 380                              .len = sizeof(m)};
 381
 382        if (i2c_transfer(adapter, &msg, 1) != 1) {
 383                pr_err(DEVICE_NAME ": Error writing EEPROM!\n");
 384                return -EIO;
 385        }
 386        return 0;
 387}
 388
 389static int i2c_read_eeprom(struct i2c_adapter *adapter,
 390                           u8 adr, u16 reg, u8 *data, int len)
 391{
 392        u8 msg[2] = {(reg >> 8), (reg & 0xff)};
 393        struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
 394                                   .buf = msg, .len = 2 },
 395                                  {.addr = adr, .flags = I2C_M_RD,
 396                                   .buf = data, .len = len} };
 397
 398        if (i2c_transfer(adapter, msgs, 2) != 2) {
 399                pr_err(DEVICE_NAME ": Error reading EEPROM\n");
 400                return -EIO;
 401        }
 402        return 0;
 403}
 404
 405static int ReadEEProm(struct i2c_adapter *adapter,
 406                      u16 Tag, u32 MaxLen, u8 *data, u32 *pLength)
 407{
 408        int status = 0;
 409        u16 Addr = MICNG_EE_START, Length, tag = 0;
 410        u8  EETag[3];
 411
 412        while (Addr + sizeof(u16) + 1 < MICNG_EE_END) {
 413                if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag)))
 414                        return -1;
 415                tag = (EETag[0] << 8) | EETag[1];
 416                if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1)
 417                        return -1;
 418                if (tag == Tag)
 419                        break;
 420                Addr += sizeof(u16) + 1 + EETag[2];
 421        }
 422        if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
 423                pr_err(DEVICE_NAME
 424                       ": Reached EOEE @ Tag = %04x Length = %3d\n",
 425                       tag, EETag[2]);
 426                return -1;
 427        }
 428        Length = EETag[2];
 429        if (Length > MaxLen)
 430                Length = (u16) MaxLen;
 431        if (Length > 0) {
 432                Addr += sizeof(u16) + 1;
 433                status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length);
 434                if (!status) {
 435                        *pLength = EETag[2];
 436#if 0
 437                        if (Length < EETag[2])
 438                                status = STATUS_BUFFER_OVERFLOW;
 439#endif
 440                }
 441        }
 442        return status;
 443}
 444
 445static int WriteEEProm(struct i2c_adapter *adapter,
 446                       u16 Tag, u32 Length, u8 *data)
 447{
 448        int status = 0;
 449        u16 Addr = MICNG_EE_START;
 450        u8 EETag[3];
 451        u16 tag = 0;
 452        int retry, i;
 453
 454        while (Addr + sizeof(u16) + 1 < MICNG_EE_END) {
 455                if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag)))
 456                        return -1;
 457                tag = (EETag[0] << 8) | EETag[1];
 458                if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1)
 459                        return -1;
 460                if (tag == Tag)
 461                        break;
 462                Addr += sizeof(u16) + 1 + EETag[2];
 463        }
 464        if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
 465                pr_err(DEVICE_NAME
 466                       ": Reached EOEE @ Tag = %04x Length = %3d\n",
 467                       tag, EETag[2]);
 468                return -1;
 469        }
 470
 471        if (Length > EETag[2])
 472                return -EINVAL;
 473        /* Note: We write the data one byte at a time to avoid
 474           issues with page sizes. (which are different for
 475           each manufacture and eeprom size)
 476         */
 477        Addr += sizeof(u16) + 1;
 478        for (i = 0; i < Length; i++, Addr++) {
 479                status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]);
 480
 481                if (status)
 482                        break;
 483
 484                /* Poll for finishing write cycle */
 485                retry = 10;
 486                while (retry) {
 487                        u8 Tmp;
 488
 489                        msleep(50);
 490                        status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1);
 491                        if (status)
 492                                break;
 493                        if (Tmp != data[i])
 494                                pr_err(DEVICE_NAME
 495                                       "eeprom write error\n");
 496                        retry -= 1;
 497                }
 498                if (status) {
 499                        pr_err(DEVICE_NAME
 500                               ": Timeout polling eeprom\n");
 501                        break;
 502                }
 503        }
 504        return status;
 505}
 506
 507static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data)
 508{
 509        int stat;
 510        u8 buf[2];
 511        u32 len = 0;
 512
 513        stat = ReadEEProm(adapter, tag, 2, buf, &len);
 514        if (stat)
 515                return stat;
 516        if (len != 2)
 517                return -EINVAL;
 518
 519        *data = (buf[0] << 8) | buf[1];
 520        return 0;
 521}
 522
 523static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data)
 524{
 525        int stat;
 526        u8 buf[2];
 527
 528        buf[0] = data >> 8;
 529        buf[1] = data & 0xff;
 530        stat = WriteEEProm(adapter, tag, 2, buf);
 531        if (stat)
 532                return stat;
 533        return 0;
 534}
 535
 536static s16 osc_deviation(void *priv, s16 deviation, int flag)
 537{
 538        struct ngene_channel *chan = priv;
 539        struct i2c_adapter *adap = &chan->i2c_adapter;
 540        u16 data = 0;
 541
 542        if (flag) {
 543                data = (u16) deviation;
 544                pr_info(DEVICE_NAME ": write deviation %d\n",
 545                       deviation);
 546                eeprom_write_ushort(adap, 0x1000 + chan->number, data);
 547        } else {
 548                if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data))
 549                        data = 0;
 550                pr_info(DEVICE_NAME ": read deviation %d\n",
 551                       (s16) data);
 552        }
 553
 554        return (s16) data;
 555}
 556
 557/****************************************************************************/
 558/* Switch control (I2C gates, etc.) *****************************************/
 559/****************************************************************************/
 560
 561
 562static struct stv090x_config fe_cineS2 = {
 563        .device         = STV0900,
 564        .demod_mode     = STV090x_DUAL,
 565        .clk_mode       = STV090x_CLK_EXT,
 566
 567        .xtal           = 27000000,
 568        .address        = 0x68,
 569
 570        .ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
 571        .ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
 572
 573        .repeater_level = STV090x_RPTLEVEL_16,
 574
 575        .adc1_range     = STV090x_ADC_1Vpp,
 576        .adc2_range     = STV090x_ADC_1Vpp,
 577
 578        .diseqc_envelope_mode = true,
 579
 580        .tuner_i2c_lock = cineS2_tuner_i2c_lock,
 581};
 582
 583static struct stv090x_config fe_cineS2_2 = {
 584        .device         = STV0900,
 585        .demod_mode     = STV090x_DUAL,
 586        .clk_mode       = STV090x_CLK_EXT,
 587
 588        .xtal           = 27000000,
 589        .address        = 0x69,
 590
 591        .ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
 592        .ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
 593
 594        .repeater_level = STV090x_RPTLEVEL_16,
 595
 596        .adc1_range     = STV090x_ADC_1Vpp,
 597        .adc2_range     = STV090x_ADC_1Vpp,
 598
 599        .diseqc_envelope_mode = true,
 600
 601        .tuner_i2c_lock = cineS2_tuner_i2c_lock,
 602};
 603
 604static struct stv6110x_config tuner_cineS2_0 = {
 605        .addr   = 0x60,
 606        .refclk = 27000000,
 607        .clk_div = 1,
 608};
 609
 610static struct stv6110x_config tuner_cineS2_1 = {
 611        .addr   = 0x63,
 612        .refclk = 27000000,
 613        .clk_div = 1,
 614};
 615
 616static struct ngene_info ngene_info_cineS2 = {
 617        .type           = NGENE_SIDEWINDER,
 618        .name           = "Linux4Media cineS2 DVB-S2 Twin Tuner",
 619        .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
 620        .demod_attach   = {demod_attach_stv0900, demod_attach_stv0900},
 621        .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110},
 622        .fe_config      = {&fe_cineS2, &fe_cineS2},
 623        .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1},
 624        .lnb            = {0x0b, 0x08},
 625        .tsf            = {3, 3},
 626        .fw_version     = 18,
 627        .msi_supported  = true,
 628};
 629
 630static struct ngene_info ngene_info_satixS2 = {
 631        .type           = NGENE_SIDEWINDER,
 632        .name           = "Mystique SaTiX-S2 Dual",
 633        .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
 634        .demod_attach   = {demod_attach_stv0900, demod_attach_stv0900},
 635        .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110},
 636        .fe_config      = {&fe_cineS2, &fe_cineS2},
 637        .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1},
 638        .lnb            = {0x0b, 0x08},
 639        .tsf            = {3, 3},
 640        .fw_version     = 18,
 641        .msi_supported  = true,
 642};
 643
 644static struct ngene_info ngene_info_satixS2v2 = {
 645        .type           = NGENE_SIDEWINDER,
 646        .name           = "Mystique SaTiX-S2 Dual (v2)",
 647        .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
 648                           NGENE_IO_TSOUT},
 649        .demod_attach   = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
 650        .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe},
 651        .fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
 652        .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
 653        .lnb            = {0x0a, 0x08, 0x0b, 0x09},
 654        .tsf            = {3, 3},
 655        .fw_version     = 18,
 656        .msi_supported  = true,
 657};
 658
 659static struct ngene_info ngene_info_cineS2v5 = {
 660        .type           = NGENE_SIDEWINDER,
 661        .name           = "Linux4Media cineS2 DVB-S2 Twin Tuner (v5)",
 662        .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
 663                           NGENE_IO_TSOUT},
 664        .demod_attach   = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
 665        .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe},
 666        .fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
 667        .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
 668        .lnb            = {0x0a, 0x08, 0x0b, 0x09},
 669        .tsf            = {3, 3},
 670        .fw_version     = 18,
 671        .msi_supported  = true,
 672};
 673
 674
 675static struct ngene_info ngene_info_duoFlex = {
 676        .type           = NGENE_SIDEWINDER,
 677        .name           = "Digital Devices DuoFlex PCIe or miniPCIe",
 678        .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
 679                           NGENE_IO_TSOUT},
 680        .demod_attach   = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe},
 681        .tuner_attach   = {tuner_attach_probe, tuner_attach_probe, tuner_attach_probe, tuner_attach_probe},
 682        .fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
 683        .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
 684        .lnb            = {0x0a, 0x08, 0x0b, 0x09},
 685        .tsf            = {3, 3},
 686        .fw_version     = 18,
 687        .msi_supported  = true,
 688};
 689
 690static struct ngene_info ngene_info_m780 = {
 691        .type           = NGENE_APP,
 692        .name           = "Aver M780 ATSC/QAM-B",
 693
 694        /* Channel 0 is analog, which is currently unsupported */
 695        .io_type        = { NGENE_IO_NONE, NGENE_IO_TSIN },
 696        .demod_attach   = { NULL, demod_attach_lg330x },
 697
 698        /* Ensure these are NULL else the frame will call them (as funcs) */
 699        .tuner_attach   = { NULL, NULL, NULL, NULL },
 700        .fe_config      = { NULL, &aver_m780 },
 701        .avf            = { 0 },
 702
 703        /* A custom electrical interface config for the demod to bridge */
 704        .tsf            = { 4, 4 },
 705        .fw_version     = 15,
 706};
 707
 708static struct drxd_config fe_terratec_dvbt_0 = {
 709        .index          = 0,
 710        .demod_address  = 0x70,
 711        .demod_revision = 0xa2,
 712        .demoda_address = 0x00,
 713        .pll_address    = 0x60,
 714        .pll_type       = DVB_PLL_THOMSON_DTT7520X,
 715        .clock          = 20000,
 716        .osc_deviation  = osc_deviation,
 717};
 718
 719static struct drxd_config fe_terratec_dvbt_1 = {
 720        .index          = 1,
 721        .demod_address  = 0x71,
 722        .demod_revision = 0xa2,
 723        .demoda_address = 0x00,
 724        .pll_address    = 0x60,
 725        .pll_type       = DVB_PLL_THOMSON_DTT7520X,
 726        .clock          = 20000,
 727        .osc_deviation  = osc_deviation,
 728};
 729
 730static struct ngene_info ngene_info_terratec = {
 731        .type           = NGENE_TERRATEC,
 732        .name           = "Terratec Integra/Cinergy2400i Dual DVB-T",
 733        .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
 734        .demod_attach   = {demod_attach_drxd, demod_attach_drxd},
 735        .tuner_attach   = {tuner_attach_dtt7520x, tuner_attach_dtt7520x},
 736        .fe_config      = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1},
 737        .i2c_access     = 1,
 738};
 739
 740/****************************************************************************/
 741
 742
 743
 744/****************************************************************************/
 745/* PCI Subsystem ID *********************************************************/
 746/****************************************************************************/
 747
 748#define NGENE_ID(_subvend, _subdev, _driverdata) { \
 749        .vendor = NGENE_VID, .device = NGENE_PID, \
 750        .subvendor = _subvend, .subdevice = _subdev, \
 751        .driver_data = (unsigned long) &_driverdata }
 752
 753/****************************************************************************/
 754
 755static const struct pci_device_id ngene_id_tbl[] = {
 756        NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2),
 757        NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2),
 758        NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
 759        NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2),
 760        NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5),
 761        NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex),
 762        NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex),
 763        NGENE_ID(0x1461, 0x062e, ngene_info_m780),
 764        NGENE_ID(0x153b, 0x1167, ngene_info_terratec),
 765        {0}
 766};
 767MODULE_DEVICE_TABLE(pci, ngene_id_tbl);
 768
 769/****************************************************************************/
 770/* Init/Exit ****************************************************************/
 771/****************************************************************************/
 772
 773static pci_ers_result_t ngene_error_detected(struct pci_dev *dev,
 774                                             enum pci_channel_state state)
 775{
 776        printk(KERN_ERR DEVICE_NAME ": PCI error\n");
 777        if (state == pci_channel_io_perm_failure)
 778                return PCI_ERS_RESULT_DISCONNECT;
 779        if (state == pci_channel_io_frozen)
 780                return PCI_ERS_RESULT_NEED_RESET;
 781        return PCI_ERS_RESULT_CAN_RECOVER;
 782}
 783
 784static pci_ers_result_t ngene_link_reset(struct pci_dev *dev)
 785{
 786        printk(KERN_INFO DEVICE_NAME ": link reset\n");
 787        return 0;
 788}
 789
 790static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev)
 791{
 792        printk(KERN_INFO DEVICE_NAME ": slot reset\n");
 793        return 0;
 794}
 795
 796static void ngene_resume(struct pci_dev *dev)
 797{
 798        printk(KERN_INFO DEVICE_NAME ": resume\n");
 799}
 800
 801static const struct pci_error_handlers ngene_errors = {
 802        .error_detected = ngene_error_detected,
 803        .link_reset = ngene_link_reset,
 804        .slot_reset = ngene_slot_reset,
 805        .resume = ngene_resume,
 806};
 807
 808static struct pci_driver ngene_pci_driver = {
 809        .name        = "ngene",
 810        .id_table    = ngene_id_tbl,
 811        .probe       = ngene_probe,
 812        .remove      = ngene_remove,
 813        .err_handler = &ngene_errors,
 814        .shutdown    = ngene_shutdown,
 815};
 816
 817static __init int module_init_ngene(void)
 818{
 819        printk(KERN_INFO
 820               "nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n");
 821        return pci_register_driver(&ngene_pci_driver);
 822}
 823
 824static __exit void module_exit_ngene(void)
 825{
 826        pci_unregister_driver(&ngene_pci_driver);
 827}
 828
 829module_init(module_init_ngene);
 830module_exit(module_exit_ngene);
 831
 832MODULE_DESCRIPTION("nGene");
 833MODULE_AUTHOR("Micronas, Ralph Metzler, Manfred Voelkel");
 834MODULE_LICENSE("GPL");
 835