Patch to use AC97 MICBOOST bit
Dear Linux Kernel Developers:
This is the first time I have submitted a patch. I've tried to
follow the guidelines in the MAINTAINERS file, and in the Documentation/SubmittingPatches file. Nevertheless, I may have messed something up. If so, please let me know.
Currently, the ac97 codec access logic in thedrivers/sound/ac97_codec.c logic does not use the AC97_MICBOOST bit. Consequently, when writing to or reading from the SOUND_MIXER_MIC channel, there are only 32 distinct values that can be used. There is alot of overlap between dB values available with the MICBOOST bit turned on, and those available with it turned off. Nevertheless, I found that by turning the MICBOOST bit on and off at appropriate times, the total dB range available is increased, and this may be of some value to some applications. In any case, its generally considered to be "good form" to make as many of the device's features as possible available to the programmer. This change is made with that intent in mind. A patch file is attached. Code changes are in the ac97_read_mixer routine, and the ac97_write_mixer routine, in the code which handles the SOUND_MIXER_MIC channel.
I originally made this change to the ac97_codec.c source file for the 2.4.2 kernel, and tested it, but retained it just for my own use. I've now made the same changes to the ac97_codec.c file for the Linux 2.4.23 kernel, and am sending it to you, but at this time I do not easily have a way to test them out. Please let me know if you run into any problems.
The attached patch file was generated by:
diff -u ac97_codec.c linux-2.4.23/drivers/sound/ac97_codec.c
Quoted 1 line
ac97_codec_patch
(the above is supposed to be one line, but pine broke it
into two lines)
Any questions, comments, feedback, etc: [email protected] Thanks alot.
Dennis Newbold
---------------------------------------------
| | | The way to be happy is to be good | | |
---------------------------------------------
linux-2.4.23\drivers\sound\ac97_codec.c renamed from ac97_codec.c +36 -6
@@ -30,6 +30,9 @@ ************************************************************************** * * History + * Dec 04, 2003 Dennis Newbold <[email protected]> + * Added logic to use the MICBOOST bit when writing or reading the + * SOUND_MIXER_MIC channel. * May 02, 2003 Liam Girdwood <[email protected]> * Removed non existant WM9700 * Added support for WM9705, WM9708, WM9709, WM9710, WM9711
@@ -240,6 +243,26 @@ {-1,0} }; +/* Note that scale for SOUND_MIXER_MIC is set to 46 rather than 32. This is +* to include the lower volume DB values that do not use the AC97_MICBOOST +* bit. There is a small glitch in the scaling in that the last value to use +* the boost bit is 31, which translates to -14.5 dB, and the next lower value, +* which does not use the boost bit is 32, which is converted to 18, which +* translates to -15 dB, a difference of only 0.5 dB. All other gain values +* differ by 1.5 dB. This is considered acceptable because it happens only +* at an extremely low volume, which most users will not be interested in. +* -dln- */ + +/* MIC_NATURAL_SCALE is the no. of different gain settings that will fit in +* the MIC Volume Gain Register. Computed gain values which fall within this +* range operate with the AC97_MICBOOST bit enabled. Computed values outside +* of this range are forced back into this range, but with the AC97_MICBOOST +* bit turned off. This allows access to the very low dB range scale of the +* AC97 codec, which cannot be accessed with the MICBOOST bit enabled. -dln- +*/ + +#define MIC_NATURAL_SCALE (32) +/* table to scale scale from OSS mixer value to AC97 mixer register value */ static struct ac97_mixer_hw { unsigned char offset;
@@ -302,7 +325,7 @@about that given mixer, and should be holding a spinlock for the card */ static int ac97_read_mixer (struct ac97_codec *codec,int oss_channel) { -u16 val; +u16 val, t;int ret =0 ;int scale;struct ac97_mixer_hw *mh = &ac97_hw[oss_channel];
@@ -340,7 +363,10 @@ scale = (1 << codec->bit_resolution); ret =100 - (((val &0x1f ) *100 ) / scale); }else if (oss_channel ==SOUND_MIXER_MIC ) { - ret =100 - (((val &0x1f ) *100 ) / mh->scale); + t = val & (MIC_NATURAL_SCALE -1 ); +if (!(val &AC97_MICBOOST )) + t += (mh->scale -MIC_NATURAL_SCALE ); + ret =100 - ((t *100 ) / mh->scale-1 );/* the low bit is optional in the tone sliders and masking it lets us avoid the 0xf 'bypass'.. */ }else if (oss_channel ==SOUND_MIXER_BASS ) {
@@ -427,7 +453,7 @@ left = ((100 - left) * mh->scale) /100 ;if (left >= mh->scale) left = mh->scale-1 ; - val = left; + val = left; }else if (oss_channel ==SOUND_MIXER_PHONEOUT ) { scale = (1 << codec->bit_resolution); left = ((100 - left) * scale) /100 ;
@@ -436,13 +462,17 @@ val = left; }else if (oss_channel ==SOUND_MIXER_MIC ) { val = codec->codec_read (codec , mh->offset) & ~0x801f ; - left = ((100 - left) * mh->scale) /100 ; + left = ((100 - left) * mh->scale-1 ) /100 ;if (left >= mh->scale) - left = mh->scale-1 ; + left = mh->scale-1 +if (left <MIC_NATURAL_SCALE ) + left |=AC97_MICBOOST ; +else + left -= (mh->scale -MIC_NATURAL_SCALE ); val |= left;/* the low bit is optional in the tone sliders and masking it lets us avoid the 0xf 'bypass'.. */ - } +#ifdef DEBUG printk (" 0x%04x" , val);#endif