Ariff Abdullah
2009-12-16 02:00:14 UTC
The following reply was made to PR kern/140453; it has been noted by GNATS.
From: Ariff Abdullah <***@FreeBSD.org>
To: bug-***@FreeBSD.org, mwisnicki+***@gmail.com
Cc:
Subject: Re: kern/140453: [sound] No sound inside Virtualbox on 50% volume
Date: Wed, 16 Dec 2009 09:57:24 +0800
This is a multi-part message in MIME format.
--Multipart=_Wed__16_Dec_2009_09_57_24_+0800_XVlF0XJkEv9TFzl7
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Virtualbox (QEMU too) default to 5bit volume resolution, but it
appears through the volume resolution calibration process as
6bit. Clearly, it is a "hardware" bug. Virtualbox doing
slightly a better job by "clamping" the results (the lower bits
written as '1') whenever there is a write attempt on 5th (or
13th) bit, but _without_ resetting those high bit. As such, it
appears as a full 6-bit resolution result on the next codec
read. FreeBSD try to be honest here by doing supposed to be
correct calibration process and see/measure the result as is.
Others <insert whatever..> probably have their own static
mapping (think about vendor specific driver) or depends on
whatever magic marker, etc.
You have two choices:
1) Fix virtualbox ac97 codec emulation (probably not for you
given the fact that your vbox runs on Windows).
or
2) "Fix" FreeBSD ac97 volume resolution calibration by
accepting certain lower bits magic marker, ignoring the high bit.
--
Ariff Abdullah
FreeBSD
... Recording in stereo is obviously too advanced
and confusing for us idiot ***** users :P ........
... Going with the standard and orthodox
is the death of intellect ..............
--Multipart=_Wed__16_Dec_2009_09_57_24_+0800_XVlF0XJkEv9TFzl7
Content-Type: text/x-diff;
name="vbox-patch-xzz.diff"
Content-Disposition: attachment;
filename="vbox-patch-xzz.diff"
Content-Transfer-Encoding: 7bit
--- src/VBox/Devices/Audio/DevIchAc97.cpp.orig 2009-12-16 09:13:05.930459951 +0800
+++ src/VBox/Devices/Audio/DevIchAc97.cpp 2009-12-16 09:18:13.404715106 +0800
@@ -490,23 +490,8 @@
static void set_volume (AC97LinkState *s, int index,
audmixerctl_t mt, uint32_t val)
{
- int mute = (val >> MUTE_SHIFT) & 1;
- uint8_t rvol = VOL_MASK - (val & VOL_MASK);
- uint8_t lvol = VOL_MASK - ((val >> 8) & VOL_MASK);
- rvol = 255 * rvol / VOL_MASK;
- lvol = 255 * lvol / VOL_MASK;
-
-# ifdef SOFT_VOLUME
- if (index == AC97_Master_Volume_Mute)
- AUD_set_volume_out (s->voice_po, mute, lvol, rvol);
- else
- AUD_set_volume (mt, &mute, &lvol, &rvol);
-# else
- AUD_set_volume (mt, &mute, &lvol, &rvol);
-# endif
-
- rvol = VOL_MASK - ((VOL_MASK * rvol) / 255);
- lvol = VOL_MASK - ((VOL_MASK * lvol) / 255);
+ int mute;
+ uint8_t rvol, lvol;
/*
* From AC'97 SoundMax Codec AD1981A: "Because AC '97 defines 6-bit volume registers, to
@@ -521,6 +506,24 @@
if (val & RT_BIT(13))
val |= RT_BIT(12) | RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8);
+ /*
+ * 5-bit volume, behave like one.
+ */
+ val &= ~(RT_BIT(5) | RT_BIT(13));
+
+ mute = (val >> MUTE_SHIFT) & 1;
+ rvol = (255 * (VOL_MASK - (val & VOL_MASK))) / VOL_MASK;
+ lvol = (255 * (VOL_MASK - ((val >> 8) & VOL_MASK))) / VOL_MASK;
+
+# ifdef SOFT_VOLUME
+ if (index == AC97_Master_Volume_Mute)
+ AUD_set_volume_out (s->voice_po, mute, lvol, rvol);
+ else
+ AUD_set_volume (mt, &mute, &lvol, &rvol);
+# else
+ AUD_set_volume (mt, &mute, &lvol, &rvol);
+# endif
+
mixer_store (s, index, val);
}
--Multipart=_Wed__16_Dec_2009_09_57_24_+0800_XVlF0XJkEv9TFzl7
Content-Type: text/x-diff;
name="ac97_due_to_buggy_codec.diff"
Content-Disposition: attachment;
filename="ac97_due_to_buggy_codec.diff"
Content-Transfer-Encoding: 7bit
--- sys/dev/sound/pcm/ac97.c.orig (revision 200510)
+++ sys/dev/sound/pcm/ac97.c (working copy)
@@ -715,8 +715,27 @@ ac97_initmixer(struct ac97_info *codec)
* (ac97 2.3).
*/
bit = codec->mix[i].bits;
- if (bit == 5)
- bit++;
+ if (bit == 5) {
+ /*
+ * Test for possible 6bit control by
+ * turning on 5th (or 13th) and detect
+ * possible clamped values on the lower
+ * bits, which might be possible for
+ * 5bit control.
+ *
+ * XXX Emulators (QEMU, Virtualbox,
+ * etc..) does not reset the
+ * high bit, making it looks like
+ * a 6bit control. Consider that
+ * as "buggy codec".
+ */
+ j = 1 << (5 + codec->mix[i].ofs);
+ ac97_wrcd(codec, reg, j);
+ k = ac97_rdcd(codec, reg);
+ k >>= codec->mix[i].ofs;
+ if ((k & 0x1f) != 0x1f)
+ bit++;
+ }
j = ((1 << bit) - 1) << codec->mix[i].ofs;
ac97_wrcd(codec, reg,
j | (codec->mix[i].mute ? 0x8000 : 0));
--Multipart=_Wed__16_Dec_2009_09_57_24_+0800_XVlF0XJkEv9TFzl7--
From: Ariff Abdullah <***@FreeBSD.org>
To: bug-***@FreeBSD.org, mwisnicki+***@gmail.com
Cc:
Subject: Re: kern/140453: [sound] No sound inside Virtualbox on 50% volume
Date: Wed, 16 Dec 2009 09:57:24 +0800
This is a multi-part message in MIME format.
--Multipart=_Wed__16_Dec_2009_09_57_24_+0800_XVlF0XJkEv9TFzl7
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Virtualbox (QEMU too) default to 5bit volume resolution, but it
appears through the volume resolution calibration process as
6bit. Clearly, it is a "hardware" bug. Virtualbox doing
slightly a better job by "clamping" the results (the lower bits
written as '1') whenever there is a write attempt on 5th (or
13th) bit, but _without_ resetting those high bit. As such, it
appears as a full 6-bit resolution result on the next codec
read. FreeBSD try to be honest here by doing supposed to be
correct calibration process and see/measure the result as is.
Others <insert whatever..> probably have their own static
mapping (think about vendor specific driver) or depends on
whatever magic marker, etc.
You have two choices:
1) Fix virtualbox ac97 codec emulation (probably not for you
given the fact that your vbox runs on Windows).
or
2) "Fix" FreeBSD ac97 volume resolution calibration by
accepting certain lower bits magic marker, ignoring the high bit.
--
Ariff Abdullah
FreeBSD
... Recording in stereo is obviously too advanced
and confusing for us idiot ***** users :P ........
... Going with the standard and orthodox
is the death of intellect ..............
--Multipart=_Wed__16_Dec_2009_09_57_24_+0800_XVlF0XJkEv9TFzl7
Content-Type: text/x-diff;
name="vbox-patch-xzz.diff"
Content-Disposition: attachment;
filename="vbox-patch-xzz.diff"
Content-Transfer-Encoding: 7bit
--- src/VBox/Devices/Audio/DevIchAc97.cpp.orig 2009-12-16 09:13:05.930459951 +0800
+++ src/VBox/Devices/Audio/DevIchAc97.cpp 2009-12-16 09:18:13.404715106 +0800
@@ -490,23 +490,8 @@
static void set_volume (AC97LinkState *s, int index,
audmixerctl_t mt, uint32_t val)
{
- int mute = (val >> MUTE_SHIFT) & 1;
- uint8_t rvol = VOL_MASK - (val & VOL_MASK);
- uint8_t lvol = VOL_MASK - ((val >> 8) & VOL_MASK);
- rvol = 255 * rvol / VOL_MASK;
- lvol = 255 * lvol / VOL_MASK;
-
-# ifdef SOFT_VOLUME
- if (index == AC97_Master_Volume_Mute)
- AUD_set_volume_out (s->voice_po, mute, lvol, rvol);
- else
- AUD_set_volume (mt, &mute, &lvol, &rvol);
-# else
- AUD_set_volume (mt, &mute, &lvol, &rvol);
-# endif
-
- rvol = VOL_MASK - ((VOL_MASK * rvol) / 255);
- lvol = VOL_MASK - ((VOL_MASK * lvol) / 255);
+ int mute;
+ uint8_t rvol, lvol;
/*
* From AC'97 SoundMax Codec AD1981A: "Because AC '97 defines 6-bit volume registers, to
@@ -521,6 +506,24 @@
if (val & RT_BIT(13))
val |= RT_BIT(12) | RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8);
+ /*
+ * 5-bit volume, behave like one.
+ */
+ val &= ~(RT_BIT(5) | RT_BIT(13));
+
+ mute = (val >> MUTE_SHIFT) & 1;
+ rvol = (255 * (VOL_MASK - (val & VOL_MASK))) / VOL_MASK;
+ lvol = (255 * (VOL_MASK - ((val >> 8) & VOL_MASK))) / VOL_MASK;
+
+# ifdef SOFT_VOLUME
+ if (index == AC97_Master_Volume_Mute)
+ AUD_set_volume_out (s->voice_po, mute, lvol, rvol);
+ else
+ AUD_set_volume (mt, &mute, &lvol, &rvol);
+# else
+ AUD_set_volume (mt, &mute, &lvol, &rvol);
+# endif
+
mixer_store (s, index, val);
}
--Multipart=_Wed__16_Dec_2009_09_57_24_+0800_XVlF0XJkEv9TFzl7
Content-Type: text/x-diff;
name="ac97_due_to_buggy_codec.diff"
Content-Disposition: attachment;
filename="ac97_due_to_buggy_codec.diff"
Content-Transfer-Encoding: 7bit
--- sys/dev/sound/pcm/ac97.c.orig (revision 200510)
+++ sys/dev/sound/pcm/ac97.c (working copy)
@@ -715,8 +715,27 @@ ac97_initmixer(struct ac97_info *codec)
* (ac97 2.3).
*/
bit = codec->mix[i].bits;
- if (bit == 5)
- bit++;
+ if (bit == 5) {
+ /*
+ * Test for possible 6bit control by
+ * turning on 5th (or 13th) and detect
+ * possible clamped values on the lower
+ * bits, which might be possible for
+ * 5bit control.
+ *
+ * XXX Emulators (QEMU, Virtualbox,
+ * etc..) does not reset the
+ * high bit, making it looks like
+ * a 6bit control. Consider that
+ * as "buggy codec".
+ */
+ j = 1 << (5 + codec->mix[i].ofs);
+ ac97_wrcd(codec, reg, j);
+ k = ac97_rdcd(codec, reg);
+ k >>= codec->mix[i].ofs;
+ if ((k & 0x1f) != 0x1f)
+ bit++;
+ }
j = ((1 << bit) - 1) << codec->mix[i].ofs;
ac97_wrcd(codec, reg,
j | (codec->mix[i].mute ? 0x8000 : 0));
--Multipart=_Wed__16_Dec_2009_09_57_24_+0800_XVlF0XJkEv9TFzl7--