[alsa-devel] [PATCH] AD1986A 6-channel bugs
Hi,
I have a ICH8M + AD1986A machine.
In 6 channel modes, if adjust the volumes when playing 2-channel or 4-channel music, codec will be muted and all widget's Amp-Out vals will be reset. If you play 2-channel files in 6 channel modes,there is noise in the jacks.
By doing experiments, I found that the 6-channel bug was caused by sharing channels.
If play 2-channel audio file,the rest channels will share channels with the first 2-channel.
The HDA spec doesn’t define the exact behavior under such circumstances.
Majority of the codec chips support sharing channel, but seem that AD1986A doesn’t support.
I wrote a patch and tested it in my hardware,now it works well.
diff -Nur a/alsa-driver-1.0.15/alsa-kernel/pci/hda/hda_codec.c b/alsa-driver-1.0.15/alsa-kernel/pci/hda/hda_codec.c --- a/alsa-driver-1.0.15/alsa-kernel/pci/hda/hda_codec.c 2007-10-25 10:03:29.000000000 -0400 +++ b/alsa-driver-1.0.15/alsa-kernel/pci/hda/hda_codec.c 2007-10-25 10:02:46.000000000 -0400 @@ -2506,7 +2506,8 @@ if (chs >= (i + 1) * 2) /* independent out */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, format); - else /* copy front */ + else if (codec->vendor_id != 0x11d41986) + /* copy front if it is NOT AD1986A*/ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format); }
In alsa bugzilla and maillist, I found a lot of issues about AD1986A 6-channel .Anybody know the detail about AD1986A codec chip and give any comments?
Here is a old description of the issue.
Hi,
I have a ICH8M + AD1986A machine and run alsa-driver-1.0.15rc.
I found that : In 6 channel mode,if adjust the front or pcm volume when playing
music,
all channel will be muted,but if adjust the volume alone(don't play music at the same time),every thing is ok. I use printk to display the verb in the azx_send_cmd(), when adjusting the volume in either case, there are just two verb (0x300) sent to the nid(0x1b) [correct action]. But in the first case, the dac widget amp-out vals are all affected.
Some other interesting thing, If i adjust the Sur or CLFE volume when playing music, the printk show that correct verb is sent, but the codec status don't change. If I adjust them alone,every thing is ok.
At Thu, 25 Oct 2007 15:05:40 +0800, zhejiang wrote:
Hi,
I have a ICH8M + AD1986A machine.
In 6 channel modes, if adjust the volumes when playing 2-channel or 4-channel music, codec will be muted and all widget's Amp-Out vals will be reset. If you play 2-channel files in 6 channel modes,there is noise in the jacks.
By doing experiments, I found that the 6-channel bug was caused by sharing channels.
If play 2-channel audio file,the rest channels will share channels with the first 2-channel.
The HDA spec doesn’t define the exact behavior under such circumstances.
Majority of the codec chips support sharing channel, but seem that AD1986A doesn’t support.
I wrote a patch and tested it in my hardware,now it works well.
Thanks! It's been a bug that I hardly understood what was wrong.
IMO, it's better to have a flag in hda_multi_out rather than hardcoding the codec id there.
Could you check whether the patch below works?
Takashi
diff -r 4f3f2f4bd5e9 pci/hda/hda_codec.c --- a/pci/hda/hda_codec.c Wed Oct 24 18:18:11 2007 +0200 +++ b/pci/hda/hda_codec.c Thu Oct 25 11:39:55 2007 +0200 @@ -2486,13 +2486,14 @@ int snd_hda_multi_out_analog_prepare(str /* front */ snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); - if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) + if (!mout->no_share_stream && + mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) /* headphone out will just decode front left/right (stereo) */ snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); /* extra outputs copied from front */ for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) - if (mout->extra_out_nid[i]) + if (!mout->no_share_stream && mout->extra_out_nid[i]) snd_hda_codec_setup_stream(codec, mout->extra_out_nid[i], stream_tag, 0, format); @@ -2502,7 +2503,7 @@ int snd_hda_multi_out_analog_prepare(str if (chs >= (i + 1) * 2) /* independent out */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, format); - else /* copy front */ + else if (!mout->no_share_stream) /* copy front */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format); } diff -r 4f3f2f4bd5e9 pci/hda/hda_local.h --- a/pci/hda/hda_local.h Wed Oct 24 18:18:11 2007 +0200 +++ b/pci/hda/hda_local.h Thu Oct 25 11:39:55 2007 +0200 @@ -220,6 +220,7 @@ struct hda_multi_out { hda_nid_t dig_out_nid; /* digital out audio widget */ int max_channels; /* currently supported analog channels */ int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ + int no_share_stream; /* don't share a stream with multiple pins */ };
int snd_hda_multi_out_dig_open(struct hda_codec *codec, diff -r 4f3f2f4bd5e9 pci/hda/patch_analog.c --- a/pci/hda/patch_analog.c Wed Oct 24 18:18:11 2007 +0200 +++ b/pci/hda/patch_analog.c Thu Oct 25 11:39:55 2007 +0200 @@ -956,6 +956,14 @@ static int patch_ad1986a(struct hda_code spec->multiout.dig_out_nid = 0; break; } + + /* AD1986A has a hardware problem that it can't share a stream + * with multiple output pins. The copy of front to surrounds + * causes noisy or silent outputs at a certain timing, e.g. + * changing the volume. + * So, let's disable the shared stream. + */ + spec->multiout.no_share_stream = 1;
return 0; }
On Thu, 2007-10-25 at 10:05 +0200, Takashi Iwai wrote:
At Thu, 25 Oct 2007 15:05:40 +0800, zhejiang wrote:
Hi,
I have a ICH8M + AD1986A machine.
In 6 channel modes, if adjust the volumes when playing 2-channel or 4-channel music, codec will be muted and all widget's Amp-Out vals will be reset. If you play 2-channel files in 6 channel modes,there is noise in the jacks.
By doing experiments, I found that the 6-channel bug was caused by sharing channels.
If play 2-channel audio file,the rest channels will share channels with the first 2-channel.
The HDA spec doesn’t define the exact behavior under such circumstances.
Majority of the codec chips support sharing channel, but seem that AD1986A doesn’t support.
I wrote a patch and tested it in my hardware,now it works well.
Thanks! It's been a bug that I hardly understood what was wrong.
IMO, it's better to have a flag in hda_multi_out rather than hardcoding the codec id there.
Could you check whether the patch below works?
I have tested them and they are okay! Thanks!
Takashi
diff -r 4f3f2f4bd5e9 pci/hda/hda_codec.c --- a/pci/hda/hda_codec.c Wed Oct 24 18:18:11 2007 +0200 +++ b/pci/hda/hda_codec.c Thu Oct 25 11:39:55 2007 +0200 @@ -2486,13 +2486,14 @@ int snd_hda_multi_out_analog_prepare(str /* front */ snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format);
- if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
- if (!mout->no_share_stream &&
/* headphone out will just decode front left/right (stereo) */ snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); /* extra outputs copied from front */ for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
if (mout->extra_out_nid[i])
if (!mout->no_share_stream && mout->extra_out_nid[i]) snd_hda_codec_setup_stream(codec, mout->extra_out_nid[i], stream_tag, 0, format);
@@ -2502,7 +2503,7 @@ int snd_hda_multi_out_analog_prepare(str if (chs >= (i + 1) * 2) /* independent out */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, format);
else /* copy front */
}else if (!mout->no_share_stream) /* copy front */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format);
diff -r 4f3f2f4bd5e9 pci/hda/hda_local.h --- a/pci/hda/hda_local.h Wed Oct 24 18:18:11 2007 +0200 +++ b/pci/hda/hda_local.h Thu Oct 25 11:39:55 2007 +0200 @@ -220,6 +220,7 @@ struct hda_multi_out { hda_nid_t dig_out_nid; /* digital out audio widget */ int max_channels; /* currently supported analog channels */ int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */
- int no_share_stream; /* don't share a stream with multiple pins */
};
int snd_hda_multi_out_dig_open(struct hda_codec *codec, diff -r 4f3f2f4bd5e9 pci/hda/patch_analog.c --- a/pci/hda/patch_analog.c Wed Oct 24 18:18:11 2007 +0200 +++ b/pci/hda/patch_analog.c Thu Oct 25 11:39:55 2007 +0200 @@ -956,6 +956,14 @@ static int patch_ad1986a(struct hda_code spec->multiout.dig_out_nid = 0; break; }
/* AD1986A has a hardware problem that it can't share a stream
* with multiple output pins. The copy of front to surrounds
* causes noisy or silent outputs at a certain timing, e.g.
* changing the volume.
* So, let's disable the shared stream.
*/
spec->multiout.no_share_stream = 1;
return 0;
}
At Fri, 26 Oct 2007 17:19:31 +0800, zhejiang wrote:
On Thu, 2007-10-25 at 10:05 +0200, Takashi Iwai wrote:
At Thu, 25 Oct 2007 15:05:40 +0800, zhejiang wrote:
Hi,
I have a ICH8M + AD1986A machine.
In 6 channel modes, if adjust the volumes when playing 2-channel or 4-channel music, codec will be muted and all widget's Amp-Out vals will be reset. If you play 2-channel files in 6 channel modes,there is noise in the jacks.
By doing experiments, I found that the 6-channel bug was caused by sharing channels.
If play 2-channel audio file,the rest channels will share channels with the first 2-channel.
The HDA spec doesn’t define the exact behavior under such circumstances.
Majority of the codec chips support sharing channel, but seem that AD1986A doesn’t support.
I wrote a patch and tested it in my hardware,now it works well.
Thanks! It's been a bug that I hardly understood what was wrong.
IMO, it's better to have a flag in hda_multi_out rather than hardcoding the codec id there.
Could you check whether the patch below works?
I have tested them and they are okay! Thanks!
Great, now I committed to ALSA HG tree.
Thanks for testing!
Takashi
participants (2)
-
Takashi Iwai
-
zhejiang