public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Michael Hunold <hunold@linuxtv.org>
To: hunold@linuxtv.org, torvalds@osdl.org, akpm@osdl.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH 1/9] V4L: Update the saa7146 driver
Date: Mon, 26 Apr 2004 09:40:43 -0400	[thread overview]
Message-ID: <10829866821854@convergence.de> (raw)
In-Reply-To: <10829866543802@convergence.de>

- [DVB] saa7146 driver updates:
   - remove bogus v_calc and h_calc parameters, which can be easily retrieved from other values
   - add class parameter to i2c initialization
   - let resource handling provide more useful informations
   - sanitize overlay/capture locking
diff -urawBN xx-linux-2.6.5/drivers/media/common/saa7146_fops.c linux-2.6.5-patched/drivers/media/common/saa7146_fops.c
--- xx-linux-2.6.5/drivers/media/common/saa7146_fops.c	2004-02-22 14:48:47.000000000 +0100
+++ linux-2.6.5-patched/drivers/media/common/saa7146_fops.c	2004-03-11 11:58:36.000000000 +0100
@@ -10,14 +10,14 @@
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
 
-	if (fh->resources & bit)
+	if (fh->resources & bit) {
+		DEB_D(("already allocated! want: 0x%02x, cur:0x%02x\n",bit,vv->resources));
 		/* have it already allocated */
 		return 1;
+	}
 
 	/* is it free? */
-	DEB_D(("getting lock...\n"));
 	down(&dev->lock);
-	DEB_D(("got lock\n"));
 	if (vv->resources & bit) {
 		DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit));
 		/* no, someone else uses it */
@@ -27,7 +27,7 @@
 	/* it's free, grab it */
 	fh->resources  |= bit;
 	vv->resources |= bit;
-	DEB_D(("res: get %d\n",bit));
+	DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources));
 	up(&dev->lock);
 	return 1;
 }
@@ -51,12 +51,10 @@
 	if ((fh->resources & bits) != bits)
 		BUG();
 
-	DEB_D(("getting lock...\n"));
 	down(&dev->lock);
-	DEB_D(("got lock\n"));
 	fh->resources  &= ~bits;
 	vv->resources &= ~bits;
-	DEB_D(("res: put %d\n",bits));
+	DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources));
 	up(&dev->lock);
 }
 
diff -urawBN xx-linux-2.6.5/drivers/media/common/saa7146_hlp.c linux-2.6.5-patched/drivers/media/common/saa7146_hlp.c
--- xx-linux-2.6.5/drivers/media/common/saa7146_hlp.c	2004-02-22 14:48:47.000000000 +0100
+++ linux-2.6.5-patched/drivers/media/common/saa7146_hlp.c	2004-03-15 20:38:14.000000000 +0100
@@ -536,13 +536,13 @@
 	/* set vertical scale */
 	hps_v_scale = 0; /* all bits get set by the function-call */
 	hps_v_gain  = 0; /* fixme: saa7146_read(dev, HPS_V_GAIN);*/ 
-	calculate_v_scale_registers(dev, field, vv->standard->v_calc, height, &hps_v_scale, &hps_v_gain);
+	calculate_v_scale_registers(dev, field, vv->standard->v_field*2, height, &hps_v_scale, &hps_v_gain);
 
 	/* set horizontal scale */
 	hps_ctrl 	= 0;
 	hps_h_prescale	= 0; /* all bits get set in the function */
 	hps_h_scale	= 0;
-	calculate_h_scale_registers(dev, vv->standard->h_calc, width, vv->hflip, &hps_ctrl, &hps_v_gain, &hps_h_prescale, &hps_h_scale);
+	calculate_h_scale_registers(dev, vv->standard->h_pixels, width, vv->hflip, &hps_ctrl, &hps_v_gain, &hps_h_prescale, &hps_h_scale);
 
 	/* set hyo and hxo */
 	calculate_hxo_and_hyo(vv, &hps_h_scale, &hps_ctrl);
diff -urawBN xx-linux-2.6.5/drivers/media/common/saa7146_i2c.c linux-2.6.5-patched/drivers/media/common/saa7146_i2c.c
--- xx-linux-2.6.5/drivers/media/common/saa7146_i2c.c	2004-01-16 18:25:17.000000000 +0100
+++ linux-2.6.5-patched/drivers/media/common/saa7146_i2c.c	2004-04-06 15:05:23.000000000 +0200
@@ -400,7 +400,7 @@
 	.functionality	= saa7146_i2c_func,
 };
 
-int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate)
+int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, unsigned int class, u32 bitrate)
 {
 	DEB_EE(("bitrate: 0x%08x\n",bitrate));
 	
@@ -417,16 +417,13 @@
 		i2c_adapter->data = dev;
 #else
 		i2c_set_adapdata(i2c_adapter,dev);
+		i2c_adapter->class = class;
 #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 -urawBN xx-linux-2.6.5/drivers/media/common/saa7146_video.c linux-2.6.5-patched/drivers/media/common/saa7146_video.c
--- xx-linux-2.6.5/drivers/media/common/saa7146_video.c	2004-03-12 20:31:28.000000000 +0100
+++ linux-2.6.5-patched/drivers/media/common/saa7146_video.c	2004-03-19 15:15:04.000000000 +0100
@@ -5,6 +5,12 @@
 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[] = {
 	{
@@ -260,24 +266,31 @@
 		return -EAGAIN;
 	}
 
-	/* 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;
+	/* 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 (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 in another open.\n"));
+		return -EBUSY;
+	}
 	
-	if( 0 != vv->streaming ) {
-		DEB_D(("streaming capture is active.\n"));
+	if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
+		DEB_D(("cannot get necessary overlay resources\n"));
 		return -EBUSY;
 	}	
 	
 	err = try_win(dev,&fh->ov.win);
 	if (0 != err) {
-		return err;
+		saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
+		return -EBUSY;
 	}
 	
 	vv->ov_data = &fh->ov;
@@ -288,11 +301,14 @@
 		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));
+		saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
 		return ret;
 	}
 
+	vv->video_status = STATUS_OVERLAY;
+	vv->video_fh = fh;
+
 	return 0;
 }
 
@@ -303,20 +319,30 @@
 
 	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"));
-		return 0;
+	/* check if streaming capture is running */
+	if (IS_CAPTURE_ACTIVE(fh) != 0) {
+		DEB_D(("streaming capture is active.\n"));
+		return -EBUSY;
 	}
 
-	if( fh != vv->ov_data->fh ) {
-		DEB_D(("overlay is active, but for another open.\n"));
+	/* check if overlay is running at all */
+	if ((vv->video_status & STATUS_OVERLAY) == 0) {		
+		DEB_D(("no active overlay.\n"));
 		return 0;
 	}
 
-	vv->ov_data = NULL;
+	if (vv->video_fh != fh) {
+		DEB_D(("overlay is active, but in another open.\n"));
+		return -EBUSY;
+	}
+
+	vv->video_status = 0;
+	vv->video_fh = NULL;
+
 	saa7146_disable_overlay(fh);
 	
+	saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
+
 	return 0;
 }
 
@@ -325,15 +351,14 @@
 	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 +384,13 @@
 		/* 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);
+		up(&dev->lock);
+
+		/* check if our current overlay is active */
+		if (IS_OVERLAY_ACTIVE(fh) != 0) {
 				saa7146_stop_preview(fh);
 				saa7146_start_preview(fh);
-				spin_unlock_irqrestore(&dev->slock,flags);
-			}
 		}
-		up(&dev->lock);
 		return 0;
 	default:
 		DEB_D(("unknown format type '%d'\n",f->type));
@@ -480,8 +502,6 @@
 	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 +509,8 @@
 		return -EINVAL;
 	}
 	
+	down(&dev->lock);
+
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_BOOLEAN:
 	case V4L2_CTRL_TYPE_MENU:
@@ -528,35 +550,31 @@
 		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);
+	up(&dev->lock);
+	
+	if (IS_OVERLAY_ACTIVE(fh) != 0) {
 				saa7146_stop_preview(fh);
 				saa7146_start_preview(fh);
-				spin_unlock_irqrestore(&dev->slock,flags);
-			}
-		}
 	}
 	return 0;
 }
@@ -687,21 +705,30 @@
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
 	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 ) {
+	if ((vv->video_status & STATUS_CAPTURE) != 0) {
+		if (vv->video_fh == fh) {
 		DEB_S(("already capturing.\n"));
-		return -EBUSY;
+			return 0;
 	}
-	if( vv->streaming != 0 ) {
-		DEB_S(("already capturing, but in another open.\n"));
+		DEB_S(("already capturing 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;
+		}
+	}
+	
 	fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
 	/* we need to have a valid format set here */
 	BUG_ON(NULL == fmt);
@@ -715,19 +742,22 @@
 	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;
 	}
 
-	spin_lock_irqsave(&dev->slock,flags);
-
 	/* clear out beginning of streaming bit (rps register 0)*/
 	saa7146_write(dev, MC2, MASK_27 );
 
 	/* enable rps0 irqs */
 	IER_ENABLE(dev, MASK_27);
 
-	vv->streaming = fh;
-	spin_unlock_irqrestore(&dev->slock,flags);
+	vv->video_fh = fh;
+	vv->video_status = STATUS_CAPTURE;
+
 	return 0;
 }
 
@@ -741,9 +771,14 @@
 	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);
@@ -757,8 +792,6 @@
 		resource = RESOURCE_DMA1_HPS;
 		dmas = MASK_22;
 	}
-	saa7146_res_free(fh, resource);
-
 	spin_lock_irqsave(&dev->slock,flags);
 
 	/* disable rps0  */
@@ -770,13 +803,20 @@
 	/* shut down all used video dma transfers */
 	saa7146_write(dev, MC1, dmas);
 
-	vv->streaming = NULL;
-
 	spin_unlock_irqrestore(&dev->slock, flags);
 	
-	return 0;
+	vv->video_fh = NULL;
+	vv->video_status = 0;
+
+	saa7146_res_free(fh, resource);
+
+	if (vv->ov_suspend != NULL) {
+		saa7146_start_preview(vv->ov_suspend);
+		vv->ov_suspend = NULL;
 }
 
+	return 0;
+}
 
 /*
  * This function is _not_ called directly, but from
@@ -790,7 +830,6 @@
 	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;
@@ -867,17 +906,12 @@
 	{
 		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"));
 
-/*
-		if(!capable(CAP_SYS_ADMIN)) { // && !capable(CAP_SYS_RAWIO)) {
-			DEB_D(("VIDIOC_S_FBUF: not CAP_SYS_ADMIN or CAP_SYS_RAWIO.\n"));
+		if(!capable(CAP_SYS_ADMIN) &&
+		   !capable(CAP_SYS_RAWIO))
 			return -EPERM;
-		}
-*/
 
 		/* check args */
 		fmt = format_by_fourcc(dev,fb->fmt.pixelformat);
@@ -890,12 +924,15 @@
 			DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",(char *)&fmt->pixelformat));
 		}
 
-		down(&dev->lock);
-		if( vv->ov_data != NULL ) {
-			ov_fh = vv->ov_data->fh;
-			saa7146_stop_preview(ov_fh);
-			restart_overlay = 1;
+		/* check if overlay is running */
+		if (IS_OVERLAY_ACTIVE(fh) != 0) {		
+			if (vv->video_fh != fh) {
+				DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n"));
+				return -EBUSY;
 		}
+		}
+
+		down(&dev->lock);
 
 		/* ok, accept it */
 		vv->ov_fb = *fb;
@@ -904,10 +941,6 @@
 			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;
@@ -966,11 +999,13 @@
 		return get_control(fh,arg);
 	}
 	case VIDIOC_S_CTRL:
+
+
+
+
 	{
 		DEB_EE(("VIDIOC_S_CTRL\n"));
-		down(&dev->lock);
 		err = set_control(fh,arg);
-		up(&dev->lock);
 		return err;
 	}
         case VIDIOC_G_PARM:
@@ -1029,29 +1064,27 @@
 	case VIDIOC_S_STD:
 	{
 		v4l2_std_id *id = arg;
-		int i;
-		
-		int restart_overlay = 0;
 		int found = 0;
-		
-		struct saa7146_fh *ov_fh = NULL;
+		int i, err;
 						
 		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;
 		}
 
-		DEB_D(("before getting lock...\n"));
-		down(&dev->lock);
-		DEB_D(("got lock\n"));
-
-		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;
@@ -1062,11 +1095,13 @@
 			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;
@@ -1076,49 +1111,20 @@
 		return 0;
 	}
 	case VIDIOC_OVERLAY:
+
+
+
+
 	{
 		int on = *(int *)arg;
 		int err = 0;
 
-		if( NULL == vv->ov_fmt && on != 0 ) {
-			DEB_D(("VIDIOC_OVERLAY: no framebuffer informations. call S_FBUF first!\n"));
-			return -EAGAIN;
-		}
-
 		DEB_D(("VIDIOC_OVERLAY on:%d\n",on));
-		if( 0 != on ) {
-			if( vv->ov_data != NULL ) {
-				if( fh != vv->ov_data->fh) {
-					DEB_D(("overlay already active in another open\n"));
-					return -EAGAIN;
-				}
-			}
-
-			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);
+		if (on != 0) {
 			err = saa7146_start_preview(fh);
-			spin_unlock_irqrestore(&dev->slock,flags);
-			return err;
-		}
-
-			if( vv->ov_data != NULL ) {
-				if( fh != vv->ov_data->fh) {
-				DEB_D(("overlay is active, but in another open\n"));
-					return -EAGAIN;
-				}
 		} else {
-			DEB_D(("overlay is not active\n"));
-			return 0;		
-			}
-			spin_lock_irqsave(&dev->slock,flags);
 			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;
 	}
 	case VIDIOC_REQBUFS: {
@@ -1149,11 +1155,6 @@
 		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;
@@ -1166,13 +1167,26 @@
 
 		DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));
 
-		if( fh != vv->streaming ) {
-			DEB_D(("this open is not capturing.\n"));
-			return -EINVAL;
+		/* 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 (vv->video_fh != fh) {
+			DEB_S(("capturing, but in another open.\n"));
+			return -EBUSY;
 		}
 
 		err = videobuf_streamoff(file,q);
+		if (0 != err) {
+			DEB_D(("warning: videobuf_streamoff() failed.\n"));
 		video_end(fh, file);
+		} else {
+			err = video_end(fh, file);
+		}
 		return err;
 	}
 	case VIDIOCGMBUF:
@@ -1406,20 +1420,16 @@
 {
 	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
 	struct saa7146_vv *vv = dev->vv_data;
-	unsigned long flags;
+	int err;
 	
-	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);
-		}
+	if (IS_CAPTURE_ACTIVE(fh) != 0) {
+		err = video_end(fh, file);		
+	} else if (IS_OVERLAY_ACTIVE(fh) != 0) {
+		err = saa7146_stop_preview(fh);
 	}
 	
-	if( fh == vv->streaming ) {
-		video_end(fh, file);		
-	}
+	/* hmm, why is this function declared void? */
+	/* return err */
 }
 
 
@@ -1447,23 +1457,16 @@
 	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"));
 
+	if ((vv->video_status & STATUS_CAPTURE) != 0) {
 	/* fixme: should we allow read() captures while streaming capture? */
-	if( 0 != vv->streaming ) {
+		if (vv->video_fh == fh) {
 		DEB_S(("already capturing.\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;
+		DEB_S(("already capturing in another open.\n"));
+		return -EBUSY;
 	}
 
 	ret = video_begin(fh);
@@ -1472,16 +1475,16 @@
 	}
 
 	ret = videobuf_read_one(file,&fh->video_q , data, count, ppos);
+	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;
diff -urawBN xx-linux-2.6.5/include/media/saa7146.h linux-2.6.5-patched/include/media/saa7146.h
--- xx-linux-2.6.5/include/media/saa7146.h	2004-02-22 14:49:05.000000000 +0100
+++ linux-2.6.5-patched/include/media/saa7146.h	2004-04-23 22:07:10.000000000 +0200
@@ -154,7 +166,7 @@
 };
 
 /* from saa7146_i2c.c */
-int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate);
+int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, unsigned int class, u32 bitrate);
 int saa7146_i2c_transfer(struct saa7146_dev *saa, const struct i2c_msg msgs[], int num,  int retries);
 
 /* from saa7146_core.c */
diff -urawBN xx-linux-2.6.5/include/media/saa7146_vv.h linux-2.6.5-patched/include/media/saa7146_vv.h
--- xx-linux-2.6.5/include/media/saa7146_vv.h	2004-02-22 14:49:05.000000000 +0100
+++ linux-2.6.5-patched/include/media/saa7146_vv.h	2004-03-15 20:38:16.000000000 +0100
@@ -44,11 +44,9 @@
 
 	int v_offset;	/* number of lines of vertical offset before processing */
 	int v_field;	/* number of lines in a field for HPS to process */
-	int v_calc;	/* number of vertical active lines */
 	
 	int h_offset;	/* horizontal offset of processing window */
 	int h_pixels;	/* number of horizontal pixels to process */
-	int h_calc;	/* number of horizontal active pixels */
 	
 	int v_max_out;
 	int h_max_out;
@@ -104,6 +102,9 @@
 	unsigned int resources;	/* resource management for device open */
 };
 
+#define STATUS_OVERLAY	0x01
+#define STATUS_CAPTURE	0x02
+
 struct saa7146_vv
 {
 	int vbi_minor;
@@ -117,14 +118,17 @@
 
 	int video_minor;
 
+	int				video_status;
+	struct saa7146_fh		*video_fh;
+
 	/* video overlay */
 	struct v4l2_framebuffer		ov_fb;
 	struct saa7146_format		*ov_fmt;
 	struct saa7146_overlay		*ov_data;
+	struct saa7146_fh		*ov_suspend;
 
 	/* video capture */
 	struct saa7146_dmaqueue		video_q;
-	struct saa7146_fh		*streaming;
 	enum v4l2_field			last_field;
 
 	/* common: fixme? shouldn't this be in saa7146_fh?



  reply	other threads:[~2004-04-26 13:42 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-04-26 13:40 [PATCH 0/9] LinuxTV.org DVB update Michael Hunold
2004-04-26 13:40 ` Michael Hunold [this message]
2004-04-26 13:41   ` [PATCH 2/9] DVB: Documentation and Kconfig updazes Michael Hunold
2004-04-26 13:41     ` [PATCH 3/9] DVB: Update DVB budget drivers Michael Hunold
2004-04-26 13:42       ` [PATCH 4/9] DVB: Add EN50221 cam support to dvb-core Michael Hunold
2004-04-26 13:42         ` [PATCH 5/9] DVB: Other DVB core updates Michael Hunold
2004-04-26 13:42           ` [PATCH 6/9] DVB: AV7110 DVB driver updates Michael Hunold
2004-04-26 13:42             ` [PATCH 7/9] DVB: Misc. DVB frontend " Michael Hunold
2004-04-26 13:42               ` [PATCH 8/9] DVB: Misc. DVB USB " Michael Hunold
2004-04-26 13:42                 ` [PATCH 9/9] DVB: Follow saa7146 changes in affected V4L drivers Michael Hunold
2004-04-26 14:05     ` [PATCH 2/9] DVB: Documentation and Kconfig updazes Måns Rullgård

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=10829866821854@convergence.de \
    --to=hunold@linuxtv.org \
    --cc=akpm@osdl.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@osdl.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox