Commit 919243ea authored by Michael Hunold's avatar Michael Hunold Committed by Linus Torvalds

[PATCH] dvb: follow changes in dvb-ttpci and budget drivers

- [DVB] dvb-ttpci, budget: updated to fix problems with some CAMs on KNC1
  cards

- [DVB] dvb-ttpci, budget: make needlessly global code static, whitespace
  and newline cleanups, thanks to Adrian Bunk <bunk@stusta.de>

- [DVB] dvb-ttpci, budget: follow frontend changes in driver

- [DVB] dvb-ttpci, budget: fix drivers to use new
  wait_for_debi_done(...,nobusywait) routine.
Signed-off-by: default avatarMichael Hunold <hunold@linuxtv.org>
Signed-off-by: default avatarAdrian Bunk <bunk@stusta.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f569744d
......@@ -94,7 +94,16 @@ MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
static void restart_feeds(struct av7110 *av7110);
int av7110_num = 0;
static int av7110_num = 0;
#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
{\
if (fe_func != NULL) { \
av7110_copy = fe_func; \
fe_func = av7110_func; \
} \
}
static void init_av7110_av(struct av7110 *av7110)
{
......@@ -259,15 +268,15 @@ void av7110_unregister_irc_handler(void (*func)(u32))
irc_handler = NULL;
}
void run_handlers(unsigned long ircom)
static void run_handlers(unsigned long ircom)
{
if (irc_handler != NULL)
(*irc_handler)((u32) ircom);
}
DECLARE_TASKLET(irtask,run_handlers,0);
static DECLARE_TASKLET(irtask, run_handlers, 0);
void IR_handle(struct av7110 *av7110, u32 ircom)
static void IR_handle(struct av7110 *av7110, u32 ircom)
{
dprintk(4, "ircommand = %08x\n", ircom);
irtask.data = (unsigned long) ircom;
......@@ -572,7 +581,7 @@ static void gpioirq (unsigned long data)
wake_up(&cibuf->queue);
iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
saa7146_wait_for_debi_done(av7110->dev);
saa7146_wait_for_debi_done(av7110->dev, 0);
saa7146_write(av7110->dev, IER,
saa7146_read(av7110->dev, IER) | MASK_19 );
if (len < 5)
......@@ -610,7 +619,7 @@ static void gpioirq (unsigned long data)
dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
saa7146_wait_for_debi_done(av7110->dev);
saa7146_wait_for_debi_done(av7110->dev, 0);
saa7146_write(av7110->dev, IER,
saa7146_read(av7110->dev, IER) | MASK_19 );
......@@ -637,7 +646,7 @@ static void gpioirq (unsigned long data)
memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
av7110->bmpp+=len;
av7110->bmplen-=len;
saa7146_wait_for_debi_done(av7110->dev);
saa7146_wait_for_debi_done(av7110->dev, 0);
saa7146_write(av7110->dev, IER,
saa7146_read(av7110->dev, IER) | MASK_19 );
if (len < 5)
......@@ -659,7 +668,7 @@ static void gpioirq (unsigned long data)
case DATA_TS_RECORD:
case DATA_PES_RECORD:
saa7146_wait_for_debi_done(av7110->dev);
saa7146_wait_for_debi_done(av7110->dev, 0);
saa7146_write(av7110->dev, IER,
saa7146_read(av7110->dev, IER) | MASK_19);
irdebi(av7110, DEBISWAB, DPRAM_BASE+rxbuf, 0, len);
......@@ -667,7 +676,7 @@ static void gpioirq (unsigned long data)
return;
case DATA_DEBUG_MESSAGE:
saa7146_wait_for_debi_done(av7110->dev);
saa7146_wait_for_debi_done(av7110->dev, 0);
if (!len || len>0xff) {
iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
break;
......@@ -1090,71 +1099,42 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
* SEC device file operations
******************************************************************************/
static int av7110_diseqc_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
{
struct av7110 *av7110 = fe->before_after_data;
dprintk(4, "%p\n", av7110);
static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
switch (cmd) {
case FE_SET_TONE:
switch ((fe_sec_tone_mode_t) arg) {
switch (tone) {
case SEC_TONE_ON:
Set22K(av7110, 1);
break;
case SEC_TONE_OFF:
Set22K(av7110, 0);
break;
default:
return -EINVAL;
};
break;
case FE_DISEQC_SEND_MASTER_CMD:
{
struct dvb_diseqc_master_cmd *cmd = arg;
av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
break;
}
case FE_DISEQC_SEND_BURST:
av7110_diseqc_send(av7110, 0, NULL, (unsigned long) arg);
break;
default:
return -EOPNOTSUPP;
};
return 0;
}
static void av7110_before_after_tune (fe_status_t s, void *data)
static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
{
struct av7110 *av7110 = data;
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
dprintk(4, "%p\n", av7110);
av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
av7110->fe_synced = (s & FE_HAS_LOCK) ? 1 : 0;
return 0;
}
if (av7110->playing)
return;
static int av7110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
if (down_interruptible(&av7110->pid_mutex))
return;
av7110_diseqc_send(av7110, 0, NULL, minicmd);
if (av7110->fe_synced) {
SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
av7110->pids[DMX_PES_AUDIO],
av7110->pids[DMX_PES_TELETEXT], 0,
av7110->pids[DMX_PES_PCR]);
av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
} else {
SetPIDs(av7110, 0, 0, 0, 0, 0);
av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, FlushTSQueue, 0);
}
up(&av7110->pid_mutex);
return 0;
}
......@@ -1170,15 +1150,6 @@ static int av7110_register(struct av7110 *av7110)
av7110->registered=1;
dvb_add_frontend_notifier (av7110->dvb_adapter,
av7110_before_after_tune, av7110);
/**
* init DiSEqC stuff
*/
dvb_add_frontend_ioctls (av7110->dvb_adapter,
av7110_diseqc_ioctl, NULL, av7110);
dvbdemux->priv = (void *) av7110;
for (i=0; i<32; i++)
......@@ -1252,12 +1223,7 @@ static void dvb_unregister(struct av7110 *av7110)
dvb_dmxdev_release(&av7110->dmxdev);
dvb_dmx_release(&av7110->demux);
dvb_remove_frontend_notifier (av7110->dvb_adapter,
av7110_before_after_tune);
dvb_remove_frontend_ioctls (av7110->dvb_adapter,
av7110_diseqc_ioctl, NULL);
if (av7110->fe != NULL) dvb_unregister_frontend(av7110->fe);
dvb_unregister_device(av7110->osd_dev);
av7110_av_unregister(av7110);
av7110_ca_unregister(av7110);
......@@ -1280,6 +1246,7 @@ int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
}
#if 0
u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
{
u8 mm1[] = {0x00};
......@@ -1296,6 +1263,7 @@ u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
return mm2[0];
}
#endif
/****************************************************************************
* INITIALIZATION
......@@ -1408,28 +1376,532 @@ static int get_firmware(struct av7110* av7110)
#endif
static int client_register(struct i2c_client *client)
static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct saa7146_dev *dev = (struct saa7146_dev*)i2c_get_adapdata(client->adapter);
struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
u8 pwr = 0;
u8 buf[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
u32 div = (params->frequency + 479500) / 125;
if (params->frequency > 2000000) pwr = 3;
else if (params->frequency > 1800000) pwr = 2;
else if (params->frequency > 1600000) pwr = 1;
else if (params->frequency > 1200000) pwr = 0;
else if (params->frequency >= 1100000) pwr = 1;
else pwr = 2;
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = ((div & 0x18000) >> 10) | 0x95;
buf[3] = (pwr << 6) | 0x30;
// NOTE: since we're using a prescaler of 2, we set the
// divisor frequency to 62.5kHz and divide by 125 above
if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
static struct ves1x93_config alps_bsrv2_config = {
.demod_address = 0x08,
.xin = 90100000UL,
.invert_pwm = 0,
.pll_set = alps_bsrv2_pll_set,
};
static u8 alps_bsru6_inittab[] = {
0x01, 0x15,
0x02, 0x30,
0x03, 0x00,
0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
0x06, 0x40, /* DAC not used, set to high impendance mode */
0x07, 0x00, /* DAC LSB */
0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
0x09, 0x00, /* FIFO */
0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
0x18, 0x00,
0x19, 0x00,
0x1a, 0x00,
0x1f, 0x50,
0x20, 0x00,
0x21, 0x00,
0x22, 0x00,
0x23, 0x00,
0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
0x29, 0x1e, // 1/2 threshold
0x2a, 0x14, // 2/3 threshold
0x2b, 0x0f, // 3/4 threshold
0x2c, 0x09, // 5/6 threshold
0x2d, 0x05, // 7/8 threshold
0x2e, 0x01,
0x31, 0x1f, // test all FECs
0x32, 0x19, // viterbi and synchro search
0x33, 0xfc, // rs control
0x34, 0x93, // error control
0x0f, 0x52,
0xff, 0xff
};
static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
{
u8 aclk = 0;
u8 bclk = 0;
if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
stv0299_writereg (fe, 0x13, aclk);
stv0299_writereg (fe, 0x14, bclk);
stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff);
stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
/* fixme: check for "type" (ie. frontend type) */
if (client->driver->command)
return client->driver->command(client, FE_REGISTER, av7110->dvb_adapter);
return 0;
}
static int client_unregister(struct i2c_client *client)
static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct saa7146_dev *dev = (struct saa7146_dev*)i2c_get_adapdata(client->adapter);
struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
int ret;
u8 data[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
if ((params->frequency < 950000) || (params->frequency > 2150000))
return -EINVAL;
div = (params->frequency + (125 - 1)) / 125; // round correctly
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
data[3] = 0xC4;
if (params->frequency > 1530000) data[3] = 0xc0;
ret = i2c_transfer (&av7110->i2c_adap, &msg, 1);
if (ret != 1)
return -EIO;
return 0;
}
static struct stv0299_config alps_bsru6_config = {
.demod_address = 0x68,
.inittab = alps_bsru6_inittab,
.mclk = 88000000UL,
.invert = 1,
.enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100,
.set_symbol_rate = alps_bsru6_set_symbol_rate,
.pll_set = alps_bsru6_pll_set,
};
static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
u32 div;
u8 data[4];
struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
div = (params->frequency + 35937500 + 31250) / 62500;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x85 | ((div >> 10) & 0x60);
data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
static struct ves1820_config alps_tdbe2_config = {
.demod_address = 0x09,
.xin = 57840000UL,
.invert = 1,
.selagc = VES1820_SELAGC_SIGNAMPERR,
.pll_set = alps_tdbe2_pll_set,
};
static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
u32 div;
u8 data[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
div = params->frequency / 125;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x8e;
data[3] = 0x00;
if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
static struct tda8083_config grundig_29504_451_config = {
.demod_address = 0x68,
.pll_set = grundig_29504_451_pll_set,
};
static int philips_cd1516_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
u32 div;
u32 f = params->frequency;
u8 data[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
div = (f + 36125000 + 31250) / 62500;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x8e;
data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
static struct ves1820_config philips_cd1516_config = {
.demod_address = 0x09,
.xin = 57840000UL,
.invert = 1,
.selagc = VES1820_SELAGC_SIGNAMPERR,
.pll_set = philips_cd1516_pll_set,
};
static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
u32 div, pwr;
u8 data[4];
struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
div = (params->frequency + 36200000) / 166666;
if (params->frequency <= 782000000)
pwr = 1;
else
pwr = 2;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x85;
data[3] = pwr << 6;
if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
return request_firmware(fw, name, &av7110->dev->pci->dev);
}
static struct sp8870_config alps_tdlb7_config = {
.demod_address = 0x71,
.pll_set = alps_tdlb7_pll_set,
.request_firmware = alps_tdlb7_request_firmware,
};
static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
u32 div;
u8 data[4];
struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
int i;
// this calculation does not match the TDA6405TS datasheet!
div = (params->frequency + 36150000 + 31250) / 62500;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0xce; // this value does not match the TDA6405TS datasheet!
if (params->frequency < 45000000)
return -EINVAL;
else if (params->frequency < 137000000)
data[3] = 0x01;
else if (params->frequency < 403000000)
data[3] = 0x02;
else if (params->frequency < 860000000)
data[3] = 0x04;
else
return -EINVAL;
stv0297_enable_plli2c(fe);
if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) {
printk("nexusca: pll transfer failed!\n");
return -EIO;
}
// wait for PLL lock
for(i=0; i< 20; i++) {
stv0297_enable_plli2c(fe);
if (i2c_transfer (&av7110->i2c_adap, &readmsg, 1) == 1)
if (data[0] & 0x40) break;
msleep(10);
}
/* fixme: check for "type" (ie. frontend type) */
if (client->driver->command)
return client->driver->command(client, FE_UNREGISTER, av7110->dvb_adapter);
return 0;
}
static struct stv0297_config nexusca_stv0297_config = {
.demod_address = 0x1C,
.pll_set = nexusca_stv0297_pll_set,
};
static void av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
{
msleep (50);
av7110->fe_synced = (status & FE_HAS_LOCK) ? 1 : 0;
if (av7110->playing)
return;
if (down_interruptible(&av7110->pid_mutex))
return;
if (av7110->fe_synced) {
SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
av7110->pids[DMX_PES_AUDIO],
av7110->pids[DMX_PES_TELETEXT], 0,
av7110->pids[DMX_PES_PCR]);
av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
} else {
SetPIDs(av7110, 0, 0, 0, 0, 0);
av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, FlushTSQueue, 0);
}
av7110->fe_status = status;
up(&av7110->pid_mutex);
}
static int av7110_fe_init(struct dvb_frontend* fe)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
av7110_fe_lock_fix(av7110, 0);
return av7110->fe_init(fe);
}
static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
int ret;
/* call the real implementation */
ret = av7110->fe_read_status(fe, status);
if (ret)
return ret;
if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK)) {
av7110_fe_lock_fix(av7110, *status);
}
return 0;
}
static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
av7110_fe_lock_fix(av7110, 0);
return av7110->fe_diseqc_reset_overload(fe);
}
static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
av7110_fe_lock_fix(av7110, 0);
return av7110->fe_diseqc_send_master_cmd(fe, cmd);
}
static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
av7110_fe_lock_fix(av7110, 0);
return av7110->fe_diseqc_send_burst(fe, minicmd);
}
static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
av7110_fe_lock_fix(av7110, 0);
return av7110->fe_set_tone(fe, tone);
}
static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
av7110_fe_lock_fix(av7110, 0);
return av7110->fe_set_voltage(fe, voltage);
}
static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned int cmd)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
av7110_fe_lock_fix(av7110, 0);
return av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
}
static u8 read_pwm(struct av7110* av7110)
{
u8 b = 0xff;
u8 pwm;
struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
{ .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
pwm = 0x48;
return pwm;
}
static void frontend_init(struct av7110 *av7110)
{
if (av7110->dev->pci->subsystem_vendor == 0x110a) {
switch(av7110->dev->pci->subsystem_device) {
case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap, read_pwm(av7110));
if (av7110->fe)
break;
break;
}
} else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
switch(av7110->dev->pci->subsystem_device) {
case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
// try the ALPS BSRV2 first of all
av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
if (av7110->fe) {
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
break;
}
// try the ALPS BSRU6 now
av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap);
if (av7110->fe) {
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
break;
}
// Try the grundig 29504-451
av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
if (av7110->fe) {
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
break;
}
break;
case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
// ALPS TDLB7
av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
if (av7110->fe)
break;
break;
case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
if (av7110->fe)
break;
break;
case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap, 0x7b);
if (av7110->fe) {
/* tuner on this needs a slower i2c bus speed */
av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
break;
}
}
}
if (av7110->fe == NULL) {
printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
av7110->dev->pci->vendor,
av7110->dev->pci->device,
av7110->dev->pci->subsystem_vendor,
av7110->dev->pci->subsystem_device);
} else {
FE_FUNC_OVERRIDE(av7110->fe->ops->init, av7110->fe_init, av7110_fe_init);
FE_FUNC_OVERRIDE(av7110->fe->ops->read_status, av7110->fe_read_status, av7110_fe_read_status);
FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
FE_FUNC_OVERRIDE(av7110->fe->ops->set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
FE_FUNC_OVERRIDE(av7110->fe->ops->set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
if (dvb_register_frontend(av7110->dvb_adapter, av7110->fe)) {
printk("av7110: Frontend registration failed!\n");
if (av7110->fe->ops->release)
av7110->fe->ops->release(av7110->fe);
av7110->fe = NULL;
}
}
}
static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext)
{
struct av7110 *av7110 = NULL;
......@@ -1446,7 +1918,7 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
memset(av7110, 0, sizeof(struct av7110));
av7110->card_name = (char*)pci_ext->ext_priv;
av7110->dev=(struct saa7146_dev *)dev;
av7110->dev = dev;
dev->ext_priv = av7110;
if ((ret = get_firmware(av7110))) {
......@@ -1460,15 +1932,11 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
get recognized before the main driver is fully loaded */
saa7146_write(dev, GPIO_CTRL, 0x500000);
av7110->i2c_adap = (struct i2c_adapter) {
.client_register = client_register,
.client_unregister = client_unregister,
#ifdef I2C_ADAP_CLASS_TV_DIGITAL
.class = I2C_ADAP_CLASS_TV_DIGITAL,
av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
#else
.class = I2C_CLASS_TV_DIGITAL,
av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
#endif
};
strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
......@@ -1567,6 +2035,9 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
if (ret)
goto err3;
av7110->dvb_adapter->priv = av7110;
frontend_init(av7110);
printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
av7110->device_initialized = 1;
av7110_num++;
......@@ -1663,33 +2134,29 @@ static struct saa7146_pci_extension_data x_var = { \
.ext_priv = x_name, \
.ext = &av7110_extension }
MAKE_AV7110_INFO(fs_1_5, "Siemens cable card PCI rev1.5");
MAKE_AV7110_INFO(fs_1_3, "Siemens/Technotrend/Hauppauge PCI rev1.3");
MAKE_AV7110_INFO(tt_1_6, "Technotrend/Hauppauge PCI rev1.3 or 1.6");
MAKE_AV7110_INFO(tt_2_1, "Technotrend/Hauppauge PCI rev2.1 or 2.2");
MAKE_AV7110_INFO(tt_t, "Technotrend/Hauppauge PCI DVB-T");
MAKE_AV7110_INFO(unkwn0, "Technotrend/Hauppauge PCI rev?(unknown0)?");
MAKE_AV7110_INFO(unkwn1, "Technotrend/Hauppauge PCI rev?(unknown1)?");
MAKE_AV7110_INFO(unkwn2, "Technotrend/Hauppauge PCI rev?(unknown2)?");
MAKE_AV7110_INFO(nexus, "Technotrend/Hauppauge Nexus PCI DVB-S");
MAKE_AV7110_INFO(dvboc11,"Octal/Technotrend DVB-C for iTV");
MAKE_AV7110_INFO(tts_1_X, "Technotrend/Hauppauge WinTV DVB-S rev1.X");
MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV Nexus-S rev1.3");
MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(fs_1_5, 0x110a, 0xffff),
MAKE_EXTENSION_PCI(fs_1_5, 0x110a, 0x0000),
MAKE_EXTENSION_PCI(fs_1_3, 0x13c2, 0x0000),
MAKE_EXTENSION_PCI(unkwn0, 0x13c2, 0x1002),
MAKE_EXTENSION_PCI(tt_1_6, 0x13c2, 0x0001),
MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0002),
MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0003),
MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0004),
MAKE_EXTENSION_PCI(tt_1_6, 0x13c2, 0x0006),
MAKE_EXTENSION_PCI(tt_t, 0x13c2, 0x0008),
MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x1102),
MAKE_EXTENSION_PCI(unkwn1, 0xffc2, 0x0000),
MAKE_EXTENSION_PCI(unkwn2, 0x00a1, 0x00a1),
MAKE_EXTENSION_PCI(nexus, 0x00a1, 0xa1a0),
MAKE_EXTENSION_PCI(dvboc11,0x13c2, 0x000a),
MAKE_EXTENSION_PCI(tts_1_X, 0x13c2, 0x0000),
MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0006), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-S v????
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0008), UNDEFINED CARD */ // TT/Hauppauge WinTV DVB-T v????
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
{
.vendor = 0,
}
......
......@@ -24,6 +24,13 @@
#include "dvb_filter.h"
#include "dvb_net.h"
#include "dvb_ringbuffer.h"
#include "dvb_frontend.h"
#include "ves1820.h"
#include "ves1x93.h"
#include "stv0299.h"
#include "tda8083.h"
#include "sp8870.h"
#include "stv0297.h"
#include <media/saa7146_vv.h>
......@@ -217,6 +224,17 @@ struct av7110 {
unsigned char *bin_root;
unsigned long size_root;
struct dvb_frontend* fe;
fe_status_t fe_status;
int (*fe_init)(struct dvb_frontend* fe);
int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status);
int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe);
int (*fe_diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd);
int (*fe_diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd);
};
......
......@@ -674,7 +674,7 @@ void av7110_p2t_write(u8 const *buf, long int length, u16 pid, struct av7110_p2t
}
int write_ts_header2(u16 pid, u8 *counter, int pes_start, u8 *buf, u8 length)
static int write_ts_header2(u16 pid, u8 *counter, int pes_start, u8 *buf, u8 length)
{
int i;
int c = 0;
......@@ -936,7 +936,7 @@ static ssize_t dvb_audio_write(struct file *file, const char __user *buf,
return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0);
}
u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 };
static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 };
#define MIN_IFRAME 400000
......
......@@ -89,20 +89,20 @@ void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len)
* CI link layer file ops
******************************************************************************/
int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size)
static int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size)
{
dvb_ringbuffer_init(cirbuf, vmalloc(size), size);
dvb_ringbuffer_init(ciwbuf, vmalloc(size), size);
return 0;
}
void ci_ll_flush(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf)
static void ci_ll_flush(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf)
{
dvb_ringbuffer_flush_spinlock_wakeup(cirbuf);
dvb_ringbuffer_flush_spinlock_wakeup(ciwbuf);
}
void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf)
static void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf)
{
vfree(cirbuf->data);
cirbuf->data = NULL;
......@@ -110,7 +110,7 @@ void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf)
ciwbuf->data = NULL;
}
int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file,
static int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file,
int slots, ca_slot_info_t *slot)
{
int i;
......
......@@ -53,10 +53,14 @@ int av7110_debiwrite(struct av7110 *av7110, u32 config,
{
struct saa7146_dev *dev = av7110->dev;
if (count <= 0 || count > 32764)
if (count <= 0 || count > 32764) {
printk("%s: invalid count %d\n", __FUNCTION__, count);
return -1;
if (saa7146_wait_for_debi_done(av7110->dev) < 0)
}
if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
printk("%s: wait_for_debi_done failed\n", __FUNCTION__);
return -1;
}
saa7146_write(dev, DEBI_CONFIG, config);
if (count <= 4) /* immediate transfer */
saa7146_write(dev, DEBI_AD, val);
......@@ -72,10 +76,14 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
struct saa7146_dev *dev = av7110->dev;
u32 result = 0;
if (count > 32764 || count <= 0)
if (count > 32764 || count <= 0) {
printk("%s: invalid count %d\n", __FUNCTION__, count);
return 0;
if (saa7146_wait_for_debi_done(av7110->dev) < 0)
}
if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__);
return 0;
}
saa7146_write(dev, DEBI_AD, av7110->debi_bus);
saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
......@@ -83,7 +91,11 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
saa7146_write(dev, MC2, (2 << 16) | 2);
if (count > 4)
return count;
saa7146_wait_for_debi_done(av7110->dev);
if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__);
return 0;
}
result = saa7146_read(dev, DEBI_AD);
result &= (0xffffffffUL >> ((4 - count) * 8));
return result;
......@@ -240,7 +252,7 @@ int av7110_bootarm(struct av7110 *av7110)
mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
if (saa7146_wait_for_debi_done(av7110->dev)) {
if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
"saa7146_wait_for_debi_done() timed out\n");
return -1;
......@@ -258,7 +270,7 @@ int av7110_bootarm(struct av7110 *av7110)
dprintk(1, "load dpram code\n");
mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
if (saa7146_wait_for_debi_done(av7110->dev)) {
if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
"saa7146_wait_for_debi_done() timed out after loading DRAM\n");
return -1;
......@@ -305,6 +317,8 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
}
}
wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
#ifndef _NOHANDSHAKE
start = jiffies;
while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) {
......@@ -334,6 +348,8 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
#ifdef COM_DEBUG
start = jiffies;
while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) {
......
......@@ -162,7 +162,7 @@ static struct v4l2_audio msp3400_v4l2_audio = {
.capability = V4L2_AUDCAP_STEREO
};
int av7110_dvb_c_switch(struct saa7146_fh *fh)
static int av7110_dvb_c_switch(struct saa7146_fh *fh)
{
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
......@@ -227,7 +227,7 @@ int av7110_dvb_c_switch(struct saa7146_fh *fh)
return 0;
}
int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct saa7146_dev *dev = fh->dev;
struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
......@@ -424,7 +424,7 @@ int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
* INITIALIZATION
****************************************************************************/
struct saa7146_extension_ioctls ioctls[] = {
static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
......@@ -684,7 +684,7 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
.flags = 0,
.stds = &standard[0],
.num_stds = sizeof(standard) / sizeof(struct saa7146_standard),
.num_stds = ARRAY_SIZE(standard),
.std_callback = &std_callback,
.ioctls = &ioctls[0],
......@@ -698,7 +698,7 @@ static struct saa7146_ext_vv av7110_vv_data_c = {
.flags = SAA7146_USE_PORT_B_FOR_VBI,
.stds = &standard[0],
.num_stds = sizeof(standard) / sizeof(struct saa7146_standard),
.num_stds = ARRAY_SIZE(standard),
.std_callback = &std_callback,
.ioctls = &ioctls[0],
......
......@@ -4,6 +4,9 @@
*
* Compiled from various sources by Michael Hunold <michael@mihu.de>
*
* CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
* Andrew de Quincey <adq_dvb@lidskialf.net>
*
* Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
*
* Copyright (C) 1999-2002 Ralph Metzler
......@@ -31,15 +34,34 @@
*/
#include "budget.h"
#include "stv0299.h"
#include "tda10021.h"
#include "tda1004x.h"
#include <media/saa7146_vv.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/spinlock.h>
#include "dvb_ca_en50221.h"
#define DEBICICAM 0x02420000
struct budget_av {
struct budget budget;
struct video_device *vd;
int cur_input;
int has_saa7113;
struct tasklet_struct ciintf_irq_tasklet;
int slot_status;
struct dvb_ca_en50221 ca;
};
int enable_ci = 0;
/****************************************************************************
* INITIALIZATION
****************************************************************************/
......@@ -55,8 +77,10 @@ static u8 i2c_readreg (struct i2c_adapter *i2c, u8 id, u8 reg)
msgs[1].flags = I2C_M_RD;
msgs[0].addr = msgs[1].addr=id/2;
mm1[0] = reg;
msgs[0].len = 1; msgs[1].len = 1;
msgs[0].buf = mm1; msgs[1].buf = mm2;
msgs[0].len = 1;
msgs[1].len = 1;
msgs[0].buf = mm1;
msgs[1].buf = mm2;
i2c_transfer(i2c, msgs, 2);
......@@ -90,6 +114,211 @@ static int i2c_writereg (struct i2c_adapter *i2c, u8 id, u8 reg, u8 val)
return i2c_transfer(i2c, &msgs, 1);
}
static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
int result;
if (slot != 0)
return -EINVAL;
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 0);
if (result == -ETIMEDOUT)
budget_av->slot_status = 0;
return result;
}
static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
int result;
if (slot != 0)
return -EINVAL;
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 0);
if (result == -ETIMEDOUT)
budget_av->slot_status = 0;
return result;
}
static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
int result;
if (slot != 0)
return -EINVAL;
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
if (result == -ETIMEDOUT)
budget_av->slot_status = 0;
return result;
}
static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
int result;
if (slot != 0)
return -EINVAL;
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
if (result == -ETIMEDOUT)
budget_av->slot_status = 0;
return result;
}
static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
if (slot != 0)
return -EINVAL;
dprintk(1, "ciintf_slot_reset\n");
/* reset the card */
saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
msleep(100);
saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
msleep(2000); /* horrendous I know, but its the only way to be absolutely sure without an IRQ line! */
ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
return 0;
}
static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
if (slot != 0)
return -EINVAL;
dprintk(1, "ciintf_slot_shutdown\n");
ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
budget_av->slot_status = 0;
return 0;
}
static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
if (slot != 0)
return -EINVAL;
dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status);
ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
return 0;
}
static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
int cam = 0;
if (slot != 0)
return -EINVAL;
if (!budget_av->slot_status) {
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
udelay(1);
cam = saa7146_read(saa, PSR) & MASK_06;
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
if (cam)
budget_av->slot_status = 1;
} else if (!open) {
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
budget_av->slot_status = 0;
}
if (budget_av->slot_status == 1)
return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
return 0;
}
static int ciintf_init(struct budget_av *budget_av)
{
struct saa7146_dev *saa = budget_av->budget.dev;
int result;
memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221));
/* setup GPIOs */
saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO);
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
/* Reset the card */
saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
msleep(50);
saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
msleep(100);
/* Enable DEBI pins */
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
/* register CI interface */
budget_av->ca.owner = THIS_MODULE;
budget_av->ca.read_attribute_mem = ciintf_read_attribute_mem;
budget_av->ca.write_attribute_mem = ciintf_write_attribute_mem;
budget_av->ca.read_cam_control = ciintf_read_cam_control;
budget_av->ca.write_cam_control = ciintf_write_cam_control;
budget_av->ca.slot_reset = ciintf_slot_reset;
budget_av->ca.slot_shutdown = ciintf_slot_shutdown;
budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
budget_av->ca.data = budget_av;
if ((result = dvb_ca_en50221_init(budget_av->budget.dvb_adapter,
&budget_av->ca, 0, 1)) != 0) {
printk("budget_av: CI interface detected, but initialisation failed.\n");
goto error;
}
// success!
printk("ciintf_init: CI interface initialised\n");
budget_av->budget.ci_present = 1;
return 0;
error:
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
return result;
}
static void ciintf_deinit(struct budget_av *budget_av)
{
struct saa7146_dev *saa = budget_av->budget.dev;
saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
/* release the CA device */
dvb_ca_en50221_release(&budget_av->ca);
/* disable DEBI pins */
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
}
static const u8 saa7113_tab[] = {
0x01, 0x08,
......@@ -165,6 +394,397 @@ static int saa7113_setinput (struct budget_av *budget_av, int input)
}
static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
{
u8 aclk = 0;
u8 bclk = 0;
u8 m1;
aclk = 0xb5;
if (srate < 2000000)
bclk = 0x86;
else if (srate < 5000000)
bclk = 0x89;
else if (srate < 15000000)
bclk = 0x8f;
else if (srate < 45000000)
bclk = 0x95;
m1 = 0x14;
if (srate < 4000000)
m1 = 0x10;
stv0299_writereg(fe, 0x13, aclk);
stv0299_writereg(fe, 0x14, bclk);
stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
stv0299_writereg(fe, 0x0f, 0x80 | m1);
return 0;
}
static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
{
struct budget_av *budget_av = (struct budget_av *) fe->dvb->priv;
u32 div;
u8 buf[4];
struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
if ((params->frequency < 950000) || (params->frequency > 2150000))
return -EINVAL;
div = (params->frequency + (125 - 1)) / 125; // round correctly
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
buf[3] = 0x20;
if (params->u.qpsk.symbol_rate < 4000000)
buf[3] |= 1;
if (params->frequency < 1250000)
buf[3] |= 0;
else if (params->frequency < 1550000)
buf[3] |= 0x40;
else if (params->frequency < 2050000)
buf[3] |= 0x80;
else if (params->frequency < 2150000)
buf[3] |= 0xC0;
if (i2c_transfer(&budget_av->budget.i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
static u8 typhoon_cinergy1200s_inittab[] = {
0x01, 0x15,
0x02, 0x30,
0x03, 0x00,
0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
0x06, 0x40, /* DAC not used, set to high impendance mode */
0x07, 0x00, /* DAC LSB */
0x08, 0x40, /* DiSEqC off */
0x09, 0x00, /* FIFO */
0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
0x18, 0x00,
0x19, 0x00,
0x1a, 0x00,
0x1f, 0x50,
0x20, 0x00,
0x21, 0x00,
0x22, 0x00,
0x23, 0x00,
0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
0x29, 0x1e, // 1/2 threshold
0x2a, 0x14, // 2/3 threshold
0x2b, 0x0f, // 3/4 threshold
0x2c, 0x09, // 5/6 threshold
0x2d, 0x05, // 7/8 threshold
0x2e, 0x01,
0x31, 0x1f, // test all FECs
0x32, 0x19, // viterbi and synchro search
0x33, 0xfc, // rs control
0x34, 0x93, // error control
0x0f, 0x92,
0xff, 0xff
};
static struct stv0299_config typhoon_config = {
.demod_address = 0x68,
.inittab = typhoon_cinergy1200s_inittab,
.mclk = 88000000UL,
.invert = 0,
.enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP0,
.min_delay_ms = 100,
.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
.pll_set = philips_su1278_ty_ci_pll_set,
};
static struct stv0299_config cinergy_1200s_config = {
.demod_address = 0x68,
.inittab = typhoon_cinergy1200s_inittab,
.mclk = 88000000UL,
.invert = 0,
.enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_0,
.volt13_op0_op1 = STV0299_VOLT13_OP0,
.min_delay_ms = 100,
.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
.pll_set = philips_su1278_ty_ci_pll_set,
};
static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct budget *budget = (struct budget *) fe->dvb->priv;
u8 buf[4];
struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
#define TUNER_MUL 62500
u32 div = (params->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL;
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x8e;
buf[3] = (params->frequency < 174500000 ? 0xa1 :
params->frequency < 454000000 ? 0x92 : 0x34);
if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
static struct tda10021_config philips_cu1216_config = {
.demod_address = 0x0c,
.pll_set = philips_cu1216_pll_set,
};
static int philips_tu1216_pll_init(struct dvb_frontend *fe)
{
struct budget *budget = (struct budget *) fe->dvb->priv;
static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len =
sizeof(tu1216_init) };
// setup PLL configuration
if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
msleep(1);
// disable the mc44BC374c (do not check for errors)
tuner_msg.addr = 0x65;
tuner_msg.buf = disable_mc44BC374c;
tuner_msg.len = sizeof(disable_mc44BC374c);
if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) {
i2c_transfer(&budget->i2c_adap, &tuner_msg, 1);
}
return 0;
}
static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct budget *budget = (struct budget *) fe->dvb->priv;
u8 tuner_buf[4];
struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len =
sizeof(tuner_buf) };
int tuner_frequency = 0;
u8 band, cp, filter;
// determine charge pump
tuner_frequency = params->frequency + 36130000;
if (tuner_frequency < 87000000)
return -EINVAL;
else if (tuner_frequency < 130000000)
cp = 3;
else if (tuner_frequency < 160000000)
cp = 5;
else if (tuner_frequency < 200000000)
cp = 6;
else if (tuner_frequency < 290000000)
cp = 3;
else if (tuner_frequency < 420000000)
cp = 5;
else if (tuner_frequency < 480000000)
cp = 6;
else if (tuner_frequency < 620000000)
cp = 3;
else if (tuner_frequency < 830000000)
cp = 5;
else if (tuner_frequency < 895000000)
cp = 7;
else
return -EINVAL;
// determine band
if (params->frequency < 49000000)
return -EINVAL;
else if (params->frequency < 159000000)
band = 1;
else if (params->frequency < 444000000)
band = 2;
else if (params->frequency < 861000000)
band = 4;
else
return -EINVAL;
// setup PLL filter
switch (params->u.ofdm.bandwidth) {
case BANDWIDTH_6_MHZ:
tda1004x_write_byte(fe, 0x0C, 0);
filter = 0;
break;
case BANDWIDTH_7_MHZ:
tda1004x_write_byte(fe, 0x0C, 0);
filter = 0;
break;
case BANDWIDTH_8_MHZ:
tda1004x_write_byte(fe, 0x0C, 0xFF);
filter = 1;
break;
default:
return -EINVAL;
}
// calculate divisor
// ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
// setup tuner buffer
tuner_buf[0] = tuner_frequency >> 8;
tuner_buf[1] = tuner_frequency & 0xff;
tuner_buf[2] = 0xca;
tuner_buf[3] = (cp << 5) | (filter << 3) | band;
if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
msleep(1);
return 0;
}
static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
const struct firmware **fw, char *name)
{
struct budget *budget = (struct budget *) fe->dvb->priv;
return request_firmware(fw, name, &budget->dev->pci->dev);
}
struct tda1004x_config philips_tu1216_config = {
.demod_address = 0x8,
.invert = 1,
.pll_init = philips_tu1216_pll_init,
.pll_set = philips_tu1216_pll_set,
.request_firmware = philips_tu1216_request_firmware,
};
static u8 read_pwm(struct budget_av *budget_av)
{
u8 b = 0xff;
u8 pwm;
struct i2c_msg msg[] = { {.addr = 0x50,.flags = 0,.buf = &b,.len = 1},
{.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1}
};
if ((i2c_transfer(&budget_av->budget.i2c_adap, msg, 2) != 2)
|| (pwm == 0xff))
pwm = 0x48;
return pwm;
}
static void frontend_init(struct budget_av *budget_av)
{
switch (budget_av->budget.dev->pci->subsystem_device) {
case 0x4f56: // Typhoon/KNC1 DVB-S budget (stv0299/Philips SU1278(tsa5059))
budget_av->budget.dvb_frontend =
stv0299_attach(&typhoon_config, &budget_av->budget.i2c_adap);
if (budget_av->budget.dvb_frontend != NULL) {
break;
}
break;
case 0x0020: // KNC1 DVB-C budget (tda10021/Philips CU1216(tua6034))
budget_av->budget.dvb_frontend =
tda10021_attach(&philips_cu1216_config,
&budget_av->budget.i2c_adap, read_pwm(budget_av));
if (budget_av->budget.dvb_frontend != NULL) {
break;
}
break;
case 0x0030: // KNC1 DVB-T budget (tda10046/Philips TU1216(tda6651tt))
budget_av->budget.dvb_frontend =
tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap);
if (budget_av->budget.dvb_frontend != NULL) {
break;
}
break;
case 0x1154: // TerraTec Cinergy 1200 DVB-S (stv0299/Philips SU1278(tsa5059))
budget_av->budget.dvb_frontend =
stv0299_attach(&cinergy_1200s_config, &budget_av->budget.i2c_adap);
if (budget_av->budget.dvb_frontend != NULL) {
break;
}
break;
case 0x1156: // Terratec Cinergy 1200 DVB-C (tda10021/Philips CU1216(tua6034))
budget_av->budget.dvb_frontend =
tda10021_attach(&philips_cu1216_config,
&budget_av->budget.i2c_adap, read_pwm(budget_av));
if (budget_av->budget.dvb_frontend) {
break;
}
break;
case 0x1157: // Terratec Cinergy 1200 DVB-T (tda10046/Philips TU1216(tda6651tt))
budget_av->budget.dvb_frontend =
tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap);
if (budget_av->budget.dvb_frontend) {
break;
}
break;
}
if (budget_av->budget.dvb_frontend == NULL) {
printk("budget_av: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
budget_av->budget.dev->pci->vendor,
budget_av->budget.dev->pci->device,
budget_av->budget.dev->pci->subsystem_vendor,
budget_av->budget.dev->pci->subsystem_device);
} else {
if (dvb_register_frontend
(budget_av->budget.dvb_adapter, budget_av->budget.dvb_frontend)) {
printk("budget-av: Frontend registration failed!\n");
if (budget_av->budget.dvb_frontend->ops->release)
budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend);
budget_av->budget.dvb_frontend = NULL;
}
}
}
static void budget_av_irq(struct saa7146_dev *dev, u32 * isr)
{
struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
dprintk(8, "dev: %p, budget_av: %p\n", dev, budget_av);
if (*isr & MASK_10)
ttpci_budget_irq10_handler(dev, isr);
}
static int budget_av_detach (struct saa7146_dev *dev)
{
struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
......@@ -180,6 +800,11 @@ static int budget_av_detach (struct saa7146_dev *dev)
saa7146_unregister_device (&budget_av->vd, dev);
}
if (budget_av->budget.ci_present)
ciintf_deinit(budget_av);
if (budget_av->budget.dvb_frontend != NULL)
dvb_unregister_frontend(budget_av->budget.dvb_frontend);
err = ttpci_budget_deinit (&budget_av->budget);
kfree (budget_av);
......@@ -189,28 +814,24 @@ static int budget_av_detach (struct saa7146_dev *dev)
static struct saa7146_ext_vv vv_data;
static int budget_av_attach (struct saa7146_dev* dev,
struct saa7146_pci_extension_data *info)
static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
{
struct budget_av *budget_av;
struct budget_info *bi = info->ext_priv;
u8 *mac;
int err;
dprintk(2, "dev: %p\n", dev);
if (bi->type != BUDGET_KNC1 && bi->type != BUDGET_CIN1200) {
return -ENODEV;
}
if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL)))
return -ENOMEM;
memset(budget_av, 0, sizeof(struct budget_av));
budget_av->budget.ci_present = 0;
dev->ext_priv = budget_av;
if ((err = ttpci_budget_init(&budget_av->budget, dev, info))) {
if ((err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE))) {
kfree(budget_av);
return err;
}
......@@ -220,8 +841,6 @@ static int budget_av_attach (struct saa7146_dev* dev,
saa7146_write(dev, DD1_INIT, 0x07000600);
saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
//test_knc_ci(av7110);
saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
msleep(500);
......@@ -234,9 +853,7 @@ static int budget_av_attach (struct saa7146_dev* dev,
return err;
}
if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1",
VFL_TYPE_GRABBER)))
{
if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
/* fixme: proper cleanup here */
ERR(("cannot register capture v4l2 device.\n"));
return err;
......@@ -261,15 +878,20 @@ static int budget_av_attach (struct saa7146_dev* dev,
printk("KNC1-%d: Could not read MAC from KNC1 card\n",
budget_av->budget.dvb_adapter->num);
memset(mac, 0, 6);
}
else
} else {
printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
budget_av->budget.dvb_adapter->num,
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return 0;
}
budget_av->budget.dvb_adapter->priv = budget_av;
frontend_init(budget_av);
if (enable_ci)
ciintf_init(budget_av);
return 0;
}
#define KNC1_INPUTS 2
static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
......@@ -290,12 +912,9 @@ static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct saa7146_dev *dev = fh->dev;
struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
/*
struct saa7146_vv *vv = dev->vv_data;
*/
switch(cmd) {
case VIDIOC_ENUMINPUT:
{
case VIDIOC_ENUMINPUT:{
struct v4l2_input *i = arg;
dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
......@@ -305,8 +924,7 @@ static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
return 0;
}
case VIDIOC_G_INPUT:
{
case VIDIOC_G_INPUT:{
int *input = (int *)arg;
*input = budget_av->cur_input;
......@@ -314,8 +932,7 @@ static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
dprintk(1, "VIDIOC_G_INPUT %d.\n", *input);
return 0;
}
case VIDIOC_S_INPUT:
{
case VIDIOC_S_INPUT:{
int input = *(int *)arg;
dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
return saa7113_setinput (budget_av, input);
......@@ -327,17 +944,15 @@ static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
}
static struct saa7146_standard standard[] = {
{
.name = "PAL", .id = V4L2_STD_PAL,
{.name = "PAL",.id = V4L2_STD_PAL,
.v_offset = 0x17, .v_field = 288,
.h_offset = 0x14, .h_pixels = 680,
.v_max_out = 576, .h_max_out = 768
}, {
.name = "NTSC", .id = V4L2_STD_NTSC,
.v_max_out = 576,.h_max_out = 768 },
{.name = "NTSC",.id = V4L2_STD_NTSC,
.v_offset = 0x16, .v_field = 240,
.h_offset = 0x06, .h_pixels = 708,
.v_max_out = 480, .h_max_out = 640,
}
.v_max_out = 480,.h_max_out = 640, },
};
static struct saa7146_ext_vv vv_data = {
......@@ -350,17 +965,22 @@ static struct saa7146_ext_vv vv_data = {
.ioctl = av_ioctl,
};
static struct saa7146_extension budget_extension;
MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1);
MAKE_BUDGET_INFO(cin1200, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200);
MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
static struct pci_device_id pci_tbl [] = {
MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56),
MAKE_EXTENSION_PCI(cin1200, 0x153b, 0x1154),
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
{
.vendor = 0,
}
......@@ -377,7 +997,7 @@ static struct saa7146_extension budget_extension = {
.detach = budget_av_detach,
.irq_mask = MASK_10,
.irq_func = ttpci_budget_irq10_handler,
.irq_func = budget_av_irq,
};
static int __init budget_av_init(void)
......@@ -396,5 +1016,6 @@ module_exit(budget_av_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
"budget PCI DVB w/ analog input (e.g. the KNC cards)");
"budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");
module_param_named(enable_ci, enable_ci, int, 0644);
MODULE_PARM_DESC(enable_ci, "Turn on/off CI module (default:off).");
......@@ -39,6 +39,8 @@
#include <linux/spinlock.h>
#include "dvb_ca_en50221.h"
#include "stv0299.h"
#include "tda1004x.h"
#define DEBIADDR_IR 0x1234
#define DEBIADDR_CICONTROL 0x0000
......@@ -64,72 +66,11 @@ struct budget_ci {
struct input_dev input_dev;
struct tasklet_struct msp430_irq_tasklet;
struct tasklet_struct ciintf_irq_tasklet;
spinlock_t debilock;
int slot_status;
struct dvb_ca_en50221 ca;
char ir_dev_name[50];
};
static u32 budget_debiread (struct budget_ci* budget_ci, u32 config, int addr, int count)
{
struct saa7146_dev *saa = budget_ci->budget.dev;
u32 result = 0;
unsigned long flags;
if (count > 4 || count <= 0)
return 0;
spin_lock_irqsave(&budget_ci->debilock, flags);
if (saa7146_wait_for_debi_done(saa) < 0) {
spin_unlock_irqrestore(&budget_ci->debilock, flags);
return 0;
}
saa7146_write (saa, DEBI_COMMAND,
(count << 17) | 0x10000 | (addr & 0xffff));
saa7146_write(saa, DEBI_CONFIG, config);
saa7146_write(saa, DEBI_PAGE, 0);
saa7146_write(saa, MC2, (2 << 16) | 2);
saa7146_wait_for_debi_done(saa);
result = saa7146_read(saa, 0x88);
result &= (0xffffffffUL >> ((4 - count) * 8));
spin_unlock_irqrestore(&budget_ci->debilock, flags);
return result;
}
static u8 budget_debiwrite (struct budget_ci* budget_ci, u32 config, int addr, int count, u32 value)
{
struct saa7146_dev *saa = budget_ci->budget.dev;
unsigned long flags;
if (count > 4 || count <= 0)
return 0;
spin_lock_irqsave(&budget_ci->debilock, flags);
if (saa7146_wait_for_debi_done(saa) < 0) {
spin_unlock_irqrestore(&budget_ci->debilock, flags);
return 0;
}
saa7146_write (saa, DEBI_COMMAND,
(count << 17) | 0x00000 | (addr & 0xffff));
saa7146_write(saa, DEBI_CONFIG, config);
saa7146_write(saa, DEBI_PAGE, 0);
saa7146_write(saa, DEBI_AD, value);
saa7146_write(saa, MC2, (2 << 16) | 2);
saa7146_wait_for_debi_done(saa);
spin_unlock_irqrestore(&budget_ci->debilock, flags);
return 0;
}
/* from reading the following remotes:
Zenith Universal 7 / TV Mode 807 / VCR Mode 837
Hauppauge (from NOVA-CI-s box product)
......@@ -206,7 +147,8 @@ static void msp430_ir_interrupt (unsigned long data)
{
struct budget_ci *budget_ci = (struct budget_ci*) data;
struct input_dev *dev = &budget_ci->input_dev;
unsigned int code = budget_debiread(budget_ci, DEBINOSWAP, DEBIADDR_IR, 2) >> 8;
unsigned int code =
ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
if (code & 0x40) {
code &= 0x3f;
......@@ -221,8 +163,7 @@ static void msp430_ir_interrupt (unsigned long data)
}
if (!key_map[code]) {
printk ("DVB (%s): no key for %02x!\n",
__FUNCTION__, code);
printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code);
return;
}
......@@ -281,79 +222,98 @@ static void msp430_ir_deinit (struct budget_ci *budget_ci)
input_unregister_device(dev);
}
static int ciintf_read_attribute_mem(struct dvb_ca_en50221* ca, int slot, int address) {
static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
{
struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
if (slot != 0) return -EINVAL;
if (slot != 0)
return -EINVAL;
return budget_debiread(budget_ci, DEBICICAM, DEBIADDR_ATTR | (address & 0xfff), 1);
return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
}
static int ciintf_write_attribute_mem(struct dvb_ca_en50221* ca, int slot, int address, u8 value) {
static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
{
struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
if (slot != 0) return -EINVAL;
if (slot != 0)
return -EINVAL;
return budget_debiwrite(budget_ci, DEBICICAM, DEBIADDR_ATTR | (address & 0xfff), 1, value);
return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
}
static int ciintf_read_cam_control(struct dvb_ca_en50221* ca, int slot, u8 address) {
static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
{
struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
if (slot != 0) return -EINVAL;
if (slot != 0)
return -EINVAL;
return budget_debiread(budget_ci, DEBICICAM, DEBIADDR_IO | (address & 3), 1);
return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
DEBIADDR_IO | (address & 3), 1, 1, 0);
}
static int ciintf_write_cam_control(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value) {
static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
{
struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
if (slot != 0) return -EINVAL;
if (slot != 0)
return -EINVAL;
return budget_debiwrite(budget_ci, DEBICICAM, DEBIADDR_IO | (address & 3), 1, value);
return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
DEBIADDR_IO | (address & 3), 1, value, 1, 0);
}
static int ciintf_slot_reset(struct dvb_ca_en50221* ca, int slot) {
static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
struct saa7146_dev *saa = budget_ci->budget.dev;
if (slot != 0) return -EINVAL;
if (slot != 0)
return -EINVAL;
// trigger on RISING edge during reset so we know when READY is re-asserted
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
budget_ci->slot_status = SLOTSTATUS_RESET;
budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0);
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
msleep(1);
budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET);
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
CICONTROL_RESET, 1, 0);
saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
return 0;
}
static int ciintf_slot_shutdown(struct dvb_ca_en50221* ca, int slot) {
static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
{
struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
struct saa7146_dev *saa = budget_ci->budget.dev;
if (slot != 0) return -EINVAL;
if (slot != 0)
return -EINVAL;
saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
return 0;
}
static int ciintf_slot_ts_enable(struct dvb_ca_en50221* ca, int slot) {
static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
{
struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
struct saa7146_dev *saa = budget_ci->budget.dev;
int tmp;
if (slot != 0) return -EINVAL;
if (slot != 0)
return -EINVAL;
saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
tmp = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1);
budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, tmp | CICONTROL_ENABLETS);
tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
tmp | CICONTROL_ENABLETS, 1, 0);
ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
return 0;
......@@ -367,10 +327,11 @@ static void ciintf_interrupt (unsigned long data)
unsigned int flags;
// ensure we don't get spurious IRQs during initialisation
if (!budget_ci->budget.ci_present) return;
if (!budget_ci->budget.ci_present)
return;
// read the CAM status
flags = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1);
flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
if (flags & CICONTROL_CAMDETECT) {
// GPIO should be set to trigger on falling edge if a CAM is present
......@@ -379,7 +340,8 @@ static void ciintf_interrupt (unsigned long data)
if (budget_ci->slot_status & SLOTSTATUS_NONE) {
// CAM insertion IRQ
budget_ci->slot_status = SLOTSTATUS_PRESENT;
dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, DVB_CA_EN50221_CAMCHANGE_INSERTED);
dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
DVB_CA_EN50221_CAMCHANGE_INSERTED);
} else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
// CAM ready (reset completed)
......@@ -401,7 +363,8 @@ static void ciintf_interrupt (unsigned long data)
if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
// CAM removal IRQ
budget_ci->slot_status = SLOTSTATUS_NONE;
dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, DVB_CA_EN50221_CAMCHANGE_REMOVED);
dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
DVB_CA_EN50221_CAMCHANGE_REMOVED);
}
}
}
......@@ -418,18 +381,18 @@ static int ciintf_init(struct budget_ci* budget_ci)
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
// test if it is there
if ((budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CIVERSION, 1) & 0xa0) != 0xa0) {
if ((ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0) & 0xa0) != 0xa0) {
result = -ENODEV;
goto error;
}
// determine whether a CAM is present or not
flags = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1);
flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
budget_ci->slot_status = SLOTSTATUS_NONE;
if (flags & CICONTROL_CAMDETECT) budget_ci->slot_status = SLOTSTATUS_PRESENT;
if (flags & CICONTROL_CAMDETECT)
budget_ci->slot_status = SLOTSTATUS_PRESENT;
// register CI interface
budget_ci->ca.owner = THIS_MODULE;
budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
budget_ci->ca.read_cam_control = ciintf_read_cam_control;
......@@ -442,8 +405,7 @@ static int ciintf_init(struct budget_ci* budget_ci)
&budget_ci->ca,
DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
DVB_CA_EN50221_FLAG_IRQ_FR |
DVB_CA_EN50221_FLAG_IRQ_DA,
1)) != 0) {
DVB_CA_EN50221_FLAG_IRQ_DA, 1)) != 0) {
printk("budget_ci: CI interface detected, but initialisation failed.\n");
goto error;
}
......@@ -456,7 +418,8 @@ static int ciintf_init(struct budget_ci* budget_ci)
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
}
saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03);
budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET);
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
CICONTROL_RESET, 1, 0);
// success!
printk("budget_ci: CI interface initialised\n");
......@@ -464,7 +427,8 @@ static int ciintf_init(struct budget_ci* budget_ci)
// forge a fake CI IRQ so the CAM state is setup correctly
flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
if (budget_ci->slot_status != SLOTSTATUS_NONE) flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
if (budget_ci->slot_status != SLOTSTATUS_NONE)
flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
return 0;
......@@ -482,9 +446,10 @@ static void ciintf_deinit(struct budget_ci* budget_ci)
saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03);
saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
tasklet_kill(&budget_ci->ciintf_irq_tasklet);
budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0);
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
msleep(1);
budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET);
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
CICONTROL_RESET, 1, 0);
// disable TS data stream to CI interface
saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
......@@ -513,9 +478,425 @@ static void budget_ci_irq (struct saa7146_dev *dev, u32 *isr)
}
static u8 alps_bsru6_inittab[] = {
0x01, 0x15,
0x02, 0x00,
0x03, 0x00,
0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
0x06, 0x40, /* DAC not used, set to high impendance mode */
0x07, 0x00, /* DAC LSB */
0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
0x09, 0x00, /* FIFO */
0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
0x18, 0x00,
0x19, 0x00,
0x1a, 0x00,
0x1f, 0x50,
0x20, 0x00,
0x21, 0x00,
0x22, 0x00,
0x23, 0x00,
0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
0x29, 0x1e, // 1/2 threshold
0x2a, 0x14, // 2/3 threshold
0x2b, 0x0f, // 3/4 threshold
0x2c, 0x09, // 5/6 threshold
0x2d, 0x05, // 7/8 threshold
0x2e, 0x01,
0x31, 0x1f, // test all FECs
0x32, 0x19, // viterbi and synchro search
0x33, 0xfc, // rs control
0x34, 0x93, // error control
0x0f, 0x52,
0xff, 0xff
};
static int budget_ci_attach (struct saa7146_dev* dev,
struct saa7146_pci_extension_data *info)
static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
{
u8 aclk = 0;
u8 bclk = 0;
if (srate < 1500000) {
aclk = 0xb7;
bclk = 0x47;
} else if (srate < 3000000) {
aclk = 0xb7;
bclk = 0x4b;
} else if (srate < 7000000) {
aclk = 0xb7;
bclk = 0x4f;
} else if (srate < 14000000) {
aclk = 0xb7;
bclk = 0x53;
} else if (srate < 30000000) {
aclk = 0xb6;
bclk = 0x53;
} else if (srate < 45000000) {
aclk = 0xb4;
bclk = 0x51;
}
stv0299_writereg(fe, 0x13, aclk);
stv0299_writereg(fe, 0x14, bclk);
stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
return 0;
}
static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
u8 buf[4];
u32 div;
struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
if ((params->frequency < 950000) || (params->frequency > 2150000))
return -EINVAL;
div = (params->frequency + (125 - 1)) / 125; // round correctly
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
buf[3] = 0xC4;
if (params->frequency > 1530000)
buf[3] = 0xc0;
if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
static struct stv0299_config alps_bsru6_config = {
.demod_address = 0x68,
.inittab = alps_bsru6_inittab,
.mclk = 88000000UL,
.invert = 1,
.enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100,
.set_symbol_rate = alps_bsru6_set_symbol_rate,
.pll_set = alps_bsru6_pll_set,
};
static u8 philips_su1278_tt_inittab[] = {
0x01, 0x0f,
0x02, 0x30,
0x03, 0x00,
0x04, 0x5b,
0x05, 0x85,
0x06, 0x02,
0x07, 0x00,
0x08, 0x02,
0x09, 0x00,
0x0C, 0x01,
0x0D, 0x81,
0x0E, 0x44,
0x0f, 0x14,
0x10, 0x3c,
0x11, 0x84,
0x12, 0xda,
0x13, 0x97,
0x14, 0x95,
0x15, 0xc9,
0x16, 0x19,
0x17, 0x8c,
0x18, 0x59,
0x19, 0xf8,
0x1a, 0xfe,
0x1c, 0x7f,
0x1d, 0x00,
0x1e, 0x00,
0x1f, 0x50,
0x20, 0x00,
0x21, 0x00,
0x22, 0x00,
0x23, 0x00,
0x28, 0x00,
0x29, 0x28,
0x2a, 0x14,
0x2b, 0x0f,
0x2c, 0x09,
0x2d, 0x09,
0x31, 0x1f,
0x32, 0x19,
0x33, 0xfc,
0x34, 0x93,
0xff, 0xff
};
static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
{
stv0299_writereg(fe, 0x0e, 0x44);
if (srate >= 10000000) {
stv0299_writereg(fe, 0x13, 0x97);
stv0299_writereg(fe, 0x14, 0x95);
stv0299_writereg(fe, 0x15, 0xc9);
stv0299_writereg(fe, 0x17, 0x8c);
stv0299_writereg(fe, 0x1a, 0xfe);
stv0299_writereg(fe, 0x1c, 0x7f);
stv0299_writereg(fe, 0x2d, 0x09);
} else {
stv0299_writereg(fe, 0x13, 0x99);
stv0299_writereg(fe, 0x14, 0x8d);
stv0299_writereg(fe, 0x15, 0xce);
stv0299_writereg(fe, 0x17, 0x43);
stv0299_writereg(fe, 0x1a, 0x1d);
stv0299_writereg(fe, 0x1c, 0x12);
stv0299_writereg(fe, 0x2d, 0x05);
}
stv0299_writereg(fe, 0x0e, 0x23);
stv0299_writereg(fe, 0x0f, 0x94);
stv0299_writereg(fe, 0x10, 0x39);
stv0299_writereg(fe, 0x15, 0xc9);
stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
return 0;
}
static int philips_su1278_tt_pll_set(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
{
struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
u32 div;
u8 buf[4];
struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
if ((params->frequency < 950000) || (params->frequency > 2150000))
return -EINVAL;
div = (params->frequency + (500 - 1)) / 500; // round correctly
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
buf[3] = 0x20;
if (params->u.qpsk.symbol_rate < 4000000)
buf[3] |= 1;
if (params->frequency < 1250000)
buf[3] |= 0;
else if (params->frequency < 1550000)
buf[3] |= 0x40;
else if (params->frequency < 2050000)
buf[3] |= 0x80;
else if (params->frequency < 2150000)
buf[3] |= 0xC0;
if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
static struct stv0299_config philips_su1278_tt_config = {
.demod_address = 0x68,
.inittab = philips_su1278_tt_inittab,
.mclk = 64000000UL,
.invert = 0,
.enhanced_tuning = 1,
.skip_reinit = 1,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 50,
.set_symbol_rate = philips_su1278_tt_set_symbol_rate,
.pll_set = philips_su1278_tt_pll_set,
};
static int philips_tdm1316l_pll_init(struct dvb_frontend *fe)
{
struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
struct i2c_msg tuner_msg = {.addr = 0x63,.flags = 0,.buf = td1316_init,.len =
sizeof(td1316_init) };
// setup PLL configuration
if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
msleep(1);
// disable the mc44BC374c (do not check for errors)
tuner_msg.addr = 0x65;
tuner_msg.buf = disable_mc44BC374c;
tuner_msg.len = sizeof(disable_mc44BC374c);
if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
}
return 0;
}
static int philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
u8 tuner_buf[4];
struct i2c_msg tuner_msg = {.addr = 0x63,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) };
int tuner_frequency = 0;
u8 band, cp, filter;
// determine charge pump
tuner_frequency = params->frequency + 36130000;
if (tuner_frequency < 87000000)
return -EINVAL;
else if (tuner_frequency < 130000000)
cp = 3;
else if (tuner_frequency < 160000000)
cp = 5;
else if (tuner_frequency < 200000000)
cp = 6;
else if (tuner_frequency < 290000000)
cp = 3;
else if (tuner_frequency < 420000000)
cp = 5;
else if (tuner_frequency < 480000000)
cp = 6;
else if (tuner_frequency < 620000000)
cp = 3;
else if (tuner_frequency < 830000000)
cp = 5;
else if (tuner_frequency < 895000000)
cp = 7;
else
return -EINVAL;
// determine band
if (params->frequency < 49000000)
return -EINVAL;
else if (params->frequency < 159000000)
band = 1;
else if (params->frequency < 444000000)
band = 2;
else if (params->frequency < 861000000)
band = 4;
else
return -EINVAL;
// setup PLL filter and TDA9889
switch (params->u.ofdm.bandwidth) {
case BANDWIDTH_6_MHZ:
tda1004x_write_byte(fe, 0x0C, 0x14);
filter = 0;
break;
case BANDWIDTH_7_MHZ:
tda1004x_write_byte(fe, 0x0C, 0x80);
filter = 0;
break;
case BANDWIDTH_8_MHZ:
tda1004x_write_byte(fe, 0x0C, 0x14);
filter = 1;
break;
default:
return -EINVAL;
}
// calculate divisor
// ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
// setup tuner buffer
tuner_buf[0] = tuner_frequency >> 8;
tuner_buf[1] = tuner_frequency & 0xff;
tuner_buf[2] = 0xca;
tuner_buf[3] = (cp << 5) | (filter << 3) | band;
if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
msleep(1);
return 0;
}
static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
const struct firmware **fw, char *name)
{
struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
}
static struct tda1004x_config philips_tdm1316l_config = {
.demod_address = 0x8,
.invert = 0,
.pll_init = philips_tdm1316l_pll_init,
.pll_set = philips_tdm1316l_pll_set,
.request_firmware = philips_tdm1316l_request_firmware,
};
static void frontend_init(struct budget_ci *budget_ci)
{
switch (budget_ci->budget.dev->pci->subsystem_device) {
case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
budget_ci->budget.dvb_frontend =
stv0299_attach(&alps_bsru6_config, &budget_ci->budget.i2c_adap);
if (budget_ci->budget.dvb_frontend) {
break;
}
break;
case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
budget_ci->budget.dvb_frontend =
stv0299_attach(&philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
if (budget_ci->budget.dvb_frontend) {
break;
}
break;
case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
budget_ci->budget.dvb_frontend =
tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
if (budget_ci->budget.dvb_frontend) {
break;
}
break;
}
if (budget_ci->budget.dvb_frontend == NULL) {
printk("budget-ci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
budget_ci->budget.dev->pci->vendor,
budget_ci->budget.dev->pci->device,
budget_ci->budget.dev->pci->subsystem_vendor,
budget_ci->budget.dev->pci->subsystem_device);
} else {
if (dvb_register_frontend
(budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
printk("budget-ci: Frontend registration failed!\n");
if (budget_ci->budget.dvb_frontend->ops->release)
budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend);
budget_ci->budget.dvb_frontend = NULL;
}
}
}
static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
{
struct budget_ci *budget_ci;
int err;
......@@ -525,12 +906,11 @@ static int budget_ci_attach (struct saa7146_dev* dev,
dprintk(2, "budget_ci: %p\n", budget_ci);
spin_lock_init(&budget_ci->debilock);
budget_ci->budget.ci_present = 0;
dev->ext_priv = budget_ci;
if ((err = ttpci_budget_init (&budget_ci->budget, dev, info))) {
if ((err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE))) {
kfree (budget_ci);
return err;
}
......@@ -542,6 +922,9 @@ static int budget_ci_attach (struct saa7146_dev* dev,
ciintf_init(budget_ci);
budget_ci->budget.dvb_adapter->priv = budget_ci;
frontend_init(budget_ci);
return 0;
}
......@@ -553,8 +936,10 @@ static int budget_ci_detach (struct saa7146_dev* dev)
struct saa7146_dev *saa = budget_ci->budget.dev;
int err;
if (budget_ci->budget.ci_present) ciintf_deinit(budget_ci);
if (budget_ci->budget.ci_present)
ciintf_deinit(budget_ci);
if (budget_ci->budget.dvb_frontend)
dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
err = ttpci_budget_deinit (&budget_ci->budget);
tasklet_kill (&budget_ci->msp430_irq_tasklet);
......
......@@ -74,8 +74,7 @@ static int start_ts_capture (struct budget *budget)
memset(budget->grabbing, 0x00, TS_HEIGHT*TS_WIDTH);
saa7146_write(dev, PCI_BT_V1, 0x001c0000 |
(saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
budget->tsf=0xff;
budget->ttbp=0;
......@@ -150,14 +149,87 @@ static void vpeirq (unsigned long data)
return;
if (newdma > olddma) { /* no wraparound, dump olddma..newdma */
dvb_dmx_swfilter_packets(&budget->demux,
mem+olddma, (newdma-olddma) / 188);
dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (newdma - olddma) / 188);
} else { /* wraparound, dump olddma..buflen and 0..newdma */
dvb_dmx_swfilter_packets(&budget->demux,
mem+olddma, (TS_BUFLEN-olddma) / 188);
dvb_dmx_swfilter_packets(&budget->demux,
mem, newdma / 188);
dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
dvb_dmx_swfilter_packets(&budget->demux, mem, newdma / 188);
}
}
int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count,
int uselocks, int nobusyloop)
{
struct saa7146_dev *saa = budget->dev;
int result = 0;
unsigned long flags = 0;
if (count > 4 || count <= 0)
return 0;
if (uselocks)
spin_lock_irqsave(&budget->debilock, flags);
if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) {
if (uselocks)
spin_unlock_irqrestore(&budget->debilock, flags);
return result;
}
saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
saa7146_write(saa, DEBI_CONFIG, config);
saa7146_write(saa, DEBI_PAGE, 0);
saa7146_write(saa, MC2, (2 << 16) | 2);
if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) {
if (uselocks)
spin_unlock_irqrestore(&budget->debilock, flags);
return result;
}
result = saa7146_read(saa, DEBI_AD);
result &= (0xffffffffUL >> ((4 - count) * 8));
if (uselocks)
spin_unlock_irqrestore(&budget->debilock, flags);
return result;
}
int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr,
int count, u32 value, int uselocks, int nobusyloop)
{
struct saa7146_dev *saa = budget->dev;
unsigned long flags = 0;
int result;
if (count > 4 || count <= 0)
return 0;
if (uselocks)
spin_lock_irqsave(&budget->debilock, flags);
if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) {
if (uselocks)
spin_unlock_irqrestore(&budget->debilock, flags);
return result;
}
saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x00000 | (addr & 0xffff));
saa7146_write(saa, DEBI_CONFIG, config);
saa7146_write(saa, DEBI_PAGE, 0);
saa7146_write(saa, DEBI_AD, value);
saa7146_write(saa, MC2, (2 << 16) | 2);
if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) {
if (uselocks)
spin_unlock_irqrestore(&budget->debilock, flags);
return result;
}
if (uselocks)
spin_unlock_irqrestore(&budget->debilock, flags);
return 0;
}
......@@ -231,13 +303,11 @@ static int budget_register(struct budget *budget)
return ret;
budget->mem_frontend.source = DMX_MEMORY_FE;
ret=dvbdemux->dmx.add_frontend (&dvbdemux->dmx,
&budget->mem_frontend);
ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->mem_frontend);
if (ret<0)
return ret;
ret=dvbdemux->dmx.connect_frontend (&dvbdemux->dmx,
&budget->hw_frontend);
ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &budget->hw_frontend);
if (ret < 0)
return ret;
......@@ -263,30 +333,9 @@ static void budget_unregister(struct budget *budget)
dvb_dmx_release(&budget->demux);
}
/* fixme: can this be unified among all saa7146 based dvb cards? */
static int client_register(struct i2c_client *client)
{
struct saa7146_dev *dev = (struct saa7146_dev*)i2c_get_adapdata(client->adapter);
struct budget *budget = (struct budget*)dev->ext_priv;
if (client->driver->command)
return client->driver->command(client, FE_REGISTER, budget->dvb_adapter);
return 0;
}
static int client_unregister(struct i2c_client *client)
{
struct saa7146_dev *dev = (struct saa7146_dev*)i2c_get_adapdata(client->adapter);
struct budget *budget = (struct budget*)dev->ext_priv;
if (client->driver->command)
return client->driver->command(client, FE_UNREGISTER, budget->dvb_adapter);
return 0;
}
int ttpci_budget_init (struct budget *budget,
struct saa7146_dev* dev,
struct saa7146_pci_extension_data *info)
int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
struct saa7146_pci_extension_data *info,
struct module *owner)
{
int length = TS_WIDTH*TS_HEIGHT;
int ret = 0;
......@@ -299,7 +348,7 @@ int ttpci_budget_init (struct budget *budget,
budget->card = bi;
budget->dev = (struct saa7146_dev *) dev;
dvb_register_adapter(&budget->dvb_adapter, budget->card->name, THIS_MODULE);
dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner);
/* set dd1 stream a & b */
saa7146_write(dev, DD1_STREAM_B, 0x00000000);
......@@ -313,21 +362,18 @@ int ttpci_budget_init (struct budget *budget,
else
budget->video_port = BUDGET_VIDEO_PORTA;
spin_lock_init(&budget->feedlock);
spin_lock_init(&budget->debilock);
/* the Siemens DVB needs this if you want to have the i2c chips
get recognized before the main driver is loaded */
if (bi->type != BUDGET_FS_ACTIVY)
saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */
budget->i2c_adap = (struct i2c_adapter) {
.client_register = client_register,
.client_unregister = client_unregister,
#ifdef I2C_ADAP_CLASS_TV_DIGITAL
.class = I2C_ADAP_CLASS_TV_DIGITAL,
budget->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
#else
.class = I2C_CLASS_TV_DIGITAL,
budget->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
#endif
};
strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name));
......@@ -341,7 +387,8 @@ int ttpci_budget_init (struct budget *budget,
ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter->proposed_mac);
if( NULL == (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci,length,&budget->pt))) {
if (NULL ==
(budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, length, &budget->pt))) {
ret = -ENOMEM;
goto err;
}
......@@ -420,8 +467,8 @@ void ttpci_budget_set_video_port(struct saa7146_dev* dev, int video_port)
spin_unlock(&budget->feedlock);
}
EXPORT_SYMBOL_GPL(ttpci_budget_debiread);
EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite);
EXPORT_SYMBOL_GPL(ttpci_budget_init);
EXPORT_SYMBOL_GPL(ttpci_budget_deinit);
EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
......
......@@ -33,6 +33,9 @@
#include "av7110.h"
#include "av7110_hw.h"
#include "budget.h"
#include "stv0299.h"
#include "ves1x93.h"
#include "tda8083.h"
#define budget_patch budget
......@@ -121,16 +124,11 @@ static int av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg,
return 0;
}
int budget_patch_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
static int budget_patch_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
struct budget_patch *budget = fe->before_after_data;
dprintk(2, "budget: %p\n", budget);
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
switch (cmd) {
case FE_SET_TONE:
switch ((fe_sec_tone_mode_t) arg) {
switch (tone) {
case SEC_TONE_ON:
av7110_set22k (budget, 1);
break;
......@@ -140,27 +138,232 @@ int budget_patch_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *
default:
return -EINVAL;
}
break;
case FE_DISEQC_SEND_MASTER_CMD:
return 0;
}
static int budget_patch_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
{
struct dvb_diseqc_master_cmd *cmd = arg;
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
av7110_send_diseqc_msg (budget, cmd->msg_len, cmd->msg, 0);
break;
return 0;
}
case FE_DISEQC_SEND_BURST:
av7110_send_diseqc_msg (budget, 0, NULL, (int) (long) arg);
break;
static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
{
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
default:
return -EOPNOTSUPP;
av7110_send_diseqc_msg (budget, 0, NULL, minicmd);
return 0;
}
static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
u8 pwr = 0;
u8 buf[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
u32 div = (params->frequency + 479500) / 125;
if (params->frequency > 2000000) pwr = 3;
else if (params->frequency > 1800000) pwr = 2;
else if (params->frequency > 1600000) pwr = 1;
else if (params->frequency > 1200000) pwr = 0;
else if (params->frequency >= 1100000) pwr = 1;
else pwr = 2;
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = ((div & 0x18000) >> 10) | 0x95;
buf[3] = (pwr << 6) | 0x30;
// NOTE: since we're using a prescaler of 2, we set the
// divisor frequency to 62.5kHz and divide by 125 above
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
static struct ves1x93_config alps_bsrv2_config = {
.demod_address = 0x08,
.xin = 90100000UL,
.invert_pwm = 0,
.pll_set = alps_bsrv2_pll_set,
};
static u8 alps_bsru6_inittab[] = {
0x01, 0x15,
0x02, 0x00,
0x03, 0x00,
0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
0x06, 0x40, /* DAC not used, set to high impendance mode */
0x07, 0x00, /* DAC LSB */
0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
0x09, 0x00, /* FIFO */
0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
0x18, 0x00,
0x19, 0x00,
0x1a, 0x00,
0x1f, 0x50,
0x20, 0x00,
0x21, 0x00,
0x22, 0x00,
0x23, 0x00,
0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
0x29, 0x1e, // 1/2 threshold
0x2a, 0x14, // 2/3 threshold
0x2b, 0x0f, // 3/4 threshold
0x2c, 0x09, // 5/6 threshold
0x2d, 0x05, // 7/8 threshold
0x2e, 0x01,
0x31, 0x1f, // test all FECs
0x32, 0x19, // viterbi and synchro search
0x33, 0xfc, // rs control
0x34, 0x93, // error control
0x0f, 0x52,
0xff, 0xff
};
static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
{
u8 aclk = 0;
u8 bclk = 0;
if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
stv0299_writereg (fe, 0x13, aclk);
stv0299_writereg (fe, 0x14, bclk);
stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff);
stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
return 0;
}
static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
u8 data[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL;
div = (params->frequency + (125 - 1)) / 125; // round correctly
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
data[3] = 0xC4;
if (params->frequency > 1530000) data[3] = 0xc0;
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
static struct stv0299_config alps_bsru6_config = {
.demod_address = 0x68,
.inittab = alps_bsru6_inittab,
.mclk = 88000000UL,
.invert = 1,
.enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100,
.set_symbol_rate = alps_bsru6_set_symbol_rate,
.pll_set = alps_bsru6_pll_set,
};
static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
u32 div;
u8 data[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
div = params->frequency / 125;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x8e;
data[3] = 0x00;
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
struct tda8083_config grundig_29504_451_config = {
.demod_address = 0x68,
.pll_set = grundig_29504_451_pll_set,
};
static void frontend_init(struct budget_patch* budget)
{
switch(budget->dev->pci->subsystem_device) {
case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
// try the ALPS BSRV2 first of all
budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst;
budget->dvb_frontend->ops->set_tone = budget_patch_set_tone;
break;
}
// try the ALPS BSRU6 now
budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst;
budget->dvb_frontend->ops->set_tone = budget_patch_set_tone;
break;
}
// Try the grundig 29504-451
budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst;
budget->dvb_frontend->ops->set_tone = budget_patch_set_tone;
break;
}
break;
}
if (budget->dvb_frontend == NULL) {
printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
budget->dev->pci->vendor,
budget->dev->pci->device,
budget->dev->pci->subsystem_vendor,
budget->dev->pci->subsystem_device);
} else {
if (dvb_register_frontend(budget->dvb_adapter, budget->dvb_frontend)) {
printk("budget-av: Frontend registration failed!\n");
if (budget->dvb_frontend->ops->release)
budget->dvb_frontend->ops->release(budget->dvb_frontend);
budget->dvb_frontend = NULL;
}
}
}
static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
{
......@@ -173,7 +376,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
dprintk(2, "budget: %p\n", budget);
if ((err = ttpci_budget_init (budget, dev, info))) {
if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
kfree (budget);
return err;
}
......@@ -221,11 +424,11 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
// Enable RPS1 (rFC p33)
saa7146_write(dev, MC1, (MASK_13 | MASK_29));
dvb_add_frontend_ioctls (budget->dvb_adapter,
budget_patch_diseqc_ioctl, NULL, budget);
dev->ext_priv = budget;
budget->dvb_adapter->priv = budget;
frontend_init(budget);
return 0;
}
......@@ -235,8 +438,7 @@ static int budget_patch_detach (struct saa7146_dev* dev)
struct budget_patch *budget = (struct budget_patch*) dev->ext_priv;
int err;
dvb_remove_frontend_ioctls (budget->dvb_adapter,
budget_patch_diseqc_ioctl, NULL);
if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
err = ttpci_budget_deinit (budget);
......
......@@ -35,6 +35,11 @@
*/
#include "budget.h"
#include "stv0299.h"
#include "ves1x93.h"
#include "ves1820.h"
#include "l64781.h"
#include "tda8083.h"
static void Set22K (struct budget *budget, int state)
{
......@@ -105,89 +110,368 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long
return 0;
}
int budget_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
/*
* Routines for the Fujitsu Siemens Activy budget card
* 22 kHz tone and DiSEqC are handled by the frontend.
* Voltage must be set here.
*/
static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
{
struct budget *budget = fe->before_after_data;
struct saa7146_dev *dev=budget->dev;
dprintk(2, "budget: %p\n", budget);
switch (cmd) {
case FE_SET_TONE:
switch ((fe_sec_tone_mode_t) arg) {
switch (voltage) {
case SEC_VOLTAGE_13:
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
break;
case SEC_VOLTAGE_18:
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
break;
default:
return -EINVAL;
}
return 0;
}
static int siemens_budget_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
return SetVoltage_Activy (budget, voltage);
}
static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
switch (tone) {
case SEC_TONE_ON:
Set22K (budget, 1);
break;
case SEC_TONE_OFF:
Set22K (budget, 0);
break;
default:
return -EINVAL;
};
break;
}
return 0;
}
case FE_DISEQC_SEND_MASTER_CMD:
static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
{
struct dvb_diseqc_master_cmd *cmd = arg;
struct budget* budget = (struct budget*) fe->dvb->priv;
SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
break;
return 0;
}
case FE_DISEQC_SEND_BURST:
SendDiSEqCMsg (budget, 0, NULL, (unsigned long)arg);
break;
static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
default:
return -EOPNOTSUPP;
};
SendDiSEqCMsg (budget, 0, NULL, minicmd);
return 0;
}
static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
u8 pwr = 0;
u8 buf[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
u32 div = (params->frequency + 479500) / 125;
if (params->frequency > 2000000) pwr = 3;
else if (params->frequency > 1800000) pwr = 2;
else if (params->frequency > 1600000) pwr = 1;
else if (params->frequency > 1200000) pwr = 0;
else if (params->frequency >= 1100000) pwr = 1;
else pwr = 2;
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = ((div & 0x18000) >> 10) | 0x95;
buf[3] = (pwr << 6) | 0x30;
// NOTE: since we're using a prescaler of 2, we set the
// divisor frequency to 62.5kHz and divide by 125 above
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
/*
* Routines for the Fujitsu Siemens Activy budget card
* 22 kHz tone and DiSEqC are handled by the frontend.
* Voltage must be set here.
*/
static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
static struct ves1x93_config alps_bsrv2_config =
{
struct saa7146_dev *dev=budget->dev;
.demod_address = 0x08,
.xin = 90100000UL,
.invert_pwm = 0,
.pll_set = alps_bsrv2_pll_set,
};
dprintk(2, "budget: %p\n", budget);
static u8 alps_bsru6_inittab[] = {
0x01, 0x15,
0x02, 0x00,
0x03, 0x00,
0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
0x06, 0x40, /* DAC not used, set to high impendance mode */
0x07, 0x00, /* DAC LSB */
0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
0x09, 0x00, /* FIFO */
0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
0x18, 0x00,
0x19, 0x00,
0x1a, 0x00,
0x1f, 0x50,
0x20, 0x00,
0x21, 0x00,
0x22, 0x00,
0x23, 0x00,
0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
0x29, 0x1e, // 1/2 threshold
0x2a, 0x14, // 2/3 threshold
0x2b, 0x0f, // 3/4 threshold
0x2c, 0x09, // 5/6 threshold
0x2d, 0x05, // 7/8 threshold
0x2e, 0x01,
0x31, 0x1f, // test all FECs
0x32, 0x19, // viterbi and synchro search
0x33, 0xfc, // rs control
0x34, 0x93, // error control
0x0f, 0x52,
0xff, 0xff
};
switch (voltage) {
case SEC_VOLTAGE_13:
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
break;
case SEC_VOLTAGE_18:
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
break;
default:
return -EINVAL;
static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
{
u8 aclk = 0;
u8 bclk = 0;
if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
stv0299_writereg (fe, 0x13, aclk);
stv0299_writereg (fe, 0x14, bclk);
stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff);
stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
return 0;
}
static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
u8 data[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL;
div = (params->frequency + (125 - 1)) / 125; // round correctly
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
data[3] = 0xC4;
if (params->frequency > 1530000) data[3] = 0xc0;
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
static struct stv0299_config alps_bsru6_config = {
.demod_address = 0x68,
.inittab = alps_bsru6_inittab,
.mclk = 88000000UL,
.invert = 1,
.enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100,
.set_symbol_rate = alps_bsru6_set_symbol_rate,
.pll_set = alps_bsru6_pll_set,
};
static int budget_ioctl_activy (struct dvb_frontend *fe, unsigned int cmd, void *arg)
static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget *budget = fe->before_after_data;
struct budget* budget = (struct budget*) fe->dvb->priv;
u32 div;
u8 data[4];
struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
dprintk(2, "budget: %p\n", budget);
div = (params->frequency + 35937500 + 31250) / 62500;
switch (cmd) {
case FE_SET_VOLTAGE:
return SetVoltage_Activy (budget, (fe_sec_voltage_t) arg);
default:
return -EOPNOTSUPP;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x85 | ((div >> 10) & 0x60);
data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
static struct ves1820_config alps_tdbe2_config = {
.demod_address = 0x09,
.xin = 57840000UL,
.invert = 1,
.selagc = VES1820_SELAGC_SIGNAMPERR,
.pll_set = alps_tdbe2_pll_set,
};
static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
u32 div;
u8 cfg, cpump, band_select;
u8 data[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
div = (36125000 + params->frequency) / 166666;
cfg = 0x88;
if (params->frequency < 175000000) cpump = 2;
else if (params->frequency < 390000000) cpump = 1;
else if (params->frequency < 470000000) cpump = 2;
else if (params->frequency < 750000000) cpump = 1;
else cpump = 3;
if (params->frequency < 175000000) band_select = 0x0e;
else if (params->frequency < 470000000) band_select = 0x05;
else band_select = 0x03;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = ((div >> 10) & 0x60) | cfg;
data[3] = (cpump << 6) | band_select;
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
static struct l64781_config grundig_29504_401_config = {
.demod_address = 0x55,
.pll_set = grundig_29504_401_pll_set,
};
static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
u32 div;
u8 data[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
div = params->frequency / 125;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x8e;
data[3] = 0x00;
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
static struct tda8083_config grundig_29504_451_config = {
.demod_address = 0x68,
.pll_set = grundig_29504_451_pll_set,
};
static u8 read_pwm(struct budget* budget)
{
u8 b = 0xff;
u8 pwm;
struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
{ .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
pwm = 0x48;
return pwm;
}
static void frontend_init(struct budget *budget)
{
switch(budget->dev->pci->subsystem_device) {
case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
// try the ALPS BSRV2 first of all
budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
budget->dvb_frontend->ops->set_tone = budget_set_tone;
break;
}
// try the ALPS BSRU6 now
budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
budget->dvb_frontend->ops->set_tone = budget_set_tone;
break;
}
break;
case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
if (budget->dvb_frontend) break;
break;
case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap);
if (budget->dvb_frontend) break;
break;
case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI (tda8083/Grundig 29504-451(tsa5522))
// grundig 29504-451
budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
break;
}
break;
}
if (budget->dvb_frontend == NULL) {
printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
budget->dev->pci->vendor,
budget->dev->pci->device,
budget->dev->pci->subsystem_vendor,
budget->dev->pci->subsystem_device);
} else {
if (dvb_register_frontend(budget->dvb_adapter, budget->dvb_frontend)) {
printk("budget: Frontend registration failed!\n");
if (budget->dvb_frontend->ops->release)
budget->dvb_frontend->ops->release(budget->dvb_frontend);
budget->dvb_frontend = NULL;
}
}
}
static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
{
......@@ -203,18 +487,14 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_
dev->ext_priv = budget;
if ((err = ttpci_budget_init (budget, dev, info))) {
if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
printk("==> failed\n");
kfree (budget);
return err;
}
if (budget->card->type == BUDGET_FS_ACTIVY)
dvb_add_frontend_ioctls (budget->dvb_adapter,
budget_ioctl_activy, NULL, budget);
else
dvb_add_frontend_ioctls (budget->dvb_adapter,
budget_diseqc_ioctl, NULL, budget);
budget->dvb_adapter->priv = budget;
frontend_init(budget);
return 0;
}
......@@ -225,12 +505,7 @@ static int budget_detach (struct saa7146_dev* dev)
struct budget *budget = (struct budget*) dev->ext_priv;
int err;
if (budget->card->type == BUDGET_FS_ACTIVY)
dvb_remove_frontend_ioctls (budget->dvb_adapter,
budget_ioctl_activy, NULL);
else
dvb_remove_frontend_ioctls (budget->dvb_adapter,
budget_diseqc_ioctl, NULL);
if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
err = ttpci_budget_deinit (budget);
......@@ -247,18 +522,14 @@ static struct saa7146_extension budget_extension;
MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC);
/* MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); UNDEFINED HARDWARE - mail linuxtv.org list */
MAKE_BUDGET_INFO(fsacs, "Fujitsu Siemens Activy Budget-S PCI", BUDGET_FS_ACTIVY);
/* Uncomment for Budget Patch */
/*MAKE_BUDGET_INFO(fs_1_3,"Siemens/Technotrend/Hauppauge PCI rev1.3+Budget_Patch", BUDGET_PATCH);*/
static struct pci_device_id pci_tbl[] = {
/* Uncomment for Budget Patch */
/*MAKE_EXTENSION_PCI(fs_1_3,0x13c2, 0x0000),*/
MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003),
MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004),
MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005),
MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
/* MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), UNDEFINED HARDWARE */
MAKE_EXTENSION_PCI(fsacs, 0x1131, 0x4f61),
{
.vendor = 0,
......
......@@ -9,6 +9,7 @@
#include "dvb_filter.h"
#include "dvb_net.h"
#include <linux/module.h>
#include <media/saa7146.h>
extern int budget_debug;
......@@ -61,7 +62,10 @@ struct budget {
spinlock_t feedlock;
spinlock_t debilock;
struct dvb_adapter *dvb_adapter;
struct dvb_frontend *dvb_frontend;
void *priv;
};
......@@ -82,20 +86,27 @@ static struct saa7146_pci_extension_data x_var = { \
#define BUDGET_TT 0
#define BUDGET_TT_HW_DISEQC 1
#define BUDGET_KNC1 2
#define BUDGET_PATCH 3
#define BUDGET_FS_ACTIVY 4
#define BUDGET_CIN1200 5
#define BUDGET_CIN1200S 5
#define BUDGET_CIN1200C 6
#define BUDGET_CIN1200T 7
#define BUDGET_KNC1S 8
#define BUDGET_KNC1C 9
#define BUDGET_KNC1T 10
#define BUDGET_VIDEO_PORTA 0
#define BUDGET_VIDEO_PORTB 1
extern int ttpci_budget_init (struct budget *budget,
struct saa7146_dev* dev,
struct saa7146_pci_extension_data *info);
extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
struct saa7146_pci_extension_data *info,
struct module *owner);
extern int ttpci_budget_deinit (struct budget *budget);
extern void ttpci_budget_irq10_handler (struct saa7146_dev* dev, u32 *isr);
extern void ttpci_budget_set_video_port(struct saa7146_dev* dev, int video_port);
extern int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count,
int uselocks, int nobusyloop);
extern int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, int count, u32 value,
int uselocks, int nobusyloop);
#endif
......@@ -1190,7 +1190,7 @@ static int philips_tdm1316l_request_firmware(struct dvb_frontend* fe, const stru
return request_firmware(fw, name, &ttusb->dev->dev);
}
struct tda1004x_config philips_tdm1316l_config = {
static struct tda1004x_config philips_tdm1316l_config = {
.demod_address = 0x8,
.invert = 1,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment