cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

budget.c (25542B)


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