Path: blob/master/drivers/media/dvb/ttpci/budget-ci.c
15112 views
/*1* budget-ci.c: driver for the SAA7146 based Budget DVB cards2*3* Compiled from various sources by Michael Hunold <[email protected]>4*5* msp430 IR support contributed by Jack Thomasson <[email protected]>6* partially based on the Siemens DVB driver by Ralph+Marcus Metzler7*8* CI interface support (c) 2004 Andrew de Quincey <[email protected]>9*10* This program is free software; you can redistribute it and/or11* modify it under the terms of the GNU General Public License12* as published by the Free Software Foundation; either version 213* of the License, or (at your option) any later version.14*15*16* This program is distributed in the hope that it will be useful,17* but WITHOUT ANY WARRANTY; without even the implied warranty of18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the19* GNU General Public License for more details.20*21*22* You should have received a copy of the GNU General Public License23* along with this program; if not, write to the Free Software24* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.25* Or, point your browser to http://www.gnu.org/copyleft/gpl.html26*27*28* the project's page is at http://www.linuxtv.org/29*/3031#include <linux/module.h>32#include <linux/errno.h>33#include <linux/slab.h>34#include <linux/interrupt.h>35#include <linux/spinlock.h>36#include <media/rc-core.h>3738#include "budget.h"3940#include "dvb_ca_en50221.h"41#include "stv0299.h"42#include "stv0297.h"43#include "tda1004x.h"44#include "stb0899_drv.h"45#include "stb0899_reg.h"46#include "stb0899_cfg.h"47#include "stb6100.h"48#include "stb6100_cfg.h"49#include "lnbp21.h"50#include "bsbe1.h"51#include "bsru6.h"52#include "tda1002x.h"53#include "tda827x.h"54#include "bsbe1-d01a.h"5556#define MODULE_NAME "budget_ci"5758/*59* Regarding DEBIADDR_IR:60* Some CI modules hang if random addresses are read.61* Using address 0x4000 for the IR read means that we62* use the same address as for CI version, which should63* be a safe default.64*/65#define DEBIADDR_IR 0x400066#define DEBIADDR_CICONTROL 0x000067#define DEBIADDR_CIVERSION 0x400068#define DEBIADDR_IO 0x100069#define DEBIADDR_ATTR 0x30007071#define CICONTROL_RESET 0x0172#define CICONTROL_ENABLETS 0x0273#define CICONTROL_CAMDETECT 0x087475#define DEBICICTL 0x0042000076#define DEBICICAM 0x024200007778#define SLOTSTATUS_NONE 179#define SLOTSTATUS_PRESENT 280#define SLOTSTATUS_RESET 481#define SLOTSTATUS_READY 882#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)8384/* RC5 device wildcard */85#define IR_DEVICE_ANY 2558687static int rc5_device = -1;88module_param(rc5_device, int, 0644);89MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");9091static int ir_debug;92module_param(ir_debug, int, 0644);93MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");9495DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);9697struct budget_ci_ir {98struct rc_dev *dev;99struct tasklet_struct msp430_irq_tasklet;100char name[72]; /* 40 + 32 for (struct saa7146_dev).name */101char phys[32];102int rc5_device;103u32 ir_key;104bool have_command;105bool full_rc5; /* Outputs a full RC5 code */106};107108struct budget_ci {109struct budget budget;110struct tasklet_struct ciintf_irq_tasklet;111int slot_status;112int ci_irq;113struct dvb_ca_en50221 ca;114struct budget_ci_ir ir;115u8 tuner_pll_address; /* used for philips_tdm1316l configs */116};117118static void msp430_ir_interrupt(unsigned long data)119{120struct budget_ci *budget_ci = (struct budget_ci *) data;121struct rc_dev *dev = budget_ci->ir.dev;122u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;123124/*125* The msp430 chip can generate two different bytes, command and device126*127* type1: X1CCCCCC, C = command bits (0 - 63)128* type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit129*130* Each signal from the remote control can generate one or more command131* bytes and one or more device bytes. For the repeated bytes, the132* highest bit (X) is set. The first command byte is always generated133* before the first device byte. Other than that, no specific order134* seems to apply. To make life interesting, bytes can also be lost.135*136* Only when we have a command and device byte, a keypress is137* generated.138*/139140if (ir_debug)141printk("budget_ci: received byte 0x%02x\n", command);142143/* Remove repeat bit, we use every command */144command = command & 0x7f;145146/* Is this a RC5 command byte? */147if (command & 0x40) {148budget_ci->ir.have_command = true;149budget_ci->ir.ir_key = command & 0x3f;150return;151}152153/* It's a RC5 device byte */154if (!budget_ci->ir.have_command)155return;156budget_ci->ir.have_command = false;157158if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&159budget_ci->ir.rc5_device != (command & 0x1f))160return;161162if (budget_ci->ir.full_rc5) {163rc_keydown(dev,164budget_ci->ir.rc5_device <<8 | budget_ci->ir.ir_key,165(command & 0x20) ? 1 : 0);166return;167}168169/* FIXME: We should generate complete scancodes for all devices */170rc_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0);171}172173static int msp430_ir_init(struct budget_ci *budget_ci)174{175struct saa7146_dev *saa = budget_ci->budget.dev;176struct rc_dev *dev;177int error;178179dev = rc_allocate_device();180if (!dev) {181printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");182return -ENOMEM;183}184185snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),186"Budget-CI dvb ir receiver %s", saa->name);187snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),188"pci-%s/ir0", pci_name(saa->pci));189190dev->driver_name = MODULE_NAME;191dev->input_name = budget_ci->ir.name;192dev->input_phys = budget_ci->ir.phys;193dev->input_id.bustype = BUS_PCI;194dev->input_id.version = 1;195dev->scanmask = 0xff;196if (saa->pci->subsystem_vendor) {197dev->input_id.vendor = saa->pci->subsystem_vendor;198dev->input_id.product = saa->pci->subsystem_device;199} else {200dev->input_id.vendor = saa->pci->vendor;201dev->input_id.product = saa->pci->device;202}203dev->dev.parent = &saa->pci->dev;204205if (rc5_device < 0)206budget_ci->ir.rc5_device = IR_DEVICE_ANY;207else208budget_ci->ir.rc5_device = rc5_device;209210/* Select keymap and address */211switch (budget_ci->budget.dev->pci->subsystem_device) {212case 0x100c:213case 0x100f:214case 0x1011:215case 0x1012:216/* The hauppauge keymap is a superset of these remotes */217dev->map_name = RC_MAP_HAUPPAUGE;218budget_ci->ir.full_rc5 = true;219220if (rc5_device < 0)221budget_ci->ir.rc5_device = 0x1f;222break;223case 0x1010:224case 0x1017:225case 0x1019:226case 0x101a:227case 0x101b:228/* for the Technotrend 1500 bundled remote */229dev->map_name = RC_MAP_TT_1500;230break;231default:232/* unknown remote */233dev->map_name = RC_MAP_BUDGET_CI_OLD;234break;235}236237error = rc_register_device(dev);238if (error) {239printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);240rc_free_device(dev);241return error;242}243244budget_ci->ir.dev = dev;245246tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,247(unsigned long) budget_ci);248249SAA7146_IER_ENABLE(saa, MASK_06);250saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);251252return 0;253}254255static void msp430_ir_deinit(struct budget_ci *budget_ci)256{257struct saa7146_dev *saa = budget_ci->budget.dev;258259SAA7146_IER_DISABLE(saa, MASK_06);260saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);261tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);262263rc_unregister_device(budget_ci->ir.dev);264}265266static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)267{268struct budget_ci *budget_ci = (struct budget_ci *) ca->data;269270if (slot != 0)271return -EINVAL;272273return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,274DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);275}276277static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)278{279struct budget_ci *budget_ci = (struct budget_ci *) ca->data;280281if (slot != 0)282return -EINVAL;283284return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,285DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);286}287288static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)289{290struct budget_ci *budget_ci = (struct budget_ci *) ca->data;291292if (slot != 0)293return -EINVAL;294295return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,296DEBIADDR_IO | (address & 3), 1, 1, 0);297}298299static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)300{301struct budget_ci *budget_ci = (struct budget_ci *) ca->data;302303if (slot != 0)304return -EINVAL;305306return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,307DEBIADDR_IO | (address & 3), 1, value, 1, 0);308}309310static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)311{312struct budget_ci *budget_ci = (struct budget_ci *) ca->data;313struct saa7146_dev *saa = budget_ci->budget.dev;314315if (slot != 0)316return -EINVAL;317318if (budget_ci->ci_irq) {319// trigger on RISING edge during reset so we know when READY is re-asserted320saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);321}322budget_ci->slot_status = SLOTSTATUS_RESET;323ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);324msleep(1);325ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,326CICONTROL_RESET, 1, 0);327328saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);329ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);330return 0;331}332333static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)334{335struct budget_ci *budget_ci = (struct budget_ci *) ca->data;336struct saa7146_dev *saa = budget_ci->budget.dev;337338if (slot != 0)339return -EINVAL;340341saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);342ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);343return 0;344}345346static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)347{348struct budget_ci *budget_ci = (struct budget_ci *) ca->data;349struct saa7146_dev *saa = budget_ci->budget.dev;350int tmp;351352if (slot != 0)353return -EINVAL;354355saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);356357tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);358ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,359tmp | CICONTROL_ENABLETS, 1, 0);360361ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);362return 0;363}364365static void ciintf_interrupt(unsigned long data)366{367struct budget_ci *budget_ci = (struct budget_ci *) data;368struct saa7146_dev *saa = budget_ci->budget.dev;369unsigned int flags;370371// ensure we don't get spurious IRQs during initialisation372if (!budget_ci->budget.ci_present)373return;374375// read the CAM status376flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);377if (flags & CICONTROL_CAMDETECT) {378379// GPIO should be set to trigger on falling edge if a CAM is present380saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);381382if (budget_ci->slot_status & SLOTSTATUS_NONE) {383// CAM insertion IRQ384budget_ci->slot_status = SLOTSTATUS_PRESENT;385dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,386DVB_CA_EN50221_CAMCHANGE_INSERTED);387388} else if (budget_ci->slot_status & SLOTSTATUS_RESET) {389// CAM ready (reset completed)390budget_ci->slot_status = SLOTSTATUS_READY;391dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);392393} else if (budget_ci->slot_status & SLOTSTATUS_READY) {394// FR/DA IRQ395dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);396}397} else {398399// trigger on rising edge if a CAM is not present - when a CAM is inserted, we400// only want to get the IRQ when it sets READY. If we trigger on the falling edge,401// the CAM might not actually be ready yet.402saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);403404// generate a CAM removal IRQ if we haven't already405if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {406// CAM removal IRQ407budget_ci->slot_status = SLOTSTATUS_NONE;408dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,409DVB_CA_EN50221_CAMCHANGE_REMOVED);410}411}412}413414static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)415{416struct budget_ci *budget_ci = (struct budget_ci *) ca->data;417unsigned int flags;418419// ensure we don't get spurious IRQs during initialisation420if (!budget_ci->budget.ci_present)421return -EINVAL;422423// read the CAM status424flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);425if (flags & CICONTROL_CAMDETECT) {426// mark it as present if it wasn't before427if (budget_ci->slot_status & SLOTSTATUS_NONE) {428budget_ci->slot_status = SLOTSTATUS_PRESENT;429}430431// during a RESET, we check if we can read from IO memory to see when CAM is ready432if (budget_ci->slot_status & SLOTSTATUS_RESET) {433if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {434budget_ci->slot_status = SLOTSTATUS_READY;435}436}437} else {438budget_ci->slot_status = SLOTSTATUS_NONE;439}440441if (budget_ci->slot_status != SLOTSTATUS_NONE) {442if (budget_ci->slot_status & SLOTSTATUS_READY) {443return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;444}445return DVB_CA_EN50221_POLL_CAM_PRESENT;446}447448return 0;449}450451static int ciintf_init(struct budget_ci *budget_ci)452{453struct saa7146_dev *saa = budget_ci->budget.dev;454int flags;455int result;456int ci_version;457int ca_flags;458459memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));460461// enable DEBI pins462saa7146_write(saa, MC1, MASK_27 | MASK_11);463464// test if it is there465ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);466if ((ci_version & 0xa0) != 0xa0) {467result = -ENODEV;468goto error;469}470471// determine whether a CAM is present or not472flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);473budget_ci->slot_status = SLOTSTATUS_NONE;474if (flags & CICONTROL_CAMDETECT)475budget_ci->slot_status = SLOTSTATUS_PRESENT;476477// version 0xa2 of the CI firmware doesn't generate interrupts478if (ci_version == 0xa2) {479ca_flags = 0;480budget_ci->ci_irq = 0;481} else {482ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |483DVB_CA_EN50221_FLAG_IRQ_FR |484DVB_CA_EN50221_FLAG_IRQ_DA;485budget_ci->ci_irq = 1;486}487488// register CI interface489budget_ci->ca.owner = THIS_MODULE;490budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;491budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;492budget_ci->ca.read_cam_control = ciintf_read_cam_control;493budget_ci->ca.write_cam_control = ciintf_write_cam_control;494budget_ci->ca.slot_reset = ciintf_slot_reset;495budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;496budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;497budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;498budget_ci->ca.data = budget_ci;499if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,500&budget_ci->ca,501ca_flags, 1)) != 0) {502printk("budget_ci: CI interface detected, but initialisation failed.\n");503goto error;504}505506// Setup CI slot IRQ507if (budget_ci->ci_irq) {508tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);509if (budget_ci->slot_status != SLOTSTATUS_NONE) {510saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);511} else {512saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);513}514SAA7146_IER_ENABLE(saa, MASK_03);515}516517// enable interface518ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,519CICONTROL_RESET, 1, 0);520521// success!522printk("budget_ci: CI interface initialised\n");523budget_ci->budget.ci_present = 1;524525// forge a fake CI IRQ so the CAM state is setup correctly526if (budget_ci->ci_irq) {527flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;528if (budget_ci->slot_status != SLOTSTATUS_NONE)529flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;530dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);531}532533return 0;534535error:536saa7146_write(saa, MC1, MASK_27);537return result;538}539540static void ciintf_deinit(struct budget_ci *budget_ci)541{542struct saa7146_dev *saa = budget_ci->budget.dev;543544// disable CI interrupts545if (budget_ci->ci_irq) {546SAA7146_IER_DISABLE(saa, MASK_03);547saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);548tasklet_kill(&budget_ci->ciintf_irq_tasklet);549}550551// reset interface552ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);553msleep(1);554ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,555CICONTROL_RESET, 1, 0);556557// disable TS data stream to CI interface558saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);559560// release the CA device561dvb_ca_en50221_release(&budget_ci->ca);562563// disable DEBI pins564saa7146_write(saa, MC1, MASK_27);565}566567static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)568{569struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;570571dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);572573if (*isr & MASK_06)574tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);575576if (*isr & MASK_10)577ttpci_budget_irq10_handler(dev, isr);578579if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))580tasklet_schedule(&budget_ci->ciintf_irq_tasklet);581}582583static u8 philips_su1278_tt_inittab[] = {5840x01, 0x0f,5850x02, 0x30,5860x03, 0x00,5870x04, 0x5b,5880x05, 0x85,5890x06, 0x02,5900x07, 0x00,5910x08, 0x02,5920x09, 0x00,5930x0C, 0x01,5940x0D, 0x81,5950x0E, 0x44,5960x0f, 0x14,5970x10, 0x3c,5980x11, 0x84,5990x12, 0xda,6000x13, 0x97,6010x14, 0x95,6020x15, 0xc9,6030x16, 0x19,6040x17, 0x8c,6050x18, 0x59,6060x19, 0xf8,6070x1a, 0xfe,6080x1c, 0x7f,6090x1d, 0x00,6100x1e, 0x00,6110x1f, 0x50,6120x20, 0x00,6130x21, 0x00,6140x22, 0x00,6150x23, 0x00,6160x28, 0x00,6170x29, 0x28,6180x2a, 0x14,6190x2b, 0x0f,6200x2c, 0x09,6210x2d, 0x09,6220x31, 0x1f,6230x32, 0x19,6240x33, 0xfc,6250x34, 0x93,6260xff, 0xff627};628629static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)630{631stv0299_writereg(fe, 0x0e, 0x44);632if (srate >= 10000000) {633stv0299_writereg(fe, 0x13, 0x97);634stv0299_writereg(fe, 0x14, 0x95);635stv0299_writereg(fe, 0x15, 0xc9);636stv0299_writereg(fe, 0x17, 0x8c);637stv0299_writereg(fe, 0x1a, 0xfe);638stv0299_writereg(fe, 0x1c, 0x7f);639stv0299_writereg(fe, 0x2d, 0x09);640} else {641stv0299_writereg(fe, 0x13, 0x99);642stv0299_writereg(fe, 0x14, 0x8d);643stv0299_writereg(fe, 0x15, 0xce);644stv0299_writereg(fe, 0x17, 0x43);645stv0299_writereg(fe, 0x1a, 0x1d);646stv0299_writereg(fe, 0x1c, 0x12);647stv0299_writereg(fe, 0x2d, 0x05);648}649stv0299_writereg(fe, 0x0e, 0x23);650stv0299_writereg(fe, 0x0f, 0x94);651stv0299_writereg(fe, 0x10, 0x39);652stv0299_writereg(fe, 0x15, 0xc9);653654stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);655stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);656stv0299_writereg(fe, 0x21, (ratio) & 0xf0);657658return 0;659}660661static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,662struct dvb_frontend_parameters *params)663{664struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;665u32 div;666u8 buf[4];667struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };668669if ((params->frequency < 950000) || (params->frequency > 2150000))670return -EINVAL;671672div = (params->frequency + (500 - 1)) / 500; // round correctly673buf[0] = (div >> 8) & 0x7f;674buf[1] = div & 0xff;675buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;676buf[3] = 0x20;677678if (params->u.qpsk.symbol_rate < 4000000)679buf[3] |= 1;680681if (params->frequency < 1250000)682buf[3] |= 0;683else if (params->frequency < 1550000)684buf[3] |= 0x40;685else if (params->frequency < 2050000)686buf[3] |= 0x80;687else if (params->frequency < 2150000)688buf[3] |= 0xC0;689690if (fe->ops.i2c_gate_ctrl)691fe->ops.i2c_gate_ctrl(fe, 1);692if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)693return -EIO;694return 0;695}696697static struct stv0299_config philips_su1278_tt_config = {698699.demod_address = 0x68,700.inittab = philips_su1278_tt_inittab,701.mclk = 64000000UL,702.invert = 0,703.skip_reinit = 1,704.lock_output = STV0299_LOCKOUTPUT_1,705.volt13_op0_op1 = STV0299_VOLT13_OP1,706.min_delay_ms = 50,707.set_symbol_rate = philips_su1278_tt_set_symbol_rate,708};709710711712static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)713{714struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;715static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };716static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };717struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =718sizeof(td1316_init) };719720// setup PLL configuration721if (fe->ops.i2c_gate_ctrl)722fe->ops.i2c_gate_ctrl(fe, 1);723if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)724return -EIO;725msleep(1);726727// disable the mc44BC374c (do not check for errors)728tuner_msg.addr = 0x65;729tuner_msg.buf = disable_mc44BC374c;730tuner_msg.len = sizeof(disable_mc44BC374c);731if (fe->ops.i2c_gate_ctrl)732fe->ops.i2c_gate_ctrl(fe, 1);733if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {734if (fe->ops.i2c_gate_ctrl)735fe->ops.i2c_gate_ctrl(fe, 1);736i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);737}738739return 0;740}741742static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)743{744struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;745u8 tuner_buf[4];746struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) };747int tuner_frequency = 0;748u8 band, cp, filter;749750// determine charge pump751tuner_frequency = params->frequency + 36130000;752if (tuner_frequency < 87000000)753return -EINVAL;754else if (tuner_frequency < 130000000)755cp = 3;756else if (tuner_frequency < 160000000)757cp = 5;758else if (tuner_frequency < 200000000)759cp = 6;760else if (tuner_frequency < 290000000)761cp = 3;762else if (tuner_frequency < 420000000)763cp = 5;764else if (tuner_frequency < 480000000)765cp = 6;766else if (tuner_frequency < 620000000)767cp = 3;768else if (tuner_frequency < 830000000)769cp = 5;770else if (tuner_frequency < 895000000)771cp = 7;772else773return -EINVAL;774775// determine band776if (params->frequency < 49000000)777return -EINVAL;778else if (params->frequency < 159000000)779band = 1;780else if (params->frequency < 444000000)781band = 2;782else if (params->frequency < 861000000)783band = 4;784else785return -EINVAL;786787// setup PLL filter and TDA9889788switch (params->u.ofdm.bandwidth) {789case BANDWIDTH_6_MHZ:790tda1004x_writereg(fe, 0x0C, 0x14);791filter = 0;792break;793794case BANDWIDTH_7_MHZ:795tda1004x_writereg(fe, 0x0C, 0x80);796filter = 0;797break;798799case BANDWIDTH_8_MHZ:800tda1004x_writereg(fe, 0x0C, 0x14);801filter = 1;802break;803804default:805return -EINVAL;806}807808// calculate divisor809// ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)810tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;811812// setup tuner buffer813tuner_buf[0] = tuner_frequency >> 8;814tuner_buf[1] = tuner_frequency & 0xff;815tuner_buf[2] = 0xca;816tuner_buf[3] = (cp << 5) | (filter << 3) | band;817818if (fe->ops.i2c_gate_ctrl)819fe->ops.i2c_gate_ctrl(fe, 1);820if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)821return -EIO;822823msleep(1);824return 0;825}826827static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,828const struct firmware **fw, char *name)829{830struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;831832return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);833}834835static struct tda1004x_config philips_tdm1316l_config = {836837.demod_address = 0x8,838.invert = 0,839.invert_oclk = 0,840.xtal_freq = TDA10046_XTAL_4M,841.agc_config = TDA10046_AGC_DEFAULT,842.if_freq = TDA10046_FREQ_3617,843.request_firmware = philips_tdm1316l_request_firmware,844};845846static struct tda1004x_config philips_tdm1316l_config_invert = {847848.demod_address = 0x8,849.invert = 1,850.invert_oclk = 0,851.xtal_freq = TDA10046_XTAL_4M,852.agc_config = TDA10046_AGC_DEFAULT,853.if_freq = TDA10046_FREQ_3617,854.request_firmware = philips_tdm1316l_request_firmware,855};856857static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)858{859struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;860u8 tuner_buf[5];861struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,862.flags = 0,863.buf = tuner_buf,864.len = sizeof(tuner_buf) };865int tuner_frequency = 0;866u8 band, cp, filter;867868// determine charge pump869tuner_frequency = params->frequency + 36125000;870if (tuner_frequency < 87000000)871return -EINVAL;872else if (tuner_frequency < 130000000) {873cp = 3;874band = 1;875} else if (tuner_frequency < 160000000) {876cp = 5;877band = 1;878} else if (tuner_frequency < 200000000) {879cp = 6;880band = 1;881} else if (tuner_frequency < 290000000) {882cp = 3;883band = 2;884} else if (tuner_frequency < 420000000) {885cp = 5;886band = 2;887} else if (tuner_frequency < 480000000) {888cp = 6;889band = 2;890} else if (tuner_frequency < 620000000) {891cp = 3;892band = 4;893} else if (tuner_frequency < 830000000) {894cp = 5;895band = 4;896} else if (tuner_frequency < 895000000) {897cp = 7;898band = 4;899} else900return -EINVAL;901902// assume PLL filter should always be 8MHz for the moment.903filter = 1;904905// calculate divisor906tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;907908// setup tuner buffer909tuner_buf[0] = tuner_frequency >> 8;910tuner_buf[1] = tuner_frequency & 0xff;911tuner_buf[2] = 0xc8;912tuner_buf[3] = (cp << 5) | (filter << 3) | band;913tuner_buf[4] = 0x80;914915if (fe->ops.i2c_gate_ctrl)916fe->ops.i2c_gate_ctrl(fe, 1);917if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)918return -EIO;919920msleep(50);921922if (fe->ops.i2c_gate_ctrl)923fe->ops.i2c_gate_ctrl(fe, 1);924if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)925return -EIO;926927msleep(1);928929return 0;930}931932static u8 dvbc_philips_tdm1316l_inittab[] = {9330x80, 0x01,9340x80, 0x00,9350x81, 0x01,9360x81, 0x00,9370x00, 0x09,9380x01, 0x69,9390x03, 0x00,9400x04, 0x00,9410x07, 0x00,9420x08, 0x00,9430x20, 0x00,9440x21, 0x40,9450x22, 0x00,9460x23, 0x00,9470x24, 0x40,9480x25, 0x88,9490x30, 0xff,9500x31, 0x00,9510x32, 0xff,9520x33, 0x00,9530x34, 0x50,9540x35, 0x7f,9550x36, 0x00,9560x37, 0x20,9570x38, 0x00,9580x40, 0x1c,9590x41, 0xff,9600x42, 0x29,9610x43, 0x20,9620x44, 0xff,9630x45, 0x00,9640x46, 0x00,9650x49, 0x04,9660x4a, 0x00,9670x4b, 0x7b,9680x52, 0x30,9690x55, 0xae,9700x56, 0x47,9710x57, 0xe1,9720x58, 0x3a,9730x5a, 0x1e,9740x5b, 0x34,9750x60, 0x00,9760x63, 0x00,9770x64, 0x00,9780x65, 0x00,9790x66, 0x00,9800x67, 0x00,9810x68, 0x00,9820x69, 0x00,9830x6a, 0x02,9840x6b, 0x00,9850x70, 0xff,9860x71, 0x00,9870x72, 0x00,9880x73, 0x00,9890x74, 0x0c,9900x80, 0x00,9910x81, 0x00,9920x82, 0x00,9930x83, 0x00,9940x84, 0x04,9950x85, 0x80,9960x86, 0x24,9970x87, 0x78,9980x88, 0x10,9990x89, 0x00,10000x90, 0x01,10010x91, 0x01,10020xa0, 0x04,10030xa1, 0x00,10040xa2, 0x00,10050xb0, 0x91,10060xb1, 0x0b,10070xc0, 0x53,10080xc1, 0x70,10090xc2, 0x12,10100xd0, 0x00,10110xd1, 0x00,10120xd2, 0x00,10130xd3, 0x00,10140xd4, 0x00,10150xd5, 0x00,10160xde, 0x00,10170xdf, 0x00,10180x61, 0x38,10190x62, 0x0a,10200x53, 0x13,10210x59, 0x08,10220xff, 0xff,1023};10241025static struct stv0297_config dvbc_philips_tdm1316l_config = {1026.demod_address = 0x1c,1027.inittab = dvbc_philips_tdm1316l_inittab,1028.invert = 0,1029.stop_during_read = 1,1030};10311032static struct tda10023_config tda10023_config = {1033.demod_address = 0xc,1034.invert = 0,1035.xtal = 16000000,1036.pll_m = 11,1037.pll_p = 3,1038.pll_n = 1,1039.deltaf = 0xa511,1040};10411042static struct tda827x_config tda827x_config = {1043.config = 0,1044};10451046/* TT S2-3200 DVB-S (STB0899) Inittab */1047static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {10481049{ STB0899_DEV_ID , 0x81 },1050{ STB0899_DISCNTRL1 , 0x32 },1051{ STB0899_DISCNTRL2 , 0x80 },1052{ STB0899_DISRX_ST0 , 0x04 },1053{ STB0899_DISRX_ST1 , 0x00 },1054{ STB0899_DISPARITY , 0x00 },1055{ STB0899_DISFIFO , 0x00 },1056{ STB0899_DISSTATUS , 0x20 },1057{ STB0899_DISF22 , 0x8c },1058{ STB0899_DISF22RX , 0x9a },1059{ STB0899_SYSREG , 0x0b },1060{ STB0899_ACRPRESC , 0x11 },1061{ STB0899_ACRDIV1 , 0x0a },1062{ STB0899_ACRDIV2 , 0x05 },1063{ STB0899_DACR1 , 0x00 },1064{ STB0899_DACR2 , 0x00 },1065{ STB0899_OUTCFG , 0x00 },1066{ STB0899_MODECFG , 0x00 },1067{ STB0899_IRQSTATUS_3 , 0x30 },1068{ STB0899_IRQSTATUS_2 , 0x00 },1069{ STB0899_IRQSTATUS_1 , 0x00 },1070{ STB0899_IRQSTATUS_0 , 0x00 },1071{ STB0899_IRQMSK_3 , 0xf3 },1072{ STB0899_IRQMSK_2 , 0xfc },1073{ STB0899_IRQMSK_1 , 0xff },1074{ STB0899_IRQMSK_0 , 0xff },1075{ STB0899_IRQCFG , 0x00 },1076{ STB0899_I2CCFG , 0x88 },1077{ STB0899_I2CRPT , 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */1078{ STB0899_IOPVALUE5 , 0x00 },1079{ STB0899_IOPVALUE4 , 0x20 },1080{ STB0899_IOPVALUE3 , 0xc9 },1081{ STB0899_IOPVALUE2 , 0x90 },1082{ STB0899_IOPVALUE1 , 0x40 },1083{ STB0899_IOPVALUE0 , 0x00 },1084{ STB0899_GPIO00CFG , 0x82 },1085{ STB0899_GPIO01CFG , 0x82 },1086{ STB0899_GPIO02CFG , 0x82 },1087{ STB0899_GPIO03CFG , 0x82 },1088{ STB0899_GPIO04CFG , 0x82 },1089{ STB0899_GPIO05CFG , 0x82 },1090{ STB0899_GPIO06CFG , 0x82 },1091{ STB0899_GPIO07CFG , 0x82 },1092{ STB0899_GPIO08CFG , 0x82 },1093{ STB0899_GPIO09CFG , 0x82 },1094{ STB0899_GPIO10CFG , 0x82 },1095{ STB0899_GPIO11CFG , 0x82 },1096{ STB0899_GPIO12CFG , 0x82 },1097{ STB0899_GPIO13CFG , 0x82 },1098{ STB0899_GPIO14CFG , 0x82 },1099{ STB0899_GPIO15CFG , 0x82 },1100{ STB0899_GPIO16CFG , 0x82 },1101{ STB0899_GPIO17CFG , 0x82 },1102{ STB0899_GPIO18CFG , 0x82 },1103{ STB0899_GPIO19CFG , 0x82 },1104{ STB0899_GPIO20CFG , 0x82 },1105{ STB0899_SDATCFG , 0xb8 },1106{ STB0899_SCLTCFG , 0xba },1107{ STB0899_AGCRFCFG , 0x1c }, /* 0x11 */1108{ STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */1109{ STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */1110{ STB0899_DIRCLKCFG , 0x82 },1111{ STB0899_CLKOUT27CFG , 0x7e },1112{ STB0899_STDBYCFG , 0x82 },1113{ STB0899_CS0CFG , 0x82 },1114{ STB0899_CS1CFG , 0x82 },1115{ STB0899_DISEQCOCFG , 0x20 },1116{ STB0899_GPIO32CFG , 0x82 },1117{ STB0899_GPIO33CFG , 0x82 },1118{ STB0899_GPIO34CFG , 0x82 },1119{ STB0899_GPIO35CFG , 0x82 },1120{ STB0899_GPIO36CFG , 0x82 },1121{ STB0899_GPIO37CFG , 0x82 },1122{ STB0899_GPIO38CFG , 0x82 },1123{ STB0899_GPIO39CFG , 0x82 },1124{ STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */1125{ STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */1126{ STB0899_FILTCTRL , 0x00 },1127{ STB0899_SYSCTRL , 0x00 },1128{ STB0899_STOPCLK1 , 0x20 },1129{ STB0899_STOPCLK2 , 0x00 },1130{ STB0899_INTBUFSTATUS , 0x00 },1131{ STB0899_INTBUFCTRL , 0x0a },1132{ 0xffff , 0xff },1133};11341135static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {1136{ STB0899_DEMOD , 0x00 },1137{ STB0899_RCOMPC , 0xc9 },1138{ STB0899_AGC1CN , 0x41 },1139{ STB0899_AGC1REF , 0x10 },1140{ STB0899_RTC , 0x7a },1141{ STB0899_TMGCFG , 0x4e },1142{ STB0899_AGC2REF , 0x34 },1143{ STB0899_TLSR , 0x84 },1144{ STB0899_CFD , 0xc7 },1145{ STB0899_ACLC , 0x87 },1146{ STB0899_BCLC , 0x94 },1147{ STB0899_EQON , 0x41 },1148{ STB0899_LDT , 0xdd },1149{ STB0899_LDT2 , 0xc9 },1150{ STB0899_EQUALREF , 0xb4 },1151{ STB0899_TMGRAMP , 0x10 },1152{ STB0899_TMGTHD , 0x30 },1153{ STB0899_IDCCOMP , 0xfb },1154{ STB0899_QDCCOMP , 0x03 },1155{ STB0899_POWERI , 0x3b },1156{ STB0899_POWERQ , 0x3d },1157{ STB0899_RCOMP , 0x81 },1158{ STB0899_AGCIQIN , 0x80 },1159{ STB0899_AGC2I1 , 0x04 },1160{ STB0899_AGC2I2 , 0xf5 },1161{ STB0899_TLIR , 0x25 },1162{ STB0899_RTF , 0x80 },1163{ STB0899_DSTATUS , 0x00 },1164{ STB0899_LDI , 0xca },1165{ STB0899_CFRM , 0xf1 },1166{ STB0899_CFRL , 0xf3 },1167{ STB0899_NIRM , 0x2a },1168{ STB0899_NIRL , 0x05 },1169{ STB0899_ISYMB , 0x17 },1170{ STB0899_QSYMB , 0xfa },1171{ STB0899_SFRH , 0x2f },1172{ STB0899_SFRM , 0x68 },1173{ STB0899_SFRL , 0x40 },1174{ STB0899_SFRUPH , 0x2f },1175{ STB0899_SFRUPM , 0x68 },1176{ STB0899_SFRUPL , 0x40 },1177{ STB0899_EQUAI1 , 0xfd },1178{ STB0899_EQUAQ1 , 0x04 },1179{ STB0899_EQUAI2 , 0x0f },1180{ STB0899_EQUAQ2 , 0xff },1181{ STB0899_EQUAI3 , 0xdf },1182{ STB0899_EQUAQ3 , 0xfa },1183{ STB0899_EQUAI4 , 0x37 },1184{ STB0899_EQUAQ4 , 0x0d },1185{ STB0899_EQUAI5 , 0xbd },1186{ STB0899_EQUAQ5 , 0xf7 },1187{ STB0899_DSTATUS2 , 0x00 },1188{ STB0899_VSTATUS , 0x00 },1189{ STB0899_VERROR , 0xff },1190{ STB0899_IQSWAP , 0x2a },1191{ STB0899_ECNT1M , 0x00 },1192{ STB0899_ECNT1L , 0x00 },1193{ STB0899_ECNT2M , 0x00 },1194{ STB0899_ECNT2L , 0x00 },1195{ STB0899_ECNT3M , 0x00 },1196{ STB0899_ECNT3L , 0x00 },1197{ STB0899_FECAUTO1 , 0x06 },1198{ STB0899_FECM , 0x01 },1199{ STB0899_VTH12 , 0xf0 },1200{ STB0899_VTH23 , 0xa0 },1201{ STB0899_VTH34 , 0x78 },1202{ STB0899_VTH56 , 0x4e },1203{ STB0899_VTH67 , 0x48 },1204{ STB0899_VTH78 , 0x38 },1205{ STB0899_PRVIT , 0xff },1206{ STB0899_VITSYNC , 0x19 },1207{ STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */1208{ STB0899_TSULC , 0x42 },1209{ STB0899_RSLLC , 0x40 },1210{ STB0899_TSLPL , 0x12 },1211{ STB0899_TSCFGH , 0x0c },1212{ STB0899_TSCFGM , 0x00 },1213{ STB0899_TSCFGL , 0x0c },1214{ STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */1215{ STB0899_RSSYNCDEL , 0x00 },1216{ STB0899_TSINHDELH , 0x02 },1217{ STB0899_TSINHDELM , 0x00 },1218{ STB0899_TSINHDELL , 0x00 },1219{ STB0899_TSLLSTKM , 0x00 },1220{ STB0899_TSLLSTKL , 0x00 },1221{ STB0899_TSULSTKM , 0x00 },1222{ STB0899_TSULSTKL , 0xab },1223{ STB0899_PCKLENUL , 0x00 },1224{ STB0899_PCKLENLL , 0xcc },1225{ STB0899_RSPCKLEN , 0xcc },1226{ STB0899_TSSTATUS , 0x80 },1227{ STB0899_ERRCTRL1 , 0xb6 },1228{ STB0899_ERRCTRL2 , 0x96 },1229{ STB0899_ERRCTRL3 , 0x89 },1230{ STB0899_DMONMSK1 , 0x27 },1231{ STB0899_DMONMSK0 , 0x03 },1232{ STB0899_DEMAPVIT , 0x5c },1233{ STB0899_PLPARM , 0x1f },1234{ STB0899_PDELCTRL , 0x48 },1235{ STB0899_PDELCTRL2 , 0x00 },1236{ STB0899_BBHCTRL1 , 0x00 },1237{ STB0899_BBHCTRL2 , 0x00 },1238{ STB0899_HYSTTHRESH , 0x77 },1239{ STB0899_MATCSTM , 0x00 },1240{ STB0899_MATCSTL , 0x00 },1241{ STB0899_UPLCSTM , 0x00 },1242{ STB0899_UPLCSTL , 0x00 },1243{ STB0899_DFLCSTM , 0x00 },1244{ STB0899_DFLCSTL , 0x00 },1245{ STB0899_SYNCCST , 0x00 },1246{ STB0899_SYNCDCSTM , 0x00 },1247{ STB0899_SYNCDCSTL , 0x00 },1248{ STB0899_ISI_ENTRY , 0x00 },1249{ STB0899_ISI_BIT_EN , 0x00 },1250{ STB0899_MATSTRM , 0x00 },1251{ STB0899_MATSTRL , 0x00 },1252{ STB0899_UPLSTRM , 0x00 },1253{ STB0899_UPLSTRL , 0x00 },1254{ STB0899_DFLSTRM , 0x00 },1255{ STB0899_DFLSTRL , 0x00 },1256{ STB0899_SYNCSTR , 0x00 },1257{ STB0899_SYNCDSTRM , 0x00 },1258{ STB0899_SYNCDSTRL , 0x00 },1259{ STB0899_CFGPDELSTATUS1 , 0x10 },1260{ STB0899_CFGPDELSTATUS2 , 0x00 },1261{ STB0899_BBFERRORM , 0x00 },1262{ STB0899_BBFERRORL , 0x00 },1263{ STB0899_UPKTERRORM , 0x00 },1264{ STB0899_UPKTERRORL , 0x00 },1265{ 0xffff , 0xff },1266};12671268static struct stb0899_config tt3200_config = {1269.init_dev = tt3200_stb0899_s1_init_1,1270.init_s2_demod = stb0899_s2_init_2,1271.init_s1_demod = tt3200_stb0899_s1_init_3,1272.init_s2_fec = stb0899_s2_init_4,1273.init_tst = stb0899_s1_init_5,12741275.postproc = NULL,12761277.demod_address = 0x68,12781279.xtal_freq = 27000000,1280.inversion = IQ_SWAP_ON, /* 1 */12811282.lo_clk = 76500000,1283.hi_clk = 99000000,12841285.esno_ave = STB0899_DVBS2_ESNO_AVE,1286.esno_quant = STB0899_DVBS2_ESNO_QUANT,1287.avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,1288.avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,1289.miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,1290.uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,1291.uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,1292.uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,1293.sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,12941295.btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,1296.btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,1297.crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,1298.ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,12991300.tuner_get_frequency = stb6100_get_frequency,1301.tuner_set_frequency = stb6100_set_frequency,1302.tuner_set_bandwidth = stb6100_set_bandwidth,1303.tuner_get_bandwidth = stb6100_get_bandwidth,1304.tuner_set_rfsiggain = NULL1305};13061307static struct stb6100_config tt3200_stb6100_config = {1308.tuner_address = 0x60,1309.refclock = 27000000,1310};13111312static void frontend_init(struct budget_ci *budget_ci)1313{1314switch (budget_ci->budget.dev->pci->subsystem_device) {1315case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))1316budget_ci->budget.dvb_frontend =1317dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);1318if (budget_ci->budget.dvb_frontend) {1319budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;1320budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;1321break;1322}1323break;13241325case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))1326budget_ci->budget.dvb_frontend =1327dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);1328if (budget_ci->budget.dvb_frontend) {1329budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;1330break;1331}1332break;13331334case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))1335budget_ci->tuner_pll_address = 0x61;1336budget_ci->budget.dvb_frontend =1337dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);1338if (budget_ci->budget.dvb_frontend) {1339budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;1340break;1341}1342break;13431344case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)1345budget_ci->tuner_pll_address = 0x63;1346budget_ci->budget.dvb_frontend =1347dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);1348if (budget_ci->budget.dvb_frontend) {1349budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;1350budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;1351break;1352}1353break;13541355case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))1356budget_ci->tuner_pll_address = 0x60;1357budget_ci->budget.dvb_frontend =1358dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);1359if (budget_ci->budget.dvb_frontend) {1360budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;1361budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;1362break;1363}1364break;13651366case 0x1017: // TT S-1500 PCI1367budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);1368if (budget_ci->budget.dvb_frontend) {1369budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;1370budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;13711372budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;1373if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {1374printk("%s: No LNBP21 found!\n", __func__);1375dvb_frontend_detach(budget_ci->budget.dvb_frontend);1376budget_ci->budget.dvb_frontend = NULL;1377}1378}1379break;13801381case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */1382budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);1383if (budget_ci->budget.dvb_frontend) {1384if (dvb_attach(tda827x_attach, budget_ci->budget.dvb_frontend, 0x61, &budget_ci->budget.i2c_adap, &tda827x_config) == NULL) {1385printk(KERN_ERR "%s: No tda827x found!\n", __func__);1386dvb_frontend_detach(budget_ci->budget.dvb_frontend);1387budget_ci->budget.dvb_frontend = NULL;1388}1389}1390break;13911392case 0x101b: /* TT S-1500B (BSBE1-D01A - STV0288/STB6000/LNBP21) */1393budget_ci->budget.dvb_frontend = dvb_attach(stv0288_attach, &stv0288_bsbe1_d01a_config, &budget_ci->budget.i2c_adap);1394if (budget_ci->budget.dvb_frontend) {1395if (dvb_attach(stb6000_attach, budget_ci->budget.dvb_frontend, 0x63, &budget_ci->budget.i2c_adap)) {1396if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {1397printk(KERN_ERR "%s: No LNBP21 found!\n", __func__);1398dvb_frontend_detach(budget_ci->budget.dvb_frontend);1399budget_ci->budget.dvb_frontend = NULL;1400}1401} else {1402printk(KERN_ERR "%s: No STB6000 found!\n", __func__);1403dvb_frontend_detach(budget_ci->budget.dvb_frontend);1404budget_ci->budget.dvb_frontend = NULL;1405}1406}1407break;14081409case 0x1019: // TT S2-3200 PCI1410/*1411* NOTE! on some STB0899 versions, the internal PLL takes a longer time1412* to settle, aka LOCK. On the older revisions of the chip, we don't see1413* this, as a result on the newer chips the entire clock tree, will not1414* be stable after a freshly POWER 'ed up situation.1415* In this case, we should RESET the STB0899 (Active LOW) and wait for1416* PLL stabilization.1417*1418* On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is1419* connected to the SAA7146 GPIO, GPIO2, Pin 1421420*/1421/* Reset Demodulator */1422saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);1423/* Wait for everything to die */1424msleep(50);1425/* Pull it up out of Reset state */1426saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);1427/* Wait for PLL to stabilize */1428msleep(250);1429/*1430* PLL state should be stable now. Ideally, we should check1431* for PLL LOCK status. But well, never mind!1432*/1433budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);1434if (budget_ci->budget.dvb_frontend) {1435if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {1436if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {1437printk("%s: No LNBP21 found!\n", __func__);1438dvb_frontend_detach(budget_ci->budget.dvb_frontend);1439budget_ci->budget.dvb_frontend = NULL;1440}1441} else {1442dvb_frontend_detach(budget_ci->budget.dvb_frontend);1443budget_ci->budget.dvb_frontend = NULL;1444}1445}1446break;14471448}14491450if (budget_ci->budget.dvb_frontend == NULL) {1451printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",1452budget_ci->budget.dev->pci->vendor,1453budget_ci->budget.dev->pci->device,1454budget_ci->budget.dev->pci->subsystem_vendor,1455budget_ci->budget.dev->pci->subsystem_device);1456} else {1457if (dvb_register_frontend1458(&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {1459printk("budget-ci: Frontend registration failed!\n");1460dvb_frontend_detach(budget_ci->budget.dvb_frontend);1461budget_ci->budget.dvb_frontend = NULL;1462}1463}1464}14651466static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)1467{1468struct budget_ci *budget_ci;1469int err;14701471budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);1472if (!budget_ci) {1473err = -ENOMEM;1474goto out1;1475}14761477dprintk(2, "budget_ci: %p\n", budget_ci);14781479dev->ext_priv = budget_ci;14801481err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,1482adapter_nr);1483if (err)1484goto out2;14851486err = msp430_ir_init(budget_ci);1487if (err)1488goto out3;14891490ciintf_init(budget_ci);14911492budget_ci->budget.dvb_adapter.priv = budget_ci;1493frontend_init(budget_ci);14941495ttpci_budget_init_hooks(&budget_ci->budget);14961497return 0;14981499out3:1500ttpci_budget_deinit(&budget_ci->budget);1501out2:1502kfree(budget_ci);1503out1:1504return err;1505}15061507static int budget_ci_detach(struct saa7146_dev *dev)1508{1509struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;1510struct saa7146_dev *saa = budget_ci->budget.dev;1511int err;15121513if (budget_ci->budget.ci_present)1514ciintf_deinit(budget_ci);1515msp430_ir_deinit(budget_ci);1516if (budget_ci->budget.dvb_frontend) {1517dvb_unregister_frontend(budget_ci->budget.dvb_frontend);1518dvb_frontend_detach(budget_ci->budget.dvb_frontend);1519}1520err = ttpci_budget_deinit(&budget_ci->budget);15211522// disable frontend and CI interface1523saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);15241525kfree(budget_ci);15261527return err;1528}15291530static struct saa7146_extension budget_extension;15311532MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);1533MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);1534MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);1535MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);1536MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);1537MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);1538MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);1539MAKE_BUDGET_INFO(ttbs1500b, "TT-Budget S-1500B PCI", BUDGET_TT);15401541static struct pci_device_id pci_tbl[] = {1542MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),1543MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),1544MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),1545MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),1546MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),1547MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),1548MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),1549MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),1550MAKE_EXTENSION_PCI(ttbs1500b, 0x13c2, 0x101b),1551{1552.vendor = 0,1553}1554};15551556MODULE_DEVICE_TABLE(pci, pci_tbl);15571558static struct saa7146_extension budget_extension = {1559.name = "budget_ci dvb",1560.flags = SAA7146_USE_I2C_IRQ,15611562.module = THIS_MODULE,1563.pci_tbl = &pci_tbl[0],1564.attach = budget_ci_attach,1565.detach = budget_ci_detach,15661567.irq_mask = MASK_03 | MASK_06 | MASK_10,1568.irq_func = budget_ci_irq,1569};15701571static int __init budget_ci_init(void)1572{1573return saa7146_register_extension(&budget_extension);1574}15751576static void __exit budget_ci_exit(void)1577{1578saa7146_unregister_extension(&budget_extension);1579}15801581module_init(budget_ci_init);1582module_exit(budget_ci_exit);15831584MODULE_LICENSE("GPL");1585MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");1586MODULE_DESCRIPTION("driver for the SAA7146 based so-called "1587"budget PCI DVB cards w/ CI-module produced by "1588"Siemens, Technotrend, Hauppauge");158915901591