Commit 94155cf4 authored by Mike Thomas's avatar Mike Thomas Committed by Greg Kroah-Hartman

staging/easycap: Add option to set the hardware audio gain

A new module parameter adjusts the gain of the AC'97 audio chip, if
one is present.  Attenuation as well as amplification should be possible
according to the datasheet, but attenuation seems not to work yet.
Signed-off-by: default avatarMike Thomas <rmthomas@sciolus.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 849322a0
...@@ -25,3 +25,4 @@ ...@@ -25,3 +25,4 @@
*/ */
/*****************************************************************************/ /*****************************************************************************/
extern int debug; extern int debug;
extern int gain;
...@@ -873,18 +873,26 @@ i1 = 0; ...@@ -873,18 +873,26 @@ i1 = 0;
while (0xFFFFFFFF != easycap_control[i1].id) { while (0xFFFFFFFF != easycap_control[i1].id) {
if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) { if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) {
if ((easycap_control[i1].minimum > value) || \ if ((easycap_control[i1].minimum > value) || \
(easycap_control[i1].maximum < value)) (easycap_control[i1].maximum < value))
value = easycap_control[i1].default_value; value = easycap_control[i1].default_value;
if ((easycap_control[i1].minimum <= peasycap->volume) && \
(easycap_control[i1].maximum >= \
peasycap->volume)) {
if (peasycap->volume == value) {
SAM("unchanged volume at 0x%02X\n", value);
return 0;
}
}
peasycap->volume = value; peasycap->volume = value;
mood = (16 > peasycap->volume) ? 16 : \ mood = (16 > peasycap->volume) ? 16 : \
((31 < peasycap->volume) ? 31 : \ ((31 < peasycap->volume) ? 31 : \
(__s8) peasycap->volume); (__s8) peasycap->volume);
if (!audio_gainset(peasycap->pusb_device, mood)) { if (!audio_gainset(peasycap->pusb_device, mood)) {
SAM("adjusting volume to 0x%01X\n", mood); SAM("adjusting volume to 0x%02X\n", mood);
return 0; return 0;
} else { } else {
SAM("WARNING: failed to adjust volume to " \ SAM("WARNING: failed to adjust volume to " \
"0x%1X\n", mood); "0x%2X\n", mood);
return -ENOENT; return -ENOENT;
} }
break; break;
......
...@@ -988,9 +988,9 @@ if (NULL == peasycap) ...@@ -988,9 +988,9 @@ if (NULL == peasycap)
pusb_device = peasycap->pusb_device; pusb_device = peasycap->pusb_device;
if (NULL == pusb_device) if (NULL == pusb_device)
return -EFAULT; return -ENODEV;
JOT(8, "%02X %02X %02X %02X %02X %02X %02X %02X\n", \ JOM(8, "%02X %02X %02X %02X %02X %02X %02X %02X\n", \
requesttype, request, \ requesttype, request, \
(0x00FF & value_unmute), \ (0x00FF & value_unmute), \
(0xFF00 & value_unmute) >> 8, \ (0xFF00 & value_unmute) >> 8, \
...@@ -1029,41 +1029,25 @@ if (rc != (int)length) ...@@ -1029,41 +1029,25 @@ if (rc != (int)length)
* THE UPPER BYTE SEEMS TO HAVE NO EFFECT. * THE UPPER BYTE SEEMS TO HAVE NO EFFECT.
*/ */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
SET(pusb_device, 0x0500, 0x0094); SET(pusb_device, 0x0500, 0x0094);
SET(pusb_device, 0x0500, 0x008C); 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);
id1 = read_vt(pusb_device, 0x007C); id1 = read_vt(pusb_device, 0x007C);
id2 = read_vt(pusb_device, 0x007E); id2 = read_vt(pusb_device, 0x007E);
SAY("0x%04X:0x%04X is audio vendor id\n", id1, id2); SAM("0x%04X:0x%04X is audio vendor id\n", id1, id2);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* SELECT AUDIO SOURCE "LINE IN" AND SET DEFAULT GAIN TO 0 dB. * SELECT AUDIO SOURCE "LINE IN" AND SET THE AUDIO GAIN.
*
* THESE COMMANDS SEEM TO BE ACCEPTED (THOUGH POSSIBLY IGNORED) EVEN WHEN
* THERE IS NO SEPARATE AUDIO CHIP PRESENT.
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
if (31 < gain)
write_vt(pusb_device, 0x0002, 0x8000); gain = 31;
write_vt(pusb_device, 0x001C, 0x8000); if (0 > gain)
gain = 0;
write_vt(pusb_device, 0x000E, 0x0000); if (0 != audio_gainset(pusb_device, (__s8)gain))
write_vt(pusb_device, 0x0010, 0x0000); SAY("ERROR: audio_gainset() failed\n");
write_vt(pusb_device, 0x0012, 0x8000);
write_vt(pusb_device, 0x0016, 0x0000);
write_vt(pusb_device, 0x001A, 0x0404);
write_vt(pusb_device, 0x0002, 0x0000);
write_vt(pusb_device, 0x001C, 0x0000);
check_vt(pusb_device); check_vt(pusb_device);
return 0; return 0;
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -1096,17 +1080,23 @@ if (0 > igot) ...@@ -1096,17 +1080,23 @@ if (0 > igot)
if (0x8000 & igot) if (0x8000 & igot)
SAY("register 0x%02X muted\n", 0x12); SAY("register 0x%02X muted\n", 0x12);
igot = read_vt(pusb_device, 0x0014);
if (0 > igot)
SAY("ERROR: failed to read VT1612A register 0x14\n");
if (0x8000 & igot)
SAY("register 0x%02X muted\n", 0x14);
igot = read_vt(pusb_device, 0x0016); igot = read_vt(pusb_device, 0x0016);
if (0 > igot) if (0 > igot)
SAY("ERROR: failed to read VT1612A register 0x16\n"); SAY("ERROR: failed to read VT1612A register 0x16\n");
if (0x8000 & igot) if (0x8000 & igot)
SAY("register 0x%02X muted\n", 0x16); SAY("register 0x%02X muted\n", 0x16);
igot = read_vt(pusb_device, 0x001A); igot = read_vt(pusb_device, 0x0018);
if (0 > igot) if (0 > igot)
SAY("ERROR: failed to read VT1612A register 0x1A\n"); SAY("ERROR: failed to read VT1612A register 0x18\n");
if (0x8000 & igot) if (0x8000 & igot)
SAY("register 0x%02X muted\n", 0x1A); SAY("register 0x%02X muted\n", 0x18);
igot = read_vt(pusb_device, 0x001C); igot = read_vt(pusb_device, 0x001C);
if (0 > igot) if (0 > igot)
...@@ -1118,14 +1108,18 @@ return 0; ...@@ -1118,14 +1108,18 @@ return 0;
} }
/*****************************************************************************/ /*****************************************************************************/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /* NOTE: THIS DOES INCREASE THE VOLUME DRAMATICALLY:
* NOTE: THIS DOES INCREASE THE VOLUME DRAMATICALLY: * audio_gainset(pusb_device, 0x000F);
* audio_gainset(pusb_device, 0x000F);
* *
* IF 16<loud<31 VT1621A REGISTER 0x1C IS SET FOR POSITIVE GAIN. * loud dB register 0x10 dB register 0x1C dB total
* IF loud<=16 VT1621A REGISTER 0x1C IS SET FOR ZERO GAIN. * 0 -34.5 0 -34.5
* THERE IS NEVER ANY (ADDITIONAL) ATTENUATION. * .. .... . ....
*/ * 15 10.5 0 10.5
* 16 12.0 0 12.0
* 17 12.0 1.5 13.5
* .. .... .... ....
* 31 12.0 22.5 34.5
*/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
audio_gainset(struct usb_device *pusb_device, __s8 loud) audio_gainset(struct usb_device *pusb_device, __s8 loud)
...@@ -1134,25 +1128,65 @@ int igot; ...@@ -1134,25 +1128,65 @@ int igot;
__u8 u8; __u8 u8;
__u16 mute; __u16 mute;
if (16 > loud) if ((struct usb_device *)NULL == pusb_device)
loud = 16; return -ENODEV;
u8 = 0x000F & (__u8)(loud - 16); if (0 > loud)
loud = 0;
if (31 < loud)
loud = 31;
write_vt(pusb_device, 0x0002, 0x8000); write_vt(pusb_device, 0x0002, 0x8000);
/*---------------------------------------------------------------------------*/
igot = read_vt(pusb_device, 0x000E);
if (0 > igot) {
SAY("ERROR: failed to read VT1612A register 0x0E\n");
mute = 0x0000;
} else
mute = 0x8000 & ((unsigned int)igot);
mute = 0;
if (16 > loud)
u8 = 0x01 | (0x001F & (((__u8)(15 - loud)) << 1));
else
u8 = 0;
JOT(8, "0x%04X=(mute|u8) for VT1612A register 0x0E\n", mute | u8);
write_vt(pusb_device, 0x000E, (mute | u8));
/*---------------------------------------------------------------------------*/
igot = read_vt(pusb_device, 0x0010);
if (0 > igot) {
SAY("ERROR: failed to read VT1612A register 0x10\n");
mute = 0x0000;
} else
mute = 0x8000 & ((unsigned int)igot);
mute = 0;
JOT(8, "0x%04X=(mute|u8|(u8<<8)) for VT1612A register 0x10,...0x18\n", \
mute | u8 | (u8 << 8));
write_vt(pusb_device, 0x0010, (mute | u8 | (u8 << 8)));
write_vt(pusb_device, 0x0012, (mute | u8 | (u8 << 8)));
write_vt(pusb_device, 0x0014, (mute | u8 | (u8 << 8)));
write_vt(pusb_device, 0x0016, (mute | u8 | (u8 << 8)));
write_vt(pusb_device, 0x0018, (mute | u8 | (u8 << 8)));
/*---------------------------------------------------------------------------*/
igot = read_vt(pusb_device, 0x001C); igot = read_vt(pusb_device, 0x001C);
if (0 > igot) { if (0 > igot) {
SAY("ERROR: failed to read VT1612A register 0x1C\n"); SAY("ERROR: failed to read VT1612A register 0x1C\n");
mute = 0x0000; mute = 0x0000;
} else } else
mute = 0x8000 & ((unsigned int)igot); mute = 0x8000 & ((unsigned int)igot);
mute = 0;
JOT(8, "0x%04X=(mute|u8|(u8<<8))\n", mute | u8 | (u8 << 8)); if (16 <= loud)
u8 = 0x000F & (__u8)(loud - 16);
else
u8 = 0;
write_vt(pusb_device, 0x001C, 0x8000); JOT(8, "0x%04X=(mute|u8|(u8<<8)) for VT1612A register 0x1C\n", \
mute | u8 | (u8 << 8));
write_vt(pusb_device, 0x001C, (mute | u8 | (u8 << 8))); write_vt(pusb_device, 0x001C, (mute | u8 | (u8 << 8)));
write_vt(pusb_device, 0x001A, 0x0404);
write_vt(pusb_device, 0x0002, 0x0000); write_vt(pusb_device, 0x0002, 0x0000);
return 0; return 0;
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -1161,6 +1195,8 @@ audio_gainget(struct usb_device *pusb_device) ...@@ -1161,6 +1195,8 @@ audio_gainget(struct usb_device *pusb_device)
{ {
int igot; int igot;
if (NULL == pusb_device)
return -ENODEV;
igot = read_vt(pusb_device, 0x001C); igot = read_vt(pusb_device, 0x001C);
if (0 > igot) if (0 > igot)
SAY("ERROR: failed to read VT1612A register 0x1C\n"); SAY("ERROR: failed to read VT1612A register 0x1C\n");
......
...@@ -34,8 +34,10 @@ ...@@ -34,8 +34,10 @@
int debug; int debug;
int bars; int bars;
int gain = 16;
module_param(debug, int, S_IRUGO | S_IWUSR); module_param(debug, int, S_IRUGO | S_IWUSR);
module_param(bars, int, S_IRUGO | S_IWUSR); module_param(bars, int, S_IRUGO | S_IWUSR);
module_param(gain, int, S_IRUGO | S_IWUSR);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
...@@ -4770,7 +4772,8 @@ easycap_module_init(void) ...@@ -4770,7 +4772,8 @@ easycap_module_init(void)
int result; int result;
SAY("========easycap=======\n"); SAY("========easycap=======\n");
JOT(4, "begins. %i=debug %i=bars\n", debug, bars); JOT(4, "begins. %i=debug %i=bars %i=gain\n", debug, bars, \
gain);
SAY("version: " EASYCAP_DRIVER_VERSION "\n"); SAY("version: " EASYCAP_DRIVER_VERSION "\n");
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
...@@ -4811,8 +4814,9 @@ MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>"); ...@@ -4811,8 +4814,9 @@ MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION); MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION);
MODULE_VERSION(EASYCAP_DRIVER_VERSION); MODULE_VERSION(EASYCAP_DRIVER_VERSION);
#if defined(EASYCAP_DEBUG) #if defined(EASYCAP_DEBUG)
MODULE_PARM_DESC(debug, "Debug level: 0 (default),1,2,...,9"); MODULE_PARM_DESC(debug, "Debug level: 0 (default),1,2,...");
#endif /*EASYCAP_DEBUG*/ #endif /*EASYCAP_DEBUG*/
MODULE_PARM_DESC(bars, \ MODULE_PARM_DESC(bars, \
"Testcard bars on input signal failure: 0=>no, 1=>yes(default)"); "Testcard bars on input signal failure: 0=>no, 1=>yes(default)");
MODULE_PARM_DESC(gain, "Audio gain: 0,...,16(default),...31");
/*****************************************************************************/ /*****************************************************************************/
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