summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2003-12-29 23:41:05 -0800
committerLinus Torvalds <torvalds@home.osdl.org>2003-12-29 23:41:05 -0800
commit7b1e171bfe382eba0c1422428d84c2b76b9fb952 (patch)
tree4e2203fff7b3a14faf6c4a0d9afbf91dbfc87f2f
parentc9a94895dcfe2848fb77e4088e4c10f44889027a (diff)
[PATCH] dvb: Update saa7146 capture core
From: Michael Hunold <hunold@linuxtv.org> fix a bunch of race conditions and locking bugs in video and vbi capture code on device closure use vmalloc_32() instead of vmalloc() in saa7146_vmalloc_build_pgtable(). this makes sure that the pagetable is in lowmem kernel memory i2c timeout fix by Gerd Knorr SAA7146_I2C_SHORT_DELAY flag to speed up I2C access by Oliver Endriss move saa7146_set_gpio() from saa7146_vv to saa7146_core, it's needed by DVB budget drivers add "new" saa7146_wait_for_debi_done() function, remove other versions from av7110 and budget.ci make budget-ci use this gpio function and the new wait_...() function, make saa7146_pgtable_build_single() deliver a return code, make sanity checks of the arguments sanitize enabling of video input pins and i2c pins, use some default values, so the hardware is always in a sane state remove SAA7146_EXT_SWAP_ODD_EVEN flag + handling, fix the hardware initialization instead change minimal picture size to 48x32 just like other drivers set up arbitrition control for video dma3 correctly remove unnecessary code for capture to framebuffer memory, it's handled in the generic code
-rw-r--r--drivers/media/common/saa7146_core.c78
-rw-r--r--drivers/media/common/saa7146_fops.c22
-rw-r--r--drivers/media/common/saa7146_hlp.c25
-rw-r--r--drivers/media/common/saa7146_i2c.c15
-rw-r--r--drivers/media/common/saa7146_vbi.c68
-rw-r--r--drivers/media/common/saa7146_video.c138
-rw-r--r--include/media/saa7146.h7
-rw-r--r--include/media/saa7146_vv.h8
8 files changed, 182 insertions, 179 deletions
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index 3d5d7a758807..f345820a2cb8 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -45,10 +45,65 @@ static void dump_registers(struct saa7146_dev* dev)
#endif
/****************************************************************************
+ * gpio and debi helper functions
+ ****************************************************************************/
+
+/* write "data" to the gpio-pin "pin" */
+void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data)
+{
+ u32 value = 0;
+
+ /* sanity check */
+ if(pin > 3)
+ return;
+
+ /* read old register contents */
+ value = saa7146_read(dev, GPIO_CTRL );
+
+ value &= ~(0xff << (8*pin));
+ value |= (data << (8*pin));
+
+ saa7146_write(dev, GPIO_CTRL, value);
+}
+
+/* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */
+int saa7146_wait_for_debi_done(struct saa7146_dev *dev)
+{
+ int start;
+
+ /* wait for registers to be programmed */
+ start = jiffies;
+ while (1) {
+ if (saa7146_read(dev, MC2) & 2)
+ break;
+ if (jiffies-start > HZ/20) {
+ DEB_S(("timed out while waiting for registers getting programmed\n"));
+ return -ETIMEDOUT;
+ }
+ }
+
+ /* wait for transfer to complete */
+ start = jiffies;
+ while (1) {
+ if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
+ break;
+ saa7146_read(dev, MC2);
+ if (jiffies-start > HZ/4) {
+ DEB_S(("timed out while waiting for transfer completion\n"));
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************
* general helper functions
****************************************************************************/
-/* this is videobuf_vmalloc_to_sg() from video-buf.c */
+/* this is videobuf_vmalloc_to_sg() from video-buf.c
+ make sure virt has been allocated with vmalloc_32(), otherwise the BUG()
+ may be triggered on highmem machines */
static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
{
struct scatterlist *sglist;
@@ -84,7 +139,7 @@ char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa
{
struct scatterlist *slist = NULL;
int pages = (length+PAGE_SIZE-1)/PAGE_SIZE;
- char *mem = vmalloc(length);
+ char *mem = vmalloc_32(length);
int slen = 0;
if (NULL == mem) {
@@ -103,7 +158,9 @@ char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa
}
slen = pci_map_sg(pci,slist,pages,PCI_DMA_FROMDEVICE);
- saa7146_pgtable_build_single(pci, pt, slist, slen);
+ if (0 != saa7146_pgtable_build_single(pci, pt, slist, slen)) {
+ return NULL;
+ }
/* fixme: here's a memory leak: slist never gets freed by any other
function ...*/
@@ -139,7 +196,7 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
return 0;
}
-void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
+int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
struct scatterlist *list, int sglen )
{
u32 *ptr, fill;
@@ -148,6 +205,11 @@ void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *p
BUG_ON( 0 == sglen);
+ if (list->offset > PAGE_SIZE) {
+ DEB_D(("offset > PAGE_SIZE. this should not happen."));
+ return -EINVAL;
+ }
+
/* if we have a user buffer, the first page may not be
aligned to a page boundary. */
pt->offset = list->offset;
@@ -177,6 +239,7 @@ void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *p
printk("ptr1 %d: 0x%08x\n",i,ptr[i]);
}
*/
+ return 0;
}
/********************************************************************************/
@@ -322,7 +385,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
saa7146_write(dev, MC1, MASK_31);
*/
- /* disable alle irqs */
+ /* disable all irqs */
saa7146_write(dev, IER, 0);
/* shut down all dma transfers */
@@ -381,8 +444,8 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
dev->module = THIS_MODULE;
init_waitqueue_head(&dev->i2c_wq);
- /* set some default values */
- saa7146_write(dev, BCS_CTRL, 0x80400040);
+ /* set some sane pci arbitrition values */
+ saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
if( 0 != ext->probe) {
if( 0 != ext->probe(dev) ) {
@@ -508,6 +571,7 @@ EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc);
EXPORT_SYMBOL_GPL(saa7146_pgtable_free);
EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single);
EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable);
+EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done);
EXPORT_SYMBOL_GPL(saa7146_setgpio);
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index 9c4fcc49da7a..29bd80f6b83e 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -86,7 +86,7 @@ void saa7146_buffer_next(struct saa7146_dev *dev,
return;
}
- DEB_EE(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
+ DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
#if DEBUG_SPINLOCKS
BUG_ON(!spin_is_locked(&dev->slock));
@@ -98,10 +98,10 @@ void saa7146_buffer_next(struct saa7146_dev *dev,
if (!list_empty(&q->queue))
next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
q->curr = buf;
- DEB_D(("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev,q->queue.next));
+ DEB_INT(("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev,q->queue.next));
buf->activate(dev,buf,next);
} else {
- DEB_D(("no next buffer. stopping.\n"));
+ DEB_INT(("no next buffer. stopping.\n"));
if( 0 != vbi ) {
/* turn off video-dma3 */
saa7146_write(dev,MC1, MASK_20);
@@ -229,10 +229,10 @@ static int fops_open(struct inode *inode, struct file *file)
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
DEB_S(("initializing vbi...\n"));
- saa7146_vbi_uops.open(dev,fh);
+ saa7146_vbi_uops.open(dev,file);
} else {
DEB_S(("initializing video...\n"));
- saa7146_video_uops.open(dev,fh);
+ saa7146_video_uops.open(dev,file);
}
result = 0;
@@ -255,9 +255,9 @@ static int fops_release(struct inode *inode, struct file *file)
return -ERESTARTSYS;
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
- saa7146_vbi_uops.release(dev,fh,file);
+ saa7146_vbi_uops.release(dev,file);
} else {
- saa7146_video_uops.release(dev,fh,file);
+ saa7146_video_uops.release(dev,file);
}
module_put(dev->ext->module);
@@ -372,7 +372,7 @@ void vv_callback(struct saa7146_dev *dev, unsigned long status)
{
u32 isr = status;
- DEB_EE(("dev:%p, isr:0x%08x\n",dev,(u32)status));
+ DEB_INT(("dev:%p, isr:0x%08x\n",dev,(u32)status));
if (0 != (isr & (MASK_27))) {
DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
@@ -410,6 +410,12 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
DEB_EE(("dev:%p\n",dev));
+ /* set default values for video parts of the saa7146 */
+ saa7146_write(dev, BCS_CTRL, 0x80400040);
+
+ /* enable video-port pins */
+ saa7146_write(dev, MC1, (MASK_10 | MASK_26));
+
/* save per-device extension data (one extension can
handle different devices that might need different
configuration data) */
diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c
index 0f41a4d8013f..cface126003c 100644
--- a/drivers/media/common/saa7146_hlp.c
+++ b/drivers/media/common/saa7146_hlp.c
@@ -660,24 +660,6 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sy
vv->current_hps_sync = sync;
}
-/* write "data" to the gpio-pin "pin" */
-void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data)
-{
- u32 value = 0;
-
- /* sanity check */
- if(pin > 3)
- return;
-
- /* read old register contents */
- value = saa7146_read(dev, GPIO_CTRL );
-
- value &= ~(0xff << (8*pin));
- value |= (data << (8*pin));
-
- saa7146_write(dev, GPIO_CTRL, value);
-}
-
/* reprogram hps, enable(1) / disable(0) video */
void saa7146_set_overlay(struct saa7146_dev *dev, struct saa7146_fh *fh, int v)
{
@@ -710,13 +692,15 @@ void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_vi
/* calculate starting address */
where = (which-1)*0x18;
+/*
if( 0 != (dev->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) {
saa7146_write(dev, where, vdma->base_even);
saa7146_write(dev, where+0x04, vdma->base_odd);
} else {
+*/
saa7146_write(dev, where, vdma->base_odd);
saa7146_write(dev, where+0x04, vdma->base_even);
- }
+// }
saa7146_write(dev, where+0x08, vdma->prot_addr);
saa7146_write(dev, where+0x0c, vdma->pitch);
saa7146_write(dev, where+0x10, vdma->base_page);
@@ -971,12 +955,13 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar)
unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
+/*
if( 0 != (dev->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) {
unsigned long tmp = e_wait;
e_wait = o_wait;
o_wait = tmp;
}
-
+*/
/* wait for o_fid_a/b / e_fid_a/b toggle only if rps register 0 is not set*/
WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | o_wait);
WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait);
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
index 4f33caa5f22c..ff94b635ec1c 100644
--- a/drivers/media/common/saa7146_i2c.c
+++ b/drivers/media/common/saa7146_i2c.c
@@ -301,7 +301,8 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i
goto out;
}
- if (count > 3) short_delay = 1;
+ if ( count > 3 || 0 != (SAA7146_I2C_SHORT_DELAY & dev->ext->flags) )
+ short_delay = 1;
do {
/* reset the i2c-device if necessary */
@@ -403,19 +404,29 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c
{
DEB_EE(("bitrate: 0x%08x\n",bitrate));
+ /* enable i2c-port pins */
+ saa7146_write(dev, MC1, (MASK_08 | MASK_24));
+
dev->i2c_bitrate = bitrate;
saa7146_i2c_reset(dev);
if( NULL != i2c_adapter ) {
memset(i2c_adapter,0,sizeof(struct i2c_adapter));
strcpy(i2c_adapter->name, dev->name);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ i2c_adapter->data = dev;
+#else
i2c_set_adapdata(i2c_adapter,dev);
- i2c_adapter->class = I2C_ADAP_CLASS_TV_ANALOG;
+#endif
i2c_adapter->algo = &saa7146_algo;
i2c_adapter->algo_data = NULL;
i2c_adapter->id = I2C_ALGO_SAA7146;
i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
i2c_adapter->retries = SAA7146_I2C_RETRIES;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#else
+ i2c_adapter->class = I2C_ADAP_CLASS_TV_ANALOG;
+#endif
}
return 0;
diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
index 9ed51e3a7989..862d9acf3026 100644
--- a/drivers/media/common/saa7146_vbi.c
+++ b/drivers/media/common/saa7146_vbi.c
@@ -41,7 +41,11 @@ static int vbi_workaround(struct saa7146_dev *dev)
/* wait for vbi_a or vbi_b*/
if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
DEB_D(("...using port b\n"));
+ WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_E_FID_B);
+ WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B);
+/*
WRITE_RPS1(CMD_PAUSE | MASK_09);
+*/
} else {
DEB_D(("...using port a\n"));
WRITE_RPS1(CMD_PAUSE | MASK_10);
@@ -137,10 +141,10 @@ void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, s
unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
/*
- vdma3.base_even = (u32)dev->ov_fb.base+2048*70;
- vdma3.base_odd = (u32)dev->ov_fb.base;
- vdma3.prot_addr = (u32)dev->ov_fb.base+2048*164;
- vdma3.pitch = 2048;
+ vdma3.base_even = 0xc8000000+2560*70;
+ vdma3.base_odd = 0xc8000000;
+ vdma3.prot_addr = 0xc8000000+2560*164;
+ vdma3.pitch = 2560;
vdma3.base_page = 0;
vdma3.num_line_byte = (64<<16)|((vbi_pixel_to_capture)<<0); // set above!
*/
@@ -244,7 +248,9 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,enum v4l
err = videobuf_iolock(dev->pci,&buf->vb,NULL);
if (err)
goto oops;
- saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen);
+ err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen);
+ if (0 != err)
+ return err;
}
buf->vb.state = STATE_PREPARED;
buf->activate = buffer_activate;
@@ -303,7 +309,7 @@ static struct videobuf_queue_ops vbi_qops = {
/* ------------------------------------------------------------------ */
-static void vbi_stop(struct saa7146_fh *fh)
+static void vbi_stop(struct saa7146_fh *fh, struct file *file)
{
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
@@ -321,23 +327,29 @@ static void vbi_stop(struct saa7146_fh *fh)
/* shut down dma 3 transfers */
saa7146_write(dev, MC1, MASK_20);
+ if (vv->vbi_q.curr) {
+ saa7146_buffer_finish(dev,&vv->vbi_q,STATE_DONE);
+ }
+
+ videobuf_queue_cancel(file,&fh->vbi_q);
+
vv->vbi_streaming = NULL;
del_timer(&vv->vbi_q.timeout);
del_timer(&fh->vbi_read_timeout);
- DEB_VBI(("out\n"));
spin_unlock_irqrestore(&dev->slock, flags);
}
static void vbi_read_timeout(unsigned long data)
{
- struct saa7146_fh *fh = (struct saa7146_fh *)data;
+ struct file *file = (struct file*)data;
+ struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
- vbi_stop(fh);
+ vbi_stop(fh, file);
}
static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
@@ -354,10 +366,21 @@ static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
init_waitqueue_head(&vv->vbi_wq);
}
-static void vbi_open(struct saa7146_dev *dev, struct saa7146_fh *fh)
+static void vbi_open(struct saa7146_dev *dev, struct file *file)
{
+ struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
+
+ u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
+ int ret = 0;
+
DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+ /* adjust arbitrition control for video dma 3 */
+ arbtr_ctrl &= ~0x1f0000;
+ arbtr_ctrl |= 0x1d0000;
+ saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
+ saa7146_write(dev, MC2, (MASK_04|MASK_20));
+
memset(&fh->vbi_fmt,0,sizeof(fh->vbi_fmt));
fh->vbi_fmt.sampling_rate = 27000000;
@@ -380,21 +403,32 @@ static void vbi_open(struct saa7146_dev *dev, struct saa7146_fh *fh)
init_timer(&fh->vbi_read_timeout);
fh->vbi_read_timeout.function = vbi_read_timeout;
- fh->vbi_read_timeout.data = (unsigned long)fh;
+ fh->vbi_read_timeout.data = (unsigned long)file;
- /* fixme: enable this again, if the dvb-c w/ analog module work properly */
-/*
- vbi_workaround(dev);
-*/
+ /* initialize the brs */
+ if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
+ saa7146_write(dev, BRS_CTRL, MASK_30|MASK_29 | (7 << 19));
+ } else {
+ saa7146_write(dev, BRS_CTRL, 0x00000001);
+
+ if (0 != (ret = vbi_workaround(dev))) {
+ DEB_VBI(("vbi workaround failed!\n"));
+ /* return ret;*/
+ }
+ }
+
+ /* upload brs register */
+ saa7146_write(dev, MC2, (MASK_08|MASK_24));
}
-static void vbi_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file)
+static void vbi_close(struct saa7146_dev *dev, struct file *file)
{
+ struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
struct saa7146_vv *vv = dev->vv_data;
DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
if( fh == vv->vbi_streaming ) {
- vbi_stop(fh);
+ vbi_stop(fh, file);
}
}
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 0a34ede32c1d..c1ed935e621d 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -116,7 +116,7 @@ static int try_win(struct saa7146_dev *dev, struct v4l2_window *win)
DEB_D(("no fb fmt set.\n"));
return -EINVAL;
}
- if (win->w.width < 64 || win->w.height < 64) {
+ if (win->w.width < 48 || win->w.height < 32) {
DEB_D(("min width/height. (%d,%d)\n",win->w.width,win->w.height));
return -EINVAL;
}
@@ -661,7 +661,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
*/
} else {
struct saa7146_pgtable *pt = &buf->pt[0];
- saa7146_pgtable_build_single(pci, pt, list, length);
+ return saa7146_pgtable_build_single(pci, pt, list, length);
}
return 0;
@@ -704,7 +704,7 @@ static int video_begin(struct saa7146_fh *fh)
return 0;
}
-static int video_end(struct saa7146_fh *fh)
+static int video_end(struct saa7146_fh *fh, struct file *file)
{
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
@@ -735,82 +735,9 @@ static int video_end(struct saa7146_fh *fh)
saa7146_write(dev, MC1, 0x00700000);
vv->streaming = NULL;
- spin_unlock_irqrestore(&dev->slock, flags);
-
- return 0;
-}
-
-/* capturing to framebuffer */
-
-int overlay_reqbufs(struct saa7146_dev *dev, struct v4l2_requestbuffers *req)
-{
-/* struct saa7146_fh *fh = file->private_data;
-
- if (req->count > VIDEO_MAX_FRAME)
- req->count = VIDEO_MAX_FRAME;
-
- *size = fh->video_fmt.sizeimage;
-
-*/
- return 0;
-}
-int overlay_querybuf(struct saa7146_dev *dev, struct v4l2_buffer *buf)
-{
- return 0;
-}
-int overlay_qbuf(struct saa7146_dev *dev, struct v4l2_buffer *b)
-{
-/* if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) {
- DEB_D(("index %d out of bounds.\n",b->index));
- goto -EINVAL;
- }
-
- buf = q->bufs[b->index];
- if (NULL == buf) {
- printk("videobuf_qbuf: NULL == buf\n");
- goto done;
- }
- if (0 == buf->baddr) {
- printk("videobuf_qbuf: 0 == buf->baddr\n");
- goto done;
- }
- if (buf->state == STATE_QUEUED ||
- buf->state == STATE_ACTIVE) {
- printk("videobuf_qbuf: already queued or activated.\n");
- goto done;
- }
- field = videobuf_next_field(q);
- retval = q->ops->buf_prepare(file,buf,field);
- if (0 != retval) {
- printk("videobuf_qbuf: buf_prepare() failed.\n");
- goto done;
- }
-
- list_add_tail(&buf->stream,&q->stream);
- if (q->streaming) {
- spin_lock_irqsave(q->irqlock,flags);
- q->ops->buf_queue(file,buf);
- spin_unlock_irqrestore(q->irqlock,flags);
- }
- retval = 0;
+ spin_unlock_irqrestore(&dev->slock, flags);
- done:
- up(&q->lock);
- return retval;
-*/
- return 0;
-}
-int overlay_dqbuf(struct saa7146_dev *dev, struct v4l2_buffer *buf)
-{
- return 0;
-}
-int overlay_streamon(struct saa7146_dev *dev)
-{
- return 0;
-}
-int overlay_streamoff(struct saa7146_dev *dev)
-{
return 0;
}
@@ -818,7 +745,7 @@ int overlay_streamoff(struct saa7146_dev *dev)
/*
* This function is _not_ called directly, but from
* video_generic_ioctl (and maybe others). userspace
- * copying is done already, arg is a kernel fhinter.
+ * copying is done already, arg is a kernel pointer.
*/
int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg)
@@ -1141,38 +1068,24 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
case VIDIOC_REQBUFS: {
struct v4l2_requestbuffers *req = arg;
DEB_D(("VIDIOC_REQBUFS, type:%d\n",req->type));
-/*
- if( req->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
- return overlay_reqbufs(dev,req);
- }
-*/
return videobuf_reqbufs(file,q,req);
}
case VIDIOC_QUERYBUF: {
struct v4l2_buffer *buf = arg;
DEB_D(("VIDIOC_QUERYBUF, type:%d, offset:%d\n",buf->type,buf->m.offset));
-/* if( buf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
- return overlay_querybuf(dev,buf);
- }
- */ return videobuf_querybuf(q,buf);
+ return videobuf_querybuf(q,buf);
}
case VIDIOC_QBUF: {
struct v4l2_buffer *buf = arg;
int ret = 0;
-/* if( buf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
- return overlay_qbuf(dev,buf);
- }
- */ ret = videobuf_qbuf(file,q,buf);
+ ret = videobuf_qbuf(file,q,buf);
DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,buf->index));
return ret;
}
case VIDIOC_DQBUF: {
struct v4l2_buffer *buf = arg;
int ret = 0;
-/* if( buf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
- return overlay_dqbuf(dev,buf);
- }
- */ ret = videobuf_dqbuf(file,q,buf);
+ ret = videobuf_dqbuf(file,q,buf);
DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,buf->index));
return ret;
}
@@ -1180,29 +1093,18 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
int *type = arg;
DEB_D(("VIDIOC_STREAMON, type:%d\n",*type));
- if( 0 != ops->capture_begin ) {
- if( 0 != (err = ops->capture_begin(fh))) {
+ if( 0 != (err = video_begin(fh))) {
return err;
}
- }
-/* if( *type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
- err = overlay_streamon(dev);
- } else { */
err = videobuf_streamon(file,q);
-/* } */
return err;
}
case VIDIOC_STREAMOFF: {
int *type = arg;
DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));
- if( 0 != ops->capture_end ) {
- ops->capture_end(fh);
- }
-/* if( *type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
- return overlay_streamoff(dev);
- }
- */ err = videobuf_streamoff(file,q);
+ err = videobuf_streamoff(file,q);
+ video_end(fh, file);
return err;
}
case VIDIOCGMBUF:
@@ -1267,8 +1169,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, enum v4
DEB_CAP(("vbuf:%p\n",vb));
/* sanity checks */
- if (fh->video_fmt.width < 64 ||
- fh->video_fmt.height < 64 ||
+ if (fh->video_fmt.width < 48 ||
+ fh->video_fmt.height < 32 ||
fh->video_fmt.width > vv->standard->h_max_out ||
fh->video_fmt.height > vv->standard->v_max_out) {
DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height));
@@ -1407,8 +1309,9 @@ static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
}
-static void video_open(struct saa7146_dev *dev, struct saa7146_fh *fh)
+static void video_open(struct saa7146_dev *dev, struct file *file)
{
+ struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
struct saa7146_format *sfmt;
fh->video_fmt.width = 384;
@@ -1429,8 +1332,9 @@ static void video_open(struct saa7146_dev *dev, struct saa7146_fh *fh)
}
-static void video_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file)
+static void video_close(struct saa7146_dev *dev, struct file *file)
{
+ struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
struct saa7146_vv *vv = dev->vv_data;
unsigned long flags;
@@ -1443,10 +1347,8 @@ static void video_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct f
}
if( fh == vv->streaming ) {
- video_end(fh);
+ video_end(fh, file);
}
-
- videobuf_queue_cancel(file,&fh->video_q);
}
@@ -1489,7 +1391,7 @@ static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *p
return -EAGAIN;
}
ret = videobuf_read_one(file,&fh->video_q , data, count, ppos);
- video_end(fh);
+ video_end(fh, file);
/* restart overlay if it was active before */
if( 0 != restart_overlay ) {
@@ -1505,6 +1407,4 @@ struct saa7146_use_ops saa7146_video_uops = {
.release = video_close,
.irq_done = video_irq_done,
.read = video_read,
- .capture_begin = video_begin,
- .capture_end = video_end,
};
diff --git a/include/media/saa7146.h b/include/media/saa7146.h
index d0d990469705..5e6b16299b05 100644
--- a/include/media/saa7146.h
+++ b/include/media/saa7146.h
@@ -87,6 +87,7 @@ struct saa7146_extension
{
char name[32]; /* name of the device */
#define SAA7146_USE_I2C_IRQ 0x1
+#define SAA7146_I2C_SHORT_DELAY 0x2
int flags;
/* pairs of subvendor and subdevice ids for
@@ -162,9 +163,10 @@ int saa7146_unregister_extension(struct saa7146_extension*);
struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc);
int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt);
void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt);
-void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length );
+int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length );
char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt);
void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data);
+int saa7146_wait_for_debi_done(struct saa7146_dev *dev);
/* some memory sizes */
#define SAA7146_I2C_MEM ( 1*PAGE_SIZE)
@@ -187,6 +189,9 @@ void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data);
#define SAA7146_GPIO_OUTLO 0x40
#define SAA7146_GPIO_OUTHI 0x50
+/* debi defines */
+#define DEBINOSWAP 0x000e0000
+
/* define for the register programming sequencer (rps) */
#define CMD_NOP 0x00000000 /* No operation */
#define CMD_CLR_EVENT 0x00000000 /* Clear event */
diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h
index f8362431c962..83d8b9d66830 100644
--- a/include/media/saa7146_vv.h
+++ b/include/media/saa7146_vv.h
@@ -149,7 +149,7 @@ struct saa7146_extension_ioctls
};
/* flags */
-#define SAA7146_EXT_SWAP_ODD_EVEN 0x1 /* needs odd/even fields swapped */
+// #define SAA7146_EXT_SWAP_ODD_EVEN 0x1 /* needs odd/even fields swapped */
#define SAA7146_USE_PORT_B_FOR_VBI 0x2 /* use input port b for vbi hardware bug workaround */
struct saa7146_ext_vv
@@ -171,12 +171,10 @@ struct saa7146_ext_vv
struct saa7146_use_ops {
void (*init)(struct saa7146_dev *, struct saa7146_vv *);
- void(*open)(struct saa7146_dev *, struct saa7146_fh *);
- void (*release)(struct saa7146_dev *, struct saa7146_fh *,struct file *);
+ void(*open)(struct saa7146_dev *, struct file *);
+ void (*release)(struct saa7146_dev *, struct file *);
void (*irq_done)(struct saa7146_dev *, unsigned long status);
ssize_t (*read)(struct file *, char *, size_t, loff_t *);
- int (*capture_begin)(struct saa7146_fh *);
- int (*capture_end)(struct saa7146_fh *);
};
/* from saa7146_fops.c */