[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 */