linux/drivers/media/pci/ttpci/budget-ci.c
<<
>>
Prefs
   1/*
   2 * budget-ci.c: driver for the SAA7146 based Budget DVB cards
   3 *
   4 * Compiled from various sources by Michael Hunold <michael@mihu.de>
   5 *
   6 *     msp430 IR support contributed by Jack Thomasson <jkt@Helius.COM>
   7 *     partially based on the Siemens DVB driver by Ralph+Marcus Metzler
   8 *
   9 * CI interface support (c) 2004 Andrew de Quincey <adq_dvb@lidskialf.net>
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License
  13 * as published by the Free Software Foundation; either version 2
  14 * of the License, or (at your option) any later version.
  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  26 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
  27 *
  28 *
  29 * the project's page is at https://linuxtv.org
  30 */
  31
  32#include <linux/module.h>
  33#include <linux/errno.h>
  34#include <linux/slab.h>
  35#include <linux/interrupt.h>
  36#include <linux/spinlock.h>
  37#include <media/rc-core.h>
  38
  39#include "budget.h"
  40
  41#include "dvb_ca_en50221.h"
  42#include "stv0299.h"
  43#include "stv0297.h"
  44#include "tda1004x.h"
  45#include "stb0899_drv.h"
  46#include "stb0899_reg.h"
  47#include "stb0899_cfg.h"
  48#include "stb6100.h"
  49#include "stb6100_cfg.h"
  50#include "lnbp21.h"
  51#include "bsbe1.h"
  52#include "bsru6.h"
  53#include "tda1002x.h"
  54#include "tda827x.h"
  55#include "bsbe1-d01a.h"
  56
  57#define MODULE_NAME "budget_ci"
  58
  59/*
  60 * Regarding DEBIADDR_IR:
  61 * Some CI modules hang if random addresses are read.
  62 * Using address 0x4000 for the IR read means that we
  63 * use the same address as for CI version, which should
  64 * be a safe default.
  65 */
  66#define DEBIADDR_IR             0x4000
  67#define DEBIADDR_CICONTROL      0x0000
  68#define DEBIADDR_CIVERSION      0x4000
  69#define DEBIADDR_IO             0x1000
  70#define DEBIADDR_ATTR           0x3000
  71
  72#define CICONTROL_RESET         0x01
  73#define CICONTROL_ENABLETS      0x02
  74#define CICONTROL_CAMDETECT     0x08
  75
  76#define DEBICICTL               0x00420000
  77#define DEBICICAM               0x02420000
  78
  79#define SLOTSTATUS_NONE         1
  80#define SLOTSTATUS_PRESENT      2
  81#define SLOTSTATUS_RESET        4
  82#define SLOTSTATUS_READY        8
  83#define SLOTSTATUS_OCCUPIED     (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
  84
  85/* RC5 device wildcard */
  86#define IR_DEVICE_ANY           255
  87
  88static int rc5_device = -1;
  89module_param(rc5_device, int, 0644);
  90MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
  91
  92static int ir_debug;
  93module_param(ir_debug, int, 0644);
  94MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
  95
  96DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  97
  98struct budget_ci_ir {
  99        struct rc_dev *dev;
 100        struct tasklet_struct msp430_irq_tasklet;
 101        char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
 102        char phys[32];
 103        int rc5_device;
 104        u32 ir_key;
 105        bool have_command;
 106        bool full_rc5;          /* Outputs a full RC5 code */
 107};
 108
 109struct budget_ci {
 110        struct budget budget;
 111        struct tasklet_struct ciintf_irq_tasklet;
 112        int slot_status;
 113        int ci_irq;
 114        struct dvb_ca_en50221 ca;
 115        struct budget_ci_ir ir;
 116        u8 tuner_pll_address; /* used for philips_tdm1316l configs */
 117};
 118
 119static void msp430_ir_interrupt(unsigned long data)
 120{
 121        struct budget_ci *budget_ci = (struct budget_ci *) data;
 122        struct rc_dev *dev = budget_ci->ir.dev;
 123        u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
 124
 125        /*
 126         * The msp430 chip can generate two different bytes, command and device
 127         *
 128         * type1: X1CCCCCC, C = command bits (0 - 63)
 129         * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
 130         *
 131         * Each signal from the remote control can generate one or more command
 132         * bytes and one or more device bytes. For the repeated bytes, the
 133         * highest bit (X) is set. The first command byte is always generated
 134         * before the first device byte. Other than that, no specific order
 135         * seems to apply. To make life interesting, bytes can also be lost.
 136         *
 137         * Only when we have a command and device byte, a keypress is
 138         * generated.
 139         */
 140
 141        if (ir_debug)
 142                printk("budget_ci: received byte 0x%02x\n", command);
 143
 144        /* Remove repeat bit, we use every command */
 145        command = command & 0x7f;
 146
 147        /* Is this a RC5 command byte? */
 148        if (command & 0x40) {
 149                budget_ci->ir.have_command = true;
 150                budget_ci->ir.ir_key = command & 0x3f;
 151                return;
 152        }
 153
 154        /* It's a RC5 device byte */
 155        if (!budget_ci->ir.have_command)
 156                return;
 157        budget_ci->ir.have_command = false;
 158
 159        if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
 160            budget_ci->ir.rc5_device != (command & 0x1f))
 161                return;
 162
 163        if (budget_ci->ir.full_rc5) {
 164                rc_keydown(dev, RC_TYPE_RC5,
 165                           RC_SCANCODE_RC5(budget_ci->ir.rc5_device, budget_ci->ir.ir_key),
 166                           !!(command & 0x20));
 167                return;
 168        }
 169
 170        /* FIXME: We should generate complete scancodes for all devices */
 171        rc_keydown(dev, RC_TYPE_UNKNOWN, budget_ci->ir.ir_key, !!(command & 0x20));
 172}
 173
 174static int msp430_ir_init(struct budget_ci *budget_ci)
 175{
 176        struct saa7146_dev *saa = budget_ci->budget.dev;
 177        struct rc_dev *dev;
 178        int error;
 179
 180        dev = rc_allocate_device();
 181        if (!dev) {
 182                printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
 183                return -ENOMEM;
 184        }
 185
 186        snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
 187                 "Budget-CI dvb ir receiver %s", saa->name);
 188        snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
 189                 "pci-%s/ir0", pci_name(saa->pci));
 190
 191        dev->driver_name = MODULE_NAME;
 192        dev->input_name = budget_ci->ir.name;
 193        dev->input_phys = budget_ci->ir.phys;
 194        dev->input_id.bustype = BUS_PCI;
 195        dev->input_id.version = 1;
 196        if (saa->pci->subsystem_vendor) {
 197                dev->input_id.vendor = saa->pci->subsystem_vendor;
 198                dev->input_id.product = saa->pci->subsystem_device;
 199        } else {
 200                dev->input_id.vendor = saa->pci->vendor;
 201                dev->input_id.product = saa->pci->device;
 202        }
 203        dev->dev.parent = &saa->pci->dev;
 204
 205        if (rc5_device < 0)
 206                budget_ci->ir.rc5_device = IR_DEVICE_ANY;
 207        else
 208                budget_ci->ir.rc5_device = rc5_device;
 209
 210        /* Select keymap and address */
 211        switch (budget_ci->budget.dev->pci->subsystem_device) {
 212        case 0x100c:
 213        case 0x100f:
 214        case 0x1011:
 215        case 0x1012:
 216                /* The hauppauge keymap is a superset of these remotes */
 217                dev->map_name = RC_MAP_HAUPPAUGE;
 218                budget_ci->ir.full_rc5 = true;
 219
 220                if (rc5_device < 0)
 221                        budget_ci->ir.rc5_device = 0x1f;
 222                break;
 223        case 0x1010:
 224        case 0x1017:
 225        case 0x1019:
 226        case 0x101a:
 227        case 0x101b:
 228                /* for the Technotrend 1500 bundled remote */
 229                dev->map_name = RC_MAP_TT_1500;
 230                break;
 231        default:
 232                /* unknown remote */
 233                dev->map_name = RC_MAP_BUDGET_CI_OLD;
 234                break;
 235        }
 236        if (!budget_ci->ir.full_rc5)
 237                dev->scancode_mask = 0xff;
 238
 239        error = rc_register_device(dev);
 240        if (error) {
 241                printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
 242                rc_free_device(dev);
 243                return error;
 244        }
 245
 246        budget_ci->ir.dev = dev;
 247
 248        tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
 249                     (unsigned long) budget_ci);
 250
 251        SAA7146_IER_ENABLE(saa, MASK_06);
 252        saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
 253
 254        return 0;
 255}
 256
 257static void msp430_ir_deinit(struct budget_ci *budget_ci)
 258{
 259        struct saa7146_dev *saa = budget_ci->budget.dev;
 260
 261        SAA7146_IER_DISABLE(saa, MASK_06);
 262        saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
 263        tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
 264
 265        rc_unregister_device(budget_ci->ir.dev);
 266}
 267
 268static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
 269{
 270        struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
 271
 272        if (slot != 0)
 273                return -EINVAL;
 274
 275        return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
 276                                     DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
 277}
 278
 279static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
 280{
 281        struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
 282
 283        if (slot != 0)
 284                return -EINVAL;
 285
 286        return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
 287                                      DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
 288}
 289
 290static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
 291{
 292        struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
 293
 294        if (slot != 0)
 295                return -EINVAL;
 296
 297        return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
 298                                     DEBIADDR_IO | (address & 3), 1, 1, 0);
 299}
 300
 301static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
 302{
 303        struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
 304
 305        if (slot != 0)
 306                return -EINVAL;
 307
 308        return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
 309                                      DEBIADDR_IO | (address & 3), 1, value, 1, 0);
 310}
 311
 312static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
 313{
 314        struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
 315        struct saa7146_dev *saa = budget_ci->budget.dev;
 316
 317        if (slot != 0)
 318                return -EINVAL;
 319
 320        if (budget_ci->ci_irq) {
 321                // trigger on RISING edge during reset so we know when READY is re-asserted
 322                saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
 323        }
 324        budget_ci->slot_status = SLOTSTATUS_RESET;
 325        ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
 326        msleep(1);
 327        ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
 328                               CICONTROL_RESET, 1, 0);
 329
 330        saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
 331        ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
 332        return 0;
 333}
 334
 335static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
 336{
 337        struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
 338        struct saa7146_dev *saa = budget_ci->budget.dev;
 339
 340        if (slot != 0)
 341                return -EINVAL;
 342
 343        saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
 344        ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
 345        return 0;
 346}
 347
 348static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
 349{
 350        struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
 351        struct saa7146_dev *saa = budget_ci->budget.dev;
 352        int tmp;
 353
 354        if (slot != 0)
 355                return -EINVAL;
 356
 357        saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
 358
 359        tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
 360        ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
 361                               tmp | CICONTROL_ENABLETS, 1, 0);
 362
 363        ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
 364        return 0;
 365}
 366
 367static void ciintf_interrupt(unsigned long data)
 368{
 369        struct budget_ci *budget_ci = (struct budget_ci *) data;
 370        struct saa7146_dev *saa = budget_ci->budget.dev;
 371        unsigned int flags;
 372
 373        // ensure we don't get spurious IRQs during initialisation
 374        if (!budget_ci->budget.ci_present)
 375                return;
 376
 377        // read the CAM status
 378        flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
 379        if (flags & CICONTROL_CAMDETECT) {
 380
 381                // GPIO should be set to trigger on falling edge if a CAM is present
 382                saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
 383
 384                if (budget_ci->slot_status & SLOTSTATUS_NONE) {
 385                        // CAM insertion IRQ
 386                        budget_ci->slot_status = SLOTSTATUS_PRESENT;
 387                        dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
 388                                                     DVB_CA_EN50221_CAMCHANGE_INSERTED);
 389
 390                } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
 391                        // CAM ready (reset completed)
 392                        budget_ci->slot_status = SLOTSTATUS_READY;
 393                        dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
 394
 395                } else if (budget_ci->slot_status & SLOTSTATUS_READY) {
 396                        // FR/DA IRQ
 397                        dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
 398                }
 399        } else {
 400
 401                // trigger on rising edge if a CAM is not present - when a CAM is inserted, we
 402                // only want to get the IRQ when it sets READY. If we trigger on the falling edge,
 403                // the CAM might not actually be ready yet.
 404                saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
 405
 406                // generate a CAM removal IRQ if we haven't already
 407                if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
 408                        // CAM removal IRQ
 409                        budget_ci->slot_status = SLOTSTATUS_NONE;
 410                        dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
 411                                                     DVB_CA_EN50221_CAMCHANGE_REMOVED);
 412                }
 413        }
 414}
 415
 416static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
 417{
 418        struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
 419        unsigned int flags;
 420
 421        // ensure we don't get spurious IRQs during initialisation
 422        if (!budget_ci->budget.ci_present)
 423                return -EINVAL;
 424
 425        // read the CAM status
 426        flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
 427        if (flags & CICONTROL_CAMDETECT) {
 428                // mark it as present if it wasn't before
 429                if (budget_ci->slot_status & SLOTSTATUS_NONE) {
 430                        budget_ci->slot_status = SLOTSTATUS_PRESENT;
 431                }
 432
 433                // during a RESET, we check if we can read from IO memory to see when CAM is ready
 434                if (budget_ci->slot_status & SLOTSTATUS_RESET) {
 435                        if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
 436                                budget_ci->slot_status = SLOTSTATUS_READY;
 437                        }
 438                }
 439        } else {
 440                budget_ci->slot_status = SLOTSTATUS_NONE;
 441        }
 442
 443        if (budget_ci->slot_status != SLOTSTATUS_NONE) {
 444                if (budget_ci->slot_status & SLOTSTATUS_READY) {
 445                        return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
 446                }
 447                return DVB_CA_EN50221_POLL_CAM_PRESENT;
 448        }
 449
 450        return 0;
 451}
 452
 453static int ciintf_init(struct budget_ci *budget_ci)
 454{
 455        struct saa7146_dev *saa = budget_ci->budget.dev;
 456        int flags;
 457        int result;
 458        int ci_version;
 459        int ca_flags;
 460
 461        memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
 462
 463        // enable DEBI pins
 464        saa7146_write(saa, MC1, MASK_27 | MASK_11);
 465
 466        // test if it is there
 467        ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
 468        if ((ci_version & 0xa0) != 0xa0) {
 469                result = -ENODEV;
 470                goto error;
 471        }
 472
 473        // determine whether a CAM is present or not
 474        flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
 475        budget_ci->slot_status = SLOTSTATUS_NONE;
 476        if (flags & CICONTROL_CAMDETECT)
 477                budget_ci->slot_status = SLOTSTATUS_PRESENT;
 478
 479        // version 0xa2 of the CI firmware doesn't generate interrupts
 480        if (ci_version == 0xa2) {
 481                ca_flags = 0;
 482                budget_ci->ci_irq = 0;
 483        } else {
 484                ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
 485                                DVB_CA_EN50221_FLAG_IRQ_FR |
 486                                DVB_CA_EN50221_FLAG_IRQ_DA;
 487                budget_ci->ci_irq = 1;
 488        }
 489
 490        // register CI interface
 491        budget_ci->ca.owner = THIS_MODULE;
 492        budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
 493        budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
 494        budget_ci->ca.read_cam_control = ciintf_read_cam_control;
 495        budget_ci->ca.write_cam_control = ciintf_write_cam_control;
 496        budget_ci->ca.slot_reset = ciintf_slot_reset;
 497        budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
 498        budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
 499        budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
 500        budget_ci->ca.data = budget_ci;
 501        if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
 502                                          &budget_ci->ca,
 503                                          ca_flags, 1)) != 0) {
 504                printk("budget_ci: CI interface detected, but initialisation failed.\n");
 505                goto error;
 506        }
 507
 508        // Setup CI slot IRQ
 509        if (budget_ci->ci_irq) {
 510                tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
 511                if (budget_ci->slot_status != SLOTSTATUS_NONE) {
 512                        saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
 513                } else {
 514                        saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
 515                }
 516                SAA7146_IER_ENABLE(saa, MASK_03);
 517        }
 518
 519        // enable interface
 520        ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
 521                               CICONTROL_RESET, 1, 0);
 522
 523        // success!
 524        printk("budget_ci: CI interface initialised\n");
 525        budget_ci->budget.ci_present = 1;
 526
 527        // forge a fake CI IRQ so the CAM state is setup correctly
 528        if (budget_ci->ci_irq) {
 529                flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
 530                if (budget_ci->slot_status != SLOTSTATUS_NONE)
 531                        flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
 532                dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
 533        }
 534
 535        return 0;
 536
 537error:
 538        saa7146_write(saa, MC1, MASK_27);
 539        return result;
 540}
 541
 542static void ciintf_deinit(struct budget_ci *budget_ci)
 543{
 544        struct saa7146_dev *saa = budget_ci->budget.dev;
 545
 546        // disable CI interrupts
 547        if (budget_ci->ci_irq) {
 548                SAA7146_IER_DISABLE(saa, MASK_03);
 549                saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
 550                tasklet_kill(&budget_ci->ciintf_irq_tasklet);
 551        }
 552
 553        // reset interface
 554        ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
 555        msleep(1);
 556        ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
 557                               CICONTROL_RESET, 1, 0);
 558
 559        // disable TS data stream to CI interface
 560        saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
 561
 562        // release the CA device
 563        dvb_ca_en50221_release(&budget_ci->ca);
 564
 565        // disable DEBI pins
 566        saa7146_write(saa, MC1, MASK_27);
 567}
 568
 569static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
 570{
 571        struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
 572
 573        dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
 574
 575        if (*isr & MASK_06)
 576                tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
 577
 578        if (*isr & MASK_10)
 579                ttpci_budget_irq10_handler(dev, isr);
 580
 581        if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
 582                tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
 583}
 584
 585static u8 philips_su1278_tt_inittab[] = {
 586        0x01, 0x0f,
 587        0x02, 0x30,
 588        0x03, 0x00,
 589        0x04, 0x5b,
 590        0x05, 0x85,
 591        0x06, 0x02,
 592        0x07, 0x00,
 593        0x08, 0x02,
 594        0x09, 0x00,
 595        0x0C, 0x01,
 596        0x0D, 0x81,
 597        0x0E, 0x44,
 598        0x0f, 0x14,
 599        0x10, 0x3c,
 600        0x11, 0x84,
 601        0x12, 0xda,
 602        0x13, 0x97,
 603        0x14, 0x95,
 604        0x15, 0xc9,
 605        0x16, 0x19,
 606        0x17, 0x8c,
 607        0x18, 0x59,
 608        0x19, 0xf8,
 609        0x1a, 0xfe,
 610        0x1c, 0x7f,
 611        0x1d, 0x00,
 612        0x1e, 0x00,
 613        0x1f, 0x50,
 614        0x20, 0x00,
 615        0x21, 0x00,
 616        0x22, 0x00,
 617        0x23, 0x00,
 618        0x28, 0x00,
 619        0x29, 0x28,
 620        0x2a, 0x14,
 621        0x2b, 0x0f,
 622        0x2c, 0x09,
 623        0x2d, 0x09,
 624        0x31, 0x1f,
 625        0x32, 0x19,
 626        0x33, 0xfc,
 627        0x34, 0x93,
 628        0xff, 0xff
 629};
 630
 631static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
 632{
 633        stv0299_writereg(fe, 0x0e, 0x44);
 634        if (srate >= 10000000) {
 635                stv0299_writereg(fe, 0x13, 0x97);
 636                stv0299_writereg(fe, 0x14, 0x95);
 637                stv0299_writereg(fe, 0x15, 0xc9);
 638                stv0299_writereg(fe, 0x17, 0x8c);
 639                stv0299_writereg(fe, 0x1a, 0xfe);
 640                stv0299_writereg(fe, 0x1c, 0x7f);
 641                stv0299_writereg(fe, 0x2d, 0x09);
 642        } else {
 643                stv0299_writereg(fe, 0x13, 0x99);
 644                stv0299_writereg(fe, 0x14, 0x8d);
 645                stv0299_writereg(fe, 0x15, 0xce);
 646                stv0299_writereg(fe, 0x17, 0x43);
 647                stv0299_writereg(fe, 0x1a, 0x1d);
 648                stv0299_writereg(fe, 0x1c, 0x12);
 649                stv0299_writereg(fe, 0x2d, 0x05);
 650        }
 651        stv0299_writereg(fe, 0x0e, 0x23);
 652        stv0299_writereg(fe, 0x0f, 0x94);
 653        stv0299_writereg(fe, 0x10, 0x39);
 654        stv0299_writereg(fe, 0x15, 0xc9);
 655
 656        stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
 657        stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
 658        stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
 659
 660        return 0;
 661}
 662
 663static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe)
 664{
 665        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 666        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
 667        u32 div;
 668        u8 buf[4];
 669        struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
 670
 671        if ((p->frequency < 950000) || (p->frequency > 2150000))
 672                return -EINVAL;
 673
 674        div = (p->frequency + (500 - 1)) / 500; /* round correctly */
 675        buf[0] = (div >> 8) & 0x7f;
 676        buf[1] = div & 0xff;
 677        buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
 678        buf[3] = 0x20;
 679
 680        if (p->symbol_rate < 4000000)
 681                buf[3] |= 1;
 682
 683        if (p->frequency < 1250000)
 684                buf[3] |= 0;
 685        else if (p->frequency < 1550000)
 686                buf[3] |= 0x40;
 687        else if (p->frequency < 2050000)
 688                buf[3] |= 0x80;
 689        else if (p->frequency < 2150000)
 690                buf[3] |= 0xC0;
 691
 692        if (fe->ops.i2c_gate_ctrl)
 693                fe->ops.i2c_gate_ctrl(fe, 1);
 694        if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
 695                return -EIO;
 696        return 0;
 697}
 698
 699static struct stv0299_config philips_su1278_tt_config = {
 700
 701        .demod_address = 0x68,
 702        .inittab = philips_su1278_tt_inittab,
 703        .mclk = 64000000UL,
 704        .invert = 0,
 705        .skip_reinit = 1,
 706        .lock_output = STV0299_LOCKOUTPUT_1,
 707        .volt13_op0_op1 = STV0299_VOLT13_OP1,
 708        .min_delay_ms = 50,
 709        .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
 710};
 711
 712
 713
 714static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
 715{
 716        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
 717        static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
 718        static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
 719        struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
 720                        sizeof(td1316_init) };
 721
 722        // setup PLL configuration
 723        if (fe->ops.i2c_gate_ctrl)
 724                fe->ops.i2c_gate_ctrl(fe, 1);
 725        if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
 726                return -EIO;
 727        msleep(1);
 728
 729        // disable the mc44BC374c (do not check for errors)
 730        tuner_msg.addr = 0x65;
 731        tuner_msg.buf = disable_mc44BC374c;
 732        tuner_msg.len = sizeof(disable_mc44BC374c);
 733        if (fe->ops.i2c_gate_ctrl)
 734                fe->ops.i2c_gate_ctrl(fe, 1);
 735        if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
 736                if (fe->ops.i2c_gate_ctrl)
 737                        fe->ops.i2c_gate_ctrl(fe, 1);
 738                i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
 739        }
 740
 741        return 0;
 742}
 743
 744static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
 745{
 746        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 747        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
 748        u8 tuner_buf[4];
 749        struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) };
 750        int tuner_frequency = 0;
 751        u8 band, cp, filter;
 752
 753        // determine charge pump
 754        tuner_frequency = p->frequency + 36130000;
 755        if (tuner_frequency < 87000000)
 756                return -EINVAL;
 757        else if (tuner_frequency < 130000000)
 758                cp = 3;
 759        else if (tuner_frequency < 160000000)
 760                cp = 5;
 761        else if (tuner_frequency < 200000000)
 762                cp = 6;
 763        else if (tuner_frequency < 290000000)
 764                cp = 3;
 765        else if (tuner_frequency < 420000000)
 766                cp = 5;
 767        else if (tuner_frequency < 480000000)
 768                cp = 6;
 769        else if (tuner_frequency < 620000000)
 770                cp = 3;
 771        else if (tuner_frequency < 830000000)
 772                cp = 5;
 773        else if (tuner_frequency < 895000000)
 774                cp = 7;
 775        else
 776                return -EINVAL;
 777
 778        // determine band
 779        if (p->frequency < 49000000)
 780                return -EINVAL;
 781        else if (p->frequency < 159000000)
 782                band = 1;
 783        else if (p->frequency < 444000000)
 784                band = 2;
 785        else if (p->frequency < 861000000)
 786                band = 4;
 787        else
 788                return -EINVAL;
 789
 790        // setup PLL filter and TDA9889
 791        switch (p->bandwidth_hz) {
 792        case 6000000:
 793                tda1004x_writereg(fe, 0x0C, 0x14);
 794                filter = 0;
 795                break;
 796
 797        case 7000000:
 798                tda1004x_writereg(fe, 0x0C, 0x80);
 799                filter = 0;
 800                break;
 801
 802        case 8000000:
 803                tda1004x_writereg(fe, 0x0C, 0x14);
 804                filter = 1;
 805                break;
 806
 807        default:
 808                return -EINVAL;
 809        }
 810
 811        // calculate divisor
 812        // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
 813        tuner_frequency = (((p->frequency / 1000) * 6) + 217280) / 1000;
 814
 815        // setup tuner buffer
 816        tuner_buf[0] = tuner_frequency >> 8;
 817        tuner_buf[1] = tuner_frequency & 0xff;
 818        tuner_buf[2] = 0xca;
 819        tuner_buf[3] = (cp << 5) | (filter << 3) | band;
 820
 821        if (fe->ops.i2c_gate_ctrl)
 822                fe->ops.i2c_gate_ctrl(fe, 1);
 823        if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
 824                return -EIO;
 825
 826        msleep(1);
 827        return 0;
 828}
 829
 830static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
 831                                             const struct firmware **fw, char *name)
 832{
 833        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
 834
 835        return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
 836}
 837
 838static struct tda1004x_config philips_tdm1316l_config = {
 839
 840        .demod_address = 0x8,
 841        .invert = 0,
 842        .invert_oclk = 0,
 843        .xtal_freq = TDA10046_XTAL_4M,
 844        .agc_config = TDA10046_AGC_DEFAULT,
 845        .if_freq = TDA10046_FREQ_3617,
 846        .request_firmware = philips_tdm1316l_request_firmware,
 847};
 848
 849static struct tda1004x_config philips_tdm1316l_config_invert = {
 850
 851        .demod_address = 0x8,
 852        .invert = 1,
 853        .invert_oclk = 0,
 854        .xtal_freq = TDA10046_XTAL_4M,
 855        .agc_config = TDA10046_AGC_DEFAULT,
 856        .if_freq = TDA10046_FREQ_3617,
 857        .request_firmware = philips_tdm1316l_request_firmware,
 858};
 859
 860static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
 861{
 862        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 863        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
 864        u8 tuner_buf[5];
 865        struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
 866                                    .flags = 0,
 867                                    .buf = tuner_buf,
 868                                    .len = sizeof(tuner_buf) };
 869        int tuner_frequency = 0;
 870        u8 band, cp, filter;
 871
 872        // determine charge pump
 873        tuner_frequency = p->frequency + 36125000;
 874        if (tuner_frequency < 87000000)
 875                return -EINVAL;
 876        else if (tuner_frequency < 130000000) {
 877                cp = 3;
 878                band = 1;
 879        } else if (tuner_frequency < 160000000) {
 880                cp = 5;
 881                band = 1;
 882        } else if (tuner_frequency < 200000000) {
 883                cp = 6;
 884                band = 1;
 885        } else if (tuner_frequency < 290000000) {
 886                cp = 3;
 887                band = 2;
 888        } else if (tuner_frequency < 420000000) {
 889                cp = 5;
 890                band = 2;
 891        } else if (tuner_frequency < 480000000) {
 892                cp = 6;
 893                band = 2;
 894        } else if (tuner_frequency < 620000000) {
 895                cp = 3;
 896                band = 4;
 897        } else if (tuner_frequency < 830000000) {
 898                cp = 5;
 899                band = 4;
 900        } else if (tuner_frequency < 895000000) {
 901                cp = 7;
 902                band = 4;
 903        } else
 904                return -EINVAL;
 905
 906        // assume PLL filter should always be 8MHz for the moment.
 907        filter = 1;
 908
 909        // calculate divisor
 910        tuner_frequency = (p->frequency + 36125000 + (62500/2)) / 62500;
 911
 912        // setup tuner buffer
 913        tuner_buf[0] = tuner_frequency >> 8;
 914        tuner_buf[1] = tuner_frequency & 0xff;
 915        tuner_buf[2] = 0xc8;
 916        tuner_buf[3] = (cp << 5) | (filter << 3) | band;
 917        tuner_buf[4] = 0x80;
 918
 919        if (fe->ops.i2c_gate_ctrl)
 920                fe->ops.i2c_gate_ctrl(fe, 1);
 921        if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
 922                return -EIO;
 923
 924        msleep(50);
 925
 926        if (fe->ops.i2c_gate_ctrl)
 927                fe->ops.i2c_gate_ctrl(fe, 1);
 928        if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
 929                return -EIO;
 930
 931        msleep(1);
 932
 933        return 0;
 934}
 935
 936static u8 dvbc_philips_tdm1316l_inittab[] = {
 937        0x80, 0x01,
 938        0x80, 0x00,
 939        0x81, 0x01,
 940        0x81, 0x00,
 941        0x00, 0x09,
 942        0x01, 0x69,
 943        0x03, 0x00,
 944        0x04, 0x00,
 945        0x07, 0x00,
 946        0x08, 0x00,
 947        0x20, 0x00,
 948        0x21, 0x40,
 949        0x22, 0x00,
 950        0x23, 0x00,
 951        0x24, 0x40,
 952        0x25, 0x88,
 953        0x30, 0xff,
 954        0x31, 0x00,
 955        0x32, 0xff,
 956        0x33, 0x00,
 957        0x34, 0x50,
 958        0x35, 0x7f,
 959        0x36, 0x00,
 960        0x37, 0x20,
 961        0x38, 0x00,
 962        0x40, 0x1c,
 963        0x41, 0xff,
 964        0x42, 0x29,
 965        0x43, 0x20,
 966        0x44, 0xff,
 967        0x45, 0x00,
 968        0x46, 0x00,
 969        0x49, 0x04,
 970        0x4a, 0x00,
 971        0x4b, 0x7b,
 972        0x52, 0x30,
 973        0x55, 0xae,
 974        0x56, 0x47,
 975        0x57, 0xe1,
 976        0x58, 0x3a,
 977        0x5a, 0x1e,
 978        0x5b, 0x34,
 979        0x60, 0x00,
 980        0x63, 0x00,
 981        0x64, 0x00,
 982        0x65, 0x00,
 983        0x66, 0x00,
 984        0x67, 0x00,
 985        0x68, 0x00,
 986        0x69, 0x00,
 987        0x6a, 0x02,
 988        0x6b, 0x00,
 989        0x70, 0xff,
 990        0x71, 0x00,
 991        0x72, 0x00,
 992        0x73, 0x00,
 993        0x74, 0x0c,
 994        0x80, 0x00,
 995        0x81, 0x00,
 996        0x82, 0x00,
 997        0x83, 0x00,
 998        0x84, 0x04,
 999        0x85, 0x80,
1000        0x86, 0x24,
1001        0x87, 0x78,
1002        0x88, 0x10,
1003        0x89, 0x00,
1004        0x90, 0x01,
1005        0x91, 0x01,
1006        0xa0, 0x04,
1007        0xa1, 0x00,
1008        0xa2, 0x00,
1009        0xb0, 0x91,
1010        0xb1, 0x0b,
1011        0xc0, 0x53,
1012        0xc1, 0x70,
1013        0xc2, 0x12,
1014        0xd0, 0x00,
1015        0xd1, 0x00,
1016        0xd2, 0x00,
1017        0xd3, 0x00,
1018        0xd4, 0x00,
1019        0xd5, 0x00,
1020        0xde, 0x00,
1021        0xdf, 0x00,
1022        0x61, 0x38,
1023        0x62, 0x0a,
1024        0x53, 0x13,
1025        0x59, 0x08,
1026        0xff, 0xff,
1027};
1028
1029static struct stv0297_config dvbc_philips_tdm1316l_config = {
1030        .demod_address = 0x1c,
1031        .inittab = dvbc_philips_tdm1316l_inittab,
1032        .invert = 0,
1033        .stop_during_read = 1,
1034};
1035
1036static struct tda10023_config tda10023_config = {
1037        .demod_address = 0xc,
1038        .invert = 0,
1039        .xtal = 16000000,
1040        .pll_m = 11,
1041        .pll_p = 3,
1042        .pll_n = 1,
1043        .deltaf = 0xa511,
1044};
1045
1046static struct tda827x_config tda827x_config = {
1047        .config = 0,
1048};
1049
1050/* TT S2-3200 DVB-S (STB0899) Inittab */
1051static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
1052
1053        { STB0899_DEV_ID                , 0x81 },
1054        { STB0899_DISCNTRL1             , 0x32 },
1055        { STB0899_DISCNTRL2             , 0x80 },
1056        { STB0899_DISRX_ST0             , 0x04 },
1057        { STB0899_DISRX_ST1             , 0x00 },
1058        { STB0899_DISPARITY             , 0x00 },
1059        { STB0899_DISSTATUS             , 0x20 },
1060        { STB0899_DISF22                , 0x8c },
1061        { STB0899_DISF22RX              , 0x9a },
1062        { STB0899_SYSREG                , 0x0b },
1063        { STB0899_ACRPRESC              , 0x11 },
1064        { STB0899_ACRDIV1               , 0x0a },
1065        { STB0899_ACRDIV2               , 0x05 },
1066        { STB0899_DACR1                 , 0x00 },
1067        { STB0899_DACR2                 , 0x00 },
1068        { STB0899_OUTCFG                , 0x00 },
1069        { STB0899_MODECFG               , 0x00 },
1070        { STB0899_IRQSTATUS_3           , 0x30 },
1071        { STB0899_IRQSTATUS_2           , 0x00 },
1072        { STB0899_IRQSTATUS_1           , 0x00 },
1073        { STB0899_IRQSTATUS_0           , 0x00 },
1074        { STB0899_IRQMSK_3              , 0xf3 },
1075        { STB0899_IRQMSK_2              , 0xfc },
1076        { STB0899_IRQMSK_1              , 0xff },
1077        { STB0899_IRQMSK_0              , 0xff },
1078        { STB0899_IRQCFG                , 0x00 },
1079        { STB0899_I2CCFG                , 0x88 },
1080        { STB0899_I2CRPT                , 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
1081        { STB0899_IOPVALUE5             , 0x00 },
1082        { STB0899_IOPVALUE4             , 0x20 },
1083        { STB0899_IOPVALUE3             , 0xc9 },
1084        { STB0899_IOPVALUE2             , 0x90 },
1085        { STB0899_IOPVALUE1             , 0x40 },
1086        { STB0899_IOPVALUE0             , 0x00 },
1087        { STB0899_GPIO00CFG             , 0x82 },
1088        { STB0899_GPIO01CFG             , 0x82 },
1089        { STB0899_GPIO02CFG             , 0x82 },
1090        { STB0899_GPIO03CFG             , 0x82 },
1091        { STB0899_GPIO04CFG             , 0x82 },
1092        { STB0899_GPIO05CFG             , 0x82 },
1093        { STB0899_GPIO06CFG             , 0x82 },
1094        { STB0899_GPIO07CFG             , 0x82 },
1095        { STB0899_GPIO08CFG             , 0x82 },
1096        { STB0899_GPIO09CFG             , 0x82 },
1097        { STB0899_GPIO10CFG             , 0x82 },
1098        { STB0899_GPIO11CFG             , 0x82 },
1099        { STB0899_GPIO12CFG             , 0x82 },
1100        { STB0899_GPIO13CFG             , 0x82 },
1101        { STB0899_GPIO14CFG             , 0x82 },
1102        { STB0899_GPIO15CFG             , 0x82 },
1103        { STB0899_GPIO16CFG             , 0x82 },
1104        { STB0899_GPIO17CFG             , 0x82 },
1105        { STB0899_GPIO18CFG             , 0x82 },
1106        { STB0899_GPIO19CFG             , 0x82 },
1107        { STB0899_GPIO20CFG             , 0x82 },
1108        { STB0899_SDATCFG               , 0xb8 },
1109        { STB0899_SCLTCFG               , 0xba },
1110        { STB0899_AGCRFCFG              , 0x1c }, /* 0x11 */
1111        { STB0899_GPIO22                , 0x82 }, /* AGCBB2CFG */
1112        { STB0899_GPIO21                , 0x91 }, /* AGCBB1CFG */
1113        { STB0899_DIRCLKCFG             , 0x82 },
1114        { STB0899_CLKOUT27CFG           , 0x7e },
1115        { STB0899_STDBYCFG              , 0x82 },
1116        { STB0899_CS0CFG                , 0x82 },
1117        { STB0899_CS1CFG                , 0x82 },
1118        { STB0899_DISEQCOCFG            , 0x20 },
1119        { STB0899_GPIO32CFG             , 0x82 },
1120        { STB0899_GPIO33CFG             , 0x82 },
1121        { STB0899_GPIO34CFG             , 0x82 },
1122        { STB0899_GPIO35CFG             , 0x82 },
1123        { STB0899_GPIO36CFG             , 0x82 },
1124        { STB0899_GPIO37CFG             , 0x82 },
1125        { STB0899_GPIO38CFG             , 0x82 },
1126        { STB0899_GPIO39CFG             , 0x82 },
1127        { STB0899_NCOARSE               , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
1128        { STB0899_SYNTCTRL              , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
1129        { STB0899_FILTCTRL              , 0x00 },
1130        { STB0899_SYSCTRL               , 0x00 },
1131        { STB0899_STOPCLK1              , 0x20 },
1132        { STB0899_STOPCLK2              , 0x00 },
1133        { STB0899_INTBUFSTATUS          , 0x00 },
1134        { STB0899_INTBUFCTRL            , 0x0a },
1135        { 0xffff                        , 0xff },
1136};
1137
1138static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
1139        { STB0899_DEMOD                 , 0x00 },
1140        { STB0899_RCOMPC                , 0xc9 },
1141        { STB0899_AGC1CN                , 0x41 },
1142        { STB0899_AGC1REF               , 0x10 },
1143        { STB0899_RTC                   , 0x7a },
1144        { STB0899_TMGCFG                , 0x4e },
1145        { STB0899_AGC2REF               , 0x34 },
1146        { STB0899_TLSR                  , 0x84 },
1147        { STB0899_CFD                   , 0xc7 },
1148        { STB0899_ACLC                  , 0x87 },
1149        { STB0899_BCLC                  , 0x94 },
1150        { STB0899_EQON                  , 0x41 },
1151        { STB0899_LDT                   , 0xdd },
1152        { STB0899_LDT2                  , 0xc9 },
1153        { STB0899_EQUALREF              , 0xb4 },
1154        { STB0899_TMGRAMP               , 0x10 },
1155        { STB0899_TMGTHD                , 0x30 },
1156        { STB0899_IDCCOMP               , 0xfb },
1157        { STB0899_QDCCOMP               , 0x03 },
1158        { STB0899_POWERI                , 0x3b },
1159        { STB0899_POWERQ                , 0x3d },
1160        { STB0899_RCOMP                 , 0x81 },
1161        { STB0899_AGCIQIN               , 0x80 },
1162        { STB0899_AGC2I1                , 0x04 },
1163        { STB0899_AGC2I2                , 0xf5 },
1164        { STB0899_TLIR                  , 0x25 },
1165        { STB0899_RTF                   , 0x80 },
1166        { STB0899_DSTATUS               , 0x00 },
1167        { STB0899_LDI                   , 0xca },
1168        { STB0899_CFRM                  , 0xf1 },
1169        { STB0899_CFRL                  , 0xf3 },
1170        { STB0899_NIRM                  , 0x2a },
1171        { STB0899_NIRL                  , 0x05 },
1172        { STB0899_ISYMB                 , 0x17 },
1173        { STB0899_QSYMB                 , 0xfa },
1174        { STB0899_SFRH                  , 0x2f },
1175        { STB0899_SFRM                  , 0x68 },
1176        { STB0899_SFRL                  , 0x40 },
1177        { STB0899_SFRUPH                , 0x2f },
1178        { STB0899_SFRUPM                , 0x68 },
1179        { STB0899_SFRUPL                , 0x40 },
1180        { STB0899_EQUAI1                , 0xfd },
1181        { STB0899_EQUAQ1                , 0x04 },
1182        { STB0899_EQUAI2                , 0x0f },
1183        { STB0899_EQUAQ2                , 0xff },
1184        { STB0899_EQUAI3                , 0xdf },
1185        { STB0899_EQUAQ3                , 0xfa },
1186        { STB0899_EQUAI4                , 0x37 },
1187        { STB0899_EQUAQ4                , 0x0d },
1188        { STB0899_EQUAI5                , 0xbd },
1189        { STB0899_EQUAQ5                , 0xf7 },
1190        { STB0899_DSTATUS2              , 0x00 },
1191        { STB0899_VSTATUS               , 0x00 },
1192        { STB0899_VERROR                , 0xff },
1193        { STB0899_IQSWAP                , 0x2a },
1194        { STB0899_ECNT1M                , 0x00 },
1195        { STB0899_ECNT1L                , 0x00 },
1196        { STB0899_ECNT2M                , 0x00 },
1197        { STB0899_ECNT2L                , 0x00 },
1198        { STB0899_ECNT3M                , 0x00 },
1199        { STB0899_ECNT3L                , 0x00 },
1200        { STB0899_FECAUTO1              , 0x06 },
1201        { STB0899_FECM                  , 0x01 },
1202        { STB0899_VTH12                 , 0xf0 },
1203        { STB0899_VTH23                 , 0xa0 },
1204        { STB0899_VTH34                 , 0x78 },
1205        { STB0899_VTH56                 , 0x4e },
1206        { STB0899_VTH67                 , 0x48 },
1207        { STB0899_VTH78                 , 0x38 },
1208        { STB0899_PRVIT                 , 0xff },
1209        { STB0899_VITSYNC               , 0x19 },
1210        { STB0899_RSULC                 , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
1211        { STB0899_TSULC                 , 0x42 },
1212        { STB0899_RSLLC                 , 0x40 },
1213        { STB0899_TSLPL                 , 0x12 },
1214        { STB0899_TSCFGH                , 0x0c },
1215        { STB0899_TSCFGM                , 0x00 },
1216        { STB0899_TSCFGL                , 0x0c },
1217        { STB0899_TSOUT                 , 0x4d }, /* 0x0d for CAM */
1218        { STB0899_RSSYNCDEL             , 0x00 },
1219        { STB0899_TSINHDELH             , 0x02 },
1220        { STB0899_TSINHDELM             , 0x00 },
1221        { STB0899_TSINHDELL             , 0x00 },
1222        { STB0899_TSLLSTKM              , 0x00 },
1223        { STB0899_TSLLSTKL              , 0x00 },
1224        { STB0899_TSULSTKM              , 0x00 },
1225        { STB0899_TSULSTKL              , 0xab },
1226        { STB0899_PCKLENUL              , 0x00 },
1227        { STB0899_PCKLENLL              , 0xcc },
1228        { STB0899_RSPCKLEN              , 0xcc },
1229        { STB0899_TSSTATUS              , 0x80 },
1230        { STB0899_ERRCTRL1              , 0xb6 },
1231        { STB0899_ERRCTRL2              , 0x96 },
1232        { STB0899_ERRCTRL3              , 0x89 },
1233        { STB0899_DMONMSK1              , 0x27 },
1234        { STB0899_DMONMSK0              , 0x03 },
1235        { STB0899_DEMAPVIT              , 0x5c },
1236        { STB0899_PLPARM                , 0x1f },
1237        { STB0899_PDELCTRL              , 0x48 },
1238        { STB0899_PDELCTRL2             , 0x00 },
1239        { STB0899_BBHCTRL1              , 0x00 },
1240        { STB0899_BBHCTRL2              , 0x00 },
1241        { STB0899_HYSTTHRESH            , 0x77 },
1242        { STB0899_MATCSTM               , 0x00 },
1243        { STB0899_MATCSTL               , 0x00 },
1244        { STB0899_UPLCSTM               , 0x00 },
1245        { STB0899_UPLCSTL               , 0x00 },
1246        { STB0899_DFLCSTM               , 0x00 },
1247        { STB0899_DFLCSTL               , 0x00 },
1248        { STB0899_SYNCCST               , 0x00 },
1249        { STB0899_SYNCDCSTM             , 0x00 },
1250        { STB0899_SYNCDCSTL             , 0x00 },
1251        { STB0899_ISI_ENTRY             , 0x00 },
1252        { STB0899_ISI_BIT_EN            , 0x00 },
1253        { STB0899_MATSTRM               , 0x00 },
1254        { STB0899_MATSTRL               , 0x00 },
1255        { STB0899_UPLSTRM               , 0x00 },
1256        { STB0899_UPLSTRL               , 0x00 },
1257        { STB0899_DFLSTRM               , 0x00 },
1258        { STB0899_DFLSTRL               , 0x00 },
1259        { STB0899_SYNCSTR               , 0x00 },
1260        { STB0899_SYNCDSTRM             , 0x00 },
1261        { STB0899_SYNCDSTRL             , 0x00 },
1262        { STB0899_CFGPDELSTATUS1        , 0x10 },
1263        { STB0899_CFGPDELSTATUS2        , 0x00 },
1264        { STB0899_BBFERRORM             , 0x00 },
1265        { STB0899_BBFERRORL             , 0x00 },
1266        { STB0899_UPKTERRORM            , 0x00 },
1267        { STB0899_UPKTERRORL            , 0x00 },
1268        { 0xffff                        , 0xff },
1269};
1270
1271static struct stb0899_config tt3200_config = {
1272        .init_dev               = tt3200_stb0899_s1_init_1,
1273        .init_s2_demod          = stb0899_s2_init_2,
1274        .init_s1_demod          = tt3200_stb0899_s1_init_3,
1275        .init_s2_fec            = stb0899_s2_init_4,
1276        .init_tst               = stb0899_s1_init_5,
1277
1278        .postproc               = NULL,
1279
1280        .demod_address          = 0x68,
1281
1282        .xtal_freq              = 27000000,
1283        .inversion              = IQ_SWAP_ON,
1284
1285        .lo_clk                 = 76500000,
1286        .hi_clk                 = 99000000,
1287
1288        .esno_ave               = STB0899_DVBS2_ESNO_AVE,
1289        .esno_quant             = STB0899_DVBS2_ESNO_QUANT,
1290        .avframes_coarse        = STB0899_DVBS2_AVFRAMES_COARSE,
1291        .avframes_fine          = STB0899_DVBS2_AVFRAMES_FINE,
1292        .miss_threshold         = STB0899_DVBS2_MISS_THRESHOLD,
1293        .uwp_threshold_acq      = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
1294        .uwp_threshold_track    = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
1295        .uwp_threshold_sof      = STB0899_DVBS2_UWP_THRESHOLD_SOF,
1296        .sof_search_timeout     = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
1297
1298        .btr_nco_bits           = STB0899_DVBS2_BTR_NCO_BITS,
1299        .btr_gain_shift_offset  = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
1300        .crl_nco_bits           = STB0899_DVBS2_CRL_NCO_BITS,
1301        .ldpc_max_iter          = STB0899_DVBS2_LDPC_MAX_ITER,
1302
1303        .tuner_get_frequency    = stb6100_get_frequency,
1304        .tuner_set_frequency    = stb6100_set_frequency,
1305        .tuner_set_bandwidth    = stb6100_set_bandwidth,
1306        .tuner_get_bandwidth    = stb6100_get_bandwidth,
1307        .tuner_set_rfsiggain    = NULL
1308};
1309
1310static struct stb6100_config tt3200_stb6100_config = {
1311        .tuner_address  = 0x60,
1312        .refclock       = 27000000,
1313};
1314
1315static void frontend_init(struct budget_ci *budget_ci)
1316{
1317        switch (budget_ci->budget.dev->pci->subsystem_device) {
1318        case 0x100c:            // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
1319                budget_ci->budget.dvb_frontend =
1320                        dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
1321                if (budget_ci->budget.dvb_frontend) {
1322                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
1323                        budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
1324                        break;
1325                }
1326                break;
1327
1328        case 0x100f:            // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
1329                budget_ci->budget.dvb_frontend =
1330                        dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
1331                if (budget_ci->budget.dvb_frontend) {
1332                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
1333                        break;
1334                }
1335                break;
1336
1337        case 0x1010:            // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
1338                budget_ci->tuner_pll_address = 0x61;
1339                budget_ci->budget.dvb_frontend =
1340                        dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
1341                if (budget_ci->budget.dvb_frontend) {
1342                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
1343                        break;
1344                }
1345                break;
1346
1347        case 0x1011:            // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
1348                budget_ci->tuner_pll_address = 0x63;
1349                budget_ci->budget.dvb_frontend =
1350                        dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
1351                if (budget_ci->budget.dvb_frontend) {
1352                        budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1353                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
1354                        break;
1355                }
1356                break;
1357
1358        case 0x1012:            // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
1359                budget_ci->tuner_pll_address = 0x60;
1360                budget_ci->budget.dvb_frontend =
1361                        dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
1362                if (budget_ci->budget.dvb_frontend) {
1363                        budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1364                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
1365                        break;
1366                }
1367                break;
1368
1369        case 0x1017:            // TT S-1500 PCI
1370                budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
1371                if (budget_ci->budget.dvb_frontend) {
1372                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
1373                        budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
1374
1375                        budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
1376                        if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
1377                                printk("%s: No LNBP21 found!\n", __func__);
1378                                dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1379                                budget_ci->budget.dvb_frontend = NULL;
1380                        }
1381                }
1382                break;
1383
1384        case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
1385                budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
1386                if (budget_ci->budget.dvb_frontend) {
1387                        if (dvb_attach(tda827x_attach, budget_ci->budget.dvb_frontend, 0x61, &budget_ci->budget.i2c_adap, &tda827x_config) == NULL) {
1388                                printk(KERN_ERR "%s: No tda827x found!\n", __func__);
1389                                dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1390                                budget_ci->budget.dvb_frontend = NULL;
1391                        }
1392                }
1393                break;
1394
1395        case 0x101b: /* TT S-1500B (BSBE1-D01A - STV0288/STB6000/LNBP21) */
1396                budget_ci->budget.dvb_frontend = dvb_attach(stv0288_attach, &stv0288_bsbe1_d01a_config, &budget_ci->budget.i2c_adap);
1397                if (budget_ci->budget.dvb_frontend) {
1398                        if (dvb_attach(stb6000_attach, budget_ci->budget.dvb_frontend, 0x63, &budget_ci->budget.i2c_adap)) {
1399                                if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
1400                                        printk(KERN_ERR "%s: No LNBP21 found!\n", __func__);
1401                                        dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1402                                        budget_ci->budget.dvb_frontend = NULL;
1403                                }
1404                        } else {
1405                                printk(KERN_ERR "%s: No STB6000 found!\n", __func__);
1406                                dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1407                                budget_ci->budget.dvb_frontend = NULL;
1408                        }
1409                }
1410                break;
1411
1412        case 0x1019:            // TT S2-3200 PCI
1413                /*
1414                 * NOTE! on some STB0899 versions, the internal PLL takes a longer time
1415                 * to settle, aka LOCK. On the older revisions of the chip, we don't see
1416                 * this, as a result on the newer chips the entire clock tree, will not
1417                 * be stable after a freshly POWER 'ed up situation.
1418                 * In this case, we should RESET the STB0899 (Active LOW) and wait for
1419                 * PLL stabilization.
1420                 *
1421                 * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
1422                 * connected to the SAA7146 GPIO, GPIO2, Pin 142
1423                 */
1424                /* Reset Demodulator */
1425                saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
1426                /* Wait for everything to die */
1427                msleep(50);
1428                /* Pull it up out of Reset state */
1429                saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
1430                /* Wait for PLL to stabilize */
1431                msleep(250);
1432                /*
1433                 * PLL state should be stable now. Ideally, we should check
1434                 * for PLL LOCK status. But well, never mind!
1435                 */
1436                budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
1437                if (budget_ci->budget.dvb_frontend) {
1438                        if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
1439                                if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
1440                                        printk("%s: No LNBP21 found!\n", __func__);
1441                                        dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1442                                        budget_ci->budget.dvb_frontend = NULL;
1443                                }
1444                        } else {
1445                                        dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1446                                        budget_ci->budget.dvb_frontend = NULL;
1447                        }
1448                }
1449                break;
1450
1451        }
1452
1453        if (budget_ci->budget.dvb_frontend == NULL) {
1454                printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
1455                       budget_ci->budget.dev->pci->vendor,
1456                       budget_ci->budget.dev->pci->device,
1457                       budget_ci->budget.dev->pci->subsystem_vendor,
1458                       budget_ci->budget.dev->pci->subsystem_device);
1459        } else {
1460                if (dvb_register_frontend
1461                    (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
1462                        printk("budget-ci: Frontend registration failed!\n");
1463                        dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1464                        budget_ci->budget.dvb_frontend = NULL;
1465                }
1466        }
1467}
1468
1469static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1470{
1471        struct budget_ci *budget_ci;
1472        int err;
1473
1474        budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
1475        if (!budget_ci) {
1476                err = -ENOMEM;
1477                goto out1;
1478        }
1479
1480        dprintk(2, "budget_ci: %p\n", budget_ci);
1481
1482        dev->ext_priv = budget_ci;
1483
1484        err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
1485                                adapter_nr);
1486        if (err)
1487                goto out2;
1488
1489        err = msp430_ir_init(budget_ci);
1490        if (err)
1491                goto out3;
1492
1493        ciintf_init(budget_ci);
1494
1495        budget_ci->budget.dvb_adapter.priv = budget_ci;
1496        frontend_init(budget_ci);
1497
1498        ttpci_budget_init_hooks(&budget_ci->budget);
1499
1500        return 0;
1501
1502out3:
1503        ttpci_budget_deinit(&budget_ci->budget);
1504out2:
1505        kfree(budget_ci);
1506out1:
1507        return err;
1508}
1509
1510static int budget_ci_detach(struct saa7146_dev *dev)
1511{
1512        struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
1513        struct saa7146_dev *saa = budget_ci->budget.dev;
1514        int err;
1515
1516        if (budget_ci->budget.ci_present)
1517                ciintf_deinit(budget_ci);
1518        msp430_ir_deinit(budget_ci);
1519        if (budget_ci->budget.dvb_frontend) {
1520                dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
1521                dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1522        }
1523        err = ttpci_budget_deinit(&budget_ci->budget);
1524
1525        // disable frontend and CI interface
1526        saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
1527
1528        kfree(budget_ci);
1529
1530        return err;
1531}
1532
1533static struct saa7146_extension budget_extension;
1534
1535MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
1536MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
1537MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T  PCI", BUDGET_TT);
1538MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
1539MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
1540MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
1541MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
1542MAKE_BUDGET_INFO(ttbs1500b, "TT-Budget S-1500B PCI", BUDGET_TT);
1543
1544static struct pci_device_id pci_tbl[] = {
1545        MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
1546        MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
1547        MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
1548        MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
1549        MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
1550        MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
1551        MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
1552        MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
1553        MAKE_EXTENSION_PCI(ttbs1500b, 0x13c2, 0x101b),
1554        {
1555         .vendor = 0,
1556         }
1557};
1558
1559MODULE_DEVICE_TABLE(pci, pci_tbl);
1560
1561static struct saa7146_extension budget_extension = {
1562        .name = "budget_ci dvb",
1563        .flags = SAA7146_USE_I2C_IRQ,
1564
1565        .module = THIS_MODULE,
1566        .pci_tbl = &pci_tbl[0],
1567        .attach = budget_ci_attach,
1568        .detach = budget_ci_detach,
1569
1570        .irq_mask = MASK_03 | MASK_06 | MASK_10,
1571        .irq_func = budget_ci_irq,
1572};
1573
1574static int __init budget_ci_init(void)
1575{
1576        return saa7146_register_extension(&budget_extension);
1577}
1578
1579static void __exit budget_ci_exit(void)
1580{
1581        saa7146_unregister_extension(&budget_extension);
1582}
1583
1584module_init(budget_ci_init);
1585module_exit(budget_ci_exit);
1586
1587MODULE_LICENSE("GPL");
1588MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
1589MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1590                   "budget PCI DVB cards w/ CI-module produced by "
1591                   "Siemens, Technotrend, Hauppauge");
1592