Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7ebc8760 authored by Mike Thomas's avatar Mike Thomas Committed by Greg Kroah-Hartman
Browse files

Staging: easycap: Upsample microphone audio



Upsampling from 8000 Hz mono to 32000 Hz stereo improves audio/video
synchronization when userspace programs adopt default buffering.  This
is an experimental feature.

Signed-off-by: default avatarMike Thomas <rmthomas@sciolus.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 3d423e91
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -135,7 +135,7 @@
#define USB_EASYCAP_VENDOR_ID	0x05e1
#define USB_EASYCAP_PRODUCT_ID	0x0408

#define EASYCAP_DRIVER_VERSION "0.8.2"
#define EASYCAP_DRIVER_VERSION "0.8.21"
#define EASYCAP_DRIVER_DESCRIPTION "easycapdc60"

#define USB_SKEL_MINOR_BASE     192
+35 −0
Original line number Diff line number Diff line
@@ -1985,10 +1985,17 @@ case SNDCTL_DSP_GETCAPS: {
	int caps;
	JOT(8, "SNDCTL_DSP_GETCAPS\n");

#if defined(UPSAMPLE)
	if (true == peasycap->microphone)
		caps = 0x04400000;
	else
		caps = 0x04400000;
#else
	if (true == peasycap->microphone)
		caps = 0x02400000;
	else
		caps = 0x04400000;
#endif /*UPSAMPLE*/

	if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int)))
		return -EFAULT;
@@ -1998,10 +2005,17 @@ case SNDCTL_DSP_GETFMTS: {
	int incoming;
	JOT(8, "SNDCTL_DSP_GETFMTS\n");

#if defined(UPSAMPLE)
	if (true == peasycap->microphone)
		incoming = AFMT_S16_LE;
	else
		incoming = AFMT_S16_LE;
#else
	if (true == peasycap->microphone)
		incoming = AFMT_S16_LE;
	else
		incoming = AFMT_S16_LE;
#endif /*UPSAMPLE*/

	if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int)))
		return -EFAULT;
@@ -2014,10 +2028,17 @@ case SNDCTL_DSP_SETFMT: {
		return -EFAULT;
	JOT(8, "........... %i=incoming\n", incoming);

#if defined(UPSAMPLE)
	if (true == peasycap->microphone)
		outgoing = AFMT_S16_LE;
	else
		outgoing = AFMT_S16_LE;
#else
	if (true == peasycap->microphone)
		outgoing = AFMT_S16_LE;
	else
		outgoing = AFMT_S16_LE;
#endif /*UPSAMPLE*/

	if (incoming != outgoing) {
		JOT(8, "........... %i=outgoing\n", outgoing);
@@ -2037,10 +2058,17 @@ case SNDCTL_DSP_STEREO: {
		return -EFAULT;
	JOT(8, "........... %i=incoming\n", incoming);

#if defined(UPSAMPLE)
	if (true == peasycap->microphone)
		incoming = 1;
	else
		incoming = 1;
#else
	if (true == peasycap->microphone)
		incoming = 0;
	else
		incoming = 1;
#endif /*UPSAMPLE*/

	if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int)))
		return -EFAULT;
@@ -2053,10 +2081,17 @@ case SNDCTL_DSP_SPEED: {
		return -EFAULT;
	JOT(8, "........... %i=incoming\n", incoming);

#if defined(UPSAMPLE)
	if (true == peasycap->microphone)
		incoming = 32000;
	else
		incoming = 48000;
#else
	if (true == peasycap->microphone)
		incoming = 8000;
	else
		incoming = 48000;
#endif /*UPSAMPLE*/

	if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int)))
		return -EFAULT;
+25 −41
Original line number Diff line number Diff line
@@ -827,7 +827,7 @@ static __u16 index = 0x0301;

static unsigned char buffer[1];
static __u16 length = 1;
int rc;
int rc, id1, id2;

if (NULL == peasycap)
	return -EFAULT;
@@ -883,12 +883,19 @@ SET(pusb_device, 0x0500, 0x008C);
SET(pusb_device, 0x0506, 0x0001);
SET(pusb_device, 0x0507, 0x0000);

if (false == peasycap->microphone) {
	/*-------------------------------------------------------------------*/
id1 = read_vt(pusb_device, 0x007C);
id2 = read_vt(pusb_device, 0x007E);
SAY("0x%04X:0x%04X is audio vendor id\n", id1, id2);

/*---------------------------------------------------------------------------*/
/*
*   SELECT AUDIO SOURCE "LINE IN" AND SET DEFAULT GAIN TO 0 dB.
*
*   THESE COMMANDS SEEM TO BE ACCEPTED (THOUGH POSSIBLY IGNORED) EVEN WHEN
*   THERE IS NO SEPARATE AUDIO CHIP PRESENT.
*/
	/*-------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/

write_vt(pusb_device, 0x0002, 0x8000);
write_vt(pusb_device, 0x001C, 0x8000);

@@ -900,29 +907,6 @@ if (false == peasycap->microphone) {
write_vt(pusb_device, 0x001A, 0x0404);
write_vt(pusb_device, 0x0002, 0x0000);
write_vt(pusb_device, 0x001C, 0x0000);
} else {
	/*-------------------------------------------------------------------*/
	/*
	*   SELECT AUDIO SOURCE "MIC" AND SET DEFAULT GAIN TO 0 dB.
	*
	*   REGISTER 0x000E CAN BE SET TO PROVIDE UP TO 34.5 dB ATTENTUATION,
	*   BUT THIS HAS NOT PROVED NECESSARY FOR THE FEW SIGNAL SOURCES
	*   TESTED HITHERTO.
	*/
	/*-------------------------------------------------------------------*/
	write_vt(pusb_device, 0x0006, 0x8000);
	write_vt(pusb_device, 0x001C, 0x8000);

	write_vt(pusb_device, 0x000E, 0x0008);

	write_vt(pusb_device, 0x0010, 0x0000);
	write_vt(pusb_device, 0x0012, 0x8000);
	write_vt(pusb_device, 0x0016, 0x0000);

	write_vt(pusb_device, 0x001A, 0x0000);
	write_vt(pusb_device, 0x0006, 0x0000);
	write_vt(pusb_device, 0x001C, 0x0000);
}

check_vt(pusb_device);

+14 −1
Original line number Diff line number Diff line
@@ -2490,6 +2490,10 @@ if (peasycap->video_idle) {
				SAY("EMSGSIZE\n");
				break;
			}
			case -ENOSPC: {
				SAY("ENOSPC\n");
				break;
			}
			default: {
				SAY("0x%08X\n", rc);
				break;
@@ -2571,6 +2575,9 @@ if (purb->status) {
	case -ECONNRESET: {
		SAY("-ECONNRESET\n"); break;
	}
	case -ENOSPC: {
		SAY("ENOSPC\n"); break;
	}
	default: {
		SAY("unknown error code 0x%08X\n", purb->status); break;
	}
@@ -2630,6 +2637,9 @@ if (purb->status) {
			case -ECONNRESET: {
				strcpy(&errbuf[0], "-ECONNRESET"); break;
			}
			case -ENOSPC: {
				SAY("ENOSPC\n"); break;
			}
			case -ESHUTDOWN: {
				strcpy(&errbuf[0], "-ESHUTDOWN"); break;
			}
@@ -2949,6 +2959,9 @@ if (peasycap->video_isoc_streaming) {
		case -EMSGSIZE: {
			SAY("EMSGSIZE\n");  break;
		}
		case -ENOSPC: {
			SAY("ENOSPC\n"); break;
		}
		default: {
			SAY("0x%08X\n", rc); break;
		}
@@ -3861,7 +3874,7 @@ case 2: {
			peasycap->ilk |= 0x02;
			SAY("hardware is FOUR-CVBS\n");
			peasycap->microphone = true;
			peasycap->audio_pages_per_fragment = 2;
			peasycap->audio_pages_per_fragment = 4;
		} else if (256 == peasycap->audio_isoc_maxframesize) {
			peasycap->ilk &= ~0x02;
			SAY("hardware is CVBS+S-VIDEO\n");
+72 −6
Original line number Diff line number Diff line
@@ -50,6 +50,10 @@ char errbuf[16];
__u8 *p1, *p2;
__s16 s16;
int i, j, more, much, leap, rc;
#if defined(UPSAMPLE)
int k;
__s16 oldaudio, newaudio, delta;
#endif /*UPSAMPLE*/

JOT(16, "\n");

@@ -99,6 +103,9 @@ if (peasycap->audio_idle) {
			case -EMSGSIZE: {
				SAY("EMSGSIZE\n");  break;
			}
			case -ENOSPC: {
				SAY("ENOSPC\n");  break;
			}
			default: {
				SAY("0x%08X\n", rc); break;
			}
@@ -172,6 +179,9 @@ if (purb->status) {
	case -ECONNRESET: {
		SAY("-ECONNRESET\n"); break;
	}
	case -ENOSPC: {
		SAY("ENOSPC\n");  break;
	}
	default: {
		SAY("unknown error code 0x%08X\n", purb->status); break;
	}
@@ -226,6 +236,10 @@ if (purb->status) {
 *  PROCEED HERE WHEN NO ERROR
 */
/*---------------------------------------------------------------------------*/
#if defined(UPSAMPLE)
oldaudio = peasycap->oldaudio;
#endif /*UPSAMPLE*/

for (i = 0;  i < purb->number_of_packets; i++) {
	switch (purb->iso_frame_desc[i].status) {
	case  0: {
@@ -276,6 +290,9 @@ for (i = 0; i < purb->number_of_packets; i++) {
	case -ECONNRESET: {
		strcpy(&errbuf[0], "-ECONNRESET"); break;
	}
	case -ENOSPC: {
		strcpy(&errbuf[0], "-ENOSPC"); break;
	}
	case -ESHUTDOWN: {
		strcpy(&errbuf[0], "-ESHUTDOWN"); break;
	}
@@ -318,7 +335,7 @@ for (i = 0; i < purb->number_of_packets; i++) {
/*---------------------------------------------------------------------------*/
/*
 *  COPY more BYTES FROM ISOC BUFFER TO AUDIO BUFFER,
 *  CONVERTING 8-BIT SAMPLES TO 16-BIT SIGNED LITTLE-ENDED SAMPLES IF NECESSARY
 *  CONVERTING 8-BIT MONO TO 16-BIT SIGNED LITTLE-ENDIAN SAMPLES IF NECESSARY
 */
/*---------------------------------------------------------------------------*/
			while (more) {
@@ -386,8 +403,6 @@ for (i = 0; i < purb->number_of_packets; i++) {

				much = PAGE_SIZE - (int)(paudio_buffer->pto -\
							 paudio_buffer->pgo);
				if (much % 2)
					JOT(8, "MISTAKE?  much is odd\n");

				if (false == peasycap->microphone) {
					if (much > more)
@@ -397,17 +412,57 @@ for (i = 0; i < purb->number_of_packets; i++) {
					p1 += much;
					more -= much;
				} else {
#if defined(UPSAMPLE)
					if (much % 16)
						JOT(8, "MISTAKE? much" \
						" is not divisible by 16\n");
					if (much > (16 * \
							more))
						much = 16 * \
							more;
					p2 = (__u8 *)paudio_buffer->pto;

					for (j = 0;  j < (much/16);  j++) {
						newaudio =  ((int) *p1) - 128;
						newaudio = 128 * \
								newaudio;

						delta = (newaudio - oldaudio) \
									/ 4;
						s16 = oldaudio + delta;

						for (k = 0;  k < 4;  k++) {
							*p2 = (0x00FF & s16);
							*(p2 + 1) = (0xFF00 & \
								s16) >> 8;
							p2 += 2;
							*p2 = (0x00FF & s16);
							*(p2 + 1) = (0xFF00 & \
								s16) >> 8;
							p2 += 2;

							s16 += delta;
						}
						p1++;
						more--;
						oldaudio = s16;
					}
#else
					if (much > (2 * more))
						much = 2 * more;
					p2 = (__u8 *)paudio_buffer->pto;

					for (j = 0;  j < (much / 2);  j++) {
						s16 =  ((int) *p1) - 128;
						*p2      = (0xFF00 & s16) >> 8;
						*(p2 + 1) = (0x00FF & s16);
						s16 = 128 * \
								s16;
						*p2 = (0x00FF & s16);
						*(p2 + 1) = (0xFF00 & s16) >> \
									8;
						p1++;  p2 += 2;
						more--;
					}
#endif /*UPSAMPLE*/
				}
				(paudio_buffer->pto) += much;
			}
@@ -417,6 +472,11 @@ for (i = 0; i < purb->number_of_packets; i++) {
			"%i=purb->iso_frame_desc[i].status\n", \
				purb->iso_frame_desc[i].status);
	}

#if defined(UPSAMPLE)
peasycap->oldaudio = oldaudio;
#endif /*UPSAMPLE*/

}
/*---------------------------------------------------------------------------*/
/*
@@ -453,6 +513,9 @@ if (peasycap->audio_isoc_streaming) {
		case -EMSGSIZE: {
			SAY("EMSGSIZE\n");  break;
		}
		case -ENOSPC: {
			SAY("ENOSPC\n");  break;
		}
		default: {
			SAY("0x%08X\n", rc); break;
		}
@@ -764,7 +827,7 @@ if (peasycap->audio_sample) {
	mean = peasycap->audio_niveau;
	sdr = signed_div(mean, peasycap->audio_sample);

	JOT(12, "%8lli=mean  %8lli=meansquare after %lli samples, =>\n", \
	JOT(8, "%8lli=mean  %8lli=meansquare after %lli samples, =>\n", \
				sdr.quotient, above, peasycap->audio_sample);

	sdr = signed_div(above, 32768);
@@ -902,6 +965,9 @@ if (!peasycap->audio_isoc_streaming) {
					case -EMSGSIZE: {
						SAY("EMSGSIZE\n"); break;
					}
					case -ENOSPC: {
						SAY("ENOSPC\n"); break;
					}
					default: {
						SAY("unknown error code %i\n",\
								 rc); break;