[alsa-devel] [RFC] virtual master control (3/3)

Takashi Iwai tiwai at suse.de
Fri Nov 23 18:33:10 CET 2007


[PATCH] AC97 virtual master control

This patch adds the virtual master control to AC97-related drivers.
It's needed for surround outputs.
At this moment, it's added when vmaster=1 option is given to either
snd-intel8x0, snd-atiixp or snd-via82xx driver.

For automatic addition of vmaster control, we'll need to resolve the
following 

- whether the vmaster is really needed (most machines have only front
  output)
- disable AD-mode on AD codecs (to back to the normal AC97 volume
  control mode)


---

diff -r 5c48888d1307 include/ac97_codec.h
--- a/include/ac97_codec.h	Tue Sep 18 15:48:30 2007 +0200
+++ b/include/ac97_codec.h	Tue Sep 18 15:48:48 2007 +0200
@@ -595,6 +595,7 @@ struct ac97_quirk {
 
 int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, const char *override);
 int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate);
+int snd_ac97_add_vmaster(struct snd_ac97 *ac97);
 
 /*
  * PCM allocation
diff -r 5c48888d1307 pci/Kconfig
--- a/pci/Kconfig	Tue Sep 18 15:48:30 2007 +0200
+++ b/pci/Kconfig	Tue Sep 18 15:48:48 2007 +0200
@@ -59,6 +59,7 @@ config SND_ATIIXP
 	tristate "ATI IXP AC97 Controller"
 	depends on SND
 	select SND_AC97_CODEC
+	select SND_VMASTER
 	help
 	  Say Y here to include support for the integrated AC97 sound
 	  device on motherboards with ATI chipsets (ATI IXP 150/200/250/
@@ -664,6 +665,7 @@ config SND_INTEL8X0
 	tristate "Intel/SiS/nVidia/AMD/ALi AC97 Controller"
 	depends on SND
 	select SND_AC97_CODEC
+	select SND_VMASTER
 	help
 	  Say Y here to include support for the integrated AC97 sound
 	  device on motherboards with Intel/SiS/nVidia/AMD chipsets, or
@@ -835,6 +837,7 @@ config SND_VIA82XX
 	depends on SND
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
+	select SND_VMASTER
 	help
 	  Say Y here to include support for the integrated AC97 sound
 	  device on motherboards with VIA chipsets.
diff -r 5c48888d1307 pci/ac97/ac97_codec.c
--- a/pci/ac97/ac97_codec.c	Tue Sep 18 15:48:30 2007 +0200
+++ b/pci/ac97/ac97_codec.c	Tue Sep 18 15:48:48 2007 +0200
@@ -2871,6 +2871,65 @@ int snd_ac97_tune_hardware(struct snd_ac
 
 EXPORT_SYMBOL(snd_ac97_tune_hardware);
 
+#ifdef CONFIG_SND_VMASTER
+/*
+ * create a virtual master control (if surround is supported)
+ */
+static const char *slave_items[] = {
+	"Front", "Surround", "Center", "LFE", "Side", "Headphone", "Mono",
+	NULL
+};
+
+static int add_vmaster(struct snd_ac97 *ac97, char *suffix, int has_tlv)
+{
+	struct snd_kcontrol *sctl;
+	struct snd_kcontrol *kctl;
+	const unsigned int *tlv = NULL;
+	char name[32];
+	const char **s;
+	int err;
+
+	sctl = ctl_find(ac97, "Surround", suffix);
+	if (!sctl)
+		return 0; /* no surrounds */
+	if (has_tlv)
+		tlv = find_db_scale((sctl->private_value >> 16) & 0xff);
+
+	if (snd_ac97_rename_ctl(ac97, "Master", "Front", suffix) < 0)
+		return 0; /* front already exists */
+	snd_ac97_rename_ctl(ac97, "Master Mono", "Mono", suffix);
+
+	sprintf(name, "Master %s", suffix);
+	kctl = snd_ctl_make_virtual_master(name, tlv);
+	if (!kctl)
+		return -ENOMEM;
+
+	err = snd_ctl_add(ac97->bus->card, kctl);
+	if (err < 0)
+		return err;
+	for (s = slave_items; *s; s++) {
+		sctl = ctl_find(ac97, *s, suffix);
+		if (!sctl)
+			continue;
+		err = snd_ctl_add_slave(kctl, sctl);
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+int snd_ac97_add_vmaster(struct snd_ac97 *ac97)
+{
+	int err;
+	err = add_vmaster(ac97, "Playback Volume", 1);
+	if (err < 0)
+		return err;
+	return add_vmaster(ac97, "Playback Switch", 0);
+}
+
+EXPORT_SYMBOL(snd_ac97_add_vmaster);
+#endif
+
 /*
  *  INIT part
  */
diff -r 5c48888d1307 pci/atiixp.c
--- a/pci/atiixp.c	Tue Sep 18 15:48:30 2007 +0200
+++ b/pci/atiixp.c	Tue Sep 18 15:48:48 2007 +0200
@@ -46,6 +46,7 @@ static char *ac97_quirk;
 static char *ac97_quirk;
 static int spdif_aclink = 1;
 static int ac97_codec = -1;
+static int vmaster;
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for ATI IXP controller.");
@@ -59,6 +60,8 @@ MODULE_PARM_DESC(ac97_codec, "Specify co
 MODULE_PARM_DESC(ac97_codec, "Specify codec instead of probing.");
 module_param(spdif_aclink, bool, 0444);
 MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
+module_param(vmaster, bool, 0444);
+MODULE_PARM_DESC(vmaster, "Add a virtual master volume if needed.");
 
 /* just for backward compatibility */
 static int enable;
@@ -1442,6 +1445,8 @@ static int __devinit snd_atiixp_mixer_ne
 	}
 
 	snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks, quirk_override);
+	if (vmaster)
+		snd_ac97_add_vmaster(chip->ac97[0]);
 
 	return 0;
 }
diff -r 5c48888d1307 pci/intel8x0.c
--- a/pci/intel8x0.c	Tue Sep 18 15:48:30 2007 +0200
+++ b/pci/intel8x0.c	Tue Sep 18 15:48:48 2007 +0200
@@ -72,6 +72,7 @@ static int buggy_irq = -1; /* auto-check
 static int buggy_irq = -1; /* auto-check */
 static int xbox;
 static int spdif_aclink = -1;
+static int vmaster;
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
@@ -89,6 +90,8 @@ MODULE_PARM_DESC(xbox, "Set to 1 for Xbo
 MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection.");
 module_param(spdif_aclink, int, 0444);
 MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
+module_param(vmaster, bool, 0444);
+MODULE_PARM_DESC(vmaster, "Add a virtual master volume if needed.");
 
 /* just for backward compatibility */
 static int enable;
@@ -2149,6 +2152,8 @@ static int __devinit snd_intel8x0_mixer(
 	}
 	/* tune up the primary codec */
 	snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks, quirk_override);
+	if (vmaster)
+		snd_ac97_add_vmaster(chip->ac97[0]);
 	/* enable separate SDINs for ICH4 */
 	if (chip->device_type == DEVICE_INTEL_ICH4)
 		pbus->isdin = 1;
diff -r 5c48888d1307 pci/via82xx.c
--- a/pci/via82xx.c	Tue Sep 18 15:48:30 2007 +0200
+++ b/pci/via82xx.c	Tue Sep 18 15:48:48 2007 +0200
@@ -86,6 +86,7 @@ static int ac97_clock = 48000;
 static int ac97_clock = 48000;
 static char *ac97_quirk;
 static int dxs_support;
+static int vmaster;
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge.");
@@ -103,6 +104,8 @@ MODULE_PARM_DESC(ac97_quirk, "AC'97 work
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
 module_param(dxs_support, int, 0444);
 MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)");
+module_param(vmaster, bool, 0444);
+MODULE_PARM_DESC(vmaster, "Add a virtual master volume if needed.");
 
 /* just for backward compatibility */
 static int enable;
@@ -1820,6 +1823,8 @@ static int __devinit snd_via82xx_mixer_n
 		return err;
 
 	snd_ac97_tune_hardware(chip->ac97, ac97_quirks, quirk_override);
+	if (vmaster)
+		snd_ac97_add_vmaster(chip->ac97);
 
 	if (chip->chip_type != TYPE_VIA686) {
 		/* use slot 10/11 */


More information about the Alsa-devel mailing list