linux/drivers/media/pci/ttpci/budget.c
<<
>>
Prefs
   1/*
   2 * budget.c: driver for the SAA7146 based Budget DVB cards
   3 *
   4 * Compiled from various sources by Michael Hunold <michael@mihu.de>
   5 *
   6 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
   7 *
   8 * Copyright (C) 1999-2002 Ralph  Metzler
   9 *                       & Marcus Metzler for convergence integrated media GmbH
  10 *
  11 * 26feb2004 Support for FS Activy Card (Grundig tuner) by
  12 *           Michael Dreher <michael@5dot1.de>,
  13 *           Oliver Endriss <o.endriss@gmx.de> and
  14 *           Andreas 'randy' Weinberger
  15 *
  16 * This program is free software; you can redistribute it and/or
  17 * modify it under the terms of the GNU General Public License
  18 * as published by the Free Software Foundation; either version 2
  19 * of the License, or (at your option) any later version.
  20 *
  21 *
  22 * This program is distributed in the hope that it will be useful,
  23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25 * GNU General Public License for more details.
  26 *
  27 * To obtain the license, point your browser to
  28 * http://www.gnu.org/copyleft/gpl.html
  29 *
  30 *
  31 * the project's page is at https://linuxtv.org
  32 */
  33
  34#include "budget.h"
  35#include "stv0299.h"
  36#include "ves1x93.h"
  37#include "ves1820.h"
  38#include "l64781.h"
  39#include "tda8083.h"
  40#include "s5h1420.h"
  41#include "tda10086.h"
  42#include "tda826x.h"
  43#include "lnbp21.h"
  44#include "bsru6.h"
  45#include "bsbe1.h"
  46#include "tdhd1.h"
  47#include "stv6110x.h"
  48#include "stv090x.h"
  49#include "isl6423.h"
  50#include "lnbh24.h"
  51
  52
  53static int diseqc_method;
  54module_param(diseqc_method, int, 0444);
  55MODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)");
  56
  57DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  58
  59static void Set22K (struct budget *budget, int state)
  60{
  61        struct saa7146_dev *dev=budget->dev;
  62        dprintk(2, "budget: %p\n", budget);
  63        saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO));
  64}
  65
  66/* Diseqc functions only for TT Budget card */
  67/* taken from the Skyvision DVB driver by
  68   Ralph Metzler <rjkm@metzlerbros.de> */
  69
  70static void DiseqcSendBit (struct budget *budget, int data)
  71{
  72        struct saa7146_dev *dev=budget->dev;
  73        dprintk(2, "budget: %p\n", budget);
  74
  75        saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
  76        udelay(data ? 500 : 1000);
  77        saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
  78        udelay(data ? 1000 : 500);
  79}
  80
  81static void DiseqcSendByte (struct budget *budget, int data)
  82{
  83        int i, par=1, d;
  84
  85        dprintk(2, "budget: %p\n", budget);
  86
  87        for (i=7; i>=0; i--) {
  88                d = (data>>i)&1;
  89                par ^= d;
  90                DiseqcSendBit(budget, d);
  91        }
  92
  93        DiseqcSendBit(budget, par);
  94}
  95
  96static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst)
  97{
  98        struct saa7146_dev *dev=budget->dev;
  99        int i;
 100
 101        dprintk(2, "budget: %p\n", budget);
 102
 103        saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
 104        mdelay(16);
 105
 106        for (i=0; i<len; i++)
 107                DiseqcSendByte(budget, msg[i]);
 108
 109        mdelay(16);
 110
 111        if (burst!=-1) {
 112                if (burst)
 113                        DiseqcSendByte(budget, 0xff);
 114                else {
 115                        saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
 116                        mdelay(12);
 117                        udelay(500);
 118                        saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
 119                }
 120                msleep(20);
 121        }
 122
 123        return 0;
 124}
 125
 126/*
 127 *   Routines for the Fujitsu Siemens Activy budget card
 128 *   22 kHz tone and DiSEqC are handled by the frontend.
 129 *   Voltage must be set here.
 130 *   GPIO 1: LNBP EN, GPIO 2: LNBP VSEL
 131 */
 132static int SetVoltage_Activy(struct budget *budget,
 133                             enum fe_sec_voltage voltage)
 134{
 135        struct saa7146_dev *dev=budget->dev;
 136
 137        dprintk(2, "budget: %p\n", budget);
 138
 139        switch (voltage) {
 140                case SEC_VOLTAGE_13:
 141                        saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
 142                        saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
 143                        break;
 144                case SEC_VOLTAGE_18:
 145                        saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
 146                        saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
 147                        break;
 148                case SEC_VOLTAGE_OFF:
 149                        saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO);
 150                        break;
 151                default:
 152                        return -EINVAL;
 153        }
 154
 155        return 0;
 156}
 157
 158static int siemens_budget_set_voltage(struct dvb_frontend *fe,
 159                                      enum fe_sec_voltage voltage)
 160{
 161        struct budget* budget = (struct budget*) fe->dvb->priv;
 162
 163        return SetVoltage_Activy (budget, voltage);
 164}
 165
 166static int budget_set_tone(struct dvb_frontend *fe,
 167                           enum fe_sec_tone_mode tone)
 168{
 169        struct budget* budget = (struct budget*) fe->dvb->priv;
 170
 171        switch (tone) {
 172        case SEC_TONE_ON:
 173                Set22K (budget, 1);
 174                break;
 175
 176        case SEC_TONE_OFF:
 177                Set22K (budget, 0);
 178                break;
 179
 180        default:
 181                return -EINVAL;
 182        }
 183
 184        return 0;
 185}
 186
 187static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
 188{
 189        struct budget* budget = (struct budget*) fe->dvb->priv;
 190
 191        SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
 192
 193        return 0;
 194}
 195
 196static int budget_diseqc_send_burst(struct dvb_frontend *fe,
 197                                    enum fe_sec_mini_cmd minicmd)
 198{
 199        struct budget* budget = (struct budget*) fe->dvb->priv;
 200
 201        SendDiSEqCMsg (budget, 0, NULL, minicmd);
 202
 203        return 0;
 204}
 205
 206static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
 207{
 208        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 209        struct budget* budget = (struct budget*) fe->dvb->priv;
 210        u8 pwr = 0;
 211        u8 buf[4];
 212        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
 213        u32 div = (c->frequency + 479500) / 125;
 214
 215        if (c->frequency > 2000000)
 216                pwr = 3;
 217        else if (c->frequency > 1800000)
 218                pwr = 2;
 219        else if (c->frequency > 1600000)
 220                pwr = 1;
 221        else if (c->frequency > 1200000)
 222                pwr = 0;
 223        else if (c->frequency >= 1100000)
 224                pwr = 1;
 225        else pwr = 2;
 226
 227        buf[0] = (div >> 8) & 0x7f;
 228        buf[1] = div & 0xff;
 229        buf[2] = ((div & 0x18000) >> 10) | 0x95;
 230        buf[3] = (pwr << 6) | 0x30;
 231
 232        // NOTE: since we're using a prescaler of 2, we set the
 233        // divisor frequency to 62.5kHz and divide by 125 above
 234
 235        if (fe->ops.i2c_gate_ctrl)
 236                fe->ops.i2c_gate_ctrl(fe, 1);
 237        if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
 238        return 0;
 239}
 240
 241static struct ves1x93_config alps_bsrv2_config =
 242{
 243        .demod_address = 0x08,
 244        .xin = 90100000UL,
 245        .invert_pwm = 0,
 246};
 247
 248static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
 249{
 250        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 251        struct budget* budget = (struct budget*) fe->dvb->priv;
 252        u32 div;
 253        u8 data[4];
 254        struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
 255
 256        div = (c->frequency + 35937500 + 31250) / 62500;
 257
 258        data[0] = (div >> 8) & 0x7f;
 259        data[1] = div & 0xff;
 260        data[2] = 0x85 | ((div >> 10) & 0x60);
 261        data[3] = (c->frequency < 174000000 ? 0x88 : c->frequency < 470000000 ? 0x84 : 0x81);
 262
 263        if (fe->ops.i2c_gate_ctrl)
 264                fe->ops.i2c_gate_ctrl(fe, 1);
 265        if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
 266        return 0;
 267}
 268
 269static struct ves1820_config alps_tdbe2_config = {
 270        .demod_address = 0x09,
 271        .xin = 57840000UL,
 272        .invert = 1,
 273        .selagc = VES1820_SELAGC_SIGNAMPERR,
 274};
 275
 276static int grundig_29504_401_tuner_set_params(struct dvb_frontend *fe)
 277{
 278        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 279        struct budget *budget = fe->dvb->priv;
 280        u8 *tuner_addr = fe->tuner_priv;
 281        u32 div;
 282        u8 cfg, cpump, band_select;
 283        u8 data[4];
 284        struct i2c_msg msg = { .flags = 0, .buf = data, .len = sizeof(data) };
 285
 286        if (tuner_addr)
 287                msg.addr = *tuner_addr;
 288        else
 289                msg.addr = 0x61;
 290
 291        div = (36125000 + c->frequency) / 166666;
 292
 293        cfg = 0x88;
 294
 295        if (c->frequency < 175000000)
 296                cpump = 2;
 297        else if (c->frequency < 390000000)
 298                cpump = 1;
 299        else if (c->frequency < 470000000)
 300                cpump = 2;
 301        else if (c->frequency < 750000000)
 302                cpump = 1;
 303        else
 304                cpump = 3;
 305
 306        if (c->frequency < 175000000)
 307                band_select = 0x0e;
 308        else if (c->frequency < 470000000)
 309                band_select = 0x05;
 310        else
 311                band_select = 0x03;
 312
 313        data[0] = (div >> 8) & 0x7f;
 314        data[1] = div & 0xff;
 315        data[2] = ((div >> 10) & 0x60) | cfg;
 316        data[3] = (cpump << 6) | band_select;
 317
 318        if (fe->ops.i2c_gate_ctrl)
 319                fe->ops.i2c_gate_ctrl(fe, 1);
 320        if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
 321        return 0;
 322}
 323
 324static struct l64781_config grundig_29504_401_config = {
 325        .demod_address = 0x55,
 326};
 327
 328static struct l64781_config grundig_29504_401_config_activy = {
 329        .demod_address = 0x54,
 330};
 331
 332static u8 tuner_address_grundig_29504_401_activy = 0x60;
 333
 334static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
 335{
 336        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 337        struct budget* budget = (struct budget*) fe->dvb->priv;
 338        u32 div;
 339        u8 data[4];
 340        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
 341
 342        div = c->frequency / 125;
 343        data[0] = (div >> 8) & 0x7f;
 344        data[1] = div & 0xff;
 345        data[2] = 0x8e;
 346        data[3] = 0x00;
 347
 348        if (fe->ops.i2c_gate_ctrl)
 349                fe->ops.i2c_gate_ctrl(fe, 1);
 350        if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
 351        return 0;
 352}
 353
 354static struct tda8083_config grundig_29504_451_config = {
 355        .demod_address = 0x68,
 356};
 357
 358static int s5h1420_tuner_set_params(struct dvb_frontend *fe)
 359{
 360        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 361        struct budget* budget = (struct budget*) fe->dvb->priv;
 362        u32 div;
 363        u8 data[4];
 364        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
 365
 366        div = c->frequency / 1000;
 367        data[0] = (div >> 8) & 0x7f;
 368        data[1] = div & 0xff;
 369        data[2] = 0xc2;
 370
 371        if (div < 1450)
 372                data[3] = 0x00;
 373        else if (div < 1850)
 374                data[3] = 0x40;
 375        else if (div < 2000)
 376                data[3] = 0x80;
 377        else
 378                data[3] = 0xc0;
 379
 380        if (fe->ops.i2c_gate_ctrl)
 381                fe->ops.i2c_gate_ctrl(fe, 1);
 382        if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
 383
 384        return 0;
 385}
 386
 387static struct s5h1420_config s5h1420_config = {
 388        .demod_address = 0x53,
 389        .invert = 1,
 390        .cdclk_polarity = 1,
 391};
 392
 393static struct tda10086_config tda10086_config = {
 394        .demod_address = 0x0e,
 395        .invert = 0,
 396        .diseqc_tone = 1,
 397        .xtal_freq = TDA10086_XTAL_16M,
 398};
 399
 400static const struct stv0299_config alps_bsru6_config_activy = {
 401        .demod_address = 0x68,
 402        .inittab = alps_bsru6_inittab,
 403        .mclk = 88000000UL,
 404        .invert = 1,
 405        .op0_off = 1,
 406        .min_delay_ms = 100,
 407        .set_symbol_rate = alps_bsru6_set_symbol_rate,
 408};
 409
 410static const struct stv0299_config alps_bsbe1_config_activy = {
 411        .demod_address = 0x68,
 412        .inittab = alps_bsbe1_inittab,
 413        .mclk = 88000000UL,
 414        .invert = 1,
 415        .op0_off = 1,
 416        .min_delay_ms = 100,
 417        .set_symbol_rate = alps_bsbe1_set_symbol_rate,
 418};
 419
 420static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name)
 421{
 422        struct budget *budget = (struct budget *)fe->dvb->priv;
 423
 424        return request_firmware(fw, name, &budget->dev->pci->dev);
 425}
 426
 427
 428static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg)
 429{
 430        u8 val;
 431        struct i2c_msg msg[] = {
 432                { .addr = adr, .flags = 0, .buf = &reg, .len = 1 },
 433                { .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
 434        };
 435
 436        return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val;
 437}
 438
 439static u8 read_pwm(struct budget* budget)
 440{
 441        u8 b = 0xff;
 442        u8 pwm;
 443        struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
 444                                 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
 445
 446        if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
 447                pwm = 0x48;
 448
 449        return pwm;
 450}
 451
 452static struct stv090x_config tt1600_stv090x_config = {
 453        .device                 = STV0903,
 454        .demod_mode             = STV090x_SINGLE,
 455        .clk_mode               = STV090x_CLK_EXT,
 456
 457        .xtal                   = 13500000,
 458        .address                = 0x68,
 459
 460        .ts1_mode               = STV090x_TSMODE_DVBCI,
 461        .ts2_mode               = STV090x_TSMODE_SERIAL_CONTINUOUS,
 462
 463        .repeater_level         = STV090x_RPTLEVEL_16,
 464
 465        .tuner_init             = NULL,
 466        .tuner_sleep            = NULL,
 467        .tuner_set_mode         = NULL,
 468        .tuner_set_frequency    = NULL,
 469        .tuner_get_frequency    = NULL,
 470        .tuner_set_bandwidth    = NULL,
 471        .tuner_get_bandwidth    = NULL,
 472        .tuner_set_bbgain       = NULL,
 473        .tuner_get_bbgain       = NULL,
 474        .tuner_set_refclk       = NULL,
 475        .tuner_get_status       = NULL,
 476};
 477
 478static struct stv6110x_config tt1600_stv6110x_config = {
 479        .addr                   = 0x60,
 480        .refclk                 = 27000000,
 481        .clk_div                = 2,
 482};
 483
 484static struct isl6423_config tt1600_isl6423_config = {
 485        .current_max            = SEC_CURRENT_515m,
 486        .curlim                 = SEC_CURRENT_LIM_ON,
 487        .mod_extern             = 1,
 488        .addr                   = 0x08,
 489};
 490
 491static void frontend_init(struct budget *budget)
 492{
 493        (void)alps_bsbe1_config; /* avoid warning */
 494
 495        switch(budget->dev->pci->subsystem_device) {
 496        case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
 497        case 0x1013:
 498                // try the ALPS BSRV2 first of all
 499                budget->dvb_frontend = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &budget->i2c_adap);
 500                if (budget->dvb_frontend) {
 501                        budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
 502                        budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
 503                        budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
 504                        budget->dvb_frontend->ops.set_tone = budget_set_tone;
 505                        break;
 506                }
 507
 508                // try the ALPS BSRU6 now
 509                budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
 510                if (budget->dvb_frontend) {
 511                        budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
 512                        budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
 513                        if (budget->dev->pci->subsystem_device == 0x1003 && diseqc_method == 0) {
 514                                budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
 515                                budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
 516                                budget->dvb_frontend->ops.set_tone = budget_set_tone;
 517                        }
 518                        break;
 519                }
 520                break;
 521
 522        case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
 523
 524                budget->dvb_frontend = dvb_attach(ves1820_attach, &alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
 525                if (budget->dvb_frontend) {
 526                        budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
 527                        break;
 528                }
 529                break;
 530
 531        case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
 532
 533                budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap);
 534                if (budget->dvb_frontend) {
 535                        budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
 536                        budget->dvb_frontend->tuner_priv = NULL;
 537                        break;
 538                }
 539                break;
 540
 541        case 0x4f52: /* Cards based on Philips Semi Sylt PCI ref. design */
 542                budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
 543                if (budget->dvb_frontend) {
 544                        printk(KERN_INFO "budget: tuner ALPS BSRU6 in Philips Semi. Sylt detected\n");
 545                        budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
 546                        budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
 547                        break;
 548                }
 549                break;
 550
 551        case 0x4f60: /* Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/tsa5059) */
 552        {
 553                int subtype = i2c_readreg(&budget->i2c_adap, 0x50, 0x67);
 554
 555                if (subtype < 0)
 556                        break;
 557                /* fixme: find a better way to identify the card */
 558                if (subtype < 0x36) {
 559                        /* assume ALPS BSRU6 */
 560                        budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config_activy, &budget->i2c_adap);
 561                        if (budget->dvb_frontend) {
 562                                printk(KERN_INFO "budget: tuner ALPS BSRU6 detected\n");
 563                                budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
 564                                budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
 565                                budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
 566                                budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
 567                                break;
 568                        }
 569                } else {
 570                        /* assume ALPS BSBE1 */
 571                        /* reset tuner */
 572                        saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTLO);
 573                        msleep(50);
 574                        saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTHI);
 575                        msleep(250);
 576                        budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config_activy, &budget->i2c_adap);
 577                        if (budget->dvb_frontend) {
 578                                printk(KERN_INFO "budget: tuner ALPS BSBE1 detected\n");
 579                                budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
 580                                budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
 581                                budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
 582                                budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
 583                                break;
 584                        }
 585                }
 586                break;
 587        }
 588
 589        case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
 590                budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap);
 591                if (budget->dvb_frontend) {
 592                        budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
 593                        budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
 594                        budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
 595                }
 596                break;
 597
 598        case 0x5f60: /* Fujitsu Siemens Activy Budget-T PCI rev AL (tda10046/ALPS TDHD1-204A) */
 599                budget->dvb_frontend = dvb_attach(tda10046_attach, &alps_tdhd1_204a_config, &budget->i2c_adap);
 600                if (budget->dvb_frontend) {
 601                        budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdhd1_204a_tuner_set_params;
 602                        budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
 603                }
 604                break;
 605
 606        case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */
 607                budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap);
 608                if (budget->dvb_frontend) {
 609                        budget->dvb_frontend->tuner_priv = &tuner_address_grundig_29504_401_activy;
 610                        budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
 611                }
 612                break;
 613
 614        case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
 615        {
 616                struct dvb_frontend *fe;
 617
 618                fe = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap);
 619                if (fe) {
 620                        fe->ops.tuner_ops.set_params = s5h1420_tuner_set_params;
 621                        budget->dvb_frontend = fe;
 622                        if (dvb_attach(lnbp21_attach, fe, &budget->i2c_adap,
 623                                       0, 0) == NULL) {
 624                                printk("%s: No LNBP21 found!\n", __func__);
 625                                goto error_out;
 626                        }
 627                        break;
 628                }
 629        }
 630        /* fall through */
 631        case 0x1018: // TT Budget-S-1401 (philips tda10086/philips tda8262)
 632        {
 633                struct dvb_frontend *fe;
 634
 635                // gpio2 is connected to CLB - reset it + leave it high
 636                saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
 637                msleep(1);
 638                saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
 639                msleep(1);
 640
 641                fe = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap);
 642                if (fe) {
 643                        budget->dvb_frontend = fe;
 644                        if (dvb_attach(tda826x_attach, fe, 0x60,
 645                                       &budget->i2c_adap, 0) == NULL)
 646                                printk("%s: No tda826x found!\n", __func__);
 647                        if (dvb_attach(lnbp21_attach, fe,
 648                                       &budget->i2c_adap, 0, 0) == NULL) {
 649                                printk("%s: No LNBP21 found!\n", __func__);
 650                                goto error_out;
 651                        }
 652                        break;
 653                }
 654        }
 655        /* fall through */
 656
 657        case 0x101c: { /* TT S2-1600 */
 658                        const struct stv6110x_devctl *ctl;
 659                        saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
 660                        msleep(50);
 661                        saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
 662                        msleep(250);
 663
 664                        budget->dvb_frontend = dvb_attach(stv090x_attach,
 665                                                          &tt1600_stv090x_config,
 666                                                          &budget->i2c_adap,
 667                                                          STV090x_DEMODULATOR_0);
 668
 669                        if (budget->dvb_frontend) {
 670
 671                                ctl = dvb_attach(stv6110x_attach,
 672                                                 budget->dvb_frontend,
 673                                                 &tt1600_stv6110x_config,
 674                                                 &budget->i2c_adap);
 675
 676                                if (ctl) {
 677                                        tt1600_stv090x_config.tuner_init          = ctl->tuner_init;
 678                                        tt1600_stv090x_config.tuner_sleep         = ctl->tuner_sleep;
 679                                        tt1600_stv090x_config.tuner_set_mode      = ctl->tuner_set_mode;
 680                                        tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
 681                                        tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
 682                                        tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
 683                                        tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
 684                                        tt1600_stv090x_config.tuner_set_bbgain    = ctl->tuner_set_bbgain;
 685                                        tt1600_stv090x_config.tuner_get_bbgain    = ctl->tuner_get_bbgain;
 686                                        tt1600_stv090x_config.tuner_set_refclk    = ctl->tuner_set_refclk;
 687                                        tt1600_stv090x_config.tuner_get_status    = ctl->tuner_get_status;
 688
 689                                        /* call the init function once to initialize
 690                                           tuner's clock output divider and demod's
 691                                           master clock */
 692                                        if (budget->dvb_frontend->ops.init)
 693                                                budget->dvb_frontend->ops.init(budget->dvb_frontend);
 694
 695                                        if (dvb_attach(isl6423_attach,
 696                                                       budget->dvb_frontend,
 697                                                       &budget->i2c_adap,
 698                                                       &tt1600_isl6423_config) == NULL) {
 699                                                printk(KERN_ERR "%s: No Intersil ISL6423 found!\n", __func__);
 700                                                goto error_out;
 701                                        }
 702                                } else {
 703                                        printk(KERN_ERR "%s: No STV6110(A) Silicon Tuner found!\n", __func__);
 704                                        goto error_out;
 705                                }
 706                        }
 707                }
 708                break;
 709
 710        case 0x1020: { /* Omicom S2 */
 711                        const struct stv6110x_devctl *ctl;
 712                        saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
 713                        msleep(50);
 714                        saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
 715                        msleep(250);
 716
 717                        budget->dvb_frontend = dvb_attach(stv090x_attach,
 718                                                          &tt1600_stv090x_config,
 719                                                          &budget->i2c_adap,
 720                                                          STV090x_DEMODULATOR_0);
 721
 722                        if (budget->dvb_frontend) {
 723                                printk(KERN_INFO "budget: Omicom S2 detected\n");
 724
 725                                ctl = dvb_attach(stv6110x_attach,
 726                                                 budget->dvb_frontend,
 727                                                 &tt1600_stv6110x_config,
 728                                                 &budget->i2c_adap);
 729
 730                                if (ctl) {
 731                                        tt1600_stv090x_config.tuner_init          = ctl->tuner_init;
 732                                        tt1600_stv090x_config.tuner_sleep         = ctl->tuner_sleep;
 733                                        tt1600_stv090x_config.tuner_set_mode      = ctl->tuner_set_mode;
 734                                        tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
 735                                        tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
 736                                        tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
 737                                        tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
 738                                        tt1600_stv090x_config.tuner_set_bbgain    = ctl->tuner_set_bbgain;
 739                                        tt1600_stv090x_config.tuner_get_bbgain    = ctl->tuner_get_bbgain;
 740                                        tt1600_stv090x_config.tuner_set_refclk    = ctl->tuner_set_refclk;
 741                                        tt1600_stv090x_config.tuner_get_status    = ctl->tuner_get_status;
 742
 743                                        /* call the init function once to initialize
 744                                           tuner's clock output divider and demod's
 745                                           master clock */
 746                                        if (budget->dvb_frontend->ops.init)
 747                                                budget->dvb_frontend->ops.init(budget->dvb_frontend);
 748
 749                                        if (dvb_attach(lnbh24_attach,
 750                                                        budget->dvb_frontend,
 751                                                        &budget->i2c_adap,
 752                                                        LNBH24_PCL | LNBH24_TTX,
 753                                                        LNBH24_TEN, 0x14>>1) == NULL) {
 754                                                printk(KERN_ERR
 755                                                "No LNBH24 found!\n");
 756                                                goto error_out;
 757                                        }
 758                                } else {
 759                                        printk(KERN_ERR "%s: No STV6110(A) Silicon Tuner found!\n", __func__);
 760                                        goto error_out;
 761                                }
 762                        }
 763                }
 764                break;
 765        }
 766
 767        if (budget->dvb_frontend == NULL) {
 768                printk("budget: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
 769                       budget->dev->pci->vendor,
 770                       budget->dev->pci->device,
 771                       budget->dev->pci->subsystem_vendor,
 772                       budget->dev->pci->subsystem_device);
 773        } else {
 774                if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend))
 775                        goto error_out;
 776        }
 777        return;
 778
 779error_out:
 780        printk("budget: Frontend registration failed!\n");
 781        dvb_frontend_detach(budget->dvb_frontend);
 782        budget->dvb_frontend = NULL;
 783        return;
 784}
 785
 786static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
 787{
 788        struct budget *budget = NULL;
 789        int err;
 790
 791        budget = kmalloc(sizeof(struct budget), GFP_KERNEL);
 792        if( NULL == budget ) {
 793                return -ENOMEM;
 794        }
 795
 796        dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget);
 797
 798        dev->ext_priv = budget;
 799
 800        err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr);
 801        if (err) {
 802                printk("==> failed\n");
 803                kfree (budget);
 804                return err;
 805        }
 806
 807        budget->dvb_adapter.priv = budget;
 808        frontend_init(budget);
 809
 810        ttpci_budget_init_hooks(budget);
 811
 812        return 0;
 813}
 814
 815static int budget_detach (struct saa7146_dev* dev)
 816{
 817        struct budget *budget = (struct budget*) dev->ext_priv;
 818        int err;
 819
 820        if (budget->dvb_frontend) {
 821                dvb_unregister_frontend(budget->dvb_frontend);
 822                dvb_frontend_detach(budget->dvb_frontend);
 823        }
 824
 825        err = ttpci_budget_deinit (budget);
 826
 827        kfree (budget);
 828        dev->ext_priv = NULL;
 829
 830        return err;
 831}
 832
 833static struct saa7146_extension budget_extension;
 834
 835MAKE_BUDGET_INFO(ttbs,  "TT-Budget/WinTV-NOVA-S  PCI",  BUDGET_TT);
 836MAKE_BUDGET_INFO(ttbc,  "TT-Budget/WinTV-NOVA-C  PCI",  BUDGET_TT);
 837MAKE_BUDGET_INFO(ttbt,  "TT-Budget/WinTV-NOVA-T  PCI",  BUDGET_TT);
 838MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI",       BUDGET_TT_HW_DISEQC);
 839MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
 840MAKE_BUDGET_INFO(tt1600, "TT-Budget S2-1600 PCI", BUDGET_TT);
 841MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
 842MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
 843MAKE_BUDGET_INFO(fsact,  "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
 844MAKE_BUDGET_INFO(fsact1, "Fujitsu Siemens Activy Budget-T PCI (rev AL/ALPS TDHD1-204A)", BUDGET_FS_ACTIVY);
 845MAKE_BUDGET_INFO(omicom, "Omicom S2 PCI", BUDGET_TT);
 846MAKE_BUDGET_INFO(sylt,   "Philips Semi Sylt PCI", BUDGET_TT_HW_DISEQC);
 847
 848static const struct pci_device_id pci_tbl[] = {
 849        MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1003),
 850        MAKE_EXTENSION_PCI(ttbc,  0x13c2, 0x1004),
 851        MAKE_EXTENSION_PCI(ttbt,  0x13c2, 0x1005),
 852        MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
 853        MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1016),
 854        MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
 855        MAKE_EXTENSION_PCI(tt1600, 0x13c2, 0x101c),
 856        MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
 857        MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
 858        MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60),
 859        MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61),
 860        MAKE_EXTENSION_PCI(omicom, 0x14c4, 0x1020),
 861        MAKE_EXTENSION_PCI(sylt, 0x1131, 0x4f52),
 862        {
 863                .vendor    = 0,
 864        }
 865};
 866
 867MODULE_DEVICE_TABLE(pci, pci_tbl);
 868
 869static struct saa7146_extension budget_extension = {
 870        .name           = "budget dvb",
 871        .flags          = SAA7146_USE_I2C_IRQ,
 872
 873        .module         = THIS_MODULE,
 874        .pci_tbl        = pci_tbl,
 875        .attach         = budget_attach,
 876        .detach         = budget_detach,
 877
 878        .irq_mask       = MASK_10,
 879        .irq_func       = ttpci_budget_irq10_handler,
 880};
 881
 882static int __init budget_init(void)
 883{
 884        return saa7146_register_extension(&budget_extension);
 885}
 886
 887static void __exit budget_exit(void)
 888{
 889        saa7146_unregister_extension(&budget_extension);
 890}
 891
 892module_init(budget_init);
 893module_exit(budget_exit);
 894
 895MODULE_LICENSE("GPL");
 896MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
 897MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB cards by Siemens, Technotrend, Hauppauge");
 898