From 50e6168f27fdc1f915d3341743b46147c626dc6e Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Mon, 28 Sep 2015 14:01:08 +0100 Subject: ASoC: arizona: add defines for single-input gain control Adds convenience defines for declaring a gain control that has an input mux. These blocks are functionally equivalent to the existing mixer blocks but can only have a single input active at once. Signed-off-by: Richard Fitzgerald Acked-by: Mark Brown Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 7b68d05a0939..b73920ab8650 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -99,6 +99,11 @@ extern const unsigned int arizona_mixer_tlv[]; extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS]; extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; +#define ARIZONA_GAINMUX_CONTROLS(name, base) \ + SOC_SINGLE_RANGE_TLV(name " Input Volume", base + 1, \ + ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ + arizona_mixer_tlv) + #define ARIZONA_MIXER_CONTROLS(name, base) \ SOC_SINGLE_RANGE_TLV(name " Input 1 Volume", base + 1, \ ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ -- cgit v1.2.3-59-g8ed1b From 6ebbce0a6e15fd52ef029f780ec5fb3282fc22e3 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Mon, 28 Sep 2015 14:01:09 +0100 Subject: ASoC: wm8998: Initial WM8998 codec driver Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/arizona.c | 33 + sound/soc/codecs/arizona.h | 7 +- sound/soc/codecs/wm8998.c | 1430 ++++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/wm8998.h | 23 + 6 files changed, 1500 insertions(+), 1 deletion(-) create mode 100644 sound/soc/codecs/wm8998.c create mode 100644 sound/soc/codecs/wm8998.h (limited to 'sound') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0c9733ecd17f..6c30bade64b6 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -171,6 +171,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8996 if I2C select SND_SOC_WM8997 if MFD_WM8997 + select SND_SOC_WM8998 if MFD_WM8998 select SND_SOC_WM9081 if I2C select SND_SOC_WM9090 if I2C select SND_SOC_WM9705 if SND_SOC_AC97_BUS @@ -195,9 +196,11 @@ config SND_SOC_ARIZONA default y if SND_SOC_WM5102=y default y if SND_SOC_WM5110=y default y if SND_SOC_WM8997=y + default y if SND_SOC_WM8998=y default m if SND_SOC_WM5102=m default m if SND_SOC_WM5110=m default m if SND_SOC_WM8997=m + default m if SND_SOC_WM8998=m config SND_SOC_WM_HUBS tristate @@ -865,6 +868,9 @@ config SND_SOC_WM8996 config SND_SOC_WM8997 tristate +config SND_SOC_WM8998 + tristate + config SND_SOC_WM9081 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 4a32077954ae..a9d47693aa56 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -176,6 +176,7 @@ snd-soc-wm8993-objs := wm8993.o snd-soc-wm8994-objs := wm8994.o wm8958-dsp2.o snd-soc-wm8995-objs := wm8995.o snd-soc-wm8997-objs := wm8997.o +snd-soc-wm8998-objs := wm8998.o snd-soc-wm9081-objs := wm9081.o snd-soc-wm9090-objs := wm9090.o snd-soc-wm9705-objs := wm9705.o @@ -364,6 +365,7 @@ obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o obj-$(CONFIG_SND_SOC_WM8997) += snd-soc-wm8997.o +obj-$(CONFIG_SND_SOC_WM8998) += snd-soc-wm8998.o obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index ac21b85ff75f..9929efc6b9aa 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -316,6 +316,7 @@ const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { "Tone Generator 2", "Haptics", "AEC", + "AEC2", "Mic Mute Mixer", "Noise Generator", "IN1L", @@ -423,6 +424,7 @@ int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = { 0x05, 0x06, /* Haptics */ 0x08, /* AEC */ + 0x09, /* AEC2 */ 0x0c, /* Noise mixer */ 0x0d, /* Comfort noise */ 0x10, /* IN1L */ @@ -527,6 +529,32 @@ EXPORT_SYMBOL_GPL(arizona_mixer_values); const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0); EXPORT_SYMBOL_GPL(arizona_mixer_tlv); +const char * const arizona_sample_rate_text[ARIZONA_SAMPLE_RATE_ENUM_SIZE] = { + "12kHz", "24kHz", "48kHz", "96kHz", "192kHz", + "11.025kHz", "22.05kHz", "44.1kHz", "88.2kHz", "176.4kHz", + "4kHz", "8kHz", "16kHz", "32kHz", +}; +EXPORT_SYMBOL_GPL(arizona_sample_rate_text); + +const unsigned int arizona_sample_rate_val[ARIZONA_SAMPLE_RATE_ENUM_SIZE] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x10, 0x11, 0x12, 0x13, +}; +EXPORT_SYMBOL_GPL(arizona_sample_rate_val); + +const char *arizona_sample_rate_val_to_name(unsigned int rate_val) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(arizona_sample_rate_val); ++i) { + if (arizona_sample_rate_val[i] == rate_val) + return arizona_sample_rate_text[i]; + } + + return "Illegal"; +} +EXPORT_SYMBOL_GPL(arizona_sample_rate_val_to_name); + const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = { "SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate", }; @@ -1884,6 +1912,11 @@ static int arizona_calc_fratio(struct arizona_fll *fll, if (fll->arizona->rev < 3 || sync) return init_ratio; break; + case WM8998: + case WM1814: + if (sync) + return init_ratio; + break; default: return init_ratio; } diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index b73920ab8650..fea8b8ae8e1a 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -93,7 +93,7 @@ struct arizona_priv { bool dvfs_cached; }; -#define ARIZONA_NUM_MIXER_INPUTS 103 +#define ARIZONA_NUM_MIXER_INPUTS 104 extern const unsigned int arizona_mixer_tlv[]; extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS]; @@ -214,8 +214,12 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; .num_regs = 1 }) } #define ARIZONA_RATE_ENUM_SIZE 4 +#define ARIZONA_SAMPLE_RATE_ENUM_SIZE 14 + extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE]; extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE]; +extern const char * const arizona_sample_rate_text[ARIZONA_SAMPLE_RATE_ENUM_SIZE]; +extern const unsigned int arizona_sample_rate_val[ARIZONA_SAMPLE_RATE_ENUM_SIZE]; extern const struct soc_enum arizona_isrc_fsl[]; extern const struct soc_enum arizona_isrc_fsh[]; @@ -301,4 +305,5 @@ int arizona_set_output_mode(struct snd_soc_codec *codec, int output, extern bool arizona_input_analog(struct snd_soc_codec *codec, int shift); +extern const char *arizona_sample_rate_val_to_name(unsigned int rate_val); #endif diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c new file mode 100644 index 000000000000..8782dfb628ab --- /dev/null +++ b/sound/soc/codecs/wm8998.c @@ -0,0 +1,1430 @@ +/* + * wm8998.c -- ALSA SoC Audio driver for WM8998 codecs + * + * Copyright 2015 Cirrus Logic, Inc. + * + * Author: Richard Fitzgerald + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "arizona.h" +#include "wm8998.h" + +struct wm8998_priv { + struct arizona_priv core; + struct arizona_fll fll[2]; +}; + +static int wm8998_asrc_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + unsigned int val; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + val = snd_soc_read(codec, ARIZONA_ASRC_RATE1); + val &= ARIZONA_ASRC_RATE1_MASK; + val >>= ARIZONA_ASRC_RATE1_SHIFT; + + switch (val) { + case 0: + case 1: + case 2: + val = snd_soc_read(codec, + ARIZONA_SAMPLE_RATE_1 + val); + if (val >= 0x11) { + dev_warn(codec->dev, + "Unsupported ASRC rate1 (%s)\n", + arizona_sample_rate_val_to_name(val)); + return -EINVAL; + } + break; + default: + dev_err(codec->dev, + "Illegal ASRC rate1 selector (0x%x)\n", + val); + return -EINVAL; + } + + val = snd_soc_read(codec, ARIZONA_ASRC_RATE2); + val &= ARIZONA_ASRC_RATE2_MASK; + val >>= ARIZONA_ASRC_RATE2_SHIFT; + + switch (val) { + case 8: + case 9: + val -= 0x8; + val = snd_soc_read(codec, + ARIZONA_ASYNC_SAMPLE_RATE_1 + val); + if (val >= 0x11) { + dev_warn(codec->dev, + "Unsupported ASRC rate2 (%s)\n", + arizona_sample_rate_val_to_name(val)); + return -EINVAL; + } + break; + default: + dev_err(codec->dev, + "Illegal ASRC rate2 selector (0x%x)\n", + val); + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return 0; +} + +static int wm8998_in1mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + struct wm8998_priv *wm8998 = snd_soc_codec_get_drvdata(codec); + struct arizona *arizona = wm8998->core.arizona; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int mux, inmode; + unsigned int mode_val, src_val; + + mux = ucontrol->value.enumerated.item[0]; + if (mux > 1) + return -EINVAL; + + /* L and R registers have same shift and mask */ + inmode = arizona->pdata.inmode[2 * mux]; + src_val = mux << ARIZONA_IN1L_SRC_SHIFT; + if (inmode & ARIZONA_INMODE_SE) + src_val |= 1 << ARIZONA_IN1L_SRC_SE_SHIFT; + + switch (arizona->pdata.inmode[0]) { + case ARIZONA_INMODE_DMIC: + if (mux) + mode_val = 0; /* B always analogue */ + else + mode_val = 1 << ARIZONA_IN1_MODE_SHIFT; + + snd_soc_update_bits(codec, ARIZONA_IN1L_CONTROL, + ARIZONA_IN1_MODE_MASK, mode_val); + + /* IN1A is digital so L and R must change together */ + /* src_val setting same for both registers */ + snd_soc_update_bits(codec, + ARIZONA_ADC_DIGITAL_VOLUME_1L, + ARIZONA_IN1L_SRC_MASK | + ARIZONA_IN1L_SRC_SE_MASK, src_val); + snd_soc_update_bits(codec, + ARIZONA_ADC_DIGITAL_VOLUME_1R, + ARIZONA_IN1R_SRC_MASK | + ARIZONA_IN1R_SRC_SE_MASK, src_val); + break; + default: + /* both analogue */ + snd_soc_update_bits(codec, + e->reg, + ARIZONA_IN1L_SRC_MASK | + ARIZONA_IN1L_SRC_SE_MASK, + src_val); + break; + } + + return snd_soc_dapm_mux_update_power(dapm, kcontrol, + ucontrol->value.enumerated.item[0], + e, NULL); +} + +static int wm8998_in2mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + struct wm8998_priv *wm8998 = snd_soc_codec_get_drvdata(codec); + struct arizona *arizona = wm8998->core.arizona; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int mux, inmode, src_val, mode_val; + + mux = ucontrol->value.enumerated.item[0]; + if (mux > 1) + return -EINVAL; + + inmode = arizona->pdata.inmode[1 + (2 * mux)]; + if (inmode & ARIZONA_INMODE_DMIC) + mode_val = 1 << ARIZONA_IN2_MODE_SHIFT; + else + mode_val = 0; + + src_val = mux << ARIZONA_IN2L_SRC_SHIFT; + if (inmode & ARIZONA_INMODE_SE) + src_val |= 1 << ARIZONA_IN2L_SRC_SE_SHIFT; + + snd_soc_update_bits(codec, ARIZONA_IN2L_CONTROL, + ARIZONA_IN2_MODE_MASK, mode_val); + + snd_soc_update_bits(codec, ARIZONA_ADC_DIGITAL_VOLUME_2L, + ARIZONA_IN2L_SRC_MASK | ARIZONA_IN2L_SRC_SE_MASK, + src_val); + + return snd_soc_dapm_mux_update_power(dapm, kcontrol, + ucontrol->value.enumerated.item[0], + e, NULL); +} + +static const char * const wm8998_inmux_texts[] = { + "A", + "B", +}; + +static const SOC_ENUM_SINGLE_DECL(wm8998_in1muxl_enum, + ARIZONA_ADC_DIGITAL_VOLUME_1L, + ARIZONA_IN1L_SRC_SHIFT, + wm8998_inmux_texts); + +static const SOC_ENUM_SINGLE_DECL(wm8998_in1muxr_enum, + ARIZONA_ADC_DIGITAL_VOLUME_1R, + ARIZONA_IN1R_SRC_SHIFT, + wm8998_inmux_texts); + +static const SOC_ENUM_SINGLE_DECL(wm8998_in2mux_enum, + ARIZONA_ADC_DIGITAL_VOLUME_2L, + ARIZONA_IN2L_SRC_SHIFT, + wm8998_inmux_texts); + +static const struct snd_kcontrol_new wm8998_in1mux[2] = { + SOC_DAPM_ENUM_EXT("IN1L Mux", wm8998_in1muxl_enum, + snd_soc_dapm_get_enum_double, wm8998_in1mux_put), + SOC_DAPM_ENUM_EXT("IN1R Mux", wm8998_in1muxr_enum, + snd_soc_dapm_get_enum_double, wm8998_in1mux_put), +}; + +static const struct snd_kcontrol_new wm8998_in2mux = + SOC_DAPM_ENUM_EXT("IN2 Mux", wm8998_in2mux_enum, + snd_soc_dapm_get_enum_double, wm8998_in2mux_put); + +static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); +static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); +static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); +static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); + +#define WM8998_NG_SRC(name, base) \ + SOC_SINGLE(name " NG HPOUTL Switch", base, 0, 1, 0), \ + SOC_SINGLE(name " NG HPOUTR Switch", base, 1, 1, 0), \ + SOC_SINGLE(name " NG LINEOUTL Switch", base, 2, 1, 0), \ + SOC_SINGLE(name " NG LINEOUTR Switch", base, 3, 1, 0), \ + SOC_SINGLE(name " NG EPOUT Switch", base, 4, 1, 0), \ + SOC_SINGLE(name " NG SPKOUTL Switch", base, 6, 1, 0), \ + SOC_SINGLE(name " NG SPKOUTR Switch", base, 7, 1, 0) + +static const struct snd_kcontrol_new wm8998_snd_controls[] = { +SOC_ENUM("IN1 OSR", arizona_in_dmic_osr[0]), +SOC_ENUM("IN2 OSR", arizona_in_dmic_osr[1]), + +SOC_SINGLE_RANGE_TLV("IN1L Volume", ARIZONA_IN1L_CONTROL, + ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), +SOC_SINGLE_RANGE_TLV("IN1R Volume", ARIZONA_IN1R_CONTROL, + ARIZONA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), +SOC_SINGLE_RANGE_TLV("IN2 Volume", ARIZONA_IN2L_CONTROL, + ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), + +SOC_ENUM("IN HPF Cutoff Frequency", arizona_in_hpf_cut_enum), + +SOC_SINGLE("IN1L HPF Switch", ARIZONA_IN1L_CONTROL, + ARIZONA_IN1L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN1R HPF Switch", ARIZONA_IN1R_CONTROL, + ARIZONA_IN1R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN2 HPF Switch", ARIZONA_IN2L_CONTROL, + ARIZONA_IN2L_HPF_SHIFT, 1, 0), + +SOC_SINGLE_TLV("IN1L Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L, + ARIZONA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv), +SOC_SINGLE_TLV("IN1R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1R, + ARIZONA_IN1R_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv), +SOC_SINGLE_TLV("IN2 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L, + ARIZONA_IN2L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv), + +SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp), +SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp), + +ARIZONA_GAINMUX_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE), +ARIZONA_GAINMUX_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), +ARIZONA_GAINMUX_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), +ARIZONA_GAINMUX_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), + +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), +SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE_SHIFT, 1, 0), +SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ1 B3 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B3_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, + 24, 0, eq_tlv), + +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), +SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE_SHIFT, 1, 0), +SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ2 B3 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B3_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, + 24, 0, eq_tlv), + +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), +SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE_SHIFT, 1, 0), +SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ3 B3 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B3_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, + 24, 0, eq_tlv), + +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), +SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE_SHIFT, 1, 0), +SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ4 B3 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B3_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ4 B4 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B4_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT, + 24, 0, eq_tlv), + +ARIZONA_GAINMUX_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE), +ARIZONA_GAINMUX_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE), + +SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5, + ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA), + +ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), + +SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1), +SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1), +SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1), +SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1), + +SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode), +SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), +SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), +SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), + +SOC_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]), +SOC_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]), +SOC_ENUM("ISRC1 FSH", arizona_isrc_fsh[0]), +SOC_ENUM("ISRC2 FSH", arizona_isrc_fsh[1]), +SOC_ENUM("ASRC RATE 1", arizona_asrc_rate1), + +ARIZONA_MIXER_CONTROLS("HPOUTL", ARIZONA_OUT1LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("HPOUTR", ARIZONA_OUT1RMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("LINEOUTL", ARIZONA_OUT2LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("LINEOUTR", ARIZONA_OUT2RMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("SPKDATL", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("SPKDATR", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), + +SOC_DOUBLE_R("HPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L, + ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("LINEOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, + ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1), +SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L, + ARIZONA_OUT3L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L, + ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("SPKDAT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L, + ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_MUTE_SHIFT, 1, 1), + +SOC_DOUBLE_R_TLV("HPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L, + ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT, + 0xbf, 0, digital_tlv), +SOC_DOUBLE_R_TLV("LINEOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L, + ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT, + 0xbf, 0, digital_tlv), +SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L, + ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv), +SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L, + ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT, + 0xbf, 0, digital_tlv), +SOC_DOUBLE_R_TLV("SPKDAT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L, + ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT, + 0xbf, 0, digital_tlv), + +SOC_DOUBLE("SPKDAT Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, + ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), + +SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), +SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), + +SOC_SINGLE("Noise Gate Switch", ARIZONA_NOISE_GATE_CONTROL, + ARIZONA_NGATE_ENA_SHIFT, 1, 0), +SOC_SINGLE_TLV("Noise Gate Threshold Volume", ARIZONA_NOISE_GATE_CONTROL, + ARIZONA_NGATE_THR_SHIFT, 7, 1, ng_tlv), +SOC_ENUM("Noise Gate Hold", arizona_ng_hold), + +WM8998_NG_SRC("HPOUTL", ARIZONA_NOISE_GATE_SELECT_1L), +WM8998_NG_SRC("HPOUTR", ARIZONA_NOISE_GATE_SELECT_1R), +WM8998_NG_SRC("LINEOUTL", ARIZONA_NOISE_GATE_SELECT_2L), +WM8998_NG_SRC("LINEOUTR", ARIZONA_NOISE_GATE_SELECT_2R), +WM8998_NG_SRC("EPOUT", ARIZONA_NOISE_GATE_SELECT_3L), +WM8998_NG_SRC("SPKOUTL", ARIZONA_NOISE_GATE_SELECT_4L), +WM8998_NG_SRC("SPKOUTR", ARIZONA_NOISE_GATE_SELECT_4R), +WM8998_NG_SRC("SPKDATL", ARIZONA_NOISE_GATE_SELECT_5L), +WM8998_NG_SRC("SPKDATR", ARIZONA_NOISE_GATE_SELECT_5R), + +ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF1TX4", ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF1TX5", ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF1TX6", ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE), + +ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF2TX3", ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF2TX4", ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF2TX5", ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF2TX6", ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE), + +ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), + +ARIZONA_GAINMUX_CONTROLS("SLIMTX1", ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE), +ARIZONA_GAINMUX_CONTROLS("SLIMTX2", ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE), +ARIZONA_GAINMUX_CONTROLS("SLIMTX3", ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE), +ARIZONA_GAINMUX_CONTROLS("SLIMTX4", ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE), +ARIZONA_GAINMUX_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE), +ARIZONA_GAINMUX_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE), + +ARIZONA_GAINMUX_CONTROLS("SPDIFTX1", ARIZONA_SPDIFTX1MIX_INPUT_1_SOURCE), +ARIZONA_GAINMUX_CONTROLS("SPDIFTX2", ARIZONA_SPDIFTX2MIX_INPUT_1_SOURCE), +}; + +ARIZONA_MUX_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE); + +ARIZONA_MUX_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(PWM1, ARIZONA_PWM1MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(PWM2, ARIZONA_PWM2MIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(SPKDATL, ARIZONA_OUT5LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(SPKDATR, ARIZONA_OUT5RMIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(AIF1TX1, ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF1TX2, ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF1TX3, ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF1TX4, ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF1TX5, ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF1TX6, ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF2TX3, ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF2TX4, ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF2TX5, ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF2TX6, ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); + +ARIZONA_MUX_ENUMS(SLIMTX1, ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(SLIMTX2, ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(SLIMTX3, ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(SLIMTX4, ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(SLIMTX5, ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(SLIMTX6, ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE); + +ARIZONA_MUX_ENUMS(SPD1TX1, ARIZONA_SPDIFTX1MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(SPD1TX2, ARIZONA_SPDIFTX2MIX_INPUT_1_SOURCE); + +ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); + +ARIZONA_MUX_ENUMS(ISRC1INT1, ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(ISRC1INT2, ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(ISRC1INT3, ARIZONA_ISRC1INT3MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(ISRC1INT4, ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE); + +ARIZONA_MUX_ENUMS(ISRC1DEC1, ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(ISRC1DEC2, ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(ISRC1DEC3, ARIZONA_ISRC1DEC3MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(ISRC1DEC4, ARIZONA_ISRC1DEC4MIX_INPUT_1_SOURCE); + +ARIZONA_MUX_ENUMS(ISRC2INT1, ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(ISRC2INT2, ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE); + +ARIZONA_MUX_ENUMS(ISRC2DEC1, ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE); +ARIZONA_MUX_ENUMS(ISRC2DEC2, ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE); + +static const char * const wm8998_aec_loopback_texts[] = { + "HPOUTL", "HPOUTR", "LINEOUTL", "LINEOUTR", "EPOUT", + "SPKOUTL", "SPKOUTR", "SPKDATL", "SPKDATR", +}; + +static const unsigned int wm8998_aec_loopback_values[] = { + 0, 1, 2, 3, 4, 6, 7, 8, 9, +}; + +static const SOC_VALUE_ENUM_SINGLE_DECL(wm8998_aec1_loopback, + ARIZONA_DAC_AEC_CONTROL_1, + ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf, + wm8998_aec_loopback_texts, + wm8998_aec_loopback_values); + +static const SOC_VALUE_ENUM_SINGLE_DECL(wm8998_aec2_loopback, + ARIZONA_DAC_AEC_CONTROL_2, + ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf, + wm8998_aec_loopback_texts, + wm8998_aec_loopback_values); + +static const struct snd_kcontrol_new wm8998_aec_loopback_mux[] = { + SOC_DAPM_ENUM("AEC1 Loopback", wm8998_aec1_loopback), + SOC_DAPM_ENUM("AEC2 Loopback", wm8998_aec2_loopback), +}; + +static const struct snd_soc_dapm_widget wm8998_dapm_widgets[] = { +SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, + ARIZONA_SYSCLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, + ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, + ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, + ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), + +SND_SOC_DAPM_SIGGEN("TONE"), +SND_SOC_DAPM_SIGGEN("HAPTICS"), + +SND_SOC_DAPM_INPUT("IN1AL"), +SND_SOC_DAPM_INPUT("IN1AR"), +SND_SOC_DAPM_INPUT("IN1BL"), +SND_SOC_DAPM_INPUT("IN1BR"), +SND_SOC_DAPM_INPUT("IN2A"), +SND_SOC_DAPM_INPUT("IN2B"), + +SND_SOC_DAPM_MUX("IN1L Mux", SND_SOC_NOPM, 0, 0, &wm8998_in1mux[0]), +SND_SOC_DAPM_MUX("IN1R Mux", SND_SOC_NOPM, 0, 0, &wm8998_in1mux[1]), +SND_SOC_DAPM_MUX("IN2 Mux", SND_SOC_NOPM, 0, 0, &wm8998_in2mux), + +SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"), + +SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, + 0, NULL, 0, arizona_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, + 0, NULL, 0, arizona_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2 PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, + 0, NULL, 0, arizona_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, + ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2, + ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3, + ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1, + ARIZONA_TONE1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1, + ARIZONA_TONE2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("EQ1", ARIZONA_EQ1_1, ARIZONA_EQ1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ2", ARIZONA_EQ2_1, ARIZONA_EQ2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ3", ARIZONA_EQ3_1, ARIZONA_EQ3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ4", ARIZONA_EQ4_1, ARIZONA_EQ4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF2", ARIZONA_HPLPF2_1, ARIZONA_LHPF2_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF3", ARIZONA_HPLPF3_1, ARIZONA_LHPF3_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF4", ARIZONA_HPLPF4_1, ARIZONA_LHPF4_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("PWM1 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM1_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_PGA("PWM2 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM2_ENA_SHIFT, + 0, NULL, 0), + +SND_SOC_DAPM_PGA_E("ASRC1L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1L_ENA_SHIFT, 0, + NULL, 0, wm8998_asrc_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_PGA_E("ASRC1R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1R_ENA_SHIFT, 0, + NULL, 0, wm8998_asrc_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_PGA_E("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, + NULL, 0, wm8998_asrc_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_PGA_E("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, + NULL, 0, wm8998_asrc_ev, SND_SOC_DAPM_PRE_PMU), + +SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3, + ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT2", ARIZONA_ISRC_1_CTRL_3, + ARIZONA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT3", ARIZONA_ISRC_1_CTRL_3, + ARIZONA_ISRC1_INT2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT4", ARIZONA_ISRC_1_CTRL_3, + ARIZONA_ISRC1_INT3_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC1DEC1", ARIZONA_ISRC_1_CTRL_3, + ARIZONA_ISRC1_DEC0_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC2", ARIZONA_ISRC_1_CTRL_3, + ARIZONA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC3", ARIZONA_ISRC_1_CTRL_3, + ARIZONA_ISRC1_DEC2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC4", ARIZONA_ISRC_1_CTRL_3, + ARIZONA_ISRC1_DEC3_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC2INT1", ARIZONA_ISRC_2_CTRL_3, + ARIZONA_ISRC2_INT0_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT2", ARIZONA_ISRC_2_CTRL_3, + ARIZONA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC2DEC1", ARIZONA_ISRC_2_CTRL_3, + ARIZONA_ISRC2_DEC0_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC2", ARIZONA_ISRC_2_CTRL_3, + ARIZONA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_MUX("AEC1 Loopback", ARIZONA_DAC_AEC_CONTROL_1, + ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0, + &wm8998_aec_loopback_mux[0]), + +SND_SOC_DAPM_MUX("AEC2 Loopback", ARIZONA_DAC_AEC_CONTROL_2, + ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0, + &wm8998_aec_loopback_mux[1]), + +SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, + ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, + ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, + ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, + ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0, + ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0, + ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX6_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, + ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, + ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, + ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, + ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0, + ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0, + ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX6_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, + ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, + ARIZONA_SLIMRX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, + ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, + ARIZONA_SLIMRX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, + ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, + ARIZONA_SLIMRX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, + ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, + ARIZONA_SLIMRX4_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, + ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, + ARIZONA_SLIMTX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, + ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, + ARIZONA_SLIMTX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, + ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, + ARIZONA_SLIMTX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, + ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, + ARIZONA_SLIMTX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, + ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, + ARIZONA_SLIMTX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, + ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, + ARIZONA_SLIMTX6_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, + ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, + ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, + ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, + ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, + ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, + ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT3", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5R", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT5R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_PGA("SPD1TX1", ARIZONA_SPD1_TX_CONTROL, + ARIZONA_SPD1_VAL1_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("SPD1TX2", ARIZONA_SPD1_TX_CONTROL, + ARIZONA_SPD1_VAL2_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_OUT_DRV("SPD1", ARIZONA_SPD1_TX_CONTROL, + ARIZONA_SPD1_ENA_SHIFT, 0, NULL, 0), + +ARIZONA_MUX_WIDGETS(EQ1, "EQ1"), +ARIZONA_MUX_WIDGETS(EQ2, "EQ2"), +ARIZONA_MUX_WIDGETS(EQ3, "EQ3"), +ARIZONA_MUX_WIDGETS(EQ4, "EQ4"), + +ARIZONA_MUX_WIDGETS(DRC1L, "DRC1L"), +ARIZONA_MUX_WIDGETS(DRC1R, "DRC1R"), + +ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"), +ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"), +ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"), +ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"), + +ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"), +ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"), + +ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUTL"), +ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUTR"), +ARIZONA_MIXER_WIDGETS(OUT2L, "LINEOUTL"), +ARIZONA_MIXER_WIDGETS(OUT2R, "LINEOUTR"), +ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"), +ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), +ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"), +ARIZONA_MIXER_WIDGETS(SPKDATL, "SPKDATL"), +ARIZONA_MIXER_WIDGETS(SPKDATR, "SPKDATR"), + +ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), +ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), +ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), +ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), +ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), +ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), + +ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), +ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), +ARIZONA_MIXER_WIDGETS(AIF2TX3, "AIF2TX3"), +ARIZONA_MIXER_WIDGETS(AIF2TX4, "AIF2TX4"), +ARIZONA_MIXER_WIDGETS(AIF2TX5, "AIF2TX5"), +ARIZONA_MIXER_WIDGETS(AIF2TX6, "AIF2TX6"), + +ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), +ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), + +ARIZONA_MUX_WIDGETS(SLIMTX1, "SLIMTX1"), +ARIZONA_MUX_WIDGETS(SLIMTX2, "SLIMTX2"), +ARIZONA_MUX_WIDGETS(SLIMTX3, "SLIMTX3"), +ARIZONA_MUX_WIDGETS(SLIMTX4, "SLIMTX4"), +ARIZONA_MUX_WIDGETS(SLIMTX5, "SLIMTX5"), +ARIZONA_MUX_WIDGETS(SLIMTX6, "SLIMTX6"), + +ARIZONA_MUX_WIDGETS(SPD1TX1, "SPDIFTX1"), +ARIZONA_MUX_WIDGETS(SPD1TX2, "SPDIFTX2"), + +ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"), +ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), +ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), +ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"), + +ARIZONA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"), +ARIZONA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"), +ARIZONA_MUX_WIDGETS(ISRC1DEC3, "ISRC1DEC3"), +ARIZONA_MUX_WIDGETS(ISRC1DEC4, "ISRC1DEC4"), + +ARIZONA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"), +ARIZONA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"), +ARIZONA_MUX_WIDGETS(ISRC1INT3, "ISRC1INT3"), +ARIZONA_MUX_WIDGETS(ISRC1INT4, "ISRC1INT4"), + +ARIZONA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"), +ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), + +ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), +ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), + +SND_SOC_DAPM_OUTPUT("HPOUTL"), +SND_SOC_DAPM_OUTPUT("HPOUTR"), +SND_SOC_DAPM_OUTPUT("LINEOUTL"), +SND_SOC_DAPM_OUTPUT("LINEOUTR"), +SND_SOC_DAPM_OUTPUT("EPOUT"), +SND_SOC_DAPM_OUTPUT("SPKOUTLN"), +SND_SOC_DAPM_OUTPUT("SPKOUTLP"), +SND_SOC_DAPM_OUTPUT("SPKOUTRN"), +SND_SOC_DAPM_OUTPUT("SPKOUTRP"), +SND_SOC_DAPM_OUTPUT("SPKDATL"), +SND_SOC_DAPM_OUTPUT("SPKDATR"), +SND_SOC_DAPM_OUTPUT("SPDIF"), + +SND_SOC_DAPM_OUTPUT("MICSUPP"), +}; + +#define ARIZONA_MIXER_INPUT_ROUTES(name) \ + { name, "Tone Generator 1", "Tone Generator 1" }, \ + { name, "Tone Generator 2", "Tone Generator 2" }, \ + { name, "Haptics", "HAPTICS" }, \ + { name, "AEC", "AEC1 Loopback" }, \ + { name, "AEC2", "AEC2 Loopback" }, \ + { name, "IN1L", "IN1L PGA" }, \ + { name, "IN1R", "IN1R PGA" }, \ + { name, "IN2L", "IN2 PGA" }, \ + { name, "AIF1RX1", "AIF1RX1" }, \ + { name, "AIF1RX2", "AIF1RX2" }, \ + { name, "AIF1RX3", "AIF1RX3" }, \ + { name, "AIF1RX4", "AIF1RX4" }, \ + { name, "AIF1RX5", "AIF1RX5" }, \ + { name, "AIF1RX6", "AIF1RX6" }, \ + { name, "AIF2RX1", "AIF2RX1" }, \ + { name, "AIF2RX2", "AIF2RX2" }, \ + { name, "AIF2RX3", "AIF2RX3" }, \ + { name, "AIF2RX4", "AIF2RX4" }, \ + { name, "AIF2RX5", "AIF2RX5" }, \ + { name, "AIF2RX6", "AIF2RX6" }, \ + { name, "AIF3RX1", "AIF3RX1" }, \ + { name, "AIF3RX2", "AIF3RX2" }, \ + { name, "SLIMRX1", "SLIMRX1" }, \ + { name, "SLIMRX2", "SLIMRX2" }, \ + { name, "SLIMRX3", "SLIMRX3" }, \ + { name, "SLIMRX4", "SLIMRX4" }, \ + { name, "EQ1", "EQ1" }, \ + { name, "EQ2", "EQ2" }, \ + { name, "EQ3", "EQ3" }, \ + { name, "EQ4", "EQ4" }, \ + { name, "DRC1L", "DRC1L" }, \ + { name, "DRC1R", "DRC1R" }, \ + { name, "LHPF1", "LHPF1" }, \ + { name, "LHPF2", "LHPF2" }, \ + { name, "LHPF3", "LHPF3" }, \ + { name, "LHPF4", "LHPF4" }, \ + { name, "ASRC1L", "ASRC1L" }, \ + { name, "ASRC1R", "ASRC1R" }, \ + { name, "ASRC2L", "ASRC2L" }, \ + { name, "ASRC2R", "ASRC2R" }, \ + { name, "ISRC1DEC1", "ISRC1DEC1" }, \ + { name, "ISRC1DEC2", "ISRC1DEC2" }, \ + { name, "ISRC1DEC3", "ISRC1DEC3" }, \ + { name, "ISRC1DEC4", "ISRC1DEC4" }, \ + { name, "ISRC1INT1", "ISRC1INT1" }, \ + { name, "ISRC1INT2", "ISRC1INT2" }, \ + { name, "ISRC1INT3", "ISRC1INT3" }, \ + { name, "ISRC1INT4", "ISRC1INT4" }, \ + { name, "ISRC2DEC1", "ISRC2DEC1" }, \ + { name, "ISRC2DEC2", "ISRC2DEC2" }, \ + { name, "ISRC2INT1", "ISRC2INT1" }, \ + { name, "ISRC2INT2", "ISRC2INT2" } + +static const struct snd_soc_dapm_route wm8998_dapm_routes[] = { + { "AIF2 Capture", NULL, "DBVDD2" }, + { "AIF2 Playback", NULL, "DBVDD2" }, + + { "AIF3 Capture", NULL, "DBVDD3" }, + { "AIF3 Playback", NULL, "DBVDD3" }, + + { "OUT1L", NULL, "CPVDD" }, + { "OUT1R", NULL, "CPVDD" }, + { "OUT2L", NULL, "CPVDD" }, + { "OUT2R", NULL, "CPVDD" }, + { "OUT3", NULL, "CPVDD" }, + + { "OUT4L", NULL, "SPKVDDL" }, + { "OUT4R", NULL, "SPKVDDR" }, + + { "OUT1L", NULL, "SYSCLK" }, + { "OUT1R", NULL, "SYSCLK" }, + { "OUT2L", NULL, "SYSCLK" }, + { "OUT2R", NULL, "SYSCLK" }, + { "OUT3", NULL, "SYSCLK" }, + { "OUT4L", NULL, "SYSCLK" }, + { "OUT4R", NULL, "SYSCLK" }, + { "OUT5L", NULL, "SYSCLK" }, + { "OUT5R", NULL, "SYSCLK" }, + + { "IN1AL", NULL, "SYSCLK" }, + { "IN1AR", NULL, "SYSCLK" }, + { "IN1BL", NULL, "SYSCLK" }, + { "IN1BR", NULL, "SYSCLK" }, + { "IN2A", NULL, "SYSCLK" }, + { "IN2B", NULL, "SYSCLK" }, + + { "SPD1", NULL, "SYSCLK" }, + { "SPD1", NULL, "SPD1TX1" }, + { "SPD1", NULL, "SPD1TX2" }, + + { "MICBIAS1", NULL, "MICVDD" }, + { "MICBIAS2", NULL, "MICVDD" }, + { "MICBIAS3", NULL, "MICVDD" }, + + { "Tone Generator 1", NULL, "SYSCLK" }, + { "Tone Generator 2", NULL, "SYSCLK" }, + + { "Tone Generator 1", NULL, "TONE" }, + { "Tone Generator 2", NULL, "TONE" }, + + { "AIF1 Capture", NULL, "AIF1TX1" }, + { "AIF1 Capture", NULL, "AIF1TX2" }, + { "AIF1 Capture", NULL, "AIF1TX3" }, + { "AIF1 Capture", NULL, "AIF1TX4" }, + { "AIF1 Capture", NULL, "AIF1TX5" }, + { "AIF1 Capture", NULL, "AIF1TX6" }, + + { "AIF1RX1", NULL, "AIF1 Playback" }, + { "AIF1RX2", NULL, "AIF1 Playback" }, + { "AIF1RX3", NULL, "AIF1 Playback" }, + { "AIF1RX4", NULL, "AIF1 Playback" }, + { "AIF1RX5", NULL, "AIF1 Playback" }, + { "AIF1RX6", NULL, "AIF1 Playback" }, + + { "AIF2 Capture", NULL, "AIF2TX1" }, + { "AIF2 Capture", NULL, "AIF2TX2" }, + { "AIF2 Capture", NULL, "AIF2TX3" }, + { "AIF2 Capture", NULL, "AIF2TX4" }, + { "AIF2 Capture", NULL, "AIF2TX5" }, + { "AIF2 Capture", NULL, "AIF2TX6" }, + + { "AIF2RX1", NULL, "AIF2 Playback" }, + { "AIF2RX2", NULL, "AIF2 Playback" }, + { "AIF2RX3", NULL, "AIF2 Playback" }, + { "AIF2RX4", NULL, "AIF2 Playback" }, + { "AIF2RX5", NULL, "AIF2 Playback" }, + { "AIF2RX6", NULL, "AIF2 Playback" }, + + { "AIF3 Capture", NULL, "AIF3TX1" }, + { "AIF3 Capture", NULL, "AIF3TX2" }, + + { "AIF3RX1", NULL, "AIF3 Playback" }, + { "AIF3RX2", NULL, "AIF3 Playback" }, + + { "Slim1 Capture", NULL, "SLIMTX1" }, + { "Slim1 Capture", NULL, "SLIMTX2" }, + { "Slim1 Capture", NULL, "SLIMTX3" }, + { "Slim1 Capture", NULL, "SLIMTX4" }, + + { "Slim2 Capture", NULL, "SLIMTX5" }, + { "Slim2 Capture", NULL, "SLIMTX6" }, + + { "SLIMRX1", NULL, "Slim1 Playback" }, + { "SLIMRX2", NULL, "Slim1 Playback" }, + + { "SLIMRX3", NULL, "Slim2 Playback" }, + { "SLIMRX4", NULL, "Slim2 Playback" }, + + { "AIF1 Playback", NULL, "SYSCLK" }, + { "AIF2 Playback", NULL, "SYSCLK" }, + { "AIF3 Playback", NULL, "SYSCLK" }, + { "Slim1 Playback", NULL, "SYSCLK" }, + { "Slim2 Playback", NULL, "SYSCLK" }, + + { "AIF1 Capture", NULL, "SYSCLK" }, + { "AIF2 Capture", NULL, "SYSCLK" }, + { "AIF3 Capture", NULL, "SYSCLK" }, + { "Slim1 Capture", NULL, "SYSCLK" }, + { "Slim2 Capture", NULL, "SYSCLK" }, + + { "IN1L Mux", "A", "IN1AL" }, + { "IN1R Mux", "A", "IN1AR" }, + { "IN1L Mux", "B", "IN1BL" }, + { "IN1R Mux", "B", "IN1BR" }, + + { "IN2 Mux", "A", "IN2A" }, + { "IN2 Mux", "B", "IN2B" }, + + { "IN1L PGA", NULL, "IN1L Mux" }, + { "IN1R PGA", NULL, "IN1R Mux" }, + { "IN2 PGA", NULL, "IN2 Mux" }, + + ARIZONA_MIXER_ROUTES("OUT1L", "HPOUTL"), + ARIZONA_MIXER_ROUTES("OUT1R", "HPOUTR"), + ARIZONA_MIXER_ROUTES("OUT2L", "LINEOUTL"), + ARIZONA_MIXER_ROUTES("OUT2R", "LINEOUTR"), + ARIZONA_MIXER_ROUTES("OUT3", "EPOUT"), + + ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"), + ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"), + ARIZONA_MIXER_ROUTES("OUT5L", "SPKDATL"), + ARIZONA_MIXER_ROUTES("OUT5R", "SPKDATR"), + + ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"), + ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"), + + ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), + ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), + ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), + ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), + ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), + ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), + + ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), + ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), + ARIZONA_MIXER_ROUTES("AIF2TX3", "AIF2TX3"), + ARIZONA_MIXER_ROUTES("AIF2TX4", "AIF2TX4"), + ARIZONA_MIXER_ROUTES("AIF2TX5", "AIF2TX5"), + ARIZONA_MIXER_ROUTES("AIF2TX6", "AIF2TX6"), + + ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), + ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), + + ARIZONA_MUX_ROUTES("SLIMTX1", "SLIMTX1"), + ARIZONA_MUX_ROUTES("SLIMTX2", "SLIMTX2"), + ARIZONA_MUX_ROUTES("SLIMTX3", "SLIMTX3"), + ARIZONA_MUX_ROUTES("SLIMTX4", "SLIMTX4"), + ARIZONA_MUX_ROUTES("SLIMTX5", "SLIMTX5"), + ARIZONA_MUX_ROUTES("SLIMTX6", "SLIMTX6"), + + ARIZONA_MUX_ROUTES("SPD1TX1", "SPDIFTX1"), + ARIZONA_MUX_ROUTES("SPD1TX2", "SPDIFTX2"), + + ARIZONA_MUX_ROUTES("EQ1", "EQ1"), + ARIZONA_MUX_ROUTES("EQ2", "EQ2"), + ARIZONA_MUX_ROUTES("EQ3", "EQ3"), + ARIZONA_MUX_ROUTES("EQ4", "EQ4"), + + ARIZONA_MUX_ROUTES("DRC1L", "DRC1L"), + ARIZONA_MUX_ROUTES("DRC1R", "DRC1R"), + + ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"), + ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"), + ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), + ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), + + ARIZONA_MUX_ROUTES("ASRC1L", "ASRC1L"), + ARIZONA_MUX_ROUTES("ASRC1R", "ASRC1R"), + ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"), + ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"), + + ARIZONA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), + ARIZONA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"), + ARIZONA_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"), + ARIZONA_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"), + + ARIZONA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), + ARIZONA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), + ARIZONA_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"), + ARIZONA_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"), + + ARIZONA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), + ARIZONA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), + + ARIZONA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), + ARIZONA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), + + { "AEC1 Loopback", "HPOUTL", "OUT1L" }, + { "AEC1 Loopback", "HPOUTR", "OUT1R" }, + { "AEC2 Loopback", "HPOUTL", "OUT1L" }, + { "AEC2 Loopback", "HPOUTR", "OUT1R" }, + { "HPOUTL", NULL, "OUT1L" }, + { "HPOUTR", NULL, "OUT1R" }, + + { "AEC1 Loopback", "LINEOUTL", "OUT2L" }, + { "AEC1 Loopback", "LINEOUTR", "OUT2R" }, + { "AEC2 Loopback", "LINEOUTL", "OUT2L" }, + { "AEC2 Loopback", "LINEOUTR", "OUT2R" }, + { "LINEOUTL", NULL, "OUT2L" }, + { "LINEOUTR", NULL, "OUT2R" }, + + { "AEC1 Loopback", "EPOUT", "OUT3" }, + { "AEC2 Loopback", "EPOUT", "OUT3" }, + { "EPOUT", NULL, "OUT3" }, + + { "AEC1 Loopback", "SPKOUTL", "OUT4L" }, + { "AEC2 Loopback", "SPKOUTL", "OUT4L" }, + { "SPKOUTLN", NULL, "OUT4L" }, + { "SPKOUTLP", NULL, "OUT4L" }, + + { "AEC1 Loopback", "SPKOUTR", "OUT4R" }, + { "AEC2 Loopback", "SPKOUTR", "OUT4R" }, + { "SPKOUTRN", NULL, "OUT4R" }, + { "SPKOUTRP", NULL, "OUT4R" }, + + { "SPDIF", NULL, "SPD1" }, + + { "AEC1 Loopback", "SPKDATL", "OUT5L" }, + { "AEC1 Loopback", "SPKDATR", "OUT5R" }, + { "AEC2 Loopback", "SPKDATL", "OUT5L" }, + { "AEC2 Loopback", "SPKDATR", "OUT5R" }, + { "SPKDATL", NULL, "OUT5L" }, + { "SPKDATR", NULL, "OUT5R" }, + + { "MICSUPP", NULL, "SYSCLK" }, + + { "DRC1 Signal Activity", NULL, "DRC1L" }, + { "DRC1 Signal Activity", NULL, "DRC1R" }, +}; + +#define WM8998_RATES SNDRV_PCM_RATE_8000_192000 + +#define WM8998_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver wm8998_dai[] = { + { + .name = "wm8998-aif1", + .id = 1, + .base = ARIZONA_AIF1_BCLK_CTRL, + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 6, + .rates = WM8998_RATES, + .formats = WM8998_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 6, + .rates = WM8998_RATES, + .formats = WM8998_FORMATS, + }, + .ops = &arizona_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "wm8998-aif2", + .id = 2, + .base = ARIZONA_AIF2_BCLK_CTRL, + .playback = { + .stream_name = "AIF2 Playback", + .channels_min = 1, + .channels_max = 6, + .rates = WM8998_RATES, + .formats = WM8998_FORMATS, + }, + .capture = { + .stream_name = "AIF2 Capture", + .channels_min = 1, + .channels_max = 6, + .rates = WM8998_RATES, + .formats = WM8998_FORMATS, + }, + .ops = &arizona_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "wm8998-aif3", + .id = 3, + .base = ARIZONA_AIF3_BCLK_CTRL, + .playback = { + .stream_name = "AIF3 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM8998_RATES, + .formats = WM8998_FORMATS, + }, + .capture = { + .stream_name = "AIF3 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM8998_RATES, + .formats = WM8998_FORMATS, + }, + .ops = &arizona_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "wm8998-slim1", + .id = 4, + .playback = { + .stream_name = "Slim1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM8998_RATES, + .formats = WM8998_FORMATS, + }, + .capture = { + .stream_name = "Slim1 Capture", + .channels_min = 1, + .channels_max = 4, + .rates = WM8998_RATES, + .formats = WM8998_FORMATS, + }, + .ops = &arizona_simple_dai_ops, + }, + { + .name = "wm8998-slim2", + .id = 5, + .playback = { + .stream_name = "Slim2 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM8998_RATES, + .formats = WM8998_FORMATS, + }, + .capture = { + .stream_name = "Slim2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM8998_RATES, + .formats = WM8998_FORMATS, + }, + .ops = &arizona_simple_dai_ops, + }, +}; + +static int wm8998_set_fll(struct snd_soc_codec *codec, int fll_id, int source, + unsigned int Fref, unsigned int Fout) +{ + struct wm8998_priv *wm8998 = snd_soc_codec_get_drvdata(codec); + + switch (fll_id) { + case WM8998_FLL1: + return arizona_set_fll(&wm8998->fll[0], source, Fref, Fout); + case WM8998_FLL2: + return arizona_set_fll(&wm8998->fll[1], source, Fref, Fout); + case WM8998_FLL1_REFCLK: + return arizona_set_fll_refclk(&wm8998->fll[0], source, Fref, + Fout); + case WM8998_FLL2_REFCLK: + return arizona_set_fll_refclk(&wm8998->fll[1], source, Fref, + Fout); + default: + return -EINVAL; + } +} + +static int wm8998_codec_probe(struct snd_soc_codec *codec) +{ + struct wm8998_priv *priv = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + + priv->core.arizona->dapm = dapm; + + arizona_init_spk(codec); + arizona_init_gpio(codec); + + snd_soc_dapm_disable_pin(dapm, "HAPTICS"); + + return 0; +} + +static int wm8998_codec_remove(struct snd_soc_codec *codec) +{ + struct wm8998_priv *priv = snd_soc_codec_get_drvdata(codec); + + priv->core.arizona->dapm = NULL; + + return 0; +} + +#define WM8998_DIG_VU 0x0200 + +static unsigned int wm8998_digital_vu[] = { + ARIZONA_DAC_DIGITAL_VOLUME_1L, + ARIZONA_DAC_DIGITAL_VOLUME_1R, + ARIZONA_DAC_DIGITAL_VOLUME_2L, + ARIZONA_DAC_DIGITAL_VOLUME_2R, + ARIZONA_DAC_DIGITAL_VOLUME_3L, + ARIZONA_DAC_DIGITAL_VOLUME_4L, + ARIZONA_DAC_DIGITAL_VOLUME_4R, + ARIZONA_DAC_DIGITAL_VOLUME_5L, + ARIZONA_DAC_DIGITAL_VOLUME_5R, +}; + +static struct regmap *wm8998_get_regmap(struct device *dev) +{ + struct wm8998_priv *priv = dev_get_drvdata(dev); + + return priv->core.arizona->regmap; +} + +static struct snd_soc_codec_driver soc_codec_dev_wm8998 = { + .probe = wm8998_codec_probe, + .remove = wm8998_codec_remove, + .get_regmap = wm8998_get_regmap, + + .idle_bias_off = true, + + .set_sysclk = arizona_set_sysclk, + .set_pll = wm8998_set_fll, + + .controls = wm8998_snd_controls, + .num_controls = ARRAY_SIZE(wm8998_snd_controls), + .dapm_widgets = wm8998_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8998_dapm_widgets), + .dapm_routes = wm8998_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8998_dapm_routes), +}; + +static int wm8998_probe(struct platform_device *pdev) +{ + struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); + struct wm8998_priv *wm8998; + int i; + + wm8998 = devm_kzalloc(&pdev->dev, sizeof(struct wm8998_priv), + GFP_KERNEL); + if (!wm8998) + return -ENOMEM; + platform_set_drvdata(pdev, wm8998); + + wm8998->core.arizona = arizona; + wm8998->core.num_inputs = 3; /* IN1L, IN1R, IN2 */ + + for (i = 0; i < ARRAY_SIZE(wm8998->fll); i++) + wm8998->fll[i].vco_mult = 1; + + arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1, + ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK, + &wm8998->fll[0]); + arizona_init_fll(arizona, 2, ARIZONA_FLL2_CONTROL_1 - 1, + ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, + &wm8998->fll[1]); + + for (i = 0; i < ARRAY_SIZE(wm8998_dai); i++) + arizona_init_dai(&wm8998->core, i); + + /* Latch volume update bits */ + for (i = 0; i < ARRAY_SIZE(wm8998_digital_vu); i++) + regmap_update_bits(arizona->regmap, wm8998_digital_vu[i], + WM8998_DIG_VU, WM8998_DIG_VU); + + pm_runtime_enable(&pdev->dev); + pm_runtime_idle(&pdev->dev); + + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8998, + wm8998_dai, ARRAY_SIZE(wm8998_dai)); +} + +static int wm8998_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static struct platform_driver wm8998_codec_driver = { + .driver = { + .name = "wm8998-codec", + }, + .probe = wm8998_probe, + .remove = wm8998_remove, +}; + +module_platform_driver(wm8998_codec_driver); + +MODULE_DESCRIPTION("ASoC WM8998 driver"); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:wm8998-codec"); diff --git a/sound/soc/codecs/wm8998.h b/sound/soc/codecs/wm8998.h new file mode 100644 index 000000000000..1e8647252162 --- /dev/null +++ b/sound/soc/codecs/wm8998.h @@ -0,0 +1,23 @@ +/* + * wm8998.h -- ALSA SoC Audio driver for WM8998 codecs + * + * Copyright 2015 Cirrus Logic, Inc. + * + * Author: Richard Fitzgerald + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _WM8998_H +#define _WM8998_H + +#include "arizona.h" + +#define WM8998_FLL1 1 +#define WM8998_FLL2 2 +#define WM8998_FLL1_REFCLK 3 +#define WM8998_FLL2_REFCLK 4 + +#endif -- cgit v1.2.3-59-g8ed1b From e5224f58e3efd74972f7dcf46264c3ba9aa807ba Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Tue, 29 Sep 2015 16:41:43 +0200 Subject: ASoC: ad193x: add support to ad1934 The AD1934 codec has no ADC feature. Hence it register mapping is slightly different from the register mapping of other members of the AD193x family. Some ASoC controls and widgets are related to the DAC feature so are not relevant in the case of an AD1934 codec. Signed-off-by: Cyrille Pitchen Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x-i2c.c | 8 +-- sound/soc/codecs/ad193x-spi.c | 16 +++++- sound/soc/codecs/ad193x.c | 122 ++++++++++++++++++++++++++++++++---------- sound/soc/codecs/ad193x.h | 9 +++- 4 files changed, 121 insertions(+), 34 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/ad193x-i2c.c b/sound/soc/codecs/ad193x-i2c.c index df3a1a415825..171313664bc8 100644 --- a/sound/soc/codecs/ad193x-i2c.c +++ b/sound/soc/codecs/ad193x-i2c.c @@ -15,8 +15,8 @@ #include "ad193x.h" static const struct i2c_device_id ad193x_id[] = { - { "ad1936", 0 }, - { "ad1937", 0 }, + { "ad1936", AD193X }, + { "ad1937", AD193X }, { } }; MODULE_DEVICE_TABLE(i2c, ad193x_id); @@ -30,7 +30,9 @@ static int ad193x_i2c_probe(struct i2c_client *client, config.val_bits = 8; config.reg_bits = 8; - return ad193x_probe(&client->dev, devm_regmap_init_i2c(client, &config)); + return ad193x_probe(&client->dev, + devm_regmap_init_i2c(client, &config), + (enum ad193x_type)id->driver_data); } static int ad193x_i2c_remove(struct i2c_client *client) diff --git a/sound/soc/codecs/ad193x-spi.c b/sound/soc/codecs/ad193x-spi.c index 390cef9b9dc2..364e82112e8c 100644 --- a/sound/soc/codecs/ad193x-spi.c +++ b/sound/soc/codecs/ad193x-spi.c @@ -16,6 +16,7 @@ static int ad193x_spi_probe(struct spi_device *spi) { + const struct spi_device_id *id = spi_get_device_id(spi); struct regmap_config config; config = ad193x_regmap_config; @@ -24,7 +25,8 @@ static int ad193x_spi_probe(struct spi_device *spi) config.read_flag_mask = 0x09; config.write_flag_mask = 0x08; - return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); + return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config), + (enum ad193x_type)id->driver_data); } static int ad193x_spi_remove(struct spi_device *spi) @@ -33,6 +35,17 @@ static int ad193x_spi_remove(struct spi_device *spi) return 0; } +static const struct spi_device_id ad193x_spi_id[] = { + { "ad193x", AD193X }, + { "ad1933", AD1933 }, + { "ad1934", AD1934 }, + { "ad1936", AD193X }, + { "ad1937", AD193X }, + { "ad1938", AD193X }, + { } +}; +MODULE_DEVICE_TABLE(spi, ad193x_spi_id); + static struct spi_driver ad193x_spi_driver = { .driver = { .name = "ad193x", @@ -40,6 +53,7 @@ static struct spi_driver ad193x_spi_driver = { }, .probe = ad193x_spi_probe, .remove = ad193x_spi_remove, + .id_table = ad193x_spi_id, }; module_spi_driver(ad193x_spi_driver); diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 17c953595660..76d7966bd72c 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -23,6 +23,7 @@ /* codec private data */ struct ad193x_priv { struct regmap *regmap; + enum ad193x_type type; int sysclk; }; @@ -47,12 +48,6 @@ static const struct snd_kcontrol_new ad193x_snd_controls[] = { SOC_DOUBLE_R_TLV("DAC4 Volume", AD193X_DAC_L4_VOL, AD193X_DAC_R4_VOL, 0, 0xFF, 1, adau193x_tlv), - /* ADC switch control */ - SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE, - AD193X_ADCR1_MUTE, 1, 1), - SOC_DOUBLE("ADC2 Switch", AD193X_ADC_CTRL0, AD193X_ADCL2_MUTE, - AD193X_ADCR2_MUTE, 1, 1), - /* DAC switch control */ SOC_DOUBLE("DAC1 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL1_MUTE, AD193X_DACR1_MUTE, 1, 1), @@ -63,26 +58,37 @@ static const struct snd_kcontrol_new ad193x_snd_controls[] = { SOC_DOUBLE("DAC4 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL4_MUTE, AD193X_DACR4_MUTE, 1, 1), + /* DAC de-emphasis */ + SOC_ENUM("Playback Deemphasis", ad193x_deemp_enum), +}; + +static const struct snd_kcontrol_new ad193x_adc_snd_controls[] = { + /* ADC switch control */ + SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE, + AD193X_ADCR1_MUTE, 1, 1), + SOC_DOUBLE("ADC2 Switch", AD193X_ADC_CTRL0, AD193X_ADCL2_MUTE, + AD193X_ADCR2_MUTE, 1, 1), + /* ADC high-pass filter */ SOC_SINGLE("ADC High Pass Filter Switch", AD193X_ADC_CTRL0, AD193X_ADC_HIGHPASS_FILTER, 1, 0), - - /* DAC de-emphasis */ - SOC_ENUM("Playback Deemphasis", ad193x_deemp_enum), }; static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_PGA("DAC Output", AD193X_DAC_CTRL0, 0, 1, NULL, 0), - SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0), - SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0), SND_SOC_DAPM_VMID("VMID"), SND_SOC_DAPM_OUTPUT("DAC1OUT"), SND_SOC_DAPM_OUTPUT("DAC2OUT"), SND_SOC_DAPM_OUTPUT("DAC3OUT"), SND_SOC_DAPM_OUTPUT("DAC4OUT"), +}; + +static const struct snd_soc_dapm_widget ad193x_adc_widgets[] = { + SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), SND_SOC_DAPM_INPUT("ADC1IN"), SND_SOC_DAPM_INPUT("ADC2IN"), }; @@ -91,18 +97,33 @@ static const struct snd_soc_dapm_route audio_paths[] = { { "DAC", NULL, "SYSCLK" }, { "DAC Output", NULL, "DAC" }, { "DAC Output", NULL, "VMID" }, - { "ADC", NULL, "SYSCLK" }, - { "DAC", NULL, "ADC_PWR" }, - { "ADC", NULL, "ADC_PWR" }, { "DAC1OUT", NULL, "DAC Output" }, { "DAC2OUT", NULL, "DAC Output" }, { "DAC3OUT", NULL, "DAC Output" }, { "DAC4OUT", NULL, "DAC Output" }, + { "SYSCLK", NULL, "PLL_PWR" }, +}; + +static const struct snd_soc_dapm_route ad193x_adc_audio_paths[] = { + { "ADC", NULL, "SYSCLK" }, + { "ADC", NULL, "ADC_PWR" }, { "ADC", NULL, "ADC1IN" }, { "ADC", NULL, "ADC2IN" }, - { "SYSCLK", NULL, "PLL_PWR" }, }; +static inline bool ad193x_has_adc(const struct ad193x_priv *ad193x) +{ + switch (ad193x->type) { + case AD1933: + case AD1934: + return false; + default: + break; + } + + return true; +} + /* * DAI ops entries */ @@ -147,8 +168,10 @@ static int ad193x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1, AD193X_DAC_CHAN_MASK, channels << AD193X_DAC_CHAN_SHFT); - regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, - AD193X_ADC_CHAN_MASK, channels << AD193X_ADC_CHAN_SHFT); + if (ad193x_has_adc(ad193x)) + regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, + AD193X_ADC_CHAN_MASK, + channels << AD193X_ADC_CHAN_SHFT); return 0; } @@ -172,7 +195,9 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai, adc_serfmt |= AD193X_ADC_SERFMT_AUX; break; default: - return -EINVAL; + if (ad193x_has_adc(ad193x)) + return -EINVAL; + break; } switch (fmt & SND_SOC_DAIFMT_INV_MASK) { @@ -217,10 +242,12 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, - AD193X_ADC_SERFMT_MASK, adc_serfmt); - regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, - AD193X_ADC_FMT_MASK, adc_fmt); + if (ad193x_has_adc(ad193x)) { + regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, + AD193X_ADC_SERFMT_MASK, adc_serfmt); + regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, + AD193X_ADC_FMT_MASK, adc_fmt); + } regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1, AD193X_DAC_FMT_MASK, dac_fmt); @@ -287,8 +314,9 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, AD193X_DAC_WORD_LEN_MASK, word_len << AD193X_DAC_WORD_LEN_SHFT); - regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, - AD193X_ADC_WORD_LEN_MASK, word_len); + if (ad193x_has_adc(ad193x)) + regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, + AD193X_ADC_WORD_LEN_MASK, word_len); return 0; } @@ -326,6 +354,8 @@ static struct snd_soc_dai_driver ad193x_dai = { static int ad193x_codec_probe(struct snd_soc_codec *codec) { struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + int num, ret; /* default setting for ad193x */ @@ -335,14 +365,46 @@ static int ad193x_codec_probe(struct snd_soc_codec *codec) regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A); /* dac in tdm mode */ regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x40); - /* high-pass filter enable */ - regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3); - /* sata delay=1, adc aux mode */ - regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43); + + /* adc only */ + if (ad193x_has_adc(ad193x)) { + /* high-pass filter enable */ + regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3); + /* sata delay=1, adc aux mode */ + regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43); + } + /* pll input: mclki/xi */ regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04); + /* adc only */ + if (ad193x_has_adc(ad193x)) { + /* add adc controls */ + num = ARRAY_SIZE(ad193x_adc_snd_controls); + ret = snd_soc_add_codec_controls(codec, + ad193x_adc_snd_controls, + num); + if (ret) + return ret; + + /* add adc widgets */ + num = ARRAY_SIZE(ad193x_adc_widgets); + ret = snd_soc_dapm_new_controls(dapm, + ad193x_adc_widgets, + num); + if (ret) + return ret; + + /* add adc routes */ + num = ARRAY_SIZE(ad193x_adc_audio_paths); + ret = snd_soc_dapm_add_routes(dapm, + ad193x_adc_audio_paths, + num); + if (ret) + return ret; + } + return 0; } @@ -367,7 +429,8 @@ const struct regmap_config ad193x_regmap_config = { }; EXPORT_SYMBOL_GPL(ad193x_regmap_config); -int ad193x_probe(struct device *dev, struct regmap *regmap) +int ad193x_probe(struct device *dev, struct regmap *regmap, + enum ad193x_type type) { struct ad193x_priv *ad193x; @@ -379,6 +442,7 @@ int ad193x_probe(struct device *dev, struct regmap *regmap) return -ENOMEM; ad193x->regmap = regmap; + ad193x->type = type; dev_set_drvdata(dev, ad193x); diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index ab9a998f15be..8b1e65f928d2 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h @@ -13,8 +13,15 @@ struct device; +enum ad193x_type { + AD193X, + AD1933, + AD1934, +}; + extern const struct regmap_config ad193x_regmap_config; -int ad193x_probe(struct device *dev, struct regmap *regmap); +int ad193x_probe(struct device *dev, struct regmap *regmap, + enum ad193x_type type); #define AD193X_PLL_CLK_CTRL0 0x00 #define AD193X_PLL_POWERDOWN 0x01 -- cgit v1.2.3-59-g8ed1b From d46183efe3b57d06461c9bea35e1a0262391fe77 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 6 Oct 2015 17:26:36 +0800 Subject: ASoC: ad193x-spi: Fixup ad193x_spi_id table AD1939 is missed from the table, so add it. AD1936 and AD1937 are controlled by I2C interface, so remove them. Fixes: e5224f58e3ef ("ASoC: ad193x: add support to ad1934") Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x-spi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/ad193x-spi.c b/sound/soc/codecs/ad193x-spi.c index 364e82112e8c..b55055a6a265 100644 --- a/sound/soc/codecs/ad193x-spi.c +++ b/sound/soc/codecs/ad193x-spi.c @@ -39,9 +39,8 @@ static const struct spi_device_id ad193x_spi_id[] = { { "ad193x", AD193X }, { "ad1933", AD1933 }, { "ad1934", AD1934 }, - { "ad1936", AD193X }, - { "ad1937", AD193X }, { "ad1938", AD193X }, + { "ad1939", AD193X }, { } }; MODULE_DEVICE_TABLE(spi, ad193x_spi_id); -- cgit v1.2.3-59-g8ed1b From 355b27e181f667dad248a40d3d4d48150e9a593c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 18 Oct 2015 10:06:11 +0800 Subject: ASoC: ad193x-spi: Add adau1328 to ad193x_spi_id table This driver also supports adau1328, thus add adau1328 to ad193x_spi_id. Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x-spi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/codecs/ad193x-spi.c b/sound/soc/codecs/ad193x-spi.c index b55055a6a265..431f95da1de1 100644 --- a/sound/soc/codecs/ad193x-spi.c +++ b/sound/soc/codecs/ad193x-spi.c @@ -41,6 +41,7 @@ static const struct spi_device_id ad193x_spi_id[] = { { "ad1934", AD1934 }, { "ad1938", AD193X }, { "ad1939", AD193X }, + { "adau1328", AD193X }, { } }; MODULE_DEVICE_TABLE(spi, ad193x_spi_id); -- cgit v1.2.3-59-g8ed1b From 92b822a499607c32ce12ffd798a095babedc3202 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 20 Oct 2015 16:56:11 +0800 Subject: ASoC: ad193x: Drop .volatile_reg implementation adau193x_reg_volatile() always return false. This seems pointless because current code uses REGCACHE_NONE cache_type which is supposed to be volatile. Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 76d7966bd72c..3a3f3f2343d7 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -418,14 +418,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ad193x = { .num_dapm_routes = ARRAY_SIZE(audio_paths), }; -static bool adau193x_reg_volatile(struct device *dev, unsigned int reg) -{ - return false; -} - const struct regmap_config ad193x_regmap_config = { .max_register = AD193X_NUM_REGS - 1, - .volatile_reg = adau193x_reg_volatile, }; EXPORT_SYMBOL_GPL(ad193x_regmap_config); -- cgit v1.2.3-59-g8ed1b