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)"); ...@@ -94,7 +94,16 @@ MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
static void restart_feeds(struct av7110 *av7110); 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) static void init_av7110_av(struct av7110 *av7110)
{ {
...@@ -259,15 +268,15 @@ void av7110_unregister_irc_handler(void (*func)(u32)) ...@@ -259,15 +268,15 @@ void av7110_unregister_irc_handler(void (*func)(u32))
irc_handler = NULL; irc_handler = NULL;
} }
void run_handlers(unsigned long ircom) static void run_handlers(unsigned long ircom)
{ {
if (irc_handler != NULL) if (irc_handler != NULL)
(*irc_handler)((u32) ircom); (*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); dprintk(4, "ircommand = %08x\n", ircom);
irtask.data = (unsigned long) ircom; irtask.data = (unsigned long) ircom;
...@@ -572,7 +581,7 @@ static void gpioirq (unsigned long data) ...@@ -572,7 +581,7 @@ static void gpioirq (unsigned long data)
wake_up(&cibuf->queue); wake_up(&cibuf->queue);
iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2); iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 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_write(av7110->dev, IER,
saa7146_read(av7110->dev, IER) | MASK_19 ); saa7146_read(av7110->dev, IER) | MASK_19 );
if (len < 5) if (len < 5)
...@@ -610,7 +619,7 @@ static void gpioirq (unsigned long data) ...@@ -610,7 +619,7 @@ static void gpioirq (unsigned long data)
dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len); dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2); iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 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_write(av7110->dev, IER,
saa7146_read(av7110->dev, IER) | MASK_19 ); saa7146_read(av7110->dev, IER) | MASK_19 );
...@@ -637,7 +646,7 @@ static void gpioirq (unsigned long data) ...@@ -637,7 +646,7 @@ static void gpioirq (unsigned long data)
memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len); memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
av7110->bmpp+=len; av7110->bmpp+=len;
av7110->bmplen-=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_write(av7110->dev, IER,
saa7146_read(av7110->dev, IER) | MASK_19 ); saa7146_read(av7110->dev, IER) | MASK_19 );
if (len < 5) if (len < 5)
...@@ -659,7 +668,7 @@ static void gpioirq (unsigned long data) ...@@ -659,7 +668,7 @@ static void gpioirq (unsigned long data)
case DATA_TS_RECORD: case DATA_TS_RECORD:
case DATA_PES_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_write(av7110->dev, IER,
saa7146_read(av7110->dev, IER) | MASK_19); saa7146_read(av7110->dev, IER) | MASK_19);
irdebi(av7110, DEBISWAB, DPRAM_BASE+rxbuf, 0, len); irdebi(av7110, DEBISWAB, DPRAM_BASE+rxbuf, 0, len);
...@@ -667,7 +676,7 @@ static void gpioirq (unsigned long data) ...@@ -667,7 +676,7 @@ static void gpioirq (unsigned long data)
return; return;
case DATA_DEBUG_MESSAGE: case DATA_DEBUG_MESSAGE:
saa7146_wait_for_debi_done(av7110->dev); saa7146_wait_for_debi_done(av7110->dev, 0);
if (!len || len>0xff) { if (!len || len>0xff) {
iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
break; break;
...@@ -1090,71 +1099,42 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num, ...@@ -1090,71 +1099,42 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
* SEC device file operations * 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) { switch (tone) {
case FE_SET_TONE:
switch ((fe_sec_tone_mode_t) arg) {
case SEC_TONE_ON: case SEC_TONE_ON:
Set22K(av7110, 1); Set22K(av7110, 1);
break; break;
case SEC_TONE_OFF: case SEC_TONE_OFF:
Set22K(av7110, 0); Set22K(av7110, 0);
break; break;
default: default:
return -EINVAL; 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; return 0;
} }
static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
static void av7110_before_after_tune (fe_status_t s, void *data)
{ {
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;
if (av7110->playing) return 0;
return; }
if (down_interruptible(&av7110->pid_mutex)) static int av7110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
return; {
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
if (av7110->fe_synced) { av7110_diseqc_send(av7110, 0, NULL, minicmd);
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) ...@@ -1170,15 +1150,6 @@ static int av7110_register(struct av7110 *av7110)
av7110->registered=1; 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; dvbdemux->priv = (void *) av7110;
for (i=0; i<32; i++) for (i=0; i<32; i++)
...@@ -1252,12 +1223,7 @@ static void dvb_unregister(struct av7110 *av7110) ...@@ -1252,12 +1223,7 @@ static void dvb_unregister(struct av7110 *av7110)
dvb_dmxdev_release(&av7110->dmxdev); dvb_dmxdev_release(&av7110->dmxdev);
dvb_dmx_release(&av7110->demux); dvb_dmx_release(&av7110->demux);
dvb_remove_frontend_notifier (av7110->dvb_adapter, if (av7110->fe != NULL) dvb_unregister_frontend(av7110->fe);
av7110_before_after_tune);
dvb_remove_frontend_ioctls (av7110->dvb_adapter,
av7110_diseqc_ioctl, NULL);
dvb_unregister_device(av7110->osd_dev); dvb_unregister_device(av7110->osd_dev);
av7110_av_unregister(av7110); av7110_av_unregister(av7110);
av7110_ca_unregister(av7110); av7110_ca_unregister(av7110);
...@@ -1280,6 +1246,7 @@ int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val) ...@@ -1280,6 +1246,7 @@ int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
return i2c_transfer(&av7110->i2c_adap, &msgs, 1); return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
} }
#if 0
u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
{ {
u8 mm1[] = {0x00}; u8 mm1[] = {0x00};
...@@ -1296,6 +1263,7 @@ u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) ...@@ -1296,6 +1263,7 @@ u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
return mm2[0]; return mm2[0];
} }
#endif
/**************************************************************************** /****************************************************************************
* INITIALIZATION * INITIALIZATION
...@@ -1408,28 +1376,532 @@ static int get_firmware(struct av7110* av7110) ...@@ -1408,28 +1376,532 @@ static int get_firmware(struct av7110* av7110)
#endif #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*) fe->dvb->priv;
struct av7110 *av7110 = (struct av7110*)dev->ext_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; 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*) fe->dvb->priv;
struct av7110 *av7110 = (struct av7110*)dev->ext_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);
}
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);
}
/* fixme: check for "type" (ie. frontend type) */
if (client->driver->command)
return client->driver->command(client, FE_UNREGISTER, av7110->dvb_adapter);
return 0; 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) static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext)
{ {
struct av7110 *av7110 = NULL; struct av7110 *av7110 = NULL;
...@@ -1446,7 +1918,7 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d ...@@ -1446,7 +1918,7 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
memset(av7110, 0, sizeof(struct av7110)); memset(av7110, 0, sizeof(struct av7110));
av7110->card_name = (char*)pci_ext->ext_priv; av7110->card_name = (char*)pci_ext->ext_priv;
av7110->dev=(struct saa7146_dev *)dev; av7110->dev = dev;
dev->ext_priv = av7110; dev->ext_priv = av7110;
if ((ret = get_firmware(av7110))) { if ((ret = get_firmware(av7110))) {
...@@ -1460,15 +1932,11 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d ...@@ -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 */ get recognized before the main driver is fully loaded */
saa7146_write(dev, GPIO_CTRL, 0x500000); 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 #ifdef I2C_ADAP_CLASS_TV_DIGITAL
.class = I2C_ADAP_CLASS_TV_DIGITAL, av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
#else #else
.class = I2C_CLASS_TV_DIGITAL, av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
#endif #endif
};
strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name)); 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 */ 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 ...@@ -1567,6 +2035,9 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
if (ret) if (ret)
goto err3; goto err3;
av7110->dvb_adapter->priv = av7110;
frontend_init(av7110);
printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num); printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
av7110->device_initialized = 1; av7110->device_initialized = 1;
av7110_num++; av7110_num++;
...@@ -1663,33 +2134,29 @@ static struct saa7146_pci_extension_data x_var = { \ ...@@ -1663,33 +2134,29 @@ static struct saa7146_pci_extension_data x_var = { \
.ext_priv = x_name, \ .ext_priv = x_name, \
.ext = &av7110_extension } .ext = &av7110_extension }
MAKE_AV7110_INFO(fs_1_5, "Siemens cable card PCI rev1.5"); MAKE_AV7110_INFO(tts_1_X, "Technotrend/Hauppauge WinTV DVB-S rev1.X");
MAKE_AV7110_INFO(fs_1_3, "Siemens/Technotrend/Hauppauge PCI rev1.3"); MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
MAKE_AV7110_INFO(tt_1_6, "Technotrend/Hauppauge PCI rev1.3 or 1.6"); MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
MAKE_AV7110_INFO(tt_2_1, "Technotrend/Hauppauge PCI rev2.1 or 2.2"); MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
MAKE_AV7110_INFO(tt_t, "Technotrend/Hauppauge PCI DVB-T"); MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
MAKE_AV7110_INFO(unkwn0, "Technotrend/Hauppauge PCI rev?(unknown0)?"); MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV Nexus-S rev1.3");
MAKE_AV7110_INFO(unkwn1, "Technotrend/Hauppauge PCI rev?(unknown1)?"); MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
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");
static struct pci_device_id pci_tbl[] = { static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(fs_1_5, 0x110a, 0xffff), MAKE_EXTENSION_PCI(tts_1_X, 0x13c2, 0x0000),
MAKE_EXTENSION_PCI(fs_1_5, 0x110a, 0x0000), MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
MAKE_EXTENSION_PCI(fs_1_3, 0x13c2, 0x0000), MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
MAKE_EXTENSION_PCI(unkwn0, 0x13c2, 0x1002), MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
MAKE_EXTENSION_PCI(tt_1_6, 0x13c2, 0x0001), MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0002), MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0003), MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0004),
MAKE_EXTENSION_PCI(tt_1_6, 0x13c2, 0x0006), /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte
MAKE_EXTENSION_PCI(tt_t, 0x13c2, 0x0008), /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x1102), /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0006), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-S v????
MAKE_EXTENSION_PCI(unkwn1, 0xffc2, 0x0000), /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0008), UNDEFINED CARD */ // TT/Hauppauge WinTV DVB-T v????
MAKE_EXTENSION_PCI(unkwn2, 0x00a1, 0x00a1), /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
MAKE_EXTENSION_PCI(nexus, 0x00a1, 0xa1a0),
MAKE_EXTENSION_PCI(dvboc11,0x13c2, 0x000a),
{ {
.vendor = 0, .vendor = 0,
} }
......
...@@ -24,6 +24,13 @@ ...@@ -24,6 +24,13 @@
#include "dvb_filter.h" #include "dvb_filter.h"
#include "dvb_net.h" #include "dvb_net.h"
#include "dvb_ringbuffer.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> #include <media/saa7146_vv.h>
...@@ -217,6 +224,17 @@ struct av7110 { ...@@ -217,6 +224,17 @@ struct av7110 {
unsigned char *bin_root; unsigned char *bin_root;
unsigned long size_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 ...@@ -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 i;
int c = 0; int c = 0;
...@@ -936,7 +936,7 @@ static ssize_t dvb_audio_write(struct file *file, const char __user *buf, ...@@ -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); 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 #define MIN_IFRAME 400000
......
...@@ -89,20 +89,20 @@ void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len) ...@@ -89,20 +89,20 @@ void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len)
* CI link layer file ops * 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(cirbuf, vmalloc(size), size);
dvb_ringbuffer_init(ciwbuf, vmalloc(size), size); dvb_ringbuffer_init(ciwbuf, vmalloc(size), size);
return 0; 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(cirbuf);
dvb_ringbuffer_flush_spinlock_wakeup(ciwbuf); 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); vfree(cirbuf->data);
cirbuf->data = NULL; cirbuf->data = NULL;
...@@ -110,7 +110,7 @@ void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) ...@@ -110,7 +110,7 @@ void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf)
ciwbuf->data = NULL; 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 slots, ca_slot_info_t *slot)
{ {
int i; int i;
......
...@@ -53,10 +53,14 @@ int av7110_debiwrite(struct av7110 *av7110, u32 config, ...@@ -53,10 +53,14 @@ int av7110_debiwrite(struct av7110 *av7110, u32 config,
{ {
struct saa7146_dev *dev = av7110->dev; 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; 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; return -1;
}
saa7146_write(dev, DEBI_CONFIG, config); saa7146_write(dev, DEBI_CONFIG, config);
if (count <= 4) /* immediate transfer */ if (count <= 4) /* immediate transfer */
saa7146_write(dev, DEBI_AD, val); saa7146_write(dev, DEBI_AD, val);
...@@ -72,10 +76,14 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count) ...@@ -72,10 +76,14 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
struct saa7146_dev *dev = av7110->dev; struct saa7146_dev *dev = av7110->dev;
u32 result = 0; u32 result = 0;
if (count > 32764 || count <= 0) if (count > 32764 || count <= 0) {
printk("%s: invalid count %d\n", __FUNCTION__, count);
return 0; 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; return 0;
}
saa7146_write(dev, DEBI_AD, av7110->debi_bus); saa7146_write(dev, DEBI_AD, av7110->debi_bus);
saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff)); 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) ...@@ -83,7 +91,11 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
saa7146_write(dev, MC2, (2 << 16) | 2); saa7146_write(dev, MC2, (2 << 16) | 2);
if (count > 4) if (count > 4)
return count; 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 = saa7146_read(dev, DEBI_AD);
result &= (0xffffffffUL >> ((4 - count) * 8)); result &= (0xffffffffUL >> ((4 - count) * 8));
return result; return result;
...@@ -240,7 +252,7 @@ int av7110_bootarm(struct av7110 *av7110) ...@@ -240,7 +252,7 @@ int av7110_bootarm(struct av7110 *av7110)
mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode)); mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); 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(): " printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
"saa7146_wait_for_debi_done() timed out\n"); "saa7146_wait_for_debi_done() timed out\n");
return -1; return -1;
...@@ -258,7 +270,7 @@ int av7110_bootarm(struct av7110 *av7110) ...@@ -258,7 +270,7 @@ int av7110_bootarm(struct av7110 *av7110)
dprintk(1, "load dpram code\n"); dprintk(1, "load dpram code\n");
mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram); 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(): " printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
"saa7146_wait_for_debi_done() timed out after loading DRAM\n"); "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
return -1; return -1;
...@@ -305,6 +317,8 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) ...@@ -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 #ifndef _NOHANDSHAKE
start = jiffies; start = jiffies;
while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) { while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) {
...@@ -334,6 +348,8 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) ...@@ -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, COMMAND, (u32) buf[0], 2);
wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
#ifdef COM_DEBUG #ifdef COM_DEBUG
start = jiffies; start = jiffies;
while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) { while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) {
......
...@@ -162,7 +162,7 @@ static struct v4l2_audio msp3400_v4l2_audio = { ...@@ -162,7 +162,7 @@ static struct v4l2_audio msp3400_v4l2_audio = {
.capability = V4L2_AUDCAP_STEREO .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_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data; struct saa7146_vv *vv = dev->vv_data;
...@@ -227,7 +227,7 @@ int av7110_dvb_c_switch(struct saa7146_fh *fh) ...@@ -227,7 +227,7 @@ int av7110_dvb_c_switch(struct saa7146_fh *fh)
return 0; 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 saa7146_dev *dev = fh->dev;
struct av7110 *av7110 = (struct av7110*) dev->ext_priv; struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
...@@ -424,7 +424,7 @@ int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) ...@@ -424,7 +424,7 @@ int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
* INITIALIZATION * INITIALIZATION
****************************************************************************/ ****************************************************************************/
struct saa7146_extension_ioctls ioctls[] = { static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
...@@ -684,7 +684,7 @@ static struct saa7146_ext_vv av7110_vv_data_st = { ...@@ -684,7 +684,7 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
.flags = 0, .flags = 0,
.stds = &standard[0], .stds = &standard[0],
.num_stds = sizeof(standard) / sizeof(struct saa7146_standard), .num_stds = ARRAY_SIZE(standard),
.std_callback = &std_callback, .std_callback = &std_callback,
.ioctls = &ioctls[0], .ioctls = &ioctls[0],
...@@ -698,7 +698,7 @@ static struct saa7146_ext_vv av7110_vv_data_c = { ...@@ -698,7 +698,7 @@ static struct saa7146_ext_vv av7110_vv_data_c = {
.flags = SAA7146_USE_PORT_B_FOR_VBI, .flags = SAA7146_USE_PORT_B_FOR_VBI,
.stds = &standard[0], .stds = &standard[0],
.num_stds = sizeof(standard) / sizeof(struct saa7146_standard), .num_stds = ARRAY_SIZE(standard),
.std_callback = &std_callback, .std_callback = &std_callback,
.ioctls = &ioctls[0], .ioctls = &ioctls[0],
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
* *
* Compiled from various sources by Michael Hunold <michael@mihu.de> * 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) 2002 Ralph Metzler <rjkm@metzlerbros.de>
* *
* Copyright (C) 1999-2002 Ralph Metzler * Copyright (C) 1999-2002 Ralph Metzler
...@@ -31,15 +34,34 @@ ...@@ -31,15 +34,34 @@
*/ */
#include "budget.h" #include "budget.h"
#include "stv0299.h"
#include "tda10021.h"
#include "tda1004x.h"
#include <media/saa7146_vv.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_av {
struct budget budget; struct budget budget;
struct video_device *vd; struct video_device *vd;
int cur_input; int cur_input;
int has_saa7113; int has_saa7113;
struct tasklet_struct ciintf_irq_tasklet;
int slot_status;
struct dvb_ca_en50221 ca;
}; };
int enable_ci = 0;
/**************************************************************************** /****************************************************************************
* INITIALIZATION * INITIALIZATION
****************************************************************************/ ****************************************************************************/
...@@ -55,8 +77,10 @@ static u8 i2c_readreg (struct i2c_adapter *i2c, u8 id, u8 reg) ...@@ -55,8 +77,10 @@ static u8 i2c_readreg (struct i2c_adapter *i2c, u8 id, u8 reg)
msgs[1].flags = I2C_M_RD; msgs[1].flags = I2C_M_RD;
msgs[0].addr = msgs[1].addr=id/2; msgs[0].addr = msgs[1].addr=id/2;
mm1[0] = reg; mm1[0] = reg;
msgs[0].len = 1; msgs[1].len = 1; msgs[0].len = 1;
msgs[0].buf = mm1; msgs[1].buf = mm2; msgs[1].len = 1;
msgs[0].buf = mm1;
msgs[1].buf = mm2;
i2c_transfer(i2c, msgs, 2); i2c_transfer(i2c, msgs, 2);
...@@ -90,6 +114,211 @@ static int i2c_writereg (struct i2c_adapter *i2c, u8 id, u8 reg, u8 val) ...@@ -90,6 +114,211 @@ static int i2c_writereg (struct i2c_adapter *i2c, u8 id, u8 reg, u8 val)
return i2c_transfer(i2c, &msgs, 1); 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[] = { static const u8 saa7113_tab[] = {
0x01, 0x08, 0x01, 0x08,
...@@ -165,6 +394,397 @@ static int saa7113_setinput (struct budget_av *budget_av, int input) ...@@ -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) static int budget_av_detach (struct saa7146_dev *dev)
{ {
struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
...@@ -180,6 +800,11 @@ static int budget_av_detach (struct saa7146_dev *dev) ...@@ -180,6 +800,11 @@ static int budget_av_detach (struct saa7146_dev *dev)
saa7146_unregister_device (&budget_av->vd, 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); err = ttpci_budget_deinit (&budget_av->budget);
kfree (budget_av); kfree (budget_av);
...@@ -189,28 +814,24 @@ static int budget_av_detach (struct saa7146_dev *dev) ...@@ -189,28 +814,24 @@ static int budget_av_detach (struct saa7146_dev *dev)
static struct saa7146_ext_vv vv_data; static struct saa7146_ext_vv vv_data;
static int budget_av_attach (struct saa7146_dev* dev, static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
struct saa7146_pci_extension_data *info)
{ {
struct budget_av *budget_av; struct budget_av *budget_av;
struct budget_info *bi = info->ext_priv;
u8 *mac; u8 *mac;
int err; int err;
dprintk(2, "dev: %p\n", dev); 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))) if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
memset(budget_av, 0, sizeof(struct budget_av)); memset(budget_av, 0, sizeof(struct budget_av));
budget_av->budget.ci_present = 0;
dev->ext_priv = budget_av; 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); kfree(budget_av);
return err; return err;
} }
...@@ -220,8 +841,6 @@ static int budget_av_attach (struct saa7146_dev* dev, ...@@ -220,8 +841,6 @@ static int budget_av_attach (struct saa7146_dev* dev,
saa7146_write(dev, DD1_INIT, 0x07000600); saa7146_write(dev, DD1_INIT, 0x07000600);
saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26); saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
//test_knc_ci(av7110);
saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI); saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
msleep(500); msleep(500);
...@@ -234,9 +853,7 @@ static int budget_av_attach (struct saa7146_dev* dev, ...@@ -234,9 +853,7 @@ static int budget_av_attach (struct saa7146_dev* dev,
return err; return err;
} }
if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
VFL_TYPE_GRABBER)))
{
/* fixme: proper cleanup here */ /* fixme: proper cleanup here */
ERR(("cannot register capture v4l2 device.\n")); ERR(("cannot register capture v4l2 device.\n"));
return err; return err;
...@@ -261,15 +878,20 @@ static int budget_av_attach (struct saa7146_dev* dev, ...@@ -261,15 +878,20 @@ static int budget_av_attach (struct saa7146_dev* dev,
printk("KNC1-%d: Could not read MAC from KNC1 card\n", printk("KNC1-%d: Could not read MAC from KNC1 card\n",
budget_av->budget.dvb_adapter->num); budget_av->budget.dvb_adapter->num);
memset(mac, 0, 6); memset(mac, 0, 6);
} } else {
else
printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
budget_av->budget.dvb_adapter->num, budget_av->budget.dvb_adapter->num,
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 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 #define KNC1_INPUTS 2
static struct v4l2_input knc1_inputs[KNC1_INPUTS] = { 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) ...@@ -290,12 +912,9 @@ static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{ {
struct saa7146_dev *dev = fh->dev; struct saa7146_dev *dev = fh->dev;
struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
/*
struct saa7146_vv *vv = dev->vv_data;
*/
switch(cmd) { switch(cmd) {
case VIDIOC_ENUMINPUT: case VIDIOC_ENUMINPUT:{
{
struct v4l2_input *i = arg; struct v4l2_input *i = arg;
dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index); 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) ...@@ -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)); memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
return 0; return 0;
} }
case VIDIOC_G_INPUT: case VIDIOC_G_INPUT:{
{
int *input = (int *)arg; int *input = (int *)arg;
*input = budget_av->cur_input; *input = budget_av->cur_input;
...@@ -314,8 +932,7 @@ static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) ...@@ -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); dprintk(1, "VIDIOC_G_INPUT %d.\n", *input);
return 0; return 0;
} }
case VIDIOC_S_INPUT: case VIDIOC_S_INPUT:{
{
int input = *(int *)arg; int input = *(int *)arg;
dprintk(1, "VIDIOC_S_INPUT %d.\n", input); dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
return saa7113_setinput (budget_av, input); return saa7113_setinput (budget_av, input);
...@@ -327,17 +944,15 @@ static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) ...@@ -327,17 +944,15 @@ static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
} }
static struct saa7146_standard standard[] = { static struct saa7146_standard standard[] = {
{ {.name = "PAL",.id = V4L2_STD_PAL,
.name = "PAL", .id = V4L2_STD_PAL,
.v_offset = 0x17, .v_field = 288, .v_offset = 0x17, .v_field = 288,
.h_offset = 0x14, .h_pixels = 680, .h_offset = 0x14, .h_pixels = 680,
.v_max_out = 576, .h_max_out = 768 .v_max_out = 576,.h_max_out = 768 },
}, {
.name = "NTSC", .id = V4L2_STD_NTSC, {.name = "NTSC",.id = V4L2_STD_NTSC,
.v_offset = 0x16, .v_field = 240, .v_offset = 0x16, .v_field = 240,
.h_offset = 0x06, .h_pixels = 708, .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 = { static struct saa7146_ext_vv vv_data = {
...@@ -350,17 +965,22 @@ static struct saa7146_ext_vv vv_data = { ...@@ -350,17 +965,22 @@ static struct saa7146_ext_vv vv_data = {
.ioctl = av_ioctl, .ioctl = av_ioctl,
}; };
static struct saa7146_extension budget_extension; static struct saa7146_extension budget_extension;
MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1); MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
MAKE_BUDGET_INFO(cin1200, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200); 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 [] = { static struct pci_device_id pci_tbl [] = {
MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56), MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
MAKE_EXTENSION_PCI(cin1200, 0x153b, 0x1154), 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, .vendor = 0,
} }
...@@ -377,7 +997,7 @@ static struct saa7146_extension budget_extension = { ...@@ -377,7 +997,7 @@ static struct saa7146_extension budget_extension = {
.detach = budget_av_detach, .detach = budget_av_detach,
.irq_mask = MASK_10, .irq_mask = MASK_10,
.irq_func = ttpci_budget_irq10_handler, .irq_func = budget_av_irq,
}; };
static int __init budget_av_init(void) static int __init budget_av_init(void)
...@@ -396,5 +1016,6 @@ module_exit(budget_av_exit); ...@@ -396,5 +1016,6 @@ module_exit(budget_av_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others"); MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
MODULE_DESCRIPTION("driver for the SAA7146 based so-called " 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 @@ ...@@ -39,6 +39,8 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include "dvb_ca_en50221.h" #include "dvb_ca_en50221.h"
#include "stv0299.h"
#include "tda1004x.h"
#define DEBIADDR_IR 0x1234 #define DEBIADDR_IR 0x1234
#define DEBIADDR_CICONTROL 0x0000 #define DEBIADDR_CICONTROL 0x0000
...@@ -64,72 +66,11 @@ struct budget_ci { ...@@ -64,72 +66,11 @@ struct budget_ci {
struct input_dev input_dev; struct input_dev input_dev;
struct tasklet_struct msp430_irq_tasklet; struct tasklet_struct msp430_irq_tasklet;
struct tasklet_struct ciintf_irq_tasklet; struct tasklet_struct ciintf_irq_tasklet;
spinlock_t debilock;
int slot_status; int slot_status;
struct dvb_ca_en50221 ca; struct dvb_ca_en50221 ca;
char ir_dev_name[50]; 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: /* from reading the following remotes:
Zenith Universal 7 / TV Mode 807 / VCR Mode 837 Zenith Universal 7 / TV Mode 807 / VCR Mode 837
Hauppauge (from NOVA-CI-s box product) Hauppauge (from NOVA-CI-s box product)
...@@ -206,7 +147,8 @@ static void msp430_ir_interrupt (unsigned long data) ...@@ -206,7 +147,8 @@ static void msp430_ir_interrupt (unsigned long data)
{ {
struct budget_ci *budget_ci = (struct budget_ci*) data; struct budget_ci *budget_ci = (struct budget_ci*) data;
struct input_dev *dev = &budget_ci->input_dev; 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) { if (code & 0x40) {
code &= 0x3f; code &= 0x3f;
...@@ -221,8 +163,7 @@ static void msp430_ir_interrupt (unsigned long data) ...@@ -221,8 +163,7 @@ static void msp430_ir_interrupt (unsigned long data)
} }
if (!key_map[code]) { if (!key_map[code]) {
printk ("DVB (%s): no key for %02x!\n", printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code);
__FUNCTION__, code);
return; return;
} }
...@@ -281,79 +222,98 @@ static void msp430_ir_deinit (struct budget_ci *budget_ci) ...@@ -281,79 +222,98 @@ static void msp430_ir_deinit (struct budget_ci *budget_ci)
input_unregister_device(dev); 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; 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; 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; 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; 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 budget_ci* budget_ci = (struct budget_ci*) ca->data;
struct saa7146_dev *saa = budget_ci->budget.dev; 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 // trigger on RISING edge during reset so we know when READY is re-asserted
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
budget_ci->slot_status = SLOTSTATUS_RESET; 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); 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); saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
return 0; 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 budget_ci* budget_ci = (struct budget_ci*) ca->data;
struct saa7146_dev *saa = budget_ci->budget.dev; 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); saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
return 0; 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 budget_ci* budget_ci = (struct budget_ci*) ca->data;
struct saa7146_dev *saa = budget_ci->budget.dev; struct saa7146_dev *saa = budget_ci->budget.dev;
int tmp; int tmp;
if (slot != 0) return -EINVAL; if (slot != 0)
return -EINVAL;
saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO); saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
tmp = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1); tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, tmp | CICONTROL_ENABLETS); ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
tmp | CICONTROL_ENABLETS, 1, 0);
ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
return 0; return 0;
...@@ -367,10 +327,11 @@ static void ciintf_interrupt (unsigned long data) ...@@ -367,10 +327,11 @@ static void ciintf_interrupt (unsigned long data)
unsigned int flags; unsigned int flags;
// ensure we don't get spurious IRQs during initialisation // 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 // 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) { if (flags & CICONTROL_CAMDETECT) {
// GPIO should be set to trigger on falling edge if a CAM is present // 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) ...@@ -379,7 +340,8 @@ static void ciintf_interrupt (unsigned long data)
if (budget_ci->slot_status & SLOTSTATUS_NONE) { if (budget_ci->slot_status & SLOTSTATUS_NONE) {
// CAM insertion IRQ // CAM insertion IRQ
budget_ci->slot_status = SLOTSTATUS_PRESENT; 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) { } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
// CAM ready (reset completed) // CAM ready (reset completed)
...@@ -401,7 +363,8 @@ static void ciintf_interrupt (unsigned long data) ...@@ -401,7 +363,8 @@ static void ciintf_interrupt (unsigned long data)
if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) { if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
// CAM removal IRQ // CAM removal IRQ
budget_ci->slot_status = SLOTSTATUS_NONE; 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) ...@@ -418,18 +381,18 @@ static int ciintf_init(struct budget_ci* budget_ci)
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
// test if it is there // 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; result = -ENODEV;
goto error; goto error;
} }
// determine whether a CAM is present or not // 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; 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 // register CI interface
budget_ci->ca.owner = THIS_MODULE;
budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem; budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem; budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
budget_ci->ca.read_cam_control = ciintf_read_cam_control; budget_ci->ca.read_cam_control = ciintf_read_cam_control;
...@@ -442,8 +405,7 @@ static int ciintf_init(struct budget_ci* budget_ci) ...@@ -442,8 +405,7 @@ static int ciintf_init(struct budget_ci* budget_ci)
&budget_ci->ca, &budget_ci->ca,
DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
DVB_CA_EN50221_FLAG_IRQ_FR | DVB_CA_EN50221_FLAG_IRQ_FR |
DVB_CA_EN50221_FLAG_IRQ_DA, DVB_CA_EN50221_FLAG_IRQ_DA, 1)) != 0) {
1)) != 0) {
printk("budget_ci: CI interface detected, but initialisation failed.\n"); printk("budget_ci: CI interface detected, but initialisation failed.\n");
goto error; goto error;
} }
...@@ -456,7 +418,8 @@ static int ciintf_init(struct budget_ci* budget_ci) ...@@ -456,7 +418,8 @@ static int ciintf_init(struct budget_ci* budget_ci)
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
} }
saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); 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! // success!
printk("budget_ci: CI interface initialised\n"); printk("budget_ci: CI interface initialised\n");
...@@ -464,7 +427,8 @@ static int ciintf_init(struct budget_ci* budget_ci) ...@@ -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 // forge a fake CI IRQ so the CAM state is setup correctly
flags = DVB_CA_EN50221_CAMCHANGE_REMOVED; 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); dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
return 0; return 0;
...@@ -482,9 +446,10 @@ static void ciintf_deinit(struct budget_ci* budget_ci) ...@@ -482,9 +446,10 @@ static void ciintf_deinit(struct budget_ci* budget_ci)
saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03);
saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
tasklet_kill(&budget_ci->ciintf_irq_tasklet); 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); 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 // disable TS data stream to CI interface
saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT); saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
...@@ -513,9 +478,425 @@ static void budget_ci_irq (struct saa7146_dev *dev, u32 *isr) ...@@ -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 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 budget_ci_attach (struct saa7146_dev* dev, static int philips_tdm1316l_pll_init(struct dvb_frontend *fe)
struct saa7146_pci_extension_data *info) {
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; struct budget_ci *budget_ci;
int err; int err;
...@@ -525,12 +906,11 @@ static int budget_ci_attach (struct saa7146_dev* dev, ...@@ -525,12 +906,11 @@ static int budget_ci_attach (struct saa7146_dev* dev,
dprintk(2, "budget_ci: %p\n", budget_ci); dprintk(2, "budget_ci: %p\n", budget_ci);
spin_lock_init(&budget_ci->debilock);
budget_ci->budget.ci_present = 0; budget_ci->budget.ci_present = 0;
dev->ext_priv = budget_ci; 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); kfree (budget_ci);
return err; return err;
} }
...@@ -542,6 +922,9 @@ static int budget_ci_attach (struct saa7146_dev* dev, ...@@ -542,6 +922,9 @@ static int budget_ci_attach (struct saa7146_dev* dev,
ciintf_init(budget_ci); ciintf_init(budget_ci);
budget_ci->budget.dvb_adapter->priv = budget_ci;
frontend_init(budget_ci);
return 0; return 0;
} }
...@@ -553,8 +936,10 @@ static int budget_ci_detach (struct saa7146_dev* dev) ...@@ -553,8 +936,10 @@ static int budget_ci_detach (struct saa7146_dev* dev)
struct saa7146_dev *saa = budget_ci->budget.dev; struct saa7146_dev *saa = budget_ci->budget.dev;
int err; 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); err = ttpci_budget_deinit (&budget_ci->budget);
tasklet_kill (&budget_ci->msp430_irq_tasklet); tasklet_kill (&budget_ci->msp430_irq_tasklet);
......
...@@ -74,8 +74,7 @@ static int start_ts_capture (struct budget *budget) ...@@ -74,8 +74,7 @@ static int start_ts_capture (struct budget *budget)
memset(budget->grabbing, 0x00, TS_HEIGHT*TS_WIDTH); memset(budget->grabbing, 0x00, TS_HEIGHT*TS_WIDTH);
saa7146_write(dev, PCI_BT_V1, 0x001c0000 | saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
(saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
budget->tsf=0xff; budget->tsf=0xff;
budget->ttbp=0; budget->ttbp=0;
...@@ -150,14 +149,87 @@ static void vpeirq (unsigned long data) ...@@ -150,14 +149,87 @@ static void vpeirq (unsigned long data)
return; return;
if (newdma > olddma) { /* no wraparound, dump olddma..newdma */ if (newdma > olddma) { /* no wraparound, dump olddma..newdma */
dvb_dmx_swfilter_packets(&budget->demux, dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (newdma - olddma) / 188);
mem+olddma, (newdma-olddma) / 188);
} else { /* wraparound, dump olddma..buflen and 0..newdma */ } else { /* wraparound, dump olddma..buflen and 0..newdma */
dvb_dmx_swfilter_packets(&budget->demux, dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
mem+olddma, (TS_BUFLEN-olddma) / 188); dvb_dmx_swfilter_packets(&budget->demux, mem, newdma / 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) ...@@ -231,13 +303,11 @@ static int budget_register(struct budget *budget)
return ret; return ret;
budget->mem_frontend.source = DMX_MEMORY_FE; budget->mem_frontend.source = DMX_MEMORY_FE;
ret=dvbdemux->dmx.add_frontend (&dvbdemux->dmx, ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->mem_frontend);
&budget->mem_frontend);
if (ret<0) if (ret<0)
return ret; return ret;
ret=dvbdemux->dmx.connect_frontend (&dvbdemux->dmx, ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &budget->hw_frontend);
&budget->hw_frontend);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -263,30 +333,9 @@ static void budget_unregister(struct budget *budget) ...@@ -263,30 +333,9 @@ static void budget_unregister(struct budget *budget)
dvb_dmx_release(&budget->demux); dvb_dmx_release(&budget->demux);
} }
/* fixme: can this be unified among all saa7146 based dvb cards? */ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
static int client_register(struct i2c_client *client) struct saa7146_pci_extension_data *info,
{ struct module *owner)
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 length = TS_WIDTH*TS_HEIGHT; int length = TS_WIDTH*TS_HEIGHT;
int ret = 0; int ret = 0;
...@@ -299,7 +348,7 @@ int ttpci_budget_init (struct budget *budget, ...@@ -299,7 +348,7 @@ int ttpci_budget_init (struct budget *budget,
budget->card = bi; budget->card = bi;
budget->dev = (struct saa7146_dev *) dev; 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 */ /* set dd1 stream a & b */
saa7146_write(dev, DD1_STREAM_B, 0x00000000); saa7146_write(dev, DD1_STREAM_B, 0x00000000);
...@@ -313,21 +362,18 @@ int ttpci_budget_init (struct budget *budget, ...@@ -313,21 +362,18 @@ int ttpci_budget_init (struct budget *budget,
else else
budget->video_port = BUDGET_VIDEO_PORTA; budget->video_port = BUDGET_VIDEO_PORTA;
spin_lock_init(&budget->feedlock); spin_lock_init(&budget->feedlock);
spin_lock_init(&budget->debilock);
/* the Siemens DVB needs this if you want to have the i2c chips /* the Siemens DVB needs this if you want to have the i2c chips
get recognized before the main driver is loaded */ get recognized before the main driver is loaded */
if (bi->type != BUDGET_FS_ACTIVY) if (bi->type != BUDGET_FS_ACTIVY)
saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */ 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 #ifdef I2C_ADAP_CLASS_TV_DIGITAL
.class = I2C_ADAP_CLASS_TV_DIGITAL, budget->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
#else #else
.class = I2C_CLASS_TV_DIGITAL, budget->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
#endif #endif
};
strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name)); strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name));
...@@ -341,7 +387,8 @@ int ttpci_budget_init (struct budget *budget, ...@@ -341,7 +387,8 @@ int ttpci_budget_init (struct budget *budget,
ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter->proposed_mac); 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; ret = -ENOMEM;
goto err; goto err;
} }
...@@ -420,8 +467,8 @@ void ttpci_budget_set_video_port(struct saa7146_dev* dev, int video_port) ...@@ -420,8 +467,8 @@ void ttpci_budget_set_video_port(struct saa7146_dev* dev, int video_port)
spin_unlock(&budget->feedlock); 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_init);
EXPORT_SYMBOL_GPL(ttpci_budget_deinit); EXPORT_SYMBOL_GPL(ttpci_budget_deinit);
EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler); EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
......
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
#include "av7110.h" #include "av7110.h"
#include "av7110_hw.h" #include "av7110_hw.h"
#include "budget.h" #include "budget.h"
#include "stv0299.h"
#include "ves1x93.h"
#include "tda8083.h"
#define budget_patch budget #define budget_patch budget
...@@ -121,16 +124,11 @@ static int av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg, ...@@ -121,16 +124,11 @@ static int av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg,
return 0; return 0;
} }
static int budget_patch_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
int budget_patch_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
{ {
struct budget_patch *budget = fe->before_after_data; struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
dprintk(2, "budget: %p\n", budget);
switch (cmd) { switch (tone) {
case FE_SET_TONE:
switch ((fe_sec_tone_mode_t) arg) {
case SEC_TONE_ON: case SEC_TONE_ON:
av7110_set22k (budget, 1); av7110_set22k (budget, 1);
break; break;
...@@ -140,27 +138,232 @@ int budget_patch_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void * ...@@ -140,27 +138,232 @@ int budget_patch_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *
default: default:
return -EINVAL; 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); av7110_send_diseqc_msg (budget, cmd->msg_len, cmd->msg, 0);
break;
return 0;
} }
case FE_DISEQC_SEND_BURST: static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
av7110_send_diseqc_msg (budget, 0, NULL, (int) (long) arg); {
break; struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
av7110_send_diseqc_msg (budget, 0, NULL, minicmd);
default: return 0;
return -EOPNOTSUPP;
} }
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; 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) 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 ...@@ -173,7 +376,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
dprintk(2, "budget: %p\n", budget); 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); kfree (budget);
return err; return err;
} }
...@@ -221,11 +424,11 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte ...@@ -221,11 +424,11 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
// Enable RPS1 (rFC p33) // Enable RPS1 (rFC p33)
saa7146_write(dev, MC1, (MASK_13 | MASK_29)); 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; dev->ext_priv = budget;
budget->dvb_adapter->priv = budget;
frontend_init(budget);
return 0; return 0;
} }
...@@ -235,8 +438,7 @@ static int budget_patch_detach (struct saa7146_dev* dev) ...@@ -235,8 +438,7 @@ static int budget_patch_detach (struct saa7146_dev* dev)
struct budget_patch *budget = (struct budget_patch*) dev->ext_priv; struct budget_patch *budget = (struct budget_patch*) dev->ext_priv;
int err; int err;
dvb_remove_frontend_ioctls (budget->dvb_adapter, if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
budget_patch_diseqc_ioctl, NULL);
err = ttpci_budget_deinit (budget); err = ttpci_budget_deinit (budget);
......
...@@ -35,6 +35,11 @@ ...@@ -35,6 +35,11 @@
*/ */
#include "budget.h" #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) static void Set22K (struct budget *budget, int state)
{ {
...@@ -105,89 +110,368 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long ...@@ -105,89 +110,368 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long
return 0; 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); dprintk(2, "budget: %p\n", budget);
switch (cmd) { switch (voltage) {
case FE_SET_TONE: case SEC_VOLTAGE_13:
switch ((fe_sec_tone_mode_t) arg) { 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: case SEC_TONE_ON:
Set22K (budget, 1); Set22K (budget, 1);
break; break;
case SEC_TONE_OFF: case SEC_TONE_OFF:
Set22K (budget, 0); Set22K (budget, 0);
break; break;
default: default:
return -EINVAL; return -EINVAL;
}; }
break;
case FE_DISEQC_SEND_MASTER_CMD: return 0;
}
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); SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
break;
return 0;
} }
case FE_DISEQC_SEND_BURST: static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
SendDiSEqCMsg (budget, 0, NULL, (unsigned long)arg); {
break; struct budget* budget = (struct budget*) fe->dvb->priv;
default: SendDiSEqCMsg (budget, 0, NULL, minicmd);
return -EOPNOTSUPP;
};
return 0; 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;
}
/* static struct ves1x93_config alps_bsrv2_config =
* 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 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) { static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
case SEC_VOLTAGE_13: {
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO); u8 aclk = 0;
break; u8 bclk = 0;
case SEC_VOLTAGE_18:
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
break; else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
default: else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
return -EINVAL; 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; 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) { data[0] = (div >> 8) & 0x7f;
case FE_SET_VOLTAGE: data[1] = div & 0xff;
return SetVoltage_Activy (budget, (fe_sec_voltage_t) arg); data[2] = 0x85 | ((div >> 10) & 0x60);
default: data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
return -EOPNOTSUPP;
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; 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) 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_ ...@@ -203,18 +487,14 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_
dev->ext_priv = budget; 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"); printk("==> failed\n");
kfree (budget); kfree (budget);
return err; return err;
} }
if (budget->card->type == BUDGET_FS_ACTIVY) budget->dvb_adapter->priv = budget;
dvb_add_frontend_ioctls (budget->dvb_adapter, frontend_init(budget);
budget_ioctl_activy, NULL, budget);
else
dvb_add_frontend_ioctls (budget->dvb_adapter,
budget_diseqc_ioctl, NULL, budget);
return 0; return 0;
} }
...@@ -225,12 +505,7 @@ static int budget_detach (struct saa7146_dev* dev) ...@@ -225,12 +505,7 @@ static int budget_detach (struct saa7146_dev* dev)
struct budget *budget = (struct budget*) dev->ext_priv; struct budget *budget = (struct budget*) dev->ext_priv;
int err; int err;
if (budget->card->type == BUDGET_FS_ACTIVY) if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
dvb_remove_frontend_ioctls (budget->dvb_adapter,
budget_ioctl_activy, NULL);
else
dvb_remove_frontend_ioctls (budget->dvb_adapter,
budget_diseqc_ioctl, NULL);
err = ttpci_budget_deinit (budget); err = ttpci_budget_deinit (budget);
...@@ -247,18 +522,14 @@ static struct saa7146_extension budget_extension; ...@@ -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(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C 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(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); 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[] = { 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(ttbs, 0x13c2, 0x1003),
MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004), MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004),
MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005), 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), MAKE_EXTENSION_PCI(fsacs, 0x1131, 0x4f61),
{ {
.vendor = 0, .vendor = 0,
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "dvb_filter.h" #include "dvb_filter.h"
#include "dvb_net.h" #include "dvb_net.h"
#include <linux/module.h>
#include <media/saa7146.h> #include <media/saa7146.h>
extern int budget_debug; extern int budget_debug;
...@@ -61,7 +62,10 @@ struct budget { ...@@ -61,7 +62,10 @@ struct budget {
spinlock_t feedlock; spinlock_t feedlock;
spinlock_t debilock;
struct dvb_adapter *dvb_adapter; struct dvb_adapter *dvb_adapter;
struct dvb_frontend *dvb_frontend;
void *priv; void *priv;
}; };
...@@ -82,20 +86,27 @@ static struct saa7146_pci_extension_data x_var = { \ ...@@ -82,20 +86,27 @@ static struct saa7146_pci_extension_data x_var = { \
#define BUDGET_TT 0 #define BUDGET_TT 0
#define BUDGET_TT_HW_DISEQC 1 #define BUDGET_TT_HW_DISEQC 1
#define BUDGET_KNC1 2
#define BUDGET_PATCH 3 #define BUDGET_PATCH 3
#define BUDGET_FS_ACTIVY 4 #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_PORTA 0
#define BUDGET_VIDEO_PORTB 1 #define BUDGET_VIDEO_PORTB 1
extern int ttpci_budget_init (struct budget *budget, extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
struct saa7146_dev* dev, struct saa7146_pci_extension_data *info,
struct saa7146_pci_extension_data *info); struct module *owner);
extern int ttpci_budget_deinit (struct budget *budget); extern int ttpci_budget_deinit (struct budget *budget);
extern void ttpci_budget_irq10_handler (struct saa7146_dev* dev, u32 *isr); 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 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 #endif
...@@ -1190,7 +1190,7 @@ static int philips_tdm1316l_request_firmware(struct dvb_frontend* fe, const stru ...@@ -1190,7 +1190,7 @@ static int philips_tdm1316l_request_firmware(struct dvb_frontend* fe, const stru
return request_firmware(fw, name, &ttusb->dev->dev); return request_firmware(fw, name, &ttusb->dev->dev);
} }
struct tda1004x_config philips_tdm1316l_config = { static struct tda1004x_config philips_tdm1316l_config = {
.demod_address = 0x8, .demod_address = 0x8,
.invert = 1, .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