162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * budget.c: driver for the SAA7146 based Budget DVB cards 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Compiled from various sources by Michael Hunold <michael@mihu.de> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Copyright (C) 1999-2002 Ralph Metzler 1062306a36Sopenharmony_ci * & Marcus Metzler for convergence integrated media GmbH 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * 26feb2004 Support for FS Activy Card (Grundig tuner) by 1362306a36Sopenharmony_ci * Michael Dreher <michael@5dot1.de>, 1462306a36Sopenharmony_ci * Oliver Endriss <o.endriss@gmx.de> and 1562306a36Sopenharmony_ci * Andreas 'randy' Weinberger 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * the project's page is at https://linuxtv.org 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include "budget.h" 2162306a36Sopenharmony_ci#include "stv0299.h" 2262306a36Sopenharmony_ci#include "ves1x93.h" 2362306a36Sopenharmony_ci#include "ves1820.h" 2462306a36Sopenharmony_ci#include "l64781.h" 2562306a36Sopenharmony_ci#include "tda8083.h" 2662306a36Sopenharmony_ci#include "s5h1420.h" 2762306a36Sopenharmony_ci#include "tda10086.h" 2862306a36Sopenharmony_ci#include "tda826x.h" 2962306a36Sopenharmony_ci#include "lnbp21.h" 3062306a36Sopenharmony_ci#include "bsru6.h" 3162306a36Sopenharmony_ci#include "bsbe1.h" 3262306a36Sopenharmony_ci#include "tdhd1.h" 3362306a36Sopenharmony_ci#include "stv6110x.h" 3462306a36Sopenharmony_ci#include "stv090x.h" 3562306a36Sopenharmony_ci#include "isl6423.h" 3662306a36Sopenharmony_ci#include "lnbh24.h" 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic int diseqc_method; 4062306a36Sopenharmony_cimodule_param(diseqc_method, int, 0444); 4162306a36Sopenharmony_ciMODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)"); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic void Set22K (struct budget *budget, int state) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci struct saa7146_dev *dev=budget->dev; 4862306a36Sopenharmony_ci dprintk(2, "budget: %p\n", budget); 4962306a36Sopenharmony_ci saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO)); 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* Diseqc functions only for TT Budget card */ 5362306a36Sopenharmony_ci/* taken from the Skyvision DVB driver by 5462306a36Sopenharmony_ci Ralph Metzler <rjkm@metzlerbros.de> */ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic void DiseqcSendBit (struct budget *budget, int data) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci struct saa7146_dev *dev=budget->dev; 5962306a36Sopenharmony_ci dprintk(2, "budget: %p\n", budget); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); 6262306a36Sopenharmony_ci udelay(data ? 500 : 1000); 6362306a36Sopenharmony_ci saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); 6462306a36Sopenharmony_ci udelay(data ? 1000 : 500); 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic void DiseqcSendByte (struct budget *budget, int data) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci int i, par=1, d; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci dprintk(2, "budget: %p\n", budget); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci for (i=7; i>=0; i--) { 7462306a36Sopenharmony_ci d = (data>>i)&1; 7562306a36Sopenharmony_ci par ^= d; 7662306a36Sopenharmony_ci DiseqcSendBit(budget, d); 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci DiseqcSendBit(budget, par); 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci struct saa7146_dev *dev=budget->dev; 8562306a36Sopenharmony_ci int i; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci dprintk(2, "budget: %p\n", budget); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); 9062306a36Sopenharmony_ci mdelay(16); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci for (i=0; i<len; i++) 9362306a36Sopenharmony_ci DiseqcSendByte(budget, msg[i]); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci mdelay(16); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci if (burst!=-1) { 9862306a36Sopenharmony_ci if (burst) 9962306a36Sopenharmony_ci DiseqcSendByte(budget, 0xff); 10062306a36Sopenharmony_ci else { 10162306a36Sopenharmony_ci saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); 10262306a36Sopenharmony_ci mdelay(12); 10362306a36Sopenharmony_ci udelay(500); 10462306a36Sopenharmony_ci saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci msleep(20); 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci return 0; 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci/* 11362306a36Sopenharmony_ci * Routines for the Fujitsu Siemens Activy budget card 11462306a36Sopenharmony_ci * 22 kHz tone and DiSEqC are handled by the frontend. 11562306a36Sopenharmony_ci * Voltage must be set here. 11662306a36Sopenharmony_ci * GPIO 1: LNBP EN, GPIO 2: LNBP VSEL 11762306a36Sopenharmony_ci */ 11862306a36Sopenharmony_cistatic int SetVoltage_Activy(struct budget *budget, 11962306a36Sopenharmony_ci enum fe_sec_voltage voltage) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci struct saa7146_dev *dev=budget->dev; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci dprintk(2, "budget: %p\n", budget); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci switch (voltage) { 12662306a36Sopenharmony_ci case SEC_VOLTAGE_13: 12762306a36Sopenharmony_ci saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); 12862306a36Sopenharmony_ci saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO); 12962306a36Sopenharmony_ci break; 13062306a36Sopenharmony_ci case SEC_VOLTAGE_18: 13162306a36Sopenharmony_ci saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); 13262306a36Sopenharmony_ci saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); 13362306a36Sopenharmony_ci break; 13462306a36Sopenharmony_ci case SEC_VOLTAGE_OFF: 13562306a36Sopenharmony_ci saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); 13662306a36Sopenharmony_ci break; 13762306a36Sopenharmony_ci default: 13862306a36Sopenharmony_ci return -EINVAL; 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci return 0; 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic int siemens_budget_set_voltage(struct dvb_frontend *fe, 14562306a36Sopenharmony_ci enum fe_sec_voltage voltage) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci struct budget *budget = fe->dvb->priv; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci return SetVoltage_Activy (budget, voltage); 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic int budget_set_tone(struct dvb_frontend *fe, 15362306a36Sopenharmony_ci enum fe_sec_tone_mode tone) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci struct budget *budget = fe->dvb->priv; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci switch (tone) { 15862306a36Sopenharmony_ci case SEC_TONE_ON: 15962306a36Sopenharmony_ci Set22K (budget, 1); 16062306a36Sopenharmony_ci break; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci case SEC_TONE_OFF: 16362306a36Sopenharmony_ci Set22K (budget, 0); 16462306a36Sopenharmony_ci break; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci default: 16762306a36Sopenharmony_ci return -EINVAL; 16862306a36Sopenharmony_ci } 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci return 0; 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistatic int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) 17462306a36Sopenharmony_ci{ 17562306a36Sopenharmony_ci struct budget *budget = fe->dvb->priv; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci return 0; 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic int budget_diseqc_send_burst(struct dvb_frontend *fe, 18362306a36Sopenharmony_ci enum fe_sec_mini_cmd minicmd) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci struct budget *budget = fe->dvb->priv; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci SendDiSEqCMsg (budget, 0, NULL, minicmd); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci return 0; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 19562306a36Sopenharmony_ci struct budget *budget = fe->dvb->priv; 19662306a36Sopenharmony_ci u8 pwr = 0; 19762306a36Sopenharmony_ci u8 buf[4]; 19862306a36Sopenharmony_ci struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; 19962306a36Sopenharmony_ci u32 div = (c->frequency + 479500) / 125; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci if (c->frequency > 2000000) 20262306a36Sopenharmony_ci pwr = 3; 20362306a36Sopenharmony_ci else if (c->frequency > 1800000) 20462306a36Sopenharmony_ci pwr = 2; 20562306a36Sopenharmony_ci else if (c->frequency > 1600000) 20662306a36Sopenharmony_ci pwr = 1; 20762306a36Sopenharmony_ci else if (c->frequency > 1200000) 20862306a36Sopenharmony_ci pwr = 0; 20962306a36Sopenharmony_ci else if (c->frequency >= 1100000) 21062306a36Sopenharmony_ci pwr = 1; 21162306a36Sopenharmony_ci else pwr = 2; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci buf[0] = (div >> 8) & 0x7f; 21462306a36Sopenharmony_ci buf[1] = div & 0xff; 21562306a36Sopenharmony_ci buf[2] = ((div & 0x18000) >> 10) | 0x95; 21662306a36Sopenharmony_ci buf[3] = (pwr << 6) | 0x30; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci // NOTE: since we're using a prescaler of 2, we set the 21962306a36Sopenharmony_ci // divisor frequency to 62.5kHz and divide by 125 above 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 22262306a36Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 1); 22362306a36Sopenharmony_ci if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; 22462306a36Sopenharmony_ci return 0; 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic struct ves1x93_config alps_bsrv2_config = 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci .demod_address = 0x08, 23062306a36Sopenharmony_ci .xin = 90100000UL, 23162306a36Sopenharmony_ci .invert_pwm = 0, 23262306a36Sopenharmony_ci}; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 23762306a36Sopenharmony_ci struct budget *budget = fe->dvb->priv; 23862306a36Sopenharmony_ci u32 div; 23962306a36Sopenharmony_ci u8 data[4]; 24062306a36Sopenharmony_ci struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) }; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci div = (c->frequency + 35937500 + 31250) / 62500; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci data[0] = (div >> 8) & 0x7f; 24562306a36Sopenharmony_ci data[1] = div & 0xff; 24662306a36Sopenharmony_ci data[2] = 0x85 | ((div >> 10) & 0x60); 24762306a36Sopenharmony_ci data[3] = (c->frequency < 174000000 ? 0x88 : c->frequency < 470000000 ? 0x84 : 0x81); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 25062306a36Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 1); 25162306a36Sopenharmony_ci if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; 25262306a36Sopenharmony_ci return 0; 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic struct ves1820_config alps_tdbe2_config = { 25662306a36Sopenharmony_ci .demod_address = 0x09, 25762306a36Sopenharmony_ci .xin = 57840000UL, 25862306a36Sopenharmony_ci .invert = 1, 25962306a36Sopenharmony_ci .selagc = VES1820_SELAGC_SIGNAMPERR, 26062306a36Sopenharmony_ci}; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic int grundig_29504_401_tuner_set_params(struct dvb_frontend *fe) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 26562306a36Sopenharmony_ci struct budget *budget = fe->dvb->priv; 26662306a36Sopenharmony_ci u8 *tuner_addr = fe->tuner_priv; 26762306a36Sopenharmony_ci u32 div; 26862306a36Sopenharmony_ci u8 cfg, cpump, band_select; 26962306a36Sopenharmony_ci u8 data[4]; 27062306a36Sopenharmony_ci struct i2c_msg msg = { .flags = 0, .buf = data, .len = sizeof(data) }; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if (tuner_addr) 27362306a36Sopenharmony_ci msg.addr = *tuner_addr; 27462306a36Sopenharmony_ci else 27562306a36Sopenharmony_ci msg.addr = 0x61; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci div = (36125000 + c->frequency) / 166666; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci cfg = 0x88; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci if (c->frequency < 175000000) 28262306a36Sopenharmony_ci cpump = 2; 28362306a36Sopenharmony_ci else if (c->frequency < 390000000) 28462306a36Sopenharmony_ci cpump = 1; 28562306a36Sopenharmony_ci else if (c->frequency < 470000000) 28662306a36Sopenharmony_ci cpump = 2; 28762306a36Sopenharmony_ci else if (c->frequency < 750000000) 28862306a36Sopenharmony_ci cpump = 1; 28962306a36Sopenharmony_ci else 29062306a36Sopenharmony_ci cpump = 3; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci if (c->frequency < 175000000) 29362306a36Sopenharmony_ci band_select = 0x0e; 29462306a36Sopenharmony_ci else if (c->frequency < 470000000) 29562306a36Sopenharmony_ci band_select = 0x05; 29662306a36Sopenharmony_ci else 29762306a36Sopenharmony_ci band_select = 0x03; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci data[0] = (div >> 8) & 0x7f; 30062306a36Sopenharmony_ci data[1] = div & 0xff; 30162306a36Sopenharmony_ci data[2] = ((div >> 10) & 0x60) | cfg; 30262306a36Sopenharmony_ci data[3] = (cpump << 6) | band_select; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 30562306a36Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 1); 30662306a36Sopenharmony_ci if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; 30762306a36Sopenharmony_ci return 0; 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic struct l64781_config grundig_29504_401_config = { 31162306a36Sopenharmony_ci .demod_address = 0x55, 31262306a36Sopenharmony_ci}; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic struct l64781_config grundig_29504_401_config_activy = { 31562306a36Sopenharmony_ci .demod_address = 0x54, 31662306a36Sopenharmony_ci}; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cistatic u8 tuner_address_grundig_29504_401_activy = 0x60; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_cistatic int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe) 32162306a36Sopenharmony_ci{ 32262306a36Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 32362306a36Sopenharmony_ci struct budget *budget = fe->dvb->priv; 32462306a36Sopenharmony_ci u32 div; 32562306a36Sopenharmony_ci u8 data[4]; 32662306a36Sopenharmony_ci struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci div = c->frequency / 125; 32962306a36Sopenharmony_ci data[0] = (div >> 8) & 0x7f; 33062306a36Sopenharmony_ci data[1] = div & 0xff; 33162306a36Sopenharmony_ci data[2] = 0x8e; 33262306a36Sopenharmony_ci data[3] = 0x00; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 33562306a36Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 1); 33662306a36Sopenharmony_ci if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; 33762306a36Sopenharmony_ci return 0; 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistatic struct tda8083_config grundig_29504_451_config = { 34162306a36Sopenharmony_ci .demod_address = 0x68, 34262306a36Sopenharmony_ci}; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic int s5h1420_tuner_set_params(struct dvb_frontend *fe) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 34762306a36Sopenharmony_ci struct budget *budget = fe->dvb->priv; 34862306a36Sopenharmony_ci u32 div; 34962306a36Sopenharmony_ci u8 data[4]; 35062306a36Sopenharmony_ci struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci div = c->frequency / 1000; 35362306a36Sopenharmony_ci data[0] = (div >> 8) & 0x7f; 35462306a36Sopenharmony_ci data[1] = div & 0xff; 35562306a36Sopenharmony_ci data[2] = 0xc2; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci if (div < 1450) 35862306a36Sopenharmony_ci data[3] = 0x00; 35962306a36Sopenharmony_ci else if (div < 1850) 36062306a36Sopenharmony_ci data[3] = 0x40; 36162306a36Sopenharmony_ci else if (div < 2000) 36262306a36Sopenharmony_ci data[3] = 0x80; 36362306a36Sopenharmony_ci else 36462306a36Sopenharmony_ci data[3] = 0xc0; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 36762306a36Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 1); 36862306a36Sopenharmony_ci if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci return 0; 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_cistatic struct s5h1420_config s5h1420_config = { 37462306a36Sopenharmony_ci .demod_address = 0x53, 37562306a36Sopenharmony_ci .invert = 1, 37662306a36Sopenharmony_ci .cdclk_polarity = 1, 37762306a36Sopenharmony_ci}; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_cistatic struct tda10086_config tda10086_config = { 38062306a36Sopenharmony_ci .demod_address = 0x0e, 38162306a36Sopenharmony_ci .invert = 0, 38262306a36Sopenharmony_ci .diseqc_tone = 1, 38362306a36Sopenharmony_ci .xtal_freq = TDA10086_XTAL_16M, 38462306a36Sopenharmony_ci}; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_cistatic const struct stv0299_config alps_bsru6_config_activy = { 38762306a36Sopenharmony_ci .demod_address = 0x68, 38862306a36Sopenharmony_ci .inittab = alps_bsru6_inittab, 38962306a36Sopenharmony_ci .mclk = 88000000UL, 39062306a36Sopenharmony_ci .invert = 1, 39162306a36Sopenharmony_ci .op0_off = 1, 39262306a36Sopenharmony_ci .min_delay_ms = 100, 39362306a36Sopenharmony_ci .set_symbol_rate = alps_bsru6_set_symbol_rate, 39462306a36Sopenharmony_ci}; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic const struct stv0299_config alps_bsbe1_config_activy = { 39762306a36Sopenharmony_ci .demod_address = 0x68, 39862306a36Sopenharmony_ci .inittab = alps_bsbe1_inittab, 39962306a36Sopenharmony_ci .mclk = 88000000UL, 40062306a36Sopenharmony_ci .invert = 1, 40162306a36Sopenharmony_ci .op0_off = 1, 40262306a36Sopenharmony_ci .min_delay_ms = 100, 40362306a36Sopenharmony_ci .set_symbol_rate = alps_bsbe1_set_symbol_rate, 40462306a36Sopenharmony_ci}; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci struct budget *budget = fe->dvb->priv; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci return request_firmware(fw, name, &budget->dev->pci->dev); 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_cistatic int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg) 41562306a36Sopenharmony_ci{ 41662306a36Sopenharmony_ci u8 val; 41762306a36Sopenharmony_ci struct i2c_msg msg[] = { 41862306a36Sopenharmony_ci { .addr = adr, .flags = 0, .buf = ®, .len = 1 }, 41962306a36Sopenharmony_ci { .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 } 42062306a36Sopenharmony_ci }; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val; 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic u8 read_pwm(struct budget* budget) 42662306a36Sopenharmony_ci{ 42762306a36Sopenharmony_ci u8 b = 0xff; 42862306a36Sopenharmony_ci u8 pwm; 42962306a36Sopenharmony_ci struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 }, 43062306a36Sopenharmony_ci { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} }; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff)) 43362306a36Sopenharmony_ci pwm = 0x48; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci return pwm; 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_cistatic struct stv090x_config tt1600_stv090x_config = { 43962306a36Sopenharmony_ci .device = STV0903, 44062306a36Sopenharmony_ci .demod_mode = STV090x_SINGLE, 44162306a36Sopenharmony_ci .clk_mode = STV090x_CLK_EXT, 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci .xtal = 13500000, 44462306a36Sopenharmony_ci .address = 0x68, 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci .ts1_mode = STV090x_TSMODE_DVBCI, 44762306a36Sopenharmony_ci .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci .repeater_level = STV090x_RPTLEVEL_16, 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci .tuner_init = NULL, 45262306a36Sopenharmony_ci .tuner_sleep = NULL, 45362306a36Sopenharmony_ci .tuner_set_mode = NULL, 45462306a36Sopenharmony_ci .tuner_set_frequency = NULL, 45562306a36Sopenharmony_ci .tuner_get_frequency = NULL, 45662306a36Sopenharmony_ci .tuner_set_bandwidth = NULL, 45762306a36Sopenharmony_ci .tuner_get_bandwidth = NULL, 45862306a36Sopenharmony_ci .tuner_set_bbgain = NULL, 45962306a36Sopenharmony_ci .tuner_get_bbgain = NULL, 46062306a36Sopenharmony_ci .tuner_set_refclk = NULL, 46162306a36Sopenharmony_ci .tuner_get_status = NULL, 46262306a36Sopenharmony_ci}; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_cistatic struct stv6110x_config tt1600_stv6110x_config = { 46562306a36Sopenharmony_ci .addr = 0x60, 46662306a36Sopenharmony_ci .refclk = 27000000, 46762306a36Sopenharmony_ci .clk_div = 2, 46862306a36Sopenharmony_ci}; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic struct isl6423_config tt1600_isl6423_config = { 47162306a36Sopenharmony_ci .current_max = SEC_CURRENT_515m, 47262306a36Sopenharmony_ci .curlim = SEC_CURRENT_LIM_ON, 47362306a36Sopenharmony_ci .mod_extern = 1, 47462306a36Sopenharmony_ci .addr = 0x08, 47562306a36Sopenharmony_ci}; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_cistatic void frontend_init(struct budget *budget) 47862306a36Sopenharmony_ci{ 47962306a36Sopenharmony_ci (void)alps_bsbe1_config; /* avoid warning */ 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci switch(budget->dev->pci->subsystem_device) { 48262306a36Sopenharmony_ci case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659)) 48362306a36Sopenharmony_ci case 0x1013: 48462306a36Sopenharmony_ci // try the ALPS BSRV2 first of all 48562306a36Sopenharmony_ci budget->dvb_frontend = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &budget->i2c_adap); 48662306a36Sopenharmony_ci if (budget->dvb_frontend) { 48762306a36Sopenharmony_ci budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params; 48862306a36Sopenharmony_ci budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; 48962306a36Sopenharmony_ci budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst; 49062306a36Sopenharmony_ci budget->dvb_frontend->ops.set_tone = budget_set_tone; 49162306a36Sopenharmony_ci break; 49262306a36Sopenharmony_ci } 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci // try the ALPS BSRU6 now 49562306a36Sopenharmony_ci budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap); 49662306a36Sopenharmony_ci if (budget->dvb_frontend) { 49762306a36Sopenharmony_ci budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; 49862306a36Sopenharmony_ci budget->dvb_frontend->tuner_priv = &budget->i2c_adap; 49962306a36Sopenharmony_ci if (budget->dev->pci->subsystem_device == 0x1003 && diseqc_method == 0) { 50062306a36Sopenharmony_ci budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; 50162306a36Sopenharmony_ci budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst; 50262306a36Sopenharmony_ci budget->dvb_frontend->ops.set_tone = budget_set_tone; 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci break; 50562306a36Sopenharmony_ci } 50662306a36Sopenharmony_ci break; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659)) 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci budget->dvb_frontend = dvb_attach(ves1820_attach, &alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget)); 51162306a36Sopenharmony_ci if (budget->dvb_frontend) { 51262306a36Sopenharmony_ci budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params; 51362306a36Sopenharmony_ci break; 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ci break; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060)) 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap); 52062306a36Sopenharmony_ci if (budget->dvb_frontend) { 52162306a36Sopenharmony_ci budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; 52262306a36Sopenharmony_ci budget->dvb_frontend->tuner_priv = NULL; 52362306a36Sopenharmony_ci break; 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci break; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci case 0x4f52: /* Cards based on Philips Semi Sylt PCI ref. design */ 52862306a36Sopenharmony_ci budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap); 52962306a36Sopenharmony_ci if (budget->dvb_frontend) { 53062306a36Sopenharmony_ci printk(KERN_INFO "budget: tuner ALPS BSRU6 in Philips Semi. Sylt detected\n"); 53162306a36Sopenharmony_ci budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; 53262306a36Sopenharmony_ci budget->dvb_frontend->tuner_priv = &budget->i2c_adap; 53362306a36Sopenharmony_ci break; 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci break; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci case 0x4f60: /* Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/tsa5059) */ 53862306a36Sopenharmony_ci { 53962306a36Sopenharmony_ci int subtype = i2c_readreg(&budget->i2c_adap, 0x50, 0x67); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci if (subtype < 0) 54262306a36Sopenharmony_ci break; 54362306a36Sopenharmony_ci /* fixme: find a better way to identify the card */ 54462306a36Sopenharmony_ci if (subtype < 0x36) { 54562306a36Sopenharmony_ci /* assume ALPS BSRU6 */ 54662306a36Sopenharmony_ci budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config_activy, &budget->i2c_adap); 54762306a36Sopenharmony_ci if (budget->dvb_frontend) { 54862306a36Sopenharmony_ci printk(KERN_INFO "budget: tuner ALPS BSRU6 detected\n"); 54962306a36Sopenharmony_ci budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; 55062306a36Sopenharmony_ci budget->dvb_frontend->tuner_priv = &budget->i2c_adap; 55162306a36Sopenharmony_ci budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; 55262306a36Sopenharmony_ci budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; 55362306a36Sopenharmony_ci break; 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci } else { 55662306a36Sopenharmony_ci /* assume ALPS BSBE1 */ 55762306a36Sopenharmony_ci /* reset tuner */ 55862306a36Sopenharmony_ci saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTLO); 55962306a36Sopenharmony_ci msleep(50); 56062306a36Sopenharmony_ci saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTHI); 56162306a36Sopenharmony_ci msleep(250); 56262306a36Sopenharmony_ci budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config_activy, &budget->i2c_adap); 56362306a36Sopenharmony_ci if (budget->dvb_frontend) { 56462306a36Sopenharmony_ci printk(KERN_INFO "budget: tuner ALPS BSBE1 detected\n"); 56562306a36Sopenharmony_ci budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params; 56662306a36Sopenharmony_ci budget->dvb_frontend->tuner_priv = &budget->i2c_adap; 56762306a36Sopenharmony_ci budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; 56862306a36Sopenharmony_ci budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; 56962306a36Sopenharmony_ci break; 57062306a36Sopenharmony_ci } 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci break; 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522)) 57662306a36Sopenharmony_ci budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap); 57762306a36Sopenharmony_ci if (budget->dvb_frontend) { 57862306a36Sopenharmony_ci budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params; 57962306a36Sopenharmony_ci budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; 58062306a36Sopenharmony_ci budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; 58162306a36Sopenharmony_ci } 58262306a36Sopenharmony_ci break; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci case 0x5f60: /* Fujitsu Siemens Activy Budget-T PCI rev AL (tda10046/ALPS TDHD1-204A) */ 58562306a36Sopenharmony_ci budget->dvb_frontend = dvb_attach(tda10046_attach, &alps_tdhd1_204a_config, &budget->i2c_adap); 58662306a36Sopenharmony_ci if (budget->dvb_frontend) { 58762306a36Sopenharmony_ci budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdhd1_204a_tuner_set_params; 58862306a36Sopenharmony_ci budget->dvb_frontend->tuner_priv = &budget->i2c_adap; 58962306a36Sopenharmony_ci } 59062306a36Sopenharmony_ci break; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */ 59362306a36Sopenharmony_ci budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap); 59462306a36Sopenharmony_ci if (budget->dvb_frontend) { 59562306a36Sopenharmony_ci budget->dvb_frontend->tuner_priv = &tuner_address_grundig_29504_401_activy; 59662306a36Sopenharmony_ci budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; 59762306a36Sopenharmony_ci } 59862306a36Sopenharmony_ci break; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260)) 60162306a36Sopenharmony_ci { 60262306a36Sopenharmony_ci struct dvb_frontend *fe; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci fe = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap); 60562306a36Sopenharmony_ci if (fe) { 60662306a36Sopenharmony_ci fe->ops.tuner_ops.set_params = s5h1420_tuner_set_params; 60762306a36Sopenharmony_ci budget->dvb_frontend = fe; 60862306a36Sopenharmony_ci if (dvb_attach(lnbp21_attach, fe, &budget->i2c_adap, 60962306a36Sopenharmony_ci 0, 0) == NULL) { 61062306a36Sopenharmony_ci printk("%s: No LNBP21 found!\n", __func__); 61162306a36Sopenharmony_ci goto error_out; 61262306a36Sopenharmony_ci } 61362306a36Sopenharmony_ci break; 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci } 61662306a36Sopenharmony_ci fallthrough; 61762306a36Sopenharmony_ci case 0x1018: // TT Budget-S-1401 (philips tda10086/philips tda8262) 61862306a36Sopenharmony_ci { 61962306a36Sopenharmony_ci struct dvb_frontend *fe; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci // gpio2 is connected to CLB - reset it + leave it high 62262306a36Sopenharmony_ci saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); 62362306a36Sopenharmony_ci msleep(1); 62462306a36Sopenharmony_ci saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); 62562306a36Sopenharmony_ci msleep(1); 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci fe = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap); 62862306a36Sopenharmony_ci if (fe) { 62962306a36Sopenharmony_ci budget->dvb_frontend = fe; 63062306a36Sopenharmony_ci if (dvb_attach(tda826x_attach, fe, 0x60, 63162306a36Sopenharmony_ci &budget->i2c_adap, 0) == NULL) 63262306a36Sopenharmony_ci printk("%s: No tda826x found!\n", __func__); 63362306a36Sopenharmony_ci if (dvb_attach(lnbp21_attach, fe, 63462306a36Sopenharmony_ci &budget->i2c_adap, 0, 0) == NULL) { 63562306a36Sopenharmony_ci printk("%s: No LNBP21 found!\n", __func__); 63662306a36Sopenharmony_ci goto error_out; 63762306a36Sopenharmony_ci } 63862306a36Sopenharmony_ci break; 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci } 64162306a36Sopenharmony_ci fallthrough; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci case 0x101c: { /* TT S2-1600 */ 64462306a36Sopenharmony_ci const struct stv6110x_devctl *ctl; 64562306a36Sopenharmony_ci saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); 64662306a36Sopenharmony_ci msleep(50); 64762306a36Sopenharmony_ci saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); 64862306a36Sopenharmony_ci msleep(250); 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci budget->dvb_frontend = dvb_attach(stv090x_attach, 65162306a36Sopenharmony_ci &tt1600_stv090x_config, 65262306a36Sopenharmony_ci &budget->i2c_adap, 65362306a36Sopenharmony_ci STV090x_DEMODULATOR_0); 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci if (budget->dvb_frontend) { 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci ctl = dvb_attach(stv6110x_attach, 65862306a36Sopenharmony_ci budget->dvb_frontend, 65962306a36Sopenharmony_ci &tt1600_stv6110x_config, 66062306a36Sopenharmony_ci &budget->i2c_adap); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci if (ctl) { 66362306a36Sopenharmony_ci tt1600_stv090x_config.tuner_init = ctl->tuner_init; 66462306a36Sopenharmony_ci tt1600_stv090x_config.tuner_sleep = ctl->tuner_sleep; 66562306a36Sopenharmony_ci tt1600_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; 66662306a36Sopenharmony_ci tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; 66762306a36Sopenharmony_ci tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; 66862306a36Sopenharmony_ci tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; 66962306a36Sopenharmony_ci tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; 67062306a36Sopenharmony_ci tt1600_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; 67162306a36Sopenharmony_ci tt1600_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; 67262306a36Sopenharmony_ci tt1600_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; 67362306a36Sopenharmony_ci tt1600_stv090x_config.tuner_get_status = ctl->tuner_get_status; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci /* call the init function once to initialize 67662306a36Sopenharmony_ci tuner's clock output divider and demod's 67762306a36Sopenharmony_ci master clock */ 67862306a36Sopenharmony_ci if (budget->dvb_frontend->ops.init) 67962306a36Sopenharmony_ci budget->dvb_frontend->ops.init(budget->dvb_frontend); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci if (dvb_attach(isl6423_attach, 68262306a36Sopenharmony_ci budget->dvb_frontend, 68362306a36Sopenharmony_ci &budget->i2c_adap, 68462306a36Sopenharmony_ci &tt1600_isl6423_config) == NULL) { 68562306a36Sopenharmony_ci printk(KERN_ERR "%s: No Intersil ISL6423 found!\n", __func__); 68662306a36Sopenharmony_ci goto error_out; 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci } else { 68962306a36Sopenharmony_ci printk(KERN_ERR "%s: No STV6110(A) Silicon Tuner found!\n", __func__); 69062306a36Sopenharmony_ci goto error_out; 69162306a36Sopenharmony_ci } 69262306a36Sopenharmony_ci } 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci break; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci case 0x1020: { /* Omicom S2 */ 69762306a36Sopenharmony_ci const struct stv6110x_devctl *ctl; 69862306a36Sopenharmony_ci saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); 69962306a36Sopenharmony_ci msleep(50); 70062306a36Sopenharmony_ci saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); 70162306a36Sopenharmony_ci msleep(250); 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci budget->dvb_frontend = dvb_attach(stv090x_attach, 70462306a36Sopenharmony_ci &tt1600_stv090x_config, 70562306a36Sopenharmony_ci &budget->i2c_adap, 70662306a36Sopenharmony_ci STV090x_DEMODULATOR_0); 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci if (budget->dvb_frontend) { 70962306a36Sopenharmony_ci printk(KERN_INFO "budget: Omicom S2 detected\n"); 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci ctl = dvb_attach(stv6110x_attach, 71262306a36Sopenharmony_ci budget->dvb_frontend, 71362306a36Sopenharmony_ci &tt1600_stv6110x_config, 71462306a36Sopenharmony_ci &budget->i2c_adap); 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci if (ctl) { 71762306a36Sopenharmony_ci tt1600_stv090x_config.tuner_init = ctl->tuner_init; 71862306a36Sopenharmony_ci tt1600_stv090x_config.tuner_sleep = ctl->tuner_sleep; 71962306a36Sopenharmony_ci tt1600_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; 72062306a36Sopenharmony_ci tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; 72162306a36Sopenharmony_ci tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; 72262306a36Sopenharmony_ci tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; 72362306a36Sopenharmony_ci tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; 72462306a36Sopenharmony_ci tt1600_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; 72562306a36Sopenharmony_ci tt1600_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; 72662306a36Sopenharmony_ci tt1600_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; 72762306a36Sopenharmony_ci tt1600_stv090x_config.tuner_get_status = ctl->tuner_get_status; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* call the init function once to initialize 73062306a36Sopenharmony_ci tuner's clock output divider and demod's 73162306a36Sopenharmony_ci master clock */ 73262306a36Sopenharmony_ci if (budget->dvb_frontend->ops.init) 73362306a36Sopenharmony_ci budget->dvb_frontend->ops.init(budget->dvb_frontend); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci if (dvb_attach(lnbh24_attach, 73662306a36Sopenharmony_ci budget->dvb_frontend, 73762306a36Sopenharmony_ci &budget->i2c_adap, 73862306a36Sopenharmony_ci LNBH24_PCL | LNBH24_TTX, 73962306a36Sopenharmony_ci LNBH24_TEN, 0x14>>1) == NULL) { 74062306a36Sopenharmony_ci printk(KERN_ERR 74162306a36Sopenharmony_ci "No LNBH24 found!\n"); 74262306a36Sopenharmony_ci goto error_out; 74362306a36Sopenharmony_ci } 74462306a36Sopenharmony_ci } else { 74562306a36Sopenharmony_ci printk(KERN_ERR "%s: No STV6110(A) Silicon Tuner found!\n", __func__); 74662306a36Sopenharmony_ci goto error_out; 74762306a36Sopenharmony_ci } 74862306a36Sopenharmony_ci } 74962306a36Sopenharmony_ci } 75062306a36Sopenharmony_ci break; 75162306a36Sopenharmony_ci } 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci if (budget->dvb_frontend == NULL) { 75462306a36Sopenharmony_ci printk("budget: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n", 75562306a36Sopenharmony_ci budget->dev->pci->vendor, 75662306a36Sopenharmony_ci budget->dev->pci->device, 75762306a36Sopenharmony_ci budget->dev->pci->subsystem_vendor, 75862306a36Sopenharmony_ci budget->dev->pci->subsystem_device); 75962306a36Sopenharmony_ci } else { 76062306a36Sopenharmony_ci if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) 76162306a36Sopenharmony_ci goto error_out; 76262306a36Sopenharmony_ci } 76362306a36Sopenharmony_ci return; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_cierror_out: 76662306a36Sopenharmony_ci printk("budget: Frontend registration failed!\n"); 76762306a36Sopenharmony_ci dvb_frontend_detach(budget->dvb_frontend); 76862306a36Sopenharmony_ci budget->dvb_frontend = NULL; 76962306a36Sopenharmony_ci return; 77062306a36Sopenharmony_ci} 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_cistatic int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) 77362306a36Sopenharmony_ci{ 77462306a36Sopenharmony_ci struct budget *budget = NULL; 77562306a36Sopenharmony_ci int err; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci budget = kmalloc(sizeof(struct budget), GFP_KERNEL); 77862306a36Sopenharmony_ci if( NULL == budget ) { 77962306a36Sopenharmony_ci return -ENOMEM; 78062306a36Sopenharmony_ci } 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget); 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci dev->ext_priv = budget; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr); 78762306a36Sopenharmony_ci if (err) { 78862306a36Sopenharmony_ci printk("==> failed\n"); 78962306a36Sopenharmony_ci kfree (budget); 79062306a36Sopenharmony_ci return err; 79162306a36Sopenharmony_ci } 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci budget->dvb_adapter.priv = budget; 79462306a36Sopenharmony_ci frontend_init(budget); 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci ttpci_budget_init_hooks(budget); 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci return 0; 79962306a36Sopenharmony_ci} 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_cistatic int budget_detach (struct saa7146_dev* dev) 80262306a36Sopenharmony_ci{ 80362306a36Sopenharmony_ci struct budget *budget = dev->ext_priv; 80462306a36Sopenharmony_ci int err; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci if (budget->dvb_frontend) { 80762306a36Sopenharmony_ci dvb_unregister_frontend(budget->dvb_frontend); 80862306a36Sopenharmony_ci dvb_frontend_detach(budget->dvb_frontend); 80962306a36Sopenharmony_ci } 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci err = ttpci_budget_deinit (budget); 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci kfree (budget); 81462306a36Sopenharmony_ci dev->ext_priv = NULL; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci return err; 81762306a36Sopenharmony_ci} 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_cistatic struct saa7146_extension budget_extension; 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ciMAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT); 82262306a36Sopenharmony_ciMAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT); 82362306a36Sopenharmony_ciMAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); 82462306a36Sopenharmony_ciMAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); 82562306a36Sopenharmony_ciMAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT); 82662306a36Sopenharmony_ciMAKE_BUDGET_INFO(tt1600, "TT-Budget S2-1600 PCI", BUDGET_TT); 82762306a36Sopenharmony_ciMAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY); 82862306a36Sopenharmony_ciMAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY); 82962306a36Sopenharmony_ciMAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY); 83062306a36Sopenharmony_ciMAKE_BUDGET_INFO(fsact1, "Fujitsu Siemens Activy Budget-T PCI (rev AL/ALPS TDHD1-204A)", BUDGET_FS_ACTIVY); 83162306a36Sopenharmony_ciMAKE_BUDGET_INFO(omicom, "Omicom S2 PCI", BUDGET_TT); 83262306a36Sopenharmony_ciMAKE_BUDGET_INFO(sylt, "Philips Semi Sylt PCI", BUDGET_TT_HW_DISEQC); 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_cistatic const struct pci_device_id pci_tbl[] = { 83562306a36Sopenharmony_ci MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003), 83662306a36Sopenharmony_ci MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004), 83762306a36Sopenharmony_ci MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005), 83862306a36Sopenharmony_ci MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), 83962306a36Sopenharmony_ci MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016), 84062306a36Sopenharmony_ci MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018), 84162306a36Sopenharmony_ci MAKE_EXTENSION_PCI(tt1600, 0x13c2, 0x101c), 84262306a36Sopenharmony_ci MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60), 84362306a36Sopenharmony_ci MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61), 84462306a36Sopenharmony_ci MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60), 84562306a36Sopenharmony_ci MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61), 84662306a36Sopenharmony_ci MAKE_EXTENSION_PCI(omicom, 0x14c4, 0x1020), 84762306a36Sopenharmony_ci MAKE_EXTENSION_PCI(sylt, 0x1131, 0x4f52), 84862306a36Sopenharmony_ci { 84962306a36Sopenharmony_ci .vendor = 0, 85062306a36Sopenharmony_ci } 85162306a36Sopenharmony_ci}; 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, pci_tbl); 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_cistatic struct saa7146_extension budget_extension = { 85662306a36Sopenharmony_ci .name = "budget dvb", 85762306a36Sopenharmony_ci .flags = SAA7146_USE_I2C_IRQ, 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci .module = THIS_MODULE, 86062306a36Sopenharmony_ci .pci_tbl = pci_tbl, 86162306a36Sopenharmony_ci .attach = budget_attach, 86262306a36Sopenharmony_ci .detach = budget_detach, 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci .irq_mask = MASK_10, 86562306a36Sopenharmony_ci .irq_func = ttpci_budget_irq10_handler, 86662306a36Sopenharmony_ci}; 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_cistatic int __init budget_init(void) 86962306a36Sopenharmony_ci{ 87062306a36Sopenharmony_ci return saa7146_register_extension(&budget_extension); 87162306a36Sopenharmony_ci} 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_cistatic void __exit budget_exit(void) 87462306a36Sopenharmony_ci{ 87562306a36Sopenharmony_ci saa7146_unregister_extension(&budget_extension); 87662306a36Sopenharmony_ci} 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_cimodule_init(budget_init); 87962306a36Sopenharmony_cimodule_exit(budget_exit); 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 88262306a36Sopenharmony_ciMODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others"); 88362306a36Sopenharmony_ciMODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB cards by Siemens, Technotrend, Hauppauge"); 884