Commit 7b1e171b authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[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
parent c9a94895
......@@ -44,11 +44,66 @@ 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);
......
......@@ -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) */
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
}
}
......
......@@ -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,
};
......@@ -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 */
......
......@@ -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 */
......
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