diff options
Diffstat (limited to 'sound/soc/codecs')
187 files changed, 9891 insertions, 1245 deletions
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index e8bed6b..b013a4c 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -1361,12 +1361,14 @@ static struct snd_soc_codec_driver soc_codec_dev_pm860x = { .set_bias_level = pm860x_set_bias_level, .get_regmap = pm860x_get_regmap, - .controls = pm860x_snd_controls, - .num_controls = ARRAY_SIZE(pm860x_snd_controls), - .dapm_widgets = pm860x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(pm860x_dapm_widgets), - .dapm_routes = pm860x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(pm860x_dapm_routes), + .component_driver = { + .controls = pm860x_snd_controls, + .num_controls = ARRAY_SIZE(pm860x_snd_controls), + .dapm_widgets = pm860x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pm860x_dapm_widgets), + .dapm_routes = pm860x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pm860x_dapm_routes), + }, }; static int pm860x_codec_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1cd6ab3..c67667b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -92,6 +92,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_MAX9877 if I2C select SND_SOC_MC13783 if MFD_MC13XXX select SND_SOC_ML26124 if I2C + select SND_SOC_NAU8810 if I2C select SND_SOC_NAU8825 if I2C select SND_SOC_HDMI_CODEC select SND_SOC_PCM1681 if I2C @@ -112,6 +113,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_RT5645 if I2C select SND_SOC_RT5651 if I2C select SND_SOC_RT5659 if I2C + select SND_SOC_RT5660 if I2C + select SND_SOC_RT5663 if I2C select SND_SOC_RT5670 if I2C select SND_SOC_RT5677 if I2C && SPI_MASTER select SND_SOC_SGTL5000 if I2C @@ -645,6 +648,8 @@ config SND_SOC_RL6231 default y if SND_SOC_RT5645=y default y if SND_SOC_RT5651=y default y if SND_SOC_RT5659=y + default y if SND_SOC_RT5660=y + default y if SND_SOC_RT5663=y default y if SND_SOC_RT5670=y default y if SND_SOC_RT5677=y default m if SND_SOC_RT5514=m @@ -653,6 +658,8 @@ config SND_SOC_RL6231 default m if SND_SOC_RT5645=m default m if SND_SOC_RT5651=m default m if SND_SOC_RT5659=m + default m if SND_SOC_RT5660=m + default m if SND_SOC_RT5663=m default m if SND_SOC_RT5670=m default m if SND_SOC_RT5677=m @@ -665,6 +672,7 @@ config SND_SOC_RL6347A config SND_SOC_RT286 tristate + select SND_SOC_RT5663 depends on I2C config SND_SOC_RT298 @@ -697,6 +705,12 @@ config SND_SOC_RT5651 config SND_SOC_RT5659 tristate +config SND_SOC_RT5660 + tristate + +config SND_SOC_RT5663 + tristate + config SND_SOC_RT5670 tristate @@ -1064,6 +1078,10 @@ config SND_SOC_MC13783 config SND_SOC_ML26124 tristate +config SND_SOC_NAU8810 + tristate "Nuvoton Technology Corporation NAU88C10 CODEC" + depends on I2C + config SND_SOC_NAU8825 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 58036af..958cd49 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -86,6 +86,7 @@ snd-soc-max9850-objs := max9850.o snd-soc-max9860-objs := max9860.o snd-soc-mc13783-objs := mc13783.o snd-soc-ml26124-objs := ml26124.o +snd-soc-nau8810-objs := nau8810.o snd-soc-nau8825-objs := nau8825.o snd-soc-hdmi-codec-objs := hdmi-codec.o snd-soc-pcm1681-objs := pcm1681.o @@ -112,6 +113,8 @@ snd-soc-rt5640-objs := rt5640.o snd-soc-rt5645-objs := rt5645.o snd-soc-rt5651-objs := rt5651.o snd-soc-rt5659-objs := rt5659.o +snd-soc-rt5660-objs := rt5660.o +snd-soc-rt5663-objs := rt5663.o snd-soc-rt5670-objs := rt5670.o snd-soc-rt5677-objs := rt5677.o snd-soc-rt5677-spi-objs := rt5677-spi.o @@ -307,6 +310,7 @@ obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o obj-$(CONFIG_SND_SOC_MAX9860) += snd-soc-max9860.o obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o +obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o @@ -333,6 +337,8 @@ obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o obj-$(CONFIG_SND_SOC_RT5659) += snd-soc-rt5659.o +obj-$(CONFIG_SND_SOC_RT5660) += snd-soc-rt5660.o +obj-$(CONFIG_SND_SOC_RT5663) += snd-soc-rt5663.o obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 2fc8915..935ff7c 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2408,28 +2408,28 @@ static void ab8500_codec_of_probe(struct device *dev, struct device_node *np, { u32 value; - if (of_get_property(np, "stericsson,amic1-type-single-ended", NULL)) + if (of_property_read_bool(np, "stericsson,amic1-type-single-ended")) codec->amics.mic1_type = AMIC_TYPE_SINGLE_ENDED; else codec->amics.mic1_type = AMIC_TYPE_DIFFERENTIAL; - if (of_get_property(np, "stericsson,amic2-type-single-ended", NULL)) + if (of_property_read_bool(np, "stericsson,amic2-type-single-ended")) codec->amics.mic2_type = AMIC_TYPE_SINGLE_ENDED; else codec->amics.mic2_type = AMIC_TYPE_DIFFERENTIAL; /* Has a non-standard Vamic been requested? */ - if (of_get_property(np, "stericsson,amic1a-bias-vamic2", NULL)) + if (of_property_read_bool(np, "stericsson,amic1a-bias-vamic2")) codec->amics.mic1a_micbias = AMIC_MICBIAS_VAMIC2; else codec->amics.mic1a_micbias = AMIC_MICBIAS_VAMIC1; - if (of_get_property(np, "stericsson,amic1b-bias-vamic2", NULL)) + if (of_property_read_bool(np, "stericsson,amic1b-bias-vamic2")) codec->amics.mic1b_micbias = AMIC_MICBIAS_VAMIC2; else codec->amics.mic1b_micbias = AMIC_MICBIAS_VAMIC1; - if (of_get_property(np, "stericsson,amic2-bias-vamic1", NULL)) + if (of_property_read_bool(np, "stericsson,amic2-bias-vamic1")) codec->amics.mic2_micbias = AMIC_MICBIAS_VAMIC1; else codec->amics.mic2_micbias = AMIC_MICBIAS_VAMIC2; @@ -2525,12 +2525,14 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver ab8500_codec_driver = { .probe = ab8500_codec_probe, - .controls = ab8500_ctrls, - .num_controls = ARRAY_SIZE(ab8500_ctrls), - .dapm_widgets = ab8500_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ab8500_dapm_widgets), - .dapm_routes = ab8500_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ab8500_dapm_routes), + .component_driver = { + .controls = ab8500_ctrls, + .num_controls = ARRAY_SIZE(ab8500_ctrls), + .dapm_widgets = ab8500_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ab8500_dapm_widgets), + .dapm_routes = ab8500_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ab8500_dapm_routes), + }, }; static int ab8500_codec_driver_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 5b3224c..f7f04c6 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -117,10 +117,12 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = { .suspend = ac97_soc_suspend, .resume = ac97_soc_resume, - .dapm_widgets = ac97_widgets, - .num_dapm_widgets = ARRAY_SIZE(ac97_widgets), - .dapm_routes = ac97_routes, - .num_dapm_routes = ARRAY_SIZE(ac97_routes), + .component_driver = { + .dapm_widgets = ac97_widgets, + .num_dapm_widgets = ARRAY_SIZE(ac97_widgets), + .dapm_routes = ac97_routes, + .num_dapm_routes = ARRAY_SIZE(ac97_routes), + }, }; static int ac97_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index e2ce6c4..a478239 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -327,12 +327,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { .suspend = ad1836_suspend, .resume = ad1836_resume, - .controls = ad183x_controls, - .num_controls = ARRAY_SIZE(ad183x_controls), - .dapm_widgets = ad183x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ad183x_dapm_widgets), - .dapm_routes = ad183x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), + .component_driver = { + .controls = ad183x_controls, + .num_controls = ARRAY_SIZE(ad183x_controls), + .dapm_widgets = ad183x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ad183x_dapm_widgets), + .dapm_routes = ad183x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), + }, }; static const struct reg_default ad1836_reg_defaults[] = { diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 3a3f3f2..d643557 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -410,12 +410,14 @@ static int ad193x_codec_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_ad193x = { .probe = ad193x_codec_probe, - .controls = ad193x_snd_controls, - .num_controls = ARRAY_SIZE(ad193x_snd_controls), - .dapm_widgets = ad193x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ad193x_dapm_widgets), - .dapm_routes = audio_paths, - .num_dapm_routes = ARRAY_SIZE(audio_paths), + .component_driver = { + .controls = ad193x_snd_controls, + .num_controls = ARRAY_SIZE(ad193x_snd_controls), + .dapm_widgets = ad193x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ad193x_dapm_widgets), + .dapm_routes = audio_paths, + .num_dapm_routes = ARRAY_SIZE(audio_paths), + }, }; const struct regmap_config ad193x_regmap_config = { diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 9ef20db..b7c1b9f 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -299,12 +299,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1980 = { .probe = ad1980_soc_probe, .remove = ad1980_soc_remove, - .controls = ad1980_snd_ac97_controls, - .num_controls = ARRAY_SIZE(ad1980_snd_ac97_controls), - .dapm_widgets = ad1980_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets), - .dapm_routes = ad1980_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ad1980_dapm_routes), + .component_driver = { + .controls = ad1980_snd_ac97_controls, + .num_controls = ARRAY_SIZE(ad1980_snd_ac97_controls), + .dapm_widgets = ad1980_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets), + .dapm_routes = ad1980_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ad1980_dapm_routes), + }, }; static int ad1980_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index a9400ae..3e358a4 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c @@ -55,10 +55,12 @@ static struct snd_soc_dai_driver ad73311_dai = { }; static struct snd_soc_codec_driver soc_codec_dev_ad73311 = { - .dapm_widgets = ad73311_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ad73311_dapm_widgets), - .dapm_routes = ad73311_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ad73311_dapm_routes), + .component_driver = { + .dapm_widgets = ad73311_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ad73311_dapm_widgets), + .dapm_routes = ad73311_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ad73311_dapm_routes), + }, }; static int ad73311_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 1556b36..8fa9045 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -1466,12 +1466,14 @@ static struct snd_soc_codec_driver adau1373_codec_driver = { .set_pll = adau1373_set_pll, - .controls = adau1373_controls, - .num_controls = ARRAY_SIZE(adau1373_controls), - .dapm_widgets = adau1373_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau1373_dapm_widgets), - .dapm_routes = adau1373_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes), + .component_driver = { + .controls = adau1373_controls, + .num_controls = ARRAY_SIZE(adau1373_controls), + .dapm_widgets = adau1373_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1373_dapm_widgets), + .dapm_routes = adau1373_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes), + }, }; static int adau1373_i2c_probe(struct i2c_client *client, diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index de53c0d..3bad1bc 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c @@ -765,13 +765,14 @@ static struct snd_soc_codec_driver adau1701_codec_drv = { .set_bias_level = adau1701_set_bias_level, .idle_bias_off = true, - .controls = adau1701_controls, - .num_controls = ARRAY_SIZE(adau1701_controls), - .dapm_widgets = adau1701_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau1701_dapm_widgets), - .dapm_routes = adau1701_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), - + .component_driver = { + .controls = adau1701_controls, + .num_controls = ARRAY_SIZE(adau1701_controls), + .dapm_widgets = adau1701_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1701_dapm_widgets), + .dapm_routes = adau1701_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), + }, .set_sysclk = adau1701_set_sysclk, }; diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index b95d29d..3bc3cc5 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c @@ -719,12 +719,14 @@ static const struct snd_soc_codec_driver adau1761_codec_driver = { .set_bias_level = adau1761_set_bias_level, .suspend_bias_off = true, - .controls = adau1761_controls, - .num_controls = ARRAY_SIZE(adau1761_controls), - .dapm_widgets = adau1x61_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau1x61_dapm_widgets), - .dapm_routes = adau1x61_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adau1x61_dapm_routes), + .component_driver = { + .controls = adau1761_controls, + .num_controls = ARRAY_SIZE(adau1761_controls), + .dapm_widgets = adau1x61_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1x61_dapm_widgets), + .dapm_routes = adau1x61_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1x61_dapm_routes), + }, }; #define ADAU1761_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c index bc1bb56..546071c 100644 --- a/sound/soc/codecs/adau1781.c +++ b/sound/soc/codecs/adau1781.c @@ -432,12 +432,14 @@ static const struct snd_soc_codec_driver adau1781_codec_driver = { .set_bias_level = adau1781_set_bias_level, .suspend_bias_off = true, - .controls = adau1781_controls, - .num_controls = ARRAY_SIZE(adau1781_controls), - .dapm_widgets = adau1781_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau1781_dapm_widgets), - .dapm_routes = adau1781_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adau1781_dapm_routes), + .component_driver = { + .controls = adau1781_controls, + .num_controls = ARRAY_SIZE(adau1781_controls), + .dapm_widgets = adau1781_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1781_dapm_widgets), + .dapm_routes = adau1781_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1781_dapm_routes), + }, }; #define ADAU1781_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c index 9bdd15f..b319db6 100644 --- a/sound/soc/codecs/adau1977.c +++ b/sound/soc/codecs/adau1977.c @@ -873,12 +873,14 @@ static struct snd_soc_codec_driver adau1977_codec_driver = { .set_sysclk = adau1977_set_sysclk, .idle_bias_off = true, - .controls = adau1977_snd_controls, - .num_controls = ARRAY_SIZE(adau1977_snd_controls), - .dapm_widgets = adau1977_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau1977_dapm_widgets), - .dapm_routes = adau1977_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adau1977_dapm_routes), + .component_driver = { + .controls = adau1977_snd_controls, + .num_controls = ARRAY_SIZE(adau1977_snd_controls), + .dapm_widgets = adau1977_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1977_dapm_widgets), + .dapm_routes = adau1977_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1977_dapm_routes), + }, }; static int adau1977_setup_micbias(struct adau1977 *adau1977) diff --git a/sound/soc/codecs/adau7002.c b/sound/soc/codecs/adau7002.c index 9df72c6..6384c54 100644 --- a/sound/soc/codecs/adau7002.c +++ b/sound/soc/codecs/adau7002.c @@ -39,10 +39,12 @@ static struct snd_soc_dai_driver adau7002_dai = { }; static const struct snd_soc_codec_driver adau7002_codec_driver = { - .dapm_widgets = adau7002_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau7002_widgets), - .dapm_routes = adau7002_routes, - .num_dapm_routes = ARRAY_SIZE(adau7002_routes), + .component_driver = { + .dapm_widgets = adau7002_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau7002_widgets), + .dapm_routes = adau7002_routes, + .num_dapm_routes = ARRAY_SIZE(adau7002_routes), + }, }; static int adau7002_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index acff8d6..6e793eb 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -834,12 +834,14 @@ static struct snd_soc_codec_driver adav80x_codec_driver = { .set_pll = adav80x_set_pll, .set_sysclk = adav80x_set_sysclk, - .controls = adav80x_controls, - .num_controls = ARRAY_SIZE(adav80x_controls), - .dapm_widgets = adav80x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adav80x_dapm_widgets), - .dapm_routes = adav80x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), + .component_driver = { + .controls = adav80x_controls, + .num_controls = ARRAY_SIZE(adav80x_controls), + .dapm_widgets = adav80x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adav80x_dapm_widgets), + .dapm_routes = adav80x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), + }, }; int adav80x_bus_probe(struct device *dev, struct regmap *regmap) diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c index c5be1bd..90c756d 100644 --- a/sound/soc/codecs/ads117x.c +++ b/sound/soc/codecs/ads117x.c @@ -59,10 +59,12 @@ static struct snd_soc_dai_driver ads117x_dai = { }; static struct snd_soc_codec_driver soc_codec_dev_ads117x = { - .dapm_widgets = ads117x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ads117x_dapm_widgets), - .dapm_routes = ads117x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ads117x_dapm_routes), + .component_driver = { + .dapm_widgets = ads117x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ads117x_dapm_widgets), + .dapm_routes = ads117x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ads117x_dapm_routes), + }, }; static int ads117x_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index 595d02d..1a9d233 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c @@ -163,7 +163,10 @@ static struct snd_soc_dai_driver ak4104_dai = { .stream_name = "Playback", .channels_min = 2, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE @@ -245,10 +248,12 @@ static struct snd_soc_codec_driver soc_codec_device_ak4104 = { .suspend = ak4104_soc_suspend, .resume = ak4104_soc_resume, - .dapm_widgets = ak4104_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4104_dapm_widgets), - .dapm_routes = ak4104_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ak4104_dapm_routes), + .component_driver = { + .dapm_widgets = ak4104_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4104_dapm_widgets), + .dapm_routes = ak4104_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ak4104_dapm_routes), + } }; static const struct regmap_config ak4104_regmap = { diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 54428c6..66cfffd 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -395,12 +395,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { .set_bias_level = ak4535_set_bias_level, .suspend_bias_off = true, - .controls = ak4535_snd_controls, - .num_controls = ARRAY_SIZE(ak4535_snd_controls), - .dapm_widgets = ak4535_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets), - .dapm_routes = ak4535_audio_map, - .num_dapm_routes = ARRAY_SIZE(ak4535_audio_map), + .component_driver = { + .controls = ak4535_snd_controls, + .num_controls = ARRAY_SIZE(ak4535_snd_controls), + .dapm_widgets = ak4535_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets), + .dapm_routes = ak4535_audio_map, + .num_dapm_routes = ARRAY_SIZE(ak4535_audio_map), + }, }; static int ak4535_i2c_probe(struct i2c_client *i2c, diff --git a/sound/soc/codecs/ak4554.c b/sound/soc/codecs/ak4554.c index 298dedc..b92c548 100644 --- a/sound/soc/codecs/ak4554.c +++ b/sound/soc/codecs/ak4554.c @@ -65,10 +65,12 @@ static struct snd_soc_dai_driver ak4554_dai = { }; static struct snd_soc_codec_driver soc_codec_dev_ak4554 = { - .dapm_widgets = ak4554_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4554_dapm_widgets), - .dapm_routes = ak4554_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ak4554_dapm_routes), + .component_driver = { + .dapm_widgets = ak4554_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4554_dapm_widgets), + .dapm_routes = ak4554_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ak4554_dapm_routes), + }, }; static int ak4554_soc_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index 97798d2..e819dd8 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -458,12 +458,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4613 = { .suspend = ak4613_suspend, .resume = ak4613_resume, .set_bias_level = ak4613_set_bias_level, - .controls = ak4613_snd_controls, - .num_controls = ARRAY_SIZE(ak4613_snd_controls), - .dapm_widgets = ak4613_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4613_dapm_widgets), - .dapm_routes = ak4613_intercon, - .num_dapm_routes = ARRAY_SIZE(ak4613_intercon), + .component_driver = { + .controls = ak4613_snd_controls, + .num_controls = ARRAY_SIZE(ak4613_snd_controls), + .dapm_widgets = ak4613_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4613_dapm_widgets), + .dapm_routes = ak4613_intercon, + .num_dapm_routes = ARRAY_SIZE(ak4613_intercon), + }, }; static void ak4613_parse_of(struct ak4613_priv *priv, diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index b14176f..c91717d 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -505,12 +505,14 @@ static struct snd_soc_dai_driver ak4641_dai[] = { }; static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { - .controls = ak4641_snd_controls, - .num_controls = ARRAY_SIZE(ak4641_snd_controls), - .dapm_widgets = ak4641_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4641_dapm_widgets), - .dapm_routes = ak4641_audio_map, - .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), + .component_driver = { + .controls = ak4641_snd_controls, + .num_controls = ARRAY_SIZE(ak4641_snd_controls), + .dapm_widgets = ak4641_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4641_dapm_widgets), + .dapm_routes = ak4641_audio_map, + .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), + }, .set_bias_level = ak4641_set_bias_level, .suspend_bias_off = true, }; diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index cc941d6..2609f95 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -555,12 +555,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { .suspend = ak4642_suspend, .resume = ak4642_resume, .set_bias_level = ak4642_set_bias_level, - .controls = ak4642_snd_controls, - .num_controls = ARRAY_SIZE(ak4642_snd_controls), - .dapm_widgets = ak4642_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets), - .dapm_routes = ak4642_intercon, - .num_dapm_routes = ARRAY_SIZE(ak4642_intercon), + .component_driver = { + .controls = ak4642_snd_controls, + .num_controls = ARRAY_SIZE(ak4642_snd_controls), + .dapm_widgets = ak4642_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets), + .dapm_routes = ak4642_intercon, + .num_dapm_routes = ARRAY_SIZE(ak4642_intercon), + }, }; static const struct regmap_config ak4642_regmap = { diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index c73a9f6..6088afa 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -612,12 +612,14 @@ static struct snd_soc_dai_driver ak4671_dai = { static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { .set_bias_level = ak4671_set_bias_level, - .controls = ak4671_snd_controls, - .num_controls = ARRAY_SIZE(ak4671_snd_controls), - .dapm_widgets = ak4671_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets), - .dapm_routes = ak4671_intercon, - .num_dapm_routes = ARRAY_SIZE(ak4671_intercon), + .component_driver = { + .controls = ak4671_snd_controls, + .num_controls = ARRAY_SIZE(ak4671_snd_controls), + .dapm_widgets = ak4671_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets), + .dapm_routes = ak4671_intercon, + .num_dapm_routes = ARRAY_SIZE(ak4671_intercon), + }, }; static const struct regmap_config ak4671_regmap = { diff --git a/sound/soc/codecs/ak5386.c b/sound/soc/codecs/ak5386.c index afa9536..0ef2df2 100644 --- a/sound/soc/codecs/ak5386.c +++ b/sound/soc/codecs/ak5386.c @@ -74,10 +74,12 @@ static struct snd_soc_codec_driver soc_codec_ak5386 = { .remove = ak5386_soc_remove, .suspend = ak5386_soc_suspend, .resume = ak5386_soc_resume, - .dapm_widgets = ak5386_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets), - .dapm_routes = ak5386_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ak5386_dapm_routes), + .component_driver = { + .dapm_widgets = ak5386_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets), + .dapm_routes = ak5386_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ak5386_dapm_routes), + }, }; static int ak5386_set_dai_fmt(struct snd_soc_dai *codec_dai, diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index 4d3ba33..adb80d8 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c @@ -1072,12 +1072,14 @@ static const struct snd_soc_codec_driver soc_codec_device_alc5632 = { .set_bias_level = alc5632_set_bias_level, .suspend_bias_off = true, - .controls = alc5632_snd_controls, - .num_controls = ARRAY_SIZE(alc5632_snd_controls), - .dapm_widgets = alc5632_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(alc5632_dapm_widgets), - .dapm_routes = alc5632_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes), + .component_driver = { + .controls = alc5632_snd_controls, + .num_controls = ARRAY_SIZE(alc5632_snd_controls), + .dapm_widgets = alc5632_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(alc5632_dapm_widgets), + .dapm_routes = alc5632_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes), + }, }; static const struct regmap_config alc5632_regmap = { diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index ecfdbfc..846ca07 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -109,7 +109,7 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w, break; } - return 0; + return arizona_out_ev(w, kcontrol, event); } static irqreturn_t arizona_thermal_warn(int irq, void *data) @@ -159,12 +159,14 @@ static irqreturn_t arizona_thermal_shutdown(int irq, void *data) static const struct snd_soc_dapm_widget arizona_spkl = SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM, ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev, - SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU); + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD); static const struct snd_soc_dapm_widget arizona_spkr = SND_SOC_DAPM_PGA_E("OUT4R", SND_SOC_NOPM, ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev, - SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU); + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD); int arizona_init_spk(struct snd_soc_codec *codec) { @@ -864,6 +866,7 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); + struct arizona *arizona = priv->arizona; switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -877,6 +880,18 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, priv->out_up_pending++; priv->out_up_delay += 17; break; + case ARIZONA_OUT4L_ENA_SHIFT: + case ARIZONA_OUT4R_ENA_SHIFT: + priv->out_up_pending++; + switch (arizona->type) { + case WM5102: + case WM8997: + break; + default: + priv->out_up_delay += 10; + break; + } + break; default: break; } @@ -889,8 +904,12 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, case ARIZONA_OUT2R_ENA_SHIFT: case ARIZONA_OUT3L_ENA_SHIFT: case ARIZONA_OUT3R_ENA_SHIFT: + case ARIZONA_OUT4L_ENA_SHIFT: + case ARIZONA_OUT4R_ENA_SHIFT: priv->out_up_pending--; - if (!priv->out_up_pending) { + if (!priv->out_up_pending && priv->out_up_delay) { + dev_dbg(codec->dev, "Power up delay: %d\n", + priv->out_up_delay); msleep(priv->out_up_delay); priv->out_up_delay = 0; } @@ -911,6 +930,21 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, priv->out_down_pending++; priv->out_down_delay++; break; + case ARIZONA_OUT4L_ENA_SHIFT: + case ARIZONA_OUT4R_ENA_SHIFT: + priv->out_down_pending++; + switch (arizona->type) { + case WM5102: + case WM8997: + break; + case WM8998: + case WM1814: + priv->out_down_delay += 5; + break; + default: + priv->out_down_delay++; + break; + } default: break; } @@ -923,8 +957,12 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, case ARIZONA_OUT2R_ENA_SHIFT: case ARIZONA_OUT3L_ENA_SHIFT: case ARIZONA_OUT3R_ENA_SHIFT: + case ARIZONA_OUT4L_ENA_SHIFT: + case ARIZONA_OUT4R_ENA_SHIFT: priv->out_down_pending--; - if (!priv->out_down_pending) { + if (!priv->out_down_pending && priv->out_down_delay) { + dev_dbg(codec->dev, "Power down delay: %d\n", + priv->out_down_delay); msleep(priv->out_down_delay); priv->out_down_delay = 0; } @@ -1920,8 +1958,8 @@ static struct { struct arizona_fll_cfg { int n; - int theta; - int lambda; + unsigned int theta; + unsigned int lambda; int refdiv; int outdiv; int fratio; @@ -2188,13 +2226,13 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base, ARIZONA_FLL1_CTRL_UPD | cfg->n); } -static int arizona_is_enabled_fll(struct arizona_fll *fll) +static int arizona_is_enabled_fll(struct arizona_fll *fll, int base) { struct arizona *arizona = fll->arizona; unsigned int reg; int ret; - ret = regmap_read(arizona->regmap, fll->base + 1, ®); + ret = regmap_read(arizona->regmap, base + 1, ®); if (ret != 0) { arizona_fll_err(fll, "Failed to read current state: %d\n", ret); @@ -2208,21 +2246,24 @@ static int arizona_enable_fll(struct arizona_fll *fll) { struct arizona *arizona = fll->arizona; bool use_sync = false; - int already_enabled = arizona_is_enabled_fll(fll); + int already_enabled = arizona_is_enabled_fll(fll, fll->base); + int sync_enabled = arizona_is_enabled_fll(fll, fll->base + 0x10); struct arizona_fll_cfg cfg; int i; unsigned int val; if (already_enabled < 0) return already_enabled; + if (sync_enabled < 0) + return sync_enabled; if (already_enabled) { /* Facilitate smooth refclk across the transition */ - regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9, - ARIZONA_FLL1_GAIN_MASK, 0); regmap_update_bits(fll->arizona->regmap, fll->base + 1, ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN); udelay(32); + regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9, + ARIZONA_FLL1_GAIN_MASK, 0); } /* @@ -2233,6 +2274,10 @@ static int arizona_enable_fll(struct arizona_fll *fll) fll->ref_src != fll->sync_src) { arizona_calc_fll(fll, &cfg, fll->ref_freq, false); + /* Ref path hardcodes lambda to 65536 when sync is on */ + if (fll->sync_src >= 0 && cfg.lambda) + cfg.theta = (cfg.theta * (1 << 16)) / cfg.lambda; + arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src, false); if (fll->sync_src >= 0) { @@ -2255,6 +2300,9 @@ static int arizona_enable_fll(struct arizona_fll *fll) return -EINVAL; } + if (already_enabled && !!sync_enabled != use_sync) + arizona_fll_warn(fll, "Synchroniser changed on active FLL\n"); + /* * Increase the bandwidth if we're not using a low frequency * sync source. @@ -2268,14 +2316,14 @@ static int arizona_enable_fll(struct arizona_fll *fll) ARIZONA_FLL1_SYNC_BW); if (!already_enabled) - pm_runtime_get(arizona->dev); + pm_runtime_get_sync(arizona->dev); - regmap_update_bits_async(arizona->regmap, fll->base + 1, - ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); if (use_sync) regmap_update_bits_async(arizona->regmap, fll->base + 0x11, ARIZONA_FLL1_SYNC_ENA, ARIZONA_FLL1_SYNC_ENA); + regmap_update_bits_async(arizona->regmap, fll->base + 1, + ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); if (already_enabled) regmap_update_bits_async(arizona->regmap, fll->base + 1, diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 69da1ef..850aa33 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -190,20 +190,21 @@ extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; #define ARIZONA_DSP_ROUTES(name) \ { name, NULL, name " Preloader"}, \ - { name " Preloader", NULL, name " Aux 1" }, \ - { name " Preloader", NULL, name " Aux 2" }, \ - { name " Preloader", NULL, name " Aux 3" }, \ - { name " Preloader", NULL, name " Aux 4" }, \ - { name " Preloader", NULL, name " Aux 5" }, \ - { name " Preloader", NULL, name " Aux 6" }, \ + { name " Preloader", NULL, "SYSCLK" }, \ + { name, NULL, name " Aux 1" }, \ + { name, NULL, name " Aux 2" }, \ + { name, NULL, name " Aux 3" }, \ + { name, NULL, name " Aux 4" }, \ + { name, NULL, name " Aux 5" }, \ + { name, NULL, name " Aux 6" }, \ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \ - ARIZONA_MIXER_ROUTES(name " Preloader", name "L"), \ - ARIZONA_MIXER_ROUTES(name " Preloader", name "R") + ARIZONA_MIXER_ROUTES(name, name "L"), \ + ARIZONA_MIXER_ROUTES(name, name "R") #define ARIZONA_EQ_CONTROL(xname, xbase) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c index 2a8d0ee..8014e69 100644 --- a/sound/soc/codecs/bt-sco.c +++ b/sound/soc/codecs/bt-sco.c @@ -63,10 +63,12 @@ static struct snd_soc_dai_driver bt_sco_dai[] = { }; static struct snd_soc_codec_driver soc_codec_dev_bt_sco = { - .dapm_widgets = bt_sco_widgets, - .num_dapm_widgets = ARRAY_SIZE(bt_sco_widgets), - .dapm_routes = bt_sco_routes, - .num_dapm_routes = ARRAY_SIZE(bt_sco_routes), + .component_driver = { + .dapm_widgets = bt_sco_widgets, + .num_dapm_widgets = ARRAY_SIZE(bt_sco_widgets), + .dapm_routes = bt_sco_routes, + .num_dapm_routes = ARRAY_SIZE(bt_sco_routes), + }, }; static int bt_sco_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index 1c895a5..7a2d9a2 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c @@ -131,8 +131,10 @@ static struct regmap *cq93vc_get_regmap(struct device *dev) static struct snd_soc_codec_driver soc_codec_dev_cq93vc = { .set_bias_level = cq93vc_set_bias_level, .get_regmap = cq93vc_get_regmap, - .controls = cq93vc_snd_controls, - .num_controls = ARRAY_SIZE(cq93vc_snd_controls), + .component_driver = { + .controls = cq93vc_snd_controls, + .num_controls = ARRAY_SIZE(cq93vc_snd_controls), + }, }; static int cq93vc_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index 287d137..7e98062 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c @@ -231,13 +231,14 @@ static int cs35l32_codec_set_sysclk(struct snd_soc_codec *codec, static const struct snd_soc_codec_driver soc_codec_dev_cs35l32 = { .set_sysclk = cs35l32_codec_set_sysclk, - .dapm_widgets = cs35l32_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs35l32_dapm_widgets), - .dapm_routes = cs35l32_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs35l32_audio_map), - - .controls = cs35l32_snd_controls, - .num_controls = ARRAY_SIZE(cs35l32_snd_controls), + .component_driver = { + .controls = cs35l32_snd_controls, + .num_controls = ARRAY_SIZE(cs35l32_snd_controls), + .dapm_widgets = cs35l32_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs35l32_dapm_widgets), + .dapm_routes = cs35l32_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs35l32_audio_map), + }, }; /* Current and threshold powerup sequence Pg37 in datasheet */ diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c index 6f9c1ad..6df29fa 100644 --- a/sound/soc/codecs/cs35l33.c +++ b/sound/soc/codecs/cs35l33.c @@ -837,13 +837,14 @@ static struct snd_soc_codec_driver soc_codec_dev_cs35l33 = { .set_bias_level = cs35l33_set_bias_level, .set_sysclk = cs35l33_codec_set_sysclk, - .dapm_widgets = cs35l33_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs35l33_dapm_widgets), - .dapm_routes = cs35l33_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs35l33_audio_map), - .controls = cs35l33_snd_controls, - .num_controls = ARRAY_SIZE(cs35l33_snd_controls), - + .component_driver = { + .controls = cs35l33_snd_controls, + .num_controls = ARRAY_SIZE(cs35l33_snd_controls), + .dapm_widgets = cs35l33_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs35l33_dapm_widgets), + .dapm_routes = cs35l33_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs35l33_audio_map), + }, .idle_bias_off = true, }; diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 55db19d..fd966bb 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c @@ -547,13 +547,14 @@ static struct snd_soc_dai_driver cs4265_dai[] = { static const struct snd_soc_codec_driver soc_codec_cs4265 = { .set_bias_level = cs4265_set_bias_level, - .dapm_widgets = cs4265_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs4265_dapm_widgets), - .dapm_routes = cs4265_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs4265_audio_map), - - .controls = cs4265_snd_controls, - .num_controls = ARRAY_SIZE(cs4265_snd_controls), + .component_driver = { + .controls = cs4265_snd_controls, + .num_controls = ARRAY_SIZE(cs4265_snd_controls), + .dapm_widgets = cs4265_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs4265_dapm_widgets), + .dapm_routes = cs4265_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs4265_audio_map), + }, }; static const struct regmap_config cs4265_regmap = { diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index e07807d..18baea2 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -617,12 +617,14 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { .suspend = cs4270_soc_suspend, .resume = cs4270_soc_resume, - .controls = cs4270_snd_controls, - .num_controls = ARRAY_SIZE(cs4270_snd_controls), - .dapm_widgets = cs4270_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs4270_dapm_widgets), - .dapm_routes = cs4270_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(cs4270_dapm_routes), + .component_driver = { + .controls = cs4270_snd_controls, + .num_controls = ARRAY_SIZE(cs4270_snd_controls), + .dapm_widgets = cs4270_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs4270_dapm_widgets), + .dapm_routes = cs4270_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs4270_dapm_routes), + }, }; /* diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 0c0010b..8c0f3b8 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -645,12 +645,14 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { .suspend = cs4271_soc_suspend, .resume = cs4271_soc_resume, - .controls = cs4271_snd_controls, - .num_controls = ARRAY_SIZE(cs4271_snd_controls), - .dapm_widgets = cs4271_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs4271_dapm_widgets), - .dapm_routes = cs4271_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes), + .component_driver = { + .controls = cs4271_snd_controls, + .num_controls = ARRAY_SIZE(cs4271_snd_controls), + .dapm_widgets = cs4271_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs4271_dapm_widgets), + .dapm_routes = cs4271_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes), + }, }; static int cs4271_common_probe(struct device *dev, diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 35488f1..96cfe38 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -507,12 +507,14 @@ static int cs42l51_codec_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { .probe = cs42l51_codec_probe, - .controls = cs42l51_snd_controls, - .num_controls = ARRAY_SIZE(cs42l51_snd_controls), - .dapm_widgets = cs42l51_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs42l51_dapm_widgets), - .dapm_routes = cs42l51_routes, - .num_dapm_routes = ARRAY_SIZE(cs42l51_routes), + .component_driver = { + .controls = cs42l51_snd_controls, + .num_controls = ARRAY_SIZE(cs42l51_snd_controls), + .dapm_widgets = cs42l51_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42l51_dapm_widgets), + .dapm_routes = cs42l51_routes, + .num_dapm_routes = ARRAY_SIZE(cs42l51_routes), + }, }; const struct regmap_config cs42l51_regmap = { diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 47b97fc..0d9c4a5 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -1056,13 +1056,14 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs42l52 = { .set_bias_level = cs42l52_set_bias_level, .suspend_bias_off = true, - .dapm_widgets = cs42l52_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs42l52_dapm_widgets), - .dapm_routes = cs42l52_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs42l52_audio_map), - - .controls = cs42l52_snd_controls, - .num_controls = ARRAY_SIZE(cs42l52_snd_controls), + .component_driver = { + .controls = cs42l52_snd_controls, + .num_controls = ARRAY_SIZE(cs42l52_snd_controls), + .dapm_widgets = cs42l52_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42l52_dapm_widgets), + .dapm_routes = cs42l52_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs42l52_audio_map), + }, }; /* Current and threshold powerup sequence Pg37 */ diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index eec1ff8..54c1768 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -1121,13 +1121,14 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs42l56 = { .set_bias_level = cs42l56_set_bias_level, .suspend_bias_off = true, - .dapm_widgets = cs42l56_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs42l56_dapm_widgets), - .dapm_routes = cs42l56_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs42l56_audio_map), - - .controls = cs42l56_snd_controls, - .num_controls = ARRAY_SIZE(cs42l56_snd_controls), + .component_driver = { + .controls = cs42l56_snd_controls, + .num_controls = ARRAY_SIZE(cs42l56_snd_controls), + .dapm_widgets = cs42l56_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42l56_dapm_widgets), + .dapm_routes = cs42l56_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs42l56_audio_map), + }, }; static const struct regmap_config cs42l56_regmap = { diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 42a8fd4..71ba560 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -794,7 +794,7 @@ struct cs42l73_mclk_div { u8 mmcc; }; -static struct cs42l73_mclk_div cs42l73_mclk_coeffs[] = { +static const struct cs42l73_mclk_div cs42l73_mclk_coeffs[] = { /* MCLK, Sample Rate, xMMCC[5:0] */ {5644800, 11025, 0x30}, {5644800, 22050, 0x20}, @@ -844,7 +844,7 @@ struct cs42l73_mclkx_div { u8 mclkdiv; }; -static struct cs42l73_mclkx_div cs42l73_mclkx_coeffs[] = { +static const struct cs42l73_mclkx_div cs42l73_mclkx_coeffs[] = { {5644800, 1, 0}, /* 5644800 */ {6000000, 1, 0}, /* 6000000 */ {6144000, 1, 0}, /* 6144000 */ @@ -1257,13 +1257,14 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs42l73 = { .set_bias_level = cs42l73_set_bias_level, .suspend_bias_off = true, - .dapm_widgets = cs42l73_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets), - .dapm_routes = cs42l73_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs42l73_audio_map), - - .controls = cs42l73_snd_controls, - .num_controls = ARRAY_SIZE(cs42l73_snd_controls), + .component_driver = { + .controls = cs42l73_snd_controls, + .num_controls = ARRAY_SIZE(cs42l73_snd_controls), + .dapm_widgets = cs42l73_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets), + .dapm_routes = cs42l73_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs42l73_audio_map), + }, }; static const struct regmap_config cs42l73_regmap = { diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index 1179101..b4d8737 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -411,12 +411,14 @@ static const struct snd_soc_codec_driver cs42xx8_driver = { .probe = cs42xx8_codec_probe, .idle_bias_off = true, - .controls = cs42xx8_snd_controls, - .num_controls = ARRAY_SIZE(cs42xx8_snd_controls), - .dapm_widgets = cs42xx8_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs42xx8_dapm_widgets), - .dapm_routes = cs42xx8_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(cs42xx8_dapm_routes), + .component_driver = { + .controls = cs42xx8_snd_controls, + .num_controls = ARRAY_SIZE(cs42xx8_snd_controls), + .dapm_widgets = cs42xx8_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42xx8_dapm_widgets), + .dapm_routes = cs42xx8_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs42xx8_dapm_routes), + }, }; const struct cs42xx8_driver_data cs42448_data = { diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c index 0ac8fc5..231ca93 100644 --- a/sound/soc/codecs/cs4349.c +++ b/sound/soc/codecs/cs4349.c @@ -256,13 +256,14 @@ static struct snd_soc_dai_driver cs4349_dai = { }; static struct snd_soc_codec_driver soc_codec_dev_cs4349 = { - .controls = cs4349_snd_controls, - .num_controls = ARRAY_SIZE(cs4349_snd_controls), - - .dapm_widgets = cs4349_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs4349_dapm_widgets), - .dapm_routes = cs4349_routes, - .num_dapm_routes = ARRAY_SIZE(cs4349_routes), + .component_driver = { + .controls = cs4349_snd_controls, + .num_controls = ARRAY_SIZE(cs4349_snd_controls), + .dapm_widgets = cs4349_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs4349_dapm_widgets), + .dapm_routes = cs4349_routes, + .num_dapm_routes = ARRAY_SIZE(cs4349_routes), + }, }; static const struct regmap_config cs4349_regmap = { diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index 954a4f5..5b22564 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -746,6 +746,16 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = { { "IN2L", NULL, "SYSCLK" }, { "IN2R", NULL, "SYSCLK" }, + { "ASRC1L", NULL, "SYSCLK" }, + { "ASRC1R", NULL, "SYSCLK" }, + { "ASRC2L", NULL, "SYSCLK" }, + { "ASRC2R", NULL, "SYSCLK" }, + + { "ASRC1L", NULL, "ASYNCCLK" }, + { "ASRC1R", NULL, "ASYNCCLK" }, + { "ASRC2L", NULL, "ASYNCCLK" }, + { "ASRC2R", NULL, "ASYNCCLK" }, + { "MICBIAS1", NULL, "MICVDD" }, { "MICBIAS2", NULL, "MICVDD" }, @@ -804,7 +814,6 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = { { "AIF3 Capture", NULL, "SYSCLK" }, { "Voice Control DSP", NULL, "DSP3" }, - { "Voice Control DSP", NULL, "SYSCLK" }, { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" }, @@ -813,7 +822,6 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = { { "IN2R PGA", NULL, "IN2R" }, { "Audio Trace DSP", NULL, "DSP2" }, - { "Audio Trace DSP", NULL, "SYSCLK" }, ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), @@ -1190,12 +1198,14 @@ static struct snd_soc_codec_driver soc_codec_dev_cs47l24 = { .set_sysclk = arizona_set_sysclk, .set_pll = cs47l24_set_fll, - .controls = cs47l24_snd_controls, - .num_controls = ARRAY_SIZE(cs47l24_snd_controls), - .dapm_widgets = cs47l24_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs47l24_dapm_widgets), - .dapm_routes = cs47l24_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(cs47l24_dapm_routes), + .component_driver = { + .controls = cs47l24_snd_controls, + .num_controls = ARRAY_SIZE(cs47l24_snd_controls), + .dapm_widgets = cs47l24_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs47l24_dapm_widgets), + .dapm_routes = cs47l24_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs47l24_dapm_routes), + }, }; static struct snd_compr_ops cs47l24_compr_ops = { diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index 2c0d9c4..cb47fb5 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -466,7 +466,7 @@ struct cs53l30_mclk_div { u8 mclk_int_scale; }; -static struct cs53l30_mclk_div cs53l30_mclk_coeffs[] = { +static const struct cs53l30_mclk_div cs53l30_mclk_coeffs[] = { /* NOTE: Enable MCLK_INT_SCALE to save power. */ /* MCLK, Sample Rate, asp_rate, internal_fs_ratio, mclk_int_scale */ @@ -511,7 +511,7 @@ struct cs53l30_mclkx_div { u8 mclkdiv; }; -static struct cs53l30_mclkx_div cs53l30_mclkx_coeffs[] = { +static const struct cs53l30_mclkx_div cs53l30_mclkx_coeffs[] = { {5644800, 1, CS53L30_MCLK_DIV_BY_1}, {6000000, 1, CS53L30_MCLK_DIV_BY_1}, {6144000, 1, CS53L30_MCLK_DIV_BY_1}, @@ -897,13 +897,14 @@ static struct snd_soc_codec_driver cs53l30_driver = { .set_bias_level = cs53l30_set_bias_level, .idle_bias_off = true, - .dapm_widgets = cs53l30_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs53l30_dapm_widgets), - .dapm_routes = cs53l30_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(cs53l30_dapm_routes), - - .controls = cs53l30_snd_controls, - .num_controls = ARRAY_SIZE(cs53l30_snd_controls), + .component_driver = { + .controls = cs53l30_snd_controls, + .num_controls = ARRAY_SIZE(cs53l30_snd_controls), + .dapm_widgets = cs53l30_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs53l30_dapm_widgets), + .dapm_routes = cs53l30_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs53l30_dapm_routes), + }, }; static struct regmap_config cs53l30_regmap = { @@ -999,8 +1000,8 @@ static int cs53l30_i2c_probe(struct i2c_client *client, /* Check if MCLK provided */ cs53l30->mclk = devm_clk_get(dev, "mclk"); if (IS_ERR(cs53l30->mclk)) { - if (PTR_ERR(cs53l30->mclk) == -EPROBE_DEFER) { - ret = -EPROBE_DEFER; + if (PTR_ERR(cs53l30->mclk) != -ENOENT) { + ret = PTR_ERR(cs53l30->mclk); goto error; } /* Otherwise mark the mclk pointer to NULL */ diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index fb3885f..2c12471 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -407,10 +407,12 @@ static struct snd_soc_codec_driver cx20442_codec_dev = { .reg_word_size = sizeof(u8), .read = cx20442_read_reg_cache, .write = cx20442_write, - .dapm_widgets = cx20442_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cx20442_dapm_widgets), - .dapm_routes = cx20442_audio_map, - .num_dapm_routes = ARRAY_SIZE(cx20442_audio_map), + .component_driver = { + .dapm_widgets = cx20442_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cx20442_dapm_widgets), + .dapm_routes = cx20442_audio_map, + .num_dapm_routes = ARRAY_SIZE(cx20442_audio_map), + }, }; static int cx20442_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index af23a61..17053df 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -1167,13 +1167,14 @@ static int da7210_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_da7210 = { .probe = da7210_probe, - .controls = da7210_snd_controls, - .num_controls = ARRAY_SIZE(da7210_snd_controls), - - .dapm_widgets = da7210_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da7210_dapm_widgets), - .dapm_routes = da7210_audio_map, - .num_dapm_routes = ARRAY_SIZE(da7210_audio_map), + .component_driver = { + .controls = da7210_snd_controls, + .num_controls = ARRAY_SIZE(da7210_snd_controls), + .dapm_widgets = da7210_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da7210_dapm_widgets), + .dapm_routes = da7210_audio_map, + .num_dapm_routes = ARRAY_SIZE(da7210_audio_map), + }, }; #if IS_ENABLED(CONFIG_I2C) diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index bcf1834..12da558 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -750,11 +750,18 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, DA7213_PC_COUNT, DA7213_PC_FREERUN_MASK, 0); - /* Slave mode, if SRM not enabled no need for status checks */ + /* If SRM not enabled then nothing more to do */ pll_ctrl = snd_soc_read(codec, DA7213_PLL_CTRL); if (!(pll_ctrl & DA7213_PLL_SRM_EN)) return 0; + /* Assist 32KHz mode PLL lock */ + if (pll_ctrl & DA7213_PLL_32K_MODE) { + snd_soc_write(codec, 0xF0, 0x8B); + snd_soc_write(codec, 0xF2, 0x03); + snd_soc_write(codec, 0xF0, 0x00); + } + /* Check SRM has locked */ do { pll_status = snd_soc_read(codec, DA7213_PLL_STATUS); @@ -771,6 +778,14 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w, return 0; case SND_SOC_DAPM_POST_PMD: + /* Revert 32KHz PLL lock udpates if applied previously */ + pll_ctrl = snd_soc_read(codec, DA7213_PLL_CTRL); + if (pll_ctrl & DA7213_PLL_32K_MODE) { + snd_soc_write(codec, 0xF0, 0x8B); + snd_soc_write(codec, 0xF2, 0x01); + snd_soc_write(codec, 0xF0, 0x00); + } + /* PC free-running */ snd_soc_update_bits(codec, DA7213_PC_COUNT, DA7213_PC_FREERUN_MASK, @@ -1297,10 +1312,13 @@ static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai, switch (clk_id) { case DA7213_CLKSRC_MCLK: - da7213->mclk_squarer_en = false; + snd_soc_update_bits(codec, DA7213_PLL_CTRL, + DA7213_PLL_MCLK_SQR_EN, 0); break; case DA7213_CLKSRC_MCLK_SQR: - da7213->mclk_squarer_en = true; + snd_soc_update_bits(codec, DA7213_PLL_CTRL, + DA7213_PLL_MCLK_SQR_EN, + DA7213_PLL_MCLK_SQR_EN); break; default: dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id); @@ -1324,7 +1342,7 @@ static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai, return 0; } -/* Supported PLL input frequencies are 5MHz - 54MHz. */ +/* Supported PLL input frequencies are 32KHz, 5MHz - 54MHz. */ static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, int source, unsigned int fref, unsigned int fout) { @@ -1336,22 +1354,26 @@ static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, u32 freq_ref; u64 frac_div; - /* Reset PLL configuration */ - snd_soc_write(codec, DA7213_PLL_CTRL, 0); - - pll_ctrl = 0; - /* Workout input divider based on MCLK rate */ if (da7213->mclk_rate == 32768) { + if (!da7213->master) { + dev_err(codec->dev, + "32KHz only valid if codec is clock master\n"); + return -EINVAL; + } + /* 32KHz PLL Mode */ indiv_bits = DA7213_PLL_INDIV_9_TO_18_MHZ; indiv = DA7213_PLL_INDIV_9_TO_18_MHZ_VAL; + source = DA7213_SYSCLK_PLL_32KHZ; freq_ref = 3750000; - pll_ctrl |= DA7213_PLL_32K_MODE; + } else { - /* 5 - 54MHz MCLK */ if (da7213->mclk_rate < 5000000) { - goto pll_err; + dev_err(codec->dev, + "PLL input clock %d below valid range\n", + da7213->mclk_rate); + return -EINVAL; } else if (da7213->mclk_rate <= 9000000) { indiv_bits = DA7213_PLL_INDIV_5_TO_9_MHZ; indiv = DA7213_PLL_INDIV_5_TO_9_MHZ_VAL; @@ -1365,32 +1387,44 @@ static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, indiv_bits = DA7213_PLL_INDIV_36_TO_54_MHZ; indiv = DA7213_PLL_INDIV_36_TO_54_MHZ_VAL; } else { - goto pll_err; + dev_err(codec->dev, + "PLL input clock %d above valid range\n", + da7213->mclk_rate); + return -EINVAL; } freq_ref = (da7213->mclk_rate / indiv); } - pll_ctrl |= indiv_bits; + pll_ctrl = indiv_bits; - /* PLL Bypass mode */ - if (source == DA7213_SYSCLK_MCLK) { - snd_soc_write(codec, DA7213_PLL_CTRL, pll_ctrl); + /* Configure PLL */ + switch (source) { + case DA7213_SYSCLK_MCLK: + snd_soc_update_bits(codec, DA7213_PLL_CTRL, + DA7213_PLL_INDIV_MASK | + DA7213_PLL_MODE_MASK, pll_ctrl); return 0; - } + case DA7213_SYSCLK_PLL: + break; + case DA7213_SYSCLK_PLL_SRM: + pll_ctrl |= DA7213_PLL_SRM_EN; + fout = DA7213_PLL_FREQ_OUT_94310400; + break; + case DA7213_SYSCLK_PLL_32KHZ: + if (da7213->mclk_rate != 32768) { + dev_err(codec->dev, + "32KHz mode only valid with 32KHz MCLK\n"); + return -EINVAL; + } - /* - * If Codec is slave and SRM enabled, - * freq_out is (98304000 + 90316800)/2 = 94310400 - */ - if (!da7213->master && da7213->srm_en) { + pll_ctrl |= DA7213_PLL_32K_MODE | DA7213_PLL_SRM_EN; fout = DA7213_PLL_FREQ_OUT_94310400; - pll_ctrl |= DA7213_PLL_SRM_EN; + break; + default: + dev_err(codec->dev, "Invalid PLL config\n"); + return -EINVAL; } - /* Enable MCLK squarer if required */ - if (da7213->mclk_squarer_en) - pll_ctrl |= DA7213_PLL_MCLK_SQR_EN; - /* Calculate dividers for PLL */ pll_integer = fout / freq_ref; frac_div = (u64)(fout % freq_ref) * 8192ULL; @@ -1405,14 +1439,19 @@ static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, /* Enable PLL */ pll_ctrl |= DA7213_PLL_EN; - snd_soc_write(codec, DA7213_PLL_CTRL, pll_ctrl); + snd_soc_update_bits(codec, DA7213_PLL_CTRL, + DA7213_PLL_INDIV_MASK | DA7213_PLL_MODE_MASK, + pll_ctrl); + + /* Assist 32KHz mode PLL lock */ + if (source == DA7213_SYSCLK_PLL_32KHZ) { + snd_soc_write(codec, 0xF0, 0x8B); + snd_soc_write(codec, 0xF1, 0x03); + snd_soc_write(codec, 0xF1, 0x01); + snd_soc_write(codec, 0xF0, 0x00); + } return 0; - -pll_err: - dev_err(codec_dai->dev, "Unsupported PLL input frequency %d\n", - da7213->mclk_rate); - return -EINVAL; } /* DAI operations */ @@ -1454,11 +1493,10 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: break; - case SND_SOC_BIAS_STANDBY: - if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { - /* MCLK */ + case SND_SOC_BIAS_PREPARE: + /* Enable MCLK for transition to ON state */ + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) { if (da7213->mclk) { ret = clk_prepare_enable(da7213->mclk); if (ret) { @@ -1467,21 +1505,24 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, return ret; } } - + } + break; + case SND_SOC_BIAS_STANDBY: + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { /* Enable VMID reference & master bias */ snd_soc_update_bits(codec, DA7213_REFERENCES, DA7213_VMID_EN | DA7213_BIAS_EN, DA7213_VMID_EN | DA7213_BIAS_EN); + } else { + /* Remove MCLK */ + if (da7213->mclk) + clk_disable_unprepare(da7213->mclk); } break; case SND_SOC_BIAS_OFF: /* Disable VMID reference & master bias */ snd_soc_update_bits(codec, DA7213_REFERENCES, DA7213_VMID_EN | DA7213_BIAS_EN, 0); - - /* MCLK */ - if (da7213->mclk) - clk_disable_unprepare(da7213->mclk); break; } return 0; @@ -1605,9 +1646,6 @@ static int da7213_probe(struct snd_soc_codec *codec) DA7213_ALC_CALIB_MODE_MAN, 0); da7213->alc_calib_auto = true; - /* Default to using SRM for slave mode */ - da7213->srm_en = true; - /* Default PC counter to free-running */ snd_soc_update_bits(codec, DA7213_PC_COUNT, DA7213_PC_FREERUN_MASK, DA7213_PC_FREERUN_MASK); @@ -1740,13 +1778,14 @@ static struct snd_soc_codec_driver soc_codec_dev_da7213 = { .probe = da7213_probe, .set_bias_level = da7213_set_bias_level, - .controls = da7213_snd_controls, - .num_controls = ARRAY_SIZE(da7213_snd_controls), - - .dapm_widgets = da7213_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da7213_dapm_widgets), - .dapm_routes = da7213_audio_map, - .num_dapm_routes = ARRAY_SIZE(da7213_audio_map), + .component_driver = { + .controls = da7213_snd_controls, + .num_controls = ARRAY_SIZE(da7213_snd_controls), + .dapm_widgets = da7213_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da7213_dapm_widgets), + .dapm_routes = da7213_audio_map, + .num_dapm_routes = ARRAY_SIZE(da7213_audio_map), + }, }; static const struct regmap_config da7213_regmap_config = { diff --git a/sound/soc/codecs/da7213.h b/sound/soc/codecs/da7213.h index fbb7a35..16ef56f 100644 --- a/sound/soc/codecs/da7213.h +++ b/sound/soc/codecs/da7213.h @@ -172,6 +172,7 @@ #define DA7213_PLL_32K_MODE (0x1 << 5) #define DA7213_PLL_SRM_EN (0x1 << 6) #define DA7213_PLL_EN (0x1 << 7) +#define DA7213_PLL_MODE_MASK (0x7 << 5) /* DA7213_DAI_CLK_MODE = 0x28 */ #define DA7213_DAI_BCLKS_PER_WCLK_32 (0x0 << 0) @@ -499,8 +500,6 @@ #define DA7213_ALC_AVG_ITERATIONS 5 /* PLL related */ -#define DA7213_SYSCLK_MCLK 0 -#define DA7213_SYSCLK_PLL 1 #define DA7213_PLL_FREQ_OUT_90316800 90316800 #define DA7213_PLL_FREQ_OUT_98304000 98304000 #define DA7213_PLL_FREQ_OUT_94310400 94310400 @@ -515,6 +514,13 @@ enum da7213_clk_src { DA7213_CLKSRC_MCLK_SQR, }; +enum da7213_sys_clk { + DA7213_SYSCLK_MCLK = 0, + DA7213_SYSCLK_PLL, + DA7213_SYSCLK_PLL_SRM, + DA7213_SYSCLK_PLL_32KHZ +}; + /* Codec private data */ struct da7213_priv { struct regmap *regmap; @@ -522,8 +528,6 @@ struct da7213_priv { unsigned int mclk_rate; int clk_src; bool master; - bool mclk_squarer_en; - bool srm_en; bool alc_calib_auto; bool alc_en; struct da7213_platform_data *pdata; diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index 99ce23e..c69e976 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -1819,7 +1819,7 @@ static int da7218_set_dai_sysclk(struct snd_soc_dai *codec_dai, if (da7218->mclk_rate == freq) return 0; - if (((freq < 2000000) && (freq != 32768)) || (freq > 54000000)) { + if ((freq < 2000000) || (freq > 54000000)) { dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", freq); return -EINVAL; @@ -1866,11 +1866,8 @@ static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, u32 freq_ref; u64 frac_div; - /* Verify 32KHz, 2MHz - 54MHz MCLK provided, and set input divider */ - if (da7218->mclk_rate == 32768) { - indiv_bits = DA7218_PLL_INDIV_9_TO_18_MHZ; - indiv = DA7218_PLL_INDIV_9_TO_18_MHZ_VAL; - } else if (da7218->mclk_rate < 2000000) { + /* Verify 2MHz - 54MHz MCLK provided, and set input divider */ + if (da7218->mclk_rate < 2000000) { dev_err(codec->dev, "PLL input clock %d below valid range\n", da7218->mclk_rate); return -EINVAL; @@ -1911,9 +1908,6 @@ static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, case DA7218_SYSCLK_PLL_SRM: pll_ctrl |= DA7218_PLL_MODE_SRM; break; - case DA7218_SYSCLK_PLL_32KHZ: - pll_ctrl |= DA7218_PLL_MODE_32KHZ; - break; default: dev_err(codec->dev, "Invalid PLL config\n"); return -EINVAL; @@ -2589,20 +2583,22 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: break; - case SND_SOC_BIAS_STANDBY: - if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { - /* MCLK */ + case SND_SOC_BIAS_PREPARE: + /* Enable MCLK for transition to ON state */ + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) { if (da7218->mclk) { ret = clk_prepare_enable(da7218->mclk); if (ret) { - dev_err(codec->dev, - "Failed to enable mclk\n"); + dev_err(codec->dev, "Failed to enable mclk\n"); return ret; } } + } + break; + case SND_SOC_BIAS_STANDBY: + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { /* Master bias */ snd_soc_update_bits(codec, DA7218_REFERENCES, DA7218_BIAS_EN_MASK, @@ -2612,6 +2608,10 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec, snd_soc_update_bits(codec, DA7218_LDO_CTRL, DA7218_LDO_EN_MASK, DA7218_LDO_EN_MASK); + } else { + /* Remove MCLK */ + if (da7218->mclk) + clk_disable_unprepare(da7218->mclk); } break; case SND_SOC_BIAS_OFF: @@ -2625,10 +2625,6 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec, snd_soc_update_bits(codec, DA7218_REFERENCES, DA7218_BIAS_EN_MASK, 0); } - - /* MCLK */ - if (da7218->mclk) - clk_disable_unprepare(da7218->mclk); break; } @@ -3045,13 +3041,14 @@ static struct snd_soc_codec_driver soc_codec_dev_da7218 = { .resume = da7218_resume, .set_bias_level = da7218_set_bias_level, - .controls = da7218_snd_controls, - .num_controls = ARRAY_SIZE(da7218_snd_controls), - - .dapm_widgets = da7218_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da7218_dapm_widgets), - .dapm_routes = da7218_audio_map, - .num_dapm_routes = ARRAY_SIZE(da7218_audio_map), + .component_driver = { + .controls = da7218_snd_controls, + .num_controls = ARRAY_SIZE(da7218_snd_controls), + .dapm_widgets = da7218_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da7218_dapm_widgets), + .dapm_routes = da7218_audio_map, + .num_dapm_routes = ARRAY_SIZE(da7218_audio_map), + }, }; diff --git a/sound/soc/codecs/da7218.h b/sound/soc/codecs/da7218.h index 477cd37..4f7ec21 100644 --- a/sound/soc/codecs/da7218.h +++ b/sound/soc/codecs/da7218.h @@ -888,7 +888,6 @@ #define DA7218_PLL_MODE_BYPASS (0x0 << 6) #define DA7218_PLL_MODE_NORMAL (0x1 << 6) #define DA7218_PLL_MODE_SRM (0x2 << 6) -#define DA7218_PLL_MODE_32KHZ (0x3 << 6) /* DA7218_PLL_FRAC_TOP = 0x92 */ #define DA7218_PLL_FBDIV_FRAC_TOP_SHIFT 0 @@ -1371,7 +1370,6 @@ enum da7218_sys_clk { DA7218_SYSCLK_MCLK = 0, DA7218_SYSCLK_PLL, DA7218_SYSCLK_PLL_SRM, - DA7218_SYSCLK_PLL_32KHZ }; enum da7218_dev_id { diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index f0057cd..2b8914d 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -13,6 +13,7 @@ #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/clk.h> #include <linux/i2c.h> #include <linux/property.h> #include <linux/pm_wakeirq.h> @@ -114,13 +115,38 @@ static void da7219_aad_hptest_work(struct work_struct *work) struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); u16 tonegen_freq_hptest; - u8 accdet_cfg8; - int report = 0; + u8 pll_srm_sts, gain_ramp_ctrl, accdet_cfg8; + int report = 0, ret = 0; /* Lock DAPM and any Kcontrols that are affected by this test */ snd_soc_dapm_mutex_lock(dapm); mutex_lock(&da7219->lock); + /* Ensure MCLK is available for HP test procedure */ + if (da7219->mclk) { + ret = clk_prepare_enable(da7219->mclk); + if (ret) { + dev_err(codec->dev, "Failed to enable mclk - %d\n", ret); + mutex_unlock(&da7219->lock); + snd_soc_dapm_mutex_unlock(dapm); + return; + } + } + + /* + * If MCLK not present, then we're using the internal oscillator and + * require different frequency settings to achieve the same result. + */ + pll_srm_sts = snd_soc_read(codec, DA7219_PLL_SRM_STS); + if (pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) + tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ); + else + tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC); + + /* Ensure gain ramping at fastest rate */ + gain_ramp_ctrl = snd_soc_read(codec, DA7219_GAIN_RAMP_CTRL); + snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_X8); + /* Bypass cache so it saves current settings */ regcache_cache_bypass(da7219->regmap, true); @@ -183,9 +209,15 @@ static void da7219_aad_hptest_work(struct work_struct *work) snd_soc_write(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK); + /* + * If we're running from the internal oscillator then give audio paths + * time to settle before running test. + */ + if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK)) + msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY); + /* Configure & start Tone Generator */ snd_soc_write(codec, DA7219_TONE_GEN_ON_PER, DA7219_BEEP_ON_PER_MASK); - tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ); regmap_raw_write(da7219->regmap, DA7219_TONE_GEN_FREQ1_L, &tonegen_freq_hptest, sizeof(tonegen_freq_hptest)); snd_soc_update_bits(codec, DA7219_TONE_GEN_CFG2, @@ -244,12 +276,26 @@ static void da7219_aad_hptest_work(struct work_struct *work) snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_8, DA7219_HPTEST_EN_MASK, 0); + /* + * If we're running from the internal oscillator then give audio paths + * time to settle before allowing headphones to be driven as required. + */ + if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK)) + msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY); + + /* Restore gain ramping rate */ + snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL, gain_ramp_ctrl); + /* Drive Headphones/lineout */ snd_soc_update_bits(codec, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK, DA7219_HP_L_AMP_OE_MASK); snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK, DA7219_HP_R_AMP_OE_MASK); + /* Remove MCLK, if previously enabled */ + if (da7219->mclk) + clk_disable_unprepare(da7219->mclk); + mutex_unlock(&da7219->lock); snd_soc_dapm_mutex_unlock(dapm); @@ -751,6 +797,62 @@ static void da7219_aad_handle_pdata(struct snd_soc_codec *codec) /* + * Suspend/Resume + */ + +void da7219_aad_suspend(struct snd_soc_codec *codec) +{ + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); + struct da7219_aad_priv *da7219_aad = da7219->aad; + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + u8 micbias_ctrl; + + if (da7219_aad->jack) { + /* Disable jack detection during suspend */ + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, + DA7219_ACCDET_EN_MASK, 0); + + /* + * If we have a 4-pole jack inserted, then micbias will be + * enabled. We can disable micbias here, and keep a note to + * re-enable it on resume. If jack removal occurred during + * suspend then this will be dealt with through the IRQ handler. + */ + if (da7219_aad->jack_inserted) { + micbias_ctrl = snd_soc_read(codec, DA7219_MICBIAS_CTRL); + if (micbias_ctrl & DA7219_MICBIAS1_EN_MASK) { + snd_soc_dapm_disable_pin(dapm, "Mic Bias"); + snd_soc_dapm_sync(dapm); + da7219_aad->micbias_resume_enable = true; + } + } + } +} + +void da7219_aad_resume(struct snd_soc_codec *codec) +{ + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); + struct da7219_aad_priv *da7219_aad = da7219->aad; + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + + if (da7219_aad->jack) { + /* Re-enable micbias if previously enabled for 4-pole jack */ + if (da7219_aad->jack_inserted && + da7219_aad->micbias_resume_enable) { + snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); + snd_soc_dapm_sync(dapm); + da7219_aad->micbias_resume_enable = false; + } + + /* Re-enable jack detection */ + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, + DA7219_ACCDET_EN_MASK, + DA7219_ACCDET_EN_MASK); + } +} + + +/* * Init/Exit */ diff --git a/sound/soc/codecs/da7219-aad.h b/sound/soc/codecs/da7219-aad.h index 4fccf67..117a3d7 100644 --- a/sound/soc/codecs/da7219-aad.h +++ b/sound/soc/codecs/da7219-aad.h @@ -176,8 +176,10 @@ #define DA7219_AAD_MICBIAS_CHK_DELAY 10 #define DA7219_AAD_MICBIAS_CHK_RETRIES 5 -#define DA7219_AAD_HPTEST_RAMP_FREQ 0x28 -#define DA7219_AAD_HPTEST_PERIOD 65 +#define DA7219_AAD_HPTEST_RAMP_FREQ 0x28 +#define DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC 0x4D +#define DA7219_AAD_HPTEST_PERIOD 65 +#define DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY 20 enum da7219_aad_event_regs { DA7219_AAD_IRQ_REG_A = 0, @@ -199,12 +201,17 @@ struct da7219_aad_priv { struct work_struct hptest_work; struct snd_soc_jack *jack; + bool micbias_resume_enable; bool jack_inserted; }; /* AAD control */ void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack); +/* Suspend/Resume */ +void da7219_aad_suspend(struct snd_soc_codec *codec); +void da7219_aad_resume(struct snd_soc_codec *codec); + /* Init/Exit */ int da7219_aad_init(struct snd_soc_codec *codec); void da7219_aad_exit(struct snd_soc_codec *codec); diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 50ea943..1152aa5 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -801,7 +801,7 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w, ++i; msleep(50); } - } while ((i < DA7219_SRM_CHECK_RETRIES) & (!srm_lock)); + } while ((i < DA7219_SRM_CHECK_RETRIES) && (!srm_lock)); if (!srm_lock) dev_warn(codec->dev, "SRM failed to lock\n"); @@ -1482,6 +1482,8 @@ static struct da7219_pdata *da7219_fw_to_pdata(struct snd_soc_codec *codec) if (!pdata) return NULL; + pdata->wakeup_source = device_property_read_bool(dev, "wakeup-source"); + if (device_property_read_u32(dev, "dlg,micbias-lvl", &of_val32) >= 0) pdata->micbias_lvl = da7219_fw_micbias_lvl(dev, of_val32); else @@ -1508,11 +1510,10 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: break; - case SND_SOC_BIAS_STANDBY: - if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { - /* MCLK */ + case SND_SOC_BIAS_PREPARE: + /* Enable MCLK for transition to ON state */ + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) { if (da7219->mclk) { ret = clk_prepare_enable(da7219->mclk); if (ret) { @@ -1521,22 +1522,28 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, return ret; } } + } + break; + case SND_SOC_BIAS_STANDBY: + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) /* Master bias */ snd_soc_update_bits(codec, DA7219_REFERENCES, DA7219_BIAS_EN_MASK, DA7219_BIAS_EN_MASK); + + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE) { + /* Remove MCLK */ + if (da7219->mclk) + clk_disable_unprepare(da7219->mclk); } break; case SND_SOC_BIAS_OFF: - /* Only disable master bias if jack detection not active */ - if (!da7219->aad->jack) + /* Only disable master bias if we're not a wake-up source */ + if (!da7219->wakeup_source) snd_soc_update_bits(codec, DA7219_REFERENCES, DA7219_BIAS_EN_MASK, 0); - /* MCLK */ - if (da7219->mclk) - clk_disable_unprepare(da7219->mclk); break; } @@ -1599,6 +1606,8 @@ static void da7219_handle_pdata(struct snd_soc_codec *codec) if (pdata) { u8 micbias_lvl = 0; + da7219->wakeup_source = pdata->wakeup_source; + /* Mic Bias voltages */ switch (pdata->micbias_lvl) { case DA7219_MICBIAS_1_6V: @@ -1733,11 +1742,11 @@ static int da7219_suspend(struct snd_soc_codec *codec) { struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); - snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); + /* Suspend AAD if we're not a wake-up source */ + if (!da7219->wakeup_source) + da7219_aad_suspend(codec); - /* Put device into standby mode if jack detection disabled */ - if (!da7219->aad->jack) - snd_soc_write(codec, DA7219_SYSTEM_ACTIVE, 0); + snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } @@ -1746,13 +1755,12 @@ static int da7219_resume(struct snd_soc_codec *codec) { struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); - /* Put device into active mode if previously pushed to standby */ - if (!da7219->aad->jack) - snd_soc_write(codec, DA7219_SYSTEM_ACTIVE, - DA7219_SYSTEM_ACTIVE_MASK); - snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); + /* Resume AAD if previously suspended */ + if (!da7219->wakeup_source) + da7219_aad_resume(codec); + return 0; } #else @@ -1767,13 +1775,14 @@ static struct snd_soc_codec_driver soc_codec_dev_da7219 = { .resume = da7219_resume, .set_bias_level = da7219_set_bias_level, - .controls = da7219_snd_controls, - .num_controls = ARRAY_SIZE(da7219_snd_controls), - - .dapm_widgets = da7219_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da7219_dapm_widgets), - .dapm_routes = da7219_audio_map, - .num_dapm_routes = ARRAY_SIZE(da7219_audio_map), + .component_driver = { + .controls = da7219_snd_controls, + .num_controls = ARRAY_SIZE(da7219_snd_controls), + .dapm_widgets = da7219_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da7219_dapm_widgets), + .dapm_routes = da7219_audio_map, + .num_dapm_routes = ARRAY_SIZE(da7219_audio_map), + }, }; @@ -1921,7 +1930,8 @@ static int da7219_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct da7219_priv *da7219; - int ret; + unsigned int system_active, system_status; + int i, ret; da7219 = devm_kzalloc(&i2c->dev, sizeof(struct da7219_priv), GFP_KERNEL); @@ -1937,6 +1947,37 @@ static int da7219_i2c_probe(struct i2c_client *i2c, return ret; } + regcache_cache_bypass(da7219->regmap, true); + + /* Disable audio paths if still active from previous start */ + regmap_read(da7219->regmap, DA7219_SYSTEM_ACTIVE, &system_active); + if (system_active) { + regmap_write(da7219->regmap, DA7219_GAIN_RAMP_CTRL, + DA7219_GAIN_RAMP_RATE_NOMINAL); + regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_INPUT, 0x00); + regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_OUTPUT, 0x01); + + for (i = 0; i < DA7219_SYS_STAT_CHECK_RETRIES; ++i) { + regmap_read(da7219->regmap, DA7219_SYSTEM_STATUS, + &system_status); + if (!system_status) + break; + + msleep(DA7219_SYS_STAT_CHECK_DELAY); + } + } + + /* Soft reset codec */ + regmap_write_bits(da7219->regmap, DA7219_ACCDET_CONFIG_1, + DA7219_ACCDET_EN_MASK, 0); + regmap_write_bits(da7219->regmap, DA7219_CIF_CTRL, + DA7219_CIF_REG_SOFT_RESET_MASK, + DA7219_CIF_REG_SOFT_RESET_MASK); + regmap_write_bits(da7219->regmap, DA7219_SYSTEM_ACTIVE, + DA7219_SYSTEM_ACTIVE_MASK, 0); + + regcache_cache_bypass(da7219->regmap, false); + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da7219, &da7219_dai, 1); if (ret < 0) { diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h index ff2a2f0..66d3bad 100644 --- a/sound/soc/codecs/da7219.h +++ b/sound/soc/codecs/da7219.h @@ -224,6 +224,7 @@ #define DA7219_PLL_SRM_STATE_MASK (0xF << 0) #define DA7219_PLL_SRM_STATUS_SHIFT 4 #define DA7219_PLL_SRM_STATUS_MASK (0xF << 4) +#define DA7219_PLL_SRM_STS_MCLK (0x1 << 4) #define DA7219_PLL_SRM_STS_SRM_LOCK (0x1 << 7) /* DA7219_DIG_ROUTING_DAI = 0x2A */ @@ -576,6 +577,8 @@ /* DA7219_GAIN_RAMP_CTRL = 0x92 */ #define DA7219_GAIN_RAMP_RATE_SHIFT 0 #define DA7219_GAIN_RAMP_RATE_MASK (0x3 << 0) +#define DA7219_GAIN_RAMP_RATE_X8 (0x0 << 0) +#define DA7219_GAIN_RAMP_RATE_NOMINAL (0x1 << 0) #define DA7219_GAIN_RAMP_RATE_MAX 4 /* DA7219_PC_COUNT = 0x94 */ @@ -770,6 +773,10 @@ /* SRM */ #define DA7219_SRM_CHECK_RETRIES 8 +/* System Controller */ +#define DA7219_SYS_STAT_CHECK_RETRIES 6 +#define DA7219_SYS_STAT_CHECK_DELAY 50 + enum da7219_clk_src { DA7219_CLKSRC_MCLK = 0, DA7219_CLKSRC_MCLK_SQR, @@ -796,6 +803,7 @@ struct da7219_priv { struct da7219_aad_priv *aad; struct da7219_pdata *pdata; + bool wakeup_source; struct regulator_bulk_data supplies[DA7219_NUM_SUPPLIES]; struct regmap *regmap; struct mutex lock; diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 461506a..c1cc1c1 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1501,12 +1501,14 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec, static struct snd_soc_codec_driver soc_codec_dev_da732x = { .set_bias_level = da732x_set_bias_level, - .controls = da732x_snd_controls, - .num_controls = ARRAY_SIZE(da732x_snd_controls), - .dapm_widgets = da732x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da732x_dapm_widgets), - .dapm_routes = da732x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes), + .component_driver = { + .controls = da732x_snd_controls, + .num_controls = ARRAY_SIZE(da732x_snd_controls), + .dapm_widgets = da732x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da732x_dapm_widgets), + .dapm_routes = da732x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes), + }, .set_pll = da732x_set_dai_pll, }; diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 0b2ede8..4efb5f8 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -1455,13 +1455,14 @@ static struct snd_soc_codec_driver soc_codec_dev_da9055 = { .probe = da9055_probe, .set_bias_level = da9055_set_bias_level, - .controls = da9055_snd_controls, - .num_controls = ARRAY_SIZE(da9055_snd_controls), - - .dapm_widgets = da9055_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da9055_dapm_widgets), - .dapm_routes = da9055_audio_map, - .num_dapm_routes = ARRAY_SIZE(da9055_audio_map), + .component_driver = { + .controls = da9055_snd_controls, + .num_controls = ARRAY_SIZE(da9055_snd_controls), + .dapm_widgets = da9055_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da9055_dapm_widgets), + .dapm_routes = da9055_audio_map, + .num_dapm_routes = ARRAY_SIZE(da9055_audio_map), + }, }; static const struct regmap_config da9055_regmap_config = { diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c index fde5325..c82b9dc 100644 --- a/sound/soc/codecs/dmic.c +++ b/sound/soc/codecs/dmic.c @@ -51,10 +51,12 @@ static const struct snd_soc_dapm_route intercon[] = { }; static struct snd_soc_codec_driver soc_dmic = { - .dapm_widgets = dmic_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(dmic_dapm_widgets), - .dapm_routes = intercon, - .num_dapm_routes = ARRAY_SIZE(intercon), + .component_driver = { + .dapm_widgets = dmic_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(dmic_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), + }, }; static int dmic_dev_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index 2086d71..37722194 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c @@ -823,12 +823,14 @@ static struct snd_soc_codec_driver es8328_codec_driver = { .set_bias_level = es8328_set_bias_level, .suspend_bias_off = true, - .controls = es8328_snd_controls, - .num_controls = ARRAY_SIZE(es8328_snd_controls), - .dapm_widgets = es8328_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(es8328_dapm_widgets), - .dapm_routes = es8328_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(es8328_dapm_routes), + .component_driver = { + .controls = es8328_snd_controls, + .num_controls = ARRAY_SIZE(es8328_snd_controls), + .dapm_widgets = es8328_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(es8328_dapm_widgets), + .dapm_routes = es8328_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(es8328_dapm_routes), + }, }; int es8328_probe(struct device *dev, struct regmap *regmap) diff --git a/sound/soc/codecs/gtm601.c b/sound/soc/codecs/gtm601.c index 0b80052..926b1a4 100644 --- a/sound/soc/codecs/gtm601.c +++ b/sound/soc/codecs/gtm601.c @@ -52,10 +52,12 @@ static struct snd_soc_dai_driver gtm601_dai = { }; static const struct snd_soc_codec_driver soc_codec_dev_gtm601 = { - .dapm_widgets = gtm601_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(gtm601_dapm_widgets), - .dapm_routes = gtm601_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(gtm601_dapm_routes), + .component_driver = { + .dapm_widgets = gtm601_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(gtm601_dapm_widgets), + .dapm_routes = gtm601_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(gtm601_dapm_routes), + }, }; static int gtm601_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 4e181b2..c602c49 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -614,7 +614,7 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, (!pin->eld.eld_valid)) { dev_warn(&hdac->hdac.dev, - "Failed: montior present? %d ELD valid?: %d for pin: %d\n", + "Failed: monitor present? %d ELD valid?: %d for pin: %d\n", pin->eld.monitor_present, pin->eld.eld_valid, pin->nid); return 0; diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index f27d115..b904492 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -24,6 +24,15 @@ #include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */ +struct hdmi_device { + struct device *dev; + struct list_head list; + int cnt; +}; +#define pos_to_hdmi_device(pos) container_of((pos), struct hdmi_device, list) +LIST_HEAD(hdmi_device_list); + +#define DAI_NAME_SIZE 16 struct hdmi_codec_priv { struct hdmi_codec_pdata hcd; struct snd_soc_dai_driver *daidrv; @@ -320,7 +329,6 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = { SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) static struct snd_soc_dai_driver hdmi_i2s_dai = { - .name = "i2s-hifi", .id = DAI_ID_I2S, .playback = { .stream_name = "Playback", @@ -334,7 +342,6 @@ static struct snd_soc_dai_driver hdmi_i2s_dai = { }; static const struct snd_soc_dai_driver hdmi_spdif_dai = { - .name = "spdif-hifi", .id = DAI_ID_SPDIF, .playback = { .stream_name = "Playback", @@ -346,13 +353,37 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = { .ops = &hdmi_dai_ops, }; +static char hdmi_dai_name[][DAI_NAME_SIZE] = { + "hdmi-hifi.0", + "hdmi-hifi.1", + "hdmi-hifi.2", + "hdmi-hifi.3", +}; + +static int hdmi_of_xlate_dai_name(struct snd_soc_component *component, + struct of_phandle_args *args, + const char **dai_name) +{ + int id = args->args[0]; + + if (id < ARRAY_SIZE(hdmi_dai_name)) { + *dai_name = hdmi_dai_name[id]; + return 0; + } + + return -EAGAIN; +} + static struct snd_soc_codec_driver hdmi_codec = { - .controls = hdmi_controls, - .num_controls = ARRAY_SIZE(hdmi_controls), - .dapm_widgets = hdmi_widgets, - .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), - .dapm_routes = hdmi_routes, - .num_dapm_routes = ARRAY_SIZE(hdmi_routes), + .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, + .num_dapm_routes = ARRAY_SIZE(hdmi_routes), + .of_xlate_dai_name = hdmi_of_xlate_dai_name, + }, }; static int hdmi_codec_probe(struct platform_device *pdev) @@ -360,6 +391,8 @@ static int hdmi_codec_probe(struct platform_device *pdev) struct hdmi_codec_pdata *hcd = pdev->dev.platform_data; struct device *dev = &pdev->dev; struct hdmi_codec_priv *hcp; + struct hdmi_device *hd; + struct list_head *pos; int dai_count, i = 0; int ret; @@ -381,6 +414,31 @@ static int hdmi_codec_probe(struct platform_device *pdev) if (!hcp) return -ENOMEM; + hd = NULL; + list_for_each(pos, &hdmi_device_list) { + struct hdmi_device *tmp = pos_to_hdmi_device(pos); + + if (tmp->dev == dev->parent) { + hd = tmp; + break; + } + } + + if (!hd) { + hd = devm_kzalloc(dev, sizeof(*hd), GFP_KERNEL); + if (!hd) + return -ENOMEM; + + hd->dev = dev->parent; + + list_add_tail(&hd->list, &hdmi_device_list); + } + + if (hd->cnt >= ARRAY_SIZE(hdmi_dai_name)) { + dev_err(dev, "too many hdmi codec are deteced\n"); + return -EINVAL; + } + hcp->hcd = *hcd; mutex_init(&hcp->current_stream_lock); @@ -393,11 +451,14 @@ static int hdmi_codec_probe(struct platform_device *pdev) hcp->daidrv[i] = hdmi_i2s_dai; hcp->daidrv[i].playback.channels_max = hcd->max_i2s_channels; + hcp->daidrv[i].name = hdmi_dai_name[hd->cnt++]; i++; } - if (hcd->spdif) + if (hcd->spdif) { hcp->daidrv[i] = hdmi_spdif_dai; + hcp->daidrv[i].name = hdmi_dai_name[hd->cnt++]; + } ret = snd_soc_register_codec(dev, &hdmi_codec, hcp->daidrv, dai_count); diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c index 9b6e884..b918ba5 100644 --- a/sound/soc/codecs/inno_rk3036.c +++ b/sound/soc/codecs/inno_rk3036.c @@ -380,12 +380,14 @@ static struct snd_soc_codec_driver rk3036_codec_driver = { .probe = rk3036_codec_probe, .remove = rk3036_codec_remove, .set_bias_level = rk3036_codec_set_bias_level, - .controls = rk3036_codec_dapm_controls, - .num_controls = ARRAY_SIZE(rk3036_codec_dapm_controls), - .dapm_routes = rk3036_codec_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rk3036_codec_dapm_routes), - .dapm_widgets = rk3036_codec_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rk3036_codec_dapm_widgets), + .component_driver = { + .controls = rk3036_codec_dapm_controls, + .num_controls = ARRAY_SIZE(rk3036_codec_dapm_controls), + .dapm_routes = rk3036_codec_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rk3036_codec_dapm_routes), + .dapm_widgets = rk3036_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rk3036_codec_dapm_widgets), + }, }; static const struct regmap_config rk3036_codec_regmap_config = { diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index be44837..a4b0ede 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -1089,12 +1089,14 @@ static struct snd_soc_dai_driver isabelle_dai[] = { static struct snd_soc_codec_driver soc_codec_dev_isabelle = { .set_bias_level = isabelle_set_bias_level, - .controls = isabelle_snd_controls, - .num_controls = ARRAY_SIZE(isabelle_snd_controls), - .dapm_widgets = isabelle_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(isabelle_dapm_widgets), - .dapm_routes = isabelle_intercon, - .num_dapm_routes = ARRAY_SIZE(isabelle_intercon), + .component_driver = { + .controls = isabelle_snd_controls, + .num_controls = ARRAY_SIZE(isabelle_snd_controls), + .dapm_widgets = isabelle_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(isabelle_dapm_widgets), + .dapm_routes = isabelle_intercon, + .num_dapm_routes = ARRAY_SIZE(isabelle_intercon), + }, .idle_bias_off = true, }; diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 1f5ab99..0290fab 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c @@ -298,12 +298,14 @@ static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = { .set_bias_level = jz4740_codec_set_bias_level, .suspend_bias_off = true, - .controls = jz4740_codec_controls, - .num_controls = ARRAY_SIZE(jz4740_codec_controls), - .dapm_widgets = jz4740_codec_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(jz4740_codec_dapm_widgets), - .dapm_routes = jz4740_codec_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(jz4740_codec_dapm_routes), + .component_driver = { + .controls = jz4740_codec_controls, + .num_controls = ARRAY_SIZE(jz4740_codec_controls), + .dapm_widgets = jz4740_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(jz4740_codec_dapm_widgets), + .dapm_routes = jz4740_codec_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(jz4740_codec_dapm_routes), + }, }; static const struct regmap_config jz4740_codec_regmap_config = { diff --git a/sound/soc/codecs/l3.c b/sound/soc/codecs/l3.c index 5353af5..a10ea3c 100644 --- a/sound/soc/codecs/l3.c +++ b/sound/soc/codecs/l3.c @@ -20,6 +20,8 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/delay.h> +#include <linux/device.h> +#include <linux/gpio.h> #include <sound/l3.h> @@ -32,11 +34,11 @@ static void sendbyte(struct l3_pins *adap, unsigned int byte) int i; for (i = 0; i < 8; i++) { - adap->setclk(0); + adap->setclk(adap, 0); udelay(adap->data_hold); - adap->setdat(byte & 1); + adap->setdat(adap, byte & 1); udelay(adap->data_setup); - adap->setclk(1); + adap->setclk(adap, 1); udelay(adap->clock_high); byte >>= 1; } @@ -55,10 +57,10 @@ static void sendbytes(struct l3_pins *adap, const u8 *buf, for (i = 0; i < len; i++) { if (i) { udelay(adap->mode_hold); - adap->setmode(0); + adap->setmode(adap, 0); udelay(adap->mode); } - adap->setmode(1); + adap->setmode(adap, 1); udelay(adap->mode_setup); sendbyte(adap, buf[i]); } @@ -66,26 +68,71 @@ static void sendbytes(struct l3_pins *adap, const u8 *buf, int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len) { - adap->setclk(1); - adap->setdat(1); - adap->setmode(1); + adap->setclk(adap, 1); + adap->setdat(adap, 1); + adap->setmode(adap, 1); udelay(adap->mode); - adap->setmode(0); + adap->setmode(adap, 0); udelay(adap->mode_setup); sendbyte(adap, addr); udelay(adap->mode_hold); sendbytes(adap, data, len); - adap->setclk(1); - adap->setdat(1); - adap->setmode(0); + adap->setclk(adap, 1); + adap->setdat(adap, 1); + adap->setmode(adap, 0); return len; } EXPORT_SYMBOL_GPL(l3_write); + +static void l3_set_clk(struct l3_pins *adap, int val) +{ + gpio_set_value(adap->gpio_clk, val); +} + +static void l3_set_data(struct l3_pins *adap, int val) +{ + gpio_set_value(adap->gpio_data, val); +} + +static void l3_set_mode(struct l3_pins *adap, int val) +{ + gpio_set_value(adap->gpio_mode, val); +} + +int l3_set_gpio_ops(struct device *dev, struct l3_pins *adap) +{ + int ret; + + if (!adap->use_gpios) + return -EINVAL; + + ret = devm_gpio_request_one(dev, adap->gpio_data, + GPIOF_OUT_INIT_LOW, "l3_data"); + if (ret < 0) + return ret; + adap->setdat = l3_set_data; + + ret = devm_gpio_request_one(dev, adap->gpio_clk, + GPIOF_OUT_INIT_LOW, "l3_clk"); + if (ret < 0) + return ret; + adap->setclk = l3_set_clk; + + ret = devm_gpio_request_one(dev, adap->gpio_mode, + GPIOF_OUT_INIT_LOW, "l3_mode"); + if (ret < 0) + return ret; + adap->setmode = l3_set_mode; + + return 0; +} +EXPORT_SYMBOL_GPL(l3_set_gpio_ops); + MODULE_DESCRIPTION("L3 bit-banging driver"); MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index 9af5640..8d413c2 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -1391,12 +1391,14 @@ static struct snd_soc_dai_driver lm49453_dai[] = { static struct snd_soc_codec_driver soc_codec_dev_lm49453 = { .set_bias_level = lm49453_set_bias_level, - .controls = lm49453_snd_controls, - .num_controls = ARRAY_SIZE(lm49453_snd_controls), - .dapm_widgets = lm49453_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(lm49453_dapm_widgets), - .dapm_routes = lm49453_audio_map, - .num_dapm_routes = ARRAY_SIZE(lm49453_audio_map), + .component_driver = { + .controls = lm49453_snd_controls, + .num_controls = ARRAY_SIZE(lm49453_snd_controls), + .dapm_widgets = lm49453_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(lm49453_dapm_widgets), + .dapm_routes = lm49453_audio_map, + .num_dapm_routes = ARRAY_SIZE(lm49453_audio_map), + }, .idle_bias_off = true, }; diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index fc22804..72f7745 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -1704,12 +1704,14 @@ static struct snd_soc_codec_driver soc_codec_dev_max98088 = { .set_bias_level = max98088_set_bias_level, .suspend_bias_off = true, - .controls = max98088_snd_controls, - .num_controls = ARRAY_SIZE(max98088_snd_controls), - .dapm_widgets = max98088_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max98088_dapm_widgets), - .dapm_routes = max98088_audio_map, - .num_dapm_routes = ARRAY_SIZE(max98088_audio_map), + .component_driver = { + .controls = max98088_snd_controls, + .num_controls = ARRAY_SIZE(max98088_snd_controls), + .dapm_widgets = max98088_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98088_dapm_widgets), + .dapm_routes = max98088_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98088_audio_map), + }, }; static int max98088_i2c_probe(struct i2c_client *i2c, diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 3577003..6f8a757 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -2108,12 +2108,14 @@ static struct snd_soc_codec_driver soc_codec_dev_max98095 = { .suspend = max98095_suspend, .resume = max98095_resume, .set_bias_level = max98095_set_bias_level, - .controls = max98095_snd_controls, - .num_controls = ARRAY_SIZE(max98095_snd_controls), - .dapm_widgets = max98095_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max98095_dapm_widgets), - .dapm_routes = max98095_audio_map, - .num_dapm_routes = ARRAY_SIZE(max98095_audio_map), + .component_driver = { + .controls = max98095_snd_controls, + .num_controls = ARRAY_SIZE(max98095_snd_controls), + .dapm_widgets = max98095_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98095_dapm_widgets), + .dapm_routes = max98095_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98095_audio_map), + }, }; static int max98095_i2c_probe(struct i2c_client *i2c, diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c index 5b1dfb1..6a6b68a 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c @@ -74,10 +74,12 @@ static int max98357a_codec_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver max98357a_codec_driver = { .probe = max98357a_codec_probe, - .dapm_widgets = max98357a_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max98357a_dapm_widgets), - .dapm_routes = max98357a_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(max98357a_dapm_routes), + .component_driver = { + .dapm_widgets = max98357a_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98357a_dapm_widgets), + .dapm_routes = max98357a_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(max98357a_dapm_routes), + }, }; static const struct snd_soc_dai_ops max98357a_dai_ops = { diff --git a/sound/soc/codecs/max98371.c b/sound/soc/codecs/max98371.c index 02352ed..781be9ba 100644 --- a/sound/soc/codecs/max98371.c +++ b/sound/soc/codecs/max98371.c @@ -426,7 +426,6 @@ MODULE_DEVICE_TABLE(of, max98371_of_match); static struct i2c_driver max98371_i2c_driver = { .driver = { .name = "max98371", - .owner = THIS_MODULE, .pm = NULL, .of_match_table = of_match_ptr(max98371_of_match), }, diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index c14a79d..0610840 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -306,12 +306,14 @@ static struct snd_soc_codec_driver soc_codec_dev_max9850 = { .set_bias_level = max9850_set_bias_level, .suspend_bias_off = true, - .controls = max9850_controls, - .num_controls = ARRAY_SIZE(max9850_controls), - .dapm_widgets = max9850_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max9850_dapm_widgets), - .dapm_routes = max9850_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(max9850_dapm_routes), + .component_driver = { + .controls = max9850_controls, + .num_controls = ARRAY_SIZE(max9850_controls), + .dapm_widgets = max9850_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max9850_dapm_widgets), + .dapm_routes = max9850_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(max9850_dapm_routes), + }, }; static int max9850_i2c_probe(struct i2c_client *i2c, diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c index 68074c9..499bdbf 100644 --- a/sound/soc/codecs/max9860.c +++ b/sound/soc/codecs/max9860.c @@ -538,12 +538,14 @@ static struct snd_soc_codec_driver max9860_codec_driver = { .set_bias_level = max9860_set_bias_level, .idle_bias_off = true, - .controls = max9860_controls, - .num_controls = ARRAY_SIZE(max9860_controls), - .dapm_widgets = max9860_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max9860_dapm_widgets), - .dapm_routes = max9860_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(max9860_dapm_routes), + .component_driver = { + .controls = max9860_controls, + .num_controls = ARRAY_SIZE(max9860_controls), + .dapm_widgets = max9860_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max9860_dapm_widgets), + .dapm_routes = max9860_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(max9860_dapm_routes), + }, }; #ifdef CONFIG_PM diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 2a22fdd..42e2e40 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -38,11 +38,10 @@ static DECLARE_TLV_DB_SCALE(max9860_capture_tlv, -600, 200, 0); static DECLARE_TLV_DB_SCALE(max9860_mic_tlv, 2000, 100, 1); static DECLARE_TLV_DB_SCALE(max9860_adc_left_tlv, -1200, 100, 1); static DECLARE_TLV_DB_SCALE(max9860_adc_right_tlv, -1200, 100, 1); -static const unsigned int max98088_micboost_tlv[] = { - TLV_DB_RANGE_HEAD(2), +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(max98088_micboost_tlv, 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), -}; +); static const struct snd_kcontrol_new max9867_snd_controls[] = { SOC_DOUBLE_R("Master Playback Volume", MAX9867_LEFTVOL, @@ -417,12 +416,14 @@ static int max9867_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver max9867_codec = { .probe = max9867_probe, - .controls = max9867_snd_controls, - .num_controls = ARRAY_SIZE(max9867_snd_controls), - .dapm_routes = max9867_audio_map, - .num_dapm_routes = ARRAY_SIZE(max9867_audio_map), - .dapm_widgets = max9867_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max9867_dapm_widgets), + .component_driver = { + .controls = max9867_snd_controls, + .num_controls = ARRAY_SIZE(max9867_snd_controls), + .dapm_routes = max9867_audio_map, + .num_dapm_routes = ARRAY_SIZE(max9867_audio_map), + .dapm_widgets = max9867_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max9867_dapm_widgets), + }, }; static bool max9867_volatile_register(struct device *dev, unsigned int reg) diff --git a/sound/soc/codecs/max98925.c b/sound/soc/codecs/max98925.c index 5990de3..327eaa2 100644 --- a/sound/soc/codecs/max98925.c +++ b/sound/soc/codecs/max98925.c @@ -540,12 +540,14 @@ static int max98925_probe(struct snd_soc_codec *codec) static const struct snd_soc_codec_driver soc_codec_dev_max98925 = { .probe = max98925_probe, - .controls = max98925_snd_controls, - .num_controls = ARRAY_SIZE(max98925_snd_controls), - .dapm_routes = max98925_audio_map, - .num_dapm_routes = ARRAY_SIZE(max98925_audio_map), - .dapm_widgets = max98925_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max98925_dapm_widgets), + .component_driver = { + .controls = max98925_snd_controls, + .num_controls = ARRAY_SIZE(max98925_snd_controls), + .dapm_routes = max98925_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98925_audio_map), + .dapm_widgets = max98925_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98925_dapm_widgets), + }, }; static const struct regmap_config max98925_regmap = { diff --git a/sound/soc/codecs/max98926.c b/sound/soc/codecs/max98926.c index 8d14ada..1eff7e0 100644 --- a/sound/soc/codecs/max98926.c +++ b/sound/soc/codecs/max98926.c @@ -347,7 +347,7 @@ static int max98926_dai_set_fmt(struct snd_soc_dai *codec_dai, max98926_set_sense_data(max98926); break; default: - dev_err(codec->dev, "DAI clock mode unsupported"); + dev_err(codec->dev, "DAI clock mode unsupported\n"); return -EINVAL; } @@ -364,7 +364,7 @@ static int max98926_dai_set_fmt(struct snd_soc_dai *codec_dai, invert = MAX98926_DAI_BCI_MASK | MAX98926_DAI_WCI_MASK; break; default: - dev_err(codec->dev, "DAI invert mode unsupported"); + dev_err(codec->dev, "DAI invert mode unsupported\n"); return -EINVAL; } @@ -408,7 +408,7 @@ static int max98926_dai_hw_params(struct snd_pcm_substream *substream, max98926->ch_size = 32; break; default: - dev_dbg(codec->dev, "format unsupported %d", + dev_dbg(codec->dev, "format unsupported %d\n", params_format(params)); return -EINVAL; } @@ -498,12 +498,14 @@ static int max98926_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_max98926 = { .probe = max98926_probe, - .controls = max98926_snd_controls, - .num_controls = ARRAY_SIZE(max98926_snd_controls), - .dapm_routes = max98926_audio_map, - .num_dapm_routes = ARRAY_SIZE(max98926_audio_map), - .dapm_widgets = max98926_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max98926_dapm_widgets), + .component_driver = { + .controls = max98926_snd_controls, + .num_controls = ARRAY_SIZE(max98926_snd_controls), + .dapm_routes = max98926_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98926_audio_map), + .dapm_widgets = max98926_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98926_dapm_widgets), + }, }; static const struct regmap_config max98926_regmap = { diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 3e770cb..9056270 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -737,12 +737,14 @@ static struct snd_soc_codec_driver soc_codec_dev_mc13783 = { .probe = mc13783_probe, .remove = mc13783_remove, .get_regmap = mc13783_get_regmap, - .controls = mc13783_control_list, - .num_controls = ARRAY_SIZE(mc13783_control_list), - .dapm_widgets = mc13783_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(mc13783_dapm_widgets), - .dapm_routes = mc13783_routes, - .num_dapm_routes = ARRAY_SIZE(mc13783_routes), + .component_driver = { + .controls = mc13783_control_list, + .num_controls = ARRAY_SIZE(mc13783_control_list), + .dapm_widgets = mc13783_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(mc13783_dapm_widgets), + .dapm_routes = mc13783_routes, + .num_dapm_routes = ARRAY_SIZE(mc13783_routes), + }, }; static int __init mc13783_codec_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index f561c78..69e5e18 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -541,12 +541,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ml26124 = { .probe = ml26124_probe, .set_bias_level = ml26124_set_bias_level, .suspend_bias_off = true, - .dapm_widgets = ml26124_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ml26124_dapm_widgets), - .dapm_routes = ml26124_intercon, - .num_dapm_routes = ARRAY_SIZE(ml26124_intercon), - .controls = ml26124_snd_controls, - .num_controls = ARRAY_SIZE(ml26124_snd_controls), + .component_driver = { + .controls = ml26124_snd_controls, + .num_controls = ARRAY_SIZE(ml26124_snd_controls), + .dapm_widgets = ml26124_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ml26124_dapm_widgets), + .dapm_routes = ml26124_intercon, + .num_dapm_routes = ARRAY_SIZE(ml26124_intercon), + }, }; static const struct regmap_config ml26124_i2c_regmap = { diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c new file mode 100644 index 0000000..e455186 --- /dev/null +++ b/sound/soc/codecs/nau8810.c @@ -0,0 +1,884 @@ +/* + * nau8810.c -- NAU8810 ALSA Soc Audio driver + * + * Copyright 2016 Nuvoton Technology Corp. + * + * Author: David Lin <ctlin0@nuvoton.com> + * + * Based on WM8974.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/i2c.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/initval.h> +#include <sound/tlv.h> + +#include "nau8810.h" + +#define NAU_PLL_FREQ_MAX 100000000 +#define NAU_PLL_FREQ_MIN 90000000 +#define NAU_PLL_REF_MAX 33000000 +#define NAU_PLL_REF_MIN 8000000 +#define NAU_PLL_OPTOP_MIN 6 + + +static const int nau8810_mclk_scaler[] = { 10, 15, 20, 30, 40, 60, 80, 120 }; + +static const struct reg_default nau8810_reg_defaults[] = { + { NAU8810_REG_POWER1, 0x0000 }, + { NAU8810_REG_POWER2, 0x0000 }, + { NAU8810_REG_POWER3, 0x0000 }, + { NAU8810_REG_IFACE, 0x0050 }, + { NAU8810_REG_COMP, 0x0000 }, + { NAU8810_REG_CLOCK, 0x0140 }, + { NAU8810_REG_SMPLR, 0x0000 }, + { NAU8810_REG_DAC, 0x0000 }, + { NAU8810_REG_DACGAIN, 0x00FF }, + { NAU8810_REG_ADC, 0x0100 }, + { NAU8810_REG_ADCGAIN, 0x00FF }, + { NAU8810_REG_EQ1, 0x012C }, + { NAU8810_REG_EQ2, 0x002C }, + { NAU8810_REG_EQ3, 0x002C }, + { NAU8810_REG_EQ4, 0x002C }, + { NAU8810_REG_EQ5, 0x002C }, + { NAU8810_REG_DACLIM1, 0x0032 }, + { NAU8810_REG_DACLIM2, 0x0000 }, + { NAU8810_REG_NOTCH1, 0x0000 }, + { NAU8810_REG_NOTCH2, 0x0000 }, + { NAU8810_REG_NOTCH3, 0x0000 }, + { NAU8810_REG_NOTCH4, 0x0000 }, + { NAU8810_REG_ALC1, 0x0038 }, + { NAU8810_REG_ALC2, 0x000B }, + { NAU8810_REG_ALC3, 0x0032 }, + { NAU8810_REG_NOISEGATE, 0x0000 }, + { NAU8810_REG_PLLN, 0x0008 }, + { NAU8810_REG_PLLK1, 0x000C }, + { NAU8810_REG_PLLK2, 0x0093 }, + { NAU8810_REG_PLLK3, 0x00E9 }, + { NAU8810_REG_ATTEN, 0x0000 }, + { NAU8810_REG_INPUT_SIGNAL, 0x0003 }, + { NAU8810_REG_PGAGAIN, 0x0010 }, + { NAU8810_REG_ADCBOOST, 0x0100 }, + { NAU8810_REG_OUTPUT, 0x0002 }, + { NAU8810_REG_SPKMIX, 0x0001 }, + { NAU8810_REG_SPKGAIN, 0x0039 }, + { NAU8810_REG_MONOMIX, 0x0001 }, + { NAU8810_REG_POWER4, 0x0000 }, + { NAU8810_REG_TSLOTCTL1, 0x0000 }, + { NAU8810_REG_TSLOTCTL2, 0x0020 }, + { NAU8810_REG_DEVICE_REVID, 0x0000 }, + { NAU8810_REG_I2C_DEVICEID, 0x001A }, + { NAU8810_REG_ADDITIONID, 0x00CA }, + { NAU8810_REG_RESERVE, 0x0124 }, + { NAU8810_REG_OUTCTL, 0x0001 }, + { NAU8810_REG_ALC1ENHAN1, 0x0010 }, + { NAU8810_REG_ALC1ENHAN2, 0x0000 }, + { NAU8810_REG_MISCCTL, 0x0000 }, + { NAU8810_REG_OUTTIEOFF, 0x0000 }, + { NAU8810_REG_AGCP2POUT, 0x0000 }, + { NAU8810_REG_AGCPOUT, 0x0000 }, + { NAU8810_REG_AMTCTL, 0x0000 }, + { NAU8810_REG_OUTTIEOFFMAN, 0x0000 }, +}; + +static bool nau8810_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case NAU8810_REG_RESET ... NAU8810_REG_SMPLR: + case NAU8810_REG_DAC ... NAU8810_REG_DACGAIN: + case NAU8810_REG_ADC ... NAU8810_REG_ADCGAIN: + case NAU8810_REG_EQ1 ... NAU8810_REG_EQ5: + case NAU8810_REG_DACLIM1 ... NAU8810_REG_DACLIM2: + case NAU8810_REG_NOTCH1 ... NAU8810_REG_NOTCH4: + case NAU8810_REG_ALC1 ... NAU8810_REG_ATTEN: + case NAU8810_REG_INPUT_SIGNAL ... NAU8810_REG_PGAGAIN: + case NAU8810_REG_ADCBOOST: + case NAU8810_REG_OUTPUT ... NAU8810_REG_SPKMIX: + case NAU8810_REG_SPKGAIN: + case NAU8810_REG_MONOMIX: + case NAU8810_REG_POWER4 ... NAU8810_REG_TSLOTCTL2: + case NAU8810_REG_DEVICE_REVID ... NAU8810_REG_RESERVE: + case NAU8810_REG_OUTCTL ... NAU8810_REG_ALC1ENHAN2: + case NAU8810_REG_MISCCTL: + case NAU8810_REG_OUTTIEOFF ... NAU8810_REG_OUTTIEOFFMAN: + return true; + default: + return false; + } +} + +static bool nau8810_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case NAU8810_REG_RESET ... NAU8810_REG_SMPLR: + case NAU8810_REG_DAC ... NAU8810_REG_DACGAIN: + case NAU8810_REG_ADC ... NAU8810_REG_ADCGAIN: + case NAU8810_REG_EQ1 ... NAU8810_REG_EQ5: + case NAU8810_REG_DACLIM1 ... NAU8810_REG_DACLIM2: + case NAU8810_REG_NOTCH1 ... NAU8810_REG_NOTCH4: + case NAU8810_REG_ALC1 ... NAU8810_REG_ATTEN: + case NAU8810_REG_INPUT_SIGNAL ... NAU8810_REG_PGAGAIN: + case NAU8810_REG_ADCBOOST: + case NAU8810_REG_OUTPUT ... NAU8810_REG_SPKMIX: + case NAU8810_REG_SPKGAIN: + case NAU8810_REG_MONOMIX: + case NAU8810_REG_POWER4 ... NAU8810_REG_TSLOTCTL2: + case NAU8810_REG_OUTCTL ... NAU8810_REG_ALC1ENHAN2: + case NAU8810_REG_MISCCTL: + case NAU8810_REG_OUTTIEOFF ... NAU8810_REG_OUTTIEOFFMAN: + return true; + default: + return false; + } +} + +static bool nau8810_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case NAU8810_REG_RESET: + case NAU8810_REG_DEVICE_REVID ... NAU8810_REG_RESERVE: + return true; + default: + return false; + } +} + +/* The EQ parameters get function is to get the 5 band equalizer control. + * The regmap raw read can't work here because regmap doesn't provide + * value format for value width of 9 bits. Therefore, the driver reads data + * from cache and makes value format according to the endianness of + * bytes type control element. + */ +static int nau8810_eq_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + struct soc_bytes_ext *params = (void *)kcontrol->private_value; + int i, reg, reg_val; + u16 *val; + + val = (u16 *)ucontrol->value.bytes.data; + reg = NAU8810_REG_EQ1; + for (i = 0; i < params->max / sizeof(u16); i++) { + regmap_read(nau8810->regmap, reg + i, ®_val); + /* conversion of 16-bit integers between native CPU format + * and big endian format + */ + reg_val = cpu_to_be16(reg_val); + memcpy(val + i, ®_val, sizeof(reg_val)); + } + + return 0; +} + +/* The EQ parameters put function is to make configuration of 5 band equalizer + * control. These configuration includes central frequency, equalizer gain, + * cut-off frequency, bandwidth control, and equalizer path. + * The regmap raw write can't work here because regmap doesn't provide + * register and value format for register with address 7 bits and value 9 bits. + * Therefore, the driver makes value format according to the endianness of + * bytes type control element and writes data to codec. + */ +static int nau8810_eq_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + struct soc_bytes_ext *params = (void *)kcontrol->private_value; + void *data; + u16 *val, value; + int i, reg, ret; + + data = kmemdup(ucontrol->value.bytes.data, + params->max, GFP_KERNEL | GFP_DMA); + if (!data) + return -ENOMEM; + + val = (u16 *)data; + reg = NAU8810_REG_EQ1; + for (i = 0; i < params->max / sizeof(u16); i++) { + /* conversion of 16-bit integers between native CPU format + * and big endian format + */ + value = be16_to_cpu(*(val + i)); + ret = regmap_write(nau8810->regmap, reg + i, value); + if (ret) { + dev_err(codec->dev, "EQ configuration fail, register: %x ret: %d\n", + reg + i, ret); + kfree(data); + return ret; + } + } + kfree(data); + + return 0; +} + +static const char * const nau8810_companding[] = { + "Off", "NC", "u-law", "A-law" }; + +static const struct soc_enum nau8810_companding_adc_enum = + SOC_ENUM_SINGLE(NAU8810_REG_COMP, NAU8810_ADCCM_SFT, + ARRAY_SIZE(nau8810_companding), nau8810_companding); + +static const struct soc_enum nau8810_companding_dac_enum = + SOC_ENUM_SINGLE(NAU8810_REG_COMP, NAU8810_DACCM_SFT, + ARRAY_SIZE(nau8810_companding), nau8810_companding); + +static const char * const nau8810_deemp[] = { + "None", "32kHz", "44.1kHz", "48kHz" }; + +static const struct soc_enum nau8810_deemp_enum = + SOC_ENUM_SINGLE(NAU8810_REG_DAC, NAU8810_DEEMP_SFT, + ARRAY_SIZE(nau8810_deemp), nau8810_deemp); + +static const char * const nau8810_eqmode[] = {"Capture", "Playback" }; + +static const struct soc_enum nau8810_eqmode_enum = + SOC_ENUM_SINGLE(NAU8810_REG_EQ1, NAU8810_EQM_SFT, + ARRAY_SIZE(nau8810_eqmode), nau8810_eqmode); + +static const char * const nau8810_alc[] = {"Normal", "Limiter" }; + +static const struct soc_enum nau8810_alc_enum = + SOC_ENUM_SINGLE(NAU8810_REG_ALC3, NAU8810_ALCM_SFT, + ARRAY_SIZE(nau8810_alc), nau8810_alc); + +static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); +static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); +static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0); +static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0); + +static const struct snd_kcontrol_new nau8810_snd_controls[] = { + SOC_ENUM("ADC Companding", nau8810_companding_adc_enum), + SOC_ENUM("DAC Companding", nau8810_companding_dac_enum), + SOC_ENUM("DAC De-emphasis", nau8810_deemp_enum), + + SOC_ENUM("EQ Function", nau8810_eqmode_enum), + SND_SOC_BYTES_EXT("EQ Parameters", 10, + nau8810_eq_get, nau8810_eq_put), + + SOC_SINGLE("DAC Inversion Switch", NAU8810_REG_DAC, + NAU8810_DACPL_SFT, 1, 0), + SOC_SINGLE_TLV("Playback Volume", NAU8810_REG_DACGAIN, + NAU8810_DACGAIN_SFT, 0xff, 0, digital_tlv), + + SOC_SINGLE("High Pass Filter Switch", NAU8810_REG_ADC, + NAU8810_HPFEN_SFT, 1, 0), + SOC_SINGLE("High Pass Cut Off", NAU8810_REG_ADC, + NAU8810_HPF_SFT, 0x7, 0), + + SOC_SINGLE("ADC Inversion Switch", NAU8810_REG_ADC, + NAU8810_ADCPL_SFT, 1, 0), + SOC_SINGLE_TLV("Capture Volume", NAU8810_REG_ADCGAIN, + NAU8810_ADCGAIN_SFT, 0xff, 0, digital_tlv), + + SOC_SINGLE_TLV("EQ1 Volume", NAU8810_REG_EQ1, + NAU8810_EQ1GC_SFT, 0x18, 1, eq_tlv), + SOC_SINGLE_TLV("EQ2 Volume", NAU8810_REG_EQ2, + NAU8810_EQ2GC_SFT, 0x18, 1, eq_tlv), + SOC_SINGLE_TLV("EQ3 Volume", NAU8810_REG_EQ3, + NAU8810_EQ3GC_SFT, 0x18, 1, eq_tlv), + SOC_SINGLE_TLV("EQ4 Volume", NAU8810_REG_EQ4, + NAU8810_EQ4GC_SFT, 0x18, 1, eq_tlv), + SOC_SINGLE_TLV("EQ5 Volume", NAU8810_REG_EQ5, + NAU8810_EQ5GC_SFT, 0x18, 1, eq_tlv), + + SOC_SINGLE("DAC Limiter Switch", NAU8810_REG_DACLIM1, + NAU8810_DACLIMEN_SFT, 1, 0), + SOC_SINGLE("DAC Limiter Decay", NAU8810_REG_DACLIM1, + NAU8810_DACLIMDCY_SFT, 0xf, 0), + SOC_SINGLE("DAC Limiter Attack", NAU8810_REG_DACLIM1, + NAU8810_DACLIMATK_SFT, 0xf, 0), + SOC_SINGLE("DAC Limiter Threshold", NAU8810_REG_DACLIM2, + NAU8810_DACLIMTHL_SFT, 0x7, 0), + SOC_SINGLE("DAC Limiter Boost", NAU8810_REG_DACLIM2, + NAU8810_DACLIMBST_SFT, 0xf, 0), + + SOC_ENUM("ALC Mode", nau8810_alc_enum), + SOC_SINGLE("ALC Enable Switch", NAU8810_REG_ALC1, + NAU8810_ALCEN_SFT, 1, 0), + SOC_SINGLE("ALC Max Volume", NAU8810_REG_ALC1, + NAU8810_ALCMXGAIN_SFT, 0x7, 0), + SOC_SINGLE("ALC Min Volume", NAU8810_REG_ALC1, + NAU8810_ALCMINGAIN_SFT, 0x7, 0), + SOC_SINGLE("ALC ZC Switch", NAU8810_REG_ALC2, + NAU8810_ALCZC_SFT, 1, 0), + SOC_SINGLE("ALC Hold", NAU8810_REG_ALC2, + NAU8810_ALCHT_SFT, 0xf, 0), + SOC_SINGLE("ALC Target", NAU8810_REG_ALC2, + NAU8810_ALCSL_SFT, 0xf, 0), + SOC_SINGLE("ALC Decay", NAU8810_REG_ALC3, + NAU8810_ALCDCY_SFT, 0xf, 0), + SOC_SINGLE("ALC Attack", NAU8810_REG_ALC3, + NAU8810_ALCATK_SFT, 0xf, 0), + SOC_SINGLE("ALC Noise Gate Switch", NAU8810_REG_NOISEGATE, + NAU8810_ALCNEN_SFT, 1, 0), + SOC_SINGLE("ALC Noise Gate Threshold", NAU8810_REG_NOISEGATE, + NAU8810_ALCNTH_SFT, 0x7, 0), + + SOC_SINGLE("PGA ZC Switch", NAU8810_REG_PGAGAIN, + NAU8810_PGAZC_SFT, 1, 0), + SOC_SINGLE_TLV("PGA Volume", NAU8810_REG_PGAGAIN, + NAU8810_PGAGAIN_SFT, 0x3f, 0, inpga_tlv), + + SOC_SINGLE("Speaker ZC Switch", NAU8810_REG_SPKGAIN, + NAU8810_SPKZC_SFT, 1, 0), + SOC_SINGLE("Speaker Mute Switch", NAU8810_REG_SPKGAIN, + NAU8810_SPKMT_SFT, 1, 0), + SOC_SINGLE_TLV("Speaker Volume", NAU8810_REG_SPKGAIN, + NAU8810_SPKGAIN_SFT, 0x3f, 0, spk_tlv), + + SOC_SINGLE("Capture Boost(+20dB)", NAU8810_REG_ADCBOOST, + NAU8810_PGABST_SFT, 1, 0), + SOC_SINGLE("Mono Mute Switch", NAU8810_REG_MONOMIX, + NAU8810_MOUTMXMT_SFT, 1, 0), + + SOC_SINGLE("DAC Oversampling Rate(128x) Switch", NAU8810_REG_DAC, + NAU8810_DACOS_SFT, 1, 0), + SOC_SINGLE("ADC Oversampling Rate(128x) Switch", NAU8810_REG_ADC, + NAU8810_ADCOS_SFT, 1, 0), +}; + +/* Speaker Output Mixer */ +static const struct snd_kcontrol_new nau8810_speaker_mixer_controls[] = { + SOC_DAPM_SINGLE("Line Bypass Switch", NAU8810_REG_SPKMIX, + NAU8810_BYPSPK_SFT, 1, 0), + SOC_DAPM_SINGLE("PCM Playback Switch", NAU8810_REG_SPKMIX, + NAU8810_DACSPK_SFT, 1, 0), +}; + +/* Mono Output Mixer */ +static const struct snd_kcontrol_new nau8810_mono_mixer_controls[] = { + SOC_DAPM_SINGLE("Line Bypass Switch", NAU8810_REG_MONOMIX, + NAU8810_BYPMOUT_SFT, 1, 0), + SOC_DAPM_SINGLE("PCM Playback Switch", NAU8810_REG_MONOMIX, + NAU8810_DACMOUT_SFT, 1, 0), +}; + +/* PGA Mute */ +static const struct snd_kcontrol_new nau8810_inpga_mute[] = { + SOC_DAPM_SINGLE("PGA Mute Switch", NAU8810_REG_PGAGAIN, + NAU8810_PGAMT_SFT, 1, 0), +}; + +/* Input PGA */ +static const struct snd_kcontrol_new nau8810_inpga[] = { + SOC_DAPM_SINGLE("MicN Switch", NAU8810_REG_INPUT_SIGNAL, + NAU8810_NMICPGA_SFT, 1, 0), + SOC_DAPM_SINGLE("MicP Switch", NAU8810_REG_INPUT_SIGNAL, + NAU8810_PMICPGA_SFT, 1, 0), +}; + +/* Mic Input boost vol */ +static const struct snd_kcontrol_new nau8810_mic_boost_controls = + SOC_DAPM_SINGLE("Mic Volume", NAU8810_REG_ADCBOOST, + NAU8810_PMICBSTGAIN_SFT, 0x7, 0); + +/* Loopback Switch */ +static const struct snd_kcontrol_new nau8810_loopback = + SOC_DAPM_SINGLE("Switch", NAU8810_REG_COMP, + NAU8810_ADDAP_SFT, 1, 0); + +static int check_mclk_select_pll(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + unsigned int value; + + regmap_read(nau8810->regmap, NAU8810_REG_CLOCK, &value); + return (value & NAU8810_CLKM_MASK); +} + +static const struct snd_soc_dapm_widget nau8810_dapm_widgets[] = { + SND_SOC_DAPM_MIXER("Speaker Mixer", NAU8810_REG_POWER3, + NAU8810_SPKMX_EN_SFT, 0, &nau8810_speaker_mixer_controls[0], + ARRAY_SIZE(nau8810_speaker_mixer_controls)), + SND_SOC_DAPM_MIXER("Mono Mixer", NAU8810_REG_POWER3, + NAU8810_MOUTMX_EN_SFT, 0, &nau8810_mono_mixer_controls[0], + ARRAY_SIZE(nau8810_mono_mixer_controls)), + SND_SOC_DAPM_DAC("DAC", "HiFi Playback", NAU8810_REG_POWER3, + NAU8810_DAC_EN_SFT, 0), + SND_SOC_DAPM_ADC("ADC", "HiFi Capture", NAU8810_REG_POWER2, + NAU8810_ADC_EN_SFT, 0), + SND_SOC_DAPM_PGA("SpkN Out", NAU8810_REG_POWER3, + NAU8810_NSPK_EN_SFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("SpkP Out", NAU8810_REG_POWER3, + NAU8810_PSPK_EN_SFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("Mono Out", NAU8810_REG_POWER3, + NAU8810_MOUT_EN_SFT, 0, NULL, 0), + + SND_SOC_DAPM_MIXER("Input PGA", NAU8810_REG_POWER2, + NAU8810_PGA_EN_SFT, 0, nau8810_inpga, + ARRAY_SIZE(nau8810_inpga)), + SND_SOC_DAPM_MIXER("Input Boost Stage", NAU8810_REG_POWER2, + NAU8810_BST_EN_SFT, 0, nau8810_inpga_mute, + ARRAY_SIZE(nau8810_inpga_mute)), + + SND_SOC_DAPM_SUPPLY("Mic Bias", NAU8810_REG_POWER1, + NAU8810_MICBIAS_EN_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL", NAU8810_REG_POWER1, + NAU8810_PLL_EN_SFT, 0, NULL, 0), + + SND_SOC_DAPM_SWITCH("Digital Loopback", SND_SOC_NOPM, 0, 0, + &nau8810_loopback), + + SND_SOC_DAPM_INPUT("MICN"), + SND_SOC_DAPM_INPUT("MICP"), + SND_SOC_DAPM_OUTPUT("MONOOUT"), + SND_SOC_DAPM_OUTPUT("SPKOUTP"), + SND_SOC_DAPM_OUTPUT("SPKOUTN"), +}; + +static const struct snd_soc_dapm_route nau8810_dapm_routes[] = { + {"DAC", NULL, "PLL", check_mclk_select_pll}, + + /* Mono output mixer */ + {"Mono Mixer", "PCM Playback Switch", "DAC"}, + {"Mono Mixer", "Line Bypass Switch", "Input Boost Stage"}, + + /* Speaker output mixer */ + {"Speaker Mixer", "PCM Playback Switch", "DAC"}, + {"Speaker Mixer", "Line Bypass Switch", "Input Boost Stage"}, + + /* Outputs */ + {"Mono Out", NULL, "Mono Mixer"}, + {"MONOOUT", NULL, "Mono Out"}, + {"SpkN Out", NULL, "Speaker Mixer"}, + {"SpkP Out", NULL, "Speaker Mixer"}, + {"SPKOUTN", NULL, "SpkN Out"}, + {"SPKOUTP", NULL, "SpkP Out"}, + + /* Input Boost Stage */ + {"ADC", NULL, "Input Boost Stage"}, + {"ADC", NULL, "PLL", check_mclk_select_pll}, + {"Input Boost Stage", NULL, "Input PGA"}, + {"Input Boost Stage", NULL, "MICP"}, + + /* Input PGA */ + {"Input PGA", NULL, "Mic Bias"}, + {"Input PGA", "MicN Switch", "MICN"}, + {"Input PGA", "MicP Switch", "MICP"}, + + /* Digital Looptack */ + {"Digital Loopback", "Switch", "ADC"}, + {"DAC", NULL, "Digital Loopback"}, +}; + +static int nau8810_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + + nau8810->clk_id = clk_id; + nau8810->sysclk = freq; + dev_dbg(nau8810->dev, "master sysclk %dHz, source %s\n", + freq, clk_id == NAU8810_SCLK_PLL ? "PLL" : "MCLK"); + + return 0; +} + +static int nau88l0_calc_pll(unsigned int pll_in, + unsigned int fs, struct nau8810_pll *pll_param) +{ + u64 f2, f2_max, pll_ratio; + int i, scal_sel; + + if (pll_in > NAU_PLL_REF_MAX || pll_in < NAU_PLL_REF_MIN) + return -EINVAL; + + f2_max = 0; + scal_sel = ARRAY_SIZE(nau8810_mclk_scaler); + for (i = 0; i < ARRAY_SIZE(nau8810_mclk_scaler); i++) { + f2 = 256 * fs * 4 * nau8810_mclk_scaler[i] / 10; + if (f2 > NAU_PLL_FREQ_MIN && f2 < NAU_PLL_FREQ_MAX && + f2_max < f2) { + f2_max = f2; + scal_sel = i; + } + } + if (ARRAY_SIZE(nau8810_mclk_scaler) == scal_sel) + return -EINVAL; + pll_param->mclk_scaler = scal_sel; + f2 = f2_max; + + /* Calculate the PLL 4-bit integer input and the PLL 24-bit fractional + * input; round up the 24+4bit. + */ + pll_ratio = div_u64(f2 << 28, pll_in); + pll_param->pre_factor = 0; + if (((pll_ratio >> 28) & 0xF) < NAU_PLL_OPTOP_MIN) { + pll_ratio <<= 1; + pll_param->pre_factor = 1; + } + pll_param->pll_int = (pll_ratio >> 28) & 0xF; + pll_param->pll_frac = ((pll_ratio & 0xFFFFFFF) >> 4); + + return 0; +} + +static int nau8810_set_pll(struct snd_soc_dai *codec_dai, int pll_id, + int source, unsigned int freq_in, unsigned int freq_out) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + struct regmap *map = nau8810->regmap; + struct nau8810_pll *pll_param = &nau8810->pll; + int ret, fs; + + fs = freq_out / 256; + ret = nau88l0_calc_pll(freq_in, fs, pll_param); + if (ret < 0) { + dev_err(nau8810->dev, "Unsupported input clock %d\n", freq_in); + return ret; + } + dev_info(nau8810->dev, "pll_int=%x pll_frac=%x mclk_scaler=%x pre_factor=%x\n", + pll_param->pll_int, pll_param->pll_frac, pll_param->mclk_scaler, + pll_param->pre_factor); + + regmap_update_bits(map, NAU8810_REG_PLLN, + NAU8810_PLLMCLK_DIV2 | NAU8810_PLLN_MASK, + (pll_param->pre_factor ? NAU8810_PLLMCLK_DIV2 : 0) | + pll_param->pll_int); + regmap_write(map, NAU8810_REG_PLLK1, + (pll_param->pll_frac >> NAU8810_PLLK1_SFT) & + NAU8810_PLLK1_MASK); + regmap_write(map, NAU8810_REG_PLLK2, + (pll_param->pll_frac >> NAU8810_PLLK2_SFT) & + NAU8810_PLLK2_MASK); + regmap_write(map, NAU8810_REG_PLLK3, + pll_param->pll_frac & NAU8810_PLLK3_MASK); + regmap_update_bits(map, NAU8810_REG_CLOCK, NAU8810_MCLKSEL_MASK, + pll_param->mclk_scaler << NAU8810_MCLKSEL_SFT); + regmap_update_bits(map, NAU8810_REG_CLOCK, + NAU8810_CLKM_MASK, NAU8810_CLKM_PLL); + + return 0; +} + +static int nau8810_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + u16 ctrl1_val = 0, ctrl2_val = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + ctrl2_val |= NAU8810_CLKIO_MASTER; + break; + case SND_SOC_DAIFMT_CBS_CFS: + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + ctrl1_val |= NAU8810_AIFMT_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + break; + case SND_SOC_DAIFMT_LEFT_J: + ctrl1_val |= NAU8810_AIFMT_LEFT; + break; + case SND_SOC_DAIFMT_DSP_A: + ctrl1_val |= NAU8810_AIFMT_PCM_A; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_IF: + ctrl1_val |= NAU8810_BCLKP_IB | NAU8810_FSP_IF; + break; + case SND_SOC_DAIFMT_IB_NF: + ctrl1_val |= NAU8810_BCLKP_IB; + break; + case SND_SOC_DAIFMT_NB_IF: + ctrl1_val |= NAU8810_FSP_IF; + break; + default: + return -EINVAL; + } + + regmap_update_bits(nau8810->regmap, NAU8810_REG_IFACE, + NAU8810_AIFMT_MASK | NAU8810_FSP_IF | + NAU8810_BCLKP_IB, ctrl1_val); + regmap_update_bits(nau8810->regmap, NAU8810_REG_CLOCK, + NAU8810_CLKIO_MASK, ctrl2_val); + + return 0; +} + +static int nau8810_mclk_clkdiv(struct nau8810 *nau8810, int rate) +{ + int i, sclk, imclk = rate * 256, div = 0; + + if (!nau8810->sysclk) { + dev_err(nau8810->dev, "Make mclk div configuration fail because of invalid system clock\n"); + return -EINVAL; + } + + /* Configure the master clock prescaler div to make system + * clock to approximate the internal master clock (IMCLK); + * and large or equal to IMCLK. + */ + for (i = 1; i < ARRAY_SIZE(nau8810_mclk_scaler); i++) { + sclk = (nau8810->sysclk * 10) / + nau8810_mclk_scaler[i]; + if (sclk < imclk) + break; + div = i; + } + dev_dbg(nau8810->dev, + "master clock prescaler %x for fs %d\n", div, rate); + + /* master clock from MCLK and disable PLL */ + regmap_update_bits(nau8810->regmap, NAU8810_REG_CLOCK, + NAU8810_MCLKSEL_MASK, (div << NAU8810_MCLKSEL_SFT)); + regmap_update_bits(nau8810->regmap, NAU8810_REG_CLOCK, + NAU8810_CLKM_MASK, NAU8810_CLKM_MCLK); + + return 0; +} + +static int nau8810_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + int val_len = 0, val_rate = 0, ret = 0; + + switch (params_width(params)) { + case 16: + break; + case 20: + val_len |= NAU8810_WLEN_20; + break; + case 24: + val_len |= NAU8810_WLEN_24; + break; + case 32: + val_len |= NAU8810_WLEN_32; + break; + } + + switch (params_rate(params)) { + case 8000: + val_rate |= NAU8810_SMPLR_8K; + break; + case 11025: + val_rate |= NAU8810_SMPLR_12K; + break; + case 16000: + val_rate |= NAU8810_SMPLR_16K; + break; + case 22050: + val_rate |= NAU8810_SMPLR_24K; + break; + case 32000: + val_rate |= NAU8810_SMPLR_32K; + break; + case 44100: + case 48000: + break; + } + + regmap_update_bits(nau8810->regmap, NAU8810_REG_IFACE, + NAU8810_WLEN_MASK, val_len); + regmap_update_bits(nau8810->regmap, NAU8810_REG_SMPLR, + NAU8810_SMPLR_MASK, val_rate); + + /* If the master clock is from MCLK, provide the runtime FS for driver + * to get the master clock prescaler configuration. + */ + if (nau8810->clk_id == NAU8810_SCLK_MCLK) { + ret = nau8810_mclk_clkdiv(nau8810, params_rate(params)); + if (ret < 0) + dev_err(nau8810->dev, "MCLK div configuration fail\n"); + } + + return ret; +} + +static int nau8810_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + struct regmap *map = nau8810->regmap; + + switch (level) { + case SND_SOC_BIAS_ON: + case SND_SOC_BIAS_PREPARE: + regmap_update_bits(map, NAU8810_REG_POWER1, + NAU8810_REFIMP_MASK, NAU8810_REFIMP_80K); + break; + + case SND_SOC_BIAS_STANDBY: + regmap_update_bits(map, NAU8810_REG_POWER1, + NAU8810_IOBUF_EN | NAU8810_ABIAS_EN, + NAU8810_IOBUF_EN | NAU8810_ABIAS_EN); + + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { + regcache_sync(map); + regmap_update_bits(map, NAU8810_REG_POWER1, + NAU8810_REFIMP_MASK, NAU8810_REFIMP_3K); + mdelay(100); + } + regmap_update_bits(map, NAU8810_REG_POWER1, + NAU8810_REFIMP_MASK, NAU8810_REFIMP_300K); + break; + + case SND_SOC_BIAS_OFF: + regmap_write(map, NAU8810_REG_POWER1, 0); + regmap_write(map, NAU8810_REG_POWER2, 0); + regmap_write(map, NAU8810_REG_POWER3, 0); + break; + } + + return 0; +} + + +#define NAU8810_RATES (SNDRV_PCM_RATE_8000_48000) + +#define NAU8810_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static const struct snd_soc_dai_ops nau8810_ops = { + .hw_params = nau8810_pcm_hw_params, + .set_fmt = nau8810_set_dai_fmt, + .set_sysclk = nau8810_set_sysclk, + .set_pll = nau8810_set_pll, +}; + +static struct snd_soc_dai_driver nau8810_dai = { + .name = "nau8810-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, /* Only 1 channel of data */ + .rates = NAU8810_RATES, + .formats = NAU8810_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, /* Only 1 channel of data */ + .rates = NAU8810_RATES, + .formats = NAU8810_FORMATS, + }, + .ops = &nau8810_ops, + .symmetric_rates = 1, +}; + +static const struct regmap_config nau8810_regmap_config = { + .reg_bits = 7, + .val_bits = 9, + + .max_register = NAU8810_REG_MAX, + .readable_reg = nau8810_readable_reg, + .writeable_reg = nau8810_writeable_reg, + .volatile_reg = nau8810_volatile_reg, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = nau8810_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(nau8810_reg_defaults), +}; + +static struct snd_soc_codec_driver nau8810_codec_driver = { + .set_bias_level = nau8810_set_bias_level, + .suspend_bias_off = true, + + .component_driver = { + .controls = nau8810_snd_controls, + .num_controls = ARRAY_SIZE(nau8810_snd_controls), + .dapm_widgets = nau8810_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(nau8810_dapm_widgets), + .dapm_routes = nau8810_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(nau8810_dapm_routes), + }, +}; + +static int nau8810_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct device *dev = &i2c->dev; + struct nau8810 *nau8810 = dev_get_platdata(dev); + + if (!nau8810) { + nau8810 = devm_kzalloc(dev, sizeof(*nau8810), GFP_KERNEL); + if (!nau8810) + return -ENOMEM; + } + i2c_set_clientdata(i2c, nau8810); + + nau8810->regmap = devm_regmap_init_i2c(i2c, &nau8810_regmap_config); + if (IS_ERR(nau8810->regmap)) + return PTR_ERR(nau8810->regmap); + nau8810->dev = dev; + + regmap_write(nau8810->regmap, NAU8810_REG_RESET, 0x00); + + return snd_soc_register_codec(dev, + &nau8810_codec_driver, &nau8810_dai, 1); +} + +static int nau8810_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + + return 0; +} + +static const struct i2c_device_id nau8810_i2c_id[] = { + { "nau8810", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, nau8810_i2c_id); + +#ifdef CONFIG_OF +static const struct of_device_id nau8810_of_match[] = { + { .compatible = "nuvoton,nau8810", }, + { } +}; +MODULE_DEVICE_TABLE(of, nau8810_of_match); +#endif + +static struct i2c_driver nau8810_i2c_driver = { + .driver = { + .name = "nau8810", + .of_match_table = of_match_ptr(nau8810_of_match), + }, + .probe = nau8810_i2c_probe, + .remove = nau8810_i2c_remove, + .id_table = nau8810_i2c_id, +}; + +module_i2c_driver(nau8810_i2c_driver); + +MODULE_DESCRIPTION("ASoC NAU8810 driver"); +MODULE_AUTHOR("David Lin <ctlin0@nuvoton.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/nau8810.h b/sound/soc/codecs/nau8810.h new file mode 100644 index 0000000..df88265 --- /dev/null +++ b/sound/soc/codecs/nau8810.h @@ -0,0 +1,281 @@ +/* + * NAU8810 ALSA SoC audio driver + * + * Copyright 2016 Nuvoton Technology Corp. + * Author: David Lin <ctlin0@nuvoton.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 __NAU8810_H__ +#define __NAU8810_H__ + +#define NAU8810_REG_RESET 0x00 +#define NAU8810_REG_POWER1 0x01 +#define NAU8810_REG_POWER2 0x02 +#define NAU8810_REG_POWER3 0x03 +#define NAU8810_REG_IFACE 0x04 +#define NAU8810_REG_COMP 0x05 +#define NAU8810_REG_CLOCK 0x06 +#define NAU8810_REG_SMPLR 0x07 +#define NAU8810_REG_DAC 0x0A +#define NAU8810_REG_DACGAIN 0x0B +#define NAU8810_REG_ADC 0x0E +#define NAU8810_REG_ADCGAIN 0x0F +#define NAU8810_REG_EQ1 0x12 +#define NAU8810_REG_EQ2 0x13 +#define NAU8810_REG_EQ3 0x14 +#define NAU8810_REG_EQ4 0x15 +#define NAU8810_REG_EQ5 0x16 +#define NAU8810_REG_DACLIM1 0x18 +#define NAU8810_REG_DACLIM2 0x19 +#define NAU8810_REG_NOTCH1 0x1B +#define NAU8810_REG_NOTCH2 0x1C +#define NAU8810_REG_NOTCH3 0x1D +#define NAU8810_REG_NOTCH4 0x1E +#define NAU8810_REG_ALC1 0x20 +#define NAU8810_REG_ALC2 0x21 +#define NAU8810_REG_ALC3 0x22 +#define NAU8810_REG_NOISEGATE 0x23 +#define NAU8810_REG_PLLN 0x24 +#define NAU8810_REG_PLLK1 0x25 +#define NAU8810_REG_PLLK2 0x26 +#define NAU8810_REG_PLLK3 0x27 +#define NAU8810_REG_ATTEN 0x28 +#define NAU8810_REG_INPUT_SIGNAL 0x2C +#define NAU8810_REG_PGAGAIN 0x2D +#define NAU8810_REG_ADCBOOST 0x2F +#define NAU8810_REG_OUTPUT 0x31 +#define NAU8810_REG_SPKMIX 0x32 +#define NAU8810_REG_SPKGAIN 0x36 +#define NAU8810_REG_MONOMIX 0x38 +#define NAU8810_REG_POWER4 0x3A +#define NAU8810_REG_TSLOTCTL1 0x3B +#define NAU8810_REG_TSLOTCTL2 0x3C +#define NAU8810_REG_DEVICE_REVID 0x3E +#define NAU8810_REG_I2C_DEVICEID 0x3F +#define NAU8810_REG_ADDITIONID 0x40 +#define NAU8810_REG_RESERVE 0x41 +#define NAU8810_REG_OUTCTL 0x45 +#define NAU8810_REG_ALC1ENHAN1 0x46 +#define NAU8810_REG_ALC1ENHAN2 0x47 +#define NAU8810_REG_MISCCTL 0x49 +#define NAU8810_REG_OUTTIEOFF 0x4B +#define NAU8810_REG_AGCP2POUT 0x4C +#define NAU8810_REG_AGCPOUT 0x4D +#define NAU8810_REG_AMTCTL 0x4E +#define NAU8810_REG_OUTTIEOFFMAN 0x4F +#define NAU8810_REG_MAX NAU8810_REG_OUTTIEOFFMAN + + +/* NAU8810_REG_POWER1 (0x1) */ +#define NAU8810_DCBUF_EN (0x1 << 8) +#define NAU8810_PLL_EN_SFT 5 +#define NAU8810_MICBIAS_EN_SFT 4 +#define NAU8810_ABIAS_EN (0x1 << 3) +#define NAU8810_IOBUF_EN (0x1 << 2) +#define NAU8810_REFIMP_MASK 0x3 +#define NAU8810_REFIMP_DIS 0x0 +#define NAU8810_REFIMP_80K 0x1 +#define NAU8810_REFIMP_300K 0x2 +#define NAU8810_REFIMP_3K 0x3 + +/* NAU8810_REG_POWER2 (0x2) */ +#define NAU8810_BST_EN_SFT 4 +#define NAU8810_PGA_EN_SFT 2 +#define NAU8810_ADC_EN_SFT 0 + +/* NAU8810_REG_POWER3 (0x3) */ +#define NAU8810_DAC_EN_SFT 0 +#define NAU8810_SPKMX_EN_SFT 2 +#define NAU8810_MOUTMX_EN_SFT 3 +#define NAU8810_PSPK_EN_SFT 5 +#define NAU8810_NSPK_EN_SFT 6 +#define NAU8810_MOUT_EN_SFT 7 + +/* NAU8810_REG_IFACE (0x4) */ +#define NAU8810_AIFMT_SFT 3 +#define NAU8810_AIFMT_MASK (0x3 << NAU8810_AIFMT_SFT) +#define NAU8810_AIFMT_RIGHT (0x0 << NAU8810_AIFMT_SFT) +#define NAU8810_AIFMT_LEFT (0x1 << NAU8810_AIFMT_SFT) +#define NAU8810_AIFMT_I2S (0x2 << NAU8810_AIFMT_SFT) +#define NAU8810_AIFMT_PCM_A (0x3 << NAU8810_AIFMT_SFT) +#define NAU8810_WLEN_SFT 5 +#define NAU8810_WLEN_MASK (0x3 << NAU8810_WLEN_SFT) +#define NAU8810_WLEN_16 (0x0 << NAU8810_WLEN_SFT) +#define NAU8810_WLEN_20 (0x1 << NAU8810_WLEN_SFT) +#define NAU8810_WLEN_24 (0x2 << NAU8810_WLEN_SFT) +#define NAU8810_WLEN_32 (0x3 << NAU8810_WLEN_SFT) +#define NAU8810_FSP_IF (0x1 << 7) +#define NAU8810_BCLKP_IB (0x1 << 8) + +/* NAU8810_REG_COMP (0x5) */ +#define NAU8810_ADDAP_SFT 0 +#define NAU8810_ADCCM_SFT 1 +#define NAU8810_DACCM_SFT 3 + +/* NAU8810_REG_CLOCK (0x6) */ +#define NAU8810_CLKIO_MASK 0x1 +#define NAU8810_CLKIO_SLAVE 0x0 +#define NAU8810_CLKIO_MASTER 0x1 +#define NAU8810_BCLKSEL_SFT 2 +#define NAU8810_BCLKSEL_MASK (0x7 << NAU8810_BCLKSEL_SFT) +#define NAU8810_BCLKDIV_1 (0x0 << NAU8810_BCLKSEL_SFT) +#define NAU8810_BCLKDIV_2 (0x1 << NAU8810_BCLKSEL_SFT) +#define NAU8810_BCLKDIV_4 (0x2 << NAU8810_BCLKSEL_SFT) +#define NAU8810_BCLKDIV_8 (0x3 << NAU8810_BCLKSEL_SFT) +#define NAU8810_BCLKDIV_16 (0x4 << NAU8810_BCLKSEL_SFT) +#define NAU8810_BCLKDIV_32 (0x5 << NAU8810_BCLKSEL_SFT) +#define NAU8810_MCLKSEL_SFT 5 +#define NAU8810_MCLKSEL_MASK (0x7 << NAU8810_MCLKSEL_SFT) +#define NAU8810_CLKM_SFT 8 +#define NAU8810_CLKM_MASK (0x1 << NAU8810_CLKM_SFT) +#define NAU8810_CLKM_MCLK (0x0 << NAU8810_CLKM_SFT) +#define NAU8810_CLKM_PLL (0x1 << NAU8810_CLKM_SFT) + +/* NAU8810_REG_SMPLR (0x7) */ +#define NAU8810_SMPLR_SFT 1 +#define NAU8810_SMPLR_MASK (0x7 << NAU8810_SMPLR_SFT) +#define NAU8810_SMPLR_48K (0x0 << NAU8810_SMPLR_SFT) +#define NAU8810_SMPLR_32K (0x1 << NAU8810_SMPLR_SFT) +#define NAU8810_SMPLR_24K (0x2 << NAU8810_SMPLR_SFT) +#define NAU8810_SMPLR_16K (0x3 << NAU8810_SMPLR_SFT) +#define NAU8810_SMPLR_12K (0x4 << NAU8810_SMPLR_SFT) +#define NAU8810_SMPLR_8K (0x5 << NAU8810_SMPLR_SFT) + +/* NAU8810_REG_DAC (0xA) */ +#define NAU8810_DACPL_SFT 0 +#define NAU8810_DACOS_SFT 3 +#define NAU8810_DEEMP_SFT 4 + +/* NAU8810_REG_DACGAIN (0xB) */ +#define NAU8810_DACGAIN_SFT 0 + +/* NAU8810_REG_ADC (0xE) */ +#define NAU8810_ADCPL_SFT 0 +#define NAU8810_ADCOS_SFT 3 +#define NAU8810_HPF_SFT 4 +#define NAU8810_HPFEN_SFT 8 + +/* NAU8810_REG_ADCGAIN (0xF) */ +#define NAU8810_ADCGAIN_SFT 0 + +/* NAU8810_REG_EQ1 (0x12) */ +#define NAU8810_EQ1GC_SFT 0 +#define NAU8810_EQ1CF_SFT 5 +#define NAU8810_EQM_SFT 8 + +/* NAU8810_REG_EQ2 (0x13) */ +#define NAU8810_EQ2GC_SFT 0 +#define NAU8810_EQ2CF_SFT 5 +#define NAU8810_EQ2BW_SFT 8 + +/* NAU8810_REG_EQ3 (0x14) */ +#define NAU8810_EQ3GC_SFT 0 +#define NAU8810_EQ3CF_SFT 5 +#define NAU8810_EQ3BW_SFT 8 + +/* NAU8810_REG_EQ4 (0x15) */ +#define NAU8810_EQ4GC_SFT 0 +#define NAU8810_EQ4CF_SFT 5 +#define NAU8810_EQ4BW_SFT 8 + +/* NAU8810_REG_EQ5 (0x16) */ +#define NAU8810_EQ5GC_SFT 0 +#define NAU8810_EQ5CF_SFT 5 + +/* NAU8810_REG_DACLIM1 (0x18) */ +#define NAU8810_DACLIMATK_SFT 0 +#define NAU8810_DACLIMDCY_SFT 4 +#define NAU8810_DACLIMEN_SFT 8 + +/* NAU8810_REG_DACLIM2 (0x19) */ +#define NAU8810_DACLIMBST_SFT 0 +#define NAU8810_DACLIMTHL_SFT 4 + +/* NAU8810_REG_ALC1 (0x20) */ +#define NAU8810_ALCMINGAIN_SFT 0 +#define NAU8810_ALCMXGAIN_SFT 3 +#define NAU8810_ALCEN_SFT 8 + +/* NAU8810_REG_ALC2 (0x21) */ +#define NAU8810_ALCSL_SFT 0 +#define NAU8810_ALCHT_SFT 4 +#define NAU8810_ALCZC_SFT 8 + +/* NAU8810_REG_ALC3 (0x22) */ +#define NAU8810_ALCATK_SFT 0 +#define NAU8810_ALCDCY_SFT 4 +#define NAU8810_ALCM_SFT 8 + +/* NAU8810_REG_NOISEGATE (0x23) */ +#define NAU8810_ALCNTH_SFT 0 +#define NAU8810_ALCNEN_SFT 3 + +/* NAU8810_REG_PLLN (0x24) */ +#define NAU8810_PLLN_MASK 0xF +#define NAU8810_PLLMCLK_DIV2 (0x1 << 4) + +/* NAU8810_REG_PLLK1 (0x25) */ +#define NAU8810_PLLK1_SFT 18 +#define NAU8810_PLLK1_MASK 0x3F + +/* NAU8810_REG_PLLK2 (0x26) */ +#define NAU8810_PLLK2_SFT 9 +#define NAU8810_PLLK2_MASK 0x1FF + +/* NAU8810_REG_PLLK3 (0x27) */ +#define NAU8810_PLLK3_MASK 0x1FF + +/* NAU8810_REG_INPUT_SIGNAL (0x2C) */ +#define NAU8810_PMICPGA_SFT 0 +#define NAU8810_NMICPGA_SFT 1 + +/* NAU8810_REG_PGAGAIN (0x2D) */ +#define NAU8810_PGAGAIN_SFT 0 +#define NAU8810_PGAMT_SFT 6 +#define NAU8810_PGAZC_SFT 7 + +/* NAU8810_REG_ADCBOOST (0x2F) */ +#define NAU8810_PMICBSTGAIN_SFT 4 +#define NAU8810_PGABST_SFT 8 + +/* NAU8810_REG_SPKMIX (0x32) */ +#define NAU8810_DACSPK_SFT 0 +#define NAU8810_BYPSPK_SFT 1 + +/* NAU8810_REG_SPKGAIN (0x36) */ +#define NAU8810_SPKGAIN_SFT 0 +#define NAU8810_SPKMT_SFT 6 +#define NAU8810_SPKZC_SFT 7 + +/* NAU8810_REG_MONOMIX (0x38) */ +#define NAU8810_DACMOUT_SFT 0 +#define NAU8810_BYPMOUT_SFT 1 +#define NAU8810_MOUTMXMT_SFT 6 + + +/* System Clock Source */ +enum { + NAU8810_SCLK_MCLK, + NAU8810_SCLK_PLL, +}; + +struct nau8810_pll { + int pre_factor; + int mclk_scaler; + int pll_frac; + int pll_int; +}; + +struct nau8810 { + struct device *dev; + struct regmap *regmap; + struct nau8810_pll pll; + int sysclk; + int clk_id; +}; + +#endif diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 2e59a85..e643be9 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -1907,7 +1907,7 @@ static int nau8825_calc_fll_param(unsigned int fll_in, unsigned int fs, /* Calculate the FLL 10-bit integer input and the FLL 16-bit fractional * input based on FDCO, FREF and FLL ratio. */ - fvco = div_u64(fvco << 16, fref * fll_param->ratio); + fvco = div_u64(fvco_max << 16, fref * fll_param->ratio); fll_param->fll_int = (fvco >> 16) & 0x3FF; fll_param->fll_frac = fvco & 0xFFFF; return 0; @@ -2256,12 +2256,14 @@ static struct snd_soc_codec_driver nau8825_codec_driver = { .suspend = nau8825_suspend, .resume = nau8825_resume, - .controls = nau8825_controls, - .num_controls = ARRAY_SIZE(nau8825_controls), - .dapm_widgets = nau8825_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(nau8825_dapm_widgets), - .dapm_routes = nau8825_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(nau8825_dapm_routes), + .component_driver = { + .controls = nau8825_controls, + .num_controls = ARRAY_SIZE(nau8825_controls), + .dapm_widgets = nau8825_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(nau8825_dapm_widgets), + .dapm_routes = nau8825_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(nau8825_dapm_routes), + }, }; static void nau8825_reset_chip(struct regmap *regmap) diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index 33e1fc2d..0b14efa 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c @@ -289,12 +289,14 @@ static const struct regmap_config pcm1681_regmap = { }; static struct snd_soc_codec_driver soc_codec_dev_pcm1681 = { - .controls = pcm1681_controls, - .num_controls = ARRAY_SIZE(pcm1681_controls), - .dapm_widgets = pcm1681_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(pcm1681_dapm_widgets), - .dapm_routes = pcm1681_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(pcm1681_dapm_routes), + .component_driver = { + .controls = pcm1681_controls, + .num_controls = ARRAY_SIZE(pcm1681_controls), + .dapm_widgets = pcm1681_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm1681_dapm_widgets), + .dapm_routes = pcm1681_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm1681_dapm_routes), + }, }; static const struct i2c_device_id pcm1681_i2c_id[] = { diff --git a/sound/soc/codecs/pcm179x.c b/sound/soc/codecs/pcm179x.c index 88fbdd1..b813a15 100644 --- a/sound/soc/codecs/pcm179x.c +++ b/sound/soc/codecs/pcm179x.c @@ -206,12 +206,14 @@ const struct regmap_config pcm179x_regmap_config = { EXPORT_SYMBOL_GPL(pcm179x_regmap_config); static struct snd_soc_codec_driver soc_codec_dev_pcm179x = { - .controls = pcm179x_controls, - .num_controls = ARRAY_SIZE(pcm179x_controls), - .dapm_widgets = pcm179x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(pcm179x_dapm_widgets), - .dapm_routes = pcm179x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(pcm179x_dapm_routes), + .component_driver = { + .controls = pcm179x_controls, + .num_controls = ARRAY_SIZE(pcm179x_controls), + .dapm_widgets = pcm179x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm179x_dapm_widgets), + .dapm_routes = pcm179x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm179x_dapm_routes), + }, }; int pcm179x_common_init(struct device *dev, struct regmap *regmap) diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index 8fb445f..708af05 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c @@ -99,10 +99,12 @@ static struct snd_soc_dai_driver pcm3008_dai = { }; static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = { - .dapm_widgets = pcm3008_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(pcm3008_dapm_widgets), - .dapm_routes = pcm3008_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(pcm3008_dapm_routes), + .component_driver = { + .dapm_widgets = pcm3008_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm3008_dapm_widgets), + .dapm_routes = pcm3008_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm3008_dapm_routes), + }, }; static int pcm3008_codec_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index 992a77e..39bc02d 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -599,12 +599,14 @@ EXPORT_SYMBOL_GPL(pcm3168a_regmap); static const struct snd_soc_codec_driver pcm3168a_driver = { .idle_bias_off = true, - .controls = pcm3168a_snd_controls, - .num_controls = ARRAY_SIZE(pcm3168a_snd_controls), - .dapm_widgets = pcm3168a_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(pcm3168a_dapm_widgets), - .dapm_routes = pcm3168a_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(pcm3168a_dapm_routes) + .component_driver = { + .controls = pcm3168a_snd_controls, + .num_controls = ARRAY_SIZE(pcm3168a_snd_controls), + .dapm_widgets = pcm3168a_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm3168a_dapm_widgets), + .dapm_routes = pcm3168a_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm3168a_dapm_routes) + }, }; int pcm3168a_probe(struct device *dev, struct regmap *regmap) diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 047c489..72b19e6 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -1348,12 +1348,14 @@ static struct snd_soc_codec_driver pcm512x_codec_driver = { .set_bias_level = pcm512x_set_bias_level, .idle_bias_off = true, - .controls = pcm512x_controls, - .num_controls = ARRAY_SIZE(pcm512x_controls), - .dapm_widgets = pcm512x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets), - .dapm_routes = pcm512x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes), + .component_driver = { + .controls = pcm512x_controls, + .num_controls = ARRAY_SIZE(pcm512x_controls), + .dapm_widgets = pcm512x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets), + .dapm_routes = pcm512x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes), + }, }; static const struct regmap_range_cfg pcm512x_range = { diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 74c0e4e..9c365a7 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1053,12 +1053,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt286 = { .resume = rt286_resume, .set_bias_level = rt286_set_bias_level, .idle_bias_off = true, - .controls = rt286_snd_controls, - .num_controls = ARRAY_SIZE(rt286_snd_controls), - .dapm_widgets = rt286_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt286_dapm_widgets), - .dapm_routes = rt286_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt286_dapm_routes), + .component_driver = { + .controls = rt286_snd_controls, + .num_controls = ARRAY_SIZE(rt286_snd_controls), + .dapm_widgets = rt286_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt286_dapm_widgets), + .dapm_routes = rt286_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt286_dapm_routes), + }, }; static const struct regmap_config rt286_regmap = { diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index f80cfe4..5555864 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -1095,12 +1095,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt298 = { .resume = rt298_resume, .set_bias_level = rt298_set_bias_level, .idle_bias_off = true, - .controls = rt298_snd_controls, - .num_controls = ARRAY_SIZE(rt298_snd_controls), - .dapm_widgets = rt298_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt298_dapm_widgets), - .dapm_routes = rt298_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt298_dapm_routes), + .component_driver = { + .controls = rt298_snd_controls, + .num_controls = ARRAY_SIZE(rt298_snd_controls), + .dapm_widgets = rt298_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt298_dapm_widgets), + .dapm_routes = rt298_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt298_dapm_routes), + }, }; static const struct regmap_config rt298_regmap = { diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c index 77ff8eb..09103aa 100644 --- a/sound/soc/codecs/rt5514-spi.c +++ b/sound/soc/codecs/rt5514-spi.c @@ -236,7 +236,7 @@ static snd_pcm_uframes_t rt5514_spi_pcm_pointer( return bytes_to_frames(runtime, rt5514_dsp->dma_offset); } -static struct snd_pcm_ops rt5514_spi_pcm_ops = { +static const struct snd_pcm_ops rt5514_spi_pcm_ops = { .open = rt5514_spi_pcm_open, .hw_params = rt5514_spi_hw_params, .hw_free = rt5514_spi_hw_free, diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c index 7162f05..f24b7cf 100644 --- a/sound/soc/codecs/rt5514.c +++ b/sound/soc/codecs/rt5514.c @@ -278,7 +278,7 @@ static const DECLARE_TLV_DB_RANGE(bst_tlv, 8, 8, TLV_DB_SCALE_ITEM(1700, 0, 0) ); -static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); +static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); static int rt5514_dsp_voice_wake_up_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -352,10 +352,10 @@ static const struct snd_kcontrol_new rt5514_snd_controls[] = { SOC_DOUBLE_TLV("MIC Boost Volume", RT5514_ANA_CTRL_MICBST, RT5514_SEL_BSTL_SFT, RT5514_SEL_BSTR_SFT, 8, 0, bst_tlv), SOC_DOUBLE_R_TLV("ADC1 Capture Volume", RT5514_DOWNFILTER0_CTRL1, - RT5514_DOWNFILTER0_CTRL2, RT5514_AD_GAIN_SFT, 127, 0, + RT5514_DOWNFILTER0_CTRL2, RT5514_AD_GAIN_SFT, 63, 0, adc_vol_tlv), SOC_DOUBLE_R_TLV("ADC2 Capture Volume", RT5514_DOWNFILTER1_CTRL1, - RT5514_DOWNFILTER1_CTRL2, RT5514_AD_GAIN_SFT, 127, 0, + RT5514_DOWNFILTER1_CTRL2, RT5514_AD_GAIN_SFT, 63, 0, adc_vol_tlv), SOC_SINGLE_EXT("DSP Voice Wake Up", SND_SOC_NOPM, 0, 1, 0, rt5514_dsp_voice_wake_up_get, rt5514_dsp_voice_wake_up_put), @@ -1023,12 +1023,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5514 = { .probe = rt5514_probe, .idle_bias_off = true, .set_bias_level = rt5514_set_bias_level, - .controls = rt5514_snd_controls, - .num_controls = ARRAY_SIZE(rt5514_snd_controls), - .dapm_widgets = rt5514_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5514_dapm_widgets), - .dapm_routes = rt5514_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5514_dapm_routes), + .component_driver = { + .controls = rt5514_snd_controls, + .num_controls = ARRAY_SIZE(rt5514_snd_controls), + .dapm_widgets = rt5514_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5514_dapm_widgets), + .dapm_routes = rt5514_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5514_dapm_routes), + }, }; static const struct regmap_config rt5514_i2c_regmap = { diff --git a/sound/soc/codecs/rt5514.h b/sound/soc/codecs/rt5514.h index 68883c6..229de0e 100644 --- a/sound/soc/codecs/rt5514.h +++ b/sound/soc/codecs/rt5514.h @@ -196,8 +196,8 @@ #define RT5514_AD_AD_MIX_BIT 10 #define RT5514_AD_AD_MUTE (0x1 << 7) #define RT5514_AD_AD_MUTE_BIT 7 -#define RT5514_AD_GAIN_MASK (0x7f << 0) -#define RT5514_AD_GAIN_SFT 0 +#define RT5514_AD_GAIN_MASK (0x3f << 1) +#define RT5514_AD_GAIN_SFT 1 /* RT5514_ANA_CTRL_MICBST (0x2220) */ #define RT5514_SEL_BSTL_MASK (0xf << 4) diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index f527b5b..d1f273b 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -294,8 +294,7 @@ static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ -static unsigned int bst_tlv[] = { - TLV_DB_RANGE_HEAD(7), +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(bst_tlv, 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), @@ -303,7 +302,7 @@ static unsigned int bst_tlv[] = { 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), -}; +); static const struct snd_kcontrol_new rt5616_snd_controls[] = { /* Headphone Output Volume */ @@ -1267,14 +1266,14 @@ static int rt5616_resume(struct snd_soc_codec *codec) #define RT5616_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) -struct snd_soc_dai_ops rt5616_aif_dai_ops = { +static struct snd_soc_dai_ops rt5616_aif_dai_ops = { .hw_params = rt5616_hw_params, .set_fmt = rt5616_set_dai_fmt, .set_sysclk = rt5616_set_dai_sysclk, .set_pll = rt5616_set_dai_pll, }; -struct snd_soc_dai_driver rt5616_dai[] = { +static struct snd_soc_dai_driver rt5616_dai[] = { { .name = "rt5616-aif1", .id = RT5616_AIF1, @@ -1302,12 +1301,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5616 = { .resume = rt5616_resume, .set_bias_level = rt5616_set_bias_level, .idle_bias_off = true, - .controls = rt5616_snd_controls, - .num_controls = ARRAY_SIZE(rt5616_snd_controls), - .dapm_widgets = rt5616_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5616_dapm_widgets), - .dapm_routes = rt5616_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5616_dapm_routes), + .component_driver = { + .controls = rt5616_snd_controls, + .num_controls = ARRAY_SIZE(rt5616_snd_controls), + .dapm_widgets = rt5616_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5616_dapm_widgets), + .dapm_routes = rt5616_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5616_dapm_routes), + }, }; static const struct regmap_config rt5616_regmap = { diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 1be2bab..0e41808 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -1657,12 +1657,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5631 = { .probe = rt5631_probe, .set_bias_level = rt5631_set_bias_level, .suspend_bias_off = true, - .controls = rt5631_snd_controls, - .num_controls = ARRAY_SIZE(rt5631_snd_controls), - .dapm_widgets = rt5631_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5631_dapm_widgets), - .dapm_routes = rt5631_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5631_dapm_routes), + .component_driver = { + .controls = rt5631_snd_controls, + .num_controls = ARRAY_SIZE(rt5631_snd_controls), + .dapm_widgets = rt5631_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5631_dapm_widgets), + .dapm_routes = rt5631_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5631_dapm_routes), + }, }; static const struct i2c_device_id rt5631_i2c_id[] = { diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 09e8988..3cc1135 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -1870,6 +1870,9 @@ static int rt5640_set_dai_sysclk(struct snd_soc_dai *dai, case RT5640_SCLK_S_PLL1: reg_val |= RT5640_SCLK_SRC_PLL1; break; + case RT5640_SCLK_S_RCCLK: + reg_val |= RT5640_SCLK_SRC_RCCLK; + break; default: dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); return -EINVAL; @@ -2261,12 +2264,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5640 = { .resume = rt5640_resume, .set_bias_level = rt5640_set_bias_level, .idle_bias_off = true, - .controls = rt5640_snd_controls, - .num_controls = ARRAY_SIZE(rt5640_snd_controls), - .dapm_widgets = rt5640_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5640_dapm_widgets), - .dapm_routes = rt5640_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5640_dapm_routes), + .component_driver = { + .controls = rt5640_snd_controls, + .num_controls = ARRAY_SIZE(rt5640_snd_controls), + .dapm_widgets = rt5640_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5640_dapm_widgets), + .dapm_routes = rt5640_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5640_dapm_routes), + }, }; static const struct regmap_config rt5640_regmap = { diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h index 58b664b..90c8871 100644 --- a/sound/soc/codecs/rt5640.h +++ b/sound/soc/codecs/rt5640.h @@ -984,6 +984,7 @@ #define RT5640_SCLK_SRC_SFT 14 #define RT5640_SCLK_SRC_MCLK (0x0 << 14) #define RT5640_SCLK_SRC_PLL1 (0x1 << 14) +#define RT5640_SCLK_SRC_RCCLK (0x2 << 14) #define RT5640_PLL1_SRC_MASK (0x3 << 12) #define RT5640_PLL1_SRC_SFT 12 #define RT5640_PLL1_SRC_MCLK (0x0 << 12) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 490bfe6..10c2a56 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3484,12 +3484,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5645 = { .resume = rt5645_resume, .set_bias_level = rt5645_set_bias_level, .idle_bias_off = true, - .controls = rt5645_snd_controls, - .num_controls = ARRAY_SIZE(rt5645_snd_controls), - .dapm_widgets = rt5645_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5645_dapm_widgets), - .dapm_routes = rt5645_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5645_dapm_routes), + .component_driver = { + .controls = rt5645_snd_controls, + .num_controls = ARRAY_SIZE(rt5645_snd_controls), + .dapm_widgets = rt5645_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5645_dapm_widgets), + .dapm_routes = rt5645_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5645_dapm_routes), + }, }; static const struct regmap_config rt5645_regmap = { diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 7a61970..f5d3415 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1712,12 +1712,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5651 = { .resume = rt5651_resume, .set_bias_level = rt5651_set_bias_level, .idle_bias_off = true, - .controls = rt5651_snd_controls, - .num_controls = ARRAY_SIZE(rt5651_snd_controls), - .dapm_widgets = rt5651_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5651_dapm_widgets), - .dapm_routes = rt5651_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5651_dapm_routes), + .component_driver = { + .controls = rt5651_snd_controls, + .num_controls = ARRAY_SIZE(rt5651_snd_controls), + .dapm_widgets = rt5651_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5651_dapm_widgets), + .dapm_routes = rt5651_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5651_dapm_routes), + }, }; static const struct regmap_config rt5651_regmap = { diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index 1b30914..db54550 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ +#include <linux/clk.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> @@ -3565,7 +3566,9 @@ static int rt5659_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) static int rt5659_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec); + int ret; switch (level) { case SND_SOC_BIAS_PREPARE: @@ -3582,6 +3585,17 @@ static int rt5659_set_bias_level(struct snd_soc_codec *codec, RT5659_PWR_FV1 | RT5659_PWR_FV2); break; + case SND_SOC_BIAS_STANDBY: + if (dapm->bias_level == SND_SOC_BIAS_OFF) { + ret = clk_prepare_enable(rt5659->mclk); + if (ret) { + dev_err(codec->dev, + "failed to enable MCLK: %d\n", ret); + return ret; + } + } + break; + case SND_SOC_BIAS_OFF: regmap_update_bits(rt5659->regmap, RT5659_PWR_DIG_1, RT5659_PWR_LDO, 0); @@ -3591,6 +3605,7 @@ static int rt5659_set_bias_level(struct snd_soc_codec *codec, RT5659_PWR_MB | RT5659_PWR_VREF2); regmap_update_bits(rt5659->regmap, RT5659_DIG_MISC, RT5659_DIG_GATE_CTRL, 0); + clk_disable_unprepare(rt5659->mclk); break; default: @@ -3722,12 +3737,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5659 = { .resume = rt5659_resume, .set_bias_level = rt5659_set_bias_level, .idle_bias_off = true, - .controls = rt5659_snd_controls, - .num_controls = ARRAY_SIZE(rt5659_snd_controls), - .dapm_widgets = rt5659_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5659_dapm_widgets), - .dapm_routes = rt5659_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5659_dapm_routes), + .component_driver = { + .controls = rt5659_snd_controls, + .num_controls = ARRAY_SIZE(rt5659_snd_controls), + .dapm_widgets = rt5659_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5659_dapm_widgets), + .dapm_routes = rt5659_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5659_dapm_routes), + }, }; @@ -4020,6 +4037,15 @@ static int rt5659_i2c_probe(struct i2c_client *i2c, regmap_write(rt5659->regmap, RT5659_RESET, 0); + /* Check if MCLK provided */ + rt5659->mclk = devm_clk_get(&i2c->dev, "mclk"); + if (IS_ERR(rt5659->mclk)) { + if (PTR_ERR(rt5659->mclk) != -ENOENT) + return PTR_ERR(rt5659->mclk); + /* Otherwise mark the mclk pointer to NULL */ + rt5659->mclk = NULL; + } + rt5659_calibrate(rt5659); /* line in diff mode*/ @@ -4163,6 +4189,9 @@ static int rt5659_i2c_probe(struct i2c_client *i2c, if (ret) dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); + /* Enable IRQ output for GPIO1 pin any way */ + regmap_update_bits(rt5659->regmap, RT5659_GPIO_CTRL_1, + RT5659_GP1_PIN_MASK, RT5659_GP1_PIN_IRQ); } return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5659, diff --git a/sound/soc/codecs/rt5659.h b/sound/soc/codecs/rt5659.h index d31c9e5..8f1aeef 100644 --- a/sound/soc/codecs/rt5659.h +++ b/sound/soc/codecs/rt5659.h @@ -180,9 +180,9 @@ #define RT5659_IRQ_CTRL_1 0x00b6 #define RT5659_IRQ_CTRL_2 0x00b7 #define RT5659_IRQ_CTRL_3 0x00b8 -#define RT5659_IRQ_CTRL_4 0x00b9 -#define RT5659_IRQ_CTRL_5 0x00ba -#define RT5659_IRQ_CTRL_6 0x00bb +#define RT5659_IRQ_CTRL_4 0x00ba +#define RT5659_IRQ_CTRL_5 0x00bb +#define RT5659_IRQ_CTRL_6 0x00bc #define RT5659_INT_ST_1 0x00be #define RT5659_INT_ST_2 0x00bf #define RT5659_GPIO_CTRL_1 0x00c0 @@ -1796,6 +1796,7 @@ struct rt5659_priv { struct gpio_desc *gpiod_reset; struct snd_soc_jack *hs_jack; struct delayed_work jack_detect_work; + struct clk *mclk; int sysclk; int sysclk_src; diff --git a/sound/soc/codecs/rt5660.c b/sound/soc/codecs/rt5660.c new file mode 100644 index 0000000..9f0933c --- /dev/null +++ b/sound/soc/codecs/rt5660.c @@ -0,0 +1,1353 @@ +/* + * rt5660.c -- RT5660 ALSA SoC audio codec driver + * + * Copyright 2016 Realtek Semiconductor Corp. + * Author: Oder Chiou <oder_chiou@realtek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/regmap.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> +#include <linux/acpi.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> +#include <sound/initval.h> +#include <sound/tlv.h> + +#include "rl6231.h" +#include "rt5660.h" + +#define RT5660_DEVICE_ID 0x6338 + +#define RT5660_PR_RANGE_BASE (0xff + 1) +#define RT5660_PR_SPACING 0x100 + +#define RT5660_PR_BASE (RT5660_PR_RANGE_BASE + (0 * RT5660_PR_SPACING)) + +static const struct regmap_range_cfg rt5660_ranges[] = { + { .name = "PR", .range_min = RT5660_PR_BASE, + .range_max = RT5660_PR_BASE + 0xf3, + .selector_reg = RT5660_PRIV_INDEX, + .selector_mask = 0xff, + .selector_shift = 0x0, + .window_start = RT5660_PRIV_DATA, + .window_len = 0x1, }, +}; + +static const struct reg_sequence rt5660_patch[] = { + { RT5660_ALC_PGA_CTRL2, 0x44c3 }, + { RT5660_PR_BASE + 0x3d, 0x2600 }, +}; + +static const struct reg_default rt5660_reg[] = { + { 0x00, 0x0000 }, + { 0x01, 0xc800 }, + { 0x02, 0xc8c8 }, + { 0x0d, 0x1010 }, + { 0x0e, 0x1010 }, + { 0x19, 0xafaf }, + { 0x1c, 0x2f2f }, + { 0x1e, 0x0000 }, + { 0x27, 0x6060 }, + { 0x29, 0x8080 }, + { 0x2a, 0x4242 }, + { 0x2f, 0x0000 }, + { 0x3b, 0x0000 }, + { 0x3c, 0x007f }, + { 0x3d, 0x0000 }, + { 0x3e, 0x007f }, + { 0x45, 0xe000 }, + { 0x46, 0x003e }, + { 0x48, 0xf800 }, + { 0x4a, 0x0004 }, + { 0x4d, 0x0000 }, + { 0x4e, 0x0000 }, + { 0x4f, 0x01ff }, + { 0x50, 0x0000 }, + { 0x51, 0x0000 }, + { 0x52, 0x01ff }, + { 0x61, 0x0000 }, + { 0x62, 0x0000 }, + { 0x63, 0x00c0 }, + { 0x64, 0x0000 }, + { 0x65, 0x0000 }, + { 0x66, 0x0000 }, + { 0x70, 0x8000 }, + { 0x73, 0x7000 }, + { 0x74, 0x3c00 }, + { 0x75, 0x2800 }, + { 0x80, 0x0000 }, + { 0x81, 0x0000 }, + { 0x82, 0x0000 }, + { 0x8c, 0x0228 }, + { 0x8d, 0xa000 }, + { 0x8e, 0x0000 }, + { 0x92, 0x0000 }, + { 0x93, 0x3000 }, + { 0xa1, 0x0059 }, + { 0xa2, 0x0001 }, + { 0xa3, 0x5c80 }, + { 0xa4, 0x0146 }, + { 0xa5, 0x1f1f }, + { 0xa6, 0x78c6 }, + { 0xa7, 0xe5ec }, + { 0xa8, 0xba61 }, + { 0xa9, 0x3c78 }, + { 0xaa, 0x8ae2 }, + { 0xab, 0xe5ec }, + { 0xac, 0xc600 }, + { 0xad, 0xba61 }, + { 0xae, 0x17ed }, + { 0xb0, 0x2080 }, + { 0xb1, 0x0000 }, + { 0xb3, 0x001f }, + { 0xb4, 0x020c }, + { 0xb5, 0x1f00 }, + { 0xb6, 0x0000 }, + { 0xb7, 0x4000 }, + { 0xbb, 0x0000 }, + { 0xbd, 0x0000 }, + { 0xbe, 0x0000 }, + { 0xbf, 0x0100 }, + { 0xc0, 0x0000 }, + { 0xc2, 0x0000 }, + { 0xd3, 0xa220 }, + { 0xd9, 0x0809 }, + { 0xda, 0x0000 }, + { 0xe0, 0x8000 }, + { 0xe1, 0x0200 }, + { 0xe2, 0x8000 }, + { 0xe3, 0x0200 }, + { 0xe4, 0x0f20 }, + { 0xe5, 0x001f }, + { 0xe6, 0x020c }, + { 0xe7, 0x1f00 }, + { 0xe8, 0x0000 }, + { 0xe9, 0x4000 }, + { 0xea, 0x00a6 }, + { 0xeb, 0x04c3 }, + { 0xec, 0x27c8 }, + { 0xed, 0x7418 }, + { 0xee, 0xbf50 }, + { 0xef, 0x0045 }, + { 0xf0, 0x0007 }, + { 0xfa, 0x0000 }, + { 0xfd, 0x0000 }, + { 0xfe, 0x10ec }, + { 0xff, 0x6338 }, +}; + +static bool rt5660_volatile_register(struct device *dev, unsigned int reg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(rt5660_ranges); i++) + if ((reg >= rt5660_ranges[i].window_start && + reg <= rt5660_ranges[i].window_start + + rt5660_ranges[i].window_len) || + (reg >= rt5660_ranges[i].range_min && + reg <= rt5660_ranges[i].range_max)) + return true; + + switch (reg) { + case RT5660_RESET: + case RT5660_PRIV_DATA: + case RT5660_EQ_CTRL1: + case RT5660_IRQ_CTRL2: + case RT5660_INT_IRQ_ST: + case RT5660_VENDOR_ID: + case RT5660_VENDOR_ID1: + case RT5660_VENDOR_ID2: + return true; + default: + return false; + } +} + +static bool rt5660_readable_register(struct device *dev, unsigned int reg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(rt5660_ranges); i++) + if ((reg >= rt5660_ranges[i].window_start && + reg <= rt5660_ranges[i].window_start + + rt5660_ranges[i].window_len) || + (reg >= rt5660_ranges[i].range_min && + reg <= rt5660_ranges[i].range_max)) + return true; + + switch (reg) { + case RT5660_RESET: + case RT5660_SPK_VOL: + case RT5660_LOUT_VOL: + case RT5660_IN1_IN2: + case RT5660_IN3_IN4: + case RT5660_DAC1_DIG_VOL: + case RT5660_STO1_ADC_DIG_VOL: + case RT5660_ADC_BST_VOL1: + case RT5660_STO1_ADC_MIXER: + case RT5660_AD_DA_MIXER: + case RT5660_STO_DAC_MIXER: + case RT5660_DIG_INF1_DATA: + case RT5660_REC_L1_MIXER: + case RT5660_REC_L2_MIXER: + case RT5660_REC_R1_MIXER: + case RT5660_REC_R2_MIXER: + case RT5660_LOUT_MIXER: + case RT5660_SPK_MIXER: + case RT5660_SPO_MIXER: + case RT5660_SPO_CLSD_RATIO: + case RT5660_OUT_L_GAIN1: + case RT5660_OUT_L_GAIN2: + case RT5660_OUT_L1_MIXER: + case RT5660_OUT_R_GAIN1: + case RT5660_OUT_R_GAIN2: + case RT5660_OUT_R1_MIXER: + case RT5660_PWR_DIG1: + case RT5660_PWR_DIG2: + case RT5660_PWR_ANLG1: + case RT5660_PWR_ANLG2: + case RT5660_PWR_MIXER: + case RT5660_PWR_VOL: + case RT5660_PRIV_INDEX: + case RT5660_PRIV_DATA: + case RT5660_I2S1_SDP: + case RT5660_ADDA_CLK1: + case RT5660_ADDA_CLK2: + case RT5660_DMIC_CTRL1: + case RT5660_GLB_CLK: + case RT5660_PLL_CTRL1: + case RT5660_PLL_CTRL2: + case RT5660_CLSD_AMP_OC_CTRL: + case RT5660_CLSD_AMP_CTRL: + case RT5660_LOUT_AMP_CTRL: + case RT5660_SPK_AMP_SPKVDD: + case RT5660_MICBIAS: + case RT5660_CLSD_OUT_CTRL1: + case RT5660_CLSD_OUT_CTRL2: + case RT5660_DIPOLE_MIC_CTRL1: + case RT5660_DIPOLE_MIC_CTRL2: + case RT5660_DIPOLE_MIC_CTRL3: + case RT5660_DIPOLE_MIC_CTRL4: + case RT5660_DIPOLE_MIC_CTRL5: + case RT5660_DIPOLE_MIC_CTRL6: + case RT5660_DIPOLE_MIC_CTRL7: + case RT5660_DIPOLE_MIC_CTRL8: + case RT5660_DIPOLE_MIC_CTRL9: + case RT5660_DIPOLE_MIC_CTRL10: + case RT5660_DIPOLE_MIC_CTRL11: + case RT5660_DIPOLE_MIC_CTRL12: + case RT5660_EQ_CTRL1: + case RT5660_EQ_CTRL2: + case RT5660_DRC_AGC_CTRL1: + case RT5660_DRC_AGC_CTRL2: + case RT5660_DRC_AGC_CTRL3: + case RT5660_DRC_AGC_CTRL4: + case RT5660_DRC_AGC_CTRL5: + case RT5660_JD_CTRL: + case RT5660_IRQ_CTRL1: + case RT5660_IRQ_CTRL2: + case RT5660_INT_IRQ_ST: + case RT5660_GPIO_CTRL1: + case RT5660_GPIO_CTRL2: + case RT5660_WIND_FILTER_CTRL1: + case RT5660_SV_ZCD1: + case RT5660_SV_ZCD2: + case RT5660_DRC1_LM_CTRL1: + case RT5660_DRC1_LM_CTRL2: + case RT5660_DRC2_LM_CTRL1: + case RT5660_DRC2_LM_CTRL2: + case RT5660_MULTI_DRC_CTRL: + case RT5660_DRC2_CTRL1: + case RT5660_DRC2_CTRL2: + case RT5660_DRC2_CTRL3: + case RT5660_DRC2_CTRL4: + case RT5660_DRC2_CTRL5: + case RT5660_ALC_PGA_CTRL1: + case RT5660_ALC_PGA_CTRL2: + case RT5660_ALC_PGA_CTRL3: + case RT5660_ALC_PGA_CTRL4: + case RT5660_ALC_PGA_CTRL5: + case RT5660_ALC_PGA_CTRL6: + case RT5660_ALC_PGA_CTRL7: + case RT5660_GEN_CTRL1: + case RT5660_GEN_CTRL2: + case RT5660_GEN_CTRL3: + case RT5660_VENDOR_ID: + case RT5660_VENDOR_ID1: + case RT5660_VENDOR_ID2: + return true; + default: + return false; + } +} + +static const DECLARE_TLV_DB_SCALE(rt5660_out_vol_tlv, -4650, 150, 0); +static const DECLARE_TLV_DB_SCALE(rt5660_dac_vol_tlv, -6525, 75, 0); +static const DECLARE_TLV_DB_SCALE(rt5660_adc_vol_tlv, -1725, 75, 0); +static const DECLARE_TLV_DB_SCALE(rt5660_adc_bst_tlv, 0, 1200, 0); +static const DECLARE_TLV_DB_SCALE(rt5660_bst_tlv, -1200, 75, 0); + +static const struct snd_kcontrol_new rt5660_snd_controls[] = { + /* Speaker Output Volume */ + SOC_SINGLE("Speaker Playback Switch", RT5660_SPK_VOL, RT5660_L_MUTE_SFT, + 1, 1), + SOC_SINGLE_TLV("Speaker Playback Volume", RT5660_SPK_VOL, + RT5660_L_VOL_SFT, 39, 1, rt5660_out_vol_tlv), + + /* OUTPUT Control */ + SOC_DOUBLE("OUT Playback Switch", RT5660_LOUT_VOL, RT5660_L_MUTE_SFT, + RT5660_R_MUTE_SFT, 1, 1), + SOC_DOUBLE_TLV("OUT Playback Volume", RT5660_LOUT_VOL, RT5660_L_VOL_SFT, + RT5660_R_VOL_SFT, 39, 1, rt5660_out_vol_tlv), + + /* DAC Digital Volume */ + SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5660_DAC1_DIG_VOL, + RT5660_DAC_L1_VOL_SFT, RT5660_DAC_R1_VOL_SFT, 87, 0, + rt5660_dac_vol_tlv), + + /* IN1/IN2/IN3 Control */ + SOC_SINGLE_TLV("IN1 Boost Volume", RT5660_IN1_IN2, RT5660_BST_SFT1, 69, + 0, rt5660_bst_tlv), + SOC_SINGLE_TLV("IN2 Boost Volume", RT5660_IN1_IN2, RT5660_BST_SFT2, 69, + 0, rt5660_bst_tlv), + SOC_SINGLE_TLV("IN3 Boost Volume", RT5660_IN3_IN4, RT5660_BST_SFT3, 69, + 0, rt5660_bst_tlv), + + /* ADC Digital Volume Control */ + SOC_DOUBLE("ADC Capture Switch", RT5660_STO1_ADC_DIG_VOL, + RT5660_L_MUTE_SFT, RT5660_R_MUTE_SFT, 1, 1), + SOC_DOUBLE_TLV("ADC Capture Volume", RT5660_STO1_ADC_DIG_VOL, + RT5660_ADC_L_VOL_SFT, RT5660_ADC_R_VOL_SFT, 63, 0, + rt5660_adc_vol_tlv), + + /* ADC Boost Volume Control */ + SOC_DOUBLE_TLV("STO1 ADC Boost Gain Volume", RT5660_ADC_BST_VOL1, + RT5660_STO1_ADC_L_BST_SFT, RT5660_STO1_ADC_R_BST_SFT, 3, 0, + rt5660_adc_bst_tlv), +}; + +/** + * rt5660_set_dmic_clk - Set parameter of dmic. + * + * @w: DAPM widget. + * @kcontrol: The kcontrol of this widget. + * @event: Event id. + * + */ +static int rt5660_set_dmic_clk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + int idx, rate; + + rate = rt5660->sysclk / rl6231_get_pre_div(rt5660->regmap, + RT5660_ADDA_CLK1, RT5660_I2S_PD1_SFT); + idx = rl6231_calc_dmic_clk(rate); + if (idx < 0) + dev_err(codec->dev, "Failed to set DMIC clock\n"); + else + snd_soc_update_bits(codec, RT5660_DMIC_CTRL1, + RT5660_DMIC_CLK_MASK, idx << RT5660_DMIC_CLK_SFT); + + return idx; +} + +static int rt5660_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); + unsigned int val; + + val = snd_soc_read(codec, RT5660_GLB_CLK); + val &= RT5660_SCLK_SRC_MASK; + if (val == RT5660_SCLK_SRC_PLL1) + return 1; + else + return 0; +} + +/* Digital Mixer */ +static const struct snd_kcontrol_new rt5660_sto1_adc_l_mix[] = { + SOC_DAPM_SINGLE("ADC1 Switch", RT5660_STO1_ADC_MIXER, + RT5660_M_ADC_L1_SFT, 1, 1), + SOC_DAPM_SINGLE("ADC2 Switch", RT5660_STO1_ADC_MIXER, + RT5660_M_ADC_L2_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_sto1_adc_r_mix[] = { + SOC_DAPM_SINGLE("ADC1 Switch", RT5660_STO1_ADC_MIXER, + RT5660_M_ADC_R1_SFT, 1, 1), + SOC_DAPM_SINGLE("ADC2 Switch", RT5660_STO1_ADC_MIXER, + RT5660_M_ADC_R2_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_dac_l_mix[] = { + SOC_DAPM_SINGLE("Stereo ADC Switch", RT5660_AD_DA_MIXER, + RT5660_M_ADCMIX_L_SFT, 1, 1), + SOC_DAPM_SINGLE("DAC1 Switch", RT5660_AD_DA_MIXER, + RT5660_M_DAC1_L_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_dac_r_mix[] = { + SOC_DAPM_SINGLE("Stereo ADC Switch", RT5660_AD_DA_MIXER, + RT5660_M_ADCMIX_R_SFT, 1, 1), + SOC_DAPM_SINGLE("DAC1 Switch", RT5660_AD_DA_MIXER, + RT5660_M_DAC1_R_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_sto_dac_l_mix[] = { + SOC_DAPM_SINGLE("DAC L1 Switch", RT5660_STO_DAC_MIXER, + RT5660_M_DAC_L1_SFT, 1, 1), + SOC_DAPM_SINGLE("DAC R1 Switch", RT5660_STO_DAC_MIXER, + RT5660_M_DAC_R1_STO_L_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_sto_dac_r_mix[] = { + SOC_DAPM_SINGLE("DAC R1 Switch", RT5660_STO_DAC_MIXER, + RT5660_M_DAC_R1_SFT, 1, 1), + SOC_DAPM_SINGLE("DAC L1 Switch", RT5660_STO_DAC_MIXER, + RT5660_M_DAC_L1_STO_R_SFT, 1, 1), +}; + +/* Analog Input Mixer */ +static const struct snd_kcontrol_new rt5660_rec_l_mix[] = { + SOC_DAPM_SINGLE("BST3 Switch", RT5660_REC_L2_MIXER, + RT5660_M_BST3_RM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("BST2 Switch", RT5660_REC_L2_MIXER, + RT5660_M_BST2_RM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("BST1 Switch", RT5660_REC_L2_MIXER, + RT5660_M_BST1_RM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("OUT MIXL Switch", RT5660_REC_L2_MIXER, + RT5660_M_OM_L_RM_L_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_rec_r_mix[] = { + SOC_DAPM_SINGLE("BST3 Switch", RT5660_REC_R2_MIXER, + RT5660_M_BST3_RM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("BST2 Switch", RT5660_REC_R2_MIXER, + RT5660_M_BST2_RM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("BST1 Switch", RT5660_REC_R2_MIXER, + RT5660_M_BST1_RM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("OUT MIXR Switch", RT5660_REC_R2_MIXER, + RT5660_M_OM_R_RM_R_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_spk_mix[] = { + SOC_DAPM_SINGLE("BST3 Switch", RT5660_SPK_MIXER, + RT5660_M_BST3_SM_SFT, 1, 1), + SOC_DAPM_SINGLE("BST1 Switch", RT5660_SPK_MIXER, + RT5660_M_BST1_SM_SFT, 1, 1), + SOC_DAPM_SINGLE("DACL Switch", RT5660_SPK_MIXER, + RT5660_M_DACL_SM_SFT, 1, 1), + SOC_DAPM_SINGLE("DACR Switch", RT5660_SPK_MIXER, + RT5660_M_DACR_SM_SFT, 1, 1), + SOC_DAPM_SINGLE("OUTMIXL Switch", RT5660_SPK_MIXER, + RT5660_M_OM_L_SM_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_out_l_mix[] = { + SOC_DAPM_SINGLE("BST3 Switch", RT5660_OUT_L1_MIXER, + RT5660_M_BST3_OM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("BST2 Switch", RT5660_OUT_L1_MIXER, + RT5660_M_BST2_OM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("BST1 Switch", RT5660_OUT_L1_MIXER, + RT5660_M_BST1_OM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("RECMIXL Switch", RT5660_OUT_L1_MIXER, + RT5660_M_RM_L_OM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("DACR Switch", RT5660_OUT_L1_MIXER, + RT5660_M_DAC_R_OM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("DACL Switch", RT5660_OUT_L1_MIXER, + RT5660_M_DAC_L_OM_L_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_out_r_mix[] = { + SOC_DAPM_SINGLE("BST2 Switch", RT5660_OUT_R1_MIXER, + RT5660_M_BST2_OM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("BST1 Switch", RT5660_OUT_R1_MIXER, + RT5660_M_BST1_OM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("RECMIXR Switch", RT5660_OUT_R1_MIXER, + RT5660_M_RM_R_OM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("DACR Switch", RT5660_OUT_R1_MIXER, + RT5660_M_DAC_R_OM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("DACL Switch", RT5660_OUT_R1_MIXER, + RT5660_M_DAC_L_OM_R_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_spo_mix[] = { + SOC_DAPM_SINGLE("DACR Switch", RT5660_SPO_MIXER, + RT5660_M_DAC_R_SPM_SFT, 1, 1), + SOC_DAPM_SINGLE("DACL Switch", RT5660_SPO_MIXER, + RT5660_M_DAC_L_SPM_SFT, 1, 1), + SOC_DAPM_SINGLE("SPKVOL Switch", RT5660_SPO_MIXER, + RT5660_M_SV_SPM_SFT, 1, 1), + SOC_DAPM_SINGLE("BST1 Switch", RT5660_SPO_MIXER, + RT5660_M_BST1_SPM_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_lout_mix[] = { + SOC_DAPM_SINGLE("DAC Switch", RT5660_LOUT_MIXER, + RT5660_M_DAC1_LM_SFT, 1, 1), + SOC_DAPM_SINGLE("OUTMIX Switch", RT5660_LOUT_MIXER, + RT5660_M_LOVOL_LM_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new spk_vol_control = + SOC_DAPM_SINGLE("Switch", RT5660_SPK_VOL, + RT5660_VOL_L_SFT, 1, 1); + +static const struct snd_kcontrol_new lout_l_vol_control = + SOC_DAPM_SINGLE("Switch", RT5660_LOUT_VOL, + RT5660_VOL_L_SFT, 1, 1); + +static const struct snd_kcontrol_new lout_r_vol_control = + SOC_DAPM_SINGLE("Switch", RT5660_LOUT_VOL, + RT5660_VOL_R_SFT, 1, 1); + +/* Interface data select */ +static const char * const rt5660_data_select[] = { + "L/R", "R/L", "L/L", "R/R" +}; + +static const SOC_ENUM_SINGLE_DECL(rt5660_if1_dac_enum, + RT5660_DIG_INF1_DATA, RT5660_IF1_DAC_IN_SFT, rt5660_data_select); + +static const SOC_ENUM_SINGLE_DECL(rt5660_if1_adc_enum, + RT5660_DIG_INF1_DATA, RT5660_IF1_ADC_IN_SFT, rt5660_data_select); + +static const struct snd_kcontrol_new rt5660_if1_dac_swap_mux = + SOC_DAPM_ENUM("IF1 DAC Swap Source", rt5660_if1_dac_enum); + +static const struct snd_kcontrol_new rt5660_if1_adc_swap_mux = + SOC_DAPM_ENUM("IF1 ADC Swap Source", rt5660_if1_adc_enum); + +static int rt5660_lout_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, RT5660_LOUT_AMP_CTRL, + RT5660_LOUT_CO_MASK | RT5660_LOUT_CB_MASK, + RT5660_LOUT_CO_EN | RT5660_LOUT_CB_PU); + break; + + case SND_SOC_DAPM_PRE_PMD: + snd_soc_update_bits(codec, RT5660_LOUT_AMP_CTRL, + RT5660_LOUT_CO_MASK | RT5660_LOUT_CB_MASK, + RT5660_LOUT_CO_DIS | RT5660_LOUT_CB_PD); + break; + + default: + return 0; + } + + return 0; +} + +static const struct snd_soc_dapm_widget rt5660_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("LDO2", RT5660_PWR_ANLG1, + RT5660_PWR_LDO2_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL1", RT5660_PWR_ANLG2, + RT5660_PWR_PLL_BIT, 0, NULL, 0), + + /* MICBIAS */ + SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5660_PWR_ANLG2, + RT5660_PWR_MB1_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MICBIAS2", RT5660_PWR_ANLG2, + RT5660_PWR_MB2_BIT, 0, NULL, 0), + + /* Input Side */ + /* Input Lines */ + SND_SOC_DAPM_INPUT("DMIC L1"), + SND_SOC_DAPM_INPUT("DMIC R1"), + + SND_SOC_DAPM_INPUT("IN1P"), + SND_SOC_DAPM_INPUT("IN1N"), + SND_SOC_DAPM_INPUT("IN2P"), + SND_SOC_DAPM_INPUT("IN3P"), + SND_SOC_DAPM_INPUT("IN3N"), + + SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0, + rt5660_set_dmic_clk, SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_SUPPLY("DMIC Power", RT5660_DMIC_CTRL1, + RT5660_DMIC_1_EN_SFT, 0, NULL, 0), + + /* Boost */ + SND_SOC_DAPM_PGA("BST1", RT5660_PWR_ANLG2, RT5660_PWR_BST1_BIT, 0, + NULL, 0), + SND_SOC_DAPM_PGA("BST2", RT5660_PWR_ANLG2, RT5660_PWR_BST2_BIT, 0, + NULL, 0), + SND_SOC_DAPM_PGA("BST3", RT5660_PWR_ANLG2, RT5660_PWR_BST3_BIT, 0, + NULL, 0), + + /* REC Mixer */ + SND_SOC_DAPM_MIXER("RECMIXL", RT5660_PWR_MIXER, RT5660_PWR_RM_L_BIT, + 0, rt5660_rec_l_mix, ARRAY_SIZE(rt5660_rec_l_mix)), + SND_SOC_DAPM_MIXER("RECMIXR", RT5660_PWR_MIXER, RT5660_PWR_RM_R_BIT, + 0, rt5660_rec_r_mix, ARRAY_SIZE(rt5660_rec_r_mix)), + + /* ADCs */ + SND_SOC_DAPM_ADC("ADC L", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADC R", NULL, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_SUPPLY("ADC L power", RT5660_PWR_DIG1, + RT5660_PWR_ADC_L_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC R power", RT5660_PWR_DIG1, + RT5660_PWR_ADC_R_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC clock", RT5660_PR_BASE + RT5660_CHOP_DAC_ADC, + 12, 0, NULL, 0), + + /* ADC Mixer */ + SND_SOC_DAPM_SUPPLY("adc stereo1 filter", RT5660_PWR_DIG2, + RT5660_PWR_ADC_S1F_BIT, 0, NULL, 0), + SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0, + rt5660_sto1_adc_l_mix, ARRAY_SIZE(rt5660_sto1_adc_l_mix)), + SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0, + rt5660_sto1_adc_r_mix, ARRAY_SIZE(rt5660_sto1_adc_r_mix)), + + /* ADC */ + SND_SOC_DAPM_ADC("Stereo1 ADC MIXL", NULL, RT5660_STO1_ADC_DIG_VOL, + RT5660_L_MUTE_SFT, 1), + SND_SOC_DAPM_ADC("Stereo1 ADC MIXR", NULL, RT5660_STO1_ADC_DIG_VOL, + RT5660_R_MUTE_SFT, 1), + + /* Digital Interface */ + SND_SOC_DAPM_SUPPLY("I2S1", RT5660_PWR_DIG1, RT5660_PWR_I2S1_BIT, 0, + NULL, 0), + SND_SOC_DAPM_PGA("IF1 DAC", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("IF1 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("IF1 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MUX("IF1 DAC Swap Mux", SND_SOC_NOPM, 0, 0, + &rt5660_if1_dac_swap_mux), + SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MUX("IF1 ADC Swap Mux", SND_SOC_NOPM, 0, 0, + &rt5660_if1_adc_swap_mux), + + /* Audio Interface */ + SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), + + /* Output Side */ + /* DAC mixer before sound effect */ + SND_SOC_DAPM_MIXER("DAC1 MIXL", SND_SOC_NOPM, 0, 0, rt5660_dac_l_mix, + ARRAY_SIZE(rt5660_dac_l_mix)), + SND_SOC_DAPM_MIXER("DAC1 MIXR", SND_SOC_NOPM, 0, 0, rt5660_dac_r_mix, + ARRAY_SIZE(rt5660_dac_r_mix)), + + /* DAC Mixer */ + SND_SOC_DAPM_SUPPLY("dac stereo1 filter", RT5660_PWR_DIG2, + RT5660_PWR_DAC_S1F_BIT, 0, NULL, 0), + SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0, + rt5660_sto_dac_l_mix, ARRAY_SIZE(rt5660_sto_dac_l_mix)), + SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0, + rt5660_sto_dac_r_mix, ARRAY_SIZE(rt5660_sto_dac_r_mix)), + + /* DACs */ + SND_SOC_DAPM_DAC("DAC L1", NULL, RT5660_PWR_DIG1, + RT5660_PWR_DAC_L1_BIT, 0), + SND_SOC_DAPM_DAC("DAC R1", NULL, RT5660_PWR_DIG1, + RT5660_PWR_DAC_R1_BIT, 0), + + /* OUT Mixer */ + SND_SOC_DAPM_MIXER("SPK MIX", RT5660_PWR_MIXER, RT5660_PWR_SM_BIT, + 0, rt5660_spk_mix, ARRAY_SIZE(rt5660_spk_mix)), + SND_SOC_DAPM_MIXER("OUT MIXL", RT5660_PWR_MIXER, RT5660_PWR_OM_L_BIT, + 0, rt5660_out_l_mix, ARRAY_SIZE(rt5660_out_l_mix)), + SND_SOC_DAPM_MIXER("OUT MIXR", RT5660_PWR_MIXER, RT5660_PWR_OM_R_BIT, + 0, rt5660_out_r_mix, ARRAY_SIZE(rt5660_out_r_mix)), + + /* Output Volume */ + SND_SOC_DAPM_SWITCH("SPKVOL", RT5660_PWR_VOL, + RT5660_PWR_SV_BIT, 0, &spk_vol_control), + SND_SOC_DAPM_PGA("DAC 1", SND_SOC_NOPM, + 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("LOUTVOL", SND_SOC_NOPM, + 0, 0, NULL, 0), + SND_SOC_DAPM_SWITCH("LOUTVOL L", SND_SOC_NOPM, + RT5660_PWR_LV_L_BIT, 0, &lout_l_vol_control), + SND_SOC_DAPM_SWITCH("LOUTVOL R", SND_SOC_NOPM, + RT5660_PWR_LV_R_BIT, 0, &lout_r_vol_control), + + /* HPO/LOUT/Mono Mixer */ + SND_SOC_DAPM_MIXER("SPO MIX", SND_SOC_NOPM, 0, + 0, rt5660_spo_mix, ARRAY_SIZE(rt5660_spo_mix)), + SND_SOC_DAPM_MIXER("LOUT MIX", SND_SOC_NOPM, 0, 0, + rt5660_lout_mix, ARRAY_SIZE(rt5660_lout_mix)), + SND_SOC_DAPM_SUPPLY("VREF HP", RT5660_GEN_CTRL1, + RT5660_PWR_VREF_HP_SFT, 0, NULL, 0), + SND_SOC_DAPM_PGA_S("LOUT amp", 1, RT5660_PWR_ANLG1, + RT5660_PWR_HA_BIT, 0, rt5660_lout_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_PGA_S("SPK amp", 1, RT5660_PWR_DIG1, + RT5660_PWR_CLS_D_BIT, 0, NULL, 0), + + /* Output Lines */ + SND_SOC_DAPM_OUTPUT("LOUTL"), + SND_SOC_DAPM_OUTPUT("LOUTR"), + SND_SOC_DAPM_OUTPUT("SPO"), +}; + +static const struct snd_soc_dapm_route rt5660_dapm_routes[] = { + { "MICBIAS1", NULL, "LDO2" }, + { "MICBIAS2", NULL, "LDO2" }, + + { "BST1", NULL, "IN1P" }, + { "BST1", NULL, "IN1N" }, + { "BST2", NULL, "IN2P" }, + { "BST3", NULL, "IN3P" }, + { "BST3", NULL, "IN3N" }, + + { "RECMIXL", "BST3 Switch", "BST3" }, + { "RECMIXL", "BST2 Switch", "BST2" }, + { "RECMIXL", "BST1 Switch", "BST1" }, + { "RECMIXL", "OUT MIXL Switch", "OUT MIXL" }, + + { "RECMIXR", "BST3 Switch", "BST3" }, + { "RECMIXR", "BST2 Switch", "BST2" }, + { "RECMIXR", "BST1 Switch", "BST1" }, + { "RECMIXR", "OUT MIXR Switch", "OUT MIXR" }, + + { "ADC L", NULL, "RECMIXL" }, + { "ADC L", NULL, "ADC L power" }, + { "ADC L", NULL, "ADC clock" }, + { "ADC R", NULL, "RECMIXR" }, + { "ADC R", NULL, "ADC R power" }, + { "ADC R", NULL, "ADC clock" }, + + {"DMIC L1", NULL, "DMIC CLK"}, + {"DMIC L1", NULL, "DMIC Power"}, + {"DMIC R1", NULL, "DMIC CLK"}, + {"DMIC R1", NULL, "DMIC Power"}, + + { "Sto1 ADC MIXL", "ADC1 Switch", "ADC L" }, + { "Sto1 ADC MIXL", "ADC2 Switch", "DMIC L1" }, + { "Sto1 ADC MIXR", "ADC1 Switch", "ADC R" }, + { "Sto1 ADC MIXR", "ADC2 Switch", "DMIC R1" }, + + { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, + { "Stereo1 ADC MIXL", NULL, "adc stereo1 filter" }, + { "adc stereo1 filter", NULL, "PLL1", rt5660_is_sys_clk_from_pll }, + + { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, + { "Stereo1 ADC MIXR", NULL, "adc stereo1 filter" }, + { "adc stereo1 filter", NULL, "PLL1", rt5660_is_sys_clk_from_pll }, + + { "IF1 ADC", NULL, "Stereo1 ADC MIXL" }, + { "IF1 ADC", NULL, "Stereo1 ADC MIXR" }, + { "IF1 ADC", NULL, "I2S1" }, + + { "IF1 ADC Swap Mux", "L/R", "IF1 ADC" }, + { "IF1 ADC Swap Mux", "R/L", "IF1 ADC" }, + { "IF1 ADC Swap Mux", "L/L", "IF1 ADC" }, + { "IF1 ADC Swap Mux", "R/R", "IF1 ADC" }, + { "AIF1TX", NULL, "IF1 ADC Swap Mux" }, + + { "IF1 DAC", NULL, "AIF1RX" }, + { "IF1 DAC", NULL, "I2S1" }, + + { "IF1 DAC Swap Mux", "L/R", "IF1 DAC" }, + { "IF1 DAC Swap Mux", "R/L", "IF1 DAC" }, + { "IF1 DAC Swap Mux", "L/L", "IF1 DAC" }, + { "IF1 DAC Swap Mux", "R/R", "IF1 DAC" }, + + { "IF1 DAC L", NULL, "IF1 DAC Swap Mux" }, + { "IF1 DAC R", NULL, "IF1 DAC Swap Mux" }, + + { "DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL" }, + { "DAC1 MIXL", "DAC1 Switch", "IF1 DAC L" }, + { "DAC1 MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR" }, + { "DAC1 MIXR", "DAC1 Switch", "IF1 DAC R" }, + + { "Stereo DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" }, + { "Stereo DAC MIXL", "DAC R1 Switch", "DAC1 MIXR" }, + { "Stereo DAC MIXL", NULL, "dac stereo1 filter" }, + { "dac stereo1 filter", NULL, "PLL1", rt5660_is_sys_clk_from_pll }, + { "Stereo DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" }, + { "Stereo DAC MIXR", "DAC L1 Switch", "DAC1 MIXL" }, + { "Stereo DAC MIXR", NULL, "dac stereo1 filter" }, + { "dac stereo1 filter", NULL, "PLL1", rt5660_is_sys_clk_from_pll }, + + { "DAC L1", NULL, "Stereo DAC MIXL" }, + { "DAC R1", NULL, "Stereo DAC MIXR" }, + + { "SPK MIX", "BST3 Switch", "BST3" }, + { "SPK MIX", "BST1 Switch", "BST1" }, + { "SPK MIX", "DACL Switch", "DAC L1" }, + { "SPK MIX", "DACR Switch", "DAC R1" }, + { "SPK MIX", "OUTMIXL Switch", "OUT MIXL" }, + + { "OUT MIXL", "BST3 Switch", "BST3" }, + { "OUT MIXL", "BST2 Switch", "BST2" }, + { "OUT MIXL", "BST1 Switch", "BST1" }, + { "OUT MIXL", "RECMIXL Switch", "RECMIXL" }, + { "OUT MIXL", "DACR Switch", "DAC R1" }, + { "OUT MIXL", "DACL Switch", "DAC L1" }, + + { "OUT MIXR", "BST2 Switch", "BST2" }, + { "OUT MIXR", "BST1 Switch", "BST1" }, + { "OUT MIXR", "RECMIXR Switch", "RECMIXR" }, + { "OUT MIXR", "DACR Switch", "DAC R1" }, + { "OUT MIXR", "DACL Switch", "DAC L1" }, + + { "SPO MIX", "DACR Switch", "DAC R1" }, + { "SPO MIX", "DACL Switch", "DAC L1" }, + { "SPO MIX", "SPKVOL Switch", "SPKVOL" }, + { "SPO MIX", "BST1 Switch", "BST1" }, + + { "SPKVOL", "Switch", "SPK MIX" }, + { "LOUTVOL L", "Switch", "OUT MIXL" }, + { "LOUTVOL R", "Switch", "OUT MIXR" }, + + { "LOUTVOL", NULL, "LOUTVOL L" }, + { "LOUTVOL", NULL, "LOUTVOL R" }, + + { "DAC 1", NULL, "DAC L1" }, + { "DAC 1", NULL, "DAC R1" }, + + { "LOUT MIX", "DAC Switch", "DAC 1" }, + { "LOUT MIX", "OUTMIX Switch", "LOUTVOL" }, + + { "LOUT amp", NULL, "LOUT MIX" }, + { "LOUT amp", NULL, "VREF HP" }, + { "LOUTL", NULL, "LOUT amp" }, + { "LOUTR", NULL, "LOUT amp" }, + + { "SPK amp", NULL, "SPO MIX" }, + { "SPO", NULL, "SPK amp" }, +}; + +static int rt5660_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 rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + unsigned int val_len = 0, val_clk, mask_clk; + int pre_div, bclk_ms, frame_size; + + rt5660->lrck[dai->id] = params_rate(params); + pre_div = rl6231_get_clk_info(rt5660->sysclk, rt5660->lrck[dai->id]); + if (pre_div < 0) { + dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n", + rt5660->lrck[dai->id], dai->id); + return -EINVAL; + } + + frame_size = snd_soc_params_to_frame_size(params); + if (frame_size < 0) { + dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size); + return frame_size; + } + + if (frame_size > 32) + bclk_ms = 1; + else + bclk_ms = 0; + + rt5660->bclk[dai->id] = rt5660->lrck[dai->id] * (32 << bclk_ms); + + dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n", + rt5660->bclk[dai->id], rt5660->lrck[dai->id]); + dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", + bclk_ms, pre_div, dai->id); + + switch (params_width(params)) { + case 16: + break; + case 20: + val_len |= RT5660_I2S_DL_20; + break; + case 24: + val_len |= RT5660_I2S_DL_24; + break; + case 8: + val_len |= RT5660_I2S_DL_8; + break; + default: + return -EINVAL; + } + + switch (dai->id) { + case RT5660_AIF1: + mask_clk = RT5660_I2S_BCLK_MS1_MASK | RT5660_I2S_PD1_MASK; + val_clk = bclk_ms << RT5660_I2S_BCLK_MS1_SFT | + pre_div << RT5660_I2S_PD1_SFT; + snd_soc_update_bits(codec, RT5660_I2S1_SDP, RT5660_I2S_DL_MASK, + val_len); + snd_soc_update_bits(codec, RT5660_ADDA_CLK1, mask_clk, val_clk); + break; + + default: + dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id); + return -EINVAL; + } + + return 0; +} + +static int rt5660_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + unsigned int reg_val = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + rt5660->master[dai->id] = 1; + break; + + case SND_SOC_DAIFMT_CBS_CFS: + reg_val |= RT5660_I2S_MS_S; + rt5660->master[dai->id] = 0; + break; + + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + + case SND_SOC_DAIFMT_IB_NF: + reg_val |= RT5660_I2S_BP_INV; + break; + + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + + case SND_SOC_DAIFMT_LEFT_J: + reg_val |= RT5660_I2S_DF_LEFT; + break; + + case SND_SOC_DAIFMT_DSP_A: + reg_val |= RT5660_I2S_DF_PCM_A; + break; + + case SND_SOC_DAIFMT_DSP_B: + reg_val |= RT5660_I2S_DF_PCM_B; + break; + + default: + return -EINVAL; + } + + switch (dai->id) { + case RT5660_AIF1: + snd_soc_update_bits(codec, RT5660_I2S1_SDP, + RT5660_I2S_MS_MASK | RT5660_I2S_BP_MASK | + RT5660_I2S_DF_MASK, reg_val); + break; + + default: + dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id); + return -EINVAL; + } + + return 0; +} + +static int rt5660_set_dai_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + unsigned int reg_val = 0; + + if (freq == rt5660->sysclk && clk_id == rt5660->sysclk_src) + return 0; + + switch (clk_id) { + case RT5660_SCLK_S_MCLK: + reg_val |= RT5660_SCLK_SRC_MCLK; + break; + + case RT5660_SCLK_S_PLL1: + reg_val |= RT5660_SCLK_SRC_PLL1; + break; + + case RT5660_SCLK_S_RCCLK: + reg_val |= RT5660_SCLK_SRC_RCCLK; + break; + + default: + dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); + return -EINVAL; + } + + snd_soc_update_bits(codec, RT5660_GLB_CLK, RT5660_SCLK_SRC_MASK, + reg_val); + + rt5660->sysclk = freq; + rt5660->sysclk_src = clk_id; + + dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); + + return 0; +} + +static int rt5660_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 rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + struct rl6231_pll_code pll_code; + int ret; + + if (source == rt5660->pll_src && freq_in == rt5660->pll_in && + freq_out == rt5660->pll_out) + return 0; + + if (!freq_in || !freq_out) { + dev_dbg(codec->dev, "PLL disabled\n"); + + rt5660->pll_in = 0; + rt5660->pll_out = 0; + snd_soc_update_bits(codec, RT5660_GLB_CLK, + RT5660_SCLK_SRC_MASK, RT5660_SCLK_SRC_MCLK); + return 0; + } + + switch (source) { + case RT5660_PLL1_S_MCLK: + snd_soc_update_bits(codec, RT5660_GLB_CLK, + RT5660_PLL1_SRC_MASK, RT5660_PLL1_SRC_MCLK); + break; + + case RT5660_PLL1_S_BCLK: + snd_soc_update_bits(codec, RT5660_GLB_CLK, + RT5660_PLL1_SRC_MASK, RT5660_PLL1_SRC_BCLK1); + break; + + default: + dev_err(codec->dev, "Unknown PLL source %d\n", source); + return -EINVAL; + } + + ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); + if (ret < 0) { + dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); + return ret; + } + + dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n", + pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), + pll_code.n_code, pll_code.k_code); + + snd_soc_write(codec, RT5660_PLL_CTRL1, + pll_code.n_code << RT5660_PLL_N_SFT | pll_code.k_code); + snd_soc_write(codec, RT5660_PLL_CTRL2, + (pll_code.m_bp ? 0 : pll_code.m_code) << RT5660_PLL_M_SFT | + pll_code.m_bp << RT5660_PLL_M_BP_SFT); + + rt5660->pll_in = freq_in; + rt5660->pll_out = freq_out; + rt5660->pll_src = source; + + return 0; +} + +static int rt5660_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + int ret; + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + snd_soc_update_bits(codec, RT5660_GEN_CTRL1, + RT5660_DIG_GATE_CTRL, RT5660_DIG_GATE_CTRL); + + if (IS_ERR(rt5660->mclk)) + break; + + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) { + clk_disable_unprepare(rt5660->mclk); + } else { + ret = clk_prepare_enable(rt5660->mclk); + if (ret) + return ret; + } + break; + + case SND_SOC_BIAS_STANDBY: + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { + snd_soc_update_bits(codec, RT5660_PWR_ANLG1, + RT5660_PWR_VREF1 | RT5660_PWR_MB | + RT5660_PWR_BG | RT5660_PWR_VREF2, + RT5660_PWR_VREF1 | RT5660_PWR_MB | + RT5660_PWR_BG | RT5660_PWR_VREF2); + usleep_range(10000, 15000); + snd_soc_update_bits(codec, RT5660_PWR_ANLG1, + RT5660_PWR_FV1 | RT5660_PWR_FV2, + RT5660_PWR_FV1 | RT5660_PWR_FV2); + } + break; + + case SND_SOC_BIAS_OFF: + snd_soc_update_bits(codec, RT5660_GEN_CTRL1, + RT5660_DIG_GATE_CTRL, 0); + break; + + default: + break; + } + + return 0; +} + +static int rt5660_probe(struct snd_soc_codec *codec) +{ + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + + rt5660->codec = codec; + + return 0; +} + +static int rt5660_remove(struct snd_soc_codec *codec) +{ + return snd_soc_write(codec, RT5660_RESET, 0); +} + +#ifdef CONFIG_PM +static int rt5660_suspend(struct snd_soc_codec *codec) +{ + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + + regcache_cache_only(rt5660->regmap, true); + regcache_mark_dirty(rt5660->regmap); + + return 0; +} + +static int rt5660_resume(struct snd_soc_codec *codec) +{ + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + + if (rt5660->pdata.poweroff_codec_in_suspend) + usleep_range(350000, 400000); + + regcache_cache_only(rt5660->regmap, false); + regcache_sync(rt5660->regmap); + + return 0; +} +#else +#define rt5660_suspend NULL +#define rt5660_resume NULL +#endif + +#define RT5660_STEREO_RATES SNDRV_PCM_RATE_8000_192000 +#define RT5660_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 rt5660_aif_dai_ops = { + .hw_params = rt5660_hw_params, + .set_fmt = rt5660_set_dai_fmt, + .set_sysclk = rt5660_set_dai_sysclk, + .set_pll = rt5660_set_dai_pll, +}; + +static struct snd_soc_dai_driver rt5660_dai[] = { + { + .name = "rt5660-aif1", + .id = RT5660_AIF1, + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT5660_STEREO_RATES, + .formats = RT5660_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT5660_STEREO_RATES, + .formats = RT5660_FORMATS, + }, + .ops = &rt5660_aif_dai_ops, + }, +}; + +static struct snd_soc_codec_driver soc_codec_dev_rt5660 = { + .probe = rt5660_probe, + .remove = rt5660_remove, + .suspend = rt5660_suspend, + .resume = rt5660_resume, + .set_bias_level = rt5660_set_bias_level, + .idle_bias_off = true, + .component_driver = { + .controls = rt5660_snd_controls, + .num_controls = ARRAY_SIZE(rt5660_snd_controls), + .dapm_widgets = rt5660_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5660_dapm_widgets), + .dapm_routes = rt5660_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5660_dapm_routes), + }, +}; + +static const struct regmap_config rt5660_regmap = { + .reg_bits = 8, + .val_bits = 16, + .use_single_rw = true, + + .max_register = RT5660_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5660_ranges) * + RT5660_PR_SPACING), + .volatile_reg = rt5660_volatile_register, + .readable_reg = rt5660_readable_register, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt5660_reg, + .num_reg_defaults = ARRAY_SIZE(rt5660_reg), + .ranges = rt5660_ranges, + .num_ranges = ARRAY_SIZE(rt5660_ranges), +}; + +static const struct i2c_device_id rt5660_i2c_id[] = { + { "rt5660", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rt5660_i2c_id); + +static const struct of_device_id rt5660_of_match[] = { + { .compatible = "realtek,rt5660", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rt5660_of_match); + +static const struct acpi_device_id rt5660_acpi_match[] = { + { "10EC5660", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, rt5660_acpi_match); + +static int rt5660_parse_dt(struct rt5660_priv *rt5660, struct device *dev) +{ + rt5660->pdata.in1_diff = device_property_read_bool(dev, + "realtek,in1-differential"); + rt5660->pdata.in3_diff = device_property_read_bool(dev, + "realtek,in3-differential"); + rt5660->pdata.poweroff_codec_in_suspend = device_property_read_bool(dev, + "realtek,poweroff-in-suspend"); + device_property_read_u32(dev, "realtek,dmic1-data-pin", + &rt5660->pdata.dmic1_data_pin); + + return 0; +} + +static int rt5660_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rt5660_platform_data *pdata = dev_get_platdata(&i2c->dev); + struct rt5660_priv *rt5660; + int ret; + unsigned int val; + + rt5660 = devm_kzalloc(&i2c->dev, sizeof(struct rt5660_priv), + GFP_KERNEL); + + if (rt5660 == NULL) + return -ENOMEM; + + /* Check if MCLK provided */ + rt5660->mclk = devm_clk_get(&i2c->dev, "mclk"); + if (PTR_ERR(rt5660->mclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + i2c_set_clientdata(i2c, rt5660); + + if (pdata) + rt5660->pdata = *pdata; + else if (i2c->dev.of_node) + rt5660_parse_dt(rt5660, &i2c->dev); + + rt5660->regmap = devm_regmap_init_i2c(i2c, &rt5660_regmap); + if (IS_ERR(rt5660->regmap)) { + ret = PTR_ERR(rt5660->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + regmap_read(rt5660->regmap, RT5660_VENDOR_ID2, &val); + if (val != RT5660_DEVICE_ID) { + dev_err(&i2c->dev, + "Device with ID register %#x is not rt5660\n", val); + return -ENODEV; + } + + regmap_write(rt5660->regmap, RT5660_RESET, 0); + + ret = regmap_register_patch(rt5660->regmap, rt5660_patch, + ARRAY_SIZE(rt5660_patch)); + if (ret != 0) + dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); + + if (rt5660->pdata.dmic1_data_pin) { + regmap_update_bits(rt5660->regmap, RT5660_GPIO_CTRL1, + RT5660_GP1_PIN_MASK, RT5660_GP1_PIN_DMIC1_SCL); + + if (rt5660->pdata.dmic1_data_pin == RT5660_DMIC1_DATA_GPIO2) + regmap_update_bits(rt5660->regmap, RT5660_DMIC_CTRL1, + RT5660_SEL_DMIC_DATA_MASK, + RT5660_SEL_DMIC_DATA_GPIO2); + else if (rt5660->pdata.dmic1_data_pin == RT5660_DMIC1_DATA_IN1P) + regmap_update_bits(rt5660->regmap, RT5660_DMIC_CTRL1, + RT5660_SEL_DMIC_DATA_MASK, + RT5660_SEL_DMIC_DATA_IN1P); + } + + return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5660, + rt5660_dai, ARRAY_SIZE(rt5660_dai)); +} + +static int rt5660_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + + return 0; +} + +static struct i2c_driver rt5660_i2c_driver = { + .driver = { + .name = "rt5660", + .acpi_match_table = ACPI_PTR(rt5660_acpi_match), + .of_match_table = of_match_ptr(rt5660_of_match), + }, + .probe = rt5660_i2c_probe, + .remove = rt5660_i2c_remove, + .id_table = rt5660_i2c_id, +}; +module_i2c_driver(rt5660_i2c_driver); + +MODULE_DESCRIPTION("ASoC RT5660 driver"); +MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt5660.h b/sound/soc/codecs/rt5660.h new file mode 100644 index 0000000..6cdb926 --- /dev/null +++ b/sound/soc/codecs/rt5660.h @@ -0,0 +1,847 @@ +/* + * rt5660.h -- RT5660 ALSA SoC audio driver + * + * Copyright 2016 Realtek Semiconductor Corp. + * Author: Oder Chiou <oder_chiou@realtek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _RT5660_H +#define _RT5660_H + +#include <linux/clk.h> +#include <sound/rt5660.h> + +/* Info */ +#define RT5660_RESET 0x00 +#define RT5660_VENDOR_ID 0xfd +#define RT5660_VENDOR_ID1 0xfe +#define RT5660_VENDOR_ID2 0xff +/* I/O - Output */ +#define RT5660_SPK_VOL 0x01 +#define RT5660_LOUT_VOL 0x02 +/* I/O - Input */ +#define RT5660_IN1_IN2 0x0d +#define RT5660_IN3_IN4 0x0e +/* I/O - ADC/DAC/DMIC */ +#define RT5660_DAC1_DIG_VOL 0x19 +#define RT5660_STO1_ADC_DIG_VOL 0x1c +#define RT5660_ADC_BST_VOL1 0x1e +/* Mixer - D-D */ +#define RT5660_STO1_ADC_MIXER 0x27 +#define RT5660_AD_DA_MIXER 0x29 +#define RT5660_STO_DAC_MIXER 0x2a +#define RT5660_DIG_INF1_DATA 0x2f +/* Mixer - ADC */ +#define RT5660_REC_L1_MIXER 0x3b +#define RT5660_REC_L2_MIXER 0x3c +#define RT5660_REC_R1_MIXER 0x3d +#define RT5660_REC_R2_MIXER 0x3e +/* Mixer - DAC */ +#define RT5660_LOUT_MIXER 0x45 +#define RT5660_SPK_MIXER 0x46 +#define RT5660_SPO_MIXER 0x48 +#define RT5660_SPO_CLSD_RATIO 0x4a +#define RT5660_OUT_L_GAIN1 0x4d +#define RT5660_OUT_L_GAIN2 0x4e +#define RT5660_OUT_L1_MIXER 0x4f +#define RT5660_OUT_R_GAIN1 0x50 +#define RT5660_OUT_R_GAIN2 0x51 +#define RT5660_OUT_R1_MIXER 0x52 +/* Power */ +#define RT5660_PWR_DIG1 0x61 +#define RT5660_PWR_DIG2 0x62 +#define RT5660_PWR_ANLG1 0x63 +#define RT5660_PWR_ANLG2 0x64 +#define RT5660_PWR_MIXER 0x65 +#define RT5660_PWR_VOL 0x66 +/* Private Register Control */ +#define RT5660_PRIV_INDEX 0x6a +#define RT5660_PRIV_DATA 0x6c +/* Format - ADC/DAC */ +#define RT5660_I2S1_SDP 0x70 +#define RT5660_ADDA_CLK1 0x73 +#define RT5660_ADDA_CLK2 0x74 +#define RT5660_DMIC_CTRL1 0x75 +/* Function - Analog */ +#define RT5660_GLB_CLK 0x80 +#define RT5660_PLL_CTRL1 0x81 +#define RT5660_PLL_CTRL2 0x82 +#define RT5660_CLSD_AMP_OC_CTRL 0x8c +#define RT5660_CLSD_AMP_CTRL 0x8d +#define RT5660_LOUT_AMP_CTRL 0x8e +#define RT5660_SPK_AMP_SPKVDD 0x92 +#define RT5660_MICBIAS 0x93 +#define RT5660_CLSD_OUT_CTRL1 0xa1 +#define RT5660_CLSD_OUT_CTRL2 0xa2 +#define RT5660_DIPOLE_MIC_CTRL1 0xa3 +#define RT5660_DIPOLE_MIC_CTRL2 0xa4 +#define RT5660_DIPOLE_MIC_CTRL3 0xa5 +#define RT5660_DIPOLE_MIC_CTRL4 0xa6 +#define RT5660_DIPOLE_MIC_CTRL5 0xa7 +#define RT5660_DIPOLE_MIC_CTRL6 0xa8 +#define RT5660_DIPOLE_MIC_CTRL7 0xa9 +#define RT5660_DIPOLE_MIC_CTRL8 0xaa +#define RT5660_DIPOLE_MIC_CTRL9 0xab +#define RT5660_DIPOLE_MIC_CTRL10 0xac +#define RT5660_DIPOLE_MIC_CTRL11 0xad +#define RT5660_DIPOLE_MIC_CTRL12 0xae +/* Function - Digital */ +#define RT5660_EQ_CTRL1 0xb0 +#define RT5660_EQ_CTRL2 0xb1 +#define RT5660_DRC_AGC_CTRL1 0xb3 +#define RT5660_DRC_AGC_CTRL2 0xb4 +#define RT5660_DRC_AGC_CTRL3 0xb5 +#define RT5660_DRC_AGC_CTRL4 0xb6 +#define RT5660_DRC_AGC_CTRL5 0xb7 +#define RT5660_JD_CTRL 0xbb +#define RT5660_IRQ_CTRL1 0xbd +#define RT5660_IRQ_CTRL2 0xbe +#define RT5660_INT_IRQ_ST 0xbf +#define RT5660_GPIO_CTRL1 0xc0 +#define RT5660_GPIO_CTRL2 0xc2 +#define RT5660_WIND_FILTER_CTRL1 0xd3 +#define RT5660_SV_ZCD1 0xd9 +#define RT5660_SV_ZCD2 0xda +#define RT5660_DRC1_LM_CTRL1 0xe0 +#define RT5660_DRC1_LM_CTRL2 0xe1 +#define RT5660_DRC2_LM_CTRL1 0xe2 +#define RT5660_DRC2_LM_CTRL2 0xe3 +#define RT5660_MULTI_DRC_CTRL 0xe4 +#define RT5660_DRC2_CTRL1 0xe5 +#define RT5660_DRC2_CTRL2 0xe6 +#define RT5660_DRC2_CTRL3 0xe7 +#define RT5660_DRC2_CTRL4 0xe8 +#define RT5660_DRC2_CTRL5 0xe9 +#define RT5660_ALC_PGA_CTRL1 0xea +#define RT5660_ALC_PGA_CTRL2 0xeb +#define RT5660_ALC_PGA_CTRL3 0xec +#define RT5660_ALC_PGA_CTRL4 0xed +#define RT5660_ALC_PGA_CTRL5 0xee +#define RT5660_ALC_PGA_CTRL6 0xef +#define RT5660_ALC_PGA_CTRL7 0xf0 + +/* General Control */ +#define RT5660_GEN_CTRL1 0xfa +#define RT5660_GEN_CTRL2 0xfb +#define RT5660_GEN_CTRL3 0xfc + +/* Index of Codec Private Register definition */ +#define RT5660_CHOP_DAC_ADC 0x3d + +/* Global Definition */ +#define RT5660_L_MUTE (0x1 << 15) +#define RT5660_L_MUTE_SFT 15 +#define RT5660_VOL_L_MUTE (0x1 << 14) +#define RT5660_VOL_L_SFT 14 +#define RT5660_R_MUTE (0x1 << 7) +#define RT5660_R_MUTE_SFT 7 +#define RT5660_VOL_R_MUTE (0x1 << 6) +#define RT5660_VOL_R_SFT 6 +#define RT5660_L_VOL_MASK (0x3f << 8) +#define RT5660_L_VOL_SFT 8 +#define RT5660_R_VOL_MASK (0x3f) +#define RT5660_R_VOL_SFT 0 + +/* IN1 and IN2 Control (0x0d) */ +#define RT5660_IN_DF1 (0x1 << 15) +#define RT5660_IN_SFT1 15 +#define RT5660_BST_MASK1 (0x7f << 8) +#define RT5660_BST_SFT1 8 +#define RT5660_IN_DF2 (0x1 << 7) +#define RT5660_IN_SFT2 7 +#define RT5660_BST_MASK2 (0x7f << 0) +#define RT5660_BST_SFT2 0 + +/* IN3 and IN4 Control (0x0e) */ +#define RT5660_IN_DF3 (0x1 << 15) +#define RT5660_IN_SFT3 15 +#define RT5660_BST_MASK3 (0x7f << 8) +#define RT5660_BST_SFT3 8 +#define RT5660_IN_DF4 (0x1 << 7) +#define RT5660_IN_SFT4 7 +#define RT5660_BST_MASK4 (0x7f << 0) +#define RT5660_BST_SFT4 0 + +/* DAC1 Digital Volume (0x19) */ +#define RT5660_DAC_L1_VOL_MASK (0x7f << 9) +#define RT5660_DAC_L1_VOL_SFT 9 +#define RT5660_DAC_R1_VOL_MASK (0x7f << 1) +#define RT5660_DAC_R1_VOL_SFT 1 + +/* ADC Digital Volume Control (0x1c) */ +#define RT5660_ADC_L_VOL_MASK (0x3f << 9) +#define RT5660_ADC_L_VOL_SFT 9 +#define RT5660_ADC_R_VOL_MASK (0x3f << 1) +#define RT5660_ADC_R_VOL_SFT 1 + +/* ADC Boost Volume Control (0x1e) */ +#define RT5660_STO1_ADC_L_BST_MASK (0x3 << 14) +#define RT5660_STO1_ADC_L_BST_SFT 14 +#define RT5660_STO1_ADC_R_BST_MASK (0x3 << 12) +#define RT5660_STO1_ADC_R_BST_SFT 12 + +/* Stereo ADC Mixer Control (0x27) */ +#define RT5660_M_ADC_L1 (0x1 << 14) +#define RT5660_M_ADC_L1_SFT 14 +#define RT5660_M_ADC_L2 (0x1 << 13) +#define RT5660_M_ADC_L2_SFT 13 +#define RT5660_M_ADC_R1 (0x1 << 6) +#define RT5660_M_ADC_R1_SFT 6 +#define RT5660_M_ADC_R2 (0x1 << 5) +#define RT5660_M_ADC_R2_SFT 5 + +/* ADC Mixer to DAC Mixer Control (0x29) */ +#define RT5660_M_ADCMIX_L (0x1 << 15) +#define RT5660_M_ADCMIX_L_SFT 15 +#define RT5660_M_DAC1_L (0x1 << 14) +#define RT5660_M_DAC1_L_SFT 14 +#define RT5660_M_ADCMIX_R (0x1 << 7) +#define RT5660_M_ADCMIX_R_SFT 7 +#define RT5660_M_DAC1_R (0x1 << 6) +#define RT5660_M_DAC1_R_SFT 6 + +/* Stereo DAC Mixer Control (0x2a) */ +#define RT5660_M_DAC_L1 (0x1 << 14) +#define RT5660_M_DAC_L1_SFT 14 +#define RT5660_DAC_L1_STO_L_VOL_MASK (0x1 << 13) +#define RT5660_DAC_L1_STO_L_VOL_SFT 13 +#define RT5660_M_DAC_R1_STO_L (0x1 << 9) +#define RT5660_M_DAC_R1_STO_L_SFT 9 +#define RT5660_DAC_R1_STO_L_VOL_MASK (0x1 << 8) +#define RT5660_DAC_R1_STO_L_VOL_SFT 8 +#define RT5660_M_DAC_R1 (0x1 << 6) +#define RT5660_M_DAC_R1_SFT 6 +#define RT5660_DAC_R1_STO_R_VOL_MASK (0x1 << 5) +#define RT5660_DAC_R1_STO_R_VOL_SFT 5 +#define RT5660_M_DAC_L1_STO_R (0x1 << 1) +#define RT5660_M_DAC_L1_STO_R_SFT 1 +#define RT5660_DAC_L1_STO_R_VOL_MASK (0x1) +#define RT5660_DAC_L1_STO_R_VOL_SFT 0 + +/* Digital Interface Data Control (0x2f) */ +#define RT5660_IF1_DAC_IN_SEL (0x3 << 14) +#define RT5660_IF1_DAC_IN_SFT 14 +#define RT5660_IF1_ADC_IN_SEL (0x3 << 12) +#define RT5660_IF1_ADC_IN_SFT 12 + +/* REC Left Mixer Control 1 (0x3b) */ +#define RT5660_G_BST3_RM_L_MASK (0x7 << 4) +#define RT5660_G_BST3_RM_L_SFT 4 +#define RT5660_G_BST2_RM_L_MASK (0x7 << 1) +#define RT5660_G_BST2_RM_L_SFT 1 + +/* REC Left Mixer Control 2 (0x3c) */ +#define RT5660_G_BST1_RM_L_MASK (0x7 << 13) +#define RT5660_G_BST1_RM_L_SFT 13 +#define RT5660_G_OM_L_RM_L_MASK (0x7 << 10) +#define RT5660_G_OM_L_RM_L_SFT 10 +#define RT5660_M_BST3_RM_L (0x1 << 3) +#define RT5660_M_BST3_RM_L_SFT 3 +#define RT5660_M_BST2_RM_L (0x1 << 2) +#define RT5660_M_BST2_RM_L_SFT 2 +#define RT5660_M_BST1_RM_L (0x1 << 1) +#define RT5660_M_BST1_RM_L_SFT 1 +#define RT5660_M_OM_L_RM_L (0x1) +#define RT5660_M_OM_L_RM_L_SFT 0 + +/* REC Right Mixer Control 1 (0x3d) */ +#define RT5660_G_BST3_RM_R_MASK (0x7 << 4) +#define RT5660_G_BST3_RM_R_SFT 4 +#define RT5660_G_BST2_RM_R_MASK (0x7 << 1) +#define RT5660_G_BST2_RM_R_SFT 1 + +/* REC Right Mixer Control 2 (0x3e) */ +#define RT5660_G_BST1_RM_R_MASK (0x7 << 13) +#define RT5660_G_BST1_RM_R_SFT 13 +#define RT5660_G_OM_R_RM_R_MASK (0x7 << 10) +#define RT5660_G_OM_R_RM_R_SFT 10 +#define RT5660_M_BST3_RM_R (0x1 << 3) +#define RT5660_M_BST3_RM_R_SFT 3 +#define RT5660_M_BST2_RM_R (0x1 << 2) +#define RT5660_M_BST2_RM_R_SFT 2 +#define RT5660_M_BST1_RM_R (0x1 << 1) +#define RT5660_M_BST1_RM_R_SFT 1 +#define RT5660_M_OM_R_RM_R (0x1) +#define RT5660_M_OM_R_RM_R_SFT 0 + +/* LOUTMIX Control (0x45) */ +#define RT5660_M_DAC1_LM (0x1 << 14) +#define RT5660_M_DAC1_LM_SFT 14 +#define RT5660_M_LOVOL_M (0x1 << 13) +#define RT5660_M_LOVOL_LM_SFT 13 + +/* SPK Mixer Control (0x46) */ +#define RT5660_G_BST3_SM_MASK (0x3 << 14) +#define RT5660_G_BST3_SM_SFT 14 +#define RT5660_G_BST1_SM_MASK (0x3 << 12) +#define RT5660_G_BST1_SM_SFT 12 +#define RT5660_G_DACl_SM_MASK (0x3 << 10) +#define RT5660_G_DACl_SM_SFT 10 +#define RT5660_G_DACR_SM_MASK (0x3 << 8) +#define RT5660_G_DACR_SM_SFT 8 +#define RT5660_G_OM_L_SM_MASK (0x3 << 6) +#define RT5660_G_OM_L_SM_SFT 6 +#define RT5660_M_DACR_SM (0x1 << 5) +#define RT5660_M_DACR_SM_SFT 5 +#define RT5660_M_BST1_SM (0x1 << 4) +#define RT5660_M_BST1_SM_SFT 4 +#define RT5660_M_BST3_SM (0x1 << 3) +#define RT5660_M_BST3_SM_SFT 3 +#define RT5660_M_DACL_SM (0x1 << 2) +#define RT5660_M_DACL_SM_SFT 2 +#define RT5660_M_OM_L_SM (0x1 << 1) +#define RT5660_M_OM_L_SM_SFT 1 + +/* SPOMIX Control (0x48) */ +#define RT5660_M_DAC_R_SPM (0x1 << 14) +#define RT5660_M_DAC_R_SPM_SFT 14 +#define RT5660_M_DAC_L_SPM (0x1 << 13) +#define RT5660_M_DAC_L_SPM_SFT 13 +#define RT5660_M_SV_SPM (0x1 << 12) +#define RT5660_M_SV_SPM_SFT 12 +#define RT5660_M_BST1_SPM (0x1 << 11) +#define RT5660_M_BST1_SPM_SFT 11 + +/* Output Left Mixer Control 1 (0x4d) */ +#define RT5660_G_BST3_OM_L_MASK (0x7 << 13) +#define RT5660_G_BST3_OM_L_SFT 13 +#define RT5660_G_BST2_OM_L_MASK (0x7 << 10) +#define RT5660_G_BST2_OM_L_SFT 10 +#define RT5660_G_BST1_OM_L_MASK (0x7 << 7) +#define RT5660_G_BST1_OM_L_SFT 7 +#define RT5660_G_RM_L_OM_L_MASK (0x7 << 1) +#define RT5660_G_RM_L_OM_L_SFT 1 + +/* Output Left Mixer Control 2 (0x4e) */ +#define RT5660_G_DAC_R1_OM_L_MASK (0x7 << 10) +#define RT5660_G_DAC_R1_OM_L_SFT 10 +#define RT5660_G_DAC_L1_OM_L_MASK (0x7 << 7) +#define RT5660_G_DAC_L1_OM_L_SFT 7 + +/* Output Left Mixer Control 3 (0x4f) */ +#define RT5660_M_BST3_OM_L (0x1 << 5) +#define RT5660_M_BST3_OM_L_SFT 5 +#define RT5660_M_BST2_OM_L (0x1 << 4) +#define RT5660_M_BST2_OM_L_SFT 4 +#define RT5660_M_BST1_OM_L (0x1 << 3) +#define RT5660_M_BST1_OM_L_SFT 3 +#define RT5660_M_RM_L_OM_L (0x1 << 2) +#define RT5660_M_RM_L_OM_L_SFT 2 +#define RT5660_M_DAC_R_OM_L (0x1 << 1) +#define RT5660_M_DAC_R_OM_L_SFT 1 +#define RT5660_M_DAC_L_OM_L (0x1) +#define RT5660_M_DAC_L_OM_L_SFT 0 + +/* Output Right Mixer Control 1 (0x50) */ +#define RT5660_G_BST2_OM_R_MASK (0x7 << 10) +#define RT5660_G_BST2_OM_R_SFT 10 +#define RT5660_G_BST1_OM_R_MASK (0x7 << 7) +#define RT5660_G_BST1_OM_R_SFT 7 +#define RT5660_G_RM_R_OM_R_MASK (0x7 << 1) +#define RT5660_G_RM_R_OM_R_SFT 1 + +/* Output Right Mixer Control 2 (0x51) */ +#define RT5660_G_DAC_L_OM_R_MASK (0x7 << 10) +#define RT5660_G_DAC_L_OM_R_SFT 10 +#define RT5660_G_DAC_R_OM_R_MASK (0x7 << 7) +#define RT5660_G_DAC_R_OM_R_SFT 7 + +/* Output Right Mixer Control 3 (0x52) */ +#define RT5660_M_BST2_OM_R (0x1 << 4) +#define RT5660_M_BST2_OM_R_SFT 4 +#define RT5660_M_BST1_OM_R (0x1 << 3) +#define RT5660_M_BST1_OM_R_SFT 3 +#define RT5660_M_RM_R_OM_R (0x1 << 2) +#define RT5660_M_RM_R_OM_R_SFT 2 +#define RT5660_M_DAC_L_OM_R (0x1 << 1) +#define RT5660_M_DAC_L_OM_R_SFT 1 +#define RT5660_M_DAC_R_OM_R (0x1) +#define RT5660_M_DAC_R_OM_R_SFT 0 + +/* Power Management for Digital 1 (0x61) */ +#define RT5660_PWR_I2S1 (0x1 << 15) +#define RT5660_PWR_I2S1_BIT 15 +#define RT5660_PWR_DAC_L1 (0x1 << 12) +#define RT5660_PWR_DAC_L1_BIT 12 +#define RT5660_PWR_DAC_R1 (0x1 << 11) +#define RT5660_PWR_DAC_R1_BIT 11 +#define RT5660_PWR_ADC_L (0x1 << 2) +#define RT5660_PWR_ADC_L_BIT 2 +#define RT5660_PWR_ADC_R (0x1 << 1) +#define RT5660_PWR_ADC_R_BIT 1 +#define RT5660_PWR_CLS_D (0x1) +#define RT5660_PWR_CLS_D_BIT 0 + +/* Power Management for Digital 2 (0x62) */ +#define RT5660_PWR_ADC_S1F (0x1 << 15) +#define RT5660_PWR_ADC_S1F_BIT 15 +#define RT5660_PWR_DAC_S1F (0x1 << 11) +#define RT5660_PWR_DAC_S1F_BIT 11 + +/* Power Management for Analog 1 (0x63) */ +#define RT5660_PWR_VREF1 (0x1 << 15) +#define RT5660_PWR_VREF1_BIT 15 +#define RT5660_PWR_FV1 (0x1 << 14) +#define RT5660_PWR_FV1_BIT 14 +#define RT5660_PWR_MB (0x1 << 13) +#define RT5660_PWR_MB_BIT 13 +#define RT5660_PWR_BG (0x1 << 11) +#define RT5660_PWR_BG_BIT 11 +#define RT5660_PWR_HP_L (0x1 << 7) +#define RT5660_PWR_HP_L_BIT 7 +#define RT5660_PWR_HP_R (0x1 << 6) +#define RT5660_PWR_HP_R_BIT 6 +#define RT5660_PWR_HA (0x1 << 5) +#define RT5660_PWR_HA_BIT 5 +#define RT5660_PWR_VREF2 (0x1 << 4) +#define RT5660_PWR_VREF2_BIT 4 +#define RT5660_PWR_FV2 (0x1 << 3) +#define RT5660_PWR_FV2_BIT 3 +#define RT5660_PWR_LDO2 (0x1 << 2) +#define RT5660_PWR_LDO2_BIT 2 + +/* Power Management for Analog 2 (0x64) */ +#define RT5660_PWR_BST1 (0x1 << 15) +#define RT5660_PWR_BST1_BIT 15 +#define RT5660_PWR_BST2 (0x1 << 14) +#define RT5660_PWR_BST2_BIT 14 +#define RT5660_PWR_BST3 (0x1 << 13) +#define RT5660_PWR_BST3_BIT 13 +#define RT5660_PWR_MB1 (0x1 << 11) +#define RT5660_PWR_MB1_BIT 11 +#define RT5660_PWR_MB2 (0x1 << 10) +#define RT5660_PWR_MB2_BIT 10 +#define RT5660_PWR_PLL (0x1 << 9) +#define RT5660_PWR_PLL_BIT 9 + +/* Power Management for Mixer (0x65) */ +#define RT5660_PWR_OM_L (0x1 << 15) +#define RT5660_PWR_OM_L_BIT 15 +#define RT5660_PWR_OM_R (0x1 << 14) +#define RT5660_PWR_OM_R_BIT 14 +#define RT5660_PWR_SM (0x1 << 13) +#define RT5660_PWR_SM_BIT 13 +#define RT5660_PWR_RM_L (0x1 << 11) +#define RT5660_PWR_RM_L_BIT 11 +#define RT5660_PWR_RM_R (0x1 << 10) +#define RT5660_PWR_RM_R_BIT 10 + +/* Power Management for Volume (0x66) */ +#define RT5660_PWR_SV (0x1 << 15) +#define RT5660_PWR_SV_BIT 15 +#define RT5660_PWR_LV_L (0x1 << 11) +#define RT5660_PWR_LV_L_BIT 11 +#define RT5660_PWR_LV_R (0x1 << 10) +#define RT5660_PWR_LV_R_BIT 10 + +/* I2S1 Audio Serial Data Port Control (0x70) */ +#define RT5660_I2S_MS_MASK (0x1 << 15) +#define RT5660_I2S_MS_SFT 15 +#define RT5660_I2S_MS_M (0x0 << 15) +#define RT5660_I2S_MS_S (0x1 << 15) +#define RT5660_I2S_O_CP_MASK (0x3 << 10) +#define RT5660_I2S_O_CP_SFT 10 +#define RT5660_I2S_O_CP_OFF (0x0 << 10) +#define RT5660_I2S_O_CP_U_LAW (0x1 << 10) +#define RT5660_I2S_O_CP_A_LAW (0x2 << 10) +#define RT5660_I2S_I_CP_MASK (0x3 << 8) +#define RT5660_I2S_I_CP_SFT 8 +#define RT5660_I2S_I_CP_OFF (0x0 << 8) +#define RT5660_I2S_I_CP_U_LAW (0x1 << 8) +#define RT5660_I2S_I_CP_A_LAW (0x2 << 8) +#define RT5660_I2S_BP_MASK (0x1 << 7) +#define RT5660_I2S_BP_SFT 7 +#define RT5660_I2S_BP_NOR (0x0 << 7) +#define RT5660_I2S_BP_INV (0x1 << 7) +#define RT5660_I2S_DL_MASK (0x3 << 2) +#define RT5660_I2S_DL_SFT 2 +#define RT5660_I2S_DL_16 (0x0 << 2) +#define RT5660_I2S_DL_20 (0x1 << 2) +#define RT5660_I2S_DL_24 (0x2 << 2) +#define RT5660_I2S_DL_8 (0x3 << 2) +#define RT5660_I2S_DF_MASK (0x3) +#define RT5660_I2S_DF_SFT 0 +#define RT5660_I2S_DF_I2S (0x0) +#define RT5660_I2S_DF_LEFT (0x1) +#define RT5660_I2S_DF_PCM_A (0x2) +#define RT5660_I2S_DF_PCM_B (0x3) + +/* ADC/DAC Clock Control 1 (0x73) */ +#define RT5660_I2S_BCLK_MS1_MASK (0x1 << 15) +#define RT5660_I2S_BCLK_MS1_SFT 15 +#define RT5660_I2S_BCLK_MS1_32 (0x0 << 15) +#define RT5660_I2S_BCLK_MS1_64 (0x1 << 15) +#define RT5660_I2S_PD1_MASK (0x7 << 12) +#define RT5660_I2S_PD1_SFT 12 +#define RT5660_I2S_PD1_1 (0x0 << 12) +#define RT5660_I2S_PD1_2 (0x1 << 12) +#define RT5660_I2S_PD1_3 (0x2 << 12) +#define RT5660_I2S_PD1_4 (0x3 << 12) +#define RT5660_I2S_PD1_6 (0x4 << 12) +#define RT5660_I2S_PD1_8 (0x5 << 12) +#define RT5660_I2S_PD1_12 (0x6 << 12) +#define RT5660_I2S_PD1_16 (0x7 << 12) +#define RT5660_DAC_OSR_MASK (0x3 << 2) +#define RT5660_DAC_OSR_SFT 2 +#define RT5660_DAC_OSR_128 (0x0 << 2) +#define RT5660_DAC_OSR_64 (0x1 << 2) +#define RT5660_DAC_OSR_32 (0x2 << 2) +#define RT5660_DAC_OSR_16 (0x3 << 2) +#define RT5660_ADC_OSR_MASK (0x3) +#define RT5660_ADC_OSR_SFT 0 +#define RT5660_ADC_OSR_128 (0x0) +#define RT5660_ADC_OSR_64 (0x1) +#define RT5660_ADC_OSR_32 (0x2) +#define RT5660_ADC_OSR_16 (0x3) + +/* ADC/DAC Clock Control 2 (0x74) */ +#define RT5660_RESET_ADF (0x1 << 13) +#define RT5660_RESET_ADF_SFT 13 +#define RT5660_RESET_DAF (0x1 << 12) +#define RT5660_RESET_DAF_SFT 12 +#define RT5660_DAHPF_EN (0x1 << 11) +#define RT5660_DAHPF_EN_SFT 11 +#define RT5660_ADHPF_EN (0x1 << 10) +#define RT5660_ADHPF_EN_SFT 10 + +/* Digital Microphone Control (0x75) */ +#define RT5660_DMIC_1_EN_MASK (0x1 << 15) +#define RT5660_DMIC_1_EN_SFT 15 +#define RT5660_DMIC_1_DIS (0x0 << 15) +#define RT5660_DMIC_1_EN (0x1 << 15) +#define RT5660_DMIC_1L_LH_MASK (0x1 << 13) +#define RT5660_DMIC_1L_LH_SFT 13 +#define RT5660_DMIC_1L_LH_RISING (0x0 << 13) +#define RT5660_DMIC_1L_LH_FALLING (0x1 << 13) +#define RT5660_DMIC_1R_LH_MASK (0x1 << 12) +#define RT5660_DMIC_1R_LH_SFT 12 +#define RT5660_DMIC_1R_LH_RISING (0x0 << 12) +#define RT5660_DMIC_1R_LH_FALLING (0x1 << 12) +#define RT5660_SEL_DMIC_DATA_MASK (0x1 << 11) +#define RT5660_SEL_DMIC_DATA_SFT 11 +#define RT5660_SEL_DMIC_DATA_GPIO2 (0x0 << 11) +#define RT5660_SEL_DMIC_DATA_IN1P (0x1 << 11) +#define RT5660_DMIC_CLK_MASK (0x7 << 5) +#define RT5660_DMIC_CLK_SFT 5 + +/* Global Clock Control (0x80) */ +#define RT5660_SCLK_SRC_MASK (0x3 << 14) +#define RT5660_SCLK_SRC_SFT 14 +#define RT5660_SCLK_SRC_MCLK (0x0 << 14) +#define RT5660_SCLK_SRC_PLL1 (0x1 << 14) +#define RT5660_SCLK_SRC_RCCLK (0x2 << 14) +#define RT5660_PLL1_SRC_MASK (0x3 << 12) +#define RT5660_PLL1_SRC_SFT 12 +#define RT5660_PLL1_SRC_MCLK (0x0 << 12) +#define RT5660_PLL1_SRC_BCLK1 (0x1 << 12) +#define RT5660_PLL1_SRC_RCCLK (0x2 << 12) +#define RT5660_PLL1_PD_MASK (0x1 << 3) +#define RT5660_PLL1_PD_SFT 3 +#define RT5660_PLL1_PD_1 (0x0 << 3) +#define RT5660_PLL1_PD_2 (0x1 << 3) + +#define RT5660_PLL_INP_MAX 40000000 +#define RT5660_PLL_INP_MIN 256000 +/* PLL M/N/K Code Control 1 (0x81) */ +#define RT5660_PLL_N_MAX 0x1ff +#define RT5660_PLL_N_MASK (RT5660_PLL_N_MAX << 7) +#define RT5660_PLL_N_SFT 7 +#define RT5660_PLL_K_MAX 0x1f +#define RT5660_PLL_K_MASK (RT5660_PLL_K_MAX) +#define RT5660_PLL_K_SFT 0 + +/* PLL M/N/K Code Control 2 (0x82) */ +#define RT5660_PLL_M_MAX 0xf +#define RT5660_PLL_M_MASK (RT5660_PLL_M_MAX << 12) +#define RT5660_PLL_M_SFT 12 +#define RT5660_PLL_M_BP (0x1 << 11) +#define RT5660_PLL_M_BP_SFT 11 + +/* Class D Over Current Control (0x8c) */ +#define RT5660_CLSD_OC_MASK (0x1 << 9) +#define RT5660_CLSD_OC_SFT 9 +#define RT5660_CLSD_OC_PU (0x0 << 9) +#define RT5660_CLSD_OC_PD (0x1 << 9) +#define RT5660_AUTO_PD_MASK (0x1 << 8) +#define RT5660_AUTO_PD_SFT 8 +#define RT5660_AUTO_PD_DIS (0x0 << 8) +#define RT5660_AUTO_PD_EN (0x1 << 8) +#define RT5660_CLSD_OC_TH_MASK (0x3f) +#define RT5660_CLSD_OC_TH_SFT 0 + +/* Class D Output Control (0x8d) */ +#define RT5660_CLSD_RATIO_MASK (0xf << 12) +#define RT5660_CLSD_RATIO_SFT 12 + +/* Lout Amp Control 1 (0x8e) */ +#define RT5660_LOUT_CO_MASK (0x1 << 4) +#define RT5660_LOUT_CO_SFT 4 +#define RT5660_LOUT_CO_DIS (0x0 << 4) +#define RT5660_LOUT_CO_EN (0x1 << 4) +#define RT5660_LOUT_CB_MASK (0x1) +#define RT5660_LOUT_CB_SFT 0 +#define RT5660_LOUT_CB_PD (0x0) +#define RT5660_LOUT_CB_PU (0x1) + +/* SPKVDD detection control (0x92) */ +#define RT5660_SPKVDD_DET_MASK (0x1 << 15) +#define RT5660_SPKVDD_DET_SFT 15 +#define RT5660_SPKVDD_DET_DIS (0x0 << 15) +#define RT5660_SPKVDD_DET_EN (0x1 << 15) +#define RT5660_SPK_AG_MASK (0x1 << 14) +#define RT5660_SPK_AG_SFT 14 +#define RT5660_SPK_AG_DIS (0x0 << 14) +#define RT5660_SPK_AG_EN (0x1 << 14) + +/* Micbias Control (0x93) */ +#define RT5660_MIC1_BS_MASK (0x1 << 15) +#define RT5660_MIC1_BS_SFT 15 +#define RT5660_MIC1_BS_9AV (0x0 << 15) +#define RT5660_MIC1_BS_75AV (0x1 << 15) +#define RT5660_MIC2_BS_MASK (0x1 << 14) +#define RT5660_MIC2_BS_SFT 14 +#define RT5660_MIC2_BS_9AV (0x0 << 14) +#define RT5660_MIC2_BS_75AV (0x1 << 14) +#define RT5660_MIC1_OVCD_MASK (0x1 << 11) +#define RT5660_MIC1_OVCD_SFT 11 +#define RT5660_MIC1_OVCD_DIS (0x0 << 11) +#define RT5660_MIC1_OVCD_EN (0x1 << 11) +#define RT5660_MIC1_OVTH_MASK (0x3 << 9) +#define RT5660_MIC1_OVTH_SFT 9 +#define RT5660_MIC1_OVTH_600UA (0x0 << 9) +#define RT5660_MIC1_OVTH_1500UA (0x1 << 9) +#define RT5660_MIC1_OVTH_2000UA (0x2 << 9) +#define RT5660_MIC2_OVCD_MASK (0x1 << 8) +#define RT5660_MIC2_OVCD_SFT 8 +#define RT5660_MIC2_OVCD_DIS (0x0 << 8) +#define RT5660_MIC2_OVCD_EN (0x1 << 8) +#define RT5660_MIC2_OVTH_MASK (0x3 << 6) +#define RT5660_MIC2_OVTH_SFT 6 +#define RT5660_MIC2_OVTH_600UA (0x0 << 6) +#define RT5660_MIC2_OVTH_1500UA (0x1 << 6) +#define RT5660_MIC2_OVTH_2000UA (0x2 << 6) +#define RT5660_PWR_CLK25M_MASK (0x1 << 4) +#define RT5660_PWR_CLK25M_SFT 4 +#define RT5660_PWR_CLK25M_PD (0x0 << 4) +#define RT5660_PWR_CLK25M_PU (0x1 << 4) + +/* EQ Control 1 (0xb0) */ +#define RT5660_EQ_SRC_MASK (0x1 << 15) +#define RT5660_EQ_SRC_SFT 15 +#define RT5660_EQ_SRC_DAC (0x0 << 15) +#define RT5660_EQ_SRC_ADC (0x1 << 15) +#define RT5660_EQ_UPD (0x1 << 14) +#define RT5660_EQ_UPD_BIT 14 + +/* Jack Detect Control (0xbb) */ +#define RT5660_JD_MASK (0x3 << 14) +#define RT5660_JD_SFT 14 +#define RT5660_JD_DIS (0x0 << 14) +#define RT5660_JD_GPIO1 (0x1 << 14) +#define RT5660_JD_GPIO2 (0x2 << 14) +#define RT5660_JD_LOUT_MASK (0x1 << 11) +#define RT5660_JD_LOUT_SFT 11 +#define RT5660_JD_LOUT_DIS (0x0 << 11) +#define RT5660_JD_LOUT_EN (0x1 << 11) +#define RT5660_JD_LOUT_TRG_MASK (0x1 << 10) +#define RT5660_JD_LOUT_TRG_SFT 10 +#define RT5660_JD_LOUT_TRG_LO (0x0 << 10) +#define RT5660_JD_LOUT_TRG_HI (0x1 << 10) +#define RT5660_JD_SPO_MASK (0x1 << 9) +#define RT5660_JD_SPO_SFT 9 +#define RT5660_JD_SPO_DIS (0x0 << 9) +#define RT5660_JD_SPO_EN (0x1 << 9) +#define RT5660_JD_SPO_TRG_MASK (0x1 << 8) +#define RT5660_JD_SPO_TRG_SFT 8 +#define RT5660_JD_SPO_TRG_LO (0x0 << 8) +#define RT5660_JD_SPO_TRG_HI (0x1 << 8) + +/* IRQ Control 1 (0xbd) */ +#define RT5660_IRQ_JD_MASK (0x1 << 15) +#define RT5660_IRQ_JD_SFT 15 +#define RT5660_IRQ_JD_BP (0x0 << 15) +#define RT5660_IRQ_JD_NOR (0x1 << 15) +#define RT5660_IRQ_OT_MASK (0x1 << 14) +#define RT5660_IRQ_OT_SFT 14 +#define RT5660_IRQ_OT_BP (0x0 << 14) +#define RT5660_IRQ_OT_NOR (0x1 << 14) +#define RT5660_JD_STKY_MASK (0x1 << 13) +#define RT5660_JD_STKY_SFT 13 +#define RT5660_JD_STKY_DIS (0x0 << 13) +#define RT5660_JD_STKY_EN (0x1 << 13) +#define RT5660_OT_STKY_MASK (0x1 << 12) +#define RT5660_OT_STKY_SFT 12 +#define RT5660_OT_STKY_DIS (0x0 << 12) +#define RT5660_OT_STKY_EN (0x1 << 12) +#define RT5660_JD_P_MASK (0x1 << 11) +#define RT5660_JD_P_SFT 11 +#define RT5660_JD_P_NOR (0x0 << 11) +#define RT5660_JD_P_INV (0x1 << 11) +#define RT5660_OT_P_MASK (0x1 << 10) +#define RT5660_OT_P_SFT 10 +#define RT5660_OT_P_NOR (0x0 << 10) +#define RT5660_OT_P_INV (0x1 << 10) + +/* IRQ Control 2 (0xbe) */ +#define RT5660_IRQ_MB1_OC_MASK (0x1 << 15) +#define RT5660_IRQ_MB1_OC_SFT 15 +#define RT5660_IRQ_MB1_OC_BP (0x0 << 15) +#define RT5660_IRQ_MB1_OC_NOR (0x1 << 15) +#define RT5660_IRQ_MB2_OC_MASK (0x1 << 14) +#define RT5660_IRQ_MB2_OC_SFT 14 +#define RT5660_IRQ_MB2_OC_BP (0x0 << 14) +#define RT5660_IRQ_MB2_OC_NOR (0x1 << 14) +#define RT5660_MB1_OC_STKY_MASK (0x1 << 11) +#define RT5660_MB1_OC_STKY_SFT 11 +#define RT5660_MB1_OC_STKY_DIS (0x0 << 11) +#define RT5660_MB1_OC_STKY_EN (0x1 << 11) +#define RT5660_MB2_OC_STKY_MASK (0x1 << 10) +#define RT5660_MB2_OC_STKY_SFT 10 +#define RT5660_MB2_OC_STKY_DIS (0x0 << 10) +#define RT5660_MB2_OC_STKY_EN (0x1 << 10) +#define RT5660_MB1_OC_P_MASK (0x1 << 7) +#define RT5660_MB1_OC_P_SFT 7 +#define RT5660_MB1_OC_P_NOR (0x0 << 7) +#define RT5660_MB1_OC_P_INV (0x1 << 7) +#define RT5660_MB2_OC_P_MASK (0x1 << 6) +#define RT5660_MB2_OC_P_SFT 6 +#define RT5660_MB2_OC_P_NOR (0x0 << 6) +#define RT5660_MB2_OC_P_INV (0x1 << 6) +#define RT5660_MB1_OC_CLR (0x1 << 3) +#define RT5660_MB1_OC_CLR_SFT 3 +#define RT5660_MB2_OC_CLR (0x1 << 2) +#define RT5660_MB2_OC_CLR_SFT 2 + +/* GPIO Control 1 (0xc0) */ +#define RT5660_GP2_PIN_MASK (0x1 << 14) +#define RT5660_GP2_PIN_SFT 14 +#define RT5660_GP2_PIN_GPIO2 (0x0 << 14) +#define RT5660_GP2_PIN_DMIC1_SDA (0x1 << 14) +#define RT5660_GP1_PIN_MASK (0x3 << 12) +#define RT5660_GP1_PIN_SFT 12 +#define RT5660_GP1_PIN_GPIO1 (0x0 << 12) +#define RT5660_GP1_PIN_DMIC1_SCL (0x1 << 12) +#define RT5660_GP1_PIN_IRQ (0x2 << 12) +#define RT5660_GPIO_M_MASK (0x1 << 9) +#define RT5660_GPIO_M_SFT 9 +#define RT5660_GPIO_M_FLT (0x0 << 9) +#define RT5660_GPIO_M_PH (0x1 << 9) + +/* GPIO Control 3 (0xc2) */ +#define RT5660_GP2_PF_MASK (0x1 << 5) +#define RT5660_GP2_PF_SFT 5 +#define RT5660_GP2_PF_IN (0x0 << 5) +#define RT5660_GP2_PF_OUT (0x1 << 5) +#define RT5660_GP2_OUT_MASK (0x1 << 4) +#define RT5660_GP2_OUT_SFT 4 +#define RT5660_GP2_OUT_LO (0x0 << 4) +#define RT5660_GP2_OUT_HI (0x1 << 4) +#define RT5660_GP2_P_MASK (0x1 << 3) +#define RT5660_GP2_P_SFT 3 +#define RT5660_GP2_P_NOR (0x0 << 3) +#define RT5660_GP2_P_INV (0x1 << 3) +#define RT5660_GP1_PF_MASK (0x1 << 2) +#define RT5660_GP1_PF_SFT 2 +#define RT5660_GP1_PF_IN (0x0 << 2) +#define RT5660_GP1_PF_OUT (0x1 << 2) +#define RT5660_GP1_OUT_MASK (0x1 << 1) +#define RT5660_GP1_OUT_SFT 1 +#define RT5660_GP1_OUT_LO (0x0 << 1) +#define RT5660_GP1_OUT_HI (0x1 << 1) +#define RT5660_GP1_P_MASK (0x1) +#define RT5660_GP1_P_SFT 0 +#define RT5660_GP1_P_NOR (0x0) +#define RT5660_GP1_P_INV (0x1) + +/* Soft volume and zero cross control 1 (0xd9) */ +#define RT5660_SV_MASK (0x1 << 15) +#define RT5660_SV_SFT 15 +#define RT5660_SV_DIS (0x0 << 15) +#define RT5660_SV_EN (0x1 << 15) +#define RT5660_SPO_SV_MASK (0x1 << 14) +#define RT5660_SPO_SV_SFT 14 +#define RT5660_SPO_SV_DIS (0x0 << 14) +#define RT5660_SPO_SV_EN (0x1 << 14) +#define RT5660_OUT_SV_MASK (0x1 << 12) +#define RT5660_OUT_SV_SFT 12 +#define RT5660_OUT_SV_DIS (0x0 << 12) +#define RT5660_OUT_SV_EN (0x1 << 12) +#define RT5660_ZCD_DIG_MASK (0x1 << 11) +#define RT5660_ZCD_DIG_SFT 11 +#define RT5660_ZCD_DIG_DIS (0x0 << 11) +#define RT5660_ZCD_DIG_EN (0x1 << 11) +#define RT5660_ZCD_MASK (0x1 << 10) +#define RT5660_ZCD_SFT 10 +#define RT5660_ZCD_PD (0x0 << 10) +#define RT5660_ZCD_PU (0x1 << 10) +#define RT5660_SV_DLY_MASK (0xf) +#define RT5660_SV_DLY_SFT 0 + +/* Soft volume and zero cross control 2 (0xda) */ +#define RT5660_ZCD_SPO_MASK (0x1 << 15) +#define RT5660_ZCD_SPO_SFT 15 +#define RT5660_ZCD_SPO_DIS (0x0 << 15) +#define RT5660_ZCD_SPO_EN (0x1 << 15) +#define RT5660_ZCD_OMR_MASK (0x1 << 8) +#define RT5660_ZCD_OMR_SFT 8 +#define RT5660_ZCD_OMR_DIS (0x0 << 8) +#define RT5660_ZCD_OMR_EN (0x1 << 8) +#define RT5660_ZCD_OML_MASK (0x1 << 7) +#define RT5660_ZCD_OML_SFT 7 +#define RT5660_ZCD_OML_DIS (0x0 << 7) +#define RT5660_ZCD_OML_EN (0x1 << 7) +#define RT5660_ZCD_SPM_MASK (0x1 << 6) +#define RT5660_ZCD_SPM_SFT 6 +#define RT5660_ZCD_SPM_DIS (0x0 << 6) +#define RT5660_ZCD_SPM_EN (0x1 << 6) +#define RT5660_ZCD_RMR_MASK (0x1 << 5) +#define RT5660_ZCD_RMR_SFT 5 +#define RT5660_ZCD_RMR_DIS (0x0 << 5) +#define RT5660_ZCD_RMR_EN (0x1 << 5) +#define RT5660_ZCD_RML_MASK (0x1 << 4) +#define RT5660_ZCD_RML_SFT 4 +#define RT5660_ZCD_RML_DIS (0x0 << 4) +#define RT5660_ZCD_RML_EN (0x1 << 4) + +/* General Control 1 (0xfa) */ +#define RT5660_PWR_VREF_HP (0x1 << 11) +#define RT5660_PWR_VREF_HP_SFT 11 +#define RT5660_DIG_GATE_CTRL (0x1) +#define RT5660_DIG_GATE_CTRL_SFT 0 + +/* System Clock Source */ +#define RT5660_SCLK_S_MCLK 0 +#define RT5660_SCLK_S_PLL1 1 +#define RT5660_SCLK_S_RCCLK 2 + +/* PLL1 Source */ +#define RT5660_PLL1_S_MCLK 0 +#define RT5660_PLL1_S_BCLK 1 + +enum { + RT5660_AIF1, + RT5660_AIFS, +}; + +struct rt5660_priv { + struct snd_soc_codec *codec; + struct rt5660_platform_data pdata; + struct regmap *regmap; + struct clk *mclk; + + int sysclk; + int sysclk_src; + int lrck[RT5660_AIFS]; + int bclk[RT5660_AIFS]; + int master[RT5660_AIFS]; + + int pll_src; + int pll_in; + int pll_out; +}; + +#endif diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c new file mode 100644 index 0000000..01a18d8 --- /dev/null +++ b/sound/soc/codecs/rt5663.c @@ -0,0 +1,3218 @@ +/* + * rt5663.c -- RT5668/RT5663 ALSA SoC audio codec driver + * + * Copyright 2016 Realtek Semiconductor Corp. + * Author: Jack Yu <jack.yu@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/acpi.h> +#include <linux/workqueue.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/jack.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> +#include <sound/initval.h> +#include <sound/tlv.h> + +#include "rt5663.h" +#include "rl6231.h" + +#define RT5668_DEVICE_ID 0x6451 +#define RT5663_DEVICE_ID 0x6406 + +enum { + CODEC_TYPE_RT5668, + CODEC_TYPE_RT5663, +}; + +struct rt5663_priv { + struct snd_soc_codec *codec; + struct regmap *regmap; + struct delayed_work jack_detect_work; + struct snd_soc_jack *hs_jack; + struct timer_list btn_check_timer; + + int codec_type; + int sysclk; + int sysclk_src; + int lrck; + + int pll_src; + int pll_in; + int pll_out; + + int jack_type; +}; + +static const struct reg_default rt5668_reg[] = { + { 0x0000, 0x0000 }, + { 0x0001, 0xc8c8 }, + { 0x0002, 0x8080 }, + { 0x0003, 0x8000 }, + { 0x0004, 0xc80a }, + { 0x0005, 0x0000 }, + { 0x0006, 0x0000 }, + { 0x0007, 0x0000 }, + { 0x000a, 0x0000 }, + { 0x000b, 0x0000 }, + { 0x000c, 0x0000 }, + { 0x000d, 0x0000 }, + { 0x000f, 0x0808 }, + { 0x0010, 0x4000 }, + { 0x0011, 0x0000 }, + { 0x0012, 0x1404 }, + { 0x0013, 0x1000 }, + { 0x0014, 0xa00a }, + { 0x0015, 0x0404 }, + { 0x0016, 0x0404 }, + { 0x0017, 0x0011 }, + { 0x0018, 0xafaf }, + { 0x0019, 0xafaf }, + { 0x001a, 0xafaf }, + { 0x001b, 0x0011 }, + { 0x001c, 0x2f2f }, + { 0x001d, 0x2f2f }, + { 0x001e, 0x2f2f }, + { 0x001f, 0x0000 }, + { 0x0020, 0x0000 }, + { 0x0021, 0x0000 }, + { 0x0022, 0x5757 }, + { 0x0023, 0x0039 }, + { 0x0024, 0x000b }, + { 0x0026, 0xc0c0 }, + { 0x0027, 0xc0c0 }, + { 0x0028, 0xc0c0 }, + { 0x0029, 0x8080 }, + { 0x002a, 0xaaaa }, + { 0x002b, 0xaaaa }, + { 0x002c, 0xaba8 }, + { 0x002d, 0x0000 }, + { 0x002e, 0x0000 }, + { 0x002f, 0x0000 }, + { 0x0030, 0x0000 }, + { 0x0031, 0x5000 }, + { 0x0032, 0x0000 }, + { 0x0033, 0x0000 }, + { 0x0034, 0x0000 }, + { 0x0035, 0x0000 }, + { 0x003a, 0x0000 }, + { 0x003b, 0x0000 }, + { 0x003c, 0x00ff }, + { 0x003d, 0x0000 }, + { 0x003e, 0x00ff }, + { 0x003f, 0x0000 }, + { 0x0040, 0x0000 }, + { 0x0041, 0x00ff }, + { 0x0042, 0x0000 }, + { 0x0043, 0x00ff }, + { 0x0044, 0x0c0c }, + { 0x0049, 0xc00b }, + { 0x004a, 0x0000 }, + { 0x004b, 0x031f }, + { 0x004d, 0x0000 }, + { 0x004e, 0x001f }, + { 0x004f, 0x0000 }, + { 0x0050, 0x001f }, + { 0x0052, 0xf000 }, + { 0x0061, 0x0000 }, + { 0x0062, 0x0000 }, + { 0x0063, 0x003e }, + { 0x0064, 0x0000 }, + { 0x0065, 0x0000 }, + { 0x0066, 0x003f }, + { 0x0067, 0x0000 }, + { 0x006b, 0x0000 }, + { 0x006d, 0xff00 }, + { 0x006e, 0x2808 }, + { 0x006f, 0x000a }, + { 0x0070, 0x8000 }, + { 0x0071, 0x8000 }, + { 0x0072, 0x8000 }, + { 0x0073, 0x7000 }, + { 0x0074, 0x7770 }, + { 0x0075, 0x0002 }, + { 0x0076, 0x0001 }, + { 0x0078, 0x00f0 }, + { 0x0079, 0x0000 }, + { 0x007a, 0x0000 }, + { 0x007b, 0x0000 }, + { 0x007c, 0x0000 }, + { 0x007d, 0x0123 }, + { 0x007e, 0x4500 }, + { 0x007f, 0x8003 }, + { 0x0080, 0x0000 }, + { 0x0081, 0x0000 }, + { 0x0082, 0x0000 }, + { 0x0083, 0x0000 }, + { 0x0084, 0x0000 }, + { 0x0085, 0x0000 }, + { 0x0086, 0x0008 }, + { 0x0087, 0x0000 }, + { 0x0088, 0x0000 }, + { 0x0089, 0x0000 }, + { 0x008a, 0x0000 }, + { 0x008b, 0x0000 }, + { 0x008c, 0x0003 }, + { 0x008e, 0x0060 }, + { 0x008f, 0x1000 }, + { 0x0091, 0x0c26 }, + { 0x0092, 0x0073 }, + { 0x0093, 0x0000 }, + { 0x0094, 0x0080 }, + { 0x0098, 0x0000 }, + { 0x0099, 0x0000 }, + { 0x009a, 0x0007 }, + { 0x009f, 0x0000 }, + { 0x00a0, 0x0000 }, + { 0x00a1, 0x0002 }, + { 0x00a2, 0x0001 }, + { 0x00a3, 0x0002 }, + { 0x00a4, 0x0001 }, + { 0x00ae, 0x2040 }, + { 0x00af, 0x0000 }, + { 0x00b6, 0x0000 }, + { 0x00b7, 0x0000 }, + { 0x00b8, 0x0000 }, + { 0x00b9, 0x0000 }, + { 0x00ba, 0x0002 }, + { 0x00bb, 0x0000 }, + { 0x00be, 0x0000 }, + { 0x00c0, 0x0000 }, + { 0x00c1, 0x0aaa }, + { 0x00c2, 0xaa80 }, + { 0x00c3, 0x0003 }, + { 0x00c4, 0x0000 }, + { 0x00d0, 0x0000 }, + { 0x00d1, 0x2244 }, + { 0x00d2, 0x0000 }, + { 0x00d3, 0x3300 }, + { 0x00d4, 0x2200 }, + { 0x00d9, 0x0809 }, + { 0x00da, 0x0000 }, + { 0x00db, 0x0008 }, + { 0x00dc, 0x00c0 }, + { 0x00dd, 0x6724 }, + { 0x00de, 0x3131 }, + { 0x00df, 0x0008 }, + { 0x00e0, 0x4000 }, + { 0x00e1, 0x3131 }, + { 0x00e2, 0x600c }, + { 0x00ea, 0xb320 }, + { 0x00eb, 0x0000 }, + { 0x00ec, 0xb300 }, + { 0x00ed, 0x0000 }, + { 0x00ee, 0xb320 }, + { 0x00ef, 0x0000 }, + { 0x00f0, 0x0201 }, + { 0x00f1, 0x0ddd }, + { 0x00f2, 0x0ddd }, + { 0x00f6, 0x0000 }, + { 0x00f7, 0x0000 }, + { 0x00f8, 0x0000 }, + { 0x00fa, 0x0000 }, + { 0x00fb, 0x0000 }, + { 0x00fc, 0x0000 }, + { 0x00fd, 0x0000 }, + { 0x00fe, 0x10ec }, + { 0x00ff, 0x6451 }, + { 0x0100, 0xaaaa }, + { 0x0101, 0x000a }, + { 0x010a, 0xaaaa }, + { 0x010b, 0xa0a0 }, + { 0x010c, 0xaeae }, + { 0x010d, 0xaaaa }, + { 0x010e, 0xaaaa }, + { 0x010f, 0xaaaa }, + { 0x0110, 0xe002 }, + { 0x0111, 0xa602 }, + { 0x0112, 0xaaaa }, + { 0x0113, 0x2000 }, + { 0x0117, 0x0f00 }, + { 0x0125, 0x0420 }, + { 0x0132, 0x0000 }, + { 0x0133, 0x0000 }, + { 0x0136, 0x5555 }, + { 0x0137, 0x5540 }, + { 0x0138, 0x3700 }, + { 0x0139, 0x79a1 }, + { 0x013a, 0x2020 }, + { 0x013b, 0x2020 }, + { 0x013c, 0x2005 }, + { 0x013f, 0x0000 }, + { 0x0145, 0x0002 }, + { 0x0146, 0x0000 }, + { 0x0147, 0x0000 }, + { 0x0148, 0x0000 }, + { 0x0160, 0x4ec0 }, + { 0x0161, 0x0080 }, + { 0x0162, 0x0200 }, + { 0x0163, 0x0800 }, + { 0x0164, 0x0000 }, + { 0x0165, 0x0000 }, + { 0x0166, 0x0000 }, + { 0x0167, 0x000f }, + { 0x0168, 0x000f }, + { 0x0170, 0x4e80 }, + { 0x0171, 0x0080 }, + { 0x0172, 0x0200 }, + { 0x0173, 0x0800 }, + { 0x0174, 0x00ff }, + { 0x0175, 0x0000 }, + { 0x0190, 0x4131 }, + { 0x0191, 0x4131 }, + { 0x0192, 0x4131 }, + { 0x0193, 0x4131 }, + { 0x0194, 0x0000 }, + { 0x0195, 0x0000 }, + { 0x0196, 0x0000 }, + { 0x0197, 0x0000 }, + { 0x0198, 0x0000 }, + { 0x0199, 0x0000 }, + { 0x01a0, 0x1e64 }, + { 0x01a1, 0x06a3 }, + { 0x01a2, 0x0000 }, + { 0x01a3, 0x0000 }, + { 0x01a4, 0x0000 }, + { 0x01a5, 0x0000 }, + { 0x01a6, 0x0000 }, + { 0x01a7, 0x0000 }, + { 0x01a8, 0x0000 }, + { 0x01a9, 0x0000 }, + { 0x01aa, 0x0000 }, + { 0x01ab, 0x0000 }, + { 0x01b5, 0x0000 }, + { 0x01b6, 0x01c3 }, + { 0x01b7, 0x02a0 }, + { 0x01b8, 0x03e9 }, + { 0x01b9, 0x1389 }, + { 0x01ba, 0xc351 }, + { 0x01bb, 0x0009 }, + { 0x01bc, 0x0018 }, + { 0x01bd, 0x002a }, + { 0x01be, 0x004c }, + { 0x01bf, 0x0097 }, + { 0x01c0, 0x433d }, + { 0x01c1, 0x0000 }, + { 0x01c2, 0x0000 }, + { 0x01c3, 0x0000 }, + { 0x01c4, 0x0000 }, + { 0x01c5, 0x0000 }, + { 0x01c6, 0x0000 }, + { 0x01c7, 0x0000 }, + { 0x01c8, 0x40af }, + { 0x01c9, 0x0702 }, + { 0x01ca, 0x0000 }, + { 0x01cb, 0x0000 }, + { 0x01cc, 0x5757 }, + { 0x01cd, 0x5757 }, + { 0x01ce, 0x5757 }, + { 0x01cf, 0x5757 }, + { 0x01d0, 0x5757 }, + { 0x01d1, 0x5757 }, + { 0x01d2, 0x5757 }, + { 0x01d3, 0x5757 }, + { 0x01d4, 0x5757 }, + { 0x01d5, 0x5757 }, + { 0x01d6, 0x003c }, + { 0x01da, 0x0000 }, + { 0x01db, 0x0000 }, + { 0x01dc, 0x0000 }, + { 0x01de, 0x7c00 }, + { 0x01df, 0x0320 }, + { 0x01e0, 0x06a1 }, + { 0x01e1, 0x0000 }, + { 0x01e2, 0x0000 }, + { 0x01e3, 0x0000 }, + { 0x01e4, 0x0000 }, + { 0x01e5, 0x0000 }, + { 0x01e6, 0x0001 }, + { 0x01e7, 0x0000 }, + { 0x01e8, 0x0000 }, + { 0x01ea, 0x0000 }, + { 0x01eb, 0x0000 }, + { 0x01ec, 0x0000 }, + { 0x01ed, 0x0000 }, + { 0x01ee, 0x0000 }, + { 0x01ef, 0x0000 }, + { 0x01f0, 0x0000 }, + { 0x01f1, 0x0000 }, + { 0x01f2, 0x0000 }, + { 0x01f3, 0x0000 }, + { 0x01f4, 0x0000 }, + { 0x0200, 0x0000 }, + { 0x0201, 0x0000 }, + { 0x0202, 0x0000 }, + { 0x0203, 0x0000 }, + { 0x0204, 0x0000 }, + { 0x0205, 0x0000 }, + { 0x0206, 0x0000 }, + { 0x0207, 0x0000 }, + { 0x0208, 0x0000 }, + { 0x0210, 0x60b1 }, + { 0x0211, 0xa000 }, + { 0x0212, 0x024c }, + { 0x0213, 0xf7ff }, + { 0x0214, 0x024c }, + { 0x0215, 0x0102 }, + { 0x0216, 0x00a3 }, + { 0x0217, 0x0048 }, + { 0x0218, 0x92c0 }, + { 0x0219, 0x0000 }, + { 0x021a, 0x00c8 }, + { 0x021b, 0x0020 }, + { 0x02fa, 0x0000 }, + { 0x02fb, 0x0000 }, + { 0x02fc, 0x0000 }, + { 0x02ff, 0x0110 }, + { 0x0300, 0x001f }, + { 0x0301, 0x032c }, + { 0x0302, 0x5f21 }, + { 0x0303, 0x4000 }, + { 0x0304, 0x4000 }, + { 0x0305, 0x06d5 }, + { 0x0306, 0x8000 }, + { 0x0307, 0x0700 }, + { 0x0310, 0x4560 }, + { 0x0311, 0xa4a8 }, + { 0x0312, 0x7418 }, + { 0x0313, 0x0000 }, + { 0x0314, 0x0006 }, + { 0x0315, 0xffff }, + { 0x0316, 0xc400 }, + { 0x0317, 0x0000 }, + { 0x0330, 0x00a6 }, + { 0x0331, 0x04c3 }, + { 0x0332, 0x27c8 }, + { 0x0333, 0xbf50 }, + { 0x0334, 0x0045 }, + { 0x0335, 0x0007 }, + { 0x0336, 0x7418 }, + { 0x0337, 0x0501 }, + { 0x0338, 0x0000 }, + { 0x0339, 0x0010 }, + { 0x033a, 0x1010 }, + { 0x03c0, 0x7e00 }, + { 0x03c1, 0x8000 }, + { 0x03c2, 0x8000 }, + { 0x03c3, 0x8000 }, + { 0x03c4, 0x8000 }, + { 0x03c5, 0x8000 }, + { 0x03c6, 0x8000 }, + { 0x03c7, 0x8000 }, + { 0x03c8, 0x8000 }, + { 0x03c9, 0x8000 }, + { 0x03ca, 0x8000 }, + { 0x03cb, 0x8000 }, + { 0x03cc, 0x8000 }, + { 0x03d0, 0x0000 }, + { 0x03d1, 0x0000 }, + { 0x03d2, 0x0000 }, + { 0x03d3, 0x0000 }, + { 0x03d4, 0x2000 }, + { 0x03d5, 0x2000 }, + { 0x03d6, 0x0000 }, + { 0x03d7, 0x0000 }, + { 0x03d8, 0x2000 }, + { 0x03d9, 0x2000 }, + { 0x03da, 0x2000 }, + { 0x03db, 0x2000 }, + { 0x03dc, 0x0000 }, + { 0x03dd, 0x0000 }, + { 0x03de, 0x0000 }, + { 0x03df, 0x2000 }, + { 0x03e0, 0x0000 }, + { 0x03e1, 0x0000 }, + { 0x03e2, 0x0000 }, + { 0x03e3, 0x0000 }, + { 0x03e4, 0x0000 }, + { 0x03e5, 0x0000 }, + { 0x03e6, 0x0000 }, + { 0x03e7, 0x0000 }, + { 0x03e8, 0x0000 }, + { 0x03e9, 0x0000 }, + { 0x03ea, 0x0000 }, + { 0x03eb, 0x0000 }, + { 0x03ec, 0x0000 }, + { 0x03ed, 0x0000 }, + { 0x03ee, 0x0000 }, + { 0x03ef, 0x0000 }, + { 0x03f0, 0x0800 }, + { 0x03f1, 0x0800 }, + { 0x03f2, 0x0800 }, + { 0x03f3, 0x0800 }, + { 0x03fe, 0x0000 }, + { 0x03ff, 0x0000 }, + { 0x07f0, 0x0000 }, + { 0x07fa, 0x0000 }, +}; + +static const struct reg_default rt5663_reg[] = { + { 0x0000, 0x0000 }, + { 0x0002, 0x0008 }, + { 0x0005, 0x1000 }, + { 0x0006, 0x1000 }, + { 0x000a, 0x0000 }, + { 0x0010, 0x000f }, + { 0x0015, 0x42c1 }, + { 0x0016, 0x0000 }, + { 0x0018, 0x000b }, + { 0x0019, 0xafaf }, + { 0x001c, 0x2f2f }, + { 0x001f, 0x0000 }, + { 0x0022, 0x5757 }, + { 0x0023, 0x0039 }, + { 0x0026, 0xc0c0 }, + { 0x0029, 0x8080 }, + { 0x002a, 0xa0a0 }, + { 0x002c, 0x000c }, + { 0x002d, 0x0000 }, + { 0x0040, 0x0808 }, + { 0x0061, 0x0000 }, + { 0x0062, 0x0000 }, + { 0x0063, 0x003e }, + { 0x0064, 0x0000 }, + { 0x0065, 0x0000 }, + { 0x0066, 0x0000 }, + { 0x006b, 0x0000 }, + { 0x006e, 0x0000 }, + { 0x006f, 0x0000 }, + { 0x0070, 0x8020 }, + { 0x0073, 0x1000 }, + { 0x0074, 0xe400 }, + { 0x0075, 0x0002 }, + { 0x0076, 0x0001 }, + { 0x0077, 0x00f0 }, + { 0x0078, 0x0000 }, + { 0x0079, 0x0000 }, + { 0x007a, 0x0123 }, + { 0x007b, 0x8003 }, + { 0x0080, 0x0000 }, + { 0x0081, 0x0000 }, + { 0x0082, 0x0000 }, + { 0x0083, 0x0000 }, + { 0x0084, 0x0000 }, + { 0x0086, 0x0008 }, + { 0x0087, 0x0000 }, + { 0x008a, 0x0000 }, + { 0x008b, 0x0000 }, + { 0x008c, 0x0003 }, + { 0x008e, 0x0004 }, + { 0x008f, 0x1000 }, + { 0x0090, 0x0646 }, + { 0x0091, 0x0e3e }, + { 0x0092, 0x1071 }, + { 0x0093, 0x0000 }, + { 0x0094, 0x0080 }, + { 0x0097, 0x0000 }, + { 0x0098, 0x0000 }, + { 0x009a, 0x0000 }, + { 0x009f, 0x0000 }, + { 0x00ae, 0x2000 }, + { 0x00af, 0x0000 }, + { 0x00b6, 0x0000 }, + { 0x00b7, 0x0000 }, + { 0x00b8, 0x0000 }, + { 0x00ba, 0x0000 }, + { 0x00bb, 0x0000 }, + { 0x00be, 0x0000 }, + { 0x00bf, 0x0000 }, + { 0x00c0, 0x0000 }, + { 0x00c1, 0x0000 }, + { 0x00c5, 0x0000 }, + { 0x00cb, 0xa02f }, + { 0x00cc, 0x0000 }, + { 0x00cd, 0x0e02 }, + { 0x00d9, 0x08f9 }, + { 0x00db, 0x0008 }, + { 0x00dc, 0x00c0 }, + { 0x00dd, 0x6724 }, + { 0x00de, 0x3131 }, + { 0x00df, 0x0008 }, + { 0x00e0, 0x4000 }, + { 0x00e1, 0x3131 }, + { 0x00e2, 0x0043 }, + { 0x00e4, 0x400b }, + { 0x00e5, 0x8031 }, + { 0x00e6, 0x3080 }, + { 0x00e7, 0x4100 }, + { 0x00e8, 0x1400 }, + { 0x00e9, 0xe00a }, + { 0x00ea, 0x0404 }, + { 0x00eb, 0x0404 }, + { 0x00ec, 0xb320 }, + { 0x00ed, 0x0000 }, + { 0x00f4, 0x0000 }, + { 0x00f6, 0x0000 }, + { 0x00f8, 0x0000 }, + { 0x00fa, 0x8000 }, + { 0x00fd, 0x0001 }, + { 0x00fe, 0x10ec }, + { 0x00ff, 0x6406 }, + { 0x0100, 0xa0a0 }, + { 0x0108, 0x4444 }, + { 0x0109, 0x4444 }, + { 0x010a, 0xaaaa }, + { 0x010b, 0x00a0 }, + { 0x010c, 0x8aaa }, + { 0x010d, 0xaaaa }, + { 0x010e, 0x2aaa }, + { 0x010f, 0x002a }, + { 0x0110, 0xa0a4 }, + { 0x0111, 0x4602 }, + { 0x0112, 0x0101 }, + { 0x0113, 0x2000 }, + { 0x0114, 0x0000 }, + { 0x0116, 0x0000 }, + { 0x0117, 0x0f00 }, + { 0x0118, 0x0006 }, + { 0x0125, 0x2224 }, + { 0x0126, 0x5550 }, + { 0x0127, 0x0400 }, + { 0x0128, 0x7711 }, + { 0x0132, 0x0004 }, + { 0x0137, 0x5441 }, + { 0x0139, 0x79a1 }, + { 0x013a, 0x30c0 }, + { 0x013b, 0x2000 }, + { 0x013c, 0x2005 }, + { 0x013d, 0x30c0 }, + { 0x013e, 0x0000 }, + { 0x0140, 0x3700 }, + { 0x0141, 0x1f00 }, + { 0x0144, 0x0000 }, + { 0x0145, 0x0002 }, + { 0x0146, 0x0000 }, + { 0x0160, 0x0e80 }, + { 0x0161, 0x0020 }, + { 0x0162, 0x0080 }, + { 0x0163, 0x0800 }, + { 0x0164, 0x0000 }, + { 0x0165, 0x0000 }, + { 0x0166, 0x0000 }, + { 0x0167, 0x1417 }, + { 0x0168, 0x0017 }, + { 0x0169, 0x0017 }, + { 0x0180, 0x2000 }, + { 0x0181, 0x0000 }, + { 0x0182, 0x0000 }, + { 0x0183, 0x2000 }, + { 0x0184, 0x0000 }, + { 0x0185, 0x0000 }, + { 0x01b0, 0x4b30 }, + { 0x01b1, 0x0000 }, + { 0x01b2, 0xd870 }, + { 0x01b3, 0x0000 }, + { 0x01b4, 0x0030 }, + { 0x01b5, 0x5757 }, + { 0x01b6, 0x5757 }, + { 0x01b7, 0x5757 }, + { 0x01b8, 0x5757 }, + { 0x01c0, 0x433d }, + { 0x01c1, 0x0540 }, + { 0x01c2, 0x0000 }, + { 0x01c3, 0x0000 }, + { 0x01c4, 0x0000 }, + { 0x01c5, 0x0009 }, + { 0x01c6, 0x0018 }, + { 0x01c7, 0x002a }, + { 0x01c8, 0x004c }, + { 0x01c9, 0x0097 }, + { 0x01ca, 0x01c3 }, + { 0x01cb, 0x03e9 }, + { 0x01cc, 0x1389 }, + { 0x01cd, 0xc351 }, + { 0x01ce, 0x0000 }, + { 0x01cf, 0x0000 }, + { 0x01d0, 0x0000 }, + { 0x01d1, 0x0000 }, + { 0x01d2, 0x0000 }, + { 0x01d3, 0x003c }, + { 0x01d4, 0x5757 }, + { 0x01d5, 0x5757 }, + { 0x01d6, 0x5757 }, + { 0x01d7, 0x5757 }, + { 0x01d8, 0x5757 }, + { 0x01d9, 0x5757 }, + { 0x01da, 0x0000 }, + { 0x01db, 0x0000 }, + { 0x01dd, 0x0009 }, + { 0x01de, 0x7f00 }, + { 0x01df, 0x00c8 }, + { 0x01e0, 0x0691 }, + { 0x01e1, 0x0000 }, + { 0x01e2, 0x0000 }, + { 0x01e3, 0x0000 }, + { 0x01e4, 0x0000 }, + { 0x01e5, 0x0040 }, + { 0x01e6, 0x0000 }, + { 0x01e7, 0x0000 }, + { 0x01e8, 0x0000 }, + { 0x01ea, 0x0000 }, + { 0x01eb, 0x0000 }, + { 0x01ec, 0x0000 }, + { 0x01ed, 0x0000 }, + { 0x01ee, 0x0000 }, + { 0x01ef, 0x0000 }, + { 0x01f0, 0x0000 }, + { 0x01f1, 0x0000 }, + { 0x01f2, 0x0000 }, + { 0x0200, 0x0000 }, + { 0x0201, 0x2244 }, + { 0x0202, 0xaaaa }, + { 0x0250, 0x8010 }, + { 0x0251, 0x0000 }, + { 0x0252, 0x028a }, + { 0x02fa, 0x0000 }, + { 0x02fb, 0x0000 }, + { 0x02fc, 0x0000 }, + { 0x0300, 0x0000 }, + { 0x03d0, 0x0000 }, + { 0x03d1, 0x0000 }, + { 0x03d2, 0x0000 }, + { 0x03d3, 0x0000 }, + { 0x03d4, 0x2000 }, + { 0x03d5, 0x2000 }, + { 0x03d6, 0x0000 }, + { 0x03d7, 0x0000 }, + { 0x03d8, 0x2000 }, + { 0x03d9, 0x2000 }, + { 0x03da, 0x2000 }, + { 0x03db, 0x2000 }, + { 0x03dc, 0x0000 }, + { 0x03dd, 0x0000 }, + { 0x03de, 0x0000 }, + { 0x03df, 0x2000 }, + { 0x03e0, 0x0000 }, + { 0x03e1, 0x0000 }, + { 0x03e2, 0x0000 }, + { 0x03e3, 0x0000 }, + { 0x03e4, 0x0000 }, + { 0x03e5, 0x0000 }, + { 0x03e6, 0x0000 }, + { 0x03e7, 0x0000 }, + { 0x03e8, 0x0000 }, + { 0x03e9, 0x0000 }, + { 0x03ea, 0x0000 }, + { 0x03eb, 0x0000 }, + { 0x03ec, 0x0000 }, + { 0x03ed, 0x0000 }, + { 0x03ee, 0x0000 }, + { 0x03ef, 0x0000 }, + { 0x03f0, 0x0800 }, + { 0x03f1, 0x0800 }, + { 0x03f2, 0x0800 }, + { 0x03f3, 0x0800 }, +}; + +static bool rt5663_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT5663_RESET: + case RT5663_SIL_DET_CTL: + case RT5663_HP_IMP_GAIN_2: + case RT5663_AD_DA_MIXER: + case RT5663_FRAC_DIV_2: + case RT5663_MICBIAS_1: + case RT5663_ASRC_11_2: + case RT5663_ADC_EQ_1: + case RT5663_INT_ST_1: + case RT5663_INT_ST_2: + case RT5663_GPIO_STA: + case RT5663_SIN_GEN_1: + case RT5663_IL_CMD_1: + case RT5663_IL_CMD_5: + case RT5663_IL_CMD_PWRSAV1: + case RT5663_EM_JACK_TYPE_1: + case RT5663_EM_JACK_TYPE_2: + case RT5663_EM_JACK_TYPE_3: + case RT5663_JD_CTRL2: + case RT5663_VENDOR_ID: + case RT5663_VENDOR_ID_1: + case RT5663_VENDOR_ID_2: + case RT5663_PLL_INT_REG: + case RT5663_SOFT_RAMP: + case RT5663_STO_DRE_1: + case RT5663_STO_DRE_5: + case RT5663_STO_DRE_6: + case RT5663_STO_DRE_7: + case RT5663_MIC_DECRO_1: + case RT5663_MIC_DECRO_4: + case RT5663_HP_IMP_SEN_1: + case RT5663_HP_IMP_SEN_3: + case RT5663_HP_IMP_SEN_4: + case RT5663_HP_IMP_SEN_5: + case RT5663_HP_CALIB_1_1: + case RT5663_HP_CALIB_9: + case RT5663_HP_CALIB_ST1: + case RT5663_HP_CALIB_ST2: + case RT5663_HP_CALIB_ST3: + case RT5663_HP_CALIB_ST4: + case RT5663_HP_CALIB_ST5: + case RT5663_HP_CALIB_ST6: + case RT5663_HP_CALIB_ST7: + case RT5663_HP_CALIB_ST8: + case RT5663_HP_CALIB_ST9: + case RT5663_ANA_JD: + return true; + default: + return false; + } +} + +static bool rt5663_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT5663_RESET: + case RT5663_HP_OUT_EN: + case RT5663_HP_LCH_DRE: + case RT5663_HP_RCH_DRE: + case RT5663_CALIB_BST: + case RT5663_RECMIX: + case RT5663_SIL_DET_CTL: + case RT5663_PWR_SAV_SILDET: + case RT5663_SIDETONE_CTL: + case RT5663_STO1_DAC_DIG_VOL: + case RT5663_STO1_ADC_DIG_VOL: + case RT5663_STO1_BOOST: + case RT5663_HP_IMP_GAIN_1: + case RT5663_HP_IMP_GAIN_2: + case RT5663_STO1_ADC_MIXER: + case RT5663_AD_DA_MIXER: + case RT5663_STO_DAC_MIXER: + case RT5663_DIG_SIDE_MIXER: + case RT5663_BYPASS_STO_DAC: + case RT5663_CALIB_REC_MIX: + case RT5663_PWR_DIG_1: + case RT5663_PWR_DIG_2: + case RT5663_PWR_ANLG_1: + case RT5663_PWR_ANLG_2: + case RT5663_PWR_ANLG_3: + case RT5663_PWR_MIXER: + case RT5663_SIG_CLK_DET: + case RT5663_PRE_DIV_GATING_1: + case RT5663_PRE_DIV_GATING_2: + case RT5663_I2S1_SDP: + case RT5663_ADDA_CLK_1: + case RT5663_ADDA_RST: + case RT5663_FRAC_DIV_1: + case RT5663_FRAC_DIV_2: + case RT5663_TDM_1: + case RT5663_TDM_2: + case RT5663_TDM_3: + case RT5663_TDM_4: + case RT5663_TDM_5: + case RT5663_GLB_CLK: + case RT5663_PLL_1: + case RT5663_PLL_2: + case RT5663_ASRC_1: + case RT5663_ASRC_2: + case RT5663_ASRC_4: + case RT5663_DUMMY_REG: + case RT5663_ASRC_8: + case RT5663_ASRC_9: + case RT5663_ASRC_11: + case RT5663_DEPOP_1: + case RT5663_DEPOP_2: + case RT5663_DEPOP_3: + case RT5663_HP_CHARGE_PUMP_1: + case RT5663_HP_CHARGE_PUMP_2: + case RT5663_MICBIAS_1: + case RT5663_RC_CLK: + case RT5663_ASRC_11_2: + case RT5663_DUMMY_REG_2: + case RT5663_REC_PATH_GAIN: + case RT5663_AUTO_1MRC_CLK: + case RT5663_ADC_EQ_1: + case RT5663_ADC_EQ_2: + case RT5663_IRQ_1: + case RT5663_IRQ_2: + case RT5663_IRQ_3: + case RT5663_IRQ_4: + case RT5663_IRQ_5: + case RT5663_INT_ST_1: + case RT5663_INT_ST_2: + case RT5663_GPIO_1: + case RT5663_GPIO_2: + case RT5663_GPIO_STA: + case RT5663_SIN_GEN_1: + case RT5663_SIN_GEN_2: + case RT5663_SIN_GEN_3: + case RT5663_SOF_VOL_ZC1: + case RT5663_IL_CMD_1: + case RT5663_IL_CMD_2: + case RT5663_IL_CMD_3: + case RT5663_IL_CMD_4: + case RT5663_IL_CMD_5: + case RT5663_IL_CMD_6: + case RT5663_IL_CMD_7: + case RT5663_IL_CMD_8: + case RT5663_IL_CMD_PWRSAV1: + case RT5663_IL_CMD_PWRSAV2: + case RT5663_EM_JACK_TYPE_1: + case RT5663_EM_JACK_TYPE_2: + case RT5663_EM_JACK_TYPE_3: + case RT5663_EM_JACK_TYPE_4: + case RT5663_EM_JACK_TYPE_5: + case RT5663_EM_JACK_TYPE_6: + case RT5663_STO1_HPF_ADJ1: + case RT5663_STO1_HPF_ADJ2: + case RT5663_FAST_OFF_MICBIAS: + case RT5663_JD_CTRL1: + case RT5663_JD_CTRL2: + case RT5663_DIG_MISC: + case RT5663_VENDOR_ID: + case RT5663_VENDOR_ID_1: + case RT5663_VENDOR_ID_2: + case RT5663_DIG_VOL_ZCD: + case RT5663_ANA_BIAS_CUR_1: + case RT5663_ANA_BIAS_CUR_2: + case RT5663_ANA_BIAS_CUR_3: + case RT5663_ANA_BIAS_CUR_4: + case RT5663_ANA_BIAS_CUR_5: + case RT5663_ANA_BIAS_CUR_6: + case RT5663_BIAS_CUR_5: + case RT5663_BIAS_CUR_6: + case RT5663_BIAS_CUR_7: + case RT5663_BIAS_CUR_8: + case RT5663_DACREF_LDO: + case RT5663_DUMMY_REG_3: + case RT5663_BIAS_CUR_9: + case RT5663_DUMMY_REG_4: + case RT5663_VREFADJ_OP: + case RT5663_VREF_RECMIX: + case RT5663_CHARGE_PUMP_1: + case RT5663_CHARGE_PUMP_1_2: + case RT5663_CHARGE_PUMP_1_3: + case RT5663_CHARGE_PUMP_2: + case RT5663_DIG_IN_PIN1: + case RT5663_PAD_DRV_CTL: + case RT5663_PLL_INT_REG: + case RT5663_CHOP_DAC_L: + case RT5663_CHOP_ADC: + case RT5663_CALIB_ADC: + case RT5663_CHOP_DAC_R: + case RT5663_DUMMY_CTL_DACLR: + case RT5663_DUMMY_REG_5: + case RT5663_SOFT_RAMP: + case RT5663_TEST_MODE_1: + case RT5663_TEST_MODE_2: + case RT5663_TEST_MODE_3: + case RT5663_STO_DRE_1: + case RT5663_STO_DRE_2: + case RT5663_STO_DRE_3: + case RT5663_STO_DRE_4: + case RT5663_STO_DRE_5: + case RT5663_STO_DRE_6: + case RT5663_STO_DRE_7: + case RT5663_STO_DRE_8: + case RT5663_STO_DRE_9: + case RT5663_STO_DRE_10: + case RT5663_MIC_DECRO_1: + case RT5663_MIC_DECRO_2: + case RT5663_MIC_DECRO_3: + case RT5663_MIC_DECRO_4: + case RT5663_MIC_DECRO_5: + case RT5663_MIC_DECRO_6: + case RT5663_HP_DECRO_1: + case RT5663_HP_DECRO_2: + case RT5663_HP_DECRO_3: + case RT5663_HP_DECRO_4: + case RT5663_HP_DECOUP: + case RT5663_HP_IMP_SEN_MAP8: + case RT5663_HP_IMP_SEN_MAP9: + case RT5663_HP_IMP_SEN_MAP10: + case RT5663_HP_IMP_SEN_MAP11: + case RT5663_HP_IMP_SEN_1: + case RT5663_HP_IMP_SEN_2: + case RT5663_HP_IMP_SEN_3: + case RT5663_HP_IMP_SEN_4: + case RT5663_HP_IMP_SEN_5: + case RT5663_HP_IMP_SEN_6: + case RT5663_HP_IMP_SEN_7: + case RT5663_HP_IMP_SEN_8: + case RT5663_HP_IMP_SEN_9: + case RT5663_HP_IMP_SEN_10: + case RT5663_HP_IMP_SEN_11: + case RT5663_HP_IMP_SEN_12: + case RT5663_HP_IMP_SEN_13: + case RT5663_HP_IMP_SEN_14: + case RT5663_HP_IMP_SEN_15: + case RT5663_HP_IMP_SEN_16: + case RT5663_HP_IMP_SEN_17: + case RT5663_HP_IMP_SEN_18: + case RT5663_HP_IMP_SEN_19: + case RT5663_HP_IMPSEN_DIG5: + case RT5663_HP_IMPSEN_MAP1: + case RT5663_HP_IMPSEN_MAP2: + case RT5663_HP_IMPSEN_MAP3: + case RT5663_HP_IMPSEN_MAP4: + case RT5663_HP_IMPSEN_MAP5: + case RT5663_HP_IMPSEN_MAP7: + case RT5663_HP_LOGIC_1: + case RT5663_HP_LOGIC_2: + case RT5663_HP_CALIB_1: + case RT5663_HP_CALIB_1_1: + case RT5663_HP_CALIB_2: + case RT5663_HP_CALIB_3: + case RT5663_HP_CALIB_4: + case RT5663_HP_CALIB_5: + case RT5663_HP_CALIB_5_1: + case RT5663_HP_CALIB_6: + case RT5663_HP_CALIB_7: + case RT5663_HP_CALIB_9: + case RT5663_HP_CALIB_10: + case RT5663_HP_CALIB_11: + case RT5663_HP_CALIB_ST1: + case RT5663_HP_CALIB_ST2: + case RT5663_HP_CALIB_ST3: + case RT5663_HP_CALIB_ST4: + case RT5663_HP_CALIB_ST5: + case RT5663_HP_CALIB_ST6: + case RT5663_HP_CALIB_ST7: + case RT5663_HP_CALIB_ST8: + case RT5663_HP_CALIB_ST9: + case RT5663_HP_AMP_DET: + case RT5663_DUMMY_REG_6: + case RT5663_HP_BIAS: + case RT5663_CBJ_1: + case RT5663_CBJ_2: + case RT5663_CBJ_3: + case RT5663_DUMMY_1: + case RT5663_DUMMY_2: + case RT5663_DUMMY_3: + case RT5663_ANA_JD: + case RT5663_ADC_LCH_LPF1_A1: + case RT5663_ADC_RCH_LPF1_A1: + case RT5663_ADC_LCH_LPF1_H0: + case RT5663_ADC_RCH_LPF1_H0: + case RT5663_ADC_LCH_BPF1_A1: + case RT5663_ADC_RCH_BPF1_A1: + case RT5663_ADC_LCH_BPF1_A2: + case RT5663_ADC_RCH_BPF1_A2: + case RT5663_ADC_LCH_BPF1_H0: + case RT5663_ADC_RCH_BPF1_H0: + case RT5663_ADC_LCH_BPF2_A1: + case RT5663_ADC_RCH_BPF2_A1: + case RT5663_ADC_LCH_BPF2_A2: + case RT5663_ADC_RCH_BPF2_A2: + case RT5663_ADC_LCH_BPF2_H0: + case RT5663_ADC_RCH_BPF2_H0: + case RT5663_ADC_LCH_BPF3_A1: + case RT5663_ADC_RCH_BPF3_A1: + case RT5663_ADC_LCH_BPF3_A2: + case RT5663_ADC_RCH_BPF3_A2: + case RT5663_ADC_LCH_BPF3_H0: + case RT5663_ADC_RCH_BPF3_H0: + case RT5663_ADC_LCH_BPF4_A1: + case RT5663_ADC_RCH_BPF4_A1: + case RT5663_ADC_LCH_BPF4_A2: + case RT5663_ADC_RCH_BPF4_A2: + case RT5663_ADC_LCH_BPF4_H0: + case RT5663_ADC_RCH_BPF4_H0: + case RT5663_ADC_LCH_HPF1_A1: + case RT5663_ADC_RCH_HPF1_A1: + case RT5663_ADC_LCH_HPF1_H0: + case RT5663_ADC_RCH_HPF1_H0: + case RT5663_ADC_EQ_PRE_VOL_L: + case RT5663_ADC_EQ_PRE_VOL_R: + case RT5663_ADC_EQ_POST_VOL_L: + case RT5663_ADC_EQ_POST_VOL_R: + return true; + default: + return false; + } +} + +static bool rt5668_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT5663_RESET: + case RT5668_CBJ_TYPE_2: + case RT5668_PDM_OUT_CTL: + case RT5668_PDM_I2C_DATA_CTL1: + case RT5668_PDM_I2C_DATA_CTL4: + case RT5668_ALC_BK_GAIN: + case RT5663_PLL_2: + case RT5663_MICBIAS_1: + case RT5663_ADC_EQ_1: + case RT5663_INT_ST_1: + case RT5668_GPIO_STA: + case RT5663_IL_CMD_1: + case RT5663_IL_CMD_5: + case RT5668_A_JD_CTRL: + case RT5663_JD_CTRL2: + case RT5663_VENDOR_ID: + case RT5663_VENDOR_ID_1: + case RT5663_VENDOR_ID_2: + case RT5663_STO_DRE_1: + case RT5663_STO_DRE_5: + case RT5663_STO_DRE_6: + case RT5663_STO_DRE_7: + case RT5668_MONO_DYNA_6: + case RT5668_STO1_SIL_DET: + case RT5668_MONOL_SIL_DET: + case RT5668_MONOR_SIL_DET: + case RT5668_STO2_DAC_SIL: + case RT5668_MONO_AMP_CAL_ST1: + case RT5668_MONO_AMP_CAL_ST2: + case RT5668_MONO_AMP_CAL_ST3: + case RT5668_MONO_AMP_CAL_ST4: + case RT5663_HP_IMP_SEN_2: + case RT5663_HP_IMP_SEN_3: + case RT5663_HP_IMP_SEN_4: + case RT5663_HP_IMP_SEN_10: + case RT5663_HP_CALIB_1: + case RT5663_HP_CALIB_10: + case RT5663_HP_CALIB_ST1: + case RT5663_HP_CALIB_ST4: + case RT5663_HP_CALIB_ST5: + case RT5663_HP_CALIB_ST6: + case RT5663_HP_CALIB_ST7: + case RT5663_HP_CALIB_ST8: + case RT5663_HP_CALIB_ST9: + case RT5668_HP_CALIB_ST10: + case RT5668_HP_CALIB_ST11: + return true; + default: + return false; + } +} + +static bool rt5668_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT5668_LOUT_CTRL: + case RT5668_HP_AMP_2: + case RT5668_MONO_OUT: + case RT5668_MONO_GAIN: + case RT5668_AEC_BST: + case RT5668_IN1_IN2: + case RT5668_IN3_IN4: + case RT5668_INL1_INR1: + case RT5668_CBJ_TYPE_2: + case RT5668_CBJ_TYPE_3: + case RT5668_CBJ_TYPE_4: + case RT5668_CBJ_TYPE_5: + case RT5668_CBJ_TYPE_8: + case RT5668_DAC3_DIG_VOL: + case RT5668_DAC3_CTRL: + case RT5668_MONO_ADC_DIG_VOL: + case RT5668_STO2_ADC_DIG_VOL: + case RT5668_MONO_ADC_BST_GAIN: + case RT5668_STO2_ADC_BST_GAIN: + case RT5668_SIDETONE_CTRL: + case RT5668_MONO1_ADC_MIXER: + case RT5668_STO2_ADC_MIXER: + case RT5668_MONO_DAC_MIXER: + case RT5668_DAC2_SRC_CTRL: + case RT5668_IF_3_4_DATA_CTL: + case RT5668_IF_5_DATA_CTL: + case RT5668_PDM_OUT_CTL: + case RT5668_PDM_I2C_DATA_CTL1: + case RT5668_PDM_I2C_DATA_CTL2: + case RT5668_PDM_I2C_DATA_CTL3: + case RT5668_PDM_I2C_DATA_CTL4: + case RT5668_RECMIX1_NEW: + case RT5668_RECMIX1L_0: + case RT5668_RECMIX1L: + case RT5668_RECMIX1R_0: + case RT5668_RECMIX1R: + case RT5668_RECMIX2_NEW: + case RT5668_RECMIX2_L_2: + case RT5668_RECMIX2_R: + case RT5668_RECMIX2_R_2: + case RT5668_CALIB_REC_LR: + case RT5668_ALC_BK_GAIN: + case RT5668_MONOMIX_GAIN: + case RT5668_MONOMIX_IN_GAIN: + case RT5668_OUT_MIXL_GAIN: + case RT5668_OUT_LMIX_IN_GAIN: + case RT5668_OUT_RMIX_IN_GAIN: + case RT5668_OUT_RMIX_IN_GAIN1: + case RT5668_LOUT_MIXER_CTRL: + case RT5668_PWR_VOL: + case RT5668_ADCDAC_RST: + case RT5668_I2S34_SDP: + case RT5668_I2S5_SDP: + case RT5668_TDM_5: + case RT5668_TDM_6: + case RT5668_TDM_7: + case RT5668_TDM_8: + case RT5668_ASRC_3: + case RT5668_ASRC_6: + case RT5668_ASRC_7: + case RT5668_PLL_TRK_13: + case RT5668_I2S_M_CLK_CTL: + case RT5668_FDIV_I2S34_M_CLK: + case RT5668_FDIV_I2S34_M_CLK2: + case RT5668_FDIV_I2S5_M_CLK: + case RT5668_FDIV_I2S5_M_CLK2: + case RT5668_IRQ_4: + case RT5668_GPIO_3: + case RT5668_GPIO_4: + case RT5668_GPIO_STA: + case RT5668_HP_AMP_DET1: + case RT5668_HP_AMP_DET2: + case RT5668_HP_AMP_DET3: + case RT5668_MID_BD_HP_AMP: + case RT5668_LOW_BD_HP_AMP: + case RT5668_SOF_VOL_ZC2: + case RT5668_ADC_STO2_ADJ1: + case RT5668_ADC_STO2_ADJ2: + case RT5668_A_JD_CTRL: + case RT5668_JD1_TRES_CTRL: + case RT5668_JD2_TRES_CTRL: + case RT5668_JD_CTRL2: + case RT5668_DUM_REG_2: + case RT5668_DUM_REG_3: + case RT5663_VENDOR_ID: + case RT5663_VENDOR_ID_1: + case RT5663_VENDOR_ID_2: + case RT5668_DACADC_DIG_VOL2: + case RT5668_DIG_IN_PIN2: + case RT5668_PAD_DRV_CTL1: + case RT5668_SOF_RAM_DEPOP: + case RT5668_VOL_TEST: + case RT5668_TEST_MODE_3: + case RT5668_TEST_MODE_4: + case RT5663_STO_DRE_9: + case RT5668_MONO_DYNA_1: + case RT5668_MONO_DYNA_2: + case RT5668_MONO_DYNA_3: + case RT5668_MONO_DYNA_4: + case RT5668_MONO_DYNA_5: + case RT5668_MONO_DYNA_6: + case RT5668_STO1_SIL_DET: + case RT5668_MONOL_SIL_DET: + case RT5668_MONOR_SIL_DET: + case RT5668_STO2_DAC_SIL: + case RT5668_PWR_SAV_CTL1: + case RT5668_PWR_SAV_CTL2: + case RT5668_PWR_SAV_CTL3: + case RT5668_PWR_SAV_CTL4: + case RT5668_PWR_SAV_CTL5: + case RT5668_PWR_SAV_CTL6: + case RT5668_MONO_AMP_CAL1: + case RT5668_MONO_AMP_CAL2: + case RT5668_MONO_AMP_CAL3: + case RT5668_MONO_AMP_CAL4: + case RT5668_MONO_AMP_CAL5: + case RT5668_MONO_AMP_CAL6: + case RT5668_MONO_AMP_CAL7: + case RT5668_MONO_AMP_CAL_ST1: + case RT5668_MONO_AMP_CAL_ST2: + case RT5668_MONO_AMP_CAL_ST3: + case RT5668_MONO_AMP_CAL_ST4: + case RT5668_MONO_AMP_CAL_ST5: + case RT5668_HP_IMP_SEN_13: + case RT5668_HP_IMP_SEN_14: + case RT5668_HP_IMP_SEN_6: + case RT5668_HP_IMP_SEN_7: + case RT5668_HP_IMP_SEN_8: + case RT5668_HP_IMP_SEN_9: + case RT5668_HP_IMP_SEN_10: + case RT5668_HP_LOGIC_3: + case RT5668_HP_CALIB_ST10: + case RT5668_HP_CALIB_ST11: + case RT5668_PRO_REG_TBL_4: + case RT5668_PRO_REG_TBL_5: + case RT5668_PRO_REG_TBL_6: + case RT5668_PRO_REG_TBL_7: + case RT5668_PRO_REG_TBL_8: + case RT5668_PRO_REG_TBL_9: + case RT5668_SAR_ADC_INL_1: + case RT5668_SAR_ADC_INL_2: + case RT5668_SAR_ADC_INL_3: + case RT5668_SAR_ADC_INL_4: + case RT5668_SAR_ADC_INL_5: + case RT5668_SAR_ADC_INL_6: + case RT5668_SAR_ADC_INL_7: + case RT5668_SAR_ADC_INL_8: + case RT5668_SAR_ADC_INL_9: + case RT5668_SAR_ADC_INL_10: + case RT5668_SAR_ADC_INL_11: + case RT5668_SAR_ADC_INL_12: + case RT5668_DRC_CTRL_1: + case RT5668_DRC1_CTRL_2: + case RT5668_DRC1_CTRL_3: + case RT5668_DRC1_CTRL_4: + case RT5668_DRC1_CTRL_5: + case RT5668_DRC1_CTRL_6: + case RT5668_DRC1_HD_CTRL_1: + case RT5668_DRC1_HD_CTRL_2: + case RT5668_DRC1_PRI_REG_1: + case RT5668_DRC1_PRI_REG_2: + case RT5668_DRC1_PRI_REG_3: + case RT5668_DRC1_PRI_REG_4: + case RT5668_DRC1_PRI_REG_5: + case RT5668_DRC1_PRI_REG_6: + case RT5668_DRC1_PRI_REG_7: + case RT5668_DRC1_PRI_REG_8: + case RT5668_ALC_PGA_CTL_1: + case RT5668_ALC_PGA_CTL_2: + case RT5668_ALC_PGA_CTL_3: + case RT5668_ALC_PGA_CTL_4: + case RT5668_ALC_PGA_CTL_5: + case RT5668_ALC_PGA_CTL_6: + case RT5668_ALC_PGA_CTL_7: + case RT5668_ALC_PGA_CTL_8: + case RT5668_ALC_PGA_REG_1: + case RT5668_ALC_PGA_REG_2: + case RT5668_ALC_PGA_REG_3: + case RT5668_ADC_EQ_RECOV_1: + case RT5668_ADC_EQ_RECOV_2: + case RT5668_ADC_EQ_RECOV_3: + case RT5668_ADC_EQ_RECOV_4: + case RT5668_ADC_EQ_RECOV_5: + case RT5668_ADC_EQ_RECOV_6: + case RT5668_ADC_EQ_RECOV_7: + case RT5668_ADC_EQ_RECOV_8: + case RT5668_ADC_EQ_RECOV_9: + case RT5668_ADC_EQ_RECOV_10: + case RT5668_ADC_EQ_RECOV_11: + case RT5668_ADC_EQ_RECOV_12: + case RT5668_ADC_EQ_RECOV_13: + case RT5668_VID_HIDDEN: + case RT5668_VID_CUSTOMER: + case RT5668_SCAN_MODE: + case RT5668_I2C_BYPA: + return true; + case RT5663_TDM_1: + case RT5663_DEPOP_3: + case RT5663_ASRC_11_2: + case RT5663_INT_ST_2: + case RT5663_GPIO_STA: + case RT5663_SIN_GEN_1: + case RT5663_SIN_GEN_2: + case RT5663_SIN_GEN_3: + case RT5663_IL_CMD_PWRSAV1: + case RT5663_IL_CMD_PWRSAV2: + case RT5663_EM_JACK_TYPE_1: + case RT5663_EM_JACK_TYPE_2: + case RT5663_EM_JACK_TYPE_3: + case RT5663_EM_JACK_TYPE_4: + case RT5663_FAST_OFF_MICBIAS: + case RT5663_ANA_BIAS_CUR_1: + case RT5663_ANA_BIAS_CUR_2: + case RT5663_BIAS_CUR_9: + case RT5663_DUMMY_REG_4: + case RT5663_VREF_RECMIX: + case RT5663_CHARGE_PUMP_1_2: + case RT5663_CHARGE_PUMP_1_3: + case RT5663_CHARGE_PUMP_2: + case RT5663_CHOP_DAC_R: + case RT5663_DUMMY_CTL_DACLR: + case RT5663_DUMMY_REG_5: + case RT5663_SOFT_RAMP: + case RT5663_TEST_MODE_1: + case RT5663_STO_DRE_10: + case RT5663_MIC_DECRO_1: + case RT5663_MIC_DECRO_2: + case RT5663_MIC_DECRO_3: + case RT5663_MIC_DECRO_4: + case RT5663_MIC_DECRO_5: + case RT5663_MIC_DECRO_6: + case RT5663_HP_DECRO_1: + case RT5663_HP_DECRO_2: + case RT5663_HP_DECRO_3: + case RT5663_HP_DECRO_4: + case RT5663_HP_DECOUP: + case RT5663_HP_IMPSEN_MAP4: + case RT5663_HP_IMPSEN_MAP5: + case RT5663_HP_IMPSEN_MAP7: + case RT5663_HP_CALIB_1: + case RT5663_CBJ_1: + case RT5663_CBJ_2: + case RT5663_CBJ_3: + return false; + default: + return rt5663_readable_register(dev, reg); + } +} + +static const DECLARE_TLV_DB_SCALE(rt5663_hp_vol_tlv, -2400, 150, 0); +static const DECLARE_TLV_DB_SCALE(rt5668_hp_vol_tlv, -2250, 150, 0); +static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0); +static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); + +/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ +static const DECLARE_TLV_DB_RANGE(in_bst_tlv, + 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), + 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), + 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), + 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), + 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), + 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), + 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0) +); + +/* Interface data select */ +static const char * const rt5663_if1_adc_data_select[] = { + "L/R", "R/L", "L/L", "R/R" +}; + +static SOC_ENUM_SINGLE_DECL(rt5663_if1_adc_enum, RT5663_TDM_2, + RT5663_DATA_SWAP_ADCDAT1_SHIFT, rt5663_if1_adc_data_select); + +static void rt5663_enable_push_button_irq(struct snd_soc_codec *codec, + bool enable) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + if (enable) { + snd_soc_update_bits(codec, RT5663_IL_CMD_6, + RT5668_EN_4BTN_INL_MASK, RT5668_EN_4BTN_INL_EN); + /* reset in-line command */ + snd_soc_update_bits(codec, RT5663_IL_CMD_6, + RT5668_RESET_4BTN_INL_MASK, + RT5668_RESET_4BTN_INL_RESET); + snd_soc_update_bits(codec, RT5663_IL_CMD_6, + RT5668_RESET_4BTN_INL_MASK, + RT5668_RESET_4BTN_INL_NOR); + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + snd_soc_update_bits(codec, RT5663_IRQ_3, + RT5668_EN_IRQ_INLINE_MASK, + RT5668_EN_IRQ_INLINE_NOR); + break; + case CODEC_TYPE_RT5663: + snd_soc_update_bits(codec, RT5663_IRQ_2, + RT5663_EN_IRQ_INLINE_MASK, + RT5663_EN_IRQ_INLINE_NOR); + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + } else { + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + snd_soc_update_bits(codec, RT5663_IRQ_3, + RT5668_EN_IRQ_INLINE_MASK, + RT5668_EN_IRQ_INLINE_BYP); + break; + case CODEC_TYPE_RT5663: + snd_soc_update_bits(codec, RT5663_IRQ_2, + RT5663_EN_IRQ_INLINE_MASK, + RT5663_EN_IRQ_INLINE_BYP); + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + snd_soc_update_bits(codec, RT5663_IL_CMD_6, + RT5668_EN_4BTN_INL_MASK, RT5668_EN_4BTN_INL_DIS); + /* reset in-line command */ + snd_soc_update_bits(codec, RT5663_IL_CMD_6, + RT5668_RESET_4BTN_INL_MASK, + RT5668_RESET_4BTN_INL_RESET); + snd_soc_update_bits(codec, RT5663_IL_CMD_6, + RT5668_RESET_4BTN_INL_MASK, + RT5668_RESET_4BTN_INL_NOR); + } +} + +/** + * rt5668_jack_detect - Detect headset. + * @codec: SoC audio codec device. + * @jack_insert: Jack insert or not. + * + * Detect whether is headset or not when jack inserted. + * + * Returns detect status. + */ + +static int rt5668_jack_detect(struct snd_soc_codec *codec, int jack_insert) +{ + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + struct rt5663_priv *rt5668 = snd_soc_codec_get_drvdata(codec); + int val, i = 0, sleep_time[5] = {300, 150, 100, 50, 30}; + + dev_dbg(codec->dev, "%s jack_insert:%d\n", __func__, jack_insert); + if (jack_insert) { + snd_soc_write(codec, RT5668_CBJ_TYPE_2, 0x8040); + snd_soc_write(codec, RT5668_CBJ_TYPE_3, 0x1484); + + snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); + snd_soc_dapm_force_enable_pin(dapm, "MICBIAS2"); + snd_soc_dapm_force_enable_pin(dapm, "Mic Det Power"); + snd_soc_dapm_force_enable_pin(dapm, "CBJ Power"); + snd_soc_dapm_sync(dapm); + snd_soc_update_bits(codec, RT5663_RC_CLK, + RT5668_DIG_1M_CLK_MASK, RT5668_DIG_1M_CLK_EN); + snd_soc_update_bits(codec, RT5663_RECMIX, 0x8, 0x8); + + while (i < 5) { + msleep(sleep_time[i]); + val = snd_soc_read(codec, RT5668_CBJ_TYPE_2) & 0x0003; + if (val == 0x1 || val == 0x2 || val == 0x3) + break; + dev_dbg(codec->dev, "%s: MX-0011 val=%x sleep %d\n", + __func__, val, sleep_time[i]); + i++; + } + dev_dbg(codec->dev, "%s val = %d\n", __func__, val); + switch (val) { + case 1: + case 2: + rt5668->jack_type = SND_JACK_HEADSET; + rt5663_enable_push_button_irq(codec, true); + break; + default: + snd_soc_dapm_disable_pin(dapm, "MICBIAS1"); + snd_soc_dapm_disable_pin(dapm, "MICBIAS2"); + snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); + snd_soc_dapm_disable_pin(dapm, "CBJ Power"); + snd_soc_dapm_sync(dapm); + rt5668->jack_type = SND_JACK_HEADPHONE; + break; + } + } else { + snd_soc_update_bits(codec, RT5663_RECMIX, 0x8, 0x0); + + if (rt5668->jack_type == SND_JACK_HEADSET) { + rt5663_enable_push_button_irq(codec, false); + snd_soc_dapm_disable_pin(dapm, "MICBIAS1"); + snd_soc_dapm_disable_pin(dapm, "MICBIAS2"); + snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); + snd_soc_dapm_disable_pin(dapm, "CBJ Power"); + snd_soc_dapm_sync(dapm); + } + rt5668->jack_type = 0; + } + + dev_dbg(codec->dev, "jack_type = %d\n", rt5668->jack_type); + return rt5668->jack_type; +} + +/** + * rt5663_jack_detect - Detect headset. + * @codec: SoC audio codec device. + * @jack_insert: Jack insert or not. + * + * Detect whether is headset or not when jack inserted. + * + * Returns detect status. + */ +static int rt5663_jack_detect(struct snd_soc_codec *codec, int jack_insert) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + int val, i = 0, sleep_time[5] = {300, 150, 100, 50, 30}; + + dev_dbg(codec->dev, "%s jack_insert:%d\n", __func__, jack_insert); + + if (jack_insert) { + snd_soc_update_bits(codec, RT5663_DIG_MISC, + RT5668_DIG_GATE_CTRL_MASK, RT5668_DIG_GATE_CTRL_EN); + snd_soc_update_bits(codec, RT5663_HP_CHARGE_PUMP_1, + RT5663_SI_HP_MASK | RT5668_OSW_HP_L_MASK | + RT5668_OSW_HP_R_MASK, RT5663_SI_HP_EN | + RT5668_OSW_HP_L_DIS | RT5668_OSW_HP_R_DIS); + snd_soc_update_bits(codec, RT5663_DUMMY_1, + RT5663_EMB_CLK_MASK | RT5663_HPA_CPL_BIAS_MASK | + RT5663_HPA_CPR_BIAS_MASK, RT5663_EMB_CLK_EN | + RT5663_HPA_CPL_BIAS_1 | RT5663_HPA_CPR_BIAS_1); + snd_soc_update_bits(codec, RT5663_CBJ_1, + RT5663_INBUF_CBJ_BST1_MASK | RT5663_CBJ_SENSE_BST1_MASK, + RT5663_INBUF_CBJ_BST1_ON | RT5663_CBJ_SENSE_BST1_L); + snd_soc_update_bits(codec, RT5663_IL_CMD_2, + RT5663_PWR_MIC_DET_MASK, RT5663_PWR_MIC_DET_ON); + /* BST1 power on for JD */ + snd_soc_update_bits(codec, RT5663_PWR_ANLG_2, + RT5668_PWR_BST1_MASK, RT5668_PWR_BST1_ON); + snd_soc_update_bits(codec, RT5663_EM_JACK_TYPE_1, + RT5663_CBJ_DET_MASK | RT5663_EXT_JD_MASK | + RT5663_POL_EXT_JD_MASK, RT5663_CBJ_DET_EN | + RT5663_EXT_JD_EN | RT5663_POL_EXT_JD_EN); + snd_soc_update_bits(codec, RT5663_PWR_ANLG_1, + RT5668_PWR_MB_MASK | RT5668_LDO1_DVO_MASK | + RT5668_AMP_HP_MASK, RT5668_PWR_MB | + RT5668_LDO1_DVO_0_9V | RT5668_AMP_HP_3X); + snd_soc_update_bits(codec, RT5663_AUTO_1MRC_CLK, + RT5668_IRQ_POW_SAV_MASK, RT5668_IRQ_POW_SAV_EN); + snd_soc_update_bits(codec, RT5663_IRQ_1, + RT5663_EN_IRQ_JD1_MASK, RT5663_EN_IRQ_JD1_EN); + while (i < 5) { + msleep(sleep_time[i]); + val = snd_soc_read(codec, RT5663_EM_JACK_TYPE_2) & + 0x0003; + i++; + if (val == 0x1 || val == 0x2 || val == 0x3) + break; + dev_dbg(codec->dev, "%s: MX-00e7 val=%x sleep %d\n", + __func__, val, sleep_time[i]); + } + dev_dbg(codec->dev, "%s val = %d\n", __func__, val); + switch (val) { + case 1: + case 2: + rt5663->jack_type = SND_JACK_HEADSET; + rt5663_enable_push_button_irq(codec, true); + break; + default: + rt5663->jack_type = SND_JACK_HEADPHONE; + break; + } + } else { + if (rt5663->jack_type == SND_JACK_HEADSET) + rt5663_enable_push_button_irq(codec, false); + rt5663->jack_type = 0; + } + + dev_dbg(codec->dev, "jack_type = %d\n", rt5663->jack_type); + return rt5663->jack_type; +} + +static int rt5663_button_detect(struct snd_soc_codec *codec) +{ + int btn_type, val; + + val = snd_soc_read(codec, RT5663_IL_CMD_5); + dev_dbg(codec->dev, "%s: val=0x%x\n", __func__, val); + btn_type = val & 0xfff0; + snd_soc_write(codec, RT5663_IL_CMD_5, val); + + return btn_type; +} + +static irqreturn_t rt5663_irq(int irq, void *data) +{ + struct rt5663_priv *rt5663 = data; + + dev_dbg(rt5663->codec->dev, "%s IRQ queue work\n", __func__); + + queue_delayed_work(system_wq, &rt5663->jack_detect_work, + msecs_to_jiffies(250)); + + return IRQ_HANDLED; +} + +int rt5663_set_jack_detect(struct snd_soc_codec *codec, + struct snd_soc_jack *hs_jack) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + rt5663->hs_jack = hs_jack; + + rt5663_irq(0, rt5663); + + return 0; +} +EXPORT_SYMBOL_GPL(rt5663_set_jack_detect); + +static bool rt5663_check_jd_status(struct snd_soc_codec *codec) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + int val = snd_soc_read(codec, RT5663_INT_ST_1); + + dev_dbg(codec->dev, "%s val=%x\n", __func__, val); + + /* JD1 */ + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + return !(val & 0x2000); + case CODEC_TYPE_RT5663: + return !(val & 0x1000); + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + + return false; +} + +static void rt5663_jack_detect_work(struct work_struct *work) +{ + struct rt5663_priv *rt5663 = + container_of(work, struct rt5663_priv, jack_detect_work.work); + struct snd_soc_codec *codec = rt5663->codec; + int btn_type, report = 0; + + if (!codec) + return; + + if (rt5663_check_jd_status(codec)) { + /* jack in */ + if (rt5663->jack_type == 0) { + /* jack was out, report jack type */ + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + report = rt5668_jack_detect(rt5663->codec, 1); + break; + case CODEC_TYPE_RT5663: + report = rt5663_jack_detect(rt5663->codec, 1); + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + } else { + /* jack is already in, report button event */ + report = SND_JACK_HEADSET; + btn_type = rt5663_button_detect(rt5663->codec); + /** + * rt5663 can report three kinds of button behavior, + * one click, double click and hold. However, + * currently we will report button pressed/released + * event. So all the three button behaviors are + * treated as button pressed. + */ + switch (btn_type) { + case 0x8000: + case 0x4000: + case 0x2000: + report |= SND_JACK_BTN_0; + break; + case 0x1000: + case 0x0800: + case 0x0400: + report |= SND_JACK_BTN_1; + break; + case 0x0200: + case 0x0100: + case 0x0080: + report |= SND_JACK_BTN_2; + break; + case 0x0040: + case 0x0020: + case 0x0010: + report |= SND_JACK_BTN_3; + break; + case 0x0000: /* unpressed */ + break; + default: + btn_type = 0; + dev_err(rt5663->codec->dev, + "Unexpected button code 0x%04x\n", + btn_type); + break; + } + /* button release or spurious interrput*/ + if (btn_type == 0) + report = rt5663->jack_type; + } + } else { + /* jack out */ + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + report = rt5668_jack_detect(rt5663->codec, 0); + break; + case CODEC_TYPE_RT5663: + report = rt5663_jack_detect(rt5663->codec, 0); + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + } + dev_dbg(codec->dev, "%s jack report: 0x%04x\n", __func__, report); + snd_soc_jack_report(rt5663->hs_jack, report, SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); +} + +static const struct snd_kcontrol_new rt5663_snd_controls[] = { + /* DAC Digital Volume */ + SOC_DOUBLE_TLV("DAC Playback Volume", RT5663_STO1_DAC_DIG_VOL, + RT5668_DAC_L1_VOL_SHIFT + 1, RT5668_DAC_R1_VOL_SHIFT + 1, + 87, 0, dac_vol_tlv), + /* ADC Digital Volume Control */ + SOC_DOUBLE("ADC Capture Switch", RT5663_STO1_ADC_DIG_VOL, + RT5668_ADC_L_MUTE_SHIFT, RT5668_ADC_R_MUTE_SHIFT, 1, 1), + SOC_DOUBLE_TLV("ADC Capture Volume", RT5663_STO1_ADC_DIG_VOL, + RT5668_ADC_L_VOL_SHIFT + 1, RT5668_ADC_R_VOL_SHIFT + 1, + 63, 0, adc_vol_tlv), +}; + +static const struct snd_kcontrol_new rt5668_specific_controls[] = { + /* Headphone Output Volume */ + SOC_DOUBLE_R_TLV("Headphone Playback Volume", RT5663_HP_LCH_DRE, + RT5663_HP_RCH_DRE, RT5668_GAIN_HP_SHIFT, 15, 1, + rt5668_hp_vol_tlv), + /* Mic Boost Volume */ + SOC_SINGLE_TLV("IN1 Capture Volume", RT5668_AEC_BST, + RT5668_GAIN_CBJ_SHIFT, 8, 0, in_bst_tlv), +}; + +static const struct snd_kcontrol_new rt5663_specific_controls[] = { + /* Headphone Output Volume */ + SOC_DOUBLE_R_TLV("Headphone Playback Volume", RT5663_STO_DRE_9, + RT5663_STO_DRE_10, RT5663_DRE_GAIN_HP_SHIFT, 23, 1, + rt5663_hp_vol_tlv), + /* Mic Boost Volume*/ + SOC_SINGLE_TLV("IN1 Capture Volume", RT5663_CBJ_2, + RT5663_GAIN_BST1_SHIFT, 8, 0, in_bst_tlv), + /* Data Swap for Slot0/1 in ADCDAT1 */ + SOC_ENUM("IF1 ADC Data Swap", rt5663_if1_adc_enum), +}; + +static int rt5663_is_sys_clk_from_pll(struct snd_soc_dapm_widget *w, + struct snd_soc_dapm_widget *sink) +{ + unsigned int val; + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + + val = snd_soc_read(codec, RT5663_GLB_CLK); + val &= RT5663_SCLK_SRC_MASK; + if (val == RT5663_SCLK_SRC_PLL1) + return 1; + else + return 0; +} + +static int rt5663_is_using_asrc(struct snd_soc_dapm_widget *w, + struct snd_soc_dapm_widget *sink) +{ + unsigned int reg, shift, val; + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + if (rt5663->codec_type == CODEC_TYPE_RT5668) { + switch (w->shift) { + case RT5668_ADC_STO1_ASRC_SHIFT: + reg = RT5668_ASRC_3; + shift = RT5668_AD_STO1_TRACK_SHIFT; + break; + case RT5668_DAC_STO1_ASRC_SHIFT: + reg = RT5663_ASRC_2; + shift = RT5668_DA_STO1_TRACK_SHIFT; + break; + default: + return 0; + } + } else { + switch (w->shift) { + case RT5663_ADC_STO1_ASRC_SHIFT: + reg = RT5663_ASRC_2; + shift = RT5663_AD_STO1_TRACK_SHIFT; + break; + case RT5663_DAC_STO1_ASRC_SHIFT: + reg = RT5663_ASRC_2; + shift = RT5663_DA_STO1_TRACK_SHIFT; + break; + default: + return 0; + } + } + + val = (snd_soc_read(codec, reg) >> shift) & 0x7; + + if (val) + return 1; + + return 0; +} + +static int rt5663_i2s_use_asrc(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + int da_asrc_en, ad_asrc_en; + + da_asrc_en = (snd_soc_read(codec, RT5663_ASRC_2) & + RT5663_DA_STO1_TRACK_MASK) ? 1 : 0; + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + ad_asrc_en = (snd_soc_read(codec, RT5668_ASRC_3) & + RT5668_AD_STO1_TRACK_MASK) ? 1 : 0; + break; + case CODEC_TYPE_RT5663: + ad_asrc_en = (snd_soc_read(codec, RT5663_ASRC_2) & + RT5663_AD_STO1_TRACK_MASK) ? 1 : 0; + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + return 1; + } + + if (da_asrc_en || ad_asrc_en) + if (rt5663->sysclk > rt5663->lrck * 384) + return 1; + + dev_err(codec->dev, "sysclk < 384 x fs, disable i2s asrc\n"); + + return 0; +} + +/** + * rt5663_sel_asrc_clk_src - select ASRC clock source for a set of filters + * @codec: SoC audio codec device. + * @filter_mask: mask of filters. + * @clk_src: clock source + * + * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5668 can + * only support standard 32fs or 64fs i2s format, ASRC should be enabled to + * support special i2s clock format such as Intel's 100fs(100 * sampling rate). + * ASRC function will track i2s clock and generate a corresponding system clock + * for codec. This function provides an API to select the clock source for a + * set of filters specified by the mask. And the codec driver will turn on ASRC + * for these filters if ASRC is selected as their clock source. + */ +int rt5663_sel_asrc_clk_src(struct snd_soc_codec *codec, + unsigned int filter_mask, unsigned int clk_src) +{ + struct rt5663_priv *rt5668 = snd_soc_codec_get_drvdata(codec); + unsigned int asrc2_mask = 0; + unsigned int asrc2_value = 0; + unsigned int asrc3_mask = 0; + unsigned int asrc3_value = 0; + + switch (clk_src) { + case RT5663_CLK_SEL_SYS: + case RT5663_CLK_SEL_I2S1_ASRC: + break; + + default: + return -EINVAL; + } + + if (filter_mask & RT5663_DA_STEREO_FILTER) { + asrc2_mask |= RT5668_DA_STO1_TRACK_MASK; + asrc2_value |= clk_src << RT5668_DA_STO1_TRACK_SHIFT; + } + + if (filter_mask & RT5663_AD_STEREO_FILTER) { + switch (rt5668->codec_type) { + case CODEC_TYPE_RT5668: + asrc3_mask |= RT5668_AD_STO1_TRACK_MASK; + asrc3_value |= clk_src << RT5668_AD_STO1_TRACK_SHIFT; + break; + case CODEC_TYPE_RT5663: + asrc2_mask |= RT5663_AD_STO1_TRACK_MASK; + asrc2_value |= clk_src << RT5663_AD_STO1_TRACK_SHIFT; + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + } + + if (asrc2_mask) + snd_soc_update_bits(codec, RT5663_ASRC_2, asrc2_mask, + asrc2_value); + + if (asrc3_mask) + snd_soc_update_bits(codec, RT5668_ASRC_3, asrc3_mask, + asrc3_value); + + return 0; +} +EXPORT_SYMBOL_GPL(rt5663_sel_asrc_clk_src); + +/* Analog Mixer */ +static const struct snd_kcontrol_new rt5668_recmix1l[] = { + SOC_DAPM_SINGLE("BST2 Switch", RT5668_RECMIX1L, + RT5668_RECMIX1L_BST2_SHIFT, 1, 1), + SOC_DAPM_SINGLE("BST1 CBJ Switch", RT5668_RECMIX1L, + RT5668_RECMIX1L_BST1_CBJ_SHIFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5668_recmix1r[] = { + SOC_DAPM_SINGLE("BST2 Switch", RT5668_RECMIX1R, + RT5668_RECMIX1R_BST2_SHIFT, 1, 1), +}; + +/* Digital Mixer */ +static const struct snd_kcontrol_new rt5663_sto1_adc_l_mix[] = { + SOC_DAPM_SINGLE("ADC1 Switch", RT5663_STO1_ADC_MIXER, + RT5668_M_STO1_ADC_L1_SHIFT, 1, 1), + SOC_DAPM_SINGLE("ADC2 Switch", RT5663_STO1_ADC_MIXER, + RT5668_M_STO1_ADC_L2_SHIFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5668_sto1_adc_r_mix[] = { + SOC_DAPM_SINGLE("ADC1 Switch", RT5663_STO1_ADC_MIXER, + RT5668_M_STO1_ADC_R1_SHIFT, 1, 1), + SOC_DAPM_SINGLE("ADC2 Switch", RT5663_STO1_ADC_MIXER, + RT5668_M_STO1_ADC_R2_SHIFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5663_adda_l_mix[] = { + SOC_DAPM_SINGLE("ADC L Switch", RT5663_AD_DA_MIXER, + RT5668_M_ADCMIX_L_SHIFT, 1, 1), + SOC_DAPM_SINGLE("DAC L Switch", RT5663_AD_DA_MIXER, + RT5668_M_DAC1_L_SHIFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5663_adda_r_mix[] = { + SOC_DAPM_SINGLE("ADC R Switch", RT5663_AD_DA_MIXER, + RT5668_M_ADCMIX_R_SHIFT, 1, 1), + SOC_DAPM_SINGLE("DAC R Switch", RT5663_AD_DA_MIXER, + RT5668_M_DAC1_R_SHIFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5663_sto1_dac_l_mix[] = { + SOC_DAPM_SINGLE("DAC L Switch", RT5663_STO_DAC_MIXER, + RT5668_M_DAC_L1_STO_L_SHIFT, 1, 1), + SOC_DAPM_SINGLE("DAC R Switch", RT5663_STO_DAC_MIXER, + RT5668_M_DAC_R1_STO_L_SHIFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5663_sto1_dac_r_mix[] = { + SOC_DAPM_SINGLE("DAC L Switch", RT5663_STO_DAC_MIXER, + RT5668_M_DAC_L1_STO_R_SHIFT, 1, 1), + SOC_DAPM_SINGLE("DAC R Switch", RT5663_STO_DAC_MIXER, + RT5668_M_DAC_R1_STO_R_SHIFT, 1, 1), +}; + +/* Out Switch */ +static const struct snd_kcontrol_new rt5668_hpo_switch = + SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5668_HP_AMP_2, + RT5668_EN_DAC_HPO_SHIFT, 1, 0); + +/* Stereo ADC source */ +static const char * const rt5668_sto1_adc_src[] = { + "ADC L", "ADC R" +}; + +static SOC_ENUM_SINGLE_DECL(rt5668_sto1_adcl_enum, RT5663_STO1_ADC_MIXER, + RT5668_STO1_ADC_L_SRC_SHIFT, rt5668_sto1_adc_src); + +static const struct snd_kcontrol_new rt5668_sto1_adcl_mux = + SOC_DAPM_ENUM("STO1 ADC L Mux", rt5668_sto1_adcl_enum); + +static SOC_ENUM_SINGLE_DECL(rt5668_sto1_adcr_enum, RT5663_STO1_ADC_MIXER, + RT5668_STO1_ADC_R_SRC_SHIFT, rt5668_sto1_adc_src); + +static const struct snd_kcontrol_new rt5668_sto1_adcr_mux = + SOC_DAPM_ENUM("STO1 ADC R Mux", rt5668_sto1_adcr_enum); + +/* RT5663: Analog DACL1 input source */ +static const char * const rt5663_alg_dacl_src[] = { + "DAC L", "STO DAC MIXL" +}; + +static SOC_ENUM_SINGLE_DECL(rt5663_alg_dacl_enum, RT5663_BYPASS_STO_DAC, + RT5663_DACL1_SRC_SHIFT, rt5663_alg_dacl_src); + +static const struct snd_kcontrol_new rt5663_alg_dacl_mux = + SOC_DAPM_ENUM("DAC L Mux", rt5663_alg_dacl_enum); + +/* RT5663: Analog DACR1 input source */ +static const char * const rt5663_alg_dacr_src[] = { + "DAC R", "STO DAC MIXR" +}; + +static SOC_ENUM_SINGLE_DECL(rt5663_alg_dacr_enum, RT5663_BYPASS_STO_DAC, + RT5663_DACR1_SRC_SHIFT, rt5663_alg_dacr_src); + +static const struct snd_kcontrol_new rt5663_alg_dacr_mux = + SOC_DAPM_ENUM("DAC R Mux", rt5663_alg_dacr_enum); + +static int rt5663_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + if (rt5663->codec_type == CODEC_TYPE_RT5668) { + snd_soc_update_bits(codec, RT5663_HP_CHARGE_PUMP_1, + RT5668_SEL_PM_HP_SHIFT, RT5668_SEL_PM_HP_HIGH); + snd_soc_update_bits(codec, RT5663_HP_LOGIC_2, + RT5668_HP_SIG_SRC1_MASK, + RT5668_HP_SIG_SRC1_SILENCE); + } else { + snd_soc_write(codec, RT5663_DEPOP_2, 0x3003); + snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x000b, + 0x000b); + snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x0030, + 0x0030); + snd_soc_update_bits(codec, RT5663_HP_CHARGE_PUMP_1, + RT5668_OVCD_HP_MASK, RT5668_OVCD_HP_DIS); + snd_soc_write(codec, RT5663_HP_CHARGE_PUMP_2, 0x1371); + snd_soc_write(codec, RT5663_HP_BIAS, 0xabba); + snd_soc_write(codec, RT5663_CHARGE_PUMP_1, 0x2224); + snd_soc_write(codec, RT5663_ANA_BIAS_CUR_1, 0x7766); + snd_soc_write(codec, RT5663_HP_BIAS, 0xafaa); + snd_soc_write(codec, RT5663_CHARGE_PUMP_2, 0x7777); + snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x3000, + 0x3000); + } + break; + + case SND_SOC_DAPM_PRE_PMD: + if (rt5663->codec_type == CODEC_TYPE_RT5668) { + snd_soc_update_bits(codec, RT5663_HP_LOGIC_2, + RT5668_HP_SIG_SRC1_MASK, + RT5668_HP_SIG_SRC1_REG); + } else { + snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x3000, 0x0); + snd_soc_update_bits(codec, RT5663_HP_CHARGE_PUMP_1, + RT5668_OVCD_HP_MASK, RT5668_OVCD_HP_EN); + snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x0030, 0x0); + snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x000b, + 0x000b); + } + break; + + default: + return 0; + } + + return 0; +} + +static int rt5668_bst2_power(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, RT5663_PWR_ANLG_2, + RT5668_PWR_BST2_MASK | RT5668_PWR_BST2_OP_MASK, + RT5668_PWR_BST2 | RT5668_PWR_BST2_OP); + break; + + case SND_SOC_DAPM_PRE_PMD: + snd_soc_update_bits(codec, RT5663_PWR_ANLG_2, + RT5668_PWR_BST2_MASK | RT5668_PWR_BST2_OP_MASK, 0); + break; + + default: + return 0; + } + + return 0; +} + +static int rt5663_pre_div_power(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_write(codec, RT5663_PRE_DIV_GATING_1, 0xff00); + snd_soc_write(codec, RT5663_PRE_DIV_GATING_2, 0xfffc); + break; + + case SND_SOC_DAPM_PRE_PMD: + snd_soc_write(codec, RT5663_PRE_DIV_GATING_1, 0x0000); + snd_soc_write(codec, RT5663_PRE_DIV_GATING_2, 0x0000); + break; + + default: + return 0; + } + + return 0; +} + +static const struct snd_soc_dapm_widget rt5663_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("PLL", RT5663_PWR_ANLG_3, RT5668_PWR_PLL_SHIFT, 0, + NULL, 0), + + /* micbias */ + SND_SOC_DAPM_MICBIAS("MICBIAS1", RT5663_PWR_ANLG_2, + RT5668_PWR_MB1_SHIFT, 0), + SND_SOC_DAPM_MICBIAS("MICBIAS2", RT5663_PWR_ANLG_2, + RT5668_PWR_MB2_SHIFT, 0), + + /* Input Lines */ + SND_SOC_DAPM_INPUT("IN1P"), + SND_SOC_DAPM_INPUT("IN1N"), + + /* REC Mixer Power */ + SND_SOC_DAPM_SUPPLY("RECMIX1L Power", RT5663_PWR_ANLG_2, + RT5668_PWR_RECMIX1_SHIFT, 0, NULL, 0), + + /* ADCs */ + SND_SOC_DAPM_ADC("ADC L", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_SUPPLY("ADC L Power", RT5663_PWR_DIG_1, + RT5668_PWR_ADC_L1_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC Clock", RT5663_CHOP_ADC, + RT5668_CKGEN_ADCC_SHIFT, 0, NULL, 0), + + /* ADC Mixer */ + SND_SOC_DAPM_MIXER("STO1 ADC MIXL", SND_SOC_NOPM, + 0, 0, rt5663_sto1_adc_l_mix, + ARRAY_SIZE(rt5663_sto1_adc_l_mix)), + + /* ADC Filter Power */ + SND_SOC_DAPM_SUPPLY("STO1 ADC Filter", RT5663_PWR_DIG_2, + RT5668_PWR_ADC_S1F_SHIFT, 0, NULL, 0), + + /* Digital Interface */ + SND_SOC_DAPM_SUPPLY("I2S", RT5663_PWR_DIG_1, RT5668_PWR_I2S1_SHIFT, 0, + NULL, 0), + SND_SOC_DAPM_PGA("IF DAC", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("IF1 ADC1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("IF ADC", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* Audio Interface */ + SND_SOC_DAPM_AIF_IN("AIFRX", "AIF Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AIFTX", "AIF Capture", 0, SND_SOC_NOPM, 0, 0), + + /* DAC mixer before sound effect */ + SND_SOC_DAPM_MIXER("ADDA MIXL", SND_SOC_NOPM, 0, 0, rt5663_adda_l_mix, + ARRAY_SIZE(rt5663_adda_l_mix)), + SND_SOC_DAPM_MIXER("ADDA MIXR", SND_SOC_NOPM, 0, 0, rt5663_adda_r_mix, + ARRAY_SIZE(rt5663_adda_r_mix)), + SND_SOC_DAPM_PGA("DAC L1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DAC R1", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* DAC Mixer */ + SND_SOC_DAPM_SUPPLY("STO1 DAC Filter", RT5663_PWR_DIG_2, + RT5668_PWR_DAC_S1F_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_MIXER("STO1 DAC MIXL", SND_SOC_NOPM, 0, 0, + rt5663_sto1_dac_l_mix, ARRAY_SIZE(rt5663_sto1_dac_l_mix)), + SND_SOC_DAPM_MIXER("STO1 DAC MIXR", SND_SOC_NOPM, 0, 0, + rt5663_sto1_dac_r_mix, ARRAY_SIZE(rt5663_sto1_dac_r_mix)), + + /* DACs */ + SND_SOC_DAPM_SUPPLY("STO1 DAC L Power", RT5663_PWR_DIG_1, + RT5668_PWR_DAC_L1_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("STO1 DAC R Power", RT5663_PWR_DIG_1, + RT5668_PWR_DAC_R1_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_DAC("DAC L", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC R", NULL, SND_SOC_NOPM, 0, 0), + + /* Headphone*/ + SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, rt5663_hp_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + + /* Output Lines */ + SND_SOC_DAPM_OUTPUT("HPOL"), + SND_SOC_DAPM_OUTPUT("HPOR"), +}; + +static const struct snd_soc_dapm_widget rt5668_specific_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("LDO2", RT5663_PWR_ANLG_3, + RT5668_PWR_LDO2_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5668_PWR_VOL, + RT5668_PWR_MIC_DET_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("LDO DAC", RT5663_PWR_DIG_1, + RT5668_PWR_LDO_DACREF_SHIFT, 0, NULL, 0), + + /* ASRC */ + SND_SOC_DAPM_SUPPLY("I2S ASRC", RT5663_ASRC_1, + RT5668_I2S1_ASRC_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC ASRC", RT5663_ASRC_1, + RT5668_DAC_STO1_ASRC_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC ASRC", RT5663_ASRC_1, + RT5668_ADC_STO1_ASRC_SHIFT, 0, NULL, 0), + + /* Input Lines */ + SND_SOC_DAPM_INPUT("IN2P"), + SND_SOC_DAPM_INPUT("IN2N"), + + /* Boost */ + SND_SOC_DAPM_PGA("BST1 CBJ", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("CBJ Power", RT5663_PWR_ANLG_3, + RT5668_PWR_CBJ_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("BST2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("BST2 Power", SND_SOC_NOPM, 0, 0, + rt5668_bst2_power, SND_SOC_DAPM_PRE_PMD | + SND_SOC_DAPM_POST_PMU), + + /* REC Mixer */ + SND_SOC_DAPM_MIXER("RECMIX1L", SND_SOC_NOPM, 0, 0, rt5668_recmix1l, + ARRAY_SIZE(rt5668_recmix1l)), + SND_SOC_DAPM_MIXER("RECMIX1R", SND_SOC_NOPM, 0, 0, rt5668_recmix1r, + ARRAY_SIZE(rt5668_recmix1r)), + SND_SOC_DAPM_SUPPLY("RECMIX1R Power", RT5663_PWR_ANLG_2, + RT5668_PWR_RECMIX2_SHIFT, 0, NULL, 0), + + /* ADC */ + SND_SOC_DAPM_ADC("ADC R", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_SUPPLY("ADC R Power", RT5663_PWR_DIG_1, + RT5668_PWR_ADC_R1_SHIFT, 0, NULL, 0), + + /* ADC Mux */ + SND_SOC_DAPM_PGA("STO1 ADC L1", RT5663_STO1_ADC_MIXER, + RT5668_STO1_ADC_L1_SRC_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("STO1 ADC R1", RT5663_STO1_ADC_MIXER, + RT5668_STO1_ADC_R1_SRC_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("STO1 ADC L2", RT5663_STO1_ADC_MIXER, + RT5668_STO1_ADC_L2_SRC_SHIFT, 1, NULL, 0), + SND_SOC_DAPM_PGA("STO1 ADC R2", RT5663_STO1_ADC_MIXER, + RT5668_STO1_ADC_R2_SRC_SHIFT, 1, NULL, 0), + + SND_SOC_DAPM_MUX("STO1 ADC L Mux", SND_SOC_NOPM, 0, 0, + &rt5668_sto1_adcl_mux), + SND_SOC_DAPM_MUX("STO1 ADC R Mux", SND_SOC_NOPM, 0, 0, + &rt5668_sto1_adcr_mux), + + /* ADC Mix */ + SND_SOC_DAPM_MIXER("STO1 ADC MIXR", SND_SOC_NOPM, 0, 0, + rt5668_sto1_adc_r_mix, ARRAY_SIZE(rt5668_sto1_adc_r_mix)), + + /* Analog DAC Clock */ + SND_SOC_DAPM_SUPPLY("DAC Clock", RT5663_CHOP_DAC_L, + RT5668_CKGEN_DAC1_SHIFT, 0, NULL, 0), + + /* Headphone out */ + SND_SOC_DAPM_SWITCH("HPO Playback", SND_SOC_NOPM, 0, 0, + &rt5668_hpo_switch), +}; + +static const struct snd_soc_dapm_widget rt5663_specific_dapm_widgets[] = { + /* System Clock Pre Divider Gating */ + SND_SOC_DAPM_SUPPLY("Pre Div Power", SND_SOC_NOPM, 0, 0, + rt5663_pre_div_power, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), + + /* LDO */ + SND_SOC_DAPM_SUPPLY("LDO ADC", RT5663_PWR_DIG_1, + RT5668_PWR_LDO_DACREF_SHIFT, 0, NULL, 0), + + /* ASRC */ + SND_SOC_DAPM_SUPPLY("I2S ASRC", RT5663_ASRC_1, + RT5663_I2S1_ASRC_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC ASRC", RT5663_ASRC_1, + RT5663_DAC_STO1_ASRC_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC ASRC", RT5663_ASRC_1, + RT5663_ADC_STO1_ASRC_SHIFT, 0, NULL, 0), + + /* Boost */ + SND_SOC_DAPM_PGA("BST1", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* STO ADC */ + SND_SOC_DAPM_PGA("STO1 ADC L1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("STO1 ADC L2", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* Analog DAC source */ + SND_SOC_DAPM_MUX("DAC L Mux", SND_SOC_NOPM, 0, 0, &rt5663_alg_dacl_mux), + SND_SOC_DAPM_MUX("DAC R Mux", SND_SOC_NOPM, 0, 0, &rt5663_alg_dacr_mux), +}; + +static const struct snd_soc_dapm_route rt5663_dapm_routes[] = { + /* PLL */ + { "I2S", NULL, "PLL", rt5663_is_sys_clk_from_pll }, + + /* ASRC */ + { "STO1 ADC Filter", NULL, "ADC ASRC", rt5663_is_using_asrc }, + { "STO1 DAC Filter", NULL, "DAC ASRC", rt5663_is_using_asrc }, + { "I2S", NULL, "I2S ASRC", rt5663_i2s_use_asrc }, + + { "ADC L", NULL, "ADC L Power" }, + { "ADC L", NULL, "ADC Clock" }, + + { "STO1 ADC L2", NULL, "STO1 DAC MIXL" }, + + { "STO1 ADC MIXL", "ADC1 Switch", "STO1 ADC L1" }, + { "STO1 ADC MIXL", "ADC2 Switch", "STO1 ADC L2" }, + { "STO1 ADC MIXL", NULL, "STO1 ADC Filter" }, + + { "IF1 ADC1", NULL, "STO1 ADC MIXL" }, + { "IF ADC", NULL, "IF1 ADC1" }, + { "AIFTX", NULL, "IF ADC" }, + { "AIFTX", NULL, "I2S" }, + + { "AIFRX", NULL, "I2S" }, + { "IF DAC", NULL, "AIFRX" }, + { "IF1 DAC1 L", NULL, "IF DAC" }, + { "IF1 DAC1 R", NULL, "IF DAC" }, + + { "ADDA MIXL", "ADC L Switch", "STO1 ADC MIXL" }, + { "ADDA MIXL", "DAC L Switch", "IF1 DAC1 L" }, + { "ADDA MIXL", NULL, "STO1 DAC Filter" }, + { "ADDA MIXL", NULL, "STO1 DAC L Power" }, + { "ADDA MIXR", "DAC R Switch", "IF1 DAC1 R" }, + { "ADDA MIXR", NULL, "STO1 DAC Filter" }, + { "ADDA MIXR", NULL, "STO1 DAC R Power" }, + + { "DAC L1", NULL, "ADDA MIXL" }, + { "DAC R1", NULL, "ADDA MIXR" }, + + { "STO1 DAC MIXL", "DAC L Switch", "DAC L1" }, + { "STO1 DAC MIXL", "DAC R Switch", "DAC R1" }, + { "STO1 DAC MIXL", NULL, "STO1 DAC L Power" }, + { "STO1 DAC MIXL", NULL, "STO1 DAC Filter" }, + { "STO1 DAC MIXR", "DAC R Switch", "DAC R1" }, + { "STO1 DAC MIXR", "DAC L Switch", "DAC L1" }, + { "STO1 DAC MIXR", NULL, "STO1 DAC R Power" }, + { "STO1 DAC MIXR", NULL, "STO1 DAC Filter" }, + + { "HP Amp", NULL, "DAC L" }, + { "HP Amp", NULL, "DAC R" }, +}; + +static const struct snd_soc_dapm_route rt5668_specific_dapm_routes[] = { + { "MICBIAS1", NULL, "LDO2" }, + { "MICBIAS2", NULL, "LDO2" }, + + { "BST1 CBJ", NULL, "IN1P" }, + { "BST1 CBJ", NULL, "IN1N" }, + { "BST1 CBJ", NULL, "CBJ Power" }, + + { "BST2", NULL, "IN2P" }, + { "BST2", NULL, "IN2N" }, + { "BST2", NULL, "BST2 Power" }, + + { "RECMIX1L", "BST2 Switch", "BST2" }, + { "RECMIX1L", "BST1 CBJ Switch", "BST1 CBJ" }, + { "RECMIX1L", NULL, "RECMIX1L Power" }, + { "RECMIX1R", "BST2 Switch", "BST2" }, + { "RECMIX1R", NULL, "RECMIX1R Power" }, + + { "ADC L", NULL, "RECMIX1L" }, + { "ADC R", NULL, "RECMIX1R" }, + { "ADC R", NULL, "ADC R Power" }, + { "ADC R", NULL, "ADC Clock" }, + + { "STO1 ADC L Mux", "ADC L", "ADC L" }, + { "STO1 ADC L Mux", "ADC R", "ADC R" }, + { "STO1 ADC L1", NULL, "STO1 ADC L Mux" }, + + { "STO1 ADC R Mux", "ADC L", "ADC L" }, + { "STO1 ADC R Mux", "ADC R", "ADC R" }, + { "STO1 ADC R1", NULL, "STO1 ADC R Mux" }, + { "STO1 ADC R2", NULL, "STO1 DAC MIXR" }, + + { "STO1 ADC MIXR", "ADC1 Switch", "STO1 ADC R1" }, + { "STO1 ADC MIXR", "ADC2 Switch", "STO1 ADC R2" }, + { "STO1 ADC MIXR", NULL, "STO1 ADC Filter" }, + + { "IF1 ADC1", NULL, "STO1 ADC MIXR" }, + + { "ADDA MIXR", "ADC R Switch", "STO1 ADC MIXR" }, + + { "DAC L", NULL, "STO1 DAC MIXL" }, + { "DAC L", NULL, "LDO DAC" }, + { "DAC L", NULL, "DAC Clock" }, + { "DAC R", NULL, "STO1 DAC MIXR" }, + { "DAC R", NULL, "LDO DAC" }, + { "DAC R", NULL, "DAC Clock" }, + + { "HPO Playback", "Switch", "HP Amp" }, + { "HPOL", NULL, "HPO Playback" }, + { "HPOR", NULL, "HPO Playback" }, +}; + +static const struct snd_soc_dapm_route rt5663_specific_dapm_routes[] = { + { "I2S", NULL, "Pre Div Power" }, + + { "BST1", NULL, "IN1P" }, + { "BST1", NULL, "IN1N" }, + { "BST1", NULL, "RECMIX1L Power" }, + + { "ADC L", NULL, "BST1" }, + + { "STO1 ADC L1", NULL, "ADC L" }, + + { "DAC L Mux", "DAC L", "DAC L1" }, + { "DAC L Mux", "STO DAC MIXL", "STO1 DAC MIXL" }, + { "DAC R Mux", "DAC R", "DAC R1"}, + { "DAC R Mux", "STO DAC MIXR", "STO1 DAC MIXR" }, + + { "DAC L", NULL, "DAC L Mux" }, + { "DAC R", NULL, "DAC R Mux" }, + + { "HPOL", NULL, "HP Amp" }, + { "HPOR", NULL, "HP Amp" }, +}; + +static int rt5663_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 rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + unsigned int val_len = 0; + int pre_div; + + rt5663->lrck = params_rate(params); + + dev_dbg(dai->dev, "bclk is %dHz and sysclk is %dHz\n", + rt5663->lrck, rt5663->sysclk); + + pre_div = rl6231_get_clk_info(rt5663->sysclk, rt5663->lrck); + if (pre_div < 0) { + dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n", + rt5663->lrck, dai->id); + return -EINVAL; + } + + dev_dbg(dai->dev, "pre_div is %d for iis %d\n", pre_div, dai->id); + + switch (params_width(params)) { + case 8: + val_len = RT5668_I2S_DL_8; + break; + case 16: + val_len = RT5668_I2S_DL_16; + break; + case 20: + val_len = RT5668_I2S_DL_20; + break; + case 24: + val_len = RT5668_I2S_DL_24; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, RT5663_I2S1_SDP, + RT5668_I2S_DL_MASK, val_len); + + snd_soc_update_bits(codec, RT5663_ADDA_CLK_1, + RT5668_I2S_PD1_MASK, pre_div << RT5668_I2S_PD1_SHIFT); + + return 0; +} + +static int rt5663_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_codec *codec = dai->codec; + unsigned int reg_val = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + break; + case SND_SOC_DAIFMT_CBS_CFS: + reg_val |= RT5668_I2S_MS_S; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + reg_val |= RT5668_I2S_BP_INV; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + case SND_SOC_DAIFMT_LEFT_J: + reg_val |= RT5668_I2S_DF_LEFT; + break; + case SND_SOC_DAIFMT_DSP_A: + reg_val |= RT5668_I2S_DF_PCM_A; + break; + case SND_SOC_DAIFMT_DSP_B: + reg_val |= RT5668_I2S_DF_PCM_B; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, RT5663_I2S1_SDP, RT5668_I2S_MS_MASK | + RT5668_I2S_BP_MASK | RT5668_I2S_DF_MASK, reg_val); + + return 0; +} + +static int rt5663_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + unsigned int reg_val = 0; + + if (freq == rt5663->sysclk && clk_id == rt5663->sysclk_src) + return 0; + + switch (clk_id) { + case RT5663_SCLK_S_MCLK: + reg_val |= RT5663_SCLK_SRC_MCLK; + break; + case RT5663_SCLK_S_PLL1: + reg_val |= RT5663_SCLK_SRC_PLL1; + break; + case RT5663_SCLK_S_RCCLK: + reg_val |= RT5663_SCLK_SRC_RCCLK; + break; + default: + dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); + return -EINVAL; + } + snd_soc_update_bits(codec, RT5663_GLB_CLK, RT5668_SCLK_SRC_MASK, + reg_val); + rt5663->sysclk = freq; + rt5663->sysclk_src = clk_id; + + dev_dbg(codec->dev, "Sysclk is %dHz and clock id is %d\n", + freq, clk_id); + + return 0; +} + +static int rt5663_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 rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + struct rl6231_pll_code pll_code; + int ret; + int mask, shift, val; + + if (source == rt5663->pll_src && freq_in == rt5663->pll_in && + freq_out == rt5663->pll_out) + return 0; + + if (!freq_in || !freq_out) { + dev_dbg(codec->dev, "PLL disabled\n"); + + rt5663->pll_in = 0; + rt5663->pll_out = 0; + snd_soc_update_bits(codec, RT5663_GLB_CLK, + RT5663_SCLK_SRC_MASK, RT5663_SCLK_SRC_MCLK); + return 0; + } + + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + mask = RT5668_PLL1_SRC_MASK; + shift = RT5668_PLL1_SRC_SHIFT; + break; + case CODEC_TYPE_RT5663: + mask = RT5663_PLL1_SRC_MASK; + shift = RT5663_PLL1_SRC_SHIFT; + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + return -EINVAL; + } + + switch (source) { + case RT5663_PLL1_S_MCLK: + val = 0x0; + break; + case RT5663_PLL1_S_BCLK1: + val = 0x1; + break; + default: + dev_err(codec->dev, "Unknown PLL source %d\n", source); + return -EINVAL; + } + snd_soc_update_bits(codec, RT5663_GLB_CLK, mask, (val << shift)); + + ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); + if (ret < 0) { + dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); + return ret; + } + + dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n", pll_code.m_bp, + (pll_code.m_bp ? 0 : pll_code.m_code), pll_code.n_code, + pll_code.k_code); + + snd_soc_write(codec, RT5663_PLL_1, + pll_code.n_code << RT5668_PLL_N_SHIFT | pll_code.k_code); + snd_soc_write(codec, RT5663_PLL_2, + (pll_code.m_bp ? 0 : pll_code.m_code) << RT5668_PLL_M_SHIFT | + pll_code.m_bp << RT5668_PLL_M_BP_SHIFT); + + rt5663->pll_in = freq_in; + rt5663->pll_out = freq_out; + rt5663->pll_src = source; + + return 0; +} + +static int rt5663_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; + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + unsigned int val = 0, reg; + + if (rx_mask || tx_mask) + val |= RT5668_TDM_MODE_TDM; + + switch (slots) { + case 4: + val |= RT5668_TDM_IN_CH_4; + val |= RT5668_TDM_OUT_CH_4; + break; + case 6: + val |= RT5668_TDM_IN_CH_6; + val |= RT5668_TDM_OUT_CH_6; + break; + case 8: + val |= RT5668_TDM_IN_CH_8; + val |= RT5668_TDM_OUT_CH_8; + break; + case 2: + break; + default: + return -EINVAL; + } + + switch (slot_width) { + case 20: + val |= RT5668_TDM_IN_LEN_20; + val |= RT5668_TDM_OUT_LEN_20; + break; + case 24: + val |= RT5668_TDM_IN_LEN_24; + val |= RT5668_TDM_OUT_LEN_24; + break; + case 32: + val |= RT5668_TDM_IN_LEN_32; + val |= RT5668_TDM_OUT_LEN_32; + break; + case 16: + break; + default: + return -EINVAL; + } + + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + reg = RT5663_TDM_2; + break; + case CODEC_TYPE_RT5663: + reg = RT5663_TDM_1; + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + return -EINVAL; + } + + snd_soc_update_bits(codec, reg, RT5668_TDM_MODE_MASK | + RT5668_TDM_IN_CH_MASK | RT5668_TDM_OUT_CH_MASK | + RT5668_TDM_IN_LEN_MASK | RT5668_TDM_OUT_LEN_MASK, val); + + return 0; +} + +static int rt5663_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + unsigned int reg; + + dev_dbg(codec->dev, "%s ratio = %d\n", __func__, ratio); + + if (rt5663->codec_type == CODEC_TYPE_RT5668) + reg = RT5668_TDM_8; + else + reg = RT5663_TDM_5; + + switch (ratio) { + case 32: + snd_soc_update_bits(codec, reg, + RT5663_TDM_LENGTN_MASK, + RT5663_TDM_LENGTN_16); + break; + case 40: + snd_soc_update_bits(codec, reg, + RT5663_TDM_LENGTN_MASK, + RT5663_TDM_LENGTN_20); + break; + case 48: + snd_soc_update_bits(codec, reg, + RT5663_TDM_LENGTN_MASK, + RT5663_TDM_LENGTN_24); + break; + case 64: + snd_soc_update_bits(codec, reg, + RT5663_TDM_LENGTN_MASK, + RT5663_TDM_LENGTN_32); + break; + default: + dev_err(codec->dev, "Invalid ratio!\n"); + return -EINVAL; + } + + return 0; +} + +static int rt5663_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + switch (level) { + case SND_SOC_BIAS_ON: + snd_soc_update_bits(codec, RT5663_PWR_ANLG_1, + RT5668_PWR_FV1_MASK | RT5668_PWR_FV2_MASK, + RT5668_PWR_FV1 | RT5668_PWR_FV2); + break; + + case SND_SOC_BIAS_PREPARE: + if (rt5663->codec_type == CODEC_TYPE_RT5668) { + snd_soc_update_bits(codec, RT5663_DIG_MISC, + RT5668_DIG_GATE_CTRL_MASK, + RT5668_DIG_GATE_CTRL_EN); + snd_soc_update_bits(codec, RT5663_SIG_CLK_DET, + RT5668_EN_ANA_CLK_DET_MASK | + RT5668_PWR_CLK_DET_MASK, + RT5668_EN_ANA_CLK_DET_AUTO | + RT5668_PWR_CLK_DET_EN); + } + break; + + case SND_SOC_BIAS_STANDBY: + if (rt5663->codec_type == CODEC_TYPE_RT5668) + snd_soc_update_bits(codec, RT5663_DIG_MISC, + RT5668_DIG_GATE_CTRL_MASK, + RT5668_DIG_GATE_CTRL_DIS); + snd_soc_update_bits(codec, RT5663_PWR_ANLG_1, + RT5668_PWR_VREF1_MASK | RT5668_PWR_VREF2_MASK | + RT5668_PWR_FV1_MASK | RT5668_PWR_FV2_MASK | + RT5668_PWR_MB_MASK, RT5668_PWR_VREF1 | + RT5668_PWR_VREF2 | RT5668_PWR_MB); + usleep_range(10000, 10005); + if (rt5663->codec_type == CODEC_TYPE_RT5668) { + snd_soc_update_bits(codec, RT5663_SIG_CLK_DET, + RT5668_EN_ANA_CLK_DET_MASK | + RT5668_PWR_CLK_DET_MASK, + RT5668_EN_ANA_CLK_DET_DIS | + RT5668_PWR_CLK_DET_DIS); + } + break; + + case SND_SOC_BIAS_OFF: + snd_soc_update_bits(codec, RT5663_PWR_ANLG_1, + RT5668_PWR_VREF1_MASK | RT5668_PWR_VREF2_MASK | + RT5668_PWR_FV1 | RT5668_PWR_FV2, 0x0); + break; + + default: + break; + } + + return 0; +} + +static int rt5663_probe(struct snd_soc_codec *codec) +{ + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + rt5663->codec = codec; + + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + snd_soc_dapm_new_controls(dapm, + rt5668_specific_dapm_widgets, + ARRAY_SIZE(rt5668_specific_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, + rt5668_specific_dapm_routes, + ARRAY_SIZE(rt5668_specific_dapm_routes)); + snd_soc_add_codec_controls(codec, rt5668_specific_controls, + ARRAY_SIZE(rt5668_specific_controls)); + break; + case CODEC_TYPE_RT5663: + snd_soc_dapm_new_controls(dapm, + rt5663_specific_dapm_widgets, + ARRAY_SIZE(rt5663_specific_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, + rt5663_specific_dapm_routes, + ARRAY_SIZE(rt5663_specific_dapm_routes)); + snd_soc_add_codec_controls(codec, rt5663_specific_controls, + ARRAY_SIZE(rt5663_specific_controls)); + break; + } + + return 0; +} + +static int rt5663_remove(struct snd_soc_codec *codec) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + regmap_write(rt5663->regmap, RT5663_RESET, 0); + + return 0; +} + +#ifdef CONFIG_PM +static int rt5663_suspend(struct snd_soc_codec *codec) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + regcache_cache_only(rt5663->regmap, true); + regcache_mark_dirty(rt5663->regmap); + + return 0; +} + +static int rt5663_resume(struct snd_soc_codec *codec) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + regcache_cache_only(rt5663->regmap, false); + regcache_sync(rt5663->regmap); + + return 0; +} +#else +#define rt5663_suspend NULL +#define rt5663_resume NULL +#endif + +#define RT5663_STEREO_RATES SNDRV_PCM_RATE_8000_192000 +#define RT5663_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) + +static struct snd_soc_dai_ops rt5663_aif_dai_ops = { + .hw_params = rt5663_hw_params, + .set_fmt = rt5663_set_dai_fmt, + .set_sysclk = rt5663_set_dai_sysclk, + .set_pll = rt5663_set_dai_pll, + .set_tdm_slot = rt5663_set_tdm_slot, + .set_bclk_ratio = rt5663_set_bclk_ratio, +}; + +static struct snd_soc_dai_driver rt5663_dai[] = { + { + .name = "rt5663-aif", + .id = RT5663_AIF, + .playback = { + .stream_name = "AIF Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT5663_STEREO_RATES, + .formats = RT5663_FORMATS, + }, + .capture = { + .stream_name = "AIF Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT5663_STEREO_RATES, + .formats = RT5663_FORMATS, + }, + .ops = &rt5663_aif_dai_ops, + }, +}; + +static struct snd_soc_codec_driver soc_codec_dev_rt5663 = { + .probe = rt5663_probe, + .remove = rt5663_remove, + .suspend = rt5663_suspend, + .resume = rt5663_resume, + .set_bias_level = rt5663_set_bias_level, + .idle_bias_off = true, + .component_driver = { + .controls = rt5663_snd_controls, + .num_controls = ARRAY_SIZE(rt5663_snd_controls), + .dapm_widgets = rt5663_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5663_dapm_widgets), + .dapm_routes = rt5663_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5663_dapm_routes), + } +}; + +static const struct regmap_config rt5668_regmap = { + .reg_bits = 16, + .val_bits = 16, + .use_single_rw = true, + .max_register = 0x07fa, + .volatile_reg = rt5668_volatile_register, + .readable_reg = rt5668_readable_register, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt5668_reg, + .num_reg_defaults = ARRAY_SIZE(rt5668_reg), +}; + +static const struct regmap_config rt5663_regmap = { + .reg_bits = 16, + .val_bits = 16, + .use_single_rw = true, + .max_register = 0x03f3, + .volatile_reg = rt5663_volatile_register, + .readable_reg = rt5663_readable_register, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt5663_reg, + .num_reg_defaults = ARRAY_SIZE(rt5663_reg), +}; + +static const struct regmap_config temp_regmap = { + .name = "nocache", + .reg_bits = 16, + .val_bits = 16, + .use_single_rw = true, + .max_register = 0x03f3, + .cache_type = REGCACHE_NONE, +}; + +static const struct i2c_device_id rt5663_i2c_id[] = { + { "rt5668", 0 }, + { "rt5663", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, rt5663_i2c_id); + +#if defined(CONFIG_OF) +static const struct of_device_id rt5663_of_match[] = { + { .compatible = "realtek,rt5668", }, + { .compatible = "realtek,rt5663", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rt5663_of_match); +#endif + +#ifdef CONFIG_ACPI +static struct acpi_device_id rt5663_acpi_match[] = { + { "10EC5668", 0}, + { "10EC5663", 0}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, rt5663_acpi_match); +#endif + +static void rt5668_calibrate(struct rt5663_priv *rt5668) +{ + regmap_write(rt5668->regmap, RT5663_BIAS_CUR_8, 0xa402); + regmap_write(rt5668->regmap, RT5663_PWR_DIG_1, 0x0100); + regmap_write(rt5668->regmap, RT5663_RECMIX, 0x4040); + regmap_write(rt5668->regmap, RT5663_DIG_MISC, 0x0001); + regmap_write(rt5668->regmap, RT5663_RC_CLK, 0x0380); + regmap_write(rt5668->regmap, RT5663_GLB_CLK, 0x8000); + regmap_write(rt5668->regmap, RT5663_ADDA_CLK_1, 0x1000); + regmap_write(rt5668->regmap, RT5663_CHOP_DAC_L, 0x3030); + regmap_write(rt5668->regmap, RT5663_CALIB_ADC, 0x3c05); + regmap_write(rt5668->regmap, RT5663_PWR_ANLG_1, 0xa23e); + msleep(40); + regmap_write(rt5668->regmap, RT5663_PWR_ANLG_1, 0xf23e); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_2, 0x0321); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_1, 0xfc00); + msleep(500); +} + +static void rt5663_calibrate(struct rt5663_priv *rt5668) +{ + int value, count; + + regmap_write(rt5668->regmap, RT5663_RC_CLK, 0x0280); + regmap_write(rt5668->regmap, RT5663_GLB_CLK, 0x8000); + regmap_write(rt5668->regmap, RT5663_DIG_MISC, 0x8001); + regmap_write(rt5668->regmap, RT5663_VREF_RECMIX, 0x0032); + regmap_write(rt5668->regmap, RT5663_PWR_ANLG_1, 0xa2be); + msleep(20); + regmap_write(rt5668->regmap, RT5663_PWR_ANLG_1, 0xf2be); + regmap_write(rt5668->regmap, RT5663_PWR_DIG_2, 0x8400); + regmap_write(rt5668->regmap, RT5663_CHOP_ADC, 0x3000); + regmap_write(rt5668->regmap, RT5663_DEPOP_1, 0x003b); + regmap_write(rt5668->regmap, RT5663_PWR_DIG_1, 0x8df8); + regmap_write(rt5668->regmap, RT5663_PWR_ANLG_2, 0x0003); + regmap_write(rt5668->regmap, RT5663_PWR_ANLG_3, 0x018c); + regmap_write(rt5668->regmap, RT5663_ADDA_CLK_1, 0x1111); + regmap_write(rt5668->regmap, RT5663_PRE_DIV_GATING_1, 0xffff); + regmap_write(rt5668->regmap, RT5663_PRE_DIV_GATING_2, 0xffff); + regmap_write(rt5668->regmap, RT5663_DEPOP_2, 0x3003); + regmap_write(rt5668->regmap, RT5663_DEPOP_1, 0x003b); + regmap_write(rt5668->regmap, RT5663_HP_CHARGE_PUMP_1, 0x1e32); + regmap_write(rt5668->regmap, RT5663_HP_CHARGE_PUMP_2, 0x1371); + regmap_write(rt5668->regmap, RT5663_DACREF_LDO, 0x3b0b); + regmap_write(rt5668->regmap, RT5663_STO_DAC_MIXER, 0x2080); + regmap_write(rt5668->regmap, RT5663_BYPASS_STO_DAC, 0x000c); + regmap_write(rt5668->regmap, RT5663_HP_BIAS, 0xabba); + regmap_write(rt5668->regmap, RT5663_CHARGE_PUMP_1, 0x2224); + regmap_write(rt5668->regmap, RT5663_HP_OUT_EN, 0x8088); + regmap_write(rt5668->regmap, RT5663_STO_DRE_9, 0x0017); + regmap_write(rt5668->regmap, RT5663_STO_DRE_10, 0x0017); + regmap_write(rt5668->regmap, RT5663_STO1_ADC_MIXER, 0x4040); + regmap_write(rt5668->regmap, RT5663_RECMIX, 0x0005); + regmap_write(rt5668->regmap, RT5663_ADDA_RST, 0xc000); + regmap_write(rt5668->regmap, RT5663_STO1_HPF_ADJ1, 0x3320); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_2, 0x00c9); + regmap_write(rt5668->regmap, RT5663_DUMMY_1, 0x004c); + regmap_write(rt5668->regmap, RT5663_ANA_BIAS_CUR_1, 0x7766); + regmap_write(rt5668->regmap, RT5663_BIAS_CUR_8, 0x4702); + msleep(200); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_1, 0x0069); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_3, 0x06c2); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_1_1, 0x7b00); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_1_1, 0xfb00); + count = 0; + while (true) { + regmap_read(rt5668->regmap, RT5663_HP_CALIB_1_1, &value); + if (value & 0x8000) + usleep_range(10000, 10005); + else + break; + + if (count > 200) + return; + count++; + } +} + +static int rt5663_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rt5663_priv *rt5663; + int ret; + unsigned int val; + struct regmap *regmap; + + rt5663 = devm_kzalloc(&i2c->dev, sizeof(struct rt5663_priv), + GFP_KERNEL); + + if (rt5663 == NULL) + return -ENOMEM; + + i2c_set_clientdata(i2c, rt5663); + + regmap = devm_regmap_init_i2c(i2c, &temp_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(&i2c->dev, "Failed to allocate temp register map: %d\n", + ret); + return ret; + } + regmap_read(regmap, RT5663_VENDOR_ID_2, &val); + switch (val) { + case RT5668_DEVICE_ID: + rt5663->regmap = devm_regmap_init_i2c(i2c, &rt5668_regmap); + rt5663->codec_type = CODEC_TYPE_RT5668; + break; + case RT5663_DEVICE_ID: + rt5663->regmap = devm_regmap_init_i2c(i2c, &rt5663_regmap); + rt5663->codec_type = CODEC_TYPE_RT5663; + break; + default: + dev_err(&i2c->dev, + "Device with ID register %#x is not rt5663 or rt5668\n", + val); + return -ENODEV; + } + + if (IS_ERR(rt5663->regmap)) { + ret = PTR_ERR(rt5663->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + /* reset and calibrate */ + regmap_write(rt5663->regmap, RT5663_RESET, 0); + regcache_cache_bypass(rt5663->regmap, true); + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + rt5668_calibrate(rt5663); + break; + case CODEC_TYPE_RT5663: + rt5663_calibrate(rt5663); + break; + default: + dev_err(&i2c->dev, "%s:Unknown codec type\n", __func__); + } + regcache_cache_bypass(rt5663->regmap, false); + regmap_write(rt5663->regmap, RT5663_RESET, 0); + dev_dbg(&i2c->dev, "calibrate done\n"); + + /* GPIO1 as IRQ */ + regmap_update_bits(rt5663->regmap, RT5663_GPIO_1, RT5668_GP1_PIN_MASK, + RT5668_GP1_PIN_IRQ); + /* 4btn inline command debounce */ + regmap_update_bits(rt5663->regmap, RT5663_IL_CMD_5, + RT5668_4BTN_CLK_DEB_MASK, RT5668_4BTN_CLK_DEB_65MS); + + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + regmap_write(rt5663->regmap, RT5663_BIAS_CUR_8, 0xa402); + /* JD1 */ + regmap_update_bits(rt5663->regmap, RT5663_AUTO_1MRC_CLK, + RT5668_IRQ_POW_SAV_MASK | RT5668_IRQ_POW_SAV_JD1_MASK, + RT5668_IRQ_POW_SAV_EN | RT5668_IRQ_POW_SAV_JD1_EN); + regmap_update_bits(rt5663->regmap, RT5663_PWR_ANLG_2, + RT5668_PWR_JD1_MASK, RT5668_PWR_JD1); + regmap_update_bits(rt5663->regmap, RT5663_IRQ_1, + RT5668_EN_CB_JD_MASK, RT5668_EN_CB_JD_EN); + + regmap_update_bits(rt5663->regmap, RT5663_HP_LOGIC_2, + RT5668_HP_SIG_SRC1_MASK, RT5668_HP_SIG_SRC1_REG); + regmap_update_bits(rt5663->regmap, RT5663_RECMIX, + RT5668_VREF_BIAS_MASK | RT5668_CBJ_DET_MASK | + RT5668_DET_TYPE_MASK, RT5668_VREF_BIAS_REG | + RT5668_CBJ_DET_EN | RT5668_DET_TYPE_QFN); + /* Set GPIO4 and GPIO8 as input for combo jack */ + regmap_update_bits(rt5663->regmap, RT5663_GPIO_2, + RT5668_GP4_PIN_CONF_MASK, RT5668_GP4_PIN_CONF_INPUT); + regmap_update_bits(rt5663->regmap, RT5668_GPIO_3, + RT5668_GP8_PIN_CONF_MASK, RT5668_GP8_PIN_CONF_INPUT); + regmap_update_bits(rt5663->regmap, RT5663_PWR_ANLG_1, + RT5668_LDO1_DVO_MASK | RT5668_AMP_HP_MASK, + RT5668_LDO1_DVO_0_9V | RT5668_AMP_HP_3X); + break; + case CODEC_TYPE_RT5663: + regmap_write(rt5663->regmap, RT5663_VREF_RECMIX, 0x0032); + regmap_write(rt5663->regmap, RT5663_PWR_ANLG_1, 0xa2be); + msleep(20); + regmap_write(rt5663->regmap, RT5663_PWR_ANLG_1, 0xf2be); + regmap_update_bits(rt5663->regmap, RT5663_GPIO_2, + RT5663_GP1_PIN_CONF_MASK, RT5663_GP1_PIN_CONF_OUTPUT); + /* DACREF LDO control */ + regmap_update_bits(rt5663->regmap, RT5663_DACREF_LDO, 0x3e0e, + 0x3a0a); + regmap_update_bits(rt5663->regmap, RT5663_RECMIX, + RT5663_RECMIX1_BST1_MASK, RT5663_RECMIX1_BST1_ON); + regmap_update_bits(rt5663->regmap, RT5663_TDM_2, + RT5663_DATA_SWAP_ADCDAT1_MASK, + RT5663_DATA_SWAP_ADCDAT1_LL); + break; + default: + dev_err(&i2c->dev, "%s:Unknown codec type\n", __func__); + } + + INIT_DELAYED_WORK(&rt5663->jack_detect_work, rt5663_jack_detect_work); + + if (i2c->irq) { + ret = request_irq(i2c->irq, rt5663_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING + | IRQF_ONESHOT, "rt5663", rt5663); + if (ret) + dev_err(&i2c->dev, "%s Failed to reguest IRQ: %d\n", + __func__, ret); + } + + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5663, + rt5663_dai, ARRAY_SIZE(rt5663_dai)); + + if (ret) { + if (i2c->irq) + free_irq(i2c->irq, rt5663); + } + + return ret; +} + +static int rt5663_i2c_remove(struct i2c_client *i2c) +{ + struct rt5663_priv *rt5663 = i2c_get_clientdata(i2c); + + if (i2c->irq) + free_irq(i2c->irq, rt5663); + + snd_soc_unregister_codec(&i2c->dev); + + return 0; +} + +static void rt5663_i2c_shutdown(struct i2c_client *client) +{ + struct rt5663_priv *rt5663 = i2c_get_clientdata(client); + + regmap_write(rt5663->regmap, RT5663_RESET, 0); +} + +static struct i2c_driver rt5663_i2c_driver = { + .driver = { + .name = "rt5663", + .acpi_match_table = ACPI_PTR(rt5663_acpi_match), + .of_match_table = of_match_ptr(rt5663_of_match), + }, + .probe = rt5663_i2c_probe, + .remove = rt5663_i2c_remove, + .shutdown = rt5663_i2c_shutdown, + .id_table = rt5663_i2c_id, +}; +module_i2c_driver(rt5663_i2c_driver); + +MODULE_DESCRIPTION("ASoC RT5663 driver"); +MODULE_AUTHOR("Jack Yu <jack.yu@realtek.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt5663.h b/sound/soc/codecs/rt5663.h new file mode 100644 index 0000000..2cc8f28 --- /dev/null +++ b/sound/soc/codecs/rt5663.h @@ -0,0 +1,1121 @@ +/* + * rt5663.h -- RT5663 ALSA SoC audio driver + * + * Copyright 2016 Realtek Microelectronics + * Author: Jack Yu <jack.yu@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 __RT5663_H__ +#define __RT5663_H__ + +/* Info */ +#define RT5663_RESET 0x0000 +#define RT5663_VENDOR_ID 0x00fd +#define RT5663_VENDOR_ID_1 0x00fe +#define RT5663_VENDOR_ID_2 0x00ff + +#define RT5668_LOUT_CTRL 0x0001 +#define RT5668_HP_AMP_2 0x0003 +#define RT5668_MONO_OUT 0x0004 +#define RT5668_MONO_GAIN 0x0007 + +#define RT5668_AEC_BST 0x000b +#define RT5668_IN1_IN2 0x000c +#define RT5668_IN3_IN4 0x000d +#define RT5668_INL1_INR1 0x000f +#define RT5668_CBJ_TYPE_2 0x0011 +#define RT5668_CBJ_TYPE_3 0x0012 +#define RT5668_CBJ_TYPE_4 0x0013 +#define RT5668_CBJ_TYPE_5 0x0014 +#define RT5668_CBJ_TYPE_8 0x0017 + +/* I/O - ADC/DAC/DMIC */ +#define RT5668_DAC3_DIG_VOL 0x001a +#define RT5668_DAC3_CTRL 0x001b +#define RT5668_MONO_ADC_DIG_VOL 0x001d +#define RT5668_STO2_ADC_DIG_VOL 0x001e +#define RT5668_MONO_ADC_BST_GAIN 0x0020 +#define RT5668_STO2_ADC_BST_GAIN 0x0021 +#define RT5668_SIDETONE_CTRL 0x0024 +/* Mixer - D-D */ +#define RT5668_MONO1_ADC_MIXER 0x0027 +#define RT5668_STO2_ADC_MIXER 0x0028 +#define RT5668_MONO_DAC_MIXER 0x002b +#define RT5668_DAC2_SRC_CTRL 0x002e +#define RT5668_IF_3_4_DATA_CTL 0x002f +#define RT5668_IF_5_DATA_CTL 0x0030 +#define RT5668_PDM_OUT_CTL 0x0031 +#define RT5668_PDM_I2C_DATA_CTL1 0x0032 +#define RT5668_PDM_I2C_DATA_CTL2 0x0033 +#define RT5668_PDM_I2C_DATA_CTL3 0x0034 +#define RT5668_PDM_I2C_DATA_CTL4 0x0035 + +/*Mixer - Analog*/ +#define RT5668_RECMIX1_NEW 0x003a +#define RT5668_RECMIX1L_0 0x003b +#define RT5668_RECMIX1L 0x003c +#define RT5668_RECMIX1R_0 0x003d +#define RT5668_RECMIX1R 0x003e +#define RT5668_RECMIX2_NEW 0x003f +#define RT5668_RECMIX2_L_2 0x0041 +#define RT5668_RECMIX2_R 0x0042 +#define RT5668_RECMIX2_R_2 0x0043 +#define RT5668_CALIB_REC_LR 0x0044 +#define RT5668_ALC_BK_GAIN 0x0049 +#define RT5668_MONOMIX_GAIN 0x004a +#define RT5668_MONOMIX_IN_GAIN 0x004b +#define RT5668_OUT_MIXL_GAIN 0x004d +#define RT5668_OUT_LMIX_IN_GAIN 0x004e +#define RT5668_OUT_RMIX_IN_GAIN 0x004f +#define RT5668_OUT_RMIX_IN_GAIN1 0x0050 +#define RT5668_LOUT_MIXER_CTRL 0x0052 +/* Power */ +#define RT5668_PWR_VOL 0x0067 + +#define RT5668_ADCDAC_RST 0x006d +/* Format - ADC/DAC */ +#define RT5668_I2S34_SDP 0x0071 +#define RT5668_I2S5_SDP 0x0072 +/* Format - TDM Control */ +#define RT5668_TDM_5 0x007c +#define RT5668_TDM_6 0x007d +#define RT5668_TDM_7 0x007e +#define RT5668_TDM_8 0x007f + +/* Function - Analog */ +#define RT5668_ASRC_3 0x0085 +#define RT5668_ASRC_6 0x0088 +#define RT5668_ASRC_7 0x0089 +#define RT5668_PLL_TRK_13 0x0099 +#define RT5668_I2S_M_CLK_CTL 0x00a0 +#define RT5668_FDIV_I2S34_M_CLK 0x00a1 +#define RT5668_FDIV_I2S34_M_CLK2 0x00a2 +#define RT5668_FDIV_I2S5_M_CLK 0x00a3 +#define RT5668_FDIV_I2S5_M_CLK2 0x00a4 + +/* Function - Digital */ +#define RT5668_IRQ_4 0x00b9 +#define RT5668_GPIO_3 0x00c2 +#define RT5668_GPIO_4 0x00c3 +#define RT5668_GPIO_STA 0x00c4 +#define RT5668_HP_AMP_DET1 0x00d0 +#define RT5668_HP_AMP_DET2 0x00d1 +#define RT5668_HP_AMP_DET3 0x00d2 +#define RT5668_MID_BD_HP_AMP 0x00d3 +#define RT5668_LOW_BD_HP_AMP 0x00d4 +#define RT5668_SOF_VOL_ZC2 0x00da +#define RT5668_ADC_STO2_ADJ1 0x00ee +#define RT5668_ADC_STO2_ADJ2 0x00ef +/* General Control */ +#define RT5668_A_JD_CTRL 0x00f0 +#define RT5668_JD1_TRES_CTRL 0x00f1 +#define RT5668_JD2_TRES_CTRL 0x00f2 +#define RT5668_JD_CTRL2 0x00f7 +#define RT5668_DUM_REG_2 0x00fb +#define RT5668_DUM_REG_3 0x00fc + + +#define RT5668_DACADC_DIG_VOL2 0x0101 +#define RT5668_DIG_IN_PIN2 0x0133 +#define RT5668_PAD_DRV_CTL1 0x0136 +#define RT5668_SOF_RAM_DEPOP 0x0138 +#define RT5668_VOL_TEST 0x013f +#define RT5668_TEST_MODE_3 0x0147 +#define RT5668_TEST_MODE_4 0x0148 +#define RT5668_MONO_DYNA_1 0x0170 +#define RT5668_MONO_DYNA_2 0x0171 +#define RT5668_MONO_DYNA_3 0x0172 +#define RT5668_MONO_DYNA_4 0x0173 +#define RT5668_MONO_DYNA_5 0x0174 +#define RT5668_MONO_DYNA_6 0x0175 +#define RT5668_STO1_SIL_DET 0x0190 +#define RT5668_MONOL_SIL_DET 0x0191 +#define RT5668_MONOR_SIL_DET 0x0192 +#define RT5668_STO2_DAC_SIL 0x0193 +#define RT5668_PWR_SAV_CTL1 0x0194 +#define RT5668_PWR_SAV_CTL2 0x0195 +#define RT5668_PWR_SAV_CTL3 0x0196 +#define RT5668_PWR_SAV_CTL4 0x0197 +#define RT5668_PWR_SAV_CTL5 0x0198 +#define RT5668_PWR_SAV_CTL6 0x0199 +#define RT5668_MONO_AMP_CAL1 0x01a0 +#define RT5668_MONO_AMP_CAL2 0x01a1 +#define RT5668_MONO_AMP_CAL3 0x01a2 +#define RT5668_MONO_AMP_CAL4 0x01a3 +#define RT5668_MONO_AMP_CAL5 0x01a4 +#define RT5668_MONO_AMP_CAL6 0x01a5 +#define RT5668_MONO_AMP_CAL7 0x01a6 +#define RT5668_MONO_AMP_CAL_ST1 0x01a7 +#define RT5668_MONO_AMP_CAL_ST2 0x01a8 +#define RT5668_MONO_AMP_CAL_ST3 0x01a9 +#define RT5668_MONO_AMP_CAL_ST4 0x01aa +#define RT5668_MONO_AMP_CAL_ST5 0x01ab +#define RT5668_HP_IMP_SEN_13 0x01b9 +#define RT5668_HP_IMP_SEN_14 0x01ba +#define RT5668_HP_IMP_SEN_6 0x01bb +#define RT5668_HP_IMP_SEN_7 0x01bc +#define RT5668_HP_IMP_SEN_8 0x01bd +#define RT5668_HP_IMP_SEN_9 0x01be +#define RT5668_HP_IMP_SEN_10 0x01bf +#define RT5668_HP_LOGIC_3 0x01dc +#define RT5668_HP_CALIB_ST10 0x01f3 +#define RT5668_HP_CALIB_ST11 0x01f4 +#define RT5668_PRO_REG_TBL_4 0x0203 +#define RT5668_PRO_REG_TBL_5 0x0204 +#define RT5668_PRO_REG_TBL_6 0x0205 +#define RT5668_PRO_REG_TBL_7 0x0206 +#define RT5668_PRO_REG_TBL_8 0x0207 +#define RT5668_PRO_REG_TBL_9 0x0208 +#define RT5668_SAR_ADC_INL_1 0x0210 +#define RT5668_SAR_ADC_INL_2 0x0211 +#define RT5668_SAR_ADC_INL_3 0x0212 +#define RT5668_SAR_ADC_INL_4 0x0213 +#define RT5668_SAR_ADC_INL_5 0x0214 +#define RT5668_SAR_ADC_INL_6 0x0215 +#define RT5668_SAR_ADC_INL_7 0x0216 +#define RT5668_SAR_ADC_INL_8 0x0217 +#define RT5668_SAR_ADC_INL_9 0x0218 +#define RT5668_SAR_ADC_INL_10 0x0219 +#define RT5668_SAR_ADC_INL_11 0x021a +#define RT5668_SAR_ADC_INL_12 0x021b +#define RT5668_DRC_CTRL_1 0x02ff +#define RT5668_DRC1_CTRL_2 0x0301 +#define RT5668_DRC1_CTRL_3 0x0302 +#define RT5668_DRC1_CTRL_4 0x0303 +#define RT5668_DRC1_CTRL_5 0x0304 +#define RT5668_DRC1_CTRL_6 0x0305 +#define RT5668_DRC1_HD_CTRL_1 0x0306 +#define RT5668_DRC1_HD_CTRL_2 0x0307 +#define RT5668_DRC1_PRI_REG_1 0x0310 +#define RT5668_DRC1_PRI_REG_2 0x0311 +#define RT5668_DRC1_PRI_REG_3 0x0312 +#define RT5668_DRC1_PRI_REG_4 0x0313 +#define RT5668_DRC1_PRI_REG_5 0x0314 +#define RT5668_DRC1_PRI_REG_6 0x0315 +#define RT5668_DRC1_PRI_REG_7 0x0316 +#define RT5668_DRC1_PRI_REG_8 0x0317 +#define RT5668_ALC_PGA_CTL_1 0x0330 +#define RT5668_ALC_PGA_CTL_2 0x0331 +#define RT5668_ALC_PGA_CTL_3 0x0332 +#define RT5668_ALC_PGA_CTL_4 0x0333 +#define RT5668_ALC_PGA_CTL_5 0x0334 +#define RT5668_ALC_PGA_CTL_6 0x0335 +#define RT5668_ALC_PGA_CTL_7 0x0336 +#define RT5668_ALC_PGA_CTL_8 0x0337 +#define RT5668_ALC_PGA_REG_1 0x0338 +#define RT5668_ALC_PGA_REG_2 0x0339 +#define RT5668_ALC_PGA_REG_3 0x033a +#define RT5668_ADC_EQ_RECOV_1 0x03c0 +#define RT5668_ADC_EQ_RECOV_2 0x03c1 +#define RT5668_ADC_EQ_RECOV_3 0x03c2 +#define RT5668_ADC_EQ_RECOV_4 0x03c3 +#define RT5668_ADC_EQ_RECOV_5 0x03c4 +#define RT5668_ADC_EQ_RECOV_6 0x03c5 +#define RT5668_ADC_EQ_RECOV_7 0x03c6 +#define RT5668_ADC_EQ_RECOV_8 0x03c7 +#define RT5668_ADC_EQ_RECOV_9 0x03c8 +#define RT5668_ADC_EQ_RECOV_10 0x03c9 +#define RT5668_ADC_EQ_RECOV_11 0x03ca +#define RT5668_ADC_EQ_RECOV_12 0x03cb +#define RT5668_ADC_EQ_RECOV_13 0x03cc +#define RT5668_VID_HIDDEN 0x03fe +#define RT5668_VID_CUSTOMER 0x03ff +#define RT5668_SCAN_MODE 0x07f0 +#define RT5668_I2C_BYPA 0x07fa + +/* Headphone Amp Control 2 (0x0003) */ +#define RT5668_EN_DAC_HPO_MASK (0x1 << 14) +#define RT5668_EN_DAC_HPO_SHIFT 14 +#define RT5668_EN_DAC_HPO_DIS (0x0 << 14) +#define RT5668_EN_DAC_HPO_EN (0x1 << 14) + +/*Headphone Amp L/R Analog Gain and Digital NG2 Gain Control (0x0005 0x0006)*/ +#define RT5668_GAIN_HP (0x1f << 8) +#define RT5668_GAIN_HP_SHIFT 8 + +/* AEC BST Control (0x000b) */ +#define RT5668_GAIN_CBJ_MASK (0xf << 8) +#define RT5668_GAIN_CBJ_SHIFT 8 + +/* IN1 Control / MIC GND REF (0x000c) */ +#define RT5668_IN1_DF_MASK (0x1 << 15) +#define RT5668_IN1_DF_SHIFT 15 + +/* Combo Jack and Type Detection Control 1 (0x0010) */ +#define RT5668_CBJ_DET_MASK (0x1 << 15) +#define RT5668_CBJ_DET_SHIFT 15 +#define RT5668_CBJ_DET_DIS (0x0 << 15) +#define RT5668_CBJ_DET_EN (0x1 << 15) +#define RT5668_DET_TYPE_MASK (0x1 << 12) +#define RT5668_DET_TYPE_SHIFT 12 +#define RT5668_DET_TYPE_WLCSP (0x0 << 12) +#define RT5668_DET_TYPE_QFN (0x1 << 12) +#define RT5668_VREF_BIAS_MASK (0x1 << 6) +#define RT5668_VREF_BIAS_SHIFT 6 +#define RT5668_VREF_BIAS_FSM (0x0 << 6) +#define RT5668_VREF_BIAS_REG (0x1 << 6) + +/* REC Left Mixer Control 2 (0x003c) */ +#define RT5668_RECMIX1L_BST1_CBJ (0x1 << 7) +#define RT5668_RECMIX1L_BST1_CBJ_SHIFT 7 +#define RT5668_RECMIX1L_BST2 (0x1 << 4) +#define RT5668_RECMIX1L_BST2_SHIFT 4 + +/* REC Right Mixer Control 2 (0x003e) */ +#define RT5668_RECMIX1R_BST2 (0x1 << 4) +#define RT5668_RECMIX1R_BST2_SHIFT 4 + +/* DAC1 Digital Volume (0x0019) */ +#define RT5668_DAC_L1_VOL_MASK (0xff << 8) +#define RT5668_DAC_L1_VOL_SHIFT 8 +#define RT5668_DAC_R1_VOL_MASK (0xff) +#define RT5668_DAC_R1_VOL_SHIFT 0 + +/* ADC Digital Volume Control (0x001c) */ +#define RT5668_ADC_L_MUTE_MASK (0x1 << 15) +#define RT5668_ADC_L_MUTE_SHIFT 15 +#define RT5668_ADC_L_VOL_MASK (0x7f << 8) +#define RT5668_ADC_L_VOL_SHIFT 8 +#define RT5668_ADC_R_MUTE_MASK (0x1 << 7) +#define RT5668_ADC_R_MUTE_SHIFT 7 +#define RT5668_ADC_R_VOL_MASK (0x7f) +#define RT5668_ADC_R_VOL_SHIFT 0 + +/* Stereo ADC Mixer Control (0x0026) */ +#define RT5668_M_STO1_ADC_L1 (0x1 << 15) +#define RT5668_M_STO1_ADC_L1_SHIFT 15 +#define RT5668_M_STO1_ADC_L2 (0x1 << 14) +#define RT5668_M_STO1_ADC_L2_SHIFT 14 +#define RT5668_STO1_ADC_L1_SRC (0x1 << 13) +#define RT5668_STO1_ADC_L1_SRC_SHIFT 13 +#define RT5668_STO1_ADC_L2_SRC (0x1 << 12) +#define RT5668_STO1_ADC_L2_SRC_SHIFT 12 +#define RT5668_STO1_ADC_L_SRC (0x3 << 10) +#define RT5668_STO1_ADC_L_SRC_SHIFT 10 +#define RT5668_M_STO1_ADC_R1 (0x1 << 7) +#define RT5668_M_STO1_ADC_R1_SHIFT 7 +#define RT5668_M_STO1_ADC_R2 (0x1 << 6) +#define RT5668_M_STO1_ADC_R2_SHIFT 6 +#define RT5668_STO1_ADC_R1_SRC (0x1 << 5) +#define RT5668_STO1_ADC_R1_SRC_SHIFT 5 +#define RT5668_STO1_ADC_R2_SRC (0x1 << 4) +#define RT5668_STO1_ADC_R2_SRC_SHIFT 4 +#define RT5668_STO1_ADC_R_SRC (0x3 << 2) +#define RT5668_STO1_ADC_R_SRC_SHIFT 2 + +/* ADC Mixer to DAC Mixer Control (0x0029) */ +#define RT5668_M_ADCMIX_L (0x1 << 15) +#define RT5668_M_ADCMIX_L_SHIFT 15 +#define RT5668_M_DAC1_L (0x1 << 14) +#define RT5668_M_DAC1_L_SHIFT 14 +#define RT5668_M_ADCMIX_R (0x1 << 7) +#define RT5668_M_ADCMIX_R_SHIFT 7 +#define RT5668_M_DAC1_R (0x1 << 6) +#define RT5668_M_DAC1_R_SHIFT 6 + +/* Stereo DAC Mixer Control (0x002a) */ +#define RT5668_M_DAC_L1_STO_L (0x1 << 15) +#define RT5668_M_DAC_L1_STO_L_SHIFT 15 +#define RT5668_M_DAC_R1_STO_L (0x1 << 13) +#define RT5668_M_DAC_R1_STO_L_SHIFT 13 +#define RT5668_M_DAC_L1_STO_R (0x1 << 7) +#define RT5668_M_DAC_L1_STO_R_SHIFT 7 +#define RT5668_M_DAC_R1_STO_R (0x1 << 5) +#define RT5668_M_DAC_R1_STO_R_SHIFT 5 + +/* Power Management for Digital 1 (0x0061) */ +#define RT5668_PWR_I2S1 (0x1 << 15) +#define RT5668_PWR_I2S1_SHIFT 15 +#define RT5668_PWR_DAC_L1 (0x1 << 11) +#define RT5668_PWR_DAC_L1_SHIFT 11 +#define RT5668_PWR_DAC_R1 (0x1 << 10) +#define RT5668_PWR_DAC_R1_SHIFT 10 +#define RT5668_PWR_LDO_DACREF_MASK (0x1 << 8) +#define RT5668_PWR_LDO_DACREF_SHIFT 8 +#define RT5668_PWR_LDO_DACREF_ON (0x1 << 8) +#define RT5668_PWR_LDO_DACREF_DOWN (0x0 << 8) +#define RT5668_PWR_LDO_SHIFT 8 +#define RT5668_PWR_ADC_L1 (0x1 << 4) +#define RT5668_PWR_ADC_L1_SHIFT 4 +#define RT5668_PWR_ADC_R1 (0x1 << 3) +#define RT5668_PWR_ADC_R1_SHIFT 3 + +/* Power Management for Digital 2 (0x0062) */ +#define RT5668_PWR_ADC_S1F (0x1 << 15) +#define RT5668_PWR_ADC_S1F_SHIFT 15 +#define RT5668_PWR_DAC_S1F (0x1 << 10) +#define RT5668_PWR_DAC_S1F_SHIFT 10 + +/* Power Management for Analog 1 (0x0063) */ +#define RT5668_PWR_VREF1 (0x1 << 15) +#define RT5668_PWR_VREF1_MASK (0x1 << 15) +#define RT5668_PWR_VREF1_SHIFT 15 +#define RT5668_PWR_FV1 (0x1 << 14) +#define RT5668_PWR_FV1_MASK (0x1 << 14) +#define RT5668_PWR_FV1_SHIFT 14 +#define RT5668_PWR_VREF2 (0x1 << 13) +#define RT5668_PWR_VREF2_MASK (0x1 << 13) +#define RT5668_PWR_VREF2_SHIFT 13 +#define RT5668_PWR_FV2 (0x1 << 12) +#define RT5668_PWR_FV2_MASK (0x1 << 12) +#define RT5668_PWR_FV2_SHIFT 12 +#define RT5668_PWR_MB (0x1 << 9) +#define RT5668_PWR_MB_MASK (0x1 << 9) +#define RT5668_PWR_MB_SHIFT 9 +#define RT5668_AMP_HP_MASK (0x3 << 2) +#define RT5668_AMP_HP_SHIFT 2 +#define RT5668_AMP_HP_1X (0x0 << 2) +#define RT5668_AMP_HP_3X (0x1 << 2) +#define RT5668_AMP_HP_5X (0x3 << 2) +#define RT5668_LDO1_DVO_MASK (0x3) +#define RT5668_LDO1_DVO_SHIFT 0 +#define RT5668_LDO1_DVO_0_9V (0x0) +#define RT5668_LDO1_DVO_1_0V (0x1) +#define RT5668_LDO1_DVO_1_2V (0x2) +#define RT5668_LDO1_DVO_1_4V (0x3) + +/* Power Management for Analog 2 (0x0064) */ +#define RT5668_PWR_BST1 (0x1 << 15) +#define RT5668_PWR_BST1_MASK (0x1 << 15) +#define RT5668_PWR_BST1_SHIFT 15 +#define RT5668_PWR_BST1_OFF (0x0 << 15) +#define RT5668_PWR_BST1_ON (0x1 << 15) +#define RT5668_PWR_BST2 (0x1 << 14) +#define RT5668_PWR_BST2_MASK (0x1 << 14) +#define RT5668_PWR_BST2_SHIFT 14 +#define RT5668_PWR_MB1 (0x1 << 11) +#define RT5668_PWR_MB1_SHIFT 11 +#define RT5668_PWR_MB2 (0x1 << 10) +#define RT5668_PWR_MB2_SHIFT 10 +#define RT5668_PWR_BST2_OP (0x1 << 6) +#define RT5668_PWR_BST2_OP_MASK (0x1 << 6) +#define RT5668_PWR_BST2_OP_SHIFT 6 +#define RT5668_PWR_JD1 (0x1 << 3) +#define RT5668_PWR_JD1_MASK (0x1 << 3) +#define RT5668_PWR_JD1_SHIFT 3 +#define RT5668_PWR_JD2 (0x1 << 2) +#define RT5668_PWR_JD2_MASK (0x1 << 2) +#define RT5668_PWR_JD2_SHIFT 2 +#define RT5668_PWR_RECMIX1 (0x1 << 1) +#define RT5668_PWR_RECMIX1_SHIFT 1 +#define RT5668_PWR_RECMIX2 (0x1) +#define RT5668_PWR_RECMIX2_SHIFT 0 + +/* Power Management for Analog 3 (0x0065) */ +#define RT5668_PWR_CBJ_MASK (0x1 << 9) +#define RT5668_PWR_CBJ_SHIFT 9 +#define RT5668_PWR_CBJ_OFF (0x0 << 9) +#define RT5668_PWR_CBJ_ON (0x1 << 9) +#define RT5668_PWR_PLL (0x1 << 6) +#define RT5668_PWR_PLL_SHIFT 6 +#define RT5668_PWR_LDO2 (0x1 << 2) +#define RT5668_PWR_LDO2_SHIFT 2 + +/* Power Management for Volume (0x0067) */ +#define RT5668_PWR_MIC_DET (0x1 << 5) +#define RT5668_PWR_MIC_DET_SHIFT 5 + +/* MCLK and System Clock Detection Control (0x006b) */ +#define RT5668_EN_ANA_CLK_DET_MASK (0x1 << 15) +#define RT5668_EN_ANA_CLK_DET_SHIFT 15 +#define RT5668_EN_ANA_CLK_DET_DIS (0x0 << 15) +#define RT5668_EN_ANA_CLK_DET_AUTO (0x1 << 15) +#define RT5668_PWR_CLK_DET_MASK (0x1) +#define RT5668_PWR_CLK_DET_SHIFT 0 +#define RT5668_PWR_CLK_DET_DIS (0x0) +#define RT5668_PWR_CLK_DET_EN (0x1) + +/* I2S1 Audio Serial Data Port Control (0x0070) */ +#define RT5668_I2S_MS_MASK (0x1 << 15) +#define RT5668_I2S_MS_SHIFT 15 +#define RT5668_I2S_MS_M (0x0 << 15) +#define RT5668_I2S_MS_S (0x1 << 15) +#define RT5668_I2S_BP_MASK (0x1 << 8) +#define RT5668_I2S_BP_SHIFT 8 +#define RT5668_I2S_BP_NOR (0x0 << 8) +#define RT5668_I2S_BP_INV (0x1 << 8) +#define RT5668_I2S_DL_MASK (0x3 << 4) +#define RT5668_I2S_DL_SHIFT 4 +#define RT5668_I2S_DL_16 (0x0 << 4) +#define RT5668_I2S_DL_20 (0x1 << 4) +#define RT5668_I2S_DL_24 (0x2 << 4) +#define RT5668_I2S_DL_8 (0x3 << 4) +#define RT5668_I2S_DF_MASK (0x7) +#define RT5668_I2S_DF_SHIFT 0 +#define RT5668_I2S_DF_I2S (0x0) +#define RT5668_I2S_DF_LEFT (0x1) +#define RT5668_I2S_DF_PCM_A (0x2) +#define RT5668_I2S_DF_PCM_B (0x3) +#define RT5668_I2S_DF_PCM_A_N (0x6) +#define RT5668_I2S_DF_PCM_B_N (0x7) + +/* ADC/DAC Clock Control 1 (0x0073) */ +#define RT5668_I2S_PD1_MASK (0x7 << 12) +#define RT5668_I2S_PD1_SHIFT 12 +#define RT5668_M_I2S_DIV_MASK (0x7 << 8) +#define RT5668_M_I2S_DIV_SHIFT 8 +#define RT5668_CLK_SRC_MASK (0x3 << 4) +#define RT5668_CLK_SRC_MCLK (0x0 << 4) +#define RT5668_CLK_SRC_PLL_OUT (0x1 << 4) +#define RT5668_CLK_SRC_DIV (0x2 << 4) +#define RT5668_CLK_SRC_RC (0x3 << 4) +#define RT5668_DAC_OSR_MASK (0x3 << 2) +#define RT5668_DAC_OSR_SHIFT 2 +#define RT5668_DAC_OSR_128 (0x0 << 2) +#define RT5668_DAC_OSR_64 (0x1 << 2) +#define RT5668_DAC_OSR_32 (0x2 << 2) +#define RT5668_ADC_OSR_MASK (0x3) +#define RT5668_ADC_OSR_SHIFT 0 +#define RT5668_ADC_OSR_128 (0x0) +#define RT5668_ADC_OSR_64 (0x1) +#define RT5668_ADC_OSR_32 (0x2) + +/* TDM1 control 1 (0x0078) */ +#define RT5668_TDM_MODE_MASK (0x1 << 15) +#define RT5668_TDM_MODE_SHIFT 15 +#define RT5668_TDM_MODE_I2S (0x0 << 15) +#define RT5668_TDM_MODE_TDM (0x1 << 15) +#define RT5668_TDM_IN_CH_MASK (0x3 << 10) +#define RT5668_TDM_IN_CH_SHIFT 10 +#define RT5668_TDM_IN_CH_2 (0x0 << 10) +#define RT5668_TDM_IN_CH_4 (0x1 << 10) +#define RT5668_TDM_IN_CH_6 (0x2 << 10) +#define RT5668_TDM_IN_CH_8 (0x3 << 10) +#define RT5668_TDM_OUT_CH_MASK (0x3 << 8) +#define RT5668_TDM_OUT_CH_SHIFT 8 +#define RT5668_TDM_OUT_CH_2 (0x0 << 8) +#define RT5668_TDM_OUT_CH_4 (0x1 << 8) +#define RT5668_TDM_OUT_CH_6 (0x2 << 8) +#define RT5668_TDM_OUT_CH_8 (0x3 << 8) +#define RT5668_TDM_IN_LEN_MASK (0x3 << 6) +#define RT5668_TDM_IN_LEN_SHIFT 6 +#define RT5668_TDM_IN_LEN_16 (0x0 << 6) +#define RT5668_TDM_IN_LEN_20 (0x1 << 6) +#define RT5668_TDM_IN_LEN_24 (0x2 << 6) +#define RT5668_TDM_IN_LEN_32 (0x3 << 6) +#define RT5668_TDM_OUT_LEN_MASK (0x3 << 4) +#define RT5668_TDM_OUT_LEN_SHIFT 4 +#define RT5668_TDM_OUT_LEN_16 (0x0 << 4) +#define RT5668_TDM_OUT_LEN_20 (0x1 << 4) +#define RT5668_TDM_OUT_LEN_24 (0x2 << 4) +#define RT5668_TDM_OUT_LEN_32 (0x3 << 4) + +/* Global Clock Control (0x0080) */ +#define RT5668_SCLK_SRC_MASK (0x3 << 14) +#define RT5668_SCLK_SRC_SHIFT 14 +#define RT5668_SCLK_SRC_MCLK (0x0 << 14) +#define RT5668_SCLK_SRC_PLL1 (0x1 << 14) +#define RT5668_SCLK_SRC_RCCLK (0x2 << 14) +#define RT5668_PLL1_SRC_MASK (0x7 << 8) +#define RT5668_PLL1_SRC_SHIFT 8 +#define RT5668_PLL1_SRC_MCLK (0x0 << 8) +#define RT5668_PLL1_SRC_BCLK1 (0x1 << 8) +#define RT5668_PLL1_PD_MASK (0x1 << 4) +#define RT5668_PLL1_PD_SHIFT 4 + +#define RT5668_PLL_INP_MAX 40000000 +#define RT5668_PLL_INP_MIN 256000 +/* PLL M/N/K Code Control 1 (0x0081) */ +#define RT5668_PLL_N_MAX 0x001ff +#define RT5668_PLL_N_MASK (RT5668_PLL_N_MAX << 7) +#define RT5668_PLL_N_SHIFT 7 +#define RT5668_PLL_K_MAX 0x001f +#define RT5668_PLL_K_MASK (RT5668_PLL_K_MAX) +#define RT5668_PLL_K_SHIFT 0 + +/* PLL M/N/K Code Control 2 (0x0082) */ +#define RT5668_PLL_M_MAX 0x00f +#define RT5668_PLL_M_MASK (RT5668_PLL_M_MAX << 12) +#define RT5668_PLL_M_SHIFT 12 +#define RT5668_PLL_M_BP (0x1 << 11) +#define RT5668_PLL_M_BP_SHIFT 11 + +/* PLL tracking mode 1 (0x0083) */ +#define RT5668_I2S1_ASRC_MASK (0x1 << 13) +#define RT5668_I2S1_ASRC_SHIFT 13 +#define RT5668_DAC_STO1_ASRC_MASK (0x1 << 12) +#define RT5668_DAC_STO1_ASRC_SHIFT 12 +#define RT5668_ADC_STO1_ASRC_MASK (0x1 << 4) +#define RT5668_ADC_STO1_ASRC_SHIFT 4 + +/* PLL tracking mode 2 (0x0084)*/ +#define RT5668_DA_STO1_TRACK_MASK (0x7 << 12) +#define RT5668_DA_STO1_TRACK_SHIFT 12 +#define RT5668_DA_STO1_TRACK_SYSCLK (0x0 << 12) +#define RT5668_DA_STO1_TRACK_I2S1 (0x1 << 12) + +/* PLL tracking mode 3 (0x0085)*/ +#define RT5668_AD_STO1_TRACK_MASK (0x7 << 12) +#define RT5668_AD_STO1_TRACK_SHIFT 12 +#define RT5668_AD_STO1_TRACK_SYSCLK (0x0 << 12) +#define RT5668_AD_STO1_TRACK_I2S1 (0x1 << 12) + +/* HPOUT Charge pump control 1 (0x0091) */ +#define RT5668_OSW_HP_L_MASK (0x1 << 11) +#define RT5668_OSW_HP_L_SHIFT 11 +#define RT5668_OSW_HP_L_EN (0x1 << 11) +#define RT5668_OSW_HP_L_DIS (0x0 << 11) +#define RT5668_OSW_HP_R_MASK (0x1 << 10) +#define RT5668_OSW_HP_R_SHIFT 10 +#define RT5668_OSW_HP_R_EN (0x1 << 10) +#define RT5668_OSW_HP_R_DIS (0x0 << 10) +#define RT5668_SEL_PM_HP_MASK (0x3 << 8) +#define RT5668_SEL_PM_HP_SHIFT 8 +#define RT5668_SEL_PM_HP_0_6 (0x0 << 8) +#define RT5668_SEL_PM_HP_0_9 (0x1 << 8) +#define RT5668_SEL_PM_HP_1_8 (0x2 << 8) +#define RT5668_SEL_PM_HP_HIGH (0x3 << 8) +#define RT5668_OVCD_HP_MASK (0x1 << 2) +#define RT5668_OVCD_HP_SHIFT 2 +#define RT5668_OVCD_HP_EN (0x1 << 2) +#define RT5668_OVCD_HP_DIS (0x0 << 2) + +/* RC Clock Control (0x0094) */ +#define RT5668_DIG_25M_CLK_MASK (0x1 << 9) +#define RT5668_DIG_25M_CLK_SHIFT 9 +#define RT5668_DIG_25M_CLK_DIS (0x0 << 9) +#define RT5668_DIG_25M_CLK_EN (0x1 << 9) +#define RT5668_DIG_1M_CLK_MASK (0x1 << 8) +#define RT5668_DIG_1M_CLK_SHIFT 8 +#define RT5668_DIG_1M_CLK_DIS (0x0 << 8) +#define RT5668_DIG_1M_CLK_EN (0x1 << 8) + +/* Auto Turn On 1M RC CLK (0x009f) */ +#define RT5668_IRQ_POW_SAV_MASK (0x1 << 15) +#define RT5668_IRQ_POW_SAV_SHIFT 15 +#define RT5668_IRQ_POW_SAV_DIS (0x0 << 15) +#define RT5668_IRQ_POW_SAV_EN (0x1 << 15) +#define RT5668_IRQ_POW_SAV_JD1_MASK (0x1 << 14) +#define RT5668_IRQ_POW_SAV_JD1_SHIFT 14 +#define RT5668_IRQ_POW_SAV_JD1_DIS (0x0 << 14) +#define RT5668_IRQ_POW_SAV_JD1_EN (0x1 << 14) + +/* IRQ Control 1 (0x00b6) */ +#define RT5668_EN_CB_JD_MASK (0x1 << 3) +#define RT5668_EN_CB_JD_SHIFT 3 +#define RT5668_EN_CB_JD_EN (0x1 << 3) +#define RT5668_EN_CB_JD_DIS (0x0 << 3) + +/* IRQ Control 3 (0x00b8) */ +#define RT5668_EN_IRQ_INLINE_MASK (0x1 << 6) +#define RT5668_EN_IRQ_INLINE_SHIFT 6 +#define RT5668_EN_IRQ_INLINE_BYP (0x0 << 6) +#define RT5668_EN_IRQ_INLINE_NOR (0x1 << 6) + +/* GPIO Control 1 (0x00c0) */ +#define RT5668_GP1_PIN_MASK (0x1 << 15) +#define RT5668_GP1_PIN_SHIFT 15 +#define RT5668_GP1_PIN_GPIO1 (0x0 << 15) +#define RT5668_GP1_PIN_IRQ (0x1 << 15) + +/* GPIO Control 2 (0x00c1) */ +#define RT5668_GP4_PIN_CONF_MASK (0x1 << 5) +#define RT5668_GP4_PIN_CONF_SHIFT 5 +#define RT5668_GP4_PIN_CONF_INPUT (0x0 << 5) +#define RT5668_GP4_PIN_CONF_OUTPUT (0x1 << 5) + +/* GPIO Control 2 (0x00c2) */ +#define RT5668_GP8_PIN_CONF_MASK (0x1 << 13) +#define RT5668_GP8_PIN_CONF_SHIFT 13 +#define RT5668_GP8_PIN_CONF_INPUT (0x0 << 13) +#define RT5668_GP8_PIN_CONF_OUTPUT (0x1 << 13) + +/* 4 Buttons Inline Command Function 1 (0x00df) */ +#define RT5668_4BTN_CLK_DEB_MASK (0x3 << 2) +#define RT5668_4BTN_CLK_DEB_SHIFT 2 +#define RT5668_4BTN_CLK_DEB_8MS (0x0 << 2) +#define RT5668_4BTN_CLK_DEB_16MS (0x1 << 2) +#define RT5668_4BTN_CLK_DEB_32MS (0x2 << 2) +#define RT5668_4BTN_CLK_DEB_65MS (0x3 << 2) + +/* Inline Command Function 6 (0x00e0) */ +#define RT5668_EN_4BTN_INL_MASK (0x1 << 15) +#define RT5668_EN_4BTN_INL_SHIFT 15 +#define RT5668_EN_4BTN_INL_DIS (0x0 << 15) +#define RT5668_EN_4BTN_INL_EN (0x1 << 15) +#define RT5668_RESET_4BTN_INL_MASK (0x1 << 14) +#define RT5668_RESET_4BTN_INL_SHIFT 14 +#define RT5668_RESET_4BTN_INL_RESET (0x0 << 14) +#define RT5668_RESET_4BTN_INL_NOR (0x1 << 14) + +/* Digital Misc Control (0x00fa) */ +#define RT5668_DIG_GATE_CTRL_MASK 0x1 +#define RT5668_DIG_GATE_CTRL_SHIFT (0) +#define RT5668_DIG_GATE_CTRL_DIS 0x0 +#define RT5668_DIG_GATE_CTRL_EN 0x1 + +/* Chopper and Clock control for DAC L (0x013a)*/ +#define RT5668_CKXEN_DAC1_MASK (0x1 << 13) +#define RT5668_CKXEN_DAC1_SHIFT 13 +#define RT5668_CKGEN_DAC1_MASK (0x1 << 12) +#define RT5668_CKGEN_DAC1_SHIFT 12 + +/* Chopper and Clock control for ADC (0x013b)*/ +#define RT5668_CKXEN_ADCC_MASK (0x1 << 13) +#define RT5668_CKXEN_ADCC_SHIFT 13 +#define RT5668_CKGEN_ADCC_MASK (0x1 << 12) +#define RT5668_CKGEN_ADCC_SHIFT 12 + +/* HP Behavior Logic Control 2 (0x01db) */ +#define RT5668_HP_SIG_SRC1_MASK (0x3) +#define RT5668_HP_SIG_SRC1_SHIFT 0 +#define RT5668_HP_SIG_SRC1_HP_DC (0x0) +#define RT5668_HP_SIG_SRC1_HP_CALIB (0x1) +#define RT5668_HP_SIG_SRC1_REG (0x2) +#define RT5668_HP_SIG_SRC1_SILENCE (0x3) + +/* RT5663 specific register */ +#define RT5663_HP_OUT_EN 0x0002 +#define RT5663_HP_LCH_DRE 0x0005 +#define RT5663_HP_RCH_DRE 0x0006 +#define RT5663_CALIB_BST 0x000a +#define RT5663_RECMIX 0x0010 +#define RT5663_SIL_DET_CTL 0x0015 +#define RT5663_PWR_SAV_SILDET 0x0016 +#define RT5663_SIDETONE_CTL 0x0018 +#define RT5663_STO1_DAC_DIG_VOL 0x0019 +#define RT5663_STO1_ADC_DIG_VOL 0x001c +#define RT5663_STO1_BOOST 0x001f +#define RT5663_HP_IMP_GAIN_1 0x0022 +#define RT5663_HP_IMP_GAIN_2 0x0023 +#define RT5663_STO1_ADC_MIXER 0x0026 +#define RT5663_AD_DA_MIXER 0x0029 +#define RT5663_STO_DAC_MIXER 0x002a +#define RT5663_DIG_SIDE_MIXER 0x002c +#define RT5663_BYPASS_STO_DAC 0x002d +#define RT5663_CALIB_REC_MIX 0x0040 +#define RT5663_PWR_DIG_1 0x0061 +#define RT5663_PWR_DIG_2 0x0062 +#define RT5663_PWR_ANLG_1 0x0063 +#define RT5663_PWR_ANLG_2 0x0064 +#define RT5663_PWR_ANLG_3 0x0065 +#define RT5663_PWR_MIXER 0x0066 +#define RT5663_SIG_CLK_DET 0x006b +#define RT5663_PRE_DIV_GATING_1 0x006e +#define RT5663_PRE_DIV_GATING_2 0x006f +#define RT5663_I2S1_SDP 0x0070 +#define RT5663_ADDA_CLK_1 0x0073 +#define RT5663_ADDA_RST 0x0074 +#define RT5663_FRAC_DIV_1 0x0075 +#define RT5663_FRAC_DIV_2 0x0076 +#define RT5663_TDM_1 0x0077 +#define RT5663_TDM_2 0x0078 +#define RT5663_TDM_3 0x0079 +#define RT5663_TDM_4 0x007a +#define RT5663_TDM_5 0x007b +#define RT5663_GLB_CLK 0x0080 +#define RT5663_PLL_1 0x0081 +#define RT5663_PLL_2 0x0082 +#define RT5663_ASRC_1 0x0083 +#define RT5663_ASRC_2 0x0084 +#define RT5663_ASRC_4 0x0086 +#define RT5663_DUMMY_REG 0x0087 +#define RT5663_ASRC_8 0x008a +#define RT5663_ASRC_9 0x008b +#define RT5663_ASRC_11 0x008c +#define RT5663_DEPOP_1 0x008e +#define RT5663_DEPOP_2 0x008f +#define RT5663_DEPOP_3 0x0090 +#define RT5663_HP_CHARGE_PUMP_1 0x0091 +#define RT5663_HP_CHARGE_PUMP_2 0x0092 +#define RT5663_MICBIAS_1 0x0093 +#define RT5663_RC_CLK 0x0094 +#define RT5663_ASRC_11_2 0x0097 +#define RT5663_DUMMY_REG_2 0x0098 +#define RT5663_REC_PATH_GAIN 0x009a +#define RT5663_AUTO_1MRC_CLK 0x009f +#define RT5663_ADC_EQ_1 0x00ae +#define RT5663_ADC_EQ_2 0x00af +#define RT5663_IRQ_1 0x00b6 +#define RT5663_IRQ_2 0x00b7 +#define RT5663_IRQ_3 0x00b8 +#define RT5663_IRQ_4 0x00ba +#define RT5663_IRQ_5 0x00bb +#define RT5663_INT_ST_1 0x00be +#define RT5663_INT_ST_2 0x00bf +#define RT5663_GPIO_1 0x00c0 +#define RT5663_GPIO_2 0x00c1 +#define RT5663_GPIO_STA 0x00c5 +#define RT5663_SIN_GEN_1 0x00cb +#define RT5663_SIN_GEN_2 0x00cc +#define RT5663_SIN_GEN_3 0x00cd +#define RT5663_SOF_VOL_ZC1 0x00d9 +#define RT5663_IL_CMD_1 0x00db +#define RT5663_IL_CMD_2 0x00dc +#define RT5663_IL_CMD_3 0x00dd +#define RT5663_IL_CMD_4 0x00de +#define RT5663_IL_CMD_5 0x00df +#define RT5663_IL_CMD_6 0x00e0 +#define RT5663_IL_CMD_7 0x00e1 +#define RT5663_IL_CMD_8 0x00e2 +#define RT5663_IL_CMD_PWRSAV1 0x00e4 +#define RT5663_IL_CMD_PWRSAV2 0x00e5 +#define RT5663_EM_JACK_TYPE_1 0x00e6 +#define RT5663_EM_JACK_TYPE_2 0x00e7 +#define RT5663_EM_JACK_TYPE_3 0x00e8 +#define RT5663_EM_JACK_TYPE_4 0x00e9 +#define RT5663_EM_JACK_TYPE_5 0x00ea +#define RT5663_EM_JACK_TYPE_6 0x00eb +#define RT5663_STO1_HPF_ADJ1 0x00ec +#define RT5663_STO1_HPF_ADJ2 0x00ed +#define RT5663_FAST_OFF_MICBIAS 0x00f4 +#define RT5663_JD_CTRL1 0x00f6 +#define RT5663_JD_CTRL2 0x00f8 +#define RT5663_DIG_MISC 0x00fa +#define RT5663_DIG_VOL_ZCD 0x0100 +#define RT5663_ANA_BIAS_CUR_1 0x0108 +#define RT5663_ANA_BIAS_CUR_2 0x0109 +#define RT5663_ANA_BIAS_CUR_3 0x010a +#define RT5663_ANA_BIAS_CUR_4 0x010b +#define RT5663_ANA_BIAS_CUR_5 0x010c +#define RT5663_ANA_BIAS_CUR_6 0x010d +#define RT5663_BIAS_CUR_5 0x010e +#define RT5663_BIAS_CUR_6 0x010f +#define RT5663_BIAS_CUR_7 0x0110 +#define RT5663_BIAS_CUR_8 0x0111 +#define RT5663_DACREF_LDO 0x0112 +#define RT5663_DUMMY_REG_3 0x0113 +#define RT5663_BIAS_CUR_9 0x0114 +#define RT5663_DUMMY_REG_4 0x0116 +#define RT5663_VREFADJ_OP 0x0117 +#define RT5663_VREF_RECMIX 0x0118 +#define RT5663_CHARGE_PUMP_1 0x0125 +#define RT5663_CHARGE_PUMP_1_2 0x0126 +#define RT5663_CHARGE_PUMP_1_3 0x0127 +#define RT5663_CHARGE_PUMP_2 0x0128 +#define RT5663_DIG_IN_PIN1 0x0132 +#define RT5663_PAD_DRV_CTL 0x0137 +#define RT5663_PLL_INT_REG 0x0139 +#define RT5663_CHOP_DAC_L 0x013a +#define RT5663_CHOP_ADC 0x013b +#define RT5663_CALIB_ADC 0x013c +#define RT5663_CHOP_DAC_R 0x013d +#define RT5663_DUMMY_CTL_DACLR 0x013e +#define RT5663_DUMMY_REG_5 0x0140 +#define RT5663_SOFT_RAMP 0x0141 +#define RT5663_TEST_MODE_1 0x0144 +#define RT5663_TEST_MODE_2 0x0145 +#define RT5663_TEST_MODE_3 0x0146 +#define RT5663_STO_DRE_1 0x0160 +#define RT5663_STO_DRE_2 0x0161 +#define RT5663_STO_DRE_3 0x0162 +#define RT5663_STO_DRE_4 0x0163 +#define RT5663_STO_DRE_5 0x0164 +#define RT5663_STO_DRE_6 0x0165 +#define RT5663_STO_DRE_7 0x0166 +#define RT5663_STO_DRE_8 0x0167 +#define RT5663_STO_DRE_9 0x0168 +#define RT5663_STO_DRE_10 0x0169 +#define RT5663_MIC_DECRO_1 0x0180 +#define RT5663_MIC_DECRO_2 0x0181 +#define RT5663_MIC_DECRO_3 0x0182 +#define RT5663_MIC_DECRO_4 0x0183 +#define RT5663_MIC_DECRO_5 0x0184 +#define RT5663_MIC_DECRO_6 0x0185 +#define RT5663_HP_DECRO_1 0x01b0 +#define RT5663_HP_DECRO_2 0x01b1 +#define RT5663_HP_DECRO_3 0x01b2 +#define RT5663_HP_DECRO_4 0x01b3 +#define RT5663_HP_DECOUP 0x01b4 +#define RT5663_HP_IMP_SEN_MAP8 0x01b5 +#define RT5663_HP_IMP_SEN_MAP9 0x01b6 +#define RT5663_HP_IMP_SEN_MAP10 0x01b7 +#define RT5663_HP_IMP_SEN_MAP11 0x01b8 +#define RT5663_HP_IMP_SEN_1 0x01c0 +#define RT5663_HP_IMP_SEN_2 0x01c1 +#define RT5663_HP_IMP_SEN_3 0x01c2 +#define RT5663_HP_IMP_SEN_4 0x01c3 +#define RT5663_HP_IMP_SEN_5 0x01c4 +#define RT5663_HP_IMP_SEN_6 0x01c5 +#define RT5663_HP_IMP_SEN_7 0x01c6 +#define RT5663_HP_IMP_SEN_8 0x01c7 +#define RT5663_HP_IMP_SEN_9 0x01c8 +#define RT5663_HP_IMP_SEN_10 0x01c9 +#define RT5663_HP_IMP_SEN_11 0x01ca +#define RT5663_HP_IMP_SEN_12 0x01cb +#define RT5663_HP_IMP_SEN_13 0x01cc +#define RT5663_HP_IMP_SEN_14 0x01cd +#define RT5663_HP_IMP_SEN_15 0x01ce +#define RT5663_HP_IMP_SEN_16 0x01cf +#define RT5663_HP_IMP_SEN_17 0x01d0 +#define RT5663_HP_IMP_SEN_18 0x01d1 +#define RT5663_HP_IMP_SEN_19 0x01d2 +#define RT5663_HP_IMPSEN_DIG5 0x01d3 +#define RT5663_HP_IMPSEN_MAP1 0x01d4 +#define RT5663_HP_IMPSEN_MAP2 0x01d5 +#define RT5663_HP_IMPSEN_MAP3 0x01d6 +#define RT5663_HP_IMPSEN_MAP4 0x01d7 +#define RT5663_HP_IMPSEN_MAP5 0x01d8 +#define RT5663_HP_IMPSEN_MAP7 0x01d9 +#define RT5663_HP_LOGIC_1 0x01da +#define RT5663_HP_LOGIC_2 0x01db +#define RT5663_HP_CALIB_1 0x01dd +#define RT5663_HP_CALIB_1_1 0x01de +#define RT5663_HP_CALIB_2 0x01df +#define RT5663_HP_CALIB_3 0x01e0 +#define RT5663_HP_CALIB_4 0x01e1 +#define RT5663_HP_CALIB_5 0x01e2 +#define RT5663_HP_CALIB_5_1 0x01e3 +#define RT5663_HP_CALIB_6 0x01e4 +#define RT5663_HP_CALIB_7 0x01e5 +#define RT5663_HP_CALIB_9 0x01e6 +#define RT5663_HP_CALIB_10 0x01e7 +#define RT5663_HP_CALIB_11 0x01e8 +#define RT5663_HP_CALIB_ST1 0x01ea +#define RT5663_HP_CALIB_ST2 0x01eb +#define RT5663_HP_CALIB_ST3 0x01ec +#define RT5663_HP_CALIB_ST4 0x01ed +#define RT5663_HP_CALIB_ST5 0x01ee +#define RT5663_HP_CALIB_ST6 0x01ef +#define RT5663_HP_CALIB_ST7 0x01f0 +#define RT5663_HP_CALIB_ST8 0x01f1 +#define RT5663_HP_CALIB_ST9 0x01f2 +#define RT5663_HP_AMP_DET 0x0200 +#define RT5663_DUMMY_REG_6 0x0201 +#define RT5663_HP_BIAS 0x0202 +#define RT5663_CBJ_1 0x0250 +#define RT5663_CBJ_2 0x0251 +#define RT5663_CBJ_3 0x0252 +#define RT5663_DUMMY_1 0x02fa +#define RT5663_DUMMY_2 0x02fb +#define RT5663_DUMMY_3 0x02fc +#define RT5663_ANA_JD 0x0300 +#define RT5663_ADC_LCH_LPF1_A1 0x03d0 +#define RT5663_ADC_RCH_LPF1_A1 0x03d1 +#define RT5663_ADC_LCH_LPF1_H0 0x03d2 +#define RT5663_ADC_RCH_LPF1_H0 0x03d3 +#define RT5663_ADC_LCH_BPF1_A1 0x03d4 +#define RT5663_ADC_RCH_BPF1_A1 0x03d5 +#define RT5663_ADC_LCH_BPF1_A2 0x03d6 +#define RT5663_ADC_RCH_BPF1_A2 0x03d7 +#define RT5663_ADC_LCH_BPF1_H0 0x03d8 +#define RT5663_ADC_RCH_BPF1_H0 0x03d9 +#define RT5663_ADC_LCH_BPF2_A1 0x03da +#define RT5663_ADC_RCH_BPF2_A1 0x03db +#define RT5663_ADC_LCH_BPF2_A2 0x03dc +#define RT5663_ADC_RCH_BPF2_A2 0x03dd +#define RT5663_ADC_LCH_BPF2_H0 0x03de +#define RT5663_ADC_RCH_BPF2_H0 0x03df +#define RT5663_ADC_LCH_BPF3_A1 0x03e0 +#define RT5663_ADC_RCH_BPF3_A1 0x03e1 +#define RT5663_ADC_LCH_BPF3_A2 0x03e2 +#define RT5663_ADC_RCH_BPF3_A2 0x03e3 +#define RT5663_ADC_LCH_BPF3_H0 0x03e4 +#define RT5663_ADC_RCH_BPF3_H0 0x03e5 +#define RT5663_ADC_LCH_BPF4_A1 0x03e6 +#define RT5663_ADC_RCH_BPF4_A1 0x03e7 +#define RT5663_ADC_LCH_BPF4_A2 0x03e8 +#define RT5663_ADC_RCH_BPF4_A2 0x03e9 +#define RT5663_ADC_LCH_BPF4_H0 0x03ea +#define RT5663_ADC_RCH_BPF4_H0 0x03eb +#define RT5663_ADC_LCH_HPF1_A1 0x03ec +#define RT5663_ADC_RCH_HPF1_A1 0x03ed +#define RT5663_ADC_LCH_HPF1_H0 0x03ee +#define RT5663_ADC_RCH_HPF1_H0 0x03ef +#define RT5663_ADC_EQ_PRE_VOL_L 0x03f0 +#define RT5663_ADC_EQ_PRE_VOL_R 0x03f1 +#define RT5663_ADC_EQ_POST_VOL_L 0x03f2 +#define RT5663_ADC_EQ_POST_VOL_R 0x03f3 + +/* RT5663: RECMIX Control (0x0010) */ +#define RT5663_RECMIX1_BST1_MASK (0x1) +#define RT5663_RECMIX1_BST1_SHIFT 0 +#define RT5663_RECMIX1_BST1_ON (0x0) +#define RT5663_RECMIX1_BST1_OFF (0x1) + +/* RT5663: Bypass Stereo1 DAC Mixer Control (0x002d) */ +#define RT5663_DACL1_SRC_MASK (0x1 << 3) +#define RT5663_DACL1_SRC_SHIFT 3 +#define RT5663_DACR1_SRC_MASK (0x1 << 2) +#define RT5663_DACR1_SRC_SHIFT 2 + +/* RT5663: TDM control 2 (0x0078) */ +#define RT5663_DATA_SWAP_ADCDAT1_MASK (0x3 << 14) +#define RT5663_DATA_SWAP_ADCDAT1_SHIFT 14 +#define RT5663_DATA_SWAP_ADCDAT1_LR (0x0 << 14) +#define RT5663_DATA_SWAP_ADCDAT1_RL (0x1 << 14) +#define RT5663_DATA_SWAP_ADCDAT1_LL (0x2 << 14) +#define RT5663_DATA_SWAP_ADCDAT1_RR (0x3 << 14) + +/* RT5663: TDM control 5 (0x007b) */ +#define RT5663_TDM_LENGTN_MASK (0x3) +#define RT5663_TDM_LENGTN_SHIFT 0 +#define RT5663_TDM_LENGTN_16 (0x0) +#define RT5663_TDM_LENGTN_20 (0x1) +#define RT5663_TDM_LENGTN_24 (0x2) +#define RT5663_TDM_LENGTN_32 (0x3) + +/* RT5663: Global Clock Control (0x0080) */ +#define RT5663_SCLK_SRC_MASK (0x3 << 14) +#define RT5663_SCLK_SRC_SHIFT 14 +#define RT5663_SCLK_SRC_MCLK (0x0 << 14) +#define RT5663_SCLK_SRC_PLL1 (0x1 << 14) +#define RT5663_SCLK_SRC_RCCLK (0x2 << 14) +#define RT5663_PLL1_SRC_MASK (0x7 << 11) +#define RT5663_PLL1_SRC_SHIFT 11 +#define RT5663_PLL1_SRC_MCLK (0x0 << 11) +#define RT5663_PLL1_SRC_BCLK1 (0x1 << 11) + +/* PLL tracking mode 1 (0x0083) */ +#define RT5663_I2S1_ASRC_MASK (0x1 << 11) +#define RT5663_I2S1_ASRC_SHIFT 11 +#define RT5663_DAC_STO1_ASRC_MASK (0x1 << 10) +#define RT5663_DAC_STO1_ASRC_SHIFT 10 +#define RT5663_ADC_STO1_ASRC_MASK (0x1 << 3) +#define RT5663_ADC_STO1_ASRC_SHIFT 3 + +/* PLL tracking mode 2 (0x0084)*/ +#define RT5663_DA_STO1_TRACK_MASK (0x7 << 12) +#define RT5663_DA_STO1_TRACK_SHIFT 12 +#define RT5663_DA_STO1_TRACK_SYSCLK (0x0 << 12) +#define RT5663_DA_STO1_TRACK_I2S1 (0x1 << 12) +#define RT5663_AD_STO1_TRACK_MASK (0x7) +#define RT5663_AD_STO1_TRACK_SHIFT 0 +#define RT5663_AD_STO1_TRACK_SYSCLK (0x0) +#define RT5663_AD_STO1_TRACK_I2S1 (0x1) + +/* RT5663: HPOUT Charge pump control 1 (0x0091) */ +#define RT5663_SI_HP_MASK (0x1 << 12) +#define RT5663_SI_HP_SHIFT 12 +#define RT5663_SI_HP_EN (0x1 << 12) +#define RT5663_SI_HP_DIS (0x0 << 12) + +/* RT5663: GPIO Control 2 (0x00b6) */ +#define RT5663_GP1_PIN_CONF_MASK (0x1 << 2) +#define RT5663_GP1_PIN_CONF_SHIFT 2 +#define RT5663_GP1_PIN_CONF_OUTPUT (0x1 << 2) +#define RT5663_GP1_PIN_CONF_INPUT (0x0 << 2) + +/* RT5663: GPIO Control 2 (0x00b7) */ +#define RT5663_EN_IRQ_INLINE_MASK (0x1 << 3) +#define RT5663_EN_IRQ_INLINE_SHIFT 3 +#define RT5663_EN_IRQ_INLINE_NOR (0x1 << 3) +#define RT5663_EN_IRQ_INLINE_BYP (0x0 << 3) + +/* RT5663: IRQ Control 1 (0x00c1) */ +#define RT5663_EN_IRQ_JD1_MASK (0x1 << 6) +#define RT5663_EN_IRQ_JD1_SHIFT 6 +#define RT5663_EN_IRQ_JD1_EN (0x1 << 6) +#define RT5663_EN_IRQ_JD1_DIS (0x0 << 6) + +/* RT5663: Inline Command Function 2 (0x00dc) */ +#define RT5663_PWR_MIC_DET_MASK (0x1) +#define RT5663_PWR_MIC_DET_SHIFT 0 +#define RT5663_PWR_MIC_DET_ON (0x1) +#define RT5663_PWR_MIC_DET_OFF (0x0) + +/* RT5663: Embeeded Jack and Type Detection Control 1 (0x00e6)*/ +#define RT5663_CBJ_DET_MASK (0x1 << 15) +#define RT5663_CBJ_DET_SHIFT 15 +#define RT5663_CBJ_DET_DIS (0x0 << 15) +#define RT5663_CBJ_DET_EN (0x1 << 15) +#define RT5663_EXT_JD_MASK (0x1 << 11) +#define RT5663_EXT_JD_SHIFT 11 +#define RT5663_EXT_JD_EN (0x1 << 11) +#define RT5663_EXT_JD_DIS (0x0 << 11) +#define RT5663_POL_EXT_JD_MASK (0x1 << 10) +#define RT5663_POL_EXT_JD_SHIFT 10 +#define RT5663_POL_EXT_JD_EN (0x1 << 10) +#define RT5663_POL_EXT_JD_DIS (0x0 << 10) + +/* RT5663: DACREF LDO Control (0x0112)*/ +#define RT5663_PWR_LDO_DACREFL_MASK (0x1 << 9) +#define RT5663_PWR_LDO_DACREFL_SHIFT 9 +#define RT5663_PWR_LDO_DACREFR_MASK (0x1 << 1) +#define RT5663_PWR_LDO_DACREFR_SHIFT 1 + +/* RT5663: Stereo Dynamic Range Enhancement Control 9 (0x0168, 0x0169)*/ +#define RT5663_DRE_GAIN_HP_MASK (0x1f) +#define RT5663_DRE_GAIN_HP_SHIFT 0 + +/* RT5663: Combo Jack Control (0x0250) */ +#define RT5663_INBUF_CBJ_BST1_MASK (0x1 << 11) +#define RT5663_INBUF_CBJ_BST1_SHIFT 11 +#define RT5663_INBUF_CBJ_BST1_ON (0x1 << 11) +#define RT5663_INBUF_CBJ_BST1_OFF (0x0 << 11) +#define RT5663_CBJ_SENSE_BST1_MASK (0x1 << 10) +#define RT5663_CBJ_SENSE_BST1_SHIFT 10 +#define RT5663_CBJ_SENSE_BST1_L (0x1 << 10) +#define RT5663_CBJ_SENSE_BST1_R (0x0 << 10) + +/* RT5663: Combo Jack Control (0x0251) */ +#define RT5663_GAIN_BST1_MASK (0xf) +#define RT5663_GAIN_BST1_SHIFT 0 + +/* RT5663: Dummy register 1 (0x02fa) */ +#define RT5663_EMB_CLK_MASK (0x1 << 9) +#define RT5663_EMB_CLK_SHIFT 9 +#define RT5663_EMB_CLK_EN (0x1 << 9) +#define RT5663_EMB_CLK_DIS (0x0 << 9) +#define RT5663_HPA_CPL_BIAS_MASK (0x7 << 6) +#define RT5663_HPA_CPL_BIAS_SHIFT 6 +#define RT5663_HPA_CPL_BIAS_0_5 (0x0 << 6) +#define RT5663_HPA_CPL_BIAS_1 (0x1 << 6) +#define RT5663_HPA_CPL_BIAS_2 (0x2 << 6) +#define RT5663_HPA_CPL_BIAS_3 (0x3 << 6) +#define RT5663_HPA_CPL_BIAS_4_1 (0x4 << 6) +#define RT5663_HPA_CPL_BIAS_4_2 (0x5 << 6) +#define RT5663_HPA_CPL_BIAS_6 (0x6 << 6) +#define RT5663_HPA_CPL_BIAS_8 (0x7 << 6) +#define RT5663_HPA_CPR_BIAS_MASK (0x7 << 3) +#define RT5663_HPA_CPR_BIAS_SHIFT 3 +#define RT5663_HPA_CPR_BIAS_0_5 (0x0 << 3) +#define RT5663_HPA_CPR_BIAS_1 (0x1 << 3) +#define RT5663_HPA_CPR_BIAS_2 (0x2 << 3) +#define RT5663_HPA_CPR_BIAS_3 (0x3 << 3) +#define RT5663_HPA_CPR_BIAS_4_1 (0x4 << 3) +#define RT5663_HPA_CPR_BIAS_4_2 (0x5 << 3) +#define RT5663_HPA_CPR_BIAS_6 (0x6 << 3) +#define RT5663_HPA_CPR_BIAS_8 (0x7 << 3) +#define RT5663_DUMMY_BIAS_MASK (0x7) +#define RT5663_DUMMY_BIAS_SHIFT 0 +#define RT5663_DUMMY_BIAS_0_5 (0x0) +#define RT5663_DUMMY_BIAS_1 (0x1) +#define RT5663_DUMMY_BIAS_2 (0x2) +#define RT5663_DUMMY_BIAS_3 (0x3) +#define RT5663_DUMMY_BIAS_4_1 (0x4) +#define RT5663_DUMMY_BIAS_4_2 (0x5) +#define RT5663_DUMMY_BIAS_6 (0x6) +#define RT5663_DUMMY_BIAS_8 (0x7) + + +/* System Clock Source */ +enum { + RT5663_SCLK_S_MCLK, + RT5663_SCLK_S_PLL1, + RT5663_SCLK_S_RCCLK, +}; + +/* PLL1 Source */ +enum { + RT5663_PLL1_S_MCLK, + RT5663_PLL1_S_BCLK1, +}; + +enum { + RT5663_AIF, + RT5663_AIFS, +}; + +/* asrc clock source */ +enum { + RT5663_CLK_SEL_SYS = 0x0, + RT5663_CLK_SEL_I2S1_ASRC = 0x1, +}; + +/* filter mask */ +enum { + RT5663_DA_STEREO_FILTER = 0x1, + RT5663_AD_STEREO_FILTER = 0x2, +}; + +int rt5663_set_jack_detect(struct snd_soc_codec *codec, + struct snd_soc_jack *hs_jack); +int rt5663_sel_asrc_clk_src(struct snd_soc_codec *codec, + unsigned int filter_mask, unsigned int clk_src); + +#endif /* __RT5663_H__ */ diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 8ef467f..49caf13 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2777,12 +2777,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5670 = { .resume = rt5670_resume, .set_bias_level = rt5670_set_bias_level, .idle_bias_off = true, - .controls = rt5670_snd_controls, - .num_controls = ARRAY_SIZE(rt5670_snd_controls), - .dapm_widgets = rt5670_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5670_dapm_widgets), - .dapm_routes = rt5670_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5670_dapm_routes), + .component_driver = { + .controls = rt5670_snd_controls, + .num_controls = ARRAY_SIZE(rt5670_snd_controls), + .dapm_widgets = rt5670_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5670_dapm_widgets), + .dapm_routes = rt5670_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5670_dapm_routes), + }, }; static const struct regmap_config rt5670_regmap = { diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index da9483c..abc802a 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ +#include <linux/acpi.h> #include <linux/fs.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -40,6 +41,15 @@ #define RT5677_PR_BASE (RT5677_PR_RANGE_BASE + (0 * RT5677_PR_SPACING)) +/* GPIO indexes defined by ACPI */ +enum { + RT5677_GPIO_PLUG_DET = 0, + RT5677_GPIO_MIC_PRESENT_L = 1, + RT5677_GPIO_HOTWORD_DET_L = 2, + RT5677_GPIO_DSP_INT = 3, + RT5677_GPIO_HP_AMP_SHDN_L = 4, +}; + static const struct regmap_range_cfg rt5677_ranges[] = { { .name = "PR", @@ -4657,7 +4667,7 @@ static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset) return regmap_irq_get_virq(data, irq); } -static struct gpio_chip rt5677_template_chip = { +static const struct gpio_chip rt5677_template_chip = { .label = "rt5677", .owner = THIS_MODULE, .direction_output = rt5677_gpio_direction_out, @@ -4974,12 +4984,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5677 = { .resume = rt5677_resume, .set_bias_level = rt5677_set_bias_level, .idle_bias_off = true, - .controls = rt5677_snd_controls, - .num_controls = ARRAY_SIZE(rt5677_snd_controls), - .dapm_widgets = rt5677_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5677_dapm_widgets), - .dapm_routes = rt5677_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5677_dapm_routes), + .component_driver = { + .controls = rt5677_snd_controls, + .num_controls = ARRAY_SIZE(rt5677_snd_controls), + .dapm_widgets = rt5677_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5677_dapm_widgets), + .dapm_routes = rt5677_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5677_dapm_routes), + }, }; static const struct regmap_config rt5677_regmap_physical = { @@ -5018,10 +5030,47 @@ static const struct regmap_config rt5677_regmap = { static const struct i2c_device_id rt5677_i2c_id[] = { { "rt5677", RT5677 }, { "rt5676", RT5676 }, + { "RT5677CE:00", RT5677 }, { } }; MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); +static const struct acpi_gpio_params plug_det_gpio = { RT5677_GPIO_PLUG_DET, 0, false }; +static const struct acpi_gpio_params mic_present_gpio = { RT5677_GPIO_MIC_PRESENT_L, 0, false }; +static const struct acpi_gpio_params headphone_enable_gpio = { RT5677_GPIO_HP_AMP_SHDN_L, 0, false }; + +static const struct acpi_gpio_mapping bdw_rt5677_gpios[] = { + { "plug-det-gpios", &plug_det_gpio, 1 }, + { "mic-present-gpios", &mic_present_gpio, 1 }, + { "headphone-enable-gpios", &headphone_enable_gpio, 1 }, + { NULL }, +}; + +static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677, + struct device *dev) +{ + int ret; + u32 val; + + ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), + bdw_rt5677_gpios); + if (ret) + dev_warn(dev, "Failed to add driver gpios\n"); + + if (!device_property_read_u32(dev, "DCLK", &val)) + rt5677->pdata.dmic2_clk_pin = val; + + rt5677->pdata.in1_diff = device_property_read_bool(dev, "IN1"); + rt5677->pdata.in2_diff = device_property_read_bool(dev, "IN2"); + rt5677->pdata.lout1_diff = device_property_read_bool(dev, "OUT1"); + rt5677->pdata.lout2_diff = device_property_read_bool(dev, "OUT2"); + rt5677->pdata.lout3_diff = device_property_read_bool(dev, "OUT3"); + + device_property_read_u32(dev, "JD1", &rt5677->pdata.jd1_gpio); + device_property_read_u32(dev, "JD2", &rt5677->pdata.jd2_gpio); + device_property_read_u32(dev, "JD3", &rt5677->pdata.jd3_gpio); +} + static void rt5677_read_device_properties(struct rt5677_priv *rt5677, struct device *dev) { @@ -5127,8 +5176,12 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, if (pdata) rt5677->pdata = *pdata; - else + else if (i2c->dev.of_node) rt5677_read_device_properties(rt5677, &i2c->dev); + else if (ACPI_HANDLE(&i2c->dev)) + rt5677_read_acpi_properties(rt5677, &i2c->dev); + else + return -EINVAL; /* pow-ldo2 and reset are optional. The codec pins may be statically * connected on the board without gpios. If the gpio device property diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 527b759..1589325 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -411,6 +411,8 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { 0, 8, 0x7f, 1, headphone_volume), + SOC_SINGLE("Headphone Playback Switch", SGTL5000_CHIP_ANA_CTRL, + 4, 1, 1), SOC_SINGLE("Headphone Playback ZC Switch", SGTL5000_CHIP_ANA_CTRL, 5, 1, 0), @@ -423,6 +425,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { SGTL5000_LINE_OUT_VOL_RIGHT_SHIFT, 0x1f, 1, lineout_volume), + SOC_SINGLE("Lineout Playback Switch", SGTL5000_CHIP_ANA_CTRL, 8, 1, 1), }; /* mute the codec used by alsa core */ @@ -1151,12 +1154,14 @@ static struct snd_soc_codec_driver sgtl5000_driver = { .remove = sgtl5000_remove, .set_bias_level = sgtl5000_set_bias_level, .suspend_bias_off = true, - .controls = sgtl5000_snd_controls, - .num_controls = ARRAY_SIZE(sgtl5000_snd_controls), - .dapm_widgets = sgtl5000_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sgtl5000_dapm_widgets), - .dapm_routes = sgtl5000_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes), + .component_driver = { + .controls = sgtl5000_snd_controls, + .num_controls = ARRAY_SIZE(sgtl5000_snd_controls), + .dapm_widgets = sgtl5000_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sgtl5000_dapm_widgets), + .dapm_routes = sgtl5000_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes), + }, }; static const struct regmap_config sgtl5000_regmap = { diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index a8402d0..5344f4a 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c @@ -238,10 +238,12 @@ static struct regmap *si476x_get_regmap(struct device *dev) static struct snd_soc_codec_driver soc_codec_dev_si476x = { .get_regmap = si476x_get_regmap, - .dapm_widgets = si476x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(si476x_dapm_widgets), - .dapm_routes = si476x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(si476x_dapm_routes), + .component_driver = { + .dapm_widgets = si476x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(si476x_dapm_widgets), + .dapm_routes = si476x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(si476x_dapm_routes), + }, }; static int si476x_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 3a7de01..eae54c3 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c @@ -888,12 +888,14 @@ static struct snd_soc_codec_driver sn95031_codec = { .set_bias_level = sn95031_set_vaud_bias, .idle_bias_off = true, - .controls = sn95031_snd_controls, - .num_controls = ARRAY_SIZE(sn95031_snd_controls), - .dapm_widgets = sn95031_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sn95031_dapm_widgets), - .dapm_routes = sn95031_audio_map, - .num_dapm_routes = ARRAY_SIZE(sn95031_audio_map), + .component_driver = { + .controls = sn95031_snd_controls, + .num_controls = ARRAY_SIZE(sn95031_snd_controls), + .dapm_widgets = sn95031_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sn95031_dapm_widgets), + .dapm_routes = sn95031_audio_map, + .num_dapm_routes = ARRAY_SIZE(sn95031_audio_map), + }, }; static int sn95031_device_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c index 3ec41ccb..234f87b 100644 --- a/sound/soc/codecs/spdif_receiver.c +++ b/sound/soc/codecs/spdif_receiver.c @@ -38,10 +38,12 @@ static const struct snd_soc_dapm_route dir_routes[] = { SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE) static struct snd_soc_codec_driver soc_codec_spdif_dir = { - .dapm_widgets = dir_widgets, - .num_dapm_widgets = ARRAY_SIZE(dir_widgets), - .dapm_routes = dir_routes, - .num_dapm_routes = ARRAY_SIZE(dir_routes), + .component_driver = { + .dapm_widgets = dir_widgets, + .num_dapm_widgets = ARRAY_SIZE(dir_widgets), + .dapm_routes = dir_routes, + .num_dapm_routes = ARRAY_SIZE(dir_routes), + }, }; static struct snd_soc_dai_driver dir_stub_dai = { diff --git a/sound/soc/codecs/spdif_transmitter.c b/sound/soc/codecs/spdif_transmitter.c index ef634a9..ee36753 100644 --- a/sound/soc/codecs/spdif_transmitter.c +++ b/sound/soc/codecs/spdif_transmitter.c @@ -38,10 +38,12 @@ static const struct snd_soc_dapm_route dit_routes[] = { }; static struct snd_soc_codec_driver soc_codec_spdif_dit = { - .dapm_widgets = dit_widgets, - .num_dapm_widgets = ARRAY_SIZE(dit_widgets), - .dapm_routes = dit_routes, - .num_dapm_routes = ARRAY_SIZE(dit_routes), + .component_driver = { + .dapm_widgets = dit_widgets, + .num_dapm_widgets = ARRAY_SIZE(dit_widgets), + .dapm_routes = dit_routes, + .num_dapm_routes = ARRAY_SIZE(dit_routes), + }, }; static struct snd_soc_dai_driver dit_stub_dai = { diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index e2e0bfa..38a85f3 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c @@ -715,12 +715,14 @@ static struct snd_soc_codec_driver ssm2518_codec_driver = { .set_sysclk = ssm2518_set_sysclk, .idle_bias_off = true, - .controls = ssm2518_snd_controls, - .num_controls = ARRAY_SIZE(ssm2518_snd_controls), - .dapm_widgets = ssm2518_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ssm2518_dapm_widgets), - .dapm_routes = ssm2518_routes, - .num_dapm_routes = ARRAY_SIZE(ssm2518_routes), + .component_driver = { + .controls = ssm2518_snd_controls, + .num_controls = ARRAY_SIZE(ssm2518_snd_controls), + .dapm_widgets = ssm2518_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ssm2518_dapm_widgets), + .dapm_routes = ssm2518_routes, + .num_dapm_routes = ARRAY_SIZE(ssm2518_routes), + }, }; static const struct regmap_config ssm2518_regmap_config = { diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 4452fea..993bde2 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -597,12 +597,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { .set_bias_level = ssm2602_set_bias_level, .suspend_bias_off = true, - .controls = ssm260x_snd_controls, - .num_controls = ARRAY_SIZE(ssm260x_snd_controls), - .dapm_widgets = ssm260x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ssm260x_dapm_widgets), - .dapm_routes = ssm260x_routes, - .num_dapm_routes = ARRAY_SIZE(ssm260x_routes), + .component_driver = { + .controls = ssm260x_snd_controls, + .num_controls = ARRAY_SIZE(ssm260x_snd_controls), + .dapm_widgets = ssm260x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ssm260x_dapm_widgets), + .dapm_routes = ssm260x_routes, + .num_dapm_routes = ARRAY_SIZE(ssm260x_routes), + }, }; static bool ssm2602_register_volatile(struct device *dev, unsigned int reg) diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c index 080c78e..2bb5a11 100644 --- a/sound/soc/codecs/ssm4567.c +++ b/sound/soc/codecs/ssm4567.c @@ -421,12 +421,14 @@ static struct snd_soc_codec_driver ssm4567_codec_driver = { .set_bias_level = ssm4567_set_bias_level, .idle_bias_off = true, - .controls = ssm4567_snd_controls, - .num_controls = ARRAY_SIZE(ssm4567_snd_controls), - .dapm_widgets = ssm4567_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ssm4567_dapm_widgets), - .dapm_routes = ssm4567_routes, - .num_dapm_routes = ARRAY_SIZE(ssm4567_routes), + .component_driver = { + .controls = ssm4567_snd_controls, + .num_controls = ARRAY_SIZE(ssm4567_snd_controls), + .dapm_widgets = ssm4567_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ssm4567_dapm_widgets), + .dapm_routes = ssm4567_routes, + .num_dapm_routes = ARRAY_SIZE(ssm4567_routes), + }, }; static const struct regmap_config ssm4567_regmap_config = { diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index a9844b2..0790ae8 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -991,12 +991,14 @@ static const struct snd_soc_codec_driver sta32x_codec = { .remove = sta32x_remove, .set_bias_level = sta32x_set_bias_level, .suspend_bias_off = true, - .controls = sta32x_snd_controls, - .num_controls = ARRAY_SIZE(sta32x_snd_controls), - .dapm_widgets = sta32x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sta32x_dapm_widgets), - .dapm_routes = sta32x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), + .component_driver = { + .controls = sta32x_snd_controls, + .num_controls = ARRAY_SIZE(sta32x_snd_controls), + .dapm_widgets = sta32x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sta32x_dapm_widgets), + .dapm_routes = sta32x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), + }, }; static const struct regmap_config sta32x_regmap = { diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index 33a4612..9644c20 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c @@ -1057,12 +1057,14 @@ static const struct snd_soc_codec_driver sta350_codec = { .remove = sta350_remove, .set_bias_level = sta350_set_bias_level, .suspend_bias_off = true, - .controls = sta350_snd_controls, - .num_controls = ARRAY_SIZE(sta350_snd_controls), - .dapm_widgets = sta350_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sta350_dapm_widgets), - .dapm_routes = sta350_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(sta350_dapm_routes), + .component_driver = { + .controls = sta350_snd_controls, + .num_controls = ARRAY_SIZE(sta350_snd_controls), + .dapm_widgets = sta350_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sta350_dapm_widgets), + .dapm_routes = sta350_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(sta350_dapm_routes), + }, }; static const struct regmap_config sta350_regmap = { diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 2cdaca9..d4b384e 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -317,8 +317,10 @@ static const struct snd_soc_codec_driver sta529_codec_driver = { .set_bias_level = sta529_set_bias_level, .suspend_bias_off = true, - .controls = sta529_snd_controls, - .num_controls = ARRAY_SIZE(sta529_snd_controls), + .component_driver = { + .controls = sta529_snd_controls, + .num_controls = ARRAY_SIZE(sta529_snd_controls), + }, }; static const struct regmap_config sta529_regmap = { diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 0945c51..27f30d3 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -85,10 +85,10 @@ static SOC_ENUM_SINGLE_DECL(stac9766_boost2_enum, static SOC_ENUM_SINGLE_DECL(stac9766_stereo_mic_enum, AC97_STAC_STEREO_MIC, 2, stac9766_stereo_mic); -static const DECLARE_TLV_DB_LINEAR(master_tlv, -4600, 0); -static const DECLARE_TLV_DB_LINEAR(record_tlv, 0, 2250); -static const DECLARE_TLV_DB_LINEAR(beep_tlv, -4500, 0); -static const DECLARE_TLV_DB_LINEAR(mix_tlv, -3450, 1200); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(master_tlv, -4650, 150, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(record_tlv, 0, 150, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(beep_tlv, -4500, 300, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(mix_tlv, -3450, 150, 0); static const struct snd_kcontrol_new stac9766_snd_ac97_controls[] = { SOC_DOUBLE_TLV("Speaker Volume", AC97_MASTER, 8, 0, 31, 1, master_tlv), @@ -320,8 +320,10 @@ static int stac9766_codec_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_stac9766 = { - .controls = stac9766_snd_ac97_controls, - .num_controls = ARRAY_SIZE(stac9766_snd_ac97_controls), + .component_driver = { + .controls = stac9766_snd_ac97_controls, + .num_controls = ARRAY_SIZE(stac9766_snd_ac97_controls), + }, .write = stac9766_ac97_write, .read = stac9766_ac97_read, .set_bias_level = stac9766_set_bias_level, diff --git a/sound/soc/codecs/sti-sas.c b/sound/soc/codecs/sti-sas.c index 160d61a..7b31ee9 100644 --- a/sound/soc/codecs/sti-sas.c +++ b/sound/soc/codecs/sti-sas.c @@ -591,11 +591,11 @@ static int sti_sas_driver_probe(struct platform_device *pdev) sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].ops = drvdata->dev_data->dac_ops; /* Set dapms*/ - sti_sas_driver.dapm_widgets = drvdata->dev_data->dapm_widgets; - sti_sas_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets; + sti_sas_driver.component_driver.dapm_widgets = drvdata->dev_data->dapm_widgets; + sti_sas_driver.component_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets; - sti_sas_driver.dapm_routes = drvdata->dev_data->dapm_routes; - sti_sas_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes; + sti_sas_driver.component_driver.dapm_routes = drvdata->dev_data->dapm_routes; + sti_sas_driver.component_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes; /* Store context */ dev_set_drvdata(&pdev->dev, drvdata); diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index cc1d398..baf455e 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -667,12 +667,14 @@ static struct snd_soc_codec_driver soc_codec_dev_tas2552 = { .resume = tas2552_resume, .ignore_pmdown_time = true, - .controls = tas2552_snd_controls, - .num_controls = ARRAY_SIZE(tas2552_snd_controls), - .dapm_widgets = tas2552_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tas2552_dapm_widgets), - .dapm_routes = tas2552_audio_map, - .num_dapm_routes = ARRAY_SIZE(tas2552_audio_map), + .component_driver = { + .controls = tas2552_snd_controls, + .num_controls = ARRAY_SIZE(tas2552_snd_controls), + .dapm_widgets = tas2552_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas2552_dapm_widgets), + .dapm_routes = tas2552_audio_map, + .num_dapm_routes = ARRAY_SIZE(tas2552_audio_map), + }, }; static const struct regmap_config tas2552_regmap_config = { diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index d49d25d..b7de857 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c @@ -387,7 +387,7 @@ static int tas5086_hw_params(struct snd_pcm_substream *substream, val = index_in_array(tas5086_ratios, ARRAY_SIZE(tas5086_ratios), priv->mclk / priv->rate); if (val < 0) { - dev_err(codec->dev, "Inavlid MCLK / Fs ratio\n"); + dev_err(codec->dev, "Invalid MCLK / Fs ratio\n"); return -EINVAL; } @@ -890,12 +890,14 @@ static struct snd_soc_codec_driver soc_codec_dev_tas5086 = { .remove = tas5086_remove, .suspend = tas5086_soc_suspend, .resume = tas5086_soc_resume, - .controls = tas5086_controls, - .num_controls = ARRAY_SIZE(tas5086_controls), - .dapm_widgets = tas5086_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tas5086_dapm_widgets), - .dapm_routes = tas5086_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(tas5086_dapm_routes), + .component_driver = { + .controls = tas5086_controls, + .num_controls = ARRAY_SIZE(tas5086_controls), + .dapm_widgets = tas5086_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas5086_dapm_widgets), + .dapm_routes = tas5086_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tas5086_dapm_routes), + }, }; static const struct i2c_device_id tas5086_i2c_id[] = { diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index d8baca3..df5e5cb 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -658,10 +658,12 @@ static const struct snd_soc_codec_driver tas571x_codec = { .set_bias_level = tas571x_set_bias_level, .idle_bias_off = true, - .dapm_widgets = tas571x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tas571x_dapm_widgets), - .dapm_routes = tas571x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(tas571x_dapm_routes), + .component_driver = { + .dapm_widgets = tas571x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas571x_dapm_widgets), + .dapm_routes = tas571x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tas571x_dapm_routes), + }, }; static struct snd_soc_dai_driver tas571x_dai = { @@ -754,8 +756,8 @@ static int tas571x_i2c_probe(struct i2c_client *client, memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver)); - priv->codec_driver.controls = priv->chip->controls; - priv->codec_driver.num_controls = priv->chip->num_controls; + priv->codec_driver.component_driver.controls = priv->chip->controls; + priv->codec_driver.component_driver.num_controls = priv->chip->num_controls; if (priv->chip->vol_reg_size == 2) { /* diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c index f54fb46..c65b917 100644 --- a/sound/soc/codecs/tas5720.c +++ b/sound/soc/codecs/tas5720.c @@ -489,12 +489,14 @@ static struct snd_soc_codec_driver soc_codec_dev_tas5720 = { .suspend = tas5720_suspend, .resume = tas5720_resume, - .controls = tas5720_snd_controls, - .num_controls = ARRAY_SIZE(tas5720_snd_controls), - .dapm_widgets = tas5720_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets), - .dapm_routes = tas5720_audio_map, - .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map), + .component_driver = { + .controls = tas5720_snd_controls, + .num_controls = ARRAY_SIZE(tas5720_snd_controls), + .dapm_widgets = tas5720_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets), + .dapm_routes = tas5720_audio_map, + .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map), + }, }; /* PCM rates supported by the TAS5720 driver */ diff --git a/sound/soc/codecs/tfa9879.c b/sound/soc/codecs/tfa9879.c index cb5310d..95e0a7a 100644 --- a/sound/soc/codecs/tfa9879.c +++ b/sound/soc/codecs/tfa9879.c @@ -231,13 +231,14 @@ static const struct snd_soc_dapm_route tfa9879_dapm_routes[] = { }; static const struct snd_soc_codec_driver tfa9879_codec = { - .controls = tfa9879_controls, - .num_controls = ARRAY_SIZE(tfa9879_controls), - - .dapm_widgets = tfa9879_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tfa9879_dapm_widgets), - .dapm_routes = tfa9879_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(tfa9879_dapm_routes), + .component_driver = { + .controls = tfa9879_controls, + .num_controls = ARRAY_SIZE(tfa9879_controls), + .dapm_widgets = tfa9879_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tfa9879_dapm_widgets), + .dapm_routes = tfa9879_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tfa9879_dapm_routes), + }, }; static const struct regmap_config tfa9879_regmap = { diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index cd8c02b..410cae0 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -583,12 +583,14 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { .set_bias_level = tlv320aic23_set_bias_level, .suspend_bias_off = true, - .controls = tlv320aic23_snd_controls, - .num_controls = ARRAY_SIZE(tlv320aic23_snd_controls), - .dapm_widgets = tlv320aic23_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), - .dapm_routes = tlv320aic23_intercon, - .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), + .component_driver = { + .controls = tlv320aic23_snd_controls, + .num_controls = ARRAY_SIZE(tlv320aic23_snd_controls), + .dapm_widgets = tlv320aic23_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), + .dapm_routes = tlv320aic23_intercon, + .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), + }, }; int tlv320aic23_probe(struct device *dev, struct regmap *regmap) diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 2c904d7..14aa96d 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -321,12 +321,14 @@ static int aic26_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver aic26_soc_codec_dev = { .probe = aic26_probe, - .controls = aic26_snd_controls, - .num_controls = ARRAY_SIZE(aic26_snd_controls), - .dapm_widgets = tlv320aic26_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tlv320aic26_dapm_widgets), - .dapm_routes = tlv320aic26_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(tlv320aic26_dapm_routes), + .component_driver = { + .controls = aic26_snd_controls, + .num_controls = ARRAY_SIZE(aic26_snd_controls), + .dapm_widgets = tlv320aic26_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tlv320aic26_dapm_widgets), + .dapm_routes = tlv320aic26_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tlv320aic26_dapm_routes), + }, }; static const struct regmap_config aic26_regmap = { diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 3c5e1df..be1a64b 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -273,10 +273,20 @@ static const DECLARE_TLV_DB_SCALE(sp_vol_tlv, -6350, 50, 0); /* * controls to be exported to the user space */ -static const struct snd_kcontrol_new aic31xx_snd_controls[] = { +static const struct snd_kcontrol_new common31xx_snd_controls[] = { SOC_DOUBLE_R_S_TLV("DAC Playback Volume", AIC31XX_LDACVOL, AIC31XX_RDACVOL, 0, -127, 48, 7, 0, dac_vol_tlv), + SOC_DOUBLE_R("HP Driver Playback Switch", AIC31XX_HPLGAIN, + AIC31XX_HPRGAIN, 2, 1, 0), + SOC_DOUBLE_R_TLV("HP Driver Playback Volume", AIC31XX_HPLGAIN, + AIC31XX_HPRGAIN, 3, 0x09, 0, hp_drv_tlv), + + SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL, + AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv), +}; + +static const struct snd_kcontrol_new aic31xx_snd_controls[] = { SOC_SINGLE_TLV("ADC Fine Capture Volume", AIC31XX_ADCFGA, 4, 4, 1, adc_fgain_tlv), @@ -286,14 +296,6 @@ static const struct snd_kcontrol_new aic31xx_snd_controls[] = { SOC_SINGLE_TLV("Mic PGA Capture Volume", AIC31XX_MICPGA, 0, 119, 0, mic_pga_tlv), - - SOC_DOUBLE_R("HP Driver Playback Switch", AIC31XX_HPLGAIN, - AIC31XX_HPRGAIN, 2, 1, 0), - SOC_DOUBLE_R_TLV("HP Driver Playback Volume", AIC31XX_HPLGAIN, - AIC31XX_HPRGAIN, 3, 0x09, 0, hp_drv_tlv), - - SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL, - AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv), }; static const struct snd_kcontrol_new aic311x_snd_controls[] = { @@ -397,17 +399,28 @@ static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w, return 0; } -static const struct snd_kcontrol_new left_output_switches[] = { +static const struct snd_kcontrol_new aic31xx_left_output_switches[] = { SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0), SOC_DAPM_SINGLE("From MIC1LP", AIC31XX_DACMIXERROUTE, 5, 1, 0), SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 4, 1, 0), }; -static const struct snd_kcontrol_new right_output_switches[] = { +static const struct snd_kcontrol_new aic31xx_right_output_switches[] = { SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0), SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 1, 1, 0), }; +static const struct snd_kcontrol_new dac31xx_left_output_switches[] = { + SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0), + SOC_DAPM_SINGLE("From AIN1", AIC31XX_DACMIXERROUTE, 5, 1, 0), + SOC_DAPM_SINGLE("From AIN2", AIC31XX_DACMIXERROUTE, 4, 1, 0), +}; + +static const struct snd_kcontrol_new dac31xx_right_output_switches[] = { + SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0), + SOC_DAPM_SINGLE("From AIN2", AIC31XX_DACMIXERROUTE, 1, 1, 0), +}; + static const struct snd_kcontrol_new p_term_mic1lp = SOC_DAPM_ENUM("MIC1LP P-Terminal", mic1lp_p_enum); @@ -457,7 +470,7 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, return 0; } -static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { +static const struct snd_soc_dapm_widget common31xx_dapm_widgets[] = { SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_MUX("DAC Left Input", @@ -473,14 +486,7 @@ static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { AIC31XX_DACSETUP, 6, 0, aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - /* Output Mixers */ - SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0, - left_output_switches, - ARRAY_SIZE(left_output_switches)), - SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0, - right_output_switches, - ARRAY_SIZE(right_output_switches)), - + /* HP */ SND_SOC_DAPM_SWITCH("HP Left", SND_SOC_NOPM, 0, 0, &aic31xx_dapm_hpl_switch), SND_SOC_DAPM_SWITCH("HP Right", SND_SOC_NOPM, 0, 0, @@ -494,10 +500,34 @@ static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { NULL, 0, aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), - /* ADC */ - SND_SOC_DAPM_ADC_E("ADC", "Capture", AIC31XX_ADCSETUP, 7, 0, - aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | - SND_SOC_DAPM_POST_PMD), + /* Mic Bias */ + SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, mic_bias_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + /* Outputs */ + SND_SOC_DAPM_OUTPUT("HPL"), + SND_SOC_DAPM_OUTPUT("HPR"), +}; + +static const struct snd_soc_dapm_widget dac31xx_dapm_widgets[] = { + /* Inputs */ + SND_SOC_DAPM_INPUT("AIN1"), + SND_SOC_DAPM_INPUT("AIN2"), + + /* Output Mixers */ + SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0, + dac31xx_left_output_switches, + ARRAY_SIZE(dac31xx_left_output_switches)), + SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0, + dac31xx_right_output_switches, + ARRAY_SIZE(dac31xx_right_output_switches)), +}; + +static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { + /* Inputs */ + SND_SOC_DAPM_INPUT("MIC1LP"), + SND_SOC_DAPM_INPUT("MIC1RP"), + SND_SOC_DAPM_INPUT("MIC1LM"), /* Input Selection to MIC_PGA */ SND_SOC_DAPM_MUX("MIC1LP P-Terminal", SND_SOC_NOPM, 0, 0, @@ -507,24 +537,25 @@ static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { SND_SOC_DAPM_MUX("MIC1LM P-Terminal", SND_SOC_NOPM, 0, 0, &p_term_mic1lm), + /* ADC */ + SND_SOC_DAPM_ADC_E("ADC", "Capture", AIC31XX_ADCSETUP, 7, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX("MIC1LM M-Terminal", SND_SOC_NOPM, 0, 0, &m_term_mic1lm), + /* Enabling & Disabling MIC Gain Ctl */ SND_SOC_DAPM_PGA("MIC_GAIN_CTL", AIC31XX_MICPGA, 7, 1, NULL, 0), - /* Mic Bias */ - SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, mic_bias_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - - /* Outputs */ - SND_SOC_DAPM_OUTPUT("HPL"), - SND_SOC_DAPM_OUTPUT("HPR"), - - /* Inputs */ - SND_SOC_DAPM_INPUT("MIC1LP"), - SND_SOC_DAPM_INPUT("MIC1RP"), - SND_SOC_DAPM_INPUT("MIC1LM"), + /* Output Mixers */ + SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0, + aic31xx_left_output_switches, + ARRAY_SIZE(aic31xx_left_output_switches)), + SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0, + aic31xx_right_output_switches, + ARRAY_SIZE(aic31xx_right_output_switches)), }; static const struct snd_soc_dapm_widget aic311x_dapm_widgets[] = { @@ -554,7 +585,7 @@ static const struct snd_soc_dapm_widget aic310x_dapm_widgets[] = { }; static const struct snd_soc_dapm_route -aic31xx_audio_map[] = { +common31xx_audio_map[] = { /* DAC Input Routing */ {"DAC Left Input", "Left Data", "DAC IN"}, {"DAC Left Input", "Right Data", "DAC IN"}, @@ -565,6 +596,31 @@ aic31xx_audio_map[] = { {"DAC Left", NULL, "DAC Left Input"}, {"DAC Right", NULL, "DAC Right Input"}, + /* HPL path */ + {"HP Left", "Switch", "Output Left"}, + {"HPL Driver", NULL, "HP Left"}, + {"HPL", NULL, "HPL Driver"}, + + /* HPR path */ + {"HP Right", "Switch", "Output Right"}, + {"HPR Driver", NULL, "HP Right"}, + {"HPR", NULL, "HPR Driver"}, +}; + +static const struct snd_soc_dapm_route +dac31xx_audio_map[] = { + /* Left Output */ + {"Output Left", "From Left DAC", "DAC Left"}, + {"Output Left", "From AIN1", "AIN1"}, + {"Output Left", "From AIN2", "AIN2"}, + + /* Right Output */ + {"Output Right", "From Right DAC", "DAC Right"}, + {"Output Right", "From AIN2", "AIN2"}, +}; + +static const struct snd_soc_dapm_route +aic31xx_audio_map[] = { /* Mic input */ {"MIC1LP P-Terminal", "FFR 10 Ohm", "MIC1LP"}, {"MIC1LP P-Terminal", "FFR 20 Ohm", "MIC1LP"}, @@ -595,16 +651,6 @@ aic31xx_audio_map[] = { /* Right Output */ {"Output Right", "From Right DAC", "DAC Right"}, {"Output Right", "From MIC1RP", "MIC1RP"}, - - /* HPL path */ - {"HP Left", "Switch", "Output Left"}, - {"HPL Driver", NULL, "HP Left"}, - {"HPL", NULL, "HPL Driver"}, - - /* HPR path */ - {"HP Right", "Switch", "Output Right"}, - {"HPR Driver", NULL, "HP Right"}, - {"HPR", NULL, "HPR Driver"}, }; static const struct snd_soc_dapm_route @@ -633,6 +679,13 @@ static int aic31xx_add_controls(struct snd_soc_codec *codec) int ret = 0; struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + if (!(aic31xx->pdata.codec_type & DAC31XX_BIT)) + ret = snd_soc_add_codec_controls( + codec, aic31xx_snd_controls, + ARRAY_SIZE(aic31xx_snd_controls)); + if (ret) + return ret; + if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) ret = snd_soc_add_codec_controls( codec, aic311x_snd_controls, @@ -651,6 +704,30 @@ static int aic31xx_add_widgets(struct snd_soc_codec *codec) struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); int ret = 0; + if (aic31xx->pdata.codec_type & DAC31XX_BIT) { + ret = snd_soc_dapm_new_controls( + dapm, dac31xx_dapm_widgets, + ARRAY_SIZE(dac31xx_dapm_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, dac31xx_audio_map, + ARRAY_SIZE(dac31xx_audio_map)); + if (ret) + return ret; + } else { + ret = snd_soc_dapm_new_controls( + dapm, aic31xx_dapm_widgets, + ARRAY_SIZE(aic31xx_dapm_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, aic31xx_audio_map, + ARRAY_SIZE(aic31xx_audio_map)); + if (ret) + return ret; + } + if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) { ret = snd_soc_dapm_new_controls( dapm, aic311x_dapm_widgets, @@ -1114,12 +1191,14 @@ static struct snd_soc_codec_driver soc_codec_driver_aic31xx = { .set_bias_level = aic31xx_set_bias_level, .suspend_bias_off = true, - .controls = aic31xx_snd_controls, - .num_controls = ARRAY_SIZE(aic31xx_snd_controls), - .dapm_widgets = aic31xx_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(aic31xx_dapm_widgets), - .dapm_routes = aic31xx_audio_map, - .num_dapm_routes = ARRAY_SIZE(aic31xx_audio_map), + .component_driver = { + .controls = common31xx_snd_controls, + .num_controls = ARRAY_SIZE(common31xx_snd_controls), + .dapm_widgets = common31xx_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(common31xx_dapm_widgets), + .dapm_routes = common31xx_audio_map, + .num_dapm_routes = ARRAY_SIZE(common31xx_audio_map), + }, }; static const struct snd_soc_dai_ops aic31xx_dai_ops = { @@ -1129,19 +1208,34 @@ static const struct snd_soc_dai_ops aic31xx_dai_ops = { .digital_mute = aic31xx_dac_mute, }; +static struct snd_soc_dai_driver dac31xx_dai_driver[] = { + { + .name = "tlv32dac31xx-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = AIC31XX_RATES, + .formats = AIC31XX_FORMATS, + }, + .ops = &aic31xx_dai_ops, + .symmetric_rates = 1, + } +}; + static struct snd_soc_dai_driver aic31xx_dai_driver[] = { { .name = "tlv320aic31xx-hifi", .playback = { .stream_name = "Playback", - .channels_min = 1, + .channels_min = 2, .channels_max = 2, .rates = AIC31XX_RATES, .formats = AIC31XX_FORMATS, }, .capture = { .stream_name = "Capture", - .channels_min = 1, + .channels_min = 2, .channels_max = 2, .rates = AIC31XX_RATES, .formats = AIC31XX_FORMATS, @@ -1259,9 +1353,16 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, if (ret) return ret; - return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx, - aic31xx_dai_driver, - ARRAY_SIZE(aic31xx_dai_driver)); + if (aic31xx->pdata.codec_type & DAC31XX_BIT) + return snd_soc_register_codec(&i2c->dev, + &soc_codec_driver_aic31xx, + dac31xx_dai_driver, + ARRAY_SIZE(dac31xx_dai_driver)); + else + return snd_soc_register_codec(&i2c->dev, + &soc_codec_driver_aic31xx, + aic31xx_dai_driver, + ARRAY_SIZE(aic31xx_dai_driver)); } static int aic31xx_i2c_remove(struct i2c_client *i2c) @@ -1277,6 +1378,7 @@ static const struct i2c_device_id aic31xx_i2c_id[] = { { "tlv320aic3110", AIC3110 }, { "tlv320aic3120", AIC3120 }, { "tlv320aic3111", AIC3111 }, + { "tlv320dac3100", DAC3100 }, { } }; MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h index ac9b146..5acd5b6 100644 --- a/sound/soc/codecs/tlv320aic31xx.h +++ b/sound/soc/codecs/tlv320aic31xx.h @@ -24,12 +24,14 @@ #define AIC31XX_STEREO_CLASS_D_BIT 0x1 #define AIC31XX_MINIDSP_BIT 0x2 +#define DAC31XX_BIT 0x4 enum aic31xx_type { AIC3100 = 0, AIC3110 = AIC31XX_STEREO_CLASS_D_BIT, AIC3120 = AIC31XX_MINIDSP_BIT, AIC3111 = (AIC31XX_STEREO_CLASS_D_BIT | AIC31XX_MINIDSP_BIT), + DAC3100 = DAC31XX_BIT, }; struct aic31xx_pdata { diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 85d4978..28fdfc5 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -797,12 +797,14 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { .set_bias_level = aic32x4_set_bias_level, .suspend_bias_off = true, - .controls = aic32x4_snd_controls, - .num_controls = ARRAY_SIZE(aic32x4_snd_controls), - .dapm_widgets = aic32x4_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(aic32x4_dapm_widgets), - .dapm_routes = aic32x4_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), + .component_driver = { + .controls = aic32x4_snd_controls, + .num_controls = ARRAY_SIZE(aic32x4_snd_controls), + .dapm_widgets = aic32x4_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic32x4_dapm_widgets), + .dapm_routes = aic32x4_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), + }, }; static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4, diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index a564759..5a8d96e 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1670,12 +1670,14 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = { .idle_bias_off = true, .probe = aic3x_probe, .remove = aic3x_remove, - .controls = aic3x_snd_controls, - .num_controls = ARRAY_SIZE(aic3x_snd_controls), - .dapm_widgets = aic3x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets), - .dapm_routes = intercon, - .num_dapm_routes = ARRAY_SIZE(intercon), + .component_driver = { + .controls = aic3x_snd_controls, + .num_controls = ARRAY_SIZE(aic3x_snd_controls), + .dapm_widgets = aic3x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), + }, }; /* diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index f7a6ce7..7bcf01e 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -90,7 +90,6 @@ static const char *dac33_supply_names[DAC33_NUM_SUPPLIES] = { struct tlv320dac33_priv { struct mutex mutex; - struct workqueue_struct *dac33_wq; struct work_struct work; struct snd_soc_codec *codec; struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; @@ -771,7 +770,7 @@ static irqreturn_t dac33_interrupt_handler(int irq, void *dev) /* Do not schedule the workqueue in Mode7 */ if (dac33->fifo_mode != DAC33_FIFO_MODE7) - queue_work(dac33->dac33_wq, &dac33->work); + schedule_work(&dac33->work); return IRQ_HANDLED; } @@ -1127,7 +1126,7 @@ static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (dac33->fifo_mode) { dac33->state = DAC33_PREFILL; - queue_work(dac33->dac33_wq, &dac33->work); + schedule_work(&dac33->work); } break; case SNDRV_PCM_TRIGGER_STOP: @@ -1135,7 +1134,7 @@ static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (dac33->fifo_mode) { dac33->state = DAC33_FLUSH; - queue_work(dac33->dac33_wq, &dac33->work); + schedule_work(&dac33->work); } break; default: @@ -1410,14 +1409,6 @@ static int dac33_soc_probe(struct snd_soc_codec *codec) dac33->irq = -1; } if (dac33->irq != -1) { - /* Setup work queue */ - dac33->dac33_wq = - create_singlethread_workqueue("tlv320dac33"); - if (dac33->dac33_wq == NULL) { - free_irq(dac33->irq, codec); - return -ENOMEM; - } - INIT_WORK(&dac33->work, dac33_work); } } @@ -1437,7 +1428,7 @@ static int dac33_soc_remove(struct snd_soc_codec *codec) if (dac33->irq >= 0) { free_irq(dac33->irq, dac33->codec); - destroy_workqueue(dac33->dac33_wq); + flush_work(&dac33->work); } return 0; } @@ -1453,12 +1444,14 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = { .probe = dac33_soc_probe, .remove = dac33_soc_remove, - .controls = dac33_snd_controls, - .num_controls = ARRAY_SIZE(dac33_snd_controls), - .dapm_widgets = dac33_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(dac33_dapm_widgets), - .dapm_routes = audio_map, - .num_dapm_routes = ARRAY_SIZE(audio_map), + .component_driver = { + .controls = dac33_snd_controls, + .num_controls = ARRAY_SIZE(dac33_snd_controls), + .dapm_widgets = dac33_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(dac33_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), + }, }; #define DAC33_RATES (SNDRV_PCM_RATE_44100 | \ diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index f1ea052..2e014c8 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -52,7 +52,7 @@ struct tpa6130a2_data { static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable) { - int ret; + int ret = 0, ret2; if (enable) { ret = regulator_enable(data->supply); @@ -64,7 +64,30 @@ static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable) /* Power on */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 1); + + /* Sync registers */ + regcache_cache_only(data->regmap, false); + ret = regcache_sync(data->regmap); + if (ret != 0) { + dev_err(data->dev, + "Failed to sync registers: %d\n", ret); + regcache_cache_only(data->regmap, true); + if (data->power_gpio >= 0) + gpio_set_value(data->power_gpio, 0); + ret2 = regulator_disable(data->supply); + if (ret2 != 0) + dev_err(data->dev, + "Failed to disable supply: %d\n", ret2); + return ret; + } } else { + /* Powered off device does not retain registers. While device + * is off, any register updates (i.e. volume changes) should + * happen in cache only. + */ + regcache_mark_dirty(data->regmap); + regcache_cache_only(data->regmap, true); + /* Power off */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 0); @@ -75,9 +98,6 @@ static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable) "Failed to disable supply: %d\n", ret); return ret; } - - /* device regs does not match the cache state anymore */ - regcache_mark_dirty(data->regmap); } return ret; @@ -88,25 +108,14 @@ static int tpa6130a2_power_event(struct snd_soc_dapm_widget *w, { struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); struct tpa6130a2_data *data = snd_soc_component_get_drvdata(c); - int ret; - /* before widget power up */ if (SND_SOC_DAPM_EVENT_ON(event)) { - /* Turn on the chip */ - tpa6130a2_power(data, true); - /* Sync the registers */ - ret = regcache_sync(data->regmap); - if (ret < 0) { - dev_err(c->dev, "Failed to initialize chip\n"); - tpa6130a2_power(data, false); - return ret; - } - /* after widget power down */ + /* Before widget power up: turn chip on, sync registers */ + return tpa6130a2_power(data, true); } else { - tpa6130a2_power(data, false); + /* After widget power down: turn chip off */ + return tpa6130a2_power(data, false); } - - return 0; } /* @@ -190,7 +199,7 @@ static const struct snd_soc_dapm_route tpa6130a2_dapm_routes[] = { { "Right PGA", NULL, "Power" }, }; -struct snd_soc_component_driver tpa6130a2_component_driver = { +static const struct snd_soc_component_driver tpa6130a2_component_driver = { .name = "tpa6130a2", .probe = tpa6130a2_component_probe, .dapm_widgets = tpa6130a2_dapm_widgets, diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index a5a4e9f..a2104d6 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -2199,12 +2199,14 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { .set_bias_level = twl4030_set_bias_level, .idle_bias_off = true, - .controls = twl4030_snd_controls, - .num_controls = ARRAY_SIZE(twl4030_snd_controls), - .dapm_widgets = twl4030_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(twl4030_dapm_widgets), - .dapm_routes = intercon, - .num_dapm_routes = ARRAY_SIZE(intercon), + .component_driver = { + .controls = twl4030_snd_controls, + .num_controls = ARRAY_SIZE(twl4030_snd_controls), + .dapm_widgets = twl4030_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(twl4030_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), + }, }; static int twl4030_codec_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 1f70810..748036e 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -1156,12 +1156,14 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { .suspend_bias_off = true, .ignore_pmdown_time = true, - .controls = twl6040_snd_controls, - .num_controls = ARRAY_SIZE(twl6040_snd_controls), - .dapm_widgets = twl6040_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets), - .dapm_routes = intercon, - .num_dapm_routes = ARRAY_SIZE(intercon), + .component_driver = { + .controls = twl6040_snd_controls, + .num_controls = ARRAY_SIZE(twl6040_snd_controls), + .dapm_widgets = twl6040_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), + }, }; static int twl6040_codec_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index e4c694c..5fdee87 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -523,10 +523,12 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = { .set_bias_level = uda134x_set_bias_level, .suspend_bias_off = true, - .dapm_widgets = uda134x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets), - .dapm_routes = uda134x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes), + .component_driver = { + .dapm_widgets = uda134x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets), + .dapm_routes = uda134x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes), + }, }; static const struct regmap_config uda134x_regmap_config = { @@ -544,6 +546,7 @@ static int uda134x_codec_probe(struct platform_device *pdev) { struct uda134x_platform_data *pd = pdev->dev.platform_data; struct uda134x_priv *uda134x; + int ret; if (!pd) { dev_err(&pdev->dev, "Missing L3 bitbang function\n"); @@ -557,6 +560,12 @@ static int uda134x_codec_probe(struct platform_device *pdev) uda134x->pd = pd; platform_set_drvdata(pdev, uda134x); + if (pd->l3.use_gpios) { + ret = l3_set_gpio_ops(&pdev->dev, &uda134x->pd->l3); + if (ret < 0) + return ret; + } + uda134x->regmap = devm_regmap_init(&pdev->dev, NULL, pd, &uda134x_regmap_config); if (IS_ERR(uda134x->regmap)) diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 35f0469..533e3bb 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -765,12 +765,14 @@ static struct snd_soc_codec_driver soc_codec_dev_uda1380 = { .reg_cache_default = uda1380_reg, .reg_cache_step = 1, - .controls = uda1380_snd_controls, - .num_controls = ARRAY_SIZE(uda1380_snd_controls), - .dapm_widgets = uda1380_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), - .dapm_routes = uda1380_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(uda1380_dapm_routes), + .component_driver = { + .controls = uda1380_snd_controls, + .num_controls = ARRAY_SIZE(uda1380_snd_controls), + .dapm_widgets = uda1380_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), + .dapm_routes = uda1380_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(uda1380_dapm_routes), + }, }; #if IS_ENABLED(CONFIG_I2C) diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index 1b79778..fcffb6e 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c @@ -484,12 +484,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wl1273 = { .probe = wl1273_probe, .remove = wl1273_remove, - .controls = wl1273_controls, - .num_controls = ARRAY_SIZE(wl1273_controls), - .dapm_widgets = wl1273_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wl1273_dapm_widgets), - .dapm_routes = wl1273_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wl1273_dapm_routes), + .component_driver = { + .controls = wl1273_controls, + .num_controls = ARRAY_SIZE(wl1273_controls), + .dapm_widgets = wl1273_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wl1273_dapm_widgets), + .dapm_routes = wl1273_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wl1273_dapm_routes), + }, }; static int wl1273_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index e3c34bd..0eb5dcf 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -789,16 +789,18 @@ static int wm0010_set_sysclk(struct snd_soc_codec *codec, int source, static int wm0010_probe(struct snd_soc_codec *codec); -static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm0010 = { .probe = wm0010_probe, .set_bias_level = wm0010_set_bias_level, .set_sysclk = wm0010_set_sysclk, .idle_bias_off = true, - .dapm_widgets = wm0010_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm0010_dapm_widgets), - .dapm_routes = wm0010_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes), + .component_driver = { + .dapm_widgets = wm0010_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm0010_dapm_widgets), + .dapm_routes = wm0010_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes), + }, }; #define WM0010_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index ec45c5b..cf5f058 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c @@ -141,12 +141,13 @@ static struct snd_soc_dai_driver wm1250_ev1_dai = { .ops = &wm1250_ev1_ops, }; -static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = { - .dapm_widgets = wm1250_ev1_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets), - .dapm_routes = wm1250_ev1_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes), - +static const struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = { + .component_driver = { + .dapm_widgets = wm1250_ev1_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets), + .dapm_routes = wm1250_ev1_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes), + }, .set_bias_level = wm1250_ev1_set_bias_level, .idle_bias_off = true, }; diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index f266439..23cde3a 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -799,18 +799,20 @@ static int wm2000_remove(struct snd_soc_codec *codec) return wm2000_anc_transition(wm2000, ANC_OFF); } -static struct snd_soc_codec_driver soc_codec_dev_wm2000 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm2000 = { .probe = wm2000_probe, .remove = wm2000_remove, .suspend = wm2000_suspend, .resume = wm2000_resume, - .dapm_widgets = wm2000_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm2000_dapm_widgets), - .dapm_routes = wm2000_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm2000_audio_map), - .controls = wm2000_controls, - .num_controls = ARRAY_SIZE(wm2000_controls), + .component_driver = { + .controls = wm2000_controls, + .num_controls = ARRAY_SIZE(wm2000_controls), + .dapm_widgets = wm2000_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm2000_dapm_widgets), + .dapm_routes = wm2000_audio_map, + .num_dapm_routes = ARRAY_SIZE(wm2000_audio_map), + }, }; static int wm2000_i2c_probe(struct i2c_client *i2c, diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index fd1439e..606bf88 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2103,7 +2103,7 @@ static struct snd_soc_dai_driver wm2200_dai = { .ops = &wm2200_dai_ops, }; -static struct snd_soc_codec_driver soc_codec_wm2200 = { +static const struct snd_soc_codec_driver soc_codec_wm2200 = { .probe = wm2200_probe, .idle_bias_off = true, @@ -2111,12 +2111,14 @@ static struct snd_soc_codec_driver soc_codec_wm2200 = { .set_sysclk = wm2200_set_sysclk, .set_pll = wm2200_set_fll, - .controls = wm2200_snd_controls, - .num_controls = ARRAY_SIZE(wm2200_snd_controls), - .dapm_widgets = wm2200_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets), - .dapm_routes = wm2200_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes), + .component_driver = { + .controls = wm2200_snd_controls, + .num_controls = ARRAY_SIZE(wm2200_snd_controls), + .dapm_widgets = wm2200_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets), + .dapm_routes = wm2200_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes), + }, }; static irqreturn_t wm2200_irq(int irq, void *data) diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 512a9d2..5605750 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2285,7 +2285,7 @@ static int wm5100_gpio_direction_in(struct gpio_chip *chip, unsigned offset) (1 << WM5100_GP1_DIR_SHIFT)); } -static struct gpio_chip wm5100_template_chip = { +static const struct gpio_chip wm5100_template_chip = { .label = "wm5100", .owner = THIS_MODULE, .direction_output = wm5100_gpio_direction_out, @@ -2381,7 +2381,7 @@ static int wm5100_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm5100 = { .probe = wm5100_probe, .remove = wm5100_remove, @@ -2390,12 +2390,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { .idle_bias_off = 1, .seq_notifier = wm5100_seq_notifier, - .controls = wm5100_snd_controls, - .num_controls = ARRAY_SIZE(wm5100_snd_controls), - .dapm_widgets = wm5100_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm5100_dapm_widgets), - .dapm_routes = wm5100_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm5100_dapm_routes), + .component_driver = { + .controls = wm5100_snd_controls, + .num_controls = ARRAY_SIZE(wm5100_snd_controls), + .dapm_widgets = wm5100_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm5100_dapm_widgets), + .dapm_routes = wm5100_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm5100_dapm_routes), + }, }; static const struct regmap_config wm5100_regmap = { diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 846deed..93876c6 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -1521,6 +1521,16 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { { "IN3L", NULL, "SYSCLK" }, { "IN3R", NULL, "SYSCLK" }, + { "ASRC1L", NULL, "SYSCLK" }, + { "ASRC1R", NULL, "SYSCLK" }, + { "ASRC2L", NULL, "SYSCLK" }, + { "ASRC2R", NULL, "SYSCLK" }, + + { "ASRC1L", NULL, "ASYNCCLK" }, + { "ASRC1R", NULL, "ASYNCCLK" }, + { "ASRC2L", NULL, "ASYNCCLK" }, + { "ASRC2R", NULL, "ASYNCCLK" }, + { "MICBIAS1", NULL, "MICVDD" }, { "MICBIAS2", NULL, "MICVDD" }, { "MICBIAS3", NULL, "MICVDD" }, @@ -1600,7 +1610,6 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { { "Slim3 Capture", NULL, "SYSCLK" }, { "Audio Trace DSP", NULL, "DSP1" }, - { "Audio Trace DSP", NULL, "SYSCLK" }, { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" }, @@ -1990,7 +1999,7 @@ static struct regmap *wm5102_get_regmap(struct device *dev) return priv->core.arizona->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm5102 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm5102 = { .probe = wm5102_codec_probe, .remove = wm5102_codec_remove, .get_regmap = wm5102_get_regmap, @@ -2000,12 +2009,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5102 = { .set_sysclk = arizona_set_sysclk, .set_pll = wm5102_set_fll, - .controls = wm5102_snd_controls, - .num_controls = ARRAY_SIZE(wm5102_snd_controls), - .dapm_widgets = wm5102_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm5102_dapm_widgets), - .dapm_routes = wm5102_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes), + .component_driver = { + .controls = wm5102_snd_controls, + .num_controls = ARRAY_SIZE(wm5102_snd_controls), + .dapm_widgets = wm5102_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm5102_dapm_widgets), + .dapm_routes = wm5102_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes), + }, }; static struct snd_compr_ops wm5102_compr_ops = { diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 1565470..06bae3b 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -1745,6 +1745,16 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { { "IN4L", NULL, "SYSCLK" }, { "IN4R", NULL, "SYSCLK" }, + { "ASRC1L", NULL, "SYSCLK" }, + { "ASRC1R", NULL, "SYSCLK" }, + { "ASRC2L", NULL, "SYSCLK" }, + { "ASRC2R", NULL, "SYSCLK" }, + + { "ASRC1L", NULL, "ASYNCCLK" }, + { "ASRC1R", NULL, "ASYNCCLK" }, + { "ASRC2L", NULL, "ASYNCCLK" }, + { "ASRC2R", NULL, "ASYNCCLK" }, + { "MICBIAS1", NULL, "MICVDD" }, { "MICBIAS2", NULL, "MICVDD" }, { "MICBIAS3", NULL, "MICVDD" }, @@ -1832,10 +1842,8 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { { "Slim3 Capture", NULL, "SYSCLK" }, { "Voice Control DSP", NULL, "DSP3" }, - { "Voice Control DSP", NULL, "SYSCLK" }, { "Audio Trace DSP", NULL, "DSP1" }, - { "Audio Trace DSP", NULL, "SYSCLK" }, { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" }, @@ -2347,7 +2355,7 @@ static struct regmap *wm5110_get_regmap(struct device *dev) return priv->core.arizona->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm5110 = { .probe = wm5110_codec_probe, .remove = wm5110_codec_remove, .get_regmap = wm5110_get_regmap, @@ -2357,12 +2365,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { .set_sysclk = arizona_set_sysclk, .set_pll = wm5110_set_fll, - .controls = wm5110_snd_controls, - .num_controls = ARRAY_SIZE(wm5110_snd_controls), - .dapm_widgets = wm5110_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm5110_dapm_widgets), - .dapm_routes = wm5110_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes), + .component_driver = { + .controls = wm5110_snd_controls, + .num_controls = ARRAY_SIZE(wm5110_snd_controls), + .dapm_widgets = wm5110_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm5110_dapm_widgets), + .dapm_routes = wm5110_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes), + }, }; static struct snd_compr_ops wm5110_compr_ops = { diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index ffbf3df..2efc5b4 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -1587,19 +1587,21 @@ static struct regmap *wm8350_get_regmap(struct device *dev) return wm8350->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm8350 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8350 = { .probe = wm8350_codec_probe, .remove = wm8350_codec_remove, .get_regmap = wm8350_get_regmap, .set_bias_level = wm8350_set_bias_level, .suspend_bias_off = true, - .controls = wm8350_snd_controls, - .num_controls = ARRAY_SIZE(wm8350_snd_controls), - .dapm_widgets = wm8350_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8350_dapm_widgets), - .dapm_routes = wm8350_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8350_dapm_routes), + .component_driver = { + .controls = wm8350_snd_controls, + .num_controls = ARRAY_SIZE(wm8350_snd_controls), + .dapm_widgets = wm8350_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8350_dapm_widgets), + .dapm_routes = wm8350_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8350_dapm_routes), + }, }; static int wm8350_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index b1d346a..6c59fb9 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -1332,19 +1332,21 @@ static struct regmap *wm8400_get_regmap(struct device *dev) return wm8400->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm8400 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8400 = { .probe = wm8400_codec_probe, .remove = wm8400_codec_remove, .get_regmap = wm8400_get_regmap, .set_bias_level = wm8400_set_bias_level, .suspend_bias_off = true, - .controls = wm8400_snd_controls, - .num_controls = ARRAY_SIZE(wm8400_snd_controls), - .dapm_widgets = wm8400_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8400_dapm_widgets), - .dapm_routes = wm8400_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8400_dapm_routes), + .component_driver = { + .controls = wm8400_snd_controls, + .num_controls = ARRAY_SIZE(wm8400_snd_controls), + .dapm_widgets = wm8400_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8400_dapm_widgets), + .dapm_routes = wm8400_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8400_dapm_routes), + }, }; static int wm8400_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 99e40e6..119ceac 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -581,17 +581,19 @@ static int wm8510_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8510 = { .probe = wm8510_probe, .set_bias_level = wm8510_set_bias_level, .suspend_bias_off = true, - .controls = wm8510_snd_controls, - .num_controls = ARRAY_SIZE(wm8510_snd_controls), - .dapm_widgets = wm8510_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8510_dapm_widgets), - .dapm_routes = wm8510_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8510_dapm_routes), + .component_driver = { + .controls = wm8510_snd_controls, + .num_controls = ARRAY_SIZE(wm8510_snd_controls), + .dapm_widgets = wm8510_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8510_dapm_widgets), + .dapm_routes = wm8510_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8510_dapm_routes), + }, }; static const struct of_device_id wm8510_of_match[] = { diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index aa287a3..deb2e07 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -413,17 +413,19 @@ static int wm8523_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8523 = { .probe = wm8523_probe, .set_bias_level = wm8523_set_bias_level, .suspend_bias_off = true, - .controls = wm8523_controls, - .num_controls = ARRAY_SIZE(wm8523_controls), - .dapm_widgets = wm8523_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8523_dapm_widgets), - .dapm_routes = wm8523_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8523_dapm_routes), + .component_driver = { + .controls = wm8523_controls, + .num_controls = ARRAY_SIZE(wm8523_controls), + .dapm_widgets = wm8523_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8523_dapm_widgets), + .dapm_routes = wm8523_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8523_dapm_routes), + }, }; static const struct of_device_id wm8523_of_match[] = { diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 66602bf..faa7287 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -899,17 +899,19 @@ static int wm8580_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8580 = { .probe = wm8580_probe, .remove = wm8580_remove, .set_bias_level = wm8580_set_bias_level, - .controls = wm8580_snd_controls, - .num_controls = ARRAY_SIZE(wm8580_snd_controls), - .dapm_widgets = wm8580_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8580_dapm_widgets), - .dapm_routes = wm8580_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8580_dapm_routes), + .component_driver = { + .controls = wm8580_snd_controls, + .num_controls = ARRAY_SIZE(wm8580_snd_controls), + .dapm_widgets = wm8580_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8580_dapm_widgets), + .dapm_routes = wm8580_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8580_dapm_routes), + }, }; static const struct of_device_id wm8580_of_match[] = { diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index c759ec0..2b376c9 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -367,17 +367,19 @@ static int wm8711_probe(struct snd_soc_codec *codec) } -static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8711 = { .probe = wm8711_probe, .set_bias_level = wm8711_set_bias_level, .suspend_bias_off = true, - .controls = wm8711_snd_controls, - .num_controls = ARRAY_SIZE(wm8711_snd_controls), - .dapm_widgets = wm8711_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8711_dapm_widgets), - .dapm_routes = wm8711_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8711_intercon), + .component_driver = { + .controls = wm8711_snd_controls, + .num_controls = ARRAY_SIZE(wm8711_snd_controls), + .dapm_widgets = wm8711_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8711_dapm_widgets), + .dapm_routes = wm8711_intercon, + .num_dapm_routes = ARRAY_SIZE(wm8711_intercon), + }, }; static const struct of_device_id wm8711_of_match[] = { diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c index bb25a75..7fde077 100644 --- a/sound/soc/codecs/wm8727.c +++ b/sound/soc/codecs/wm8727.c @@ -53,11 +53,13 @@ static struct snd_soc_dai_driver wm8727_dai = { }, }; -static struct snd_soc_codec_driver soc_codec_dev_wm8727 = { - .dapm_widgets = wm8727_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8727_dapm_widgets), - .dapm_routes = wm8727_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8727_dapm_routes), +static const struct snd_soc_codec_driver soc_codec_dev_wm8727 = { + .component_driver = { + .dapm_widgets = wm8727_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8727_dapm_widgets), + .dapm_routes = wm8727_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8727_dapm_routes), + }, }; static int wm8727_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 1564e69..797cc6e 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -211,16 +211,18 @@ static struct snd_soc_dai_driver wm8728_dai = { .ops = &wm8728_dai_ops, }; -static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8728 = { .set_bias_level = wm8728_set_bias_level, .suspend_bias_off = true, - .controls = wm8728_snd_controls, - .num_controls = ARRAY_SIZE(wm8728_snd_controls), - .dapm_widgets = wm8728_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8728_dapm_widgets), - .dapm_routes = wm8728_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8728_intercon), + .component_driver = { + .controls = wm8728_snd_controls, + .num_controls = ARRAY_SIZE(wm8728_snd_controls), + .dapm_widgets = wm8728_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8728_dapm_widgets), + .dapm_routes = wm8728_intercon, + .num_dapm_routes = ARRAY_SIZE(wm8728_intercon), + }, }; static const struct of_device_id wm8728_of_match[] = { diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index d18261a..4f9a1eb 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -628,16 +628,18 @@ err_regulator_enable: return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8731 = { .set_bias_level = wm8731_set_bias_level, .suspend_bias_off = true, - .dapm_widgets = wm8731_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), - .dapm_routes = wm8731_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8731_intercon), - .controls = wm8731_snd_controls, - .num_controls = ARRAY_SIZE(wm8731_snd_controls), + .component_driver = { + .controls = wm8731_snd_controls, + .num_controls = ARRAY_SIZE(wm8731_snd_controls), + .dapm_widgets = wm8731_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), + .dapm_routes = wm8731_intercon, + .num_dapm_routes = ARRAY_SIZE(wm8731_intercon), + }, }; static const struct of_device_id wm8731_of_match[] = { diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index e780760..f0cb1c4 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -573,17 +573,19 @@ err_get: return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8737 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8737 = { .probe = wm8737_probe, .set_bias_level = wm8737_set_bias_level, .suspend_bias_off = true, - .controls = wm8737_snd_controls, - .num_controls = ARRAY_SIZE(wm8737_snd_controls), - .dapm_widgets = wm8737_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8737_dapm_widgets), - .dapm_routes = intercon, - .num_dapm_routes = ARRAY_SIZE(intercon), + .component_driver = { + .controls = wm8737_snd_controls, + .num_controls = ARRAY_SIZE(wm8737_snd_controls), + .dapm_widgets = wm8737_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8737_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), + }, }; static const struct of_device_id wm8737_of_match[] = { diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 36ef91f..565d477 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -497,15 +497,17 @@ static int wm8741_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8741 = { .probe = wm8741_probe, .remove = wm8741_remove, .resume = wm8741_resume, - .dapm_widgets = wm8741_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8741_dapm_widgets), - .dapm_routes = wm8741_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8741_dapm_routes), + .component_driver = { + .dapm_widgets = wm8741_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8741_dapm_widgets), + .dapm_routes = wm8741_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8741_dapm_routes), + }, }; static const struct of_device_id wm8741_of_match[] = { diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index bd9dcd2..0da2bba 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -708,17 +708,19 @@ static int wm8750_probe(struct snd_soc_codec *codec) return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8750 = { .probe = wm8750_probe, .set_bias_level = wm8750_set_bias_level, .suspend_bias_off = true, - .controls = wm8750_snd_controls, - .num_controls = ARRAY_SIZE(wm8750_snd_controls), - .dapm_widgets = wm8750_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), - .dapm_routes = wm8750_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8750_dapm_routes), + .component_driver = { + .controls = wm8750_snd_controls, + .num_controls = ARRAY_SIZE(wm8750_snd_controls), + .dapm_widgets = wm8750_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), + .dapm_routes = wm8750_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8750_dapm_routes), + }, }; static const struct of_device_id wm8750_of_match[] = { diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index cdcc912..9bdf544 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1478,18 +1478,20 @@ static int wm8753_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8753 = { .probe = wm8753_probe, .resume = wm8753_resume, .set_bias_level = wm8753_set_bias_level, .suspend_bias_off = true, - .controls = wm8753_snd_controls, - .num_controls = ARRAY_SIZE(wm8753_snd_controls), - .dapm_widgets = wm8753_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8753_dapm_widgets), - .dapm_routes = wm8753_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8753_dapm_routes), + .component_driver = { + .controls = wm8753_snd_controls, + .num_controls = ARRAY_SIZE(wm8753_snd_controls), + .dapm_widgets = wm8753_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8753_dapm_widgets), + .dapm_routes = wm8753_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8753_dapm_routes), + }, }; static const struct of_device_id wm8753_of_match[] = { diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index df61784..d6edcbb 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -608,17 +608,19 @@ err_reg_enable: return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8770 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8770 = { .probe = wm8770_probe, .set_bias_level = wm8770_set_bias_level, .idle_bias_off = true, - .controls = wm8770_snd_controls, - .num_controls = ARRAY_SIZE(wm8770_snd_controls), - .dapm_widgets = wm8770_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8770_dapm_widgets), - .dapm_routes = wm8770_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8770_intercon), + .component_driver = { + .controls = wm8770_snd_controls, + .num_controls = ARRAY_SIZE(wm8770_snd_controls), + .dapm_widgets = wm8770_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8770_dapm_widgets), + .dapm_routes = wm8770_intercon, + .num_dapm_routes = ARRAY_SIZE(wm8770_intercon), + }, }; static const struct of_device_id wm8770_of_match[] = { diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 5af44f9..ae30480 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -425,17 +425,19 @@ static int wm8776_probe(struct snd_soc_codec *codec) return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8776 = { .probe = wm8776_probe, .set_bias_level = wm8776_set_bias_level, .suspend_bias_off = true, - .controls = wm8776_snd_controls, - .num_controls = ARRAY_SIZE(wm8776_snd_controls), - .dapm_widgets = wm8776_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8776_dapm_widgets), - .dapm_routes = routes, - .num_dapm_routes = ARRAY_SIZE(routes), + .component_driver = { + .controls = wm8776_snd_controls, + .num_controls = ARRAY_SIZE(wm8776_snd_controls), + .dapm_widgets = wm8776_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8776_dapm_widgets), + .dapm_routes = routes, + .num_dapm_routes = ARRAY_SIZE(routes), + }, }; static const struct of_device_id wm8776_of_match[] = { diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c index fb55fd8..bcda210 100644 --- a/sound/soc/codecs/wm8782.c +++ b/sound/soc/codecs/wm8782.c @@ -50,11 +50,13 @@ static struct snd_soc_dai_driver wm8782_dai = { }, }; -static struct snd_soc_codec_driver soc_codec_dev_wm8782 = { - .dapm_widgets = wm8782_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8782_dapm_widgets), - .dapm_routes = wm8782_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8782_dapm_routes), +static const struct snd_soc_codec_driver soc_codec_dev_wm8782 = { + .component_driver = { + .dapm_widgets = wm8782_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8782_dapm_widgets), + .dapm_routes = wm8782_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8782_dapm_routes), + }, }; static int wm8782_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 8d91470..af95d648 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -545,10 +545,12 @@ static struct snd_soc_dai_driver wm8804_dai = { static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { .idle_bias_off = true, - .dapm_widgets = wm8804_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), - .dapm_routes = wm8804_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8804_dapm_routes), + .component_driver = { + .dapm_widgets = wm8804_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), + .dapm_routes = wm8804_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8804_dapm_routes), + }, }; const struct regmap_config wm8804_regmap_config = { diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5d8dca88..c77b49a 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -1208,18 +1208,20 @@ static int wm8900_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8900 = { .probe = wm8900_probe, .suspend = wm8900_suspend, .resume = wm8900_resume, .set_bias_level = wm8900_set_bias_level, - .controls = wm8900_snd_controls, - .num_controls = ARRAY_SIZE(wm8900_snd_controls), - .dapm_widgets = wm8900_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8900_dapm_widgets), - .dapm_routes = wm8900_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8900_dapm_routes), + .component_driver = { + .controls = wm8900_snd_controls, + .num_controls = ARRAY_SIZE(wm8900_snd_controls), + .dapm_widgets = wm8900_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8900_dapm_widgets), + .dapm_routes = wm8900_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8900_dapm_routes), + }, }; static const struct regmap_config wm8900_regmap = { diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index a26ca49..6e887c2 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1830,7 +1830,7 @@ static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value) !!value << WM8903_GP1_LVL_SHIFT); } -static struct gpio_chip wm8903_template_chip = { +static const struct gpio_chip wm8903_template_chip = { .label = "wm8903", .owner = THIS_MODULE, .request = wm8903_gpio_request, @@ -1874,18 +1874,20 @@ static void wm8903_free_gpio(struct wm8903_priv *wm8903) } #endif -static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8903 = { .resume = wm8903_resume, .set_bias_level = wm8903_set_bias_level, .seq_notifier = wm8903_seq_notifier, .suspend_bias_off = true, - .controls = wm8903_snd_controls, - .num_controls = ARRAY_SIZE(wm8903_snd_controls), - .dapm_widgets = wm8903_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8903_dapm_widgets), - .dapm_routes = wm8903_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8903_intercon), + .component_driver = { + .controls = wm8903_snd_controls, + .num_controls = ARRAY_SIZE(wm8903_snd_controls), + .dapm_widgets = wm8903_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8903_dapm_widgets), + .dapm_routes = wm8903_intercon, + .num_dapm_routes = ARRAY_SIZE(wm8903_intercon), + }, }; static const struct regmap_config wm8903_regmap = { diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index edd7a77..4fd350e8 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2086,7 +2086,7 @@ static int wm8904_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8904 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8904 = { .probe = wm8904_probe, .remove = wm8904_remove, .set_bias_level = wm8904_set_bias_level, diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 1c60081..b593562 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -723,17 +723,19 @@ static int wm8940_probe(struct snd_soc_codec *codec) return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8940 = { .probe = wm8940_probe, .set_bias_level = wm8940_set_bias_level, .suspend_bias_off = true, - .controls = wm8940_snd_controls, - .num_controls = ARRAY_SIZE(wm8940_snd_controls), - .dapm_widgets = wm8940_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8940_dapm_widgets), - .dapm_routes = wm8940_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8940_dapm_routes), + .component_driver = { + .controls = wm8940_snd_controls, + .num_controls = ARRAY_SIZE(wm8940_snd_controls), + .dapm_widgets = wm8940_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8940_dapm_widgets), + .dapm_routes = wm8940_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8940_dapm_routes), + }, }; static const struct regmap_config wm8940_regmap = { diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 9db00d5..1edc7b1 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -940,17 +940,19 @@ err_enable: return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8955 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8955 = { .probe = wm8955_probe, .set_bias_level = wm8955_set_bias_level, .suspend_bias_off = true, - .controls = wm8955_snd_controls, - .num_controls = ARRAY_SIZE(wm8955_snd_controls), - .dapm_widgets = wm8955_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8955_dapm_widgets), - .dapm_routes = wm8955_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8955_dapm_routes), + .component_driver = { + .controls = wm8955_snd_controls, + .num_controls = ARRAY_SIZE(wm8955_snd_controls), + .dapm_widgets = wm8955_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8955_dapm_widgets), + .dapm_routes = wm8955_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8955_dapm_routes), + }, }; static const struct regmap_config wm8955_regmap = { diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index d7f444f..3bf081a 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -226,11 +226,10 @@ static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0); static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); static const DECLARE_TLV_DB_SCALE(lineinboost_tlv, -1500, 300, 1); -static const unsigned int micboost_tlv[] = { - TLV_DB_RANGE_HEAD(2), +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(micboost_tlv, 0, 1, TLV_DB_SCALE_ITEM(0, 1300, 0), 2, 3, TLV_DB_SCALE_ITEM(2000, 900, 0), -}; +); static const struct snd_kcontrol_new wm8960_snd_controls[] = { SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL, @@ -1264,7 +1263,7 @@ static int wm8960_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8960 = { .probe = wm8960_probe, .set_bias_level = wm8960_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index e30446a..e23ceac 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -882,18 +882,20 @@ static int wm8961_resume(struct snd_soc_codec *codec) #define wm8961_resume NULL #endif -static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8961 = { .probe = wm8961_probe, .resume = wm8961_resume, .set_bias_level = wm8961_set_bias_level, .suspend_bias_off = true, - .controls = wm8961_snd_controls, - .num_controls = ARRAY_SIZE(wm8961_snd_controls), - .dapm_widgets = wm8961_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8961_dapm_widgets), - .dapm_routes = audio_paths, - .num_dapm_routes = ARRAY_SIZE(audio_paths), + .component_driver = { + .controls = wm8961_snd_controls, + .num_controls = ARRAY_SIZE(wm8961_snd_controls), + .dapm_widgets = wm8961_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8961_dapm_widgets), + .dapm_routes = audio_paths, + .num_dapm_routes = ARRAY_SIZE(audio_paths), + }, }; static const struct regmap_config wm8961_regmap = { diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index f3109da..fd2731d 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3357,7 +3357,7 @@ static int wm8962_gpio_direction_out(struct gpio_chip *chip, return 0; } -static struct gpio_chip wm8962_template_chip = { +static const struct gpio_chip wm8962_template_chip = { .label = "wm8962", .owner = THIS_MODULE, .request = wm8962_gpio_request, @@ -3479,7 +3479,7 @@ static int wm8962_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8962 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8962 = { .probe = wm8962_probe, .remove = wm8962_remove, .set_bias_level = wm8962_set_bias_level, @@ -3713,7 +3713,7 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, ARRAY_SIZE(wm8962_dc_measure)); if (ret != 0) dev_err(&i2c->dev, - "Failed to configure for DC mesurement: %d\n", + "Failed to configure for DC measurement: %d\n", ret); } diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 2cdde32..887d31c 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -649,17 +649,19 @@ static int wm8971_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8971 = { .probe = wm8971_probe, .set_bias_level = wm8971_set_bias_level, .suspend_bias_off = true, - .controls = wm8971_snd_controls, - .num_controls = ARRAY_SIZE(wm8971_snd_controls), - .dapm_widgets = wm8971_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8971_dapm_widgets), - .dapm_routes = wm8971_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes), + .component_driver = { + .controls = wm8971_snd_controls, + .num_controls = ARRAY_SIZE(wm8971_snd_controls), + .dapm_widgets = wm8971_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8971_dapm_widgets), + .dapm_routes = wm8971_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes), + }, }; static const struct regmap_config wm8971_regmap = { diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index dc8c3b1..d414ddd 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -676,17 +676,19 @@ static int wm8974_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8974 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8974 = { .probe = wm8974_probe, .set_bias_level = wm8974_set_bias_level, .suspend_bias_off = true, - .controls = wm8974_snd_controls, - .num_controls = ARRAY_SIZE(wm8974_snd_controls), - .dapm_widgets = wm8974_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8974_dapm_widgets), - .dapm_routes = wm8974_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8974_dapm_routes), + .component_driver = { + .controls = wm8974_snd_controls, + .num_controls = ARRAY_SIZE(wm8974_snd_controls), + .dapm_widgets = wm8974_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8974_dapm_widgets), + .dapm_routes = wm8974_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8974_dapm_routes), + }, }; static int wm8974_i2c_probe(struct i2c_client *i2c, diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index d36d600..90b2d41 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -993,18 +993,20 @@ static int wm8978_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8978 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8978 = { .probe = wm8978_probe, .suspend = wm8978_suspend, .resume = wm8978_resume, .set_bias_level = wm8978_set_bias_level, - .controls = wm8978_snd_controls, - .num_controls = ARRAY_SIZE(wm8978_snd_controls), - .dapm_widgets = wm8978_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8978_dapm_widgets), - .dapm_routes = wm8978_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8978_dapm_routes), + .component_driver = { + .controls = wm8978_snd_controls, + .num_controls = ARRAY_SIZE(wm8978_snd_controls), + .dapm_widgets = wm8978_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8978_dapm_widgets), + .dapm_routes = wm8978_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8978_dapm_routes), + }, }; static const struct regmap_config wm8978_regmap_config = { diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 0c002a5..bfdbe72 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -976,16 +976,18 @@ static struct snd_soc_dai_driver wm8983_dai = { .symmetric_rates = 1 }; -static struct snd_soc_codec_driver soc_codec_dev_wm8983 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8983 = { .probe = wm8983_probe, .set_bias_level = wm8983_set_bias_level, .suspend_bias_off = true, - .controls = wm8983_snd_controls, - .num_controls = ARRAY_SIZE(wm8983_snd_controls), - .dapm_widgets = wm8983_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), - .dapm_routes = wm8983_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), + .component_driver = { + .controls = wm8983_snd_controls, + .num_controls = ARRAY_SIZE(wm8983_snd_controls), + .dapm_widgets = wm8983_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), + .dapm_routes = wm8983_audio_map, + .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), + }, }; static const struct regmap_config wm8983_regmap = { diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index 7347abf..05344f9 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c @@ -1105,17 +1105,19 @@ static struct snd_soc_dai_driver wm8985_dai = { .symmetric_rates = 1 }; -static struct snd_soc_codec_driver soc_codec_dev_wm8985 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8985 = { .probe = wm8985_probe, .set_bias_level = wm8985_set_bias_level, .suspend_bias_off = true, - .controls = wm8985_common_snd_controls, - .num_controls = ARRAY_SIZE(wm8985_common_snd_controls), - .dapm_widgets = wm8985_common_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8985_common_dapm_widgets), - .dapm_routes = wm8985_common_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8985_common_dapm_routes), + .component_driver = { + .controls = wm8985_common_snd_controls, + .num_controls = ARRAY_SIZE(wm8985_common_snd_controls), + .dapm_widgets = wm8985_common_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8985_common_dapm_widgets), + .dapm_routes = wm8985_common_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8985_common_dapm_routes), + }, }; static const struct regmap_config wm8985_regmap = { diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 895721a2..b0d0219 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -817,12 +817,14 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm8988 = { .set_bias_level = wm8988_set_bias_level, .suspend_bias_off = true, - .controls = wm8988_snd_controls, - .num_controls = ARRAY_SIZE(wm8988_snd_controls), - .dapm_widgets = wm8988_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8988_dapm_widgets), - .dapm_routes = wm8988_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes), + .component_driver = { + .controls = wm8988_snd_controls, + .num_controls = ARRAY_SIZE(wm8988_snd_controls), + .dapm_widgets = wm8988_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8988_dapm_widgets), + .dapm_routes = wm8988_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes), + }, }; static const struct regmap_config wm8988_regmap = { diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 23ecd30..a894500 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1294,17 +1294,19 @@ static int wm8990_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8990 = { .probe = wm8990_probe, .set_bias_level = wm8990_set_bias_level, .suspend_bias_off = true, - .controls = wm8990_snd_controls, - .num_controls = ARRAY_SIZE(wm8990_snd_controls), - .dapm_widgets = wm8990_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8990_dapm_widgets), - .dapm_routes = wm8990_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8990_dapm_routes), + .component_driver = { + .controls = wm8990_snd_controls, + .num_controls = ARRAY_SIZE(wm8990_snd_controls), + .dapm_widgets = wm8990_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8990_dapm_widgets), + .dapm_routes = wm8990_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8990_dapm_routes), + }, }; static const struct regmap_config wm8990_regmap = { diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index c9ee0ac..802c0694 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -111,14 +111,24 @@ static bool wm8991_volatile(struct device *dev, unsigned int reg) } } -static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); -static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000); -static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, 0, -2100); -static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600); -static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0); -static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0); -static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763); -static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(in_pga_tlv, -1650, 150, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(out_mix_tlv, -2100, 300, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(out_pga_tlv, + 0x00, 0x2f, SNDRV_CTL_TLVD_DB_SCALE_ITEM(SNDRV_CTL_TLVD_DB_GAIN_MUTE, 0, 1), + 0x30, 0x7f, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-7300, 100, 0), +); +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(out_dac_tlv, + 0x00, 0xbf, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-71625, 375, 1), + 0xc0, 0xff, SNDRV_CTL_TLVD_DB_SCALE_ITEM(0, 0, 0), +); +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(in_adc_tlv, + 0x00, 0xef, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-71625, 375, 1), + 0xf0, 0xff, SNDRV_CTL_TLVD_DB_SCALE_ITEM(17625, 0, 0), +); +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(out_sidetone_tlv, + 0x00, 0x0c, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-3600, 300, 0), + 0x0d, 0x0f, SNDRV_CTL_TLVD_DB_SCALE_ITEM(0, 0, 0), +); static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -398,7 +408,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, } /* INMIX dB values */ -static const DECLARE_TLV_DB_LINEAR(in_mix_tlv, -1200, 600); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(in_mix_tlv, -1200, 300, 1); /* Left In PGA Connections */ static const struct snd_kcontrol_new wm8991_dapm_lin12_pga_controls[] = { @@ -1232,16 +1242,18 @@ static struct snd_soc_dai_driver wm8991_dai = { .ops = &wm8991_ops }; -static struct snd_soc_codec_driver soc_codec_dev_wm8991 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8991 = { .set_bias_level = wm8991_set_bias_level, .suspend_bias_off = true, - .controls = wm8991_snd_controls, - .num_controls = ARRAY_SIZE(wm8991_snd_controls), - .dapm_widgets = wm8991_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8991_dapm_widgets), - .dapm_routes = wm8991_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8991_dapm_routes), + .component_driver = { + .controls = wm8991_snd_controls, + .num_controls = ARRAY_SIZE(wm8991_snd_controls), + .dapm_widgets = wm8991_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8991_dapm_widgets), + .dapm_routes = wm8991_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8991_dapm_routes), + }, }; static const struct regmap_config wm8991_regmap = { diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 8668c4c..195f7bf 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1613,7 +1613,7 @@ static const struct regmap_config wm8993_regmap = { .num_reg_defaults = ARRAY_SIZE(wm8993_reg_defaults), }; -static struct snd_soc_codec_driver soc_codec_dev_wm8993 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8993 = { .probe = wm8993_probe, .suspend = wm8993_suspend, .resume = wm8993_resume, diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index a18aecb..3896523 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -4439,7 +4439,7 @@ static struct regmap *wm8994_get_regmap(struct device *dev) return control->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8994 = { .probe = wm8994_codec_probe, .remove = wm8994_codec_remove, .suspend = wm8994_codec_suspend, diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 24500ba..19b08a5 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -2192,12 +2192,14 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm8995 = { .set_bias_level = wm8995_set_bias_level, .idle_bias_off = true, - .controls = wm8995_snd_controls, - .num_controls = ARRAY_SIZE(wm8995_snd_controls), - .dapm_widgets = wm8995_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8995_dapm_widgets), - .dapm_routes = wm8995_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8995_intercon), + .component_driver = { + .controls = wm8995_snd_controls, + .num_controls = ARRAY_SIZE(wm8995_snd_controls), + .dapm_widgets = wm8995_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8995_dapm_widgets), + .dapm_routes = wm8995_intercon, + .num_dapm_routes = ARRAY_SIZE(wm8995_intercon), + }, }; static const struct regmap_config wm8995_regmap = { diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index a730442..8affa49 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -2184,7 +2184,7 @@ static int wm8996_gpio_direction_in(struct gpio_chip *chip, unsigned offset) (1 << WM8996_GP1_DIR_SHIFT)); } -static struct gpio_chip wm8996_template_chip = { +static const struct gpio_chip wm8996_template_chip = { .label = "wm8996", .owner = THIS_MODULE, .direction_output = wm8996_gpio_direction_out, @@ -2684,18 +2684,20 @@ static int wm8996_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8996 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8996 = { .probe = wm8996_probe, .remove = wm8996_remove, .set_bias_level = wm8996_set_bias_level, .idle_bias_off = true, .seq_notifier = wm8996_seq_notifier, - .controls = wm8996_snd_controls, - .num_controls = ARRAY_SIZE(wm8996_snd_controls), - .dapm_widgets = wm8996_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8996_dapm_widgets), - .dapm_routes = wm8996_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8996_dapm_routes), + .component_driver = { + .controls = wm8996_snd_controls, + .num_controls = ARRAY_SIZE(wm8996_snd_controls), + .dapm_widgets = wm8996_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8996_dapm_widgets), + .dapm_routes = wm8996_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8996_dapm_routes), + }, .set_pll = wm8996_set_fll, }; diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 6b0785b..2f2821b 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -1095,7 +1095,7 @@ static struct regmap *wm8997_get_regmap(struct device *dev) return priv->core.arizona->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm8997 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8997 = { .probe = wm8997_codec_probe, .remove = wm8997_codec_remove, .get_regmap = wm8997_get_regmap, @@ -1105,12 +1105,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8997 = { .set_sysclk = arizona_set_sysclk, .set_pll = wm8997_set_fll, - .controls = wm8997_snd_controls, - .num_controls = ARRAY_SIZE(wm8997_snd_controls), - .dapm_widgets = wm8997_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8997_dapm_widgets), - .dapm_routes = wm8997_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8997_dapm_routes), + .component_driver = { + .controls = wm8997_snd_controls, + .num_controls = ARRAY_SIZE(wm8997_snd_controls), + .dapm_widgets = wm8997_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8997_dapm_widgets), + .dapm_routes = wm8997_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8997_dapm_routes), + }, }; static int wm8997_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 3a5c896..bcc2e10 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -966,6 +966,16 @@ static const struct snd_soc_dapm_route wm8998_dapm_routes[] = { { "IN2A", NULL, "SYSCLK" }, { "IN2B", NULL, "SYSCLK" }, + { "ASRC1L", NULL, "SYSCLK" }, + { "ASRC1R", NULL, "SYSCLK" }, + { "ASRC2L", NULL, "SYSCLK" }, + { "ASRC2R", NULL, "SYSCLK" }, + + { "ASRC1L", NULL, "ASYNCCLK" }, + { "ASRC1R", NULL, "ASYNCCLK" }, + { "ASRC2L", NULL, "ASYNCCLK" }, + { "ASRC2R", NULL, "ASYNCCLK" }, + { "SPD1", NULL, "SYSCLK" }, { "SPD1", NULL, "SPD1TX1" }, { "SPD1", NULL, "SPD1TX2" }, @@ -1351,7 +1361,7 @@ static struct regmap *wm8998_get_regmap(struct device *dev) return priv->core.arizona->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm8998 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8998 = { .probe = wm8998_codec_probe, .remove = wm8998_codec_remove, .get_regmap = wm8998_get_regmap, @@ -1361,12 +1371,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8998 = { .set_sysclk = arizona_set_sysclk, .set_pll = wm8998_set_fll, - .controls = wm8998_snd_controls, - .num_controls = ARRAY_SIZE(wm8998_snd_controls), - .dapm_widgets = wm8998_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8998_dapm_widgets), - .dapm_routes = wm8998_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8998_dapm_routes), + .component_driver = { + .controls = wm8998_snd_controls, + .num_controls = ARRAY_SIZE(wm8998_snd_controls), + .dapm_widgets = wm8998_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8998_dapm_widgets), + .dapm_routes = wm8998_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8998_dapm_routes), + }, }; static int wm8998_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 363b3b6..856867e 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -1274,7 +1274,7 @@ static int wm9081_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm9081 = { .probe = wm9081_probe, .set_sysclk = wm9081_set_sysclk, @@ -1282,12 +1282,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { .idle_bias_off = true, - .controls = wm9081_snd_controls, - .num_controls = ARRAY_SIZE(wm9081_snd_controls), - .dapm_widgets = wm9081_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm9081_dapm_widgets), - .dapm_routes = wm9081_audio_paths, - .num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths), + .component_driver = { + .controls = wm9081_snd_controls, + .num_controls = ARRAY_SIZE(wm9081_snd_controls), + .dapm_widgets = wm9081_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm9081_dapm_widgets), + .dapm_routes = wm9081_audio_paths, + .num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths), + }, }; static const struct regmap_config wm9081_regmap = { diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 5d73729..5a13138 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -550,7 +550,7 @@ static int wm9090_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm9090 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm9090 = { .probe = wm9090_probe, .set_bias_level = wm9090_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 744842c..dcdd055 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -352,7 +352,7 @@ static int wm9705_soc_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm9705 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm9705 = { .probe = wm9705_soc_probe, .remove = wm9705_soc_remove, .suspend = wm9705_soc_suspend, @@ -364,12 +364,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9705 = { .reg_cache_step = 2, .reg_cache_default = wm9705_reg, - .controls = wm9705_snd_ac97_controls, - .num_controls = ARRAY_SIZE(wm9705_snd_ac97_controls), - .dapm_widgets = wm9705_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm9705_dapm_widgets), - .dapm_routes = wm9705_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm9705_audio_map), + .component_driver = { + .controls = wm9705_snd_ac97_controls, + .num_controls = ARRAY_SIZE(wm9705_snd_ac97_controls), + .dapm_widgets = wm9705_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm9705_dapm_widgets), + .dapm_routes = wm9705_audio_map, + .num_dapm_routes = ARRAY_SIZE(wm9705_audio_map), + }, }; static int wm9705_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 488a922..557709e 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -669,7 +669,7 @@ static int wm9712_soc_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm9712 = { .probe = wm9712_soc_probe, .remove = wm9712_soc_remove, .resume = wm9712_soc_resume, @@ -682,12 +682,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { .reg_cache_step = 2, .reg_cache_default = wm9712_reg, - .controls = wm9712_snd_ac97_controls, - .num_controls = ARRAY_SIZE(wm9712_snd_ac97_controls), - .dapm_widgets = wm9712_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm9712_dapm_widgets), - .dapm_routes = wm9712_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm9712_audio_map), + .component_driver = { + .controls = wm9712_snd_ac97_controls, + .num_controls = ARRAY_SIZE(wm9712_snd_ac97_controls), + .dapm_widgets = wm9712_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm9712_dapm_widgets), + .dapm_routes = wm9712_audio_map, + .num_dapm_routes = ARRAY_SIZE(wm9712_audio_map), + }, }; static int wm9712_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 9849643..e4301dd 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -1235,19 +1235,21 @@ static int wm9713_soc_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm9713 = { .probe = wm9713_soc_probe, .remove = wm9713_soc_remove, .suspend = wm9713_soc_suspend, .resume = wm9713_soc_resume, .set_bias_level = wm9713_set_bias_level, - .controls = wm9713_snd_ac97_controls, - .num_controls = ARRAY_SIZE(wm9713_snd_ac97_controls), - .dapm_widgets = wm9713_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets), - .dapm_routes = wm9713_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm9713_audio_map), + .component_driver = { + .controls = wm9713_snd_ac97_controls, + .num_controls = ARRAY_SIZE(wm9713_snd_ac97_controls), + .dapm_widgets = wm9713_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets), + .dapm_routes = wm9713_audio_map, + .num_dapm_routes = ARRAY_SIZE(wm9713_audio_map), + }, }; static int wm9713_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 21fbe7d..b943dde 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -480,7 +480,7 @@ static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file, mutex_lock(&dsp->pwr_lock); - if (!dsp->wmfw_file_name || !dsp->running) + if (!dsp->wmfw_file_name || !dsp->booted) ret = 0; else ret = simple_read_from_buffer(user_buf, count, ppos, @@ -500,7 +500,7 @@ static ssize_t wm_adsp_debugfs_bin_read(struct file *file, mutex_lock(&dsp->pwr_lock); - if (!dsp->bin_file_name || !dsp->running) + if (!dsp->bin_file_name || !dsp->booted) ret = 0; else ret = simple_read_from_buffer(user_buf, count, ppos, @@ -554,6 +554,9 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp, if (!root) goto err; + if (!debugfs_create_bool("booted", S_IRUGO, root, &dsp->booted)) + goto err; + if (!debugfs_create_bool("running", S_IRUGO, root, &dsp->running)) goto err; @@ -637,7 +640,7 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, mutex_lock(&dsp[e->shift_l].pwr_lock); - if (dsp[e->shift_l].running || dsp[e->shift_l].compr) + if (dsp[e->shift_l].booted || dsp[e->shift_l].compr) ret = -EBUSY; else dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0]; @@ -789,7 +792,7 @@ static int wm_coeff_put(struct snd_kcontrol *kctl, memcpy(ctl->cache, p, ctl->len); ctl->set = 1; - if (ctl->enabled) + if (ctl->enabled && ctl->dsp->running) ret = wm_coeff_write_control(ctl, p, ctl->len); mutex_unlock(&ctl->dsp->pwr_lock); @@ -811,7 +814,7 @@ static int wm_coeff_tlv_put(struct snd_kcontrol *kctl, ret = -EFAULT; } else { ctl->set = 1; - if (ctl->enabled) + if (ctl->enabled && ctl->dsp->running) ret = wm_coeff_write_control(ctl, ctl->cache, size); } @@ -871,12 +874,12 @@ static int wm_coeff_get(struct snd_kcontrol *kctl, mutex_lock(&ctl->dsp->pwr_lock); if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { - if (ctl->enabled) + if (ctl->enabled && ctl->dsp->running) ret = wm_coeff_read_control(ctl, p, ctl->len); else ret = -EPERM; } else { - if (!ctl->flags && ctl->enabled) + if (!ctl->flags && ctl->enabled && ctl->dsp->running) ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len); memcpy(p, ctl->cache, ctl->len); @@ -898,12 +901,12 @@ static int wm_coeff_tlv_get(struct snd_kcontrol *kctl, mutex_lock(&ctl->dsp->pwr_lock); if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { - if (ctl->enabled) + if (ctl->enabled && ctl->dsp->running) ret = wm_coeff_read_control(ctl, ctl->cache, size); else ret = -EPERM; } else { - if (!ctl->flags && ctl->enabled) + if (!ctl->flags && ctl->enabled && ctl->dsp->running) ret = wm_coeff_read_control(ctl, ctl->cache, size); } @@ -2166,13 +2169,20 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, if (ret != 0) goto err_ena; + dsp->booted = true; + /* Start the core running */ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, ADSP1_CORE_ENA | ADSP1_START, ADSP1_CORE_ENA | ADSP1_START); + + dsp->running = true; break; case SND_SOC_DAPM_PRE_PMD: + dsp->running = false; + dsp->booted = false; + /* Halt the core */ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, ADSP1_CORE_ENA | ADSP1_START, 0); @@ -2227,7 +2237,7 @@ static int wm_adsp2_ena(struct wm_adsp *dsp) if (val & ADSP2_RAM_RDY) break; - msleep(1); + usleep_range(250, 500); } if (!(val & ADSP2_RAM_RDY)) { @@ -2249,6 +2259,11 @@ static void wm_adsp2_boot_work(struct work_struct *work) mutex_lock(&dsp->pwr_lock); + ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, + ADSP2_MEM_ENA, ADSP2_MEM_ENA); + if (ret != 0) + goto err_mutex; + ret = wm_adsp2_ena(dsp); if (ret != 0) goto err_mutex; @@ -2270,13 +2285,14 @@ static void wm_adsp2_boot_work(struct work_struct *work) if (ret != 0) goto err_ena; - /* Sync set controls */ - ret = wm_coeff_sync_controls(dsp); + dsp->booted = true; + + /* Turn DSP back off until we are ready to run */ + ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, + ADSP2_SYS_ENA, 0); if (ret != 0) goto err_ena; - dsp->running = true; - mutex_unlock(&dsp->pwr_lock); return; @@ -2307,6 +2323,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); struct wm_adsp *dsp = &dsps[w->shift]; + struct wm_coeff_ctl *ctl; dsp->card = codec->component.card; @@ -2315,6 +2332,24 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, wm_adsp2_set_dspclk(dsp, freq); queue_work(system_unbound_wq, &dsp->boot_work); break; + case SND_SOC_DAPM_PRE_PMD: + wm_adsp_debugfs_clear(dsp); + + dsp->fw_id = 0; + dsp->fw_id_version = 0; + + dsp->booted = false; + + regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, + ADSP2_MEM_ENA, 0); + + list_for_each_entry(ctl, &dsp->ctl_list, list) + ctl->enabled = 0; + + wm_adsp_free_alg_regions(dsp); + + adsp_dbg(dsp, "Shutdown complete\n"); + break; default: break; } @@ -2329,16 +2364,24 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); struct wm_adsp *dsp = &dsps[w->shift]; - struct wm_coeff_ctl *ctl; int ret; switch (event) { case SND_SOC_DAPM_POST_PMU: flush_work(&dsp->boot_work); - if (!dsp->running) + if (!dsp->booted) return -EIO; + ret = wm_adsp2_ena(dsp); + if (ret != 0) + goto err; + + /* Sync set controls */ + ret = wm_coeff_sync_controls(dsp); + if (ret != 0) + goto err; + ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, ADSP2_CORE_ENA | ADSP2_START, @@ -2346,6 +2389,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, if (ret != 0) goto err; + dsp->running = true; + mutex_lock(&dsp->pwr_lock); if (wm_adsp_fw[dsp->fw].num_caps != 0) @@ -2361,10 +2406,6 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, mutex_lock(&dsp->pwr_lock); - wm_adsp_debugfs_clear(dsp); - - dsp->fw_id = 0; - dsp->fw_id_version = 0; dsp->running = false; regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, @@ -2378,17 +2419,12 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, ADSP2_SYS_ENA, 0); - list_for_each_entry(ctl, &dsp->ctl_list, list) - ctl->enabled = 0; - - wm_adsp_free_alg_regions(dsp); - if (wm_adsp_fw[dsp->fw].num_caps != 0) wm_adsp_buffer_free(dsp); mutex_unlock(&dsp->pwr_lock); - adsp_dbg(dsp, "Shutdown complete\n"); + adsp_dbg(dsp, "Execution stopped\n"); break; default: diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index be3b5bc..362dd7c 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -61,6 +61,8 @@ struct wm_adsp { int fw; int fw_ver; + + bool booted; bool running; struct list_head ctl_list; @@ -85,9 +87,10 @@ struct wm_adsp { wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) #define WM_ADSP2(wname, num, event_fn) \ -{ .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \ +{ .id = snd_soc_dapm_supply, .name = wname " Preloader", \ .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ - .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \ + .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD, \ + .subseq = 100, /* Ensure we run after SYSCLK supply widget */ }, \ { .id = snd_soc_dapm_out_drv, .name = wname, \ .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } |