Commit 47d3a8f9 authored by Johannes Stezenbach's avatar Johannes Stezenbach Committed by Linus Torvalds

[PATCH] dvb: dvb-ttpci: fix SMP race, budget: fixe init race, misc fixes

- [DVB] dvb-ttpci: re-added support for Fujitsu-Siemens DVB-S rev 1.6 0x13c2:0x0006
- [DVB] dvb-ttpci: finally clean up debi irq/tasklet handling to make it work on SMP
- [DVB] dvb-ttpci: misc. changes to av7110_send_fw_cmd() error handling done along the way
- [DVB] dvb-ttpci: budgetpatch integrated into dvb-ttpci: enables full ts option running
        in parallel with all previous functions of dvb-ttpci
- [DVB] dvb-ttpci: fix Oops provoked by insmod/rmmod test loop, patch by Emard
- [DVB] budget: Fixed start_ts_capture(): saa7146 will not issue a VPE interrupt
        if VPE bit is set in PSR and VPE interrupts are enabled afterwards.
- [DVB] budget: enable satelco support. code was commented out, but actually it works, patch by Emard
- [DVB] budget: Budget patch improved driver, fixed slight packet loss by using different trigger mode
Signed-off-by: default avatarMichael Hunold <hunold@linuxtv.org>
Signed-off-by: default avatarJohannes Stezenbach <js@linuxtv.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent d6586193
This diff is collapsed.
......@@ -115,7 +115,7 @@ struct av7110 {
int bmpp;
int bmplen;
int bmp_state;
volatile int bmp_state;
#define BMP_NONE 0
#define BMP_LOADING 1
#define BMP_LOADINGS 2
......@@ -158,6 +158,18 @@ struct av7110 {
struct dmx_frontend hw_frontend;
struct dmx_frontend mem_frontend;
/* for budget mode demux1 */
struct dmxdev dmxdev1;
struct dvb_demux demux1;
struct dvb_net dvb_net1;
spinlock_t feedlock1;
int feeding1;
u8 tsf;
u32 ttbp;
unsigned char *grabbing;
struct saa7146_pgtable pt;
struct tasklet_struct vpe_tasklet;
int fe_synced;
struct semaphore pid_mutex;
......
......@@ -153,8 +153,10 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len)
base = DRAM_START_CODE;
for (i = 0; i < blocks; i++) {
if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0)
if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
return -1;
}
dprintk(4, "writing DRAM block %d\n", i);
mwdebi(av7110, DEBISWAB, bootblock,
((char*)data) + i * BOOT_MAX_SIZE, BOOT_MAX_SIZE);
......@@ -166,8 +168,10 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len)
}
if (rest > 0) {
if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0)
if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
return -1;
}
if (rest > 4)
mwdebi(av7110, DEBISWAB, bootblock,
((char*)data) + i * BOOT_MAX_SIZE, rest);
......@@ -179,12 +183,16 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len)
iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, rest, 2);
iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
}
if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0)
if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
return -1;
}
iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, 0, 2);
iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BOOT_COMPLETE) < 0)
if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BOOT_COMPLETE) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
return -1;
}
return 0;
}
......@@ -261,8 +269,11 @@ int av7110_bootarm(struct av7110 *av7110)
mdelay(1);
dprintk(1, "load dram code\n");
if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0)
if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) {
printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
"load_dram() failed\n");
return -1;
}
saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
mdelay(1);
......@@ -336,7 +347,7 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
if (!av7110->arm_ready) {
dprintk(1, "arm not ready.\n");
return -1;
return -ENXIO;
}
start = jiffies;
......@@ -344,7 +355,7 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
msleep(1);
if (time_after(jiffies, start + ARM_WAIT_FREE)) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
return -1;
return -ETIMEDOUT;
}
}
......@@ -356,7 +367,7 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
msleep(1);
if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
return -1;
return -ETIMEDOUT;
}
}
#endif
......@@ -375,6 +386,13 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
flags[0] = OSDQOver;
flags[1] = OSDQFull;
break;
case COMTYPE_MISC:
if (FW_VERSION(av7110->arm_app) >= 0x261d) {
type = "MSG";
flags[0] = GPMQOver;
flags[1] = GPMQBusy;
}
break;
default:
break;
}
......@@ -419,18 +437,18 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
if (time_after(jiffies, start + ARM_WAIT_FREE)) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND to complete\n",
__FUNCTION__);
return -1;
return -ETIMEDOUT;
}
}
stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
if (stat & GPMQOver) {
printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
return -1;
return -ENOSPC;
}
else if (stat & OSDQOver) {
printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
return -1;
return -ENOSPC;
}
#endif
......@@ -453,7 +471,8 @@ int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
ret = __av7110_send_fw_cmd(av7110, buf, length);
up(&av7110->dcomlock);
if (ret)
printk("dvb-ttpci: %s(): av7110_send_fw_cmd error\n", __FUNCTION__);
printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
__FUNCTION__, ret);
return ret;
}
......@@ -477,7 +496,7 @@ int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
ret = av7110_send_fw_cmd(av7110, buf, num + 2);
if (ret)
printk("dvb-ttpci: av7110_fw_cmd error\n");
printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
return ret;
}
......@@ -499,7 +518,7 @@ int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
ret = av7110_send_fw_cmd(av7110, cmd, 18);
if (ret)
printk("dvb-ttpci: av7110_send_ci_cmd error\n");
printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
return ret;
}
......@@ -525,7 +544,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
up(&av7110->dcomlock);
printk("dvb-ttpci: av7110_fw_request error\n");
printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
return err;
}
......@@ -579,7 +598,7 @@ int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
int ret;
ret = av7110_fw_request(av7110, &tag, 0, buf, length);
if (ret)
printk("dvb-ttpci: av7110_fw_query error\n");
printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret);
return ret;
}
......@@ -626,7 +645,7 @@ int av7110_firmversion(struct av7110 *av7110)
int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
{
int i;
int i, ret;
u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
......@@ -646,8 +665,8 @@ int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long bu
for (i = 0; i < len; i++)
buf[i + 4] = msg[i];
if (av7110_send_fw_cmd(av7110, buf, 18))
printk("dvb-ttpci: av7110_diseqc_send error\n");
if ((ret = av7110_send_fw_cmd(av7110, buf, 18)))
printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
return 0;
}
......@@ -741,7 +760,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
up(&av7110->dcomlock);
if (ret)
printk("dvb-ttpci: WriteText error\n");
printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
return ret;
}
......@@ -808,7 +827,8 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format,
ret = wait_event_interruptible_timeout(av7110->bmpq, av7110->bmp_state != BMP_LOADING, HZ);
if (ret == -ERESTARTSYS || ret == 0) {
printk("dvb-ttpci: warning: timeout waiting in %s()\n", __FUNCTION__);
printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
ret, av7110->bmp_state);
av7110->bmp_state = BMP_NONE;
return -1;
}
......@@ -850,6 +870,7 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format,
}
}
av7110->bmplen += 1024;
dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
return av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
}
......@@ -861,11 +882,13 @@ static int BlitBitmap(struct av7110 *av7110, u16 win, u16 x, u16 y, u16 trans)
BUG_ON (av7110->bmp_state == BMP_NONE);
ret = wait_event_interruptible_timeout(av7110->bmpq, av7110->bmp_state != BMP_LOADING, HZ);
ret = wait_event_interruptible_timeout(av7110->bmpq,
av7110->bmp_state != BMP_LOADING, 10*HZ);
if (ret == -ERESTARTSYS || ret == 0) {
printk("dvb-ttpci: warning: timeout waiting in %s()\n", __FUNCTION__);
printk("dvb-ttpci: warning: timeout waiting in BlitBitmap: %d, %d\n",
ret, av7110->bmp_state);
av7110->bmp_state = BMP_NONE;
return -1;
return (ret == 0) ? -ETIMEDOUT : ret;
}
BUG_ON (av7110->bmp_state != BMP_LOADED);
......@@ -943,6 +966,7 @@ static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
{
uint w, h, bpp, bpl, size, lpb, bnum, brest;
int i;
int rc;
w = x1 - x0 + 1;
h = y1 - y0 + 1;
......@@ -958,15 +982,23 @@ static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
brest = size - bnum * lpb * bpl;
for (i = 0; i < bnum; i++) {
LoadBitmap(av7110, bpp2bit[av7110->osdbpp[av7110->osdwin]],
rc = LoadBitmap(av7110, bpp2bit[av7110->osdbpp[av7110->osdwin]],
w, lpb, inc, data);
BlitBitmap(av7110, av7110->osdwin, x0, y0 + i * lpb, 0);
if (rc)
return rc;
rc = BlitBitmap(av7110, av7110->osdwin, x0, y0 + i * lpb, 0);
if (rc)
return rc;
data += lpb * inc;
}
if (brest) {
LoadBitmap(av7110, bpp2bit[av7110->osdbpp[av7110->osdwin]],
rc = LoadBitmap(av7110, bpp2bit[av7110->osdbpp[av7110->osdwin]],
w, brest / bpl, inc, data);
BlitBitmap(av7110, av7110->osdwin, x0, y0 + bnum * lpb, 0);
if (rc)
return rc;
rc = BlitBitmap(av7110, av7110->osdwin, x0, y0 + bnum * lpb, 0);
if (rc)
return rc;
}
ReleaseBitmap(av7110);
return 0;
......@@ -1019,7 +1051,7 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
goto out;
} else {
int i, len = dc->x0-dc->color+1;
u8 __user *colors = (u8 __user *)dc->data;
u8 __user *colors = (u8 *)dc->data;
u8 r, g, b, blend;
for (i = 0; i<len; i++) {
......@@ -1048,7 +1080,7 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
dc->y1 = dc->y0;
/* fall through */
case OSD_SetBlock:
OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
goto out;
case OSD_FillRow:
DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
......
......@@ -250,7 +250,7 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
dprintk(1, "setting band in demodulator failed.\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
}
}
......@@ -591,7 +591,7 @@ int av7110_init_analog_module(struct av7110 *av7110)
if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
dprintk(1, "setting band in demodulator failed.\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
}
......
......@@ -89,11 +89,18 @@ static int start_ts_capture (struct budget *budget)
* Pitch: 188, NumBytes3: 188, NumLines3: 1024
*/
if (budget->card->type == BUDGET_FS_ACTIVY) {
switch(budget->card->type) {
case BUDGET_FS_ACTIVY:
saa7146_write(dev, DD1_INIT, 0x04000000);
saa7146_write(dev, MC2, (MASK_09 | MASK_25));
saa7146_write(dev, BRS_CTRL, 0x00000000);
} else {
break;
case BUDGET_PATCH:
saa7146_write(dev, DD1_INIT, 0x00000200);
saa7146_write(dev, MC2, (MASK_10 | MASK_26));
saa7146_write(dev, BRS_CTRL, 0x60000000);
break;
default:
if (budget->video_port == BUDGET_VIDEO_PORTA) {
saa7146_write(dev, DD1_INIT, 0x06000200);
saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
......@@ -122,9 +129,10 @@ static int start_ts_capture (struct budget *budget)
}
saa7146_write(dev, MC2, (MASK_04 | MASK_20));
saa7146_write(dev, MC1, (MASK_04 | MASK_20)); // DMA3 on
SAA7146_IER_ENABLE(budget->dev, MASK_10); // VPE
SAA7146_ISR_CLEAR(budget->dev, MASK_10); /* VPE */
SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
saa7146_write(dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
return ++budget->feeding;
}
......@@ -249,6 +257,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed)
return -EINVAL;
spin_lock(&budget->feedlock);
feed->pusi_seen = 0; /* have a clean section start */
status = start_ts_capture (budget);
spin_unlock(&budget->feedlock);
return status;
......
This diff is collapsed.
......@@ -414,7 +414,7 @@ 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))
case 0x1013:
// try the ALPS BSRV2 first of all
budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
......@@ -522,14 +522,14 @@ static struct saa7146_extension budget_extension;
MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
/* MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); UNDEFINED HARDWARE - mail linuxtv.org list */
MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC);
MAKE_BUDGET_INFO(fsacs, "Fujitsu Siemens Activy Budget-S PCI", BUDGET_FS_ACTIVY);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003),
MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004),
MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005),
/* MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), UNDEFINED HARDWARE */
MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
MAKE_EXTENSION_PCI(fsacs, 0x1131, 0x4f61),
{
.vendor = 0,
......
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