Преглед изворни кода

staging/easycap: Improve hardware initialization

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@sciolus.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Mike Thomas пре 14 година
родитељ
комит
f36bc37a48

+ 36 - 11
drivers/staging/easycap/easycap.h

@@ -42,12 +42,19 @@
 #if (!defined(EASYCAP_H))
 #define EASYCAP_H
 
+/*---------------------------------------------------------------------------*/
+/*
+ *  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 *);

+ 251 - 110
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;

+ 414 - 261
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;
-}
-/*****************************************************************************/

Разлика између датотеке није приказан због своје велике величине
+ 634 - 141
drivers/staging/easycap/easycap_main.c


+ 4 - 16
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) {

Неке датотеке нису приказане због велике количине промена