[alsa-devel] [PATCH v2 01/10] ASoC: upd9976: Add Renesas uPD9976 codec driver
Lu Guanqun
guanqun.lu at intel.com
Fri May 6 07:46:03 CEST 2011
uPD9976 is a complex codec, however this patch only provides basic playback
functionality for headphone. More functionality will be added bit by bit in the
following patches.
Signed-off-by: Lu Guanqun <guanqun.lu at intel.com>
Signed-off-by: Wang Xingchao <xingchao.wang at intel.com>
---
sound/soc/codecs/Kconfig | 4
sound/soc/codecs/Makefile | 2
sound/soc/codecs/upd9976.c | 407 ++++++++++++++++++++++++++++++++++++++++++++
sound/soc/codecs/upd9976.h | 83 +++++++++
4 files changed, 496 insertions(+), 0 deletions(-)
create mode 100644 sound/soc/codecs/upd9976.c
create mode 100644 sound/soc/codecs/upd9976.h
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 2a69718..b914bc6 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -52,6 +52,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_TWL6040 if TWL4030_CORE
select SND_SOC_UDA134X
select SND_SOC_UDA1380 if I2C
+ select SND_SOC_UPD9976 if INTEL_SCU_IPC
select SND_SOC_WL1273 if MFD_WL1273_CORE
select SND_SOC_WM1250_EV1 if I2C
select SND_SOC_WM2000 if I2C
@@ -244,6 +245,9 @@ config SND_SOC_UDA134X
config SND_SOC_UDA1380
tristate
+config SND_SOC_UPD9976
+ tristate
+
config SND_SOC_WL1273
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 4cb2f42..163c623 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -37,6 +37,7 @@ snd-soc-twl4030-objs := twl4030.o
snd-soc-twl6040-objs := twl6040.o
snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o
+snd-soc-upd9976-objs := upd9976.o
snd-soc-wl1273-objs := wl1273.o
snd-soc-wm1250-ev1-objs := wm1250-ev1.o
snd-soc-wm8350-objs := wm8350.o
@@ -128,6 +129,7 @@ obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
+obj-$(CONFIG_SND_SOC_UPD9976) += snd-soc-upd9976.o
obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
diff --git a/sound/soc/codecs/upd9976.c b/sound/soc/codecs/upd9976.c
new file mode 100644
index 0000000..7642356
--- /dev/null
+++ b/sound/soc/codecs/upd9976.c
@@ -0,0 +1,407 @@
+/*
+ * upd9976.c - Renesas uPD9976 codec driver
+ *
+ * Copyright (C) 2011 Intel Corporation
+ *
+ * Maintainer:
+ * Lu Guanqun <guanqun.lu at intel.com>
+ * Wang Xingchao <xingchao.wang at intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <asm/intel_scu_ipc.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/jack.h>
+#include "upd9976.h"
+
+static inline unsigned int upd9976_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u8 value = 0;
+ int ret;
+
+ ret = intel_scu_ipc_ioread8(reg, &value);
+ if (ret)
+ dev_err(codec->dev,
+ "upd9976 read of 0x%x failed, error: %d\n", reg, ret);
+ return value;
+}
+
+static inline int upd9976_write(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int value)
+{
+ int ret;
+
+ ret = intel_scu_ipc_iowrite8(reg, value);
+ if (ret)
+ dev_err(codec->dev,
+ "upd9976 write of 0x%x failed, error: %d\n", reg, ret);
+ return ret;
+}
+
+/*
+ * Mixing Volume: from -25 dB to 6 dB in 1 dB steps.
+ */
+static DECLARE_TLV_DB_SCALE(mixer_tlv, -2500, 100, 0);
+
+/*
+ * Audio DAC Volume: From -84 dB to 10.5 dB in 0.75 steps.
+ */
+static DECLARE_TLV_DB_SCALE(adac_tlv, -8400, 75, 0);
+static const struct snd_kcontrol_new upd9976_snd_controls[] = {
+ SOC_DOUBLE_R_TLV("Master Volume",
+ UPD9976_AUDIOLVOL, UPD9976_AUDIORVOL,
+ 0, 0x7f, 1, adac_tlv),
+ SOC_DOUBLE_R_TLV("PCM Volume",
+ UPD9976_HPSPRLVOL, UPD9976_HPSPRRVOL,
+ 0, 0x1f, 1, mixer_tlv),
+};
+
+static const struct snd_kcontrol_new upd9976_hp_spkr_mixer_left_controls[] = {
+ SOC_DAPM_SINGLE("Audio DAC Left Switch", UPD9976_HPLMIXSEL, 4, 1, 1),
+ SOC_DAPM_SINGLE("Audio DAC Right Switch", UPD9976_HPLMIXSEL, 3, 1, 1),
+};
+
+static const struct snd_kcontrol_new upd9976_hp_spkr_mixer_right_controls[] = {
+ SOC_DAPM_SINGLE("Audio DAC Left Switch", UPD9976_HPRMIXSEL, 4, 1, 1),
+ SOC_DAPM_SINGLE("Audio DAC Right Switch", UPD9976_HPRMIXSEL, 3, 1, 1),
+};
+
+static const struct snd_soc_dapm_widget upd9976_dapm_widgets[] = {
+ /* Input */
+ SND_SOC_DAPM_INPUT("LINEINL"),
+ SND_SOC_DAPM_INPUT("LINEINR"),
+ SND_SOC_DAPM_INPUT("MIC1"),
+ SND_SOC_DAPM_INPUT("MIC2"),
+ SND_SOC_DAPM_INPUT("DMICDAT"),
+ SND_SOC_DAPM_INPUT("HPINL"),
+ SND_SOC_DAPM_INPUT("HPINR"),
+
+ /* Output */
+ SND_SOC_DAPM_OUTPUT("PREOUTL"),
+ SND_SOC_DAPM_OUTPUT("PREOUTR"),
+ SND_SOC_DAPM_OUTPUT("EPOUTP"),
+ SND_SOC_DAPM_OUTPUT("EPOUTN"),
+ SND_SOC_DAPM_OUTPUT("LINEOUTL"),
+ SND_SOC_DAPM_OUTPUT("LINEOUTR"),
+ SND_SOC_DAPM_OUTPUT("HPOUTL"),
+ SND_SOC_DAPM_OUTPUT("HPOUTR"),
+
+ /* DAC */
+ SND_SOC_DAPM_DAC("ADAC", "Audio Playback", UPD9976_POWERCTRL1, 0, 0),
+ SND_SOC_DAPM_DAC("VDAC", "Voice Playback", UPD9976_POWERCTRL1, 6, 0),
+
+ /* ADC */
+ SND_SOC_DAPM_ADC("AADC", "Audio Capture", UPD9976_POWERCTRL1, 1, 0),
+ SND_SOC_DAPM_ADC("VADC", "Voice Capture", UPD9976_POWERCTRL1, 7, 0),
+
+ /* Mixer */
+ SND_SOC_DAPM_MIXER("HP Spkr Mixer Left", UPD9976_POWERCTRL2, 3, 0,
+ upd9976_hp_spkr_mixer_left_controls,
+ ARRAY_SIZE(upd9976_hp_spkr_mixer_left_controls)),
+ SND_SOC_DAPM_MIXER("HP Spkr Mixer Right", UPD9976_POWERCTRL2, 2, 0,
+ upd9976_hp_spkr_mixer_right_controls,
+ ARRAY_SIZE(upd9976_hp_spkr_mixer_right_controls)),
+
+ /* Microphose Bias */
+ SND_SOC_DAPM_MICBIAS("MIC1 Bias", UPD9976_MICCTRL, 6, 0),
+ SND_SOC_DAPM_MICBIAS("MIC2 Bias", UPD9976_MICCTRL, 4, 0),
+
+ /* PGA */
+ SND_SOC_DAPM_PGA("HP Playback Left PGA", UPD9976_DRVPOWERCTRL,
+ 2, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("HP Playback Right PGA", UPD9976_DRVPOWERCTRL,
+ 1, 0, NULL, 0),
+
+};
+
+static const struct snd_soc_dapm_route upd9976_dapm_routes[] = {
+ {"HP Spkr Mixer Left", "Audio DAC Left Switch", "ADAC"},
+ {"HP Spkr Mixer Left", "Audio DAC Right Switch", "ADAC"},
+
+ {"HP Spkr Mixer Right", "Audio DAC Left Switch", "ADAC"},
+ {"HP Spkr Mixer Right", "Audio DAC Right Switch", "ADAC"},
+
+ {"PREOUTL", NULL, "HP Spkr Mixer Left"},
+ {"PREOUTR", NULL, "HP Spkr Mixer Right"},
+
+ {"HP Playback Left PGA", NULL, "HPINL"},
+ {"HP Playback Right PGA", NULL, "HPINR"},
+
+ {"HPOUTL", NULL, "HP Playback Left PGA"},
+ {"HPOUTR", NULL, "HP Playback Right PGA"},
+
+};
+
+static int upd9976_audio_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int value, mask;
+
+ /* soft mute on, fast 0.75dB/6fs */
+ value = 0;
+ if (mute)
+ value = 1;
+ mask = BIT(1) | BIT(0);
+ snd_soc_update_bits(codec, UPD9976_SOFTMUTE, mask, value);
+
+ /* mute headphone, internals speaker, internal earpiece mono */
+ value = 0;
+ if (mute)
+ value = BIT(2) | BIT(1) | BIT(0);
+ mask = BIT(2) | BIT(1) | BIT(0);
+ snd_soc_update_bits(codec, UPD9976_LMUTE, mask, value);
+
+ /* mute headphone, internal speaker */
+ value = 0;
+ if (mute)
+ value = BIT(2) | BIT(1);
+ mask = BIT(2) | BIT(1);
+ snd_soc_update_bits(codec, UPD9976_RMUTE, mask, value);
+
+ /* mute audio DAC */
+ value = 0;
+ if (mute)
+ value = BIT(7);
+ mask = BIT(7);
+ snd_soc_update_bits(codec, UPD9976_AUDIOLVOL, mask, value);
+ snd_soc_update_bits(codec, UPD9976_AUDIORVOL, mask, value);
+
+ return 0;
+}
+
+static int upd9976_audio_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int mode, mask;
+
+ mask = BIT(5) | BIT(4);
+ mode = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ mode |= BIT(4);
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ mode |= BIT(5);
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ mode |= BIT(5) | BIT(4);
+ break;
+ }
+
+ mask |= BIT(7) | BIT(3);
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ case SND_SOC_DAIFMT_CBM_CFS:
+ mode |= BIT(7) | BIT(3);
+ break;
+ }
+
+ return snd_soc_update_bits(codec, UPD9976_AUDIOPORT1, mask, mode);
+}
+
+static int upd9976_audio_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int rates[] = { 8000, 11025, 12000, 16000, 22050,
+ 24000, 32000, 0, 44100, 48000 };
+ unsigned int rate;
+ unsigned int tmp;
+ int i;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ tmp = 0x00;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ tmp = 0x03;
+ break;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ tmp = 0x01;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ tmp = 0x02;
+ break;
+ default:
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, UPD9976_AUDIOPORT1,
+ BIT(2)|BIT(1)|BIT(0), tmp);
+
+ rate = params_rate(params);
+ if (!rate)
+ return -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(rates); i++) {
+ if (rates[i] == rate) {
+ tmp = i;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(rates))
+ return -EINVAL;
+
+ snd_soc_update_bits(codec, UPD9976_AUDIOPORT2,
+ BIT(3)|BIT(2)|BIT(1)|BIT(0), tmp);
+
+ return 0;
+}
+
+static int upd9976_audio_set_tristate(struct snd_soc_dai *dai, int tristate)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ if (tristate)
+ snd_soc_update_bits(codec, UPD9976_AUDIOPORT1,
+ BIT(4)|BIT(5), 0);
+ return 0;
+}
+
+static struct snd_soc_dai_ops upd9976_audio_dai_ops = {
+ .digital_mute = upd9976_audio_digital_mute,
+ .set_fmt = upd9976_audio_set_dai_fmt,
+ .set_tristate = upd9976_audio_set_tristate,
+ .hw_params = upd9976_audio_hw_params,
+};
+
+static struct snd_soc_dai_driver upd9976_dais[] = {
+{
+ .name = "upd9976-audio",
+ .playback = {
+ .stream_name = "Audio Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = (SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_8000),
+ .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
+ SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
+ SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
+ },
+ .ops = &upd9976_audio_dai_ops,
+},
+};
+
+static int upd9976_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
+ snd_soc_update_bits(codec, UPD9976_VAUDIOCNT,
+ 0x27, 0x27);
+ snd_soc_update_bits(codec, UPD9976_VREFPLL,
+ 0x35, 0x35);
+ }
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ snd_soc_write(codec, UPD9976_VAUDIOCNT, 0x25);
+ snd_soc_write(codec, UPD9976_VREFPLL, 0x10);
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ snd_soc_write(codec, UPD9976_VREFPLL, 0);
+ snd_soc_write(codec, UPD9976_VAUDIOCNT, 0x24);
+ break;
+ }
+
+ codec->dapm.bias_level = level;
+ return 0;
+}
+
+static int upd9976_codec_probe(struct snd_soc_codec *codec)
+{
+ upd9976_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ return 0;
+}
+
+static int upd9976_codec_remove(struct snd_soc_codec *codec)
+{
+ upd9976_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver upd9976_codec = {
+ .probe = upd9976_codec_probe,
+ .remove = upd9976_codec_remove,
+ .read = upd9976_read,
+ .write = upd9976_write,
+ .set_bias_level = upd9976_set_bias_level,
+
+ .controls = upd9976_snd_controls,
+ .num_controls = ARRAY_SIZE(upd9976_snd_controls),
+ .dapm_widgets = upd9976_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(upd9976_dapm_widgets),
+ .dapm_routes = upd9976_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(upd9976_dapm_routes),
+};
+
+static int __devinit upd9976_device_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev, &upd9976_codec,
+ upd9976_dais, ARRAY_SIZE(upd9976_dais));
+}
+
+static int __devexit upd9976_device_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver upd9976_codec_driver = {
+ .driver = {
+ .name = "upd9976",
+ .owner = THIS_MODULE,
+ },
+ .probe = upd9976_device_probe,
+ .remove = __devexit_p(upd9976_device_remove),
+};
+
+static int __init upd9976_init(void)
+{
+ return platform_driver_register(&upd9976_codec_driver);
+}
+module_init(upd9976_init);
+
+static void __exit upd9976_exit(void)
+{
+ platform_driver_unregister(&upd9976_codec_driver);
+}
+module_exit(upd9976_exit);
+
+MODULE_DESCRIPTION("ASoC Renesas uPD9976 codec driver");
+MODULE_AUTHOR("Lu Guanqun <guanqun.lu at intel.com>");
+MODULE_AUTHOR("Wang Xingchao <xingchao.wang at intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:upd9976");
diff --git a/sound/soc/codecs/upd9976.h b/sound/soc/codecs/upd9976.h
new file mode 100644
index 0000000..ab2ea15
--- /dev/null
+++ b/sound/soc/codecs/upd9976.h
@@ -0,0 +1,83 @@
+/*
+ * upd9976.h - Renesas uPD9976 codec driver
+ *
+ * Copyright (C) 2011 Intel Corporation
+ *
+ * Maintainer:
+ * Lu Guanqun <guanqun.lu at intel.com>
+ * Wang Xingchao <xingchao.wang at intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef _UPD9976_H
+#define _UPD9976_H
+
+#define UPD9976_VAUDIOCNT 0x51
+
+#define UPD9976_VOICEPORT1 0x100
+#define UPD9976_VOICEPORT2 0x101
+#define UPD9976_AUDIOPORT1 0x102
+#define UPD9976_AUDIOPORT2 0x103
+#define UPD9976_ADCSAMPLERATE 0x104
+#define UPD9976_DMICCTRL1 0x105
+#define UPD9976_DMICCTRL2 0x106
+#define UPD9976_MICCTRL 0x107
+#define UPD9976_MICSELVOL 0x108
+#define UPD9976_LILSEL 0x109
+#define UPD9976_LIRSEL 0x10a
+#define UPD9976_VOICEVOL 0x10b
+#define UPD9976_AUDIOLVOL 0x10c
+#define UPD9976_AUDIORVOL 0x10d
+#define UPD9976_LMUTE 0x10e
+#define UPD9976_RMUTE 0x10f
+#define UPD9976_POWERCTRL1 0x110
+#define UPD9976_POWERCTRL2 0x111
+#define UPD9976_DRVPOWERCTRL 0x112
+#define UPD9976_VREFPLL 0x113
+#define UPD9976_PCMBUFCTRL 0x114
+#define UPD9976_SOFTMUTE 0x115
+#define UPD9976_DTMFPATH 0x116
+#define UPD9976_DTMFVOL 0x117
+#define UPD9976_DTMFFREQ 0x118
+#define UPD9976_DTMFHFREQ 0x119
+#define UPD9976_DTMFLFREQ 0x11a
+#define UPD9976_DTMFCTRL 0x11b
+#define UPD9976_DTMFASON 0x11c
+#define UPD9976_DTMFASOFF 0x11d
+#define UPD9976_DTMFASINUM 0x11e
+#define UPD9976_CLASSDVOL 0x11f
+#define UPD9976_VOICEDACAVOL 0x120
+#define UPD9976_AUDDACAVOL 0x121
+#define UPD9976_LOMUTEVOL 0x122
+#define UPD9976_HPSPRLVOL 0x123
+#define UPD9976_HPSPRRVOL 0x124
+#define UPD9976_MONOVOL 0x125
+#define UPD9976_LINEOUTMIXVOL 0x126
+#define UPD9976_EPMIXVOL 0x127
+#define UPD9976_LINEOUTLSEL 0x128
+#define UPD9976_LINEOUTRSEL 0x129
+#define UPD9976_EPMIXOUTSEL 0x12a
+#define UPD9976_HPLMIXSEL 0x12b
+#define UPD9976_HPRMIXSEL 0x12c
+#define UPD9976_LOANTIPOP 0x12d
+#define UPD9976_AUXDBNC 0x12f
+
+#define UPD9976_SAUXINT 0x132
+
+#endif
More information about the Alsa-devel
mailing list