Re: [alsa-devel] snd-hda-intel, AD 1988b: SPDIF output not working correctly, volume low for analog output
At Mon, 23 Jul 2007 23:02:57 +0200, Matthias Dahl wrote:
Hello Takashi.
On Friday 20 July 2007 15:47:55 Takashi Iwai wrote:
This is expected behavior. The PCM volume is implemented via softvol plugin, and it creates dynamically at the first run. But, usually, it's restored via alsactl at the next boot.
It is. Thanks for the info.
Yes, it'll involve with patch_analog.c deeply. Basically you need to modify init verb table and the mixer element table. Check the AD1988B datasheet, and try to assign the different PIN (and corresponding mixer / selector widgets) in init verb and mixer tables. Then, rebuild driver, and try the driver until you get the complete mapping of pin widgets.
I am currently a bit limited in time (end of semester exams) but after a few hours of playing around (and reading the specs) I figured the following:
From time to time no analog output is routed to the spdif anymore. The only clue I could get is the "IEC958 Playback Default" which is set to
06820002 [... many more zeros ...]
and thus restored to that value after reboots. When things work like they should (analog output is routed to spdif), its value is
04820002 [... many more zeros ...]
Manually setting it to this value naturally solves the problem. I have yet to figure out how to trigger this problem?! It seems to happen rather randomly. In both cases, ac3 passthrough works just fine btw.
Maybe some apps change the IEC958 status bits and doesn't restore the original value at close. (Or interrupting via ctrl-C may cause it.)
You can see the meaning of these bits via iecset utility included in alsa-utils package.
I have come a step closer in solving the analog-to-spdif volume/distortions problem... at least I hope.
The following patch fixes the volume problem for me. Without it, I had to set the IEC958 volume somewhere around 58... increasing it would result in noticable clipping and even short audio gaps (noise).
Honestly, I don't quite understand the purpose of the code I removed in the first place. From what I figured reading the specs and the code, the spdif in is mixed with the spdif out stream... but that's all I could gather. But still it doesn't seem quite right to me.
--- patch_analog.c.orig 2007-07-23 22:44:25.000000000 +0200 +++ patch_analog.c 2007-07-23 22:45:15.000000000 +0200 @@ -2037,12 +2037,8 @@ static struct hda_verb ad1988_spdif_init_verbs[] = { /* SPDIF out sel */ {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
{0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, /* SPDIF out pin */ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x17}, /* 0dB */ { }
};
The audio distortions in the background have become a little less noisy but are still there. (a bass-like pumping, some white noise and sometimes some high frequency tone) But the volume works just fine now... (iec958 vol at 100%) and the audio sounds somewhat "clearer"!
So, the culprit looks like the analog loopback. Could you try the patch below, and make sure that you set "PCM" as the "IEC958 Playback Source"?
thanks,
Takashi
diff -r c2078875c0cd pci/hda/patch_analog.c --- a/pci/hda/patch_analog.c Tue Jul 24 12:10:34 2007 +0200 +++ b/pci/hda/patch_analog.c Tue Jul 24 12:47:42 2007 +0200 @@ -1889,16 +1889,19 @@ static int ad1988_spdif_playback_source_ struct hda_codec *codec = snd_kcontrol_chip(kcontrol); unsigned int sel;
- sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); - if (sel > 0) { + sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE, + AC_AMP_GET_INPUT); + if (!(sel & 0x80)) + ucontrol->value.enumerated.item[0] = 0; + else { sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0); if (sel < 3) sel++; else sel = 0; + ucontrol->value.enumerated.item[0] = sel; } - ucontrol->value.enumerated.item[0] = sel; return 0; }
@@ -1910,17 +1913,32 @@ static int ad1988_spdif_playback_source_ int change;
val = ucontrol->value.enumerated.item[0]; - sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); if (!val) { - change = sel != 0; - if (change || codec->in_resume) - snd_hda_codec_write(codec, 0x02, 0, - AC_VERB_SET_CONNECT_SEL, 0); + sel = snd_hda_codec_read(codec, 0x1d, 0, + AC_VERB_GET_AMP_GAIN_MUTE, + AC_AMP_GET_INPUT); + change = sel & 0x80; + if (change || codec->in_resume) { + snd_hda_codec_write(codec, 0x1d, 0, + AC_VERB_SET_AMP_GAIN_MUTE, + AMP_IN_UNMUTE(0)); + snd_hda_codec_write(codec, 0x1d, 0, + AC_VERB_SET_AMP_GAIN_MUTE, + AMP_IN_MUTE(1)); + } } else { - change = sel == 0; - if (change || codec->in_resume) - snd_hda_codec_write(codec, 0x02, 0, - AC_VERB_SET_CONNECT_SEL, 1); + sel = snd_hda_codec_read(codec, 0x1d, 0, + AC_VERB_GET_AMP_GAIN_MUTE, + AC_AMP_GET_INPUT | 0x01); + change = sel & 0x80; + if (change || codec->in_resume) { + snd_hda_codec_write(codec, 0x1d, 0, + AC_VERB_SET_AMP_GAIN_MUTE, + AMP_IN_MUTE(0)); + snd_hda_codec_write(codec, 0x1d, 0, + AC_VERB_SET_AMP_GAIN_MUTE, + AMP_IN_UNMUTE(1)); + } sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0) + 1; change |= sel != val; @@ -2039,10 +2057,9 @@ static struct hda_verb ad1988_spdif_init {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */ {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* SPDIF out pin */ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x17}, /* 0dB */
{ } };
On Tuesday 24 July 2007 12:47:59 Takashi Iwai wrote:
Maybe some apps change the IEC958 status bits and doesn't restore the original value at close. (Or interrupting via ctrl-C may cause it.)
You can see the meaning of these bits via iecset utility included in alsa-utils package.
Thanks. I'll keep that in mind and check things when it happens again.
So, the culprit looks like the analog loopback. Could you try the patch below, and make sure that you set "PCM" as the "IEC958 Playback Source"?
I can confirm this definitely solves the volume problem for me. I can increase the pcm and spdif volume to 100% and no clipping or distortions whatsoever happen on the spdif output. Works like a charm.
So far the other distortions I wrote about are now only hearable when I turn up the volume of my headphone to nearly its maximum. If it stays that way, I can live with it... reminds me, before the problem was fixed, I had my headphone at almost 100% most of the time, so that could be the reason why those distortions where so visible in the first place. I'll have an eye on it...
I am curious, will that patch make it into the offical mercurial repository and what was the problem exactly with the analog loopback?
Thanks for taking the time!
Best regards, Matthias Dahl
At Tue, 24 Jul 2007 17:58:12 +0200, Matthias Dahl wrote:
So, the culprit looks like the analog loopback. Could you try the patch below, and make sure that you set "PCM" as the "IEC958 Playback Source"?
I can confirm this definitely solves the volume problem for me. I can increase the pcm and spdif volume to 100% and no clipping or distortions whatsoever happen on the spdif output. Works like a charm.
Great, thanks for confirmation.
So far the other distortions I wrote about are now only hearable when I turn up the volume of my headphone to nearly its maximum. If it stays that way, I can live with it... reminds me, before the problem was fixed, I had my headphone at almost 100% most of the time, so that could be the reason why those distortions where so visible in the first place. I'll have an eye on it...
I'm not sure whether it's a driver problem or a hardware problem. Is the dB above 0 in the maximum level?
I am curious, will that patch make it into the offical mercurial repository and what was the problem exactly with the analog loopback?
Yes, the patch will be merged soon. Hopefully we can put it to 2.6.23 tree, too.
The problem was that the analog loopback is routed wrongly to the SPDIF output unconditionally, and no way to cut it out. The patch fixes the implementation of "IEC958 playback source" mixer element to handle correctly it.
Takashi
participants (2)
-
Matthias Dahl
-
Takashi Iwai