[alsa-devel] [PATCH] AD1986A 6-channel bugs

Takashi Iwai tiwai at suse.de
Thu Oct 25 10:05:21 CEST 2007


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;
 }


More information about the Alsa-devel mailing list