summaryrefslogtreecommitdiff
path: root/sound/soc/codecs
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2017-09-01 14:12:16 +0300
committerMark Brown <broonie@kernel.org>2017-09-01 14:12:16 +0300
commitab99d9872e93e83fc2d992eeb8de7d9a128858eb (patch)
tree49910d189623ffaab04dd5241e7eabe236053b16 /sound/soc/codecs
parenta5ef8ca69a6bea61062854ee37cb199a5659964c (diff)
parent56026714bd45fccda710114982789c5145285560 (diff)
downloadlinux-ab99d9872e93e83fc2d992eeb8de7d9a128858eb.tar.xz
Merge remote-tracking branch 'asoc/topic/msm8916' into asoc-next
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/88pm860x-codec.c2
-rw-r--r--sound/soc/codecs/Kconfig9
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/ab8500-codec.c2
-rw-r--r--sound/soc/codecs/ac97.c2
-rw-r--r--sound/soc/codecs/ad1836.c2
-rw-r--r--sound/soc/codecs/ad193x.c2
-rw-r--r--sound/soc/codecs/ad1980.c2
-rw-r--r--sound/soc/codecs/ad73311.c2
-rw-r--r--sound/soc/codecs/adau1373.c2
-rw-r--r--sound/soc/codecs/adau1701.c2
-rw-r--r--sound/soc/codecs/adau1977.c2
-rw-r--r--sound/soc/codecs/adav80x.c2
-rw-r--r--sound/soc/codecs/ads117x.c2
-rw-r--r--sound/soc/codecs/ak4104.c2
-rw-r--r--sound/soc/codecs/ak4535.c2
-rw-r--r--sound/soc/codecs/ak4554.c2
-rw-r--r--sound/soc/codecs/ak4613.c2
-rw-r--r--sound/soc/codecs/ak4641.c2
-rw-r--r--sound/soc/codecs/ak4642.c2
-rw-r--r--sound/soc/codecs/ak4671.c2
-rw-r--r--sound/soc/codecs/ak5386.c2
-rw-r--r--sound/soc/codecs/alc5623.c2
-rw-r--r--sound/soc/codecs/bt-sco.c2
-rw-r--r--sound/soc/codecs/cq93vc.c2
-rw-r--r--sound/soc/codecs/cs35l33.c2
-rw-r--r--sound/soc/codecs/cs35l34.c2
-rw-r--r--sound/soc/codecs/cs35l35.c2
-rw-r--r--sound/soc/codecs/cs4271.c2
-rw-r--r--sound/soc/codecs/cs42l51.c2
-rw-r--r--sound/soc/codecs/cs4349.c2
-rw-r--r--sound/soc/codecs/cs47l24.c4
-rw-r--r--sound/soc/codecs/cs53l30.c2
-rw-r--r--sound/soc/codecs/cx20442.c2
-rw-r--r--sound/soc/codecs/da7210.c2
-rw-r--r--sound/soc/codecs/da7213.c2
-rw-r--r--sound/soc/codecs/da7218.c2
-rw-r--r--sound/soc/codecs/da7219.c2
-rw-r--r--sound/soc/codecs/da732x.c2
-rw-r--r--sound/soc/codecs/da9055.c2
-rw-r--r--sound/soc/codecs/dmic.c54
-rw-r--r--sound/soc/codecs/es7134.c2
-rw-r--r--sound/soc/codecs/es8316.c2
-rw-r--r--sound/soc/codecs/es8328.c2
-rw-r--r--sound/soc/codecs/hdac_hdmi.c4
-rw-r--r--sound/soc/codecs/hdmi-codec.c37
-rw-r--r--sound/soc/codecs/ics43432.c2
-rw-r--r--sound/soc/codecs/inno_rk3036.c2
-rw-r--r--sound/soc/codecs/isabelle.c2
-rw-r--r--sound/soc/codecs/jz4740.c2
-rw-r--r--sound/soc/codecs/lm4857.c2
-rw-r--r--sound/soc/codecs/lm49453.c2
-rw-r--r--sound/soc/codecs/max9768.c2
-rw-r--r--sound/soc/codecs/max98088.c2
-rw-r--r--sound/soc/codecs/max98090.c2
-rw-r--r--sound/soc/codecs/max98095.c2
-rw-r--r--sound/soc/codecs/max98357a.c2
-rw-r--r--sound/soc/codecs/max9850.c2
-rw-r--r--sound/soc/codecs/max9860.c2
-rw-r--r--sound/soc/codecs/max9867.c2
-rw-r--r--sound/soc/codecs/max98926.c2
-rw-r--r--sound/soc/codecs/mc13783.c2
-rw-r--r--sound/soc/codecs/ml26124.c2
-rw-r--r--sound/soc/codecs/msm8916-wcd-analog.c416
-rw-r--r--sound/soc/codecs/msm8916-wcd-digital.c39
-rw-r--r--sound/soc/codecs/nau8540.c2
-rw-r--r--sound/soc/codecs/nau8810.c2
-rw-r--r--sound/soc/codecs/nau8824.c2
-rw-r--r--sound/soc/codecs/nau8825.c2
-rw-r--r--sound/soc/codecs/pcm1681.c2
-rw-r--r--sound/soc/codecs/pcm179x.c2
-rw-r--r--sound/soc/codecs/pcm3008.c2
-rw-r--r--sound/soc/codecs/pcm512x.c2
-rw-r--r--sound/soc/codecs/rt274.c1228
-rw-r--r--sound/soc/codecs/rt274.h217
-rw-r--r--sound/soc/codecs/rt286.c2
-rw-r--r--sound/soc/codecs/rt298.c2
-rw-r--r--sound/soc/codecs/rt5514-spi.c2
-rw-r--r--sound/soc/codecs/rt5514.c2
-rw-r--r--sound/soc/codecs/rt5616.c2
-rw-r--r--sound/soc/codecs/rt5631.c2
-rw-r--r--sound/soc/codecs/rt5640.c2
-rw-r--r--sound/soc/codecs/rt5645.c2
-rw-r--r--sound/soc/codecs/rt5651.c2
-rw-r--r--sound/soc/codecs/rt5659.c2
-rw-r--r--sound/soc/codecs/rt5660.c2
-rw-r--r--sound/soc/codecs/rt5663.c2
-rw-r--r--sound/soc/codecs/rt5665.c2
-rw-r--r--sound/soc/codecs/rt5670.c2
-rw-r--r--sound/soc/codecs/rt5677.c2
-rw-r--r--sound/soc/codecs/sgtl5000.c2
-rw-r--r--sound/soc/codecs/si476x.c2
-rw-r--r--sound/soc/codecs/sirf-audio-codec.c2
-rw-r--r--sound/soc/codecs/sn95031.c2
-rw-r--r--sound/soc/codecs/spdif_receiver.c2
-rw-r--r--sound/soc/codecs/spdif_transmitter.c2
-rw-r--r--sound/soc/codecs/ssm2518.c2
-rw-r--r--sound/soc/codecs/ssm2602.c2
-rw-r--r--sound/soc/codecs/ssm4567.c2
-rw-r--r--sound/soc/codecs/stac9766.c2
-rw-r--r--sound/soc/codecs/tas2552.c2
-rw-r--r--sound/soc/codecs/tas5086.c2
-rw-r--r--sound/soc/codecs/tas5720.c2
-rw-r--r--sound/soc/codecs/tlv320aic23.c2
-rw-r--r--sound/soc/codecs/tlv320aic26.c2
-rw-r--r--sound/soc/codecs/tlv320aic31xx.c2
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c2
-rw-r--r--sound/soc/codecs/tlv320aic3x.c2
-rw-r--r--sound/soc/codecs/tlv320dac33.c2
-rw-r--r--sound/soc/codecs/twl4030.c2
-rw-r--r--sound/soc/codecs/twl6040.c2
-rw-r--r--sound/soc/codecs/uda134x.c2
-rw-r--r--sound/soc/codecs/uda1380.c2
-rw-r--r--sound/soc/codecs/wl1273.c2
-rw-r--r--sound/soc/codecs/wm5102.c2
-rw-r--r--sound/soc/codecs/wm5110.c2
-rw-r--r--sound/soc/codecs/zx_aud96p22.c2
117 files changed, 2065 insertions, 159 deletions
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index b013a4c62b63..848c5fe49bc7 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -1355,7 +1355,7 @@ static struct regmap *pm860x_get_regmap(struct device *dev)
return pm860x->regmap;
}
-static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
+static const struct snd_soc_codec_driver soc_codec_dev_pm860x = {
.probe = pm860x_probe,
.remove = pm860x_remove,
.set_bias_level = pm860x_set_bias_level,
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 6c78b0b49b81..aee9ef16dae6 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -71,7 +71,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_DA732X if I2C
select SND_SOC_DA9055 if I2C
select SND_SOC_DIO2125
- select SND_SOC_DMIC
+ select SND_SOC_DMIC if GPIOLIB
select SND_SOC_ES8316 if I2C
select SND_SOC_ES8328_SPI if SPI_MASTER
select SND_SOC_ES8328_I2C if I2C
@@ -114,6 +114,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_PCM5102A
select SND_SOC_PCM512x_I2C if I2C
select SND_SOC_PCM512x_SPI if SPI_MASTER
+ select SND_SOC_RT274 if I2C
select SND_SOC_RT286 if I2C
select SND_SOC_RT298 if I2C
select SND_SOC_RT5514 if I2C
@@ -716,11 +717,17 @@ config SND_SOC_RL6231
config SND_SOC_RL6347A
tristate
+ default y if SND_SOC_RT274=y
default y if SND_SOC_RT286=y
default y if SND_SOC_RT298=y
+ default m if SND_SOC_RT274=m
default m if SND_SOC_RT286=m
default m if SND_SOC_RT298=m
+config SND_SOC_RT274
+ tristate
+ depends on I2C
+
config SND_SOC_RT286
tristate
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 1755a54e3dc9..a8a4b0797f46 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -113,6 +113,7 @@ snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
snd-soc-pcm512x-spi-objs := pcm512x-spi.o
snd-soc-rl6231-objs := rl6231.o
snd-soc-rl6347a-objs := rl6347a.o
+snd-soc-rt274-objs := rt274.o
snd-soc-rt286-objs := rt286.o
snd-soc-rt298-objs := rt298.o
snd-soc-rt5514-objs := rt5514.o
@@ -349,6 +350,7 @@ 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_RL6347A) += snd-soc-rl6347a.o
+obj-$(CONFIG_SND_SOC_RT274) += snd-soc-rt274.o
obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o
obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o
obj-$(CONFIG_SND_SOC_RT5514) += snd-soc-rt5514.o
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index 312b2a11abb6..006627b8c3a8 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -2523,7 +2523,7 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec)
return status;
}
-static struct snd_soc_codec_driver ab8500_codec_driver = {
+static const struct snd_soc_codec_driver ab8500_codec_driver = {
.probe = ab8500_codec_probe,
.component_driver = {
.controls = ab8500_ctrls,
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index f7f04c6be01e..440b4ce54376 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -112,7 +112,7 @@ static int ac97_soc_resume(struct snd_soc_codec *codec)
#define ac97_soc_resume NULL
#endif
-static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
+static const struct snd_soc_codec_driver soc_codec_dev_ac97 = {
.probe = ac97_soc_probe,
.suspend = ac97_soc_suspend,
.resume = ac97_soc_resume,
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index a478239aadac..d0361caad09e 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -321,7 +321,7 @@ static int ad1836_remove(struct snd_soc_codec *codec)
AD1836_ADC_SERFMT_MASK, 0);
}
-static struct snd_soc_codec_driver soc_codec_dev_ad1836 = {
+static const struct snd_soc_codec_driver soc_codec_dev_ad1836 = {
.probe = ad1836_probe,
.remove = ad1836_remove,
.suspend = ad1836_suspend,
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index d643557d89a7..d10988eec0c1 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -408,7 +408,7 @@ static int ad193x_codec_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
+static const struct snd_soc_codec_driver soc_codec_dev_ad193x = {
.probe = ad193x_codec_probe,
.component_driver = {
.controls = ad193x_snd_controls,
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index b7c1b9f4bf5f..ce89bfb42094 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -295,7 +295,7 @@ static int ad1980_soc_remove(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
+static const struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
.probe = ad1980_soc_probe,
.remove = ad1980_soc_remove,
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index 3e358a49442d..d8d86a0fea60 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -54,7 +54,7 @@ static struct snd_soc_dai_driver ad73311_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
};
-static struct snd_soc_codec_driver soc_codec_dev_ad73311 = {
+static const struct snd_soc_codec_driver soc_codec_dev_ad73311 = {
.component_driver = {
.dapm_widgets = ad73311_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(ad73311_dapm_widgets),
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index 8fa9045571ff..a865945d776a 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -1458,7 +1458,7 @@ static const struct regmap_config adau1373_regmap_config = {
.num_reg_defaults = ARRAY_SIZE(adau1373_reg_defaults),
};
-static struct snd_soc_codec_driver adau1373_codec_driver = {
+static const struct snd_soc_codec_driver adau1373_codec_driver = {
.probe = adau1373_probe,
.resume = adau1373_resume,
.set_bias_level = adau1373_set_bias_level,
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 3bad1bc8c00a..805afac8146b 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -757,7 +757,7 @@ static int adau1701_resume(struct snd_soc_codec *codec)
#define adau1701_suspend NULL
#endif /* CONFIG_PM */
-static struct snd_soc_codec_driver adau1701_codec_drv = {
+static const struct snd_soc_codec_driver adau1701_codec_drv = {
.probe = adau1701_probe,
.remove = adau1701_remove,
.resume = adau1701_resume,
diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c
index b319db6a69f8..329281675765 100644
--- a/sound/soc/codecs/adau1977.c
+++ b/sound/soc/codecs/adau1977.c
@@ -867,7 +867,7 @@ static int adau1977_codec_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver adau1977_codec_driver = {
+static const struct snd_soc_codec_driver adau1977_codec_driver = {
.probe = adau1977_codec_probe,
.set_bias_level = adau1977_set_bias_level,
.set_sysclk = adau1977_set_sysclk,
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index 6e793ebb5883..da7ca81f47cf 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -825,7 +825,7 @@ static int adav80x_resume(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver adav80x_codec_driver = {
+static const struct snd_soc_codec_driver adav80x_codec_driver = {
.probe = adav80x_probe,
.resume = adav80x_resume,
.set_bias_level = adav80x_set_bias_level,
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c
index 90c756d183b4..b7f0057c0239 100644
--- a/sound/soc/codecs/ads117x.c
+++ b/sound/soc/codecs/ads117x.c
@@ -58,7 +58,7 @@ static struct snd_soc_dai_driver ads117x_dai = {
.formats = ADS117X_FORMATS,},
};
-static struct snd_soc_codec_driver soc_codec_dev_ads117x = {
+static const struct snd_soc_codec_driver soc_codec_dev_ads117x = {
.component_driver = {
.dapm_widgets = ads117x_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(ads117x_dapm_widgets),
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index 1a9d233c94d0..dbb184118f2e 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -242,7 +242,7 @@ static int ak4104_soc_resume(struct snd_soc_codec *codec)
#define ak4104_soc_resume NULL
#endif /* CONFIG_PM */
-static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
+static const struct snd_soc_codec_driver soc_codec_device_ak4104 = {
.probe = ak4104_probe,
.remove = ak4104_remove,
.suspend = ak4104_soc_suspend,
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 66cfffde9a12..e3c157dc88db 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -390,7 +390,7 @@ static const struct regmap_config ak4535_regmap = {
.num_reg_defaults = ARRAY_SIZE(ak4535_reg_defaults),
};
-static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
+static const struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
.resume = ak4535_resume,
.set_bias_level = ak4535_set_bias_level,
.suspend_bias_off = true,
diff --git a/sound/soc/codecs/ak4554.c b/sound/soc/codecs/ak4554.c
index b92c548b9d29..0bb4fe5c122a 100644
--- a/sound/soc/codecs/ak4554.c
+++ b/sound/soc/codecs/ak4554.c
@@ -64,7 +64,7 @@ static struct snd_soc_dai_driver ak4554_dai = {
.symmetric_rates = 1,
};
-static struct snd_soc_codec_driver soc_codec_dev_ak4554 = {
+static const struct snd_soc_codec_driver soc_codec_dev_ak4554 = {
.component_driver = {
.dapm_widgets = ak4554_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(ak4554_dapm_widgets),
diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c
index 690edebf029e..b95bb8b52e51 100644
--- a/sound/soc/codecs/ak4613.c
+++ b/sound/soc/codecs/ak4613.c
@@ -522,7 +522,7 @@ static int ak4613_resume(struct snd_soc_codec *codec)
return regcache_sync(regmap);
}
-static struct snd_soc_codec_driver soc_codec_dev_ak4613 = {
+static const struct snd_soc_codec_driver soc_codec_dev_ak4613 = {
.suspend = ak4613_suspend,
.resume = ak4613_resume,
.set_bias_level = ak4613_set_bias_level,
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index ebdaf56c1d61..60142ff32d4f 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -524,7 +524,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_ak4641 = {
+static const struct snd_soc_codec_driver soc_codec_dev_ak4641 = {
.component_driver = {
.controls = ak4641_snd_controls,
.num_controls = ARRAY_SIZE(ak4641_snd_controls),
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 66de8a2013a6..29530c567bd9 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -550,7 +550,7 @@ static int ak4642_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
+static const struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
.probe = ak4642_probe,
.suspend = ak4642_suspend,
.resume = ak4642_resume,
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index 6088afaabf62..dcfdff56fc5a 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -610,7 +610,7 @@ static struct snd_soc_dai_driver ak4671_dai = {
.ops = &ak4671_dai_ops,
};
-static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
+static const struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
.set_bias_level = ak4671_set_bias_level,
.component_driver = {
.controls = ak4671_snd_controls,
diff --git a/sound/soc/codecs/ak5386.c b/sound/soc/codecs/ak5386.c
index 0ef2df223336..d0e16c03815c 100644
--- a/sound/soc/codecs/ak5386.c
+++ b/sound/soc/codecs/ak5386.c
@@ -69,7 +69,7 @@ static int ak5386_soc_resume(struct snd_soc_codec *codec)
#define ak5386_soc_resume NULL
#endif /* CONFIG_PM */
-static struct snd_soc_codec_driver soc_codec_ak5386 = {
+static const struct snd_soc_codec_driver soc_codec_ak5386 = {
.probe = ak5386_soc_probe,
.remove = ak5386_soc_remove,
.suspend = ak5386_soc_suspend,
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index d2e3a3ef7499..1db965a93632 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -951,7 +951,7 @@ static int alc5623_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
+static const struct snd_soc_codec_driver soc_codec_device_alc5623 = {
.probe = alc5623_probe,
.suspend = alc5623_suspend,
.resume = alc5623_resume,
diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c
index 8014e697d540..806191addb44 100644
--- a/sound/soc/codecs/bt-sco.c
+++ b/sound/soc/codecs/bt-sco.c
@@ -62,7 +62,7 @@ static struct snd_soc_dai_driver bt_sco_dai[] = {
}
};
-static struct snd_soc_codec_driver soc_codec_dev_bt_sco = {
+static const struct snd_soc_codec_driver soc_codec_dev_bt_sco = {
.component_driver = {
.dapm_widgets = bt_sco_widgets,
.num_dapm_widgets = ARRAY_SIZE(bt_sco_widgets),
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index 7a2d9a2ee427..6ed2cc374768 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -128,7 +128,7 @@ static struct regmap *cq93vc_get_regmap(struct device *dev)
return davinci_vc->regmap;
}
-static struct snd_soc_codec_driver soc_codec_dev_cq93vc = {
+static const struct snd_soc_codec_driver soc_codec_dev_cq93vc = {
.set_bias_level = cq93vc_set_bias_level,
.get_regmap = cq93vc_get_regmap,
.component_driver = {
diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c
index 6df29fa30fb9..61d128b53e14 100644
--- a/sound/soc/codecs/cs35l33.c
+++ b/sound/soc/codecs/cs35l33.c
@@ -831,7 +831,7 @@ static int cs35l33_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_cs35l33 = {
+static const struct snd_soc_codec_driver soc_codec_dev_cs35l33 = {
.probe = cs35l33_probe,
.set_bias_level = cs35l33_set_bias_level,
diff --git a/sound/soc/codecs/cs35l34.c b/sound/soc/codecs/cs35l34.c
index 0a747c66cc6c..15d712f4803e 100644
--- a/sound/soc/codecs/cs35l34.c
+++ b/sound/soc/codecs/cs35l34.c
@@ -779,7 +779,7 @@ static int cs35l34_probe(struct snd_soc_codec *codec)
}
-static struct snd_soc_codec_driver soc_codec_dev_cs35l34 = {
+static const struct snd_soc_codec_driver soc_codec_dev_cs35l34 = {
.probe = cs35l34_probe,
.component_driver = {
diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c
index f1ee184ecab2..129978d1243e 100644
--- a/sound/soc/codecs/cs35l35.c
+++ b/sound/soc/codecs/cs35l35.c
@@ -1079,7 +1079,7 @@ static int cs35l35_codec_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_cs35l35 = {
+static const struct snd_soc_codec_driver soc_codec_dev_cs35l35 = {
.probe = cs35l35_codec_probe,
.set_sysclk = cs35l35_codec_set_sysclk,
.component_driver = {
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index d8824773dc29..49a80627af12 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -639,7 +639,7 @@ static int cs4271_codec_remove(struct snd_soc_codec *codec)
return 0;
};
-static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
+static const struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
.probe = cs4271_codec_probe,
.remove = cs4271_codec_remove,
.suspend = cs4271_soc_suspend,
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index 96cfe38943cd..f8072f1897d4 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -504,7 +504,7 @@ static int cs42l51_codec_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
+static const struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
.probe = cs42l51_codec_probe,
.component_driver = {
diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c
index 231ca935cdf3..0a749c79ef57 100644
--- a/sound/soc/codecs/cs4349.c
+++ b/sound/soc/codecs/cs4349.c
@@ -255,7 +255,7 @@ static struct snd_soc_dai_driver cs4349_dai = {
.symmetric_rates = 1,
};
-static struct snd_soc_codec_driver soc_codec_dev_cs4349 = {
+static const struct snd_soc_codec_driver soc_codec_dev_cs4349 = {
.component_driver = {
.controls = cs4349_snd_controls,
.num_controls = ARRAY_SIZE(cs4349_snd_controls),
diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c
index 47e6fddef92b..505dbc9d73cf 100644
--- a/sound/soc/codecs/cs47l24.c
+++ b/sound/soc/codecs/cs47l24.c
@@ -1183,7 +1183,7 @@ static struct regmap *cs47l24_get_regmap(struct device *dev)
return priv->core.arizona->regmap;
}
-static struct snd_soc_codec_driver soc_codec_dev_cs47l24 = {
+static const struct snd_soc_codec_driver soc_codec_dev_cs47l24 = {
.probe = cs47l24_codec_probe,
.remove = cs47l24_codec_remove,
.get_regmap = cs47l24_get_regmap,
@@ -1213,7 +1213,7 @@ static struct snd_compr_ops cs47l24_compr_ops = {
.copy = wm_adsp_compr_copy,
};
-static struct snd_soc_platform_driver cs47l24_compr_platform = {
+static const struct snd_soc_platform_driver cs47l24_compr_platform = {
.compr_ops = &cs47l24_compr_ops,
};
diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c
index 06933a5d0a75..da4ee5633778 100644
--- a/sound/soc/codecs/cs53l30.c
+++ b/sound/soc/codecs/cs53l30.c
@@ -892,7 +892,7 @@ static int cs53l30_codec_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver cs53l30_driver = {
+static const struct snd_soc_codec_driver cs53l30_driver = {
.probe = cs53l30_codec_probe,
.set_bias_level = cs53l30_set_bias_level,
.idle_bias_off = true,
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index 2c12471e42a6..46b1fbb66eba 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -398,7 +398,7 @@ static int cx20442_codec_remove(struct snd_soc_codec *codec)
static const u8 cx20442_reg;
-static struct snd_soc_codec_driver cx20442_codec_dev = {
+static const struct snd_soc_codec_driver cx20442_codec_dev = {
.probe = cx20442_codec_probe,
.remove = cx20442_codec_remove,
.set_bias_level = cx20442_set_bias_level,
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index 17053dfc94cf..1af443ccbc51 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -1164,7 +1164,7 @@ static int da7210_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
+static const struct snd_soc_codec_driver soc_codec_dev_da7210 = {
.probe = da7210_probe,
.component_driver = {
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c
index c3e11897f8ae..cc0b2d2eaf15 100644
--- a/sound/soc/codecs/da7213.c
+++ b/sound/soc/codecs/da7213.c
@@ -1787,7 +1787,7 @@ static int da7213_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_da7213 = {
+static const struct snd_soc_codec_driver soc_codec_dev_da7213 = {
.probe = da7213_probe,
.set_bias_level = da7213_set_bias_level,
diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c
index 6e1940eb0653..b2d42ec1dcd9 100644
--- a/sound/soc/codecs/da7218.c
+++ b/sound/soc/codecs/da7218.c
@@ -3035,7 +3035,7 @@ static int da7218_resume(struct snd_soc_codec *codec)
#define da7218_resume NULL
#endif
-static struct snd_soc_codec_driver soc_codec_dev_da7218 = {
+static const struct snd_soc_codec_driver soc_codec_dev_da7218 = {
.probe = da7218_probe,
.remove = da7218_remove,
.suspend = da7218_suspend,
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index f71d72c22bfc..6f088536df32 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -1891,7 +1891,7 @@ static int da7219_resume(struct snd_soc_codec *codec)
#define da7219_resume NULL
#endif
-static struct snd_soc_codec_driver soc_codec_dev_da7219 = {
+static const struct snd_soc_codec_driver soc_codec_dev_da7219 = {
.probe = da7219_probe,
.remove = da7219_remove,
.suspend = da7219_suspend,
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c
index c1cc1c1c28f2..83db4d23c90b 100644
--- a/sound/soc/codecs/da732x.c
+++ b/sound/soc/codecs/da732x.c
@@ -1499,7 +1499,7 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_da732x = {
+static const struct snd_soc_codec_driver soc_codec_dev_da732x = {
.set_bias_level = da732x_set_bias_level,
.component_driver = {
.controls = da732x_snd_controls,
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c
index 4efb5f897a0c..bd7faaee5802 100644
--- a/sound/soc/codecs/da9055.c
+++ b/sound/soc/codecs/da9055.c
@@ -1451,7 +1451,7 @@ static int da9055_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_da9055 = {
+static const struct snd_soc_codec_driver soc_codec_dev_da9055 = {
.probe = da9055_probe,
.set_bias_level = da9055_set_bias_level,
diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c
index c82b9dc41e9a..b88a1ee66f80 100644
--- a/sound/soc/codecs/dmic.c
+++ b/sound/soc/codecs/dmic.c
@@ -19,6 +19,8 @@
*
*/
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -27,6 +29,34 @@
#include <sound/soc.h>
#include <sound/soc-dapm.h>
+static int dmic_daiops_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct gpio_desc *dmic_en = snd_soc_dai_get_drvdata(dai);
+
+ if (!dmic_en)
+ return 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ gpiod_set_value(dmic_en, 1);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ gpiod_set_value(dmic_en, 0);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops dmic_dai_ops = {
+ .trigger = dmic_daiops_trigger,
+};
+
static struct snd_soc_dai_driver dmic_dai = {
.name = "dmic-hifi",
.capture = {
@@ -38,8 +68,23 @@ static struct snd_soc_dai_driver dmic_dai = {
| SNDRV_PCM_FMTBIT_S24_LE
| SNDRV_PCM_FMTBIT_S16_LE,
},
+ .ops = &dmic_dai_ops,
};
+static int dmic_codec_probe(struct snd_soc_codec *codec)
+{
+ struct gpio_desc *dmic_en;
+
+ dmic_en = devm_gpiod_get_optional(codec->dev,
+ "dmicen", GPIOD_OUT_LOW);
+ if (IS_ERR(dmic_en))
+ return PTR_ERR(dmic_en);
+
+ snd_soc_codec_set_drvdata(codec, dmic_en);
+
+ return 0;
+}
+
static const struct snd_soc_dapm_widget dmic_dapm_widgets[] = {
SND_SOC_DAPM_AIF_OUT("DMIC AIF", "Capture", 0,
SND_SOC_NOPM, 0, 0),
@@ -50,7 +95,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"DMIC AIF", NULL, "DMic"},
};
-static struct snd_soc_codec_driver soc_dmic = {
+static const struct snd_soc_codec_driver soc_dmic = {
+ .probe = dmic_codec_probe,
.component_driver = {
.dapm_widgets = dmic_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(dmic_dapm_widgets),
@@ -73,9 +119,15 @@ static int dmic_dev_remove(struct platform_device *pdev)
MODULE_ALIAS("platform:dmic-codec");
+static const struct of_device_id dmic_dev_match[] = {
+ {.compatible = "dmic-codec"},
+ {}
+};
+
static struct platform_driver dmic_driver = {
.driver = {
.name = "dmic-codec",
+ .of_match_table = dmic_dev_match,
},
.probe = dmic_dev_probe,
.remove = dmic_dev_remove,
diff --git a/sound/soc/codecs/es7134.c b/sound/soc/codecs/es7134.c
index 25ede825d349..3869025754d8 100644
--- a/sound/soc/codecs/es7134.c
+++ b/sound/soc/codecs/es7134.c
@@ -69,7 +69,7 @@ static const struct snd_soc_dapm_route es7134_dapm_routes[] = {
{ "AOUTR", NULL, "DAC" },
};
-static struct snd_soc_codec_driver es7134_codec_driver = {
+static const struct snd_soc_codec_driver es7134_codec_driver = {
.component_driver = {
.dapm_widgets = es7134_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(es7134_dapm_widgets),
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index ecc02449c569..4f35af6a5d3a 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -554,7 +554,7 @@ static int es8316_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_es8316 = {
+static const struct snd_soc_codec_driver soc_codec_dev_es8316 = {
.probe = es8316_probe,
.idle_bias_off = true,
diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c
index ed7cc42d1ee2..bcdb8914ec16 100644
--- a/sound/soc/codecs/es8328.c
+++ b/sound/soc/codecs/es8328.c
@@ -830,7 +830,7 @@ const struct regmap_config es8328_regmap_config = {
};
EXPORT_SYMBOL_GPL(es8328_regmap_config);
-static struct snd_soc_codec_driver es8328_codec_driver = {
+static const struct snd_soc_codec_driver es8328_codec_driver = {
.probe = es8328_codec_probe,
.suspend = es8328_suspend,
.resume = es8328_resume,
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index bc2e74ff3b2d..e808f94bf8d1 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -1360,7 +1360,7 @@ static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdac)
}
-static struct snd_soc_dai_ops hdmi_dai_ops = {
+static const struct snd_soc_dai_ops hdmi_dai_ops = {
.startup = hdac_hdmi_pcm_open,
.shutdown = hdac_hdmi_pcm_close,
.hw_params = hdac_hdmi_set_hw_params,
@@ -1858,7 +1858,7 @@ static void hdmi_codec_complete(struct device *dev)
#define hdmi_codec_complete NULL
#endif
-static struct snd_soc_codec_driver hdmi_hda_codec = {
+static const struct snd_soc_codec_driver hdmi_hda_codec = {
.probe = hdmi_codec_probe,
.remove = hdmi_codec_remove,
.idle_bias_off = true,
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 22ed0dc88f0a..d73d2c1ed823 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -326,7 +326,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
static unsigned long hdmi_codec_spk_mask_from_alloc(int spk_alloc)
{
int i;
- const unsigned long hdmi_codec_eld_spk_alloc_bits[] = {
+ static const unsigned long hdmi_codec_eld_spk_alloc_bits[] = {
[0] = FL | FR, [1] = LFE, [2] = FC, [3] = RL | RR,
[4] = RC, [5] = FLC | FRC, [6] = RLC | RRC,
};
@@ -399,18 +399,6 @@ static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol,
return 0;
}
-
-static const struct snd_kcontrol_new hdmi_controls[] = {
- {
- .access = SNDRV_CTL_ELEM_ACCESS_READ |
- SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = "ELD",
- .info = hdmi_eld_ctl_info,
- .get = hdmi_eld_ctl_get,
- },
-};
-
static int hdmi_codec_new_stream(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -668,6 +656,16 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
{
struct snd_soc_dai_driver *drv = dai->driver;
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_new hdmi_eld_ctl = {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "ELD",
+ .info = hdmi_eld_ctl_info,
+ .get = hdmi_eld_ctl_get,
+ .device = rtd->pcm->device,
+ };
int ret;
dev_dbg(dai->dev, "%s()\n", __func__);
@@ -686,10 +684,15 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps;
hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
- return 0;
+ /* add ELD ctl with the device number corresponding to the PCM stream */
+ kctl = snd_ctl_new1(&hdmi_eld_ctl, dai->component);
+ if (!kctl)
+ return -ENOMEM;
+
+ return snd_ctl_add(rtd->card->snd_card, kctl);
}
-static struct snd_soc_dai_driver hdmi_i2s_dai = {
+static const struct snd_soc_dai_driver hdmi_i2s_dai = {
.name = "i2s-hifi",
.id = DAI_ID_I2S,
.playback = {
@@ -730,10 +733,8 @@ static int hdmi_of_xlate_dai_id(struct snd_soc_component *component,
return ret;
}
-static struct snd_soc_codec_driver hdmi_codec = {
+static const struct snd_soc_codec_driver hdmi_codec = {
.component_driver = {
- .controls = hdmi_controls,
- .num_controls = ARRAY_SIZE(hdmi_controls),
.dapm_widgets = hdmi_widgets,
.num_dapm_widgets = ARRAY_SIZE(hdmi_widgets),
.dapm_routes = hdmi_routes,
diff --git a/sound/soc/codecs/ics43432.c b/sound/soc/codecs/ics43432.c
index dd850b93938d..651206273f36 100644
--- a/sound/soc/codecs/ics43432.c
+++ b/sound/soc/codecs/ics43432.c
@@ -37,7 +37,7 @@ static struct snd_soc_dai_driver ics43432_dai = {
},
};
-static struct snd_soc_codec_driver ics43432_codec_driver = {
+static const struct snd_soc_codec_driver ics43432_codec_driver = {
};
static int ics43432_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c
index b918ba5c8ce5..64b0be94bea3 100644
--- a/sound/soc/codecs/inno_rk3036.c
+++ b/sound/soc/codecs/inno_rk3036.c
@@ -376,7 +376,7 @@ static int rk3036_codec_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static struct snd_soc_codec_driver rk3036_codec_driver = {
+static const struct snd_soc_codec_driver rk3036_codec_driver = {
.probe = rk3036_codec_probe,
.remove = rk3036_codec_remove,
.set_bias_level = rk3036_codec_set_bias_level,
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c
index a4b0eded984a..5ca99280ae00 100644
--- a/sound/soc/codecs/isabelle.c
+++ b/sound/soc/codecs/isabelle.c
@@ -1087,7 +1087,7 @@ static struct snd_soc_dai_driver isabelle_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_isabelle = {
+static const struct snd_soc_codec_driver soc_codec_dev_isabelle = {
.set_bias_level = isabelle_set_bias_level,
.component_driver = {
.controls = isabelle_snd_controls,
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index 0290fab383da..6324ccdc8a5c 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -293,7 +293,7 @@ static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
+static const struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
.probe = jz4740_codec_dev_probe,
.set_bias_level = jz4740_codec_set_bias_level,
.suspend_bias_off = true,
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 558de1053f73..1e964079642a 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -100,7 +100,7 @@ static const struct snd_soc_dapm_route lm4857_routes[] = {
{ "EP", "Earpiece", "Mode" },
};
-static struct snd_soc_component_driver lm4857_component_driver = {
+static const struct snd_soc_component_driver lm4857_component_driver = {
.controls = lm4857_controls,
.num_controls = ARRAY_SIZE(lm4857_controls),
.dapm_widgets = lm4857_dapm_widgets,
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c
index 8d413c2677cc..41e09d1287b8 100644
--- a/sound/soc/codecs/lm49453.c
+++ b/sound/soc/codecs/lm49453.c
@@ -1389,7 +1389,7 @@ static struct snd_soc_dai_driver lm49453_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_lm49453 = {
+static const struct snd_soc_codec_driver soc_codec_dev_lm49453 = {
.set_bias_level = lm49453_set_bias_level,
.component_driver = {
.controls = lm49453_snd_controls,
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
index 5b82e26cd5d1..7017c0389e73 100644
--- a/sound/soc/codecs/max9768.c
+++ b/sound/soc/codecs/max9768.c
@@ -151,7 +151,7 @@ static int max9768_probe(struct snd_soc_component *component)
return 0;
}
-static struct snd_soc_component_driver max9768_component_driver = {
+static const struct snd_soc_component_driver max9768_component_driver = {
.probe = max9768_probe,
.controls = max9768_volume,
.num_controls = ARRAY_SIZE(max9768_volume),
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 72f77455582e..f0bb830874e5 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -1698,7 +1698,7 @@ static int max98088_remove(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_max98088 = {
+static const struct snd_soc_codec_driver soc_codec_dev_max98088 = {
.probe = max98088_probe,
.remove = max98088_remove,
.set_bias_level = max98088_set_bias_level,
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index 66828480d484..13bcfb1ef9b4 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -2499,7 +2499,7 @@ static void max98090_seq_notifier(struct snd_soc_dapm_context *dapm,
}
}
-static struct snd_soc_codec_driver soc_codec_dev_max98090 = {
+static const struct snd_soc_codec_driver soc_codec_dev_max98090 = {
.probe = max98090_probe,
.remove = max98090_remove,
.seq_notifier = max98090_seq_notifier,
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 6f8a757876ed..5ead87d2ab1d 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -2102,7 +2102,7 @@ static int max98095_remove(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_max98095 = {
+static const struct snd_soc_codec_driver soc_codec_dev_max98095 = {
.probe = max98095_probe,
.remove = max98095_remove,
.suspend = max98095_suspend,
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c
index 6a6b68a4cb52..426ed2dae6ca 100644
--- a/sound/soc/codecs/max98357a.c
+++ b/sound/soc/codecs/max98357a.c
@@ -72,7 +72,7 @@ static int max98357a_codec_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver max98357a_codec_driver = {
+static const struct snd_soc_codec_driver max98357a_codec_driver = {
.probe = max98357a_codec_probe,
.component_driver = {
.dapm_widgets = max98357a_dapm_widgets,
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c
index 0610840733d1..a3dfc918c278 100644
--- a/sound/soc/codecs/max9850.c
+++ b/sound/soc/codecs/max9850.c
@@ -301,7 +301,7 @@ static int max9850_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_max9850 = {
+static const struct snd_soc_codec_driver soc_codec_dev_max9850 = {
.probe = max9850_probe,
.set_bias_level = max9850_set_bias_level,
.suspend_bias_off = true,
diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c
index 499bdbfd0a2d..a2dc6a47f466 100644
--- a/sound/soc/codecs/max9860.c
+++ b/sound/soc/codecs/max9860.c
@@ -534,7 +534,7 @@ static int max9860_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static struct snd_soc_codec_driver max9860_codec_driver = {
+static const struct snd_soc_codec_driver max9860_codec_driver = {
.set_bias_level = max9860_set_bias_level,
.idle_bias_off = true,
diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c
index 2a40a69a7513..6c0c0d6e8f3c 100644
--- a/sound/soc/codecs/max9867.c
+++ b/sound/soc/codecs/max9867.c
@@ -413,7 +413,7 @@ static int max9867_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver max9867_codec = {
+static const struct snd_soc_codec_driver max9867_codec = {
.probe = max9867_probe,
.component_driver = {
.controls = max9867_snd_controls,
diff --git a/sound/soc/codecs/max98926.c b/sound/soc/codecs/max98926.c
index 1eff7e0b092e..7a39bfb9e0f9 100644
--- a/sound/soc/codecs/max98926.c
+++ b/sound/soc/codecs/max98926.c
@@ -496,7 +496,7 @@ static int max98926_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_max98926 = {
+static const struct snd_soc_codec_driver soc_codec_dev_max98926 = {
.probe = max98926_probe,
.component_driver = {
.controls = max98926_snd_controls,
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index 90562703dcfd..4fd8d1dc4eef 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -733,7 +733,7 @@ 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 = {
+static const struct snd_soc_codec_driver soc_codec_dev_mc13783 = {
.probe = mc13783_probe,
.remove = mc13783_remove,
.get_regmap = mc13783_get_regmap,
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
index 69e5e18880c5..5cc960d8211e 100644
--- a/sound/soc/codecs/ml26124.c
+++ b/sound/soc/codecs/ml26124.c
@@ -537,7 +537,7 @@ static int ml26124_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_ml26124 = {
+static const struct snd_soc_codec_driver soc_codec_dev_ml26124 = {
.probe = ml26124_probe,
.set_bias_level = ml26124_set_bias_level,
.suspend_bias_off = true,
diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c
index 5710fd440bcd..cd4d60ef4c77 100644
--- a/sound/soc/codecs/msm8916-wcd-analog.c
+++ b/sound/soc/codecs/msm8916-wcd-analog.c
@@ -12,9 +12,16 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/tlv.h>
+#include <sound/jack.h>
#define CDC_D_REVISION1 (0xf000)
#define CDC_D_PERPH_SUBTYPE (0xf005)
+#define CDC_D_INT_EN_SET (0x015)
+#define CDC_D_INT_EN_CLR (0x016)
+#define MBHC_SWITCH_INT BIT(7)
+#define MBHC_MIC_ELECTRICAL_INS_REM_DET BIT(6)
+#define MBHC_BUTTON_PRESS_DET BIT(5)
+#define MBHC_BUTTON_RELEASE_DET BIT(4)
#define CDC_D_CDC_RST_CTL (0xf046)
#define RST_CTL_DIG_SW_RST_N_MASK BIT(7)
#define RST_CTL_DIG_SW_RST_N_RESET 0
@@ -37,6 +44,8 @@
#define DIG_CLK_CTL_RXD1_CLK_EN BIT(0)
#define DIG_CLK_CTL_RXD2_CLK_EN BIT(1)
#define DIG_CLK_CTL_RXD3_CLK_EN BIT(2)
+#define DIG_CLK_CTL_D_MBHC_CLK_EN_MASK BIT(3)
+#define DIG_CLK_CTL_D_MBHC_CLK_EN BIT(3)
#define DIG_CLK_CTL_TXD_CLK_EN BIT(4)
#define DIG_CLK_CTL_NCP_CLK_EN_MASK BIT(6)
#define DIG_CLK_CTL_NCP_CLK_EN BIT(6)
@@ -93,8 +102,12 @@
#define MICB_1_EN_TX3_GND_SEL_TX_GND 0
#define CDC_A_MICB_1_VAL (0xf141)
+#define MICB_MIN_VAL 1600
+#define MICB_STEP_SIZE 50
+#define MICB_VOLTAGE_REGVAL(v) ((v - MICB_MIN_VAL)/MICB_STEP_SIZE)
#define MICB_1_VAL_MICB_OUT_VAL_MASK GENMASK(7, 3)
#define MICB_1_VAL_MICB_OUT_VAL_V2P70V ((0x16) << 3)
+#define MICB_1_VAL_MICB_OUT_VAL_V1P80V ((0x4) << 3)
#define CDC_A_MICB_1_CTL (0xf142)
#define MICB_1_CTL_CFILT_REF_SEL_MASK BIT(1)
@@ -128,8 +141,51 @@
#define MICB_1_INT_TX3_INT_PULLUP_EN_TX1N_TO_GND 0
#define CDC_A_MICB_2_EN (0xf144)
+#define CDC_A_MICB_2_EN_ENABLE BIT(7)
+#define CDC_A_MICB_2_PULL_DOWN_EN_MASK BIT(5)
+#define CDC_A_MICB_2_PULL_DOWN_EN BIT(5)
#define CDC_A_TX_1_2_ATEST_CTL_2 (0xf145)
#define CDC_A_MASTER_BIAS_CTL (0xf146)
+#define CDC_A_MBHC_DET_CTL_1 (0xf147)
+#define CDC_A_MBHC_DET_CTL_L_DET_EN BIT(7)
+#define CDC_A_MBHC_DET_CTL_GND_DET_EN BIT(6)
+#define CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_INSERTION BIT(5)
+#define CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_REMOVAL (0)
+#define CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_MASK BIT(5)
+#define CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_SHIFT (5)
+#define CDC_A_MBHC_DET_CTL_MIC_CLAMP_CTL_AUTO BIT(4)
+#define CDC_A_MBHC_DET_CTL_MIC_CLAMP_CTL_MANUAL BIT(3)
+#define CDC_A_MBHC_DET_CTL_MIC_CLAMP_CTL_MASK GENMASK(4, 3)
+#define CDC_A_MBHC_DET_CTL_MBHC_BIAS_EN BIT(2)
+#define CDC_A_MBHC_DET_CTL_2 (0xf150)
+#define CDC_A_MBHC_DET_CTL_HS_L_DET_PULL_UP_CTRL_I_3P0 (BIT(7) | BIT(6))
+#define CDC_A_MBHC_DET_CTL_HS_L_DET_COMPA_CTRL_V0P9_VDD BIT(5)
+#define CDC_A_PLUG_TYPE_MASK GENMASK(4, 3)
+#define CDC_A_HPHL_PLUG_TYPE_NO BIT(4)
+#define CDC_A_GND_PLUG_TYPE_NO BIT(3)
+#define CDC_A_MBHC_DET_CTL_HPHL_100K_TO_GND_EN_MASK BIT(0)
+#define CDC_A_MBHC_DET_CTL_HPHL_100K_TO_GND_EN BIT(0)
+#define CDC_A_MBHC_FSM_CTL (0xf151)
+#define CDC_A_MBHC_FSM_CTL_MBHC_FSM_EN BIT(7)
+#define CDC_A_MBHC_FSM_CTL_MBHC_FSM_EN_MASK BIT(7)
+#define CDC_A_MBHC_FSM_CTL_BTN_ISRC_CTRL_I_100UA (0x3 << 4)
+#define CDC_A_MBHC_FSM_CTL_BTN_ISRC_CTRL_MASK GENMASK(6, 4)
+#define CDC_A_MBHC_DBNC_TIMER (0xf152)
+#define CDC_A_MBHC_DBNC_TIMER_BTN_DBNC_T_16MS BIT(3)
+#define CDC_A_MBHC_DBNC_TIMER_INSREM_DBNC_T_256_MS (0x9 << 4)
+#define CDC_A_MBHC_BTN0_ZDET_CTL_0 (0xf153)
+#define CDC_A_MBHC_BTN1_ZDET_CTL_1 (0xf154)
+#define CDC_A_MBHC_BTN2_ZDET_CTL_2 (0xf155)
+#define CDC_A_MBHC_BTN3_CTL (0xf156)
+#define CDC_A_MBHC_BTN4_CTL (0xf157)
+#define CDC_A_MBHC_BTN_VREF_FINE_SHIFT (2)
+#define CDC_A_MBHC_BTN_VREF_FINE_MASK GENMASK(4, 2)
+#define CDC_A_MBHC_BTN_VREF_COARSE_MASK GENMASK(7, 5)
+#define CDC_A_MBHC_BTN_VREF_COARSE_SHIFT (5)
+#define CDC_A_MBHC_BTN_VREF_MASK (CDC_A_MBHC_BTN_VREF_COARSE_MASK | \
+ CDC_A_MBHC_BTN_VREF_FINE_MASK)
+#define CDC_A_MBHC_RESULT_1 (0xf158)
+#define CDC_A_MBHC_RESULT_1_BTN_RESULT_MASK GENMASK(4, 0)
#define CDC_A_TX_1_EN (0xf160)
#define CDC_A_TX_2_EN (0xf161)
#define CDC_A_TX_1_2_TEST_CTL_1 (0xf162)
@@ -213,18 +269,37 @@
#define MSM8916_WCD_ANALOG_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE)
+static int btn_mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_BTN_4;
+static int hs_jack_mask = SND_JACK_HEADPHONE | SND_JACK_HEADSET;
+
static const char * const supply_names[] = {
"vdd-cdc-io",
"vdd-cdc-tx-rx-cx",
};
+#define MBHC_MAX_BUTTONS (5)
+
struct pm8916_wcd_analog_priv {
u16 pmic_rev;
u16 codec_version;
+ bool mbhc_btn_enabled;
+ /* special event to detect accessory type */
+ bool mbhc_btn0_pressed;
+ bool detect_accessory_type;
struct clk *mclk;
+ struct snd_soc_codec *codec;
struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
+ struct snd_soc_jack *jack;
+ bool hphl_jack_type_normally_open;
+ bool gnd_jack_type_normally_open;
+ /* Voltage threshold when internal current source of 100uA is used */
+ u32 vref_btn_cs[MBHC_MAX_BUTTONS];
+ /* Voltage threshold when microphone bias is ON */
+ u32 vref_btn_micb[MBHC_MAX_BUTTONS];
unsigned int micbias1_cap_mode;
unsigned int micbias2_cap_mode;
+ unsigned int micbias_mv;
};
static const char *const adc2_mux_text[] = { "ZERO", "INP2", "INP3" };
@@ -265,18 +340,25 @@ static const struct snd_kcontrol_new pm8916_wcd_analog_snd_controls[] = {
static void pm8916_wcd_analog_micbias_enable(struct snd_soc_codec *codec)
{
+ struct pm8916_wcd_analog_priv *wcd = snd_soc_codec_get_drvdata(codec);
+
snd_soc_update_bits(codec, CDC_A_MICB_1_CTL,
MICB_1_CTL_EXT_PRECHARG_EN_MASK |
MICB_1_CTL_INT_PRECHARG_BYP_MASK,
MICB_1_CTL_INT_PRECHARG_BYP_EXT_PRECHRG_SEL
| MICB_1_CTL_EXT_PRECHARG_EN_ENABLE);
- snd_soc_write(codec, CDC_A_MICB_1_VAL, MICB_1_VAL_MICB_OUT_VAL_V2P70V);
- /*
- * Special headset needs MICBIAS as 2.7V so wait for
- * 50 msec for the MICBIAS to reach 2.7 volts.
- */
- msleep(50);
+ if (wcd->micbias_mv) {
+ snd_soc_write(codec, CDC_A_MICB_1_VAL,
+ MICB_VOLTAGE_REGVAL(wcd->micbias_mv));
+ /*
+ * Special headset needs MICBIAS as 2.7V so wait for
+ * 50 msec for the MICBIAS to reach 2.7 volts.
+ */
+ if (wcd->micbias_mv >= 2700)
+ msleep(50);
+ }
+
snd_soc_update_bits(codec, CDC_A_MICB_1_CTL,
MICB_1_CTL_EXT_PRECHARG_EN_MASK |
MICB_1_CTL_INT_PRECHARG_BYP_MASK, 0);
@@ -361,6 +443,97 @@ static int pm8916_wcd_analog_enable_micbias_int1(struct
wcd->micbias1_cap_mode);
}
+static void pm8916_wcd_setup_mbhc(struct pm8916_wcd_analog_priv *wcd)
+{
+ struct snd_soc_codec *codec = wcd->codec;
+ u32 plug_type = 0;
+ u32 int_en_mask;
+
+ snd_soc_write(codec, CDC_A_MBHC_DET_CTL_1,
+ CDC_A_MBHC_DET_CTL_L_DET_EN |
+ CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_INSERTION |
+ CDC_A_MBHC_DET_CTL_MIC_CLAMP_CTL_AUTO |
+ CDC_A_MBHC_DET_CTL_MBHC_BIAS_EN);
+
+ if (wcd->hphl_jack_type_normally_open)
+ plug_type |= CDC_A_HPHL_PLUG_TYPE_NO;
+
+ if (wcd->gnd_jack_type_normally_open)
+ plug_type |= CDC_A_GND_PLUG_TYPE_NO;
+
+ snd_soc_write(codec, CDC_A_MBHC_DET_CTL_2,
+ CDC_A_MBHC_DET_CTL_HS_L_DET_PULL_UP_CTRL_I_3P0 |
+ CDC_A_MBHC_DET_CTL_HS_L_DET_COMPA_CTRL_V0P9_VDD |
+ plug_type |
+ CDC_A_MBHC_DET_CTL_HPHL_100K_TO_GND_EN);
+
+
+ snd_soc_write(codec, CDC_A_MBHC_DBNC_TIMER,
+ CDC_A_MBHC_DBNC_TIMER_INSREM_DBNC_T_256_MS |
+ CDC_A_MBHC_DBNC_TIMER_BTN_DBNC_T_16MS);
+
+ /* enable MBHC clock */
+ snd_soc_update_bits(codec, CDC_D_CDC_DIG_CLK_CTL,
+ DIG_CLK_CTL_D_MBHC_CLK_EN_MASK,
+ DIG_CLK_CTL_D_MBHC_CLK_EN);
+
+ int_en_mask = MBHC_SWITCH_INT;
+ if (wcd->mbhc_btn_enabled)
+ int_en_mask |= MBHC_BUTTON_PRESS_DET | MBHC_BUTTON_RELEASE_DET;
+
+ snd_soc_update_bits(codec, CDC_D_INT_EN_CLR, int_en_mask, 0);
+ snd_soc_update_bits(codec, CDC_D_INT_EN_SET, int_en_mask, int_en_mask);
+ wcd->mbhc_btn0_pressed = false;
+ wcd->detect_accessory_type = true;
+}
+
+static int pm8916_mbhc_configure_bias(struct pm8916_wcd_analog_priv *priv,
+ bool micbias2_enabled)
+{
+ struct snd_soc_codec *codec = priv->codec;
+ u32 coarse, fine, reg_val, reg_addr;
+ int *vrefs, i;
+
+ if (!micbias2_enabled) { /* use internal 100uA Current source */
+ /* Enable internal 2.2k Internal Rbias Resistor */
+ snd_soc_update_bits(codec, CDC_A_MICB_1_INT_RBIAS,
+ MICB_1_INT_TX2_INT_RBIAS_EN_MASK,
+ MICB_1_INT_TX2_INT_RBIAS_EN_ENABLE);
+ /* Remove pull down on MIC BIAS2 */
+ snd_soc_update_bits(codec, CDC_A_MICB_2_EN,
+ CDC_A_MICB_2_PULL_DOWN_EN_MASK,
+ 0);
+ /* enable 100uA internal current source */
+ snd_soc_update_bits(codec, CDC_A_MBHC_FSM_CTL,
+ CDC_A_MBHC_FSM_CTL_BTN_ISRC_CTRL_MASK,
+ CDC_A_MBHC_FSM_CTL_BTN_ISRC_CTRL_I_100UA);
+ }
+ snd_soc_update_bits(codec, CDC_A_MBHC_FSM_CTL,
+ CDC_A_MBHC_FSM_CTL_MBHC_FSM_EN_MASK,
+ CDC_A_MBHC_FSM_CTL_MBHC_FSM_EN);
+
+ if (micbias2_enabled)
+ vrefs = &priv->vref_btn_micb[0];
+ else
+ vrefs = &priv->vref_btn_cs[0];
+
+ /* program vref ranges for all the buttons */
+ reg_addr = CDC_A_MBHC_BTN0_ZDET_CTL_0;
+ for (i = 0; i < MBHC_MAX_BUTTONS; i++) {
+ /* split mv in to coarse parts of 100mv & fine parts of 12mv */
+ coarse = (vrefs[i] / 100);
+ fine = ((vrefs[i] % 100) / 12);
+ reg_val = (coarse << CDC_A_MBHC_BTN_VREF_COARSE_SHIFT) |
+ (fine << CDC_A_MBHC_BTN_VREF_FINE_SHIFT);
+ snd_soc_update_bits(codec, reg_addr,
+ CDC_A_MBHC_BTN_VREF_MASK,
+ reg_val);
+ reg_addr++;
+ }
+
+ return 0;
+}
+
static int pm8916_wcd_analog_enable_micbias_int2(struct
snd_soc_dapm_widget
*w, struct snd_kcontrol
@@ -369,6 +542,15 @@ static int pm8916_wcd_analog_enable_micbias_int2(struct
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct pm8916_wcd_analog_priv *wcd = snd_soc_codec_get_drvdata(codec);
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ pm8916_mbhc_configure_bias(wcd, true);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ pm8916_mbhc_configure_bias(wcd, false);
+ break;
+ }
+
return pm8916_wcd_analog_enable_micbias_int(codec, event, w->reg,
wcd->micbias2_cap_mode);
}
@@ -536,6 +718,14 @@ static int pm8916_wcd_analog_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, wcd_reg_defaults_2_0[reg].reg,
wcd_reg_defaults_2_0[reg].def);
+ priv->codec = codec;
+
+ snd_soc_update_bits(codec, CDC_D_CDC_RST_CTL,
+ RST_CTL_DIG_SW_RST_N_MASK,
+ RST_CTL_DIG_SW_RST_N_REMOVE_RESET);
+
+ pm8916_wcd_setup_mbhc(priv);
+
return 0;
}
@@ -543,6 +733,9 @@ static int pm8916_wcd_analog_remove(struct snd_soc_codec *codec)
{
struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(codec->dev);
+ snd_soc_update_bits(codec, CDC_D_CDC_RST_CTL,
+ RST_CTL_DIG_SW_RST_N_MASK, 0);
+
return regulator_bulk_disable(ARRAY_SIZE(priv->supplies),
priv->supplies);
}
@@ -731,32 +924,129 @@ static const struct snd_soc_dapm_widget pm8916_wcd_analog_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("A_MCLK2", CDC_D_CDC_TOP_CLK_CTL, 3, 0, NULL, 0),
};
+static int pm8916_wcd_analog_set_jack(struct snd_soc_codec *codec,
+ struct snd_soc_jack *jack,
+ void *data)
+{
+ struct pm8916_wcd_analog_priv *wcd = snd_soc_codec_get_drvdata(codec);
+
+ wcd->jack = jack;
+
+ return 0;
+}
+
static struct regmap *pm8916_get_regmap(struct device *dev)
{
return dev_get_regmap(dev->parent, NULL);
}
-static int pm8916_wcd_analog_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static irqreturn_t mbhc_btn_release_irq_handler(int irq, void *arg)
{
- snd_soc_update_bits(dai->codec, CDC_D_CDC_RST_CTL,
- RST_CTL_DIG_SW_RST_N_MASK,
- RST_CTL_DIG_SW_RST_N_REMOVE_RESET);
+ struct pm8916_wcd_analog_priv *priv = arg;
- return 0;
+ if (priv->detect_accessory_type) {
+ struct snd_soc_codec *codec = priv->codec;
+ u32 val = snd_soc_read(codec, CDC_A_MBHC_RESULT_1);
+
+ /* check if its BTN0 thats released */
+ if ((val != -1) && !(val & CDC_A_MBHC_RESULT_1_BTN_RESULT_MASK))
+ priv->mbhc_btn0_pressed = false;
+
+ } else {
+ snd_soc_jack_report(priv->jack, 0, btn_mask);
+ }
+
+ return IRQ_HANDLED;
}
-static void pm8916_wcd_analog_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static irqreturn_t mbhc_btn_press_irq_handler(int irq, void *arg)
{
- snd_soc_update_bits(dai->codec, CDC_D_CDC_RST_CTL,
- RST_CTL_DIG_SW_RST_N_MASK, 0);
+ struct pm8916_wcd_analog_priv *priv = arg;
+ struct snd_soc_codec *codec = priv->codec;
+ u32 btn_result;
+
+ btn_result = snd_soc_read(codec, CDC_A_MBHC_RESULT_1) &
+ CDC_A_MBHC_RESULT_1_BTN_RESULT_MASK;
+
+ switch (btn_result) {
+ case 0xf:
+ snd_soc_jack_report(priv->jack, SND_JACK_BTN_4, btn_mask);
+ break;
+ case 0x7:
+ snd_soc_jack_report(priv->jack, SND_JACK_BTN_3, btn_mask);
+ break;
+ case 0x3:
+ snd_soc_jack_report(priv->jack, SND_JACK_BTN_2, btn_mask);
+ break;
+ case 0x1:
+ snd_soc_jack_report(priv->jack, SND_JACK_BTN_1, btn_mask);
+ break;
+ case 0x0:
+ /* handle BTN_0 specially for type detection */
+ if (priv->detect_accessory_type)
+ priv->mbhc_btn0_pressed = true;
+ else
+ snd_soc_jack_report(priv->jack,
+ SND_JACK_BTN_0, btn_mask);
+ break;
+ default:
+ dev_err(codec->dev,
+ "Unexpected button press result (%x)", btn_result);
+ break;
+ }
+
+ return IRQ_HANDLED;
}
-static struct snd_soc_dai_ops pm8916_wcd_analog_dai_ops = {
- .startup = pm8916_wcd_analog_startup,
- .shutdown = pm8916_wcd_analog_shutdown,
-};
+
+static irqreturn_t pm8916_mbhc_switch_irq_handler(int irq, void *arg)
+{
+ struct pm8916_wcd_analog_priv *priv = arg;
+ struct snd_soc_codec *codec = priv->codec;
+ bool ins = false;
+
+ if (snd_soc_read(codec, CDC_A_MBHC_DET_CTL_1) &
+ CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_MASK)
+ ins = true;
+
+ /* Set the detection type appropriately */
+ snd_soc_update_bits(codec, CDC_A_MBHC_DET_CTL_1,
+ CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_MASK,
+ (!ins << CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_SHIFT));
+
+
+ if (ins) { /* hs insertion */
+ bool micbias_enabled = false;
+
+ if (snd_soc_read(codec, CDC_A_MICB_2_EN) &
+ CDC_A_MICB_2_EN_ENABLE)
+ micbias_enabled = true;
+
+ pm8916_mbhc_configure_bias(priv, micbias_enabled);
+
+ /*
+ * if only a btn0 press event is receive just before
+ * insert event then its a 3 pole headphone else if
+ * both press and release event received then its
+ * a headset.
+ */
+ if (priv->mbhc_btn0_pressed)
+ snd_soc_jack_report(priv->jack,
+ SND_JACK_HEADPHONE, hs_jack_mask);
+ else
+ snd_soc_jack_report(priv->jack,
+ SND_JACK_HEADSET, hs_jack_mask);
+
+ priv->detect_accessory_type = false;
+
+ } else { /* removal */
+ snd_soc_jack_report(priv->jack, 0, hs_jack_mask);
+ priv->detect_accessory_type = true;
+ priv->mbhc_btn0_pressed = false;
+ }
+
+ return IRQ_HANDLED;
+}
static struct snd_soc_dai_driver pm8916_wcd_analog_dai[] = {
[0] = {
@@ -769,7 +1059,6 @@ static struct snd_soc_dai_driver pm8916_wcd_analog_dai[] = {
.channels_min = 1,
.channels_max = 3,
},
- .ops = &pm8916_wcd_analog_dai_ops,
},
[1] = {
.name = "pm8916_wcd_analog_pdm_tx",
@@ -781,13 +1070,13 @@ static struct snd_soc_dai_driver pm8916_wcd_analog_dai[] = {
.channels_min = 1,
.channels_max = 4,
},
- .ops = &pm8916_wcd_analog_dai_ops,
},
};
-static struct snd_soc_codec_driver pm8916_wcd_analog = {
+static const struct snd_soc_codec_driver pm8916_wcd_analog = {
.probe = pm8916_wcd_analog_probe,
.remove = pm8916_wcd_analog_remove,
+ .set_jack = pm8916_wcd_analog_set_jack,
.get_regmap = pm8916_get_regmap,
.component_driver = {
.controls = pm8916_wcd_analog_snd_controls,
@@ -802,6 +1091,7 @@ static struct snd_soc_codec_driver pm8916_wcd_analog = {
static int pm8916_wcd_analog_parse_dt(struct device *dev,
struct pm8916_wcd_analog_priv *priv)
{
+ int rval;
if (of_property_read_bool(dev->of_node, "qcom,micbias1-ext-cap"))
priv->micbias1_cap_mode = MICB_1_EN_EXT_BYP_CAP;
@@ -813,6 +1103,42 @@ static int pm8916_wcd_analog_parse_dt(struct device *dev,
else
priv->micbias2_cap_mode = MICB_1_EN_NO_EXT_BYP_CAP;
+ of_property_read_u32(dev->of_node, "qcom,micbias-lvl",
+ &priv->micbias_mv);
+
+ if (of_property_read_bool(dev->of_node,
+ "qcom,hphl-jack-type-normally-open"))
+ priv->hphl_jack_type_normally_open = true;
+ else
+ priv->hphl_jack_type_normally_open = false;
+
+ if (of_property_read_bool(dev->of_node,
+ "qcom,gnd-jack-type-normally-open"))
+ priv->gnd_jack_type_normally_open = true;
+ else
+ priv->gnd_jack_type_normally_open = false;
+
+ priv->mbhc_btn_enabled = true;
+ rval = of_property_read_u32_array(dev->of_node,
+ "qcom,mbhc-vthreshold-low",
+ &priv->vref_btn_cs[0],
+ MBHC_MAX_BUTTONS);
+ if (rval < 0) {
+ priv->mbhc_btn_enabled = false;
+ } else {
+ rval = of_property_read_u32_array(dev->of_node,
+ "qcom,mbhc-vthreshold-high",
+ &priv->vref_btn_micb[0],
+ MBHC_MAX_BUTTONS);
+ if (rval < 0)
+ priv->mbhc_btn_enabled = false;
+ }
+
+ if (!priv->mbhc_btn_enabled)
+ dev_err(dev,
+ "DT property missing, MBHC btn detection disabled\n");
+
+
return 0;
}
@@ -820,7 +1146,7 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
{
struct pm8916_wcd_analog_priv *priv;
struct device *dev = &pdev->dev;
- int ret, i;
+ int ret, i, irq;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -852,6 +1178,48 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
return ret;
}
+ irq = platform_get_irq_byname(pdev, "mbhc_switch_int");
+ if (irq < 0) {
+ dev_err(dev, "failed to get mbhc switch irq\n");
+ return irq;
+ }
+
+ ret = devm_request_irq(dev, irq, pm8916_mbhc_switch_irq_handler,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ "mbhc switch irq", priv);
+ if (ret)
+ dev_err(dev, "cannot request mbhc switch irq\n");
+
+ if (priv->mbhc_btn_enabled) {
+ irq = platform_get_irq_byname(pdev, "mbhc_but_press_det");
+ if (irq < 0) {
+ dev_err(dev, "failed to get button press irq\n");
+ return irq;
+ }
+
+ ret = devm_request_irq(dev, irq, mbhc_btn_press_irq_handler,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "mbhc btn press irq", priv);
+ if (ret)
+ dev_err(dev, "cannot request mbhc button press irq\n");
+
+ irq = platform_get_irq_byname(pdev, "mbhc_but_rel_det");
+ if (irq < 0) {
+ dev_err(dev, "failed to get button release irq\n");
+ return irq;
+ }
+
+ ret = devm_request_irq(dev, irq, mbhc_btn_release_irq_handler,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "mbhc btn release irq", priv);
+ if (ret)
+ dev_err(dev, "cannot request mbhc button release irq\n");
+
+ }
+
dev_set_drvdata(dev, priv);
return snd_soc_register_codec(dev, &pm8916_wcd_analog,
diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c
index f690442af8c9..66df8f810f0d 100644
--- a/sound/soc/codecs/msm8916-wcd-digital.c
+++ b/sound/soc/codecs/msm8916-wcd-digital.c
@@ -218,6 +218,8 @@ static const char *const rx_mix1_text[] = {
static const char *const dec_mux_text[] = {
"ZERO", "ADC1", "ADC2", "ADC3", "DMIC1", "DMIC2"
};
+
+static const char *const cic_mux_text[] = { "AMIC", "DMIC" };
static const char *const rx_mix2_text[] = { "ZERO", "IIR1", "IIR2" };
static const char *const adc2_mux_text[] = { "ZERO", "INP2", "INP3" };
@@ -256,11 +258,21 @@ static const struct soc_enum dec1_mux_enum = SOC_ENUM_SINGLE(
static const struct soc_enum dec2_mux_enum = SOC_ENUM_SINGLE(
LPASS_CDC_CONN_TX_B1_CTL, 3, 6, dec_mux_text);
+/* CIC */
+static const struct soc_enum cic1_mux_enum = SOC_ENUM_SINGLE(
+ LPASS_CDC_TX1_MUX_CTL, 0, 2, cic_mux_text);
+static const struct soc_enum cic2_mux_enum = SOC_ENUM_SINGLE(
+ LPASS_CDC_TX2_MUX_CTL, 0, 2, cic_mux_text);
+
/* RDAC2 MUX */
static const struct snd_kcontrol_new dec1_mux = SOC_DAPM_ENUM(
"DEC1 MUX Mux", dec1_mux_enum);
static const struct snd_kcontrol_new dec2_mux = SOC_DAPM_ENUM(
"DEC2 MUX Mux", dec2_mux_enum);
+static const struct snd_kcontrol_new cic1_mux = SOC_DAPM_ENUM(
+ "CIC1 MUX Mux", cic1_mux_enum);
+static const struct snd_kcontrol_new cic2_mux = SOC_DAPM_ENUM(
+ "CIC2 MUX Mux", cic2_mux_enum);
static const struct snd_kcontrol_new rx_mix1_inp1_mux = SOC_DAPM_ENUM(
"RX1 MIX1 INP1 Mux", rx_mix1_inp_enum[0]);
static const struct snd_kcontrol_new rx_mix1_inp2_mux = SOC_DAPM_ENUM(
@@ -500,6 +512,8 @@ static const struct snd_soc_dapm_widget msm8916_wcd_digital_dapm_widgets[] = {
SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0,
&rx3_mix1_inp3_mux),
+ SND_SOC_DAPM_MUX("CIC1 MUX", SND_SOC_NOPM, 0, 0, &cic1_mux),
+ SND_SOC_DAPM_MUX("CIC2 MUX", SND_SOC_NOPM, 0, 0, &cic2_mux),
/* TX */
SND_SOC_DAPM_MIXER("ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -536,6 +550,8 @@ static const struct snd_soc_dapm_widget msm8916_wcd_digital_dapm_widgets[] = {
/* Connectivity Clock */
SND_SOC_DAPM_SUPPLY_S("CDC_CONN", -2, LPASS_CDC_CLK_OTHR_CTL, 2, 0,
NULL, 0),
+ SND_SOC_DAPM_MIC("Digital Mic1", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic2", NULL),
};
@@ -568,6 +584,15 @@ static int msm8916_wcd_digital_codec_probe(struct snd_soc_codec *codec)
return 0;
}
+static int msm8916_wcd_digital_codec_set_sysclk(struct snd_soc_codec *codec,
+ int clk_id, int source,
+ unsigned int freq, int dir)
+{
+ struct msm8916_wcd_digital_priv *p = dev_get_drvdata(codec->dev);
+
+ return clk_set_rate(p->mclk, freq);
+}
+
static int msm8916_wcd_digital_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -646,6 +671,11 @@ static const struct snd_soc_dapm_route msm8916_wcd_digital_audio_map[] = {
{"AIF1 Capture", NULL, "I2S TX2"},
{"AIF1 Capture", NULL, "I2S TX3"},
+ {"CIC1 MUX", "DMIC", "DEC1 MUX"},
+ {"CIC1 MUX", "AMIC", "DEC1 MUX"},
+ {"CIC2 MUX", "DMIC", "DEC2 MUX"},
+ {"CIC2 MUX", "AMIC", "DEC2 MUX"},
+
/* Decimator Inputs */
{"DEC1 MUX", "DMIC1", "DMIC1"},
{"DEC1 MUX", "DMIC2", "DMIC2"},
@@ -664,8 +694,8 @@ static const struct snd_soc_dapm_route msm8916_wcd_digital_audio_map[] = {
{"DMIC1", NULL, "DMIC_CLK"},
{"DMIC2", NULL, "DMIC_CLK"},
- {"I2S TX1", NULL, "DEC1 MUX"},
- {"I2S TX2", NULL, "DEC2 MUX"},
+ {"I2S TX1", NULL, "CIC1 MUX"},
+ {"I2S TX2", NULL, "CIC2 MUX"},
{"I2S TX1", NULL, "TX_I2S_CLK"},
{"I2S TX2", NULL, "TX_I2S_CLK"},
@@ -788,7 +818,7 @@ static void msm8916_wcd_digital_shutdown(struct snd_pcm_substream *substream,
LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_MASK, 0);
}
-static struct snd_soc_dai_ops msm8916_wcd_digital_dai_ops = {
+static const struct snd_soc_dai_ops msm8916_wcd_digital_dai_ops = {
.startup = msm8916_wcd_digital_startup,
.shutdown = msm8916_wcd_digital_shutdown,
.hw_params = msm8916_wcd_digital_hw_params,
@@ -821,8 +851,9 @@ static struct snd_soc_dai_driver msm8916_wcd_digital_dai[] = {
},
};
-static struct snd_soc_codec_driver msm8916_wcd_digital = {
+static const struct snd_soc_codec_driver msm8916_wcd_digital = {
.probe = msm8916_wcd_digital_codec_probe,
+ .set_sysclk = msm8916_wcd_digital_codec_set_sysclk,
.component_driver = {
.controls = msm8916_wcd_digital_snd_controls,
.num_controls = ARRAY_SIZE(msm8916_wcd_digital_snd_controls),
diff --git a/sound/soc/codecs/nau8540.c b/sound/soc/codecs/nau8540.c
index c8bcb1db966d..f9c9933acffb 100644
--- a/sound/soc/codecs/nau8540.c
+++ b/sound/soc/codecs/nau8540.c
@@ -735,7 +735,7 @@ static int __maybe_unused nau8540_resume(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver nau8540_codec_driver = {
+static const struct snd_soc_codec_driver nau8540_codec_driver = {
.set_sysclk = nau8540_set_sysclk,
.set_pll = nau8540_set_pll,
.suspend = nau8540_suspend,
diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c
index e45518629968..c8e2451ae0a3 100644
--- a/sound/soc/codecs/nau8810.c
+++ b/sound/soc/codecs/nau8810.c
@@ -808,7 +808,7 @@ static const struct regmap_config nau8810_regmap_config = {
.num_reg_defaults = ARRAY_SIZE(nau8810_reg_defaults),
};
-static struct snd_soc_codec_driver nau8810_codec_driver = {
+static const struct snd_soc_codec_driver nau8810_codec_driver = {
.set_bias_level = nau8810_set_bias_level,
.suspend_bias_off = true,
diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c
index 3a309b18035e..0240759f951c 100644
--- a/sound/soc/codecs/nau8824.c
+++ b/sound/soc/codecs/nau8824.c
@@ -1469,7 +1469,7 @@ static int __maybe_unused nau8824_resume(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver nau8824_codec_driver = {
+static const struct snd_soc_codec_driver nau8824_codec_driver = {
.probe = nau8824_codec_probe,
.set_sysclk = nau8824_set_sysclk,
.set_pll = nau8824_set_pll,
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c
index 46a30eaa7ace..000aa79314fa 100644
--- a/sound/soc/codecs/nau8825.c
+++ b/sound/soc/codecs/nau8825.c
@@ -2388,7 +2388,7 @@ static int __maybe_unused nau8825_resume(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver nau8825_codec_driver = {
+static const struct snd_soc_codec_driver nau8825_codec_driver = {
.probe = nau8825_codec_probe,
.remove = nau8825_codec_remove,
.set_sysclk = nau8825_set_sysclk,
diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c
index 0b14efab6280..c7e28dd2e815 100644
--- a/sound/soc/codecs/pcm1681.c
+++ b/sound/soc/codecs/pcm1681.c
@@ -288,7 +288,7 @@ static const struct regmap_config pcm1681_regmap = {
.readable_reg = pcm1681_accessible_reg,
};
-static struct snd_soc_codec_driver soc_codec_dev_pcm1681 = {
+static const struct snd_soc_codec_driver soc_codec_dev_pcm1681 = {
.component_driver = {
.controls = pcm1681_controls,
.num_controls = ARRAY_SIZE(pcm1681_controls),
diff --git a/sound/soc/codecs/pcm179x.c b/sound/soc/codecs/pcm179x.c
index b813a154ddd9..82a3d9db32cb 100644
--- a/sound/soc/codecs/pcm179x.c
+++ b/sound/soc/codecs/pcm179x.c
@@ -205,7 +205,7 @@ const struct regmap_config pcm179x_regmap_config = {
};
EXPORT_SYMBOL_GPL(pcm179x_regmap_config);
-static struct snd_soc_codec_driver soc_codec_dev_pcm179x = {
+static const struct snd_soc_codec_driver soc_codec_dev_pcm179x = {
.component_driver = {
.controls = pcm179x_controls,
.num_controls = ARRAY_SIZE(pcm179x_controls),
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
index 708af05486f6..e59d8ffb93bd 100644
--- a/sound/soc/codecs/pcm3008.c
+++ b/sound/soc/codecs/pcm3008.c
@@ -98,7 +98,7 @@ static struct snd_soc_dai_driver pcm3008_dai = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
+static const struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
.component_driver = {
.dapm_widgets = pcm3008_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(pcm3008_dapm_widgets),
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
index 72b19e62f626..f1005a31c709 100644
--- a/sound/soc/codecs/pcm512x.c
+++ b/sound/soc/codecs/pcm512x.c
@@ -1344,7 +1344,7 @@ static struct snd_soc_dai_driver pcm512x_dai = {
.ops = &pcm512x_dai_ops,
};
-static struct snd_soc_codec_driver pcm512x_codec_driver = {
+static const struct snd_soc_codec_driver pcm512x_codec_driver = {
.set_bias_level = pcm512x_set_bias_level,
.idle_bias_off = true,
diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c
new file mode 100644
index 000000000000..58cfe244f81e
--- /dev/null
+++ b/sound/soc/codecs/rt274.c
@@ -0,0 +1,1228 @@
+/*
+ * rt274.c -- RT274 ALSA SoC audio codec driver
+ *
+ * Copyright 2017 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 <linux/dmi.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 <sound/jack.h>
+#include <linux/workqueue.h>
+
+#include "rl6347a.h"
+#include "rt274.h"
+
+#define RT274_VENDOR_ID 0x10ec0274
+
+struct rt274_priv {
+ struct reg_default *index_cache;
+ int index_cache_size;
+ struct regmap *regmap;
+ struct snd_soc_codec *codec;
+ struct i2c_client *i2c;
+ struct snd_soc_jack *jack;
+ struct delayed_work jack_detect_work;
+ int sys_clk;
+ int clk_id;
+ int fs;
+ bool master;
+};
+
+static const struct reg_default rt274_index_def[] = {
+ { 0x00, 0x1004 },
+ { 0x01, 0xaaaa },
+ { 0x02, 0x88aa },
+ { 0x03, 0x0002 },
+ { 0x04, 0xaa09 },
+ { 0x05, 0x0700 },
+ { 0x06, 0x6110 },
+ { 0x07, 0x0200 },
+ { 0x08, 0xa807 },
+ { 0x09, 0x0021 },
+ { 0x0a, 0x7770 },
+ { 0x0b, 0x7770 },
+ { 0x0c, 0x002b },
+ { 0x0d, 0x2420 },
+ { 0x0e, 0x65c0 },
+ { 0x0f, 0x7770 },
+ { 0x10, 0x0420 },
+ { 0x11, 0x7418 },
+ { 0x12, 0x6bd0 },
+ { 0x13, 0x645f },
+ { 0x14, 0x0400 },
+ { 0x15, 0x8ccc },
+ { 0x16, 0x4c50 },
+ { 0x17, 0xff00 },
+ { 0x18, 0x0003 },
+ { 0x19, 0x2c11 },
+ { 0x1a, 0x830b },
+ { 0x1b, 0x4e4b },
+ { 0x1c, 0x0000 },
+ { 0x1d, 0x0000 },
+ { 0x1e, 0x0000 },
+ { 0x1f, 0x0000 },
+ { 0x20, 0x51ff },
+ { 0x21, 0x8000 },
+ { 0x22, 0x8f00 },
+ { 0x23, 0x88f4 },
+ { 0x24, 0x0000 },
+ { 0x25, 0x0000 },
+ { 0x26, 0x0000 },
+ { 0x27, 0x0000 },
+ { 0x28, 0x0000 },
+ { 0x29, 0x3000 },
+ { 0x2a, 0x0000 },
+ { 0x2b, 0x0000 },
+ { 0x2c, 0x0f00 },
+ { 0x2d, 0x100f },
+ { 0x2e, 0x2902 },
+ { 0x2f, 0xe280 },
+ { 0x30, 0x1000 },
+ { 0x31, 0x8400 },
+ { 0x32, 0x5aaa },
+ { 0x33, 0x8420 },
+ { 0x34, 0xa20c },
+ { 0x35, 0x096a },
+ { 0x36, 0x5757 },
+ { 0x37, 0xfe05 },
+ { 0x38, 0x4901 },
+ { 0x39, 0x110a },
+ { 0x3a, 0x0010 },
+ { 0x3b, 0x60d9 },
+ { 0x3c, 0xf214 },
+ { 0x3d, 0xc2ba },
+ { 0x3e, 0xa928 },
+ { 0x3f, 0x0000 },
+ { 0x40, 0x9800 },
+ { 0x41, 0x0000 },
+ { 0x42, 0x2000 },
+ { 0x43, 0x3d90 },
+ { 0x44, 0x4900 },
+ { 0x45, 0x5289 },
+ { 0x46, 0x0004 },
+ { 0x47, 0xa47a },
+ { 0x48, 0xd049 },
+ { 0x49, 0x0049 },
+ { 0x4a, 0xa83b },
+ { 0x4b, 0x0777 },
+ { 0x4c, 0x065c },
+ { 0x4d, 0x7fff },
+ { 0x4e, 0x7fff },
+ { 0x4f, 0x0000 },
+ { 0x50, 0x0000 },
+ { 0x51, 0x0000 },
+ { 0x52, 0xbf5f },
+ { 0x53, 0x3320 },
+ { 0x54, 0xcc00 },
+ { 0x55, 0x0000 },
+ { 0x56, 0x3f00 },
+ { 0x57, 0x0000 },
+ { 0x58, 0x0000 },
+ { 0x59, 0x0000 },
+ { 0x5a, 0x1300 },
+ { 0x5b, 0x005f },
+ { 0x5c, 0x0000 },
+ { 0x5d, 0x1001 },
+ { 0x5e, 0x1000 },
+ { 0x5f, 0x0000 },
+ { 0x60, 0x5554 },
+ { 0x61, 0xffc0 },
+ { 0x62, 0xa000 },
+ { 0x63, 0xd010 },
+ { 0x64, 0x0000 },
+ { 0x65, 0x3fb1 },
+ { 0x66, 0x1881 },
+ { 0x67, 0xc810 },
+ { 0x68, 0x2000 },
+ { 0x69, 0xfff0 },
+ { 0x6a, 0x0300 },
+ { 0x6b, 0x5060 },
+ { 0x6c, 0x0000 },
+ { 0x6d, 0x0000 },
+ { 0x6e, 0x0c25 },
+ { 0x6f, 0x0c0b },
+ { 0x70, 0x8000 },
+ { 0x71, 0x4008 },
+ { 0x72, 0x0000 },
+ { 0x73, 0x0800 },
+ { 0x74, 0xa28f },
+ { 0x75, 0xa050 },
+ { 0x76, 0x7fe8 },
+ { 0x77, 0xdb8c },
+ { 0x78, 0x0000 },
+ { 0x79, 0x0000 },
+ { 0x7a, 0x2a96 },
+ { 0x7b, 0x800f },
+ { 0x7c, 0x0200 },
+ { 0x7d, 0x1600 },
+ { 0x7e, 0x0000 },
+ { 0x7f, 0x0000 },
+};
+#define INDEX_CACHE_SIZE ARRAY_SIZE(rt274_index_def)
+
+static const struct reg_default rt274_reg[] = {
+ { 0x00170500, 0x00000400 },
+ { 0x00220000, 0x00000031 },
+ { 0x00239000, 0x00000057 },
+ { 0x0023a000, 0x00000057 },
+ { 0x00270500, 0x00000400 },
+ { 0x00370500, 0x00000400 },
+ { 0x00870500, 0x00000400 },
+ { 0x00920000, 0x00000031 },
+ { 0x00935000, 0x00000097 },
+ { 0x00936000, 0x00000097 },
+ { 0x00970500, 0x00000400 },
+ { 0x00b37000, 0x00000400 },
+ { 0x00b37200, 0x00000400 },
+ { 0x00b37300, 0x00000400 },
+ { 0x00c37000, 0x00000400 },
+ { 0x00c37100, 0x00000400 },
+ { 0x01270500, 0x00000400 },
+ { 0x01370500, 0x00000400 },
+ { 0x01371f00, 0x411111f0 },
+ { 0x01937000, 0x00000000 },
+ { 0x01970500, 0x00000400 },
+ { 0x02050000, 0x0000001b },
+ { 0x02139000, 0x00000080 },
+ { 0x0213a000, 0x00000080 },
+ { 0x02170100, 0x00000001 },
+ { 0x02170500, 0x00000400 },
+ { 0x02170700, 0x00000000 },
+ { 0x02270100, 0x00000000 },
+ { 0x02370100, 0x00000000 },
+ { 0x01970700, 0x00000020 },
+ { 0x00830000, 0x00000097 },
+ { 0x00930000, 0x00000097 },
+ { 0x01270700, 0x00000000 },
+};
+
+static bool rt274_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case 0 ... 0xff:
+ case RT274_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID):
+ case RT274_GET_HP_SENSE:
+ case RT274_GET_MIC_SENSE:
+ case RT274_PROC_COEF:
+ case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT274_MIC, 0):
+ case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT274_HP_OUT, 0):
+ case VERB_CMD(AC_VERB_GET_STREAM_FORMAT, RT274_DAC_OUT0, 0):
+ case VERB_CMD(AC_VERB_GET_STREAM_FORMAT, RT274_DAC_OUT1, 0):
+ case VERB_CMD(AC_VERB_GET_STREAM_FORMAT, RT274_ADC_IN1, 0):
+ case VERB_CMD(AC_VERB_GET_STREAM_FORMAT, RT274_ADC_IN2, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_DAC_OUT0, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_DAC_OUT1, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_ADC_IN1, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_ADC_IN2, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_DMIC1, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_DMIC2, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_MIC, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_LINE1, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_LINE2, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_HP_OUT, 0):
+ case VERB_CMD(AC_VERB_GET_CONNECT_SEL, RT274_HP_OUT, 0):
+ case VERB_CMD(AC_VERB_GET_CONNECT_SEL, RT274_MIXER_IN1, 0):
+ case VERB_CMD(AC_VERB_GET_CONNECT_SEL, RT274_MIXER_IN2, 0):
+ case VERB_CMD(AC_VERB_GET_PIN_WIDGET_CONTROL, RT274_DMIC1, 0):
+ case VERB_CMD(AC_VERB_GET_PIN_WIDGET_CONTROL, RT274_DMIC2, 0):
+ case VERB_CMD(AC_VERB_GET_PIN_WIDGET_CONTROL, RT274_MIC, 0):
+ case VERB_CMD(AC_VERB_GET_PIN_WIDGET_CONTROL, RT274_LINE1, 0):
+ case VERB_CMD(AC_VERB_GET_PIN_WIDGET_CONTROL, RT274_LINE2, 0):
+ case VERB_CMD(AC_VERB_GET_PIN_WIDGET_CONTROL, RT274_HP_OUT, 0):
+ case VERB_CMD(AC_VERB_GET_UNSOLICITED_RESPONSE, RT274_HP_OUT, 0):
+ case VERB_CMD(AC_VERB_GET_UNSOLICITED_RESPONSE, RT274_MIC, 0):
+ case VERB_CMD(AC_VERB_GET_UNSOLICITED_RESPONSE, RT274_INLINE_CMD, 0):
+ return true;
+ default:
+ return false;
+ }
+
+
+}
+
+static bool rt274_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case 0 ... 0xff:
+ case RT274_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID):
+ case RT274_GET_HP_SENSE:
+ case RT274_GET_MIC_SENSE:
+ case RT274_SET_AUDIO_POWER:
+ case RT274_SET_HPO_POWER:
+ case RT274_SET_DMIC1_POWER:
+ case RT274_LOUT_MUX:
+ case RT274_HPO_MUX:
+ case RT274_ADC0_MUX:
+ case RT274_ADC1_MUX:
+ case RT274_SET_MIC:
+ case RT274_SET_PIN_HPO:
+ case RT274_SET_PIN_LOUT3:
+ case RT274_SET_PIN_DMIC1:
+ case RT274_SET_AMP_GAIN_HPO:
+ case RT274_SET_DMIC2_DEFAULT:
+ case RT274_DAC0L_GAIN:
+ case RT274_DAC0R_GAIN:
+ case RT274_DAC1L_GAIN:
+ case RT274_DAC1R_GAIN:
+ case RT274_ADCL_GAIN:
+ case RT274_ADCR_GAIN:
+ case RT274_MIC_GAIN:
+ case RT274_HPOL_GAIN:
+ case RT274_HPOR_GAIN:
+ case RT274_LOUTL_GAIN:
+ case RT274_LOUTR_GAIN:
+ case RT274_DAC_FORMAT:
+ case RT274_ADC_FORMAT:
+ case RT274_COEF_INDEX:
+ case RT274_PROC_COEF:
+ case RT274_SET_AMP_GAIN_ADC_IN1:
+ case RT274_SET_AMP_GAIN_ADC_IN2:
+ case RT274_SET_POWER(RT274_DAC_OUT0):
+ case RT274_SET_POWER(RT274_DAC_OUT1):
+ case RT274_SET_POWER(RT274_ADC_IN1):
+ case RT274_SET_POWER(RT274_ADC_IN2):
+ case RT274_SET_POWER(RT274_DMIC2):
+ case RT274_SET_POWER(RT274_MIC):
+ case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT274_MIC, 0):
+ case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT274_HP_OUT, 0):
+ case VERB_CMD(AC_VERB_GET_STREAM_FORMAT, RT274_DAC_OUT0, 0):
+ case VERB_CMD(AC_VERB_GET_STREAM_FORMAT, RT274_DAC_OUT1, 0):
+ case VERB_CMD(AC_VERB_GET_STREAM_FORMAT, RT274_ADC_IN1, 0):
+ case VERB_CMD(AC_VERB_GET_STREAM_FORMAT, RT274_ADC_IN2, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_DAC_OUT0, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_DAC_OUT1, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_ADC_IN1, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_ADC_IN2, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_DMIC1, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_DMIC2, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_MIC, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_LINE1, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_LINE2, 0):
+ case VERB_CMD(AC_VERB_GET_AMP_GAIN_MUTE, RT274_HP_OUT, 0):
+ case VERB_CMD(AC_VERB_GET_CONNECT_SEL, RT274_HP_OUT, 0):
+ case VERB_CMD(AC_VERB_GET_CONNECT_SEL, RT274_MIXER_IN1, 0):
+ case VERB_CMD(AC_VERB_GET_CONNECT_SEL, RT274_MIXER_IN2, 0):
+ case VERB_CMD(AC_VERB_GET_PIN_WIDGET_CONTROL, RT274_DMIC1, 0):
+ case VERB_CMD(AC_VERB_GET_PIN_WIDGET_CONTROL, RT274_DMIC2, 0):
+ case VERB_CMD(AC_VERB_GET_PIN_WIDGET_CONTROL, RT274_MIC, 0):
+ case VERB_CMD(AC_VERB_GET_PIN_WIDGET_CONTROL, RT274_LINE1, 0):
+ case VERB_CMD(AC_VERB_GET_PIN_WIDGET_CONTROL, RT274_LINE2, 0):
+ case VERB_CMD(AC_VERB_GET_PIN_WIDGET_CONTROL, RT274_HP_OUT, 0):
+ case VERB_CMD(AC_VERB_GET_UNSOLICITED_RESPONSE, RT274_HP_OUT, 0):
+ case VERB_CMD(AC_VERB_GET_UNSOLICITED_RESPONSE, RT274_MIC, 0):
+ case VERB_CMD(AC_VERB_GET_UNSOLICITED_RESPONSE, RT274_INLINE_CMD, 0):
+ return true;
+ default:
+ return false;
+ }
+}
+
+#ifdef CONFIG_PM
+static void rt274_index_sync(struct snd_soc_codec *codec)
+{
+ struct rt274_priv *rt274 = snd_soc_codec_get_drvdata(codec);
+ int i;
+
+ for (i = 0; i < INDEX_CACHE_SIZE; i++) {
+ snd_soc_write(codec, rt274->index_cache[i].reg,
+ rt274->index_cache[i].def);
+ }
+}
+#endif
+
+static int rt274_jack_detect(struct rt274_priv *rt274, bool *hp, bool *mic)
+{
+ unsigned int buf;
+
+ *hp = false;
+ *mic = false;
+
+ if (!rt274->codec)
+ return -EINVAL;
+
+ regmap_read(rt274->regmap, RT274_GET_HP_SENSE, &buf);
+ *hp = buf & 0x80000000;
+ regmap_read(rt274->regmap, RT274_GET_MIC_SENSE, &buf);
+ *mic = buf & 0x80000000;
+
+ pr_debug("*hp = %d *mic = %d\n", *hp, *mic);
+
+ return 0;
+}
+
+static void rt274_jack_detect_work(struct work_struct *work)
+{
+ struct rt274_priv *rt274 =
+ container_of(work, struct rt274_priv, jack_detect_work.work);
+ int status = 0;
+ bool hp = false;
+ bool mic = false;
+
+ if (rt274_jack_detect(rt274, &hp, &mic) < 0)
+ return;
+
+ if (hp == true)
+ status |= SND_JACK_HEADPHONE;
+
+ if (mic == true)
+ status |= SND_JACK_MICROPHONE;
+
+ snd_soc_jack_report(rt274->jack, status,
+ SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
+}
+
+static irqreturn_t rt274_irq(int irq, void *data);
+
+static int rt274_mic_detect(struct snd_soc_codec *codec,
+ struct snd_soc_jack *jack, void *data)
+{
+ struct rt274_priv *rt274 = snd_soc_codec_get_drvdata(codec);
+
+ if (jack == NULL) {
+ /* Disable jack detection */
+ regmap_update_bits(rt274->regmap, RT274_EAPD_GPIO_IRQ_CTRL,
+ RT274_IRQ_EN, RT274_IRQ_DIS);
+
+ return 0;
+ }
+ rt274->jack = jack;
+
+ regmap_update_bits(rt274->regmap, RT274_EAPD_GPIO_IRQ_CTRL,
+ RT274_IRQ_EN, RT274_IRQ_EN);
+
+ /* Send an initial report */
+ rt274_irq(0, rt274);
+
+ return 0;
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0);
+static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
+
+static const struct snd_kcontrol_new rt274_snd_controls[] = {
+ SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT274_DAC0L_GAIN,
+ RT274_DAC0R_GAIN, 0, 0x7f, 0, out_vol_tlv),
+ SOC_DOUBLE_R_TLV("DAC1 Playback Volume", RT274_DAC1L_GAIN,
+ RT274_DAC1R_GAIN, 0, 0x7f, 0, out_vol_tlv),
+ SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT274_ADCL_GAIN,
+ RT274_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv),
+ SOC_DOUBLE_R("ADC0 Capture Switch", RT274_ADCL_GAIN,
+ RT274_ADCR_GAIN, RT274_MUTE_SFT, 1, 1),
+ SOC_SINGLE_TLV("AMIC Volume", RT274_MIC_GAIN,
+ 0, 0x3, 0, mic_vol_tlv),
+};
+
+static const struct snd_kcontrol_new hpol_enable_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT274_HPOL_GAIN,
+ RT274_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hpor_enable_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT274_HPOR_GAIN,
+ RT274_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new loutl_enable_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT274_LOUTL_GAIN,
+ RT274_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new loutr_enable_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT274_LOUTR_GAIN,
+ RT274_MUTE_SFT, 1, 1);
+
+/* ADC0 source */
+static const char * const rt274_adc_src[] = {
+ "Mic", "Line1", "Line2", "Dmic"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt274_adc0_enum, RT274_ADC0_MUX, RT274_ADC_SEL_SFT,
+ rt274_adc_src);
+
+static const struct snd_kcontrol_new rt274_adc0_mux =
+ SOC_DAPM_ENUM("ADC 0 source", rt274_adc0_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+ rt274_adc1_enum, RT274_ADC1_MUX, RT274_ADC_SEL_SFT,
+ rt274_adc_src);
+
+static const struct snd_kcontrol_new rt274_adc1_mux =
+ SOC_DAPM_ENUM("ADC 1 source", rt274_adc1_enum);
+
+static const char * const rt274_dac_src[] = {
+ "DAC OUT0", "DAC OUT1"
+};
+/* HP-OUT source */
+static SOC_ENUM_SINGLE_DECL(rt274_hpo_enum, RT274_HPO_MUX,
+ 0, rt274_dac_src);
+
+static const struct snd_kcontrol_new rt274_hpo_mux =
+SOC_DAPM_ENUM("HPO source", rt274_hpo_enum);
+
+/* Line out source */
+static SOC_ENUM_SINGLE_DECL(rt274_lout_enum, RT274_LOUT_MUX,
+ 0, rt274_dac_src);
+
+static const struct snd_kcontrol_new rt274_lout_mux =
+SOC_DAPM_ENUM("LOUT source", rt274_lout_enum);
+
+static const struct snd_soc_dapm_widget rt274_dapm_widgets[] = {
+ /* Input Lines */
+ SND_SOC_DAPM_INPUT("DMIC1 Pin"),
+ SND_SOC_DAPM_INPUT("DMIC2 Pin"),
+ SND_SOC_DAPM_INPUT("MIC"),
+ SND_SOC_DAPM_INPUT("LINE1"),
+ SND_SOC_DAPM_INPUT("LINE2"),
+
+ /* DMIC */
+ SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* ADCs */
+ SND_SOC_DAPM_ADC("ADC 0", NULL, RT274_SET_STREAMID_ADC1, 4, 0),
+ SND_SOC_DAPM_ADC("ADC 1", NULL, RT274_SET_STREAMID_ADC2, 4, 0),
+
+ /* ADC Mux */
+ SND_SOC_DAPM_MUX("ADC 0 Mux", SND_SOC_NOPM, 0, 0,
+ &rt274_adc0_mux),
+ SND_SOC_DAPM_MUX("ADC 1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt274_adc1_mux),
+
+ /* Audio Interface */
+ SND_SOC_DAPM_AIF_IN("AIF1RXL", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF1RXR", "AIF1 Playback", 1, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF1TXL", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF1TXR", "AIF1 Capture", 1, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF2RXL", "AIF1 Playback", 2, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF2RXR", "AIF1 Playback", 3, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF2TXL", "AIF1 Capture", 2, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF2TXR", "AIF1 Capture", 3, SND_SOC_NOPM, 0, 0),
+
+ /* Output Side */
+ /* DACs */
+ SND_SOC_DAPM_DAC("DAC 0", NULL, RT274_SET_STREAMID_DAC0, 4, 0),
+ SND_SOC_DAPM_DAC("DAC 1", NULL, RT274_SET_STREAMID_DAC1, 4, 0),
+
+ /* Output Mux */
+ SND_SOC_DAPM_MUX("HPO Mux", SND_SOC_NOPM, 0, 0, &rt274_hpo_mux),
+ SND_SOC_DAPM_MUX("LOUT Mux", SND_SOC_NOPM, 0, 0, &rt274_lout_mux),
+
+ SND_SOC_DAPM_SUPPLY("HP Power", RT274_SET_PIN_HPO,
+ RT274_SET_PIN_SFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("LOUT Power", RT274_SET_PIN_LOUT3,
+ RT274_SET_PIN_SFT, 0, NULL, 0),
+
+ /* Output Mixer */
+ SND_SOC_DAPM_PGA("DAC OUT0", SND_SOC_NOPM, 0, 0,
+ NULL, 0),
+ SND_SOC_DAPM_PGA("DAC OUT1", SND_SOC_NOPM, 0, 0,
+ NULL, 0),
+
+ /* Output Pga */
+ SND_SOC_DAPM_SWITCH("LOUT L", SND_SOC_NOPM, 0, 0,
+ &loutl_enable_control),
+ SND_SOC_DAPM_SWITCH("LOUT R", SND_SOC_NOPM, 0, 0,
+ &loutr_enable_control),
+ SND_SOC_DAPM_SWITCH("HPO L", SND_SOC_NOPM, 0, 0,
+ &hpol_enable_control),
+ SND_SOC_DAPM_SWITCH("HPO R", SND_SOC_NOPM, 0, 0,
+ &hpor_enable_control),
+
+ /* Output Lines */
+ SND_SOC_DAPM_OUTPUT("HPO Pin"),
+ SND_SOC_DAPM_OUTPUT("SPDIF"),
+ SND_SOC_DAPM_OUTPUT("LINE3"),
+};
+
+static const struct snd_soc_dapm_route rt274_dapm_routes[] = {
+ {"DMIC1", NULL, "DMIC1 Pin"},
+ {"DMIC2", NULL, "DMIC2 Pin"},
+
+ {"ADC 0 Mux", "Mic", "MIC"},
+ {"ADC 0 Mux", "Dmic", "DMIC1"},
+ {"ADC 0 Mux", "Line1", "LINE1"},
+ {"ADC 0 Mux", "Line2", "LINE2"},
+ {"ADC 1 Mux", "Mic", "MIC"},
+ {"ADC 1 Mux", "Dmic", "DMIC2"},
+ {"ADC 1 Mux", "Line1", "LINE1"},
+ {"ADC 1 Mux", "Line2", "LINE2"},
+
+ {"ADC 0", NULL, "ADC 0 Mux"},
+ {"ADC 1", NULL, "ADC 1 Mux"},
+
+ {"AIF1TXL", NULL, "ADC 0"},
+ {"AIF1TXR", NULL, "ADC 0"},
+ {"AIF2TXL", NULL, "ADC 1"},
+ {"AIF2TXR", NULL, "ADC 1"},
+
+ {"DAC 0", NULL, "AIF1RXL"},
+ {"DAC 0", NULL, "AIF1RXR"},
+ {"DAC 1", NULL, "AIF2RXL"},
+ {"DAC 1", NULL, "AIF2RXR"},
+
+ {"DAC OUT0", NULL, "DAC 0"},
+
+ {"DAC OUT1", NULL, "DAC 1"},
+
+ {"LOUT Mux", "DAC OUT0", "DAC OUT0"},
+ {"LOUT Mux", "DAC OUT1", "DAC OUT1"},
+
+ {"LOUT L", "Switch", "LOUT Mux"},
+ {"LOUT R", "Switch", "LOUT Mux"},
+ {"LOUT L", NULL, "LOUT Power"},
+ {"LOUT R", NULL, "LOUT Power"},
+
+ {"LINE3", NULL, "LOUT L"},
+ {"LINE3", NULL, "LOUT R"},
+
+ {"HPO Mux", "DAC OUT0", "DAC OUT0"},
+ {"HPO Mux", "DAC OUT1", "DAC OUT1"},
+
+ {"HPO L", "Switch", "HPO Mux"},
+ {"HPO R", "Switch", "HPO Mux"},
+ {"HPO L", NULL, "HP Power"},
+ {"HPO R", NULL, "HP Power"},
+
+ {"HPO Pin", NULL, "HPO L"},
+ {"HPO Pin", NULL, "HPO R"},
+};
+
+static int rt274_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 rt274_priv *rt274 = snd_soc_codec_get_drvdata(codec);
+ unsigned int val = 0;
+ int d_len_code = 0, c_len_code = 0;
+
+ switch (params_rate(params)) {
+ /* bit 14 0:48K 1:44.1K */
+ case 44100:
+ case 48000:
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported sample rate %d\n",
+ params_rate(params));
+ return -EINVAL;
+ }
+ switch (rt274->sys_clk) {
+ case 12288000:
+ case 24576000:
+ if (params_rate(params) != 48000) {
+ dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n",
+ params_rate(params), rt274->sys_clk);
+ return -EINVAL;
+ }
+ break;
+ case 11289600:
+ case 22579200:
+ if (params_rate(params) != 44100) {
+ dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n",
+ params_rate(params), rt274->sys_clk);
+ return -EINVAL;
+ }
+ break;
+ }
+
+ if (params_channels(params) <= 16) {
+ /* bit 3:0 Number of Channel */
+ val |= (params_channels(params) - 1);
+ } else {
+ dev_err(codec->dev, "Unsupported channels %d\n",
+ params_channels(params));
+ return -EINVAL;
+ }
+
+ switch (params_width(params)) {
+ /* bit 6:4 Bits per Sample */
+ case 16:
+ d_len_code = 0;
+ c_len_code = 0;
+ val |= (0x1 << 4);
+ break;
+ case 32:
+ d_len_code = 2;
+ c_len_code = 3;
+ val |= (0x4 << 4);
+ break;
+ case 20:
+ d_len_code = 1;
+ c_len_code = 1;
+ val |= (0x2 << 4);
+ break;
+ case 24:
+ d_len_code = 2;
+ c_len_code = 2;
+ val |= (0x3 << 4);
+ break;
+ case 8:
+ d_len_code = 3;
+ c_len_code = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (rt274->master)
+ c_len_code = 0x3;
+
+ snd_soc_update_bits(codec,
+ RT274_I2S_CTRL1, 0xc018, d_len_code << 3 | c_len_code << 14);
+ dev_dbg(codec->dev, "format val = 0x%x\n", val);
+
+ snd_soc_update_bits(codec, RT274_DAC_FORMAT, 0x407f, val);
+ snd_soc_update_bits(codec, RT274_ADC_FORMAT, 0x407f, val);
+
+ return 0;
+}
+
+static int rt274_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt274_priv *rt274 = snd_soc_codec_get_drvdata(codec);
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ snd_soc_update_bits(codec,
+ RT274_I2S_CTRL1, RT274_I2S_MODE_MASK, RT274_I2S_MODE_M);
+ rt274->master = true;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ snd_soc_update_bits(codec,
+ RT274_I2S_CTRL1, RT274_I2S_MODE_MASK, RT274_I2S_MODE_S);
+ rt274->master = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ snd_soc_update_bits(codec, RT274_I2S_CTRL1,
+ RT274_I2S_FMT_MASK, RT274_I2S_FMT_I2S);
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ snd_soc_update_bits(codec, RT274_I2S_CTRL1,
+ RT274_I2S_FMT_MASK, RT274_I2S_FMT_LJ);
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ snd_soc_update_bits(codec, RT274_I2S_CTRL1,
+ RT274_I2S_FMT_MASK, RT274_I2S_FMT_PCMA);
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ snd_soc_update_bits(codec, RT274_I2S_CTRL1,
+ RT274_I2S_FMT_MASK, RT274_I2S_FMT_PCMB);
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* bit 15 Stream Type 0:PCM 1:Non-PCM */
+ snd_soc_update_bits(codec, RT274_DAC_FORMAT, 0x8000, 0);
+ snd_soc_update_bits(codec, RT274_ADC_FORMAT, 0x8000, 0);
+
+ return 0;
+}
+
+static int rt274_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 rt274_priv *rt274 = snd_soc_codec_get_drvdata(codec);
+
+ switch (source) {
+ case RT274_PLL2_S_MCLK:
+ snd_soc_update_bits(codec, RT274_PLL2_CTRL,
+ RT274_PLL2_SRC_MASK, RT274_PLL2_SRC_MCLK);
+ break;
+ default:
+ dev_warn(codec->dev, "invalid pll source, use BCLK\n");
+ case RT274_PLL2_S_BCLK:
+ snd_soc_update_bits(codec, RT274_PLL2_CTRL,
+ RT274_PLL2_SRC_MASK, RT274_PLL2_SRC_BCLK);
+ break;
+ }
+
+ if (source == RT274_PLL2_S_BCLK) {
+ snd_soc_update_bits(codec, RT274_MCLK_CTRL,
+ (0x3 << 12), (0x3 << 12));
+ switch (rt274->fs) {
+ case 50:
+ snd_soc_write(codec, 0x7a, 0xaab6);
+ snd_soc_write(codec, 0x7b, 0x0301);
+ snd_soc_write(codec, 0x7c, 0x04fe);
+ break;
+ case 64:
+ snd_soc_write(codec, 0x7a, 0xaa96);
+ snd_soc_write(codec, 0x7b, 0x8003);
+ snd_soc_write(codec, 0x7c, 0x081e);
+ break;
+ case 128:
+ snd_soc_write(codec, 0x7a, 0xaa96);
+ snd_soc_write(codec, 0x7b, 0x8003);
+ snd_soc_write(codec, 0x7c, 0x080e);
+ break;
+ default:
+ dev_warn(codec->dev, "invalid freq_in, assume 4.8M\n");
+ case 100:
+ snd_soc_write(codec, 0x7a, 0xaab6);
+ snd_soc_write(codec, 0x7b, 0x0301);
+ snd_soc_write(codec, 0x7c, 0x047e);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int rt274_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt274_priv *rt274 = snd_soc_codec_get_drvdata(codec);
+ unsigned int clk_src, mclk_en;
+
+ dev_dbg(codec->dev, "%s freq=%d\n", __func__, freq);
+
+ switch (clk_id) {
+ case RT274_SCLK_S_MCLK:
+ mclk_en = RT274_MCLK_MODE_EN;
+ clk_src = RT274_CLK_SRC_MCLK;
+ break;
+ case RT274_SCLK_S_PLL1:
+ mclk_en = RT274_MCLK_MODE_DIS;
+ clk_src = RT274_CLK_SRC_MCLK;
+ break;
+ case RT274_SCLK_S_PLL2:
+ mclk_en = RT274_MCLK_MODE_EN;
+ clk_src = RT274_CLK_SRC_PLL2;
+ break;
+ default:
+ mclk_en = RT274_MCLK_MODE_DIS;
+ clk_src = RT274_CLK_SRC_MCLK;
+ dev_warn(codec->dev, "invalid sysclk source, use PLL1\n");
+ break;
+ }
+ snd_soc_update_bits(codec, RT274_MCLK_CTRL,
+ RT274_MCLK_MODE_MASK, mclk_en);
+ snd_soc_update_bits(codec, RT274_CLK_CTRL,
+ RT274_CLK_SRC_MASK, clk_src);
+
+ switch (freq) {
+ case 19200000:
+ if (clk_id == RT274_SCLK_S_MCLK) {
+ dev_err(codec->dev, "Should not use MCLK\n");
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec,
+ RT274_I2S_CTRL2, 0x40, 0x40);
+ break;
+ case 24000000:
+ if (clk_id == RT274_SCLK_S_MCLK) {
+ dev_err(codec->dev, "Should not use MCLK\n");
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec,
+ RT274_I2S_CTRL2, 0x40, 0x0);
+ break;
+ case 12288000:
+ case 11289600:
+ snd_soc_update_bits(codec,
+ RT274_MCLK_CTRL, 0x1fcf, 0x0008);
+ break;
+ case 24576000:
+ case 22579200:
+ snd_soc_update_bits(codec,
+ RT274_MCLK_CTRL, 0x1fcf, 0x1543);
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported system clock\n");
+ return -EINVAL;
+ }
+
+ rt274->sys_clk = freq;
+ rt274->clk_id = clk_id;
+
+ return 0;
+}
+
+static int rt274_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt274_priv *rt274 = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "%s ratio=%d\n", __func__, ratio);
+ rt274->fs = ratio;
+ if ((ratio / 50) == 0)
+ snd_soc_update_bits(codec,
+ RT274_I2S_CTRL1, 0x1000, 0x1000);
+ else
+ snd_soc_update_bits(codec,
+ RT274_I2S_CTRL1, 0x1000, 0x0);
+
+
+ return 0;
+}
+
+static int rt274_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;
+
+ if (rx_mask || tx_mask) {
+ snd_soc_update_bits(codec,
+ RT274_I2S_CTRL1, RT274_TDM_EN, RT274_TDM_EN);
+ } else {
+ snd_soc_update_bits(codec,
+ RT274_I2S_CTRL1, RT274_TDM_EN, RT274_TDM_DIS);
+ return 0;
+ }
+
+ switch (slots) {
+ case 4:
+ snd_soc_update_bits(codec,
+ RT274_I2S_CTRL1, RT274_TDM_CH_NUM, RT274_TDM_4CH);
+ break;
+ case 2:
+ snd_soc_update_bits(codec,
+ RT274_I2S_CTRL1, RT274_TDM_CH_NUM, RT274_TDM_2CH);
+ break;
+ default:
+ dev_err(codec->dev,
+ "Support 2 or 4 slots TDM only\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rt274_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 ==
+ snd_soc_codec_get_bias_level(codec)) {
+ snd_soc_write(codec,
+ RT274_SET_AUDIO_POWER, AC_PWRST_D0);
+ }
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ snd_soc_write(codec,
+ RT274_SET_AUDIO_POWER, AC_PWRST_D3);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static irqreturn_t rt274_irq(int irq, void *data)
+{
+ struct rt274_priv *rt274 = data;
+ bool hp = false;
+ bool mic = false;
+ int ret, status = 0;
+
+ /* Clear IRQ */
+ regmap_update_bits(rt274->regmap, RT274_EAPD_GPIO_IRQ_CTRL,
+ RT274_IRQ_CLR, RT274_IRQ_CLR);
+
+ ret = rt274_jack_detect(rt274, &hp, &mic);
+
+ if (ret == 0) {
+ if (hp == true)
+ status |= SND_JACK_HEADPHONE;
+
+ if (mic == true)
+ status |= SND_JACK_MICROPHONE;
+
+ snd_soc_jack_report(rt274->jack, status,
+ SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
+
+ pm_wakeup_event(&rt274->i2c->dev, 300);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int rt274_probe(struct snd_soc_codec *codec)
+{
+ struct rt274_priv *rt274 = snd_soc_codec_get_drvdata(codec);
+
+ rt274->codec = codec;
+
+ if (rt274->i2c->irq) {
+ INIT_DELAYED_WORK(&rt274->jack_detect_work,
+ rt274_jack_detect_work);
+ schedule_delayed_work(&rt274->jack_detect_work,
+ msecs_to_jiffies(1250));
+ }
+
+ return 0;
+}
+
+static int rt274_remove(struct snd_soc_codec *codec)
+{
+ struct rt274_priv *rt274 = snd_soc_codec_get_drvdata(codec);
+
+ cancel_delayed_work_sync(&rt274->jack_detect_work);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt274_suspend(struct snd_soc_codec *codec)
+{
+ struct rt274_priv *rt274 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_cache_only(rt274->regmap, true);
+ regcache_mark_dirty(rt274->regmap);
+
+ return 0;
+}
+
+static int rt274_resume(struct snd_soc_codec *codec)
+{
+ struct rt274_priv *rt274 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_cache_only(rt274->regmap, false);
+ rt274_index_sync(codec);
+ regcache_sync(rt274->regmap);
+
+ return 0;
+}
+#else
+#define rt274_suspend NULL
+#define rt274_resume NULL
+#endif
+
+#define RT274_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+#define RT274_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 rt274_aif_dai_ops = {
+ .hw_params = rt274_hw_params,
+ .set_fmt = rt274_set_dai_fmt,
+ .set_sysclk = rt274_set_dai_sysclk,
+ .set_pll = rt274_set_dai_pll,
+ .set_bclk_ratio = rt274_set_bclk_ratio,
+ .set_tdm_slot = rt274_set_tdm_slot,
+};
+
+static struct snd_soc_dai_driver rt274_dai[] = {
+ {
+ .name = "rt274-aif1",
+ .id = RT274_AIF1,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT274_STEREO_RATES,
+ .formats = RT274_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT274_STEREO_RATES,
+ .formats = RT274_FORMATS,
+ },
+ .ops = &rt274_aif_dai_ops,
+ .symmetric_rates = 1,
+ },
+};
+
+static const struct snd_soc_codec_driver soc_codec_dev_rt274 = {
+ .probe = rt274_probe,
+ .remove = rt274_remove,
+ .suspend = rt274_suspend,
+ .resume = rt274_resume,
+ .set_bias_level = rt274_set_bias_level,
+ .idle_bias_off = true,
+ .component_driver = {
+ .controls = rt274_snd_controls,
+ .num_controls = ARRAY_SIZE(rt274_snd_controls),
+ .dapm_widgets = rt274_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(rt274_dapm_widgets),
+ .dapm_routes = rt274_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(rt274_dapm_routes),
+ },
+ .set_jack = rt274_mic_detect,
+};
+
+static const struct regmap_config rt274_regmap = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .max_register = 0x05bfffff,
+ .volatile_reg = rt274_volatile_register,
+ .readable_reg = rt274_readable_register,
+ .reg_write = rl6347a_hw_write,
+ .reg_read = rl6347a_hw_read,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = rt274_reg,
+ .num_reg_defaults = ARRAY_SIZE(rt274_reg),
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id rt274_of_match[] = {
+ {.compatible = "realtek,rt274"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, rt274_of_match);
+#endif
+
+static const struct i2c_device_id rt274_i2c_id[] = {
+ {"rt274", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, rt274_i2c_id);
+
+static const struct acpi_device_id rt274_acpi_match[] = {
+ { "10EC0274", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, rt274_acpi_match);
+
+static int rt274_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct rt274_priv *rt274;
+
+ int ret;
+ unsigned int val;
+
+ rt274 = devm_kzalloc(&i2c->dev, sizeof(*rt274),
+ GFP_KERNEL);
+ if (rt274 == NULL)
+ return -ENOMEM;
+
+ rt274->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt274_regmap);
+ if (IS_ERR(rt274->regmap)) {
+ ret = PTR_ERR(rt274->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ regmap_read(rt274->regmap,
+ RT274_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val);
+ if (val != RT274_VENDOR_ID) {
+ dev_err(&i2c->dev,
+ "Device with ID register %#x is not rt274\n", val);
+ return -ENODEV;
+ }
+
+ rt274->index_cache = devm_kmemdup(&i2c->dev, rt274_index_def,
+ sizeof(rt274_index_def), GFP_KERNEL);
+ if (!rt274->index_cache)
+ return -ENOMEM;
+
+ rt274->index_cache_size = INDEX_CACHE_SIZE;
+ rt274->i2c = i2c;
+ i2c_set_clientdata(i2c, rt274);
+
+ /* reset codec */
+ regmap_write(rt274->regmap, RT274_RESET, 0);
+ regmap_update_bits(rt274->regmap, 0x1a, 0x4000, 0x4000);
+
+ /* Set Pad PDB is floating */
+ regmap_update_bits(rt274->regmap, RT274_PAD_CTRL12, 0x3, 0x0);
+ regmap_write(rt274->regmap, RT274_COEF5b_INDEX, 0x01);
+ regmap_write(rt274->regmap, RT274_COEF5b_COEF, 0x8540);
+ regmap_update_bits(rt274->regmap, 0x6f, 0x0100, 0x0100);
+ /* Combo jack auto detect */
+ regmap_write(rt274->regmap, 0x4a, 0x201b);
+ /* Aux mode off */
+ regmap_update_bits(rt274->regmap, 0x6f, 0x3000, 0x2000);
+ /* HP DC Calibration */
+ regmap_update_bits(rt274->regmap, 0x6f, 0xf, 0x0);
+ /* Set NID=58h.Index 00h [15]= 1b; */
+ regmap_write(rt274->regmap, RT274_COEF58_INDEX, 0x00);
+ regmap_write(rt274->regmap, RT274_COEF58_COEF, 0xb888);
+ msleep(500);
+ regmap_update_bits(rt274->regmap, 0x6f, 0xf, 0xb);
+ regmap_write(rt274->regmap, RT274_COEF58_INDEX, 0x00);
+ regmap_write(rt274->regmap, RT274_COEF58_COEF, 0x3888);
+ /* Set pin widget */
+ regmap_write(rt274->regmap, RT274_SET_PIN_HPO, 0x40);
+ regmap_write(rt274->regmap, RT274_SET_PIN_LOUT3, 0x40);
+ regmap_write(rt274->regmap, RT274_SET_MIC, 0x20);
+ regmap_write(rt274->regmap, RT274_SET_PIN_DMIC1, 0x20);
+
+ regmap_update_bits(rt274->regmap, RT274_I2S_CTRL2, 0xc004, 0x4004);
+ regmap_update_bits(rt274->regmap, RT274_EAPD_GPIO_IRQ_CTRL,
+ RT274_GPI2_SEL_MASK, RT274_GPI2_SEL_DMIC_CLK);
+
+ /* jack detection */
+ regmap_write(rt274->regmap, RT274_UNSOLICITED_HP_OUT, 0x81);
+ regmap_write(rt274->regmap, RT274_UNSOLICITED_MIC, 0x82);
+
+ if (rt274->i2c->irq) {
+ ret = request_threaded_irq(rt274->i2c->irq, NULL, rt274_irq,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt274", rt274);
+ if (ret != 0) {
+ dev_err(&i2c->dev,
+ "Failed to reguest IRQ: %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt274,
+ rt274_dai, ARRAY_SIZE(rt274_dai));
+
+ return ret;
+}
+
+static int rt274_i2c_remove(struct i2c_client *i2c)
+{
+ struct rt274_priv *rt274 = i2c_get_clientdata(i2c);
+
+ if (i2c->irq)
+ free_irq(i2c->irq, rt274);
+ snd_soc_unregister_codec(&i2c->dev);
+
+ return 0;
+}
+
+
+static struct i2c_driver rt274_i2c_driver = {
+ .driver = {
+ .name = "rt274",
+ .acpi_match_table = ACPI_PTR(rt274_acpi_match),
+#ifdef CONFIG_OF
+ .of_match_table = of_match_ptr(rt274_of_match),
+#endif
+ },
+ .probe = rt274_i2c_probe,
+ .remove = rt274_i2c_remove,
+ .id_table = rt274_i2c_id,
+};
+
+module_i2c_driver(rt274_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC RT274 driver");
+MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt274.h b/sound/soc/codecs/rt274.h
new file mode 100644
index 000000000000..4fd1bcb73dba
--- /dev/null
+++ b/sound/soc/codecs/rt274.h
@@ -0,0 +1,217 @@
+/*
+ * rt274.h -- RT274 ALSA SoC audio driver
+ *
+ * Copyright 2016 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 __RT274_H__
+#define __RT274_H__
+
+#define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D)
+
+#define RT274_AUDIO_FUNCTION_GROUP 0x01
+#define RT274_DAC_OUT0 0x02
+#define RT274_DAC_OUT1 0x03
+#define RT274_ADC_IN2 0x08
+#define RT274_ADC_IN1 0x09
+#define RT274_DIG_CVT 0x0a
+#define RT274_DMIC1 0x12
+#define RT274_DMIC2 0x13
+#define RT274_MIC 0x19
+#define RT274_LINE1 0x1a
+#define RT274_LINE2 0x1b
+#define RT274_LINE3 0x16
+#define RT274_SPDIF 0x1e
+#define RT274_VENDOR_REGISTERS 0x20
+#define RT274_HP_OUT 0x21
+#define RT274_MIXER_IN1 0x22
+#define RT274_MIXER_IN2 0x23
+#define RT274_INLINE_CMD 0x55
+
+#define RT274_SET_PIN_SFT 6
+#define RT274_SET_PIN_ENABLE 0x40
+#define RT274_SET_PIN_DISABLE 0
+#define RT274_SET_EAPD_HIGH 0x2
+#define RT274_SET_EAPD_LOW 0
+
+#define RT274_MUTE_SFT 7
+
+/* Verb commands */
+#define RT274_RESET\
+ VERB_CMD(AC_VERB_SET_CODEC_RESET, RT274_AUDIO_FUNCTION_GROUP, 0)
+#define RT274_GET_PARAM(NID, PARAM) VERB_CMD(AC_VERB_PARAMETERS, NID, PARAM)
+#define RT274_SET_POWER(NID) VERB_CMD(AC_VERB_SET_POWER_STATE, NID, 0)
+#define RT274_SET_AUDIO_POWER RT274_SET_POWER(RT274_AUDIO_FUNCTION_GROUP)
+#define RT274_SET_HPO_POWER RT274_SET_POWER(RT274_HP_OUT)
+#define RT274_SET_DMIC1_POWER RT274_SET_POWER(RT274_DMIC1)
+#define RT274_LOUT_MUX\
+ VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT274_LINE3, 0)
+#define RT274_HPO_MUX\
+ VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT274_HP_OUT, 0)
+#define RT274_ADC0_MUX\
+ VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT274_MIXER_IN1, 0)
+#define RT274_ADC1_MUX\
+ VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT274_MIXER_IN2, 0)
+#define RT274_SET_MIC\
+ VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT274_MIC, 0)
+#define RT274_SET_PIN_LOUT3\
+ VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT274_LINE3, 0)
+#define RT274_SET_PIN_HPO\
+ VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT274_HP_OUT, 0)
+#define RT274_SET_PIN_DMIC1\
+ VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT274_DMIC1, 0)
+#define RT274_SET_PIN_SPDIF\
+ VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT274_SPDIF, 0)
+#define RT274_SET_PIN_DIG_CVT\
+ VERB_CMD(AC_VERB_SET_DIGI_CONVERT_1, RT274_DIG_CVT, 0)
+#define RT274_SET_AMP_GAIN_HPO\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_HP_OUT, 0)
+#define RT274_SET_AMP_GAIN_ADC_IN1\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_ADC_IN1, 0)
+#define RT274_SET_AMP_GAIN_ADC_IN2\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_ADC_IN2, 0)
+#define RT274_GET_HP_SENSE\
+ VERB_CMD(AC_VERB_GET_PIN_SENSE, RT274_HP_OUT, 0)
+#define RT274_GET_MIC_SENSE\
+ VERB_CMD(AC_VERB_GET_PIN_SENSE, RT274_MIC, 0)
+#define RT274_SET_DMIC2_DEFAULT\
+ VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT274_DMIC2, 0)
+#define RT274_SET_SPDIF_DEFAULT\
+ VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT274_SPDIF, 0)
+#define RT274_DAC0L_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_DAC_OUT0, 0xa000)
+#define RT274_DAC0R_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_DAC_OUT0, 0x9000)
+#define RT274_DAC1L_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_DAC_OUT1, 0xa000)
+#define RT274_DAC1R_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_DAC_OUT1, 0x9000)
+#define RT274_ADCL_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_ADC_IN1, 0x6000)
+#define RT274_ADCR_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_ADC_IN1, 0x5000)
+#define RT274_MIC_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_MIC, 0x7000)
+#define RT274_LOUTL_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_LINE3, 0xa000)
+#define RT274_LOUTR_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_LINE3, 0x9000)
+#define RT274_HPOL_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_HP_OUT, 0xa000)
+#define RT274_HPOR_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT274_HP_OUT, 0x9000)
+#define RT274_DAC_FORMAT\
+ VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT274_DAC_OUT0, 0)
+#define RT274_ADC_FORMAT\
+ VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT274_ADC_IN1, 0)
+#define RT274_COEF_INDEX\
+ VERB_CMD(AC_VERB_SET_COEF_INDEX, RT274_VENDOR_REGISTERS, 0)
+#define RT274_PROC_COEF\
+ VERB_CMD(AC_VERB_SET_PROC_COEF, RT274_VENDOR_REGISTERS, 0)
+#define RT274_UNSOLICITED_INLINE_CMD\
+ VERB_CMD(AC_VERB_SET_UNSOLICITED_ENABLE, RT274_INLINE_CMD, 0)
+#define RT274_UNSOLICITED_HP_OUT\
+ VERB_CMD(AC_VERB_SET_UNSOLICITED_ENABLE, RT274_HP_OUT, 0)
+#define RT274_UNSOLICITED_MIC\
+ VERB_CMD(AC_VERB_SET_UNSOLICITED_ENABLE, RT274_MIC, 0)
+#define RT274_COEF58_INDEX\
+ VERB_CMD(AC_VERB_SET_COEF_INDEX, 0x58, 0)
+#define RT274_COEF58_COEF\
+ VERB_CMD(AC_VERB_SET_PROC_COEF, 0x58, 0)
+#define RT274_COEF5b_INDEX\
+ VERB_CMD(AC_VERB_SET_COEF_INDEX, 0x5b, 0)
+#define RT274_COEF5b_COEF\
+ VERB_CMD(AC_VERB_SET_PROC_COEF, 0x5b, 0)
+#define RT274_SET_STREAMID_DAC0\
+ VERB_CMD(AC_VERB_SET_CHANNEL_STREAMID, RT274_DAC_OUT0, 0)
+#define RT274_SET_STREAMID_DAC1\
+ VERB_CMD(AC_VERB_SET_CHANNEL_STREAMID, RT274_DAC_OUT1, 0)
+#define RT274_SET_STREAMID_ADC1\
+ VERB_CMD(AC_VERB_SET_CHANNEL_STREAMID, RT274_ADC_IN1, 0)
+#define RT274_SET_STREAMID_ADC2\
+ VERB_CMD(AC_VERB_SET_CHANNEL_STREAMID, RT274_ADC_IN2, 0)
+
+/* Index registers */
+#define RT274_EAPD_GPIO_IRQ_CTRL 0x10
+#define RT274_PAD_CTRL12 0x35
+#define RT274_I2S_CTRL1 0x63
+#define RT274_I2S_CTRL2 0x64
+#define RT274_MCLK_CTRL 0x71
+#define RT274_CLK_CTRL 0x72
+#define RT274_PLL2_CTRL 0x7b
+
+
+/* EAPD GPIO IRQ control (Index 0x10) */
+#define RT274_IRQ_DIS (0x0 << 13)
+#define RT274_IRQ_EN (0x1 << 13)
+#define RT274_IRQ_CLR (0x1 << 12)
+#define RT274_GPI2_SEL_MASK (0x3 << 7)
+#define RT274_GPI2_SEL_GPIO2 (0x0 << 7)
+#define RT274_GPI2_SEL_I2S (0x1 << 7)
+#define RT274_GPI2_SEL_DMIC_CLK (0x2 << 7)
+#define RT274_GPI2_SEL_CBJ (0x3 << 7)
+
+/* Front I2S_Interface control 1 (Index 0x63) */
+#define RT274_I2S_MODE_MASK (0x1 << 11)
+#define RT274_I2S_MODE_S (0x0 << 11)
+#define RT274_I2S_MODE_M (0x1 << 11)
+#define RT274_TDM_DIS (0x0 << 10)
+#define RT274_TDM_EN (0x1 << 10)
+#define RT274_TDM_CH_NUM (0x1 << 7)
+#define RT274_TDM_2CH (0x0 << 7)
+#define RT274_TDM_4CH (0x1 << 7)
+#define RT274_I2S_FMT_MASK (0x3 << 8)
+#define RT274_I2S_FMT_I2S (0x0 << 8)
+#define RT274_I2S_FMT_LJ (0x1 << 8)
+#define RT274_I2S_FMT_PCMA (0x2 << 8)
+#define RT274_I2S_FMT_PCMB (0x3 << 8)
+
+/* MCLK clock domain control (Index 0x71) */
+#define RT274_MCLK_MODE_MASK (0x1 << 14)
+#define RT274_MCLK_MODE_DIS (0x0 << 14)
+#define RT274_MCLK_MODE_EN (0x1 << 14)
+
+/* Clock control (Index 0x72) */
+#define RT274_CLK_SRC_MASK (0x7 << 3)
+#define RT274_CLK_SRC_MCLK (0x0 << 3)
+#define RT274_CLK_SRC_PLL2 (0x3 << 3)
+
+/* PLL2 control (Index 0x7b) */
+#define RT274_PLL2_SRC_MASK (0x1 << 13)
+#define RT274_PLL2_SRC_MCLK (0x0 << 13)
+#define RT274_PLL2_SRC_BCLK (0x1 << 13)
+
+/* HP-OUT (0x21) */
+#define RT274_M_HP_MUX_SFT 14
+#define RT274_HP_SEL_MASK 0x1
+#define RT274_HP_SEL_SFT 0
+#define RT274_HP_SEL_F 0
+#define RT274_HP_SEL_S 1
+
+/* ADC (0x22) (0x23) */
+#define RT274_ADC_SEL_MASK 0x7
+#define RT274_ADC_SEL_SFT 0
+#define RT274_ADC_SEL_MIC 0
+#define RT274_ADC_SEL_LINE1 1
+#define RT274_ADC_SEL_LINE2 2
+#define RT274_ADC_SEL_DMIC 3
+
+#define RT274_SCLK_S_MCLK 0
+#define RT274_SCLK_S_PLL1 1
+#define RT274_SCLK_S_PLL2 2
+
+#define RT274_PLL2_S_MCLK 0
+#define RT274_PLL2_S_BCLK 1
+
+enum {
+ RT274_AIF1,
+ RT274_AIFS,
+};
+
+#endif /* __RT274_H__ */
+
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
index 7899a2cdeb42..af6325c78292 100644
--- a/sound/soc/codecs/rt286.c
+++ b/sound/soc/codecs/rt286.c
@@ -1046,7 +1046,7 @@ static struct snd_soc_dai_driver rt286_dai[] = {
};
-static struct snd_soc_codec_driver soc_codec_dev_rt286 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt286 = {
.probe = rt286_probe,
.remove = rt286_remove,
.suspend = rt286_suspend,
diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c
index d9e96e65e1c4..ce963768449f 100644
--- a/sound/soc/codecs/rt298.c
+++ b/sound/soc/codecs/rt298.c
@@ -1113,7 +1113,7 @@ static struct snd_soc_dai_driver rt298_dai[] = {
};
-static struct snd_soc_codec_driver soc_codec_dev_rt298 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt298 = {
.probe = rt298_probe,
.remove = rt298_remove,
.suspend = rt298_suspend,
diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c
index 7ed62e8c80b4..87a587fa90fe 100644
--- a/sound/soc/codecs/rt5514-spi.c
+++ b/sound/soc/codecs/rt5514-spi.c
@@ -260,7 +260,7 @@ static int rt5514_spi_pcm_probe(struct snd_soc_platform *platform)
return 0;
}
-static struct snd_soc_platform_driver rt5514_spi_platform = {
+static const struct snd_soc_platform_driver rt5514_spi_platform = {
.probe = rt5514_spi_pcm_probe,
.ops = &rt5514_spi_pcm_ops,
};
diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c
index 1b6796c4c471..7a1b36f6596a 100644
--- a/sound/soc/codecs/rt5514.c
+++ b/sound/soc/codecs/rt5514.c
@@ -1042,7 +1042,7 @@ struct snd_soc_dai_driver rt5514_dai[] = {
}
};
-static struct snd_soc_codec_driver soc_codec_dev_rt5514 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt5514 = {
.probe = rt5514_probe,
.idle_bias_off = true,
.set_bias_level = rt5514_set_bias_level,
diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c
index 7d6e0823f98f..3c5f555ae6d0 100644
--- a/sound/soc/codecs/rt5616.c
+++ b/sound/soc/codecs/rt5616.c
@@ -1294,7 +1294,7 @@ static struct snd_soc_dai_driver rt5616_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_rt5616 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt5616 = {
.probe = rt5616_probe,
.suspend = rt5616_suspend,
.resume = rt5616_resume,
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
index 0e418089c053..55b04c55fb4b 100644
--- a/sound/soc/codecs/rt5631.c
+++ b/sound/soc/codecs/rt5631.c
@@ -1653,7 +1653,7 @@ static struct snd_soc_dai_driver rt5631_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_rt5631 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt5631 = {
.probe = rt5631_probe,
.set_bias_level = rt5631_set_bias_level,
.suspend_bias_off = true,
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 1584ccc3a87b..438fe52a12df 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -2259,7 +2259,7 @@ static struct snd_soc_dai_driver rt5640_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_rt5640 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt5640 = {
.probe = rt5640_probe,
.remove = rt5640_remove,
.suspend = rt5640_suspend,
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 9ec58166f7c4..ce31d0dcf894 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -3473,7 +3473,7 @@ static struct snd_soc_dai_driver rt5645_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_rt5645 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt5645 = {
.probe = rt5645_probe,
.remove = rt5645_remove,
.suspend = rt5645_suspend,
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index db05b60d5002..da60b28ba3df 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -1664,7 +1664,7 @@ static struct snd_soc_dai_driver rt5651_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_rt5651 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt5651 = {
.probe = rt5651_probe,
.suspend = rt5651_suspend,
.resume = rt5651_resume,
diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c
index 1b7060850340..e8018fce7e4b 100644
--- a/sound/soc/codecs/rt5659.c
+++ b/sound/soc/codecs/rt5659.c
@@ -3730,7 +3730,7 @@ static struct snd_soc_dai_driver rt5659_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_rt5659 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt5659 = {
.probe = rt5659_probe,
.remove = rt5659_remove,
.suspend = rt5659_suspend,
diff --git a/sound/soc/codecs/rt5660.c b/sound/soc/codecs/rt5660.c
index c93490d77f2a..d22ef00e0d96 100644
--- a/sound/soc/codecs/rt5660.c
+++ b/sound/soc/codecs/rt5660.c
@@ -1197,7 +1197,7 @@ static struct snd_soc_dai_driver rt5660_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_rt5660 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt5660 = {
.probe = rt5660_probe,
.remove = rt5660_remove,
.suspend = rt5660_suspend,
diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c
index fa550e3c1332..31aeb2ba6204 100644
--- a/sound/soc/codecs/rt5663.c
+++ b/sound/soc/codecs/rt5663.c
@@ -2891,7 +2891,7 @@ static struct snd_soc_dai_driver rt5663_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_rt5663 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt5663 = {
.probe = rt5663_probe,
.remove = rt5663_remove,
.suspend = rt5663_suspend,
diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c
index e597c893536d..02493bbb07e1 100644
--- a/sound/soc/codecs/rt5665.c
+++ b/sound/soc/codecs/rt5665.c
@@ -4562,7 +4562,7 @@ static struct snd_soc_dai_driver rt5665_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_rt5665 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt5665 = {
.probe = rt5665_probe,
.remove = rt5665_remove,
.suspend = rt5665_suspend,
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
index 054b613cb0d0..f2d6a999df6f 100644
--- a/sound/soc/codecs/rt5670.c
+++ b/sound/soc/codecs/rt5670.c
@@ -2765,7 +2765,7 @@ static struct snd_soc_dai_driver rt5670_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_rt5670 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt5670 = {
.probe = rt5670_probe,
.remove = rt5670_remove,
.suspend = rt5670_suspend,
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c
index 6f629278d982..8dacfdd05d6b 100644
--- a/sound/soc/codecs/rt5677.c
+++ b/sound/soc/codecs/rt5677.c
@@ -4968,7 +4968,7 @@ static struct snd_soc_dai_driver rt5677_dai[] = {
},
};
-static struct snd_soc_codec_driver soc_codec_dev_rt5677 = {
+static const struct snd_soc_codec_driver soc_codec_dev_rt5677 = {
.probe = rt5677_probe,
.remove = rt5677_remove,
.suspend = rt5677_suspend,
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 80f6d1da7095..f2bb4feba3b6 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -1248,7 +1248,7 @@ static int sgtl5000_remove(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver sgtl5000_driver = {
+static const struct snd_soc_codec_driver sgtl5000_driver = {
.probe = sgtl5000_probe,
.remove = sgtl5000_remove,
.set_bias_level = sgtl5000_set_bias_level,
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
index 5344f4aa8fde..354dc0d64f11 100644
--- a/sound/soc/codecs/si476x.c
+++ b/sound/soc/codecs/si476x.c
@@ -236,7 +236,7 @@ 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 = {
+static const struct snd_soc_codec_driver soc_codec_dev_si476x = {
.get_regmap = si476x_get_regmap,
.component_driver = {
.dapm_widgets = si476x_dapm_widgets,
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c
index 6bfd25c289d1..50bc22266ecb 100644
--- a/sound/soc/codecs/sirf-audio-codec.c
+++ b/sound/soc/codecs/sirf-audio-codec.c
@@ -429,7 +429,7 @@ static int sirf_audio_codec_remove(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_device_sirf_audio_codec = {
+static const 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,
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index eae54c37cff9..887923e68849 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -883,7 +883,7 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver sn95031_codec = {
+static const struct snd_soc_codec_driver sn95031_codec = {
.probe = sn95031_codec_probe,
.set_bias_level = sn95031_set_vaud_bias,
.idle_bias_off = true,
diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c
index 234f87b54838..7acd05140a81 100644
--- a/sound/soc/codecs/spdif_receiver.c
+++ b/sound/soc/codecs/spdif_receiver.c
@@ -37,7 +37,7 @@ static const struct snd_soc_dapm_route dir_routes[] = {
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
-static struct snd_soc_codec_driver soc_codec_spdif_dir = {
+static const struct snd_soc_codec_driver soc_codec_spdif_dir = {
.component_driver = {
.dapm_widgets = dir_widgets,
.num_dapm_widgets = ARRAY_SIZE(dir_widgets),
diff --git a/sound/soc/codecs/spdif_transmitter.c b/sound/soc/codecs/spdif_transmitter.c
index ee367536a498..063a64ff82d3 100644
--- a/sound/soc/codecs/spdif_transmitter.c
+++ b/sound/soc/codecs/spdif_transmitter.c
@@ -37,7 +37,7 @@ static const struct snd_soc_dapm_route dit_routes[] = {
{ "spdif-out", NULL, "Playback" },
};
-static struct snd_soc_codec_driver soc_codec_spdif_dit = {
+static const struct snd_soc_codec_driver soc_codec_spdif_dit = {
.component_driver = {
.dapm_widgets = dit_widgets,
.num_dapm_widgets = ARRAY_SIZE(dit_widgets),
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c
index 38a85f3adc80..15486fd16269 100644
--- a/sound/soc/codecs/ssm2518.c
+++ b/sound/soc/codecs/ssm2518.c
@@ -710,7 +710,7 @@ static int ssm2518_set_sysclk(struct snd_soc_codec *codec, int clk_id,
SSM2518_POWER1_NO_BCLK, val);
}
-static struct snd_soc_codec_driver ssm2518_codec_driver = {
+static const struct snd_soc_codec_driver ssm2518_codec_driver = {
.set_bias_level = ssm2518_set_bias_level,
.set_sysclk = ssm2518_set_sysclk,
.idle_bias_off = true,
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 993bde29ca1b..9b341c23f62b 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -591,7 +591,7 @@ static int ssm260x_codec_probe(struct snd_soc_codec *codec)
return ret;
}
-static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
+static const struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
.probe = ssm260x_codec_probe,
.resume = ssm2602_resume,
.set_bias_level = ssm2602_set_bias_level,
diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c
index a622623e8558..4afeddef7728 100644
--- a/sound/soc/codecs/ssm4567.c
+++ b/sound/soc/codecs/ssm4567.c
@@ -417,7 +417,7 @@ static struct snd_soc_dai_driver ssm4567_dai = {
.ops = &ssm4567_dai_ops,
};
-static struct snd_soc_codec_driver ssm4567_codec_driver = {
+static const struct snd_soc_codec_driver ssm4567_codec_driver = {
.set_bias_level = ssm4567_set_bias_level,
.idle_bias_off = true,
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index 9de7fe8af255..c66363a2cac7 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -307,7 +307,7 @@ static int stac9766_codec_remove(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
+static const struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
.component_driver = {
.controls = stac9766_snd_ac97_controls,
.num_controls = ARRAY_SIZE(stac9766_snd_ac97_controls),
diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c
index 8840f72f3c4a..49cf9bc32eb6 100644
--- a/sound/soc/codecs/tas2552.c
+++ b/sound/soc/codecs/tas2552.c
@@ -660,7 +660,7 @@ static int tas2552_resume(struct snd_soc_codec *codec)
#define tas2552_resume NULL
#endif
-static struct snd_soc_codec_driver soc_codec_dev_tas2552 = {
+static const struct snd_soc_codec_driver soc_codec_dev_tas2552 = {
.probe = tas2552_codec_probe,
.remove = tas2552_codec_remove,
.suspend = tas2552_suspend,
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c
index b7de857abb16..199272d5cb6a 100644
--- a/sound/soc/codecs/tas5086.c
+++ b/sound/soc/codecs/tas5086.c
@@ -885,7 +885,7 @@ static int tas5086_remove(struct snd_soc_codec *codec)
return 0;
};
-static struct snd_soc_codec_driver soc_codec_dev_tas5086 = {
+static const struct snd_soc_codec_driver soc_codec_dev_tas5086 = {
.probe = tas5086_probe,
.remove = tas5086_remove,
.suspend = tas5086_soc_suspend,
diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c
index c65b917598d2..d14b78b1917b 100644
--- a/sound/soc/codecs/tas5720.c
+++ b/sound/soc/codecs/tas5720.c
@@ -483,7 +483,7 @@ static const struct snd_soc_dapm_route tas5720_audio_map[] = {
{ "OUT", NULL, "DAC" },
};
-static struct snd_soc_codec_driver soc_codec_dev_tas5720 = {
+static const struct snd_soc_codec_driver soc_codec_dev_tas5720 = {
.probe = tas5720_codec_probe,
.remove = tas5720_codec_remove,
.suspend = tas5720_suspend,
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 628a8eeaab68..3d42138a7974 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -576,7 +576,7 @@ static int tlv320aic23_codec_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
+static const struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
.probe = tlv320aic23_codec_probe,
.resume = tlv320aic23_resume,
.set_bias_level = tlv320aic23_set_bias_level,
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 14aa96d41719..89421caaeb70 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -319,7 +319,7 @@ static int aic26_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver aic26_soc_codec_dev = {
+static const struct snd_soc_codec_driver aic26_soc_codec_dev = {
.probe = aic26_probe,
.component_driver = {
.controls = aic26_snd_controls,
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index d7d03c92cb8a..54a87a905eb6 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -1185,7 +1185,7 @@ static int aic31xx_codec_remove(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_driver_aic31xx = {
+static const struct snd_soc_codec_driver soc_codec_driver_aic31xx = {
.probe = aic31xx_codec_probe,
.remove = aic31xx_codec_remove,
.set_bias_level = aic31xx_set_bias_level,
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 28fdfc5ec544..ccfc955321ae 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -792,7 +792,7 @@ static int aic32x4_codec_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
+static const struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
.probe = aic32x4_codec_probe,
.set_bias_level = aic32x4_set_bias_level,
.suspend_bias_off = true,
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 29bf8c81ae02..405f4602888a 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1684,7 +1684,7 @@ static int aic3x_remove(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
+static const struct snd_soc_codec_driver soc_codec_dev_aic3x = {
.set_bias_level = aic3x_set_bias_level,
.idle_bias_off = true,
.probe = aic3x_probe,
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 7bcf01efdf9a..5b94a151539c 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -1433,7 +1433,7 @@ static int dac33_soc_remove(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
+static const struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
.read = dac33_read_reg_cache,
.write = dac33_write_locked,
.set_bias_level = dac33_set_bias_level,
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index a2104d68169d..d439c4c6fe50 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -2191,7 +2191,7 @@ static int twl4030_soc_remove(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
+static const struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
.probe = twl4030_soc_probe,
.remove = twl4030_soc_remove,
.read = twl4030_read,
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 2b6ad09e0886..0dc21f7e0af9 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -1155,7 +1155,7 @@ static int twl6040_remove(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
+static const struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
.probe = twl6040_probe,
.remove = twl6040_remove,
.read = twl6040_read,
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index 5fdee874406d..77c9cc4467b8 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -518,7 +518,7 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
+static const struct snd_soc_codec_driver soc_codec_dev_uda134x = {
.probe = uda134x_soc_probe,
.set_bias_level = uda134x_set_bias_level,
.suspend_bias_off = true,
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 61cdc79840e7..926c81ae8185 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -720,7 +720,7 @@ static int uda1380_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_uda1380 = {
+static const struct snd_soc_codec_driver soc_codec_dev_uda1380 = {
.probe = uda1380_probe,
.read = uda1380_read_reg_cache,
.write = uda1380_write,
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index fcffb6e707d9..942f1644973e 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -480,7 +480,7 @@ static int wl1273_remove(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_wl1273 = {
+static const struct snd_soc_codec_driver soc_codec_dev_wl1273 = {
.probe = wl1273_probe,
.remove = wl1273_remove,
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 1fe358e6be61..f5006923be2e 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -2027,7 +2027,7 @@ static struct snd_compr_ops wm5102_compr_ops = {
.copy = wm_adsp_compr_copy,
};
-static struct snd_soc_platform_driver wm5102_compr_platform = {
+static const struct snd_soc_platform_driver wm5102_compr_platform = {
.compr_ops = &wm5102_compr_ops,
};
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 1bc942152eff..d6fae1397ce2 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -2382,7 +2382,7 @@ static struct snd_compr_ops wm5110_compr_ops = {
.copy = wm_adsp_compr_copy,
};
-static struct snd_soc_platform_driver wm5110_compr_platform = {
+static const struct snd_soc_platform_driver wm5110_compr_platform = {
.compr_ops = &wm5110_compr_ops,
};
diff --git a/sound/soc/codecs/zx_aud96p22.c b/sound/soc/codecs/zx_aud96p22.c
index 032fb7cf6cbd..36d0a7087a54 100644
--- a/sound/soc/codecs/zx_aud96p22.c
+++ b/sound/soc/codecs/zx_aud96p22.c
@@ -261,7 +261,7 @@ static const struct snd_soc_dapm_route aud96p22_dapm_routes[] = {
{ "LINEOUTMN", NULL, "LD2" },
};
-static struct snd_soc_codec_driver aud96p22_driver = {
+static const struct snd_soc_codec_driver aud96p22_driver = {
.component_driver = {
.controls = aud96p22_snd_controls,
.num_controls = ARRAY_SIZE(aud96p22_snd_controls),