aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/88pm860x-codec.c134
-rw-r--r--sound/soc/codecs/Kconfig285
-rw-r--r--sound/soc/codecs/Makefile75
-rw-r--r--sound/soc/codecs/ab8500-codec.c12
-rw-r--r--sound/soc/codecs/ad1836.c4
-rw-r--r--sound/soc/codecs/ad193x-i2c.c54
-rw-r--r--sound/soc/codecs/ad193x-spi.c48
-rw-r--r--sound/soc/codecs/ad193x.c154
-rw-r--r--sound/soc/codecs/ad193x.h7
-rw-r--r--sound/soc/codecs/ad1980.c43
-rw-r--r--sound/soc/codecs/adau1373.c46
-rw-r--r--sound/soc/codecs/adau1761-i2c.c60
-rw-r--r--sound/soc/codecs/adau1761-spi.c77
-rw-r--r--sound/soc/codecs/adau1761.c803
-rw-r--r--sound/soc/codecs/adau1761.h23
-rw-r--r--sound/soc/codecs/adau1781-i2c.c58
-rw-r--r--sound/soc/codecs/adau1781-spi.c75
-rw-r--r--sound/soc/codecs/adau1781.c511
-rw-r--r--sound/soc/codecs/adau1781.h23
-rw-r--r--sound/soc/codecs/adau17x1.c866
-rw-r--r--sound/soc/codecs/adau17x1.h124
-rw-r--r--sound/soc/codecs/adau1977-i2c.c59
-rw-r--r--sound/soc/codecs/adau1977-spi.c76
-rw-r--r--sound/soc/codecs/adau1977.c1018
-rw-r--r--sound/soc/codecs/adau1977.h37
-rw-r--r--sound/soc/codecs/adav801.c53
-rw-r--r--sound/soc/codecs/adav803.c50
-rw-r--r--sound/soc/codecs/adav80x.c171
-rw-r--r--sound/soc/codecs/adav80x.h7
-rw-r--r--sound/soc/codecs/ak4104.c62
-rw-r--r--sound/soc/codecs/ak4535.c9
-rw-r--r--sound/soc/codecs/ak4641.c28
-rw-r--r--sound/soc/codecs/ak4642.c83
-rw-r--r--sound/soc/codecs/ak4671.c250
-rw-r--r--sound/soc/codecs/ak4671.h2
-rw-r--r--sound/soc/codecs/alc5623.c145
-rw-r--r--sound/soc/codecs/alc5632.c58
-rw-r--r--sound/soc/codecs/arizona.c325
-rw-r--r--sound/soc/codecs/arizona.h4
-rw-r--r--sound/soc/codecs/cq93vc.c11
-rw-r--r--sound/soc/codecs/cs4270.c11
-rw-r--r--sound/soc/codecs/cs4271.c67
-rw-r--r--sound/soc/codecs/cs42l51-i2c.c59
-rw-r--r--sound/soc/codecs/cs42l51.c143
-rw-r--r--sound/soc/codecs/cs42l51.h6
-rw-r--r--sound/soc/codecs/cs42l52.c129
-rw-r--r--sound/soc/codecs/cs42l52.h2
-rw-r--r--sound/soc/codecs/cs42l56.c1419
-rw-r--r--sound/soc/codecs/cs42l56.h177
-rw-r--r--sound/soc/codecs/cs42l73.c78
-rw-r--r--sound/soc/codecs/cs42xx8-i2c.c64
-rw-r--r--sound/soc/codecs/cs42xx8.c600
-rw-r--r--sound/soc/codecs/cs42xx8.h238
-rw-r--r--sound/soc/codecs/da7210.c32
-rw-r--r--sound/soc/codecs/da7213.c163
-rw-r--r--sound/soc/codecs/da732x.c215
-rw-r--r--sound/soc/codecs/da732x.h3
-rw-r--r--sound/soc/codecs/da9055.c113
-rw-r--r--sound/soc/codecs/hdmi.c1
-rw-r--r--sound/soc/codecs/isabelle.c71
-rw-r--r--sound/soc/codecs/lm4857.c7
-rw-r--r--sound/soc/codecs/lm49453.c47
-rw-r--r--sound/soc/codecs/max9768.c9
-rw-r--r--sound/soc/codecs/max98088.c59
-rw-r--r--sound/soc/codecs/max98090.c319
-rw-r--r--sound/soc/codecs/max98090.h3
-rw-r--r--sound/soc/codecs/max98095.c105
-rw-r--r--sound/soc/codecs/max9850.c8
-rw-r--r--sound/soc/codecs/mc13783.c62
-rw-r--r--sound/soc/codecs/ml26124.c22
-rw-r--r--sound/soc/codecs/pcm1681.c19
-rw-r--r--sound/soc/codecs/pcm1792a.c33
-rw-r--r--sound/soc/codecs/pcm512x-i2c.c71
-rw-r--r--sound/soc/codecs/pcm512x-spi.c69
-rw-r--r--sound/soc/codecs/pcm512x.c591
-rw-r--r--sound/soc/codecs/pcm512x.h171
-rw-r--r--sound/soc/codecs/rl6231.c152
-rw-r--r--sound/soc/codecs/rl6231.h34
-rw-r--r--sound/soc/codecs/rt5631.c88
-rw-r--r--sound/soc/codecs/rt5640.c628
-rw-r--r--sound/soc/codecs/rt5640.h18
-rw-r--r--sound/soc/codecs/rt5645.c2378
-rw-r--r--sound/soc/codecs/rt5645.h2181
-rw-r--r--sound/soc/codecs/rt5651.c1818
-rw-r--r--sound/soc/codecs/rt5651.h2080
-rw-r--r--sound/soc/codecs/rt5677.c3498
-rw-r--r--sound/soc/codecs/rt5677.h1451
-rw-r--r--sound/soc/codecs/sgtl5000.c108
-rw-r--r--sound/soc/codecs/si476x.c14
-rw-r--r--sound/soc/codecs/sigmadsp-i2c.c35
-rw-r--r--sound/soc/codecs/sigmadsp-regmap.c36
-rw-r--r--sound/soc/codecs/sigmadsp.c65
-rw-r--r--sound/soc/codecs/sigmadsp.h20
-rw-r--r--sound/soc/codecs/sirf-audio-codec.c580
-rw-r--r--sound/soc/codecs/sirf-audio-codec.h125
-rw-r--r--sound/soc/codecs/sn95031.c46
-rw-r--r--sound/soc/codecs/ssm2518.c24
-rw-r--r--sound/soc/codecs/ssm2602-i2c.c57
-rw-r--r--sound/soc/codecs/ssm2602-spi.c41
-rw-r--r--sound/soc/codecs/ssm2602.c180
-rw-r--r--sound/soc/codecs/ssm2602.h14
-rw-r--r--sound/soc/codecs/sta32x.c94
-rw-r--r--sound/soc/codecs/sta350.c1311
-rw-r--r--sound/soc/codecs/sta350.h238
-rw-r--r--sound/soc/codecs/sta529.c15
-rw-r--r--sound/soc/codecs/stac9766.c38
-rw-r--r--sound/soc/codecs/tas5086.c4
-rw-r--r--sound/soc/codecs/tlv320aic23-i2c.c67
-rw-r--r--sound/soc/codecs/tlv320aic23-spi.c56
-rw-r--r--sound/soc/codecs/tlv320aic23.c83
-rw-r--r--sound/soc/codecs/tlv320aic23.h6
-rw-r--r--sound/soc/codecs/tlv320aic26.c7
-rw-r--r--sound/soc/codecs/tlv320aic31xx.c1281
-rw-r--r--sound/soc/codecs/tlv320aic31xx.h258
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c234
-rw-r--r--sound/soc/codecs/tlv320aic3x.c17
-rw-r--r--sound/soc/codecs/tlv320dac33.c47
-rw-r--r--sound/soc/codecs/tpa6130a2.c1
-rw-r--r--sound/soc/codecs/twl4030.c111
-rw-r--r--sound/soc/codecs/twl6040.c25
-rw-r--r--sound/soc/codecs/uda134x.c3
-rw-r--r--sound/soc/codecs/uda1380.c43
-rw-r--r--sound/soc/codecs/wl1273.c21
-rw-r--r--sound/soc/codecs/wm2000.c10
-rw-r--r--sound/soc/codecs/wm2200.c29
-rw-r--r--sound/soc/codecs/wm5100.c47
-rw-r--r--sound/soc/codecs/wm5102.c56
-rw-r--r--sound/soc/codecs/wm5110.c55
-rw-r--r--sound/soc/codecs/wm8350.c16
-rw-r--r--sound/soc/codecs/wm8400.c47
-rw-r--r--sound/soc/codecs/wm8510.c10
-rw-r--r--sound/soc/codecs/wm8523.c11
-rw-r--r--sound/soc/codecs/wm8580.c11
-rw-r--r--sound/soc/codecs/wm8711.c8
-rw-r--r--sound/soc/codecs/wm8728.c11
-rw-r--r--sound/soc/codecs/wm8731.c22
-rw-r--r--sound/soc/codecs/wm8737.c56
-rw-r--r--sound/soc/codecs/wm8741.c40
-rw-r--r--sound/soc/codecs/wm8750.c6
-rw-r--r--sound/soc/codecs/wm8753.c16
-rw-r--r--sound/soc/codecs/wm8770.c10
-rw-r--r--sound/soc/codecs/wm8776.c6
-rw-r--r--sound/soc/codecs/wm8804.c38
-rw-r--r--sound/soc/codecs/wm8804.h4
-rw-r--r--sound/soc/codecs/wm8900.c52
-rw-r--r--sound/soc/codecs/wm8903.c122
-rw-r--r--sound/soc/codecs/wm8904.c100
-rw-r--r--sound/soc/codecs/wm8940.c26
-rw-r--r--sound/soc/codecs/wm8955.c32
-rw-r--r--sound/soc/codecs/wm8958-dsp2.c42
-rw-r--r--sound/soc/codecs/wm8960.c10
-rw-r--r--sound/soc/codecs/wm8961.c23
-rw-r--r--sound/soc/codecs/wm8962.c122
-rw-r--r--sound/soc/codecs/wm8962.h4
-rw-r--r--sound/soc/codecs/wm8971.c6
-rw-r--r--sound/soc/codecs/wm8974.c10
-rw-r--r--sound/soc/codecs/wm8978.c38
-rw-r--r--sound/soc/codecs/wm8983.c55
-rw-r--r--sound/soc/codecs/wm8985.c57
-rw-r--r--sound/soc/codecs/wm8988.c78
-rw-r--r--sound/soc/codecs/wm8990.c49
-rw-r--r--sound/soc/codecs/wm8991.c52
-rw-r--r--sound/soc/codecs/wm8993.c74
-rw-r--r--sound/soc/codecs/wm8994.c216
-rw-r--r--sound/soc/codecs/wm8995.c60
-rw-r--r--sound/soc/codecs/wm8996.c91
-rw-r--r--sound/soc/codecs/wm8997.c52
-rw-r--r--sound/soc/codecs/wm9081.c38
-rw-r--r--sound/soc/codecs/wm9090.c10
-rw-r--r--sound/soc/codecs/wm9705.c12
-rw-r--r--sound/soc/codecs/wm9713.c3
-rw-r--r--sound/soc/codecs/wm_adsp.c93
-rw-r--r--sound/soc/codecs/wm_hubs.c18
173 files changed, 28919 insertions, 3882 deletions
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index 75d0ad5d2dc..3c4b10ff48c 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -276,7 +276,7 @@ static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int reg = mc->reg;
unsigned int reg2 = mc->rreg;
int val[2], val2[2], i;
@@ -300,7 +300,7 @@ static int snd_soc_put_volsw_2r_st(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int reg = mc->reg;
unsigned int reg2 = mc->rreg;
int err;
@@ -333,7 +333,7 @@ static int snd_soc_get_volsw_2r_out(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int reg = mc->reg;
unsigned int reg2 = mc->rreg;
unsigned int shift = mc->shift;
@@ -353,7 +353,7 @@ static int snd_soc_put_volsw_2r_out(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int reg = mc->reg;
unsigned int reg2 = mc->rreg;
unsigned int shift = mc->shift;
@@ -448,38 +448,38 @@ static const char *pm860x_opamp_texts[] = {"-50%", "-25%", "0%", "75%"};
static const char *pm860x_pa_texts[] = {"-33%", "0%", "33%", "66%"};
-static const struct soc_enum pm860x_hs1_opamp_enum =
- SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 5, 4, pm860x_opamp_texts);
+static SOC_ENUM_SINGLE_DECL(pm860x_hs1_opamp_enum,
+ PM860X_HS1_CTRL, 5, pm860x_opamp_texts);
-static const struct soc_enum pm860x_hs2_opamp_enum =
- SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 5, 4, pm860x_opamp_texts);
+static SOC_ENUM_SINGLE_DECL(pm860x_hs2_opamp_enum,
+ PM860X_HS2_CTRL, 5, pm860x_opamp_texts);
-static const struct soc_enum pm860x_hs1_pa_enum =
- SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 3, 4, pm860x_pa_texts);
+static SOC_ENUM_SINGLE_DECL(pm860x_hs1_pa_enum,
+ PM860X_HS1_CTRL, 3, pm860x_pa_texts);
-static const struct soc_enum pm860x_hs2_pa_enum =
- SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 3, 4, pm860x_pa_texts);
+static SOC_ENUM_SINGLE_DECL(pm860x_hs2_pa_enum,
+ PM860X_HS2_CTRL, 3, pm860x_pa_texts);
-static const struct soc_enum pm860x_lo1_opamp_enum =
- SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 5, 4, pm860x_opamp_texts);
+static SOC_ENUM_SINGLE_DECL(pm860x_lo1_opamp_enum,
+ PM860X_LO1_CTRL, 5, pm860x_opamp_texts);
-static const struct soc_enum pm860x_lo2_opamp_enum =
- SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 5, 4, pm860x_opamp_texts);
+static SOC_ENUM_SINGLE_DECL(pm860x_lo2_opamp_enum,
+ PM860X_LO2_CTRL, 5, pm860x_opamp_texts);
-static const struct soc_enum pm860x_lo1_pa_enum =
- SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 3, 4, pm860x_pa_texts);
+static SOC_ENUM_SINGLE_DECL(pm860x_lo1_pa_enum,
+ PM860X_LO1_CTRL, 3, pm860x_pa_texts);
-static const struct soc_enum pm860x_lo2_pa_enum =
- SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 3, 4, pm860x_pa_texts);
+static SOC_ENUM_SINGLE_DECL(pm860x_lo2_pa_enum,
+ PM860X_LO2_CTRL, 3, pm860x_pa_texts);
-static const struct soc_enum pm860x_spk_pa_enum =
- SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 5, 4, pm860x_pa_texts);
+static SOC_ENUM_SINGLE_DECL(pm860x_spk_pa_enum,
+ PM860X_EAR_CTRL_1, 5, pm860x_pa_texts);
-static const struct soc_enum pm860x_ear_pa_enum =
- SOC_ENUM_SINGLE(PM860X_EAR_CTRL_2, 0, 4, pm860x_pa_texts);
+static SOC_ENUM_SINGLE_DECL(pm860x_ear_pa_enum,
+ PM860X_EAR_CTRL_2, 0, pm860x_pa_texts);
-static const struct soc_enum pm860x_spk_ear_opamp_enum =
- SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 3, 4, pm860x_opamp_texts);
+static SOC_ENUM_SINGLE_DECL(pm860x_spk_ear_opamp_enum,
+ PM860X_EAR_CTRL_1, 3, pm860x_opamp_texts);
static const struct snd_kcontrol_new pm860x_snd_controls[] = {
SOC_DOUBLE_R_TLV("ADC Capture Volume", PM860X_ADC_ANA_2,
@@ -561,8 +561,8 @@ static const char *aif1_text[] = {
"PCM L", "PCM R",
};
-static const struct soc_enum aif1_enum =
- SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 6, 2, aif1_text);
+static SOC_ENUM_SINGLE_DECL(aif1_enum,
+ PM860X_PCM_IFACE_3, 6, aif1_text);
static const struct snd_kcontrol_new aif1_mux =
SOC_DAPM_ENUM("PCM Mux", aif1_enum);
@@ -572,8 +572,8 @@ static const char *i2s_din_text[] = {
"DIN", "DIN1",
};
-static const struct soc_enum i2s_din_enum =
- SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 1, 2, i2s_din_text);
+static SOC_ENUM_SINGLE_DECL(i2s_din_enum,
+ PM860X_I2S_IFACE_3, 1, i2s_din_text);
static const struct snd_kcontrol_new i2s_din_mux =
SOC_DAPM_ENUM("I2S DIN Mux", i2s_din_enum);
@@ -583,8 +583,8 @@ static const char *i2s_mic_text[] = {
"Ex PA", "ADC",
};
-static const struct soc_enum i2s_mic_enum =
- SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 4, 2, i2s_mic_text);
+static SOC_ENUM_SINGLE_DECL(i2s_mic_enum,
+ PM860X_I2S_IFACE_3, 4, i2s_mic_text);
static const struct snd_kcontrol_new i2s_mic_mux =
SOC_DAPM_ENUM("I2S Mic Mux", i2s_mic_enum);
@@ -594,8 +594,8 @@ static const char *adcl_text[] = {
"ADCR", "ADCL",
};
-static const struct soc_enum adcl_enum =
- SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 4, 2, adcl_text);
+static SOC_ENUM_SINGLE_DECL(adcl_enum,
+ PM860X_PCM_IFACE_3, 4, adcl_text);
static const struct snd_kcontrol_new adcl_mux =
SOC_DAPM_ENUM("ADC Left Mux", adcl_enum);
@@ -605,8 +605,8 @@ static const char *adcr_text[] = {
"ADCL", "ADCR",
};
-static const struct soc_enum adcr_enum =
- SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 2, 2, adcr_text);
+static SOC_ENUM_SINGLE_DECL(adcr_enum,
+ PM860X_PCM_IFACE_3, 2, adcr_text);
static const struct snd_kcontrol_new adcr_mux =
SOC_DAPM_ENUM("ADC Right Mux", adcr_enum);
@@ -616,8 +616,8 @@ static const char *adcr_ec_text[] = {
"ADCR", "EC",
};
-static const struct soc_enum adcr_ec_enum =
- SOC_ENUM_SINGLE(PM860X_ADC_EN_2, 3, 2, adcr_ec_text);
+static SOC_ENUM_SINGLE_DECL(adcr_ec_enum,
+ PM860X_ADC_EN_2, 3, adcr_ec_text);
static const struct snd_kcontrol_new adcr_ec_mux =
SOC_DAPM_ENUM("ADCR EC Mux", adcr_ec_enum);
@@ -627,8 +627,8 @@ static const char *ec_text[] = {
"Left", "Right", "Left + Right",
};
-static const struct soc_enum ec_enum =
- SOC_ENUM_SINGLE(PM860X_EC_PATH, 1, 3, ec_text);
+static SOC_ENUM_SINGLE_DECL(ec_enum,
+ PM860X_EC_PATH, 1, ec_text);
static const struct snd_kcontrol_new ec_mux =
SOC_DAPM_ENUM("EC Mux", ec_enum);
@@ -638,36 +638,36 @@ static const char *dac_text[] = {
};
/* DAC Headset 1 Mux / Mux10 */
-static const struct soc_enum dac_hs1_enum =
- SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 0, 4, dac_text);
+static SOC_ENUM_SINGLE_DECL(dac_hs1_enum,
+ PM860X_ANA_INPUT_SEL_1, 0, dac_text);
static const struct snd_kcontrol_new dac_hs1_mux =
SOC_DAPM_ENUM("DAC HS1 Mux", dac_hs1_enum);
/* DAC Headset 2 Mux / Mux11 */
-static const struct soc_enum dac_hs2_enum =
- SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 2, 4, dac_text);
+static SOC_ENUM_SINGLE_DECL(dac_hs2_enum,
+ PM860X_ANA_INPUT_SEL_1, 2, dac_text);
static const struct snd_kcontrol_new dac_hs2_mux =
SOC_DAPM_ENUM("DAC HS2 Mux", dac_hs2_enum);
/* DAC Lineout 1 Mux / Mux12 */
-static const struct soc_enum dac_lo1_enum =
- SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 4, 4, dac_text);
+static SOC_ENUM_SINGLE_DECL(dac_lo1_enum,
+ PM860X_ANA_INPUT_SEL_1, 4, dac_text);
static const struct snd_kcontrol_new dac_lo1_mux =
SOC_DAPM_ENUM("DAC LO1 Mux", dac_lo1_enum);
/* DAC Lineout 2 Mux / Mux13 */
-static const struct soc_enum dac_lo2_enum =
- SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 6, 4, dac_text);
+static SOC_ENUM_SINGLE_DECL(dac_lo2_enum,
+ PM860X_ANA_INPUT_SEL_1, 6, dac_text);
static const struct snd_kcontrol_new dac_lo2_mux =
SOC_DAPM_ENUM("DAC LO2 Mux", dac_lo2_enum);
/* DAC Spearker Earphone Mux / Mux14 */
-static const struct soc_enum dac_spk_ear_enum =
- SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_2, 0, 4, dac_text);
+static SOC_ENUM_SINGLE_DECL(dac_spk_ear_enum,
+ PM860X_ANA_INPUT_SEL_2, 0, dac_text);
static const struct snd_kcontrol_new dac_spk_ear_mux =
SOC_DAPM_ENUM("DAC SP Mux", dac_spk_ear_enum);
@@ -677,29 +677,29 @@ static const char *in_text[] = {
"Digital", "Analog",
};
-static const struct soc_enum hs1_enum =
- SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 0, 2, in_text);
+static SOC_ENUM_SINGLE_DECL(hs1_enum,
+ PM860X_ANA_TO_ANA, 0, in_text);
static const struct snd_kcontrol_new hs1_mux =
SOC_DAPM_ENUM("Headset1 Mux", hs1_enum);
/* Headset 2 Mux / Mux16 */
-static const struct soc_enum hs2_enum =
- SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 1, 2, in_text);
+static SOC_ENUM_SINGLE_DECL(hs2_enum,
+ PM860X_ANA_TO_ANA, 1, in_text);
static const struct snd_kcontrol_new hs2_mux =
SOC_DAPM_ENUM("Headset2 Mux", hs2_enum);
/* Lineout 1 Mux / Mux17 */
-static const struct soc_enum lo1_enum =
- SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 2, 2, in_text);
+static SOC_ENUM_SINGLE_DECL(lo1_enum,
+ PM860X_ANA_TO_ANA, 2, in_text);
static const struct snd_kcontrol_new lo1_mux =
SOC_DAPM_ENUM("Lineout1 Mux", lo1_enum);
/* Lineout 2 Mux / Mux18 */
-static const struct soc_enum lo2_enum =
- SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 3, 2, in_text);
+static SOC_ENUM_SINGLE_DECL(lo2_enum,
+ PM860X_ANA_TO_ANA, 3, in_text);
static const struct snd_kcontrol_new lo2_mux =
SOC_DAPM_ENUM("Lineout2 Mux", lo2_enum);
@@ -709,8 +709,8 @@ static const char *spk_text[] = {
"Earpiece", "Speaker",
};
-static const struct soc_enum spk_enum =
- SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 6, 2, spk_text);
+static SOC_ENUM_SINGLE_DECL(spk_enum,
+ PM860X_ANA_TO_ANA, 6, spk_text);
static const struct snd_kcontrol_new spk_demux =
SOC_DAPM_ENUM("Speaker Earpiece Demux", spk_enum);
@@ -720,8 +720,8 @@ static const char *mic_text[] = {
"Mic 1", "Mic 2",
};
-static const struct soc_enum mic_enum =
- SOC_ENUM_SINGLE(PM860X_ADC_ANA_4, 4, 2, mic_text);
+static SOC_ENUM_SINGLE_DECL(mic_enum,
+ PM860X_ADC_ANA_4, 4, mic_text);
static const struct snd_kcontrol_new mic_mux =
SOC_DAPM_ENUM("MIC Mux", mic_enum);
@@ -1327,8 +1327,6 @@ static int pm860x_probe(struct snd_soc_codec *codec)
pm860x->codec = codec;
- codec->control_data = pm860x->regmap;
-
for (i = 0; i < 4; i++) {
ret = request_threaded_irq(pm860x->irq[i], NULL,
pm860x_codec_handler, IRQF_ONESHOT,
@@ -1360,10 +1358,18 @@ static int pm860x_remove(struct snd_soc_codec *codec)
return 0;
}
+static struct regmap *pm860x_get_regmap(struct device *dev)
+{
+ struct pm860x_priv *pm860x = dev_get_drvdata(dev);
+
+ return pm860x->regmap;
+}
+
static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
.probe = pm860x_probe,
.remove = pm860x_remove,
.set_bias_level = pm860x_set_bias_level,
+ .get_regmap = pm860x_get_regmap,
.controls = pm860x_snd_controls,
.num_controls = ARRAY_SIZE(pm860x_snd_controls),
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 983d087aa92..0b9571c858f 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -8,6 +8,8 @@ config SND_SOC_I2C_AND_SPI
default y if I2C=y
default y if SPI_MASTER=y
+menu "CODEC drivers"
+
config SND_SOC_ALL_CODECS
tristate "Build all ASoC CODEC drivers"
depends on COMPILE_TEST
@@ -16,15 +18,24 @@ config SND_SOC_ALL_CODECS
select SND_SOC_AB8500_CODEC if ABX500_CORE
select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
select SND_SOC_AD1836 if SPI_MASTER
- select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI
+ select SND_SOC_AD193X_SPI if SPI_MASTER
+ select SND_SOC_AD193X_I2C if I2C
select SND_SOC_AD1980 if SND_SOC_AC97_BUS
select SND_SOC_AD73311
select SND_SOC_ADAU1373 if I2C
- select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI
+ select SND_SOC_ADAU1761_I2C if I2C
+ select SND_SOC_ADAU1761_SPI if SPI
+ select SND_SOC_ADAU1781_I2C if I2C
+ select SND_SOC_ADAU1781_SPI if SPI
+ select SND_SOC_ADAV801 if SPI_MASTER
+ select SND_SOC_ADAV803 if I2C
+ select SND_SOC_ADAU1977_SPI if SPI_MASTER
+ select SND_SOC_ADAU1977_I2C if I2C
select SND_SOC_ADAU1701 if I2C
select SND_SOC_ADS117X
select SND_SOC_AK4104 if SPI_MASTER
select SND_SOC_AK4535 if I2C
+ select SND_SOC_AK4554
select SND_SOC_AK4641 if I2C
select SND_SOC_AK4642 if I2C
select SND_SOC_AK4671 if I2C
@@ -32,11 +43,13 @@ config SND_SOC_ALL_CODECS
select SND_SOC_ALC5623 if I2C
select SND_SOC_ALC5632 if I2C
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
- select SND_SOC_CS42L51 if I2C
- select SND_SOC_CS42L52 if I2C
+ select SND_SOC_CS42L51_I2C if I2C
+ select SND_SOC_CS42L52 if I2C && INPUT
+ select SND_SOC_CS42L56 if I2C && INPUT
select SND_SOC_CS42L73 if I2C
select SND_SOC_CS4270 if I2C
select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
+ select SND_SOC_CS42XX8_I2C if I2C
select SND_SOC_CX20442 if TTY
select SND_SOC_DA7210 if I2C
select SND_SOC_DA7213 if I2C
@@ -59,20 +72,30 @@ config SND_SOC_ALL_CODECS
select SND_SOC_PCM1681 if I2C
select SND_SOC_PCM1792A if SPI_MASTER
select SND_SOC_PCM3008
+ select SND_SOC_PCM512x_I2C if I2C
+ select SND_SOC_PCM512x_SPI if SPI_MASTER
select SND_SOC_RT5631 if I2C
select SND_SOC_RT5640 if I2C
+ select SND_SOC_RT5645 if I2C
+ select SND_SOC_RT5651 if I2C
+ select SND_SOC_RT5677 if I2C
select SND_SOC_SGTL5000 if I2C
select SND_SOC_SI476X if MFD_SI476X_CORE
+ select SND_SOC_SIRF_AUDIO_CODEC
select SND_SOC_SN95031 if INTEL_SCU_IPC
select SND_SOC_SPDIF
select SND_SOC_SSM2518 if I2C
- select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
+ select SND_SOC_SSM2602_SPI if SPI_MASTER
+ select SND_SOC_SSM2602_I2C if I2C
select SND_SOC_STA32X if I2C
+ select SND_SOC_STA350 if I2C
select SND_SOC_STA529 if I2C
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
select SND_SOC_TAS5086 if I2C
- select SND_SOC_TLV320AIC23 if I2C
+ select SND_SOC_TLV320AIC23_I2C if I2C
+ select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
select SND_SOC_TLV320AIC26 if SPI_MASTER
+ select SND_SOC_TLV320AIC31XX if I2C
select SND_SOC_TLV320AIC32X4 if I2C
select SND_SOC_TLV320AIC3X if I2C
select SND_SOC_TPA6130A2 if I2C
@@ -113,7 +136,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM8955 if I2C
select SND_SOC_WM8960 if I2C
select SND_SOC_WM8961 if I2C
- select SND_SOC_WM8962 if I2C
+ select SND_SOC_WM8962 if I2C && INPUT
select SND_SOC_WM8971 if I2C
select SND_SOC_WM8974 if I2C
select SND_SOC_WM8978 if I2C
@@ -182,48 +205,114 @@ config SND_SOC_AD1836
config SND_SOC_AD193X
tristate
+config SND_SOC_AD193X_SPI
+ tristate
+ select SND_SOC_AD193X
+
+config SND_SOC_AD193X_I2C
+ tristate
+ select SND_SOC_AD193X
+
config SND_SOC_AD1980
tristate
config SND_SOC_AD73311
tristate
+config SND_SOC_ADAU1373
+ tristate
+
config SND_SOC_ADAU1701
- select SND_SOC_SIGMADSP
+ tristate "Analog Devices ADAU1701 CODEC"
+ depends on I2C
+ select SND_SOC_SIGMADSP_I2C
+
+config SND_SOC_ADAU17X1
tristate
+ select SND_SOC_SIGMADSP_REGMAP
-config SND_SOC_ADAU1373
+config SND_SOC_ADAU1761
+ tristate
+ select SND_SOC_ADAU17X1
+
+config SND_SOC_ADAU1761_I2C
+ tristate
+ select SND_SOC_ADAU1761
+ select REGMAP_I2C
+
+config SND_SOC_ADAU1761_SPI
+ tristate
+ select SND_SOC_ADAU1761
+ select REGMAP_SPI
+
+config SND_SOC_ADAU1781
+ select SND_SOC_ADAU17X1
+ tristate
+
+config SND_SOC_ADAU1781_I2C
+ tristate
+ select SND_SOC_ADAU1781
+ select REGMAP_I2C
+
+config SND_SOC_ADAU1781_SPI
+ tristate
+ select SND_SOC_ADAU1781
+ select REGMAP_SPI
+
+config SND_SOC_ADAU1977
+ tristate
+
+config SND_SOC_ADAU1977_SPI
+ tristate
+ select SND_SOC_ADAU1977
+ select REGMAP_SPI
+
+config SND_SOC_ADAU1977_I2C
tristate
+ select SND_SOC_ADAU1977
+ select REGMAP_I2C
config SND_SOC_ADAV80X
tristate
+config SND_SOC_ADAV801
+ tristate
+ select SND_SOC_ADAV80X
+
+config SND_SOC_ADAV803
+ tristate
+ select SND_SOC_ADAV80X
+
config SND_SOC_ADS117X
tristate
config SND_SOC_AK4104
- tristate
+ tristate "AKM AK4104 CODEC"
+ depends on SPI_MASTER
config SND_SOC_AK4535
tristate
config SND_SOC_AK4554
- tristate
+ tristate "AKM AK4554 CODEC"
config SND_SOC_AK4641
tristate
config SND_SOC_AK4642
- tristate
+ tristate "AKM AK4642 CODEC"
+ depends on I2C
config SND_SOC_AK4671
tristate
config SND_SOC_AK5386
- tristate
+ tristate "AKM AK5638 CODEC"
config SND_SOC_ALC5623
- tristate
+ tristate "Realtek ALC5623 CODEC"
+ depends on I2C
+
config SND_SOC_ALC5632
tristate
@@ -233,15 +322,26 @@ config SND_SOC_CQ0093VC
config SND_SOC_CS42L51
tristate
-config SND_SOC_CS42L52
+config SND_SOC_CS42L51_I2C
tristate
+ select SND_SOC_CS42L51
+
+config SND_SOC_CS42L52
+ tristate "Cirrus Logic CS42L52 CODEC"
+ depends on I2C && INPUT
+
+config SND_SOC_CS42L56
+ tristate "Cirrus Logic CS42L56 CODEC"
+ depends on I2C && INPUT
config SND_SOC_CS42L73
- tristate
+ tristate "Cirrus Logic CS42L73 CODEC"
+ depends on I2C
# Cirrus Logic CS4270 Codec
config SND_SOC_CS4270
- tristate
+ tristate "Cirrus Logic CS4270 CODEC"
+ depends on I2C
# Cirrus Logic CS4270 Codec VD = 3.3V Errata
# Select if you are affected by the errata where the part will not function
@@ -252,8 +352,18 @@ config SND_SOC_CS4270_VD33_ERRATA
depends on SND_SOC_CS4270
config SND_SOC_CS4271
+ tristate "Cirrus Logic CS4271 CODEC"
+ depends on SND_SOC_I2C_AND_SPI
+
+config SND_SOC_CS42XX8
tristate
+config SND_SOC_CS42XX8_I2C
+ tristate "Cirrus Logic CS42448/CS42888 CODEC (I2C)"
+ depends on I2C
+ select SND_SOC_CS42XX8
+ select REGMAP_I2C
+
config SND_SOC_CX20442
tristate
depends on TTY
@@ -283,6 +393,9 @@ config SND_SOC_BT_SCO
config SND_SOC_DMIC
tristate
+config SND_SOC_HDMI_CODEC
+ tristate "HDMI stub CODEC"
+
config SND_SOC_ISABELLE
tristate
@@ -301,27 +414,60 @@ config SND_SOC_MAX98095
config SND_SOC_MAX9850
tristate
-config SND_SOC_HDMI_CODEC
- tristate
-
config SND_SOC_PCM1681
- tristate
+ tristate "Texas Instruments PCM1681 CODEC"
+ depends on I2C
config SND_SOC_PCM1792A
- tristate
+ tristate "Texas Instruments PCM1792A CODEC"
+ depends on SPI_MASTER
config SND_SOC_PCM3008
tristate
+config SND_SOC_PCM512x
+ tristate
+
+config SND_SOC_PCM512x_I2C
+ tristate "Texas Instruments PCM512x CODECs - I2C"
+ depends on I2C
+ select SND_SOC_PCM512x
+ select REGMAP_I2C
+
+config SND_SOC_PCM512x_SPI
+ tristate "Texas Instruments PCM512x CODECs - SPI"
+ depends on SPI_MASTER
+ select SND_SOC_PCM512x
+ select REGMAP_SPI
+
+config SND_SOC_RL6231
+ tristate
+ default y if SND_SOC_RT5640=y
+ default y if SND_SOC_RT5645=y
+ default y if SND_SOC_RT5651=y
+ default m if SND_SOC_RT5640=m
+ default m if SND_SOC_RT5645=m
+ default m if SND_SOC_RT5651=m
+
config SND_SOC_RT5631
tristate
config SND_SOC_RT5640
tristate
+config SND_SOC_RT5645
+ tristate
+
+config SND_SOC_RT5651
+ tristate
+
+config SND_SOC_RT5677
+ tristate
+
#Freescale sgtl5000 codec
config SND_SOC_SGTL5000
- tristate
+ tristate "Freescale SGTL5000 CODEC"
+ depends on I2C
config SND_SOC_SI476X
tristate
@@ -330,11 +476,23 @@ config SND_SOC_SIGMADSP
tristate
select CRC32
+config SND_SOC_SIGMADSP_I2C
+ tristate
+ select SND_SOC_SIGMADSP
+
+config SND_SOC_SIGMADSP_REGMAP
+ tristate
+ select SND_SOC_SIGMADSP
+
+config SND_SOC_SIRF_AUDIO_CODEC
+ tristate "SiRF SoC internal audio codec"
+ select REGMAP_MMIO
+
config SND_SOC_SN95031
tristate
config SND_SOC_SPDIF
- tristate
+ tristate "S/PDIF CODEC"
config SND_SOC_SSM2518
tristate
@@ -342,9 +500,21 @@ config SND_SOC_SSM2518
config SND_SOC_SSM2602
tristate
+config SND_SOC_SSM2602_SPI
+ select SND_SOC_SSM2602
+ tristate
+
+config SND_SOC_SSM2602_I2C
+ select SND_SOC_SSM2602
+ tristate
+
config SND_SOC_STA32X
tristate
+config SND_SOC_STA350
+ tristate "STA350 speaker amplifier"
+ depends on I2C
+
config SND_SOC_STA529
tristate
@@ -352,20 +522,33 @@ config SND_SOC_STAC9766
tristate
config SND_SOC_TAS5086
- tristate
+ tristate "Texas Instruments TAS5086 speaker amplifier"
+ depends on I2C
config SND_SOC_TLV320AIC23
tristate
+config SND_SOC_TLV320AIC23_I2C
+ tristate
+ select SND_SOC_TLV320AIC23
+
+config SND_SOC_TLV320AIC23_SPI
+ tristate
+ select SND_SOC_TLV320AIC23
+
config SND_SOC_TLV320AIC26
tristate
depends on SPI
+config SND_SOC_TLV320AIC31XX
+ tristate
+
config SND_SOC_TLV320AIC32X4
tristate
config SND_SOC_TLV320AIC3X
- tristate
+ tristate "Texas Instruments TLV320AIC3x CODECs"
+ depends on I2C
config SND_SOC_TLV320DAC33
tristate
@@ -414,55 +597,69 @@ config SND_SOC_WM8400
tristate
config SND_SOC_WM8510
- tristate
+ tristate "Wolfson Microelectronics WM8510 CODEC"
+ depends on SND_SOC_I2C_AND_SPI
config SND_SOC_WM8523
- tristate
+ tristate "Wolfson Microelectronics WM8523 DAC"
+ depends on I2C
config SND_SOC_WM8580
- tristate
+ tristate "Wolfson Microelectronics WM8523 CODEC"
+ depends on I2C
config SND_SOC_WM8711
- tristate
+ tristate "Wolfson Microelectronics WM8711 CODEC"
+ depends on SND_SOC_I2C_AND_SPI
config SND_SOC_WM8727
tristate
config SND_SOC_WM8728
- tristate
+ tristate "Wolfson Microelectronics WM8728 DAC"
+ depends on SND_SOC_I2C_AND_SPI
config SND_SOC_WM8731
- tristate
+ tristate "Wolfson Microelectronics WM8731 CODEC"
+ depends on SND_SOC_I2C_AND_SPI
config SND_SOC_WM8737
- tristate
+ tristate "Wolfson Microelectronics WM8737 ADC"
+ depends on SND_SOC_I2C_AND_SPI
config SND_SOC_WM8741
- tristate
+ tristate "Wolfson Microelectronics WM8737 DAC"
+ depends on SND_SOC_I2C_AND_SPI
config SND_SOC_WM8750
- tristate
+ tristate "Wolfson Microelectronics WM8750 CODEC"
+ depends on SND_SOC_I2C_AND_SPI
config SND_SOC_WM8753
- tristate
+ tristate "Wolfson Microelectronics WM8753 CODEC"
+ depends on SND_SOC_I2C_AND_SPI
config SND_SOC_WM8770
- tristate
+ tristate "Wolfson Microelectronics WM8770 CODEC"
+ depends on SPI_MASTER
config SND_SOC_WM8776
- tristate
+ tristate "Wolfson Microelectronics WM8776 CODEC"
+ depends on SND_SOC_I2C_AND_SPI
config SND_SOC_WM8782
tristate
config SND_SOC_WM8804
- tristate
+ tristate "Wolfson Microelectronics WM8804 S/PDIF transceiver"
+ depends on SND_SOC_I2C_AND_SPI
config SND_SOC_WM8900
tristate
config SND_SOC_WM8903
- tristate
+ tristate "Wolfson Microelectronics WM8903 CODEC"
+ depends on I2C
config SND_SOC_WM8904
tristate
@@ -480,7 +677,8 @@ config SND_SOC_WM8961
tristate
config SND_SOC_WM8962
- tristate
+ tristate "Wolfson Microelectronics WM8962 CODEC"
+ depends on I2C && INPUT
config SND_SOC_WM8971
tristate
@@ -553,4 +751,7 @@ config SND_SOC_ML26124
tristate
config SND_SOC_TPA6130A2
- tristate
+ tristate "Texas Instruments TPA6130A2 headphone amplifier"
+ depends on I2C
+
+endmenu
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bc126764a44..1bd6e1cf6f8 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -3,11 +3,25 @@ snd-soc-ab8500-codec-objs := ab8500-codec.o
snd-soc-ac97-objs := ac97.o
snd-soc-ad1836-objs := ad1836.o
snd-soc-ad193x-objs := ad193x.o
+snd-soc-ad193x-spi-objs := ad193x-spi.o
+snd-soc-ad193x-i2c-objs := ad193x-i2c.o
snd-soc-ad1980-objs := ad1980.o
snd-soc-ad73311-objs := ad73311.o
-snd-soc-adau1701-objs := adau1701.o
snd-soc-adau1373-objs := adau1373.o
+snd-soc-adau1701-objs := adau1701.o
+snd-soc-adau17x1-objs := adau17x1.o
+snd-soc-adau1761-objs := adau1761.o
+snd-soc-adau1761-i2c-objs := adau1761-i2c.o
+snd-soc-adau1761-spi-objs := adau1761-spi.o
+snd-soc-adau1781-objs := adau1781.o
+snd-soc-adau1781-i2c-objs := adau1781-i2c.o
+snd-soc-adau1781-spi-objs := adau1781-spi.o
+snd-soc-adau1977-objs := adau1977.o
+snd-soc-adau1977-spi-objs := adau1977-spi.o
+snd-soc-adau1977-i2c-objs := adau1977-i2c.o
snd-soc-adav80x-objs := adav80x.o
+snd-soc-adav801-objs := adav801.o
+snd-soc-adav803-objs := adav803.o
snd-soc-ads117x-objs := ads117x.o
snd-soc-ak4104-objs := ak4104.o
snd-soc-ak4535-objs := ak4535.o
@@ -19,10 +33,14 @@ snd-soc-ak5386-objs := ak5386.o
snd-soc-arizona-objs := arizona.o
snd-soc-cq93vc-objs := cq93vc.o
snd-soc-cs42l51-objs := cs42l51.o
+snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
snd-soc-cs42l52-objs := cs42l52.o
+snd-soc-cs42l56-objs := cs42l56.o
snd-soc-cs42l73-objs := cs42l73.o
snd-soc-cs4270-objs := cs4270.o
snd-soc-cs4271-objs := cs4271.o
+snd-soc-cs42xx8-objs := cs42xx8.o
+snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o
snd-soc-cx20442-objs := cx20442.o
snd-soc-da7210-objs := da7210.o
snd-soc-da7213-objs := da7213.o
@@ -46,26 +64,42 @@ snd-soc-hdmi-codec-objs := hdmi.o
snd-soc-pcm1681-objs := pcm1681.o
snd-soc-pcm1792a-codec-objs := pcm1792a.o
snd-soc-pcm3008-objs := pcm3008.o
+snd-soc-pcm512x-objs := pcm512x.o
+snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
+snd-soc-pcm512x-spi-objs := pcm512x-spi.o
+snd-soc-rl6231-objs := rl6231.o
snd-soc-rt5631-objs := rt5631.o
snd-soc-rt5640-objs := rt5640.o
+snd-soc-rt5645-objs := rt5645.o
+snd-soc-rt5651-objs := rt5651.o
+snd-soc-rt5677-objs := rt5677.o
snd-soc-sgtl5000-objs := sgtl5000.o
snd-soc-alc5623-objs := alc5623.o
snd-soc-alc5632-objs := alc5632.o
snd-soc-sigmadsp-objs := sigmadsp.o
+snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o
+snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o
snd-soc-si476x-objs := si476x.o
+snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o
snd-soc-sn95031-objs := sn95031.o
snd-soc-spdif-tx-objs := spdif_transmitter.o
snd-soc-spdif-rx-objs := spdif_receiver.o
snd-soc-ssm2518-objs := ssm2518.o
snd-soc-ssm2602-objs := ssm2602.o
+snd-soc-ssm2602-spi-objs := ssm2602-spi.o
+snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o
snd-soc-sta32x-objs := sta32x.o
+snd-soc-sta350-objs := sta350.o
snd-soc-sta529-objs := sta529.o
snd-soc-stac9766-objs := stac9766.o
snd-soc-tas5086-objs := tas5086.o
snd-soc-tlv320aic23-objs := tlv320aic23.o
+snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
+snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o
snd-soc-tlv320aic26-objs := tlv320aic26.o
-snd-soc-tlv320aic3x-objs := tlv320aic3x.o
+snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o
snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
+snd-soc-tlv320aic3x-objs := tlv320aic3x.o
snd-soc-tlv320dac33-objs := tlv320dac33.o
snd-soc-twl4030-objs := twl4030.o
snd-soc-twl6040-objs := twl6040.o
@@ -134,11 +168,25 @@ obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o
obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o
+obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o
+obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o
obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o
-obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o
+obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o
+obj-$(CONFIG_SND_SOC_ADAU17X1) += snd-soc-adau17x1.o
+obj-$(CONFIG_SND_SOC_ADAU1761) += snd-soc-adau1761.o
+obj-$(CONFIG_SND_SOC_ADAU1761_I2C) += snd-soc-adau1761-i2c.o
+obj-$(CONFIG_SND_SOC_ADAU1761_SPI) += snd-soc-adau1761-spi.o
+obj-$(CONFIG_SND_SOC_ADAU1781) += snd-soc-adau1781.o
+obj-$(CONFIG_SND_SOC_ADAU1781_I2C) += snd-soc-adau1781-i2c.o
+obj-$(CONFIG_SND_SOC_ADAU1781_SPI) += snd-soc-adau1781-spi.o
+obj-$(CONFIG_SND_SOC_ADAU1977) += snd-soc-adau1977.o
+obj-$(CONFIG_SND_SOC_ADAU1977_SPI) += snd-soc-adau1977-spi.o
+obj-$(CONFIG_SND_SOC_ADAU1977_I2C) += snd-soc-adau1977-i2c.o
obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o
+obj-$(CONFIG_SND_SOC_ADAV801) += snd-soc-adav801.o
+obj-$(CONFIG_SND_SOC_ADAV803) += snd-soc-adav803.o
obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o
obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
@@ -152,10 +200,14 @@ obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o
obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o
obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
+obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o
obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
+obj-$(CONFIG_SND_SOC_CS42L56) += snd-soc-cs42l56.o
obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o
+obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o
+obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o
@@ -179,23 +231,38 @@ obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o
obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
+obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
+obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
+obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
+obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
+obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o
+obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o
+obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
+obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o
+obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP) += snd-soc-sigmadsp-regmap.o
obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o
obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
+obj-$(CONFIG_SND_SOC_SSM2602_SPI) += snd-soc-ssm2602-spi.o
+obj-$(CONFIG_SND_SOC_SSM2602_I2C) += snd-soc-ssm2602-i2c.o
obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o
+obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o
obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
+obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o
+obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
-obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
+obj-$(CONFIG_SND_SOC_TLV320AIC31XX) += snd-soc-tlv320aic31xx.o
obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o
+obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index 1ad92cbf0b2..1fb4402bf72 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -1139,7 +1139,7 @@ static void anc_configure(struct snd_soc_codec *codec,
static int sid_status_control_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
mutex_lock(&codec->mutex);
@@ -1153,7 +1153,7 @@ static int sid_status_control_get(struct snd_kcontrol *kcontrol,
static int sid_status_control_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
unsigned int param, sidconf, val;
int status = 1;
@@ -1208,7 +1208,7 @@ out:
static int anc_status_control_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
mutex_lock(&codec->mutex);
@@ -1221,7 +1221,7 @@ static int anc_status_control_get(struct snd_kcontrol *kcontrol,
static int anc_status_control_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
struct device *dev = codec->dev;
bool apply_fir, apply_iir;
@@ -1306,7 +1306,7 @@ static int filter_control_info(struct snd_kcontrol *kcontrol,
static int filter_control_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct filter_control *fc =
(struct filter_control *)kcontrol->private_value;
unsigned int i;
@@ -1322,7 +1322,7 @@ static int filter_control_get(struct snd_kcontrol *kcontrol,
static int filter_control_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct filter_control *fc =
(struct filter_control *)kcontrol->private_value;
unsigned int i;
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index 77f45986857..685998dd086 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -40,8 +40,8 @@ struct ad1836_priv {
*/
static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"};
-static const struct soc_enum ad1836_deemp_enum =
- SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp);
+static SOC_ENUM_SINGLE_DECL(ad1836_deemp_enum,
+ AD1836_DAC_CTRL1, 8, ad1836_deemp);
#define AD1836_DAC_VOLUME(x) \
SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \
diff --git a/sound/soc/codecs/ad193x-i2c.c b/sound/soc/codecs/ad193x-i2c.c
new file mode 100644
index 00000000000..df3a1a41582
--- /dev/null
+++ b/sound/soc/codecs/ad193x-i2c.c
@@ -0,0 +1,54 @@
+/*
+ * AD1936/AD1937 audio driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+#include <sound/soc.h>
+
+#include "ad193x.h"
+
+static const struct i2c_device_id ad193x_id[] = {
+ { "ad1936", 0 },
+ { "ad1937", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ad193x_id);
+
+static int ad193x_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct regmap_config config;
+
+ config = ad193x_regmap_config;
+ config.val_bits = 8;
+ config.reg_bits = 8;
+
+ return ad193x_probe(&client->dev, devm_regmap_init_i2c(client, &config));
+}
+
+static int ad193x_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static struct i2c_driver ad193x_i2c_driver = {
+ .driver = {
+ .name = "ad193x",
+ },
+ .probe = ad193x_i2c_probe,
+ .remove = ad193x_i2c_remove,
+ .id_table = ad193x_id,
+};
+module_i2c_driver(ad193x_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC AD1936/AD1937 audio CODEC driver");
+MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad193x-spi.c b/sound/soc/codecs/ad193x-spi.c
new file mode 100644
index 00000000000..390cef9b9dc
--- /dev/null
+++ b/sound/soc/codecs/ad193x-spi.c
@@ -0,0 +1,48 @@
+/*
+ * AD1938/AD1939 audio driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+
+#include <sound/soc.h>
+
+#include "ad193x.h"
+
+static int ad193x_spi_probe(struct spi_device *spi)
+{
+ struct regmap_config config;
+
+ config = ad193x_regmap_config;
+ config.val_bits = 8;
+ config.reg_bits = 16;
+ config.read_flag_mask = 0x09;
+ config.write_flag_mask = 0x08;
+
+ return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config));
+}
+
+static int ad193x_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ return 0;
+}
+
+static struct spi_driver ad193x_spi_driver = {
+ .driver = {
+ .name = "ad193x",
+ .owner = THIS_MODULE,
+ },
+ .probe = ad193x_spi_probe,
+ .remove = ad193x_spi_remove,
+};
+module_spi_driver(ad193x_spi_driver);
+
+MODULE_DESCRIPTION("ASoC AD1938/AD1939 audio CODEC driver");
+MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index 5a42dca535b..6844d0b2af6 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -6,12 +6,10 @@
* Licensed under the GPL-2 or later.
*/
-#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
-#include <linux/i2c.h>
-#include <linux/spi/spi.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -19,6 +17,7 @@
#include <sound/initval.h>
#include <sound/soc.h>
#include <sound/tlv.h>
+
#include "ad193x.h"
/* codec private data */
@@ -32,8 +31,8 @@ struct ad193x_priv {
*/
static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
-static const struct soc_enum ad193x_deemp_enum =
- SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp);
+static SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1,
+ ad193x_deemp);
static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0);
@@ -320,17 +319,9 @@ static struct snd_soc_dai_driver ad193x_dai = {
.ops = &ad193x_dai_ops,
};
-static int ad193x_probe(struct snd_soc_codec *codec)
+static int ad193x_codec_probe(struct snd_soc_codec *codec)
{
struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- codec->control_data = ad193x->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
- return ret;
- }
/* default setting for ad193x */
@@ -348,11 +339,11 @@ static int ad193x_probe(struct snd_soc_codec *codec)
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);
- return ret;
+ return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
- .probe = ad193x_probe,
+ .probe = ad193x_codec_probe,
.controls = ad193x_snd_controls,
.num_controls = ARRAY_SIZE(ad193x_snd_controls),
.dapm_widgets = ad193x_dapm_widgets,
@@ -366,140 +357,31 @@ static bool adau193x_reg_volatile(struct device *dev, unsigned int reg)
return false;
}
-#if defined(CONFIG_SPI_MASTER)
-
-static const struct regmap_config ad193x_spi_regmap_config = {
- .val_bits = 8,
- .reg_bits = 16,
- .read_flag_mask = 0x09,
- .write_flag_mask = 0x08,
-
+const struct regmap_config ad193x_regmap_config = {
.max_register = AD193X_NUM_REGS - 1,
.volatile_reg = adau193x_reg_volatile,
};
+EXPORT_SYMBOL_GPL(ad193x_regmap_config);
-static int ad193x_spi_probe(struct spi_device *spi)
+int ad193x_probe(struct device *dev, struct regmap *regmap)
{
struct ad193x_priv *ad193x;
- ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv),
- GFP_KERNEL);
- if (ad193x == NULL)
- return -ENOMEM;
-
- ad193x->regmap = devm_regmap_init_spi(spi, &ad193x_spi_regmap_config);
- if (IS_ERR(ad193x->regmap))
- return PTR_ERR(ad193x->regmap);
-
- spi_set_drvdata(spi, ad193x);
-
- return snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x,
- &ad193x_dai, 1);
-}
-
-static int ad193x_spi_remove(struct spi_device *spi)
-{
- snd_soc_unregister_codec(&spi->dev);
- return 0;
-}
-
-static struct spi_driver ad193x_spi_driver = {
- .driver = {
- .name = "ad193x",
- .owner = THIS_MODULE,
- },
- .probe = ad193x_spi_probe,
- .remove = ad193x_spi_remove,
-};
-#endif
-
-#if IS_ENABLED(CONFIG_I2C)
-
-static const struct regmap_config ad193x_i2c_regmap_config = {
- .val_bits = 8,
- .reg_bits = 8,
-
- .max_register = AD193X_NUM_REGS - 1,
- .volatile_reg = adau193x_reg_volatile,
-};
-
-static const struct i2c_device_id ad193x_id[] = {
- { "ad1936", 0 },
- { "ad1937", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, ad193x_id);
-
-static int ad193x_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct ad193x_priv *ad193x;
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
- ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv),
- GFP_KERNEL);
+ ad193x = devm_kzalloc(dev, sizeof(*ad193x), GFP_KERNEL);
if (ad193x == NULL)
return -ENOMEM;
- ad193x->regmap = devm_regmap_init_i2c(client, &ad193x_i2c_regmap_config);
- if (IS_ERR(ad193x->regmap))
- return PTR_ERR(ad193x->regmap);
-
- i2c_set_clientdata(client, ad193x);
-
- return snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x,
- &ad193x_dai, 1);
-}
-
-static int ad193x_i2c_remove(struct i2c_client *client)
-{
- snd_soc_unregister_codec(&client->dev);
- return 0;
-}
-
-static struct i2c_driver ad193x_i2c_driver = {
- .driver = {
- .name = "ad193x",
- },
- .probe = ad193x_i2c_probe,
- .remove = ad193x_i2c_remove,
- .id_table = ad193x_id,
-};
-#endif
-
-static int __init ad193x_modinit(void)
-{
- int ret;
-
-#if IS_ENABLED(CONFIG_I2C)
- ret = i2c_add_driver(&ad193x_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n",
- ret);
- }
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
- ret = spi_register_driver(&ad193x_spi_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register AD193X SPI driver: %d\n",
- ret);
- }
-#endif
- return ret;
-}
-module_init(ad193x_modinit);
+ ad193x->regmap = regmap;
-static void __exit ad193x_modexit(void)
-{
-#if defined(CONFIG_SPI_MASTER)
- spi_unregister_driver(&ad193x_spi_driver);
-#endif
+ dev_set_drvdata(dev, ad193x);
-#if IS_ENABLED(CONFIG_I2C)
- i2c_del_driver(&ad193x_i2c_driver);
-#endif
+ return snd_soc_register_codec(dev, &soc_codec_dev_ad193x,
+ &ad193x_dai, 1);
}
-module_exit(ad193x_modexit);
+EXPORT_SYMBOL_GPL(ad193x_probe);
MODULE_DESCRIPTION("ASoC ad193x driver");
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h
index 47338804999..ab9a998f15b 100644
--- a/sound/soc/codecs/ad193x.h
+++ b/sound/soc/codecs/ad193x.h
@@ -9,6 +9,13 @@
#ifndef __AD193X_H__
#define __AD193X_H__
+#include <linux/regmap.h>
+
+struct device;
+
+extern const struct regmap_config ad193x_regmap_config;
+int ad193x_probe(struct device *dev, struct regmap *regmap);
+
#define AD193X_PLL_CLK_CTRL0 0x00
#define AD193X_PLL_POWERDOWN 0x01
#define AD193X_PLL_INPUT_MASK 0x6
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 7257a8885f4..304d3003339 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -57,8 +57,8 @@ static const u16 ad1980_reg[] = {
static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line",
"Stereo Mix", "Mono Mix", "Phone"};
-static const struct soc_enum ad1980_cap_src =
- SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 7, ad1980_rec_sel);
+static SOC_ENUM_DOUBLE_DECL(ad1980_cap_src,
+ AC97_REC_SEL, 8, 0, ad1980_rec_sel);
static const struct snd_kcontrol_new ad1980_snd_ac97_controls[] = {
SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1),
@@ -189,28 +189,27 @@ static struct snd_soc_dai_driver ad1980_dai = {
static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
{
- u16 retry_cnt = 0;
+ unsigned int retry_cnt = 0;
-retry:
- if (try_warm && soc_ac97_ops->warm_reset) {
- soc_ac97_ops->warm_reset(codec->ac97);
- if (ac97_read(codec, AC97_RESET) == 0x0090)
- return 1;
- }
-
- soc_ac97_ops->reset(codec->ac97);
- /* Set bit 16slot in register 74h, then every slot will has only 16
- * bits. This command is sent out in 20bit mode, in which case the
- * first nibble of data is eaten by the addr. (Tag is always 16 bit)*/
- ac97_write(codec, AC97_AD_SERIAL_CFG, 0x9900);
-
- if (ac97_read(codec, AC97_RESET) != 0x0090)
- goto err;
- return 0;
+ do {
+ if (try_warm && soc_ac97_ops->warm_reset) {
+ soc_ac97_ops->warm_reset(codec->ac97);
+ if (ac97_read(codec, AC97_RESET) == 0x0090)
+ return 1;
+ }
-err:
- while (retry_cnt++ < 10)
- goto retry;
+ soc_ac97_ops->reset(codec->ac97);
+ /*
+ * Set bit 16slot in register 74h, then every slot will has only
+ * 16 bits. This command is sent out in 20bit mode, in which
+ * case the first nibble of data is eaten by the addr. (Tag is
+ * always 16 bit)
+ */
+ ac97_write(codec, AC97_AD_SERIAL_CFG, 0x9900);
+
+ if (ac97_read(codec, AC97_RESET) == 0x0090)
+ return 0;
+ } while (retry_cnt++ < 10);
printk(KERN_ERR "AD1980 AC97 reset failed\n");
return -EIO;
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index eb836ed5271..1ff7d4d027e 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -345,15 +345,15 @@ static const char *adau1373_fdsp_sel_text[] = {
"Channel 5",
};
-static const SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum,
+static SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum,
ADAU1373_FDSP_SEL1, 4, adau1373_fdsp_sel_text);
-static const SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum,
+static SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum,
ADAU1373_FDSP_SEL1, 0, adau1373_fdsp_sel_text);
-static const SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum,
+static SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum,
ADAU1373_FDSP_SEL2, 0, adau1373_fdsp_sel_text);
-static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum,
+static SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum,
ADAU1373_FDSP_SEL3, 0, adau1373_fdsp_sel_text);
-static const SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum,
+static SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum,
ADAU1373_FDSP_SEL4, 4, adau1373_fdsp_sel_text);
static const char *adau1373_hpf_cutoff_text[] = {
@@ -362,7 +362,7 @@ static const char *adau1373_hpf_cutoff_text[] = {
"800Hz",
};
-static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum,
+static SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum,
ADAU1373_HPF_CTRL, 3, adau1373_hpf_cutoff_text);
static const char *adau1373_bass_lpf_cutoff_text[] = {
@@ -388,14 +388,14 @@ static const unsigned int adau1373_bass_tlv[] = {
5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0),
};
-static const SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum,
+static SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum,
ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text);
-static const SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum,
+static SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum,
ADAU1373_BASS1, 2, 7, adau1373_bass_clip_level_text,
adau1373_bass_clip_level_values);
-static const SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum,
+static SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum,
ADAU1373_BASS1, 0, adau1373_bass_hpf_cutoff_text);
static const char *adau1373_3d_level_text[] = {
@@ -409,9 +409,9 @@ static const char *adau1373_3d_cutoff_text[] = {
"0.16875 fs", "0.27083 fs"
};
-static const SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum,
+static SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum,
ADAU1373_3D_CTRL1, 4, adau1373_3d_level_text);
-static const SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum,
+static SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum,
ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text);
static const unsigned int adau1373_3d_tlv[] = {
@@ -427,11 +427,11 @@ static const char *adau1373_lr_mux_text[] = {
"Stereo",
};
-static const SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum,
+static SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum,
ADAU1373_OUTPUT_CTRL, 4, adau1373_lr_mux_text);
-static const SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum,
+static SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum,
ADAU1373_OUTPUT_CTRL, 6, adau1373_lr_mux_text);
-static const SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum,
+static SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum,
ADAU1373_LS_CTRL, 4, adau1373_lr_mux_text);
static const struct snd_kcontrol_new adau1373_controls[] = {
@@ -519,8 +519,7 @@ static const struct snd_kcontrol_new adau1373_controls[] = {
SOC_ENUM("HPF Channel", adau1373_hpf_channel_enum),
SOC_ENUM("Bass HPF Cutoff", adau1373_bass_hpf_cutoff_enum),
- SOC_VALUE_ENUM("Bass Clip Level Threshold",
- adau1373_bass_clip_level_enum),
+ SOC_ENUM("Bass Clip Level Threshold", adau1373_bass_clip_level_enum),
SOC_ENUM("Bass LPF Cutoff", adau1373_bass_lpf_cutoff_enum),
SOC_DOUBLE("Bass Playback Switch", ADAU1373_BASS2, 0, 1, 1, 0),
SOC_SINGLE_TLV("Bass Playback Volume", ADAU1373_BASS2, 2, 7, 0,
@@ -576,11 +575,11 @@ static const char *adau1373_decimator_text[] = {
"DMIC1",
};
-static const struct soc_enum adau1373_decimator_enum =
- SOC_ENUM_SINGLE(0, 0, 2, adau1373_decimator_text);
+static SOC_ENUM_SINGLE_VIRT_DECL(adau1373_decimator_enum,
+ adau1373_decimator_text);
static const struct snd_kcontrol_new adau1373_decimator_mux =
- SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum);
+ SOC_DAPM_ENUM("Decimator Mux", adau1373_decimator_enum);
static const struct snd_kcontrol_new adau1373_left_adc_mixer_controls[] = {
SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_LADC_MIXER, 4, 1, 0),
@@ -694,7 +693,7 @@ static const struct snd_soc_dapm_widget adau1373_dapm_widgets[] = {
SND_SOC_DAPM_ADC("DMIC1", NULL, ADAU1373_DIGMICCTRL, 0, 0),
SND_SOC_DAPM_ADC("DMIC2", NULL, ADAU1373_DIGMICCTRL, 2, 0),
- SND_SOC_DAPM_VIRT_MUX("Decimator Mux", SND_SOC_NOPM, 0, 0,
+ SND_SOC_DAPM_MUX("Decimator Mux", SND_SOC_NOPM, 0, 0,
&adau1373_decimator_mux),
SND_SOC_DAPM_SUPPLY("MICBIAS2", ADAU1373_PWDN_CTRL1, 5, 0, NULL, 0),
@@ -1376,15 +1375,8 @@ static int adau1373_probe(struct snd_soc_codec *codec)
struct adau1373_platform_data *pdata = codec->dev->platform_data;
bool lineout_differential = false;
unsigned int val;
- int ret;
int i;
- ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
- if (ret) {
- dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
if (pdata) {
if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting))
return -EINVAL;
diff --git a/sound/soc/codecs/adau1761-i2c.c b/sound/soc/codecs/adau1761-i2c.c
new file mode 100644
index 00000000000..862796dec69
--- /dev/null
+++ b/sound/soc/codecs/adau1761-i2c.c
@@ -0,0 +1,60 @@
+/*
+ * Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961 codec
+ *
+ * Copyright 2014 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/i2c.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+
+#include "adau1761.h"
+
+static int adau1761_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct regmap_config config;
+
+ config = adau1761_regmap_config;
+ config.val_bits = 8;
+ config.reg_bits = 16;
+
+ return adau1761_probe(&client->dev,
+ devm_regmap_init_i2c(client, &config),
+ id->driver_data, NULL);
+}
+
+static int adau1761_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static const struct i2c_device_id adau1761_i2c_ids[] = {
+ { "adau1361", ADAU1361 },
+ { "adau1461", ADAU1761 },
+ { "adau1761", ADAU1761 },
+ { "adau1961", ADAU1361 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adau1761_i2c_ids);
+
+static struct i2c_driver adau1761_i2c_driver = {
+ .driver = {
+ .name = "adau1761",
+ .owner = THIS_MODULE,
+ },
+ .probe = adau1761_i2c_probe,
+ .remove = adau1761_i2c_remove,
+ .id_table = adau1761_i2c_ids,
+};
+module_i2c_driver(adau1761_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC ADAU1361/ADAU1461/ADAU1761/ADAU1961 CODEC I2C driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1761-spi.c b/sound/soc/codecs/adau1761-spi.c
new file mode 100644
index 00000000000..cce2f11f1ff
--- /dev/null
+++ b/sound/soc/codecs/adau1761-spi.c
@@ -0,0 +1,77 @@
+/*
+ * Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961 codec
+ *
+ * Copyright 2014 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <sound/soc.h>
+
+#include "adau1761.h"
+
+static void adau1761_spi_switch_mode(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+
+ /*
+ * To get the device into SPI mode CLATCH has to be pulled low three
+ * times. Do this by issuing three dummy reads.
+ */
+ spi_w8r8(spi, 0x00);
+ spi_w8r8(spi, 0x00);
+ spi_w8r8(spi, 0x00);
+}
+
+static int adau1761_spi_probe(struct spi_device *spi)
+{
+ const struct spi_device_id *id = spi_get_device_id(spi);
+ struct regmap_config config;
+
+ if (!id)
+ return -EINVAL;
+
+ config = adau1761_regmap_config;
+ config.val_bits = 8;
+ config.reg_bits = 24;
+ config.read_flag_mask = 0x1;
+
+ return adau1761_probe(&spi->dev,
+ devm_regmap_init_spi(spi, &config),
+ id->driver_data, adau1761_spi_switch_mode);
+}
+
+static int adau1761_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ return 0;
+}
+
+static const struct spi_device_id adau1761_spi_id[] = {
+ { "adau1361", ADAU1361 },
+ { "adau1461", ADAU1761 },
+ { "adau1761", ADAU1761 },
+ { "adau1961", ADAU1361 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, adau1761_spi_id);
+
+static struct spi_driver adau1761_spi_driver = {
+ .driver = {
+ .name = "adau1761",
+ .owner = THIS_MODULE,
+ },
+ .probe = adau1761_spi_probe,
+ .remove = adau1761_spi_remove,
+ .id_table = adau1761_spi_id,
+};
+module_spi_driver(adau1761_spi_driver);
+
+MODULE_DESCRIPTION("ASoC ADAU1361/ADAU1461/ADAU1761/ADAU1961 CODEC SPI driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c
new file mode 100644
index 00000000000..848cab83955
--- /dev/null
+++ b/sound/soc/codecs/adau1761.c
@@ -0,0 +1,803 @@
+/*
+ * Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961 codec
+ *
+ * Copyright 2011-2013 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <linux/platform_data/adau17x1.h>
+
+#include "adau17x1.h"
+#include "adau1761.h"
+
+#define ADAU1761_DIGMIC_JACKDETECT 0x4008
+#define ADAU1761_REC_MIXER_LEFT0 0x400a
+#define ADAU1761_REC_MIXER_LEFT1 0x400b
+#define ADAU1761_REC_MIXER_RIGHT0 0x400c
+#define ADAU1761_REC_MIXER_RIGHT1 0x400d
+#define ADAU1761_LEFT_DIFF_INPUT_VOL 0x400e
+#define ADAU1761_RIGHT_DIFF_INPUT_VOL 0x400f
+#define ADAU1761_PLAY_LR_MIXER_LEFT 0x4020
+#define ADAU1761_PLAY_MIXER_LEFT0 0x401c
+#define ADAU1761_PLAY_MIXER_LEFT1 0x401d
+#define ADAU1761_PLAY_MIXER_RIGHT0 0x401e
+#define ADAU1761_PLAY_MIXER_RIGHT1 0x401f
+#define ADAU1761_PLAY_LR_MIXER_RIGHT 0x4021
+#define ADAU1761_PLAY_MIXER_MONO 0x4022
+#define ADAU1761_PLAY_HP_LEFT_VOL 0x4023
+#define ADAU1761_PLAY_HP_RIGHT_VOL 0x4024
+#define ADAU1761_PLAY_LINE_LEFT_VOL 0x4025
+#define ADAU1761_PLAY_LINE_RIGHT_VOL 0x4026
+#define ADAU1761_PLAY_MONO_OUTPUT_VOL 0x4027
+#define ADAU1761_POP_CLICK_SUPPRESS 0x4028
+#define ADAU1761_JACK_DETECT_PIN 0x4031
+#define ADAU1761_DEJITTER 0x4036
+#define ADAU1761_CLK_ENABLE0 0x40f9
+#define ADAU1761_CLK_ENABLE1 0x40fa
+
+#define ADAU1761_DIGMIC_JACKDETECT_ACTIVE_LOW BIT(0)
+#define ADAU1761_DIGMIC_JACKDETECT_DIGMIC BIT(5)
+
+#define ADAU1761_DIFF_INPUT_VOL_LDEN BIT(0)
+
+#define ADAU1761_PLAY_MONO_OUTPUT_VOL_MODE_HP BIT(0)
+#define ADAU1761_PLAY_MONO_OUTPUT_VOL_UNMUTE BIT(1)
+
+#define ADAU1761_PLAY_HP_RIGHT_VOL_MODE_HP BIT(0)
+
+#define ADAU1761_PLAY_LINE_LEFT_VOL_MODE_HP BIT(0)
+
+#define ADAU1761_PLAY_LINE_RIGHT_VOL_MODE_HP BIT(0)
+
+
+#define ADAU1761_FIRMWARE "adau1761.bin"
+
+static const struct reg_default adau1761_reg_defaults[] = {
+ { ADAU1761_DEJITTER, 0x03 },
+ { ADAU1761_DIGMIC_JACKDETECT, 0x00 },
+ { ADAU1761_REC_MIXER_LEFT0, 0x00 },
+ { ADAU1761_REC_MIXER_LEFT1, 0x00 },
+ { ADAU1761_REC_MIXER_RIGHT0, 0x00 },
+ { ADAU1761_REC_MIXER_RIGHT1, 0x00 },
+ { ADAU1761_LEFT_DIFF_INPUT_VOL, 0x00 },
+ { ADAU1761_RIGHT_DIFF_INPUT_VOL, 0x00 },
+ { ADAU1761_PLAY_LR_MIXER_LEFT, 0x00 },
+ { ADAU1761_PLAY_MIXER_LEFT0, 0x00 },
+ { ADAU1761_PLAY_MIXER_LEFT1, 0x00 },
+ { ADAU1761_PLAY_MIXER_RIGHT0, 0x00 },
+ { ADAU1761_PLAY_MIXER_RIGHT1, 0x00 },
+ { ADAU1761_PLAY_LR_MIXER_RIGHT, 0x00 },
+ { ADAU1761_PLAY_MIXER_MONO, 0x00 },
+ { ADAU1761_PLAY_HP_LEFT_VOL, 0x00 },
+ { ADAU1761_PLAY_HP_RIGHT_VOL, 0x00 },
+ { ADAU1761_PLAY_LINE_LEFT_VOL, 0x00 },
+ { ADAU1761_PLAY_LINE_RIGHT_VOL, 0x00 },
+ { ADAU1761_PLAY_MONO_OUTPUT_VOL, 0x00 },
+ { ADAU1761_POP_CLICK_SUPPRESS, 0x00 },
+ { ADAU1761_JACK_DETECT_PIN, 0x00 },
+ { ADAU1761_CLK_ENABLE0, 0x00 },
+ { ADAU1761_CLK_ENABLE1, 0x00 },
+ { ADAU17X1_CLOCK_CONTROL, 0x00 },
+ { ADAU17X1_PLL_CONTROL, 0x00 },
+ { ADAU17X1_REC_POWER_MGMT, 0x00 },
+ { ADAU17X1_MICBIAS, 0x00 },
+ { ADAU17X1_SERIAL_PORT0, 0x00 },
+ { ADAU17X1_SERIAL_PORT1, 0x00 },
+ { ADAU17X1_CONVERTER0, 0x00 },
+ { ADAU17X1_CONVERTER1, 0x00 },
+ { ADAU17X1_LEFT_INPUT_DIGITAL_VOL, 0x00 },
+ { ADAU17X1_RIGHT_INPUT_DIGITAL_VOL, 0x00 },
+ { ADAU17X1_ADC_CONTROL, 0x00 },
+ { ADAU17X1_PLAY_POWER_MGMT, 0x00 },
+ { ADAU17X1_DAC_CONTROL0, 0x00 },
+ { ADAU17X1_DAC_CONTROL1, 0x00 },
+ { ADAU17X1_DAC_CONTROL2, 0x00 },
+ { ADAU17X1_SERIAL_PORT_PAD, 0xaa },
+ { ADAU17X1_CONTROL_PORT_PAD0, 0xaa },
+ { ADAU17X1_CONTROL_PORT_PAD1, 0x00 },
+ { ADAU17X1_DSP_SAMPLING_RATE, 0x01 },
+ { ADAU17X1_SERIAL_INPUT_ROUTE, 0x00 },
+ { ADAU17X1_SERIAL_OUTPUT_ROUTE, 0x00 },
+ { ADAU17X1_DSP_ENABLE, 0x00 },
+ { ADAU17X1_DSP_RUN, 0x00 },
+ { ADAU17X1_SERIAL_SAMPLING_RATE, 0x00 },
+};
+
+static const DECLARE_TLV_DB_SCALE(adau1761_sing_in_tlv, -1500, 300, 1);
+static const DECLARE_TLV_DB_SCALE(adau1761_diff_in_tlv, -1200, 75, 0);
+static const DECLARE_TLV_DB_SCALE(adau1761_out_tlv, -5700, 100, 0);
+static const DECLARE_TLV_DB_SCALE(adau1761_sidetone_tlv, -1800, 300, 1);
+static const DECLARE_TLV_DB_SCALE(adau1761_boost_tlv, -600, 600, 1);
+static const DECLARE_TLV_DB_SCALE(adau1761_pga_boost_tlv, -2000, 2000, 1);
+
+static const unsigned int adau1761_bias_select_values[] = {
+ 0, 2, 3,
+};
+
+static const char * const adau1761_bias_select_text[] = {
+ "Normal operation", "Enhanced performance", "Power saving",
+};
+
+static const char * const adau1761_bias_select_extreme_text[] = {
+ "Normal operation", "Extreme power saving", "Enhanced performance",
+ "Power saving",
+};
+
+static SOC_ENUM_SINGLE_DECL(adau1761_adc_bias_enum,
+ ADAU17X1_REC_POWER_MGMT, 3, adau1761_bias_select_extreme_text);
+static SOC_ENUM_SINGLE_DECL(adau1761_hp_bias_enum,
+ ADAU17X1_PLAY_POWER_MGMT, 6, adau1761_bias_select_extreme_text);
+static SOC_ENUM_SINGLE_DECL(adau1761_dac_bias_enum,
+ ADAU17X1_PLAY_POWER_MGMT, 4, adau1761_bias_select_extreme_text);
+static SOC_VALUE_ENUM_SINGLE_DECL(adau1761_playback_bias_enum,
+ ADAU17X1_PLAY_POWER_MGMT, 2, 0x3, adau1761_bias_select_text,
+ adau1761_bias_select_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(adau1761_capture_bias_enum,
+ ADAU17X1_REC_POWER_MGMT, 1, 0x3, adau1761_bias_select_text,
+ adau1761_bias_select_values);
+
+static const struct snd_kcontrol_new adau1761_jack_detect_controls[] = {
+ SOC_SINGLE("Speaker Auto-mute Switch", ADAU1761_DIGMIC_JACKDETECT,
+ 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new adau1761_differential_mode_controls[] = {
+ SOC_DOUBLE_R_TLV("Capture Volume", ADAU1761_LEFT_DIFF_INPUT_VOL,
+ ADAU1761_RIGHT_DIFF_INPUT_VOL, 2, 0x3f, 0,
+ adau1761_diff_in_tlv),
+ SOC_DOUBLE_R("Capture Switch", ADAU1761_LEFT_DIFF_INPUT_VOL,
+ ADAU1761_RIGHT_DIFF_INPUT_VOL, 1, 1, 0),
+
+ SOC_DOUBLE_R_TLV("PGA Boost Capture Volume", ADAU1761_REC_MIXER_LEFT1,
+ ADAU1761_REC_MIXER_RIGHT1, 3, 2, 0, adau1761_pga_boost_tlv),
+};
+
+static const struct snd_kcontrol_new adau1761_single_mode_controls[] = {
+ SOC_SINGLE_TLV("Input 1 Capture Volume", ADAU1761_REC_MIXER_LEFT0,
+ 4, 7, 0, adau1761_sing_in_tlv),
+ SOC_SINGLE_TLV("Input 2 Capture Volume", ADAU1761_REC_MIXER_LEFT0,
+ 1, 7, 0, adau1761_sing_in_tlv),
+ SOC_SINGLE_TLV("Input 3 Capture Volume", ADAU1761_REC_MIXER_RIGHT0,
+ 4, 7, 0, adau1761_sing_in_tlv),
+ SOC_SINGLE_TLV("Input 4 Capture Volume", ADAU1761_REC_MIXER_RIGHT0,
+ 1, 7, 0, adau1761_sing_in_tlv),
+};
+
+static const struct snd_kcontrol_new adau1761_controls[] = {
+ SOC_DOUBLE_R_TLV("Aux Capture Volume", ADAU1761_REC_MIXER_LEFT1,
+ ADAU1761_REC_MIXER_RIGHT1, 0, 7, 0, adau1761_sing_in_tlv),
+
+ SOC_DOUBLE_R_TLV("Headphone Playback Volume", ADAU1761_PLAY_HP_LEFT_VOL,
+ ADAU1761_PLAY_HP_RIGHT_VOL, 2, 0x3f, 0, adau1761_out_tlv),
+ SOC_DOUBLE_R("Headphone Playback Switch", ADAU1761_PLAY_HP_LEFT_VOL,
+ ADAU1761_PLAY_HP_RIGHT_VOL, 1, 1, 0),
+ SOC_DOUBLE_R_TLV("Lineout Playback Volume", ADAU1761_PLAY_LINE_LEFT_VOL,
+ ADAU1761_PLAY_LINE_RIGHT_VOL, 2, 0x3f, 0, adau1761_out_tlv),
+ SOC_DOUBLE_R("Lineout Playback Switch", ADAU1761_PLAY_LINE_LEFT_VOL,
+ ADAU1761_PLAY_LINE_RIGHT_VOL, 1, 1, 0),
+
+ SOC_ENUM("ADC Bias", adau1761_adc_bias_enum),
+ SOC_ENUM("DAC Bias", adau1761_dac_bias_enum),
+ SOC_ENUM("Capture Bias", adau1761_capture_bias_enum),
+ SOC_ENUM("Playback Bias", adau1761_playback_bias_enum),
+ SOC_ENUM("Headphone Bias", adau1761_hp_bias_enum),
+};
+
+static const struct snd_kcontrol_new adau1761_mono_controls[] = {
+ SOC_SINGLE_TLV("Mono Playback Volume", ADAU1761_PLAY_MONO_OUTPUT_VOL,
+ 2, 0x3f, 0, adau1761_out_tlv),
+ SOC_SINGLE("Mono Playback Switch", ADAU1761_PLAY_MONO_OUTPUT_VOL,
+ 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new adau1761_left_mixer_controls[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("Left DAC Switch",
+ ADAU1761_PLAY_MIXER_LEFT0, 5, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("Right DAC Switch",
+ ADAU1761_PLAY_MIXER_LEFT0, 6, 1, 0),
+ SOC_DAPM_SINGLE_TLV("Aux Bypass Volume",
+ ADAU1761_PLAY_MIXER_LEFT0, 1, 8, 0, adau1761_sidetone_tlv),
+ SOC_DAPM_SINGLE_TLV("Right Bypass Volume",
+ ADAU1761_PLAY_MIXER_LEFT1, 4, 8, 0, adau1761_sidetone_tlv),
+ SOC_DAPM_SINGLE_TLV("Left Bypass Volume",
+ ADAU1761_PLAY_MIXER_LEFT1, 0, 8, 0, adau1761_sidetone_tlv),
+};
+
+static const struct snd_kcontrol_new adau1761_right_mixer_controls[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("Left DAC Switch",
+ ADAU1761_PLAY_MIXER_RIGHT0, 5, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("Right DAC Switch",
+ ADAU1761_PLAY_MIXER_RIGHT0, 6, 1, 0),
+ SOC_DAPM_SINGLE_TLV("Aux Bypass Volume",
+ ADAU1761_PLAY_MIXER_RIGHT0, 1, 8, 0, adau1761_sidetone_tlv),
+ SOC_DAPM_SINGLE_TLV("Right Bypass Volume",
+ ADAU1761_PLAY_MIXER_RIGHT1, 4, 8, 0, adau1761_sidetone_tlv),
+ SOC_DAPM_SINGLE_TLV("Left Bypass Volume",
+ ADAU1761_PLAY_MIXER_RIGHT1, 0, 8, 0, adau1761_sidetone_tlv),
+};
+
+static const struct snd_kcontrol_new adau1761_left_lr_mixer_controls[] = {
+ SOC_DAPM_SINGLE_TLV("Left Volume",
+ ADAU1761_PLAY_LR_MIXER_LEFT, 1, 2, 0, adau1761_boost_tlv),
+ SOC_DAPM_SINGLE_TLV("Right Volume",
+ ADAU1761_PLAY_LR_MIXER_LEFT, 3, 2, 0, adau1761_boost_tlv),
+};
+
+static const struct snd_kcontrol_new adau1761_right_lr_mixer_controls[] = {
+ SOC_DAPM_SINGLE_TLV("Left Volume",
+ ADAU1761_PLAY_LR_MIXER_RIGHT, 1, 2, 0, adau1761_boost_tlv),
+ SOC_DAPM_SINGLE_TLV("Right Volume",
+ ADAU1761_PLAY_LR_MIXER_RIGHT, 3, 2, 0, adau1761_boost_tlv),
+};
+
+static const char * const adau1761_input_mux_text[] = {
+ "ADC", "DMIC",
+};
+
+static SOC_ENUM_SINGLE_DECL(adau1761_input_mux_enum,
+ ADAU17X1_ADC_CONTROL, 2, adau1761_input_mux_text);
+
+static const struct snd_kcontrol_new adau1761_input_mux_control =
+ SOC_DAPM_ENUM("Input Select", adau1761_input_mux_enum);
+
+static int adau1761_dejitter_fixup(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(w->codec);
+
+ /* After any power changes have been made the dejitter circuit
+ * has to be reinitialized. */
+ regmap_write(adau->regmap, ADAU1761_DEJITTER, 0);
+ if (!adau->master)
+ regmap_write(adau->regmap, ADAU1761_DEJITTER, 3);
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget adau1x61_dapm_widgets[] = {
+ SND_SOC_DAPM_MIXER("Left Input Mixer", ADAU1761_REC_MIXER_LEFT0, 0, 0,
+ NULL, 0),
+ SND_SOC_DAPM_MIXER("Right Input Mixer", ADAU1761_REC_MIXER_RIGHT0, 0, 0,
+ NULL, 0),
+
+ SOC_MIXER_ARRAY("Left Playback Mixer", ADAU1761_PLAY_MIXER_LEFT0,
+ 0, 0, adau1761_left_mixer_controls),
+ SOC_MIXER_ARRAY("Right Playback Mixer", ADAU1761_PLAY_MIXER_RIGHT0,
+ 0, 0, adau1761_right_mixer_controls),
+ SOC_MIXER_ARRAY("Left LR Playback Mixer", ADAU1761_PLAY_LR_MIXER_LEFT,
+ 0, 0, adau1761_left_lr_mixer_controls),
+ SOC_MIXER_ARRAY("Right LR Playback Mixer", ADAU1761_PLAY_LR_MIXER_RIGHT,
+ 0, 0, adau1761_right_lr_mixer_controls),
+
+ SND_SOC_DAPM_SUPPLY("Headphone", ADAU1761_PLAY_HP_LEFT_VOL,
+ 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY_S("SYSCLK", 2, SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_POST("Dejitter fixup", adau1761_dejitter_fixup),
+
+ SND_SOC_DAPM_INPUT("LAUX"),
+ SND_SOC_DAPM_INPUT("RAUX"),
+ SND_SOC_DAPM_INPUT("LINP"),
+ SND_SOC_DAPM_INPUT("LINN"),
+ SND_SOC_DAPM_INPUT("RINP"),
+ SND_SOC_DAPM_INPUT("RINN"),
+
+ SND_SOC_DAPM_OUTPUT("LOUT"),
+ SND_SOC_DAPM_OUTPUT("ROUT"),
+ SND_SOC_DAPM_OUTPUT("LHP"),
+ SND_SOC_DAPM_OUTPUT("RHP"),
+};
+
+static const struct snd_soc_dapm_widget adau1761_mono_dapm_widgets[] = {
+ SND_SOC_DAPM_MIXER("Mono Playback Mixer", ADAU1761_PLAY_MIXER_MONO,
+ 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_OUTPUT("MONOOUT"),
+};
+
+static const struct snd_soc_dapm_widget adau1761_capless_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY_S("Headphone VGND", 1, ADAU1761_PLAY_MIXER_MONO,
+ 0, 0, NULL, 0),
+};
+
+static const struct snd_soc_dapm_route adau1x61_dapm_routes[] = {
+ { "Left Input Mixer", NULL, "LINP" },
+ { "Left Input Mixer", NULL, "LINN" },
+ { "Left Input Mixer", NULL, "LAUX" },
+
+ { "Right Input Mixer", NULL, "RINP" },
+ { "Right Input Mixer", NULL, "RINN" },
+ { "Right Input Mixer", NULL, "RAUX" },
+
+ { "Left Playback Mixer", NULL, "Left Playback Enable"},
+ { "Right Playback Mixer", NULL, "Right Playback Enable"},
+ { "Left LR Playback Mixer", NULL, "Left Playback Enable"},
+ { "Right LR Playback Mixer", NULL, "Right Playback Enable"},
+
+ { "Left Playback Mixer", "Left DAC Switch", "Left DAC" },
+ { "Left Playback Mixer", "Right DAC Switch", "Right DAC" },
+
+ { "Right Playback Mixer", "Left DAC Switch", "Left DAC" },
+ { "Right Playback Mixer", "Right DAC Switch", "Right DAC" },
+
+ { "Left LR Playback Mixer", "Left Volume", "Left Playback Mixer" },
+ { "Left LR Playback Mixer", "Right Volume", "Right Playback Mixer" },
+
+ { "Right LR Playback Mixer", "Left Volume", "Left Playback Mixer" },
+ { "Right LR Playback Mixer", "Right Volume", "Right Playback Mixer" },
+
+ { "LHP", NULL, "Left Playback Mixer" },
+ { "RHP", NULL, "Right Playback Mixer" },
+
+ { "LHP", NULL, "Headphone" },
+ { "RHP", NULL, "Headphone" },
+
+ { "LOUT", NULL, "Left LR Playback Mixer" },
+ { "ROUT", NULL, "Right LR Playback Mixer" },
+
+ { "Left Playback Mixer", "Aux Bypass Volume", "LAUX" },
+ { "Left Playback Mixer", "Left Bypass Volume", "Left Input Mixer" },
+ { "Left Playback Mixer", "Right Bypass Volume", "Right Input Mixer" },
+ { "Right Playback Mixer", "Aux Bypass Volume", "RAUX" },
+ { "Right Playback Mixer", "Left Bypass Volume", "Left Input Mixer" },
+ { "Right Playback Mixer", "Right Bypass Volume", "Right Input Mixer" },
+};
+
+static const struct snd_soc_dapm_route adau1761_mono_dapm_routes[] = {
+ { "Mono Playback Mixer", NULL, "Left Playback Mixer" },
+ { "Mono Playback Mixer", NULL, "Right Playback Mixer" },
+
+ { "MONOOUT", NULL, "Mono Playback Mixer" },
+};
+
+static const struct snd_soc_dapm_route adau1761_capless_dapm_routes[] = {
+ { "Headphone", NULL, "Headphone VGND" },
+};
+
+static const struct snd_soc_dapm_widget adau1761_dmic_widgets[] = {
+ SND_SOC_DAPM_MUX("Left Decimator Mux", SND_SOC_NOPM, 0, 0,
+ &adau1761_input_mux_control),
+ SND_SOC_DAPM_MUX("Right Decimator Mux", SND_SOC_NOPM, 0, 0,
+ &adau1761_input_mux_control),
+
+ SND_SOC_DAPM_INPUT("DMIC"),
+};
+
+static const struct snd_soc_dapm_route adau1761_dmic_routes[] = {
+ { "Left Decimator Mux", "ADC", "Left Input Mixer" },
+ { "Left Decimator Mux", "DMIC", "DMIC" },
+ { "Right Decimator Mux", "ADC", "Right Input Mixer" },
+ { "Right Decimator Mux", "DMIC", "DMIC" },
+
+ { "Left Decimator", NULL, "Left Decimator Mux" },
+ { "Right Decimator", NULL, "Right Decimator Mux" },
+};
+
+static const struct snd_soc_dapm_route adau1761_no_dmic_routes[] = {
+ { "Left Decimator", NULL, "Left Input Mixer" },
+ { "Right Decimator", NULL, "Right Input Mixer" },
+};
+
+static const struct snd_soc_dapm_widget adau1761_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("Serial Port Clock", ADAU1761_CLK_ENABLE0,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Serial Input Routing Clock", ADAU1761_CLK_ENABLE0,
+ 1, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Serial Output Routing Clock", ADAU1761_CLK_ENABLE0,
+ 3, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("Decimator Resync Clock", ADAU1761_CLK_ENABLE0,
+ 4, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Interpolator Resync Clock", ADAU1761_CLK_ENABLE0,
+ 2, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("Slew Clock", ADAU1761_CLK_ENABLE0, 6, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY_S("Digital Clock 0", 1, ADAU1761_CLK_ENABLE1,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("Digital Clock 1", 1, ADAU1761_CLK_ENABLE1,
+ 1, 0, NULL, 0),
+};
+
+static const struct snd_soc_dapm_route adau1761_dapm_routes[] = {
+ { "Left Decimator", NULL, "Digital Clock 0", },
+ { "Right Decimator", NULL, "Digital Clock 0", },
+ { "Left DAC", NULL, "Digital Clock 0", },
+ { "Right DAC", NULL, "Digital Clock 0", },
+
+ { "AIFCLK", NULL, "Digital Clock 1" },
+
+ { "Playback", NULL, "Serial Port Clock" },
+ { "Capture", NULL, "Serial Port Clock" },
+ { "Playback", NULL, "Serial Input Routing Clock" },
+ { "Capture", NULL, "Serial Output Routing Clock" },
+
+ { "Left Decimator", NULL, "Decimator Resync Clock" },
+ { "Right Decimator", NULL, "Decimator Resync Clock" },
+ { "Left DAC", NULL, "Interpolator Resync Clock" },
+ { "Right DAC", NULL, "Interpolator Resync Clock" },
+
+ { "DSP", NULL, "Digital Clock 0" },
+
+ { "Slew Clock", NULL, "Digital Clock 0" },
+ { "Right Playback Mixer", NULL, "Slew Clock" },
+ { "Left Playback Mixer", NULL, "Slew Clock" },
+
+ { "Digital Clock 0", NULL, "SYSCLK" },
+ { "Digital Clock 1", NULL, "SYSCLK" },
+};
+
+static int adau1761_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
+ ADAU17X1_CLOCK_CONTROL_SYSCLK_EN,
+ ADAU17X1_CLOCK_CONTROL_SYSCLK_EN);
+ break;
+ case SND_SOC_BIAS_OFF:
+ regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
+ ADAU17X1_CLOCK_CONTROL_SYSCLK_EN, 0);
+ break;
+
+ }
+ codec->dapm.bias_level = level;
+ return 0;
+}
+
+static enum adau1761_output_mode adau1761_get_lineout_mode(
+ struct snd_soc_codec *codec)
+{
+ struct adau1761_platform_data *pdata = codec->dev->platform_data;
+
+ if (pdata)
+ return pdata->lineout_mode;
+
+ return ADAU1761_OUTPUT_MODE_LINE;
+}
+
+static int adau1761_setup_digmic_jackdetect(struct snd_soc_codec *codec)
+{
+ struct adau1761_platform_data *pdata = codec->dev->platform_data;
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ enum adau1761_digmic_jackdet_pin_mode mode;
+ unsigned int val = 0;
+ int ret;
+
+ if (pdata)
+ mode = pdata->digmic_jackdetect_pin_mode;
+ else
+ mode = ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE;
+
+ switch (mode) {
+ case ADAU1761_DIGMIC_JACKDET_PIN_MODE_JACKDETECT:
+ switch (pdata->jackdetect_debounce_time) {
+ case ADAU1761_JACKDETECT_DEBOUNCE_5MS:
+ case ADAU1761_JACKDETECT_DEBOUNCE_10MS:
+ case ADAU1761_JACKDETECT_DEBOUNCE_20MS:
+ case ADAU1761_JACKDETECT_DEBOUNCE_40MS:
+ val |= pdata->jackdetect_debounce_time << 6;
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (pdata->jackdetect_active_low)
+ val |= ADAU1761_DIGMIC_JACKDETECT_ACTIVE_LOW;
+
+ ret = snd_soc_add_codec_controls(codec,
+ adau1761_jack_detect_controls,
+ ARRAY_SIZE(adau1761_jack_detect_controls));
+ if (ret)
+ return ret;
+ case ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: /* fallthrough */
+ ret = snd_soc_dapm_add_routes(&codec->dapm,
+ adau1761_no_dmic_routes,
+ ARRAY_SIZE(adau1761_no_dmic_routes));
+ if (ret)
+ return ret;
+ break;
+ case ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC:
+ ret = snd_soc_dapm_new_controls(&codec->dapm,
+ adau1761_dmic_widgets,
+ ARRAY_SIZE(adau1761_dmic_widgets));
+ if (ret)
+ return ret;
+
+ ret = snd_soc_dapm_add_routes(&codec->dapm,
+ adau1761_dmic_routes,
+ ARRAY_SIZE(adau1761_dmic_routes));
+ if (ret)
+ return ret;
+
+ val |= ADAU1761_DIGMIC_JACKDETECT_DIGMIC;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_write(adau->regmap, ADAU1761_DIGMIC_JACKDETECT, val);
+
+ return 0;
+}
+
+static int adau1761_setup_headphone_mode(struct snd_soc_codec *codec)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ struct adau1761_platform_data *pdata = codec->dev->platform_data;
+ enum adau1761_output_mode mode;
+ int ret;
+
+ if (pdata)
+ mode = pdata->headphone_mode;
+ else
+ mode = ADAU1761_OUTPUT_MODE_HEADPHONE;
+
+ switch (mode) {
+ case ADAU1761_OUTPUT_MODE_LINE:
+ break;
+ case ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS:
+ regmap_update_bits(adau->regmap, ADAU1761_PLAY_MONO_OUTPUT_VOL,
+ ADAU1761_PLAY_MONO_OUTPUT_VOL_MODE_HP |
+ ADAU1761_PLAY_MONO_OUTPUT_VOL_UNMUTE,
+ ADAU1761_PLAY_MONO_OUTPUT_VOL_MODE_HP |
+ ADAU1761_PLAY_MONO_OUTPUT_VOL_UNMUTE);
+ /* fallthrough */
+ case ADAU1761_OUTPUT_MODE_HEADPHONE:
+ regmap_update_bits(adau->regmap, ADAU1761_PLAY_HP_RIGHT_VOL,
+ ADAU1761_PLAY_HP_RIGHT_VOL_MODE_HP,
+ ADAU1761_PLAY_HP_RIGHT_VOL_MODE_HP);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (mode == ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS) {
+ ret = snd_soc_dapm_new_controls(&codec->dapm,
+ adau1761_capless_dapm_widgets,
+ ARRAY_SIZE(adau1761_capless_dapm_widgets));
+ if (ret)
+ return ret;
+ ret = snd_soc_dapm_add_routes(&codec->dapm,
+ adau1761_capless_dapm_routes,
+ ARRAY_SIZE(adau1761_capless_dapm_routes));
+ } else {
+ ret = snd_soc_add_codec_controls(codec, adau1761_mono_controls,
+ ARRAY_SIZE(adau1761_mono_controls));
+ if (ret)
+ return ret;
+ ret = snd_soc_dapm_new_controls(&codec->dapm,
+ adau1761_mono_dapm_widgets,
+ ARRAY_SIZE(adau1761_mono_dapm_widgets));
+ if (ret)
+ return ret;
+ ret = snd_soc_dapm_add_routes(&codec->dapm,
+ adau1761_mono_dapm_routes,
+ ARRAY_SIZE(adau1761_mono_dapm_routes));
+ }
+
+ return ret;
+}
+
+static bool adau1761_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ADAU1761_DIGMIC_JACKDETECT:
+ case ADAU1761_REC_MIXER_LEFT0:
+ case ADAU1761_REC_MIXER_LEFT1:
+ case ADAU1761_REC_MIXER_RIGHT0:
+ case ADAU1761_REC_MIXER_RIGHT1:
+ case ADAU1761_LEFT_DIFF_INPUT_VOL:
+ case ADAU1761_RIGHT_DIFF_INPUT_VOL:
+ case ADAU1761_PLAY_LR_MIXER_LEFT:
+ case ADAU1761_PLAY_MIXER_LEFT0:
+ case ADAU1761_PLAY_MIXER_LEFT1:
+ case ADAU1761_PLAY_MIXER_RIGHT0:
+ case ADAU1761_PLAY_MIXER_RIGHT1:
+ case ADAU1761_PLAY_LR_MIXER_RIGHT:
+ case ADAU1761_PLAY_MIXER_MONO:
+ case ADAU1761_PLAY_HP_LEFT_VOL:
+ case ADAU1761_PLAY_HP_RIGHT_VOL:
+ case ADAU1761_PLAY_LINE_LEFT_VOL:
+ case ADAU1761_PLAY_LINE_RIGHT_VOL:
+ case ADAU1761_PLAY_MONO_OUTPUT_VOL:
+ case ADAU1761_POP_CLICK_SUPPRESS:
+ case ADAU1761_JACK_DETECT_PIN:
+ case ADAU1761_DEJITTER:
+ case ADAU1761_CLK_ENABLE0:
+ case ADAU1761_CLK_ENABLE1:
+ return true;
+ default:
+ break;
+ }
+
+ return adau17x1_readable_register(dev, reg);
+}
+
+static int adau1761_codec_probe(struct snd_soc_codec *codec)
+{
+ struct adau1761_platform_data *pdata = codec->dev->platform_data;
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ ret = adau17x1_add_widgets(codec);
+ if (ret < 0)
+ return ret;
+
+ if (pdata && pdata->input_differential) {
+ regmap_update_bits(adau->regmap, ADAU1761_LEFT_DIFF_INPUT_VOL,
+ ADAU1761_DIFF_INPUT_VOL_LDEN,
+ ADAU1761_DIFF_INPUT_VOL_LDEN);
+ regmap_update_bits(adau->regmap, ADAU1761_RIGHT_DIFF_INPUT_VOL,
+ ADAU1761_DIFF_INPUT_VOL_LDEN,
+ ADAU1761_DIFF_INPUT_VOL_LDEN);
+ ret = snd_soc_add_codec_controls(codec,
+ adau1761_differential_mode_controls,
+ ARRAY_SIZE(adau1761_differential_mode_controls));
+ if (ret)
+ return ret;
+ } else {
+ ret = snd_soc_add_codec_controls(codec,
+ adau1761_single_mode_controls,
+ ARRAY_SIZE(adau1761_single_mode_controls));
+ if (ret)
+ return ret;
+ }
+
+ switch (adau1761_get_lineout_mode(codec)) {
+ case ADAU1761_OUTPUT_MODE_LINE:
+ break;
+ case ADAU1761_OUTPUT_MODE_HEADPHONE:
+ regmap_update_bits(adau->regmap, ADAU1761_PLAY_LINE_LEFT_VOL,
+ ADAU1761_PLAY_LINE_LEFT_VOL_MODE_HP,
+ ADAU1761_PLAY_LINE_LEFT_VOL_MODE_HP);
+ regmap_update_bits(adau->regmap, ADAU1761_PLAY_LINE_RIGHT_VOL,
+ ADAU1761_PLAY_LINE_RIGHT_VOL_MODE_HP,
+ ADAU1761_PLAY_LINE_RIGHT_VOL_MODE_HP);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = adau1761_setup_headphone_mode(codec);
+ if (ret)
+ return ret;
+
+ ret = adau1761_setup_digmic_jackdetect(codec);
+ if (ret)
+ return ret;
+
+ if (adau->type == ADAU1761) {
+ ret = snd_soc_dapm_new_controls(&codec->dapm,
+ adau1761_dapm_widgets,
+ ARRAY_SIZE(adau1761_dapm_widgets));
+ if (ret)
+ return ret;
+
+ ret = snd_soc_dapm_add_routes(&codec->dapm,
+ adau1761_dapm_routes,
+ ARRAY_SIZE(adau1761_dapm_routes));
+ if (ret)
+ return ret;
+
+ ret = adau17x1_load_firmware(adau, codec->dev,
+ ADAU1761_FIRMWARE);
+ if (ret)
+ dev_warn(codec->dev, "Failed to firmware\n");
+ }
+
+ ret = adau17x1_add_routes(codec);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static const struct snd_soc_codec_driver adau1761_codec_driver = {
+ .probe = adau1761_codec_probe,
+ .suspend = adau17x1_suspend,
+ .resume = adau17x1_resume,
+ .set_bias_level = adau1761_set_bias_level,
+
+ .controls = adau1761_controls,
+ .num_controls = ARRAY_SIZE(adau1761_controls),
+ .dapm_widgets = adau1x61_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(adau1x61_dapm_widgets),
+ .dapm_routes = adau1x61_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(adau1x61_dapm_routes),
+};
+
+#define ADAU1761_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver adau1361_dai_driver = {
+ .name = "adau-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 4,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = ADAU1761_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 4,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = ADAU1761_FORMATS,
+ },
+ .ops = &adau17x1_dai_ops,
+};
+
+static struct snd_soc_dai_driver adau1761_dai_driver = {
+ .name = "adau-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = ADAU1761_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = ADAU1761_FORMATS,
+ },
+ .ops = &adau17x1_dai_ops,
+};
+
+int adau1761_probe(struct device *dev, struct regmap *regmap,
+ enum adau17x1_type type, void (*switch_mode)(struct device *dev))
+{
+ struct snd_soc_dai_driver *dai_drv;
+ int ret;
+
+ ret = adau17x1_probe(dev, regmap, type, switch_mode);
+ if (ret)
+ return ret;
+
+ if (type == ADAU1361)
+ dai_drv = &adau1361_dai_driver;
+ else
+ dai_drv = &adau1761_dai_driver;
+
+ return snd_soc_register_codec(dev, &adau1761_codec_driver, dai_drv, 1);
+}
+EXPORT_SYMBOL_GPL(adau1761_probe);
+
+const struct regmap_config adau1761_regmap_config = {
+ .val_bits = 8,
+ .reg_bits = 16,
+ .max_register = 0x40fa,
+ .reg_defaults = adau1761_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(adau1761_reg_defaults),
+ .readable_reg = adau1761_readable_register,
+ .volatile_reg = adau17x1_volatile_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(adau1761_regmap_config);
+
+MODULE_DESCRIPTION("ASoC ADAU1361/ADAU1461/ADAU1761/ADAU1961 CODEC driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1761.h b/sound/soc/codecs/adau1761.h
new file mode 100644
index 00000000000..a9e0d288301
--- /dev/null
+++ b/sound/soc/codecs/adau1761.h
@@ -0,0 +1,23 @@
+/*
+ * ADAU1361/ADAU1461/ADAU1761/ADAU1961 driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef __SOUND_SOC_CODECS_ADAU1761_H__
+#define __SOUND_SOC_CODECS_ADAU1761_H__
+
+#include <linux/regmap.h>
+#include "adau17x1.h"
+
+struct device;
+
+int adau1761_probe(struct device *dev, struct regmap *regmap,
+ enum adau17x1_type type, void (*switch_mode)(struct device *dev));
+
+extern const struct regmap_config adau1761_regmap_config;
+
+#endif
diff --git a/sound/soc/codecs/adau1781-i2c.c b/sound/soc/codecs/adau1781-i2c.c
new file mode 100644
index 00000000000..2ce4362ccec
--- /dev/null
+++ b/sound/soc/codecs/adau1781-i2c.c
@@ -0,0 +1,58 @@
+/*
+ * Driver for ADAU1381/ADAU1781 CODEC
+ *
+ * Copyright 2014 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/i2c.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+
+#include "adau1781.h"
+
+static int adau1781_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct regmap_config config;
+
+ config = adau1781_regmap_config;
+ config.val_bits = 8;
+ config.reg_bits = 16;
+
+ return adau1781_probe(&client->dev,
+ devm_regmap_init_i2c(client, &config),
+ id->driver_data, NULL);
+}
+
+static int adau1781_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static const struct i2c_device_id adau1781_i2c_ids[] = {
+ { "adau1381", ADAU1381 },
+ { "adau1781", ADAU1781 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adau1781_i2c_ids);
+
+static struct i2c_driver adau1781_i2c_driver = {
+ .driver = {
+ .name = "adau1781",
+ .owner = THIS_MODULE,
+ },
+ .probe = adau1781_i2c_probe,
+ .remove = adau1781_i2c_remove,
+ .id_table = adau1781_i2c_ids,
+};
+module_i2c_driver(adau1781_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC ADAU1381/ADAU1781 CODEC I2C driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1781-spi.c b/sound/soc/codecs/adau1781-spi.c
new file mode 100644
index 00000000000..194686716bb
--- /dev/null
+++ b/sound/soc/codecs/adau1781-spi.c
@@ -0,0 +1,75 @@
+/*
+ * Driver for ADAU1381/ADAU1781 CODEC
+ *
+ * Copyright 2014 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <sound/soc.h>
+
+#include "adau1781.h"
+
+static void adau1781_spi_switch_mode(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+
+ /*
+ * To get the device into SPI mode CLATCH has to be pulled low three
+ * times. Do this by issuing three dummy reads.
+ */
+ spi_w8r8(spi, 0x00);
+ spi_w8r8(spi, 0x00);
+ spi_w8r8(spi, 0x00);
+}
+
+static int adau1781_spi_probe(struct spi_device *spi)
+{
+ const struct spi_device_id *id = spi_get_device_id(spi);
+ struct regmap_config config;
+
+ if (!id)
+ return -EINVAL;
+
+ config = adau1781_regmap_config;
+ config.val_bits = 8;
+ config.reg_bits = 24;
+ config.read_flag_mask = 0x1;
+
+ return adau1781_probe(&spi->dev,
+ devm_regmap_init_spi(spi, &config),
+ id->driver_data, adau1781_spi_switch_mode);
+}
+
+static int adau1781_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ return 0;
+}
+
+static const struct spi_device_id adau1781_spi_id[] = {
+ { "adau1381", ADAU1381 },
+ { "adau1781", ADAU1781 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, adau1781_spi_id);
+
+static struct spi_driver adau1781_spi_driver = {
+ .driver = {
+ .name = "adau1781",
+ .owner = THIS_MODULE,
+ },
+ .probe = adau1781_spi_probe,
+ .remove = adau1781_spi_remove,
+ .id_table = adau1781_spi_id,
+};
+module_spi_driver(adau1781_spi_driver);
+
+MODULE_DESCRIPTION("ASoC ADAU1381/ADAU1781 CODEC SPI driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c
new file mode 100644
index 00000000000..045a6141384
--- /dev/null
+++ b/sound/soc/codecs/adau1781.c
@@ -0,0 +1,511 @@
+/*
+ * Driver for ADAU1781/ADAU1781 codec
+ *
+ * Copyright 2011-2013 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <linux/platform_data/adau17x1.h>
+
+#include "adau17x1.h"
+#include "adau1781.h"
+
+#define ADAU1781_DMIC_BEEP_CTRL 0x4008
+#define ADAU1781_LEFT_PGA 0x400e
+#define ADAU1781_RIGHT_PGA 0x400f
+#define ADAU1781_LEFT_PLAYBACK_MIXER 0x401c
+#define ADAU1781_RIGHT_PLAYBACK_MIXER 0x401e
+#define ADAU1781_MONO_PLAYBACK_MIXER 0x401f
+#define ADAU1781_LEFT_LINEOUT 0x4025
+#define ADAU1781_RIGHT_LINEOUT 0x4026
+#define ADAU1781_SPEAKER 0x4027
+#define ADAU1781_BEEP_ZC 0x4028
+#define ADAU1781_DEJITTER 0x4032
+#define ADAU1781_DIG_PWDN0 0x4080
+#define ADAU1781_DIG_PWDN1 0x4081
+
+#define ADAU1781_INPUT_DIFFERNTIAL BIT(3)
+
+#define ADAU1381_FIRMWARE "adau1381.bin"
+#define ADAU1781_FIRMWARE "adau1781.bin"
+
+static const struct reg_default adau1781_reg_defaults[] = {
+ { ADAU1781_DMIC_BEEP_CTRL, 0x00 },
+ { ADAU1781_LEFT_PGA, 0xc7 },
+ { ADAU1781_RIGHT_PGA, 0xc7 },
+ { ADAU1781_LEFT_PLAYBACK_MIXER, 0x00 },
+ { ADAU1781_RIGHT_PLAYBACK_MIXER, 0x00 },
+ { ADAU1781_MONO_PLAYBACK_MIXER, 0x00 },
+ { ADAU1781_LEFT_LINEOUT, 0x00 },
+ { ADAU1781_RIGHT_LINEOUT, 0x00 },
+ { ADAU1781_SPEAKER, 0x00 },
+ { ADAU1781_BEEP_ZC, 0x19 },
+ { ADAU1781_DEJITTER, 0x60 },
+ { ADAU1781_DIG_PWDN1, 0x0c },
+ { ADAU1781_DIG_PWDN1, 0x00 },
+ { ADAU17X1_CLOCK_CONTROL, 0x00 },
+ { ADAU17X1_PLL_CONTROL, 0x00 },
+ { ADAU17X1_REC_POWER_MGMT, 0x00 },
+ { ADAU17X1_MICBIAS, 0x04 },
+ { ADAU17X1_SERIAL_PORT0, 0x00 },
+ { ADAU17X1_SERIAL_PORT1, 0x00 },
+ { ADAU17X1_CONVERTER0, 0x00 },
+ { ADAU17X1_CONVERTER1, 0x00 },
+ { ADAU17X1_LEFT_INPUT_DIGITAL_VOL, 0x00 },
+ { ADAU17X1_RIGHT_INPUT_DIGITAL_VOL, 0x00 },
+ { ADAU17X1_ADC_CONTROL, 0x00 },
+ { ADAU17X1_PLAY_POWER_MGMT, 0x00 },
+ { ADAU17X1_DAC_CONTROL0, 0x00 },
+ { ADAU17X1_DAC_CONTROL1, 0x00 },
+ { ADAU17X1_DAC_CONTROL2, 0x00 },
+ { ADAU17X1_SERIAL_PORT_PAD, 0x00 },
+ { ADAU17X1_CONTROL_PORT_PAD0, 0x00 },
+ { ADAU17X1_CONTROL_PORT_PAD1, 0x00 },
+ { ADAU17X1_DSP_SAMPLING_RATE, 0x01 },
+ { ADAU17X1_SERIAL_INPUT_ROUTE, 0x00 },
+ { ADAU17X1_SERIAL_OUTPUT_ROUTE, 0x00 },
+ { ADAU17X1_DSP_ENABLE, 0x00 },
+ { ADAU17X1_DSP_RUN, 0x00 },
+ { ADAU17X1_SERIAL_SAMPLING_RATE, 0x00 },
+};
+
+static const DECLARE_TLV_DB_SCALE(adau1781_speaker_tlv, 0, 200, 0);
+
+static const DECLARE_TLV_DB_RANGE(adau1781_pga_tlv,
+ 0, 1, TLV_DB_SCALE_ITEM(0, 600, 0),
+ 2, 3, TLV_DB_SCALE_ITEM(1000, 400, 0),
+ 4, 4, TLV_DB_SCALE_ITEM(1700, 0, 0),
+ 5, 7, TLV_DB_SCALE_ITEM(2000, 600, 0)
+);
+
+static const DECLARE_TLV_DB_RANGE(adau1781_beep_tlv,
+ 0, 1, TLV_DB_SCALE_ITEM(0, 600, 0),
+ 2, 3, TLV_DB_SCALE_ITEM(1000, 400, 0),
+ 4, 4, TLV_DB_SCALE_ITEM(-2300, 0, 0),
+ 5, 7, TLV_DB_SCALE_ITEM(2000, 600, 0)
+);
+
+static const DECLARE_TLV_DB_SCALE(adau1781_sidetone_tlv, -1800, 300, 1);
+
+static const char * const adau1781_speaker_bias_select_text[] = {
+ "Normal operation", "Power saving", "Enhanced performance",
+};
+
+static const char * const adau1781_bias_select_text[] = {
+ "Normal operation", "Extreme power saving", "Power saving",
+ "Enhanced performance",
+};
+
+static SOC_ENUM_SINGLE_DECL(adau1781_adc_bias_enum,
+ ADAU17X1_REC_POWER_MGMT, 3, adau1781_bias_select_text);
+static SOC_ENUM_SINGLE_DECL(adau1781_speaker_bias_enum,
+ ADAU17X1_PLAY_POWER_MGMT, 6, adau1781_speaker_bias_select_text);
+static SOC_ENUM_SINGLE_DECL(adau1781_dac_bias_enum,
+ ADAU17X1_PLAY_POWER_MGMT, 4, adau1781_bias_select_text);
+static SOC_ENUM_SINGLE_DECL(adau1781_playback_bias_enum,
+ ADAU17X1_PLAY_POWER_MGMT, 2, adau1781_bias_select_text);
+static SOC_ENUM_SINGLE_DECL(adau1781_capture_bias_enum,
+ ADAU17X1_REC_POWER_MGMT, 1, adau1781_bias_select_text);
+
+static const struct snd_kcontrol_new adau1781_controls[] = {
+ SOC_SINGLE_TLV("Beep Capture Volume", ADAU1781_DMIC_BEEP_CTRL, 0, 7, 0,
+ adau1781_beep_tlv),
+ SOC_DOUBLE_R_TLV("PGA Capture Volume", ADAU1781_LEFT_PGA,
+ ADAU1781_RIGHT_PGA, 5, 7, 0, adau1781_pga_tlv),
+ SOC_DOUBLE_R("PGA Capture Switch", ADAU1781_LEFT_PGA,
+ ADAU1781_RIGHT_PGA, 1, 1, 0),
+
+ SOC_DOUBLE_R("Lineout Playback Switch", ADAU1781_LEFT_LINEOUT,
+ ADAU1781_RIGHT_LINEOUT, 1, 1, 0),
+ SOC_SINGLE("Beep ZC Switch", ADAU1781_BEEP_ZC, 0, 1, 0),
+
+ SOC_SINGLE("Mono Playback Switch", ADAU1781_MONO_PLAYBACK_MIXER,
+ 0, 1, 0),
+ SOC_SINGLE_TLV("Mono Playback Volume", ADAU1781_SPEAKER, 6, 3, 0,
+ adau1781_speaker_tlv),
+
+ SOC_ENUM("ADC Bias", adau1781_adc_bias_enum),
+ SOC_ENUM("DAC Bias", adau1781_dac_bias_enum),
+ SOC_ENUM("Capture Bias", adau1781_capture_bias_enum),
+ SOC_ENUM("Playback Bias", adau1781_playback_bias_enum),
+ SOC_ENUM("Speaker Bias", adau1781_speaker_bias_enum),
+};
+
+static const struct snd_kcontrol_new adau1781_beep_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Beep Capture Switch", ADAU1781_DMIC_BEEP_CTRL,
+ 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new adau1781_left_mixer_controls[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch",
+ ADAU1781_LEFT_PLAYBACK_MIXER, 5, 1, 0),
+ SOC_DAPM_SINGLE_TLV("Beep Playback Volume",
+ ADAU1781_LEFT_PLAYBACK_MIXER, 1, 8, 0, adau1781_sidetone_tlv),
+};
+
+static const struct snd_kcontrol_new adau1781_right_mixer_controls[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch",
+ ADAU1781_RIGHT_PLAYBACK_MIXER, 6, 1, 0),
+ SOC_DAPM_SINGLE_TLV("Beep Playback Volume",
+ ADAU1781_LEFT_PLAYBACK_MIXER, 1, 8, 0, adau1781_sidetone_tlv),
+};
+
+static const struct snd_kcontrol_new adau1781_mono_mixer_controls[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("Left Switch",
+ ADAU1781_MONO_PLAYBACK_MIXER, 7, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("Right Switch",
+ ADAU1781_MONO_PLAYBACK_MIXER, 6, 1, 0),
+ SOC_DAPM_SINGLE_TLV("Beep Playback Volume",
+ ADAU1781_MONO_PLAYBACK_MIXER, 2, 8, 0, adau1781_sidetone_tlv),
+};
+
+static int adau1781_dejitter_fixup(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+
+ /* After any power changes have been made the dejitter circuit
+ * has to be reinitialized. */
+ regmap_write(adau->regmap, ADAU1781_DEJITTER, 0);
+ if (!adau->master)
+ regmap_write(adau->regmap, ADAU1781_DEJITTER, 5);
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget adau1781_dapm_widgets[] = {
+ SND_SOC_DAPM_PGA("Left PGA", ADAU1781_LEFT_PGA, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Right PGA", ADAU1781_RIGHT_PGA, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_OUT_DRV("Speaker", ADAU1781_SPEAKER, 0, 0, NULL, 0),
+
+ SOC_MIXER_NAMED_CTL_ARRAY("Beep Mixer", ADAU17X1_MICBIAS, 4, 0,
+ adau1781_beep_mixer_controls),
+
+ SOC_MIXER_ARRAY("Left Lineout Mixer", SND_SOC_NOPM, 0, 0,
+ adau1781_left_mixer_controls),
+ SOC_MIXER_ARRAY("Right Lineout Mixer", SND_SOC_NOPM, 0, 0,
+ adau1781_right_mixer_controls),
+ SOC_MIXER_ARRAY("Mono Mixer", SND_SOC_NOPM, 0, 0,
+ adau1781_mono_mixer_controls),
+
+ SND_SOC_DAPM_SUPPLY("Serial Input Routing", ADAU1781_DIG_PWDN0,
+ 2, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Serial Output Routing", ADAU1781_DIG_PWDN0,
+ 3, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Clock Domain Transfer", ADAU1781_DIG_PWDN0,
+ 5, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Serial Ports", ADAU1781_DIG_PWDN0, 4, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("ADC Engine", ADAU1781_DIG_PWDN0, 7, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DAC Engine", ADAU1781_DIG_PWDN1, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Digital Mic", ADAU1781_DIG_PWDN1, 1, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("Sound Engine", ADAU1781_DIG_PWDN0, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, ADAU1781_DIG_PWDN0, 1, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("Zero Crossing Detector", ADAU1781_DIG_PWDN1, 2, 0,
+ NULL, 0),
+
+ SND_SOC_DAPM_POST("Dejitter fixup", adau1781_dejitter_fixup),
+
+ SND_SOC_DAPM_INPUT("BEEP"),
+
+ SND_SOC_DAPM_OUTPUT("AOUTL"),
+ SND_SOC_DAPM_OUTPUT("AOUTR"),
+ SND_SOC_DAPM_OUTPUT("SP"),
+ SND_SOC_DAPM_INPUT("LMIC"),
+ SND_SOC_DAPM_INPUT("RMIC"),
+};
+
+static const struct snd_soc_dapm_route adau1781_dapm_routes[] = {
+ { "Left Lineout Mixer", NULL, "Left Playback Enable" },
+ { "Right Lineout Mixer", NULL, "Right Playback Enable" },
+
+ { "Left Lineout Mixer", "Beep Playback Volume", "Beep Mixer" },
+ { "Left Lineout Mixer", "Switch", "Left DAC" },
+
+ { "Right Lineout Mixer", "Beep Playback Volume", "Beep Mixer" },
+ { "Right Lineout Mixer", "Switch", "Right DAC" },
+
+ { "Mono Mixer", "Beep Playback Volume", "Beep Mixer" },
+ { "Mono Mixer", "Right Switch", "Right DAC" },
+ { "Mono Mixer", "Left Switch", "Left DAC" },
+ { "Speaker", NULL, "Mono Mixer" },
+
+ { "Mono Mixer", NULL, "SYSCLK" },
+ { "Left Lineout Mixer", NULL, "SYSCLK" },
+ { "Left Lineout Mixer", NULL, "SYSCLK" },
+
+ { "Beep Mixer", "Beep Capture Switch", "BEEP" },
+ { "Beep Mixer", NULL, "Zero Crossing Detector" },
+
+ { "Left DAC", NULL, "DAC Engine" },
+ { "Right DAC", NULL, "DAC Engine" },
+
+ { "Sound Engine", NULL, "SYSCLK" },
+ { "DSP", NULL, "Sound Engine" },
+
+ { "Left Decimator", NULL, "ADC Engine" },
+ { "Right Decimator", NULL, "ADC Engine" },
+
+ { "AIFCLK", NULL, "SYSCLK" },
+
+ { "Playback", NULL, "Serial Input Routing" },
+ { "Playback", NULL, "Serial Ports" },
+ { "Playback", NULL, "Clock Domain Transfer" },
+ { "Capture", NULL, "Serial Output Routing" },
+ { "Capture", NULL, "Serial Ports" },
+ { "Capture", NULL, "Clock Domain Transfer" },
+
+ { "AOUTL", NULL, "Left Lineout Mixer" },
+ { "AOUTR", NULL, "Right Lineout Mixer" },
+ { "SP", NULL, "Speaker" },
+};
+
+static const struct snd_soc_dapm_route adau1781_adc_dapm_routes[] = {
+ { "Left PGA", NULL, "LMIC" },
+ { "Right PGA", NULL, "RMIC" },
+
+ { "Left Decimator", NULL, "Left PGA" },
+ { "Right Decimator", NULL, "Right PGA" },
+};
+
+static const char * const adau1781_dmic_select_text[] = {
+ "DMIC1", "DMIC2",
+};
+
+static SOC_ENUM_SINGLE_VIRT_DECL(adau1781_dmic_select_enum,
+ adau1781_dmic_select_text);
+
+static const struct snd_kcontrol_new adau1781_dmic_mux =
+ SOC_DAPM_ENUM("DMIC Select", adau1781_dmic_select_enum);
+
+static const struct snd_soc_dapm_widget adau1781_dmic_dapm_widgets[] = {
+ SND_SOC_DAPM_MUX("DMIC Select", SND_SOC_NOPM, 0, 0, &adau1781_dmic_mux),
+
+ SND_SOC_DAPM_ADC("DMIC1", NULL, ADAU1781_DMIC_BEEP_CTRL, 4, 0),
+ SND_SOC_DAPM_ADC("DMIC2", NULL, ADAU1781_DMIC_BEEP_CTRL, 5, 0),
+};
+
+static const struct snd_soc_dapm_route adau1781_dmic_dapm_routes[] = {
+ { "DMIC1", NULL, "LMIC" },
+ { "DMIC2", NULL, "RMIC" },
+
+ { "DMIC1", NULL, "Digital Mic" },
+ { "DMIC2", NULL, "Digital Mic" },
+
+ { "DMIC Select", "DMIC1", "DMIC1" },
+ { "DMIC Select", "DMIC2", "DMIC2" },
+
+ { "Left Decimator", NULL, "DMIC Select" },
+ { "Right Decimator", NULL, "DMIC Select" },
+};
+
+static int adau1781_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
+ ADAU17X1_CLOCK_CONTROL_SYSCLK_EN,
+ ADAU17X1_CLOCK_CONTROL_SYSCLK_EN);
+
+ /* Precharge */
+ regmap_update_bits(adau->regmap, ADAU1781_DIG_PWDN1, 0x8, 0x8);
+ break;
+ case SND_SOC_BIAS_OFF:
+ regmap_update_bits(adau->regmap, ADAU1781_DIG_PWDN1, 0xc, 0x0);
+ regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
+ ADAU17X1_CLOCK_CONTROL_SYSCLK_EN, 0);
+ break;
+ }
+
+ codec->dapm.bias_level = level;
+ return 0;
+}
+
+static bool adau1781_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ADAU1781_DMIC_BEEP_CTRL:
+ case ADAU1781_LEFT_PGA:
+ case ADAU1781_RIGHT_PGA:
+ case ADAU1781_LEFT_PLAYBACK_MIXER:
+ case ADAU1781_RIGHT_PLAYBACK_MIXER:
+ case ADAU1781_MONO_PLAYBACK_MIXER:
+ case ADAU1781_LEFT_LINEOUT:
+ case ADAU1781_RIGHT_LINEOUT:
+ case ADAU1781_SPEAKER:
+ case ADAU1781_BEEP_ZC:
+ case ADAU1781_DEJITTER:
+ case ADAU1781_DIG_PWDN0:
+ case ADAU1781_DIG_PWDN1:
+ return true;
+ default:
+ break;
+ }
+
+ return adau17x1_readable_register(dev, reg);
+}
+
+static int adau1781_set_input_mode(struct adau *adau, unsigned int reg,
+ bool differential)
+{
+ unsigned int val;
+
+ if (differential)
+ val = ADAU1781_INPUT_DIFFERNTIAL;
+ else
+ val = 0;
+
+ return regmap_update_bits(adau->regmap, reg,
+ ADAU1781_INPUT_DIFFERNTIAL, val);
+}
+
+static int adau1781_codec_probe(struct snd_soc_codec *codec)
+{
+ struct adau1781_platform_data *pdata = dev_get_platdata(codec->dev);
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ const char *firmware;
+ int ret;
+
+ ret = adau17x1_add_widgets(codec);
+ if (ret)
+ return ret;
+
+ if (pdata) {
+ ret = adau1781_set_input_mode(adau, ADAU1781_LEFT_PGA,
+ pdata->left_input_differential);
+ if (ret)
+ return ret;
+ ret = adau1781_set_input_mode(adau, ADAU1781_RIGHT_PGA,
+ pdata->right_input_differential);
+ if (ret)
+ return ret;
+ }
+
+ if (pdata && pdata->use_dmic) {
+ ret = snd_soc_dapm_new_controls(&codec->dapm,
+ adau1781_dmic_dapm_widgets,
+ ARRAY_SIZE(adau1781_dmic_dapm_widgets));
+ if (ret)
+ return ret;
+ ret = snd_soc_dapm_add_routes(&codec->dapm,
+ adau1781_dmic_dapm_routes,
+ ARRAY_SIZE(adau1781_dmic_dapm_routes));
+ if (ret)
+ return ret;
+ } else {
+ ret = snd_soc_dapm_add_routes(&codec->dapm,
+ adau1781_adc_dapm_routes,
+ ARRAY_SIZE(adau1781_adc_dapm_routes));
+ if (ret)
+ return ret;
+ }
+
+ switch (adau->type) {
+ case ADAU1381:
+ firmware = ADAU1381_FIRMWARE;
+ break;
+ case ADAU1781:
+ firmware = ADAU1781_FIRMWARE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = adau17x1_add_routes(codec);
+ if (ret < 0)
+ return ret;
+
+ ret = adau17x1_load_firmware(adau, codec->dev, firmware);
+ if (ret)
+ dev_warn(codec->dev, "Failed to load firmware\n");
+
+ return 0;
+}
+
+static const struct snd_soc_codec_driver adau1781_codec_driver = {
+ .probe = adau1781_codec_probe,
+ .suspend = adau17x1_suspend,
+ .resume = adau17x1_resume,
+ .set_bias_level = adau1781_set_bias_level,
+
+ .controls = adau1781_controls,
+ .num_controls = ARRAY_SIZE(adau1781_controls),
+ .dapm_widgets = adau1781_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(adau1781_dapm_widgets),
+ .dapm_routes = adau1781_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(adau1781_dapm_routes),
+};
+
+#define ADAU1781_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver adau1781_dai_driver = {
+ .name = "adau-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = ADAU1781_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = ADAU1781_FORMATS,
+ },
+ .ops = &adau17x1_dai_ops,
+};
+
+const struct regmap_config adau1781_regmap_config = {
+ .val_bits = 8,
+ .reg_bits = 16,
+ .max_register = 0x40f8,
+ .reg_defaults = adau1781_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(adau1781_reg_defaults),
+ .readable_reg = adau1781_readable_register,
+ .volatile_reg = adau17x1_volatile_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(adau1781_regmap_config);
+
+int adau1781_probe(struct device *dev, struct regmap *regmap,
+ enum adau17x1_type type, void (*switch_mode)(struct device *dev))
+{
+ int ret;
+
+ ret = adau17x1_probe(dev, regmap, type, switch_mode);
+ if (ret)
+ return ret;
+
+ return snd_soc_register_codec(dev, &adau1781_codec_driver,
+ &adau1781_dai_driver, 1);
+}
+EXPORT_SYMBOL_GPL(adau1781_probe);
+
+MODULE_DESCRIPTION("ASoC ADAU1381/ADAU1781 driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1781.h b/sound/soc/codecs/adau1781.h
new file mode 100644
index 00000000000..2b96e0a9ff2
--- /dev/null
+++ b/sound/soc/codecs/adau1781.h
@@ -0,0 +1,23 @@
+/*
+ * ADAU1381/ADAU1781 driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef __SOUND_SOC_CODECS_ADAU1781_H__
+#define __SOUND_SOC_CODECS_ADAU1781_H__
+
+#include <linux/regmap.h>
+#include "adau17x1.h"
+
+struct device;
+
+int adau1781_probe(struct device *dev, struct regmap *regmap,
+ enum adau17x1_type type, void (*switch_mode)(struct device *dev));
+
+extern const struct regmap_config adau1781_regmap_config;
+
+#endif
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c
new file mode 100644
index 00000000000..2961fae9670
--- /dev/null
+++ b/sound/soc/codecs/adau17x1.c
@@ -0,0 +1,866 @@
+/*
+ * Common code for ADAU1X61 and ADAU1X81 codecs
+ *
+ * Copyright 2011-2014 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <linux/gcd.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+
+#include "sigmadsp.h"
+#include "adau17x1.h"
+
+static const char * const adau17x1_capture_mixer_boost_text[] = {
+ "Normal operation", "Boost Level 1", "Boost Level 2", "Boost Level 3",
+};
+
+static SOC_ENUM_SINGLE_DECL(adau17x1_capture_boost_enum,
+ ADAU17X1_REC_POWER_MGMT, 5, adau17x1_capture_mixer_boost_text);
+
+static const char * const adau17x1_mic_bias_mode_text[] = {
+ "Normal operation", "High performance",
+};
+
+static SOC_ENUM_SINGLE_DECL(adau17x1_mic_bias_mode_enum,
+ ADAU17X1_MICBIAS, 3, adau17x1_mic_bias_mode_text);
+
+static const DECLARE_TLV_DB_MINMAX(adau17x1_digital_tlv, -9563, 0);
+
+static const struct snd_kcontrol_new adau17x1_controls[] = {
+ SOC_DOUBLE_R_TLV("Digital Capture Volume",
+ ADAU17X1_LEFT_INPUT_DIGITAL_VOL,
+ ADAU17X1_RIGHT_INPUT_DIGITAL_VOL,
+ 0, 0xff, 1, adau17x1_digital_tlv),
+ SOC_DOUBLE_R_TLV("Digital Playback Volume", ADAU17X1_DAC_CONTROL1,
+ ADAU17X1_DAC_CONTROL2, 0, 0xff, 1, adau17x1_digital_tlv),
+
+ SOC_SINGLE("ADC High Pass Filter Switch", ADAU17X1_ADC_CONTROL,
+ 5, 1, 0),
+ SOC_SINGLE("Playback De-emphasis Switch", ADAU17X1_DAC_CONTROL0,
+ 2, 1, 0),
+
+ SOC_ENUM("Capture Boost", adau17x1_capture_boost_enum),
+
+ SOC_ENUM("Mic Bias Mode", adau17x1_mic_bias_mode_enum),
+};
+
+static int adau17x1_pll_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(w->codec);
+ int ret;
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ adau->pll_regs[5] = 1;
+ } else {
+ adau->pll_regs[5] = 0;
+ /* Bypass the PLL when disabled, otherwise registers will become
+ * inaccessible. */
+ regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
+ ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL, 0);
+ }
+
+ /* The PLL register is 6 bytes long and can only be written at once. */
+ ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL,
+ adau->pll_regs, ARRAY_SIZE(adau->pll_regs));
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ mdelay(5);
+ regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
+ ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL,
+ ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL);
+ }
+
+ return 0;
+}
+
+static const char * const adau17x1_mono_stereo_text[] = {
+ "Stereo",
+ "Mono Left Channel (L+R)",
+ "Mono Right Channel (L+R)",
+ "Mono (L+R)",
+};
+
+static SOC_ENUM_SINGLE_DECL(adau17x1_dac_mode_enum,
+ ADAU17X1_DAC_CONTROL0, 6, adau17x1_mono_stereo_text);
+
+static const struct snd_kcontrol_new adau17x1_dac_mode_mux =
+ SOC_DAPM_ENUM("DAC Mono-Stereo-Mode", adau17x1_dac_mode_enum);
+
+static const struct snd_soc_dapm_widget adau17x1_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY_S("PLL", 3, SND_SOC_NOPM, 0, 0, adau17x1_pll_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY("AIFCLK", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("MICBIAS", ADAU17X1_MICBIAS, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("Left Playback Enable", ADAU17X1_PLAY_POWER_MGMT,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Right Playback Enable", ADAU17X1_PLAY_POWER_MGMT,
+ 1, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("Left DAC Mode Mux", SND_SOC_NOPM, 0, 0,
+ &adau17x1_dac_mode_mux),
+ SND_SOC_DAPM_MUX("Right DAC Mode Mux", SND_SOC_NOPM, 0, 0,
+ &adau17x1_dac_mode_mux),
+
+ SND_SOC_DAPM_ADC("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0),
+ SND_SOC_DAPM_ADC("Right Decimator", NULL, ADAU17X1_ADC_CONTROL, 1, 0),
+ SND_SOC_DAPM_DAC("Left DAC", NULL, ADAU17X1_DAC_CONTROL0, 0, 0),
+ SND_SOC_DAPM_DAC("Right DAC", NULL, ADAU17X1_DAC_CONTROL0, 1, 0),
+};
+
+static const struct snd_soc_dapm_route adau17x1_dapm_routes[] = {
+ { "Left Decimator", NULL, "SYSCLK" },
+ { "Right Decimator", NULL, "SYSCLK" },
+ { "Left DAC", NULL, "SYSCLK" },
+ { "Right DAC", NULL, "SYSCLK" },
+ { "Capture", NULL, "SYSCLK" },
+ { "Playback", NULL, "SYSCLK" },
+
+ { "Left DAC", NULL, "Left DAC Mode Mux" },
+ { "Right DAC", NULL, "Right DAC Mode Mux" },
+
+ { "Capture", NULL, "AIFCLK" },
+ { "Playback", NULL, "AIFCLK" },
+};
+
+static const struct snd_soc_dapm_route adau17x1_dapm_pll_route = {
+ "SYSCLK", NULL, "PLL",
+};
+
+/*
+ * The MUX register for the Capture and Playback MUXs selects either DSP as
+ * source/destination or one of the TDM slots. The TDM slot is selected via
+ * snd_soc_dai_set_tdm_slot(), so we only expose whether to go to the DSP or
+ * directly to the DAI interface with this control.
+ */
+static int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ struct snd_soc_dapm_update update;
+ unsigned int stream = e->shift_l;
+ unsigned int val, change;
+ int reg;
+
+ if (ucontrol->value.enumerated.item[0] >= e->items)
+ return -EINVAL;
+
+ switch (ucontrol->value.enumerated.item[0]) {
+ case 0:
+ val = 0;
+ adau->dsp_bypass[stream] = false;
+ break;
+ default:
+ val = (adau->tdm_slot[stream] * 2) + 1;
+ adau->dsp_bypass[stream] = true;
+ break;
+ }
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ reg = ADAU17X1_SERIAL_INPUT_ROUTE;
+ else
+ reg = ADAU17X1_SERIAL_OUTPUT_ROUTE;
+
+ change = snd_soc_test_bits(codec, reg, 0xff, val);
+ if (change) {
+ update.kcontrol = kcontrol;
+ update.mask = 0xff;
+ update.reg = reg;
+ update.val = val;
+
+ snd_soc_dapm_mux_update_power(&codec->dapm, kcontrol,
+ ucontrol->value.enumerated.item[0], e, &update);
+ }
+
+ return change;
+}
+
+static int adau17x1_dsp_mux_enum_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int stream = e->shift_l;
+ unsigned int reg, val;
+ int ret;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ reg = ADAU17X1_SERIAL_INPUT_ROUTE;
+ else
+ reg = ADAU17X1_SERIAL_OUTPUT_ROUTE;
+
+ ret = regmap_read(adau->regmap, reg, &val);
+ if (ret)
+ return ret;
+
+ if (val != 0)
+ val = 1;
+ ucontrol->value.enumerated.item[0] = val;
+
+ return 0;
+}
+
+#define DECLARE_ADAU17X1_DSP_MUX_CTRL(_name, _label, _stream, _text) \
+ const struct snd_kcontrol_new _name = \
+ SOC_DAPM_ENUM_EXT(_label, (const struct soc_enum)\
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, _stream, \
+ ARRAY_SIZE(_text), _text), \
+ adau17x1_dsp_mux_enum_get, adau17x1_dsp_mux_enum_put)
+
+static const char * const adau17x1_dac_mux_text[] = {
+ "DSP",
+ "AIFIN",
+};
+
+static const char * const adau17x1_capture_mux_text[] = {
+ "DSP",
+ "Decimator",
+};
+
+static DECLARE_ADAU17X1_DSP_MUX_CTRL(adau17x1_dac_mux, "DAC Playback Mux",
+ SNDRV_PCM_STREAM_PLAYBACK, adau17x1_dac_mux_text);
+
+static DECLARE_ADAU17X1_DSP_MUX_CTRL(adau17x1_capture_mux, "Capture Mux",
+ SNDRV_PCM_STREAM_CAPTURE, adau17x1_capture_mux_text);
+
+static const struct snd_soc_dapm_widget adau17x1_dsp_dapm_widgets[] = {
+ SND_SOC_DAPM_PGA("DSP", ADAU17X1_DSP_RUN, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SIGGEN("DSP Siggen"),
+
+ SND_SOC_DAPM_MUX("DAC Playback Mux", SND_SOC_NOPM, 0, 0,
+ &adau17x1_dac_mux),
+ SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0,
+ &adau17x1_capture_mux),
+};
+
+static const struct snd_soc_dapm_route adau17x1_dsp_dapm_routes[] = {
+ { "DAC Playback Mux", "DSP", "DSP" },
+ { "DAC Playback Mux", "AIFIN", "Playback" },
+
+ { "Left DAC Mode Mux", "Stereo", "DAC Playback Mux" },
+ { "Left DAC Mode Mux", "Mono (L+R)", "DAC Playback Mux" },
+ { "Left DAC Mode Mux", "Mono Left Channel (L+R)", "DAC Playback Mux" },
+ { "Right DAC Mode Mux", "Stereo", "DAC Playback Mux" },
+ { "Right DAC Mode Mux", "Mono (L+R)", "DAC Playback Mux" },
+ { "Right DAC Mode Mux", "Mono Right Channel (L+R)", "DAC Playback Mux" },
+
+ { "Capture Mux", "DSP", "DSP" },
+ { "Capture Mux", "Decimator", "Left Decimator" },
+ { "Capture Mux", "Decimator", "Right Decimator" },
+
+ { "Capture", NULL, "Capture Mux" },
+
+ { "DSP", NULL, "DSP Siggen" },
+
+ { "DSP", NULL, "Left Decimator" },
+ { "DSP", NULL, "Right Decimator" },
+};
+
+static const struct snd_soc_dapm_route adau17x1_no_dsp_dapm_routes[] = {
+ { "Left DAC Mode Mux", "Stereo", "Playback" },
+ { "Left DAC Mode Mux", "Mono (L+R)", "Playback" },
+ { "Left DAC Mode Mux", "Mono Left Channel (L+R)", "Playback" },
+ { "Right DAC Mode Mux", "Stereo", "Playback" },
+ { "Right DAC Mode Mux", "Mono (L+R)", "Playback" },
+ { "Right DAC Mode Mux", "Mono Right Channel (L+R)", "Playback" },
+ { "Capture", NULL, "Left Decimator" },
+ { "Capture", NULL, "Right Decimator" },
+};
+
+bool adau17x1_has_dsp(struct adau *adau)
+{
+ switch (adau->type) {
+ case ADAU1761:
+ case ADAU1381:
+ case ADAU1781:
+ return true;
+ default:
+ return false;
+ }
+}
+EXPORT_SYMBOL_GPL(adau17x1_has_dsp);
+
+static int adau17x1_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;
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ unsigned int val, div, dsp_div;
+ unsigned int freq;
+
+ if (adau->clk_src == ADAU17X1_CLK_SRC_PLL)
+ freq = adau->pll_freq;
+ else
+ freq = adau->sysclk;
+
+ if (freq % params_rate(params) != 0)
+ return -EINVAL;
+
+ switch (freq / params_rate(params)) {
+ case 1024: /* fs */
+ div = 0;
+ dsp_div = 1;
+ break;
+ case 6144: /* fs / 6 */
+ div = 1;
+ dsp_div = 6;
+ break;
+ case 4096: /* fs / 4 */
+ div = 2;
+ dsp_div = 5;
+ break;
+ case 3072: /* fs / 3 */
+ div = 3;
+ dsp_div = 4;
+ break;
+ case 2048: /* fs / 2 */
+ div = 4;
+ dsp_div = 3;
+ break;
+ case 1536: /* fs / 1.5 */
+ div = 5;
+ dsp_div = 2;
+ break;
+ case 512: /* fs / 0.5 */
+ div = 6;
+ dsp_div = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
+ ADAU17X1_CONVERTER0_CONVSR_MASK, div);
+ if (adau17x1_has_dsp(adau)) {
+ regmap_write(adau->regmap, ADAU17X1_SERIAL_SAMPLING_RATE, div);
+ regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dsp_div);
+ }
+
+ if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J)
+ return 0;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ val = ADAU17X1_SERIAL_PORT1_DELAY16;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ val = ADAU17X1_SERIAL_PORT1_DELAY8;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ val = ADAU17X1_SERIAL_PORT1_DELAY0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1,
+ ADAU17X1_SERIAL_PORT1_DELAY_MASK, val);
+}
+
+static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id,
+ int source, unsigned int freq_in, unsigned int freq_out)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ unsigned int r, n, m, i, j;
+ unsigned int div;
+ int ret;
+
+ if (freq_in < 8000000 || freq_in > 27000000)
+ return -EINVAL;
+
+ if (!freq_out) {
+ r = 0;
+ n = 0;
+ m = 0;
+ div = 0;
+ } else {
+ if (freq_out % freq_in != 0) {
+ div = DIV_ROUND_UP(freq_in, 13500000);
+ freq_in /= div;
+ r = freq_out / freq_in;
+ i = freq_out % freq_in;
+ j = gcd(i, freq_in);
+ n = i / j;
+ m = freq_in / j;
+ div--;
+ } else {
+ r = freq_out / freq_in;
+ n = 0;
+ m = 0;
+ div = 0;
+ }
+ if (n > 0xffff || m > 0xffff || div > 3 || r > 8 || r < 2)
+ return -EINVAL;
+ }
+
+ adau->pll_regs[0] = m >> 8;
+ adau->pll_regs[1] = m & 0xff;
+ adau->pll_regs[2] = n >> 8;
+ adau->pll_regs[3] = n & 0xff;
+ adau->pll_regs[4] = (r << 3) | (div << 1);
+ if (m != 0)
+ adau->pll_regs[4] |= 1; /* Fractional mode */
+
+ /* The PLL register is 6 bytes long and can only be written at once. */
+ ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL,
+ adau->pll_regs, ARRAY_SIZE(adau->pll_regs));
+ if (ret)
+ return ret;
+
+ adau->pll_freq = freq_out;
+
+ return 0;
+}
+
+static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
+ struct snd_soc_dapm_context *dapm = &dai->codec->dapm;
+
+ switch (clk_id) {
+ case ADAU17X1_CLK_SRC_MCLK:
+ case ADAU17X1_CLK_SRC_PLL:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ adau->sysclk = freq;
+
+ if (adau->clk_src != clk_id) {
+ if (clk_id == ADAU17X1_CLK_SRC_PLL) {
+ snd_soc_dapm_add_routes(dapm,
+ &adau17x1_dapm_pll_route, 1);
+ } else {
+ snd_soc_dapm_del_routes(dapm,
+ &adau17x1_dapm_pll_route, 1);
+ }
+ }
+
+ adau->clk_src = clk_id;
+
+ return 0;
+}
+
+static int adau17x1_set_dai_fmt(struct snd_soc_dai *dai,
+ unsigned int fmt)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
+ unsigned int ctrl0, ctrl1;
+ int lrclk_pol;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ ctrl0 = ADAU17X1_SERIAL_PORT0_MASTER;
+ adau->master = true;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ ctrl0 = 0;
+ adau->master = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ lrclk_pol = 0;
+ ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY1;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ case SND_SOC_DAIFMT_RIGHT_J:
+ lrclk_pol = 1;
+ ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY0;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ lrclk_pol = 1;
+ ctrl0 |= ADAU17X1_SERIAL_PORT0_PULSE_MODE;
+ ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY1;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ lrclk_pol = 1;
+ ctrl0 |= ADAU17X1_SERIAL_PORT0_PULSE_MODE;
+ ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ ctrl0 |= ADAU17X1_SERIAL_PORT0_BCLK_POL;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ lrclk_pol = !lrclk_pol;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ ctrl0 |= ADAU17X1_SERIAL_PORT0_BCLK_POL;
+ lrclk_pol = !lrclk_pol;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (lrclk_pol)
+ ctrl0 |= ADAU17X1_SERIAL_PORT0_LRCLK_POL;
+
+ regmap_write(adau->regmap, ADAU17X1_SERIAL_PORT0, ctrl0);
+ regmap_write(adau->regmap, ADAU17X1_SERIAL_PORT1, ctrl1);
+
+ adau->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+
+ return 0;
+}
+
+static int adau17x1_set_dai_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
+ unsigned int ser_ctrl0, ser_ctrl1;
+ unsigned int conv_ctrl0, conv_ctrl1;
+
+ /* I2S mode */
+ if (slots == 0) {
+ slots = 2;
+ rx_mask = 3;
+ tx_mask = 3;
+ slot_width = 32;
+ }
+
+ switch (slots) {
+ case 2:
+ ser_ctrl0 = ADAU17X1_SERIAL_PORT0_STEREO;
+ break;
+ case 4:
+ ser_ctrl0 = ADAU17X1_SERIAL_PORT0_TDM4;
+ break;
+ case 8:
+ if (adau->type == ADAU1361)
+ return -EINVAL;
+
+ ser_ctrl0 = ADAU17X1_SERIAL_PORT0_TDM8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (slot_width * slots) {
+ case 32:
+ if (adau->type == ADAU1761)
+ return -EINVAL;
+
+ ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK32;
+ break;
+ case 64:
+ ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK64;
+ break;
+ case 48:
+ ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK48;
+ break;
+ case 128:
+ ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK128;
+ break;
+ case 256:
+ if (adau->type == ADAU1361)
+ return -EINVAL;
+
+ ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK256;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (rx_mask) {
+ case 0x03:
+ conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(1);
+ adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 0;
+ break;
+ case 0x0c:
+ conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(2);
+ adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 1;
+ break;
+ case 0x30:
+ conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(3);
+ adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 2;
+ break;
+ case 0xc0:
+ conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(4);
+ adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (tx_mask) {
+ case 0x03:
+ conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(1);
+ adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 0;
+ break;
+ case 0x0c:
+ conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(2);
+ adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 1;
+ break;
+ case 0x30:
+ conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(3);
+ adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 2;
+ break;
+ case 0xc0:
+ conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(4);
+ adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
+ ADAU17X1_CONVERTER0_DAC_PAIR_MASK, conv_ctrl0);
+ regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER1,
+ ADAU17X1_CONVERTER1_ADC_PAIR_MASK, conv_ctrl1);
+ regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT0,
+ ADAU17X1_SERIAL_PORT0_TDM_MASK, ser_ctrl0);
+ regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1,
+ ADAU17X1_SERIAL_PORT1_BCLK_MASK, ser_ctrl1);
+
+ if (!adau17x1_has_dsp(adau))
+ return 0;
+
+ if (adau->dsp_bypass[SNDRV_PCM_STREAM_PLAYBACK]) {
+ regmap_write(adau->regmap, ADAU17X1_SERIAL_INPUT_ROUTE,
+ (adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] * 2) + 1);
+ }
+
+ if (adau->dsp_bypass[SNDRV_PCM_STREAM_CAPTURE]) {
+ regmap_write(adau->regmap, ADAU17X1_SERIAL_OUTPUT_ROUTE,
+ (adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] * 2) + 1);
+ }
+
+ return 0;
+}
+
+const struct snd_soc_dai_ops adau17x1_dai_ops = {
+ .hw_params = adau17x1_hw_params,
+ .set_sysclk = adau17x1_set_dai_sysclk,
+ .set_fmt = adau17x1_set_dai_fmt,
+ .set_pll = adau17x1_set_dai_pll,
+ .set_tdm_slot = adau17x1_set_dai_tdm_slot,
+};
+EXPORT_SYMBOL_GPL(adau17x1_dai_ops);
+
+int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec,
+ enum adau17x1_micbias_voltage micbias)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+
+ switch (micbias) {
+ case ADAU17X1_MICBIAS_0_90_AVDD:
+ case ADAU17X1_MICBIAS_0_65_AVDD:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_write(adau->regmap, ADAU17X1_MICBIAS, micbias << 2);
+}
+EXPORT_SYMBOL_GPL(adau17x1_set_micbias_voltage);
+
+bool adau17x1_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ADAU17X1_CLOCK_CONTROL:
+ case ADAU17X1_PLL_CONTROL:
+ case ADAU17X1_REC_POWER_MGMT:
+ case ADAU17X1_MICBIAS:
+ case ADAU17X1_SERIAL_PORT0:
+ case ADAU17X1_SERIAL_PORT1:
+ case ADAU17X1_CONVERTER0:
+ case ADAU17X1_CONVERTER1:
+ case ADAU17X1_LEFT_INPUT_DIGITAL_VOL:
+ case ADAU17X1_RIGHT_INPUT_DIGITAL_VOL:
+ case ADAU17X1_ADC_CONTROL:
+ case ADAU17X1_PLAY_POWER_MGMT:
+ case ADAU17X1_DAC_CONTROL0:
+ case ADAU17X1_DAC_CONTROL1:
+ case ADAU17X1_DAC_CONTROL2:
+ case ADAU17X1_SERIAL_PORT_PAD:
+ case ADAU17X1_CONTROL_PORT_PAD0:
+ case ADAU17X1_CONTROL_PORT_PAD1:
+ case ADAU17X1_DSP_SAMPLING_RATE:
+ case ADAU17X1_SERIAL_INPUT_ROUTE:
+ case ADAU17X1_SERIAL_OUTPUT_ROUTE:
+ case ADAU17X1_DSP_ENABLE:
+ case ADAU17X1_DSP_RUN:
+ case ADAU17X1_SERIAL_SAMPLING_RATE:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+EXPORT_SYMBOL_GPL(adau17x1_readable_register);
+
+bool adau17x1_volatile_register(struct device *dev, unsigned int reg)
+{
+ /* SigmaDSP parameter and program memory */
+ if (reg < 0x4000)
+ return true;
+
+ switch (reg) {
+ /* The PLL register is 6 bytes long */
+ case ADAU17X1_PLL_CONTROL:
+ case ADAU17X1_PLL_CONTROL + 1:
+ case ADAU17X1_PLL_CONTROL + 2:
+ case ADAU17X1_PLL_CONTROL + 3:
+ case ADAU17X1_PLL_CONTROL + 4:
+ case ADAU17X1_PLL_CONTROL + 5:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(adau17x1_volatile_register);
+
+int adau17x1_load_firmware(struct adau *adau, struct device *dev,
+ const char *firmware)
+{
+ int ret;
+ int dspsr;
+
+ ret = regmap_read(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, &dspsr);
+ if (ret)
+ return ret;
+
+ regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1);
+ regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf);
+
+ ret = process_sigma_firmware_regmap(dev, adau->regmap, firmware);
+ if (ret) {
+ regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0);
+ return ret;
+ }
+ regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dspsr);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adau17x1_load_firmware);
+
+int adau17x1_add_widgets(struct snd_soc_codec *codec)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ ret = snd_soc_add_codec_controls(codec, adau17x1_controls,
+ ARRAY_SIZE(adau17x1_controls));
+ if (ret)
+ return ret;
+ ret = snd_soc_dapm_new_controls(&codec->dapm, adau17x1_dapm_widgets,
+ ARRAY_SIZE(adau17x1_dapm_widgets));
+ if (ret)
+ return ret;
+
+ if (adau17x1_has_dsp(adau)) {
+ ret = snd_soc_dapm_new_controls(&codec->dapm,
+ adau17x1_dsp_dapm_widgets,
+ ARRAY_SIZE(adau17x1_dsp_dapm_widgets));
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(adau17x1_add_widgets);
+
+int adau17x1_add_routes(struct snd_soc_codec *codec)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ ret = snd_soc_dapm_add_routes(&codec->dapm, adau17x1_dapm_routes,
+ ARRAY_SIZE(adau17x1_dapm_routes));
+ if (ret)
+ return ret;
+
+ if (adau17x1_has_dsp(adau)) {
+ ret = snd_soc_dapm_add_routes(&codec->dapm,
+ adau17x1_dsp_dapm_routes,
+ ARRAY_SIZE(adau17x1_dsp_dapm_routes));
+ } else {
+ ret = snd_soc_dapm_add_routes(&codec->dapm,
+ adau17x1_no_dsp_dapm_routes,
+ ARRAY_SIZE(adau17x1_no_dsp_dapm_routes));
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(adau17x1_add_routes);
+
+int adau17x1_suspend(struct snd_soc_codec *codec)
+{
+ codec->driver->set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adau17x1_suspend);
+
+int adau17x1_resume(struct snd_soc_codec *codec)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+
+ if (adau->switch_mode)
+ adau->switch_mode(codec->dev);
+
+ codec->driver->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ regcache_sync(adau->regmap);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adau17x1_resume);
+
+int adau17x1_probe(struct device *dev, struct regmap *regmap,
+ enum adau17x1_type type, void (*switch_mode)(struct device *dev))
+{
+ struct adau *adau;
+
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ adau = devm_kzalloc(dev, sizeof(*adau), GFP_KERNEL);
+ if (!adau)
+ return -ENOMEM;
+
+ adau->regmap = regmap;
+ adau->switch_mode = switch_mode;
+ adau->type = type;
+
+ dev_set_drvdata(dev, adau);
+
+ if (switch_mode)
+ switch_mode(dev);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adau17x1_probe);
+
+MODULE_DESCRIPTION("ASoC ADAU1X61/ADAU1X81 common code");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h
new file mode 100644
index 00000000000..3ffabaf4c7a
--- /dev/null
+++ b/sound/soc/codecs/adau17x1.h
@@ -0,0 +1,124 @@
+#ifndef __ADAU17X1_H__
+#define __ADAU17X1_H__
+
+#include <linux/regmap.h>
+#include <linux/platform_data/adau17x1.h>
+
+enum adau17x1_type {
+ ADAU1361,
+ ADAU1761,
+ ADAU1381,
+ ADAU1781,
+};
+
+enum adau17x1_pll {
+ ADAU17X1_PLL,
+};
+
+enum adau17x1_pll_src {
+ ADAU17X1_PLL_SRC_MCLK,
+};
+
+enum adau17x1_clk_src {
+ ADAU17X1_CLK_SRC_MCLK,
+ ADAU17X1_CLK_SRC_PLL,
+};
+
+struct adau {
+ unsigned int sysclk;
+ unsigned int pll_freq;
+
+ enum adau17x1_clk_src clk_src;
+ enum adau17x1_type type;
+ void (*switch_mode)(struct device *dev);
+
+ unsigned int dai_fmt;
+
+ uint8_t pll_regs[6];
+
+ bool master;
+
+ unsigned int tdm_slot[2];
+ bool dsp_bypass[2];
+
+ struct regmap *regmap;
+};
+
+int adau17x1_add_widgets(struct snd_soc_codec *codec);
+int adau17x1_add_routes(struct snd_soc_codec *codec);
+int adau17x1_probe(struct device *dev, struct regmap *regmap,
+ enum adau17x1_type type, void (*switch_mode)(struct device *dev));
+int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec,
+ enum adau17x1_micbias_voltage micbias);
+bool adau17x1_readable_register(struct device *dev, unsigned int reg);
+bool adau17x1_volatile_register(struct device *dev, unsigned int reg);
+int adau17x1_suspend(struct snd_soc_codec *codec);
+int adau17x1_resume(struct snd_soc_codec *codec);
+
+extern const struct snd_soc_dai_ops adau17x1_dai_ops;
+
+int adau17x1_load_firmware(struct adau *adau, struct device *dev,
+ const char *firmware);
+bool adau17x1_has_dsp(struct adau *adau);
+
+#define ADAU17X1_CLOCK_CONTROL 0x4000
+#define ADAU17X1_PLL_CONTROL 0x4002
+#define ADAU17X1_REC_POWER_MGMT 0x4009
+#define ADAU17X1_MICBIAS 0x4010
+#define ADAU17X1_SERIAL_PORT0 0x4015
+#define ADAU17X1_SERIAL_PORT1 0x4016
+#define ADAU17X1_CONVERTER0 0x4017
+#define ADAU17X1_CONVERTER1 0x4018
+#define ADAU17X1_LEFT_INPUT_DIGITAL_VOL 0x401a
+#define ADAU17X1_RIGHT_INPUT_DIGITAL_VOL 0x401b
+#define ADAU17X1_ADC_CONTROL 0x4019
+#define ADAU17X1_PLAY_POWER_MGMT 0x4029
+#define ADAU17X1_DAC_CONTROL0 0x402a
+#define ADAU17X1_DAC_CONTROL1 0x402b
+#define ADAU17X1_DAC_CONTROL2 0x402c
+#define ADAU17X1_SERIAL_PORT_PAD 0x402d
+#define ADAU17X1_CONTROL_PORT_PAD0 0x402f
+#define ADAU17X1_CONTROL_PORT_PAD1 0x4030
+#define ADAU17X1_DSP_SAMPLING_RATE 0x40eb
+#define ADAU17X1_SERIAL_INPUT_ROUTE 0x40f2
+#define ADAU17X1_SERIAL_OUTPUT_ROUTE 0x40f3
+#define ADAU17X1_DSP_ENABLE 0x40f5
+#define ADAU17X1_DSP_RUN 0x40f6
+#define ADAU17X1_SERIAL_SAMPLING_RATE 0x40f8
+
+#define ADAU17X1_SERIAL_PORT0_BCLK_POL BIT(4)
+#define ADAU17X1_SERIAL_PORT0_LRCLK_POL BIT(3)
+#define ADAU17X1_SERIAL_PORT0_MASTER BIT(0)
+
+#define ADAU17X1_SERIAL_PORT1_DELAY1 0x00
+#define ADAU17X1_SERIAL_PORT1_DELAY0 0x01
+#define ADAU17X1_SERIAL_PORT1_DELAY8 0x02
+#define ADAU17X1_SERIAL_PORT1_DELAY16 0x03
+#define ADAU17X1_SERIAL_PORT1_DELAY_MASK 0x03
+
+#define ADAU17X1_CLOCK_CONTROL_INFREQ_MASK 0x6
+#define ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL BIT(3)
+#define ADAU17X1_CLOCK_CONTROL_SYSCLK_EN BIT(0)
+
+#define ADAU17X1_SERIAL_PORT1_BCLK32 (0x0 << 5)
+#define ADAU17X1_SERIAL_PORT1_BCLK48 (0x1 << 5)
+#define ADAU17X1_SERIAL_PORT1_BCLK64 (0x2 << 5)
+#define ADAU17X1_SERIAL_PORT1_BCLK128 (0x3 << 5)
+#define ADAU17X1_SERIAL_PORT1_BCLK256 (0x4 << 5)
+#define ADAU17X1_SERIAL_PORT1_BCLK_MASK (0x7 << 5)
+
+#define ADAU17X1_SERIAL_PORT0_STEREO (0x0 << 1)
+#define ADAU17X1_SERIAL_PORT0_TDM4 (0x1 << 1)
+#define ADAU17X1_SERIAL_PORT0_TDM8 (0x2 << 1)
+#define ADAU17X1_SERIAL_PORT0_TDM_MASK (0x3 << 1)
+#define ADAU17X1_SERIAL_PORT0_PULSE_MODE BIT(5)
+
+#define ADAU17X1_CONVERTER0_DAC_PAIR(x) (((x) - 1) << 5)
+#define ADAU17X1_CONVERTER0_DAC_PAIR_MASK (0x3 << 5)
+#define ADAU17X1_CONVERTER1_ADC_PAIR(x) ((x) - 1)
+#define ADAU17X1_CONVERTER1_ADC_PAIR_MASK 0x3
+
+#define ADAU17X1_CONVERTER0_CONVSR_MASK 0x7
+
+
+#endif
diff --git a/sound/soc/codecs/adau1977-i2c.c b/sound/soc/codecs/adau1977-i2c.c
new file mode 100644
index 00000000000..9700e8c838c
--- /dev/null
+++ b/sound/soc/codecs/adau1977-i2c.c
@@ -0,0 +1,59 @@
+/*
+ * ADAU1977/ADAU1978/ADAU1979 driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/i2c.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+
+#include "adau1977.h"
+
+static int adau1977_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct regmap_config config;
+
+ config = adau1977_regmap_config;
+ config.val_bits = 8;
+ config.reg_bits = 8;
+
+ return adau1977_probe(&client->dev,
+ devm_regmap_init_i2c(client, &config),
+ id->driver_data, NULL);
+}
+
+static int adau1977_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static const struct i2c_device_id adau1977_i2c_ids[] = {
+ { "adau1977", ADAU1977 },
+ { "adau1978", ADAU1978 },
+ { "adau1979", ADAU1978 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adau1977_i2c_ids);
+
+static struct i2c_driver adau1977_i2c_driver = {
+ .driver = {
+ .name = "adau1977",
+ .owner = THIS_MODULE,
+ },
+ .probe = adau1977_i2c_probe,
+ .remove = adau1977_i2c_remove,
+ .id_table = adau1977_i2c_ids,
+};
+module_i2c_driver(adau1977_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1977-spi.c b/sound/soc/codecs/adau1977-spi.c
new file mode 100644
index 00000000000..b05cf5da3a9
--- /dev/null
+++ b/sound/soc/codecs/adau1977-spi.c
@@ -0,0 +1,76 @@
+/*
+ * ADAU1977/ADAU1978/ADAU1979 driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <sound/soc.h>
+
+#include "adau1977.h"
+
+static void adau1977_spi_switch_mode(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+
+ /*
+ * To get the device into SPI mode CLATCH has to be pulled low three
+ * times. Do this by issuing three dummy reads.
+ */
+ spi_w8r8(spi, 0x00);
+ spi_w8r8(spi, 0x00);
+ spi_w8r8(spi, 0x00);
+}
+
+static int adau1977_spi_probe(struct spi_device *spi)
+{
+ const struct spi_device_id *id = spi_get_device_id(spi);
+ struct regmap_config config;
+
+ if (!id)
+ return -EINVAL;
+
+ config = adau1977_regmap_config;
+ config.val_bits = 8;
+ config.reg_bits = 16;
+ config.read_flag_mask = 0x1;
+
+ return adau1977_probe(&spi->dev,
+ devm_regmap_init_spi(spi, &config),
+ id->driver_data, adau1977_spi_switch_mode);
+}
+
+static int adau1977_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ return 0;
+}
+
+static const struct spi_device_id adau1977_spi_ids[] = {
+ { "adau1977", ADAU1977 },
+ { "adau1978", ADAU1978 },
+ { "adau1979", ADAU1978 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, adau1977_spi_ids);
+
+static struct spi_driver adau1977_spi_driver = {
+ .driver = {
+ .name = "adau1977",
+ .owner = THIS_MODULE,
+ },
+ .probe = adau1977_spi_probe,
+ .remove = adau1977_spi_remove,
+ .id_table = adau1977_spi_ids,
+};
+module_spi_driver(adau1977_spi_driver);
+
+MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c
new file mode 100644
index 00000000000..fd55da7cb9d
--- /dev/null
+++ b/sound/soc/codecs/adau1977.c
@@ -0,0 +1,1018 @@
+/*
+ * ADAU1977/ADAU1978/ADAU1979 driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_data/adau1977.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+#include "adau1977.h"
+
+#define ADAU1977_REG_POWER 0x00
+#define ADAU1977_REG_PLL 0x01
+#define ADAU1977_REG_BOOST 0x02
+#define ADAU1977_REG_MICBIAS 0x03
+#define ADAU1977_REG_BLOCK_POWER_SAI 0x04
+#define ADAU1977_REG_SAI_CTRL0 0x05
+#define ADAU1977_REG_SAI_CTRL1 0x06
+#define ADAU1977_REG_CMAP12 0x07
+#define ADAU1977_REG_CMAP34 0x08
+#define ADAU1977_REG_SAI_OVERTEMP 0x09
+#define ADAU1977_REG_POST_ADC_GAIN(x) (0x0a + (x))
+#define ADAU1977_REG_MISC_CONTROL 0x0e
+#define ADAU1977_REG_DIAG_CONTROL 0x10
+#define ADAU1977_REG_STATUS(x) (0x11 + (x))
+#define ADAU1977_REG_DIAG_IRQ1 0x15
+#define ADAU1977_REG_DIAG_IRQ2 0x16
+#define ADAU1977_REG_ADJUST1 0x17
+#define ADAU1977_REG_ADJUST2 0x18
+#define ADAU1977_REG_ADC_CLIP 0x19
+#define ADAU1977_REG_DC_HPF_CAL 0x1a
+
+#define ADAU1977_POWER_RESET BIT(7)
+#define ADAU1977_POWER_PWUP BIT(0)
+
+#define ADAU1977_PLL_CLK_S BIT(4)
+#define ADAU1977_PLL_MCS_MASK 0x7
+
+#define ADAU1977_MICBIAS_MB_VOLTS_MASK 0xf0
+#define ADAU1977_MICBIAS_MB_VOLTS_OFFSET 4
+
+#define ADAU1977_BLOCK_POWER_SAI_LR_POL BIT(7)
+#define ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE BIT(6)
+#define ADAU1977_BLOCK_POWER_SAI_LDO_EN BIT(5)
+
+#define ADAU1977_SAI_CTRL0_FMT_MASK (0x3 << 6)
+#define ADAU1977_SAI_CTRL0_FMT_I2S (0x0 << 6)
+#define ADAU1977_SAI_CTRL0_FMT_LJ (0x1 << 6)
+#define ADAU1977_SAI_CTRL0_FMT_RJ_24BIT (0x2 << 6)
+#define ADAU1977_SAI_CTRL0_FMT_RJ_16BIT (0x3 << 6)
+
+#define ADAU1977_SAI_CTRL0_SAI_MASK (0x7 << 3)
+#define ADAU1977_SAI_CTRL0_SAI_I2S (0x0 << 3)
+#define ADAU1977_SAI_CTRL0_SAI_TDM_2 (0x1 << 3)
+#define ADAU1977_SAI_CTRL0_SAI_TDM_4 (0x2 << 3)
+#define ADAU1977_SAI_CTRL0_SAI_TDM_8 (0x3 << 3)
+#define ADAU1977_SAI_CTRL0_SAI_TDM_16 (0x4 << 3)
+
+#define ADAU1977_SAI_CTRL0_FS_MASK (0x7)
+#define ADAU1977_SAI_CTRL0_FS_8000_12000 (0x0)
+#define ADAU1977_SAI_CTRL0_FS_16000_24000 (0x1)
+#define ADAU1977_SAI_CTRL0_FS_32000_48000 (0x2)
+#define ADAU1977_SAI_CTRL0_FS_64000_96000 (0x3)
+#define ADAU1977_SAI_CTRL0_FS_128000_192000 (0x4)
+
+#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK (0x3 << 5)
+#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_32 (0x0 << 5)
+#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_24 (0x1 << 5)
+#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_16 (0x2 << 5)
+#define ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK (0x1 << 4)
+#define ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT (0x1 << 4)
+#define ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT (0x0 << 4)
+#define ADAU1977_SAI_CTRL1_LRCLK_PULSE BIT(3)
+#define ADAU1977_SAI_CTRL1_MSB BIT(2)
+#define ADAU1977_SAI_CTRL1_BCLKRATE_16 (0x1 << 1)
+#define ADAU1977_SAI_CTRL1_BCLKRATE_32 (0x0 << 1)
+#define ADAU1977_SAI_CTRL1_BCLKRATE_MASK (0x1 << 1)
+#define ADAU1977_SAI_CTRL1_MASTER BIT(0)
+
+#define ADAU1977_SAI_OVERTEMP_DRV_C(x) BIT(4 + (x))
+#define ADAU1977_SAI_OVERTEMP_DRV_HIZ BIT(3)
+
+#define ADAU1977_MISC_CONTROL_SUM_MODE_MASK (0x3 << 6)
+#define ADAU1977_MISC_CONTROL_SUM_MODE_1CH (0x2 << 6)
+#define ADAU1977_MISC_CONTROL_SUM_MODE_2CH (0x1 << 6)
+#define ADAU1977_MISC_CONTROL_SUM_MODE_4CH (0x0 << 6)
+#define ADAU1977_MISC_CONTROL_MMUTE BIT(4)
+#define ADAU1977_MISC_CONTROL_DC_CAL BIT(0)
+
+#define ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET 4
+#define ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET 0
+
+struct adau1977 {
+ struct regmap *regmap;
+ bool right_j;
+ unsigned int sysclk;
+ enum adau1977_sysclk_src sysclk_src;
+ struct gpio_desc *reset_gpio;
+ enum adau1977_type type;
+
+ struct regulator *avdd_reg;
+ struct regulator *dvdd_reg;
+
+ struct snd_pcm_hw_constraint_list constraints;
+
+ struct device *dev;
+ void (*switch_mode)(struct device *dev);
+
+ unsigned int max_master_fs;
+ unsigned int slot_width;
+ bool enabled;
+ bool master;
+};
+
+static const struct reg_default adau1977_reg_defaults[] = {
+ { 0x00, 0x00 },
+ { 0x01, 0x41 },
+ { 0x02, 0x4a },
+ { 0x03, 0x7d },
+ { 0x04, 0x3d },
+ { 0x05, 0x02 },
+ { 0x06, 0x00 },
+ { 0x07, 0x10 },
+ { 0x08, 0x32 },
+ { 0x09, 0xf0 },
+ { 0x0a, 0xa0 },
+ { 0x0b, 0xa0 },
+ { 0x0c, 0xa0 },
+ { 0x0d, 0xa0 },
+ { 0x0e, 0x02 },
+ { 0x10, 0x0f },
+ { 0x15, 0x20 },
+ { 0x16, 0x00 },
+ { 0x17, 0x00 },
+ { 0x18, 0x00 },
+ { 0x1a, 0x00 },
+};
+
+static const DECLARE_TLV_DB_MINMAX_MUTE(adau1977_adc_gain, -3562, 6000);
+
+static const struct snd_soc_dapm_widget adau1977_micbias_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("MICBIAS", ADAU1977_REG_MICBIAS,
+ 3, 0, NULL, 0)
+};
+
+static const struct snd_soc_dapm_widget adau1977_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("Vref", ADAU1977_REG_BLOCK_POWER_SAI,
+ 4, 0, NULL, 0),
+
+ SND_SOC_DAPM_ADC("ADC1", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 0, 0),
+ SND_SOC_DAPM_ADC("ADC2", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 1, 0),
+ SND_SOC_DAPM_ADC("ADC3", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 2, 0),
+ SND_SOC_DAPM_ADC("ADC4", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 3, 0),
+
+ SND_SOC_DAPM_INPUT("AIN1"),
+ SND_SOC_DAPM_INPUT("AIN2"),
+ SND_SOC_DAPM_INPUT("AIN3"),
+ SND_SOC_DAPM_INPUT("AIN4"),
+
+ SND_SOC_DAPM_OUTPUT("VREF"),
+};
+
+static const struct snd_soc_dapm_route adau1977_dapm_routes[] = {
+ { "ADC1", NULL, "AIN1" },
+ { "ADC2", NULL, "AIN2" },
+ { "ADC3", NULL, "AIN3" },
+ { "ADC4", NULL, "AIN4" },
+
+ { "ADC1", NULL, "Vref" },
+ { "ADC2", NULL, "Vref" },
+ { "ADC3", NULL, "Vref" },
+ { "ADC4", NULL, "Vref" },
+
+ { "VREF", NULL, "Vref" },
+};
+
+#define ADAU1977_VOLUME(x) \
+ SOC_SINGLE_TLV("ADC" #x " Capture Volume", \
+ ADAU1977_REG_POST_ADC_GAIN((x) - 1), \
+ 0, 255, 1, adau1977_adc_gain)
+
+#define ADAU1977_HPF_SWITCH(x) \
+ SOC_SINGLE("ADC" #x " Highpass-Filter Capture Switch", \
+ ADAU1977_REG_DC_HPF_CAL, (x) - 1, 1, 0)
+
+#define ADAU1977_DC_SUB_SWITCH(x) \
+ SOC_SINGLE("ADC" #x " DC Substraction Capture Switch", \
+ ADAU1977_REG_DC_HPF_CAL, (x) + 3, 1, 0)
+
+static const struct snd_kcontrol_new adau1977_snd_controls[] = {
+ ADAU1977_VOLUME(1),
+ ADAU1977_VOLUME(2),
+ ADAU1977_VOLUME(3),
+ ADAU1977_VOLUME(4),
+
+ ADAU1977_HPF_SWITCH(1),
+ ADAU1977_HPF_SWITCH(2),
+ ADAU1977_HPF_SWITCH(3),
+ ADAU1977_HPF_SWITCH(4),
+
+ ADAU1977_DC_SUB_SWITCH(1),
+ ADAU1977_DC_SUB_SWITCH(2),
+ ADAU1977_DC_SUB_SWITCH(3),
+ ADAU1977_DC_SUB_SWITCH(4),
+};
+
+static int adau1977_reset(struct adau1977 *adau1977)
+{
+ int ret;
+
+ /*
+ * The reset bit is obviously volatile, but we need to be able to cache
+ * the other bits in the register, so we can't just mark the whole
+ * register as volatile. Since this is the only place where we'll ever
+ * touch the reset bit just bypass the cache for this operation.
+ */
+ regcache_cache_bypass(adau1977->regmap, true);
+ ret = regmap_write(adau1977->regmap, ADAU1977_REG_POWER,
+ ADAU1977_POWER_RESET);
+ regcache_cache_bypass(adau1977->regmap, false);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+/*
+ * Returns the appropriate setting for ths FS field in the CTRL0 register
+ * depending on the rate.
+ */
+static int adau1977_lookup_fs(unsigned int rate)
+{
+ if (rate >= 8000 && rate <= 12000)
+ return ADAU1977_SAI_CTRL0_FS_8000_12000;
+ else if (rate >= 16000 && rate <= 24000)
+ return ADAU1977_SAI_CTRL0_FS_16000_24000;
+ else if (rate >= 32000 && rate <= 48000)
+ return ADAU1977_SAI_CTRL0_FS_32000_48000;
+ else if (rate >= 64000 && rate <= 96000)
+ return ADAU1977_SAI_CTRL0_FS_64000_96000;
+ else if (rate >= 128000 && rate <= 192000)
+ return ADAU1977_SAI_CTRL0_FS_128000_192000;
+ else
+ return -EINVAL;
+}
+
+static int adau1977_lookup_mcs(struct adau1977 *adau1977, unsigned int rate,
+ unsigned int fs)
+{
+ unsigned int mcs;
+
+ /*
+ * rate = sysclk / (512 * mcs_lut[mcs]) * 2**fs
+ * => mcs_lut[mcs] = sysclk / (512 * rate) * 2**fs
+ * => mcs_lut[mcs] = sysclk / ((512 / 2**fs) * rate)
+ */
+
+ rate *= 512 >> fs;
+
+ if (adau1977->sysclk % rate != 0)
+ return -EINVAL;
+
+ mcs = adau1977->sysclk / rate;
+
+ /* The factors configured by MCS are 1, 2, 3, 4, 6 */
+ if (mcs < 1 || mcs > 6 || mcs == 5)
+ return -EINVAL;
+
+ mcs = mcs - 1;
+ if (mcs == 5)
+ mcs = 4;
+
+ return mcs;
+}
+
+static int adau1977_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;
+ struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec);
+ unsigned int rate = params_rate(params);
+ unsigned int slot_width;
+ unsigned int ctrl0, ctrl0_mask;
+ unsigned int ctrl1;
+ int mcs, fs;
+ int ret;
+
+ fs = adau1977_lookup_fs(rate);
+ if (fs < 0)
+ return fs;
+
+ if (adau1977->sysclk_src == ADAU1977_SYSCLK_SRC_MCLK) {
+ mcs = adau1977_lookup_mcs(adau1977, rate, fs);
+ if (mcs < 0)
+ return mcs;
+ } else {
+ mcs = 0;
+ }
+
+ ctrl0_mask = ADAU1977_SAI_CTRL0_FS_MASK;
+ ctrl0 = fs;
+
+ if (adau1977->right_j) {
+ switch (params_width(params)) {
+ case 16:
+ ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_16BIT;
+ break;
+ case 24:
+ ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT;
+ break;
+ default:
+ return -EINVAL;
+ }
+ ctrl0_mask |= ADAU1977_SAI_CTRL0_FMT_MASK;
+ }
+
+ if (adau1977->master) {
+ switch (params_width(params)) {
+ case 16:
+ ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT;
+ slot_width = 16;
+ break;
+ case 24:
+ case 32:
+ ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT;
+ slot_width = 32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* In TDM mode there is a fixed slot width */
+ if (adau1977->slot_width)
+ slot_width = adau1977->slot_width;
+
+ if (slot_width == 16)
+ ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_16;
+ else
+ ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_32;
+
+ ret = regmap_update_bits(adau1977->regmap,
+ ADAU1977_REG_SAI_CTRL1,
+ ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK |
+ ADAU1977_SAI_CTRL1_BCLKRATE_MASK,
+ ctrl1);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0,
+ ctrl0_mask, ctrl0);
+ if (ret < 0)
+ return ret;
+
+ return regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL,
+ ADAU1977_PLL_MCS_MASK, mcs);
+}
+
+static int adau1977_power_disable(struct adau1977 *adau1977)
+{
+ int ret = 0;
+
+ if (!adau1977->enabled)
+ return 0;
+
+ ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER,
+ ADAU1977_POWER_PWUP, 0);
+ if (ret)
+ return ret;
+
+ regcache_mark_dirty(adau1977->regmap);
+
+ if (adau1977->reset_gpio)
+ gpiod_set_value_cansleep(adau1977->reset_gpio, 0);
+
+ regcache_cache_only(adau1977->regmap, true);
+
+ regulator_disable(adau1977->avdd_reg);
+ if (adau1977->dvdd_reg)
+ regulator_disable(adau1977->dvdd_reg);
+
+ adau1977->enabled = false;
+
+ return 0;
+}
+
+static int adau1977_power_enable(struct adau1977 *adau1977)
+{
+ unsigned int val;
+ int ret = 0;
+
+ if (adau1977->enabled)
+ return 0;
+
+ ret = regulator_enable(adau1977->avdd_reg);
+ if (ret)
+ return ret;
+
+ if (adau1977->dvdd_reg) {
+ ret = regulator_enable(adau1977->dvdd_reg);
+ if (ret)
+ goto err_disable_avdd;
+ }
+
+ if (adau1977->reset_gpio)
+ gpiod_set_value_cansleep(adau1977->reset_gpio, 1);
+
+ regcache_cache_only(adau1977->regmap, false);
+
+ if (adau1977->switch_mode)
+ adau1977->switch_mode(adau1977->dev);
+
+ ret = adau1977_reset(adau1977);
+ if (ret)
+ goto err_disable_dvdd;
+
+ ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER,
+ ADAU1977_POWER_PWUP, ADAU1977_POWER_PWUP);
+ if (ret)
+ goto err_disable_dvdd;
+
+ ret = regcache_sync(adau1977->regmap);
+ if (ret)
+ goto err_disable_dvdd;
+
+ /*
+ * The PLL register is not affected by the software reset. It is
+ * possible that the value of the register was changed to the
+ * default value while we were in cache only mode. In this case
+ * regcache_sync will skip over it and we have to manually sync
+ * it.
+ */
+ ret = regmap_read(adau1977->regmap, ADAU1977_REG_PLL, &val);
+ if (ret)
+ goto err_disable_dvdd;
+
+ if (val == 0x41) {
+ regcache_cache_bypass(adau1977->regmap, true);
+ ret = regmap_write(adau1977->regmap, ADAU1977_REG_PLL,
+ 0x41);
+ if (ret)
+ goto err_disable_dvdd;
+ regcache_cache_bypass(adau1977->regmap, false);
+ }
+
+ adau1977->enabled = true;
+
+ return ret;
+
+err_disable_dvdd:
+ if (adau1977->dvdd_reg)
+ regulator_disable(adau1977->dvdd_reg);
+err_disable_avdd:
+ regulator_disable(adau1977->avdd_reg);
+ return ret;
+}
+
+static int adau1977_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+ ret = adau1977_power_enable(adau1977);
+ break;
+ case SND_SOC_BIAS_OFF:
+ ret = adau1977_power_disable(adau1977);
+ break;
+ }
+
+ if (ret)
+ return ret;
+
+ codec->dapm.bias_level = level;
+
+ return 0;
+}
+
+static int adau1977_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+ unsigned int rx_mask, int slots, int width)
+{
+ struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec);
+ unsigned int ctrl0, ctrl1, drv;
+ unsigned int slot[4];
+ unsigned int i;
+ int ret;
+
+ if (slots == 0) {
+ /* 0 = No fixed slot width */
+ adau1977->slot_width = 0;
+ adau1977->max_master_fs = 192000;
+ return regmap_update_bits(adau1977->regmap,
+ ADAU1977_REG_SAI_CTRL0, ADAU1977_SAI_CTRL0_SAI_MASK,
+ ADAU1977_SAI_CTRL0_SAI_I2S);
+ }
+
+ if (rx_mask == 0 || tx_mask != 0)
+ return -EINVAL;
+
+ drv = 0;
+ for (i = 0; i < 4; i++) {
+ slot[i] = __ffs(rx_mask);
+ drv |= ADAU1977_SAI_OVERTEMP_DRV_C(i);
+ rx_mask &= ~(1 << slot[i]);
+ if (slot[i] >= slots)
+ return -EINVAL;
+ if (rx_mask == 0)
+ break;
+ }
+
+ if (rx_mask != 0)
+ return -EINVAL;
+
+ switch (width) {
+ case 16:
+ ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_16;
+ break;
+ case 24:
+ /* We can only generate 16 bit or 32 bit wide slots */
+ if (adau1977->master)
+ return -EINVAL;
+ ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_24;
+ break;
+ case 32:
+ ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (slots) {
+ case 2:
+ ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_2;
+ break;
+ case 4:
+ ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_4;
+ break;
+ case 8:
+ ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_8;
+ break;
+ case 16:
+ ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_16;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP,
+ ADAU1977_SAI_OVERTEMP_DRV_C(0) |
+ ADAU1977_SAI_OVERTEMP_DRV_C(1) |
+ ADAU1977_SAI_OVERTEMP_DRV_C(2) |
+ ADAU1977_SAI_OVERTEMP_DRV_C(3), drv);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP12,
+ (slot[1] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) |
+ (slot[0] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET));
+ if (ret)
+ return ret;
+
+ ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP34,
+ (slot[3] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) |
+ (slot[2] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0,
+ ADAU1977_SAI_CTRL0_SAI_MASK, ctrl0);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1,
+ ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK, ctrl1);
+ if (ret)
+ return ret;
+
+ adau1977->slot_width = width;
+
+ /* In master mode the maximum bitclock is 24.576 MHz */
+ adau1977->max_master_fs = min(192000, 24576000 / width / slots);
+
+ return 0;
+}
+
+static int adau1977_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+ struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec);
+ unsigned int val;
+
+ if (mute)
+ val = ADAU1977_MISC_CONTROL_MMUTE;
+ else
+ val = 0;
+
+ return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MISC_CONTROL,
+ ADAU1977_MISC_CONTROL_MMUTE, val);
+}
+
+static int adau1977_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec);
+ unsigned int ctrl0 = 0, ctrl1 = 0, block_power = 0;
+ bool invert_lrclk;
+ int ret;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ adau1977->master = false;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ ctrl1 |= ADAU1977_SAI_CTRL1_MASTER;
+ adau1977->master = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ invert_lrclk = false;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE;
+ invert_lrclk = false;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ invert_lrclk = true;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE;
+ invert_lrclk = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ adau1977->right_j = false;
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ;
+ invert_lrclk = !invert_lrclk;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT;
+ adau1977->right_j = true;
+ invert_lrclk = !invert_lrclk;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE;
+ ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S;
+ invert_lrclk = false;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE;
+ ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ;
+ invert_lrclk = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (invert_lrclk)
+ block_power |= ADAU1977_BLOCK_POWER_SAI_LR_POL;
+
+ ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI,
+ ADAU1977_BLOCK_POWER_SAI_LR_POL |
+ ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE, block_power);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0,
+ ADAU1977_SAI_CTRL0_FMT_MASK,
+ ctrl0);
+ if (ret)
+ return ret;
+
+ return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1,
+ ADAU1977_SAI_CTRL1_MASTER | ADAU1977_SAI_CTRL1_LRCLK_PULSE,
+ ctrl1);
+}
+
+static int adau1977_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec);
+ u64 formats = 0;
+
+ if (adau1977->slot_width == 16)
+ formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE;
+ else if (adau1977->right_j || adau1977->slot_width == 24)
+ formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE;
+
+ snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &adau1977->constraints);
+
+ if (adau1977->master)
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_RATE, 8000, adau1977->max_master_fs);
+
+ if (formats != 0)
+ snd_pcm_hw_constraint_mask64(substream->runtime,
+ SNDRV_PCM_HW_PARAM_FORMAT, formats);
+
+ return 0;
+}
+
+static int adau1977_set_tristate(struct snd_soc_dai *dai, int tristate)
+{
+ struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec);
+ unsigned int val;
+
+ if (tristate)
+ val = ADAU1977_SAI_OVERTEMP_DRV_HIZ;
+ else
+ val = 0;
+
+ return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP,
+ ADAU1977_SAI_OVERTEMP_DRV_HIZ, val);
+}
+
+static const struct snd_soc_dai_ops adau1977_dai_ops = {
+ .startup = adau1977_startup,
+ .hw_params = adau1977_hw_params,
+ .mute_stream = adau1977_mute,
+ .set_fmt = adau1977_set_dai_fmt,
+ .set_tdm_slot = adau1977_set_tdm_slot,
+ .set_tristate = adau1977_set_tristate,
+};
+
+static struct snd_soc_dai_driver adau1977_dai = {
+ .name = "adau1977-hifi",
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .sig_bits = 24,
+ },
+ .ops = &adau1977_dai_ops,
+};
+
+static const unsigned int adau1977_rates[] = {
+ 8000, 16000, 32000, 64000, 128000,
+ 11025, 22050, 44100, 88200, 172400,
+ 12000, 24000, 48000, 96000, 192000,
+};
+
+#define ADAU1977_RATE_CONSTRAINT_MASK_32000 0x001f
+#define ADAU1977_RATE_CONSTRAINT_MASK_44100 0x03e0
+#define ADAU1977_RATE_CONSTRAINT_MASK_48000 0x7c00
+/* All rates >= 32000 */
+#define ADAU1977_RATE_CONSTRAINT_MASK_LRCLK 0x739c
+
+static bool adau1977_check_sysclk(unsigned int mclk, unsigned int base_freq)
+{
+ unsigned int mcs;
+
+ if (mclk % (base_freq * 128) != 0)
+ return false;
+
+ mcs = mclk / (128 * base_freq);
+ if (mcs < 1 || mcs > 6 || mcs == 5)
+ return false;
+
+ return true;
+}
+
+static int adau1977_set_sysclk(struct snd_soc_codec *codec,
+ int clk_id, int source, unsigned int freq, int dir)
+{
+ struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec);
+ unsigned int mask = 0;
+ unsigned int clk_src;
+ unsigned int ret;
+
+ if (dir != SND_SOC_CLOCK_IN)
+ return -EINVAL;
+
+ if (clk_id != ADAU1977_SYSCLK)
+ return -EINVAL;
+
+ switch (source) {
+ case ADAU1977_SYSCLK_SRC_MCLK:
+ clk_src = 0;
+ break;
+ case ADAU1977_SYSCLK_SRC_LRCLK:
+ clk_src = ADAU1977_PLL_CLK_S;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (freq != 0 && source == ADAU1977_SYSCLK_SRC_MCLK) {
+ if (freq < 4000000 || freq > 36864000)
+ return -EINVAL;
+
+ if (adau1977_check_sysclk(freq, 32000))
+ mask |= ADAU1977_RATE_CONSTRAINT_MASK_32000;
+ if (adau1977_check_sysclk(freq, 44100))
+ mask |= ADAU1977_RATE_CONSTRAINT_MASK_44100;
+ if (adau1977_check_sysclk(freq, 48000))
+ mask |= ADAU1977_RATE_CONSTRAINT_MASK_48000;
+
+ if (mask == 0)
+ return -EINVAL;
+ } else if (source == ADAU1977_SYSCLK_SRC_LRCLK) {
+ mask = ADAU1977_RATE_CONSTRAINT_MASK_LRCLK;
+ }
+
+ ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL,
+ ADAU1977_PLL_CLK_S, clk_src);
+ if (ret)
+ return ret;
+
+ adau1977->constraints.mask = mask;
+ adau1977->sysclk_src = source;
+ adau1977->sysclk = freq;
+
+ return 0;
+}
+
+static int adau1977_codec_probe(struct snd_soc_codec *codec)
+{
+ struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ switch (adau1977->type) {
+ case ADAU1977:
+ ret = snd_soc_dapm_new_controls(&codec->dapm,
+ adau1977_micbias_dapm_widgets,
+ ARRAY_SIZE(adau1977_micbias_dapm_widgets));
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver adau1977_codec_driver = {
+ .probe = adau1977_codec_probe,
+ .set_bias_level = adau1977_set_bias_level,
+ .set_sysclk = adau1977_set_sysclk,
+ .idle_bias_off = true,
+
+ .controls = adau1977_snd_controls,
+ .num_controls = ARRAY_SIZE(adau1977_snd_controls),
+ .dapm_widgets = adau1977_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(adau1977_dapm_widgets),
+ .dapm_routes = adau1977_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(adau1977_dapm_routes),
+};
+
+static int adau1977_setup_micbias(struct adau1977 *adau1977)
+{
+ struct adau1977_platform_data *pdata = adau1977->dev->platform_data;
+ unsigned int micbias;
+
+ if (pdata) {
+ micbias = pdata->micbias;
+ if (micbias > ADAU1977_MICBIAS_9V0)
+ return -EINVAL;
+
+ } else {
+ micbias = ADAU1977_MICBIAS_8V5;
+ }
+
+ return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MICBIAS,
+ ADAU1977_MICBIAS_MB_VOLTS_MASK,
+ micbias << ADAU1977_MICBIAS_MB_VOLTS_OFFSET);
+}
+
+int adau1977_probe(struct device *dev, struct regmap *regmap,
+ enum adau1977_type type, void (*switch_mode)(struct device *dev))
+{
+ unsigned int power_off_mask;
+ struct adau1977 *adau1977;
+ int ret;
+
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ adau1977 = devm_kzalloc(dev, sizeof(*adau1977), GFP_KERNEL);
+ if (adau1977 == NULL)
+ return -ENOMEM;
+
+ adau1977->dev = dev;
+ adau1977->type = type;
+ adau1977->regmap = regmap;
+ adau1977->switch_mode = switch_mode;
+ adau1977->max_master_fs = 192000;
+
+ adau1977->constraints.list = adau1977_rates;
+ adau1977->constraints.count = ARRAY_SIZE(adau1977_rates);
+
+ adau1977->avdd_reg = devm_regulator_get(dev, "AVDD");
+ if (IS_ERR(adau1977->avdd_reg))
+ return PTR_ERR(adau1977->avdd_reg);
+
+ adau1977->dvdd_reg = devm_regulator_get_optional(dev, "DVDD");
+ if (IS_ERR(adau1977->dvdd_reg)) {
+ if (PTR_ERR(adau1977->dvdd_reg) != -ENODEV)
+ return PTR_ERR(adau1977->dvdd_reg);
+ adau1977->dvdd_reg = NULL;
+ }
+
+ adau1977->reset_gpio = devm_gpiod_get(dev, "reset");
+ if (IS_ERR(adau1977->reset_gpio)) {
+ ret = PTR_ERR(adau1977->reset_gpio);
+ if (ret != -ENOENT && ret != -ENOSYS)
+ return PTR_ERR(adau1977->reset_gpio);
+ adau1977->reset_gpio = NULL;
+ }
+
+ dev_set_drvdata(dev, adau1977);
+
+ if (adau1977->reset_gpio) {
+ ret = gpiod_direction_output(adau1977->reset_gpio, 0);
+ if (ret)
+ return ret;
+ ndelay(100);
+ }
+
+ ret = adau1977_power_enable(adau1977);
+ if (ret)
+ return ret;
+
+ if (type == ADAU1977) {
+ ret = adau1977_setup_micbias(adau1977);
+ if (ret)
+ goto err_poweroff;
+ }
+
+ if (adau1977->dvdd_reg)
+ power_off_mask = ~0;
+ else
+ power_off_mask = ~ADAU1977_BLOCK_POWER_SAI_LDO_EN;
+
+ ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI,
+ power_off_mask, 0x00);
+ if (ret)
+ goto err_poweroff;
+
+ ret = adau1977_power_disable(adau1977);
+ if (ret)
+ return ret;
+
+ return snd_soc_register_codec(dev, &adau1977_codec_driver,
+ &adau1977_dai, 1);
+
+err_poweroff:
+ adau1977_power_disable(adau1977);
+ return ret;
+
+}
+EXPORT_SYMBOL_GPL(adau1977_probe);
+
+static bool adau1977_register_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ADAU1977_REG_STATUS(0):
+ case ADAU1977_REG_STATUS(1):
+ case ADAU1977_REG_STATUS(2):
+ case ADAU1977_REG_STATUS(3):
+ case ADAU1977_REG_ADC_CLIP:
+ return true;
+ }
+
+ return false;
+}
+
+const struct regmap_config adau1977_regmap_config = {
+ .max_register = ADAU1977_REG_DC_HPF_CAL,
+ .volatile_reg = adau1977_register_volatile,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = adau1977_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(adau1977_reg_defaults),
+};
+EXPORT_SYMBOL_GPL(adau1977_regmap_config);
+
+MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1977.h b/sound/soc/codecs/adau1977.h
new file mode 100644
index 00000000000..95e714345a8
--- /dev/null
+++ b/sound/soc/codecs/adau1977.h
@@ -0,0 +1,37 @@
+/*
+ * ADAU1977/ADAU1978/ADAU1979 driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef __SOUND_SOC_CODECS_ADAU1977_H__
+#define __SOUND_SOC_CODECS_ADAU1977_H__
+
+#include <linux/regmap.h>
+
+struct device;
+
+enum adau1977_type {
+ ADAU1977,
+ ADAU1978,
+ ADAU1979,
+};
+
+int adau1977_probe(struct device *dev, struct regmap *regmap,
+ enum adau1977_type type, void (*switch_mode)(struct device *dev));
+
+extern const struct regmap_config adau1977_regmap_config;
+
+enum adau1977_clk_id {
+ ADAU1977_SYSCLK,
+};
+
+enum adau1977_sysclk_src {
+ ADAU1977_SYSCLK_SRC_MCLK,
+ ADAU1977_SYSCLK_SRC_LRCLK,
+};
+
+#endif
diff --git a/sound/soc/codecs/adav801.c b/sound/soc/codecs/adav801.c
new file mode 100644
index 00000000000..790fce33ab1
--- /dev/null
+++ b/sound/soc/codecs/adav801.c
@@ -0,0 +1,53 @@
+/*
+ * ADAV801 audio driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+
+#include <sound/soc.h>
+
+#include "adav80x.h"
+
+static const struct spi_device_id adav80x_spi_id[] = {
+ { "adav801", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, adav80x_spi_id);
+
+static int adav80x_spi_probe(struct spi_device *spi)
+{
+ struct regmap_config config;
+
+ config = adav80x_regmap_config;
+ config.read_flag_mask = 0x01;
+
+ return adav80x_bus_probe(&spi->dev, devm_regmap_init_spi(spi, &config));
+}
+
+static int adav80x_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ return 0;
+}
+
+static struct spi_driver adav80x_spi_driver = {
+ .driver = {
+ .name = "adav801",
+ .owner = THIS_MODULE,
+ },
+ .probe = adav80x_spi_probe,
+ .remove = adav80x_spi_remove,
+ .id_table = adav80x_spi_id,
+};
+module_spi_driver(adav80x_spi_driver);
+
+MODULE_DESCRIPTION("ASoC ADAV801 driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_AUTHOR("Yi Li <yi.li@analog.com>>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adav803.c b/sound/soc/codecs/adav803.c
new file mode 100644
index 00000000000..66d9fce34e6
--- /dev/null
+++ b/sound/soc/codecs/adav803.c
@@ -0,0 +1,50 @@
+/*
+ * ADAV803 audio driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+#include <sound/soc.h>
+
+#include "adav80x.h"
+
+static const struct i2c_device_id adav803_id[] = {
+ { "adav803", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adav803_id);
+
+static int adav803_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return adav80x_bus_probe(&client->dev,
+ devm_regmap_init_i2c(client, &adav80x_regmap_config));
+}
+
+static int adav803_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static struct i2c_driver adav803_driver = {
+ .driver = {
+ .name = "adav803",
+ .owner = THIS_MODULE,
+ },
+ .probe = adav803_probe,
+ .remove = adav803_remove,
+ .id_table = adav803_id,
+};
+module_i2c_driver(adav803_driver);
+
+MODULE_DESCRIPTION("ASoC ADAV803 driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_AUTHOR("Yi Li <yi.li@analog.com>>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index f78b27a7c46..c43b93fdf0d 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -8,17 +8,15 @@
* Licensed under the GPL-2 or later.
*/
-#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/spi/spi.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
-#include <sound/core.h>
+
#include <sound/pcm.h>
#include <sound/pcm_params.h>
-#include <sound/tlv.h>
#include <sound/soc.h>
+#include <sound/tlv.h>
#include "adav80x.h"
@@ -174,14 +172,14 @@ static ADAV80X_MUX_ENUM_DECL(adav80x_capture_enum, ADAV80X_DPATH_CTRL1, 3);
static ADAV80X_MUX_ENUM_DECL(adav80x_dac_enum, ADAV80X_DPATH_CTRL2, 3);
static const struct snd_kcontrol_new adav80x_aux_capture_mux_ctrl =
- SOC_DAPM_VALUE_ENUM("Route", adav80x_aux_capture_enum);
+ SOC_DAPM_ENUM("Route", adav80x_aux_capture_enum);
static const struct snd_kcontrol_new adav80x_capture_mux_ctrl =
- SOC_DAPM_VALUE_ENUM("Route", adav80x_capture_enum);
+ SOC_DAPM_ENUM("Route", adav80x_capture_enum);
static const struct snd_kcontrol_new adav80x_dac_mux_ctrl =
- SOC_DAPM_VALUE_ENUM("Route", adav80x_dac_enum);
+ SOC_DAPM_ENUM("Route", adav80x_dac_enum);
#define ADAV80X_MUX(name, ctrl) \
- SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+ SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = {
SND_SOC_DAPM_DAC("DAC", NULL, ADAV80X_DAC_CTRL1, 7, 1),
@@ -317,7 +315,7 @@ static int adav80x_set_deemph(struct snd_soc_codec *codec)
static int adav80x_put_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
unsigned int deemph = ucontrol->value.enumerated.item[0];
@@ -332,7 +330,7 @@ static int adav80x_put_deemph(struct snd_kcontrol *kcontrol,
static int adav80x_get_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = adav80x->deemph;
@@ -541,6 +539,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
unsigned int freq, int dir)
{
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
if (dir == SND_SOC_CLOCK_IN) {
switch (clk_id) {
@@ -573,7 +572,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2,
iclk_ctrl2);
- snd_soc_dapm_sync(&codec->dapm);
+ snd_soc_dapm_sync(dapm);
}
} else {
unsigned int mask;
@@ -600,17 +599,21 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
adav80x->sysclk_pd[clk_id] = false;
}
+ snd_soc_dapm_mutex_lock(dapm);
+
if (adav80x->sysclk_pd[0])
- snd_soc_dapm_disable_pin(&codec->dapm, "PLL1");
+ snd_soc_dapm_disable_pin_unlocked(dapm, "PLL1");
else
- snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
+ snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL1");
if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2])
- snd_soc_dapm_disable_pin(&codec->dapm, "PLL2");
+ snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2");
else
- snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2");
+ snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2");
- snd_soc_dapm_sync(&codec->dapm);
+ snd_soc_dapm_sync_unlocked(dapm);
+
+ snd_soc_dapm_mutex_unlock(dapm);
}
return 0;
@@ -722,7 +725,7 @@ static int adav80x_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = dai->codec;
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
- if (!codec->active || !adav80x->rate)
+ if (!snd_soc_codec_is_active(codec) || !adav80x->rate)
return 0;
return snd_pcm_hw_constraint_minmax(substream->runtime,
@@ -735,7 +738,7 @@ static void adav80x_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = dai->codec;
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
- if (!codec->active)
+ if (!snd_soc_codec_is_active(codec))
adav80x->rate = 0;
}
@@ -798,15 +801,8 @@ static struct snd_soc_dai_driver adav80x_dais[] = {
static int adav80x_probe(struct snd_soc_codec *codec)
{
- int ret;
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
- ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
- if (ret) {
- dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
/* Force PLLs on for SYSCLK output */
snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2");
@@ -864,39 +860,26 @@ static struct snd_soc_codec_driver adav80x_codec_driver = {
.num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes),
};
-static int adav80x_bus_probe(struct device *dev, struct regmap *regmap)
+int adav80x_bus_probe(struct device *dev, struct regmap *regmap)
{
struct adav80x *adav80x;
- int ret;
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL);
+ adav80x = devm_kzalloc(dev, sizeof(*adav80x), GFP_KERNEL);
if (!adav80x)
return -ENOMEM;
-
dev_set_drvdata(dev, adav80x);
adav80x->regmap = regmap;
- ret = snd_soc_register_codec(dev, &adav80x_codec_driver,
+ return snd_soc_register_codec(dev, &adav80x_codec_driver,
adav80x_dais, ARRAY_SIZE(adav80x_dais));
- if (ret)
- kfree(adav80x);
-
- return ret;
-}
-
-static int adav80x_bus_remove(struct device *dev)
-{
- snd_soc_unregister_codec(dev);
- kfree(dev_get_drvdata(dev));
- return 0;
}
+EXPORT_SYMBOL_GPL(adav80x_bus_probe);
-#if defined(CONFIG_SPI_MASTER)
-static const struct regmap_config adav80x_spi_regmap_config = {
+const struct regmap_config adav80x_regmap_config = {
.val_bits = 8,
.pad_bits = 1,
.reg_bits = 7,
@@ -908,105 +891,7 @@ static const struct regmap_config adav80x_spi_regmap_config = {
.reg_defaults = adav80x_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults),
};
-
-static const struct spi_device_id adav80x_spi_id[] = {
- { "adav801", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(spi, adav80x_spi_id);
-
-static int adav80x_spi_probe(struct spi_device *spi)
-{
- return adav80x_bus_probe(&spi->dev,
- devm_regmap_init_spi(spi, &adav80x_spi_regmap_config));
-}
-
-static int adav80x_spi_remove(struct spi_device *spi)
-{
- return adav80x_bus_remove(&spi->dev);
-}
-
-static struct spi_driver adav80x_spi_driver = {
- .driver = {
- .name = "adav801",
- .owner = THIS_MODULE,
- },
- .probe = adav80x_spi_probe,
- .remove = adav80x_spi_remove,
- .id_table = adav80x_spi_id,
-};
-#endif
-
-#if IS_ENABLED(CONFIG_I2C)
-static const struct regmap_config adav80x_i2c_regmap_config = {
- .val_bits = 8,
- .pad_bits = 1,
- .reg_bits = 7,
-
- .max_register = ADAV80X_PLL_OUTE,
-
- .cache_type = REGCACHE_RBTREE,
- .reg_defaults = adav80x_reg_defaults,
- .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults),
-};
-
-static const struct i2c_device_id adav80x_i2c_id[] = {
- { "adav803", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id);
-
-static int adav80x_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- return adav80x_bus_probe(&client->dev,
- devm_regmap_init_i2c(client, &adav80x_i2c_regmap_config));
-}
-
-static int adav80x_i2c_remove(struct i2c_client *client)
-{
- return adav80x_bus_remove(&client->dev);
-}
-
-static struct i2c_driver adav80x_i2c_driver = {
- .driver = {
- .name = "adav803",
- .owner = THIS_MODULE,
- },
- .probe = adav80x_i2c_probe,
- .remove = adav80x_i2c_remove,
- .id_table = adav80x_i2c_id,
-};
-#endif
-
-static int __init adav80x_init(void)
-{
- int ret = 0;
-
-#if IS_ENABLED(CONFIG_I2C)
- ret = i2c_add_driver(&adav80x_i2c_driver);
- if (ret)
- return ret;
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
- ret = spi_register_driver(&adav80x_spi_driver);
-#endif
-
- return ret;
-}
-module_init(adav80x_init);
-
-static void __exit adav80x_exit(void)
-{
-#if IS_ENABLED(CONFIG_I2C)
- i2c_del_driver(&adav80x_i2c_driver);
-#endif
-#if defined(CONFIG_SPI_MASTER)
- spi_unregister_driver(&adav80x_spi_driver);
-#endif
-}
-module_exit(adav80x_exit);
+EXPORT_SYMBOL_GPL(adav80x_regmap_config);
MODULE_DESCRIPTION("ASoC ADAV80x driver");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
diff --git a/sound/soc/codecs/adav80x.h b/sound/soc/codecs/adav80x.h
index adb0fc76d4e..8a1d7c09dca 100644
--- a/sound/soc/codecs/adav80x.h
+++ b/sound/soc/codecs/adav80x.h
@@ -9,6 +9,13 @@
#ifndef _ADAV80X_H
#define _ADAV80X_H
+#include <linux/regmap.h>
+
+struct device;
+
+extern const struct regmap_config adav80x_regmap_config;
+int adav80x_bus_probe(struct device *dev, struct regmap *regmap);
+
enum adav80x_pll_src {
ADAV80X_PLL_SRC_XIN,
ADAV80X_PLL_SRC_XTAL,
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index b4819dcd4f4..1fd7f72b2a6 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -11,13 +11,14 @@
#include <linux/module.h>
#include <linux/slab.h>
-#include <sound/core.h>
-#include <sound/soc.h>
-#include <sound/initval.h>
#include <linux/spi/spi.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
#include <sound/asoundef.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
/* AK4104 registers addresses */
#define AK4104_REG_CONTROL1 0x00
@@ -47,6 +48,7 @@
struct ak4104_private {
struct regmap *regmap;
+ struct regulator *regulator;
};
static const struct snd_soc_dapm_widget ak4104_dapm_widgets[] = {
@@ -174,22 +176,30 @@ static int ak4104_probe(struct snd_soc_codec *codec)
struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
int ret;
- codec->control_data = ak4104->regmap;
+ ret = regulator_enable(ak4104->regulator);
+ if (ret < 0) {
+ dev_err(codec->dev, "Unable to enable regulator: %d\n", ret);
+ return ret;
+ }
/* set power-up and non-reset bits */
ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
if (ret < 0)
- return ret;
+ goto exit_disable_regulator;
/* enable transmitter */
ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
AK4104_TX_TXE, AK4104_TX_TXE);
if (ret < 0)
- return ret;
+ goto exit_disable_regulator;
return 0;
+
+exit_disable_regulator:
+ regulator_disable(ak4104->regulator);
+ return ret;
}
static int ak4104_remove(struct snd_soc_codec *codec)
@@ -198,13 +208,42 @@ static int ak4104_remove(struct snd_soc_codec *codec)
regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
+ regulator_disable(ak4104->regulator);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int ak4104_soc_suspend(struct snd_soc_codec *codec)
+{
+ struct ak4104_private *priv = snd_soc_codec_get_drvdata(codec);
+
+ regulator_disable(priv->regulator);
return 0;
}
+static int ak4104_soc_resume(struct snd_soc_codec *codec)
+{
+ struct ak4104_private *priv = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ ret = regulator_enable(priv->regulator);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+#else
+#define ak4104_soc_suspend NULL
+#define ak4104_soc_resume NULL
+#endif /* CONFIG_PM */
+
static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
- .probe = ak4104_probe,
- .remove = ak4104_remove,
+ .probe = ak4104_probe,
+ .remove = ak4104_remove,
+ .suspend = ak4104_soc_suspend,
+ .resume = ak4104_soc_resume,
.dapm_widgets = ak4104_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(ak4104_dapm_widgets),
@@ -241,6 +280,13 @@ static int ak4104_spi_probe(struct spi_device *spi)
if (ak4104 == NULL)
return -ENOMEM;
+ ak4104->regulator = devm_regulator_get(&spi->dev, "vdd");
+ if (IS_ERR(ak4104->regulator)) {
+ ret = PTR_ERR(ak4104->regulator);
+ dev_err(&spi->dev, "Unable to get Vdd regulator: %d\n", ret);
+ return ret;
+ }
+
ak4104->regmap = devm_regmap_init_spi(spi, &ak4104_regmap);
if (IS_ERR(ak4104->regmap)) {
ret = PTR_ERR(ak4104->regmap);
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 684fe910669..30e297890fe 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -388,15 +388,6 @@ static int ak4535_resume(struct snd_soc_codec *codec)
static int ak4535_probe(struct snd_soc_codec *codec)
{
- struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- codec->control_data = ak4535->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
/* power on device */
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index 94cbe508dd3..7afe8f48208 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -74,7 +74,7 @@ static int ak4641_set_deemph(struct snd_soc_codec *codec)
static int ak4641_put_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec);
int deemph = ucontrol->value.enumerated.item[0];
@@ -89,7 +89,7 @@ static int ak4641_put_deemph(struct snd_kcontrol *kcontrol,
static int ak4641_get_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = ak4641->deemph;
@@ -113,14 +113,14 @@ static const DECLARE_TLV_DB_SCALE(alc_tlv, -800, 50, 0);
static const DECLARE_TLV_DB_SCALE(aux_in_tlv, -2100, 300, 0);
-static const struct soc_enum ak4641_mono_out_enum =
- SOC_ENUM_SINGLE(AK4641_SIG1, 6, 2, ak4641_mono_out);
-static const struct soc_enum ak4641_hp_out_enum =
- SOC_ENUM_SINGLE(AK4641_MODE2, 2, 2, ak4641_hp_out);
-static const struct soc_enum ak4641_mic_select_enum =
- SOC_ENUM_SINGLE(AK4641_MIC, 1, 2, ak4641_mic_select);
-static const struct soc_enum ak4641_mic_or_dac_enum =
- SOC_ENUM_SINGLE(AK4641_BTIF, 4, 2, ak4641_mic_or_dac);
+static SOC_ENUM_SINGLE_DECL(ak4641_mono_out_enum,
+ AK4641_SIG1, 6, ak4641_mono_out);
+static SOC_ENUM_SINGLE_DECL(ak4641_hp_out_enum,
+ AK4641_MODE2, 2, ak4641_hp_out);
+static SOC_ENUM_SINGLE_DECL(ak4641_mic_select_enum,
+ AK4641_MIC, 1, ak4641_mic_select);
+static SOC_ENUM_SINGLE_DECL(ak4641_mic_or_dac_enum,
+ AK4641_BTIF, 4, ak4641_mic_or_dac);
static const struct snd_kcontrol_new ak4641_snd_controls[] = {
SOC_ENUM("Mono 1 Output", ak4641_mono_out_enum),
@@ -519,14 +519,6 @@ static int ak4641_resume(struct snd_soc_codec *codec)
static int ak4641_probe(struct snd_soc_codec *codec)
{
- int ret;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
/* power on device */
ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 1f646c6e90c..3ba4c0f1141 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -98,7 +98,7 @@
#define MGAIN0 (1 << 0) /* MIC amp gain*/
/* TIMER */
-#define ZTM(param) ((param & 0x3) << 4) /* ALC Zoro Crossing TimeOut */
+#define ZTM(param) ((param & 0x3) << 4) /* ALC Zero Crossing TimeOut */
#define WTM(param) (((param & 0x4) << 4) | ((param & 0x3) << 2))
/* ALC_CTL1 */
@@ -134,6 +134,15 @@
/* MD_CTL4 */
#define DACH (1 << 0)
+struct ak4642_drvdata {
+ const struct regmap_config *regmap_config;
+ int extended_frequencies;
+};
+
+struct ak4642_priv {
+ const struct ak4642_drvdata *drvdata;
+};
+
/*
* Playback Volume (table 39)
*
@@ -148,6 +157,8 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
SOC_DOUBLE_R_TLV("Digital Playback Volume", L_DVC, R_DVC,
0, 0xFF, 1, out_tlv),
+ SOC_SINGLE("ALC Capture Switch", ALC_CTL1, 5, 1, 0),
+ SOC_SINGLE("ALC Capture ZC Switch", ALC_CTL1, 4, 1, 1),
};
static const struct snd_kcontrol_new ak4642_headphone_control =
@@ -287,7 +298,9 @@ static int ak4642_dai_set_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
+ struct ak4642_priv *priv = snd_soc_codec_get_drvdata(codec);
u8 pll;
+ int extended_freq = 0;
switch (freq) {
case 11289600:
@@ -308,9 +321,25 @@ static int ak4642_dai_set_sysclk(struct snd_soc_dai *codec_dai,
case 27000000:
pll = PLL3 | PLL2 | PLL0;
break;
+ case 19200000:
+ pll = PLL3;
+ extended_freq = 1;
+ break;
+ case 13000000:
+ pll = PLL3 | PLL2 | PLL1;
+ extended_freq = 1;
+ break;
+ case 26000000:
+ pll = PLL3 | PLL2 | PLL1 | PLL0;
+ extended_freq = 1;
+ break;
default:
return -EINVAL;
}
+
+ if (extended_freq && !priv->drvdata->extended_frequencies)
+ return -EINVAL;
+
snd_soc_update_bits(codec, MD_CTL1, PLL_MASK, pll);
return 0;
@@ -465,14 +494,6 @@ static int ak4642_resume(struct snd_soc_codec *codec)
static int ak4642_probe(struct snd_soc_codec *codec)
{
- int ret;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -513,30 +534,52 @@ static const struct regmap_config ak4648_regmap = {
.num_reg_defaults = ARRAY_SIZE(ak4648_reg),
};
+static const struct ak4642_drvdata ak4642_drvdata = {
+ .regmap_config = &ak4642_regmap,
+};
+
+static const struct ak4642_drvdata ak4643_drvdata = {
+ .regmap_config = &ak4642_regmap,
+};
+
+static const struct ak4642_drvdata ak4648_drvdata = {
+ .regmap_config = &ak4648_regmap,
+ .extended_frequencies = 1,
+};
+
static struct of_device_id ak4642_of_match[];
static int ak4642_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct device_node *np = i2c->dev.of_node;
- const struct regmap_config *regmap_config = NULL;
+ const struct ak4642_drvdata *drvdata = NULL;
struct regmap *regmap;
+ struct ak4642_priv *priv;
if (np) {
const struct of_device_id *of_id;
of_id = of_match_device(ak4642_of_match, &i2c->dev);
if (of_id)
- regmap_config = of_id->data;
+ drvdata = of_id->data;
} else {
- regmap_config = (const struct regmap_config *)id->driver_data;
+ drvdata = (const struct ak4642_drvdata *)id->driver_data;
}
- if (!regmap_config) {
+ if (!drvdata) {
dev_err(&i2c->dev, "Unknown device type\n");
return -EINVAL;
}
- regmap = devm_regmap_init_i2c(i2c, regmap_config);
+ priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->drvdata = drvdata;
+
+ i2c_set_clientdata(i2c, priv);
+
+ regmap = devm_regmap_init_i2c(i2c, drvdata->regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
@@ -551,17 +594,17 @@ static int ak4642_i2c_remove(struct i2c_client *client)
}
static struct of_device_id ak4642_of_match[] = {
- { .compatible = "asahi-kasei,ak4642", .data = &ak4642_regmap},
- { .compatible = "asahi-kasei,ak4643", .data = &ak4642_regmap},
- { .compatible = "asahi-kasei,ak4648", .data = &ak4648_regmap},
+ { .compatible = "asahi-kasei,ak4642", .data = &ak4642_drvdata},
+ { .compatible = "asahi-kasei,ak4643", .data = &ak4643_drvdata},
+ { .compatible = "asahi-kasei,ak4648", .data = &ak4648_drvdata},
{},
};
MODULE_DEVICE_TABLE(of, ak4642_of_match);
static const struct i2c_device_id ak4642_i2c_id[] = {
- { "ak4642", (kernel_ulong_t)&ak4642_regmap },
- { "ak4643", (kernel_ulong_t)&ak4642_regmap },
- { "ak4648", (kernel_ulong_t)&ak4648_regmap },
+ { "ak4642", (kernel_ulong_t)&ak4642_drvdata },
+ { "ak4643", (kernel_ulong_t)&ak4643_drvdata },
+ { "ak4648", (kernel_ulong_t)&ak4648_drvdata },
{ }
};
MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index 25bdf6ad4a5..998fa0c5a0b 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/delay.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/soc.h>
#include <sound/initval.h>
@@ -23,104 +24,99 @@
#include "ak4671.h"
-/* codec private data */
-struct ak4671_priv {
- enum snd_soc_control_type control_type;
-};
-
/* ak4671 register cache & default register settings */
-static const u8 ak4671_reg[AK4671_CACHEREGNUM] = {
- 0x00, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */
- 0xf6, /* AK4671_PLL_MODE_SELECT0 (0x01) */
- 0x00, /* AK4671_PLL_MODE_SELECT1 (0x02) */
- 0x02, /* AK4671_FORMAT_SELECT (0x03) */
- 0x00, /* AK4671_MIC_SIGNAL_SELECT (0x04) */
- 0x55, /* AK4671_MIC_AMP_GAIN (0x05) */
- 0x00, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */
- 0x00, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */
- 0xb5, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */
- 0x00, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */
- 0x00, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */
- 0x00, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */
- 0x00, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */
- 0x00, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */
- 0x00, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */
- 0x00, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */
- 0x00, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */
- 0x80, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */
- 0x91, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */
- 0x91, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */
- 0xe1, /* AK4671_ALC_REFERENCE_SELECT (0x14) */
- 0x00, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */
- 0x00, /* AK4671_ALC_TIMER_SELECT (0x16) */
- 0x00, /* AK4671_ALC_MODE_CONTROL (0x17) */
- 0x02, /* AK4671_MODE_CONTROL1 (0x18) */
- 0x01, /* AK4671_MODE_CONTROL2 (0x19) */
- 0x18, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */
- 0x18, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */
- 0x00, /* AK4671_SIDETONE_A_CONTROL (0x1c) */
- 0x02, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */
- 0x00, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */
- 0x00, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */
- 0x00, /* AK4671_FIL3_COEFFICIENT2 (0x20) */
- 0x00, /* AK4671_FIL3_COEFFICIENT3 (0x21) */
- 0x00, /* AK4671_EQ_COEFFICIENT0 (0x22) */
- 0x00, /* AK4671_EQ_COEFFICIENT1 (0x23) */
- 0x00, /* AK4671_EQ_COEFFICIENT2 (0x24) */
- 0x00, /* AK4671_EQ_COEFFICIENT3 (0x25) */
- 0x00, /* AK4671_EQ_COEFFICIENT4 (0x26) */
- 0x00, /* AK4671_EQ_COEFFICIENT5 (0x27) */
- 0xa9, /* AK4671_FIL1_COEFFICIENT0 (0x28) */
- 0x1f, /* AK4671_FIL1_COEFFICIENT1 (0x29) */
- 0xad, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */
- 0x20, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */
- 0x00, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */
- 0x00, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */
- 0x00, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */
- 0x00, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */
- 0x00, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */
- 0x00, /* this register not used */
- 0x00, /* AK4671_E1_COEFFICIENT0 (0x32) */
- 0x00, /* AK4671_E1_COEFFICIENT1 (0x33) */
- 0x00, /* AK4671_E1_COEFFICIENT2 (0x34) */
- 0x00, /* AK4671_E1_COEFFICIENT3 (0x35) */
- 0x00, /* AK4671_E1_COEFFICIENT4 (0x36) */
- 0x00, /* AK4671_E1_COEFFICIENT5 (0x37) */
- 0x00, /* AK4671_E2_COEFFICIENT0 (0x38) */
- 0x00, /* AK4671_E2_COEFFICIENT1 (0x39) */
- 0x00, /* AK4671_E2_COEFFICIENT2 (0x3a) */
- 0x00, /* AK4671_E2_COEFFICIENT3 (0x3b) */
- 0x00, /* AK4671_E2_COEFFICIENT4 (0x3c) */
- 0x00, /* AK4671_E2_COEFFICIENT5 (0x3d) */
- 0x00, /* AK4671_E3_COEFFICIENT0 (0x3e) */
- 0x00, /* AK4671_E3_COEFFICIENT1 (0x3f) */
- 0x00, /* AK4671_E3_COEFFICIENT2 (0x40) */
- 0x00, /* AK4671_E3_COEFFICIENT3 (0x41) */
- 0x00, /* AK4671_E3_COEFFICIENT4 (0x42) */
- 0x00, /* AK4671_E3_COEFFICIENT5 (0x43) */
- 0x00, /* AK4671_E4_COEFFICIENT0 (0x44) */
- 0x00, /* AK4671_E4_COEFFICIENT1 (0x45) */
- 0x00, /* AK4671_E4_COEFFICIENT2 (0x46) */
- 0x00, /* AK4671_E4_COEFFICIENT3 (0x47) */
- 0x00, /* AK4671_E4_COEFFICIENT4 (0x48) */
- 0x00, /* AK4671_E4_COEFFICIENT5 (0x49) */
- 0x00, /* AK4671_E5_COEFFICIENT0 (0x4a) */
- 0x00, /* AK4671_E5_COEFFICIENT1 (0x4b) */
- 0x00, /* AK4671_E5_COEFFICIENT2 (0x4c) */
- 0x00, /* AK4671_E5_COEFFICIENT3 (0x4d) */
- 0x00, /* AK4671_E5_COEFFICIENT4 (0x4e) */
- 0x00, /* AK4671_E5_COEFFICIENT5 (0x4f) */
- 0x88, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */
- 0x88, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */
- 0x08, /* AK4671_EQ_CONTRO_10KHZ (0x52) */
- 0x00, /* AK4671_PCM_IF_CONTROL0 (0x53) */
- 0x00, /* AK4671_PCM_IF_CONTROL1 (0x54) */
- 0x00, /* AK4671_PCM_IF_CONTROL2 (0x55) */
- 0x18, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */
- 0x18, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */
- 0x00, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */
- 0x00, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */
- 0x00, /* AK4671_SAR_ADC_CONTROL (0x5a) */
+static const struct reg_default ak4671_reg_defaults[] = {
+ { 0x00, 0x00 }, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */
+ { 0x01, 0xf6 }, /* AK4671_PLL_MODE_SELECT0 (0x01) */
+ { 0x02, 0x00 }, /* AK4671_PLL_MODE_SELECT1 (0x02) */
+ { 0x03, 0x02 }, /* AK4671_FORMAT_SELECT (0x03) */
+ { 0x04, 0x00 }, /* AK4671_MIC_SIGNAL_SELECT (0x04) */
+ { 0x05, 0x55 }, /* AK4671_MIC_AMP_GAIN (0x05) */
+ { 0x06, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */
+ { 0x07, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */
+ { 0x08, 0xb5 }, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */
+ { 0x09, 0x00 }, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */
+ { 0x0a, 0x00 }, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */
+ { 0x0b, 0x00 }, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */
+ { 0x0c, 0x00 }, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */
+ { 0x0d, 0x00 }, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */
+ { 0x0e, 0x00 }, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */
+ { 0x0f, 0x00 }, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */
+ { 0x10, 0x00 }, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */
+ { 0x11, 0x80 }, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */
+ { 0x12, 0x91 }, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */
+ { 0x13, 0x91 }, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */
+ { 0x14, 0xe1 }, /* AK4671_ALC_REFERENCE_SELECT (0x14) */
+ { 0x15, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */
+ { 0x16, 0x00 }, /* AK4671_ALC_TIMER_SELECT (0x16) */
+ { 0x17, 0x00 }, /* AK4671_ALC_MODE_CONTROL (0x17) */
+ { 0x18, 0x02 }, /* AK4671_MODE_CONTROL1 (0x18) */
+ { 0x19, 0x01 }, /* AK4671_MODE_CONTROL2 (0x19) */
+ { 0x1a, 0x18 }, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */
+ { 0x1b, 0x18 }, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */
+ { 0x1c, 0x00 }, /* AK4671_SIDETONE_A_CONTROL (0x1c) */
+ { 0x1d, 0x02 }, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */
+ { 0x1e, 0x00 }, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */
+ { 0x1f, 0x00 }, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */
+ { 0x20, 0x00 }, /* AK4671_FIL3_COEFFICIENT2 (0x20) */
+ { 0x21, 0x00 }, /* AK4671_FIL3_COEFFICIENT3 (0x21) */
+ { 0x22, 0x00 }, /* AK4671_EQ_COEFFICIENT0 (0x22) */
+ { 0x23, 0x00 }, /* AK4671_EQ_COEFFICIENT1 (0x23) */
+ { 0x24, 0x00 }, /* AK4671_EQ_COEFFICIENT2 (0x24) */
+ { 0x25, 0x00 }, /* AK4671_EQ_COEFFICIENT3 (0x25) */
+ { 0x26, 0x00 }, /* AK4671_EQ_COEFFICIENT4 (0x26) */
+ { 0x27, 0x00 }, /* AK4671_EQ_COEFFICIENT5 (0x27) */
+ { 0x28, 0xa9 }, /* AK4671_FIL1_COEFFICIENT0 (0x28) */
+ { 0x29, 0x1f }, /* AK4671_FIL1_COEFFICIENT1 (0x29) */
+ { 0x2a, 0xad }, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */
+ { 0x2b, 0x20 }, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */
+ { 0x2c, 0x00 }, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */
+ { 0x2d, 0x00 }, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */
+ { 0x2e, 0x00 }, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */
+ { 0x2f, 0x00 }, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */
+ { 0x30, 0x00 }, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */
+
+ { 0x32, 0x00 }, /* AK4671_E1_COEFFICIENT0 (0x32) */
+ { 0x33, 0x00 }, /* AK4671_E1_COEFFICIENT1 (0x33) */
+ { 0x34, 0x00 }, /* AK4671_E1_COEFFICIENT2 (0x34) */
+ { 0x35, 0x00 }, /* AK4671_E1_COEFFICIENT3 (0x35) */
+ { 0x36, 0x00 }, /* AK4671_E1_COEFFICIENT4 (0x36) */
+ { 0x37, 0x00 }, /* AK4671_E1_COEFFICIENT5 (0x37) */
+ { 0x38, 0x00 }, /* AK4671_E2_COEFFICIENT0 (0x38) */
+ { 0x39, 0x00 }, /* AK4671_E2_COEFFICIENT1 (0x39) */
+ { 0x3a, 0x00 }, /* AK4671_E2_COEFFICIENT2 (0x3a) */
+ { 0x3b, 0x00 }, /* AK4671_E2_COEFFICIENT3 (0x3b) */
+ { 0x3c, 0x00 }, /* AK4671_E2_COEFFICIENT4 (0x3c) */
+ { 0x3d, 0x00 }, /* AK4671_E2_COEFFICIENT5 (0x3d) */
+ { 0x3e, 0x00 }, /* AK4671_E3_COEFFICIENT0 (0x3e) */
+ { 0x3f, 0x00 }, /* AK4671_E3_COEFFICIENT1 (0x3f) */
+ { 0x40, 0x00 }, /* AK4671_E3_COEFFICIENT2 (0x40) */
+ { 0x41, 0x00 }, /* AK4671_E3_COEFFICIENT3 (0x41) */
+ { 0x42, 0x00 }, /* AK4671_E3_COEFFICIENT4 (0x42) */
+ { 0x43, 0x00 }, /* AK4671_E3_COEFFICIENT5 (0x43) */
+ { 0x44, 0x00 }, /* AK4671_E4_COEFFICIENT0 (0x44) */
+ { 0x45, 0x00 }, /* AK4671_E4_COEFFICIENT1 (0x45) */
+ { 0x46, 0x00 }, /* AK4671_E4_COEFFICIENT2 (0x46) */
+ { 0x47, 0x00 }, /* AK4671_E4_COEFFICIENT3 (0x47) */
+ { 0x48, 0x00 }, /* AK4671_E4_COEFFICIENT4 (0x48) */
+ { 0x49, 0x00 }, /* AK4671_E4_COEFFICIENT5 (0x49) */
+ { 0x4a, 0x00 }, /* AK4671_E5_COEFFICIENT0 (0x4a) */
+ { 0x4b, 0x00 }, /* AK4671_E5_COEFFICIENT1 (0x4b) */
+ { 0x4c, 0x00 }, /* AK4671_E5_COEFFICIENT2 (0x4c) */
+ { 0x4d, 0x00 }, /* AK4671_E5_COEFFICIENT3 (0x4d) */
+ { 0x4e, 0x00 }, /* AK4671_E5_COEFFICIENT4 (0x4e) */
+ { 0x4f, 0x00 }, /* AK4671_E5_COEFFICIENT5 (0x4f) */
+ { 0x50, 0x88 }, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */
+ { 0x51, 0x88 }, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */
+ { 0x52, 0x08 }, /* AK4671_EQ_CONTRO_10KHZ (0x52) */
+ { 0x53, 0x00 }, /* AK4671_PCM_IF_CONTROL0 (0x53) */
+ { 0x54, 0x00 }, /* AK4671_PCM_IF_CONTROL1 (0x54) */
+ { 0x55, 0x00 }, /* AK4671_PCM_IF_CONTROL2 (0x55) */
+ { 0x56, 0x18 }, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */
+ { 0x57, 0x18 }, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */
+ { 0x58, 0x00 }, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */
+ { 0x59, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */
+ { 0x5a, 0x00 }, /* AK4671_SAR_ADC_CONTROL (0x5a) */
};
/*
@@ -241,19 +237,17 @@ static const struct snd_kcontrol_new ak4671_rout3_mixer_controls[] = {
/* Input MUXs */
static const char *ak4671_lin_mux_texts[] =
{"LIN1", "LIN2", "LIN3", "LIN4"};
-static const struct soc_enum ak4671_lin_mux_enum =
- SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 0,
- ARRAY_SIZE(ak4671_lin_mux_texts),
- ak4671_lin_mux_texts);
+static SOC_ENUM_SINGLE_DECL(ak4671_lin_mux_enum,
+ AK4671_MIC_SIGNAL_SELECT, 0,
+ ak4671_lin_mux_texts);
static const struct snd_kcontrol_new ak4671_lin_mux_control =
SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum);
static const char *ak4671_rin_mux_texts[] =
{"RIN1", "RIN2", "RIN3", "RIN4"};
-static const struct soc_enum ak4671_rin_mux_enum =
- SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 2,
- ARRAY_SIZE(ak4671_rin_mux_texts),
- ak4671_rin_mux_texts);
+static SOC_ENUM_SINGLE_DECL(ak4671_rin_mux_enum,
+ AK4671_MIC_SIGNAL_SELECT, 2,
+ ak4671_rin_mux_texts);
static const struct snd_kcontrol_new ak4671_rin_mux_control =
SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum);
@@ -619,21 +613,7 @@ static struct snd_soc_dai_driver ak4671_dai = {
static int ak4671_probe(struct snd_soc_codec *codec)
{
- struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
- snd_soc_add_codec_controls(codec, ak4671_snd_controls,
- ARRAY_SIZE(ak4671_snd_controls));
-
- ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- return ret;
+ return ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
}
static int ak4671_remove(struct snd_soc_codec *codec)
@@ -646,28 +626,36 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
.probe = ak4671_probe,
.remove = ak4671_remove,
.set_bias_level = ak4671_set_bias_level,
- .reg_cache_size = AK4671_CACHEREGNUM,
- .reg_word_size = sizeof(u8),
- .reg_cache_default = ak4671_reg,
+ .controls = ak4671_snd_controls,
+ .num_controls = ARRAY_SIZE(ak4671_snd_controls),
.dapm_widgets = ak4671_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets),
.dapm_routes = ak4671_intercon,
.num_dapm_routes = ARRAY_SIZE(ak4671_intercon),
};
+static const struct regmap_config ak4671_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = AK4671_SAR_ADC_CONTROL,
+ .reg_defaults = ak4671_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(ak4671_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+};
+
static int ak4671_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct ak4671_priv *ak4671;
+ struct regmap *regmap;
int ret;
- ak4671 = devm_kzalloc(&client->dev, sizeof(struct ak4671_priv),
- GFP_KERNEL);
- if (ak4671 == NULL)
- return -ENOMEM;
-
- i2c_set_clientdata(client, ak4671);
- ak4671->control_type = SND_SOC_I2C;
+ regmap = devm_regmap_init_i2c(client, &ak4671_regmap);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(&client->dev, "Failed to create regmap: %d\n", ret);
+ return ret;
+ }
ret = snd_soc_register_codec(&client->dev,
&soc_codec_dev_ak4671, &ak4671_dai, 1);
diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h
index 61cb7ab7552..394a34d3f50 100644
--- a/sound/soc/codecs/ak4671.h
+++ b/sound/soc/codecs/ak4671.h
@@ -105,8 +105,6 @@
#define AK4671_DIGITAL_MIXING_CONTROL2 0x59
#define AK4671_SAR_ADC_CONTROL 0x5a
-#define AK4671_CACHEREGNUM (AK4671_SAR_ADC_CONTROL + 1)
-
/* Bitfield Definitions */
/* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index d3036283482..9d0755aa1d1 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -21,7 +21,9 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
+#include <linux/of.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -38,26 +40,13 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)");
/* codec private data */
struct alc5623_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
u8 id;
unsigned int sysclk;
- u16 reg_cache[ALC5623_VENDOR_ID2+2];
unsigned int add_ctrl;
unsigned int jack_det_ctrl;
};
-static void alc5623_fill_cache(struct snd_soc_codec *codec)
-{
- int i, step = codec->driver->reg_cache_step;
- u16 *cache = codec->reg_cache;
-
- /* not really efficient ... */
- codec->cache_bypass = 1;
- for (i = 0 ; i < codec->driver->reg_cache_size ; i += step)
- cache[i] = snd_soc_read(codec, i);
- codec->cache_bypass = 0;
-}
-
static inline int alc5623_reset(struct snd_soc_codec *codec)
{
return snd_soc_write(codec, ALC5623_RESET, 0);
@@ -228,32 +217,37 @@ static const char *alc5623_aux_out_input_sel[] = {
"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
/* auxout output mux */
-static const struct soc_enum alc5623_aux_out_input_enum =
-SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 6, 4, alc5623_aux_out_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5623_aux_out_input_enum,
+ ALC5623_OUTPUT_MIXER_CTRL, 6,
+ alc5623_aux_out_input_sel);
static const struct snd_kcontrol_new alc5623_auxout_mux_controls =
SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum);
/* speaker output mux */
-static const struct soc_enum alc5623_spkout_input_enum =
-SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 10, 4, alc5623_spkout_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5623_spkout_input_enum,
+ ALC5623_OUTPUT_MIXER_CTRL, 10,
+ alc5623_spkout_input_sel);
static const struct snd_kcontrol_new alc5623_spkout_mux_controls =
SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum);
/* headphone left output mux */
-static const struct soc_enum alc5623_hpl_out_input_enum =
-SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 9, 2, alc5623_hpl_out_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5623_hpl_out_input_enum,
+ ALC5623_OUTPUT_MIXER_CTRL, 9,
+ alc5623_hpl_out_input_sel);
static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls =
SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum);
/* headphone right output mux */
-static const struct soc_enum alc5623_hpr_out_input_enum =
-SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 8, 2, alc5623_hpr_out_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5623_hpr_out_input_enum,
+ ALC5623_OUTPUT_MIXER_CTRL, 8,
+ alc5623_hpr_out_input_sel);
static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls =
SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum);
/* speaker output N select */
-static const struct soc_enum alc5623_spk_n_sour_enum =
-SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 14, 4, alc5623_spk_n_sour_sel);
+static SOC_ENUM_SINGLE_DECL(alc5623_spk_n_sour_enum,
+ ALC5623_OUTPUT_MIXER_CTRL, 14,
+ alc5623_spk_n_sour_sel);
static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls =
SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum);
@@ -338,8 +332,9 @@ SND_SOC_DAPM_VMID("Vmid"),
};
static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"};
-static const struct soc_enum alc5623_amp_enum =
- SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 13, 2, alc5623_amp_names);
+static SOC_ENUM_SINGLE_DECL(alc5623_amp_enum,
+ ALC5623_OUTPUT_MIXER_CTRL, 13,
+ alc5623_amp_names);
static const struct snd_kcontrol_new alc5623_amp_mux_controls =
SOC_DAPM_ENUM("Route", alc5623_amp_enum);
@@ -869,18 +864,28 @@ static struct snd_soc_dai_driver alc5623_dai = {
static int alc5623_suspend(struct snd_soc_codec *codec)
{
+ struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
+
alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ regcache_cache_only(alc5623->regmap, true);
+
return 0;
}
static int alc5623_resume(struct snd_soc_codec *codec)
{
- int i, step = codec->driver->reg_cache_step;
- u16 *cache = codec->reg_cache;
+ struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
+ int ret;
/* Sync reg_cache with the hardware */
- for (i = 2 ; i < codec->driver->reg_cache_size ; i += step)
- snd_soc_write(codec, i, cache[i]);
+ regcache_cache_only(alc5623->regmap, false);
+ ret = regcache_sync(alc5623->regmap);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to sync register cache: %d\n",
+ ret);
+ regcache_cache_only(alc5623->regmap, true);
+ return ret;
+ }
alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -898,16 +903,8 @@ static int alc5623_probe(struct snd_soc_codec *codec)
{
struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
alc5623_reset(codec);
- alc5623_fill_cache(codec);
/* power on device */
alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -964,7 +961,7 @@ static int alc5623_probe(struct snd_soc_codec *codec)
return -EINVAL;
}
- return ret;
+ return 0;
}
/* power down chip */
@@ -980,9 +977,15 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
.suspend = alc5623_suspend,
.resume = alc5623_resume,
.set_bias_level = alc5623_set_bias_level,
- .reg_cache_size = ALC5623_VENDOR_ID2+2,
- .reg_word_size = sizeof(u16),
- .reg_cache_step = 2,
+};
+
+static const struct regmap_config alc5623_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .reg_stride = 2,
+
+ .max_register = ALC5623_VENDOR_ID2,
+ .cache_type = REGCACHE_RBTREE,
};
/*
@@ -996,20 +999,35 @@ static int alc5623_i2c_probe(struct i2c_client *client,
{
struct alc5623_platform_data *pdata;
struct alc5623_priv *alc5623;
- int ret, vid1, vid2;
+ struct device_node *np;
+ unsigned int vid1, vid2;
+ int ret;
+ u32 val32;
- vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1);
- if (vid1 < 0) {
- dev_err(&client->dev, "failed to read I2C\n");
- return -EIO;
+ alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
+ GFP_KERNEL);
+ if (alc5623 == NULL)
+ return -ENOMEM;
+
+ alc5623->regmap = devm_regmap_init_i2c(client, &alc5623_regmap);
+ if (IS_ERR(alc5623->regmap)) {
+ ret = PTR_ERR(alc5623->regmap);
+ dev_err(&client->dev, "Failed to initialise I/O: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID1, &vid1);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed to read vendor ID1: %d\n", ret);
+ return ret;
}
- vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8);
- vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2);
- if (vid2 < 0) {
- dev_err(&client->dev, "failed to read I2C\n");
- return -EIO;
+ ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret);
+ return ret;
}
+ vid2 >>= 8;
if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) {
dev_err(&client->dev, "unknown or wrong codec\n");
@@ -1021,15 +1039,20 @@ static int alc5623_i2c_probe(struct i2c_client *client,
dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2);
- alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
- GFP_KERNEL);
- if (alc5623 == NULL)
- return -ENOMEM;
-
pdata = client->dev.platform_data;
if (pdata) {
alc5623->add_ctrl = pdata->add_ctrl;
alc5623->jack_det_ctrl = pdata->jack_det_ctrl;
+ } else {
+ if (client->dev.of_node) {
+ np = client->dev.of_node;
+ ret = of_property_read_u32(np, "add-ctrl", &val32);
+ if (!ret)
+ alc5623->add_ctrl = val32;
+ ret = of_property_read_u32(np, "jack-det-ctrl", &val32);
+ if (!ret)
+ alc5623->jack_det_ctrl = val32;
+ }
}
alc5623->id = vid2;
@@ -1048,7 +1071,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
}
i2c_set_clientdata(client, alc5623);
- alc5623->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&client->dev,
&soc_codec_device_alc5623, &alc5623_dai, 1);
@@ -1072,11 +1094,18 @@ static const struct i2c_device_id alc5623_i2c_table[] = {
};
MODULE_DEVICE_TABLE(i2c, alc5623_i2c_table);
+static const struct of_device_id alc5623_of_match[] = {
+ { .compatible = "realtek,alc5623", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, alc5623_of_match);
+
/* i2c codec control layer */
static struct i2c_driver alc5623_i2c_driver = {
.driver = {
.name = "alc562x-codec",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(alc5623_of_match),
},
.probe = alc5623_i2c_probe,
.remove = alc5623_i2c_remove,
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
index fb001c56cf8..85942ca36cb 100644
--- a/sound/soc/codecs/alc5632.c
+++ b/sound/soc/codecs/alc5632.c
@@ -293,51 +293,59 @@ static const char * const alc5632_i2s_out_sel[] = {
"ADC LR", "Voice Stereo Digital"};
/* auxout output mux */
-static const struct soc_enum alc5632_aux_out_input_enum =
-SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 6, 4, alc5632_aux_out_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_aux_out_input_enum,
+ ALC5632_OUTPUT_MIXER_CTRL, 6,
+ alc5632_aux_out_input_sel);
static const struct snd_kcontrol_new alc5632_auxout_mux_controls =
SOC_DAPM_ENUM("AuxOut Mux", alc5632_aux_out_input_enum);
/* speaker output mux */
-static const struct soc_enum alc5632_spkout_input_enum =
-SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 10, 4, alc5632_spkout_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_spkout_input_enum,
+ ALC5632_OUTPUT_MIXER_CTRL, 10,
+ alc5632_spkout_input_sel);
static const struct snd_kcontrol_new alc5632_spkout_mux_controls =
SOC_DAPM_ENUM("SpeakerOut Mux", alc5632_spkout_input_enum);
/* headphone left output mux */
-static const struct soc_enum alc5632_hpl_out_input_enum =
-SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 9, 2, alc5632_hpl_out_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_hpl_out_input_enum,
+ ALC5632_OUTPUT_MIXER_CTRL, 9,
+ alc5632_hpl_out_input_sel);
static const struct snd_kcontrol_new alc5632_hpl_out_mux_controls =
SOC_DAPM_ENUM("Left Headphone Mux", alc5632_hpl_out_input_enum);
/* headphone right output mux */
-static const struct soc_enum alc5632_hpr_out_input_enum =
-SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 8, 2, alc5632_hpr_out_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_hpr_out_input_enum,
+ ALC5632_OUTPUT_MIXER_CTRL, 8,
+ alc5632_hpr_out_input_sel);
static const struct snd_kcontrol_new alc5632_hpr_out_mux_controls =
SOC_DAPM_ENUM("Right Headphone Mux", alc5632_hpr_out_input_enum);
/* speaker output N select */
-static const struct soc_enum alc5632_spk_n_sour_enum =
-SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 14, 4, alc5632_spk_n_sour_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_spk_n_sour_enum,
+ ALC5632_OUTPUT_MIXER_CTRL, 14,
+ alc5632_spk_n_sour_sel);
static const struct snd_kcontrol_new alc5632_spkoutn_mux_controls =
SOC_DAPM_ENUM("SpeakerOut N Mux", alc5632_spk_n_sour_enum);
/* speaker amplifier */
static const char *alc5632_amp_names[] = {"AB Amp", "D Amp"};
-static const struct soc_enum alc5632_amp_enum =
- SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 13, 2, alc5632_amp_names);
+static SOC_ENUM_SINGLE_DECL(alc5632_amp_enum,
+ ALC5632_OUTPUT_MIXER_CTRL, 13,
+ alc5632_amp_names);
static const struct snd_kcontrol_new alc5632_amp_mux_controls =
SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum);
/* ADC output select */
-static const struct soc_enum alc5632_adcr_func_enum =
- SOC_ENUM_SINGLE(ALC5632_DAC_FUNC_SELECT, 5, 2, alc5632_adcr_func_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_adcr_func_enum,
+ ALC5632_DAC_FUNC_SELECT, 5,
+ alc5632_adcr_func_sel);
static const struct snd_kcontrol_new alc5632_adcr_func_controls =
SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum);
/* I2S out select */
-static const struct soc_enum alc5632_i2s_out_enum =
- SOC_ENUM_SINGLE(ALC5632_I2S_OUT_CTL, 5, 2, alc5632_i2s_out_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_i2s_out_enum,
+ ALC5632_I2S_OUT_CTL, 5,
+ alc5632_i2s_out_sel);
static const struct snd_kcontrol_new alc5632_i2s_out_controls =
SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum);
@@ -1053,15 +1061,6 @@ static int alc5632_resume(struct snd_soc_codec *codec)
static int alc5632_probe(struct snd_soc_codec *codec)
{
struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- codec->control_data = alc5632->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
/* power on device */
alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1075,7 +1074,7 @@ static int alc5632_probe(struct snd_soc_codec *codec)
return -EINVAL;
}
- return ret;
+ return 0;
}
/* power down chip */
@@ -1191,11 +1190,18 @@ static const struct i2c_device_id alc5632_i2c_table[] = {
};
MODULE_DEVICE_TABLE(i2c, alc5632_i2c_table);
+static const struct of_device_id alc5632_of_match[] = {
+ { .compatible = "realtek,alc5632", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, alc5632_of_match);
+
/* i2c codec control layer */
static struct i2c_driver alc5632_i2c_driver = {
.driver = {
.name = "alc5632",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(alc5632_of_match),
},
.probe = alc5632_i2c_probe,
.remove = alc5632_i2c_remove,
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index e4295fee8f1..29e198f57d4 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -53,6 +53,14 @@
#define ARIZONA_AIF_RX_ENABLES 0x1A
#define ARIZONA_AIF_FORCE_WRITE 0x1B
+#define ARIZONA_FLL_VCO_CORNER 141900000
+#define ARIZONA_FLL_MAX_FREF 13500000
+#define ARIZONA_FLL_MIN_FVCO 90000000
+#define ARIZONA_FLL_MAX_FRATIO 16
+#define ARIZONA_FLL_MAX_REFDIV 8
+#define ARIZONA_FLL_MIN_OUTDIV 2
+#define ARIZONA_FLL_MAX_OUTDIV 7
+
#define arizona_fll_err(_fll, fmt, ...) \
dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
#define arizona_fll_warn(_fll, fmt, ...) \
@@ -542,67 +550,76 @@ static const char *arizona_vol_ramp_text[] = {
"15ms/6dB", "30ms/6dB",
};
-const struct soc_enum arizona_in_vd_ramp =
- SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
- ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+SOC_ENUM_SINGLE_DECL(arizona_in_vd_ramp,
+ ARIZONA_INPUT_VOLUME_RAMP,
+ ARIZONA_IN_VD_RAMP_SHIFT,
+ arizona_vol_ramp_text);
EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
-const struct soc_enum arizona_in_vi_ramp =
- SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
- ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+SOC_ENUM_SINGLE_DECL(arizona_in_vi_ramp,
+ ARIZONA_INPUT_VOLUME_RAMP,
+ ARIZONA_IN_VI_RAMP_SHIFT,
+ arizona_vol_ramp_text);
EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
-const struct soc_enum arizona_out_vd_ramp =
- SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
- ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+SOC_ENUM_SINGLE_DECL(arizona_out_vd_ramp,
+ ARIZONA_OUTPUT_VOLUME_RAMP,
+ ARIZONA_OUT_VD_RAMP_SHIFT,
+ arizona_vol_ramp_text);
EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
-const struct soc_enum arizona_out_vi_ramp =
- SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
- ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+SOC_ENUM_SINGLE_DECL(arizona_out_vi_ramp,
+ ARIZONA_OUTPUT_VOLUME_RAMP,
+ ARIZONA_OUT_VI_RAMP_SHIFT,
+ arizona_vol_ramp_text);
EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
static const char *arizona_lhpf_mode_text[] = {
"Low-pass", "High-pass"
};
-const struct soc_enum arizona_lhpf1_mode =
- SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2,
- arizona_lhpf_mode_text);
+SOC_ENUM_SINGLE_DECL(arizona_lhpf1_mode,
+ ARIZONA_HPLPF1_1,
+ ARIZONA_LHPF1_MODE_SHIFT,
+ arizona_lhpf_mode_text);
EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
-const struct soc_enum arizona_lhpf2_mode =
- SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2,
- arizona_lhpf_mode_text);
+SOC_ENUM_SINGLE_DECL(arizona_lhpf2_mode,
+ ARIZONA_HPLPF2_1,
+ ARIZONA_LHPF2_MODE_SHIFT,
+ arizona_lhpf_mode_text);
EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
-const struct soc_enum arizona_lhpf3_mode =
- SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2,
- arizona_lhpf_mode_text);
+SOC_ENUM_SINGLE_DECL(arizona_lhpf3_mode,
+ ARIZONA_HPLPF3_1,
+ ARIZONA_LHPF3_MODE_SHIFT,
+ arizona_lhpf_mode_text);
EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
-const struct soc_enum arizona_lhpf4_mode =
- SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2,
- arizona_lhpf_mode_text);
+SOC_ENUM_SINGLE_DECL(arizona_lhpf4_mode,
+ ARIZONA_HPLPF4_1,
+ ARIZONA_LHPF4_MODE_SHIFT,
+ arizona_lhpf_mode_text);
EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
static const char *arizona_ng_hold_text[] = {
"30ms", "120ms", "250ms", "500ms",
};
-const struct soc_enum arizona_ng_hold =
- SOC_ENUM_SINGLE(ARIZONA_NOISE_GATE_CONTROL, ARIZONA_NGATE_HOLD_SHIFT,
- 4, arizona_ng_hold_text);
+SOC_ENUM_SINGLE_DECL(arizona_ng_hold,
+ ARIZONA_NOISE_GATE_CONTROL,
+ ARIZONA_NGATE_HOLD_SHIFT,
+ arizona_ng_hold_text);
EXPORT_SYMBOL_GPL(arizona_ng_hold);
static const char * const arizona_in_hpf_cut_text[] = {
"2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
};
-const struct soc_enum arizona_in_hpf_cut_enum =
- SOC_ENUM_SINGLE(ARIZONA_HPF_CONTROL, ARIZONA_IN_HPF_CUT_SHIFT,
- ARRAY_SIZE(arizona_in_hpf_cut_text),
- arizona_in_hpf_cut_text);
+SOC_ENUM_SINGLE_DECL(arizona_in_hpf_cut_enum,
+ ARIZONA_HPF_CONTROL,
+ ARIZONA_IN_HPF_CUT_SHIFT,
+ arizona_in_hpf_cut_text);
EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum);
static const char * const arizona_in_dmic_osr_text[] = {
@@ -1377,74 +1394,147 @@ struct arizona_fll_cfg {
int gain;
};
-static int arizona_calc_fll(struct arizona_fll *fll,
- struct arizona_fll_cfg *cfg,
- unsigned int Fref,
- unsigned int Fout)
+static int arizona_validate_fll(struct arizona_fll *fll,
+ unsigned int Fref,
+ unsigned int Fout)
{
- unsigned int target, div, gcd_fll;
- int i, ratio;
+ unsigned int Fvco_min;
+
+ if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
+ arizona_fll_err(fll,
+ "Can't scale %dMHz in to <=13.5MHz\n",
+ Fref);
+ return -EINVAL;
+ }
- arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
+ Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult;
+ if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) {
+ arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
+ Fout);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int arizona_find_fratio(unsigned int Fref, int *fratio)
+{
+ int i;
+
+ /* Find an appropriate FLL_FRATIO */
+ for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
+ if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
+ if (fratio)
+ *fratio = fll_fratios[i].fratio;
+ return fll_fratios[i].ratio;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int arizona_calc_fratio(struct arizona_fll *fll,
+ struct arizona_fll_cfg *cfg,
+ unsigned int target,
+ unsigned int Fref, bool sync)
+{
+ int init_ratio, ratio;
+ int refdiv, div;
- /* Fref must be <=13.5MHz */
+ /* Fref must be <=13.5MHz, find initial refdiv */
div = 1;
cfg->refdiv = 0;
- while ((Fref / div) > 13500000) {
+ while (Fref > ARIZONA_FLL_MAX_FREF) {
div *= 2;
+ Fref /= 2;
cfg->refdiv++;
- if (div > 8) {
- arizona_fll_err(fll,
- "Can't scale %dMHz in to <=13.5MHz\n",
- Fref);
+ if (div > ARIZONA_FLL_MAX_REFDIV)
return -EINVAL;
+ }
+
+ /* Find an appropriate FLL_FRATIO */
+ init_ratio = arizona_find_fratio(Fref, &cfg->fratio);
+ if (init_ratio < 0) {
+ arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
+ Fref);
+ return init_ratio;
+ }
+
+ switch (fll->arizona->type) {
+ case WM5110:
+ if (fll->arizona->rev < 3 || sync)
+ return init_ratio;
+ break;
+ default:
+ return init_ratio;
+ }
+
+ cfg->fratio = init_ratio - 1;
+
+ /* Adjust FRATIO/refdiv to avoid integer mode if possible */
+ refdiv = cfg->refdiv;
+
+ while (div <= ARIZONA_FLL_MAX_REFDIV) {
+ for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO;
+ ratio++) {
+ if (target % (ratio * Fref)) {
+ cfg->refdiv = refdiv;
+ cfg->fratio = ratio - 1;
+ return ratio;
+ }
}
+
+ for (ratio = init_ratio - 1; ratio >= 0; ratio--) {
+ if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) <
+ Fref)
+ break;
+
+ if (target % (ratio * Fref)) {
+ cfg->refdiv = refdiv;
+ cfg->fratio = ratio - 1;
+ return ratio;
+ }
+ }
+
+ div *= 2;
+ Fref /= 2;
+ refdiv++;
+ init_ratio = arizona_find_fratio(Fref, NULL);
}
- /* Apply the division for our remaining calculations */
- Fref /= div;
+ arizona_fll_warn(fll, "Falling back to integer mode operation\n");
+ return cfg->fratio + 1;
+}
+
+static int arizona_calc_fll(struct arizona_fll *fll,
+ struct arizona_fll_cfg *cfg,
+ unsigned int Fref, bool sync)
+{
+ unsigned int target, div, gcd_fll;
+ int i, ratio;
+
+ arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout);
/* Fvco should be over the targt; don't check the upper bound */
- div = 1;
- while (Fout * div < 90000000 * fll->vco_mult) {
+ div = ARIZONA_FLL_MIN_OUTDIV;
+ while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) {
div++;
- if (div > 7) {
- arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
- Fout);
+ if (div > ARIZONA_FLL_MAX_OUTDIV)
return -EINVAL;
- }
}
- target = Fout * div / fll->vco_mult;
+ target = fll->fout * div / fll->vco_mult;
cfg->outdiv = div;
arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
- /* Find an appropraite FLL_FRATIO and factor it out of the target */
- for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
- if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
- cfg->fratio = fll_fratios[i].fratio;
- ratio = fll_fratios[i].ratio;
- break;
- }
- }
- if (i == ARRAY_SIZE(fll_fratios)) {
- arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
- Fref);
- return -EINVAL;
- }
+ /* Find an appropriate FLL_FRATIO and refdiv */
+ ratio = arizona_calc_fratio(fll, cfg, target, Fref, sync);
+ if (ratio < 0)
+ return ratio;
- for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
- if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
- cfg->gain = fll_gains[i].gain;
- break;
- }
- }
- if (i == ARRAY_SIZE(fll_gains)) {
- arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
- Fref);
- return -EINVAL;
- }
+ /* Apply the division for our remaining calculations */
+ Fref = Fref / (1 << cfg->refdiv);
cfg->n = target / (ratio * Fref);
@@ -1469,6 +1559,18 @@ static int arizona_calc_fll(struct arizona_fll *fll,
cfg->lambda >>= 1;
}
+ for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
+ if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
+ cfg->gain = fll_gains[i].gain;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(fll_gains)) {
+ arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
+ Fref);
+ return -EINVAL;
+ }
+
arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
cfg->n, cfg->theta, cfg->lambda);
arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
@@ -1496,14 +1598,18 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
- if (sync)
- regmap_update_bits_async(arizona->regmap, base + 0x7,
- ARIZONA_FLL1_GAIN_MASK,
- cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
- else
- regmap_update_bits_async(arizona->regmap, base + 0x9,
- ARIZONA_FLL1_GAIN_MASK,
- cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
+ if (sync) {
+ regmap_update_bits(arizona->regmap, base + 0x7,
+ ARIZONA_FLL1_GAIN_MASK,
+ cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
+ } else {
+ regmap_update_bits(arizona->regmap, base + 0x5,
+ ARIZONA_FLL1_OUTDIV_MASK,
+ cfg->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
+ regmap_update_bits(arizona->regmap, base + 0x9,
+ ARIZONA_FLL1_GAIN_MASK,
+ cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
+ }
regmap_update_bits_async(arizona->regmap, base + 2,
ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
@@ -1526,13 +1632,12 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll)
return reg & ARIZONA_FLL1_ENA;
}
-static void arizona_enable_fll(struct arizona_fll *fll,
- struct arizona_fll_cfg *ref,
- struct arizona_fll_cfg *sync)
+static void arizona_enable_fll(struct arizona_fll *fll)
{
struct arizona *arizona = fll->arizona;
int ret;
bool use_sync = false;
+ struct arizona_fll_cfg cfg;
/*
* If we have both REFCLK and SYNCCLK then enable both,
@@ -1540,23 +1645,21 @@ static void arizona_enable_fll(struct arizona_fll *fll,
*/
if (fll->ref_src >= 0 && fll->ref_freq &&
fll->ref_src != fll->sync_src) {
- regmap_update_bits_async(arizona->regmap, fll->base + 5,
- ARIZONA_FLL1_OUTDIV_MASK,
- ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
+ arizona_calc_fll(fll, &cfg, fll->ref_freq, false);
- arizona_apply_fll(arizona, fll->base, ref, fll->ref_src,
+ arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src,
false);
if (fll->sync_src >= 0) {
- arizona_apply_fll(arizona, fll->base + 0x10, sync,
+ arizona_calc_fll(fll, &cfg, fll->sync_freq, true);
+
+ arizona_apply_fll(arizona, fll->base + 0x10, &cfg,
fll->sync_src, true);
use_sync = true;
}
} else if (fll->sync_src >= 0) {
- regmap_update_bits_async(arizona->regmap, fll->base + 5,
- ARIZONA_FLL1_OUTDIV_MASK,
- sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
+ arizona_calc_fll(fll, &cfg, fll->sync_freq, false);
- arizona_apply_fll(arizona, fll->base, sync,
+ arizona_apply_fll(arizona, fll->base, &cfg,
fll->sync_src, false);
regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
@@ -1618,32 +1721,22 @@ static void arizona_disable_fll(struct arizona_fll *fll)
int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
unsigned int Fref, unsigned int Fout)
{
- struct arizona_fll_cfg ref, sync;
int ret;
if (fll->ref_src == source && fll->ref_freq == Fref)
return 0;
- if (fll->fout) {
- if (Fref > 0) {
- ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
- if (ret != 0)
- return ret;
- }
-
- if (fll->sync_src >= 0) {
- ret = arizona_calc_fll(fll, &sync, fll->sync_freq,
- fll->fout);
- if (ret != 0)
- return ret;
- }
+ if (fll->fout && Fref > 0) {
+ ret = arizona_validate_fll(fll, Fref, fll->fout);
+ if (ret != 0)
+ return ret;
}
fll->ref_src = source;
fll->ref_freq = Fref;
if (fll->fout && Fref > 0) {
- arizona_enable_fll(fll, &ref, &sync);
+ arizona_enable_fll(fll);
}
return 0;
@@ -1653,7 +1746,6 @@ EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
int arizona_set_fll(struct arizona_fll *fll, int source,
unsigned int Fref, unsigned int Fout)
{
- struct arizona_fll_cfg ref, sync;
int ret;
if (fll->sync_src == source &&
@@ -1662,13 +1754,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
if (Fout) {
if (fll->ref_src >= 0) {
- ret = arizona_calc_fll(fll, &ref, fll->ref_freq,
- Fout);
+ ret = arizona_validate_fll(fll, fll->ref_freq, Fout);
if (ret != 0)
return ret;
}
- ret = arizona_calc_fll(fll, &sync, Fref, Fout);
+ ret = arizona_validate_fll(fll, Fref, Fout);
if (ret != 0)
return ret;
}
@@ -1678,7 +1769,7 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
fll->fout = Fout;
if (Fout) {
- arizona_enable_fll(fll, &ref, &sync);
+ arizona_enable_fll(fll);
} else {
arizona_disable_fll(fll);
}
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index 16df0f91335..05ae17f5bca 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -107,7 +107,7 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
#define ARIZONA_MUX_CTL_DECL(name) \
const struct snd_kcontrol_new name##_mux = \
- SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+ SOC_DAPM_ENUM("Route", name##_enum)
#define ARIZONA_MUX_ENUMS(name, base_reg) \
static ARIZONA_MUX_ENUM_DECL(name##_enum, base_reg); \
@@ -128,7 +128,7 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
ARIZONA_MUX_ENUMS(name##_aux6, base_reg + 40)
#define ARIZONA_MUX(name, ctrl) \
- SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+ SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
#define ARIZONA_MUX_WIDGETS(name, name_str) \
ARIZONA_MUX(name_str " Input", &name##_mux)
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index 43737a27d79..537327c7f7f 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -138,9 +138,6 @@ static int cq93vc_probe(struct snd_soc_codec *codec)
struct davinci_vc *davinci_vc = codec->dev->platform_data;
davinci_vc->cq93vc.codec = codec;
- codec->control_data = davinci_vc->regmap;
-
- snd_soc_codec_set_cache_io(codec, 32, 32, SND_SOC_REGMAP);
/* Off, with power on */
cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -155,11 +152,19 @@ static int cq93vc_remove(struct snd_soc_codec *codec)
return 0;
}
+static struct regmap *cq93vc_get_regmap(struct device *dev)
+{
+ struct davinci_vc *davinci_vc = dev->platform_data;
+
+ return davinci_vc->regmap;
+}
+
static struct snd_soc_codec_driver soc_codec_dev_cq93vc = {
.set_bias_level = cq93vc_set_bias_level,
.probe = cq93vc_probe,
.remove = cq93vc_remove,
.resume = cq93vc_resume,
+ .get_regmap = cq93vc_get_regmap,
.controls = cq93vc_snd_controls,
.num_controls = ARRAY_SIZE(cq93vc_snd_controls),
};
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 83c835d9fd8..9947a958367 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -438,7 +438,7 @@ static int cs4270_dai_mute(struct snd_soc_dai *dai, int mute)
static int cs4270_soc_put_mute(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int left = !ucontrol->value.integer.value[0];
int right = !ucontrol->value.integer.value[1];
@@ -506,15 +506,6 @@ static int cs4270_probe(struct snd_soc_codec *codec)
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int ret;
- /* Tell ASoC what kind of I/O to use to read the registers. ASoC will
- * then do the I2C transactions itself.
- */
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret);
- return ret;
- }
-
/* Disable auto-mute. This feature appears to be buggy. In some
* situations, auto-mute will not deactivate when it should, so we want
* this feature disabled by default. An application (e.g. alsactl) can
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index ce05fd93dc7..93cec52f473 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -159,7 +159,6 @@ static bool cs4271_volatile_reg(struct device *dev, unsigned int reg)
}
struct cs4271_private {
- /* SND_SOC_I2C or SND_SOC_SPI */
unsigned int mclk;
bool master;
bool deemph;
@@ -285,7 +284,7 @@ static int cs4271_set_deemph(struct snd_soc_codec *codec)
static int cs4271_get_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = cs4271->deemph;
@@ -295,7 +294,7 @@ static int cs4271_get_deemph(struct snd_kcontrol *kcontrol,
static int cs4271_put_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
cs4271->deemph = ucontrol->value.enumerated.item[0];
@@ -540,14 +539,10 @@ static int cs4271_probe(struct snd_soc_codec *codec)
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
struct cs4271_platform_data *cs4271plat = codec->dev->platform_data;
int ret;
- int gpio_nreset = -EINVAL;
bool amutec_eq_bmutec = false;
#ifdef CONFIG_OF
if (of_match_device(cs4271_dt_ids, codec->dev)) {
- gpio_nreset = of_get_named_gpio(codec->dev->of_node,
- "reset-gpio", 0);
-
if (of_get_property(codec->dev->of_node,
"cirrus,amutec-eq-bmutec", NULL))
amutec_eq_bmutec = true;
@@ -559,27 +554,19 @@ static int cs4271_probe(struct snd_soc_codec *codec)
#endif
if (cs4271plat) {
- if (gpio_is_valid(cs4271plat->gpio_nreset))
- gpio_nreset = cs4271plat->gpio_nreset;
-
amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec;
cs4271->enable_soft_reset = cs4271plat->enable_soft_reset;
}
- if (gpio_nreset >= 0)
- if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset"))
- gpio_nreset = -EINVAL;
- if (gpio_nreset >= 0) {
+ if (gpio_is_valid(cs4271->gpio_nreset)) {
/* Reset codec */
- gpio_direction_output(gpio_nreset, 0);
+ gpio_direction_output(cs4271->gpio_nreset, 0);
udelay(1);
- gpio_set_value(gpio_nreset, 1);
+ gpio_set_value(cs4271->gpio_nreset, 1);
/* Give the codec time to wake up */
udelay(1);
}
- cs4271->gpio_nreset = gpio_nreset;
-
ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
CS4271_MODE2_PDN | CS4271_MODE2_CPEN,
CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
@@ -625,6 +612,36 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
.num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes),
};
+static int cs4271_common_probe(struct device *dev,
+ struct cs4271_private **c)
+{
+ struct cs4271_platform_data *cs4271plat = dev->platform_data;
+ struct cs4271_private *cs4271;
+
+ cs4271 = devm_kzalloc(dev, sizeof(*cs4271), GFP_KERNEL);
+ if (!cs4271)
+ return -ENOMEM;
+
+ if (of_match_device(cs4271_dt_ids, dev))
+ cs4271->gpio_nreset =
+ of_get_named_gpio(dev->of_node, "reset-gpio", 0);
+
+ if (cs4271plat)
+ cs4271->gpio_nreset = cs4271plat->gpio_nreset;
+
+ if (gpio_is_valid(cs4271->gpio_nreset)) {
+ int ret;
+
+ ret = devm_gpio_request(dev, cs4271->gpio_nreset,
+ "CS4271 Reset");
+ if (ret < 0)
+ return ret;
+ }
+
+ *c = cs4271;
+ return 0;
+}
+
#if defined(CONFIG_SPI_MASTER)
static const struct regmap_config cs4271_spi_regmap = {
@@ -644,10 +661,11 @@ static const struct regmap_config cs4271_spi_regmap = {
static int cs4271_spi_probe(struct spi_device *spi)
{
struct cs4271_private *cs4271;
+ int ret;
- cs4271 = devm_kzalloc(&spi->dev, sizeof(*cs4271), GFP_KERNEL);
- if (!cs4271)
- return -ENOMEM;
+ ret = cs4271_common_probe(&spi->dev, &cs4271);
+ if (ret < 0)
+ return ret;
spi_set_drvdata(spi, cs4271);
cs4271->regmap = devm_regmap_init_spi(spi, &cs4271_spi_regmap);
@@ -698,10 +716,11 @@ static int cs4271_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct cs4271_private *cs4271;
+ int ret;
- cs4271 = devm_kzalloc(&client->dev, sizeof(*cs4271), GFP_KERNEL);
- if (!cs4271)
- return -ENOMEM;
+ ret = cs4271_common_probe(&client->dev, &cs4271);
+ if (ret < 0)
+ return ret;
i2c_set_clientdata(client, cs4271);
cs4271->regmap = devm_regmap_init_i2c(client, &cs4271_i2c_regmap);
diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c
new file mode 100644
index 00000000000..cee51ae177c
--- /dev/null
+++ b/sound/soc/codecs/cs42l51-i2c.c
@@ -0,0 +1,59 @@
+/*
+ * cs42l56.c -- CS42L51 ALSA SoC I2C audio driver
+ *
+ * Copyright 2014 CirrusLogic, Inc.
+ *
+ * Author: Brian Austin <brian.austin@cirrus.com>
+ *
+ * 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 <linux/i2c.h>
+#include <linux/module.h>
+#include <sound/soc.h>
+
+#include "cs42l51.h"
+
+static struct i2c_device_id cs42l51_i2c_id[] = {
+ {"cs42l51", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, cs42l51_i2c_id);
+
+static int cs42l51_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct regmap_config config;
+
+ config = cs42l51_regmap;
+ config.val_bits = 8;
+ config.reg_bits = 8;
+
+ return cs42l51_probe(&i2c->dev, devm_regmap_init_i2c(i2c, &config));
+}
+
+static int cs42l51_i2c_remove(struct i2c_client *i2c)
+{
+ snd_soc_unregister_codec(&i2c->dev);
+
+ return 0;
+}
+
+static struct i2c_driver cs42l51_i2c_driver = {
+ .driver = {
+ .name = "cs42l51",
+ .owner = THIS_MODULE,
+ },
+ .probe = cs42l51_i2c_probe,
+ .remove = cs42l51_i2c_remove,
+ .id_table = cs42l51_i2c_id,
+};
+
+module_i2c_driver(cs42l51_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC CS42L51 I2C Driver");
+MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index 6e9ea8379a9..09488d97de6 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -29,7 +29,7 @@
#include <sound/initval.h>
#include <sound/pcm_params.h>
#include <sound/pcm.h>
-#include <linux/i2c.h>
+#include <linux/regmap.h>
#include "cs42l51.h"
@@ -40,7 +40,6 @@ enum master_slave_mode {
};
struct cs42l51_private {
- enum snd_soc_control_type control_type;
unsigned int mclk;
unsigned int audio_mode; /* The mode (I2S or left-justified) */
enum master_slave_mode func;
@@ -52,28 +51,10 @@ struct cs42l51_private {
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE)
-static int cs42l51_fill_cache(struct snd_soc_codec *codec)
-{
- u8 *cache = codec->reg_cache + 1;
- struct i2c_client *i2c_client = to_i2c_client(codec->dev);
- s32 length;
-
- length = i2c_smbus_read_i2c_block_data(i2c_client,
- CS42L51_FIRSTREG | 0x80, CS42L51_NUMREGS, cache);
- if (length != CS42L51_NUMREGS) {
- dev_err(&i2c_client->dev,
- "I2C read failure, addr=0x%x (ret=%d vs %d)\n",
- i2c_client->addr, length, CS42L51_NUMREGS);
- return -EIO;
- }
-
- return 0;
-}
-
static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned long value = snd_soc_read(codec, CS42L51_PCM_MIXER)&3;
switch (value) {
@@ -101,7 +82,7 @@ static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned char val;
switch (ucontrol->value.integer.value[0]) {
@@ -124,9 +105,8 @@ static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol,
static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0);
static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0);
-/* This is a lie. after -102 db, it stays at -102 */
-/* maybe a range would be better */
-static const DECLARE_TLV_DB_SCALE(aout_tlv, -11550, 50, 0);
+
+static const DECLARE_TLV_DB_SCALE(aout_tlv, -10200, 50, 0);
static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0);
static const char *chan_mix[] = {
@@ -135,13 +115,12 @@ static const char *chan_mix[] = {
"R L",
};
-static const struct soc_enum cs42l51_chan_mix =
- SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chan_mix), chan_mix);
+static SOC_ENUM_SINGLE_EXT_DECL(cs42l51_chan_mix, chan_mix);
static const struct snd_kcontrol_new cs42l51_snd_controls[] = {
SOC_DOUBLE_R_SX_TLV("PCM Playback Volume",
CS42L51_PCMA_VOL, CS42L51_PCMB_VOL,
- 6, 0x19, 0x7F, adc_pcm_tlv),
+ 0, 0x19, 0x7F, adc_pcm_tlv),
SOC_DOUBLE_R("PCM Playback Switch",
CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1),
SOC_DOUBLE_R_SX_TLV("Analog Playback Volume",
@@ -149,7 +128,7 @@ static const struct snd_kcontrol_new cs42l51_snd_controls[] = {
0, 0x34, 0xE4, aout_tlv),
SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
CS42L51_ADCA_VOL, CS42L51_ADCB_VOL,
- 6, 0x19, 0x7F, adc_pcm_tlv),
+ 0, 0x19, 0x7F, adc_pcm_tlv),
SOC_DOUBLE_R("ADC Mixer Switch",
CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1),
SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0),
@@ -192,22 +171,22 @@ static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w,
static const char *cs42l51_dac_names[] = {"Direct PCM",
"DSP PCM", "ADC"};
-static const struct soc_enum cs42l51_dac_mux_enum =
- SOC_ENUM_SINGLE(CS42L51_DAC_CTL, 6, 3, cs42l51_dac_names);
+static SOC_ENUM_SINGLE_DECL(cs42l51_dac_mux_enum,
+ CS42L51_DAC_CTL, 6, cs42l51_dac_names);
static const struct snd_kcontrol_new cs42l51_dac_mux_controls =
SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum);
static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left",
"MIC Left", "MIC+preamp Left"};
-static const struct soc_enum cs42l51_adcl_mux_enum =
- SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 4, 4, cs42l51_adcl_names);
+static SOC_ENUM_SINGLE_DECL(cs42l51_adcl_mux_enum,
+ CS42L51_ADC_INPUT, 4, cs42l51_adcl_names);
static const struct snd_kcontrol_new cs42l51_adcl_mux_controls =
SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum);
static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right",
"MIC Right", "MIC+preamp Right"};
-static const struct soc_enum cs42l51_adcr_mux_enum =
- SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 6, 4, cs42l51_adcr_names);
+static SOC_ENUM_SINGLE_DECL(cs42l51_adcr_mux_enum,
+ CS42L51_ADC_INPUT, 6, cs42l51_adcr_names);
static const struct snd_kcontrol_new cs42l51_adcr_mux_controls =
SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum);
@@ -503,23 +482,10 @@ static struct snd_soc_dai_driver cs42l51_dai = {
.ops = &cs42l51_dai_ops,
};
-static int cs42l51_probe(struct snd_soc_codec *codec)
+static int cs42l51_codec_probe(struct snd_soc_codec *codec)
{
- struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
int ret, reg;
- ret = cs42l51_fill_cache(codec);
- if (ret < 0) {
- dev_err(codec->dev, "failed to fill register cache\n");
- return ret;
- }
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
/*
* DAC configuration
* - Use signal processor
@@ -537,9 +503,7 @@ static int cs42l51_probe(struct snd_soc_codec *codec)
}
static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
- .probe = cs42l51_probe,
- .reg_cache_size = CS42L51_NUMREGS + 1,
- .reg_word_size = sizeof(u8),
+ .probe = cs42l51_codec_probe,
.controls = cs42l51_snd_controls,
.num_controls = ARRAY_SIZE(cs42l51_snd_controls),
@@ -549,69 +513,56 @@ static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
.num_dapm_routes = ARRAY_SIZE(cs42l51_routes),
};
-static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
- const struct i2c_device_id *id)
+const struct regmap_config cs42l51_regmap = {
+ .max_register = CS42L51_CHARGE_FREQ,
+ .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs42l51_regmap);
+
+int cs42l51_probe(struct device *dev, struct regmap *regmap)
{
struct cs42l51_private *cs42l51;
+ unsigned int val;
int ret;
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ cs42l51 = devm_kzalloc(dev, sizeof(struct cs42l51_private),
+ GFP_KERNEL);
+ if (!cs42l51)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, cs42l51);
+
/* Verify that we have a CS42L51 */
- ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
+ ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val);
if (ret < 0) {
- dev_err(&i2c_client->dev, "failed to read I2C\n");
+ dev_err(dev, "failed to read I2C\n");
goto error;
}
- if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
- (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
- dev_err(&i2c_client->dev, "Invalid chip id\n");
+ if ((val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
+ (val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
+ dev_err(dev, "Invalid chip id: %x\n", val);
ret = -ENODEV;
goto error;
}
+ dev_info(dev, "Cirrus Logic CS42L51, Revision: %02X\n",
+ val & CS42L51_CHIP_REV_MASK);
- dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
- ret & 7);
-
- cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private),
- GFP_KERNEL);
- if (!cs42l51) {
- dev_err(&i2c_client->dev, "could not allocate codec\n");
- return -ENOMEM;
- }
-
- i2c_set_clientdata(i2c_client, cs42l51);
- cs42l51->control_type = SND_SOC_I2C;
-
- ret = snd_soc_register_codec(&i2c_client->dev,
+ ret = snd_soc_register_codec(dev,
&soc_codec_device_cs42l51, &cs42l51_dai, 1);
error:
return ret;
}
+EXPORT_SYMBOL_GPL(cs42l51_probe);
-static int cs42l51_i2c_remove(struct i2c_client *client)
-{
- snd_soc_unregister_codec(&client->dev);
- return 0;
-}
-
-static const struct i2c_device_id cs42l51_id[] = {
- {"cs42l51", 0},
- {}
+static const struct of_device_id cs42l51_of_match[] = {
+ { .compatible = "cirrus,cs42l51", },
+ { }
};
-MODULE_DEVICE_TABLE(i2c, cs42l51_id);
-
-static struct i2c_driver cs42l51_i2c_driver = {
- .driver = {
- .name = "cs42l51-codec",
- .owner = THIS_MODULE,
- },
- .id_table = cs42l51_id,
- .probe = cs42l51_i2c_probe,
- .remove = cs42l51_i2c_remove,
-};
-
-module_i2c_driver(cs42l51_i2c_driver);
-
+MODULE_DEVICE_TABLE(of, cs42l51_of_match);
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h
index 2beeb171db4..8c55bf384bc 100644
--- a/sound/soc/codecs/cs42l51.h
+++ b/sound/soc/codecs/cs42l51.h
@@ -18,9 +18,15 @@
#ifndef _CS42L51_H
#define _CS42L51_H
+struct device;
+
+extern const struct regmap_config cs42l51_regmap;
+int cs42l51_probe(struct device *dev, struct regmap *regmap);
+
#define CS42L51_CHIP_ID 0x1B
#define CS42L51_CHIP_REV_A 0x00
#define CS42L51_CHIP_REV_B 0x01
+#define CS42L51_CHIP_REV_MASK 0x07
#define CS42L51_CHIP_REV_ID 0x01
#define CS42L51_MK_CHIP_REV(a, b) ((a)<<3|(b))
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index 0bac6d5a4ac..071fc77f2f0 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -50,11 +50,9 @@ struct cs42l52_private {
u8 mclksel;
u32 mclk;
u8 flags;
-#if IS_ENABLED(CONFIG_INPUT)
struct input_dev *beep;
struct work_struct beep_work;
int beep_rate;
-#endif
};
static const struct reg_default cs42l52_reg_defaults[] = {
@@ -210,13 +208,11 @@ static const char * const cs42l52_adca_text[] = {
static const char * const cs42l52_adcb_text[] = {
"Input1B", "Input2B", "Input3B", "Input4B", "PGA Input Right"};
-static const struct soc_enum adca_enum =
- SOC_ENUM_SINGLE(CS42L52_ADC_PGA_A, 5,
- ARRAY_SIZE(cs42l52_adca_text), cs42l52_adca_text);
+static SOC_ENUM_SINGLE_DECL(adca_enum,
+ CS42L52_ADC_PGA_A, 5, cs42l52_adca_text);
-static const struct soc_enum adcb_enum =
- SOC_ENUM_SINGLE(CS42L52_ADC_PGA_B, 5,
- ARRAY_SIZE(cs42l52_adcb_text), cs42l52_adcb_text);
+static SOC_ENUM_SINGLE_DECL(adcb_enum,
+ CS42L52_ADC_PGA_B, 5, cs42l52_adcb_text);
static const struct snd_kcontrol_new adca_mux =
SOC_DAPM_ENUM("Left ADC Input Capture Mux", adca_enum);
@@ -229,26 +225,22 @@ static const char * const mic_bias_level_text[] = {
"0.8 +VA", "0.83 +VA", "0.91 +VA"
};
-static const struct soc_enum mic_bias_level_enum =
- SOC_ENUM_SINGLE(CS42L52_IFACE_CTL2, 0,
- ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text);
+static SOC_ENUM_SINGLE_DECL(mic_bias_level_enum,
+ CS42L52_IFACE_CTL2, 0, mic_bias_level_text);
static const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" };
-static const struct soc_enum mica_enum =
- SOC_ENUM_SINGLE(CS42L52_MICA_CTL, 5,
- ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text);
+static SOC_ENUM_SINGLE_DECL(mica_enum,
+ CS42L52_MICA_CTL, 5, cs42l52_mic_text);
-static const struct soc_enum micb_enum =
- SOC_ENUM_SINGLE(CS42L52_MICB_CTL, 5,
- ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text);
+static SOC_ENUM_SINGLE_DECL(micb_enum,
+ CS42L52_MICB_CTL, 5, cs42l52_mic_text);
static const char * const digital_output_mux_text[] = {"ADC", "DSP"};
-static const struct soc_enum digital_output_mux_enum =
- SOC_ENUM_SINGLE(CS42L52_ADC_MISC_CTL, 6,
- ARRAY_SIZE(digital_output_mux_text),
- digital_output_mux_text);
+static SOC_ENUM_SINGLE_DECL(digital_output_mux_enum,
+ CS42L52_ADC_MISC_CTL, 6,
+ digital_output_mux_text);
static const struct snd_kcontrol_new digital_output_mux =
SOC_DAPM_ENUM("Digital Output Mux", digital_output_mux_enum);
@@ -258,18 +250,18 @@ static const char * const hp_gain_num_text[] = {
"0.7099", "0.8399", "1.000", "1.1430"
};
-static const struct soc_enum hp_gain_enum =
- SOC_ENUM_SINGLE(CS42L52_PB_CTL1, 5,
- ARRAY_SIZE(hp_gain_num_text), hp_gain_num_text);
+static SOC_ENUM_SINGLE_DECL(hp_gain_enum,
+ CS42L52_PB_CTL1, 5,
+ hp_gain_num_text);
static const char * const beep_pitch_text[] = {
"C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5",
"C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7"
};
-static const struct soc_enum beep_pitch_enum =
- SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 4,
- ARRAY_SIZE(beep_pitch_text), beep_pitch_text);
+static SOC_ENUM_SINGLE_DECL(beep_pitch_enum,
+ CS42L52_BEEP_FREQ, 4,
+ beep_pitch_text);
static const char * const beep_ontime_text[] = {
"86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s",
@@ -277,66 +269,66 @@ static const char * const beep_ontime_text[] = {
"3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s"
};
-static const struct soc_enum beep_ontime_enum =
- SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 0,
- ARRAY_SIZE(beep_ontime_text), beep_ontime_text);
+static SOC_ENUM_SINGLE_DECL(beep_ontime_enum,
+ CS42L52_BEEP_FREQ, 0,
+ beep_ontime_text);
static const char * const beep_offtime_text[] = {
"1.23 s", "2.58 s", "3.90 s", "5.20 s",
"6.60 s", "8.05 s", "9.35 s", "10.80 s"
};
-static const struct soc_enum beep_offtime_enum =
- SOC_ENUM_SINGLE(CS42L52_BEEP_VOL, 5,
- ARRAY_SIZE(beep_offtime_text), beep_offtime_text);
+static SOC_ENUM_SINGLE_DECL(beep_offtime_enum,
+ CS42L52_BEEP_VOL, 5,
+ beep_offtime_text);
static const char * const beep_config_text[] = {
"Off", "Single", "Multiple", "Continuous"
};
-static const struct soc_enum beep_config_enum =
- SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 6,
- ARRAY_SIZE(beep_config_text), beep_config_text);
+static SOC_ENUM_SINGLE_DECL(beep_config_enum,
+ CS42L52_BEEP_TONE_CTL, 6,
+ beep_config_text);
static const char * const beep_bass_text[] = {
"50 Hz", "100 Hz", "200 Hz", "250 Hz"
};
-static const struct soc_enum beep_bass_enum =
- SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 1,
- ARRAY_SIZE(beep_bass_text), beep_bass_text);
+static SOC_ENUM_SINGLE_DECL(beep_bass_enum,
+ CS42L52_BEEP_TONE_CTL, 1,
+ beep_bass_text);
static const char * const beep_treble_text[] = {
"5 kHz", "7 kHz", "10 kHz", " 15 kHz"
};
-static const struct soc_enum beep_treble_enum =
- SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 3,
- ARRAY_SIZE(beep_treble_text), beep_treble_text);
+static SOC_ENUM_SINGLE_DECL(beep_treble_enum,
+ CS42L52_BEEP_TONE_CTL, 3,
+ beep_treble_text);
static const char * const ng_threshold_text[] = {
"-34dB", "-37dB", "-40dB", "-43dB",
"-46dB", "-52dB", "-58dB", "-64dB"
};
-static const struct soc_enum ng_threshold_enum =
- SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 2,
- ARRAY_SIZE(ng_threshold_text), ng_threshold_text);
+static SOC_ENUM_SINGLE_DECL(ng_threshold_enum,
+ CS42L52_NOISE_GATE_CTL, 2,
+ ng_threshold_text);
static const char * const cs42l52_ng_delay_text[] = {
"50ms", "100ms", "150ms", "200ms"};
-static const struct soc_enum ng_delay_enum =
- SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 0,
- ARRAY_SIZE(cs42l52_ng_delay_text), cs42l52_ng_delay_text);
+static SOC_ENUM_SINGLE_DECL(ng_delay_enum,
+ CS42L52_NOISE_GATE_CTL, 0,
+ cs42l52_ng_delay_text);
static const char * const cs42l52_ng_type_text[] = {
"Apply Specific", "Apply All"
};
-static const struct soc_enum ng_type_enum =
- SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 6,
- ARRAY_SIZE(cs42l52_ng_type_text), cs42l52_ng_type_text);
+static SOC_ENUM_SINGLE_DECL(ng_type_enum,
+ CS42L52_NOISE_GATE_CTL, 6,
+ cs42l52_ng_type_text);
static const char * const left_swap_text[] = {
"Left", "LR 2", "Right"};
@@ -347,7 +339,7 @@ static const char * const right_swap_text[] = {
static const unsigned int swap_values[] = { 0, 1, 3 };
static const struct soc_enum adca_swap_enum =
- SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 1,
+ SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 3,
ARRAY_SIZE(left_swap_text),
left_swap_text,
swap_values);
@@ -356,7 +348,7 @@ static const struct snd_kcontrol_new adca_mixer =
SOC_DAPM_ENUM("Route", adca_swap_enum);
static const struct soc_enum pcma_swap_enum =
- SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 1,
+ SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 3,
ARRAY_SIZE(left_swap_text),
left_swap_text,
swap_values);
@@ -365,7 +357,7 @@ static const struct snd_kcontrol_new pcma_mixer =
SOC_DAPM_ENUM("Route", pcma_swap_enum);
static const struct soc_enum adcb_swap_enum =
- SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 1,
+ SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 3,
ARRAY_SIZE(right_swap_text),
right_swap_text,
swap_values);
@@ -374,7 +366,7 @@ static const struct snd_kcontrol_new adcb_mixer =
SOC_DAPM_ENUM("Route", adcb_swap_enum);
static const struct soc_enum pcmb_swap_enum =
- SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 1,
+ SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 3,
ARRAY_SIZE(right_swap_text),
right_swap_text,
swap_values);
@@ -968,7 +960,6 @@ static int cs42l52_resume(struct snd_soc_codec *codec)
return 0;
}
-#if IS_ENABLED(CONFIG_INPUT)
static int beep_rates[] = {
261, 522, 585, 667, 706, 774, 889, 1000,
1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182
@@ -1102,27 +1093,11 @@ static void cs42l52_free_beep(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, CS42L52_BEEP_TONE_CTL,
CS42L52_BEEP_EN_MASK, 0);
}
-#else
-static void cs42l52_init_beep(struct snd_soc_codec *codec)
-{
-}
-
-static void cs42l52_free_beep(struct snd_soc_codec *codec)
-{
-}
-#endif
static int cs42l52_probe(struct snd_soc_codec *codec)
{
struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
- int ret;
- codec->control_data = cs42l52->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
regcache_cache_only(cs42l52->regmap, true);
cs42l52_add_mic_controls(codec);
@@ -1134,7 +1109,7 @@ static int cs42l52_probe(struct snd_soc_codec *codec)
cs42l52->sysclk = CS42L52_DEFAULT_CLK;
cs42l52->config.format = CS42L52_DEFAULT_FORMAT;
- return ret;
+ return 0;
}
static int cs42l52_remove(struct snd_soc_codec *codec)
@@ -1242,8 +1217,10 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
}
if (cs42l52->pdata.reset_gpio) {
- ret = gpio_request_one(cs42l52->pdata.reset_gpio,
- GPIOF_OUT_INIT_HIGH, "CS42L52 /RST");
+ ret = devm_gpio_request_one(&i2c_client->dev,
+ cs42l52->pdata.reset_gpio,
+ GPIOF_OUT_INIT_HIGH,
+ "CS42L52 /RST");
if (ret < 0) {
dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
cs42l52->pdata.reset_gpio, ret);
@@ -1272,7 +1249,7 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
}
dev_info(&i2c_client->dev, "Cirrus Logic CS42L52, Revision: %02X\n",
- reg & 0xFF);
+ reg & CS42L52_CHIP_REV_MASK);
/* Set Platform Data */
if (cs42l52->pdata.mica_diff_cfg)
diff --git a/sound/soc/codecs/cs42l52.h b/sound/soc/codecs/cs42l52.h
index 6fb8f00f419..ac445993e6b 100644
--- a/sound/soc/codecs/cs42l52.h
+++ b/sound/soc/codecs/cs42l52.h
@@ -37,7 +37,7 @@
#define CS42L52_CHIP_REV_A0 0x00
#define CS42L52_CHIP_REV_A1 0x01
#define CS42L52_CHIP_REV_B0 0x02
-#define CS42L52_CHIP_REV_MASK 0x03
+#define CS42L52_CHIP_REV_MASK 0x07
#define CS42L52_PWRCTL1 0x02
#define CS42L52_PWRCTL1_PDN_ALL 0x9F
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c
new file mode 100644
index 00000000000..fdc4bd27b0d
--- /dev/null
+++ b/sound/soc/codecs/cs42l56.c
@@ -0,0 +1,1419 @@
+/*
+ * cs42l56.c -- CS42L56 ALSA SoC audio driver
+ *
+ * Copyright 2014 CirrusLogic, Inc.
+ *
+ * Author: Brian Austin <brian.austin@cirrus.com>
+ *
+ * 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 <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <sound/core.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/cs42l56.h>
+#include "cs42l56.h"
+
+#define CS42L56_NUM_SUPPLIES 3
+static const char *const cs42l56_supply_names[CS42L56_NUM_SUPPLIES] = {
+ "VA",
+ "VCP",
+ "VLDO",
+};
+
+struct cs42l56_private {
+ struct regmap *regmap;
+ struct snd_soc_codec *codec;
+ struct device *dev;
+ struct cs42l56_platform_data pdata;
+ struct regulator_bulk_data supplies[CS42L56_NUM_SUPPLIES];
+ u32 mclk;
+ u8 mclk_prediv;
+ u8 mclk_div2;
+ u8 mclk_ratio;
+ u8 iface;
+ u8 iface_fmt;
+ u8 iface_inv;
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+ struct input_dev *beep;
+ struct work_struct beep_work;
+ int beep_rate;
+#endif
+};
+
+static const struct reg_default cs42l56_reg_defaults[] = {
+ { 1, 0x56 }, /* r01 - ID 1 */
+ { 2, 0x04 }, /* r02 - ID 2 */
+ { 3, 0x7f }, /* r03 - Power Ctl 1 */
+ { 4, 0xff }, /* r04 - Power Ctl 2 */
+ { 5, 0x00 }, /* ro5 - Clocking Ctl 1 */
+ { 6, 0x0b }, /* r06 - Clocking Ctl 2 */
+ { 7, 0x00 }, /* r07 - Serial Format */
+ { 8, 0x05 }, /* r08 - Class H Ctl */
+ { 9, 0x0c }, /* r09 - Misc Ctl */
+ { 10, 0x80 }, /* r0a - INT Status */
+ { 11, 0x00 }, /* r0b - Playback Ctl */
+ { 12, 0x0c }, /* r0c - DSP Mute Ctl */
+ { 13, 0x00 }, /* r0d - ADCA Mixer Volume */
+ { 14, 0x00 }, /* r0e - ADCB Mixer Volume */
+ { 15, 0x00 }, /* r0f - PCMA Mixer Volume */
+ { 16, 0x00 }, /* r10 - PCMB Mixer Volume */
+ { 17, 0x00 }, /* r11 - Analog Input Advisory Volume */
+ { 18, 0x00 }, /* r12 - Digital Input Advisory Volume */
+ { 19, 0x00 }, /* r13 - Master A Volume */
+ { 20, 0x00 }, /* r14 - Master B Volume */
+ { 21, 0x00 }, /* r15 - Beep Freq / On Time */
+ { 22, 0x00 }, /* r16 - Beep Volume / Off Time */
+ { 23, 0x00 }, /* r17 - Beep Tone Ctl */
+ { 24, 0x88 }, /* r18 - Tone Ctl */
+ { 25, 0x00 }, /* r19 - Channel Mixer & Swap */
+ { 26, 0x00 }, /* r1a - AIN Ref Config / ADC Mux */
+ { 27, 0xa0 }, /* r1b - High-Pass Filter Ctl */
+ { 28, 0x00 }, /* r1c - Misc ADC Ctl */
+ { 29, 0x00 }, /* r1d - Gain & Bias Ctl */
+ { 30, 0x00 }, /* r1e - PGAA Mux & Volume */
+ { 31, 0x00 }, /* r1f - PGAB Mux & Volume */
+ { 32, 0x00 }, /* r20 - ADCA Attenuator */
+ { 33, 0x00 }, /* r21 - ADCB Attenuator */
+ { 34, 0x00 }, /* r22 - ALC Enable & Attack Rate */
+ { 35, 0xbf }, /* r23 - ALC Release Rate */
+ { 36, 0x00 }, /* r24 - ALC Threshold */
+ { 37, 0x00 }, /* r25 - Noise Gate Ctl */
+ { 38, 0x00 }, /* r26 - ALC, Limiter, SFT, ZeroCross */
+ { 39, 0x00 }, /* r27 - Analog Mute, LO & HP Mux */
+ { 40, 0x00 }, /* r28 - HP A Volume */
+ { 41, 0x00 }, /* r29 - HP B Volume */
+ { 42, 0x00 }, /* r2a - LINEOUT A Volume */
+ { 43, 0x00 }, /* r2b - LINEOUT B Volume */
+ { 44, 0x00 }, /* r2c - Limit Threshold Ctl */
+ { 45, 0x7f }, /* r2d - Limiter Ctl & Release Rate */
+ { 46, 0x00 }, /* r2e - Limiter Attack Rate */
+};
+
+static bool cs42l56_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS42L56_CHIP_ID_1:
+ case CS42L56_CHIP_ID_2:
+ case CS42L56_PWRCTL_1:
+ case CS42L56_PWRCTL_2:
+ case CS42L56_CLKCTL_1:
+ case CS42L56_CLKCTL_2:
+ case CS42L56_SERIAL_FMT:
+ case CS42L56_CLASSH_CTL:
+ case CS42L56_MISC_CTL:
+ case CS42L56_INT_STATUS:
+ case CS42L56_PLAYBACK_CTL:
+ case CS42L56_DSP_MUTE_CTL:
+ case CS42L56_ADCA_MIX_VOLUME:
+ case CS42L56_ADCB_MIX_VOLUME:
+ case CS42L56_PCMA_MIX_VOLUME:
+ case CS42L56_PCMB_MIX_VOLUME:
+ case CS42L56_ANAINPUT_ADV_VOLUME:
+ case CS42L56_DIGINPUT_ADV_VOLUME:
+ case CS42L56_MASTER_A_VOLUME:
+ case CS42L56_MASTER_B_VOLUME:
+ case CS42L56_BEEP_FREQ_ONTIME:
+ case CS42L56_BEEP_FREQ_OFFTIME:
+ case CS42L56_BEEP_TONE_CFG:
+ case CS42L56_TONE_CTL:
+ case CS42L56_CHAN_MIX_SWAP:
+ case CS42L56_AIN_REFCFG_ADC_MUX:
+ case CS42L56_HPF_CTL:
+ case CS42L56_MISC_ADC_CTL:
+ case CS42L56_GAIN_BIAS_CTL:
+ case CS42L56_PGAA_MUX_VOLUME:
+ case CS42L56_PGAB_MUX_VOLUME:
+ case CS42L56_ADCA_ATTENUATOR:
+ case CS42L56_ADCB_ATTENUATOR:
+ case CS42L56_ALC_EN_ATTACK_RATE:
+ case CS42L56_ALC_RELEASE_RATE:
+ case CS42L56_ALC_THRESHOLD:
+ case CS42L56_NOISE_GATE_CTL:
+ case CS42L56_ALC_LIM_SFT_ZC:
+ case CS42L56_AMUTE_HPLO_MUX:
+ case CS42L56_HPA_VOLUME:
+ case CS42L56_HPB_VOLUME:
+ case CS42L56_LOA_VOLUME:
+ case CS42L56_LOB_VOLUME:
+ case CS42L56_LIM_THRESHOLD_CTL:
+ case CS42L56_LIM_CTL_RELEASE_RATE:
+ case CS42L56_LIM_ATTACK_RATE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs42l56_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS42L56_INT_STATUS:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static DECLARE_TLV_DB_SCALE(beep_tlv, -5000, 200, 0);
+static DECLARE_TLV_DB_SCALE(hl_tlv, -6000, 50, 0);
+static DECLARE_TLV_DB_SCALE(adv_tlv, -10200, 50, 0);
+static DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 100, 0);
+static DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0);
+static DECLARE_TLV_DB_SCALE(preamp_tlv, 0, 1000, 0);
+static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0);
+
+static const unsigned int ngnb_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 1, TLV_DB_SCALE_ITEM(-8200, 600, 0),
+ 2, 5, TLV_DB_SCALE_ITEM(-7600, 300, 0),
+};
+static const unsigned int ngb_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 2, TLV_DB_SCALE_ITEM(-6400, 600, 0),
+ 3, 7, TLV_DB_SCALE_ITEM(-4600, 300, 0),
+};
+static const unsigned int alc_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
+ 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0),
+};
+
+static const char * const beep_config_text[] = {
+ "Off", "Single", "Multiple", "Continuous"
+};
+
+static const struct soc_enum beep_config_enum =
+ SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 6,
+ ARRAY_SIZE(beep_config_text), beep_config_text);
+
+static const char * const beep_pitch_text[] = {
+ "C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5",
+ "C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7"
+};
+
+static const struct soc_enum beep_pitch_enum =
+ SOC_ENUM_SINGLE(CS42L56_BEEP_FREQ_ONTIME, 4,
+ ARRAY_SIZE(beep_pitch_text), beep_pitch_text);
+
+static const char * const beep_ontime_text[] = {
+ "86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s",
+ "1.80 s", "2.20 s", "2.50 s", "2.80 s", "3.20 s",
+ "3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s"
+};
+
+static const struct soc_enum beep_ontime_enum =
+ SOC_ENUM_SINGLE(CS42L56_BEEP_FREQ_ONTIME, 0,
+ ARRAY_SIZE(beep_ontime_text), beep_ontime_text);
+
+static const char * const beep_offtime_text[] = {
+ "1.23 s", "2.58 s", "3.90 s", "5.20 s",
+ "6.60 s", "8.05 s", "9.35 s", "10.80 s"
+};
+
+static const struct soc_enum beep_offtime_enum =
+ SOC_ENUM_SINGLE(CS42L56_BEEP_FREQ_OFFTIME, 5,
+ ARRAY_SIZE(beep_offtime_text), beep_offtime_text);
+
+static const char * const beep_treble_text[] = {
+ "5kHz", "7kHz", "10kHz", "15kHz"
+};
+
+static const struct soc_enum beep_treble_enum =
+ SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 3,
+ ARRAY_SIZE(beep_treble_text), beep_treble_text);
+
+static const char * const beep_bass_text[] = {
+ "50Hz", "100Hz", "200Hz", "250Hz"
+};
+
+static const struct soc_enum beep_bass_enum =
+ SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 1,
+ ARRAY_SIZE(beep_bass_text), beep_bass_text);
+
+static const char * const adc_swap_text[] = {
+ "None", "A+B/2", "A-B/2", "Swap"
+};
+
+static const struct soc_enum adc_swap_enum =
+ SOC_ENUM_SINGLE(CS42L56_MISC_ADC_CTL, 3,
+ ARRAY_SIZE(adc_swap_text), adc_swap_text);
+
+static const char * const pgaa_mux_text[] = {
+ "AIN1A", "AIN2A", "AIN3A"};
+
+static const struct soc_enum pgaa_mux_enum =
+ SOC_ENUM_SINGLE(CS42L56_PGAA_MUX_VOLUME, 0,
+ ARRAY_SIZE(pgaa_mux_text),
+ pgaa_mux_text);
+
+static const struct snd_kcontrol_new pgaa_mux =
+ SOC_DAPM_ENUM("Route", pgaa_mux_enum);
+
+static const char * const pgab_mux_text[] = {
+ "AIN1B", "AIN2B", "AIN3B"};
+
+static const struct soc_enum pgab_mux_enum =
+ SOC_ENUM_SINGLE(CS42L56_PGAB_MUX_VOLUME, 0,
+ ARRAY_SIZE(pgab_mux_text),
+ pgab_mux_text);
+
+static const struct snd_kcontrol_new pgab_mux =
+ SOC_DAPM_ENUM("Route", pgab_mux_enum);
+
+static const char * const adca_mux_text[] = {
+ "PGAA", "AIN1A", "AIN2A", "AIN3A"};
+
+static const struct soc_enum adca_mux_enum =
+ SOC_ENUM_SINGLE(CS42L56_AIN_REFCFG_ADC_MUX, 0,
+ ARRAY_SIZE(adca_mux_text),
+ adca_mux_text);
+
+static const struct snd_kcontrol_new adca_mux =
+ SOC_DAPM_ENUM("Route", adca_mux_enum);
+
+static const char * const adcb_mux_text[] = {
+ "PGAB", "AIN1B", "AIN2B", "AIN3B"};
+
+static const struct soc_enum adcb_mux_enum =
+ SOC_ENUM_SINGLE(CS42L56_AIN_REFCFG_ADC_MUX, 2,
+ ARRAY_SIZE(adcb_mux_text),
+ adcb_mux_text);
+
+static const struct snd_kcontrol_new adcb_mux =
+ SOC_DAPM_ENUM("Route", adcb_mux_enum);
+
+static const char * const left_swap_text[] = {
+ "Left", "LR 2", "Right"};
+
+static const char * const right_swap_text[] = {
+ "Right", "LR 2", "Left"};
+
+static const unsigned int swap_values[] = { 0, 1, 3 };
+
+static const struct soc_enum adca_swap_enum =
+ SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 0, 3,
+ ARRAY_SIZE(left_swap_text),
+ left_swap_text,
+ swap_values);
+
+static const struct soc_enum pcma_swap_enum =
+ SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 4, 3,
+ ARRAY_SIZE(left_swap_text),
+ left_swap_text,
+ swap_values);
+
+static const struct soc_enum adcb_swap_enum =
+ SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 2, 3,
+ ARRAY_SIZE(right_swap_text),
+ right_swap_text,
+ swap_values);
+
+static const struct soc_enum pcmb_swap_enum =
+ SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 6, 3,
+ ARRAY_SIZE(right_swap_text),
+ right_swap_text,
+ swap_values);
+
+static const struct snd_kcontrol_new hpa_switch =
+ SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 6, 1, 1);
+
+static const struct snd_kcontrol_new hpb_switch =
+ SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 4, 1, 1);
+
+static const struct snd_kcontrol_new loa_switch =
+ SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 2, 1, 1);
+
+static const struct snd_kcontrol_new lob_switch =
+ SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 0, 1, 1);
+
+static const char * const hploa_input_text[] = {
+ "DACA", "PGAA"};
+
+static const struct soc_enum lineouta_input_enum =
+ SOC_ENUM_SINGLE(CS42L56_AMUTE_HPLO_MUX, 2,
+ ARRAY_SIZE(hploa_input_text),
+ hploa_input_text);
+
+static const struct snd_kcontrol_new lineouta_input =
+ SOC_DAPM_ENUM("Route", lineouta_input_enum);
+
+static const struct soc_enum hpa_input_enum =
+ SOC_ENUM_SINGLE(CS42L56_AMUTE_HPLO_MUX, 0,
+ ARRAY_SIZE(hploa_input_text),
+ hploa_input_text);
+
+static const struct snd_kcontrol_new hpa_input =
+ SOC_DAPM_ENUM("Route", hpa_input_enum);
+
+static const char * const hplob_input_text[] = {
+ "DACB", "PGAB"};
+
+static const struct soc_enum lineoutb_input_enum =
+ SOC_ENUM_SINGLE(CS42L56_AMUTE_HPLO_MUX, 3,
+ ARRAY_SIZE(hplob_input_text),
+ hplob_input_text);
+
+static const struct snd_kcontrol_new lineoutb_input =
+ SOC_DAPM_ENUM("Route", lineoutb_input_enum);
+
+static const struct soc_enum hpb_input_enum =
+ SOC_ENUM_SINGLE(CS42L56_AMUTE_HPLO_MUX, 1,
+ ARRAY_SIZE(hplob_input_text),
+ hplob_input_text);
+
+static const struct snd_kcontrol_new hpb_input =
+ SOC_DAPM_ENUM("Route", hpb_input_enum);
+
+static const char * const dig_mux_text[] = {
+ "ADC", "DSP"};
+
+static const struct soc_enum dig_mux_enum =
+ SOC_ENUM_SINGLE(CS42L56_MISC_CTL, 7,
+ ARRAY_SIZE(dig_mux_text),
+ dig_mux_text);
+
+static const struct snd_kcontrol_new dig_mux =
+ SOC_DAPM_ENUM("Route", dig_mux_enum);
+
+static const char * const hpf_freq_text[] = {
+ "1.8Hz", "119Hz", "236Hz", "464Hz"
+};
+
+static const struct soc_enum hpfa_freq_enum =
+ SOC_ENUM_SINGLE(CS42L56_HPF_CTL, 0,
+ ARRAY_SIZE(hpf_freq_text), hpf_freq_text);
+
+static const struct soc_enum hpfb_freq_enum =
+ SOC_ENUM_SINGLE(CS42L56_HPF_CTL, 2,
+ ARRAY_SIZE(hpf_freq_text), hpf_freq_text);
+
+static const char * const ng_delay_text[] = {
+ "50ms", "100ms", "150ms", "200ms"
+};
+
+static const struct soc_enum ng_delay_enum =
+ SOC_ENUM_SINGLE(CS42L56_NOISE_GATE_CTL, 0,
+ ARRAY_SIZE(ng_delay_text), ng_delay_text);
+
+static const struct snd_kcontrol_new cs42l56_snd_controls[] = {
+
+ SOC_DOUBLE_R_SX_TLV("Master Volume", CS42L56_MASTER_A_VOLUME,
+ CS42L56_MASTER_B_VOLUME, 0, 0x34, 0xfd, adv_tlv),
+ SOC_DOUBLE("Master Mute Switch", CS42L56_DSP_MUTE_CTL, 0, 1, 1, 1),
+
+ SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", CS42L56_ADCA_MIX_VOLUME,
+ CS42L56_ADCB_MIX_VOLUME, 0, 0x88, 0xa9, hl_tlv),
+ SOC_DOUBLE("ADC Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 6, 7, 1, 1),
+
+ SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", CS42L56_PCMA_MIX_VOLUME,
+ CS42L56_PCMB_MIX_VOLUME, 0, 0x88, 0xa9, hl_tlv),
+ SOC_DOUBLE("PCM Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 4, 5, 1, 1),
+
+ SOC_SINGLE_TLV("Analog Advisory Volume",
+ CS42L56_ANAINPUT_ADV_VOLUME, 0, 0x00, 1, adv_tlv),
+ SOC_SINGLE_TLV("Digital Advisory Volume",
+ CS42L56_DIGINPUT_ADV_VOLUME, 0, 0x00, 1, adv_tlv),
+
+ SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L56_PGAA_MUX_VOLUME,
+ CS42L56_PGAB_MUX_VOLUME, 0, 0x34, 0xfd, pga_tlv),
+ SOC_DOUBLE_R_TLV("ADC Volume", CS42L56_ADCA_ATTENUATOR,
+ CS42L56_ADCB_ATTENUATOR, 0, 0x00, 1, adc_tlv),
+ SOC_DOUBLE("ADC Mute Switch", CS42L56_MISC_ADC_CTL, 2, 3, 1, 1),
+ SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1),
+
+ SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME,
+ CS42L56_HPA_VOLUME, 0, 0x44, 0x55, hl_tlv),
+ SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME,
+ CS42L56_LOA_VOLUME, 0, 0x44, 0x55, hl_tlv),
+
+ SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL,
+ 0, 0x00, 1, tone_tlv),
+ SOC_SINGLE_TLV("Treble Shelving Volume", CS42L56_TONE_CTL,
+ 4, 0x00, 1, tone_tlv),
+
+ SOC_DOUBLE_TLV("PGA Preamp Volume", CS42L56_GAIN_BIAS_CTL,
+ 4, 6, 0x02, 1, preamp_tlv),
+
+ SOC_SINGLE("DSP Switch", CS42L56_PLAYBACK_CTL, 7, 1, 1),
+ SOC_SINGLE("Gang Playback Switch", CS42L56_PLAYBACK_CTL, 4, 1, 1),
+ SOC_SINGLE("Gang ADC Switch", CS42L56_MISC_ADC_CTL, 7, 1, 1),
+ SOC_SINGLE("Gang PGA Switch", CS42L56_MISC_ADC_CTL, 6, 1, 1),
+
+ SOC_SINGLE("PCMA Invert", CS42L56_PLAYBACK_CTL, 2, 1, 1),
+ SOC_SINGLE("PCMB Invert", CS42L56_PLAYBACK_CTL, 3, 1, 1),
+ SOC_SINGLE("ADCA Invert", CS42L56_MISC_ADC_CTL, 2, 1, 1),
+ SOC_SINGLE("ADCB Invert", CS42L56_MISC_ADC_CTL, 3, 1, 1),
+
+ SOC_ENUM("PCMA Swap", pcma_swap_enum),
+ SOC_ENUM("PCMB Swap", pcmb_swap_enum),
+ SOC_ENUM("ADCA Swap", adca_swap_enum),
+ SOC_ENUM("ADCB Swap", adcb_swap_enum),
+
+ SOC_DOUBLE("HPF Switch", CS42L56_HPF_CTL, 5, 7, 1, 1),
+ SOC_DOUBLE("HPF Freeze Switch", CS42L56_HPF_CTL, 4, 6, 1, 1),
+ SOC_ENUM("HPFA Corner Freq", hpfa_freq_enum),
+ SOC_ENUM("HPFB Corner Freq", hpfb_freq_enum),
+
+ SOC_SINGLE("Analog Soft Ramp", CS42L56_MISC_CTL, 4, 1, 1),
+ SOC_DOUBLE("Analog Soft Ramp Disable", CS42L56_ALC_LIM_SFT_ZC,
+ 7, 5, 1, 1),
+ SOC_SINGLE("Analog Zero Cross", CS42L56_MISC_CTL, 3, 1, 1),
+ SOC_DOUBLE("Analog Zero Cross Disable", CS42L56_ALC_LIM_SFT_ZC,
+ 6, 4, 1, 1),
+ SOC_SINGLE("Digital Soft Ramp", CS42L56_MISC_CTL, 2, 1, 1),
+ SOC_SINGLE("Digital Soft Ramp Disable", CS42L56_ALC_LIM_SFT_ZC,
+ 3, 1, 1),
+
+ SOC_SINGLE("HL Deemphasis", CS42L56_PLAYBACK_CTL, 6, 1, 1),
+
+ SOC_SINGLE("ALC Switch", CS42L56_ALC_EN_ATTACK_RATE, 6, 1, 1),
+ SOC_SINGLE("ALC Limit All Switch", CS42L56_ALC_RELEASE_RATE, 7, 1, 1),
+ SOC_SINGLE_RANGE("ALC Attack", CS42L56_ALC_EN_ATTACK_RATE,
+ 0, 0, 0x3f, 0),
+ SOC_SINGLE_RANGE("ALC Release", CS42L56_ALC_RELEASE_RATE,
+ 0, 0x3f, 0, 0),
+ SOC_SINGLE_TLV("ALC MAX", CS42L56_ALC_THRESHOLD,
+ 5, 0x07, 1, alc_tlv),
+ SOC_SINGLE_TLV("ALC MIN", CS42L56_ALC_THRESHOLD,
+ 2, 0x07, 1, alc_tlv),
+
+ SOC_SINGLE("Limiter Switch", CS42L56_LIM_CTL_RELEASE_RATE, 7, 1, 1),
+ SOC_SINGLE("Limit All Switch", CS42L56_LIM_CTL_RELEASE_RATE, 6, 1, 1),
+ SOC_SINGLE_RANGE("Limiter Attack", CS42L56_LIM_ATTACK_RATE,
+ 0, 0, 0x3f, 0),
+ SOC_SINGLE_RANGE("Limiter Release", CS42L56_LIM_CTL_RELEASE_RATE,
+ 0, 0x3f, 0, 0),
+ SOC_SINGLE_TLV("Limiter MAX", CS42L56_LIM_THRESHOLD_CTL,
+ 5, 0x07, 1, alc_tlv),
+ SOC_SINGLE_TLV("Limiter Cushion", CS42L56_ALC_THRESHOLD,
+ 2, 0x07, 1, alc_tlv),
+
+ SOC_SINGLE("NG Switch", CS42L56_NOISE_GATE_CTL, 6, 1, 1),
+ SOC_SINGLE("NG All Switch", CS42L56_NOISE_GATE_CTL, 7, 1, 1),
+ SOC_SINGLE("NG Boost Switch", CS42L56_NOISE_GATE_CTL, 5, 1, 1),
+ SOC_SINGLE_TLV("NG Unboost Threshold", CS42L56_NOISE_GATE_CTL,
+ 2, 0x07, 1, ngnb_tlv),
+ SOC_SINGLE_TLV("NG Boost Threshold", CS42L56_NOISE_GATE_CTL,
+ 2, 0x07, 1, ngb_tlv),
+ SOC_ENUM("NG Delay", ng_delay_enum),
+
+ SOC_ENUM("Beep Config", beep_config_enum),
+ SOC_ENUM("Beep Pitch", beep_pitch_enum),
+ SOC_ENUM("Beep on Time", beep_ontime_enum),
+ SOC_ENUM("Beep off Time", beep_offtime_enum),
+ SOC_SINGLE_SX_TLV("Beep Volume", CS42L56_BEEP_FREQ_OFFTIME,
+ 0, 0x07, 0x23, beep_tlv),
+ SOC_SINGLE("Beep Tone Ctl Switch", CS42L56_BEEP_TONE_CFG, 0, 1, 1),
+ SOC_ENUM("Beep Treble Corner Freq", beep_treble_enum),
+ SOC_ENUM("Beep Bass Corner Freq", beep_bass_enum),
+
+};
+
+static const struct snd_soc_dapm_widget cs42l56_dapm_widgets[] = {
+
+ SND_SOC_DAPM_SIGGEN("Beep"),
+ SND_SOC_DAPM_SUPPLY("VBUF", CS42L56_PWRCTL_1, 5, 1, NULL, 0),
+ SND_SOC_DAPM_MICBIAS("MIC1 Bias", CS42L56_PWRCTL_1, 4, 1),
+ SND_SOC_DAPM_SUPPLY("Charge Pump", CS42L56_PWRCTL_1, 3, 1, NULL, 0),
+
+ SND_SOC_DAPM_INPUT("AIN1A"),
+ SND_SOC_DAPM_INPUT("AIN2A"),
+ SND_SOC_DAPM_INPUT("AIN1B"),
+ SND_SOC_DAPM_INPUT("AIN2B"),
+ SND_SOC_DAPM_INPUT("AIN3A"),
+ SND_SOC_DAPM_INPUT("AIN3B"),
+
+ SND_SOC_DAPM_AIF_OUT("SDOUT", NULL, 0,
+ SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_AIF_IN("SDIN", NULL, 0,
+ SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_MUX("Digital Output Mux", SND_SOC_NOPM,
+ 0, 0, &dig_mux),
+
+ SND_SOC_DAPM_PGA("PGAA", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("PGAB", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MUX("PGAA Input Mux",
+ SND_SOC_NOPM, 0, 0, &pgaa_mux),
+ SND_SOC_DAPM_MUX("PGAB Input Mux",
+ SND_SOC_NOPM, 0, 0, &pgab_mux),
+
+ SND_SOC_DAPM_MUX("ADCA Mux", SND_SOC_NOPM,
+ 0, 0, &adca_mux),
+ SND_SOC_DAPM_MUX("ADCB Mux", SND_SOC_NOPM,
+ 0, 0, &adcb_mux),
+
+ SND_SOC_DAPM_ADC("ADCA", NULL, CS42L56_PWRCTL_1, 1, 1),
+ SND_SOC_DAPM_ADC("ADCB", NULL, CS42L56_PWRCTL_1, 2, 1),
+
+ SND_SOC_DAPM_DAC("DACA", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("DACB", NULL, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_OUTPUT("HPA"),
+ SND_SOC_DAPM_OUTPUT("LOA"),
+ SND_SOC_DAPM_OUTPUT("HPB"),
+ SND_SOC_DAPM_OUTPUT("LOB"),
+
+ SND_SOC_DAPM_SWITCH("Headphone Right",
+ CS42L56_PWRCTL_2, 4, 1, &hpb_switch),
+ SND_SOC_DAPM_SWITCH("Headphone Left",
+ CS42L56_PWRCTL_2, 6, 1, &hpa_switch),
+
+ SND_SOC_DAPM_SWITCH("Lineout Right",
+ CS42L56_PWRCTL_2, 0, 1, &lob_switch),
+ SND_SOC_DAPM_SWITCH("Lineout Left",
+ CS42L56_PWRCTL_2, 2, 1, &loa_switch),
+
+ SND_SOC_DAPM_MUX("LINEOUTA Input Mux", SND_SOC_NOPM,
+ 0, 0, &lineouta_input),
+ SND_SOC_DAPM_MUX("LINEOUTB Input Mux", SND_SOC_NOPM,
+ 0, 0, &lineoutb_input),
+ SND_SOC_DAPM_MUX("HPA Input Mux", SND_SOC_NOPM,
+ 0, 0, &hpa_input),
+ SND_SOC_DAPM_MUX("HPB Input Mux", SND_SOC_NOPM,
+ 0, 0, &hpb_input),
+
+};
+
+static const struct snd_soc_dapm_route cs42l56_audio_map[] = {
+
+ {"HiFi Capture", "DSP", "Digital Output Mux"},
+ {"HiFi Capture", "ADC", "Digital Output Mux"},
+
+ {"Digital Output Mux", NULL, "ADCA"},
+ {"Digital Output Mux", NULL, "ADCB"},
+
+ {"ADCB", NULL, "ADCB Mux"},
+ {"ADCA", NULL, "ADCA Mux"},
+
+ {"ADCA Mux", NULL, "AIN3A"},
+ {"ADCA Mux", NULL, "AIN2A"},
+ {"ADCA Mux", NULL, "AIN1A"},
+ {"ADCA Mux", NULL, "PGAA"},
+ {"ADCB Mux", NULL, "AIN3B"},
+ {"ADCB Mux", NULL, "AIN2B"},
+ {"ADCB Mux", NULL, "AIN1B"},
+ {"ADCB Mux", NULL, "PGAB"},
+
+ {"PGAA", "AIN1A", "PGAA Input Mux"},
+ {"PGAA", "AIN2A", "PGAA Input Mux"},
+ {"PGAA", "AIN3A", "PGAA Input Mux"},
+ {"PGAB", "AIN1B", "PGAB Input Mux"},
+ {"PGAB", "AIN2B", "PGAB Input Mux"},
+ {"PGAB", "AIN3B", "PGAB Input Mux"},
+
+ {"PGAA Input Mux", NULL, "AIN1A"},
+ {"PGAA Input Mux", NULL, "AIN2A"},
+ {"PGAA Input Mux", NULL, "AIN3A"},
+ {"PGAB Input Mux", NULL, "AIN1B"},
+ {"PGAB Input Mux", NULL, "AIN2B"},
+ {"PGAB Input Mux", NULL, "AIN3B"},
+
+ {"LOB", NULL, "Lineout Right"},
+ {"LOA", NULL, "Lineout Left"},
+
+ {"Lineout Right", "Switch", "LINEOUTB Input Mux"},
+ {"Lineout Left", "Switch", "LINEOUTA Input Mux"},
+
+ {"LINEOUTA Input Mux", "PGAA", "PGAA"},
+ {"LINEOUTB Input Mux", "PGAB", "PGAB"},
+ {"LINEOUTA Input Mux", "DACA", "DACA"},
+ {"LINEOUTB Input Mux", "DACB", "DACB"},
+
+ {"HPA", NULL, "Headphone Left"},
+ {"HPB", NULL, "Headphone Right"},
+
+ {"Headphone Right", "Switch", "HPB Input Mux"},
+ {"Headphone Left", "Switch", "HPA Input Mux"},
+
+ {"HPA Input Mux", "PGAA", "PGAA"},
+ {"HPB Input Mux", "PGAB", "PGAB"},
+ {"HPA Input Mux", "DACA", "DACA"},
+ {"HPB Input Mux", "DACB", "DACB"},
+
+ {"DACB", NULL, "HiFi Playback"},
+ {"DACA", NULL, "HiFi Playback"},
+
+};
+
+struct cs42l56_clk_para {
+ u32 mclk;
+ u32 srate;
+ u8 ratio;
+};
+
+static const struct cs42l56_clk_para clk_ratio_table[] = {
+ /* 8k */
+ { 6000000, 8000, CS42L56_MCLK_LRCLK_768 },
+ { 6144000, 8000, CS42L56_MCLK_LRCLK_750 },
+ { 12000000, 8000, CS42L56_MCLK_LRCLK_768 },
+ { 12288000, 8000, CS42L56_MCLK_LRCLK_750 },
+ { 24000000, 8000, CS42L56_MCLK_LRCLK_768 },
+ { 24576000, 8000, CS42L56_MCLK_LRCLK_750 },
+ /* 11.025k */
+ { 5644800, 11025, CS42L56_MCLK_LRCLK_512},
+ { 11289600, 11025, CS42L56_MCLK_LRCLK_512},
+ { 22579200, 11025, CS42L56_MCLK_LRCLK_512 },
+ /* 11.0294k */
+ { 6000000, 110294, CS42L56_MCLK_LRCLK_544 },
+ { 12000000, 110294, CS42L56_MCLK_LRCLK_544 },
+ { 24000000, 110294, CS42L56_MCLK_LRCLK_544 },
+ /* 12k */
+ { 6000000, 12000, CS42L56_MCLK_LRCLK_500 },
+ { 6144000, 12000, CS42L56_MCLK_LRCLK_512 },
+ { 12000000, 12000, CS42L56_MCLK_LRCLK_500 },
+ { 12288000, 12000, CS42L56_MCLK_LRCLK_512 },
+ { 24000000, 12000, CS42L56_MCLK_LRCLK_500 },
+ { 24576000, 12000, CS42L56_MCLK_LRCLK_512 },
+ /* 16k */
+ { 6000000, 16000, CS42L56_MCLK_LRCLK_375 },
+ { 6144000, 16000, CS42L56_MCLK_LRCLK_384 },
+ { 12000000, 16000, CS42L56_MCLK_LRCLK_375 },
+ { 12288000, 16000, CS42L56_MCLK_LRCLK_384 },
+ { 24000000, 16000, CS42L56_MCLK_LRCLK_375 },
+ { 24576000, 16000, CS42L56_MCLK_LRCLK_384 },
+ /* 22.050k */
+ { 5644800, 22050, CS42L56_MCLK_LRCLK_256 },
+ { 11289600, 22050, CS42L56_MCLK_LRCLK_256 },
+ { 22579200, 22050, CS42L56_MCLK_LRCLK_256 },
+ /* 22.0588k */
+ { 6000000, 220588, CS42L56_MCLK_LRCLK_272 },
+ { 12000000, 220588, CS42L56_MCLK_LRCLK_272 },
+ { 24000000, 220588, CS42L56_MCLK_LRCLK_272 },
+ /* 24k */
+ { 6000000, 24000, CS42L56_MCLK_LRCLK_250 },
+ { 6144000, 24000, CS42L56_MCLK_LRCLK_256 },
+ { 12000000, 24000, CS42L56_MCLK_LRCLK_250 },
+ { 12288000, 24000, CS42L56_MCLK_LRCLK_256 },
+ { 24000000, 24000, CS42L56_MCLK_LRCLK_250 },
+ { 24576000, 24000, CS42L56_MCLK_LRCLK_256 },
+ /* 32k */
+ { 6000000, 32000, CS42L56_MCLK_LRCLK_187P5 },
+ { 6144000, 32000, CS42L56_MCLK_LRCLK_192 },
+ { 12000000, 32000, CS42L56_MCLK_LRCLK_187P5 },
+ { 12288000, 32000, CS42L56_MCLK_LRCLK_192 },
+ { 24000000, 32000, CS42L56_MCLK_LRCLK_187P5 },
+ { 24576000, 32000, CS42L56_MCLK_LRCLK_192 },
+ /* 44.118k */
+ { 6000000, 44118, CS42L56_MCLK_LRCLK_136 },
+ { 12000000, 44118, CS42L56_MCLK_LRCLK_136 },
+ { 24000000, 44118, CS42L56_MCLK_LRCLK_136 },
+ /* 44.1k */
+ { 5644800, 44100, CS42L56_MCLK_LRCLK_128 },
+ { 11289600, 44100, CS42L56_MCLK_LRCLK_128 },
+ { 22579200, 44100, CS42L56_MCLK_LRCLK_128 },
+ /* 48k */
+ { 6000000, 48000, CS42L56_MCLK_LRCLK_125 },
+ { 6144000, 48000, CS42L56_MCLK_LRCLK_128 },
+ { 12000000, 48000, CS42L56_MCLK_LRCLK_125 },
+ { 12288000, 48000, CS42L56_MCLK_LRCLK_128 },
+ { 24000000, 48000, CS42L56_MCLK_LRCLK_125 },
+ { 24576000, 48000, CS42L56_MCLK_LRCLK_128 },
+};
+
+static int cs42l56_get_mclk_ratio(int mclk, int rate)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(clk_ratio_table); i++) {
+ if (clk_ratio_table[i].mclk == mclk &&
+ clk_ratio_table[i].srate == rate)
+ return clk_ratio_table[i].ratio;
+ }
+ return -EINVAL;
+}
+
+static int cs42l56_set_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
+
+ switch (freq) {
+ case CS42L56_MCLK_5P6448MHZ:
+ case CS42L56_MCLK_6MHZ:
+ case CS42L56_MCLK_6P144MHZ:
+ cs42l56->mclk_div2 = 0;
+ cs42l56->mclk_prediv = 0;
+ break;
+ case CS42L56_MCLK_11P2896MHZ:
+ case CS42L56_MCLK_12MHZ:
+ case CS42L56_MCLK_12P288MHZ:
+ cs42l56->mclk_div2 = CS42L56_MCLK_DIV2;
+ cs42l56->mclk_prediv = 0;
+ break;
+ case CS42L56_MCLK_22P5792MHZ:
+ case CS42L56_MCLK_24MHZ:
+ case CS42L56_MCLK_24P576MHZ:
+ cs42l56->mclk_div2 = CS42L56_MCLK_DIV2;
+ cs42l56->mclk_prediv = CS42L56_MCLK_PREDIV;
+ break;
+ default:
+ return -EINVAL;
+ }
+ cs42l56->mclk = freq;
+
+ snd_soc_update_bits(codec, CS42L56_CLKCTL_1,
+ CS42L56_MCLK_PREDIV_MASK,
+ cs42l56->mclk_prediv);
+ snd_soc_update_bits(codec, CS42L56_CLKCTL_1,
+ CS42L56_MCLK_DIV2_MASK,
+ cs42l56->mclk_div2);
+
+ return 0;
+}
+
+static int cs42l56_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ cs42l56->iface = CS42L56_MASTER_MODE;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ cs42l56->iface = CS42L56_SLAVE_MODE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ cs42l56->iface_fmt = CS42L56_DIG_FMT_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ cs42l56->iface_fmt = CS42L56_DIG_FMT_LEFT_J;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* sclk inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ cs42l56->iface_inv = 0;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ cs42l56->iface_inv = CS42L56_SCLK_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, CS42L56_CLKCTL_1,
+ CS42L56_MS_MODE_MASK, cs42l56->iface);
+ snd_soc_update_bits(codec, CS42L56_SERIAL_FMT,
+ CS42L56_DIG_FMT_MASK, cs42l56->iface_fmt);
+ snd_soc_update_bits(codec, CS42L56_CLKCTL_1,
+ CS42L56_SCLK_INV_MASK, cs42l56->iface_inv);
+ return 0;
+}
+
+static int cs42l56_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+
+ if (mute) {
+ /* Hit the DSP Mixer first */
+ snd_soc_update_bits(codec, CS42L56_DSP_MUTE_CTL,
+ CS42L56_ADCAMIX_MUTE_MASK |
+ CS42L56_ADCBMIX_MUTE_MASK |
+ CS42L56_PCMAMIX_MUTE_MASK |
+ CS42L56_PCMBMIX_MUTE_MASK |
+ CS42L56_MSTB_MUTE_MASK |
+ CS42L56_MSTA_MUTE_MASK,
+ CS42L56_MUTE_ALL);
+ /* Mute ADC's */
+ snd_soc_update_bits(codec, CS42L56_MISC_ADC_CTL,
+ CS42L56_ADCA_MUTE_MASK |
+ CS42L56_ADCB_MUTE_MASK,
+ CS42L56_MUTE_ALL);
+ /* HP And LO */
+ snd_soc_update_bits(codec, CS42L56_HPA_VOLUME,
+ CS42L56_HP_MUTE_MASK, CS42L56_MUTE_ALL);
+ snd_soc_update_bits(codec, CS42L56_HPB_VOLUME,
+ CS42L56_HP_MUTE_MASK, CS42L56_MUTE_ALL);
+ snd_soc_update_bits(codec, CS42L56_LOA_VOLUME,
+ CS42L56_LO_MUTE_MASK, CS42L56_MUTE_ALL);
+ snd_soc_update_bits(codec, CS42L56_LOB_VOLUME,
+ CS42L56_LO_MUTE_MASK, CS42L56_MUTE_ALL);
+ } else {
+ snd_soc_update_bits(codec, CS42L56_DSP_MUTE_CTL,
+ CS42L56_ADCAMIX_MUTE_MASK |
+ CS42L56_ADCBMIX_MUTE_MASK |
+ CS42L56_PCMAMIX_MUTE_MASK |
+ CS42L56_PCMBMIX_MUTE_MASK |
+ CS42L56_MSTB_MUTE_MASK |
+ CS42L56_MSTA_MUTE_MASK,
+ CS42L56_UNMUTE);
+
+ snd_soc_update_bits(codec, CS42L56_MISC_ADC_CTL,
+ CS42L56_ADCA_MUTE_MASK |
+ CS42L56_ADCB_MUTE_MASK,
+ CS42L56_UNMUTE);
+
+ snd_soc_update_bits(codec, CS42L56_HPA_VOLUME,
+ CS42L56_HP_MUTE_MASK, CS42L56_UNMUTE);
+ snd_soc_update_bits(codec, CS42L56_HPB_VOLUME,
+ CS42L56_HP_MUTE_MASK, CS42L56_UNMUTE);
+ snd_soc_update_bits(codec, CS42L56_LOA_VOLUME,
+ CS42L56_LO_MUTE_MASK, CS42L56_UNMUTE);
+ snd_soc_update_bits(codec, CS42L56_LOB_VOLUME,
+ CS42L56_LO_MUTE_MASK, CS42L56_UNMUTE);
+ }
+ return 0;
+}
+
+static int cs42l56_pcm_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;
+ struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
+ int ratio;
+
+ ratio = cs42l56_get_mclk_ratio(cs42l56->mclk, params_rate(params));
+ if (ratio >= 0) {
+ snd_soc_update_bits(codec, CS42L56_CLKCTL_2,
+ CS42L56_CLK_RATIO_MASK, ratio);
+ } else {
+ dev_err(codec->dev, "unsupported mclk/sclk/lrclk ratio\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cs42l56_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ snd_soc_update_bits(codec, CS42L56_CLKCTL_1,
+ CS42L56_MCLK_DIS_MASK, 0);
+ snd_soc_update_bits(codec, CS42L56_PWRCTL_1,
+ CS42L56_PDN_ALL_MASK, 0);
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ regcache_cache_only(cs42l56->regmap, false);
+ regcache_sync(cs42l56->regmap);
+ ret = regulator_bulk_enable(ARRAY_SIZE(cs42l56->supplies),
+ cs42l56->supplies);
+ if (ret != 0) {
+ dev_err(cs42l56->dev,
+ "Failed to enable regulators: %d\n",
+ ret);
+ return ret;
+ }
+ }
+ snd_soc_update_bits(codec, CS42L56_PWRCTL_1,
+ CS42L56_PDN_ALL_MASK, 1);
+ break;
+ case SND_SOC_BIAS_OFF:
+ snd_soc_update_bits(codec, CS42L56_PWRCTL_1,
+ CS42L56_PDN_ALL_MASK, 1);
+ snd_soc_update_bits(codec, CS42L56_CLKCTL_1,
+ CS42L56_MCLK_DIS_MASK, 1);
+ regcache_cache_only(cs42l56->regmap, true);
+ regulator_bulk_disable(ARRAY_SIZE(cs42l56->supplies),
+ cs42l56->supplies);
+ break;
+ }
+ codec->dapm.bias_level = level;
+
+ return 0;
+}
+
+#define CS42L56_RATES (SNDRV_PCM_RATE_8000_48000)
+
+#define CS42L56_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+
+static struct snd_soc_dai_ops cs42l56_ops = {
+ .hw_params = cs42l56_pcm_hw_params,
+ .digital_mute = cs42l56_digital_mute,
+ .set_fmt = cs42l56_set_dai_fmt,
+ .set_sysclk = cs42l56_set_sysclk,
+};
+
+static struct snd_soc_dai_driver cs42l56_dai = {
+ .name = "cs42l56",
+ .playback = {
+ .stream_name = "HiFi Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = CS42L56_RATES,
+ .formats = CS42L56_FORMATS,
+ },
+ .capture = {
+ .stream_name = "HiFi Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = CS42L56_RATES,
+ .formats = CS42L56_FORMATS,
+ },
+ .ops = &cs42l56_ops,
+};
+
+static int cs42l56_suspend(struct snd_soc_codec *codec)
+{
+ cs42l56_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static int cs42l56_resume(struct snd_soc_codec *codec)
+{
+ cs42l56_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ return 0;
+}
+
+static int beep_freq[] = {
+ 261, 522, 585, 667, 706, 774, 889, 1000,
+ 1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182
+};
+
+static void cs42l56_beep_work(struct work_struct *work)
+{
+ struct cs42l56_private *cs42l56 =
+ container_of(work, struct cs42l56_private, beep_work);
+ struct snd_soc_codec *codec = cs42l56->codec;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ int i;
+ int val = 0;
+ int best = 0;
+
+ if (cs42l56->beep_rate) {
+ for (i = 0; i < ARRAY_SIZE(beep_freq); i++) {
+ if (abs(cs42l56->beep_rate - beep_freq[i]) <
+ abs(cs42l56->beep_rate - beep_freq[best]))
+ best = i;
+ }
+
+ dev_dbg(codec->dev, "Set beep rate %dHz for requested %dHz\n",
+ beep_freq[best], cs42l56->beep_rate);
+
+ val = (best << CS42L56_BEEP_RATE_SHIFT);
+
+ snd_soc_dapm_enable_pin(dapm, "Beep");
+ } else {
+ dev_dbg(codec->dev, "Disabling beep\n");
+ snd_soc_dapm_disable_pin(dapm, "Beep");
+ }
+
+ snd_soc_update_bits(codec, CS42L56_BEEP_FREQ_ONTIME,
+ CS42L56_BEEP_FREQ_MASK, val);
+
+ snd_soc_dapm_sync(dapm);
+}
+
+/* For usability define a way of injecting beep events for the device -
+ * many systems will not have a keyboard.
+ */
+static int cs42l56_beep_event(struct input_dev *dev, unsigned int type,
+ unsigned int code, int hz)
+{
+ struct snd_soc_codec *codec = input_get_drvdata(dev);
+ struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "Beep event %x %x\n", code, hz);
+
+ switch (code) {
+ case SND_BELL:
+ if (hz)
+ hz = 261;
+ case SND_TONE:
+ break;
+ default:
+ return -1;
+ }
+
+ /* Kick the beep from a workqueue */
+ cs42l56->beep_rate = hz;
+ schedule_work(&cs42l56->beep_work);
+ return 0;
+}
+
+static ssize_t cs42l56_beep_set(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cs42l56_private *cs42l56 = dev_get_drvdata(dev);
+ long int time;
+ int ret;
+
+ ret = kstrtol(buf, 10, &time);
+ if (ret != 0)
+ return ret;
+
+ input_event(cs42l56->beep, EV_SND, SND_TONE, time);
+
+ return count;
+}
+
+static DEVICE_ATTR(beep, 0200, NULL, cs42l56_beep_set);
+
+static void cs42l56_init_beep(struct snd_soc_codec *codec)
+{
+ struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ cs42l56->beep = devm_input_allocate_device(codec->dev);
+ if (!cs42l56->beep) {
+ dev_err(codec->dev, "Failed to allocate beep device\n");
+ return;
+ }
+
+ INIT_WORK(&cs42l56->beep_work, cs42l56_beep_work);
+ cs42l56->beep_rate = 0;
+
+ cs42l56->beep->name = "CS42L56 Beep Generator";
+ cs42l56->beep->phys = dev_name(codec->dev);
+ cs42l56->beep->id.bustype = BUS_I2C;
+
+ cs42l56->beep->evbit[0] = BIT_MASK(EV_SND);
+ cs42l56->beep->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
+ cs42l56->beep->event = cs42l56_beep_event;
+ cs42l56->beep->dev.parent = codec->dev;
+ input_set_drvdata(cs42l56->beep, codec);
+
+ ret = input_register_device(cs42l56->beep);
+ if (ret != 0) {
+ cs42l56->beep = NULL;
+ dev_err(codec->dev, "Failed to register beep device\n");
+ }
+
+ ret = device_create_file(codec->dev, &dev_attr_beep);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to create keyclick file: %d\n",
+ ret);
+ }
+}
+
+static void cs42l56_free_beep(struct snd_soc_codec *codec)
+{
+ struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
+
+ device_remove_file(codec->dev, &dev_attr_beep);
+ cancel_work_sync(&cs42l56->beep_work);
+ cs42l56->beep = NULL;
+
+ snd_soc_update_bits(codec, CS42L56_BEEP_TONE_CFG,
+ CS42L56_BEEP_EN_MASK, 0);
+}
+
+static int cs42l56_probe(struct snd_soc_codec *codec)
+{
+ cs42l56_init_beep(codec);
+
+ cs42l56_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ return 0;
+}
+
+static int cs42l56_remove(struct snd_soc_codec *codec)
+{
+ struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
+
+ cs42l56_free_beep(codec);
+ cs42l56_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ regulator_bulk_free(ARRAY_SIZE(cs42l56->supplies), cs42l56->supplies);
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_cs42l56 = {
+ .probe = cs42l56_probe,
+ .remove = cs42l56_remove,
+ .suspend = cs42l56_suspend,
+ .resume = cs42l56_resume,
+ .set_bias_level = cs42l56_set_bias_level,
+
+ .dapm_widgets = cs42l56_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(cs42l56_dapm_widgets),
+ .dapm_routes = cs42l56_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(cs42l56_audio_map),
+
+ .controls = cs42l56_snd_controls,
+ .num_controls = ARRAY_SIZE(cs42l56_snd_controls),
+};
+
+static struct regmap_config cs42l56_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = CS42L56_MAX_REGISTER,
+ .reg_defaults = cs42l56_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(cs42l56_reg_defaults),
+ .readable_reg = cs42l56_readable_register,
+ .volatile_reg = cs42l56_volatile_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int cs42l56_handle_of_data(struct i2c_client *i2c_client,
+ struct cs42l56_platform_data *pdata)
+{
+ struct device_node *np = i2c_client->dev.of_node;
+ u32 val32;
+
+ if (of_property_read_bool(np, "cirrus,ain1a-reference-cfg"))
+ pdata->ain1a_ref_cfg = true;
+
+ if (of_property_read_bool(np, "cirrus,ain2a-reference-cfg"))
+ pdata->ain2a_ref_cfg = true;
+
+ if (of_property_read_bool(np, "cirrus,ain1b-reference-cfg"))
+ pdata->ain1b_ref_cfg = true;
+
+ if (of_property_read_bool(np, "cirrus,ain2b-reference-cfg"))
+ pdata->ain2b_ref_cfg = true;
+
+ if (of_property_read_u32(np, "cirrus,micbias-lvl", &val32) >= 0)
+ pdata->micbias_lvl = val32;
+
+ if (of_property_read_u32(np, "cirrus,chgfreq-divisor", &val32) >= 0)
+ pdata->chgfreq = val32;
+
+ if (of_property_read_u32(np, "cirrus,adaptive-pwr-cfg", &val32) >= 0)
+ pdata->adaptive_pwr = val32;
+
+ if (of_property_read_u32(np, "cirrus,hpf-left-freq", &val32) >= 0)
+ pdata->hpfa_freq = val32;
+
+ if (of_property_read_u32(np, "cirrus,hpf-left-freq", &val32) >= 0)
+ pdata->hpfb_freq = val32;
+
+ pdata->gpio_nreset = of_get_named_gpio(np, "cirrus,gpio-nreset", 0);
+
+ return 0;
+}
+
+static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
+ const struct i2c_device_id *id)
+{
+ struct cs42l56_private *cs42l56;
+ struct cs42l56_platform_data *pdata =
+ dev_get_platdata(&i2c_client->dev);
+ int ret, i;
+ unsigned int devid = 0;
+ unsigned int alpha_rev, metal_rev;
+ unsigned int reg;
+
+ cs42l56 = devm_kzalloc(&i2c_client->dev,
+ sizeof(struct cs42l56_private),
+ GFP_KERNEL);
+ if (cs42l56 == NULL)
+ return -ENOMEM;
+ cs42l56->dev = &i2c_client->dev;
+
+ cs42l56->regmap = devm_regmap_init_i2c(i2c_client, &cs42l56_regmap);
+ if (IS_ERR(cs42l56->regmap)) {
+ ret = PTR_ERR(cs42l56->regmap);
+ dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+ return ret;
+ }
+
+ if (pdata) {
+ cs42l56->pdata = *pdata;
+ } else {
+ pdata = devm_kzalloc(&i2c_client->dev,
+ sizeof(struct cs42l56_platform_data),
+ GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&i2c_client->dev,
+ "could not allocate pdata\n");
+ return -ENOMEM;
+ }
+ if (i2c_client->dev.of_node) {
+ ret = cs42l56_handle_of_data(i2c_client,
+ &cs42l56->pdata);
+ if (ret != 0)
+ return ret;
+ }
+ cs42l56->pdata = *pdata;
+ }
+
+ if (cs42l56->pdata.gpio_nreset) {
+ ret = gpio_request_one(cs42l56->pdata.gpio_nreset,
+ GPIOF_OUT_INIT_HIGH, "CS42L56 /RST");
+ if (ret < 0) {
+ dev_err(&i2c_client->dev,
+ "Failed to request /RST %d: %d\n",
+ cs42l56->pdata.gpio_nreset, ret);
+ return ret;
+ }
+ gpio_set_value_cansleep(cs42l56->pdata.gpio_nreset, 0);
+ gpio_set_value_cansleep(cs42l56->pdata.gpio_nreset, 1);
+ }
+
+
+ i2c_set_clientdata(i2c_client, cs42l56);
+
+ for (i = 0; i < ARRAY_SIZE(cs42l56->supplies); i++)
+ cs42l56->supplies[i].supply = cs42l56_supply_names[i];
+
+ ret = devm_regulator_bulk_get(&i2c_client->dev,
+ ARRAY_SIZE(cs42l56->supplies),
+ cs42l56->supplies);
+ if (ret != 0) {
+ dev_err(&i2c_client->dev,
+ "Failed to request supplies: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(cs42l56->supplies),
+ cs42l56->supplies);
+ if (ret != 0) {
+ dev_err(&i2c_client->dev,
+ "Failed to enable supplies: %d\n", ret);
+ return ret;
+ }
+
+ regcache_cache_bypass(cs42l56->regmap, true);
+
+ ret = regmap_read(cs42l56->regmap, CS42L56_CHIP_ID_1, &reg);
+ devid = reg & CS42L56_CHIP_ID_MASK;
+ if (devid != CS42L56_DEVID) {
+ dev_err(&i2c_client->dev,
+ "CS42L56 Device ID (%X). Expected %X\n",
+ devid, CS42L56_DEVID);
+ goto err_enable;
+ }
+ alpha_rev = reg & CS42L56_AREV_MASK;
+ metal_rev = reg & CS42L56_MTLREV_MASK;
+
+ dev_info(&i2c_client->dev, "Cirrus Logic CS42L56 ");
+ dev_info(&i2c_client->dev, "Alpha Rev %X Metal Rev %X\n",
+ alpha_rev, metal_rev);
+
+ regcache_cache_bypass(cs42l56->regmap, false);
+
+ if (cs42l56->pdata.ain1a_ref_cfg)
+ regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX,
+ CS42L56_AIN1A_REF_MASK, 1);
+
+ if (cs42l56->pdata.ain1b_ref_cfg)
+ regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX,
+ CS42L56_AIN1B_REF_MASK, 1);
+
+ if (cs42l56->pdata.ain2a_ref_cfg)
+ regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX,
+ CS42L56_AIN2A_REF_MASK, 1);
+
+ if (cs42l56->pdata.ain2b_ref_cfg)
+ regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX,
+ CS42L56_AIN2B_REF_MASK, 1);
+
+ if (cs42l56->pdata.micbias_lvl)
+ regmap_update_bits(cs42l56->regmap, CS42L56_GAIN_BIAS_CTL,
+ CS42L56_MIC_BIAS_MASK,
+ cs42l56->pdata.micbias_lvl);
+
+ if (cs42l56->pdata.chgfreq)
+ regmap_update_bits(cs42l56->regmap, CS42L56_CLASSH_CTL,
+ CS42L56_CHRG_FREQ_MASK,
+ cs42l56->pdata.chgfreq);
+
+ if (cs42l56->pdata.hpfb_freq)
+ regmap_update_bits(cs42l56->regmap, CS42L56_HPF_CTL,
+ CS42L56_HPFB_FREQ_MASK,
+ cs42l56->pdata.hpfb_freq);
+
+ if (cs42l56->pdata.hpfa_freq)
+ regmap_update_bits(cs42l56->regmap, CS42L56_HPF_CTL,
+ CS42L56_HPFA_FREQ_MASK,
+ cs42l56->pdata.hpfa_freq);
+
+ if (cs42l56->pdata.adaptive_pwr)
+ regmap_update_bits(cs42l56->regmap, CS42L56_CLASSH_CTL,
+ CS42L56_ADAPT_PWR_MASK,
+ cs42l56->pdata.adaptive_pwr);
+
+ ret = snd_soc_register_codec(&i2c_client->dev,
+ &soc_codec_dev_cs42l56, &cs42l56_dai, 1);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(cs42l56->supplies),
+ cs42l56->supplies);
+ return ret;
+}
+
+static int cs42l56_i2c_remove(struct i2c_client *client)
+{
+ struct cs42l56_private *cs42l56 = i2c_get_clientdata(client);
+
+ snd_soc_unregister_codec(&client->dev);
+ regulator_bulk_disable(ARRAY_SIZE(cs42l56->supplies),
+ cs42l56->supplies);
+ return 0;
+}
+
+static const struct of_device_id cs42l56_of_match[] = {
+ { .compatible = "cirrus,cs42l56", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, cs42l56_of_match);
+
+
+static const struct i2c_device_id cs42l56_id[] = {
+ { "cs42l56", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, cs42l56_id);
+
+static struct i2c_driver cs42l56_i2c_driver = {
+ .driver = {
+ .name = "cs42l56",
+ .owner = THIS_MODULE,
+ .of_match_table = cs42l56_of_match,
+ },
+ .id_table = cs42l56_id,
+ .probe = cs42l56_i2c_probe,
+ .remove = cs42l56_i2c_remove,
+};
+
+module_i2c_driver(cs42l56_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC CS42L56 driver");
+MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l56.h b/sound/soc/codecs/cs42l56.h
new file mode 100644
index 00000000000..5025ec9be9b
--- /dev/null
+++ b/sound/soc/codecs/cs42l56.h
@@ -0,0 +1,177 @@
+/*
+ * cs42l52.h -- CS42L56 ALSA SoC audio driver
+ *
+ * Copyright 2014 CirrusLogic, Inc.
+ *
+ * Author: Brian Austin <brian.austin@cirrus.com>
+ *
+ * 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 __CS42L56_H__
+#define __CS42L56_H__
+
+#define CS42L56_CHIP_ID_1 0x01
+#define CS42L56_CHIP_ID_2 0x02
+#define CS42L56_PWRCTL_1 0x03
+#define CS42L56_PWRCTL_2 0x04
+#define CS42L56_CLKCTL_1 0x05
+#define CS42L56_CLKCTL_2 0x06
+#define CS42L56_SERIAL_FMT 0x07
+#define CS42L56_CLASSH_CTL 0x08
+#define CS42L56_MISC_CTL 0x09
+#define CS42L56_INT_STATUS 0x0a
+#define CS42L56_PLAYBACK_CTL 0x0b
+#define CS42L56_DSP_MUTE_CTL 0x0c
+#define CS42L56_ADCA_MIX_VOLUME 0x0d
+#define CS42L56_ADCB_MIX_VOLUME 0x0e
+#define CS42L56_PCMA_MIX_VOLUME 0x0f
+#define CS42L56_PCMB_MIX_VOLUME 0x10
+#define CS42L56_ANAINPUT_ADV_VOLUME 0x11
+#define CS42L56_DIGINPUT_ADV_VOLUME 0x12
+#define CS42L56_MASTER_A_VOLUME 0x13
+#define CS42L56_MASTER_B_VOLUME 0x14
+#define CS42L56_BEEP_FREQ_ONTIME 0x15
+#define CS42L56_BEEP_FREQ_OFFTIME 0x16
+#define CS42L56_BEEP_TONE_CFG 0x17
+#define CS42L56_TONE_CTL 0x18
+#define CS42L56_CHAN_MIX_SWAP 0x19
+#define CS42L56_AIN_REFCFG_ADC_MUX 0x1a
+#define CS42L56_HPF_CTL 0x1b
+#define CS42L56_MISC_ADC_CTL 0x1c
+#define CS42L56_GAIN_BIAS_CTL 0x1d
+#define CS42L56_PGAA_MUX_VOLUME 0x1e
+#define CS42L56_PGAB_MUX_VOLUME 0x1f
+#define CS42L56_ADCA_ATTENUATOR 0x20
+#define CS42L56_ADCB_ATTENUATOR 0x21
+#define CS42L56_ALC_EN_ATTACK_RATE 0x22
+#define CS42L56_ALC_RELEASE_RATE 0x23
+#define CS42L56_ALC_THRESHOLD 0x24
+#define CS42L56_NOISE_GATE_CTL 0x25
+#define CS42L56_ALC_LIM_SFT_ZC 0x26
+#define CS42L56_AMUTE_HPLO_MUX 0x27
+#define CS42L56_HPA_VOLUME 0x28
+#define CS42L56_HPB_VOLUME 0x29
+#define CS42L56_LOA_VOLUME 0x2a
+#define CS42L56_LOB_VOLUME 0x2b
+#define CS42L56_LIM_THRESHOLD_CTL 0x2c
+#define CS42L56_LIM_CTL_RELEASE_RATE 0x2d
+#define CS42L56_LIM_ATTACK_RATE 0x2e
+
+/* Device ID and Rev ID Masks */
+#define CS42L56_DEVID 0x56
+#define CS42L56_CHIP_ID_MASK 0xff
+#define CS42L56_AREV_MASK 0x1c
+#define CS42L56_MTLREV_MASK 0x03
+
+/* Power bit masks */
+#define CS42L56_PDN_ALL_MASK 0x01
+#define CS42L56_PDN_ADCA_MASK 0x02
+#define CS42L56_PDN_ADCB_MASK 0x04
+#define CS42L56_PDN_CHRG_MASK 0x08
+#define CS42L56_PDN_BIAS_MASK 0x10
+#define CS42L56_PDN_VBUF_MASK 0x20
+#define CS42L56_PDN_LOA_MASK 0x03
+#define CS42L56_PDN_LOB_MASK 0x0c
+#define CS42L56_PDN_HPA_MASK 0x30
+#define CS42L56_PDN_HPB_MASK 0xc0
+
+/* serial port and clk masks */
+#define CS42L56_MASTER_MODE 0x40
+#define CS42L56_SLAVE_MODE 0
+#define CS42L56_MS_MODE_MASK 0x40
+#define CS42L56_SCLK_INV 0x20
+#define CS42L56_SCLK_INV_MASK 0x20
+#define CS42L56_SCLK_MCLK_MASK 0x18
+#define CS42L56_MCLK_PREDIV 0x04
+#define CS42L56_MCLK_PREDIV_MASK 0x04
+#define CS42L56_MCLK_DIV2 0x02
+#define CS42L56_MCLK_DIV2_MASK 0x02
+#define CS42L56_MCLK_DIS_MASK 0x01
+#define CS42L56_CLK_AUTO_MASK 0x20
+#define CS42L56_CLK_RATIO_MASK 0x1f
+#define CS42L56_DIG_FMT_I2S 0
+#define CS42L56_DIG_FMT_LEFT_J 0x08
+#define CS42L56_DIG_FMT_MASK 0x08
+
+/* Class H and misc ctl masks */
+#define CS42L56_ADAPT_PWR_MASK 0xc0
+#define CS42L56_CHRG_FREQ_MASK 0x0f
+#define CS42L56_DIG_MUX_MASK 0x80
+#define CS42L56_ANLGSFT_MASK 0x10
+#define CS42L56_ANLGZC_MASK 0x08
+#define CS42L56_DIGSFT_MASK 0x04
+#define CS42L56_FREEZE_MASK 0x01
+#define CS42L56_MIC_BIAS_MASK 0x03
+#define CS42L56_HPFA_FREQ_MASK 0x03
+#define CS42L56_HPFB_FREQ_MASK 0xc0
+#define CS42L56_AIN1A_REF_MASK 0x10
+#define CS42L56_AIN2A_REF_MASK 0x40
+#define CS42L56_AIN1B_REF_MASK 0x20
+#define CS42L56_AIN2B_REF_MASK 0x80
+
+/* Playback Capture ctl masks */
+#define CS42L56_PDN_DSP_MASK 0x80
+#define CS42L56_DEEMPH_MASK 0x40
+#define CS42L56_PLYBCK_GANG_MASK 0x10
+#define CS42L56_PCM_INV_MASK 0x0c
+#define CS42L56_MUTE_ALL 0xff
+#define CS42L56_UNMUTE 0
+#define CS42L56_ADCAMIX_MUTE_MASK 0x40
+#define CS42L56_ADCBMIX_MUTE_MASK 0x80
+#define CS42L56_PCMAMIX_MUTE_MASK 0x10
+#define CS42L56_PCMBMIX_MUTE_MASK 0x20
+#define CS42L56_MSTB_MUTE_MASK 0x02
+#define CS42L56_MSTA_MUTE_MASK 0x01
+#define CS42L56_ADCA_MUTE_MASK 0x01
+#define CS42L56_ADCB_MUTE_MASK 0x02
+#define CS42L56_HP_MUTE_MASK 0x80
+#define CS42L56_LO_MUTE_MASK 0x80
+
+/* Beep masks */
+#define CS42L56_BEEP_FREQ_MASK 0xf0
+#define CS42L56_BEEP_ONTIME_MASK 0x0f
+#define CS42L56_BEEP_OFFTIME_MASK 0xe0
+#define CS42L56_BEEP_CFG_MASK 0xc0
+#define CS42L56_BEEP_TREBCF_MASK 0x18
+#define CS42L56_BEEP_BASSCF_MASK 0x06
+#define CS42L56_BEEP_TCEN_MASK 0x01
+#define CS42L56_BEEP_RATE_SHIFT 4
+#define CS42L56_BEEP_EN_MASK 0x3f
+
+
+/* Supported MCLKS */
+#define CS42L56_MCLK_5P6448MHZ 5644800
+#define CS42L56_MCLK_6MHZ 6000000
+#define CS42L56_MCLK_6P144MHZ 6144000
+#define CS42L56_MCLK_11P2896MHZ 11289600
+#define CS42L56_MCLK_12MHZ 12000000
+#define CS42L56_MCLK_12P288MHZ 12288000
+#define CS42L56_MCLK_22P5792MHZ 22579200
+#define CS42L56_MCLK_24MHZ 24000000
+#define CS42L56_MCLK_24P576MHZ 24576000
+
+/* Clock ratios */
+#define CS42L56_MCLK_LRCLK_128 0x08
+#define CS42L56_MCLK_LRCLK_125 0x09
+#define CS42L56_MCLK_LRCLK_136 0x0b
+#define CS42L56_MCLK_LRCLK_192 0x0c
+#define CS42L56_MCLK_LRCLK_187P5 0x0d
+#define CS42L56_MCLK_LRCLK_256 0x10
+#define CS42L56_MCLK_LRCLK_250 0x11
+#define CS42L56_MCLK_LRCLK_272 0x13
+#define CS42L56_MCLK_LRCLK_384 0x14
+#define CS42L56_MCLK_LRCLK_375 0x15
+#define CS42L56_MCLK_LRCLK_512 0x18
+#define CS42L56_MCLK_LRCLK_500 0x19
+#define CS42L56_MCLK_LRCLK_544 0x1b
+#define CS42L56_MCLK_LRCLK_750 0x1c
+#define CS42L56_MCLK_LRCLK_768 0x1d
+
+
+#define CS42L56_MAX_REGISTER 0x34
+
+#endif
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index 549d5d6a3fe..ae3717992d5 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -278,13 +278,13 @@ static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1);
static const char * const cs42l73_pgaa_text[] = { "Line A", "Mic 1" };
static const char * const cs42l73_pgab_text[] = { "Line B", "Mic 2" };
-static const struct soc_enum pgaa_enum =
- SOC_ENUM_SINGLE(CS42L73_ADCIPC, 3,
- ARRAY_SIZE(cs42l73_pgaa_text), cs42l73_pgaa_text);
+static SOC_ENUM_SINGLE_DECL(pgaa_enum,
+ CS42L73_ADCIPC, 3,
+ cs42l73_pgaa_text);
-static const struct soc_enum pgab_enum =
- SOC_ENUM_SINGLE(CS42L73_ADCIPC, 7,
- ARRAY_SIZE(cs42l73_pgab_text), cs42l73_pgab_text);
+static SOC_ENUM_SINGLE_DECL(pgab_enum,
+ CS42L73_ADCIPC, 7,
+ cs42l73_pgab_text);
static const struct snd_kcontrol_new pgaa_mux =
SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum);
@@ -309,9 +309,9 @@ static const struct snd_kcontrol_new input_right_mixer[] = {
static const char * const cs42l73_ng_delay_text[] = {
"50ms", "100ms", "150ms", "200ms" };
-static const struct soc_enum ng_delay_enum =
- SOC_ENUM_SINGLE(CS42L73_NGCAB, 0,
- ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text);
+static SOC_ENUM_SINGLE_DECL(ng_delay_enum,
+ CS42L73_NGCAB, 0,
+ cs42l73_ng_delay_text);
static const char * const cs42l73_mono_mix_texts[] = {
"Left", "Right", "Mono Mix"};
@@ -319,7 +319,7 @@ static const char * const cs42l73_mono_mix_texts[] = {
static const unsigned int cs42l73_mono_mix_values[] = { 0, 1, 2 };
static const struct soc_enum spk_asp_enum =
- SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 1,
+ SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 3,
ARRAY_SIZE(cs42l73_mono_mix_texts),
cs42l73_mono_mix_texts,
cs42l73_mono_mix_values);
@@ -337,7 +337,7 @@ static const struct snd_kcontrol_new spk_xsp_mixer =
SOC_DAPM_ENUM("Route", spk_xsp_enum);
static const struct soc_enum esl_asp_enum =
- SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 5,
+ SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 3,
ARRAY_SIZE(cs42l73_mono_mix_texts),
cs42l73_mono_mix_texts,
cs42l73_mono_mix_values);
@@ -346,7 +346,7 @@ static const struct snd_kcontrol_new esl_asp_mixer =
SOC_DAPM_ENUM("Route", esl_asp_enum);
static const struct soc_enum esl_xsp_enum =
- SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 7,
+ SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 3,
ARRAY_SIZE(cs42l73_mono_mix_texts),
cs42l73_mono_mix_texts,
cs42l73_mono_mix_values);
@@ -357,19 +357,19 @@ static const struct snd_kcontrol_new esl_xsp_mixer =
static const char * const cs42l73_ip_swap_text[] = {
"Stereo", "Mono A", "Mono B", "Swap A-B"};
-static const struct soc_enum ip_swap_enum =
- SOC_ENUM_SINGLE(CS42L73_MIOPC, 6,
- ARRAY_SIZE(cs42l73_ip_swap_text), cs42l73_ip_swap_text);
+static SOC_ENUM_SINGLE_DECL(ip_swap_enum,
+ CS42L73_MIOPC, 6,
+ cs42l73_ip_swap_text);
static const char * const cs42l73_spo_mixer_text[] = {"Mono", "Stereo"};
-static const struct soc_enum vsp_output_mux_enum =
- SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 5,
- ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text);
+static SOC_ENUM_SINGLE_DECL(vsp_output_mux_enum,
+ CS42L73_MIXERCTL, 5,
+ cs42l73_spo_mixer_text);
-static const struct soc_enum xsp_output_mux_enum =
- SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 4,
- ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text);
+static SOC_ENUM_SINGLE_DECL(xsp_output_mux_enum,
+ CS42L73_MIXERCTL, 4,
+ cs42l73_spo_mixer_text);
static const struct snd_kcontrol_new vsp_output_mux =
SOC_DAPM_ENUM("Route", vsp_output_mux_enum);
@@ -1108,7 +1108,7 @@ static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
return 0;
}
-static u32 cs42l73_asrc_rates[] = {
+static const unsigned int cs42l73_asrc_rates[] = {
8000, 11025, 12000, 16000, 22050,
24000, 32000, 44100, 48000
};
@@ -1241,7 +1241,7 @@ static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate)
0x7F, tristate << 7);
}
-static struct snd_pcm_hw_constraint_list constraints_12_24 = {
+static const struct snd_pcm_hw_constraint_list constraints_12_24 = {
.count = ARRAY_SIZE(cs42l73_asrc_rates),
.list = cs42l73_asrc_rates,
};
@@ -1255,9 +1255,6 @@ static int cs42l73_pcm_startup(struct snd_pcm_substream *substream,
return 0;
}
-/* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */
-#define CS42L73_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT)
-
#define CS42L73_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
@@ -1278,14 +1275,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
.stream_name = "XSP Playback",
.channels_min = 1,
.channels_max = 2,
- .rates = CS42L73_RATES,
+ .rates = SNDRV_PCM_RATE_KNOT,
.formats = CS42L73_FORMATS,
},
.capture = {
.stream_name = "XSP Capture",
.channels_min = 1,
.channels_max = 2,
- .rates = CS42L73_RATES,
+ .rates = SNDRV_PCM_RATE_KNOT,
.formats = CS42L73_FORMATS,
},
.ops = &cs42l73_ops,
@@ -1298,14 +1295,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
.stream_name = "ASP Playback",
.channels_min = 2,
.channels_max = 2,
- .rates = CS42L73_RATES,
+ .rates = SNDRV_PCM_RATE_KNOT,
.formats = CS42L73_FORMATS,
},
.capture = {
.stream_name = "ASP Capture",
.channels_min = 2,
.channels_max = 2,
- .rates = CS42L73_RATES,
+ .rates = SNDRV_PCM_RATE_KNOT,
.formats = CS42L73_FORMATS,
},
.ops = &cs42l73_ops,
@@ -1318,14 +1315,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
.stream_name = "VSP Playback",
.channels_min = 1,
.channels_max = 2,
- .rates = CS42L73_RATES,
+ .rates = SNDRV_PCM_RATE_KNOT,
.formats = CS42L73_FORMATS,
},
.capture = {
.stream_name = "VSP Capture",
.channels_min = 1,
.channels_max = 2,
- .rates = CS42L73_RATES,
+ .rates = SNDRV_PCM_RATE_KNOT,
.formats = CS42L73_FORMATS,
},
.ops = &cs42l73_ops,
@@ -1348,17 +1345,8 @@ static int cs42l73_resume(struct snd_soc_codec *codec)
static int cs42l73_probe(struct snd_soc_codec *codec)
{
- int ret;
struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec);
- codec->control_data = cs42l73->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Set Charge Pump Frequency */
@@ -1371,7 +1359,7 @@ static int cs42l73_probe(struct snd_soc_codec *codec)
cs42l73->mclksel = CS42L73_CLKID_MCLK1;
cs42l73->mclk = 0;
- return ret;
+ return 0;
}
static int cs42l73_remove(struct snd_soc_codec *codec)
@@ -1455,8 +1443,10 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
i2c_set_clientdata(i2c_client, cs42l73);
if (cs42l73->pdata.reset_gpio) {
- ret = gpio_request_one(cs42l73->pdata.reset_gpio,
- GPIOF_OUT_INIT_HIGH, "CS42L73 /RST");
+ ret = devm_gpio_request_one(&i2c_client->dev,
+ cs42l73->pdata.reset_gpio,
+ GPIOF_OUT_INIT_HIGH,
+ "CS42L73 /RST");
if (ret < 0) {
dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
cs42l73->pdata.reset_gpio, ret);
diff --git a/sound/soc/codecs/cs42xx8-i2c.c b/sound/soc/codecs/cs42xx8-i2c.c
new file mode 100644
index 00000000000..657dce27ead
--- /dev/null
+++ b/sound/soc/codecs/cs42xx8-i2c.c
@@ -0,0 +1,64 @@
+/*
+ * Cirrus Logic CS42448/CS42888 Audio CODEC DAI I2C driver
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Nicolin Chen <Guangyu.Chen@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <sound/soc.h>
+
+#include "cs42xx8.h"
+
+static int cs42xx8_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ u32 ret = cs42xx8_probe(&i2c->dev,
+ devm_regmap_init_i2c(i2c, &cs42xx8_regmap_config));
+ if (ret)
+ return ret;
+
+ pm_runtime_enable(&i2c->dev);
+ pm_request_idle(&i2c->dev);
+
+ return 0;
+}
+
+static int cs42xx8_i2c_remove(struct i2c_client *i2c)
+{
+ snd_soc_unregister_codec(&i2c->dev);
+ pm_runtime_disable(&i2c->dev);
+
+ return 0;
+}
+
+static struct i2c_device_id cs42xx8_i2c_id[] = {
+ {"cs42448", (kernel_ulong_t)&cs42448_data},
+ {"cs42888", (kernel_ulong_t)&cs42888_data},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id);
+
+static struct i2c_driver cs42xx8_i2c_driver = {
+ .driver = {
+ .name = "cs42xx8",
+ .owner = THIS_MODULE,
+ .pm = &cs42xx8_pm,
+ },
+ .probe = cs42xx8_i2c_probe,
+ .remove = cs42xx8_i2c_remove,
+ .id_table = cs42xx8_i2c_id,
+};
+
+module_i2c_driver(cs42xx8_i2c_driver);
+
+MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec I2C Driver");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c
new file mode 100644
index 00000000000..a25bc6061a3
--- /dev/null
+++ b/sound/soc/codecs/cs42xx8.c
@@ -0,0 +1,600 @@
+/*
+ * Cirrus Logic CS42448/CS42888 Audio CODEC Digital Audio Interface (DAI) driver
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Nicolin Chen <Guangyu.Chen@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+#include "cs42xx8.h"
+
+#define CS42XX8_NUM_SUPPLIES 4
+static const char *const cs42xx8_supply_names[CS42XX8_NUM_SUPPLIES] = {
+ "VA",
+ "VD",
+ "VLS",
+ "VLC",
+};
+
+#define CS42XX8_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+/* codec private data */
+struct cs42xx8_priv {
+ struct regulator_bulk_data supplies[CS42XX8_NUM_SUPPLIES];
+ const struct cs42xx8_driver_data *drvdata;
+ struct regmap *regmap;
+ struct clk *clk;
+
+ bool slave_mode;
+ unsigned long sysclk;
+};
+
+/* -127.5dB to 0dB with step of 0.5dB */
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
+/* -64dB to 24dB with step of 0.5dB */
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -6400, 50, 0);
+
+static const char *const cs42xx8_adc_single[] = { "Differential", "Single-Ended" };
+static const char *const cs42xx8_szc[] = { "Immediate Change", "Zero Cross",
+ "Soft Ramp", "Soft Ramp on Zero Cross" };
+
+static const struct soc_enum adc1_single_enum =
+ SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 4, 2, cs42xx8_adc_single);
+static const struct soc_enum adc2_single_enum =
+ SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 3, 2, cs42xx8_adc_single);
+static const struct soc_enum adc3_single_enum =
+ SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 2, 2, cs42xx8_adc_single);
+static const struct soc_enum dac_szc_enum =
+ SOC_ENUM_SINGLE(CS42XX8_TXCTL, 5, 4, cs42xx8_szc);
+static const struct soc_enum adc_szc_enum =
+ SOC_ENUM_SINGLE(CS42XX8_TXCTL, 0, 4, cs42xx8_szc);
+
+static const struct snd_kcontrol_new cs42xx8_snd_controls[] = {
+ SOC_DOUBLE_R_TLV("DAC1 Playback Volume", CS42XX8_VOLAOUT1,
+ CS42XX8_VOLAOUT2, 0, 0xff, 1, dac_tlv),
+ SOC_DOUBLE_R_TLV("DAC2 Playback Volume", CS42XX8_VOLAOUT3,
+ CS42XX8_VOLAOUT4, 0, 0xff, 1, dac_tlv),
+ SOC_DOUBLE_R_TLV("DAC3 Playback Volume", CS42XX8_VOLAOUT5,
+ CS42XX8_VOLAOUT6, 0, 0xff, 1, dac_tlv),
+ SOC_DOUBLE_R_TLV("DAC4 Playback Volume", CS42XX8_VOLAOUT7,
+ CS42XX8_VOLAOUT8, 0, 0xff, 1, dac_tlv),
+ SOC_DOUBLE_R_S_TLV("ADC1 Capture Volume", CS42XX8_VOLAIN1,
+ CS42XX8_VOLAIN2, 0, -0x80, 0x30, 7, 0, adc_tlv),
+ SOC_DOUBLE_R_S_TLV("ADC2 Capture Volume", CS42XX8_VOLAIN3,
+ CS42XX8_VOLAIN4, 0, -0x80, 0x30, 7, 0, adc_tlv),
+ SOC_DOUBLE("DAC1 Invert Switch", CS42XX8_DACINV, 0, 1, 1, 0),
+ SOC_DOUBLE("DAC2 Invert Switch", CS42XX8_DACINV, 2, 3, 1, 0),
+ SOC_DOUBLE("DAC3 Invert Switch", CS42XX8_DACINV, 4, 5, 1, 0),
+ SOC_DOUBLE("DAC4 Invert Switch", CS42XX8_DACINV, 6, 7, 1, 0),
+ SOC_DOUBLE("ADC1 Invert Switch", CS42XX8_ADCINV, 0, 1, 1, 0),
+ SOC_DOUBLE("ADC2 Invert Switch", CS42XX8_ADCINV, 2, 3, 1, 0),
+ SOC_SINGLE("ADC High-Pass Filter Switch", CS42XX8_ADCCTL, 7, 1, 1),
+ SOC_SINGLE("DAC De-emphasis Switch", CS42XX8_ADCCTL, 5, 1, 0),
+ SOC_ENUM("ADC1 Single Ended Mode Switch", adc1_single_enum),
+ SOC_ENUM("ADC2 Single Ended Mode Switch", adc2_single_enum),
+ SOC_SINGLE("DAC Single Volume Control Switch", CS42XX8_TXCTL, 7, 1, 0),
+ SOC_ENUM("DAC Soft Ramp & Zero Cross Control Switch", dac_szc_enum),
+ SOC_SINGLE("DAC Auto Mute Switch", CS42XX8_TXCTL, 4, 1, 0),
+ SOC_SINGLE("Mute ADC Serial Port Switch", CS42XX8_TXCTL, 3, 1, 0),
+ SOC_SINGLE("ADC Single Volume Control Switch", CS42XX8_TXCTL, 2, 1, 0),
+ SOC_ENUM("ADC Soft Ramp & Zero Cross Control Switch", adc_szc_enum),
+};
+
+static const struct snd_kcontrol_new cs42xx8_adc3_snd_controls[] = {
+ SOC_DOUBLE_R_S_TLV("ADC3 Capture Volume", CS42XX8_VOLAIN5,
+ CS42XX8_VOLAIN6, 0, -0x80, 0x30, 7, 0, adc_tlv),
+ SOC_DOUBLE("ADC3 Invert Switch", CS42XX8_ADCINV, 4, 5, 1, 0),
+ SOC_ENUM("ADC3 Single Ended Mode Switch", adc3_single_enum),
+};
+
+static const struct snd_soc_dapm_widget cs42xx8_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC("DAC1", "Playback", CS42XX8_PWRCTL, 1, 1),
+ SND_SOC_DAPM_DAC("DAC2", "Playback", CS42XX8_PWRCTL, 2, 1),
+ SND_SOC_DAPM_DAC("DAC3", "Playback", CS42XX8_PWRCTL, 3, 1),
+ SND_SOC_DAPM_DAC("DAC4", "Playback", CS42XX8_PWRCTL, 4, 1),
+
+ SND_SOC_DAPM_OUTPUT("AOUT1L"),
+ SND_SOC_DAPM_OUTPUT("AOUT1R"),
+ SND_SOC_DAPM_OUTPUT("AOUT2L"),
+ SND_SOC_DAPM_OUTPUT("AOUT2R"),
+ SND_SOC_DAPM_OUTPUT("AOUT3L"),
+ SND_SOC_DAPM_OUTPUT("AOUT3R"),
+ SND_SOC_DAPM_OUTPUT("AOUT4L"),
+ SND_SOC_DAPM_OUTPUT("AOUT4R"),
+
+ SND_SOC_DAPM_ADC("ADC1", "Capture", CS42XX8_PWRCTL, 5, 1),
+ SND_SOC_DAPM_ADC("ADC2", "Capture", CS42XX8_PWRCTL, 6, 1),
+
+ SND_SOC_DAPM_INPUT("AIN1L"),
+ SND_SOC_DAPM_INPUT("AIN1R"),
+ SND_SOC_DAPM_INPUT("AIN2L"),
+ SND_SOC_DAPM_INPUT("AIN2R"),
+
+ SND_SOC_DAPM_SUPPLY("PWR", CS42XX8_PWRCTL, 0, 1, NULL, 0),
+};
+
+static const struct snd_soc_dapm_widget cs42xx8_adc3_dapm_widgets[] = {
+ SND_SOC_DAPM_ADC("ADC3", "Capture", CS42XX8_PWRCTL, 7, 1),
+
+ SND_SOC_DAPM_INPUT("AIN3L"),
+ SND_SOC_DAPM_INPUT("AIN3R"),
+};
+
+static const struct snd_soc_dapm_route cs42xx8_dapm_routes[] = {
+ /* Playback */
+ { "AOUT1L", NULL, "DAC1" },
+ { "AOUT1R", NULL, "DAC1" },
+ { "DAC1", NULL, "PWR" },
+
+ { "AOUT2L", NULL, "DAC2" },
+ { "AOUT2R", NULL, "DAC2" },
+ { "DAC2", NULL, "PWR" },
+
+ { "AOUT3L", NULL, "DAC3" },
+ { "AOUT3R", NULL, "DAC3" },
+ { "DAC3", NULL, "PWR" },
+
+ { "AOUT4L", NULL, "DAC4" },
+ { "AOUT4R", NULL, "DAC4" },
+ { "DAC4", NULL, "PWR" },
+
+ /* Capture */
+ { "ADC1", NULL, "AIN1L" },
+ { "ADC1", NULL, "AIN1R" },
+ { "ADC1", NULL, "PWR" },
+
+ { "ADC2", NULL, "AIN2L" },
+ { "ADC2", NULL, "AIN2R" },
+ { "ADC2", NULL, "PWR" },
+};
+
+static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = {
+ /* Capture */
+ { "ADC3", NULL, "AIN3L" },
+ { "ADC3", NULL, "AIN3R" },
+ { "ADC3", NULL, "PWR" },
+};
+
+struct cs42xx8_ratios {
+ unsigned int ratio;
+ unsigned char speed;
+ unsigned char mclk;
+};
+
+static const struct cs42xx8_ratios cs42xx8_ratios[] = {
+ { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) },
+ { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) },
+ { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) },
+ { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) },
+ { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) },
+ { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) },
+ { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) },
+ { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) },
+ { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) }
+};
+
+static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
+
+ cs42xx8->sysclk = freq;
+
+ return 0;
+}
+
+static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int format)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
+ u32 val;
+
+ /* Set DAI format */
+ switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_LEFT_J:
+ val = CS42XX8_INTF_DAC_DIF_LEFTJ | CS42XX8_INTF_ADC_DIF_LEFTJ;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ val = CS42XX8_INTF_DAC_DIF_I2S | CS42XX8_INTF_ADC_DIF_I2S;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ val = CS42XX8_INTF_DAC_DIF_RIGHTJ | CS42XX8_INTF_ADC_DIF_RIGHTJ;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported dai format\n");
+ return -EINVAL;
+ }
+
+ regmap_update_bits(cs42xx8->regmap, CS42XX8_INTF,
+ CS42XX8_INTF_DAC_DIF_MASK |
+ CS42XX8_INTF_ADC_DIF_MASK, val);
+
+ /* Set master/slave audio interface */
+ switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ cs42xx8->slave_mode = true;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ cs42xx8->slave_mode = false;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported master/slave mode\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cs42xx8_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;
+ struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ u32 ratio = cs42xx8->sysclk / params_rate(params);
+ u32 i, fm, val, mask;
+
+ for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) {
+ if (cs42xx8_ratios[i].ratio == ratio)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(cs42xx8_ratios)) {
+ dev_err(codec->dev, "unsupported sysclk ratio\n");
+ return -EINVAL;
+ }
+
+ mask = CS42XX8_FUNCMOD_MFREQ_MASK;
+ val = cs42xx8_ratios[i].mclk;
+
+ fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed;
+
+ regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
+ CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask,
+ CS42XX8_FUNCMOD_xC_FM(tx, fm) | val);
+
+ return 0;
+}
+
+static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
+
+ regmap_update_bits(cs42xx8->regmap, CS42XX8_DACMUTE,
+ CS42XX8_DACMUTE_ALL, mute ? CS42XX8_DACMUTE_ALL : 0);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops cs42xx8_dai_ops = {
+ .set_fmt = cs42xx8_set_dai_fmt,
+ .set_sysclk = cs42xx8_set_dai_sysclk,
+ .hw_params = cs42xx8_hw_params,
+ .digital_mute = cs42xx8_digital_mute,
+};
+
+static struct snd_soc_dai_driver cs42xx8_dai = {
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = CS42XX8_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = CS42XX8_FORMATS,
+ },
+ .ops = &cs42xx8_dai_ops,
+};
+
+static const struct reg_default cs42xx8_reg[] = {
+ { 0x01, 0x01 }, /* Chip I.D. and Revision Register */
+ { 0x02, 0x00 }, /* Power Control */
+ { 0x03, 0xF0 }, /* Functional Mode */
+ { 0x04, 0x46 }, /* Interface Formats */
+ { 0x05, 0x00 }, /* ADC Control & DAC De-Emphasis */
+ { 0x06, 0x10 }, /* Transition Control */
+ { 0x07, 0x00 }, /* DAC Channel Mute */
+ { 0x08, 0x00 }, /* Volume Control AOUT1 */
+ { 0x09, 0x00 }, /* Volume Control AOUT2 */
+ { 0x0a, 0x00 }, /* Volume Control AOUT3 */
+ { 0x0b, 0x00 }, /* Volume Control AOUT4 */
+ { 0x0c, 0x00 }, /* Volume Control AOUT5 */
+ { 0x0d, 0x00 }, /* Volume Control AOUT6 */
+ { 0x0e, 0x00 }, /* Volume Control AOUT7 */
+ { 0x0f, 0x00 }, /* Volume Control AOUT8 */
+ { 0x10, 0x00 }, /* DAC Channel Invert */
+ { 0x11, 0x00 }, /* Volume Control AIN1 */
+ { 0x12, 0x00 }, /* Volume Control AIN2 */
+ { 0x13, 0x00 }, /* Volume Control AIN3 */
+ { 0x14, 0x00 }, /* Volume Control AIN4 */
+ { 0x15, 0x00 }, /* Volume Control AIN5 */
+ { 0x16, 0x00 }, /* Volume Control AIN6 */
+ { 0x17, 0x00 }, /* ADC Channel Invert */
+ { 0x18, 0x00 }, /* Status Control */
+ { 0x1a, 0x00 }, /* Status Mask */
+ { 0x1b, 0x00 }, /* MUTEC Pin Control */
+};
+
+static bool cs42xx8_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS42XX8_STATUS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs42xx8_writeable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS42XX8_CHIPID:
+ case CS42XX8_STATUS:
+ return false;
+ default:
+ return true;
+ }
+}
+
+const struct regmap_config cs42xx8_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = CS42XX8_LASTREG,
+ .reg_defaults = cs42xx8_reg,
+ .num_reg_defaults = ARRAY_SIZE(cs42xx8_reg),
+ .volatile_reg = cs42xx8_volatile_register,
+ .writeable_reg = cs42xx8_writeable_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs42xx8_regmap_config);
+
+static int cs42xx8_codec_probe(struct snd_soc_codec *codec)
+{
+ struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+ switch (cs42xx8->drvdata->num_adcs) {
+ case 3:
+ snd_soc_add_codec_controls(codec, cs42xx8_adc3_snd_controls,
+ ARRAY_SIZE(cs42xx8_adc3_snd_controls));
+ snd_soc_dapm_new_controls(dapm, cs42xx8_adc3_dapm_widgets,
+ ARRAY_SIZE(cs42xx8_adc3_dapm_widgets));
+ snd_soc_dapm_add_routes(dapm, cs42xx8_adc3_dapm_routes,
+ ARRAY_SIZE(cs42xx8_adc3_dapm_routes));
+ break;
+ default:
+ break;
+ }
+
+ /* Mute all DAC channels */
+ regmap_write(cs42xx8->regmap, CS42XX8_DACMUTE, CS42XX8_DACMUTE_ALL);
+
+ return 0;
+}
+
+static const struct snd_soc_codec_driver cs42xx8_driver = {
+ .probe = cs42xx8_codec_probe,
+ .idle_bias_off = true,
+
+ .controls = cs42xx8_snd_controls,
+ .num_controls = ARRAY_SIZE(cs42xx8_snd_controls),
+ .dapm_widgets = cs42xx8_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(cs42xx8_dapm_widgets),
+ .dapm_routes = cs42xx8_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(cs42xx8_dapm_routes),
+};
+
+const struct cs42xx8_driver_data cs42448_data = {
+ .name = "cs42448",
+ .num_adcs = 3,
+};
+EXPORT_SYMBOL_GPL(cs42448_data);
+
+const struct cs42xx8_driver_data cs42888_data = {
+ .name = "cs42888",
+ .num_adcs = 2,
+};
+EXPORT_SYMBOL_GPL(cs42888_data);
+
+const struct of_device_id cs42xx8_of_match[] = {
+ { .compatible = "cirrus,cs42448", .data = &cs42448_data, },
+ { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
+EXPORT_SYMBOL_GPL(cs42xx8_of_match);
+
+int cs42xx8_probe(struct device *dev, struct regmap *regmap)
+{
+ const struct of_device_id *of_id = of_match_device(cs42xx8_of_match, dev);
+ struct cs42xx8_priv *cs42xx8;
+ int ret, val, i;
+
+ cs42xx8 = devm_kzalloc(dev, sizeof(*cs42xx8), GFP_KERNEL);
+ if (cs42xx8 == NULL)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, cs42xx8);
+
+ if (of_id)
+ cs42xx8->drvdata = of_id->data;
+
+ if (!cs42xx8->drvdata) {
+ dev_err(dev, "failed to find driver data\n");
+ return -EINVAL;
+ }
+
+ cs42xx8->clk = devm_clk_get(dev, "mclk");
+ if (IS_ERR(cs42xx8->clk)) {
+ dev_err(dev, "failed to get the clock: %ld\n",
+ PTR_ERR(cs42xx8->clk));
+ return -EINVAL;
+ }
+
+ cs42xx8->sysclk = clk_get_rate(cs42xx8->clk);
+
+ for (i = 0; i < ARRAY_SIZE(cs42xx8->supplies); i++)
+ cs42xx8->supplies[i].supply = cs42xx8_supply_names[i];
+
+ ret = devm_regulator_bulk_get(dev,
+ ARRAY_SIZE(cs42xx8->supplies), cs42xx8->supplies);
+ if (ret) {
+ dev_err(dev, "failed to request supplies: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies),
+ cs42xx8->supplies);
+ if (ret) {
+ dev_err(dev, "failed to enable supplies: %d\n", ret);
+ return ret;
+ }
+
+ /* Make sure hardware reset done */
+ msleep(5);
+
+ cs42xx8->regmap = regmap;
+ if (IS_ERR(cs42xx8->regmap)) {
+ ret = PTR_ERR(cs42xx8->regmap);
+ dev_err(dev, "failed to allocate regmap: %d\n", ret);
+ goto err_enable;
+ }
+
+ /*
+ * We haven't marked the chip revision as volatile due to
+ * sharing a register with the right input volume; explicitly
+ * bypass the cache to read it.
+ */
+ regcache_cache_bypass(cs42xx8->regmap, true);
+
+ /* Validate the chip ID */
+ ret = regmap_read(cs42xx8->regmap, CS42XX8_CHIPID, &val);
+ if (ret < 0) {
+ dev_err(dev, "failed to get device ID, ret = %d", ret);
+ goto err_enable;
+ }
+
+ /* The top four bits of the chip ID should be 0000 */
+ if (((val & CS42XX8_CHIPID_CHIP_ID_MASK) >> 4) != 0x00) {
+ dev_err(dev, "unmatched chip ID: %d\n",
+ (val & CS42XX8_CHIPID_CHIP_ID_MASK) >> 4);
+ ret = -EINVAL;
+ goto err_enable;
+ }
+
+ dev_info(dev, "found device, revision %X\n",
+ val & CS42XX8_CHIPID_REV_ID_MASK);
+
+ regcache_cache_bypass(cs42xx8->regmap, false);
+
+ cs42xx8_dai.name = cs42xx8->drvdata->name;
+
+ /* Each adc supports stereo input */
+ cs42xx8_dai.capture.channels_max = cs42xx8->drvdata->num_adcs * 2;
+
+ ret = snd_soc_register_codec(dev, &cs42xx8_driver, &cs42xx8_dai, 1);
+ if (ret) {
+ dev_err(dev, "failed to register codec:%d\n", ret);
+ goto err_enable;
+ }
+
+ regcache_cache_only(cs42xx8->regmap, true);
+
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies),
+ cs42xx8->supplies);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cs42xx8_probe);
+
+#ifdef CONFIG_PM_RUNTIME
+static int cs42xx8_runtime_resume(struct device *dev)
+{
+ struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(cs42xx8->clk);
+ if (ret) {
+ dev_err(dev, "failed to enable mclk: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies),
+ cs42xx8->supplies);
+ if (ret) {
+ dev_err(dev, "failed to enable supplies: %d\n", ret);
+ goto err_clk;
+ }
+
+ /* Make sure hardware reset done */
+ msleep(5);
+
+ regcache_cache_only(cs42xx8->regmap, false);
+
+ ret = regcache_sync(cs42xx8->regmap);
+ if (ret) {
+ dev_err(dev, "failed to sync regmap: %d\n", ret);
+ goto err_bulk;
+ }
+
+ return 0;
+
+err_bulk:
+ regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies),
+ cs42xx8->supplies);
+err_clk:
+ clk_disable_unprepare(cs42xx8->clk);
+
+ return ret;
+}
+
+static int cs42xx8_runtime_suspend(struct device *dev)
+{
+ struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev);
+
+ regcache_cache_only(cs42xx8->regmap, true);
+
+ regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies),
+ cs42xx8->supplies);
+
+ clk_disable_unprepare(cs42xx8->clk);
+
+ return 0;
+}
+#endif
+
+const struct dev_pm_ops cs42xx8_pm = {
+ SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL)
+};
+EXPORT_SYMBOL_GPL(cs42xx8_pm);
+
+MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec Driver");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42xx8.h b/sound/soc/codecs/cs42xx8.h
new file mode 100644
index 00000000000..da0b94aee41
--- /dev/null
+++ b/sound/soc/codecs/cs42xx8.h
@@ -0,0 +1,238 @@
+/*
+ * cs42xx8.h - Cirrus Logic CS42448/CS42888 Audio CODEC driver header file
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Nicolin Chen <Guangyu.Chen@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef _CS42XX8_H
+#define _CS42XX8_H
+
+struct cs42xx8_driver_data {
+ char name[32];
+ int num_adcs;
+};
+
+extern const struct dev_pm_ops cs42xx8_pm;
+extern const struct cs42xx8_driver_data cs42448_data;
+extern const struct cs42xx8_driver_data cs42888_data;
+extern const struct regmap_config cs42xx8_regmap_config;
+int cs42xx8_probe(struct device *dev, struct regmap *regmap);
+
+/* CS42888 register map */
+#define CS42XX8_CHIPID 0x01 /* Chip ID */
+#define CS42XX8_PWRCTL 0x02 /* Power Control */
+#define CS42XX8_FUNCMOD 0x03 /* Functional Mode */
+#define CS42XX8_INTF 0x04 /* Interface Formats */
+#define CS42XX8_ADCCTL 0x05 /* ADC Control */
+#define CS42XX8_TXCTL 0x06 /* Transition Control */
+#define CS42XX8_DACMUTE 0x07 /* DAC Mute Control */
+#define CS42XX8_VOLAOUT1 0x08 /* Volume Control AOUT1 */
+#define CS42XX8_VOLAOUT2 0x09 /* Volume Control AOUT2 */
+#define CS42XX8_VOLAOUT3 0x0A /* Volume Control AOUT3 */
+#define CS42XX8_VOLAOUT4 0x0B /* Volume Control AOUT4 */
+#define CS42XX8_VOLAOUT5 0x0C /* Volume Control AOUT5 */
+#define CS42XX8_VOLAOUT6 0x0D /* Volume Control AOUT6 */
+#define CS42XX8_VOLAOUT7 0x0E /* Volume Control AOUT7 */
+#define CS42XX8_VOLAOUT8 0x0F /* Volume Control AOUT8 */
+#define CS42XX8_DACINV 0x10 /* DAC Channel Invert */
+#define CS42XX8_VOLAIN1 0x11 /* Volume Control AIN1 */
+#define CS42XX8_VOLAIN2 0x12 /* Volume Control AIN2 */
+#define CS42XX8_VOLAIN3 0x13 /* Volume Control AIN3 */
+#define CS42XX8_VOLAIN4 0x14 /* Volume Control AIN4 */
+#define CS42XX8_VOLAIN5 0x15 /* Volume Control AIN5 */
+#define CS42XX8_VOLAIN6 0x16 /* Volume Control AIN6 */
+#define CS42XX8_ADCINV 0x17 /* ADC Channel Invert */
+#define CS42XX8_STATUSCTL 0x18 /* Status Control */
+#define CS42XX8_STATUS 0x19 /* Status */
+#define CS42XX8_STATUSM 0x1A /* Status Mask */
+#define CS42XX8_MUTEC 0x1B /* MUTEC Pin Control */
+
+#define CS42XX8_FIRSTREG CS42XX8_CHIPID
+#define CS42XX8_LASTREG CS42XX8_MUTEC
+#define CS42XX8_NUMREGS (CS42XX8_LASTREG - CS42XX8_FIRSTREG + 1)
+#define CS42XX8_I2C_INCR 0x80
+
+/* Chip I.D. and Revision Register (Address 01h) */
+#define CS42XX8_CHIPID_CHIP_ID_MASK 0xF0
+#define CS42XX8_CHIPID_REV_ID_MASK 0x0F
+
+/* Power Control (Address 02h) */
+#define CS42XX8_PWRCTL_PDN_ADC3_SHIFT 7
+#define CS42XX8_PWRCTL_PDN_ADC3_MASK (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT)
+#define CS42XX8_PWRCTL_PDN_ADC3 (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT)
+#define CS42XX8_PWRCTL_PDN_ADC2_SHIFT 6
+#define CS42XX8_PWRCTL_PDN_ADC2_MASK (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT)
+#define CS42XX8_PWRCTL_PDN_ADC2 (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT)
+#define CS42XX8_PWRCTL_PDN_ADC1_SHIFT 5
+#define CS42XX8_PWRCTL_PDN_ADC1_MASK (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT)
+#define CS42XX8_PWRCTL_PDN_ADC1 (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC4_SHIFT 4
+#define CS42XX8_PWRCTL_PDN_DAC4_MASK (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC4 (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC3_SHIFT 3
+#define CS42XX8_PWRCTL_PDN_DAC3_MASK (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC3 (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC2_SHIFT 2
+#define CS42XX8_PWRCTL_PDN_DAC2_MASK (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC2 (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC1_SHIFT 1
+#define CS42XX8_PWRCTL_PDN_DAC1_MASK (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC1 (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT)
+#define CS42XX8_PWRCTL_PDN_SHIFT 0
+#define CS42XX8_PWRCTL_PDN_MASK (1 << CS42XX8_PWRCTL_PDN_SHIFT)
+#define CS42XX8_PWRCTL_PDN (1 << CS42XX8_PWRCTL_PDN_SHIFT)
+
+/* Functional Mode (Address 03h) */
+#define CS42XX8_FUNCMOD_DAC_FM_SHIFT 6
+#define CS42XX8_FUNCMOD_DAC_FM_WIDTH 2
+#define CS42XX8_FUNCMOD_DAC_FM_MASK (((1 << CS42XX8_FUNCMOD_DAC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_DAC_FM_SHIFT)
+#define CS42XX8_FUNCMOD_DAC_FM(v) ((v) << CS42XX8_FUNCMOD_DAC_FM_SHIFT)
+#define CS42XX8_FUNCMOD_ADC_FM_SHIFT 4
+#define CS42XX8_FUNCMOD_ADC_FM_WIDTH 2
+#define CS42XX8_FUNCMOD_ADC_FM_MASK (((1 << CS42XX8_FUNCMOD_ADC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_ADC_FM_SHIFT)
+#define CS42XX8_FUNCMOD_ADC_FM(v) ((v) << CS42XX8_FUNCMOD_ADC_FM_SHIFT)
+#define CS42XX8_FUNCMOD_xC_FM_MASK(x) ((x) ? CS42XX8_FUNCMOD_DAC_FM_MASK : CS42XX8_FUNCMOD_ADC_FM_MASK)
+#define CS42XX8_FUNCMOD_xC_FM(x, v) ((x) ? CS42XX8_FUNCMOD_DAC_FM(v) : CS42XX8_FUNCMOD_ADC_FM(v))
+#define CS42XX8_FUNCMOD_MFREQ_SHIFT 1
+#define CS42XX8_FUNCMOD_MFREQ_WIDTH 3
+#define CS42XX8_FUNCMOD_MFREQ_MASK (((1 << CS42XX8_FUNCMOD_MFREQ_WIDTH) - 1) << CS42XX8_FUNCMOD_MFREQ_SHIFT)
+#define CS42XX8_FUNCMOD_MFREQ_256(s) ((0 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1))
+#define CS42XX8_FUNCMOD_MFREQ_384(s) ((1 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1))
+#define CS42XX8_FUNCMOD_MFREQ_512(s) ((2 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1))
+#define CS42XX8_FUNCMOD_MFREQ_768(s) ((3 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1))
+#define CS42XX8_FUNCMOD_MFREQ_1024(s) ((4 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1))
+
+#define CS42XX8_FM_SINGLE 0
+#define CS42XX8_FM_DOUBLE 1
+#define CS42XX8_FM_QUAD 2
+#define CS42XX8_FM_AUTO 3
+
+/* Interface Formats (Address 04h) */
+#define CS42XX8_INTF_FREEZE_SHIFT 7
+#define CS42XX8_INTF_FREEZE_MASK (1 << CS42XX8_INTF_FREEZE_SHIFT)
+#define CS42XX8_INTF_FREEZE (1 << CS42XX8_INTF_FREEZE_SHIFT)
+#define CS42XX8_INTF_AUX_DIF_SHIFT 6
+#define CS42XX8_INTF_AUX_DIF_MASK (1 << CS42XX8_INTF_AUX_DIF_SHIFT)
+#define CS42XX8_INTF_AUX_DIF (1 << CS42XX8_INTF_AUX_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_SHIFT 3
+#define CS42XX8_INTF_DAC_DIF_WIDTH 3
+#define CS42XX8_INTF_DAC_DIF_MASK (((1 << CS42XX8_INTF_DAC_DIF_WIDTH) - 1) << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_LEFTJ (0 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_I2S (1 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_RIGHTJ (2 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_ONELINE_20 (4 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_ONELINE_24 (6 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_TDM (7 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_SHIFT 0
+#define CS42XX8_INTF_ADC_DIF_WIDTH 3
+#define CS42XX8_INTF_ADC_DIF_MASK (((1 << CS42XX8_INTF_ADC_DIF_WIDTH) - 1) << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_LEFTJ (0 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_I2S (1 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_RIGHTJ (2 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_ONELINE_20 (4 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_ONELINE_24 (6 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_TDM (7 << CS42XX8_INTF_ADC_DIF_SHIFT)
+
+/* ADC Control & DAC De-Emphasis (Address 05h) */
+#define CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT 7
+#define CS42XX8_ADCCTL_ADC_HPF_FREEZE_MASK (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT)
+#define CS42XX8_ADCCTL_ADC_HPF_FREEZE (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT)
+#define CS42XX8_ADCCTL_DAC_DEM_SHIFT 5
+#define CS42XX8_ADCCTL_DAC_DEM_MASK (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT)
+#define CS42XX8_ADCCTL_DAC_DEM (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT)
+#define CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT 4
+#define CS42XX8_ADCCTL_ADC1_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT)
+#define CS42XX8_ADCCTL_ADC1_SINGLE (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT)
+#define CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT 3
+#define CS42XX8_ADCCTL_ADC2_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT)
+#define CS42XX8_ADCCTL_ADC2_SINGLE (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT)
+#define CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT 2
+#define CS42XX8_ADCCTL_ADC3_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT)
+#define CS42XX8_ADCCTL_ADC3_SINGLE (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT)
+#define CS42XX8_ADCCTL_AIN5_MUX_SHIFT 1
+#define CS42XX8_ADCCTL_AIN5_MUX_MASK (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT)
+#define CS42XX8_ADCCTL_AIN5_MUX (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT)
+#define CS42XX8_ADCCTL_AIN6_MUX_SHIFT 0
+#define CS42XX8_ADCCTL_AIN6_MUX_MASK (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT)
+#define CS42XX8_ADCCTL_AIN6_MUX (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT)
+
+/* Transition Control (Address 06h) */
+#define CS42XX8_TXCTL_DAC_SNGVOL_SHIFT 7
+#define CS42XX8_TXCTL_DAC_SNGVOL_MASK (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT)
+#define CS42XX8_TXCTL_DAC_SNGVOL (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT)
+#define CS42XX8_TXCTL_DAC_SZC_SHIFT 5
+#define CS42XX8_TXCTL_DAC_SZC_WIDTH 2
+#define CS42XX8_TXCTL_DAC_SZC_MASK (((1 << CS42XX8_TXCTL_DAC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_DAC_SZC_SHIFT)
+#define CS42XX8_TXCTL_DAC_SZC_IC (0 << CS42XX8_TXCTL_DAC_SZC_SHIFT)
+#define CS42XX8_TXCTL_DAC_SZC_ZC (1 << CS42XX8_TXCTL_DAC_SZC_SHIFT)
+#define CS42XX8_TXCTL_DAC_SZC_SR (2 << CS42XX8_TXCTL_DAC_SZC_SHIFT)
+#define CS42XX8_TXCTL_DAC_SZC_SRZC (3 << CS42XX8_TXCTL_DAC_SZC_SHIFT)
+#define CS42XX8_TXCTL_AMUTE_SHIFT 4
+#define CS42XX8_TXCTL_AMUTE_MASK (1 << CS42XX8_TXCTL_AMUTE_SHIFT)
+#define CS42XX8_TXCTL_AMUTE (1 << CS42XX8_TXCTL_AMUTE_SHIFT)
+#define CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT 3
+#define CS42XX8_TXCTL_MUTE_ADC_SP_MASK (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT)
+#define CS42XX8_TXCTL_MUTE_ADC_SP (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT)
+#define CS42XX8_TXCTL_ADC_SNGVOL_SHIFT 2
+#define CS42XX8_TXCTL_ADC_SNGVOL_MASK (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT)
+#define CS42XX8_TXCTL_ADC_SNGVOL (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT)
+#define CS42XX8_TXCTL_ADC_SZC_SHIFT 0
+#define CS42XX8_TXCTL_ADC_SZC_MASK (((1 << CS42XX8_TXCTL_ADC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_ADC_SZC_SHIFT)
+#define CS42XX8_TXCTL_ADC_SZC_IC (0 << CS42XX8_TXCTL_ADC_SZC_SHIFT)
+#define CS42XX8_TXCTL_ADC_SZC_ZC (1 << CS42XX8_TXCTL_ADC_SZC_SHIFT)
+#define CS42XX8_TXCTL_ADC_SZC_SR (2 << CS42XX8_TXCTL_ADC_SZC_SHIFT)
+#define CS42XX8_TXCTL_ADC_SZC_SRZC (3 << CS42XX8_TXCTL_ADC_SZC_SHIFT)
+
+/* DAC Channel Mute (Address 07h) */
+#define CS42XX8_DACMUTE_AOUT(n) (0x1 << n)
+#define CS42XX8_DACMUTE_ALL 0xff
+
+/* Status Control (Address 18h)*/
+#define CS42XX8_STATUSCTL_INI_SHIFT 2
+#define CS42XX8_STATUSCTL_INI_WIDTH 2
+#define CS42XX8_STATUSCTL_INI_MASK (((1 << CS42XX8_STATUSCTL_INI_WIDTH) - 1) << CS42XX8_STATUSCTL_INI_SHIFT)
+#define CS42XX8_STATUSCTL_INT_ACTIVE_HIGH (0 << CS42XX8_STATUSCTL_INI_SHIFT)
+#define CS42XX8_STATUSCTL_INT_ACTIVE_LOW (1 << CS42XX8_STATUSCTL_INI_SHIFT)
+#define CS42XX8_STATUSCTL_INT_OPEN_DRAIN (2 << CS42XX8_STATUSCTL_INI_SHIFT)
+
+/* Status (Address 19h)*/
+#define CS42XX8_STATUS_DAC_CLK_ERR_SHIFT 4
+#define CS42XX8_STATUS_DAC_CLK_ERR_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_SHIFT)
+#define CS42XX8_STATUS_ADC_CLK_ERR_SHIFT 3
+#define CS42XX8_STATUS_ADC_CLK_ERR_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_SHIFT)
+#define CS42XX8_STATUS_ADC3_OVFL_SHIFT 2
+#define CS42XX8_STATUS_ADC3_OVFL_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_SHIFT)
+#define CS42XX8_STATUS_ADC2_OVFL_SHIFT 1
+#define CS42XX8_STATUS_ADC2_OVFL_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_SHIFT)
+#define CS42XX8_STATUS_ADC1_OVFL_SHIFT 0
+#define CS42XX8_STATUS_ADC1_OVFL_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_SHIFT)
+
+/* Status Mask (Address 1Ah) */
+#define CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT 4
+#define CS42XX8_STATUS_DAC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT)
+#define CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT 3
+#define CS42XX8_STATUS_ADC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT)
+#define CS42XX8_STATUS_ADC3_OVFL_M_SHIFT 2
+#define CS42XX8_STATUS_ADC3_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_M_SHIFT)
+#define CS42XX8_STATUS_ADC2_OVFL_M_SHIFT 1
+#define CS42XX8_STATUS_ADC2_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_M_SHIFT)
+#define CS42XX8_STATUS_ADC1_OVFL_M_SHIFT 0
+#define CS42XX8_STATUS_ADC1_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_M_SHIFT)
+
+/* MUTEC Pin Control (Address 1Bh) */
+#define CS42XX8_MUTEC_MCPOLARITY_SHIFT 1
+#define CS42XX8_MUTEC_MCPOLARITY_MASK (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT)
+#define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_LOW (0 << CS42XX8_MUTEC_MCPOLARITY_SHIFT)
+#define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_HIGH (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT)
+#define CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT 0
+#define CS42XX8_MUTEC_MUTEC_ACTIVE_MASK (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT)
+#define CS42XX8_MUTEC_MUTEC_ACTIVE (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT)
+#endif /* _CS42XX8_H */
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index e62e294a803..21810e5f332 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -307,35 +307,35 @@ static const char * const da7210_hpf_cutoff_txt[] = {
"Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi"
};
-static const struct soc_enum da7210_dac_hpf_cutoff =
- SOC_ENUM_SINGLE(DA7210_DAC_HPF, 0, 4, da7210_hpf_cutoff_txt);
+static SOC_ENUM_SINGLE_DECL(da7210_dac_hpf_cutoff,
+ DA7210_DAC_HPF, 0, da7210_hpf_cutoff_txt);
-static const struct soc_enum da7210_adc_hpf_cutoff =
- SOC_ENUM_SINGLE(DA7210_ADC_HPF, 0, 4, da7210_hpf_cutoff_txt);
+static SOC_ENUM_SINGLE_DECL(da7210_adc_hpf_cutoff,
+ DA7210_ADC_HPF, 0, da7210_hpf_cutoff_txt);
/* ADC and DAC voice (8kHz) high pass cutoff value */
static const char * const da7210_vf_cutoff_txt[] = {
"2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
};
-static const struct soc_enum da7210_dac_vf_cutoff =
- SOC_ENUM_SINGLE(DA7210_DAC_HPF, 4, 8, da7210_vf_cutoff_txt);
+static SOC_ENUM_SINGLE_DECL(da7210_dac_vf_cutoff,
+ DA7210_DAC_HPF, 4, da7210_vf_cutoff_txt);
-static const struct soc_enum da7210_adc_vf_cutoff =
- SOC_ENUM_SINGLE(DA7210_ADC_HPF, 4, 8, da7210_vf_cutoff_txt);
+static SOC_ENUM_SINGLE_DECL(da7210_adc_vf_cutoff,
+ DA7210_ADC_HPF, 4, da7210_vf_cutoff_txt);
static const char *da7210_hp_mode_txt[] = {
"Class H", "Class G"
};
-static const struct soc_enum da7210_hp_mode_sel =
- SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt);
+static SOC_ENUM_SINGLE_DECL(da7210_hp_mode_sel,
+ DA7210_HP_CFG, 0, da7210_hp_mode_txt);
/* ALC can be enabled only if noise suppression is disabled */
static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
if (ucontrol->value.integer.value[0]) {
/* Check if noise suppression is enabled */
@@ -358,7 +358,7 @@ static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol,
static int da7210_put_noise_sup_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
u8 val;
if (ucontrol->value.integer.value[0]) {
@@ -1071,17 +1071,9 @@ static struct snd_soc_dai_driver da7210_dai = {
static int da7210_probe(struct snd_soc_codec *codec)
{
struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
- int ret;
dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
- codec->control_data = da7210->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
da7210->mclk_rate = 0; /* This will be set from set_sysclk() */
da7210->master = 0; /* This will be set from set_fmt() */
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c
index 0c77e7ad742..9ec577f0edb 100644
--- a/sound/soc/codecs/da7213.c
+++ b/sound/soc/codecs/da7213.c
@@ -63,30 +63,30 @@ static const char * const da7213_voice_hpf_corner_txt[] = {
"2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
};
-static const struct soc_enum da7213_dac_voice_hpf_corner =
- SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT,
- DA7213_VOICE_HPF_CORNER_MAX,
- da7213_voice_hpf_corner_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_dac_voice_hpf_corner,
+ DA7213_DAC_FILTERS1,
+ DA7213_VOICE_HPF_CORNER_SHIFT,
+ da7213_voice_hpf_corner_txt);
-static const struct soc_enum da7213_adc_voice_hpf_corner =
- SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT,
- DA7213_VOICE_HPF_CORNER_MAX,
- da7213_voice_hpf_corner_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_adc_voice_hpf_corner,
+ DA7213_ADC_FILTERS1,
+ DA7213_VOICE_HPF_CORNER_SHIFT,
+ da7213_voice_hpf_corner_txt);
/* ADC and DAC high pass filter cutoff value */
static const char * const da7213_audio_hpf_corner_txt[] = {
"Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000"
};
-static const struct soc_enum da7213_dac_audio_hpf_corner =
- SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT,
- DA7213_AUDIO_HPF_CORNER_MAX,
- da7213_audio_hpf_corner_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_dac_audio_hpf_corner,
+ DA7213_DAC_FILTERS1
+ , DA7213_AUDIO_HPF_CORNER_SHIFT,
+ da7213_audio_hpf_corner_txt);
-static const struct soc_enum da7213_adc_audio_hpf_corner =
- SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT,
- DA7213_AUDIO_HPF_CORNER_MAX,
- da7213_audio_hpf_corner_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_adc_audio_hpf_corner,
+ DA7213_ADC_FILTERS1,
+ DA7213_AUDIO_HPF_CORNER_SHIFT,
+ da7213_audio_hpf_corner_txt);
/* Gain ramping rate value */
static const char * const da7213_gain_ramp_rate_txt[] = {
@@ -94,52 +94,50 @@ static const char * const da7213_gain_ramp_rate_txt[] = {
"nominal rate / 32"
};
-static const struct soc_enum da7213_gain_ramp_rate =
- SOC_ENUM_SINGLE(DA7213_GAIN_RAMP_CTRL, DA7213_GAIN_RAMP_RATE_SHIFT,
- DA7213_GAIN_RAMP_RATE_MAX, da7213_gain_ramp_rate_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_gain_ramp_rate,
+ DA7213_GAIN_RAMP_CTRL,
+ DA7213_GAIN_RAMP_RATE_SHIFT,
+ da7213_gain_ramp_rate_txt);
/* DAC noise gate setup time value */
static const char * const da7213_dac_ng_setup_time_txt[] = {
"256 samples", "512 samples", "1024 samples", "2048 samples"
};
-static const struct soc_enum da7213_dac_ng_setup_time =
- SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME,
- DA7213_DAC_NG_SETUP_TIME_SHIFT,
- DA7213_DAC_NG_SETUP_TIME_MAX,
- da7213_dac_ng_setup_time_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_setup_time,
+ DA7213_DAC_NG_SETUP_TIME,
+ DA7213_DAC_NG_SETUP_TIME_SHIFT,
+ da7213_dac_ng_setup_time_txt);
/* DAC noise gate rampup rate value */
static const char * const da7213_dac_ng_rampup_txt[] = {
"0.02 ms/dB", "0.16 ms/dB"
};
-static const struct soc_enum da7213_dac_ng_rampup_rate =
- SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME,
- DA7213_DAC_NG_RAMPUP_RATE_SHIFT,
- DA7213_DAC_NG_RAMP_RATE_MAX,
- da7213_dac_ng_rampup_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampup_rate,
+ DA7213_DAC_NG_SETUP_TIME,
+ DA7213_DAC_NG_RAMPUP_RATE_SHIFT,
+ da7213_dac_ng_rampup_txt);
/* DAC noise gate rampdown rate value */
static const char * const da7213_dac_ng_rampdown_txt[] = {
"0.64 ms/dB", "20.48 ms/dB"
};
-static const struct soc_enum da7213_dac_ng_rampdown_rate =
- SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME,
- DA7213_DAC_NG_RAMPDN_RATE_SHIFT,
- DA7213_DAC_NG_RAMP_RATE_MAX,
- da7213_dac_ng_rampdown_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampdown_rate,
+ DA7213_DAC_NG_SETUP_TIME,
+ DA7213_DAC_NG_RAMPDN_RATE_SHIFT,
+ da7213_dac_ng_rampdown_txt);
/* DAC soft mute rate value */
static const char * const da7213_dac_soft_mute_rate_txt[] = {
"1", "2", "4", "8", "16", "32", "64"
};
-static const struct soc_enum da7213_dac_soft_mute_rate =
- SOC_ENUM_SINGLE(DA7213_DAC_FILTERS5, DA7213_DAC_SOFTMUTE_RATE_SHIFT,
- DA7213_DAC_SOFTMUTE_RATE_MAX,
- da7213_dac_soft_mute_rate_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_dac_soft_mute_rate,
+ DA7213_DAC_FILTERS5,
+ DA7213_DAC_SOFTMUTE_RATE_SHIFT,
+ da7213_dac_soft_mute_rate_txt);
/* ALC Attack Rate select */
static const char * const da7213_alc_attack_rate_txt[] = {
@@ -147,9 +145,10 @@ static const char * const da7213_alc_attack_rate_txt[] = {
"5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs"
};
-static const struct soc_enum da7213_alc_attack_rate =
- SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_ATTACK_SHIFT,
- DA7213_ALC_ATTACK_MAX, da7213_alc_attack_rate_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_alc_attack_rate,
+ DA7213_ALC_CTRL2,
+ DA7213_ALC_ATTACK_SHIFT,
+ da7213_alc_attack_rate_txt);
/* ALC Release Rate select */
static const char * const da7213_alc_release_rate_txt[] = {
@@ -157,9 +156,10 @@ static const char * const da7213_alc_release_rate_txt[] = {
"11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs"
};
-static const struct soc_enum da7213_alc_release_rate =
- SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_RELEASE_SHIFT,
- DA7213_ALC_RELEASE_MAX, da7213_alc_release_rate_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_alc_release_rate,
+ DA7213_ALC_CTRL2,
+ DA7213_ALC_RELEASE_SHIFT,
+ da7213_alc_release_rate_txt);
/* ALC Hold Time select */
static const char * const da7213_alc_hold_time_txt[] = {
@@ -168,22 +168,25 @@ static const char * const da7213_alc_hold_time_txt[] = {
"253952/fs", "507904/fs", "1015808/fs", "2031616/fs"
};
-static const struct soc_enum da7213_alc_hold_time =
- SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_HOLD_SHIFT,
- DA7213_ALC_HOLD_MAX, da7213_alc_hold_time_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_alc_hold_time,
+ DA7213_ALC_CTRL3,
+ DA7213_ALC_HOLD_SHIFT,
+ da7213_alc_hold_time_txt);
/* ALC Input Signal Tracking rate select */
static const char * const da7213_alc_integ_rate_txt[] = {
"1/4", "1/16", "1/256", "1/65536"
};
-static const struct soc_enum da7213_alc_integ_attack_rate =
- SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_ATTACK_SHIFT,
- DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_attack_rate,
+ DA7213_ALC_CTRL3,
+ DA7213_ALC_INTEG_ATTACK_SHIFT,
+ da7213_alc_integ_rate_txt);
-static const struct soc_enum da7213_alc_integ_release_rate =
- SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_RELEASE_SHIFT,
- DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_release_rate,
+ DA7213_ALC_CTRL3,
+ DA7213_ALC_INTEG_RELEASE_SHIFT,
+ da7213_alc_integ_rate_txt);
/*
@@ -342,7 +345,7 @@ static void da7213_alc_calib(struct snd_soc_codec *codec)
static int da7213_put_mixin_gain(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec);
int ret;
@@ -358,7 +361,7 @@ static int da7213_put_mixin_gain(struct snd_kcontrol *kcontrol,
static int da7213_put_alc_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec);
/* Force ALC offset calibration if enabling ALC */
@@ -584,15 +587,17 @@ static const char * const da7213_mic_amp_in_sel_txt[] = {
"Differential", "MIC_P", "MIC_N"
};
-static const struct soc_enum da7213_mic_1_amp_in_sel =
- SOC_ENUM_SINGLE(DA7213_MIC_1_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT,
- DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_mic_1_amp_in_sel,
+ DA7213_MIC_1_CTRL,
+ DA7213_MIC_AMP_IN_SEL_SHIFT,
+ da7213_mic_amp_in_sel_txt);
static const struct snd_kcontrol_new da7213_mic_1_amp_in_sel_mux =
SOC_DAPM_ENUM("Mic 1 Amp Source MUX", da7213_mic_1_amp_in_sel);
-static const struct soc_enum da7213_mic_2_amp_in_sel =
- SOC_ENUM_SINGLE(DA7213_MIC_2_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT,
- DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_mic_2_amp_in_sel,
+ DA7213_MIC_2_CTRL,
+ DA7213_MIC_AMP_IN_SEL_SHIFT,
+ da7213_mic_amp_in_sel_txt);
static const struct snd_kcontrol_new da7213_mic_2_amp_in_sel_mux =
SOC_DAPM_ENUM("Mic 2 Amp Source MUX", da7213_mic_2_amp_in_sel);
@@ -601,15 +606,17 @@ static const char * const da7213_dai_src_txt[] = {
"ADC Left", "ADC Right", "DAI Input Left", "DAI Input Right"
};
-static const struct soc_enum da7213_dai_l_src =
- SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_L_SRC_SHIFT,
- DA7213_DAI_SRC_MAX, da7213_dai_src_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_dai_l_src,
+ DA7213_DIG_ROUTING_DAI,
+ DA7213_DAI_L_SRC_SHIFT,
+ da7213_dai_src_txt);
static const struct snd_kcontrol_new da7213_dai_l_src_mux =
SOC_DAPM_ENUM("DAI Left Source MUX", da7213_dai_l_src);
-static const struct soc_enum da7213_dai_r_src =
- SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_R_SRC_SHIFT,
- DA7213_DAI_SRC_MAX, da7213_dai_src_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_dai_r_src,
+ DA7213_DIG_ROUTING_DAI,
+ DA7213_DAI_R_SRC_SHIFT,
+ da7213_dai_src_txt);
static const struct snd_kcontrol_new da7213_dai_r_src_mux =
SOC_DAPM_ENUM("DAI Right Source MUX", da7213_dai_r_src);
@@ -619,15 +626,17 @@ static const char * const da7213_dac_src_txt[] = {
"DAI Input Right"
};
-static const struct soc_enum da7213_dac_l_src =
- SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_L_SRC_SHIFT,
- DA7213_DAC_SRC_MAX, da7213_dac_src_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_dac_l_src,
+ DA7213_DIG_ROUTING_DAC,
+ DA7213_DAC_L_SRC_SHIFT,
+ da7213_dac_src_txt);
static const struct snd_kcontrol_new da7213_dac_l_src_mux =
SOC_DAPM_ENUM("DAC Left Source MUX", da7213_dac_l_src);
-static const struct soc_enum da7213_dac_r_src =
- SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_R_SRC_SHIFT,
- DA7213_DAC_SRC_MAX, da7213_dac_src_txt);
+static SOC_ENUM_SINGLE_DECL(da7213_dac_r_src,
+ DA7213_DIG_ROUTING_DAC,
+ DA7213_DAC_R_SRC_SHIFT,
+ da7213_dac_src_txt);
static const struct snd_kcontrol_new da7213_dac_r_src_mux =
SOC_DAPM_ENUM("DAC Right Source MUX", da7213_dac_r_src);
@@ -1384,17 +1393,9 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec,
static int da7213_probe(struct snd_soc_codec *codec)
{
- int ret;
struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec);
struct da7213_platform_data *pdata = da7213->pdata;
- codec->control_data = da7213->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
/* Default to using ALC auto offset calibration mode. */
snd_soc_update_bits(codec, DA7213_ALC_CTRL1,
DA7213_ALC_CALIB_MODE_MAN, 0);
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c
index f295b656991..2fae31cb006 100644
--- a/sound/soc/codecs/da732x.c
+++ b/sound/soc/codecs/da732x.c
@@ -269,86 +269,70 @@ static const char *da732x_hpf_voice[] = {
"150Hz", "200Hz", "300Hz", "400Hz"
};
-static const struct soc_enum da732x_dac1_hpf_mode_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT,
- DA732X_HPF_MODE_MAX, da732x_hpf_mode)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_dac1_hpf_mode_enum,
+ DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT,
+ da732x_hpf_mode);
-static const struct soc_enum da732x_dac2_hpf_mode_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT,
- DA732X_HPF_MODE_MAX, da732x_hpf_mode)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_dac2_hpf_mode_enum,
+ DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT,
+ da732x_hpf_mode);
-static const struct soc_enum da732x_dac3_hpf_mode_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT,
- DA732X_HPF_MODE_MAX, da732x_hpf_mode)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_dac3_hpf_mode_enum,
+ DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT,
+ da732x_hpf_mode);
-static const struct soc_enum da732x_adc1_hpf_mode_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT,
- DA732X_HPF_MODE_MAX, da732x_hpf_mode)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_adc1_hpf_mode_enum,
+ DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT,
+ da732x_hpf_mode);
-static const struct soc_enum da732x_adc2_hpf_mode_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT,
- DA732X_HPF_MODE_MAX, da732x_hpf_mode)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_adc2_hpf_mode_enum,
+ DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT,
+ da732x_hpf_mode);
-static const struct soc_enum da732x_dac1_hp_filter_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT,
- DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_dac1_hp_filter_enum,
+ DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT,
+ da732x_hpf_music);
-static const struct soc_enum da732x_dac2_hp_filter_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT,
- DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_dac2_hp_filter_enum,
+ DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT,
+ da732x_hpf_music);
-static const struct soc_enum da732x_dac3_hp_filter_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT,
- DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_dac3_hp_filter_enum,
+ DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT,
+ da732x_hpf_music);
-static const struct soc_enum da732x_adc1_hp_filter_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT,
- DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_adc1_hp_filter_enum,
+ DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT,
+ da732x_hpf_music);
-static const struct soc_enum da732x_adc2_hp_filter_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT,
- DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_adc2_hp_filter_enum,
+ DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT,
+ da732x_hpf_music);
-static const struct soc_enum da732x_dac1_voice_filter_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT,
- DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_dac1_voice_filter_enum,
+ DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT,
+ da732x_hpf_voice);
-static const struct soc_enum da732x_dac2_voice_filter_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT,
- DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_dac2_voice_filter_enum,
+ DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT,
+ da732x_hpf_voice);
-static const struct soc_enum da732x_dac3_voice_filter_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT,
- DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_dac3_voice_filter_enum,
+ DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT,
+ da732x_hpf_voice);
-static const struct soc_enum da732x_adc1_voice_filter_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT,
- DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
-};
-
-static const struct soc_enum da732x_adc2_voice_filter_enum[] = {
- SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT,
- DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
-};
+static SOC_ENUM_SINGLE_DECL(da732x_adc1_voice_filter_enum,
+ DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT,
+ da732x_hpf_voice);
+static SOC_ENUM_SINGLE_DECL(da732x_adc2_voice_filter_enum,
+ DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT,
+ da732x_hpf_voice);
static int da732x_hpf_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value;
unsigned int reg = enum_ctrl->reg;
unsigned int sel = ucontrol->value.integer.value[0];
@@ -376,7 +360,7 @@ static int da732x_hpf_set(struct snd_kcontrol *kcontrol,
static int da732x_hpf_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value;
unsigned int reg = enum_ctrl->reg;
int val;
@@ -714,65 +698,65 @@ static const char *enable_text[] = {
};
/* ADC1LMUX */
-static const struct soc_enum adc1l_enum =
- SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT,
- DA732X_ADCL_MUX_MAX, adcl_text);
+static SOC_ENUM_SINGLE_DECL(adc1l_enum,
+ DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT,
+ adcl_text);
static const struct snd_kcontrol_new adc1l_mux =
SOC_DAPM_ENUM("ADC Route", adc1l_enum);
/* ADC1RMUX */
-static const struct soc_enum adc1r_enum =
- SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT,
- DA732X_ADCR_MUX_MAX, adcr_text);
+static SOC_ENUM_SINGLE_DECL(adc1r_enum,
+ DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT,
+ adcr_text);
static const struct snd_kcontrol_new adc1r_mux =
SOC_DAPM_ENUM("ADC Route", adc1r_enum);
/* ADC2LMUX */
-static const struct soc_enum adc2l_enum =
- SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT,
- DA732X_ADCL_MUX_MAX, adcl_text);
+static SOC_ENUM_SINGLE_DECL(adc2l_enum,
+ DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT,
+ adcl_text);
static const struct snd_kcontrol_new adc2l_mux =
SOC_DAPM_ENUM("ADC Route", adc2l_enum);
/* ADC2RMUX */
-static const struct soc_enum adc2r_enum =
- SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT,
- DA732X_ADCR_MUX_MAX, adcr_text);
+static SOC_ENUM_SINGLE_DECL(adc2r_enum,
+ DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT,
+ adcr_text);
static const struct snd_kcontrol_new adc2r_mux =
SOC_DAPM_ENUM("ADC Route", adc2r_enum);
-static const struct soc_enum da732x_hp_left_output =
- SOC_ENUM_SINGLE(DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT,
- DA732X_DAC_EN_MAX, enable_text);
+static SOC_ENUM_SINGLE_DECL(da732x_hp_left_output,
+ DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT,
+ enable_text);
static const struct snd_kcontrol_new hpl_mux =
SOC_DAPM_ENUM("HPL Switch", da732x_hp_left_output);
-static const struct soc_enum da732x_hp_right_output =
- SOC_ENUM_SINGLE(DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT,
- DA732X_DAC_EN_MAX, enable_text);
+static SOC_ENUM_SINGLE_DECL(da732x_hp_right_output,
+ DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT,
+ enable_text);
static const struct snd_kcontrol_new hpr_mux =
SOC_DAPM_ENUM("HPR Switch", da732x_hp_right_output);
-static const struct soc_enum da732x_speaker_output =
- SOC_ENUM_SINGLE(DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT,
- DA732X_DAC_EN_MAX, enable_text);
+static SOC_ENUM_SINGLE_DECL(da732x_speaker_output,
+ DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT,
+ enable_text);
static const struct snd_kcontrol_new spk_mux =
SOC_DAPM_ENUM("SPK Switch", da732x_speaker_output);
-static const struct soc_enum da732x_lout4_output =
- SOC_ENUM_SINGLE(DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT,
- DA732X_DAC_EN_MAX, enable_text);
+static SOC_ENUM_SINGLE_DECL(da732x_lout4_output,
+ DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT,
+ enable_text);
static const struct snd_kcontrol_new lout4_mux =
SOC_DAPM_ENUM("LOUT4 Switch", da732x_lout4_output);
-static const struct soc_enum da732x_lout2_output =
- SOC_ENUM_SINGLE(DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT,
- DA732X_DAC_EN_MAX, enable_text);
+static SOC_ENUM_SINGLE_DECL(da732x_lout2_output,
+ DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT,
+ enable_text);
static const struct snd_kcontrol_new lout2_mux =
SOC_DAPM_ENUM("LOUT2 Switch", da732x_lout2_output);
@@ -1268,11 +1252,23 @@ static struct snd_soc_dai_driver da732x_dai[] = {
},
};
+static bool da732x_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case DA732X_REG_HPL_DAC_OFF_CNTL:
+ case DA732X_REG_HPR_DAC_OFF_CNTL:
+ return true;
+ default:
+ return false;
+ }
+}
+
static const struct regmap_config da732x_regmap = {
.reg_bits = 8,
.val_bits = 8,
.max_register = DA732X_MAX_REG,
+ .volatile_reg = da732x_volatile,
.reg_defaults = da732x_reg_cache,
.num_reg_defaults = ARRAY_SIZE(da732x_reg_cache),
.cache_type = REGCACHE_RBTREE,
@@ -1301,9 +1297,9 @@ static void da732x_dac_offset_adjust(struct snd_soc_codec *codec)
msleep(DA732X_WAIT_FOR_STABILIZATION);
/* Check DAC offset sign */
- sign[DA732X_HPL_DAC] = (codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) &
+ sign[DA732X_HPL_DAC] = (snd_soc_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) &
DA732X_HP_DAC_OFF_CNTL_COMPO);
- sign[DA732X_HPR_DAC] = (codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) &
+ sign[DA732X_HPR_DAC] = (snd_soc_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) &
DA732X_HP_DAC_OFF_CNTL_COMPO);
/* Binary search DAC offset values (both channels at once) */
@@ -1320,10 +1316,10 @@ static void da732x_dac_offset_adjust(struct snd_soc_codec *codec)
msleep(DA732X_WAIT_FOR_STABILIZATION);
- if ((codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) &
+ if ((snd_soc_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) &
DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC])
offset[DA732X_HPL_DAC] &= ~step;
- if ((codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) &
+ if ((snd_soc_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) &
DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC])
offset[DA732X_HPR_DAC] &= ~step;
@@ -1364,9 +1360,9 @@ static void da732x_output_offset_adjust(struct snd_soc_codec *codec)
msleep(DA732X_WAIT_FOR_STABILIZATION);
/* Check output offset sign */
- sign[DA732X_HPL_AMP] = codec->hw_read(codec, DA732X_REG_HPL) &
+ sign[DA732X_HPL_AMP] = snd_soc_read(codec, DA732X_REG_HPL) &
DA732X_HP_OUT_COMPO;
- sign[DA732X_HPR_AMP] = codec->hw_read(codec, DA732X_REG_HPR) &
+ sign[DA732X_HPR_AMP] = snd_soc_read(codec, DA732X_REG_HPR) &
DA732X_HP_OUT_COMPO;
snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_COMP |
@@ -1387,10 +1383,10 @@ static void da732x_output_offset_adjust(struct snd_soc_codec *codec)
msleep(DA732X_WAIT_FOR_STABILIZATION);
- if ((codec->hw_read(codec, DA732X_REG_HPL) &
+ if ((snd_soc_read(codec, DA732X_REG_HPL) &
DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP])
offset[DA732X_HPL_AMP] &= ~step;
- if ((codec->hw_read(codec, DA732X_REG_HPR) &
+ if ((snd_soc_read(codec, DA732X_REG_HPR) &
DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP])
offset[DA732X_HPR_AMP] &= ~step;
@@ -1487,8 +1483,8 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec,
da732x_hp_dc_offset_cancellation(codec);
- regcache_cache_only(codec->control_data, false);
- regcache_sync(codec->control_data);
+ regcache_cache_only(da732x->regmap, false);
+ regcache_sync(da732x->regmap);
} else {
snd_soc_update_bits(codec, DA732X_REG_BIAS_EN,
DA732X_BIAS_BOOST_MASK,
@@ -1499,7 +1495,7 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec,
}
break;
case SND_SOC_BIAS_OFF:
- regcache_cache_only(codec->control_data, true);
+ regcache_cache_only(da732x->regmap, true);
da732x_set_charge_pump(codec, DA732X_DISABLE_CP);
snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_EN,
DA732X_BIAS_DIS);
@@ -1516,23 +1512,14 @@ static int da732x_probe(struct snd_soc_codec *codec)
{
struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret = 0;
da732x->codec = codec;
dapm->idle_bias_off = false;
- codec->control_data = da732x->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec.\n");
- goto err;
- }
-
da732x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-err:
- return ret;
+
+ return 0;
}
static int da732x_remove(struct snd_soc_codec *codec)
@@ -1554,7 +1541,6 @@ static struct snd_soc_codec_driver soc_codec_dev_da732x = {
.dapm_routes = da732x_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes),
.set_pll = da732x_set_dai_pll,
- .reg_cache_size = ARRAY_SIZE(da732x_reg_cache),
};
static int da732x_i2c_probe(struct i2c_client *i2c,
@@ -1585,7 +1571,8 @@ static int da732x_i2c_probe(struct i2c_client *i2c,
}
dev_info(&i2c->dev, "Revision: %d.%d\n",
- (reg & DA732X_ID_MAJOR_MASK), (reg & DA732X_ID_MINOR_MASK));
+ (reg & DA732X_ID_MAJOR_MASK) >> 4,
+ (reg & DA732X_ID_MINOR_MASK));
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da732x,
da732x_dai, ARRAY_SIZE(da732x_dai));
diff --git a/sound/soc/codecs/da732x.h b/sound/soc/codecs/da732x.h
index c8ce5475de2..1dceafeec41 100644
--- a/sound/soc/codecs/da732x.h
+++ b/sound/soc/codecs/da732x.h
@@ -113,9 +113,6 @@
#define DA732X_EQ_OVERALL_VOL_DB_MIN -1800
#define DA732X_EQ_OVERALL_VOL_DB_INC 600
-#define DA732X_SOC_ENUM_DOUBLE_R(xreg, xrreg, xmax, xtext) \
- {.reg = xreg, .reg2 = xrreg, .max = xmax, .texts = xtext}
-
enum da732x_sysctl {
DA732X_SR_8KHZ = 0x1,
DA732X_SR_11_025KHZ = 0x2,
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c
index 52b79a487ac..ad19cc56702 100644
--- a/sound/soc/codecs/da9055.c
+++ b/sound/soc/codecs/da9055.c
@@ -18,6 +18,8 @@
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -321,22 +323,22 @@ static const char * const da9055_hpf_cutoff_txt[] = {
"Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000"
};
-static const struct soc_enum da9055_dac_hpf_cutoff =
- SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_dac_hpf_cutoff,
+ DA9055_DAC_FILTERS1, 4, da9055_hpf_cutoff_txt);
-static const struct soc_enum da9055_adc_hpf_cutoff =
- SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_adc_hpf_cutoff,
+ DA9055_ADC_FILTERS1, 4, da9055_hpf_cutoff_txt);
/* ADC and DAC voice mode (8kHz) high pass cutoff value */
static const char * const da9055_vf_cutoff_txt[] = {
"2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
};
-static const struct soc_enum da9055_dac_vf_cutoff =
- SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 0, 8, da9055_vf_cutoff_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_dac_vf_cutoff,
+ DA9055_DAC_FILTERS1, 0, da9055_vf_cutoff_txt);
-static const struct soc_enum da9055_adc_vf_cutoff =
- SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 0, 8, da9055_vf_cutoff_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_adc_vf_cutoff,
+ DA9055_ADC_FILTERS1, 0, da9055_vf_cutoff_txt);
/* Gain ramping rate value */
static const char * const da9055_gain_ramping_txt[] = {
@@ -344,44 +346,44 @@ static const char * const da9055_gain_ramping_txt[] = {
"nominal rate / 8"
};
-static const struct soc_enum da9055_gain_ramping_rate =
- SOC_ENUM_SINGLE(DA9055_GAIN_RAMP_CTRL, 0, 4, da9055_gain_ramping_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_gain_ramping_rate,
+ DA9055_GAIN_RAMP_CTRL, 0, da9055_gain_ramping_txt);
/* DAC noise gate setup time value */
static const char * const da9055_dac_ng_setup_time_txt[] = {
"256 samples", "512 samples", "1024 samples", "2048 samples"
};
-static const struct soc_enum da9055_dac_ng_setup_time =
- SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 0, 4,
- da9055_dac_ng_setup_time_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_setup_time,
+ DA9055_DAC_NG_SETUP_TIME, 0,
+ da9055_dac_ng_setup_time_txt);
/* DAC noise gate rampup rate value */
static const char * const da9055_dac_ng_rampup_txt[] = {
"0.02 ms/dB", "0.16 ms/dB"
};
-static const struct soc_enum da9055_dac_ng_rampup_rate =
- SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 2, 2,
- da9055_dac_ng_rampup_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampup_rate,
+ DA9055_DAC_NG_SETUP_TIME, 2,
+ da9055_dac_ng_rampup_txt);
/* DAC noise gate rampdown rate value */
static const char * const da9055_dac_ng_rampdown_txt[] = {
"0.64 ms/dB", "20.48 ms/dB"
};
-static const struct soc_enum da9055_dac_ng_rampdown_rate =
- SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 3, 2,
- da9055_dac_ng_rampdown_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampdown_rate,
+ DA9055_DAC_NG_SETUP_TIME, 3,
+ da9055_dac_ng_rampdown_txt);
/* DAC soft mute rate value */
static const char * const da9055_dac_soft_mute_rate_txt[] = {
"1", "2", "4", "8", "16", "32", "64"
};
-static const struct soc_enum da9055_dac_soft_mute_rate =
- SOC_ENUM_SINGLE(DA9055_DAC_FILTERS5, 4, 7,
- da9055_dac_soft_mute_rate_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_dac_soft_mute_rate,
+ DA9055_DAC_FILTERS5, 4,
+ da9055_dac_soft_mute_rate_txt);
/* DAC routing select */
static const char * const da9055_dac_src_txt[] = {
@@ -389,40 +391,40 @@ static const char * const da9055_dac_src_txt[] = {
"AIF input right"
};
-static const struct soc_enum da9055_dac_l_src =
- SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 0, 4, da9055_dac_src_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_dac_l_src,
+ DA9055_DIG_ROUTING_DAC, 0, da9055_dac_src_txt);
-static const struct soc_enum da9055_dac_r_src =
- SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 4, 4, da9055_dac_src_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_dac_r_src,
+ DA9055_DIG_ROUTING_DAC, 4, da9055_dac_src_txt);
/* MIC PGA Left source select */
static const char * const da9055_mic_l_src_txt[] = {
"MIC1_P_N", "MIC1_P", "MIC1_N", "MIC2_L"
};
-static const struct soc_enum da9055_mic_l_src =
- SOC_ENUM_SINGLE(DA9055_MIXIN_L_SELECT, 4, 4, da9055_mic_l_src_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_mic_l_src,
+ DA9055_MIXIN_L_SELECT, 4, da9055_mic_l_src_txt);
/* MIC PGA Right source select */
static const char * const da9055_mic_r_src_txt[] = {
"MIC2_R_L", "MIC2_R", "MIC2_L"
};
-static const struct soc_enum da9055_mic_r_src =
- SOC_ENUM_SINGLE(DA9055_MIXIN_R_SELECT, 4, 3, da9055_mic_r_src_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_mic_r_src,
+ DA9055_MIXIN_R_SELECT, 4, da9055_mic_r_src_txt);
/* ALC Input Signal Tracking rate select */
static const char * const da9055_signal_tracking_rate_txt[] = {
"1/4", "1/16", "1/256", "1/65536"
};
-static const struct soc_enum da9055_integ_attack_rate =
- SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 4, 4,
- da9055_signal_tracking_rate_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_integ_attack_rate,
+ DA9055_ALC_CTRL3, 4,
+ da9055_signal_tracking_rate_txt);
-static const struct soc_enum da9055_integ_release_rate =
- SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 6, 4,
- da9055_signal_tracking_rate_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_integ_release_rate,
+ DA9055_ALC_CTRL3, 6,
+ da9055_signal_tracking_rate_txt);
/* ALC Attack Rate select */
static const char * const da9055_attack_rate_txt[] = {
@@ -430,8 +432,8 @@ static const char * const da9055_attack_rate_txt[] = {
"5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs"
};
-static const struct soc_enum da9055_attack_rate =
- SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 0, 13, da9055_attack_rate_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_attack_rate,
+ DA9055_ALC_CTRL2, 0, da9055_attack_rate_txt);
/* ALC Release Rate select */
static const char * const da9055_release_rate_txt[] = {
@@ -439,8 +441,8 @@ static const char * const da9055_release_rate_txt[] = {
"11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs"
};
-static const struct soc_enum da9055_release_rate =
- SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 4, 11, da9055_release_rate_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_release_rate,
+ DA9055_ALC_CTRL2, 4, da9055_release_rate_txt);
/* ALC Hold Time select */
static const char * const da9055_hold_time_txt[] = {
@@ -449,8 +451,8 @@ static const char * const da9055_hold_time_txt[] = {
"253952/fs", "507904/fs", "1015808/fs", "2031616/fs"
};
-static const struct soc_enum da9055_hold_time =
- SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 0, 16, da9055_hold_time_txt);
+static SOC_ENUM_SINGLE_DECL(da9055_hold_time,
+ DA9055_ALC_CTRL3, 0, da9055_hold_time_txt);
static int da9055_get_alc_data(struct snd_soc_codec *codec, u8 reg_val)
{
@@ -482,7 +484,7 @@ static int da9055_get_alc_data(struct snd_soc_codec *codec, u8 reg_val)
static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
u8 reg_val, adc_left, adc_right, mic_left, mic_right;
int avg_left_data, avg_right_data, offset_l, offset_r;
@@ -1381,16 +1383,8 @@ static int da9055_set_bias_level(struct snd_soc_codec *codec,
static int da9055_probe(struct snd_soc_codec *codec)
{
- int ret;
struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec);
- codec->control_data = da9055->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
/* Enable all Gain Ramps */
snd_soc_update_bits(codec, DA9055_AUX_L_CTRL,
DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN);
@@ -1523,17 +1517,30 @@ static int da9055_remove(struct i2c_client *client)
return 0;
}
+/*
+ * DO NOT change the device Ids. The naming is intentionally specific as both
+ * the CODEC and PMIC parts of this chip are instantiated separately as I2C
+ * devices (both have configurable I2C addresses, and are to all intents and
+ * purposes separate). As a result there are specific DA9055 Ids for CODEC
+ * and PMIC, which must be different to operate together.
+ */
static const struct i2c_device_id da9055_i2c_id[] = {
- { "da9055", 0 },
+ { "da9055-codec", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
+static const struct of_device_id da9055_of_match[] = {
+ { .compatible = "dlg,da9055-codec", },
+ { }
+};
+
/* I2C codec control layer */
static struct i2c_driver da9055_i2c_driver = {
.driver = {
- .name = "da9055",
+ .name = "da9055-codec",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(da9055_of_match),
},
.probe = da9055_i2c_probe,
.remove = da9055_remove,
diff --git a/sound/soc/codecs/hdmi.c b/sound/soc/codecs/hdmi.c
index 9cb1c7d3e1d..1087fd5f991 100644
--- a/sound/soc/codecs/hdmi.c
+++ b/sound/soc/codecs/hdmi.c
@@ -20,6 +20,7 @@
*/
#include <linux/module.h>
#include <sound/soc.h>
+#include <linux/of.h>
#include <linux/of_device.h>
#define DRV_NAME "hdmi-audio-codec"
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c
index 5839048ec46..3a89ce66d51 100644
--- a/sound/soc/codecs/isabelle.c
+++ b/sound/soc/codecs/isabelle.c
@@ -140,13 +140,17 @@ static const char *isabelle_rx1_texts[] = {"VRX1", "ARX1"};
static const char *isabelle_rx2_texts[] = {"VRX2", "ARX2"};
static const struct soc_enum isabelle_rx1_enum[] = {
- SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3, 1, isabelle_rx1_texts),
- SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5, 1, isabelle_rx1_texts),
+ SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3,
+ ARRAY_SIZE(isabelle_rx1_texts), isabelle_rx1_texts),
+ SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5,
+ ARRAY_SIZE(isabelle_rx1_texts), isabelle_rx1_texts),
};
static const struct soc_enum isabelle_rx2_enum[] = {
- SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2, 1, isabelle_rx2_texts),
- SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4, 1, isabelle_rx2_texts),
+ SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2,
+ ARRAY_SIZE(isabelle_rx2_texts), isabelle_rx2_texts),
+ SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4,
+ ARRAY_SIZE(isabelle_rx2_texts), isabelle_rx2_texts),
};
/* Headset DAC playback switches */
@@ -161,13 +165,17 @@ static const char *isabelle_atx_texts[] = {"AMIC1", "DMIC"};
static const char *isabelle_vtx_texts[] = {"AMIC2", "DMIC"};
static const struct soc_enum isabelle_atx_enum[] = {
- SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7, 1, isabelle_atx_texts),
- SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_atx_texts),
+ SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7,
+ ARRAY_SIZE(isabelle_atx_texts), isabelle_atx_texts),
+ SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0,
+ ARRAY_SIZE(isabelle_atx_texts), isabelle_atx_texts),
};
static const struct soc_enum isabelle_vtx_enum[] = {
- SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6, 1, isabelle_vtx_texts),
- SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_vtx_texts),
+ SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6,
+ ARRAY_SIZE(isabelle_vtx_texts), isabelle_vtx_texts),
+ SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0,
+ ARRAY_SIZE(isabelle_vtx_texts), isabelle_vtx_texts),
};
static const struct snd_kcontrol_new atx_mux_controls =
@@ -183,17 +191,13 @@ static const char *isabelle_amic1_texts[] = {
/* Left analog microphone selection */
static const char *isabelle_amic2_texts[] = {"Sub Mic", "Aux/FM Right"};
-static const struct soc_enum isabelle_amic1_enum[] = {
- SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 5,
- ARRAY_SIZE(isabelle_amic1_texts),
- isabelle_amic1_texts),
-};
+static SOC_ENUM_SINGLE_DECL(isabelle_amic1_enum,
+ ISABELLE_AMIC_CFG_REG, 5,
+ isabelle_amic1_texts);
-static const struct soc_enum isabelle_amic2_enum[] = {
- SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 4,
- ARRAY_SIZE(isabelle_amic2_texts),
- isabelle_amic2_texts),
-};
+static SOC_ENUM_SINGLE_DECL(isabelle_amic2_enum,
+ ISABELLE_AMIC_CFG_REG, 4,
+ isabelle_amic2_texts);
static const struct snd_kcontrol_new amic1_control =
SOC_DAPM_ENUM("Route", isabelle_amic1_enum);
@@ -206,16 +210,20 @@ static const char *isabelle_st_audio_texts[] = {"ATX1", "ATX2"};
static const char *isabelle_st_voice_texts[] = {"VTX1", "VTX2"};
static const struct soc_enum isabelle_st_audio_enum[] = {
- SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7, 1,
+ SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7,
+ ARRAY_SIZE(isabelle_st_audio_texts),
isabelle_st_audio_texts),
- SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7, 1,
+ SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7,
+ ARRAY_SIZE(isabelle_st_audio_texts),
isabelle_st_audio_texts),
};
static const struct soc_enum isabelle_st_voice_enum[] = {
- SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7, 1,
+ SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7,
+ ARRAY_SIZE(isabelle_st_voice_texts),
isabelle_st_voice_texts),
- SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7, 1,
+ SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7,
+ ARRAY_SIZE(isabelle_st_voice_texts),
isabelle_st_voice_texts),
};
@@ -910,8 +918,7 @@ static int isabelle_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 aif = 0;
unsigned int fs_val = 0;
@@ -1082,23 +1089,7 @@ static struct snd_soc_dai_driver isabelle_dai[] = {
},
};
-static int isabelle_probe(struct snd_soc_codec *codec)
-{
- int ret = 0;
-
- codec->control_data = dev_get_regmap(codec->dev, NULL);
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
static struct snd_soc_codec_driver soc_codec_dev_isabelle = {
- .probe = isabelle_probe,
.set_bias_level = isabelle_set_bias_level,
.controls = isabelle_snd_controls,
.num_controls = ARRAY_SIZE(isabelle_snd_controls),
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 0e5743ea79d..a924bb9d788 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -49,7 +49,7 @@ static const struct reg_default lm4857_default_regs[] = {
static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = lm4857->mode;
@@ -60,7 +60,7 @@ static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
uint8_t value = ucontrol->value.integer.value[0];
@@ -101,8 +101,7 @@ static const char *lm4857_mode[] = {
"Headphone",
};
-static const struct soc_enum lm4857_mode_enum =
- SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode);
+static SOC_ENUM_SINGLE_EXT_DECL(lm4857_mode_enum, lm4857_mode);
static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("IN"),
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c
index e19490cfb3a..275b3f72f3f 100644
--- a/sound/soc/codecs/lm49453.c
+++ b/sound/soc/codecs/lm49453.c
@@ -195,33 +195,31 @@ struct lm49453_priv {
static const char *lm49453_mic2mode_text[] = {"Single Ended", "Differential"};
-static const SOC_ENUM_SINGLE_DECL(lm49453_mic2mode_enum, LM49453_P0_MICR_REG, 5,
- lm49453_mic2mode_text);
+static SOC_ENUM_SINGLE_DECL(lm49453_mic2mode_enum, LM49453_P0_MICR_REG, 5,
+ lm49453_mic2mode_text);
static const char *lm49453_dmic_cfg_text[] = {"DMICDAT1", "DMICDAT2"};
-static const SOC_ENUM_SINGLE_DECL(lm49453_dmic12_cfg_enum,
- LM49453_P0_DIGITAL_MIC1_CONFIG_REG,
- 7, lm49453_dmic_cfg_text);
+static SOC_ENUM_SINGLE_DECL(lm49453_dmic12_cfg_enum,
+ LM49453_P0_DIGITAL_MIC1_CONFIG_REG, 7,
+ lm49453_dmic_cfg_text);
-static const SOC_ENUM_SINGLE_DECL(lm49453_dmic34_cfg_enum,
- LM49453_P0_DIGITAL_MIC2_CONFIG_REG,
- 7, lm49453_dmic_cfg_text);
+static SOC_ENUM_SINGLE_DECL(lm49453_dmic34_cfg_enum,
+ LM49453_P0_DIGITAL_MIC2_CONFIG_REG, 7,
+ lm49453_dmic_cfg_text);
/* MUX Controls */
static const char *lm49453_adcl_mux_text[] = { "MIC1", "Aux_L" };
static const char *lm49453_adcr_mux_text[] = { "MIC2", "Aux_R" };
-static const struct soc_enum lm49453_adcl_enum =
- SOC_ENUM_SINGLE(LM49453_P0_ANALOG_MIXER_ADC_REG, 0,
- ARRAY_SIZE(lm49453_adcl_mux_text),
- lm49453_adcl_mux_text);
+static SOC_ENUM_SINGLE_DECL(lm49453_adcl_enum,
+ LM49453_P0_ANALOG_MIXER_ADC_REG, 0,
+ lm49453_adcl_mux_text);
-static const struct soc_enum lm49453_adcr_enum =
- SOC_ENUM_SINGLE(LM49453_P0_ANALOG_MIXER_ADC_REG, 1,
- ARRAY_SIZE(lm49453_adcr_mux_text),
- lm49453_adcr_mux_text);
+static SOC_ENUM_SINGLE_DECL(lm49453_adcr_enum,
+ LM49453_P0_ANALOG_MIXER_ADC_REG, 1,
+ lm49453_adcr_mux_text);
static const struct snd_kcontrol_new lm49453_adcl_mux_control =
SOC_DAPM_ENUM("ADC Left Mux", lm49453_adcl_enum);
@@ -1409,22 +1407,6 @@ static int lm49453_resume(struct snd_soc_codec *codec)
return 0;
}
-static int lm49453_probe(struct snd_soc_codec *codec)
-{
- struct lm49453_priv *lm49453 = snd_soc_codec_get_drvdata(codec);
- int ret = 0;
-
- codec->control_data = lm49453->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
/* power down chip */
static int lm49453_remove(struct snd_soc_codec *codec)
{
@@ -1433,7 +1415,6 @@ static int lm49453_remove(struct snd_soc_codec *codec)
}
static struct snd_soc_codec_driver soc_codec_dev_lm49453 = {
- .probe = lm49453_probe,
.remove = lm49453_remove,
.suspend = lm49453_suspend,
.resume = lm49453_resume,
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
index 31f91560e9f..e1c196a4193 100644
--- a/sound/soc/codecs/max9768.c
+++ b/sound/soc/codecs/max9768.c
@@ -43,7 +43,7 @@ static struct reg_default max9768_default_regs[] = {
static int max9768_get_gpio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
int val = gpio_get_value_cansleep(max9768->mute_gpio);
@@ -55,7 +55,7 @@ static int max9768_get_gpio(struct snd_kcontrol *kcontrol,
static int max9768_set_gpio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
gpio_set_value_cansleep(max9768->mute_gpio, !ucontrol->value.integer.value[0]);
@@ -135,11 +135,6 @@ static int max9768_probe(struct snd_soc_codec *codec)
struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
int ret;
- codec->control_data = max9768->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 2, 6, SND_SOC_REGMAP);
- if (ret)
- return ret;
-
if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) {
ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM);
if (ret)
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index ee660e2d3df..9134982807b 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -597,28 +597,27 @@ static const unsigned int max98088_exmode_values[] = {
0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32
};
-static const struct soc_enum max98088_exmode_enum =
- SOC_VALUE_ENUM_SINGLE(M98088_REG_41_SPKDHP, 0, 127,
- ARRAY_SIZE(max98088_exmode_texts),
- max98088_exmode_texts,
- max98088_exmode_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(max98088_exmode_enum,
+ M98088_REG_41_SPKDHP, 0, 127,
+ max98088_exmode_texts,
+ max98088_exmode_values);
static const char *max98088_ex_thresh[] = { /* volts PP */
"0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"};
-static const struct soc_enum max98088_ex_thresh_enum[] = {
- SOC_ENUM_SINGLE(M98088_REG_42_SPKDHP_THRESH, 0, 8,
- max98088_ex_thresh),
-};
+static SOC_ENUM_SINGLE_DECL(max98088_ex_thresh_enum,
+ M98088_REG_42_SPKDHP_THRESH, 0,
+ max98088_ex_thresh);
static const char *max98088_fltr_mode[] = {"Voice", "Music" };
-static const struct soc_enum max98088_filter_mode_enum[] = {
- SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 7, 2, max98088_fltr_mode),
-};
+static SOC_ENUM_SINGLE_DECL(max98088_filter_mode_enum,
+ M98088_REG_18_DAI1_FILTERS, 7,
+ max98088_fltr_mode);
static const char *max98088_extmic_text[] = { "None", "MIC1", "MIC2" };
-static const struct soc_enum max98088_extmic_enum =
- SOC_ENUM_SINGLE(M98088_REG_48_CFG_MIC, 0, 3, max98088_extmic_text);
+static SOC_ENUM_SINGLE_DECL(max98088_extmic_enum,
+ M98088_REG_48_CFG_MIC, 0,
+ max98088_extmic_text);
static const struct snd_kcontrol_new max98088_extmic_mux =
SOC_DAPM_ENUM("External MIC Mux", max98088_extmic_enum);
@@ -626,17 +625,17 @@ static const struct snd_kcontrol_new max98088_extmic_mux =
static const char *max98088_dai1_fltr[] = {
"Off", "fc=258/fs=16k", "fc=500/fs=16k",
"fc=258/fs=8k", "fc=500/fs=8k", "fc=200"};
-static const struct soc_enum max98088_dai1_dac_filter_enum[] = {
- SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 0, 6, max98088_dai1_fltr),
-};
-static const struct soc_enum max98088_dai1_adc_filter_enum[] = {
- SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 4, 6, max98088_dai1_fltr),
-};
+static SOC_ENUM_SINGLE_DECL(max98088_dai1_dac_filter_enum,
+ M98088_REG_18_DAI1_FILTERS, 0,
+ max98088_dai1_fltr);
+static SOC_ENUM_SINGLE_DECL(max98088_dai1_adc_filter_enum,
+ M98088_REG_18_DAI1_FILTERS, 4,
+ max98088_dai1_fltr);
static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
unsigned int sel = ucontrol->value.integer.value[0];
@@ -650,7 +649,7 @@ static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol,
static int max98088_mic1pre_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = max98088->mic1pre;
@@ -660,7 +659,7 @@ static int max98088_mic1pre_get(struct snd_kcontrol *kcontrol,
static int max98088_mic2pre_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
unsigned int sel = ucontrol->value.integer.value[0];
@@ -674,7 +673,7 @@ static int max98088_mic2pre_set(struct snd_kcontrol *kcontrol,
static int max98088_mic2pre_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = max98088->mic2pre;
@@ -1751,7 +1750,7 @@ static void max98088_setup_eq2(struct snd_soc_codec *codec)
static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
struct max98088_pdata *pdata = max98088->pdata;
int channel = max98088_get_channel(codec, kcontrol->id.name);
@@ -1783,7 +1782,7 @@ static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol,
static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
int channel = max98088_get_channel(codec, kcontrol->id.name);
struct max98088_cdata *cdata;
@@ -1849,7 +1848,7 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
/* Now point the soc_enum to .texts array items */
max98088->eq_enum.texts = max98088->eq_texts;
- max98088->eq_enum.max = max98088->eq_textcnt;
+ max98088->eq_enum.items = max98088->eq_textcnt;
ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
@@ -1915,12 +1914,6 @@ static int max98088_probe(struct snd_soc_codec *codec)
regcache_mark_dirty(max98088->regmap);
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
/* initialize private data */
max98088->sysclk = (unsigned)-1;
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index 51f9b3d16b4..f5fccc7a8e8 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -11,10 +11,13 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <linux/clk.h>
#include <sound/jack.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -255,6 +258,7 @@ static struct reg_default max98090_reg[] = {
static bool max98090_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
+ case M98090_REG_SOFTWARE_RESET:
case M98090_REG_DEVICE_STATUS:
case M98090_REG_JACK_STATUS:
case M98090_REG_REVISION_ID:
@@ -336,6 +340,7 @@ static bool max98090_readable_register(struct device *dev, unsigned int reg)
case M98090_REG_RECORD_TDM_SLOT:
case M98090_REG_SAMPLE_RATE:
case M98090_REG_DMIC34_BIQUAD_BASE ... M98090_REG_DMIC34_BIQUAD_BASE + 0x0E:
+ case M98090_REG_REVISION_ID:
return true;
default:
return false;
@@ -388,6 +393,7 @@ static const DECLARE_TLV_DB_SCALE(max98090_alc_tlv, -1500, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98090_alcmakeup_tlv, 0, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98090_alccomp_tlv, -3100, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98090_drcexp_tlv, -6600, 100, 0);
+static const DECLARE_TLV_DB_SCALE(max98090_sdg_tlv, 50, 200, 0);
static const unsigned int max98090_mixout_tlv[] = {
TLV_DB_RANGE_HEAD(2),
@@ -425,7 +431,7 @@ static const unsigned int max98090_rcv_lout_tlv[] = {
static int max98090_get_enab_tlv(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
@@ -465,7 +471,7 @@ static int max98090_get_enab_tlv(struct snd_kcontrol *kcontrol,
static int max98090_put_enab_tlv(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
@@ -512,65 +518,75 @@ static const char *max98090_perf_pwr_text[] =
static const char *max98090_pwr_perf_text[] =
{ "Low Power", "High Performance" };
-static const struct soc_enum max98090_vcmbandgap_enum =
- SOC_ENUM_SINGLE(M98090_REG_BIAS_CONTROL, M98090_VCM_MODE_SHIFT,
- ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text);
+static SOC_ENUM_SINGLE_DECL(max98090_vcmbandgap_enum,
+ M98090_REG_BIAS_CONTROL,
+ M98090_VCM_MODE_SHIFT,
+ max98090_pwr_perf_text);
static const char *max98090_osr128_text[] = { "64*fs", "128*fs" };
-static const struct soc_enum max98090_osr128_enum =
- SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_OSR128_SHIFT,
- ARRAY_SIZE(max98090_osr128_text), max98090_osr128_text);
+static SOC_ENUM_SINGLE_DECL(max98090_osr128_enum,
+ M98090_REG_ADC_CONTROL,
+ M98090_OSR128_SHIFT,
+ max98090_osr128_text);
static const char *max98090_mode_text[] = { "Voice", "Music" };
-static const struct soc_enum max98090_mode_enum =
- SOC_ENUM_SINGLE(M98090_REG_FILTER_CONFIG, M98090_MODE_SHIFT,
- ARRAY_SIZE(max98090_mode_text), max98090_mode_text);
+static SOC_ENUM_SINGLE_DECL(max98090_mode_enum,
+ M98090_REG_FILTER_CONFIG,
+ M98090_MODE_SHIFT,
+ max98090_mode_text);
-static const struct soc_enum max98090_filter_dmic34mode_enum =
- SOC_ENUM_SINGLE(M98090_REG_FILTER_CONFIG,
- M98090_FLT_DMIC34MODE_SHIFT,
- ARRAY_SIZE(max98090_mode_text), max98090_mode_text);
+static SOC_ENUM_SINGLE_DECL(max98090_filter_dmic34mode_enum,
+ M98090_REG_FILTER_CONFIG,
+ M98090_FLT_DMIC34MODE_SHIFT,
+ max98090_mode_text);
static const char *max98090_drcatk_text[] =
{ "0.5ms", "1ms", "5ms", "10ms", "25ms", "50ms", "100ms", "200ms" };
-static const struct soc_enum max98090_drcatk_enum =
- SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCATK_SHIFT,
- ARRAY_SIZE(max98090_drcatk_text), max98090_drcatk_text);
+static SOC_ENUM_SINGLE_DECL(max98090_drcatk_enum,
+ M98090_REG_DRC_TIMING,
+ M98090_DRCATK_SHIFT,
+ max98090_drcatk_text);
static const char *max98090_drcrls_text[] =
{ "8s", "4s", "2s", "1s", "0.5s", "0.25s", "0.125s", "0.0625s" };
-static const struct soc_enum max98090_drcrls_enum =
- SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCRLS_SHIFT,
- ARRAY_SIZE(max98090_drcrls_text), max98090_drcrls_text);
+static SOC_ENUM_SINGLE_DECL(max98090_drcrls_enum,
+ M98090_REG_DRC_TIMING,
+ M98090_DRCRLS_SHIFT,
+ max98090_drcrls_text);
static const char *max98090_alccmp_text[] =
{ "1:1", "1:1.5", "1:2", "1:4", "1:INF" };
-static const struct soc_enum max98090_alccmp_enum =
- SOC_ENUM_SINGLE(M98090_REG_DRC_COMPRESSOR, M98090_DRCCMP_SHIFT,
- ARRAY_SIZE(max98090_alccmp_text), max98090_alccmp_text);
+static SOC_ENUM_SINGLE_DECL(max98090_alccmp_enum,
+ M98090_REG_DRC_COMPRESSOR,
+ M98090_DRCCMP_SHIFT,
+ max98090_alccmp_text);
static const char *max98090_drcexp_text[] = { "1:1", "2:1", "3:1" };
-static const struct soc_enum max98090_drcexp_enum =
- SOC_ENUM_SINGLE(M98090_REG_DRC_EXPANDER, M98090_DRCEXP_SHIFT,
- ARRAY_SIZE(max98090_drcexp_text), max98090_drcexp_text);
+static SOC_ENUM_SINGLE_DECL(max98090_drcexp_enum,
+ M98090_REG_DRC_EXPANDER,
+ M98090_DRCEXP_SHIFT,
+ max98090_drcexp_text);
-static const struct soc_enum max98090_dac_perfmode_enum =
- SOC_ENUM_SINGLE(M98090_REG_DAC_CONTROL, M98090_PERFMODE_SHIFT,
- ARRAY_SIZE(max98090_perf_pwr_text), max98090_perf_pwr_text);
+static SOC_ENUM_SINGLE_DECL(max98090_dac_perfmode_enum,
+ M98090_REG_DAC_CONTROL,
+ M98090_PERFMODE_SHIFT,
+ max98090_perf_pwr_text);
-static const struct soc_enum max98090_dachp_enum =
- SOC_ENUM_SINGLE(M98090_REG_DAC_CONTROL, M98090_DACHP_SHIFT,
- ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text);
+static SOC_ENUM_SINGLE_DECL(max98090_dachp_enum,
+ M98090_REG_DAC_CONTROL,
+ M98090_DACHP_SHIFT,
+ max98090_pwr_perf_text);
-static const struct soc_enum max98090_adchp_enum =
- SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_ADCHP_SHIFT,
- ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text);
+static SOC_ENUM_SINGLE_DECL(max98090_adchp_enum,
+ M98090_REG_ADC_CONTROL,
+ M98090_ADCHP_SHIFT,
+ max98090_pwr_perf_text);
static const struct snd_kcontrol_new max98090_snd_controls[] = {
SOC_ENUM("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum),
@@ -654,7 +670,7 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
SOC_SINGLE_EXT_TLV("Digital Sidetone Volume",
M98090_REG_ADC_SIDETONE, M98090_DVST_SHIFT,
M98090_DVST_NUM - 1, 1, max98090_get_enab_tlv,
- max98090_put_enab_tlv, max98090_micboost_tlv),
+ max98090_put_enab_tlv, max98090_sdg_tlv),
SOC_SINGLE_TLV("Digital Coarse Volume", M98090_REG_DAI_PLAYBACK_LEVEL,
M98090_DVG_SHIFT, M98090_DVG_NUM - 1, 0,
max98090_dvg_tlv),
@@ -841,39 +857,42 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w,
static const char *mic1_mux_text[] = { "IN12", "IN56" };
-static const struct soc_enum mic1_mux_enum =
- SOC_ENUM_SINGLE(M98090_REG_INPUT_MODE, M98090_EXTMIC1_SHIFT,
- ARRAY_SIZE(mic1_mux_text), mic1_mux_text);
+static SOC_ENUM_SINGLE_DECL(mic1_mux_enum,
+ M98090_REG_INPUT_MODE,
+ M98090_EXTMIC1_SHIFT,
+ mic1_mux_text);
static const struct snd_kcontrol_new max98090_mic1_mux =
SOC_DAPM_ENUM("MIC1 Mux", mic1_mux_enum);
static const char *mic2_mux_text[] = { "IN34", "IN56" };
-static const struct soc_enum mic2_mux_enum =
- SOC_ENUM_SINGLE(M98090_REG_INPUT_MODE, M98090_EXTMIC2_SHIFT,
- ARRAY_SIZE(mic2_mux_text), mic2_mux_text);
+static SOC_ENUM_SINGLE_DECL(mic2_mux_enum,
+ M98090_REG_INPUT_MODE,
+ M98090_EXTMIC2_SHIFT,
+ mic2_mux_text);
static const struct snd_kcontrol_new max98090_mic2_mux =
SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum);
static const char *dmic_mux_text[] = { "ADC", "DMIC" };
-static const struct soc_enum dmic_mux_enum =
- SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dmic_mux_text), dmic_mux_text);
+static SOC_ENUM_SINGLE_VIRT_DECL(dmic_mux_enum, dmic_mux_text);
static const struct snd_kcontrol_new max98090_dmic_mux =
- SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum);
+ SOC_DAPM_ENUM("DMIC Mux", dmic_mux_enum);
static const char *max98090_micpre_text[] = { "Off", "On" };
-static const struct soc_enum max98090_pa1en_enum =
- SOC_ENUM_SINGLE(M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT,
- ARRAY_SIZE(max98090_micpre_text), max98090_micpre_text);
+static SOC_ENUM_SINGLE_DECL(max98090_pa1en_enum,
+ M98090_REG_MIC1_INPUT_LEVEL,
+ M98090_MIC_PA1EN_SHIFT,
+ max98090_micpre_text);
-static const struct soc_enum max98090_pa2en_enum =
- SOC_ENUM_SINGLE(M98090_REG_MIC2_INPUT_LEVEL, M98090_MIC_PA2EN_SHIFT,
- ARRAY_SIZE(max98090_micpre_text), max98090_micpre_text);
+static SOC_ENUM_SINGLE_DECL(max98090_pa2en_enum,
+ M98090_REG_MIC2_INPUT_LEVEL,
+ M98090_MIC_PA2EN_SHIFT,
+ max98090_micpre_text);
/* LINEA mixer switch */
static const struct snd_kcontrol_new max98090_linea_mixer_controls[] = {
@@ -937,13 +956,15 @@ static const struct snd_kcontrol_new max98090_right_adc_mixer_controls[] = {
static const char *lten_mux_text[] = { "Normal", "Loopthrough" };
-static const struct soc_enum ltenl_mux_enum =
- SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LTEN_SHIFT,
- ARRAY_SIZE(lten_mux_text), lten_mux_text);
+static SOC_ENUM_SINGLE_DECL(ltenl_mux_enum,
+ M98090_REG_IO_CONFIGURATION,
+ M98090_LTEN_SHIFT,
+ lten_mux_text);
-static const struct soc_enum ltenr_mux_enum =
- SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LTEN_SHIFT,
- ARRAY_SIZE(lten_mux_text), lten_mux_text);
+static SOC_ENUM_SINGLE_DECL(ltenr_mux_enum,
+ M98090_REG_IO_CONFIGURATION,
+ M98090_LTEN_SHIFT,
+ lten_mux_text);
static const struct snd_kcontrol_new max98090_ltenl_mux =
SOC_DAPM_ENUM("LTENL Mux", ltenl_mux_enum);
@@ -953,13 +974,15 @@ static const struct snd_kcontrol_new max98090_ltenr_mux =
static const char *lben_mux_text[] = { "Normal", "Loopback" };
-static const struct soc_enum lbenl_mux_enum =
- SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LBEN_SHIFT,
- ARRAY_SIZE(lben_mux_text), lben_mux_text);
+static SOC_ENUM_SINGLE_DECL(lbenl_mux_enum,
+ M98090_REG_IO_CONFIGURATION,
+ M98090_LBEN_SHIFT,
+ lben_mux_text);
-static const struct soc_enum lbenr_mux_enum =
- SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LBEN_SHIFT,
- ARRAY_SIZE(lben_mux_text), lben_mux_text);
+static SOC_ENUM_SINGLE_DECL(lbenr_mux_enum,
+ M98090_REG_IO_CONFIGURATION,
+ M98090_LBEN_SHIFT,
+ lben_mux_text);
static const struct snd_kcontrol_new max98090_lbenl_mux =
SOC_DAPM_ENUM("LBENL Mux", lbenl_mux_enum);
@@ -971,13 +994,15 @@ static const char *stenl_mux_text[] = { "Normal", "Sidetone Left" };
static const char *stenr_mux_text[] = { "Normal", "Sidetone Right" };
-static const struct soc_enum stenl_mux_enum =
- SOC_ENUM_SINGLE(M98090_REG_ADC_SIDETONE, M98090_DSTSL_SHIFT,
- ARRAY_SIZE(stenl_mux_text), stenl_mux_text);
+static SOC_ENUM_SINGLE_DECL(stenl_mux_enum,
+ M98090_REG_ADC_SIDETONE,
+ M98090_DSTSL_SHIFT,
+ stenl_mux_text);
-static const struct soc_enum stenr_mux_enum =
- SOC_ENUM_SINGLE(M98090_REG_ADC_SIDETONE, M98090_DSTSR_SHIFT,
- ARRAY_SIZE(stenr_mux_text), stenr_mux_text);
+static SOC_ENUM_SINGLE_DECL(stenr_mux_enum,
+ M98090_REG_ADC_SIDETONE,
+ M98090_DSTSR_SHIFT,
+ stenr_mux_text);
static const struct snd_kcontrol_new max98090_stenl_mux =
SOC_DAPM_ENUM("STENL Mux", stenl_mux_enum);
@@ -1085,9 +1110,10 @@ static const struct snd_kcontrol_new max98090_right_rcv_mixer_controls[] = {
static const char *linmod_mux_text[] = { "Left Only", "Left and Right" };
-static const struct soc_enum linmod_mux_enum =
- SOC_ENUM_SINGLE(M98090_REG_LOUTR_MIXER, M98090_LINMOD_SHIFT,
- ARRAY_SIZE(linmod_mux_text), linmod_mux_text);
+static SOC_ENUM_SINGLE_DECL(linmod_mux_enum,
+ M98090_REG_LOUTR_MIXER,
+ M98090_LINMOD_SHIFT,
+ linmod_mux_text);
static const struct snd_kcontrol_new max98090_linmod_mux =
SOC_DAPM_ENUM("LINMOD Mux", linmod_mux_enum);
@@ -1097,16 +1123,18 @@ static const char *mixhpsel_mux_text[] = { "DAC Only", "HP Mixer" };
/*
* This is a mux as it selects the HP output, but to DAPM it is a Mixer enable
*/
-static const struct soc_enum mixhplsel_mux_enum =
- SOC_ENUM_SINGLE(M98090_REG_HP_CONTROL, M98090_MIXHPLSEL_SHIFT,
- ARRAY_SIZE(mixhpsel_mux_text), mixhpsel_mux_text);
+static SOC_ENUM_SINGLE_DECL(mixhplsel_mux_enum,
+ M98090_REG_HP_CONTROL,
+ M98090_MIXHPLSEL_SHIFT,
+ mixhpsel_mux_text);
static const struct snd_kcontrol_new max98090_mixhplsel_mux =
SOC_DAPM_ENUM("MIXHPLSEL Mux", mixhplsel_mux_enum);
-static const struct soc_enum mixhprsel_mux_enum =
- SOC_ENUM_SINGLE(M98090_REG_HP_CONTROL, M98090_MIXHPRSEL_SHIFT,
- ARRAY_SIZE(mixhpsel_mux_text), mixhpsel_mux_text);
+static SOC_ENUM_SINGLE_DECL(mixhprsel_mux_enum,
+ M98090_REG_HP_CONTROL,
+ M98090_MIXHPRSEL_SHIFT,
+ mixhpsel_mux_text);
static const struct snd_kcontrol_new max98090_mixhprsel_mux =
SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum);
@@ -1152,8 +1180,7 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
SND_SOC_DAPM_MUX("MIC2 Mux", SND_SOC_NOPM,
0, 0, &max98090_mic2_mux),
- SND_SOC_DAPM_VIRT_MUX("DMIC Mux", SND_SOC_NOPM,
- 0, 0, &max98090_dmic_mux),
+ SND_SOC_DAPM_MUX("DMIC Mux", SND_SOC_NOPM, 0, 0, &max98090_dmic_mux),
SND_SOC_DAPM_PGA_E("MIC1 Input", M98090_REG_MIC1_INPUT_LEVEL,
M98090_MIC_PA1EN_SHIFT, 0, NULL, 0, max98090_micinput_event,
@@ -1521,19 +1548,19 @@ static const int lrclk_rates[] = {
};
static const int user_pclk_rates[] = {
- 13000000, 13000000
+ 13000000, 13000000, 19200000, 19200000,
};
static const int user_lrclk_rates[] = {
- 44100, 48000
+ 44100, 48000, 44100, 48000,
};
static const unsigned long long ni_value[] = {
- 3528, 768
+ 3528, 768, 441, 8
};
static const unsigned long long mi_value[] = {
- 8125, 1625
+ 8125, 1625, 1500, 25
};
static void max98090_configure_bclk(struct snd_soc_codec *codec)
@@ -1650,6 +1677,7 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
M98090_REG_CLOCK_RATIO_NI_LSB, 0x00);
snd_soc_update_bits(codec, M98090_REG_CLOCK_MODE,
M98090_USE_M1_MASK, 0);
+ max98090->master = false;
break;
case SND_SOC_DAIFMT_CBM_CFM:
/* Set to master mode */
@@ -1666,6 +1694,7 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
regval |= M98090_MAS_MASK |
M98090_BSEL_32;
}
+ max98090->master = true;
break;
case SND_SOC_DAIFMT_CBS_CFM:
case SND_SOC_DAIFMT_CBM_CFS:
@@ -1769,29 +1798,35 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec,
switch (level) {
case SND_SOC_BIAS_ON:
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ /*
+ * SND_SOC_BIAS_PREPARE is called while preparing for a
+ * transition to ON or away from ON. If current bias_level
+ * is SND_SOC_BIAS_ON, then it is preparing for a transition
+ * away from ON. Disable the clock in that case, otherwise
+ * enable it.
+ */
+ if (!IS_ERR(max98090->mclk)) {
+ if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
+ clk_disable_unprepare(max98090->mclk);
+ else
+ clk_prepare_enable(max98090->mclk);
+ }
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
ret = regcache_sync(max98090->regmap);
-
if (ret != 0) {
dev_err(codec->dev,
"Failed to sync cache: %d\n", ret);
return ret;
}
}
-
- if (max98090->jack_state == M98090_JACK_STATE_HEADSET) {
- /*
- * Set to normal bias level.
- */
- snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE,
- M98090_MBVSEL_MASK, M98090_MBVSEL_2V8);
- }
break;
- case SND_SOC_BIAS_PREPARE:
- break;
-
- case SND_SOC_BIAS_STANDBY:
case SND_SOC_BIAS_OFF:
/* Set internal pull-up to lowest power mode */
snd_soc_update_bits(codec, M98090_REG_JACK_DETECT,
@@ -1849,7 +1884,8 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- max98090_configure_bclk(codec);
+ if (max98090->master)
+ max98090_configure_bclk(codec);
cdata->rate = max98090->lrclk;
@@ -1907,6 +1943,11 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
if (freq == max98090->sysclk)
return 0;
+ if (!IS_ERR(max98090->mclk)) {
+ freq = clk_round_rate(max98090->mclk, freq);
+ clk_set_rate(max98090->mclk, freq);
+ }
+
/* Setup clocks for slave mode, and using the PLL
* PSCLK = 0x01 (when master clk is 10MHz to 20MHz)
* 0x02 (when master clk is 20MHz to 40MHz)..
@@ -1928,8 +1969,6 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
max98090->sysclk = freq;
- max98090_configure_bclk(codec);
-
return 0;
}
@@ -2193,15 +2232,11 @@ static int max98090_probe(struct snd_soc_codec *codec)
dev_dbg(codec->dev, "max98090_probe\n");
- max98090->codec = codec;
-
- codec->control_data = max98090->regmap;
+ max98090->mclk = devm_clk_get(codec->dev, "mclk");
+ if (PTR_ERR(max98090->mclk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
+ max98090->codec = codec;
/* Reset the codec, the DSP core, and disable all interrupts */
max98090_reset(max98090);
@@ -2209,6 +2244,7 @@ static int max98090_probe(struct snd_soc_codec *codec)
/* Initialize private data */
max98090->sysclk = (unsigned)-1;
+ max98090->master = false;
cdata = &max98090->dai[0];
cdata->rate = (unsigned)-1;
@@ -2278,6 +2314,9 @@ static int max98090_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, M98090_REG_BIAS_CONTROL,
M98090_VCM_MODE_MASK);
+ snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE,
+ M98090_MBVSEL_MASK, M98090_MBVSEL_2V8);
+
max98090_handle_pdata(codec);
max98090_add_widgets(codec);
@@ -2314,9 +2353,11 @@ static const struct regmap_config max98090_regmap = {
};
static int max98090_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *i2c_id)
{
struct max98090_priv *max98090;
+ const struct acpi_device_id *acpi_id;
+ kernel_ulong_t driver_data = 0;
int ret;
pr_debug("max98090_i2c_probe\n");
@@ -2326,9 +2367,20 @@ static int max98090_i2c_probe(struct i2c_client *i2c,
if (max98090 == NULL)
return -ENOMEM;
- max98090->devtype = id->driver_data;
+ if (ACPI_HANDLE(&i2c->dev)) {
+ acpi_id = acpi_match_device(i2c->dev.driver->acpi_match_table,
+ &i2c->dev);
+ if (!acpi_id) {
+ dev_err(&i2c->dev, "No driver data\n");
+ return -EINVAL;
+ }
+ driver_data = acpi_id->driver_data;
+ } else if (i2c_id) {
+ driver_data = i2c_id->driver_data;
+ }
+
+ max98090->devtype = driver_data;
i2c_set_clientdata(i2c, max98090);
- max98090->control_data = i2c;
max98090->pdata = i2c->dev.platform_data;
max98090->irq = i2c->irq;
@@ -2359,6 +2411,8 @@ static int max98090_runtime_resume(struct device *dev)
regcache_cache_only(max98090->regmap, false);
+ max98090_reset(max98090);
+
regcache_sync(max98090->regmap);
return 0;
@@ -2374,9 +2428,34 @@ static int max98090_runtime_suspend(struct device *dev)
}
#endif
+#ifdef CONFIG_PM
+static int max98090_resume(struct device *dev)
+{
+ struct max98090_priv *max98090 = dev_get_drvdata(dev);
+ unsigned int status;
+
+ regcache_mark_dirty(max98090->regmap);
+
+ max98090_reset(max98090);
+
+ /* clear IRQ status */
+ regmap_read(max98090->regmap, M98090_REG_DEVICE_STATUS, &status);
+
+ regcache_sync(max98090->regmap);
+
+ return 0;
+}
+
+static int max98090_suspend(struct device *dev)
+{
+ return 0;
+}
+#endif
+
static const struct dev_pm_ops max98090_pm = {
SET_RUNTIME_PM_OPS(max98090_runtime_suspend,
max98090_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(max98090_suspend, max98090_resume)
};
static const struct i2c_device_id max98090_i2c_id[] = {
@@ -2385,11 +2464,27 @@ static const struct i2c_device_id max98090_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, max98090_i2c_id);
+static const struct of_device_id max98090_of_match[] = {
+ { .compatible = "maxim,max98090", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max98090_of_match);
+
+#ifdef CONFIG_ACPI
+static struct acpi_device_id max98090_acpi_match[] = {
+ { "193C9890", MAX98090 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, max98090_acpi_match);
+#endif
+
static struct i2c_driver max98090_i2c_driver = {
.driver = {
.name = "max98090",
.owner = THIS_MODULE,
.pm = &max98090_pm,
+ .of_match_table = of_match_ptr(max98090_of_match),
+ .acpi_match_table = ACPI_PTR(max98090_acpi_match),
},
.probe = max98090_i2c_probe,
.remove = max98090_i2c_remove,
diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h
index 7e103f24905..cf1b6062ba8 100644
--- a/sound/soc/codecs/max98090.h
+++ b/sound/soc/codecs/max98090.h
@@ -1523,8 +1523,8 @@ struct max98090_priv {
struct regmap *regmap;
struct snd_soc_codec *codec;
enum max98090_type devtype;
- void *control_data;
struct max98090_pdata *pdata;
+ struct clk *mclk;
unsigned int sysclk;
unsigned int bclk;
unsigned int lrclk;
@@ -1541,6 +1541,7 @@ struct max98090_priv {
unsigned int pa2en;
unsigned int extmic_mux;
unsigned int sidetone;
+ bool master;
};
int max98090_mic_detect(struct snd_soc_codec *codec,
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 3ba1170ebb5..89ec0042488 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -15,6 +15,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/clk.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -42,6 +43,7 @@ struct max98095_priv {
struct regmap *regmap;
enum max98095_type devtype;
struct max98095_pdata *pdata;
+ struct clk *mclk;
unsigned int sysclk;
struct max98095_cdata dai[3];
const char **eq_texts;
@@ -560,25 +562,27 @@ static void m98095_biquad_band(struct snd_soc_codec *codec, unsigned int dai,
}
static const char * const max98095_fltr_mode[] = { "Voice", "Music" };
-static const struct soc_enum max98095_dai1_filter_mode_enum[] = {
- SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 7, 2, max98095_fltr_mode),
-};
-static const struct soc_enum max98095_dai2_filter_mode_enum[] = {
- SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 7, 2, max98095_fltr_mode),
-};
+static SOC_ENUM_SINGLE_DECL(max98095_dai1_filter_mode_enum,
+ M98095_02E_DAI1_FILTERS, 7,
+ max98095_fltr_mode);
+static SOC_ENUM_SINGLE_DECL(max98095_dai2_filter_mode_enum,
+ M98095_038_DAI2_FILTERS, 7,
+ max98095_fltr_mode);
static const char * const max98095_extmic_text[] = { "None", "MIC1", "MIC2" };
-static const struct soc_enum max98095_extmic_enum =
- SOC_ENUM_SINGLE(M98095_087_CFG_MIC, 0, 3, max98095_extmic_text);
+static SOC_ENUM_SINGLE_DECL(max98095_extmic_enum,
+ M98095_087_CFG_MIC, 0,
+ max98095_extmic_text);
static const struct snd_kcontrol_new max98095_extmic_mux =
SOC_DAPM_ENUM("External MIC Mux", max98095_extmic_enum);
static const char * const max98095_linein_text[] = { "INA", "INB" };
-static const struct soc_enum max98095_linein_enum =
- SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 6, 2, max98095_linein_text);
+static SOC_ENUM_SINGLE_DECL(max98095_linein_enum,
+ M98095_086_CFG_LINE, 6,
+ max98095_linein_text);
static const struct snd_kcontrol_new max98095_linein_mux =
SOC_DAPM_ENUM("Linein Input Mux", max98095_linein_enum);
@@ -586,29 +590,31 @@ static const struct snd_kcontrol_new max98095_linein_mux =
static const char * const max98095_line_mode_text[] = {
"Stereo", "Differential"};
-static const struct soc_enum max98095_linein_mode_enum =
- SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 7, 2, max98095_line_mode_text);
+static SOC_ENUM_SINGLE_DECL(max98095_linein_mode_enum,
+ M98095_086_CFG_LINE, 7,
+ max98095_line_mode_text);
-static const struct soc_enum max98095_lineout_mode_enum =
- SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 4, 2, max98095_line_mode_text);
+static SOC_ENUM_SINGLE_DECL(max98095_lineout_mode_enum,
+ M98095_086_CFG_LINE, 4,
+ max98095_line_mode_text);
static const char * const max98095_dai_fltr[] = {
"Off", "Elliptical-HPF-16k", "Butterworth-HPF-16k",
"Elliptical-HPF-8k", "Butterworth-HPF-8k", "Butterworth-HPF-Fs/240"};
-static const struct soc_enum max98095_dai1_dac_filter_enum[] = {
- SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 0, 6, max98095_dai_fltr),
-};
-static const struct soc_enum max98095_dai2_dac_filter_enum[] = {
- SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 0, 6, max98095_dai_fltr),
-};
-static const struct soc_enum max98095_dai3_dac_filter_enum[] = {
- SOC_ENUM_SINGLE(M98095_042_DAI3_FILTERS, 0, 6, max98095_dai_fltr),
-};
+static SOC_ENUM_SINGLE_DECL(max98095_dai1_dac_filter_enum,
+ M98095_02E_DAI1_FILTERS, 0,
+ max98095_dai_fltr);
+static SOC_ENUM_SINGLE_DECL(max98095_dai2_dac_filter_enum,
+ M98095_038_DAI2_FILTERS, 0,
+ max98095_dai_fltr);
+static SOC_ENUM_SINGLE_DECL(max98095_dai3_dac_filter_enum,
+ M98095_042_DAI3_FILTERS, 0,
+ max98095_dai_fltr);
static int max98095_mic1pre_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
unsigned int sel = ucontrol->value.integer.value[0];
@@ -622,7 +628,7 @@ static int max98095_mic1pre_set(struct snd_kcontrol *kcontrol,
static int max98095_mic1pre_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = max98095->mic1pre;
@@ -632,7 +638,7 @@ static int max98095_mic1pre_get(struct snd_kcontrol *kcontrol,
static int max98095_mic2pre_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
unsigned int sel = ucontrol->value.integer.value[0];
@@ -646,7 +652,7 @@ static int max98095_mic2pre_set(struct snd_kcontrol *kcontrol,
static int max98095_mic2pre_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = max98095->mic2pre;
@@ -1391,6 +1397,11 @@ static int max98095_dai_set_sysclk(struct snd_soc_dai *dai,
if (freq == max98095->sysclk)
return 0;
+ if (!IS_ERR(max98095->mclk)) {
+ freq = clk_round_rate(max98095->mclk, freq);
+ clk_set_rate(max98095->mclk, freq);
+ }
+
/* Setup clocks for slave mode, and using the PLL
* PSCLK = 0x01 (when master clk is 10MHz to 20MHz)
* 0x02 (when master clk is 20MHz to 40MHz)..
@@ -1630,6 +1641,19 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec,
break;
case SND_SOC_BIAS_PREPARE:
+ /*
+ * SND_SOC_BIAS_PREPARE is called while preparing for a
+ * transition to ON or away from ON. If current bias_level
+ * is SND_SOC_BIAS_ON, then it is preparing for a transition
+ * away from ON. Disable the clock in that case, otherwise
+ * enable it.
+ */
+ if (!IS_ERR(max98095->mclk)) {
+ if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
+ clk_disable_unprepare(max98095->mclk);
+ else
+ clk_prepare_enable(max98095->mclk);
+ }
break;
case SND_SOC_BIAS_STANDBY:
@@ -1733,7 +1757,7 @@ static int max98095_get_eq_channel(const char *name)
static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
struct max98095_pdata *pdata = max98095->pdata;
int channel = max98095_get_eq_channel(kcontrol->id.name);
@@ -1797,7 +1821,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol,
static int max98095_get_eq_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
int channel = max98095_get_eq_channel(kcontrol->id.name);
struct max98095_cdata *cdata;
@@ -1861,7 +1885,7 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec)
/* Now point the soc_enum to .texts array items */
max98095->eq_enum.texts = max98095->eq_texts;
- max98095->eq_enum.max = max98095->eq_textcnt;
+ max98095->eq_enum.items = max98095->eq_textcnt;
ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
@@ -1887,7 +1911,7 @@ static int max98095_get_bq_channel(struct snd_soc_codec *codec,
static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
struct max98095_pdata *pdata = max98095->pdata;
int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
@@ -1948,7 +1972,7 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
static int max98095_get_bq_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
struct max98095_cdata *cdata;
@@ -2016,7 +2040,7 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec)
/* Now point the soc_enum to .texts array items */
max98095->bq_enum.texts = max98095->bq_texts;
- max98095->bq_enum.max = max98095->bq_textcnt;
+ max98095->bq_enum.items = max98095->bq_textcnt;
ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
@@ -2234,11 +2258,9 @@ static int max98095_probe(struct snd_soc_codec *codec)
struct i2c_client *client;
int ret = 0;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
+ max98095->mclk = devm_clk_get(codec->dev, "mclk");
+ if (PTR_ERR(max98095->mclk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
/* reset the codec, the DSP core, and disable all interrupts */
max98095_reset(codec);
@@ -2401,10 +2423,17 @@ static const struct i2c_device_id max98095_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, max98095_i2c_id);
+static const struct of_device_id max98095_of_match[] = {
+ { .compatible = "maxim,max98095", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max98095_of_match);
+
static struct i2c_driver max98095_i2c_driver = {
.driver = {
.name = "max98095",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(max98095_of_match),
},
.probe = max98095_i2c_probe,
.remove = max98095_i2c_remove,
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c
index 82757ebf030..4fdf5aaa236 100644
--- a/sound/soc/codecs/max9850.c
+++ b/sound/soc/codecs/max9850.c
@@ -312,14 +312,6 @@ static int max9850_resume(struct snd_soc_codec *codec)
static int max9850_probe(struct snd_soc_codec *codec)
{
- int ret;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
/* enable zero-detect */
snd_soc_update_bits(codec, MAX9850_GENERAL_PURPOSE, 1, 1);
/* enable slew-rate control */
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index 582c2bbd42c..9965277b595 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -22,6 +22,7 @@
*/
#include <linux/module.h>
#include <linux/device.h>
+#include <linux/of.h>
#include <linux/mfd/mc13xxx.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -106,8 +107,7 @@ static int mc13783_pcm_hw_params_dac(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
unsigned int rate = params_rate(params);
int i;
@@ -126,8 +126,7 @@ static int mc13783_pcm_hw_params_codec(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
unsigned int rate = params_rate(params);
unsigned int val;
@@ -408,21 +407,19 @@ static const char * const adcl_enum_text[] = {
"MC1L", "RXINL",
};
-static const struct soc_enum adcl_enum =
- SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcl_enum_text), adcl_enum_text);
+static SOC_ENUM_SINGLE_VIRT_DECL(adcl_enum, adcl_enum_text);
static const struct snd_kcontrol_new left_input_mux =
- SOC_DAPM_ENUM_VIRT("Route", adcl_enum);
+ SOC_DAPM_ENUM("Route", adcl_enum);
static const char * const adcr_enum_text[] = {
"MC1R", "MC2", "RXINR", "TXIN",
};
-static const struct soc_enum adcr_enum =
- SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcr_enum_text), adcr_enum_text);
+static SOC_ENUM_SINGLE_VIRT_DECL(adcr_enum, adcr_enum_text);
static const struct snd_kcontrol_new right_input_mux =
- SOC_DAPM_ENUM_VIRT("Route", adcr_enum);
+ SOC_DAPM_ENUM("Route", adcr_enum);
static const struct snd_kcontrol_new samp_ctl =
SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 3, 1, 0);
@@ -430,8 +427,8 @@ static const struct snd_kcontrol_new samp_ctl =
static const char * const speaker_amp_source_text[] = {
"CODEC", "Right"
};
-static const SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4,
- speaker_amp_source_text);
+static SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4,
+ speaker_amp_source_text);
static const struct snd_kcontrol_new speaker_amp_source_mux =
SOC_DAPM_ENUM("Speaker Amp Source MUX", speaker_amp_source);
@@ -439,8 +436,8 @@ static const char * const headset_amp_source_text[] = {
"CODEC", "Mixer"
};
-static const SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11,
- headset_amp_source_text);
+static SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11,
+ headset_amp_source_text);
static const struct snd_kcontrol_new headset_amp_source_mux =
SOC_DAPM_ENUM("Headset Amp Source MUX", headset_amp_source);
@@ -482,9 +479,9 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = {
SND_SOC_DAPM_SWITCH("MC2 Amp", MC13783_AUDIO_TX, 9, 0, &mc2_amp_ctl),
SND_SOC_DAPM_SWITCH("TXIN Amp", MC13783_AUDIO_TX, 11, 0, &atx_amp_ctl),
- SND_SOC_DAPM_VIRT_MUX("PGA Left Input Mux", SND_SOC_NOPM, 0, 0,
+ SND_SOC_DAPM_MUX("PGA Left Input Mux", SND_SOC_NOPM, 0, 0,
&left_input_mux),
- SND_SOC_DAPM_VIRT_MUX("PGA Right Input Mux", SND_SOC_NOPM, 0, 0,
+ SND_SOC_DAPM_MUX("PGA Right Input Mux", SND_SOC_NOPM, 0, 0,
&right_input_mux),
SND_SOC_DAPM_MUX("Speaker Amp Source MUX", SND_SOC_NOPM, 0, 0,
@@ -580,9 +577,9 @@ static struct snd_soc_dapm_route mc13783_routes[] = {
static const char * const mc13783_3d_mixer[] = {"Stereo", "Phase Mix",
"Mono", "Mono Mix"};
-static const struct soc_enum mc13783_enum_3d_mixer =
- SOC_ENUM_SINGLE(MC13783_AUDIO_RX1, 16, ARRAY_SIZE(mc13783_3d_mixer),
- mc13783_3d_mixer);
+static SOC_ENUM_SINGLE_DECL(mc13783_enum_3d_mixer,
+ MC13783_AUDIO_RX1, 16,
+ mc13783_3d_mixer);
static struct snd_kcontrol_new mc13783_control_list[] = {
SOC_SINGLE("Loudspeaker enable", MC13783_AUDIO_RX0, 5, 1, 0),
@@ -612,14 +609,6 @@ static struct snd_kcontrol_new mc13783_control_list[] = {
static int mc13783_probe(struct snd_soc_codec *codec)
{
struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- codec->control_data = dev_get_regmap(codec->dev->parent, NULL);
- ret = snd_soc_codec_set_cache_io(codec, 8, 24, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
/* these are the reset values */
mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_RX0, 0x25893);
@@ -739,9 +728,15 @@ static struct snd_soc_dai_driver mc13783_dai_sync[] = {
}
};
+static struct regmap *mc13783_get_regmap(struct device *dev)
+{
+ return dev_get_regmap(dev->parent, NULL);
+}
+
static struct snd_soc_codec_driver soc_codec_dev_mc13783 = {
.probe = mc13783_probe,
.remove = mc13783_remove,
+ .get_regmap = mc13783_get_regmap,
.controls = mc13783_control_list,
.num_controls = ARRAY_SIZE(mc13783_control_list),
.dapm_widgets = mc13783_dapm_widgets,
@@ -754,6 +749,7 @@ static int __init mc13783_codec_probe(struct platform_device *pdev)
{
struct mc13783_priv *priv;
struct mc13xxx_codec_platform_data *pdata = pdev->dev.platform_data;
+ struct device_node *np;
int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -764,7 +760,17 @@ static int __init mc13783_codec_probe(struct platform_device *pdev)
priv->adc_ssi_port = pdata->adc_ssi_port;
priv->dac_ssi_port = pdata->dac_ssi_port;
} else {
- return -ENOSYS;
+ np = of_get_child_by_name(pdev->dev.parent->of_node, "codec");
+ if (!np)
+ return -ENOSYS;
+
+ ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port);
+ if (ret)
+ return ret;
}
dev_set_drvdata(&pdev->dev, priv);
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
index 185fa3bc305..e661e8420e3 100644
--- a/sound/soc/codecs/ml26124.c
+++ b/sound/soc/codecs/ml26124.c
@@ -73,11 +73,11 @@ static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0);
static const char * const ml26124_companding[] = {"16bit PCM", "u-law",
"A-law"};
-static const struct soc_enum ml26124_adc_companding_enum
- = SOC_ENUM_SINGLE(ML26124_SAI_TRANS_CTL, 6, 3, ml26124_companding);
+static SOC_ENUM_SINGLE_DECL(ml26124_adc_companding_enum,
+ ML26124_SAI_TRANS_CTL, 6, ml26124_companding);
-static const struct soc_enum ml26124_dac_companding_enum
- = SOC_ENUM_SINGLE(ML26124_SAI_RCV_CTL, 6, 3, ml26124_companding);
+static SOC_ENUM_SINGLE_DECL(ml26124_dac_companding_enum,
+ ML26124_SAI_RCV_CTL, 6, ml26124_companding);
static const struct snd_kcontrol_new ml26124_snd_controls[] = {
SOC_SINGLE_TLV("Capture Digital Volume", ML26124_RECORD_DIG_VOL, 0,
@@ -136,8 +136,8 @@ static const struct snd_kcontrol_new ml26124_output_mixer_controls[] = {
static const char * const ml26124_input_select[] = {"Analog MIC SingleEnded in",
"Digital MIC in", "Analog MIC Differential in"};
-static const struct soc_enum ml26124_insel_enum =
- SOC_ENUM_SINGLE(ML26124_MIC_IF_CTL, 0, 3, ml26124_input_select);
+static SOC_ENUM_SINGLE_DECL(ml26124_insel_enum,
+ ML26124_MIC_IF_CTL, 0, ml26124_input_select);
static const struct snd_kcontrol_new ml26124_input_mux_controls =
SOC_DAPM_ENUM("Input Select", ml26124_insel_enum);
@@ -586,16 +586,6 @@ static int ml26124_resume(struct snd_soc_codec *codec)
static int ml26124_probe(struct snd_soc_codec *codec)
{
- int ret;
- struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
- codec->control_data = priv->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
/* Software Reset */
snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 1);
snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 0);
diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c
index 73f9c3630e2..a722a023c26 100644
--- a/sound/soc/codecs/pcm1681.c
+++ b/sound/soc/codecs/pcm1681.c
@@ -115,7 +115,7 @@ static int pcm1681_set_deemph(struct snd_soc_codec *codec)
static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = priv->deemph;
@@ -126,7 +126,7 @@ static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol,
static int pcm1681_put_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
priv->deemph = ucontrol->value.enumerated.item[0];
@@ -172,16 +172,21 @@ static int pcm1681_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = dai->codec;
struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
int val = 0, ret;
- int pcm_format = params_format(params);
priv->rate = params_rate(params);
switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_RIGHT_J:
- if (pcm_format == SNDRV_PCM_FORMAT_S24_LE)
- val = 0x00;
- else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE)
- val = 0x03;
+ switch (params_width(params)) {
+ case 24:
+ val = 0;
+ break;
+ case 16:
+ val = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
case SND_SOC_DAIFMT_I2S:
val = 0x04;
diff --git a/sound/soc/codecs/pcm1792a.c b/sound/soc/codecs/pcm1792a.c
index 7146653a8e1..3a80ba4452d 100644
--- a/sound/soc/codecs/pcm1792a.c
+++ b/sound/soc/codecs/pcm1792a.c
@@ -107,24 +107,35 @@ static int pcm1792a_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = dai->codec;
struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
int val = 0, ret;
- int pcm_format = params_format(params);
priv->rate = params_rate(params);
switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_RIGHT_J:
- if (pcm_format == SNDRV_PCM_FORMAT_S24_LE ||
- pcm_format == SNDRV_PCM_FORMAT_S32_LE)
- val = 0x02;
- else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE)
- val = 0x00;
+ switch (params_width(params)) {
+ case 24:
+ case 32:
+ val = 2;
+ break;
+ case 16:
+ val = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
case SND_SOC_DAIFMT_I2S:
- if (pcm_format == SNDRV_PCM_FORMAT_S24_LE ||
- pcm_format == SNDRV_PCM_FORMAT_S32_LE)
- val = 0x05;
- else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE)
- val = 0x04;
+ switch (params_width(params)) {
+ case 24:
+ case 32:
+ val = 5;
+ break;
+ case 16:
+ val = 4;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
default:
dev_err(codec->dev, "Invalid DAI format\n");
diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c
new file mode 100644
index 00000000000..4d62230bd37
--- /dev/null
+++ b/sound/soc/codecs/pcm512x-i2c.c
@@ -0,0 +1,71 @@
+/*
+ * Driver for the PCM512x CODECs
+ *
+ * Author: Mark Brown <broonie@linaro.org>
+ * Copyright 2014 Linaro Ltd
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+
+#include "pcm512x.h"
+
+static int pcm512x_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return pcm512x_probe(&i2c->dev, regmap);
+}
+
+static int pcm512x_i2c_remove(struct i2c_client *i2c)
+{
+ pcm512x_remove(&i2c->dev);
+ return 0;
+}
+
+static const struct i2c_device_id pcm512x_i2c_id[] = {
+ { "pcm5121", },
+ { "pcm5122", },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id);
+
+static const struct of_device_id pcm512x_of_match[] = {
+ { .compatible = "ti,pcm5121", },
+ { .compatible = "ti,pcm5122", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pcm512x_of_match);
+
+static struct i2c_driver pcm512x_i2c_driver = {
+ .probe = pcm512x_i2c_probe,
+ .remove = pcm512x_i2c_remove,
+ .id_table = pcm512x_i2c_id,
+ .driver = {
+ .name = "pcm512x",
+ .owner = THIS_MODULE,
+ .of_match_table = pcm512x_of_match,
+ .pm = &pcm512x_pm_ops,
+ },
+};
+
+module_i2c_driver(pcm512x_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC PCM512x codec driver - I2C");
+MODULE_AUTHOR("Mark Brown <broonie@linaro.org>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm512x-spi.c b/sound/soc/codecs/pcm512x-spi.c
new file mode 100644
index 00000000000..f297058c003
--- /dev/null
+++ b/sound/soc/codecs/pcm512x-spi.c
@@ -0,0 +1,69 @@
+/*
+ * Driver for the PCM512x CODECs
+ *
+ * Author: Mark Brown <broonie@linaro.org>
+ * Copyright 2014 Linaro Ltd
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#include "pcm512x.h"
+
+static int pcm512x_spi_probe(struct spi_device *spi)
+{
+ struct regmap *regmap;
+ int ret;
+
+ regmap = devm_regmap_init_spi(spi, &pcm512x_regmap);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ return ret;
+ }
+
+ return pcm512x_probe(&spi->dev, regmap);
+}
+
+static int pcm512x_spi_remove(struct spi_device *spi)
+{
+ pcm512x_remove(&spi->dev);
+ return 0;
+}
+
+static const struct spi_device_id pcm512x_spi_id[] = {
+ { "pcm5121", },
+ { "pcm5122", },
+ { },
+};
+MODULE_DEVICE_TABLE(spi, pcm512x_spi_id);
+
+static const struct of_device_id pcm512x_of_match[] = {
+ { .compatible = "ti,pcm5121", },
+ { .compatible = "ti,pcm5122", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pcm512x_of_match);
+
+static struct spi_driver pcm512x_spi_driver = {
+ .probe = pcm512x_spi_probe,
+ .remove = pcm512x_spi_remove,
+ .id_table = pcm512x_spi_id,
+ .driver = {
+ .name = "pcm512x",
+ .owner = THIS_MODULE,
+ .of_match_table = pcm512x_of_match,
+ .pm = &pcm512x_pm_ops,
+ },
+};
+
+module_spi_driver(pcm512x_spi_driver);
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
new file mode 100644
index 00000000000..163ec3855fd
--- /dev/null
+++ b/sound/soc/codecs/pcm512x.c
@@ -0,0 +1,591 @@
+/*
+ * Driver for the PCM512x CODECs
+ *
+ * Author: Mark Brown <broonie@linaro.org>
+ * Copyright 2014 Linaro Ltd
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+
+#include "pcm512x.h"
+
+#define PCM512x_NUM_SUPPLIES 3
+static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = {
+ "AVDD",
+ "DVDD",
+ "CPVDD",
+};
+
+struct pcm512x_priv {
+ struct regmap *regmap;
+ struct clk *sclk;
+ struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES];
+ struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES];
+};
+
+/*
+ * We can't use the same notifier block for more than one supply and
+ * there's no way I can see to get from a callback to the caller
+ * except container_of().
+ */
+#define PCM512x_REGULATOR_EVENT(n) \
+static int pcm512x_regulator_event_##n(struct notifier_block *nb, \
+ unsigned long event, void *data) \
+{ \
+ struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \
+ supply_nb[n]); \
+ if (event & REGULATOR_EVENT_DISABLE) { \
+ regcache_mark_dirty(pcm512x->regmap); \
+ regcache_cache_only(pcm512x->regmap, true); \
+ } \
+ return 0; \
+}
+
+PCM512x_REGULATOR_EVENT(0)
+PCM512x_REGULATOR_EVENT(1)
+PCM512x_REGULATOR_EVENT(2)
+
+static const struct reg_default pcm512x_reg_defaults[] = {
+ { PCM512x_RESET, 0x00 },
+ { PCM512x_POWER, 0x00 },
+ { PCM512x_MUTE, 0x00 },
+ { PCM512x_DSP, 0x00 },
+ { PCM512x_PLL_REF, 0x00 },
+ { PCM512x_DAC_ROUTING, 0x11 },
+ { PCM512x_DSP_PROGRAM, 0x01 },
+ { PCM512x_CLKDET, 0x00 },
+ { PCM512x_AUTO_MUTE, 0x00 },
+ { PCM512x_ERROR_DETECT, 0x00 },
+ { PCM512x_DIGITAL_VOLUME_1, 0x00 },
+ { PCM512x_DIGITAL_VOLUME_2, 0x30 },
+ { PCM512x_DIGITAL_VOLUME_3, 0x30 },
+ { PCM512x_DIGITAL_MUTE_1, 0x22 },
+ { PCM512x_DIGITAL_MUTE_2, 0x00 },
+ { PCM512x_DIGITAL_MUTE_3, 0x07 },
+ { PCM512x_OUTPUT_AMPLITUDE, 0x00 },
+ { PCM512x_ANALOG_GAIN_CTRL, 0x00 },
+ { PCM512x_UNDERVOLTAGE_PROT, 0x00 },
+ { PCM512x_ANALOG_MUTE_CTRL, 0x00 },
+ { PCM512x_ANALOG_GAIN_BOOST, 0x00 },
+ { PCM512x_VCOM_CTRL_1, 0x00 },
+ { PCM512x_VCOM_CTRL_2, 0x01 },
+};
+
+static bool pcm512x_readable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case PCM512x_RESET:
+ case PCM512x_POWER:
+ case PCM512x_MUTE:
+ case PCM512x_PLL_EN:
+ case PCM512x_SPI_MISO_FUNCTION:
+ case PCM512x_DSP:
+ case PCM512x_GPIO_EN:
+ case PCM512x_BCLK_LRCLK_CFG:
+ case PCM512x_DSP_GPIO_INPUT:
+ case PCM512x_MASTER_MODE:
+ case PCM512x_PLL_REF:
+ case PCM512x_PLL_COEFF_0:
+ case PCM512x_PLL_COEFF_1:
+ case PCM512x_PLL_COEFF_2:
+ case PCM512x_PLL_COEFF_3:
+ case PCM512x_PLL_COEFF_4:
+ case PCM512x_DSP_CLKDIV:
+ case PCM512x_DAC_CLKDIV:
+ case PCM512x_NCP_CLKDIV:
+ case PCM512x_OSR_CLKDIV:
+ case PCM512x_MASTER_CLKDIV_1:
+ case PCM512x_MASTER_CLKDIV_2:
+ case PCM512x_FS_SPEED_MODE:
+ case PCM512x_IDAC_1:
+ case PCM512x_IDAC_2:
+ case PCM512x_ERROR_DETECT:
+ case PCM512x_I2S_1:
+ case PCM512x_I2S_2:
+ case PCM512x_DAC_ROUTING:
+ case PCM512x_DSP_PROGRAM:
+ case PCM512x_CLKDET:
+ case PCM512x_AUTO_MUTE:
+ case PCM512x_DIGITAL_VOLUME_1:
+ case PCM512x_DIGITAL_VOLUME_2:
+ case PCM512x_DIGITAL_VOLUME_3:
+ case PCM512x_DIGITAL_MUTE_1:
+ case PCM512x_DIGITAL_MUTE_2:
+ case PCM512x_DIGITAL_MUTE_3:
+ case PCM512x_GPIO_OUTPUT_1:
+ case PCM512x_GPIO_OUTPUT_2:
+ case PCM512x_GPIO_OUTPUT_3:
+ case PCM512x_GPIO_OUTPUT_4:
+ case PCM512x_GPIO_OUTPUT_5:
+ case PCM512x_GPIO_OUTPUT_6:
+ case PCM512x_GPIO_CONTROL_1:
+ case PCM512x_GPIO_CONTROL_2:
+ case PCM512x_OVERFLOW:
+ case PCM512x_RATE_DET_1:
+ case PCM512x_RATE_DET_2:
+ case PCM512x_RATE_DET_3:
+ case PCM512x_RATE_DET_4:
+ case PCM512x_ANALOG_MUTE_DET:
+ case PCM512x_GPIN:
+ case PCM512x_DIGITAL_MUTE_DET:
+ case PCM512x_OUTPUT_AMPLITUDE:
+ case PCM512x_ANALOG_GAIN_CTRL:
+ case PCM512x_UNDERVOLTAGE_PROT:
+ case PCM512x_ANALOG_MUTE_CTRL:
+ case PCM512x_ANALOG_GAIN_BOOST:
+ case PCM512x_VCOM_CTRL_1:
+ case PCM512x_VCOM_CTRL_2:
+ case PCM512x_CRAM_CTRL:
+ return true;
+ default:
+ /* There are 256 raw register addresses */
+ return reg < 0xff;
+ }
+}
+
+static bool pcm512x_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case PCM512x_PLL_EN:
+ case PCM512x_OVERFLOW:
+ case PCM512x_RATE_DET_1:
+ case PCM512x_RATE_DET_2:
+ case PCM512x_RATE_DET_3:
+ case PCM512x_RATE_DET_4:
+ case PCM512x_ANALOG_MUTE_DET:
+ case PCM512x_GPIN:
+ case PCM512x_DIGITAL_MUTE_DET:
+ case PCM512x_CRAM_CTRL:
+ return true;
+ default:
+ /* There are 256 raw register addresses */
+ return reg < 0xff;
+ }
+}
+
+static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1);
+static const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0);
+static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0);
+
+static const char * const pcm512x_dsp_program_texts[] = {
+ "FIR interpolation with de-emphasis",
+ "Low latency IIR with de-emphasis",
+ "Fixed process flow",
+ "High attenuation with de-emphasis",
+ "Ringing-less low latency FIR",
+};
+
+static const unsigned int pcm512x_dsp_program_values[] = {
+ 1,
+ 2,
+ 3,
+ 5,
+ 7,
+};
+
+static SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program,
+ PCM512x_DSP_PROGRAM, 0, 0x1f,
+ pcm512x_dsp_program_texts,
+ pcm512x_dsp_program_values);
+
+static const char * const pcm512x_clk_missing_text[] = {
+ "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s"
+};
+
+static const struct soc_enum pcm512x_clk_missing =
+ SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 8, pcm512x_clk_missing_text);
+
+static const char * const pcm512x_autom_text[] = {
+ "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s"
+};
+
+static const struct soc_enum pcm512x_autom_l =
+ SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 8,
+ pcm512x_autom_text);
+
+static const struct soc_enum pcm512x_autom_r =
+ SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 8,
+ pcm512x_autom_text);
+
+static const char * const pcm512x_ramp_rate_text[] = {
+ "1 sample/update", "2 samples/update", "4 samples/update",
+ "Immediate"
+};
+
+static const struct soc_enum pcm512x_vndf =
+ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4,
+ pcm512x_ramp_rate_text);
+
+static const struct soc_enum pcm512x_vnuf =
+ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4,
+ pcm512x_ramp_rate_text);
+
+static const struct soc_enum pcm512x_vedf =
+ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4,
+ pcm512x_ramp_rate_text);
+
+static const char * const pcm512x_ramp_step_text[] = {
+ "4dB/step", "2dB/step", "1dB/step", "0.5dB/step"
+};
+
+static const struct soc_enum pcm512x_vnds =
+ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4,
+ pcm512x_ramp_step_text);
+
+static const struct soc_enum pcm512x_vnus =
+ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4,
+ pcm512x_ramp_step_text);
+
+static const struct soc_enum pcm512x_veds =
+ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4,
+ pcm512x_ramp_step_text);
+
+static const struct snd_kcontrol_new pcm512x_controls[] = {
+SOC_DOUBLE_R_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2,
+ PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv),
+SOC_DOUBLE_TLV("Playback Volume", PCM512x_ANALOG_GAIN_CTRL,
+ PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv),
+SOC_DOUBLE_TLV("Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST,
+ PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv),
+SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT,
+ PCM512x_RQMR_SHIFT, 1, 1),
+
+SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
+SOC_ENUM("DSP Program", pcm512x_dsp_program),
+
+SOC_ENUM("Clock Missing Period", pcm512x_clk_missing),
+SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l),
+SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r),
+SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3,
+ PCM512x_ACTL_SHIFT, 1, 0),
+SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT,
+ PCM512x_AMLR_SHIFT, 1, 0),
+
+SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf),
+SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds),
+SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf),
+SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus),
+SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf),
+SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds),
+};
+
+static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = {
+SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
+
+SND_SOC_DAPM_OUTPUT("OUTL"),
+SND_SOC_DAPM_OUTPUT("OUTR"),
+};
+
+static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = {
+ { "DACL", NULL, "Playback" },
+ { "DACR", NULL, "Playback" },
+
+ { "OUTL", NULL, "DACL" },
+ { "OUTR", NULL, "DACR" },
+};
+
+static int pcm512x_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct pcm512x_priv *pcm512x = dev_get_drvdata(codec->dev);
+ int ret;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ case SND_SOC_BIAS_PREPARE:
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
+ PCM512x_RQST, 0);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to remove standby: %d\n",
+ ret);
+ return ret;
+ }
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
+ PCM512x_RQST, PCM512x_RQST);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request standby: %d\n",
+ ret);
+ return ret;
+ }
+ break;
+ }
+
+ codec->dapm.bias_level = level;
+
+ return 0;
+}
+
+static struct snd_soc_dai_driver pcm512x_dai = {
+ .name = "pcm512x-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE
+ },
+};
+
+static struct snd_soc_codec_driver pcm512x_codec_driver = {
+ .set_bias_level = pcm512x_set_bias_level,
+ .idle_bias_off = true,
+
+ .controls = pcm512x_controls,
+ .num_controls = ARRAY_SIZE(pcm512x_controls),
+ .dapm_widgets = pcm512x_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets),
+ .dapm_routes = pcm512x_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes),
+};
+
+static const struct regmap_range_cfg pcm512x_range = {
+ .name = "Pages", .range_min = PCM512x_VIRT_BASE,
+ .range_max = PCM512x_MAX_REGISTER,
+ .selector_reg = PCM512x_PAGE,
+ .selector_mask = 0xff,
+ .window_start = 0, .window_len = 0x100,
+};
+
+const struct regmap_config pcm512x_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .readable_reg = pcm512x_readable,
+ .volatile_reg = pcm512x_volatile,
+
+ .ranges = &pcm512x_range,
+ .num_ranges = 1,
+
+ .max_register = PCM512x_MAX_REGISTER,
+ .reg_defaults = pcm512x_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(pcm512x_regmap);
+
+int pcm512x_probe(struct device *dev, struct regmap *regmap)
+{
+ struct pcm512x_priv *pcm512x;
+ int i, ret;
+
+ pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL);
+ if (!pcm512x)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, pcm512x);
+ pcm512x->regmap = regmap;
+
+ for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++)
+ pcm512x->supplies[i].supply = pcm512x_supply_names[i];
+
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies),
+ pcm512x->supplies);
+ if (ret != 0) {
+ dev_err(dev, "Failed to get supplies: %d\n", ret);
+ return ret;
+ }
+
+ pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0;
+ pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1;
+ pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2;
+
+ for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) {
+ ret = regulator_register_notifier(pcm512x->supplies[i].consumer,
+ &pcm512x->supply_nb[i]);
+ if (ret != 0) {
+ dev_err(dev,
+ "Failed to register regulator notifier: %d\n",
+ ret);
+ }
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
+ pcm512x->supplies);
+ if (ret != 0) {
+ dev_err(dev, "Failed to enable supplies: %d\n", ret);
+ return ret;
+ }
+
+ /* Reset the device, verifying I/O in the process for I2C */
+ ret = regmap_write(regmap, PCM512x_RESET,
+ PCM512x_RSTM | PCM512x_RSTR);
+ if (ret != 0) {
+ dev_err(dev, "Failed to reset device: %d\n", ret);
+ goto err;
+ }
+
+ ret = regmap_write(regmap, PCM512x_RESET, 0);
+ if (ret != 0) {
+ dev_err(dev, "Failed to reset device: %d\n", ret);
+ goto err;
+ }
+
+ pcm512x->sclk = devm_clk_get(dev, NULL);
+ if (IS_ERR(pcm512x->sclk)) {
+ if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ dev_info(dev, "No SCLK, using BCLK: %ld\n",
+ PTR_ERR(pcm512x->sclk));
+
+ /* Disable reporting of missing SCLK as an error */
+ regmap_update_bits(regmap, PCM512x_ERROR_DETECT,
+ PCM512x_IDCH, PCM512x_IDCH);
+
+ /* Switch PLL input to BCLK */
+ regmap_update_bits(regmap, PCM512x_PLL_REF,
+ PCM512x_SREF, PCM512x_SREF);
+ } else {
+ ret = clk_prepare_enable(pcm512x->sclk);
+ if (ret != 0) {
+ dev_err(dev, "Failed to enable SCLK: %d\n", ret);
+ return ret;
+ }
+ }
+
+ /* Default to standby mode */
+ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
+ PCM512x_RQST, PCM512x_RQST);
+ if (ret != 0) {
+ dev_err(dev, "Failed to request standby: %d\n",
+ ret);
+ goto err_clk;
+ }
+
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ pm_runtime_idle(dev);
+
+ ret = snd_soc_register_codec(dev, &pcm512x_codec_driver,
+ &pcm512x_dai, 1);
+ if (ret != 0) {
+ dev_err(dev, "Failed to register CODEC: %d\n", ret);
+ goto err_pm;
+ }
+
+ return 0;
+
+err_pm:
+ pm_runtime_disable(dev);
+err_clk:
+ if (!IS_ERR(pcm512x->sclk))
+ clk_disable_unprepare(pcm512x->sclk);
+err:
+ regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
+ pcm512x->supplies);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcm512x_probe);
+
+void pcm512x_remove(struct device *dev)
+{
+ struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
+
+ snd_soc_unregister_codec(dev);
+ pm_runtime_disable(dev);
+ if (!IS_ERR(pcm512x->sclk))
+ clk_disable_unprepare(pcm512x->sclk);
+ regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
+ pcm512x->supplies);
+}
+EXPORT_SYMBOL_GPL(pcm512x_remove);
+
+#ifdef CONFIG_PM_RUNTIME
+static int pcm512x_suspend(struct device *dev)
+{
+ struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
+ PCM512x_RQPD, PCM512x_RQPD);
+ if (ret != 0) {
+ dev_err(dev, "Failed to request power down: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
+ pcm512x->supplies);
+ if (ret != 0) {
+ dev_err(dev, "Failed to disable supplies: %d\n", ret);
+ return ret;
+ }
+
+ if (!IS_ERR(pcm512x->sclk))
+ clk_disable_unprepare(pcm512x->sclk);
+
+ return 0;
+}
+
+static int pcm512x_resume(struct device *dev)
+{
+ struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
+ int ret;
+
+ if (!IS_ERR(pcm512x->sclk)) {
+ ret = clk_prepare_enable(pcm512x->sclk);
+ if (ret != 0) {
+ dev_err(dev, "Failed to enable SCLK: %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
+ pcm512x->supplies);
+ if (ret != 0) {
+ dev_err(dev, "Failed to enable supplies: %d\n", ret);
+ return ret;
+ }
+
+ regcache_cache_only(pcm512x->regmap, false);
+ ret = regcache_sync(pcm512x->regmap);
+ if (ret != 0) {
+ dev_err(dev, "Failed to sync cache: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
+ PCM512x_RQPD, 0);
+ if (ret != 0) {
+ dev_err(dev, "Failed to remove power down: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+#endif
+
+const struct dev_pm_ops pcm512x_pm_ops = {
+ SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL)
+};
+EXPORT_SYMBOL_GPL(pcm512x_pm_ops);
+
+MODULE_DESCRIPTION("ASoC PCM512x codec driver");
+MODULE_AUTHOR("Mark Brown <broonie@linaro.org>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h
new file mode 100644
index 00000000000..6ee76aaca09
--- /dev/null
+++ b/sound/soc/codecs/pcm512x.h
@@ -0,0 +1,171 @@
+/*
+ * Driver for the PCM512x CODECs
+ *
+ * Author: Mark Brown <broonie@linaro.org>
+ * Copyright 2014 Linaro Ltd
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#ifndef _SND_SOC_PCM512X
+#define _SND_SOC_PCM512X
+
+#include <linux/pm.h>
+#include <linux/regmap.h>
+
+#define PCM512x_VIRT_BASE 0x100
+#define PCM512x_PAGE_LEN 0x100
+#define PCM512x_PAGE_BASE(n) (PCM512x_VIRT_BASE + (PCM512x_PAGE_LEN * n))
+
+#define PCM512x_PAGE 0
+
+#define PCM512x_RESET (PCM512x_PAGE_BASE(0) + 1)
+#define PCM512x_POWER (PCM512x_PAGE_BASE(0) + 2)
+#define PCM512x_MUTE (PCM512x_PAGE_BASE(0) + 3)
+#define PCM512x_PLL_EN (PCM512x_PAGE_BASE(0) + 4)
+#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_BASE(0) + 6)
+#define PCM512x_DSP (PCM512x_PAGE_BASE(0) + 7)
+#define PCM512x_GPIO_EN (PCM512x_PAGE_BASE(0) + 8)
+#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_BASE(0) + 9)
+#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_BASE(0) + 10)
+#define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12)
+#define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13)
+#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20)
+#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_BASE(0) + 21)
+#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_BASE(0) + 22)
+#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_BASE(0) + 23)
+#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_BASE(0) + 24)
+#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_BASE(0) + 27)
+#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_BASE(0) + 28)
+#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_BASE(0) + 29)
+#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_BASE(0) + 30)
+#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_BASE(0) + 32)
+#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_BASE(0) + 33)
+#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_BASE(0) + 34)
+#define PCM512x_IDAC_1 (PCM512x_PAGE_BASE(0) + 35)
+#define PCM512x_IDAC_2 (PCM512x_PAGE_BASE(0) + 36)
+#define PCM512x_ERROR_DETECT (PCM512x_PAGE_BASE(0) + 37)
+#define PCM512x_I2S_1 (PCM512x_PAGE_BASE(0) + 40)
+#define PCM512x_I2S_2 (PCM512x_PAGE_BASE(0) + 41)
+#define PCM512x_DAC_ROUTING (PCM512x_PAGE_BASE(0) + 42)
+#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_BASE(0) + 43)
+#define PCM512x_CLKDET (PCM512x_PAGE_BASE(0) + 44)
+#define PCM512x_AUTO_MUTE (PCM512x_PAGE_BASE(0) + 59)
+#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_BASE(0) + 60)
+#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_BASE(0) + 61)
+#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_BASE(0) + 62)
+#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_BASE(0) + 63)
+#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_BASE(0) + 64)
+#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_BASE(0) + 65)
+#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_BASE(0) + 80)
+#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_BASE(0) + 81)
+#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_BASE(0) + 82)
+#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_BASE(0) + 83)
+#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_BASE(0) + 84)
+#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_BASE(0) + 85)
+#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_BASE(0) + 86)
+#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_BASE(0) + 87)
+#define PCM512x_OVERFLOW (PCM512x_PAGE_BASE(0) + 90)
+#define PCM512x_RATE_DET_1 (PCM512x_PAGE_BASE(0) + 91)
+#define PCM512x_RATE_DET_2 (PCM512x_PAGE_BASE(0) + 92)
+#define PCM512x_RATE_DET_3 (PCM512x_PAGE_BASE(0) + 93)
+#define PCM512x_RATE_DET_4 (PCM512x_PAGE_BASE(0) + 94)
+#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_BASE(0) + 108)
+#define PCM512x_GPIN (PCM512x_PAGE_BASE(0) + 119)
+#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_BASE(0) + 120)
+
+#define PCM512x_OUTPUT_AMPLITUDE (PCM512x_PAGE_BASE(1) + 1)
+#define PCM512x_ANALOG_GAIN_CTRL (PCM512x_PAGE_BASE(1) + 2)
+#define PCM512x_UNDERVOLTAGE_PROT (PCM512x_PAGE_BASE(1) + 5)
+#define PCM512x_ANALOG_MUTE_CTRL (PCM512x_PAGE_BASE(1) + 6)
+#define PCM512x_ANALOG_GAIN_BOOST (PCM512x_PAGE_BASE(1) + 7)
+#define PCM512x_VCOM_CTRL_1 (PCM512x_PAGE_BASE(1) + 8)
+#define PCM512x_VCOM_CTRL_2 (PCM512x_PAGE_BASE(1) + 9)
+
+#define PCM512x_CRAM_CTRL (PCM512x_PAGE_BASE(44) + 1)
+
+#define PCM512x_MAX_REGISTER (PCM512x_PAGE_BASE(44) + 1)
+
+/* Page 0, Register 1 - reset */
+#define PCM512x_RSTR (1 << 0)
+#define PCM512x_RSTM (1 << 4)
+
+/* Page 0, Register 2 - power */
+#define PCM512x_RQPD (1 << 0)
+#define PCM512x_RQPD_SHIFT 0
+#define PCM512x_RQST (1 << 4)
+#define PCM512x_RQST_SHIFT 4
+
+/* Page 0, Register 3 - mute */
+#define PCM512x_RQMR_SHIFT 0
+#define PCM512x_RQML_SHIFT 4
+
+/* Page 0, Register 4 - PLL */
+#define PCM512x_PLCE (1 << 0)
+#define PCM512x_RLCE_SHIFT 0
+#define PCM512x_PLCK (1 << 4)
+#define PCM512x_PLCK_SHIFT 4
+
+/* Page 0, Register 7 - DSP */
+#define PCM512x_SDSL (1 << 0)
+#define PCM512x_SDSL_SHIFT 0
+#define PCM512x_DEMP (1 << 4)
+#define PCM512x_DEMP_SHIFT 4
+
+/* Page 0, Register 13 - PLL reference */
+#define PCM512x_SREF (1 << 4)
+
+/* Page 0, Register 37 - Error detection */
+#define PCM512x_IPLK (1 << 0)
+#define PCM512x_DCAS (1 << 1)
+#define PCM512x_IDCM (1 << 2)
+#define PCM512x_IDCH (1 << 3)
+#define PCM512x_IDSK (1 << 4)
+#define PCM512x_IDBK (1 << 5)
+#define PCM512x_IDFS (1 << 6)
+
+/* Page 0, Register 42 - DAC routing */
+#define PCM512x_AUPR_SHIFT 0
+#define PCM512x_AUPL_SHIFT 4
+
+/* Page 0, Register 59 - auto mute */
+#define PCM512x_ATMR_SHIFT 0
+#define PCM512x_ATML_SHIFT 4
+
+/* Page 0, Register 63 - ramp rates */
+#define PCM512x_VNDF_SHIFT 6
+#define PCM512x_VNDS_SHIFT 4
+#define PCM512x_VNUF_SHIFT 2
+#define PCM512x_VNUS_SHIFT 0
+
+/* Page 0, Register 64 - emergency ramp rates */
+#define PCM512x_VEDF_SHIFT 6
+#define PCM512x_VEDS_SHIFT 4
+
+/* Page 0, Register 65 - Digital mute enables */
+#define PCM512x_ACTL_SHIFT 2
+#define PCM512x_AMLE_SHIFT 1
+#define PCM512x_AMLR_SHIFT 0
+
+/* Page 1, Register 2 - analog volume control */
+#define PCM512x_RAGN_SHIFT 0
+#define PCM512x_LAGN_SHIFT 4
+
+/* Page 1, Register 7 - analog boost control */
+#define PCM512x_AGBR_SHIFT 0
+#define PCM512x_AGBL_SHIFT 4
+
+extern const struct dev_pm_ops pcm512x_pm_ops;
+extern const struct regmap_config pcm512x_regmap;
+
+int pcm512x_probe(struct device *dev, struct regmap *regmap);
+void pcm512x_remove(struct device *dev);
+
+#endif
diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c
new file mode 100644
index 00000000000..7b82fbe0d14
--- /dev/null
+++ b/sound/soc/codecs/rl6231.c
@@ -0,0 +1,152 @@
+/*
+ * rl6231.c - RL6231 class device shared support
+ *
+ * Copyright 2014 Realtek Semiconductor Corp.
+ *
+ * Author: Oder Chiou <oder_chiou@realtek.com>
+ *
+ * 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 <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/acpi.h>
+#include <sound/core.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 "rl6231.h"
+
+/**
+ * rl6231_calc_dmic_clk - Calculate the parameter of dmic.
+ *
+ * @rate: base clock rate.
+ *
+ * Choose dmic clock between 1MHz and 3MHz.
+ * It is better for clock to approximate 3MHz.
+ */
+int rl6231_calc_dmic_clk(int rate)
+{
+ int div[] = {2, 3, 4, 6, 8, 12}, idx = -EINVAL;
+ int i, red, bound, temp;
+
+ red = 3000000 * 12;
+ for (i = 0; i < ARRAY_SIZE(div); i++) {
+ bound = div[i] * 3000000;
+ if (rate > bound)
+ continue;
+ temp = bound - rate;
+ if (temp < red) {
+ red = temp;
+ idx = i;
+ }
+ }
+
+ return idx;
+}
+EXPORT_SYMBOL_GPL(rl6231_calc_dmic_clk);
+
+/**
+ * rl6231_pll_calc - Calcualte PLL M/N/K code.
+ * @freq_in: external clock provided to codec.
+ * @freq_out: target clock which codec works on.
+ * @pll_code: Pointer to structure with M, N, K and bypass flag.
+ *
+ * Calcualte M/N/K code to configure PLL for codec.
+ *
+ * Returns 0 for success or negative error code.
+ */
+int rl6231_pll_calc(const unsigned int freq_in,
+ const unsigned int freq_out, struct rl6231_pll_code *pll_code)
+{
+ int max_n = RL6231_PLL_N_MAX, max_m = RL6231_PLL_M_MAX;
+ int k, red, n_t, pll_out, in_t, out_t;
+ int n = 0, m = 0, m_t = 0;
+ int red_t = abs(freq_out - freq_in);
+ bool bypass = false;
+
+ if (RL6231_PLL_INP_MAX < freq_in || RL6231_PLL_INP_MIN > freq_in)
+ return -EINVAL;
+
+ k = 100000000 / freq_out - 2;
+ if (k > RL6231_PLL_K_MAX)
+ k = RL6231_PLL_K_MAX;
+ for (n_t = 0; n_t <= max_n; n_t++) {
+ in_t = freq_in / (k + 2);
+ pll_out = freq_out / (n_t + 2);
+ if (in_t < 0)
+ continue;
+ if (in_t == pll_out) {
+ bypass = true;
+ n = n_t;
+ goto code_find;
+ }
+ red = abs(in_t - pll_out);
+ if (red < red_t) {
+ bypass = true;
+ n = n_t;
+ m = m_t;
+ if (red == 0)
+ goto code_find;
+ red_t = red;
+ }
+ for (m_t = 0; m_t <= max_m; m_t++) {
+ out_t = in_t / (m_t + 2);
+ red = abs(out_t - pll_out);
+ if (red < red_t) {
+ bypass = false;
+ n = n_t;
+ m = m_t;
+ if (red == 0)
+ goto code_find;
+ red_t = red;
+ }
+ }
+ }
+ pr_debug("Only get approximation about PLL\n");
+
+code_find:
+
+ pll_code->m_bp = bypass;
+ pll_code->m_code = m;
+ pll_code->n_code = n;
+ pll_code->k_code = k;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rl6231_pll_calc);
+
+int rl6231_get_clk_info(int sclk, int rate)
+{
+ int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
+
+ if (sclk <= 0 || rate <= 0)
+ return -EINVAL;
+
+ rate = rate << 8;
+ for (i = 0; i < ARRAY_SIZE(pd); i++)
+ if (sclk == rate * pd[i])
+ return i;
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(rl6231_get_clk_info);
+
+MODULE_DESCRIPTION("RL6231 class device shared support");
+MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rl6231.h b/sound/soc/codecs/rl6231.h
new file mode 100644
index 00000000000..0f7b057ed73
--- /dev/null
+++ b/sound/soc/codecs/rl6231.h
@@ -0,0 +1,34 @@
+/*
+ * rl6231.h - RL6231 class device shared support
+ *
+ * Copyright 2014 Realtek Semiconductor Corp.
+ *
+ * Author: Oder Chiou <oder_chiou@realtek.com>
+ *
+ * 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 __RL6231_H__
+#define __RL6231_H__
+
+#define RL6231_PLL_INP_MAX 40000000
+#define RL6231_PLL_INP_MIN 256000
+#define RL6231_PLL_N_MAX 0x1ff
+#define RL6231_PLL_K_MAX 0x1f
+#define RL6231_PLL_M_MAX 0xf
+
+struct rl6231_pll_code {
+ bool m_bp; /* Indicates bypass m code or not. */
+ int m_code;
+ int n_code;
+ int k_code;
+};
+
+int rl6231_calc_dmic_clk(int rate);
+int rl6231_pll_calc(const unsigned int freq_in,
+ const unsigned int freq_out, struct rl6231_pll_code *pll_code);
+int rl6231_get_clk_info(int sclk, int rate);
+
+#endif /* __RL6231_H__ */
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
index 912c9cbc272..30e23470857 100644
--- a/sound/soc/codecs/rt5631.c
+++ b/sound/soc/codecs/rt5631.c
@@ -188,7 +188,7 @@ static unsigned int mic_bst_tlv[] = {
static int rt5631_dmic_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = rt5631->dmic_used_flag;
@@ -199,7 +199,7 @@ static int rt5631_dmic_get(struct snd_kcontrol *kcontrol,
static int rt5631_dmic_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
rt5631->dmic_used_flag = ucontrol->value.integer.value[0];
@@ -210,26 +210,22 @@ static int rt5631_dmic_put(struct snd_kcontrol *kcontrol,
static const char *rt5631_input_mode[] = {
"Single ended", "Differential"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1,
- RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode);
+static SOC_ENUM_SINGLE_DECL(rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1,
+ RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode);
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1,
- RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode);
+static SOC_ENUM_SINGLE_DECL(rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1,
+ RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode);
/* MONO Input Type */
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL,
- RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode);
+static SOC_ENUM_SINGLE_DECL(rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL,
+ RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode);
/* SPK Ratio Gain Control */
static const char *rt5631_spk_ratio[] = {"1.00x", "1.09x", "1.27x", "1.44x",
"1.56x", "1.68x", "1.99x", "2.34x"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG,
- RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio);
+static SOC_ENUM_SINGLE_DECL(rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG,
+ RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio);
static const struct snd_kcontrol_new rt5631_snd_controls[] = {
/* MIC */
@@ -759,9 +755,8 @@ static const struct snd_kcontrol_new rt5631_monomix_mixer_controls[] = {
/* Left SPK Volume Input */
static const char *rt5631_spkvoll_sel[] = {"Vmid", "SPKMIXL"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL,
- RT5631_L_EN_SHIFT, rt5631_spkvoll_sel);
+static SOC_ENUM_SINGLE_DECL(rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL,
+ RT5631_L_EN_SHIFT, rt5631_spkvoll_sel);
static const struct snd_kcontrol_new rt5631_spkvoll_mux_control =
SOC_DAPM_ENUM("Left SPKVOL SRC", rt5631_spkvoll_enum);
@@ -769,9 +764,8 @@ static const struct snd_kcontrol_new rt5631_spkvoll_mux_control =
/* Left HP Volume Input */
static const char *rt5631_hpvoll_sel[] = {"Vmid", "OUTMIXL"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_hpvoll_enum, RT5631_HP_OUT_VOL,
- RT5631_L_EN_SHIFT, rt5631_hpvoll_sel);
+static SOC_ENUM_SINGLE_DECL(rt5631_hpvoll_enum, RT5631_HP_OUT_VOL,
+ RT5631_L_EN_SHIFT, rt5631_hpvoll_sel);
static const struct snd_kcontrol_new rt5631_hpvoll_mux_control =
SOC_DAPM_ENUM("Left HPVOL SRC", rt5631_hpvoll_enum);
@@ -779,9 +773,8 @@ static const struct snd_kcontrol_new rt5631_hpvoll_mux_control =
/* Left Out Volume Input */
static const char *rt5631_outvoll_sel[] = {"Vmid", "OUTMIXL"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL,
- RT5631_L_EN_SHIFT, rt5631_outvoll_sel);
+static SOC_ENUM_SINGLE_DECL(rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL,
+ RT5631_L_EN_SHIFT, rt5631_outvoll_sel);
static const struct snd_kcontrol_new rt5631_outvoll_mux_control =
SOC_DAPM_ENUM("Left OUTVOL SRC", rt5631_outvoll_enum);
@@ -789,9 +782,8 @@ static const struct snd_kcontrol_new rt5631_outvoll_mux_control =
/* Right Out Volume Input */
static const char *rt5631_outvolr_sel[] = {"Vmid", "OUTMIXR"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL,
- RT5631_R_EN_SHIFT, rt5631_outvolr_sel);
+static SOC_ENUM_SINGLE_DECL(rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL,
+ RT5631_R_EN_SHIFT, rt5631_outvolr_sel);
static const struct snd_kcontrol_new rt5631_outvolr_mux_control =
SOC_DAPM_ENUM("Right OUTVOL SRC", rt5631_outvolr_enum);
@@ -799,9 +791,8 @@ static const struct snd_kcontrol_new rt5631_outvolr_mux_control =
/* Right HP Volume Input */
static const char *rt5631_hpvolr_sel[] = {"Vmid", "OUTMIXR"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_hpvolr_enum, RT5631_HP_OUT_VOL,
- RT5631_R_EN_SHIFT, rt5631_hpvolr_sel);
+static SOC_ENUM_SINGLE_DECL(rt5631_hpvolr_enum, RT5631_HP_OUT_VOL,
+ RT5631_R_EN_SHIFT, rt5631_hpvolr_sel);
static const struct snd_kcontrol_new rt5631_hpvolr_mux_control =
SOC_DAPM_ENUM("Right HPVOL SRC", rt5631_hpvolr_enum);
@@ -809,9 +800,8 @@ static const struct snd_kcontrol_new rt5631_hpvolr_mux_control =
/* Right SPK Volume Input */
static const char *rt5631_spkvolr_sel[] = {"Vmid", "SPKMIXR"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL,
- RT5631_R_EN_SHIFT, rt5631_spkvolr_sel);
+static SOC_ENUM_SINGLE_DECL(rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL,
+ RT5631_R_EN_SHIFT, rt5631_spkvolr_sel);
static const struct snd_kcontrol_new rt5631_spkvolr_mux_control =
SOC_DAPM_ENUM("Right SPKVOL SRC", rt5631_spkvolr_enum);
@@ -820,9 +810,8 @@ static const struct snd_kcontrol_new rt5631_spkvolr_mux_control =
static const char *rt5631_spol_src_sel[] = {
"SPOLMIX", "MONOIN_RX", "VDAC", "DACL"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
- RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel);
+static SOC_ENUM_SINGLE_DECL(rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+ RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel);
static const struct snd_kcontrol_new rt5631_spol_mux_control =
SOC_DAPM_ENUM("SPOL SRC", rt5631_spol_src_enum);
@@ -831,9 +820,8 @@ static const struct snd_kcontrol_new rt5631_spol_mux_control =
static const char *rt5631_spor_src_sel[] = {
"SPORMIX", "MONOIN_RX", "VDAC", "DACR"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
- RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel);
+static SOC_ENUM_SINGLE_DECL(rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+ RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel);
static const struct snd_kcontrol_new rt5631_spor_mux_control =
SOC_DAPM_ENUM("SPOR SRC", rt5631_spor_src_enum);
@@ -841,9 +829,8 @@ static const struct snd_kcontrol_new rt5631_spor_mux_control =
/* MONO Input */
static const char *rt5631_mono_src_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
- RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel);
+static SOC_ENUM_SINGLE_DECL(rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+ RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel);
static const struct snd_kcontrol_new rt5631_mono_mux_control =
SOC_DAPM_ENUM("MONO SRC", rt5631_mono_src_enum);
@@ -851,9 +838,8 @@ static const struct snd_kcontrol_new rt5631_mono_mux_control =
/* Left HPO Input */
static const char *rt5631_hpl_src_sel[] = {"Left HPVOL", "Left DAC"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
- RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel);
+static SOC_ENUM_SINGLE_DECL(rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+ RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel);
static const struct snd_kcontrol_new rt5631_hpl_mux_control =
SOC_DAPM_ENUM("HPL SRC", rt5631_hpl_src_enum);
@@ -861,9 +847,8 @@ static const struct snd_kcontrol_new rt5631_hpl_mux_control =
/* Right HPO Input */
static const char *rt5631_hpr_src_sel[] = {"Right HPVOL", "Right DAC"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
- RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel);
+static SOC_ENUM_SINGLE_DECL(rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+ RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel);
static const struct snd_kcontrol_new rt5631_hpr_mux_control =
SOC_DAPM_ENUM("HPR SRC", rt5631_hpr_src_enum);
@@ -1585,15 +1570,6 @@ static int rt5631_probe(struct snd_soc_codec *codec)
{
struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
unsigned int val;
- int ret;
-
- codec->control_data = rt5631->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
val = rt5631_read_index(codec, RT5631_ADDA_MIXER_INTL_REG3);
if (val & 0x0002)
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index a3fb4117963..de80e89b5fd 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -1,5 +1,5 @@
/*
- * rt5640.c -- RT5640 ALSA SoC audio codec driver
+ * rt5640.c -- RT5640/RT5639 ALSA SoC audio codec driver
*
* Copyright 2011 Realtek Semiconductor Corp.
* Author: Johnny Hsu <johnnyhsu@realtek.com>
@@ -18,6 +18,7 @@
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
+#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
@@ -30,6 +31,7 @@
#include <sound/initval.h>
#include <sound/tlv.h>
+#include "rl6231.h"
#include "rt5640.h"
#define RT5640_DEVICE_ID 0x6231
@@ -59,7 +61,7 @@ static struct reg_default init_list[] = {
};
#define RT5640_INIT_REG_LEN ARRAY_SIZE(init_list)
-static const struct reg_default rt5640_reg[RT5640_VENDOR_ID2 + 1] = {
+static const struct reg_default rt5640_reg[] = {
{ 0x00, 0x000e },
{ 0x01, 0xc8c8 },
{ 0x02, 0xc8c8 },
@@ -361,25 +363,24 @@ static unsigned int bst_tlv[] = {
static const char * const rt5640_data_select[] = {
"Normal", "left copy to right", "right copy to left", "Swap"};
-static const SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA,
- RT5640_IF1_DAC_SEL_SFT, rt5640_data_select);
+static SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA,
+ RT5640_IF1_DAC_SEL_SFT, rt5640_data_select);
-static const SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA,
- RT5640_IF1_ADC_SEL_SFT, rt5640_data_select);
+static SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA,
+ RT5640_IF1_ADC_SEL_SFT, rt5640_data_select);
-static const SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA,
- RT5640_IF2_DAC_SEL_SFT, rt5640_data_select);
+static SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA,
+ RT5640_IF2_DAC_SEL_SFT, rt5640_data_select);
-static const SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA,
- RT5640_IF2_ADC_SEL_SFT, rt5640_data_select);
+static SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA,
+ RT5640_IF2_ADC_SEL_SFT, rt5640_data_select);
/* Class D speaker gain ratio */
static const char * const rt5640_clsd_spk_ratio[] = {"1.66x", "1.83x", "1.94x",
"2x", "2.11x", "2.22x", "2.33x", "2.44x", "2.55x", "2.66x", "2.77x"};
-static const SOC_ENUM_SINGLE_DECL(
- rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT,
- RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio);
+static SOC_ENUM_SINGLE_DECL(rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT,
+ RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio);
static const struct snd_kcontrol_new rt5640_snd_controls[] = {
/* Speaker Output Volume */
@@ -399,18 +400,13 @@ static const struct snd_kcontrol_new rt5640_snd_controls[] = {
RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
SOC_DOUBLE_TLV("OUT Playback Volume", RT5640_OUTPUT,
RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv),
- /* MONO Output Control */
- SOC_SINGLE("Mono Playback Switch", RT5640_MONO_OUT,
- RT5640_L_MUTE_SFT, 1, 1),
+
/* DAC Digital Volume */
SOC_DOUBLE("DAC2 Playback Switch", RT5640_DAC2_CTRL,
RT5640_M_DAC_L2_VOL_SFT, RT5640_M_DAC_R2_VOL_SFT, 1, 1),
SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5640_DAC1_DIG_VOL,
RT5640_L_VOL_SFT, RT5640_R_VOL_SFT,
175, 0, dac_vol_tlv),
- SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5640_DAC2_DIG_VOL,
- RT5640_L_VOL_SFT, RT5640_R_VOL_SFT,
- 175, 0, dac_vol_tlv),
/* IN1/IN2 Control */
SOC_SINGLE_TLV("IN1 Boost", RT5640_IN1_IN2,
RT5640_BST_SFT1, 8, 0, bst_tlv),
@@ -442,6 +438,15 @@ static const struct snd_kcontrol_new rt5640_snd_controls[] = {
SOC_ENUM("DAC IF2 Data Switch", rt5640_if2_dac_enum),
};
+static const struct snd_kcontrol_new rt5640_specific_snd_controls[] = {
+ /* MONO Output Control */
+ SOC_SINGLE("Mono Playback Switch", RT5640_MONO_OUT, RT5640_L_MUTE_SFT,
+ 1, 1),
+
+ SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5640_DAC2_DIG_VOL,
+ RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 175, 0, dac_vol_tlv),
+};
+
/**
* set_dmic_clk - Set parameter of dmic.
*
@@ -449,30 +454,16 @@ static const struct snd_kcontrol_new rt5640_snd_controls[] = {
* @kcontrol: The kcontrol of this widget.
* @event: Event id.
*
- * Choose dmic clock between 1MHz and 3MHz.
- * It is better for clock to approximate 3MHz.
*/
static int set_dmic_clk(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
- int div[] = {2, 3, 4, 6, 8, 12};
- int idx = -EINVAL, i;
- int rate, red, bound, temp;
-
- rate = rt5640->sysclk;
- red = 3000000 * 12;
- for (i = 0; i < ARRAY_SIZE(div); i++) {
- bound = div[i] * 3000000;
- if (rate > bound)
- continue;
- temp = bound - rate;
- if (temp < red) {
- red = temp;
- idx = i;
- }
- }
+ int idx = -EINVAL;
+
+ idx = rl6231_calc_dmic_clk(rt5640->sysclk);
+
if (idx < 0)
dev_err(codec->dev, "Failed to set DMIC clock\n");
else
@@ -481,14 +472,14 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
return idx;
}
-static int check_sysclk1_source(struct snd_soc_dapm_widget *source,
+static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
unsigned int val;
val = snd_soc_read(source->codec, RT5640_GLB_CLK);
val &= RT5640_SCLK_SRC_MASK;
- if (val == RT5640_SCLK_SRC_PLL1 || val == RT5640_SCLK_SRC_PLL1T)
+ if (val == RT5640_SCLK_SRC_PLL1)
return 1;
else
return 0;
@@ -555,6 +546,20 @@ static const struct snd_kcontrol_new rt5640_sto_dac_r_mix[] = {
RT5640_M_ANC_DAC_R_SFT, 1, 1),
};
+static const struct snd_kcontrol_new rt5639_sto_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_STO_DAC_MIXER,
+ RT5640_M_DAC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_STO_DAC_MIXER,
+ RT5640_M_DAC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5639_sto_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_STO_DAC_MIXER,
+ RT5640_M_DAC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_STO_DAC_MIXER,
+ RT5640_M_DAC_R2_SFT, 1, 1),
+};
+
static const struct snd_kcontrol_new rt5640_mono_dac_l_mix[] = {
SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_MONO_DAC_MIXER,
RT5640_M_DAC_L1_MONO_L_SFT, 1, 1),
@@ -677,6 +682,30 @@ static const struct snd_kcontrol_new rt5640_out_r_mix[] = {
RT5640_M_DAC_R1_OM_R_SFT, 1, 1),
};
+static const struct snd_kcontrol_new rt5639_out_l_mix[] = {
+ SOC_DAPM_SINGLE("BST1 Switch", RT5640_OUT_L3_MIXER,
+ RT5640_M_BST1_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL Switch", RT5640_OUT_L3_MIXER,
+ RT5640_M_IN_L_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("REC MIXL Switch", RT5640_OUT_L3_MIXER,
+ RT5640_M_RM_L_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_OUT_L3_MIXER,
+ RT5640_M_DAC_L1_OM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5639_out_r_mix[] = {
+ SOC_DAPM_SINGLE("BST2 Switch", RT5640_OUT_R3_MIXER,
+ RT5640_M_BST4_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5640_OUT_R3_MIXER,
+ RT5640_M_BST1_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR Switch", RT5640_OUT_R3_MIXER,
+ RT5640_M_IN_R_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("REC MIXR Switch", RT5640_OUT_R3_MIXER,
+ RT5640_M_RM_R_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_OUT_R3_MIXER,
+ RT5640_M_DAC_R1_OM_R_SFT, 1, 1),
+};
+
static const struct snd_kcontrol_new rt5640_spo_l_mix[] = {
SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_SPO_L_MIXER,
RT5640_M_DAC_R1_SPM_L_SFT, 1, 1),
@@ -708,6 +737,13 @@ static const struct snd_kcontrol_new rt5640_hpo_mix[] = {
RT5640_M_HPVOL_HM_SFT, 1, 1),
};
+static const struct snd_kcontrol_new rt5639_hpo_mix[] = {
+ SOC_DAPM_SINGLE("HPO MIX DAC1 Switch", RT5640_HPO_MIXER,
+ RT5640_M_DAC1_HM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("HPO MIX HPVOL Switch", RT5640_HPO_MIXER,
+ RT5640_M_HPVOL_HM_SFT, 1, 1),
+};
+
static const struct snd_kcontrol_new rt5640_lout_mix[] = {
SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_LOUT_MIXER,
RT5640_M_DAC_L1_LM_SFT, 1, 1),
@@ -753,9 +789,8 @@ static const char * const rt5640_stereo_adc1_src[] = {
"DIG MIX", "ADC"
};
-static const SOC_ENUM_SINGLE_DECL(
- rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER,
- RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src);
+static SOC_ENUM_SINGLE_DECL(rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER,
+ RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src);
static const struct snd_kcontrol_new rt5640_sto_adc_1_mux =
SOC_DAPM_ENUM("Stereo ADC1 Mux", rt5640_stereo_adc1_enum);
@@ -764,9 +799,8 @@ static const char * const rt5640_stereo_adc2_src[] = {
"DMIC1", "DMIC2", "DIG MIX"
};
-static const SOC_ENUM_SINGLE_DECL(
- rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER,
- RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src);
+static SOC_ENUM_SINGLE_DECL(rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER,
+ RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src);
static const struct snd_kcontrol_new rt5640_sto_adc_2_mux =
SOC_DAPM_ENUM("Stereo ADC2 Mux", rt5640_stereo_adc2_enum);
@@ -776,9 +810,8 @@ static const char * const rt5640_mono_adc_l1_src[] = {
"Mono DAC MIXL", "ADCL"
};
-static const SOC_ENUM_SINGLE_DECL(
- rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER,
- RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src);
+static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER,
+ RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src);
static const struct snd_kcontrol_new rt5640_mono_adc_l1_mux =
SOC_DAPM_ENUM("Mono ADC1 left source", rt5640_mono_adc_l1_enum);
@@ -787,9 +820,8 @@ static const char * const rt5640_mono_adc_l2_src[] = {
"DMIC L1", "DMIC L2", "Mono DAC MIXL"
};
-static const SOC_ENUM_SINGLE_DECL(
- rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER,
- RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src);
+static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER,
+ RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src);
static const struct snd_kcontrol_new rt5640_mono_adc_l2_mux =
SOC_DAPM_ENUM("Mono ADC2 left source", rt5640_mono_adc_l2_enum);
@@ -798,9 +830,8 @@ static const char * const rt5640_mono_adc_r1_src[] = {
"Mono DAC MIXR", "ADCR"
};
-static const SOC_ENUM_SINGLE_DECL(
- rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER,
- RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src);
+static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER,
+ RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src);
static const struct snd_kcontrol_new rt5640_mono_adc_r1_mux =
SOC_DAPM_ENUM("Mono ADC1 right source", rt5640_mono_adc_r1_enum);
@@ -809,9 +840,8 @@ static const char * const rt5640_mono_adc_r2_src[] = {
"DMIC R1", "DMIC R2", "Mono DAC MIXR"
};
-static const SOC_ENUM_SINGLE_DECL(
- rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER,
- RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src);
+static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER,
+ RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src);
static const struct snd_kcontrol_new rt5640_mono_adc_r2_mux =
SOC_DAPM_ENUM("Mono ADC2 right source", rt5640_mono_adc_r2_enum);
@@ -826,12 +856,12 @@ static int rt5640_dac_l2_values[] = {
3,
};
-static const SOC_VALUE_ENUM_SINGLE_DECL(
- rt5640_dac_l2_enum, RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT,
- 0x3, rt5640_dac_l2_src, rt5640_dac_l2_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dac_l2_enum,
+ RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT,
+ 0x3, rt5640_dac_l2_src, rt5640_dac_l2_values);
static const struct snd_kcontrol_new rt5640_dac_l2_mux =
- SOC_DAPM_VALUE_ENUM("DAC2 left channel source", rt5640_dac_l2_enum);
+ SOC_DAPM_ENUM("DAC2 left channel source", rt5640_dac_l2_enum);
static const char * const rt5640_dac_r2_src[] = {
"IF2",
@@ -841,9 +871,9 @@ static int rt5640_dac_r2_values[] = {
0,
};
-static const SOC_VALUE_ENUM_SINGLE_DECL(
- rt5640_dac_r2_enum, RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT,
- 0x3, rt5640_dac_r2_src, rt5640_dac_r2_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dac_r2_enum,
+ RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT,
+ 0x3, rt5640_dac_r2_src, rt5640_dac_r2_values);
static const struct snd_kcontrol_new rt5640_dac_r2_mux =
SOC_DAPM_ENUM("DAC2 right channel source", rt5640_dac_r2_enum);
@@ -860,73 +890,25 @@ static int rt5640_dai_iis_map_values[] = {
7,
};
-static const SOC_VALUE_ENUM_SINGLE_DECL(
- rt5640_dai_iis_map_enum, RT5640_I2S1_SDP, RT5640_I2S_IF_SFT,
- 0x7, rt5640_dai_iis_map, rt5640_dai_iis_map_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dai_iis_map_enum,
+ RT5640_I2S1_SDP, RT5640_I2S_IF_SFT,
+ 0x7, rt5640_dai_iis_map,
+ rt5640_dai_iis_map_values);
static const struct snd_kcontrol_new rt5640_dai_mux =
- SOC_DAPM_VALUE_ENUM("DAI select", rt5640_dai_iis_map_enum);
+ SOC_DAPM_ENUM("DAI select", rt5640_dai_iis_map_enum);
/* SDI select */
static const char * const rt5640_sdi_sel[] = {
"IF1", "IF2"
};
-static const SOC_ENUM_SINGLE_DECL(
- rt5640_sdi_sel_enum, RT5640_I2S2_SDP,
- RT5640_I2S2_SDI_SFT, rt5640_sdi_sel);
+static SOC_ENUM_SINGLE_DECL(rt5640_sdi_sel_enum, RT5640_I2S2_SDP,
+ RT5640_I2S2_SDI_SFT, rt5640_sdi_sel);
static const struct snd_kcontrol_new rt5640_sdi_mux =
SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum);
-static int rt5640_set_dmic1_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, RT5640_GPIO_CTRL1,
- RT5640_GP2_PIN_MASK | RT5640_GP3_PIN_MASK,
- RT5640_GP2_PIN_DMIC1_SCL | RT5640_GP3_PIN_DMIC1_SDA);
- snd_soc_update_bits(codec, RT5640_DMIC,
- RT5640_DMIC_1L_LH_MASK | RT5640_DMIC_1R_LH_MASK |
- RT5640_DMIC_1_DP_MASK,
- RT5640_DMIC_1L_LH_FALLING | RT5640_DMIC_1R_LH_RISING |
- RT5640_DMIC_1_DP_IN1P);
- break;
-
- default:
- return 0;
- }
-
- return 0;
-}
-
-static int rt5640_set_dmic2_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, RT5640_GPIO_CTRL1,
- RT5640_GP2_PIN_MASK | RT5640_GP4_PIN_MASK,
- RT5640_GP2_PIN_DMIC1_SCL | RT5640_GP4_PIN_DMIC2_SDA);
- snd_soc_update_bits(codec, RT5640_DMIC,
- RT5640_DMIC_2L_LH_MASK | RT5640_DMIC_2R_LH_MASK |
- RT5640_DMIC_2_DP_MASK,
- RT5640_DMIC_2L_LH_FALLING | RT5640_DMIC_2R_LH_RISING |
- RT5640_DMIC_2_DP_IN1N);
- break;
-
- default:
- return 0;
- }
-
- return 0;
-}
-
static void hp_amp_power_on(struct snd_soc_codec *codec)
{
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
@@ -1061,12 +1043,10 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0,
set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
- SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5640_DMIC,
- RT5640_DMIC_1_EN_SFT, 0, rt5640_set_dmic1_event,
- SND_SOC_DAPM_PRE_PMU),
- SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5640_DMIC,
- RT5640_DMIC_2_EN_SFT, 0, rt5640_set_dmic2_event,
- SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5640_DMIC, RT5640_DMIC_1_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5640_DMIC, RT5640_DMIC_2_EN_SFT, 0,
+ NULL, 0),
/* Boost */
SND_SOC_DAPM_PGA("BST1", RT5640_PWR_ANLG2,
RT5640_PWR_BST1_BIT, 0, NULL, 0),
@@ -1153,26 +1133,15 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
- /* Audio DSP */
- SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
- /* ANC */
- SND_SOC_DAPM_PGA("ANC", SND_SOC_NOPM, 0, 0, NULL, 0),
+
/* Output Side */
/* DAC mixer before sound effect */
SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0,
rt5640_dac_l_mix, ARRAY_SIZE(rt5640_dac_l_mix)),
SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0,
rt5640_dac_r_mix, ARRAY_SIZE(rt5640_dac_r_mix)),
- /* DAC2 channel Mux */
- SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0,
- &rt5640_dac_l2_mux),
- SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0,
- &rt5640_dac_r2_mux),
+
/* DAC Mixer */
- SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
- rt5640_sto_dac_l_mix, ARRAY_SIZE(rt5640_sto_dac_l_mix)),
- SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
- rt5640_sto_dac_r_mix, ARRAY_SIZE(rt5640_sto_dac_r_mix)),
SND_SOC_DAPM_MIXER("Mono DAC MIXL", SND_SOC_NOPM, 0, 0,
rt5640_mono_dac_l_mix, ARRAY_SIZE(rt5640_mono_dac_l_mix)),
SND_SOC_DAPM_MIXER("Mono DAC MIXR", SND_SOC_NOPM, 0, 0,
@@ -1184,21 +1153,14 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
/* DACs */
SND_SOC_DAPM_DAC("DAC L1", NULL, RT5640_PWR_DIG1,
RT5640_PWR_DAC_L1_BIT, 0),
- SND_SOC_DAPM_DAC("DAC L2", NULL, RT5640_PWR_DIG1,
- RT5640_PWR_DAC_L2_BIT, 0),
SND_SOC_DAPM_DAC("DAC R1", NULL, RT5640_PWR_DIG1,
RT5640_PWR_DAC_R1_BIT, 0),
- SND_SOC_DAPM_DAC("DAC R2", NULL, RT5640_PWR_DIG1,
- RT5640_PWR_DAC_R2_BIT, 0),
+
/* SPK/OUT Mixer */
SND_SOC_DAPM_MIXER("SPK MIXL", RT5640_PWR_MIXER, RT5640_PWR_SM_L_BIT,
0, rt5640_spk_l_mix, ARRAY_SIZE(rt5640_spk_l_mix)),
SND_SOC_DAPM_MIXER("SPK MIXR", RT5640_PWR_MIXER, RT5640_PWR_SM_R_BIT,
0, rt5640_spk_r_mix, ARRAY_SIZE(rt5640_spk_r_mix)),
- SND_SOC_DAPM_MIXER("OUT MIXL", RT5640_PWR_MIXER, RT5640_PWR_OM_L_BIT,
- 0, rt5640_out_l_mix, ARRAY_SIZE(rt5640_out_l_mix)),
- SND_SOC_DAPM_MIXER("OUT MIXR", RT5640_PWR_MIXER, RT5640_PWR_OM_R_BIT,
- 0, rt5640_out_r_mix, ARRAY_SIZE(rt5640_out_r_mix)),
/* Ouput Volume */
SND_SOC_DAPM_PGA("SPKVOL L", RT5640_PWR_VOL,
RT5640_PWR_SV_L_BIT, 0, NULL, 0),
@@ -1217,16 +1179,8 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
0, rt5640_spo_l_mix, ARRAY_SIZE(rt5640_spo_l_mix)),
SND_SOC_DAPM_MIXER("SPOR MIX", SND_SOC_NOPM, 0,
0, rt5640_spo_r_mix, ARRAY_SIZE(rt5640_spo_r_mix)),
- SND_SOC_DAPM_MIXER("HPO MIX L", SND_SOC_NOPM, 0, 0,
- rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
- SND_SOC_DAPM_MIXER("HPO MIX R", SND_SOC_NOPM, 0, 0,
- rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
SND_SOC_DAPM_MIXER("LOUT MIX", RT5640_PWR_ANLG1, RT5640_PWR_LM_BIT, 0,
rt5640_lout_mix, ARRAY_SIZE(rt5640_lout_mix)),
- SND_SOC_DAPM_MIXER("Mono MIX", RT5640_PWR_ANLG1, RT5640_PWR_MM_BIT, 0,
- rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)),
- SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1,
- RT5640_PWR_MA_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("Improve HP Amp Drv", 1, SND_SOC_NOPM,
0, 0, rt5640_hp_power_event, SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0,
@@ -1258,10 +1212,69 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("HPOR"),
SND_SOC_DAPM_OUTPUT("LOUTL"),
SND_SOC_DAPM_OUTPUT("LOUTR"),
+};
+
+static const struct snd_soc_dapm_widget rt5640_specific_dapm_widgets[] = {
+ /* Audio DSP */
+ SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
+ /* ANC */
+ SND_SOC_DAPM_PGA("ANC", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* DAC2 channel Mux */
+ SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dac_l2_mux),
+ SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dac_r2_mux),
+
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5640_sto_dac_l_mix, ARRAY_SIZE(rt5640_sto_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5640_sto_dac_r_mix, ARRAY_SIZE(rt5640_sto_dac_r_mix)),
+
+ SND_SOC_DAPM_DAC("DAC R2", NULL, RT5640_PWR_DIG1, RT5640_PWR_DAC_R2_BIT,
+ 0),
+ SND_SOC_DAPM_DAC("DAC L2", NULL, RT5640_PWR_DIG1, RT5640_PWR_DAC_L2_BIT,
+ 0),
+
+ SND_SOC_DAPM_MIXER("OUT MIXL", RT5640_PWR_MIXER, RT5640_PWR_OM_L_BIT,
+ 0, rt5640_out_l_mix, ARRAY_SIZE(rt5640_out_l_mix)),
+ SND_SOC_DAPM_MIXER("OUT MIXR", RT5640_PWR_MIXER, RT5640_PWR_OM_R_BIT,
+ 0, rt5640_out_r_mix, ARRAY_SIZE(rt5640_out_r_mix)),
+
+ SND_SOC_DAPM_MIXER("HPO MIX L", SND_SOC_NOPM, 0, 0,
+ rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
+ SND_SOC_DAPM_MIXER("HPO MIX R", SND_SOC_NOPM, 0, 0,
+ rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
+
+ SND_SOC_DAPM_MIXER("Mono MIX", RT5640_PWR_ANLG1, RT5640_PWR_MM_BIT, 0,
+ rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)),
+ SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1,
+ RT5640_PWR_MA_BIT, 0, NULL, 0),
+
SND_SOC_DAPM_OUTPUT("MONOP"),
SND_SOC_DAPM_OUTPUT("MONON"),
};
+static const struct snd_soc_dapm_widget rt5639_specific_dapm_widgets[] = {
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5639_sto_dac_l_mix, ARRAY_SIZE(rt5639_sto_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5639_sto_dac_r_mix, ARRAY_SIZE(rt5639_sto_dac_r_mix)),
+
+ SND_SOC_DAPM_SUPPLY("DAC L2 Filter", RT5640_PWR_DIG1,
+ RT5640_PWR_DAC_L2_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DAC R2 Filter", RT5640_PWR_DIG1,
+ RT5640_PWR_DAC_R2_BIT, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER("OUT MIXL", RT5640_PWR_MIXER, RT5640_PWR_OM_L_BIT,
+ 0, rt5639_out_l_mix, ARRAY_SIZE(rt5639_out_l_mix)),
+ SND_SOC_DAPM_MIXER("OUT MIXR", RT5640_PWR_MIXER, RT5640_PWR_OM_R_BIT,
+ 0, rt5639_out_r_mix, ARRAY_SIZE(rt5639_out_r_mix)),
+
+ SND_SOC_DAPM_MIXER("HPO MIX L", SND_SOC_NOPM, 0, 0,
+ rt5639_hpo_mix, ARRAY_SIZE(rt5639_hpo_mix)),
+ SND_SOC_DAPM_MIXER("HPO MIX R", SND_SOC_NOPM, 0, 0,
+ rt5639_hpo_mix, ARRAY_SIZE(rt5639_hpo_mix)),
+};
+
static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
{"IN1P", NULL, "LDO2"},
{"IN2P", NULL, "LDO2"},
@@ -1330,22 +1343,22 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
{"Stereo ADC MIXL", "ADC1 Switch", "Stereo ADC L1 Mux"},
{"Stereo ADC MIXL", "ADC2 Switch", "Stereo ADC L2 Mux"},
{"Stereo ADC MIXL", NULL, "Stereo Filter"},
- {"Stereo Filter", NULL, "PLL1", check_sysclk1_source},
+ {"Stereo Filter", NULL, "PLL1", is_sys_clk_from_pll},
{"Stereo ADC MIXR", "ADC1 Switch", "Stereo ADC R1 Mux"},
{"Stereo ADC MIXR", "ADC2 Switch", "Stereo ADC R2 Mux"},
{"Stereo ADC MIXR", NULL, "Stereo Filter"},
- {"Stereo Filter", NULL, "PLL1", check_sysclk1_source},
+ {"Stereo Filter", NULL, "PLL1", is_sys_clk_from_pll},
{"Mono ADC MIXL", "ADC1 Switch", "Mono ADC L1 Mux"},
{"Mono ADC MIXL", "ADC2 Switch", "Mono ADC L2 Mux"},
{"Mono ADC MIXL", NULL, "Mono Left Filter"},
- {"Mono Left Filter", NULL, "PLL1", check_sysclk1_source},
+ {"Mono Left Filter", NULL, "PLL1", is_sys_clk_from_pll},
{"Mono ADC MIXR", "ADC1 Switch", "Mono ADC R1 Mux"},
{"Mono ADC MIXR", "ADC2 Switch", "Mono ADC R2 Mux"},
{"Mono ADC MIXR", NULL, "Mono Right Filter"},
- {"Mono Right Filter", NULL, "PLL1", check_sysclk1_source},
+ {"Mono Right Filter", NULL, "PLL1", is_sys_clk_from_pll},
{"IF2 ADC L", NULL, "Mono ADC MIXL"},
{"IF2 ADC R", NULL, "Mono ADC MIXR"},
@@ -1403,71 +1416,38 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
{"DAC MIXR", "Stereo ADC Switch", "Stereo ADC MIXR"},
{"DAC MIXR", "INF1 Switch", "IF1 DAC R"},
- {"ANC", NULL, "Stereo ADC MIXL"},
- {"ANC", NULL, "Stereo ADC MIXR"},
-
- {"Audio DSP", NULL, "DAC MIXL"},
- {"Audio DSP", NULL, "DAC MIXR"},
-
- {"DAC L2 Mux", "IF2", "IF2 DAC L"},
- {"DAC L2 Mux", "Base L/R", "Audio DSP"},
-
- {"DAC R2 Mux", "IF2", "IF2 DAC R"},
-
{"Stereo DAC MIXL", "DAC L1 Switch", "DAC MIXL"},
- {"Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
- {"Stereo DAC MIXL", "ANC Switch", "ANC"},
{"Stereo DAC MIXR", "DAC R1 Switch", "DAC MIXR"},
- {"Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
- {"Stereo DAC MIXR", "ANC Switch", "ANC"},
{"Mono DAC MIXL", "DAC L1 Switch", "DAC MIXL"},
- {"Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
- {"Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Mux"},
{"Mono DAC MIXR", "DAC R1 Switch", "DAC MIXR"},
- {"Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
- {"Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Mux"},
{"DIG MIXL", "DAC L1 Switch", "DAC MIXL"},
- {"DIG MIXL", "DAC L2 Switch", "DAC L2 Mux"},
{"DIG MIXR", "DAC R1 Switch", "DAC MIXR"},
- {"DIG MIXR", "DAC R2 Switch", "DAC R2 Mux"},
{"DAC L1", NULL, "Stereo DAC MIXL"},
- {"DAC L1", NULL, "PLL1", check_sysclk1_source},
+ {"DAC L1", NULL, "PLL1", is_sys_clk_from_pll},
{"DAC R1", NULL, "Stereo DAC MIXR"},
- {"DAC R1", NULL, "PLL1", check_sysclk1_source},
- {"DAC L2", NULL, "Mono DAC MIXL"},
- {"DAC L2", NULL, "PLL1", check_sysclk1_source},
- {"DAC R2", NULL, "Mono DAC MIXR"},
- {"DAC R2", NULL, "PLL1", check_sysclk1_source},
+ {"DAC R1", NULL, "PLL1", is_sys_clk_from_pll},
{"SPK MIXL", "REC MIXL Switch", "RECMIXL"},
{"SPK MIXL", "INL Switch", "INL VOL"},
{"SPK MIXL", "DAC L1 Switch", "DAC L1"},
- {"SPK MIXL", "DAC L2 Switch", "DAC L2"},
{"SPK MIXL", "OUT MIXL Switch", "OUT MIXL"},
{"SPK MIXR", "REC MIXR Switch", "RECMIXR"},
{"SPK MIXR", "INR Switch", "INR VOL"},
{"SPK MIXR", "DAC R1 Switch", "DAC R1"},
- {"SPK MIXR", "DAC R2 Switch", "DAC R2"},
{"SPK MIXR", "OUT MIXR Switch", "OUT MIXR"},
- {"OUT MIXL", "SPK MIXL Switch", "SPK MIXL"},
{"OUT MIXL", "BST1 Switch", "BST1"},
{"OUT MIXL", "INL Switch", "INL VOL"},
{"OUT MIXL", "REC MIXL Switch", "RECMIXL"},
- {"OUT MIXL", "DAC R2 Switch", "DAC R2"},
- {"OUT MIXL", "DAC L2 Switch", "DAC L2"},
{"OUT MIXL", "DAC L1 Switch", "DAC L1"},
- {"OUT MIXR", "SPK MIXR Switch", "SPK MIXR"},
{"OUT MIXR", "BST2 Switch", "BST2"},
{"OUT MIXR", "BST1 Switch", "BST1"},
{"OUT MIXR", "INR Switch", "INR VOL"},
{"OUT MIXR", "REC MIXR Switch", "RECMIXR"},
- {"OUT MIXR", "DAC L2 Switch", "DAC L2"},
- {"OUT MIXR", "DAC R2 Switch", "DAC R2"},
{"OUT MIXR", "DAC R1 Switch", "DAC R1"},
{"SPKVOL L", NULL, "SPK MIXL"},
@@ -1486,11 +1466,9 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
{"SPOR MIX", "SPKVOL R Switch", "SPKVOL R"},
{"SPOR MIX", "BST1 Switch", "BST1"},
- {"HPO MIX L", "HPO MIX DAC2 Switch", "DAC L2"},
{"HPO MIX L", "HPO MIX DAC1 Switch", "DAC L1"},
{"HPO MIX L", "HPO MIX HPVOL Switch", "HPOVOL L"},
{"HPO MIX L", NULL, "HP L Amp"},
- {"HPO MIX R", "HPO MIX DAC2 Switch", "DAC R2"},
{"HPO MIX R", "HPO MIX DAC1 Switch", "DAC R1"},
{"HPO MIX R", "HPO MIX HPVOL Switch", "HPOVOL R"},
{"HPO MIX R", NULL, "HP R Amp"},
@@ -1500,12 +1478,6 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
{"LOUT MIX", "OUTVOL L Switch", "OUTVOL L"},
{"LOUT MIX", "OUTVOL R Switch", "OUTVOL R"},
- {"Mono MIX", "DAC R2 Switch", "DAC R2"},
- {"Mono MIX", "DAC L2 Switch", "DAC L2"},
- {"Mono MIX", "OUTVOL R Switch", "OUTVOL R"},
- {"Mono MIX", "OUTVOL L Switch", "OUTVOL L"},
- {"Mono MIX", "BST1 Switch", "BST1"},
-
{"HP Amp", NULL, "HPO MIX L"},
{"HP Amp", NULL, "HPO MIX R"},
@@ -1530,11 +1502,82 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
{"HPOR", NULL, "HP R Playback"},
{"LOUTL", NULL, "LOUT MIX"},
{"LOUTR", NULL, "LOUT MIX"},
+};
+
+static const struct snd_soc_dapm_route rt5640_specific_dapm_routes[] = {
+ {"ANC", NULL, "Stereo ADC MIXL"},
+ {"ANC", NULL, "Stereo ADC MIXR"},
+
+ {"Audio DSP", NULL, "DAC MIXL"},
+ {"Audio DSP", NULL, "DAC MIXR"},
+
+ {"DAC L2 Mux", "IF2", "IF2 DAC L"},
+ {"DAC L2 Mux", "Base L/R", "Audio DSP"},
+
+ {"DAC R2 Mux", "IF2", "IF2 DAC R"},
+
+ {"Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
+ {"Stereo DAC MIXL", "ANC Switch", "ANC"},
+ {"Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
+ {"Stereo DAC MIXR", "ANC Switch", "ANC"},
+
+ {"Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
+ {"Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Mux"},
+
+ {"Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
+ {"Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Mux"},
+
+ {"DIG MIXR", "DAC R2 Switch", "DAC R2 Mux"},
+ {"DIG MIXL", "DAC L2 Switch", "DAC L2 Mux"},
+
+ {"DAC L2", NULL, "Mono DAC MIXL"},
+ {"DAC L2", NULL, "PLL1", is_sys_clk_from_pll},
+ {"DAC R2", NULL, "Mono DAC MIXR"},
+ {"DAC R2", NULL, "PLL1", is_sys_clk_from_pll},
+
+ {"SPK MIXL", "DAC L2 Switch", "DAC L2"},
+ {"SPK MIXR", "DAC R2 Switch", "DAC R2"},
+
+ {"OUT MIXL", "SPK MIXL Switch", "SPK MIXL"},
+ {"OUT MIXR", "SPK MIXR Switch", "SPK MIXR"},
+
+ {"OUT MIXL", "DAC R2 Switch", "DAC R2"},
+ {"OUT MIXL", "DAC L2 Switch", "DAC L2"},
+
+ {"OUT MIXR", "DAC L2 Switch", "DAC L2"},
+ {"OUT MIXR", "DAC R2 Switch", "DAC R2"},
+
+ {"HPO MIX L", "HPO MIX DAC2 Switch", "DAC L2"},
+ {"HPO MIX R", "HPO MIX DAC2 Switch", "DAC R2"},
+
+ {"Mono MIX", "DAC R2 Switch", "DAC R2"},
+ {"Mono MIX", "DAC L2 Switch", "DAC L2"},
+ {"Mono MIX", "OUTVOL R Switch", "OUTVOL R"},
+ {"Mono MIX", "OUTVOL L Switch", "OUTVOL L"},
+ {"Mono MIX", "BST1 Switch", "BST1"},
+
{"MONOP", NULL, "Mono MIX"},
{"MONON", NULL, "Mono MIX"},
{"MONOP", NULL, "Improve MONO Amp Drv"},
};
+static const struct snd_soc_dapm_route rt5639_specific_dapm_routes[] = {
+ {"Stereo DAC MIXL", "DAC L2 Switch", "IF2 DAC L"},
+ {"Stereo DAC MIXR", "DAC R2 Switch", "IF2 DAC R"},
+
+ {"Mono DAC MIXL", "DAC L2 Switch", "IF2 DAC L"},
+ {"Mono DAC MIXL", "DAC R2 Switch", "IF2 DAC R"},
+
+ {"Mono DAC MIXR", "DAC R2 Switch", "IF2 DAC R"},
+ {"Mono DAC MIXR", "DAC L2 Switch", "IF2 DAC L"},
+
+ {"DIG MIXL", "DAC L2 Switch", "IF2 DAC L"},
+ {"DIG MIXR", "DAC R2 Switch", "IF2 DAC R"},
+
+ {"IF2 DAC L", NULL, "DAC L2 Filter"},
+ {"IF2 DAC R", NULL, "DAC R2 Filter"},
+};
+
static int get_sdp_info(struct snd_soc_codec *codec, int dai_id)
{
int ret = 0, val;
@@ -1583,32 +1626,16 @@ static int get_sdp_info(struct snd_soc_codec *codec, int dai_id)
return ret;
}
-static int get_clk_info(int sclk, int rate)
-{
- int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
-
- if (sclk <= 0 || rate <= 0)
- return -EINVAL;
-
- rate = rate << 8;
- for (i = 0; i < ARRAY_SIZE(pd); i++)
- if (sclk == rate * pd[i])
- return i;
-
- return -EINVAL;
-}
-
static int rt5640_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
unsigned int val_len = 0, val_clk, mask_clk;
int dai_sel, pre_div, bclk_ms, frame_size;
rt5640->lrck[dai->id] = params_rate(params);
- pre_div = get_clk_info(rt5640->sysclk, rt5640->lrck[dai->id]);
+ pre_div = rl6231_get_clk_info(rt5640->sysclk, rt5640->lrck[dai->id]);
if (pre_div < 0) {
dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n",
rt5640->lrck[dai->id], dai->id);
@@ -1630,16 +1657,16 @@ static int rt5640_hw_params(struct snd_pcm_substream *substream,
dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
bclk_ms, pre_div, dai->id);
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
+ switch (params_width(params)) {
+ case 16:
break;
- case SNDRV_PCM_FORMAT_S20_3LE:
+ case 20:
val_len |= RT5640_I2S_DL_20;
break;
- case SNDRV_PCM_FORMAT_S24_LE:
+ case 24:
val_len |= RT5640_I2S_DL_24;
break;
- case SNDRV_PCM_FORMAT_S8:
+ case 8:
val_len |= RT5640_I2S_DL_8;
break;
default:
@@ -1752,12 +1779,6 @@ static int rt5640_set_dai_sysclk(struct snd_soc_dai *dai,
case RT5640_SCLK_S_PLL1:
reg_val |= RT5640_SCLK_SRC_PLL1;
break;
- case RT5640_SCLK_S_PLL1_TK:
- reg_val |= RT5640_SCLK_SRC_PLL1T;
- break;
- case RT5640_SCLK_S_RCCLK:
- reg_val |= RT5640_SCLK_SRC_RCCLK;
- break;
default:
dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
return -EINVAL;
@@ -1771,65 +1792,12 @@ static int rt5640_set_dai_sysclk(struct snd_soc_dai *dai,
return 0;
}
-/**
- * rt5640_pll_calc - Calculate PLL M/N/K code.
- * @freq_in: external clock provided to codec.
- * @freq_out: target clock which codec works on.
- * @pll_code: Pointer to structure with M, N, K and bypass flag.
- *
- * Calculate M/N/K code to configure PLL for codec. And K is assigned to 2
- * which make calculation more efficiently.
- *
- * Returns 0 for success or negative error code.
- */
-static int rt5640_pll_calc(const unsigned int freq_in,
- const unsigned int freq_out, struct rt5640_pll_code *pll_code)
-{
- int max_n = RT5640_PLL_N_MAX, max_m = RT5640_PLL_M_MAX;
- int n = 0, m = 0, red, n_t, m_t, in_t, out_t;
- int red_t = abs(freq_out - freq_in);
- bool bypass = false;
-
- if (RT5640_PLL_INP_MAX < freq_in || RT5640_PLL_INP_MIN > freq_in)
- return -EINVAL;
-
- for (n_t = 0; n_t <= max_n; n_t++) {
- in_t = (freq_in >> 1) + (freq_in >> 2) * n_t;
- if (in_t < 0)
- continue;
- if (in_t == freq_out) {
- bypass = true;
- n = n_t;
- goto code_find;
- }
- for (m_t = 0; m_t <= max_m; m_t++) {
- out_t = in_t / (m_t + 2);
- red = abs(out_t - freq_out);
- if (red < red_t) {
- n = n_t;
- m = m_t;
- if (red == 0)
- goto code_find;
- red_t = red;
- }
- }
- }
- pr_debug("Only get approximation about PLL\n");
-
-code_find:
- pll_code->m_bp = bypass;
- pll_code->m_code = m;
- pll_code->n_code = n;
- pll_code->k_code = 2;
- return 0;
-}
-
static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
unsigned int freq_in, unsigned int freq_out)
{
struct snd_soc_codec *codec = dai->codec;
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
- struct rt5640_pll_code *pll_code = &rt5640->pll_code;
+ struct rl6231_pll_code pll_code;
int ret, dai_sel;
if (source == rt5640->pll_src && freq_in == rt5640->pll_in &&
@@ -1873,20 +1841,21 @@ static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
return -EINVAL;
}
- ret = rt5640_pll_calc(freq_in, freq_out, pll_code);
+ ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
if (ret < 0) {
dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
return ret;
}
- dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=2\n", pll_code->m_bp,
- (pll_code->m_bp ? 0 : pll_code->m_code), pll_code->n_code);
+ dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n",
+ pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
+ pll_code.n_code, pll_code.k_code);
snd_soc_write(codec, RT5640_PLL_CTRL1,
- pll_code->n_code << RT5640_PLL_N_SFT | pll_code->k_code);
+ pll_code.n_code << RT5640_PLL_N_SFT | pll_code.k_code);
snd_soc_write(codec, RT5640_PLL_CTRL2,
- (pll_code->m_bp ? 0 : pll_code->m_code) << RT5640_PLL_M_SFT |
- pll_code->m_bp << RT5640_PLL_M_BP_SFT);
+ (pll_code.m_bp ? 0 : pll_code.m_code) << RT5640_PLL_M_SFT |
+ pll_code.m_bp << RT5640_PLL_M_BP_SFT);
rt5640->pll_in = freq_in;
rt5640->pll_out = freq_out;
@@ -1898,11 +1867,9 @@ static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
static int rt5640_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
switch (level) {
case SND_SOC_BIAS_STANDBY:
if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) {
- regcache_cache_only(rt5640->regmap, false);
snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
RT5640_PWR_VREF1 | RT5640_PWR_MB |
RT5640_PWR_BG | RT5640_PWR_VREF2,
@@ -1912,7 +1879,6 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
RT5640_PWR_FV1 | RT5640_PWR_FV2,
RT5640_PWR_FV1 | RT5640_PWR_FV2);
- regcache_sync(rt5640->regmap);
snd_soc_update_bits(codec, RT5640_DUMMY1,
0x0301, 0x0301);
snd_soc_update_bits(codec, RT5640_MICBIAS,
@@ -1943,24 +1909,42 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
static int rt5640_probe(struct snd_soc_codec *codec)
{
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
- int ret;
rt5640->codec = codec;
- codec->control_data = rt5640->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
- codec->dapm.idle_bias_off = 1;
rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
snd_soc_update_bits(codec, RT5640_DUMMY1, 0x0301, 0x0301);
snd_soc_update_bits(codec, RT5640_MICBIAS, 0x0030, 0x0030);
snd_soc_update_bits(codec, RT5640_DSP_PATH2, 0xfc00, 0x0c00);
+ switch (snd_soc_read(codec, RT5640_RESET) & RT5640_ID_MASK) {
+ case RT5640_ID_5640:
+ case RT5640_ID_5642:
+ snd_soc_add_codec_controls(codec,
+ rt5640_specific_snd_controls,
+ ARRAY_SIZE(rt5640_specific_snd_controls));
+ snd_soc_dapm_new_controls(&codec->dapm,
+ rt5640_specific_dapm_widgets,
+ ARRAY_SIZE(rt5640_specific_dapm_widgets));
+ snd_soc_dapm_add_routes(&codec->dapm,
+ rt5640_specific_dapm_routes,
+ ARRAY_SIZE(rt5640_specific_dapm_routes));
+ break;
+ case RT5640_ID_5639:
+ snd_soc_dapm_new_controls(&codec->dapm,
+ rt5639_specific_dapm_widgets,
+ ARRAY_SIZE(rt5639_specific_dapm_widgets));
+ snd_soc_dapm_add_routes(&codec->dapm,
+ rt5639_specific_dapm_routes,
+ ARRAY_SIZE(rt5639_specific_dapm_routes));
+ break;
+ default:
+ dev_err(codec->dev,
+ "The driver is for RT5639 RT5640 or RT5642 only\n");
+ return -ENODEV;
+ }
+
return 0;
}
@@ -1995,6 +1979,9 @@ static int rt5640_resume(struct snd_soc_codec *codec)
msleep(400);
}
+ regcache_cache_only(rt5640->regmap, false);
+ regcache_sync(rt5640->regmap);
+
return 0;
}
#else
@@ -2060,6 +2047,7 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5640 = {
.suspend = rt5640_suspend,
.resume = rt5640_resume,
.set_bias_level = rt5640_set_bias_level,
+ .idle_bias_off = true,
.controls = rt5640_snd_controls,
.num_controls = ARRAY_SIZE(rt5640_snd_controls),
.dapm_widgets = rt5640_dapm_widgets,
@@ -2086,13 +2074,25 @@ static const struct regmap_config rt5640_regmap = {
static const struct i2c_device_id rt5640_i2c_id[] = {
{ "rt5640", 0 },
+ { "rt5639", 0 },
+ { "rt5642", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id);
+#if defined(CONFIG_OF)
+static const struct of_device_id rt5640_of_match[] = {
+ { .compatible = "realtek,rt5639", },
+ { .compatible = "realtek,rt5640", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, rt5640_of_match);
+#endif
+
#ifdef CONFIG_ACPI
static struct acpi_device_id rt5640_acpi_match[] = {
{ "INT33CA", 0 },
+ { "10EC5640", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match);
@@ -2173,7 +2173,7 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
}
regmap_read(rt5640->regmap, RT5640_VENDOR_ID2, &val);
- if ((val != RT5640_DEVICE_ID)) {
+ if (val != RT5640_DEVICE_ID) {
dev_err(&i2c->dev,
"Device with ID register %x is not rt5640/39\n", val);
return -ENODEV;
@@ -2194,6 +2194,25 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
regmap_update_bits(rt5640->regmap, RT5640_IN3_IN4,
RT5640_IN_DF2, RT5640_IN_DF2);
+ if (rt5640->pdata.dmic_en) {
+ regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
+ RT5640_GP2_PIN_MASK, RT5640_GP2_PIN_DMIC1_SCL);
+
+ if (rt5640->pdata.dmic1_data_pin) {
+ regmap_update_bits(rt5640->regmap, RT5640_DMIC,
+ RT5640_DMIC_1_DP_MASK, RT5640_DMIC_1_DP_GPIO3);
+ regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
+ RT5640_GP3_PIN_MASK, RT5640_GP3_PIN_DMIC1_SDA);
+ }
+
+ if (rt5640->pdata.dmic2_data_pin) {
+ regmap_update_bits(rt5640->regmap, RT5640_DMIC,
+ RT5640_DMIC_2_DP_MASK, RT5640_DMIC_2_DP_GPIO4);
+ regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
+ RT5640_GP4_PIN_MASK, RT5640_GP4_PIN_DMIC2_SDA);
+ }
+ }
+
rt5640->hp_mute = 1;
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640,
@@ -2218,6 +2237,7 @@ static struct i2c_driver rt5640_i2c_driver = {
.name = "rt5640",
.owner = THIS_MODULE,
.acpi_match_table = ACPI_PTR(rt5640_acpi_match),
+ .of_match_table = of_match_ptr(rt5640_of_match),
},
.probe = rt5640_i2c_probe,
.remove = rt5640_i2c_remove,
@@ -2225,6 +2245,6 @@ static struct i2c_driver rt5640_i2c_driver = {
};
module_i2c_driver(rt5640_i2c_driver);
-MODULE_DESCRIPTION("ASoC RT5640 driver");
+MODULE_DESCRIPTION("ASoC RT5640/RT5639 driver");
MODULE_AUTHOR("Johnny Hsu <johnnyhsu@realtek.com>");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index 5e8df25a13f..58ebe96b86d 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -192,6 +192,13 @@
#define RT5640_R_VOL_MASK (0x3f)
#define RT5640_R_VOL_SFT 0
+/* SW Reset & Device ID (0x00) */
+#define RT5640_ID_MASK (0x3 << 1)
+#define RT5640_ID_5639 (0x0 << 1)
+#define RT5640_ID_5640 (0x2 << 1)
+#define RT5640_ID_5642 (0x3 << 1)
+
+
/* IN1 and IN2 Control (0x0d) */
/* IN3 and IN4 Control (0x0e) */
#define RT5640_BST_SFT1 12
@@ -976,8 +983,6 @@
#define RT5640_SCLK_SRC_SFT 14
#define RT5640_SCLK_SRC_MCLK (0x0 << 14)
#define RT5640_SCLK_SRC_PLL1 (0x1 << 14)
-#define RT5640_SCLK_SRC_PLL1T (0x2 << 14)
-#define RT5640_SCLK_SRC_RCCLK (0x3 << 14) /* 15MHz */
#define RT5640_PLL1_SRC_MASK (0x3 << 12)
#define RT5640_PLL1_SRC_SFT 12
#define RT5640_PLL1_SRC_MCLK (0x0 << 12)
@@ -2074,13 +2079,6 @@ enum {
RT5640_DMIC2,
};
-struct rt5640_pll_code {
- bool m_bp; /* Indicates bypass m code or not. */
- int m_code;
- int n_code;
- int k_code;
-};
-
struct rt5640_priv {
struct snd_soc_codec *codec;
struct rt5640_platform_data pdata;
@@ -2092,12 +2090,10 @@ struct rt5640_priv {
int bclk[RT5640_AIFS];
int master[RT5640_AIFS];
- struct rt5640_pll_code pll_code;
int pll_src;
int pll_in;
int pll_out;
- int dmic_en;
bool hp_mute;
};
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
new file mode 100644
index 00000000000..02147be2b30
--- /dev/null
+++ b/sound/soc/codecs/rt5645.c
@@ -0,0 +1,2378 @@
+/*
+ * rt5645.c -- RT5645 ALSA SoC audio codec driver
+ *
+ * Copyright 2013 Realtek Semiconductor Corp.
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * 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 <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/jack.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "rl6231.h"
+#include "rt5645.h"
+
+#define RT5645_DEVICE_ID 0x6308
+
+#define RT5645_PR_RANGE_BASE (0xff + 1)
+#define RT5645_PR_SPACING 0x100
+
+#define RT5645_PR_BASE (RT5645_PR_RANGE_BASE + (0 * RT5645_PR_SPACING))
+
+static const struct regmap_range_cfg rt5645_ranges[] = {
+ {
+ .name = "PR",
+ .range_min = RT5645_PR_BASE,
+ .range_max = RT5645_PR_BASE + 0xf8,
+ .selector_reg = RT5645_PRIV_INDEX,
+ .selector_mask = 0xff,
+ .selector_shift = 0x0,
+ .window_start = RT5645_PRIV_DATA,
+ .window_len = 0x1,
+ },
+};
+
+static const struct reg_default init_list[] = {
+ {RT5645_PR_BASE + 0x3d, 0x3600},
+ {RT5645_PR_BASE + 0x1c, 0xfd20},
+ {RT5645_PR_BASE + 0x20, 0x611f},
+ {RT5645_PR_BASE + 0x21, 0x4040},
+ {RT5645_PR_BASE + 0x23, 0x0004},
+};
+#define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list)
+
+static const struct reg_default rt5645_reg[] = {
+ { 0x00, 0x0000 },
+ { 0x01, 0xc8c8 },
+ { 0x02, 0xc8c8 },
+ { 0x03, 0xc8c8 },
+ { 0x0a, 0x0002 },
+ { 0x0b, 0x2827 },
+ { 0x0c, 0xe000 },
+ { 0x0d, 0x0000 },
+ { 0x0e, 0x0000 },
+ { 0x0f, 0x0808 },
+ { 0x14, 0x3333 },
+ { 0x16, 0x4b00 },
+ { 0x18, 0x018b },
+ { 0x19, 0xafaf },
+ { 0x1a, 0xafaf },
+ { 0x1b, 0x0001 },
+ { 0x1c, 0x2f2f },
+ { 0x1d, 0x2f2f },
+ { 0x1e, 0x0000 },
+ { 0x20, 0x0000 },
+ { 0x27, 0x7060 },
+ { 0x28, 0x7070 },
+ { 0x29, 0x8080 },
+ { 0x2a, 0x5656 },
+ { 0x2b, 0x5454 },
+ { 0x2c, 0xaaa0 },
+ { 0x2f, 0x1002 },
+ { 0x31, 0x5000 },
+ { 0x32, 0x0000 },
+ { 0x33, 0x0000 },
+ { 0x34, 0x0000 },
+ { 0x35, 0x0000 },
+ { 0x3b, 0x0000 },
+ { 0x3c, 0x007f },
+ { 0x3d, 0x0000 },
+ { 0x3e, 0x007f },
+ { 0x3f, 0x0000 },
+ { 0x40, 0x001f },
+ { 0x41, 0x0000 },
+ { 0x42, 0x001f },
+ { 0x45, 0x6000 },
+ { 0x46, 0x003e },
+ { 0x47, 0x003e },
+ { 0x48, 0xf807 },
+ { 0x4a, 0x0004 },
+ { 0x4d, 0x0000 },
+ { 0x4e, 0x0000 },
+ { 0x4f, 0x01ff },
+ { 0x50, 0x0000 },
+ { 0x51, 0x0000 },
+ { 0x52, 0x01ff },
+ { 0x53, 0xf000 },
+ { 0x56, 0x0111 },
+ { 0x57, 0x0064 },
+ { 0x58, 0xef0e },
+ { 0x59, 0xf0f0 },
+ { 0x5a, 0xef0e },
+ { 0x5b, 0xf0f0 },
+ { 0x5c, 0xef0e },
+ { 0x5d, 0xf0f0 },
+ { 0x5e, 0xf000 },
+ { 0x5f, 0x0000 },
+ { 0x61, 0x0300 },
+ { 0x62, 0x0000 },
+ { 0x63, 0x00c2 },
+ { 0x64, 0x0000 },
+ { 0x65, 0x0000 },
+ { 0x66, 0x0000 },
+ { 0x6a, 0x0000 },
+ { 0x6c, 0x0aaa },
+ { 0x70, 0x8000 },
+ { 0x71, 0x8000 },
+ { 0x72, 0x8000 },
+ { 0x73, 0x7770 },
+ { 0x74, 0x3e00 },
+ { 0x75, 0x2409 },
+ { 0x76, 0x000a },
+ { 0x77, 0x0c00 },
+ { 0x78, 0x0000 },
+ { 0x80, 0x0000 },
+ { 0x81, 0x0000 },
+ { 0x82, 0x0000 },
+ { 0x83, 0x0000 },
+ { 0x84, 0x0000 },
+ { 0x85, 0x0000 },
+ { 0x8a, 0x0000 },
+ { 0x8e, 0x0004 },
+ { 0x8f, 0x1100 },
+ { 0x90, 0x0646 },
+ { 0x91, 0x0c06 },
+ { 0x93, 0x0000 },
+ { 0x94, 0x0200 },
+ { 0x95, 0x0000 },
+ { 0x9a, 0x2184 },
+ { 0x9b, 0x010a },
+ { 0x9c, 0x0aea },
+ { 0x9d, 0x000c },
+ { 0x9e, 0x0400 },
+ { 0xa0, 0xa0a8 },
+ { 0xa1, 0x0059 },
+ { 0xa2, 0x0001 },
+ { 0xae, 0x6000 },
+ { 0xaf, 0x0000 },
+ { 0xb0, 0x6000 },
+ { 0xb1, 0x0000 },
+ { 0xb2, 0x0000 },
+ { 0xb3, 0x001f },
+ { 0xb4, 0x020c },
+ { 0xb5, 0x1f00 },
+ { 0xb6, 0x0000 },
+ { 0xbb, 0x0000 },
+ { 0xbc, 0x0000 },
+ { 0xbd, 0x0000 },
+ { 0xbe, 0x0000 },
+ { 0xbf, 0x3100 },
+ { 0xc0, 0x0000 },
+ { 0xc1, 0x0000 },
+ { 0xc2, 0x0000 },
+ { 0xc3, 0x2000 },
+ { 0xcd, 0x0000 },
+ { 0xce, 0x0000 },
+ { 0xcf, 0x1813 },
+ { 0xd0, 0x0690 },
+ { 0xd1, 0x1c17 },
+ { 0xd3, 0xb320 },
+ { 0xd4, 0x0000 },
+ { 0xd6, 0x0400 },
+ { 0xd9, 0x0809 },
+ { 0xda, 0x0000 },
+ { 0xdb, 0x0003 },
+ { 0xdc, 0x0049 },
+ { 0xdd, 0x001b },
+ { 0xe6, 0x8000 },
+ { 0xe7, 0x0200 },
+ { 0xec, 0xb300 },
+ { 0xed, 0x0000 },
+ { 0xf0, 0x001f },
+ { 0xf1, 0x020c },
+ { 0xf2, 0x1f00 },
+ { 0xf3, 0x0000 },
+ { 0xf4, 0x4000 },
+ { 0xf8, 0x0000 },
+ { 0xf9, 0x0000 },
+ { 0xfa, 0x2060 },
+ { 0xfb, 0x4040 },
+ { 0xfc, 0x0000 },
+ { 0xfd, 0x0002 },
+ { 0xfe, 0x10ec },
+ { 0xff, 0x6308 },
+};
+
+static int rt5645_reset(struct snd_soc_codec *codec)
+{
+ return snd_soc_write(codec, RT5645_RESET, 0);
+}
+
+static bool rt5645_volatile_register(struct device *dev, unsigned int reg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rt5645_ranges); i++) {
+ if (reg >= rt5645_ranges[i].range_min &&
+ reg <= rt5645_ranges[i].range_max) {
+ return true;
+ }
+ }
+
+ switch (reg) {
+ case RT5645_RESET:
+ case RT5645_PRIV_DATA:
+ case RT5645_IN1_CTRL1:
+ case RT5645_IN1_CTRL2:
+ case RT5645_IN1_CTRL3:
+ case RT5645_A_JD_CTRL1:
+ case RT5645_ADC_EQ_CTRL1:
+ case RT5645_EQ_CTRL1:
+ case RT5645_ALC_CTRL_1:
+ case RT5645_IRQ_CTRL2:
+ case RT5645_IRQ_CTRL3:
+ case RT5645_INT_IRQ_ST:
+ case RT5645_IL_CMD:
+ case RT5645_VENDOR_ID:
+ case RT5645_VENDOR_ID1:
+ case RT5645_VENDOR_ID2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool rt5645_readable_register(struct device *dev, unsigned int reg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rt5645_ranges); i++) {
+ if (reg >= rt5645_ranges[i].range_min &&
+ reg <= rt5645_ranges[i].range_max) {
+ return true;
+ }
+ }
+
+ switch (reg) {
+ case RT5645_RESET:
+ case RT5645_SPK_VOL:
+ case RT5645_HP_VOL:
+ case RT5645_LOUT1:
+ case RT5645_IN1_CTRL1:
+ case RT5645_IN1_CTRL2:
+ case RT5645_IN1_CTRL3:
+ case RT5645_IN2_CTRL:
+ case RT5645_INL1_INR1_VOL:
+ case RT5645_SPK_FUNC_LIM:
+ case RT5645_ADJ_HPF_CTRL:
+ case RT5645_DAC1_DIG_VOL:
+ case RT5645_DAC2_DIG_VOL:
+ case RT5645_DAC_CTRL:
+ case RT5645_STO1_ADC_DIG_VOL:
+ case RT5645_MONO_ADC_DIG_VOL:
+ case RT5645_ADC_BST_VOL1:
+ case RT5645_ADC_BST_VOL2:
+ case RT5645_STO1_ADC_MIXER:
+ case RT5645_MONO_ADC_MIXER:
+ case RT5645_AD_DA_MIXER:
+ case RT5645_STO_DAC_MIXER:
+ case RT5645_MONO_DAC_MIXER:
+ case RT5645_DIG_MIXER:
+ case RT5645_DIG_INF1_DATA:
+ case RT5645_PDM_OUT_CTRL:
+ case RT5645_REC_L1_MIXER:
+ case RT5645_REC_L2_MIXER:
+ case RT5645_REC_R1_MIXER:
+ case RT5645_REC_R2_MIXER:
+ case RT5645_HPMIXL_CTRL:
+ case RT5645_HPOMIXL_CTRL:
+ case RT5645_HPMIXR_CTRL:
+ case RT5645_HPOMIXR_CTRL:
+ case RT5645_HPO_MIXER:
+ case RT5645_SPK_L_MIXER:
+ case RT5645_SPK_R_MIXER:
+ case RT5645_SPO_MIXER:
+ case RT5645_SPO_CLSD_RATIO:
+ case RT5645_OUT_L1_MIXER:
+ case RT5645_OUT_R1_MIXER:
+ case RT5645_OUT_L_GAIN1:
+ case RT5645_OUT_L_GAIN2:
+ case RT5645_OUT_R_GAIN1:
+ case RT5645_OUT_R_GAIN2:
+ case RT5645_LOUT_MIXER:
+ case RT5645_HAPTIC_CTRL1:
+ case RT5645_HAPTIC_CTRL2:
+ case RT5645_HAPTIC_CTRL3:
+ case RT5645_HAPTIC_CTRL4:
+ case RT5645_HAPTIC_CTRL5:
+ case RT5645_HAPTIC_CTRL6:
+ case RT5645_HAPTIC_CTRL7:
+ case RT5645_HAPTIC_CTRL8:
+ case RT5645_HAPTIC_CTRL9:
+ case RT5645_HAPTIC_CTRL10:
+ case RT5645_PWR_DIG1:
+ case RT5645_PWR_DIG2:
+ case RT5645_PWR_ANLG1:
+ case RT5645_PWR_ANLG2:
+ case RT5645_PWR_MIXER:
+ case RT5645_PWR_VOL:
+ case RT5645_PRIV_INDEX:
+ case RT5645_PRIV_DATA:
+ case RT5645_I2S1_SDP:
+ case RT5645_I2S2_SDP:
+ case RT5645_ADDA_CLK1:
+ case RT5645_ADDA_CLK2:
+ case RT5645_DMIC_CTRL1:
+ case RT5645_DMIC_CTRL2:
+ case RT5645_TDM_CTRL_1:
+ case RT5645_TDM_CTRL_2:
+ case RT5645_GLB_CLK:
+ case RT5645_PLL_CTRL1:
+ case RT5645_PLL_CTRL2:
+ case RT5645_ASRC_1:
+ case RT5645_ASRC_2:
+ case RT5645_ASRC_3:
+ case RT5645_ASRC_4:
+ case RT5645_DEPOP_M1:
+ case RT5645_DEPOP_M2:
+ case RT5645_DEPOP_M3:
+ case RT5645_MICBIAS:
+ case RT5645_A_JD_CTRL1:
+ case RT5645_VAD_CTRL4:
+ case RT5645_CLSD_OUT_CTRL:
+ case RT5645_ADC_EQ_CTRL1:
+ case RT5645_ADC_EQ_CTRL2:
+ case RT5645_EQ_CTRL1:
+ case RT5645_EQ_CTRL2:
+ case RT5645_ALC_CTRL_1:
+ case RT5645_ALC_CTRL_2:
+ case RT5645_ALC_CTRL_3:
+ case RT5645_ALC_CTRL_4:
+ case RT5645_ALC_CTRL_5:
+ case RT5645_JD_CTRL:
+ case RT5645_IRQ_CTRL1:
+ case RT5645_IRQ_CTRL2:
+ case RT5645_IRQ_CTRL3:
+ case RT5645_INT_IRQ_ST:
+ case RT5645_GPIO_CTRL1:
+ case RT5645_GPIO_CTRL2:
+ case RT5645_GPIO_CTRL3:
+ case RT5645_BASS_BACK:
+ case RT5645_MP3_PLUS1:
+ case RT5645_MP3_PLUS2:
+ case RT5645_ADJ_HPF1:
+ case RT5645_ADJ_HPF2:
+ case RT5645_HP_CALIB_AMP_DET:
+ case RT5645_SV_ZCD1:
+ case RT5645_SV_ZCD2:
+ case RT5645_IL_CMD:
+ case RT5645_IL_CMD2:
+ case RT5645_IL_CMD3:
+ case RT5645_DRC1_HL_CTRL1:
+ case RT5645_DRC2_HL_CTRL1:
+ case RT5645_ADC_MONO_HP_CTRL1:
+ case RT5645_ADC_MONO_HP_CTRL2:
+ case RT5645_DRC2_CTRL1:
+ case RT5645_DRC2_CTRL2:
+ case RT5645_DRC2_CTRL3:
+ case RT5645_DRC2_CTRL4:
+ case RT5645_DRC2_CTRL5:
+ case RT5645_JD_CTRL3:
+ case RT5645_JD_CTRL4:
+ case RT5645_GEN_CTRL1:
+ case RT5645_GEN_CTRL2:
+ case RT5645_GEN_CTRL3:
+ case RT5645_VENDOR_ID:
+ case RT5645_VENDOR_ID1:
+ case RT5645_VENDOR_ID2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
+
+/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
+static unsigned int bst_tlv[] = {
+ TLV_DB_RANGE_HEAD(7),
+ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+ 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
+ 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
+ 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
+ 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
+ 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
+};
+
+static const char * const rt5645_tdm_data_swap_select[] = {
+ "L/R", "R/L", "L/L", "R/R"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot0_1_enum,
+ RT5645_TDM_CTRL_1, 6, rt5645_tdm_data_swap_select);
+
+static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot2_3_enum,
+ RT5645_TDM_CTRL_1, 4, rt5645_tdm_data_swap_select);
+
+static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot4_5_enum,
+ RT5645_TDM_CTRL_1, 2, rt5645_tdm_data_swap_select);
+
+static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot6_7_enum,
+ RT5645_TDM_CTRL_1, 0, rt5645_tdm_data_swap_select);
+
+static const char * const rt5645_tdm_adc_data_select[] = {
+ "1/2/R", "2/1/R", "R/1/2", "R/2/1"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_sel_enum,
+ RT5645_TDM_CTRL_1, 8,
+ rt5645_tdm_adc_data_select);
+
+static const struct snd_kcontrol_new rt5645_snd_controls[] = {
+ /* Speaker Output Volume */
+ SOC_DOUBLE("Speaker Channel Switch", RT5645_SPK_VOL,
+ RT5645_VOL_L_SFT, RT5645_VOL_R_SFT, 1, 1),
+ SOC_DOUBLE_TLV("Speaker Playback Volume", RT5645_SPK_VOL,
+ RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, out_vol_tlv),
+
+ /* Headphone Output Volume */
+ SOC_DOUBLE("HP Channel Switch", RT5645_HP_VOL,
+ RT5645_VOL_L_SFT, RT5645_VOL_R_SFT, 1, 1),
+ SOC_DOUBLE_TLV("HP Playback Volume", RT5645_HP_VOL,
+ RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, out_vol_tlv),
+
+ /* OUTPUT Control */
+ SOC_DOUBLE("OUT Playback Switch", RT5645_LOUT1,
+ RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE("OUT Channel Switch", RT5645_LOUT1,
+ RT5645_VOL_L_SFT, RT5645_VOL_R_SFT, 1, 1),
+ SOC_DOUBLE_TLV("OUT Playback Volume", RT5645_LOUT1,
+ RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, out_vol_tlv),
+
+ /* DAC Digital Volume */
+ SOC_DOUBLE("DAC2 Playback Switch", RT5645_DAC_CTRL,
+ RT5645_M_DAC_L2_VOL_SFT, RT5645_M_DAC_R2_VOL_SFT, 1, 1),
+ SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5645_DAC1_DIG_VOL,
+ RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 175, 0, dac_vol_tlv),
+ SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5645_DAC2_DIG_VOL,
+ RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 175, 0, dac_vol_tlv),
+
+ /* IN1/IN2 Control */
+ SOC_SINGLE_TLV("IN1 Boost", RT5645_IN1_CTRL1,
+ RT5645_BST_SFT1, 8, 0, bst_tlv),
+ SOC_SINGLE_TLV("IN2 Boost", RT5645_IN2_CTRL,
+ RT5645_BST_SFT2, 8, 0, bst_tlv),
+
+ /* INL/INR Volume Control */
+ SOC_DOUBLE_TLV("IN Capture Volume", RT5645_INL1_INR1_VOL,
+ RT5645_INL_VOL_SFT, RT5645_INR_VOL_SFT, 31, 1, in_vol_tlv),
+
+ /* ADC Digital Volume Control */
+ SOC_DOUBLE("ADC Capture Switch", RT5645_STO1_ADC_DIG_VOL,
+ RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE_TLV("ADC Capture Volume", RT5645_STO1_ADC_DIG_VOL,
+ RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 127, 0, adc_vol_tlv),
+ SOC_DOUBLE("Mono ADC Capture Switch", RT5645_MONO_ADC_DIG_VOL,
+ RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5645_MONO_ADC_DIG_VOL,
+ RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 127, 0, adc_vol_tlv),
+
+ /* ADC Boost Volume Control */
+ SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5645_ADC_BST_VOL1,
+ RT5645_STO1_ADC_L_BST_SFT, RT5645_STO1_ADC_R_BST_SFT, 3, 0,
+ adc_bst_tlv),
+ SOC_DOUBLE_TLV("STO2 ADC Boost Gain", RT5645_ADC_BST_VOL1,
+ RT5645_STO2_ADC_L_BST_SFT, RT5645_STO2_ADC_R_BST_SFT, 3, 0,
+ adc_bst_tlv),
+
+ /* I2S2 function select */
+ SOC_SINGLE("I2S2 Func Switch", RT5645_GPIO_CTRL1, RT5645_I2S2_SEL_SFT,
+ 1, 1),
+
+ /* TDM */
+ SOC_ENUM("TDM Adc Slot0 1 Data", rt5645_tdm_adc_slot0_1_enum),
+ SOC_ENUM("TDM Adc Slot2 3 Data", rt5645_tdm_adc_slot2_3_enum),
+ SOC_ENUM("TDM Adc Slot4 5 Data", rt5645_tdm_adc_slot4_5_enum),
+ SOC_ENUM("TDM Adc Slot6 7 Data", rt5645_tdm_adc_slot6_7_enum),
+ SOC_ENUM("TDM IF1 ADC DATA Sel", rt5645_tdm_adc_sel_enum),
+ SOC_SINGLE("TDM IF1_DAC1_L Sel", RT5645_TDM_CTRL_3, 12, 7, 0),
+ SOC_SINGLE("TDM IF1_DAC1_R Sel", RT5645_TDM_CTRL_3, 8, 7, 0),
+ SOC_SINGLE("TDM IF1_DAC2_L Sel", RT5645_TDM_CTRL_3, 4, 7, 0),
+ SOC_SINGLE("TDM IF1_DAC2_R Sel", RT5645_TDM_CTRL_3, 0, 7, 0),
+};
+
+/**
+ * set_dmic_clk - Set parameter of dmic.
+ *
+ * @w: DAPM widget.
+ * @kcontrol: The kcontrol of this widget.
+ * @event: Event id.
+ *
+ */
+static int set_dmic_clk(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+ int idx = -EINVAL;
+
+ idx = rl6231_calc_dmic_clk(rt5645->sysclk);
+
+ if (idx < 0)
+ dev_err(codec->dev, "Failed to set DMIC clock\n");
+ else
+ snd_soc_update_bits(codec, RT5645_DMIC_CTRL1,
+ RT5645_DMIC_CLK_MASK, idx << RT5645_DMIC_CLK_SFT);
+ return idx;
+}
+
+static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int val;
+
+ val = snd_soc_read(source->codec, RT5645_GLB_CLK);
+ val &= RT5645_SCLK_SRC_MASK;
+ if (val == RT5645_SCLK_SRC_PLL1)
+ return 1;
+ else
+ return 0;
+}
+
+/* Digital Mixer */
+static const struct snd_kcontrol_new rt5645_sto1_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER,
+ RT5645_M_ADC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5645_STO1_ADC_MIXER,
+ RT5645_M_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_sto1_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER,
+ RT5645_M_ADC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5645_STO1_ADC_MIXER,
+ RT5645_M_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_mono_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5645_MONO_ADC_MIXER,
+ RT5645_M_MONO_ADC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5645_MONO_ADC_MIXER,
+ RT5645_M_MONO_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_mono_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5645_MONO_ADC_MIXER,
+ RT5645_M_MONO_ADC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5645_MONO_ADC_MIXER,
+ RT5645_M_MONO_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("Stereo ADC Switch", RT5645_AD_DA_MIXER,
+ RT5645_M_ADCMIX_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC1 Switch", RT5645_AD_DA_MIXER,
+ RT5645_M_DAC1_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("Stereo ADC Switch", RT5645_AD_DA_MIXER,
+ RT5645_M_ADCMIX_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC1 Switch", RT5645_AD_DA_MIXER,
+ RT5645_M_DAC1_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_sto_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_STO_DAC_MIXER,
+ RT5645_M_DAC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_STO_DAC_MIXER,
+ RT5645_M_DAC_L2_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_STO_DAC_MIXER,
+ RT5645_M_DAC_R1_STO_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_sto_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_STO_DAC_MIXER,
+ RT5645_M_DAC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_STO_DAC_MIXER,
+ RT5645_M_DAC_R2_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_STO_DAC_MIXER,
+ RT5645_M_DAC_L1_STO_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_mono_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_MONO_DAC_MIXER,
+ RT5645_M_DAC_L1_MONO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_MONO_DAC_MIXER,
+ RT5645_M_DAC_L2_MONO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_MONO_DAC_MIXER,
+ RT5645_M_DAC_R2_MONO_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_mono_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_MONO_DAC_MIXER,
+ RT5645_M_DAC_R1_MONO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_MONO_DAC_MIXER,
+ RT5645_M_DAC_R2_MONO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_MONO_DAC_MIXER,
+ RT5645_M_DAC_L2_MONO_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_dig_l_mix[] = {
+ SOC_DAPM_SINGLE("Sto DAC Mix L Switch", RT5645_DIG_MIXER,
+ RT5645_M_STO_L_DAC_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_DIG_MIXER,
+ RT5645_M_DAC_L2_DAC_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_DIG_MIXER,
+ RT5645_M_DAC_R2_DAC_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_dig_r_mix[] = {
+ SOC_DAPM_SINGLE("Sto DAC Mix R Switch", RT5645_DIG_MIXER,
+ RT5645_M_STO_R_DAC_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_DIG_MIXER,
+ RT5645_M_DAC_R2_DAC_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_DIG_MIXER,
+ RT5645_M_DAC_L2_DAC_R_SFT, 1, 1),
+};
+
+/* Analog Input Mixer */
+static const struct snd_kcontrol_new rt5645_rec_l_mix[] = {
+ SOC_DAPM_SINGLE("HPOL Switch", RT5645_REC_L2_MIXER,
+ RT5645_M_HP_L_RM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL Switch", RT5645_REC_L2_MIXER,
+ RT5645_M_IN_L_RM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5645_REC_L2_MIXER,
+ RT5645_M_BST2_RM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5645_REC_L2_MIXER,
+ RT5645_M_BST1_RM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUT MIXL Switch", RT5645_REC_L2_MIXER,
+ RT5645_M_OM_L_RM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_rec_r_mix[] = {
+ SOC_DAPM_SINGLE("HPOR Switch", RT5645_REC_R2_MIXER,
+ RT5645_M_HP_R_RM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR Switch", RT5645_REC_R2_MIXER,
+ RT5645_M_IN_R_RM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5645_REC_R2_MIXER,
+ RT5645_M_BST2_RM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5645_REC_R2_MIXER,
+ RT5645_M_BST1_RM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUT MIXR Switch", RT5645_REC_R2_MIXER,
+ RT5645_M_OM_R_RM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_spk_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_SPK_L_MIXER,
+ RT5645_M_DAC_L1_SM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_SPK_L_MIXER,
+ RT5645_M_DAC_L2_SM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL Switch", RT5645_SPK_L_MIXER,
+ RT5645_M_IN_L_SM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5645_SPK_L_MIXER,
+ RT5645_M_BST1_L_SM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_spk_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_SPK_R_MIXER,
+ RT5645_M_DAC_R1_SM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_SPK_R_MIXER,
+ RT5645_M_DAC_R2_SM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR Switch", RT5645_SPK_R_MIXER,
+ RT5645_M_IN_R_SM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5645_SPK_R_MIXER,
+ RT5645_M_BST2_R_SM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_out_l_mix[] = {
+ SOC_DAPM_SINGLE("BST1 Switch", RT5645_OUT_L1_MIXER,
+ RT5645_M_BST1_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL Switch", RT5645_OUT_L1_MIXER,
+ RT5645_M_IN_L_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_OUT_L1_MIXER,
+ RT5645_M_DAC_L2_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_OUT_L1_MIXER,
+ RT5645_M_DAC_L1_OM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_out_r_mix[] = {
+ SOC_DAPM_SINGLE("BST2 Switch", RT5645_OUT_R1_MIXER,
+ RT5645_M_BST2_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR Switch", RT5645_OUT_R1_MIXER,
+ RT5645_M_IN_R_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_OUT_R1_MIXER,
+ RT5645_M_DAC_R2_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_OUT_R1_MIXER,
+ RT5645_M_DAC_R1_OM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_spo_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_SPO_MIXER,
+ RT5645_M_DAC_R1_SPM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_SPO_MIXER,
+ RT5645_M_DAC_L1_SPM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("SPKVOL R Switch", RT5645_SPO_MIXER,
+ RT5645_M_SV_R_SPM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("SPKVOL L Switch", RT5645_SPO_MIXER,
+ RT5645_M_SV_L_SPM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_spo_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_SPO_MIXER,
+ RT5645_M_DAC_R1_SPM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("SPKVOL R Switch", RT5645_SPO_MIXER,
+ RT5645_M_SV_R_SPM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_hpo_mix[] = {
+ SOC_DAPM_SINGLE("DAC1 Switch", RT5645_HPO_MIXER,
+ RT5645_M_DAC1_HM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("HPVOL Switch", RT5645_HPO_MIXER,
+ RT5645_M_HPVOL_HM_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_hpvoll_mix[] = {
+ SOC_DAPM_SINGLE("DAC1 Switch", RT5645_HPOMIXL_CTRL,
+ RT5645_M_DAC1_HV_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC2 Switch", RT5645_HPOMIXL_CTRL,
+ RT5645_M_DAC2_HV_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL Switch", RT5645_HPOMIXL_CTRL,
+ RT5645_M_IN_HV_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5645_HPOMIXL_CTRL,
+ RT5645_M_BST1_HV_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_hpvolr_mix[] = {
+ SOC_DAPM_SINGLE("DAC1 Switch", RT5645_HPOMIXR_CTRL,
+ RT5645_M_DAC1_HV_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC2 Switch", RT5645_HPOMIXR_CTRL,
+ RT5645_M_DAC2_HV_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR Switch", RT5645_HPOMIXR_CTRL,
+ RT5645_M_IN_HV_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5645_HPOMIXR_CTRL,
+ RT5645_M_BST2_HV_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_lout_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_LOUT_MIXER,
+ RT5645_M_DAC_L1_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_LOUT_MIXER,
+ RT5645_M_DAC_R1_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTMIX L Switch", RT5645_LOUT_MIXER,
+ RT5645_M_OV_L_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTMIX R Switch", RT5645_LOUT_MIXER,
+ RT5645_M_OV_R_LM_SFT, 1, 1),
+};
+
+/*DAC1 L/R source*/ /* MX-29 [9:8] [11:10] */
+static const char * const rt5645_dac1_src[] = {
+ "IF1 DAC", "IF2 DAC", "IF3 DAC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_dac1l_enum, RT5645_AD_DA_MIXER,
+ RT5645_DAC1_L_SEL_SFT, rt5645_dac1_src);
+
+static const struct snd_kcontrol_new rt5645_dac1l_mux =
+ SOC_DAPM_ENUM("DAC1 L source", rt5645_dac1l_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_dac1r_enum, RT5645_AD_DA_MIXER,
+ RT5645_DAC1_R_SEL_SFT, rt5645_dac1_src);
+
+static const struct snd_kcontrol_new rt5645_dac1r_mux =
+ SOC_DAPM_ENUM("DAC1 R source", rt5645_dac1r_enum);
+
+/*DAC2 L/R source*/ /* MX-1B [6:4] [2:0] */
+static const char * const rt5645_dac12_src[] = {
+ "IF1 DAC", "IF2 DAC", "IF3 DAC", "Mono ADC", "VAD_ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_dac2l_enum, RT5645_DAC_CTRL,
+ RT5645_DAC2_L_SEL_SFT, rt5645_dac12_src);
+
+static const struct snd_kcontrol_new rt5645_dac_l2_mux =
+ SOC_DAPM_ENUM("DAC2 L source", rt5645_dac2l_enum);
+
+static const char * const rt5645_dacr2_src[] = {
+ "IF1 DAC", "IF2 DAC", "IF3 DAC", "Mono ADC", "Haptic"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_dac2r_enum, RT5645_DAC_CTRL,
+ RT5645_DAC2_R_SEL_SFT, rt5645_dacr2_src);
+
+static const struct snd_kcontrol_new rt5645_dac_r2_mux =
+ SOC_DAPM_ENUM("DAC2 R source", rt5645_dac2r_enum);
+
+
+/* INL/R source */
+static const char * const rt5645_inl_src[] = {
+ "IN2P", "MonoP"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_inl_enum, RT5645_INL1_INR1_VOL,
+ RT5645_INL_SEL_SFT, rt5645_inl_src);
+
+static const struct snd_kcontrol_new rt5645_inl_mux =
+ SOC_DAPM_ENUM("INL source", rt5645_inl_enum);
+
+static const char * const rt5645_inr_src[] = {
+ "IN2N", "MonoN"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_inr_enum, RT5645_INL1_INR1_VOL,
+ RT5645_INR_SEL_SFT, rt5645_inr_src);
+
+static const struct snd_kcontrol_new rt5645_inr_mux =
+ SOC_DAPM_ENUM("INR source", rt5645_inr_enum);
+
+/* Stereo1 ADC source */
+/* MX-27 [12] */
+static const char * const rt5645_stereo_adc1_src[] = {
+ "DAC MIX", "ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_stereo1_adc1_enum, RT5645_STO1_ADC_MIXER,
+ RT5645_ADC_1_SRC_SFT, rt5645_stereo_adc1_src);
+
+static const struct snd_kcontrol_new rt5645_sto_adc1_mux =
+ SOC_DAPM_ENUM("Stereo1 ADC1 Mux", rt5645_stereo1_adc1_enum);
+
+/* MX-27 [11] */
+static const char * const rt5645_stereo_adc2_src[] = {
+ "DAC MIX", "DMIC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_stereo1_adc2_enum, RT5645_STO1_ADC_MIXER,
+ RT5645_ADC_2_SRC_SFT, rt5645_stereo_adc2_src);
+
+static const struct snd_kcontrol_new rt5645_sto_adc2_mux =
+ SOC_DAPM_ENUM("Stereo1 ADC2 Mux", rt5645_stereo1_adc2_enum);
+
+/* MX-27 [8] */
+static const char * const rt5645_stereo_dmic_src[] = {
+ "DMIC1", "DMIC2"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_stereo1_dmic_enum, RT5645_STO1_ADC_MIXER,
+ RT5645_DMIC_SRC_SFT, rt5645_stereo_dmic_src);
+
+static const struct snd_kcontrol_new rt5645_sto1_dmic_mux =
+ SOC_DAPM_ENUM("Stereo1 DMIC source", rt5645_stereo1_dmic_enum);
+
+/* Mono ADC source */
+/* MX-28 [12] */
+static const char * const rt5645_mono_adc_l1_src[] = {
+ "Mono DAC MIXL", "ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_mono_adc_l1_enum, RT5645_MONO_ADC_MIXER,
+ RT5645_MONO_ADC_L1_SRC_SFT, rt5645_mono_adc_l1_src);
+
+static const struct snd_kcontrol_new rt5645_mono_adc_l1_mux =
+ SOC_DAPM_ENUM("Mono ADC1 left source", rt5645_mono_adc_l1_enum);
+/* MX-28 [11] */
+static const char * const rt5645_mono_adc_l2_src[] = {
+ "Mono DAC MIXL", "DMIC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_mono_adc_l2_enum, RT5645_MONO_ADC_MIXER,
+ RT5645_MONO_ADC_L2_SRC_SFT, rt5645_mono_adc_l2_src);
+
+static const struct snd_kcontrol_new rt5645_mono_adc_l2_mux =
+ SOC_DAPM_ENUM("Mono ADC2 left source", rt5645_mono_adc_l2_enum);
+
+/* MX-28 [8] */
+static const char * const rt5645_mono_dmic_src[] = {
+ "DMIC1", "DMIC2"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_mono_dmic_l_enum, RT5645_MONO_ADC_MIXER,
+ RT5645_MONO_DMIC_L_SRC_SFT, rt5645_mono_dmic_src);
+
+static const struct snd_kcontrol_new rt5645_mono_dmic_l_mux =
+ SOC_DAPM_ENUM("Mono DMIC left source", rt5645_mono_dmic_l_enum);
+/* MX-28 [1:0] */
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_mono_dmic_r_enum, RT5645_MONO_ADC_MIXER,
+ RT5645_MONO_DMIC_R_SRC_SFT, rt5645_mono_dmic_src);
+
+static const struct snd_kcontrol_new rt5645_mono_dmic_r_mux =
+ SOC_DAPM_ENUM("Mono DMIC Right source", rt5645_mono_dmic_r_enum);
+/* MX-28 [4] */
+static const char * const rt5645_mono_adc_r1_src[] = {
+ "Mono DAC MIXR", "ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_mono_adc_r1_enum, RT5645_MONO_ADC_MIXER,
+ RT5645_MONO_ADC_R1_SRC_SFT, rt5645_mono_adc_r1_src);
+
+static const struct snd_kcontrol_new rt5645_mono_adc_r1_mux =
+ SOC_DAPM_ENUM("Mono ADC1 right source", rt5645_mono_adc_r1_enum);
+/* MX-28 [3] */
+static const char * const rt5645_mono_adc_r2_src[] = {
+ "Mono DAC MIXR", "DMIC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_mono_adc_r2_enum, RT5645_MONO_ADC_MIXER,
+ RT5645_MONO_ADC_R2_SRC_SFT, rt5645_mono_adc_r2_src);
+
+static const struct snd_kcontrol_new rt5645_mono_adc_r2_mux =
+ SOC_DAPM_ENUM("Mono ADC2 right source", rt5645_mono_adc_r2_enum);
+
+/* MX-77 [9:8] */
+static const char * const rt5645_if1_adc_in_src[] = {
+ "IF_ADC1", "IF_ADC2", "VAD_ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_if1_adc_in_enum, RT5645_TDM_CTRL_1,
+ RT5645_IF1_ADC_IN_SFT, rt5645_if1_adc_in_src);
+
+static const struct snd_kcontrol_new rt5645_if1_adc_in_mux =
+ SOC_DAPM_ENUM("IF1 ADC IN source", rt5645_if1_adc_in_enum);
+
+/* MX-2F [13:12] */
+static const char * const rt5645_if2_adc_in_src[] = {
+ "IF_ADC1", "IF_ADC2", "VAD_ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_if2_adc_in_enum, RT5645_DIG_INF1_DATA,
+ RT5645_IF2_ADC_IN_SFT, rt5645_if2_adc_in_src);
+
+static const struct snd_kcontrol_new rt5645_if2_adc_in_mux =
+ SOC_DAPM_ENUM("IF2 ADC IN source", rt5645_if2_adc_in_enum);
+
+/* MX-2F [1:0] */
+static const char * const rt5645_if3_adc_in_src[] = {
+ "IF_ADC1", "IF_ADC2", "VAD_ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_if3_adc_in_enum, RT5645_DIG_INF1_DATA,
+ RT5645_IF3_ADC_IN_SFT, rt5645_if3_adc_in_src);
+
+static const struct snd_kcontrol_new rt5645_if3_adc_in_mux =
+ SOC_DAPM_ENUM("IF3 ADC IN source", rt5645_if3_adc_in_enum);
+
+/* MX-31 [15] [13] [11] [9] */
+static const char * const rt5645_pdm_src[] = {
+ "Mono DAC", "Stereo DAC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_pdm1_l_enum, RT5645_PDM_OUT_CTRL,
+ RT5645_PDM1_L_SFT, rt5645_pdm_src);
+
+static const struct snd_kcontrol_new rt5645_pdm1_l_mux =
+ SOC_DAPM_ENUM("PDM1 L source", rt5645_pdm1_l_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_pdm1_r_enum, RT5645_PDM_OUT_CTRL,
+ RT5645_PDM1_R_SFT, rt5645_pdm_src);
+
+static const struct snd_kcontrol_new rt5645_pdm1_r_mux =
+ SOC_DAPM_ENUM("PDM1 R source", rt5645_pdm1_r_enum);
+
+/* MX-9D [9:8] */
+static const char * const rt5645_vad_adc_src[] = {
+ "Sto1 ADC L", "Mono ADC L", "Mono ADC R"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5645_vad_adc_enum, RT5645_VAD_CTRL4,
+ RT5645_VAD_SEL_SFT, rt5645_vad_adc_src);
+
+static const struct snd_kcontrol_new rt5645_vad_adc_mux =
+ SOC_DAPM_ENUM("VAD ADC source", rt5645_vad_adc_enum);
+
+static const struct snd_kcontrol_new spk_l_vol_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5645_SPK_VOL,
+ RT5645_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new spk_r_vol_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5645_SPK_VOL,
+ RT5645_R_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hp_l_vol_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5645_HP_VOL,
+ RT5645_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hp_r_vol_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5645_HP_VOL,
+ RT5645_R_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new pdm1_l_vol_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5645_PDM_OUT_CTRL,
+ RT5645_M_PDM1_L, 1, 1);
+
+static const struct snd_kcontrol_new pdm1_r_vol_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5645_PDM_OUT_CTRL,
+ RT5645_M_PDM1_R, 1, 1);
+
+static void hp_amp_power(struct snd_soc_codec *codec, int on)
+{
+ static int hp_amp_power_count;
+ struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+
+ if (on) {
+ if (hp_amp_power_count <= 0) {
+ /* depop parameters */
+ snd_soc_update_bits(codec, RT5645_DEPOP_M2,
+ RT5645_DEPOP_MASK, RT5645_DEPOP_MAN);
+ snd_soc_write(codec, RT5645_DEPOP_M1, 0x000d);
+ regmap_write(rt5645->regmap, RT5645_PR_BASE +
+ RT5645_HP_DCC_INT1, 0x9f01);
+ mdelay(150);
+ /* headphone amp power on */
+ snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+ RT5645_PWR_FV1 | RT5645_PWR_FV2 , 0);
+ snd_soc_update_bits(codec, RT5645_PWR_VOL,
+ RT5645_PWR_HV_L | RT5645_PWR_HV_R,
+ RT5645_PWR_HV_L | RT5645_PWR_HV_R);
+ snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+ RT5645_PWR_HP_L | RT5645_PWR_HP_R |
+ RT5645_PWR_HA,
+ RT5645_PWR_HP_L | RT5645_PWR_HP_R |
+ RT5645_PWR_HA);
+ mdelay(5);
+ snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+ RT5645_PWR_FV1 | RT5645_PWR_FV2,
+ RT5645_PWR_FV1 | RT5645_PWR_FV2);
+
+ snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+ RT5645_HP_CO_MASK | RT5645_HP_SG_MASK,
+ RT5645_HP_CO_EN | RT5645_HP_SG_EN);
+ regmap_write(rt5645->regmap, RT5645_PR_BASE +
+ 0x14, 0x1aaa);
+ regmap_write(rt5645->regmap, RT5645_PR_BASE +
+ 0x24, 0x0430);
+ }
+ hp_amp_power_count++;
+ } else {
+ hp_amp_power_count--;
+ if (hp_amp_power_count <= 0) {
+ snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+ RT5645_HP_SG_MASK | RT5645_HP_L_SMT_MASK |
+ RT5645_HP_R_SMT_MASK, RT5645_HP_SG_DIS |
+ RT5645_HP_L_SMT_DIS | RT5645_HP_R_SMT_DIS);
+ /* headphone amp power down */
+ snd_soc_write(codec, RT5645_DEPOP_M1, 0x0000);
+ snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+ RT5645_PWR_HP_L | RT5645_PWR_HP_R |
+ RT5645_PWR_HA, 0);
+ }
+ }
+}
+
+static int rt5645_hp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ hp_amp_power(codec, 1);
+ /* headphone unmute sequence */
+ snd_soc_update_bits(codec, RT5645_DEPOP_M3, RT5645_CP_FQ1_MASK |
+ RT5645_CP_FQ2_MASK | RT5645_CP_FQ3_MASK,
+ (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ1_SFT) |
+ (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) |
+ (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ3_SFT));
+ regmap_write(rt5645->regmap,
+ RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00);
+ snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+ RT5645_SMT_TRIG_MASK, RT5645_SMT_TRIG_EN);
+ snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+ RT5645_RSTN_MASK, RT5645_RSTN_EN);
+ snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+ RT5645_RSTN_MASK | RT5645_HP_L_SMT_MASK |
+ RT5645_HP_R_SMT_MASK, RT5645_RSTN_DIS |
+ RT5645_HP_L_SMT_EN | RT5645_HP_R_SMT_EN);
+ msleep(40);
+ snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+ RT5645_HP_SG_MASK | RT5645_HP_L_SMT_MASK |
+ RT5645_HP_R_SMT_MASK, RT5645_HP_SG_DIS |
+ RT5645_HP_L_SMT_DIS | RT5645_HP_R_SMT_DIS);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ /* headphone mute sequence */
+ snd_soc_update_bits(codec, RT5645_DEPOP_M3,
+ RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK |
+ RT5645_CP_FQ3_MASK,
+ (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ1_SFT) |
+ (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) |
+ (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ3_SFT));
+ regmap_write(rt5645->regmap,
+ RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00);
+ snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+ RT5645_HP_SG_MASK, RT5645_HP_SG_EN);
+ snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+ RT5645_RSTP_MASK, RT5645_RSTP_EN);
+ snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+ RT5645_RSTP_MASK | RT5645_HP_L_SMT_MASK |
+ RT5645_HP_R_SMT_MASK, RT5645_RSTP_DIS |
+ RT5645_HP_L_SMT_EN | RT5645_HP_R_SMT_EN);
+ msleep(30);
+ hp_amp_power(codec, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5645_spk_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, RT5645_PWR_DIG1,
+ RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
+ RT5645_PWR_CLS_D_L,
+ RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
+ RT5645_PWR_CLS_D_L);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, RT5645_PWR_DIG1,
+ RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
+ RT5645_PWR_CLS_D_L, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5645_lout_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ hp_amp_power(codec, 1);
+ snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+ RT5645_PWR_LM, RT5645_PWR_LM);
+ snd_soc_update_bits(codec, RT5645_LOUT1,
+ RT5645_L_MUTE | RT5645_R_MUTE, 0);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, RT5645_LOUT1,
+ RT5645_L_MUTE | RT5645_R_MUTE,
+ RT5645_L_MUTE | RT5645_R_MUTE);
+ snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+ RT5645_PWR_LM, 0);
+ hp_amp_power(codec, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5645_bst2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, RT5645_PWR_ANLG2,
+ RT5645_PWR_BST2_P, RT5645_PWR_BST2_P);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, RT5645_PWR_ANLG2,
+ RT5645_PWR_BST2_P, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("LDO2", RT5645_PWR_MIXER,
+ RT5645_PWR_LDO2_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("PLL1", RT5645_PWR_ANLG2,
+ RT5645_PWR_PLL_BIT, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("JD Power", RT5645_PWR_ANLG2,
+ RT5645_PWR_JD1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5645_PWR_VOL,
+ RT5645_PWR_MIC_DET_BIT, 0, NULL, 0),
+
+ /* Input Side */
+ /* micbias */
+ SND_SOC_DAPM_MICBIAS("micbias1", RT5645_PWR_ANLG2,
+ RT5645_PWR_MB1_BIT, 0),
+ SND_SOC_DAPM_MICBIAS("micbias2", RT5645_PWR_ANLG2,
+ RT5645_PWR_MB2_BIT, 0),
+ /* Input Lines */
+ SND_SOC_DAPM_INPUT("DMIC L1"),
+ SND_SOC_DAPM_INPUT("DMIC R1"),
+ SND_SOC_DAPM_INPUT("DMIC L2"),
+ SND_SOC_DAPM_INPUT("DMIC R2"),
+
+ SND_SOC_DAPM_INPUT("IN1P"),
+ SND_SOC_DAPM_INPUT("IN1N"),
+ SND_SOC_DAPM_INPUT("IN2P"),
+ SND_SOC_DAPM_INPUT("IN2N"),
+
+ SND_SOC_DAPM_INPUT("Haptic Generator"),
+
+ SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0,
+ set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5645_DMIC_CTRL1,
+ RT5645_DMIC_1_EN_SFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5645_DMIC_CTRL1,
+ RT5645_DMIC_2_EN_SFT, 0, NULL, 0),
+ /* Boost */
+ SND_SOC_DAPM_PGA("BST1", RT5645_PWR_ANLG2,
+ RT5645_PWR_BST1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA_E("BST2", RT5645_PWR_ANLG2,
+ RT5645_PWR_BST2_BIT, 0, NULL, 0, rt5645_bst2_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ /* Input Volume */
+ SND_SOC_DAPM_PGA("INL VOL", RT5645_PWR_VOL,
+ RT5645_PWR_IN_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INR VOL", RT5645_PWR_VOL,
+ RT5645_PWR_IN_R_BIT, 0, NULL, 0),
+ /* REC Mixer */
+ SND_SOC_DAPM_MIXER("RECMIXL", RT5645_PWR_MIXER, RT5645_PWR_RM_L_BIT,
+ 0, rt5645_rec_l_mix, ARRAY_SIZE(rt5645_rec_l_mix)),
+ SND_SOC_DAPM_MIXER("RECMIXR", RT5645_PWR_MIXER, RT5645_PWR_RM_R_BIT,
+ 0, rt5645_rec_r_mix, ARRAY_SIZE(rt5645_rec_r_mix)),
+ /* ADCs */
+ SND_SOC_DAPM_ADC("ADC L", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_ADC("ADC R", NULL, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_SUPPLY("ADC L power", RT5645_PWR_DIG1,
+ RT5645_PWR_ADC_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("ADC R power", RT5645_PWR_DIG1,
+ RT5645_PWR_ADC_R_BIT, 0, NULL, 0),
+
+ /* ADC Mux */
+ SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_sto1_dmic_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC L2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_sto_adc2_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC R2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_sto_adc2_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC L1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_sto_adc1_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC R1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_sto_adc1_mux),
+ SND_SOC_DAPM_MUX("Mono DMIC L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_mono_dmic_l_mux),
+ SND_SOC_DAPM_MUX("Mono DMIC R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_mono_dmic_r_mux),
+ SND_SOC_DAPM_MUX("Mono ADC L2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_mono_adc_l2_mux),
+ SND_SOC_DAPM_MUX("Mono ADC L1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_mono_adc_l1_mux),
+ SND_SOC_DAPM_MUX("Mono ADC R1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_mono_adc_r1_mux),
+ SND_SOC_DAPM_MUX("Mono ADC R2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_mono_adc_r2_mux),
+ /* ADC Mixer */
+
+ SND_SOC_DAPM_SUPPLY_S("adc stereo1 filter", 1, RT5645_PWR_DIG2,
+ RT5645_PWR_ADC_S1F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("adc stereo2 filter", 1, RT5645_PWR_DIG2,
+ RT5645_PWR_ADC_S2F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER_E("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5645_sto1_adc_l_mix, ARRAY_SIZE(rt5645_sto1_adc_l_mix),
+ NULL, 0),
+ SND_SOC_DAPM_MIXER_E("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5645_sto1_adc_r_mix, ARRAY_SIZE(rt5645_sto1_adc_r_mix),
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("adc mono left filter", 1, RT5645_PWR_DIG2,
+ RT5645_PWR_ADC_MF_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER_E("Mono ADC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5645_mono_adc_l_mix, ARRAY_SIZE(rt5645_mono_adc_l_mix),
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("adc mono right filter", 1, RT5645_PWR_DIG2,
+ RT5645_PWR_ADC_MF_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER_E("Mono ADC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5645_mono_adc_r_mix, ARRAY_SIZE(rt5645_mono_adc_r_mix),
+ NULL, 0),
+
+ /* ADC PGA */
+ SND_SOC_DAPM_PGA("Stereo1 ADC MIXL", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo1 ADC MIXR", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Sto2 ADC LR MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("VAD_ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* IF1 2 Mux */
+ SND_SOC_DAPM_MUX("IF1 ADC Mux", SND_SOC_NOPM,
+ 0, 0, &rt5645_if1_adc_in_mux),
+ SND_SOC_DAPM_MUX("IF2 ADC Mux", SND_SOC_NOPM,
+ 0, 0, &rt5645_if2_adc_in_mux),
+
+ /* Digital Interface */
+ SND_SOC_DAPM_SUPPLY("I2S1", RT5645_PWR_DIG1,
+ RT5645_PWR_I2S1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC2 L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC2 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("I2S2", RT5645_PWR_DIG1,
+ RT5645_PWR_I2S2_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Digital Interface Select */
+ SND_SOC_DAPM_MUX("VAD ADC Mux", SND_SOC_NOPM,
+ 0, 0, &rt5645_vad_adc_mux),
+
+ /* Audio Interface */
+ SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+
+ /* Output Side */
+ /* DAC mixer before sound effect */
+ SND_SOC_DAPM_MIXER("DAC1 MIXL", SND_SOC_NOPM, 0, 0,
+ rt5645_dac_l_mix, ARRAY_SIZE(rt5645_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("DAC1 MIXR", SND_SOC_NOPM, 0, 0,
+ rt5645_dac_r_mix, ARRAY_SIZE(rt5645_dac_r_mix)),
+
+ /* DAC2 channel Mux */
+ SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0, &rt5645_dac_l2_mux),
+ SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0, &rt5645_dac_r2_mux),
+ SND_SOC_DAPM_PGA("DAC L2 Volume", RT5645_PWR_DIG1,
+ RT5645_PWR_DAC_L2_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("DAC R2 Volume", RT5645_PWR_DIG1,
+ RT5645_PWR_DAC_R2_BIT, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("DAC1 L Mux", SND_SOC_NOPM, 0, 0, &rt5645_dac1l_mux),
+ SND_SOC_DAPM_MUX("DAC1 R Mux", SND_SOC_NOPM, 0, 0, &rt5645_dac1r_mux),
+
+ /* DAC Mixer */
+ SND_SOC_DAPM_SUPPLY_S("dac stereo1 filter", 1, RT5645_PWR_DIG2,
+ RT5645_PWR_DAC_S1F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("dac mono left filter", 1, RT5645_PWR_DIG2,
+ RT5645_PWR_DAC_MF_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("dac mono right filter", 1, RT5645_PWR_DIG2,
+ RT5645_PWR_DAC_MF_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5645_sto_dac_l_mix, ARRAY_SIZE(rt5645_sto_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5645_sto_dac_r_mix, ARRAY_SIZE(rt5645_sto_dac_r_mix)),
+ SND_SOC_DAPM_MIXER("Mono DAC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5645_mono_dac_l_mix, ARRAY_SIZE(rt5645_mono_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("Mono DAC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5645_mono_dac_r_mix, ARRAY_SIZE(rt5645_mono_dac_r_mix)),
+ SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5645_dig_l_mix, ARRAY_SIZE(rt5645_dig_l_mix)),
+ SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5645_dig_r_mix, ARRAY_SIZE(rt5645_dig_r_mix)),
+
+ /* DACs */
+ SND_SOC_DAPM_DAC("DAC L1", NULL, RT5645_PWR_DIG1, RT5645_PWR_DAC_L1_BIT,
+ 0),
+ SND_SOC_DAPM_DAC("DAC L2", NULL, RT5645_PWR_DIG1, RT5645_PWR_DAC_L2_BIT,
+ 0),
+ SND_SOC_DAPM_DAC("DAC R1", NULL, RT5645_PWR_DIG1, RT5645_PWR_DAC_R1_BIT,
+ 0),
+ SND_SOC_DAPM_DAC("DAC R2", NULL, RT5645_PWR_DIG1, RT5645_PWR_DAC_R2_BIT,
+ 0),
+ /* OUT Mixer */
+ SND_SOC_DAPM_MIXER("SPK MIXL", RT5645_PWR_MIXER, RT5645_PWR_SM_L_BIT,
+ 0, rt5645_spk_l_mix, ARRAY_SIZE(rt5645_spk_l_mix)),
+ SND_SOC_DAPM_MIXER("SPK MIXR", RT5645_PWR_MIXER, RT5645_PWR_SM_R_BIT,
+ 0, rt5645_spk_r_mix, ARRAY_SIZE(rt5645_spk_r_mix)),
+ SND_SOC_DAPM_MIXER("OUT MIXL", RT5645_PWR_MIXER, RT5645_PWR_OM_L_BIT,
+ 0, rt5645_out_l_mix, ARRAY_SIZE(rt5645_out_l_mix)),
+ SND_SOC_DAPM_MIXER("OUT MIXR", RT5645_PWR_MIXER, RT5645_PWR_OM_R_BIT,
+ 0, rt5645_out_r_mix, ARRAY_SIZE(rt5645_out_r_mix)),
+ /* Ouput Volume */
+ SND_SOC_DAPM_SWITCH("SPKVOL L", RT5645_PWR_VOL, RT5645_PWR_SV_L_BIT, 0,
+ &spk_l_vol_control),
+ SND_SOC_DAPM_SWITCH("SPKVOL R", RT5645_PWR_VOL, RT5645_PWR_SV_R_BIT, 0,
+ &spk_r_vol_control),
+ SND_SOC_DAPM_MIXER("HPOVOL MIXL", RT5645_PWR_VOL, RT5645_PWR_HV_L_BIT,
+ 0, rt5645_hpvoll_mix, ARRAY_SIZE(rt5645_hpvoll_mix)),
+ SND_SOC_DAPM_MIXER("HPOVOL MIXR", RT5645_PWR_VOL, RT5645_PWR_HV_R_BIT,
+ 0, rt5645_hpvolr_mix, ARRAY_SIZE(rt5645_hpvolr_mix)),
+ SND_SOC_DAPM_SUPPLY("HPOVOL MIXL Power", RT5645_PWR_MIXER,
+ RT5645_PWR_HM_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("HPOVOL MIXR Power", RT5645_PWR_MIXER,
+ RT5645_PWR_HM_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("DAC 1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("DAC 2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("HPOVOL", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SWITCH("HPOVOL L", SND_SOC_NOPM, 0, 0, &hp_l_vol_control),
+ SND_SOC_DAPM_SWITCH("HPOVOL R", SND_SOC_NOPM, 0, 0, &hp_r_vol_control),
+
+ /* HPO/LOUT/Mono Mixer */
+ SND_SOC_DAPM_MIXER("SPOL MIX", SND_SOC_NOPM, 0, 0, rt5645_spo_l_mix,
+ ARRAY_SIZE(rt5645_spo_l_mix)),
+ SND_SOC_DAPM_MIXER("SPOR MIX", SND_SOC_NOPM, 0, 0, rt5645_spo_r_mix,
+ ARRAY_SIZE(rt5645_spo_r_mix)),
+ SND_SOC_DAPM_MIXER("HPO MIX", SND_SOC_NOPM, 0, 0, rt5645_hpo_mix,
+ ARRAY_SIZE(rt5645_hpo_mix)),
+ SND_SOC_DAPM_MIXER("LOUT MIX", SND_SOC_NOPM, 0, 0, rt5645_lout_mix,
+ ARRAY_SIZE(rt5645_lout_mix)),
+
+ SND_SOC_DAPM_PGA_S("HP amp", 1, SND_SOC_NOPM, 0, 0, rt5645_hp_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_S("LOUT amp", 1, SND_SOC_NOPM, 0, 0, rt5645_lout_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_S("SPK amp", 2, SND_SOC_NOPM, 0, 0, rt5645_spk_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+
+ /* PDM */
+ SND_SOC_DAPM_SUPPLY("PDM1 Power", RT5645_PWR_DIG2, RT5645_PWR_PDM1_BIT,
+ 0, NULL, 0),
+ SND_SOC_DAPM_MUX("PDM1 L Mux", SND_SOC_NOPM, 0, 0, &rt5645_pdm1_l_mux),
+ SND_SOC_DAPM_MUX("PDM1 R Mux", SND_SOC_NOPM, 0, 0, &rt5645_pdm1_r_mux),
+
+ SND_SOC_DAPM_SWITCH("PDM1 L", SND_SOC_NOPM, 0, 0, &pdm1_l_vol_control),
+ SND_SOC_DAPM_SWITCH("PDM1 R", SND_SOC_NOPM, 0, 0, &pdm1_r_vol_control),
+
+ /* Output Lines */
+ SND_SOC_DAPM_OUTPUT("HPOL"),
+ SND_SOC_DAPM_OUTPUT("HPOR"),
+ SND_SOC_DAPM_OUTPUT("LOUTL"),
+ SND_SOC_DAPM_OUTPUT("LOUTR"),
+ SND_SOC_DAPM_OUTPUT("PDM1L"),
+ SND_SOC_DAPM_OUTPUT("PDM1R"),
+ SND_SOC_DAPM_OUTPUT("SPOL"),
+ SND_SOC_DAPM_OUTPUT("SPOR"),
+};
+
+static const struct snd_soc_dapm_route rt5645_dapm_routes[] = {
+ { "IN1P", NULL, "LDO2" },
+ { "IN2P", NULL, "LDO2" },
+
+ { "DMIC1", NULL, "DMIC L1" },
+ { "DMIC1", NULL, "DMIC R1" },
+ { "DMIC2", NULL, "DMIC L2" },
+ { "DMIC2", NULL, "DMIC R2" },
+
+ { "BST1", NULL, "IN1P" },
+ { "BST1", NULL, "IN1N" },
+ { "BST1", NULL, "JD Power" },
+ { "BST1", NULL, "Mic Det Power" },
+ { "BST2", NULL, "IN2P" },
+ { "BST2", NULL, "IN2N" },
+
+ { "INL VOL", NULL, "IN2P" },
+ { "INR VOL", NULL, "IN2N" },
+
+ { "RECMIXL", "HPOL Switch", "HPOL" },
+ { "RECMIXL", "INL Switch", "INL VOL" },
+ { "RECMIXL", "BST2 Switch", "BST2" },
+ { "RECMIXL", "BST1 Switch", "BST1" },
+ { "RECMIXL", "OUT MIXL Switch", "OUT MIXL" },
+
+ { "RECMIXR", "HPOR Switch", "HPOR" },
+ { "RECMIXR", "INR Switch", "INR VOL" },
+ { "RECMIXR", "BST2 Switch", "BST2" },
+ { "RECMIXR", "BST1 Switch", "BST1" },
+ { "RECMIXR", "OUT MIXR Switch", "OUT MIXR" },
+
+ { "ADC L", NULL, "RECMIXL" },
+ { "ADC L", NULL, "ADC L power" },
+ { "ADC R", NULL, "RECMIXR" },
+ { "ADC R", NULL, "ADC R power" },
+
+ {"DMIC L1", NULL, "DMIC CLK"},
+ {"DMIC L1", NULL, "DMIC1 Power"},
+ {"DMIC R1", NULL, "DMIC CLK"},
+ {"DMIC R1", NULL, "DMIC1 Power"},
+ {"DMIC L2", NULL, "DMIC CLK"},
+ {"DMIC L2", NULL, "DMIC2 Power"},
+ {"DMIC R2", NULL, "DMIC CLK"},
+ {"DMIC R2", NULL, "DMIC2 Power"},
+
+ { "Stereo1 DMIC Mux", "DMIC1", "DMIC1" },
+ { "Stereo1 DMIC Mux", "DMIC2", "DMIC2" },
+
+ { "Mono DMIC L Mux", "DMIC1", "DMIC L1" },
+ { "Mono DMIC L Mux", "DMIC2", "DMIC L2" },
+
+ { "Mono DMIC R Mux", "DMIC1", "DMIC R1" },
+ { "Mono DMIC R Mux", "DMIC2", "DMIC R2" },
+
+ { "Stereo1 ADC L2 Mux", "DMIC", "Stereo1 DMIC Mux" },
+ { "Stereo1 ADC L2 Mux", "DAC MIX", "DAC MIXL" },
+ { "Stereo1 ADC L1 Mux", "ADC", "ADC L" },
+ { "Stereo1 ADC L1 Mux", "DAC MIX", "DAC MIXL" },
+
+ { "Stereo1 ADC R1 Mux", "ADC", "ADC R" },
+ { "Stereo1 ADC R1 Mux", "DAC MIX", "DAC MIXR" },
+ { "Stereo1 ADC R2 Mux", "DMIC", "Stereo1 DMIC Mux" },
+ { "Stereo1 ADC R2 Mux", "DAC MIX", "DAC MIXR" },
+
+ { "Mono ADC L2 Mux", "DMIC", "Mono DMIC L Mux" },
+ { "Mono ADC L2 Mux", "Mono DAC MIXL", "Mono DAC MIXL" },
+ { "Mono ADC L1 Mux", "Mono DAC MIXL", "Mono DAC MIXL" },
+ { "Mono ADC L1 Mux", "ADC", "ADC L" },
+
+ { "Mono ADC R1 Mux", "Mono DAC MIXR", "Mono DAC MIXR" },
+ { "Mono ADC R1 Mux", "ADC", "ADC R" },
+ { "Mono ADC R2 Mux", "DMIC", "Mono DMIC R Mux" },
+ { "Mono ADC R2 Mux", "Mono DAC MIXR", "Mono DAC MIXR" },
+
+ { "Sto1 ADC MIXL", "ADC1 Switch", "Stereo1 ADC L1 Mux" },
+ { "Sto1 ADC MIXL", "ADC2 Switch", "Stereo1 ADC L2 Mux" },
+ { "Sto1 ADC MIXR", "ADC1 Switch", "Stereo1 ADC R1 Mux" },
+ { "Sto1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux" },
+
+ { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" },
+ { "Stereo1 ADC MIXL", NULL, "adc stereo1 filter" },
+ { "adc stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" },
+ { "Stereo1 ADC MIXR", NULL, "adc stereo1 filter" },
+ { "adc stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "Mono ADC MIXL", "ADC1 Switch", "Mono ADC L1 Mux" },
+ { "Mono ADC MIXL", "ADC2 Switch", "Mono ADC L2 Mux" },
+ { "Mono ADC MIXL", NULL, "adc mono left filter" },
+ { "adc mono left filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "Mono ADC MIXR", "ADC1 Switch", "Mono ADC R1 Mux" },
+ { "Mono ADC MIXR", "ADC2 Switch", "Mono ADC R2 Mux" },
+ { "Mono ADC MIXR", NULL, "adc mono right filter" },
+ { "adc mono right filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "VAD ADC Mux", "Sto1 ADC L", "Stereo1 ADC MIXL" },
+ { "VAD ADC Mux", "Mono ADC L", "Mono ADC MIXL" },
+ { "VAD ADC Mux", "Mono ADC R", "Mono ADC MIXR" },
+
+ { "IF_ADC1", NULL, "Stereo1 ADC MIXL" },
+ { "IF_ADC1", NULL, "Stereo1 ADC MIXR" },
+ { "IF_ADC2", NULL, "Mono ADC MIXL" },
+ { "IF_ADC2", NULL, "Mono ADC MIXR" },
+ { "VAD_ADC", NULL, "VAD ADC Mux" },
+
+ { "IF1 ADC Mux", "IF_ADC1", "IF_ADC1" },
+ { "IF1 ADC Mux", "IF_ADC2", "IF_ADC2" },
+ { "IF1 ADC Mux", "VAD_ADC", "VAD_ADC" },
+
+ { "IF2 ADC Mux", "IF_ADC1", "IF_ADC1" },
+ { "IF2 ADC Mux", "IF_ADC2", "IF_ADC2" },
+ { "IF2 ADC Mux", "VAD_ADC", "VAD_ADC" },
+
+ { "IF1 ADC", NULL, "I2S1" },
+ { "IF1 ADC", NULL, "IF1 ADC Mux" },
+ { "IF2 ADC", NULL, "I2S2" },
+ { "IF2 ADC", NULL, "IF2 ADC Mux" },
+
+ { "AIF1TX", NULL, "IF1 ADC" },
+ { "AIF1TX", NULL, "IF2 ADC" },
+ { "AIF2TX", NULL, "IF2 ADC" },
+
+ { "IF1 DAC1", NULL, "AIF1RX" },
+ { "IF1 DAC2", NULL, "AIF1RX" },
+ { "IF2 DAC", NULL, "AIF2RX" },
+
+ { "IF1 DAC1", NULL, "I2S1" },
+ { "IF1 DAC2", NULL, "I2S1" },
+ { "IF2 DAC", NULL, "I2S2" },
+
+ { "IF1 DAC2 L", NULL, "IF1 DAC2" },
+ { "IF1 DAC2 R", NULL, "IF1 DAC2" },
+ { "IF1 DAC1 L", NULL, "IF1 DAC1" },
+ { "IF1 DAC1 R", NULL, "IF1 DAC1" },
+ { "IF2 DAC L", NULL, "IF2 DAC" },
+ { "IF2 DAC R", NULL, "IF2 DAC" },
+
+ { "DAC1 L Mux", "IF1 DAC", "IF1 DAC1 L" },
+ { "DAC1 L Mux", "IF2 DAC", "IF2 DAC L" },
+
+ { "DAC1 R Mux", "IF1 DAC", "IF1 DAC1 R" },
+ { "DAC1 R Mux", "IF2 DAC", "IF2 DAC R" },
+
+ { "DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL" },
+ { "DAC1 MIXL", "DAC1 Switch", "DAC1 L Mux" },
+ { "DAC1 MIXL", NULL, "dac stereo1 filter" },
+ { "DAC1 MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR" },
+ { "DAC1 MIXR", "DAC1 Switch", "DAC1 R Mux" },
+ { "DAC1 MIXR", NULL, "dac stereo1 filter" },
+
+ { "DAC L2 Mux", "IF1 DAC", "IF1 DAC2 L" },
+ { "DAC L2 Mux", "IF2 DAC", "IF2 DAC L" },
+ { "DAC L2 Mux", "Mono ADC", "Mono ADC MIXL" },
+ { "DAC L2 Mux", "VAD_ADC", "VAD_ADC" },
+ { "DAC L2 Volume", NULL, "DAC L2 Mux" },
+ { "DAC L2 Volume", NULL, "dac mono left filter" },
+
+ { "DAC R2 Mux", "IF1 DAC", "IF1 DAC2 R" },
+ { "DAC R2 Mux", "IF2 DAC", "IF2 DAC R" },
+ { "DAC R2 Mux", "Mono ADC", "Mono ADC MIXR" },
+ { "DAC R2 Mux", "Haptic", "Haptic Generator" },
+ { "DAC R2 Volume", NULL, "DAC R2 Mux" },
+ { "DAC R2 Volume", NULL, "dac mono right filter" },
+
+ { "Stereo DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" },
+ { "Stereo DAC MIXL", "DAC R1 Switch", "DAC1 MIXR" },
+ { "Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" },
+ { "Stereo DAC MIXL", NULL, "dac stereo1 filter" },
+ { "Stereo DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" },
+ { "Stereo DAC MIXR", "DAC L1 Switch", "DAC1 MIXL" },
+ { "Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" },
+ { "Stereo DAC MIXR", NULL, "dac stereo1 filter" },
+
+ { "Mono DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" },
+ { "Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" },
+ { "Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Volume" },
+ { "Mono DAC MIXL", NULL, "dac mono left filter" },
+ { "Mono DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" },
+ { "Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" },
+ { "Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" },
+ { "Mono DAC MIXR", NULL, "dac mono right filter" },
+
+ { "DAC MIXL", "Sto DAC Mix L Switch", "Stereo DAC MIXL" },
+ { "DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" },
+ { "DAC MIXL", "DAC R2 Switch", "DAC R2 Volume" },
+ { "DAC MIXR", "Sto DAC Mix R Switch", "Stereo DAC MIXR" },
+ { "DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" },
+ { "DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" },
+
+ { "DAC L1", NULL, "Stereo DAC MIXL" },
+ { "DAC L1", NULL, "PLL1", is_sys_clk_from_pll },
+ { "DAC R1", NULL, "Stereo DAC MIXR" },
+ { "DAC R1", NULL, "PLL1", is_sys_clk_from_pll },
+ { "DAC L2", NULL, "Mono DAC MIXL" },
+ { "DAC L2", NULL, "PLL1", is_sys_clk_from_pll },
+ { "DAC R2", NULL, "Mono DAC MIXR" },
+ { "DAC R2", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "SPK MIXL", "BST1 Switch", "BST1" },
+ { "SPK MIXL", "INL Switch", "INL VOL" },
+ { "SPK MIXL", "DAC L1 Switch", "DAC L1" },
+ { "SPK MIXL", "DAC L2 Switch", "DAC L2" },
+ { "SPK MIXR", "BST2 Switch", "BST2" },
+ { "SPK MIXR", "INR Switch", "INR VOL" },
+ { "SPK MIXR", "DAC R1 Switch", "DAC R1" },
+ { "SPK MIXR", "DAC R2 Switch", "DAC R2" },
+
+ { "OUT MIXL", "BST1 Switch", "BST1" },
+ { "OUT MIXL", "INL Switch", "INL VOL" },
+ { "OUT MIXL", "DAC L2 Switch", "DAC L2" },
+ { "OUT MIXL", "DAC L1 Switch", "DAC L1" },
+
+ { "OUT MIXR", "BST2 Switch", "BST2" },
+ { "OUT MIXR", "INR Switch", "INR VOL" },
+ { "OUT MIXR", "DAC R2 Switch", "DAC R2" },
+ { "OUT MIXR", "DAC R1 Switch", "DAC R1" },
+
+ { "HPOVOL MIXL", "DAC1 Switch", "DAC L1" },
+ { "HPOVOL MIXL", "DAC2 Switch", "DAC L2" },
+ { "HPOVOL MIXL", "INL Switch", "INL VOL" },
+ { "HPOVOL MIXL", "BST1 Switch", "BST1" },
+ { "HPOVOL MIXL", NULL, "HPOVOL MIXL Power" },
+ { "HPOVOL MIXR", "DAC1 Switch", "DAC R1" },
+ { "HPOVOL MIXR", "DAC2 Switch", "DAC R2" },
+ { "HPOVOL MIXR", "INR Switch", "INR VOL" },
+ { "HPOVOL MIXR", "BST2 Switch", "BST2" },
+ { "HPOVOL MIXR", NULL, "HPOVOL MIXR Power" },
+
+ { "DAC 2", NULL, "DAC L2" },
+ { "DAC 2", NULL, "DAC R2" },
+ { "DAC 1", NULL, "DAC L1" },
+ { "DAC 1", NULL, "DAC R1" },
+ { "HPOVOL L", "Switch", "HPOVOL MIXL" },
+ { "HPOVOL R", "Switch", "HPOVOL MIXR" },
+ { "HPOVOL", NULL, "HPOVOL L" },
+ { "HPOVOL", NULL, "HPOVOL R" },
+ { "HPO MIX", "DAC1 Switch", "DAC 1" },
+ { "HPO MIX", "HPVOL Switch", "HPOVOL" },
+
+ { "SPKVOL L", "Switch", "SPK MIXL" },
+ { "SPKVOL R", "Switch", "SPK MIXR" },
+
+ { "SPOL MIX", "DAC R1 Switch", "DAC R1" },
+ { "SPOL MIX", "DAC L1 Switch", "DAC L1" },
+ { "SPOL MIX", "SPKVOL R Switch", "SPKVOL R" },
+ { "SPOL MIX", "SPKVOL L Switch", "SPKVOL L" },
+ { "SPOR MIX", "DAC R1 Switch", "DAC R1" },
+ { "SPOR MIX", "SPKVOL R Switch", "SPKVOL R" },
+
+ { "LOUT MIX", "DAC L1 Switch", "DAC L1" },
+ { "LOUT MIX", "DAC R1 Switch", "DAC R1" },
+ { "LOUT MIX", "OUTMIX L Switch", "OUT MIXL" },
+ { "LOUT MIX", "OUTMIX R Switch", "OUT MIXR" },
+
+ { "PDM1 L Mux", "Stereo DAC", "Stereo DAC MIXL" },
+ { "PDM1 L Mux", "Mono DAC", "Mono DAC MIXL" },
+ { "PDM1 L Mux", NULL, "PDM1 Power" },
+ { "PDM1 R Mux", "Stereo DAC", "Stereo DAC MIXR" },
+ { "PDM1 R Mux", "Mono DAC", "Mono DAC MIXR" },
+ { "PDM1 R Mux", NULL, "PDM1 Power" },
+
+ { "HP amp", NULL, "HPO MIX" },
+ { "HP amp", NULL, "JD Power" },
+ { "HP amp", NULL, "Mic Det Power" },
+ { "HP amp", NULL, "LDO2" },
+ { "HPOL", NULL, "HP amp" },
+ { "HPOR", NULL, "HP amp" },
+
+ { "LOUT amp", NULL, "LOUT MIX" },
+ { "LOUTL", NULL, "LOUT amp" },
+ { "LOUTR", NULL, "LOUT amp" },
+
+ { "PDM1 L", "Switch", "PDM1 L Mux" },
+ { "PDM1 R", "Switch", "PDM1 R Mux" },
+
+ { "PDM1L", NULL, "PDM1 L" },
+ { "PDM1R", NULL, "PDM1 R" },
+
+ { "SPK amp", NULL, "SPOL MIX" },
+ { "SPK amp", NULL, "SPOR MIX" },
+ { "SPOL", NULL, "SPK amp" },
+ { "SPOR", NULL, "SPK amp" },
+};
+
+static int rt5645_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;
+ struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+ unsigned int val_len = 0, val_clk, mask_clk;
+ int pre_div, bclk_ms, frame_size;
+
+ rt5645->lrck[dai->id] = params_rate(params);
+ pre_div = rl6231_get_clk_info(rt5645->sysclk, rt5645->lrck[dai->id]);
+ if (pre_div < 0) {
+ dev_err(codec->dev, "Unsupported clock setting\n");
+ return -EINVAL;
+ }
+ frame_size = snd_soc_params_to_frame_size(params);
+ if (frame_size < 0) {
+ dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size);
+ return -EINVAL;
+ }
+ bclk_ms = frame_size > 32;
+ rt5645->bclk[dai->id] = rt5645->lrck[dai->id] * (32 << bclk_ms);
+
+ dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n",
+ rt5645->bclk[dai->id], rt5645->lrck[dai->id]);
+ dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
+ bclk_ms, pre_div, dai->id);
+
+ switch (params_width(params)) {
+ case 16:
+ break;
+ case 20:
+ val_len |= RT5645_I2S_DL_20;
+ break;
+ case 24:
+ val_len |= RT5645_I2S_DL_24;
+ break;
+ case 8:
+ val_len |= RT5645_I2S_DL_8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (dai->id) {
+ case RT5645_AIF1:
+ mask_clk = RT5645_I2S_BCLK_MS1_MASK | RT5645_I2S_PD1_MASK;
+ val_clk = bclk_ms << RT5645_I2S_BCLK_MS1_SFT |
+ pre_div << RT5645_I2S_PD1_SFT;
+ snd_soc_update_bits(codec, RT5645_I2S1_SDP,
+ RT5645_I2S_DL_MASK, val_len);
+ snd_soc_update_bits(codec, RT5645_ADDA_CLK1, mask_clk, val_clk);
+ break;
+ case RT5645_AIF2:
+ mask_clk = RT5645_I2S_BCLK_MS2_MASK | RT5645_I2S_PD2_MASK;
+ val_clk = bclk_ms << RT5645_I2S_BCLK_MS2_SFT |
+ pre_div << RT5645_I2S_PD2_SFT;
+ snd_soc_update_bits(codec, RT5645_I2S2_SDP,
+ RT5645_I2S_DL_MASK, val_len);
+ snd_soc_update_bits(codec, RT5645_ADDA_CLK1, mask_clk, val_clk);
+ break;
+ default:
+ dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rt5645_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+ unsigned int reg_val = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ rt5645->master[dai->id] = 1;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ reg_val |= RT5645_I2S_MS_S;
+ rt5645->master[dai->id] = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ reg_val |= RT5645_I2S_BP_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ reg_val |= RT5645_I2S_DF_LEFT;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ reg_val |= RT5645_I2S_DF_PCM_A;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ reg_val |= RT5645_I2S_DF_PCM_B;
+ break;
+ default:
+ return -EINVAL;
+ }
+ switch (dai->id) {
+ case RT5645_AIF1:
+ snd_soc_update_bits(codec, RT5645_I2S1_SDP,
+ RT5645_I2S_MS_MASK | RT5645_I2S_BP_MASK |
+ RT5645_I2S_DF_MASK, reg_val);
+ break;
+ case RT5645_AIF2:
+ snd_soc_update_bits(codec, RT5645_I2S2_SDP,
+ RT5645_I2S_MS_MASK | RT5645_I2S_BP_MASK |
+ RT5645_I2S_DF_MASK, reg_val);
+ break;
+ default:
+ dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int rt5645_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+ unsigned int reg_val = 0;
+
+ if (freq == rt5645->sysclk && clk_id == rt5645->sysclk_src)
+ return 0;
+
+ switch (clk_id) {
+ case RT5645_SCLK_S_MCLK:
+ reg_val |= RT5645_SCLK_SRC_MCLK;
+ break;
+ case RT5645_SCLK_S_PLL1:
+ reg_val |= RT5645_SCLK_SRC_PLL1;
+ break;
+ case RT5645_SCLK_S_RCCLK:
+ reg_val |= RT5645_SCLK_SRC_RCCLK;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, RT5645_GLB_CLK,
+ RT5645_SCLK_SRC_MASK, reg_val);
+ rt5645->sysclk = freq;
+ rt5645->sysclk_src = clk_id;
+
+ dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
+
+ return 0;
+}
+
+static int rt5645_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
+ unsigned int freq_in, unsigned int freq_out)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+ struct rl6231_pll_code pll_code;
+ int ret;
+
+ if (source == rt5645->pll_src && freq_in == rt5645->pll_in &&
+ freq_out == rt5645->pll_out)
+ return 0;
+
+ if (!freq_in || !freq_out) {
+ dev_dbg(codec->dev, "PLL disabled\n");
+
+ rt5645->pll_in = 0;
+ rt5645->pll_out = 0;
+ snd_soc_update_bits(codec, RT5645_GLB_CLK,
+ RT5645_SCLK_SRC_MASK, RT5645_SCLK_SRC_MCLK);
+ return 0;
+ }
+
+ switch (source) {
+ case RT5645_PLL1_S_MCLK:
+ snd_soc_update_bits(codec, RT5645_GLB_CLK,
+ RT5645_PLL1_SRC_MASK, RT5645_PLL1_SRC_MCLK);
+ break;
+ case RT5645_PLL1_S_BCLK1:
+ case RT5645_PLL1_S_BCLK2:
+ switch (dai->id) {
+ case RT5645_AIF1:
+ snd_soc_update_bits(codec, RT5645_GLB_CLK,
+ RT5645_PLL1_SRC_MASK, RT5645_PLL1_SRC_BCLK1);
+ break;
+ case RT5645_AIF2:
+ snd_soc_update_bits(codec, RT5645_GLB_CLK,
+ RT5645_PLL1_SRC_MASK, RT5645_PLL1_SRC_BCLK2);
+ break;
+ default:
+ dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id);
+ return -EINVAL;
+ }
+ break;
+ default:
+ dev_err(codec->dev, "Unknown PLL source %d\n", source);
+ return -EINVAL;
+ }
+
+ ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
+ if (ret < 0) {
+ dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
+ return ret;
+ }
+
+ dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n",
+ pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
+ pll_code.n_code, pll_code.k_code);
+
+ snd_soc_write(codec, RT5645_PLL_CTRL1,
+ pll_code.n_code << RT5645_PLL_N_SFT | pll_code.k_code);
+ snd_soc_write(codec, RT5645_PLL_CTRL2,
+ (pll_code.m_bp ? 0 : pll_code.m_code) << RT5645_PLL_M_SFT |
+ pll_code.m_bp << RT5645_PLL_M_BP_SFT);
+
+ rt5645->pll_in = freq_in;
+ rt5645->pll_out = freq_out;
+ rt5645->pll_src = source;
+
+ return 0;
+}
+
+static int rt5645_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+ unsigned int rx_mask, int slots, int slot_width)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int val = 0;
+
+ if (rx_mask || tx_mask)
+ val |= (1 << 14);
+
+ switch (slots) {
+ case 4:
+ val |= (1 << 12);
+ break;
+ case 6:
+ val |= (2 << 12);
+ break;
+ case 8:
+ val |= (3 << 12);
+ break;
+ case 2:
+ default:
+ break;
+ }
+
+ switch (slot_width) {
+ case 20:
+ val |= (1 << 10);
+ break;
+ case 24:
+ val |= (2 << 10);
+ break;
+ case 32:
+ val |= (3 << 10);
+ break;
+ case 16:
+ default:
+ break;
+ }
+
+ snd_soc_update_bits(codec, RT5645_TDM_CTRL_1, 0x7c00, val);
+
+ return 0;
+}
+
+static int rt5645_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_STANDBY:
+ if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) {
+ snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+ RT5645_PWR_VREF1 | RT5645_PWR_MB |
+ RT5645_PWR_BG | RT5645_PWR_VREF2,
+ RT5645_PWR_VREF1 | RT5645_PWR_MB |
+ RT5645_PWR_BG | RT5645_PWR_VREF2);
+ mdelay(10);
+ snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+ RT5645_PWR_FV1 | RT5645_PWR_FV2,
+ RT5645_PWR_FV1 | RT5645_PWR_FV2);
+ snd_soc_update_bits(codec, RT5645_GEN_CTRL1,
+ RT5645_DIG_GATE_CTRL, RT5645_DIG_GATE_CTRL);
+ }
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ snd_soc_write(codec, RT5645_DEPOP_M2, 0x1100);
+ snd_soc_write(codec, RT5645_GEN_CTRL1, 0x0128);
+ snd_soc_write(codec, RT5645_PWR_DIG1, 0x0000);
+ snd_soc_write(codec, RT5645_PWR_DIG2, 0x0000);
+ snd_soc_write(codec, RT5645_PWR_VOL, 0x0000);
+ snd_soc_write(codec, RT5645_PWR_MIXER, 0x0000);
+ snd_soc_write(codec, RT5645_PWR_ANLG1, 0x0000);
+ snd_soc_write(codec, RT5645_PWR_ANLG2, 0x0000);
+ break;
+
+ default:
+ break;
+ }
+ codec->dapm.bias_level = level;
+
+ return 0;
+}
+
+static int rt5645_probe(struct snd_soc_codec *codec)
+{
+ struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+
+ rt5645->codec = codec;
+
+ rt5645_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200);
+
+ return 0;
+}
+
+static int rt5645_remove(struct snd_soc_codec *codec)
+{
+ rt5645_reset(codec);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt5645_suspend(struct snd_soc_codec *codec)
+{
+ struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_cache_only(rt5645->regmap, true);
+ regcache_mark_dirty(rt5645->regmap);
+
+ return 0;
+}
+
+static int rt5645_resume(struct snd_soc_codec *codec)
+{
+ struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_cache_only(rt5645->regmap, false);
+ regcache_sync(rt5645->regmap);
+
+ return 0;
+}
+#else
+#define rt5645_suspend NULL
+#define rt5645_resume NULL
+#endif
+
+#define RT5645_STEREO_RATES SNDRV_PCM_RATE_8000_96000
+#define RT5645_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
+
+static struct snd_soc_dai_ops rt5645_aif_dai_ops = {
+ .hw_params = rt5645_hw_params,
+ .set_fmt = rt5645_set_dai_fmt,
+ .set_sysclk = rt5645_set_dai_sysclk,
+ .set_tdm_slot = rt5645_set_tdm_slot,
+ .set_pll = rt5645_set_dai_pll,
+};
+
+static struct snd_soc_dai_driver rt5645_dai[] = {
+ {
+ .name = "rt5645-aif1",
+ .id = RT5645_AIF1,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5645_STEREO_RATES,
+ .formats = RT5645_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5645_STEREO_RATES,
+ .formats = RT5645_FORMATS,
+ },
+ .ops = &rt5645_aif_dai_ops,
+ },
+ {
+ .name = "rt5645-aif2",
+ .id = RT5645_AIF2,
+ .playback = {
+ .stream_name = "AIF2 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5645_STEREO_RATES,
+ .formats = RT5645_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5645_STEREO_RATES,
+ .formats = RT5645_FORMATS,
+ },
+ .ops = &rt5645_aif_dai_ops,
+ },
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt5645 = {
+ .probe = rt5645_probe,
+ .remove = rt5645_remove,
+ .suspend = rt5645_suspend,
+ .resume = rt5645_resume,
+ .set_bias_level = rt5645_set_bias_level,
+ .idle_bias_off = true,
+ .controls = rt5645_snd_controls,
+ .num_controls = ARRAY_SIZE(rt5645_snd_controls),
+ .dapm_widgets = rt5645_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(rt5645_dapm_widgets),
+ .dapm_routes = rt5645_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(rt5645_dapm_routes),
+};
+
+static const struct regmap_config rt5645_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = RT5645_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5645_ranges) *
+ RT5645_PR_SPACING),
+ .volatile_reg = rt5645_volatile_register,
+ .readable_reg = rt5645_readable_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = rt5645_reg,
+ .num_reg_defaults = ARRAY_SIZE(rt5645_reg),
+ .ranges = rt5645_ranges,
+ .num_ranges = ARRAY_SIZE(rt5645_ranges),
+};
+
+static const struct i2c_device_id rt5645_i2c_id[] = {
+ { "rt5645", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id);
+
+static int rt5645_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct rt5645_platform_data *pdata = dev_get_platdata(&i2c->dev);
+ struct rt5645_priv *rt5645;
+ int ret;
+ unsigned int val;
+
+ rt5645 = devm_kzalloc(&i2c->dev, sizeof(struct rt5645_priv),
+ GFP_KERNEL);
+ if (rt5645 == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, rt5645);
+
+ if (pdata)
+ rt5645->pdata = *pdata;
+
+ rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5645_regmap);
+ if (IS_ERR(rt5645->regmap)) {
+ ret = PTR_ERR(rt5645->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ regmap_read(rt5645->regmap, RT5645_VENDOR_ID2, &val);
+ if (val != RT5645_DEVICE_ID) {
+ dev_err(&i2c->dev,
+ "Device with ID register %x is not rt5645\n", val);
+ return -ENODEV;
+ }
+
+ regmap_write(rt5645->regmap, RT5645_RESET, 0);
+
+ ret = regmap_register_patch(rt5645->regmap, init_list,
+ ARRAY_SIZE(init_list));
+ if (ret != 0)
+ dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
+
+ if (rt5645->pdata.in2_diff)
+ regmap_update_bits(rt5645->regmap, RT5645_IN2_CTRL,
+ RT5645_IN_DF2, RT5645_IN_DF2);
+
+ if (rt5645->pdata.dmic_en) {
+ regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
+ RT5645_GP2_PIN_MASK, RT5645_GP2_PIN_DMIC1_SCL);
+
+ switch (rt5645->pdata.dmic1_data_pin) {
+ case RT5645_DMIC_DATA_IN2N:
+ regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+ RT5645_DMIC_1_DP_MASK, RT5645_DMIC_1_DP_IN2N);
+ break;
+
+ case RT5645_DMIC_DATA_GPIO5:
+ regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+ RT5645_DMIC_1_DP_MASK, RT5645_DMIC_1_DP_GPIO5);
+ regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
+ RT5645_GP5_PIN_MASK, RT5645_GP5_PIN_DMIC1_SDA);
+ break;
+
+ case RT5645_DMIC_DATA_GPIO11:
+ regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+ RT5645_DMIC_1_DP_MASK, RT5645_DMIC_1_DP_GPIO11);
+ regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
+ RT5645_GP11_PIN_MASK,
+ RT5645_GP11_PIN_DMIC1_SDA);
+ break;
+
+ default:
+ break;
+ }
+
+ switch (rt5645->pdata.dmic2_data_pin) {
+ case RT5645_DMIC_DATA_IN2P:
+ regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+ RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_IN2P);
+ break;
+
+ case RT5645_DMIC_DATA_GPIO6:
+ regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+ RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_GPIO6);
+ regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
+ RT5645_GP6_PIN_MASK, RT5645_GP6_PIN_DMIC2_SDA);
+ break;
+
+ case RT5645_DMIC_DATA_GPIO10:
+ regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+ RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_GPIO10);
+ regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
+ RT5645_GP10_PIN_MASK,
+ RT5645_GP10_PIN_DMIC2_SDA);
+ break;
+
+ case RT5645_DMIC_DATA_GPIO12:
+ regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+ RT5645_DMIC_1_DP_MASK, RT5645_DMIC_2_DP_GPIO12);
+ regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
+ RT5645_GP12_PIN_MASK,
+ RT5645_GP12_PIN_DMIC2_SDA);
+ break;
+
+ default:
+ break;
+ }
+
+ }
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645,
+ rt5645_dai, ARRAY_SIZE(rt5645_dai));
+ if (ret < 0)
+ goto err;
+
+ return 0;
+err:
+ return ret;
+}
+
+static int rt5645_i2c_remove(struct i2c_client *i2c)
+{
+ snd_soc_unregister_codec(&i2c->dev);
+
+ return 0;
+}
+
+static struct i2c_driver rt5645_i2c_driver = {
+ .driver = {
+ .name = "rt5645",
+ .owner = THIS_MODULE,
+ },
+ .probe = rt5645_i2c_probe,
+ .remove = rt5645_i2c_remove,
+ .id_table = rt5645_i2c_id,
+};
+module_i2c_driver(rt5645_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC RT5645 driver");
+MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h
new file mode 100644
index 00000000000..355b7e9eefa
--- /dev/null
+++ b/sound/soc/codecs/rt5645.h
@@ -0,0 +1,2181 @@
+/*
+ * rt5645.h -- RT5645 ALSA SoC audio driver
+ *
+ * Copyright 2013 Realtek Microelectronics
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * 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 __RT5645_H__
+#define __RT5645_H__
+
+#include <sound/rt5645.h>
+
+/* Info */
+#define RT5645_RESET 0x00
+#define RT5645_VENDOR_ID 0xfd
+#define RT5645_VENDOR_ID1 0xfe
+#define RT5645_VENDOR_ID2 0xff
+/* I/O - Output */
+#define RT5645_SPK_VOL 0x01
+#define RT5645_HP_VOL 0x02
+#define RT5645_LOUT1 0x03
+#define RT5645_LOUT_CTRL 0x05
+/* I/O - Input */
+#define RT5645_IN1_CTRL1 0x0a
+#define RT5645_IN1_CTRL2 0x0b
+#define RT5645_IN1_CTRL3 0x0c
+#define RT5645_IN2_CTRL 0x0d
+#define RT5645_INL1_INR1_VOL 0x0f
+#define RT5645_SPK_FUNC_LIM 0x14
+#define RT5645_ADJ_HPF_CTRL 0x16
+/* I/O - ADC/DAC/DMIC */
+#define RT5645_DAC1_DIG_VOL 0x19
+#define RT5645_DAC2_DIG_VOL 0x1a
+#define RT5645_DAC_CTRL 0x1b
+#define RT5645_STO1_ADC_DIG_VOL 0x1c
+#define RT5645_MONO_ADC_DIG_VOL 0x1d
+#define RT5645_ADC_BST_VOL1 0x1e
+/* Mixer - D-D */
+#define RT5645_ADC_BST_VOL2 0x20
+#define RT5645_STO1_ADC_MIXER 0x27
+#define RT5645_MONO_ADC_MIXER 0x28
+#define RT5645_AD_DA_MIXER 0x29
+#define RT5645_STO_DAC_MIXER 0x2a
+#define RT5645_MONO_DAC_MIXER 0x2b
+#define RT5645_DIG_MIXER 0x2c
+#define RT5645_DIG_INF1_DATA 0x2f
+/* Mixer - PDM */
+#define RT5645_PDM_OUT_CTRL 0x31
+/* Mixer - ADC */
+#define RT5645_REC_L1_MIXER 0x3b
+#define RT5645_REC_L2_MIXER 0x3c
+#define RT5645_REC_R1_MIXER 0x3d
+#define RT5645_REC_R2_MIXER 0x3e
+/* Mixer - DAC */
+#define RT5645_HPMIXL_CTRL 0x3f
+#define RT5645_HPOMIXL_CTRL 0x40
+#define RT5645_HPMIXR_CTRL 0x41
+#define RT5645_HPOMIXR_CTRL 0x42
+#define RT5645_HPO_MIXER 0x45
+#define RT5645_SPK_L_MIXER 0x46
+#define RT5645_SPK_R_MIXER 0x47
+#define RT5645_SPO_MIXER 0x48
+#define RT5645_SPO_CLSD_RATIO 0x4a
+#define RT5645_OUT_L_GAIN1 0x4d
+#define RT5645_OUT_L_GAIN2 0x4e
+#define RT5645_OUT_L1_MIXER 0x4f
+#define RT5645_OUT_R_GAIN1 0x50
+#define RT5645_OUT_R_GAIN2 0x51
+#define RT5645_OUT_R1_MIXER 0x52
+#define RT5645_LOUT_MIXER 0x53
+/* Haptic */
+#define RT5645_HAPTIC_CTRL1 0x56
+#define RT5645_HAPTIC_CTRL2 0x57
+#define RT5645_HAPTIC_CTRL3 0x58
+#define RT5645_HAPTIC_CTRL4 0x59
+#define RT5645_HAPTIC_CTRL5 0x5a
+#define RT5645_HAPTIC_CTRL6 0x5b
+#define RT5645_HAPTIC_CTRL7 0x5c
+#define RT5645_HAPTIC_CTRL8 0x5d
+#define RT5645_HAPTIC_CTRL9 0x5e
+#define RT5645_HAPTIC_CTRL10 0x5f
+/* Power */
+#define RT5645_PWR_DIG1 0x61
+#define RT5645_PWR_DIG2 0x62
+#define RT5645_PWR_ANLG1 0x63
+#define RT5645_PWR_ANLG2 0x64
+#define RT5645_PWR_MIXER 0x65
+#define RT5645_PWR_VOL 0x66
+/* Private Register Control */
+#define RT5645_PRIV_INDEX 0x6a
+#define RT5645_PRIV_DATA 0x6c
+/* Format - ADC/DAC */
+#define RT5645_I2S1_SDP 0x70
+#define RT5645_I2S2_SDP 0x71
+#define RT5645_ADDA_CLK1 0x73
+#define RT5645_ADDA_CLK2 0x74
+#define RT5645_DMIC_CTRL1 0x75
+#define RT5645_DMIC_CTRL2 0x76
+/* Format - TDM Control */
+#define RT5645_TDM_CTRL_1 0x77
+#define RT5645_TDM_CTRL_2 0x78
+#define RT5645_TDM_CTRL_3 0x79
+
+/* Function - Analog */
+#define RT5645_GLB_CLK 0x80
+#define RT5645_PLL_CTRL1 0x81
+#define RT5645_PLL_CTRL2 0x82
+#define RT5645_ASRC_1 0x83
+#define RT5645_ASRC_2 0x84
+#define RT5645_ASRC_3 0x85
+#define RT5645_ASRC_4 0x8a
+#define RT5645_DEPOP_M1 0x8e
+#define RT5645_DEPOP_M2 0x8f
+#define RT5645_DEPOP_M3 0x90
+#define RT5645_CHARGE_PUMP 0x91
+#define RT5645_MICBIAS 0x93
+#define RT5645_A_JD_CTRL1 0x94
+#define RT5645_VAD_CTRL4 0x9d
+#define RT5645_CLSD_OUT_CTRL 0xa0
+/* Function - Digital */
+#define RT5645_ADC_EQ_CTRL1 0xae
+#define RT5645_ADC_EQ_CTRL2 0xaf
+#define RT5645_EQ_CTRL1 0xb0
+#define RT5645_EQ_CTRL2 0xb1
+#define RT5645_ALC_CTRL_1 0xb3
+#define RT5645_ALC_CTRL_2 0xb4
+#define RT5645_ALC_CTRL_3 0xb5
+#define RT5645_ALC_CTRL_4 0xb6
+#define RT5645_ALC_CTRL_5 0xb7
+#define RT5645_JD_CTRL 0xbb
+#define RT5645_IRQ_CTRL1 0xbc
+#define RT5645_IRQ_CTRL2 0xbd
+#define RT5645_IRQ_CTRL3 0xbe
+#define RT5645_INT_IRQ_ST 0xbf
+#define RT5645_GPIO_CTRL1 0xc0
+#define RT5645_GPIO_CTRL2 0xc1
+#define RT5645_GPIO_CTRL3 0xc2
+#define RT5645_BASS_BACK 0xcf
+#define RT5645_MP3_PLUS1 0xd0
+#define RT5645_MP3_PLUS2 0xd1
+#define RT5645_ADJ_HPF1 0xd3
+#define RT5645_ADJ_HPF2 0xd4
+#define RT5645_HP_CALIB_AMP_DET 0xd6
+#define RT5645_SV_ZCD1 0xd9
+#define RT5645_SV_ZCD2 0xda
+#define RT5645_IL_CMD 0xdb
+#define RT5645_IL_CMD2 0xdc
+#define RT5645_IL_CMD3 0xdd
+#define RT5645_DRC1_HL_CTRL1 0xe7
+#define RT5645_DRC2_HL_CTRL1 0xe9
+#define RT5645_MUTI_DRC_CTRL1 0xea
+#define RT5645_ADC_MONO_HP_CTRL1 0xec
+#define RT5645_ADC_MONO_HP_CTRL2 0xed
+#define RT5645_DRC2_CTRL1 0xf0
+#define RT5645_DRC2_CTRL2 0xf1
+#define RT5645_DRC2_CTRL3 0xf2
+#define RT5645_DRC2_CTRL4 0xf3
+#define RT5645_DRC2_CTRL5 0xf4
+#define RT5645_JD_CTRL3 0xf8
+#define RT5645_JD_CTRL4 0xf9
+/* General Control */
+#define RT5645_GEN_CTRL1 0xfa
+#define RT5645_GEN_CTRL2 0xfb
+#define RT5645_GEN_CTRL3 0xfc
+
+
+/* Index of Codec Private Register definition */
+#define RT5645_DIG_VOL 0x00
+#define RT5645_PR_ALC_CTRL_1 0x01
+#define RT5645_PR_ALC_CTRL_2 0x02
+#define RT5645_PR_ALC_CTRL_3 0x03
+#define RT5645_PR_ALC_CTRL_4 0x04
+#define RT5645_PR_ALC_CTRL_5 0x05
+#define RT5645_PR_ALC_CTRL_6 0x06
+#define RT5645_BIAS_CUR1 0x12
+#define RT5645_BIAS_CUR3 0x14
+#define RT5645_CLSD_INT_REG1 0x1c
+#define RT5645_MAMP_INT_REG2 0x37
+#define RT5645_CHOP_DAC_ADC 0x3d
+#define RT5645_MIXER_INT_REG 0x3f
+#define RT5645_3D_SPK 0x63
+#define RT5645_WND_1 0x6c
+#define RT5645_WND_2 0x6d
+#define RT5645_WND_3 0x6e
+#define RT5645_WND_4 0x6f
+#define RT5645_WND_5 0x70
+#define RT5645_WND_8 0x73
+#define RT5645_DIP_SPK_INF 0x75
+#define RT5645_HP_DCC_INT1 0x77
+#define RT5645_EQ_BW_LOP 0xa0
+#define RT5645_EQ_GN_LOP 0xa1
+#define RT5645_EQ_FC_BP1 0xa2
+#define RT5645_EQ_BW_BP1 0xa3
+#define RT5645_EQ_GN_BP1 0xa4
+#define RT5645_EQ_FC_BP2 0xa5
+#define RT5645_EQ_BW_BP2 0xa6
+#define RT5645_EQ_GN_BP2 0xa7
+#define RT5645_EQ_FC_BP3 0xa8
+#define RT5645_EQ_BW_BP3 0xa9
+#define RT5645_EQ_GN_BP3 0xaa
+#define RT5645_EQ_FC_BP4 0xab
+#define RT5645_EQ_BW_BP4 0xac
+#define RT5645_EQ_GN_BP4 0xad
+#define RT5645_EQ_FC_HIP1 0xae
+#define RT5645_EQ_GN_HIP1 0xaf
+#define RT5645_EQ_FC_HIP2 0xb0
+#define RT5645_EQ_BW_HIP2 0xb1
+#define RT5645_EQ_GN_HIP2 0xb2
+#define RT5645_EQ_PRE_VOL 0xb3
+#define RT5645_EQ_PST_VOL 0xb4
+
+
+/* global definition */
+#define RT5645_L_MUTE (0x1 << 15)
+#define RT5645_L_MUTE_SFT 15
+#define RT5645_VOL_L_MUTE (0x1 << 14)
+#define RT5645_VOL_L_SFT 14
+#define RT5645_R_MUTE (0x1 << 7)
+#define RT5645_R_MUTE_SFT 7
+#define RT5645_VOL_R_MUTE (0x1 << 6)
+#define RT5645_VOL_R_SFT 6
+#define RT5645_L_VOL_MASK (0x3f << 8)
+#define RT5645_L_VOL_SFT 8
+#define RT5645_R_VOL_MASK (0x3f)
+#define RT5645_R_VOL_SFT 0
+
+/* IN1 Control 1 (0x0a) */
+#define RT5645_CBJ_BST1_MASK (0xf << 12)
+#define RT5645_CBJ_BST1_SFT (12)
+#define RT5645_CBJ_JD_HP_EN (0x1 << 9)
+#define RT5645_CBJ_JD_MIC_EN (0x1 << 8)
+#define RT5645_CBJ_JD_MIC_SW_EN (0x1 << 7)
+#define RT5645_CBJ_MIC_SEL_R (0x1 << 6)
+#define RT5645_CBJ_MIC_SEL_L (0x1 << 5)
+#define RT5645_CBJ_MIC_SW (0x1 << 4)
+#define RT5645_CBJ_BST1_EN (0x1 << 2)
+
+/* IN1 Control 2 (0x0b) */
+#define RT5645_CBJ_MN_JD (0x1 << 12)
+#define RT5645_CAPLESS_EN (0x1 << 11)
+#define RT5645_CBJ_DET_MODE (0x1 << 7)
+
+/* IN1 Control 3 (0x0c) */
+#define RT5645_CBJ_TIE_G_L (0x1 << 15)
+#define RT5645_CBJ_TIE_G_R (0x1 << 14)
+
+/* IN2 Control (0x0d) */
+#define RT5645_BST_MASK1 (0xf<<12)
+#define RT5645_BST_SFT1 12
+#define RT5645_BST_MASK2 (0xf<<8)
+#define RT5645_BST_SFT2 8
+#define RT5645_IN_DF2 (0x1 << 6)
+#define RT5645_IN_SFT2 6
+
+/* INL and INR Volume Control (0x0f) */
+#define RT5645_INL_SEL_MASK (0x1 << 15)
+#define RT5645_INL_SEL_SFT 15
+#define RT5645_INL_SEL_IN4P (0x0 << 15)
+#define RT5645_INL_SEL_MONOP (0x1 << 15)
+#define RT5645_INL_VOL_MASK (0x1f << 8)
+#define RT5645_INL_VOL_SFT 8
+#define RT5645_INR_SEL_MASK (0x1 << 7)
+#define RT5645_INR_SEL_SFT 7
+#define RT5645_INR_SEL_IN4N (0x0 << 7)
+#define RT5645_INR_SEL_MONON (0x1 << 7)
+#define RT5645_INR_VOL_MASK (0x1f)
+#define RT5645_INR_VOL_SFT 0
+
+/* DAC1 Digital Volume (0x19) */
+#define RT5645_DAC_L1_VOL_MASK (0xff << 8)
+#define RT5645_DAC_L1_VOL_SFT 8
+#define RT5645_DAC_R1_VOL_MASK (0xff)
+#define RT5645_DAC_R1_VOL_SFT 0
+
+/* DAC2 Digital Volume (0x1a) */
+#define RT5645_DAC_L2_VOL_MASK (0xff << 8)
+#define RT5645_DAC_L2_VOL_SFT 8
+#define RT5645_DAC_R2_VOL_MASK (0xff)
+#define RT5645_DAC_R2_VOL_SFT 0
+
+/* DAC2 Control (0x1b) */
+#define RT5645_M_DAC_L2_VOL (0x1 << 13)
+#define RT5645_M_DAC_L2_VOL_SFT 13
+#define RT5645_M_DAC_R2_VOL (0x1 << 12)
+#define RT5645_M_DAC_R2_VOL_SFT 12
+#define RT5645_DAC2_L_SEL_MASK (0x7 << 4)
+#define RT5645_DAC2_L_SEL_SFT 4
+#define RT5645_DAC2_R_SEL_MASK (0x7 << 0)
+#define RT5645_DAC2_R_SEL_SFT 0
+
+/* ADC Digital Volume Control (0x1c) */
+#define RT5645_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5645_ADC_L_VOL_SFT 8
+#define RT5645_ADC_R_VOL_MASK (0x7f)
+#define RT5645_ADC_R_VOL_SFT 0
+
+/* Mono ADC Digital Volume Control (0x1d) */
+#define RT5645_MONO_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5645_MONO_ADC_L_VOL_SFT 8
+#define RT5645_MONO_ADC_R_VOL_MASK (0x7f)
+#define RT5645_MONO_ADC_R_VOL_SFT 0
+
+/* ADC Boost Volume Control (0x1e) */
+#define RT5645_STO1_ADC_L_BST_MASK (0x3 << 14)
+#define RT5645_STO1_ADC_L_BST_SFT 14
+#define RT5645_STO1_ADC_R_BST_MASK (0x3 << 12)
+#define RT5645_STO1_ADC_R_BST_SFT 12
+#define RT5645_STO1_ADC_COMP_MASK (0x3 << 10)
+#define RT5645_STO1_ADC_COMP_SFT 10
+#define RT5645_STO2_ADC_L_BST_MASK (0x3 << 8)
+#define RT5645_STO2_ADC_L_BST_SFT 8
+#define RT5645_STO2_ADC_R_BST_MASK (0x3 << 6)
+#define RT5645_STO2_ADC_R_BST_SFT 6
+#define RT5645_STO2_ADC_COMP_MASK (0x3 << 4)
+#define RT5645_STO2_ADC_COMP_SFT 4
+
+/* Stereo2 ADC Mixer Control (0x26) */
+#define RT5645_STO2_ADC_SRC_MASK (0x1 << 15)
+#define RT5645_STO2_ADC_SRC_SFT 15
+
+/* Stereo ADC Mixer Control (0x27) */
+#define RT5645_M_ADC_L1 (0x1 << 14)
+#define RT5645_M_ADC_L1_SFT 14
+#define RT5645_M_ADC_L2 (0x1 << 13)
+#define RT5645_M_ADC_L2_SFT 13
+#define RT5645_ADC_1_SRC_MASK (0x1 << 12)
+#define RT5645_ADC_1_SRC_SFT 12
+#define RT5645_ADC_1_SRC_ADC (0x1 << 12)
+#define RT5645_ADC_1_SRC_DACMIX (0x0 << 12)
+#define RT5645_ADC_2_SRC_MASK (0x1 << 11)
+#define RT5645_ADC_2_SRC_SFT 11
+#define RT5645_DMIC_SRC_MASK (0x1 << 8)
+#define RT5645_DMIC_SRC_SFT 8
+#define RT5645_M_ADC_R1 (0x1 << 6)
+#define RT5645_M_ADC_R1_SFT 6
+#define RT5645_M_ADC_R2 (0x1 << 5)
+#define RT5645_M_ADC_R2_SFT 5
+#define RT5645_DMIC3_SRC_MASK (0x1 << 1)
+#define RT5645_DMIC3_SRC_SFT 0
+
+/* Mono ADC Mixer Control (0x28) */
+#define RT5645_M_MONO_ADC_L1 (0x1 << 14)
+#define RT5645_M_MONO_ADC_L1_SFT 14
+#define RT5645_M_MONO_ADC_L2 (0x1 << 13)
+#define RT5645_M_MONO_ADC_L2_SFT 13
+#define RT5645_MONO_ADC_L1_SRC_MASK (0x1 << 12)
+#define RT5645_MONO_ADC_L1_SRC_SFT 12
+#define RT5645_MONO_ADC_L1_SRC_DACMIXL (0x0 << 12)
+#define RT5645_MONO_ADC_L1_SRC_ADCL (0x1 << 12)
+#define RT5645_MONO_ADC_L2_SRC_MASK (0x1 << 11)
+#define RT5645_MONO_ADC_L2_SRC_SFT 11
+#define RT5645_MONO_DMIC_L_SRC_MASK (0x1 << 8)
+#define RT5645_MONO_DMIC_L_SRC_SFT 8
+#define RT5645_M_MONO_ADC_R1 (0x1 << 6)
+#define RT5645_M_MONO_ADC_R1_SFT 6
+#define RT5645_M_MONO_ADC_R2 (0x1 << 5)
+#define RT5645_M_MONO_ADC_R2_SFT 5
+#define RT5645_MONO_ADC_R1_SRC_MASK (0x1 << 4)
+#define RT5645_MONO_ADC_R1_SRC_SFT 4
+#define RT5645_MONO_ADC_R1_SRC_ADCR (0x1 << 4)
+#define RT5645_MONO_ADC_R1_SRC_DACMIXR (0x0 << 4)
+#define RT5645_MONO_ADC_R2_SRC_MASK (0x1 << 3)
+#define RT5645_MONO_ADC_R2_SRC_SFT 3
+#define RT5645_MONO_DMIC_R_SRC_MASK (0x3)
+#define RT5645_MONO_DMIC_R_SRC_SFT 0
+
+/* ADC Mixer to DAC Mixer Control (0x29) */
+#define RT5645_M_ADCMIX_L (0x1 << 15)
+#define RT5645_M_ADCMIX_L_SFT 15
+#define RT5645_M_DAC1_L (0x1 << 14)
+#define RT5645_M_DAC1_L_SFT 14
+#define RT5645_DAC1_R_SEL_MASK (0x3 << 10)
+#define RT5645_DAC1_R_SEL_SFT 10
+#define RT5645_DAC1_R_SEL_IF1 (0x0 << 10)
+#define RT5645_DAC1_R_SEL_IF2 (0x1 << 10)
+#define RT5645_DAC1_R_SEL_IF3 (0x2 << 10)
+#define RT5645_DAC1_R_SEL_IF4 (0x3 << 10)
+#define RT5645_DAC1_L_SEL_MASK (0x3 << 8)
+#define RT5645_DAC1_L_SEL_SFT 8
+#define RT5645_DAC1_L_SEL_IF1 (0x0 << 8)
+#define RT5645_DAC1_L_SEL_IF2 (0x1 << 8)
+#define RT5645_DAC1_L_SEL_IF3 (0x2 << 8)
+#define RT5645_DAC1_L_SEL_IF4 (0x3 << 8)
+#define RT5645_M_ADCMIX_R (0x1 << 7)
+#define RT5645_M_ADCMIX_R_SFT 7
+#define RT5645_M_DAC1_R (0x1 << 6)
+#define RT5645_M_DAC1_R_SFT 6
+
+/* Stereo DAC Mixer Control (0x2a) */
+#define RT5645_M_DAC_L1 (0x1 << 14)
+#define RT5645_M_DAC_L1_SFT 14
+#define RT5645_DAC_L1_STO_L_VOL_MASK (0x1 << 13)
+#define RT5645_DAC_L1_STO_L_VOL_SFT 13
+#define RT5645_M_DAC_L2 (0x1 << 12)
+#define RT5645_M_DAC_L2_SFT 12
+#define RT5645_DAC_L2_STO_L_VOL_MASK (0x1 << 11)
+#define RT5645_DAC_L2_STO_L_VOL_SFT 11
+#define RT5645_M_ANC_DAC_L (0x1 << 10)
+#define RT5645_M_ANC_DAC_L_SFT 10
+#define RT5645_M_DAC_R1_STO_L (0x1 << 9)
+#define RT5645_M_DAC_R1_STO_L_SFT 9
+#define RT5645_DAC_R1_STO_L_VOL_MASK (0x1 << 8)
+#define RT5645_DAC_R1_STO_L_VOL_SFT 8
+#define RT5645_M_DAC_R1 (0x1 << 6)
+#define RT5645_M_DAC_R1_SFT 6
+#define RT5645_DAC_R1_STO_R_VOL_MASK (0x1 << 5)
+#define RT5645_DAC_R1_STO_R_VOL_SFT 5
+#define RT5645_M_DAC_R2 (0x1 << 4)
+#define RT5645_M_DAC_R2_SFT 4
+#define RT5645_DAC_R2_STO_R_VOL_MASK (0x1 << 3)
+#define RT5645_DAC_R2_STO_R_VOL_SFT 3
+#define RT5645_M_ANC_DAC_R (0x1 << 2)
+#define RT5645_M_ANC_DAC_R_SFT 2
+#define RT5645_M_DAC_L1_STO_R (0x1 << 1)
+#define RT5645_M_DAC_L1_STO_R_SFT 1
+#define RT5645_DAC_L1_STO_R_VOL_MASK (0x1)
+#define RT5645_DAC_L1_STO_R_VOL_SFT 0
+
+/* Mono DAC Mixer Control (0x2b) */
+#define RT5645_M_DAC_L1_MONO_L (0x1 << 14)
+#define RT5645_M_DAC_L1_MONO_L_SFT 14
+#define RT5645_DAC_L1_MONO_L_VOL_MASK (0x1 << 13)
+#define RT5645_DAC_L1_MONO_L_VOL_SFT 13
+#define RT5645_M_DAC_L2_MONO_L (0x1 << 12)
+#define RT5645_M_DAC_L2_MONO_L_SFT 12
+#define RT5645_DAC_L2_MONO_L_VOL_MASK (0x1 << 11)
+#define RT5645_DAC_L2_MONO_L_VOL_SFT 11
+#define RT5645_M_DAC_R2_MONO_L (0x1 << 10)
+#define RT5645_M_DAC_R2_MONO_L_SFT 10
+#define RT5645_DAC_R2_MONO_L_VOL_MASK (0x1 << 9)
+#define RT5645_DAC_R2_MONO_L_VOL_SFT 9
+#define RT5645_M_DAC_R1_MONO_R (0x1 << 6)
+#define RT5645_M_DAC_R1_MONO_R_SFT 6
+#define RT5645_DAC_R1_MONO_R_VOL_MASK (0x1 << 5)
+#define RT5645_DAC_R1_MONO_R_VOL_SFT 5
+#define RT5645_M_DAC_R2_MONO_R (0x1 << 4)
+#define RT5645_M_DAC_R2_MONO_R_SFT 4
+#define RT5645_DAC_R2_MONO_R_VOL_MASK (0x1 << 3)
+#define RT5645_DAC_R2_MONO_R_VOL_SFT 3
+#define RT5645_M_DAC_L2_MONO_R (0x1 << 2)
+#define RT5645_M_DAC_L2_MONO_R_SFT 2
+#define RT5645_DAC_L2_MONO_R_VOL_MASK (0x1 << 1)
+#define RT5645_DAC_L2_MONO_R_VOL_SFT 1
+
+/* Digital Mixer Control (0x2c) */
+#define RT5645_M_STO_L_DAC_L (0x1 << 15)
+#define RT5645_M_STO_L_DAC_L_SFT 15
+#define RT5645_STO_L_DAC_L_VOL_MASK (0x1 << 14)
+#define RT5645_STO_L_DAC_L_VOL_SFT 14
+#define RT5645_M_DAC_L2_DAC_L (0x1 << 13)
+#define RT5645_M_DAC_L2_DAC_L_SFT 13
+#define RT5645_DAC_L2_DAC_L_VOL_MASK (0x1 << 12)
+#define RT5645_DAC_L2_DAC_L_VOL_SFT 12
+#define RT5645_M_STO_R_DAC_R (0x1 << 11)
+#define RT5645_M_STO_R_DAC_R_SFT 11
+#define RT5645_STO_R_DAC_R_VOL_MASK (0x1 << 10)
+#define RT5645_STO_R_DAC_R_VOL_SFT 10
+#define RT5645_M_DAC_R2_DAC_R (0x1 << 9)
+#define RT5645_M_DAC_R2_DAC_R_SFT 9
+#define RT5645_DAC_R2_DAC_R_VOL_MASK (0x1 << 8)
+#define RT5645_DAC_R2_DAC_R_VOL_SFT 8
+#define RT5645_M_DAC_R2_DAC_L (0x1 << 7)
+#define RT5645_M_DAC_R2_DAC_L_SFT 7
+#define RT5645_DAC_R2_DAC_L_VOL_MASK (0x1 << 6)
+#define RT5645_DAC_R2_DAC_L_VOL_SFT 6
+#define RT5645_M_DAC_L2_DAC_R (0x1 << 5)
+#define RT5645_M_DAC_L2_DAC_R_SFT 5
+#define RT5645_DAC_L2_DAC_R_VOL_MASK (0x1 << 4)
+#define RT5645_DAC_L2_DAC_R_VOL_SFT 4
+
+/* Digital Interface Data Control (0x2f) */
+#define RT5645_IF1_ADC2_IN_SEL (0x1 << 15)
+#define RT5645_IF1_ADC2_IN_SFT 15
+#define RT5645_IF2_ADC_IN_MASK (0x7 << 12)
+#define RT5645_IF2_ADC_IN_SFT 12
+#define RT5645_IF2_DAC_SEL_MASK (0x3 << 10)
+#define RT5645_IF2_DAC_SEL_SFT 10
+#define RT5645_IF2_ADC_SEL_MASK (0x3 << 8)
+#define RT5645_IF2_ADC_SEL_SFT 8
+#define RT5645_IF3_DAC_SEL_MASK (0x3 << 6)
+#define RT5645_IF3_DAC_SEL_SFT 6
+#define RT5645_IF3_ADC_SEL_MASK (0x3 << 4)
+#define RT5645_IF3_ADC_SEL_SFT 4
+#define RT5645_IF3_ADC_IN_MASK (0x7)
+#define RT5645_IF3_ADC_IN_SFT 0
+
+/* PDM Output Control (0x31) */
+#define RT5645_PDM1_L_MASK (0x1 << 15)
+#define RT5645_PDM1_L_SFT 15
+#define RT5645_M_PDM1_L (0x1 << 14)
+#define RT5645_M_PDM1_L_SFT 14
+#define RT5645_PDM1_R_MASK (0x1 << 13)
+#define RT5645_PDM1_R_SFT 13
+#define RT5645_M_PDM1_R (0x1 << 12)
+#define RT5645_M_PDM1_R_SFT 12
+#define RT5645_PDM2_L_MASK (0x1 << 11)
+#define RT5645_PDM2_L_SFT 11
+#define RT5645_M_PDM2_L (0x1 << 10)
+#define RT5645_M_PDM2_L_SFT 10
+#define RT5645_PDM2_R_MASK (0x1 << 9)
+#define RT5645_PDM2_R_SFT 9
+#define RT5645_M_PDM2_R (0x1 << 8)
+#define RT5645_M_PDM2_R_SFT 8
+#define RT5645_PDM2_BUSY (0x1 << 7)
+#define RT5645_PDM1_BUSY (0x1 << 6)
+#define RT5645_PDM_PATTERN (0x1 << 5)
+#define RT5645_PDM_GAIN (0x1 << 4)
+#define RT5645_PDM_DIV_MASK (0x3)
+
+/* REC Left Mixer Control 1 (0x3b) */
+#define RT5645_G_HP_L_RM_L_MASK (0x7 << 13)
+#define RT5645_G_HP_L_RM_L_SFT 13
+#define RT5645_G_IN_L_RM_L_MASK (0x7 << 10)
+#define RT5645_G_IN_L_RM_L_SFT 10
+#define RT5645_G_BST4_RM_L_MASK (0x7 << 7)
+#define RT5645_G_BST4_RM_L_SFT 7
+#define RT5645_G_BST3_RM_L_MASK (0x7 << 4)
+#define RT5645_G_BST3_RM_L_SFT 4
+#define RT5645_G_BST2_RM_L_MASK (0x7 << 1)
+#define RT5645_G_BST2_RM_L_SFT 1
+
+/* REC Left Mixer Control 2 (0x3c) */
+#define RT5645_G_BST1_RM_L_MASK (0x7 << 13)
+#define RT5645_G_BST1_RM_L_SFT 13
+#define RT5645_G_OM_L_RM_L_MASK (0x7 << 10)
+#define RT5645_G_OM_L_RM_L_SFT 10
+#define RT5645_M_MM_L_RM_L (0x1 << 6)
+#define RT5645_M_MM_L_RM_L_SFT 6
+#define RT5645_M_IN_L_RM_L (0x1 << 5)
+#define RT5645_M_IN_L_RM_L_SFT 5
+#define RT5645_M_HP_L_RM_L (0x1 << 4)
+#define RT5645_M_HP_L_RM_L_SFT 4
+#define RT5645_M_BST3_RM_L (0x1 << 3)
+#define RT5645_M_BST3_RM_L_SFT 3
+#define RT5645_M_BST2_RM_L (0x1 << 2)
+#define RT5645_M_BST2_RM_L_SFT 2
+#define RT5645_M_BST1_RM_L (0x1 << 1)
+#define RT5645_M_BST1_RM_L_SFT 1
+#define RT5645_M_OM_L_RM_L (0x1)
+#define RT5645_M_OM_L_RM_L_SFT 0
+
+/* REC Right Mixer Control 1 (0x3d) */
+#define RT5645_G_HP_R_RM_R_MASK (0x7 << 13)
+#define RT5645_G_HP_R_RM_R_SFT 13
+#define RT5645_G_IN_R_RM_R_MASK (0x7 << 10)
+#define RT5645_G_IN_R_RM_R_SFT 10
+#define RT5645_G_BST4_RM_R_MASK (0x7 << 7)
+#define RT5645_G_BST4_RM_R_SFT 7
+#define RT5645_G_BST3_RM_R_MASK (0x7 << 4)
+#define RT5645_G_BST3_RM_R_SFT 4
+#define RT5645_G_BST2_RM_R_MASK (0x7 << 1)
+#define RT5645_G_BST2_RM_R_SFT 1
+
+/* REC Right Mixer Control 2 (0x3e) */
+#define RT5645_G_BST1_RM_R_MASK (0x7 << 13)
+#define RT5645_G_BST1_RM_R_SFT 13
+#define RT5645_G_OM_R_RM_R_MASK (0x7 << 10)
+#define RT5645_G_OM_R_RM_R_SFT 10
+#define RT5645_M_MM_R_RM_R (0x1 << 6)
+#define RT5645_M_MM_R_RM_R_SFT 6
+#define RT5645_M_IN_R_RM_R (0x1 << 5)
+#define RT5645_M_IN_R_RM_R_SFT 5
+#define RT5645_M_HP_R_RM_R (0x1 << 4)
+#define RT5645_M_HP_R_RM_R_SFT 4
+#define RT5645_M_BST3_RM_R (0x1 << 3)
+#define RT5645_M_BST3_RM_R_SFT 3
+#define RT5645_M_BST2_RM_R (0x1 << 2)
+#define RT5645_M_BST2_RM_R_SFT 2
+#define RT5645_M_BST1_RM_R (0x1 << 1)
+#define RT5645_M_BST1_RM_R_SFT 1
+#define RT5645_M_OM_R_RM_R (0x1)
+#define RT5645_M_OM_R_RM_R_SFT 0
+
+/* HPOMIX Control (0x40) (0x42) */
+#define RT5645_M_BST1_HV (0x1 << 4)
+#define RT5645_M_BST1_HV_SFT 4
+#define RT5645_M_BST2_HV (0x1 << 4)
+#define RT5645_M_BST2_HV_SFT 4
+#define RT5645_M_BST3_HV (0x1 << 3)
+#define RT5645_M_BST3_HV_SFT 3
+#define RT5645_M_IN_HV (0x1 << 2)
+#define RT5645_M_IN_HV_SFT 2
+#define RT5645_M_DAC2_HV (0x1 << 1)
+#define RT5645_M_DAC2_HV_SFT 1
+#define RT5645_M_DAC1_HV (0x1 << 0)
+#define RT5645_M_DAC1_HV_SFT 0
+
+/* HPMIX Control (0x45) */
+#define RT5645_M_DAC1_HM (0x1 << 14)
+#define RT5645_M_DAC1_HM_SFT 14
+#define RT5645_M_HPVOL_HM (0x1 << 13)
+#define RT5645_M_HPVOL_HM_SFT 13
+
+/* SPK Left Mixer Control (0x46) */
+#define RT5645_G_RM_L_SM_L_MASK (0x3 << 14)
+#define RT5645_G_RM_L_SM_L_SFT 14
+#define RT5645_G_IN_L_SM_L_MASK (0x3 << 12)
+#define RT5645_G_IN_L_SM_L_SFT 12
+#define RT5645_G_DAC_L1_SM_L_MASK (0x3 << 10)
+#define RT5645_G_DAC_L1_SM_L_SFT 10
+#define RT5645_G_DAC_L2_SM_L_MASK (0x3 << 8)
+#define RT5645_G_DAC_L2_SM_L_SFT 8
+#define RT5645_G_OM_L_SM_L_MASK (0x3 << 6)
+#define RT5645_G_OM_L_SM_L_SFT 6
+#define RT5645_M_BST1_L_SM_L (0x1 << 5)
+#define RT5645_M_BST1_L_SM_L_SFT 5
+#define RT5645_M_IN_L_SM_L (0x1 << 3)
+#define RT5645_M_IN_L_SM_L_SFT 3
+#define RT5645_M_DAC_L1_SM_L (0x1 << 1)
+#define RT5645_M_DAC_L1_SM_L_SFT 1
+#define RT5645_M_DAC_L2_SM_L (0x1 << 2)
+#define RT5645_M_DAC_L2_SM_L_SFT 2
+#define RT5645_M_BST3_L_SM_L (0x1 << 4)
+#define RT5645_M_BST3_L_SM_L_SFT 4
+
+/* SPK Right Mixer Control (0x47) */
+#define RT5645_G_RM_R_SM_R_MASK (0x3 << 14)
+#define RT5645_G_RM_R_SM_R_SFT 14
+#define RT5645_G_IN_R_SM_R_MASK (0x3 << 12)
+#define RT5645_G_IN_R_SM_R_SFT 12
+#define RT5645_G_DAC_R1_SM_R_MASK (0x3 << 10)
+#define RT5645_G_DAC_R1_SM_R_SFT 10
+#define RT5645_G_DAC_R2_SM_R_MASK (0x3 << 8)
+#define RT5645_G_DAC_R2_SM_R_SFT 8
+#define RT5645_G_OM_R_SM_R_MASK (0x3 << 6)
+#define RT5645_G_OM_R_SM_R_SFT 6
+#define RT5645_M_BST2_R_SM_R (0x1 << 5)
+#define RT5645_M_BST2_R_SM_R_SFT 5
+#define RT5645_M_IN_R_SM_R (0x1 << 3)
+#define RT5645_M_IN_R_SM_R_SFT 3
+#define RT5645_M_DAC_R1_SM_R (0x1 << 1)
+#define RT5645_M_DAC_R1_SM_R_SFT 1
+#define RT5645_M_DAC_R2_SM_R (0x1 << 2)
+#define RT5645_M_DAC_R2_SM_R_SFT 2
+#define RT5645_M_BST3_R_SM_R (0x1 << 4)
+#define RT5645_M_BST3_R_SM_R_SFT 4
+
+/* SPOLMIX Control (0x48) */
+#define RT5645_M_DAC_L1_SPM_L (0x1 << 15)
+#define RT5645_M_DAC_L1_SPM_L_SFT 15
+#define RT5645_M_DAC_R1_SPM_L (0x1 << 14)
+#define RT5645_M_DAC_R1_SPM_L_SFT 14
+#define RT5645_M_SV_L_SPM_L (0x1 << 13)
+#define RT5645_M_SV_L_SPM_L_SFT 13
+#define RT5645_M_SV_R_SPM_L (0x1 << 12)
+#define RT5645_M_SV_R_SPM_L_SFT 12
+#define RT5645_M_BST3_SPM_L (0x1 << 11)
+#define RT5645_M_BST3_SPM_L_SFT 11
+#define RT5645_M_DAC_R1_SPM_R (0x1 << 2)
+#define RT5645_M_DAC_R1_SPM_R_SFT 2
+#define RT5645_M_BST3_SPM_R (0x1 << 1)
+#define RT5645_M_BST3_SPM_R_SFT 1
+#define RT5645_M_SV_R_SPM_R (0x1 << 0)
+#define RT5645_M_SV_R_SPM_R_SFT 0
+
+/* Mono Output Mixer Control (0x4c) */
+#define RT5645_M_OV_L_MM (0x1 << 9)
+#define RT5645_M_OV_L_MM_SFT 9
+#define RT5645_M_DAC_L2_MA (0x1 << 8)
+#define RT5645_M_DAC_L2_MA_SFT 8
+#define RT5645_G_MONOMIX_MASK (0x1 << 10)
+#define RT5645_G_MONOMIX_SFT 10
+#define RT5645_M_BST2_MM (0x1 << 4)
+#define RT5645_M_BST2_MM_SFT 4
+#define RT5645_M_DAC_R1_MM (0x1 << 3)
+#define RT5645_M_DAC_R1_MM_SFT 3
+#define RT5645_M_DAC_R2_MM (0x1 << 2)
+#define RT5645_M_DAC_R2_MM_SFT 2
+#define RT5645_M_DAC_L2_MM (0x1 << 1)
+#define RT5645_M_DAC_L2_MM_SFT 1
+#define RT5645_M_BST3_MM (0x1 << 0)
+#define RT5645_M_BST3_MM_SFT 0
+
+/* Output Left Mixer Control 1 (0x4d) */
+#define RT5645_G_BST3_OM_L_MASK (0x7 << 13)
+#define RT5645_G_BST3_OM_L_SFT 13
+#define RT5645_G_BST2_OM_L_MASK (0x7 << 10)
+#define RT5645_G_BST2_OM_L_SFT 10
+#define RT5645_G_BST1_OM_L_MASK (0x7 << 7)
+#define RT5645_G_BST1_OM_L_SFT 7
+#define RT5645_G_IN_L_OM_L_MASK (0x7 << 4)
+#define RT5645_G_IN_L_OM_L_SFT 4
+#define RT5645_G_RM_L_OM_L_MASK (0x7 << 1)
+#define RT5645_G_RM_L_OM_L_SFT 1
+
+/* Output Left Mixer Control 2 (0x4e) */
+#define RT5645_G_DAC_R2_OM_L_MASK (0x7 << 13)
+#define RT5645_G_DAC_R2_OM_L_SFT 13
+#define RT5645_G_DAC_L2_OM_L_MASK (0x7 << 10)
+#define RT5645_G_DAC_L2_OM_L_SFT 10
+#define RT5645_G_DAC_L1_OM_L_MASK (0x7 << 7)
+#define RT5645_G_DAC_L1_OM_L_SFT 7
+
+/* Output Left Mixer Control 3 (0x4f) */
+#define RT5645_M_BST3_OM_L (0x1 << 4)
+#define RT5645_M_BST3_OM_L_SFT 4
+#define RT5645_M_BST1_OM_L (0x1 << 3)
+#define RT5645_M_BST1_OM_L_SFT 3
+#define RT5645_M_IN_L_OM_L (0x1 << 2)
+#define RT5645_M_IN_L_OM_L_SFT 2
+#define RT5645_M_DAC_L2_OM_L (0x1 << 1)
+#define RT5645_M_DAC_L2_OM_L_SFT 1
+#define RT5645_M_DAC_L1_OM_L (0x1)
+#define RT5645_M_DAC_L1_OM_L_SFT 0
+
+/* Output Right Mixer Control 1 (0x50) */
+#define RT5645_G_BST4_OM_R_MASK (0x7 << 13)
+#define RT5645_G_BST4_OM_R_SFT 13
+#define RT5645_G_BST2_OM_R_MASK (0x7 << 10)
+#define RT5645_G_BST2_OM_R_SFT 10
+#define RT5645_G_BST1_OM_R_MASK (0x7 << 7)
+#define RT5645_G_BST1_OM_R_SFT 7
+#define RT5645_G_IN_R_OM_R_MASK (0x7 << 4)
+#define RT5645_G_IN_R_OM_R_SFT 4
+#define RT5645_G_RM_R_OM_R_MASK (0x7 << 1)
+#define RT5645_G_RM_R_OM_R_SFT 1
+
+/* Output Right Mixer Control 2 (0x51) */
+#define RT5645_G_DAC_L2_OM_R_MASK (0x7 << 13)
+#define RT5645_G_DAC_L2_OM_R_SFT 13
+#define RT5645_G_DAC_R2_OM_R_MASK (0x7 << 10)
+#define RT5645_G_DAC_R2_OM_R_SFT 10
+#define RT5645_G_DAC_R1_OM_R_MASK (0x7 << 7)
+#define RT5645_G_DAC_R1_OM_R_SFT 7
+
+/* Output Right Mixer Control 3 (0x52) */
+#define RT5645_M_BST3_OM_R (0x1 << 4)
+#define RT5645_M_BST3_OM_R_SFT 4
+#define RT5645_M_BST2_OM_R (0x1 << 3)
+#define RT5645_M_BST2_OM_R_SFT 3
+#define RT5645_M_IN_R_OM_R (0x1 << 2)
+#define RT5645_M_IN_R_OM_R_SFT 2
+#define RT5645_M_DAC_R2_OM_R (0x1 << 1)
+#define RT5645_M_DAC_R2_OM_R_SFT 1
+#define RT5645_M_DAC_R1_OM_R (0x1)
+#define RT5645_M_DAC_R1_OM_R_SFT 0
+
+/* LOUT Mixer Control (0x53) */
+#define RT5645_M_DAC_L1_LM (0x1 << 15)
+#define RT5645_M_DAC_L1_LM_SFT 15
+#define RT5645_M_DAC_R1_LM (0x1 << 14)
+#define RT5645_M_DAC_R1_LM_SFT 14
+#define RT5645_M_OV_L_LM (0x1 << 13)
+#define RT5645_M_OV_L_LM_SFT 13
+#define RT5645_M_OV_R_LM (0x1 << 12)
+#define RT5645_M_OV_R_LM_SFT 12
+#define RT5645_G_LOUTMIX_MASK (0x1 << 11)
+#define RT5645_G_LOUTMIX_SFT 11
+
+/* Power Management for Digital 1 (0x61) */
+#define RT5645_PWR_I2S1 (0x1 << 15)
+#define RT5645_PWR_I2S1_BIT 15
+#define RT5645_PWR_I2S2 (0x1 << 14)
+#define RT5645_PWR_I2S2_BIT 14
+#define RT5645_PWR_I2S3 (0x1 << 13)
+#define RT5645_PWR_I2S3_BIT 13
+#define RT5645_PWR_DAC_L1 (0x1 << 12)
+#define RT5645_PWR_DAC_L1_BIT 12
+#define RT5645_PWR_DAC_R1 (0x1 << 11)
+#define RT5645_PWR_DAC_R1_BIT 11
+#define RT5645_PWR_CLS_D_R (0x1 << 9)
+#define RT5645_PWR_CLS_D_R_BIT 9
+#define RT5645_PWR_CLS_D_L (0x1 << 8)
+#define RT5645_PWR_CLS_D_L_BIT 8
+#define RT5645_PWR_ADC_R (0x1 << 1)
+#define RT5645_PWR_ADC_R_BIT 1
+#define RT5645_PWR_DAC_L2 (0x1 << 7)
+#define RT5645_PWR_DAC_L2_BIT 7
+#define RT5645_PWR_DAC_R2 (0x1 << 6)
+#define RT5645_PWR_DAC_R2_BIT 6
+#define RT5645_PWR_ADC_L (0x1 << 2)
+#define RT5645_PWR_ADC_L_BIT 2
+#define RT5645_PWR_ADC_R (0x1 << 1)
+#define RT5645_PWR_ADC_R_BIT 1
+#define RT5645_PWR_CLS_D (0x1)
+#define RT5645_PWR_CLS_D_BIT 0
+
+/* Power Management for Digital 2 (0x62) */
+#define RT5645_PWR_ADC_S1F (0x1 << 15)
+#define RT5645_PWR_ADC_S1F_BIT 15
+#define RT5645_PWR_ADC_MF_L (0x1 << 14)
+#define RT5645_PWR_ADC_MF_L_BIT 14
+#define RT5645_PWR_ADC_MF_R (0x1 << 13)
+#define RT5645_PWR_ADC_MF_R_BIT 13
+#define RT5645_PWR_I2S_DSP (0x1 << 12)
+#define RT5645_PWR_I2S_DSP_BIT 12
+#define RT5645_PWR_DAC_S1F (0x1 << 11)
+#define RT5645_PWR_DAC_S1F_BIT 11
+#define RT5645_PWR_DAC_MF_L (0x1 << 10)
+#define RT5645_PWR_DAC_MF_L_BIT 10
+#define RT5645_PWR_DAC_MF_R (0x1 << 9)
+#define RT5645_PWR_DAC_MF_R_BIT 9
+#define RT5645_PWR_ADC_S2F (0x1 << 8)
+#define RT5645_PWR_ADC_S2F_BIT 8
+#define RT5645_PWR_PDM1 (0x1 << 7)
+#define RT5645_PWR_PDM1_BIT 7
+#define RT5645_PWR_PDM2 (0x1 << 6)
+#define RT5645_PWR_PDM2_BIT 6
+#define RT5645_PWR_IPTV (0x1 << 1)
+#define RT5645_PWR_IPTV_BIT 1
+#define RT5645_PWR_PAD (0x1)
+#define RT5645_PWR_PAD_BIT 0
+
+/* Power Management for Analog 1 (0x63) */
+#define RT5645_PWR_VREF1 (0x1 << 15)
+#define RT5645_PWR_VREF1_BIT 15
+#define RT5645_PWR_FV1 (0x1 << 14)
+#define RT5645_PWR_FV1_BIT 14
+#define RT5645_PWR_MB (0x1 << 13)
+#define RT5645_PWR_MB_BIT 13
+#define RT5645_PWR_LM (0x1 << 12)
+#define RT5645_PWR_LM_BIT 12
+#define RT5645_PWR_BG (0x1 << 11)
+#define RT5645_PWR_BG_BIT 11
+#define RT5645_PWR_MA (0x1 << 10)
+#define RT5645_PWR_MA_BIT 10
+#define RT5645_PWR_HP_L (0x1 << 7)
+#define RT5645_PWR_HP_L_BIT 7
+#define RT5645_PWR_HP_R (0x1 << 6)
+#define RT5645_PWR_HP_R_BIT 6
+#define RT5645_PWR_HA (0x1 << 5)
+#define RT5645_PWR_HA_BIT 5
+#define RT5645_PWR_VREF2 (0x1 << 4)
+#define RT5645_PWR_VREF2_BIT 4
+#define RT5645_PWR_FV2 (0x1 << 3)
+#define RT5645_PWR_FV2_BIT 3
+#define RT5645_LDO_SEL_MASK (0x3)
+#define RT5645_LDO_SEL_SFT 0
+
+/* Power Management for Analog 2 (0x64) */
+#define RT5645_PWR_BST1 (0x1 << 15)
+#define RT5645_PWR_BST1_BIT 15
+#define RT5645_PWR_BST2 (0x1 << 14)
+#define RT5645_PWR_BST2_BIT 14
+#define RT5645_PWR_BST3 (0x1 << 13)
+#define RT5645_PWR_BST3_BIT 13
+#define RT5645_PWR_BST4 (0x1 << 12)
+#define RT5645_PWR_BST4_BIT 12
+#define RT5645_PWR_MB1 (0x1 << 11)
+#define RT5645_PWR_MB1_BIT 11
+#define RT5645_PWR_MB2 (0x1 << 10)
+#define RT5645_PWR_MB2_BIT 10
+#define RT5645_PWR_PLL (0x1 << 9)
+#define RT5645_PWR_PLL_BIT 9
+#define RT5645_PWR_BST2_P (0x1 << 5)
+#define RT5645_PWR_BST2_P_BIT 5
+#define RT5645_PWR_BST3_P (0x1 << 4)
+#define RT5645_PWR_BST3_P_BIT 4
+#define RT5645_PWR_BST4_P (0x1 << 3)
+#define RT5645_PWR_BST4_P_BIT 3
+#define RT5645_PWR_JD1 (0x1 << 2)
+#define RT5645_PWR_JD1_BIT 2
+#define RT5645_PWR_JD (0x1 << 1)
+#define RT5645_PWR_JD_BIT 1
+
+/* Power Management for Mixer (0x65) */
+#define RT5645_PWR_OM_L (0x1 << 15)
+#define RT5645_PWR_OM_L_BIT 15
+#define RT5645_PWR_OM_R (0x1 << 14)
+#define RT5645_PWR_OM_R_BIT 14
+#define RT5645_PWR_SM_L (0x1 << 13)
+#define RT5645_PWR_SM_L_BIT 13
+#define RT5645_PWR_SM_R (0x1 << 12)
+#define RT5645_PWR_SM_R_BIT 12
+#define RT5645_PWR_RM_L (0x1 << 11)
+#define RT5645_PWR_RM_L_BIT 11
+#define RT5645_PWR_RM_R (0x1 << 10)
+#define RT5645_PWR_RM_R_BIT 10
+#define RT5645_PWR_MM (0x1 << 8)
+#define RT5645_PWR_MM_BIT 8
+#define RT5645_PWR_HM_L (0x1 << 7)
+#define RT5645_PWR_HM_L_BIT 7
+#define RT5645_PWR_HM_R (0x1 << 6)
+#define RT5645_PWR_HM_R_BIT 6
+#define RT5645_PWR_LDO2 (0x1 << 1)
+#define RT5645_PWR_LDO2_BIT 1
+
+/* Power Management for Volume (0x66) */
+#define RT5645_PWR_SV_L (0x1 << 15)
+#define RT5645_PWR_SV_L_BIT 15
+#define RT5645_PWR_SV_R (0x1 << 14)
+#define RT5645_PWR_SV_R_BIT 14
+#define RT5645_PWR_HV_L (0x1 << 11)
+#define RT5645_PWR_HV_L_BIT 11
+#define RT5645_PWR_HV_R (0x1 << 10)
+#define RT5645_PWR_HV_R_BIT 10
+#define RT5645_PWR_IN_L (0x1 << 9)
+#define RT5645_PWR_IN_L_BIT 9
+#define RT5645_PWR_IN_R (0x1 << 8)
+#define RT5645_PWR_IN_R_BIT 8
+#define RT5645_PWR_MIC_DET (0x1 << 5)
+#define RT5645_PWR_MIC_DET_BIT 5
+
+/* I2S1/2 Audio Serial Data Port Control (0x70 0x71) */
+#define RT5645_I2S_MS_MASK (0x1 << 15)
+#define RT5645_I2S_MS_SFT 15
+#define RT5645_I2S_MS_M (0x0 << 15)
+#define RT5645_I2S_MS_S (0x1 << 15)
+#define RT5645_I2S_O_CP_MASK (0x3 << 10)
+#define RT5645_I2S_O_CP_SFT 10
+#define RT5645_I2S_O_CP_OFF (0x0 << 10)
+#define RT5645_I2S_O_CP_U_LAW (0x1 << 10)
+#define RT5645_I2S_O_CP_A_LAW (0x2 << 10)
+#define RT5645_I2S_I_CP_MASK (0x3 << 8)
+#define RT5645_I2S_I_CP_SFT 8
+#define RT5645_I2S_I_CP_OFF (0x0 << 8)
+#define RT5645_I2S_I_CP_U_LAW (0x1 << 8)
+#define RT5645_I2S_I_CP_A_LAW (0x2 << 8)
+#define RT5645_I2S_BP_MASK (0x1 << 7)
+#define RT5645_I2S_BP_SFT 7
+#define RT5645_I2S_BP_NOR (0x0 << 7)
+#define RT5645_I2S_BP_INV (0x1 << 7)
+#define RT5645_I2S_DL_MASK (0x3 << 2)
+#define RT5645_I2S_DL_SFT 2
+#define RT5645_I2S_DL_16 (0x0 << 2)
+#define RT5645_I2S_DL_20 (0x1 << 2)
+#define RT5645_I2S_DL_24 (0x2 << 2)
+#define RT5645_I2S_DL_8 (0x3 << 2)
+#define RT5645_I2S_DF_MASK (0x3)
+#define RT5645_I2S_DF_SFT 0
+#define RT5645_I2S_DF_I2S (0x0)
+#define RT5645_I2S_DF_LEFT (0x1)
+#define RT5645_I2S_DF_PCM_A (0x2)
+#define RT5645_I2S_DF_PCM_B (0x3)
+
+/* I2S2 Audio Serial Data Port Control (0x71) */
+#define RT5645_I2S2_SDI_MASK (0x1 << 6)
+#define RT5645_I2S2_SDI_SFT 6
+#define RT5645_I2S2_SDI_I2S1 (0x0 << 6)
+#define RT5645_I2S2_SDI_I2S2 (0x1 << 6)
+
+/* ADC/DAC Clock Control 1 (0x73) */
+#define RT5645_I2S_BCLK_MS1_MASK (0x1 << 15)
+#define RT5645_I2S_BCLK_MS1_SFT 15
+#define RT5645_I2S_BCLK_MS1_32 (0x0 << 15)
+#define RT5645_I2S_BCLK_MS1_64 (0x1 << 15)
+#define RT5645_I2S_PD1_MASK (0x7 << 12)
+#define RT5645_I2S_PD1_SFT 12
+#define RT5645_I2S_PD1_1 (0x0 << 12)
+#define RT5645_I2S_PD1_2 (0x1 << 12)
+#define RT5645_I2S_PD1_3 (0x2 << 12)
+#define RT5645_I2S_PD1_4 (0x3 << 12)
+#define RT5645_I2S_PD1_6 (0x4 << 12)
+#define RT5645_I2S_PD1_8 (0x5 << 12)
+#define RT5645_I2S_PD1_12 (0x6 << 12)
+#define RT5645_I2S_PD1_16 (0x7 << 12)
+#define RT5645_I2S_BCLK_MS2_MASK (0x1 << 11)
+#define RT5645_I2S_BCLK_MS2_SFT 11
+#define RT5645_I2S_BCLK_MS2_32 (0x0 << 11)
+#define RT5645_I2S_BCLK_MS2_64 (0x1 << 11)
+#define RT5645_I2S_PD2_MASK (0x7 << 8)
+#define RT5645_I2S_PD2_SFT 8
+#define RT5645_I2S_PD2_1 (0x0 << 8)
+#define RT5645_I2S_PD2_2 (0x1 << 8)
+#define RT5645_I2S_PD2_3 (0x2 << 8)
+#define RT5645_I2S_PD2_4 (0x3 << 8)
+#define RT5645_I2S_PD2_6 (0x4 << 8)
+#define RT5645_I2S_PD2_8 (0x5 << 8)
+#define RT5645_I2S_PD2_12 (0x6 << 8)
+#define RT5645_I2S_PD2_16 (0x7 << 8)
+#define RT5645_I2S_BCLK_MS3_MASK (0x1 << 7)
+#define RT5645_I2S_BCLK_MS3_SFT 7
+#define RT5645_I2S_BCLK_MS3_32 (0x0 << 7)
+#define RT5645_I2S_BCLK_MS3_64 (0x1 << 7)
+#define RT5645_I2S_PD3_MASK (0x7 << 4)
+#define RT5645_I2S_PD3_SFT 4
+#define RT5645_I2S_PD3_1 (0x0 << 4)
+#define RT5645_I2S_PD3_2 (0x1 << 4)
+#define RT5645_I2S_PD3_3 (0x2 << 4)
+#define RT5645_I2S_PD3_4 (0x3 << 4)
+#define RT5645_I2S_PD3_6 (0x4 << 4)
+#define RT5645_I2S_PD3_8 (0x5 << 4)
+#define RT5645_I2S_PD3_12 (0x6 << 4)
+#define RT5645_I2S_PD3_16 (0x7 << 4)
+#define RT5645_DAC_OSR_MASK (0x3 << 2)
+#define RT5645_DAC_OSR_SFT 2
+#define RT5645_DAC_OSR_128 (0x0 << 2)
+#define RT5645_DAC_OSR_64 (0x1 << 2)
+#define RT5645_DAC_OSR_32 (0x2 << 2)
+#define RT5645_DAC_OSR_16 (0x3 << 2)
+#define RT5645_ADC_OSR_MASK (0x3)
+#define RT5645_ADC_OSR_SFT 0
+#define RT5645_ADC_OSR_128 (0x0)
+#define RT5645_ADC_OSR_64 (0x1)
+#define RT5645_ADC_OSR_32 (0x2)
+#define RT5645_ADC_OSR_16 (0x3)
+
+/* ADC/DAC Clock Control 2 (0x74) */
+#define RT5645_DAC_L_OSR_MASK (0x3 << 14)
+#define RT5645_DAC_L_OSR_SFT 14
+#define RT5645_DAC_L_OSR_128 (0x0 << 14)
+#define RT5645_DAC_L_OSR_64 (0x1 << 14)
+#define RT5645_DAC_L_OSR_32 (0x2 << 14)
+#define RT5645_DAC_L_OSR_16 (0x3 << 14)
+#define RT5645_ADC_R_OSR_MASK (0x3 << 12)
+#define RT5645_ADC_R_OSR_SFT 12
+#define RT5645_ADC_R_OSR_128 (0x0 << 12)
+#define RT5645_ADC_R_OSR_64 (0x1 << 12)
+#define RT5645_ADC_R_OSR_32 (0x2 << 12)
+#define RT5645_ADC_R_OSR_16 (0x3 << 12)
+#define RT5645_DAHPF_EN (0x1 << 11)
+#define RT5645_DAHPF_EN_SFT 11
+#define RT5645_ADHPF_EN (0x1 << 10)
+#define RT5645_ADHPF_EN_SFT 10
+
+/* Digital Microphone Control (0x75) */
+#define RT5645_DMIC_1_EN_MASK (0x1 << 15)
+#define RT5645_DMIC_1_EN_SFT 15
+#define RT5645_DMIC_1_DIS (0x0 << 15)
+#define RT5645_DMIC_1_EN (0x1 << 15)
+#define RT5645_DMIC_2_EN_MASK (0x1 << 14)
+#define RT5645_DMIC_2_EN_SFT 14
+#define RT5645_DMIC_2_DIS (0x0 << 14)
+#define RT5645_DMIC_2_EN (0x1 << 14)
+#define RT5645_DMIC_1L_LH_MASK (0x1 << 13)
+#define RT5645_DMIC_1L_LH_SFT 13
+#define RT5645_DMIC_1L_LH_FALLING (0x0 << 13)
+#define RT5645_DMIC_1L_LH_RISING (0x1 << 13)
+#define RT5645_DMIC_1R_LH_MASK (0x1 << 12)
+#define RT5645_DMIC_1R_LH_SFT 12
+#define RT5645_DMIC_1R_LH_FALLING (0x0 << 12)
+#define RT5645_DMIC_1R_LH_RISING (0x1 << 12)
+#define RT5645_DMIC_2_DP_MASK (0x3 << 10)
+#define RT5645_DMIC_2_DP_SFT 10
+#define RT5645_DMIC_2_DP_GPIO6 (0x0 << 10)
+#define RT5645_DMIC_2_DP_GPIO10 (0x1 << 10)
+#define RT5645_DMIC_2_DP_GPIO12 (0x2 << 10)
+#define RT5645_DMIC_2_DP_IN2P (0x3 << 10)
+#define RT5645_DMIC_2L_LH_MASK (0x1 << 9)
+#define RT5645_DMIC_2L_LH_SFT 9
+#define RT5645_DMIC_2L_LH_FALLING (0x0 << 9)
+#define RT5645_DMIC_2L_LH_RISING (0x1 << 9)
+#define RT5645_DMIC_2R_LH_MASK (0x1 << 8)
+#define RT5645_DMIC_2R_LH_SFT 8
+#define RT5645_DMIC_2R_LH_FALLING (0x0 << 8)
+#define RT5645_DMIC_2R_LH_RISING (0x1 << 8)
+#define RT5645_DMIC_CLK_MASK (0x7 << 5)
+#define RT5645_DMIC_CLK_SFT 5
+#define RT5645_DMIC_3_EN_MASK (0x1 << 4)
+#define RT5645_DMIC_3_EN_SFT 4
+#define RT5645_DMIC_3_DIS (0x0 << 4)
+#define RT5645_DMIC_3_EN (0x1 << 4)
+#define RT5645_DMIC_1_DP_MASK (0x3 << 0)
+#define RT5645_DMIC_1_DP_SFT 0
+#define RT5645_DMIC_1_DP_GPIO5 (0x0 << 0)
+#define RT5645_DMIC_1_DP_IN2N (0x1 << 0)
+#define RT5645_DMIC_1_DP_GPIO11 (0x2 << 0)
+
+/* TDM Control 1 (0x77) */
+#define RT5645_IF1_ADC_IN_MASK (0x3 << 8)
+#define RT5645_IF1_ADC_IN_SFT 8
+
+/* Global Clock Control (0x80) */
+#define RT5645_SCLK_SRC_MASK (0x3 << 14)
+#define RT5645_SCLK_SRC_SFT 14
+#define RT5645_SCLK_SRC_MCLK (0x0 << 14)
+#define RT5645_SCLK_SRC_PLL1 (0x1 << 14)
+#define RT5645_SCLK_SRC_RCCLK (0x2 << 14) /* 15MHz */
+#define RT5645_PLL1_SRC_MASK (0x3 << 12)
+#define RT5645_PLL1_SRC_SFT 12
+#define RT5645_PLL1_SRC_MCLK (0x0 << 12)
+#define RT5645_PLL1_SRC_BCLK1 (0x1 << 12)
+#define RT5645_PLL1_SRC_BCLK2 (0x2 << 12)
+#define RT5645_PLL1_SRC_BCLK3 (0x3 << 12)
+#define RT5645_PLL1_PD_MASK (0x1 << 3)
+#define RT5645_PLL1_PD_SFT 3
+#define RT5645_PLL1_PD_1 (0x0 << 3)
+#define RT5645_PLL1_PD_2 (0x1 << 3)
+
+#define RT5645_PLL_INP_MAX 40000000
+#define RT5645_PLL_INP_MIN 256000
+/* PLL M/N/K Code Control 1 (0x81) */
+#define RT5645_PLL_N_MAX 0x1ff
+#define RT5645_PLL_N_MASK (RT5645_PLL_N_MAX << 7)
+#define RT5645_PLL_N_SFT 7
+#define RT5645_PLL_K_MAX 0x1f
+#define RT5645_PLL_K_MASK (RT5645_PLL_K_MAX)
+#define RT5645_PLL_K_SFT 0
+
+/* PLL M/N/K Code Control 2 (0x82) */
+#define RT5645_PLL_M_MAX 0xf
+#define RT5645_PLL_M_MASK (RT5645_PLL_M_MAX << 12)
+#define RT5645_PLL_M_SFT 12
+#define RT5645_PLL_M_BP (0x1 << 11)
+#define RT5645_PLL_M_BP_SFT 11
+
+/* ASRC Control 1 (0x83) */
+#define RT5645_STO_T_MASK (0x1 << 15)
+#define RT5645_STO_T_SFT 15
+#define RT5645_STO_T_SCLK (0x0 << 15)
+#define RT5645_STO_T_LRCK1 (0x1 << 15)
+#define RT5645_M1_T_MASK (0x1 << 14)
+#define RT5645_M1_T_SFT 14
+#define RT5645_M1_T_I2S2 (0x0 << 14)
+#define RT5645_M1_T_I2S2_D3 (0x1 << 14)
+#define RT5645_I2S2_F_MASK (0x1 << 12)
+#define RT5645_I2S2_F_SFT 12
+#define RT5645_I2S2_F_I2S2_D2 (0x0 << 12)
+#define RT5645_I2S2_F_I2S1_TCLK (0x1 << 12)
+#define RT5645_DMIC_1_M_MASK (0x1 << 9)
+#define RT5645_DMIC_1_M_SFT 9
+#define RT5645_DMIC_1_M_NOR (0x0 << 9)
+#define RT5645_DMIC_1_M_ASYN (0x1 << 9)
+#define RT5645_DMIC_2_M_MASK (0x1 << 8)
+#define RT5645_DMIC_2_M_SFT 8
+#define RT5645_DMIC_2_M_NOR (0x0 << 8)
+#define RT5645_DMIC_2_M_ASYN (0x1 << 8)
+
+/* ASRC Control 2 (0x84) */
+#define RT5645_MDA_L_M_MASK (0x1 << 15)
+#define RT5645_MDA_L_M_SFT 15
+#define RT5645_MDA_L_M_NOR (0x0 << 15)
+#define RT5645_MDA_L_M_ASYN (0x1 << 15)
+#define RT5645_MDA_R_M_MASK (0x1 << 14)
+#define RT5645_MDA_R_M_SFT 14
+#define RT5645_MDA_R_M_NOR (0x0 << 14)
+#define RT5645_MDA_R_M_ASYN (0x1 << 14)
+#define RT5645_MAD_L_M_MASK (0x1 << 13)
+#define RT5645_MAD_L_M_SFT 13
+#define RT5645_MAD_L_M_NOR (0x0 << 13)
+#define RT5645_MAD_L_M_ASYN (0x1 << 13)
+#define RT5645_MAD_R_M_MASK (0x1 << 12)
+#define RT5645_MAD_R_M_SFT 12
+#define RT5645_MAD_R_M_NOR (0x0 << 12)
+#define RT5645_MAD_R_M_ASYN (0x1 << 12)
+#define RT5645_ADC_M_MASK (0x1 << 11)
+#define RT5645_ADC_M_SFT 11
+#define RT5645_ADC_M_NOR (0x0 << 11)
+#define RT5645_ADC_M_ASYN (0x1 << 11)
+#define RT5645_STO_DAC_M_MASK (0x1 << 5)
+#define RT5645_STO_DAC_M_SFT 5
+#define RT5645_STO_DAC_M_NOR (0x0 << 5)
+#define RT5645_STO_DAC_M_ASYN (0x1 << 5)
+#define RT5645_I2S1_R_D_MASK (0x1 << 4)
+#define RT5645_I2S1_R_D_SFT 4
+#define RT5645_I2S1_R_D_DIS (0x0 << 4)
+#define RT5645_I2S1_R_D_EN (0x1 << 4)
+#define RT5645_I2S2_R_D_MASK (0x1 << 3)
+#define RT5645_I2S2_R_D_SFT 3
+#define RT5645_I2S2_R_D_DIS (0x0 << 3)
+#define RT5645_I2S2_R_D_EN (0x1 << 3)
+#define RT5645_PRE_SCLK_MASK (0x3)
+#define RT5645_PRE_SCLK_SFT 0
+#define RT5645_PRE_SCLK_512 (0x0)
+#define RT5645_PRE_SCLK_1024 (0x1)
+#define RT5645_PRE_SCLK_2048 (0x2)
+
+/* ASRC Control 3 (0x85) */
+#define RT5645_I2S1_RATE_MASK (0xf << 12)
+#define RT5645_I2S1_RATE_SFT 12
+#define RT5645_I2S2_RATE_MASK (0xf << 8)
+#define RT5645_I2S2_RATE_SFT 8
+
+/* ASRC Control 4 (0x89) */
+#define RT5645_I2S1_PD_MASK (0x7 << 12)
+#define RT5645_I2S1_PD_SFT 12
+#define RT5645_I2S2_PD_MASK (0x7 << 8)
+#define RT5645_I2S2_PD_SFT 8
+
+/* HPOUT Over Current Detection (0x8b) */
+#define RT5645_HP_OVCD_MASK (0x1 << 10)
+#define RT5645_HP_OVCD_SFT 10
+#define RT5645_HP_OVCD_DIS (0x0 << 10)
+#define RT5645_HP_OVCD_EN (0x1 << 10)
+#define RT5645_HP_OC_TH_MASK (0x3 << 8)
+#define RT5645_HP_OC_TH_SFT 8
+#define RT5645_HP_OC_TH_90 (0x0 << 8)
+#define RT5645_HP_OC_TH_105 (0x1 << 8)
+#define RT5645_HP_OC_TH_120 (0x2 << 8)
+#define RT5645_HP_OC_TH_135 (0x3 << 8)
+
+/* Class D Over Current Control (0x8c) */
+#define RT5645_CLSD_OC_MASK (0x1 << 9)
+#define RT5645_CLSD_OC_SFT 9
+#define RT5645_CLSD_OC_PU (0x0 << 9)
+#define RT5645_CLSD_OC_PD (0x1 << 9)
+#define RT5645_AUTO_PD_MASK (0x1 << 8)
+#define RT5645_AUTO_PD_SFT 8
+#define RT5645_AUTO_PD_DIS (0x0 << 8)
+#define RT5645_AUTO_PD_EN (0x1 << 8)
+#define RT5645_CLSD_OC_TH_MASK (0x3f)
+#define RT5645_CLSD_OC_TH_SFT 0
+
+/* Class D Output Control (0x8d) */
+#define RT5645_CLSD_RATIO_MASK (0xf << 12)
+#define RT5645_CLSD_RATIO_SFT 12
+#define RT5645_CLSD_OM_MASK (0x1 << 11)
+#define RT5645_CLSD_OM_SFT 11
+#define RT5645_CLSD_OM_MONO (0x0 << 11)
+#define RT5645_CLSD_OM_STO (0x1 << 11)
+#define RT5645_CLSD_SCH_MASK (0x1 << 10)
+#define RT5645_CLSD_SCH_SFT 10
+#define RT5645_CLSD_SCH_L (0x0 << 10)
+#define RT5645_CLSD_SCH_S (0x1 << 10)
+
+/* Depop Mode Control 1 (0x8e) */
+#define RT5645_SMT_TRIG_MASK (0x1 << 15)
+#define RT5645_SMT_TRIG_SFT 15
+#define RT5645_SMT_TRIG_DIS (0x0 << 15)
+#define RT5645_SMT_TRIG_EN (0x1 << 15)
+#define RT5645_HP_L_SMT_MASK (0x1 << 9)
+#define RT5645_HP_L_SMT_SFT 9
+#define RT5645_HP_L_SMT_DIS (0x0 << 9)
+#define RT5645_HP_L_SMT_EN (0x1 << 9)
+#define RT5645_HP_R_SMT_MASK (0x1 << 8)
+#define RT5645_HP_R_SMT_SFT 8
+#define RT5645_HP_R_SMT_DIS (0x0 << 8)
+#define RT5645_HP_R_SMT_EN (0x1 << 8)
+#define RT5645_HP_CD_PD_MASK (0x1 << 7)
+#define RT5645_HP_CD_PD_SFT 7
+#define RT5645_HP_CD_PD_DIS (0x0 << 7)
+#define RT5645_HP_CD_PD_EN (0x1 << 7)
+#define RT5645_RSTN_MASK (0x1 << 6)
+#define RT5645_RSTN_SFT 6
+#define RT5645_RSTN_DIS (0x0 << 6)
+#define RT5645_RSTN_EN (0x1 << 6)
+#define RT5645_RSTP_MASK (0x1 << 5)
+#define RT5645_RSTP_SFT 5
+#define RT5645_RSTP_DIS (0x0 << 5)
+#define RT5645_RSTP_EN (0x1 << 5)
+#define RT5645_HP_CO_MASK (0x1 << 4)
+#define RT5645_HP_CO_SFT 4
+#define RT5645_HP_CO_DIS (0x0 << 4)
+#define RT5645_HP_CO_EN (0x1 << 4)
+#define RT5645_HP_CP_MASK (0x1 << 3)
+#define RT5645_HP_CP_SFT 3
+#define RT5645_HP_CP_PD (0x0 << 3)
+#define RT5645_HP_CP_PU (0x1 << 3)
+#define RT5645_HP_SG_MASK (0x1 << 2)
+#define RT5645_HP_SG_SFT 2
+#define RT5645_HP_SG_DIS (0x0 << 2)
+#define RT5645_HP_SG_EN (0x1 << 2)
+#define RT5645_HP_DP_MASK (0x1 << 1)
+#define RT5645_HP_DP_SFT 1
+#define RT5645_HP_DP_PD (0x0 << 1)
+#define RT5645_HP_DP_PU (0x1 << 1)
+#define RT5645_HP_CB_MASK (0x1)
+#define RT5645_HP_CB_SFT 0
+#define RT5645_HP_CB_PD (0x0)
+#define RT5645_HP_CB_PU (0x1)
+
+/* Depop Mode Control 2 (0x8f) */
+#define RT5645_DEPOP_MASK (0x1 << 13)
+#define RT5645_DEPOP_SFT 13
+#define RT5645_DEPOP_AUTO (0x0 << 13)
+#define RT5645_DEPOP_MAN (0x1 << 13)
+#define RT5645_RAMP_MASK (0x1 << 12)
+#define RT5645_RAMP_SFT 12
+#define RT5645_RAMP_DIS (0x0 << 12)
+#define RT5645_RAMP_EN (0x1 << 12)
+#define RT5645_BPS_MASK (0x1 << 11)
+#define RT5645_BPS_SFT 11
+#define RT5645_BPS_DIS (0x0 << 11)
+#define RT5645_BPS_EN (0x1 << 11)
+#define RT5645_FAST_UPDN_MASK (0x1 << 10)
+#define RT5645_FAST_UPDN_SFT 10
+#define RT5645_FAST_UPDN_DIS (0x0 << 10)
+#define RT5645_FAST_UPDN_EN (0x1 << 10)
+#define RT5645_MRES_MASK (0x3 << 8)
+#define RT5645_MRES_SFT 8
+#define RT5645_MRES_15MO (0x0 << 8)
+#define RT5645_MRES_25MO (0x1 << 8)
+#define RT5645_MRES_35MO (0x2 << 8)
+#define RT5645_MRES_45MO (0x3 << 8)
+#define RT5645_VLO_MASK (0x1 << 7)
+#define RT5645_VLO_SFT 7
+#define RT5645_VLO_3V (0x0 << 7)
+#define RT5645_VLO_32V (0x1 << 7)
+#define RT5645_DIG_DP_MASK (0x1 << 6)
+#define RT5645_DIG_DP_SFT 6
+#define RT5645_DIG_DP_DIS (0x0 << 6)
+#define RT5645_DIG_DP_EN (0x1 << 6)
+#define RT5645_DP_TH_MASK (0x3 << 4)
+#define RT5645_DP_TH_SFT 4
+
+/* Depop Mode Control 3 (0x90) */
+#define RT5645_CP_SYS_MASK (0x7 << 12)
+#define RT5645_CP_SYS_SFT 12
+#define RT5645_CP_FQ1_MASK (0x7 << 8)
+#define RT5645_CP_FQ1_SFT 8
+#define RT5645_CP_FQ2_MASK (0x7 << 4)
+#define RT5645_CP_FQ2_SFT 4
+#define RT5645_CP_FQ3_MASK (0x7)
+#define RT5645_CP_FQ3_SFT 0
+#define RT5645_CP_FQ_1_5_KHZ 0
+#define RT5645_CP_FQ_3_KHZ 1
+#define RT5645_CP_FQ_6_KHZ 2
+#define RT5645_CP_FQ_12_KHZ 3
+#define RT5645_CP_FQ_24_KHZ 4
+#define RT5645_CP_FQ_48_KHZ 5
+#define RT5645_CP_FQ_96_KHZ 6
+#define RT5645_CP_FQ_192_KHZ 7
+
+/* PV detection and SPK gain control (0x92) */
+#define RT5645_PVDD_DET_MASK (0x1 << 15)
+#define RT5645_PVDD_DET_SFT 15
+#define RT5645_PVDD_DET_DIS (0x0 << 15)
+#define RT5645_PVDD_DET_EN (0x1 << 15)
+#define RT5645_SPK_AG_MASK (0x1 << 14)
+#define RT5645_SPK_AG_SFT 14
+#define RT5645_SPK_AG_DIS (0x0 << 14)
+#define RT5645_SPK_AG_EN (0x1 << 14)
+
+/* Micbias Control (0x93) */
+#define RT5645_MIC1_BS_MASK (0x1 << 15)
+#define RT5645_MIC1_BS_SFT 15
+#define RT5645_MIC1_BS_9AV (0x0 << 15)
+#define RT5645_MIC1_BS_75AV (0x1 << 15)
+#define RT5645_MIC2_BS_MASK (0x1 << 14)
+#define RT5645_MIC2_BS_SFT 14
+#define RT5645_MIC2_BS_9AV (0x0 << 14)
+#define RT5645_MIC2_BS_75AV (0x1 << 14)
+#define RT5645_MIC1_CLK_MASK (0x1 << 13)
+#define RT5645_MIC1_CLK_SFT 13
+#define RT5645_MIC1_CLK_DIS (0x0 << 13)
+#define RT5645_MIC1_CLK_EN (0x1 << 13)
+#define RT5645_MIC2_CLK_MASK (0x1 << 12)
+#define RT5645_MIC2_CLK_SFT 12
+#define RT5645_MIC2_CLK_DIS (0x0 << 12)
+#define RT5645_MIC2_CLK_EN (0x1 << 12)
+#define RT5645_MIC1_OVCD_MASK (0x1 << 11)
+#define RT5645_MIC1_OVCD_SFT 11
+#define RT5645_MIC1_OVCD_DIS (0x0 << 11)
+#define RT5645_MIC1_OVCD_EN (0x1 << 11)
+#define RT5645_MIC1_OVTH_MASK (0x3 << 9)
+#define RT5645_MIC1_OVTH_SFT 9
+#define RT5645_MIC1_OVTH_600UA (0x0 << 9)
+#define RT5645_MIC1_OVTH_1500UA (0x1 << 9)
+#define RT5645_MIC1_OVTH_2000UA (0x2 << 9)
+#define RT5645_MIC2_OVCD_MASK (0x1 << 8)
+#define RT5645_MIC2_OVCD_SFT 8
+#define RT5645_MIC2_OVCD_DIS (0x0 << 8)
+#define RT5645_MIC2_OVCD_EN (0x1 << 8)
+#define RT5645_MIC2_OVTH_MASK (0x3 << 6)
+#define RT5645_MIC2_OVTH_SFT 6
+#define RT5645_MIC2_OVTH_600UA (0x0 << 6)
+#define RT5645_MIC2_OVTH_1500UA (0x1 << 6)
+#define RT5645_MIC2_OVTH_2000UA (0x2 << 6)
+#define RT5645_PWR_MB_MASK (0x1 << 5)
+#define RT5645_PWR_MB_SFT 5
+#define RT5645_PWR_MB_PD (0x0 << 5)
+#define RT5645_PWR_MB_PU (0x1 << 5)
+#define RT5645_PWR_CLK25M_MASK (0x1 << 4)
+#define RT5645_PWR_CLK25M_SFT 4
+#define RT5645_PWR_CLK25M_PD (0x0 << 4)
+#define RT5645_PWR_CLK25M_PU (0x1 << 4)
+
+/* VAD Control 4 (0x9d) */
+#define RT5645_VAD_SEL_MASK (0x3 << 8)
+#define RT5645_VAD_SEL_SFT 8
+
+/* EQ Control 1 (0xb0) */
+#define RT5645_EQ_SRC_MASK (0x1 << 15)
+#define RT5645_EQ_SRC_SFT 15
+#define RT5645_EQ_SRC_DAC (0x0 << 15)
+#define RT5645_EQ_SRC_ADC (0x1 << 15)
+#define RT5645_EQ_UPD (0x1 << 14)
+#define RT5645_EQ_UPD_BIT 14
+#define RT5645_EQ_CD_MASK (0x1 << 13)
+#define RT5645_EQ_CD_SFT 13
+#define RT5645_EQ_CD_DIS (0x0 << 13)
+#define RT5645_EQ_CD_EN (0x1 << 13)
+#define RT5645_EQ_DITH_MASK (0x3 << 8)
+#define RT5645_EQ_DITH_SFT 8
+#define RT5645_EQ_DITH_NOR (0x0 << 8)
+#define RT5645_EQ_DITH_LSB (0x1 << 8)
+#define RT5645_EQ_DITH_LSB_1 (0x2 << 8)
+#define RT5645_EQ_DITH_LSB_2 (0x3 << 8)
+
+/* EQ Control 2 (0xb1) */
+#define RT5645_EQ_HPF1_M_MASK (0x1 << 8)
+#define RT5645_EQ_HPF1_M_SFT 8
+#define RT5645_EQ_HPF1_M_HI (0x0 << 8)
+#define RT5645_EQ_HPF1_M_1ST (0x1 << 8)
+#define RT5645_EQ_LPF1_M_MASK (0x1 << 7)
+#define RT5645_EQ_LPF1_M_SFT 7
+#define RT5645_EQ_LPF1_M_LO (0x0 << 7)
+#define RT5645_EQ_LPF1_M_1ST (0x1 << 7)
+#define RT5645_EQ_HPF2_MASK (0x1 << 6)
+#define RT5645_EQ_HPF2_SFT 6
+#define RT5645_EQ_HPF2_DIS (0x0 << 6)
+#define RT5645_EQ_HPF2_EN (0x1 << 6)
+#define RT5645_EQ_HPF1_MASK (0x1 << 5)
+#define RT5645_EQ_HPF1_SFT 5
+#define RT5645_EQ_HPF1_DIS (0x0 << 5)
+#define RT5645_EQ_HPF1_EN (0x1 << 5)
+#define RT5645_EQ_BPF4_MASK (0x1 << 4)
+#define RT5645_EQ_BPF4_SFT 4
+#define RT5645_EQ_BPF4_DIS (0x0 << 4)
+#define RT5645_EQ_BPF4_EN (0x1 << 4)
+#define RT5645_EQ_BPF3_MASK (0x1 << 3)
+#define RT5645_EQ_BPF3_SFT 3
+#define RT5645_EQ_BPF3_DIS (0x0 << 3)
+#define RT5645_EQ_BPF3_EN (0x1 << 3)
+#define RT5645_EQ_BPF2_MASK (0x1 << 2)
+#define RT5645_EQ_BPF2_SFT 2
+#define RT5645_EQ_BPF2_DIS (0x0 << 2)
+#define RT5645_EQ_BPF2_EN (0x1 << 2)
+#define RT5645_EQ_BPF1_MASK (0x1 << 1)
+#define RT5645_EQ_BPF1_SFT 1
+#define RT5645_EQ_BPF1_DIS (0x0 << 1)
+#define RT5645_EQ_BPF1_EN (0x1 << 1)
+#define RT5645_EQ_LPF_MASK (0x1)
+#define RT5645_EQ_LPF_SFT 0
+#define RT5645_EQ_LPF_DIS (0x0)
+#define RT5645_EQ_LPF_EN (0x1)
+#define RT5645_EQ_CTRL_MASK (0x7f)
+
+/* Memory Test (0xb2) */
+#define RT5645_MT_MASK (0x1 << 15)
+#define RT5645_MT_SFT 15
+#define RT5645_MT_DIS (0x0 << 15)
+#define RT5645_MT_EN (0x1 << 15)
+
+/* DRC/AGC Control 1 (0xb4) */
+#define RT5645_DRC_AGC_P_MASK (0x1 << 15)
+#define RT5645_DRC_AGC_P_SFT 15
+#define RT5645_DRC_AGC_P_DAC (0x0 << 15)
+#define RT5645_DRC_AGC_P_ADC (0x1 << 15)
+#define RT5645_DRC_AGC_MASK (0x1 << 14)
+#define RT5645_DRC_AGC_SFT 14
+#define RT5645_DRC_AGC_DIS (0x0 << 14)
+#define RT5645_DRC_AGC_EN (0x1 << 14)
+#define RT5645_DRC_AGC_UPD (0x1 << 13)
+#define RT5645_DRC_AGC_UPD_BIT 13
+#define RT5645_DRC_AGC_AR_MASK (0x1f << 8)
+#define RT5645_DRC_AGC_AR_SFT 8
+#define RT5645_DRC_AGC_R_MASK (0x7 << 5)
+#define RT5645_DRC_AGC_R_SFT 5
+#define RT5645_DRC_AGC_R_48K (0x1 << 5)
+#define RT5645_DRC_AGC_R_96K (0x2 << 5)
+#define RT5645_DRC_AGC_R_192K (0x3 << 5)
+#define RT5645_DRC_AGC_R_441K (0x5 << 5)
+#define RT5645_DRC_AGC_R_882K (0x6 << 5)
+#define RT5645_DRC_AGC_R_1764K (0x7 << 5)
+#define RT5645_DRC_AGC_RC_MASK (0x1f)
+#define RT5645_DRC_AGC_RC_SFT 0
+
+/* DRC/AGC Control 2 (0xb5) */
+#define RT5645_DRC_AGC_POB_MASK (0x3f << 8)
+#define RT5645_DRC_AGC_POB_SFT 8
+#define RT5645_DRC_AGC_CP_MASK (0x1 << 7)
+#define RT5645_DRC_AGC_CP_SFT 7
+#define RT5645_DRC_AGC_CP_DIS (0x0 << 7)
+#define RT5645_DRC_AGC_CP_EN (0x1 << 7)
+#define RT5645_DRC_AGC_CPR_MASK (0x3 << 5)
+#define RT5645_DRC_AGC_CPR_SFT 5
+#define RT5645_DRC_AGC_CPR_1_1 (0x0 << 5)
+#define RT5645_DRC_AGC_CPR_1_2 (0x1 << 5)
+#define RT5645_DRC_AGC_CPR_1_3 (0x2 << 5)
+#define RT5645_DRC_AGC_CPR_1_4 (0x3 << 5)
+#define RT5645_DRC_AGC_PRB_MASK (0x1f)
+#define RT5645_DRC_AGC_PRB_SFT 0
+
+/* DRC/AGC Control 3 (0xb6) */
+#define RT5645_DRC_AGC_NGB_MASK (0xf << 12)
+#define RT5645_DRC_AGC_NGB_SFT 12
+#define RT5645_DRC_AGC_TAR_MASK (0x1f << 7)
+#define RT5645_DRC_AGC_TAR_SFT 7
+#define RT5645_DRC_AGC_NG_MASK (0x1 << 6)
+#define RT5645_DRC_AGC_NG_SFT 6
+#define RT5645_DRC_AGC_NG_DIS (0x0 << 6)
+#define RT5645_DRC_AGC_NG_EN (0x1 << 6)
+#define RT5645_DRC_AGC_NGH_MASK (0x1 << 5)
+#define RT5645_DRC_AGC_NGH_SFT 5
+#define RT5645_DRC_AGC_NGH_DIS (0x0 << 5)
+#define RT5645_DRC_AGC_NGH_EN (0x1 << 5)
+#define RT5645_DRC_AGC_NGT_MASK (0x1f)
+#define RT5645_DRC_AGC_NGT_SFT 0
+
+/* ANC Control 1 (0xb8) */
+#define RT5645_ANC_M_MASK (0x1 << 15)
+#define RT5645_ANC_M_SFT 15
+#define RT5645_ANC_M_NOR (0x0 << 15)
+#define RT5645_ANC_M_REV (0x1 << 15)
+#define RT5645_ANC_MASK (0x1 << 14)
+#define RT5645_ANC_SFT 14
+#define RT5645_ANC_DIS (0x0 << 14)
+#define RT5645_ANC_EN (0x1 << 14)
+#define RT5645_ANC_MD_MASK (0x3 << 12)
+#define RT5645_ANC_MD_SFT 12
+#define RT5645_ANC_MD_DIS (0x0 << 12)
+#define RT5645_ANC_MD_67MS (0x1 << 12)
+#define RT5645_ANC_MD_267MS (0x2 << 12)
+#define RT5645_ANC_MD_1067MS (0x3 << 12)
+#define RT5645_ANC_SN_MASK (0x1 << 11)
+#define RT5645_ANC_SN_SFT 11
+#define RT5645_ANC_SN_DIS (0x0 << 11)
+#define RT5645_ANC_SN_EN (0x1 << 11)
+#define RT5645_ANC_CLK_MASK (0x1 << 10)
+#define RT5645_ANC_CLK_SFT 10
+#define RT5645_ANC_CLK_ANC (0x0 << 10)
+#define RT5645_ANC_CLK_REG (0x1 << 10)
+#define RT5645_ANC_ZCD_MASK (0x3 << 8)
+#define RT5645_ANC_ZCD_SFT 8
+#define RT5645_ANC_ZCD_DIS (0x0 << 8)
+#define RT5645_ANC_ZCD_T1 (0x1 << 8)
+#define RT5645_ANC_ZCD_T2 (0x2 << 8)
+#define RT5645_ANC_ZCD_WT (0x3 << 8)
+#define RT5645_ANC_CS_MASK (0x1 << 7)
+#define RT5645_ANC_CS_SFT 7
+#define RT5645_ANC_CS_DIS (0x0 << 7)
+#define RT5645_ANC_CS_EN (0x1 << 7)
+#define RT5645_ANC_SW_MASK (0x1 << 6)
+#define RT5645_ANC_SW_SFT 6
+#define RT5645_ANC_SW_NOR (0x0 << 6)
+#define RT5645_ANC_SW_AUTO (0x1 << 6)
+#define RT5645_ANC_CO_L_MASK (0x3f)
+#define RT5645_ANC_CO_L_SFT 0
+
+/* ANC Control 2 (0xb6) */
+#define RT5645_ANC_FG_R_MASK (0xf << 12)
+#define RT5645_ANC_FG_R_SFT 12
+#define RT5645_ANC_FG_L_MASK (0xf << 8)
+#define RT5645_ANC_FG_L_SFT 8
+#define RT5645_ANC_CG_R_MASK (0xf << 4)
+#define RT5645_ANC_CG_R_SFT 4
+#define RT5645_ANC_CG_L_MASK (0xf)
+#define RT5645_ANC_CG_L_SFT 0
+
+/* ANC Control 3 (0xb6) */
+#define RT5645_ANC_CD_MASK (0x1 << 6)
+#define RT5645_ANC_CD_SFT 6
+#define RT5645_ANC_CD_BOTH (0x0 << 6)
+#define RT5645_ANC_CD_IND (0x1 << 6)
+#define RT5645_ANC_CO_R_MASK (0x3f)
+#define RT5645_ANC_CO_R_SFT 0
+
+/* Jack Detect Control (0xbb) */
+#define RT5645_JD_MASK (0x7 << 13)
+#define RT5645_JD_SFT 13
+#define RT5645_JD_DIS (0x0 << 13)
+#define RT5645_JD_GPIO1 (0x1 << 13)
+#define RT5645_JD_JD1_IN4P (0x2 << 13)
+#define RT5645_JD_JD2_IN4N (0x3 << 13)
+#define RT5645_JD_GPIO2 (0x4 << 13)
+#define RT5645_JD_GPIO3 (0x5 << 13)
+#define RT5645_JD_GPIO4 (0x6 << 13)
+#define RT5645_JD_HP_MASK (0x1 << 11)
+#define RT5645_JD_HP_SFT 11
+#define RT5645_JD_HP_DIS (0x0 << 11)
+#define RT5645_JD_HP_EN (0x1 << 11)
+#define RT5645_JD_HP_TRG_MASK (0x1 << 10)
+#define RT5645_JD_HP_TRG_SFT 10
+#define RT5645_JD_HP_TRG_LO (0x0 << 10)
+#define RT5645_JD_HP_TRG_HI (0x1 << 10)
+#define RT5645_JD_SPL_MASK (0x1 << 9)
+#define RT5645_JD_SPL_SFT 9
+#define RT5645_JD_SPL_DIS (0x0 << 9)
+#define RT5645_JD_SPL_EN (0x1 << 9)
+#define RT5645_JD_SPL_TRG_MASK (0x1 << 8)
+#define RT5645_JD_SPL_TRG_SFT 8
+#define RT5645_JD_SPL_TRG_LO (0x0 << 8)
+#define RT5645_JD_SPL_TRG_HI (0x1 << 8)
+#define RT5645_JD_SPR_MASK (0x1 << 7)
+#define RT5645_JD_SPR_SFT 7
+#define RT5645_JD_SPR_DIS (0x0 << 7)
+#define RT5645_JD_SPR_EN (0x1 << 7)
+#define RT5645_JD_SPR_TRG_MASK (0x1 << 6)
+#define RT5645_JD_SPR_TRG_SFT 6
+#define RT5645_JD_SPR_TRG_LO (0x0 << 6)
+#define RT5645_JD_SPR_TRG_HI (0x1 << 6)
+#define RT5645_JD_MO_MASK (0x1 << 5)
+#define RT5645_JD_MO_SFT 5
+#define RT5645_JD_MO_DIS (0x0 << 5)
+#define RT5645_JD_MO_EN (0x1 << 5)
+#define RT5645_JD_MO_TRG_MASK (0x1 << 4)
+#define RT5645_JD_MO_TRG_SFT 4
+#define RT5645_JD_MO_TRG_LO (0x0 << 4)
+#define RT5645_JD_MO_TRG_HI (0x1 << 4)
+#define RT5645_JD_LO_MASK (0x1 << 3)
+#define RT5645_JD_LO_SFT 3
+#define RT5645_JD_LO_DIS (0x0 << 3)
+#define RT5645_JD_LO_EN (0x1 << 3)
+#define RT5645_JD_LO_TRG_MASK (0x1 << 2)
+#define RT5645_JD_LO_TRG_SFT 2
+#define RT5645_JD_LO_TRG_LO (0x0 << 2)
+#define RT5645_JD_LO_TRG_HI (0x1 << 2)
+#define RT5645_JD1_IN4P_MASK (0x1 << 1)
+#define RT5645_JD1_IN4P_SFT 1
+#define RT5645_JD1_IN4P_DIS (0x0 << 1)
+#define RT5645_JD1_IN4P_EN (0x1 << 1)
+#define RT5645_JD2_IN4N_MASK (0x1)
+#define RT5645_JD2_IN4N_SFT 0
+#define RT5645_JD2_IN4N_DIS (0x0)
+#define RT5645_JD2_IN4N_EN (0x1)
+
+/* Jack detect for ANC (0xbc) */
+#define RT5645_ANC_DET_MASK (0x3 << 4)
+#define RT5645_ANC_DET_SFT 4
+#define RT5645_ANC_DET_DIS (0x0 << 4)
+#define RT5645_ANC_DET_MB1 (0x1 << 4)
+#define RT5645_ANC_DET_MB2 (0x2 << 4)
+#define RT5645_ANC_DET_JD (0x3 << 4)
+#define RT5645_AD_TRG_MASK (0x1 << 3)
+#define RT5645_AD_TRG_SFT 3
+#define RT5645_AD_TRG_LO (0x0 << 3)
+#define RT5645_AD_TRG_HI (0x1 << 3)
+#define RT5645_ANCM_DET_MASK (0x3 << 4)
+#define RT5645_ANCM_DET_SFT 4
+#define RT5645_ANCM_DET_DIS (0x0 << 4)
+#define RT5645_ANCM_DET_MB1 (0x1 << 4)
+#define RT5645_ANCM_DET_MB2 (0x2 << 4)
+#define RT5645_ANCM_DET_JD (0x3 << 4)
+#define RT5645_AMD_TRG_MASK (0x1 << 3)
+#define RT5645_AMD_TRG_SFT 3
+#define RT5645_AMD_TRG_LO (0x0 << 3)
+#define RT5645_AMD_TRG_HI (0x1 << 3)
+
+/* IRQ Control 1 (0xbd) */
+#define RT5645_IRQ_JD_MASK (0x1 << 15)
+#define RT5645_IRQ_JD_SFT 15
+#define RT5645_IRQ_JD_BP (0x0 << 15)
+#define RT5645_IRQ_JD_NOR (0x1 << 15)
+#define RT5645_IRQ_OT_MASK (0x1 << 14)
+#define RT5645_IRQ_OT_SFT 14
+#define RT5645_IRQ_OT_BP (0x0 << 14)
+#define RT5645_IRQ_OT_NOR (0x1 << 14)
+#define RT5645_JD_STKY_MASK (0x1 << 13)
+#define RT5645_JD_STKY_SFT 13
+#define RT5645_JD_STKY_DIS (0x0 << 13)
+#define RT5645_JD_STKY_EN (0x1 << 13)
+#define RT5645_OT_STKY_MASK (0x1 << 12)
+#define RT5645_OT_STKY_SFT 12
+#define RT5645_OT_STKY_DIS (0x0 << 12)
+#define RT5645_OT_STKY_EN (0x1 << 12)
+#define RT5645_JD_P_MASK (0x1 << 11)
+#define RT5645_JD_P_SFT 11
+#define RT5645_JD_P_NOR (0x0 << 11)
+#define RT5645_JD_P_INV (0x1 << 11)
+#define RT5645_OT_P_MASK (0x1 << 10)
+#define RT5645_OT_P_SFT 10
+#define RT5645_OT_P_NOR (0x0 << 10)
+#define RT5645_OT_P_INV (0x1 << 10)
+
+/* IRQ Control 2 (0xbe) */
+#define RT5645_IRQ_MB1_OC_MASK (0x1 << 15)
+#define RT5645_IRQ_MB1_OC_SFT 15
+#define RT5645_IRQ_MB1_OC_BP (0x0 << 15)
+#define RT5645_IRQ_MB1_OC_NOR (0x1 << 15)
+#define RT5645_IRQ_MB2_OC_MASK (0x1 << 14)
+#define RT5645_IRQ_MB2_OC_SFT 14
+#define RT5645_IRQ_MB2_OC_BP (0x0 << 14)
+#define RT5645_IRQ_MB2_OC_NOR (0x1 << 14)
+#define RT5645_MB1_OC_STKY_MASK (0x1 << 13)
+#define RT5645_MB1_OC_STKY_SFT 13
+#define RT5645_MB1_OC_STKY_DIS (0x0 << 13)
+#define RT5645_MB1_OC_STKY_EN (0x1 << 13)
+#define RT5645_MB2_OC_STKY_MASK (0x1 << 12)
+#define RT5645_MB2_OC_STKY_SFT 12
+#define RT5645_MB2_OC_STKY_DIS (0x0 << 12)
+#define RT5645_MB2_OC_STKY_EN (0x1 << 12)
+#define RT5645_MB1_OC_P_MASK (0x1 << 7)
+#define RT5645_MB1_OC_P_SFT 7
+#define RT5645_MB1_OC_P_NOR (0x0 << 7)
+#define RT5645_MB1_OC_P_INV (0x1 << 7)
+#define RT5645_MB2_OC_P_MASK (0x1 << 6)
+#define RT5645_MB2_OC_P_SFT 6
+#define RT5645_MB2_OC_P_NOR (0x0 << 6)
+#define RT5645_MB2_OC_P_INV (0x1 << 6)
+#define RT5645_MB1_OC_CLR (0x1 << 3)
+#define RT5645_MB1_OC_CLR_SFT 3
+#define RT5645_MB2_OC_CLR (0x1 << 2)
+#define RT5645_MB2_OC_CLR_SFT 2
+
+/* GPIO Control 1 (0xc0) */
+#define RT5645_GP1_PIN_MASK (0x1 << 15)
+#define RT5645_GP1_PIN_SFT 15
+#define RT5645_GP1_PIN_GPIO1 (0x0 << 15)
+#define RT5645_GP1_PIN_IRQ (0x1 << 15)
+#define RT5645_GP2_PIN_MASK (0x1 << 14)
+#define RT5645_GP2_PIN_SFT 14
+#define RT5645_GP2_PIN_GPIO2 (0x0 << 14)
+#define RT5645_GP2_PIN_DMIC1_SCL (0x1 << 14)
+#define RT5645_GP3_PIN_MASK (0x3 << 12)
+#define RT5645_GP3_PIN_SFT 12
+#define RT5645_GP3_PIN_GPIO3 (0x0 << 12)
+#define RT5645_GP3_PIN_DMIC1_SDA (0x1 << 12)
+#define RT5645_GP3_PIN_IRQ (0x2 << 12)
+#define RT5645_GP4_PIN_MASK (0x1 << 11)
+#define RT5645_GP4_PIN_SFT 11
+#define RT5645_GP4_PIN_GPIO4 (0x0 << 11)
+#define RT5645_GP4_PIN_DMIC2_SDA (0x1 << 11)
+#define RT5645_DP_SIG_MASK (0x1 << 10)
+#define RT5645_DP_SIG_SFT 10
+#define RT5645_DP_SIG_TEST (0x0 << 10)
+#define RT5645_DP_SIG_AP (0x1 << 10)
+#define RT5645_GPIO_M_MASK (0x1 << 9)
+#define RT5645_GPIO_M_SFT 9
+#define RT5645_GPIO_M_FLT (0x0 << 9)
+#define RT5645_GPIO_M_PH (0x1 << 9)
+#define RT5645_I2S2_SEL (0x1 << 8)
+#define RT5645_I2S2_SEL_SFT 8
+#define RT5645_GP5_PIN_MASK (0x1 << 7)
+#define RT5645_GP5_PIN_SFT 7
+#define RT5645_GP5_PIN_GPIO5 (0x0 << 7)
+#define RT5645_GP5_PIN_DMIC1_SDA (0x1 << 7)
+#define RT5645_GP6_PIN_MASK (0x1 << 6)
+#define RT5645_GP6_PIN_SFT 6
+#define RT5645_GP6_PIN_GPIO6 (0x0 << 6)
+#define RT5645_GP6_PIN_DMIC2_SDA (0x1 << 6)
+#define RT5645_GP8_PIN_MASK (0x1 << 3)
+#define RT5645_GP8_PIN_SFT 3
+#define RT5645_GP8_PIN_GPIO8 (0x0 << 3)
+#define RT5645_GP8_PIN_DMIC2_SDA (0x1 << 3)
+#define RT5645_GP12_PIN_MASK (0x1 << 2)
+#define RT5645_GP12_PIN_SFT 2
+#define RT5645_GP12_PIN_GPIO12 (0x0 << 2)
+#define RT5645_GP12_PIN_DMIC2_SDA (0x1 << 2)
+#define RT5645_GP11_PIN_MASK (0x1 << 1)
+#define RT5645_GP11_PIN_SFT 1
+#define RT5645_GP11_PIN_GPIO11 (0x0 << 1)
+#define RT5645_GP11_PIN_DMIC1_SDA (0x1 << 1)
+#define RT5645_GP10_PIN_MASK (0x1)
+#define RT5645_GP10_PIN_SFT 0
+#define RT5645_GP10_PIN_GPIO10 (0x0)
+#define RT5645_GP10_PIN_DMIC2_SDA (0x1)
+
+/* GPIO Control 3 (0xc2) */
+#define RT5645_GP4_PF_MASK (0x1 << 11)
+#define RT5645_GP4_PF_SFT 11
+#define RT5645_GP4_PF_IN (0x0 << 11)
+#define RT5645_GP4_PF_OUT (0x1 << 11)
+#define RT5645_GP4_OUT_MASK (0x1 << 10)
+#define RT5645_GP4_OUT_SFT 10
+#define RT5645_GP4_OUT_LO (0x0 << 10)
+#define RT5645_GP4_OUT_HI (0x1 << 10)
+#define RT5645_GP4_P_MASK (0x1 << 9)
+#define RT5645_GP4_P_SFT 9
+#define RT5645_GP4_P_NOR (0x0 << 9)
+#define RT5645_GP4_P_INV (0x1 << 9)
+#define RT5645_GP3_PF_MASK (0x1 << 8)
+#define RT5645_GP3_PF_SFT 8
+#define RT5645_GP3_PF_IN (0x0 << 8)
+#define RT5645_GP3_PF_OUT (0x1 << 8)
+#define RT5645_GP3_OUT_MASK (0x1 << 7)
+#define RT5645_GP3_OUT_SFT 7
+#define RT5645_GP3_OUT_LO (0x0 << 7)
+#define RT5645_GP3_OUT_HI (0x1 << 7)
+#define RT5645_GP3_P_MASK (0x1 << 6)
+#define RT5645_GP3_P_SFT 6
+#define RT5645_GP3_P_NOR (0x0 << 6)
+#define RT5645_GP3_P_INV (0x1 << 6)
+#define RT5645_GP2_PF_MASK (0x1 << 5)
+#define RT5645_GP2_PF_SFT 5
+#define RT5645_GP2_PF_IN (0x0 << 5)
+#define RT5645_GP2_PF_OUT (0x1 << 5)
+#define RT5645_GP2_OUT_MASK (0x1 << 4)
+#define RT5645_GP2_OUT_SFT 4
+#define RT5645_GP2_OUT_LO (0x0 << 4)
+#define RT5645_GP2_OUT_HI (0x1 << 4)
+#define RT5645_GP2_P_MASK (0x1 << 3)
+#define RT5645_GP2_P_SFT 3
+#define RT5645_GP2_P_NOR (0x0 << 3)
+#define RT5645_GP2_P_INV (0x1 << 3)
+#define RT5645_GP1_PF_MASK (0x1 << 2)
+#define RT5645_GP1_PF_SFT 2
+#define RT5645_GP1_PF_IN (0x0 << 2)
+#define RT5645_GP1_PF_OUT (0x1 << 2)
+#define RT5645_GP1_OUT_MASK (0x1 << 1)
+#define RT5645_GP1_OUT_SFT 1
+#define RT5645_GP1_OUT_LO (0x0 << 1)
+#define RT5645_GP1_OUT_HI (0x1 << 1)
+#define RT5645_GP1_P_MASK (0x1)
+#define RT5645_GP1_P_SFT 0
+#define RT5645_GP1_P_NOR (0x0)
+#define RT5645_GP1_P_INV (0x1)
+
+/* Programmable Register Array Control 1 (0xc8) */
+#define RT5645_REG_SEQ_MASK (0xf << 12)
+#define RT5645_REG_SEQ_SFT 12
+#define RT5645_SEQ1_ST_MASK (0x1 << 11) /*RO*/
+#define RT5645_SEQ1_ST_SFT 11
+#define RT5645_SEQ1_ST_RUN (0x0 << 11)
+#define RT5645_SEQ1_ST_FIN (0x1 << 11)
+#define RT5645_SEQ2_ST_MASK (0x1 << 10) /*RO*/
+#define RT5645_SEQ2_ST_SFT 10
+#define RT5645_SEQ2_ST_RUN (0x0 << 10)
+#define RT5645_SEQ2_ST_FIN (0x1 << 10)
+#define RT5645_REG_LV_MASK (0x1 << 9)
+#define RT5645_REG_LV_SFT 9
+#define RT5645_REG_LV_MX (0x0 << 9)
+#define RT5645_REG_LV_PR (0x1 << 9)
+#define RT5645_SEQ_2_PT_MASK (0x1 << 8)
+#define RT5645_SEQ_2_PT_BIT 8
+#define RT5645_REG_IDX_MASK (0xff)
+#define RT5645_REG_IDX_SFT 0
+
+/* Programmable Register Array Control 2 (0xc9) */
+#define RT5645_REG_DAT_MASK (0xffff)
+#define RT5645_REG_DAT_SFT 0
+
+/* Programmable Register Array Control 3 (0xca) */
+#define RT5645_SEQ_DLY_MASK (0xff << 8)
+#define RT5645_SEQ_DLY_SFT 8
+#define RT5645_PROG_MASK (0x1 << 7)
+#define RT5645_PROG_SFT 7
+#define RT5645_PROG_DIS (0x0 << 7)
+#define RT5645_PROG_EN (0x1 << 7)
+#define RT5645_SEQ1_PT_RUN (0x1 << 6)
+#define RT5645_SEQ1_PT_RUN_BIT 6
+#define RT5645_SEQ2_PT_RUN (0x1 << 5)
+#define RT5645_SEQ2_PT_RUN_BIT 5
+
+/* Programmable Register Array Control 4 (0xcb) */
+#define RT5645_SEQ1_START_MASK (0xf << 8)
+#define RT5645_SEQ1_START_SFT 8
+#define RT5645_SEQ1_END_MASK (0xf)
+#define RT5645_SEQ1_END_SFT 0
+
+/* Programmable Register Array Control 5 (0xcc) */
+#define RT5645_SEQ2_START_MASK (0xf << 8)
+#define RT5645_SEQ2_START_SFT 8
+#define RT5645_SEQ2_END_MASK (0xf)
+#define RT5645_SEQ2_END_SFT 0
+
+/* Scramble Function (0xcd) */
+#define RT5645_SCB_KEY_MASK (0xff)
+#define RT5645_SCB_KEY_SFT 0
+
+/* Scramble Control (0xce) */
+#define RT5645_SCB_SWAP_MASK (0x1 << 15)
+#define RT5645_SCB_SWAP_SFT 15
+#define RT5645_SCB_SWAP_DIS (0x0 << 15)
+#define RT5645_SCB_SWAP_EN (0x1 << 15)
+#define RT5645_SCB_MASK (0x1 << 14)
+#define RT5645_SCB_SFT 14
+#define RT5645_SCB_DIS (0x0 << 14)
+#define RT5645_SCB_EN (0x1 << 14)
+
+/* Baseback Control (0xcf) */
+#define RT5645_BB_MASK (0x1 << 15)
+#define RT5645_BB_SFT 15
+#define RT5645_BB_DIS (0x0 << 15)
+#define RT5645_BB_EN (0x1 << 15)
+#define RT5645_BB_CT_MASK (0x7 << 12)
+#define RT5645_BB_CT_SFT 12
+#define RT5645_BB_CT_A (0x0 << 12)
+#define RT5645_BB_CT_B (0x1 << 12)
+#define RT5645_BB_CT_C (0x2 << 12)
+#define RT5645_BB_CT_D (0x3 << 12)
+#define RT5645_M_BB_L_MASK (0x1 << 9)
+#define RT5645_M_BB_L_SFT 9
+#define RT5645_M_BB_R_MASK (0x1 << 8)
+#define RT5645_M_BB_R_SFT 8
+#define RT5645_M_BB_HPF_L_MASK (0x1 << 7)
+#define RT5645_M_BB_HPF_L_SFT 7
+#define RT5645_M_BB_HPF_R_MASK (0x1 << 6)
+#define RT5645_M_BB_HPF_R_SFT 6
+#define RT5645_G_BB_BST_MASK (0x3f)
+#define RT5645_G_BB_BST_SFT 0
+
+/* MP3 Plus Control 1 (0xd0) */
+#define RT5645_M_MP3_L_MASK (0x1 << 15)
+#define RT5645_M_MP3_L_SFT 15
+#define RT5645_M_MP3_R_MASK (0x1 << 14)
+#define RT5645_M_MP3_R_SFT 14
+#define RT5645_M_MP3_MASK (0x1 << 13)
+#define RT5645_M_MP3_SFT 13
+#define RT5645_M_MP3_DIS (0x0 << 13)
+#define RT5645_M_MP3_EN (0x1 << 13)
+#define RT5645_EG_MP3_MASK (0x1f << 8)
+#define RT5645_EG_MP3_SFT 8
+#define RT5645_MP3_HLP_MASK (0x1 << 7)
+#define RT5645_MP3_HLP_SFT 7
+#define RT5645_MP3_HLP_DIS (0x0 << 7)
+#define RT5645_MP3_HLP_EN (0x1 << 7)
+#define RT5645_M_MP3_ORG_L_MASK (0x1 << 6)
+#define RT5645_M_MP3_ORG_L_SFT 6
+#define RT5645_M_MP3_ORG_R_MASK (0x1 << 5)
+#define RT5645_M_MP3_ORG_R_SFT 5
+
+/* MP3 Plus Control 2 (0xd1) */
+#define RT5645_MP3_WT_MASK (0x1 << 13)
+#define RT5645_MP3_WT_SFT 13
+#define RT5645_MP3_WT_1_4 (0x0 << 13)
+#define RT5645_MP3_WT_1_2 (0x1 << 13)
+#define RT5645_OG_MP3_MASK (0x1f << 8)
+#define RT5645_OG_MP3_SFT 8
+#define RT5645_HG_MP3_MASK (0x3f)
+#define RT5645_HG_MP3_SFT 0
+
+/* 3D HP Control 1 (0xd2) */
+#define RT5645_3D_CF_MASK (0x1 << 15)
+#define RT5645_3D_CF_SFT 15
+#define RT5645_3D_CF_DIS (0x0 << 15)
+#define RT5645_3D_CF_EN (0x1 << 15)
+#define RT5645_3D_HP_MASK (0x1 << 14)
+#define RT5645_3D_HP_SFT 14
+#define RT5645_3D_HP_DIS (0x0 << 14)
+#define RT5645_3D_HP_EN (0x1 << 14)
+#define RT5645_3D_BT_MASK (0x1 << 13)
+#define RT5645_3D_BT_SFT 13
+#define RT5645_3D_BT_DIS (0x0 << 13)
+#define RT5645_3D_BT_EN (0x1 << 13)
+#define RT5645_3D_1F_MIX_MASK (0x3 << 11)
+#define RT5645_3D_1F_MIX_SFT 11
+#define RT5645_3D_HP_M_MASK (0x1 << 10)
+#define RT5645_3D_HP_M_SFT 10
+#define RT5645_3D_HP_M_SUR (0x0 << 10)
+#define RT5645_3D_HP_M_FRO (0x1 << 10)
+#define RT5645_M_3D_HRTF_MASK (0x1 << 9)
+#define RT5645_M_3D_HRTF_SFT 9
+#define RT5645_M_3D_D2H_MASK (0x1 << 8)
+#define RT5645_M_3D_D2H_SFT 8
+#define RT5645_M_3D_D2R_MASK (0x1 << 7)
+#define RT5645_M_3D_D2R_SFT 7
+#define RT5645_M_3D_REVB_MASK (0x1 << 6)
+#define RT5645_M_3D_REVB_SFT 6
+
+/* Adjustable high pass filter control 1 (0xd3) */
+#define RT5645_2ND_HPF_MASK (0x1 << 15)
+#define RT5645_2ND_HPF_SFT 15
+#define RT5645_2ND_HPF_DIS (0x0 << 15)
+#define RT5645_2ND_HPF_EN (0x1 << 15)
+#define RT5645_HPF_CF_L_MASK (0x7 << 12)
+#define RT5645_HPF_CF_L_SFT 12
+#define RT5645_1ST_HPF_MASK (0x1 << 11)
+#define RT5645_1ST_HPF_SFT 11
+#define RT5645_1ST_HPF_DIS (0x0 << 11)
+#define RT5645_1ST_HPF_EN (0x1 << 11)
+#define RT5645_HPF_CF_R_MASK (0x7 << 8)
+#define RT5645_HPF_CF_R_SFT 8
+#define RT5645_ZD_T_MASK (0x3 << 6)
+#define RT5645_ZD_T_SFT 6
+#define RT5645_ZD_F_MASK (0x3 << 4)
+#define RT5645_ZD_F_SFT 4
+#define RT5645_ZD_F_IM (0x0 << 4)
+#define RT5645_ZD_F_ZC_IM (0x1 << 4)
+#define RT5645_ZD_F_ZC_IOD (0x2 << 4)
+#define RT5645_ZD_F_UN (0x3 << 4)
+
+/* HP calibration control and Amp detection (0xd6) */
+#define RT5645_SI_DAC_MASK (0x1 << 11)
+#define RT5645_SI_DAC_SFT 11
+#define RT5645_SI_DAC_AUTO (0x0 << 11)
+#define RT5645_SI_DAC_TEST (0x1 << 11)
+#define RT5645_DC_CAL_M_MASK (0x1 << 10)
+#define RT5645_DC_CAL_M_SFT 10
+#define RT5645_DC_CAL_M_CAL (0x0 << 10)
+#define RT5645_DC_CAL_M_NOR (0x1 << 10)
+#define RT5645_DC_CAL_MASK (0x1 << 9)
+#define RT5645_DC_CAL_SFT 9
+#define RT5645_DC_CAL_DIS (0x0 << 9)
+#define RT5645_DC_CAL_EN (0x1 << 9)
+#define RT5645_HPD_RCV_MASK (0x7 << 6)
+#define RT5645_HPD_RCV_SFT 6
+#define RT5645_HPD_PS_MASK (0x1 << 5)
+#define RT5645_HPD_PS_SFT 5
+#define RT5645_HPD_PS_DIS (0x0 << 5)
+#define RT5645_HPD_PS_EN (0x1 << 5)
+#define RT5645_CAL_M_MASK (0x1 << 4)
+#define RT5645_CAL_M_SFT 4
+#define RT5645_CAL_M_DEP (0x0 << 4)
+#define RT5645_CAL_M_CAL (0x1 << 4)
+#define RT5645_CAL_MASK (0x1 << 3)
+#define RT5645_CAL_SFT 3
+#define RT5645_CAL_DIS (0x0 << 3)
+#define RT5645_CAL_EN (0x1 << 3)
+#define RT5645_CAL_TEST_MASK (0x1 << 2)
+#define RT5645_CAL_TEST_SFT 2
+#define RT5645_CAL_TEST_DIS (0x0 << 2)
+#define RT5645_CAL_TEST_EN (0x1 << 2)
+#define RT5645_CAL_P_MASK (0x3)
+#define RT5645_CAL_P_SFT 0
+#define RT5645_CAL_P_NONE (0x0)
+#define RT5645_CAL_P_CAL (0x1)
+#define RT5645_CAL_P_DAC_CAL (0x2)
+
+/* Soft volume and zero cross control 1 (0xd9) */
+#define RT5645_SV_MASK (0x1 << 15)
+#define RT5645_SV_SFT 15
+#define RT5645_SV_DIS (0x0 << 15)
+#define RT5645_SV_EN (0x1 << 15)
+#define RT5645_SPO_SV_MASK (0x1 << 14)
+#define RT5645_SPO_SV_SFT 14
+#define RT5645_SPO_SV_DIS (0x0 << 14)
+#define RT5645_SPO_SV_EN (0x1 << 14)
+#define RT5645_OUT_SV_MASK (0x1 << 13)
+#define RT5645_OUT_SV_SFT 13
+#define RT5645_OUT_SV_DIS (0x0 << 13)
+#define RT5645_OUT_SV_EN (0x1 << 13)
+#define RT5645_HP_SV_MASK (0x1 << 12)
+#define RT5645_HP_SV_SFT 12
+#define RT5645_HP_SV_DIS (0x0 << 12)
+#define RT5645_HP_SV_EN (0x1 << 12)
+#define RT5645_ZCD_DIG_MASK (0x1 << 11)
+#define RT5645_ZCD_DIG_SFT 11
+#define RT5645_ZCD_DIG_DIS (0x0 << 11)
+#define RT5645_ZCD_DIG_EN (0x1 << 11)
+#define RT5645_ZCD_MASK (0x1 << 10)
+#define RT5645_ZCD_SFT 10
+#define RT5645_ZCD_PD (0x0 << 10)
+#define RT5645_ZCD_PU (0x1 << 10)
+#define RT5645_M_ZCD_MASK (0x3f << 4)
+#define RT5645_M_ZCD_SFT 4
+#define RT5645_M_ZCD_RM_L (0x1 << 9)
+#define RT5645_M_ZCD_RM_R (0x1 << 8)
+#define RT5645_M_ZCD_SM_L (0x1 << 7)
+#define RT5645_M_ZCD_SM_R (0x1 << 6)
+#define RT5645_M_ZCD_OM_L (0x1 << 5)
+#define RT5645_M_ZCD_OM_R (0x1 << 4)
+#define RT5645_SV_DLY_MASK (0xf)
+#define RT5645_SV_DLY_SFT 0
+
+/* Soft volume and zero cross control 2 (0xda) */
+#define RT5645_ZCD_HP_MASK (0x1 << 15)
+#define RT5645_ZCD_HP_SFT 15
+#define RT5645_ZCD_HP_DIS (0x0 << 15)
+#define RT5645_ZCD_HP_EN (0x1 << 15)
+
+
+/* Codec Private Register definition */
+/* 3D Speaker Control (0x63) */
+#define RT5645_3D_SPK_MASK (0x1 << 15)
+#define RT5645_3D_SPK_SFT 15
+#define RT5645_3D_SPK_DIS (0x0 << 15)
+#define RT5645_3D_SPK_EN (0x1 << 15)
+#define RT5645_3D_SPK_M_MASK (0x3 << 13)
+#define RT5645_3D_SPK_M_SFT 13
+#define RT5645_3D_SPK_CG_MASK (0x1f << 8)
+#define RT5645_3D_SPK_CG_SFT 8
+#define RT5645_3D_SPK_SG_MASK (0x1f)
+#define RT5645_3D_SPK_SG_SFT 0
+
+/* Wind Noise Detection Control 1 (0x6c) */
+#define RT5645_WND_MASK (0x1 << 15)
+#define RT5645_WND_SFT 15
+#define RT5645_WND_DIS (0x0 << 15)
+#define RT5645_WND_EN (0x1 << 15)
+
+/* Wind Noise Detection Control 2 (0x6d) */
+#define RT5645_WND_FC_NW_MASK (0x3f << 10)
+#define RT5645_WND_FC_NW_SFT 10
+#define RT5645_WND_FC_WK_MASK (0x3f << 4)
+#define RT5645_WND_FC_WK_SFT 4
+
+/* Wind Noise Detection Control 3 (0x6e) */
+#define RT5645_HPF_FC_MASK (0x3f << 6)
+#define RT5645_HPF_FC_SFT 6
+#define RT5645_WND_FC_ST_MASK (0x3f)
+#define RT5645_WND_FC_ST_SFT 0
+
+/* Wind Noise Detection Control 4 (0x6f) */
+#define RT5645_WND_TH_LO_MASK (0x3ff)
+#define RT5645_WND_TH_LO_SFT 0
+
+/* Wind Noise Detection Control 5 (0x70) */
+#define RT5645_WND_TH_HI_MASK (0x3ff)
+#define RT5645_WND_TH_HI_SFT 0
+
+/* Wind Noise Detection Control 8 (0x73) */
+#define RT5645_WND_WIND_MASK (0x1 << 13) /* Read-Only */
+#define RT5645_WND_WIND_SFT 13
+#define RT5645_WND_STRONG_MASK (0x1 << 12) /* Read-Only */
+#define RT5645_WND_STRONG_SFT 12
+enum {
+ RT5645_NO_WIND,
+ RT5645_BREEZE,
+ RT5645_STORM,
+};
+
+/* Dipole Speaker Interface (0x75) */
+#define RT5645_DP_ATT_MASK (0x3 << 14)
+#define RT5645_DP_ATT_SFT 14
+#define RT5645_DP_SPK_MASK (0x1 << 10)
+#define RT5645_DP_SPK_SFT 10
+#define RT5645_DP_SPK_DIS (0x0 << 10)
+#define RT5645_DP_SPK_EN (0x1 << 10)
+
+/* EQ Pre Volume Control (0xb3) */
+#define RT5645_EQ_PRE_VOL_MASK (0xffff)
+#define RT5645_EQ_PRE_VOL_SFT 0
+
+/* EQ Post Volume Control (0xb4) */
+#define RT5645_EQ_PST_VOL_MASK (0xffff)
+#define RT5645_EQ_PST_VOL_SFT 0
+
+/* Jack Detect Control 3 (0xf8) */
+#define RT5645_CMP_MIC_IN_DET_MASK (0x7 << 12)
+#define RT5645_JD_CBJ_EN (0x1 << 7)
+#define RT5645_JD_CBJ_POL (0x1 << 6)
+#define RT5645_JD_TRI_CBJ_SEL_MASK (0x7 << 3)
+#define RT5645_JD_TRI_CBJ_SEL_SFT (3)
+#define RT5645_JD_TRI_HPO_SEL_MASK (0x7)
+#define RT5645_JD_TRI_HPO_SEL_SFT (0)
+#define RT5645_JD_F_GPIO_JD1 (0x0)
+#define RT5645_JD_F_JD1_1 (0x1)
+#define RT5645_JD_F_JD1_2 (0x2)
+#define RT5645_JD_F_JD2 (0x3)
+#define RT5645_JD_F_JD3 (0x4)
+#define RT5645_JD_F_GPIO_JD2 (0x5)
+#define RT5645_JD_F_MX0B_12 (0x6)
+
+/* Digital Misc Control (0xfa) */
+#define RT5645_RST_DSP (0x1 << 13)
+#define RT5645_IF1_ADC1_IN1_SEL (0x1 << 12)
+#define RT5645_IF1_ADC1_IN1_SFT 12
+#define RT5645_IF1_ADC1_IN2_SEL (0x1 << 11)
+#define RT5645_IF1_ADC1_IN2_SFT 11
+#define RT5645_IF1_ADC2_IN1_SEL (0x1 << 10)
+#define RT5645_IF1_ADC2_IN1_SFT 10
+#define RT5645_DIG_GATE_CTRL 0x1
+
+/* General Control2 (0xfb) */
+#define RT5645_RXDC_SRC_MASK (0x1 << 7)
+#define RT5645_RXDC_SRC_STO (0x0 << 7)
+#define RT5645_RXDC_SRC_MONO (0x1 << 7)
+#define RT5645_RXDC_SRC_SFT (7)
+#define RT5645_RXDP2_SEL_MASK (0x1 << 3)
+#define RT5645_RXDP2_SEL_IF2 (0x0 << 3)
+#define RT5645_RXDP2_SEL_ADC (0x1 << 3)
+#define RT5645_RXDP2_SEL_SFT (3)
+
+
+/* Vendor ID (0xfd) */
+#define RT5645_VER_C 0x2
+#define RT5645_VER_D 0x3
+
+
+/* Volume Rescale */
+#define RT5645_VOL_RSCL_MAX 0x27
+#define RT5645_VOL_RSCL_RANGE 0x1F
+/* Debug String Length */
+#define RT5645_REG_DISP_LEN 23
+
+
+/* System Clock Source */
+enum {
+ RT5645_SCLK_S_MCLK,
+ RT5645_SCLK_S_PLL1,
+ RT5645_SCLK_S_RCCLK,
+};
+
+/* PLL1 Source */
+enum {
+ RT5645_PLL1_S_MCLK,
+ RT5645_PLL1_S_BCLK1,
+ RT5645_PLL1_S_BCLK2,
+};
+
+enum {
+ RT5645_AIF1,
+ RT5645_AIF2,
+ RT5645_AIFS,
+};
+
+enum {
+ RT5645_DMIC_DATA_IN2P,
+ RT5645_DMIC_DATA_GPIO6,
+ RT5645_DMIC_DATA_GPIO10,
+ RT5645_DMIC_DATA_GPIO12,
+};
+
+enum {
+ RT5645_DMIC_DATA_IN2N,
+ RT5645_DMIC_DATA_GPIO5,
+ RT5645_DMIC_DATA_GPIO11,
+};
+
+struct rt5645_priv {
+ struct snd_soc_codec *codec;
+ struct rt5645_platform_data pdata;
+ struct regmap *regmap;
+
+ int sysclk;
+ int sysclk_src;
+ int lrck[RT5645_AIFS];
+ int bclk[RT5645_AIFS];
+ int master[RT5645_AIFS];
+
+ int pll_src;
+ int pll_in;
+ int pll_out;
+};
+
+#endif /* __RT5645_H__ */
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
new file mode 100644
index 00000000000..ea4b1c652a2
--- /dev/null
+++ b/sound/soc/codecs/rt5651.c
@@ -0,0 +1,1818 @@
+/*
+ * rt5651.c -- RT5651 ALSA SoC audio codec driver
+ *
+ * Copyright 2014 Realtek Semiconductor Corp.
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * 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 <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <sound/core.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 "rl6231.h"
+#include "rt5651.h"
+
+#define RT5651_DEVICE_ID_VALUE 0x6281
+
+#define RT5651_PR_RANGE_BASE (0xff + 1)
+#define RT5651_PR_SPACING 0x100
+
+#define RT5651_PR_BASE (RT5651_PR_RANGE_BASE + (0 * RT5651_PR_SPACING))
+
+static const struct regmap_range_cfg rt5651_ranges[] = {
+ { .name = "PR", .range_min = RT5651_PR_BASE,
+ .range_max = RT5651_PR_BASE + 0xb4,
+ .selector_reg = RT5651_PRIV_INDEX,
+ .selector_mask = 0xff,
+ .selector_shift = 0x0,
+ .window_start = RT5651_PRIV_DATA,
+ .window_len = 0x1, },
+};
+
+static struct reg_default init_list[] = {
+ {RT5651_PR_BASE + 0x3d, 0x3e00},
+};
+
+static const struct reg_default rt5651_reg[] = {
+ { 0x00, 0x0000 },
+ { 0x02, 0xc8c8 },
+ { 0x03, 0xc8c8 },
+ { 0x05, 0x0000 },
+ { 0x0d, 0x0000 },
+ { 0x0e, 0x0000 },
+ { 0x0f, 0x0808 },
+ { 0x10, 0x0808 },
+ { 0x19, 0xafaf },
+ { 0x1a, 0xafaf },
+ { 0x1b, 0x0c00 },
+ { 0x1c, 0x2f2f },
+ { 0x1d, 0x2f2f },
+ { 0x1e, 0x0000 },
+ { 0x27, 0x7860 },
+ { 0x28, 0x7070 },
+ { 0x29, 0x8080 },
+ { 0x2a, 0x5252 },
+ { 0x2b, 0x5454 },
+ { 0x2f, 0x0000 },
+ { 0x30, 0x5000 },
+ { 0x3b, 0x0000 },
+ { 0x3c, 0x006f },
+ { 0x3d, 0x0000 },
+ { 0x3e, 0x006f },
+ { 0x45, 0x6000 },
+ { 0x4d, 0x0000 },
+ { 0x4e, 0x0000 },
+ { 0x4f, 0x0279 },
+ { 0x50, 0x0000 },
+ { 0x51, 0x0000 },
+ { 0x52, 0x0279 },
+ { 0x53, 0xf000 },
+ { 0x61, 0x0000 },
+ { 0x62, 0x0000 },
+ { 0x63, 0x00c0 },
+ { 0x64, 0x0000 },
+ { 0x65, 0x0000 },
+ { 0x66, 0x0000 },
+ { 0x70, 0x8000 },
+ { 0x71, 0x8000 },
+ { 0x73, 0x1104 },
+ { 0x74, 0x0c00 },
+ { 0x75, 0x1400 },
+ { 0x77, 0x0c00 },
+ { 0x78, 0x4000 },
+ { 0x79, 0x0123 },
+ { 0x80, 0x0000 },
+ { 0x81, 0x0000 },
+ { 0x82, 0x0000 },
+ { 0x83, 0x0800 },
+ { 0x84, 0x0000 },
+ { 0x85, 0x0008 },
+ { 0x89, 0x0000 },
+ { 0x8e, 0x0004 },
+ { 0x8f, 0x1100 },
+ { 0x90, 0x0000 },
+ { 0x93, 0x2000 },
+ { 0x94, 0x0200 },
+ { 0xb0, 0x2080 },
+ { 0xb1, 0x0000 },
+ { 0xb4, 0x2206 },
+ { 0xb5, 0x1f00 },
+ { 0xb6, 0x0000 },
+ { 0xbb, 0x0000 },
+ { 0xbc, 0x0000 },
+ { 0xbd, 0x0000 },
+ { 0xbe, 0x0000 },
+ { 0xbf, 0x0000 },
+ { 0xc0, 0x0400 },
+ { 0xc1, 0x0000 },
+ { 0xc2, 0x0000 },
+ { 0xcf, 0x0013 },
+ { 0xd0, 0x0680 },
+ { 0xd1, 0x1c17 },
+ { 0xd3, 0xb320 },
+ { 0xd9, 0x0809 },
+ { 0xfa, 0x0010 },
+ { 0xfe, 0x10ec },
+ { 0xff, 0x6281 },
+};
+
+static bool rt5651_volatile_register(struct device *dev, unsigned int reg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rt5651_ranges); i++) {
+ if ((reg >= rt5651_ranges[i].window_start &&
+ reg <= rt5651_ranges[i].window_start +
+ rt5651_ranges[i].window_len) ||
+ (reg >= rt5651_ranges[i].range_min &&
+ reg <= rt5651_ranges[i].range_max)) {
+ return true;
+ }
+ }
+
+ switch (reg) {
+ case RT5651_RESET:
+ case RT5651_PRIV_DATA:
+ case RT5651_EQ_CTRL1:
+ case RT5651_ALC_1:
+ case RT5651_IRQ_CTRL2:
+ case RT5651_INT_IRQ_ST:
+ case RT5651_PGM_REG_ARR1:
+ case RT5651_PGM_REG_ARR3:
+ case RT5651_VENDOR_ID:
+ case RT5651_DEVICE_ID:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool rt5651_readable_register(struct device *dev, unsigned int reg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rt5651_ranges); i++) {
+ if ((reg >= rt5651_ranges[i].window_start &&
+ reg <= rt5651_ranges[i].window_start +
+ rt5651_ranges[i].window_len) ||
+ (reg >= rt5651_ranges[i].range_min &&
+ reg <= rt5651_ranges[i].range_max)) {
+ return true;
+ }
+ }
+
+ switch (reg) {
+ case RT5651_RESET:
+ case RT5651_VERSION_ID:
+ case RT5651_VENDOR_ID:
+ case RT5651_DEVICE_ID:
+ case RT5651_HP_VOL:
+ case RT5651_LOUT_CTRL1:
+ case RT5651_LOUT_CTRL2:
+ case RT5651_IN1_IN2:
+ case RT5651_IN3:
+ case RT5651_INL1_INR1_VOL:
+ case RT5651_INL2_INR2_VOL:
+ case RT5651_DAC1_DIG_VOL:
+ case RT5651_DAC2_DIG_VOL:
+ case RT5651_DAC2_CTRL:
+ case RT5651_ADC_DIG_VOL:
+ case RT5651_ADC_DATA:
+ case RT5651_ADC_BST_VOL:
+ case RT5651_STO1_ADC_MIXER:
+ case RT5651_STO2_ADC_MIXER:
+ case RT5651_AD_DA_MIXER:
+ case RT5651_STO_DAC_MIXER:
+ case RT5651_DD_MIXER:
+ case RT5651_DIG_INF_DATA:
+ case RT5651_PDM_CTL:
+ case RT5651_REC_L1_MIXER:
+ case RT5651_REC_L2_MIXER:
+ case RT5651_REC_R1_MIXER:
+ case RT5651_REC_R2_MIXER:
+ case RT5651_HPO_MIXER:
+ case RT5651_OUT_L1_MIXER:
+ case RT5651_OUT_L2_MIXER:
+ case RT5651_OUT_L3_MIXER:
+ case RT5651_OUT_R1_MIXER:
+ case RT5651_OUT_R2_MIXER:
+ case RT5651_OUT_R3_MIXER:
+ case RT5651_LOUT_MIXER:
+ case RT5651_PWR_DIG1:
+ case RT5651_PWR_DIG2:
+ case RT5651_PWR_ANLG1:
+ case RT5651_PWR_ANLG2:
+ case RT5651_PWR_MIXER:
+ case RT5651_PWR_VOL:
+ case RT5651_PRIV_INDEX:
+ case RT5651_PRIV_DATA:
+ case RT5651_I2S1_SDP:
+ case RT5651_I2S2_SDP:
+ case RT5651_ADDA_CLK1:
+ case RT5651_ADDA_CLK2:
+ case RT5651_DMIC:
+ case RT5651_TDM_CTL_1:
+ case RT5651_TDM_CTL_2:
+ case RT5651_TDM_CTL_3:
+ case RT5651_GLB_CLK:
+ case RT5651_PLL_CTRL1:
+ case RT5651_PLL_CTRL2:
+ case RT5651_PLL_MODE_1:
+ case RT5651_PLL_MODE_2:
+ case RT5651_PLL_MODE_3:
+ case RT5651_PLL_MODE_4:
+ case RT5651_PLL_MODE_5:
+ case RT5651_PLL_MODE_6:
+ case RT5651_PLL_MODE_7:
+ case RT5651_DEPOP_M1:
+ case RT5651_DEPOP_M2:
+ case RT5651_DEPOP_M3:
+ case RT5651_CHARGE_PUMP:
+ case RT5651_MICBIAS:
+ case RT5651_A_JD_CTL1:
+ case RT5651_EQ_CTRL1:
+ case RT5651_EQ_CTRL2:
+ case RT5651_ALC_1:
+ case RT5651_ALC_2:
+ case RT5651_ALC_3:
+ case RT5651_JD_CTRL1:
+ case RT5651_JD_CTRL2:
+ case RT5651_IRQ_CTRL1:
+ case RT5651_IRQ_CTRL2:
+ case RT5651_INT_IRQ_ST:
+ case RT5651_GPIO_CTRL1:
+ case RT5651_GPIO_CTRL2:
+ case RT5651_GPIO_CTRL3:
+ case RT5651_PGM_REG_ARR1:
+ case RT5651_PGM_REG_ARR2:
+ case RT5651_PGM_REG_ARR3:
+ case RT5651_PGM_REG_ARR4:
+ case RT5651_PGM_REG_ARR5:
+ case RT5651_SCB_FUNC:
+ case RT5651_SCB_CTRL:
+ case RT5651_BASE_BACK:
+ case RT5651_MP3_PLUS1:
+ case RT5651_MP3_PLUS2:
+ case RT5651_ADJ_HPF_CTRL1:
+ case RT5651_ADJ_HPF_CTRL2:
+ case RT5651_HP_CALIB_AMP_DET:
+ case RT5651_HP_CALIB2:
+ case RT5651_SV_ZCD1:
+ case RT5651_SV_ZCD2:
+ case RT5651_D_MISC:
+ case RT5651_DUMMY2:
+ case RT5651_DUMMY3:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
+
+/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
+static unsigned int bst_tlv[] = {
+ TLV_DB_RANGE_HEAD(7),
+ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+ 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
+ 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
+ 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
+ 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
+ 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
+};
+
+/* Interface data select */
+static const char * const rt5651_data_select[] = {
+ "Normal", "Swap", "left copy to right", "right copy to left"};
+
+static SOC_ENUM_SINGLE_DECL(rt5651_if2_dac_enum, RT5651_DIG_INF_DATA,
+ RT5651_IF2_DAC_SEL_SFT, rt5651_data_select);
+
+static SOC_ENUM_SINGLE_DECL(rt5651_if2_adc_enum, RT5651_DIG_INF_DATA,
+ RT5651_IF2_ADC_SEL_SFT, rt5651_data_select);
+
+static const struct snd_kcontrol_new rt5651_snd_controls[] = {
+ /* Headphone Output Volume */
+ SOC_DOUBLE_TLV("HP Playback Volume", RT5651_HP_VOL,
+ RT5651_L_VOL_SFT, RT5651_R_VOL_SFT, 39, 1, out_vol_tlv),
+ /* OUTPUT Control */
+ SOC_DOUBLE_TLV("OUT Playback Volume", RT5651_LOUT_CTRL1,
+ RT5651_L_VOL_SFT, RT5651_R_VOL_SFT, 39, 1, out_vol_tlv),
+
+ /* DAC Digital Volume */
+ SOC_DOUBLE("DAC2 Playback Switch", RT5651_DAC2_CTRL,
+ RT5651_M_DAC_L2_VOL_SFT, RT5651_M_DAC_R2_VOL_SFT, 1, 1),
+ SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5651_DAC1_DIG_VOL,
+ RT5651_L_VOL_SFT, RT5651_R_VOL_SFT,
+ 175, 0, dac_vol_tlv),
+ SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5651_DAC2_DIG_VOL,
+ RT5651_L_VOL_SFT, RT5651_R_VOL_SFT,
+ 175, 0, dac_vol_tlv),
+ /* IN1/IN2 Control */
+ SOC_SINGLE_TLV("IN1 Boost", RT5651_IN1_IN2,
+ RT5651_BST_SFT1, 8, 0, bst_tlv),
+ SOC_SINGLE_TLV("IN2 Boost", RT5651_IN1_IN2,
+ RT5651_BST_SFT2, 8, 0, bst_tlv),
+ /* INL/INR Volume Control */
+ SOC_DOUBLE_TLV("IN Capture Volume", RT5651_INL1_INR1_VOL,
+ RT5651_INL_VOL_SFT, RT5651_INR_VOL_SFT,
+ 31, 1, in_vol_tlv),
+ /* ADC Digital Volume Control */
+ SOC_DOUBLE("ADC Capture Switch", RT5651_ADC_DIG_VOL,
+ RT5651_L_MUTE_SFT, RT5651_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE_TLV("ADC Capture Volume", RT5651_ADC_DIG_VOL,
+ RT5651_L_VOL_SFT, RT5651_R_VOL_SFT,
+ 127, 0, adc_vol_tlv),
+ SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5651_ADC_DATA,
+ RT5651_L_VOL_SFT, RT5651_R_VOL_SFT,
+ 127, 0, adc_vol_tlv),
+ /* ADC Boost Volume Control */
+ SOC_DOUBLE_TLV("ADC Boost Gain", RT5651_ADC_BST_VOL,
+ RT5651_ADC_L_BST_SFT, RT5651_ADC_R_BST_SFT,
+ 3, 0, adc_bst_tlv),
+
+ /* ASRC */
+ SOC_SINGLE("IF1 ASRC Switch", RT5651_PLL_MODE_1,
+ RT5651_STO1_T_SFT, 1, 0),
+ SOC_SINGLE("IF2 ASRC Switch", RT5651_PLL_MODE_1,
+ RT5651_STO2_T_SFT, 1, 0),
+ SOC_SINGLE("DMIC ASRC Switch", RT5651_PLL_MODE_1,
+ RT5651_DMIC_1_M_SFT, 1, 0),
+
+ SOC_ENUM("ADC IF2 Data Switch", rt5651_if2_adc_enum),
+ SOC_ENUM("DAC IF2 Data Switch", rt5651_if2_dac_enum),
+};
+
+/**
+ * set_dmic_clk - Set parameter of dmic.
+ *
+ * @w: DAPM widget.
+ * @kcontrol: The kcontrol of this widget.
+ * @event: Event id.
+ *
+ */
+static int set_dmic_clk(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+ int idx = -EINVAL;
+
+ idx = rl6231_calc_dmic_clk(rt5651->sysclk);
+
+ if (idx < 0)
+ dev_err(codec->dev, "Failed to set DMIC clock\n");
+ else
+ snd_soc_update_bits(codec, RT5651_DMIC, RT5651_DMIC_CLK_MASK,
+ idx << RT5651_DMIC_CLK_SFT);
+
+ return idx;
+}
+
+static int is_sysclk_from_pll(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int val;
+
+ val = snd_soc_read(source->codec, RT5651_GLB_CLK);
+ val &= RT5651_SCLK_SRC_MASK;
+ if (val == RT5651_SCLK_SRC_PLL1)
+ return 1;
+ else
+ return 0;
+}
+
+/* Digital Mixer */
+static const struct snd_kcontrol_new rt5651_sto1_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5651_STO1_ADC_MIXER,
+ RT5651_M_STO1_ADC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5651_STO1_ADC_MIXER,
+ RT5651_M_STO1_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_sto1_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5651_STO1_ADC_MIXER,
+ RT5651_M_STO1_ADC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5651_STO1_ADC_MIXER,
+ RT5651_M_STO1_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_sto2_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5651_STO2_ADC_MIXER,
+ RT5651_M_STO2_ADC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5651_STO2_ADC_MIXER,
+ RT5651_M_STO2_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_sto2_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5651_STO2_ADC_MIXER,
+ RT5651_M_STO2_ADC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5651_STO2_ADC_MIXER,
+ RT5651_M_STO2_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("Stereo ADC Switch", RT5651_AD_DA_MIXER,
+ RT5651_M_ADCMIX_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INF1 Switch", RT5651_AD_DA_MIXER,
+ RT5651_M_IF1_DAC_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("Stereo ADC Switch", RT5651_AD_DA_MIXER,
+ RT5651_M_ADCMIX_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INF1 Switch", RT5651_AD_DA_MIXER,
+ RT5651_M_IF1_DAC_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_sto_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5651_STO_DAC_MIXER,
+ RT5651_M_DAC_L1_MIXL_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5651_STO_DAC_MIXER,
+ RT5651_M_DAC_L2_MIXL_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5651_STO_DAC_MIXER,
+ RT5651_M_DAC_R1_MIXL_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_sto_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5651_STO_DAC_MIXER,
+ RT5651_M_DAC_R1_MIXR_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5651_STO_DAC_MIXER,
+ RT5651_M_DAC_R2_MIXR_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5651_STO_DAC_MIXER,
+ RT5651_M_DAC_L1_MIXR_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_dd_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5651_DD_MIXER,
+ RT5651_M_STO_DD_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5651_DD_MIXER,
+ RT5651_M_STO_DD_L2_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5651_DD_MIXER,
+ RT5651_M_STO_DD_R2_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_dd_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5651_DD_MIXER,
+ RT5651_M_STO_DD_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5651_DD_MIXER,
+ RT5651_M_STO_DD_R2_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5651_DD_MIXER,
+ RT5651_M_STO_DD_L2_R_SFT, 1, 1),
+};
+
+/* Analog Input Mixer */
+static const struct snd_kcontrol_new rt5651_rec_l_mix[] = {
+ SOC_DAPM_SINGLE("INL1 Switch", RT5651_REC_L2_MIXER,
+ RT5651_M_IN1_L_RM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST3 Switch", RT5651_REC_L2_MIXER,
+ RT5651_M_BST3_RM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5651_REC_L2_MIXER,
+ RT5651_M_BST2_RM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5651_REC_L2_MIXER,
+ RT5651_M_BST1_RM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_rec_r_mix[] = {
+ SOC_DAPM_SINGLE("INR1 Switch", RT5651_REC_R2_MIXER,
+ RT5651_M_IN1_R_RM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST3 Switch", RT5651_REC_R2_MIXER,
+ RT5651_M_BST3_RM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5651_REC_R2_MIXER,
+ RT5651_M_BST2_RM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5651_REC_R2_MIXER,
+ RT5651_M_BST1_RM_R_SFT, 1, 1),
+};
+
+/* Analog Output Mixer */
+
+static const struct snd_kcontrol_new rt5651_out_l_mix[] = {
+ SOC_DAPM_SINGLE("BST1 Switch", RT5651_OUT_L3_MIXER,
+ RT5651_M_BST1_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5651_OUT_L3_MIXER,
+ RT5651_M_BST2_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL1 Switch", RT5651_OUT_L3_MIXER,
+ RT5651_M_IN1_L_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("REC MIXL Switch", RT5651_OUT_L3_MIXER,
+ RT5651_M_RM_L_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5651_OUT_L3_MIXER,
+ RT5651_M_DAC_L1_OM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_out_r_mix[] = {
+ SOC_DAPM_SINGLE("BST2 Switch", RT5651_OUT_R3_MIXER,
+ RT5651_M_BST2_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5651_OUT_R3_MIXER,
+ RT5651_M_BST1_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR1 Switch", RT5651_OUT_R3_MIXER,
+ RT5651_M_IN1_R_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("REC MIXR Switch", RT5651_OUT_R3_MIXER,
+ RT5651_M_RM_R_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5651_OUT_R3_MIXER,
+ RT5651_M_DAC_R1_OM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_hpo_mix[] = {
+ SOC_DAPM_SINGLE("HPO MIX DAC1 Switch", RT5651_HPO_MIXER,
+ RT5651_M_DAC1_HM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("HPO MIX HPVOL Switch", RT5651_HPO_MIXER,
+ RT5651_M_HPVOL_HM_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_lout_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5651_LOUT_MIXER,
+ RT5651_M_DAC_L1_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5651_LOUT_MIXER,
+ RT5651_M_DAC_R1_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOL L Switch", RT5651_LOUT_MIXER,
+ RT5651_M_OV_L_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOL R Switch", RT5651_LOUT_MIXER,
+ RT5651_M_OV_R_LM_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new outvol_l_control =
+ SOC_DAPM_SINGLE("Switch", RT5651_LOUT_CTRL1,
+ RT5651_VOL_L_SFT, 1, 1);
+
+static const struct snd_kcontrol_new outvol_r_control =
+ SOC_DAPM_SINGLE("Switch", RT5651_LOUT_CTRL1,
+ RT5651_VOL_R_SFT, 1, 1);
+
+static const struct snd_kcontrol_new lout_l_mute_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5651_LOUT_CTRL1,
+ RT5651_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new lout_r_mute_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5651_LOUT_CTRL1,
+ RT5651_R_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hpovol_l_control =
+ SOC_DAPM_SINGLE("Switch", RT5651_HP_VOL,
+ RT5651_VOL_L_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hpovol_r_control =
+ SOC_DAPM_SINGLE("Switch", RT5651_HP_VOL,
+ RT5651_VOL_R_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hpo_l_mute_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5651_HP_VOL,
+ RT5651_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hpo_r_mute_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5651_HP_VOL,
+ RT5651_R_MUTE_SFT, 1, 1);
+
+/* INL/R source */
+static const char * const rt5651_inl_src[] = {"IN2P", "HPOVOLLP"};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5651_inl_enum, RT5651_INL1_INR1_VOL,
+ RT5651_INL_SEL_SFT, rt5651_inl_src);
+
+static const struct snd_kcontrol_new rt5651_inl1_mux =
+ SOC_DAPM_ENUM("INL1 source", rt5651_inl_enum);
+
+static const char * const rt5651_inr1_src[] = {"IN2N", "HPOVOLRP"};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5651_inr1_enum, RT5651_INL1_INR1_VOL,
+ RT5651_INR_SEL_SFT, rt5651_inr1_src);
+
+static const struct snd_kcontrol_new rt5651_inr1_mux =
+ SOC_DAPM_ENUM("INR1 source", rt5651_inr1_enum);
+
+static const char * const rt5651_inl2_src[] = {"IN3P", "OUTVOLLP"};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5651_inl2_enum, RT5651_INL2_INR2_VOL,
+ RT5651_INL_SEL_SFT, rt5651_inl2_src);
+
+static const struct snd_kcontrol_new rt5651_inl2_mux =
+ SOC_DAPM_ENUM("INL2 source", rt5651_inl2_enum);
+
+static const char * const rt5651_inr2_src[] = {"IN3N", "OUTVOLRP"};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5651_inr2_enum, RT5651_INL2_INR2_VOL,
+ RT5651_INR_SEL_SFT, rt5651_inr2_src);
+
+static const struct snd_kcontrol_new rt5651_inr2_mux =
+ SOC_DAPM_ENUM("INR2 source", rt5651_inr2_enum);
+
+
+/* Stereo ADC source */
+static const char * const rt5651_stereo1_adc1_src[] = {"DD MIX", "ADC"};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5651_stereo1_adc1_enum, RT5651_STO1_ADC_MIXER,
+ RT5651_STO1_ADC_1_SRC_SFT, rt5651_stereo1_adc1_src);
+
+static const struct snd_kcontrol_new rt5651_sto1_adc_l1_mux =
+ SOC_DAPM_ENUM("Stereo1 ADC L1 source", rt5651_stereo1_adc1_enum);
+
+static const struct snd_kcontrol_new rt5651_sto1_adc_r1_mux =
+ SOC_DAPM_ENUM("Stereo1 ADC R1 source", rt5651_stereo1_adc1_enum);
+
+static const char * const rt5651_stereo1_adc2_src[] = {"DMIC", "DD MIX"};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5651_stereo1_adc2_enum, RT5651_STO1_ADC_MIXER,
+ RT5651_STO1_ADC_2_SRC_SFT, rt5651_stereo1_adc2_src);
+
+static const struct snd_kcontrol_new rt5651_sto1_adc_l2_mux =
+ SOC_DAPM_ENUM("Stereo1 ADC L2 source", rt5651_stereo1_adc2_enum);
+
+static const struct snd_kcontrol_new rt5651_sto1_adc_r2_mux =
+ SOC_DAPM_ENUM("Stereo1 ADC R2 source", rt5651_stereo1_adc2_enum);
+
+/* Mono ADC source */
+static const char * const rt5651_sto2_adc_l1_src[] = {"DD MIXL", "ADCL"};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5651_sto2_adc_l1_enum, RT5651_STO1_ADC_MIXER,
+ RT5651_STO2_ADC_L1_SRC_SFT, rt5651_sto2_adc_l1_src);
+
+static const struct snd_kcontrol_new rt5651_sto2_adc_l1_mux =
+ SOC_DAPM_ENUM("Stereo2 ADC1 left source", rt5651_sto2_adc_l1_enum);
+
+static const char * const rt5651_sto2_adc_l2_src[] = {"DMIC L", "DD MIXL"};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5651_sto2_adc_l2_enum, RT5651_STO1_ADC_MIXER,
+ RT5651_STO2_ADC_L2_SRC_SFT, rt5651_sto2_adc_l2_src);
+
+static const struct snd_kcontrol_new rt5651_sto2_adc_l2_mux =
+ SOC_DAPM_ENUM("Stereo2 ADC2 left source", rt5651_sto2_adc_l2_enum);
+
+static const char * const rt5651_sto2_adc_r1_src[] = {"DD MIXR", "ADCR"};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5651_sto2_adc_r1_enum, RT5651_STO1_ADC_MIXER,
+ RT5651_STO2_ADC_R1_SRC_SFT, rt5651_sto2_adc_r1_src);
+
+static const struct snd_kcontrol_new rt5651_sto2_adc_r1_mux =
+ SOC_DAPM_ENUM("Stereo2 ADC1 right source", rt5651_sto2_adc_r1_enum);
+
+static const char * const rt5651_sto2_adc_r2_src[] = {"DMIC R", "DD MIXR"};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5651_sto2_adc_r2_enum, RT5651_STO1_ADC_MIXER,
+ RT5651_STO2_ADC_R2_SRC_SFT, rt5651_sto2_adc_r2_src);
+
+static const struct snd_kcontrol_new rt5651_sto2_adc_r2_mux =
+ SOC_DAPM_ENUM("Stereo2 ADC2 right source", rt5651_sto2_adc_r2_enum);
+
+/* DAC2 channel source */
+
+static const char * const rt5651_dac_src[] = {"IF1", "IF2"};
+
+static SOC_ENUM_SINGLE_DECL(rt5651_dac_l2_enum, RT5651_DAC2_CTRL,
+ RT5651_SEL_DAC_L2_SFT, rt5651_dac_src);
+
+static const struct snd_kcontrol_new rt5651_dac_l2_mux =
+ SOC_DAPM_ENUM("DAC2 left channel source", rt5651_dac_l2_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5651_dac_r2_enum, RT5651_DAC2_CTRL,
+ RT5651_SEL_DAC_R2_SFT, rt5651_dac_src);
+
+static const struct snd_kcontrol_new rt5651_dac_r2_mux =
+ SOC_DAPM_ENUM("DAC2 right channel source", rt5651_dac_r2_enum);
+
+/* IF2_ADC channel source */
+
+static const char * const rt5651_adc_src[] = {"IF1 ADC1", "IF1 ADC2"};
+
+static SOC_ENUM_SINGLE_DECL(rt5651_if2_adc_src_enum, RT5651_DIG_INF_DATA,
+ RT5651_IF2_ADC_SRC_SFT, rt5651_adc_src);
+
+static const struct snd_kcontrol_new rt5651_if2_adc_src_mux =
+ SOC_DAPM_ENUM("IF2 ADC channel source", rt5651_if2_adc_src_enum);
+
+/* PDM select */
+static const char * const rt5651_pdm_sel[] = {"DD MIX", "Stereo DAC MIX"};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5651_pdm_l_sel_enum, RT5651_PDM_CTL,
+ RT5651_PDM_L_SEL_SFT, rt5651_pdm_sel);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5651_pdm_r_sel_enum, RT5651_PDM_CTL,
+ RT5651_PDM_R_SEL_SFT, rt5651_pdm_sel);
+
+static const struct snd_kcontrol_new rt5651_pdm_l_mux =
+ SOC_DAPM_ENUM("PDM L select", rt5651_pdm_l_sel_enum);
+
+static const struct snd_kcontrol_new rt5651_pdm_r_mux =
+ SOC_DAPM_ENUM("PDM R select", rt5651_pdm_r_sel_enum);
+
+static int rt5651_amp_power_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /* depop parameters */
+ regmap_update_bits(rt5651->regmap, RT5651_PR_BASE +
+ RT5651_CHPUMP_INT_REG1, 0x0700, 0x0200);
+ regmap_update_bits(rt5651->regmap, RT5651_DEPOP_M2,
+ RT5651_DEPOP_MASK, RT5651_DEPOP_MAN);
+ regmap_update_bits(rt5651->regmap, RT5651_DEPOP_M1,
+ RT5651_HP_CP_MASK | RT5651_HP_SG_MASK |
+ RT5651_HP_CB_MASK, RT5651_HP_CP_PU |
+ RT5651_HP_SG_DIS | RT5651_HP_CB_PU);
+ regmap_write(rt5651->regmap, RT5651_PR_BASE +
+ RT5651_HP_DCC_INT1, 0x9f00);
+ /* headphone amp power on */
+ regmap_update_bits(rt5651->regmap, RT5651_PWR_ANLG1,
+ RT5651_PWR_FV1 | RT5651_PWR_FV2, 0);
+ regmap_update_bits(rt5651->regmap, RT5651_PWR_ANLG1,
+ RT5651_PWR_HA,
+ RT5651_PWR_HA);
+ usleep_range(10000, 15000);
+ regmap_update_bits(rt5651->regmap, RT5651_PWR_ANLG1,
+ RT5651_PWR_FV1 | RT5651_PWR_FV2 ,
+ RT5651_PWR_FV1 | RT5651_PWR_FV2);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5651_hp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /* headphone unmute sequence */
+ regmap_update_bits(rt5651->regmap, RT5651_DEPOP_M2,
+ RT5651_DEPOP_MASK | RT5651_DIG_DP_MASK,
+ RT5651_DEPOP_AUTO | RT5651_DIG_DP_EN);
+ regmap_update_bits(rt5651->regmap, RT5651_CHARGE_PUMP,
+ RT5651_PM_HP_MASK, RT5651_PM_HP_HV);
+
+ regmap_update_bits(rt5651->regmap, RT5651_DEPOP_M3,
+ RT5651_CP_FQ1_MASK | RT5651_CP_FQ2_MASK |
+ RT5651_CP_FQ3_MASK,
+ (RT5651_CP_FQ_192_KHZ << RT5651_CP_FQ1_SFT) |
+ (RT5651_CP_FQ_12_KHZ << RT5651_CP_FQ2_SFT) |
+ (RT5651_CP_FQ_192_KHZ << RT5651_CP_FQ3_SFT));
+
+ regmap_write(rt5651->regmap, RT5651_PR_BASE +
+ RT5651_MAMP_INT_REG2, 0x1c00);
+ regmap_update_bits(rt5651->regmap, RT5651_DEPOP_M1,
+ RT5651_HP_CP_MASK | RT5651_HP_SG_MASK,
+ RT5651_HP_CP_PD | RT5651_HP_SG_EN);
+ regmap_update_bits(rt5651->regmap, RT5651_PR_BASE +
+ RT5651_CHPUMP_INT_REG1, 0x0700, 0x0400);
+ rt5651->hp_mute = 0;
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ rt5651->hp_mute = 1;
+ usleep_range(70000, 75000);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5651_hp_post_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ if (!rt5651->hp_mute)
+ usleep_range(80000, 85000);
+
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5651_bst1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+ RT5651_PWR_BST1_OP2, RT5651_PWR_BST1_OP2);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+ RT5651_PWR_BST1_OP2, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5651_bst2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+ RT5651_PWR_BST2_OP2, RT5651_PWR_BST2_OP2);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+ RT5651_PWR_BST2_OP2, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5651_bst3_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+ RT5651_PWR_BST3_OP2, RT5651_PWR_BST3_OP2);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+ RT5651_PWR_BST3_OP2, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget rt5651_dapm_widgets[] = {
+ /* ASRC */
+ SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5651_PLL_MODE_2,
+ 15, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5651_PLL_MODE_2,
+ 14, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("STO1 DAC ASRC", 1, RT5651_PLL_MODE_2,
+ 13, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("STO2 DAC ASRC", 1, RT5651_PLL_MODE_2,
+ 12, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ADC ASRC", 1, RT5651_PLL_MODE_2,
+ 11, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("PLL1", RT5651_PWR_ANLG2,
+ RT5651_PWR_PLL_BIT, 0, NULL, 0),
+ /* Input Side */
+ /* micbias */
+ SND_SOC_DAPM_SUPPLY("LDO", RT5651_PWR_ANLG1,
+ RT5651_PWR_LDO_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MICBIAS("micbias1", RT5651_PWR_ANLG2,
+ RT5651_PWR_MB1_BIT, 0),
+ /* Input Lines */
+ SND_SOC_DAPM_INPUT("MIC1"),
+ SND_SOC_DAPM_INPUT("MIC2"),
+ SND_SOC_DAPM_INPUT("MIC3"),
+
+ SND_SOC_DAPM_INPUT("IN1P"),
+ SND_SOC_DAPM_INPUT("IN2P"),
+ SND_SOC_DAPM_INPUT("IN2N"),
+ SND_SOC_DAPM_INPUT("IN3P"),
+ SND_SOC_DAPM_INPUT("DMIC L1"),
+ SND_SOC_DAPM_INPUT("DMIC R1"),
+ SND_SOC_DAPM_SUPPLY("DMIC CLK", RT5651_DMIC, RT5651_DMIC_1_EN_SFT,
+ 0, set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
+ /* Boost */
+ SND_SOC_DAPM_PGA_E("BST1", RT5651_PWR_ANLG2,
+ RT5651_PWR_BST1_BIT, 0, NULL, 0, rt5651_bst1_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_E("BST2", RT5651_PWR_ANLG2,
+ RT5651_PWR_BST2_BIT, 0, NULL, 0, rt5651_bst2_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_E("BST3", RT5651_PWR_ANLG2,
+ RT5651_PWR_BST3_BIT, 0, NULL, 0, rt5651_bst3_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ /* Input Volume */
+ SND_SOC_DAPM_PGA("INL1 VOL", RT5651_PWR_VOL,
+ RT5651_PWR_IN1_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INR1 VOL", RT5651_PWR_VOL,
+ RT5651_PWR_IN1_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INL2 VOL", RT5651_PWR_VOL,
+ RT5651_PWR_IN2_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INR2 VOL", RT5651_PWR_VOL,
+ RT5651_PWR_IN2_R_BIT, 0, NULL, 0),
+ /* IN Mux */
+ SND_SOC_DAPM_MUX("INL1 Mux", SND_SOC_NOPM, 0, 0, &rt5651_inl1_mux),
+ SND_SOC_DAPM_MUX("INR1 Mux", SND_SOC_NOPM, 0, 0, &rt5651_inr1_mux),
+ SND_SOC_DAPM_MUX("INL2 Mux", SND_SOC_NOPM, 0, 0, &rt5651_inl2_mux),
+ SND_SOC_DAPM_MUX("INR2 Mux", SND_SOC_NOPM, 0, 0, &rt5651_inr2_mux),
+ /* REC Mixer */
+ SND_SOC_DAPM_MIXER("RECMIXL", RT5651_PWR_MIXER, RT5651_PWR_RM_L_BIT, 0,
+ rt5651_rec_l_mix, ARRAY_SIZE(rt5651_rec_l_mix)),
+ SND_SOC_DAPM_MIXER("RECMIXR", RT5651_PWR_MIXER, RT5651_PWR_RM_R_BIT, 0,
+ rt5651_rec_r_mix, ARRAY_SIZE(rt5651_rec_r_mix)),
+ /* ADCs */
+ SND_SOC_DAPM_ADC("ADC L", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_ADC("ADC R", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_SUPPLY("ADC L Power", RT5651_PWR_DIG1,
+ RT5651_PWR_ADC_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("ADC R Power", RT5651_PWR_DIG1,
+ RT5651_PWR_ADC_R_BIT, 0, NULL, 0),
+ /* ADC Mux */
+ SND_SOC_DAPM_MUX("Stereo1 ADC L2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5651_sto1_adc_l2_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC R2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5651_sto1_adc_r2_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC L1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5651_sto1_adc_l1_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC R1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5651_sto1_adc_r1_mux),
+ SND_SOC_DAPM_MUX("Stereo2 ADC L2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5651_sto2_adc_l2_mux),
+ SND_SOC_DAPM_MUX("Stereo2 ADC L1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5651_sto2_adc_l1_mux),
+ SND_SOC_DAPM_MUX("Stereo2 ADC R1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5651_sto2_adc_r1_mux),
+ SND_SOC_DAPM_MUX("Stereo2 ADC R2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5651_sto2_adc_r2_mux),
+ /* ADC Mixer */
+ SND_SOC_DAPM_SUPPLY("Stereo1 Filter", RT5651_PWR_DIG2,
+ RT5651_PWR_ADC_STO1_F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Stereo2 Filter", RT5651_PWR_DIG2,
+ RT5651_PWR_ADC_STO2_F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Stereo1 ADC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5651_sto1_adc_l_mix,
+ ARRAY_SIZE(rt5651_sto1_adc_l_mix)),
+ SND_SOC_DAPM_MIXER("Stereo1 ADC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5651_sto1_adc_r_mix,
+ ARRAY_SIZE(rt5651_sto1_adc_r_mix)),
+ SND_SOC_DAPM_MIXER("Stereo2 ADC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5651_sto2_adc_l_mix,
+ ARRAY_SIZE(rt5651_sto2_adc_l_mix)),
+ SND_SOC_DAPM_MIXER("Stereo2 ADC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5651_sto2_adc_r_mix,
+ ARRAY_SIZE(rt5651_sto2_adc_r_mix)),
+
+ /* Digital Interface */
+ SND_SOC_DAPM_SUPPLY("I2S1", RT5651_PWR_DIG1,
+ RT5651_PWR_I2S1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC2 L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC2 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("I2S2", RT5651_PWR_DIG1,
+ RT5651_PWR_I2S2_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MUX("IF2 ADC", SND_SOC_NOPM, 0, 0,
+ &rt5651_if2_adc_src_mux),
+
+ /* Digital Interface Select */
+
+ SND_SOC_DAPM_MUX("PDM L Mux", RT5651_PDM_CTL,
+ RT5651_M_PDM_L_SFT, 1, &rt5651_pdm_l_mux),
+ SND_SOC_DAPM_MUX("PDM R Mux", RT5651_PDM_CTL,
+ RT5651_M_PDM_R_SFT, 1, &rt5651_pdm_r_mux),
+ /* Audio Interface */
+ SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+
+ /* Audio DSP */
+ SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Output Side */
+ /* DAC mixer before sound effect */
+ SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5651_dac_l_mix, ARRAY_SIZE(rt5651_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5651_dac_r_mix, ARRAY_SIZE(rt5651_dac_r_mix)),
+
+ /* DAC2 channel Mux */
+ SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0, &rt5651_dac_l2_mux),
+ SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0, &rt5651_dac_r2_mux),
+ SND_SOC_DAPM_PGA("DAC L2 Volume", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("DAC R2 Volume", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("Stero1 DAC Power", RT5651_PWR_DIG2,
+ RT5651_PWR_DAC_STO1_F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Stero2 DAC Power", RT5651_PWR_DIG2,
+ RT5651_PWR_DAC_STO2_F_BIT, 0, NULL, 0),
+ /* DAC Mixer */
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5651_sto_dac_l_mix,
+ ARRAY_SIZE(rt5651_sto_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5651_sto_dac_r_mix,
+ ARRAY_SIZE(rt5651_sto_dac_r_mix)),
+ SND_SOC_DAPM_MIXER("DD MIXL", SND_SOC_NOPM, 0, 0,
+ rt5651_dd_dac_l_mix,
+ ARRAY_SIZE(rt5651_dd_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("DD MIXR", SND_SOC_NOPM, 0, 0,
+ rt5651_dd_dac_r_mix,
+ ARRAY_SIZE(rt5651_dd_dac_r_mix)),
+
+ /* DACs */
+ SND_SOC_DAPM_DAC("DAC L1", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("DAC R1", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_SUPPLY("DAC L1 Power", RT5651_PWR_DIG1,
+ RT5651_PWR_DAC_L1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DAC R1 Power", RT5651_PWR_DIG1,
+ RT5651_PWR_DAC_R1_BIT, 0, NULL, 0),
+ /* OUT Mixer */
+ SND_SOC_DAPM_MIXER("OUT MIXL", RT5651_PWR_MIXER, RT5651_PWR_OM_L_BIT,
+ 0, rt5651_out_l_mix, ARRAY_SIZE(rt5651_out_l_mix)),
+ SND_SOC_DAPM_MIXER("OUT MIXR", RT5651_PWR_MIXER, RT5651_PWR_OM_R_BIT,
+ 0, rt5651_out_r_mix, ARRAY_SIZE(rt5651_out_r_mix)),
+ /* Ouput Volume */
+ SND_SOC_DAPM_SWITCH("OUTVOL L", RT5651_PWR_VOL,
+ RT5651_PWR_OV_L_BIT, 0, &outvol_l_control),
+ SND_SOC_DAPM_SWITCH("OUTVOL R", RT5651_PWR_VOL,
+ RT5651_PWR_OV_R_BIT, 0, &outvol_r_control),
+ SND_SOC_DAPM_SWITCH("HPOVOL L", RT5651_PWR_VOL,
+ RT5651_PWR_HV_L_BIT, 0, &hpovol_l_control),
+ SND_SOC_DAPM_SWITCH("HPOVOL R", RT5651_PWR_VOL,
+ RT5651_PWR_HV_R_BIT, 0, &hpovol_r_control),
+ SND_SOC_DAPM_PGA("INL1", RT5651_PWR_VOL,
+ RT5651_PWR_IN1_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INR1", RT5651_PWR_VOL,
+ RT5651_PWR_IN1_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INL2", RT5651_PWR_VOL,
+ RT5651_PWR_IN2_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INR2", RT5651_PWR_VOL,
+ RT5651_PWR_IN2_R_BIT, 0, NULL, 0),
+ /* HPO/LOUT/Mono Mixer */
+ SND_SOC_DAPM_MIXER("HPOL MIX", SND_SOC_NOPM, 0, 0,
+ rt5651_hpo_mix, ARRAY_SIZE(rt5651_hpo_mix)),
+ SND_SOC_DAPM_MIXER("HPOR MIX", SND_SOC_NOPM, 0, 0,
+ rt5651_hpo_mix, ARRAY_SIZE(rt5651_hpo_mix)),
+ SND_SOC_DAPM_SUPPLY("HP L Amp", RT5651_PWR_ANLG1,
+ RT5651_PWR_HP_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("HP R Amp", RT5651_PWR_ANLG1,
+ RT5651_PWR_HP_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("LOUT MIX", RT5651_PWR_ANLG1, RT5651_PWR_LM_BIT, 0,
+ rt5651_lout_mix, ARRAY_SIZE(rt5651_lout_mix)),
+
+ SND_SOC_DAPM_SUPPLY("Amp Power", RT5651_PWR_ANLG1,
+ RT5651_PWR_HA_BIT, 0, rt5651_amp_power_event,
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, rt5651_hp_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_SWITCH("HPO L Playback", SND_SOC_NOPM, 0, 0,
+ &hpo_l_mute_control),
+ SND_SOC_DAPM_SWITCH("HPO R Playback", SND_SOC_NOPM, 0, 0,
+ &hpo_r_mute_control),
+ SND_SOC_DAPM_SWITCH("LOUT L Playback", SND_SOC_NOPM, 0, 0,
+ &lout_l_mute_control),
+ SND_SOC_DAPM_SWITCH("LOUT R Playback", SND_SOC_NOPM, 0, 0,
+ &lout_r_mute_control),
+ SND_SOC_DAPM_POST("HP Post", rt5651_hp_post_event),
+
+ /* Output Lines */
+ SND_SOC_DAPM_OUTPUT("HPOL"),
+ SND_SOC_DAPM_OUTPUT("HPOR"),
+ SND_SOC_DAPM_OUTPUT("LOUTL"),
+ SND_SOC_DAPM_OUTPUT("LOUTR"),
+ SND_SOC_DAPM_OUTPUT("PDML"),
+ SND_SOC_DAPM_OUTPUT("PDMR"),
+};
+
+static const struct snd_soc_dapm_route rt5651_dapm_routes[] = {
+ {"Stero1 DAC Power", NULL, "STO1 DAC ASRC"},
+ {"Stero2 DAC Power", NULL, "STO2 DAC ASRC"},
+ {"I2S1", NULL, "I2S1 ASRC"},
+ {"I2S2", NULL, "I2S2 ASRC"},
+
+ {"IN1P", NULL, "LDO"},
+ {"IN2P", NULL, "LDO"},
+ {"IN3P", NULL, "LDO"},
+
+ {"IN1P", NULL, "MIC1"},
+ {"IN2P", NULL, "MIC2"},
+ {"IN2N", NULL, "MIC2"},
+ {"IN3P", NULL, "MIC3"},
+
+ {"BST1", NULL, "IN1P"},
+ {"BST2", NULL, "IN2P"},
+ {"BST2", NULL, "IN2N"},
+ {"BST3", NULL, "IN3P"},
+
+ {"INL1 VOL", NULL, "IN2P"},
+ {"INR1 VOL", NULL, "IN2N"},
+
+ {"RECMIXL", "INL1 Switch", "INL1 VOL"},
+ {"RECMIXL", "BST3 Switch", "BST3"},
+ {"RECMIXL", "BST2 Switch", "BST2"},
+ {"RECMIXL", "BST1 Switch", "BST1"},
+
+ {"RECMIXR", "INR1 Switch", "INR1 VOL"},
+ {"RECMIXR", "BST3 Switch", "BST3"},
+ {"RECMIXR", "BST2 Switch", "BST2"},
+ {"RECMIXR", "BST1 Switch", "BST1"},
+
+ {"ADC L", NULL, "RECMIXL"},
+ {"ADC L", NULL, "ADC L Power"},
+ {"ADC R", NULL, "RECMIXR"},
+ {"ADC R", NULL, "ADC R Power"},
+
+ {"DMIC L1", NULL, "DMIC CLK"},
+ {"DMIC R1", NULL, "DMIC CLK"},
+
+ {"Stereo1 ADC L2 Mux", "DMIC", "DMIC L1"},
+ {"Stereo1 ADC L2 Mux", "DD MIX", "DD MIXL"},
+ {"Stereo1 ADC L1 Mux", "ADC", "ADC L"},
+ {"Stereo1 ADC L1 Mux", "DD MIX", "DD MIXL"},
+
+ {"Stereo1 ADC R1 Mux", "ADC", "ADC R"},
+ {"Stereo1 ADC R1 Mux", "DD MIX", "DD MIXR"},
+ {"Stereo1 ADC R2 Mux", "DMIC", "DMIC R1"},
+ {"Stereo1 ADC R2 Mux", "DD MIX", "DD MIXR"},
+
+ {"Stereo2 ADC L2 Mux", "DMIC L", "DMIC L1"},
+ {"Stereo2 ADC L2 Mux", "DD MIXL", "DD MIXL"},
+ {"Stereo2 ADC L1 Mux", "DD MIXL", "DD MIXL"},
+ {"Stereo2 ADC L1 Mux", "ADCL", "ADC L"},
+
+ {"Stereo2 ADC R1 Mux", "DD MIXR", "DD MIXR"},
+ {"Stereo2 ADC R1 Mux", "ADCR", "ADC R"},
+ {"Stereo2 ADC R2 Mux", "DMIC R", "DMIC R1"},
+ {"Stereo2 ADC R2 Mux", "DD MIXR", "DD MIXR"},
+
+ {"Stereo1 ADC MIXL", "ADC1 Switch", "Stereo1 ADC L1 Mux"},
+ {"Stereo1 ADC MIXL", "ADC2 Switch", "Stereo1 ADC L2 Mux"},
+ {"Stereo1 ADC MIXL", NULL, "Stereo1 Filter"},
+ {"Stereo1 Filter", NULL, "PLL1", is_sysclk_from_pll},
+ {"Stereo1 Filter", NULL, "ADC ASRC"},
+
+ {"Stereo1 ADC MIXR", "ADC1 Switch", "Stereo1 ADC R1 Mux"},
+ {"Stereo1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux"},
+ {"Stereo1 ADC MIXR", NULL, "Stereo1 Filter"},
+
+ {"Stereo2 ADC MIXL", "ADC1 Switch", "Stereo2 ADC L1 Mux"},
+ {"Stereo2 ADC MIXL", "ADC2 Switch", "Stereo2 ADC L2 Mux"},
+ {"Stereo2 ADC MIXL", NULL, "Stereo2 Filter"},
+ {"Stereo2 Filter", NULL, "PLL1", is_sysclk_from_pll},
+ {"Stereo2 Filter", NULL, "ADC ASRC"},
+
+ {"Stereo2 ADC MIXR", "ADC1 Switch", "Stereo2 ADC R1 Mux"},
+ {"Stereo2 ADC MIXR", "ADC2 Switch", "Stereo2 ADC R2 Mux"},
+ {"Stereo2 ADC MIXR", NULL, "Stereo2 Filter"},
+
+ {"IF1 ADC2", NULL, "Stereo2 ADC MIXL"},
+ {"IF1 ADC2", NULL, "Stereo2 ADC MIXR"},
+ {"IF1 ADC1", NULL, "Stereo1 ADC MIXL"},
+ {"IF1 ADC1", NULL, "Stereo1 ADC MIXR"},
+
+ {"IF1 ADC1", NULL, "I2S1"},
+
+ {"IF2 ADC", "IF1 ADC1", "IF1 ADC1"},
+ {"IF2 ADC", "IF1 ADC2", "IF1 ADC2"},
+ {"IF2 ADC", NULL, "I2S2"},
+
+ {"AIF1TX", NULL, "IF1 ADC1"},
+ {"AIF1TX", NULL, "IF1 ADC2"},
+ {"AIF2TX", NULL, "IF2 ADC"},
+
+ {"IF1 DAC", NULL, "AIF1RX"},
+ {"IF1 DAC", NULL, "I2S1"},
+ {"IF2 DAC", NULL, "AIF2RX"},
+ {"IF2 DAC", NULL, "I2S2"},
+
+ {"IF1 DAC1 L", NULL, "IF1 DAC"},
+ {"IF1 DAC1 R", NULL, "IF1 DAC"},
+ {"IF1 DAC2 L", NULL, "IF1 DAC"},
+ {"IF1 DAC2 R", NULL, "IF1 DAC"},
+ {"IF2 DAC L", NULL, "IF2 DAC"},
+ {"IF2 DAC R", NULL, "IF2 DAC"},
+
+ {"DAC MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL"},
+ {"DAC MIXL", "INF1 Switch", "IF1 DAC1 L"},
+ {"DAC MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR"},
+ {"DAC MIXR", "INF1 Switch", "IF1 DAC1 R"},
+
+ {"Audio DSP", NULL, "DAC MIXL"},
+ {"Audio DSP", NULL, "DAC MIXR"},
+
+ {"DAC L2 Mux", "IF1", "IF1 DAC2 L"},
+ {"DAC L2 Mux", "IF2", "IF2 DAC L"},
+ {"DAC L2 Volume", NULL, "DAC L2 Mux"},
+
+ {"DAC R2 Mux", "IF1", "IF1 DAC2 R"},
+ {"DAC R2 Mux", "IF2", "IF2 DAC R"},
+ {"DAC R2 Volume", NULL, "DAC R2 Mux"},
+
+ {"Stereo DAC MIXL", "DAC L1 Switch", "Audio DSP"},
+ {"Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Volume"},
+ {"Stereo DAC MIXL", "DAC R1 Switch", "DAC MIXR"},
+ {"Stereo DAC MIXL", NULL, "Stero1 DAC Power"},
+ {"Stereo DAC MIXL", NULL, "Stero2 DAC Power"},
+ {"Stereo DAC MIXR", "DAC R1 Switch", "Audio DSP"},
+ {"Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Volume"},
+ {"Stereo DAC MIXR", "DAC L1 Switch", "DAC MIXL"},
+ {"Stereo DAC MIXR", NULL, "Stero1 DAC Power"},
+ {"Stereo DAC MIXR", NULL, "Stero2 DAC Power"},
+
+ {"PDM L Mux", "Stereo DAC MIX", "Stereo DAC MIXL"},
+ {"PDM L Mux", "DD MIX", "DAC MIXL"},
+ {"PDM R Mux", "Stereo DAC MIX", "Stereo DAC MIXR"},
+ {"PDM R Mux", "DD MIX", "DAC MIXR"},
+
+ {"DAC L1", NULL, "Stereo DAC MIXL"},
+ {"DAC L1", NULL, "PLL1", is_sysclk_from_pll},
+ {"DAC L1", NULL, "DAC L1 Power"},
+ {"DAC R1", NULL, "Stereo DAC MIXR"},
+ {"DAC R1", NULL, "PLL1", is_sysclk_from_pll},
+ {"DAC R1", NULL, "DAC R1 Power"},
+
+ {"DD MIXL", "DAC L1 Switch", "DAC MIXL"},
+ {"DD MIXL", "DAC L2 Switch", "DAC L2 Volume"},
+ {"DD MIXL", "DAC R2 Switch", "DAC R2 Volume"},
+ {"DD MIXL", NULL, "Stero2 DAC Power"},
+
+ {"DD MIXR", "DAC R1 Switch", "DAC MIXR"},
+ {"DD MIXR", "DAC R2 Switch", "DAC R2 Volume"},
+ {"DD MIXR", "DAC L2 Switch", "DAC L2 Volume"},
+ {"DD MIXR", NULL, "Stero2 DAC Power"},
+
+ {"OUT MIXL", "BST1 Switch", "BST1"},
+ {"OUT MIXL", "BST2 Switch", "BST2"},
+ {"OUT MIXL", "INL1 Switch", "INL1 VOL"},
+ {"OUT MIXL", "REC MIXL Switch", "RECMIXL"},
+ {"OUT MIXL", "DAC L1 Switch", "DAC L1"},
+
+ {"OUT MIXR", "BST2 Switch", "BST2"},
+ {"OUT MIXR", "BST1 Switch", "BST1"},
+ {"OUT MIXR", "INR1 Switch", "INR1 VOL"},
+ {"OUT MIXR", "REC MIXR Switch", "RECMIXR"},
+ {"OUT MIXR", "DAC R1 Switch", "DAC R1"},
+
+ {"HPOVOL L", "Switch", "OUT MIXL"},
+ {"HPOVOL R", "Switch", "OUT MIXR"},
+ {"OUTVOL L", "Switch", "OUT MIXL"},
+ {"OUTVOL R", "Switch", "OUT MIXR"},
+
+ {"HPOL MIX", "HPO MIX DAC1 Switch", "DAC L1"},
+ {"HPOL MIX", "HPO MIX HPVOL Switch", "HPOVOL L"},
+ {"HPOL MIX", NULL, "HP L Amp"},
+ {"HPOR MIX", "HPO MIX DAC1 Switch", "DAC R1"},
+ {"HPOR MIX", "HPO MIX HPVOL Switch", "HPOVOL R"},
+ {"HPOR MIX", NULL, "HP R Amp"},
+
+ {"LOUT MIX", "DAC L1 Switch", "DAC L1"},
+ {"LOUT MIX", "DAC R1 Switch", "DAC R1"},
+ {"LOUT MIX", "OUTVOL L Switch", "OUTVOL L"},
+ {"LOUT MIX", "OUTVOL R Switch", "OUTVOL R"},
+
+ {"HP Amp", NULL, "HPOL MIX"},
+ {"HP Amp", NULL, "HPOR MIX"},
+ {"HP Amp", NULL, "Amp Power"},
+ {"HPO L Playback", "Switch", "HP Amp"},
+ {"HPO R Playback", "Switch", "HP Amp"},
+ {"HPOL", NULL, "HPO L Playback"},
+ {"HPOR", NULL, "HPO R Playback"},
+
+ {"LOUT L Playback", "Switch", "LOUT MIX"},
+ {"LOUT R Playback", "Switch", "LOUT MIX"},
+ {"LOUTL", NULL, "LOUT L Playback"},
+ {"LOUTL", NULL, "Amp Power"},
+ {"LOUTR", NULL, "LOUT R Playback"},
+ {"LOUTR", NULL, "Amp Power"},
+
+ {"PDML", NULL, "PDM L Mux"},
+ {"PDMR", NULL, "PDM R Mux"},
+};
+
+static int rt5651_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;
+ struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+ unsigned int val_len = 0, val_clk, mask_clk;
+ int pre_div, bclk_ms, frame_size;
+
+ rt5651->lrck[dai->id] = params_rate(params);
+ pre_div = rl6231_get_clk_info(rt5651->sysclk, rt5651->lrck[dai->id]);
+
+ if (pre_div < 0) {
+ dev_err(codec->dev, "Unsupported clock setting\n");
+ return -EINVAL;
+ }
+ frame_size = snd_soc_params_to_frame_size(params);
+ if (frame_size < 0) {
+ dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size);
+ return -EINVAL;
+ }
+ bclk_ms = frame_size > 32 ? 1 : 0;
+ rt5651->bclk[dai->id] = rt5651->lrck[dai->id] * (32 << bclk_ms);
+
+ dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n",
+ rt5651->bclk[dai->id], rt5651->lrck[dai->id]);
+ dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
+ bclk_ms, pre_div, dai->id);
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ val_len |= RT5651_I2S_DL_20;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ val_len |= RT5651_I2S_DL_24;
+ break;
+ case SNDRV_PCM_FORMAT_S8:
+ val_len |= RT5651_I2S_DL_8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (dai->id) {
+ case RT5651_AIF1:
+ mask_clk = RT5651_I2S_PD1_MASK;
+ val_clk = pre_div << RT5651_I2S_PD1_SFT;
+ snd_soc_update_bits(codec, RT5651_I2S1_SDP,
+ RT5651_I2S_DL_MASK, val_len);
+ snd_soc_update_bits(codec, RT5651_ADDA_CLK1, mask_clk, val_clk);
+ break;
+ case RT5651_AIF2:
+ mask_clk = RT5651_I2S_BCLK_MS2_MASK | RT5651_I2S_PD2_MASK;
+ val_clk = pre_div << RT5651_I2S_PD2_SFT;
+ snd_soc_update_bits(codec, RT5651_I2S2_SDP,
+ RT5651_I2S_DL_MASK, val_len);
+ snd_soc_update_bits(codec, RT5651_ADDA_CLK1, mask_clk, val_clk);
+ break;
+ default:
+ dev_err(codec->dev, "Wrong dai->id: %d\n", dai->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rt5651_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+ unsigned int reg_val = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ rt5651->master[dai->id] = 1;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ reg_val |= RT5651_I2S_MS_S;
+ rt5651->master[dai->id] = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ reg_val |= RT5651_I2S_BP_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ reg_val |= RT5651_I2S_DF_LEFT;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ reg_val |= RT5651_I2S_DF_PCM_A;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ reg_val |= RT5651_I2S_DF_PCM_B;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (dai->id) {
+ case RT5651_AIF1:
+ snd_soc_update_bits(codec, RT5651_I2S1_SDP,
+ RT5651_I2S_MS_MASK | RT5651_I2S_BP_MASK |
+ RT5651_I2S_DF_MASK, reg_val);
+ break;
+ case RT5651_AIF2:
+ snd_soc_update_bits(codec, RT5651_I2S2_SDP,
+ RT5651_I2S_MS_MASK | RT5651_I2S_BP_MASK |
+ RT5651_I2S_DF_MASK, reg_val);
+ break;
+ default:
+ dev_err(codec->dev, "Wrong dai->id: %d\n", dai->id);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int rt5651_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+ unsigned int reg_val = 0;
+
+ if (freq == rt5651->sysclk && clk_id == rt5651->sysclk_src)
+ return 0;
+
+ switch (clk_id) {
+ case RT5651_SCLK_S_MCLK:
+ reg_val |= RT5651_SCLK_SRC_MCLK;
+ break;
+ case RT5651_SCLK_S_PLL1:
+ reg_val |= RT5651_SCLK_SRC_PLL1;
+ break;
+ case RT5651_SCLK_S_RCCLK:
+ reg_val |= RT5651_SCLK_SRC_RCCLK;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, RT5651_GLB_CLK,
+ RT5651_SCLK_SRC_MASK, reg_val);
+ rt5651->sysclk = freq;
+ rt5651->sysclk_src = clk_id;
+
+ dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
+
+ return 0;
+}
+
+static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
+ unsigned int freq_in, unsigned int freq_out)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+ struct rl6231_pll_code pll_code;
+ int ret;
+
+ if (source == rt5651->pll_src && freq_in == rt5651->pll_in &&
+ freq_out == rt5651->pll_out)
+ return 0;
+
+ if (!freq_in || !freq_out) {
+ dev_dbg(codec->dev, "PLL disabled\n");
+
+ rt5651->pll_in = 0;
+ rt5651->pll_out = 0;
+ snd_soc_update_bits(codec, RT5651_GLB_CLK,
+ RT5651_SCLK_SRC_MASK, RT5651_SCLK_SRC_MCLK);
+ return 0;
+ }
+
+ switch (source) {
+ case RT5651_PLL1_S_MCLK:
+ snd_soc_update_bits(codec, RT5651_GLB_CLK,
+ RT5651_PLL1_SRC_MASK, RT5651_PLL1_SRC_MCLK);
+ break;
+ case RT5651_PLL1_S_BCLK1:
+ snd_soc_update_bits(codec, RT5651_GLB_CLK,
+ RT5651_PLL1_SRC_MASK, RT5651_PLL1_SRC_BCLK1);
+ break;
+ case RT5651_PLL1_S_BCLK2:
+ snd_soc_update_bits(codec, RT5651_GLB_CLK,
+ RT5651_PLL1_SRC_MASK, RT5651_PLL1_SRC_BCLK2);
+ break;
+ default:
+ dev_err(codec->dev, "Unknown PLL source %d\n", source);
+ return -EINVAL;
+ }
+
+ ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
+ if (ret < 0) {
+ dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
+ return ret;
+ }
+
+ dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n",
+ pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
+ pll_code.n_code, pll_code.k_code);
+
+ snd_soc_write(codec, RT5651_PLL_CTRL1,
+ pll_code.n_code << RT5651_PLL_N_SFT | pll_code.k_code);
+ snd_soc_write(codec, RT5651_PLL_CTRL2,
+ (pll_code.m_bp ? 0 : pll_code.m_code) << RT5651_PLL_M_SFT |
+ pll_code.m_bp << RT5651_PLL_M_BP_SFT);
+
+ rt5651->pll_in = freq_in;
+ rt5651->pll_out = freq_out;
+ rt5651->pll_src = source;
+
+ return 0;
+}
+
+static int rt5651_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_PREPARE:
+ if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) {
+ snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
+ RT5651_PWR_VREF1 | RT5651_PWR_MB |
+ RT5651_PWR_BG | RT5651_PWR_VREF2,
+ RT5651_PWR_VREF1 | RT5651_PWR_MB |
+ RT5651_PWR_BG | RT5651_PWR_VREF2);
+ usleep_range(10000, 15000);
+ snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
+ RT5651_PWR_FV1 | RT5651_PWR_FV2,
+ RT5651_PWR_FV1 | RT5651_PWR_FV2);
+ snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
+ RT5651_PWR_LDO_DVO_MASK,
+ RT5651_PWR_LDO_DVO_1_2V);
+ snd_soc_update_bits(codec, RT5651_D_MISC, 0x1, 0x1);
+ if (snd_soc_read(codec, RT5651_PLL_MODE_1) & 0x9200)
+ snd_soc_update_bits(codec, RT5651_D_MISC,
+ 0xc00, 0xc00);
+ }
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ snd_soc_write(codec, RT5651_D_MISC, 0x0010);
+ snd_soc_write(codec, RT5651_PWR_DIG1, 0x0000);
+ snd_soc_write(codec, RT5651_PWR_DIG2, 0x0000);
+ snd_soc_write(codec, RT5651_PWR_VOL, 0x0000);
+ snd_soc_write(codec, RT5651_PWR_MIXER, 0x0000);
+ snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
+ snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
+ break;
+
+ default:
+ break;
+ }
+ codec->dapm.bias_level = level;
+
+ return 0;
+}
+
+static int rt5651_probe(struct snd_soc_codec *codec)
+{
+ struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+ rt5651->codec = codec;
+
+ snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
+ RT5651_PWR_VREF1 | RT5651_PWR_MB |
+ RT5651_PWR_BG | RT5651_PWR_VREF2,
+ RT5651_PWR_VREF1 | RT5651_PWR_MB |
+ RT5651_PWR_BG | RT5651_PWR_VREF2);
+ usleep_range(10000, 15000);
+ snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
+ RT5651_PWR_FV1 | RT5651_PWR_FV2,
+ RT5651_PWR_FV1 | RT5651_PWR_FV2);
+
+ rt5651_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt5651_suspend(struct snd_soc_codec *codec)
+{
+ struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_cache_only(rt5651->regmap, true);
+ regcache_mark_dirty(rt5651->regmap);
+ return 0;
+}
+
+static int rt5651_resume(struct snd_soc_codec *codec)
+{
+ struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_cache_only(rt5651->regmap, false);
+ snd_soc_cache_sync(codec);
+
+ return 0;
+}
+#else
+#define rt5651_suspend NULL
+#define rt5651_resume NULL
+#endif
+
+#define RT5651_STEREO_RATES SNDRV_PCM_RATE_8000_96000
+#define RT5651_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
+
+static const struct snd_soc_dai_ops rt5651_aif_dai_ops = {
+ .hw_params = rt5651_hw_params,
+ .set_fmt = rt5651_set_dai_fmt,
+ .set_sysclk = rt5651_set_dai_sysclk,
+ .set_pll = rt5651_set_dai_pll,
+};
+
+static struct snd_soc_dai_driver rt5651_dai[] = {
+ {
+ .name = "rt5651-aif1",
+ .id = RT5651_AIF1,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5651_STEREO_RATES,
+ .formats = RT5651_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5651_STEREO_RATES,
+ .formats = RT5651_FORMATS,
+ },
+ .ops = &rt5651_aif_dai_ops,
+ },
+ {
+ .name = "rt5651-aif2",
+ .id = RT5651_AIF2,
+ .playback = {
+ .stream_name = "AIF2 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5651_STEREO_RATES,
+ .formats = RT5651_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5651_STEREO_RATES,
+ .formats = RT5651_FORMATS,
+ },
+ .ops = &rt5651_aif_dai_ops,
+ },
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt5651 = {
+ .probe = rt5651_probe,
+ .suspend = rt5651_suspend,
+ .resume = rt5651_resume,
+ .set_bias_level = rt5651_set_bias_level,
+ .idle_bias_off = true,
+ .controls = rt5651_snd_controls,
+ .num_controls = ARRAY_SIZE(rt5651_snd_controls),
+ .dapm_widgets = rt5651_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(rt5651_dapm_widgets),
+ .dapm_routes = rt5651_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(rt5651_dapm_routes),
+};
+
+static const struct regmap_config rt5651_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = RT5651_DEVICE_ID + 1 + (ARRAY_SIZE(rt5651_ranges) *
+ RT5651_PR_SPACING),
+ .volatile_reg = rt5651_volatile_register,
+ .readable_reg = rt5651_readable_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = rt5651_reg,
+ .num_reg_defaults = ARRAY_SIZE(rt5651_reg),
+ .ranges = rt5651_ranges,
+ .num_ranges = ARRAY_SIZE(rt5651_ranges),
+};
+
+static const struct i2c_device_id rt5651_i2c_id[] = {
+ { "rt5651", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, rt5651_i2c_id);
+
+static int rt5651_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct rt5651_platform_data *pdata = dev_get_platdata(&i2c->dev);
+ struct rt5651_priv *rt5651;
+ int ret;
+
+ rt5651 = devm_kzalloc(&i2c->dev, sizeof(*rt5651),
+ GFP_KERNEL);
+ if (NULL == rt5651)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, rt5651);
+
+ if (pdata)
+ rt5651->pdata = *pdata;
+
+ rt5651->regmap = devm_regmap_init_i2c(i2c, &rt5651_regmap);
+ if (IS_ERR(rt5651->regmap)) {
+ ret = PTR_ERR(rt5651->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ regmap_read(rt5651->regmap, RT5651_DEVICE_ID, &ret);
+ if (ret != RT5651_DEVICE_ID_VALUE) {
+ dev_err(&i2c->dev,
+ "Device with ID register %x is not rt5651\n", ret);
+ return -ENODEV;
+ }
+
+ regmap_write(rt5651->regmap, RT5651_RESET, 0);
+
+ ret = regmap_register_patch(rt5651->regmap, init_list,
+ ARRAY_SIZE(init_list));
+ if (ret != 0)
+ dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
+
+ if (rt5651->pdata.in2_diff)
+ regmap_update_bits(rt5651->regmap, RT5651_IN1_IN2,
+ RT5651_IN_DF2, RT5651_IN_DF2);
+
+ if (rt5651->pdata.dmic_en)
+ regmap_update_bits(rt5651->regmap, RT5651_GPIO_CTRL1,
+ RT5651_GP2_PIN_MASK, RT5651_GP2_PIN_DMIC1_SCL);
+
+ rt5651->hp_mute = 1;
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5651,
+ rt5651_dai, ARRAY_SIZE(rt5651_dai));
+
+ return ret;
+}
+
+static int rt5651_i2c_remove(struct i2c_client *i2c)
+{
+ snd_soc_unregister_codec(&i2c->dev);
+
+ return 0;
+}
+
+static struct i2c_driver rt5651_i2c_driver = {
+ .driver = {
+ .name = "rt5651",
+ .owner = THIS_MODULE,
+ },
+ .probe = rt5651_i2c_probe,
+ .remove = rt5651_i2c_remove,
+ .id_table = rt5651_i2c_id,
+};
+module_i2c_driver(rt5651_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC RT5651 driver");
+MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h
new file mode 100644
index 00000000000..1bd33cfa641
--- /dev/null
+++ b/sound/soc/codecs/rt5651.h
@@ -0,0 +1,2080 @@
+/*
+ * rt5651.h -- RT5651 ALSA SoC audio driver
+ *
+ * Copyright 2011 Realtek Microelectronics
+ * Author: Johnny Hsu <johnnyhsu@realtek.com>
+ *
+ * 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 __RT5651_H__
+#define __RT5651_H__
+
+#include <sound/rt5651.h>
+
+/* Info */
+#define RT5651_RESET 0x00
+#define RT5651_VERSION_ID 0xfd
+#define RT5651_VENDOR_ID 0xfe
+#define RT5651_DEVICE_ID 0xff
+/* I/O - Output */
+#define RT5651_HP_VOL 0x02
+#define RT5651_LOUT_CTRL1 0x03
+#define RT5651_LOUT_CTRL2 0x05
+/* I/O - Input */
+#define RT5651_IN1_IN2 0x0d
+#define RT5651_IN3 0x0e
+#define RT5651_INL1_INR1_VOL 0x0f
+#define RT5651_INL2_INR2_VOL 0x10
+/* I/O - ADC/DAC/DMIC */
+#define RT5651_DAC1_DIG_VOL 0x19
+#define RT5651_DAC2_DIG_VOL 0x1a
+#define RT5651_DAC2_CTRL 0x1b
+#define RT5651_ADC_DIG_VOL 0x1c
+#define RT5651_ADC_DATA 0x1d
+#define RT5651_ADC_BST_VOL 0x1e
+/* Mixer - D-D */
+#define RT5651_STO1_ADC_MIXER 0x27
+#define RT5651_STO2_ADC_MIXER 0x28
+#define RT5651_AD_DA_MIXER 0x29
+#define RT5651_STO_DAC_MIXER 0x2a
+#define RT5651_DD_MIXER 0x2b
+#define RT5651_DIG_INF_DATA 0x2f
+/* PDM */
+#define RT5651_PDM_CTL 0x30
+#define RT5651_PDM_I2C_CTL1 0x31
+#define RT5651_PDM_I2C_CTL2 0x32
+#define RT5651_PDM_I2C_DATA_W 0x33
+#define RT5651_PDM_I2C_DATA_R 0x34
+/* Mixer - ADC */
+#define RT5651_REC_L1_MIXER 0x3b
+#define RT5651_REC_L2_MIXER 0x3c
+#define RT5651_REC_R1_MIXER 0x3d
+#define RT5651_REC_R2_MIXER 0x3e
+/* Mixer - DAC */
+#define RT5651_HPO_MIXER 0x45
+#define RT5651_OUT_L1_MIXER 0x4d
+#define RT5651_OUT_L2_MIXER 0x4e
+#define RT5651_OUT_L3_MIXER 0x4f
+#define RT5651_OUT_R1_MIXER 0x50
+#define RT5651_OUT_R2_MIXER 0x51
+#define RT5651_OUT_R3_MIXER 0x52
+#define RT5651_LOUT_MIXER 0x53
+/* Power */
+#define RT5651_PWR_DIG1 0x61
+#define RT5651_PWR_DIG2 0x62
+#define RT5651_PWR_ANLG1 0x63
+#define RT5651_PWR_ANLG2 0x64
+#define RT5651_PWR_MIXER 0x65
+#define RT5651_PWR_VOL 0x66
+/* Private Register Control */
+#define RT5651_PRIV_INDEX 0x6a
+#define RT5651_PRIV_DATA 0x6c
+/* Format - ADC/DAC */
+#define RT5651_I2S1_SDP 0x70
+#define RT5651_I2S2_SDP 0x71
+#define RT5651_ADDA_CLK1 0x73
+#define RT5651_ADDA_CLK2 0x74
+#define RT5651_DMIC 0x75
+/* TDM Control */
+#define RT5651_TDM_CTL_1 0x77
+#define RT5651_TDM_CTL_2 0x78
+#define RT5651_TDM_CTL_3 0x79
+/* Function - Analog */
+#define RT5651_GLB_CLK 0x80
+#define RT5651_PLL_CTRL1 0x81
+#define RT5651_PLL_CTRL2 0x82
+#define RT5651_PLL_MODE_1 0x83
+#define RT5651_PLL_MODE_2 0x84
+#define RT5651_PLL_MODE_3 0x85
+#define RT5651_PLL_MODE_4 0x86
+#define RT5651_PLL_MODE_5 0x87
+#define RT5651_PLL_MODE_6 0x89
+#define RT5651_PLL_MODE_7 0x8a
+#define RT5651_DEPOP_M1 0x8e
+#define RT5651_DEPOP_M2 0x8f
+#define RT5651_DEPOP_M3 0x90
+#define RT5651_CHARGE_PUMP 0x91
+#define RT5651_MICBIAS 0x93
+#define RT5651_A_JD_CTL1 0x94
+/* Function - Digital */
+#define RT5651_EQ_CTRL1 0xb0
+#define RT5651_EQ_CTRL2 0xb1
+#define RT5651_ALC_1 0xb4
+#define RT5651_ALC_2 0xb5
+#define RT5651_ALC_3 0xb6
+#define RT5651_JD_CTRL1 0xbb
+#define RT5651_JD_CTRL2 0xbc
+#define RT5651_IRQ_CTRL1 0xbd
+#define RT5651_IRQ_CTRL2 0xbe
+#define RT5651_INT_IRQ_ST 0xbf
+#define RT5651_GPIO_CTRL1 0xc0
+#define RT5651_GPIO_CTRL2 0xc1
+#define RT5651_GPIO_CTRL3 0xc2
+#define RT5651_PGM_REG_ARR1 0xc8
+#define RT5651_PGM_REG_ARR2 0xc9
+#define RT5651_PGM_REG_ARR3 0xca
+#define RT5651_PGM_REG_ARR4 0xcb
+#define RT5651_PGM_REG_ARR5 0xcc
+#define RT5651_SCB_FUNC 0xcd
+#define RT5651_SCB_CTRL 0xce
+#define RT5651_BASE_BACK 0xcf
+#define RT5651_MP3_PLUS1 0xd0
+#define RT5651_MP3_PLUS2 0xd1
+#define RT5651_ADJ_HPF_CTRL1 0xd3
+#define RT5651_ADJ_HPF_CTRL2 0xd4
+#define RT5651_HP_CALIB_AMP_DET 0xd6
+#define RT5651_HP_CALIB2 0xd7
+#define RT5651_SV_ZCD1 0xd9
+#define RT5651_SV_ZCD2 0xda
+#define RT5651_D_MISC 0xfa
+/* Dummy Register */
+#define RT5651_DUMMY2 0xfb
+#define RT5651_DUMMY3 0xfc
+
+
+/* Index of Codec Private Register definition */
+#define RT5651_BIAS_CUR1 0x12
+#define RT5651_BIAS_CUR3 0x14
+#define RT5651_CLSD_INT_REG1 0x1c
+#define RT5651_CHPUMP_INT_REG1 0x24
+#define RT5651_MAMP_INT_REG2 0x37
+#define RT5651_CHOP_DAC_ADC 0x3d
+#define RT5651_3D_SPK 0x63
+#define RT5651_WND_1 0x6c
+#define RT5651_WND_2 0x6d
+#define RT5651_WND_3 0x6e
+#define RT5651_WND_4 0x6f
+#define RT5651_WND_5 0x70
+#define RT5651_WND_8 0x73
+#define RT5651_DIP_SPK_INF 0x75
+#define RT5651_HP_DCC_INT1 0x77
+#define RT5651_EQ_BW_LOP 0xa0
+#define RT5651_EQ_GN_LOP 0xa1
+#define RT5651_EQ_FC_BP1 0xa2
+#define RT5651_EQ_BW_BP1 0xa3
+#define RT5651_EQ_GN_BP1 0xa4
+#define RT5651_EQ_FC_BP2 0xa5
+#define RT5651_EQ_BW_BP2 0xa6
+#define RT5651_EQ_GN_BP2 0xa7
+#define RT5651_EQ_FC_BP3 0xa8
+#define RT5651_EQ_BW_BP3 0xa9
+#define RT5651_EQ_GN_BP3 0xaa
+#define RT5651_EQ_FC_BP4 0xab
+#define RT5651_EQ_BW_BP4 0xac
+#define RT5651_EQ_GN_BP4 0xad
+#define RT5651_EQ_FC_HIP1 0xae
+#define RT5651_EQ_GN_HIP1 0xaf
+#define RT5651_EQ_FC_HIP2 0xb0
+#define RT5651_EQ_BW_HIP2 0xb1
+#define RT5651_EQ_GN_HIP2 0xb2
+#define RT5651_EQ_PRE_VOL 0xb3
+#define RT5651_EQ_PST_VOL 0xb4
+
+
+/* global definition */
+#define RT5651_L_MUTE (0x1 << 15)
+#define RT5651_L_MUTE_SFT 15
+#define RT5651_VOL_L_MUTE (0x1 << 14)
+#define RT5651_VOL_L_SFT 14
+#define RT5651_R_MUTE (0x1 << 7)
+#define RT5651_R_MUTE_SFT 7
+#define RT5651_VOL_R_MUTE (0x1 << 6)
+#define RT5651_VOL_R_SFT 6
+#define RT5651_L_VOL_MASK (0x3f << 8)
+#define RT5651_L_VOL_SFT 8
+#define RT5651_R_VOL_MASK (0x3f)
+#define RT5651_R_VOL_SFT 0
+
+/* LOUT Control 2(0x05) */
+#define RT5651_EN_DFO (0x1 << 15)
+
+/* IN1 and IN2 Control (0x0d) */
+/* IN3 and IN4 Control (0x0e) */
+#define RT5651_BST_MASK1 (0xf<<12)
+#define RT5651_BST_SFT1 12
+#define RT5651_BST_MASK2 (0xf<<8)
+#define RT5651_BST_SFT2 8
+#define RT5651_IN_DF1 (0x1 << 7)
+#define RT5651_IN_SFT1 7
+#define RT5651_IN_DF2 (0x1 << 6)
+#define RT5651_IN_SFT2 6
+
+/* INL1 and INR1 Volume Control (0x0f) */
+/* INL2 and INR2 Volume Control (0x10) */
+#define RT5651_INL_SEL_MASK (0x1 << 15)
+#define RT5651_INL_SEL_SFT 15
+#define RT5651_INL_SEL_IN4P (0x0 << 15)
+#define RT5651_INL_SEL_MONOP (0x1 << 15)
+#define RT5651_INL_VOL_MASK (0x1f << 8)
+#define RT5651_INL_VOL_SFT 8
+#define RT5651_INR_SEL_MASK (0x1 << 7)
+#define RT5651_INR_SEL_SFT 7
+#define RT5651_INR_SEL_IN4N (0x0 << 7)
+#define RT5651_INR_SEL_MONON (0x1 << 7)
+#define RT5651_INR_VOL_MASK (0x1f)
+#define RT5651_INR_VOL_SFT 0
+
+/* DAC1 Digital Volume (0x19) */
+#define RT5651_DAC_L1_VOL_MASK (0xff << 8)
+#define RT5651_DAC_L1_VOL_SFT 8
+#define RT5651_DAC_R1_VOL_MASK (0xff)
+#define RT5651_DAC_R1_VOL_SFT 0
+
+/* DAC2 Digital Volume (0x1a) */
+#define RT5651_DAC_L2_VOL_MASK (0xff << 8)
+#define RT5651_DAC_L2_VOL_SFT 8
+#define RT5651_DAC_R2_VOL_MASK (0xff)
+#define RT5651_DAC_R2_VOL_SFT 0
+
+/* DAC2 Control (0x1b) */
+#define RT5651_M_DAC_L2_VOL (0x1 << 13)
+#define RT5651_M_DAC_L2_VOL_SFT 13
+#define RT5651_M_DAC_R2_VOL (0x1 << 12)
+#define RT5651_M_DAC_R2_VOL_SFT 12
+#define RT5651_SEL_DAC_L2 (0x1 << 11)
+#define RT5651_IF2_DAC_L2 (0x1 << 11)
+#define RT5651_IF1_DAC_L2 (0x0 << 11)
+#define RT5651_SEL_DAC_L2_SFT 11
+#define RT5651_SEL_DAC_R2 (0x1 << 10)
+#define RT5651_IF2_DAC_R2 (0x1 << 11)
+#define RT5651_IF1_DAC_R2 (0x0 << 11)
+#define RT5651_SEL_DAC_R2_SFT 10
+
+/* ADC Digital Volume Control (0x1c) */
+#define RT5651_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5651_ADC_L_VOL_SFT 8
+#define RT5651_ADC_R_VOL_MASK (0x7f)
+#define RT5651_ADC_R_VOL_SFT 0
+
+/* Mono ADC Digital Volume Control (0x1d) */
+#define RT5651_M_MONO_ADC_L (0x1 << 15)
+#define RT5651_M_MONO_ADC_L_SFT 15
+#define RT5651_MONO_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5651_MONO_ADC_L_VOL_SFT 8
+#define RT5651_M_MONO_ADC_R (0x1 << 7)
+#define RT5651_M_MONO_ADC_R_SFT 7
+#define RT5651_MONO_ADC_R_VOL_MASK (0x7f)
+#define RT5651_MONO_ADC_R_VOL_SFT 0
+
+/* ADC Boost Volume Control (0x1e) */
+#define RT5651_ADC_L_BST_MASK (0x3 << 14)
+#define RT5651_ADC_L_BST_SFT 14
+#define RT5651_ADC_R_BST_MASK (0x3 << 12)
+#define RT5651_ADC_R_BST_SFT 12
+#define RT5651_ADC_COMP_MASK (0x3 << 10)
+#define RT5651_ADC_COMP_SFT 10
+
+/* Stereo ADC1 Mixer Control (0x27) */
+#define RT5651_M_STO1_ADC_L1 (0x1 << 14)
+#define RT5651_M_STO1_ADC_L1_SFT 14
+#define RT5651_M_STO1_ADC_L2 (0x1 << 13)
+#define RT5651_M_STO1_ADC_L2_SFT 13
+#define RT5651_STO1_ADC_1_SRC_MASK (0x1 << 12)
+#define RT5651_STO1_ADC_1_SRC_SFT 12
+#define RT5651_STO1_ADC_1_SRC_ADC (0x1 << 12)
+#define RT5651_STO1_ADC_1_SRC_DACMIX (0x0 << 12)
+#define RT5651_STO1_ADC_2_SRC_MASK (0x1 << 11)
+#define RT5651_STO1_ADC_2_SRC_SFT 11
+#define RT5651_STO1_ADC_2_SRC_DMIC (0x0 << 11)
+#define RT5651_STO1_ADC_2_SRC_DACMIXR (0x1 << 11)
+#define RT5651_M_STO1_ADC_R1 (0x1 << 6)
+#define RT5651_M_STO1_ADC_R1_SFT 6
+#define RT5651_M_STO1_ADC_R2 (0x1 << 5)
+#define RT5651_M_STO1_ADC_R2_SFT 5
+
+/* Stereo ADC2 Mixer Control (0x28) */
+#define RT5651_M_STO2_ADC_L1 (0x1 << 14)
+#define RT5651_M_STO2_ADC_L1_SFT 14
+#define RT5651_M_STO2_ADC_L2 (0x1 << 13)
+#define RT5651_M_STO2_ADC_L2_SFT 13
+#define RT5651_STO2_ADC_L1_SRC_MASK (0x1 << 12)
+#define RT5651_STO2_ADC_L1_SRC_SFT 12
+#define RT5651_STO2_ADC_L1_SRC_DACMIXL (0x0 << 12)
+#define RT5651_STO2_ADC_L1_SRC_ADCL (0x1 << 12)
+#define RT5651_STO2_ADC_L2_SRC_MASK (0x1 << 11)
+#define RT5651_STO2_ADC_L2_SRC_SFT 11
+#define RT5651_STO2_ADC_L2_SRC_DMIC (0x0 << 11)
+#define RT5651_STO2_ADC_L2_SRC_DACMIXR (0x1 << 11)
+#define RT5651_M_STO2_ADC_R1 (0x1 << 6)
+#define RT5651_M_STO2_ADC_R1_SFT 6
+#define RT5651_M_STO2_ADC_R2 (0x1 << 5)
+#define RT5651_M_STO2_ADC_R2_SFT 5
+#define RT5651_STO2_ADC_R1_SRC_MASK (0x1 << 4)
+#define RT5651_STO2_ADC_R1_SRC_SFT 4
+#define RT5651_STO2_ADC_R1_SRC_ADCR (0x1 << 4)
+#define RT5651_STO2_ADC_R1_SRC_DACMIXR (0x0 << 4)
+#define RT5651_STO2_ADC_R2_SRC_MASK (0x1 << 3)
+#define RT5651_STO2_ADC_R2_SRC_SFT 3
+#define RT5651_STO2_ADC_R2_SRC_DMIC (0x0 << 3)
+#define RT5651_STO2_ADC_R2_SRC_DACMIXR (0x1 << 3)
+
+/* ADC Mixer to DAC Mixer Control (0x29) */
+#define RT5651_M_ADCMIX_L (0x1 << 15)
+#define RT5651_M_ADCMIX_L_SFT 15
+#define RT5651_M_IF1_DAC_L (0x1 << 14)
+#define RT5651_M_IF1_DAC_L_SFT 14
+#define RT5651_M_ADCMIX_R (0x1 << 7)
+#define RT5651_M_ADCMIX_R_SFT 7
+#define RT5651_M_IF1_DAC_R (0x1 << 6)
+#define RT5651_M_IF1_DAC_R_SFT 6
+
+/* Stereo DAC Mixer Control (0x2a) */
+#define RT5651_M_DAC_L1_MIXL (0x1 << 14)
+#define RT5651_M_DAC_L1_MIXL_SFT 14
+#define RT5651_DAC_L1_STO_L_VOL_MASK (0x1 << 13)
+#define RT5651_DAC_L1_STO_L_VOL_SFT 13
+#define RT5651_M_DAC_L2_MIXL (0x1 << 12)
+#define RT5651_M_DAC_L2_MIXL_SFT 12
+#define RT5651_DAC_L2_STO_L_VOL_MASK (0x1 << 11)
+#define RT5651_DAC_L2_STO_L_VOL_SFT 11
+#define RT5651_M_DAC_R1_MIXL (0x1 << 9)
+#define RT5651_M_DAC_R1_MIXL_SFT 9
+#define RT5651_DAC_R1_STO_L_VOL_MASK (0x1 << 8)
+#define RT5651_DAC_R1_STO_L_VOL_SFT 8
+#define RT5651_M_DAC_R1_MIXR (0x1 << 6)
+#define RT5651_M_DAC_R1_MIXR_SFT 6
+#define RT5651_DAC_R1_STO_R_VOL_MASK (0x1 << 5)
+#define RT5651_DAC_R1_STO_R_VOL_SFT 5
+#define RT5651_M_DAC_R2_MIXR (0x1 << 4)
+#define RT5651_M_DAC_R2_MIXR_SFT 4
+#define RT5651_DAC_R2_STO_R_VOL_MASK (0x1 << 3)
+#define RT5651_DAC_R2_STO_R_VOL_SFT 3
+#define RT5651_M_DAC_L1_MIXR (0x1 << 1)
+#define RT5651_M_DAC_L1_MIXR_SFT 1
+#define RT5651_DAC_L1_STO_R_VOL_MASK (0x1)
+#define RT5651_DAC_L1_STO_R_VOL_SFT 0
+
+/* DD Mixer Control (0x2b) */
+#define RT5651_M_STO_DD_L1 (0x1 << 14)
+#define RT5651_M_STO_DD_L1_SFT 14
+#define RT5651_STO_DD_L1_VOL_MASK (0x1 << 13)
+#define RT5651_DAC_DD_L1_VOL_SFT 13
+#define RT5651_M_STO_DD_L2 (0x1 << 12)
+#define RT5651_M_STO_DD_L2_SFT 12
+#define RT5651_STO_DD_L2_VOL_MASK (0x1 << 11)
+#define RT5651_STO_DD_L2_VOL_SFT 11
+#define RT5651_M_STO_DD_R2_L (0x1 << 10)
+#define RT5651_M_STO_DD_R2_L_SFT 10
+#define RT5651_STO_DD_R2_L_VOL_MASK (0x1 << 9)
+#define RT5651_STO_DD_R2_L_VOL_SFT 9
+#define RT5651_M_STO_DD_R1 (0x1 << 6)
+#define RT5651_M_STO_DD_R1_SFT 6
+#define RT5651_STO_DD_R1_VOL_MASK (0x1 << 5)
+#define RT5651_STO_DD_R1_VOL_SFT 5
+#define RT5651_M_STO_DD_R2 (0x1 << 4)
+#define RT5651_M_STO_DD_R2_SFT 4
+#define RT5651_STO_DD_R2_VOL_MASK (0x1 << 3)
+#define RT5651_STO_DD_R2_VOL_SFT 3
+#define RT5651_M_STO_DD_L2_R (0x1 << 2)
+#define RT5651_M_STO_DD_L2_R_SFT 2
+#define RT5651_STO_DD_L2_R_VOL_MASK (0x1 << 1)
+#define RT5651_STO_DD_L2_R_VOL_SFT 1
+
+/* Digital Mixer Control (0x2c) */
+#define RT5651_M_STO_L_DAC_L (0x1 << 15)
+#define RT5651_M_STO_L_DAC_L_SFT 15
+#define RT5651_STO_L_DAC_L_VOL_MASK (0x1 << 14)
+#define RT5651_STO_L_DAC_L_VOL_SFT 14
+#define RT5651_M_DAC_L2_DAC_L (0x1 << 13)
+#define RT5651_M_DAC_L2_DAC_L_SFT 13
+#define RT5651_DAC_L2_DAC_L_VOL_MASK (0x1 << 12)
+#define RT5651_DAC_L2_DAC_L_VOL_SFT 12
+#define RT5651_M_STO_R_DAC_R (0x1 << 11)
+#define RT5651_M_STO_R_DAC_R_SFT 11
+#define RT5651_STO_R_DAC_R_VOL_MASK (0x1 << 10)
+#define RT5651_STO_R_DAC_R_VOL_SFT 10
+#define RT5651_M_DAC_R2_DAC_R (0x1 << 9)
+#define RT5651_M_DAC_R2_DAC_R_SFT 9
+#define RT5651_DAC_R2_DAC_R_VOL_MASK (0x1 << 8)
+#define RT5651_DAC_R2_DAC_R_VOL_SFT 8
+
+/* DSP Path Control 1 (0x2d) */
+#define RT5651_RXDP_SRC_MASK (0x1 << 15)
+#define RT5651_RXDP_SRC_SFT 15
+#define RT5651_RXDP_SRC_NOR (0x0 << 15)
+#define RT5651_RXDP_SRC_DIV3 (0x1 << 15)
+#define RT5651_TXDP_SRC_MASK (0x1 << 14)
+#define RT5651_TXDP_SRC_SFT 14
+#define RT5651_TXDP_SRC_NOR (0x0 << 14)
+#define RT5651_TXDP_SRC_DIV3 (0x1 << 14)
+
+/* DSP Path Control 2 (0x2e) */
+#define RT5651_DAC_L2_SEL_MASK (0x3 << 14)
+#define RT5651_DAC_L2_SEL_SFT 14
+#define RT5651_DAC_L2_SEL_IF2 (0x0 << 14)
+#define RT5651_DAC_L2_SEL_IF3 (0x1 << 14)
+#define RT5651_DAC_L2_SEL_TXDC (0x2 << 14)
+#define RT5651_DAC_L2_SEL_BASS (0x3 << 14)
+#define RT5651_DAC_R2_SEL_MASK (0x3 << 12)
+#define RT5651_DAC_R2_SEL_SFT 12
+#define RT5651_DAC_R2_SEL_IF2 (0x0 << 12)
+#define RT5651_DAC_R2_SEL_IF3 (0x1 << 12)
+#define RT5651_DAC_R2_SEL_TXDC (0x2 << 12)
+#define RT5651_IF2_ADC_L_SEL_MASK (0x1 << 11)
+#define RT5651_IF2_ADC_L_SEL_SFT 11
+#define RT5651_IF2_ADC_L_SEL_TXDP (0x0 << 11)
+#define RT5651_IF2_ADC_L_SEL_PASS (0x1 << 11)
+#define RT5651_IF2_ADC_R_SEL_MASK (0x1 << 10)
+#define RT5651_IF2_ADC_R_SEL_SFT 10
+#define RT5651_IF2_ADC_R_SEL_TXDP (0x0 << 10)
+#define RT5651_IF2_ADC_R_SEL_PASS (0x1 << 10)
+#define RT5651_RXDC_SEL_MASK (0x3 << 8)
+#define RT5651_RXDC_SEL_SFT 8
+#define RT5651_RXDC_SEL_NOR (0x0 << 8)
+#define RT5651_RXDC_SEL_L2R (0x1 << 8)
+#define RT5651_RXDC_SEL_R2L (0x2 << 8)
+#define RT5651_RXDC_SEL_SWAP (0x3 << 8)
+#define RT5651_RXDP_SEL_MASK (0x3 << 6)
+#define RT5651_RXDP_SEL_SFT 6
+#define RT5651_RXDP_SEL_NOR (0x0 << 6)
+#define RT5651_RXDP_SEL_L2R (0x1 << 6)
+#define RT5651_RXDP_SEL_R2L (0x2 << 6)
+#define RT5651_RXDP_SEL_SWAP (0x3 << 6)
+#define RT5651_TXDC_SEL_MASK (0x3 << 4)
+#define RT5651_TXDC_SEL_SFT 4
+#define RT5651_TXDC_SEL_NOR (0x0 << 4)
+#define RT5651_TXDC_SEL_L2R (0x1 << 4)
+#define RT5651_TXDC_SEL_R2L (0x2 << 4)
+#define RT5651_TXDC_SEL_SWAP (0x3 << 4)
+#define RT5651_TXDP_SEL_MASK (0x3 << 2)
+#define RT5651_TXDP_SEL_SFT 2
+#define RT5651_TXDP_SEL_NOR (0x0 << 2)
+#define RT5651_TXDP_SEL_L2R (0x1 << 2)
+#define RT5651_TXDP_SEL_R2L (0x2 << 2)
+#define RT5651_TRXDP_SEL_SWAP (0x3 << 2)
+
+/* Digital Interface Data Control (0x2f) */
+#define RT5651_IF2_DAC_SEL_MASK (0x3 << 10)
+#define RT5651_IF2_DAC_SEL_SFT 10
+#define RT5651_IF2_DAC_SEL_NOR (0x0 << 10)
+#define RT5651_IF2_DAC_SEL_SWAP (0x1 << 10)
+#define RT5651_IF2_DAC_SEL_L2R (0x2 << 10)
+#define RT5651_IF2_DAC_SEL_R2L (0x3 << 10)
+#define RT5651_IF2_ADC_SEL_MASK (0x3 << 8)
+#define RT5651_IF2_ADC_SEL_SFT 8
+#define RT5651_IF2_ADC_SEL_NOR (0x0 << 8)
+#define RT5651_IF2_ADC_SEL_SWAP (0x1 << 8)
+#define RT5651_IF2_ADC_SEL_L2R (0x2 << 8)
+#define RT5651_IF2_ADC_SEL_R2L (0x3 << 8)
+#define RT5651_IF2_ADC_SRC_MASK (0x1 << 7)
+#define RT5651_IF2_ADC_SRC_SFT 7
+#define RT5651_IF1_ADC1 (0x0 << 7)
+#define RT5651_IF1_ADC2 (0x1 << 7)
+
+/* PDM Output Control (0x30) */
+#define RT5651_PDM_L_SEL_MASK (0x1 << 15)
+#define RT5651_PDM_L_SEL_SFT 15
+#define RT5651_PDM_L_SEL_DD_L (0x0 << 15)
+#define RT5651_PDM_L_SEL_STO_L (0x1 << 15)
+#define RT5651_M_PDM_L (0x1 << 14)
+#define RT5651_M_PDM_L_SFT 14
+#define RT5651_PDM_R_SEL_MASK (0x1 << 13)
+#define RT5651_PDM_R_SEL_SFT 13
+#define RT5651_PDM_R_SEL_DD_L (0x0 << 13)
+#define RT5651_PDM_R_SEL_STO_L (0x1 << 13)
+#define RT5651_M_PDM_R (0x1 << 12)
+#define RT5651_M_PDM_R_SFT 12
+#define RT5651_PDM_BUSY (0x1 << 6)
+#define RT5651_PDM_BUSY_SFT 6
+#define RT5651_PDM_PATTERN_SEL_MASK (0x1 << 5)
+#define RT5651_PDM_PATTERN_SEL_64 (0x0 << 5)
+#define RT5651_PDM_PATTERN_SEL_128 (0x1 << 5)
+#define RT5651_PDM_VOL_MASK (0x1 << 4)
+#define RT5651_PDM_VOL_SFT 4
+#define RT5651_PDM_DIV_MASK (0x3)
+#define RT5651_PDM_DIV_SFT 0
+#define RT5651_PDM_DIV_1 0
+#define RT5651_PDM_DIV_2 1
+#define RT5651_PDM_DIV_3 2
+#define RT5651_PDM_DIV_4 3
+
+/* PDM I2C/Data Control 1 (0x31) */
+#define RT5651_PDM_I2C_ID_MASK (0xf << 12)
+#define PT5631_PDM_CMD_EXE (0x1 << 11)
+#define RT5651_PDM_I2C_CMD_MASK (0x1 << 10)
+#define RT5651_PDM_I2C_CMD_R (0x0 << 10)
+#define RT5651_PDM_I2C_CMD_W (0x1 << 10)
+#define RT5651_PDM_I2C_CMD_EXE (0x1 << 9)
+#define RT5651_PDM_I2C_NORMAL (0x0 << 8)
+#define RT5651_PDM_I2C_BUSY (0x1 << 8)
+
+/* PDM I2C/Data Control 2 (0x32) */
+#define RT5651_PDM_I2C_ADDR (0xff << 8)
+#define RT5651_PDM_I2C_CMD_PATTERN (0xff)
+
+
+/* REC Left Mixer Control 1 (0x3b) */
+#define RT5651_G_LN_L2_RM_L_MASK (0x7 << 13)
+#define RT5651_G_IN_L2_RM_L_SFT 13
+#define RT5651_G_LN_L1_RM_L_MASK (0x7 << 10)
+#define RT5651_G_IN_L1_RM_L_SFT 10
+#define RT5651_G_BST3_RM_L_MASK (0x7 << 4)
+#define RT5651_G_BST3_RM_L_SFT 4
+#define RT5651_G_BST2_RM_L_MASK (0x7 << 1)
+#define RT5651_G_BST2_RM_L_SFT 1
+
+/* REC Left Mixer Control 2 (0x3c) */
+#define RT5651_G_BST1_RM_L_MASK (0x7 << 13)
+#define RT5651_G_BST1_RM_L_SFT 13
+#define RT5651_G_OM_L_RM_L_MASK (0x7 << 10)
+#define RT5651_G_OM_L_RM_L_SFT 10
+#define RT5651_M_IN2_L_RM_L (0x1 << 6)
+#define RT5651_M_IN2_L_RM_L_SFT 6
+#define RT5651_M_IN1_L_RM_L (0x1 << 5)
+#define RT5651_M_IN1_L_RM_L_SFT 5
+#define RT5651_M_BST3_RM_L (0x1 << 3)
+#define RT5651_M_BST3_RM_L_SFT 3
+#define RT5651_M_BST2_RM_L (0x1 << 2)
+#define RT5651_M_BST2_RM_L_SFT 2
+#define RT5651_M_BST1_RM_L (0x1 << 1)
+#define RT5651_M_BST1_RM_L_SFT 1
+#define RT5651_M_OM_L_RM_L (0x1)
+#define RT5651_M_OM_L_RM_L_SFT 0
+
+/* REC Right Mixer Control 1 (0x3d) */
+#define RT5651_G_IN2_R_RM_R_MASK (0x7 << 13)
+#define RT5651_G_IN2_R_RM_R_SFT 13
+#define RT5651_G_IN1_R_RM_R_MASK (0x7 << 10)
+#define RT5651_G_IN1_R_RM_R_SFT 10
+#define RT5651_G_BST3_RM_R_MASK (0x7 << 4)
+#define RT5651_G_BST3_RM_R_SFT 4
+#define RT5651_G_BST2_RM_R_MASK (0x7 << 1)
+#define RT5651_G_BST2_RM_R_SFT 1
+
+/* REC Right Mixer Control 2 (0x3e) */
+#define RT5651_G_BST1_RM_R_MASK (0x7 << 13)
+#define RT5651_G_BST1_RM_R_SFT 13
+#define RT5651_G_OM_R_RM_R_MASK (0x7 << 10)
+#define RT5651_G_OM_R_RM_R_SFT 10
+#define RT5651_M_IN2_R_RM_R (0x1 << 6)
+#define RT5651_M_IN2_R_RM_R_SFT 6
+#define RT5651_M_IN1_R_RM_R (0x1 << 5)
+#define RT5651_M_IN1_R_RM_R_SFT 5
+#define RT5651_M_BST3_RM_R (0x1 << 3)
+#define RT5651_M_BST3_RM_R_SFT 3
+#define RT5651_M_BST2_RM_R (0x1 << 2)
+#define RT5651_M_BST2_RM_R_SFT 2
+#define RT5651_M_BST1_RM_R (0x1 << 1)
+#define RT5651_M_BST1_RM_R_SFT 1
+#define RT5651_M_OM_R_RM_R (0x1)
+#define RT5651_M_OM_R_RM_R_SFT 0
+
+/* HPMIX Control (0x45) */
+#define RT5651_M_DAC1_HM (0x1 << 14)
+#define RT5651_M_DAC1_HM_SFT 14
+#define RT5651_M_HPVOL_HM (0x1 << 13)
+#define RT5651_M_HPVOL_HM_SFT 13
+#define RT5651_G_HPOMIX_MASK (0x1 << 12)
+#define RT5651_G_HPOMIX_SFT 12
+
+/* SPK Left Mixer Control (0x46) */
+#define RT5651_G_RM_L_SM_L_MASK (0x3 << 14)
+#define RT5651_G_RM_L_SM_L_SFT 14
+#define RT5651_G_IN_L_SM_L_MASK (0x3 << 12)
+#define RT5651_G_IN_L_SM_L_SFT 12
+#define RT5651_G_DAC_L1_SM_L_MASK (0x3 << 10)
+#define RT5651_G_DAC_L1_SM_L_SFT 10
+#define RT5651_G_DAC_L2_SM_L_MASK (0x3 << 8)
+#define RT5651_G_DAC_L2_SM_L_SFT 8
+#define RT5651_G_OM_L_SM_L_MASK (0x3 << 6)
+#define RT5651_G_OM_L_SM_L_SFT 6
+#define RT5651_M_RM_L_SM_L (0x1 << 5)
+#define RT5651_M_RM_L_SM_L_SFT 5
+#define RT5651_M_IN_L_SM_L (0x1 << 4)
+#define RT5651_M_IN_L_SM_L_SFT 4
+#define RT5651_M_DAC_L1_SM_L (0x1 << 3)
+#define RT5651_M_DAC_L1_SM_L_SFT 3
+#define RT5651_M_DAC_L2_SM_L (0x1 << 2)
+#define RT5651_M_DAC_L2_SM_L_SFT 2
+#define RT5651_M_OM_L_SM_L (0x1 << 1)
+#define RT5651_M_OM_L_SM_L_SFT 1
+
+/* SPK Right Mixer Control (0x47) */
+#define RT5651_G_RM_R_SM_R_MASK (0x3 << 14)
+#define RT5651_G_RM_R_SM_R_SFT 14
+#define RT5651_G_IN_R_SM_R_MASK (0x3 << 12)
+#define RT5651_G_IN_R_SM_R_SFT 12
+#define RT5651_G_DAC_R1_SM_R_MASK (0x3 << 10)
+#define RT5651_G_DAC_R1_SM_R_SFT 10
+#define RT5651_G_DAC_R2_SM_R_MASK (0x3 << 8)
+#define RT5651_G_DAC_R2_SM_R_SFT 8
+#define RT5651_G_OM_R_SM_R_MASK (0x3 << 6)
+#define RT5651_G_OM_R_SM_R_SFT 6
+#define RT5651_M_RM_R_SM_R (0x1 << 5)
+#define RT5651_M_RM_R_SM_R_SFT 5
+#define RT5651_M_IN_R_SM_R (0x1 << 4)
+#define RT5651_M_IN_R_SM_R_SFT 4
+#define RT5651_M_DAC_R1_SM_R (0x1 << 3)
+#define RT5651_M_DAC_R1_SM_R_SFT 3
+#define RT5651_M_DAC_R2_SM_R (0x1 << 2)
+#define RT5651_M_DAC_R2_SM_R_SFT 2
+#define RT5651_M_OM_R_SM_R (0x1 << 1)
+#define RT5651_M_OM_R_SM_R_SFT 1
+
+/* SPOLMIX Control (0x48) */
+#define RT5651_M_DAC_R1_SPM_L (0x1 << 15)
+#define RT5651_M_DAC_R1_SPM_L_SFT 15
+#define RT5651_M_DAC_L1_SPM_L (0x1 << 14)
+#define RT5651_M_DAC_L1_SPM_L_SFT 14
+#define RT5651_M_SV_R_SPM_L (0x1 << 13)
+#define RT5651_M_SV_R_SPM_L_SFT 13
+#define RT5651_M_SV_L_SPM_L (0x1 << 12)
+#define RT5651_M_SV_L_SPM_L_SFT 12
+#define RT5651_M_BST1_SPM_L (0x1 << 11)
+#define RT5651_M_BST1_SPM_L_SFT 11
+
+/* SPORMIX Control (0x49) */
+#define RT5651_M_DAC_R1_SPM_R (0x1 << 13)
+#define RT5651_M_DAC_R1_SPM_R_SFT 13
+#define RT5651_M_SV_R_SPM_R (0x1 << 12)
+#define RT5651_M_SV_R_SPM_R_SFT 12
+#define RT5651_M_BST1_SPM_R (0x1 << 11)
+#define RT5651_M_BST1_SPM_R_SFT 11
+
+/* SPOLMIX / SPORMIX Ratio Control (0x4a) */
+#define RT5651_SPO_CLSD_RATIO_MASK (0x7)
+#define RT5651_SPO_CLSD_RATIO_SFT 0
+
+/* Mono Output Mixer Control (0x4c) */
+#define RT5651_M_DAC_R2_MM (0x1 << 15)
+#define RT5651_M_DAC_R2_MM_SFT 15
+#define RT5651_M_DAC_L2_MM (0x1 << 14)
+#define RT5651_M_DAC_L2_MM_SFT 14
+#define RT5651_M_OV_R_MM (0x1 << 13)
+#define RT5651_M_OV_R_MM_SFT 13
+#define RT5651_M_OV_L_MM (0x1 << 12)
+#define RT5651_M_OV_L_MM_SFT 12
+#define RT5651_M_BST1_MM (0x1 << 11)
+#define RT5651_M_BST1_MM_SFT 11
+#define RT5651_G_MONOMIX_MASK (0x1 << 10)
+#define RT5651_G_MONOMIX_SFT 10
+
+/* Output Left Mixer Control 1 (0x4d) */
+#define RT5651_G_BST2_OM_L_MASK (0x7 << 10)
+#define RT5651_G_BST2_OM_L_SFT 10
+#define RT5651_G_BST1_OM_L_MASK (0x7 << 7)
+#define RT5651_G_BST1_OM_L_SFT 7
+#define RT5651_G_IN1_L_OM_L_MASK (0x7 << 4)
+#define RT5651_G_IN1_L_OM_L_SFT 4
+#define RT5651_G_RM_L_OM_L_MASK (0x7 << 1)
+#define RT5651_G_RM_L_OM_L_SFT 1
+
+/* Output Left Mixer Control 2 (0x4e) */
+#define RT5651_G_DAC_L1_OM_L_MASK (0x7 << 7)
+#define RT5651_G_DAC_L1_OM_L_SFT 7
+#define RT5651_G_IN2_L_OM_L_MASK (0x7 << 4)
+#define RT5651_G_IN2_L_OM_L_SFT 4
+
+/* Output Left Mixer Control 3 (0x4f) */
+#define RT5651_M_IN2_L_OM_L (0x1 << 9)
+#define RT5651_M_IN2_L_OM_L_SFT 9
+#define RT5651_M_BST2_OM_L (0x1 << 6)
+#define RT5651_M_BST2_OM_L_SFT 6
+#define RT5651_M_BST1_OM_L (0x1 << 5)
+#define RT5651_M_BST1_OM_L_SFT 5
+#define RT5651_M_IN1_L_OM_L (0x1 << 4)
+#define RT5651_M_IN1_L_OM_L_SFT 4
+#define RT5651_M_RM_L_OM_L (0x1 << 3)
+#define RT5651_M_RM_L_OM_L_SFT 3
+#define RT5651_M_DAC_L1_OM_L (0x1)
+#define RT5651_M_DAC_L1_OM_L_SFT 0
+
+/* Output Right Mixer Control 1 (0x50) */
+#define RT5651_G_BST2_OM_R_MASK (0x7 << 10)
+#define RT5651_G_BST2_OM_R_SFT 10
+#define RT5651_G_BST1_OM_R_MASK (0x7 << 7)
+#define RT5651_G_BST1_OM_R_SFT 7
+#define RT5651_G_IN1_R_OM_R_MASK (0x7 << 4)
+#define RT5651_G_IN1_R_OM_R_SFT 4
+#define RT5651_G_RM_R_OM_R_MASK (0x7 << 1)
+#define RT5651_G_RM_R_OM_R_SFT 1
+
+/* Output Right Mixer Control 2 (0x51) */
+#define RT5651_G_DAC_R1_OM_R_MASK (0x7 << 7)
+#define RT5651_G_DAC_R1_OM_R_SFT 7
+#define RT5651_G_IN2_R_OM_R_MASK (0x7 << 4)
+#define RT5651_G_IN2_R_OM_R_SFT 4
+
+/* Output Right Mixer Control 3 (0x52) */
+#define RT5651_M_IN2_R_OM_R (0x1 << 9)
+#define RT5651_M_IN2_R_OM_R_SFT 9
+#define RT5651_M_BST2_OM_R (0x1 << 6)
+#define RT5651_M_BST2_OM_R_SFT 6
+#define RT5651_M_BST1_OM_R (0x1 << 5)
+#define RT5651_M_BST1_OM_R_SFT 5
+#define RT5651_M_IN1_R_OM_R (0x1 << 4)
+#define RT5651_M_IN1_R_OM_R_SFT 4
+#define RT5651_M_RM_R_OM_R (0x1 << 3)
+#define RT5651_M_RM_R_OM_R_SFT 3
+#define RT5651_M_DAC_R1_OM_R (0x1)
+#define RT5651_M_DAC_R1_OM_R_SFT 0
+
+/* LOUT Mixer Control (0x53) */
+#define RT5651_M_DAC_L1_LM (0x1 << 15)
+#define RT5651_M_DAC_L1_LM_SFT 15
+#define RT5651_M_DAC_R1_LM (0x1 << 14)
+#define RT5651_M_DAC_R1_LM_SFT 14
+#define RT5651_M_OV_L_LM (0x1 << 13)
+#define RT5651_M_OV_L_LM_SFT 13
+#define RT5651_M_OV_R_LM (0x1 << 12)
+#define RT5651_M_OV_R_LM_SFT 12
+#define RT5651_G_LOUTMIX_MASK (0x1 << 11)
+#define RT5651_G_LOUTMIX_SFT 11
+
+/* Power Management for Digital 1 (0x61) */
+#define RT5651_PWR_I2S1 (0x1 << 15)
+#define RT5651_PWR_I2S1_BIT 15
+#define RT5651_PWR_I2S2 (0x1 << 14)
+#define RT5651_PWR_I2S2_BIT 14
+#define RT5651_PWR_DAC_L1 (0x1 << 12)
+#define RT5651_PWR_DAC_L1_BIT 12
+#define RT5651_PWR_DAC_R1 (0x1 << 11)
+#define RT5651_PWR_DAC_R1_BIT 11
+#define RT5651_PWR_ADC_L (0x1 << 2)
+#define RT5651_PWR_ADC_L_BIT 2
+#define RT5651_PWR_ADC_R (0x1 << 1)
+#define RT5651_PWR_ADC_R_BIT 1
+
+/* Power Management for Digital 2 (0x62) */
+#define RT5651_PWR_ADC_STO1_F (0x1 << 15)
+#define RT5651_PWR_ADC_STO1_F_BIT 15
+#define RT5651_PWR_ADC_STO2_F (0x1 << 14)
+#define RT5651_PWR_ADC_STO2_F_BIT 14
+#define RT5651_PWR_DAC_STO1_F (0x1 << 11)
+#define RT5651_PWR_DAC_STO1_F_BIT 11
+#define RT5651_PWR_DAC_STO2_F (0x1 << 10)
+#define RT5651_PWR_DAC_STO2_F_BIT 10
+#define RT5651_PWR_PDM (0x1 << 9)
+#define RT5651_PWR_PDM_BIT 9
+
+/* Power Management for Analog 1 (0x63) */
+#define RT5651_PWR_VREF1 (0x1 << 15)
+#define RT5651_PWR_VREF1_BIT 15
+#define RT5651_PWR_FV1 (0x1 << 14)
+#define RT5651_PWR_FV1_BIT 14
+#define RT5651_PWR_MB (0x1 << 13)
+#define RT5651_PWR_MB_BIT 13
+#define RT5651_PWR_LM (0x1 << 12)
+#define RT5651_PWR_LM_BIT 12
+#define RT5651_PWR_BG (0x1 << 11)
+#define RT5651_PWR_BG_BIT 11
+#define RT5651_PWR_HP_L (0x1 << 7)
+#define RT5651_PWR_HP_L_BIT 7
+#define RT5651_PWR_HP_R (0x1 << 6)
+#define RT5651_PWR_HP_R_BIT 6
+#define RT5651_PWR_HA (0x1 << 5)
+#define RT5651_PWR_HA_BIT 5
+#define RT5651_PWR_VREF2 (0x1 << 4)
+#define RT5651_PWR_VREF2_BIT 4
+#define RT5651_PWR_FV2 (0x1 << 3)
+#define RT5651_PWR_FV2_BIT 3
+#define RT5651_PWR_LDO (0x1 << 2)
+#define RT5651_PWR_LDO_BIT 2
+#define RT5651_PWR_LDO_DVO_MASK (0x3)
+#define RT5651_PWR_LDO_DVO_1_0V 0
+#define RT5651_PWR_LDO_DVO_1_1V 1
+#define RT5651_PWR_LDO_DVO_1_2V 2
+#define RT5651_PWR_LDO_DVO_1_3V 3
+
+/* Power Management for Analog 2 (0x64) */
+#define RT5651_PWR_BST1 (0x1 << 15)
+#define RT5651_PWR_BST1_BIT 15
+#define RT5651_PWR_BST2 (0x1 << 14)
+#define RT5651_PWR_BST2_BIT 14
+#define RT5651_PWR_BST3 (0x1 << 13)
+#define RT5651_PWR_BST3_BIT 13
+#define RT5651_PWR_MB1 (0x1 << 11)
+#define RT5651_PWR_MB1_BIT 11
+#define RT5651_PWR_PLL (0x1 << 9)
+#define RT5651_PWR_PLL_BIT 9
+#define RT5651_PWR_BST1_OP2 (0x1 << 5)
+#define RT5651_PWR_BST1_OP2_BIT 5
+#define RT5651_PWR_BST2_OP2 (0x1 << 4)
+#define RT5651_PWR_BST2_OP2_BIT 4
+#define RT5651_PWR_BST3_OP2 (0x1 << 3)
+#define RT5651_PWR_BST3_OP2_BIT 3
+#define RT5651_PWR_JD_M (0x1 << 2)
+#define RT5651_PWM_JD_M_BIT 2
+#define RT5651_PWR_JD2 (0x1 << 1)
+#define RT5651_PWM_JD2_BIT 1
+#define RT5651_PWR_JD3 (0x1)
+#define RT5651_PWM_JD3_BIT 0
+
+/* Power Management for Mixer (0x65) */
+#define RT5651_PWR_OM_L (0x1 << 15)
+#define RT5651_PWR_OM_L_BIT 15
+#define RT5651_PWR_OM_R (0x1 << 14)
+#define RT5651_PWR_OM_R_BIT 14
+#define RT5651_PWR_RM_L (0x1 << 11)
+#define RT5651_PWR_RM_L_BIT 11
+#define RT5651_PWR_RM_R (0x1 << 10)
+#define RT5651_PWR_RM_R_BIT 10
+
+/* Power Management for Volume (0x66) */
+#define RT5651_PWR_OV_L (0x1 << 13)
+#define RT5651_PWR_OV_L_BIT 13
+#define RT5651_PWR_OV_R (0x1 << 12)
+#define RT5651_PWR_OV_R_BIT 12
+#define RT5651_PWR_HV_L (0x1 << 11)
+#define RT5651_PWR_HV_L_BIT 11
+#define RT5651_PWR_HV_R (0x1 << 10)
+#define RT5651_PWR_HV_R_BIT 10
+#define RT5651_PWR_IN1_L (0x1 << 9)
+#define RT5651_PWR_IN1_L_BIT 9
+#define RT5651_PWR_IN1_R (0x1 << 8)
+#define RT5651_PWR_IN1_R_BIT 8
+#define RT5651_PWR_IN2_L (0x1 << 7)
+#define RT5651_PWR_IN2_L_BIT 7
+#define RT5651_PWR_IN2_R (0x1 << 6)
+#define RT5651_PWR_IN2_R_BIT 6
+
+/* I2S1/2/3 Audio Serial Data Port Control (0x70 0x71) */
+#define RT5651_I2S_MS_MASK (0x1 << 15)
+#define RT5651_I2S_MS_SFT 15
+#define RT5651_I2S_MS_M (0x0 << 15)
+#define RT5651_I2S_MS_S (0x1 << 15)
+#define RT5651_I2S_O_CP_MASK (0x3 << 10)
+#define RT5651_I2S_O_CP_SFT 10
+#define RT5651_I2S_O_CP_OFF (0x0 << 10)
+#define RT5651_I2S_O_CP_U_LAW (0x1 << 10)
+#define RT5651_I2S_O_CP_A_LAW (0x2 << 10)
+#define RT5651_I2S_I_CP_MASK (0x3 << 8)
+#define RT5651_I2S_I_CP_SFT 8
+#define RT5651_I2S_I_CP_OFF (0x0 << 8)
+#define RT5651_I2S_I_CP_U_LAW (0x1 << 8)
+#define RT5651_I2S_I_CP_A_LAW (0x2 << 8)
+#define RT5651_I2S_BP_MASK (0x1 << 7)
+#define RT5651_I2S_BP_SFT 7
+#define RT5651_I2S_BP_NOR (0x0 << 7)
+#define RT5651_I2S_BP_INV (0x1 << 7)
+#define RT5651_I2S_DL_MASK (0x3 << 2)
+#define RT5651_I2S_DL_SFT 2
+#define RT5651_I2S_DL_16 (0x0 << 2)
+#define RT5651_I2S_DL_20 (0x1 << 2)
+#define RT5651_I2S_DL_24 (0x2 << 2)
+#define RT5651_I2S_DL_8 (0x3 << 2)
+#define RT5651_I2S_DF_MASK (0x3)
+#define RT5651_I2S_DF_SFT 0
+#define RT5651_I2S_DF_I2S (0x0)
+#define RT5651_I2S_DF_LEFT (0x1)
+#define RT5651_I2S_DF_PCM_A (0x2)
+#define RT5651_I2S_DF_PCM_B (0x3)
+
+/* ADC/DAC Clock Control 1 (0x73) */
+#define RT5651_I2S_PD1_MASK (0x7 << 12)
+#define RT5651_I2S_PD1_SFT 12
+#define RT5651_I2S_PD1_1 (0x0 << 12)
+#define RT5651_I2S_PD1_2 (0x1 << 12)
+#define RT5651_I2S_PD1_3 (0x2 << 12)
+#define RT5651_I2S_PD1_4 (0x3 << 12)
+#define RT5651_I2S_PD1_6 (0x4 << 12)
+#define RT5651_I2S_PD1_8 (0x5 << 12)
+#define RT5651_I2S_PD1_12 (0x6 << 12)
+#define RT5651_I2S_PD1_16 (0x7 << 12)
+#define RT5651_I2S_BCLK_MS2_MASK (0x1 << 11)
+#define RT5651_I2S_BCLK_MS2_SFT 11
+#define RT5651_I2S_BCLK_MS2_32 (0x0 << 11)
+#define RT5651_I2S_BCLK_MS2_64 (0x1 << 11)
+#define RT5651_I2S_PD2_MASK (0x7 << 8)
+#define RT5651_I2S_PD2_SFT 8
+#define RT5651_I2S_PD2_1 (0x0 << 8)
+#define RT5651_I2S_PD2_2 (0x1 << 8)
+#define RT5651_I2S_PD2_3 (0x2 << 8)
+#define RT5651_I2S_PD2_4 (0x3 << 8)
+#define RT5651_I2S_PD2_6 (0x4 << 8)
+#define RT5651_I2S_PD2_8 (0x5 << 8)
+#define RT5651_I2S_PD2_12 (0x6 << 8)
+#define RT5651_I2S_PD2_16 (0x7 << 8)
+#define RT5651_DAC_OSR_MASK (0x3 << 2)
+#define RT5651_DAC_OSR_SFT 2
+#define RT5651_DAC_OSR_128 (0x0 << 2)
+#define RT5651_DAC_OSR_64 (0x1 << 2)
+#define RT5651_DAC_OSR_32 (0x2 << 2)
+#define RT5651_DAC_OSR_128_3 (0x3 << 2)
+#define RT5651_ADC_OSR_MASK (0x3)
+#define RT5651_ADC_OSR_SFT 0
+#define RT5651_ADC_OSR_128 (0x0)
+#define RT5651_ADC_OSR_64 (0x1)
+#define RT5651_ADC_OSR_32 (0x2)
+#define RT5651_ADC_OSR_128_3 (0x3)
+
+/* ADC/DAC Clock Control 2 (0x74) */
+#define RT5651_DAHPF_EN (0x1 << 11)
+#define RT5651_DAHPF_EN_SFT 11
+#define RT5651_ADHPF_EN (0x1 << 10)
+#define RT5651_ADHPF_EN_SFT 10
+
+/* Digital Microphone Control (0x75) */
+#define RT5651_DMIC_1_EN_MASK (0x1 << 15)
+#define RT5651_DMIC_1_EN_SFT 15
+#define RT5651_DMIC_1_DIS (0x0 << 15)
+#define RT5651_DMIC_1_EN (0x1 << 15)
+#define RT5651_DMIC_1L_LH_MASK (0x1 << 13)
+#define RT5651_DMIC_1L_LH_SFT 13
+#define RT5651_DMIC_1L_LH_FALLING (0x0 << 13)
+#define RT5651_DMIC_1L_LH_RISING (0x1 << 13)
+#define RT5651_DMIC_1R_LH_MASK (0x1 << 12)
+#define RT5651_DMIC_1R_LH_SFT 12
+#define RT5651_DMIC_1R_LH_FALLING (0x0 << 12)
+#define RT5651_DMIC_1R_LH_RISING (0x1 << 12)
+#define RT5651_DMIC_1_DP_MASK (0x3 << 10)
+#define RT5651_DMIC_1_DP_SFT 10
+#define RT5651_DMIC_1_DP_GPIO6 (0x0 << 10)
+#define RT5651_DMIC_1_DP_IN1P (0x1 << 10)
+#define RT5651_DMIC_2_DP_GPIO8 (0x2 << 10)
+#define RT5651_DMIC_CLK_MASK (0x7 << 5)
+#define RT5651_DMIC_CLK_SFT 5
+
+/* TDM Control 1 (0x77) */
+#define RT5651_TDM_INTEL_SEL_MASK (0x1 << 15)
+#define RT5651_TDM_INTEL_SEL_SFT 15
+#define RT5651_TDM_INTEL_SEL_64 (0x0 << 15)
+#define RT5651_TDM_INTEL_SEL_50 (0x1 << 15)
+#define RT5651_TDM_MODE_SEL_MASK (0x1 << 14)
+#define RT5651_TDM_MODE_SEL_SFT 14
+#define RT5651_TDM_MODE_SEL_NOR (0x0 << 14)
+#define RT5651_TDM_MODE_SEL_TDM (0x1 << 14)
+#define RT5651_TDM_CH_NUM_SEL_MASK (0x3 << 12)
+#define RT5651_TDM_CH_NUM_SEL_SFT 12
+#define RT5651_TDM_CH_NUM_SEL_2 (0x0 << 12)
+#define RT5651_TDM_CH_NUM_SEL_4 (0x1 << 12)
+#define RT5651_TDM_CH_NUM_SEL_6 (0x2 << 12)
+#define RT5651_TDM_CH_NUM_SEL_8 (0x3 << 12)
+#define RT5651_TDM_CH_LEN_SEL_MASK (0x3 << 10)
+#define RT5651_TDM_CH_LEN_SEL_SFT 10
+#define RT5651_TDM_CH_LEN_SEL_16 (0x0 << 10)
+#define RT5651_TDM_CH_LEN_SEL_20 (0x1 << 10)
+#define RT5651_TDM_CH_LEN_SEL_24 (0x2 << 10)
+#define RT5651_TDM_CH_LEN_SEL_32 (0x3 << 10)
+#define RT5651_TDM_ADC_SEL_MASK (0x1 << 9)
+#define RT5651_TDM_ADC_SEL_SFT 9
+#define RT5651_TDM_ADC_SEL_NOR (0x0 << 9)
+#define RT5651_TDM_ADC_SEL_SWAP (0x1 << 9)
+#define RT5651_TDM_ADC_START_SEL_MASK (0x1 << 8)
+#define RT5651_TDM_ADC_START_SEL_SFT 8
+#define RT5651_TDM_ADC_START_SEL_SL0 (0x0 << 8)
+#define RT5651_TDM_ADC_START_SEL_SL4 (0x1 << 8)
+#define RT5651_TDM_I2S_CH2_SEL_MASK (0x3 << 6)
+#define RT5651_TDM_I2S_CH2_SEL_SFT 6
+#define RT5651_TDM_I2S_CH2_SEL_LR (0x0 << 6)
+#define RT5651_TDM_I2S_CH2_SEL_RL (0x1 << 6)
+#define RT5651_TDM_I2S_CH2_SEL_LL (0x2 << 6)
+#define RT5651_TDM_I2S_CH2_SEL_RR (0x3 << 6)
+#define RT5651_TDM_I2S_CH4_SEL_MASK (0x3 << 4)
+#define RT5651_TDM_I2S_CH4_SEL_SFT 4
+#define RT5651_TDM_I2S_CH4_SEL_LR (0x0 << 4)
+#define RT5651_TDM_I2S_CH4_SEL_RL (0x1 << 4)
+#define RT5651_TDM_I2S_CH4_SEL_LL (0x2 << 4)
+#define RT5651_TDM_I2S_CH4_SEL_RR (0x3 << 4)
+#define RT5651_TDM_I2S_CH6_SEL_MASK (0x3 << 2)
+#define RT5651_TDM_I2S_CH6_SEL_SFT 2
+#define RT5651_TDM_I2S_CH6_SEL_LR (0x0 << 2)
+#define RT5651_TDM_I2S_CH6_SEL_RL (0x1 << 2)
+#define RT5651_TDM_I2S_CH6_SEL_LL (0x2 << 2)
+#define RT5651_TDM_I2S_CH6_SEL_RR (0x3 << 2)
+#define RT5651_TDM_I2S_CH8_SEL_MASK (0x3)
+#define RT5651_TDM_I2S_CH8_SEL_SFT 0
+#define RT5651_TDM_I2S_CH8_SEL_LR (0x0)
+#define RT5651_TDM_I2S_CH8_SEL_RL (0x1)
+#define RT5651_TDM_I2S_CH8_SEL_LL (0x2)
+#define RT5651_TDM_I2S_CH8_SEL_RR (0x3)
+
+/* TDM Control 2 (0x78) */
+#define RT5651_TDM_LRCK_POL_SEL_MASK (0x1 << 15)
+#define RT5651_TDM_LRCK_POL_SEL_SFT 15
+#define RT5651_TDM_LRCK_POL_SEL_NOR (0x0 << 15)
+#define RT5651_TDM_LRCK_POL_SEL_INV (0x1 << 15)
+#define RT5651_TDM_CH_VAL_SEL_MASK (0x1 << 14)
+#define RT5651_TDM_CH_VAL_SEL_SFT 14
+#define RT5651_TDM_CH_VAL_SEL_CH01 (0x0 << 14)
+#define RT5651_TDM_CH_VAL_SEL_CH0123 (0x1 << 14)
+#define RT5651_TDM_CH_VAL_EN (0x1 << 13)
+#define RT5651_TDM_CH_VAL_SFT 13
+#define RT5651_TDM_LPBK_EN (0x1 << 12)
+#define RT5651_TDM_LPBK_SFT 12
+#define RT5651_TDM_LRCK_PULSE_SEL_MASK (0x1 << 11)
+#define RT5651_TDM_LRCK_PULSE_SEL_SFT 11
+#define RT5651_TDM_LRCK_PULSE_SEL_BCLK (0x0 << 11)
+#define RT5651_TDM_LRCK_PULSE_SEL_CH (0x1 << 11)
+#define RT5651_TDM_END_EDGE_SEL_MASK (0x1 << 10)
+#define RT5651_TDM_END_EDGE_SEL_SFT 10
+#define RT5651_TDM_END_EDGE_SEL_POS (0x0 << 10)
+#define RT5651_TDM_END_EDGE_SEL_NEG (0x1 << 10)
+#define RT5651_TDM_END_EDGE_EN (0x1 << 9)
+#define RT5651_TDM_END_EDGE_EN_SFT 9
+#define RT5651_TDM_TRAN_EDGE_SEL_MASK (0x1 << 8)
+#define RT5651_TDM_TRAN_EDGE_SEL_SFT 8
+#define RT5651_TDM_TRAN_EDGE_SEL_POS (0x0 << 8)
+#define RT5651_TDM_TRAN_EDGE_SEL_NEG (0x1 << 8)
+#define RT5651_M_TDM2_L (0x1 << 7)
+#define RT5651_M_TDM2_L_SFT 7
+#define RT5651_M_TDM2_R (0x1 << 6)
+#define RT5651_M_TDM2_R_SFT 6
+#define RT5651_M_TDM4_L (0x1 << 5)
+#define RT5651_M_TDM4_L_SFT 5
+#define RT5651_M_TDM4_R (0x1 << 4)
+#define RT5651_M_TDM4_R_SFT 4
+
+/* TDM Control 3 (0x79) */
+#define RT5651_CH2_L_SEL_MASK (0x7 << 12)
+#define RT5651_CH2_L_SEL_SFT 12
+#define RT5651_CH2_L_SEL_SL0 (0x0 << 12)
+#define RT5651_CH2_L_SEL_SL1 (0x1 << 12)
+#define RT5651_CH2_L_SEL_SL2 (0x2 << 12)
+#define RT5651_CH2_L_SEL_SL3 (0x3 << 12)
+#define RT5651_CH2_L_SEL_SL4 (0x4 << 12)
+#define RT5651_CH2_L_SEL_SL5 (0x5 << 12)
+#define RT5651_CH2_L_SEL_SL6 (0x6 << 12)
+#define RT5651_CH2_L_SEL_SL7 (0x7 << 12)
+#define RT5651_CH2_R_SEL_MASK (0x7 << 8)
+#define RT5651_CH2_R_SEL_SFT 8
+#define RT5651_CH2_R_SEL_SL0 (0x0 << 8)
+#define RT5651_CH2_R_SEL_SL1 (0x1 << 8)
+#define RT5651_CH2_R_SEL_SL2 (0x2 << 8)
+#define RT5651_CH2_R_SEL_SL3 (0x3 << 8)
+#define RT5651_CH2_R_SEL_SL4 (0x4 << 8)
+#define RT5651_CH2_R_SEL_SL5 (0x5 << 8)
+#define RT5651_CH2_R_SEL_SL6 (0x6 << 8)
+#define RT5651_CH2_R_SEL_SL7 (0x7 << 8)
+#define RT5651_CH4_L_SEL_MASK (0x7 << 4)
+#define RT5651_CH4_L_SEL_SFT 4
+#define RT5651_CH4_L_SEL_SL0 (0x0 << 4)
+#define RT5651_CH4_L_SEL_SL1 (0x1 << 4)
+#define RT5651_CH4_L_SEL_SL2 (0x2 << 4)
+#define RT5651_CH4_L_SEL_SL3 (0x3 << 4)
+#define RT5651_CH4_L_SEL_SL4 (0x4 << 4)
+#define RT5651_CH4_L_SEL_SL5 (0x5 << 4)
+#define RT5651_CH4_L_SEL_SL6 (0x6 << 4)
+#define RT5651_CH4_L_SEL_SL7 (0x7 << 4)
+#define RT5651_CH4_R_SEL_MASK (0x7)
+#define RT5651_CH4_R_SEL_SFT 0
+#define RT5651_CH4_R_SEL_SL0 (0x0)
+#define RT5651_CH4_R_SEL_SL1 (0x1)
+#define RT5651_CH4_R_SEL_SL2 (0x2)
+#define RT5651_CH4_R_SEL_SL3 (0x3)
+#define RT5651_CH4_R_SEL_SL4 (0x4)
+#define RT5651_CH4_R_SEL_SL5 (0x5)
+#define RT5651_CH4_R_SEL_SL6 (0x6)
+#define RT5651_CH4_R_SEL_SL7 (0x7)
+
+/* Global Clock Control (0x80) */
+#define RT5651_SCLK_SRC_MASK (0x3 << 14)
+#define RT5651_SCLK_SRC_SFT 14
+#define RT5651_SCLK_SRC_MCLK (0x0 << 14)
+#define RT5651_SCLK_SRC_PLL1 (0x1 << 14)
+#define RT5651_SCLK_SRC_RCCLK (0x2 << 14)
+#define RT5651_PLL1_SRC_MASK (0x3 << 12)
+#define RT5651_PLL1_SRC_SFT 12
+#define RT5651_PLL1_SRC_MCLK (0x0 << 12)
+#define RT5651_PLL1_SRC_BCLK1 (0x1 << 12)
+#define RT5651_PLL1_SRC_BCLK2 (0x2 << 12)
+#define RT5651_PLL1_PD_MASK (0x1 << 3)
+#define RT5651_PLL1_PD_SFT 3
+#define RT5651_PLL1_PD_1 (0x0 << 3)
+#define RT5651_PLL1_PD_2 (0x1 << 3)
+
+#define RT5651_PLL_INP_MAX 40000000
+#define RT5651_PLL_INP_MIN 256000
+/* PLL M/N/K Code Control 1 (0x81) */
+#define RT5651_PLL_N_MAX 0x1ff
+#define RT5651_PLL_N_MASK (RT5651_PLL_N_MAX << 7)
+#define RT5651_PLL_N_SFT 7
+#define RT5651_PLL_K_MAX 0x1f
+#define RT5651_PLL_K_MASK (RT5651_PLL_K_MAX)
+#define RT5651_PLL_K_SFT 0
+
+/* PLL M/N/K Code Control 2 (0x82) */
+#define RT5651_PLL_M_MAX 0xf
+#define RT5651_PLL_M_MASK (RT5651_PLL_M_MAX << 12)
+#define RT5651_PLL_M_SFT 12
+#define RT5651_PLL_M_BP (0x1 << 11)
+#define RT5651_PLL_M_BP_SFT 11
+
+/* PLL tracking mode 1 (0x83) */
+#define RT5651_STO1_T_MASK (0x1 << 15)
+#define RT5651_STO1_T_SFT 15
+#define RT5651_STO1_T_SCLK (0x0 << 15)
+#define RT5651_STO1_T_LRCK1 (0x1 << 15)
+#define RT5651_STO2_T_MASK (0x1 << 12)
+#define RT5651_STO2_T_SFT 12
+#define RT5651_STO2_T_I2S2 (0x0 << 12)
+#define RT5651_STO2_T_LRCK2 (0x1 << 12)
+#define RT5651_ASRC2_REF_MASK (0x1 << 11)
+#define RT5651_ASRC2_REF_SFT 11
+#define RT5651_ASRC2_REF_LRCK2 (0x0 << 11)
+#define RT5651_ASRC2_REF_LRCK1 (0x1 << 11)
+#define RT5651_DMIC_1_M_MASK (0x1 << 9)
+#define RT5651_DMIC_1_M_SFT 9
+#define RT5651_DMIC_1_M_NOR (0x0 << 9)
+#define RT5651_DMIC_1_M_ASYN (0x1 << 9)
+
+/* PLL tracking mode 2 (0x84) */
+#define RT5651_STO1_ASRC_EN (0x1 << 15)
+#define RT5651_STO1_ASRC_EN_SFT 15
+#define RT5651_STO2_ASRC_EN (0x1 << 14)
+#define RT5651_STO2_ASRC_EN_SFT 14
+#define RT5651_STO1_DAC_M_MASK (0x1 << 13)
+#define RT5651_STO1_DAC_M_SFT 13
+#define RT5651_STO1_DAC_M_NOR (0x0 << 13)
+#define RT5651_STO1_DAC_M_ASRC (0x1 << 13)
+#define RT5651_STO2_DAC_M_MASK (0x1 << 12)
+#define RT5651_STO2_DAC_M_SFT 12
+#define RT5651_STO2_DAC_M_NOR (0x0 << 12)
+#define RT5651_STO2_DAC_M_ASRC (0x1 << 12)
+#define RT5651_ADC_M_MASK (0x1 << 11)
+#define RT5651_ADC_M_SFT 11
+#define RT5651_ADC_M_NOR (0x0 << 11)
+#define RT5651_ADC_M_ASRC (0x1 << 11)
+#define RT5651_I2S1_R_D_MASK (0x1 << 4)
+#define RT5651_I2S1_R_D_SFT 4
+#define RT5651_I2S1_R_D_DIS (0x0 << 4)
+#define RT5651_I2S1_R_D_EN (0x1 << 4)
+#define RT5651_I2S2_R_D_MASK (0x1 << 3)
+#define RT5651_I2S2_R_D_SFT 3
+#define RT5651_I2S2_R_D_DIS (0x0 << 3)
+#define RT5651_I2S2_R_D_EN (0x1 << 3)
+#define RT5651_PRE_SCLK_MASK (0x3)
+#define RT5651_PRE_SCLK_SFT 0
+#define RT5651_PRE_SCLK_512 (0x0)
+#define RT5651_PRE_SCLK_1024 (0x1)
+#define RT5651_PRE_SCLK_2048 (0x2)
+
+/* PLL tracking mode 3 (0x85) */
+#define RT5651_I2S1_RATE_MASK (0xf << 12)
+#define RT5651_I2S1_RATE_SFT 12
+#define RT5651_I2S2_RATE_MASK (0xf << 8)
+#define RT5651_I2S2_RATE_SFT 8
+#define RT5651_G_ASRC_LP_MASK (0x1 << 3)
+#define RT5651_G_ASRC_LP_SFT 3
+#define RT5651_ASRC_LP_F_M (0x1 << 2)
+#define RT5651_ASRC_LP_F_SFT 2
+#define RT5651_ASRC_LP_F_NOR (0x0 << 2)
+#define RT5651_ASRC_LP_F_SB (0x1 << 2)
+#define RT5651_FTK_PH_DET_MASK (0x3)
+#define RT5651_FTK_PH_DET_SFT 0
+#define RT5651_FTK_PH_DET_DIV1 (0x0)
+#define RT5651_FTK_PH_DET_DIV2 (0x1)
+#define RT5651_FTK_PH_DET_DIV4 (0x2)
+#define RT5651_FTK_PH_DET_DIV8 (0x3)
+
+/*PLL tracking mode 6 (0x89) */
+#define RT5651_I2S1_PD_MASK (0x7 << 12)
+#define RT5651_I2S1_PD_SFT 12
+#define RT5651_I2S2_PD_MASK (0x7 << 8)
+#define RT5651_I2S2_PD_SFT 8
+
+/*PLL tracking mode 7 (0x8a) */
+#define RT5651_FSI1_RATE_MASK (0xf << 12)
+#define RT5651_FSI1_RATE_SFT 12
+#define RT5651_FSI2_RATE_MASK (0xf << 8)
+#define RT5651_FSI2_RATE_SFT 8
+
+/* HPOUT Over Current Detection (0x8b) */
+#define RT5651_HP_OVCD_MASK (0x1 << 10)
+#define RT5651_HP_OVCD_SFT 10
+#define RT5651_HP_OVCD_DIS (0x0 << 10)
+#define RT5651_HP_OVCD_EN (0x1 << 10)
+#define RT5651_HP_OC_TH_MASK (0x3 << 8)
+#define RT5651_HP_OC_TH_SFT 8
+#define RT5651_HP_OC_TH_90 (0x0 << 8)
+#define RT5651_HP_OC_TH_105 (0x1 << 8)
+#define RT5651_HP_OC_TH_120 (0x2 << 8)
+#define RT5651_HP_OC_TH_135 (0x3 << 8)
+
+/* Depop Mode Control 1 (0x8e) */
+#define RT5651_SMT_TRIG_MASK (0x1 << 15)
+#define RT5651_SMT_TRIG_SFT 15
+#define RT5651_SMT_TRIG_DIS (0x0 << 15)
+#define RT5651_SMT_TRIG_EN (0x1 << 15)
+#define RT5651_HP_L_SMT_MASK (0x1 << 9)
+#define RT5651_HP_L_SMT_SFT 9
+#define RT5651_HP_L_SMT_DIS (0x0 << 9)
+#define RT5651_HP_L_SMT_EN (0x1 << 9)
+#define RT5651_HP_R_SMT_MASK (0x1 << 8)
+#define RT5651_HP_R_SMT_SFT 8
+#define RT5651_HP_R_SMT_DIS (0x0 << 8)
+#define RT5651_HP_R_SMT_EN (0x1 << 8)
+#define RT5651_HP_CD_PD_MASK (0x1 << 7)
+#define RT5651_HP_CD_PD_SFT 7
+#define RT5651_HP_CD_PD_DIS (0x0 << 7)
+#define RT5651_HP_CD_PD_EN (0x1 << 7)
+#define RT5651_RSTN_MASK (0x1 << 6)
+#define RT5651_RSTN_SFT 6
+#define RT5651_RSTN_DIS (0x0 << 6)
+#define RT5651_RSTN_EN (0x1 << 6)
+#define RT5651_RSTP_MASK (0x1 << 5)
+#define RT5651_RSTP_SFT 5
+#define RT5651_RSTP_DIS (0x0 << 5)
+#define RT5651_RSTP_EN (0x1 << 5)
+#define RT5651_HP_CO_MASK (0x1 << 4)
+#define RT5651_HP_CO_SFT 4
+#define RT5651_HP_CO_DIS (0x0 << 4)
+#define RT5651_HP_CO_EN (0x1 << 4)
+#define RT5651_HP_CP_MASK (0x1 << 3)
+#define RT5651_HP_CP_SFT 3
+#define RT5651_HP_CP_PD (0x0 << 3)
+#define RT5651_HP_CP_PU (0x1 << 3)
+#define RT5651_HP_SG_MASK (0x1 << 2)
+#define RT5651_HP_SG_SFT 2
+#define RT5651_HP_SG_DIS (0x0 << 2)
+#define RT5651_HP_SG_EN (0x1 << 2)
+#define RT5651_HP_DP_MASK (0x1 << 1)
+#define RT5651_HP_DP_SFT 1
+#define RT5651_HP_DP_PD (0x0 << 1)
+#define RT5651_HP_DP_PU (0x1 << 1)
+#define RT5651_HP_CB_MASK (0x1)
+#define RT5651_HP_CB_SFT 0
+#define RT5651_HP_CB_PD (0x0)
+#define RT5651_HP_CB_PU (0x1)
+
+/* Depop Mode Control 2 (0x8f) */
+#define RT5651_DEPOP_MASK (0x1 << 13)
+#define RT5651_DEPOP_SFT 13
+#define RT5651_DEPOP_AUTO (0x0 << 13)
+#define RT5651_DEPOP_MAN (0x1 << 13)
+#define RT5651_RAMP_MASK (0x1 << 12)
+#define RT5651_RAMP_SFT 12
+#define RT5651_RAMP_DIS (0x0 << 12)
+#define RT5651_RAMP_EN (0x1 << 12)
+#define RT5651_BPS_MASK (0x1 << 11)
+#define RT5651_BPS_SFT 11
+#define RT5651_BPS_DIS (0x0 << 11)
+#define RT5651_BPS_EN (0x1 << 11)
+#define RT5651_FAST_UPDN_MASK (0x1 << 10)
+#define RT5651_FAST_UPDN_SFT 10
+#define RT5651_FAST_UPDN_DIS (0x0 << 10)
+#define RT5651_FAST_UPDN_EN (0x1 << 10)
+#define RT5651_MRES_MASK (0x3 << 8)
+#define RT5651_MRES_SFT 8
+#define RT5651_MRES_15MO (0x0 << 8)
+#define RT5651_MRES_25MO (0x1 << 8)
+#define RT5651_MRES_35MO (0x2 << 8)
+#define RT5651_MRES_45MO (0x3 << 8)
+#define RT5651_VLO_MASK (0x1 << 7)
+#define RT5651_VLO_SFT 7
+#define RT5651_VLO_3V (0x0 << 7)
+#define RT5651_VLO_32V (0x1 << 7)
+#define RT5651_DIG_DP_MASK (0x1 << 6)
+#define RT5651_DIG_DP_SFT 6
+#define RT5651_DIG_DP_DIS (0x0 << 6)
+#define RT5651_DIG_DP_EN (0x1 << 6)
+#define RT5651_DP_TH_MASK (0x3 << 4)
+#define RT5651_DP_TH_SFT 4
+
+/* Depop Mode Control 3 (0x90) */
+#define RT5651_CP_SYS_MASK (0x7 << 12)
+#define RT5651_CP_SYS_SFT 12
+#define RT5651_CP_FQ1_MASK (0x7 << 8)
+#define RT5651_CP_FQ1_SFT 8
+#define RT5651_CP_FQ2_MASK (0x7 << 4)
+#define RT5651_CP_FQ2_SFT 4
+#define RT5651_CP_FQ3_MASK (0x7)
+#define RT5651_CP_FQ3_SFT 0
+#define RT5651_CP_FQ_1_5_KHZ 0
+#define RT5651_CP_FQ_3_KHZ 1
+#define RT5651_CP_FQ_6_KHZ 2
+#define RT5651_CP_FQ_12_KHZ 3
+#define RT5651_CP_FQ_24_KHZ 4
+#define RT5651_CP_FQ_48_KHZ 5
+#define RT5651_CP_FQ_96_KHZ 6
+#define RT5651_CP_FQ_192_KHZ 7
+
+/* HPOUT charge pump (0x91) */
+#define RT5651_OSW_L_MASK (0x1 << 11)
+#define RT5651_OSW_L_SFT 11
+#define RT5651_OSW_L_DIS (0x0 << 11)
+#define RT5651_OSW_L_EN (0x1 << 11)
+#define RT5651_OSW_R_MASK (0x1 << 10)
+#define RT5651_OSW_R_SFT 10
+#define RT5651_OSW_R_DIS (0x0 << 10)
+#define RT5651_OSW_R_EN (0x1 << 10)
+#define RT5651_PM_HP_MASK (0x3 << 8)
+#define RT5651_PM_HP_SFT 8
+#define RT5651_PM_HP_LV (0x0 << 8)
+#define RT5651_PM_HP_MV (0x1 << 8)
+#define RT5651_PM_HP_HV (0x2 << 8)
+#define RT5651_IB_HP_MASK (0x3 << 6)
+#define RT5651_IB_HP_SFT 6
+#define RT5651_IB_HP_125IL (0x0 << 6)
+#define RT5651_IB_HP_25IL (0x1 << 6)
+#define RT5651_IB_HP_5IL (0x2 << 6)
+#define RT5651_IB_HP_1IL (0x3 << 6)
+
+/* Micbias Control (0x93) */
+#define RT5651_MIC1_BS_MASK (0x1 << 15)
+#define RT5651_MIC1_BS_SFT 15
+#define RT5651_MIC1_BS_9AV (0x0 << 15)
+#define RT5651_MIC1_BS_75AV (0x1 << 15)
+#define RT5651_MIC1_CLK_MASK (0x1 << 13)
+#define RT5651_MIC1_CLK_SFT 13
+#define RT5651_MIC1_CLK_DIS (0x0 << 13)
+#define RT5651_MIC1_CLK_EN (0x1 << 13)
+#define RT5651_MIC1_OVCD_MASK (0x1 << 11)
+#define RT5651_MIC1_OVCD_SFT 11
+#define RT5651_MIC1_OVCD_DIS (0x0 << 11)
+#define RT5651_MIC1_OVCD_EN (0x1 << 11)
+#define RT5651_MIC1_OVTH_MASK (0x3 << 9)
+#define RT5651_MIC1_OVTH_SFT 9
+#define RT5651_MIC1_OVTH_600UA (0x0 << 9)
+#define RT5651_MIC1_OVTH_1500UA (0x1 << 9)
+#define RT5651_MIC1_OVTH_2000UA (0x2 << 9)
+#define RT5651_PWR_MB_MASK (0x1 << 5)
+#define RT5651_PWR_MB_SFT 5
+#define RT5651_PWR_MB_PD (0x0 << 5)
+#define RT5651_PWR_MB_PU (0x1 << 5)
+#define RT5651_PWR_CLK12M_MASK (0x1 << 4)
+#define RT5651_PWR_CLK12M_SFT 4
+#define RT5651_PWR_CLK12M_PD (0x0 << 4)
+#define RT5651_PWR_CLK12M_PU (0x1 << 4)
+
+/* Analog JD Control 1 (0x94) */
+#define RT5651_JD2_CMP_MASK (0x7 << 12)
+#define RT5651_JD2_CMP_SFT 12
+#define RT5651_JD_PU (0x1 << 11)
+#define RT5651_JD_PU_SFT 11
+#define RT5651_JD_PD (0x1 << 10)
+#define RT5651_JD_PD_SFT 10
+#define RT5651_JD_MODE_SEL_MASK (0x3 << 8)
+#define RT5651_JD_MODE_SEL_SFT 8
+#define RT5651_JD_MODE_SEL_M0 (0x0 << 8)
+#define RT5651_JD_MODE_SEL_M1 (0x1 << 8)
+#define RT5651_JD_MODE_SEL_M2 (0x2 << 8)
+#define RT5651_JD_M_CMP (0x7 << 4)
+#define RT5651_JD_M_CMP_SFT 4
+#define RT5651_JD_M_PU (0x1 << 3)
+#define RT5651_JD_M_PU_SFT 3
+#define RT5651_JD_M_PD (0x1 << 2)
+#define RT5651_JD_M_PD_SFT 2
+#define RT5651_JD_M_MODE_SEL_MASK (0x3)
+#define RT5651_JD_M_MODE_SEL_SFT 0
+#define RT5651_JD_M_MODE_SEL_M0 (0x0)
+#define RT5651_JD_M_MODE_SEL_M1 (0x1)
+#define RT5651_JD_M_MODE_SEL_M2 (0x2)
+
+/* Analog JD Control 2 (0x95) */
+#define RT5651_JD3_CMP_MASK (0x7 << 12)
+#define RT5651_JD3_CMP_SFT 12
+
+/* EQ Control 1 (0xb0) */
+#define RT5651_EQ_SRC_MASK (0x1 << 15)
+#define RT5651_EQ_SRC_SFT 15
+#define RT5651_EQ_SRC_DAC (0x0 << 15)
+#define RT5651_EQ_SRC_ADC (0x1 << 15)
+#define RT5651_EQ_UPD (0x1 << 14)
+#define RT5651_EQ_UPD_BIT 14
+#define RT5651_EQ_CD_MASK (0x1 << 13)
+#define RT5651_EQ_CD_SFT 13
+#define RT5651_EQ_CD_DIS (0x0 << 13)
+#define RT5651_EQ_CD_EN (0x1 << 13)
+#define RT5651_EQ_DITH_MASK (0x3 << 8)
+#define RT5651_EQ_DITH_SFT 8
+#define RT5651_EQ_DITH_NOR (0x0 << 8)
+#define RT5651_EQ_DITH_LSB (0x1 << 8)
+#define RT5651_EQ_DITH_LSB_1 (0x2 << 8)
+#define RT5651_EQ_DITH_LSB_2 (0x3 << 8)
+#define RT5651_EQ_CD_F (0x1 << 7)
+#define RT5651_EQ_CD_F_BIT 7
+#define RT5651_EQ_STA_HP2 (0x1 << 6)
+#define RT5651_EQ_STA_HP2_BIT 6
+#define RT5651_EQ_STA_HP1 (0x1 << 5)
+#define RT5651_EQ_STA_HP1_BIT 5
+#define RT5651_EQ_STA_BP4 (0x1 << 4)
+#define RT5651_EQ_STA_BP4_BIT 4
+#define RT5651_EQ_STA_BP3 (0x1 << 3)
+#define RT5651_EQ_STA_BP3_BIT 3
+#define RT5651_EQ_STA_BP2 (0x1 << 2)
+#define RT5651_EQ_STA_BP2_BIT 2
+#define RT5651_EQ_STA_BP1 (0x1 << 1)
+#define RT5651_EQ_STA_BP1_BIT 1
+#define RT5651_EQ_STA_LP (0x1)
+#define RT5651_EQ_STA_LP_BIT 0
+
+/* EQ Control 2 (0xb1) */
+#define RT5651_EQ_HPF1_M_MASK (0x1 << 8)
+#define RT5651_EQ_HPF1_M_SFT 8
+#define RT5651_EQ_HPF1_M_HI (0x0 << 8)
+#define RT5651_EQ_HPF1_M_1ST (0x1 << 8)
+#define RT5651_EQ_LPF1_M_MASK (0x1 << 7)
+#define RT5651_EQ_LPF1_M_SFT 7
+#define RT5651_EQ_LPF1_M_LO (0x0 << 7)
+#define RT5651_EQ_LPF1_M_1ST (0x1 << 7)
+#define RT5651_EQ_HPF2_MASK (0x1 << 6)
+#define RT5651_EQ_HPF2_SFT 6
+#define RT5651_EQ_HPF2_DIS (0x0 << 6)
+#define RT5651_EQ_HPF2_EN (0x1 << 6)
+#define RT5651_EQ_HPF1_MASK (0x1 << 5)
+#define RT5651_EQ_HPF1_SFT 5
+#define RT5651_EQ_HPF1_DIS (0x0 << 5)
+#define RT5651_EQ_HPF1_EN (0x1 << 5)
+#define RT5651_EQ_BPF4_MASK (0x1 << 4)
+#define RT5651_EQ_BPF4_SFT 4
+#define RT5651_EQ_BPF4_DIS (0x0 << 4)
+#define RT5651_EQ_BPF4_EN (0x1 << 4)
+#define RT5651_EQ_BPF3_MASK (0x1 << 3)
+#define RT5651_EQ_BPF3_SFT 3
+#define RT5651_EQ_BPF3_DIS (0x0 << 3)
+#define RT5651_EQ_BPF3_EN (0x1 << 3)
+#define RT5651_EQ_BPF2_MASK (0x1 << 2)
+#define RT5651_EQ_BPF2_SFT 2
+#define RT5651_EQ_BPF2_DIS (0x0 << 2)
+#define RT5651_EQ_BPF2_EN (0x1 << 2)
+#define RT5651_EQ_BPF1_MASK (0x1 << 1)
+#define RT5651_EQ_BPF1_SFT 1
+#define RT5651_EQ_BPF1_DIS (0x0 << 1)
+#define RT5651_EQ_BPF1_EN (0x1 << 1)
+#define RT5651_EQ_LPF_MASK (0x1)
+#define RT5651_EQ_LPF_SFT 0
+#define RT5651_EQ_LPF_DIS (0x0)
+#define RT5651_EQ_LPF_EN (0x1)
+#define RT5651_EQ_CTRL_MASK (0x7f)
+
+/* Memory Test (0xb2) */
+#define RT5651_MT_MASK (0x1 << 15)
+#define RT5651_MT_SFT 15
+#define RT5651_MT_DIS (0x0 << 15)
+#define RT5651_MT_EN (0x1 << 15)
+
+/* ALC Control 1 (0xb4) */
+#define RT5651_ALC_P_MASK (0x1 << 15)
+#define RT5651_ALC_P_SFT 15
+#define RT5651_ALC_P_DAC (0x0 << 15)
+#define RT5651_ALC_P_ADC (0x1 << 15)
+#define RT5651_ALC_MASK (0x1 << 14)
+#define RT5651_ALC_SFT 14
+#define RT5651_ALC_DIS (0x0 << 14)
+#define RT5651_ALC_EN (0x1 << 14)
+#define RT5651_ALC_UPD (0x1 << 13)
+#define RT5651_ALC_UPD_BIT 13
+#define RT5651_ALC_AR_MASK (0x1f << 8)
+#define RT5651_ALC_AR_SFT 8
+#define RT5651_ALC_R_MASK (0x7 << 5)
+#define RT5651_ALC_R_SFT 5
+#define RT5651_ALC_R_48K (0x1 << 5)
+#define RT5651_ALC_R_96K (0x2 << 5)
+#define RT5651_ALC_R_192K (0x3 << 5)
+#define RT5651_ALC_R_441K (0x5 << 5)
+#define RT5651_ALC_R_882K (0x6 << 5)
+#define RT5651_ALC_R_1764K (0x7 << 5)
+#define RT5651_ALC_RC_MASK (0x1f)
+#define RT5651_ALC_RC_SFT 0
+
+/* ALC Control 2 (0xb5) */
+#define RT5651_ALC_POB_MASK (0x3f << 8)
+#define RT5651_ALC_POB_SFT 8
+#define RT5651_ALC_DRC_MASK (0x1 << 7)
+#define RT5651_ALC_DRC_SFT 7
+#define RT5651_ALC_DRC_DIS (0x0 << 7)
+#define RT5651_ALC_DRC_EN (0x1 << 7)
+#define RT5651_ALC_CPR_MASK (0x3 << 5)
+#define RT5651_ALC_CPR_SFT 5
+#define RT5651_ALC_CPR_1_1 (0x0 << 5)
+#define RT5651_ALC_CPR_1_2 (0x1 << 5)
+#define RT5651_ALC_CPR_1_4 (0x2 << 5)
+#define RT5651_ALC_CPR_1_8 (0x3 << 5)
+#define RT5651_ALC_PRB_MASK (0x1f)
+#define RT5651_ALC_PRB_SFT 0
+
+/* ALC Control 3 (0xb6) */
+#define RT5651_ALC_NGB_MASK (0xf << 12)
+#define RT5651_ALC_NGB_SFT 12
+#define RT5651_ALC_TAR_MASK (0x1f << 7)
+#define RT5651_ALC_TAR_SFT 7
+#define RT5651_ALC_NG_MASK (0x1 << 6)
+#define RT5651_ALC_NG_SFT 6
+#define RT5651_ALC_NG_DIS (0x0 << 6)
+#define RT5651_ALC_NG_EN (0x1 << 6)
+#define RT5651_ALC_NGH_MASK (0x1 << 5)
+#define RT5651_ALC_NGH_SFT 5
+#define RT5651_ALC_NGH_DIS (0x0 << 5)
+#define RT5651_ALC_NGH_EN (0x1 << 5)
+#define RT5651_ALC_NGT_MASK (0x1f)
+#define RT5651_ALC_NGT_SFT 0
+
+/* Jack Detect Control 1 (0xbb) */
+#define RT5651_JD_MASK (0x7 << 13)
+#define RT5651_JD_SFT 13
+#define RT5651_JD_DIS (0x0 << 13)
+#define RT5651_JD_GPIO1 (0x1 << 13)
+#define RT5651_JD_GPIO2 (0x2 << 13)
+#define RT5651_JD_GPIO3 (0x3 << 13)
+#define RT5651_JD_GPIO4 (0x4 << 13)
+#define RT5651_JD_GPIO5 (0x5 << 13)
+#define RT5651_JD_GPIO6 (0x6 << 13)
+#define RT5651_JD_HP_MASK (0x1 << 11)
+#define RT5651_JD_HP_SFT 11
+#define RT5651_JD_HP_DIS (0x0 << 11)
+#define RT5651_JD_HP_EN (0x1 << 11)
+#define RT5651_JD_HP_TRG_MASK (0x1 << 10)
+#define RT5651_JD_HP_TRG_SFT 10
+#define RT5651_JD_HP_TRG_LO (0x0 << 10)
+#define RT5651_JD_HP_TRG_HI (0x1 << 10)
+#define RT5651_JD_SPL_MASK (0x1 << 9)
+#define RT5651_JD_SPL_SFT 9
+#define RT5651_JD_SPL_DIS (0x0 << 9)
+#define RT5651_JD_SPL_EN (0x1 << 9)
+#define RT5651_JD_SPL_TRG_MASK (0x1 << 8)
+#define RT5651_JD_SPL_TRG_SFT 8
+#define RT5651_JD_SPL_TRG_LO (0x0 << 8)
+#define RT5651_JD_SPL_TRG_HI (0x1 << 8)
+#define RT5651_JD_SPR_MASK (0x1 << 7)
+#define RT5651_JD_SPR_SFT 7
+#define RT5651_JD_SPR_DIS (0x0 << 7)
+#define RT5651_JD_SPR_EN (0x1 << 7)
+#define RT5651_JD_SPR_TRG_MASK (0x1 << 6)
+#define RT5651_JD_SPR_TRG_SFT 6
+#define RT5651_JD_SPR_TRG_LO (0x0 << 6)
+#define RT5651_JD_SPR_TRG_HI (0x1 << 6)
+#define RT5651_JD_LO_MASK (0x1 << 3)
+#define RT5651_JD_LO_SFT 3
+#define RT5651_JD_LO_DIS (0x0 << 3)
+#define RT5651_JD_LO_EN (0x1 << 3)
+#define RT5651_JD_LO_TRG_MASK (0x1 << 2)
+#define RT5651_JD_LO_TRG_SFT 2
+#define RT5651_JD_LO_TRG_LO (0x0 << 2)
+#define RT5651_JD_LO_TRG_HI (0x1 << 2)
+
+/* Jack Detect Control 2 (0xbc) */
+#define RT5651_JD_TRG_SEL_MASK (0x7 << 9)
+#define RT5651_JD_TRG_SEL_SFT 9
+#define RT5651_JD_TRG_SEL_GPIO (0x0 << 9)
+#define RT5651_JD_TRG_SEL_JD1_1 (0x1 << 9)
+#define RT5651_JD_TRG_SEL_JD1_2 (0x2 << 9)
+#define RT5651_JD_TRG_SEL_JD2 (0x3 << 9)
+#define RT5651_JD_TRG_SEL_JD3 (0x4 << 9)
+#define RT5651_JD3_IRQ_EN (0x1 << 8)
+#define RT5651_JD3_IRQ_EN_SFT 8
+#define RT5651_JD3_EN_STKY (0x1 << 7)
+#define RT5651_JD3_EN_STKY_SFT 7
+#define RT5651_JD3_INV (0x1 << 6)
+#define RT5651_JD3_INV_SFT 6
+
+/* IRQ Control 1 (0xbd) */
+#define RT5651_IRQ_JD_MASK (0x1 << 15)
+#define RT5651_IRQ_JD_SFT 15
+#define RT5651_IRQ_JD_BP (0x0 << 15)
+#define RT5651_IRQ_JD_NOR (0x1 << 15)
+#define RT5651_JD_STKY_MASK (0x1 << 13)
+#define RT5651_JD_STKY_SFT 13
+#define RT5651_JD_STKY_DIS (0x0 << 13)
+#define RT5651_JD_STKY_EN (0x1 << 13)
+#define RT5651_JD_P_MASK (0x1 << 11)
+#define RT5651_JD_P_SFT 11
+#define RT5651_JD_P_NOR (0x0 << 11)
+#define RT5651_JD_P_INV (0x1 << 11)
+#define RT5651_JD1_1_IRQ_EN (0x1 << 9)
+#define RT5651_JD1_1_IRQ_EN_SFT 9
+#define RT5651_JD1_1_EN_STKY (0x1 << 8)
+#define RT5651_JD1_1_EN_STKY_SFT 8
+#define RT5651_JD1_1_INV (0x1 << 7)
+#define RT5651_JD1_1_INV_SFT 7
+#define RT5651_JD1_2_IRQ_EN (0x1 << 6)
+#define RT5651_JD1_2_IRQ_EN_SFT 6
+#define RT5651_JD1_2_EN_STKY (0x1 << 5)
+#define RT5651_JD1_2_EN_STKY_SFT 5
+#define RT5651_JD1_2_INV (0x1 << 4)
+#define RT5651_JD1_2_INV_SFT 4
+#define RT5651_JD2_IRQ_EN (0x1 << 3)
+#define RT5651_JD2_IRQ_EN_SFT 3
+#define RT5651_JD2_EN_STKY (0x1 << 2)
+#define RT5651_JD2_EN_STKY_SFT 2
+#define RT5651_JD2_INV (0x1 << 1)
+#define RT5651_JD2_INV_SFT 1
+
+/* IRQ Control 2 (0xbe) */
+#define RT5651_IRQ_MB1_OC_MASK (0x1 << 15)
+#define RT5651_IRQ_MB1_OC_SFT 15
+#define RT5651_IRQ_MB1_OC_BP (0x0 << 15)
+#define RT5651_IRQ_MB1_OC_NOR (0x1 << 15)
+#define RT5651_MB1_OC_STKY_MASK (0x1 << 11)
+#define RT5651_MB1_OC_STKY_SFT 11
+#define RT5651_MB1_OC_STKY_DIS (0x0 << 11)
+#define RT5651_MB1_OC_STKY_EN (0x1 << 11)
+#define RT5651_MB1_OC_P_MASK (0x1 << 7)
+#define RT5651_MB1_OC_P_SFT 7
+#define RT5651_MB1_OC_P_NOR (0x0 << 7)
+#define RT5651_MB1_OC_P_INV (0x1 << 7)
+#define RT5651_MB2_OC_P_MASK (0x1 << 6)
+#define RT5651_MB1_OC_CLR (0x1 << 3)
+#define RT5651_MB1_OC_CLR_SFT 3
+#define RT5651_STA_GPIO8 (0x1)
+#define RT5651_STA_GPIO8_BIT 0
+
+/* Internal Status and GPIO status (0xbf) */
+#define RT5651_STA_JD3 (0x1 << 15)
+#define RT5651_STA_JD3_BIT 15
+#define RT5651_STA_JD2 (0x1 << 14)
+#define RT5651_STA_JD2_BIT 14
+#define RT5651_STA_JD1_2 (0x1 << 13)
+#define RT5651_STA_JD1_2_BIT 13
+#define RT5651_STA_JD1_1 (0x1 << 12)
+#define RT5651_STA_JD1_1_BIT 12
+#define RT5651_STA_GP7 (0x1 << 11)
+#define RT5651_STA_GP7_BIT 11
+#define RT5651_STA_GP6 (0x1 << 10)
+#define RT5651_STA_GP6_BIT 10
+#define RT5651_STA_GP5 (0x1 << 9)
+#define RT5651_STA_GP5_BIT 9
+#define RT5651_STA_GP1 (0x1 << 8)
+#define RT5651_STA_GP1_BIT 8
+#define RT5651_STA_GP2 (0x1 << 7)
+#define RT5651_STA_GP2_BIT 7
+#define RT5651_STA_GP3 (0x1 << 6)
+#define RT5651_STA_GP3_BIT 6
+#define RT5651_STA_GP4 (0x1 << 5)
+#define RT5651_STA_GP4_BIT 5
+#define RT5651_STA_GP_JD (0x1 << 4)
+#define RT5651_STA_GP_JD_BIT 4
+
+/* GPIO Control 1 (0xc0) */
+#define RT5651_GP1_PIN_MASK (0x1 << 15)
+#define RT5651_GP1_PIN_SFT 15
+#define RT5651_GP1_PIN_GPIO1 (0x0 << 15)
+#define RT5651_GP1_PIN_IRQ (0x1 << 15)
+#define RT5651_GP2_PIN_MASK (0x1 << 14)
+#define RT5651_GP2_PIN_SFT 14
+#define RT5651_GP2_PIN_GPIO2 (0x0 << 14)
+#define RT5651_GP2_PIN_DMIC1_SCL (0x1 << 14)
+#define RT5651_GPIO_M_MASK (0x1 << 9)
+#define RT5651_GPIO_M_SFT 9
+#define RT5651_GPIO_M_FLT (0x0 << 9)
+#define RT5651_GPIO_M_PH (0x1 << 9)
+#define RT5651_I2S2_SEL_MASK (0x1 << 8)
+#define RT5651_I2S2_SEL_SFT 8
+#define RT5651_I2S2_SEL_I2S (0x0 << 8)
+#define RT5651_I2S2_SEL_GPIO (0x1 << 8)
+#define RT5651_GP5_PIN_MASK (0x1 << 7)
+#define RT5651_GP5_PIN_SFT 7
+#define RT5651_GP5_PIN_GPIO5 (0x0 << 7)
+#define RT5651_GP5_PIN_IRQ (0x1 << 7)
+#define RT5651_GP6_PIN_MASK (0x1 << 6)
+#define RT5651_GP6_PIN_SFT 6
+#define RT5651_GP6_PIN_GPIO6 (0x0 << 6)
+#define RT5651_GP6_PIN_DMIC_SDA (0x1 << 6)
+#define RT5651_GP7_PIN_MASK (0x1 << 5)
+#define RT5651_GP7_PIN_SFT 5
+#define RT5651_GP7_PIN_GPIO7 (0x0 << 5)
+#define RT5651_GP7_PIN_IRQ (0x1 << 5)
+#define RT5651_GP8_PIN_MASK (0x1 << 4)
+#define RT5651_GP8_PIN_SFT 4
+#define RT5651_GP8_PIN_GPIO8 (0x0 << 4)
+#define RT5651_GP8_PIN_DMIC_SDA (0x1 << 4)
+#define RT5651_GPIO_PDM_SEL_MASK (0x1 << 3)
+#define RT5651_GPIO_PDM_SEL_SFT 3
+#define RT5651_GPIO_PDM_SEL_GPIO (0x0 << 3)
+#define RT5651_GPIO_PDM_SEL_PDM (0x1 << 3)
+
+/* GPIO Control 2 (0xc1) */
+#define RT5651_GP5_DR_MASK (0x1 << 14)
+#define RT5651_GP5_DR_SFT 14
+#define RT5651_GP5_DR_IN (0x0 << 14)
+#define RT5651_GP5_DR_OUT (0x1 << 14)
+#define RT5651_GP5_OUT_MASK (0x1 << 13)
+#define RT5651_GP5_OUT_SFT 13
+#define RT5651_GP5_OUT_LO (0x0 << 13)
+#define RT5651_GP5_OUT_HI (0x1 << 13)
+#define RT5651_GP5_P_MASK (0x1 << 12)
+#define RT5651_GP5_P_SFT 12
+#define RT5651_GP5_P_NOR (0x0 << 12)
+#define RT5651_GP5_P_INV (0x1 << 12)
+#define RT5651_GP4_DR_MASK (0x1 << 11)
+#define RT5651_GP4_DR_SFT 11
+#define RT5651_GP4_DR_IN (0x0 << 11)
+#define RT5651_GP4_DR_OUT (0x1 << 11)
+#define RT5651_GP4_OUT_MASK (0x1 << 10)
+#define RT5651_GP4_OUT_SFT 10
+#define RT5651_GP4_OUT_LO (0x0 << 10)
+#define RT5651_GP4_OUT_HI (0x1 << 10)
+#define RT5651_GP4_P_MASK (0x1 << 9)
+#define RT5651_GP4_P_SFT 9
+#define RT5651_GP4_P_NOR (0x0 << 9)
+#define RT5651_GP4_P_INV (0x1 << 9)
+#define RT5651_GP3_DR_MASK (0x1 << 8)
+#define RT5651_GP3_DR_SFT 8
+#define RT5651_GP3_DR_IN (0x0 << 8)
+#define RT5651_GP3_DR_OUT (0x1 << 8)
+#define RT5651_GP3_OUT_MASK (0x1 << 7)
+#define RT5651_GP3_OUT_SFT 7
+#define RT5651_GP3_OUT_LO (0x0 << 7)
+#define RT5651_GP3_OUT_HI (0x1 << 7)
+#define RT5651_GP3_P_MASK (0x1 << 6)
+#define RT5651_GP3_P_SFT 6
+#define RT5651_GP3_P_NOR (0x0 << 6)
+#define RT5651_GP3_P_INV (0x1 << 6)
+#define RT5651_GP2_DR_MASK (0x1 << 5)
+#define RT5651_GP2_DR_SFT 5
+#define RT5651_GP2_DR_IN (0x0 << 5)
+#define RT5651_GP2_DR_OUT (0x1 << 5)
+#define RT5651_GP2_OUT_MASK (0x1 << 4)
+#define RT5651_GP2_OUT_SFT 4
+#define RT5651_GP2_OUT_LO (0x0 << 4)
+#define RT5651_GP2_OUT_HI (0x1 << 4)
+#define RT5651_GP2_P_MASK (0x1 << 3)
+#define RT5651_GP2_P_SFT 3
+#define RT5651_GP2_P_NOR (0x0 << 3)
+#define RT5651_GP2_P_INV (0x1 << 3)
+#define RT5651_GP1_DR_MASK (0x1 << 2)
+#define RT5651_GP1_DR_SFT 2
+#define RT5651_GP1_DR_IN (0x0 << 2)
+#define RT5651_GP1_DR_OUT (0x1 << 2)
+#define RT5651_GP1_OUT_MASK (0x1 << 1)
+#define RT5651_GP1_OUT_SFT 1
+#define RT5651_GP1_OUT_LO (0x0 << 1)
+#define RT5651_GP1_OUT_HI (0x1 << 1)
+#define RT5651_GP1_P_MASK (0x1)
+#define RT5651_GP1_P_SFT 0
+#define RT5651_GP1_P_NOR (0x0)
+#define RT5651_GP1_P_INV (0x1)
+
+/* GPIO Control 3 (0xc2) */
+#define RT5651_GP8_DR_MASK (0x1 << 8)
+#define RT5651_GP8_DR_SFT 8
+#define RT5651_GP8_DR_IN (0x0 << 8)
+#define RT5651_GP8_DR_OUT (0x1 << 8)
+#define RT5651_GP8_OUT_MASK (0x1 << 7)
+#define RT5651_GP8_OUT_SFT 7
+#define RT5651_GP8_OUT_LO (0x0 << 7)
+#define RT5651_GP8_OUT_HI (0x1 << 7)
+#define RT5651_GP8_P_MASK (0x1 << 6)
+#define RT5651_GP8_P_SFT 6
+#define RT5651_GP8_P_NOR (0x0 << 6)
+#define RT5651_GP8_P_INV (0x1 << 6)
+#define RT5651_GP7_DR_MASK (0x1 << 5)
+#define RT5651_GP7_DR_SFT 5
+#define RT5651_GP7_DR_IN (0x0 << 5)
+#define RT5651_GP7_DR_OUT (0x1 << 5)
+#define RT5651_GP7_OUT_MASK (0x1 << 4)
+#define RT5651_GP7_OUT_SFT 4
+#define RT5651_GP7_OUT_LO (0x0 << 4)
+#define RT5651_GP7_OUT_HI (0x1 << 4)
+#define RT5651_GP7_P_MASK (0x1 << 3)
+#define RT5651_GP7_P_SFT 3
+#define RT5651_GP7_P_NOR (0x0 << 3)
+#define RT5651_GP7_P_INV (0x1 << 3)
+#define RT5651_GP6_DR_MASK (0x1 << 2)
+#define RT5651_GP6_DR_SFT 2
+#define RT5651_GP6_DR_IN (0x0 << 2)
+#define RT5651_GP6_DR_OUT (0x1 << 2)
+#define RT5651_GP6_OUT_MASK (0x1 << 1)
+#define RT5651_GP6_OUT_SFT 1
+#define RT5651_GP6_OUT_LO (0x0 << 1)
+#define RT5651_GP6_OUT_HI (0x1 << 1)
+#define RT5651_GP6_P_MASK (0x1)
+#define RT5651_GP6_P_SFT 0
+#define RT5651_GP6_P_NOR (0x0)
+#define RT5651_GP6_P_INV (0x1)
+
+/* Scramble Control (0xce) */
+#define RT5651_SCB_SWAP_MASK (0x1 << 15)
+#define RT5651_SCB_SWAP_SFT 15
+#define RT5651_SCB_SWAP_DIS (0x0 << 15)
+#define RT5651_SCB_SWAP_EN (0x1 << 15)
+#define RT5651_SCB_MASK (0x1 << 14)
+#define RT5651_SCB_SFT 14
+#define RT5651_SCB_DIS (0x0 << 14)
+#define RT5651_SCB_EN (0x1 << 14)
+
+/* Baseback Control (0xcf) */
+#define RT5651_BB_MASK (0x1 << 15)
+#define RT5651_BB_SFT 15
+#define RT5651_BB_DIS (0x0 << 15)
+#define RT5651_BB_EN (0x1 << 15)
+#define RT5651_BB_CT_MASK (0x7 << 12)
+#define RT5651_BB_CT_SFT 12
+#define RT5651_BB_CT_A (0x0 << 12)
+#define RT5651_BB_CT_B (0x1 << 12)
+#define RT5651_BB_CT_C (0x2 << 12)
+#define RT5651_BB_CT_D (0x3 << 12)
+#define RT5651_M_BB_L_MASK (0x1 << 9)
+#define RT5651_M_BB_L_SFT 9
+#define RT5651_M_BB_R_MASK (0x1 << 8)
+#define RT5651_M_BB_R_SFT 8
+#define RT5651_M_BB_HPF_L_MASK (0x1 << 7)
+#define RT5651_M_BB_HPF_L_SFT 7
+#define RT5651_M_BB_HPF_R_MASK (0x1 << 6)
+#define RT5651_M_BB_HPF_R_SFT 6
+#define RT5651_G_BB_BST_MASK (0x3f)
+#define RT5651_G_BB_BST_SFT 0
+
+/* MP3 Plus Control 1 (0xd0) */
+#define RT5651_M_MP3_L_MASK (0x1 << 15)
+#define RT5651_M_MP3_L_SFT 15
+#define RT5651_M_MP3_R_MASK (0x1 << 14)
+#define RT5651_M_MP3_R_SFT 14
+#define RT5651_M_MP3_MASK (0x1 << 13)
+#define RT5651_M_MP3_SFT 13
+#define RT5651_M_MP3_DIS (0x0 << 13)
+#define RT5651_M_MP3_EN (0x1 << 13)
+#define RT5651_EG_MP3_MASK (0x1f << 8)
+#define RT5651_EG_MP3_SFT 8
+#define RT5651_MP3_HLP_MASK (0x1 << 7)
+#define RT5651_MP3_HLP_SFT 7
+#define RT5651_MP3_HLP_DIS (0x0 << 7)
+#define RT5651_MP3_HLP_EN (0x1 << 7)
+#define RT5651_M_MP3_ORG_L_MASK (0x1 << 6)
+#define RT5651_M_MP3_ORG_L_SFT 6
+#define RT5651_M_MP3_ORG_R_MASK (0x1 << 5)
+#define RT5651_M_MP3_ORG_R_SFT 5
+
+/* MP3 Plus Control 2 (0xd1) */
+#define RT5651_MP3_WT_MASK (0x1 << 13)
+#define RT5651_MP3_WT_SFT 13
+#define RT5651_MP3_WT_1_4 (0x0 << 13)
+#define RT5651_MP3_WT_1_2 (0x1 << 13)
+#define RT5651_OG_MP3_MASK (0x1f << 8)
+#define RT5651_OG_MP3_SFT 8
+#define RT5651_HG_MP3_MASK (0x3f)
+#define RT5651_HG_MP3_SFT 0
+
+/* 3D HP Control 1 (0xd2) */
+#define RT5651_3D_CF_MASK (0x1 << 15)
+#define RT5651_3D_CF_SFT 15
+#define RT5651_3D_CF_DIS (0x0 << 15)
+#define RT5651_3D_CF_EN (0x1 << 15)
+#define RT5651_3D_HP_MASK (0x1 << 14)
+#define RT5651_3D_HP_SFT 14
+#define RT5651_3D_HP_DIS (0x0 << 14)
+#define RT5651_3D_HP_EN (0x1 << 14)
+#define RT5651_3D_BT_MASK (0x1 << 13)
+#define RT5651_3D_BT_SFT 13
+#define RT5651_3D_BT_DIS (0x0 << 13)
+#define RT5651_3D_BT_EN (0x1 << 13)
+#define RT5651_3D_1F_MIX_MASK (0x3 << 11)
+#define RT5651_3D_1F_MIX_SFT 11
+#define RT5651_3D_HP_M_MASK (0x1 << 10)
+#define RT5651_3D_HP_M_SFT 10
+#define RT5651_3D_HP_M_SUR (0x0 << 10)
+#define RT5651_3D_HP_M_FRO (0x1 << 10)
+#define RT5651_M_3D_HRTF_MASK (0x1 << 9)
+#define RT5651_M_3D_HRTF_SFT 9
+#define RT5651_M_3D_D2H_MASK (0x1 << 8)
+#define RT5651_M_3D_D2H_SFT 8
+#define RT5651_M_3D_D2R_MASK (0x1 << 7)
+#define RT5651_M_3D_D2R_SFT 7
+#define RT5651_M_3D_REVB_MASK (0x1 << 6)
+#define RT5651_M_3D_REVB_SFT 6
+
+/* Adjustable high pass filter control 1 (0xd3) */
+#define RT5651_2ND_HPF_MASK (0x1 << 15)
+#define RT5651_2ND_HPF_SFT 15
+#define RT5651_2ND_HPF_DIS (0x0 << 15)
+#define RT5651_2ND_HPF_EN (0x1 << 15)
+#define RT5651_HPF_CF_L_MASK (0x7 << 12)
+#define RT5651_HPF_CF_L_SFT 12
+#define RT5651_HPF_CF_R_MASK (0x7 << 8)
+#define RT5651_HPF_CF_R_SFT 8
+#define RT5651_ZD_T_MASK (0x3 << 6)
+#define RT5651_ZD_T_SFT 6
+#define RT5651_ZD_F_MASK (0x3 << 4)
+#define RT5651_ZD_F_SFT 4
+#define RT5651_ZD_F_IM (0x0 << 4)
+#define RT5651_ZD_F_ZC_IM (0x1 << 4)
+#define RT5651_ZD_F_ZC_IOD (0x2 << 4)
+#define RT5651_ZD_F_UN (0x3 << 4)
+
+/* Adjustable high pass filter control 2 (0xd4) */
+#define RT5651_HPF_CF_L_NUM_MASK (0x3f << 8)
+#define RT5651_HPF_CF_L_NUM_SFT 8
+#define RT5651_HPF_CF_R_NUM_MASK (0x3f)
+#define RT5651_HPF_CF_R_NUM_SFT 0
+
+/* HP calibration control and Amp detection (0xd6) */
+#define RT5651_SI_DAC_MASK (0x1 << 11)
+#define RT5651_SI_DAC_SFT 11
+#define RT5651_SI_DAC_AUTO (0x0 << 11)
+#define RT5651_SI_DAC_TEST (0x1 << 11)
+#define RT5651_DC_CAL_M_MASK (0x1 << 10)
+#define RT5651_DC_CAL_M_SFT 10
+#define RT5651_DC_CAL_M_NOR (0x0 << 10)
+#define RT5651_DC_CAL_M_CAL (0x1 << 10)
+#define RT5651_DC_CAL_MASK (0x1 << 9)
+#define RT5651_DC_CAL_SFT 9
+#define RT5651_DC_CAL_DIS (0x0 << 9)
+#define RT5651_DC_CAL_EN (0x1 << 9)
+#define RT5651_HPD_RCV_MASK (0x7 << 6)
+#define RT5651_HPD_RCV_SFT 6
+#define RT5651_HPD_PS_MASK (0x1 << 5)
+#define RT5651_HPD_PS_SFT 5
+#define RT5651_HPD_PS_DIS (0x0 << 5)
+#define RT5651_HPD_PS_EN (0x1 << 5)
+#define RT5651_CAL_M_MASK (0x1 << 4)
+#define RT5651_CAL_M_SFT 4
+#define RT5651_CAL_M_DEP (0x0 << 4)
+#define RT5651_CAL_M_CAL (0x1 << 4)
+#define RT5651_CAL_MASK (0x1 << 3)
+#define RT5651_CAL_SFT 3
+#define RT5651_CAL_DIS (0x0 << 3)
+#define RT5651_CAL_EN (0x1 << 3)
+#define RT5651_CAL_TEST_MASK (0x1 << 2)
+#define RT5651_CAL_TEST_SFT 2
+#define RT5651_CAL_TEST_DIS (0x0 << 2)
+#define RT5651_CAL_TEST_EN (0x1 << 2)
+#define RT5651_CAL_P_MASK (0x3)
+#define RT5651_CAL_P_SFT 0
+#define RT5651_CAL_P_NONE (0x0)
+#define RT5651_CAL_P_CAL (0x1)
+#define RT5651_CAL_P_DAC_CAL (0x2)
+
+/* Soft volume and zero cross control 1 (0xd9) */
+#define RT5651_SV_MASK (0x1 << 15)
+#define RT5651_SV_SFT 15
+#define RT5651_SV_DIS (0x0 << 15)
+#define RT5651_SV_EN (0x1 << 15)
+#define RT5651_OUT_SV_MASK (0x1 << 13)
+#define RT5651_OUT_SV_SFT 13
+#define RT5651_OUT_SV_DIS (0x0 << 13)
+#define RT5651_OUT_SV_EN (0x1 << 13)
+#define RT5651_HP_SV_MASK (0x1 << 12)
+#define RT5651_HP_SV_SFT 12
+#define RT5651_HP_SV_DIS (0x0 << 12)
+#define RT5651_HP_SV_EN (0x1 << 12)
+#define RT5651_ZCD_DIG_MASK (0x1 << 11)
+#define RT5651_ZCD_DIG_SFT 11
+#define RT5651_ZCD_DIG_DIS (0x0 << 11)
+#define RT5651_ZCD_DIG_EN (0x1 << 11)
+#define RT5651_ZCD_MASK (0x1 << 10)
+#define RT5651_ZCD_SFT 10
+#define RT5651_ZCD_PD (0x0 << 10)
+#define RT5651_ZCD_PU (0x1 << 10)
+#define RT5651_M_ZCD_MASK (0x3f << 4)
+#define RT5651_M_ZCD_SFT 4
+#define RT5651_M_ZCD_OM_L (0x1 << 7)
+#define RT5651_M_ZCD_OM_R (0x1 << 6)
+#define RT5651_M_ZCD_RM_L (0x1 << 5)
+#define RT5651_M_ZCD_RM_R (0x1 << 4)
+#define RT5651_SV_DLY_MASK (0xf)
+#define RT5651_SV_DLY_SFT 0
+
+/* Soft volume and zero cross control 2 (0xda) */
+#define RT5651_ZCD_HP_MASK (0x1 << 15)
+#define RT5651_ZCD_HP_SFT 15
+#define RT5651_ZCD_HP_DIS (0x0 << 15)
+#define RT5651_ZCD_HP_EN (0x1 << 15)
+
+/* Digital Misc Control (0xfa) */
+#define RT5651_I2S2_MS_SP_MASK (0x1 << 8)
+#define RT5651_I2S2_MS_SP_SEL 8
+#define RT5651_I2S2_MS_SP_64 (0x0 << 8)
+#define RT5651_I2S2_MS_SP_50 (0x1 << 8)
+#define RT5651_CLK_DET_EN (0x1 << 3)
+#define RT5651_CLK_DET_EN_SFT 3
+#define RT5651_AMP_DET_EN (0x1 << 1)
+#define RT5651_AMP_DET_EN_SFT 1
+#define RT5651_D_GATE_EN (0x1)
+#define RT5651_D_GATE_EN_SFT 0
+
+/* Codec Private Register definition */
+/* 3D Speaker Control (0x63) */
+#define RT5651_3D_SPK_MASK (0x1 << 15)
+#define RT5651_3D_SPK_SFT 15
+#define RT5651_3D_SPK_DIS (0x0 << 15)
+#define RT5651_3D_SPK_EN (0x1 << 15)
+#define RT5651_3D_SPK_M_MASK (0x3 << 13)
+#define RT5651_3D_SPK_M_SFT 13
+#define RT5651_3D_SPK_CG_MASK (0x1f << 8)
+#define RT5651_3D_SPK_CG_SFT 8
+#define RT5651_3D_SPK_SG_MASK (0x1f)
+#define RT5651_3D_SPK_SG_SFT 0
+
+/* Wind Noise Detection Control 1 (0x6c) */
+#define RT5651_WND_MASK (0x1 << 15)
+#define RT5651_WND_SFT 15
+#define RT5651_WND_DIS (0x0 << 15)
+#define RT5651_WND_EN (0x1 << 15)
+
+/* Wind Noise Detection Control 2 (0x6d) */
+#define RT5651_WND_FC_NW_MASK (0x3f << 10)
+#define RT5651_WND_FC_NW_SFT 10
+#define RT5651_WND_FC_WK_MASK (0x3f << 4)
+#define RT5651_WND_FC_WK_SFT 4
+
+/* Wind Noise Detection Control 3 (0x6e) */
+#define RT5651_HPF_FC_MASK (0x3f << 6)
+#define RT5651_HPF_FC_SFT 6
+#define RT5651_WND_FC_ST_MASK (0x3f)
+#define RT5651_WND_FC_ST_SFT 0
+
+/* Wind Noise Detection Control 4 (0x6f) */
+#define RT5651_WND_TH_LO_MASK (0x3ff)
+#define RT5651_WND_TH_LO_SFT 0
+
+/* Wind Noise Detection Control 5 (0x70) */
+#define RT5651_WND_TH_HI_MASK (0x3ff)
+#define RT5651_WND_TH_HI_SFT 0
+
+/* Wind Noise Detection Control 8 (0x73) */
+#define RT5651_WND_WIND_MASK (0x1 << 13) /* Read-Only */
+#define RT5651_WND_WIND_SFT 13
+#define RT5651_WND_STRONG_MASK (0x1 << 12) /* Read-Only */
+#define RT5651_WND_STRONG_SFT 12
+enum {
+ RT5651_NO_WIND,
+ RT5651_BREEZE,
+ RT5651_STORM,
+};
+
+/* Dipole Speaker Interface (0x75) */
+#define RT5651_DP_ATT_MASK (0x3 << 14)
+#define RT5651_DP_ATT_SFT 14
+#define RT5651_DP_SPK_MASK (0x1 << 10)
+#define RT5651_DP_SPK_SFT 10
+#define RT5651_DP_SPK_DIS (0x0 << 10)
+#define RT5651_DP_SPK_EN (0x1 << 10)
+
+/* EQ Pre Volume Control (0xb3) */
+#define RT5651_EQ_PRE_VOL_MASK (0xffff)
+#define RT5651_EQ_PRE_VOL_SFT 0
+
+/* EQ Post Volume Control (0xb4) */
+#define RT5651_EQ_PST_VOL_MASK (0xffff)
+#define RT5651_EQ_PST_VOL_SFT 0
+
+/* System Clock Source */
+enum {
+ RT5651_SCLK_S_MCLK,
+ RT5651_SCLK_S_PLL1,
+ RT5651_SCLK_S_RCCLK,
+};
+
+/* PLL1 Source */
+enum {
+ RT5651_PLL1_S_MCLK,
+ RT5651_PLL1_S_BCLK1,
+ RT5651_PLL1_S_BCLK2,
+};
+
+enum {
+ RT5651_AIF1,
+ RT5651_AIF2,
+ RT5651_AIFS,
+};
+
+struct rt5651_pll_code {
+ bool m_bp; /* Indicates bypass m code or not. */
+ int m_code;
+ int n_code;
+ int k_code;
+};
+
+struct rt5651_priv {
+ struct snd_soc_codec *codec;
+ struct rt5651_platform_data pdata;
+ struct regmap *regmap;
+
+ int sysclk;
+ int sysclk_src;
+ int lrck[RT5651_AIFS];
+ int bclk[RT5651_AIFS];
+ int master[RT5651_AIFS];
+
+ int pll_src;
+ int pll_in;
+ int pll_out;
+
+ int dmic_en;
+ bool hp_mute;
+};
+
+#endif /* __RT5651_H__ */
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c
new file mode 100644
index 00000000000..833231e2734
--- /dev/null
+++ b/sound/soc/codecs/rt5677.c
@@ -0,0 +1,3498 @@
+/*
+ * rt5677.c -- RT5677 ALSA SoC audio codec driver
+ *
+ * Copyright 2013 Realtek Semiconductor Corp.
+ * Author: Oder Chiou <oder_chiou@realtek.com>
+ *
+ * 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 <linux/fs.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <sound/core.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 "rt5677.h"
+
+#define RT5677_DEVICE_ID 0x6327
+
+#define RT5677_PR_RANGE_BASE (0xff + 1)
+#define RT5677_PR_SPACING 0x100
+
+#define RT5677_PR_BASE (RT5677_PR_RANGE_BASE + (0 * RT5677_PR_SPACING))
+
+static const struct regmap_range_cfg rt5677_ranges[] = {
+ {
+ .name = "PR",
+ .range_min = RT5677_PR_BASE,
+ .range_max = RT5677_PR_BASE + 0xfd,
+ .selector_reg = RT5677_PRIV_INDEX,
+ .selector_mask = 0xff,
+ .selector_shift = 0x0,
+ .window_start = RT5677_PRIV_DATA,
+ .window_len = 0x1,
+ },
+};
+
+static const struct reg_default init_list[] = {
+ {RT5677_PR_BASE + 0x3d, 0x364d},
+ {RT5677_PR_BASE + 0x17, 0x4fc0},
+ {RT5677_PR_BASE + 0x13, 0x0312},
+ {RT5677_PR_BASE + 0x1e, 0x0000},
+ {RT5677_PR_BASE + 0x12, 0x0eaa},
+ {RT5677_PR_BASE + 0x14, 0x018a},
+};
+#define RT5677_INIT_REG_LEN ARRAY_SIZE(init_list)
+
+static const struct reg_default rt5677_reg[] = {
+ {RT5677_RESET , 0x0000},
+ {RT5677_LOUT1 , 0xa800},
+ {RT5677_IN1 , 0x0000},
+ {RT5677_MICBIAS , 0x0000},
+ {RT5677_SLIMBUS_PARAM , 0x0000},
+ {RT5677_SLIMBUS_RX , 0x0000},
+ {RT5677_SLIMBUS_CTRL , 0x0000},
+ {RT5677_SIDETONE_CTRL , 0x000b},
+ {RT5677_ANA_DAC1_2_3_SRC , 0x0000},
+ {RT5677_IF_DSP_DAC3_4_MIXER , 0x1111},
+ {RT5677_DAC4_DIG_VOL , 0xafaf},
+ {RT5677_DAC3_DIG_VOL , 0xafaf},
+ {RT5677_DAC1_DIG_VOL , 0xafaf},
+ {RT5677_DAC2_DIG_VOL , 0xafaf},
+ {RT5677_IF_DSP_DAC2_MIXER , 0x0011},
+ {RT5677_STO1_ADC_DIG_VOL , 0x2f2f},
+ {RT5677_MONO_ADC_DIG_VOL , 0x2f2f},
+ {RT5677_STO1_2_ADC_BST , 0x0000},
+ {RT5677_STO2_ADC_DIG_VOL , 0x2f2f},
+ {RT5677_ADC_BST_CTRL2 , 0x0000},
+ {RT5677_STO3_4_ADC_BST , 0x0000},
+ {RT5677_STO3_ADC_DIG_VOL , 0x2f2f},
+ {RT5677_STO4_ADC_DIG_VOL , 0x2f2f},
+ {RT5677_STO4_ADC_MIXER , 0xd4c0},
+ {RT5677_STO3_ADC_MIXER , 0xd4c0},
+ {RT5677_STO2_ADC_MIXER , 0xd4c0},
+ {RT5677_STO1_ADC_MIXER , 0xd4c0},
+ {RT5677_MONO_ADC_MIXER , 0xd4d1},
+ {RT5677_ADC_IF_DSP_DAC1_MIXER , 0x8080},
+ {RT5677_STO1_DAC_MIXER , 0xaaaa},
+ {RT5677_MONO_DAC_MIXER , 0xaaaa},
+ {RT5677_DD1_MIXER , 0xaaaa},
+ {RT5677_DD2_MIXER , 0xaaaa},
+ {RT5677_IF3_DATA , 0x0000},
+ {RT5677_IF4_DATA , 0x0000},
+ {RT5677_PDM_OUT_CTRL , 0x8888},
+ {RT5677_PDM_DATA_CTRL1 , 0x0000},
+ {RT5677_PDM_DATA_CTRL2 , 0x0000},
+ {RT5677_PDM1_DATA_CTRL2 , 0x0000},
+ {RT5677_PDM1_DATA_CTRL3 , 0x0000},
+ {RT5677_PDM1_DATA_CTRL4 , 0x0000},
+ {RT5677_PDM2_DATA_CTRL2 , 0x0000},
+ {RT5677_PDM2_DATA_CTRL3 , 0x0000},
+ {RT5677_PDM2_DATA_CTRL4 , 0x0000},
+ {RT5677_TDM1_CTRL1 , 0x0300},
+ {RT5677_TDM1_CTRL2 , 0x0000},
+ {RT5677_TDM1_CTRL3 , 0x4000},
+ {RT5677_TDM1_CTRL4 , 0x0123},
+ {RT5677_TDM1_CTRL5 , 0x4567},
+ {RT5677_TDM2_CTRL1 , 0x0300},
+ {RT5677_TDM2_CTRL2 , 0x0000},
+ {RT5677_TDM2_CTRL3 , 0x4000},
+ {RT5677_TDM2_CTRL4 , 0x0123},
+ {RT5677_TDM2_CTRL5 , 0x4567},
+ {RT5677_I2C_MASTER_CTRL1 , 0x0001},
+ {RT5677_I2C_MASTER_CTRL2 , 0x0000},
+ {RT5677_I2C_MASTER_CTRL3 , 0x0000},
+ {RT5677_I2C_MASTER_CTRL4 , 0x0000},
+ {RT5677_I2C_MASTER_CTRL5 , 0x0000},
+ {RT5677_I2C_MASTER_CTRL6 , 0x0000},
+ {RT5677_I2C_MASTER_CTRL7 , 0x0000},
+ {RT5677_I2C_MASTER_CTRL8 , 0x0000},
+ {RT5677_DMIC_CTRL1 , 0x1505},
+ {RT5677_DMIC_CTRL2 , 0x0055},
+ {RT5677_HAP_GENE_CTRL1 , 0x0111},
+ {RT5677_HAP_GENE_CTRL2 , 0x0064},
+ {RT5677_HAP_GENE_CTRL3 , 0xef0e},
+ {RT5677_HAP_GENE_CTRL4 , 0xf0f0},
+ {RT5677_HAP_GENE_CTRL5 , 0xef0e},
+ {RT5677_HAP_GENE_CTRL6 , 0xf0f0},
+ {RT5677_HAP_GENE_CTRL7 , 0xef0e},
+ {RT5677_HAP_GENE_CTRL8 , 0xf0f0},
+ {RT5677_HAP_GENE_CTRL9 , 0xf000},
+ {RT5677_HAP_GENE_CTRL10 , 0x0000},
+ {RT5677_PWR_DIG1 , 0x0000},
+ {RT5677_PWR_DIG2 , 0x0000},
+ {RT5677_PWR_ANLG1 , 0x0055},
+ {RT5677_PWR_ANLG2 , 0x0000},
+ {RT5677_PWR_DSP1 , 0x0001},
+ {RT5677_PWR_DSP_ST , 0x0000},
+ {RT5677_PWR_DSP2 , 0x0000},
+ {RT5677_ADC_DAC_HPF_CTRL1 , 0x0e00},
+ {RT5677_PRIV_INDEX , 0x0000},
+ {RT5677_PRIV_DATA , 0x0000},
+ {RT5677_I2S4_SDP , 0x8000},
+ {RT5677_I2S1_SDP , 0x8000},
+ {RT5677_I2S2_SDP , 0x8000},
+ {RT5677_I2S3_SDP , 0x8000},
+ {RT5677_CLK_TREE_CTRL1 , 0x1111},
+ {RT5677_CLK_TREE_CTRL2 , 0x1111},
+ {RT5677_CLK_TREE_CTRL3 , 0x0000},
+ {RT5677_PLL1_CTRL1 , 0x0000},
+ {RT5677_PLL1_CTRL2 , 0x0000},
+ {RT5677_PLL2_CTRL1 , 0x0c60},
+ {RT5677_PLL2_CTRL2 , 0x2000},
+ {RT5677_GLB_CLK1 , 0x0000},
+ {RT5677_GLB_CLK2 , 0x0000},
+ {RT5677_ASRC_1 , 0x0000},
+ {RT5677_ASRC_2 , 0x0000},
+ {RT5677_ASRC_3 , 0x0000},
+ {RT5677_ASRC_4 , 0x0000},
+ {RT5677_ASRC_5 , 0x0000},
+ {RT5677_ASRC_6 , 0x0000},
+ {RT5677_ASRC_7 , 0x0000},
+ {RT5677_ASRC_8 , 0x0000},
+ {RT5677_ASRC_9 , 0x0000},
+ {RT5677_ASRC_10 , 0x0000},
+ {RT5677_ASRC_11 , 0x0000},
+ {RT5677_ASRC_12 , 0x0008},
+ {RT5677_ASRC_13 , 0x0000},
+ {RT5677_ASRC_14 , 0x0000},
+ {RT5677_ASRC_15 , 0x0000},
+ {RT5677_ASRC_16 , 0x0000},
+ {RT5677_ASRC_17 , 0x0000},
+ {RT5677_ASRC_18 , 0x0000},
+ {RT5677_ASRC_19 , 0x0000},
+ {RT5677_ASRC_20 , 0x0000},
+ {RT5677_ASRC_21 , 0x000c},
+ {RT5677_ASRC_22 , 0x0000},
+ {RT5677_ASRC_23 , 0x0000},
+ {RT5677_VAD_CTRL1 , 0x2184},
+ {RT5677_VAD_CTRL2 , 0x010a},
+ {RT5677_VAD_CTRL3 , 0x0aea},
+ {RT5677_VAD_CTRL4 , 0x000c},
+ {RT5677_VAD_CTRL5 , 0x0000},
+ {RT5677_DSP_INB_CTRL1 , 0x0000},
+ {RT5677_DSP_INB_CTRL2 , 0x0000},
+ {RT5677_DSP_IN_OUTB_CTRL , 0x0000},
+ {RT5677_DSP_OUTB0_1_DIG_VOL , 0x2f2f},
+ {RT5677_DSP_OUTB2_3_DIG_VOL , 0x2f2f},
+ {RT5677_DSP_OUTB4_5_DIG_VOL , 0x2f2f},
+ {RT5677_DSP_OUTB6_7_DIG_VOL , 0x2f2f},
+ {RT5677_ADC_EQ_CTRL1 , 0x6000},
+ {RT5677_ADC_EQ_CTRL2 , 0x0000},
+ {RT5677_EQ_CTRL1 , 0xc000},
+ {RT5677_EQ_CTRL2 , 0x0000},
+ {RT5677_EQ_CTRL3 , 0x0000},
+ {RT5677_SOFT_VOL_ZERO_CROSS1 , 0x0009},
+ {RT5677_JD_CTRL1 , 0x0000},
+ {RT5677_JD_CTRL2 , 0x0000},
+ {RT5677_JD_CTRL3 , 0x0000},
+ {RT5677_IRQ_CTRL1 , 0x0000},
+ {RT5677_IRQ_CTRL2 , 0x0000},
+ {RT5677_GPIO_ST , 0x0000},
+ {RT5677_GPIO_CTRL1 , 0x0000},
+ {RT5677_GPIO_CTRL2 , 0x0000},
+ {RT5677_GPIO_CTRL3 , 0x0000},
+ {RT5677_STO1_ADC_HI_FILTER1 , 0xb320},
+ {RT5677_STO1_ADC_HI_FILTER2 , 0x0000},
+ {RT5677_MONO_ADC_HI_FILTER1 , 0xb300},
+ {RT5677_MONO_ADC_HI_FILTER2 , 0x0000},
+ {RT5677_STO2_ADC_HI_FILTER1 , 0xb300},
+ {RT5677_STO2_ADC_HI_FILTER2 , 0x0000},
+ {RT5677_STO3_ADC_HI_FILTER1 , 0xb300},
+ {RT5677_STO3_ADC_HI_FILTER2 , 0x0000},
+ {RT5677_STO4_ADC_HI_FILTER1 , 0xb300},
+ {RT5677_STO4_ADC_HI_FILTER2 , 0x0000},
+ {RT5677_MB_DRC_CTRL1 , 0x0f20},
+ {RT5677_DRC1_CTRL1 , 0x001f},
+ {RT5677_DRC1_CTRL2 , 0x020c},
+ {RT5677_DRC1_CTRL3 , 0x1f00},
+ {RT5677_DRC1_CTRL4 , 0x0000},
+ {RT5677_DRC1_CTRL5 , 0x0000},
+ {RT5677_DRC1_CTRL6 , 0x0029},
+ {RT5677_DRC2_CTRL1 , 0x001f},
+ {RT5677_DRC2_CTRL2 , 0x020c},
+ {RT5677_DRC2_CTRL3 , 0x1f00},
+ {RT5677_DRC2_CTRL4 , 0x0000},
+ {RT5677_DRC2_CTRL5 , 0x0000},
+ {RT5677_DRC2_CTRL6 , 0x0029},
+ {RT5677_DRC1_HL_CTRL1 , 0x8000},
+ {RT5677_DRC1_HL_CTRL2 , 0x0200},
+ {RT5677_DRC2_HL_CTRL1 , 0x8000},
+ {RT5677_DRC2_HL_CTRL2 , 0x0200},
+ {RT5677_DSP_INB1_SRC_CTRL1 , 0x5800},
+ {RT5677_DSP_INB1_SRC_CTRL2 , 0x0000},
+ {RT5677_DSP_INB1_SRC_CTRL3 , 0x0000},
+ {RT5677_DSP_INB1_SRC_CTRL4 , 0x0800},
+ {RT5677_DSP_INB2_SRC_CTRL1 , 0x5800},
+ {RT5677_DSP_INB2_SRC_CTRL2 , 0x0000},
+ {RT5677_DSP_INB2_SRC_CTRL3 , 0x0000},
+ {RT5677_DSP_INB2_SRC_CTRL4 , 0x0800},
+ {RT5677_DSP_INB3_SRC_CTRL1 , 0x5800},
+ {RT5677_DSP_INB3_SRC_CTRL2 , 0x0000},
+ {RT5677_DSP_INB3_SRC_CTRL3 , 0x0000},
+ {RT5677_DSP_INB3_SRC_CTRL4 , 0x0800},
+ {RT5677_DSP_OUTB1_SRC_CTRL1 , 0x5800},
+ {RT5677_DSP_OUTB1_SRC_CTRL2 , 0x0000},
+ {RT5677_DSP_OUTB1_SRC_CTRL3 , 0x0000},
+ {RT5677_DSP_OUTB1_SRC_CTRL4 , 0x0800},
+ {RT5677_DSP_OUTB2_SRC_CTRL1 , 0x5800},
+ {RT5677_DSP_OUTB2_SRC_CTRL2 , 0x0000},
+ {RT5677_DSP_OUTB2_SRC_CTRL3 , 0x0000},
+ {RT5677_DSP_OUTB2_SRC_CTRL4 , 0x0800},
+ {RT5677_DSP_OUTB_0123_MIXER_CTRL, 0xfefe},
+ {RT5677_DSP_OUTB_45_MIXER_CTRL , 0xfefe},
+ {RT5677_DSP_OUTB_67_MIXER_CTRL , 0xfefe},
+ {RT5677_DIG_MISC , 0x0000},
+ {RT5677_GEN_CTRL1 , 0x0000},
+ {RT5677_GEN_CTRL2 , 0x0000},
+ {RT5677_VENDOR_ID , 0x0000},
+ {RT5677_VENDOR_ID1 , 0x10ec},
+ {RT5677_VENDOR_ID2 , 0x6327},
+};
+
+static bool rt5677_volatile_register(struct device *dev, unsigned int reg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rt5677_ranges); i++) {
+ if (reg >= rt5677_ranges[i].range_min &&
+ reg <= rt5677_ranges[i].range_max) {
+ return true;
+ }
+ }
+
+ switch (reg) {
+ case RT5677_RESET:
+ case RT5677_SLIMBUS_PARAM:
+ case RT5677_PDM_DATA_CTRL1:
+ case RT5677_PDM_DATA_CTRL2:
+ case RT5677_PDM1_DATA_CTRL4:
+ case RT5677_PDM2_DATA_CTRL4:
+ case RT5677_I2C_MASTER_CTRL1:
+ case RT5677_I2C_MASTER_CTRL7:
+ case RT5677_I2C_MASTER_CTRL8:
+ case RT5677_HAP_GENE_CTRL2:
+ case RT5677_PWR_DSP_ST:
+ case RT5677_PRIV_DATA:
+ case RT5677_PLL1_CTRL2:
+ case RT5677_PLL2_CTRL2:
+ case RT5677_ASRC_22:
+ case RT5677_ASRC_23:
+ case RT5677_VAD_CTRL5:
+ case RT5677_ADC_EQ_CTRL1:
+ case RT5677_EQ_CTRL1:
+ case RT5677_IRQ_CTRL1:
+ case RT5677_IRQ_CTRL2:
+ case RT5677_GPIO_ST:
+ case RT5677_DSP_INB1_SRC_CTRL4:
+ case RT5677_DSP_INB2_SRC_CTRL4:
+ case RT5677_DSP_INB3_SRC_CTRL4:
+ case RT5677_DSP_OUTB1_SRC_CTRL4:
+ case RT5677_DSP_OUTB2_SRC_CTRL4:
+ case RT5677_VENDOR_ID:
+ case RT5677_VENDOR_ID1:
+ case RT5677_VENDOR_ID2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool rt5677_readable_register(struct device *dev, unsigned int reg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rt5677_ranges); i++) {
+ if (reg >= rt5677_ranges[i].range_min &&
+ reg <= rt5677_ranges[i].range_max) {
+ return true;
+ }
+ }
+
+ switch (reg) {
+ case RT5677_RESET:
+ case RT5677_LOUT1:
+ case RT5677_IN1:
+ case RT5677_MICBIAS:
+ case RT5677_SLIMBUS_PARAM:
+ case RT5677_SLIMBUS_RX:
+ case RT5677_SLIMBUS_CTRL:
+ case RT5677_SIDETONE_CTRL:
+ case RT5677_ANA_DAC1_2_3_SRC:
+ case RT5677_IF_DSP_DAC3_4_MIXER:
+ case RT5677_DAC4_DIG_VOL:
+ case RT5677_DAC3_DIG_VOL:
+ case RT5677_DAC1_DIG_VOL:
+ case RT5677_DAC2_DIG_VOL:
+ case RT5677_IF_DSP_DAC2_MIXER:
+ case RT5677_STO1_ADC_DIG_VOL:
+ case RT5677_MONO_ADC_DIG_VOL:
+ case RT5677_STO1_2_ADC_BST:
+ case RT5677_STO2_ADC_DIG_VOL:
+ case RT5677_ADC_BST_CTRL2:
+ case RT5677_STO3_4_ADC_BST:
+ case RT5677_STO3_ADC_DIG_VOL:
+ case RT5677_STO4_ADC_DIG_VOL:
+ case RT5677_STO4_ADC_MIXER:
+ case RT5677_STO3_ADC_MIXER:
+ case RT5677_STO2_ADC_MIXER:
+ case RT5677_STO1_ADC_MIXER:
+ case RT5677_MONO_ADC_MIXER:
+ case RT5677_ADC_IF_DSP_DAC1_MIXER:
+ case RT5677_STO1_DAC_MIXER:
+ case RT5677_MONO_DAC_MIXER:
+ case RT5677_DD1_MIXER:
+ case RT5677_DD2_MIXER:
+ case RT5677_IF3_DATA:
+ case RT5677_IF4_DATA:
+ case RT5677_PDM_OUT_CTRL:
+ case RT5677_PDM_DATA_CTRL1:
+ case RT5677_PDM_DATA_CTRL2:
+ case RT5677_PDM1_DATA_CTRL2:
+ case RT5677_PDM1_DATA_CTRL3:
+ case RT5677_PDM1_DATA_CTRL4:
+ case RT5677_PDM2_DATA_CTRL2:
+ case RT5677_PDM2_DATA_CTRL3:
+ case RT5677_PDM2_DATA_CTRL4:
+ case RT5677_TDM1_CTRL1:
+ case RT5677_TDM1_CTRL2:
+ case RT5677_TDM1_CTRL3:
+ case RT5677_TDM1_CTRL4:
+ case RT5677_TDM1_CTRL5:
+ case RT5677_TDM2_CTRL1:
+ case RT5677_TDM2_CTRL2:
+ case RT5677_TDM2_CTRL3:
+ case RT5677_TDM2_CTRL4:
+ case RT5677_TDM2_CTRL5:
+ case RT5677_I2C_MASTER_CTRL1:
+ case RT5677_I2C_MASTER_CTRL2:
+ case RT5677_I2C_MASTER_CTRL3:
+ case RT5677_I2C_MASTER_CTRL4:
+ case RT5677_I2C_MASTER_CTRL5:
+ case RT5677_I2C_MASTER_CTRL6:
+ case RT5677_I2C_MASTER_CTRL7:
+ case RT5677_I2C_MASTER_CTRL8:
+ case RT5677_DMIC_CTRL1:
+ case RT5677_DMIC_CTRL2:
+ case RT5677_HAP_GENE_CTRL1:
+ case RT5677_HAP_GENE_CTRL2:
+ case RT5677_HAP_GENE_CTRL3:
+ case RT5677_HAP_GENE_CTRL4:
+ case RT5677_HAP_GENE_CTRL5:
+ case RT5677_HAP_GENE_CTRL6:
+ case RT5677_HAP_GENE_CTRL7:
+ case RT5677_HAP_GENE_CTRL8:
+ case RT5677_HAP_GENE_CTRL9:
+ case RT5677_HAP_GENE_CTRL10:
+ case RT5677_PWR_DIG1:
+ case RT5677_PWR_DIG2:
+ case RT5677_PWR_ANLG1:
+ case RT5677_PWR_ANLG2:
+ case RT5677_PWR_DSP1:
+ case RT5677_PWR_DSP_ST:
+ case RT5677_PWR_DSP2:
+ case RT5677_ADC_DAC_HPF_CTRL1:
+ case RT5677_PRIV_INDEX:
+ case RT5677_PRIV_DATA:
+ case RT5677_I2S4_SDP:
+ case RT5677_I2S1_SDP:
+ case RT5677_I2S2_SDP:
+ case RT5677_I2S3_SDP:
+ case RT5677_CLK_TREE_CTRL1:
+ case RT5677_CLK_TREE_CTRL2:
+ case RT5677_CLK_TREE_CTRL3:
+ case RT5677_PLL1_CTRL1:
+ case RT5677_PLL1_CTRL2:
+ case RT5677_PLL2_CTRL1:
+ case RT5677_PLL2_CTRL2:
+ case RT5677_GLB_CLK1:
+ case RT5677_GLB_CLK2:
+ case RT5677_ASRC_1:
+ case RT5677_ASRC_2:
+ case RT5677_ASRC_3:
+ case RT5677_ASRC_4:
+ case RT5677_ASRC_5:
+ case RT5677_ASRC_6:
+ case RT5677_ASRC_7:
+ case RT5677_ASRC_8:
+ case RT5677_ASRC_9:
+ case RT5677_ASRC_10:
+ case RT5677_ASRC_11:
+ case RT5677_ASRC_12:
+ case RT5677_ASRC_13:
+ case RT5677_ASRC_14:
+ case RT5677_ASRC_15:
+ case RT5677_ASRC_16:
+ case RT5677_ASRC_17:
+ case RT5677_ASRC_18:
+ case RT5677_ASRC_19:
+ case RT5677_ASRC_20:
+ case RT5677_ASRC_21:
+ case RT5677_ASRC_22:
+ case RT5677_ASRC_23:
+ case RT5677_VAD_CTRL1:
+ case RT5677_VAD_CTRL2:
+ case RT5677_VAD_CTRL3:
+ case RT5677_VAD_CTRL4:
+ case RT5677_VAD_CTRL5:
+ case RT5677_DSP_INB_CTRL1:
+ case RT5677_DSP_INB_CTRL2:
+ case RT5677_DSP_IN_OUTB_CTRL:
+ case RT5677_DSP_OUTB0_1_DIG_VOL:
+ case RT5677_DSP_OUTB2_3_DIG_VOL:
+ case RT5677_DSP_OUTB4_5_DIG_VOL:
+ case RT5677_DSP_OUTB6_7_DIG_VOL:
+ case RT5677_ADC_EQ_CTRL1:
+ case RT5677_ADC_EQ_CTRL2:
+ case RT5677_EQ_CTRL1:
+ case RT5677_EQ_CTRL2:
+ case RT5677_EQ_CTRL3:
+ case RT5677_SOFT_VOL_ZERO_CROSS1:
+ case RT5677_JD_CTRL1:
+ case RT5677_JD_CTRL2:
+ case RT5677_JD_CTRL3:
+ case RT5677_IRQ_CTRL1:
+ case RT5677_IRQ_CTRL2:
+ case RT5677_GPIO_ST:
+ case RT5677_GPIO_CTRL1:
+ case RT5677_GPIO_CTRL2:
+ case RT5677_GPIO_CTRL3:
+ case RT5677_STO1_ADC_HI_FILTER1:
+ case RT5677_STO1_ADC_HI_FILTER2:
+ case RT5677_MONO_ADC_HI_FILTER1:
+ case RT5677_MONO_ADC_HI_FILTER2:
+ case RT5677_STO2_ADC_HI_FILTER1:
+ case RT5677_STO2_ADC_HI_FILTER2:
+ case RT5677_STO3_ADC_HI_FILTER1:
+ case RT5677_STO3_ADC_HI_FILTER2:
+ case RT5677_STO4_ADC_HI_FILTER1:
+ case RT5677_STO4_ADC_HI_FILTER2:
+ case RT5677_MB_DRC_CTRL1:
+ case RT5677_DRC1_CTRL1:
+ case RT5677_DRC1_CTRL2:
+ case RT5677_DRC1_CTRL3:
+ case RT5677_DRC1_CTRL4:
+ case RT5677_DRC1_CTRL5:
+ case RT5677_DRC1_CTRL6:
+ case RT5677_DRC2_CTRL1:
+ case RT5677_DRC2_CTRL2:
+ case RT5677_DRC2_CTRL3:
+ case RT5677_DRC2_CTRL4:
+ case RT5677_DRC2_CTRL5:
+ case RT5677_DRC2_CTRL6:
+ case RT5677_DRC1_HL_CTRL1:
+ case RT5677_DRC1_HL_CTRL2:
+ case RT5677_DRC2_HL_CTRL1:
+ case RT5677_DRC2_HL_CTRL2:
+ case RT5677_DSP_INB1_SRC_CTRL1:
+ case RT5677_DSP_INB1_SRC_CTRL2:
+ case RT5677_DSP_INB1_SRC_CTRL3:
+ case RT5677_DSP_INB1_SRC_CTRL4:
+ case RT5677_DSP_INB2_SRC_CTRL1:
+ case RT5677_DSP_INB2_SRC_CTRL2:
+ case RT5677_DSP_INB2_SRC_CTRL3:
+ case RT5677_DSP_INB2_SRC_CTRL4:
+ case RT5677_DSP_INB3_SRC_CTRL1:
+ case RT5677_DSP_INB3_SRC_CTRL2:
+ case RT5677_DSP_INB3_SRC_CTRL3:
+ case RT5677_DSP_INB3_SRC_CTRL4:
+ case RT5677_DSP_OUTB1_SRC_CTRL1:
+ case RT5677_DSP_OUTB1_SRC_CTRL2:
+ case RT5677_DSP_OUTB1_SRC_CTRL3:
+ case RT5677_DSP_OUTB1_SRC_CTRL4:
+ case RT5677_DSP_OUTB2_SRC_CTRL1:
+ case RT5677_DSP_OUTB2_SRC_CTRL2:
+ case RT5677_DSP_OUTB2_SRC_CTRL3:
+ case RT5677_DSP_OUTB2_SRC_CTRL4:
+ case RT5677_DSP_OUTB_0123_MIXER_CTRL:
+ case RT5677_DSP_OUTB_45_MIXER_CTRL:
+ case RT5677_DSP_OUTB_67_MIXER_CTRL:
+ case RT5677_DIG_MISC:
+ case RT5677_GEN_CTRL1:
+ case RT5677_GEN_CTRL2:
+ case RT5677_VENDOR_ID:
+ case RT5677_VENDOR_ID1:
+ case RT5677_VENDOR_ID2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
+
+/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
+static unsigned int bst_tlv[] = {
+ TLV_DB_RANGE_HEAD(7),
+ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+ 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
+ 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
+ 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
+ 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
+ 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
+};
+
+static const struct snd_kcontrol_new rt5677_snd_controls[] = {
+ /* OUTPUT Control */
+ SOC_SINGLE("OUT1 Playback Switch", RT5677_LOUT1,
+ RT5677_LOUT1_L_MUTE_SFT, 1, 1),
+ SOC_SINGLE("OUT2 Playback Switch", RT5677_LOUT1,
+ RT5677_LOUT2_L_MUTE_SFT, 1, 1),
+ SOC_SINGLE("OUT3 Playback Switch", RT5677_LOUT1,
+ RT5677_LOUT3_L_MUTE_SFT, 1, 1),
+
+ /* DAC Digital Volume */
+ SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5677_DAC1_DIG_VOL,
+ RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 175, 0, dac_vol_tlv),
+ SOC_DOUBLE_TLV("DAC2 Playback Volume", RT5677_DAC2_DIG_VOL,
+ RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 175, 0, dac_vol_tlv),
+ SOC_DOUBLE_TLV("DAC3 Playback Volume", RT5677_DAC3_DIG_VOL,
+ RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 175, 0, dac_vol_tlv),
+ SOC_DOUBLE_TLV("DAC4 Playback Volume", RT5677_DAC4_DIG_VOL,
+ RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 175, 0, dac_vol_tlv),
+
+ /* IN1/IN2 Control */
+ SOC_SINGLE_TLV("IN1 Boost", RT5677_IN1, RT5677_BST_SFT1, 8, 0, bst_tlv),
+ SOC_SINGLE_TLV("IN2 Boost", RT5677_IN1, RT5677_BST_SFT2, 8, 0, bst_tlv),
+
+ /* ADC Digital Volume Control */
+ SOC_DOUBLE("ADC1 Capture Switch", RT5677_STO1_ADC_DIG_VOL,
+ RT5677_L_MUTE_SFT, RT5677_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE("ADC2 Capture Switch", RT5677_STO2_ADC_DIG_VOL,
+ RT5677_L_MUTE_SFT, RT5677_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE("ADC3 Capture Switch", RT5677_STO3_ADC_DIG_VOL,
+ RT5677_L_MUTE_SFT, RT5677_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE("ADC4 Capture Switch", RT5677_STO4_ADC_DIG_VOL,
+ RT5677_L_MUTE_SFT, RT5677_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE("Mono ADC Capture Switch", RT5677_MONO_ADC_DIG_VOL,
+ RT5677_L_MUTE_SFT, RT5677_R_MUTE_SFT, 1, 1),
+
+ SOC_DOUBLE_TLV("ADC1 Capture Volume", RT5677_STO1_ADC_DIG_VOL,
+ RT5677_STO1_ADC_L_VOL_SFT, RT5677_STO1_ADC_R_VOL_SFT, 127, 0,
+ adc_vol_tlv),
+ SOC_DOUBLE_TLV("ADC2 Capture Volume", RT5677_STO2_ADC_DIG_VOL,
+ RT5677_STO1_ADC_L_VOL_SFT, RT5677_STO1_ADC_R_VOL_SFT, 127, 0,
+ adc_vol_tlv),
+ SOC_DOUBLE_TLV("ADC3 Capture Volume", RT5677_STO3_ADC_DIG_VOL,
+ RT5677_STO1_ADC_L_VOL_SFT, RT5677_STO1_ADC_R_VOL_SFT, 127, 0,
+ adc_vol_tlv),
+ SOC_DOUBLE_TLV("ADC4 Capture Volume", RT5677_STO4_ADC_DIG_VOL,
+ RT5677_STO1_ADC_L_VOL_SFT, RT5677_STO1_ADC_R_VOL_SFT, 127, 0,
+ adc_vol_tlv),
+ SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5677_MONO_ADC_DIG_VOL,
+ RT5677_MONO_ADC_L_VOL_SFT, RT5677_MONO_ADC_R_VOL_SFT, 127, 0,
+ adc_vol_tlv),
+
+ /* ADC Boost Volume Control */
+ SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5677_STO1_2_ADC_BST,
+ RT5677_STO1_ADC_L_BST_SFT, RT5677_STO1_ADC_R_BST_SFT, 3, 0,
+ adc_bst_tlv),
+ SOC_DOUBLE_TLV("STO2 ADC Boost Gain", RT5677_STO1_2_ADC_BST,
+ RT5677_STO2_ADC_L_BST_SFT, RT5677_STO2_ADC_R_BST_SFT, 3, 0,
+ adc_bst_tlv),
+ SOC_DOUBLE_TLV("STO3 ADC Boost Gain", RT5677_STO3_4_ADC_BST,
+ RT5677_STO3_ADC_L_BST_SFT, RT5677_STO3_ADC_R_BST_SFT, 3, 0,
+ adc_bst_tlv),
+ SOC_DOUBLE_TLV("STO4 ADC Boost Gain", RT5677_STO3_4_ADC_BST,
+ RT5677_STO4_ADC_L_BST_SFT, RT5677_STO4_ADC_R_BST_SFT, 3, 0,
+ adc_bst_tlv),
+ SOC_DOUBLE_TLV("Mono ADC Boost Gain", RT5677_ADC_BST_CTRL2,
+ RT5677_MONO_ADC_L_BST_SFT, RT5677_MONO_ADC_R_BST_SFT, 3, 0,
+ adc_bst_tlv),
+};
+
+/**
+ * set_dmic_clk - Set parameter of dmic.
+ *
+ * @w: DAPM widget.
+ * @kcontrol: The kcontrol of this widget.
+ * @event: Event id.
+ *
+ * Choose dmic clock between 1MHz and 3MHz.
+ * It is better for clock to approximate 3MHz.
+ */
+static int set_dmic_clk(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+ int div[] = {2, 3, 4, 6, 8, 12}, idx = -EINVAL, i;
+ int rate, red, bound, temp;
+
+ rate = rt5677->sysclk;
+ red = 3000000 * 12;
+ for (i = 0; i < ARRAY_SIZE(div); i++) {
+ bound = div[i] * 3000000;
+ if (rate > bound)
+ continue;
+ temp = bound - rate;
+ if (temp < red) {
+ red = temp;
+ idx = i;
+ }
+ }
+
+ if (idx < 0)
+ dev_err(codec->dev, "Failed to set DMIC clock\n");
+ else
+ regmap_update_bits(rt5677->regmap, RT5677_DMIC_CTRL1,
+ RT5677_DMIC_CLK_MASK, idx << RT5677_DMIC_CLK_SFT);
+ return idx;
+}
+
+static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(source->codec);
+ unsigned int val;
+
+ regmap_read(rt5677->regmap, RT5677_GLB_CLK1, &val);
+ val &= RT5677_SCLK_SRC_MASK;
+ if (val == RT5677_SCLK_SRC_PLL1)
+ return 1;
+ else
+ return 0;
+}
+
+/* Digital Mixer */
+static const struct snd_kcontrol_new rt5677_sto1_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO1_ADC_MIXER,
+ RT5677_M_STO1_ADC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5677_STO1_ADC_MIXER,
+ RT5677_M_STO1_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_sto1_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO1_ADC_MIXER,
+ RT5677_M_STO1_ADC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5677_STO1_ADC_MIXER,
+ RT5677_M_STO1_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_sto2_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO2_ADC_MIXER,
+ RT5677_M_STO2_ADC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5677_STO2_ADC_MIXER,
+ RT5677_M_STO2_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_sto2_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO2_ADC_MIXER,
+ RT5677_M_STO2_ADC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5677_STO2_ADC_MIXER,
+ RT5677_M_STO2_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_sto3_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO3_ADC_MIXER,
+ RT5677_M_STO3_ADC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5677_STO3_ADC_MIXER,
+ RT5677_M_STO3_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_sto3_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO3_ADC_MIXER,
+ RT5677_M_STO3_ADC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5677_STO3_ADC_MIXER,
+ RT5677_M_STO3_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_sto4_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO4_ADC_MIXER,
+ RT5677_M_STO4_ADC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5677_STO4_ADC_MIXER,
+ RT5677_M_STO4_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_sto4_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO4_ADC_MIXER,
+ RT5677_M_STO4_ADC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5677_STO4_ADC_MIXER,
+ RT5677_M_STO4_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_mono_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5677_MONO_ADC_MIXER,
+ RT5677_M_MONO_ADC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5677_MONO_ADC_MIXER,
+ RT5677_M_MONO_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_mono_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5677_MONO_ADC_MIXER,
+ RT5677_M_MONO_ADC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5677_MONO_ADC_MIXER,
+ RT5677_M_MONO_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("Stereo ADC Switch", RT5677_ADC_IF_DSP_DAC1_MIXER,
+ RT5677_M_ADDA_MIXER1_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC1 Switch", RT5677_ADC_IF_DSP_DAC1_MIXER,
+ RT5677_M_DAC1_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("Stereo ADC Switch", RT5677_ADC_IF_DSP_DAC1_MIXER,
+ RT5677_M_ADDA_MIXER1_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC1 Switch", RT5677_ADC_IF_DSP_DAC1_MIXER,
+ RT5677_M_DAC1_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_sto1_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("ST L Switch", RT5677_STO1_DAC_MIXER,
+ RT5677_M_ST_DAC1_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC1 L Switch", RT5677_STO1_DAC_MIXER,
+ RT5677_M_DAC1_L_STO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC2 L Switch", RT5677_STO1_DAC_MIXER,
+ RT5677_M_DAC2_L_STO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC1 R Switch", RT5677_STO1_DAC_MIXER,
+ RT5677_M_DAC1_R_STO_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_sto1_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("ST R Switch", RT5677_STO1_DAC_MIXER,
+ RT5677_M_ST_DAC1_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC1 R Switch", RT5677_STO1_DAC_MIXER,
+ RT5677_M_DAC1_R_STO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC2 R Switch", RT5677_STO1_DAC_MIXER,
+ RT5677_M_DAC2_R_STO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC1 L Switch", RT5677_STO1_DAC_MIXER,
+ RT5677_M_DAC1_L_STO_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_mono_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("ST L Switch", RT5677_MONO_DAC_MIXER,
+ RT5677_M_ST_DAC2_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC1 L Switch", RT5677_MONO_DAC_MIXER,
+ RT5677_M_DAC1_L_MONO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC2 L Switch", RT5677_MONO_DAC_MIXER,
+ RT5677_M_DAC2_L_MONO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC2 R Switch", RT5677_MONO_DAC_MIXER,
+ RT5677_M_DAC2_R_MONO_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_mono_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("ST R Switch", RT5677_MONO_DAC_MIXER,
+ RT5677_M_ST_DAC2_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC1 R Switch", RT5677_MONO_DAC_MIXER,
+ RT5677_M_DAC1_R_MONO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC2 R Switch", RT5677_MONO_DAC_MIXER,
+ RT5677_M_DAC2_R_MONO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC2 L Switch", RT5677_MONO_DAC_MIXER,
+ RT5677_M_DAC2_L_MONO_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_dd1_l_mix[] = {
+ SOC_DAPM_SINGLE("Sto DAC Mix L Switch", RT5677_DD1_MIXER,
+ RT5677_M_STO_L_DD1_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("Mono DAC Mix L Switch", RT5677_DD1_MIXER,
+ RT5677_M_MONO_L_DD1_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC3 L Switch", RT5677_DD1_MIXER,
+ RT5677_M_DAC3_L_DD1_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC3 R Switch", RT5677_DD1_MIXER,
+ RT5677_M_DAC3_R_DD1_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_dd1_r_mix[] = {
+ SOC_DAPM_SINGLE("Sto DAC Mix R Switch", RT5677_DD1_MIXER,
+ RT5677_M_STO_R_DD1_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("Mono DAC Mix R Switch", RT5677_DD1_MIXER,
+ RT5677_M_MONO_R_DD1_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC3 R Switch", RT5677_DD1_MIXER,
+ RT5677_M_DAC3_R_DD1_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC3 L Switch", RT5677_DD1_MIXER,
+ RT5677_M_DAC3_L_DD1_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_dd2_l_mix[] = {
+ SOC_DAPM_SINGLE("Sto DAC Mix L Switch", RT5677_DD2_MIXER,
+ RT5677_M_STO_L_DD2_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("Mono DAC Mix L Switch", RT5677_DD2_MIXER,
+ RT5677_M_MONO_L_DD2_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC4 L Switch", RT5677_DD2_MIXER,
+ RT5677_M_DAC4_L_DD2_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC4 R Switch", RT5677_DD2_MIXER,
+ RT5677_M_DAC4_R_DD2_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_dd2_r_mix[] = {
+ SOC_DAPM_SINGLE("Sto DAC Mix R Switch", RT5677_DD2_MIXER,
+ RT5677_M_STO_R_DD2_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("Mono DAC Mix R Switch", RT5677_DD2_MIXER,
+ RT5677_M_MONO_R_DD2_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC4 R Switch", RT5677_DD2_MIXER,
+ RT5677_M_DAC4_R_DD2_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC4 L Switch", RT5677_DD2_MIXER,
+ RT5677_M_DAC4_L_DD2_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_ob_01_mix[] = {
+ SOC_DAPM_SINGLE("IB01 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_01_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB23 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_23_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB45 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_45_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB6 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_6_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB7 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_7_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB8 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_8_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB9 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_9_H_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_ob_23_mix[] = {
+ SOC_DAPM_SINGLE("IB01 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_01_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB23 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_23_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB45 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_45_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB6 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_6_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB7 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_7_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB8 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_8_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB9 Switch", RT5677_DSP_OUTB_0123_MIXER_CTRL,
+ RT5677_DSP_IB_9_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_ob_4_mix[] = {
+ SOC_DAPM_SINGLE("IB01 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_01_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB23 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_23_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB45 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_45_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB6 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_6_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB7 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_7_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB8 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_8_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB9 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_9_H_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_ob_5_mix[] = {
+ SOC_DAPM_SINGLE("IB01 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_01_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB23 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_23_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB45 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_45_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB6 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_6_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB7 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_7_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB8 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_8_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB9 Switch", RT5677_DSP_OUTB_45_MIXER_CTRL,
+ RT5677_DSP_IB_9_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_ob_6_mix[] = {
+ SOC_DAPM_SINGLE("IB01 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_01_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB23 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_23_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB45 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_45_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB6 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_6_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB7 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_7_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB8 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_8_H_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB9 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_9_H_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5677_ob_7_mix[] = {
+ SOC_DAPM_SINGLE("IB01 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_01_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB23 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_23_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB45 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_45_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB6 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_6_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB7 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_7_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB8 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_8_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("IB9 Switch", RT5677_DSP_OUTB_67_MIXER_CTRL,
+ RT5677_DSP_IB_9_L_SFT, 1, 1),
+};
+
+
+/* Mux */
+/* DAC1 L/R source */ /* MX-29 [10:8] */
+static const char * const rt5677_dac1_src[] = {
+ "IF1 DAC 01", "IF2 DAC 01", "IF3 DAC LR", "IF4 DAC LR", "SLB DAC 01",
+ "OB 01"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_dac1_enum, RT5677_ADC_IF_DSP_DAC1_MIXER,
+ RT5677_DAC1_L_SEL_SFT, rt5677_dac1_src);
+
+static const struct snd_kcontrol_new rt5677_dac1_mux =
+ SOC_DAPM_ENUM("DAC1 source", rt5677_dac1_enum);
+
+/* ADDA1 L/R source */ /* MX-29 [1:0] */
+static const char * const rt5677_adda1_src[] = {
+ "STO1 ADC MIX", "STO2 ADC MIX", "OB 67",
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_adda1_enum, RT5677_ADC_IF_DSP_DAC1_MIXER,
+ RT5677_ADDA1_SEL_SFT, rt5677_adda1_src);
+
+static const struct snd_kcontrol_new rt5677_adda1_mux =
+ SOC_DAPM_ENUM("ADDA1 source", rt5677_adda1_enum);
+
+
+/*DAC2 L/R source*/ /* MX-1B [6:4] [2:0] */
+static const char * const rt5677_dac2l_src[] = {
+ "IF1 DAC 2", "IF2 DAC 2", "IF3 DAC L", "IF4 DAC L", "SLB DAC 2",
+ "OB 2",
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_dac2l_enum, RT5677_IF_DSP_DAC2_MIXER,
+ RT5677_SEL_DAC2_L_SRC_SFT, rt5677_dac2l_src);
+
+static const struct snd_kcontrol_new rt5677_dac2_l_mux =
+ SOC_DAPM_ENUM("DAC2 L source", rt5677_dac2l_enum);
+
+static const char * const rt5677_dac2r_src[] = {
+ "IF1 DAC 3", "IF2 DAC 3", "IF3 DAC R", "IF4 DAC R", "SLB DAC 3",
+ "OB 3", "Haptic Generator", "VAD ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_dac2r_enum, RT5677_IF_DSP_DAC2_MIXER,
+ RT5677_SEL_DAC2_R_SRC_SFT, rt5677_dac2r_src);
+
+static const struct snd_kcontrol_new rt5677_dac2_r_mux =
+ SOC_DAPM_ENUM("DAC2 R source", rt5677_dac2r_enum);
+
+/*DAC3 L/R source*/ /* MX-16 [6:4] [2:0] */
+static const char * const rt5677_dac3l_src[] = {
+ "IF1 DAC 4", "IF2 DAC 4", "IF3 DAC L", "IF4 DAC L",
+ "SLB DAC 4", "OB 4"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_dac3l_enum, RT5677_IF_DSP_DAC3_4_MIXER,
+ RT5677_SEL_DAC3_L_SRC_SFT, rt5677_dac3l_src);
+
+static const struct snd_kcontrol_new rt5677_dac3_l_mux =
+ SOC_DAPM_ENUM("DAC3 L source", rt5677_dac3l_enum);
+
+static const char * const rt5677_dac3r_src[] = {
+ "IF1 DAC 5", "IF2 DAC 5", "IF3 DAC R", "IF4 DAC R",
+ "SLB DAC 5", "OB 5"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_dac3r_enum, RT5677_IF_DSP_DAC3_4_MIXER,
+ RT5677_SEL_DAC3_R_SRC_SFT, rt5677_dac3r_src);
+
+static const struct snd_kcontrol_new rt5677_dac3_r_mux =
+ SOC_DAPM_ENUM("DAC3 R source", rt5677_dac3r_enum);
+
+/*DAC4 L/R source*/ /* MX-16 [14:12] [10:8] */
+static const char * const rt5677_dac4l_src[] = {
+ "IF1 DAC 6", "IF2 DAC 6", "IF3 DAC L", "IF4 DAC L",
+ "SLB DAC 6", "OB 6"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_dac4l_enum, RT5677_IF_DSP_DAC3_4_MIXER,
+ RT5677_SEL_DAC4_L_SRC_SFT, rt5677_dac4l_src);
+
+static const struct snd_kcontrol_new rt5677_dac4_l_mux =
+ SOC_DAPM_ENUM("DAC4 L source", rt5677_dac4l_enum);
+
+static const char * const rt5677_dac4r_src[] = {
+ "IF1 DAC 7", "IF2 DAC 7", "IF3 DAC R", "IF4 DAC R",
+ "SLB DAC 7", "OB 7"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_dac4r_enum, RT5677_IF_DSP_DAC3_4_MIXER,
+ RT5677_SEL_DAC4_R_SRC_SFT, rt5677_dac4r_src);
+
+static const struct snd_kcontrol_new rt5677_dac4_r_mux =
+ SOC_DAPM_ENUM("DAC4 R source", rt5677_dac4r_enum);
+
+/* In/OutBound Source Pass SRC */ /* MX-A5 [3] [4] [0] [1] [2] */
+static const char * const rt5677_iob_bypass_src[] = {
+ "Bypass", "Pass SRC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_ob01_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL,
+ RT5677_SEL_SRC_OB01_SFT, rt5677_iob_bypass_src);
+
+static const struct snd_kcontrol_new rt5677_ob01_bypass_src_mux =
+ SOC_DAPM_ENUM("OB01 Bypass source", rt5677_ob01_bypass_src_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_ob23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL,
+ RT5677_SEL_SRC_OB23_SFT, rt5677_iob_bypass_src);
+
+static const struct snd_kcontrol_new rt5677_ob23_bypass_src_mux =
+ SOC_DAPM_ENUM("OB23 Bypass source", rt5677_ob23_bypass_src_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_ib01_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL,
+ RT5677_SEL_SRC_IB01_SFT, rt5677_iob_bypass_src);
+
+static const struct snd_kcontrol_new rt5677_ib01_bypass_src_mux =
+ SOC_DAPM_ENUM("IB01 Bypass source", rt5677_ib01_bypass_src_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_ib23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL,
+ RT5677_SEL_SRC_IB23_SFT, rt5677_iob_bypass_src);
+
+static const struct snd_kcontrol_new rt5677_ib23_bypass_src_mux =
+ SOC_DAPM_ENUM("IB23 Bypass source", rt5677_ib23_bypass_src_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_ib45_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL,
+ RT5677_SEL_SRC_IB45_SFT, rt5677_iob_bypass_src);
+
+static const struct snd_kcontrol_new rt5677_ib45_bypass_src_mux =
+ SOC_DAPM_ENUM("IB45 Bypass source", rt5677_ib45_bypass_src_enum);
+
+/* Stereo ADC Source 2 */ /* MX-27 MX26 MX25 [11:10] */
+static const char * const rt5677_stereo_adc2_src[] = {
+ "DD MIX1", "DMIC", "Stereo DAC MIX"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_stereo1_adc2_enum, RT5677_STO1_ADC_MIXER,
+ RT5677_SEL_STO1_ADC2_SFT, rt5677_stereo_adc2_src);
+
+static const struct snd_kcontrol_new rt5677_sto1_adc2_mux =
+ SOC_DAPM_ENUM("Stereo1 ADC2 source", rt5677_stereo1_adc2_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_stereo2_adc2_enum, RT5677_STO2_ADC_MIXER,
+ RT5677_SEL_STO2_ADC2_SFT, rt5677_stereo_adc2_src);
+
+static const struct snd_kcontrol_new rt5677_sto2_adc2_mux =
+ SOC_DAPM_ENUM("Stereo2 ADC2 source", rt5677_stereo2_adc2_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_stereo3_adc2_enum, RT5677_STO3_ADC_MIXER,
+ RT5677_SEL_STO3_ADC2_SFT, rt5677_stereo_adc2_src);
+
+static const struct snd_kcontrol_new rt5677_sto3_adc2_mux =
+ SOC_DAPM_ENUM("Stereo3 ADC2 source", rt5677_stereo3_adc2_enum);
+
+/* DMIC Source */ /* MX-28 [9:8][1:0] MX-27 MX-26 MX-25 MX-24 [9:8] */
+static const char * const rt5677_dmic_src[] = {
+ "DMIC1", "DMIC2", "DMIC3", "DMIC4"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_mono_dmic_l_enum, RT5677_MONO_ADC_MIXER,
+ RT5677_SEL_MONO_DMIC_L_SFT, rt5677_dmic_src);
+
+static const struct snd_kcontrol_new rt5677_mono_dmic_l_mux =
+ SOC_DAPM_ENUM("Mono DMIC L source", rt5677_mono_dmic_l_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_mono_dmic_r_enum, RT5677_MONO_ADC_MIXER,
+ RT5677_SEL_MONO_DMIC_R_SFT, rt5677_dmic_src);
+
+static const struct snd_kcontrol_new rt5677_mono_dmic_r_mux =
+ SOC_DAPM_ENUM("Mono DMIC R source", rt5677_mono_dmic_r_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_stereo1_dmic_enum, RT5677_STO1_ADC_MIXER,
+ RT5677_SEL_STO1_DMIC_SFT, rt5677_dmic_src);
+
+static const struct snd_kcontrol_new rt5677_sto1_dmic_mux =
+ SOC_DAPM_ENUM("Stereo1 DMIC source", rt5677_stereo1_dmic_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_stereo2_dmic_enum, RT5677_STO2_ADC_MIXER,
+ RT5677_SEL_STO2_DMIC_SFT, rt5677_dmic_src);
+
+static const struct snd_kcontrol_new rt5677_sto2_dmic_mux =
+ SOC_DAPM_ENUM("Stereo2 DMIC source", rt5677_stereo2_dmic_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_stereo3_dmic_enum, RT5677_STO3_ADC_MIXER,
+ RT5677_SEL_STO3_DMIC_SFT, rt5677_dmic_src);
+
+static const struct snd_kcontrol_new rt5677_sto3_dmic_mux =
+ SOC_DAPM_ENUM("Stereo3 DMIC source", rt5677_stereo3_dmic_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_stereo4_dmic_enum, RT5677_STO4_ADC_MIXER,
+ RT5677_SEL_STO4_DMIC_SFT, rt5677_dmic_src);
+
+static const struct snd_kcontrol_new rt5677_sto4_dmic_mux =
+ SOC_DAPM_ENUM("Stereo4 DMIC source", rt5677_stereo4_dmic_enum);
+
+/* Stereo2 ADC source */ /* MX-26 [0] */
+static const char * const rt5677_stereo2_adc_lr_src[] = {
+ "L", "LR"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_stereo2_adc_lr_enum, RT5677_STO2_ADC_MIXER,
+ RT5677_SEL_STO2_LR_MIX_SFT, rt5677_stereo2_adc_lr_src);
+
+static const struct snd_kcontrol_new rt5677_sto2_adc_lr_mux =
+ SOC_DAPM_ENUM("Stereo2 ADC LR source", rt5677_stereo2_adc_lr_enum);
+
+/* Stereo1 ADC Source 1 */ /* MX-27 MX26 MX25 [13:12] */
+static const char * const rt5677_stereo_adc1_src[] = {
+ "DD MIX1", "ADC1/2", "Stereo DAC MIX"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_stereo1_adc1_enum, RT5677_STO1_ADC_MIXER,
+ RT5677_SEL_STO1_ADC1_SFT, rt5677_stereo_adc1_src);
+
+static const struct snd_kcontrol_new rt5677_sto1_adc1_mux =
+ SOC_DAPM_ENUM("Stereo1 ADC1 source", rt5677_stereo1_adc1_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_stereo2_adc1_enum, RT5677_STO2_ADC_MIXER,
+ RT5677_SEL_STO2_ADC1_SFT, rt5677_stereo_adc1_src);
+
+static const struct snd_kcontrol_new rt5677_sto2_adc1_mux =
+ SOC_DAPM_ENUM("Stereo2 ADC1 source", rt5677_stereo2_adc1_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_stereo3_adc1_enum, RT5677_STO3_ADC_MIXER,
+ RT5677_SEL_STO3_ADC1_SFT, rt5677_stereo_adc1_src);
+
+static const struct snd_kcontrol_new rt5677_sto3_adc1_mux =
+ SOC_DAPM_ENUM("Stereo3 ADC1 source", rt5677_stereo3_adc1_enum);
+
+/* Mono ADC Left source 2 */ /* MX-28 [11:10] */
+static const char * const rt5677_mono_adc2_l_src[] = {
+ "DD MIX1L", "DMIC", "MONO DAC MIXL"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_mono_adc2_l_enum, RT5677_MONO_ADC_MIXER,
+ RT5677_SEL_MONO_ADC_L2_SFT, rt5677_mono_adc2_l_src);
+
+static const struct snd_kcontrol_new rt5677_mono_adc2_l_mux =
+ SOC_DAPM_ENUM("Mono ADC2 L source", rt5677_mono_adc2_l_enum);
+
+/* Mono ADC Left source 1 */ /* MX-28 [13:12] */
+static const char * const rt5677_mono_adc1_l_src[] = {
+ "DD MIX1L", "ADC1", "MONO DAC MIXL"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_mono_adc1_l_enum, RT5677_MONO_ADC_MIXER,
+ RT5677_SEL_MONO_ADC_L1_SFT, rt5677_mono_adc1_l_src);
+
+static const struct snd_kcontrol_new rt5677_mono_adc1_l_mux =
+ SOC_DAPM_ENUM("Mono ADC1 L source", rt5677_mono_adc1_l_enum);
+
+/* Mono ADC Right source 2 */ /* MX-28 [3:2] */
+static const char * const rt5677_mono_adc2_r_src[] = {
+ "DD MIX1R", "DMIC", "MONO DAC MIXR"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_mono_adc2_r_enum, RT5677_MONO_ADC_MIXER,
+ RT5677_SEL_MONO_ADC_R2_SFT, rt5677_mono_adc2_r_src);
+
+static const struct snd_kcontrol_new rt5677_mono_adc2_r_mux =
+ SOC_DAPM_ENUM("Mono ADC2 R source", rt5677_mono_adc2_r_enum);
+
+/* Mono ADC Right source 1 */ /* MX-28 [5:4] */
+static const char * const rt5677_mono_adc1_r_src[] = {
+ "DD MIX1R", "ADC2", "MONO DAC MIXR"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_mono_adc1_r_enum, RT5677_MONO_ADC_MIXER,
+ RT5677_SEL_MONO_ADC_R1_SFT, rt5677_mono_adc1_r_src);
+
+static const struct snd_kcontrol_new rt5677_mono_adc1_r_mux =
+ SOC_DAPM_ENUM("Mono ADC1 R source", rt5677_mono_adc1_r_enum);
+
+/* Stereo4 ADC Source 2 */ /* MX-24 [11:10] */
+static const char * const rt5677_stereo4_adc2_src[] = {
+ "DD MIX1", "DMIC", "DD MIX2"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_stereo4_adc2_enum, RT5677_STO4_ADC_MIXER,
+ RT5677_SEL_STO4_ADC2_SFT, rt5677_stereo4_adc2_src);
+
+static const struct snd_kcontrol_new rt5677_sto4_adc2_mux =
+ SOC_DAPM_ENUM("Stereo4 ADC2 source", rt5677_stereo4_adc2_enum);
+
+
+/* Stereo4 ADC Source 1 */ /* MX-24 [13:12] */
+static const char * const rt5677_stereo4_adc1_src[] = {
+ "DD MIX1", "ADC1/2", "DD MIX2"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_stereo4_adc1_enum, RT5677_STO4_ADC_MIXER,
+ RT5677_SEL_STO4_ADC1_SFT, rt5677_stereo4_adc1_src);
+
+static const struct snd_kcontrol_new rt5677_sto4_adc1_mux =
+ SOC_DAPM_ENUM("Stereo4 ADC1 source", rt5677_stereo4_adc1_enum);
+
+/* InBound0/1 Source */ /* MX-A3 [14:12] */
+static const char * const rt5677_inbound01_src[] = {
+ "IF1 DAC 01", "IF2 DAC 01", "SLB DAC 01", "STO1 ADC MIX",
+ "VAD ADC/DAC1 FS"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_inbound01_enum, RT5677_DSP_INB_CTRL1,
+ RT5677_IB01_SRC_SFT, rt5677_inbound01_src);
+
+static const struct snd_kcontrol_new rt5677_ib01_src_mux =
+ SOC_DAPM_ENUM("InBound0/1 Source", rt5677_inbound01_enum);
+
+/* InBound2/3 Source */ /* MX-A3 [10:8] */
+static const char * const rt5677_inbound23_src[] = {
+ "IF1 DAC 23", "IF2 DAC 23", "SLB DAC 23", "STO2 ADC MIX",
+ "DAC1 FS", "IF4 DAC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_inbound23_enum, RT5677_DSP_INB_CTRL1,
+ RT5677_IB23_SRC_SFT, rt5677_inbound23_src);
+
+static const struct snd_kcontrol_new rt5677_ib23_src_mux =
+ SOC_DAPM_ENUM("InBound2/3 Source", rt5677_inbound23_enum);
+
+/* InBound4/5 Source */ /* MX-A3 [6:4] */
+static const char * const rt5677_inbound45_src[] = {
+ "IF1 DAC 45", "IF2 DAC 45", "SLB DAC 45", "STO3 ADC MIX",
+ "IF3 DAC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_inbound45_enum, RT5677_DSP_INB_CTRL1,
+ RT5677_IB45_SRC_SFT, rt5677_inbound45_src);
+
+static const struct snd_kcontrol_new rt5677_ib45_src_mux =
+ SOC_DAPM_ENUM("InBound4/5 Source", rt5677_inbound45_enum);
+
+/* InBound6 Source */ /* MX-A3 [2:0] */
+static const char * const rt5677_inbound6_src[] = {
+ "IF1 DAC 6", "IF2 DAC 6", "SLB DAC 6", "STO4 ADC MIX L",
+ "IF4 DAC L", "STO1 ADC MIX L", "STO2 ADC MIX L", "STO3 ADC MIX L"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_inbound6_enum, RT5677_DSP_INB_CTRL1,
+ RT5677_IB6_SRC_SFT, rt5677_inbound6_src);
+
+static const struct snd_kcontrol_new rt5677_ib6_src_mux =
+ SOC_DAPM_ENUM("InBound6 Source", rt5677_inbound6_enum);
+
+/* InBound7 Source */ /* MX-A4 [14:12] */
+static const char * const rt5677_inbound7_src[] = {
+ "IF1 DAC 7", "IF2 DAC 7", "SLB DAC 7", "STO4 ADC MIX R",
+ "IF4 DAC R", "STO1 ADC MIX R", "STO2 ADC MIX R", "STO3 ADC MIX R"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_inbound7_enum, RT5677_DSP_INB_CTRL2,
+ RT5677_IB7_SRC_SFT, rt5677_inbound7_src);
+
+static const struct snd_kcontrol_new rt5677_ib7_src_mux =
+ SOC_DAPM_ENUM("InBound7 Source", rt5677_inbound7_enum);
+
+/* InBound8 Source */ /* MX-A4 [10:8] */
+static const char * const rt5677_inbound8_src[] = {
+ "STO1 ADC MIX L", "STO2 ADC MIX L", "STO3 ADC MIX L", "STO4 ADC MIX L",
+ "MONO ADC MIX L", "DACL1 FS"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_inbound8_enum, RT5677_DSP_INB_CTRL2,
+ RT5677_IB8_SRC_SFT, rt5677_inbound8_src);
+
+static const struct snd_kcontrol_new rt5677_ib8_src_mux =
+ SOC_DAPM_ENUM("InBound8 Source", rt5677_inbound8_enum);
+
+/* InBound9 Source */ /* MX-A4 [6:4] */
+static const char * const rt5677_inbound9_src[] = {
+ "STO1 ADC MIX R", "STO2 ADC MIX R", "STO3 ADC MIX R", "STO4 ADC MIX R",
+ "MONO ADC MIX R", "DACR1 FS", "DAC1 FS"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_inbound9_enum, RT5677_DSP_INB_CTRL2,
+ RT5677_IB9_SRC_SFT, rt5677_inbound9_src);
+
+static const struct snd_kcontrol_new rt5677_ib9_src_mux =
+ SOC_DAPM_ENUM("InBound9 Source", rt5677_inbound9_enum);
+
+/* VAD Source */ /* MX-9F [6:4] */
+static const char * const rt5677_vad_src[] = {
+ "STO1 ADC MIX L", "MONO ADC MIX L", "MONO ADC MIX R", "STO2 ADC MIX L",
+ "STO3 ADC MIX L"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_vad_enum, RT5677_VAD_CTRL4,
+ RT5677_VAD_SRC_SFT, rt5677_vad_src);
+
+static const struct snd_kcontrol_new rt5677_vad_src_mux =
+ SOC_DAPM_ENUM("VAD Source", rt5677_vad_enum);
+
+/* Sidetone Source */ /* MX-13 [11:9] */
+static const char * const rt5677_sidetone_src[] = {
+ "DMIC1 L", "DMIC2 L", "DMIC3 L", "DMIC4 L", "ADC1", "ADC2"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_sidetone_enum, RT5677_SIDETONE_CTRL,
+ RT5677_ST_SEL_SFT, rt5677_sidetone_src);
+
+static const struct snd_kcontrol_new rt5677_sidetone_mux =
+ SOC_DAPM_ENUM("Sidetone Source", rt5677_sidetone_enum);
+
+/* DAC1/2 Source */ /* MX-15 [1:0] */
+static const char * const rt5677_dac12_src[] = {
+ "STO1 DAC MIX", "MONO DAC MIX", "DD MIX1", "DD MIX2"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_dac12_enum, RT5677_ANA_DAC1_2_3_SRC,
+ RT5677_ANA_DAC1_2_SRC_SEL_SFT, rt5677_dac12_src);
+
+static const struct snd_kcontrol_new rt5677_dac12_mux =
+ SOC_DAPM_ENUM("Analog DAC1/2 Source", rt5677_dac12_enum);
+
+/* DAC3 Source */ /* MX-15 [5:4] */
+static const char * const rt5677_dac3_src[] = {
+ "MONO DAC MIXL", "MONO DAC MIXR", "DD MIX1L", "DD MIX2L"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_dac3_enum, RT5677_ANA_DAC1_2_3_SRC,
+ RT5677_ANA_DAC3_SRC_SEL_SFT, rt5677_dac3_src);
+
+static const struct snd_kcontrol_new rt5677_dac3_mux =
+ SOC_DAPM_ENUM("Analog DAC3 Source", rt5677_dac3_enum);
+
+/* PDM channel source */ /* MX-31 [13:12][9:8][5:4][1:0] */
+static const char * const rt5677_pdm_src[] = {
+ "STO1 DAC MIX", "MONO DAC MIX", "DD MIX1", "DD MIX2"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_pdm1_l_enum, RT5677_PDM_OUT_CTRL,
+ RT5677_SEL_PDM1_L_SFT, rt5677_pdm_src);
+
+static const struct snd_kcontrol_new rt5677_pdm1_l_mux =
+ SOC_DAPM_ENUM("PDM1 source", rt5677_pdm1_l_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_pdm2_l_enum, RT5677_PDM_OUT_CTRL,
+ RT5677_SEL_PDM2_L_SFT, rt5677_pdm_src);
+
+static const struct snd_kcontrol_new rt5677_pdm2_l_mux =
+ SOC_DAPM_ENUM("PDM2 source", rt5677_pdm2_l_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_pdm1_r_enum, RT5677_PDM_OUT_CTRL,
+ RT5677_SEL_PDM1_R_SFT, rt5677_pdm_src);
+
+static const struct snd_kcontrol_new rt5677_pdm1_r_mux =
+ SOC_DAPM_ENUM("PDM1 source", rt5677_pdm1_r_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_pdm2_r_enum, RT5677_PDM_OUT_CTRL,
+ RT5677_SEL_PDM2_R_SFT, rt5677_pdm_src);
+
+static const struct snd_kcontrol_new rt5677_pdm2_r_mux =
+ SOC_DAPM_ENUM("PDM2 source", rt5677_pdm2_r_enum);
+
+/* TDM IF1/2 SLB ADC1 Data Selection */ /* MX-3C MX-41 [5:4] MX-08 [1:0]*/
+static const char * const rt5677_if12_adc1_src[] = {
+ "STO1 ADC MIX", "OB01", "VAD ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_if1_adc1_enum, RT5677_TDM1_CTRL2,
+ RT5677_IF1_ADC1_SFT, rt5677_if12_adc1_src);
+
+static const struct snd_kcontrol_new rt5677_if1_adc1_mux =
+ SOC_DAPM_ENUM("IF1 ADC1 source", rt5677_if1_adc1_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_if2_adc1_enum, RT5677_TDM2_CTRL2,
+ RT5677_IF2_ADC1_SFT, rt5677_if12_adc1_src);
+
+static const struct snd_kcontrol_new rt5677_if2_adc1_mux =
+ SOC_DAPM_ENUM("IF2 ADC1 source", rt5677_if2_adc1_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_slb_adc1_enum, RT5677_SLIMBUS_RX,
+ RT5677_SLB_ADC1_SFT, rt5677_if12_adc1_src);
+
+static const struct snd_kcontrol_new rt5677_slb_adc1_mux =
+ SOC_DAPM_ENUM("SLB ADC1 source", rt5677_slb_adc1_enum);
+
+/* TDM IF1/2 SLB ADC2 Data Selection */ /* MX-3C MX-41 [7:6] MX-08 [3:2] */
+static const char * const rt5677_if12_adc2_src[] = {
+ "STO2 ADC MIX", "OB23"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_if1_adc2_enum, RT5677_TDM1_CTRL2,
+ RT5677_IF1_ADC2_SFT, rt5677_if12_adc2_src);
+
+static const struct snd_kcontrol_new rt5677_if1_adc2_mux =
+ SOC_DAPM_ENUM("IF1 ADC2 source", rt5677_if1_adc2_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_if2_adc2_enum, RT5677_TDM2_CTRL2,
+ RT5677_IF2_ADC2_SFT, rt5677_if12_adc2_src);
+
+static const struct snd_kcontrol_new rt5677_if2_adc2_mux =
+ SOC_DAPM_ENUM("IF2 ADC2 source", rt5677_if2_adc2_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_slb_adc2_enum, RT5677_SLIMBUS_RX,
+ RT5677_SLB_ADC2_SFT, rt5677_if12_adc2_src);
+
+static const struct snd_kcontrol_new rt5677_slb_adc2_mux =
+ SOC_DAPM_ENUM("SLB ADC2 source", rt5677_slb_adc2_enum);
+
+/* TDM IF1/2 SLB ADC3 Data Selection */ /* MX-3C MX-41 [9:8] MX-08 [5:4] */
+static const char * const rt5677_if12_adc3_src[] = {
+ "STO3 ADC MIX", "MONO ADC MIX", "OB45"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_if1_adc3_enum, RT5677_TDM1_CTRL2,
+ RT5677_IF1_ADC3_SFT, rt5677_if12_adc3_src);
+
+static const struct snd_kcontrol_new rt5677_if1_adc3_mux =
+ SOC_DAPM_ENUM("IF1 ADC3 source", rt5677_if1_adc3_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_if2_adc3_enum, RT5677_TDM2_CTRL2,
+ RT5677_IF2_ADC3_SFT, rt5677_if12_adc3_src);
+
+static const struct snd_kcontrol_new rt5677_if2_adc3_mux =
+ SOC_DAPM_ENUM("IF2 ADC3 source", rt5677_if2_adc3_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_slb_adc3_enum, RT5677_SLIMBUS_RX,
+ RT5677_SLB_ADC3_SFT, rt5677_if12_adc3_src);
+
+static const struct snd_kcontrol_new rt5677_slb_adc3_mux =
+ SOC_DAPM_ENUM("SLB ADC3 source", rt5677_slb_adc3_enum);
+
+/* TDM IF1/2 SLB ADC4 Data Selection */ /* MX-3C MX-41 [11:10] MX-08 [7:6] */
+static const char * const rt5677_if12_adc4_src[] = {
+ "STO4 ADC MIX", "OB67", "OB01"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_if1_adc4_enum, RT5677_TDM1_CTRL2,
+ RT5677_IF1_ADC4_SFT, rt5677_if12_adc4_src);
+
+static const struct snd_kcontrol_new rt5677_if1_adc4_mux =
+ SOC_DAPM_ENUM("IF1 ADC4 source", rt5677_if1_adc4_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_if2_adc4_enum, RT5677_TDM2_CTRL2,
+ RT5677_IF2_ADC4_SFT, rt5677_if12_adc4_src);
+
+static const struct snd_kcontrol_new rt5677_if2_adc4_mux =
+ SOC_DAPM_ENUM("IF2 ADC4 source", rt5677_if2_adc4_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_slb_adc4_enum, RT5677_SLIMBUS_RX,
+ RT5677_SLB_ADC4_SFT, rt5677_if12_adc4_src);
+
+static const struct snd_kcontrol_new rt5677_slb_adc4_mux =
+ SOC_DAPM_ENUM("SLB ADC4 source", rt5677_slb_adc4_enum);
+
+/* Interface3/4 ADC Data Input */ /* MX-2F [3:0] MX-30 [7:4]*/
+static const char * const rt5677_if34_adc_src[] = {
+ "STO1 ADC MIX", "STO2 ADC MIX", "STO3 ADC MIX", "STO4 ADC MIX",
+ "MONO ADC MIX", "OB01", "OB23", "VAD ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_if3_adc_enum, RT5677_IF3_DATA,
+ RT5677_IF3_ADC_IN_SFT, rt5677_if34_adc_src);
+
+static const struct snd_kcontrol_new rt5677_if3_adc_mux =
+ SOC_DAPM_ENUM("IF3 ADC source", rt5677_if3_adc_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt5677_if4_adc_enum, RT5677_IF4_DATA,
+ RT5677_IF4_ADC_IN_SFT, rt5677_if34_adc_src);
+
+static const struct snd_kcontrol_new rt5677_if4_adc_mux =
+ SOC_DAPM_ENUM("IF4 ADC source", rt5677_if4_adc_enum);
+
+static int rt5677_bst1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
+ RT5677_PWR_BST1_P, RT5677_PWR_BST1_P);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
+ RT5677_PWR_BST1_P, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5677_bst2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
+ RT5677_PWR_BST2_P, RT5677_PWR_BST2_P);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
+ RT5677_PWR_BST2_P, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5677_set_pll1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_update_bits(rt5677->regmap, RT5677_PLL1_CTRL2, 0x2, 0x2);
+ regmap_update_bits(rt5677->regmap, RT5677_PLL1_CTRL2, 0x2, 0x0);
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5677_set_pll2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_update_bits(rt5677->regmap, RT5677_PLL2_CTRL2, 0x2, 0x2);
+ regmap_update_bits(rt5677->regmap, RT5677_PLL2_CTRL2, 0x2, 0x0);
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5677_set_micbias1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
+ RT5677_PWR_CLK_MB1 | RT5677_PWR_PP_MB1 |
+ RT5677_PWR_CLK_MB, RT5677_PWR_CLK_MB1 |
+ RT5677_PWR_PP_MB1 | RT5677_PWR_CLK_MB);
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("PLL1", RT5677_PWR_ANLG2, RT5677_PWR_PLL1_BIT,
+ 0, rt5677_set_pll1_event, SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_SUPPLY("PLL2", RT5677_PWR_ANLG2, RT5677_PWR_PLL2_BIT,
+ 0, rt5677_set_pll2_event, SND_SOC_DAPM_POST_PMU),
+
+ /* Input Side */
+ /* micbias */
+ SND_SOC_DAPM_SUPPLY("micbias1", RT5677_PWR_ANLG2, RT5677_PWR_MB1_BIT,
+ 0, rt5677_set_micbias1_event, SND_SOC_DAPM_POST_PMU),
+
+ /* Input Lines */
+ SND_SOC_DAPM_INPUT("DMIC L1"),
+ SND_SOC_DAPM_INPUT("DMIC R1"),
+ SND_SOC_DAPM_INPUT("DMIC L2"),
+ SND_SOC_DAPM_INPUT("DMIC R2"),
+ SND_SOC_DAPM_INPUT("DMIC L3"),
+ SND_SOC_DAPM_INPUT("DMIC R3"),
+ SND_SOC_DAPM_INPUT("DMIC L4"),
+ SND_SOC_DAPM_INPUT("DMIC R4"),
+
+ SND_SOC_DAPM_INPUT("IN1P"),
+ SND_SOC_DAPM_INPUT("IN1N"),
+ SND_SOC_DAPM_INPUT("IN2P"),
+ SND_SOC_DAPM_INPUT("IN2N"),
+
+ SND_SOC_DAPM_INPUT("Haptic Generator"),
+
+ SND_SOC_DAPM_PGA("DMIC1", RT5677_DMIC_CTRL1, RT5677_DMIC_1_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_PGA("DMIC2", RT5677_DMIC_CTRL1, RT5677_DMIC_2_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_PGA("DMIC3", RT5677_DMIC_CTRL1, RT5677_DMIC_3_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_PGA("DMIC4", RT5677_DMIC_CTRL2, RT5677_DMIC_4_EN_SFT, 0,
+ NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0,
+ set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
+
+ /* Boost */
+ SND_SOC_DAPM_PGA_E("BST1", RT5677_PWR_ANLG2,
+ RT5677_PWR_BST1_BIT, 0, NULL, 0, rt5677_bst1_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_E("BST2", RT5677_PWR_ANLG2,
+ RT5677_PWR_BST2_BIT, 0, NULL, 0, rt5677_bst2_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+
+ /* ADCs */
+ SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM,
+ 0, 0),
+ SND_SOC_DAPM_ADC("ADC 2", NULL, SND_SOC_NOPM,
+ 0, 0),
+ SND_SOC_DAPM_PGA("ADC 1_2", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("ADC 1 power", RT5677_PWR_DIG1,
+ RT5677_PWR_ADC_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("ADC 2 power", RT5677_PWR_DIG1,
+ RT5677_PWR_ADC_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("ADC1 clock", RT5677_PWR_DIG1,
+ RT5677_PWR_ADCFED1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("ADC2 clock", RT5677_PWR_DIG1,
+ RT5677_PWR_ADCFED2_BIT, 0, NULL, 0),
+
+ /* ADC Mux */
+ SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sto1_dmic_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sto1_adc1_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sto1_adc2_mux),
+ SND_SOC_DAPM_MUX("Stereo2 DMIC Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sto2_dmic_mux),
+ SND_SOC_DAPM_MUX("Stereo2 ADC1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sto2_adc1_mux),
+ SND_SOC_DAPM_MUX("Stereo2 ADC2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sto2_adc2_mux),
+ SND_SOC_DAPM_MUX("Stereo2 ADC LR Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sto2_adc_lr_mux),
+ SND_SOC_DAPM_MUX("Stereo3 DMIC Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sto3_dmic_mux),
+ SND_SOC_DAPM_MUX("Stereo3 ADC1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sto3_adc1_mux),
+ SND_SOC_DAPM_MUX("Stereo3 ADC2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sto3_adc2_mux),
+ SND_SOC_DAPM_MUX("Stereo4 DMIC Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sto4_dmic_mux),
+ SND_SOC_DAPM_MUX("Stereo4 ADC1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sto4_adc1_mux),
+ SND_SOC_DAPM_MUX("Stereo4 ADC2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sto4_adc2_mux),
+ SND_SOC_DAPM_MUX("Mono DMIC L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_mono_dmic_l_mux),
+ SND_SOC_DAPM_MUX("Mono DMIC R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_mono_dmic_r_mux),
+ SND_SOC_DAPM_MUX("Mono ADC2 L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_mono_adc2_l_mux),
+ SND_SOC_DAPM_MUX("Mono ADC1 L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_mono_adc1_l_mux),
+ SND_SOC_DAPM_MUX("Mono ADC1 R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_mono_adc1_r_mux),
+ SND_SOC_DAPM_MUX("Mono ADC2 R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_mono_adc2_r_mux),
+
+ /* ADC Mixer */
+ SND_SOC_DAPM_SUPPLY("adc stereo1 filter", RT5677_PWR_DIG2,
+ RT5677_PWR_ADC_S1F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("adc stereo2 filter", RT5677_PWR_DIG2,
+ RT5677_PWR_ADC_S2F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("adc stereo3 filter", RT5677_PWR_DIG2,
+ RT5677_PWR_ADC_S3F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("adc stereo4 filter", RT5677_PWR_DIG2,
+ RT5677_PWR_ADC_S4F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5677_sto1_adc_l_mix, ARRAY_SIZE(rt5677_sto1_adc_l_mix)),
+ SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5677_sto1_adc_r_mix, ARRAY_SIZE(rt5677_sto1_adc_r_mix)),
+ SND_SOC_DAPM_MIXER("Sto2 ADC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5677_sto2_adc_l_mix, ARRAY_SIZE(rt5677_sto2_adc_l_mix)),
+ SND_SOC_DAPM_MIXER("Sto2 ADC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5677_sto2_adc_r_mix, ARRAY_SIZE(rt5677_sto2_adc_r_mix)),
+ SND_SOC_DAPM_MIXER("Sto3 ADC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5677_sto3_adc_l_mix, ARRAY_SIZE(rt5677_sto3_adc_l_mix)),
+ SND_SOC_DAPM_MIXER("Sto3 ADC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5677_sto3_adc_r_mix, ARRAY_SIZE(rt5677_sto3_adc_r_mix)),
+ SND_SOC_DAPM_MIXER("Sto4 ADC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5677_sto4_adc_l_mix, ARRAY_SIZE(rt5677_sto4_adc_l_mix)),
+ SND_SOC_DAPM_MIXER("Sto4 ADC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5677_sto4_adc_r_mix, ARRAY_SIZE(rt5677_sto4_adc_r_mix)),
+ SND_SOC_DAPM_SUPPLY("adc mono left filter", RT5677_PWR_DIG2,
+ RT5677_PWR_ADC_MF_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Mono ADC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5677_mono_adc_l_mix, ARRAY_SIZE(rt5677_mono_adc_l_mix)),
+ SND_SOC_DAPM_SUPPLY("adc mono right filter", RT5677_PWR_DIG2,
+ RT5677_PWR_ADC_MF_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Mono ADC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5677_mono_adc_r_mix, ARRAY_SIZE(rt5677_mono_adc_r_mix)),
+
+ /* ADC PGA */
+ SND_SOC_DAPM_PGA("Stereo1 ADC MIXL", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo1 ADC MIXR", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo2 ADC MIXL", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo2 ADC MIXR", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo2 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo3 ADC MIXL", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo3 ADC MIXR", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo3 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo4 ADC MIXL", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo4 ADC MIXR", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo4 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Sto2 ADC LR MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Mono ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* DSP */
+ SND_SOC_DAPM_MUX("IB9 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_ib9_src_mux),
+ SND_SOC_DAPM_MUX("IB8 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_ib8_src_mux),
+ SND_SOC_DAPM_MUX("IB7 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_ib7_src_mux),
+ SND_SOC_DAPM_MUX("IB6 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_ib6_src_mux),
+ SND_SOC_DAPM_MUX("IB45 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_ib45_src_mux),
+ SND_SOC_DAPM_MUX("IB23 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_ib23_src_mux),
+ SND_SOC_DAPM_MUX("IB01 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_ib01_src_mux),
+ SND_SOC_DAPM_MUX("IB45 Bypass Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_ib45_bypass_src_mux),
+ SND_SOC_DAPM_MUX("IB23 Bypass Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_ib23_bypass_src_mux),
+ SND_SOC_DAPM_MUX("IB01 Bypass Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_ib01_bypass_src_mux),
+ SND_SOC_DAPM_MUX("OB23 Bypass Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_ob23_bypass_src_mux),
+ SND_SOC_DAPM_MUX("OB01 Bypass Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_ob01_bypass_src_mux),
+
+ SND_SOC_DAPM_PGA("OB45", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("OB67", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_PGA("OutBound2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("OutBound3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("OutBound4", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("OutBound5", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("OutBound6", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("OutBound7", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Digital Interface */
+ SND_SOC_DAPM_SUPPLY("I2S1", RT5677_PWR_DIG1,
+ RT5677_PWR_I2S1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC0", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC4", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC5", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC6", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC7", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC01", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC23", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC45", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC67", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 ADC4", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("I2S2", RT5677_PWR_DIG1,
+ RT5677_PWR_I2S2_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC0", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC4", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC5", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC6", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC7", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC01", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC23", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC45", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC67", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 ADC4", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("I2S3", RT5677_PWR_DIG1,
+ RT5677_PWR_I2S3_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF3 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF3 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF3 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF3 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF3 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF3 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("I2S4", RT5677_PWR_DIG1,
+ RT5677_PWR_I2S4_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF4 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF4 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF4 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF4 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF4 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF4 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("SLB", RT5677_PWR_DIG1,
+ RT5677_PWR_SLB_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB DAC0", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB DAC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB DAC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB DAC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB DAC4", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB DAC5", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB DAC6", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB DAC7", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB DAC01", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB DAC23", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB DAC45", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB DAC67", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SLB ADC4", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Digital Interface Select */
+ SND_SOC_DAPM_MUX("IF1 ADC1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_if1_adc1_mux),
+ SND_SOC_DAPM_MUX("IF1 ADC2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_if1_adc2_mux),
+ SND_SOC_DAPM_MUX("IF1 ADC3 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_if1_adc3_mux),
+ SND_SOC_DAPM_MUX("IF1 ADC4 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_if1_adc4_mux),
+ SND_SOC_DAPM_MUX("IF2 ADC1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_if2_adc1_mux),
+ SND_SOC_DAPM_MUX("IF2 ADC2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_if2_adc2_mux),
+ SND_SOC_DAPM_MUX("IF2 ADC3 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_if2_adc3_mux),
+ SND_SOC_DAPM_MUX("IF2 ADC4 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_if2_adc4_mux),
+ SND_SOC_DAPM_MUX("IF3 ADC Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_if3_adc_mux),
+ SND_SOC_DAPM_MUX("IF4 ADC Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_if4_adc_mux),
+ SND_SOC_DAPM_MUX("SLB ADC1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_slb_adc1_mux),
+ SND_SOC_DAPM_MUX("SLB ADC2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_slb_adc2_mux),
+ SND_SOC_DAPM_MUX("SLB ADC3 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_slb_adc3_mux),
+ SND_SOC_DAPM_MUX("SLB ADC4 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_slb_adc4_mux),
+
+ /* Audio Interface */
+ SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF3RX", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF3TX", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF4RX", "AIF4 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF4TX", "AIF4 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SLBRX", "SLIMBus Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("SLBTX", "SLIMBus Capture", 0, SND_SOC_NOPM, 0, 0),
+
+ /* Sidetone Mux */
+ SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_sidetone_mux),
+ /* VAD Mux*/
+ SND_SOC_DAPM_MUX("VAD ADC Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_vad_src_mux),
+
+ /* Tensilica DSP */
+ SND_SOC_DAPM_PGA("Tensilica DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("OB01 MIX", SND_SOC_NOPM, 0, 0,
+ rt5677_ob_01_mix, ARRAY_SIZE(rt5677_ob_01_mix)),
+ SND_SOC_DAPM_MIXER("OB23 MIX", SND_SOC_NOPM, 0, 0,
+ rt5677_ob_23_mix, ARRAY_SIZE(rt5677_ob_23_mix)),
+ SND_SOC_DAPM_MIXER("OB4 MIX", SND_SOC_NOPM, 0, 0,
+ rt5677_ob_4_mix, ARRAY_SIZE(rt5677_ob_4_mix)),
+ SND_SOC_DAPM_MIXER("OB5 MIX", SND_SOC_NOPM, 0, 0,
+ rt5677_ob_5_mix, ARRAY_SIZE(rt5677_ob_5_mix)),
+ SND_SOC_DAPM_MIXER("OB6 MIX", SND_SOC_NOPM, 0, 0,
+ rt5677_ob_6_mix, ARRAY_SIZE(rt5677_ob_6_mix)),
+ SND_SOC_DAPM_MIXER("OB7 MIX", SND_SOC_NOPM, 0, 0,
+ rt5677_ob_7_mix, ARRAY_SIZE(rt5677_ob_7_mix)),
+
+ /* Output Side */
+ /* DAC mixer before sound effect */
+ SND_SOC_DAPM_MIXER("DAC1 MIXL", SND_SOC_NOPM, 0, 0,
+ rt5677_dac_l_mix, ARRAY_SIZE(rt5677_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("DAC1 MIXR", SND_SOC_NOPM, 0, 0,
+ rt5677_dac_r_mix, ARRAY_SIZE(rt5677_dac_r_mix)),
+ SND_SOC_DAPM_PGA("DAC1 FS", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* DAC Mux */
+ SND_SOC_DAPM_MUX("DAC1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_dac1_mux),
+ SND_SOC_DAPM_MUX("ADDA1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_adda1_mux),
+ SND_SOC_DAPM_MUX("DAC12 SRC Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_dac12_mux),
+ SND_SOC_DAPM_MUX("DAC3 SRC Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_dac3_mux),
+
+ /* DAC2 channel Mux */
+ SND_SOC_DAPM_MUX("DAC2 L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_dac2_l_mux),
+ SND_SOC_DAPM_MUX("DAC2 R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_dac2_r_mux),
+
+ /* DAC3 channel Mux */
+ SND_SOC_DAPM_MUX("DAC3 L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_dac3_l_mux),
+ SND_SOC_DAPM_MUX("DAC3 R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_dac3_r_mux),
+
+ /* DAC4 channel Mux */
+ SND_SOC_DAPM_MUX("DAC4 L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_dac4_l_mux),
+ SND_SOC_DAPM_MUX("DAC4 R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5677_dac4_r_mux),
+
+ /* DAC Mixer */
+ SND_SOC_DAPM_SUPPLY("dac stereo1 filter", RT5677_PWR_DIG2,
+ RT5677_PWR_DAC_S1F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("dac mono left filter", RT5677_PWR_DIG2,
+ RT5677_PWR_DAC_M2F_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("dac mono right filter", RT5677_PWR_DIG2,
+ RT5677_PWR_DAC_M2F_R_BIT, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5677_sto1_dac_l_mix, ARRAY_SIZE(rt5677_sto1_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5677_sto1_dac_r_mix, ARRAY_SIZE(rt5677_sto1_dac_r_mix)),
+ SND_SOC_DAPM_MIXER("Mono DAC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5677_mono_dac_l_mix, ARRAY_SIZE(rt5677_mono_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("Mono DAC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5677_mono_dac_r_mix, ARRAY_SIZE(rt5677_mono_dac_r_mix)),
+ SND_SOC_DAPM_MIXER("DD1 MIXL", SND_SOC_NOPM, 0, 0,
+ rt5677_dd1_l_mix, ARRAY_SIZE(rt5677_dd1_l_mix)),
+ SND_SOC_DAPM_MIXER("DD1 MIXR", SND_SOC_NOPM, 0, 0,
+ rt5677_dd1_r_mix, ARRAY_SIZE(rt5677_dd1_r_mix)),
+ SND_SOC_DAPM_MIXER("DD2 MIXL", SND_SOC_NOPM, 0, 0,
+ rt5677_dd2_l_mix, ARRAY_SIZE(rt5677_dd2_l_mix)),
+ SND_SOC_DAPM_MIXER("DD2 MIXR", SND_SOC_NOPM, 0, 0,
+ rt5677_dd2_r_mix, ARRAY_SIZE(rt5677_dd2_r_mix)),
+ SND_SOC_DAPM_PGA("Stereo DAC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Mono DAC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("DD1 MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("DD2 MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* DACs */
+ SND_SOC_DAPM_DAC("DAC 1", NULL, RT5677_PWR_DIG1,
+ RT5677_PWR_DAC1_BIT, 0),
+ SND_SOC_DAPM_DAC("DAC 2", NULL, RT5677_PWR_DIG1,
+ RT5677_PWR_DAC2_BIT, 0),
+ SND_SOC_DAPM_DAC("DAC 3", NULL, RT5677_PWR_DIG1,
+ RT5677_PWR_DAC3_BIT, 0),
+
+ /* PDM */
+ SND_SOC_DAPM_SUPPLY("PDM1 Power", RT5677_PWR_DIG2,
+ RT5677_PWR_PDM1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("PDM2 Power", RT5677_PWR_DIG2,
+ RT5677_PWR_PDM2_BIT, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("PDM1 L Mux", RT5677_PDM_OUT_CTRL, RT5677_M_PDM1_L_SFT,
+ 1, &rt5677_pdm1_l_mux),
+ SND_SOC_DAPM_MUX("PDM1 R Mux", RT5677_PDM_OUT_CTRL, RT5677_M_PDM1_R_SFT,
+ 1, &rt5677_pdm1_r_mux),
+ SND_SOC_DAPM_MUX("PDM2 L Mux", RT5677_PDM_OUT_CTRL, RT5677_M_PDM2_L_SFT,
+ 1, &rt5677_pdm2_l_mux),
+ SND_SOC_DAPM_MUX("PDM2 R Mux", RT5677_PDM_OUT_CTRL, RT5677_M_PDM2_R_SFT,
+ 1, &rt5677_pdm2_r_mux),
+
+ SND_SOC_DAPM_PGA_S("LOUT1 amp", 1, RT5677_PWR_ANLG1, RT5677_PWR_LO1_BIT,
+ 0, NULL, 0),
+ SND_SOC_DAPM_PGA_S("LOUT2 amp", 1, RT5677_PWR_ANLG1, RT5677_PWR_LO2_BIT,
+ 0, NULL, 0),
+ SND_SOC_DAPM_PGA_S("LOUT3 amp", 1, RT5677_PWR_ANLG1, RT5677_PWR_LO3_BIT,
+ 0, NULL, 0),
+
+ /* Output Lines */
+ SND_SOC_DAPM_OUTPUT("LOUT1"),
+ SND_SOC_DAPM_OUTPUT("LOUT2"),
+ SND_SOC_DAPM_OUTPUT("LOUT3"),
+ SND_SOC_DAPM_OUTPUT("PDM1L"),
+ SND_SOC_DAPM_OUTPUT("PDM1R"),
+ SND_SOC_DAPM_OUTPUT("PDM2L"),
+ SND_SOC_DAPM_OUTPUT("PDM2R"),
+};
+
+static const struct snd_soc_dapm_route rt5677_dapm_routes[] = {
+ { "DMIC1", NULL, "DMIC L1" },
+ { "DMIC1", NULL, "DMIC R1" },
+ { "DMIC2", NULL, "DMIC L2" },
+ { "DMIC2", NULL, "DMIC R2" },
+ { "DMIC3", NULL, "DMIC L3" },
+ { "DMIC3", NULL, "DMIC R3" },
+ { "DMIC4", NULL, "DMIC L4" },
+ { "DMIC4", NULL, "DMIC R4" },
+
+ { "DMIC L1", NULL, "DMIC CLK" },
+ { "DMIC R1", NULL, "DMIC CLK" },
+ { "DMIC L2", NULL, "DMIC CLK" },
+ { "DMIC R2", NULL, "DMIC CLK" },
+ { "DMIC L3", NULL, "DMIC CLK" },
+ { "DMIC R3", NULL, "DMIC CLK" },
+ { "DMIC L4", NULL, "DMIC CLK" },
+ { "DMIC R4", NULL, "DMIC CLK" },
+
+ { "BST1", NULL, "IN1P" },
+ { "BST1", NULL, "IN1N" },
+ { "BST2", NULL, "IN2P" },
+ { "BST2", NULL, "IN2N" },
+
+ { "IN1P", NULL, "micbias1" },
+ { "IN1N", NULL, "micbias1" },
+ { "IN2P", NULL, "micbias1" },
+ { "IN2N", NULL, "micbias1" },
+
+ { "ADC 1", NULL, "BST1" },
+ { "ADC 1", NULL, "ADC 1 power" },
+ { "ADC 1", NULL, "ADC1 clock" },
+ { "ADC 2", NULL, "BST2" },
+ { "ADC 2", NULL, "ADC 2 power" },
+ { "ADC 2", NULL, "ADC2 clock" },
+
+ { "Stereo1 DMIC Mux", "DMIC1", "DMIC1" },
+ { "Stereo1 DMIC Mux", "DMIC2", "DMIC2" },
+ { "Stereo1 DMIC Mux", "DMIC3", "DMIC3" },
+ { "Stereo1 DMIC Mux", "DMIC4", "DMIC4" },
+
+ { "Stereo2 DMIC Mux", "DMIC1", "DMIC1" },
+ { "Stereo2 DMIC Mux", "DMIC2", "DMIC2" },
+ { "Stereo2 DMIC Mux", "DMIC3", "DMIC3" },
+ { "Stereo2 DMIC Mux", "DMIC4", "DMIC4" },
+
+ { "Stereo3 DMIC Mux", "DMIC1", "DMIC1" },
+ { "Stereo3 DMIC Mux", "DMIC2", "DMIC2" },
+ { "Stereo3 DMIC Mux", "DMIC3", "DMIC3" },
+ { "Stereo3 DMIC Mux", "DMIC4", "DMIC4" },
+
+ { "Stereo4 DMIC Mux", "DMIC1", "DMIC1" },
+ { "Stereo4 DMIC Mux", "DMIC2", "DMIC2" },
+ { "Stereo4 DMIC Mux", "DMIC3", "DMIC3" },
+ { "Stereo4 DMIC Mux", "DMIC4", "DMIC4" },
+
+ { "Mono DMIC L Mux", "DMIC1", "DMIC1" },
+ { "Mono DMIC L Mux", "DMIC2", "DMIC2" },
+ { "Mono DMIC L Mux", "DMIC3", "DMIC3" },
+ { "Mono DMIC L Mux", "DMIC4", "DMIC4" },
+
+ { "Mono DMIC R Mux", "DMIC1", "DMIC1" },
+ { "Mono DMIC R Mux", "DMIC2", "DMIC2" },
+ { "Mono DMIC R Mux", "DMIC3", "DMIC3" },
+ { "Mono DMIC R Mux", "DMIC4", "DMIC4" },
+
+ { "ADC 1_2", NULL, "ADC 1" },
+ { "ADC 1_2", NULL, "ADC 2" },
+
+ { "Stereo1 ADC1 Mux", "DD MIX1", "DD1 MIX" },
+ { "Stereo1 ADC1 Mux", "ADC1/2", "ADC 1_2" },
+ { "Stereo1 ADC1 Mux", "Stereo DAC MIX", "Stereo DAC MIX" },
+
+ { "Stereo1 ADC2 Mux", "DD MIX1", "DD1 MIX" },
+ { "Stereo1 ADC2 Mux", "DMIC", "Stereo1 DMIC Mux" },
+ { "Stereo1 ADC2 Mux", "Stereo DAC MIX", "Stereo DAC MIX" },
+
+ { "Stereo2 ADC1 Mux", "DD MIX1", "DD1 MIX" },
+ { "Stereo2 ADC1 Mux", "ADC1/2", "ADC 1_2" },
+ { "Stereo2 ADC1 Mux", "Stereo DAC MIX", "Stereo DAC MIX" },
+
+ { "Stereo2 ADC2 Mux", "DD MIX1", "DD1 MIX" },
+ { "Stereo2 ADC2 Mux", "DMIC", "Stereo2 DMIC Mux" },
+ { "Stereo2 ADC2 Mux", "Stereo DAC MIX", "Stereo DAC MIX" },
+
+ { "Stereo3 ADC1 Mux", "DD MIX1", "DD1 MIX" },
+ { "Stereo3 ADC1 Mux", "ADC1/2", "ADC 1_2" },
+ { "Stereo3 ADC1 Mux", "Stereo DAC MIX", "Stereo DAC MIX" },
+
+ { "Stereo3 ADC2 Mux", "DD MIX1", "DD1 MIX" },
+ { "Stereo3 ADC2 Mux", "DMIC", "Stereo3 DMIC Mux" },
+ { "Stereo3 ADC2 Mux", "Stereo DAC MIX", "Stereo DAC MIX" },
+
+ { "Stereo4 ADC1 Mux", "DD MIX1", "DD1 MIX" },
+ { "Stereo4 ADC1 Mux", "ADC1/2", "ADC 1_2" },
+ { "Stereo4 ADC1 Mux", "DD MIX2", "DD2 MIX" },
+
+ { "Stereo4 ADC2 Mux", "DD MIX1", "DD1 MIX" },
+ { "Stereo4 ADC2 Mux", "DMIC", "Stereo3 DMIC Mux" },
+ { "Stereo4 ADC2 Mux", "DD MIX2", "DD2 MIX" },
+
+ { "Mono ADC2 L Mux", "DD MIX1L", "DD1 MIXL" },
+ { "Mono ADC2 L Mux", "DMIC", "Mono DMIC L Mux" },
+ { "Mono ADC2 L Mux", "MONO DAC MIXL", "Mono DAC MIXL" },
+
+ { "Mono ADC1 L Mux", "DD MIX1L", "DD1 MIXL" },
+ { "Mono ADC1 L Mux", "ADC1", "ADC 1" },
+ { "Mono ADC1 L Mux", "MONO DAC MIXL", "Mono DAC MIXL" },
+
+ { "Mono ADC1 R Mux", "DD MIX1R", "DD1 MIXR" },
+ { "Mono ADC1 R Mux", "ADC2", "ADC 2" },
+ { "Mono ADC1 R Mux", "MONO DAC MIXR", "Mono DAC MIXR" },
+
+ { "Mono ADC2 R Mux", "DD MIX1R", "DD1 MIXR" },
+ { "Mono ADC2 R Mux", "DMIC", "Mono DMIC R Mux" },
+ { "Mono ADC2 R Mux", "MONO DAC MIXR", "Mono DAC MIXR" },
+
+ { "Sto1 ADC MIXL", "ADC1 Switch", "Stereo1 ADC1 Mux" },
+ { "Sto1 ADC MIXL", "ADC2 Switch", "Stereo1 ADC2 Mux" },
+ { "Sto1 ADC MIXR", "ADC1 Switch", "Stereo1 ADC1 Mux" },
+ { "Sto1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC2 Mux" },
+
+ { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" },
+ { "Stereo1 ADC MIXL", NULL, "adc stereo1 filter" },
+ { "adc stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" },
+ { "Stereo1 ADC MIXR", NULL, "adc stereo1 filter" },
+ { "adc stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL" },
+ { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR" },
+
+ { "Sto2 ADC MIXL", "ADC1 Switch", "Stereo2 ADC1 Mux" },
+ { "Sto2 ADC MIXL", "ADC2 Switch", "Stereo2 ADC2 Mux" },
+ { "Sto2 ADC MIXR", "ADC1 Switch", "Stereo2 ADC1 Mux" },
+ { "Sto2 ADC MIXR", "ADC2 Switch", "Stereo2 ADC2 Mux" },
+
+ { "Sto2 ADC LR MIX", NULL, "Sto2 ADC MIXL" },
+ { "Sto2 ADC LR MIX", NULL, "Sto2 ADC MIXR" },
+
+ { "Stereo2 ADC LR Mux", "L", "Sto2 ADC MIXL" },
+ { "Stereo2 ADC LR Mux", "LR", "Sto2 ADC LR MIX" },
+
+ { "Stereo2 ADC MIXL", NULL, "Stereo2 ADC LR Mux" },
+ { "Stereo2 ADC MIXL", NULL, "adc stereo2 filter" },
+ { "adc stereo2 filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" },
+ { "Stereo2 ADC MIXR", NULL, "adc stereo2 filter" },
+ { "adc stereo2 filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXL" },
+ { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXR" },
+
+ { "Sto3 ADC MIXL", "ADC1 Switch", "Stereo3 ADC1 Mux" },
+ { "Sto3 ADC MIXL", "ADC2 Switch", "Stereo3 ADC2 Mux" },
+ { "Sto3 ADC MIXR", "ADC1 Switch", "Stereo3 ADC1 Mux" },
+ { "Sto3 ADC MIXR", "ADC2 Switch", "Stereo3 ADC2 Mux" },
+
+ { "Stereo3 ADC MIXL", NULL, "Sto3 ADC MIXL" },
+ { "Stereo3 ADC MIXL", NULL, "adc stereo3 filter" },
+ { "adc stereo3 filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "Stereo3 ADC MIXR", NULL, "Sto3 ADC MIXR" },
+ { "Stereo3 ADC MIXR", NULL, "adc stereo3 filter" },
+ { "adc stereo3 filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "Stereo3 ADC MIX", NULL, "Stereo3 ADC MIXL" },
+ { "Stereo3 ADC MIX", NULL, "Stereo3 ADC MIXR" },
+
+ { "Sto4 ADC MIXL", "ADC1 Switch", "Stereo4 ADC1 Mux" },
+ { "Sto4 ADC MIXL", "ADC2 Switch", "Stereo4 ADC2 Mux" },
+ { "Sto4 ADC MIXR", "ADC1 Switch", "Stereo4 ADC1 Mux" },
+ { "Sto4 ADC MIXR", "ADC2 Switch", "Stereo4 ADC2 Mux" },
+
+ { "Stereo4 ADC MIXL", NULL, "Sto4 ADC MIXL" },
+ { "Stereo4 ADC MIXL", NULL, "adc stereo4 filter" },
+ { "adc stereo4 filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "Stereo4 ADC MIXR", NULL, "Sto4 ADC MIXR" },
+ { "Stereo4 ADC MIXR", NULL, "adc stereo4 filter" },
+ { "adc stereo4 filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "Stereo4 ADC MIX", NULL, "Stereo4 ADC MIXL" },
+ { "Stereo4 ADC MIX", NULL, "Stereo4 ADC MIXR" },
+
+ { "Mono ADC MIXL", "ADC1 Switch", "Mono ADC1 L Mux" },
+ { "Mono ADC MIXL", "ADC2 Switch", "Mono ADC2 L Mux" },
+ { "Mono ADC MIXL", NULL, "adc mono left filter" },
+ { "adc mono left filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "Mono ADC MIXR", "ADC1 Switch", "Mono ADC1 R Mux" },
+ { "Mono ADC MIXR", "ADC2 Switch", "Mono ADC2 R Mux" },
+ { "Mono ADC MIXR", NULL, "adc mono right filter" },
+ { "adc mono right filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "Mono ADC MIX", NULL, "Mono ADC MIXL" },
+ { "Mono ADC MIX", NULL, "Mono ADC MIXR" },
+
+ { "VAD ADC Mux", "STO1 ADC MIX L", "Stereo1 ADC MIXL" },
+ { "VAD ADC Mux", "MONO ADC MIX L", "Mono ADC MIXL" },
+ { "VAD ADC Mux", "MONO ADC MIX R", "Mono ADC MIXR" },
+ { "VAD ADC Mux", "STO2 ADC MIX L", "Stereo2 ADC MIXL" },
+ { "VAD ADC Mux", "STO3 ADC MIX L", "Stereo3 ADC MIXL" },
+
+ { "IF1 ADC1 Mux", "STO1 ADC MIX", "Stereo1 ADC MIX" },
+ { "IF1 ADC1 Mux", "OB01", "OB01 Bypass Mux" },
+ { "IF1 ADC1 Mux", "VAD ADC", "VAD ADC Mux" },
+
+ { "IF1 ADC2 Mux", "STO2 ADC MIX", "Stereo2 ADC MIX" },
+ { "IF1 ADC2 Mux", "OB23", "OB23 Bypass Mux" },
+
+ { "IF1 ADC3 Mux", "STO3 ADC MIX", "Stereo3 ADC MIX" },
+ { "IF1 ADC3 Mux", "MONO ADC MIX", "Mono ADC MIX" },
+ { "IF1 ADC3 Mux", "OB45", "OB45" },
+
+ { "IF1 ADC4 Mux", "STO4 ADC MIX", "Stereo4 ADC MIX" },
+ { "IF1 ADC4 Mux", "OB67", "OB67" },
+ { "IF1 ADC4 Mux", "OB01", "OB01 Bypass Mux" },
+
+ { "AIF1TX", NULL, "I2S1" },
+ { "AIF1TX", NULL, "IF1 ADC1 Mux" },
+ { "AIF1TX", NULL, "IF1 ADC2 Mux" },
+ { "AIF1TX", NULL, "IF1 ADC3 Mux" },
+ { "AIF1TX", NULL, "IF1 ADC4 Mux" },
+
+ { "IF2 ADC1 Mux", "STO1 ADC MIX", "Stereo1 ADC MIX" },
+ { "IF2 ADC1 Mux", "OB01", "OB01 Bypass Mux" },
+ { "IF2 ADC1 Mux", "VAD ADC", "VAD ADC Mux" },
+
+ { "IF2 ADC2 Mux", "STO2 ADC MIX", "Stereo2 ADC MIX" },
+ { "IF2 ADC2 Mux", "OB23", "OB23 Bypass Mux" },
+
+ { "IF2 ADC3 Mux", "STO3 ADC MIX", "Stereo3 ADC MIX" },
+ { "IF2 ADC3 Mux", "MONO ADC MIX", "Mono ADC MIX" },
+ { "IF2 ADC3 Mux", "OB45", "OB45" },
+
+ { "IF2 ADC4 Mux", "STO4 ADC MIX", "Stereo4 ADC MIX" },
+ { "IF2 ADC4 Mux", "OB67", "OB67" },
+ { "IF2 ADC4 Mux", "OB01", "OB01 Bypass Mux" },
+
+ { "AIF2TX", NULL, "I2S2" },
+ { "AIF2TX", NULL, "IF2 ADC1 Mux" },
+ { "AIF2TX", NULL, "IF2 ADC2 Mux" },
+ { "AIF2TX", NULL, "IF2 ADC3 Mux" },
+ { "AIF2TX", NULL, "IF2 ADC4 Mux" },
+
+ { "IF3 ADC Mux", "STO1 ADC MIX", "Stereo1 ADC MIX" },
+ { "IF3 ADC Mux", "STO2 ADC MIX", "Stereo2 ADC MIX" },
+ { "IF3 ADC Mux", "STO3 ADC MIX", "Stereo3 ADC MIX" },
+ { "IF3 ADC Mux", "STO4 ADC MIX", "Stereo4 ADC MIX" },
+ { "IF3 ADC Mux", "MONO ADC MIX", "Mono ADC MIX" },
+ { "IF3 ADC Mux", "OB01", "OB01 Bypass Mux" },
+ { "IF3 ADC Mux", "OB23", "OB23 Bypass Mux" },
+ { "IF3 ADC Mux", "VAD ADC", "VAD ADC Mux" },
+
+ { "AIF3TX", NULL, "I2S3" },
+ { "AIF3TX", NULL, "IF3 ADC Mux" },
+
+ { "IF4 ADC Mux", "STO1 ADC MIX", "Stereo1 ADC MIX" },
+ { "IF4 ADC Mux", "STO2 ADC MIX", "Stereo2 ADC MIX" },
+ { "IF4 ADC Mux", "STO3 ADC MIX", "Stereo3 ADC MIX" },
+ { "IF4 ADC Mux", "STO4 ADC MIX", "Stereo4 ADC MIX" },
+ { "IF4 ADC Mux", "MONO ADC MIX", "Mono ADC MIX" },
+ { "IF4 ADC Mux", "OB01", "OB01 Bypass Mux" },
+ { "IF4 ADC Mux", "OB23", "OB23 Bypass Mux" },
+ { "IF4 ADC Mux", "VAD ADC", "VAD ADC Mux" },
+
+ { "AIF4TX", NULL, "I2S4" },
+ { "AIF4TX", NULL, "IF4 ADC Mux" },
+
+ { "SLB ADC1 Mux", "STO1 ADC MIX", "Stereo1 ADC MIX" },
+ { "SLB ADC1 Mux", "OB01", "OB01 Bypass Mux" },
+ { "SLB ADC1 Mux", "VAD ADC", "VAD ADC Mux" },
+
+ { "SLB ADC2 Mux", "STO2 ADC MIX", "Stereo2 ADC MIX" },
+ { "SLB ADC2 Mux", "OB23", "OB23 Bypass Mux" },
+
+ { "SLB ADC3 Mux", "STO3 ADC MIX", "Stereo3 ADC MIX" },
+ { "SLB ADC3 Mux", "MONO ADC MIX", "Mono ADC MIX" },
+ { "SLB ADC3 Mux", "OB45", "OB45" },
+
+ { "SLB ADC4 Mux", "STO4 ADC MIX", "Stereo4 ADC MIX" },
+ { "SLB ADC4 Mux", "OB67", "OB67" },
+ { "SLB ADC4 Mux", "OB01", "OB01 Bypass Mux" },
+
+ { "SLBTX", NULL, "SLB" },
+ { "SLBTX", NULL, "SLB ADC1 Mux" },
+ { "SLBTX", NULL, "SLB ADC2 Mux" },
+ { "SLBTX", NULL, "SLB ADC3 Mux" },
+ { "SLBTX", NULL, "SLB ADC4 Mux" },
+
+ { "IB01 Mux", "IF1 DAC 01", "IF1 DAC01" },
+ { "IB01 Mux", "IF2 DAC 01", "IF2 DAC01" },
+ { "IB01 Mux", "SLB DAC 01", "SLB DAC01" },
+ { "IB01 Mux", "STO1 ADC MIX", "Stereo1 ADC MIX" },
+ { "IB01 Mux", "VAD ADC/DAC1 FS", "DAC1 FS" },
+
+ { "IB01 Bypass Mux", "Bypass", "IB01 Mux" },
+ { "IB01 Bypass Mux", "Pass SRC", "IB01 Mux" },
+
+ { "IB23 Mux", "IF1 DAC 23", "IF1 DAC23" },
+ { "IB23 Mux", "IF2 DAC 23", "IF2 DAC23" },
+ { "IB23 Mux", "SLB DAC 23", "SLB DAC23" },
+ { "IB23 Mux", "STO2 ADC MIX", "Stereo2 ADC MIX" },
+ { "IB23 Mux", "DAC1 FS", "DAC1 FS" },
+ { "IB23 Mux", "IF4 DAC", "IF4 DAC" },
+
+ { "IB23 Bypass Mux", "Bypass", "IB23 Mux" },
+ { "IB23 Bypass Mux", "Pass SRC", "IB23 Mux" },
+
+ { "IB45 Mux", "IF1 DAC 45", "IF1 DAC45" },
+ { "IB45 Mux", "IF2 DAC 45", "IF2 DAC45" },
+ { "IB45 Mux", "SLB DAC 45", "SLB DAC45" },
+ { "IB45 Mux", "STO3 ADC MIX", "Stereo3 ADC MIX" },
+ { "IB45 Mux", "IF3 DAC", "IF3 DAC" },
+
+ { "IB45 Bypass Mux", "Bypass", "IB45 Mux" },
+ { "IB45 Bypass Mux", "Pass SRC", "IB45 Mux" },
+
+ { "IB6 Mux", "IF1 DAC 6", "IF1 DAC6" },
+ { "IB6 Mux", "IF2 DAC 6", "IF2 DAC6" },
+ { "IB6 Mux", "SLB DAC 6", "SLB DAC6" },
+ { "IB6 Mux", "STO4 ADC MIX L", "Stereo4 ADC MIXL" },
+ { "IB6 Mux", "IF4 DAC L", "IF4 DAC L" },
+ { "IB6 Mux", "STO1 ADC MIX L", "Stereo1 ADC MIXL" },
+ { "IB6 Mux", "STO2 ADC MIX L", "Stereo2 ADC MIXL" },
+ { "IB6 Mux", "STO3 ADC MIX L", "Stereo3 ADC MIXL" },
+
+ { "IB7 Mux", "IF1 DAC 7", "IF1 DAC7" },
+ { "IB7 Mux", "IF2 DAC 7", "IF2 DAC7" },
+ { "IB7 Mux", "SLB DAC 7", "SLB DAC7" },
+ { "IB7 Mux", "STO4 ADC MIX R", "Stereo4 ADC MIXR" },
+ { "IB7 Mux", "IF4 DAC R", "IF4 DAC R" },
+ { "IB7 Mux", "STO1 ADC MIX R", "Stereo1 ADC MIXR" },
+ { "IB7 Mux", "STO2 ADC MIX R", "Stereo2 ADC MIXR" },
+ { "IB7 Mux", "STO3 ADC MIX R", "Stereo3 ADC MIXR" },
+
+ { "IB8 Mux", "STO1 ADC MIX L", "Stereo1 ADC MIXL" },
+ { "IB8 Mux", "STO2 ADC MIX L", "Stereo2 ADC MIXL" },
+ { "IB8 Mux", "STO3 ADC MIX L", "Stereo3 ADC MIXL" },
+ { "IB8 Mux", "STO4 ADC MIX L", "Stereo4 ADC MIXL" },
+ { "IB8 Mux", "MONO ADC MIX L", "Mono ADC MIXL" },
+ { "IB8 Mux", "DACL1 FS", "DAC1 MIXL" },
+
+ { "IB9 Mux", "STO1 ADC MIX R", "Stereo1 ADC MIXR" },
+ { "IB9 Mux", "STO2 ADC MIX R", "Stereo2 ADC MIXR" },
+ { "IB9 Mux", "STO3 ADC MIX R", "Stereo3 ADC MIXR" },
+ { "IB9 Mux", "STO4 ADC MIX R", "Stereo4 ADC MIXR" },
+ { "IB9 Mux", "MONO ADC MIX R", "Mono ADC MIXR" },
+ { "IB9 Mux", "DACR1 FS", "DAC1 MIXR" },
+ { "IB9 Mux", "DAC1 FS", "DAC1 FS" },
+
+ { "OB01 MIX", "IB01 Switch", "IB01 Bypass Mux" },
+ { "OB01 MIX", "IB23 Switch", "IB23 Bypass Mux" },
+ { "OB01 MIX", "IB45 Switch", "IB45 Bypass Mux" },
+ { "OB01 MIX", "IB6 Switch", "IB6 Mux" },
+ { "OB01 MIX", "IB7 Switch", "IB7 Mux" },
+ { "OB01 MIX", "IB8 Switch", "IB8 Mux" },
+ { "OB01 MIX", "IB9 Switch", "IB9 Mux" },
+
+ { "OB23 MIX", "IB01 Switch", "IB01 Bypass Mux" },
+ { "OB23 MIX", "IB23 Switch", "IB23 Bypass Mux" },
+ { "OB23 MIX", "IB45 Switch", "IB45 Bypass Mux" },
+ { "OB23 MIX", "IB6 Switch", "IB6 Mux" },
+ { "OB23 MIX", "IB7 Switch", "IB7 Mux" },
+ { "OB23 MIX", "IB8 Switch", "IB8 Mux" },
+ { "OB23 MIX", "IB9 Switch", "IB9 Mux" },
+
+ { "OB4 MIX", "IB01 Switch", "IB01 Bypass Mux" },
+ { "OB4 MIX", "IB23 Switch", "IB23 Bypass Mux" },
+ { "OB4 MIX", "IB45 Switch", "IB45 Bypass Mux" },
+ { "OB4 MIX", "IB6 Switch", "IB6 Mux" },
+ { "OB4 MIX", "IB7 Switch", "IB7 Mux" },
+ { "OB4 MIX", "IB8 Switch", "IB8 Mux" },
+ { "OB4 MIX", "IB9 Switch", "IB9 Mux" },
+
+ { "OB5 MIX", "IB01 Switch", "IB01 Bypass Mux" },
+ { "OB5 MIX", "IB23 Switch", "IB23 Bypass Mux" },
+ { "OB5 MIX", "IB45 Switch", "IB45 Bypass Mux" },
+ { "OB5 MIX", "IB6 Switch", "IB6 Mux" },
+ { "OB5 MIX", "IB7 Switch", "IB7 Mux" },
+ { "OB5 MIX", "IB8 Switch", "IB8 Mux" },
+ { "OB5 MIX", "IB9 Switch", "IB9 Mux" },
+
+ { "OB6 MIX", "IB01 Switch", "IB01 Bypass Mux" },
+ { "OB6 MIX", "IB23 Switch", "IB23 Bypass Mux" },
+ { "OB6 MIX", "IB45 Switch", "IB45 Bypass Mux" },
+ { "OB6 MIX", "IB6 Switch", "IB6 Mux" },
+ { "OB6 MIX", "IB7 Switch", "IB7 Mux" },
+ { "OB6 MIX", "IB8 Switch", "IB8 Mux" },
+ { "OB6 MIX", "IB9 Switch", "IB9 Mux" },
+
+ { "OB7 MIX", "IB01 Switch", "IB01 Bypass Mux" },
+ { "OB7 MIX", "IB23 Switch", "IB23 Bypass Mux" },
+ { "OB7 MIX", "IB45 Switch", "IB45 Bypass Mux" },
+ { "OB7 MIX", "IB6 Switch", "IB6 Mux" },
+ { "OB7 MIX", "IB7 Switch", "IB7 Mux" },
+ { "OB7 MIX", "IB8 Switch", "IB8 Mux" },
+ { "OB7 MIX", "IB9 Switch", "IB9 Mux" },
+
+ { "OB01 Bypass Mux", "Bypass", "OB01 MIX" },
+ { "OB01 Bypass Mux", "Pass SRC", "OB01 MIX" },
+ { "OB23 Bypass Mux", "Bypass", "OB23 MIX" },
+ { "OB23 Bypass Mux", "Pass SRC", "OB23 MIX" },
+
+ { "OutBound2", NULL, "OB23 Bypass Mux" },
+ { "OutBound3", NULL, "OB23 Bypass Mux" },
+ { "OutBound4", NULL, "OB4 MIX" },
+ { "OutBound5", NULL, "OB5 MIX" },
+ { "OutBound6", NULL, "OB6 MIX" },
+ { "OutBound7", NULL, "OB7 MIX" },
+
+ { "OB45", NULL, "OutBound4" },
+ { "OB45", NULL, "OutBound5" },
+ { "OB67", NULL, "OutBound6" },
+ { "OB67", NULL, "OutBound7" },
+
+ { "IF1 DAC0", NULL, "AIF1RX" },
+ { "IF1 DAC1", NULL, "AIF1RX" },
+ { "IF1 DAC2", NULL, "AIF1RX" },
+ { "IF1 DAC3", NULL, "AIF1RX" },
+ { "IF1 DAC4", NULL, "AIF1RX" },
+ { "IF1 DAC5", NULL, "AIF1RX" },
+ { "IF1 DAC6", NULL, "AIF1RX" },
+ { "IF1 DAC7", NULL, "AIF1RX" },
+ { "IF1 DAC0", NULL, "I2S1" },
+ { "IF1 DAC1", NULL, "I2S1" },
+ { "IF1 DAC2", NULL, "I2S1" },
+ { "IF1 DAC3", NULL, "I2S1" },
+ { "IF1 DAC4", NULL, "I2S1" },
+ { "IF1 DAC5", NULL, "I2S1" },
+ { "IF1 DAC6", NULL, "I2S1" },
+ { "IF1 DAC7", NULL, "I2S1" },
+
+ { "IF1 DAC01", NULL, "IF1 DAC0" },
+ { "IF1 DAC01", NULL, "IF1 DAC1" },
+ { "IF1 DAC23", NULL, "IF1 DAC2" },
+ { "IF1 DAC23", NULL, "IF1 DAC3" },
+ { "IF1 DAC45", NULL, "IF1 DAC4" },
+ { "IF1 DAC45", NULL, "IF1 DAC5" },
+ { "IF1 DAC67", NULL, "IF1 DAC6" },
+ { "IF1 DAC67", NULL, "IF1 DAC7" },
+
+ { "IF2 DAC0", NULL, "AIF2RX" },
+ { "IF2 DAC1", NULL, "AIF2RX" },
+ { "IF2 DAC2", NULL, "AIF2RX" },
+ { "IF2 DAC3", NULL, "AIF2RX" },
+ { "IF2 DAC4", NULL, "AIF2RX" },
+ { "IF2 DAC5", NULL, "AIF2RX" },
+ { "IF2 DAC6", NULL, "AIF2RX" },
+ { "IF2 DAC7", NULL, "AIF2RX" },
+ { "IF2 DAC0", NULL, "I2S2" },
+ { "IF2 DAC1", NULL, "I2S2" },
+ { "IF2 DAC2", NULL, "I2S2" },
+ { "IF2 DAC3", NULL, "I2S2" },
+ { "IF2 DAC4", NULL, "I2S2" },
+ { "IF2 DAC5", NULL, "I2S2" },
+ { "IF2 DAC6", NULL, "I2S2" },
+ { "IF2 DAC7", NULL, "I2S2" },
+
+ { "IF2 DAC01", NULL, "IF2 DAC0" },
+ { "IF2 DAC01", NULL, "IF2 DAC1" },
+ { "IF2 DAC23", NULL, "IF2 DAC2" },
+ { "IF2 DAC23", NULL, "IF2 DAC3" },
+ { "IF2 DAC45", NULL, "IF2 DAC4" },
+ { "IF2 DAC45", NULL, "IF2 DAC5" },
+ { "IF2 DAC67", NULL, "IF2 DAC6" },
+ { "IF2 DAC67", NULL, "IF2 DAC7" },
+
+ { "IF3 DAC", NULL, "AIF3RX" },
+ { "IF3 DAC", NULL, "I2S3" },
+
+ { "IF4 DAC", NULL, "AIF4RX" },
+ { "IF4 DAC", NULL, "I2S4" },
+
+ { "IF3 DAC L", NULL, "IF3 DAC" },
+ { "IF3 DAC R", NULL, "IF3 DAC" },
+
+ { "IF4 DAC L", NULL, "IF4 DAC" },
+ { "IF4 DAC R", NULL, "IF4 DAC" },
+
+ { "SLB DAC0", NULL, "SLBRX" },
+ { "SLB DAC1", NULL, "SLBRX" },
+ { "SLB DAC2", NULL, "SLBRX" },
+ { "SLB DAC3", NULL, "SLBRX" },
+ { "SLB DAC4", NULL, "SLBRX" },
+ { "SLB DAC5", NULL, "SLBRX" },
+ { "SLB DAC6", NULL, "SLBRX" },
+ { "SLB DAC7", NULL, "SLBRX" },
+ { "SLB DAC0", NULL, "SLB" },
+ { "SLB DAC1", NULL, "SLB" },
+ { "SLB DAC2", NULL, "SLB" },
+ { "SLB DAC3", NULL, "SLB" },
+ { "SLB DAC4", NULL, "SLB" },
+ { "SLB DAC5", NULL, "SLB" },
+ { "SLB DAC6", NULL, "SLB" },
+ { "SLB DAC7", NULL, "SLB" },
+
+ { "SLB DAC01", NULL, "SLB DAC0" },
+ { "SLB DAC01", NULL, "SLB DAC1" },
+ { "SLB DAC23", NULL, "SLB DAC2" },
+ { "SLB DAC23", NULL, "SLB DAC3" },
+ { "SLB DAC45", NULL, "SLB DAC4" },
+ { "SLB DAC45", NULL, "SLB DAC5" },
+ { "SLB DAC67", NULL, "SLB DAC6" },
+ { "SLB DAC67", NULL, "SLB DAC7" },
+
+ { "ADDA1 Mux", "STO1 ADC MIX", "Stereo1 ADC MIX" },
+ { "ADDA1 Mux", "STO2 ADC MIX", "Stereo2 ADC MIX" },
+ { "ADDA1 Mux", "OB 67", "OB67" },
+
+ { "DAC1 Mux", "IF1 DAC 01", "IF1 DAC01" },
+ { "DAC1 Mux", "IF2 DAC 01", "IF2 DAC01" },
+ { "DAC1 Mux", "IF3 DAC LR", "IF3 DAC" },
+ { "DAC1 Mux", "IF4 DAC LR", "IF4 DAC" },
+ { "DAC1 Mux", "SLB DAC 01", "SLB DAC01" },
+ { "DAC1 Mux", "OB 01", "OB01 Bypass Mux" },
+
+ { "DAC1 MIXL", "Stereo ADC Switch", "ADDA1 Mux" },
+ { "DAC1 MIXL", "DAC1 Switch", "DAC1 Mux" },
+ { "DAC1 MIXL", NULL, "dac stereo1 filter" },
+ { "DAC1 MIXR", "Stereo ADC Switch", "ADDA1 Mux" },
+ { "DAC1 MIXR", "DAC1 Switch", "DAC1 Mux" },
+ { "DAC1 MIXR", NULL, "dac stereo1 filter" },
+
+ { "DAC1 FS", NULL, "DAC1 MIXL" },
+ { "DAC1 FS", NULL, "DAC1 MIXR" },
+
+ { "DAC2 L Mux", "IF1 DAC 2", "IF1 DAC2" },
+ { "DAC2 L Mux", "IF2 DAC 2", "IF2 DAC2" },
+ { "DAC2 L Mux", "IF3 DAC L", "IF3 DAC L" },
+ { "DAC2 L Mux", "IF4 DAC L", "IF4 DAC L" },
+ { "DAC2 L Mux", "SLB DAC 2", "SLB DAC2" },
+ { "DAC2 L Mux", "OB 2", "OutBound2" },
+
+ { "DAC2 R Mux", "IF1 DAC 3", "IF1 DAC3" },
+ { "DAC2 R Mux", "IF2 DAC 3", "IF2 DAC3" },
+ { "DAC2 R Mux", "IF3 DAC R", "IF3 DAC R" },
+ { "DAC2 R Mux", "IF4 DAC R", "IF4 DAC R" },
+ { "DAC2 R Mux", "SLB DAC 3", "SLB DAC3" },
+ { "DAC2 R Mux", "OB 3", "OutBound3" },
+ { "DAC2 R Mux", "Haptic Generator", "Haptic Generator" },
+ { "DAC2 R Mux", "VAD ADC", "VAD ADC Mux" },
+
+ { "DAC3 L Mux", "IF1 DAC 4", "IF1 DAC4" },
+ { "DAC3 L Mux", "IF2 DAC 4", "IF2 DAC4" },
+ { "DAC3 L Mux", "IF3 DAC L", "IF3 DAC L" },
+ { "DAC3 L Mux", "IF4 DAC L", "IF4 DAC L" },
+ { "DAC3 L Mux", "SLB DAC 4", "SLB DAC4" },
+ { "DAC3 L Mux", "OB 4", "OutBound4" },
+
+ { "DAC3 R Mux", "IF1 DAC 5", "IF1 DAC4" },
+ { "DAC3 R Mux", "IF2 DAC 5", "IF2 DAC4" },
+ { "DAC3 R Mux", "IF3 DAC R", "IF3 DAC R" },
+ { "DAC3 R Mux", "IF4 DAC R", "IF4 DAC R" },
+ { "DAC3 R Mux", "SLB DAC 5", "SLB DAC5" },
+ { "DAC3 R Mux", "OB 5", "OutBound5" },
+
+ { "DAC4 L Mux", "IF1 DAC 6", "IF1 DAC6" },
+ { "DAC4 L Mux", "IF2 DAC 6", "IF2 DAC6" },
+ { "DAC4 L Mux", "IF3 DAC L", "IF3 DAC L" },
+ { "DAC4 L Mux", "IF4 DAC L", "IF4 DAC L" },
+ { "DAC4 L Mux", "SLB DAC 6", "SLB DAC6" },
+ { "DAC4 L Mux", "OB 6", "OutBound6" },
+
+ { "DAC4 R Mux", "IF1 DAC 7", "IF1 DAC7" },
+ { "DAC4 R Mux", "IF2 DAC 7", "IF2 DAC7" },
+ { "DAC4 R Mux", "IF3 DAC R", "IF3 DAC R" },
+ { "DAC4 R Mux", "IF4 DAC R", "IF4 DAC R" },
+ { "DAC4 R Mux", "SLB DAC 7", "SLB DAC7" },
+ { "DAC4 R Mux", "OB 7", "OutBound7" },
+
+ { "Sidetone Mux", "DMIC1 L", "DMIC L1" },
+ { "Sidetone Mux", "DMIC2 L", "DMIC L2" },
+ { "Sidetone Mux", "DMIC3 L", "DMIC L3" },
+ { "Sidetone Mux", "DMIC4 L", "DMIC L4" },
+ { "Sidetone Mux", "ADC1", "ADC 1" },
+ { "Sidetone Mux", "ADC2", "ADC 2" },
+
+ { "Stereo DAC MIXL", "ST L Switch", "Sidetone Mux" },
+ { "Stereo DAC MIXL", "DAC1 L Switch", "DAC1 MIXL" },
+ { "Stereo DAC MIXL", "DAC2 L Switch", "DAC2 L Mux" },
+ { "Stereo DAC MIXL", "DAC1 R Switch", "DAC1 MIXR" },
+ { "Stereo DAC MIXL", NULL, "dac stereo1 filter" },
+ { "Stereo DAC MIXR", "ST R Switch", "Sidetone Mux" },
+ { "Stereo DAC MIXR", "DAC1 R Switch", "DAC1 MIXR" },
+ { "Stereo DAC MIXR", "DAC2 R Switch", "DAC2 R Mux" },
+ { "Stereo DAC MIXR", "DAC1 L Switch", "DAC1 MIXL" },
+ { "Stereo DAC MIXR", NULL, "dac stereo1 filter" },
+
+ { "Mono DAC MIXL", "ST L Switch", "Sidetone Mux" },
+ { "Mono DAC MIXL", "DAC1 L Switch", "DAC1 MIXL" },
+ { "Mono DAC MIXL", "DAC2 L Switch", "DAC2 L Mux" },
+ { "Mono DAC MIXL", "DAC2 R Switch", "DAC2 R Mux" },
+ { "Mono DAC MIXL", NULL, "dac mono left filter" },
+ { "Mono DAC MIXR", "ST R Switch", "Sidetone Mux" },
+ { "Mono DAC MIXR", "DAC1 R Switch", "DAC1 MIXR" },
+ { "Mono DAC MIXR", "DAC2 R Switch", "DAC2 R Mux" },
+ { "Mono DAC MIXR", "DAC2 L Switch", "DAC2 L Mux" },
+ { "Mono DAC MIXR", NULL, "dac mono right filter" },
+
+ { "DD1 MIXL", "Sto DAC Mix L Switch", "Stereo DAC MIXL" },
+ { "DD1 MIXL", "Mono DAC Mix L Switch", "Mono DAC MIXL" },
+ { "DD1 MIXL", "DAC3 L Switch", "DAC3 L Mux" },
+ { "DD1 MIXL", "DAC3 R Switch", "DAC3 R Mux" },
+ { "DD1 MIXR", "Sto DAC Mix R Switch", "Stereo DAC MIXR" },
+ { "DD1 MIXR", "Mono DAC Mix R Switch", "Mono DAC MIXR" },
+ { "DD1 MIXR", "DAC3 L Switch", "DAC3 L Mux" },
+ { "DD1 MIXR", "DAC3 R Switch", "DAC3 R Mux" },
+
+ { "DD2 MIXL", "Sto DAC Mix L Switch", "Stereo DAC MIXL" },
+ { "DD2 MIXL", "Mono DAC Mix L Switch", "Mono DAC MIXL" },
+ { "DD2 MIXL", "DAC4 L Switch", "DAC4 L Mux" },
+ { "DD2 MIXL", "DAC4 R Switch", "DAC4 R Mux" },
+ { "DD2 MIXR", "Sto DAC Mix R Switch", "Stereo DAC MIXR" },
+ { "DD2 MIXR", "Mono DAC Mix R Switch", "Mono DAC MIXR" },
+ { "DD2 MIXR", "DAC4 L Switch", "DAC4 L Mux" },
+ { "DD2 MIXR", "DAC4 R Switch", "DAC4 R Mux" },
+
+ { "Stereo DAC MIX", NULL, "Stereo DAC MIXL" },
+ { "Stereo DAC MIX", NULL, "Stereo DAC MIXR" },
+ { "Mono DAC MIX", NULL, "Mono DAC MIXL" },
+ { "Mono DAC MIX", NULL, "Mono DAC MIXR" },
+ { "DD1 MIX", NULL, "DD1 MIXL" },
+ { "DD1 MIX", NULL, "DD1 MIXR" },
+ { "DD2 MIX", NULL, "DD2 MIXL" },
+ { "DD2 MIX", NULL, "DD2 MIXR" },
+
+ { "DAC12 SRC Mux", "STO1 DAC MIX", "Stereo DAC MIX" },
+ { "DAC12 SRC Mux", "MONO DAC MIX", "Mono DAC MIX" },
+ { "DAC12 SRC Mux", "DD MIX1", "DD1 MIX" },
+ { "DAC12 SRC Mux", "DD MIX2", "DD2 MIX" },
+
+ { "DAC3 SRC Mux", "MONO DAC MIXL", "Mono DAC MIXL" },
+ { "DAC3 SRC Mux", "MONO DAC MIXR", "Mono DAC MIXR" },
+ { "DAC3 SRC Mux", "DD MIX1L", "DD1 MIXL" },
+ { "DAC3 SRC Mux", "DD MIX2L", "DD2 MIXL" },
+
+ { "DAC 1", NULL, "DAC12 SRC Mux" },
+ { "DAC 1", NULL, "PLL1", is_sys_clk_from_pll },
+ { "DAC 2", NULL, "DAC12 SRC Mux" },
+ { "DAC 2", NULL, "PLL1", is_sys_clk_from_pll },
+ { "DAC 3", NULL, "DAC3 SRC Mux" },
+ { "DAC 3", NULL, "PLL1", is_sys_clk_from_pll },
+
+ { "PDM1 L Mux", "STO1 DAC MIX", "Stereo DAC MIXL" },
+ { "PDM1 L Mux", "MONO DAC MIX", "Mono DAC MIXL" },
+ { "PDM1 L Mux", "DD MIX1", "DD1 MIXL" },
+ { "PDM1 L Mux", "DD MIX2", "DD2 MIXL" },
+ { "PDM1 L Mux", NULL, "PDM1 Power" },
+ { "PDM1 R Mux", "STO1 DAC MIX", "Stereo DAC MIXR" },
+ { "PDM1 R Mux", "MONO DAC MIX", "Mono DAC MIXR" },
+ { "PDM1 R Mux", "DD MIX1", "DD1 MIXR" },
+ { "PDM1 R Mux", "DD MIX2", "DD2 MIXR" },
+ { "PDM1 R Mux", NULL, "PDM1 Power" },
+ { "PDM2 L Mux", "STO1 DAC MIX", "Stereo DAC MIXL" },
+ { "PDM2 L Mux", "MONO DAC MIX", "Mono DAC MIXL" },
+ { "PDM2 L Mux", "DD MIX1", "DD1 MIXL" },
+ { "PDM2 L Mux", "DD MIX2", "DD2 MIXL" },
+ { "PDM2 L Mux", NULL, "PDM2 Power" },
+ { "PDM2 R Mux", "STO1 DAC MIX", "Stereo DAC MIXR" },
+ { "PDM2 R Mux", "MONO DAC MIX", "Mono DAC MIXR" },
+ { "PDM2 R Mux", "DD MIX1", "DD1 MIXR" },
+ { "PDM2 R Mux", "DD MIX1", "DD2 MIXR" },
+ { "PDM2 R Mux", NULL, "PDM2 Power" },
+
+ { "LOUT1 amp", NULL, "DAC 1" },
+ { "LOUT2 amp", NULL, "DAC 2" },
+ { "LOUT3 amp", NULL, "DAC 3" },
+
+ { "LOUT1", NULL, "LOUT1 amp" },
+ { "LOUT2", NULL, "LOUT2 amp" },
+ { "LOUT3", NULL, "LOUT3 amp" },
+
+ { "PDM1L", NULL, "PDM1 L Mux" },
+ { "PDM1R", NULL, "PDM1 R Mux" },
+ { "PDM2L", NULL, "PDM2 L Mux" },
+ { "PDM2R", NULL, "PDM2 R Mux" },
+};
+
+static int get_clk_info(int sclk, int rate)
+{
+ int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
+
+ if (sclk <= 0 || rate <= 0)
+ return -EINVAL;
+
+ rate = rate << 8;
+ for (i = 0; i < ARRAY_SIZE(pd); i++)
+ if (sclk == rate * pd[i])
+ return i;
+
+ return -EINVAL;
+}
+
+static int rt5677_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;
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+ unsigned int val_len = 0, val_clk, mask_clk;
+ int pre_div, bclk_ms, frame_size;
+
+ rt5677->lrck[dai->id] = params_rate(params);
+ pre_div = get_clk_info(rt5677->sysclk, rt5677->lrck[dai->id]);
+ if (pre_div < 0) {
+ dev_err(codec->dev, "Unsupported clock setting\n");
+ return -EINVAL;
+ }
+ frame_size = snd_soc_params_to_frame_size(params);
+ if (frame_size < 0) {
+ dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size);
+ return -EINVAL;
+ }
+ bclk_ms = frame_size > 32;
+ rt5677->bclk[dai->id] = rt5677->lrck[dai->id] * (32 << bclk_ms);
+
+ dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n",
+ rt5677->bclk[dai->id], rt5677->lrck[dai->id]);
+ dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
+ bclk_ms, pre_div, dai->id);
+
+ switch (params_width(params)) {
+ case 16:
+ break;
+ case 20:
+ val_len |= RT5677_I2S_DL_20;
+ break;
+ case 24:
+ val_len |= RT5677_I2S_DL_24;
+ break;
+ case 8:
+ val_len |= RT5677_I2S_DL_8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (dai->id) {
+ case RT5677_AIF1:
+ mask_clk = RT5677_I2S_PD1_MASK;
+ val_clk = pre_div << RT5677_I2S_PD1_SFT;
+ regmap_update_bits(rt5677->regmap, RT5677_I2S1_SDP,
+ RT5677_I2S_DL_MASK, val_len);
+ regmap_update_bits(rt5677->regmap, RT5677_CLK_TREE_CTRL1,
+ mask_clk, val_clk);
+ break;
+ case RT5677_AIF2:
+ mask_clk = RT5677_I2S_PD2_MASK;
+ val_clk = pre_div << RT5677_I2S_PD2_SFT;
+ regmap_update_bits(rt5677->regmap, RT5677_I2S2_SDP,
+ RT5677_I2S_DL_MASK, val_len);
+ regmap_update_bits(rt5677->regmap, RT5677_CLK_TREE_CTRL1,
+ mask_clk, val_clk);
+ break;
+ case RT5677_AIF3:
+ mask_clk = RT5677_I2S_BCLK_MS3_MASK | RT5677_I2S_PD3_MASK;
+ val_clk = bclk_ms << RT5677_I2S_BCLK_MS3_SFT |
+ pre_div << RT5677_I2S_PD3_SFT;
+ regmap_update_bits(rt5677->regmap, RT5677_I2S3_SDP,
+ RT5677_I2S_DL_MASK, val_len);
+ regmap_update_bits(rt5677->regmap, RT5677_CLK_TREE_CTRL1,
+ mask_clk, val_clk);
+ break;
+ case RT5677_AIF4:
+ mask_clk = RT5677_I2S_BCLK_MS4_MASK | RT5677_I2S_PD4_MASK;
+ val_clk = bclk_ms << RT5677_I2S_BCLK_MS4_SFT |
+ pre_div << RT5677_I2S_PD4_SFT;
+ regmap_update_bits(rt5677->regmap, RT5677_I2S4_SDP,
+ RT5677_I2S_DL_MASK, val_len);
+ regmap_update_bits(rt5677->regmap, RT5677_CLK_TREE_CTRL1,
+ mask_clk, val_clk);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int rt5677_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+ unsigned int reg_val = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ rt5677->master[dai->id] = 1;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ reg_val |= RT5677_I2S_MS_S;
+ rt5677->master[dai->id] = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ reg_val |= RT5677_I2S_BP_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ reg_val |= RT5677_I2S_DF_LEFT;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ reg_val |= RT5677_I2S_DF_PCM_A;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ reg_val |= RT5677_I2S_DF_PCM_B;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (dai->id) {
+ case RT5677_AIF1:
+ regmap_update_bits(rt5677->regmap, RT5677_I2S1_SDP,
+ RT5677_I2S_MS_MASK | RT5677_I2S_BP_MASK |
+ RT5677_I2S_DF_MASK, reg_val);
+ break;
+ case RT5677_AIF2:
+ regmap_update_bits(rt5677->regmap, RT5677_I2S2_SDP,
+ RT5677_I2S_MS_MASK | RT5677_I2S_BP_MASK |
+ RT5677_I2S_DF_MASK, reg_val);
+ break;
+ case RT5677_AIF3:
+ regmap_update_bits(rt5677->regmap, RT5677_I2S3_SDP,
+ RT5677_I2S_MS_MASK | RT5677_I2S_BP_MASK |
+ RT5677_I2S_DF_MASK, reg_val);
+ break;
+ case RT5677_AIF4:
+ regmap_update_bits(rt5677->regmap, RT5677_I2S4_SDP,
+ RT5677_I2S_MS_MASK | RT5677_I2S_BP_MASK |
+ RT5677_I2S_DF_MASK, reg_val);
+ break;
+ default:
+ break;
+ }
+
+
+ return 0;
+}
+
+static int rt5677_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+ unsigned int reg_val = 0;
+
+ if (freq == rt5677->sysclk && clk_id == rt5677->sysclk_src)
+ return 0;
+
+ switch (clk_id) {
+ case RT5677_SCLK_S_MCLK:
+ reg_val |= RT5677_SCLK_SRC_MCLK;
+ break;
+ case RT5677_SCLK_S_PLL1:
+ reg_val |= RT5677_SCLK_SRC_PLL1;
+ break;
+ case RT5677_SCLK_S_RCCLK:
+ reg_val |= RT5677_SCLK_SRC_RCCLK;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
+ return -EINVAL;
+ }
+ regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK1,
+ RT5677_SCLK_SRC_MASK, reg_val);
+ rt5677->sysclk = freq;
+ rt5677->sysclk_src = clk_id;
+
+ dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
+
+ return 0;
+}
+
+/**
+ * rt5677_pll_calc - Calcualte PLL M/N/K code.
+ * @freq_in: external clock provided to codec.
+ * @freq_out: target clock which codec works on.
+ * @pll_code: Pointer to structure with M, N, K, bypass K and bypass M flag.
+ *
+ * Calcualte M/N/K code and bypass K/M flag to configure PLL for codec.
+ *
+ * Returns 0 for success or negative error code.
+ */
+static int rt5677_pll_calc(const unsigned int freq_in,
+ const unsigned int freq_out, struct rt5677_pll_code *pll_code)
+{
+ int max_n = RT5677_PLL_N_MAX, max_m = RT5677_PLL_M_MAX;
+ int k, red, n_t, pll_out, in_t;
+ int n = 0, m = 0, m_t = 0;
+ int out_t, red_t = abs(freq_out - freq_in);
+ bool m_bp = false, k_bp = false;
+
+ if (RT5677_PLL_INP_MAX < freq_in || RT5677_PLL_INP_MIN > freq_in)
+ return -EINVAL;
+
+ k = 100000000 / freq_out - 2;
+ if (k > RT5677_PLL_K_MAX)
+ k = RT5677_PLL_K_MAX;
+ for (n_t = 0; n_t <= max_n; n_t++) {
+ in_t = freq_in / (k + 2);
+ pll_out = freq_out / (n_t + 2);
+ if (in_t < 0)
+ continue;
+ if (in_t == pll_out) {
+ m_bp = true;
+ n = n_t;
+ goto code_find;
+ }
+ red = abs(in_t - pll_out);
+ if (red < red_t) {
+ m_bp = true;
+ n = n_t;
+ m = m_t;
+ if (red == 0)
+ goto code_find;
+ red_t = red;
+ }
+ for (m_t = 0; m_t <= max_m; m_t++) {
+ out_t = in_t / (m_t + 2);
+ red = abs(out_t - pll_out);
+ if (red < red_t) {
+ m_bp = false;
+ n = n_t;
+ m = m_t;
+ if (red == 0)
+ goto code_find;
+ red_t = red;
+ }
+ }
+ }
+ pr_debug("Only get approximation about PLL\n");
+
+code_find:
+
+ pll_code->m_bp = m_bp;
+ pll_code->k_bp = k_bp;
+ pll_code->m_code = m;
+ pll_code->n_code = n;
+ pll_code->k_code = k;
+ return 0;
+}
+
+static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
+ unsigned int freq_in, unsigned int freq_out)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+ struct rt5677_pll_code pll_code;
+ int ret;
+
+ if (source == rt5677->pll_src && freq_in == rt5677->pll_in &&
+ freq_out == rt5677->pll_out)
+ return 0;
+
+ if (!freq_in || !freq_out) {
+ dev_dbg(codec->dev, "PLL disabled\n");
+
+ rt5677->pll_in = 0;
+ rt5677->pll_out = 0;
+ regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK1,
+ RT5677_SCLK_SRC_MASK, RT5677_SCLK_SRC_MCLK);
+ return 0;
+ }
+
+ switch (source) {
+ case RT5677_PLL1_S_MCLK:
+ regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK1,
+ RT5677_PLL1_SRC_MASK, RT5677_PLL1_SRC_MCLK);
+ break;
+ case RT5677_PLL1_S_BCLK1:
+ case RT5677_PLL1_S_BCLK2:
+ case RT5677_PLL1_S_BCLK3:
+ case RT5677_PLL1_S_BCLK4:
+ switch (dai->id) {
+ case RT5677_AIF1:
+ regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK1,
+ RT5677_PLL1_SRC_MASK, RT5677_PLL1_SRC_BCLK1);
+ break;
+ case RT5677_AIF2:
+ regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK1,
+ RT5677_PLL1_SRC_MASK, RT5677_PLL1_SRC_BCLK2);
+ break;
+ case RT5677_AIF3:
+ regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK1,
+ RT5677_PLL1_SRC_MASK, RT5677_PLL1_SRC_BCLK3);
+ break;
+ case RT5677_AIF4:
+ regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK1,
+ RT5677_PLL1_SRC_MASK, RT5677_PLL1_SRC_BCLK4);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ dev_err(codec->dev, "Unknown PLL source %d\n", source);
+ return -EINVAL;
+ }
+
+ ret = rt5677_pll_calc(freq_in, freq_out, &pll_code);
+ if (ret < 0) {
+ dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
+ return ret;
+ }
+
+ dev_dbg(codec->dev, "m_bypass=%d k_bypass=%d m=%d n=%d k=%d\n",
+ pll_code.m_bp, pll_code.k_bp,
+ (pll_code.m_bp ? 0 : pll_code.m_code), pll_code.n_code,
+ (pll_code.k_bp ? 0 : pll_code.k_code));
+
+ regmap_write(rt5677->regmap, RT5677_PLL1_CTRL1,
+ pll_code.n_code << RT5677_PLL_N_SFT |
+ pll_code.k_bp << RT5677_PLL_K_BP_SFT |
+ (pll_code.k_bp ? 0 : pll_code.k_code));
+ regmap_write(rt5677->regmap, RT5677_PLL1_CTRL2,
+ (pll_code.m_bp ? 0 : pll_code.m_code) << RT5677_PLL_M_SFT |
+ pll_code.m_bp << RT5677_PLL_M_BP_SFT);
+
+ rt5677->pll_in = freq_in;
+ rt5677->pll_out = freq_out;
+ rt5677->pll_src = source;
+
+ return 0;
+}
+
+static int rt5677_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
+ regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1,
+ RT5677_LDO1_SEL_MASK | RT5677_LDO2_SEL_MASK,
+ 0x0055);
+ regmap_update_bits(rt5677->regmap,
+ RT5677_PR_BASE + RT5677_BIAS_CUR4,
+ 0x0f00, 0x0f00);
+ regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1,
+ RT5677_PWR_VREF1 | RT5677_PWR_MB |
+ RT5677_PWR_BG | RT5677_PWR_VREF2,
+ RT5677_PWR_VREF1 | RT5677_PWR_MB |
+ RT5677_PWR_BG | RT5677_PWR_VREF2);
+ mdelay(20);
+ regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1,
+ RT5677_PWR_FV1 | RT5677_PWR_FV2,
+ RT5677_PWR_FV1 | RT5677_PWR_FV2);
+ regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
+ RT5677_PWR_CORE, RT5677_PWR_CORE);
+ regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC,
+ 0x1, 0x1);
+ }
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x1, 0x0);
+ regmap_write(rt5677->regmap, RT5677_PWR_DIG1, 0x0000);
+ regmap_write(rt5677->regmap, RT5677_PWR_DIG2, 0x0000);
+ regmap_write(rt5677->regmap, RT5677_PWR_ANLG1, 0x0000);
+ regmap_write(rt5677->regmap, RT5677_PWR_ANLG2, 0x0000);
+ regmap_update_bits(rt5677->regmap,
+ RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000);
+ break;
+
+ default:
+ break;
+ }
+ codec->dapm.bias_level = level;
+
+ return 0;
+}
+
+static int rt5677_probe(struct snd_soc_codec *codec)
+{
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+
+ rt5677->codec = codec;
+
+ rt5677_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ regmap_write(rt5677->regmap, RT5677_DIG_MISC, 0x0020);
+ regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x0c00);
+
+ return 0;
+}
+
+static int rt5677_remove(struct snd_soc_codec *codec)
+{
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+
+ regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt5677_suspend(struct snd_soc_codec *codec)
+{
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_cache_only(rt5677->regmap, true);
+ regcache_mark_dirty(rt5677->regmap);
+
+ return 0;
+}
+
+static int rt5677_resume(struct snd_soc_codec *codec)
+{
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_cache_only(rt5677->regmap, false);
+ regcache_sync(rt5677->regmap);
+
+ return 0;
+}
+#else
+#define rt5677_suspend NULL
+#define rt5677_resume NULL
+#endif
+
+#define RT5677_STEREO_RATES SNDRV_PCM_RATE_8000_96000
+#define RT5677_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
+
+static struct snd_soc_dai_ops rt5677_aif_dai_ops = {
+ .hw_params = rt5677_hw_params,
+ .set_fmt = rt5677_set_dai_fmt,
+ .set_sysclk = rt5677_set_dai_sysclk,
+ .set_pll = rt5677_set_dai_pll,
+};
+
+static struct snd_soc_dai_driver rt5677_dai[] = {
+ {
+ .name = "rt5677-aif1",
+ .id = RT5677_AIF1,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5677_STEREO_RATES,
+ .formats = RT5677_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5677_STEREO_RATES,
+ .formats = RT5677_FORMATS,
+ },
+ .ops = &rt5677_aif_dai_ops,
+ },
+ {
+ .name = "rt5677-aif2",
+ .id = RT5677_AIF2,
+ .playback = {
+ .stream_name = "AIF2 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5677_STEREO_RATES,
+ .formats = RT5677_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5677_STEREO_RATES,
+ .formats = RT5677_FORMATS,
+ },
+ .ops = &rt5677_aif_dai_ops,
+ },
+ {
+ .name = "rt5677-aif3",
+ .id = RT5677_AIF3,
+ .playback = {
+ .stream_name = "AIF3 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5677_STEREO_RATES,
+ .formats = RT5677_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF3 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5677_STEREO_RATES,
+ .formats = RT5677_FORMATS,
+ },
+ .ops = &rt5677_aif_dai_ops,
+ },
+ {
+ .name = "rt5677-aif4",
+ .id = RT5677_AIF4,
+ .playback = {
+ .stream_name = "AIF4 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5677_STEREO_RATES,
+ .formats = RT5677_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF4 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5677_STEREO_RATES,
+ .formats = RT5677_FORMATS,
+ },
+ .ops = &rt5677_aif_dai_ops,
+ },
+ {
+ .name = "rt5677-slimbus",
+ .id = RT5677_AIF5,
+ .playback = {
+ .stream_name = "SLIMBus Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5677_STEREO_RATES,
+ .formats = RT5677_FORMATS,
+ },
+ .capture = {
+ .stream_name = "SLIMBus Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5677_STEREO_RATES,
+ .formats = RT5677_FORMATS,
+ },
+ .ops = &rt5677_aif_dai_ops,
+ },
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt5677 = {
+ .probe = rt5677_probe,
+ .remove = rt5677_remove,
+ .suspend = rt5677_suspend,
+ .resume = rt5677_resume,
+ .set_bias_level = rt5677_set_bias_level,
+ .idle_bias_off = true,
+ .controls = rt5677_snd_controls,
+ .num_controls = ARRAY_SIZE(rt5677_snd_controls),
+ .dapm_widgets = rt5677_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(rt5677_dapm_widgets),
+ .dapm_routes = rt5677_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(rt5677_dapm_routes),
+};
+
+static const struct regmap_config rt5677_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = RT5677_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5677_ranges) *
+ RT5677_PR_SPACING),
+
+ .volatile_reg = rt5677_volatile_register,
+ .readable_reg = rt5677_readable_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = rt5677_reg,
+ .num_reg_defaults = ARRAY_SIZE(rt5677_reg),
+ .ranges = rt5677_ranges,
+ .num_ranges = ARRAY_SIZE(rt5677_ranges),
+};
+
+static const struct i2c_device_id rt5677_i2c_id[] = {
+ { "rt5677", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id);
+
+static int rt5677_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct rt5677_platform_data *pdata = dev_get_platdata(&i2c->dev);
+ struct rt5677_priv *rt5677;
+ int ret;
+ unsigned int val;
+
+ rt5677 = devm_kzalloc(&i2c->dev, sizeof(struct rt5677_priv),
+ GFP_KERNEL);
+ if (rt5677 == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, rt5677);
+
+ if (pdata)
+ rt5677->pdata = *pdata;
+
+ rt5677->regmap = devm_regmap_init_i2c(i2c, &rt5677_regmap);
+ if (IS_ERR(rt5677->regmap)) {
+ ret = PTR_ERR(rt5677->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ regmap_read(rt5677->regmap, RT5677_VENDOR_ID2, &val);
+ if (val != RT5677_DEVICE_ID) {
+ dev_err(&i2c->dev,
+ "Device with ID register %x is not rt5677\n", val);
+ return -ENODEV;
+ }
+
+ regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec);
+
+ ret = regmap_register_patch(rt5677->regmap, init_list,
+ ARRAY_SIZE(init_list));
+ if (ret != 0)
+ dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
+
+ if (rt5677->pdata.in1_diff)
+ regmap_update_bits(rt5677->regmap, RT5677_IN1,
+ RT5677_IN_DF1, RT5677_IN_DF1);
+
+ if (rt5677->pdata.in2_diff)
+ regmap_update_bits(rt5677->regmap, RT5677_IN1,
+ RT5677_IN_DF2, RT5677_IN_DF2);
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677,
+ rt5677_dai, ARRAY_SIZE(rt5677_dai));
+ if (ret < 0)
+ goto err;
+
+ return 0;
+err:
+ return ret;
+}
+
+static int rt5677_i2c_remove(struct i2c_client *i2c)
+{
+ snd_soc_unregister_codec(&i2c->dev);
+
+ return 0;
+}
+
+static struct i2c_driver rt5677_i2c_driver = {
+ .driver = {
+ .name = "rt5677",
+ .owner = THIS_MODULE,
+ },
+ .probe = rt5677_i2c_probe,
+ .remove = rt5677_i2c_remove,
+ .id_table = rt5677_i2c_id,
+};
+
+static int __init rt5677_modinit(void)
+{
+ return i2c_add_driver(&rt5677_i2c_driver);
+}
+module_init(rt5677_modinit);
+
+static void __exit rt5677_modexit(void)
+{
+ i2c_del_driver(&rt5677_i2c_driver);
+}
+module_exit(rt5677_modexit);
+
+MODULE_DESCRIPTION("ASoC RT5677 driver");
+MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h
new file mode 100644
index 00000000000..af4e9c79740
--- /dev/null
+++ b/sound/soc/codecs/rt5677.h
@@ -0,0 +1,1451 @@
+/*
+ * rt5677.h -- RT5677 ALSA SoC audio driver
+ *
+ * Copyright 2013 Realtek Semiconductor Corp.
+ * Author: Oder Chiou <oder_chiou@realtek.com>
+ *
+ * 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 __RT5677_H__
+#define __RT5677_H__
+
+#include <sound/rt5677.h>
+
+/* Info */
+#define RT5677_RESET 0x00
+#define RT5677_VENDOR_ID 0xfd
+#define RT5677_VENDOR_ID1 0xfe
+#define RT5677_VENDOR_ID2 0xff
+/* I/O - Output */
+#define RT5677_LOUT1 0x01
+/* I/O - Input */
+#define RT5677_IN1 0x03
+#define RT5677_MICBIAS 0x04
+/* I/O - SLIMBus */
+#define RT5677_SLIMBUS_PARAM 0x07
+#define RT5677_SLIMBUS_RX 0x08
+#define RT5677_SLIMBUS_CTRL 0x09
+/* I/O */
+#define RT5677_SIDETONE_CTRL 0x13
+/* I/O - ADC/DAC */
+#define RT5677_ANA_DAC1_2_3_SRC 0x15
+#define RT5677_IF_DSP_DAC3_4_MIXER 0x16
+#define RT5677_DAC4_DIG_VOL 0x17
+#define RT5677_DAC3_DIG_VOL 0x18
+#define RT5677_DAC1_DIG_VOL 0x19
+#define RT5677_DAC2_DIG_VOL 0x1a
+#define RT5677_IF_DSP_DAC2_MIXER 0x1b
+#define RT5677_STO1_ADC_DIG_VOL 0x1c
+#define RT5677_MONO_ADC_DIG_VOL 0x1d
+#define RT5677_STO1_2_ADC_BST 0x1e
+#define RT5677_STO2_ADC_DIG_VOL 0x1f
+/* Mixer - D-D */
+#define RT5677_ADC_BST_CTRL2 0x20
+#define RT5677_STO3_4_ADC_BST 0x21
+#define RT5677_STO3_ADC_DIG_VOL 0x22
+#define RT5677_STO4_ADC_DIG_VOL 0x23
+#define RT5677_STO4_ADC_MIXER 0x24
+#define RT5677_STO3_ADC_MIXER 0x25
+#define RT5677_STO2_ADC_MIXER 0x26
+#define RT5677_STO1_ADC_MIXER 0x27
+#define RT5677_MONO_ADC_MIXER 0x28
+#define RT5677_ADC_IF_DSP_DAC1_MIXER 0x29
+#define RT5677_STO1_DAC_MIXER 0x2a
+#define RT5677_MONO_DAC_MIXER 0x2b
+#define RT5677_DD1_MIXER 0x2c
+#define RT5677_DD2_MIXER 0x2d
+#define RT5677_IF3_DATA 0x2f
+#define RT5677_IF4_DATA 0x30
+/* Mixer - PDM */
+#define RT5677_PDM_OUT_CTRL 0x31
+#define RT5677_PDM_DATA_CTRL1 0x32
+#define RT5677_PDM_DATA_CTRL2 0x33
+#define RT5677_PDM1_DATA_CTRL2 0x34
+#define RT5677_PDM1_DATA_CTRL3 0x35
+#define RT5677_PDM1_DATA_CTRL4 0x36
+#define RT5677_PDM2_DATA_CTRL2 0x37
+#define RT5677_PDM2_DATA_CTRL3 0x38
+#define RT5677_PDM2_DATA_CTRL4 0x39
+/* TDM */
+#define RT5677_TDM1_CTRL1 0x3b
+#define RT5677_TDM1_CTRL2 0x3c
+#define RT5677_TDM1_CTRL3 0x3d
+#define RT5677_TDM1_CTRL4 0x3e
+#define RT5677_TDM1_CTRL5 0x3f
+#define RT5677_TDM2_CTRL1 0x40
+#define RT5677_TDM2_CTRL2 0x41
+#define RT5677_TDM2_CTRL3 0x42
+#define RT5677_TDM2_CTRL4 0x43
+#define RT5677_TDM2_CTRL5 0x44
+/* I2C_MASTER_CTRL */
+#define RT5677_I2C_MASTER_CTRL1 0x47
+#define RT5677_I2C_MASTER_CTRL2 0x48
+#define RT5677_I2C_MASTER_CTRL3 0x49
+#define RT5677_I2C_MASTER_CTRL4 0x4a
+#define RT5677_I2C_MASTER_CTRL5 0x4b
+#define RT5677_I2C_MASTER_CTRL6 0x4c
+#define RT5677_I2C_MASTER_CTRL7 0x4d
+#define RT5677_I2C_MASTER_CTRL8 0x4e
+/* DMIC */
+#define RT5677_DMIC_CTRL1 0x50
+#define RT5677_DMIC_CTRL2 0x51
+/* Haptic Generator */
+#define RT5677_HAP_GENE_CTRL1 0x56
+#define RT5677_HAP_GENE_CTRL2 0x57
+#define RT5677_HAP_GENE_CTRL3 0x58
+#define RT5677_HAP_GENE_CTRL4 0x59
+#define RT5677_HAP_GENE_CTRL5 0x5a
+#define RT5677_HAP_GENE_CTRL6 0x5b
+#define RT5677_HAP_GENE_CTRL7 0x5c
+#define RT5677_HAP_GENE_CTRL8 0x5d
+#define RT5677_HAP_GENE_CTRL9 0x5e
+#define RT5677_HAP_GENE_CTRL10 0x5f
+/* Power */
+#define RT5677_PWR_DIG1 0x61
+#define RT5677_PWR_DIG2 0x62
+#define RT5677_PWR_ANLG1 0x63
+#define RT5677_PWR_ANLG2 0x64
+#define RT5677_PWR_DSP1 0x65
+#define RT5677_PWR_DSP_ST 0x66
+#define RT5677_PWR_DSP2 0x67
+#define RT5677_ADC_DAC_HPF_CTRL1 0x68
+/* Private Register Control */
+#define RT5677_PRIV_INDEX 0x6a
+#define RT5677_PRIV_DATA 0x6c
+/* Format - ADC/DAC */
+#define RT5677_I2S4_SDP 0x6f
+#define RT5677_I2S1_SDP 0x70
+#define RT5677_I2S2_SDP 0x71
+#define RT5677_I2S3_SDP 0x72
+#define RT5677_CLK_TREE_CTRL1 0x73
+#define RT5677_CLK_TREE_CTRL2 0x74
+#define RT5677_CLK_TREE_CTRL3 0x75
+/* Function - Analog */
+#define RT5677_PLL1_CTRL1 0x7a
+#define RT5677_PLL1_CTRL2 0x7b
+#define RT5677_PLL2_CTRL1 0x7c
+#define RT5677_PLL2_CTRL2 0x7d
+#define RT5677_GLB_CLK1 0x80
+#define RT5677_GLB_CLK2 0x81
+#define RT5677_ASRC_1 0x83
+#define RT5677_ASRC_2 0x84
+#define RT5677_ASRC_3 0x85
+#define RT5677_ASRC_4 0x86
+#define RT5677_ASRC_5 0x87
+#define RT5677_ASRC_6 0x88
+#define RT5677_ASRC_7 0x89
+#define RT5677_ASRC_8 0x8a
+#define RT5677_ASRC_9 0x8b
+#define RT5677_ASRC_10 0x8c
+#define RT5677_ASRC_11 0x8d
+#define RT5677_ASRC_12 0x8e
+#define RT5677_ASRC_13 0x8f
+#define RT5677_ASRC_14 0x90
+#define RT5677_ASRC_15 0x91
+#define RT5677_ASRC_16 0x92
+#define RT5677_ASRC_17 0x93
+#define RT5677_ASRC_18 0x94
+#define RT5677_ASRC_19 0x95
+#define RT5677_ASRC_20 0x97
+#define RT5677_ASRC_21 0x98
+#define RT5677_ASRC_22 0x99
+#define RT5677_ASRC_23 0x9a
+#define RT5677_VAD_CTRL1 0x9c
+#define RT5677_VAD_CTRL2 0x9d
+#define RT5677_VAD_CTRL3 0x9e
+#define RT5677_VAD_CTRL4 0x9f
+#define RT5677_VAD_CTRL5 0xa0
+/* Function - Digital */
+#define RT5677_DSP_INB_CTRL1 0xa3
+#define RT5677_DSP_INB_CTRL2 0xa4
+#define RT5677_DSP_IN_OUTB_CTRL 0xa5
+#define RT5677_DSP_OUTB0_1_DIG_VOL 0xa6
+#define RT5677_DSP_OUTB2_3_DIG_VOL 0xa7
+#define RT5677_DSP_OUTB4_5_DIG_VOL 0xa8
+#define RT5677_DSP_OUTB6_7_DIG_VOL 0xa9
+#define RT5677_ADC_EQ_CTRL1 0xae
+#define RT5677_ADC_EQ_CTRL2 0xaf
+#define RT5677_EQ_CTRL1 0xb0
+#define RT5677_EQ_CTRL2 0xb1
+#define RT5677_EQ_CTRL3 0xb2
+#define RT5677_SOFT_VOL_ZERO_CROSS1 0xb3
+#define RT5677_JD_CTRL1 0xb5
+#define RT5677_JD_CTRL2 0xb6
+#define RT5677_JD_CTRL3 0xb8
+#define RT5677_IRQ_CTRL1 0xbd
+#define RT5677_IRQ_CTRL2 0xbe
+#define RT5677_GPIO_ST 0xbf
+#define RT5677_GPIO_CTRL1 0xc0
+#define RT5677_GPIO_CTRL2 0xc1
+#define RT5677_GPIO_CTRL3 0xc2
+#define RT5677_STO1_ADC_HI_FILTER1 0xc5
+#define RT5677_STO1_ADC_HI_FILTER2 0xc6
+#define RT5677_MONO_ADC_HI_FILTER1 0xc7
+#define RT5677_MONO_ADC_HI_FILTER2 0xc8
+#define RT5677_STO2_ADC_HI_FILTER1 0xc9
+#define RT5677_STO2_ADC_HI_FILTER2 0xca
+#define RT5677_STO3_ADC_HI_FILTER1 0xcb
+#define RT5677_STO3_ADC_HI_FILTER2 0xcc
+#define RT5677_STO4_ADC_HI_FILTER1 0xcd
+#define RT5677_STO4_ADC_HI_FILTER2 0xce
+#define RT5677_MB_DRC_CTRL1 0xd0
+#define RT5677_DRC1_CTRL1 0xd2
+#define RT5677_DRC1_CTRL2 0xd3
+#define RT5677_DRC1_CTRL3 0xd4
+#define RT5677_DRC1_CTRL4 0xd5
+#define RT5677_DRC1_CTRL5 0xd6
+#define RT5677_DRC1_CTRL6 0xd7
+#define RT5677_DRC2_CTRL1 0xd8
+#define RT5677_DRC2_CTRL2 0xd9
+#define RT5677_DRC2_CTRL3 0xda
+#define RT5677_DRC2_CTRL4 0xdb
+#define RT5677_DRC2_CTRL5 0xdc
+#define RT5677_DRC2_CTRL6 0xdd
+#define RT5677_DRC1_HL_CTRL1 0xde
+#define RT5677_DRC1_HL_CTRL2 0xdf
+#define RT5677_DRC2_HL_CTRL1 0xe0
+#define RT5677_DRC2_HL_CTRL2 0xe1
+#define RT5677_DSP_INB1_SRC_CTRL1 0xe3
+#define RT5677_DSP_INB1_SRC_CTRL2 0xe4
+#define RT5677_DSP_INB1_SRC_CTRL3 0xe5
+#define RT5677_DSP_INB1_SRC_CTRL4 0xe6
+#define RT5677_DSP_INB2_SRC_CTRL1 0xe7
+#define RT5677_DSP_INB2_SRC_CTRL2 0xe8
+#define RT5677_DSP_INB2_SRC_CTRL3 0xe9
+#define RT5677_DSP_INB2_SRC_CTRL4 0xea
+#define RT5677_DSP_INB3_SRC_CTRL1 0xeb
+#define RT5677_DSP_INB3_SRC_CTRL2 0xec
+#define RT5677_DSP_INB3_SRC_CTRL3 0xed
+#define RT5677_DSP_INB3_SRC_CTRL4 0xee
+#define RT5677_DSP_OUTB1_SRC_CTRL1 0xef
+#define RT5677_DSP_OUTB1_SRC_CTRL2 0xf0
+#define RT5677_DSP_OUTB1_SRC_CTRL3 0xf1
+#define RT5677_DSP_OUTB1_SRC_CTRL4 0xf2
+#define RT5677_DSP_OUTB2_SRC_CTRL1 0xf3
+#define RT5677_DSP_OUTB2_SRC_CTRL2 0xf4
+#define RT5677_DSP_OUTB2_SRC_CTRL3 0xf5
+#define RT5677_DSP_OUTB2_SRC_CTRL4 0xf6
+
+/* Virtual DSP Mixer Control */
+#define RT5677_DSP_OUTB_0123_MIXER_CTRL 0xf7
+#define RT5677_DSP_OUTB_45_MIXER_CTRL 0xf8
+#define RT5677_DSP_OUTB_67_MIXER_CTRL 0xf9
+
+/* General Control */
+#define RT5677_DIG_MISC 0xfa
+#define RT5677_GEN_CTRL1 0xfb
+#define RT5677_GEN_CTRL2 0xfc
+
+/* DSP Mode I2C Control*/
+#define RT5677_DSP_I2C_OP_CODE 0x00
+#define RT5677_DSP_I2C_ADDR_LSB 0x01
+#define RT5677_DSP_I2C_ADDR_MSB 0x02
+#define RT5677_DSP_I2C_DATA_LSB 0x03
+#define RT5677_DSP_I2C_DATA_MSB 0x04
+
+/* Index of Codec Private Register definition */
+#define RT5677_PR_DRC1_CTRL_1 0x01
+#define RT5677_PR_DRC1_CTRL_2 0x02
+#define RT5677_PR_DRC1_CTRL_3 0x03
+#define RT5677_PR_DRC1_CTRL_4 0x04
+#define RT5677_PR_DRC1_CTRL_5 0x05
+#define RT5677_PR_DRC1_CTRL_6 0x06
+#define RT5677_PR_DRC1_CTRL_7 0x07
+#define RT5677_PR_DRC2_CTRL_1 0x08
+#define RT5677_PR_DRC2_CTRL_2 0x09
+#define RT5677_PR_DRC2_CTRL_3 0x0a
+#define RT5677_PR_DRC2_CTRL_4 0x0b
+#define RT5677_PR_DRC2_CTRL_5 0x0c
+#define RT5677_PR_DRC2_CTRL_6 0x0d
+#define RT5677_PR_DRC2_CTRL_7 0x0e
+#define RT5677_BIAS_CUR1 0x10
+#define RT5677_BIAS_CUR2 0x12
+#define RT5677_BIAS_CUR3 0x13
+#define RT5677_BIAS_CUR4 0x14
+#define RT5677_BIAS_CUR5 0x15
+#define RT5677_VREF_LOUT_CTRL 0x17
+#define RT5677_DIG_VOL_CTRL1 0x1a
+#define RT5677_DIG_VOL_CTRL2 0x1b
+#define RT5677_ANA_ADC_GAIN_CTRL 0x1e
+#define RT5677_VAD_SRAM_TEST1 0x20
+#define RT5677_VAD_SRAM_TEST2 0x21
+#define RT5677_VAD_SRAM_TEST3 0x22
+#define RT5677_VAD_SRAM_TEST4 0x23
+#define RT5677_PAD_DRV_CTRL 0x26
+#define RT5677_DIG_IN_PIN_ST_CTRL1 0x29
+#define RT5677_DIG_IN_PIN_ST_CTRL2 0x2a
+#define RT5677_DIG_IN_PIN_ST_CTRL3 0x2b
+#define RT5677_PLL1_INT 0x38
+#define RT5677_PLL2_INT 0x39
+#define RT5677_TEST_CTRL1 0x3a
+#define RT5677_TEST_CTRL2 0x3b
+#define RT5677_TEST_CTRL3 0x3c
+#define RT5677_CHOP_DAC_ADC 0x3d
+#define RT5677_SOFT_DEPOP_DAC_CLK_CTRL 0x3e
+#define RT5677_CROSS_OVER_FILTER1 0x90
+#define RT5677_CROSS_OVER_FILTER2 0x91
+#define RT5677_CROSS_OVER_FILTER3 0x92
+#define RT5677_CROSS_OVER_FILTER4 0x93
+#define RT5677_CROSS_OVER_FILTER5 0x94
+#define RT5677_CROSS_OVER_FILTER6 0x95
+#define RT5677_CROSS_OVER_FILTER7 0x96
+#define RT5677_CROSS_OVER_FILTER8 0x97
+#define RT5677_CROSS_OVER_FILTER9 0x98
+#define RT5677_CROSS_OVER_FILTER10 0x99
+
+/* global definition */
+#define RT5677_L_MUTE (0x1 << 15)
+#define RT5677_L_MUTE_SFT 15
+#define RT5677_VOL_L_MUTE (0x1 << 14)
+#define RT5677_VOL_L_SFT 14
+#define RT5677_R_MUTE (0x1 << 7)
+#define RT5677_R_MUTE_SFT 7
+#define RT5677_VOL_R_MUTE (0x1 << 6)
+#define RT5677_VOL_R_SFT 6
+#define RT5677_L_VOL_MASK (0x3f << 8)
+#define RT5677_L_VOL_SFT 8
+#define RT5677_R_VOL_MASK (0x3f)
+#define RT5677_R_VOL_SFT 0
+
+/* LOUT1 Control (0x01) */
+#define RT5677_LOUT1_L_MUTE (0x1 << 15)
+#define RT5677_LOUT1_L_MUTE_SFT (15)
+#define RT5677_LOUT1_L_DF (0x1 << 14)
+#define RT5677_LOUT1_L_DF_SFT (14)
+#define RT5677_LOUT2_L_MUTE (0x1 << 13)
+#define RT5677_LOUT2_L_MUTE_SFT (13)
+#define RT5677_LOUT2_L_DF (0x1 << 12)
+#define RT5677_LOUT2_L_DF_SFT (12)
+#define RT5677_LOUT3_L_MUTE (0x1 << 11)
+#define RT5677_LOUT3_L_MUTE_SFT (11)
+#define RT5677_LOUT3_L_DF (0x1 << 10)
+#define RT5677_LOUT3_L_DF_SFT (10)
+#define RT5677_LOUT1_ENH_DRV (0x1 << 9)
+#define RT5677_LOUT1_ENH_DRV_SFT (9)
+#define RT5677_LOUT2_ENH_DRV (0x1 << 8)
+#define RT5677_LOUT2_ENH_DRV_SFT (8)
+#define RT5677_LOUT3_ENH_DRV (0x1 << 7)
+#define RT5677_LOUT3_ENH_DRV_SFT (7)
+
+/* IN1 Control (0x03) */
+#define RT5677_BST_MASK1 (0xf << 12)
+#define RT5677_BST_SFT1 12
+#define RT5677_BST_MASK2 (0xf << 8)
+#define RT5677_BST_SFT2 8
+#define RT5677_IN_DF1 (0x1 << 7)
+#define RT5677_IN_DF1_SFT 7
+#define RT5677_IN_DF2 (0x1 << 6)
+#define RT5677_IN_DF2_SFT 6
+
+/* Micbias Control (0x04) */
+#define RT5677_MICBIAS1_OUTVOLT_MASK (0x1 << 15)
+#define RT5677_MICBIAS1_OUTVOLT_SFT (15)
+#define RT5677_MICBIAS1_OUTVOLT_2_7V (0x0 << 15)
+#define RT5677_MICBIAS1_OUTVOLT_2_25V (0x1 << 15)
+#define RT5677_MICBIAS1_CTRL_VDD_MASK (0x1 << 14)
+#define RT5677_MICBIAS1_CTRL_VDD_SFT (14)
+#define RT5677_MICBIAS1_CTRL_VDD_1_8V (0x0 << 14)
+#define RT5677_MICBIAS1_CTRL_VDD_3_3V (0x1 << 14)
+#define RT5677_MICBIAS1_OVCD_MASK (0x1 << 11)
+#define RT5677_MICBIAS1_OVCD_SHIFT (11)
+#define RT5677_MICBIAS1_OVCD_DIS (0x0 << 11)
+#define RT5677_MICBIAS1_OVCD_EN (0x1 << 11)
+#define RT5677_MICBIAS1_OVTH_MASK (0x3 << 9)
+#define RT5677_MICBIAS1_OVTH_SFT 9
+#define RT5677_MICBIAS1_OVTH_640UA (0x0 << 9)
+#define RT5677_MICBIAS1_OVTH_1280UA (0x1 << 9)
+#define RT5677_MICBIAS1_OVTH_1920UA (0x2 << 9)
+
+/* SLIMbus Parameter (0x07) */
+
+/* SLIMbus Rx (0x08) */
+#define RT5677_SLB_ADC4_MASK (0x3 << 6)
+#define RT5677_SLB_ADC4_SFT 6
+#define RT5677_SLB_ADC3_MASK (0x3 << 4)
+#define RT5677_SLB_ADC3_SFT 4
+#define RT5677_SLB_ADC2_MASK (0x3 << 2)
+#define RT5677_SLB_ADC2_SFT 2
+#define RT5677_SLB_ADC1_MASK (0x3 << 0)
+#define RT5677_SLB_ADC1_SFT 0
+
+/* SLIMBus control (0x09) */
+
+/* Sidetone Control (0x13) */
+#define RT5677_ST_HPF_SEL_MASK (0x7 << 13)
+#define RT5677_ST_HPF_SEL_SFT 13
+#define RT5677_ST_HPF_PATH (0x1 << 12)
+#define RT5677_ST_HPF_PATH_SFT 12
+#define RT5677_ST_SEL_MASK (0x7 << 9)
+#define RT5677_ST_SEL_SFT 9
+#define RT5677_ST_EN (0x1 << 6)
+#define RT5677_ST_EN_SFT 6
+
+/* Analog DAC1/2/3 Source Control (0x15) */
+#define RT5677_ANA_DAC3_SRC_SEL_MASK (0x3 << 4)
+#define RT5677_ANA_DAC3_SRC_SEL_SFT 4
+#define RT5677_ANA_DAC1_2_SRC_SEL_MASK (0x3 << 0)
+#define RT5677_ANA_DAC1_2_SRC_SEL_SFT 0
+
+/* IF/DSP to DAC3/4 Mixer Control (0x16) */
+#define RT5677_M_DAC4_L_VOL (0x1 << 15)
+#define RT5677_M_DAC4_L_VOL_SFT 15
+#define RT5677_SEL_DAC4_L_SRC_MASK (0x7 << 12)
+#define RT5677_SEL_DAC4_L_SRC_SFT 12
+#define RT5677_M_DAC4_R_VOL (0x1 << 11)
+#define RT5677_M_DAC4_R_VOL_SFT 11
+#define RT5677_SEL_DAC4_R_SRC_MASK (0x7 << 8)
+#define RT5677_SEL_DAC4_R_SRC_SFT 8
+#define RT5677_M_DAC3_L_VOL (0x1 << 7)
+#define RT5677_M_DAC3_L_VOL_SFT 7
+#define RT5677_SEL_DAC3_L_SRC_MASK (0x7 << 4)
+#define RT5677_SEL_DAC3_L_SRC_SFT 4
+#define RT5677_M_DAC3_R_VOL (0x1 << 3)
+#define RT5677_M_DAC3_R_VOL_SFT 3
+#define RT5677_SEL_DAC3_R_SRC_MASK (0x7 << 0)
+#define RT5677_SEL_DAC3_R_SRC_SFT 0
+
+/* DAC4 Digital Volume (0x17) */
+#define RT5677_DAC4_L_VOL_MASK (0xff << 8)
+#define RT5677_DAC4_L_VOL_SFT 8
+#define RT5677_DAC4_R_VOL_MASK (0xff)
+#define RT5677_DAC4_R_VOL_SFT 0
+
+/* DAC3 Digital Volume (0x18) */
+#define RT5677_DAC3_L_VOL_MASK (0xff << 8)
+#define RT5677_DAC3_L_VOL_SFT 8
+#define RT5677_DAC3_R_VOL_MASK (0xff)
+#define RT5677_DAC3_R_VOL_SFT 0
+
+/* DAC3 Digital Volume (0x19) */
+#define RT5677_DAC1_L_VOL_MASK (0xff << 8)
+#define RT5677_DAC1_L_VOL_SFT 8
+#define RT5677_DAC1_R_VOL_MASK (0xff)
+#define RT5677_DAC1_R_VOL_SFT 0
+
+/* DAC2 Digital Volume (0x1a) */
+#define RT5677_DAC2_L_VOL_MASK (0xff << 8)
+#define RT5677_DAC2_L_VOL_SFT 8
+#define RT5677_DAC2_R_VOL_MASK (0xff)
+#define RT5677_DAC2_R_VOL_SFT 0
+
+/* IF/DSP to DAC2 Mixer Control (0x1b) */
+#define RT5677_M_DAC2_L_VOL (0x1 << 7)
+#define RT5677_M_DAC2_L_VOL_SFT 7
+#define RT5677_SEL_DAC2_L_SRC_MASK (0x7 << 4)
+#define RT5677_SEL_DAC2_L_SRC_SFT 4
+#define RT5677_M_DAC2_R_VOL (0x1 << 3)
+#define RT5677_M_DAC2_R_VOL_SFT 3
+#define RT5677_SEL_DAC2_R_SRC_MASK (0x7 << 0)
+#define RT5677_SEL_DAC2_R_SRC_SFT 0
+
+/* Stereo1 ADC Digital Volume Control (0x1c) */
+#define RT5677_STO1_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5677_STO1_ADC_L_VOL_SFT 8
+#define RT5677_STO1_ADC_R_VOL_MASK (0x7f)
+#define RT5677_STO1_ADC_R_VOL_SFT 0
+
+/* Mono ADC Digital Volume Control (0x1d) */
+#define RT5677_MONO_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5677_MONO_ADC_L_VOL_SFT 8
+#define RT5677_MONO_ADC_R_VOL_MASK (0x7f)
+#define RT5677_MONO_ADC_R_VOL_SFT 0
+
+/* Stereo 1/2 ADC Boost Gain Control (0x1e) */
+#define RT5677_STO1_ADC_L_BST_MASK (0x3 << 14)
+#define RT5677_STO1_ADC_L_BST_SFT 14
+#define RT5677_STO1_ADC_R_BST_MASK (0x3 << 12)
+#define RT5677_STO1_ADC_R_BST_SFT 12
+#define RT5677_STO1_ADC_COMP_MASK (0x3 << 10)
+#define RT5677_STO1_ADC_COMP_SFT 10
+#define RT5677_STO2_ADC_L_BST_MASK (0x3 << 8)
+#define RT5677_STO2_ADC_L_BST_SFT 8
+#define RT5677_STO2_ADC_R_BST_MASK (0x3 << 6)
+#define RT5677_STO2_ADC_R_BST_SFT 6
+#define RT5677_STO2_ADC_COMP_MASK (0x3 << 4)
+#define RT5677_STO2_ADC_COMP_SFT 4
+
+/* Stereo2 ADC Digital Volume Control (0x1f) */
+#define RT5677_STO2_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5677_STO2_ADC_L_VOL_SFT 8
+#define RT5677_STO2_ADC_R_VOL_MASK (0x7f)
+#define RT5677_STO2_ADC_R_VOL_SFT 0
+
+/* ADC Boost Gain Control 2 (0x20) */
+#define RT5677_MONO_ADC_L_BST_MASK (0x3 << 14)
+#define RT5677_MONO_ADC_L_BST_SFT 14
+#define RT5677_MONO_ADC_R_BST_MASK (0x3 << 12)
+#define RT5677_MONO_ADC_R_BST_SFT 12
+#define RT5677_MONO_ADC_COMP_MASK (0x3 << 10)
+#define RT5677_MONO_ADC_COMP_SFT 10
+
+/* Stereo 3/4 ADC Boost Gain Control (0x21) */
+#define RT5677_STO3_ADC_L_BST_MASK (0x3 << 14)
+#define RT5677_STO3_ADC_L_BST_SFT 14
+#define RT5677_STO3_ADC_R_BST_MASK (0x3 << 12)
+#define RT5677_STO3_ADC_R_BST_SFT 12
+#define RT5677_STO3_ADC_COMP_MASK (0x3 << 10)
+#define RT5677_STO3_ADC_COMP_SFT 10
+#define RT5677_STO4_ADC_L_BST_MASK (0x3 << 8)
+#define RT5677_STO4_ADC_L_BST_SFT 8
+#define RT5677_STO4_ADC_R_BST_MASK (0x3 << 6)
+#define RT5677_STO4_ADC_R_BST_SFT 6
+#define RT5677_STO4_ADC_COMP_MASK (0x3 << 4)
+#define RT5677_STO4_ADC_COMP_SFT 4
+
+/* Stereo3 ADC Digital Volume Control (0x22) */
+#define RT5677_STO3_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5677_STO3_ADC_L_VOL_SFT 8
+#define RT5677_STO3_ADC_R_VOL_MASK (0x7f)
+#define RT5677_STO3_ADC_R_VOL_SFT 0
+
+/* Stereo4 ADC Digital Volume Control (0x23) */
+#define RT5677_STO4_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5677_STO4_ADC_L_VOL_SFT 8
+#define RT5677_STO4_ADC_R_VOL_MASK (0x7f)
+#define RT5677_STO4_ADC_R_VOL_SFT 0
+
+/* Stereo4 ADC Mixer control (0x24) */
+#define RT5677_M_STO4_ADC_L2 (0x1 << 15)
+#define RT5677_M_STO4_ADC_L2_SFT 15
+#define RT5677_M_STO4_ADC_L1 (0x1 << 14)
+#define RT5677_M_STO4_ADC_L1_SFT 14
+#define RT5677_SEL_STO4_ADC1_MASK (0x3 << 12)
+#define RT5677_SEL_STO4_ADC1_SFT 12
+#define RT5677_SEL_STO4_ADC2_MASK (0x3 << 10)
+#define RT5677_SEL_STO4_ADC2_SFT 10
+#define RT5677_SEL_STO4_DMIC_MASK (0x3 << 8)
+#define RT5677_SEL_STO4_DMIC_SFT 8
+#define RT5677_M_STO4_ADC_R1 (0x1 << 7)
+#define RT5677_M_STO4_ADC_R1_SFT 7
+#define RT5677_M_STO4_ADC_R2 (0x1 << 6)
+#define RT5677_M_STO4_ADC_R2_SFT 6
+
+/* Stereo3 ADC Mixer control (0x25) */
+#define RT5677_M_STO3_ADC_L2 (0x1 << 15)
+#define RT5677_M_STO3_ADC_L2_SFT 15
+#define RT5677_M_STO3_ADC_L1 (0x1 << 14)
+#define RT5677_M_STO3_ADC_L1_SFT 14
+#define RT5677_SEL_STO3_ADC1_MASK (0x3 << 12)
+#define RT5677_SEL_STO3_ADC1_SFT 12
+#define RT5677_SEL_STO3_ADC2_MASK (0x3 << 10)
+#define RT5677_SEL_STO3_ADC2_SFT 10
+#define RT5677_SEL_STO3_DMIC_MASK (0x3 << 8)
+#define RT5677_SEL_STO3_DMIC_SFT 8
+#define RT5677_M_STO3_ADC_R1 (0x1 << 7)
+#define RT5677_M_STO3_ADC_R1_SFT 7
+#define RT5677_M_STO3_ADC_R2 (0x1 << 6)
+#define RT5677_M_STO3_ADC_R2_SFT 6
+
+/* Stereo2 ADC Mixer Control (0x26) */
+#define RT5677_M_STO2_ADC_L2 (0x1 << 15)
+#define RT5677_M_STO2_ADC_L2_SFT 15
+#define RT5677_M_STO2_ADC_L1 (0x1 << 14)
+#define RT5677_M_STO2_ADC_L1_SFT 14
+#define RT5677_SEL_STO2_ADC1_MASK (0x3 << 12)
+#define RT5677_SEL_STO2_ADC1_SFT 12
+#define RT5677_SEL_STO2_ADC2_MASK (0x3 << 10)
+#define RT5677_SEL_STO2_ADC2_SFT 10
+#define RT5677_SEL_STO2_DMIC_MASK (0x3 << 8)
+#define RT5677_SEL_STO2_DMIC_SFT 8
+#define RT5677_M_STO2_ADC_R1 (0x1 << 7)
+#define RT5677_M_STO2_ADC_R1_SFT 7
+#define RT5677_M_STO2_ADC_R2 (0x1 << 6)
+#define RT5677_M_STO2_ADC_R2_SFT 6
+#define RT5677_SEL_STO2_LR_MIX_MASK (0x1 << 0)
+#define RT5677_SEL_STO2_LR_MIX_SFT 0
+#define RT5677_SEL_STO2_LR_MIX_L (0x0 << 0)
+#define RT5677_SEL_STO2_LR_MIX_LR (0x1 << 0)
+
+/* Stereo1 ADC Mixer control (0x27) */
+#define RT5677_M_STO1_ADC_L2 (0x1 << 15)
+#define RT5677_M_STO1_ADC_L2_SFT 15
+#define RT5677_M_STO1_ADC_L1 (0x1 << 14)
+#define RT5677_M_STO1_ADC_L1_SFT 14
+#define RT5677_SEL_STO1_ADC1_MASK (0x3 << 12)
+#define RT5677_SEL_STO1_ADC1_SFT 12
+#define RT5677_SEL_STO1_ADC2_MASK (0x3 << 10)
+#define RT5677_SEL_STO1_ADC2_SFT 10
+#define RT5677_SEL_STO1_DMIC_MASK (0x3 << 8)
+#define RT5677_SEL_STO1_DMIC_SFT 8
+#define RT5677_M_STO1_ADC_R1 (0x1 << 7)
+#define RT5677_M_STO1_ADC_R1_SFT 7
+#define RT5677_M_STO1_ADC_R2 (0x1 << 6)
+#define RT5677_M_STO1_ADC_R2_SFT 6
+
+/* Mono ADC Mixer control (0x28) */
+#define RT5677_M_MONO_ADC_L2 (0x1 << 15)
+#define RT5677_M_MONO_ADC_L2_SFT 15
+#define RT5677_M_MONO_ADC_L1 (0x1 << 14)
+#define RT5677_M_MONO_ADC_L1_SFT 14
+#define RT5677_SEL_MONO_ADC_L1_MASK (0x3 << 12)
+#define RT5677_SEL_MONO_ADC_L1_SFT 12
+#define RT5677_SEL_MONO_ADC_L2_MASK (0x3 << 10)
+#define RT5677_SEL_MONO_ADC_L2_SFT 10
+#define RT5677_SEL_MONO_DMIC_L_MASK (0x3 << 8)
+#define RT5677_SEL_MONO_DMIC_L_SFT 8
+#define RT5677_M_MONO_ADC_R1 (0x1 << 7)
+#define RT5677_M_MONO_ADC_R1_SFT 7
+#define RT5677_M_MONO_ADC_R2 (0x1 << 6)
+#define RT5677_M_MONO_ADC_R2_SFT 6
+#define RT5677_SEL_MONO_ADC_R1_MASK (0x3 << 4)
+#define RT5677_SEL_MONO_ADC_R1_SFT 4
+#define RT5677_SEL_MONO_ADC_R2_MASK (0x3 << 2)
+#define RT5677_SEL_MONO_ADC_R2_SFT 2
+#define RT5677_SEL_MONO_DMIC_R_MASK (0x3 << 0)
+#define RT5677_SEL_MONO_DMIC_R_SFT 0
+
+/* ADC/IF/DSP to DAC1 Mixer control (0x29) */
+#define RT5677_M_ADDA_MIXER1_L (0x1 << 15)
+#define RT5677_M_ADDA_MIXER1_L_SFT 15
+#define RT5677_M_DAC1_L (0x1 << 14)
+#define RT5677_M_DAC1_L_SFT 14
+#define RT5677_DAC1_L_SEL_MASK (0x7 << 8)
+#define RT5677_DAC1_L_SEL_SFT 8
+#define RT5677_M_ADDA_MIXER1_R (0x1 << 7)
+#define RT5677_M_ADDA_MIXER1_R_SFT 7
+#define RT5677_M_DAC1_R (0x1 << 6)
+#define RT5677_M_DAC1_R_SFT 6
+#define RT5677_ADDA1_SEL_MASK (0x3 << 0)
+#define RT5677_ADDA1_SEL_SFT 0
+
+/* Stereo1 DAC Mixer L/R Control (0x2a) */
+#define RT5677_M_ST_DAC1_L (0x1 << 15)
+#define RT5677_M_ST_DAC1_L_SFT 15
+#define RT5677_M_DAC1_L_STO_L (0x1 << 13)
+#define RT5677_M_DAC1_L_STO_L_SFT 13
+#define RT5677_DAC1_L_STO_L_VOL_MASK (0x1 << 12)
+#define RT5677_DAC1_L_STO_L_VOL_SFT 12
+#define RT5677_M_DAC2_L_STO_L (0x1 << 11)
+#define RT5677_M_DAC2_L_STO_L_SFT 11
+#define RT5677_DAC2_L_STO_L_VOL_MASK (0x1 << 10)
+#define RT5677_DAC2_L_STO_L_VOL_SFT 10
+#define RT5677_M_DAC1_R_STO_L (0x1 << 9)
+#define RT5677_M_DAC1_R_STO_L_SFT 9
+#define RT5677_DAC1_R_STO_L_VOL_MASK (0x1 << 8)
+#define RT5677_DAC1_R_STO_L_VOL_SFT 8
+#define RT5677_M_ST_DAC1_R (0x1 << 7)
+#define RT5677_M_ST_DAC1_R_SFT 7
+#define RT5677_M_DAC1_R_STO_R (0x1 << 5)
+#define RT5677_M_DAC1_R_STO_R_SFT 5
+#define RT5677_DAC1_R_STO_R_VOL_MASK (0x1 << 4)
+#define RT5677_DAC1_R_STO_R_VOL_SFT 4
+#define RT5677_M_DAC2_R_STO_R (0x1 << 3)
+#define RT5677_M_DAC2_R_STO_R_SFT 3
+#define RT5677_DAC2_R_STO_R_VOL_MASK (0x1 << 2)
+#define RT5677_DAC2_R_STO_R_VOL_SFT 2
+#define RT5677_M_DAC1_L_STO_R (0x1 << 1)
+#define RT5677_M_DAC1_L_STO_R_SFT 1
+#define RT5677_DAC1_L_STO_R_VOL_MASK (0x1 << 0)
+#define RT5677_DAC1_L_STO_R_VOL_SFT 0
+
+/* Mono DAC Mixer L/R Control (0x2b) */
+#define RT5677_M_ST_DAC2_L (0x1 << 15)
+#define RT5677_M_ST_DAC2_L_SFT 15
+#define RT5677_M_DAC2_L_MONO_L (0x1 << 13)
+#define RT5677_M_DAC2_L_MONO_L_SFT 13
+#define RT5677_DAC2_L_MONO_L_VOL_MASK (0x1 << 12)
+#define RT5677_DAC2_L_MONO_L_VOL_SFT 12
+#define RT5677_M_DAC2_R_MONO_L (0x1 << 11)
+#define RT5677_M_DAC2_R_MONO_L_SFT 11
+#define RT5677_DAC2_R_MONO_L_VOL_MASK (0x1 << 10)
+#define RT5677_DAC2_R_MONO_L_VOL_SFT 10
+#define RT5677_M_DAC1_L_MONO_L (0x1 << 9)
+#define RT5677_M_DAC1_L_MONO_L_SFT 9
+#define RT5677_DAC1_L_MONO_L_VOL_MASK (0x1 << 8)
+#define RT5677_DAC1_L_MONO_L_VOL_SFT 8
+#define RT5677_M_ST_DAC2_R (0x1 << 7)
+#define RT5677_M_ST_DAC2_R_SFT 7
+#define RT5677_M_DAC2_R_MONO_R (0x1 << 5)
+#define RT5677_M_DAC2_R_MONO_R_SFT 5
+#define RT5677_DAC2_R_MONO_R_VOL_MASK (0x1 << 4)
+#define RT5677_DAC2_R_MONO_R_VOL_SFT 4
+#define RT5677_M_DAC1_R_MONO_R (0x1 << 3)
+#define RT5677_M_DAC1_R_MONO_R_SFT 3
+#define RT5677_DAC1_R_MONO_R_VOL_MASK (0x1 << 2)
+#define RT5677_DAC1_R_MONO_R_VOL_SFT 2
+#define RT5677_M_DAC2_L_MONO_R (0x1 << 1)
+#define RT5677_M_DAC2_L_MONO_R_SFT 1
+#define RT5677_DAC2_L_MONO_R_VOL_MASK (0x1 << 0)
+#define RT5677_DAC2_L_MONO_R_VOL_SFT 0
+
+/* DD Mixer 1 Control (0x2c) */
+#define RT5677_M_STO_L_DD1_L (0x1 << 15)
+#define RT5677_M_STO_L_DD1_L_SFT 15
+#define RT5677_STO_L_DD1_L_VOL_MASK (0x1 << 14)
+#define RT5677_STO_L_DD1_L_VOL_SFT 14
+#define RT5677_M_MONO_L_DD1_L (0x1 << 13)
+#define RT5677_M_MONO_L_DD1_L_SFT 13
+#define RT5677_MONO_L_DD1_L_VOL_MASK (0x1 << 12)
+#define RT5677_MONO_L_DD1_L_VOL_SFT 12
+#define RT5677_M_DAC3_L_DD1_L (0x1 << 11)
+#define RT5677_M_DAC3_L_DD1_L_SFT 11
+#define RT5677_DAC3_L_DD1_L_VOL_MASK (0x1 << 10)
+#define RT5677_DAC3_L_DD1_L_VOL_SFT 10
+#define RT5677_M_DAC3_R_DD1_L (0x1 << 9)
+#define RT5677_M_DAC3_R_DD1_L_SFT 9
+#define RT5677_DAC3_R_DD1_L_VOL_MASK (0x1 << 8)
+#define RT5677_DAC3_R_DD1_L_VOL_SFT 8
+#define RT5677_M_STO_R_DD1_R (0x1 << 7)
+#define RT5677_M_STO_R_DD1_R_SFT 7
+#define RT5677_STO_R_DD1_R_VOL_MASK (0x1 << 6)
+#define RT5677_STO_R_DD1_R_VOL_SFT 6
+#define RT5677_M_MONO_R_DD1_R (0x1 << 5)
+#define RT5677_M_MONO_R_DD1_R_SFT 5
+#define RT5677_MONO_R_DD1_R_VOL_MASK (0x1 << 4)
+#define RT5677_MONO_R_DD1_R_VOL_SFT 4
+#define RT5677_M_DAC3_R_DD1_R (0x1 << 3)
+#define RT5677_M_DAC3_R_DD1_R_SFT 3
+#define RT5677_DAC3_R_DD1_R_VOL_MASK (0x1 << 2)
+#define RT5677_DAC3_R_DD1_R_VOL_SFT 2
+#define RT5677_M_DAC3_L_DD1_R (0x1 << 1)
+#define RT5677_M_DAC3_L_DD1_R_SFT 1
+#define RT5677_DAC3_L_DD1_R_VOL_MASK (0x1 << 0)
+#define RT5677_DAC3_L_DD1_R_VOL_SFT 0
+
+/* DD Mixer 2 Control (0x2d) */
+#define RT5677_M_STO_L_DD2_L (0x1 << 15)
+#define RT5677_M_STO_L_DD2_L_SFT 15
+#define RT5677_STO_L_DD2_L_VOL_MASK (0x1 << 14)
+#define RT5677_STO_L_DD2_L_VOL_SFT 14
+#define RT5677_M_MONO_L_DD2_L (0x1 << 13)
+#define RT5677_M_MONO_L_DD2_L_SFT 13
+#define RT5677_MONO_L_DD2_L_VOL_MASK (0x1 << 12)
+#define RT5677_MONO_L_DD2_L_VOL_SFT 12
+#define RT5677_M_DAC4_L_DD2_L (0x1 << 11)
+#define RT5677_M_DAC4_L_DD2_L_SFT 11
+#define RT5677_DAC4_L_DD2_L_VOL_MASK (0x1 << 10)
+#define RT5677_DAC4_L_DD2_L_VOL_SFT 10
+#define RT5677_M_DAC4_R_DD2_L (0x1 << 9)
+#define RT5677_M_DAC4_R_DD2_L_SFT 9
+#define RT5677_DAC4_R_DD2_L_VOL_MASK (0x1 << 8)
+#define RT5677_DAC4_R_DD2_L_VOL_SFT 8
+#define RT5677_M_STO_R_DD2_R (0x1 << 7)
+#define RT5677_M_STO_R_DD2_R_SFT 7
+#define RT5677_STO_R_DD2_R_VOL_MASK (0x1 << 6)
+#define RT5677_STO_R_DD2_R_VOL_SFT 6
+#define RT5677_M_MONO_R_DD2_R (0x1 << 5)
+#define RT5677_M_MONO_R_DD2_R_SFT 5
+#define RT5677_MONO_R_DD2_R_VOL_MASK (0x1 << 4)
+#define RT5677_MONO_R_DD2_R_VOL_SFT 4
+#define RT5677_M_DAC4_R_DD2_R (0x1 << 3)
+#define RT5677_M_DAC4_R_DD2_R_SFT 3
+#define RT5677_DAC4_R_DD2_R_VOL_MASK (0x1 << 2)
+#define RT5677_DAC4_R_DD2_R_VOL_SFT 2
+#define RT5677_M_DAC4_L_DD2_R (0x1 << 1)
+#define RT5677_M_DAC4_L_DD2_R_SFT 1
+#define RT5677_DAC4_L_DD2_R_VOL_MASK (0x1 << 0)
+#define RT5677_DAC4_L_DD2_R_VOL_SFT 0
+
+/* IF3 data control (0x2f) */
+#define RT5677_IF3_DAC_SEL_MASK (0x3 << 6)
+#define RT5677_IF3_DAC_SEL_SFT 6
+#define RT5677_IF3_ADC_SEL_MASK (0x3 << 4)
+#define RT5677_IF3_ADC_SEL_SFT 4
+#define RT5677_IF3_ADC_IN_MASK (0xf << 0)
+#define RT5677_IF3_ADC_IN_SFT 0
+
+/* IF4 data control (0x30) */
+#define RT5677_IF4_ADC_IN_MASK (0xf << 4)
+#define RT5677_IF4_ADC_IN_SFT 4
+#define RT5677_IF4_DAC_SEL_MASK (0x3 << 2)
+#define RT5677_IF4_DAC_SEL_SFT 2
+#define RT5677_IF4_ADC_SEL_MASK (0x3 << 0)
+#define RT5677_IF4_ADC_SEL_SFT 0
+
+/* PDM Output Control (0x31) */
+#define RT5677_M_PDM1_L (0x1 << 15)
+#define RT5677_M_PDM1_L_SFT 15
+#define RT5677_SEL_PDM1_L_MASK (0x3 << 12)
+#define RT5677_SEL_PDM1_L_SFT 12
+#define RT5677_M_PDM1_R (0x1 << 11)
+#define RT5677_M_PDM1_R_SFT 11
+#define RT5677_SEL_PDM1_R_MASK (0x3 << 8)
+#define RT5677_SEL_PDM1_R_SFT 8
+#define RT5677_M_PDM2_L (0x1 << 7)
+#define RT5677_M_PDM2_L_SFT 7
+#define RT5677_SEL_PDM2_L_MASK (0x3 << 4)
+#define RT5677_SEL_PDM2_L_SFT 4
+#define RT5677_M_PDM2_R (0x1 << 3)
+#define RT5677_M_PDM2_R_SFT 3
+#define RT5677_SEL_PDM2_R_MASK (0x3 << 0)
+#define RT5677_SEL_PDM2_R_SFT 0
+
+/* PDM I2C / Data Control 1 (0x32) */
+#define RT5677_PDM2_PW_DOWN (0x1 << 7)
+#define RT5677_PDM1_PW_DOWN (0x1 << 6)
+#define RT5677_PDM2_BUSY (0x1 << 5)
+#define RT5677_PDM1_BUSY (0x1 << 4)
+#define RT5677_PDM_PATTERN (0x1 << 3)
+#define RT5677_PDM_GAIN (0x1 << 2)
+#define RT5677_PDM_DIV_MASK (0x3 << 0)
+
+/* PDM I2C / Data Control 2 (0x33) */
+#define RT5677_PDM1_I2C_ID (0xf << 12)
+#define RT5677_PDM1_EXE (0x1 << 11)
+#define RT5677_PDM1_I2C_CMD (0x1 << 10)
+#define RT5677_PDM1_I2C_EXE (0x1 << 9)
+#define RT5677_PDM1_I2C_BUSY (0x1 << 8)
+#define RT5677_PDM2_I2C_ID (0xf << 4)
+#define RT5677_PDM2_EXE (0x1 << 3)
+#define RT5677_PDM2_I2C_CMD (0x1 << 2)
+#define RT5677_PDM2_I2C_EXE (0x1 << 1)
+#define RT5677_PDM2_I2C_BUSY (0x1 << 0)
+
+/* MX3C TDM1 control 1 (0x3c) */
+#define RT5677_IF1_ADC4_MASK (0x3 << 10)
+#define RT5677_IF1_ADC4_SFT 10
+#define RT5677_IF1_ADC3_MASK (0x3 << 8)
+#define RT5677_IF1_ADC3_SFT 8
+#define RT5677_IF1_ADC2_MASK (0x3 << 6)
+#define RT5677_IF1_ADC2_SFT 6
+#define RT5677_IF1_ADC1_MASK (0x3 << 4)
+#define RT5677_IF1_ADC1_SFT 4
+
+/* MX41 TDM2 control 1 (0x41) */
+#define RT5677_IF2_ADC4_MASK (0x3 << 10)
+#define RT5677_IF2_ADC4_SFT 10
+#define RT5677_IF2_ADC3_MASK (0x3 << 8)
+#define RT5677_IF2_ADC3_SFT 8
+#define RT5677_IF2_ADC2_MASK (0x3 << 6)
+#define RT5677_IF2_ADC2_SFT 6
+#define RT5677_IF2_ADC1_MASK (0x3 << 4)
+#define RT5677_IF2_ADC1_SFT 4
+
+/* Digital Microphone Control 1 (0x50) */
+#define RT5677_DMIC_1_EN_MASK (0x1 << 15)
+#define RT5677_DMIC_1_EN_SFT 15
+#define RT5677_DMIC_1_DIS (0x0 << 15)
+#define RT5677_DMIC_1_EN (0x1 << 15)
+#define RT5677_DMIC_2_EN_MASK (0x1 << 14)
+#define RT5677_DMIC_2_EN_SFT 14
+#define RT5677_DMIC_2_DIS (0x0 << 14)
+#define RT5677_DMIC_2_EN (0x1 << 14)
+#define RT5677_DMIC_L_STO1_LH_MASK (0x1 << 13)
+#define RT5677_DMIC_L_STO1_LH_SFT 13
+#define RT5677_DMIC_L_STO1_LH_FALLING (0x0 << 13)
+#define RT5677_DMIC_L_STO1_LH_RISING (0x1 << 13)
+#define RT5677_DMIC_R_STO1_LH_MASK (0x1 << 12)
+#define RT5677_DMIC_R_STO1_LH_SFT 12
+#define RT5677_DMIC_R_STO1_LH_FALLING (0x0 << 12)
+#define RT5677_DMIC_R_STO1_LH_RISING (0x1 << 12)
+#define RT5677_DMIC_L_STO3_LH_MASK (0x1 << 11)
+#define RT5677_DMIC_L_STO3_LH_SFT 11
+#define RT5677_DMIC_L_STO3_LH_FALLING (0x0 << 11)
+#define RT5677_DMIC_L_STO3_LH_RISING (0x1 << 11)
+#define RT5677_DMIC_R_STO3_LH_MASK (0x1 << 10)
+#define RT5677_DMIC_R_STO3_LH_SFT 10
+#define RT5677_DMIC_R_STO3_LH_FALLING (0x0 << 10)
+#define RT5677_DMIC_R_STO3_LH_RISING (0x1 << 10)
+#define RT5677_DMIC_L_STO2_LH_MASK (0x1 << 9)
+#define RT5677_DMIC_L_STO2_LH_SFT 9
+#define RT5677_DMIC_L_STO2_LH_FALLING (0x0 << 9)
+#define RT5677_DMIC_L_STO2_LH_RISING (0x1 << 9)
+#define RT5677_DMIC_R_STO2_LH_MASK (0x1 << 8)
+#define RT5677_DMIC_R_STO2_LH_SFT 8
+#define RT5677_DMIC_R_STO2_LH_FALLING (0x0 << 8)
+#define RT5677_DMIC_R_STO2_LH_RISING (0x1 << 8)
+#define RT5677_DMIC_CLK_MASK (0x7 << 5)
+#define RT5677_DMIC_CLK_SFT 5
+#define RT5677_DMIC_3_EN_MASK (0x1 << 4)
+#define RT5677_DMIC_3_EN_SFT 4
+#define RT5677_DMIC_3_DIS (0x0 << 4)
+#define RT5677_DMIC_3_EN (0x1 << 4)
+#define RT5677_DMIC_R_MONO_LH_MASK (0x1 << 2)
+#define RT5677_DMIC_R_MONO_LH_SFT 2
+#define RT5677_DMIC_R_MONO_LH_FALLING (0x0 << 2)
+#define RT5677_DMIC_R_MONO_LH_RISING (0x1 << 2)
+#define RT5677_DMIC_L_STO4_LH_MASK (0x1 << 1)
+#define RT5677_DMIC_L_STO4_LH_SFT 1
+#define RT5677_DMIC_L_STO4_LH_FALLING (0x0 << 1)
+#define RT5677_DMIC_L_STO4_LH_RISING (0x1 << 1)
+#define RT5677_DMIC_R_STO4_LH_MASK (0x1 << 0)
+#define RT5677_DMIC_R_STO4_LH_SFT 0
+#define RT5677_DMIC_R_STO4_LH_FALLING (0x0 << 0)
+#define RT5677_DMIC_R_STO4_LH_RISING (0x1 << 0)
+
+/* Digital Microphone Control 2 (0x51) */
+#define RT5677_DMIC_4_EN_MASK (0x1 << 15)
+#define RT5677_DMIC_4_EN_SFT 15
+#define RT5677_DMIC_4_DIS (0x0 << 15)
+#define RT5677_DMIC_4_EN (0x1 << 15)
+#define RT5677_DMIC_4L_LH_MASK (0x1 << 7)
+#define RT5677_DMIC_4L_LH_SFT 7
+#define RT5677_DMIC_4L_LH_FALLING (0x0 << 7)
+#define RT5677_DMIC_4L_LH_RISING (0x1 << 7)
+#define RT5677_DMIC_4R_LH_MASK (0x1 << 6)
+#define RT5677_DMIC_4R_LH_SFT 6
+#define RT5677_DMIC_4R_LH_FALLING (0x0 << 6)
+#define RT5677_DMIC_4R_LH_RISING (0x1 << 6)
+#define RT5677_DMIC_3L_LH_MASK (0x1 << 5)
+#define RT5677_DMIC_3L_LH_SFT 5
+#define RT5677_DMIC_3L_LH_FALLING (0x0 << 5)
+#define RT5677_DMIC_3L_LH_RISING (0x1 << 5)
+#define RT5677_DMIC_3R_LH_MASK (0x1 << 4)
+#define RT5677_DMIC_3R_LH_SFT 4
+#define RT5677_DMIC_3R_LH_FALLING (0x0 << 4)
+#define RT5677_DMIC_3R_LH_RISING (0x1 << 4)
+#define RT5677_DMIC_2L_LH_MASK (0x1 << 3)
+#define RT5677_DMIC_2L_LH_SFT 3
+#define RT5677_DMIC_2L_LH_FALLING (0x0 << 3)
+#define RT5677_DMIC_2L_LH_RISING (0x1 << 3)
+#define RT5677_DMIC_2R_LH_MASK (0x1 << 2)
+#define RT5677_DMIC_2R_LH_SFT 2
+#define RT5677_DMIC_2R_LH_FALLING (0x0 << 2)
+#define RT5677_DMIC_2R_LH_RISING (0x1 << 2)
+#define RT5677_DMIC_1L_LH_MASK (0x1 << 1)
+#define RT5677_DMIC_1L_LH_SFT 1
+#define RT5677_DMIC_1L_LH_FALLING (0x0 << 1)
+#define RT5677_DMIC_1L_LH_RISING (0x1 << 1)
+#define RT5677_DMIC_1R_LH_MASK (0x1 << 0)
+#define RT5677_DMIC_1R_LH_SFT 0
+#define RT5677_DMIC_1R_LH_FALLING (0x0 << 0)
+#define RT5677_DMIC_1R_LH_RISING (0x1 << 0)
+
+/* Power Management for Digital 1 (0x61) */
+#define RT5677_PWR_I2S1 (0x1 << 15)
+#define RT5677_PWR_I2S1_BIT 15
+#define RT5677_PWR_I2S2 (0x1 << 14)
+#define RT5677_PWR_I2S2_BIT 14
+#define RT5677_PWR_I2S3 (0x1 << 13)
+#define RT5677_PWR_I2S3_BIT 13
+#define RT5677_PWR_DAC1 (0x1 << 12)
+#define RT5677_PWR_DAC1_BIT 12
+#define RT5677_PWR_DAC2 (0x1 << 11)
+#define RT5677_PWR_DAC2_BIT 11
+#define RT5677_PWR_I2S4 (0x1 << 10)
+#define RT5677_PWR_I2S4_BIT 10
+#define RT5677_PWR_SLB (0x1 << 9)
+#define RT5677_PWR_SLB_BIT 9
+#define RT5677_PWR_DAC3 (0x1 << 7)
+#define RT5677_PWR_DAC3_BIT 7
+#define RT5677_PWR_ADCFED2 (0x1 << 4)
+#define RT5677_PWR_ADCFED2_BIT 4
+#define RT5677_PWR_ADCFED1 (0x1 << 3)
+#define RT5677_PWR_ADCFED1_BIT 3
+#define RT5677_PWR_ADC_L (0x1 << 2)
+#define RT5677_PWR_ADC_L_BIT 2
+#define RT5677_PWR_ADC_R (0x1 << 1)
+#define RT5677_PWR_ADC_R_BIT 1
+#define RT5677_PWR_I2C_MASTER (0x1 << 0)
+#define RT5677_PWR_I2C_MASTER_BIT 0
+
+/* Power Management for Digital 2 (0x62) */
+#define RT5677_PWR_ADC_S1F (0x1 << 15)
+#define RT5677_PWR_ADC_S1F_BIT 15
+#define RT5677_PWR_ADC_MF_L (0x1 << 14)
+#define RT5677_PWR_ADC_MF_L_BIT 14
+#define RT5677_PWR_ADC_MF_R (0x1 << 13)
+#define RT5677_PWR_ADC_MF_R_BIT 13
+#define RT5677_PWR_DAC_S1F (0x1 << 12)
+#define RT5677_PWR_DAC_S1F_BIT 12
+#define RT5677_PWR_DAC_M2F_L (0x1 << 11)
+#define RT5677_PWR_DAC_M2F_L_BIT 11
+#define RT5677_PWR_DAC_M2F_R (0x1 << 10)
+#define RT5677_PWR_DAC_M2F_R_BIT 10
+#define RT5677_PWR_DAC_M3F_L (0x1 << 9)
+#define RT5677_PWR_DAC_M3F_L_BIT 9
+#define RT5677_PWR_DAC_M3F_R (0x1 << 8)
+#define RT5677_PWR_DAC_M3F_R_BIT 8
+#define RT5677_PWR_DAC_M4F_L (0x1 << 7)
+#define RT5677_PWR_DAC_M4F_L_BIT 7
+#define RT5677_PWR_DAC_M4F_R (0x1 << 6)
+#define RT5677_PWR_DAC_M4F_R_BIT 6
+#define RT5677_PWR_ADC_S2F (0x1 << 5)
+#define RT5677_PWR_ADC_S2F_BIT 5
+#define RT5677_PWR_ADC_S3F (0x1 << 4)
+#define RT5677_PWR_ADC_S3F_BIT 4
+#define RT5677_PWR_ADC_S4F (0x1 << 3)
+#define RT5677_PWR_ADC_S4F_BIT 3
+#define RT5677_PWR_PDM1 (0x1 << 2)
+#define RT5677_PWR_PDM1_BIT 2
+#define RT5677_PWR_PDM2 (0x1 << 1)
+#define RT5677_PWR_PDM2_BIT 1
+
+/* Power Management for Analog 1 (0x63) */
+#define RT5677_PWR_VREF1 (0x1 << 15)
+#define RT5677_PWR_VREF1_BIT 15
+#define RT5677_PWR_FV1 (0x1 << 14)
+#define RT5677_PWR_FV1_BIT 14
+#define RT5677_PWR_MB (0x1 << 13)
+#define RT5677_PWR_MB_BIT 13
+#define RT5677_PWR_LO1 (0x1 << 12)
+#define RT5677_PWR_LO1_BIT 12
+#define RT5677_PWR_BG (0x1 << 11)
+#define RT5677_PWR_BG_BIT 11
+#define RT5677_PWR_LO2 (0x1 << 10)
+#define RT5677_PWR_LO2_BIT 10
+#define RT5677_PWR_LO3 (0x1 << 9)
+#define RT5677_PWR_LO3_BIT 9
+#define RT5677_PWR_VREF2 (0x1 << 8)
+#define RT5677_PWR_VREF2_BIT 8
+#define RT5677_PWR_FV2 (0x1 << 7)
+#define RT5677_PWR_FV2_BIT 7
+#define RT5677_LDO2_SEL_MASK (0x7 << 4)
+#define RT5677_LDO2_SEL_SFT 4
+#define RT5677_LDO1_SEL_MASK (0x7 << 0)
+#define RT5677_LDO1_SEL_SFT 0
+
+/* Power Management for Analog 2 (0x64) */
+#define RT5677_PWR_BST1 (0x1 << 15)
+#define RT5677_PWR_BST1_BIT 15
+#define RT5677_PWR_BST2 (0x1 << 14)
+#define RT5677_PWR_BST2_BIT 14
+#define RT5677_PWR_CLK_MB1 (0x1 << 13)
+#define RT5677_PWR_CLK_MB1_BIT 13
+#define RT5677_PWR_SLIM (0x1 << 12)
+#define RT5677_PWR_SLIM_BIT 12
+#define RT5677_PWR_MB1 (0x1 << 11)
+#define RT5677_PWR_MB1_BIT 11
+#define RT5677_PWR_PP_MB1 (0x1 << 10)
+#define RT5677_PWR_PP_MB1_BIT 10
+#define RT5677_PWR_PLL1 (0x1 << 9)
+#define RT5677_PWR_PLL1_BIT 9
+#define RT5677_PWR_PLL2 (0x1 << 8)
+#define RT5677_PWR_PLL2_BIT 8
+#define RT5677_PWR_CORE (0x1 << 7)
+#define RT5677_PWR_CORE_BIT 7
+#define RT5677_PWR_CLK_MB (0x1 << 6)
+#define RT5677_PWR_CLK_MB_BIT 6
+#define RT5677_PWR_BST1_P (0x1 << 5)
+#define RT5677_PWR_BST1_P_BIT 5
+#define RT5677_PWR_BST2_P (0x1 << 4)
+#define RT5677_PWR_BST2_P_BIT 4
+#define RT5677_PWR_IPTV (0x1 << 3)
+#define RT5677_PWR_IPTV_BIT 3
+#define RT5677_PWR_25M_CLK (0x1 << 1)
+#define RT5677_PWR_25M_CLK_BIT 1
+#define RT5677_PWR_LDO1 (0x1 << 0)
+#define RT5677_PWR_LDO1_BIT 0
+
+/* Power Management for DSP (0x65) */
+#define RT5677_PWR_SR7 (0x1 << 10)
+#define RT5677_PWR_SR7_BIT 10
+#define RT5677_PWR_SR6 (0x1 << 9)
+#define RT5677_PWR_SR6_BIT 9
+#define RT5677_PWR_SR5 (0x1 << 8)
+#define RT5677_PWR_SR5_BIT 8
+#define RT5677_PWR_SR4 (0x1 << 7)
+#define RT5677_PWR_SR4_BIT 7
+#define RT5677_PWR_SR3 (0x1 << 6)
+#define RT5677_PWR_SR3_BIT 6
+#define RT5677_PWR_SR2 (0x1 << 5)
+#define RT5677_PWR_SR2_BIT 5
+#define RT5677_PWR_SR1 (0x1 << 4)
+#define RT5677_PWR_SR1_BIT 4
+#define RT5677_PWR_SR0 (0x1 << 3)
+#define RT5677_PWR_SR0_BIT 3
+#define RT5677_PWR_MLT (0x1 << 2)
+#define RT5677_PWR_MLT_BIT 2
+#define RT5677_PWR_DSP (0x1 << 1)
+#define RT5677_PWR_DSP_BIT 1
+#define RT5677_PWR_DSP_CPU (0x1 << 0)
+#define RT5677_PWR_DSP_CPU_BIT 0
+
+/* Power Status for DSP (0x66) */
+#define RT5677_PWR_SR7_RDY (0x1 << 9)
+#define RT5677_PWR_SR7_RDY_BIT 9
+#define RT5677_PWR_SR6_RDY (0x1 << 8)
+#define RT5677_PWR_SR6_RDY_BIT 8
+#define RT5677_PWR_SR5_RDY (0x1 << 7)
+#define RT5677_PWR_SR5_RDY_BIT 7
+#define RT5677_PWR_SR4_RDY (0x1 << 6)
+#define RT5677_PWR_SR4_RDY_BIT 6
+#define RT5677_PWR_SR3_RDY (0x1 << 5)
+#define RT5677_PWR_SR3_RDY_BIT 5
+#define RT5677_PWR_SR2_RDY (0x1 << 4)
+#define RT5677_PWR_SR2_RDY_BIT 4
+#define RT5677_PWR_SR1_RDY (0x1 << 3)
+#define RT5677_PWR_SR1_RDY_BIT 3
+#define RT5677_PWR_SR0_RDY (0x1 << 2)
+#define RT5677_PWR_SR0_RDY_BIT 2
+#define RT5677_PWR_MLT_RDY (0x1 << 1)
+#define RT5677_PWR_MLT_RDY_BIT 1
+#define RT5677_PWR_DSP_RDY (0x1 << 0)
+#define RT5677_PWR_DSP_RDY_BIT 0
+
+/* Power Management for DSP (0x67) */
+#define RT5677_PWR_SLIM_ISO (0x1 << 11)
+#define RT5677_PWR_SLIM_ISO_BIT 11
+#define RT5677_PWR_CORE_ISO (0x1 << 10)
+#define RT5677_PWR_CORE_ISO_BIT 10
+#define RT5677_PWR_DSP_ISO (0x1 << 9)
+#define RT5677_PWR_DSP_ISO_BIT 9
+#define RT5677_PWR_SR7_ISO (0x1 << 8)
+#define RT5677_PWR_SR7_ISO_BIT 8
+#define RT5677_PWR_SR6_ISO (0x1 << 7)
+#define RT5677_PWR_SR6_ISO_BIT 7
+#define RT5677_PWR_SR5_ISO (0x1 << 6)
+#define RT5677_PWR_SR5_ISO_BIT 6
+#define RT5677_PWR_SR4_ISO (0x1 << 5)
+#define RT5677_PWR_SR4_ISO_BIT 5
+#define RT5677_PWR_SR3_ISO (0x1 << 4)
+#define RT5677_PWR_SR3_ISO_BIT 4
+#define RT5677_PWR_SR2_ISO (0x1 << 3)
+#define RT5677_PWR_SR2_ISO_BIT 3
+#define RT5677_PWR_SR1_ISO (0x1 << 2)
+#define RT5677_PWR_SR1_ISO_BIT 2
+#define RT5677_PWR_SR0_ISO (0x1 << 1)
+#define RT5677_PWR_SR0_ISO_BIT 1
+#define RT5677_PWR_MLT_ISO (0x1 << 0)
+#define RT5677_PWR_MLT_ISO_BIT 0
+
+/* I2S1/2/3/4 Audio Serial Data Port Control (0x6f 0x70 0x71 0x72) */
+#define RT5677_I2S_MS_MASK (0x1 << 15)
+#define RT5677_I2S_MS_SFT 15
+#define RT5677_I2S_MS_M (0x0 << 15)
+#define RT5677_I2S_MS_S (0x1 << 15)
+#define RT5677_I2S_O_CP_MASK (0x3 << 10)
+#define RT5677_I2S_O_CP_SFT 10
+#define RT5677_I2S_O_CP_OFF (0x0 << 10)
+#define RT5677_I2S_O_CP_U_LAW (0x1 << 10)
+#define RT5677_I2S_O_CP_A_LAW (0x2 << 10)
+#define RT5677_I2S_I_CP_MASK (0x3 << 8)
+#define RT5677_I2S_I_CP_SFT 8
+#define RT5677_I2S_I_CP_OFF (0x0 << 8)
+#define RT5677_I2S_I_CP_U_LAW (0x1 << 8)
+#define RT5677_I2S_I_CP_A_LAW (0x2 << 8)
+#define RT5677_I2S_BP_MASK (0x1 << 7)
+#define RT5677_I2S_BP_SFT 7
+#define RT5677_I2S_BP_NOR (0x0 << 7)
+#define RT5677_I2S_BP_INV (0x1 << 7)
+#define RT5677_I2S_DL_MASK (0x3 << 2)
+#define RT5677_I2S_DL_SFT 2
+#define RT5677_I2S_DL_16 (0x0 << 2)
+#define RT5677_I2S_DL_20 (0x1 << 2)
+#define RT5677_I2S_DL_24 (0x2 << 2)
+#define RT5677_I2S_DL_8 (0x3 << 2)
+#define RT5677_I2S_DF_MASK (0x3 << 0)
+#define RT5677_I2S_DF_SFT 0
+#define RT5677_I2S_DF_I2S (0x0 << 0)
+#define RT5677_I2S_DF_LEFT (0x1 << 0)
+#define RT5677_I2S_DF_PCM_A (0x2 << 0)
+#define RT5677_I2S_DF_PCM_B (0x3 << 0)
+
+/* Clock Tree Control 1 (0x73) */
+#define RT5677_I2S_PD1_MASK (0x7 << 12)
+#define RT5677_I2S_PD1_SFT 12
+#define RT5677_I2S_PD1_1 (0x0 << 12)
+#define RT5677_I2S_PD1_2 (0x1 << 12)
+#define RT5677_I2S_PD1_3 (0x2 << 12)
+#define RT5677_I2S_PD1_4 (0x3 << 12)
+#define RT5677_I2S_PD1_6 (0x4 << 12)
+#define RT5677_I2S_PD1_8 (0x5 << 12)
+#define RT5677_I2S_PD1_12 (0x6 << 12)
+#define RT5677_I2S_PD1_16 (0x7 << 12)
+#define RT5677_I2S_BCLK_MS2_MASK (0x1 << 11)
+#define RT5677_I2S_BCLK_MS2_SFT 11
+#define RT5677_I2S_BCLK_MS2_32 (0x0 << 11)
+#define RT5677_I2S_BCLK_MS2_64 (0x1 << 11)
+#define RT5677_I2S_PD2_MASK (0x7 << 8)
+#define RT5677_I2S_PD2_SFT 8
+#define RT5677_I2S_PD2_1 (0x0 << 8)
+#define RT5677_I2S_PD2_2 (0x1 << 8)
+#define RT5677_I2S_PD2_3 (0x2 << 8)
+#define RT5677_I2S_PD2_4 (0x3 << 8)
+#define RT5677_I2S_PD2_6 (0x4 << 8)
+#define RT5677_I2S_PD2_8 (0x5 << 8)
+#define RT5677_I2S_PD2_12 (0x6 << 8)
+#define RT5677_I2S_PD2_16 (0x7 << 8)
+#define RT5677_I2S_BCLK_MS3_MASK (0x1 << 7)
+#define RT5677_I2S_BCLK_MS3_SFT 7
+#define RT5677_I2S_BCLK_MS3_32 (0x0 << 7)
+#define RT5677_I2S_BCLK_MS3_64 (0x1 << 7)
+#define RT5677_I2S_PD3_MASK (0x7 << 4)
+#define RT5677_I2S_PD3_SFT 4
+#define RT5677_I2S_PD3_1 (0x0 << 4)
+#define RT5677_I2S_PD3_2 (0x1 << 4)
+#define RT5677_I2S_PD3_3 (0x2 << 4)
+#define RT5677_I2S_PD3_4 (0x3 << 4)
+#define RT5677_I2S_PD3_6 (0x4 << 4)
+#define RT5677_I2S_PD3_8 (0x5 << 4)
+#define RT5677_I2S_PD3_12 (0x6 << 4)
+#define RT5677_I2S_PD3_16 (0x7 << 4)
+#define RT5677_I2S_BCLK_MS4_MASK (0x1 << 3)
+#define RT5677_I2S_BCLK_MS4_SFT 3
+#define RT5677_I2S_BCLK_MS4_32 (0x0 << 3)
+#define RT5677_I2S_BCLK_MS4_64 (0x1 << 3)
+#define RT5677_I2S_PD4_MASK (0x7 << 0)
+#define RT5677_I2S_PD4_SFT 0
+#define RT5677_I2S_PD4_1 (0x0 << 0)
+#define RT5677_I2S_PD4_2 (0x1 << 0)
+#define RT5677_I2S_PD4_3 (0x2 << 0)
+#define RT5677_I2S_PD4_4 (0x3 << 0)
+#define RT5677_I2S_PD4_6 (0x4 << 0)
+#define RT5677_I2S_PD4_8 (0x5 << 0)
+#define RT5677_I2S_PD4_12 (0x6 << 0)
+#define RT5677_I2S_PD4_16 (0x7 << 0)
+
+/* Clock Tree Control 2 (0x74) */
+#define RT5677_I2S_PD5_MASK (0x7 << 12)
+#define RT5677_I2S_PD5_SFT 12
+#define RT5677_I2S_PD5_1 (0x0 << 12)
+#define RT5677_I2S_PD5_2 (0x1 << 12)
+#define RT5677_I2S_PD5_3 (0x2 << 12)
+#define RT5677_I2S_PD5_4 (0x3 << 12)
+#define RT5677_I2S_PD5_6 (0x4 << 12)
+#define RT5677_I2S_PD5_8 (0x5 << 12)
+#define RT5677_I2S_PD5_12 (0x6 << 12)
+#define RT5677_I2S_PD5_16 (0x7 << 12)
+#define RT5677_I2S_PD6_MASK (0x7 << 8)
+#define RT5677_I2S_PD6_SFT 8
+#define RT5677_I2S_PD6_1 (0x0 << 8)
+#define RT5677_I2S_PD6_2 (0x1 << 8)
+#define RT5677_I2S_PD6_3 (0x2 << 8)
+#define RT5677_I2S_PD6_4 (0x3 << 8)
+#define RT5677_I2S_PD6_6 (0x4 << 8)
+#define RT5677_I2S_PD6_8 (0x5 << 8)
+#define RT5677_I2S_PD6_12 (0x6 << 8)
+#define RT5677_I2S_PD6_16 (0x7 << 8)
+#define RT5677_I2S_PD7_MASK (0x7 << 4)
+#define RT5677_I2S_PD7_SFT 4
+#define RT5677_I2S_PD7_1 (0x0 << 4)
+#define RT5677_I2S_PD7_2 (0x1 << 4)
+#define RT5677_I2S_PD7_3 (0x2 << 4)
+#define RT5677_I2S_PD7_4 (0x3 << 4)
+#define RT5677_I2S_PD7_6 (0x4 << 4)
+#define RT5677_I2S_PD7_8 (0x5 << 4)
+#define RT5677_I2S_PD7_12 (0x6 << 4)
+#define RT5677_I2S_PD7_16 (0x7 << 4)
+#define RT5677_I2S_PD8_MASK (0x7 << 0)
+#define RT5677_I2S_PD8_SFT 0
+#define RT5677_I2S_PD8_1 (0x0 << 0)
+#define RT5677_I2S_PD8_2 (0x1 << 0)
+#define RT5677_I2S_PD8_3 (0x2 << 0)
+#define RT5677_I2S_PD8_4 (0x3 << 0)
+#define RT5677_I2S_PD8_6 (0x4 << 0)
+#define RT5677_I2S_PD8_8 (0x5 << 0)
+#define RT5677_I2S_PD8_12 (0x6 << 0)
+#define RT5677_I2S_PD8_16 (0x7 << 0)
+
+/* Clock Tree Control 3 (0x75) */
+#define RT5677_DSP_ASRC_O_MASK (0x3 << 6)
+#define RT5677_DSP_ASRC_O_SFT 6
+#define RT5677_DSP_ASRC_O_1_0 (0x0 << 6)
+#define RT5677_DSP_ASRC_O_1_5 (0x1 << 6)
+#define RT5677_DSP_ASRC_O_2_0 (0x2 << 6)
+#define RT5677_DSP_ASRC_O_3_0 (0x3 << 6)
+#define RT5677_DSP_ASRC_I_MASK (0x3 << 4)
+#define RT5677_DSP_ASRC_I_SFT 4
+#define RT5677_DSP_ASRC_I_1_0 (0x0 << 4)
+#define RT5677_DSP_ASRC_I_1_5 (0x1 << 4)
+#define RT5677_DSP_ASRC_I_2_0 (0x2 << 4)
+#define RT5677_DSP_ASRC_I_3_0 (0x3 << 4)
+#define RT5677_DSP_BUS_PD_MASK (0x7 << 0)
+#define RT5677_DSP_BUS_PD_SFT 0
+#define RT5677_DSP_BUS_PD_1 (0x0 << 0)
+#define RT5677_DSP_BUS_PD_2 (0x1 << 0)
+#define RT5677_DSP_BUS_PD_3 (0x2 << 0)
+#define RT5677_DSP_BUS_PD_4 (0x3 << 0)
+#define RT5677_DSP_BUS_PD_6 (0x4 << 0)
+#define RT5677_DSP_BUS_PD_8 (0x5 << 0)
+#define RT5677_DSP_BUS_PD_12 (0x6 << 0)
+#define RT5677_DSP_BUS_PD_16 (0x7 << 0)
+
+#define RT5677_PLL_INP_MAX 40000000
+#define RT5677_PLL_INP_MIN 2048000
+/* PLL M/N/K Code Control 1 (0x7a 0x7c) */
+#define RT5677_PLL_N_MAX 0x1ff
+#define RT5677_PLL_N_MASK (RT5677_PLL_N_MAX << 7)
+#define RT5677_PLL_N_SFT 7
+#define RT5677_PLL_K_BP (0x1 << 5)
+#define RT5677_PLL_K_BP_SFT 5
+#define RT5677_PLL_K_MAX 0x1f
+#define RT5677_PLL_K_MASK (RT5677_PLL_K_MAX)
+#define RT5677_PLL_K_SFT 0
+
+/* PLL M/N/K Code Control 2 (0x7b 0x7d) */
+#define RT5677_PLL_M_MAX 0xf
+#define RT5677_PLL_M_MASK (RT5677_PLL_M_MAX << 12)
+#define RT5677_PLL_M_SFT 12
+#define RT5677_PLL_M_BP (0x1 << 11)
+#define RT5677_PLL_M_BP_SFT 11
+
+/* Global Clock Control 1 (0x80) */
+#define RT5677_SCLK_SRC_MASK (0x3 << 14)
+#define RT5677_SCLK_SRC_SFT 14
+#define RT5677_SCLK_SRC_MCLK (0x0 << 14)
+#define RT5677_SCLK_SRC_PLL1 (0x1 << 14)
+#define RT5677_SCLK_SRC_RCCLK (0x2 << 14) /* 25MHz */
+#define RT5677_SCLK_SRC_SLIM (0x3 << 14)
+#define RT5677_PLL1_SRC_MASK (0x7 << 11)
+#define RT5677_PLL1_SRC_SFT 11
+#define RT5677_PLL1_SRC_MCLK (0x0 << 11)
+#define RT5677_PLL1_SRC_BCLK1 (0x1 << 11)
+#define RT5677_PLL1_SRC_BCLK2 (0x2 << 11)
+#define RT5677_PLL1_SRC_BCLK3 (0x3 << 11)
+#define RT5677_PLL1_SRC_BCLK4 (0x4 << 11)
+#define RT5677_PLL1_SRC_RCCLK (0x5 << 11)
+#define RT5677_PLL1_SRC_SLIM (0x6 << 11)
+#define RT5677_MCLK_SRC_MASK (0x1 << 10)
+#define RT5677_MCLK_SRC_SFT 10
+#define RT5677_MCLK1_SRC (0x0 << 10)
+#define RT5677_MCLK2_SRC (0x1 << 10)
+#define RT5677_PLL1_PD_MASK (0x1 << 8)
+#define RT5677_PLL1_PD_SFT 8
+#define RT5677_PLL1_PD_1 (0x0 << 8)
+#define RT5677_PLL1_PD_2 (0x1 << 8)
+#define RT5671_DAC_OSR_MASK (0x3 << 6)
+#define RT5671_DAC_OSR_SFT 6
+#define RT5671_DAC_OSR_128 (0x0 << 6)
+#define RT5671_DAC_OSR_64 (0x1 << 6)
+#define RT5671_DAC_OSR_32 (0x2 << 6)
+#define RT5671_ADC_OSR_MASK (0x3 << 4)
+#define RT5671_ADC_OSR_SFT 4
+#define RT5671_ADC_OSR_128 (0x0 << 4)
+#define RT5671_ADC_OSR_64 (0x1 << 4)
+#define RT5671_ADC_OSR_32 (0x2 << 4)
+
+/* Global Clock Control 2 (0x81) */
+#define RT5677_PLL2_PR_SRC_MASK (0x1 << 15)
+#define RT5677_PLL2_PR_SRC_SFT 15
+#define RT5677_PLL2_PR_SRC_MCLK1 (0x0 << 15)
+#define RT5677_PLL2_PR_SRC_MCLK2 (0x1 << 15)
+#define RT5677_PLL2_SRC_MASK (0x7 << 12)
+#define RT5677_PLL2_SRC_SFT 12
+#define RT5677_PLL2_SRC_MCLK (0x0 << 12)
+#define RT5677_PLL2_SRC_BCLK1 (0x1 << 12)
+#define RT5677_PLL2_SRC_BCLK2 (0x2 << 12)
+#define RT5677_PLL2_SRC_BCLK3 (0x3 << 12)
+#define RT5677_PLL2_SRC_BCLK4 (0x4 << 12)
+#define RT5677_PLL2_SRC_RCCLK (0x5 << 12)
+#define RT5677_PLL2_SRC_SLIM (0x6 << 12)
+#define RT5671_DSP_ASRC_O_SRC (0x3 << 10)
+#define RT5671_DSP_ASRC_O_SRC_SFT 10
+#define RT5671_DSP_ASRC_O_MCLK (0x0 << 10)
+#define RT5671_DSP_ASRC_O_PLL1 (0x1 << 10)
+#define RT5671_DSP_ASRC_O_SLIM (0x2 << 10)
+#define RT5671_DSP_ASRC_O_RCCLK (0x3 << 10)
+#define RT5671_DSP_ASRC_I_SRC (0x3 << 8)
+#define RT5671_DSP_ASRC_I_SRC_SFT 8
+#define RT5671_DSP_ASRC_I_MCLK (0x0 << 8)
+#define RT5671_DSP_ASRC_I_PLL1 (0x1 << 8)
+#define RT5671_DSP_ASRC_I_SLIM (0x2 << 8)
+#define RT5671_DSP_ASRC_I_RCCLK (0x3 << 8)
+#define RT5677_DSP_CLK_SRC_MASK (0x1 << 7)
+#define RT5677_DSP_CLK_SRC_SFT 7
+#define RT5677_DSP_CLK_SRC_PLL2 (0x0 << 7)
+#define RT5677_DSP_CLK_SRC_BYPASS (0x1 << 7)
+
+/* VAD Function Control 4 (0x9f) */
+#define RT5677_VAD_SRC_MASK (0x7 << 8)
+#define RT5677_VAD_SRC_SFT 8
+
+/* DSP InBound Control (0xa3) */
+#define RT5677_IB01_SRC_MASK (0x7 << 12)
+#define RT5677_IB01_SRC_SFT 12
+#define RT5677_IB23_SRC_MASK (0x7 << 8)
+#define RT5677_IB23_SRC_SFT 8
+#define RT5677_IB45_SRC_MASK (0x7 << 4)
+#define RT5677_IB45_SRC_SFT 4
+#define RT5677_IB6_SRC_MASK (0x7 << 0)
+#define RT5677_IB6_SRC_SFT 0
+
+/* DSP InBound Control (0xa4) */
+#define RT5677_IB7_SRC_MASK (0x7 << 12)
+#define RT5677_IB7_SRC_SFT 12
+#define RT5677_IB8_SRC_MASK (0x7 << 8)
+#define RT5677_IB8_SRC_SFT 8
+#define RT5677_IB9_SRC_MASK (0x7 << 4)
+#define RT5677_IB9_SRC_SFT 4
+
+/* DSP In/OutBound Control (0xa5) */
+#define RT5677_SEL_SRC_OB23 (0x1 << 4)
+#define RT5677_SEL_SRC_OB23_SFT 4
+#define RT5677_SEL_SRC_OB01 (0x1 << 3)
+#define RT5677_SEL_SRC_OB01_SFT 3
+#define RT5677_SEL_SRC_IB45 (0x1 << 2)
+#define RT5677_SEL_SRC_IB45_SFT 2
+#define RT5677_SEL_SRC_IB23 (0x1 << 1)
+#define RT5677_SEL_SRC_IB23_SFT 1
+#define RT5677_SEL_SRC_IB01 (0x1 << 0)
+#define RT5677_SEL_SRC_IB01_SFT 0
+
+/* Virtual DSP Mixer Control (0xf7 0xf8 0xf9) */
+#define RT5677_DSP_IB_01_H (0x1 << 15)
+#define RT5677_DSP_IB_01_H_SFT 15
+#define RT5677_DSP_IB_23_H (0x1 << 14)
+#define RT5677_DSP_IB_23_H_SFT 14
+#define RT5677_DSP_IB_45_H (0x1 << 13)
+#define RT5677_DSP_IB_45_H_SFT 13
+#define RT5677_DSP_IB_6_H (0x1 << 12)
+#define RT5677_DSP_IB_6_H_SFT 12
+#define RT5677_DSP_IB_7_H (0x1 << 11)
+#define RT5677_DSP_IB_7_H_SFT 11
+#define RT5677_DSP_IB_8_H (0x1 << 10)
+#define RT5677_DSP_IB_8_H_SFT 10
+#define RT5677_DSP_IB_9_H (0x1 << 9)
+#define RT5677_DSP_IB_9_H_SFT 9
+#define RT5677_DSP_IB_01_L (0x1 << 7)
+#define RT5677_DSP_IB_01_L_SFT 7
+#define RT5677_DSP_IB_23_L (0x1 << 6)
+#define RT5677_DSP_IB_23_L_SFT 6
+#define RT5677_DSP_IB_45_L (0x1 << 5)
+#define RT5677_DSP_IB_45_L_SFT 5
+#define RT5677_DSP_IB_6_L (0x1 << 4)
+#define RT5677_DSP_IB_6_L_SFT 4
+#define RT5677_DSP_IB_7_L (0x1 << 3)
+#define RT5677_DSP_IB_7_L_SFT 3
+#define RT5677_DSP_IB_8_L (0x1 << 2)
+#define RT5677_DSP_IB_8_L_SFT 2
+#define RT5677_DSP_IB_9_L (0x1 << 1)
+#define RT5677_DSP_IB_9_L_SFT 1
+
+/* Debug String Length */
+#define RT5677_REG_DISP_LEN 23
+
+#define RT5677_NO_JACK BIT(0)
+#define RT5677_HEADSET_DET BIT(1)
+#define RT5677_HEADPHO_DET BIT(2)
+
+/* System Clock Source */
+enum {
+ RT5677_SCLK_S_MCLK,
+ RT5677_SCLK_S_PLL1,
+ RT5677_SCLK_S_RCCLK,
+};
+
+/* PLL1 Source */
+enum {
+ RT5677_PLL1_S_MCLK,
+ RT5677_PLL1_S_BCLK1,
+ RT5677_PLL1_S_BCLK2,
+ RT5677_PLL1_S_BCLK3,
+ RT5677_PLL1_S_BCLK4,
+};
+
+enum {
+ RT5677_AIF1,
+ RT5677_AIF2,
+ RT5677_AIF3,
+ RT5677_AIF4,
+ RT5677_AIF5,
+ RT5677_AIFS,
+};
+
+struct rt5677_pll_code {
+ bool m_bp; /* Indicates bypass m code or not. */
+ bool k_bp; /* Indicates bypass k code or not. */
+ int m_code;
+ int n_code;
+ int k_code;
+};
+
+struct rt5677_priv {
+ struct snd_soc_codec *codec;
+ struct rt5677_platform_data pdata;
+ struct regmap *regmap;
+
+ int sysclk;
+ int sysclk_src;
+ int lrck[RT5677_AIFS];
+ int bclk[RT5677_AIFS];
+ int master[RT5677_AIFS];
+ int pll_src;
+ int pll_in;
+ int pll_out;
+};
+
+#endif /* __RT5677_H__ */
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 0fcbe90f3ef..3d39f0b5b4a 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -36,18 +36,32 @@
/* default value of sgtl5000 registers */
static const struct reg_default sgtl5000_reg_defaults[] = {
+ { SGTL5000_CHIP_DIG_POWER, 0x0000 },
{ SGTL5000_CHIP_CLK_CTRL, 0x0008 },
{ SGTL5000_CHIP_I2S_CTRL, 0x0010 },
{ SGTL5000_CHIP_SSS_CTRL, 0x0010 },
+ { SGTL5000_CHIP_ADCDAC_CTRL, 0x020c },
{ SGTL5000_CHIP_DAC_VOL, 0x3c3c },
{ SGTL5000_CHIP_PAD_STRENGTH, 0x015f },
+ { SGTL5000_CHIP_ANA_ADC_CTRL, 0x0000 },
{ SGTL5000_CHIP_ANA_HP_CTRL, 0x1818 },
{ SGTL5000_CHIP_ANA_CTRL, 0x0111 },
+ { SGTL5000_CHIP_LINREG_CTRL, 0x0000 },
+ { SGTL5000_CHIP_REF_CTRL, 0x0000 },
+ { SGTL5000_CHIP_MIC_CTRL, 0x0000 },
+ { SGTL5000_CHIP_LINE_OUT_CTRL, 0x0000 },
{ SGTL5000_CHIP_LINE_OUT_VOL, 0x0404 },
{ SGTL5000_CHIP_ANA_POWER, 0x7060 },
{ SGTL5000_CHIP_PLL_CTRL, 0x5000 },
+ { SGTL5000_CHIP_CLK_TOP_CTRL, 0x0000 },
+ { SGTL5000_CHIP_ANA_STATUS, 0x0000 },
+ { SGTL5000_CHIP_SHORT_CTRL, 0x0000 },
+ { SGTL5000_CHIP_ANA_TEST2, 0x0000 },
+ { SGTL5000_DAP_CTRL, 0x0000 },
+ { SGTL5000_DAP_PEQ, 0x0000 },
{ SGTL5000_DAP_BASS_ENHANCE, 0x0040 },
{ SGTL5000_DAP_BASS_ENHANCE_CTRL, 0x051f },
+ { SGTL5000_DAP_AUDIO_EQ, 0x0000 },
{ SGTL5000_DAP_SURROUND, 0x0040 },
{ SGTL5000_DAP_EQ_BASS_BAND0, 0x002f },
{ SGTL5000_DAP_EQ_BASS_BAND1, 0x002f },
@@ -55,6 +69,7 @@ static const struct reg_default sgtl5000_reg_defaults[] = {
{ SGTL5000_DAP_EQ_BASS_BAND3, 0x002f },
{ SGTL5000_DAP_EQ_BASS_BAND4, 0x002f },
{ SGTL5000_DAP_MAIN_CHAN, 0x8000 },
+ { SGTL5000_DAP_MIX_CHAN, 0x0000 },
{ SGTL5000_DAP_AVC_CTRL, 0x0510 },
{ SGTL5000_DAP_AVC_THRESHOLD, 0x1473 },
{ SGTL5000_DAP_AVC_ATTACK, 0x0028 },
@@ -187,8 +202,9 @@ static const char *adc_mux_text[] = {
"MIC_IN", "LINE_IN"
};
-static const struct soc_enum adc_enum =
-SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 2, 2, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(adc_enum,
+ SGTL5000_CHIP_ANA_CTRL, 2,
+ adc_mux_text);
static const struct snd_kcontrol_new adc_mux =
SOC_DAPM_ENUM("Capture Mux", adc_enum);
@@ -198,8 +214,9 @@ static const char *dac_mux_text[] = {
"DAC", "LINE_IN"
};
-static const struct soc_enum dac_enum =
-SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 6, 2, dac_mux_text);
+static SOC_ENUM_SINGLE_DECL(dac_enum,
+ SGTL5000_CHIP_ANA_CTRL, 6,
+ dac_mux_text);
static const struct snd_kcontrol_new dac_mux =
SOC_DAPM_ENUM("Headphone Mux", dac_enum);
@@ -294,7 +311,7 @@ static int dac_info_volsw(struct snd_kcontrol *kcontrol,
static int dac_get_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
int reg;
int l;
int r;
@@ -347,7 +364,7 @@ static int dac_get_volsw(struct snd_kcontrol *kcontrol,
static int dac_put_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
int reg;
int l;
int r;
@@ -1066,71 +1083,11 @@ static int sgtl5000_suspend(struct snd_soc_codec *codec)
return 0;
}
-/*
- * restore all sgtl5000 registers,
- * since a big hole between dap and regular registers,
- * we will restore them respectively.
- */
-static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
-{
- u16 *cache = codec->reg_cache;
- u16 reg;
-
- /* restore regular registers */
- for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
-
- /* These regs should restore in particular order */
- if (reg == SGTL5000_CHIP_ANA_POWER ||
- reg == SGTL5000_CHIP_CLK_CTRL ||
- reg == SGTL5000_CHIP_LINREG_CTRL ||
- reg == SGTL5000_CHIP_LINE_OUT_CTRL ||
- reg == SGTL5000_CHIP_REF_CTRL)
- continue;
-
- snd_soc_write(codec, reg, cache[reg]);
- }
-
- /* restore dap registers */
- for (reg = SGTL5000_DAP_REG_OFFSET; reg < SGTL5000_MAX_REG_OFFSET; reg += 2)
- snd_soc_write(codec, reg, cache[reg]);
-
- /*
- * restore these regs according to the power setting sequence in
- * sgtl5000_set_power_regs() and clock setting sequence in
- * sgtl5000_set_clock().
- *
- * The order of restore is:
- * 1. SGTL5000_CHIP_CLK_CTRL MCLK_FREQ bits (1:0) should be restore after
- * SGTL5000_CHIP_ANA_POWER PLL bits set
- * 2. SGTL5000_CHIP_LINREG_CTRL should be set before
- * SGTL5000_CHIP_ANA_POWER LINREG_D restored
- * 3. SGTL5000_CHIP_REF_CTRL controls Analog Ground Voltage,
- * prefer to resotre it after SGTL5000_CHIP_ANA_POWER restored
- */
- snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
- cache[SGTL5000_CHIP_LINREG_CTRL]);
-
- snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER,
- cache[SGTL5000_CHIP_ANA_POWER]);
-
- snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL,
- cache[SGTL5000_CHIP_CLK_CTRL]);
-
- snd_soc_write(codec, SGTL5000_CHIP_REF_CTRL,
- cache[SGTL5000_CHIP_REF_CTRL]);
-
- snd_soc_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
- cache[SGTL5000_CHIP_LINE_OUT_CTRL]);
- return 0;
-}
-
static int sgtl5000_resume(struct snd_soc_codec *codec)
{
/* Bring the codec back up to standby to enable regulators */
sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- /* Restore registers by cached in memory */
- sgtl5000_restore_regs(codec);
return 0;
}
#else
@@ -1320,7 +1277,7 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
return ret;
}
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
+ ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
sgtl5000->supplies);
if (ret)
goto err_ldo_remove;
@@ -1328,16 +1285,13 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
sgtl5000->supplies);
if (ret)
- goto err_regulator_free;
+ goto err_ldo_remove;
/* wait for all power rails bring up */
udelay(10);
return 0;
-err_regulator_free:
- regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
- sgtl5000->supplies);
err_ldo_remove:
if (!external_vddd)
ldo_regulator_remove(codec);
@@ -1350,14 +1304,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
int ret;
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
- /* setup i2c data ops */
- codec->control_data = sgtl5000->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = sgtl5000_enable_regulators(codec);
if (ret)
return ret;
@@ -1415,8 +1361,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
err:
regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
sgtl5000->supplies);
- regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
- sgtl5000->supplies);
ldo_regulator_remove(codec);
return ret;
@@ -1430,8 +1374,6 @@ static int sgtl5000_remove(struct snd_soc_codec *codec)
regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
sgtl5000->supplies);
- regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
- sgtl5000->supplies);
ldo_regulator_remove(codec);
return 0;
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
index 52e7cb08434..f26befb0c29 100644
--- a/sound/soc/codecs/si476x.c
+++ b/sound/soc/codecs/si476x.c
@@ -21,6 +21,7 @@
#include <linux/slab.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
+#include <linux/regmap.h>
#include <sound/soc.h>
#include <sound/initval.h>
@@ -207,12 +208,6 @@ out:
return err;
}
-static int si476x_codec_probe(struct snd_soc_codec *codec)
-{
- codec->control_data = dev_get_regmap(codec->dev->parent, NULL);
- return 0;
-}
-
static struct snd_soc_dai_ops si476x_dai_ops = {
.hw_params = si476x_codec_hw_params,
.set_fmt = si476x_codec_set_dai_fmt,
@@ -236,8 +231,13 @@ static struct snd_soc_dai_driver si476x_dai = {
.ops = &si476x_dai_ops,
};
+static struct regmap *si476x_get_regmap(struct device *dev)
+{
+ return dev_get_regmap(dev->parent, NULL);
+}
+
static struct snd_soc_codec_driver soc_codec_dev_si476x = {
- .probe = si476x_codec_probe,
+ .get_regmap = si476x_get_regmap,
.dapm_widgets = si476x_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(si476x_dapm_widgets),
.dapm_routes = si476x_dapm_routes,
diff --git a/sound/soc/codecs/sigmadsp-i2c.c b/sound/soc/codecs/sigmadsp-i2c.c
new file mode 100644
index 00000000000..246081aae8c
--- /dev/null
+++ b/sound/soc/codecs/sigmadsp-i2c.c
@@ -0,0 +1,35 @@
+/*
+ * Load Analog Devices SigmaStudio firmware files
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/i2c.h>
+#include <linux/export.h>
+#include <linux/module.h>
+
+#include "sigmadsp.h"
+
+static int sigma_action_write_i2c(void *control_data,
+ const struct sigma_action *sa, size_t len)
+{
+ return i2c_master_send(control_data, (const unsigned char *)&sa->addr,
+ len);
+}
+
+int process_sigma_firmware(struct i2c_client *client, const char *name)
+{
+ struct sigma_firmware ssfw;
+
+ ssfw.control_data = client;
+ ssfw.write = sigma_action_write_i2c;
+
+ return _process_sigma_firmware(&client->dev, &ssfw, name);
+}
+EXPORT_SYMBOL(process_sigma_firmware);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("SigmaDSP I2C firmware loader");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sigmadsp-regmap.c b/sound/soc/codecs/sigmadsp-regmap.c
new file mode 100644
index 00000000000..f78ed8d2cfb
--- /dev/null
+++ b/sound/soc/codecs/sigmadsp-regmap.c
@@ -0,0 +1,36 @@
+/*
+ * Load Analog Devices SigmaStudio firmware files
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/regmap.h>
+#include <linux/export.h>
+#include <linux/module.h>
+
+#include "sigmadsp.h"
+
+static int sigma_action_write_regmap(void *control_data,
+ const struct sigma_action *sa, size_t len)
+{
+ return regmap_raw_write(control_data, be16_to_cpu(sa->addr),
+ sa->payload, len - 2);
+}
+
+int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap,
+ const char *name)
+{
+ struct sigma_firmware ssfw;
+
+ ssfw.control_data = regmap;
+ ssfw.write = sigma_action_write_regmap;
+
+ return _process_sigma_firmware(dev, &ssfw, name);
+}
+EXPORT_SYMBOL(process_sigma_firmware_regmap);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("SigmaDSP regmap firmware loader");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c
index 4068f249123..f2de7e049bc 100644
--- a/sound/soc/codecs/sigmadsp.c
+++ b/sound/soc/codecs/sigmadsp.c
@@ -34,23 +34,6 @@ enum {
SIGMA_ACTION_END,
};
-struct sigma_action {
- u8 instr;
- u8 len_hi;
- __le16 len;
- __be16 addr;
- unsigned char payload[];
-} __packed;
-
-struct sigma_firmware {
- const struct firmware *fw;
- size_t pos;
-
- void *control_data;
- int (*write)(void *control_data, const struct sigma_action *sa,
- size_t len);
-};
-
static inline u32 sigma_action_len(struct sigma_action *sa)
{
return (sa->len_hi << 16) | le16_to_cpu(sa->len);
@@ -138,7 +121,7 @@ process_sigma_actions(struct sigma_firmware *ssfw)
return 0;
}
-static int _process_sigma_firmware(struct device *dev,
+int _process_sigma_firmware(struct device *dev,
struct sigma_firmware *ssfw, const char *name)
{
int ret;
@@ -197,50 +180,6 @@ static int _process_sigma_firmware(struct device *dev,
return ret;
}
-
-#if IS_ENABLED(CONFIG_I2C)
-
-static int sigma_action_write_i2c(void *control_data,
- const struct sigma_action *sa, size_t len)
-{
- return i2c_master_send(control_data, (const unsigned char *)&sa->addr,
- len);
-}
-
-int process_sigma_firmware(struct i2c_client *client, const char *name)
-{
- struct sigma_firmware ssfw;
-
- ssfw.control_data = client;
- ssfw.write = sigma_action_write_i2c;
-
- return _process_sigma_firmware(&client->dev, &ssfw, name);
-}
-EXPORT_SYMBOL(process_sigma_firmware);
-
-#endif
-
-#if IS_ENABLED(CONFIG_REGMAP)
-
-static int sigma_action_write_regmap(void *control_data,
- const struct sigma_action *sa, size_t len)
-{
- return regmap_raw_write(control_data, be16_to_cpu(sa->addr),
- sa->payload, len - 2);
-}
-
-int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap,
- const char *name)
-{
- struct sigma_firmware ssfw;
-
- ssfw.control_data = regmap;
- ssfw.write = sigma_action_write_regmap;
-
- return _process_sigma_firmware(dev, &ssfw, name);
-}
-EXPORT_SYMBOL(process_sigma_firmware_regmap);
-
-#endif
+EXPORT_SYMBOL_GPL(_process_sigma_firmware);
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sigmadsp.h b/sound/soc/codecs/sigmadsp.h
index e439cbd7af7..c47cd23e982 100644
--- a/sound/soc/codecs/sigmadsp.h
+++ b/sound/soc/codecs/sigmadsp.h
@@ -12,6 +12,26 @@
#include <linux/device.h>
#include <linux/regmap.h>
+struct sigma_action {
+ u8 instr;
+ u8 len_hi;
+ __le16 len;
+ __be16 addr;
+ unsigned char payload[];
+} __packed;
+
+struct sigma_firmware {
+ const struct firmware *fw;
+ size_t pos;
+
+ void *control_data;
+ int (*write)(void *control_data, const struct sigma_action *sa,
+ size_t len);
+};
+
+int _process_sigma_firmware(struct device *dev,
+ struct sigma_firmware *ssfw, const char *name);
+
struct i2c_client;
extern int process_sigma_firmware(struct i2c_client *client, const char *name);
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c
new file mode 100644
index 00000000000..d90cb0fafcb
--- /dev/null
+++ b/sound/soc/codecs/sirf-audio-codec.c
@@ -0,0 +1,580 @@
+/*
+ * SiRF audio codec driver
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/regmap.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
+
+#include "sirf-audio-codec.h"
+
+struct sirf_audio_codec {
+ struct clk *clk;
+ struct regmap *regmap;
+ u32 reg_ctrl0, reg_ctrl1;
+};
+
+static const char * const input_mode_mux[] = {"Single-ended",
+ "Differential"};
+
+static const struct soc_enum input_mode_mux_enum =
+ SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux);
+
+static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control =
+ SOC_DAPM_ENUM("Route", input_mode_mux_enum);
+
+static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0);
+static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0);
+static const DECLARE_TLV_DB_RANGE(capture_vol_tlv_atlas6,
+ 0, 7, TLV_DB_SCALE_ITEM(-100, 100, 0),
+ 0x22, 0x3F, TLV_DB_SCALE_ITEM(700, 100, 0),
+);
+
+static struct snd_kcontrol_new volume_controls_atlas6[] = {
+ SOC_DOUBLE_TLV("Playback Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
+ 0x7F, 0, playback_vol_tlv),
+ SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 16, 10,
+ 0x3F, 0, capture_vol_tlv_atlas6),
+};
+
+static struct snd_kcontrol_new volume_controls_prima2[] = {
+ SOC_DOUBLE_TLV("Speaker Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
+ 0x7F, 0, playback_vol_tlv),
+ SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 15, 10,
+ 0x1F, 0, capture_vol_tlv_prima2),
+};
+
+static struct snd_kcontrol_new left_input_path_controls[] = {
+ SOC_DAPM_SINGLE("Line Left Switch", AUDIO_IC_CODEC_CTRL1, 6, 1, 0),
+ SOC_DAPM_SINGLE("Mic Left Switch", AUDIO_IC_CODEC_CTRL1, 3, 1, 0),
+};
+
+static struct snd_kcontrol_new right_input_path_controls[] = {
+ SOC_DAPM_SINGLE("Line Right Switch", AUDIO_IC_CODEC_CTRL1, 5, 1, 0),
+ SOC_DAPM_SINGLE("Mic Right Switch", AUDIO_IC_CODEC_CTRL1, 2, 1, 0),
+};
+
+static struct snd_kcontrol_new left_dac_to_hp_left_amp_switch_control =
+ SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 9, 1, 0);
+
+static struct snd_kcontrol_new left_dac_to_hp_right_amp_switch_control =
+ SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 8, 1, 0);
+
+static struct snd_kcontrol_new right_dac_to_hp_left_amp_switch_control =
+ SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 7, 1, 0);
+
+static struct snd_kcontrol_new right_dac_to_hp_right_amp_switch_control =
+ SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 6, 1, 0);
+
+static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control =
+ SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0);
+
+static struct snd_kcontrol_new right_dac_to_speaker_lineout_switch_control =
+ SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 10, 1, 0);
+
+/* After enable adc, Delay 200ms to avoid pop noise */
+static int adc_enable_delay_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ msleep(200);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void enable_and_reset_codec(struct regmap *regmap,
+ u32 codec_enable_bits, u32 codec_reset_bits)
+{
+ regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
+ codec_enable_bits | codec_reset_bits,
+ codec_enable_bits);
+ msleep(20);
+ regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
+ codec_reset_bits, codec_reset_bits);
+}
+
+static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+#define ATLAS6_CODEC_ENABLE_BITS (1 << 29)
+#define ATLAS6_CODEC_RESET_BITS (1 << 28)
+ struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ enable_and_reset_codec(sirf_audio_codec->regmap,
+ ATLAS6_CODEC_ENABLE_BITS, ATLAS6_CODEC_RESET_BITS);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ regmap_update_bits(sirf_audio_codec->regmap,
+ AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, 0);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+#define PRIMA2_CODEC_ENABLE_BITS (1 << 27)
+#define PRIMA2_CODEC_RESET_BITS (1 << 26)
+ struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev);
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ enable_and_reset_codec(sirf_audio_codec->regmap,
+ PRIMA2_CODEC_ENABLE_BITS, PRIMA2_CODEC_RESET_BITS);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ regmap_update_bits(sirf_audio_codec->regmap,
+ AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, 0);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget atlas6_output_driver_dapm_widgets[] = {
+ SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
+ 25, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
+ 26, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
+ 27, 0, NULL, 0),
+};
+
+static const struct snd_soc_dapm_widget prima2_output_driver_dapm_widgets[] = {
+ SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
+ 23, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
+ 24, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
+ 25, 0, NULL, 0),
+};
+
+static const struct snd_soc_dapm_widget atlas6_codec_clock_dapm_widget =
+ SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
+ atlas6_codec_enable_and_reset_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
+
+static const struct snd_soc_dapm_widget prima2_codec_clock_dapm_widget =
+ SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
+ prima2_codec_enable_and_reset_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
+
+static const struct snd_soc_dapm_widget sirf_audio_codec_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC("DAC left", NULL, AUDIO_IC_CODEC_CTRL0, 1, 0),
+ SND_SOC_DAPM_DAC("DAC right", NULL, AUDIO_IC_CODEC_CTRL0, 0, 0),
+ SND_SOC_DAPM_SWITCH("Left dac to hp left amp", SND_SOC_NOPM, 0, 0,
+ &left_dac_to_hp_left_amp_switch_control),
+ SND_SOC_DAPM_SWITCH("Left dac to hp right amp", SND_SOC_NOPM, 0, 0,
+ &left_dac_to_hp_right_amp_switch_control),
+ SND_SOC_DAPM_SWITCH("Right dac to hp left amp", SND_SOC_NOPM, 0, 0,
+ &right_dac_to_hp_left_amp_switch_control),
+ SND_SOC_DAPM_SWITCH("Right dac to hp right amp", SND_SOC_NOPM, 0, 0,
+ &right_dac_to_hp_right_amp_switch_control),
+ SND_SOC_DAPM_OUT_DRV("HP amp left driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
+ NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("HP amp right driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
+ NULL, 0),
+
+ SND_SOC_DAPM_SWITCH("Left dac to speaker lineout", SND_SOC_NOPM, 0, 0,
+ &left_dac_to_speaker_lineout_switch_control),
+ SND_SOC_DAPM_SWITCH("Right dac to speaker lineout", SND_SOC_NOPM, 0, 0,
+ &right_dac_to_speaker_lineout_switch_control),
+ SND_SOC_DAPM_OUT_DRV("Speaker amp driver", AUDIO_IC_CODEC_CTRL0, 4, 0,
+ NULL, 0),
+
+ SND_SOC_DAPM_OUTPUT("HPOUTL"),
+ SND_SOC_DAPM_OUTPUT("HPOUTR"),
+ SND_SOC_DAPM_OUTPUT("SPKOUT"),
+
+ SND_SOC_DAPM_ADC_E("ADC left", NULL, AUDIO_IC_CODEC_CTRL1, 8, 0,
+ adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_ADC_E("ADC right", NULL, AUDIO_IC_CODEC_CTRL1, 7, 0,
+ adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MIXER("Left PGA mixer", AUDIO_IC_CODEC_CTRL1, 1, 0,
+ &left_input_path_controls[0],
+ ARRAY_SIZE(left_input_path_controls)),
+ SND_SOC_DAPM_MIXER("Right PGA mixer", AUDIO_IC_CODEC_CTRL1, 0, 0,
+ &right_input_path_controls[0],
+ ARRAY_SIZE(right_input_path_controls)),
+
+ SND_SOC_DAPM_MUX("Mic input mode mux", SND_SOC_NOPM, 0, 0,
+ &sirf_audio_codec_input_mode_control),
+ SND_SOC_DAPM_MICBIAS("Mic Bias", AUDIO_IC_CODEC_PWR, 3, 0),
+ SND_SOC_DAPM_INPUT("MICIN1"),
+ SND_SOC_DAPM_INPUT("MICIN2"),
+ SND_SOC_DAPM_INPUT("LINEIN1"),
+ SND_SOC_DAPM_INPUT("LINEIN2"),
+
+ SND_SOC_DAPM_SUPPLY("HSL Phase Opposite", AUDIO_IC_CODEC_CTRL0,
+ 30, 0, NULL, 0),
+};
+
+static const struct snd_soc_dapm_route sirf_audio_codec_map[] = {
+ {"SPKOUT", NULL, "Speaker Driver"},
+ {"Speaker Driver", NULL, "Speaker amp driver"},
+ {"Speaker amp driver", NULL, "Left dac to speaker lineout"},
+ {"Speaker amp driver", NULL, "Right dac to speaker lineout"},
+ {"Left dac to speaker lineout", "Switch", "DAC left"},
+ {"Right dac to speaker lineout", "Switch", "DAC right"},
+ {"HPOUTL", NULL, "HP Left Driver"},
+ {"HPOUTR", NULL, "HP Right Driver"},
+ {"HP Left Driver", NULL, "HP amp left driver"},
+ {"HP Right Driver", NULL, "HP amp right driver"},
+ {"HP amp left driver", NULL, "Right dac to hp left amp"},
+ {"HP amp right driver", NULL , "Right dac to hp right amp"},
+ {"HP amp left driver", NULL, "Left dac to hp left amp"},
+ {"HP amp right driver", NULL , "Right dac to hp right amp"},
+ {"Right dac to hp left amp", "Switch", "DAC left"},
+ {"Right dac to hp right amp", "Switch", "DAC right"},
+ {"Left dac to hp left amp", "Switch", "DAC left"},
+ {"Left dac to hp right amp", "Switch", "DAC right"},
+ {"DAC left", NULL, "codecclk"},
+ {"DAC right", NULL, "codecclk"},
+ {"DAC left", NULL, "Playback"},
+ {"DAC right", NULL, "Playback"},
+ {"DAC left", NULL, "HSL Phase Opposite"},
+ {"DAC right", NULL, "HSL Phase Opposite"},
+
+ {"Capture", NULL, "ADC left"},
+ {"Capture", NULL, "ADC right"},
+ {"ADC left", NULL, "codecclk"},
+ {"ADC right", NULL, "codecclk"},
+ {"ADC left", NULL, "Left PGA mixer"},
+ {"ADC right", NULL, "Right PGA mixer"},
+ {"Left PGA mixer", "Line Left Switch", "LINEIN2"},
+ {"Right PGA mixer", "Line Right Switch", "LINEIN1"},
+ {"Left PGA mixer", "Mic Left Switch", "MICIN2"},
+ {"Right PGA mixer", "Mic Right Switch", "Mic input mode mux"},
+ {"Mic input mode mux", "Single-ended", "MICIN1"},
+ {"Mic input mode mux", "Differential", "MICIN1"},
+};
+
+static void sirf_audio_codec_tx_enable(struct sirf_audio_codec *sirf_audio_codec)
+{
+ regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
+ AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
+ regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
+ AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
+ regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0);
+ regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
+ regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
+ AUDIO_FIFO_START, AUDIO_FIFO_START);
+ regmap_update_bits(sirf_audio_codec->regmap,
+ AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, IC_TX_ENABLE);
+}
+
+static void sirf_audio_codec_tx_disable(struct sirf_audio_codec *sirf_audio_codec)
+{
+ regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
+ regmap_update_bits(sirf_audio_codec->regmap,
+ AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, ~IC_TX_ENABLE);
+}
+
+static void sirf_audio_codec_rx_enable(struct sirf_audio_codec *sirf_audio_codec,
+ int channels)
+{
+ regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
+ AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
+ regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
+ AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
+ regmap_write(sirf_audio_codec->regmap,
+ AUDIO_PORT_IC_RXFIFO_INT_MSK, 0);
+ regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0);
+ regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
+ AUDIO_FIFO_START, AUDIO_FIFO_START);
+ if (channels == 1)
+ regmap_update_bits(sirf_audio_codec->regmap,
+ AUDIO_PORT_IC_CODEC_RX_CTRL,
+ IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO);
+ else
+ regmap_update_bits(sirf_audio_codec->regmap,
+ AUDIO_PORT_IC_CODEC_RX_CTRL,
+ IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO);
+}
+
+static void sirf_audio_codec_rx_disable(struct sirf_audio_codec *sirf_audio_codec)
+{
+ regmap_update_bits(sirf_audio_codec->regmap,
+ AUDIO_PORT_IC_CODEC_RX_CTRL,
+ IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO);
+}
+
+static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream,
+ int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec);
+ int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+
+ /*
+ * This is a workaround, When stop playback,
+ * need disable HP amp, avoid the current noise.
+ */
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (playback) {
+ snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0,
+ IC_HSLEN | IC_HSREN, 0);
+ sirf_audio_codec_tx_disable(sirf_audio_codec);
+ } else
+ sirf_audio_codec_rx_disable(sirf_audio_codec);
+ break;
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (playback) {
+ sirf_audio_codec_tx_enable(sirf_audio_codec);
+ snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0,
+ IC_HSLEN | IC_HSREN, IC_HSLEN | IC_HSREN);
+ } else
+ sirf_audio_codec_rx_enable(sirf_audio_codec,
+ substream->runtime->channels);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+struct snd_soc_dai_ops sirf_audio_codec_dai_ops = {
+ .trigger = sirf_audio_codec_trigger,
+};
+
+struct snd_soc_dai_driver sirf_audio_codec_dai = {
+ .name = "sirf-audio-codec",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .ops = &sirf_audio_codec_dai_ops,
+};
+
+static int sirf_audio_codec_probe(struct snd_soc_codec *codec)
+{
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+ pm_runtime_enable(codec->dev);
+
+ if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) {
+ snd_soc_dapm_new_controls(dapm,
+ prima2_output_driver_dapm_widgets,
+ ARRAY_SIZE(prima2_output_driver_dapm_widgets));
+ snd_soc_dapm_new_controls(dapm,
+ &prima2_codec_clock_dapm_widget, 1);
+ return snd_soc_add_codec_controls(codec,
+ volume_controls_prima2,
+ ARRAY_SIZE(volume_controls_prima2));
+ }
+ if (of_device_is_compatible(codec->dev->of_node, "sirf,atlas6-audio-codec")) {
+ snd_soc_dapm_new_controls(dapm,
+ atlas6_output_driver_dapm_widgets,
+ ARRAY_SIZE(atlas6_output_driver_dapm_widgets));
+ snd_soc_dapm_new_controls(dapm,
+ &atlas6_codec_clock_dapm_widget, 1);
+ return snd_soc_add_codec_controls(codec,
+ volume_controls_atlas6,
+ ARRAY_SIZE(volume_controls_atlas6));
+ }
+
+ return -EINVAL;
+}
+
+static int sirf_audio_codec_remove(struct snd_soc_codec *codec)
+{
+ pm_runtime_disable(codec->dev);
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_device_sirf_audio_codec = {
+ .probe = sirf_audio_codec_probe,
+ .remove = sirf_audio_codec_remove,
+ .dapm_widgets = sirf_audio_codec_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sirf_audio_codec_dapm_widgets),
+ .dapm_routes = sirf_audio_codec_map,
+ .num_dapm_routes = ARRAY_SIZE(sirf_audio_codec_map),
+ .idle_bias_off = true,
+};
+
+static const struct of_device_id sirf_audio_codec_of_match[] = {
+ { .compatible = "sirf,prima2-audio-codec" },
+ { .compatible = "sirf,atlas6-audio-codec" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match);
+
+static const struct regmap_config sirf_audio_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK,
+ .cache_type = REGCACHE_NONE,
+};
+
+static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct sirf_audio_codec *sirf_audio_codec;
+ void __iomem *base;
+ struct resource *mem_res;
+ const struct of_device_id *match;
+
+ match = of_match_node(sirf_audio_codec_of_match, pdev->dev.of_node);
+
+ sirf_audio_codec = devm_kzalloc(&pdev->dev,
+ sizeof(struct sirf_audio_codec), GFP_KERNEL);
+ if (!sirf_audio_codec)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, sirf_audio_codec);
+
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, mem_res);
+ if (base == NULL)
+ return -ENOMEM;
+
+ sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &sirf_audio_codec_regmap_config);
+ if (IS_ERR(sirf_audio_codec->regmap))
+ return PTR_ERR(sirf_audio_codec->regmap);
+
+ sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(sirf_audio_codec->clk)) {
+ dev_err(&pdev->dev, "Get clock failed.\n");
+ return PTR_ERR(sirf_audio_codec->clk);
+ }
+
+ ret = clk_prepare_enable(sirf_audio_codec->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Enable clock failed.\n");
+ return ret;
+ }
+
+ ret = snd_soc_register_codec(&(pdev->dev),
+ &soc_codec_device_sirf_audio_codec,
+ &sirf_audio_codec_dai, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "Register Audio Codec dai failed.\n");
+ goto err_clk_put;
+ }
+
+ /*
+ * Always open charge pump, if not, when the charge pump closed the
+ * adc will not stable
+ */
+ regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
+ IC_CPFREQ, IC_CPFREQ);
+
+ if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec"))
+ regmap_update_bits(sirf_audio_codec->regmap,
+ AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN);
+ return 0;
+
+err_clk_put:
+ clk_disable_unprepare(sirf_audio_codec->clk);
+ return ret;
+}
+
+static int sirf_audio_codec_driver_remove(struct platform_device *pdev)
+{
+ struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(sirf_audio_codec->clk);
+ snd_soc_unregister_codec(&(pdev->dev));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int sirf_audio_codec_suspend(struct device *dev)
+{
+ struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
+
+ regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
+ &sirf_audio_codec->reg_ctrl0);
+ regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
+ &sirf_audio_codec->reg_ctrl1);
+ clk_disable_unprepare(sirf_audio_codec->clk);
+
+ return 0;
+}
+
+static int sirf_audio_codec_resume(struct device *dev)
+{
+ struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(sirf_audio_codec->clk);
+ if (ret)
+ return ret;
+
+ regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
+ sirf_audio_codec->reg_ctrl0);
+ regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
+ sirf_audio_codec->reg_ctrl1);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops sirf_audio_codec_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume)
+};
+
+static struct platform_driver sirf_audio_codec_driver = {
+ .driver = {
+ .name = "sirf-audio-codec",
+ .owner = THIS_MODULE,
+ .of_match_table = sirf_audio_codec_of_match,
+ .pm = &sirf_audio_codec_pm_ops,
+ },
+ .probe = sirf_audio_codec_driver_probe,
+ .remove = sirf_audio_codec_driver_remove,
+};
+
+module_platform_driver(sirf_audio_codec_driver);
+
+MODULE_DESCRIPTION("SiRF audio codec driver");
+MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/sirf-audio-codec.h b/sound/soc/codecs/sirf-audio-codec.h
new file mode 100644
index 00000000000..ba1adc03839
--- /dev/null
+++ b/sound/soc/codecs/sirf-audio-codec.h
@@ -0,0 +1,125 @@
+/*
+ * SiRF inner codec controllers define
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef _SIRF_AUDIO_CODEC_H
+#define _SIRF_AUDIO_CODEC_H
+
+
+#define AUDIO_IC_CODEC_PWR (0x00E0)
+#define AUDIO_IC_CODEC_CTRL0 (0x00E4)
+#define AUDIO_IC_CODEC_CTRL1 (0x00E8)
+#define AUDIO_IC_CODEC_CTRL2 (0x00EC)
+#define AUDIO_IC_CODEC_CTRL3 (0x00F0)
+
+#define MICBIASEN (1 << 3)
+
+#define IC_RDACEN (1 << 0)
+#define IC_LDACEN (1 << 1)
+#define IC_HSREN (1 << 2)
+#define IC_HSLEN (1 << 3)
+#define IC_SPEN (1 << 4)
+#define IC_CPEN (1 << 5)
+
+#define IC_HPRSELR (1 << 6)
+#define IC_HPLSELR (1 << 7)
+#define IC_HPRSELL (1 << 8)
+#define IC_HPLSELL (1 << 9)
+#define IC_SPSELR (1 << 10)
+#define IC_SPSELL (1 << 11)
+
+#define IC_MONOR (1 << 12)
+#define IC_MONOL (1 << 13)
+
+#define IC_RXOSRSEL (1 << 28)
+#define IC_CPFREQ (1 << 29)
+#define IC_HSINVEN (1 << 30)
+
+#define IC_MICINREN (1 << 0)
+#define IC_MICINLEN (1 << 1)
+#define IC_MICIN1SEL (1 << 2)
+#define IC_MICIN2SEL (1 << 3)
+#define IC_MICDIFSEL (1 << 4)
+#define IC_LINEIN1SEL (1 << 5)
+#define IC_LINEIN2SEL (1 << 6)
+#define IC_RADCEN (1 << 7)
+#define IC_LADCEN (1 << 8)
+#define IC_ALM (1 << 9)
+
+#define IC_DIGMICEN (1 << 22)
+#define IC_DIGMICFREQ (1 << 23)
+#define IC_ADC14B_12 (1 << 24)
+#define IC_FIRDAC_HSL_EN (1 << 25)
+#define IC_FIRDAC_HSR_EN (1 << 26)
+#define IC_FIRDAC_LOUT_EN (1 << 27)
+#define IC_POR (1 << 28)
+#define IC_CODEC_CLK_EN (1 << 29)
+#define IC_HP_3DB_BOOST (1 << 30)
+
+#define IC_ADC_LEFT_GAIN_SHIFT 16
+#define IC_ADC_RIGHT_GAIN_SHIFT 10
+#define IC_ADC_GAIN_MASK 0x3F
+#define IC_MIC_MAX_GAIN 0x39
+
+#define IC_RXPGAR_MASK 0x3F
+#define IC_RXPGAR_SHIFT 14
+#define IC_RXPGAL_MASK 0x3F
+#define IC_RXPGAL_SHIFT 21
+#define IC_RXPGAR 0x7B
+#define IC_RXPGAL 0x7B
+
+#define AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK 0x3F
+#define AUDIO_PORT_TX_FIFO_SC_OFFSET 0
+#define AUDIO_PORT_TX_FIFO_LC_OFFSET 10
+#define AUDIO_PORT_TX_FIFO_HC_OFFSET 20
+
+#define TX_FIFO_SC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \
+ << AUDIO_PORT_TX_FIFO_SC_OFFSET)
+#define TX_FIFO_LC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \
+ << AUDIO_PORT_TX_FIFO_LC_OFFSET)
+#define TX_FIFO_HC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \
+ << AUDIO_PORT_TX_FIFO_HC_OFFSET)
+
+#define AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK 0x0F
+#define AUDIO_PORT_RX_FIFO_SC_OFFSET 0
+#define AUDIO_PORT_RX_FIFO_LC_OFFSET 10
+#define AUDIO_PORT_RX_FIFO_HC_OFFSET 20
+
+#define RX_FIFO_SC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \
+ << AUDIO_PORT_RX_FIFO_SC_OFFSET)
+#define RX_FIFO_LC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \
+ << AUDIO_PORT_RX_FIFO_LC_OFFSET)
+#define RX_FIFO_HC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \
+ << AUDIO_PORT_RX_FIFO_HC_OFFSET)
+#define AUDIO_PORT_IC_CODEC_TX_CTRL (0x00F4)
+#define AUDIO_PORT_IC_CODEC_RX_CTRL (0x00F8)
+
+#define AUDIO_PORT_IC_TXFIFO_OP (0x00FC)
+#define AUDIO_PORT_IC_TXFIFO_LEV_CHK (0x0100)
+#define AUDIO_PORT_IC_TXFIFO_STS (0x0104)
+#define AUDIO_PORT_IC_TXFIFO_INT (0x0108)
+#define AUDIO_PORT_IC_TXFIFO_INT_MSK (0x010C)
+
+#define AUDIO_PORT_IC_RXFIFO_OP (0x0110)
+#define AUDIO_PORT_IC_RXFIFO_LEV_CHK (0x0114)
+#define AUDIO_PORT_IC_RXFIFO_STS (0x0118)
+#define AUDIO_PORT_IC_RXFIFO_INT (0x011C)
+#define AUDIO_PORT_IC_RXFIFO_INT_MSK (0x0120)
+
+#define AUDIO_FIFO_START (1 << 0)
+#define AUDIO_FIFO_RESET (1 << 1)
+
+#define AUDIO_FIFO_FULL (1 << 0)
+#define AUDIO_FIFO_EMPTY (1 << 1)
+#define AUDIO_FIFO_OFLOW (1 << 2)
+#define AUDIO_FIFO_UFLOW (1 << 3)
+
+#define IC_TX_ENABLE (0x03)
+#define IC_RX_ENABLE_MONO (0x01)
+#define IC_RX_ENABLE_STEREO (0x03)
+
+#endif /*__SIRF_AUDIO_CODEC_H*/
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index 13045f2af4d..42dff26b3a2 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -312,14 +312,14 @@ static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w,
/* mux controls */
static const char *sn95031_mic_texts[] = { "AMIC", "LineIn" };
-static const struct soc_enum sn95031_micl_enum =
- SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 1, 2, sn95031_mic_texts);
+static SOC_ENUM_SINGLE_DECL(sn95031_micl_enum,
+ SN95031_ADCCONFIG, 1, sn95031_mic_texts);
static const struct snd_kcontrol_new sn95031_micl_mux_control =
SOC_DAPM_ENUM("Route", sn95031_micl_enum);
-static const struct soc_enum sn95031_micr_enum =
- SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 3, 2, sn95031_mic_texts);
+static SOC_ENUM_SINGLE_DECL(sn95031_micr_enum,
+ SN95031_ADCCONFIG, 3, sn95031_mic_texts);
static const struct snd_kcontrol_new sn95031_micr_mux_control =
SOC_DAPM_ENUM("Route", sn95031_micr_enum);
@@ -328,26 +328,26 @@ static const char *sn95031_input_texts[] = { "DMIC1", "DMIC2", "DMIC3",
"DMIC4", "DMIC5", "DMIC6",
"ADC Left", "ADC Right" };
-static const struct soc_enum sn95031_input1_enum =
- SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 0, 8, sn95031_input_texts);
+static SOC_ENUM_SINGLE_DECL(sn95031_input1_enum,
+ SN95031_AUDIOMUX12, 0, sn95031_input_texts);
static const struct snd_kcontrol_new sn95031_input1_mux_control =
SOC_DAPM_ENUM("Route", sn95031_input1_enum);
-static const struct soc_enum sn95031_input2_enum =
- SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 4, 8, sn95031_input_texts);
+static SOC_ENUM_SINGLE_DECL(sn95031_input2_enum,
+ SN95031_AUDIOMUX12, 4, sn95031_input_texts);
static const struct snd_kcontrol_new sn95031_input2_mux_control =
SOC_DAPM_ENUM("Route", sn95031_input2_enum);
-static const struct soc_enum sn95031_input3_enum =
- SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 0, 8, sn95031_input_texts);
+static SOC_ENUM_SINGLE_DECL(sn95031_input3_enum,
+ SN95031_AUDIOMUX34, 0, sn95031_input_texts);
static const struct snd_kcontrol_new sn95031_input3_mux_control =
SOC_DAPM_ENUM("Route", sn95031_input3_enum);
-static const struct soc_enum sn95031_input4_enum =
- SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 4, 8, sn95031_input_texts);
+static SOC_ENUM_SINGLE_DECL(sn95031_input4_enum,
+ SN95031_AUDIOMUX34, 4, sn95031_input_texts);
static const struct snd_kcontrol_new sn95031_input4_mux_control =
SOC_DAPM_ENUM("Route", sn95031_input4_enum);
@@ -359,19 +359,19 @@ static const char *sn95031_micmode_text[] = {"Single Ended", "Differential"};
/* 0dB to 30dB in 10dB steps */
static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 10, 0);
-static const struct soc_enum sn95031_micmode1_enum =
- SOC_ENUM_SINGLE(SN95031_MICAMP1, 1, 2, sn95031_micmode_text);
-static const struct soc_enum sn95031_micmode2_enum =
- SOC_ENUM_SINGLE(SN95031_MICAMP2, 1, 2, sn95031_micmode_text);
+static SOC_ENUM_SINGLE_DECL(sn95031_micmode1_enum,
+ SN95031_MICAMP1, 1, sn95031_micmode_text);
+static SOC_ENUM_SINGLE_DECL(sn95031_micmode2_enum,
+ SN95031_MICAMP2, 1, sn95031_micmode_text);
static const char *sn95031_dmic_cfg_text[] = {"GPO", "DMIC"};
-static const struct soc_enum sn95031_dmic12_cfg_enum =
- SOC_ENUM_SINGLE(SN95031_DMICMUX, 0, 2, sn95031_dmic_cfg_text);
-static const struct soc_enum sn95031_dmic34_cfg_enum =
- SOC_ENUM_SINGLE(SN95031_DMICMUX, 1, 2, sn95031_dmic_cfg_text);
-static const struct soc_enum sn95031_dmic56_cfg_enum =
- SOC_ENUM_SINGLE(SN95031_DMICMUX, 2, 2, sn95031_dmic_cfg_text);
+static SOC_ENUM_SINGLE_DECL(sn95031_dmic12_cfg_enum,
+ SN95031_DMICMUX, 0, sn95031_dmic_cfg_text);
+static SOC_ENUM_SINGLE_DECL(sn95031_dmic34_cfg_enum,
+ SN95031_DMICMUX, 1, sn95031_dmic_cfg_text);
+static SOC_ENUM_SINGLE_DECL(sn95031_dmic56_cfg_enum,
+ SN95031_DMICMUX, 2, sn95031_dmic_cfg_text);
static const struct snd_kcontrol_new sn95031_snd_controls[] = {
SOC_ENUM("Mic1Mode Capture Route", sn95031_micmode1_enum),
@@ -825,8 +825,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
{
pr_debug("codec_probe called\n");
- snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
-
/* PCM interface config
* This sets the pcm rx slot conguration to max 6 slots
* for max 4 dais (2 stereo and 2 mono)
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c
index cc8debce752..56adb3e2def 100644
--- a/sound/soc/codecs/ssm2518.c
+++ b/sound/soc/codecs/ssm2518.c
@@ -169,19 +169,19 @@ static const char * const ssm2518_drc_hold_time_text[] = {
"682.24 ms", "1364 ms",
};
-static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum,
+static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum,
SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text);
-static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum,
+static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum,
SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text);
-static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum,
+static SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum,
SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text);
-static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum,
+static SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum,
SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text);
-static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum,
+static SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum,
SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text);
-static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum,
+static SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum,
SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text);
-static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum,
+static SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum,
SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text);
static const struct snd_kcontrol_new ssm2518_snd_controls[] = {
@@ -648,16 +648,6 @@ static struct snd_soc_dai_driver ssm2518_dai = {
static int ssm2518_probe(struct snd_soc_codec *codec)
{
- struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- codec->control_data = ssm2518->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
return ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
diff --git a/sound/soc/codecs/ssm2602-i2c.c b/sound/soc/codecs/ssm2602-i2c.c
new file mode 100644
index 00000000000..abd63d53717
--- /dev/null
+++ b/sound/soc/codecs/ssm2602-i2c.c
@@ -0,0 +1,57 @@
+/*
+ * SSM2602/SSM2603/SSM2604 I2C audio driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+#include <sound/soc.h>
+
+#include "ssm2602.h"
+
+/*
+ * ssm2602 2 wire address is determined by GPIO5
+ * state during powerup.
+ * low = 0x1a
+ * high = 0x1b
+ */
+static int ssm2602_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return ssm2602_probe(&client->dev, id->driver_data,
+ devm_regmap_init_i2c(client, &ssm2602_regmap_config));
+}
+
+static int ssm2602_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static const struct i2c_device_id ssm2602_i2c_id[] = {
+ { "ssm2602", SSM2602 },
+ { "ssm2603", SSM2602 },
+ { "ssm2604", SSM2604 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
+
+static struct i2c_driver ssm2602_i2c_driver = {
+ .driver = {
+ .name = "ssm2602",
+ .owner = THIS_MODULE,
+ },
+ .probe = ssm2602_i2c_probe,
+ .remove = ssm2602_i2c_remove,
+ .id_table = ssm2602_i2c_id,
+};
+module_i2c_driver(ssm2602_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 I2C driver");
+MODULE_AUTHOR("Cliff Cai");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ssm2602-spi.c b/sound/soc/codecs/ssm2602-spi.c
new file mode 100644
index 00000000000..2bf55e24a7b
--- /dev/null
+++ b/sound/soc/codecs/ssm2602-spi.c
@@ -0,0 +1,41 @@
+/*
+ * SSM2602 SPI audio driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+
+#include <sound/soc.h>
+
+#include "ssm2602.h"
+
+static int ssm2602_spi_probe(struct spi_device *spi)
+{
+ return ssm2602_probe(&spi->dev, SSM2602,
+ devm_regmap_init_spi(spi, &ssm2602_regmap_config));
+}
+
+static int ssm2602_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ return 0;
+}
+
+static struct spi_driver ssm2602_spi_driver = {
+ .driver = {
+ .name = "ssm2602",
+ .owner = THIS_MODULE,
+ },
+ .probe = ssm2602_spi_probe,
+ .remove = ssm2602_spi_remove,
+};
+module_spi_driver(ssm2602_spi_driver);
+
+MODULE_DESCRIPTION("ASoC SSM2602 SPI driver");
+MODULE_AUTHOR("Cliff Cai");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index af76bbd1b24..97b0454eb34 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -27,32 +27,20 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/i2c.h>
-#include <linux/spi/spi.h>
#include <linux/regmap.h>
#include <linux/slab.h>
-#include <sound/core.h>
+
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
-#include <sound/initval.h>
#include <sound/tlv.h>
#include "ssm2602.h"
-enum ssm2602_type {
- SSM2602,
- SSM2604,
-};
-
/* codec private data */
struct ssm2602_priv {
unsigned int sysclk;
- struct snd_pcm_hw_constraint_list *sysclk_constraints;
+ const struct snd_pcm_hw_constraint_list *sysclk_constraints;
struct regmap *regmap;
@@ -75,15 +63,16 @@ static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = {
/*Appending several "None"s just for OSS mixer use*/
static const char *ssm2602_input_select[] = {
- "Line", "Mic", "None", "None", "None",
- "None", "None", "None",
+ "Line", "Mic",
};
static const char *ssm2602_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
static const struct soc_enum ssm2602_enum[] = {
- SOC_ENUM_SINGLE(SSM2602_APANA, 2, 2, ssm2602_input_select),
- SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, 4, ssm2602_deemph),
+ SOC_ENUM_SINGLE(SSM2602_APANA, 2, ARRAY_SIZE(ssm2602_input_select),
+ ssm2602_input_select),
+ SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, ARRAY_SIZE(ssm2602_deemph),
+ ssm2602_deemph),
};
static const unsigned int ssm260x_outmix_tlv[] = {
@@ -197,7 +186,7 @@ static const unsigned int ssm2602_rates_12288000[] = {
8000, 16000, 32000, 48000, 96000,
};
-static struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = {
+static const struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = {
.list = ssm2602_rates_12288000,
.count = ARRAY_SIZE(ssm2602_rates_12288000),
};
@@ -206,7 +195,7 @@ static const unsigned int ssm2602_rates_11289600[] = {
8000, 44100, 88200,
};
-static struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = {
+static const struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = {
.list = ssm2602_rates_11289600,
.count = ARRAY_SIZE(ssm2602_rates_11289600),
};
@@ -529,7 +518,7 @@ static int ssm2602_resume(struct snd_soc_codec *codec)
return 0;
}
-static int ssm2602_probe(struct snd_soc_codec *codec)
+static int ssm2602_codec_probe(struct snd_soc_codec *codec)
{
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
@@ -554,7 +543,7 @@ static int ssm2602_probe(struct snd_soc_codec *codec)
ARRAY_SIZE(ssm2602_routes));
}
-static int ssm2604_probe(struct snd_soc_codec *codec)
+static int ssm2604_codec_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret;
@@ -568,18 +557,11 @@ static int ssm2604_probe(struct snd_soc_codec *codec)
ARRAY_SIZE(ssm2604_routes));
}
-static int ssm260x_probe(struct snd_soc_codec *codec)
+static int ssm260x_codec_probe(struct snd_soc_codec *codec)
{
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
int ret;
- codec->control_data = ssm2602->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = regmap_write(ssm2602->regmap, SSM2602_RESET, 0);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
@@ -597,10 +579,10 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
switch (ssm2602->type) {
case SSM2602:
- ret = ssm2602_probe(codec);
+ ret = ssm2602_codec_probe(codec);
break;
case SSM2604:
- ret = ssm2604_probe(codec);
+ ret = ssm2604_codec_probe(codec);
break;
}
@@ -620,7 +602,7 @@ static int ssm2602_remove(struct snd_soc_codec *codec)
}
static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
- .probe = ssm260x_probe,
+ .probe = ssm260x_codec_probe,
.remove = ssm2602_remove,
.suspend = ssm2602_suspend,
.resume = ssm2602_resume,
@@ -639,7 +621,7 @@ static bool ssm2602_register_volatile(struct device *dev, unsigned int reg)
return reg == SSM2602_RESET;
}
-static const struct regmap_config ssm2602_regmap_config = {
+const struct regmap_config ssm2602_regmap_config = {
.val_bits = 9,
.reg_bits = 7,
@@ -650,134 +632,28 @@ static const struct regmap_config ssm2602_regmap_config = {
.reg_defaults_raw = ssm2602_reg,
.num_reg_defaults_raw = ARRAY_SIZE(ssm2602_reg),
};
+EXPORT_SYMBOL_GPL(ssm2602_regmap_config);
-#if defined(CONFIG_SPI_MASTER)
-static int ssm2602_spi_probe(struct spi_device *spi)
+int ssm2602_probe(struct device *dev, enum ssm2602_type type,
+ struct regmap *regmap)
{
struct ssm2602_priv *ssm2602;
- int ret;
-
- ssm2602 = devm_kzalloc(&spi->dev, sizeof(struct ssm2602_priv),
- GFP_KERNEL);
- if (ssm2602 == NULL)
- return -ENOMEM;
-
- spi_set_drvdata(spi, ssm2602);
- ssm2602->type = SSM2602;
- ssm2602->regmap = devm_regmap_init_spi(spi, &ssm2602_regmap_config);
- if (IS_ERR(ssm2602->regmap))
- return PTR_ERR(ssm2602->regmap);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
- ret = snd_soc_register_codec(&spi->dev,
- &soc_codec_dev_ssm2602, &ssm2602_dai, 1);
- return ret;
-}
-
-static int ssm2602_spi_remove(struct spi_device *spi)
-{
- snd_soc_unregister_codec(&spi->dev);
- return 0;
-}
-
-static struct spi_driver ssm2602_spi_driver = {
- .driver = {
- .name = "ssm2602",
- .owner = THIS_MODULE,
- },
- .probe = ssm2602_spi_probe,
- .remove = ssm2602_spi_remove,
-};
-#endif
-
-#if IS_ENABLED(CONFIG_I2C)
-/*
- * ssm2602 2 wire address is determined by GPIO5
- * state during powerup.
- * low = 0x1a
- * high = 0x1b
- */
-static int ssm2602_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
-{
- struct ssm2602_priv *ssm2602;
- int ret;
-
- ssm2602 = devm_kzalloc(&i2c->dev, sizeof(struct ssm2602_priv),
- GFP_KERNEL);
+ ssm2602 = devm_kzalloc(dev, sizeof(*ssm2602), GFP_KERNEL);
if (ssm2602 == NULL)
return -ENOMEM;
- i2c_set_clientdata(i2c, ssm2602);
- ssm2602->type = id->driver_data;
-
- ssm2602->regmap = devm_regmap_init_i2c(i2c, &ssm2602_regmap_config);
- if (IS_ERR(ssm2602->regmap))
- return PTR_ERR(ssm2602->regmap);
-
- ret = snd_soc_register_codec(&i2c->dev,
- &soc_codec_dev_ssm2602, &ssm2602_dai, 1);
- return ret;
-}
-
-static int ssm2602_i2c_remove(struct i2c_client *client)
-{
- snd_soc_unregister_codec(&client->dev);
- return 0;
-}
-
-static const struct i2c_device_id ssm2602_i2c_id[] = {
- { "ssm2602", SSM2602 },
- { "ssm2603", SSM2602 },
- { "ssm2604", SSM2604 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
-
-/* corgi i2c codec control layer */
-static struct i2c_driver ssm2602_i2c_driver = {
- .driver = {
- .name = "ssm2602",
- .owner = THIS_MODULE,
- },
- .probe = ssm2602_i2c_probe,
- .remove = ssm2602_i2c_remove,
- .id_table = ssm2602_i2c_id,
-};
-#endif
-
-
-static int __init ssm2602_modinit(void)
-{
- int ret = 0;
-
-#if defined(CONFIG_SPI_MASTER)
- ret = spi_register_driver(&ssm2602_spi_driver);
- if (ret)
- return ret;
-#endif
-
-#if IS_ENABLED(CONFIG_I2C)
- ret = i2c_add_driver(&ssm2602_i2c_driver);
- if (ret)
- return ret;
-#endif
-
- return ret;
-}
-module_init(ssm2602_modinit);
-
-static void __exit ssm2602_exit(void)
-{
-#if defined(CONFIG_SPI_MASTER)
- spi_unregister_driver(&ssm2602_spi_driver);
-#endif
+ dev_set_drvdata(dev, ssm2602);
+ ssm2602->type = SSM2602;
+ ssm2602->regmap = regmap;
-#if IS_ENABLED(CONFIG_I2C)
- i2c_del_driver(&ssm2602_i2c_driver);
-#endif
+ return snd_soc_register_codec(dev, &soc_codec_dev_ssm2602,
+ &ssm2602_dai, 1);
}
-module_exit(ssm2602_exit);
+EXPORT_SYMBOL_GPL(ssm2602_probe);
MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 driver");
MODULE_AUTHOR("Cliff Cai");
diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h
index fbd07d7b73c..74753884768 100644
--- a/sound/soc/codecs/ssm2602.h
+++ b/sound/soc/codecs/ssm2602.h
@@ -28,6 +28,20 @@
#ifndef _SSM2602_H
#define _SSM2602_H
+#include <linux/regmap.h>
+
+struct device;
+
+enum ssm2602_type {
+ SSM2602,
+ SSM2604,
+};
+
+extern const struct regmap_config ssm2602_regmap_config;
+
+int ssm2602_probe(struct device *dev, enum ssm2602_type type,
+ struct regmap *regmap);
+
/* SSM2602 Codec Register definitions */
#define SSM2602_LINVOL 0x00
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index 06edb396e73..0579d187135 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -187,42 +187,42 @@ static const unsigned int sta32x_limiter_drc_release_tlv[] = {
13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
};
-static const struct soc_enum sta32x_drc_ac_enum =
- SOC_ENUM_SINGLE(STA32X_CONFD, STA32X_CONFD_DRC_SHIFT,
- 2, sta32x_drc_ac);
-static const struct soc_enum sta32x_auto_eq_enum =
- SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT,
- 3, sta32x_auto_eq_mode);
-static const struct soc_enum sta32x_auto_gc_enum =
- SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT,
- 4, sta32x_auto_gc_mode);
-static const struct soc_enum sta32x_auto_xo_enum =
- SOC_ENUM_SINGLE(STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT,
- 16, sta32x_auto_xo_mode);
-static const struct soc_enum sta32x_preset_eq_enum =
- SOC_ENUM_SINGLE(STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT,
- 32, sta32x_preset_eq_mode);
-static const struct soc_enum sta32x_limiter_ch1_enum =
- SOC_ENUM_SINGLE(STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT,
- 3, sta32x_limiter_select);
-static const struct soc_enum sta32x_limiter_ch2_enum =
- SOC_ENUM_SINGLE(STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT,
- 3, sta32x_limiter_select);
-static const struct soc_enum sta32x_limiter_ch3_enum =
- SOC_ENUM_SINGLE(STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT,
- 3, sta32x_limiter_select);
-static const struct soc_enum sta32x_limiter1_attack_rate_enum =
- SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxA_SHIFT,
- 16, sta32x_limiter_attack_rate);
-static const struct soc_enum sta32x_limiter2_attack_rate_enum =
- SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxA_SHIFT,
- 16, sta32x_limiter_attack_rate);
-static const struct soc_enum sta32x_limiter1_release_rate_enum =
- SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxR_SHIFT,
- 16, sta32x_limiter_release_rate);
-static const struct soc_enum sta32x_limiter2_release_rate_enum =
- SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxR_SHIFT,
- 16, sta32x_limiter_release_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_drc_ac_enum,
+ STA32X_CONFD, STA32X_CONFD_DRC_SHIFT,
+ sta32x_drc_ac);
+static SOC_ENUM_SINGLE_DECL(sta32x_auto_eq_enum,
+ STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT,
+ sta32x_auto_eq_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_auto_gc_enum,
+ STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT,
+ sta32x_auto_gc_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_auto_xo_enum,
+ STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT,
+ sta32x_auto_xo_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_preset_eq_enum,
+ STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT,
+ sta32x_preset_eq_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch1_enum,
+ STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT,
+ sta32x_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch2_enum,
+ STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT,
+ sta32x_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch3_enum,
+ STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT,
+ sta32x_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_attack_rate_enum,
+ STA32X_L1AR, STA32X_LxA_SHIFT,
+ sta32x_limiter_attack_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_attack_rate_enum,
+ STA32X_L2AR, STA32X_LxA_SHIFT,
+ sta32x_limiter_attack_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_release_rate_enum,
+ STA32X_L1AR, STA32X_LxR_SHIFT,
+ sta32x_limiter_release_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_release_rate_enum,
+ STA32X_L2AR, STA32X_LxR_SHIFT,
+ sta32x_limiter_release_rate);
/* byte array controls for setting biquad, mixer, scaling coefficients;
* for biquads all five coefficients need to be set in one go,
@@ -243,7 +243,7 @@ static int sta32x_coefficient_info(struct snd_kcontrol *kcontrol,
static int sta32x_coefficient_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
int numcoef = kcontrol->private_value >> 16;
int index = kcontrol->private_value & 0xffff;
unsigned int cfud;
@@ -272,7 +272,7 @@ static int sta32x_coefficient_get(struct snd_kcontrol *kcontrol,
static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
int numcoef = kcontrol->private_value >> 16;
int index = kcontrol->private_value & 0xffff;
@@ -331,7 +331,7 @@ static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
static int sta32x_cache_sync(struct snd_soc_codec *codec)
{
- struct sta32x_priv *sta32x = codec->control_data;
+ struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
unsigned int mute;
int rc;
@@ -434,7 +434,7 @@ SOC_SINGLE_TLV("Treble Tone Control", STA32X_TONE, STA32X_TONE_TTC_SHIFT, 15, 0,
SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum),
SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum),
SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
-SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
+SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter2_release_rate_enum),
/* depending on mode, the attack/release thresholds have
* two different enum definitions; provide both
@@ -872,16 +872,6 @@ static int sta32x_probe(struct snd_soc_codec *codec)
return ret;
}
- /* Tell ASoC what kind of I/O to use to read the registers. ASoC will
- * then do the I2C transactions itself.
- */
- codec->control_data = sta32x->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret);
- goto err;
- }
-
/* Chip documentation explicitly requires that the reset values
* of reserved register bits are left untouched.
* Write the register default value to cache for reserved registers,
@@ -946,10 +936,6 @@ static int sta32x_probe(struct snd_soc_codec *codec)
regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
return 0;
-
-err:
- regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
- return ret;
}
static int sta32x_remove(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c
new file mode 100644
index 00000000000..cc97dd52aa9
--- /dev/null
+++ b/sound/soc/codecs/sta350.c
@@ -0,0 +1,1311 @@
+/*
+ * Codec driver for ST STA350 2.1-channel high-efficiency digital audio system
+ *
+ * Copyright: 2014 Raumfeld GmbH
+ * Author: Sven Brandau <info@brandau.biz>
+ *
+ * based on code from:
+ * Raumfeld GmbH
+ * Johannes Stezenbach <js@sig21.net>
+ * Wolfson Microelectronics PLC.
+ * Mark Brown <broonie@opensource.wolfsonmicro.com>
+ * Freescale Semiconductor, Inc.
+ * Timur Tabi <timur@freescale.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; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s:%d: " fmt, __func__, __LINE__
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio/consumer.h>
+#include <linux/slab.h>
+#include <sound/core.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/sta350.h>
+#include "sta350.h"
+
+#define STA350_RATES (SNDRV_PCM_RATE_32000 | \
+ SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000 | \
+ SNDRV_PCM_RATE_88200 | \
+ SNDRV_PCM_RATE_96000 | \
+ SNDRV_PCM_RATE_176400 | \
+ SNDRV_PCM_RATE_192000)
+
+#define STA350_FORMATS \
+ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
+ SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
+ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \
+ SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
+
+/* Power-up register defaults */
+static const struct reg_default sta350_regs[] = {
+ { 0x0, 0x63 },
+ { 0x1, 0x80 },
+ { 0x2, 0xdf },
+ { 0x3, 0x40 },
+ { 0x4, 0xc2 },
+ { 0x5, 0x5c },
+ { 0x6, 0x00 },
+ { 0x7, 0xff },
+ { 0x8, 0x60 },
+ { 0x9, 0x60 },
+ { 0xa, 0x60 },
+ { 0xb, 0x00 },
+ { 0xc, 0x00 },
+ { 0xd, 0x00 },
+ { 0xe, 0x00 },
+ { 0xf, 0x40 },
+ { 0x10, 0x80 },
+ { 0x11, 0x77 },
+ { 0x12, 0x6a },
+ { 0x13, 0x69 },
+ { 0x14, 0x6a },
+ { 0x15, 0x69 },
+ { 0x16, 0x00 },
+ { 0x17, 0x00 },
+ { 0x18, 0x00 },
+ { 0x19, 0x00 },
+ { 0x1a, 0x00 },
+ { 0x1b, 0x00 },
+ { 0x1c, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1e, 0x00 },
+ { 0x1f, 0x00 },
+ { 0x20, 0x00 },
+ { 0x21, 0x00 },
+ { 0x22, 0x00 },
+ { 0x23, 0x00 },
+ { 0x24, 0x00 },
+ { 0x25, 0x00 },
+ { 0x26, 0x00 },
+ { 0x27, 0x2a },
+ { 0x28, 0xc0 },
+ { 0x29, 0xf3 },
+ { 0x2a, 0x33 },
+ { 0x2b, 0x00 },
+ { 0x2c, 0x0c },
+ { 0x31, 0x00 },
+ { 0x36, 0x00 },
+ { 0x37, 0x00 },
+ { 0x38, 0x00 },
+ { 0x39, 0x01 },
+ { 0x3a, 0xee },
+ { 0x3b, 0xff },
+ { 0x3c, 0x7e },
+ { 0x3d, 0xc0 },
+ { 0x3e, 0x26 },
+ { 0x3f, 0x00 },
+ { 0x48, 0x00 },
+ { 0x49, 0x00 },
+ { 0x4a, 0x00 },
+ { 0x4b, 0x04 },
+ { 0x4c, 0x00 },
+};
+
+static const struct regmap_range sta350_write_regs_range[] = {
+ regmap_reg_range(STA350_CONFA, STA350_AUTO2),
+ regmap_reg_range(STA350_C1CFG, STA350_FDRC2),
+ regmap_reg_range(STA350_EQCFG, STA350_EVOLRES),
+ regmap_reg_range(STA350_NSHAPE, STA350_MISC2),
+};
+
+static const struct regmap_range sta350_read_regs_range[] = {
+ regmap_reg_range(STA350_CONFA, STA350_AUTO2),
+ regmap_reg_range(STA350_C1CFG, STA350_STATUS),
+ regmap_reg_range(STA350_EQCFG, STA350_EVOLRES),
+ regmap_reg_range(STA350_NSHAPE, STA350_MISC2),
+};
+
+static const struct regmap_range sta350_volatile_regs_range[] = {
+ regmap_reg_range(STA350_CFADDR2, STA350_CFUD),
+ regmap_reg_range(STA350_STATUS, STA350_STATUS),
+};
+
+static const struct regmap_access_table sta350_write_regs = {
+ .yes_ranges = sta350_write_regs_range,
+ .n_yes_ranges = ARRAY_SIZE(sta350_write_regs_range),
+};
+
+static const struct regmap_access_table sta350_read_regs = {
+ .yes_ranges = sta350_read_regs_range,
+ .n_yes_ranges = ARRAY_SIZE(sta350_read_regs_range),
+};
+
+static const struct regmap_access_table sta350_volatile_regs = {
+ .yes_ranges = sta350_volatile_regs_range,
+ .n_yes_ranges = ARRAY_SIZE(sta350_volatile_regs_range),
+};
+
+/* regulator power supply names */
+static const char * const sta350_supply_names[] = {
+ "vdd-dig", /* digital supply, 3.3V */
+ "vdd-pll", /* pll supply, 3.3V */
+ "vcc" /* power amp supply, 5V - 26V */
+};
+
+/* codec private data */
+struct sta350_priv {
+ struct regmap *regmap;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(sta350_supply_names)];
+ struct sta350_platform_data *pdata;
+
+ unsigned int mclk;
+ unsigned int format;
+
+ u32 coef_shadow[STA350_COEF_COUNT];
+ int shutdown;
+
+ struct gpio_desc *gpiod_nreset;
+ struct gpio_desc *gpiod_power_down;
+
+ struct mutex coeff_lock;
+};
+
+static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12750, 50, 1);
+static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1);
+static const DECLARE_TLV_DB_SCALE(tone_tlv, -1200, 200, 0);
+
+static const char * const sta350_drc_ac[] = {
+ "Anti-Clipping", "Dynamic Range Compression"
+};
+static const char * const sta350_auto_gc_mode[] = {
+ "User", "AC no clipping", "AC limited clipping (10%)",
+ "DRC nighttime listening mode"
+};
+static const char * const sta350_auto_xo_mode[] = {
+ "User", "80Hz", "100Hz", "120Hz", "140Hz", "160Hz", "180Hz",
+ "200Hz", "220Hz", "240Hz", "260Hz", "280Hz", "300Hz", "320Hz",
+ "340Hz", "360Hz"
+};
+static const char * const sta350_binary_output[] = {
+ "FFX 3-state output - normal operation", "Binary output"
+};
+static const char * const sta350_limiter_select[] = {
+ "Limiter Disabled", "Limiter #1", "Limiter #2"
+};
+static const char * const sta350_limiter_attack_rate[] = {
+ "3.1584", "2.7072", "2.2560", "1.8048", "1.3536", "0.9024",
+ "0.4512", "0.2256", "0.1504", "0.1123", "0.0902", "0.0752",
+ "0.0645", "0.0564", "0.0501", "0.0451"
+};
+static const char * const sta350_limiter_release_rate[] = {
+ "0.5116", "0.1370", "0.0744", "0.0499", "0.0360", "0.0299",
+ "0.0264", "0.0208", "0.0198", "0.0172", "0.0147", "0.0137",
+ "0.0134", "0.0117", "0.0110", "0.0104"
+};
+static const char * const sta350_noise_shaper_type[] = {
+ "Third order", "Fourth order"
+};
+
+static DECLARE_TLV_DB_RANGE(sta350_limiter_ac_attack_tlv,
+ 0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0),
+ 8, 16, TLV_DB_SCALE_ITEM(300, 100, 0),
+);
+
+static DECLARE_TLV_DB_RANGE(sta350_limiter_ac_release_tlv,
+ 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
+ 1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0),
+ 3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0),
+ 8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0),
+);
+
+static DECLARE_TLV_DB_RANGE(sta350_limiter_drc_attack_tlv,
+ 0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0),
+ 8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0),
+ 14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0),
+);
+
+static DECLARE_TLV_DB_RANGE(sta350_limiter_drc_release_tlv,
+ 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
+ 1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0),
+ 3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0),
+ 5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0),
+ 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
+);
+
+static SOC_ENUM_SINGLE_DECL(sta350_drc_ac_enum,
+ STA350_CONFD, STA350_CONFD_DRC_SHIFT,
+ sta350_drc_ac);
+static SOC_ENUM_SINGLE_DECL(sta350_noise_shaper_enum,
+ STA350_CONFE, STA350_CONFE_NSBW_SHIFT,
+ sta350_noise_shaper_type);
+static SOC_ENUM_SINGLE_DECL(sta350_auto_gc_enum,
+ STA350_AUTO1, STA350_AUTO1_AMGC_SHIFT,
+ sta350_auto_gc_mode);
+static SOC_ENUM_SINGLE_DECL(sta350_auto_xo_enum,
+ STA350_AUTO2, STA350_AUTO2_XO_SHIFT,
+ sta350_auto_xo_mode);
+static SOC_ENUM_SINGLE_DECL(sta350_binary_output_ch1_enum,
+ STA350_C1CFG, STA350_CxCFG_BO_SHIFT,
+ sta350_binary_output);
+static SOC_ENUM_SINGLE_DECL(sta350_binary_output_ch2_enum,
+ STA350_C2CFG, STA350_CxCFG_BO_SHIFT,
+ sta350_binary_output);
+static SOC_ENUM_SINGLE_DECL(sta350_binary_output_ch3_enum,
+ STA350_C3CFG, STA350_CxCFG_BO_SHIFT,
+ sta350_binary_output);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter_ch1_enum,
+ STA350_C1CFG, STA350_CxCFG_LS_SHIFT,
+ sta350_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter_ch2_enum,
+ STA350_C2CFG, STA350_CxCFG_LS_SHIFT,
+ sta350_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter_ch3_enum,
+ STA350_C3CFG, STA350_CxCFG_LS_SHIFT,
+ sta350_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter1_attack_rate_enum,
+ STA350_L1AR, STA350_LxA_SHIFT,
+ sta350_limiter_attack_rate);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter2_attack_rate_enum,
+ STA350_L2AR, STA350_LxA_SHIFT,
+ sta350_limiter_attack_rate);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter1_release_rate_enum,
+ STA350_L1AR, STA350_LxR_SHIFT,
+ sta350_limiter_release_rate);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter2_release_rate_enum,
+ STA350_L2AR, STA350_LxR_SHIFT,
+ sta350_limiter_release_rate);
+
+/*
+ * byte array controls for setting biquad, mixer, scaling coefficients;
+ * for biquads all five coefficients need to be set in one go,
+ * mixer and pre/postscale coefs can be set individually;
+ * each coef is 24bit, the bytes are ordered in the same way
+ * as given in the STA350 data sheet (big endian; b1, b2, a1, a2, b0)
+ */
+
+static int sta350_coefficient_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ int numcoef = kcontrol->private_value >> 16;
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ uinfo->count = 3 * numcoef;
+ return 0;
+}
+
+static int sta350_coefficient_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+ int numcoef = kcontrol->private_value >> 16;
+ int index = kcontrol->private_value & 0xffff;
+ unsigned int cfud, val;
+ int i, ret = 0;
+
+ mutex_lock(&sta350->coeff_lock);
+
+ /* preserve reserved bits in STA350_CFUD */
+ regmap_read(sta350->regmap, STA350_CFUD, &cfud);
+ cfud &= 0xf0;
+ /*
+ * chip documentation does not say if the bits are self clearing,
+ * so do it explicitly
+ */
+ regmap_write(sta350->regmap, STA350_CFUD, cfud);
+
+ regmap_write(sta350->regmap, STA350_CFADDR2, index);
+ if (numcoef == 1) {
+ regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x04);
+ } else if (numcoef == 5) {
+ regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x08);
+ } else {
+ ret = -EINVAL;
+ goto exit_unlock;
+ }
+
+ for (i = 0; i < 3 * numcoef; i++) {
+ regmap_read(sta350->regmap, STA350_B1CF1 + i, &val);
+ ucontrol->value.bytes.data[i] = val;
+ }
+
+exit_unlock:
+ mutex_unlock(&sta350->coeff_lock);
+
+ return ret;
+}
+
+static int sta350_coefficient_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+ int numcoef = kcontrol->private_value >> 16;
+ int index = kcontrol->private_value & 0xffff;
+ unsigned int cfud;
+ int i;
+
+ /* preserve reserved bits in STA350_CFUD */
+ regmap_read(sta350->regmap, STA350_CFUD, &cfud);
+ cfud &= 0xf0;
+ /*
+ * chip documentation does not say if the bits are self clearing,
+ * so do it explicitly
+ */
+ regmap_write(sta350->regmap, STA350_CFUD, cfud);
+
+ regmap_write(sta350->regmap, STA350_CFADDR2, index);
+ for (i = 0; i < numcoef && (index + i < STA350_COEF_COUNT); i++)
+ sta350->coef_shadow[index + i] =
+ (ucontrol->value.bytes.data[3 * i] << 16)
+ | (ucontrol->value.bytes.data[3 * i + 1] << 8)
+ | (ucontrol->value.bytes.data[3 * i + 2]);
+ for (i = 0; i < 3 * numcoef; i++)
+ regmap_write(sta350->regmap, STA350_B1CF1 + i,
+ ucontrol->value.bytes.data[i]);
+ if (numcoef == 1)
+ regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x01);
+ else if (numcoef == 5)
+ regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x02);
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int sta350_sync_coef_shadow(struct snd_soc_codec *codec)
+{
+ struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+ unsigned int cfud;
+ int i;
+
+ /* preserve reserved bits in STA350_CFUD */
+ regmap_read(sta350->regmap, STA350_CFUD, &cfud);
+ cfud &= 0xf0;
+
+ for (i = 0; i < STA350_COEF_COUNT; i++) {
+ regmap_write(sta350->regmap, STA350_CFADDR2, i);
+ regmap_write(sta350->regmap, STA350_B1CF1,
+ (sta350->coef_shadow[i] >> 16) & 0xff);
+ regmap_write(sta350->regmap, STA350_B1CF2,
+ (sta350->coef_shadow[i] >> 8) & 0xff);
+ regmap_write(sta350->regmap, STA350_B1CF3,
+ (sta350->coef_shadow[i]) & 0xff);
+ /*
+ * chip documentation does not say if the bits are
+ * self-clearing, so do it explicitly
+ */
+ regmap_write(sta350->regmap, STA350_CFUD, cfud);
+ regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x01);
+ }
+ return 0;
+}
+
+static int sta350_cache_sync(struct snd_soc_codec *codec)
+{
+ struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+ unsigned int mute;
+ int rc;
+
+ /* mute during register sync */
+ regmap_read(sta350->regmap, STA350_CFUD, &mute);
+ regmap_write(sta350->regmap, STA350_MMUTE, mute | STA350_MMUTE_MMUTE);
+ sta350_sync_coef_shadow(codec);
+ rc = regcache_sync(sta350->regmap);
+ regmap_write(sta350->regmap, STA350_MMUTE, mute);
+ return rc;
+}
+
+#define SINGLE_COEF(xname, index) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = sta350_coefficient_info, \
+ .get = sta350_coefficient_get,\
+ .put = sta350_coefficient_put, \
+ .private_value = index | (1 << 16) }
+
+#define BIQUAD_COEFS(xname, index) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = sta350_coefficient_info, \
+ .get = sta350_coefficient_get,\
+ .put = sta350_coefficient_put, \
+ .private_value = index | (5 << 16) }
+
+static const struct snd_kcontrol_new sta350_snd_controls[] = {
+SOC_SINGLE_TLV("Master Volume", STA350_MVOL, 0, 0xff, 1, mvol_tlv),
+/* VOL */
+SOC_SINGLE_TLV("Ch1 Volume", STA350_C1VOL, 0, 0xff, 1, chvol_tlv),
+SOC_SINGLE_TLV("Ch2 Volume", STA350_C2VOL, 0, 0xff, 1, chvol_tlv),
+SOC_SINGLE_TLV("Ch3 Volume", STA350_C3VOL, 0, 0xff, 1, chvol_tlv),
+/* CONFD */
+SOC_SINGLE("High Pass Filter Bypass Switch",
+ STA350_CONFD, STA350_CONFD_HPB_SHIFT, 1, 1),
+SOC_SINGLE("De-emphasis Filter Switch",
+ STA350_CONFD, STA350_CONFD_DEMP_SHIFT, 1, 0),
+SOC_SINGLE("DSP Bypass Switch",
+ STA350_CONFD, STA350_CONFD_DSPB_SHIFT, 1, 0),
+SOC_SINGLE("Post-scale Link Switch",
+ STA350_CONFD, STA350_CONFD_PSL_SHIFT, 1, 0),
+SOC_SINGLE("Biquad Coefficient Link Switch",
+ STA350_CONFD, STA350_CONFD_BQL_SHIFT, 1, 0),
+SOC_ENUM("Compressor/Limiter Switch", sta350_drc_ac_enum),
+SOC_ENUM("Noise Shaper Bandwidth", sta350_noise_shaper_enum),
+SOC_SINGLE("Zero-detect Mute Enable Switch",
+ STA350_CONFD, STA350_CONFD_ZDE_SHIFT, 1, 0),
+SOC_SINGLE("Submix Mode Switch",
+ STA350_CONFD, STA350_CONFD_SME_SHIFT, 1, 0),
+/* CONFE */
+SOC_SINGLE("Zero Cross Switch", STA350_CONFE, STA350_CONFE_ZCE_SHIFT, 1, 0),
+SOC_SINGLE("Soft Ramp Switch", STA350_CONFE, STA350_CONFE_SVE_SHIFT, 1, 0),
+/* MUTE */
+SOC_SINGLE("Master Switch", STA350_MMUTE, STA350_MMUTE_MMUTE_SHIFT, 1, 1),
+SOC_SINGLE("Ch1 Switch", STA350_MMUTE, STA350_MMUTE_C1M_SHIFT, 1, 1),
+SOC_SINGLE("Ch2 Switch", STA350_MMUTE, STA350_MMUTE_C2M_SHIFT, 1, 1),
+SOC_SINGLE("Ch3 Switch", STA350_MMUTE, STA350_MMUTE_C3M_SHIFT, 1, 1),
+/* AUTOx */
+SOC_ENUM("Automode GC", sta350_auto_gc_enum),
+SOC_ENUM("Automode XO", sta350_auto_xo_enum),
+/* CxCFG */
+SOC_SINGLE("Ch1 Tone Control Bypass Switch",
+ STA350_C1CFG, STA350_CxCFG_TCB_SHIFT, 1, 0),
+SOC_SINGLE("Ch2 Tone Control Bypass Switch",
+ STA350_C2CFG, STA350_CxCFG_TCB_SHIFT, 1, 0),
+SOC_SINGLE("Ch1 EQ Bypass Switch",
+ STA350_C1CFG, STA350_CxCFG_EQBP_SHIFT, 1, 0),
+SOC_SINGLE("Ch2 EQ Bypass Switch",
+ STA350_C2CFG, STA350_CxCFG_EQBP_SHIFT, 1, 0),
+SOC_SINGLE("Ch1 Master Volume Bypass Switch",
+ STA350_C1CFG, STA350_CxCFG_VBP_SHIFT, 1, 0),
+SOC_SINGLE("Ch2 Master Volume Bypass Switch",
+ STA350_C1CFG, STA350_CxCFG_VBP_SHIFT, 1, 0),
+SOC_SINGLE("Ch3 Master Volume Bypass Switch",
+ STA350_C1CFG, STA350_CxCFG_VBP_SHIFT, 1, 0),
+SOC_ENUM("Ch1 Binary Output Select", sta350_binary_output_ch1_enum),
+SOC_ENUM("Ch2 Binary Output Select", sta350_binary_output_ch2_enum),
+SOC_ENUM("Ch3 Binary Output Select", sta350_binary_output_ch3_enum),
+SOC_ENUM("Ch1 Limiter Select", sta350_limiter_ch1_enum),
+SOC_ENUM("Ch2 Limiter Select", sta350_limiter_ch2_enum),
+SOC_ENUM("Ch3 Limiter Select", sta350_limiter_ch3_enum),
+/* TONE */
+SOC_SINGLE_RANGE_TLV("Bass Tone Control Volume",
+ STA350_TONE, STA350_TONE_BTC_SHIFT, 1, 13, 0, tone_tlv),
+SOC_SINGLE_RANGE_TLV("Treble Tone Control Volume",
+ STA350_TONE, STA350_TONE_TTC_SHIFT, 1, 13, 0, tone_tlv),
+SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta350_limiter1_attack_rate_enum),
+SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta350_limiter2_attack_rate_enum),
+SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta350_limiter1_release_rate_enum),
+SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta350_limiter2_release_rate_enum),
+
+/*
+ * depending on mode, the attack/release thresholds have
+ * two different enum definitions; provide both
+ */
+SOC_SINGLE_TLV("Limiter1 Attack Threshold (AC Mode)",
+ STA350_L1ATRT, STA350_LxA_SHIFT,
+ 16, 0, sta350_limiter_ac_attack_tlv),
+SOC_SINGLE_TLV("Limiter2 Attack Threshold (AC Mode)",
+ STA350_L2ATRT, STA350_LxA_SHIFT,
+ 16, 0, sta350_limiter_ac_attack_tlv),
+SOC_SINGLE_TLV("Limiter1 Release Threshold (AC Mode)",
+ STA350_L1ATRT, STA350_LxR_SHIFT,
+ 16, 0, sta350_limiter_ac_release_tlv),
+SOC_SINGLE_TLV("Limiter2 Release Threshold (AC Mode)",
+ STA350_L2ATRT, STA350_LxR_SHIFT,
+ 16, 0, sta350_limiter_ac_release_tlv),
+SOC_SINGLE_TLV("Limiter1 Attack Threshold (DRC Mode)",
+ STA350_L1ATRT, STA350_LxA_SHIFT,
+ 16, 0, sta350_limiter_drc_attack_tlv),
+SOC_SINGLE_TLV("Limiter2 Attack Threshold (DRC Mode)",
+ STA350_L2ATRT, STA350_LxA_SHIFT,
+ 16, 0, sta350_limiter_drc_attack_tlv),
+SOC_SINGLE_TLV("Limiter1 Release Threshold (DRC Mode)",
+ STA350_L1ATRT, STA350_LxR_SHIFT,
+ 16, 0, sta350_limiter_drc_release_tlv),
+SOC_SINGLE_TLV("Limiter2 Release Threshold (DRC Mode)",
+ STA350_L2ATRT, STA350_LxR_SHIFT,
+ 16, 0, sta350_limiter_drc_release_tlv),
+
+BIQUAD_COEFS("Ch1 - Biquad 1", 0),
+BIQUAD_COEFS("Ch1 - Biquad 2", 5),
+BIQUAD_COEFS("Ch1 - Biquad 3", 10),
+BIQUAD_COEFS("Ch1 - Biquad 4", 15),
+BIQUAD_COEFS("Ch2 - Biquad 1", 20),
+BIQUAD_COEFS("Ch2 - Biquad 2", 25),
+BIQUAD_COEFS("Ch2 - Biquad 3", 30),
+BIQUAD_COEFS("Ch2 - Biquad 4", 35),
+BIQUAD_COEFS("High-pass", 40),
+BIQUAD_COEFS("Low-pass", 45),
+SINGLE_COEF("Ch1 - Prescale", 50),
+SINGLE_COEF("Ch2 - Prescale", 51),
+SINGLE_COEF("Ch1 - Postscale", 52),
+SINGLE_COEF("Ch2 - Postscale", 53),
+SINGLE_COEF("Ch3 - Postscale", 54),
+SINGLE_COEF("Thermal warning - Postscale", 55),
+SINGLE_COEF("Ch1 - Mix 1", 56),
+SINGLE_COEF("Ch1 - Mix 2", 57),
+SINGLE_COEF("Ch2 - Mix 1", 58),
+SINGLE_COEF("Ch2 - Mix 2", 59),
+SINGLE_COEF("Ch3 - Mix 1", 60),
+SINGLE_COEF("Ch3 - Mix 2", 61),
+};
+
+static const struct snd_soc_dapm_widget sta350_dapm_widgets[] = {
+SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_OUTPUT("LEFT"),
+SND_SOC_DAPM_OUTPUT("RIGHT"),
+SND_SOC_DAPM_OUTPUT("SUB"),
+};
+
+static const struct snd_soc_dapm_route sta350_dapm_routes[] = {
+ { "LEFT", NULL, "DAC" },
+ { "RIGHT", NULL, "DAC" },
+ { "SUB", NULL, "DAC" },
+ { "DAC", NULL, "Playback" },
+};
+
+/* MCLK interpolation ratio per fs */
+static struct {
+ int fs;
+ int ir;
+} interpolation_ratios[] = {
+ { 32000, 0 },
+ { 44100, 0 },
+ { 48000, 0 },
+ { 88200, 1 },
+ { 96000, 1 },
+ { 176400, 2 },
+ { 192000, 2 },
+};
+
+/* MCLK to fs clock ratios */
+static int mcs_ratio_table[3][6] = {
+ { 768, 512, 384, 256, 128, 576 },
+ { 384, 256, 192, 128, 64, 0 },
+ { 192, 128, 96, 64, 32, 0 },
+};
+
+/**
+ * sta350_set_dai_sysclk - configure MCLK
+ * @codec_dai: the codec DAI
+ * @clk_id: the clock ID (ignored)
+ * @freq: the MCLK input frequency
+ * @dir: the clock direction (ignored)
+ *
+ * The value of MCLK is used to determine which sample rates are supported
+ * by the STA350, based on the mcs_ratio_table.
+ *
+ * This function must be called by the machine driver's 'startup' function,
+ * otherwise the list of supported sample rates will not be available in
+ * time for ALSA.
+ */
+static int sta350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "mclk=%u\n", freq);
+ sta350->mclk = freq;
+
+ return 0;
+}
+
+/**
+ * sta350_set_dai_fmt - configure the codec for the selected audio format
+ * @codec_dai: the codec DAI
+ * @fmt: a SND_SOC_DAIFMT_x value indicating the data format
+ *
+ * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the
+ * codec accordingly.
+ */
+static int sta350_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+ unsigned int confb = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_RIGHT_J:
+ case SND_SOC_DAIFMT_LEFT_J:
+ sta350->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ confb |= STA350_CONFB_C2IM;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ confb |= STA350_CONFB_C1IM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(sta350->regmap, STA350_CONFB,
+ STA350_CONFB_C1IM | STA350_CONFB_C2IM, confb);
+}
+
+/**
+ * sta350_hw_params - program the STA350 with the given hardware parameters.
+ * @substream: the audio stream
+ * @params: the hardware parameters to set
+ * @dai: the SOC DAI (ignored)
+ *
+ * This function programs the hardware with the values provided.
+ * Specifically, the sample rate and the data format.
+ */
+static int sta350_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;
+ struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+ int i, mcs = -EINVAL, ir = -EINVAL;
+ unsigned int confa, confb;
+ unsigned int rate, ratio;
+ int ret;
+
+ if (!sta350->mclk) {
+ dev_err(codec->dev,
+ "sta350->mclk is unset. Unable to determine ratio\n");
+ return -EIO;
+ }
+
+ rate = params_rate(params);
+ ratio = sta350->mclk / rate;
+ dev_dbg(codec->dev, "rate: %u, ratio: %u\n", rate, ratio);
+
+ for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) {
+ if (interpolation_ratios[i].fs == rate) {
+ ir = interpolation_ratios[i].ir;
+ break;
+ }
+ }
+
+ if (ir < 0) {
+ dev_err(codec->dev, "Unsupported samplerate: %u\n", rate);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < 6; i++) {
+ if (mcs_ratio_table[ir][i] == ratio) {
+ mcs = i;
+ break;
+ }
+ }
+
+ if (mcs < 0) {
+ dev_err(codec->dev, "Unresolvable ratio: %u\n", ratio);
+ return -EINVAL;
+ }
+
+ confa = (ir << STA350_CONFA_IR_SHIFT) |
+ (mcs << STA350_CONFA_MCS_SHIFT);
+ confb = 0;
+
+ switch (params_width(params)) {
+ case 24:
+ dev_dbg(codec->dev, "24bit\n");
+ /* fall through */
+ case 32:
+ dev_dbg(codec->dev, "24bit or 32bit\n");
+ switch (sta350->format) {
+ case SND_SOC_DAIFMT_I2S:
+ confb |= 0x0;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ confb |= 0x1;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ confb |= 0x2;
+ break;
+ }
+
+ break;
+ case 20:
+ dev_dbg(codec->dev, "20bit\n");
+ switch (sta350->format) {
+ case SND_SOC_DAIFMT_I2S:
+ confb |= 0x4;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ confb |= 0x5;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ confb |= 0x6;
+ break;
+ }
+
+ break;
+ case 18:
+ dev_dbg(codec->dev, "18bit\n");
+ switch (sta350->format) {
+ case SND_SOC_DAIFMT_I2S:
+ confb |= 0x8;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ confb |= 0x9;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ confb |= 0xa;
+ break;
+ }
+
+ break;
+ case 16:
+ dev_dbg(codec->dev, "16bit\n");
+ switch (sta350->format) {
+ case SND_SOC_DAIFMT_I2S:
+ confb |= 0x0;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ confb |= 0xd;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ confb |= 0xe;
+ break;
+ }
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_update_bits(sta350->regmap, STA350_CONFA,
+ STA350_CONFA_MCS_MASK | STA350_CONFA_IR_MASK,
+ confa);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_update_bits(sta350->regmap, STA350_CONFB,
+ STA350_CONFB_SAI_MASK | STA350_CONFB_SAIFB,
+ confb);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int sta350_startup_sequence(struct sta350_priv *sta350)
+{
+ if (sta350->gpiod_power_down)
+ gpiod_set_value(sta350->gpiod_power_down, 1);
+
+ if (sta350->gpiod_nreset) {
+ gpiod_set_value(sta350->gpiod_nreset, 0);
+ mdelay(1);
+ gpiod_set_value(sta350->gpiod_nreset, 1);
+ mdelay(1);
+ }
+
+ return 0;
+}
+
+/**
+ * sta350_set_bias_level - DAPM callback
+ * @codec: the codec device
+ * @level: DAPM power level
+ *
+ * This is called by ALSA to put the codec into low power mode
+ * or to wake it up. If the codec is powered off completely
+ * all registers must be restored after power on.
+ */
+static int sta350_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ dev_dbg(codec->dev, "level = %d\n", level);
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ /* Full power on */
+ regmap_update_bits(sta350->regmap, STA350_CONFF,
+ STA350_CONFF_PWDN | STA350_CONFF_EAPD,
+ STA350_CONFF_PWDN | STA350_CONFF_EAPD);
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ ret = regulator_bulk_enable(
+ ARRAY_SIZE(sta350->supplies),
+ sta350->supplies);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to enable supplies: %d\n",
+ ret);
+ return ret;
+ }
+ sta350_startup_sequence(sta350);
+ sta350_cache_sync(codec);
+ }
+
+ /* Power down */
+ regmap_update_bits(sta350->regmap, STA350_CONFF,
+ STA350_CONFF_PWDN | STA350_CONFF_EAPD,
+ 0);
+
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ /* The chip runs through the power down sequence for us */
+ regmap_update_bits(sta350->regmap, STA350_CONFF,
+ STA350_CONFF_PWDN | STA350_CONFF_EAPD, 0);
+
+ /* power down: low */
+ if (sta350->gpiod_power_down)
+ gpiod_set_value(sta350->gpiod_power_down, 0);
+
+ if (sta350->gpiod_nreset)
+ gpiod_set_value(sta350->gpiod_nreset, 0);
+
+ regulator_bulk_disable(ARRAY_SIZE(sta350->supplies),
+ sta350->supplies);
+ break;
+ }
+ codec->dapm.bias_level = level;
+ return 0;
+}
+
+static const struct snd_soc_dai_ops sta350_dai_ops = {
+ .hw_params = sta350_hw_params,
+ .set_sysclk = sta350_set_dai_sysclk,
+ .set_fmt = sta350_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver sta350_dai = {
+ .name = "sta350-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = STA350_RATES,
+ .formats = STA350_FORMATS,
+ },
+ .ops = &sta350_dai_ops,
+};
+
+#ifdef CONFIG_PM
+static int sta350_suspend(struct snd_soc_codec *codec)
+{
+ sta350_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int sta350_resume(struct snd_soc_codec *codec)
+{
+ sta350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ return 0;
+}
+#else
+#define sta350_suspend NULL
+#define sta350_resume NULL
+#endif
+
+static int sta350_probe(struct snd_soc_codec *codec)
+{
+ struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+ struct sta350_platform_data *pdata = sta350->pdata;
+ int i, ret = 0, thermal = 0;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(sta350->supplies),
+ sta350->supplies);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+ return ret;
+ }
+
+ ret = sta350_startup_sequence(sta350);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to startup device\n");
+ return ret;
+ }
+
+ /* CONFA */
+ if (!pdata->thermal_warning_recovery)
+ thermal |= STA350_CONFA_TWAB;
+ if (!pdata->thermal_warning_adjustment)
+ thermal |= STA350_CONFA_TWRB;
+ if (!pdata->fault_detect_recovery)
+ thermal |= STA350_CONFA_FDRB;
+ regmap_update_bits(sta350->regmap, STA350_CONFA,
+ STA350_CONFA_TWAB | STA350_CONFA_TWRB |
+ STA350_CONFA_FDRB,
+ thermal);
+
+ /* CONFC */
+ regmap_update_bits(sta350->regmap, STA350_CONFC,
+ STA350_CONFC_OM_MASK,
+ pdata->ffx_power_output_mode
+ << STA350_CONFC_OM_SHIFT);
+ regmap_update_bits(sta350->regmap, STA350_CONFC,
+ STA350_CONFC_CSZ_MASK,
+ pdata->drop_compensation_ns
+ << STA350_CONFC_CSZ_SHIFT);
+ regmap_update_bits(sta350->regmap,
+ STA350_CONFC,
+ STA350_CONFC_OCRB,
+ pdata->oc_warning_adjustment ?
+ STA350_CONFC_OCRB : 0);
+
+ /* CONFE */
+ regmap_update_bits(sta350->regmap, STA350_CONFE,
+ STA350_CONFE_MPCV,
+ pdata->max_power_use_mpcc ?
+ STA350_CONFE_MPCV : 0);
+ regmap_update_bits(sta350->regmap, STA350_CONFE,
+ STA350_CONFE_MPC,
+ pdata->max_power_correction ?
+ STA350_CONFE_MPC : 0);
+ regmap_update_bits(sta350->regmap, STA350_CONFE,
+ STA350_CONFE_AME,
+ pdata->am_reduction_mode ?
+ STA350_CONFE_AME : 0);
+ regmap_update_bits(sta350->regmap, STA350_CONFE,
+ STA350_CONFE_PWMS,
+ pdata->odd_pwm_speed_mode ?
+ STA350_CONFE_PWMS : 0);
+ regmap_update_bits(sta350->regmap, STA350_CONFE,
+ STA350_CONFE_DCCV,
+ pdata->distortion_compensation ?
+ STA350_CONFE_DCCV : 0);
+ /* CONFF */
+ regmap_update_bits(sta350->regmap, STA350_CONFF,
+ STA350_CONFF_IDE,
+ pdata->invalid_input_detect_mute ?
+ STA350_CONFF_IDE : 0);
+ regmap_update_bits(sta350->regmap, STA350_CONFF,
+ STA350_CONFF_OCFG_MASK,
+ pdata->output_conf
+ << STA350_CONFF_OCFG_SHIFT);
+
+ /* channel to output mapping */
+ regmap_update_bits(sta350->regmap, STA350_C1CFG,
+ STA350_CxCFG_OM_MASK,
+ pdata->ch1_output_mapping
+ << STA350_CxCFG_OM_SHIFT);
+ regmap_update_bits(sta350->regmap, STA350_C2CFG,
+ STA350_CxCFG_OM_MASK,
+ pdata->ch2_output_mapping
+ << STA350_CxCFG_OM_SHIFT);
+ regmap_update_bits(sta350->regmap, STA350_C3CFG,
+ STA350_CxCFG_OM_MASK,
+ pdata->ch3_output_mapping
+ << STA350_CxCFG_OM_SHIFT);
+
+ /* miscellaneous registers */
+ regmap_update_bits(sta350->regmap, STA350_MISC1,
+ STA350_MISC1_CPWMEN,
+ pdata->activate_mute_output ?
+ STA350_MISC1_CPWMEN : 0);
+ regmap_update_bits(sta350->regmap, STA350_MISC1,
+ STA350_MISC1_BRIDGOFF,
+ pdata->bridge_immediate_off ?
+ STA350_MISC1_BRIDGOFF : 0);
+ regmap_update_bits(sta350->regmap, STA350_MISC1,
+ STA350_MISC1_NSHHPEN,
+ pdata->noise_shape_dc_cut ?
+ STA350_MISC1_NSHHPEN : 0);
+ regmap_update_bits(sta350->regmap, STA350_MISC1,
+ STA350_MISC1_RPDNEN,
+ pdata->powerdown_master_vol ?
+ STA350_MISC1_RPDNEN: 0);
+
+ regmap_update_bits(sta350->regmap, STA350_MISC2,
+ STA350_MISC2_PNDLSL_MASK,
+ pdata->powerdown_delay_divider
+ << STA350_MISC2_PNDLSL_SHIFT);
+
+ /* initialize coefficient shadow RAM with reset values */
+ for (i = 4; i <= 49; i += 5)
+ sta350->coef_shadow[i] = 0x400000;
+ for (i = 50; i <= 54; i++)
+ sta350->coef_shadow[i] = 0x7fffff;
+ sta350->coef_shadow[55] = 0x5a9df7;
+ sta350->coef_shadow[56] = 0x7fffff;
+ sta350->coef_shadow[59] = 0x7fffff;
+ sta350->coef_shadow[60] = 0x400000;
+ sta350->coef_shadow[61] = 0x400000;
+
+ sta350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ /* Bias level configuration will have done an extra enable */
+ regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies);
+
+ return 0;
+}
+
+static int sta350_remove(struct snd_soc_codec *codec)
+{
+ struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+
+ sta350_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies);
+
+ return 0;
+}
+
+static const struct snd_soc_codec_driver sta350_codec = {
+ .probe = sta350_probe,
+ .remove = sta350_remove,
+ .suspend = sta350_suspend,
+ .resume = sta350_resume,
+ .set_bias_level = sta350_set_bias_level,
+ .controls = sta350_snd_controls,
+ .num_controls = ARRAY_SIZE(sta350_snd_controls),
+ .dapm_widgets = sta350_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sta350_dapm_widgets),
+ .dapm_routes = sta350_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(sta350_dapm_routes),
+};
+
+static const struct regmap_config sta350_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = STA350_MISC2,
+ .reg_defaults = sta350_regs,
+ .num_reg_defaults = ARRAY_SIZE(sta350_regs),
+ .cache_type = REGCACHE_RBTREE,
+ .wr_table = &sta350_write_regs,
+ .rd_table = &sta350_read_regs,
+ .volatile_table = &sta350_volatile_regs,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id st350_dt_ids[] = {
+ { .compatible = "st,sta350", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, st350_dt_ids);
+
+static const char * const sta350_ffx_modes[] = {
+ [STA350_FFX_PM_DROP_COMP] = "drop-compensation",
+ [STA350_FFX_PM_TAPERED_COMP] = "tapered-compensation",
+ [STA350_FFX_PM_FULL_POWER] = "full-power-mode",
+ [STA350_FFX_PM_VARIABLE_DROP_COMP] = "variable-drop-compensation",
+};
+
+static int sta350_probe_dt(struct device *dev, struct sta350_priv *sta350)
+{
+ struct device_node *np = dev->of_node;
+ struct sta350_platform_data *pdata;
+ const char *ffx_power_mode;
+ u16 tmp;
+ u8 tmp8;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ of_property_read_u8(np, "st,output-conf",
+ &pdata->output_conf);
+ of_property_read_u8(np, "st,ch1-output-mapping",
+ &pdata->ch1_output_mapping);
+ of_property_read_u8(np, "st,ch2-output-mapping",
+ &pdata->ch2_output_mapping);
+ of_property_read_u8(np, "st,ch3-output-mapping",
+ &pdata->ch3_output_mapping);
+
+ if (of_get_property(np, "st,thermal-warning-recovery", NULL))
+ pdata->thermal_warning_recovery = 1;
+ if (of_get_property(np, "st,thermal-warning-adjustment", NULL))
+ pdata->thermal_warning_adjustment = 1;
+ if (of_get_property(np, "st,fault-detect-recovery", NULL))
+ pdata->fault_detect_recovery = 1;
+
+ pdata->ffx_power_output_mode = STA350_FFX_PM_VARIABLE_DROP_COMP;
+ if (!of_property_read_string(np, "st,ffx-power-output-mode",
+ &ffx_power_mode)) {
+ int i, mode = -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(sta350_ffx_modes); i++)
+ if (!strcasecmp(ffx_power_mode, sta350_ffx_modes[i]))
+ mode = i;
+
+ if (mode < 0)
+ dev_warn(dev, "Unsupported ffx output mode: %s\n",
+ ffx_power_mode);
+ else
+ pdata->ffx_power_output_mode = mode;
+ }
+
+ tmp = 140;
+ of_property_read_u16(np, "st,drop-compensation-ns", &tmp);
+ pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20;
+
+ if (of_get_property(np, "st,overcurrent-warning-adjustment", NULL))
+ pdata->oc_warning_adjustment = 1;
+
+ /* CONFE */
+ if (of_get_property(np, "st,max-power-use-mpcc", NULL))
+ pdata->max_power_use_mpcc = 1;
+
+ if (of_get_property(np, "st,max-power-correction", NULL))
+ pdata->max_power_correction = 1;
+
+ if (of_get_property(np, "st,am-reduction-mode", NULL))
+ pdata->am_reduction_mode = 1;
+
+ if (of_get_property(np, "st,odd-pwm-speed-mode", NULL))
+ pdata->odd_pwm_speed_mode = 1;
+
+ if (of_get_property(np, "st,distortion-compensation", NULL))
+ pdata->distortion_compensation = 1;
+
+ /* CONFF */
+ if (of_get_property(np, "st,invalid-input-detect-mute", NULL))
+ pdata->invalid_input_detect_mute = 1;
+
+ /* MISC */
+ if (of_get_property(np, "st,activate-mute-output", NULL))
+ pdata->activate_mute_output = 1;
+
+ if (of_get_property(np, "st,bridge-immediate-off", NULL))
+ pdata->bridge_immediate_off = 1;
+
+ if (of_get_property(np, "st,noise-shape-dc-cut", NULL))
+ pdata->noise_shape_dc_cut = 1;
+
+ if (of_get_property(np, "st,powerdown-master-volume", NULL))
+ pdata->powerdown_master_vol = 1;
+
+ if (!of_property_read_u8(np, "st,powerdown-delay-divider", &tmp8)) {
+ if (is_power_of_2(tmp8) && tmp8 >= 1 && tmp8 <= 128)
+ pdata->powerdown_delay_divider = ilog2(tmp8);
+ else
+ dev_warn(dev, "Unsupported powerdown delay divider %d\n",
+ tmp8);
+ }
+
+ sta350->pdata = pdata;
+
+ return 0;
+}
+#endif
+
+static int sta350_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &i2c->dev;
+ struct sta350_priv *sta350;
+ int ret, i;
+
+ sta350 = devm_kzalloc(dev, sizeof(struct sta350_priv), GFP_KERNEL);
+ if (!sta350)
+ return -ENOMEM;
+
+ mutex_init(&sta350->coeff_lock);
+ sta350->pdata = dev_get_platdata(dev);
+
+#ifdef CONFIG_OF
+ if (dev->of_node) {
+ ret = sta350_probe_dt(dev, sta350);
+ if (ret < 0)
+ return ret;
+ }
+#endif
+
+ /* GPIOs */
+ sta350->gpiod_nreset = devm_gpiod_get(dev, "reset");
+ if (IS_ERR(sta350->gpiod_nreset)) {
+ ret = PTR_ERR(sta350->gpiod_nreset);
+ if (ret != -ENOENT && ret != -ENOSYS)
+ return ret;
+
+ sta350->gpiod_nreset = NULL;
+ } else {
+ gpiod_direction_output(sta350->gpiod_nreset, 0);
+ }
+
+ sta350->gpiod_power_down = devm_gpiod_get(dev, "power-down");
+ if (IS_ERR(sta350->gpiod_power_down)) {
+ ret = PTR_ERR(sta350->gpiod_power_down);
+ if (ret != -ENOENT && ret != -ENOSYS)
+ return ret;
+
+ sta350->gpiod_power_down = NULL;
+ } else {
+ gpiod_direction_output(sta350->gpiod_power_down, 0);
+ }
+
+ /* regulators */
+ for (i = 0; i < ARRAY_SIZE(sta350->supplies); i++)
+ sta350->supplies[i].supply = sta350_supply_names[i];
+
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(sta350->supplies),
+ sta350->supplies);
+ if (ret < 0) {
+ dev_err(dev, "Failed to request supplies: %d\n", ret);
+ return ret;
+ }
+
+ sta350->regmap = devm_regmap_init_i2c(i2c, &sta350_regmap);
+ if (IS_ERR(sta350->regmap)) {
+ ret = PTR_ERR(sta350->regmap);
+ dev_err(dev, "Failed to init regmap: %d\n", ret);
+ return ret;
+ }
+
+ i2c_set_clientdata(i2c, sta350);
+
+ ret = snd_soc_register_codec(dev, &sta350_codec, &sta350_dai, 1);
+ if (ret < 0)
+ dev_err(dev, "Failed to register codec (%d)\n", ret);
+
+ return ret;
+}
+
+static int sta350_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static const struct i2c_device_id sta350_i2c_id[] = {
+ { "sta350", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sta350_i2c_id);
+
+static struct i2c_driver sta350_i2c_driver = {
+ .driver = {
+ .name = "sta350",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(st350_dt_ids),
+ },
+ .probe = sta350_i2c_probe,
+ .remove = sta350_i2c_remove,
+ .id_table = sta350_i2c_id,
+};
+
+module_i2c_driver(sta350_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC STA350 driver");
+MODULE_AUTHOR("Sven Brandau <info@brandau.biz>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sta350.h b/sound/soc/codecs/sta350.h
new file mode 100644
index 00000000000..fb728529077
--- /dev/null
+++ b/sound/soc/codecs/sta350.h
@@ -0,0 +1,238 @@
+/*
+ * Codec driver for ST STA350 2.1-channel high-efficiency digital audio system
+ *
+ * Copyright: 2011 Raumfeld GmbH
+ * Author: Sven Brandau <info@brandau.biz>
+ *
+ * based on code from:
+ * Raumfeld GmbH
+ * Johannes Stezenbach <js@sig21.net>
+ * Wolfson Microelectronics PLC.
+ * Mark Brown <broonie@opensource.wolfsonmicro.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; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef _ASOC_STA_350_H
+#define _ASOC_STA_350_H
+
+/* STA50 register addresses */
+
+#define STA350_REGISTER_COUNT 0x4D
+#define STA350_COEF_COUNT 62
+
+#define STA350_CONFA 0x00
+#define STA350_CONFB 0x01
+#define STA350_CONFC 0x02
+#define STA350_CONFD 0x03
+#define STA350_CONFE 0x04
+#define STA350_CONFF 0x05
+#define STA350_MMUTE 0x06
+#define STA350_MVOL 0x07
+#define STA350_C1VOL 0x08
+#define STA350_C2VOL 0x09
+#define STA350_C3VOL 0x0a
+#define STA350_AUTO1 0x0b
+#define STA350_AUTO2 0x0c
+#define STA350_AUTO3 0x0d
+#define STA350_C1CFG 0x0e
+#define STA350_C2CFG 0x0f
+#define STA350_C3CFG 0x10
+#define STA350_TONE 0x11
+#define STA350_L1AR 0x12
+#define STA350_L1ATRT 0x13
+#define STA350_L2AR 0x14
+#define STA350_L2ATRT 0x15
+#define STA350_CFADDR2 0x16
+#define STA350_B1CF1 0x17
+#define STA350_B1CF2 0x18
+#define STA350_B1CF3 0x19
+#define STA350_B2CF1 0x1a
+#define STA350_B2CF2 0x1b
+#define STA350_B2CF3 0x1c
+#define STA350_A1CF1 0x1d
+#define STA350_A1CF2 0x1e
+#define STA350_A1CF3 0x1f
+#define STA350_A2CF1 0x20
+#define STA350_A2CF2 0x21
+#define STA350_A2CF3 0x22
+#define STA350_B0CF1 0x23
+#define STA350_B0CF2 0x24
+#define STA350_B0CF3 0x25
+#define STA350_CFUD 0x26
+#define STA350_MPCC1 0x27
+#define STA350_MPCC2 0x28
+#define STA350_DCC1 0x29
+#define STA350_DCC2 0x2a
+#define STA350_FDRC1 0x2b
+#define STA350_FDRC2 0x2c
+#define STA350_STATUS 0x2d
+/* reserved: 0x2d - 0x30 */
+#define STA350_EQCFG 0x31
+#define STA350_EATH1 0x32
+#define STA350_ERTH1 0x33
+#define STA350_EATH2 0x34
+#define STA350_ERTH2 0x35
+#define STA350_CONFX 0x36
+#define STA350_SVCA 0x37
+#define STA350_SVCB 0x38
+#define STA350_RMS0A 0x39
+#define STA350_RMS0B 0x3a
+#define STA350_RMS0C 0x3b
+#define STA350_RMS1A 0x3c
+#define STA350_RMS1B 0x3d
+#define STA350_RMS1C 0x3e
+#define STA350_EVOLRES 0x3f
+/* reserved: 0x40 - 0x47 */
+#define STA350_NSHAPE 0x48
+#define STA350_CTXB4B1 0x49
+#define STA350_CTXB7B5 0x4a
+#define STA350_MISC1 0x4b
+#define STA350_MISC2 0x4c
+
+/* 0x00 CONFA */
+#define STA350_CONFA_MCS_MASK 0x03
+#define STA350_CONFA_MCS_SHIFT 0
+#define STA350_CONFA_IR_MASK 0x18
+#define STA350_CONFA_IR_SHIFT 3
+#define STA350_CONFA_TWRB BIT(5)
+#define STA350_CONFA_TWAB BIT(6)
+#define STA350_CONFA_FDRB BIT(7)
+
+/* 0x01 CONFB */
+#define STA350_CONFB_SAI_MASK 0x0f
+#define STA350_CONFB_SAI_SHIFT 0
+#define STA350_CONFB_SAIFB BIT(4)
+#define STA350_CONFB_DSCKE BIT(5)
+#define STA350_CONFB_C1IM BIT(6)
+#define STA350_CONFB_C2IM BIT(7)
+
+/* 0x02 CONFC */
+#define STA350_CONFC_OM_MASK 0x03
+#define STA350_CONFC_OM_SHIFT 0
+#define STA350_CONFC_CSZ_MASK 0x3c
+#define STA350_CONFC_CSZ_SHIFT 2
+#define STA350_CONFC_OCRB BIT(7)
+
+/* 0x03 CONFD */
+#define STA350_CONFD_HPB_SHIFT 0
+#define STA350_CONFD_DEMP_SHIFT 1
+#define STA350_CONFD_DSPB_SHIFT 2
+#define STA350_CONFD_PSL_SHIFT 3
+#define STA350_CONFD_BQL_SHIFT 4
+#define STA350_CONFD_DRC_SHIFT 5
+#define STA350_CONFD_ZDE_SHIFT 6
+#define STA350_CONFD_SME_SHIFT 7
+
+/* 0x04 CONFE */
+#define STA350_CONFE_MPCV BIT(0)
+#define STA350_CONFE_MPCV_SHIFT 0
+#define STA350_CONFE_MPC BIT(1)
+#define STA350_CONFE_MPC_SHIFT 1
+#define STA350_CONFE_NSBW BIT(2)
+#define STA350_CONFE_NSBW_SHIFT 2
+#define STA350_CONFE_AME BIT(3)
+#define STA350_CONFE_AME_SHIFT 3
+#define STA350_CONFE_PWMS BIT(4)
+#define STA350_CONFE_PWMS_SHIFT 4
+#define STA350_CONFE_DCCV BIT(5)
+#define STA350_CONFE_DCCV_SHIFT 5
+#define STA350_CONFE_ZCE BIT(6)
+#define STA350_CONFE_ZCE_SHIFT 6
+#define STA350_CONFE_SVE BIT(7)
+#define STA350_CONFE_SVE_SHIFT 7
+
+/* 0x05 CONFF */
+#define STA350_CONFF_OCFG_MASK 0x03
+#define STA350_CONFF_OCFG_SHIFT 0
+#define STA350_CONFF_IDE BIT(2)
+#define STA350_CONFF_BCLE BIT(3)
+#define STA350_CONFF_LDTE BIT(4)
+#define STA350_CONFF_ECLE BIT(5)
+#define STA350_CONFF_PWDN BIT(6)
+#define STA350_CONFF_EAPD BIT(7)
+
+/* 0x06 MMUTE */
+#define STA350_MMUTE_MMUTE 0x01
+#define STA350_MMUTE_MMUTE_SHIFT 0
+#define STA350_MMUTE_C1M 0x02
+#define STA350_MMUTE_C1M_SHIFT 1
+#define STA350_MMUTE_C2M 0x04
+#define STA350_MMUTE_C2M_SHIFT 2
+#define STA350_MMUTE_C3M 0x08
+#define STA350_MMUTE_C3M_SHIFT 3
+#define STA350_MMUTE_LOC_MASK 0xC0
+#define STA350_MMUTE_LOC_SHIFT 6
+
+/* 0x0b AUTO1 */
+#define STA350_AUTO1_AMGC_MASK 0x30
+#define STA350_AUTO1_AMGC_SHIFT 4
+
+/* 0x0c AUTO2 */
+#define STA350_AUTO2_AMAME 0x01
+#define STA350_AUTO2_AMAM_MASK 0x0e
+#define STA350_AUTO2_AMAM_SHIFT 1
+#define STA350_AUTO2_XO_MASK 0xf0
+#define STA350_AUTO2_XO_SHIFT 4
+
+/* 0x0d AUTO3 */
+#define STA350_AUTO3_PEQ_MASK 0x1f
+#define STA350_AUTO3_PEQ_SHIFT 0
+
+/* 0x0e 0x0f 0x10 CxCFG */
+#define STA350_CxCFG_TCB_SHIFT 0
+#define STA350_CxCFG_EQBP_SHIFT 1
+#define STA350_CxCFG_VBP_SHIFT 2
+#define STA350_CxCFG_BO_SHIFT 3
+#define STA350_CxCFG_LS_SHIFT 4
+#define STA350_CxCFG_OM_MASK 0xc0
+#define STA350_CxCFG_OM_SHIFT 6
+
+/* 0x11 TONE */
+#define STA350_TONE_BTC_SHIFT 0
+#define STA350_TONE_TTC_SHIFT 4
+
+/* 0x12 0x13 0x14 0x15 limiter attack/release */
+#define STA350_LxA_SHIFT 0
+#define STA350_LxR_SHIFT 4
+
+/* 0x26 CFUD */
+#define STA350_CFUD_W1 0x01
+#define STA350_CFUD_WA 0x02
+#define STA350_CFUD_R1 0x04
+#define STA350_CFUD_RA 0x08
+
+
+/* biquad filter coefficient table offsets */
+#define STA350_C1_BQ_BASE 0
+#define STA350_C2_BQ_BASE 20
+#define STA350_CH_BQ_NUM 4
+#define STA350_BQ_NUM_COEF 5
+#define STA350_XO_HP_BQ_BASE 40
+#define STA350_XO_LP_BQ_BASE 45
+#define STA350_C1_PRESCALE 50
+#define STA350_C2_PRESCALE 51
+#define STA350_C1_POSTSCALE 52
+#define STA350_C2_POSTSCALE 53
+#define STA350_C3_POSTSCALE 54
+#define STA350_TW_POSTSCALE 55
+#define STA350_C1_MIX1 56
+#define STA350_C1_MIX2 57
+#define STA350_C2_MIX1 58
+#define STA350_C2_MIX2 59
+#define STA350_C3_MIX1 60
+#define STA350_C3_MIX2 61
+
+/* miscellaneous register 1 */
+#define STA350_MISC1_CPWMEN BIT(2)
+#define STA350_MISC1_BRIDGOFF BIT(5)
+#define STA350_MISC1_NSHHPEN BIT(6)
+#define STA350_MISC1_RPDNEN BIT(7)
+
+/* miscellaneous register 2 */
+#define STA350_MISC2_PNDLSL_MASK 0x1c
+#define STA350_MISC2_PNDLSL_SHIFT 2
+
+#endif /* _ASOC_STA_350_H */
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c
index 40c07be9b58..a40c4b0196a 100644
--- a/sound/soc/codecs/sta529.c
+++ b/sound/soc/codecs/sta529.c
@@ -141,7 +141,7 @@ static const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary",
static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0);
static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0);
-static const SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text);
+static SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text);
static const struct snd_kcontrol_new sta529_snd_controls[] = {
SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0,
@@ -193,8 +193,7 @@ static int sta529_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
int pdata, play_freq_val, record_freq_val;
int bclk_to_fs_ratio;
@@ -322,16 +321,6 @@ static struct snd_soc_dai_driver sta529_dai = {
static int sta529_probe(struct snd_soc_codec *codec)
{
- struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- codec->control_data = sta529->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
-
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index a5455c1aea4..53b810d23fe 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -62,25 +62,25 @@ static const char *stac9766_boost1[] = {"0dB", "10dB"};
static const char *stac9766_boost2[] = {"0dB", "20dB"};
static const char *stac9766_stereo_mic[] = {"Off", "On"};
-static const struct soc_enum stac9766_record_enum =
- SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, stac9766_record_mux);
-static const struct soc_enum stac9766_mono_enum =
- SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, stac9766_mono_mux);
-static const struct soc_enum stac9766_mic_enum =
- SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, stac9766_mic_mux);
-static const struct soc_enum stac9766_SPDIF_enum =
- SOC_ENUM_SINGLE(AC97_STAC_DA_CONTROL, 1, 2, stac9766_SPDIF_mux);
-static const struct soc_enum stac9766_popbypass_enum =
- SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, stac9766_popbypass_mux);
-static const struct soc_enum stac9766_record_all_enum =
- SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 12, 2,
- stac9766_record_all_mux);
-static const struct soc_enum stac9766_boost1_enum =
- SOC_ENUM_SINGLE(AC97_MIC, 6, 2, stac9766_boost1); /* 0/10dB */
-static const struct soc_enum stac9766_boost2_enum =
- SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 2, 2, stac9766_boost2); /* 0/20dB */
-static const struct soc_enum stac9766_stereo_mic_enum =
- SOC_ENUM_SINGLE(AC97_STAC_STEREO_MIC, 2, 1, stac9766_stereo_mic);
+static SOC_ENUM_DOUBLE_DECL(stac9766_record_enum,
+ AC97_REC_SEL, 8, 0, stac9766_record_mux);
+static SOC_ENUM_SINGLE_DECL(stac9766_mono_enum,
+ AC97_GENERAL_PURPOSE, 9, stac9766_mono_mux);
+static SOC_ENUM_SINGLE_DECL(stac9766_mic_enum,
+ AC97_GENERAL_PURPOSE, 8, stac9766_mic_mux);
+static SOC_ENUM_SINGLE_DECL(stac9766_SPDIF_enum,
+ AC97_STAC_DA_CONTROL, 1, stac9766_SPDIF_mux);
+static SOC_ENUM_SINGLE_DECL(stac9766_popbypass_enum,
+ AC97_GENERAL_PURPOSE, 15, stac9766_popbypass_mux);
+static SOC_ENUM_SINGLE_DECL(stac9766_record_all_enum,
+ AC97_STAC_ANALOG_SPECIAL, 12,
+ stac9766_record_all_mux);
+static SOC_ENUM_SINGLE_DECL(stac9766_boost1_enum,
+ AC97_MIC, 6, stac9766_boost1); /* 0/10dB */
+static SOC_ENUM_SINGLE_DECL(stac9766_boost2_enum,
+ AC97_STAC_ANALOG_SPECIAL, 2, stac9766_boost2); /* 0/20dB */
+static SOC_ENUM_SINGLE_DECL(stac9766_stereo_mic_enum,
+ AC97_STAC_STEREO_MIC, 2, stac9766_stereo_mic);
static const DECLARE_TLV_DB_LINEAR(master_tlv, -4600, 0);
static const DECLARE_TLV_DB_LINEAR(record_tlv, 0, 2250);
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c
index a895a5e4bdf..d48491a4a19 100644
--- a/sound/soc/codecs/tas5086.c
+++ b/sound/soc/codecs/tas5086.c
@@ -272,7 +272,7 @@ static int tas5086_set_deemph(struct snd_soc_codec *codec)
static int tas5086_get_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = priv->deemph;
@@ -283,7 +283,7 @@ static int tas5086_get_deemph(struct snd_kcontrol *kcontrol,
static int tas5086_put_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
priv->deemph = ucontrol->value.enumerated.item[0];
diff --git a/sound/soc/codecs/tlv320aic23-i2c.c b/sound/soc/codecs/tlv320aic23-i2c.c
new file mode 100644
index 00000000000..f1370199548
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic23-i2c.c
@@ -0,0 +1,67 @@
+/*
+ * ALSA SoC TLV320AIC23 codec driver I2C interface
+ *
+ * Author: Arun KS, <arunks@mistralsolutions.com>
+ * Copyright: (C) 2008 Mistral Solutions Pvt Ltd.,
+ *
+ * Based on sound/soc/codecs/wm8731.c by Richard Purdie
+ *
+ * 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 <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+
+#include "tlv320aic23.h"
+
+static int tlv320aic23_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *i2c_id)
+{
+ struct regmap *regmap;
+
+ if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EINVAL;
+
+ regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap);
+ return tlv320aic23_probe(&i2c->dev, regmap);
+}
+
+static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
+{
+ snd_soc_unregister_codec(&i2c->dev);
+ return 0;
+}
+
+static const struct i2c_device_id tlv320aic23_id[] = {
+ {"tlv320aic23", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
+
+static const struct of_device_id tlv320aic23_of_match[] = {
+ { .compatible = "ti,tlv320aic23", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, tlv320aic23_of_match);
+
+static struct i2c_driver tlv320aic23_i2c_driver = {
+ .driver = {
+ .name = "tlv320aic23-codec",
+ .of_match_table = of_match_ptr(tlv320aic23_of_match),
+ },
+ .probe = tlv320aic23_i2c_probe,
+ .remove = __exit_p(tlv320aic23_i2c_remove),
+ .id_table = tlv320aic23_id,
+};
+
+module_i2c_driver(tlv320aic23_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver I2C");
+MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic23-spi.c b/sound/soc/codecs/tlv320aic23-spi.c
new file mode 100644
index 00000000000..3b387e41d75
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic23-spi.c
@@ -0,0 +1,56 @@
+/*
+ * ALSA SoC TLV320AIC23 codec driver SPI interface
+ *
+ * Author: Arun KS, <arunks@mistralsolutions.com>
+ * Copyright: (C) 2008 Mistral Solutions Pvt Ltd.,
+ *
+ * Based on sound/soc/codecs/wm8731.c by Richard Purdie
+ *
+ * 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 <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <sound/soc.h>
+
+#include "tlv320aic23.h"
+
+static int aic23_spi_probe(struct spi_device *spi)
+{
+ int ret;
+ struct regmap *regmap;
+
+ dev_dbg(&spi->dev, "probing tlv320aic23 spi device\n");
+
+ spi->mode = SPI_MODE_0;
+ ret = spi_setup(spi);
+ if (ret < 0)
+ return ret;
+
+ regmap = devm_regmap_init_spi(spi, &tlv320aic23_regmap);
+ return tlv320aic23_probe(&spi->dev, regmap);
+}
+
+static int aic23_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ return 0;
+}
+
+static struct spi_driver aic23_spi = {
+ .driver = {
+ .name = "tlv320aic23",
+ .owner = THIS_MODULE,
+ },
+ .probe = aic23_spi_probe,
+ .remove = aic23_spi_remove,
+};
+
+module_spi_driver(aic23_spi);
+
+MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver SPI");
+MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 5d430cc56f5..686b8b85b95 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -23,7 +23,6 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
-#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -51,7 +50,7 @@ static const struct reg_default tlv320aic23_reg[] = {
{ 9, 0x0000 },
};
-static const struct regmap_config tlv320aic23_regmap = {
+const struct regmap_config tlv320aic23_regmap = {
.reg_bits = 7,
.val_bits = 9,
@@ -60,20 +59,21 @@ static const struct regmap_config tlv320aic23_regmap = {
.num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg),
.cache_type = REGCACHE_RBTREE,
};
+EXPORT_SYMBOL(tlv320aic23_regmap);
static const char *rec_src_text[] = { "Line", "Mic" };
static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
-static const struct soc_enum rec_src_enum =
- SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
+static SOC_ENUM_SINGLE_DECL(rec_src_enum,
+ TLV320AIC23_ANLG, 2, rec_src_text);
static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls =
SOC_DAPM_ENUM("Input Select", rec_src_enum);
-static const struct soc_enum tlv320aic23_rec_src =
- SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
-static const struct soc_enum tlv320aic23_deemph =
- SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text);
+static SOC_ENUM_SINGLE_DECL(tlv320aic23_rec_src,
+ TLV320AIC23_ANLG, 2, rec_src_text);
+static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph,
+ TLV320AIC23_DIGT, 1, deemph_text);
static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0);
static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0);
@@ -82,7 +82,7 @@ static const DECLARE_TLV_DB_SCALE(sidetone_vol_tlv, -1800, 300, 0);
static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
u16 val, reg;
val = (ucontrol->value.integer.value[0] & 0x07);
@@ -105,7 +105,7 @@ static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
u16 val;
val = snd_soc_read(codec, TLV320AIC23_ANLG) & (0x1C0);
@@ -400,7 +400,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
/* deactivate */
- if (!codec->active) {
+ if (!snd_soc_codec_is_active(codec)) {
udelay(50);
snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
}
@@ -557,16 +557,8 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec)
return 0;
}
-static int tlv320aic23_probe(struct snd_soc_codec *codec)
+static int tlv320aic23_codec_probe(struct snd_soc_codec *codec)
{
- int ret;
-
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
/* Reset codec */
snd_soc_write(codec, TLV320AIC23_RESET, 0);
@@ -604,7 +596,7 @@ static int tlv320aic23_remove(struct snd_soc_codec *codec)
}
static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
- .probe = tlv320aic23_probe,
+ .probe = tlv320aic23_codec_probe,
.remove = tlv320aic23_remove,
.suspend = tlv320aic23_suspend,
.resume = tlv320aic23_resume,
@@ -617,56 +609,25 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
.num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon),
};
-/*
- * If the i2c layer weren't so broken, we could pass this kind of data
- * around
- */
-static int tlv320aic23_codec_probe(struct i2c_client *i2c,
- const struct i2c_device_id *i2c_id)
+int tlv320aic23_probe(struct device *dev, struct regmap *regmap)
{
struct aic23 *aic23;
- int ret;
- if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return -EINVAL;
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
- aic23 = devm_kzalloc(&i2c->dev, sizeof(struct aic23), GFP_KERNEL);
+ aic23 = devm_kzalloc(dev, sizeof(struct aic23), GFP_KERNEL);
if (aic23 == NULL)
return -ENOMEM;
- aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap);
- if (IS_ERR(aic23->regmap))
- return PTR_ERR(aic23->regmap);
+ aic23->regmap = regmap;
- i2c_set_clientdata(i2c, aic23);
+ dev_set_drvdata(dev, aic23);
- ret = snd_soc_register_codec(&i2c->dev,
- &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1);
- return ret;
+ return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23,
+ &tlv320aic23_dai, 1);
}
-static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
-{
- snd_soc_unregister_codec(&i2c->dev);
- return 0;
-}
-
-static const struct i2c_device_id tlv320aic23_id[] = {
- {"tlv320aic23", 0},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
-
-static struct i2c_driver tlv320aic23_i2c_driver = {
- .driver = {
- .name = "tlv320aic23-codec",
- },
- .probe = tlv320aic23_codec_probe,
- .remove = __exit_p(tlv320aic23_i2c_remove),
- .id_table = tlv320aic23_id,
-};
-
-module_i2c_driver(tlv320aic23_i2c_driver);
+EXPORT_SYMBOL(tlv320aic23_probe);
MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h
index e804120bd3d..3a7235a04a8 100644
--- a/sound/soc/codecs/tlv320aic23.h
+++ b/sound/soc/codecs/tlv320aic23.h
@@ -12,6 +12,12 @@
#ifndef _TLV320AIC23_H
#define _TLV320AIC23_H
+struct device;
+struct regmap_config;
+
+extern const struct regmap_config tlv320aic23_regmap;
+int tlv320aic23_probe(struct device *dev, struct regmap *regmap);
+
/* Codec TLV320AIC23 */
#define TLV320AIC23_LINVOL 0x00
#define TLV320AIC23_RINVOL 0x01
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 94a658fa6d9..43069de3d56 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -238,8 +238,9 @@ static struct snd_soc_dai_driver aic26_dai = {
* ALSA controls
*/
static const char *aic26_capture_src_text[] = {"Mic", "Aux"};
-static const struct soc_enum aic26_capture_src_enum =
- SOC_ENUM_SINGLE(AIC26_REG_AUDIO_CTRL1, 12, 2, aic26_capture_src_text);
+static SOC_ENUM_SINGLE_DECL(aic26_capture_src_enum,
+ AIC26_REG_AUDIO_CTRL1, 12,
+ aic26_capture_src_text);
static const struct snd_kcontrol_new aic26_snd_controls[] = {
/* Output */
@@ -295,8 +296,6 @@ static int aic26_probe(struct snd_soc_codec *codec)
struct aic26 *aic26 = dev_get_drvdata(codec->dev);
int ret, reg;
- snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
-
aic26->codec = codec;
/* Reset the codec to power on defaults */
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
new file mode 100644
index 00000000000..23419109eca
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -0,0 +1,1281 @@
+/*
+ * ALSA SoC TLV320AIC31XX codec driver
+ *
+ * Copyright (C) 2014 Texas Instruments, Inc.
+ *
+ * Author: Jyri Sarha <jsarha@ti.com>
+ *
+ * Based on ground work by: Ajit Kulkarni <x0175765@ti.com>
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * The TLV320AIC31xx series of audio codec is a low-power, highly integrated
+ * high performance codec which provides a stereo DAC, a mono ADC,
+ * and mono/stereo Class-D speaker driver.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <dt-bindings/sound/tlv320aic31xx-micbias.h>
+
+#include "tlv320aic31xx.h"
+
+static const struct reg_default aic31xx_reg_defaults[] = {
+ { AIC31XX_CLKMUX, 0x00 },
+ { AIC31XX_PLLPR, 0x11 },
+ { AIC31XX_PLLJ, 0x04 },
+ { AIC31XX_PLLDMSB, 0x00 },
+ { AIC31XX_PLLDLSB, 0x00 },
+ { AIC31XX_NDAC, 0x01 },
+ { AIC31XX_MDAC, 0x01 },
+ { AIC31XX_DOSRMSB, 0x00 },
+ { AIC31XX_DOSRLSB, 0x80 },
+ { AIC31XX_NADC, 0x01 },
+ { AIC31XX_MADC, 0x01 },
+ { AIC31XX_AOSR, 0x80 },
+ { AIC31XX_IFACE1, 0x00 },
+ { AIC31XX_DATA_OFFSET, 0x00 },
+ { AIC31XX_IFACE2, 0x00 },
+ { AIC31XX_BCLKN, 0x01 },
+ { AIC31XX_DACSETUP, 0x14 },
+ { AIC31XX_DACMUTE, 0x0c },
+ { AIC31XX_LDACVOL, 0x00 },
+ { AIC31XX_RDACVOL, 0x00 },
+ { AIC31XX_ADCSETUP, 0x00 },
+ { AIC31XX_ADCFGA, 0x80 },
+ { AIC31XX_ADCVOL, 0x00 },
+ { AIC31XX_HPDRIVER, 0x04 },
+ { AIC31XX_SPKAMP, 0x06 },
+ { AIC31XX_DACMIXERROUTE, 0x00 },
+ { AIC31XX_LANALOGHPL, 0x7f },
+ { AIC31XX_RANALOGHPR, 0x7f },
+ { AIC31XX_LANALOGSPL, 0x7f },
+ { AIC31XX_RANALOGSPR, 0x7f },
+ { AIC31XX_HPLGAIN, 0x02 },
+ { AIC31XX_HPRGAIN, 0x02 },
+ { AIC31XX_SPLGAIN, 0x00 },
+ { AIC31XX_SPRGAIN, 0x00 },
+ { AIC31XX_MICBIAS, 0x00 },
+ { AIC31XX_MICPGA, 0x80 },
+ { AIC31XX_MICPGAPI, 0x00 },
+ { AIC31XX_MICPGAMI, 0x00 },
+};
+
+static bool aic31xx_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case AIC31XX_PAGECTL: /* regmap implementation requires this */
+ case AIC31XX_RESET: /* always clears after write */
+ case AIC31XX_OT_FLAG:
+ case AIC31XX_ADCFLAG:
+ case AIC31XX_DACFLAG1:
+ case AIC31XX_DACFLAG2:
+ case AIC31XX_OFFLAG: /* Sticky interrupt flags */
+ case AIC31XX_INTRDACFLAG: /* Sticky interrupt flags */
+ case AIC31XX_INTRADCFLAG: /* Sticky interrupt flags */
+ case AIC31XX_INTRDACFLAG2:
+ case AIC31XX_INTRADCFLAG2:
+ return true;
+ }
+ return false;
+}
+
+static bool aic31xx_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case AIC31XX_OT_FLAG:
+ case AIC31XX_ADCFLAG:
+ case AIC31XX_DACFLAG1:
+ case AIC31XX_DACFLAG2:
+ case AIC31XX_OFFLAG: /* Sticky interrupt flags */
+ case AIC31XX_INTRDACFLAG: /* Sticky interrupt flags */
+ case AIC31XX_INTRADCFLAG: /* Sticky interrupt flags */
+ case AIC31XX_INTRDACFLAG2:
+ case AIC31XX_INTRADCFLAG2:
+ return false;
+ }
+ return true;
+}
+
+static const struct regmap_range_cfg aic31xx_ranges[] = {
+ {
+ .range_min = 0,
+ .range_max = 12 * 128,
+ .selector_reg = AIC31XX_PAGECTL,
+ .selector_mask = 0xff,
+ .selector_shift = 0,
+ .window_start = 0,
+ .window_len = 128,
+ },
+};
+
+static const struct regmap_config aic31xx_i2c_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = aic31xx_writeable,
+ .volatile_reg = aic31xx_volatile,
+ .reg_defaults = aic31xx_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(aic31xx_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+ .ranges = aic31xx_ranges,
+ .num_ranges = ARRAY_SIZE(aic31xx_ranges),
+ .max_register = 12 * 128,
+};
+
+#define AIC31XX_NUM_SUPPLIES 6
+static const char * const aic31xx_supply_names[AIC31XX_NUM_SUPPLIES] = {
+ "HPVDD",
+ "SPRVDD",
+ "SPLVDD",
+ "AVDD",
+ "IOVDD",
+ "DVDD",
+};
+
+struct aic31xx_disable_nb {
+ struct notifier_block nb;
+ struct aic31xx_priv *aic31xx;
+};
+
+struct aic31xx_priv {
+ struct snd_soc_codec *codec;
+ u8 i2c_regs_status;
+ struct device *dev;
+ struct regmap *regmap;
+ struct aic31xx_pdata pdata;
+ struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES];
+ struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES];
+ unsigned int sysclk;
+ int rate_div_line;
+};
+
+struct aic31xx_rate_divs {
+ u32 mclk;
+ u32 rate;
+ u8 p_val;
+ u8 pll_j;
+ u16 pll_d;
+ u16 dosr;
+ u8 ndac;
+ u8 mdac;
+ u8 aosr;
+ u8 nadc;
+ u8 madc;
+};
+
+/* ADC dividers can be disabled by cofiguring them to 0 */
+static const struct aic31xx_rate_divs aic31xx_divs[] = {
+ /* mclk rate pll: p j d dosr ndac mdac aors nadc madc */
+ /* 8k rate */
+ {12000000, 8000, 1, 8, 1920, 128, 48, 2, 128, 48, 2},
+ {24000000, 8000, 2, 8, 1920, 128, 48, 2, 128, 48, 2},
+ {25000000, 8000, 2, 7, 8643, 128, 48, 2, 128, 48, 2},
+ /* 11.025k rate */
+ {12000000, 11025, 1, 7, 5264, 128, 32, 2, 128, 32, 2},
+ {24000000, 11025, 2, 7, 5264, 128, 32, 2, 128, 32, 2},
+ {25000000, 11025, 2, 7, 2253, 128, 32, 2, 128, 32, 2},
+ /* 16k rate */
+ {12000000, 16000, 1, 8, 1920, 128, 24, 2, 128, 24, 2},
+ {24000000, 16000, 2, 8, 1920, 128, 24, 2, 128, 24, 2},
+ {25000000, 16000, 2, 7, 8643, 128, 24, 2, 128, 24, 2},
+ /* 22.05k rate */
+ {12000000, 22050, 1, 7, 5264, 128, 16, 2, 128, 16, 2},
+ {24000000, 22050, 2, 7, 5264, 128, 16, 2, 128, 16, 2},
+ {25000000, 22050, 2, 7, 2253, 128, 16, 2, 128, 16, 2},
+ /* 32k rate */
+ {12000000, 32000, 1, 8, 1920, 128, 12, 2, 128, 12, 2},
+ {24000000, 32000, 2, 8, 1920, 128, 12, 2, 128, 12, 2},
+ {25000000, 32000, 2, 7, 8643, 128, 12, 2, 128, 12, 2},
+ /* 44.1k rate */
+ {12000000, 44100, 1, 7, 5264, 128, 8, 2, 128, 8, 2},
+ {24000000, 44100, 2, 7, 5264, 128, 8, 2, 128, 8, 2},
+ {25000000, 44100, 2, 7, 2253, 128, 8, 2, 128, 8, 2},
+ /* 48k rate */
+ {12000000, 48000, 1, 8, 1920, 128, 8, 2, 128, 8, 2},
+ {24000000, 48000, 2, 8, 1920, 128, 8, 2, 128, 8, 2},
+ {25000000, 48000, 2, 7, 8643, 128, 8, 2, 128, 8, 2},
+ /* 88.2k rate */
+ {12000000, 88200, 1, 7, 5264, 64, 8, 2, 64, 8, 2},
+ {24000000, 88200, 2, 7, 5264, 64, 8, 2, 64, 8, 2},
+ {25000000, 88200, 2, 7, 2253, 64, 8, 2, 64, 8, 2},
+ /* 96k rate */
+ {12000000, 96000, 1, 8, 1920, 64, 8, 2, 64, 8, 2},
+ {24000000, 96000, 2, 8, 1920, 64, 8, 2, 64, 8, 2},
+ {25000000, 96000, 2, 7, 8643, 64, 8, 2, 64, 8, 2},
+ /* 176.4k rate */
+ {12000000, 176400, 1, 7, 5264, 32, 8, 2, 32, 8, 2},
+ {24000000, 176400, 2, 7, 5264, 32, 8, 2, 32, 8, 2},
+ {25000000, 176400, 2, 7, 2253, 32, 8, 2, 32, 8, 2},
+ /* 192k rate */
+ {12000000, 192000, 1, 8, 1920, 32, 8, 2, 32, 8, 2},
+ {24000000, 192000, 2, 8, 1920, 32, 8, 2, 32, 8, 2},
+ {25000000, 192000, 2, 7, 8643, 32, 8, 2, 32, 8, 2},
+};
+
+static const char * const ldac_in_text[] = {
+ "Off", "Left Data", "Right Data", "Mono"
+};
+
+static const char * const rdac_in_text[] = {
+ "Off", "Right Data", "Left Data", "Mono"
+};
+
+static SOC_ENUM_SINGLE_DECL(ldac_in_enum, AIC31XX_DACSETUP, 4, ldac_in_text);
+
+static SOC_ENUM_SINGLE_DECL(rdac_in_enum, AIC31XX_DACSETUP, 2, rdac_in_text);
+
+static const char * const mic_select_text[] = {
+ "Off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm"
+};
+
+static const
+SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, mic_select_text);
+static const
+SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, mic_select_text);
+static const
+SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, mic_select_text);
+
+static const
+SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text);
+static const
+SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, mic_select_text);
+
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0);
+static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0);
+static const DECLARE_TLV_DB_SCALE(adc_cgain_tlv, -2000, 50, 0);
+static const DECLARE_TLV_DB_SCALE(mic_pga_tlv, 0, 50, 0);
+static const DECLARE_TLV_DB_SCALE(hp_drv_tlv, 0, 100, 0);
+static const DECLARE_TLV_DB_SCALE(class_D_drv_tlv, 600, 600, 0);
+static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -6350, 50, 0);
+static const DECLARE_TLV_DB_SCALE(sp_vol_tlv, -6350, 50, 0);
+
+/*
+ * controls to be exported to the user space
+ */
+static const struct snd_kcontrol_new aic31xx_snd_controls[] = {
+ SOC_DOUBLE_R_S_TLV("DAC Playback Volume", AIC31XX_LDACVOL,
+ AIC31XX_RDACVOL, 0, -127, 48, 7, 0, dac_vol_tlv),
+
+ SOC_SINGLE_TLV("ADC Fine Capture Volume", AIC31XX_ADCFGA, 4, 4, 1,
+ adc_fgain_tlv),
+
+ SOC_SINGLE("ADC Capture Switch", AIC31XX_ADCFGA, 7, 1, 1),
+ SOC_DOUBLE_R_S_TLV("ADC Capture Volume", AIC31XX_ADCVOL, AIC31XX_ADCVOL,
+ 0, -24, 40, 6, 0, adc_cgain_tlv),
+
+ SOC_SINGLE_TLV("Mic PGA Capture Volume", AIC31XX_MICPGA, 0,
+ 119, 0, mic_pga_tlv),
+
+ SOC_DOUBLE_R("HP Driver Playback Switch", AIC31XX_HPLGAIN,
+ AIC31XX_HPRGAIN, 2, 1, 0),
+ SOC_DOUBLE_R_TLV("HP Driver Playback Volume", AIC31XX_HPLGAIN,
+ AIC31XX_HPRGAIN, 3, 0x09, 0, hp_drv_tlv),
+
+ SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL,
+ AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv),
+};
+
+static const struct snd_kcontrol_new aic311x_snd_controls[] = {
+ SOC_DOUBLE_R("Speaker Driver Playback Switch", AIC31XX_SPLGAIN,
+ AIC31XX_SPRGAIN, 2, 1, 0),
+ SOC_DOUBLE_R_TLV("Speaker Driver Playback Volume", AIC31XX_SPLGAIN,
+ AIC31XX_SPRGAIN, 3, 3, 0, class_D_drv_tlv),
+
+ SOC_DOUBLE_R_TLV("Speaker Analog Playback Volume", AIC31XX_LANALOGSPL,
+ AIC31XX_RANALOGSPR, 0, 0x7F, 1, sp_vol_tlv),
+};
+
+static const struct snd_kcontrol_new aic310x_snd_controls[] = {
+ SOC_SINGLE("Speaker Driver Playback Switch", AIC31XX_SPLGAIN,
+ 2, 1, 0),
+ SOC_SINGLE_TLV("Speaker Driver Playback Volume", AIC31XX_SPLGAIN,
+ 3, 3, 0, class_D_drv_tlv),
+
+ SOC_SINGLE_TLV("Speaker Analog Playback Volume", AIC31XX_LANALOGSPL,
+ 0, 0x7F, 1, sp_vol_tlv),
+};
+
+static const struct snd_kcontrol_new ldac_in_control =
+ SOC_DAPM_ENUM("DAC Left Input", ldac_in_enum);
+
+static const struct snd_kcontrol_new rdac_in_control =
+ SOC_DAPM_ENUM("DAC Right Input", rdac_in_enum);
+
+static int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg,
+ unsigned int mask, unsigned int wbits, int sleep,
+ int count)
+{
+ unsigned int bits;
+ int counter = count;
+ int ret = regmap_read(aic31xx->regmap, reg, &bits);
+ while ((bits & mask) != wbits && counter && !ret) {
+ usleep_range(sleep, sleep * 2);
+ ret = regmap_read(aic31xx->regmap, reg, &bits);
+ counter--;
+ }
+ if ((bits & mask) != wbits) {
+ dev_err(aic31xx->dev,
+ "%s: Failed! 0x%x was 0x%x expected 0x%x (%d, 0x%x, %d us)\n",
+ __func__, reg, bits, wbits, ret, mask,
+ (count - counter) * sleep);
+ ret = -1;
+ }
+ return ret;
+}
+
+#define WIDGET_BIT(reg, shift) (((shift) << 8) | (reg))
+
+static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(w->codec);
+ unsigned int reg = AIC31XX_DACFLAG1;
+ unsigned int mask;
+
+ switch (WIDGET_BIT(w->reg, w->shift)) {
+ case WIDGET_BIT(AIC31XX_DACSETUP, 7):
+ mask = AIC31XX_LDACPWRSTATUS_MASK;
+ break;
+ case WIDGET_BIT(AIC31XX_DACSETUP, 6):
+ mask = AIC31XX_RDACPWRSTATUS_MASK;
+ break;
+ case WIDGET_BIT(AIC31XX_HPDRIVER, 7):
+ mask = AIC31XX_HPLDRVPWRSTATUS_MASK;
+ break;
+ case WIDGET_BIT(AIC31XX_HPDRIVER, 6):
+ mask = AIC31XX_HPRDRVPWRSTATUS_MASK;
+ break;
+ case WIDGET_BIT(AIC31XX_SPKAMP, 7):
+ mask = AIC31XX_SPLDRVPWRSTATUS_MASK;
+ break;
+ case WIDGET_BIT(AIC31XX_SPKAMP, 6):
+ mask = AIC31XX_SPRDRVPWRSTATUS_MASK;
+ break;
+ case WIDGET_BIT(AIC31XX_ADCSETUP, 7):
+ mask = AIC31XX_ADCPWRSTATUS_MASK;
+ reg = AIC31XX_ADCFLAG;
+ break;
+ default:
+ dev_err(w->codec->dev, "Unknown widget '%s' calling %s\n",
+ w->name, __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ return aic31xx_wait_bits(aic31xx, reg, mask, mask, 5000, 100);
+ case SND_SOC_DAPM_POST_PMD:
+ return aic31xx_wait_bits(aic31xx, reg, mask, 0, 5000, 100);
+ default:
+ dev_dbg(w->codec->dev,
+ "Unhandled dapm widget event %d from %s\n",
+ event, w->name);
+ }
+ return 0;
+}
+
+static const struct snd_kcontrol_new left_output_switches[] = {
+ SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0),
+ SOC_DAPM_SINGLE("From MIC1LP", AIC31XX_DACMIXERROUTE, 5, 1, 0),
+ SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_output_switches[] = {
+ SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0),
+ SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new p_term_mic1lp =
+ SOC_DAPM_ENUM("MIC1LP P-Terminal", mic1lp_p_enum);
+
+static const struct snd_kcontrol_new p_term_mic1rp =
+ SOC_DAPM_ENUM("MIC1RP P-Terminal", mic1rp_p_enum);
+
+static const struct snd_kcontrol_new p_term_mic1lm =
+ SOC_DAPM_ENUM("MIC1LM P-Terminal", mic1lm_p_enum);
+
+static const struct snd_kcontrol_new m_term_mic1lm =
+ SOC_DAPM_ENUM("MIC1LM M-Terminal", mic1lm_m_enum);
+
+static const struct snd_kcontrol_new aic31xx_dapm_hpl_switch =
+ SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGHPL, 7, 1, 0);
+
+static const struct snd_kcontrol_new aic31xx_dapm_hpr_switch =
+ SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGHPR, 7, 1, 0);
+
+static const struct snd_kcontrol_new aic31xx_dapm_spl_switch =
+ SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGSPL, 7, 1, 0);
+
+static const struct snd_kcontrol_new aic31xx_dapm_spr_switch =
+ SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGSPR, 7, 1, 0);
+
+static int mic_bias_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /* change mic bias voltage to user defined */
+ snd_soc_update_bits(codec, AIC31XX_MICBIAS,
+ AIC31XX_MICBIAS_MASK,
+ aic31xx->pdata.micbias_vg <<
+ AIC31XX_MICBIAS_SHIFT);
+ dev_dbg(codec->dev, "%s: turned on\n", __func__);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ /* turn mic bias off */
+ snd_soc_update_bits(codec, AIC31XX_MICBIAS,
+ AIC31XX_MICBIAS_MASK, 0);
+ dev_dbg(codec->dev, "%s: turned off\n", __func__);
+ break;
+ }
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = {
+ SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_MUX("DAC Left Input",
+ SND_SOC_NOPM, 0, 0, &ldac_in_control),
+ SND_SOC_DAPM_MUX("DAC Right Input",
+ SND_SOC_NOPM, 0, 0, &rdac_in_control),
+ /* DACs */
+ SND_SOC_DAPM_DAC_E("DAC Left", "Left Playback",
+ AIC31XX_DACSETUP, 7, 0, aic31xx_dapm_power_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_DAC_E("DAC Right", "Right Playback",
+ AIC31XX_DACSETUP, 6, 0, aic31xx_dapm_power_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* Output Mixers */
+ SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0,
+ left_output_switches,
+ ARRAY_SIZE(left_output_switches)),
+ SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0,
+ right_output_switches,
+ ARRAY_SIZE(right_output_switches)),
+
+ SND_SOC_DAPM_SWITCH("HP Left", SND_SOC_NOPM, 0, 0,
+ &aic31xx_dapm_hpl_switch),
+ SND_SOC_DAPM_SWITCH("HP Right", SND_SOC_NOPM, 0, 0,
+ &aic31xx_dapm_hpr_switch),
+
+ /* Output drivers */
+ SND_SOC_DAPM_OUT_DRV_E("HPL Driver", AIC31XX_HPDRIVER, 7, 0,
+ NULL, 0, aic31xx_dapm_power_event,
+ SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_OUT_DRV_E("HPR Driver", AIC31XX_HPDRIVER, 6, 0,
+ NULL, 0, aic31xx_dapm_power_event,
+ SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+
+ /* ADC */
+ SND_SOC_DAPM_ADC_E("ADC", "Capture", AIC31XX_ADCSETUP, 7, 0,
+ aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* Input Selection to MIC_PGA */
+ SND_SOC_DAPM_MUX("MIC1LP P-Terminal", SND_SOC_NOPM, 0, 0,
+ &p_term_mic1lp),
+ SND_SOC_DAPM_MUX("MIC1RP P-Terminal", SND_SOC_NOPM, 0, 0,
+ &p_term_mic1rp),
+ SND_SOC_DAPM_MUX("MIC1LM P-Terminal", SND_SOC_NOPM, 0, 0,
+ &p_term_mic1lm),
+
+ SND_SOC_DAPM_MUX("MIC1LM M-Terminal", SND_SOC_NOPM, 0, 0,
+ &m_term_mic1lm),
+ /* Enabling & Disabling MIC Gain Ctl */
+ SND_SOC_DAPM_PGA("MIC_GAIN_CTL", AIC31XX_MICPGA,
+ 7, 1, NULL, 0),
+
+ /* Mic Bias */
+ SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, mic_bias_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+ /* Outputs */
+ SND_SOC_DAPM_OUTPUT("HPL"),
+ SND_SOC_DAPM_OUTPUT("HPR"),
+
+ /* Inputs */
+ SND_SOC_DAPM_INPUT("MIC1LP"),
+ SND_SOC_DAPM_INPUT("MIC1RP"),
+ SND_SOC_DAPM_INPUT("MIC1LM"),
+};
+
+static const struct snd_soc_dapm_widget aic311x_dapm_widgets[] = {
+ /* AIC3111 and AIC3110 have stereo class-D amplifier */
+ SND_SOC_DAPM_OUT_DRV_E("SPL ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0,
+ aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_OUT_DRV_E("SPR ClassD", AIC31XX_SPKAMP, 6, 0, NULL, 0,
+ aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SWITCH("Speaker Left", SND_SOC_NOPM, 0, 0,
+ &aic31xx_dapm_spl_switch),
+ SND_SOC_DAPM_SWITCH("Speaker Right", SND_SOC_NOPM, 0, 0,
+ &aic31xx_dapm_spr_switch),
+ SND_SOC_DAPM_OUTPUT("SPL"),
+ SND_SOC_DAPM_OUTPUT("SPR"),
+};
+
+/* AIC3100 and AIC3120 have only mono class-D amplifier */
+static const struct snd_soc_dapm_widget aic310x_dapm_widgets[] = {
+ SND_SOC_DAPM_OUT_DRV_E("SPK ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0,
+ aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SWITCH("Speaker", SND_SOC_NOPM, 0, 0,
+ &aic31xx_dapm_spl_switch),
+ SND_SOC_DAPM_OUTPUT("SPK"),
+};
+
+static const struct snd_soc_dapm_route
+aic31xx_audio_map[] = {
+ /* DAC Input Routing */
+ {"DAC Left Input", "Left Data", "DAC IN"},
+ {"DAC Left Input", "Right Data", "DAC IN"},
+ {"DAC Left Input", "Mono", "DAC IN"},
+ {"DAC Right Input", "Left Data", "DAC IN"},
+ {"DAC Right Input", "Right Data", "DAC IN"},
+ {"DAC Right Input", "Mono", "DAC IN"},
+ {"DAC Left", NULL, "DAC Left Input"},
+ {"DAC Right", NULL, "DAC Right Input"},
+
+ /* Mic input */
+ {"MIC1LP P-Terminal", "FFR 10 Ohm", "MIC1LP"},
+ {"MIC1LP P-Terminal", "FFR 20 Ohm", "MIC1LP"},
+ {"MIC1LP P-Terminal", "FFR 40 Ohm", "MIC1LP"},
+ {"MIC1RP P-Terminal", "FFR 10 Ohm", "MIC1RP"},
+ {"MIC1RP P-Terminal", "FFR 20 Ohm", "MIC1RP"},
+ {"MIC1RP P-Terminal", "FFR 40 Ohm", "MIC1RP"},
+ {"MIC1LM P-Terminal", "FFR 10 Ohm", "MIC1LM"},
+ {"MIC1LM P-Terminal", "FFR 20 Ohm", "MIC1LM"},
+ {"MIC1LM P-Terminal", "FFR 40 Ohm", "MIC1LM"},
+
+ {"MIC1LM M-Terminal", "FFR 10 Ohm", "MIC1LM"},
+ {"MIC1LM M-Terminal", "FFR 20 Ohm", "MIC1LM"},
+ {"MIC1LM M-Terminal", "FFR 40 Ohm", "MIC1LM"},
+
+ {"MIC_GAIN_CTL", NULL, "MIC1LP P-Terminal"},
+ {"MIC_GAIN_CTL", NULL, "MIC1RP P-Terminal"},
+ {"MIC_GAIN_CTL", NULL, "MIC1LM P-Terminal"},
+ {"MIC_GAIN_CTL", NULL, "MIC1LM M-Terminal"},
+
+ {"ADC", NULL, "MIC_GAIN_CTL"},
+
+ /* Left Output */
+ {"Output Left", "From Left DAC", "DAC Left"},
+ {"Output Left", "From MIC1LP", "MIC1LP"},
+ {"Output Left", "From MIC1RP", "MIC1RP"},
+
+ /* Right Output */
+ {"Output Right", "From Right DAC", "DAC Right"},
+ {"Output Right", "From MIC1RP", "MIC1RP"},
+
+ /* HPL path */
+ {"HP Left", "Switch", "Output Left"},
+ {"HPL Driver", NULL, "HP Left"},
+ {"HPL", NULL, "HPL Driver"},
+
+ /* HPR path */
+ {"HP Right", "Switch", "Output Right"},
+ {"HPR Driver", NULL, "HP Right"},
+ {"HPR", NULL, "HPR Driver"},
+};
+
+static const struct snd_soc_dapm_route
+aic311x_audio_map[] = {
+ /* SP L path */
+ {"Speaker Left", "Switch", "Output Left"},
+ {"SPL ClassD", NULL, "Speaker Left"},
+ {"SPL", NULL, "SPL ClassD"},
+
+ /* SP R path */
+ {"Speaker Right", "Switch", "Output Right"},
+ {"SPR ClassD", NULL, "Speaker Right"},
+ {"SPR", NULL, "SPR ClassD"},
+};
+
+static const struct snd_soc_dapm_route
+aic310x_audio_map[] = {
+ /* SP L path */
+ {"Speaker", "Switch", "Output Left"},
+ {"SPK ClassD", NULL, "Speaker"},
+ {"SPK", NULL, "SPK ClassD"},
+};
+
+static int aic31xx_add_controls(struct snd_soc_codec *codec)
+{
+ int ret = 0;
+ struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+
+ if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT)
+ ret = snd_soc_add_codec_controls(
+ codec, aic311x_snd_controls,
+ ARRAY_SIZE(aic311x_snd_controls));
+ else
+ ret = snd_soc_add_codec_controls(
+ codec, aic310x_snd_controls,
+ ARRAY_SIZE(aic310x_snd_controls));
+
+ return ret;
+}
+
+static int aic31xx_add_widgets(struct snd_soc_codec *codec)
+{
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
+ if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) {
+ ret = snd_soc_dapm_new_controls(
+ dapm, aic311x_dapm_widgets,
+ ARRAY_SIZE(aic311x_dapm_widgets));
+ if (ret)
+ return ret;
+
+ ret = snd_soc_dapm_add_routes(dapm, aic311x_audio_map,
+ ARRAY_SIZE(aic311x_audio_map));
+ if (ret)
+ return ret;
+ } else {
+ ret = snd_soc_dapm_new_controls(
+ dapm, aic310x_dapm_widgets,
+ ARRAY_SIZE(aic310x_dapm_widgets));
+ if (ret)
+ return ret;
+
+ ret = snd_soc_dapm_add_routes(dapm, aic310x_audio_map,
+ ARRAY_SIZE(aic310x_audio_map));
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int aic31xx_setup_pll(struct snd_soc_codec *codec,
+ struct snd_pcm_hw_params *params)
+{
+ struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+ int bclk_n = 0;
+ int i;
+
+ /* Use PLL as CODEC_CLKIN and DAC_CLK as BDIV_CLKIN */
+ snd_soc_update_bits(codec, AIC31XX_CLKMUX,
+ AIC31XX_CODEC_CLKIN_MASK, AIC31XX_CODEC_CLKIN_PLL);
+ snd_soc_update_bits(codec, AIC31XX_IFACE2,
+ AIC31XX_BDIVCLK_MASK, AIC31XX_DAC2BCLK);
+
+ for (i = 0; i < ARRAY_SIZE(aic31xx_divs); i++) {
+ if (aic31xx_divs[i].rate == params_rate(params) &&
+ aic31xx_divs[i].mclk == aic31xx->sysclk)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(aic31xx_divs)) {
+ dev_err(codec->dev, "%s: Sampling rate %u not supported\n",
+ __func__, params_rate(params));
+ return -EINVAL;
+ }
+
+ /* PLL configuration */
+ snd_soc_update_bits(codec, AIC31XX_PLLPR, AIC31XX_PLL_MASK,
+ (aic31xx_divs[i].p_val << 4) | 0x01);
+ snd_soc_write(codec, AIC31XX_PLLJ, aic31xx_divs[i].pll_j);
+
+ snd_soc_write(codec, AIC31XX_PLLDMSB,
+ aic31xx_divs[i].pll_d >> 8);
+ snd_soc_write(codec, AIC31XX_PLLDLSB,
+ aic31xx_divs[i].pll_d & 0xff);
+
+ /* DAC dividers configuration */
+ snd_soc_update_bits(codec, AIC31XX_NDAC, AIC31XX_PLL_MASK,
+ aic31xx_divs[i].ndac);
+ snd_soc_update_bits(codec, AIC31XX_MDAC, AIC31XX_PLL_MASK,
+ aic31xx_divs[i].mdac);
+
+ snd_soc_write(codec, AIC31XX_DOSRMSB, aic31xx_divs[i].dosr >> 8);
+ snd_soc_write(codec, AIC31XX_DOSRLSB, aic31xx_divs[i].dosr & 0xff);
+
+ /* ADC dividers configuration. Write reset value 1 if not used. */
+ snd_soc_update_bits(codec, AIC31XX_NADC, AIC31XX_PLL_MASK,
+ aic31xx_divs[i].nadc ? aic31xx_divs[i].nadc : 1);
+ snd_soc_update_bits(codec, AIC31XX_MADC, AIC31XX_PLL_MASK,
+ aic31xx_divs[i].madc ? aic31xx_divs[i].madc : 1);
+
+ snd_soc_write(codec, AIC31XX_AOSR, aic31xx_divs[i].aosr);
+
+ /* Bit clock divider configuration. */
+ bclk_n = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac)
+ / snd_soc_params_to_frame_size(params);
+ if (bclk_n == 0) {
+ dev_err(codec->dev, "%s: Not enough BLCK bandwidth\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, AIC31XX_BCLKN,
+ AIC31XX_PLL_MASK, bclk_n);
+
+ aic31xx->rate_div_line = i;
+
+ dev_dbg(codec->dev,
+ "pll %d.%04d/%d dosr %d n %d m %d aosr %d n %d m %d bclk_n %d\n",
+ aic31xx_divs[i].pll_j, aic31xx_divs[i].pll_d,
+ aic31xx_divs[i].p_val, aic31xx_divs[i].dosr,
+ aic31xx_divs[i].ndac, aic31xx_divs[i].mdac,
+ aic31xx_divs[i].aosr, aic31xx_divs[i].nadc,
+ aic31xx_divs[i].madc, bclk_n);
+
+ return 0;
+}
+
+static int aic31xx_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;
+ u8 data = 0;
+
+ dev_dbg(codec->dev, "## %s: format %d width %d rate %d\n",
+ __func__, params_format(params), params_width(params),
+ params_rate(params));
+
+ switch (params_width(params)) {
+ case 16:
+ break;
+ case 20:
+ data = (AIC31XX_WORD_LEN_20BITS <<
+ AIC31XX_IFACE1_DATALEN_SHIFT);
+ break;
+ case 24:
+ data = (AIC31XX_WORD_LEN_24BITS <<
+ AIC31XX_IFACE1_DATALEN_SHIFT);
+ break;
+ case 32:
+ data = (AIC31XX_WORD_LEN_32BITS <<
+ AIC31XX_IFACE1_DATALEN_SHIFT);
+ break;
+ default:
+ dev_err(codec->dev, "%s: Unsupported format %d\n",
+ __func__, params_format(params));
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, AIC31XX_IFACE1,
+ AIC31XX_IFACE1_DATALEN_MASK,
+ data);
+
+ return aic31xx_setup_pll(codec, params);
+}
+
+static int aic31xx_dac_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+
+ if (mute) {
+ snd_soc_update_bits(codec, AIC31XX_DACMUTE,
+ AIC31XX_DACMUTE_MASK,
+ AIC31XX_DACMUTE_MASK);
+ } else {
+ snd_soc_update_bits(codec, AIC31XX_DACMUTE,
+ AIC31XX_DACMUTE_MASK, 0x0);
+ }
+
+ return 0;
+}
+
+static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u8 iface_reg1 = 0;
+ u8 iface_reg3 = 0;
+ u8 dsp_a_val = 0;
+
+ dev_dbg(codec->dev, "## %s: fmt = 0x%x\n", __func__, fmt);
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ iface_reg1 |= AIC31XX_BCLK_MASTER | AIC31XX_WCLK_MASTER;
+ break;
+ default:
+ dev_alert(codec->dev, "Invalid DAI master/slave interface\n");
+ return -EINVAL;
+ }
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ dsp_a_val = 0x1;
+ case SND_SOC_DAIFMT_DSP_B:
+ /* NOTE: BCLKINV bit value 1 equas NB and 0 equals IB */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ iface_reg3 |= AIC31XX_BCLKINV_MASK;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ break;
+ default:
+ return -EINVAL;
+ }
+ iface_reg1 |= (AIC31XX_DSP_MODE <<
+ AIC31XX_IFACE1_DATATYPE_SHIFT);
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ iface_reg1 |= (AIC31XX_RIGHT_JUSTIFIED_MODE <<
+ AIC31XX_IFACE1_DATATYPE_SHIFT);
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iface_reg1 |= (AIC31XX_LEFT_JUSTIFIED_MODE <<
+ AIC31XX_IFACE1_DATATYPE_SHIFT);
+ break;
+ default:
+ dev_err(codec->dev, "Invalid DAI interface format\n");
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, AIC31XX_IFACE1,
+ AIC31XX_IFACE1_DATATYPE_MASK |
+ AIC31XX_IFACE1_MASTER_MASK,
+ iface_reg1);
+ snd_soc_update_bits(codec, AIC31XX_DATA_OFFSET,
+ AIC31XX_DATA_OFFSET_MASK,
+ dsp_a_val);
+ snd_soc_update_bits(codec, AIC31XX_IFACE2,
+ AIC31XX_BCLKINV_MASK,
+ iface_reg3);
+
+ return 0;
+}
+
+static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+ int i;
+
+ dev_dbg(codec->dev, "## %s: clk_id = %d, freq = %d, dir = %d\n",
+ __func__, clk_id, freq, dir);
+
+ for (i = 0; aic31xx_divs[i].mclk != freq; i++) {
+ if (i == ARRAY_SIZE(aic31xx_divs)) {
+ dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n",
+ __func__, freq);
+ return -EINVAL;
+ }
+ }
+
+ /* set clock on MCLK, BCLK, or GPIO1 as PLL input */
+ snd_soc_update_bits(codec, AIC31XX_CLKMUX, AIC31XX_PLL_CLKIN_MASK,
+ clk_id << AIC31XX_PLL_CLKIN_SHIFT);
+
+ aic31xx->sysclk = freq;
+ return 0;
+}
+
+static int aic31xx_regulator_event(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct aic31xx_disable_nb *disable_nb =
+ container_of(nb, struct aic31xx_disable_nb, nb);
+ struct aic31xx_priv *aic31xx = disable_nb->aic31xx;
+
+ if (event & REGULATOR_EVENT_DISABLE) {
+ /*
+ * Put codec to reset and as at least one of the
+ * supplies was disabled.
+ */
+ if (gpio_is_valid(aic31xx->pdata.gpio_reset))
+ gpio_set_value(aic31xx->pdata.gpio_reset, 0);
+
+ regcache_mark_dirty(aic31xx->regmap);
+ dev_dbg(aic31xx->dev, "## %s: DISABLE received\n", __func__);
+ }
+
+ return 0;
+}
+
+static void aic31xx_clk_on(struct snd_soc_codec *codec)
+{
+ struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+ u8 mask = AIC31XX_PM_MASK;
+ u8 on = AIC31XX_PM_MASK;
+
+ dev_dbg(codec->dev, "codec clock -> on (rate %d)\n",
+ aic31xx_divs[aic31xx->rate_div_line].rate);
+ snd_soc_update_bits(codec, AIC31XX_PLLPR, mask, on);
+ mdelay(10);
+ snd_soc_update_bits(codec, AIC31XX_NDAC, mask, on);
+ snd_soc_update_bits(codec, AIC31XX_MDAC, mask, on);
+ if (aic31xx_divs[aic31xx->rate_div_line].nadc)
+ snd_soc_update_bits(codec, AIC31XX_NADC, mask, on);
+ if (aic31xx_divs[aic31xx->rate_div_line].madc)
+ snd_soc_update_bits(codec, AIC31XX_MADC, mask, on);
+ snd_soc_update_bits(codec, AIC31XX_BCLKN, mask, on);
+}
+
+static void aic31xx_clk_off(struct snd_soc_codec *codec)
+{
+ u8 mask = AIC31XX_PM_MASK;
+ u8 off = 0;
+
+ dev_dbg(codec->dev, "codec clock -> off\n");
+ snd_soc_update_bits(codec, AIC31XX_BCLKN, mask, off);
+ snd_soc_update_bits(codec, AIC31XX_MADC, mask, off);
+ snd_soc_update_bits(codec, AIC31XX_NADC, mask, off);
+ snd_soc_update_bits(codec, AIC31XX_MDAC, mask, off);
+ snd_soc_update_bits(codec, AIC31XX_NDAC, mask, off);
+ snd_soc_update_bits(codec, AIC31XX_PLLPR, mask, off);
+}
+
+static int aic31xx_power_on(struct snd_soc_codec *codec)
+{
+ struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(aic31xx->supplies),
+ aic31xx->supplies);
+ if (ret)
+ return ret;
+
+ if (gpio_is_valid(aic31xx->pdata.gpio_reset)) {
+ gpio_set_value(aic31xx->pdata.gpio_reset, 1);
+ udelay(100);
+ }
+ regcache_cache_only(aic31xx->regmap, false);
+ ret = regcache_sync(aic31xx->regmap);
+ if (ret != 0) {
+ dev_err(codec->dev,
+ "Failed to restore cache: %d\n", ret);
+ regcache_cache_only(aic31xx->regmap, true);
+ regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies),
+ aic31xx->supplies);
+ return ret;
+ }
+ return 0;
+}
+
+static int aic31xx_power_off(struct snd_soc_codec *codec)
+{
+ struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
+ regcache_cache_only(aic31xx->regmap, true);
+ ret = regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies),
+ aic31xx->supplies);
+
+ return ret;
+}
+
+static int aic31xx_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ dev_dbg(codec->dev, "## %s: %d -> %d\n", __func__,
+ codec->dapm.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)
+ aic31xx_clk_on(codec);
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ switch (codec->dapm.bias_level) {
+ case SND_SOC_BIAS_OFF:
+ aic31xx_power_on(codec);
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ aic31xx_clk_off(codec);
+ break;
+ default:
+ BUG();
+ }
+ break;
+ case SND_SOC_BIAS_OFF:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
+ aic31xx_power_off(codec);
+ break;
+ }
+ codec->dapm.bias_level = level;
+
+ return 0;
+}
+
+static int aic31xx_suspend(struct snd_soc_codec *codec)
+{
+ aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int aic31xx_resume(struct snd_soc_codec *codec)
+{
+ aic31xx_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ return 0;
+}
+
+static int aic31xx_codec_probe(struct snd_soc_codec *codec)
+{
+ int ret = 0;
+ struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+ int i;
+
+ dev_dbg(aic31xx->dev, "## %s\n", __func__);
+
+ aic31xx = snd_soc_codec_get_drvdata(codec);
+
+ aic31xx->codec = codec;
+
+ for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) {
+ aic31xx->disable_nb[i].nb.notifier_call =
+ aic31xx_regulator_event;
+ aic31xx->disable_nb[i].aic31xx = aic31xx;
+ ret = regulator_register_notifier(aic31xx->supplies[i].consumer,
+ &aic31xx->disable_nb[i].nb);
+ if (ret) {
+ dev_err(codec->dev,
+ "Failed to request regulator notifier: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ regcache_cache_only(aic31xx->regmap, true);
+ regcache_mark_dirty(aic31xx->regmap);
+
+ ret = aic31xx_add_controls(codec);
+ if (ret)
+ return ret;
+
+ ret = aic31xx_add_widgets(codec);
+
+ return ret;
+}
+
+static int aic31xx_codec_remove(struct snd_soc_codec *codec)
+{
+ struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+ int i;
+ /* power down chip */
+ aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++)
+ regulator_unregister_notifier(aic31xx->supplies[i].consumer,
+ &aic31xx->disable_nb[i].nb);
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_driver_aic31xx = {
+ .probe = aic31xx_codec_probe,
+ .remove = aic31xx_codec_remove,
+ .suspend = aic31xx_suspend,
+ .resume = aic31xx_resume,
+ .set_bias_level = aic31xx_set_bias_level,
+ .controls = aic31xx_snd_controls,
+ .num_controls = ARRAY_SIZE(aic31xx_snd_controls),
+ .dapm_widgets = aic31xx_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(aic31xx_dapm_widgets),
+ .dapm_routes = aic31xx_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(aic31xx_audio_map),
+};
+
+static struct snd_soc_dai_ops aic31xx_dai_ops = {
+ .hw_params = aic31xx_hw_params,
+ .set_sysclk = aic31xx_set_dai_sysclk,
+ .set_fmt = aic31xx_set_dai_fmt,
+ .digital_mute = aic31xx_dac_mute,
+};
+
+static struct snd_soc_dai_driver aic31xx_dai_driver[] = {
+ {
+ .name = "tlv320aic31xx-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AIC31XX_RATES,
+ .formats = AIC31XX_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AIC31XX_RATES,
+ .formats = AIC31XX_FORMATS,
+ },
+ .ops = &aic31xx_dai_ops,
+ .symmetric_rates = 1,
+ }
+};
+
+#if defined(CONFIG_OF)
+static const struct of_device_id tlv320aic31xx_of_match[] = {
+ { .compatible = "ti,tlv320aic310x" },
+ { .compatible = "ti,tlv320aic311x" },
+ { .compatible = "ti,tlv320aic3100" },
+ { .compatible = "ti,tlv320aic3110" },
+ { .compatible = "ti,tlv320aic3120" },
+ { .compatible = "ti,tlv320aic3111" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, tlv320aic31xx_of_match);
+
+static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx)
+{
+ struct device_node *np = aic31xx->dev->of_node;
+ unsigned int value = MICBIAS_2_0V;
+ int ret;
+
+ of_property_read_u32(np, "ai31xx-micbias-vg", &value);
+ switch (value) {
+ case MICBIAS_2_0V:
+ case MICBIAS_2_5V:
+ case MICBIAS_AVDDV:
+ aic31xx->pdata.micbias_vg = value;
+ break;
+ default:
+ dev_err(aic31xx->dev,
+ "Bad ai31xx-micbias-vg value %d DT\n",
+ value);
+ aic31xx->pdata.micbias_vg = MICBIAS_2_0V;
+ }
+
+ ret = of_get_named_gpio(np, "gpio-reset", 0);
+ if (ret > 0)
+ aic31xx->pdata.gpio_reset = ret;
+}
+#else /* CONFIG_OF */
+static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx)
+{
+}
+#endif /* CONFIG_OF */
+
+static void aic31xx_device_init(struct aic31xx_priv *aic31xx)
+{
+ int ret, i;
+
+ dev_set_drvdata(aic31xx->dev, aic31xx);
+
+ if (dev_get_platdata(aic31xx->dev))
+ memcpy(&aic31xx->pdata, dev_get_platdata(aic31xx->dev),
+ sizeof(aic31xx->pdata));
+ else if (aic31xx->dev->of_node)
+ aic31xx_pdata_from_of(aic31xx);
+
+ if (aic31xx->pdata.gpio_reset) {
+ ret = devm_gpio_request_one(aic31xx->dev,
+ aic31xx->pdata.gpio_reset,
+ GPIOF_OUT_INIT_HIGH,
+ "aic31xx-reset-pin");
+ if (ret < 0) {
+ dev_err(aic31xx->dev, "not able to acquire gpio\n");
+ return;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++)
+ aic31xx->supplies[i].supply = aic31xx_supply_names[i];
+
+ ret = devm_regulator_bulk_get(aic31xx->dev,
+ ARRAY_SIZE(aic31xx->supplies),
+ aic31xx->supplies);
+ if (ret != 0)
+ dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret);
+
+}
+
+static int aic31xx_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct aic31xx_priv *aic31xx;
+ int ret;
+ const struct regmap_config *regmap_config;
+
+ dev_dbg(&i2c->dev, "## %s: %s codec_type = %d\n", __func__,
+ id->name, (int) id->driver_data);
+
+ regmap_config = &aic31xx_i2c_regmap;
+
+ aic31xx = devm_kzalloc(&i2c->dev, sizeof(*aic31xx), GFP_KERNEL);
+ if (aic31xx == NULL)
+ return -ENOMEM;
+
+ aic31xx->regmap = devm_regmap_init_i2c(i2c, regmap_config);
+ if (IS_ERR(aic31xx->regmap)) {
+ ret = PTR_ERR(aic31xx->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+ aic31xx->dev = &i2c->dev;
+
+ aic31xx->pdata.codec_type = id->driver_data;
+
+ aic31xx_device_init(aic31xx);
+
+ return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx,
+ aic31xx_dai_driver,
+ ARRAY_SIZE(aic31xx_dai_driver));
+}
+
+static int aic31xx_i2c_remove(struct i2c_client *i2c)
+{
+ snd_soc_unregister_codec(&i2c->dev);
+ return 0;
+}
+
+static const struct i2c_device_id aic31xx_i2c_id[] = {
+ { "tlv320aic310x", AIC3100 },
+ { "tlv320aic311x", AIC3110 },
+ { "tlv320aic3100", AIC3100 },
+ { "tlv320aic3110", AIC3110 },
+ { "tlv320aic3120", AIC3120 },
+ { "tlv320aic3111", AIC3111 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id);
+
+static struct i2c_driver aic31xx_i2c_driver = {
+ .driver = {
+ .name = "tlv320aic31xx-codec",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tlv320aic31xx_of_match),
+ },
+ .probe = aic31xx_i2c_probe,
+ .remove = aic31xx_i2c_remove,
+ .id_table = aic31xx_i2c_id,
+};
+
+module_i2c_driver(aic31xx_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC TLV320AIC3111 codec driver");
+MODULE_AUTHOR("Jyri Sarha");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h
new file mode 100644
index 00000000000..52ed57c69df
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic31xx.h
@@ -0,0 +1,258 @@
+/*
+ * ALSA SoC TLV320AIC31XX codec driver
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+#ifndef _TLV320AIC31XX_H
+#define _TLV320AIC31XX_H
+
+#define AIC31XX_RATES SNDRV_PCM_RATE_8000_192000
+
+#define AIC31XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
+ | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+
+#define AIC31XX_STEREO_CLASS_D_BIT 0x1
+#define AIC31XX_MINIDSP_BIT 0x2
+
+enum aic31xx_type {
+ AIC3100 = 0,
+ AIC3110 = AIC31XX_STEREO_CLASS_D_BIT,
+ AIC3120 = AIC31XX_MINIDSP_BIT,
+ AIC3111 = (AIC31XX_STEREO_CLASS_D_BIT | AIC31XX_MINIDSP_BIT),
+};
+
+struct aic31xx_pdata {
+ enum aic31xx_type codec_type;
+ unsigned int gpio_reset;
+ int micbias_vg;
+};
+
+/* Page Control Register */
+#define AIC31XX_PAGECTL 0x00
+
+/* Page 0 Registers */
+/* Software reset register */
+#define AIC31XX_RESET 0x01
+/* OT FLAG register */
+#define AIC31XX_OT_FLAG 0x03
+/* Clock clock Gen muxing, Multiplexers*/
+#define AIC31XX_CLKMUX 0x04
+/* PLL P and R-VAL register */
+#define AIC31XX_PLLPR 0x05
+/* PLL J-VAL register */
+#define AIC31XX_PLLJ 0x06
+/* PLL D-VAL MSB register */
+#define AIC31XX_PLLDMSB 0x07
+/* PLL D-VAL LSB register */
+#define AIC31XX_PLLDLSB 0x08
+/* DAC NDAC_VAL register*/
+#define AIC31XX_NDAC 0x0B
+/* DAC MDAC_VAL register */
+#define AIC31XX_MDAC 0x0C
+/* DAC OSR setting register 1, MSB value */
+#define AIC31XX_DOSRMSB 0x0D
+/* DAC OSR setting register 2, LSB value */
+#define AIC31XX_DOSRLSB 0x0E
+#define AIC31XX_MINI_DSP_INPOL 0x10
+/* Clock setting register 8, PLL */
+#define AIC31XX_NADC 0x12
+/* Clock setting register 9, PLL */
+#define AIC31XX_MADC 0x13
+/* ADC Oversampling (AOSR) Register */
+#define AIC31XX_AOSR 0x14
+/* Clock setting register 9, Multiplexers */
+#define AIC31XX_CLKOUTMUX 0x19
+/* Clock setting register 10, CLOCKOUT M divider value */
+#define AIC31XX_CLKOUTMVAL 0x1A
+/* Audio Interface Setting Register 1 */
+#define AIC31XX_IFACE1 0x1B
+/* Audio Data Slot Offset Programming */
+#define AIC31XX_DATA_OFFSET 0x1C
+/* Audio Interface Setting Register 2 */
+#define AIC31XX_IFACE2 0x1D
+/* Clock setting register 11, BCLK N Divider */
+#define AIC31XX_BCLKN 0x1E
+/* Audio Interface Setting Register 3, Secondary Audio Interface */
+#define AIC31XX_IFACESEC1 0x1F
+/* Audio Interface Setting Register 4 */
+#define AIC31XX_IFACESEC2 0x20
+/* Audio Interface Setting Register 5 */
+#define AIC31XX_IFACESEC3 0x21
+/* I2C Bus Condition */
+#define AIC31XX_I2C 0x22
+/* ADC FLAG */
+#define AIC31XX_ADCFLAG 0x24
+/* DAC Flag Registers */
+#define AIC31XX_DACFLAG1 0x25
+#define AIC31XX_DACFLAG2 0x26
+/* Sticky Interrupt flag (overflow) */
+#define AIC31XX_OFFLAG 0x27
+/* Sticy DAC Interrupt flags */
+#define AIC31XX_INTRDACFLAG 0x2C
+/* Sticy ADC Interrupt flags */
+#define AIC31XX_INTRADCFLAG 0x2D
+/* DAC Interrupt flags 2 */
+#define AIC31XX_INTRDACFLAG2 0x2E
+/* ADC Interrupt flags 2 */
+#define AIC31XX_INTRADCFLAG2 0x2F
+/* INT1 interrupt control */
+#define AIC31XX_INT1CTRL 0x30
+/* INT2 interrupt control */
+#define AIC31XX_INT2CTRL 0x31
+/* GPIO1 control */
+#define AIC31XX_GPIO1 0x33
+
+#define AIC31XX_DACPRB 0x3C
+/* ADC Instruction Set Register */
+#define AIC31XX_ADCPRB 0x3D
+/* DAC channel setup register */
+#define AIC31XX_DACSETUP 0x3F
+/* DAC Mute and volume control register */
+#define AIC31XX_DACMUTE 0x40
+/* Left DAC channel digital volume control */
+#define AIC31XX_LDACVOL 0x41
+/* Right DAC channel digital volume control */
+#define AIC31XX_RDACVOL 0x42
+/* Headset detection */
+#define AIC31XX_HSDETECT 0x43
+/* ADC Digital Mic */
+#define AIC31XX_ADCSETUP 0x51
+/* ADC Digital Volume Control Fine Adjust */
+#define AIC31XX_ADCFGA 0x52
+/* ADC Digital Volume Control Coarse Adjust */
+#define AIC31XX_ADCVOL 0x53
+
+
+/* Page 1 Registers */
+/* Headphone drivers */
+#define AIC31XX_HPDRIVER 0x9F
+/* Class-D Speakear Amplifier */
+#define AIC31XX_SPKAMP 0xA0
+/* HP Output Drivers POP Removal Settings */
+#define AIC31XX_HPPOP 0xA1
+/* Output Driver PGA Ramp-Down Period Control */
+#define AIC31XX_SPPGARAMP 0xA2
+/* DAC_L and DAC_R Output Mixer Routing */
+#define AIC31XX_DACMIXERROUTE 0xA3
+/* Left Analog Vol to HPL */
+#define AIC31XX_LANALOGHPL 0xA4
+/* Right Analog Vol to HPR */
+#define AIC31XX_RANALOGHPR 0xA5
+/* Left Analog Vol to SPL */
+#define AIC31XX_LANALOGSPL 0xA6
+/* Right Analog Vol to SPR */
+#define AIC31XX_RANALOGSPR 0xA7
+/* HPL Driver */
+#define AIC31XX_HPLGAIN 0xA8
+/* HPR Driver */
+#define AIC31XX_HPRGAIN 0xA9
+/* SPL Driver */
+#define AIC31XX_SPLGAIN 0xAA
+/* SPR Driver */
+#define AIC31XX_SPRGAIN 0xAB
+/* HP Driver Control */
+#define AIC31XX_HPCONTROL 0xAC
+/* MIC Bias Control */
+#define AIC31XX_MICBIAS 0xAE
+/* MIC PGA*/
+#define AIC31XX_MICPGA 0xAF
+/* Delta-Sigma Mono ADC Channel Fine-Gain Input Selection for P-Terminal */
+#define AIC31XX_MICPGAPI 0xB0
+/* ADC Input Selection for M-Terminal */
+#define AIC31XX_MICPGAMI 0xB1
+/* Input CM Settings */
+#define AIC31XX_MICPGACM 0xB2
+
+/* Bits, masks and shifts */
+
+/* AIC31XX_CLKMUX */
+#define AIC31XX_PLL_CLKIN_MASK 0x0c
+#define AIC31XX_PLL_CLKIN_SHIFT 2
+#define AIC31XX_PLL_CLKIN_MCLK 0
+#define AIC31XX_CODEC_CLKIN_MASK 0x03
+#define AIC31XX_CODEC_CLKIN_SHIFT 0
+#define AIC31XX_CODEC_CLKIN_PLL 3
+#define AIC31XX_CODEC_CLKIN_BCLK 1
+
+/* AIC31XX_PLLPR, AIC31XX_NDAC, AIC31XX_MDAC, AIC31XX_NADC, AIC31XX_MADC,
+ AIC31XX_BCLKN */
+#define AIC31XX_PLL_MASK 0x7f
+#define AIC31XX_PM_MASK 0x80
+
+/* AIC31XX_IFACE1 */
+#define AIC31XX_WORD_LEN_16BITS 0x00
+#define AIC31XX_WORD_LEN_20BITS 0x01
+#define AIC31XX_WORD_LEN_24BITS 0x02
+#define AIC31XX_WORD_LEN_32BITS 0x03
+#define AIC31XX_IFACE1_DATALEN_MASK 0x30
+#define AIC31XX_IFACE1_DATALEN_SHIFT (4)
+#define AIC31XX_IFACE1_DATATYPE_MASK 0xC0
+#define AIC31XX_IFACE1_DATATYPE_SHIFT (6)
+#define AIC31XX_I2S_MODE 0x00
+#define AIC31XX_DSP_MODE 0x01
+#define AIC31XX_RIGHT_JUSTIFIED_MODE 0x02
+#define AIC31XX_LEFT_JUSTIFIED_MODE 0x03
+#define AIC31XX_IFACE1_MASTER_MASK 0x0C
+#define AIC31XX_BCLK_MASTER 0x08
+#define AIC31XX_WCLK_MASTER 0x04
+
+/* AIC31XX_DATA_OFFSET */
+#define AIC31XX_DATA_OFFSET_MASK 0xFF
+
+/* AIC31XX_IFACE2 */
+#define AIC31XX_BCLKINV_MASK 0x08
+#define AIC31XX_BDIVCLK_MASK 0x03
+#define AIC31XX_DAC2BCLK 0x00
+#define AIC31XX_DACMOD2BCLK 0x01
+#define AIC31XX_ADC2BCLK 0x02
+#define AIC31XX_ADCMOD2BCLK 0x03
+
+/* AIC31XX_ADCFLAG */
+#define AIC31XX_ADCPWRSTATUS_MASK 0x40
+
+/* AIC31XX_DACFLAG1 */
+#define AIC31XX_LDACPWRSTATUS_MASK 0x80
+#define AIC31XX_RDACPWRSTATUS_MASK 0x08
+#define AIC31XX_HPLDRVPWRSTATUS_MASK 0x20
+#define AIC31XX_HPRDRVPWRSTATUS_MASK 0x02
+#define AIC31XX_SPLDRVPWRSTATUS_MASK 0x10
+#define AIC31XX_SPRDRVPWRSTATUS_MASK 0x01
+
+/* AIC31XX_INTRDACFLAG */
+#define AIC31XX_HPSCDETECT_MASK 0x80
+#define AIC31XX_BUTTONPRESS_MASK 0x20
+#define AIC31XX_HSPLUG_MASK 0x10
+#define AIC31XX_LDRCTHRES_MASK 0x08
+#define AIC31XX_RDRCTHRES_MASK 0x04
+#define AIC31XX_DACSINT_MASK 0x02
+#define AIC31XX_DACAINT_MASK 0x01
+
+/* AIC31XX_INT1CTRL */
+#define AIC31XX_HSPLUGDET_MASK 0x80
+#define AIC31XX_BUTTONPRESSDET_MASK 0x40
+#define AIC31XX_DRCTHRES_MASK 0x20
+#define AIC31XX_AGCNOISE_MASK 0x10
+#define AIC31XX_OC_MASK 0x08
+#define AIC31XX_ENGINE_MASK 0x04
+
+/* AIC31XX_DACSETUP */
+#define AIC31XX_SOFTSTEP_MASK 0x03
+
+/* AIC31XX_DACMUTE */
+#define AIC31XX_DACMUTE_MASK 0x0C
+
+/* AIC31XX_MICBIAS */
+#define AIC31XX_MICBIAS_MASK 0x03
+#define AIC31XX_MICBIAS_SHIFT 0
+
+#endif /* _TLV320AIC31XX_H */
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 688151ba309..1d9b117345a 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -29,9 +29,12 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <linux/i2c.h>
#include <linux/cdev.h>
#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
#include <sound/tlv320aic32x4.h>
#include <sound/core.h>
@@ -66,20 +69,32 @@ struct aic32x4_priv {
u32 micpga_routing;
bool swapdacs;
int rstn_gpio;
+ struct clk *mclk;
+
+ struct regulator *supply_ldo;
+ struct regulator *supply_iov;
+ struct regulator *supply_dv;
+ struct regulator *supply_av;
};
-/* 0dB min, 1dB steps */
-static DECLARE_TLV_DB_SCALE(tlv_step_1, 0, 100, 0);
/* 0dB min, 0.5dB steps */
static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0);
+/* -63.5dB min, 0.5dB steps */
+static DECLARE_TLV_DB_SCALE(tlv_pcm, -6350, 50, 0);
+/* -6dB min, 1dB steps */
+static DECLARE_TLV_DB_SCALE(tlv_driver_gain, -600, 100, 0);
+/* -12dB min, 0.5dB steps */
+static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0);
static const struct snd_kcontrol_new aic32x4_snd_controls[] = {
- SOC_DOUBLE_R_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
- AIC32X4_RDACVOL, 0, 0x30, 0, tlv_step_0_5),
- SOC_DOUBLE_R_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN,
- AIC32X4_HPRGAIN, 0, 0x1D, 0, tlv_step_1),
- SOC_DOUBLE_R_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN,
- AIC32X4_LORGAIN, 0, 0x1D, 0, tlv_step_1),
+ SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
+ AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm),
+ SOC_DOUBLE_R_S_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN,
+ AIC32X4_HPRGAIN, 0, -0x6, 0x1d, 5, 0,
+ tlv_driver_gain),
+ SOC_DOUBLE_R_S_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN,
+ AIC32X4_LORGAIN, 0, -0x6, 0x1d, 5, 0,
+ tlv_driver_gain),
SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN,
AIC32X4_HPRGAIN, 6, 0x01, 1),
SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN,
@@ -90,8 +105,8 @@ static const struct snd_kcontrol_new aic32x4_snd_controls[] = {
SOC_SINGLE("ADCFGA Left Mute Switch", AIC32X4_ADCFGA, 7, 1, 0),
SOC_SINGLE("ADCFGA Right Mute Switch", AIC32X4_ADCFGA, 3, 1, 0),
- SOC_DOUBLE_R_TLV("ADC Level Volume", AIC32X4_LADCVOL,
- AIC32X4_RADCVOL, 0, 0x28, 0, tlv_step_0_5),
+ SOC_DOUBLE_R_S_TLV("ADC Level Volume", AIC32X4_LADCVOL,
+ AIC32X4_RADCVOL, 0, -0x18, 0x28, 6, 0, tlv_adc_vol),
SOC_DOUBLE_R_TLV("PGA Level Volume", AIC32X4_LMICPGAVOL,
AIC32X4_RMICPGAVOL, 0, 0x5f, 0, tlv_step_0_5),
@@ -480,8 +495,18 @@ static int aic32x4_mute(struct snd_soc_dai *dai, int mute)
static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
switch (level) {
case SND_SOC_BIAS_ON:
+ /* Switch on master clock */
+ ret = clk_prepare_enable(aic32x4->mclk);
+ if (ret) {
+ dev_err(codec->dev, "Failed to enable master clock\n");
+ return ret;
+ }
+
/* Switch on PLL */
snd_soc_update_bits(codec, AIC32X4_PLLPR,
AIC32X4_PLLEN, AIC32X4_PLLEN);
@@ -509,29 +534,32 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
- /* Switch off PLL */
- snd_soc_update_bits(codec, AIC32X4_PLLPR,
- AIC32X4_PLLEN, 0);
+ /* Switch off BCLK_N Divider */
+ snd_soc_update_bits(codec, AIC32X4_BCLKN,
+ AIC32X4_BCLKEN, 0);
- /* Switch off NDAC Divider */
- snd_soc_update_bits(codec, AIC32X4_NDAC,
- AIC32X4_NDACEN, 0);
+ /* Switch off MADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_MADC,
+ AIC32X4_MADCEN, 0);
+
+ /* Switch off NADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NADC,
+ AIC32X4_NADCEN, 0);
/* Switch off MDAC Divider */
snd_soc_update_bits(codec, AIC32X4_MDAC,
AIC32X4_MDACEN, 0);
- /* Switch off NADC Divider */
- snd_soc_update_bits(codec, AIC32X4_NADC,
- AIC32X4_NADCEN, 0);
+ /* Switch off NDAC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NDAC,
+ AIC32X4_NDACEN, 0);
- /* Switch off MADC Divider */
- snd_soc_update_bits(codec, AIC32X4_MADC,
- AIC32X4_MADCEN, 0);
+ /* Switch off PLL */
+ snd_soc_update_bits(codec, AIC32X4_PLLPR,
+ AIC32X4_PLLEN, 0);
- /* Switch off BCLK_N Divider */
- snd_soc_update_bits(codec, AIC32X4_BCLKN,
- AIC32X4_BCLKEN, 0);
+ /* Switch off master clock */
+ clk_disable_unprepare(aic32x4->mclk);
break;
case SND_SOC_BIAS_OFF:
break;
@@ -586,9 +614,7 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
u32 tmp_reg;
- snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
-
- if (aic32x4->rstn_gpio >= 0) {
+ if (gpio_is_valid(aic32x4->rstn_gpio)) {
ndelay(10);
gpio_set_value(aic32x4->rstn_gpio, 1);
}
@@ -663,11 +689,122 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
.num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes),
};
+static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4,
+ struct device_node *np)
+{
+ aic32x4->swapdacs = false;
+ aic32x4->micpga_routing = 0;
+ aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0);
+
+ return 0;
+}
+
+static void aic32x4_disable_regulators(struct aic32x4_priv *aic32x4)
+{
+ regulator_disable(aic32x4->supply_iov);
+
+ if (!IS_ERR(aic32x4->supply_ldo))
+ regulator_disable(aic32x4->supply_ldo);
+
+ if (!IS_ERR(aic32x4->supply_dv))
+ regulator_disable(aic32x4->supply_dv);
+
+ if (!IS_ERR(aic32x4->supply_av))
+ regulator_disable(aic32x4->supply_av);
+}
+
+static int aic32x4_setup_regulators(struct device *dev,
+ struct aic32x4_priv *aic32x4)
+{
+ int ret = 0;
+
+ aic32x4->supply_ldo = devm_regulator_get_optional(dev, "ldoin");
+ aic32x4->supply_iov = devm_regulator_get(dev, "iov");
+ aic32x4->supply_dv = devm_regulator_get_optional(dev, "dv");
+ aic32x4->supply_av = devm_regulator_get_optional(dev, "av");
+
+ /* Check if the regulator requirements are fulfilled */
+
+ if (IS_ERR(aic32x4->supply_iov)) {
+ dev_err(dev, "Missing supply 'iov'\n");
+ return PTR_ERR(aic32x4->supply_iov);
+ }
+
+ if (IS_ERR(aic32x4->supply_ldo)) {
+ if (PTR_ERR(aic32x4->supply_ldo) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ if (IS_ERR(aic32x4->supply_dv)) {
+ dev_err(dev, "Missing supply 'dv' or 'ldoin'\n");
+ return PTR_ERR(aic32x4->supply_dv);
+ }
+ if (IS_ERR(aic32x4->supply_av)) {
+ dev_err(dev, "Missing supply 'av' or 'ldoin'\n");
+ return PTR_ERR(aic32x4->supply_av);
+ }
+ } else {
+ if (IS_ERR(aic32x4->supply_dv) &&
+ PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ if (IS_ERR(aic32x4->supply_av) &&
+ PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ }
+
+ ret = regulator_enable(aic32x4->supply_iov);
+ if (ret) {
+ dev_err(dev, "Failed to enable regulator iov\n");
+ return ret;
+ }
+
+ if (!IS_ERR(aic32x4->supply_ldo)) {
+ ret = regulator_enable(aic32x4->supply_ldo);
+ if (ret) {
+ dev_err(dev, "Failed to enable regulator ldo\n");
+ goto error_ldo;
+ }
+ }
+
+ if (!IS_ERR(aic32x4->supply_dv)) {
+ ret = regulator_enable(aic32x4->supply_dv);
+ if (ret) {
+ dev_err(dev, "Failed to enable regulator dv\n");
+ goto error_dv;
+ }
+ }
+
+ if (!IS_ERR(aic32x4->supply_av)) {
+ ret = regulator_enable(aic32x4->supply_av);
+ if (ret) {
+ dev_err(dev, "Failed to enable regulator av\n");
+ goto error_av;
+ }
+ }
+
+ if (!IS_ERR(aic32x4->supply_ldo) && IS_ERR(aic32x4->supply_av))
+ aic32x4->power_cfg |= AIC32X4_PWR_AIC32X4_LDO_ENABLE;
+
+ return 0;
+
+error_av:
+ if (!IS_ERR(aic32x4->supply_dv))
+ regulator_disable(aic32x4->supply_dv);
+
+error_dv:
+ if (!IS_ERR(aic32x4->supply_ldo))
+ regulator_disable(aic32x4->supply_ldo);
+
+error_ldo:
+ regulator_disable(aic32x4->supply_iov);
+ return ret;
+}
+
static int aic32x4_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct aic32x4_pdata *pdata = i2c->dev.platform_data;
struct aic32x4_priv *aic32x4;
+ struct device_node *np = i2c->dev.of_node;
int ret;
aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv),
@@ -686,6 +823,12 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c,
aic32x4->swapdacs = pdata->swapdacs;
aic32x4->micpga_routing = pdata->micpga_routing;
aic32x4->rstn_gpio = pdata->rstn_gpio;
+ } else if (np) {
+ ret = aic32x4_parse_dt(aic32x4, np);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to parse DT node\n");
+ return ret;
+ }
} else {
aic32x4->power_cfg = 0;
aic32x4->swapdacs = false;
@@ -693,20 +836,44 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c,
aic32x4->rstn_gpio = -1;
}
- if (aic32x4->rstn_gpio >= 0) {
+ aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk");
+ if (IS_ERR(aic32x4->mclk)) {
+ dev_err(&i2c->dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n");
+ return PTR_ERR(aic32x4->mclk);
+ }
+
+ if (gpio_is_valid(aic32x4->rstn_gpio)) {
ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio,
GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
if (ret != 0)
return ret;
}
+ ret = aic32x4_setup_regulators(&i2c->dev, aic32x4);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to setup regulators\n");
+ return ret;
+ }
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_aic32x4, &aic32x4_dai, 1);
- return ret;
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to register codec\n");
+ aic32x4_disable_regulators(aic32x4);
+ return ret;
+ }
+
+ i2c_set_clientdata(i2c, aic32x4);
+
+ return 0;
}
static int aic32x4_i2c_remove(struct i2c_client *client)
{
+ struct aic32x4_priv *aic32x4 = i2c_get_clientdata(client);
+
+ aic32x4_disable_regulators(aic32x4);
+
snd_soc_unregister_codec(&client->dev);
return 0;
}
@@ -717,10 +884,17 @@ static const struct i2c_device_id aic32x4_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id);
+static const struct of_device_id aic32x4_of_id[] = {
+ { .compatible = "ti,tlv320aic32x4", },
+ { /* senitel */ }
+};
+MODULE_DEVICE_TABLE(of, aic32x4_of_id);
+
static struct i2c_driver aic32x4_i2c_driver = {
.driver = {
.name = "tlv320aic32x4",
.owner = THIS_MODULE,
+ .of_match_table = aic32x4_of_id,
},
.probe = aic32x4_i2c_probe,
.remove = aic32x4_i2c_remove,
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 470fbfb4b38..e12fafbb1e0 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -169,7 +169,7 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
mask <<= shift;
val <<= shift;
- change = snd_soc_test_bits(codec, val, mask, reg);
+ change = snd_soc_test_bits(codec, reg, mask, val);
if (change) {
update.kcontrol = kcontrol;
update.reg = reg;
@@ -1344,12 +1344,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
INIT_LIST_HEAD(&aic3x->list);
aic3x->codec = codec;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event;
aic3x->disable_nb[i].aic3x = aic3x;
@@ -1405,7 +1399,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
}
aic3x_add_widgets(codec);
- list_add(&aic3x->list, &reset_list);
return 0;
@@ -1575,7 +1568,13 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_aic3x, &aic3x_dai, 1);
- return ret;
+
+ if (ret != 0)
+ goto err_gpio;
+
+ list_add(&aic3x->list, &reset_list);
+
+ return 0;
err_gpio:
if (gpio_is_valid(aic3x->gpio_reset) &&
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 4f358393d6d..df3a7506c02 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -122,7 +122,6 @@ struct tlv320dac33_priv {
unsigned int uthr;
enum dac33_state state;
- enum snd_soc_control_type control_type;
void *control_data;
};
@@ -443,7 +442,7 @@ static int dac33_playback_event(struct snd_soc_dapm_widget *w,
static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = dac33->fifo_mode;
@@ -454,14 +453,14 @@ static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol,
static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
if (dac33->fifo_mode == ucontrol->value.integer.value[0])
return 0;
/* Do not allow changes while stream is running*/
- if (codec->active)
+ if (snd_soc_codec_is_active(codec))
return -EPERM;
if (ucontrol->value.integer.value[0] < 0 ||
@@ -478,9 +477,7 @@ static const char *dac33_fifo_mode_texts[] = {
"Bypass", "Mode 1", "Mode 7"
};
-static const struct soc_enum dac33_fifo_mode_enum =
- SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dac33_fifo_mode_texts),
- dac33_fifo_mode_texts);
+static SOC_ENUM_SINGLE_EXT_DECL(dac33_fifo_mode_enum, dac33_fifo_mode_texts);
/* L/R Line Output Gain */
static const char *lr_lineout_gain_texts[] = {
@@ -488,15 +485,13 @@ static const char *lr_lineout_gain_texts[] = {
"Line 0dB DAC 12dB", "Line 6dB DAC 18dB",
};
-static const struct soc_enum l_lineout_gain_enum =
- SOC_ENUM_SINGLE(DAC33_LDAC_PWR_CTRL, 0,
- ARRAY_SIZE(lr_lineout_gain_texts),
- lr_lineout_gain_texts);
+static SOC_ENUM_SINGLE_DECL(l_lineout_gain_enum,
+ DAC33_LDAC_PWR_CTRL, 0,
+ lr_lineout_gain_texts);
-static const struct soc_enum r_lineout_gain_enum =
- SOC_ENUM_SINGLE(DAC33_RDAC_PWR_CTRL, 0,
- ARRAY_SIZE(lr_lineout_gain_texts),
- lr_lineout_gain_texts);
+static SOC_ENUM_SINGLE_DECL(r_lineout_gain_enum,
+ DAC33_RDAC_PWR_CTRL, 0,
+ lr_lineout_gain_texts);
/*
* DACL/R digital volume control:
@@ -534,18 +529,16 @@ static const struct snd_kcontrol_new dac33_dapm_abypassr_control =
/* LOP L/R invert selection */
static const char *dac33_lr_lom_texts[] = {"DAC", "LOP"};
-static const struct soc_enum dac33_left_lom_enum =
- SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 3,
- ARRAY_SIZE(dac33_lr_lom_texts),
- dac33_lr_lom_texts);
+static SOC_ENUM_SINGLE_DECL(dac33_left_lom_enum,
+ DAC33_OUT_AMP_CTRL, 3,
+ dac33_lr_lom_texts);
static const struct snd_kcontrol_new dac33_dapm_left_lom_control =
SOC_DAPM_ENUM("Route", dac33_left_lom_enum);
-static const struct soc_enum dac33_right_lom_enum =
- SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 2,
- ARRAY_SIZE(dac33_lr_lom_texts),
- dac33_lr_lom_texts);
+static SOC_ENUM_SINGLE_DECL(dac33_right_lom_enum,
+ DAC33_OUT_AMP_CTRL, 2,
+ dac33_lr_lom_texts);
static const struct snd_kcontrol_new dac33_dapm_right_lom_control =
SOC_DAPM_ENUM("Route", dac33_right_lom_enum);
@@ -1547,7 +1540,7 @@ static int dac33_i2c_probe(struct i2c_client *client,
for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++)
dac33->supplies[i].supply = dac33_supply_names[i];
- ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies),
+ ret = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies),
dac33->supplies);
if (ret != 0) {
@@ -1558,11 +1551,9 @@ static int dac33_i2c_probe(struct i2c_client *client,
ret = snd_soc_register_codec(&client->dev,
&soc_codec_dev_tlv320dac33, &dac33_dai, 1);
if (ret < 0)
- goto err_register;
+ goto err_get;
return ret;
-err_register:
- regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
err_get:
if (dac33->power_gpio >= 0)
gpio_free(dac33->power_gpio);
@@ -1580,8 +1571,6 @@ static int dac33_i2c_remove(struct i2c_client *client)
if (dac33->power_gpio >= 0)
gpio_free(dac33->power_gpio);
- regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
-
snd_soc_unregister_codec(&client->dev);
return 0;
}
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index b27c396037d..8fc5a647453 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -30,6 +30,7 @@
#include <sound/tpa6130a2-plat.h>
#include <sound/soc.h>
#include <sound/tlv.h>
+#include <linux/of.h>
#include <linux/of_gpio.h>
#include "tpa6130a2.h"
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 00665ada23e..69e12a311ba 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -415,10 +415,9 @@ static const struct snd_kcontrol_new twl4030_dapm_carkitr_controls[] = {
static const char *twl4030_handsfreel_texts[] =
{"Voice", "AudioL1", "AudioL2", "AudioR2"};
-static const struct soc_enum twl4030_handsfreel_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0,
- ARRAY_SIZE(twl4030_handsfreel_texts),
- twl4030_handsfreel_texts);
+static SOC_ENUM_SINGLE_DECL(twl4030_handsfreel_enum,
+ TWL4030_REG_HFL_CTL, 0,
+ twl4030_handsfreel_texts);
static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control =
SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum);
@@ -431,10 +430,9 @@ static const struct snd_kcontrol_new twl4030_dapm_handsfreelmute_control =
static const char *twl4030_handsfreer_texts[] =
{"Voice", "AudioR1", "AudioR2", "AudioL2"};
-static const struct soc_enum twl4030_handsfreer_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0,
- ARRAY_SIZE(twl4030_handsfreer_texts),
- twl4030_handsfreer_texts);
+static SOC_ENUM_SINGLE_DECL(twl4030_handsfreer_enum,
+ TWL4030_REG_HFR_CTL, 0,
+ twl4030_handsfreer_texts);
static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control =
SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);
@@ -448,10 +446,9 @@ static const struct snd_kcontrol_new twl4030_dapm_handsfreermute_control =
static const char *twl4030_vibra_texts[] =
{"AudioL1", "AudioR1", "AudioL2", "AudioR2"};
-static const struct soc_enum twl4030_vibra_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 2,
- ARRAY_SIZE(twl4030_vibra_texts),
- twl4030_vibra_texts);
+static SOC_ENUM_SINGLE_DECL(twl4030_vibra_enum,
+ TWL4030_REG_VIBRA_CTL, 2,
+ twl4030_vibra_texts);
static const struct snd_kcontrol_new twl4030_dapm_vibra_control =
SOC_DAPM_ENUM("Route", twl4030_vibra_enum);
@@ -460,10 +457,9 @@ SOC_DAPM_ENUM("Route", twl4030_vibra_enum);
static const char *twl4030_vibrapath_texts[] =
{"Local vibrator", "Audio"};
-static const struct soc_enum twl4030_vibrapath_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 4,
- ARRAY_SIZE(twl4030_vibrapath_texts),
- twl4030_vibrapath_texts);
+static SOC_ENUM_SINGLE_DECL(twl4030_vibrapath_enum,
+ TWL4030_REG_VIBRA_CTL, 4,
+ twl4030_vibrapath_texts);
static const struct snd_kcontrol_new twl4030_dapm_vibrapath_control =
SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum);
@@ -490,10 +486,9 @@ static const struct snd_kcontrol_new twl4030_dapm_analogrmic_controls[] = {
static const char *twl4030_micpathtx1_texts[] =
{"Analog", "Digimic0"};
-static const struct soc_enum twl4030_micpathtx1_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 0,
- ARRAY_SIZE(twl4030_micpathtx1_texts),
- twl4030_micpathtx1_texts);
+static SOC_ENUM_SINGLE_DECL(twl4030_micpathtx1_enum,
+ TWL4030_REG_ADCMICSEL, 0,
+ twl4030_micpathtx1_texts);
static const struct snd_kcontrol_new twl4030_dapm_micpathtx1_control =
SOC_DAPM_ENUM("Route", twl4030_micpathtx1_enum);
@@ -502,10 +497,9 @@ SOC_DAPM_ENUM("Route", twl4030_micpathtx1_enum);
static const char *twl4030_micpathtx2_texts[] =
{"Analog", "Digimic1"};
-static const struct soc_enum twl4030_micpathtx2_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 2,
- ARRAY_SIZE(twl4030_micpathtx2_texts),
- twl4030_micpathtx2_texts);
+static SOC_ENUM_SINGLE_DECL(twl4030_micpathtx2_enum,
+ TWL4030_REG_ADCMICSEL, 2,
+ twl4030_micpathtx2_texts);
static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control =
SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum);
@@ -836,7 +830,7 @@ static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int reg = mc->reg;
unsigned int shift = mc->shift;
unsigned int rshift = mc->rshift;
@@ -865,7 +859,7 @@ static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int reg = mc->reg;
unsigned int shift = mc->shift;
unsigned int rshift = mc->rshift;
@@ -894,7 +888,7 @@ static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int reg = mc->reg;
unsigned int reg2 = mc->rreg;
unsigned int shift = mc->shift;
@@ -921,7 +915,7 @@ static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int reg = mc->reg;
unsigned int reg2 = mc->rreg;
unsigned int shift = mc->shift;
@@ -955,19 +949,15 @@ static const char *twl4030_op_modes_texts[] = {
"Option 2 (voice/audio)", "Option 1 (audio)"
};
-static const struct soc_enum twl4030_op_modes_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_CODEC_MODE, 0,
- ARRAY_SIZE(twl4030_op_modes_texts),
- twl4030_op_modes_texts);
+static SOC_ENUM_SINGLE_DECL(twl4030_op_modes_enum,
+ TWL4030_REG_CODEC_MODE, 0,
+ twl4030_op_modes_texts);
static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
- struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
- unsigned short val;
- unsigned short mask;
if (twl4030->configured) {
dev_err(codec->dev,
@@ -975,19 +965,7 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
return -EBUSY;
}
- if (ucontrol->value.enumerated.item[0] > e->max - 1)
- return -EINVAL;
-
- val = ucontrol->value.enumerated.item[0] << e->shift_l;
- mask = e->mask << e->shift_l;
- if (e->shift_l != e->shift_r) {
- if (ucontrol->value.enumerated.item[1] > e->max - 1)
- return -EINVAL;
- val |= ucontrol->value.enumerated.item[1] << e->shift_r;
- mask |= e->mask << e->shift_r;
- }
-
- return snd_soc_update_bits(codec, e->reg, mask, val);
+ return snd_soc_put_enum_double(kcontrol, ucontrol);
}
/*
@@ -1044,10 +1022,9 @@ static const char *twl4030_avadc_clk_priority_texts[] = {
"Voice high priority", "HiFi high priority"
};
-static const struct soc_enum twl4030_avadc_clk_priority_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_AVADC_CTL, 2,
- ARRAY_SIZE(twl4030_avadc_clk_priority_texts),
- twl4030_avadc_clk_priority_texts);
+static SOC_ENUM_SINGLE_DECL(twl4030_avadc_clk_priority_enum,
+ TWL4030_REG_AVADC_CTL, 2,
+ twl4030_avadc_clk_priority_texts);
static const char *twl4030_rampdelay_texts[] = {
"27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms",
@@ -1055,40 +1032,36 @@ static const char *twl4030_rampdelay_texts[] = {
"3495/2581/1748 ms"
};
-static const struct soc_enum twl4030_rampdelay_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_HS_POPN_SET, 2,
- ARRAY_SIZE(twl4030_rampdelay_texts),
- twl4030_rampdelay_texts);
+static SOC_ENUM_SINGLE_DECL(twl4030_rampdelay_enum,
+ TWL4030_REG_HS_POPN_SET, 2,
+ twl4030_rampdelay_texts);
/* Vibra H-bridge direction mode */
static const char *twl4030_vibradirmode_texts[] = {
"Vibra H-bridge direction", "Audio data MSB",
};
-static const struct soc_enum twl4030_vibradirmode_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 5,
- ARRAY_SIZE(twl4030_vibradirmode_texts),
- twl4030_vibradirmode_texts);
+static SOC_ENUM_SINGLE_DECL(twl4030_vibradirmode_enum,
+ TWL4030_REG_VIBRA_CTL, 5,
+ twl4030_vibradirmode_texts);
/* Vibra H-bridge direction */
static const char *twl4030_vibradir_texts[] = {
"Positive polarity", "Negative polarity",
};
-static const struct soc_enum twl4030_vibradir_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 1,
- ARRAY_SIZE(twl4030_vibradir_texts),
- twl4030_vibradir_texts);
+static SOC_ENUM_SINGLE_DECL(twl4030_vibradir_enum,
+ TWL4030_REG_VIBRA_CTL, 1,
+ twl4030_vibradir_texts);
/* Digimic Left and right swapping */
static const char *twl4030_digimicswap_texts[] = {
"Not swapped", "Swapped",
};
-static const struct soc_enum twl4030_digimicswap_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_MISC_SET_1, 0,
- ARRAY_SIZE(twl4030_digimicswap_texts),
- twl4030_digimicswap_texts);
+static SOC_ENUM_SINGLE_DECL(twl4030_digimicswap_enum,
+ TWL4030_REG_MISC_SET_1, 0,
+ twl4030_digimicswap_texts);
static const struct snd_kcontrol_new twl4030_snd_controls[] = {
/* Codec operation mode control */
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 0afe8bef676..0f6067f04e2 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -81,7 +81,7 @@ struct twl6040_data {
};
/* set of rates for each pll: low-power and high-performance */
-static unsigned int lp_rates[] = {
+static const unsigned int lp_rates[] = {
8000,
11250,
16000,
@@ -93,7 +93,7 @@ static unsigned int lp_rates[] = {
96000,
};
-static unsigned int hp_rates[] = {
+static const unsigned int hp_rates[] = {
8000,
16000,
32000,
@@ -101,7 +101,7 @@ static unsigned int hp_rates[] = {
96000,
};
-static struct snd_pcm_hw_constraint_list sysclk_constraints[] = {
+static const struct snd_pcm_hw_constraint_list sysclk_constraints[] = {
{ .count = ARRAY_SIZE(lp_rates), .list = lp_rates, },
{ .count = ARRAY_SIZE(hp_rates), .list = hp_rates, },
};
@@ -392,8 +392,10 @@ static const char *twl6040_amicr_texts[] =
{"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"};
static const struct soc_enum twl6040_enum[] = {
- SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 4, twl6040_amicl_texts),
- SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 4, twl6040_amicr_texts),
+ SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3,
+ ARRAY_SIZE(twl6040_amicl_texts), twl6040_amicl_texts),
+ SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3,
+ ARRAY_SIZE(twl6040_amicr_texts), twl6040_amicr_texts),
};
static const char *twl6040_hs_texts[] = {
@@ -476,14 +478,13 @@ static const char *twl6040_power_mode_texts[] = {
"Low-Power", "High-Performance",
};
-static const struct soc_enum twl6040_power_mode_enum =
- SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl6040_power_mode_texts),
- twl6040_power_mode_texts);
+static SOC_ENUM_SINGLE_EXT_DECL(twl6040_power_mode_enum,
+ twl6040_power_mode_texts);
static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = priv->hs_power_mode;
@@ -494,7 +495,7 @@ static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol,
static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
int high_perf = ucontrol->value.enumerated.item[0];
int ret = 0;
@@ -511,7 +512,7 @@ static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol,
static int twl6040_pll_get_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = priv->pll_power_mode;
@@ -522,7 +523,7 @@ static int twl6040_pll_get_enum(struct snd_kcontrol *kcontrol,
static int twl6040_pll_put_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
priv->pll_power_mode = ucontrol->value.enumerated.item[0];
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index c94d4c1e3da..edf27acc1d7 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -203,8 +203,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
u8 hw_params;
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 726df6d43c2..e62e70781ec 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -108,7 +108,7 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
/* the interpolator & decimator regs must only be written when the
* codec DAI is active.
*/
- if (!codec->active && (reg >= UDA1380_MVOL))
+ if (!snd_soc_codec_is_active(codec) && (reg >= UDA1380_MVOL))
return 0;
pr_debug("uda1380: hw write %x val %x\n", reg, value);
if (codec->hw_write(codec->control_data, data, 3) == 3) {
@@ -237,25 +237,27 @@ static const char *uda1380_os_setting[] = {
};
static const struct soc_enum uda1380_deemp_enum[] = {
- SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, 5, uda1380_deemp),
- SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, 5, uda1380_deemp),
+ SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, ARRAY_SIZE(uda1380_deemp),
+ uda1380_deemp),
+ SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, ARRAY_SIZE(uda1380_deemp),
+ uda1380_deemp),
};
-static const struct soc_enum uda1380_input_sel_enum =
- SOC_ENUM_SINGLE(UDA1380_ADC, 2, 4, uda1380_input_sel); /* SEL_MIC, SEL_LNA */
-static const struct soc_enum uda1380_output_sel_enum =
- SOC_ENUM_SINGLE(UDA1380_PM, 7, 2, uda1380_output_sel); /* R02_EN_AVC */
-static const struct soc_enum uda1380_spf_enum =
- SOC_ENUM_SINGLE(UDA1380_MODE, 14, 4, uda1380_spf_mode); /* M */
-static const struct soc_enum uda1380_capture_sel_enum =
- SOC_ENUM_SINGLE(UDA1380_IFACE, 6, 2, uda1380_capture_sel); /* SEL_SOURCE */
-static const struct soc_enum uda1380_sel_ns_enum =
- SOC_ENUM_SINGLE(UDA1380_MIXER, 14, 2, uda1380_sel_ns); /* SEL_NS */
-static const struct soc_enum uda1380_mix_enum =
- SOC_ENUM_SINGLE(UDA1380_MIXER, 12, 4, uda1380_mix_control); /* MIX, MIX_POS */
-static const struct soc_enum uda1380_sdet_enum =
- SOC_ENUM_SINGLE(UDA1380_MIXER, 4, 4, uda1380_sdet_setting); /* SD_VALUE */
-static const struct soc_enum uda1380_os_enum =
- SOC_ENUM_SINGLE(UDA1380_MIXER, 0, 3, uda1380_os_setting); /* OS */
+static SOC_ENUM_SINGLE_DECL(uda1380_input_sel_enum,
+ UDA1380_ADC, 2, uda1380_input_sel); /* SEL_MIC, SEL_LNA */
+static SOC_ENUM_SINGLE_DECL(uda1380_output_sel_enum,
+ UDA1380_PM, 7, uda1380_output_sel); /* R02_EN_AVC */
+static SOC_ENUM_SINGLE_DECL(uda1380_spf_enum,
+ UDA1380_MODE, 14, uda1380_spf_mode); /* M */
+static SOC_ENUM_SINGLE_DECL(uda1380_capture_sel_enum,
+ UDA1380_IFACE, 6, uda1380_capture_sel); /* SEL_SOURCE */
+static SOC_ENUM_SINGLE_DECL(uda1380_sel_ns_enum,
+ UDA1380_MIXER, 14, uda1380_sel_ns); /* SEL_NS */
+static SOC_ENUM_SINGLE_DECL(uda1380_mix_enum,
+ UDA1380_MIXER, 12, uda1380_mix_control); /* MIX, MIX_POS */
+static SOC_ENUM_SINGLE_DECL(uda1380_sdet_enum,
+ UDA1380_MIXER, 4, uda1380_sdet_setting); /* SD_VALUE */
+static SOC_ENUM_SINGLE_DECL(uda1380_os_enum,
+ UDA1380_MIXER, 0, uda1380_os_setting); /* OS */
/*
* from -48 dB in 1.5 dB steps (mute instead of -49.5 dB)
@@ -564,8 +566,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
/* shut down WSPLL power if running from this clock */
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index b7ab2ef567c..4ead0dc02b8 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -172,7 +172,7 @@ out:
static int snd_wl1273_get_audio_route(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = wl1273->mode;
@@ -190,14 +190,14 @@ static const char * const wl1273_audio_route[] = { "Bt", "FmRx", "FmTx" };
static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
if (wl1273->mode == ucontrol->value.integer.value[0])
return 0;
/* Do not allow changes while stream is running */
- if (codec->active)
+ if (snd_soc_codec_is_active(codec))
return -EPERM;
if (ucontrol->value.integer.value[0] < 0 ||
@@ -209,13 +209,12 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol,
return 1;
}
-static const struct soc_enum wl1273_enum =
- SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_route), wl1273_audio_route);
+static SOC_ENUM_SINGLE_EXT_DECL(wl1273_enum, wl1273_audio_route);
static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
dev_dbg(codec->dev, "%s: enter.\n", __func__);
@@ -228,7 +227,7 @@ static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol,
static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
int val, r = 0;
@@ -247,14 +246,12 @@ static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol,
static const char * const wl1273_audio_strings[] = { "Digital", "Analog" };
-static const struct soc_enum wl1273_audio_enum =
- SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_strings),
- wl1273_audio_strings);
+static SOC_ENUM_SINGLE_EXT_DECL(wl1273_audio_enum, wl1273_audio_strings);
static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
dev_dbg(codec->dev, "%s: enter.\n", __func__);
@@ -267,7 +264,7 @@ static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol,
static int snd_wl1273_fm_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
int r;
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 8ae50274ea8..a4c352cc346 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -607,7 +607,7 @@ static int wm2000_anc_set_mode(struct wm2000_priv *wm2000)
static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
ucontrol->value.enumerated.item[0] = wm2000->anc_active;
@@ -618,7 +618,7 @@ static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol,
static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
int anc_active = ucontrol->value.enumerated.item[0];
int ret;
@@ -640,7 +640,7 @@ static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol,
static int wm2000_speaker_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
ucontrol->value.enumerated.item[0] = wm2000->spk_ena;
@@ -651,7 +651,7 @@ static int wm2000_speaker_get(struct snd_kcontrol *kcontrol,
static int wm2000_speaker_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
int val = ucontrol->value.enumerated.item[0];
int ret;
@@ -786,8 +786,6 @@ static int wm2000_probe(struct snd_soc_codec *codec)
{
struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
- snd_soc_codec_set_cache_io(codec, 16, 8, SND_SOC_REGMAP);
-
/* This will trigger a transition to standby mode by default */
wm2000_anc_set_mode(wm2000);
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
index 57ba315d0c8..cdea9d9c163 100644
--- a/sound/soc/codecs/wm2200.c
+++ b/sound/soc/codecs/wm2200.c
@@ -1083,7 +1083,7 @@ static int wm2200_mixer_values[] = {
#define WM2200_MUX_CTL_DECL(name) \
const struct snd_kcontrol_new name##_mux = \
- SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+ SOC_DAPM_ENUM("Route", name##_enum)
#define WM2200_MIXER_ENUMS(name, base_reg) \
static WM2200_MUX_ENUM_DECL(name##_in1_enum, base_reg); \
@@ -1113,11 +1113,10 @@ static const char *wm2200_rxanc_input_sel_texts[] = {
"None", "IN1", "IN2", "IN3",
};
-static const struct soc_enum wm2200_rxanc_input_sel =
- SOC_ENUM_SINGLE(WM2200_RXANC_SRC,
- WM2200_IN_RXANC_SEL_SHIFT,
- ARRAY_SIZE(wm2200_rxanc_input_sel_texts),
- wm2200_rxanc_input_sel_texts);
+static SOC_ENUM_SINGLE_DECL(wm2200_rxanc_input_sel,
+ WM2200_RXANC_SRC,
+ WM2200_IN_RXANC_SEL_SHIFT,
+ wm2200_rxanc_input_sel_texts);
static const struct snd_kcontrol_new wm2200_snd_controls[] = {
SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
@@ -1208,7 +1207,7 @@ WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
#define WM2200_MUX(name, ctrl) \
- SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+ SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
#define WM2200_MIXER_WIDGETS(name, name_str) \
WM2200_MUX(name_str " Input 1", &name##_in1_mux), \
@@ -1288,11 +1287,10 @@ static const char *wm2200_aec_loopback_texts[] = {
"OUT1L", "OUT1R", "OUT2L", "OUT2R",
};
-static const struct soc_enum wm2200_aec_loopback =
- SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1,
- WM2200_AEC_LOOPBACK_SRC_SHIFT,
- ARRAY_SIZE(wm2200_aec_loopback_texts),
- wm2200_aec_loopback_texts);
+static SOC_ENUM_SINGLE_DECL(wm2200_aec_loopback,
+ WM2200_DAC_AEC_CONTROL_1,
+ WM2200_AEC_LOOPBACK_SRC_SHIFT,
+ wm2200_aec_loopback_texts);
static const struct snd_kcontrol_new wm2200_aec_loopback_mux =
SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback);
@@ -1556,15 +1554,8 @@ static int wm2200_probe(struct snd_soc_codec *codec)
int ret;
wm2200->codec = codec;
- codec->control_data = wm2200->regmap;
codec->dapm.bias_level = SND_SOC_BIAS_OFF;
- ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = snd_soc_add_codec_controls(codec, wm_adsp1_fw_controls, 2);
if (ret != 0)
return ret;
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index 4e3e31aaf50..91a9ea2a205 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -390,7 +390,7 @@ static int wm5100_mixer_values[] = {
#define WM5100_MUX_CTL_DECL(name) \
const struct snd_kcontrol_new name##_mux = \
- SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+ SOC_DAPM_ENUM("Route", name##_enum)
#define WM5100_MIXER_ENUMS(name, base_reg) \
static WM5100_MUX_ENUM_DECL(name##_in1_enum, base_reg); \
@@ -448,7 +448,7 @@ WM5100_MIXER_ENUMS(LHPF3, WM5100_HPLP3MIX_INPUT_1_SOURCE);
WM5100_MIXER_ENUMS(LHPF4, WM5100_HPLP4MIX_INPUT_1_SOURCE);
#define WM5100_MUX(name, ctrl) \
- SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+ SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
#define WM5100_MIXER_WIDGETS(name, name_str) \
WM5100_MUX(name_str " Input 1", &name##_in1_mux), \
@@ -506,21 +506,21 @@ static const char *wm5100_lhpf_mode_text[] = {
"Low-pass", "High-pass"
};
-static const struct soc_enum wm5100_lhpf1_mode =
- SOC_ENUM_SINGLE(WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, 2,
- wm5100_lhpf_mode_text);
+static SOC_ENUM_SINGLE_DECL(wm5100_lhpf1_mode,
+ WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT,
+ wm5100_lhpf_mode_text);
-static const struct soc_enum wm5100_lhpf2_mode =
- SOC_ENUM_SINGLE(WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, 2,
- wm5100_lhpf_mode_text);
+static SOC_ENUM_SINGLE_DECL(wm5100_lhpf2_mode,
+ WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT,
+ wm5100_lhpf_mode_text);
-static const struct soc_enum wm5100_lhpf3_mode =
- SOC_ENUM_SINGLE(WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, 2,
- wm5100_lhpf_mode_text);
+static SOC_ENUM_SINGLE_DECL(wm5100_lhpf3_mode,
+ WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT,
+ wm5100_lhpf_mode_text);
-static const struct soc_enum wm5100_lhpf4_mode =
- SOC_ENUM_SINGLE(WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, 2,
- wm5100_lhpf_mode_text);
+static SOC_ENUM_SINGLE_DECL(wm5100_lhpf4_mode,
+ WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT,
+ wm5100_lhpf_mode_text);
static const struct snd_kcontrol_new wm5100_snd_controls[] = {
SOC_SINGLE("IN1 High Performance Switch", WM5100_IN1L_CONTROL,
@@ -2100,6 +2100,7 @@ static void wm5100_micd_irq(struct wm5100_priv *wm5100)
int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
{
struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
if (jack) {
wm5100->jack = jack;
@@ -2117,9 +2118,14 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
WM5100_ACCDET_RATE_MASK);
/* We need the charge pump to power MICBIAS */
- snd_soc_dapm_force_enable_pin(&codec->dapm, "CP2");
- snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
- snd_soc_dapm_sync(&codec->dapm);
+ snd_soc_dapm_mutex_lock(dapm);
+
+ snd_soc_dapm_force_enable_pin_unlocked(dapm, "CP2");
+ snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK");
+
+ snd_soc_dapm_sync_unlocked(dapm);
+
+ snd_soc_dapm_mutex_unlock(dapm);
/* We start off just enabling microphone detection - even a
* plain headphone will trigger detection.
@@ -2337,13 +2343,6 @@ static int wm5100_probe(struct snd_soc_codec *codec)
int ret, i;
wm5100->codec = codec;
- codec->control_data = wm5100->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++)
snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU,
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index ce9c8e14d4b..289b64d89ab 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -582,7 +582,7 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
{
struct snd_soc_codec *codec = w->codec;
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
- struct regmap *regmap = codec->control_data;
+ struct regmap *regmap = arizona->regmap;
const struct reg_default *patch = NULL;
int i, patch_size;
@@ -622,13 +622,16 @@ static const unsigned int wm5102_osr_val[] = {
static const struct soc_enum wm5102_hpout_osr[] = {
SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L,
- ARIZONA_OUT1_OSR_SHIFT, 0x7, 3,
+ ARIZONA_OUT1_OSR_SHIFT, 0x7,
+ ARRAY_SIZE(wm5102_osr_text),
wm5102_osr_text, wm5102_osr_val),
SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L,
- ARIZONA_OUT2_OSR_SHIFT, 0x7, 3,
+ ARIZONA_OUT2_OSR_SHIFT, 0x7,
+ ARRAY_SIZE(wm5102_osr_text),
wm5102_osr_text, wm5102_osr_val),
SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L,
- ARIZONA_OUT3_OSR_SHIFT, 0x7, 3,
+ ARIZONA_OUT3_OSR_SHIFT, 0x7,
+ ARRAY_SIZE(wm5102_osr_text),
wm5102_osr_text, wm5102_osr_val),
};
@@ -685,15 +688,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
-SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21,
- ARIZONA_EQ1_ENA_MASK),
-SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21,
- ARIZONA_EQ2_ENA_MASK),
-SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21,
- ARIZONA_EQ3_ENA_MASK),
-SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21,
- ARIZONA_EQ4_ENA_MASK),
-
+SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19),
+SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 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,
@@ -705,6 +701,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
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, 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,
@@ -716,6 +714,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
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, 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,
@@ -727,6 +727,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
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, 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,
@@ -762,8 +764,8 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
-SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
-SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
+SOC_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
+SOC_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
@@ -812,9 +814,9 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
0xbf, 0, digital_tlv),
-SOC_VALUE_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]),
-SOC_VALUE_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]),
-SOC_VALUE_ENUM("EPOUT OSR", wm5102_hpout_osr[2]),
+SOC_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]),
+SOC_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]),
+SOC_ENUM("EPOUT OSR", wm5102_hpout_osr[2]),
SOC_DOUBLE("HPOUT1 DRE Switch", ARIZONA_DRE_ENABLE,
ARIZONA_DRE1L_ENA_SHIFT, ARIZONA_DRE1R_ENA_SHIFT, 1, 0),
@@ -968,7 +970,7 @@ static const struct soc_enum wm5102_aec_loopback =
wm5102_aec_loopback_values);
static const struct snd_kcontrol_new wm5102_aec_loopback_mux =
- SOC_DAPM_VALUE_ENUM("AEC Loopback", wm5102_aec_loopback);
+ SOC_DAPM_ENUM("AEC Loopback", wm5102_aec_loopback);
static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
@@ -1202,7 +1204,7 @@ SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0,
ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
-SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
+SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0,
&wm5102_aec_loopback_mux),
@@ -1758,12 +1760,6 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
int ret;
- codec->control_data = priv->core.arizona->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
- if (ret != 0)
- return ret;
-
ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 2);
if (ret != 0)
return ret;
@@ -1802,9 +1798,17 @@ static unsigned int wm5102_digital_vu[] = {
ARIZONA_DAC_DIGITAL_VOLUME_5R,
};
+static struct regmap *wm5102_get_regmap(struct device *dev)
+{
+ struct wm5102_priv *priv = dev_get_drvdata(dev);
+
+ return priv->core.arizona->regmap;
+}
+
static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
.probe = wm5102_codec_probe,
.remove = wm5102_codec_remove,
+ .get_regmap = wm5102_get_regmap,
.idle_bias_off = true,
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 2c3c962d9a8..2e5fcb559e9 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -136,7 +136,7 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w,
{
struct snd_soc_codec *codec = w->codec;
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
- struct regmap *regmap = codec->control_data;
+ struct regmap *regmap = arizona->regmap;
const struct reg_default *patch = NULL;
int i, patch_size;
@@ -247,15 +247,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
-SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21,
- ARIZONA_EQ1_ENA_MASK),
-SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21,
- ARIZONA_EQ2_ENA_MASK),
-SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21,
- ARIZONA_EQ3_ENA_MASK),
-SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21,
- ARIZONA_EQ4_ENA_MASK),
-
+SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19),
+SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 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,
@@ -267,6 +260,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
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, 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,
@@ -278,6 +273,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
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, 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,
@@ -289,6 +286,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
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, 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,
@@ -325,13 +324,13 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
-SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
-SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
-SOC_VALUE_ENUM("ISRC3 FSL", arizona_isrc_fsl[2]),
-SOC_VALUE_ENUM("ISRC1 FSH", arizona_isrc_fsh[0]),
-SOC_VALUE_ENUM("ISRC2 FSH", arizona_isrc_fsh[1]),
-SOC_VALUE_ENUM("ISRC3 FSH", arizona_isrc_fsh[2]),
-SOC_VALUE_ENUM("ASRC RATE 1", arizona_asrc_rate1),
+SOC_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
+SOC_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
+SOC_ENUM("ISRC3 FSL", arizona_isrc_fsl[2]),
+SOC_ENUM("ISRC1 FSH", arizona_isrc_fsh[0]),
+SOC_ENUM("ISRC2 FSH", arizona_isrc_fsh[1]),
+SOC_ENUM("ISRC3 FSH", arizona_isrc_fsh[2]),
+SOC_ENUM("ASRC RATE 1", arizona_asrc_rate1),
ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
@@ -368,6 +367,11 @@ SOC_SINGLE("HPOUT2 SC Protect Switch", ARIZONA_HP2_SHORT_CIRCUIT_CTRL,
SOC_SINGLE("HPOUT3 SC Protect Switch", ARIZONA_HP3_SHORT_CIRCUIT_CTRL,
ARIZONA_HP3_SC_ENA_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
+ ARIZONA_OUT5_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_6L,
+ ARIZONA_OUT6_OSR_SHIFT, 1, 0),
+
SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
SOC_DOUBLE_R("HPOUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
@@ -593,7 +597,7 @@ static const struct soc_enum wm5110_aec_loopback =
wm5110_aec_loopback_values);
static const struct snd_kcontrol_new wm5110_aec_loopback_mux =
- SOC_DAPM_VALUE_ENUM("AEC Loopback", wm5110_aec_loopback);
+ SOC_DAPM_ENUM("AEC Loopback", wm5110_aec_loopback);
static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
@@ -775,7 +779,7 @@ SND_SOC_DAPM_PGA("ISRC3DEC3", ARIZONA_ISRC_3_CTRL_3,
SND_SOC_DAPM_PGA("ISRC3DEC4", ARIZONA_ISRC_3_CTRL_3,
ARIZONA_ISRC3_DEC3_ENA_SHIFT, 0, NULL, 0),
-SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
+SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0,
&wm5110_aec_loopback_mux),
@@ -1588,13 +1592,8 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
int ret;
- codec->control_data = priv->core.arizona->regmap;
priv->core.arizona->dapm = &codec->dapm;
- ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
- if (ret != 0)
- return ret;
-
arizona_init_spk(codec);
arizona_init_gpio(codec);
@@ -1635,9 +1634,17 @@ static unsigned int wm5110_digital_vu[] = {
ARIZONA_DAC_DIGITAL_VOLUME_6R,
};
+static struct regmap *wm5110_get_regmap(struct device *dev)
+{
+ struct wm5110_priv *priv = dev_get_drvdata(dev);
+
+ return priv->core.arizona->regmap;
+}
+
static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
.probe = wm5110_codec_probe,
.remove = wm5110_codec_remove,
+ .get_regmap = wm5110_get_regmap,
.idle_bias_off = true,
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index a183dcf3d5c..392285edb59 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -302,7 +302,7 @@ static int pga_event(struct snd_soc_dapm_widget *w,
static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8350_data *wm8350_priv = snd_soc_codec_get_drvdata(codec);
struct wm8350_output *out = NULL;
struct soc_mixer_control *mc =
@@ -345,7 +345,7 @@ static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
static int wm8350_get_volsw_2r(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8350_data *wm8350_priv = snd_soc_codec_get_drvdata(codec);
struct wm8350_output *out1 = &wm8350_priv->out1;
struct wm8350_output *out2 = &wm8350_priv->out2;
@@ -1505,10 +1505,6 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec)
if (ret != 0)
return ret;
- codec->control_data = wm8350->regmap;
-
- snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
-
/* Put the codec into reset if it wasn't already */
wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
@@ -1610,11 +1606,19 @@ static int wm8350_codec_remove(struct snd_soc_codec *codec)
return 0;
}
+static struct regmap *wm8350_get_regmap(struct device *dev)
+{
+ struct wm8350 *wm8350 = dev_get_platdata(dev);
+
+ return wm8350->regmap;
+}
+
static struct snd_soc_codec_driver soc_codec_dev_wm8350 = {
.probe = wm8350_codec_probe,
.remove = wm8350_codec_remove,
.suspend = wm8350_suspend,
.resume = wm8350_resume,
+ .get_regmap = wm8350_get_regmap,
.set_bias_level = wm8350_set_bias_level,
.controls = wm8350_snd_controls,
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 48dc7d2fee3..06e913d3fea 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -93,7 +93,7 @@ static const DECLARE_TLV_DB_SCALE(out_sidetone_tlv, -3600, 0, 0);
static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int reg = mc->reg;
@@ -117,19 +117,23 @@ static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
static const char *wm8400_digital_sidetone[] =
{"None", "Left ADC", "Right ADC", "Reserved"};
-static const struct soc_enum wm8400_left_digital_sidetone_enum =
-SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE,
- WM8400_ADC_TO_DACL_SHIFT, 2, wm8400_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8400_left_digital_sidetone_enum,
+ WM8400_DIGITAL_SIDE_TONE,
+ WM8400_ADC_TO_DACL_SHIFT,
+ wm8400_digital_sidetone);
-static const struct soc_enum wm8400_right_digital_sidetone_enum =
-SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE,
- WM8400_ADC_TO_DACR_SHIFT, 2, wm8400_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8400_right_digital_sidetone_enum,
+ WM8400_DIGITAL_SIDE_TONE,
+ WM8400_ADC_TO_DACR_SHIFT,
+ wm8400_digital_sidetone);
static const char *wm8400_adcmode[] =
{"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
-static const struct soc_enum wm8400_right_adcmode_enum =
-SOC_ENUM_SINGLE(WM8400_ADC_CTRL, WM8400_ADC_HPF_CUT_SHIFT, 3, wm8400_adcmode);
+static SOC_ENUM_SINGLE_DECL(wm8400_right_adcmode_enum,
+ WM8400_ADC_CTRL,
+ WM8400_ADC_HPF_CUT_SHIFT,
+ wm8400_adcmode);
static const struct snd_kcontrol_new wm8400_snd_controls[] = {
/* INMIXL */
@@ -422,9 +426,10 @@ SOC_DAPM_SINGLE("RINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT,
static const char *wm8400_ainlmux[] =
{"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
-static const struct soc_enum wm8400_ainlmux_enum =
-SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINLMODE_SHIFT,
- ARRAY_SIZE(wm8400_ainlmux), wm8400_ainlmux);
+static SOC_ENUM_SINGLE_DECL(wm8400_ainlmux_enum,
+ WM8400_INPUT_MIXER1,
+ WM8400_AINLMODE_SHIFT,
+ wm8400_ainlmux);
static const struct snd_kcontrol_new wm8400_dapm_ainlmux_controls =
SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum);
@@ -435,9 +440,10 @@ SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum);
static const char *wm8400_ainrmux[] =
{"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
-static const struct soc_enum wm8400_ainrmux_enum =
-SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINRMODE_SHIFT,
- ARRAY_SIZE(wm8400_ainrmux), wm8400_ainrmux);
+static SOC_ENUM_SINGLE_DECL(wm8400_ainrmux_enum,
+ WM8400_INPUT_MIXER1,
+ WM8400_AINRMODE_SHIFT,
+ wm8400_ainrmux);
static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls =
SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum);
@@ -1310,11 +1316,8 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
snd_soc_codec_set_drvdata(codec, priv);
priv->wm8400 = wm8400;
- codec->control_data = wm8400->regmap;
priv->codec = codec;
- snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
-
ret = devm_regulator_bulk_get(wm8400->dev,
ARRAY_SIZE(power), &power[0]);
if (ret != 0) {
@@ -1356,11 +1359,19 @@ static int wm8400_codec_remove(struct snd_soc_codec *codec)
return 0;
}
+static struct regmap *wm8400_get_regmap(struct device *dev)
+{
+ struct wm8400 *wm8400 = dev_get_platdata(dev);
+
+ return wm8400->regmap;
+}
+
static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
.probe = wm8400_codec_probe,
.remove = wm8400_codec_remove,
.suspend = wm8400_suspend,
.resume = wm8400_resume,
+ .get_regmap = wm8400_get_regmap,
.set_bias_level = wm8400_set_bias_level,
.controls = wm8400_snd_controls,
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 7df7d457275..1c1e328feeb 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -589,20 +589,12 @@ static int wm8510_resume(struct snd_soc_codec *codec)
static int wm8510_probe(struct snd_soc_codec *codec)
{
- int ret;
-
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
wm8510_reset(codec);
/* power on device */
wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- return ret;
+ return 0;
}
/* power down chip */
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 74d106dc766..601ee8178af 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -75,8 +75,8 @@ static const char *wm8523_zd_count_text[] = {
"2048",
};
-static const struct soc_enum wm8523_zc_count =
- SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text);
+static SOC_ENUM_SINGLE_DECL(wm8523_zc_count, WM8523_ZERO_DETECT, 0,
+ wm8523_zd_count_text);
static const struct snd_kcontrol_new wm8523_controls[] = {
SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR,
@@ -392,18 +392,11 @@ static int wm8523_resume(struct snd_soc_codec *codec)
static int wm8523_probe(struct snd_soc_codec *codec)
{
struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
- int ret;
wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
wm8523->rate_constraint.count =
ARRAY_SIZE(wm8523->rate_constraint_list);
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
/* Change some default settings - latch VU and enable ZC */
snd_soc_update_bits(codec, WM8523_DAC_GAINR,
WM8523_DACR_VU, WM8523_DACR_VU);
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 318989acbbe..7665ff6aea6 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -252,7 +252,7 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
unsigned int reg = mc->reg;
unsigned int reg2 = mc->rreg;
@@ -504,8 +504,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
u16 paifa = 0;
u16 paifb = 0;
@@ -869,12 +868,6 @@ static int wm8580_probe(struct snd_soc_codec *codec)
struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies),
wm8580->supplies);
if (ret != 0) {
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index d99f948c513..b0fbcb377ba 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -201,7 +201,7 @@ static void wm8711_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = dai->codec;
/* deactivate */
- if (!codec->active) {
+ if (!snd_soc_codec_is_active(codec)) {
udelay(50);
snd_soc_write(codec, WM8711_ACTIVE, 0x0);
}
@@ -367,12 +367,6 @@ static int wm8711_probe(struct snd_soc_codec *codec)
{
int ret;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = wm8711_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index cd89033e84c..bac7fc28fe7 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -228,19 +228,10 @@ static int wm8728_resume(struct snd_soc_codec *codec)
static int wm8728_probe(struct snd_soc_codec *codec)
{
- int ret;
-
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n",
- ret);
- return ret;
- }
-
/* power on device */
wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- return ret;
+ return 0;
}
static int wm8728_remove(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 029720366ff..5ada6161132 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -83,8 +83,8 @@ static bool wm8731_writeable(struct device *dev, unsigned int reg)
static const char *wm8731_input_select[] = {"Line In", "Mic"};
-static const struct soc_enum wm8731_insel_enum =
- SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select);
+static SOC_ENUM_SINGLE_DECL(wm8731_insel_enum,
+ WM8731_APANA, 2, wm8731_input_select);
static int wm8731_deemph[] = { 0, 32000, 44100, 48000 };
@@ -119,7 +119,7 @@ static int wm8731_set_deemph(struct snd_soc_codec *codec)
static int wm8731_get_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = wm8731->deemph;
@@ -130,7 +130,7 @@ static int wm8731_get_deemph(struct snd_kcontrol *kcontrol,
static int wm8731_put_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
int deemph = ucontrol->value.enumerated.item[0];
int ret = 0;
@@ -583,17 +583,10 @@ static int wm8731_probe(struct snd_soc_codec *codec)
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
int ret = 0, i;
- codec->control_data = wm8731->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++)
wm8731->supplies[i].supply = wm8731_supply_names[i];
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies),
+ ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies),
wm8731->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
@@ -604,7 +597,7 @@ static int wm8731_probe(struct snd_soc_codec *codec)
wm8731->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
- goto err_regulator_get;
+ return ret;
}
ret = wm8731_reset(codec);
@@ -631,8 +624,6 @@ static int wm8731_probe(struct snd_soc_codec *codec)
err_regulator_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
-err_regulator_get:
- regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
return ret;
}
@@ -645,7 +636,6 @@ static int wm8731_remove(struct snd_soc_codec *codec)
wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
- regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
return 0;
}
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
index 2f167a8ca01..b27f26cdc04 100644
--- a/sound/soc/codecs/wm8737.c
+++ b/sound/soc/codecs/wm8737.c
@@ -99,29 +99,29 @@ static const char *micbias_enum_text[] = {
"100%",
};
-static const struct soc_enum micbias_enum =
- SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 0, 4, micbias_enum_text);
+static SOC_ENUM_SINGLE_DECL(micbias_enum,
+ WM8737_MIC_PREAMP_CONTROL, 0, micbias_enum_text);
static const char *low_cutoff_text[] = {
"Low", "High"
};
-static const struct soc_enum low_3d =
- SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 6, 2, low_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(low_3d,
+ WM8737_3D_ENHANCE, 6, low_cutoff_text);
static const char *high_cutoff_text[] = {
"High", "Low"
};
-static const struct soc_enum high_3d =
- SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 5, 2, high_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(high_3d,
+ WM8737_3D_ENHANCE, 5, high_cutoff_text);
static const char *alc_fn_text[] = {
"Disabled", "Right", "Left", "Stereo"
};
-static const struct soc_enum alc_fn =
- SOC_ENUM_SINGLE(WM8737_ALC1, 7, 4, alc_fn_text);
+static SOC_ENUM_SINGLE_DECL(alc_fn,
+ WM8737_ALC1, 7, alc_fn_text);
static const char *alc_hold_text[] = {
"0", "2.67ms", "5.33ms", "10.66ms", "21.32ms", "42.64ms", "85.28ms",
@@ -129,24 +129,24 @@ static const char *alc_hold_text[] = {
"10.916s", "21.832s", "43.691s"
};
-static const struct soc_enum alc_hold =
- SOC_ENUM_SINGLE(WM8737_ALC2, 0, 16, alc_hold_text);
+static SOC_ENUM_SINGLE_DECL(alc_hold,
+ WM8737_ALC2, 0, alc_hold_text);
static const char *alc_atk_text[] = {
"8.4ms", "16.8ms", "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms",
"1.075s", "2.15s", "4.3s", "8.6s"
};
-static const struct soc_enum alc_atk =
- SOC_ENUM_SINGLE(WM8737_ALC3, 0, 11, alc_atk_text);
+static SOC_ENUM_SINGLE_DECL(alc_atk,
+ WM8737_ALC3, 0, alc_atk_text);
static const char *alc_dcy_text[] = {
"33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", "1.075s", "2.15s",
"4.3s", "8.6s", "17.2s", "34.41s"
};
-static const struct soc_enum alc_dcy =
- SOC_ENUM_SINGLE(WM8737_ALC3, 4, 11, alc_dcy_text);
+static SOC_ENUM_SINGLE_DECL(alc_dcy,
+ WM8737_ALC3, 4, alc_dcy_text);
static const struct snd_kcontrol_new wm8737_snd_controls[] = {
SOC_DOUBLE_R_TLV("Mic Boost Volume", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R,
@@ -191,8 +191,8 @@ static const char *linsel_text[] = {
"LINPUT1", "LINPUT2", "LINPUT3", "LINPUT1 DC",
};
-static const struct soc_enum linsel_enum =
- SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_L, 7, 4, linsel_text);
+static SOC_ENUM_SINGLE_DECL(linsel_enum,
+ WM8737_AUDIO_PATH_L, 7, linsel_text);
static const struct snd_kcontrol_new linsel_mux =
SOC_DAPM_ENUM("LINSEL", linsel_enum);
@@ -202,8 +202,8 @@ static const char *rinsel_text[] = {
"RINPUT1", "RINPUT2", "RINPUT3", "RINPUT1 DC",
};
-static const struct soc_enum rinsel_enum =
- SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_R, 7, 4, rinsel_text);
+static SOC_ENUM_SINGLE_DECL(rinsel_enum,
+ WM8737_AUDIO_PATH_R, 7, rinsel_text);
static const struct snd_kcontrol_new rinsel_mux =
SOC_DAPM_ENUM("RINSEL", rinsel_enum);
@@ -212,15 +212,15 @@ static const char *bypass_text[] = {
"Direct", "Preamp"
};
-static const struct soc_enum lbypass_enum =
- SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 2, 2, bypass_text);
+static SOC_ENUM_SINGLE_DECL(lbypass_enum,
+ WM8737_MIC_PREAMP_CONTROL, 2, bypass_text);
static const struct snd_kcontrol_new lbypass_mux =
SOC_DAPM_ENUM("Left Bypass", lbypass_enum);
-static const struct soc_enum rbypass_enum =
- SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 3, 2, bypass_text);
+static SOC_ENUM_SINGLE_DECL(rbypass_enum,
+ WM8737_MIC_PREAMP_CONTROL, 3, bypass_text);
static const struct snd_kcontrol_new rbypass_mux =
SOC_DAPM_ENUM("Left Bypass", rbypass_enum);
@@ -570,12 +570,6 @@ static int wm8737_probe(struct snd_soc_codec *codec)
struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec);
int ret;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies),
wm8737->supplies);
if (ret != 0) {
@@ -644,7 +638,7 @@ static const struct regmap_config wm8737_regmap = {
.volatile_reg = wm8737_volatile,
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
static int wm8737_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -758,7 +752,7 @@ static struct spi_driver wm8737_spi_driver = {
static int __init wm8737_modinit(void)
{
int ret;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
ret = i2c_add_driver(&wm8737_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register WM8737 I2C driver: %d\n",
@@ -781,7 +775,7 @@ static void __exit wm8737_exit(void)
#if defined(CONFIG_SPI_MASTER)
spi_unregister_driver(&wm8737_spi_driver);
#endif
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
i2c_del_driver(&wm8737_i2c_driver);
#endif
}
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 2895c8d3b5e..b33542a0460 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -44,7 +44,7 @@ struct wm8741_priv {
struct regmap *regmap;
struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];
unsigned int sysclk;
- struct snd_pcm_hw_constraint_list *sysclk_constraints;
+ const struct snd_pcm_hw_constraint_list *sysclk_constraints;
};
static const struct reg_default wm8741_reg_defaults[] = {
@@ -122,74 +122,74 @@ static struct {
{ 6, 768 },
};
-static unsigned int rates_11289[] = {
+static const unsigned int rates_11289[] = {
44100, 88235,
};
-static struct snd_pcm_hw_constraint_list constraints_11289 = {
+static const struct snd_pcm_hw_constraint_list constraints_11289 = {
.count = ARRAY_SIZE(rates_11289),
.list = rates_11289,
};
-static unsigned int rates_12288[] = {
+static const unsigned int rates_12288[] = {
32000, 48000, 96000,
};
-static struct snd_pcm_hw_constraint_list constraints_12288 = {
+static const struct snd_pcm_hw_constraint_list constraints_12288 = {
.count = ARRAY_SIZE(rates_12288),
.list = rates_12288,
};
-static unsigned int rates_16384[] = {
+static const unsigned int rates_16384[] = {
32000,
};
-static struct snd_pcm_hw_constraint_list constraints_16384 = {
+static const struct snd_pcm_hw_constraint_list constraints_16384 = {
.count = ARRAY_SIZE(rates_16384),
.list = rates_16384,
};
-static unsigned int rates_16934[] = {
+static const unsigned int rates_16934[] = {
44100, 88235,
};
-static struct snd_pcm_hw_constraint_list constraints_16934 = {
+static const struct snd_pcm_hw_constraint_list constraints_16934 = {
.count = ARRAY_SIZE(rates_16934),
.list = rates_16934,
};
-static unsigned int rates_18432[] = {
+static const unsigned int rates_18432[] = {
48000, 96000,
};
-static struct snd_pcm_hw_constraint_list constraints_18432 = {
+static const struct snd_pcm_hw_constraint_list constraints_18432 = {
.count = ARRAY_SIZE(rates_18432),
.list = rates_18432,
};
-static unsigned int rates_22579[] = {
+static const unsigned int rates_22579[] = {
44100, 88235, 1764000
};
-static struct snd_pcm_hw_constraint_list constraints_22579 = {
+static const struct snd_pcm_hw_constraint_list constraints_22579 = {
.count = ARRAY_SIZE(rates_22579),
.list = rates_22579,
};
-static unsigned int rates_24576[] = {
+static const unsigned int rates_24576[] = {
32000, 48000, 96000, 192000
};
-static struct snd_pcm_hw_constraint_list constraints_24576 = {
+static const struct snd_pcm_hw_constraint_list constraints_24576 = {
.count = ARRAY_SIZE(rates_24576),
.list = rates_24576,
};
-static unsigned int rates_36864[] = {
+static const unsigned int rates_36864[] = {
48000, 96000, 19200
};
-static struct snd_pcm_hw_constraint_list constraints_36864 = {
+static const struct snd_pcm_hw_constraint_list constraints_36864 = {
.count = ARRAY_SIZE(rates_36864),
.list = rates_36864,
};
@@ -429,12 +429,6 @@ static int wm8741_probe(struct snd_soc_codec *codec)
goto err_get;
}
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err_enable;
- }
-
ret = wm8741_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 78616a638a5..33990b63d21 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -702,12 +702,6 @@ static int wm8750_probe(struct snd_soc_codec *codec)
{
int ret;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = wm8750_reset(codec);
if (ret < 0) {
printk(KERN_ERR "wm8750: failed to reset: %d\n", ret);
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index be85da93a26..53e57b4049a 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -234,7 +234,7 @@ SOC_ENUM_SINGLE(WM8753_OUTCTL, 2, 2, wm8753_rout2_phase),
static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = wm8753->dai_func;
@@ -244,14 +244,14 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
u16 ioctl;
if (wm8753->dai_func == ucontrol->value.integer.value[0])
return 0;
- if (codec->active)
+ if (snd_soc_codec_is_active(codec))
return -EBUSY;
ioctl = snd_soc_read(codec, WM8753_IOCTL);
@@ -1314,7 +1314,7 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)
/* the digital mute covers the HiFi and Voice DAC's on the WM8753.
* make sure we check if they are not both active when we mute */
if (mute && wm8753->dai_func == 1) {
- if (!codec->active)
+ if (!snd_soc_codec_is_active(codec))
snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
} else {
if (mute)
@@ -1440,7 +1440,6 @@ static void wm8753_work(struct work_struct *work)
static int wm8753_suspend(struct snd_soc_codec *codec)
{
wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
- codec->cache_sync = 1;
return 0;
}
@@ -1471,13 +1470,6 @@ static int wm8753_probe(struct snd_soc_codec *codec)
INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work);
- codec->control_data = wm8753->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = wm8753_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index 89a18d82f30..c61aeb38efb 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -196,8 +196,8 @@ static const char *ain_text[] = {
"AIN5", "AIN6", "AIN7", "AIN8"
};
-static const struct soc_enum ain_enum =
- SOC_ENUM_DOUBLE(WM8770_ADCMUX, 0, 4, 8, ain_text);
+static SOC_ENUM_DOUBLE_DECL(ain_enum,
+ WM8770_ADCMUX, 0, 4, ain_text);
static const struct snd_kcontrol_new ain_mux =
SOC_DAPM_ENUM("Capture Mux", ain_enum);
@@ -580,12 +580,6 @@ static int wm8770_probe(struct snd_soc_codec *codec)
wm8770 = snd_soc_codec_get_drvdata(codec);
wm8770->codec = codec;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies),
wm8770->supplies);
if (ret) {
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index ef824672523..70952ceb278 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -430,12 +430,6 @@ static int wm8776_probe(struct snd_soc_codec *codec)
{
int ret = 0;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = wm8776_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index 9bc8206a680..d96e5963ee3 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -63,6 +63,7 @@ struct wm8804_priv {
struct regmap *regmap;
struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
struct notifier_block disable_nb[WM8804_NUM_SUPPLIES];
+ int mclk_div;
};
static int txsrc_get(struct snd_kcontrol *kcontrol,
@@ -92,7 +93,7 @@ WM8804_REGULATOR_EVENT(0)
WM8804_REGULATOR_EVENT(1)
static const char *txsrc_text[] = { "S/PDIF RX", "AIF" };
-static const SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text);
+static SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text);
static const struct snd_kcontrol_new wm8804_snd_controls[] = {
SOC_ENUM_EXT("Input Source", txsrc, txsrc_get, txsrc_put),
@@ -106,7 +107,7 @@ static int txsrc_get(struct snd_kcontrol *kcontrol,
struct snd_soc_codec *codec;
unsigned int src;
- codec = snd_kcontrol_chip(kcontrol);
+ codec = snd_soc_kcontrol_codec(kcontrol);
src = snd_soc_read(codec, WM8804_SPDTX4);
if (src & 0x40)
ucontrol->value.integer.value[0] = 1;
@@ -122,7 +123,7 @@ static int txsrc_put(struct snd_kcontrol *kcontrol,
struct snd_soc_codec *codec;
unsigned int src, txpwr;
- codec = snd_kcontrol_chip(kcontrol);
+ codec = snd_soc_kcontrol_codec(kcontrol);
if (ucontrol->value.integer.value[0] != 0
&& ucontrol->value.integer.value[0] != 1)
@@ -318,7 +319,7 @@ static struct {
#define FIXED_PLL_SIZE ((1ULL << 22) * 10)
static int pll_factors(struct pll_div *pll_div, unsigned int target,
- unsigned int source)
+ unsigned int source, unsigned int mclk_div)
{
u64 Kpart;
unsigned long int K, Ndiv, Nmod, tmp;
@@ -330,7 +331,8 @@ static int pll_factors(struct pll_div *pll_div, unsigned int target,
*/
for (i = 0; i < ARRAY_SIZE(post_table); i++) {
tmp = target * post_table[i].div;
- if (tmp >= 90000000 && tmp <= 100000000) {
+ if ((tmp >= 90000000 && tmp <= 100000000) &&
+ (mclk_div == post_table[i].mclkdiv)) {
pll_div->freqmode = post_table[i].freqmode;
pll_div->mclkdiv = post_table[i].mclkdiv;
target *= post_table[i].div;
@@ -387,8 +389,12 @@ static int wm8804_set_pll(struct snd_soc_dai *dai, int pll_id,
} else {
int ret;
struct pll_div pll_div;
+ struct wm8804_priv *wm8804;
- ret = pll_factors(&pll_div, freq_out, freq_in);
+ wm8804 = snd_soc_codec_get_drvdata(codec);
+
+ ret = pll_factors(&pll_div, freq_out, freq_in,
+ wm8804->mclk_div);
if (ret)
return ret;
@@ -452,6 +458,7 @@ static int wm8804_set_clkdiv(struct snd_soc_dai *dai,
int div_id, int div)
{
struct snd_soc_codec *codec;
+ struct wm8804_priv *wm8804;
codec = dai->codec;
switch (div_id) {
@@ -459,6 +466,10 @@ static int wm8804_set_clkdiv(struct snd_soc_dai *dai,
snd_soc_update_bits(codec, WM8804_PLL5, 0x30,
(div & 0x3) << 4);
break;
+ case WM8804_MCLK_DIV:
+ wm8804 = snd_soc_codec_get_drvdata(codec);
+ wm8804->mclk_div = div;
+ break;
default:
dev_err(dai->dev, "Unknown clock divider: %d\n", div_id);
return -EINVAL;
@@ -535,7 +546,6 @@ static int wm8804_remove(struct snd_soc_codec *codec)
for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i)
regulator_unregister_notifier(wm8804->supplies[i].consumer,
&wm8804->disable_nb[i]);
- regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
return 0;
}
@@ -546,18 +556,10 @@ static int wm8804_probe(struct snd_soc_codec *codec)
wm8804 = snd_soc_codec_get_drvdata(codec);
- codec->control_data = wm8804->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
- return ret;
- }
-
for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
wm8804->supplies[i].supply = wm8804_supply_names[i];
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8804->supplies),
+ ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8804->supplies),
wm8804->supplies);
if (ret) {
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
@@ -582,7 +584,7 @@ static int wm8804_probe(struct snd_soc_codec *codec)
wm8804->supplies);
if (ret) {
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
- goto err_reg_get;
+ return ret;
}
id1 = snd_soc_read(codec, WM8804_RST_DEVID1);
@@ -627,8 +629,6 @@ static int wm8804_probe(struct snd_soc_codec *codec)
err_reg_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
-err_reg_get:
- regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
return ret;
}
diff --git a/sound/soc/codecs/wm8804.h b/sound/soc/codecs/wm8804.h
index 8ec14f5573c..e72d4f4ba6b 100644
--- a/sound/soc/codecs/wm8804.h
+++ b/sound/soc/codecs/wm8804.h
@@ -57,5 +57,9 @@
#define WM8804_CLKOUT_SRC_OSCCLK 4
#define WM8804_CLKOUT_DIV 1
+#define WM8804_MCLK_DIV 2
+
+#define WM8804_MCLKDIV_256FS 0
+#define WM8804_MCLKDIV_128FS 1
#endif /* _WM8804_H */
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index e98bc7038a0..d09fdce57f5 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -304,53 +304,53 @@ static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1);
static const char *mic_bias_level_txt[] = { "0.9*AVDD", "0.65*AVDD" };
-static const struct soc_enum mic_bias_level =
-SOC_ENUM_SINGLE(WM8900_REG_INCTL, 8, 2, mic_bias_level_txt);
+static SOC_ENUM_SINGLE_DECL(mic_bias_level,
+ WM8900_REG_INCTL, 8, mic_bias_level_txt);
static const char *dac_mute_rate_txt[] = { "Fast", "Slow" };
-static const struct soc_enum dac_mute_rate =
-SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 7, 2, dac_mute_rate_txt);
+static SOC_ENUM_SINGLE_DECL(dac_mute_rate,
+ WM8900_REG_DACCTRL, 7, dac_mute_rate_txt);
static const char *dac_deemphasis_txt[] = {
"Disabled", "32kHz", "44.1kHz", "48kHz"
};
-static const struct soc_enum dac_deemphasis =
-SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 4, 4, dac_deemphasis_txt);
+static SOC_ENUM_SINGLE_DECL(dac_deemphasis,
+ WM8900_REG_DACCTRL, 4, dac_deemphasis_txt);
static const char *adc_hpf_cut_txt[] = {
"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"
};
-static const struct soc_enum adc_hpf_cut =
-SOC_ENUM_SINGLE(WM8900_REG_ADCCTRL, 5, 4, adc_hpf_cut_txt);
+static SOC_ENUM_SINGLE_DECL(adc_hpf_cut,
+ WM8900_REG_ADCCTRL, 5, adc_hpf_cut_txt);
static const char *lr_txt[] = {
"Left", "Right"
};
-static const struct soc_enum aifl_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 15, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(aifl_src,
+ WM8900_REG_AUDIO1, 15, lr_txt);
-static const struct soc_enum aifr_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 14, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(aifr_src,
+ WM8900_REG_AUDIO1, 14, lr_txt);
-static const struct soc_enum dacl_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 15, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(dacl_src,
+ WM8900_REG_AUDIO2, 15, lr_txt);
-static const struct soc_enum dacr_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 14, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(dacr_src,
+ WM8900_REG_AUDIO2, 14, lr_txt);
static const char *sidetone_txt[] = {
"Disabled", "Left ADC", "Right ADC"
};
-static const struct soc_enum dacl_sidetone =
-SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 2, 3, sidetone_txt);
+static SOC_ENUM_SINGLE_DECL(dacl_sidetone,
+ WM8900_REG_SIDETONE, 2, sidetone_txt);
-static const struct soc_enum dacr_sidetone =
-SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 0, 3, sidetone_txt);
+static SOC_ENUM_SINGLE_DECL(dacr_sidetone,
+ WM8900_REG_SIDETONE, 0, sidetone_txt);
static const struct snd_kcontrol_new wm8900_snd_controls[] = {
SOC_ENUM("Mic Bias Level", mic_bias_level),
@@ -496,8 +496,8 @@ SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0),
static const char *wm8900_lp_mux[] = { "Disabled", "Enabled" };
-static const struct soc_enum wm8900_lineout2_lp_mux =
-SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm8900_lp_mux);
+static SOC_ENUM_SINGLE_DECL(wm8900_lineout2_lp_mux,
+ WM8900_REG_LOUTMIXCTL1, 1, wm8900_lp_mux);
static const struct snd_kcontrol_new wm8900_lineout2_lp =
SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux);
@@ -1178,13 +1178,7 @@ static int wm8900_resume(struct snd_soc_codec *codec)
static int wm8900_probe(struct snd_soc_codec *codec)
{
- int ret = 0, reg;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
+ int reg;
reg = snd_soc_read(codec, WM8900_REG_ID);
if (reg != 0x8900) {
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index eebcb1da3b7..b84940c359a 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -439,7 +439,7 @@ static int wm8903_set_deemph(struct snd_soc_codec *codec)
static int wm8903_get_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = wm8903->deemph;
@@ -450,7 +450,7 @@ static int wm8903_get_deemph(struct snd_kcontrol *kcontrol,
static int wm8903_put_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
int deemph = ucontrol->value.enumerated.item[0];
int ret = 0;
@@ -489,28 +489,28 @@ static const char *hpf_mode_text[] = {
"Hi-fi", "Voice 1", "Voice 2", "Voice 3"
};
-static const struct soc_enum hpf_mode =
- SOC_ENUM_SINGLE(WM8903_ADC_DIGITAL_0, 5, 4, hpf_mode_text);
+static SOC_ENUM_SINGLE_DECL(hpf_mode,
+ WM8903_ADC_DIGITAL_0, 5, hpf_mode_text);
static const char *osr_text[] = {
"Low power", "High performance"
};
-static const struct soc_enum adc_osr =
- SOC_ENUM_SINGLE(WM8903_ANALOGUE_ADC_0, 0, 2, osr_text);
+static SOC_ENUM_SINGLE_DECL(adc_osr,
+ WM8903_ANALOGUE_ADC_0, 0, osr_text);
-static const struct soc_enum dac_osr =
- SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 0, 2, osr_text);
+static SOC_ENUM_SINGLE_DECL(dac_osr,
+ WM8903_DAC_DIGITAL_1, 0, osr_text);
static const char *drc_slope_text[] = {
"1", "1/2", "1/4", "1/8", "1/16", "0"
};
-static const struct soc_enum drc_slope_r0 =
- SOC_ENUM_SINGLE(WM8903_DRC_2, 3, 6, drc_slope_text);
+static SOC_ENUM_SINGLE_DECL(drc_slope_r0,
+ WM8903_DRC_2, 3, drc_slope_text);
-static const struct soc_enum drc_slope_r1 =
- SOC_ENUM_SINGLE(WM8903_DRC_2, 0, 6, drc_slope_text);
+static SOC_ENUM_SINGLE_DECL(drc_slope_r1,
+ WM8903_DRC_2, 0, drc_slope_text);
static const char *drc_attack_text[] = {
"instantaneous",
@@ -518,125 +518,125 @@ static const char *drc_attack_text[] = {
"46.4ms", "92.8ms", "185.6ms"
};
-static const struct soc_enum drc_attack =
- SOC_ENUM_SINGLE(WM8903_DRC_1, 12, 11, drc_attack_text);
+static SOC_ENUM_SINGLE_DECL(drc_attack,
+ WM8903_DRC_1, 12, drc_attack_text);
static const char *drc_decay_text[] = {
"186ms", "372ms", "743ms", "1.49s", "2.97s", "5.94s", "11.89s",
"23.87s", "47.56s"
};
-static const struct soc_enum drc_decay =
- SOC_ENUM_SINGLE(WM8903_DRC_1, 8, 9, drc_decay_text);
+static SOC_ENUM_SINGLE_DECL(drc_decay,
+ WM8903_DRC_1, 8, drc_decay_text);
static const char *drc_ff_delay_text[] = {
"5 samples", "9 samples"
};
-static const struct soc_enum drc_ff_delay =
- SOC_ENUM_SINGLE(WM8903_DRC_0, 5, 2, drc_ff_delay_text);
+static SOC_ENUM_SINGLE_DECL(drc_ff_delay,
+ WM8903_DRC_0, 5, drc_ff_delay_text);
static const char *drc_qr_decay_text[] = {
"0.725ms", "1.45ms", "5.8ms"
};
-static const struct soc_enum drc_qr_decay =
- SOC_ENUM_SINGLE(WM8903_DRC_1, 4, 3, drc_qr_decay_text);
+static SOC_ENUM_SINGLE_DECL(drc_qr_decay,
+ WM8903_DRC_1, 4, drc_qr_decay_text);
static const char *drc_smoothing_text[] = {
"Low", "Medium", "High"
};
-static const struct soc_enum drc_smoothing =
- SOC_ENUM_SINGLE(WM8903_DRC_0, 11, 3, drc_smoothing_text);
+static SOC_ENUM_SINGLE_DECL(drc_smoothing,
+ WM8903_DRC_0, 11, drc_smoothing_text);
static const char *soft_mute_text[] = {
"Fast (fs/2)", "Slow (fs/32)"
};
-static const struct soc_enum soft_mute =
- SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 10, 2, soft_mute_text);
+static SOC_ENUM_SINGLE_DECL(soft_mute,
+ WM8903_DAC_DIGITAL_1, 10, soft_mute_text);
static const char *mute_mode_text[] = {
"Hard", "Soft"
};
-static const struct soc_enum mute_mode =
- SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 9, 2, mute_mode_text);
+static SOC_ENUM_SINGLE_DECL(mute_mode,
+ WM8903_DAC_DIGITAL_1, 9, mute_mode_text);
static const char *companding_text[] = {
"ulaw", "alaw"
};
-static const struct soc_enum dac_companding =
- SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 0, 2, companding_text);
+static SOC_ENUM_SINGLE_DECL(dac_companding,
+ WM8903_AUDIO_INTERFACE_0, 0, companding_text);
-static const struct soc_enum adc_companding =
- SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 2, 2, companding_text);
+static SOC_ENUM_SINGLE_DECL(adc_companding,
+ WM8903_AUDIO_INTERFACE_0, 2, companding_text);
static const char *input_mode_text[] = {
"Single-Ended", "Differential Line", "Differential Mic"
};
-static const struct soc_enum linput_mode_enum =
- SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text);
+static SOC_ENUM_SINGLE_DECL(linput_mode_enum,
+ WM8903_ANALOGUE_LEFT_INPUT_1, 0, input_mode_text);
-static const struct soc_enum rinput_mode_enum =
- SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text);
+static SOC_ENUM_SINGLE_DECL(rinput_mode_enum,
+ WM8903_ANALOGUE_RIGHT_INPUT_1, 0, input_mode_text);
static const char *linput_mux_text[] = {
"IN1L", "IN2L", "IN3L"
};
-static const struct soc_enum linput_enum =
- SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 2, 3, linput_mux_text);
+static SOC_ENUM_SINGLE_DECL(linput_enum,
+ WM8903_ANALOGUE_LEFT_INPUT_1, 2, linput_mux_text);
-static const struct soc_enum linput_inv_enum =
- SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 4, 3, linput_mux_text);
+static SOC_ENUM_SINGLE_DECL(linput_inv_enum,
+ WM8903_ANALOGUE_LEFT_INPUT_1, 4, linput_mux_text);
static const char *rinput_mux_text[] = {
"IN1R", "IN2R", "IN3R"
};
-static const struct soc_enum rinput_enum =
- SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 2, 3, rinput_mux_text);
+static SOC_ENUM_SINGLE_DECL(rinput_enum,
+ WM8903_ANALOGUE_RIGHT_INPUT_1, 2, rinput_mux_text);
-static const struct soc_enum rinput_inv_enum =
- SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text);
+static SOC_ENUM_SINGLE_DECL(rinput_inv_enum,
+ WM8903_ANALOGUE_RIGHT_INPUT_1, 4, rinput_mux_text);
static const char *sidetone_text[] = {
"None", "Left", "Right"
};
-static const struct soc_enum lsidetone_enum =
- SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 2, 3, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(lsidetone_enum,
+ WM8903_DAC_DIGITAL_0, 2, sidetone_text);
-static const struct soc_enum rsidetone_enum =
- SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(rsidetone_enum,
+ WM8903_DAC_DIGITAL_0, 0, sidetone_text);
static const char *adcinput_text[] = {
"ADC", "DMIC"
};
-static const struct soc_enum adcinput_enum =
- SOC_ENUM_SINGLE(WM8903_CLOCK_RATE_TEST_4, 9, 2, adcinput_text);
+static SOC_ENUM_SINGLE_DECL(adcinput_enum,
+ WM8903_CLOCK_RATE_TEST_4, 9, adcinput_text);
static const char *aif_text[] = {
"Left", "Right"
};
-static const struct soc_enum lcapture_enum =
- SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 7, 2, aif_text);
+static SOC_ENUM_SINGLE_DECL(lcapture_enum,
+ WM8903_AUDIO_INTERFACE_0, 7, aif_text);
-static const struct soc_enum rcapture_enum =
- SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 6, 2, aif_text);
+static SOC_ENUM_SINGLE_DECL(rcapture_enum,
+ WM8903_AUDIO_INTERFACE_0, 6, aif_text);
-static const struct soc_enum lplay_enum =
- SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 5, 2, aif_text);
+static SOC_ENUM_SINGLE_DECL(lplay_enum,
+ WM8903_AUDIO_INTERFACE_0, 5, aif_text);
-static const struct soc_enum rplay_enum =
- SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 4, 2, aif_text);
+static SOC_ENUM_SINGLE_DECL(rplay_enum,
+ WM8903_AUDIO_INTERFACE_0, 4, aif_text);
static const struct snd_kcontrol_new wm8903_snd_controls[] = {
@@ -1897,21 +1897,13 @@ static void wm8903_free_gpio(struct wm8903_priv *wm8903)
static int wm8903_probe(struct snd_soc_codec *codec)
{
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
- int ret;
wm8903->codec = codec;
- codec->control_data = wm8903->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
/* power on device */
wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- return ret;
+ return 0;
}
/* power down chip */
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 53bbfac6a83..f7c549949c5 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -391,7 +391,7 @@ static void wm8904_set_drc(struct snd_soc_codec *codec)
static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
struct wm8904_pdata *pdata = wm8904->pdata;
int value = ucontrol->value.integer.value[0];
@@ -409,7 +409,7 @@ static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol,
static int wm8904_get_drc_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = wm8904->drc_cfg;
@@ -462,7 +462,7 @@ static void wm8904_set_retune_mobile(struct snd_soc_codec *codec)
static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
struct wm8904_pdata *pdata = wm8904->pdata;
int value = ucontrol->value.integer.value[0];
@@ -480,7 +480,7 @@ static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
static int wm8904_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = wm8904->retune_mobile_cfg;
@@ -520,7 +520,7 @@ static int wm8904_set_deemph(struct snd_soc_codec *codec)
static int wm8904_get_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = wm8904->deemph;
@@ -530,7 +530,7 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol,
static int wm8904_put_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
int deemph = ucontrol->value.enumerated.item[0];
@@ -552,23 +552,25 @@ static const char *input_mode_text[] = {
"Single-Ended", "Differential Line", "Differential Mic"
};
-static const struct soc_enum lin_mode =
- SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text);
+static SOC_ENUM_SINGLE_DECL(lin_mode,
+ WM8904_ANALOGUE_LEFT_INPUT_1, 0,
+ input_mode_text);
-static const struct soc_enum rin_mode =
- SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text);
+static SOC_ENUM_SINGLE_DECL(rin_mode,
+ WM8904_ANALOGUE_RIGHT_INPUT_1, 0,
+ input_mode_text);
static const char *hpf_mode_text[] = {
"Hi-fi", "Voice 1", "Voice 2", "Voice 3"
};
-static const struct soc_enum hpf_mode =
- SOC_ENUM_SINGLE(WM8904_ADC_DIGITAL_0, 5, 4, hpf_mode_text);
+static SOC_ENUM_SINGLE_DECL(hpf_mode, WM8904_ADC_DIGITAL_0, 5,
+ hpf_mode_text);
static int wm8904_adc_osr_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int val;
int ret;
@@ -611,8 +613,7 @@ static const char *drc_path_text[] = {
"ADC", "DAC"
};
-static const struct soc_enum drc_path =
- SOC_ENUM_SINGLE(WM8904_DRC_0, 14, 2, drc_path_text);
+static SOC_ENUM_SINGLE_DECL(drc_path, WM8904_DRC_0, 14, drc_path_text);
static const struct snd_kcontrol_new wm8904_dac_snd_controls[] = {
SOC_SINGLE_TLV("Digital Playback Boost Volume",
@@ -858,14 +859,14 @@ static const char *lin_text[] = {
"IN1L", "IN2L", "IN3L"
};
-static const struct soc_enum lin_enum =
- SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 2, 3, lin_text);
+static SOC_ENUM_SINGLE_DECL(lin_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 2,
+ lin_text);
static const struct snd_kcontrol_new lin_mux =
SOC_DAPM_ENUM("Left Capture Mux", lin_enum);
-static const struct soc_enum lin_inv_enum =
- SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 4, 3, lin_text);
+static SOC_ENUM_SINGLE_DECL(lin_inv_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 4,
+ lin_text);
static const struct snd_kcontrol_new lin_inv_mux =
SOC_DAPM_ENUM("Left Capture Inveting Mux", lin_inv_enum);
@@ -874,14 +875,14 @@ static const char *rin_text[] = {
"IN1R", "IN2R", "IN3R"
};
-static const struct soc_enum rin_enum =
- SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 2, 3, rin_text);
+static SOC_ENUM_SINGLE_DECL(rin_enum, WM8904_ANALOGUE_RIGHT_INPUT_1, 2,
+ rin_text);
static const struct snd_kcontrol_new rin_mux =
SOC_DAPM_ENUM("Right Capture Mux", rin_enum);
-static const struct soc_enum rin_inv_enum =
- SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 4, 3, rin_text);
+static SOC_ENUM_SINGLE_DECL(rin_inv_enum, WM8904_ANALOGUE_RIGHT_INPUT_1, 4,
+ rin_text);
static const struct snd_kcontrol_new rin_inv_mux =
SOC_DAPM_ENUM("Right Capture Inveting Mux", rin_inv_enum);
@@ -890,26 +891,26 @@ static const char *aif_text[] = {
"Left", "Right"
};
-static const struct soc_enum aifoutl_enum =
- SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 7, 2, aif_text);
+static SOC_ENUM_SINGLE_DECL(aifoutl_enum, WM8904_AUDIO_INTERFACE_0, 7,
+ aif_text);
static const struct snd_kcontrol_new aifoutl_mux =
SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum);
-static const struct soc_enum aifoutr_enum =
- SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 6, 2, aif_text);
+static SOC_ENUM_SINGLE_DECL(aifoutr_enum, WM8904_AUDIO_INTERFACE_0, 6,
+ aif_text);
static const struct snd_kcontrol_new aifoutr_mux =
SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum);
-static const struct soc_enum aifinl_enum =
- SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 5, 2, aif_text);
+static SOC_ENUM_SINGLE_DECL(aifinl_enum, WM8904_AUDIO_INTERFACE_0, 5,
+ aif_text);
static const struct snd_kcontrol_new aifinl_mux =
SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum);
-static const struct soc_enum aifinr_enum =
- SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 4, 2, aif_text);
+static SOC_ENUM_SINGLE_DECL(aifinr_enum, WM8904_AUDIO_INTERFACE_0, 4,
+ aif_text);
static const struct snd_kcontrol_new aifinr_mux =
SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum);
@@ -991,26 +992,26 @@ static const char *out_mux_text[] = {
"DAC", "Bypass"
};
-static const struct soc_enum hpl_enum =
- SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 3, 2, out_mux_text);
+static SOC_ENUM_SINGLE_DECL(hpl_enum, WM8904_ANALOGUE_OUT12_ZC, 3,
+ out_mux_text);
static const struct snd_kcontrol_new hpl_mux =
SOC_DAPM_ENUM("HPL Mux", hpl_enum);
-static const struct soc_enum hpr_enum =
- SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 2, 2, out_mux_text);
+static SOC_ENUM_SINGLE_DECL(hpr_enum, WM8904_ANALOGUE_OUT12_ZC, 2,
+ out_mux_text);
static const struct snd_kcontrol_new hpr_mux =
SOC_DAPM_ENUM("HPR Mux", hpr_enum);
-static const struct soc_enum linel_enum =
- SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 1, 2, out_mux_text);
+static SOC_ENUM_SINGLE_DECL(linel_enum, WM8904_ANALOGUE_OUT12_ZC, 1,
+ out_mux_text);
static const struct snd_kcontrol_new linel_mux =
SOC_DAPM_ENUM("LINEL Mux", linel_enum);
-static const struct soc_enum liner_enum =
- SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 0, 2, out_mux_text);
+static SOC_ENUM_SINGLE_DECL(liner_enum, WM8904_ANALOGUE_OUT12_ZC, 0,
+ out_mux_text);
static const struct snd_kcontrol_new liner_mux =
SOC_DAPM_ENUM("LINER Mux", liner_enum);
@@ -1019,14 +1020,14 @@ static const char *sidetone_text[] = {
"None", "Left", "Right"
};
-static const struct soc_enum dacl_sidetone_enum =
- SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 2, 3, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(dacl_sidetone_enum, WM8904_DAC_DIGITAL_0, 2,
+ sidetone_text);
static const struct snd_kcontrol_new dacl_sidetone_mux =
SOC_DAPM_ENUM("Left Sidetone Mux", dacl_sidetone_enum);
-static const struct soc_enum dacr_sidetone_enum =
- SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 0, 3, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(dacr_sidetone_enum, WM8904_DAC_DIGITAL_0, 0,
+ sidetone_text);
static const struct snd_kcontrol_new dacr_sidetone_mux =
SOC_DAPM_ENUM("Right Sidetone Mux", dacr_sidetone_enum);
@@ -1981,7 +1982,7 @@ static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec)
dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n",
wm8904->num_retune_mobile_texts);
- wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts;
+ wm8904->retune_mobile_enum.items = wm8904->num_retune_mobile_texts;
wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts;
ret = snd_soc_add_codec_controls(codec, &control, 1);
@@ -2022,7 +2023,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
for (i = 0; i < pdata->num_drc_cfgs; i++)
wm8904->drc_texts[i] = pdata->drc_cfgs[i].name;
- wm8904->drc_enum.max = pdata->num_drc_cfgs;
+ wm8904->drc_enum.items = pdata->num_drc_cfgs;
wm8904->drc_enum.texts = wm8904->drc_texts;
ret = snd_soc_add_codec_controls(codec, &control, 1);
@@ -2047,9 +2048,6 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
static int wm8904_probe(struct snd_soc_codec *codec)
{
struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- codec->control_data = wm8904->regmap;
switch (wm8904->devtype) {
case WM8904:
@@ -2063,12 +2061,6 @@ static int wm8904_probe(struct snd_soc_codec *codec)
return -EINVAL;
}
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
wm8904_handle_pdata(codec);
wm8904_add_widgets(codec);
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index b404c26c175..fc6eec9ad66 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -154,22 +154,22 @@ static const struct reg_default wm8940_reg_defaults[] = {
};
static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" };
-static const struct soc_enum wm8940_adc_companding_enum
-= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 1, 4, wm8940_companding);
-static const struct soc_enum wm8940_dac_companding_enum
-= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 3, 4, wm8940_companding);
+static SOC_ENUM_SINGLE_DECL(wm8940_adc_companding_enum,
+ WM8940_COMPANDINGCTL, 1, wm8940_companding);
+static SOC_ENUM_SINGLE_DECL(wm8940_dac_companding_enum,
+ WM8940_COMPANDINGCTL, 3, wm8940_companding);
static const char *wm8940_alc_mode_text[] = {"ALC", "Limiter"};
-static const struct soc_enum wm8940_alc_mode_enum
-= SOC_ENUM_SINGLE(WM8940_ALC3, 8, 2, wm8940_alc_mode_text);
+static SOC_ENUM_SINGLE_DECL(wm8940_alc_mode_enum,
+ WM8940_ALC3, 8, wm8940_alc_mode_text);
static const char *wm8940_mic_bias_level_text[] = {"0.9", "0.65"};
-static const struct soc_enum wm8940_mic_bias_level_enum
-= SOC_ENUM_SINGLE(WM8940_INPUTCTL, 8, 2, wm8940_mic_bias_level_text);
+static SOC_ENUM_SINGLE_DECL(wm8940_mic_bias_level_enum,
+ WM8940_INPUTCTL, 8, wm8940_mic_bias_level_text);
static const char *wm8940_filter_mode_text[] = {"Audio", "Application"};
-static const struct soc_enum wm8940_filter_mode_enum
-= SOC_ENUM_SINGLE(WM8940_ADC, 7, 2, wm8940_filter_mode_text);
+static SOC_ENUM_SINGLE_DECL(wm8940_filter_mode_enum,
+ WM8940_ADC, 7, wm8940_filter_mode_text);
static DECLARE_TLV_DB_SCALE(wm8940_spk_vol_tlv, -5700, 100, 1);
static DECLARE_TLV_DB_SCALE(wm8940_att_tlv, -1000, 1000, 0);
@@ -712,12 +712,6 @@ static int wm8940_probe(struct snd_soc_codec *codec)
int ret;
u16 reg;
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = wm8940_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 82c8ba97572..2a35108f233 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -390,7 +390,7 @@ static int wm8955_set_deemph(struct snd_soc_codec *codec)
static int wm8955_get_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = wm8955->deemph;
@@ -400,7 +400,7 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol,
static int wm8955_put_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
int deemph = ucontrol->value.enumerated.item[0];
@@ -416,22 +416,21 @@ static const char *bass_mode_text[] = {
"Linear", "Adaptive",
};
-static const struct soc_enum bass_mode =
- SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 7, 2, bass_mode_text);
+static SOC_ENUM_SINGLE_DECL(bass_mode, WM8955_BASS_CONTROL, 7, bass_mode_text);
static const char *bass_cutoff_text[] = {
"Low", "High"
};
-static const struct soc_enum bass_cutoff =
- SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 6, 2, bass_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(bass_cutoff, WM8955_BASS_CONTROL, 6,
+ bass_cutoff_text);
static const char *treble_cutoff_text[] = {
"High", "Low"
};
-static const struct soc_enum treble_cutoff =
- SOC_ENUM_SINGLE(WM8955_TREBLE_CONTROL, 6, 2, treble_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(treble_cutoff, WM8955_TREBLE_CONTROL, 2,
+ treble_cutoff_text);
static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1);
static const DECLARE_TLV_DB_SCALE(atten_tlv, -600, 600, 0);
@@ -896,18 +895,10 @@ static int wm8955_probe(struct snd_soc_codec *codec)
struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
int ret, i;
- codec->control_data = wm8955->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++)
wm8955->supplies[i].supply = wm8955_supply_names[i];
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8955->supplies),
+ ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8955->supplies),
wm8955->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
@@ -918,7 +909,7 @@ static int wm8955_probe(struct snd_soc_codec *codec)
wm8955->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
- goto err_get;
+ return ret;
}
ret = wm8955_reset(codec);
@@ -970,17 +961,12 @@ static int wm8955_probe(struct snd_soc_codec *codec)
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
-err_get:
- regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
return ret;
}
static int wm8955_remove(struct snd_soc_codec *codec)
{
- struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
-
wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
- regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
return 0;
}
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index b7488f190d2..b2ebb104d87 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -153,7 +153,7 @@ static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name,
data32 &= 0xffffff;
- wm8994_bulk_write(codec->control_data,
+ wm8994_bulk_write(wm8994->wm8994,
data32 & 0xffffff,
block_len / 2,
(void *)(data + 8));
@@ -456,7 +456,7 @@ static int wm8958_dsp2_busy(struct wm8994_priv *wm8994, int aif)
static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
int value = ucontrol->value.integer.value[0];
@@ -478,7 +478,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
static int wm8958_get_mbc_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = wm8994->mbc_cfg;
@@ -500,7 +500,7 @@ static int wm8958_mbc_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int mbc = kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = wm8994->mbc_ena[mbc];
@@ -512,7 +512,7 @@ static int wm8958_mbc_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int mbc = kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
if (wm8994->mbc_ena[mbc] == ucontrol->value.integer.value[0])
@@ -546,7 +546,7 @@ static int wm8958_mbc_put(struct snd_kcontrol *kcontrol,
static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
int value = ucontrol->value.integer.value[0];
@@ -568,7 +568,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
static int wm8958_get_vss_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = wm8994->vss_cfg;
@@ -579,7 +579,7 @@ static int wm8958_get_vss_enum(struct snd_kcontrol *kcontrol,
static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
int value = ucontrol->value.integer.value[0];
@@ -601,7 +601,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
static int wm8958_get_vss_hpf_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = wm8994->vss_hpf_cfg;
@@ -623,7 +623,7 @@ static int wm8958_vss_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int vss = kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = wm8994->vss_ena[vss];
@@ -635,7 +635,7 @@ static int wm8958_vss_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int vss = kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
if (wm8994->vss_ena[vss] == ucontrol->value.integer.value[0])
@@ -684,7 +684,7 @@ static int wm8958_hpf_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int hpf = kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
if (hpf < 3)
@@ -699,7 +699,7 @@ static int wm8958_hpf_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int hpf = kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
if (hpf < 3) {
@@ -746,7 +746,7 @@ static int wm8958_hpf_put(struct snd_kcontrol *kcontrol,
static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
int value = ucontrol->value.integer.value[0];
@@ -768,7 +768,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
static int wm8958_get_enh_eq_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = wm8994->enh_eq_cfg;
@@ -790,7 +790,7 @@ static int wm8958_enh_eq_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int eq = kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = wm8994->enh_eq_ena[eq];
@@ -802,7 +802,7 @@ static int wm8958_enh_eq_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int eq = kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
if (wm8994->enh_eq_ena[eq] == ucontrol->value.integer.value[0])
@@ -944,7 +944,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
for (i = 0; i < pdata->num_mbc_cfgs; i++)
wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name;
- wm8994->mbc_enum.max = pdata->num_mbc_cfgs;
+ wm8994->mbc_enum.items = pdata->num_mbc_cfgs;
wm8994->mbc_enum.texts = wm8994->mbc_texts;
ret = snd_soc_add_codec_controls(wm8994->hubs.codec,
@@ -973,7 +973,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
for (i = 0; i < pdata->num_vss_cfgs; i++)
wm8994->vss_texts[i] = pdata->vss_cfgs[i].name;
- wm8994->vss_enum.max = pdata->num_vss_cfgs;
+ wm8994->vss_enum.items = pdata->num_vss_cfgs;
wm8994->vss_enum.texts = wm8994->vss_texts;
ret = snd_soc_add_codec_controls(wm8994->hubs.codec,
@@ -1003,7 +1003,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
for (i = 0; i < pdata->num_vss_hpf_cfgs; i++)
wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name;
- wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs;
+ wm8994->vss_hpf_enum.items = pdata->num_vss_hpf_cfgs;
wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts;
ret = snd_soc_add_codec_controls(wm8994->hubs.codec,
@@ -1034,7 +1034,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
for (i = 0; i < pdata->num_enh_eq_cfgs; i++)
wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name;
- wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs;
+ wm8994->enh_eq_enum.items = pdata->num_enh_eq_cfgs;
wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts;
ret = snd_soc_add_codec_controls(wm8994->hubs.codec,
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index f156010e52b..a145d0431b6 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -178,7 +178,7 @@ static int wm8960_set_deemph(struct snd_soc_codec *codec)
static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = wm8960->deemph;
@@ -188,7 +188,7 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,
static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
int deemph = ucontrol->value.enumerated.item[0];
@@ -976,12 +976,6 @@ static int wm8960_probe(struct snd_soc_codec *codec)
wm8960->set_bias_level = wm8960_set_bias_level_capless;
}
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = wm8960_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 900328e28a1..9c88f04442b 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -317,15 +317,15 @@ static const char *adc_hpf_text[] = {
"Hi-fi", "Voice 1", "Voice 2", "Voice 3",
};
-static const struct soc_enum adc_hpf =
- SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_2, 7, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(adc_hpf,
+ WM8961_ADC_DAC_CONTROL_2, 7, adc_hpf_text);
static const char *dac_deemph_text[] = {
"None", "32kHz", "44.1kHz", "48kHz",
};
-static const struct soc_enum dac_deemph =
- SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_1, 1, 4, dac_deemph_text);
+static SOC_ENUM_SINGLE_DECL(dac_deemph,
+ WM8961_ADC_DAC_CONTROL_1, 1, dac_deemph_text);
static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0);
@@ -385,11 +385,11 @@ static const char *sidetone_text[] = {
"None", "Left", "Right"
};
-static const struct soc_enum dacl_sidetone =
- SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_0, 2, 3, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(dacl_sidetone,
+ WM8961_DSP_SIDETONE_0, 2, sidetone_text);
-static const struct soc_enum dacr_sidetone =
- SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_1, 2, 3, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(dacr_sidetone,
+ WM8961_DSP_SIDETONE_1, 2, sidetone_text);
static const struct snd_kcontrol_new dacl_mux =
SOC_DAPM_ENUM("DACL Sidetone", dacl_sidetone);
@@ -836,15 +836,8 @@ static struct snd_soc_dai_driver wm8961_dai = {
static int wm8961_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret = 0;
u16 reg;
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
/* Enable class W */
reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B);
reg |= WM8961_CP_DYN_PWR_MASK;
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 97db3b45b41..ca2fda9d72b 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -74,11 +74,9 @@ struct wm8962_priv {
struct regulator_bulk_data supplies[WM8962_NUM_SUPPLIES];
struct notifier_block disable_nb[WM8962_NUM_SUPPLIES];
-#if IS_ENABLED(CONFIG_INPUT)
struct input_dev *beep;
struct work_struct beep_work;
int beep_rate;
-#endif
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio_chip;
@@ -154,6 +152,7 @@ static struct reg_default wm8962_reg[] = {
{ 40, 0x0000 }, /* R40 - SPKOUTL volume */
{ 41, 0x0000 }, /* R41 - SPKOUTR volume */
+ { 49, 0x0010 }, /* R49 - Class D Control 1 */
{ 51, 0x0003 }, /* R51 - Class D Control 2 */
{ 56, 0x0506 }, /* R56 - Clocking 4 */
@@ -795,7 +794,6 @@ static bool wm8962_volatile_register(struct device *dev, unsigned int reg)
case WM8962_ALC2:
case WM8962_THERMAL_SHUTDOWN_STATUS:
case WM8962_ADDITIONAL_CONTROL_4:
- case WM8962_CLASS_D_CONTROL_1:
case WM8962_DC_SERVO_6:
case WM8962_INTERRUPT_STATUS_1:
case WM8962_INTERRUPT_STATUS_2:
@@ -1479,7 +1477,9 @@ static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
static int wm8962_dsp2_write_config(struct snd_soc_codec *codec)
{
- return regcache_sync_region(codec->control_data,
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+
+ return regcache_sync_region(wm8962->regmap,
WM8962_HDBASS_AI_1, WM8962_MAX_REGISTER);
}
@@ -1550,7 +1550,7 @@ static int wm8962_dsp2_ena_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int shift = kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = !!(wm8962->dsp2_ena & 1 << shift);
@@ -1562,7 +1562,7 @@ static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int shift = kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
int old = wm8962->dsp2_ena;
int ret = 0;
@@ -1600,7 +1600,7 @@ out:
static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
int ret;
/* Apply the update (if any) */
@@ -1630,7 +1630,7 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
int ret;
/* Apply the update (if any) */
@@ -1658,16 +1658,16 @@ static const char *cap_hpf_mode_text[] = {
"Hi-fi", "Application"
};
-static const struct soc_enum cap_hpf_mode =
- SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text);
+static SOC_ENUM_SINGLE_DECL(cap_hpf_mode,
+ WM8962_ADC_DAC_CONTROL_2, 10, cap_hpf_mode_text);
static const char *cap_lhpf_mode_text[] = {
"LPF", "HPF"
};
-static const struct soc_enum cap_lhpf_mode =
- SOC_ENUM_SINGLE(WM8962_LHPF1, 1, 2, cap_lhpf_mode_text);
+static SOC_ENUM_SINGLE_DECL(cap_lhpf_mode,
+ WM8962_LHPF1, 1, cap_lhpf_mode_text);
static const struct snd_kcontrol_new wm8962_snd_controls[] = {
SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1),
@@ -2014,40 +2014,40 @@ static int dsp2_event(struct snd_soc_dapm_widget *w,
static const char *st_text[] = { "None", "Left", "Right" };
-static const struct soc_enum str_enum =
- SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text);
+static SOC_ENUM_SINGLE_DECL(str_enum,
+ WM8962_DAC_DSP_MIXING_1, 2, st_text);
static const struct snd_kcontrol_new str_mux =
SOC_DAPM_ENUM("Right Sidetone", str_enum);
-static const struct soc_enum stl_enum =
- SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_2, 2, 3, st_text);
+static SOC_ENUM_SINGLE_DECL(stl_enum,
+ WM8962_DAC_DSP_MIXING_2, 2, st_text);
static const struct snd_kcontrol_new stl_mux =
SOC_DAPM_ENUM("Left Sidetone", stl_enum);
static const char *outmux_text[] = { "DAC", "Mixer" };
-static const struct soc_enum spkoutr_enum =
- SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_2, 7, 2, outmux_text);
+static SOC_ENUM_SINGLE_DECL(spkoutr_enum,
+ WM8962_SPEAKER_MIXER_2, 7, outmux_text);
static const struct snd_kcontrol_new spkoutr_mux =
SOC_DAPM_ENUM("SPKOUTR Mux", spkoutr_enum);
-static const struct soc_enum spkoutl_enum =
- SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_1, 7, 2, outmux_text);
+static SOC_ENUM_SINGLE_DECL(spkoutl_enum,
+ WM8962_SPEAKER_MIXER_1, 7, outmux_text);
static const struct snd_kcontrol_new spkoutl_mux =
SOC_DAPM_ENUM("SPKOUTL Mux", spkoutl_enum);
-static const struct soc_enum hpoutr_enum =
- SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_2, 7, 2, outmux_text);
+static SOC_ENUM_SINGLE_DECL(hpoutr_enum,
+ WM8962_HEADPHONE_MIXER_2, 7, outmux_text);
static const struct snd_kcontrol_new hpoutr_mux =
SOC_DAPM_ENUM("HPOUTR Mux", hpoutr_enum);
-static const struct soc_enum hpoutl_enum =
- SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_1, 7, 2, outmux_text);
+static SOC_ENUM_SINGLE_DECL(hpoutl_enum,
+ WM8962_HEADPHONE_MIXER_1, 7, outmux_text);
static const struct snd_kcontrol_new hpoutl_mux =
SOC_DAPM_ENUM("HPOUTL Mux", hpoutl_enum);
@@ -2884,9 +2884,13 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda);
snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n);
- try_wait_for_completion(&wm8962->fll_lock);
+ reinit_completion(&wm8962->fll_lock);
- pm_runtime_get_sync(codec->dev);
+ ret = pm_runtime_get_sync(codec->dev);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to resume device: %d\n", ret);
+ return ret;
+ }
snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK |
@@ -2894,8 +2898,6 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
- ret = 0;
-
/* This should be a massive overestimate but go even
* higher if we'll error out
*/
@@ -2909,26 +2911,38 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
if (timeout == 0 && wm8962->irq) {
dev_err(codec->dev, "FLL lock timed out");
- ret = -ETIMEDOUT;
+ snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
+ WM8962_FLL_ENA, 0);
+ pm_runtime_put(codec->dev);
+ return -ETIMEDOUT;
}
wm8962->fll_fref = Fref;
wm8962->fll_fout = Fout;
wm8962->fll_src = source;
- return ret;
+ return 0;
}
static int wm8962_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
- int val;
+ int val, ret;
if (mute)
- val = WM8962_DAC_MUTE;
+ val = WM8962_DAC_MUTE | WM8962_DAC_MUTE_ALT;
else
val = 0;
+ /**
+ * The DAC mute bit is mirrored in two registers, update both to keep
+ * the register cache consistent.
+ */
+ ret = snd_soc_update_bits(codec, WM8962_CLASS_D_CONTROL_1,
+ WM8962_DAC_MUTE_ALT, val);
+ if (ret < 0)
+ return ret;
+
return snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1,
WM8962_DAC_MUTE, val);
}
@@ -3003,9 +3017,16 @@ static irqreturn_t wm8962_irq(int irq, void *data)
unsigned int active;
int reg, ret;
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0) {
+ dev_err(dev, "Failed to resume: %d\n", ret);
+ return IRQ_NONE;
+ }
+
ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK,
&mask);
if (ret != 0) {
+ pm_runtime_put(dev);
dev_err(dev, "Failed to read interrupt mask: %d\n",
ret);
return IRQ_NONE;
@@ -3013,14 +3034,17 @@ static irqreturn_t wm8962_irq(int irq, void *data)
ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active);
if (ret != 0) {
+ pm_runtime_put(dev);
dev_err(dev, "Failed to read interrupt: %d\n", ret);
return IRQ_NONE;
}
active &= ~mask;
- if (!active)
+ if (!active) {
+ pm_runtime_put(dev);
return IRQ_NONE;
+ }
/* Acknowledge the interrupts */
ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active);
@@ -3070,6 +3094,8 @@ static irqreturn_t wm8962_irq(int irq, void *data)
msecs_to_jiffies(250));
}
+ pm_runtime_put(dev);
+
return IRQ_HANDLED;
}
@@ -3089,6 +3115,7 @@ static irqreturn_t wm8962_irq(int irq, void *data)
int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
{
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
int irq_mask, enable;
wm8962->jack = jack;
@@ -3109,19 +3136,22 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
snd_soc_jack_report(wm8962->jack, 0,
SND_JACK_MICROPHONE | SND_JACK_BTN_0);
+ snd_soc_dapm_mutex_lock(dapm);
+
if (jack) {
- snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
- snd_soc_dapm_force_enable_pin(&codec->dapm, "MICBIAS");
+ snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK");
+ snd_soc_dapm_force_enable_pin_unlocked(dapm, "MICBIAS");
} else {
- snd_soc_dapm_disable_pin(&codec->dapm, "SYSCLK");
- snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS");
+ snd_soc_dapm_disable_pin_unlocked(dapm, "SYSCLK");
+ snd_soc_dapm_disable_pin_unlocked(dapm, "MICBIAS");
}
+ snd_soc_dapm_mutex_unlock(dapm);
+
return 0;
}
EXPORT_SYMBOL_GPL(wm8962_mic_detect);
-#if IS_ENABLED(CONFIG_INPUT)
static int beep_rates[] = {
500, 1000, 2000, 4000,
};
@@ -3253,15 +3283,6 @@ static void wm8962_free_beep(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, WM8962_BEEP_GENERATOR_1, WM8962_BEEP_ENA,0);
}
-#else
-static void wm8962_init_beep(struct snd_soc_codec *codec)
-{
-}
-
-static void wm8962_free_beep(struct snd_soc_codec *codec)
-{
-}
-#endif
static void wm8962_set_gpio_mode(struct wm8962_priv *wm8962, int gpio)
{
@@ -3400,13 +3421,6 @@ static int wm8962_probe(struct snd_soc_codec *codec)
bool dmicclk, dmicdat;
wm8962->codec = codec;
- codec->control_data = wm8962->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0;
wm8962->disable_nb[1].notifier_call = wm8962_regulator_event_1;
diff --git a/sound/soc/codecs/wm8962.h b/sound/soc/codecs/wm8962.h
index a1a5d5294c1..910aafd09d2 100644
--- a/sound/soc/codecs/wm8962.h
+++ b/sound/soc/codecs/wm8962.h
@@ -1954,6 +1954,10 @@
#define WM8962_SPKOUTL_ENA_MASK 0x0040 /* SPKOUTL_ENA */
#define WM8962_SPKOUTL_ENA_SHIFT 6 /* SPKOUTL_ENA */
#define WM8962_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */
+#define WM8962_DAC_MUTE_ALT 0x0010 /* DAC_MUTE */
+#define WM8962_DAC_MUTE_ALT_MASK 0x0010 /* DAC_MUTE */
+#define WM8962_DAC_MUTE_ALT_SHIFT 4 /* DAC_MUTE */
+#define WM8962_DAC_MUTE_ALT_WIDTH 1 /* DAC_MUTE */
#define WM8962_SPKOUTL_PGA_MUTE 0x0002 /* SPKOUTL_PGA_MUTE */
#define WM8962_SPKOUTL_PGA_MUTE_MASK 0x0002 /* SPKOUTL_PGA_MUTE */
#define WM8962_SPKOUTL_PGA_MUTE_SHIFT 1 /* SPKOUTL_PGA_MUTE */
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 67aba78a7ca..09b7b420022 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -648,12 +648,6 @@ static int wm8971_probe(struct snd_soc_codec *codec)
int ret = 0;
u16 reg;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8971_work);
wm8971_workq = create_workqueue("wm8971");
if (wm8971_workq == NULL)
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 15f45c7bd83..0627c56fa44 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -84,8 +84,8 @@ static const struct soc_enum wm8974_enum[] = {
static const char *wm8974_auxmode_text[] = { "Buffer", "Mixer" };
-static const struct soc_enum wm8974_auxmode =
- SOC_ENUM_SINGLE(WM8974_INPUT, 3, 2, wm8974_auxmode_text);
+static SOC_ENUM_SINGLE_DECL(wm8974_auxmode,
+ WM8974_INPUT, 3, wm8974_auxmode_text);
static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1);
static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
@@ -593,12 +593,6 @@ static int wm8974_probe(struct snd_soc_codec *codec)
{
int ret = 0;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = wm8974_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index d8fc531c0e5..28ef46c91f6 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -117,21 +117,21 @@ static const char *wm8978_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz"};
static const char *wm8978_alc3[] = {"ALC", "Limiter"};
static const char *wm8978_alc1[] = {"Off", "Right", "Left", "Both"};
-static const SOC_ENUM_SINGLE_DECL(adc_compand, WM8978_COMPANDING_CONTROL, 1,
- wm8978_companding);
-static const SOC_ENUM_SINGLE_DECL(dac_compand, WM8978_COMPANDING_CONTROL, 3,
- wm8978_companding);
-static const SOC_ENUM_SINGLE_DECL(eqmode, WM8978_EQ1, 8, wm8978_eqmode);
-static const SOC_ENUM_SINGLE_DECL(eq1, WM8978_EQ1, 5, wm8978_eq1);
-static const SOC_ENUM_SINGLE_DECL(eq2bw, WM8978_EQ2, 8, wm8978_bw);
-static const SOC_ENUM_SINGLE_DECL(eq2, WM8978_EQ2, 5, wm8978_eq2);
-static const SOC_ENUM_SINGLE_DECL(eq3bw, WM8978_EQ3, 8, wm8978_bw);
-static const SOC_ENUM_SINGLE_DECL(eq3, WM8978_EQ3, 5, wm8978_eq3);
-static const SOC_ENUM_SINGLE_DECL(eq4bw, WM8978_EQ4, 8, wm8978_bw);
-static const SOC_ENUM_SINGLE_DECL(eq4, WM8978_EQ4, 5, wm8978_eq4);
-static const SOC_ENUM_SINGLE_DECL(eq5, WM8978_EQ5, 5, wm8978_eq5);
-static const SOC_ENUM_SINGLE_DECL(alc3, WM8978_ALC_CONTROL_3, 8, wm8978_alc3);
-static const SOC_ENUM_SINGLE_DECL(alc1, WM8978_ALC_CONTROL_1, 7, wm8978_alc1);
+static SOC_ENUM_SINGLE_DECL(adc_compand, WM8978_COMPANDING_CONTROL, 1,
+ wm8978_companding);
+static SOC_ENUM_SINGLE_DECL(dac_compand, WM8978_COMPANDING_CONTROL, 3,
+ wm8978_companding);
+static SOC_ENUM_SINGLE_DECL(eqmode, WM8978_EQ1, 8, wm8978_eqmode);
+static SOC_ENUM_SINGLE_DECL(eq1, WM8978_EQ1, 5, wm8978_eq1);
+static SOC_ENUM_SINGLE_DECL(eq2bw, WM8978_EQ2, 8, wm8978_bw);
+static SOC_ENUM_SINGLE_DECL(eq2, WM8978_EQ2, 5, wm8978_eq2);
+static SOC_ENUM_SINGLE_DECL(eq3bw, WM8978_EQ3, 8, wm8978_bw);
+static SOC_ENUM_SINGLE_DECL(eq3, WM8978_EQ3, 5, wm8978_eq3);
+static SOC_ENUM_SINGLE_DECL(eq4bw, WM8978_EQ4, 8, wm8978_bw);
+static SOC_ENUM_SINGLE_DECL(eq4, WM8978_EQ4, 5, wm8978_eq4);
+static SOC_ENUM_SINGLE_DECL(eq5, WM8978_EQ5, 5, wm8978_eq5);
+static SOC_ENUM_SINGLE_DECL(alc3, WM8978_ALC_CONTROL_3, 8, wm8978_alc3);
+static SOC_ENUM_SINGLE_DECL(alc1, WM8978_ALC_CONTROL_1, 7, wm8978_alc1);
static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1);
static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
@@ -975,19 +975,13 @@ static const int update_reg[] = {
static int wm8978_probe(struct snd_soc_codec *codec)
{
struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
- int ret = 0, i;
+ int i;
/*
* Set default system clock to PLL, it is more precise, this is also the
* default hardware setting
*/
wm8978->sysclk = WM8978_PLL;
- codec->control_data = wm8978->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
/*
* Set the update bit in all registers, that have one. This way all
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index aa41ba0dfff..19d5baa38f5 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -205,49 +205,44 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0);
static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" };
-static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7,
- alc_sel_text);
+static SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7, alc_sel_text);
static const char *alc_mode_text[] = { "ALC", "Limiter" };
-static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8,
- alc_mode_text);
+static SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8, alc_mode_text);
static const char *filter_mode_text[] = { "Audio", "Application" };
-static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7,
- filter_mode_text);
+static SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7,
+ filter_mode_text);
static const char *eq_bw_text[] = { "Narrow", "Wide" };
static const char *eqmode_text[] = { "Capture", "Playback" };
-static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text);
+static SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text);
static const char *eq1_cutoff_text[] = {
"80Hz", "105Hz", "135Hz", "175Hz"
};
-static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5,
- eq1_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5,
+ eq1_cutoff_text);
static const char *eq2_cutoff_text[] = {
"230Hz", "300Hz", "385Hz", "500Hz"
};
-static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text);
-static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5,
- eq2_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text);
+static SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5, eq2_cutoff_text);
static const char *eq3_cutoff_text[] = {
"650Hz", "850Hz", "1.1kHz", "1.4kHz"
};
-static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text);
-static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5,
- eq3_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text);
+static SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5, eq3_cutoff_text);
static const char *eq4_cutoff_text[] = {
"1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz"
};
-static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text);
-static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5,
- eq4_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text);
+static SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5, eq4_cutoff_text);
static const char *eq5_cutoff_text[] = {
"5.3kHz", "6.9kHz", "9kHz", "11.7kHz"
};
-static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5,
- eq5_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5,
+ eq5_cutoff_text);
static const char *depth_3d_text[] = {
"Off",
@@ -267,8 +262,8 @@ static const char *depth_3d_text[] = {
"93.3%",
"100%"
};
-static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0,
- depth_3d_text);
+static SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0,
+ depth_3d_text);
static const struct snd_kcontrol_new wm8983_snd_controls[] = {
SOC_SINGLE("Digital Loopback Switch", WM8983_COMPANDING_CONTROL,
@@ -557,7 +552,7 @@ static const struct snd_soc_dapm_route wm8983_audio_map[] = {
static int eqmode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int reg;
reg = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF);
@@ -572,7 +567,7 @@ static int eqmode_get(struct snd_kcontrol *kcontrol,
static int eqmode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int regpwr2, regpwr3;
unsigned int reg_eq;
@@ -1000,12 +995,6 @@ static int wm8983_probe(struct snd_soc_codec *codec)
int ret;
int i;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
- return ret;
- }
-
ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
@@ -1129,7 +1118,7 @@ static struct spi_driver wm8983_spi_driver = {
};
#endif
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
static int wm8983_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -1182,7 +1171,7 @@ static int __init wm8983_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
ret = i2c_add_driver(&wm8983_i2c_driver);
if (ret) {
printk(KERN_ERR "Failed to register wm8983 I2C driver: %d\n",
@@ -1202,7 +1191,7 @@ module_init(wm8983_modinit);
static void __exit wm8983_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
i2c_del_driver(&wm8983_i2c_driver);
#endif
#if defined(CONFIG_SPI_MASTER)
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index 271b517911a..0f5780c09f3 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -226,52 +226,48 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0);
static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" };
-static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7,
- alc_sel_text);
+static SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7, alc_sel_text);
static const char *alc_mode_text[] = { "ALC", "Limiter" };
-static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8,
- alc_mode_text);
+static SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8, alc_mode_text);
static const char *filter_mode_text[] = { "Audio", "Application" };
-static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7,
- filter_mode_text);
+static SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7,
+ filter_mode_text);
static const char *eq_bw_text[] = { "Narrow", "Wide" };
static const char *eqmode_text[] = { "Capture", "Playback" };
-static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text);
+static SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text);
static const char *eq1_cutoff_text[] = {
"80Hz", "105Hz", "135Hz", "175Hz"
};
-static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5,
- eq1_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5,
+ eq1_cutoff_text);
static const char *eq2_cutoff_text[] = {
"230Hz", "300Hz", "385Hz", "500Hz"
};
-static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text);
-static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5,
- eq2_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text);
+static SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5, eq2_cutoff_text);
static const char *eq3_cutoff_text[] = {
"650Hz", "850Hz", "1.1kHz", "1.4kHz"
};
-static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text);
-static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5,
- eq3_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text);
+static SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5,
+ eq3_cutoff_text);
static const char *eq4_cutoff_text[] = {
"1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz"
};
-static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text);
-static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5,
- eq4_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text);
+static SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5, eq4_cutoff_text);
static const char *eq5_cutoff_text[] = {
"5.3kHz", "6.9kHz", "9kHz", "11.7kHz"
};
-static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5,
+static SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5,
eq5_cutoff_text);
static const char *speaker_mode_text[] = { "Class A/B", "Class D" };
-static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text);
+static SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text);
static const char *depth_3d_text[] = {
"Off",
@@ -291,8 +287,7 @@ static const char *depth_3d_text[] = {
"93.3%",
"100%"
};
-static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0,
- depth_3d_text);
+static SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0, depth_3d_text);
static const struct snd_kcontrol_new wm8985_snd_controls[] = {
SOC_SINGLE("Digital Loopback Switch", WM8985_COMPANDING_CONTROL,
@@ -531,7 +526,7 @@ static const struct snd_soc_dapm_route wm8985_dapm_routes[] = {
static int eqmode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int reg;
reg = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF);
@@ -546,7 +541,7 @@ static int eqmode_get(struct snd_kcontrol *kcontrol,
static int eqmode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int regpwr2, regpwr3;
unsigned int reg_eq;
@@ -989,7 +984,6 @@ static int wm8985_remove(struct snd_soc_codec *codec)
wm8985 = snd_soc_codec_get_drvdata(codec);
wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF);
- regulator_bulk_free(ARRAY_SIZE(wm8985->supplies), wm8985->supplies);
return 0;
}
@@ -1000,18 +994,11 @@ static int wm8985_probe(struct snd_soc_codec *codec)
int ret;
wm8985 = snd_soc_codec_get_drvdata(codec);
- codec->control_data = wm8985->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
- return ret;
- }
for (i = 0; i < ARRAY_SIZE(wm8985->supplies); i++)
wm8985->supplies[i].supply = wm8985_supply_names[i];
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8985->supplies),
+ ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8985->supplies),
wm8985->supplies);
if (ret) {
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
@@ -1022,7 +1009,7 @@ static int wm8985_probe(struct snd_soc_codec *codec)
wm8985->supplies);
if (ret) {
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
- goto err_reg_get;
+ return ret;
}
ret = wm8985_reset(codec);
@@ -1044,8 +1031,6 @@ static int wm8985_probe(struct snd_soc_codec *codec)
err_reg_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8985->supplies), wm8985->supplies);
-err_reg_get:
- regulator_bulk_free(ARRAY_SIZE(wm8985->supplies), wm8985->supplies);
return ret;
}
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index a55e1c2c382..d3fea46d58e 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -116,7 +116,7 @@ static bool wm8988_writeable(struct device *dev, unsigned int reg)
struct wm8988_priv {
struct regmap *regmap;
unsigned int sysclk;
- struct snd_pcm_hw_constraint_list *sysclk_constraints;
+ const struct snd_pcm_hw_constraint_list *sysclk_constraints;
};
#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0)
@@ -126,46 +126,46 @@ struct wm8988_priv {
*/
static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"};
-static const struct soc_enum bass_boost =
- SOC_ENUM_SINGLE(WM8988_BASS, 7, 2, bass_boost_txt);
+static SOC_ENUM_SINGLE_DECL(bass_boost,
+ WM8988_BASS, 7, bass_boost_txt);
static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };
-static const struct soc_enum bass_filter =
- SOC_ENUM_SINGLE(WM8988_BASS, 6, 2, bass_filter_txt);
+static SOC_ENUM_SINGLE_DECL(bass_filter,
+ WM8988_BASS, 6, bass_filter_txt);
static const char *treble_txt[] = {"8kHz", "4kHz"};
-static const struct soc_enum treble =
- SOC_ENUM_SINGLE(WM8988_TREBLE, 6, 2, treble_txt);
+static SOC_ENUM_SINGLE_DECL(treble,
+ WM8988_TREBLE, 6, treble_txt);
static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"};
-static const struct soc_enum stereo_3d_lc =
- SOC_ENUM_SINGLE(WM8988_3D, 5, 2, stereo_3d_lc_txt);
+static SOC_ENUM_SINGLE_DECL(stereo_3d_lc,
+ WM8988_3D, 5, stereo_3d_lc_txt);
static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"};
-static const struct soc_enum stereo_3d_uc =
- SOC_ENUM_SINGLE(WM8988_3D, 6, 2, stereo_3d_uc_txt);
+static SOC_ENUM_SINGLE_DECL(stereo_3d_uc,
+ WM8988_3D, 6, stereo_3d_uc_txt);
static const char *stereo_3d_func_txt[] = {"Capture", "Playback"};
-static const struct soc_enum stereo_3d_func =
- SOC_ENUM_SINGLE(WM8988_3D, 7, 2, stereo_3d_func_txt);
+static SOC_ENUM_SINGLE_DECL(stereo_3d_func,
+ WM8988_3D, 7, stereo_3d_func_txt);
static const char *alc_func_txt[] = {"Off", "Right", "Left", "Stereo"};
-static const struct soc_enum alc_func =
- SOC_ENUM_SINGLE(WM8988_ALC1, 7, 4, alc_func_txt);
+static SOC_ENUM_SINGLE_DECL(alc_func,
+ WM8988_ALC1, 7, alc_func_txt);
static const char *ng_type_txt[] = {"Constant PGA Gain",
"Mute ADC Output"};
-static const struct soc_enum ng_type =
- SOC_ENUM_SINGLE(WM8988_NGATE, 1, 2, ng_type_txt);
+static SOC_ENUM_SINGLE_DECL(ng_type,
+ WM8988_NGATE, 1, ng_type_txt);
static const char *deemph_txt[] = {"None", "32Khz", "44.1Khz", "48Khz"};
-static const struct soc_enum deemph =
- SOC_ENUM_SINGLE(WM8988_ADCDAC, 1, 4, deemph_txt);
+static SOC_ENUM_SINGLE_DECL(deemph,
+ WM8988_ADCDAC, 1, deemph_txt);
static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert",
"L + R Invert"};
-static const struct soc_enum adcpol =
- SOC_ENUM_SINGLE(WM8988_ADCDAC, 5, 4, adcpol_txt);
+static SOC_ENUM_SINGLE_DECL(adcpol,
+ WM8988_ADCDAC, 5, adcpol_txt);
static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0);
static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);
@@ -268,7 +268,7 @@ static const struct soc_enum wm8988_lline_enum =
wm8988_line_texts,
wm8988_line_values);
static const struct snd_kcontrol_new wm8988_left_line_controls =
- SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum);
+ SOC_DAPM_ENUM("Route", wm8988_lline_enum);
static const struct soc_enum wm8988_rline_enum =
SOC_VALUE_ENUM_SINGLE(WM8988_ROUTM1, 0, 7,
@@ -276,7 +276,7 @@ static const struct soc_enum wm8988_rline_enum =
wm8988_line_texts,
wm8988_line_values);
static const struct snd_kcontrol_new wm8988_right_line_controls =
- SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum);
+ SOC_DAPM_ENUM("Route", wm8988_lline_enum);
/* Left Mixer */
static const struct snd_kcontrol_new wm8988_left_mixer_controls[] = {
@@ -304,7 +304,7 @@ static const struct soc_enum wm8988_lpga_enum =
wm8988_pga_sel,
wm8988_pga_val);
static const struct snd_kcontrol_new wm8988_left_pga_controls =
- SOC_DAPM_VALUE_ENUM("Route", wm8988_lpga_enum);
+ SOC_DAPM_ENUM("Route", wm8988_lpga_enum);
/* Right PGA Mux */
static const struct soc_enum wm8988_rpga_enum =
@@ -313,20 +313,20 @@ static const struct soc_enum wm8988_rpga_enum =
wm8988_pga_sel,
wm8988_pga_val);
static const struct snd_kcontrol_new wm8988_right_pga_controls =
- SOC_DAPM_VALUE_ENUM("Route", wm8988_rpga_enum);
+ SOC_DAPM_ENUM("Route", wm8988_rpga_enum);
/* Differential Mux */
static const char *wm8988_diff_sel[] = {"Line 1", "Line 2"};
-static const struct soc_enum diffmux =
- SOC_ENUM_SINGLE(WM8988_ADCIN, 8, 2, wm8988_diff_sel);
+static SOC_ENUM_SINGLE_DECL(diffmux,
+ WM8988_ADCIN, 8, wm8988_diff_sel);
static const struct snd_kcontrol_new wm8988_diffmux_controls =
SOC_DAPM_ENUM("Route", diffmux);
/* Mono ADC Mux */
static const char *wm8988_mono_mux[] = {"Stereo", "Mono (Left)",
"Mono (Right)", "Digital Mono"};
-static const struct soc_enum monomux =
- SOC_ENUM_SINGLE(WM8988_ADCIN, 6, 4, wm8988_mono_mux);
+static SOC_ENUM_SINGLE_DECL(monomux,
+ WM8988_ADCIN, 6, wm8988_mono_mux);
static const struct snd_kcontrol_new wm8988_monomux_controls =
SOC_DAPM_ENUM("Route", monomux);
@@ -521,30 +521,30 @@ static inline int get_coeff(int mclk, int rate)
/* The set of rates we can generate from the above for each SYSCLK */
-static unsigned int rates_12288[] = {
+static const unsigned int rates_12288[] = {
8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
};
-static struct snd_pcm_hw_constraint_list constraints_12288 = {
+static const struct snd_pcm_hw_constraint_list constraints_12288 = {
.count = ARRAY_SIZE(rates_12288),
.list = rates_12288,
};
-static unsigned int rates_112896[] = {
+static const unsigned int rates_112896[] = {
8000, 11025, 22050, 44100,
};
-static struct snd_pcm_hw_constraint_list constraints_112896 = {
+static const struct snd_pcm_hw_constraint_list constraints_112896 = {
.count = ARRAY_SIZE(rates_112896),
.list = rates_112896,
};
-static unsigned int rates_12[] = {
+static const unsigned int rates_12[] = {
8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000,
48000, 88235, 96000,
};
-static struct snd_pcm_hw_constraint_list constraints_12 = {
+static const struct snd_pcm_hw_constraint_list constraints_12 = {
.count = ARRAY_SIZE(rates_12),
.list = rates_12,
};
@@ -810,16 +810,8 @@ static int wm8988_resume(struct snd_soc_codec *codec)
static int wm8988_probe(struct snd_soc_codec *codec)
{
- struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
- codec->control_data = wm8988->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = wm8988_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 0ccd4d8d043..b5c1f0f0705 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -132,7 +132,7 @@ static const DECLARE_TLV_DB_SCALE(out_sidetone_tlv, -3600, 0, 0);
static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int reg = mc->reg;
@@ -157,26 +157,23 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
static const char *wm8990_digital_sidetone[] =
{"None", "Left ADC", "Right ADC", "Reserved"};
-static const struct soc_enum wm8990_left_digital_sidetone_enum =
-SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE,
- WM8990_ADC_TO_DACL_SHIFT,
- WM8990_ADC_TO_DACL_MASK,
- wm8990_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8990_left_digital_sidetone_enum,
+ WM8990_DIGITAL_SIDE_TONE,
+ WM8990_ADC_TO_DACL_SHIFT,
+ wm8990_digital_sidetone);
-static const struct soc_enum wm8990_right_digital_sidetone_enum =
-SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE,
- WM8990_ADC_TO_DACR_SHIFT,
- WM8990_ADC_TO_DACR_MASK,
- wm8990_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8990_right_digital_sidetone_enum,
+ WM8990_DIGITAL_SIDE_TONE,
+ WM8990_ADC_TO_DACR_SHIFT,
+ wm8990_digital_sidetone);
static const char *wm8990_adcmode[] =
{"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
-static const struct soc_enum wm8990_right_adcmode_enum =
-SOC_ENUM_SINGLE(WM8990_ADC_CTRL,
- WM8990_ADC_HPF_CUT_SHIFT,
- WM8990_ADC_HPF_CUT_MASK,
- wm8990_adcmode);
+static SOC_ENUM_SINGLE_DECL(wm8990_right_adcmode_enum,
+ WM8990_ADC_CTRL,
+ WM8990_ADC_HPF_CUT_SHIFT,
+ wm8990_adcmode);
static const struct snd_kcontrol_new wm8990_snd_controls[] = {
/* INMIXL */
@@ -475,9 +472,9 @@ SOC_DAPM_SINGLE("RINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT,
static const char *wm8990_ainlmux[] =
{"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
-static const struct soc_enum wm8990_ainlmux_enum =
-SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT,
- ARRAY_SIZE(wm8990_ainlmux), wm8990_ainlmux);
+static SOC_ENUM_SINGLE_DECL(wm8990_ainlmux_enum,
+ WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT,
+ wm8990_ainlmux);
static const struct snd_kcontrol_new wm8990_dapm_ainlmux_controls =
SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum);
@@ -488,9 +485,9 @@ SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum);
static const char *wm8990_ainrmux[] =
{"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
-static const struct soc_enum wm8990_ainrmux_enum =
-SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT,
- ARRAY_SIZE(wm8990_ainrmux), wm8990_ainrmux);
+static SOC_ENUM_SINGLE_DECL(wm8990_ainrmux_enum,
+ WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT,
+ wm8990_ainrmux);
static const struct snd_kcontrol_new wm8990_dapm_ainrmux_controls =
SOC_DAPM_ENUM("Route", wm8990_ainrmux_enum);
@@ -1292,14 +1289,6 @@ static int wm8990_resume(struct snd_soc_codec *codec)
*/
static int wm8990_probe(struct snd_soc_codec *codec)
{
- int ret;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret < 0) {
- printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
wm8990_reset(codec);
/* charge output caps */
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index dba0306c42a..b8fd284fc0c 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -154,7 +154,7 @@ static const unsigned int out_sidetone_tlv[] = {
static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
int reg = kcontrol->private_value & 0xff;
int ret;
u16 val;
@@ -171,26 +171,23 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
static const char *wm8991_digital_sidetone[] =
{"None", "Left ADC", "Right ADC", "Reserved"};
-static const struct soc_enum wm8991_left_digital_sidetone_enum =
- SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE,
- WM8991_ADC_TO_DACL_SHIFT,
- WM8991_ADC_TO_DACL_MASK,
- wm8991_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8991_left_digital_sidetone_enum,
+ WM8991_DIGITAL_SIDE_TONE,
+ WM8991_ADC_TO_DACL_SHIFT,
+ wm8991_digital_sidetone);
-static const struct soc_enum wm8991_right_digital_sidetone_enum =
- SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE,
- WM8991_ADC_TO_DACR_SHIFT,
- WM8991_ADC_TO_DACR_MASK,
- wm8991_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8991_right_digital_sidetone_enum,
+ WM8991_DIGITAL_SIDE_TONE,
+ WM8991_ADC_TO_DACR_SHIFT,
+ wm8991_digital_sidetone);
static const char *wm8991_adcmode[] =
{"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
-static const struct soc_enum wm8991_right_adcmode_enum =
- SOC_ENUM_SINGLE(WM8991_ADC_CTRL,
- WM8991_ADC_HPF_CUT_SHIFT,
- WM8991_ADC_HPF_CUT_MASK,
- wm8991_adcmode);
+static SOC_ENUM_SINGLE_DECL(wm8991_right_adcmode_enum,
+ WM8991_ADC_CTRL,
+ WM8991_ADC_HPF_CUT_SHIFT,
+ wm8991_adcmode);
static const struct snd_kcontrol_new wm8991_snd_controls[] = {
/* INMIXL */
@@ -486,9 +483,9 @@ static const struct snd_kcontrol_new wm8991_dapm_inmixr_controls[] = {
static const char *wm8991_ainlmux[] =
{"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
-static const struct soc_enum wm8991_ainlmux_enum =
- SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT,
- ARRAY_SIZE(wm8991_ainlmux), wm8991_ainlmux);
+static SOC_ENUM_SINGLE_DECL(wm8991_ainlmux_enum,
+ WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT,
+ wm8991_ainlmux);
static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls =
SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum);
@@ -499,9 +496,9 @@ static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls =
static const char *wm8991_ainrmux[] =
{"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
-static const struct soc_enum wm8991_ainrmux_enum =
- SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT,
- ARRAY_SIZE(wm8991_ainrmux), wm8991_ainrmux);
+static SOC_ENUM_SINGLE_DECL(wm8991_ainrmux_enum,
+ WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT,
+ wm8991_ainrmux);
static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls =
SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum);
@@ -1251,17 +1248,6 @@ static int wm8991_remove(struct snd_soc_codec *codec)
static int wm8991_probe(struct snd_soc_codec *codec)
{
- struct wm8991_priv *wm8991;
- int ret;
-
- wm8991 = snd_soc_codec_get_drvdata(codec);
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
- return ret;
- }
-
wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 433d59a0f3e..f825dc04ebe 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -646,8 +646,8 @@ static const char *dac_deemph_text[] = {
"48kHz",
};
-static const struct soc_enum dac_deemph =
- SOC_ENUM_SINGLE(WM8993_DAC_CTRL, 4, 4, dac_deemph_text);
+static SOC_ENUM_SINGLE_DECL(dac_deemph,
+ WM8993_DAC_CTRL, 4, dac_deemph_text);
static const char *adc_hpf_text[] = {
"Hi-Fi",
@@ -656,16 +656,16 @@ static const char *adc_hpf_text[] = {
"Voice 3",
};
-static const struct soc_enum adc_hpf =
- SOC_ENUM_SINGLE(WM8993_ADC_CTRL, 5, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(adc_hpf,
+ WM8993_ADC_CTRL, 5, adc_hpf_text);
static const char *drc_path_text[] = {
"ADC",
"DAC"
};
-static const struct soc_enum drc_path =
- SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text);
+static SOC_ENUM_SINGLE_DECL(drc_path,
+ WM8993_DRC_CONTROL_1, 14, drc_path_text);
static const char *drc_r0_text[] = {
"1",
@@ -676,8 +676,8 @@ static const char *drc_r0_text[] = {
"0",
};
-static const struct soc_enum drc_r0 =
- SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 8, 6, drc_r0_text);
+static SOC_ENUM_SINGLE_DECL(drc_r0,
+ WM8993_DRC_CONTROL_3, 8, drc_r0_text);
static const char *drc_r1_text[] = {
"1",
@@ -687,8 +687,8 @@ static const char *drc_r1_text[] = {
"0",
};
-static const struct soc_enum drc_r1 =
- SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_4, 13, 5, drc_r1_text);
+static SOC_ENUM_SINGLE_DECL(drc_r1,
+ WM8993_DRC_CONTROL_4, 13, drc_r1_text);
static const char *drc_attack_text[] = {
"Reserved",
@@ -705,8 +705,8 @@ static const char *drc_attack_text[] = {
"185.6ms",
};
-static const struct soc_enum drc_attack =
- SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 12, 12, drc_attack_text);
+static SOC_ENUM_SINGLE_DECL(drc_attack,
+ WM8993_DRC_CONTROL_2, 12, drc_attack_text);
static const char *drc_decay_text[] = {
"186ms",
@@ -720,16 +720,16 @@ static const char *drc_decay_text[] = {
"47.56ms",
};
-static const struct soc_enum drc_decay =
- SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 8, 9, drc_decay_text);
+static SOC_ENUM_SINGLE_DECL(drc_decay,
+ WM8993_DRC_CONTROL_2, 8, drc_decay_text);
static const char *drc_ff_text[] = {
"5 samples",
"9 samples",
};
-static const struct soc_enum drc_ff =
- SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 7, 2, drc_ff_text);
+static SOC_ENUM_SINGLE_DECL(drc_ff,
+ WM8993_DRC_CONTROL_3, 7, drc_ff_text);
static const char *drc_qr_rate_text[] = {
"0.725ms",
@@ -737,8 +737,8 @@ static const char *drc_qr_rate_text[] = {
"5.8ms",
};
-static const struct soc_enum drc_qr_rate =
- SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 0, 3, drc_qr_rate_text);
+static SOC_ENUM_SINGLE_DECL(drc_qr_rate,
+ WM8993_DRC_CONTROL_3, 0, drc_qr_rate_text);
static const char *drc_smooth_text[] = {
"Low",
@@ -746,8 +746,8 @@ static const char *drc_smooth_text[] = {
"High",
};
-static const struct soc_enum drc_smooth =
- SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 4, 3, drc_smooth_text);
+static SOC_ENUM_SINGLE_DECL(drc_smooth,
+ WM8993_DRC_CONTROL_1, 4, drc_smooth_text);
static const struct snd_kcontrol_new wm8993_snd_controls[] = {
SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE,
@@ -841,26 +841,26 @@ static const char *aif_text[] = {
"Left", "Right"
};
-static const struct soc_enum aifoutl_enum =
- SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 15, 2, aif_text);
+static SOC_ENUM_SINGLE_DECL(aifoutl_enum,
+ WM8993_AUDIO_INTERFACE_1, 15, aif_text);
static const struct snd_kcontrol_new aifoutl_mux =
SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum);
-static const struct soc_enum aifoutr_enum =
- SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 14, 2, aif_text);
+static SOC_ENUM_SINGLE_DECL(aifoutr_enum,
+ WM8993_AUDIO_INTERFACE_1, 14, aif_text);
static const struct snd_kcontrol_new aifoutr_mux =
SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum);
-static const struct soc_enum aifinl_enum =
- SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 15, 2, aif_text);
+static SOC_ENUM_SINGLE_DECL(aifinl_enum,
+ WM8993_AUDIO_INTERFACE_2, 15, aif_text);
static const struct snd_kcontrol_new aifinl_mux =
SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum);
-static const struct soc_enum aifinr_enum =
- SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 14, 2, aif_text);
+static SOC_ENUM_SINGLE_DECL(aifinr_enum,
+ WM8993_AUDIO_INTERFACE_2, 14, aif_text);
static const struct snd_kcontrol_new aifinr_mux =
SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum);
@@ -869,14 +869,14 @@ static const char *sidetone_text[] = {
"None", "Left", "Right"
};
-static const struct soc_enum sidetonel_enum =
- SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 2, 3, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(sidetonel_enum,
+ WM8993_DIGITAL_SIDE_TONE, 2, sidetone_text);
static const struct snd_kcontrol_new sidetonel_mux =
SOC_DAPM_ENUM("Left Sidetone", sidetonel_enum);
-static const struct soc_enum sidetoner_enum =
- SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 0, 3, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(sidetoner_enum,
+ WM8993_DIGITAL_SIDE_TONE, 0, sidetone_text);
static const struct snd_kcontrol_new sidetoner_mux =
SOC_DAPM_ENUM("Right Sidetone", sidetoner_enum);
@@ -1493,13 +1493,6 @@ static int wm8993_probe(struct snd_soc_codec *codec)
wm8993->hubs_data.dcs_codes_r = -2;
wm8993->hubs_data.series_startup = 1;
- codec->control_data = wm8993->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
/* Latch volume update bits and default ZC on */
snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
WM8993_DAC_VU, WM8993_DAC_VU);
@@ -1559,10 +1552,7 @@ static int wm8993_probe(struct snd_soc_codec *codec)
static int wm8993_remove(struct snd_soc_codec *codec)
{
- struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
-
wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
- regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
return 0;
}
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index b9be9cbc460..247b39013fb 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -265,21 +265,21 @@ static const char *sidetone_hpf_text[] = {
"2.7kHz", "1.35kHz", "675Hz", "370Hz", "180Hz", "90Hz", "45Hz"
};
-static const struct soc_enum sidetone_hpf =
- SOC_ENUM_SINGLE(WM8994_SIDETONE, 7, 7, sidetone_hpf_text);
+static SOC_ENUM_SINGLE_DECL(sidetone_hpf,
+ WM8994_SIDETONE, 7, sidetone_hpf_text);
static const char *adc_hpf_text[] = {
"HiFi", "Voice 1", "Voice 2", "Voice 3"
};
-static const struct soc_enum aif1adc1_hpf =
- SOC_ENUM_SINGLE(WM8994_AIF1_ADC1_FILTERS, 13, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(aif1adc1_hpf,
+ WM8994_AIF1_ADC1_FILTERS, 13, adc_hpf_text);
-static const struct soc_enum aif1adc2_hpf =
- SOC_ENUM_SINGLE(WM8994_AIF1_ADC2_FILTERS, 13, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(aif1adc2_hpf,
+ WM8994_AIF1_ADC2_FILTERS, 13, adc_hpf_text);
-static const struct soc_enum aif2adc_hpf =
- SOC_ENUM_SINGLE(WM8994_AIF2_ADC_FILTERS, 13, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(aif2adc_hpf,
+ WM8994_AIF2_ADC_FILTERS, 13, adc_hpf_text);
static const DECLARE_TLV_DB_SCALE(aif_tlv, 0, 600, 0);
static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
@@ -298,7 +298,7 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
int mask, ret;
/* Can't enable both ADC and DAC paths simultaneously */
@@ -355,7 +355,7 @@ static int wm8994_get_drc(const char *name)
static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
struct wm8994_pdata *pdata = &control->pdata;
@@ -378,7 +378,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
static int wm8994_get_drc_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int drc = wm8994_get_drc(kcontrol->id.name);
@@ -462,7 +462,7 @@ static int wm8994_get_retune_mobile_block(const char *name)
static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
struct wm8994_pdata *pdata = &control->pdata;
@@ -485,7 +485,7 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
@@ -501,39 +501,39 @@ static const char *aif_chan_src_text[] = {
"Left", "Right"
};
-static const struct soc_enum aif1adcl_src =
- SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1adcl_src,
+ WM8994_AIF1_CONTROL_1, 15, aif_chan_src_text);
-static const struct soc_enum aif1adcr_src =
- SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1adcr_src,
+ WM8994_AIF1_CONTROL_1, 14, aif_chan_src_text);
-static const struct soc_enum aif2adcl_src =
- SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2adcl_src,
+ WM8994_AIF2_CONTROL_1, 15, aif_chan_src_text);
-static const struct soc_enum aif2adcr_src =
- SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2adcr_src,
+ WM8994_AIF2_CONTROL_1, 14, aif_chan_src_text);
-static const struct soc_enum aif1dacl_src =
- SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1dacl_src,
+ WM8994_AIF1_CONTROL_2, 15, aif_chan_src_text);
-static const struct soc_enum aif1dacr_src =
- SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1dacr_src,
+ WM8994_AIF1_CONTROL_2, 14, aif_chan_src_text);
-static const struct soc_enum aif2dacl_src =
- SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacl_src,
+ WM8994_AIF2_CONTROL_2, 15, aif_chan_src_text);
-static const struct soc_enum aif2dacr_src =
- SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacr_src,
+ WM8994_AIF2_CONTROL_2, 14, aif_chan_src_text);
static const char *osr_text[] = {
"Low Power", "High Performance",
};
-static const struct soc_enum dac_osr =
- SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 0, 2, osr_text);
+static SOC_ENUM_SINGLE_DECL(dac_osr,
+ WM8994_OVERSAMPLING, 0, osr_text);
-static const struct soc_enum adc_osr =
- SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 1, 2, osr_text);
+static SOC_ENUM_SINGLE_DECL(adc_osr,
+ WM8994_OVERSAMPLING, 1, osr_text);
static const struct snd_kcontrol_new wm8994_snd_controls[] = {
SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME,
@@ -690,17 +690,20 @@ static const char *wm8958_ng_text[] = {
"30ms", "125ms", "250ms", "500ms",
};
-static const struct soc_enum wm8958_aif1dac1_ng_hold =
- SOC_ENUM_SINGLE(WM8958_AIF1_DAC1_NOISE_GATE,
- WM8958_AIF1DAC1_NG_THR_SHIFT, 4, wm8958_ng_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac1_ng_hold,
+ WM8958_AIF1_DAC1_NOISE_GATE,
+ WM8958_AIF1DAC1_NG_THR_SHIFT,
+ wm8958_ng_text);
-static const struct soc_enum wm8958_aif1dac2_ng_hold =
- SOC_ENUM_SINGLE(WM8958_AIF1_DAC2_NOISE_GATE,
- WM8958_AIF1DAC2_NG_THR_SHIFT, 4, wm8958_ng_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac2_ng_hold,
+ WM8958_AIF1_DAC2_NOISE_GATE,
+ WM8958_AIF1DAC2_NG_THR_SHIFT,
+ wm8958_ng_text);
-static const struct soc_enum wm8958_aif2dac_ng_hold =
- SOC_ENUM_SINGLE(WM8958_AIF2_DAC_NOISE_GATE,
- WM8958_AIF2DAC_NG_THR_SHIFT, 4, wm8958_ng_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif2dac_ng_hold,
+ WM8958_AIF2_DAC_NOISE_GATE,
+ WM8958_AIF2DAC_NG_THR_SHIFT,
+ wm8958_ng_text);
static const struct snd_kcontrol_new wm8958_snd_controls[] = {
SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv),
@@ -1341,14 +1344,13 @@ static const char *adc_mux_text[] = {
"DMIC",
};
-static const struct soc_enum adc_enum =
- SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text);
+static SOC_ENUM_SINGLE_VIRT_DECL(adc_enum, adc_mux_text);
static const struct snd_kcontrol_new adcl_mux =
- SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum);
+ SOC_DAPM_ENUM("ADCL Mux", adc_enum);
static const struct snd_kcontrol_new adcr_mux =
- SOC_DAPM_ENUM_VIRT("ADCR Mux", adc_enum);
+ SOC_DAPM_ENUM("ADCR Mux", adc_enum);
static const struct snd_kcontrol_new left_speaker_mixer[] = {
SOC_DAPM_SINGLE("DAC2 Switch", WM8994_SPEAKER_MIXER, 9, 1, 0),
@@ -1478,14 +1480,14 @@ static const char *sidetone_text[] = {
"ADC/DMIC1", "DMIC2",
};
-static const struct soc_enum sidetone1_enum =
- SOC_ENUM_SINGLE(WM8994_SIDETONE, 0, 2, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(sidetone1_enum,
+ WM8994_SIDETONE, 0, sidetone_text);
static const struct snd_kcontrol_new sidetone1_mux =
SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum);
-static const struct soc_enum sidetone2_enum =
- SOC_ENUM_SINGLE(WM8994_SIDETONE, 1, 2, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(sidetone2_enum,
+ WM8994_SIDETONE, 1, sidetone_text);
static const struct snd_kcontrol_new sidetone2_mux =
SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum);
@@ -1498,22 +1500,24 @@ static const char *loopback_text[] = {
"None", "ADCDAT",
};
-static const struct soc_enum aif1_loopback_enum =
- SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, WM8994_AIF1_LOOPBACK_SHIFT, 2,
- loopback_text);
+static SOC_ENUM_SINGLE_DECL(aif1_loopback_enum,
+ WM8994_AIF1_CONTROL_2,
+ WM8994_AIF1_LOOPBACK_SHIFT,
+ loopback_text);
static const struct snd_kcontrol_new aif1_loopback =
SOC_DAPM_ENUM("AIF1 Loopback", aif1_loopback_enum);
-static const struct soc_enum aif2_loopback_enum =
- SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, WM8994_AIF2_LOOPBACK_SHIFT, 2,
- loopback_text);
+static SOC_ENUM_SINGLE_DECL(aif2_loopback_enum,
+ WM8994_AIF2_CONTROL_2,
+ WM8994_AIF2_LOOPBACK_SHIFT,
+ loopback_text);
static const struct snd_kcontrol_new aif2_loopback =
SOC_DAPM_ENUM("AIF2 Loopback", aif2_loopback_enum);
-static const struct soc_enum aif1dac_enum =
- SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text);
+static SOC_ENUM_SINGLE_DECL(aif1dac_enum,
+ WM8994_POWER_MANAGEMENT_6, 0, aif1dac_text);
static const struct snd_kcontrol_new aif1dac_mux =
SOC_DAPM_ENUM("AIF1DAC Mux", aif1dac_enum);
@@ -1522,8 +1526,8 @@ static const char *aif2dac_text[] = {
"AIF2DACDAT", "AIF3DACDAT",
};
-static const struct soc_enum aif2dac_enum =
- SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 1, 2, aif2dac_text);
+static SOC_ENUM_SINGLE_DECL(aif2dac_enum,
+ WM8994_POWER_MANAGEMENT_6, 1, aif2dac_text);
static const struct snd_kcontrol_new aif2dac_mux =
SOC_DAPM_ENUM("AIF2DAC Mux", aif2dac_enum);
@@ -1532,8 +1536,8 @@ static const char *aif2adc_text[] = {
"AIF2ADCDAT", "AIF3DACDAT",
};
-static const struct soc_enum aif2adc_enum =
- SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 2, 2, aif2adc_text);
+static SOC_ENUM_SINGLE_DECL(aif2adc_enum,
+ WM8994_POWER_MANAGEMENT_6, 2, aif2adc_text);
static const struct snd_kcontrol_new aif2adc_mux =
SOC_DAPM_ENUM("AIF2ADC Mux", aif2adc_enum);
@@ -1542,14 +1546,14 @@ static const char *aif3adc_text[] = {
"AIF1ADCDAT", "AIF2ADCDAT", "AIF2DACDAT", "Mono PCM",
};
-static const struct soc_enum wm8994_aif3adc_enum =
- SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 3, aif3adc_text);
+static SOC_ENUM_SINGLE_DECL(wm8994_aif3adc_enum,
+ WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text);
static const struct snd_kcontrol_new wm8994_aif3adc_mux =
SOC_DAPM_ENUM("AIF3ADC Mux", wm8994_aif3adc_enum);
-static const struct soc_enum wm8958_aif3adc_enum =
- SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 4, aif3adc_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif3adc_enum,
+ WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text);
static const struct snd_kcontrol_new wm8958_aif3adc_mux =
SOC_DAPM_ENUM("AIF3ADC Mux", wm8958_aif3adc_enum);
@@ -1558,8 +1562,8 @@ static const char *mono_pcm_out_text[] = {
"None", "AIF2ADCL", "AIF2ADCR",
};
-static const struct soc_enum mono_pcm_out_enum =
- SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 9, 3, mono_pcm_out_text);
+static SOC_ENUM_SINGLE_DECL(mono_pcm_out_enum,
+ WM8994_POWER_MANAGEMENT_6, 9, mono_pcm_out_text);
static const struct snd_kcontrol_new mono_pcm_out_mux =
SOC_DAPM_ENUM("Mono PCM Out Mux", mono_pcm_out_enum);
@@ -1569,14 +1573,14 @@ static const char *aif2dac_src_text[] = {
};
/* Note that these two control shouldn't be simultaneously switched to AIF3 */
-static const struct soc_enum aif2dacl_src_enum =
- SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 7, 2, aif2dac_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacl_src_enum,
+ WM8994_POWER_MANAGEMENT_6, 7, aif2dac_src_text);
static const struct snd_kcontrol_new aif2dacl_src_mux =
SOC_DAPM_ENUM("AIF2DACL Mux", aif2dacl_src_enum);
-static const struct soc_enum aif2dacr_src_enum =
- SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 8, 2, aif2dac_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacr_src_enum,
+ WM8994_POWER_MANAGEMENT_6, 8, aif2dac_src_text);
static const struct snd_kcontrol_new aif2dacr_src_mux =
SOC_DAPM_ENUM("AIF2DACR Mux", aif2dacr_src_enum);
@@ -1647,15 +1651,15 @@ SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0),
};
static const struct snd_soc_dapm_widget wm8994_adc_revd_widgets[] = {
-SND_SOC_DAPM_VIRT_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux,
+SND_SOC_DAPM_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux,
adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
-SND_SOC_DAPM_VIRT_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux,
+SND_SOC_DAPM_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux,
adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
};
static const struct snd_soc_dapm_widget wm8994_adc_widgets[] = {
-SND_SOC_DAPM_VIRT_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux),
-SND_SOC_DAPM_VIRT_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux),
+SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux),
+SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux),
};
static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = {
@@ -2549,43 +2553,52 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
switch (mode) {
case WM8994_VMID_NORMAL:
+ snd_soc_dapm_mutex_lock(dapm);
+
if (wm8994->hubs.lineout1_se) {
- snd_soc_dapm_disable_pin(&codec->dapm,
- "LINEOUT1N Driver");
- snd_soc_dapm_disable_pin(&codec->dapm,
- "LINEOUT1P Driver");
+ snd_soc_dapm_disable_pin_unlocked(dapm,
+ "LINEOUT1N Driver");
+ snd_soc_dapm_disable_pin_unlocked(dapm,
+ "LINEOUT1P Driver");
}
if (wm8994->hubs.lineout2_se) {
- snd_soc_dapm_disable_pin(&codec->dapm,
- "LINEOUT2N Driver");
- snd_soc_dapm_disable_pin(&codec->dapm,
- "LINEOUT2P Driver");
+ snd_soc_dapm_disable_pin_unlocked(dapm,
+ "LINEOUT2N Driver");
+ snd_soc_dapm_disable_pin_unlocked(dapm,
+ "LINEOUT2P Driver");
}
/* Do the sync with the old mode to allow it to clean up */
- snd_soc_dapm_sync(&codec->dapm);
+ snd_soc_dapm_sync_unlocked(dapm);
wm8994->vmid_mode = mode;
+
+ snd_soc_dapm_mutex_unlock(dapm);
break;
case WM8994_VMID_FORCE:
+ snd_soc_dapm_mutex_lock(dapm);
+
if (wm8994->hubs.lineout1_se) {
- snd_soc_dapm_force_enable_pin(&codec->dapm,
- "LINEOUT1N Driver");
- snd_soc_dapm_force_enable_pin(&codec->dapm,
- "LINEOUT1P Driver");
+ snd_soc_dapm_force_enable_pin_unlocked(dapm,
+ "LINEOUT1N Driver");
+ snd_soc_dapm_force_enable_pin_unlocked(dapm,
+ "LINEOUT1P Driver");
}
if (wm8994->hubs.lineout2_se) {
- snd_soc_dapm_force_enable_pin(&codec->dapm,
- "LINEOUT2N Driver");
- snd_soc_dapm_force_enable_pin(&codec->dapm,
- "LINEOUT2P Driver");
+ snd_soc_dapm_force_enable_pin_unlocked(dapm,
+ "LINEOUT2N Driver");
+ snd_soc_dapm_force_enable_pin_unlocked(dapm,
+ "LINEOUT2P Driver");
}
wm8994->vmid_mode = mode;
- snd_soc_dapm_sync(&codec->dapm);
+ snd_soc_dapm_sync_unlocked(dapm);
+
+ snd_soc_dapm_mutex_unlock(dapm);
break;
default:
@@ -3237,7 +3250,7 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n",
wm8994->num_retune_mobile_texts);
- wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts;
+ wm8994->retune_mobile_enum.items = wm8994->num_retune_mobile_texts;
wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts;
ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls,
@@ -3293,7 +3306,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
for (i = 0; i < pdata->num_drc_cfgs; i++)
wm8994->drc_texts[i] = pdata->drc_cfgs[i].name;
- wm8994->drc_enum.max = pdata->num_drc_cfgs;
+ wm8994->drc_enum.items = pdata->num_drc_cfgs;
wm8994->drc_enum.texts = wm8994->drc_texts;
ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls,
@@ -3985,9 +3998,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
int ret, i;
wm8994->hubs.codec = codec;
- codec->control_data = control->regmap;
-
- snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
mutex_init(&wm8994->accdet_lock);
INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap,
@@ -4422,11 +4432,19 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
return 0;
}
+static struct regmap *wm8994_get_regmap(struct device *dev)
+{
+ struct wm8994 *control = dev_get_drvdata(dev->parent);
+
+ return control->regmap;
+}
+
static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
.probe = wm8994_codec_probe,
.remove = wm8994_codec_remove,
.suspend = wm8994_codec_suspend,
.resume = wm8994_codec_resume,
+ .get_regmap = wm8994_get_regmap,
.set_bias_level = wm8994_set_bias_level,
};
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 4300caff178..863a2c38bcb 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -423,24 +423,24 @@ static const char *in1l_text[] = {
"Differential", "Single-ended IN1LN", "Single-ended IN1LP"
};
-static const SOC_ENUM_SINGLE_DECL(in1l_enum, WM8995_LEFT_LINE_INPUT_CONTROL,
- 2, in1l_text);
+static SOC_ENUM_SINGLE_DECL(in1l_enum, WM8995_LEFT_LINE_INPUT_CONTROL,
+ 2, in1l_text);
static const char *in1r_text[] = {
"Differential", "Single-ended IN1RN", "Single-ended IN1RP"
};
-static const SOC_ENUM_SINGLE_DECL(in1r_enum, WM8995_LEFT_LINE_INPUT_CONTROL,
- 0, in1r_text);
+static SOC_ENUM_SINGLE_DECL(in1r_enum, WM8995_LEFT_LINE_INPUT_CONTROL,
+ 0, in1r_text);
static const char *dmic_src_text[] = {
"DMICDAT1", "DMICDAT2", "DMICDAT3"
};
-static const SOC_ENUM_SINGLE_DECL(dmic_src1_enum, WM8995_POWER_MANAGEMENT_5,
- 8, dmic_src_text);
-static const SOC_ENUM_SINGLE_DECL(dmic_src2_enum, WM8995_POWER_MANAGEMENT_5,
- 6, dmic_src_text);
+static SOC_ENUM_SINGLE_DECL(dmic_src1_enum, WM8995_POWER_MANAGEMENT_5,
+ 8, dmic_src_text);
+static SOC_ENUM_SINGLE_DECL(dmic_src2_enum, WM8995_POWER_MANAGEMENT_5,
+ 6, dmic_src_text);
static const struct snd_kcontrol_new wm8995_snd_controls[] = {
SOC_DOUBLE_R_TLV("DAC1 Volume", WM8995_DAC1_LEFT_VOLUME,
@@ -561,10 +561,8 @@ static int hp_supply_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec;
- struct wm8995_priv *wm8995;
codec = w->codec;
- wm8995 = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@@ -783,14 +781,12 @@ static const char *sidetone_text[] = {
"ADC/DMIC1", "DMIC2",
};
-static const struct soc_enum sidetone1_enum =
- SOC_ENUM_SINGLE(WM8995_SIDETONE, 0, 2, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(sidetone1_enum, WM8995_SIDETONE, 0, sidetone_text);
static const struct snd_kcontrol_new sidetone1_mux =
SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum);
-static const struct soc_enum sidetone2_enum =
- SOC_ENUM_SINGLE(WM8995_SIDETONE, 1, 2, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(sidetone2_enum, WM8995_SIDETONE, 1, sidetone_text);
static const struct snd_kcontrol_new sidetone2_mux =
SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum);
@@ -886,27 +882,26 @@ static const char *adc_mux_text[] = {
"DMIC",
};
-static const struct soc_enum adc_enum =
- SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text);
+static SOC_ENUM_SINGLE_VIRT_DECL(adc_enum, adc_mux_text);
static const struct snd_kcontrol_new adcl_mux =
- SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum);
+ SOC_DAPM_ENUM("ADCL Mux", adc_enum);
static const struct snd_kcontrol_new adcr_mux =
- SOC_DAPM_ENUM_VIRT("ADCR Mux", adc_enum);
+ SOC_DAPM_ENUM("ADCR Mux", adc_enum);
static const char *spk_src_text[] = {
"DAC1L", "DAC1R", "DAC2L", "DAC2R"
};
-static const SOC_ENUM_SINGLE_DECL(spk1l_src_enum, WM8995_LEFT_PDM_SPEAKER_1,
- 0, spk_src_text);
-static const SOC_ENUM_SINGLE_DECL(spk1r_src_enum, WM8995_RIGHT_PDM_SPEAKER_1,
- 0, spk_src_text);
-static const SOC_ENUM_SINGLE_DECL(spk2l_src_enum, WM8995_LEFT_PDM_SPEAKER_2,
- 0, spk_src_text);
-static const SOC_ENUM_SINGLE_DECL(spk2r_src_enum, WM8995_RIGHT_PDM_SPEAKER_2,
- 0, spk_src_text);
+static SOC_ENUM_SINGLE_DECL(spk1l_src_enum, WM8995_LEFT_PDM_SPEAKER_1,
+ 0, spk_src_text);
+static SOC_ENUM_SINGLE_DECL(spk1r_src_enum, WM8995_RIGHT_PDM_SPEAKER_1,
+ 0, spk_src_text);
+static SOC_ENUM_SINGLE_DECL(spk2l_src_enum, WM8995_LEFT_PDM_SPEAKER_2,
+ 0, spk_src_text);
+static SOC_ENUM_SINGLE_DECL(spk2r_src_enum, WM8995_RIGHT_PDM_SPEAKER_2,
+ 0, spk_src_text);
static const struct snd_kcontrol_new spk1l_mux =
SOC_DAPM_ENUM("SPK1L SRC", spk1l_src_enum);
@@ -953,10 +948,8 @@ static const struct snd_soc_dapm_widget wm8995_dapm_widgets[] = {
SND_SOC_DAPM_AIF_OUT("AIF1ADC2R", "AIF1 Capture",
0, WM8995_POWER_MANAGEMENT_3, 10, 0),
- SND_SOC_DAPM_VIRT_MUX("ADCL Mux", SND_SOC_NOPM, 1, 0,
- &adcl_mux),
- SND_SOC_DAPM_VIRT_MUX("ADCR Mux", SND_SOC_NOPM, 0, 0,
- &adcr_mux),
+ SND_SOC_DAPM_MUX("ADCL Mux", SND_SOC_NOPM, 1, 0, &adcl_mux),
+ SND_SOC_DAPM_MUX("ADCR Mux", SND_SOC_NOPM, 0, 0, &adcr_mux),
SND_SOC_DAPM_ADC("DMIC2L", NULL, WM8995_POWER_MANAGEMENT_3, 5, 0),
SND_SOC_DAPM_ADC("DMIC2R", NULL, WM8995_POWER_MANAGEMENT_3, 4, 0),
@@ -2047,13 +2040,6 @@ static int wm8995_probe(struct snd_soc_codec *codec)
wm8995 = snd_soc_codec_get_drvdata(codec);
wm8995->codec = codec;
- codec->control_data = wm8995->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
- return ret;
- }
-
for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++)
wm8995->supplies[i].supply = wm8995_supply_names[i];
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 1a7655b0aa2..69266332760 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -311,28 +311,28 @@ static const char *sidetone_hpf_text[] = {
"2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz"
};
-static const struct soc_enum sidetone_hpf =
- SOC_ENUM_SINGLE(WM8996_SIDETONE, 7, 7, sidetone_hpf_text);
+static SOC_ENUM_SINGLE_DECL(sidetone_hpf,
+ WM8996_SIDETONE, 7, sidetone_hpf_text);
static const char *hpf_mode_text[] = {
"HiFi", "Custom", "Voice"
};
-static const struct soc_enum dsp1tx_hpf_mode =
- SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 3, 3, hpf_mode_text);
+static SOC_ENUM_SINGLE_DECL(dsp1tx_hpf_mode,
+ WM8996_DSP1_TX_FILTERS, 3, hpf_mode_text);
-static const struct soc_enum dsp2tx_hpf_mode =
- SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 3, 3, hpf_mode_text);
+static SOC_ENUM_SINGLE_DECL(dsp2tx_hpf_mode,
+ WM8996_DSP2_TX_FILTERS, 3, hpf_mode_text);
static const char *hpf_cutoff_text[] = {
"50Hz", "75Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
};
-static const struct soc_enum dsp1tx_hpf_cutoff =
- SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 0, 7, hpf_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(dsp1tx_hpf_cutoff,
+ WM8996_DSP1_TX_FILTERS, 0, hpf_cutoff_text);
-static const struct soc_enum dsp2tx_hpf_cutoff =
- SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 0, 7, hpf_cutoff_text);
+static SOC_ENUM_SINGLE_DECL(dsp2tx_hpf_cutoff,
+ WM8996_DSP2_TX_FILTERS, 0, hpf_cutoff_text);
static void wm8996_set_retune_mobile(struct snd_soc_codec *codec, int block)
{
@@ -412,7 +412,7 @@ static int wm8996_get_retune_mobile_block(const char *name)
static int wm8996_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
struct wm8996_pdata *pdata = &wm8996->pdata;
int block = wm8996_get_retune_mobile_block(kcontrol->id.name);
@@ -434,7 +434,7 @@ static int wm8996_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
static int wm8996_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
int block = wm8996_get_retune_mobile_block(kcontrol->id.name);
@@ -780,14 +780,14 @@ static const char *sidetone_text[] = {
"IN1", "IN2",
};
-static const struct soc_enum left_sidetone_enum =
- SOC_ENUM_SINGLE(WM8996_SIDETONE, 0, 2, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(left_sidetone_enum,
+ WM8996_SIDETONE, 0, sidetone_text);
static const struct snd_kcontrol_new left_sidetone =
SOC_DAPM_ENUM("Left Sidetone", left_sidetone_enum);
-static const struct soc_enum right_sidetone_enum =
- SOC_ENUM_SINGLE(WM8996_SIDETONE, 1, 2, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(right_sidetone_enum,
+ WM8996_SIDETONE, 1, sidetone_text);
static const struct snd_kcontrol_new right_sidetone =
SOC_DAPM_ENUM("Right Sidetone", right_sidetone_enum);
@@ -796,14 +796,14 @@ static const char *spk_text[] = {
"DAC1L", "DAC1R", "DAC2L", "DAC2R"
};
-static const struct soc_enum spkl_enum =
- SOC_ENUM_SINGLE(WM8996_LEFT_PDM_SPEAKER, 0, 4, spk_text);
+static SOC_ENUM_SINGLE_DECL(spkl_enum,
+ WM8996_LEFT_PDM_SPEAKER, 0, spk_text);
static const struct snd_kcontrol_new spkl_mux =
SOC_DAPM_ENUM("SPKL", spkl_enum);
-static const struct soc_enum spkr_enum =
- SOC_ENUM_SINGLE(WM8996_RIGHT_PDM_SPEAKER, 0, 4, spk_text);
+static SOC_ENUM_SINGLE_DECL(spkr_enum,
+ WM8996_RIGHT_PDM_SPEAKER, 0, spk_text);
static const struct snd_kcontrol_new spkr_mux =
SOC_DAPM_ENUM("SPKR", spkr_enum);
@@ -812,8 +812,8 @@ static const char *dsp1rx_text[] = {
"AIF1", "AIF2"
};
-static const struct soc_enum dsp1rx_enum =
- SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 0, 2, dsp1rx_text);
+static SOC_ENUM_SINGLE_DECL(dsp1rx_enum,
+ WM8996_POWER_MANAGEMENT_8, 0, dsp1rx_text);
static const struct snd_kcontrol_new dsp1rx =
SOC_DAPM_ENUM("DSP1RX", dsp1rx_enum);
@@ -822,8 +822,8 @@ static const char *dsp2rx_text[] = {
"AIF2", "AIF1"
};
-static const struct soc_enum dsp2rx_enum =
- SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 4, 2, dsp2rx_text);
+static SOC_ENUM_SINGLE_DECL(dsp2rx_enum,
+ WM8996_POWER_MANAGEMENT_8, 4, dsp2rx_text);
static const struct snd_kcontrol_new dsp2rx =
SOC_DAPM_ENUM("DSP2RX", dsp2rx_enum);
@@ -832,8 +832,8 @@ static const char *aif2tx_text[] = {
"DSP2", "DSP1", "AIF1"
};
-static const struct soc_enum aif2tx_enum =
- SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 6, 3, aif2tx_text);
+static SOC_ENUM_SINGLE_DECL(aif2tx_enum,
+ WM8996_POWER_MANAGEMENT_8, 6, aif2tx_text);
static const struct snd_kcontrol_new aif2tx =
SOC_DAPM_ENUM("AIF2TX", aif2tx_enum);
@@ -842,14 +842,14 @@ static const char *inmux_text[] = {
"ADC", "DMIC1", "DMIC2"
};
-static const struct soc_enum in1_enum =
- SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 0, 3, inmux_text);
+static SOC_ENUM_SINGLE_DECL(in1_enum,
+ WM8996_POWER_MANAGEMENT_7, 0, inmux_text);
static const struct snd_kcontrol_new in1_mux =
SOC_DAPM_ENUM("IN1 Mux", in1_enum);
-static const struct soc_enum in2_enum =
- SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 4, 3, inmux_text);
+static SOC_ENUM_SINGLE_DECL(in2_enum,
+ WM8996_POWER_MANAGEMENT_7, 4, inmux_text);
static const struct snd_kcontrol_new in2_mux =
SOC_DAPM_ENUM("IN2 Mux", in2_enum);
@@ -1608,8 +1608,8 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec,
msleep(5);
}
- regcache_cache_only(codec->control_data, false);
- regcache_sync(codec->control_data);
+ regcache_cache_only(wm8996->regmap, false);
+ regcache_sync(wm8996->regmap);
}
/* Bypass the MICBIASes for lowest power */
@@ -1620,10 +1620,10 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec,
break;
case SND_SOC_BIAS_OFF:
- regcache_cache_only(codec->control_data, true);
+ regcache_cache_only(wm8996->regmap, true);
if (wm8996->pdata.ldo_ena >= 0) {
gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
- regcache_cache_only(codec->control_data, true);
+ regcache_cache_only(wm8996->regmap, true);
}
regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies),
wm8996->supplies);
@@ -2251,6 +2251,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
wm8996_polarity_fn polarity_cb)
{
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
wm8996->jack = jack;
wm8996->detecting = true;
@@ -2267,8 +2268,12 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
WM8996_MICB2_DISCH, 0);
/* LDO2 powers the microphones, SYSCLK clocks detection */
- snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2");
- snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
+ snd_soc_dapm_mutex_lock(dapm);
+
+ snd_soc_dapm_force_enable_pin_unlocked(dapm, "LDO2");
+ snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK");
+
+ snd_soc_dapm_mutex_unlock(dapm);
/* We start off just enabling microphone detection - even a
* plain headphone will trigger detection.
@@ -2595,7 +2600,7 @@ static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec)
dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n",
wm8996->num_retune_mobile_texts);
- wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts;
+ wm8996->retune_mobile_enum.items = wm8996->num_retune_mobile_texts;
wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts;
ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
@@ -2628,14 +2633,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
init_completion(&wm8996->dcs_done);
init_completion(&wm8996->fll_lock);
- codec->control_data = wm8996->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
- }
-
if (wm8996->pdata.num_retune_mobile_cfgs)
wm8996_retune_mobile_pdata(codec);
else
@@ -2674,13 +2671,11 @@ static int wm8996_probe(struct snd_soc_codec *codec)
} else {
dev_err(codec->dev, "Failed to request IRQ: %d\n",
ret);
+ return ret;
}
}
return 0;
-
-err:
- return ret;
}
static int wm8996_remove(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c
index 555115ee215..bb9b47b956a 100644
--- a/sound/soc/codecs/wm8997.c
+++ b/sound/soc/codecs/wm8997.c
@@ -86,7 +86,7 @@ static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w,
{
struct snd_soc_codec *codec = w->codec;
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
- struct regmap *regmap = codec->control_data;
+ struct regmap *regmap = arizona->regmap;
const struct reg_default *patch = NULL;
int i, patch_size;
@@ -123,10 +123,12 @@ static const unsigned int wm8997_osr_val[] = {
static const struct soc_enum wm8997_hpout_osr[] = {
SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L,
- ARIZONA_OUT1_OSR_SHIFT, 0x7, 3,
+ ARIZONA_OUT1_OSR_SHIFT, 0x7,
+ ARRAY_SIZE(wm8997_osr_text),
wm8997_osr_text, wm8997_osr_val),
SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L,
- ARIZONA_OUT3_OSR_SHIFT, 0x7, 3,
+ ARIZONA_OUT3_OSR_SHIFT, 0x7,
+ ARRAY_SIZE(wm8997_osr_text),
wm8997_osr_text, wm8997_osr_val),
};
@@ -170,15 +172,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
-SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21,
- ARIZONA_EQ1_ENA_MASK),
-SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21,
- ARIZONA_EQ2_ENA_MASK),
-SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21,
- ARIZONA_EQ3_ENA_MASK),
-SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21,
- ARIZONA_EQ4_ENA_MASK),
-
+SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19),
+SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 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,
@@ -190,6 +185,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
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, 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,
@@ -201,6 +198,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
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, 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,
@@ -212,6 +211,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
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, 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,
@@ -244,8 +245,8 @@ 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_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
-SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
+SOC_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
+SOC_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
@@ -285,8 +286,8 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
0xbf, 0, digital_tlv),
-SOC_VALUE_ENUM("HPOUT1 OSR", wm8997_hpout_osr[0]),
-SOC_VALUE_ENUM("EPOUT OSR", wm8997_hpout_osr[1]),
+SOC_ENUM("HPOUT1 OSR", wm8997_hpout_osr[0]),
+SOC_ENUM("EPOUT OSR", wm8997_hpout_osr[1]),
SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
@@ -404,7 +405,7 @@ static const struct soc_enum wm8997_aec_loopback =
wm8997_aec_loopback_values);
static const struct snd_kcontrol_new wm8997_aec_loopback_mux =
- SOC_DAPM_VALUE_ENUM("AEC Loopback", wm8997_aec_loopback);
+ SOC_DAPM_ENUM("AEC Loopback", wm8997_aec_loopback);
static const struct snd_soc_dapm_widget wm8997_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
@@ -603,7 +604,7 @@ SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX8_ENA_SHIFT, 0),
-SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
+SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0,
&wm8997_aec_loopback_mux),
@@ -1050,13 +1051,6 @@ static struct snd_soc_dai_driver wm8997_dai[] = {
static int wm8997_codec_probe(struct snd_soc_codec *codec)
{
struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- codec->control_data = priv->core.arizona->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
- if (ret != 0)
- return ret;
arizona_init_spk(codec);
@@ -1087,9 +1081,17 @@ static unsigned int wm8997_digital_vu[] = {
ARIZONA_DAC_DIGITAL_VOLUME_5R,
};
+static struct regmap *wm8997_get_regmap(struct device *dev)
+{
+ struct wm8997_priv *priv = dev_get_drvdata(dev);
+
+ return priv->core.arizona->regmap;
+}
+
static struct snd_soc_codec_driver soc_codec_dev_wm8997 = {
.probe = wm8997_codec_probe,
.remove = wm8997_codec_remove,
+ .get_regmap = wm8997_get_regmap,
.idle_bias_off = true,
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 0982c1d38ec..185eb97769e 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -268,8 +268,7 @@ static const char *drc_high_text[] = {
"0",
};
-static const struct soc_enum drc_high =
- SOC_ENUM_SINGLE(WM9081_DRC_3, 3, 6, drc_high_text);
+static SOC_ENUM_SINGLE_DECL(drc_high, WM9081_DRC_3, 3, drc_high_text);
static const char *drc_low_text[] = {
"1",
@@ -279,8 +278,7 @@ static const char *drc_low_text[] = {
"0",
};
-static const struct soc_enum drc_low =
- SOC_ENUM_SINGLE(WM9081_DRC_3, 0, 5, drc_low_text);
+static SOC_ENUM_SINGLE_DECL(drc_low, WM9081_DRC_3, 0, drc_low_text);
static const char *drc_atk_text[] = {
"181us",
@@ -297,8 +295,7 @@ static const char *drc_atk_text[] = {
"185.6ms",
};
-static const struct soc_enum drc_atk =
- SOC_ENUM_SINGLE(WM9081_DRC_2, 12, 12, drc_atk_text);
+static SOC_ENUM_SINGLE_DECL(drc_atk, WM9081_DRC_2, 12, drc_atk_text);
static const char *drc_dcy_text[] = {
"186ms",
@@ -312,8 +309,7 @@ static const char *drc_dcy_text[] = {
"47.56s",
};
-static const struct soc_enum drc_dcy =
- SOC_ENUM_SINGLE(WM9081_DRC_2, 8, 9, drc_dcy_text);
+static SOC_ENUM_SINGLE_DECL(drc_dcy, WM9081_DRC_2, 8, drc_dcy_text);
static const char *drc_qr_dcy_text[] = {
"0.725ms",
@@ -321,8 +317,7 @@ static const char *drc_qr_dcy_text[] = {
"5.8ms",
};
-static const struct soc_enum drc_qr_dcy =
- SOC_ENUM_SINGLE(WM9081_DRC_2, 4, 3, drc_qr_dcy_text);
+static SOC_ENUM_SINGLE_DECL(drc_qr_dcy, WM9081_DRC_2, 4, drc_qr_dcy_text);
static const char *dac_deemph_text[] = {
"None",
@@ -331,21 +326,21 @@ static const char *dac_deemph_text[] = {
"48kHz",
};
-static const struct soc_enum dac_deemph =
- SOC_ENUM_SINGLE(WM9081_DAC_DIGITAL_2, 1, 4, dac_deemph_text);
+static SOC_ENUM_SINGLE_DECL(dac_deemph, WM9081_DAC_DIGITAL_2, 1,
+ dac_deemph_text);
static const char *speaker_mode_text[] = {
"Class D",
"Class AB",
};
-static const struct soc_enum speaker_mode =
- SOC_ENUM_SINGLE(WM9081_ANALOGUE_SPEAKER_2, 6, 2, speaker_mode_text);
+static SOC_ENUM_SINGLE_DECL(speaker_mode, WM9081_ANALOGUE_SPEAKER_2, 6,
+ speaker_mode_text);
static int speaker_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int reg;
reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
@@ -366,7 +361,7 @@ static int speaker_mode_get(struct snd_kcontrol *kcontrol,
static int speaker_mode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
unsigned int reg_pwr = snd_soc_read(codec, WM9081_POWER_MANAGEMENT);
unsigned int reg2 = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
@@ -1265,15 +1260,6 @@ static struct snd_soc_dai_driver wm9081_dai = {
static int wm9081_probe(struct snd_soc_codec *codec)
{
struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- codec->control_data = wm9081->regmap;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
/* Enable zero cross by default */
snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT,
@@ -1288,7 +1274,7 @@ static int wm9081_probe(struct snd_soc_codec *codec)
ARRAY_SIZE(wm9081_eq_controls));
}
- return ret;
+ return 0;
}
static int wm9081_remove(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index a07fe1618ee..87934171f06 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -522,16 +522,6 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
static int wm9090_probe(struct snd_soc_codec *codec)
{
- struct wm9090_priv *wm9090 = dev_get_drvdata(codec->dev);
- int ret;
-
- codec->control_data = wm9090->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
/* Configure some defaults; they will be written out when we
* bring the bias up.
*/
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index 70ce6793c5b..c0b7f45dfa3 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -67,12 +67,12 @@ static const char *wm9705_mic[] = {"Mic 1", "Mic 2"};
static const char *wm9705_rec_sel[] = {"Mic", "CD", "NC", "NC",
"Line", "Stereo Mix", "Mono Mix", "Phone"};
-static const struct soc_enum wm9705_enum_mic =
- SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, wm9705_mic);
-static const struct soc_enum wm9705_enum_rec_l =
- SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9705_rec_sel);
-static const struct soc_enum wm9705_enum_rec_r =
- SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9705_rec_sel);
+static SOC_ENUM_SINGLE_DECL(wm9705_enum_mic,
+ AC97_GENERAL_PURPOSE, 8, wm9705_mic);
+static SOC_ENUM_SINGLE_DECL(wm9705_enum_rec_l,
+ AC97_REC_SEL, 8, wm9705_rec_sel);
+static SOC_ENUM_SINGLE_DECL(wm9705_enum_rec_r,
+ AC97_REC_SEL, 0, wm9705_rec_sel);
/* Headphone Mixer */
static const struct snd_kcontrol_new wm9705_hp_mixer_controls[] = {
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index acea8927905..2a9c6d11330 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -74,8 +74,7 @@ static const char *wm9713_rec_src[] =
"Mono Out", "Zh"};
static const char *wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
static const char *wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"};
-static const char *wm9713_mono_pga[] = {"Vmid", "Zh", "Mono", "Inv",
- "Mono Vmid", "Inv Vmid"};
+static const char *wm9713_mono_pga[] = {"Vmid", "Zh", "Mono", "Inv"};
static const char *wm9713_spk_pga[] =
{"Vmid", "Zh", "Headphone", "Speaker", "Inv", "Headphone Vmid",
"Speaker Vmid", "Inv Vmid"};
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 444626fcab4..060027182dc 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -242,7 +242,7 @@ struct wm_coeff_ctl {
static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
@@ -254,7 +254,7 @@ static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
@@ -684,24 +684,38 @@ static int wm_adsp_load(struct wm_adsp *dsp)
}
if (reg) {
- buf = wm_adsp_buf_alloc(region->data,
- le32_to_cpu(region->len),
- &buf_list);
- if (!buf) {
- adsp_err(dsp, "Out of memory\n");
- ret = -ENOMEM;
- goto out_fw;
- }
+ size_t to_write = PAGE_SIZE;
+ size_t remain = le32_to_cpu(region->len);
+ const u8 *data = region->data;
+
+ while (remain > 0) {
+ if (remain < PAGE_SIZE)
+ to_write = remain;
+
+ buf = wm_adsp_buf_alloc(data,
+ to_write,
+ &buf_list);
+ if (!buf) {
+ adsp_err(dsp, "Out of memory\n");
+ ret = -ENOMEM;
+ goto out_fw;
+ }
- ret = regmap_raw_write_async(regmap, reg, buf->buf,
- le32_to_cpu(region->len));
- if (ret != 0) {
- adsp_err(dsp,
- "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
- file, regions,
- le32_to_cpu(region->len), offset,
- region_name, ret);
- goto out_fw;
+ ret = regmap_raw_write_async(regmap, reg,
+ buf->buf,
+ to_write);
+ if (ret != 0) {
+ adsp_err(dsp,
+ "%s.%d: Failed to write %zd bytes at %d in %s: %d\n",
+ file, regions,
+ to_write, offset,
+ region_name, ret);
+ goto out_fw;
+ }
+
+ data += to_write;
+ reg += to_write / 2;
+ remain -= to_write;
}
}
@@ -1529,16 +1543,16 @@ static void wm_adsp2_boot_work(struct work_struct *work)
ret = regmap_read(dsp->regmap,
dsp->base + ADSP2_CLOCKING, &val);
if (ret != 0) {
- dev_err(dsp->dev, "Failed to read clocking: %d\n", ret);
+ adsp_err(dsp, "Failed to read clocking: %d\n", ret);
return;
}
if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
ret = regulator_enable(dsp->dvfs);
if (ret != 0) {
- dev_err(dsp->dev,
- "Failed to enable supply: %d\n",
- ret);
+ adsp_err(dsp,
+ "Failed to enable supply: %d\n",
+ ret);
return;
}
@@ -1546,9 +1560,9 @@ static void wm_adsp2_boot_work(struct work_struct *work)
1800000,
1800000);
if (ret != 0) {
- dev_err(dsp->dev,
- "Failed to raise supply: %d\n",
- ret);
+ adsp_err(dsp,
+ "Failed to raise supply: %d\n",
+ ret);
return;
}
}
@@ -1611,7 +1625,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
break;
default:
break;
- };
+ }
return 0;
}
@@ -1658,15 +1672,15 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
ret = regulator_set_voltage(dsp->dvfs, 1200000,
1800000);
if (ret != 0)
- dev_warn(dsp->dev,
- "Failed to lower supply: %d\n",
- ret);
+ adsp_warn(dsp,
+ "Failed to lower supply: %d\n",
+ ret);
ret = regulator_disable(dsp->dvfs);
if (ret != 0)
- dev_err(dsp->dev,
- "Failed to enable supply: %d\n",
- ret);
+ adsp_err(dsp,
+ "Failed to enable supply: %d\n",
+ ret);
}
list_for_each_entry(ctl, &dsp->ctl_list, list)
@@ -1679,6 +1693,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
list_del(&alg_region->list);
kfree(alg_region);
}
+
+ adsp_dbg(dsp, "Shutdown complete\n");
break;
default:
@@ -1716,28 +1732,25 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
if (IS_ERR(adsp->dvfs)) {
ret = PTR_ERR(adsp->dvfs);
- dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
+ adsp_err(adsp, "Failed to get DCVDD: %d\n", ret);
return ret;
}
ret = regulator_enable(adsp->dvfs);
if (ret != 0) {
- dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
- ret);
+ adsp_err(adsp, "Failed to enable DCVDD: %d\n", ret);
return ret;
}
ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
if (ret != 0) {
- dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
- ret);
+ adsp_err(adsp, "Failed to initialise DVFS: %d\n", ret);
return ret;
}
ret = regulator_disable(adsp->dvfs);
if (ret != 0) {
- dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
- ret);
+ adsp_err(adsp, "Failed to disable DCVDD: %d\n", ret);
return ret;
}
}
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index b371066dd5b..916817fe663 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -50,16 +50,16 @@ static const char *speaker_ref_text[] = {
"VMID",
};
-static const struct soc_enum speaker_ref =
- SOC_ENUM_SINGLE(WM8993_SPEAKER_MIXER, 8, 2, speaker_ref_text);
+static SOC_ENUM_SINGLE_DECL(speaker_ref,
+ WM8993_SPEAKER_MIXER, 8, speaker_ref_text);
static const char *speaker_mode_text[] = {
"Class D",
"Class AB",
};
-static const struct soc_enum speaker_mode =
- SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text);
+static SOC_ENUM_SINGLE_DECL(speaker_mode,
+ WM8993_SPKMIXR_ATTENUATION, 8, speaker_mode_text);
static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op)
{
@@ -337,7 +337,7 @@ static void enable_dc_servo(struct snd_soc_codec *codec)
static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
int ret;
@@ -735,15 +735,15 @@ static const char *hp_mux_text[] = {
"DAC",
};
-static const struct soc_enum hpl_enum =
- SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text);
+static SOC_ENUM_SINGLE_DECL(hpl_enum,
+ WM8993_OUTPUT_MIXER1, 8, hp_mux_text);
const struct snd_kcontrol_new wm_hubs_hpl_mux =
WM_HUBS_ENUM_W("Left Headphone Mux", hpl_enum);
EXPORT_SYMBOL_GPL(wm_hubs_hpl_mux);
-static const struct soc_enum hpr_enum =
- SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text);
+static SOC_ENUM_SINGLE_DECL(hpr_enum,
+ WM8993_OUTPUT_MIXER2, 8, hp_mux_text);
const struct snd_kcontrol_new wm_hubs_hpr_mux =
WM_HUBS_ENUM_W("Right Headphone Mux", hpr_enum);