summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorMichael Hunold <devnull@localhost>2004-03-12 12:47:55 +0000
committerMichael Hunold <devnull@localhost>2004-03-12 12:47:55 +0000
commit87c4e37cac037d4f59eb6a69795715ff655eb615 (patch)
tree674c2d76dc2bf5b15e8c5d44951d5878f983ed50 /linux
parent47196b544cfc6aaee1cf3d1649c4b0745da3c401 (diff)
downloadmediapointer-dvb-s2-87c4e37cac037d4f59eb6a69795715ff655eb615.tar.gz
mediapointer-dvb-s2-87c4e37cac037d4f59eb6a69795715ff655eb615.tar.bz2
With the addition of the ressource management, an overlay couldn't be
interrupted by a streaming capture any more. So: - revamp video_begin()/video_end(), saa7146_start_preview()/saa7146_stop_preview - clean up a lot of mess around the usage of these functions - allow overlay to be suspended by streaming capture again, if ressources are available
Diffstat (limited to 'linux')
-rw-r--r--linux/drivers/media/common/saa7146_video.c352
1 files changed, 179 insertions, 173 deletions
diff --git a/linux/drivers/media/common/saa7146_video.c b/linux/drivers/media/common/saa7146_video.c
index 875bfe535..9ccda048a 100644
--- a/linux/drivers/media/common/saa7146_video.c
+++ b/linux/drivers/media/common/saa7146_video.c
@@ -5,6 +5,12 @@ static int memory = 32;
MODULE_PARM(memory,"i");
MODULE_PARM_DESC(memory, "maximum memory usage for capture buffers (default: 32Mb)");
+#define IS_CAPTURE_ACTIVE(fh) \
+ (((vv->video_status & STATUS_CAPTURE) != 0) && (vv->video_fh == fh))
+
+#define IS_OVERLAY_ACTIVE(fh) \
+ (((vv->video_status & STATUS_OVERLAY) != 0) && (vv->video_fh == fh))
+
/* format descriptions for capture and preview */
static struct saa7146_format formats[] = {
{
@@ -251,6 +257,7 @@ int saa7146_start_preview(struct saa7146_fh *fh)
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
int ret = 0, err = 0;
+ unsigned long flags;
DEB_EE(("dev:%p, fh:%p\n",dev,fh));
@@ -260,24 +267,35 @@ int saa7146_start_preview(struct saa7146_fh *fh)
return -EAGAIN;
}
+ /* check if streaming capture is running */
+ if (IS_CAPTURE_ACTIVE(fh) != 0) {
+ DEB_D(("streaming capture is active.\n"));
+ return -EBUSY;
+ }
+
/* check if overlay is running */
- if( 0 != vv->ov_data ) {
- if( fh != vv->ov_data->fh ) {
- DEB_D(("overlay is running in another open.\n"));
- return -EAGAIN;
+ if (IS_OVERLAY_ACTIVE(fh) != 0) {
+ if (vv->video_fh == fh) {
+ DEB_D(("overlay is already active.\n"));
+ return 0;
}
- DEB_D(("overlay is already active.\n"));
- return 0;
- }
-
- if( 0 != vv->streaming ) {
- DEB_D(("streaming capture is active.\n"));
+ DEB_D(("overlay is already active in another open.\n"));
return -EBUSY;
- }
-
+ }
+
+ spin_lock_irqsave(&dev->slock,flags);
+
+ if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
+ DEB_D(("cannot get necessary overlay resources\n"));
+ err = -EBUSY;
+ goto out;
+ }
+
err = try_win(dev,&fh->ov.win);
if (0 != err) {
- return err;
+ saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
+ err = -EBUSY;
+ goto out;
}
vv->ov_data = &fh->ov;
@@ -288,35 +306,55 @@ int saa7146_start_preview(struct saa7146_fh *fh)
vv->ov_fmt->name,v4l2_field_names[fh->ov.win.field]));
if (0 != (ret = saa7146_enable_overlay(fh))) {
- vv->ov_data = NULL;
DEB_D(("enabling overlay failed: %d\n",ret));
- return ret;
+ saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
+ err = ret;
+ goto out;
}
- return 0;
+ vv->video_status = STATUS_OVERLAY;
+ vv->video_fh = fh;
+ err = 0;
+
+out:
+ spin_unlock_irqrestore(&dev->slock,flags);
+ return err;
}
int saa7146_stop_preview(struct saa7146_fh *fh)
{
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
+ unsigned long flags;
DEB_EE(("dev:%p, fh:%p\n",dev,fh));
- /* check if overlay is running */
- if( 0 == vv->ov_data ) {
- DEB_D(("overlay is not active.\n"));
+ /* check if streaming capture is running */
+ if (IS_CAPTURE_ACTIVE(fh) != 0) {
+ DEB_D(("streaming capture is active.\n"));
+ return -EBUSY;
+ }
+ /* check if overlay is running at all */
+ if ((vv->video_status & STATUS_OVERLAY) == 0) {
+ DEB_D(("no active streaming capture.\n"));
return 0;
}
- if( fh != vv->ov_data->fh ) {
- DEB_D(("overlay is active, but for another open.\n"));
- return 1;
+ if (vv->video_fh != fh) {
+ DEB_D(("streaming capture is active, but in another open.\n"));
+ return -EBUSY;
}
- vv->ov_data = NULL;
+ spin_lock_irqsave(&dev->slock,flags);
+
+ saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
+
+ vv->video_status = 0;
+ vv->video_fh = NULL;
+
saa7146_disable_overlay(fh);
+ spin_unlock_irqrestore(&dev->slock,flags);
return 0;
}
@@ -325,15 +363,14 @@ static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
- unsigned long flags;
int err;
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh));
- if( fh == vv->streaming ) {
- DEB_EE(("streaming capture is active"));
- return -EAGAIN;
+ if (IS_CAPTURE_ACTIVE(fh) != 0) {
+ DEB_EE(("streaming capture is active\n"));
+ return -EBUSY;
}
err = try_fmt(fh,f);
if (0 != err)
@@ -359,16 +396,13 @@ static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
/* fh->ov.fh is used to indicate that we have valid overlay informations, too */
fh->ov.fh = fh;
- /* check if we have an active overlay */
- if( vv->ov_data != NULL ) {
- if( fh == vv->ov_data->fh) {
- spin_lock_irqsave(&dev->slock,flags);
- saa7146_stop_preview(fh);
- saa7146_start_preview(fh);
- spin_unlock_irqrestore(&dev->slock,flags);
- }
- }
up(&dev->lock);
+
+ /* check if our current overlay is active */
+ if (IS_OVERLAY_ACTIVE(fh) != 0) {
+ saa7146_stop_preview(fh);
+ saa7146_start_preview(fh);
+ }
return 0;
default:
DEB_D(("unknown format type '%d'\n",f->type));
@@ -480,8 +514,6 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
struct saa7146_vv *vv = dev->vv_data;
const struct v4l2_queryctrl* ctrl;
- unsigned long flags;
- int restart_overlay = 0;
ctrl = ctrl_by_id(c->id);
if (NULL == ctrl) {
@@ -489,6 +521,8 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
return -EINVAL;
}
+ down(&dev->lock);
+
switch (ctrl->type) {
case V4L2_CTRL_TYPE_BOOLEAN:
case V4L2_CTRL_TYPE_MENU:
@@ -528,35 +562,31 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
break;
}
case V4L2_CID_HFLIP:
- /* fixme: we can supfhrt changing VFLIP and HFLIP here... */
- if( 0 != vv->streaming ) {
+ /* fixme: we can support changing VFLIP and HFLIP here... */
+ if (IS_CAPTURE_ACTIVE(fh) != 0) {
DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
+ up(&dev->lock);
return -EINVAL;
}
vv->hflip = c->value;
- restart_overlay = 1;
break;
case V4L2_CID_VFLIP:
- if( 0 != vv->streaming ) {
+ if (IS_CAPTURE_ACTIVE(fh) != 0) {
DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
+ up(&dev->lock);
return -EINVAL;
}
vv->vflip = c->value;
- restart_overlay = 1;
break;
default: {
return -EINVAL;
}
}
- if( 0 != restart_overlay ) {
- if( 0 != vv->ov_data ) {
- if( fh == vv->ov_data->fh ) {
- spin_lock_irqsave(&dev->slock,flags);
- saa7146_stop_preview(fh);
- saa7146_start_preview(fh);
- spin_unlock_irqrestore(&dev->slock,flags);
- }
- }
+ up(&dev->lock);
+
+ if (IS_OVERLAY_ACTIVE(fh) != 0) {
+ saa7146_stop_preview(fh);
+ saa7146_start_preview(fh);
}
return 0;
}
@@ -689,25 +719,29 @@ static int video_begin(struct saa7146_fh *fh)
struct saa7146_format *fmt = NULL;
unsigned long flags;
unsigned int resource;
- int ret = 0;
+ int ret = 0, err = 0;
DEB_EE(("dev:%p, fh:%p\n",dev,fh));
- if( fh == vv->streaming ) {
- DEB_S(("already capturing.\n"));
+ if ((vv->video_status & STATUS_CAPTURE) != 0) {
+ if (vv->video_fh == fh) {
+ DEB_S(("already capturing.\n"));
+ return 0;
+ }
+ DEB_S(("already capturing in another open.\n"));
return -EBUSY;
}
- if( vv->streaming != 0 ) {
- DEB_S(("already capturing, but in another open.\n"));
- return -EBUSY;
+ if ((vv->video_status & STATUS_OVERLAY) != 0) {
+ DEB_S(("warning: suspending overlay video for streaming capture.\n"));
+ vv->ov_suspend = vv->video_fh;
+ err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
+ if (0 != err) {
+ DEB_D(("suspending video failed. aborting\n"));
+ return err;
+ }
}
- if( 0 != vv->ov_data ) {
- DEB_S(("overlay is active. disable it first.\n"));
- return -EBUSY;
- }
-
fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
/* we need to have a valid format set here */
BUG_ON(NULL == fmt);
@@ -721,6 +755,10 @@ static int video_begin(struct saa7146_fh *fh)
ret = saa7146_res_get(fh, resource);
if (0 == ret) {
DEB_S(("cannot get capture resource %d\n",resource));
+ if (vv->ov_suspend != NULL) {
+ saa7146_start_preview(vv->ov_suspend);
+ vv->ov_suspend = NULL;
+ }
return -EBUSY;
}
@@ -732,7 +770,9 @@ static int video_begin(struct saa7146_fh *fh)
/* enable rps0 irqs */
IER_ENABLE(dev, MASK_27);
- vv->streaming = fh;
+ vv->video_fh = fh;
+ vv->video_status = STATUS_CAPTURE;
+
spin_unlock_irqrestore(&dev->slock,flags);
return 0;
}
@@ -747,9 +787,14 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
u32 dmas = 0;
DEB_EE(("dev:%p, fh:%p\n",dev,fh));
- if( vv->streaming != fh ) {
+ if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
DEB_S(("not capturing.\n"));
- return -EINVAL;
+ return 0;
+ }
+
+ if (vv->video_fh != fh) {
+ DEB_S(("capturing, but in another open.\n"));
+ return -EBUSY;
}
fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
@@ -776,9 +821,15 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
/* shut down all used video dma transfers */
saa7146_write(dev, MC1, dmas);
- vv->streaming = NULL;
+ vv->video_fh = NULL;
+ vv->video_status = 0;
spin_unlock_irqrestore(&dev->slock, flags);
+
+ if (vv->ov_suspend != NULL) {
+ saa7146_start_preview(vv->ov_suspend);
+ vv->ov_suspend = NULL;
+ }
return 0;
}
@@ -795,7 +846,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
- unsigned long flags;
int err = 0, result = 0, ee = 0;
struct saa7146_use_ops *ops;
@@ -872,8 +922,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
{
struct v4l2_framebuffer *fb = arg;
struct saa7146_format *fmt;
- struct saa7146_fh *ov_fh = NULL;
- int restart_overlay = 0;
DEB_EE(("VIDIOC_S_FBUF\n"));
/*
@@ -895,10 +943,10 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
}
down(&dev->lock);
- if( vv->ov_data != NULL ) {
- ov_fh = vv->ov_data->fh;
- saa7146_stop_preview(ov_fh);
- restart_overlay = 1;
+ if (vv->video_status != 0) {
+ DEB_S(("overlay video is active\n"));
+ up(&dev->lock);
+ return -EBUSY;
}
/* ok, accept it */
@@ -908,10 +956,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
vv->ov_fb.fmt.bytesperline =
vv->ov_fb.fmt.width*fmt->depth/8;
- if( 0 != restart_overlay ) {
- saa7146_start_preview(ov_fh);
- }
-
up(&dev->lock);
return 0;
@@ -976,9 +1020,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
#endif
{
DEB_EE(("VIDIOC_S_CTRL\n"));
- down(&dev->lock);
err = set_control(fh,arg);
- up(&dev->lock);
return err;
}
case VIDIOC_G_PARM:
@@ -1037,27 +1079,27 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
case VIDIOC_S_STD:
{
v4l2_std_id *id = arg;
- int i;
-
- int restart_overlay = 0;
int found = 0;
+ int i, err;
- struct saa7146_fh *ov_fh = NULL;
-
DEB_EE(("VIDIOC_S_STD\n"));
- if( 0 != vv->streaming ) {
+ if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
+ DEB_D(("cannot change video standard while streaming capture is active\n"));
return -EBUSY;
}
- down(&dev->lock);
-
- if( vv->ov_data != NULL ) {
- ov_fh = vv->ov_data->fh;
- saa7146_stop_preview(ov_fh);
- restart_overlay = 1;
+ if ((vv->video_status & STATUS_OVERLAY) != 0) {
+ vv->ov_suspend = vv->video_fh;
+ err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
+ if (0 != err) {
+ DEB_D(("suspending video failed. aborting\n"));
+ return err;
+ }
}
+ down(&dev->lock);
+
for(i = 0; i < dev->ext_vv_data->num_stds; i++)
if (*id & dev->ext_vv_data->stds[i].id)
break;
@@ -1068,11 +1110,13 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
found = 1;
}
- if( 0 != restart_overlay ) {
- saa7146_start_preview(ov_fh);
- }
up(&dev->lock);
+ if (vv->ov_suspend != NULL) {
+ saa7146_start_preview(vv->ov_suspend);
+ vv->ov_suspend = NULL;
+ }
+
if( 0 == found ) {
DEB_EE(("VIDIOC_S_STD: standard not found.\n"));
return -EINVAL;
@@ -1091,41 +1135,11 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
int err = 0;
DEB_D(("VIDIOC_OVERLAY on:%d\n",on));
-
- if( NULL == vv->ov_fmt && on != 0 ) {
- DEB_D(("VIDIOC_OVERLAY: no framebuffer informations. call S_FBUF first!\n"));
- return -EAGAIN;
- }
-
- if( vv->ov_data != NULL ) {
- if( fh != vv->ov_data->fh) {
- DEB_D(("overlay already active in another open\n"));
- return -EAGAIN;
- }
- if (on != 0) {
- DEB_D(("overlay is already active.\n"));
- return 0;
- }
- spin_lock_irqsave(&dev->slock,flags);
+ if (on != 0) {
+ err = saa7146_start_preview(fh);
+ } else {
err = saa7146_stop_preview(fh);
- spin_unlock_irqrestore(&dev->slock,flags);
- /* free resources */
- saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
- return err;
}
- if (on == 0) {
- DEB_D(("overlay not running. doing nothing.\n"));
- return 0;
- }
-
- if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
- DEB_D(("cannot get overlay resources\n"));
- return -EBUSY;
- }
-
- spin_lock_irqsave(&dev->slock,flags);
- err = saa7146_start_preview(fh);
- spin_unlock_irqrestore(&dev->slock,flags);
return err;
}
case VIDIOC_REQBUFS: {
@@ -1156,11 +1170,6 @@ 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( fh == vv->streaming ) {
- DEB_D(("already capturing.\n"));
- return 0;
- }
-
err = video_begin(fh);
if( 0 != err) {
return err;
@@ -1173,18 +1182,26 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));
- if (NULL == vv->streaming ) {
- DEB_D(("not capturing\n"));
+ /* ugly: we need to copy some checks from video_end(),
+ because videobuf_streamoff() relies on the capture running.
+ check and fix this */
+ if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
+ DEB_S(("not capturing.\n"));
return 0;
}
- if( fh != vv->streaming ) {
- DEB_D(("this open is not capturing.\n"));
- return -EINVAL;
+ if (vv->video_fh != fh) {
+ DEB_S(("capturing, but in another open.\n"));
+ return -EBUSY;
}
err = videobuf_streamoff(file,q);
- video_end(fh, file);
+ if (0 != err) {
+ DEB_D(("warning: videobuf_streamoff() failed.\n"));
+ video_end(fh, file);
+ } else {
+ err = video_end(fh, file);
+ }
return err;
}
case VIDIOCGMBUF:
@@ -1418,20 +1435,16 @@ 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;
-
- if( 0 != vv->ov_data ) {
- if( fh == vv->ov_data->fh ) {
- spin_lock_irqsave(&dev->slock,flags);
- saa7146_stop_preview(fh);
- spin_unlock_irqrestore(&dev->slock,flags);
- saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
- }
- }
+ int err;
- if( fh == vv->streaming ) {
- video_end(fh, file);
+ if (IS_CAPTURE_ACTIVE(fh) != 0) {
+ err = video_end(fh, file);
+ } else if (IS_CAPTURE_ACTIVE(fh) != 0) {
+ err = saa7146_stop_preview(fh);
}
+
+ /* hmm, why is this function declared void? */
+ /* return err */
}
@@ -1459,41 +1472,34 @@ static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *p
struct saa7146_vv *vv = dev->vv_data;
ssize_t ret = 0;
- int restart_overlay = 0;
- struct saa7146_fh *ov_fh = NULL;
-
DEB_EE(("called.\n"));
- /* fixme: should we allow read() captures while streaming capture? */
- if( 0 != vv->streaming ) {
- DEB_S(("already capturing.\n"));
+ if ((vv->video_status & STATUS_CAPTURE) != 0) {
+ /* fixme: should we allow read() captures while streaming capture? */
+ if (vv->video_fh == fh) {
+ DEB_S(("already capturing.\n"));
+ return -EBUSY;
+ }
+ DEB_S(("already capturing in another open.\n"));
return -EBUSY;
}
- /* stop any active overlay */
- if( vv->ov_data != NULL ) {
- ov_fh = vv->ov_data->fh;
- saa7146_stop_preview(ov_fh);
- saa7146_res_free(ov_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
- restart_overlay = 1;
- }
-
ret = video_begin(fh);
if( 0 != ret) {
goto out;
}
ret = videobuf_read_one(file,&fh->video_q , data, count, ppos);
- video_end(fh, file);
-
+ if (ret != 0) {
+ video_end(fh, file);
+ } else {
+ ret = video_end(fh, file);
+ }
out:
/* restart overlay if it was active before */
- if( 0 != restart_overlay ) {
- if (0 == saa7146_res_get(ov_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
- DEB_D(("cannot get overlay resources again!\n"));
- BUG();
- }
- saa7146_start_preview(ov_fh);
+ if (vv->ov_suspend != NULL) {
+ saa7146_start_preview(vv->ov_suspend);
+ vv->ov_suspend = NULL;
}
return ret;