Attached are two new patches: it turned out that an extra wait was 
necessary, otherwise flickering could still occur even though 
INITIALIZE_INPUT would no longer freeze.

Regards,

       Hans

On Saturday 28 July 2007 12:30, Hans Verkuil wrote:
> Hi all,
>
> There have been various bug reports lately regarding freezing of the
> PC when starting a capture or when changing channels.
>
> I've been stress testing this yesterday and today and I believe I
> have found and fixed the problem. And as an additional bonus I
> believe that this patch also fixes the bug that sometimes occurs
> where the top third of the captured screen is continuously
> flickering.
>
> I've attached two patches: ivtv-0.10.diff is against ivtv-0.10 and
> ivtv.diff is against the http://www.linuxtv.org/hg/~hverkuil/v4l-dvb
> repository (for kernels >= 2.6.22).
>
> These patches also make an important change in the behavior of the
> driver: if a capture is in progress, then it is no longer possible to
> change inputs or open the radio device. EBUSY is returned as an
> error.
>
> The underlying problem was the use of the
> CX2341X_ENC_INITIALIZE_INPUT firmware call. This call should be made
> whenever the digitizer (saa7115 or cx25840) has changed, either
> because the TV standard was changed, another input was chosen or the
> video format changes (e.g. capture size, VBI settings). But it turned
> out that the digitizer has to be turned off before calling this API
> and turned on afterwards. This is definitely the case for the
> saa7115, the cx25840 seems to be more forgiving.
>
> If the digitizer is NOT turned off, then this FW call can sometimes
> freeze your PC: it looks like the MPEG card crashes and freezes the
> PCI bus. Any PCI access simply freezes everything.
>
> The problem was that CX2341X_ENC_INITIALIZE_INPUT was called on every
> channel change, even though there was no need to call it at that
> time. So this call was removed.
>
> The CX2341X_ENC_INITIALIZE_INPUT was also called on the start of a
> capture and ensures that the MPEG encoder has the correct digitizer
> settings. If this is not called, then flickering may occur.
>
> Opening the radio device or changing input also requires a call to
> CX2341X_ENC_INITIALIZE_INPUT. However, testing showed that this call
> doesn't do anything when a capture is in progress, hence the new
> requirement that the radio device or changing inputs can only be done
> when no capture is running. Otherwise, changing inputs in midstream
> can cause flickering.
>
> While running a stress test app I also noticed that when recordings
> are stopped and started in quick succession the start of the capture
> can sometimes be garbled. It is actually a left-over from the
> previous capture. It turns out that stopping the capture needs to
> wait a bit (100 ms is enough) to make sure the last pending
> interrupts are handled. This actually makes for simpler code and
> works very well.
>
> Please test this patch, whether or not you have these problems. I'd
> like to get some feedback on this!
>
> Thanks,
>
>        Hans
>
> The CX2341X_ENC_INITIALIZE_INPUT firmware call is very important
Index: ivtv-ioctl.c
===================================================================
--- ivtv-ioctl.c	(revision 3935)
+++ ivtv-ioctl.c	(working copy)
@@ -784,6 +784,9 @@
 			IVTV_DEBUG_INFO("Input unchanged\n");
 			break;
 		}
+		if (atomic_read(&itv->capturing) > 0) {
+			return -EBUSY;
+		}
 		IVTV_DEBUG_INFO("Changing input from %d to %d\n",
 			       	itv->active_input, inp);
 
Index: ivtv-streams.c
===================================================================
--- ivtv-streams.c	(revision 3935)
+++ ivtv-streams.c	(working copy)
@@ -557,9 +557,10 @@
         	clear_bit(IVTV_F_I_EOS, &itv->i_flags);
 
 		/* Initialize Digitizer for Capture */
+		itv->video_dec_func(itv, VIDIOC_STREAMOFF, 0);
+		ivtv_sleep_timeout(HZ / 20, 1);
                 ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
-
-        	ivtv_sleep_timeout(HZ / 10, 0);
+		itv->video_dec_func(itv, VIDIOC_STREAMON, 0);
         }
 
 	/* begin_capture */
@@ -723,7 +724,6 @@
 	int cap_type;
 	unsigned long then;
 	int stopmode;
-	u32 data[CX2341X_MBOX_MAX_DATA];
 
 	if (s->v4l2dev == NULL)
 		return -EINVAL;
@@ -802,29 +802,9 @@
 		}
 
 		then = jiffies;
-		/* Make sure DMA is complete */
-		add_wait_queue(&s->waitq, &wait);
-		set_current_state(TASK_INTERRUPTIBLE);
-		do {
-			/* check if DMA is pending */
-			if ((s->type == IVTV_ENC_STREAM_TYPE_MPG) &&	/* MPG Only */
-			    (read_reg(IVTV_REG_DMASTATUS) & 0x02)) {
-				/* Check for last DMA */
-				ivtv_vapi_result(itv, data, CX2341X_ENC_GET_SEQ_END, 2, 0, 0);
 
-				if (data[0] == 1) {
-					IVTV_DEBUG_DMA("%s: Last DMA of size 0x%08x\n", s->name, data[1]);
-					break;
-				}
-			} else if (read_reg(IVTV_REG_DMASTATUS) & 0x02) {
-				break;
-			}
-
-			ivtv_sleep_timeout(HZ / 100, 1);
-		} while (then + HZ * 2 > jiffies);
-
-		set_current_state(TASK_RUNNING);
-		remove_wait_queue(&s->waitq, &wait);
+		/* Handle any pending interrupts */
+		ivtv_sleep_timeout(HZ / 10, 1);
 	}
 
 	atomic_dec(&itv->capturing);
Index: ivtv-fileops.c
===================================================================
--- ivtv-fileops.c	(revision 3935)
+++ ivtv-fileops.c	(working copy)
@@ -816,12 +816,20 @@
 			return -EBUSY;
 		}
 
+		if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
+			if (atomic_read(&itv->capturing) > 0) {
+				/* switching to radio while capture is 
+				   in progress is not polite */
+				kfree(item);
+				return -EBUSY;
+			}
+		}
+		/* Mark that the radio is being used. */
+		set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
 		/* We have the radio */
 		ivtv_mute(itv);
 		/* Switch tuner to radio */
 		ivtv_call_i2c_clients(itv, AUDC_SET_RADIO, NULL);
-		/* Mark that the radio is being used. */
-		set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
 		/* Select the correct audio input (i.e. radio tuner) */
 		ivtv_audio_set_io(itv);
 		if (itv->hw_flags & IVTV_HW_SAA711X)
@@ -863,13 +871,8 @@
 {
 	struct v4l2_control ctrl = { V4L2_CID_AUDIO_MUTE, 0 };
 
-        /* initialize or refresh input */
-        if (atomic_read(&itv->capturing) == 0)
-                ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
-
-	ivtv_sleep_timeout(HZ / 10, 0);
-
 	if (atomic_read(&itv->capturing)) {
+		ivtv_sleep_timeout(HZ / 10, 0);
 		ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12);
 		ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 0);
 	}
diff -r c392ac29add0 linux/drivers/media/video/ivtv/ivtv-fileops.c
--- a/linux/drivers/media/video/ivtv/ivtv-fileops.c	Wed Jul 25 23:02:03 2007 +0200
+++ b/linux/drivers/media/video/ivtv/ivtv-fileops.c	Sat Jul 28 13:18:59 2007 +0200
@@ -888,12 +888,20 @@ int ivtv_v4l2_open(struct inode *inode, 
 			return -EBUSY;
 		}
 
+		if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
+			if (atomic_read(&itv->capturing) > 0) {
+				/* switching to radio while capture is 
+				   in progress is not polite */
+				kfree(item);
+				return -EBUSY;
+			}
+		}
+		/* Mark that the radio is being used. */
+		set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
 		/* We have the radio */
 		ivtv_mute(itv);
 		/* Switch tuner to radio */
 		ivtv_call_i2c_clients(itv, AUDC_SET_RADIO, NULL);
-		/* Mark that the radio is being used. */
-		set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
 		/* Select the correct audio input (i.e. radio tuner) */
 		ivtv_audio_set_io(itv);
 		if (itv->hw_flags & IVTV_HW_SAA711X)
@@ -935,13 +943,8 @@ void ivtv_unmute(struct ivtv *itv)
 {
 	struct v4l2_control ctrl = { V4L2_CID_AUDIO_MUTE, 0 };
 
-	/* initialize or refresh input */
-	if (atomic_read(&itv->capturing) == 0)
-		ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
-
-	ivtv_msleep_timeout(100, 0);
-
 	if (atomic_read(&itv->capturing)) {
+		ivtv_msleep_timeout(100, 0);
 		ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12);
 		ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 0);
 	}
diff -r c392ac29add0 linux/drivers/media/video/ivtv/ivtv-ioctl.c
--- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c	Wed Jul 25 23:02:03 2007 +0200
+++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c	Sat Jul 28 13:18:59 2007 +0200
@@ -903,6 +903,9 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, s
 		if (inp == itv->active_input) {
 			IVTV_DEBUG_INFO("Input unchanged\n");
 			break;
+		}
+		if (atomic_read(&itv->capturing) > 0) {
+			return -EBUSY;
 		}
 		IVTV_DEBUG_INFO("Changing input from %d to %d\n",
 				itv->active_input, inp);
diff -r c392ac29add0 linux/drivers/media/video/ivtv/ivtv-streams.c
--- a/linux/drivers/media/video/ivtv/ivtv-streams.c	Wed Jul 25 23:02:03 2007 +0200
+++ b/linux/drivers/media/video/ivtv/ivtv-streams.c	Sat Jul 28 13:18:59 2007 +0200
@@ -554,9 +554,10 @@ int ivtv_start_v4l2_encode_stream(struct
 		clear_bit(IVTV_F_I_EOS, &itv->i_flags);
 
 		/* Initialize Digitizer for Capture */
+		itv->video_dec_func(itv, VIDIOC_STREAMOFF, 0);
+		ivtv_msleep_timeout(50, 1);
 		ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
-
-		ivtv_msleep_timeout(100, 0);
+		itv->video_dec_func(itv, VIDIOC_STREAMON, 0);
 	}
 
 	/* begin_capture */
@@ -713,7 +714,6 @@ int ivtv_stop_v4l2_encode_stream(struct 
 	int cap_type;
 	unsigned long then;
 	int stopmode;
-	u32 data[CX2341X_MBOX_MAX_DATA];
 
 	if (s->v4l2dev == NULL)
 		return -EINVAL;
@@ -793,27 +793,9 @@ int ivtv_stop_v4l2_encode_stream(struct 
 		}
 
 		then = jiffies;
-		/* Make sure DMA is complete */
-		add_wait_queue(&s->waitq, &wait);
-		do {
-			/* check if DMA is pending */
-			if ((s->type == IVTV_ENC_STREAM_TYPE_MPG) &&	/* MPG Only */
-			    (read_reg(IVTV_REG_DMASTATUS) & 0x02)) {
-				/* Check for last DMA */
-				ivtv_vapi_result(itv, data, CX2341X_ENC_GET_SEQ_END, 2, 0, 0);
-
-				if (data[0] == 1) {
-					IVTV_DEBUG_DMA("%s: Last DMA of size 0x%08x\n", s->name, data[1]);
-					break;
-				}
-			} else if (read_reg(IVTV_REG_DMASTATUS) & 0x02) {
-				break;
-			}
-		} while (!ivtv_msleep_timeout(10, 1) &&
-			 then + msecs_to_jiffies(2000) > jiffies);
-
-		set_current_state(TASK_RUNNING);
-		remove_wait_queue(&s->waitq, &wait);
+
+		/* Handle any pending interrupts */
+		ivtv_msleep_timeout(100, 1);
 	}
 
 	atomic_dec(&itv->capturing);
_______________________________________________
ivtv-devel mailing list
[email protected]
http://ivtvdriver.org/mailman/listinfo/ivtv-devel

Reply via email to