[PATCH 3/9] staging/easycap: Improve hardware initialization

Mike Thomas rmthomas at sciolus.org
Sun Nov 7 20:00:35 UTC 2010


Sometimes at startup the video urbs consistently and persistently deliver
bad data, each video frame (not isoc frame) containing an excess of
precisely two bytes.  A brute-force cure implemented here is to
repeatedly reinitialize the registers of the SAA7113H chip and the
STK1160 USB bridge until good behaviour is obtained.

Signed-off-by: Mike Thomas <rmthomas at sciolus.org>
---
 drivers/staging/easycap/easycap.h       |   47 ++-
 drivers/staging/easycap/easycap_ioctl.c |  361 ++++++++++-----
 drivers/staging/easycap/easycap_low.c   |  675 ++++++++++++++++----------
 drivers/staging/easycap/easycap_main.c  |  786 +++++++++++++++++++++++++------
 drivers/staging/easycap/easycap_sound.c |   20 +-
 5 files changed, 1345 insertions(+), 544 deletions(-)

diff --git a/drivers/staging/easycap/easycap.h b/drivers/staging/easycap/easycap.h
index 11ceda7..20e51dd 100644
--- a/drivers/staging/easycap/easycap.h
+++ b/drivers/staging/easycap/easycap.h
@@ -44,10 +44,17 @@
 
 /*---------------------------------------------------------------------------*/
 /*
+ *  THESE ARE NORMALLY DEFINED
+ */
+/*---------------------------------------------------------------------------*/
+#define  PATIENCE  500
+#undef   PREFER_NTSC
+#define  PERSEVERE
+/*---------------------------------------------------------------------------*/
+/*
  *  THESE ARE FOR MAINTENANCE ONLY - NORMALLY UNDEFINED:
  */
 /*---------------------------------------------------------------------------*/
-#undef  PREFER_NTSC
 #undef  EASYCAP_TESTCARD
 #undef  EASYCAP_TESTTONE
 #undef  NOREADBACK
@@ -122,7 +129,7 @@
 
 #define USB_SKEL_MINOR_BASE     192
 #define DONGLE_MANY 8
-
+#define INPUT_MANY 6
 /*---------------------------------------------------------------------------*/
 /*
  *  DEFAULT LUMINANCE, CONTRAST, SATURATION AND HUE
@@ -146,6 +153,7 @@
 #if (USB_2_0_MAXPACKETSIZE > PAGE_SIZE)
 #error video_isoc_buffer[.] will not be big enough
 #endif
+#define VIDEO_JUNK_TOLERATE VIDEO_ISOC_BUFFER_MANY
 /*---------------------------------------------------------------------------*/
 /*
  *  VIDEO BUFFERS
@@ -238,6 +246,7 @@ struct list_head list_head;
 void *pgo;
 void *pto;
 __u16 kount;
+__u16 input;
 };
 /*---------------------------------------------------------------------------*/
 struct data_urb {
@@ -256,6 +265,22 @@ __u16 mask;
 char name[128];
 struct v4l2_format v4l2_format;
 };
+struct inputset {
+int input;
+int input_ok;
+int standard_offset;
+int standard_offset_ok;
+int format_offset;
+int format_offset_ok;
+int brightness;
+int brightness_ok;
+int contrast;
+int contrast_ok;
+int saturation;
+int saturation_ok;
+int hue;
+int hue_ok;
+};
 /*---------------------------------------------------------------------------*/
 /*
  *   easycap.ilk == 0   =>  CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=256
@@ -274,7 +299,7 @@ struct v4l2_device v4l2_device;
 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-
+int status;
 unsigned int audio_pages_per_fragment;
 unsigned int audio_bytes_per_fragment;
 unsigned int audio_buffer_page_many;
@@ -302,7 +327,9 @@ int input;
 int polled;
 int standard_offset;
 int format_offset;
+struct inputset inputset[INPUT_MANY];
 
+bool ntsc;
 int fps;
 int usec;
 int tolerate;
@@ -480,6 +507,8 @@ int              redaub(struct easycap *, void *, void *, \
 						int, int, __u8, __u8, bool);
 void             easycap_testcard(struct easycap *, int);
 int              fillin_formats(void);
+int              reset(struct easycap *);
+int              newinput(struct easycap *, int);
 int              adjust_standard(struct easycap *, v4l2_std_id);
 int              adjust_format(struct easycap *, __u32, __u32, __u32, \
 								int, bool);
@@ -517,11 +546,11 @@ int              wakeup_device(struct usb_device *);
 int              confirm_resolution(struct usb_device *);
 int              confirm_stream(struct usb_device *);
 
-int              setup_stk(struct usb_device *);
-int              setup_saa(struct usb_device *);
+int              setup_stk(struct usb_device *, bool);
+int              setup_saa(struct usb_device *, bool);
 int              setup_vt(struct usb_device *);
-int              check_stk(struct usb_device *);
-int              check_saa(struct usb_device *);
+int              check_stk(struct usb_device *, bool);
+int              check_saa(struct usb_device *, bool);
 int              ready_saa(struct usb_device *);
 int              merit_saa(struct usb_device *);
 int              check_vt(struct usb_device *);
@@ -539,10 +568,6 @@ int              stop_100(struct usb_device *);
 int              write_300(struct usb_device *);
 int              read_vt(struct usb_device *, __u16);
 int              write_vt(struct usb_device *, __u16, __u16);
-
-int              set2to78(struct usb_device *);
-int              set2to93(struct usb_device *);
-
 int              regset(struct usb_device *, __u16, __u16);
 int              regget(struct usb_device *, __u16, void *);
 int		isdongle(struct easycap *);
diff --git a/drivers/staging/easycap/easycap_ioctl.c b/drivers/staging/easycap/easycap_ioctl.c
index d91d64a..0ed37c2 100644
--- a/drivers/staging/easycap/easycap_ioctl.c
+++ b/drivers/staging/easycap/easycap_ioctl.c
@@ -36,6 +36,7 @@
  *  UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE
  *  FOLLOWING:
  *          peasycap->standard_offset
+ *          peasycap->inputset[peasycap->input].standard_offset
  *          peasycap->fps
  *          peasycap->usec
  *          peasycap->tolerate
@@ -45,8 +46,9 @@ int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
 {
 struct easycap_standard const *peasycap_standard;
 __u16 reg, set;
-int ir, rc, need;
+int ir, rc, need, k;
 unsigned int itwas, isnow;
+bool resubmit;
 
 if (NULL == peasycap) {
 	SAY("ERROR: peasycap is NULL\n");
@@ -67,7 +69,7 @@ if (0xFFFF == peasycap_standard->mask) {
 							(unsigned int)std_id);
 	return -EINVAL;
 }
-SAM("user requests standard: %s\n", \
+SAM("selected standard: %s\n", \
 			&(peasycap_standard->v4l2_standard.name[0]));
 if (peasycap->standard_offset == \
 			(int)(peasycap_standard - &easycap_standard[0])) {
@@ -75,18 +77,43 @@ if (peasycap->standard_offset == \
 	return 0;
 }
 peasycap->standard_offset = (int)(peasycap_standard - &easycap_standard[0]);
+for (k = 0; k < INPUT_MANY;  k++) {
+	if (!peasycap->inputset[k].standard_offset_ok) {
+			peasycap->inputset[k].standard_offset = \
+						peasycap->standard_offset;
+	}
+}
+if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+	peasycap->inputset[peasycap->input].standard_offset = \
+						peasycap->standard_offset;
+	peasycap->inputset[peasycap->input].standard_offset_ok = 1;
+} else
+	JOM(8, "%i=peasycap->input\n", peasycap->input);
 peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator / \
 		peasycap_standard->v4l2_standard.frameperiod.numerator;
-if (!peasycap->fps) {
-	SAM("MISTAKE: frames-per-second is zero\n");
-	return -EFAULT;
+switch (peasycap->fps) {
+case 30: {
+	peasycap->ntsc = true;
+	break;
+}
+case 25: {
+	peasycap->ntsc = false;
+	break;
+}
+default: {
+	SAM("MISTAKE: %i=frames-per-second\n", peasycap->fps);
+	return -ENOENT;
+}
 }
 JOM(8, "%i frames-per-second\n", peasycap->fps);
 peasycap->usec = 1000000 / (2 * peasycap->fps);
 peasycap->tolerate = 1000 * (25 / peasycap->fps);
 
-kill_video_urbs(peasycap);
-
+if (peasycap->video_isoc_streaming) {
+	resubmit = true;
+	kill_video_urbs(peasycap);
+} else
+	resubmit = false;
 /*--------------------------------------------------------------------------*/
 /*
  *  SAA7113H DATASHEET PAGE 44, TABLE 42
@@ -101,11 +128,6 @@ case NTSC_M_JP: {
 		SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
 	else
 		itwas = (unsigned int)ir;
-
-
-	set2to78(peasycap->pusb_device);
-
-
 	rc = write_saa(peasycap->pusb_device, reg, set);
 	if (0 != rc)
 		SAM("ERROR: failed to set SAA register " \
@@ -118,9 +140,6 @@ case NTSC_M_JP: {
 		else
 			JOM(8, "SAA register 0x%02X changed " \
 				"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
-
-		set2to78(peasycap->pusb_device);
-
 	}
 
 	reg = 0x0B;  set = 0x48;
@@ -129,9 +148,6 @@ case NTSC_M_JP: {
 		SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
 	else
 		itwas = (unsigned int)ir;
-
-	set2to78(peasycap->pusb_device);
-
 	rc = write_saa(peasycap->pusb_device, reg, set);
 	if (0 != rc)
 		SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X " \
@@ -144,9 +160,6 @@ case NTSC_M_JP: {
 		else
 			JOM(8, "SAA register 0x%02X changed " \
 				"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
-
-		set2to78(peasycap->pusb_device);
-
 	}
 /*--------------------------------------------------------------------------*/
 /*
@@ -183,9 +196,6 @@ if (need) {
 		SAM("ERROR: failed to read SAA register 0x%02X\n", reg);
 	else
 		itwas = (unsigned int)ir;
-
-	set2to78(peasycap->pusb_device);
-
 	rc = write_saa(peasycap->pusb_device, reg, set);
 	if (0 != write_saa(peasycap->pusb_device, reg, set)) {
 		SAM("ERROR: failed to set SAA register " \
@@ -216,19 +226,18 @@ else {
 		set = itwas | 0x40 ;
 	else
 		set = itwas & ~0x40 ;
-
-set2to78(peasycap->pusb_device);
-
-rc  = write_saa(peasycap->pusb_device, reg, set);
-if (0 != rc)
-	SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", reg, set);
-else {
-	isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
-	if (0 > ir)
-		JOM(8, "SAA register 0x%02X changed to 0x%02X\n", reg, isnow);
-	else
-		JOM(8, "SAA register 0x%02X changed " \
-			"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
+	rc  = write_saa(peasycap->pusb_device, reg, set);
+	if (0 != rc)
+		SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
+								reg, set);
+	else {
+		isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
+		if (0 > ir)
+			JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
+								reg, isnow);
+		else
+			JOM(8, "SAA register 0x%02X changed " \
+				"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 	}
 }
 /*--------------------------------------------------------------------------*/
@@ -247,19 +256,18 @@ else {
 		set = itwas | 0x80 ;
 	else
 		set = itwas & ~0x80 ;
-
-set2to78(peasycap->pusb_device);
-
-rc = write_saa(peasycap->pusb_device, reg, set);
-if (0 != rc)
-	SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", reg, set);
-else {
-	isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
-	if (0 > ir)
-		JOM(8, "SAA register 0x%02X changed to 0x%02X\n", reg, isnow);
-	else
-		JOM(8, "SAA register 0x%02X changed " \
-			"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
+	rc = write_saa(peasycap->pusb_device, reg, set);
+	if (0 != rc)
+		SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
+								reg, set);
+	else {
+		isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
+		if (0 > ir)
+			JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
+								reg, isnow);
+		else
+			JOM(8, "SAA register 0x%02X changed " \
+				"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 	}
 }
 /*--------------------------------------------------------------------------*/
@@ -276,9 +284,6 @@ if (0 > ir)
 		set = 0x0A ;
 	else
 		set = 0x07 ;
-
-	set2to78(peasycap->pusb_device);
-
 	if (0 != write_saa(peasycap->pusb_device, reg, set))
 		SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
 								reg, set);
@@ -291,18 +296,20 @@ if (0 > ir)
 			JOM(8, "SAA register 0x%02X changed "
 				"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 	}
-	if (0 != check_saa(peasycap->pusb_device))
-		SAM("ERROR: check_saa() failed\n");
+if (true == resubmit)
+	submit_video_urbs(peasycap);
 return 0;
 }
 /*****************************************************************************/
 /*--------------------------------------------------------------------------*/
 /*
- *  THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL DEPENDS ON THE
- *  CURRENT VALUE OF peasycap->standard_offset.
+ *  THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL REQUIRES
+ *  A VALID VALUE OF peasycap->standard_offset, OTHERWISE -EBUSY IS RETURNED.
+ *
  *  PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN
  *  THIS ROUTINE UPDATES THE FOLLOWING:
  *          peasycap->format_offset
+ *          peasycap->inputset[peasycap->input].format_offset
  *          peasycap->pixelformat
  *          peasycap->field
  *          peasycap->height
@@ -325,14 +332,19 @@ int adjust_format(struct easycap *peasycap, \
 struct easycap_format *peasycap_format, *peasycap_best_format;
 __u16 mask;
 struct usb_device *p;
-int miss, multiplier, best;
+int miss, multiplier, best, k;
 char bf[5], *pc;
 __u32 uc;
+bool resubmit;
 
 if (NULL == peasycap) {
 	SAY("ERROR: peasycap is NULL\n");
 	return -EFAULT;
 }
+if (0 > peasycap->standard_offset) {
+	JOM(8, "%i=peasycap->standard_offset\n", peasycap->standard_offset);
+	return -EBUSY;
+}
 p = peasycap->pusb_device;
 if ((struct usb_device *)NULL == p) {
 	SAM("ERROR: peaycap->pusb_device is NULL\n");
@@ -422,6 +434,23 @@ peasycap->width         = peasycap_format->v4l2_format.fmt.pix.width;
 peasycap->pixelformat   = peasycap_format->v4l2_format.fmt.pix.pixelformat;
 peasycap->field         = peasycap_format->v4l2_format.fmt.pix.field;
 peasycap->format_offset = (int)(peasycap_format - &easycap_format[0]);
+
+
+for (k = 0; k < INPUT_MANY; k++) {
+	if (!peasycap->inputset[k].format_offset_ok) {
+		peasycap->inputset[k].format_offset = \
+						peasycap->format_offset;
+	}
+}
+if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+	peasycap->inputset[peasycap->input].format_offset = \
+						peasycap->format_offset;
+	peasycap->inputset[peasycap->input].format_offset_ok = 1;
+} else
+	JOM(8, "%i=peasycap->input\n", peasycap->input);
+
+
+
 peasycap->bytesperpixel = (0x00F0 & peasycap_format->mask) >> 4 ;
 if (0x0100 & peasycap_format->mask)
 	peasycap->byteswaporder = true;
@@ -461,9 +490,11 @@ if (true == peasycap->offerfields) {
 
 
 }
-
-kill_video_urbs(peasycap);
-
+if (peasycap->video_isoc_streaming) {
+	resubmit = true;
+	kill_video_urbs(peasycap);
+} else
+	resubmit = false;
 /*---------------------------------------------------------------------------*/
 /*
  *  PAL
@@ -536,16 +567,15 @@ if (0 == (0x01 & peasycap_format->mask)) {
 	}
 }
 /*---------------------------------------------------------------------------*/
-
-check_stk(peasycap->pusb_device);
-
+if (true == resubmit)
+	submit_video_urbs(peasycap);
 return (int)(peasycap_best_format - &easycap_format[0]);
 }
 /*****************************************************************************/
 int adjust_brightness(struct easycap *peasycap, int value)
 {
 unsigned int mood;
-int i1;
+int i1, k;
 
 if (NULL == peasycap) {
 	SAY("ERROR: peasycap is NULL\n");
@@ -561,11 +591,29 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
 		if ((easycap_control[i1].minimum > value) || \
 					(easycap_control[i1].maximum < value))
 			value = easycap_control[i1].default_value;
+
+		if ((easycap_control[i1].minimum <= peasycap->brightness) && \
+					(easycap_control[i1].maximum >= \
+						peasycap->brightness)) {
+			if (peasycap->brightness == value) {
+				SAM("unchanged brightness at  0x%02X\n", \
+								value);
+				return 0;
+			}
+		}
 		peasycap->brightness = value;
+		for (k = 0; k < INPUT_MANY; k++) {
+			if (!peasycap->inputset[k].brightness_ok)
+				peasycap->inputset[k].brightness = \
+							peasycap->brightness;
+		}
+		if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+			peasycap->inputset[peasycap->input].brightness = \
+							peasycap->brightness;
+			peasycap->inputset[peasycap->input].brightness_ok = 1;
+		} else
+			JOM(8, "%i=peasycap->input\n", peasycap->input);
 		mood = 0x00FF & (unsigned int)peasycap->brightness;
-
-		set2to78(peasycap->pusb_device);
-
 		if (!write_saa(peasycap->pusb_device, 0x0A, mood)) {
 			SAM("adjusting brightness to  0x%02X\n", mood);
 			return 0;
@@ -574,9 +622,6 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
 							"to 0x%02X\n", mood);
 			return -ENOENT;
 		}
-
-		set2to78(peasycap->pusb_device);
-
 		break;
 	}
 	i1++;
@@ -588,7 +633,7 @@ return -ENOENT;
 int adjust_contrast(struct easycap *peasycap, int value)
 {
 unsigned int mood;
-int i1;
+int i1, k;
 
 if (NULL == peasycap) {
 	SAY("ERROR: peasycap is NULL\n");
@@ -604,11 +649,31 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
 		if ((easycap_control[i1].minimum > value) || \
 					(easycap_control[i1].maximum < value))
 			value = easycap_control[i1].default_value;
-		peasycap->contrast = value;
-		mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
 
-		set2to78(peasycap->pusb_device);
 
+
+		if ((easycap_control[i1].minimum <= peasycap->contrast) && \
+				(easycap_control[i1].maximum >= \
+							peasycap->contrast)) {
+			if (peasycap->contrast == value) {
+				SAM("unchanged contrast at  0x%02X\n", value);
+				return 0;
+			}
+		}
+		peasycap->contrast = value;
+		for (k = 0; k < INPUT_MANY; k++) {
+			if (!peasycap->inputset[k].contrast_ok) {
+				peasycap->inputset[k].contrast = \
+							peasycap->contrast;
+			}
+		}
+		if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+			peasycap->inputset[peasycap->input].contrast = \
+							peasycap->contrast;
+			peasycap->inputset[peasycap->input].contrast_ok = 1;
+		} else
+			JOM(8, "%i=peasycap->input\n", peasycap->input);
+		mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
 		if (!write_saa(peasycap->pusb_device, 0x0B, mood)) {
 			SAM("adjusting contrast to  0x%02X\n", mood);
 			return 0;
@@ -617,9 +682,6 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
 							"0x%02X\n", mood);
 			return -ENOENT;
 		}
-
-		set2to78(peasycap->pusb_device);
-
 		break;
 	}
 	i1++;
@@ -631,7 +693,7 @@ return -ENOENT;
 int adjust_saturation(struct easycap *peasycap, int value)
 {
 unsigned int mood;
-int i1;
+int i1, k;
 
 if (NULL == peasycap) {
 	SAY("ERROR: peasycap is NULL\n");
@@ -647,11 +709,31 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
 		if ((easycap_control[i1].minimum > value) || \
 					(easycap_control[i1].maximum < value))
 			value = easycap_control[i1].default_value;
-		peasycap->saturation = value;
-		mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
 
-		set2to78(peasycap->pusb_device);
 
+		if ((easycap_control[i1].minimum <= peasycap->saturation) && \
+					(easycap_control[i1].maximum >= \
+						peasycap->saturation)) {
+			if (peasycap->saturation == value) {
+				SAM("unchanged saturation at  0x%02X\n", \
+								value);
+				return 0;
+			}
+		}
+		peasycap->saturation = value;
+		for (k = 0; k < INPUT_MANY; k++) {
+			if (!peasycap->inputset[k].saturation_ok) {
+				peasycap->inputset[k].saturation = \
+							peasycap->saturation;
+			}
+		}
+		if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+			peasycap->inputset[peasycap->input].saturation = \
+							peasycap->saturation;
+			peasycap->inputset[peasycap->input].saturation_ok = 1;
+		} else
+			JOM(8, "%i=peasycap->input\n", peasycap->input);
+		mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
 		if (!write_saa(peasycap->pusb_device, 0x0C, mood)) {
 			SAM("adjusting saturation to  0x%02X\n", mood);
 			return 0;
@@ -661,9 +743,6 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
 			return -ENOENT;
 		}
 		break;
-
-		set2to78(peasycap->pusb_device);
-
 	}
 	i1++;
 }
@@ -674,7 +753,7 @@ return -ENOENT;
 int adjust_hue(struct easycap *peasycap, int value)
 {
 unsigned int mood;
-int i1, i2;
+int i1, i2, k;
 
 if (NULL == peasycap) {
 	SAY("ERROR: peasycap is NULL\n");
@@ -690,12 +769,28 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
 		if ((easycap_control[i1].minimum > value) || \
 					(easycap_control[i1].maximum < value))
 			value = easycap_control[i1].default_value;
+
+		if ((easycap_control[i1].minimum <= peasycap->hue) && \
+					(easycap_control[i1].maximum >= \
+							peasycap->hue)) {
+			if (peasycap->hue == value) {
+				SAM("unchanged hue at  0x%02X\n", value);
+				return 0;
+			}
+		}
 		peasycap->hue = value;
+		for (k = 0; k < INPUT_MANY; k++) {
+			if (!peasycap->inputset[k].hue_ok)
+				peasycap->inputset[k].hue = peasycap->hue;
+		}
+		if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+			peasycap->inputset[peasycap->input].hue = \
+							peasycap->hue;
+			peasycap->inputset[peasycap->input].hue_ok = 1;
+		} else
+			JOM(8, "%i=peasycap->input\n", peasycap->input);
 		i2 = peasycap->hue - 128;
 		mood = 0x00FF & ((int) i2);
-
-		set2to78(peasycap->pusb_device);
-
 		if (!write_saa(peasycap->pusb_device, 0x0D, mood)) {
 			SAM("adjusting hue to  0x%02X\n", mood);
 			return 0;
@@ -703,9 +798,6 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
 			SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
 			return -ENOENT;
 		}
-
-		set2to78(peasycap->pusb_device);
-
 		break;
 	}
 	i1++;
@@ -1004,6 +1096,7 @@ case VIDIOC_G_INPUT: {
 case VIDIOC_S_INPUT:
 	{
 	__u32 index;
+	int rc;
 
 	JOM(8, "VIDIOC_S_INPUT\n");
 
@@ -1017,14 +1110,18 @@ case VIDIOC_S_INPUT:
 		break;
 	}
 
-	if ((0 > index) || (5 < index)) {
+	if ((0 > index) || (INPUT_MANY <= index)) {
 		JOM(8, "ERROR:  bad requested input: %i\n", index);
 		return -EINVAL;
 	}
-	peasycap->input = (int)index;
-
-	select_input(peasycap->pusb_device, peasycap->input, 9);
 
+	rc = newinput(peasycap, (int)index);
+	if (0 == rc) {
+		JOM(8, "newinput(.,%i) OK\n", (int)index);
+	} else {
+		SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
+		return -EFAULT;
+	}
 	break;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
@@ -1351,6 +1448,8 @@ case VIDIOC_S_FMT: {
 					v4l2_format.fmt.pix.field, \
 					try);
 	if (0 > best_format) {
+		if (-EBUSY == best_format)
+			return -EBUSY;
 		JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
 		return -ENOENT;
 	}
@@ -1472,6 +1571,12 @@ case VIDIOC_G_STD: {
 
 	JOM(8, "VIDIOC_G_STD\n");
 
+	if (0 > peasycap->standard_offset) {
+		JOM(8, "%i=peasycap->standard_offset\n", \
+					peasycap->standard_offset);
+		return -EBUSY;
+	}
+
 	if (0 != copy_from_user(&std_id, (void __user *)arg, \
 						sizeof(v4l2_std_id)))
 		return -EFAULT;
@@ -1549,9 +1654,9 @@ case VIDIOC_QUERYBUF: {
 	JOM(8, "VIDIOC_QUERYBUF\n");
 
 	if (peasycap->video_eof) {
-		JOM(8, "returning -1 because  %i=video_eof\n", \
+		JOM(8, "returning -EIO because  %i=video_eof\n", \
 							peasycap->video_eof);
-		return -1;
+		return -EIO;
 	}
 
 	if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
@@ -1632,12 +1737,14 @@ case VIDIOC_DQBUF:
 	struct signed_div_result sdr;
 	long long int above, below, dnbydt, fudge, sll;
 	unsigned long long int ull;
-	struct timeval timeval0;
+	struct timeval timeval8;
 	struct timeval timeval1;
 #endif /*AUDIOTIME*/
 	struct timeval timeval, timeval2;
 	int i, j;
 	struct v4l2_buffer v4l2_buffer;
+	int rcdq;
+	__u16 input;
 
 	JOM(8, "VIDIOC_DQBUF\n");
 
@@ -1668,8 +1775,14 @@ case VIDIOC_DQBUF:
 /*---------------------------------------------------------------------------*/
 
 	if (!peasycap->polled) {
-		if (-EIO == easycap_dqbuf(peasycap, 0))
-			return -EIO;
+		do {
+			rcdq = easycap_dqbuf(peasycap, 0);
+			if (-EIO == rcdq) {
+				JOM(8, "returning -EIO because " \
+						"dqbuf() returned -EIO\n");
+				return -EIO;
+			}
+		} while (0 != rcdq);
 	} else {
 		if (peasycap->video_eof)
 			return -EIO;
@@ -1708,11 +1821,11 @@ case VIDIOC_DQBUF:
 
 #if defined(AUDIOTIME)
 	if (!peasycap->timeval0.tv_sec) {
-		timeval0 = timeval;
+		timeval8 = timeval;
 		timeval1 = timeval;
 		timeval2 = timeval;
 		dnbydt = 192000;
-		peasycap->timeval0 = timeval0;
+		peasycap->timeval0 = timeval8;
 	} else {
 		dnbydt = peasycap->dnbydt;
 		timeval1 = peasycap->timeval1;
@@ -1766,21 +1879,26 @@ case VIDIOC_DQBUF:
 	JOM(8, "..... user is offered frame buffer %i\n", \
 							peasycap->frame_read);
 	peasycap->frame_lock = 1;
+
+	input = peasycap->frame_buffer[peasycap->frame_read][0].input;
+	if (0x08 & input) {
+		JOM(8, "user is offered frame buffer %i, input %i\n", \
+					peasycap->frame_read, (0x07 & input));
+	} else {
+		JOM(8, "user is offered frame buffer %i\n", \
+							peasycap->frame_read);
+	}
+	peasycap->frame_lock = 1;
+	JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
 	if (peasycap->frame_read == peasycap->frame_fill) {
 		if (peasycap->frame_lock) {
-			JOM(8, "ERROR:  filling frame buffer " \
+			JOM(8, "WORRY:  filling frame buffer " \
 						"while offered to user\n");
 		}
 	}
 	break;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/*---------------------------------------------------------------------------*/
-/*
- *  AUDIO URBS HAVE ALREADY BEEN SUBMITTED WHEN THIS COMMAND IS RECEIVED;
- *  VIDEO URBS HAVE NOT.
- */
-/*---------------------------------------------------------------------------*/
 case VIDIOC_STREAMON: {
 	int i;
 
@@ -1839,6 +1957,20 @@ case VIDIOC_G_PARM: {
 	v4l2_streamparm.parm.capture.capturemode = 0;
 	v4l2_streamparm.parm.capture.timeperframe.numerator = 1;
 	v4l2_streamparm.parm.capture.timeperframe.denominator = 30;
+
+	if (peasycap->fps) {
+		v4l2_streamparm.parm.capture.timeperframe.\
+						denominator = peasycap->fps;
+	} else {
+		if (true == peasycap->ntsc) {
+			v4l2_streamparm.parm.capture.timeperframe.\
+						denominator = 30;
+		} else {
+			v4l2_streamparm.parm.capture.timeperframe.\
+						denominator = 25;
+		}
+	}
+
 	v4l2_streamparm.parm.capture.readbuffers = peasycap->frame_buffer_many;
 	v4l2_streamparm.parm.capture.extendedmode = 0;
 	if (0 != copy_to_user((void __user *)arg, &v4l2_streamparm, \
@@ -2095,6 +2227,15 @@ case SNDCTL_DSP_GETISPACE: {
 		return -EFAULT;
 	break;
 }
+case 0x00005401:
+case 0x00005402:
+case 0x00005403:
+case 0x00005404:
+case 0x00005405:
+case 0x00005406: {
+	JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd);
+	return -ENOIOCTLCMD;
+}
 default: {
 	JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd);
 	return -ENOIOCTLCMD;
diff --git a/drivers/staging/easycap/easycap_low.c b/drivers/staging/easycap/easycap_low.c
index a3be9c1..4badef2 100644
--- a/drivers/staging/easycap/easycap_low.c
+++ b/drivers/staging/easycap/easycap_low.c
@@ -42,121 +42,205 @@
 #include "easycap.h"
 
 /*--------------------------------------------------------------------------*/
-const struct stk1160config { int reg; int set; } stk1160config[256] = {
-	{0x000, 0x0098},
-	{0x002, 0x0093},
-
-	{0x001, 0x0003},
-	{0x003, 0x0080},
-	{0x00D, 0x0000},
-	{0x00F, 0x0002},
-	{0x018, 0x0010},
-	{0x019, 0x0000},
-	{0x01A, 0x0014},
-	{0x01B, 0x000E},
-	{0x01C, 0x0046},
-
-	{0x100, 0x0033},
-	{0x103, 0x0000},
-	{0x104, 0x0000},
-	{0x105, 0x0000},
-	{0x106, 0x0000},
-
-#if defined(PREFER_NTSC)
-
-	{0x110, 0x0014},
-	{0x111, 0x0000},
-	{0x112, 0x0003},
-	{0x113, 0x0000},
-	{0x114, 0x0514},
-	{0x115, 0x0005},
-	{0x116, 0x00F3},
-	{0x117, 0x0000},
-
-#else /* ! PREFER_NTSC*/
-
-	{0x110, 0x0014},
-	{0x111, 0x0000},
-	{0x112, 0x0020},
-	{0x113, 0x0000},
-	{0x114, 0x0514},
-	{0x115, 0x0005},
-	{0x116, 0x0110},
-	{0x117, 0x0001},
-
-#endif /* ! PREFER_NTSC*/
-
-	{0x202, 0x000F},
-	{0x203, 0x004A},
-	{0x2FF, 0x0000},
-/*---------------------------------------------------------------------------*/
-	{0xFFF, 0xFFFF}
-	};
+const struct stk1160config { int reg; int set; } stk1160configPAL[256] = {
+		{0x000, 0x0098},
+		{0x002, 0x0093},
+
+		{0x001, 0x0003},
+		{0x003, 0x0080},
+		{0x00D, 0x0000},
+		{0x00F, 0x0002},
+		{0x018, 0x0010},
+		{0x019, 0x0000},
+		{0x01A, 0x0014},
+		{0x01B, 0x000E},
+		{0x01C, 0x0046},
+
+		{0x100, 0x0033},
+		{0x103, 0x0000},
+		{0x104, 0x0000},
+		{0x105, 0x0000},
+		{0x106, 0x0000},
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/*
+ *  RESOLUTION 640x480
+*/
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+		{0x110, 0x0008},
+		{0x111, 0x0000},
+		{0x112, 0x0020},
+		{0x113, 0x0000},
+		{0x114, 0x0508},
+		{0x115, 0x0005},
+		{0x116, 0x0110},
+		{0x117, 0x0001},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+		{0x202, 0x000F},
+		{0x203, 0x004A},
+		{0x2FF, 0x0000},
+
+		{0xFFF, 0xFFFF}
+};
 /*--------------------------------------------------------------------------*/
-const struct saa7113config { int reg; int set; } saa7113config[256] = {
-	{0x01, 0x08},
-	{0x02, 0x80},
-	{0x03, 0x33},
-	{0x04, 0x00},
-	{0x05, 0x00},
-	{0x06, 0xE9},
-	{0x07, 0x0D},
-#if defined(PREFER_NTSC)
-	{0x08, 0x78},
-#else
-	{0x08, 0x38},
-#endif /* ! PREFER_NTSC*/
-	{0x09, 0x00},
-	{0x0A, SAA_0A_DEFAULT},
-	{0x0B, SAA_0B_DEFAULT},
-	{0x0C, SAA_0C_DEFAULT},
-	{0x0D, SAA_0D_DEFAULT},
-	{0x0E, 0x01},
-	{0x0F, 0x36},
-	{0x10, 0x00},
-	{0x11, 0x0C},
-	{0x12, 0xE7},
-	{0x13, 0x00},
-	{0x15, 0x00},
-	{0x16, 0x00},
-#if defined(PREFER_NTSC)
-	{0x40, 0x82},
+const struct stk1160config stk1160configNTSC[256] = {
+		{0x000, 0x0098},
+		{0x002, 0x0093},
+
+		{0x001, 0x0003},
+		{0x003, 0x0080},
+		{0x00D, 0x0000},
+		{0x00F, 0x0002},
+		{0x018, 0x0010},
+		{0x019, 0x0000},
+		{0x01A, 0x0014},
+		{0x01B, 0x000E},
+		{0x01C, 0x0046},
+
+		{0x100, 0x0033},
+		{0x103, 0x0000},
+		{0x104, 0x0000},
+		{0x105, 0x0000},
+		{0x106, 0x0000},
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/*
+ *  RESOLUTION 640x480
+*/
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+		{0x110, 0x0008},
+		{0x111, 0x0000},
+		{0x112, 0x0003},
+		{0x113, 0x0000},
+		{0x114, 0x0508},
+		{0x115, 0x0005},
+		{0x116, 0x00F3},
+		{0x117, 0x0000},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+		{0x202, 0x000F},
+		{0x203, 0x004A},
+		{0x2FF, 0x0000},
+
+		{0xFFF, 0xFFFF}
+};
+/*--------------------------------------------------------------------------*/
+const struct saa7113config { int reg; int set; } saa7113configPAL[256] = {
+		{0x01, 0x08},
+#if defined(ANTIALIAS)
+		{0x02, 0xC0},
 #else
-	{0x40, 0x02},
-#endif /* ! PREFER_NTSC*/
-	{0x41, 0xFF},
-	{0x42, 0xFF},
-	{0x43, 0xFF},
-	{0x44, 0xFF},
-	{0x45, 0xFF},
-	{0x46, 0xFF},
-	{0x47, 0xFF},
-	{0x48, 0xFF},
-	{0x49, 0xFF},
-	{0x4A, 0xFF},
-	{0x4B, 0xFF},
-	{0x4C, 0xFF},
-	{0x4D, 0xFF},
-	{0x4E, 0xFF},
-	{0x4F, 0xFF},
-	{0x50, 0xFF},
-	{0x51, 0xFF},
-	{0x52, 0xFF},
-	{0x53, 0xFF},
-	{0x54, 0xFF},
-	{0x55, 0xFF},
-	{0x56, 0xFF},
-	{0x57, 0xFF},
-	{0x58, 0x40},
-	{0x59, 0x54},
-#if defined(PREFER_NTSC)
-	{0x5A, 0x0A},
+		{0x02, 0x80},
+#endif /*ANTIALIAS*/
+		{0x03, 0x33},
+		{0x04, 0x00},
+		{0x05, 0x00},
+		{0x06, 0xE9},
+		{0x07, 0x0D},
+		{0x08, 0x38},
+		{0x09, 0x00},
+		{0x0A, SAA_0A_DEFAULT},
+		{0x0B, SAA_0B_DEFAULT},
+		{0x0C, SAA_0C_DEFAULT},
+		{0x0D, SAA_0D_DEFAULT},
+		{0x0E, 0x01},
+		{0x0F, 0x36},
+		{0x10, 0x00},
+		{0x11, 0x0C},
+		{0x12, 0xE7},
+		{0x13, 0x00},
+		{0x15, 0x00},
+		{0x16, 0x00},
+		{0x40, 0x02},
+		{0x41, 0xFF},
+		{0x42, 0xFF},
+		{0x43, 0xFF},
+		{0x44, 0xFF},
+		{0x45, 0xFF},
+		{0x46, 0xFF},
+		{0x47, 0xFF},
+		{0x48, 0xFF},
+		{0x49, 0xFF},
+		{0x4A, 0xFF},
+		{0x4B, 0xFF},
+		{0x4C, 0xFF},
+		{0x4D, 0xFF},
+		{0x4E, 0xFF},
+		{0x4F, 0xFF},
+		{0x50, 0xFF},
+		{0x51, 0xFF},
+		{0x52, 0xFF},
+		{0x53, 0xFF},
+		{0x54, 0xFF},
+		{0x55, 0xFF},
+		{0x56, 0xFF},
+		{0x57, 0xFF},
+		{0x58, 0x40},
+		{0x59, 0x54},
+		{0x5A, 0x07},
+		{0x5B, 0x83},
+
+		{0xFF, 0xFF}
+};
+/*--------------------------------------------------------------------------*/
+const struct saa7113config saa7113configNTSC[256] = {
+		{0x01, 0x08},
+#if defined(ANTIALIAS)
+		{0x02, 0xC0},
 #else
-	{0x5A, 0x07},
-#endif /* ! PREFER_NTSC*/
-	{0x5B, 0x83},
-	{0xFF, 0xFF}
-	};
+		{0x02, 0x80},
+#endif /*ANTIALIAS*/
+		{0x03, 0x33},
+		{0x04, 0x00},
+		{0x05, 0x00},
+		{0x06, 0xE9},
+		{0x07, 0x0D},
+		{0x08, 0x78},
+		{0x09, 0x00},
+		{0x0A, SAA_0A_DEFAULT},
+		{0x0B, SAA_0B_DEFAULT},
+		{0x0C, SAA_0C_DEFAULT},
+		{0x0D, SAA_0D_DEFAULT},
+		{0x0E, 0x01},
+		{0x0F, 0x36},
+		{0x10, 0x00},
+		{0x11, 0x0C},
+		{0x12, 0xE7},
+		{0x13, 0x00},
+		{0x15, 0x00},
+		{0x16, 0x00},
+		{0x40, 0x82},
+		{0x41, 0xFF},
+		{0x42, 0xFF},
+		{0x43, 0xFF},
+		{0x44, 0xFF},
+		{0x45, 0xFF},
+		{0x46, 0xFF},
+		{0x47, 0xFF},
+		{0x48, 0xFF},
+		{0x49, 0xFF},
+		{0x4A, 0xFF},
+		{0x4B, 0xFF},
+		{0x4C, 0xFF},
+		{0x4D, 0xFF},
+		{0x4E, 0xFF},
+		{0x4F, 0xFF},
+		{0x50, 0xFF},
+		{0x51, 0xFF},
+		{0x52, 0xFF},
+		{0x53, 0xFF},
+		{0x54, 0xFF},
+		{0x55, 0xFF},
+		{0x56, 0xFF},
+		{0x57, 0xFF},
+		{0x58, 0x40},
+		{0x59, 0x54},
+		{0x5A, 0x0A},
+		{0x5B, 0x83},
+
+		{0xFF, 0xFF}
+};
 /*--------------------------------------------------------------------------*/
 
 /****************************************************************************/
@@ -213,15 +297,22 @@ return 0;
 }
 /****************************************************************************/
 int
-setup_stk(struct usb_device *p)
+setup_stk(struct usb_device *p, bool ntsc)
 {
 int i0;
 
 i0 = 0;
-while (0xFFF != stk1160config[i0].reg) {
-	SET(p, stk1160config[i0].reg, stk1160config[i0].set);
-	i0++;
+if (true == ntsc) {
+	while (0xFFF != stk1160configNTSC[i0].reg) {
+		SET(p, stk1160configNTSC[i0].reg, stk1160configNTSC[i0].set);
+		i0++;
+	}
+} else {
+	while (0xFFF != stk1160configPAL[i0].reg) {
+		SET(p, stk1160configPAL[i0].reg, stk1160configPAL[i0].set);
+		i0++;
 	}
+}
 
 write_300(p);
 
@@ -229,19 +320,24 @@ return 0;
 }
 /****************************************************************************/
 int
-setup_saa(struct usb_device *p)
+setup_saa(struct usb_device *p, bool ntsc)
 {
 int i0, ir;
 
-
-set2to78(p);
-
-
 i0 = 0;
-while (0xFF != saa7113config[i0].reg) {
-	ir = write_saa(p, saa7113config[i0].reg, saa7113config[i0].set);
-	i0++;
+if (true == ntsc) {
+	while (0xFF != saa7113configNTSC[i0].reg) {
+		ir = write_saa(p, saa7113configNTSC[i0].reg, \
+					saa7113configNTSC[i0].set);
+		i0++;
+	}
+} else {
+	while (0xFF != saa7113configPAL[i0].reg) {
+		ir = write_saa(p, saa7113configPAL[i0].reg, \
+					saa7113configPAL[i0].set);
+		i0++;
 	}
+}
 return 0;
 }
 /****************************************************************************/
@@ -353,24 +449,46 @@ return 0;
  */
 /*--------------------------------------------------------------------------*/
 int
-check_saa(struct usb_device *p)
+check_saa(struct usb_device *p, bool ntsc)
 {
 int i0, ir, rc;
-i0 = 0;
 
+i0 = 0;
 rc = 0;
-while (0xFF != saa7113config[i0].reg) {
-	if (0x0F == saa7113config[i0].reg) {
-		i0++; continue;
+if (true == ntsc) {
+	while (0xFF != saa7113configNTSC[i0].reg) {
+		if (0x0F == saa7113configNTSC[i0].reg) {
+			i0++;
+			continue;
+		}
+
+		ir = read_saa(p, saa7113configNTSC[i0].reg);
+		if (ir != saa7113configNTSC[i0].set) {
+			SAY("SAA register 0x%02X has 0x%02X, " \
+						"expected 0x%02X\n", \
+						saa7113configNTSC[i0].reg, \
+						ir, saa7113configNTSC[i0].set);
+			rc--;
+		}
+		i0++;
 	}
+} else {
+	while (0xFF != saa7113configPAL[i0].reg) {
+		if (0x0F == saa7113configPAL[i0].reg) {
+			i0++;
+			continue;
+		}
 
-	ir = read_saa(p, saa7113config[i0].reg);
-	if (ir != saa7113config[i0].set) {
-		SAY("SAA register 0x%02X has 0x%02X, expected 0x%02X\n", \
-			saa7113config[i0].reg, ir, saa7113config[i0].set);
-		rc--;
+		ir = read_saa(p, saa7113configPAL[i0].reg);
+		if (ir != saa7113configPAL[i0].set) {
+			SAY("SAA register 0x%02X has 0x%02X, " \
+						"expected 0x%02X\n", \
+						saa7113configPAL[i0].reg, \
+						ir, saa7113configPAL[i0].set);
+			rc--;
+		}
+		i0++;
 	}
-	i0++;
 }
 if (-8 > rc)
 	return rc;
@@ -393,29 +511,44 @@ else
 int
 ready_saa(struct usb_device *p)
 {
-int j, rc;
-static int max = 10;
-
+int j, rc, rate;
+const int max = 5, marktime = PATIENCE/5;
+/*--------------------------------------------------------------------------*/
+/*
+ *   RETURNS    0     FOR INTERLACED       50 Hz
+ *              1     FOR NON-INTERLACED   50 Hz
+ *              2     FOR INTERLACED       60 Hz
+ *              3     FOR NON-INTERLACED   60 Hz
+*/
+/*--------------------------------------------------------------------------*/
 j = 0;
 while (max > j) {
 	rc = read_saa(p, 0x1F);
 	if (0 <= rc) {
-		if ((1 == (0x01 & rc))&&(0 == (0x40 & rc)))
+		if (0 == (0x40 & rc))
+			break;
+		if (1 == (0x01 & rc))
 			break;
 	}
-	msleep(100);  j++;
+	msleep(marktime);
+	j++;
 }
 if (max == j)
 	return -1;
 else {
-	if (0x20 & rc)
+	if (0x20 & rc) {
+		rate = 2;
 		JOT(8, "hardware detects 60 Hz\n");
-	else
+	} else {
+		rate = 0;
 		JOT(8, "hardware detects 50 Hz\n");
+	}
 	if (0x80 & rc)
 		JOT(8, "hardware detects interlacing\n");
-	else
+	else {
+		rate++;
 		JOT(8, "hardware detects no interlacing\n");
+	}
 }
 return 0;
 }
@@ -424,45 +557,78 @@ return 0;
 /*
  *  NOTE: THE FOLLOWING ARE NOT CHECKED:
  *  REGISTERS 0x000, 0x002:  FUNCTIONALITY IS NOT KNOWN
- *  REGISTER  0x100:  ACCEPT ALSO (0x80 | stk1160config[.].set)
+ *  REGISTER  0x100:  ACCEPT ALSO (0x80 | stk1160config....[.].set)
  */
 /*--------------------------------------------------------------------------*/
 int
-check_stk(struct usb_device *p)
+check_stk(struct usb_device *p, bool ntsc)
 {
 int i0, ir;
-i0 = 0;
-while (0xFFF != stk1160config[i0].reg) {
-	if (0x000 == stk1160config[i0].reg) {
-		i0++; continue;
-	}
-	if (0x002 == stk1160config[i0].reg) {
-		i0++; continue;
-	}
-
-	ir = read_stk(p, stk1160config[i0].reg);
 
-	if (0x100 == stk1160config[i0].reg) {
-		if ((ir != (0xFF & stk1160config[i0].set)) && \
-			(ir != (0x80 | (0xFF & stk1160config[i0].set))) && \
-				(0xFFFF != stk1160config[i0].set)) {
-			SAY("STK register 0x%03X has 0x%02X, " \
-					"expected 0x%02X\n", \
-					stk1160config[i0].reg, ir, \
-					stk1160config[i0].set);
+i0 = 0;
+if (true == ntsc) {
+	while (0xFFF != stk1160configNTSC[i0].reg) {
+		if (0x000 == stk1160configNTSC[i0].reg) {
+			i0++; continue;
+		}
+		if (0x002 == stk1160configNTSC[i0].reg) {
+			i0++; continue;
+		}
+		ir = read_stk(p, stk1160configNTSC[i0].reg);
+		if (0x100 == stk1160configNTSC[i0].reg) {
+			if ((ir != (0xFF & stk1160configNTSC[i0].set)) && \
+					(ir != (0x80 | (0xFF & \
+					stk1160configNTSC[i0].set))) && \
+					(0xFFFF != \
+					stk1160configNTSC[i0].set)) {
+				SAY("STK register 0x%03X has 0x%02X, " \
+						"expected 0x%02X\n", \
+						stk1160configNTSC[i0].reg, \
+						ir, stk1160configNTSC[i0].set);
+				}
+			i0++; continue;
 			}
-		i0++; continue;
+		if ((ir != (0xFF & stk1160configNTSC[i0].set)) && \
+				(0xFFFF != stk1160configNTSC[i0].set)) {
+			SAY("STK register 0x%03X has 0x%02X, " \
+						"expected 0x%02X\n", \
+						stk1160configNTSC[i0].reg, \
+						ir, stk1160configNTSC[i0].set);
 		}
-
-	if ((ir != (0xFF & stk1160config[i0].set)) && \
-			(0xFFFF != stk1160config[i0].set)) {
-		SAY("STK register 0x%03X has 0x%02X, " \
-					"expected 0x%02X\n", \
-					stk1160config[i0].reg, ir, \
-					stk1160config[i0].set);
+		i0++;
+	}
+} else {
+	while (0xFFF != stk1160configPAL[i0].reg) {
+		if (0x000 == stk1160configPAL[i0].reg) {
+			i0++; continue;
+		}
+		if (0x002 == stk1160configPAL[i0].reg) {
+			i0++; continue;
+		}
+		ir = read_stk(p, stk1160configPAL[i0].reg);
+		if (0x100 == stk1160configPAL[i0].reg) {
+			if ((ir != (0xFF & stk1160configPAL[i0].set)) && \
+					(ir != (0x80 | (0xFF & \
+					stk1160configPAL[i0].set))) && \
+					(0xFFFF != \
+					stk1160configPAL[i0].set)) {
+				SAY("STK register 0x%03X has 0x%02X, " \
+						"expected 0x%02X\n", \
+						stk1160configPAL[i0].reg, \
+						ir, stk1160configPAL[i0].set);
+				}
+			i0++; continue;
+			}
+		if ((ir != (0xFF & stk1160configPAL[i0].set)) && \
+				(0xFFFF != stk1160configPAL[i0].set)) {
+			SAY("STK register 0x%03X has 0x%02X, " \
+						"expected 0x%02X\n", \
+						stk1160configPAL[i0].reg, \
+						ir, stk1160configPAL[i0].set);
 		}
-	i0++;
+		i0++;
 	}
+}
 return 0;
 }
 /****************************************************************************/
@@ -489,8 +655,8 @@ igot = 0;
 GET(p, reg0, &igot);
 return igot;
 }
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
+/****************************************************************************/
+/*--------------------------------------------------------------------------*/
 /*
  *    HARDWARE    USERSPACE INPUT NUMBER   PHYSICAL INPUT   DRIVER input VALUE
  *
@@ -511,81 +677,98 @@ return igot;
 int
 select_input(struct usb_device *p, int input, int mode)
 {
+int ir;
 
 stop_100(p);
-
-msleep(20);
 switch (input) {
 case 0:
 case 1: {
-	SET(p, 0x0000, 0x0098); break;
+	if (0 != write_saa(p, 0x02, 0x80)) {
+		SAY("ERROR: failed to set SAA register 0x02 for input %i\n", \
+									input);
+	}
+	SET(p, 0x0000, 0x0098);
+	SET(p, 0x0002, 0x0078);
+	break;
 }
 case 2: {
-	SET(p, 0x0000, 0x0090); break;
+	if (0 != write_saa(p, 0x02, 0x80)) {
+		SAY("ERROR: failed to set SAA register 0x02 for input %i\n", \
+									input);
+	}
+	SET(p, 0x0000, 0x0090);
+	SET(p, 0x0002, 0x0078);
+	break;
 }
 case 3: {
-	SET(p, 0x0000, 0x0088); break;
+	if (0 != write_saa(p, 0x02, 0x80)) {
+		SAY("ERROR: failed to set SAA register 0x02 for input %i\n", \
+									input);
+	}
+	SET(p, 0x0000, 0x0088);
+	SET(p, 0x0002, 0x0078);
+	break;
 }
 case 4: {
-	SET(p, 0x0000, 0x0080); break;
+	if (0 != write_saa(p, 0x02, 0x80)) {
+		SAY("ERROR: failed to set SAA register 0x02 for input %i\n", \
+									input);
+	}
+	SET(p, 0x0000, 0x0080);
+	SET(p, 0x0002, 0x0078);
+	break;
 }
 case 5: {
 	if (9 != mode)
 		mode = 7;
 	switch (mode) {
-	case 7:
-		{
+	case 7: {
 		if (0 != write_saa(p, 0x02, 0x87)) {
-			SAY("ERROR: failed to set SAA " \
-				"register 0x02 for input " \
-				"%i\n", input);
+			SAY("ERROR: failed to set SAA register 0x02 " \
+						"for input %i\n", input);
 		}
 		if (0 != write_saa(p, 0x05, 0xFF)) {
-			SAY("ERROR: failed to set SAA " \
-				"register 0x05 for input " \
-				"%i\n", input);
+			SAY("ERROR: failed to set SAA register 0x05 " \
+						"for input %i\n", input);
 		}
 		break;
 	}
-	case 9:
-		{
+	case 9: {
 		if (0 != write_saa(p, 0x02, 0x89)) {
-			SAY("ERROR: failed to set SAA " \
-				"register 0x02 for input " \
-				"%i\n", input);
+			SAY("ERROR: failed to set SAA register 0x02 " \
+						"for input %i\n", input);
 		}
 		if (0 != write_saa(p, 0x05, 0x00)) {
-			SAY("ERROR: failed to set SAA " \
-				"register 0x05 for input " \
-				"%i\n", input);
+			SAY("ERROR: failed to set SAA register 0x05 " \
+						"for input %i\n", input);
 		}
-		break;
+	break;
 	}
-	default:
-		{
+	default: {
 		SAY("MISTAKE:  bad mode: %i\n", mode);
 		return -1;
-		}
+	}
 	}
 	if (0 != write_saa(p, 0x04, 0x00)) {
-		SAY("ERROR: failed to set SAA register 0x04 " \
-					"for input %i\n", input);
+		SAY("ERROR: failed to set SAA register 0x04 for input %i\n", \
+									input);
 	}
 	if (0 != write_saa(p, 0x09, 0x80)) {
-		SAY("ERROR: failed to set SAA register 0x09 " \
-					"for input %i\n", input);
+		SAY("ERROR: failed to set SAA register 0x09 for input %i\n", \
+									input);
 	}
+	SET(p, 0x0002, 0x0093);
 	break;
 }
-default:
-	{
+default: {
 	SAY("ERROR:  bad input: %i\n", input);
 	return -1;
 }
 }
-msleep(20);
-SET(p, 0x0002, 0x0093);
-msleep(20);
+ir = read_stk(p, 0x00);
+JOT(8, "STK register 0x00 has 0x%02X\n", ir);
+ir = read_saa(p, 0x02);
+JOT(8, "SAA register 0x02 has 0x%02X\n", ir);
 
 start_100(p);
 
@@ -618,13 +801,23 @@ return 0;
 int
 start_100(struct usb_device *p)
 {
-__u16 get0;
-__u8 igot;
-
-GET(p, 0x0100, &igot);  get0 = igot;
-msleep(0x1f4);
+__u16 get116, get117, get0;
+__u8 igot116, igot117, igot;
+
+GET(p, 0x0116, &igot116);
+get116 = igot116;
+GET(p, 0x0117, &igot117);
+get117 = igot117;
+SET(p, 0x0116, 0x0000);
+SET(p, 0x0117, 0x0000);
+
+GET(p, 0x0100, &igot);
+get0 = igot;
 SET(p, 0x0100, (0x80 | get0));
-msleep(0x1f4);
+
+SET(p, 0x0116, get116);
+SET(p, 0x0117, get117);
+
 return 0;
 }
 /****************************************************************************/
@@ -634,10 +827,9 @@ stop_100(struct usb_device *p)
 __u16 get0;
 __u8 igot;
 
-GET(p, 0x0100, &igot);  get0 = igot;
-msleep(0x1f4);
+GET(p, 0x0100, &igot);
+get0 = igot;
 SET(p, 0x0100, (0x7F & get0));
-msleep(0x1f4);
 return 0;
 }
 /****************************************************************************/
@@ -651,7 +843,7 @@ wait_i2c(struct usb_device *p)
 {
 __u16 get0;
 __u8 igot;
-const int max = 4;
+const int max = 2;
 int k;
 
 for (k = 0;  k < max;  k++) {
@@ -662,7 +854,7 @@ for (k = 0;  k < max;  k++) {
 		return 0;
 	}
 	case 0x00: {
-		msleep(10);
+		msleep(20);
 		continue;
 	}
 	default: {
@@ -718,27 +910,14 @@ case 0x204:
 case 0x205:
 case 0x350:
 case 0x351: {
-	if (0 != igot) {
+	if (0 != (0xFF & igot)) {
 		JOT(8, "unexpected 0x%02X for STK register 0x%03X\n", \
 								igot, index);
 	}
 break;
 }
-case 0x114:
-case 0x116: {
-	if ((0xFF & value) != igot) {
-		JOT(8, "unexpected 0x%02X != 0x%02X " \
-						"for STK register 0x%03X\n", \
-						igot, value, index);
-	}
-break;
-}
-case 0x200: {
-	if (0 == igot)
-		break;
-}
 default: {
-	if (value != igot) {
+	if ((0xFF & value) != (0xFF & igot)) {
 		JOT(8, "unexpected 0x%02X != 0x%02X " \
 					"for STK register 0x%03X\n", \
 					igot, value, index);
@@ -988,29 +1167,3 @@ if (0 > igot)
 return igot;
 }
 /*****************************************************************************/
-int
-set2to78(struct usb_device *p)
-{
-int ir;
-
-msleep(20);
-ir = regset(p, 0x0002, 0x0078);
-if (0 > ir)
-	SAY("ERROR: failed to set register 0x0002 to 0x0078\n");
-msleep(20);
-return ir;
-}
-/*****************************************************************************/
-int
-set2to93(struct usb_device *p)
-{
-int ir;
-
-msleep(20);
-ir = regset(p, 0x0002, 0x0093);
-if (0 > ir)
-	SAY("ERROR: failed to set register 0x0002 to 0x0078\n");
-msleep(20);
-return ir;
-}
-/*****************************************************************************/
diff --git a/drivers/staging/easycap/easycap_main.c b/drivers/staging/easycap/easycap_main.c
index ff6addf..b522c6e 100644
--- a/drivers/staging/easycap/easycap_main.c
+++ b/drivers/staging/easycap/easycap_main.c
@@ -30,6 +30,7 @@
 
 #include "easycap.h"
 #include "easycap_standard.h"
+#include "easycap_ioctl.h"
 
 int debug;
 module_param(debug, int, S_IRUGO | S_IWUSR);
@@ -162,9 +163,8 @@ struct usb_interface *pusb_interface;
 #else
 struct video_device *pvideo_device;
 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
-struct usb_device *p;
 struct easycap *peasycap;
-int i, k, m, rc;
+int rc;
 
 JOT(4, "\n");
 SAY("==========OPEN=========\n");
@@ -197,19 +197,7 @@ if ((struct easycap *)NULL == peasycap) {
 	return -EFAULT;
 }
 file->private_data = peasycap;
-/*---------------------------------------------------------------------------*/
-/*
- *  INITIALIZATION
- */
-/*---------------------------------------------------------------------------*/
-JOM(4, "starting initialization\n");
-
-for (k = 0;  k < FRAME_BUFFER_MANY;  k++) {
-	for (m = 0;  m < FRAME_BUFFER_SIZE/PAGE_SIZE;  m++)
-		memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
-}
-p = peasycap->pusb_device;
-if ((struct usb_device *)NULL == p) {
+if (NULL == peasycap->pusb_device) {
 	SAM("ERROR: peasycap->pusb_device is NULL\n");
 	return -EFAULT;
 } else {
@@ -221,121 +209,398 @@ if (0 == rc)
 	JOM(8, "wakeup_device() OK\n");
 else {
 	SAM("ERROR: wakeup_device() returned %i\n", rc);
+	if (-ENODEV == rc)
+		SAM("ERROR: wakeup_device() returned -ENODEV\n");
+	else
+		SAM("ERROR: wakeup_device() returned %i\n", rc);
+	return rc;
+}
+peasycap->input = 0;
+rc = reset(peasycap);
+if (0 != rc) {
+	SAM("ERROR: reset() returned %i\n", rc);
 	return -EFAULT;
 }
-rc = setup_stk(p);  peasycap->input = 0;
+return 0;
+}
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ *  RESET THE HARDWARE TO ITS REFERENCE STATE.
+ *
+ *  THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
+ *  A BAD VIDEO FRAME SIZE.
+*/
+/*---------------------------------------------------------------------------*/
+int
+reset(struct easycap *peasycap)
+{
+struct easycap_standard const *peasycap_standard;
+int i, rc, input, rate;
+bool ntsc, other;
+
+if ((struct easycap *)NULL == peasycap) {
+	SAY("ERROR: peasycap is NULL\n");
+	return -EFAULT;
+}
+input = peasycap->input;
+
+/*---------------------------------------------------------------------------*/
+/*
+ *  IF THE SAA7113H HAS ALREADY ACQUIRED LOCK, USE ITS HARDWARE-DETECTED
+ *  FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL.  THIS IS ESSENTIAL FOR
+ *  gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
+ *  A SWITCH BETWEEN PAL AND NTSC.
+ *
+ *  FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
+ *  COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
+*/
+/*---------------------------------------------------------------------------*/
+other = false;
+if (true == peasycap->ntsc)
+	JOM(8, "true=peasycap->ntsc\n");
+else
+	JOM(8, "false=peasycap->ntsc\n");
+rate = ready_saa(peasycap->pusb_device);
+if (0 > rate) {
+	JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
+	if (true == peasycap->ntsc) {
+		JOM(8, "... trying PAL ...\n");  ntsc = false;
+	} else {
+		JOM(8, "... trying NTSC ...\n"); ntsc = true;
+}
+rc = setup_stk(peasycap->pusb_device, ntsc);
 if (0 == rc)
-	JOM(8, "setup_stk() OK\n");
+	JOM(4, "setup_stk() OK\n");
 else {
 	SAM("ERROR: setup_stk() returned %i\n", rc);
 	return -EFAULT;
 }
-rc = setup_saa(p);
+rc = setup_saa(peasycap->pusb_device, ntsc);
 if (0 == rc)
-	JOM(8, "setup_saa() OK\n");
+	JOM(4, "setup_saa() OK\n");
 else {
 	SAM("ERROR: setup_saa() returned %i\n", rc);
 	return -EFAULT;
 }
-rc = check_saa(p);
-if (0 == rc)
-	JOM(8, "check_saa() OK\n");
-else if (-8 < rc)
-	SAM("check_saa() returned %i\n", rc);
-else {
-	SAM("ERROR: check_saa() returned %i\n", rc);
-	return -EFAULT;
+rate = ready_saa(peasycap->pusb_device);
+if (0 > rate) {
+	JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
+	JOM(8, "... saa register 0x1F has 0x%02X\n", \
+				read_saa(peasycap->pusb_device, 0x1F));
+	ntsc = peasycap->ntsc;
+	} else {
+		JOM(8, "... success at second try:  %i=rate\n", rate);
+		ntsc = (0 < (rate/2)) ? true : false ;
+		other = true;
+	}
+} else {
+	JOM(8, "... success at first try:  %i=rate\n", rate);
+	ntsc = (0 < rate/2) ? true : false ;
 }
-peasycap->standard_offset = -1;
+if (true == ntsc)
+	JOM(8, "true=ntsc\n");
+else
+	JOM(8, "false=ntsc\n");
 /*---------------------------------------------------------------------------*/
-#if defined(PREFER_NTSC)
 
-rc = adjust_standard(peasycap, V4L2_STD_NTSC_M);
+rc = setup_stk(peasycap->pusb_device, ntsc);
 if (0 == rc)
-	JOM(8, "adjust_standard(.,NTSC_M) OK\n");
+	JOM(4, "setup_stk() OK\n");
 else {
-	SAM("ERROR: adjust_standard(.,NTSC_M) returned %i\n", rc);
+	SAM("ERROR: setup_stk() returned %i\n", rc);
 	return -EFAULT;
 }
-rc = adjust_format(peasycap, 640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, \
-									false);
-if (0 <= rc)
-	JOM(8, "adjust_format(.,640,480,UYVY) OK\n");
+rc = setup_saa(peasycap->pusb_device, ntsc);
+if (0 == rc)
+	JOM(4, "setup_saa() OK\n");
 else {
-	SAM("ERROR: adjust_format(.,640,480,UYVY) returned %i\n", rc);
+	SAM("ERROR: setup_saa() returned %i\n", rc);
 	return -EFAULT;
 }
 
-#else
+for (i = 0; i < 180; i++)
+	peasycap->merit[i] = 0;
+peasycap->video_eof = 0;
+peasycap->audio_eof = 0;
+do_gettimeofday(&peasycap->timeval7);
+/*---------------------------------------------------------------------------*/
+/*
+ * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
+ *
+ * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
+*/
+/*---------------------------------------------------------------------------*/
+peasycap->input = -8192;
+peasycap->standard_offset = -8192;
+if (true == other) {
+	peasycap_standard = &easycap_standard[0];
+	while (0xFFFF != peasycap_standard->mask) {
+		if (true == ntsc) {
+			if (NTSC_M == \
+				peasycap_standard->v4l2_standard.index) {
+				peasycap->inputset[input].standard_offset = \
+						peasycap_standard - \
+							&easycap_standard[0];
+				break;
+			}
+		} else {
+			if (PAL_BGHIN == \
+				peasycap_standard->v4l2_standard.index) {
+				peasycap->inputset[input].standard_offset = \
+						peasycap_standard -
+							&easycap_standard[0];
+				break;
+			}
+		}
+		peasycap_standard++;
+	}
+	if (0xFFFF == peasycap_standard->mask) {
+		SAM("ERROR: standard not found\n");
+		return -EINVAL;
+	}
+JOM(8, "%i=peasycap->inputset[%i].standard_offset\n", \
+		peasycap->inputset[input].standard_offset, input);
+}
+peasycap->format_offset = -8192;
+peasycap->brightness = -8192;
+peasycap->contrast = -8192;
+peasycap->saturation = -8192;
+peasycap->hue = -8192;
+
+rc = newinput(peasycap, input);
 
-rc = adjust_standard(peasycap, \
-		(V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_H | \
-		V4L2_STD_PAL_I | V4L2_STD_PAL_N));
 if (0 == rc)
-	JOM(8, "adjust_standard(.,PAL_BGHIN) OK\n");
+	JOM(4, "restored input, standard and format\n");
 else {
-	SAM("ERROR: adjust_standard(.,PAL_BGHIN) returned %i\n", rc);
+	SAM("ERROR: newinput(.,%i) returned %i\n", rc, input);
 	return -EFAULT;
 }
-rc = adjust_format(peasycap, 640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, \
-									false);
-if (0 <= rc)
-	JOM(8, "adjust_format(.,640,480,uyvy,false) OK\n");
-else {
-	SAM("ERROR: adjust_format(.,640,480,uyvy,false) returned %i\n", rc);
+if (true == peasycap->ntsc)
+	JOM(8, "true=peasycap->ntsc\n");
+else
+	JOM(8, "false=peasycap->ntsc\n");
+
+if (0 > peasycap->input) {
+	SAM("MISTAKE:  %i=peasycap->input\n", peasycap->input);
+	return -ENOENT;
+}
+if (0 > peasycap->standard_offset) {
+	SAM("MISTAKE:  %i=peasycap->standard_offset\n", \
+						peasycap->standard_offset);
+	return -ENOENT;
+}
+if (0 > peasycap->format_offset) {
+	SAM("MISTAKE:  %i=peasycap->format_offset\n", \
+						peasycap->format_offset);
+	return -ENOENT;
+}
+if (0 > peasycap->brightness) {
+	SAM("MISTAKE:  %i=peasycap->brightness\n", peasycap->brightness);
+	return -ENOENT;
+}
+if (0 > peasycap->contrast) {
+	SAM("MISTAKE:  %i=peasycap->contrast\n", peasycap->contrast);
+	return -ENOENT;
+}
+if (0 > peasycap->saturation) {
+	SAM("MISTAKE:  %i=peasycap->saturation\n", peasycap->saturation);
+	return -ENOENT;
+}
+if (0 > peasycap->hue) {
+	SAM("MISTAKE:  %i=peasycap->hue\n", peasycap->hue);
+	return -ENOENT;
+}
+return 0;
+}
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ *  IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
+ *  OTHERWISE:
+ *      KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
+ *           _read AND _fill POINTERS.
+ *      SELECT THE NEW INPUT.
+ *      ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
+ *          ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
+ *      RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
+ *
+ *  NOTE:
+ *      THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
+ *      SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
+*/
+/*---------------------------------------------------------------------------*/
+int
+newinput(struct easycap *peasycap, int input)
+{
+int rc, k, m, mood, off;
+int inputnow, video_idlenow, audio_idlenow;
+bool resubmit;
+
+if (NULL == peasycap) {
+	SAY("ERROR: peasycap is NULL\n");
 	return -EFAULT;
 }
+JOM(8, "%i=input sought\n", input);
 
-#endif /* !PREFER_NTSC*/
+if ((0 > input) &&(INPUT_MANY <= input))
+	return -ENOENT;
+inputnow = peasycap->input;
+if (input == inputnow)
+	return 0;
 /*---------------------------------------------------------------------------*/
-rc = adjust_brightness(peasycap, -8192);
-if (0 != rc) {
-	SAM("ERROR: adjust_brightness(default) returned %i\n", rc);
-	return -EFAULT;
+/*
+ *  IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
+ *  STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
+ *  IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
+ *  ROUTINE.
+*/
+/*---------------------------------------------------------------------------*/
+video_idlenow = peasycap->video_idle;
+audio_idlenow = peasycap->audio_idle;
+
+peasycap->video_idle = 1;
+peasycap->audio_idle = 1;
+if (peasycap->video_isoc_streaming) {
+	resubmit = true;
+	kill_video_urbs(peasycap);
+} else
+	resubmit = false;
+/*---------------------------------------------------------------------------*/
+if (NULL == peasycap->pusb_device) {
+	SAM("ERROR: peasycap->pusb_device is NULL\n");
+	return -ENODEV;
 }
-rc = adjust_contrast(peasycap, -8192);
+rc = usb_set_interface(peasycap->pusb_device, \
+			peasycap->video_interface, \
+			peasycap->video_altsetting_off);
 if (0 != rc) {
-	SAM("ERROR: adjust_contrast(default) returned %i\n", rc);
+	SAM("ERROR: usb_set_interface() returned %i\n", rc);
 	return -EFAULT;
 }
-rc = adjust_saturation(peasycap, -8192);
+rc = stop_100(peasycap->pusb_device);
 if (0 != rc) {
-	SAM("ERROR: adjust_saturation(default) returned %i\n", rc);
+	SAM("ERROR: stop_100() returned %i\n", rc);
 	return -EFAULT;
 }
-rc = adjust_hue(peasycap, -8192);
-if (0 != rc) {
-	SAM("ERROR: adjust_hue(default) returned %i\n", rc);
-	return -EFAULT;
+for (k = 0; k < FIELD_BUFFER_MANY; k++) {
+	for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
+		memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
+}
+for (k = 0; k < FRAME_BUFFER_MANY; k++) {
+	for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
+		memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
+}
+peasycap->field_page = 0;
+peasycap->field_read = 0;
+peasycap->field_fill = 0;
+
+peasycap->frame_read = 0;
+peasycap->frame_fill = 0;
+for (k = 0; k < peasycap->input; k++) {
+	(peasycap->frame_fill)++;
+	if (peasycap->frame_buffer_many <= peasycap->frame_fill)
+		peasycap->frame_fill = 0;
 }
+peasycap->input = input;
+select_input(peasycap->pusb_device, peasycap->input, 9);
 /*---------------------------------------------------------------------------*/
-rc = usb_set_interface(peasycap->pusb_device, peasycap->video_interface, \
-						peasycap->video_altsetting_on);
-if (0 == rc)
-	JOM(8, "usb_set_interface(.,%i,%i) OK\n", peasycap->video_interface, \
-						peasycap->video_altsetting_on);
-else {
+if (input == peasycap->inputset[input].input) {
+	off = peasycap->inputset[input].standard_offset;
+	if (off != peasycap->standard_offset) {
+		rc = adjust_standard(peasycap, \
+				easycap_standard[off].v4l2_standard.id);
+		if (0 != rc) {
+			SAM("ERROR: adjust_standard() returned %i\n", rc);
+			return -EFAULT;
+		}
+		JOM(8, "%i=peasycap->standard_offset\n", \
+						peasycap->standard_offset);
+	} else {
+		JOM(8, "%i=peasycap->standard_offset unchanged\n", \
+						peasycap->standard_offset);
+	}
+	off = peasycap->inputset[input].format_offset;
+	if (off != peasycap->format_offset) {
+		rc = adjust_format(peasycap, \
+			easycap_format[off].v4l2_format.fmt.pix.width, \
+			easycap_format[off].v4l2_format.fmt.pix.height, \
+			easycap_format[off].v4l2_format.fmt.pix.pixelformat, \
+			easycap_format[off].v4l2_format.fmt.pix.field, false);
+		if (0 > rc) {
+			SAM("ERROR: adjust_format() returned %i\n", rc);
+			return -EFAULT;
+		}
+		JOM(8, "%i=peasycap->format_offset\n", peasycap->format_offset);
+	} else {
+		JOM(8, "%i=peasycap->format_offset unchanged\n", \
+						peasycap->format_offset);
+	}
+	mood = peasycap->inputset[input].brightness;
+	if (mood != peasycap->brightness) {
+		rc = adjust_brightness(peasycap, mood);
+		if (0 != rc) {
+			SAM("ERROR: adjust_brightness returned %i\n", rc);
+			return -EFAULT;
+		}
+		JOM(8, "%i=peasycap->brightness\n", peasycap->brightness);
+	}
+	mood = peasycap->inputset[input].contrast;
+	if (mood != peasycap->contrast) {
+		rc = adjust_contrast(peasycap, mood);
+		if (0 != rc) {
+			SAM("ERROR: adjust_contrast returned %i\n", rc);
+			return -EFAULT;
+		}
+		JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
+	}
+	mood = peasycap->inputset[input].saturation;
+	if (mood != peasycap->saturation) {
+		rc = adjust_saturation(peasycap, mood);
+		if (0 != rc) {
+			SAM("ERROR: adjust_saturation returned %i\n", rc);
+			return -EFAULT;
+		}
+		JOM(8, "%i=peasycap->saturation\n", peasycap->saturation);
+	}
+	mood = peasycap->inputset[input].hue;
+	if (mood != peasycap->hue) {
+		rc = adjust_hue(peasycap, mood);
+		if (0 != rc) {
+			SAM("ERROR: adjust_hue returned %i\n", rc);
+			return -EFAULT;
+		}
+		JOM(8, "%i=peasycap->hue\n", peasycap->hue);
+	}
+} else {
+	SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
+	return -ENOENT;
+}
+/*---------------------------------------------------------------------------*/
+if ((struct usb_device *)NULL == peasycap->pusb_device) {
+	SAM("ERROR: peasycap->pusb_device is NULL\n");
+	return -ENODEV;
+}
+rc = usb_set_interface(peasycap->pusb_device,
+			peasycap->video_interface, \
+			peasycap->video_altsetting_on);
+if (0 != rc) {
 	SAM("ERROR: usb_set_interface() returned %i\n", rc);
 	return -EFAULT;
 }
-rc = start_100(p);
-if (0 == rc)
-	JOM(8, "start_100() OK\n");
-else {
+rc = start_100(peasycap->pusb_device);
+if (0 != rc) {
 	SAM("ERROR: start_100() returned %i\n", rc);
 	return -EFAULT;
 }
+if (true == resubmit)
+	submit_video_urbs(peasycap);
+
 peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
-peasycap->video_idle = 0;
+peasycap->video_idle = video_idlenow;
+peasycap->audio_idle = audio_idlenow;
 peasycap->video_junk = 0;
-for (i = 0; i < 180; i++)
-	peasycap->merit[i] = 0;
-peasycap->video_eof = 0;
-peasycap->audio_eof = 0;
-
-do_gettimeofday(&peasycap->timeval7);
 
-JOM(4, "finished initialization\n");
 return 0;
 }
 /*****************************************************************************/
@@ -864,24 +1129,44 @@ while ((peasycap->field_read == peasycap->field_fill) || \
 				"%i=field_read  %i=field_fill\n", \
 				peasycap->field_read, peasycap->field_fill);
 
-	msleep(1);
 	if (0 != (wait_event_interruptible(peasycap->wq_video, \
 			(peasycap->video_idle || peasycap->video_eof  || \
 			((peasycap->field_read != peasycap->field_fill) && \
 				(0 == (0xFF00 & peasycap->field_buffer\
 					[peasycap->field_read][0].kount)) && \
 				(0 == (0x00FF & peasycap->field_buffer\
-					[peasycap->field_read][0].kount))))))){
+					[peasycap->field_read][0].kount))))))) {
 		SAM("aborted by signal\n");
 		return -EIO;
 		}
 	if (peasycap->video_idle) {
-		JOM(8, "%i=peasycap->video_idle\n", peasycap->video_idle);
-		return -EIO;
+		JOM(8, "%i=peasycap->video_idle ... returning -EAGAIN\n", \
+							peasycap->video_idle);
+		return -EAGAIN;
 	}
 	if (peasycap->video_eof) {
 		JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
+		#if defined(PERSEVERE)
+		if (1 == peasycap->status) {
+			JOM(8, "persevering ...\n");
+			peasycap->video_eof = 0;
+			peasycap->audio_eof = 0;
+			if (0 != reset(peasycap)) {
+				JOM(8, " ... failed ... returning -EIO\n");
+				peasycap->video_eof = 1;
+				peasycap->audio_eof = 1;
+				kill_video_urbs(peasycap);
+				return -EIO;
+			}
+			peasycap->status = 0;
+			JOM(8, " ... OK ... returning -EAGAIN\n");
+			return -EAGAIN;
+		}
+		#endif /*PERSEVERE*/
+		peasycap->video_eof = 1;
+		peasycap->audio_eof = 1;
 		kill_video_urbs(peasycap);
+		JOM(8, "returning -EIO\n");
 		return -EIO;
 	}
 miss++;
@@ -925,24 +1210,44 @@ while ((peasycap->field_read == peasycap->field_fill) || \
 	JOM(8, "second wait on wq_video, " \
 				"%i=field_read  %i=field_fill\n", \
 				peasycap->field_read, peasycap->field_fill);
-	msleep(1);
 	if (0 != (wait_event_interruptible(peasycap->wq_video, \
 			(peasycap->video_idle || peasycap->video_eof  || \
 			((peasycap->field_read != peasycap->field_fill) && \
 				(0 == (0xFF00 & peasycap->field_buffer\
 					[peasycap->field_read][0].kount)) && \
 				(0 != (0x00FF & peasycap->field_buffer\
-					[peasycap->field_read][0].kount))))))){
+					[peasycap->field_read][0].kount))))))) {
 		SAM("aborted by signal\n");
 		return -EIO;
 	}
 	if (peasycap->video_idle) {
-		JOM(8, "%i=peasycap->video_idle\n", peasycap->video_idle);
-		return -EIO;
+		JOM(8, "%i=peasycap->video_idle ... returning -EAGAIN\n", \
+							peasycap->video_idle);
+		return -EAGAIN;
 	}
 	if (peasycap->video_eof) {
 		JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
+		#if defined(PERSEVERE)
+		if (1 == peasycap->status) {
+			JOM(8, "persevering ...\n");
+			peasycap->video_eof = 0;
+			peasycap->audio_eof = 0;
+			if (0 != reset(peasycap)) {
+				JOM(8, " ... failed ... returning -EIO\n");
+				peasycap->video_eof = 1;
+				peasycap->audio_eof = 1;
+				kill_video_urbs(peasycap);
+				return -EIO;
+			}
+			peasycap->status = 0;
+			JOM(8, " ... OK ... returning -EAGAIN\n");
+			return -EAGAIN;
+		}
+		#endif /*PERSEVERE*/
+		peasycap->video_eof = 1;
+		peasycap->audio_eof = 1;
 		kill_video_urbs(peasycap);
+		JOM(8, "returning -EIO\n");
 		return -EIO;
 	}
 miss++;
@@ -1001,13 +1306,15 @@ int kex, kad, mex, mad, rex, rad, rad2;
 int c2, c3, w2, w3, cz, wz;
 int rc, bytesperpixel, multiplier, much, more, over, rump, caches;
 __u8 mask, margin;
-bool odd, isuy, decimatepixel, offerfields;
+bool odd, isuy, decimatepixel, offerfields, badinput;
 
 if ((struct easycap *)NULL == peasycap) {
 	SAY("ERROR: peasycap is NULL\n");
 	return -EFAULT;
 }
 
+badinput = false;
+
 JOM(8, "=====  parity %i, field buffer %i --> frame buffer %i\n", \
 			peasycap->field_buffer[peasycap->field_read][0].kount,\
 			peasycap->field_read, peasycap->frame_fill);
@@ -1138,6 +1445,15 @@ while (cz < wz) {
 			if (rump)
 				caches++;
 
+				if (true == badinput) {
+					JOM(8, "ERROR: 0x%02X=->field_buffer" \
+						"[%i][%i].input, " \
+						"0x%02X=(0x08|->input)\n", \
+						peasycap->field_buffer\
+						[kex][mex].input, kex, mex, \
+						(0x08|peasycap->input));
+				}
+
 			rc = redaub(peasycap, pad, pex, much, more, \
 							mask, margin, isuy);
 			if (0 > rc) {
@@ -1156,6 +1472,9 @@ while (cz < wz) {
 				mex++;
 				pex = peasycap->field_buffer[kex][mex].pgo;
 				rex = PAGE_SIZE;
+				if (peasycap->field_buffer[kex][mex].input != \
+						(0x08|peasycap->input))
+					badinput = true;
 			}
 			pad  += more;
 			rad -= more;
@@ -1254,6 +1573,15 @@ while (cz < wz) {
 			if (rump)
 				caches++;
 
+				if (true == badinput) {
+					JOM(8, "ERROR: 0x%02X=->field_buffer" \
+						"[%i][%i].input, " \
+						"0x%02X=(0x08|->input)\n", \
+						peasycap->field_buffer\
+						[kex][mex].input, kex, mex, \
+						(0x08|peasycap->input));
+				}
+
 			rc = redaub(peasycap, pad, pex, much, more, \
 							mask, margin, isuy);
 			if (0 > rc) {
@@ -1266,6 +1594,9 @@ while (cz < wz) {
 				mex++;
 				pex = peasycap->field_buffer[kex][mex].pgo;
 				rex = PAGE_SIZE;
+				if (peasycap->field_buffer[kex][mex].input != \
+						(0x08|peasycap->input))
+					badinput = true;
 			}
 			pad  += more;
 			rad -= more;
@@ -1292,6 +1623,16 @@ while (cz < wz) {
 				mex++;
 				pex = peasycap->field_buffer[kex][mex].pgo;
 				rex = PAGE_SIZE;
+				if (peasycap->field_buffer[kex][mex].input != \
+						(0x08|peasycap->input)) {
+					JOM(8, "ERROR: 0x%02X=->field_buffer"\
+						"[%i][%i].input, " \
+						"0x%02X=(0x08|->input)\n", \
+						peasycap->field_buffer\
+						[kex][mex].input, kex, mex, \
+						(0x08|peasycap->input));
+					badinput = true;
+				}
 			}
 			much = over;
 			if (rex < much)
@@ -2350,6 +2691,7 @@ return retcode;
  *      0 != (kount & 0x8000)   => AT LEAST ONE URB COMPLETED WITH ERRORS
  *      0 != (kount & 0x4000)   => BUFFER HAS TOO MUCH DATA
  *      0 != (kount & 0x2000)   => BUFFER HAS NOT ENOUGH DATA
+ *      0 != (kount & 0x1000)   => BUFFER HAS DATA FROM DISPARATE INPUTS
  *      0 != (kount & 0x0400)   => RESERVED
  *      0 != (kount & 0x0200)   => FIELD BUFFER NOT YET CHECKED
  *      0 != (kount & 0x0100)   => BUFFER HAS TWO EXTRA BYTES - WHY?
@@ -2363,7 +2705,7 @@ struct data_buffer *pfield_buffer;
 char errbuf[16];
 int i, more, much, leap, rc, last;
 int videofieldamount;
-unsigned int override;
+unsigned int override, bad;
 int framestatus, framelength, frameactual, frameoffset;
 __u8 *pu;
 
@@ -2389,7 +2731,7 @@ if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && \
 						(0 != i)) || \
 	(((VIDEO_ISOC_BUFFER_MANY - 1) != last) && \
 						((last + 1) != i))) {
-	SAM("ERROR: out-of-order urbs %i,%i ... continuing\n", last, i);
+	JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n", last, i);
 }
 peasycap->video_isoc_sequence = i;
 
@@ -2399,9 +2741,6 @@ if (peasycap->video_idle) {
 	if (peasycap->video_isoc_streaming) {
 		rc = usb_submit_urb(purb, GFP_ATOMIC);
 		if (0 != rc) {
-			SAM("ERROR: while %i=video_idle, " \
-					"usb_submit_urb() failed with rc:\n", \
-							peasycap->video_idle);
 			switch (rc) {
 			case -ENOMEM: {
 				SAM("ENOMEM\n");
@@ -2444,6 +2783,11 @@ if (peasycap->video_idle) {
 				break;
 			}
 			}
+			if (-ENODEV != rc) \
+				SAM("ERROR: while %i=video_idle, " \
+							"usb_submit_urb() " \
+							"failed with rc:\n", \
+							peasycap->video_idle);
 		}
 	}
 return;
@@ -2662,6 +3006,8 @@ if (purb->status) {
 						(peasycap->field_buffer\
 						[peasycap->field_fill]\
 							[0].kount) |= 0x0100;
+						peasycap->video_junk += (1 + \
+							VIDEO_JUNK_TOLERATE);
 					} else
 						(peasycap->field_buffer\
 						[peasycap->field_fill]\
@@ -2673,53 +3019,74 @@ if (purb->status) {
 						[peasycap->field_fill]\
 							[0].kount) |= 0x2000;
 					}
-				if (!(0xFF00 & peasycap->field_buffer\
+					bad = 0xFF00 & peasycap->field_buffer\
 						[peasycap->field_fill]\
-						[0].kount)) {
-					(peasycap->video_junk)--;
-					if (-16 > peasycap->video_junk)
-						peasycap->video_junk = -16;
-					peasycap->field_read = \
+						[0].kount;
+					if (!bad) {
+						(peasycap->video_junk)--;
+						if (-VIDEO_JUNK_TOLERATE > \
+							peasycap->video_junk) \
+							peasycap->video_junk =\
+							-VIDEO_JUNK_TOLERATE;
+						peasycap->field_read = \
 							(peasycap->\
 								field_fill)++;
-
-					if (FIELD_BUFFER_MANY <= \
-						peasycap->field_fill)
-						peasycap->field_fill = 0;
-					peasycap->field_page = 0;
-					pfield_buffer = &peasycap->\
-						field_buffer\
-						[peasycap->field_fill]\
-						[peasycap->field_page];
-					pfield_buffer->pto = \
+						if (FIELD_BUFFER_MANY <= \
+								peasycap->\
+								field_fill)
+							peasycap->\
+								field_fill = 0;
+						peasycap->field_page = 0;
+						pfield_buffer = &peasycap->\
+							field_buffer\
+							[peasycap->\
+							field_fill]\
+							[peasycap->\
+							field_page];
+						pfield_buffer->pto = \
 							pfield_buffer->pgo;
-
-					JOM(8, "bumped to: %i=peasycap->" \
-						"field_fill  %i=parity\n", \
-						peasycap->field_fill, \
-						0x00FF & pfield_buffer->kount);
-					JOM(8, "field buffer %i has %i " \
-						"bytes fit to be read\n", \
-						peasycap->field_read, \
-						videofieldamount);
-					JOM(8, "wakeup call to wq_video, " \
-						"%i=field_read %i=field_fill "\
-						"%i=parity\n", \
-						peasycap->field_read, \
-						peasycap->field_fill, \
-						0x00FF & peasycap->\
-						field_buffer[peasycap->\
-						field_read][0].kount);
-					wake_up_interruptible(&(peasycap->\
-								wq_video));
-					do_gettimeofday(&peasycap->timeval7);
+						JOM(8, "bumped to: %i="\
+							"peasycap->" \
+							"field_fill  %i="\
+							"parity\n", \
+							peasycap->field_fill, \
+							0x00FF & \
+							pfield_buffer->kount);
+						JOM(8, "field buffer %i has "\
+							"%i bytes fit to be "\
+							"read\n", \
+							peasycap->field_read, \
+							videofieldamount);
+						JOM(8, "wakeup call to "\
+							"wq_video, " \
+							"%i=field_read "\
+							"%i=field_fill "\
+							"%i=parity\n", \
+							peasycap->field_read, \
+							peasycap->field_fill, \
+							0x00FF & peasycap->\
+							field_buffer\
+							[peasycap->\
+							field_read][0].kount);
+						wake_up_interruptible\
+							(&(peasycap->\
+								 wq_video));
+						do_gettimeofday\
+							(&peasycap->timeval7);
 					} else {
 					peasycap->video_junk++;
+					if (bad & 0x0010) \
+						peasycap->video_junk += \
+						(1 + VIDEO_JUNK_TOLERATE/2);
 					JOM(8, "field buffer %i had %i " \
-						"bytes, now discarded\n", \
+						"bytes, now discarded: "\
+						"0x%04X\n", \
 						peasycap->field_fill, \
-						videofieldamount);
-
+						videofieldamount,\
+						(0xFF00 & \
+						peasycap->field_buffer\
+						[peasycap->field_fill][0].\
+						kount));
 					(peasycap->field_fill)++;
 
 					if (FIELD_BUFFER_MANY <= \
@@ -2746,6 +3113,8 @@ if (purb->status) {
 						pfield_buffer->kount = 0x0000;
 					else
 						pfield_buffer->kount = 0x0001;
+					pfield_buffer->input = 0x08 | \
+						(0x07 & peasycap->input);
 					JOM(8, "end-of-field: 0x%02X=kount\n",\
 						0xFF & pfield_buffer->kount);
 				}
@@ -2819,18 +3188,19 @@ if (purb->status) {
 /*---------------------------------------------------------------------------*/
 if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
 	SAM("easycap driver shutting down on condition green\n");
+	peasycap->status = 1;
 	peasycap->video_eof = 1;
+	peasycap->video_junk = 0;
+	wake_up_interruptible(&peasycap->wq_video);
+#if !defined(PERSEVERE)
 	peasycap->audio_eof = 1;
-	peasycap->video_junk = -VIDEO_ISOC_BUFFER_MANY;
-	wake_up_interruptible(&(peasycap->wq_video));
-	wake_up_interruptible(&(peasycap->wq_audio));
+	wake_up_interruptible(&peasycap->wq_audio);
+#endif /*PERSEVERE*/
 	return;
 }
 if (peasycap->video_isoc_streaming) {
 	rc = usb_submit_urb(purb, GFP_ATOMIC);
 	if (0 != rc) {
-		SAM("ERROR: while %i=video_idle, usb_submit_urb() failed " \
-					"with rc:\n", peasycap->video_idle);
 		switch (rc) {
 		case -ENOMEM: {
 			SAM("ENOMEM\n"); break;
@@ -2863,6 +3233,11 @@ if (peasycap->video_isoc_streaming) {
 			SAM("0x%08X\n", rc); break;
 		}
 		}
+		if (-ENODEV != rc) \
+			SAM("ERROR: while %i=video_idle, " \
+						"usb_submit_urb() " \
+						"failed with rc:\n", \
+						peasycap->video_idle);
 	}
 }
 return;
@@ -2910,6 +3285,9 @@ int okalt[8], isokalt;
 int okepn[8];
 int okmps[8];
 int maxpacketsize;
+__u16 mask;
+__s32 value;
+struct easycap_format *peasycap_format;
 
 JOT(4, "\n");
 peasycap = (struct easycap *)NULL;
@@ -3056,13 +3434,14 @@ if (0 == bInterfaceNumber) {
 
 	for (dongle_this = 0; dongle_this < DONGLE_MANY; dongle_this++) {
 		if ((struct easycap *)NULL == peasycap_dongle[dongle_this]) {
-			peasycap_dongle[dongle_this] = peasycap;
-			JOM(8, "intf[%i]: peasycap-->easycap" \
+				peasycap_dongle[dongle_this] = peasycap;
+				JOM(8, "intf[%i]: peasycap-->easycap" \
 						"_dongle[%i].peasycap\n", \
 						bInterfaceNumber, dongle_this);
 			break;
 		}
 	}
+
 	if (DONGLE_MANY <= dongle_this) {
 		SAM("ERROR: too many dongles\n");
 		return -ENOMEM;
@@ -3105,7 +3484,7 @@ if (0 == bInterfaceNumber) {
 	peasycap->offerfields = 0;
 /*---------------------------------------------------------------------------*/
 /*
- *  DYNAMICALLY FILL IN THE AVAILABLE FORMATS.
+ *  DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
  */
 /*---------------------------------------------------------------------------*/
 	rc = fillin_formats();
@@ -3114,6 +3493,120 @@ if (0 == bInterfaceNumber) {
 		return -EFAULT;
 	}
 	JOM(4, "%i formats available\n", rc);
+/*---------------------------------------------------------------------------*/
+/*
+ *  ... AND POPULATE easycap.inputset[]
+*/
+/*---------------------------------------------------------------------------*/
+	for (k = 0; k < INPUT_MANY; k++) {
+		peasycap->inputset[k].input_ok = 0;
+		peasycap->inputset[k].standard_offset_ok = 0;
+		peasycap->inputset[k].format_offset_ok = 0;
+		peasycap->inputset[k].brightness_ok = 0;
+		peasycap->inputset[k].contrast_ok = 0;
+		peasycap->inputset[k].saturation_ok = 0;
+		peasycap->inputset[k].hue_ok = 0;
+	}
+	if (true == peasycap->ntsc) {
+		i = 0;
+		m = 0;
+		mask = 0;
+		while (0xFFFF != easycap_standard[i].mask) {
+			if (NTSC_M == easycap_standard[i].\
+							v4l2_standard.index) {
+				m++;
+				for (k = 0; k < INPUT_MANY; k++) {
+					peasycap->inputset[k].\
+							standard_offset = i;
+				}
+			mask = easycap_standard[i].mask;
+			}
+			i++;
+		}
+	} else {
+		i = 0;
+		m = 0;
+		mask = 0;
+		while (0xFFFF != easycap_standard[i].mask) {
+			if (PAL_BGHIN == easycap_standard[i].\
+							v4l2_standard.index) {
+				m++;
+				for (k = 0; k < INPUT_MANY; k++) {
+					peasycap->inputset[k].\
+							standard_offset = i;
+				}
+			mask = easycap_standard[i].mask;
+			}
+			i++;
+		}
+	}
+
+	if (1 != m) {
+		SAM("MISTAKE: easycap.inputset[].standard_offset " \
+						"unpopulated, %i=m\n", m);
+		return -ENOENT;
+	}
+
+	peasycap_format = &easycap_format[0];
+	i = 0;
+	m = 0;
+	while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
+		if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) && \
+				(peasycap_format->\
+					v4l2_format.fmt.pix.field == \
+							V4L2_FIELD_NONE) && \
+				(peasycap_format->\
+					v4l2_format.fmt.pix.pixelformat == \
+							V4L2_PIX_FMT_UYVY) && \
+				(peasycap_format->\
+					v4l2_format.fmt.pix.width  == \
+							640) && \
+				(peasycap_format->\
+					v4l2_format.fmt.pix.height == 480)) {
+			m++;
+			for (k = 0; k < INPUT_MANY; k++)
+				peasycap->inputset[k].format_offset = i;
+			break;
+		}
+	peasycap_format++;
+	i++;
+	}
+	if (1 != m) {
+		SAM("MISTAKE: easycap.inputset[].format_offset unpopulated\n");
+	return -ENOENT;
+	}
+
+	i = 0;
+	m = 0;
+	while (0xFFFFFFFF != easycap_control[i].id) {
+		value = easycap_control[i].default_value;
+		if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
+			m++;
+			for (k = 0; k < INPUT_MANY; k++)
+				peasycap->inputset[k].brightness = value;
+		} else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
+			m++;
+			for (k = 0; k < INPUT_MANY; k++)
+				peasycap->inputset[k].contrast = value;
+		} else if (V4L2_CID_SATURATION == easycap_control[i].id) {
+			m++;
+			for (k = 0; k < INPUT_MANY; k++)
+				peasycap->inputset[k].saturation = value;
+		} else if (V4L2_CID_HUE == easycap_control[i].id) {
+			m++;
+			for (k = 0; k < INPUT_MANY; k++)
+				peasycap->inputset[k].hue = value;
+		}
+		i++;
+	}
+	if (4 != m) {
+		SAM("MISTAKE: easycap.inputset[].brightness,... " \
+						"underpopulated\n");
+		return -ENOENT;
+	}
+	for (k = 0; k < INPUT_MANY; k++)
+		peasycap->inputset[k].input = k;
+	JOM(4, "populated easycap.inputset[]\n");
 	JOM(4, "finished initialization\n");
 } else {
 /*---------------------------------------------------------------------------*/
@@ -4095,15 +4588,16 @@ if (NULL == peasycap) {
 /*---------------------------------------------------------------------------*/
 peasycap->video_eof = 1;
 peasycap->audio_eof = 1;
-wake_up_interruptible(&peasycap->wq_video);
-wake_up_interruptible(&peasycap->wq_audio);
+wake_up_interruptible(&(peasycap->wq_video));
+wake_up_interruptible(&(peasycap->wq_audio));
 /*---------------------------------------------------------------------------*/
 switch (bInterfaceNumber) {
 case 0: {
 	if ((struct list_head *)NULL != peasycap->purb_video_head) {
 		JOM(4, "killing video urbs\n");
 		m = 0;
-		list_for_each(plist_head, (peasycap->purb_video_head)) {
+		list_for_each(plist_head, (peasycap->purb_video_head))
+			{
 			pdata_urb = list_entry(plist_head, \
 					struct data_urb, list_head);
 			if ((struct data_urb *)NULL != pdata_urb) {
@@ -4123,7 +4617,8 @@ case 2: {
 	if ((struct list_head *)NULL != peasycap->purb_audio_head) {
 		JOM(4, "killing audio urbs\n");
 		m = 0;
-		list_for_each(plist_head, (peasycap->purb_audio_head)) {
+		list_for_each(plist_head, \
+					(peasycap->purb_audio_head)) {
 			pdata_urb = list_entry(plist_head, \
 					struct data_urb, list_head);
 			if ((struct data_urb *)NULL != pdata_urb) {
@@ -4149,7 +4644,6 @@ default:
 /*--------------------------------------------------------------------------*/
 switch (bInterfaceNumber) {
 case 0: {
-
 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
 	if ((struct easycap *)NULL == peasycap) {
 		SAM("ERROR: peasycap has become NULL\n");
diff --git a/drivers/staging/easycap/easycap_sound.c b/drivers/staging/easycap/easycap_sound.c
index 2127597..0b4b60b 100644
--- a/drivers/staging/easycap/easycap_sound.c
+++ b/drivers/staging/easycap/easycap_sound.c
@@ -638,11 +638,6 @@ if ((struct usb_device *)NULL == peasycap->pusb_device) {
 	SAM("ERROR: peasycap->pusb_device has become NULL\n");
 	return -EFAULT;
 }
-rc = adjust_volume(peasycap, -8192);
-if (0 != rc) {
-	SAM("ERROR: adjust_volume(default) returned %i\n", rc);
-	return -EFAULT;
-}
 /*---------------------------------------------------------------------------*/
 if ((struct usb_device *)NULL == peasycap->pusb_device) {
 	SAM("ERROR: peasycap->pusb_device has become NULL\n");
@@ -653,26 +648,20 @@ rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \
 JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, \
 					peasycap->audio_altsetting_on, rc);
 
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device has become NULL\n");
-	return -EFAULT;
-}
 rc = wakeup_device(peasycap->pusb_device);
 if (0 == rc)
 	JOM(8, "wakeup_device() returned %i\n", rc);
 else
-	JOM(8, "easysnd open(): ERROR: wakeup_device() returned %i\n", rc);
+	JOM(8, "ERROR: wakeup_device() returned %i\n", rc);
 
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device has become NULL\n");
-	return -EFAULT;
-}
-submit_audio_urbs(peasycap);
+peasycap->audio_eof = 0;
 peasycap->audio_idle = 0;
 
 peasycap->timeval1.tv_sec  = 0;
 peasycap->timeval1.tv_usec = 0;
 
+submit_audio_urbs(peasycap);
+
 JOM(4, "finished initialization\n");
 return 0;
 }
@@ -764,7 +753,6 @@ while ((fragment == (peasycap->audio_fill / \
 		JOM(8, "returning 0 because  %i=audio_eof\n", \
 							peasycap->audio_eof);
 		kill_audio_urbs(peasycap);
-		msleep(500);
 		return 0;
 	}
 	if (peasycap->audio_idle) {
-- 
1.5.6.5






More information about the devel mailing list