Alsa-Devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: p z oooo <pzad@pobox.sk>
Cc: James@superbug.demon.co.uk, mserg@gala.net,
	alsa-devel@lists.sourceforge.net
Subject: Re: ALC650 GPIO bits
Date: Wed, 03 Mar 2004 18:54:17 +0100	[thread overview]
Message-ID: <s5h1xo9n7ee.wl@alsa2.suse.de> (raw)
In-Reply-To: <200403031713.i23HDHbe010376@www7.pobox.sk>

[-- Attachment #1: Type: text/plain, Size: 1310 bytes --]

At Wed, 3 Mar 2004 18:13:17 +0100,
p z oooo wrote:
> 
> Hi,
> 
> My fault.
> 
> This is what is in datasheets:
> 
> >There are two option circuits for MIC to disable bias voltage. For 
> >ALC650 ver.E or later, there is Vrefout-disabled function, so
> >bias voltage from Vrefout(pin28) is recommended as option2 circuit. 
> >When MIC is shared with Center/LFE, software should
> >disable Vrefout. For ALC650 ver.C/ver.D, Vrefout-disabled function 
> >is not implemented yet, so GPIO is used to switch bias
> >voltage as option1/option3 circuit.
> 
> ALC650 ver. C, D and uses GPIO
> ALC650 ver. E and later can use GPIO or Vrefout (register MX74 
> MISCELLANEOUS CONTROL bit 12 - it is used similiar as GPIO), maybe 
> all motherboards uses GPIO (but vrefout needs less components)

yes, i found it after rereading, too.
it looks like it's harmless to handle this GPIO0 regardless of the
revision.

> 
> and there is this too:
> 
> >Vrefout Disable (Supported by the ALC650 Rev. E and Rev.F)
> >0: Vrefout is driven by the internal reference (Default)
> >1: Vrefout is in high-Z mode.
> >Software must set this bit to disable Vrefout output before MX6A.10 
> >is set (MIC1 and MIC2 are shared as Center and LFE output).

yep.

could you check the attached patch whether it breaks something?


thanks,

Takashi

[-- Attachment #2: Type: text/plain, Size: 7767 bytes --]

Index: alsa-kernel/pci/ac97/ac97_patch.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/pci/ac97/ac97_patch.c,v
retrieving revision 1.38
diff -u -r1.38 ac97_patch.c
--- alsa-kernel/pci/ac97/ac97_patch.c	11 Feb 2004 19:43:53 -0000	1.38
+++ alsa-kernel/pci/ac97/ac97_patch.c	3 Mar 2004 17:51:13 -0000
@@ -292,6 +292,9 @@
 	return 0;
 }
 
+/*
+ * Tritech codec
+ */
 int patch_tritech_tr28028(ac97_t * ac97)
 {
 	snd_ac97_write_cache(ac97, 0x26, 0x0300);
@@ -301,6 +304,9 @@
 	return 0;
 }
 
+/*
+ * Sigmatel STAC97xx codecs
+ */
 static int patch_sigmatel_stac9700_3d(ac97_t * ac97)
 {
 	snd_kcontrol_t *kctl;
@@ -441,6 +447,9 @@
 	return 0;
 }
 
+/*
+ * Cirrus Logic CS42xx codecs
+ */
 static const snd_kcontrol_new_t snd_ac97_cirrus_controls_spdif[2] = {
 	AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0),
 	AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE, 0, 3, 0)
@@ -499,6 +508,9 @@
 	return patch_cirrus_spdif(ac97);
 }
 
+/*
+ * Conexant codecs
+ */
 static const snd_kcontrol_new_t snd_ac97_conexant_controls_spdif[1] = {
 	AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1, 0),
 };
@@ -530,6 +542,9 @@
 	return 0;
 }
 
+/*
+ * Analog Device AD18xx, AD19xx codecs
+ */
 int patch_ad1819(ac97_t * ac97)
 {
 	// patch for Analog Devices
@@ -992,6 +1007,38 @@
 	return 0;
 }
 
+/*
+ * realtek ALC65x codecs
+ */
+static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+        ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
+        return 0;
+}
+
+static int snd_ac97_alc650_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+	int change, val;
+	val = !!(snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10));
+	change = (ucontrol->value.integer.value[0] != val);
+	if (change) {
+		/* disable/enable vref */
+		snd_ac97_update_bits(ac97, AC97_ALC650_MISC, 1 << 12,
+				     ucontrol->value.integer.value[0] ? (1 << 12) : 0);
+		/* turn on/off center-on-mic */
+		snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
+				     ucontrol->value.integer.value[0] ? (1 << 10) : 0);
+                /* GPIO0 write for mic */
+                snd_ac97_update_bits(ac97, 0x76, 0x01, 0x01);
+                /* GPIO0 high for mic */
+                snd_ac97_update_bits(ac97, 0x78, 0x100,
+                                     ucontrol->value.integer.value[0] ? 0 : 0x100);
+        }
+        return change;
+}
+
 static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
 	AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
 	AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
@@ -1014,41 +1061,13 @@
 	AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
 	AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
 #endif
-};
-
-static const snd_kcontrol_new_t snd_ac97_control_alc650_mic =
-AC97_SINGLE("Mic As Center/LFE", AC97_ALC650_MULTICH, 10, 1, 0);
-
-static int snd_ac97_alc650_mic_gpio_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
-        return 0;
-}
-
-static int snd_ac97_alc650_mic_gpio_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        int change;
-        change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
-                                      ucontrol->value.integer.value[0] ? (1 << 10) : 0);
-        if (change) {
-                /* GPIO0 write for mic */
-                snd_ac97_update_bits(ac97, 0x76, 0x01, 0x01);
-                /* GPIO0 high for mic */
-                snd_ac97_update_bits(ac97, 0x78, 0x100,
-                                     ucontrol->value.integer.value[0] ? 0 : 0x100);
-        }
-        return change;
-}
-
-static const snd_kcontrol_new_t snd_ac97_control_alc650_mic_gpio = {
-        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-        .name = "Mic As Center/LFE",
-        .info = snd_ac97_info_single,
-        .get = snd_ac97_alc650_mic_gpio_get,
-        .put = snd_ac97_alc650_mic_gpio_put,
-        .private_value = (1 << 16), /* for info */
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Mic As Center/LFE",
+		.info = snd_ac97_info_single,
+		.get = snd_ac97_alc650_mic_get,
+		.put = snd_ac97_alc650_mic_put,
+	},
 };
 
 static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
@@ -1063,11 +1082,6 @@
 
 	if ((err = patch_build_controls(ac97, snd_ac97_controls_alc650, ARRAY_SIZE(snd_ac97_controls_alc650))) < 0)
 		return err;
-	if ((err = patch_build_controls(ac97,
-					ac97->spec.dev_flags ?
-						&snd_ac97_control_alc650_mic :
-						&snd_ac97_control_alc650_mic_gpio, 1)) < 0)
-		return err;
 	if (ac97->ext_id & AC97_EI_SPDIF) {
 		if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0)
 			return err;
@@ -1095,31 +1109,24 @@
 		snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x8000);
 
 	/* Enable SPDIF-IN only on Rev.E and above */
-	if (ac97->spec.dev_flags) {
-		/* enable spdif in */
-		snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK,
-				     snd_ac97_read(ac97, AC97_ALC650_CLOCK) | 0x03);
-	}
+	val = snd_ac97_read(ac97, AC97_ALC650_CLOCK);
+	/* SPDIF IN with pin 47 */
+	if (ac97->spec.dev_flags)
+		val |= 0x03; /* enable */
+	else
+		val &= ~0x03; /* disable */
+	snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK, val);
 
 	val = snd_ac97_read(ac97, AC97_ALC650_MULTICH);
 	val &= ~0xc000; /* slot: 3,4,7,8,6,9 */
+	val &= ~(1 << 10); /* center-on-mic off */
 	snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, val);
 
-	if (! ac97->spec.dev_flags) {
-		/* set GPIO */
-		int mic_off;
-		mic_off = snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10);
-		/* GPIO0 direction */
-		val = snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP);
-		val |= 0x01;
-		snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP, val);
-		val = snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS);
-		if (mic_off)
-			val &= ~0x100;
-		else
-			val = val | 0x100;
-		snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS, val);
-	}
+	/* set GPIO0 for mic bias */
+	snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP,
+			     snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP) | 0x01);
+	snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
+			     snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x100);
 
 	/* full DAC volume */
 	snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
@@ -1251,6 +1258,9 @@
 	return 0;
 }
 
+/*
+ * C-Media CM97xx codecs
+ */
 static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {
 	AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),
 	AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
@@ -1360,7 +1370,10 @@
 	/* bit 13: enable internal vref output for mic */
 	/* bit 12: enable center/lfe */
 	/* bit 14: 0 = SPDIF, 1 = EAPD */
-	snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, 0x3000);
+	val = (1 << 12) | (1 << 13);
+	if (! (ac97->ext_id & AC97_EI_SPDIF))
+		val |= (1 << 14);
+	snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, val);
 
 	/* FIXME: set up GPIO */
 	snd_ac97_write_cache(ac97, 0x70, 0x0100);
@@ -1369,6 +1382,9 @@
 	return 0;
 }
 
+/*
+ * VIA VT1616 codec
+ */
 static const snd_kcontrol_new_t snd_ac97_controls_vt1616[] = {
 AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
 AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),

  reply	other threads:[~2004-03-03 17:54 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-03-03 17:13 ALC650 GPIO bits p z oooo
2004-03-03 17:54 ` Takashi Iwai [this message]
2004-03-05 13:16   ` CVS version (Re: ALC650 GPIO bits) Takashi Iwai
  -- strict thread matches above, loose matches on Subject: below --
2004-03-03 17:22 ALC650 GPIO bits p z oooo
2004-03-03 17:14 p z oooo
2004-03-03 15:30 Takashi Iwai
2004-03-03 15:48 ` James Courtier-Dutton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=s5h1xo9n7ee.wl@alsa2.suse.de \
    --to=tiwai@suse.de \
    --cc=James@superbug.demon.co.uk \
    --cc=alsa-devel@lists.sourceforge.net \
    --cc=mserg@gala.net \
    --cc=pzad@pobox.sk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox