summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/saa7134/saa7134-oss.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/saa7134/saa7134-oss.c')
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-oss.c50
1 files changed, 35 insertions, 15 deletions
diff --git a/linux/drivers/media/video/saa7134/saa7134-oss.c b/linux/drivers/media/video/saa7134/saa7134-oss.c
index 398e62438..b9081e027 100644
--- a/linux/drivers/media/video/saa7134/saa7134-oss.c
+++ b/linux/drivers/media/video/saa7134/saa7134-oss.c
@@ -92,6 +92,20 @@ static int dsp_buffer_free(struct saa7134_dev *dev)
return 0;
}
+static void dsp_dma_start(struct saa7134_dev *dev)
+{
+ dev->oss.dma_blk = 0;
+ dev->oss.dma_running = 1;
+ saa7134_set_dmabits(dev);
+}
+
+static void dsp_dma_stop(struct saa7134_dev *dev)
+{
+ dev->oss.dma_blk = -1;
+ dev->oss.dma_running = 0;
+ saa7134_set_dmabits(dev);
+}
+
static int dsp_rec_start(struct saa7134_dev *dev)
{
int err, bswap, sign;
@@ -178,10 +192,9 @@ static int dsp_rec_start(struct saa7134_dev *dev)
saa_writel(SAA7134_RS_CONTROL(6),control);
/* start dma */
+ dev->oss.recording_on = 1;
spin_lock_irqsave(&dev->slock,flags);
- dev->oss.recording = 1;
- dev->oss.dma_blk = 0;
- saa7134_set_dmabits(dev);
+ dsp_dma_start(dev);
spin_unlock_irqrestore(&dev->slock,flags);
return 0;
@@ -199,10 +212,9 @@ static int dsp_rec_stop(struct saa7134_dev *dev)
dprintk("rec_stop dma_blk=%d\n",dev->oss.dma_blk);
/* stop dma */
+ dev->oss.recording_on = 0;
spin_lock_irqsave(&dev->slock,flags);
- dev->oss.dma_blk = -1;
- dev->oss.recording = 0;
- saa7134_set_dmabits(dev);
+ dsp_dma_stop(dev);
spin_unlock_irqrestore(&dev->slock,flags);
/* unlock buffer */
@@ -259,7 +271,7 @@ static int dsp_release(struct inode *inode, struct file *file)
struct saa7134_dev *dev = file->private_data;
down(&dev->oss.lock);
- if (dev->oss.recording)
+ if (dev->oss.recording_on)
dsp_rec_stop(dev);
dsp_buffer_free(dev);
dev->oss.users_dsp--;
@@ -274,6 +286,7 @@ static ssize_t dsp_read(struct file *file, char *buffer,
struct saa7134_dev *dev = file->private_data;
DECLARE_WAITQUEUE(wait, current);
unsigned int bytes;
+ unsigned long flags;
int err,ret = 0;
add_wait_queue(&dev->oss.wq, &wait);
@@ -281,7 +294,7 @@ static ssize_t dsp_read(struct file *file, char *buffer,
while (count > 0) {
/* wait for data if needed */
if (0 == dev->oss.read_count) {
- if (!dev->oss.recording) {
+ if (!dev->oss.recording_on) {
err = dsp_rec_start(dev);
if (err < 0) {
if (0 == ret)
@@ -289,6 +302,13 @@ static ssize_t dsp_read(struct file *file, char *buffer,
break;
}
}
+ if (dev->oss.recording_on &&
+ !dev->oss.dma_running) {
+ /* recover from overruns */
+ spin_lock_irqsave(&dev->slock,flags);
+ dsp_dma_start(dev);
+ spin_unlock_irqrestore(&dev->slock,flags);
+ }
if (file->f_flags & O_NONBLOCK) {
if (0 == ret)
ret = -EAGAIN;
@@ -365,7 +385,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
down(&dev->oss.lock);
dev->oss.channels = val ? 2 : 1;
- if (dev->oss.recording) {
+ if (dev->oss.recording_on) {
dsp_rec_stop(dev);
dsp_rec_start(dev);
}
@@ -379,7 +399,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
down(&dev->oss.lock);
dev->oss.channels = val;
- if (dev->oss.recording) {
+ if (dev->oss.recording_on) {
dsp_rec_stop(dev);
dsp_rec_start(dev);
}
@@ -408,7 +428,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
case AFMT_S16_BE:
down(&dev->oss.lock);
dev->oss.afmt = val;
- if (dev->oss.recording) {
+ if (dev->oss.recording_on) {
dsp_rec_stop(dev);
dsp_rec_start(dev);
}
@@ -438,7 +458,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
case SNDCTL_DSP_RESET:
down(&dev->oss.lock);
- if (dev->oss.recording)
+ if (dev->oss.recording_on)
dsp_rec_stop(dev);
up(&dev->oss.lock);
return 0;
@@ -448,7 +468,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
case SNDCTL_DSP_SETFRAGMENT:
if (get_user(val, (int*)arg))
return -EFAULT;
- if (dev->oss.recording)
+ if (dev->oss.recording_on)
return -EBUSY;
dsp_buffer_free(dev);
dsp_buffer_conf(dev,1 << (val & 0xffff), (arg >> 16) & 0xffff);
@@ -484,7 +504,7 @@ static unsigned int dsp_poll(struct file *file, struct poll_table_struct *wait)
if (0 == dev->oss.read_count) {
down(&dev->oss.lock);
- if (!dev->oss.recording)
+ if (!dev->oss.recording_on)
dsp_rec_start(dev);
up(&dev->oss.lock);
} else
@@ -800,7 +820,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
if (dev->oss.read_count >= dev->oss.blksize * (dev->oss.blocks-2)) {
dprintk("irq: overrun [full=%d/%d]\n",dev->oss.read_count,
dev->oss.bufsize);
- dsp_rec_stop(dev);
+ dsp_dma_stop(dev);
goto done;
}