Commit 6f2f7e21 authored by Gerd Knorr's avatar Gerd Knorr Committed by Linus Torvalds

[PATCH] saa7134 driver update

This updates the saa7134 driver.  It adds support for a few more cards
and includes adaptions to the video-buf.c changes sent earlier.
parent f26843fa
...@@ -288,6 +288,81 @@ struct saa7134_board saa7134_boards[] = { ...@@ -288,6 +288,81 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE2, .amux = LINE2,
}, },
}, },
[SAA7134_BOARD_KWORLD] = {
.name = "Kworld/KuroutoShikou SAA7130-TVPCI",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_NTSC_M,
.inputs = {{
.name = name_svideo,
.vmux = 8,
.amux = LINE1,
},{
.name = name_comp1,
.vmux = 3,
.amux = LINE1,
},{
.name = name_tv,
.vmux = 1,
.amux = TV,
.tv = 1,
}},
},
[SAA7134_BOARD_CINERGY600] = {
.name = "Terratec Cinergy 600 TV",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_PAL,
.inputs = {{
.name = name_tv,
.vmux = 1,
.amux = TV,
.tv = 1,
},{
.name = name_comp1,
.vmux = 4,
.amux = LINE1,
},{
.name = name_svideo,
.vmux = 8,
.amux = LINE1,
},{
.name = name_comp2, // CVideo over SVideo Connector
.vmux = 0,
.amux = LINE1,
}},
.radio = {
.name = name_radio,
.amux = LINE2,
},
},
[SAA7134_BOARD_MD7134] = {
.name = "Medion 7134",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
.need_tda9887 = 1,
.inputs = {{
.name = name_tv,
.vmux = 1,
.amux = LINE2,
.tv = 1,
},{
.name = name_comp1,
.vmux = 0,
.amux = LINE2,
},{
.name = name_comp2,
.vmux = 3,
.amux = LINE2,
},{
.name = name_svideo,
.vmux = 8,
.amux = LINE2,
}},
.radio = {
.name = name_radio,
.amux = LINE2,
},
},
}; };
const int saa7134_bcount = (sizeof(saa7134_boards)/sizeof(struct saa7134_board)); const int saa7134_bcount = (sizeof(saa7134_boards)/sizeof(struct saa7134_board));
...@@ -320,7 +395,25 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = { ...@@ -320,7 +395,25 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = {
.subdevice = 0x1142, .subdevice = 0x1142,
.driver_data = SAA7134_BOARD_CINERGY400, .driver_data = SAA7134_BOARD_CINERGY400,
},{ },{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = 0x153B,
.subdevice = 0x1143,
.driver_data = SAA7134_BOARD_CINERGY600,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = 0x5168,
.subdevice = 0x0138,
.driver_data = SAA7134_BOARD_FLYVIDEO3000,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = 0x16be,
.subdevice = 0x0003,
.driver_data = SAA7134_BOARD_MD7134,
},{
/* --- boards without eeprom + subsystem ID --- */ /* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS, .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134, .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
......
...@@ -318,6 +318,7 @@ static u32 functionality(struct i2c_adapter *adap) ...@@ -318,6 +318,7 @@ static u32 functionality(struct i2c_adapter *adap)
return I2C_FUNC_SMBUS_EMUL; return I2C_FUNC_SMBUS_EMUL;
} }
static int attach_inform(struct i2c_client *client) static int attach_inform(struct i2c_client *client)
{ {
struct saa7134_dev *dev = client->adapter->algo_data; struct saa7134_dev *dev = client->adapter->algo_data;
......
...@@ -102,11 +102,13 @@ static int dsp_rec_start(struct saa7134_dev *dev) ...@@ -102,11 +102,13 @@ static int dsp_rec_start(struct saa7134_dev *dev)
/* prepare buffer */ /* prepare buffer */
if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma))) if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma)))
return err; return err;
if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt)))
goto fail1;
if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt, if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt,
dev->oss.dma.sglist, dev->oss.dma.sglist,
dev->oss.dma.sglen, dev->oss.dma.sglen,
0))) 0)))
goto fail1; goto fail2;
/* sample format */ /* sample format */
switch (dev->oss.afmt) { switch (dev->oss.afmt) {
......
...@@ -52,21 +52,24 @@ static int buffer_activate(struct saa7134_dev *dev, ...@@ -52,21 +52,24 @@ static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *buf, struct saa7134_buf *buf,
struct saa7134_buf *next) struct saa7134_buf *next)
{ {
unsigned long control,status; u32 control;
dprintk("buffer_activate [%p]\n",buf); dprintk("buffer_activate [%p]\n",buf);
buf->vb.state = STATE_ACTIVE; buf->vb.state = STATE_ACTIVE;
/* dma: setup channel 5 (= TS) */ /* dma: setup channel 5 (= TS) */
control = SAA7134_RS_CONTROL_BURST_16 | control = SAA7134_RS_CONTROL_BURST_16 |
SAA7134_RS_CONTROL_ME | SAA7134_RS_CONTROL_ME |
(buf->pt->dma >> 12); (buf->pt->dma >> 12);
status = saa_readl(SAA7134_IRQ_STATUS); if (NULL == next)
if (0 == (status & 0x100000)) { next = buf;
if (V4L2_FIELD_TOP == buf->vb.field) {
dprintk("[top] buf=%p next=%p",buf,next);
saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(buf)); saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(buf));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next)); saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next));
} else { } else {
dprintk("[bottom] buf=%p next=%p",buf,next);
saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next)); saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf)); saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf));
} }
...@@ -80,7 +83,8 @@ static int buffer_activate(struct saa7134_dev *dev, ...@@ -80,7 +83,8 @@ static int buffer_activate(struct saa7134_dev *dev,
return 0; return 0;
} }
static int buffer_prepare(struct file *file, struct videobuf_buffer *vb) static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
enum v4l2_field field)
{ {
struct saa7134_dev *dev = file->private_data; struct saa7134_dev *dev = file->private_data;
struct saa7134_buf *buf = (struct saa7134_buf *)vb; struct saa7134_buf *buf = (struct saa7134_buf *)vb;
...@@ -116,7 +120,7 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb) ...@@ -116,7 +120,7 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb)
buf->vb.state = STATE_PREPARED; buf->vb.state = STATE_PREPARED;
buf->top_seen = 0; buf->top_seen = 0;
buf->activate = buffer_activate; buf->activate = buffer_activate;
buf->vb.field = V4L2_FIELD_SEQ_TB; buf->vb.field = field;
return 0; return 0;
oops: oops:
...@@ -408,11 +412,13 @@ int saa7134_ts_init(struct saa7134_dev *dev) ...@@ -408,11 +412,13 @@ int saa7134_ts_init(struct saa7134_dev *dev)
tsbufs = VIDEO_MAX_FRAME; tsbufs = VIDEO_MAX_FRAME;
INIT_LIST_HEAD(&dev->ts_q.queue); INIT_LIST_HEAD(&dev->ts_q.queue);
init_timer(&dev->ts_q.timeout);
dev->ts_q.timeout.function = saa7134_buffer_timeout; dev->ts_q.timeout.function = saa7134_buffer_timeout;
dev->ts_q.timeout.data = (unsigned long)(&dev->ts_q); dev->ts_q.timeout.data = (unsigned long)(&dev->ts_q);
dev->ts_q.dev = dev; dev->ts_q.dev = dev;
videobuf_queue_init(&dev->ts.ts, &ts_qops, dev->pci, &dev->slock, videobuf_queue_init(&dev->ts.ts, &ts_qops, dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_ALTERNATE,
sizeof(struct saa7134_buf)); sizeof(struct saa7134_buf));
saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts); saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts);
...@@ -437,11 +443,23 @@ int saa7134_ts_fini(struct saa7134_dev *dev) ...@@ -437,11 +443,23 @@ int saa7134_ts_fini(struct saa7134_dev *dev)
void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status) void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status)
{ {
enum v4l2_field field;
spin_lock(&dev->slock); spin_lock(&dev->slock);
if (dev->ts_q.curr) { if (dev->ts_q.curr) {
field = dev->video_q.curr->vb.field;
if (field == V4L2_FIELD_TOP) {
if ((status & 0x100000) != 0x100000)
goto done;
} else {
if ((status & 0x100000) != 0x000000)
goto done;
}
saa7134_buffer_finish(dev,&dev->ts_q,STATE_DONE); saa7134_buffer_finish(dev,&dev->ts_q,STATE_DONE);
} }
saa7134_buffer_next(dev,&dev->ts_q); saa7134_buffer_next(dev,&dev->ts_q);
done:
spin_unlock(&dev->slock); spin_unlock(&dev->slock);
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <asm/div64.h> #include <asm/div64.h>
...@@ -119,6 +120,10 @@ static void tvaudio_init(struct saa7134_dev *dev) ...@@ -119,6 +120,10 @@ static void tvaudio_init(struct saa7134_dev *dev)
/* init all audio registers */ /* init all audio registers */
saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x00); saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x00);
if (need_resched())
schedule();
else
udelay(10);
saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff); saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff);
saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff); saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff);
...@@ -357,6 +362,7 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, int carrier) ...@@ -357,6 +362,7 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, int carrier)
return value; return value;
} }
#if 0
static void sifdebug_dump_regs(struct saa7134_dev *dev) static void sifdebug_dump_regs(struct saa7134_dev *dev)
{ {
print_regb(AUDIO_STATUS); print_regb(AUDIO_STATUS);
...@@ -372,6 +378,7 @@ static void sifdebug_dump_regs(struct saa7134_dev *dev) ...@@ -372,6 +378,7 @@ static void sifdebug_dump_regs(struct saa7134_dev *dev)
print_regb(SIF_SAMPLE_FREQ); print_regb(SIF_SAMPLE_FREQ);
print_regb(ANALOG_IO_SELECT); print_regb(ANALOG_IO_SELECT);
} }
#endif
static int tvaudio_thread(void *data) static int tvaudio_thread(void *data)
{ {
...@@ -440,9 +447,8 @@ static int tvaudio_thread(void *data) ...@@ -440,9 +447,8 @@ static int tvaudio_thread(void *data)
} }
if (0 == carrier) { if (0 == carrier) {
/* Oops: autoscan didn't work for some reason :-/ */ /* Oops: autoscan didn't work for some reason :-/ */
printk("%s/audio: oops: audio carrier scan failed\n", printk(KERN_WARNING "%s/audio: oops: audio carrier "
dev->name); "scan failed\n", dev->name);
sifdebug_dump_regs(dev);
} else { } else {
dprintk("found %s main sound carrier @ %d.%03d MHz\n", dprintk("found %s main sound carrier @ %d.%03d MHz\n",
dev->tvnorm->name, dev->tvnorm->name,
......
...@@ -114,7 +114,8 @@ static int buffer_activate(struct saa7134_dev *dev, ...@@ -114,7 +114,8 @@ static int buffer_activate(struct saa7134_dev *dev,
return 0; return 0;
} }
static int buffer_prepare(struct file *file, struct videobuf_buffer *vb) static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
enum v4l2_field field)
{ {
struct saa7134_fh *fh = file->private_data; struct saa7134_fh *fh = file->private_data;
struct saa7134_dev *dev = fh->dev; struct saa7134_dev *dev = fh->dev;
...@@ -158,7 +159,7 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb) ...@@ -158,7 +159,7 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb)
buf->vb.state = STATE_PREPARED; buf->vb.state = STATE_PREPARED;
buf->top_seen = 0; buf->top_seen = 0;
buf->activate = buffer_activate; buf->activate = buffer_activate;
buf->vb.field = V4L2_FIELD_SEQ_TB; buf->vb.field = field;
return 0; return 0;
oops: oops:
...@@ -218,6 +219,7 @@ struct videobuf_queue_ops saa7134_vbi_qops = { ...@@ -218,6 +219,7 @@ struct videobuf_queue_ops saa7134_vbi_qops = {
int saa7134_vbi_init(struct saa7134_dev *dev) int saa7134_vbi_init(struct saa7134_dev *dev)
{ {
INIT_LIST_HEAD(&dev->vbi_q.queue); INIT_LIST_HEAD(&dev->vbi_q.queue);
init_timer(&dev->vbi_q.timeout);
dev->vbi_q.timeout.function = saa7134_buffer_timeout; dev->vbi_q.timeout.function = saa7134_buffer_timeout;
dev->vbi_q.timeout.data = (unsigned long)(&dev->vbi_q); dev->vbi_q.timeout.data = (unsigned long)(&dev->vbi_q);
dev->vbi_q.dev = dev; dev->vbi_q.dev = dev;
......
...@@ -133,10 +133,9 @@ static struct saa7134_format formats[] = { ...@@ -133,10 +133,9 @@ static struct saa7134_format formats[] = {
}; };
#define FORMATS (sizeof(formats)/sizeof(struct saa7134_format)) #define FORMATS (sizeof(formats)/sizeof(struct saa7134_format))
static struct saa7134_tvnorm tvnorms[] = { static struct saa7134_tvnorm tvnorms[] = {
{ {
.name = "PAL-BGHI", .name = "PAL",
.id = V4L2_STD_PAL, .id = V4L2_STD_PAL,
.width = 720, .width = 720,
.height = 576, .height = 576,
...@@ -154,7 +153,7 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -154,7 +153,7 @@ static struct saa7134_tvnorm tvnorms[] = {
.vbi_v_start = 7-3, /* FIXME */ .vbi_v_start = 7-3, /* FIXME */
.vbi_v_stop = 22-3, .vbi_v_stop = 22-3,
},{ },{
.name = "NTSC-M", .name = "NTSC",
.id = V4L2_STD_NTSC, .id = V4L2_STD_NTSC,
.width = 720, .width = 720,
.height = 480, .height = 480,
...@@ -189,9 +188,10 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -189,9 +188,10 @@ static struct saa7134_tvnorm tvnorms[] = {
.video_v_stop = 311, .video_v_stop = 311,
.vbi_v_start = 7, .vbi_v_start = 7,
.vbi_v_stop = 22, .vbi_v_stop = 22,
#if 0
},{ },{
.name = "AUTO", .name = "AUTO",
.id = -1, .id = V4L2_STD_PAL|V4L2_STD_NTSC|V4L2_STD_SECAM,
.width = 768, .width = 768,
.height = 576, .height = 576,
...@@ -207,6 +207,7 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -207,6 +207,7 @@ static struct saa7134_tvnorm tvnorms[] = {
.video_v_stop = 311, .video_v_stop = 311,
.vbi_v_start = 7, .vbi_v_start = 7,
.vbi_v_stop = 22, .vbi_v_stop = 22,
#endif
} }
}; };
#define TVNORMS (sizeof(tvnorms)/sizeof(struct saa7134_tvnorm)) #define TVNORMS (sizeof(tvnorms)/sizeof(struct saa7134_tvnorm))
...@@ -825,7 +826,8 @@ static int buffer_activate(struct saa7134_dev *dev, ...@@ -825,7 +826,8 @@ static int buffer_activate(struct saa7134_dev *dev,
return 0; return 0;
} }
static int buffer_prepare(struct file *file, struct videobuf_buffer *vb) static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
enum v4l2_field field)
{ {
struct saa7134_fh *fh = file->private_data; struct saa7134_fh *fh = file->private_data;
struct saa7134_dev *dev = fh->dev; struct saa7134_dev *dev = fh->dev;
...@@ -845,12 +847,12 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb) ...@@ -845,12 +847,12 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb)
return -EINVAL; return -EINVAL;
dprintk("buffer_prepare [size=%dx%d,bytes=%d,fields=%s,%s]\n", dprintk("buffer_prepare [size=%dx%d,bytes=%d,fields=%s,%s]\n",
fh->width,fh->height,size,v4l2_field_names[fh->field], fh->width,fh->height,size,v4l2_field_names[field],
fh->fmt->name); fh->fmt->name);
if (buf->vb.width != fh->width || if (buf->vb.width != fh->width ||
buf->vb.height != fh->height || buf->vb.height != fh->height ||
buf->vb.size != size || buf->vb.size != size ||
buf->vb.field != fh->field || buf->vb.field != field ||
buf->fmt != fh->fmt) { buf->fmt != fh->fmt) {
saa7134_dma_free(dev,buf); saa7134_dma_free(dev,buf);
} }
...@@ -859,8 +861,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb) ...@@ -859,8 +861,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb)
buf->vb.width = fh->width; buf->vb.width = fh->width;
buf->vb.height = fh->height; buf->vb.height = fh->height;
buf->vb.size = size; buf->vb.size = size;
buf->vb.field = field;
buf->fmt = fh->fmt; buf->fmt = fh->fmt;
buf->vb.field = fh->field;
buf->pt = &fh->pt_cap; buf->pt = &fh->pt_cap;
err = videobuf_iolock(dev->pci,&buf->vb); err = videobuf_iolock(dev->pci,&buf->vb);
...@@ -1125,6 +1127,7 @@ static int video_open(struct inode *inode, struct file *file) ...@@ -1125,6 +1127,7 @@ static int video_open(struct inode *inode, struct file *file)
videobuf_queue_init(&fh->cap, &video_qops, videobuf_queue_init(&fh->cap, &video_qops,
dev->pci, &dev->slock, dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,
sizeof(struct saa7134_buf)); sizeof(struct saa7134_buf));
init_MUTEX(&fh->cap.lock); init_MUTEX(&fh->cap.lock);
saa7134_pgtable_alloc(dev->pci,&fh->pt_cap); saa7134_pgtable_alloc(dev->pci,&fh->pt_cap);
...@@ -1132,6 +1135,7 @@ static int video_open(struct inode *inode, struct file *file) ...@@ -1132,6 +1135,7 @@ static int video_open(struct inode *inode, struct file *file)
videobuf_queue_init(&fh->vbi, &saa7134_vbi_qops, videobuf_queue_init(&fh->vbi, &saa7134_vbi_qops,
dev->pci, &dev->slock, dev->pci, &dev->slock,
V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_BUF_TYPE_VBI_CAPTURE,
V4L2_FIELD_SEQ_TB,
sizeof(struct saa7134_buf)); sizeof(struct saa7134_buf));
init_MUTEX(&fh->vbi.lock); init_MUTEX(&fh->vbi.lock);
saa7134_pgtable_alloc(dev->pci,&fh->pt_vbi); saa7134_pgtable_alloc(dev->pci,&fh->pt_vbi);
...@@ -1155,9 +1159,13 @@ video_read(struct file *file, char *data, size_t count, loff_t *ppos) ...@@ -1155,9 +1159,13 @@ video_read(struct file *file, char *data, size_t count, loff_t *ppos)
switch (fh->type) { switch (fh->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (res_locked(fh->dev,RESOURCE_VIDEO))
return -EBUSY;
return videobuf_read_one(file, saa7134_queue(fh), return videobuf_read_one(file, saa7134_queue(fh),
data, count, ppos); data, count, ppos);
case V4L2_BUF_TYPE_VBI_CAPTURE: case V4L2_BUF_TYPE_VBI_CAPTURE:
if (!res_get(fh->dev,fh,RESOURCE_VBI))
return -EBUSY;
return videobuf_read_stream(file, saa7134_queue(fh), return videobuf_read_stream(file, saa7134_queue(fh),
data, count, ppos, 1); data, count, ppos, 1);
break; break;
...@@ -1187,7 +1195,7 @@ video_poll(struct file *file, struct poll_table_struct *wait) ...@@ -1187,7 +1195,7 @@ video_poll(struct file *file, struct poll_table_struct *wait)
up(&fh->cap.lock); up(&fh->cap.lock);
return POLLERR; return POLLERR;
} }
if (0 != fh->cap.ops->buf_prepare(file,fh->cap.read_buf)) { if (0 != fh->cap.ops->buf_prepare(file,fh->cap.read_buf,fh->cap.field)) {
up(&fh->cap.lock); up(&fh->cap.lock);
return POLLERR; return POLLERR;
} }
...@@ -1214,12 +1222,15 @@ static int video_release(struct inode *inode, struct file *file) ...@@ -1214,12 +1222,15 @@ static int video_release(struct inode *inode, struct file *file)
struct saa7134_dev *dev = fh->dev; struct saa7134_dev *dev = fh->dev;
unsigned long flags; unsigned long flags;
/* turn off overlay */
if (res_check(fh, RESOURCE_OVERLAY)) { if (res_check(fh, RESOURCE_OVERLAY)) {
spin_lock_irqsave(&dev->slock,flags); spin_lock_irqsave(&dev->slock,flags);
stop_preview(dev,fh); stop_preview(dev,fh);
spin_unlock_irqrestore(&dev->slock,flags); spin_unlock_irqrestore(&dev->slock,flags);
res_free(dev,fh,RESOURCE_OVERLAY); res_free(dev,fh,RESOURCE_OVERLAY);
} }
/* stop video capture */
if (res_check(fh, RESOURCE_VIDEO)) { if (res_check(fh, RESOURCE_VIDEO)) {
videobuf_queue_cancel(file,&fh->cap); videobuf_queue_cancel(file,&fh->cap);
res_free(dev,fh,RESOURCE_VIDEO); res_free(dev,fh,RESOURCE_VIDEO);
...@@ -1228,10 +1239,15 @@ static int video_release(struct inode *inode, struct file *file) ...@@ -1228,10 +1239,15 @@ static int video_release(struct inode *inode, struct file *file)
buffer_release(file,fh->cap.read_buf); buffer_release(file,fh->cap.read_buf);
kfree(fh->cap.read_buf); kfree(fh->cap.read_buf);
} }
if (fh->vbi.streaming)
videobuf_streamoff(file,&fh->vbi); /* stop vbi capture */
if (fh->vbi.reading) if (res_check(fh, RESOURCE_VBI)) {
videobuf_read_stop(file,&fh->vbi); if (fh->vbi.streaming)
videobuf_streamoff(file,&fh->vbi);
if (fh->vbi.reading)
videobuf_read_stop(file,&fh->vbi);
res_free(dev,fh,RESOURCE_VBI);
}
saa7134_pgtable_free(dev->pci,&fh->pt_cap); saa7134_pgtable_free(dev->pci,&fh->pt_cap);
saa7134_pgtable_free(dev->pci,&fh->pt_vbi); saa7134_pgtable_free(dev->pci,&fh->pt_vbi);
...@@ -1259,6 +1275,7 @@ int saa7134_g_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, ...@@ -1259,6 +1275,7 @@ int saa7134_g_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
memset(&f->fmt.pix,0,sizeof(f->fmt.pix)); memset(&f->fmt.pix,0,sizeof(f->fmt.pix));
f->fmt.pix.width = fh->width; f->fmt.pix.width = fh->width;
f->fmt.pix.height = fh->height; f->fmt.pix.height = fh->height;
f->fmt.pix.field = fh->cap.field;
f->fmt.pix.pixelformat = fh->fmt->fourcc; f->fmt.pix.pixelformat = fh->fmt->fourcc;
f->fmt.pix.sizeimage = f->fmt.pix.sizeimage =
(fh->width*fh->height*fh->fmt->depth)/8; (fh->width*fh->height*fh->fmt->depth)/8;
...@@ -1354,10 +1371,10 @@ int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, ...@@ -1354,10 +1371,10 @@ int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
if (0 != err) if (0 != err)
return err; return err;
fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
fh->width = f->fmt.pix.width; fh->width = f->fmt.pix.width;
fh->height = f->fmt.pix.height; fh->height = f->fmt.pix.height;
fh->field = f->fmt.pix.field; fh->cap.field = f->fmt.pix.field;
return 0; return 0;
case V4L2_BUF_TYPE_VIDEO_OVERLAY: case V4L2_BUF_TYPE_VIDEO_OVERLAY:
err = verify_preview(dev,&f->fmt.win); err = verify_preview(dev,&f->fmt.win);
...@@ -1429,11 +1446,14 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1429,11 +1446,14 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_ENUMSTD: case VIDIOC_ENUMSTD:
{ {
struct v4l2_standard *e = arg; struct v4l2_standard *e = arg;
int i;
if (e->index < 0 || e->index >= TVNORMS) i = e->index;
if (i < 0 || i >= TVNORMS)
return -EINVAL; return -EINVAL;
err = v4l2_video_std_construct(e, tvnorms[e->index].id, err = v4l2_video_std_construct(e, tvnorms[e->index].id,
tvnorms[e->index].name); tvnorms[e->index].name);
e->index = i;
if (err < 0) if (err < 0)
return err; return err;
return 0; return 0;
...@@ -1473,15 +1493,33 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1473,15 +1493,33 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_ENUMINPUT: case VIDIOC_ENUMINPUT:
{ {
struct v4l2_input *i = arg; struct v4l2_input *i = arg;
int n;
if (i->index >= SAA7134_INPUT_MAX)
n = i->index;
if (n >= SAA7134_INPUT_MAX)
return -EINVAL; return -EINVAL;
if (NULL == card_in(dev,i->index).name) if (NULL == card_in(dev,i->index).name)
return -EINVAL; return -EINVAL;
i->type = V4L2_INPUT_TYPE_CAMERA; memset(i,0,sizeof(*i));
strcpy(i->name,card_in(dev,i->index).name); i->index = n;
if (card_in(dev,i->index).tv) i->type = V4L2_INPUT_TYPE_CAMERA;
strcpy(i->name,card_in(dev,n).name);
if (card_in(dev,n).tv)
i->type = V4L2_INPUT_TYPE_TUNER; i->type = V4L2_INPUT_TYPE_TUNER;
i->audioset = 1;
if (n == dev->ctl_input) {
int v1 = saa_readb(SAA7134_STATUS_VIDEO1);
int v2 = saa_readb(SAA7134_STATUS_VIDEO2);
if (0 != (v1 & 0x40))
i->status |= V4L2_IN_ST_NO_H_LOCK;
if (0 != (v2 & 0x40))
i->status |= V4L2_IN_ST_NO_SYNC;
if (0 != (v2 & 0x0e))
i->status |= V4L2_IN_ST_MACROVISION;
}
for (n = 0; n < TVNORMS; n++)
i->std |= tvnorms[n].id;
return 0; return 0;
} }
case VIDIOC_G_INPUT: case VIDIOC_G_INPUT:
...@@ -1510,6 +1548,8 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1510,6 +1548,8 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
struct v4l2_tuner *t = arg; struct v4l2_tuner *t = arg;
int n; int n;
if (0 != t->index)
return -EINVAL;
memset(t,0,sizeof(*t)); memset(t,0,sizeof(*t));
for (n = 0; n < SAA7134_INPUT_MAX; n++) for (n = 0; n < SAA7134_INPUT_MAX; n++)
if (card_in(dev,n).tv) if (card_in(dev,n).tv)
...@@ -1521,12 +1561,12 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1521,12 +1561,12 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG1 |
V4L2_TUNER_CAP_LANG2; V4L2_TUNER_CAP_LANG2;
t->rangehigh = 0xffffffffUL; t->rangehigh = 0xffffffffUL;
if (dev->tvaudio) { t->rxsubchans = -1;
if (dev->tvaudio)
t->rxsubchans = saa7134_tvaudio_getstereo t->rxsubchans = saa7134_tvaudio_getstereo
(dev,dev->tvaudio); (dev,dev->tvaudio);
} else { if (-1 == t->rxsubchans)
t->rxsubchans = V4L2_TUNER_SUB_MONO; t->rxsubchans = V4L2_TUNER_SUB_MONO;
}
#if 1 #if 1
/* fill audmode -- FIXME: allow manual switching */ /* fill audmode -- FIXME: allow manual switching */
t->audmode = V4L2_TUNER_MODE_MONO; t->audmode = V4L2_TUNER_MODE_MONO;
...@@ -1618,12 +1658,14 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1618,12 +1658,14 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_ENUM_FMT: case VIDIOC_ENUM_FMT:
{ {
struct v4l2_fmtdesc *f = arg; struct v4l2_fmtdesc *f = arg;
enum v4l2_buf_type type;
int index; int index;
switch (f->type) { index = f->index;
type = f->type;
switch (type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OVERLAY: case V4L2_BUF_TYPE_VIDEO_OVERLAY:
index = f->index;
if (index < 0 || index >= FORMATS) if (index < 0 || index >= FORMATS)
return -EINVAL; return -EINVAL;
if (f->type == V4L2_BUF_TYPE_VIDEO_OVERLAY && if (f->type == V4L2_BUF_TYPE_VIDEO_OVERLAY &&
...@@ -1631,9 +1673,19 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1631,9 +1673,19 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL; return -EINVAL;
memset(f,0,sizeof(*f)); memset(f,0,sizeof(*f));
f->index = index; f->index = index;
f->type = type;
strncpy(f->description,formats[index].name,31); strncpy(f->description,formats[index].name,31);
f->pixelformat = formats[index].fourcc; f->pixelformat = formats[index].fourcc;
break; break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
if (0 != index)
return -EINVAL;
memset(f,0,sizeof(*f));
f->index = index;
f->type = type;
f->pixelformat = V4L2_PIX_FMT_GREY;
strcpy(f->description,"vbi data");
break;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -1898,8 +1950,8 @@ static struct file_operations radio_fops = ...@@ -1898,8 +1950,8 @@ static struct file_operations radio_fops =
struct video_device saa7134_video_template = struct video_device saa7134_video_template =
{ {
.name = "saa7134-video", .name = "saa7134-video",
type: VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY| .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY|
VID_TYPE_CLIPPING|VID_TYPE_SCALES, VID_TYPE_CLIPPING|VID_TYPE_SCALES,
.hardware = 0, .hardware = 0,
.fops = &video_fops, .fops = &video_fops,
.minor = -1, .minor = -1,
...@@ -1944,6 +1996,7 @@ int saa7134_video_init(struct saa7134_dev *dev) ...@@ -1944,6 +1996,7 @@ int saa7134_video_init(struct saa7134_dev *dev)
dev->automute = 0; dev->automute = 0;
INIT_LIST_HEAD(&dev->video_q.queue); INIT_LIST_HEAD(&dev->video_q.queue);
init_timer(&dev->video_q.timeout);
dev->video_q.timeout.function = saa7134_buffer_timeout; dev->video_q.timeout.function = saa7134_buffer_timeout;
dev->video_q.timeout.data = (unsigned long)(&dev->video_q); dev->video_q.timeout.data = (unsigned long)(&dev->video_q);
dev->video_q.dev = dev; dev->video_q.dev = dev;
...@@ -1984,7 +2037,7 @@ void saa7134_irq_video_intl(struct saa7134_dev *dev) ...@@ -1984,7 +2037,7 @@ void saa7134_irq_video_intl(struct saa7134_dev *dev)
int norm; int norm;
norm = saa_readb(SAA7134_STATUS_VIDEO1) & 0x03; norm = saa_readb(SAA7134_STATUS_VIDEO1) & 0x03;
printk("%s/video: DCSDT: %s\n",dev->name,st[norm]); dprintk("DCSDT: %s\n",st[norm]);
if (0 != norm) { if (0 != norm) {
/* wake up tvaudio audio carrier scan thread */ /* wake up tvaudio audio carrier scan thread */
......
...@@ -117,6 +117,9 @@ struct saa7134_format { ...@@ -117,6 +117,9 @@ struct saa7134_format {
#define SAA7134_BOARD_TVSTATION_RDS 7 #define SAA7134_BOARD_TVSTATION_RDS 7
#define SAA7134_BOARD_CINERGY400 8 #define SAA7134_BOARD_CINERGY400 8
#define SAA7134_BOARD_MD5044 9 #define SAA7134_BOARD_MD5044 9
#define SAA7134_BOARD_KWORLD 10
#define SAA7134_BOARD_CINERGY600 11
#define SAA7134_BOARD_MD7134 12
#define SAA7134_INPUT_MAX 8 #define SAA7134_INPUT_MAX 8
...@@ -159,7 +162,7 @@ struct saa7134_board { ...@@ -159,7 +162,7 @@ struct saa7134_board {
#define RESOURCE_OVERLAY 1 #define RESOURCE_OVERLAY 1
#define RESOURCE_VIDEO 2 #define RESOURCE_VIDEO 2
#define RESOURCE_VBI 3 #define RESOURCE_VBI 4
#define INTERLACE_AUTO 0 #define INTERLACE_AUTO 0
#define INTERLACE_ON 1 #define INTERLACE_ON 1
...@@ -224,7 +227,6 @@ struct saa7134_fh { ...@@ -224,7 +227,6 @@ struct saa7134_fh {
/* video capture */ /* video capture */
struct saa7134_format *fmt; struct saa7134_format *fmt;
int width,height; int width,height;
enum v4l2_field field;
struct videobuf_queue cap; struct videobuf_queue cap;
struct saa7134_pgtable pt_cap; struct saa7134_pgtable pt_cap;
......
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