summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
Diffstat (limited to 'linux')
-rw-r--r--linux/drivers/media/video/bttv-driver.c2
-rw-r--r--linux/drivers/media/video/cx88/cx88-blackbird.c6
-rw-r--r--linux/drivers/media/video/cx88/cx88-cards.c14
-rw-r--r--linux/drivers/media/video/cx88/cx88-core.c44
-rw-r--r--linux/drivers/media/video/cx88/cx88-dvb.c78
-rw-r--r--linux/drivers/media/video/cx88/cx88-i2c.c56
-rw-r--r--linux/drivers/media/video/cx88/cx88-mpeg.c67
-rw-r--r--linux/drivers/media/video/cx88/cx88-vbi.c2
-rw-r--r--linux/drivers/media/video/cx88/cx88-video.c5
-rw-r--r--linux/drivers/media/video/cx88/cx88.h16
10 files changed, 204 insertions, 86 deletions
diff --git a/linux/drivers/media/video/bttv-driver.c b/linux/drivers/media/video/bttv-driver.c
index f332ee8fa..c0cda0be5 100644
--- a/linux/drivers/media/video/bttv-driver.c
+++ b/linux/drivers/media/video/bttv-driver.c
@@ -1863,6 +1863,8 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
if (NULL == fh->ovfmt)
return -EINVAL;
+ if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
+ return -EINVAL;
retval = verify_window(&bttv_tvnorms[btv->tvnorm],win,fixup);
if (0 != retval)
return retval;
diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c
index 51f4b1e9a..218b2805f 100644
--- a/linux/drivers/media/video/cx88/cx88-blackbird.c
+++ b/linux/drivers/media/video/cx88/cx88-blackbird.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-blackbird.c,v 1.5 2004/08/25 14:47:53 kraxel Exp $
+ * $Id: cx88-blackbird.c,v 1.6 2004/08/31 11:58:53 kraxel Exp $
*
* Support for a cx23416 mpeg encoder via cx2388x host port.
* "blackbird" reference design.
@@ -848,8 +848,6 @@ static void __devexit blackbird_remove(struct pci_dev *pci_dev)
/* common */
cx8802_fini_common(dev);
- cx88_core_put(dev->core,dev->pci);
- kfree(dev);
}
static struct pci_device_id cx8802_pci_tbl[] = {
@@ -865,7 +863,7 @@ static struct pci_device_id cx8802_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
static struct pci_driver blackbird_pci_driver = {
- .name = "cx8802",
+ .name = "cx88-blackbird",
.id_table = cx8802_pci_tbl,
.probe = blackbird_probe,
.remove = blackbird_remove,
diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c
index c8f44c472..25fe03d86 100644
--- a/linux/drivers/media/video/cx88/cx88-cards.c
+++ b/linux/drivers/media/video/cx88/cx88-cards.c
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/delay.h>
#include "cx88.h"
@@ -316,12 +317,6 @@ struct cx88_board cx88_boards[] = {
.gpio0 = 0x000027df,
}},
.dvb = 1,
-#if 0
- .ts = {
- .type = CX88_TS,
- .gpio0 = 0x00000101, /* Hooked to tuner reset bit */
- }
-#endif
},
[CX88_BOARD_KWORLD_LTV883] = {
.name = "KWorld LTV883RF",
@@ -720,6 +715,13 @@ void cx88_card_setup(struct cx88_core *core)
case CX88_BOARD_KWORLD_LTV883:
core->has_radio = 1;
break;
+ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
+ /* Tuner reset is hooked to the tuner out of reset */
+ cx_set(MO_GP0_IO, 0x00000101);
+ cx_clear(MO_GP0_IO, 0x00000001);
+ msleep(1);
+ cx_set(MO_GP0_IO, 0x00000101);
+ break;
}
}
diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c
index 0c338a944..eaee42b9d 100644
--- a/linux/drivers/media/video/cx88/cx88-core.c
+++ b/linux/drivers/media/video/cx88/cx88-core.c
@@ -121,6 +121,7 @@ void cx88_print_ioctl(char *name, unsigned int cmd)
}
/* ------------------------------------------------------------------ */
+#define NO_SYNC_LINE (-1U)
static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
unsigned int offset, u32 sync_line,
@@ -131,7 +132,8 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
unsigned int line,todo;
/* sync instruction */
- *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+ if (sync_line != NO_SYNC_LINE)
+ *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
/* scan lines */
sg = sglist;
@@ -207,6 +209,30 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
return 0;
}
+int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+ struct scatterlist *sglist, unsigned int bpl,
+ unsigned int lines)
+{
+ u32 instructions;
+ u32 *rp;
+ int rc;
+
+ /* estimate risc mem: worst case is one write per page border +
+ one write per scan line + syncs + jump (all 2 dwords) */
+ instructions = (bpl * lines) / PAGE_SIZE + lines;
+ instructions += 3 + 4;
+ if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
+ return rc;
+
+ /* write risc instructions */
+ rp = risc->cpu;
+ rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
+
+ /* save pointer to jmp instruction address */
+ risc->jmp = rp;
+ return 0;
+}
+
int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
u32 reg, u32 mask, u32 value)
{
@@ -536,7 +562,10 @@ void cx88_print_irqbits(char *name, char *tag, char **strings,
for (i = 0; i < 32; i++) {
if (!(bits & (1 << i)))
continue;
- printk(" %s",strings[i]);
+ if (strings[i])
+ printk(" %s", strings[i]);
+ else
+ printk(" %d", i);
if (!(mask & (1 << i)))
continue;
printk("*");
@@ -556,8 +585,9 @@ void cx88_wakeup(struct cx88_core *core,
struct cx88_dmaqueue *q, u32 count)
{
struct cx88_buffer *buf;
+ int bc;
- for (;;) {
+ for (bc = 0;; bc++) {
if (list_empty(&q->active))
break;
buf = list_entry(q->active.next,
@@ -576,6 +606,8 @@ void cx88_wakeup(struct cx88_core *core,
} else {
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
}
+ if (bc != 1)
+ printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
}
void cx88_shutdown(struct cx88_core *core)
@@ -590,7 +622,7 @@ void cx88_shutdown(struct cx88_core *core)
cx_write(MO_VIP_DMACNTRL, 0x0);
cx_write(MO_GPHST_DMACNTRL, 0x0);
- /* stop interupts */
+ /* stop interrupts */
cx_write(MO_PCI_INTMSK, 0x0);
cx_write(MO_VID_INTMSK, 0x0);
cx_write(MO_AUD_INTMSK, 0x0);
@@ -622,7 +654,7 @@ int cx88_reset(struct cx88_core *core)
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
- cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 512, 0);
+ cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
/* misc init ... */
cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable
@@ -1142,6 +1174,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
EXPORT_SYMBOL(cx88_print_ioctl);
EXPORT_SYMBOL(cx88_pci_irqs);
EXPORT_SYMBOL(cx88_vid_irqs);
+EXPORT_SYMBOL(cx88_mpeg_irqs);
EXPORT_SYMBOL(cx88_print_irqbits);
EXPORT_SYMBOL(cx88_irq);
@@ -1150,6 +1183,7 @@ EXPORT_SYMBOL(cx88_reset);
EXPORT_SYMBOL(cx88_shutdown);
EXPORT_SYMBOL(cx88_risc_buffer);
+EXPORT_SYMBOL(cx88_risc_databuffer);
EXPORT_SYMBOL(cx88_risc_stopper);
EXPORT_SYMBOL(cx88_free_buffer);
diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c
index 398fbbd16..03969ebc1 100644
--- a/linux/drivers/media/video/cx88/cx88-dvb.c
+++ b/linux/drivers/media/video/cx88/cx88-dvb.c
@@ -88,7 +88,7 @@ static int dvb_thread(void *data)
unsigned long flags;
int err;
- dprintk(1,"cx88: dvb thread started\n");
+ dprintk(1,"dvb thread started\n");
file = get_empty_filp();
file->private_data = dev;
videobuf_read_start(file, &dev->dvbq);
@@ -113,11 +113,19 @@ static int dvb_thread(void *data)
spin_lock_irqsave(dev->dvbq.irqlock,flags);
dev->dvbq.ops->buf_queue(file,buf);
spin_unlock_irqrestore(dev->dvbq.irqlock,flags);
+
+ /* log errors if any */
+ if (dev->error_count || dev->stopper_count) {
+ printk("%s: error=%d stopper=%d\n",
+ dev->core->name, dev->error_count, dev->stopper_count);
+ dev->error_count = 0;
+ dev->stopper_count = 0;
+ }
}
videobuf_read_stop(file, &dev->dvbq);
put_filp(file);
- dprintk(1,"cx88: dvb thread stopped\n");
+ dprintk(1,"dvb thread stopped\n");
return 0;
}
@@ -127,20 +135,26 @@ static int dvb_start_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct cx8802_dev *dev = demux->priv;
- int rc = 0;
-
- dprintk(2, "dvb_cx8800_start_feed\n");
+ int rc;
if (!demux->dmx.frontend)
return -EINVAL;
- if (dev->dvb_thread)
- return -EINVAL;
+ down(&dev->lock);
+ dev->nfeeds++;
+ rc = dev->nfeeds;
+
+ if (NULL != dev->dvb_thread)
+ goto out;
dev->dvb_thread = kthread_run(dvb_thread, dev, "%s dvb", dev->core->name);
if (IS_ERR(dev->dvb_thread)) {
rc = PTR_ERR(dev->dvb_thread);
dev->dvb_thread = NULL;
}
+
+out:
+ up(&dev->lock);
+ dprintk(2, "dvb_cx8800_start_feed rc=%d\n",rc);
return rc;
}
@@ -148,24 +162,29 @@ static int dvb_stop_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct cx8802_dev *dev = demux->priv;
- int err;
+ int err = 0;
dprintk(2, "dvb_cx8800_stop_feed\n");
- if (NULL == dev->dvb_thread)
- return -EINVAL;
- err = kthread_stop(dev->dvb_thread);
- dev->dvb_thread = NULL;
+ down(&dev->lock);
+ dev->nfeeds--;
+ if (0 == dev->nfeeds && NULL != dev->dvb_thread) {
+ err = kthread_stop(dev->dvb_thread);
+ dev->dvb_thread = NULL;
+ }
+ up(&dev->lock);
return err;
}
static void dvb_unregister(struct cx8802_dev *dev)
{
#if 1 /* really needed? */
+ down(&dev->lock);
if (NULL != dev->dvb_thread) {
kthread_stop(dev->dvb_thread);
BUG();
}
+ up(&dev->lock);
#endif
dvb_net_release(&dev->dvbnet);
@@ -173,7 +192,8 @@ static void dvb_unregister(struct cx8802_dev *dev)
dev->demux.dmx.remove_frontend(&dev->demux.dmx, &dev->fe_hw);
dvb_dmxdev_release(&dev->dmxdev);
dvb_dmx_release(&dev->demux);
- dvb_unregister_adapter(dev->dvb_adapter);
+ dvb_unregister_adapter(dev->core->dvb_adapter);
+ dev->core->dvb_adapter = NULL;
return;
}
@@ -181,15 +201,7 @@ static int dvb_register(struct cx8802_dev *dev)
{
int result;
-#if 0 /* hmm, this is board specific I guess? move to cx88-cards.c? */
- /* Take DVB hardware out of reset */
- cx_set(MO_GP0_IO, cx88_boards[dev->board].ts.gpio0);
- cx_clear(MO_GP0_IO, cx88_boards[dev->board].ts.gpio0 & 0xff);
- msleep(1);
- cx_set(MO_GP0_IO, cx88_boards[dev->board].ts.gpio0);
-#endif
-
- result = dvb_register_adapter(&dev->dvb_adapter, dev->core->name,
+ result = dvb_register_adapter(&dev->core->dvb_adapter, dev->core->name,
THIS_MODULE);
if (result < 0) {
printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
@@ -215,7 +227,7 @@ static int dvb_register(struct cx8802_dev *dev)
dev->dmxdev.filternum = 256;
dev->dmxdev.demux = &dev->demux.dmx;
dev->dmxdev.capabilities = 0;
- result = dvb_dmxdev_init(&dev->dmxdev, dev->dvb_adapter);
+ result = dvb_dmxdev_init(&dev->dmxdev, dev->core->dvb_adapter);
if (result < 0) {
printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
dev->core->name, result);
@@ -233,19 +245,19 @@ static int dvb_register(struct cx8802_dev *dev)
dev->fe_mem.source = DMX_MEMORY_FE;
result = dev->demux.dmx.add_frontend(&dev->demux.dmx, &dev->fe_mem);
if (result < 0) {
- printk(KERN_WARNING "%s: add_frontent failed (DMX_MEMORY_FE, errno = %d)\n",
+ printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
dev->core->name, result);
goto fail5;
}
result = dev->demux.dmx.connect_frontend(&dev->demux.dmx, &dev->fe_hw);
if (result < 0) {
- printk(KERN_WARNING "%s: connect_frontent failed (errno = %d)\n",
+ printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n",
dev->core->name, result);
goto fail6;
}
- dvb_net_init(dev->dvb_adapter, &dev->dvbnet, &dev->demux.dmx);
+ dvb_net_init(dev->core->dvb_adapter, &dev->dvbnet, &dev->demux.dmx);
return 0;
fail6:
@@ -257,7 +269,7 @@ fail4:
fail3:
dvb_dmx_release(&dev->demux);
fail2:
- dvb_unregister_adapter(dev->dvb_adapter);
+ dvb_unregister_adapter(dev->core->dvb_adapter);
fail1:
return result;
}
@@ -293,15 +305,17 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev,
goto fail_free;
/* dvb stuff */
- printk("%s/2: cx23416 based dvb card\n", core->name);
+ printk("%s/2: cx2388x based dvb card\n", core->name);
videobuf_queue_init(&dev->dvbq, &dvb_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_TOP,
sizeof(struct cx88_buffer));
init_MUTEX(&dev->dvbq.lock);
- dvb_register(dev);
-
+
+ err = dvb_register(dev);
+ if (0 != err)
+ goto fail_free;
return 0;
fail_free:
@@ -317,7 +331,7 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev)
/* dvb */
dvb_unregister(dev);
-
+
/* common */
cx8802_fini_common(dev);
cx88_core_put(dev->core,dev->pci);
@@ -337,7 +351,7 @@ static struct pci_device_id cx8802_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
static struct pci_driver dvb_pci_driver = {
- .name = "cx8802",
+ .name = "cx88-dvb",
.id_table = cx8802_pci_tbl,
.probe = dvb_probe,
.remove = dvb_remove,
diff --git a/linux/drivers/media/video/cx88/cx88-i2c.c b/linux/drivers/media/video/cx88/cx88-i2c.c
index 02595d86c..ef04a431d 100644
--- a/linux/drivers/media/video/cx88/cx88-i2c.c
+++ b/linux/drivers/media/video/cx88/cx88-i2c.c
@@ -29,6 +29,19 @@
#include "cx88.h"
+static unsigned int i2c_debug = 0;
+MODULE_PARM(i2c_debug,"i");
+MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
+
+#define dprintk(level,fmt, arg...) if (i2c_debug >= level) \
+ printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
+
+/* temporary here until new dvb-kernel code is merged ... */
+#ifndef FE_REGISTER
+# define FE_REGISTER _IO ('v', 84)
+# define FE_UNREGISTER _IO ('v', 85)
+#endif
+
/* ----------------------------------------------------------------------- */
void cx8800_bit_setscl(void *data, int state)
@@ -89,17 +102,43 @@ static void cx8800_dec_use(struct i2c_adapter *adap)
static int attach_inform(struct i2c_client *client)
{
- struct cx88_core *core = i2c_get_adapdata(client->adapter);
+ struct cx88_core *core = i2c_get_adapdata(client->adapter);
if (core->tuner_type != UNSET)
cx88_call_i2c_clients(core,TUNER_SET_TYPE,&core->tuner_type);
if (core->tda9887_conf)
cx88_call_i2c_clients(core,TDA9887_SET_CONFIG,&core->tda9887_conf);
- if (1 /* fixme: debug */)
- printk("%s: i2c attach [client=%s]\n",
- core->name, i2c_clientname(client));
- return 0;
+#if 1
+ /* FIXME: should switch to cx88_call_i2c_clients */
+ if (core->dvb_adapter && client->driver->command) {
+ dprintk(1, "i2c attach [client=%s] dvb_adapter %p\n",
+ i2c_clientname(client), core->dvb_adapter);
+ return client->driver->command(client, FE_REGISTER, core->dvb_adapter);
+ }
+#endif
+
+ dprintk(1, "i2c attach [client=%s]\n", i2c_clientname(client));
+ return 0;
+}
+
+static int detach_inform(struct i2c_client *client)
+{
+ struct cx88_core *core = i2c_get_adapdata(client->adapter);
+
+#if 1
+ /* FIXME: should switch to cx88_call_i2c_clients */
+ /* FIXME: drop FE_UNREGISTER altogether in favor of using
+ * i2c_driver->detach_client() ??? */
+ if (core->dvb_adapter && client->driver->command) {
+ dprintk(1, "i2c detach [client=%s] dvb_adapter %p\n",
+ i2c_clientname(client), core->dvb_adapter);
+ return client->driver->command(client, FE_UNREGISTER, core->dvb_adapter);
+ }
+#endif
+
+ dprintk(1, "i2c detach [client=%s]\n", i2c_clientname(client));
+ return 0;
}
void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
@@ -134,6 +173,7 @@ static struct i2c_adapter cx8800_i2c_adap_template = {
I2C_DEVNAME("cx2388x"),
.id = I2C_HW_B_BT848,
.client_register = attach_inform,
+ .client_unregister = detach_inform,
};
static struct i2c_client cx8800_i2c_client_template = {
@@ -164,8 +204,10 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
cx8800_bit_setsda(core,1);
core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap);
- printk("%s: i2c register %s\n", core->name,
- (0 == core->i2c_rc) ? "ok" : "FAILED");
+ if (0 != core->i2c_rc)
+ printk("%s: i2c register FAILED\n", core->name);
+ else
+ dprintk(1, "i2c register ok\n");
return core->i2c_rc;
}
diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c
index 735356325..a0445baf5 100644
--- a/linux/drivers/media/video/cx88/cx88-mpeg.c
+++ b/linux/drivers/media/video/cx88/cx88-mpeg.c
@@ -1,10 +1,11 @@
/*
- * $Id: cx88-mpeg.c,v 1.5 2004/08/25 14:47:53 kraxel Exp $
+ * $Id: cx88-mpeg.c,v 1.6 2004/08/31 11:58:53 kraxel Exp $
*
* Support for the mpeg transport stream transfers
* PCI function #2 of the cx2388x.
*
* (c) 2004 Jelle Foks <jelle@foks.8m.com>
+ * (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au>
* (c) 2004 Gerd Knorr <kraxel@bytesex.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -34,6 +35,7 @@
MODULE_DESCRIPTION("mpeg driver for cx2388x based TV cards");
MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>");
+MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
@@ -58,6 +60,9 @@ int cx8802_start_dma(struct cx8802_dev *dev,
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
dev->ts_packet_size, buf->risc.dma);
+ /* write TS length to chip */
+ cx_write(MO_TS_LNGTH, buf->vb.width);
+
#if 1
/* FIXME: this needs a review.
* also: move to cx88-blackbird + cx88-dvb source files? */
@@ -65,19 +70,13 @@ int cx8802_start_dma(struct cx8802_dev *dev,
if (cx88_boards[core->board].dvb) {
/* Setup TS portion of chip */
cx_write(TS_GEN_CNTRL, 0x0c);
-
- /* write TS length to chip */
- cx_write(MO_TS_LNGTH, buf->bpl);
}
if (cx88_boards[core->board].blackbird) {
cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
-
// cx_write(TS_F2_CMD_STAT_MM, 0x2900106); /* F2_CMD_STAT_MM defaults + master + memory space */
cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
- // cx_write(MO_TS_LNGTH, MD_TS_LNGHT_VAL);
-
udelay(100);
cx_write(TS_HW_SOP_CNTRL, 0x408); /* mpeg start byte */
@@ -95,14 +94,30 @@ int cx8802_start_dma(struct cx8802_dev *dev,
/* enable irqs */
cx_set(MO_PCI_INTMSK, 0x00fc04);
- cx_set(MO_TS_INTMSK, 0x1f0011);
+ cx_write(MO_TS_INTMSK, 0x1f0011);
/* start dma */
- cx_set(MO_DEV_CNTRL2, (1<<5));
- cx_set(MO_TS_DMACNTRL, 0x11);
+ cx_write(MO_DEV_CNTRL2, (1<<5)); /* FIXME: s/write/set/ ??? */
+ cx_write(MO_TS_DMACNTRL, 0x11);
return 0;
}
+void cx8802_shutdown(struct cx8802_dev *dev)
+{
+ struct cx88_core *core = dev->core;
+
+ /* disable and clear irqs */
+ cx_write(MO_TS_INTMSK, 0x0);
+ cx_write(MO_TS_INTSTAT, 0x1f1111);
+
+ /* stop dma */
+ cx_clear(MO_TS_DMACNTRL, 0x11);
+ cx_write(MO_DEV_CNTRL2, 0); /* FIXME: affects other pci functions ??? */
+
+ /* Reset the controller */
+ cx_write(TS_GEN_CNTRL, 0xcd);
+}
+
int cx8802_restart_queue(struct cx8802_dev *dev,
struct cx88_dmaqueue *q)
{
@@ -143,11 +158,9 @@ int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf)
if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL)))
goto fail;
- cx88_risc_buffer(dev->pci, &buf->risc,
- buf->vb.dma.sglist,
- 0, UNSET,
- buf->vb.width, 0,
- buf->vb.height);
+ cx88_risc_databuffer(dev->pci, &buf->risc,
+ buf->vb.dma.sglist,
+ buf->vb.width, buf->vb.height);
}
buf->vb.state = STATE_PREPARED;
return 0;
@@ -186,12 +199,6 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
}
}
-void cx8802_buf_release(struct cx8802_dev *dev, struct cx88_buffer *buf)
-{
- dprintk(1, "%s: %p\n", __FUNCTION__, buf);
-
-}
-
/* ----------------------------------------------------------- */
static void cx8802_timeout(unsigned long data)
@@ -238,7 +245,7 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
cx_write(MO_TS_INTSTAT, status);
if (debug || (status & mask & ~0xff))
cx88_print_irqbits(core->name, "irq mpeg ",
- cx88_vid_irqs, status, mask);
+ cx88_mpeg_irqs, status, mask);
/* risc op code error */
if (status & (1 << 16)) {
@@ -256,11 +263,21 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
}
/* risc2 y */
- if (status & 0x10) { /* I don't know what this does/when it's needed */
+ if (status & 0x10) {
spin_lock(&dev->slock);
+ dev->stopper_count++;
cx8802_restart_queue(dev,&dev->mpegq);
spin_unlock(&dev->slock);
}
+
+ /* other general errors */
+ if (status & 0x1f0100) {
+ spin_lock(&dev->slock);
+ dev->error_count++;
+ cx8802_shutdown(dev);
+ cx8802_restart_queue(dev,&dev->mpegq);
+ spin_unlock(&dev->slock);
+ }
}
static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
@@ -355,9 +372,7 @@ int cx8802_init_common(struct cx8802_dev *dev)
void cx8802_fini_common(struct cx8802_dev *dev)
{
-#if 0
cx8802_shutdown(dev);
-#endif
pci_disable_device(dev->pci);
/* unregister stuff */
@@ -366,8 +381,6 @@ void cx8802_fini_common(struct cx8802_dev *dev)
/* free memory */
btcx_riscmem_free(dev->pci,&dev->mpegq.stopper);
- cx88_core_put(dev->core,dev->pci);
- kfree(dev);
}
/* ----------------------------------------------------------- */
diff --git a/linux/drivers/media/video/cx88/cx88-vbi.c b/linux/drivers/media/video/cx88/cx88-vbi.c
index 09829a10f..7651ca890 100644
--- a/linux/drivers/media/video/cx88/cx88-vbi.c
+++ b/linux/drivers/media/video/cx88/cx88-vbi.c
@@ -11,7 +11,7 @@ MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
static unsigned int vbi_debug = 0;
MODULE_PARM(vbi_debug,"i");
-MODULE_PARM_DESC(vbi_debug,"enable debug messages [video]");
+MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
#define dprintk(level,fmt, arg...) if (vbi_debug >= level) \
printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg)
diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c
index 8d2de17a1..f425d73f3 100644
--- a/linux/drivers/media/video/cx88/cx88-video.c
+++ b/linux/drivers/media/video/cx88/cx88-video.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-video.c,v 1.33 2004/08/26 10:59:39 kraxel Exp $
+ * $Id: cx88-video.c,v 1.34 2004/08/31 11:58:53 kraxel Exp $
*
* device driver for Conexant 2388x based TV cards
* video4linux video interface
@@ -2079,7 +2079,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
up(&dev->lock);
/* start tvaudio thread */
- core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
+ if (core->tuner_type != TUNER_ABSENT)
+ core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
return 0;
fail_unreg:
diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h
index 4abb91649..9db2c04df 100644
--- a/linux/drivers/media/video/cx88/cx88.h
+++ b/linux/drivers/media/video/cx88/cx88.h
@@ -1,5 +1,5 @@
/*
- * $Id: cx88.h,v 1.26 2004/08/26 10:59:39 kraxel Exp $
+ * $Id: cx88.h,v 1.27 2004/08/31 11:58:53 kraxel Exp $
*
* v4l2 device driver for cx2388x based TV cards
*
@@ -266,6 +266,9 @@ struct cx88_core {
u32 tvaudio;
u32 input;
u32 astat;
+
+ /* used by cx88-dvb -- i2c code needs access to this for FE register */
+ struct dvb_adapter *dvb_adapter;
};
struct cx8800_dev;
@@ -365,6 +368,10 @@ struct cx8802_dev {
u32 ts_packet_size;
u32 ts_packet_count;
+ /* error stats */
+ u32 stopper_count;
+ u32 error_count;
+
/* for blackbird only */
struct list_head devlist;
struct video_device *mpeg_dev;
@@ -373,12 +380,12 @@ struct cx8802_dev {
/* for dvb only */
struct videobuf_queue dvbq;
struct task_struct *dvb_thread;
- struct dvb_adapter *dvb_adapter;
struct dvb_demux demux;
struct dmxdev dmxdev;
struct dmx_frontend fe_hw;
struct dmx_frontend fe_mem;
struct dvb_net dvbnet;
+ int nfeeds;
};
/* ----------------------------------------------------------- */
@@ -409,6 +416,7 @@ struct cx8802_dev {
extern char *cx88_pci_irqs[32];
extern char *cx88_vid_irqs[32];
+extern char *cx88_mpeg_irqs[32];
extern void cx88_print_irqbits(char *name, char *tag, char **strings,
u32 bits, u32 mask);
extern void cx88_print_ioctl(char *name, unsigned int cmd);
@@ -425,6 +433,10 @@ cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
unsigned int top_offset, unsigned int bottom_offset,
unsigned int bpl, unsigned int padding, unsigned int lines);
extern int
+cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+ struct scatterlist *sglist, unsigned int bpl,
+ unsigned int lines);
+extern int
cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
u32 reg, u32 mask, u32 value);
extern void