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

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
...@@ -135,7 +135,7 @@ ...@@ -135,7 +135,7 @@
#define USB_EASYCAP_VENDOR_ID 0x05e1 #define USB_EASYCAP_VENDOR_ID 0x05e1
#define USB_EASYCAP_PRODUCT_ID 0x0408 #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 EASYCAP_DRIVER_DESCRIPTION "easycapdc60"
#define USB_SKEL_MINOR_BASE 192 #define USB_SKEL_MINOR_BASE 192
......
...@@ -1985,10 +1985,17 @@ case SNDCTL_DSP_GETCAPS: { ...@@ -1985,10 +1985,17 @@ case SNDCTL_DSP_GETCAPS: {
int caps; int caps;
JOT(8, "SNDCTL_DSP_GETCAPS\n"); JOT(8, "SNDCTL_DSP_GETCAPS\n");
#if defined(UPSAMPLE)
if (true == peasycap->microphone)
caps = 0x04400000;
else
caps = 0x04400000;
#else
if (true == peasycap->microphone) if (true == peasycap->microphone)
caps = 0x02400000; caps = 0x02400000;
else else
caps = 0x04400000; caps = 0x04400000;
#endif /*UPSAMPLE*/
if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int)))
return -EFAULT; return -EFAULT;
...@@ -1998,10 +2005,17 @@ case SNDCTL_DSP_GETFMTS: { ...@@ -1998,10 +2005,17 @@ case SNDCTL_DSP_GETFMTS: {
int incoming; int incoming;
JOT(8, "SNDCTL_DSP_GETFMTS\n"); 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) if (true == peasycap->microphone)
incoming = AFMT_S16_LE; incoming = AFMT_S16_LE;
else else
incoming = AFMT_S16_LE; incoming = AFMT_S16_LE;
#endif /*UPSAMPLE*/
if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int)))
return -EFAULT; return -EFAULT;
...@@ -2014,10 +2028,17 @@ case SNDCTL_DSP_SETFMT: { ...@@ -2014,10 +2028,17 @@ case SNDCTL_DSP_SETFMT: {
return -EFAULT; return -EFAULT;
JOT(8, "........... %i=incoming\n", incoming); JOT(8, "........... %i=incoming\n", incoming);
#if defined(UPSAMPLE)
if (true == peasycap->microphone) if (true == peasycap->microphone)
outgoing = AFMT_S16_LE; outgoing = AFMT_S16_LE;
else else
outgoing = AFMT_S16_LE; outgoing = AFMT_S16_LE;
#else
if (true == peasycap->microphone)
outgoing = AFMT_S16_LE;
else
outgoing = AFMT_S16_LE;
#endif /*UPSAMPLE*/
if (incoming != outgoing) { if (incoming != outgoing) {
JOT(8, "........... %i=outgoing\n", outgoing); JOT(8, "........... %i=outgoing\n", outgoing);
...@@ -2037,10 +2058,17 @@ case SNDCTL_DSP_STEREO: { ...@@ -2037,10 +2058,17 @@ case SNDCTL_DSP_STEREO: {
return -EFAULT; return -EFAULT;
JOT(8, "........... %i=incoming\n", incoming); JOT(8, "........... %i=incoming\n", incoming);
#if defined(UPSAMPLE)
if (true == peasycap->microphone)
incoming = 1;
else
incoming = 1;
#else
if (true == peasycap->microphone) if (true == peasycap->microphone)
incoming = 0; incoming = 0;
else else
incoming = 1; incoming = 1;
#endif /*UPSAMPLE*/
if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int)))
return -EFAULT; return -EFAULT;
...@@ -2053,10 +2081,17 @@ case SNDCTL_DSP_SPEED: { ...@@ -2053,10 +2081,17 @@ case SNDCTL_DSP_SPEED: {
return -EFAULT; return -EFAULT;
JOT(8, "........... %i=incoming\n", incoming); JOT(8, "........... %i=incoming\n", incoming);
#if defined(UPSAMPLE)
if (true == peasycap->microphone)
incoming = 32000;
else
incoming = 48000;
#else
if (true == peasycap->microphone) if (true == peasycap->microphone)
incoming = 8000; incoming = 8000;
else else
incoming = 48000; incoming = 48000;
#endif /*UPSAMPLE*/
if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int)))
return -EFAULT; return -EFAULT;
......
...@@ -827,7 +827,7 @@ static __u16 index = 0x0301; ...@@ -827,7 +827,7 @@ static __u16 index = 0x0301;
static unsigned char buffer[1]; static unsigned char buffer[1];
static __u16 length = 1; static __u16 length = 1;
int rc; int rc, id1, id2;
if (NULL == peasycap) if (NULL == peasycap)
return -EFAULT; return -EFAULT;
...@@ -883,46 +883,30 @@ SET(pusb_device, 0x0500, 0x008C); ...@@ -883,46 +883,30 @@ SET(pusb_device, 0x0500, 0x008C);
SET(pusb_device, 0x0506, 0x0001); SET(pusb_device, 0x0506, 0x0001);
SET(pusb_device, 0x0507, 0x0000); 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 0dB.
*/ /*---------------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/ /*
write_vt(pusb_device, 0x0002, 0x8000); * SELECT AUDIO SOURCE "LINE IN" AND SET DEFAULT GAIN TO 0 dB.
write_vt(pusb_device, 0x001C, 0x8000); *
* THESE COMMANDS SEEM TO BE ACCEPTED (THOUGH POSSIBLY IGNORED) EVEN WHEN
write_vt(pusb_device, 0x000E, 0x0000); * THERE IS NO SEPARATE AUDIO CHIP PRESENT.
write_vt(pusb_device, 0x0010, 0x0000); */
write_vt(pusb_device, 0x0012, 0x8000); /*---------------------------------------------------------------------------*/
write_vt(pusb_device, 0x0016, 0x0000);
write_vt(pusb_device, 0x0002, 0x8000);
write_vt(pusb_device, 0x001A, 0x0404); write_vt(pusb_device, 0x001C, 0x8000);
write_vt(pusb_device, 0x0002, 0x0000);
write_vt(pusb_device, 0x001C, 0x0000); write_vt(pusb_device, 0x000E, 0x0000);
} else { write_vt(pusb_device, 0x0010, 0x0000);
/*-------------------------------------------------------------------*/ write_vt(pusb_device, 0x0012, 0x8000);
/* write_vt(pusb_device, 0x0016, 0x0000);
* SELECT AUDIO SOURCE "MIC" AND SET DEFAULT GAIN TO 0 dB.
* write_vt(pusb_device, 0x001A, 0x0404);
* REGISTER 0x000E CAN BE SET TO PROVIDE UP TO 34.5 dB ATTENTUATION, write_vt(pusb_device, 0x0002, 0x0000);
* BUT THIS HAS NOT PROVED NECESSARY FOR THE FEW SIGNAL SOURCES write_vt(pusb_device, 0x001C, 0x0000);
* 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); check_vt(pusb_device);
......
...@@ -2490,6 +2490,10 @@ if (peasycap->video_idle) { ...@@ -2490,6 +2490,10 @@ if (peasycap->video_idle) {
SAY("EMSGSIZE\n"); SAY("EMSGSIZE\n");
break; break;
} }
case -ENOSPC: {
SAY("ENOSPC\n");
break;
}
default: { default: {
SAY("0x%08X\n", rc); SAY("0x%08X\n", rc);
break; break;
...@@ -2571,6 +2575,9 @@ if (purb->status) { ...@@ -2571,6 +2575,9 @@ if (purb->status) {
case -ECONNRESET: { case -ECONNRESET: {
SAY("-ECONNRESET\n"); break; SAY("-ECONNRESET\n"); break;
} }
case -ENOSPC: {
SAY("ENOSPC\n"); break;
}
default: { default: {
SAY("unknown error code 0x%08X\n", purb->status); break; SAY("unknown error code 0x%08X\n", purb->status); break;
} }
...@@ -2630,6 +2637,9 @@ if (purb->status) { ...@@ -2630,6 +2637,9 @@ if (purb->status) {
case -ECONNRESET: { case -ECONNRESET: {
strcpy(&errbuf[0], "-ECONNRESET"); break; strcpy(&errbuf[0], "-ECONNRESET"); break;
} }
case -ENOSPC: {
SAY("ENOSPC\n"); break;
}
case -ESHUTDOWN: { case -ESHUTDOWN: {
strcpy(&errbuf[0], "-ESHUTDOWN"); break; strcpy(&errbuf[0], "-ESHUTDOWN"); break;
} }
...@@ -2949,6 +2959,9 @@ if (peasycap->video_isoc_streaming) { ...@@ -2949,6 +2959,9 @@ if (peasycap->video_isoc_streaming) {
case -EMSGSIZE: { case -EMSGSIZE: {
SAY("EMSGSIZE\n"); break; SAY("EMSGSIZE\n"); break;
} }
case -ENOSPC: {
SAY("ENOSPC\n"); break;
}
default: { default: {
SAY("0x%08X\n", rc); break; SAY("0x%08X\n", rc); break;
} }
...@@ -3861,7 +3874,7 @@ case 2: { ...@@ -3861,7 +3874,7 @@ case 2: {
peasycap->ilk |= 0x02; peasycap->ilk |= 0x02;
SAY("hardware is FOUR-CVBS\n"); SAY("hardware is FOUR-CVBS\n");
peasycap->microphone = true; peasycap->microphone = true;
peasycap->audio_pages_per_fragment = 2; peasycap->audio_pages_per_fragment = 4;
} else if (256 == peasycap->audio_isoc_maxframesize) { } else if (256 == peasycap->audio_isoc_maxframesize) {
peasycap->ilk &= ~0x02; peasycap->ilk &= ~0x02;
SAY("hardware is CVBS+S-VIDEO\n"); SAY("hardware is CVBS+S-VIDEO\n");
......
...@@ -50,6 +50,10 @@ char errbuf[16]; ...@@ -50,6 +50,10 @@ char errbuf[16];
__u8 *p1, *p2; __u8 *p1, *p2;
__s16 s16; __s16 s16;
int i, j, more, much, leap, rc; int i, j, more, much, leap, rc;
#if defined(UPSAMPLE)
int k;
__s16 oldaudio, newaudio, delta;
#endif /*UPSAMPLE*/
JOT(16, "\n"); JOT(16, "\n");
...@@ -99,6 +103,9 @@ if (peasycap->audio_idle) { ...@@ -99,6 +103,9 @@ if (peasycap->audio_idle) {
case -EMSGSIZE: { case -EMSGSIZE: {
SAY("EMSGSIZE\n"); break; SAY("EMSGSIZE\n"); break;
} }
case -ENOSPC: {
SAY("ENOSPC\n"); break;
}
default: { default: {
SAY("0x%08X\n", rc); break; SAY("0x%08X\n", rc); break;
} }
...@@ -172,6 +179,9 @@ if (purb->status) { ...@@ -172,6 +179,9 @@ if (purb->status) {
case -ECONNRESET: { case -ECONNRESET: {
SAY("-ECONNRESET\n"); break; SAY("-ECONNRESET\n"); break;
} }
case -ENOSPC: {
SAY("ENOSPC\n"); break;
}
default: { default: {
SAY("unknown error code 0x%08X\n", purb->status); break; SAY("unknown error code 0x%08X\n", purb->status); break;
} }
...@@ -226,6 +236,10 @@ if (purb->status) { ...@@ -226,6 +236,10 @@ if (purb->status) {
* PROCEED HERE WHEN NO ERROR * PROCEED HERE WHEN NO ERROR
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if defined(UPSAMPLE)
oldaudio = peasycap->oldaudio;
#endif /*UPSAMPLE*/
for (i = 0; i < purb->number_of_packets; i++) { for (i = 0; i < purb->number_of_packets; i++) {
switch (purb->iso_frame_desc[i].status) { switch (purb->iso_frame_desc[i].status) {
case 0: { case 0: {
...@@ -276,6 +290,9 @@ for (i = 0; i < purb->number_of_packets; i++) { ...@@ -276,6 +290,9 @@ for (i = 0; i < purb->number_of_packets; i++) {
case -ECONNRESET: { case -ECONNRESET: {
strcpy(&errbuf[0], "-ECONNRESET"); break; strcpy(&errbuf[0], "-ECONNRESET"); break;
} }
case -ENOSPC: {
strcpy(&errbuf[0], "-ENOSPC"); break;
}
case -ESHUTDOWN: { case -ESHUTDOWN: {
strcpy(&errbuf[0], "-ESHUTDOWN"); break; strcpy(&errbuf[0], "-ESHUTDOWN"); break;
} }
...@@ -318,7 +335,7 @@ for (i = 0; i < purb->number_of_packets; i++) { ...@@ -318,7 +335,7 @@ for (i = 0; i < purb->number_of_packets; i++) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* COPY more BYTES FROM ISOC BUFFER TO AUDIO BUFFER, * 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) { while (more) {
...@@ -386,8 +403,6 @@ for (i = 0; i < purb->number_of_packets; i++) { ...@@ -386,8 +403,6 @@ for (i = 0; i < purb->number_of_packets; i++) {
much = PAGE_SIZE - (int)(paudio_buffer->pto -\ much = PAGE_SIZE - (int)(paudio_buffer->pto -\
paudio_buffer->pgo); paudio_buffer->pgo);
if (much % 2)
JOT(8, "MISTAKE? much is odd\n");
if (false == peasycap->microphone) { if (false == peasycap->microphone) {
if (much > more) if (much > more)
...@@ -397,17 +412,57 @@ for (i = 0; i < purb->number_of_packets; i++) { ...@@ -397,17 +412,57 @@ for (i = 0; i < purb->number_of_packets; i++) {
p1 += much; p1 += much;
more -= much; more -= much;
} else { } 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)) if (much > (2 * more))
much = 2 * more; much = 2 * more;
p2 = (__u8 *)paudio_buffer->pto; p2 = (__u8 *)paudio_buffer->pto;
for (j = 0; j < (much / 2); j++) { for (j = 0; j < (much / 2); j++) {
s16 = ((int) *p1) - 128; s16 = ((int) *p1) - 128;
*p2 = (0xFF00 & s16) >> 8; s16 = 128 * \
*(p2 + 1) = (0x00FF & s16); s16;
*p2 = (0x00FF & s16);
*(p2 + 1) = (0xFF00 & s16) >> \
8;
p1++; p2 += 2; p1++; p2 += 2;
more--; more--;
} }
#endif /*UPSAMPLE*/
} }
(paudio_buffer->pto) += much; (paudio_buffer->pto) += much;
} }
...@@ -417,6 +472,11 @@ for (i = 0; i < purb->number_of_packets; i++) { ...@@ -417,6 +472,11 @@ for (i = 0; i < purb->number_of_packets; i++) {
"%i=purb->iso_frame_desc[i].status\n", \ "%i=purb->iso_frame_desc[i].status\n", \
purb->iso_frame_desc[i].status); purb->iso_frame_desc[i].status);
} }
#if defined(UPSAMPLE)
peasycap->oldaudio = oldaudio;
#endif /*UPSAMPLE*/
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
...@@ -453,6 +513,9 @@ if (peasycap->audio_isoc_streaming) { ...@@ -453,6 +513,9 @@ if (peasycap->audio_isoc_streaming) {
case -EMSGSIZE: { case -EMSGSIZE: {
SAY("EMSGSIZE\n"); break; SAY("EMSGSIZE\n"); break;
} }
case -ENOSPC: {
SAY("ENOSPC\n"); break;
}
default: { default: {
SAY("0x%08X\n", rc); break; SAY("0x%08X\n", rc); break;
} }
...@@ -764,7 +827,7 @@ if (peasycap->audio_sample) { ...@@ -764,7 +827,7 @@ if (peasycap->audio_sample) {
mean = peasycap->audio_niveau; mean = peasycap->audio_niveau;
sdr = signed_div(mean, peasycap->audio_sample); 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.quotient, above, peasycap->audio_sample);
sdr = signed_div(above, 32768); sdr = signed_div(above, 32768);
...@@ -902,6 +965,9 @@ if (!peasycap->audio_isoc_streaming) { ...@@ -902,6 +965,9 @@ if (!peasycap->audio_isoc_streaming) {
case -EMSGSIZE: { case -EMSGSIZE: {
SAY("EMSGSIZE\n"); break; SAY("EMSGSIZE\n"); break;
} }
case -ENOSPC: {
SAY("ENOSPC\n"); break;
}
default: { default: {
SAY("unknown error code %i\n",\ SAY("unknown error code %i\n",\
rc); break; rc); break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment