From 4f29b663c08d369fe320a148179996c94cf7d01b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 7 Jun 2018 15:50:48 +0200 Subject: ASoC: rt1305: Use ULL suffixes for 64-bit constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With gcc 4.1.2: sound/soc/codecs/rt1305.c: In function ‘rt1305_calibrate’: sound/soc/codecs/rt1305.c:1069: warning: integer constant is too large for ‘long’ type sound/soc/codecs/rt1305.c:1086: warning: integer constant is too large for ‘long’ type Add the missing "ULL" suffixes to fix this. Fixes: 29bc643ddd7efb74 ("ASoC: rt1305: Add RT1305/RT1306 amplifier driver") Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- sound/soc/codecs/rt1305.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt1305.c b/sound/soc/codecs/rt1305.c index f4c8c45f4010..421b8fb2fa04 100644 --- a/sound/soc/codecs/rt1305.c +++ b/sound/soc/codecs/rt1305.c @@ -1066,7 +1066,7 @@ static void rt1305_calibrate(struct rt1305_priv *rt1305) pr_debug("Left_rhl = 0x%x rh=0x%x rl=0x%x\n", rhl, rh, rl); pr_info("Left channel %d.%dohm\n", (r0ohm/10), (r0ohm%10)); - r0l = 562949953421312; + r0l = 562949953421312ULL; if (rhl != 0) do_div(r0l, rhl); pr_debug("Left_r0 = 0x%llx\n", r0l); @@ -1083,7 +1083,7 @@ static void rt1305_calibrate(struct rt1305_priv *rt1305) pr_debug("Right_rhl = 0x%x rh=0x%x rl=0x%x\n", rhl, rh, rl); pr_info("Right channel %d.%dohm\n", (r0ohm/10), (r0ohm%10)); - r0r = 562949953421312; + r0r = 562949953421312ULL; if (rhl != 0) do_div(r0r, rhl); pr_debug("Right_r0 = 0x%llx\n", r0r); -- cgit v1.2.3 From e380be7c557c4ddb1cb71404c10e0bfb3daf4644 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 6 Jun 2018 10:57:19 +0100 Subject: ASoC: ak5558: make two structures static The structure ak5558_pm and soc_codec_dev_ak5558 are local to the source and do not need to be in global scope, so make them static. Also make soc_codec_dev_ak5558 static. Cleans up sparse warnings: warning: symbol 'ak5558_pm' was not declared. Should it be static? warning: symbol 'soc_codec_dev_ak5558' was not declared. Should it be static? Signed-off-by: Colin Ian King Reviewed-by: Daniel Baluta Signed-off-by: Mark Brown --- sound/soc/codecs/ak5558.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c index f4ed5cc40661..448bb90c9c8e 100644 --- a/sound/soc/codecs/ak5558.c +++ b/sound/soc/codecs/ak5558.c @@ -322,13 +322,13 @@ static int __maybe_unused ak5558_runtime_resume(struct device *dev) return regcache_sync(ak5558->regmap); } -const struct dev_pm_ops ak5558_pm = { +static const struct dev_pm_ops ak5558_pm = { SET_RUNTIME_PM_OPS(ak5558_runtime_suspend, ak5558_runtime_resume, NULL) SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; -struct snd_soc_component_driver soc_codec_dev_ak5558 = { +static const struct snd_soc_component_driver soc_codec_dev_ak5558 = { .probe = ak5558_probe, .remove = ak5558_remove, .controls = ak5558_snd_controls, -- cgit v1.2.3 From 62624f72592b1d8e756e699cd6ade2be379f95a9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 6 Jun 2018 11:31:23 +0100 Subject: ASoC: ak4458: make structure soc_codec_dev_ak4458 static const The structure soc_codec_dev_ak4458 is local to the source and do not need to be in global scope and can be const, make it static const. Cleans up sparse warnings: warning: symbol 'soc_codec_dev_ak4458' was not declared. Should it be static? Signed-off-by: Colin Ian King Signed-off-by: Mark Brown --- sound/soc/codecs/ak4458.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c index 31ec0ba2e639..299ada4dfaa0 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -558,7 +558,7 @@ static int __maybe_unused ak4458_runtime_resume(struct device *dev) } #endif /* CONFIG_PM */ -struct snd_soc_component_driver soc_codec_dev_ak4458 = { +static const struct snd_soc_component_driver soc_codec_dev_ak4458 = { .probe = ak4458_probe, .remove = ak4458_remove, .controls = ak4458_snd_controls, -- cgit v1.2.3 From 58f7d470c85801f55bbae2d3c93fe1a3d34aa143 Mon Sep 17 00:00:00 2001 From: Steven Eckhoff Date: Mon, 4 Jun 2018 15:45:40 -0500 Subject: ASoC: TSCS42xx: Add mic bias boost control Add mic bias boost control Signed-off-by: Steven Eckhoff Signed-off-by: Mark Brown --- sound/soc/codecs/tscs42xx.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/tscs42xx.c b/sound/soc/codecs/tscs42xx.c index d18ff17719cc..743194052fc4 100644 --- a/sound/soc/codecs/tscs42xx.c +++ b/sound/soc/codecs/tscs42xx.c @@ -644,6 +644,9 @@ static const struct snd_kcontrol_new tscs42xx_snd_controls[] = { /* Input Channel Map */ SOC_ENUM("Input Channel Map", ch_map_select_enum), + /* Mic Bias */ + SOC_SINGLE("Mic Bias Boost Switch", 0x71, 0x07, 1, 0), + /* Coefficient Ram */ COEFF_RAM_CTL("Cascade1L BiQuad1", BIQUAD_SIZE, 0x00), COEFF_RAM_CTL("Cascade1L BiQuad2", BIQUAD_SIZE, 0x05), -- cgit v1.2.3 From 19d996cc3ad698379bcd8482dabe78abe3dc8d96 Mon Sep 17 00:00:00 2001 From: Steven Eckhoff Date: Mon, 4 Jun 2018 15:46:28 -0500 Subject: ASoC: TSCS42xx: Remove Playback/Capture in names These aren't needed and some userspace apps don't work consistently with them. Remove Playback/Capture from control names Signed-off-by: Steven Eckhoff Signed-off-by: Mark Brown --- sound/soc/codecs/tscs42xx.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/tscs42xx.c b/sound/soc/codecs/tscs42xx.c index 743194052fc4..5d596e4dab0c 100644 --- a/sound/soc/codecs/tscs42xx.c +++ b/sound/soc/codecs/tscs42xx.c @@ -625,19 +625,19 @@ static int bytes_info_ext(struct snd_kcontrol *kcontrol, static const struct snd_kcontrol_new tscs42xx_snd_controls[] = { /* Volumes */ - SOC_DOUBLE_R_TLV("Headphone Playback Volume", R_HPVOLL, R_HPVOLR, + SOC_DOUBLE_R_TLV("Headphone Volume", R_HPVOLL, R_HPVOLR, FB_HPVOLL, 0x7F, 0, hpvol_scale), - SOC_DOUBLE_R_TLV("Speaker Playback Volume", R_SPKVOLL, R_SPKVOLR, + SOC_DOUBLE_R_TLV("Speaker Volume", R_SPKVOLL, R_SPKVOLR, FB_SPKVOLL, 0x7F, 0, spkvol_scale), - SOC_DOUBLE_R_TLV("Master Playback Volume", R_DACVOLL, R_DACVOLR, + SOC_DOUBLE_R_TLV("Master Volume", R_DACVOLL, R_DACVOLR, FB_DACVOLL, 0xFF, 0, dacvol_scale), - SOC_DOUBLE_R_TLV("PCM Capture Volume", R_ADCVOLL, R_ADCVOLR, + SOC_DOUBLE_R_TLV("PCM Volume", R_ADCVOLL, R_ADCVOLR, FB_ADCVOLL, 0xFF, 0, adcvol_scale), - SOC_DOUBLE_R_TLV("Master Capture Volume", R_INVOLL, R_INVOLR, + SOC_DOUBLE_R_TLV("Input Volume", R_INVOLL, R_INVOLR, FB_INVOLL, 0x3F, 0, invol_scale), /* INSEL */ - SOC_DOUBLE_R_TLV("Mic Boost Capture Volume", R_INSELL, R_INSELR, + SOC_DOUBLE_R_TLV("Mic Boost Volume", R_INSELL, R_INSELR, FB_INSELL_MICBSTL, FV_INSELL_MICBSTL_30DB, 0, mic_boost_scale), @@ -736,9 +736,9 @@ static const struct snd_kcontrol_new tscs42xx_snd_controls[] = { R_CLECTL, FB_CLECTL_LIMIT_EN, 1, 0), SOC_SINGLE("Comp Switch", R_CLECTL, FB_CLECTL_COMP_EN, 1, 0), - SOC_SINGLE_TLV("CLE Make-Up Gain Playback Volume", + SOC_SINGLE_TLV("CLE Make-Up Gain Volume", R_MUGAIN, FB_MUGAIN_CLEMUG, 0x1f, 0, mugain_scale), - SOC_SINGLE_TLV("Comp Thresh Playback Volume", + SOC_SINGLE_TLV("Comp Thresh Volume", R_COMPTH, FB_COMPTH, 0xff, 0, compth_scale), SOC_ENUM("Comp Ratio", compressor_ratio_enum), SND_SOC_BYTES("Comp Atk Time", R_CATKTCL, 2), @@ -769,9 +769,9 @@ static const struct snd_kcontrol_new tscs42xx_snd_controls[] = { SOC_SINGLE("MBC1 Phase Invert Switch", R_DACMBCMUG1, FB_DACMBCMUG1_PHASE, 1, 0), - SOC_SINGLE_TLV("DAC MBC1 Make-Up Gain Playback Volume", + SOC_SINGLE_TLV("DAC MBC1 Make-Up Gain Volume", R_DACMBCMUG1, FB_DACMBCMUG1_MUGAIN, 0x1f, 0, mugain_scale), - SOC_SINGLE_TLV("DAC MBC1 Comp Thresh Playback Volume", + SOC_SINGLE_TLV("DAC MBC1 Comp Thresh Volume", R_DACMBCTHR1, FB_DACMBCTHR1_THRESH, 0xff, 0, compth_scale), SOC_ENUM("DAC MBC1 Comp Ratio", dac_mbc1_compressor_ratio_enum), @@ -781,9 +781,9 @@ static const struct snd_kcontrol_new tscs42xx_snd_controls[] = { SOC_SINGLE("MBC2 Phase Invert Switch", R_DACMBCMUG2, FB_DACMBCMUG2_PHASE, 1, 0), - SOC_SINGLE_TLV("DAC MBC2 Make-Up Gain Playback Volume", + SOC_SINGLE_TLV("DAC MBC2 Make-Up Gain Volume", R_DACMBCMUG2, FB_DACMBCMUG2_MUGAIN, 0x1f, 0, mugain_scale), - SOC_SINGLE_TLV("DAC MBC2 Comp Thresh Playback Volume", + SOC_SINGLE_TLV("DAC MBC2 Comp Thresh Volume", R_DACMBCTHR2, FB_DACMBCTHR2_THRESH, 0xff, 0, compth_scale), SOC_ENUM("DAC MBC2 Comp Ratio", dac_mbc2_compressor_ratio_enum), @@ -793,9 +793,9 @@ static const struct snd_kcontrol_new tscs42xx_snd_controls[] = { SOC_SINGLE("MBC3 Phase Invert Switch", R_DACMBCMUG3, FB_DACMBCMUG3_PHASE, 1, 0), - SOC_SINGLE_TLV("DAC MBC3 Make-Up Gain Playback Volume", + SOC_SINGLE_TLV("DAC MBC3 Make-Up Gain Volume", R_DACMBCMUG3, FB_DACMBCMUG3_MUGAIN, 0x1f, 0, mugain_scale), - SOC_SINGLE_TLV("DAC MBC3 Comp Thresh Playback Volume", + SOC_SINGLE_TLV("DAC MBC3 Comp Thresh Volume", R_DACMBCTHR3, FB_DACMBCTHR3_THRESH, 0xff, 0, compth_scale), SOC_ENUM("DAC MBC3 Comp Ratio", dac_mbc3_compressor_ratio_enum), -- cgit v1.2.3 From 53af408cd9f2d1c66bc081c1d82797bfe44af3e5 Mon Sep 17 00:00:00 2001 From: Steven Eckhoff Date: Mon, 4 Jun 2018 15:47:02 -0500 Subject: ASoC: TSCS42xx: Add headphone auto switching Add headphone auto switching controls Signed-off-by: Steven Eckhoff Signed-off-by: Mark Brown --- sound/soc/codecs/tscs42xx.c | 6 ++++++ sound/soc/codecs/tscs42xx.h | 8 ++++++++ 2 files changed, 14 insertions(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/tscs42xx.c b/sound/soc/codecs/tscs42xx.c index 5d596e4dab0c..7396a6e5277e 100644 --- a/sound/soc/codecs/tscs42xx.c +++ b/sound/soc/codecs/tscs42xx.c @@ -647,6 +647,12 @@ static const struct snd_kcontrol_new tscs42xx_snd_controls[] = { /* Mic Bias */ SOC_SINGLE("Mic Bias Boost Switch", 0x71, 0x07, 1, 0), + /* Headphone Auto Switching */ + SOC_SINGLE("Headphone Auto Switching Switch", + R_CTL, FB_CTL_HPSWEN, 1, 0), + SOC_SINGLE("Headphone Detect Polarity Toggle Switch", + R_CTL, FB_CTL_HPSWPOL, 1, 0), + /* Coefficient Ram */ COEFF_RAM_CTL("Cascade1L BiQuad1", BIQUAD_SIZE, 0x00), COEFF_RAM_CTL("Cascade1L BiQuad2", BIQUAD_SIZE, 0x05), diff --git a/sound/soc/codecs/tscs42xx.h b/sound/soc/codecs/tscs42xx.h index 814c8f3c4a68..6b3a21081635 100644 --- a/sound/soc/codecs/tscs42xx.h +++ b/sound/soc/codecs/tscs42xx.h @@ -34,6 +34,7 @@ enum { #define R_DACSR 0x19 #define R_PWRM1 0x1A #define R_PWRM2 0x1B +#define R_CTL 0x1C #define R_CONFIG0 0x1F #define R_CONFIG1 0x20 #define R_DMICCTL 0x24 @@ -1110,6 +1111,13 @@ enum { #define RV_PWRM2_VREF_DISABLE \ RV(FV_PWRM2_VREF_DISABLE, FB_PWRM2_VREF) +/****************************** + * R_CTL (0x1C) * + ******************************/ + +/* Fiel Offsets */ +#define FB_CTL_HPSWEN 7 +#define FB_CTL_HPSWPOL 6 /****************************** * R_CONFIG0 (0x1F) * -- cgit v1.2.3 From 0ddce71c21f03fd19867c4939d3ca710f37cdf1a Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 7 Jun 2018 16:37:38 +0800 Subject: ASoC: rt5682: add rt5682 codec driver This is the initial codec driver for rt5682. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/rt5682.txt | 50 + include/sound/rt5682.h | 40 + sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt5682.c | 2682 ++++++++++++++++++++ sound/soc/codecs/rt5682.h | 1324 ++++++++++ 6 files changed, 4104 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/rt5682.txt create mode 100644 include/sound/rt5682.h create mode 100644 sound/soc/codecs/rt5682.c create mode 100644 sound/soc/codecs/rt5682.h (limited to 'sound/soc/codecs') diff --git a/Documentation/devicetree/bindings/sound/rt5682.txt b/Documentation/devicetree/bindings/sound/rt5682.txt new file mode 100644 index 000000000000..312e9a129530 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rt5682.txt @@ -0,0 +1,50 @@ +RT5682 audio CODEC + +This device supports I2C only. + +Required properties: + +- compatible : "realtek,rt5682" or "realtek,rt5682i" + +- reg : The I2C address of the device. + +Optional properties: + +- interrupts : The CODEC's interrupt output. + +- realtek,dmic1-data-pin + 0: dmic1 is not used + 1: using GPIO2 pin as dmic1 data pin + 2: using GPIO5 pin as dmic1 data pin + +- realtek,dmic1-clk-pin + 0: using GPIO1 pin as dmic1 clock pin + 1: using GPIO3 pin as dmic1 clock pin + +- realtek,jd-src + 0: No JD is used + 1: using JD1 as JD source + +- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin. + +Pins on the device (for linking into audio routes) for RT5682: + + * DMIC L1 + * DMIC R1 + * IN1P + * HPOL + * HPOR + +Example: + +rt5682 { + compatible = "realtek,rt5682i"; + reg = <0x1a>; + interrupt-parent = <&gpio>; + interrupts = ; + realtek,ldo1-en-gpios = + <&gpio TEGRA_GPIO(R, 2) GPIO_ACTIVE_HIGH>; + realtek,dmic1-data-pin = <1>; + realtek,dmic1-clk-pin = <1>; + realtek,jd-src = <1>; +}; diff --git a/include/sound/rt5682.h b/include/sound/rt5682.h new file mode 100644 index 000000000000..0251797ab438 --- /dev/null +++ b/include/sound/rt5682.h @@ -0,0 +1,40 @@ +/* + * linux/sound/rt5682.h -- Platform data for RT5682 + * + * Copyright 2018 Realtek Microelectronics + * + * 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 __LINUX_SND_RT5682_H +#define __LINUX_SND_RT5682_H + +enum rt5682_dmic1_data_pin { + RT5682_DMIC1_NULL, + RT5682_DMIC1_DATA_GPIO2, + RT5682_DMIC1_DATA_GPIO5, +}; + +enum rt5682_dmic1_clk_pin { + RT5682_DMIC1_CLK_GPIO1, + RT5682_DMIC1_CLK_GPIO3, +}; + +enum rt5682_jd_src { + RT5682_JD_NULL, + RT5682_JD1, +}; + +struct rt5682_platform_data { + + int ldo1_en; /* GPIO for LDO1_EN */ + + enum rt5682_dmic1_data_pin dmic1_data_pin; + enum rt5682_dmic1_clk_pin dmic1_clk_pin; + enum rt5682_jd_src jd_src; +}; + +#endif + diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 63cf62e9c9aa..f6b8d4bf8796 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -141,6 +141,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_RT5668 if I2C select SND_SOC_RT5670 if I2C select SND_SOC_RT5677 if I2C && SPI_MASTER + select SND_SOC_RT5682 if I2C select SND_SOC_SGTL5000 if I2C select SND_SOC_SI476X if MFD_SI476X_CORE select SND_SOC_SIRF_AUDIO_CODEC @@ -778,6 +779,7 @@ config SND_SOC_RL6231 default y if SND_SOC_RT5668=y default y if SND_SOC_RT5670=y default y if SND_SOC_RT5677=y + default y if SND_SOC_RT5682=y default y if SND_SOC_RT1305=y default m if SND_SOC_RT5514=m default m if SND_SOC_RT5616=m @@ -791,6 +793,7 @@ config SND_SOC_RL6231 default m if SND_SOC_RT5668=m default m if SND_SOC_RT5670=m default m if SND_SOC_RT5677=m + default m if SND_SOC_RT5682=m default m if SND_SOC_RT1305=m config SND_SOC_RL6347A @@ -871,6 +874,9 @@ config SND_SOC_RT5677_SPI tristate default SND_SOC_RT5677 && SPI +config SND_SOC_RT5682 + tristate + #Freescale sgtl5000 codec config SND_SOC_SGTL5000 tristate "Freescale SGTL5000 CODEC" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index e023fdf85221..e43d99a039d3 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -146,6 +146,7 @@ snd-soc-rt5668-objs := rt5668.o snd-soc-rt5670-objs := rt5670.o snd-soc-rt5677-objs := rt5677.o snd-soc-rt5677-spi-objs := rt5677-spi.o +snd-soc-rt5682-objs := rt5682.o snd-soc-sgtl5000-objs := sgtl5000.o snd-soc-alc5623-objs := alc5623.o snd-soc-alc5632-objs := alc5632.o @@ -405,6 +406,7 @@ obj-$(CONFIG_SND_SOC_RT5668) += snd-soc-rt5668.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 +obj-$(CONFIG_SND_SOC_RT5682) += snd-soc-rt5682.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c new file mode 100644 index 000000000000..61a97301bcfa --- /dev/null +++ b/sound/soc/codecs/rt5682.c @@ -0,0 +1,2682 @@ +/* + * rt5682.c -- RT5682 ALSA SoC audio component driver + * + * Copyright 2018 Realtek Semiconductor Corp. + * Author: Bard Liao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rl6231.h" +#include "rt5682.h" + +#define RT5682_NUM_SUPPLIES 3 + +static const char *rt5682_supply_names[RT5682_NUM_SUPPLIES] = { + "AVDD", + "MICVDD", + "VBAT", +}; + +struct rt5682_priv { + struct snd_soc_component *component; + struct rt5682_platform_data pdata; + struct regmap *regmap; + struct snd_soc_jack *hs_jack; + struct regulator_bulk_data supplies[RT5682_NUM_SUPPLIES]; + struct delayed_work jack_detect_work; + struct delayed_work jd_check_work; + struct mutex calibrate_mutex; + + int sysclk; + int sysclk_src; + int lrck[RT5682_AIFS]; + int bclk[RT5682_AIFS]; + int master[RT5682_AIFS]; + + int pll_src; + int pll_in; + int pll_out; + + int jack_type; +}; + +static const struct reg_sequence patch_list[] = { + {0x01c1, 0x1000}, +}; + +static const struct reg_default rt5682_reg[] = { + {0x0002, 0x8080}, + {0x0003, 0x8000}, + {0x0005, 0x0000}, + {0x0006, 0x0000}, + {0x0008, 0x800f}, + {0x000b, 0x0000}, + {0x0010, 0x4040}, + {0x0011, 0x0000}, + {0x0012, 0x1404}, + {0x0013, 0x1000}, + {0x0014, 0xa00a}, + {0x0015, 0x0404}, + {0x0016, 0x0404}, + {0x0019, 0xafaf}, + {0x001c, 0x2f2f}, + {0x001f, 0x0000}, + {0x0022, 0x5757}, + {0x0023, 0x0039}, + {0x0024, 0x000b}, + {0x0026, 0xc0c4}, + {0x0029, 0x8080}, + {0x002a, 0xa0a0}, + {0x002b, 0x0300}, + {0x0030, 0x0000}, + {0x003c, 0x0080}, + {0x0044, 0x0c0c}, + {0x0049, 0x0000}, + {0x0061, 0x0000}, + {0x0062, 0x0000}, + {0x0063, 0x003f}, + {0x0064, 0x0000}, + {0x0065, 0x0000}, + {0x0066, 0x0030}, + {0x0067, 0x0000}, + {0x006b, 0x0000}, + {0x006c, 0x0000}, + {0x006d, 0x2200}, + {0x006e, 0x0a10}, + {0x0070, 0x8000}, + {0x0071, 0x8000}, + {0x0073, 0x0000}, + {0x0074, 0x0000}, + {0x0075, 0x0002}, + {0x0076, 0x0001}, + {0x0079, 0x0000}, + {0x007a, 0x0000}, + {0x007b, 0x0000}, + {0x007c, 0x0100}, + {0x007e, 0x0000}, + {0x0080, 0x0000}, + {0x0081, 0x0000}, + {0x0082, 0x0000}, + {0x0083, 0x0000}, + {0x0084, 0x0000}, + {0x0085, 0x0000}, + {0x0086, 0x0005}, + {0x0087, 0x0000}, + {0x0088, 0x0000}, + {0x008c, 0x0003}, + {0x008d, 0x0000}, + {0x008e, 0x0060}, + {0x008f, 0x1000}, + {0x0091, 0x0c26}, + {0x0092, 0x0073}, + {0x0093, 0x0000}, + {0x0094, 0x0080}, + {0x0098, 0x0000}, + {0x009a, 0x0000}, + {0x009b, 0x0000}, + {0x009c, 0x0000}, + {0x009d, 0x0000}, + {0x009e, 0x100c}, + {0x009f, 0x0000}, + {0x00a0, 0x0000}, + {0x00a3, 0x0002}, + {0x00a4, 0x0001}, + {0x00ae, 0x2040}, + {0x00af, 0x0000}, + {0x00b6, 0x0000}, + {0x00b7, 0x0000}, + {0x00b8, 0x0000}, + {0x00b9, 0x0002}, + {0x00be, 0x0000}, + {0x00c0, 0x0160}, + {0x00c1, 0x82a0}, + {0x00c2, 0x0000}, + {0x00d0, 0x0000}, + {0x00d1, 0x2244}, + {0x00d2, 0x3300}, + {0x00d3, 0x2200}, + {0x00d4, 0x0000}, + {0x00d9, 0x0009}, + {0x00da, 0x0000}, + {0x00db, 0x0000}, + {0x00dc, 0x00c0}, + {0x00dd, 0x2220}, + {0x00de, 0x3131}, + {0x00df, 0x3131}, + {0x00e0, 0x3131}, + {0x00e2, 0x0000}, + {0x00e3, 0x4000}, + {0x00e4, 0x0aa0}, + {0x00e5, 0x3131}, + {0x00e6, 0x3131}, + {0x00e7, 0x3131}, + {0x00e8, 0x3131}, + {0x00ea, 0xb320}, + {0x00eb, 0x0000}, + {0x00f0, 0x0000}, + {0x00f1, 0x00d0}, + {0x00f2, 0x00d0}, + {0x00f6, 0x0000}, + {0x00fa, 0x0000}, + {0x00fb, 0x0000}, + {0x00fc, 0x0000}, + {0x00fd, 0x0000}, + {0x00fe, 0x10ec}, + {0x00ff, 0x6530}, + {0x0100, 0xa0a0}, + {0x010b, 0x0000}, + {0x010c, 0xae00}, + {0x010d, 0xaaa0}, + {0x010e, 0x8aa2}, + {0x010f, 0x02a2}, + {0x0110, 0xc000}, + {0x0111, 0x04a2}, + {0x0112, 0x2800}, + {0x0113, 0x0000}, + {0x0117, 0x0100}, + {0x0125, 0x0410}, + {0x0132, 0x6026}, + {0x0136, 0x5555}, + {0x0138, 0x3700}, + {0x013a, 0x2000}, + {0x013b, 0x2000}, + {0x013c, 0x2005}, + {0x013f, 0x0000}, + {0x0142, 0x0000}, + {0x0145, 0x0002}, + {0x0146, 0x0000}, + {0x0147, 0x0000}, + {0x0148, 0x0000}, + {0x0149, 0x0000}, + {0x0150, 0x79a1}, + {0x0151, 0x0000}, + {0x0160, 0x4ec0}, + {0x0161, 0x0080}, + {0x0162, 0x0200}, + {0x0163, 0x0800}, + {0x0164, 0x0000}, + {0x0165, 0x0000}, + {0x0166, 0x0000}, + {0x0167, 0x000f}, + {0x0168, 0x000f}, + {0x0169, 0x0021}, + {0x0190, 0x413d}, + {0x0194, 0x0000}, + {0x0195, 0x0000}, + {0x0197, 0x0022}, + {0x0198, 0x0000}, + {0x0199, 0x0000}, + {0x01af, 0x0000}, + {0x01b0, 0x0400}, + {0x01b1, 0x0000}, + {0x01b2, 0x0000}, + {0x01b3, 0x0000}, + {0x01b4, 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}, + {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, 0x0000}, + {0x01d7, 0x0008}, + {0x01d8, 0x0029}, + {0x01d9, 0x3333}, + {0x01da, 0x0000}, + {0x01db, 0x0004}, + {0x01dc, 0x0000}, + {0x01de, 0x7c00}, + {0x01df, 0x0320}, + {0x01e0, 0x06a1}, + {0x01e1, 0x0000}, + {0x01e2, 0x0000}, + {0x01e3, 0x0000}, + {0x01e4, 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}, + {0x0210, 0x6297}, + {0x0211, 0xa005}, + {0x0212, 0x824c}, + {0x0213, 0xf7ff}, + {0x0214, 0xf24c}, + {0x0215, 0x0102}, + {0x0216, 0x00a3}, + {0x0217, 0x0048}, + {0x0218, 0xa2c0}, + {0x0219, 0x0400}, + {0x021a, 0x00c8}, + {0x021b, 0x00c0}, + {0x021c, 0x0000}, + {0x0250, 0x4500}, + {0x0251, 0x40b3}, + {0x0252, 0x0000}, + {0x0253, 0x0000}, + {0x0254, 0x0000}, + {0x0255, 0x0000}, + {0x0256, 0x0000}, + {0x0257, 0x0000}, + {0x0258, 0x0000}, + {0x0259, 0x0000}, + {0x025a, 0x0005}, + {0x0270, 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}, + {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}, +}; + +static bool rt5682_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT5682_RESET: + case RT5682_CBJ_CTRL_2: + case RT5682_INT_ST_1: + case RT5682_4BTN_IL_CMD_1: + case RT5682_AJD1_CTRL: + case RT5682_HP_CALIB_CTRL_1: + case RT5682_DEVICE_ID: + case RT5682_I2C_MODE: + case RT5682_HP_CALIB_CTRL_10: + case RT5682_EFUSE_CTRL_2: + case RT5682_JD_TOP_VC_VTRL: + case RT5682_HP_IMP_SENS_CTRL_19: + case RT5682_IL_CMD_1: + case RT5682_SAR_IL_CMD_2: + case RT5682_SAR_IL_CMD_4: + case RT5682_SAR_IL_CMD_10: + case RT5682_SAR_IL_CMD_11: + case RT5682_EFUSE_CTRL_6...RT5682_EFUSE_CTRL_11: + case RT5682_HP_CALIB_STA_1...RT5682_HP_CALIB_STA_11: + return true; + default: + return false; + } +} + +static bool rt5682_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT5682_RESET: + case RT5682_VERSION_ID: + case RT5682_VENDOR_ID: + case RT5682_DEVICE_ID: + case RT5682_HP_CTRL_1: + case RT5682_HP_CTRL_2: + case RT5682_HPL_GAIN: + case RT5682_HPR_GAIN: + case RT5682_I2C_CTRL: + case RT5682_CBJ_BST_CTRL: + case RT5682_CBJ_CTRL_1: + case RT5682_CBJ_CTRL_2: + case RT5682_CBJ_CTRL_3: + case RT5682_CBJ_CTRL_4: + case RT5682_CBJ_CTRL_5: + case RT5682_CBJ_CTRL_6: + case RT5682_CBJ_CTRL_7: + case RT5682_DAC1_DIG_VOL: + case RT5682_STO1_ADC_DIG_VOL: + case RT5682_STO1_ADC_BOOST: + case RT5682_HP_IMP_GAIN_1: + case RT5682_HP_IMP_GAIN_2: + case RT5682_SIDETONE_CTRL: + case RT5682_STO1_ADC_MIXER: + case RT5682_AD_DA_MIXER: + case RT5682_STO1_DAC_MIXER: + case RT5682_A_DAC1_MUX: + case RT5682_DIG_INF2_DATA: + case RT5682_REC_MIXER: + case RT5682_CAL_REC: + case RT5682_ALC_BACK_GAIN: + case RT5682_PWR_DIG_1: + case RT5682_PWR_DIG_2: + case RT5682_PWR_ANLG_1: + case RT5682_PWR_ANLG_2: + case RT5682_PWR_ANLG_3: + case RT5682_PWR_MIXER: + case RT5682_PWR_VOL: + case RT5682_CLK_DET: + case RT5682_RESET_LPF_CTRL: + case RT5682_RESET_HPF_CTRL: + case RT5682_DMIC_CTRL_1: + case RT5682_I2S1_SDP: + case RT5682_I2S2_SDP: + case RT5682_ADDA_CLK_1: + case RT5682_ADDA_CLK_2: + case RT5682_I2S1_F_DIV_CTRL_1: + case RT5682_I2S1_F_DIV_CTRL_2: + case RT5682_TDM_CTRL: + case RT5682_TDM_ADDA_CTRL_1: + case RT5682_TDM_ADDA_CTRL_2: + case RT5682_DATA_SEL_CTRL_1: + case RT5682_TDM_TCON_CTRL: + case RT5682_GLB_CLK: + case RT5682_PLL_CTRL_1: + case RT5682_PLL_CTRL_2: + case RT5682_PLL_TRACK_1: + case RT5682_PLL_TRACK_2: + case RT5682_PLL_TRACK_3: + case RT5682_PLL_TRACK_4: + case RT5682_PLL_TRACK_5: + case RT5682_PLL_TRACK_6: + case RT5682_PLL_TRACK_11: + case RT5682_SDW_REF_CLK: + case RT5682_DEPOP_1: + case RT5682_DEPOP_2: + case RT5682_HP_CHARGE_PUMP_1: + case RT5682_HP_CHARGE_PUMP_2: + case RT5682_MICBIAS_1: + case RT5682_MICBIAS_2: + case RT5682_PLL_TRACK_12: + case RT5682_PLL_TRACK_14: + case RT5682_PLL2_CTRL_1: + case RT5682_PLL2_CTRL_2: + case RT5682_PLL2_CTRL_3: + case RT5682_PLL2_CTRL_4: + case RT5682_RC_CLK_CTRL: + case RT5682_I2S_M_CLK_CTRL_1: + case RT5682_I2S2_F_DIV_CTRL_1: + case RT5682_I2S2_F_DIV_CTRL_2: + case RT5682_EQ_CTRL_1: + case RT5682_EQ_CTRL_2: + case RT5682_IRQ_CTRL_1: + case RT5682_IRQ_CTRL_2: + case RT5682_IRQ_CTRL_3: + case RT5682_IRQ_CTRL_4: + case RT5682_INT_ST_1: + case RT5682_GPIO_CTRL_1: + case RT5682_GPIO_CTRL_2: + case RT5682_GPIO_CTRL_3: + case RT5682_HP_AMP_DET_CTRL_1: + case RT5682_HP_AMP_DET_CTRL_2: + case RT5682_MID_HP_AMP_DET: + case RT5682_LOW_HP_AMP_DET: + case RT5682_DELAY_BUF_CTRL: + case RT5682_SV_ZCD_1: + case RT5682_SV_ZCD_2: + case RT5682_IL_CMD_1: + case RT5682_IL_CMD_2: + case RT5682_IL_CMD_3: + case RT5682_IL_CMD_4: + case RT5682_IL_CMD_5: + case RT5682_IL_CMD_6: + case RT5682_4BTN_IL_CMD_1: + case RT5682_4BTN_IL_CMD_2: + case RT5682_4BTN_IL_CMD_3: + case RT5682_4BTN_IL_CMD_4: + case RT5682_4BTN_IL_CMD_5: + case RT5682_4BTN_IL_CMD_6: + case RT5682_4BTN_IL_CMD_7: + case RT5682_ADC_STO1_HP_CTRL_1: + case RT5682_ADC_STO1_HP_CTRL_2: + case RT5682_AJD1_CTRL: + case RT5682_JD1_THD: + case RT5682_JD2_THD: + case RT5682_JD_CTRL_1: + case RT5682_DUMMY_1: + case RT5682_DUMMY_2: + case RT5682_DUMMY_3: + case RT5682_DAC_ADC_DIG_VOL1: + case RT5682_BIAS_CUR_CTRL_2: + case RT5682_BIAS_CUR_CTRL_3: + case RT5682_BIAS_CUR_CTRL_4: + case RT5682_BIAS_CUR_CTRL_5: + case RT5682_BIAS_CUR_CTRL_6: + case RT5682_BIAS_CUR_CTRL_7: + case RT5682_BIAS_CUR_CTRL_8: + case RT5682_BIAS_CUR_CTRL_9: + case RT5682_BIAS_CUR_CTRL_10: + case RT5682_VREF_REC_OP_FB_CAP_CTRL: + case RT5682_CHARGE_PUMP_1: + case RT5682_DIG_IN_CTRL_1: + case RT5682_PAD_DRIVING_CTRL: + case RT5682_SOFT_RAMP_DEPOP: + case RT5682_CHOP_DAC: + case RT5682_CHOP_ADC: + case RT5682_CALIB_ADC_CTRL: + case RT5682_VOL_TEST: + case RT5682_SPKVDD_DET_STA: + case RT5682_TEST_MODE_CTRL_1: + case RT5682_TEST_MODE_CTRL_2: + case RT5682_TEST_MODE_CTRL_3: + case RT5682_TEST_MODE_CTRL_4: + case RT5682_TEST_MODE_CTRL_5: + case RT5682_PLL1_INTERNAL: + case RT5682_PLL2_INTERNAL: + case RT5682_STO_NG2_CTRL_1: + case RT5682_STO_NG2_CTRL_2: + case RT5682_STO_NG2_CTRL_3: + case RT5682_STO_NG2_CTRL_4: + case RT5682_STO_NG2_CTRL_5: + case RT5682_STO_NG2_CTRL_6: + case RT5682_STO_NG2_CTRL_7: + case RT5682_STO_NG2_CTRL_8: + case RT5682_STO_NG2_CTRL_9: + case RT5682_STO_NG2_CTRL_10: + case RT5682_STO1_DAC_SIL_DET: + case RT5682_SIL_PSV_CTRL1: + case RT5682_SIL_PSV_CTRL2: + case RT5682_SIL_PSV_CTRL3: + case RT5682_SIL_PSV_CTRL4: + case RT5682_SIL_PSV_CTRL5: + case RT5682_HP_IMP_SENS_CTRL_01: + case RT5682_HP_IMP_SENS_CTRL_02: + case RT5682_HP_IMP_SENS_CTRL_03: + case RT5682_HP_IMP_SENS_CTRL_04: + case RT5682_HP_IMP_SENS_CTRL_05: + case RT5682_HP_IMP_SENS_CTRL_06: + case RT5682_HP_IMP_SENS_CTRL_07: + case RT5682_HP_IMP_SENS_CTRL_08: + case RT5682_HP_IMP_SENS_CTRL_09: + case RT5682_HP_IMP_SENS_CTRL_10: + case RT5682_HP_IMP_SENS_CTRL_11: + case RT5682_HP_IMP_SENS_CTRL_12: + case RT5682_HP_IMP_SENS_CTRL_13: + case RT5682_HP_IMP_SENS_CTRL_14: + case RT5682_HP_IMP_SENS_CTRL_15: + case RT5682_HP_IMP_SENS_CTRL_16: + case RT5682_HP_IMP_SENS_CTRL_17: + case RT5682_HP_IMP_SENS_CTRL_18: + case RT5682_HP_IMP_SENS_CTRL_19: + case RT5682_HP_IMP_SENS_CTRL_20: + case RT5682_HP_IMP_SENS_CTRL_21: + case RT5682_HP_IMP_SENS_CTRL_22: + case RT5682_HP_IMP_SENS_CTRL_23: + case RT5682_HP_IMP_SENS_CTRL_24: + case RT5682_HP_IMP_SENS_CTRL_25: + case RT5682_HP_IMP_SENS_CTRL_26: + case RT5682_HP_IMP_SENS_CTRL_27: + case RT5682_HP_IMP_SENS_CTRL_28: + case RT5682_HP_IMP_SENS_CTRL_29: + case RT5682_HP_IMP_SENS_CTRL_30: + case RT5682_HP_IMP_SENS_CTRL_31: + case RT5682_HP_IMP_SENS_CTRL_32: + case RT5682_HP_IMP_SENS_CTRL_33: + case RT5682_HP_IMP_SENS_CTRL_34: + case RT5682_HP_IMP_SENS_CTRL_35: + case RT5682_HP_IMP_SENS_CTRL_36: + case RT5682_HP_IMP_SENS_CTRL_37: + case RT5682_HP_IMP_SENS_CTRL_38: + case RT5682_HP_IMP_SENS_CTRL_39: + case RT5682_HP_IMP_SENS_CTRL_40: + case RT5682_HP_IMP_SENS_CTRL_41: + case RT5682_HP_IMP_SENS_CTRL_42: + case RT5682_HP_IMP_SENS_CTRL_43: + case RT5682_HP_LOGIC_CTRL_1: + case RT5682_HP_LOGIC_CTRL_2: + case RT5682_HP_LOGIC_CTRL_3: + case RT5682_HP_CALIB_CTRL_1: + case RT5682_HP_CALIB_CTRL_2: + case RT5682_HP_CALIB_CTRL_3: + case RT5682_HP_CALIB_CTRL_4: + case RT5682_HP_CALIB_CTRL_5: + case RT5682_HP_CALIB_CTRL_6: + case RT5682_HP_CALIB_CTRL_7: + case RT5682_HP_CALIB_CTRL_9: + case RT5682_HP_CALIB_CTRL_10: + case RT5682_HP_CALIB_CTRL_11: + case RT5682_HP_CALIB_STA_1: + case RT5682_HP_CALIB_STA_2: + case RT5682_HP_CALIB_STA_3: + case RT5682_HP_CALIB_STA_4: + case RT5682_HP_CALIB_STA_5: + case RT5682_HP_CALIB_STA_6: + case RT5682_HP_CALIB_STA_7: + case RT5682_HP_CALIB_STA_8: + case RT5682_HP_CALIB_STA_9: + case RT5682_HP_CALIB_STA_10: + case RT5682_HP_CALIB_STA_11: + case RT5682_SAR_IL_CMD_1: + case RT5682_SAR_IL_CMD_2: + case RT5682_SAR_IL_CMD_3: + case RT5682_SAR_IL_CMD_4: + case RT5682_SAR_IL_CMD_5: + case RT5682_SAR_IL_CMD_6: + case RT5682_SAR_IL_CMD_7: + case RT5682_SAR_IL_CMD_8: + case RT5682_SAR_IL_CMD_9: + case RT5682_SAR_IL_CMD_10: + case RT5682_SAR_IL_CMD_11: + case RT5682_SAR_IL_CMD_12: + case RT5682_SAR_IL_CMD_13: + case RT5682_EFUSE_CTRL_1: + case RT5682_EFUSE_CTRL_2: + case RT5682_EFUSE_CTRL_3: + case RT5682_EFUSE_CTRL_4: + case RT5682_EFUSE_CTRL_5: + case RT5682_EFUSE_CTRL_6: + case RT5682_EFUSE_CTRL_7: + case RT5682_EFUSE_CTRL_8: + case RT5682_EFUSE_CTRL_9: + case RT5682_EFUSE_CTRL_10: + case RT5682_EFUSE_CTRL_11: + case RT5682_JD_TOP_VC_VTRL: + case RT5682_DRC1_CTRL_0: + case RT5682_DRC1_CTRL_1: + case RT5682_DRC1_CTRL_2: + case RT5682_DRC1_CTRL_3: + case RT5682_DRC1_CTRL_4: + case RT5682_DRC1_CTRL_5: + case RT5682_DRC1_CTRL_6: + case RT5682_DRC1_HARD_LMT_CTRL_1: + case RT5682_DRC1_HARD_LMT_CTRL_2: + case RT5682_DRC1_PRIV_1: + case RT5682_DRC1_PRIV_2: + case RT5682_DRC1_PRIV_3: + case RT5682_DRC1_PRIV_4: + case RT5682_DRC1_PRIV_5: + case RT5682_DRC1_PRIV_6: + case RT5682_DRC1_PRIV_7: + case RT5682_DRC1_PRIV_8: + case RT5682_EQ_AUTO_RCV_CTRL1: + case RT5682_EQ_AUTO_RCV_CTRL2: + case RT5682_EQ_AUTO_RCV_CTRL3: + case RT5682_EQ_AUTO_RCV_CTRL4: + case RT5682_EQ_AUTO_RCV_CTRL5: + case RT5682_EQ_AUTO_RCV_CTRL6: + case RT5682_EQ_AUTO_RCV_CTRL7: + case RT5682_EQ_AUTO_RCV_CTRL8: + case RT5682_EQ_AUTO_RCV_CTRL9: + case RT5682_EQ_AUTO_RCV_CTRL10: + case RT5682_EQ_AUTO_RCV_CTRL11: + case RT5682_EQ_AUTO_RCV_CTRL12: + case RT5682_EQ_AUTO_RCV_CTRL13: + case RT5682_ADC_L_EQ_LPF1_A1: + case RT5682_R_EQ_LPF1_A1: + case RT5682_L_EQ_LPF1_H0: + case RT5682_R_EQ_LPF1_H0: + case RT5682_L_EQ_BPF1_A1: + case RT5682_R_EQ_BPF1_A1: + case RT5682_L_EQ_BPF1_A2: + case RT5682_R_EQ_BPF1_A2: + case RT5682_L_EQ_BPF1_H0: + case RT5682_R_EQ_BPF1_H0: + case RT5682_L_EQ_BPF2_A1: + case RT5682_R_EQ_BPF2_A1: + case RT5682_L_EQ_BPF2_A2: + case RT5682_R_EQ_BPF2_A2: + case RT5682_L_EQ_BPF2_H0: + case RT5682_R_EQ_BPF2_H0: + case RT5682_L_EQ_BPF3_A1: + case RT5682_R_EQ_BPF3_A1: + case RT5682_L_EQ_BPF3_A2: + case RT5682_R_EQ_BPF3_A2: + case RT5682_L_EQ_BPF3_H0: + case RT5682_R_EQ_BPF3_H0: + case RT5682_L_EQ_BPF4_A1: + case RT5682_R_EQ_BPF4_A1: + case RT5682_L_EQ_BPF4_A2: + case RT5682_R_EQ_BPF4_A2: + case RT5682_L_EQ_BPF4_H0: + case RT5682_R_EQ_BPF4_H0: + case RT5682_L_EQ_HPF1_A1: + case RT5682_R_EQ_HPF1_A1: + case RT5682_L_EQ_HPF1_H0: + case RT5682_R_EQ_HPF1_H0: + case RT5682_L_EQ_PRE_VOL: + case RT5682_R_EQ_PRE_VOL: + case RT5682_L_EQ_POST_VOL: + case RT5682_R_EQ_POST_VOL: + case RT5682_I2C_MODE: + return true; + default: + return false; + } +} + +static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -2250, 150, 0); +static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); +static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); +static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); + +/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ +static const DECLARE_TLV_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), + 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 rt5682_data_select[] = { + "L/R", "R/L", "L/L", "R/R" +}; + +static SOC_ENUM_SINGLE_DECL(rt5682_if2_adc_enum, + RT5682_DIG_INF2_DATA, RT5682_IF2_ADC_SEL_SFT, rt5682_data_select); + +static SOC_ENUM_SINGLE_DECL(rt5682_if1_01_adc_enum, + RT5682_TDM_ADDA_CTRL_1, RT5682_IF1_ADC1_SEL_SFT, rt5682_data_select); + +static SOC_ENUM_SINGLE_DECL(rt5682_if1_23_adc_enum, + RT5682_TDM_ADDA_CTRL_1, RT5682_IF1_ADC2_SEL_SFT, rt5682_data_select); + +static SOC_ENUM_SINGLE_DECL(rt5682_if1_45_adc_enum, + RT5682_TDM_ADDA_CTRL_1, RT5682_IF1_ADC3_SEL_SFT, rt5682_data_select); + +static SOC_ENUM_SINGLE_DECL(rt5682_if1_67_adc_enum, + RT5682_TDM_ADDA_CTRL_1, RT5682_IF1_ADC4_SEL_SFT, rt5682_data_select); + +static const struct snd_kcontrol_new rt5682_if2_adc_swap_mux = + SOC_DAPM_ENUM("IF2 ADC Swap Mux", rt5682_if2_adc_enum); + +static const struct snd_kcontrol_new rt5682_if1_01_adc_swap_mux = + SOC_DAPM_ENUM("IF1 01 ADC Swap Mux", rt5682_if1_01_adc_enum); + +static const struct snd_kcontrol_new rt5682_if1_23_adc_swap_mux = + SOC_DAPM_ENUM("IF1 23 ADC Swap Mux", rt5682_if1_23_adc_enum); + +static const struct snd_kcontrol_new rt5682_if1_45_adc_swap_mux = + SOC_DAPM_ENUM("IF1 45 ADC Swap Mux", rt5682_if1_45_adc_enum); + +static const struct snd_kcontrol_new rt5682_if1_67_adc_swap_mux = + SOC_DAPM_ENUM("IF1 67 ADC Swap Mux", rt5682_if1_67_adc_enum); + +static void rt5682_reset(struct regmap *regmap) +{ + regmap_write(regmap, RT5682_RESET, 0); + regmap_write(regmap, RT5682_I2C_MODE, 1); +} +/** + * rt5682_sel_asrc_clk_src - select ASRC clock source for a set of filters + * @component: SoC audio component device. + * @filter_mask: mask of filters. + * @clk_src: clock source + * + * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5682 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 component driver will turn on + * ASRC for these filters if ASRC is selected as their clock source. + */ +int rt5682_sel_asrc_clk_src(struct snd_soc_component *component, + unsigned int filter_mask, unsigned int clk_src) +{ + + switch (clk_src) { + case RT5682_CLK_SEL_SYS: + case RT5682_CLK_SEL_I2S1_ASRC: + case RT5682_CLK_SEL_I2S2_ASRC: + break; + + default: + return -EINVAL; + } + + if (filter_mask & RT5682_DA_STEREO1_FILTER) { + snd_soc_component_update_bits(component, RT5682_PLL_TRACK_2, + RT5682_FILTER_CLK_SEL_MASK, + clk_src << RT5682_FILTER_CLK_SEL_SFT); + } + + if (filter_mask & RT5682_AD_STEREO1_FILTER) { + snd_soc_component_update_bits(component, RT5682_PLL_TRACK_3, + RT5682_FILTER_CLK_SEL_MASK, + clk_src << RT5682_FILTER_CLK_SEL_SFT); + } + + return 0; +} +EXPORT_SYMBOL_GPL(rt5682_sel_asrc_clk_src); + +static int rt5682_button_detect(struct snd_soc_component *component) +{ + int btn_type, val; + + val = snd_soc_component_read32(component, RT5682_4BTN_IL_CMD_1); + btn_type = val & 0xfff0; + snd_soc_component_write(component, RT5682_4BTN_IL_CMD_1, val); + pr_debug("%s btn_type=%x\n", __func__, btn_type); + + return btn_type; +} + +static void rt5682_enable_push_button_irq(struct snd_soc_component *component, + bool enable) +{ + if (enable) { + snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1, + RT5682_SAR_BUTT_DET_MASK, RT5682_SAR_BUTT_DET_EN); + snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_13, + RT5682_SAR_SOUR_MASK, RT5682_SAR_SOUR_BTN); + snd_soc_component_write(component, RT5682_IL_CMD_1, 0x0040); + snd_soc_component_update_bits(component, RT5682_4BTN_IL_CMD_2, + RT5682_4BTN_IL_MASK | RT5682_4BTN_IL_RST_MASK, + RT5682_4BTN_IL_EN | RT5682_4BTN_IL_NOR); + snd_soc_component_update_bits(component, RT5682_IRQ_CTRL_3, + RT5682_IL_IRQ_MASK, RT5682_IL_IRQ_EN); + } else { + snd_soc_component_update_bits(component, RT5682_IRQ_CTRL_3, + RT5682_IL_IRQ_MASK, RT5682_IL_IRQ_DIS); + snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1, + RT5682_SAR_BUTT_DET_MASK, RT5682_SAR_BUTT_DET_DIS); + snd_soc_component_update_bits(component, RT5682_4BTN_IL_CMD_2, + RT5682_4BTN_IL_MASK, RT5682_4BTN_IL_DIS); + snd_soc_component_update_bits(component, RT5682_4BTN_IL_CMD_2, + RT5682_4BTN_IL_RST_MASK, RT5682_4BTN_IL_RST); + snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_13, + RT5682_SAR_SOUR_MASK, RT5682_SAR_SOUR_TYPE); + } +} + +/** + * rt5682_headset_detect - Detect headset. + * @component: SoC audio component device. + * @jack_insert: Jack insert or not. + * + * Detect whether is headset or not when jack inserted. + * + * Returns detect status. + */ +static int rt5682_headset_detect(struct snd_soc_component *component, + int jack_insert) +{ + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + unsigned int val, count; + + if (jack_insert) { + snd_soc_dapm_force_enable_pin(dapm, "CBJ Power"); + snd_soc_dapm_sync(dapm); + snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, + RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_HIGH); + + count = 0; + val = snd_soc_component_read32(component, RT5682_CBJ_CTRL_2) + & RT5682_JACK_TYPE_MASK; + while (val == 0 && count < 50) { + usleep_range(10000, 15000); + val = snd_soc_component_read32(component, + RT5682_CBJ_CTRL_2) & RT5682_JACK_TYPE_MASK; + count++; + } + + switch (val) { + case 0x1: + case 0x2: + rt5682->jack_type = SND_JACK_HEADSET; + rt5682_enable_push_button_irq(component, true); + break; + default: + rt5682->jack_type = SND_JACK_HEADPHONE; + } + + } else { + rt5682_enable_push_button_irq(component, false); + snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, + RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_LOW); + snd_soc_dapm_disable_pin(dapm, "CBJ Power"); + snd_soc_dapm_sync(dapm); + + rt5682->jack_type = 0; + } + + dev_dbg(component->dev, "jack_type = %d\n", rt5682->jack_type); + return rt5682->jack_type; +} + +static irqreturn_t rt5682_irq(int irq, void *data) +{ + struct rt5682_priv *rt5682 = data; + + mod_delayed_work(system_power_efficient_wq, + &rt5682->jack_detect_work, msecs_to_jiffies(250)); + + return IRQ_HANDLED; +} + +static void rt5682_jd_check_handler(struct work_struct *work) +{ + struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv, + jd_check_work.work); + + if (snd_soc_component_read32(rt5682->component, RT5682_AJD1_CTRL) + & RT5682_JDH_RS_MASK) { + /* jack out */ + rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0); + + snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); + } else { + schedule_delayed_work(&rt5682->jd_check_work, 500); + } +} + +static int rt5682_set_jack_detect(struct snd_soc_component *component, + struct snd_soc_jack *hs_jack, void *data) +{ + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + + switch (rt5682->pdata.jd_src) { + case RT5682_JD1: + snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_2, + RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL); + snd_soc_component_write(component, RT5682_CBJ_CTRL_1, 0xd042); + snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_3, + RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN); + snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1, + RT5682_SAR_POW_MASK, RT5682_SAR_POW_EN); + regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, + RT5682_GP1_PIN_MASK, RT5682_GP1_PIN_IRQ); + regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, + RT5682_POW_IRQ | RT5682_POW_JDH | + RT5682_POW_ANA, RT5682_POW_IRQ | + RT5682_POW_JDH | RT5682_POW_ANA); + regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2, + RT5682_PWR_JDH | RT5682_PWR_JDL, + RT5682_PWR_JDH | RT5682_PWR_JDL); + regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, + RT5682_JD1_EN_MASK | RT5682_JD1_POL_MASK, + RT5682_JD1_EN | RT5682_JD1_POL_NOR); + mod_delayed_work(system_power_efficient_wq, + &rt5682->jack_detect_work, msecs_to_jiffies(250)); + break; + + case RT5682_JD_NULL: + regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, + RT5682_JD1_EN_MASK, RT5682_JD1_DIS); + regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, + RT5682_POW_JDH | RT5682_POW_JDL, 0); + break; + + default: + dev_warn(component->dev, "Wrong JD source\n"); + break; + } + + rt5682->hs_jack = hs_jack; + + return 0; +} + +static void rt5682_jack_detect_handler(struct work_struct *work) +{ + struct rt5682_priv *rt5682 = + container_of(work, struct rt5682_priv, jack_detect_work.work); + int val, btn_type; + + while (!rt5682->component) + usleep_range(10000, 15000); + + while (!rt5682->component->card->instantiated) + usleep_range(10000, 15000); + + mutex_lock(&rt5682->calibrate_mutex); + + val = snd_soc_component_read32(rt5682->component, RT5682_AJD1_CTRL) + & RT5682_JDH_RS_MASK; + if (!val) { + /* jack in */ + if (rt5682->jack_type == 0) { + /* jack was out, report jack type */ + rt5682->jack_type = + rt5682_headset_detect(rt5682->component, 1); + } else { + /* jack is already in, report button event */ + rt5682->jack_type = SND_JACK_HEADSET; + btn_type = rt5682_button_detect(rt5682->component); + /** + * rt5682 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: + rt5682->jack_type |= SND_JACK_BTN_0; + break; + case 0x1000: + case 0x0800: + case 0x0400: + rt5682->jack_type |= SND_JACK_BTN_1; + break; + case 0x0200: + case 0x0100: + case 0x0080: + rt5682->jack_type |= SND_JACK_BTN_2; + break; + case 0x0040: + case 0x0020: + case 0x0010: + rt5682->jack_type |= SND_JACK_BTN_3; + break; + case 0x0000: /* unpressed */ + break; + default: + btn_type = 0; + dev_err(rt5682->component->dev, + "Unexpected button code 0x%04x\n", + btn_type); + break; + } + } + } else { + /* jack out */ + rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0); + } + + snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); + + if (rt5682->jack_type & (SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3)) + schedule_delayed_work(&rt5682->jd_check_work, 0); + else + cancel_delayed_work_sync(&rt5682->jd_check_work); + + mutex_unlock(&rt5682->calibrate_mutex); +} + +static const struct snd_kcontrol_new rt5682_snd_controls[] = { + /* Headphone Output Volume */ + SOC_DOUBLE_R_TLV("Headphone Playback Volume", RT5682_HPL_GAIN, + RT5682_HPR_GAIN, RT5682_G_HP_SFT, 15, 1, hp_vol_tlv), + + /* DAC Digital Volume */ + SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5682_DAC1_DIG_VOL, + RT5682_L_VOL_SFT, RT5682_R_VOL_SFT, 175, 0, dac_vol_tlv), + + /* IN Boost Volume */ + SOC_SINGLE_TLV("CBJ Boost Volume", RT5682_CBJ_BST_CTRL, + RT5682_BST_CBJ_SFT, 8, 0, bst_tlv), + + /* ADC Digital Volume Control */ + SOC_DOUBLE("STO1 ADC Capture Switch", RT5682_STO1_ADC_DIG_VOL, + RT5682_L_MUTE_SFT, RT5682_R_MUTE_SFT, 1, 1), + SOC_DOUBLE_TLV("STO1 ADC Capture Volume", RT5682_STO1_ADC_DIG_VOL, + RT5682_L_VOL_SFT, RT5682_R_VOL_SFT, 127, 0, adc_vol_tlv), + + /* ADC Boost Volume Control */ + SOC_DOUBLE_TLV("STO1 ADC Boost Gain Volume", RT5682_STO1_ADC_BOOST, + RT5682_STO1_ADC_L_BST_SFT, RT5682_STO1_ADC_R_BST_SFT, + 3, 0, adc_bst_tlv), +}; + + +static int rt5682_div_sel(struct rt5682_priv *rt5682, + int target, const int div[], int size) +{ + int i; + + if (rt5682->sysclk < target) { + pr_err("sysclk rate %d is too low\n", + rt5682->sysclk); + return 0; + } + + for (i = 0; i < size - 1; i++) { + pr_info("div[%d]=%d\n", i, div[i]); + if (target * div[i] == rt5682->sysclk) + return i; + if (target * div[i + 1] > rt5682->sysclk) { + pr_err("can't find div for sysclk %d\n", + rt5682->sysclk); + return i; + } + } + + if (target * div[i] < rt5682->sysclk) + pr_err("sysclk rate %d is too high\n", + rt5682->sysclk); + + return size - 1; + +} + +/** + * set_dmic_clk - Set parameter of dmic. + * + * @w: DAPM widget. + * @kcontrol: The kcontrol of this widget. + * @event: Event id. + * + * Choose dmic clock between 1MHz and 3MHz. + * It is better for clock to approximate 3MHz. + */ +static int set_dmic_clk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + int idx = -EINVAL; + static const int div[] = {2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128}; + + idx = rt5682_div_sel(rt5682, 1500000, div, ARRAY_SIZE(div)); + + snd_soc_component_update_bits(component, RT5682_DMIC_CTRL_1, + RT5682_DMIC_CLK_MASK, idx << RT5682_DMIC_CLK_SFT); + + return 0; +} + +static int set_filter_clk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + int ref, val, reg, sft, mask, idx = -EINVAL; + static const int div_f[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48}; + static const int div_o[] = {1, 2, 4, 6, 8, 12, 16, 24, 32, 48}; + + val = snd_soc_component_read32(component, RT5682_GPIO_CTRL_1) & + RT5682_GP4_PIN_MASK; + if (w->shift == RT5682_PWR_ADC_S1F_BIT && + val == RT5682_GP4_PIN_ADCDAT2) + ref = 256 * rt5682->lrck[RT5682_AIF2]; + else + ref = 256 * rt5682->lrck[RT5682_AIF1]; + + idx = rt5682_div_sel(rt5682, ref, div_f, ARRAY_SIZE(div_f)); + + if (w->shift == RT5682_PWR_ADC_S1F_BIT) { + reg = RT5682_PLL_TRACK_3; + sft = RT5682_ADC_OSR_SFT; + mask = RT5682_ADC_OSR_MASK; + } else { + reg = RT5682_PLL_TRACK_2; + sft = RT5682_DAC_OSR_SFT; + mask = RT5682_DAC_OSR_MASK; + } + + snd_soc_component_update_bits(component, reg, + RT5682_FILTER_CLK_DIV_MASK, idx << RT5682_FILTER_CLK_DIV_SFT); + + /* select over sample rate */ + for (idx = 0; idx < ARRAY_SIZE(div_o); idx++) { + if (rt5682->sysclk <= 12288000 * div_o[idx]) + break; + } + + snd_soc_component_update_bits(component, RT5682_ADDA_CLK_1, + mask, idx << sft); + + return 0; +} + +static int is_sys_clk_from_pll1(struct snd_soc_dapm_widget *w, + struct snd_soc_dapm_widget *sink) +{ + unsigned int val; + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + val = snd_soc_component_read32(component, RT5682_GLB_CLK); + val &= RT5682_SCLK_SRC_MASK; + if (val == RT5682_SCLK_SRC_PLL1) + return 1; + else + return 0; +} + +static int is_using_asrc(struct snd_soc_dapm_widget *w, + struct snd_soc_dapm_widget *sink) +{ + unsigned int reg, shift, val; + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + switch (w->shift) { + case RT5682_ADC_STO1_ASRC_SFT: + reg = RT5682_PLL_TRACK_3; + shift = RT5682_FILTER_CLK_SEL_SFT; + break; + case RT5682_DAC_STO1_ASRC_SFT: + reg = RT5682_PLL_TRACK_2; + shift = RT5682_FILTER_CLK_SEL_SFT; + break; + default: + return 0; + } + + val = (snd_soc_component_read32(component, reg) >> shift) & 0xf; + switch (val) { + case RT5682_CLK_SEL_I2S1_ASRC: + case RT5682_CLK_SEL_I2S2_ASRC: + return 1; + default: + return 0; + } + +} + +/* Digital Mixer */ +static const struct snd_kcontrol_new rt5682_sto1_adc_l_mix[] = { + SOC_DAPM_SINGLE("ADC1 Switch", RT5682_STO1_ADC_MIXER, + RT5682_M_STO1_ADC_L1_SFT, 1, 1), + SOC_DAPM_SINGLE("ADC2 Switch", RT5682_STO1_ADC_MIXER, + RT5682_M_STO1_ADC_L2_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5682_sto1_adc_r_mix[] = { + SOC_DAPM_SINGLE("ADC1 Switch", RT5682_STO1_ADC_MIXER, + RT5682_M_STO1_ADC_R1_SFT, 1, 1), + SOC_DAPM_SINGLE("ADC2 Switch", RT5682_STO1_ADC_MIXER, + RT5682_M_STO1_ADC_R2_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5682_dac_l_mix[] = { + SOC_DAPM_SINGLE("Stereo ADC Switch", RT5682_AD_DA_MIXER, + RT5682_M_ADCMIX_L_SFT, 1, 1), + SOC_DAPM_SINGLE("DAC1 Switch", RT5682_AD_DA_MIXER, + RT5682_M_DAC1_L_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5682_dac_r_mix[] = { + SOC_DAPM_SINGLE("Stereo ADC Switch", RT5682_AD_DA_MIXER, + RT5682_M_ADCMIX_R_SFT, 1, 1), + SOC_DAPM_SINGLE("DAC1 Switch", RT5682_AD_DA_MIXER, + RT5682_M_DAC1_R_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5682_sto1_dac_l_mix[] = { + SOC_DAPM_SINGLE("DAC L1 Switch", RT5682_STO1_DAC_MIXER, + RT5682_M_DAC_L1_STO_L_SFT, 1, 1), + SOC_DAPM_SINGLE("DAC R1 Switch", RT5682_STO1_DAC_MIXER, + RT5682_M_DAC_R1_STO_L_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5682_sto1_dac_r_mix[] = { + SOC_DAPM_SINGLE("DAC L1 Switch", RT5682_STO1_DAC_MIXER, + RT5682_M_DAC_L1_STO_R_SFT, 1, 1), + SOC_DAPM_SINGLE("DAC R1 Switch", RT5682_STO1_DAC_MIXER, + RT5682_M_DAC_R1_STO_R_SFT, 1, 1), +}; + +/* Analog Input Mixer */ +static const struct snd_kcontrol_new rt5682_rec1_l_mix[] = { + SOC_DAPM_SINGLE("CBJ Switch", RT5682_REC_MIXER, + RT5682_M_CBJ_RM1_L_SFT, 1, 1), +}; + +/* STO1 ADC1 Source */ +/* MX-26 [13] [5] */ +static const char * const rt5682_sto1_adc1_src[] = { + "DAC MIX", "ADC" +}; + +static SOC_ENUM_SINGLE_DECL( + rt5682_sto1_adc1l_enum, RT5682_STO1_ADC_MIXER, + RT5682_STO1_ADC1L_SRC_SFT, rt5682_sto1_adc1_src); + +static const struct snd_kcontrol_new rt5682_sto1_adc1l_mux = + SOC_DAPM_ENUM("Stereo1 ADC1L Source", rt5682_sto1_adc1l_enum); + +static SOC_ENUM_SINGLE_DECL( + rt5682_sto1_adc1r_enum, RT5682_STO1_ADC_MIXER, + RT5682_STO1_ADC1R_SRC_SFT, rt5682_sto1_adc1_src); + +static const struct snd_kcontrol_new rt5682_sto1_adc1r_mux = + SOC_DAPM_ENUM("Stereo1 ADC1L Source", rt5682_sto1_adc1r_enum); + +/* STO1 ADC Source */ +/* MX-26 [11:10] [3:2] */ +static const char * const rt5682_sto1_adc_src[] = { + "ADC1 L", "ADC1 R" +}; + +static SOC_ENUM_SINGLE_DECL( + rt5682_sto1_adcl_enum, RT5682_STO1_ADC_MIXER, + RT5682_STO1_ADCL_SRC_SFT, rt5682_sto1_adc_src); + +static const struct snd_kcontrol_new rt5682_sto1_adcl_mux = + SOC_DAPM_ENUM("Stereo1 ADCL Source", rt5682_sto1_adcl_enum); + +static SOC_ENUM_SINGLE_DECL( + rt5682_sto1_adcr_enum, RT5682_STO1_ADC_MIXER, + RT5682_STO1_ADCR_SRC_SFT, rt5682_sto1_adc_src); + +static const struct snd_kcontrol_new rt5682_sto1_adcr_mux = + SOC_DAPM_ENUM("Stereo1 ADCR Source", rt5682_sto1_adcr_enum); + +/* STO1 ADC2 Source */ +/* MX-26 [12] [4] */ +static const char * const rt5682_sto1_adc2_src[] = { + "DAC MIX", "DMIC" +}; + +static SOC_ENUM_SINGLE_DECL( + rt5682_sto1_adc2l_enum, RT5682_STO1_ADC_MIXER, + RT5682_STO1_ADC2L_SRC_SFT, rt5682_sto1_adc2_src); + +static const struct snd_kcontrol_new rt5682_sto1_adc2l_mux = + SOC_DAPM_ENUM("Stereo1 ADC2L Source", rt5682_sto1_adc2l_enum); + +static SOC_ENUM_SINGLE_DECL( + rt5682_sto1_adc2r_enum, RT5682_STO1_ADC_MIXER, + RT5682_STO1_ADC2R_SRC_SFT, rt5682_sto1_adc2_src); + +static const struct snd_kcontrol_new rt5682_sto1_adc2r_mux = + SOC_DAPM_ENUM("Stereo1 ADC2R Source", rt5682_sto1_adc2r_enum); + +/* MX-79 [6:4] I2S1 ADC data location */ +static const unsigned int rt5682_if1_adc_slot_values[] = { + 0, + 2, + 4, + 6, +}; + +static const char * const rt5682_if1_adc_slot_src[] = { + "Slot 0", "Slot 2", "Slot 4", "Slot 6" +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(rt5682_if1_adc_slot_enum, + RT5682_TDM_CTRL, RT5682_TDM_ADC_LCA_SFT, RT5682_TDM_ADC_LCA_MASK, + rt5682_if1_adc_slot_src, rt5682_if1_adc_slot_values); + +static const struct snd_kcontrol_new rt5682_if1_adc_slot_mux = + SOC_DAPM_ENUM("IF1 ADC Slot location", rt5682_if1_adc_slot_enum); + +/* Analog DAC L1 Source, Analog DAC R1 Source*/ +/* MX-2B [4], MX-2B [0]*/ +static const char * const rt5682_alg_dac1_src[] = { + "Stereo1 DAC Mixer", "DAC1" +}; + +static SOC_ENUM_SINGLE_DECL( + rt5682_alg_dac_l1_enum, RT5682_A_DAC1_MUX, + RT5682_A_DACL1_SFT, rt5682_alg_dac1_src); + +static const struct snd_kcontrol_new rt5682_alg_dac_l1_mux = + SOC_DAPM_ENUM("Analog DAC L1 Source", rt5682_alg_dac_l1_enum); + +static SOC_ENUM_SINGLE_DECL( + rt5682_alg_dac_r1_enum, RT5682_A_DAC1_MUX, + RT5682_A_DACR1_SFT, rt5682_alg_dac1_src); + +static const struct snd_kcontrol_new rt5682_alg_dac_r1_mux = + SOC_DAPM_ENUM("Analog DAC R1 Source", rt5682_alg_dac_r1_enum); + +/* Out Switch */ +static const struct snd_kcontrol_new hpol_switch = + SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5682_HP_CTRL_1, + RT5682_L_MUTE_SFT, 1, 1); +static const struct snd_kcontrol_new hpor_switch = + SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5682_HP_CTRL_1, + RT5682_R_MUTE_SFT, 1, 1); + +static int rt5682_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_write(component, + RT5682_HP_LOGIC_CTRL_2, 0x0012); + snd_soc_component_write(component, + RT5682_HP_CTRL_2, 0x6000); + snd_soc_component_update_bits(component, RT5682_STO_NG2_CTRL_1, + RT5682_NG2_EN_MASK, RT5682_NG2_EN); + snd_soc_component_update_bits(component, + RT5682_DEPOP_1, 0x60, 0x60); + break; + + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_update_bits(component, + RT5682_DEPOP_1, 0x60, 0x0); + snd_soc_component_write(component, + RT5682_HP_CTRL_2, 0x0000); + break; + + default: + return 0; + } + + return 0; + +} + +static int set_dmic_power(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /*Add delay to avoid pop noise*/ + msleep(150); + break; + + default: + return 0; + } + + return 0; +} + +static int rt5655_set_verf(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + switch (w->shift) { + case RT5682_PWR_VREF1_BIT: + snd_soc_component_update_bits(component, + RT5682_PWR_ANLG_1, RT5682_PWR_FV1, 0); + break; + + case RT5682_PWR_VREF2_BIT: + snd_soc_component_update_bits(component, + RT5682_PWR_ANLG_1, RT5682_PWR_FV2, 0); + break; + + default: + break; + } + break; + + case SND_SOC_DAPM_POST_PMU: + usleep_range(15000, 20000); + switch (w->shift) { + case RT5682_PWR_VREF1_BIT: + snd_soc_component_update_bits(component, + RT5682_PWR_ANLG_1, RT5682_PWR_FV1, + RT5682_PWR_FV1); + break; + + case RT5682_PWR_VREF2_BIT: + snd_soc_component_update_bits(component, + RT5682_PWR_ANLG_1, RT5682_PWR_FV2, + RT5682_PWR_FV2); + break; + + default: + break; + } + break; + + default: + return 0; + } + + return 0; +} + +static const unsigned int rt5682_adcdat_pin_values[] = { + 1, + 3, +}; + +static const char * const rt5682_adcdat_pin_select[] = { + "ADCDAT1", + "ADCDAT2", +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(rt5682_adcdat_pin_enum, + RT5682_GPIO_CTRL_1, RT5682_GP4_PIN_SFT, RT5682_GP4_PIN_MASK, + rt5682_adcdat_pin_select, rt5682_adcdat_pin_values); + +static const struct snd_kcontrol_new rt5682_adcdat_pin_ctrl = + SOC_DAPM_ENUM("ADCDAT", rt5682_adcdat_pin_enum); + +static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("LDO2", RT5682_PWR_ANLG_3, RT5682_PWR_LDO2_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL1", RT5682_PWR_ANLG_3, RT5682_PWR_PLL_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL2B", RT5682_PWR_ANLG_3, RT5682_PWR_PLL2B_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL2F", RT5682_PWR_ANLG_3, RT5682_PWR_PLL2F_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Vref1", RT5682_PWR_ANLG_1, RT5682_PWR_VREF1_BIT, 0, + rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_SUPPLY("Vref2", RT5682_PWR_ANLG_1, RT5682_PWR_VREF2_BIT, 0, + rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + + /* ASRC */ + SND_SOC_DAPM_SUPPLY_S("DAC STO1 ASRC", 1, RT5682_PLL_TRACK_1, + RT5682_DAC_STO1_ASRC_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("ADC STO1 ASRC", 1, RT5682_PLL_TRACK_1, + RT5682_ADC_STO1_ASRC_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AD ASRC", 1, RT5682_PLL_TRACK_1, + RT5682_AD_ASRC_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DA ASRC", 1, RT5682_PLL_TRACK_1, + RT5682_DA_ASRC_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DMIC ASRC", 1, RT5682_PLL_TRACK_1, + RT5682_DMIC_ASRC_SFT, 0, NULL, 0), + + /* Input Side */ + SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5682_PWR_ANLG_2, RT5682_PWR_MB1_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MICBIAS2", RT5682_PWR_ANLG_2, RT5682_PWR_MB2_BIT, + 0, NULL, 0), + + /* Input Lines */ + SND_SOC_DAPM_INPUT("DMIC L1"), + SND_SOC_DAPM_INPUT("DMIC R1"), + + SND_SOC_DAPM_INPUT("IN1P"), + + SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0, + set_dmic_clk, SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5682_DMIC_CTRL_1, + RT5682_DMIC_1_EN_SFT, 0, set_dmic_power, SND_SOC_DAPM_POST_PMU), + + /* Boost */ + SND_SOC_DAPM_PGA("BST1 CBJ", SND_SOC_NOPM, + 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("CBJ Power", RT5682_PWR_ANLG_3, + RT5682_PWR_CBJ_BIT, 0, NULL, 0), + + /* REC Mixer */ + SND_SOC_DAPM_MIXER("RECMIX1L", SND_SOC_NOPM, 0, 0, rt5682_rec1_l_mix, + ARRAY_SIZE(rt5682_rec1_l_mix)), + SND_SOC_DAPM_SUPPLY("RECMIX1L Power", RT5682_PWR_ANLG_2, + RT5682_PWR_RM1_L_BIT, 0, NULL, 0), + + /* ADCs */ + SND_SOC_DAPM_ADC("ADC1 L", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADC1 R", NULL, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_SUPPLY("ADC1 L Power", RT5682_PWR_DIG_1, + RT5682_PWR_ADC_L1_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC1 R Power", RT5682_PWR_DIG_1, + RT5682_PWR_ADC_R1_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC1 clock", RT5682_CHOP_ADC, + RT5682_CKGEN_ADC1_SFT, 0, NULL, 0), + + /* ADC Mux */ + SND_SOC_DAPM_MUX("Stereo1 ADC L1 Mux", SND_SOC_NOPM, 0, 0, + &rt5682_sto1_adc1l_mux), + SND_SOC_DAPM_MUX("Stereo1 ADC R1 Mux", SND_SOC_NOPM, 0, 0, + &rt5682_sto1_adc1r_mux), + SND_SOC_DAPM_MUX("Stereo1 ADC L2 Mux", SND_SOC_NOPM, 0, 0, + &rt5682_sto1_adc2l_mux), + SND_SOC_DAPM_MUX("Stereo1 ADC R2 Mux", SND_SOC_NOPM, 0, 0, + &rt5682_sto1_adc2r_mux), + SND_SOC_DAPM_MUX("Stereo1 ADC L Mux", SND_SOC_NOPM, 0, 0, + &rt5682_sto1_adcl_mux), + SND_SOC_DAPM_MUX("Stereo1 ADC R Mux", SND_SOC_NOPM, 0, 0, + &rt5682_sto1_adcr_mux), + SND_SOC_DAPM_MUX("IF1_ADC Mux", SND_SOC_NOPM, 0, 0, + &rt5682_if1_adc_slot_mux), + + /* ADC Mixer */ + SND_SOC_DAPM_SUPPLY("ADC Stereo1 Filter", RT5682_PWR_DIG_2, + RT5682_PWR_ADC_S1F_BIT, 0, set_filter_clk, + SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_MIXER("Stereo1 ADC MIXL", RT5682_STO1_ADC_DIG_VOL, + RT5682_L_MUTE_SFT, 1, rt5682_sto1_adc_l_mix, + ARRAY_SIZE(rt5682_sto1_adc_l_mix)), + SND_SOC_DAPM_MIXER("Stereo1 ADC MIXR", RT5682_STO1_ADC_DIG_VOL, + RT5682_R_MUTE_SFT, 1, rt5682_sto1_adc_r_mix, + ARRAY_SIZE(rt5682_sto1_adc_r_mix)), + + /* ADC PGA */ + SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* Digital Interface */ + SND_SOC_DAPM_SUPPLY("I2S1", RT5682_PWR_DIG_1, RT5682_PWR_I2S1_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("I2S2", RT5682_PWR_DIG_1, RT5682_PWR_I2S2_BIT, + 0, NULL, 0), + SND_SOC_DAPM_PGA("IF1 DAC1", 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), + + /* Digital Interface Select */ + SND_SOC_DAPM_MUX("IF1 01 ADC Swap Mux", SND_SOC_NOPM, 0, 0, + &rt5682_if1_01_adc_swap_mux), + SND_SOC_DAPM_MUX("IF1 23 ADC Swap Mux", SND_SOC_NOPM, 0, 0, + &rt5682_if1_23_adc_swap_mux), + SND_SOC_DAPM_MUX("IF1 45 ADC Swap Mux", SND_SOC_NOPM, 0, 0, + &rt5682_if1_45_adc_swap_mux), + SND_SOC_DAPM_MUX("IF1 67 ADC Swap Mux", SND_SOC_NOPM, 0, 0, + &rt5682_if1_67_adc_swap_mux), + SND_SOC_DAPM_MUX("IF2 ADC Swap Mux", SND_SOC_NOPM, 0, 0, + &rt5682_if2_adc_swap_mux), + + SND_SOC_DAPM_MUX("ADCDAT Mux", SND_SOC_NOPM, 0, 0, + &rt5682_adcdat_pin_ctrl), + + /* Audio Interface */ + SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, + RT5682_I2S1_SDP, RT5682_SEL_ADCDAT_SFT, 1), + SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, + RT5682_I2S2_SDP, RT5682_I2S2_PIN_CFG_SFT, 1), + SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), + + /* Output Side */ + /* DAC mixer before sound effect */ + SND_SOC_DAPM_MIXER("DAC1 MIXL", SND_SOC_NOPM, 0, 0, + rt5682_dac_l_mix, ARRAY_SIZE(rt5682_dac_l_mix)), + SND_SOC_DAPM_MIXER("DAC1 MIXR", SND_SOC_NOPM, 0, 0, + rt5682_dac_r_mix, ARRAY_SIZE(rt5682_dac_r_mix)), + + /* DAC channel Mux */ + SND_SOC_DAPM_MUX("DAC L1 Source", SND_SOC_NOPM, 0, 0, + &rt5682_alg_dac_l1_mux), + SND_SOC_DAPM_MUX("DAC R1 Source", SND_SOC_NOPM, 0, 0, + &rt5682_alg_dac_r1_mux), + + /* DAC Mixer */ + SND_SOC_DAPM_SUPPLY("DAC Stereo1 Filter", RT5682_PWR_DIG_2, + RT5682_PWR_DAC_S1F_BIT, 0, set_filter_clk, + SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_MIXER("Stereo1 DAC MIXL", SND_SOC_NOPM, 0, 0, + rt5682_sto1_dac_l_mix, ARRAY_SIZE(rt5682_sto1_dac_l_mix)), + SND_SOC_DAPM_MIXER("Stereo1 DAC MIXR", SND_SOC_NOPM, 0, 0, + rt5682_sto1_dac_r_mix, ARRAY_SIZE(rt5682_sto1_dac_r_mix)), + + /* DACs */ + SND_SOC_DAPM_DAC("DAC L1", NULL, RT5682_PWR_DIG_1, + RT5682_PWR_DAC_L1_BIT, 0), + SND_SOC_DAPM_DAC("DAC R1", NULL, RT5682_PWR_DIG_1, + RT5682_PWR_DAC_R1_BIT, 0), + SND_SOC_DAPM_SUPPLY_S("DAC 1 Clock", 3, RT5682_CHOP_DAC, + RT5682_CKGEN_DAC1_SFT, 0, NULL, 0), + + /* HPO */ + SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, rt5682_hp_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU), + + SND_SOC_DAPM_SUPPLY("HP Amp L", RT5682_PWR_ANLG_1, + RT5682_PWR_HA_L_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("HP Amp R", RT5682_PWR_ANLG_1, + RT5682_PWR_HA_R_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("Charge Pump", 1, RT5682_DEPOP_1, + RT5682_PUMP_EN_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("Capless", 2, RT5682_DEPOP_1, + RT5682_CAPLESS_EN_SFT, 0, NULL, 0), + + SND_SOC_DAPM_SWITCH("HPOL Playback", SND_SOC_NOPM, 0, 0, + &hpol_switch), + SND_SOC_DAPM_SWITCH("HPOR Playback", SND_SOC_NOPM, 0, 0, + &hpor_switch), + + /* CLK DET */ + SND_SOC_DAPM_SUPPLY("CLKDET SYS", RT5682_CLK_DET, + RT5682_SYS_CLK_DET_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("CLKDET PLL1", RT5682_CLK_DET, + RT5682_PLL1_CLK_DET_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("CLKDET PLL2", RT5682_CLK_DET, + RT5682_PLL2_CLK_DET_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("CLKDET", RT5682_CLK_DET, + RT5682_POW_CLK_DET_SFT, 0, NULL, 0), + + /* Output Lines */ + SND_SOC_DAPM_OUTPUT("HPOL"), + SND_SOC_DAPM_OUTPUT("HPOR"), + +}; + +static const struct snd_soc_dapm_route rt5682_dapm_routes[] = { + /*PLL*/ + {"ADC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll1}, + {"DAC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll1}, + + /*ASRC*/ + {"ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc}, + {"DAC Stereo1 Filter", NULL, "DAC STO1 ASRC", is_using_asrc}, + {"ADC STO1 ASRC", NULL, "AD ASRC"}, + {"ADC STO1 ASRC", NULL, "CLKDET"}, + {"DAC STO1 ASRC", NULL, "DA ASRC"}, + {"DAC STO1 ASRC", NULL, "CLKDET"}, + + /*Vref*/ + {"MICBIAS1", NULL, "Vref1"}, + {"MICBIAS1", NULL, "Vref2"}, + {"MICBIAS2", NULL, "Vref1"}, + {"MICBIAS2", NULL, "Vref2"}, + + {"CLKDET SYS", NULL, "CLKDET"}, + + {"IN1P", NULL, "LDO2"}, + + {"BST1 CBJ", NULL, "IN1P"}, + {"BST1 CBJ", NULL, "CBJ Power"}, + {"CBJ Power", NULL, "Vref2"}, + + {"RECMIX1L", "CBJ Switch", "BST1 CBJ"}, + {"RECMIX1L", NULL, "RECMIX1L Power"}, + + {"ADC1 L", NULL, "RECMIX1L"}, + {"ADC1 L", NULL, "ADC1 L Power"}, + {"ADC1 L", NULL, "ADC1 clock"}, + + {"DMIC L1", NULL, "DMIC CLK"}, + {"DMIC L1", NULL, "DMIC1 Power"}, + {"DMIC R1", NULL, "DMIC CLK"}, + {"DMIC R1", NULL, "DMIC1 Power"}, + {"DMIC CLK", NULL, "DMIC ASRC"}, + + {"Stereo1 ADC L Mux", "ADC1 L", "ADC1 L"}, + {"Stereo1 ADC L Mux", "ADC1 R", "ADC1 R"}, + {"Stereo1 ADC R Mux", "ADC1 L", "ADC1 L"}, + {"Stereo1 ADC R Mux", "ADC1 R", "ADC1 R"}, + + {"Stereo1 ADC L1 Mux", "ADC", "Stereo1 ADC L Mux"}, + {"Stereo1 ADC L1 Mux", "DAC MIX", "Stereo1 DAC MIXL"}, + {"Stereo1 ADC L2 Mux", "DMIC", "DMIC L1"}, + {"Stereo1 ADC L2 Mux", "DAC MIX", "Stereo1 DAC MIXL"}, + + {"Stereo1 ADC R1 Mux", "ADC", "Stereo1 ADC R Mux"}, + {"Stereo1 ADC R1 Mux", "DAC MIX", "Stereo1 DAC MIXR"}, + {"Stereo1 ADC R2 Mux", "DMIC", "DMIC R1"}, + {"Stereo1 ADC R2 Mux", "DAC MIX", "Stereo1 DAC MIXR"}, + + {"Stereo1 ADC MIXL", "ADC1 Switch", "Stereo1 ADC L1 Mux"}, + {"Stereo1 ADC MIXL", "ADC2 Switch", "Stereo1 ADC L2 Mux"}, + {"Stereo1 ADC MIXL", NULL, "ADC Stereo1 Filter"}, + + {"Stereo1 ADC MIXR", "ADC1 Switch", "Stereo1 ADC R1 Mux"}, + {"Stereo1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux"}, + {"Stereo1 ADC MIXR", NULL, "ADC Stereo1 Filter"}, + + {"Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL"}, + {"Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR"}, + + {"IF1 01 ADC Swap Mux", "L/R", "Stereo1 ADC MIX"}, + {"IF1 01 ADC Swap Mux", "L/L", "Stereo1 ADC MIX"}, + {"IF1 01 ADC Swap Mux", "R/L", "Stereo1 ADC MIX"}, + {"IF1 01 ADC Swap Mux", "R/R", "Stereo1 ADC MIX"}, + {"IF1 23 ADC Swap Mux", "L/R", "Stereo1 ADC MIX"}, + {"IF1 23 ADC Swap Mux", "R/L", "Stereo1 ADC MIX"}, + {"IF1 23 ADC Swap Mux", "L/L", "Stereo1 ADC MIX"}, + {"IF1 23 ADC Swap Mux", "R/R", "Stereo1 ADC MIX"}, + {"IF1 45 ADC Swap Mux", "L/R", "Stereo1 ADC MIX"}, + {"IF1 45 ADC Swap Mux", "R/L", "Stereo1 ADC MIX"}, + {"IF1 45 ADC Swap Mux", "L/L", "Stereo1 ADC MIX"}, + {"IF1 45 ADC Swap Mux", "R/R", "Stereo1 ADC MIX"}, + {"IF1 67 ADC Swap Mux", "L/R", "Stereo1 ADC MIX"}, + {"IF1 67 ADC Swap Mux", "R/L", "Stereo1 ADC MIX"}, + {"IF1 67 ADC Swap Mux", "L/L", "Stereo1 ADC MIX"}, + {"IF1 67 ADC Swap Mux", "R/R", "Stereo1 ADC MIX"}, + + {"IF1_ADC Mux", "Slot 0", "IF1 01 ADC Swap Mux"}, + {"IF1_ADC Mux", "Slot 2", "IF1 23 ADC Swap Mux"}, + {"IF1_ADC Mux", "Slot 4", "IF1 45 ADC Swap Mux"}, + {"IF1_ADC Mux", "Slot 6", "IF1 67 ADC Swap Mux"}, + {"IF1_ADC Mux", NULL, "I2S1"}, + {"ADCDAT Mux", "ADCDAT1", "IF1_ADC Mux"}, + {"AIF1TX", NULL, "ADCDAT Mux"}, + {"IF2 ADC Swap Mux", "L/R", "Stereo1 ADC MIX"}, + {"IF2 ADC Swap Mux", "R/L", "Stereo1 ADC MIX"}, + {"IF2 ADC Swap Mux", "L/L", "Stereo1 ADC MIX"}, + {"IF2 ADC Swap Mux", "R/R", "Stereo1 ADC MIX"}, + {"ADCDAT Mux", "ADCDAT2", "IF2 ADC Swap Mux"}, + {"AIF2TX", NULL, "ADCDAT Mux"}, + + {"IF1 DAC1 L", NULL, "AIF1RX"}, + {"IF1 DAC1 L", NULL, "I2S1"}, + {"IF1 DAC1 L", NULL, "DAC Stereo1 Filter"}, + {"IF1 DAC1 R", NULL, "AIF1RX"}, + {"IF1 DAC1 R", NULL, "I2S1"}, + {"IF1 DAC1 R", NULL, "DAC Stereo1 Filter"}, + + {"DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL"}, + {"DAC1 MIXL", "DAC1 Switch", "IF1 DAC1 L"}, + {"DAC1 MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR"}, + {"DAC1 MIXR", "DAC1 Switch", "IF1 DAC1 R"}, + + {"Stereo1 DAC MIXL", "DAC L1 Switch", "DAC1 MIXL"}, + {"Stereo1 DAC MIXL", "DAC R1 Switch", "DAC1 MIXR"}, + + {"Stereo1 DAC MIXR", "DAC R1 Switch", "DAC1 MIXR"}, + {"Stereo1 DAC MIXR", "DAC L1 Switch", "DAC1 MIXL"}, + + {"DAC L1 Source", "DAC1", "DAC1 MIXL"}, + {"DAC L1 Source", "Stereo1 DAC Mixer", "Stereo1 DAC MIXL"}, + {"DAC R1 Source", "DAC1", "DAC1 MIXR"}, + {"DAC R1 Source", "Stereo1 DAC Mixer", "Stereo1 DAC MIXR"}, + + {"DAC L1", NULL, "DAC L1 Source"}, + {"DAC R1", NULL, "DAC R1 Source"}, + + {"DAC L1", NULL, "DAC 1 Clock"}, + {"DAC R1", NULL, "DAC 1 Clock"}, + + {"HP Amp", NULL, "DAC L1"}, + {"HP Amp", NULL, "DAC R1"}, + {"HP Amp", NULL, "HP Amp L"}, + {"HP Amp", NULL, "HP Amp R"}, + {"HP Amp", NULL, "Capless"}, + {"HP Amp", NULL, "Charge Pump"}, + {"HP Amp", NULL, "CLKDET SYS"}, + {"HP Amp", NULL, "CBJ Power"}, + {"HP Amp", NULL, "Vref2"}, + {"HPOL Playback", "Switch", "HP Amp"}, + {"HPOR Playback", "Switch", "HP Amp"}, + {"HPOL", NULL, "HPOL Playback"}, + {"HPOR", NULL, "HPOR Playback"}, +}; + +static int rt5682_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int slot_width) +{ + struct snd_soc_component *component = dai->component; + unsigned int cl, val = 0; + + if (tx_mask || rx_mask) + snd_soc_component_update_bits(component, RT5682_TDM_ADDA_CTRL_2, + RT5682_TDM_EN, RT5682_TDM_EN); + else + snd_soc_component_update_bits(component, RT5682_TDM_ADDA_CTRL_2, + RT5682_TDM_EN, 0); + + switch (slots) { + case 4: + val |= RT5682_TDM_TX_CH_4; + val |= RT5682_TDM_RX_CH_4; + break; + case 6: + val |= RT5682_TDM_TX_CH_6; + val |= RT5682_TDM_RX_CH_6; + break; + case 8: + val |= RT5682_TDM_TX_CH_8; + val |= RT5682_TDM_RX_CH_8; + break; + case 2: + break; + default: + return -EINVAL; + } + + snd_soc_component_update_bits(component, RT5682_TDM_CTRL, + RT5682_TDM_TX_CH_MASK | RT5682_TDM_RX_CH_MASK, val); + + switch (slot_width) { + case 8: + if (tx_mask || rx_mask) + return -EINVAL; + cl = RT5682_I2S1_TX_CHL_8 | RT5682_I2S1_RX_CHL_8; + break; + case 16: + val = RT5682_TDM_CL_16; + cl = RT5682_I2S1_TX_CHL_16 | RT5682_I2S1_RX_CHL_16; + break; + case 20: + val = RT5682_TDM_CL_20; + cl = RT5682_I2S1_TX_CHL_20 | RT5682_I2S1_RX_CHL_20; + break; + case 24: + val = RT5682_TDM_CL_24; + cl = RT5682_I2S1_TX_CHL_24 | RT5682_I2S1_RX_CHL_24; + break; + case 32: + val = RT5682_TDM_CL_32; + cl = RT5682_I2S1_TX_CHL_32 | RT5682_I2S1_RX_CHL_32; + break; + default: + return -EINVAL; + } + + snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL, + RT5682_TDM_CL_MASK, val); + snd_soc_component_update_bits(component, RT5682_I2S1_SDP, + RT5682_I2S1_TX_CHL_MASK | RT5682_I2S1_RX_CHL_MASK, cl); + + return 0; +} + + +static int rt5682_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + unsigned int len_1 = 0, len_2 = 0; + int pre_div, frame_size; + + rt5682->lrck[dai->id] = params_rate(params); + pre_div = rl6231_get_clk_info(rt5682->sysclk, rt5682->lrck[dai->id]); + + frame_size = snd_soc_params_to_frame_size(params); + if (frame_size < 0) { + dev_err(component->dev, "Unsupported frame size: %d\n", + frame_size); + return -EINVAL; + } + + dev_dbg(dai->dev, "lrck is %dHz and pre_div is %d for iis %d\n", + rt5682->lrck[dai->id], pre_div, dai->id); + + switch (params_width(params)) { + case 16: + break; + case 20: + len_1 |= RT5682_I2S1_DL_20; + len_2 |= RT5682_I2S2_DL_20; + break; + case 24: + len_1 |= RT5682_I2S1_DL_24; + len_2 |= RT5682_I2S2_DL_24; + break; + case 32: + len_1 |= RT5682_I2S1_DL_32; + len_2 |= RT5682_I2S2_DL_24; + break; + case 8: + len_1 |= RT5682_I2S2_DL_8; + len_2 |= RT5682_I2S2_DL_8; + break; + default: + return -EINVAL; + } + + switch (dai->id) { + case RT5682_AIF1: + snd_soc_component_update_bits(component, RT5682_I2S1_SDP, + RT5682_I2S1_DL_MASK, len_1); + if (rt5682->master[RT5682_AIF1]) { + snd_soc_component_update_bits(component, + RT5682_ADDA_CLK_1, RT5682_I2S_M_DIV_MASK, + pre_div << RT5682_I2S_M_DIV_SFT); + } + if (params_channels(params) == 1) /* mono mode */ + snd_soc_component_update_bits(component, + RT5682_I2S1_SDP, RT5682_I2S1_MONO_MASK, + RT5682_I2S1_MONO_EN); + else + snd_soc_component_update_bits(component, + RT5682_I2S1_SDP, RT5682_I2S1_MONO_MASK, + RT5682_I2S1_MONO_DIS); + break; + case RT5682_AIF2: + snd_soc_component_update_bits(component, RT5682_I2S2_SDP, + RT5682_I2S2_DL_MASK, len_2); + if (rt5682->master[RT5682_AIF2]) { + snd_soc_component_update_bits(component, + RT5682_I2S_M_CLK_CTRL_1, RT5682_I2S2_M_PD_MASK, + pre_div << RT5682_I2S2_M_PD_SFT); + } + if (params_channels(params) == 1) /* mono mode */ + snd_soc_component_update_bits(component, + RT5682_I2S2_SDP, RT5682_I2S2_MONO_MASK, + RT5682_I2S2_MONO_EN); + else + snd_soc_component_update_bits(component, + RT5682_I2S2_SDP, RT5682_I2S2_MONO_MASK, + RT5682_I2S2_MONO_DIS); + break; + default: + dev_err(component->dev, "Invalid dai->id: %d\n", dai->id); + return -EINVAL; + } + + return 0; +} + +static int rt5682_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + unsigned int reg_val = 0, tdm_ctrl = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + rt5682->master[dai->id] = 1; + break; + case SND_SOC_DAIFMT_CBS_CFS: + rt5682->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 |= RT5682_I2S_BP_INV; + tdm_ctrl |= RT5682_TDM_S_BP_INV; + break; + case SND_SOC_DAIFMT_NB_IF: + if (dai->id == RT5682_AIF1) + tdm_ctrl |= RT5682_TDM_S_LP_INV | RT5682_TDM_M_BP_INV; + else + return -EINVAL; + break; + case SND_SOC_DAIFMT_IB_IF: + if (dai->id == RT5682_AIF1) + tdm_ctrl |= RT5682_TDM_S_BP_INV | RT5682_TDM_S_LP_INV | + RT5682_TDM_M_BP_INV | RT5682_TDM_M_LP_INV; + else + return -EINVAL; + 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 |= RT5682_I2S_DF_LEFT; + tdm_ctrl |= RT5682_TDM_DF_LEFT; + break; + case SND_SOC_DAIFMT_DSP_A: + reg_val |= RT5682_I2S_DF_PCM_A; + tdm_ctrl |= RT5682_TDM_DF_PCM_A; + break; + case SND_SOC_DAIFMT_DSP_B: + reg_val |= RT5682_I2S_DF_PCM_B; + tdm_ctrl |= RT5682_TDM_DF_PCM_B; + break; + default: + return -EINVAL; + } + + switch (dai->id) { + case RT5682_AIF1: + snd_soc_component_update_bits(component, RT5682_I2S1_SDP, + RT5682_I2S_DF_MASK, reg_val); + snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL, + RT5682_TDM_MS_MASK | RT5682_TDM_S_BP_MASK | + RT5682_TDM_DF_MASK | RT5682_TDM_M_BP_MASK | + RT5682_TDM_M_LP_MASK | RT5682_TDM_S_LP_MASK, + tdm_ctrl | rt5682->master[dai->id]); + break; + case RT5682_AIF2: + if (rt5682->master[dai->id] == 0) + reg_val |= RT5682_I2S2_MS_S; + snd_soc_component_update_bits(component, RT5682_I2S2_SDP, + RT5682_I2S2_MS_MASK | RT5682_I2S_BP_MASK | + RT5682_I2S_DF_MASK, reg_val); + break; + default: + dev_err(component->dev, "Invalid dai->id: %d\n", dai->id); + return -EINVAL; + } + return 0; +} + +static int rt5682_set_component_sysclk(struct snd_soc_component *component, + int clk_id, int source, unsigned int freq, int dir) +{ + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + unsigned int reg_val = 0, src = 0; + + if (freq == rt5682->sysclk && clk_id == rt5682->sysclk_src) + return 0; + + switch (clk_id) { + case RT5682_SCLK_S_MCLK: + reg_val |= RT5682_SCLK_SRC_MCLK; + src = RT5682_CLK_SRC_MCLK; + break; + case RT5682_SCLK_S_PLL1: + reg_val |= RT5682_SCLK_SRC_PLL1; + src = RT5682_CLK_SRC_PLL1; + break; + case RT5682_SCLK_S_PLL2: + reg_val |= RT5682_SCLK_SRC_PLL2; + src = RT5682_CLK_SRC_PLL2; + break; + case RT5682_SCLK_S_RCCLK: + reg_val |= RT5682_SCLK_SRC_RCCLK; + src = RT5682_CLK_SRC_RCCLK; + break; + default: + dev_err(component->dev, "Invalid clock id (%d)\n", clk_id); + return -EINVAL; + } + snd_soc_component_update_bits(component, RT5682_GLB_CLK, + RT5682_SCLK_SRC_MASK, reg_val); + + if (rt5682->master[RT5682_AIF2]) { + snd_soc_component_update_bits(component, + RT5682_I2S_M_CLK_CTRL_1, RT5682_I2S2_SRC_MASK, + src << RT5682_I2S2_SRC_SFT); + } + + rt5682->sysclk = freq; + rt5682->sysclk_src = clk_id; + + dev_dbg(component->dev, "Sysclk is %dHz and clock id is %d\n", + freq, clk_id); + + return 0; +} + +static int rt5682_set_component_pll(struct snd_soc_component *component, + int pll_id, int source, unsigned int freq_in, + unsigned int freq_out) +{ + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + struct rl6231_pll_code pll_code; + int ret; + + if (source == rt5682->pll_src && freq_in == rt5682->pll_in && + freq_out == rt5682->pll_out) + return 0; + + if (!freq_in || !freq_out) { + dev_dbg(component->dev, "PLL disabled\n"); + + rt5682->pll_in = 0; + rt5682->pll_out = 0; + snd_soc_component_update_bits(component, RT5682_GLB_CLK, + RT5682_SCLK_SRC_MASK, RT5682_SCLK_SRC_MCLK); + return 0; + } + + switch (source) { + case RT5682_PLL1_S_MCLK: + snd_soc_component_update_bits(component, RT5682_GLB_CLK, + RT5682_PLL1_SRC_MASK, RT5682_PLL1_SRC_MCLK); + break; + case RT5682_PLL1_S_BCLK1: + snd_soc_component_update_bits(component, RT5682_GLB_CLK, + RT5682_PLL1_SRC_MASK, RT5682_PLL1_SRC_BCLK1); + break; + default: + dev_err(component->dev, "Unknown PLL Source %d\n", source); + return -EINVAL; + } + + ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); + if (ret < 0) { + dev_err(component->dev, "Unsupport input clock %d\n", freq_in); + return ret; + } + + dev_dbg(component->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_component_write(component, RT5682_PLL_CTRL_1, + pll_code.n_code << RT5682_PLL_N_SFT | pll_code.k_code); + snd_soc_component_write(component, RT5682_PLL_CTRL_2, + (pll_code.m_bp ? 0 : pll_code.m_code) << RT5682_PLL_M_SFT | + pll_code.m_bp << RT5682_PLL_M_BP_SFT | RT5682_PLL_RST); + + rt5682->pll_in = freq_in; + rt5682->pll_out = freq_out; + rt5682->pll_src = source; + + return 0; +} + +static int rt5682_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) +{ + struct snd_soc_component *component = dai->component; + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + + rt5682->bclk[dai->id] = ratio; + + switch (ratio) { + case 64: + snd_soc_component_update_bits(component, RT5682_ADDA_CLK_2, + RT5682_I2S2_BCLK_MS2_MASK, + RT5682_I2S2_BCLK_MS2_64); + break; + case 32: + snd_soc_component_update_bits(component, RT5682_ADDA_CLK_2, + RT5682_I2S2_BCLK_MS2_MASK, + RT5682_I2S2_BCLK_MS2_32); + break; + default: + dev_err(dai->dev, "Invalid bclk ratio %d\n", ratio); + return -EINVAL; + } + + return 0; +} + +static int rt5682_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + + switch (level) { + case SND_SOC_BIAS_PREPARE: + regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, + RT5682_PWR_MB | RT5682_PWR_BG, + RT5682_PWR_MB | RT5682_PWR_BG); + regmap_update_bits(rt5682->regmap, RT5682_PWR_DIG_1, + RT5682_DIG_GATE_CTRL | RT5682_PWR_LDO, + RT5682_DIG_GATE_CTRL | RT5682_PWR_LDO); + break; + + case SND_SOC_BIAS_STANDBY: + regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, + RT5682_PWR_MB, RT5682_PWR_MB); + regmap_update_bits(rt5682->regmap, RT5682_PWR_DIG_1, + RT5682_DIG_GATE_CTRL, RT5682_DIG_GATE_CTRL); + break; + case SND_SOC_BIAS_OFF: + regmap_update_bits(rt5682->regmap, RT5682_PWR_DIG_1, + RT5682_DIG_GATE_CTRL | RT5682_PWR_LDO, 0); + regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, + RT5682_PWR_MB | RT5682_PWR_BG, 0); + break; + + default: + break; + } + + return 0; +} + +static int rt5682_probe(struct snd_soc_component *component) +{ + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + + rt5682->component = component; + + return 0; +} + +static void rt5682_remove(struct snd_soc_component *component) +{ + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + + rt5682_reset(rt5682->regmap); +} + +#ifdef CONFIG_PM +static int rt5682_suspend(struct snd_soc_component *component) +{ + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + + regcache_cache_only(rt5682->regmap, true); + regcache_mark_dirty(rt5682->regmap); + return 0; +} + +static int rt5682_resume(struct snd_soc_component *component) +{ + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + + regcache_cache_only(rt5682->regmap, false); + regcache_sync(rt5682->regmap); + + return 0; +} +#else +#define rt5682_suspend NULL +#define rt5682_resume NULL +#endif + +#define RT5682_STEREO_RATES SNDRV_PCM_RATE_8000_192000 +#define RT5682_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 rt5682_aif1_dai_ops = { + .hw_params = rt5682_hw_params, + .set_fmt = rt5682_set_dai_fmt, + .set_tdm_slot = rt5682_set_tdm_slot, +}; + +static const struct snd_soc_dai_ops rt5682_aif2_dai_ops = { + .hw_params = rt5682_hw_params, + .set_fmt = rt5682_set_dai_fmt, + .set_bclk_ratio = rt5682_set_bclk_ratio, +}; + +static struct snd_soc_dai_driver rt5682_dai[] = { + { + .name = "rt5682-aif1", + .id = RT5682_AIF1, + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT5682_STEREO_RATES, + .formats = RT5682_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT5682_STEREO_RATES, + .formats = RT5682_FORMATS, + }, + .ops = &rt5682_aif1_dai_ops, + }, + { + .name = "rt5682-aif2", + .id = RT5682_AIF2, + .capture = { + .stream_name = "AIF2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT5682_STEREO_RATES, + .formats = RT5682_FORMATS, + }, + .ops = &rt5682_aif2_dai_ops, + }, +}; + +static const struct snd_soc_component_driver soc_component_dev_rt5682 = { + .probe = rt5682_probe, + .remove = rt5682_remove, + .suspend = rt5682_suspend, + .resume = rt5682_resume, + .set_bias_level = rt5682_set_bias_level, + .controls = rt5682_snd_controls, + .num_controls = ARRAY_SIZE(rt5682_snd_controls), + .dapm_widgets = rt5682_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5682_dapm_widgets), + .dapm_routes = rt5682_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5682_dapm_routes), + .set_sysclk = rt5682_set_component_sysclk, + .set_pll = rt5682_set_component_pll, + .set_jack = rt5682_set_jack_detect, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static const struct regmap_config rt5682_regmap = { + .reg_bits = 16, + .val_bits = 16, + .max_register = RT5682_I2C_MODE, + .volatile_reg = rt5682_volatile_register, + .readable_reg = rt5682_readable_register, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt5682_reg, + .num_reg_defaults = ARRAY_SIZE(rt5682_reg), + .use_single_rw = true, +}; + +static const struct i2c_device_id rt5682_i2c_id[] = { + {"rt5682", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, rt5682_i2c_id); + +static int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev) +{ + + device_property_read_u32(dev, "realtek,dmic1-data-pin", + &rt5682->pdata.dmic1_data_pin); + device_property_read_u32(dev, "realtek,dmic1-clk-pin", + &rt5682->pdata.dmic1_clk_pin); + device_property_read_u32(dev, "realtek,jd-src", + &rt5682->pdata.jd_src); + + rt5682->pdata.ldo1_en = of_get_named_gpio(dev->of_node, + "realtek,ldo1-en-gpios", 0); + + return 0; +} + +static void rt5682_calibrate(struct rt5682_priv *rt5682) +{ + int value, count; + + mutex_lock(&rt5682->calibrate_mutex); + + rt5682_reset(rt5682->regmap); + regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xa2bf); + usleep_range(15000, 20000); + regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xf2bf); + regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); + regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x8001); + regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); + regmap_write(rt5682->regmap, RT5682_STO1_DAC_MIXER, 0x2080); + regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0x4040); + regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0069); + regmap_write(rt5682->regmap, RT5682_CHOP_DAC, 0x3000); + regmap_write(rt5682->regmap, RT5682_HP_CTRL_2, 0x6000); + regmap_write(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1, 0x0f26); + regmap_write(rt5682->regmap, RT5682_CALIB_ADC_CTRL, 0x7f05); + regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0x686c); + regmap_write(rt5682->regmap, RT5682_CAL_REC, 0x0d0d); + regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_9, 0x000f); + regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x8d01); + regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_2, 0x0321); + regmap_write(rt5682->regmap, RT5682_HP_LOGIC_CTRL_2, 0x0004); + regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_1, 0x7c00); + regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_3, 0x06a1); + regmap_write(rt5682->regmap, RT5682_A_DAC1_MUX, 0x0311); + regmap_write(rt5682->regmap, RT5682_RESET_HPF_CTRL, 0x0000); + regmap_write(rt5682->regmap, RT5682_ADC_STO1_HP_CTRL_1, 0x3320); + + regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_1, 0xfc00); + + for (count = 0; count < 60; count++) { + regmap_read(rt5682->regmap, RT5682_HP_CALIB_STA_1, &value); + if (!(value & 0x8000)) + break; + + usleep_range(10000, 10005); + } + + if (count >= 60) + pr_err("HP Calibration Failure\n"); + + /* restore settings */ + regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0xc0c4); + regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x0000); + + mutex_unlock(&rt5682->calibrate_mutex); + +} + +static int rt5682_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rt5682_platform_data *pdata = dev_get_platdata(&i2c->dev); + struct rt5682_priv *rt5682; + int i, ret; + unsigned int val; + + rt5682 = devm_kzalloc(&i2c->dev, sizeof(struct rt5682_priv), + GFP_KERNEL); + + if (rt5682 == NULL) + return -ENOMEM; + + i2c_set_clientdata(i2c, rt5682); + + if (pdata) + rt5682->pdata = *pdata; + else + rt5682_parse_dt(rt5682, &i2c->dev); + + rt5682->regmap = devm_regmap_init_i2c(i2c, &rt5682_regmap); + if (IS_ERR(rt5682->regmap)) { + ret = PTR_ERR(rt5682->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + for (i = 0; i < ARRAY_SIZE(rt5682->supplies); i++) + rt5682->supplies[i].supply = rt5682_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(rt5682->supplies), + rt5682->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies), + rt5682->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); + return ret; + } + + if (gpio_is_valid(rt5682->pdata.ldo1_en)) { + if (devm_gpio_request_one(&i2c->dev, rt5682->pdata.ldo1_en, + GPIOF_OUT_INIT_HIGH, "rt5682")) + dev_err(&i2c->dev, "Fail gpio_request gpio_ldo\n"); + } + + /* Sleep for 300 ms miniumum */ + usleep_range(300000, 350000); + + regmap_write(rt5682->regmap, RT5682_I2C_MODE, 0x1); + usleep_range(10000, 15000); + + regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); + if (val != DEVICE_ID) { + pr_err("Device with ID register %x is not rt5682\n", val); + return -ENODEV; + } + + rt5682_reset(rt5682->regmap); + + rt5682_calibrate(rt5682); + + ret = regmap_register_patch(rt5682->regmap, patch_list, + ARRAY_SIZE(patch_list)); + if (ret != 0) + dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); + + regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000); + + /* DMIC pin*/ + if (rt5682->pdata.dmic1_data_pin != RT5682_DMIC1_NULL) { + switch (rt5682->pdata.dmic1_data_pin) { + case RT5682_DMIC1_DATA_GPIO2: /* share with LRCK2 */ + regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1, + RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO2); + regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, + RT5682_GP2_PIN_MASK, RT5682_GP2_PIN_DMIC_SDA); + break; + + case RT5682_DMIC1_DATA_GPIO5: /* share with DACDAT1 */ + regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1, + RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO5); + regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, + RT5682_GP5_PIN_MASK, RT5682_GP5_PIN_DMIC_SDA); + break; + + default: + dev_warn(&i2c->dev, "invalid DMIC_DAT pin\n"); + break; + } + + switch (rt5682->pdata.dmic1_clk_pin) { + case RT5682_DMIC1_CLK_GPIO1: /* share with IRQ */ + regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, + RT5682_GP1_PIN_MASK, RT5682_GP1_PIN_DMIC_CLK); + break; + + case RT5682_DMIC1_CLK_GPIO3: /* share with BCLK2 */ + regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, + RT5682_GP3_PIN_MASK, RT5682_GP3_PIN_DMIC_CLK); + break; + + default: + dev_warn(&i2c->dev, "invalid DMIC_CLK pin\n"); + break; + } + } + + regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, + RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, + RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); + regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); + regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, + RT5682_GP4_PIN_MASK | RT5682_GP5_PIN_MASK, + RT5682_GP4_PIN_ADCDAT1 | RT5682_GP5_PIN_DACDAT1); + regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); + + INIT_DELAYED_WORK(&rt5682->jack_detect_work, + rt5682_jack_detect_handler); + INIT_DELAYED_WORK(&rt5682->jd_check_work, + rt5682_jd_check_handler); + + mutex_init(&rt5682->calibrate_mutex); + + if (i2c->irq) { + ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, + rt5682_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING + | IRQF_ONESHOT, "rt5682", rt5682); + if (ret) + dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); + + } + + return snd_soc_register_component(&i2c->dev, &soc_component_dev_rt5682, + rt5682_dai, ARRAY_SIZE(rt5682_dai)); +} + +static int rt5682_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_component(&i2c->dev); + + return 0; +} + +static void rt5682_i2c_shutdown(struct i2c_client *client) +{ + struct rt5682_priv *rt5682 = i2c_get_clientdata(client); + + rt5682_reset(rt5682->regmap); +} + +#ifdef CONFIG_OF +static const struct of_device_id rt5682_of_match[] = { + {.compatible = "realtek,rt5682i"}, + {}, +}; +MODULE_DEVICE_TABLE(of, rt5682_of_match); +#endif + +#ifdef CONFIG_ACPI +static const struct acpi_device_id rt5682_acpi_match[] = { + {"10EC5682", 0,}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, rt5682_acpi_match); +#endif + +static struct i2c_driver rt5682_i2c_driver = { + .driver = { + .name = "rt5682", + .of_match_table = of_match_ptr(rt5682_of_match), + .acpi_match_table = ACPI_PTR(rt5682_acpi_match), + }, + .probe = rt5682_i2c_probe, + .remove = rt5682_i2c_remove, + .shutdown = rt5682_i2c_shutdown, + .id_table = rt5682_i2c_id, +}; +module_i2c_driver(rt5682_i2c_driver); + +MODULE_DESCRIPTION("ASoC RT5682 driver"); +MODULE_AUTHOR("Bard Liao "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h new file mode 100644 index 000000000000..8068140ebe3f --- /dev/null +++ b/sound/soc/codecs/rt5682.h @@ -0,0 +1,1324 @@ +/* + * rt5682.h -- RT5682/RT5658 ALSA SoC audio driver + * + * Copyright 2018 Realtek Microelectronics + * Author: Bard Liao + * + * 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 __RT5682_H__ +#define __RT5682_H__ + +#include + +#define DEVICE_ID 0x6530 + +/* Info */ +#define RT5682_RESET 0x0000 +#define RT5682_VERSION_ID 0x00fd +#define RT5682_VENDOR_ID 0x00fe +#define RT5682_DEVICE_ID 0x00ff +/* I/O - Output */ +#define RT5682_HP_CTRL_1 0x0002 +#define RT5682_HP_CTRL_2 0x0003 +#define RT5682_HPL_GAIN 0x0005 +#define RT5682_HPR_GAIN 0x0006 + +#define RT5682_I2C_CTRL 0x0008 + +/* I/O - Input */ +#define RT5682_CBJ_BST_CTRL 0x000b +#define RT5682_CBJ_CTRL_1 0x0010 +#define RT5682_CBJ_CTRL_2 0x0011 +#define RT5682_CBJ_CTRL_3 0x0012 +#define RT5682_CBJ_CTRL_4 0x0013 +#define RT5682_CBJ_CTRL_5 0x0014 +#define RT5682_CBJ_CTRL_6 0x0015 +#define RT5682_CBJ_CTRL_7 0x0016 +/* I/O - ADC/DAC/DMIC */ +#define RT5682_DAC1_DIG_VOL 0x0019 +#define RT5682_STO1_ADC_DIG_VOL 0x001c +#define RT5682_STO1_ADC_BOOST 0x001f +#define RT5682_HP_IMP_GAIN_1 0x0022 +#define RT5682_HP_IMP_GAIN_2 0x0023 +/* Mixer - D-D */ +#define RT5682_SIDETONE_CTRL 0x0024 +#define RT5682_STO1_ADC_MIXER 0x0026 +#define RT5682_AD_DA_MIXER 0x0029 +#define RT5682_STO1_DAC_MIXER 0x002a +#define RT5682_A_DAC1_MUX 0x002b +#define RT5682_DIG_INF2_DATA 0x0030 +/* Mixer - ADC */ +#define RT5682_REC_MIXER 0x003c +#define RT5682_CAL_REC 0x0044 +#define RT5682_ALC_BACK_GAIN 0x0049 +/* Power */ +#define RT5682_PWR_DIG_1 0x0061 +#define RT5682_PWR_DIG_2 0x0062 +#define RT5682_PWR_ANLG_1 0x0063 +#define RT5682_PWR_ANLG_2 0x0064 +#define RT5682_PWR_ANLG_3 0x0065 +#define RT5682_PWR_MIXER 0x0066 +#define RT5682_PWR_VOL 0x0067 +/* Clock Detect */ +#define RT5682_CLK_DET 0x006b +/* Filter Auto Reset */ +#define RT5682_RESET_LPF_CTRL 0x006c +#define RT5682_RESET_HPF_CTRL 0x006d +/* DMIC */ +#define RT5682_DMIC_CTRL_1 0x006e +/* Format - ADC/DAC */ +#define RT5682_I2S1_SDP 0x0070 +#define RT5682_I2S2_SDP 0x0071 +#define RT5682_ADDA_CLK_1 0x0073 +#define RT5682_ADDA_CLK_2 0x0074 +#define RT5682_I2S1_F_DIV_CTRL_1 0x0075 +#define RT5682_I2S1_F_DIV_CTRL_2 0x0076 +/* Format - TDM Control */ +#define RT5682_TDM_CTRL 0x0079 +#define RT5682_TDM_ADDA_CTRL_1 0x007a +#define RT5682_TDM_ADDA_CTRL_2 0x007b +#define RT5682_DATA_SEL_CTRL_1 0x007c +#define RT5682_TDM_TCON_CTRL 0x007e +/* Function - Analog */ +#define RT5682_GLB_CLK 0x0080 +#define RT5682_PLL_CTRL_1 0x0081 +#define RT5682_PLL_CTRL_2 0x0082 +#define RT5682_PLL_TRACK_1 0x0083 +#define RT5682_PLL_TRACK_2 0x0084 +#define RT5682_PLL_TRACK_3 0x0085 +#define RT5682_PLL_TRACK_4 0x0086 +#define RT5682_PLL_TRACK_5 0x0087 +#define RT5682_PLL_TRACK_6 0x0088 +#define RT5682_PLL_TRACK_11 0x008c +#define RT5682_SDW_REF_CLK 0x008d +#define RT5682_DEPOP_1 0x008e +#define RT5682_DEPOP_2 0x008f +#define RT5682_HP_CHARGE_PUMP_1 0x0091 +#define RT5682_HP_CHARGE_PUMP_2 0x0092 +#define RT5682_MICBIAS_1 0x0093 +#define RT5682_MICBIAS_2 0x0094 +#define RT5682_PLL_TRACK_12 0x0098 +#define RT5682_PLL_TRACK_14 0x009a +#define RT5682_PLL2_CTRL_1 0x009b +#define RT5682_PLL2_CTRL_2 0x009c +#define RT5682_PLL2_CTRL_3 0x009d +#define RT5682_PLL2_CTRL_4 0x009e +#define RT5682_RC_CLK_CTRL 0x009f +#define RT5682_I2S_M_CLK_CTRL_1 0x00a0 +#define RT5682_I2S2_F_DIV_CTRL_1 0x00a3 +#define RT5682_I2S2_F_DIV_CTRL_2 0x00a4 +/* Function - Digital */ +#define RT5682_EQ_CTRL_1 0x00ae +#define RT5682_EQ_CTRL_2 0x00af +#define RT5682_IRQ_CTRL_1 0x00b6 +#define RT5682_IRQ_CTRL_2 0x00b7 +#define RT5682_IRQ_CTRL_3 0x00b8 +#define RT5682_IRQ_CTRL_4 0x00b9 +#define RT5682_INT_ST_1 0x00be +#define RT5682_GPIO_CTRL_1 0x00c0 +#define RT5682_GPIO_CTRL_2 0x00c1 +#define RT5682_GPIO_CTRL_3 0x00c2 +#define RT5682_HP_AMP_DET_CTRL_1 0x00d0 +#define RT5682_HP_AMP_DET_CTRL_2 0x00d1 +#define RT5682_MID_HP_AMP_DET 0x00d2 +#define RT5682_LOW_HP_AMP_DET 0x00d3 +#define RT5682_DELAY_BUF_CTRL 0x00d4 +#define RT5682_SV_ZCD_1 0x00d9 +#define RT5682_SV_ZCD_2 0x00da +#define RT5682_IL_CMD_1 0x00db +#define RT5682_IL_CMD_2 0x00dc +#define RT5682_IL_CMD_3 0x00dd +#define RT5682_IL_CMD_4 0x00de +#define RT5682_IL_CMD_5 0x00df +#define RT5682_IL_CMD_6 0x00e0 +#define RT5682_4BTN_IL_CMD_1 0x00e2 +#define RT5682_4BTN_IL_CMD_2 0x00e3 +#define RT5682_4BTN_IL_CMD_3 0x00e4 +#define RT5682_4BTN_IL_CMD_4 0x00e5 +#define RT5682_4BTN_IL_CMD_5 0x00e6 +#define RT5682_4BTN_IL_CMD_6 0x00e7 +#define RT5682_4BTN_IL_CMD_7 0x00e8 + +#define RT5682_ADC_STO1_HP_CTRL_1 0x00ea +#define RT5682_ADC_STO1_HP_CTRL_2 0x00eb +#define RT5682_AJD1_CTRL 0x00f0 +#define RT5682_JD1_THD 0x00f1 +#define RT5682_JD2_THD 0x00f2 +#define RT5682_JD_CTRL_1 0x00f6 +/* General Control */ +#define RT5682_DUMMY_1 0x00fa +#define RT5682_DUMMY_2 0x00fb +#define RT5682_DUMMY_3 0x00fc + +#define RT5682_DAC_ADC_DIG_VOL1 0x0100 +#define RT5682_BIAS_CUR_CTRL_2 0x010b +#define RT5682_BIAS_CUR_CTRL_3 0x010c +#define RT5682_BIAS_CUR_CTRL_4 0x010d +#define RT5682_BIAS_CUR_CTRL_5 0x010e +#define RT5682_BIAS_CUR_CTRL_6 0x010f +#define RT5682_BIAS_CUR_CTRL_7 0x0110 +#define RT5682_BIAS_CUR_CTRL_8 0x0111 +#define RT5682_BIAS_CUR_CTRL_9 0x0112 +#define RT5682_BIAS_CUR_CTRL_10 0x0113 +#define RT5682_VREF_REC_OP_FB_CAP_CTRL 0x0117 +#define RT5682_CHARGE_PUMP_1 0x0125 +#define RT5682_DIG_IN_CTRL_1 0x0132 +#define RT5682_PAD_DRIVING_CTRL 0x0136 +#define RT5682_SOFT_RAMP_DEPOP 0x0138 +#define RT5682_CHOP_DAC 0x013a +#define RT5682_CHOP_ADC 0x013b +#define RT5682_CALIB_ADC_CTRL 0x013c +#define RT5682_VOL_TEST 0x013f +#define RT5682_SPKVDD_DET_STA 0x0142 +#define RT5682_TEST_MODE_CTRL_1 0x0145 +#define RT5682_TEST_MODE_CTRL_2 0x0146 +#define RT5682_TEST_MODE_CTRL_3 0x0147 +#define RT5682_TEST_MODE_CTRL_4 0x0148 +#define RT5682_TEST_MODE_CTRL_5 0x0149 +#define RT5682_PLL1_INTERNAL 0x0150 +#define RT5682_PLL2_INTERNAL 0x0151 +#define RT5682_STO_NG2_CTRL_1 0x0160 +#define RT5682_STO_NG2_CTRL_2 0x0161 +#define RT5682_STO_NG2_CTRL_3 0x0162 +#define RT5682_STO_NG2_CTRL_4 0x0163 +#define RT5682_STO_NG2_CTRL_5 0x0164 +#define RT5682_STO_NG2_CTRL_6 0x0165 +#define RT5682_STO_NG2_CTRL_7 0x0166 +#define RT5682_STO_NG2_CTRL_8 0x0167 +#define RT5682_STO_NG2_CTRL_9 0x0168 +#define RT5682_STO_NG2_CTRL_10 0x0169 +#define RT5682_STO1_DAC_SIL_DET 0x0190 +#define RT5682_SIL_PSV_CTRL1 0x0194 +#define RT5682_SIL_PSV_CTRL2 0x0195 +#define RT5682_SIL_PSV_CTRL3 0x0197 +#define RT5682_SIL_PSV_CTRL4 0x0198 +#define RT5682_SIL_PSV_CTRL5 0x0199 +#define RT5682_HP_IMP_SENS_CTRL_01 0x01af +#define RT5682_HP_IMP_SENS_CTRL_02 0x01b0 +#define RT5682_HP_IMP_SENS_CTRL_03 0x01b1 +#define RT5682_HP_IMP_SENS_CTRL_04 0x01b2 +#define RT5682_HP_IMP_SENS_CTRL_05 0x01b3 +#define RT5682_HP_IMP_SENS_CTRL_06 0x01b4 +#define RT5682_HP_IMP_SENS_CTRL_07 0x01b5 +#define RT5682_HP_IMP_SENS_CTRL_08 0x01b6 +#define RT5682_HP_IMP_SENS_CTRL_09 0x01b7 +#define RT5682_HP_IMP_SENS_CTRL_10 0x01b8 +#define RT5682_HP_IMP_SENS_CTRL_11 0x01b9 +#define RT5682_HP_IMP_SENS_CTRL_12 0x01ba +#define RT5682_HP_IMP_SENS_CTRL_13 0x01bb +#define RT5682_HP_IMP_SENS_CTRL_14 0x01bc +#define RT5682_HP_IMP_SENS_CTRL_15 0x01bd +#define RT5682_HP_IMP_SENS_CTRL_16 0x01be +#define RT5682_HP_IMP_SENS_CTRL_17 0x01bf +#define RT5682_HP_IMP_SENS_CTRL_18 0x01c0 +#define RT5682_HP_IMP_SENS_CTRL_19 0x01c1 +#define RT5682_HP_IMP_SENS_CTRL_20 0x01c2 +#define RT5682_HP_IMP_SENS_CTRL_21 0x01c3 +#define RT5682_HP_IMP_SENS_CTRL_22 0x01c4 +#define RT5682_HP_IMP_SENS_CTRL_23 0x01c5 +#define RT5682_HP_IMP_SENS_CTRL_24 0x01c6 +#define RT5682_HP_IMP_SENS_CTRL_25 0x01c7 +#define RT5682_HP_IMP_SENS_CTRL_26 0x01c8 +#define RT5682_HP_IMP_SENS_CTRL_27 0x01c9 +#define RT5682_HP_IMP_SENS_CTRL_28 0x01ca +#define RT5682_HP_IMP_SENS_CTRL_29 0x01cb +#define RT5682_HP_IMP_SENS_CTRL_30 0x01cc +#define RT5682_HP_IMP_SENS_CTRL_31 0x01cd +#define RT5682_HP_IMP_SENS_CTRL_32 0x01ce +#define RT5682_HP_IMP_SENS_CTRL_33 0x01cf +#define RT5682_HP_IMP_SENS_CTRL_34 0x01d0 +#define RT5682_HP_IMP_SENS_CTRL_35 0x01d1 +#define RT5682_HP_IMP_SENS_CTRL_36 0x01d2 +#define RT5682_HP_IMP_SENS_CTRL_37 0x01d3 +#define RT5682_HP_IMP_SENS_CTRL_38 0x01d4 +#define RT5682_HP_IMP_SENS_CTRL_39 0x01d5 +#define RT5682_HP_IMP_SENS_CTRL_40 0x01d6 +#define RT5682_HP_IMP_SENS_CTRL_41 0x01d7 +#define RT5682_HP_IMP_SENS_CTRL_42 0x01d8 +#define RT5682_HP_IMP_SENS_CTRL_43 0x01d9 +#define RT5682_HP_LOGIC_CTRL_1 0x01da +#define RT5682_HP_LOGIC_CTRL_2 0x01db +#define RT5682_HP_LOGIC_CTRL_3 0x01dc +#define RT5682_HP_CALIB_CTRL_1 0x01de +#define RT5682_HP_CALIB_CTRL_2 0x01df +#define RT5682_HP_CALIB_CTRL_3 0x01e0 +#define RT5682_HP_CALIB_CTRL_4 0x01e1 +#define RT5682_HP_CALIB_CTRL_5 0x01e2 +#define RT5682_HP_CALIB_CTRL_6 0x01e3 +#define RT5682_HP_CALIB_CTRL_7 0x01e4 +#define RT5682_HP_CALIB_CTRL_9 0x01e6 +#define RT5682_HP_CALIB_CTRL_10 0x01e7 +#define RT5682_HP_CALIB_CTRL_11 0x01e8 +#define RT5682_HP_CALIB_STA_1 0x01ea +#define RT5682_HP_CALIB_STA_2 0x01eb +#define RT5682_HP_CALIB_STA_3 0x01ec +#define RT5682_HP_CALIB_STA_4 0x01ed +#define RT5682_HP_CALIB_STA_5 0x01ee +#define RT5682_HP_CALIB_STA_6 0x01ef +#define RT5682_HP_CALIB_STA_7 0x01f0 +#define RT5682_HP_CALIB_STA_8 0x01f1 +#define RT5682_HP_CALIB_STA_9 0x01f2 +#define RT5682_HP_CALIB_STA_10 0x01f3 +#define RT5682_HP_CALIB_STA_11 0x01f4 +#define RT5682_SAR_IL_CMD_1 0x0210 +#define RT5682_SAR_IL_CMD_2 0x0211 +#define RT5682_SAR_IL_CMD_3 0x0212 +#define RT5682_SAR_IL_CMD_4 0x0213 +#define RT5682_SAR_IL_CMD_5 0x0214 +#define RT5682_SAR_IL_CMD_6 0x0215 +#define RT5682_SAR_IL_CMD_7 0x0216 +#define RT5682_SAR_IL_CMD_8 0x0217 +#define RT5682_SAR_IL_CMD_9 0x0218 +#define RT5682_SAR_IL_CMD_10 0x0219 +#define RT5682_SAR_IL_CMD_11 0x021a +#define RT5682_SAR_IL_CMD_12 0x021b +#define RT5682_SAR_IL_CMD_13 0x021c +#define RT5682_EFUSE_CTRL_1 0x0250 +#define RT5682_EFUSE_CTRL_2 0x0251 +#define RT5682_EFUSE_CTRL_3 0x0252 +#define RT5682_EFUSE_CTRL_4 0x0253 +#define RT5682_EFUSE_CTRL_5 0x0254 +#define RT5682_EFUSE_CTRL_6 0x0255 +#define RT5682_EFUSE_CTRL_7 0x0256 +#define RT5682_EFUSE_CTRL_8 0x0257 +#define RT5682_EFUSE_CTRL_9 0x0258 +#define RT5682_EFUSE_CTRL_10 0x0259 +#define RT5682_EFUSE_CTRL_11 0x025a +#define RT5682_JD_TOP_VC_VTRL 0x0270 +#define RT5682_DRC1_CTRL_0 0x02ff +#define RT5682_DRC1_CTRL_1 0x0300 +#define RT5682_DRC1_CTRL_2 0x0301 +#define RT5682_DRC1_CTRL_3 0x0302 +#define RT5682_DRC1_CTRL_4 0x0303 +#define RT5682_DRC1_CTRL_5 0x0304 +#define RT5682_DRC1_CTRL_6 0x0305 +#define RT5682_DRC1_HARD_LMT_CTRL_1 0x0306 +#define RT5682_DRC1_HARD_LMT_CTRL_2 0x0307 +#define RT5682_DRC1_PRIV_1 0x0310 +#define RT5682_DRC1_PRIV_2 0x0311 +#define RT5682_DRC1_PRIV_3 0x0312 +#define RT5682_DRC1_PRIV_4 0x0313 +#define RT5682_DRC1_PRIV_5 0x0314 +#define RT5682_DRC1_PRIV_6 0x0315 +#define RT5682_DRC1_PRIV_7 0x0316 +#define RT5682_DRC1_PRIV_8 0x0317 +#define RT5682_EQ_AUTO_RCV_CTRL1 0x03c0 +#define RT5682_EQ_AUTO_RCV_CTRL2 0x03c1 +#define RT5682_EQ_AUTO_RCV_CTRL3 0x03c2 +#define RT5682_EQ_AUTO_RCV_CTRL4 0x03c3 +#define RT5682_EQ_AUTO_RCV_CTRL5 0x03c4 +#define RT5682_EQ_AUTO_RCV_CTRL6 0x03c5 +#define RT5682_EQ_AUTO_RCV_CTRL7 0x03c6 +#define RT5682_EQ_AUTO_RCV_CTRL8 0x03c7 +#define RT5682_EQ_AUTO_RCV_CTRL9 0x03c8 +#define RT5682_EQ_AUTO_RCV_CTRL10 0x03c9 +#define RT5682_EQ_AUTO_RCV_CTRL11 0x03ca +#define RT5682_EQ_AUTO_RCV_CTRL12 0x03cb +#define RT5682_EQ_AUTO_RCV_CTRL13 0x03cc +#define RT5682_ADC_L_EQ_LPF1_A1 0x03d0 +#define RT5682_R_EQ_LPF1_A1 0x03d1 +#define RT5682_L_EQ_LPF1_H0 0x03d2 +#define RT5682_R_EQ_LPF1_H0 0x03d3 +#define RT5682_L_EQ_BPF1_A1 0x03d4 +#define RT5682_R_EQ_BPF1_A1 0x03d5 +#define RT5682_L_EQ_BPF1_A2 0x03d6 +#define RT5682_R_EQ_BPF1_A2 0x03d7 +#define RT5682_L_EQ_BPF1_H0 0x03d8 +#define RT5682_R_EQ_BPF1_H0 0x03d9 +#define RT5682_L_EQ_BPF2_A1 0x03da +#define RT5682_R_EQ_BPF2_A1 0x03db +#define RT5682_L_EQ_BPF2_A2 0x03dc +#define RT5682_R_EQ_BPF2_A2 0x03dd +#define RT5682_L_EQ_BPF2_H0 0x03de +#define RT5682_R_EQ_BPF2_H0 0x03df +#define RT5682_L_EQ_BPF3_A1 0x03e0 +#define RT5682_R_EQ_BPF3_A1 0x03e1 +#define RT5682_L_EQ_BPF3_A2 0x03e2 +#define RT5682_R_EQ_BPF3_A2 0x03e3 +#define RT5682_L_EQ_BPF3_H0 0x03e4 +#define RT5682_R_EQ_BPF3_H0 0x03e5 +#define RT5682_L_EQ_BPF4_A1 0x03e6 +#define RT5682_R_EQ_BPF4_A1 0x03e7 +#define RT5682_L_EQ_BPF4_A2 0x03e8 +#define RT5682_R_EQ_BPF4_A2 0x03e9 +#define RT5682_L_EQ_BPF4_H0 0x03ea +#define RT5682_R_EQ_BPF4_H0 0x03eb +#define RT5682_L_EQ_HPF1_A1 0x03ec +#define RT5682_R_EQ_HPF1_A1 0x03ed +#define RT5682_L_EQ_HPF1_H0 0x03ee +#define RT5682_R_EQ_HPF1_H0 0x03ef +#define RT5682_L_EQ_PRE_VOL 0x03f0 +#define RT5682_R_EQ_PRE_VOL 0x03f1 +#define RT5682_L_EQ_POST_VOL 0x03f2 +#define RT5682_R_EQ_POST_VOL 0x03f3 +#define RT5682_I2C_MODE 0xffff + + +/* global definition */ +#define RT5682_L_MUTE (0x1 << 15) +#define RT5682_L_MUTE_SFT 15 +#define RT5682_VOL_L_MUTE (0x1 << 14) +#define RT5682_VOL_L_SFT 14 +#define RT5682_R_MUTE (0x1 << 7) +#define RT5682_R_MUTE_SFT 7 +#define RT5682_VOL_R_MUTE (0x1 << 6) +#define RT5682_VOL_R_SFT 6 +#define RT5682_L_VOL_MASK (0x3f << 8) +#define RT5682_L_VOL_SFT 8 +#define RT5682_R_VOL_MASK (0x3f) +#define RT5682_R_VOL_SFT 0 + +/*Headphone Amp L/R Analog Gain and Digital NG2 Gain Control (0x0005 0x0006)*/ +#define RT5682_G_HP (0xf << 8) +#define RT5682_G_HP_SFT 8 +#define RT5682_G_STO_DA_DMIX (0xf) +#define RT5682_G_STO_DA_SFT 0 + +/* CBJ Control (0x000b) */ +#define RT5682_BST_CBJ_MASK (0xf << 8) +#define RT5682_BST_CBJ_SFT 8 + +/* Embeeded Jack and Type Detection Control 1 (0x0010) */ +#define RT5682_EMB_JD_EN (0x1 << 15) +#define RT5682_EMB_JD_EN_SFT 15 +#define RT5682_EMB_JD_RST (0x1 << 14) +#define RT5682_JD_MODE (0x1 << 13) +#define RT5682_JD_MODE_SFT 13 +#define RT5682_DET_TYPE (0x1 << 12) +#define RT5682_DET_TYPE_SFT 12 +#define RT5682_POLA_EXT_JD_MASK (0x1 << 11) +#define RT5682_POLA_EXT_JD_LOW (0x1 << 11) +#define RT5682_POLA_EXT_JD_HIGH (0x0 << 11) +#define RT5682_EXT_JD_DIG (0x1 << 9) +#define RT5682_POL_FAST_OFF_MASK (0x1 << 8) +#define RT5682_POL_FAST_OFF_HIGH (0x1 << 8) +#define RT5682_POL_FAST_OFF_LOW (0x0 << 8) +#define RT5682_FAST_OFF_MASK (0x1 << 7) +#define RT5682_FAST_OFF_EN (0x1 << 7) +#define RT5682_FAST_OFF_DIS (0x0 << 7) +#define RT5682_VREF_POW_MASK (0x1 << 6) +#define RT5682_VREF_POW_FSM (0x0 << 6) +#define RT5682_VREF_POW_REG (0x1 << 6) +#define RT5682_MB1_PATH_MASK (0x1 << 5) +#define RT5682_CTRL_MB1_REG (0x1 << 5) +#define RT5682_CTRL_MB1_FSM (0x0 << 5) +#define RT5682_MB2_PATH_MASK (0x1 << 4) +#define RT5682_CTRL_MB2_REG (0x1 << 4) +#define RT5682_CTRL_MB2_FSM (0x0 << 4) +#define RT5682_TRIG_JD_MASK (0x1 << 3) +#define RT5682_TRIG_JD_HIGH (0x1 << 3) +#define RT5682_TRIG_JD_LOW (0x0 << 3) +#define RT5682_MIC_CAP_MASK (0x1 << 1) +#define RT5682_MIC_CAP_HS (0x1 << 1) +#define RT5682_MIC_CAP_HP (0x0 << 1) +#define RT5682_MIC_CAP_SRC_MASK (0x1) +#define RT5682_MIC_CAP_SRC_REG (0x1) +#define RT5682_MIC_CAP_SRC_ANA (0x0) + +/* Embeeded Jack and Type Detection Control 2 (0x0011) */ +#define RT5682_EXT_JD_SRC (0x7 << 4) +#define RT5682_EXT_JD_SRC_SFT 4 +#define RT5682_EXT_JD_SRC_GPIO_JD1 (0x0 << 4) +#define RT5682_EXT_JD_SRC_GPIO_JD2 (0x1 << 4) +#define RT5682_EXT_JD_SRC_JDH (0x2 << 4) +#define RT5682_EXT_JD_SRC_JDL (0x3 << 4) +#define RT5682_EXT_JD_SRC_MANUAL (0x4 << 4) +#define RT5682_JACK_TYPE_MASK (0x3) + +/* Combo Jack and Type Detection Control 3 (0x0012) */ +#define RT5682_CBJ_IN_BUF_EN (0x1 << 7) + +/* Combo Jack and Type Detection Control 4 (0x0013) */ +#define RT5682_SEL_SHT_MID_TON_MASK (0x3 << 12) +#define RT5682_SEL_SHT_MID_TON_2 (0x0 << 12) +#define RT5682_SEL_SHT_MID_TON_3 (0x1 << 12) +#define RT5682_CBJ_JD_TEST_MASK (0x1 << 6) +#define RT5682_CBJ_JD_TEST_NORM (0x0 << 6) +#define RT5682_CBJ_JD_TEST_MODE (0x1 << 6) + +/* DAC1 Digital Volume (0x0019) */ +#define RT5682_DAC_L1_VOL_MASK (0xff << 8) +#define RT5682_DAC_L1_VOL_SFT 8 +#define RT5682_DAC_R1_VOL_MASK (0xff) +#define RT5682_DAC_R1_VOL_SFT 0 + +/* ADC Digital Volume Control (0x001c) */ +#define RT5682_ADC_L_VOL_MASK (0x7f << 8) +#define RT5682_ADC_L_VOL_SFT 8 +#define RT5682_ADC_R_VOL_MASK (0x7f) +#define RT5682_ADC_R_VOL_SFT 0 + +/* Stereo1 ADC Boost Gain Control (0x001f) */ +#define RT5682_STO1_ADC_L_BST_MASK (0x3 << 14) +#define RT5682_STO1_ADC_L_BST_SFT 14 +#define RT5682_STO1_ADC_R_BST_MASK (0x3 << 12) +#define RT5682_STO1_ADC_R_BST_SFT 12 + +/* Sidetone Control (0x0024) */ +#define RT5682_ST_SRC_SEL (0x1 << 8) +#define RT5682_ST_SRC_SFT 8 +#define RT5682_ST_EN_MASK (0x1 << 6) +#define RT5682_ST_DIS (0x0 << 6) +#define RT5682_ST_EN (0x1 << 6) +#define RT5682_ST_EN_SFT 6 + +/* Stereo1 ADC Mixer Control (0x0026) */ +#define RT5682_M_STO1_ADC_L1 (0x1 << 15) +#define RT5682_M_STO1_ADC_L1_SFT 15 +#define RT5682_M_STO1_ADC_L2 (0x1 << 14) +#define RT5682_M_STO1_ADC_L2_SFT 14 +#define RT5682_STO1_ADC1L_SRC_MASK (0x1 << 13) +#define RT5682_STO1_ADC1L_SRC_SFT 13 +#define RT5682_STO1_ADC1_SRC_ADC (0x1 << 13) +#define RT5682_STO1_ADC1_SRC_DACMIX (0x0 << 13) +#define RT5682_STO1_ADC2L_SRC_MASK (0x1 << 12) +#define RT5682_STO1_ADC2L_SRC_SFT 12 +#define RT5682_STO1_ADCL_SRC_MASK (0x3 << 10) +#define RT5682_STO1_ADCL_SRC_SFT 10 +#define RT5682_STO1_DD_L_SRC_MASK (0x1 << 9) +#define RT5682_STO1_DD_L_SRC_SFT 9 +#define RT5682_STO1_DMIC_SRC_MASK (0x1 << 8) +#define RT5682_STO1_DMIC_SRC_SFT 8 +#define RT5682_STO1_DMIC_SRC_DMIC2 (0x1 << 8) +#define RT5682_STO1_DMIC_SRC_DMIC1 (0x0 << 8) +#define RT5682_M_STO1_ADC_R1 (0x1 << 7) +#define RT5682_M_STO1_ADC_R1_SFT 7 +#define RT5682_M_STO1_ADC_R2 (0x1 << 6) +#define RT5682_M_STO1_ADC_R2_SFT 6 +#define RT5682_STO1_ADC1R_SRC_MASK (0x1 << 5) +#define RT5682_STO1_ADC1R_SRC_SFT 5 +#define RT5682_STO1_ADC2R_SRC_MASK (0x1 << 4) +#define RT5682_STO1_ADC2R_SRC_SFT 4 +#define RT5682_STO1_ADCR_SRC_MASK (0x3 << 2) +#define RT5682_STO1_ADCR_SRC_SFT 2 + +/* ADC Mixer to DAC Mixer Control (0x0029) */ +#define RT5682_M_ADCMIX_L (0x1 << 15) +#define RT5682_M_ADCMIX_L_SFT 15 +#define RT5682_M_DAC1_L (0x1 << 14) +#define RT5682_M_DAC1_L_SFT 14 +#define RT5682_DAC1_R_SEL_MASK (0x1 << 10) +#define RT5682_DAC1_R_SEL_SFT 10 +#define RT5682_DAC1_L_SEL_MASK (0x1 << 8) +#define RT5682_DAC1_L_SEL_SFT 8 +#define RT5682_M_ADCMIX_R (0x1 << 7) +#define RT5682_M_ADCMIX_R_SFT 7 +#define RT5682_M_DAC1_R (0x1 << 6) +#define RT5682_M_DAC1_R_SFT 6 + +/* Stereo1 DAC Mixer Control (0x002a) */ +#define RT5682_M_DAC_L1_STO_L (0x1 << 15) +#define RT5682_M_DAC_L1_STO_L_SFT 15 +#define RT5682_G_DAC_L1_STO_L_MASK (0x1 << 14) +#define RT5682_G_DAC_L1_STO_L_SFT 14 +#define RT5682_M_DAC_R1_STO_L (0x1 << 13) +#define RT5682_M_DAC_R1_STO_L_SFT 13 +#define RT5682_G_DAC_R1_STO_L_MASK (0x1 << 12) +#define RT5682_G_DAC_R1_STO_L_SFT 12 +#define RT5682_M_DAC_L1_STO_R (0x1 << 7) +#define RT5682_M_DAC_L1_STO_R_SFT 7 +#define RT5682_G_DAC_L1_STO_R_MASK (0x1 << 6) +#define RT5682_G_DAC_L1_STO_R_SFT 6 +#define RT5682_M_DAC_R1_STO_R (0x1 << 5) +#define RT5682_M_DAC_R1_STO_R_SFT 5 +#define RT5682_G_DAC_R1_STO_R_MASK (0x1 << 4) +#define RT5682_G_DAC_R1_STO_R_SFT 4 + +/* Analog DAC1 Input Source Control (0x002b) */ +#define RT5682_M_ST_STO_L (0x1 << 9) +#define RT5682_M_ST_STO_L_SFT 9 +#define RT5682_M_ST_STO_R (0x1 << 8) +#define RT5682_M_ST_STO_R_SFT 8 +#define RT5682_DAC_L1_SRC_MASK (0x3 << 4) +#define RT5682_A_DACL1_SFT 4 +#define RT5682_DAC_R1_SRC_MASK (0x3) +#define RT5682_A_DACR1_SFT 0 + +/* Digital Interface Data Control (0x0030) */ +#define RT5682_IF2_ADC_SEL_MASK (0x3 << 0) +#define RT5682_IF2_ADC_SEL_SFT 0 + +/* REC Left Mixer Control 2 (0x003c) */ +#define RT5682_G_CBJ_RM1_L (0x7 << 10) +#define RT5682_G_CBJ_RM1_L_SFT 10 +#define RT5682_M_CBJ_RM1_L (0x1 << 7) +#define RT5682_M_CBJ_RM1_L_SFT 7 + +/* Power Management for Digital 1 (0x0061) */ +#define RT5682_PWR_I2S1 (0x1 << 15) +#define RT5682_PWR_I2S1_BIT 15 +#define RT5682_PWR_I2S2 (0x1 << 14) +#define RT5682_PWR_I2S2_BIT 14 +#define RT5682_PWR_DAC_L1 (0x1 << 11) +#define RT5682_PWR_DAC_L1_BIT 11 +#define RT5682_PWR_DAC_R1 (0x1 << 10) +#define RT5682_PWR_DAC_R1_BIT 10 +#define RT5682_PWR_LDO (0x1 << 8) +#define RT5682_PWR_LDO_BIT 8 +#define RT5682_PWR_ADC_L1 (0x1 << 4) +#define RT5682_PWR_ADC_L1_BIT 4 +#define RT5682_PWR_ADC_R1 (0x1 << 3) +#define RT5682_PWR_ADC_R1_BIT 3 +#define RT5682_DIG_GATE_CTRL (0x1 << 0) +#define RT5682_DIG_GATE_CTRL_SFT 0 + + +/* Power Management for Digital 2 (0x0062) */ +#define RT5682_PWR_ADC_S1F (0x1 << 15) +#define RT5682_PWR_ADC_S1F_BIT 15 +#define RT5682_PWR_DAC_S1F (0x1 << 10) +#define RT5682_PWR_DAC_S1F_BIT 10 + +/* Power Management for Analog 1 (0x0063) */ +#define RT5682_PWR_VREF1 (0x1 << 15) +#define RT5682_PWR_VREF1_BIT 15 +#define RT5682_PWR_FV1 (0x1 << 14) +#define RT5682_PWR_FV1_BIT 14 +#define RT5682_PWR_VREF2 (0x1 << 13) +#define RT5682_PWR_VREF2_BIT 13 +#define RT5682_PWR_FV2 (0x1 << 12) +#define RT5682_PWR_FV2_BIT 12 +#define RT5682_LDO1_DBG_MASK (0x3 << 10) +#define RT5682_PWR_MB (0x1 << 9) +#define RT5682_PWR_MB_BIT 9 +#define RT5682_PWR_BG (0x1 << 7) +#define RT5682_PWR_BG_BIT 7 +#define RT5682_LDO1_BYPASS_MASK (0x1 << 6) +#define RT5682_LDO1_BYPASS (0x1 << 6) +#define RT5682_LDO1_NOT_BYPASS (0x0 << 6) +#define RT5682_PWR_MA_BIT 6 +#define RT5682_LDO1_DVO_MASK (0x3 << 4) +#define RT5682_LDO1_DVO_09 (0x0 << 4) +#define RT5682_LDO1_DVO_10 (0x1 << 4) +#define RT5682_LDO1_DVO_12 (0x2 << 4) +#define RT5682_LDO1_DVO_14 (0x3 << 4) +#define RT5682_HP_DRIVER_MASK (0x3 << 2) +#define RT5682_HP_DRIVER_1X (0x0 << 2) +#define RT5682_HP_DRIVER_3X (0x1 << 2) +#define RT5682_HP_DRIVER_5X (0x3 << 2) +#define RT5682_PWR_HA_L (0x1 << 1) +#define RT5682_PWR_HA_L_BIT 1 +#define RT5682_PWR_HA_R (0x1 << 0) +#define RT5682_PWR_HA_R_BIT 0 + +/* Power Management for Analog 2 (0x0064) */ +#define RT5682_PWR_MB1 (0x1 << 11) +#define RT5682_PWR_MB1_PWR_DOWN (0x0 << 11) +#define RT5682_PWR_MB1_BIT 11 +#define RT5682_PWR_MB2 (0x1 << 10) +#define RT5682_PWR_MB2_PWR_DOWN (0x0 << 10) +#define RT5682_PWR_MB2_BIT 10 +#define RT5682_PWR_JDH (0x1 << 3) +#define RT5682_PWR_JDH_BIT 3 +#define RT5682_PWR_JDL (0x1 << 2) +#define RT5682_PWR_JDL_BIT 2 +#define RT5682_PWR_RM1_L (0x1 << 1) +#define RT5682_PWR_RM1_L_BIT 1 + +/* Power Management for Analog 3 (0x0065) */ +#define RT5682_PWR_CBJ (0x1 << 9) +#define RT5682_PWR_CBJ_BIT 9 +#define RT5682_PWR_PLL (0x1 << 6) +#define RT5682_PWR_PLL_BIT 6 +#define RT5682_PWR_PLL2B (0x1 << 5) +#define RT5682_PWR_PLL2B_BIT 5 +#define RT5682_PWR_PLL2F (0x1 << 4) +#define RT5682_PWR_PLL2F_BIT 4 +#define RT5682_PWR_LDO2 (0x1 << 2) +#define RT5682_PWR_LDO2_BIT 2 +#define RT5682_PWR_DET_SPKVDD (0x1 << 1) +#define RT5682_PWR_DET_SPKVDD_BIT 1 + +/* Power Management for Mixer (0x0066) */ +#define RT5682_PWR_STO1_DAC_L (0x1 << 5) +#define RT5682_PWR_STO1_DAC_L_BIT 5 +#define RT5682_PWR_STO1_DAC_R (0x1 << 4) +#define RT5682_PWR_STO1_DAC_R_BIT 4 + +/* MCLK and System Clock Detection Control (0x006b) */ +#define RT5682_SYS_CLK_DET (0x1 << 15) +#define RT5682_SYS_CLK_DET_SFT 15 +#define RT5682_PLL1_CLK_DET (0x1 << 14) +#define RT5682_PLL1_CLK_DET_SFT 14 +#define RT5682_PLL2_CLK_DET (0x1 << 13) +#define RT5682_PLL2_CLK_DET_SFT 13 +#define RT5682_POW_CLK_DET2_SFT 8 +#define RT5682_POW_CLK_DET_SFT 0 + +/* Digital Microphone Control 1 (0x006e) */ +#define RT5682_DMIC_1_EN_MASK (0x1 << 15) +#define RT5682_DMIC_1_EN_SFT 15 +#define RT5682_DMIC_1_DIS (0x0 << 15) +#define RT5682_DMIC_1_EN (0x1 << 15) +#define RT5682_DMIC_1_DP_MASK (0x3 << 4) +#define RT5682_DMIC_1_DP_SFT 4 +#define RT5682_DMIC_1_DP_GPIO2 (0x0 << 4) +#define RT5682_DMIC_1_DP_GPIO5 (0x1 << 4) +#define RT5682_DMIC_CLK_MASK (0xf << 0) +#define RT5682_DMIC_CLK_SFT 0 + +/* I2S1 Audio Serial Data Port Control (0x0070) */ +#define RT5682_SEL_ADCDAT_MASK (0x1 << 15) +#define RT5682_SEL_ADCDAT_OUT (0x0 << 15) +#define RT5682_SEL_ADCDAT_IN (0x1 << 15) +#define RT5682_SEL_ADCDAT_SFT 15 +#define RT5682_I2S1_TX_CHL_MASK (0x7 << 12) +#define RT5682_I2S1_TX_CHL_SFT 12 +#define RT5682_I2S1_TX_CHL_16 (0x0 << 12) +#define RT5682_I2S1_TX_CHL_20 (0x1 << 12) +#define RT5682_I2S1_TX_CHL_24 (0x2 << 12) +#define RT5682_I2S1_TX_CHL_32 (0x3 << 12) +#define RT5682_I2S1_TX_CHL_8 (0x4 << 12) +#define RT5682_I2S1_RX_CHL_MASK (0x7 << 8) +#define RT5682_I2S1_RX_CHL_SFT 8 +#define RT5682_I2S1_RX_CHL_16 (0x0 << 8) +#define RT5682_I2S1_RX_CHL_20 (0x1 << 8) +#define RT5682_I2S1_RX_CHL_24 (0x2 << 8) +#define RT5682_I2S1_RX_CHL_32 (0x3 << 8) +#define RT5682_I2S1_RX_CHL_8 (0x4 << 8) +#define RT5682_I2S1_MONO_MASK (0x1 << 7) +#define RT5682_I2S1_MONO_EN (0x1 << 7) +#define RT5682_I2S1_MONO_DIS (0x0 << 7) +#define RT5682_I2S2_MONO_MASK (0x1 << 6) +#define RT5682_I2S2_MONO_EN (0x1 << 6) +#define RT5682_I2S2_MONO_DIS (0x0 << 6) +#define RT5682_I2S1_DL_MASK (0x7 << 4) +#define RT5682_I2S1_DL_SFT 4 +#define RT5682_I2S1_DL_16 (0x0 << 4) +#define RT5682_I2S1_DL_20 (0x1 << 4) +#define RT5682_I2S1_DL_24 (0x2 << 4) +#define RT5682_I2S1_DL_32 (0x3 << 4) +#define RT5682_I2S1_DL_8 (0x4 << 4) + +/* I2S1/2 Audio Serial Data Port Control (0x0070)(0x0071) */ +#define RT5682_I2S2_MS_MASK (0x1 << 15) +#define RT5682_I2S2_MS_SFT 15 +#define RT5682_I2S2_MS_M (0x0 << 15) +#define RT5682_I2S2_MS_S (0x1 << 15) +#define RT5682_I2S2_PIN_CFG_MASK (0x1 << 14) +#define RT5682_I2S2_PIN_CFG_SFT 14 +#define RT5682_I2S2_CLK_SEL_MASK (0x1 << 11) +#define RT5682_I2S2_CLK_SEL_SFT 11 +#define RT5682_I2S2_OUT_MASK (0x1 << 9) +#define RT5682_I2S2_OUT_SFT 9 +#define RT5682_I2S2_OUT_UM (0x0 << 9) +#define RT5682_I2S2_OUT_M (0x1 << 9) +#define RT5682_I2S_BP_MASK (0x1 << 8) +#define RT5682_I2S_BP_SFT 8 +#define RT5682_I2S_BP_NOR (0x0 << 8) +#define RT5682_I2S_BP_INV (0x1 << 8) +#define RT5682_I2S2_MONO_EN (0x1 << 6) +#define RT5682_I2S2_MONO_DIS (0x0 << 6) +#define RT5682_I2S2_DL_MASK (0x3 << 4) +#define RT5682_I2S2_DL_SFT 4 +#define RT5682_I2S2_DL_16 (0x0 << 4) +#define RT5682_I2S2_DL_20 (0x1 << 4) +#define RT5682_I2S2_DL_24 (0x2 << 4) +#define RT5682_I2S2_DL_8 (0x3 << 4) +#define RT5682_I2S_DF_MASK (0x7) +#define RT5682_I2S_DF_SFT 0 +#define RT5682_I2S_DF_I2S (0x0) +#define RT5682_I2S_DF_LEFT (0x1) +#define RT5682_I2S_DF_PCM_A (0x2) +#define RT5682_I2S_DF_PCM_B (0x3) +#define RT5682_I2S_DF_PCM_A_N (0x6) +#define RT5682_I2S_DF_PCM_B_N (0x7) + +/* ADC/DAC Clock Control 1 (0x0073) */ +#define RT5682_ADC_OSR_MASK (0xf << 12) +#define RT5682_ADC_OSR_SFT 12 +#define RT5682_ADC_OSR_D_1 (0x0 << 12) +#define RT5682_ADC_OSR_D_2 (0x1 << 12) +#define RT5682_ADC_OSR_D_4 (0x2 << 12) +#define RT5682_ADC_OSR_D_6 (0x3 << 12) +#define RT5682_ADC_OSR_D_8 (0x4 << 12) +#define RT5682_ADC_OSR_D_12 (0x5 << 12) +#define RT5682_ADC_OSR_D_16 (0x6 << 12) +#define RT5682_ADC_OSR_D_24 (0x7 << 12) +#define RT5682_ADC_OSR_D_32 (0x8 << 12) +#define RT5682_ADC_OSR_D_48 (0x9 << 12) +#define RT5682_I2S_M_DIV_MASK (0xf << 12) +#define RT5682_I2S_M_DIV_SFT 8 +#define RT5682_I2S_M_D_1 (0x0 << 8) +#define RT5682_I2S_M_D_2 (0x1 << 8) +#define RT5682_I2S_M_D_3 (0x2 << 8) +#define RT5682_I2S_M_D_4 (0x3 << 8) +#define RT5682_I2S_M_D_6 (0x4 << 8) +#define RT5682_I2S_M_D_8 (0x5 << 8) +#define RT5682_I2S_M_D_12 (0x6 << 8) +#define RT5682_I2S_M_D_16 (0x7 << 8) +#define RT5682_I2S_M_D_24 (0x8 << 8) +#define RT5682_I2S_M_D_32 (0x9 << 8) +#define RT5682_I2S_M_D_48 (0x10 << 8) +#define RT5682_I2S_CLK_SRC_MASK (0x7 << 4) +#define RT5682_I2S_CLK_SRC_SFT 4 +#define RT5682_I2S_CLK_SRC_MCLK (0x0 << 4) +#define RT5682_I2S_CLK_SRC_PLL1 (0x1 << 4) +#define RT5682_I2S_CLK_SRC_PLL2 (0x2 << 4) +#define RT5682_I2S_CLK_SRC_SDW (0x3 << 4) +#define RT5682_I2S_CLK_SRC_RCCLK (0x4 << 4) /* 25M */ +#define RT5682_DAC_OSR_MASK (0xf << 0) +#define RT5682_DAC_OSR_SFT 0 +#define RT5682_DAC_OSR_D_1 (0x0 << 0) +#define RT5682_DAC_OSR_D_2 (0x1 << 0) +#define RT5682_DAC_OSR_D_4 (0x2 << 0) +#define RT5682_DAC_OSR_D_6 (0x3 << 0) +#define RT5682_DAC_OSR_D_8 (0x4 << 0) +#define RT5682_DAC_OSR_D_12 (0x5 << 0) +#define RT5682_DAC_OSR_D_16 (0x6 << 0) +#define RT5682_DAC_OSR_D_24 (0x7 << 0) +#define RT5682_DAC_OSR_D_32 (0x8 << 0) +#define RT5682_DAC_OSR_D_48 (0x9 << 0) + +/* ADC/DAC Clock Control 2 (0x0074) */ +#define RT5682_I2S2_BCLK_MS2_MASK (0x1 << 11) +#define RT5682_I2S2_BCLK_MS2_SFT 11 +#define RT5682_I2S2_BCLK_MS2_32 (0x0 << 11) +#define RT5682_I2S2_BCLK_MS2_64 (0x1 << 11) + + +/* TDM control 1 (0x0079) */ +#define RT5682_TDM_TX_CH_MASK (0x3 << 12) +#define RT5682_TDM_TX_CH_2 (0x0 << 12) +#define RT5682_TDM_TX_CH_4 (0x1 << 12) +#define RT5682_TDM_TX_CH_6 (0x2 << 12) +#define RT5682_TDM_TX_CH_8 (0x3 << 12) +#define RT5682_TDM_RX_CH_MASK (0x3 << 8) +#define RT5682_TDM_RX_CH_2 (0x0 << 8) +#define RT5682_TDM_RX_CH_4 (0x1 << 8) +#define RT5682_TDM_RX_CH_6 (0x2 << 8) +#define RT5682_TDM_RX_CH_8 (0x3 << 8) +#define RT5682_TDM_ADC_LCA_MASK (0xf << 4) +#define RT5682_TDM_ADC_LCA_SFT 4 +#define RT5682_TDM_ADC_DL_SFT 0 + +/* TDM control 2 (0x007a) */ +#define RT5682_IF1_ADC1_SEL_SFT 14 +#define RT5682_IF1_ADC2_SEL_SFT 12 +#define RT5682_IF1_ADC3_SEL_SFT 10 +#define RT5682_IF1_ADC4_SEL_SFT 8 +#define RT5682_TDM_ADC_SEL_SFT 4 + +/* TDM control 3 (0x007b) */ +#define RT5682_TDM_EN (0x1 << 7) + +/* TDM/I2S control (0x007e) */ +#define RT5682_TDM_S_BP_MASK (0x1 << 15) +#define RT5682_TDM_S_BP_SFT 15 +#define RT5682_TDM_S_BP_NOR (0x0 << 15) +#define RT5682_TDM_S_BP_INV (0x1 << 15) +#define RT5682_TDM_S_LP_MASK (0x1 << 14) +#define RT5682_TDM_S_LP_SFT 14 +#define RT5682_TDM_S_LP_NOR (0x0 << 14) +#define RT5682_TDM_S_LP_INV (0x1 << 14) +#define RT5682_TDM_DF_MASK (0x7 << 11) +#define RT5682_TDM_DF_SFT 11 +#define RT5682_TDM_DF_I2S (0x0 << 11) +#define RT5682_TDM_DF_LEFT (0x1 << 11) +#define RT5682_TDM_DF_PCM_A (0x2 << 11) +#define RT5682_TDM_DF_PCM_B (0x3 << 11) +#define RT5682_TDM_DF_PCM_A_N (0x6 << 11) +#define RT5682_TDM_DF_PCM_B_N (0x7 << 11) +#define RT5682_TDM_CL_MASK (0x3 << 4) +#define RT5682_TDM_CL_16 (0x0 << 4) +#define RT5682_TDM_CL_20 (0x1 << 4) +#define RT5682_TDM_CL_24 (0x2 << 4) +#define RT5682_TDM_CL_32 (0x3 << 4) +#define RT5682_TDM_M_BP_MASK (0x1 << 2) +#define RT5682_TDM_M_BP_SFT 2 +#define RT5682_TDM_M_BP_NOR (0x0 << 2) +#define RT5682_TDM_M_BP_INV (0x1 << 2) +#define RT5682_TDM_M_LP_MASK (0x1 << 1) +#define RT5682_TDM_M_LP_SFT 1 +#define RT5682_TDM_M_LP_NOR (0x0 << 1) +#define RT5682_TDM_M_LP_INV (0x1 << 1) +#define RT5682_TDM_MS_MASK (0x1 << 0) +#define RT5682_TDM_MS_SFT 0 +#define RT5682_TDM_MS_M (0x0 << 0) +#define RT5682_TDM_MS_S (0x1 << 0) + +/* Global Clock Control (0x0080) */ +#define RT5682_SCLK_SRC_MASK (0x7 << 13) +#define RT5682_SCLK_SRC_SFT 13 +#define RT5682_SCLK_SRC_MCLK (0x0 << 13) +#define RT5682_SCLK_SRC_PLL1 (0x1 << 13) +#define RT5682_SCLK_SRC_PLL2 (0x2 << 13) +#define RT5682_SCLK_SRC_SDW (0x3 << 13) +#define RT5682_SCLK_SRC_RCCLK (0x4 << 13) +#define RT5682_PLL1_SRC_MASK (0x3 << 10) +#define RT5682_PLL1_SRC_SFT 10 +#define RT5682_PLL1_SRC_MCLK (0x0 << 10) +#define RT5682_PLL1_SRC_BCLK1 (0x1 << 10) +#define RT5682_PLL1_SRC_SDW (0x2 << 10) +#define RT5682_PLL1_SRC_RC (0x3 << 10) +#define RT5682_PLL2_SRC_MASK (0x3 << 8) +#define RT5682_PLL2_SRC_SFT 8 +#define RT5682_PLL2_SRC_MCLK (0x0 << 8) +#define RT5682_PLL2_SRC_BCLK1 (0x1 << 8) +#define RT5682_PLL2_SRC_SDW (0x2 << 8) +#define RT5682_PLL2_SRC_RC (0x3 << 8) + + + +#define RT5682_PLL_INP_MAX 40000000 +#define RT5682_PLL_INP_MIN 256000 +/* PLL M/N/K Code Control 1 (0x0081) */ +#define RT5682_PLL_N_MAX 0x001ff +#define RT5682_PLL_N_MASK (RT5682_PLL_N_MAX << 7) +#define RT5682_PLL_N_SFT 7 +#define RT5682_PLL_K_MAX 0x001f +#define RT5682_PLL_K_MASK (RT5682_PLL_K_MAX) +#define RT5682_PLL_K_SFT 0 + +/* PLL M/N/K Code Control 2 (0x0082) */ +#define RT5682_PLL_M_MAX 0x00f +#define RT5682_PLL_M_MASK (RT5682_PLL_M_MAX << 12) +#define RT5682_PLL_M_SFT 12 +#define RT5682_PLL_M_BP (0x1 << 11) +#define RT5682_PLL_M_BP_SFT 11 +#define RT5682_PLL_K_BP (0x1 << 10) +#define RT5682_PLL_K_BP_SFT 10 +#define RT5682_PLL_RST (0x1 << 1) + +/* PLL tracking mode 1 (0x0083) */ +#define RT5682_DA_ASRC_MASK (0x1 << 13) +#define RT5682_DA_ASRC_SFT 13 +#define RT5682_DAC_STO1_ASRC_MASK (0x1 << 12) +#define RT5682_DAC_STO1_ASRC_SFT 12 +#define RT5682_AD_ASRC_MASK (0x1 << 8) +#define RT5682_AD_ASRC_SFT 8 +#define RT5682_AD_ASRC_SEL_MASK (0x1 << 4) +#define RT5682_AD_ASRC_SEL_SFT 4 +#define RT5682_DMIC_ASRC_MASK (0x1 << 3) +#define RT5682_DMIC_ASRC_SFT 3 +#define RT5682_ADC_STO1_ASRC_MASK (0x1 << 2) +#define RT5682_ADC_STO1_ASRC_SFT 2 +#define RT5682_DA_ASRC_SEL_MASK (0x1 << 0) +#define RT5682_DA_ASRC_SEL_SFT 0 + +/* PLL tracking mode 2 3 (0x0084)(0x0085)*/ +#define RT5682_FILTER_CLK_SEL_MASK (0x7 << 12) +#define RT5682_FILTER_CLK_SEL_SFT 12 +#define RT5682_FILTER_CLK_DIV_MASK (0xf << 8) +#define RT5682_FILTER_CLK_DIV_SFT 8 + +/* ASRC Control 4 (0x0086) */ +#define RT5682_ASRCIN_FTK_N1_MASK (0x3 << 14) +#define RT5682_ASRCIN_FTK_N1_SFT 14 +#define RT5682_ASRCIN_FTK_N2_MASK (0x3 << 12) +#define RT5682_ASRCIN_FTK_N2_SFT 12 +#define RT5682_ASRCIN_FTK_M1_MASK (0x7 << 8) +#define RT5682_ASRCIN_FTK_M1_SFT 8 +#define RT5682_ASRCIN_FTK_M2_MASK (0x7 << 4) +#define RT5682_ASRCIN_FTK_M2_SFT 4 + +/* SoundWire reference clk (0x008d) */ +#define RT5682_PLL2_OUT_MASK (0x1 << 8) +#define RT5682_PLL2_OUT_98M (0x0 << 8) +#define RT5682_PLL2_OUT_49M (0x1 << 8) +#define RT5682_SDW_REF_2_MASK (0xf << 4) +#define RT5682_SDW_REF_2_SFT 4 +#define RT5682_SDW_REF_2_48K (0x0 << 4) +#define RT5682_SDW_REF_2_96K (0x1 << 4) +#define RT5682_SDW_REF_2_192K (0x2 << 4) +#define RT5682_SDW_REF_2_32K (0x3 << 4) +#define RT5682_SDW_REF_2_24K (0x4 << 4) +#define RT5682_SDW_REF_2_16K (0x5 << 4) +#define RT5682_SDW_REF_2_12K (0x6 << 4) +#define RT5682_SDW_REF_2_8K (0x7 << 4) +#define RT5682_SDW_REF_2_44K (0x8 << 4) +#define RT5682_SDW_REF_2_88K (0x9 << 4) +#define RT5682_SDW_REF_2_176K (0xa << 4) +#define RT5682_SDW_REF_2_353K (0xb << 4) +#define RT5682_SDW_REF_2_22K (0xc << 4) +#define RT5682_SDW_REF_2_384K (0xd << 4) +#define RT5682_SDW_REF_2_11K (0xe << 4) +#define RT5682_SDW_REF_1_MASK (0xf << 0) +#define RT5682_SDW_REF_1_SFT 0 +#define RT5682_SDW_REF_1_48K (0x0 << 0) +#define RT5682_SDW_REF_1_96K (0x1 << 0) +#define RT5682_SDW_REF_1_192K (0x2 << 0) +#define RT5682_SDW_REF_1_32K (0x3 << 0) +#define RT5682_SDW_REF_1_24K (0x4 << 0) +#define RT5682_SDW_REF_1_16K (0x5 << 0) +#define RT5682_SDW_REF_1_12K (0x6 << 0) +#define RT5682_SDW_REF_1_8K (0x7 << 0) +#define RT5682_SDW_REF_1_44K (0x8 << 0) +#define RT5682_SDW_REF_1_88K (0x9 << 0) +#define RT5682_SDW_REF_1_176K (0xa << 0) +#define RT5682_SDW_REF_1_353K (0xb << 0) +#define RT5682_SDW_REF_1_22K (0xc << 0) +#define RT5682_SDW_REF_1_384K (0xd << 0) +#define RT5682_SDW_REF_1_11K (0xe << 0) + +/* Depop Mode Control 1 (0x008e) */ +#define RT5682_PUMP_EN (0x1 << 3) +#define RT5682_PUMP_EN_SFT 3 +#define RT5682_CAPLESS_EN (0x1 << 0) +#define RT5682_CAPLESS_EN_SFT 0 + +/* Depop Mode Control 2 (0x8f) */ +#define RT5682_RAMP_MASK (0x1 << 12) +#define RT5682_RAMP_SFT 12 +#define RT5682_RAMP_DIS (0x0 << 12) +#define RT5682_RAMP_EN (0x1 << 12) +#define RT5682_BPS_MASK (0x1 << 11) +#define RT5682_BPS_SFT 11 +#define RT5682_BPS_DIS (0x0 << 11) +#define RT5682_BPS_EN (0x1 << 11) +#define RT5682_FAST_UPDN_MASK (0x1 << 10) +#define RT5682_FAST_UPDN_SFT 10 +#define RT5682_FAST_UPDN_DIS (0x0 << 10) +#define RT5682_FAST_UPDN_EN (0x1 << 10) +#define RT5682_VLO_MASK (0x1 << 7) +#define RT5682_VLO_SFT 7 +#define RT5682_VLO_3V (0x0 << 7) +#define RT5682_VLO_33V (0x1 << 7) + +/* HPOUT charge pump 1 (0x0091) */ +#define RT5682_OSW_L_MASK (0x1 << 11) +#define RT5682_OSW_L_SFT 11 +#define RT5682_OSW_L_DIS (0x0 << 11) +#define RT5682_OSW_L_EN (0x1 << 11) +#define RT5682_OSW_R_MASK (0x1 << 10) +#define RT5682_OSW_R_SFT 10 +#define RT5682_OSW_R_DIS (0x0 << 10) +#define RT5682_OSW_R_EN (0x1 << 10) +#define RT5682_PM_HP_MASK (0x3 << 8) +#define RT5682_PM_HP_SFT 8 +#define RT5682_PM_HP_LV (0x0 << 8) +#define RT5682_PM_HP_MV (0x1 << 8) +#define RT5682_PM_HP_HV (0x2 << 8) +#define RT5682_IB_HP_MASK (0x3 << 6) +#define RT5682_IB_HP_SFT 6 +#define RT5682_IB_HP_125IL (0x0 << 6) +#define RT5682_IB_HP_25IL (0x1 << 6) +#define RT5682_IB_HP_5IL (0x2 << 6) +#define RT5682_IB_HP_1IL (0x3 << 6) + +/* Micbias Control1 (0x93) */ +#define RT5682_MIC1_OV_MASK (0x3 << 14) +#define RT5682_MIC1_OV_SFT 14 +#define RT5682_MIC1_OV_2V7 (0x0 << 14) +#define RT5682_MIC1_OV_2V4 (0x1 << 14) +#define RT5682_MIC1_OV_2V25 (0x3 << 14) +#define RT5682_MIC1_OV_1V8 (0x4 << 14) +#define RT5682_MIC1_CLK_MASK (0x1 << 13) +#define RT5682_MIC1_CLK_SFT 13 +#define RT5682_MIC1_CLK_DIS (0x0 << 13) +#define RT5682_MIC1_CLK_EN (0x1 << 13) +#define RT5682_MIC1_OVCD_MASK (0x1 << 12) +#define RT5682_MIC1_OVCD_SFT 12 +#define RT5682_MIC1_OVCD_DIS (0x0 << 12) +#define RT5682_MIC1_OVCD_EN (0x1 << 12) +#define RT5682_MIC1_OVTH_MASK (0x3 << 10) +#define RT5682_MIC1_OVTH_SFT 10 +#define RT5682_MIC1_OVTH_768UA (0x0 << 10) +#define RT5682_MIC1_OVTH_960UA (0x1 << 10) +#define RT5682_MIC1_OVTH_1152UA (0x2 << 10) +#define RT5682_MIC1_OVTH_1960UA (0x3 << 10) +#define RT5682_MIC2_OV_MASK (0x3 << 8) +#define RT5682_MIC2_OV_SFT 8 +#define RT5682_MIC2_OV_2V7 (0x0 << 8) +#define RT5682_MIC2_OV_2V4 (0x1 << 8) +#define RT5682_MIC2_OV_2V25 (0x3 << 8) +#define RT5682_MIC2_OV_1V8 (0x4 << 8) +#define RT5682_MIC2_CLK_MASK (0x1 << 7) +#define RT5682_MIC2_CLK_SFT 7 +#define RT5682_MIC2_CLK_DIS (0x0 << 7) +#define RT5682_MIC2_CLK_EN (0x1 << 7) +#define RT5682_MIC2_OVTH_MASK (0x3 << 4) +#define RT5682_MIC2_OVTH_SFT 4 +#define RT5682_MIC2_OVTH_768UA (0x0 << 4) +#define RT5682_MIC2_OVTH_960UA (0x1 << 4) +#define RT5682_MIC2_OVTH_1152UA (0x2 << 4) +#define RT5682_MIC2_OVTH_1960UA (0x3 << 4) +#define RT5682_PWR_MB_MASK (0x1 << 3) +#define RT5682_PWR_MB_SFT 3 +#define RT5682_PWR_MB_PD (0x0 << 3) +#define RT5682_PWR_MB_PU (0x1 << 3) + +/* Micbias Control2 (0x0094) */ +#define RT5682_PWR_CLK25M_MASK (0x1 << 9) +#define RT5682_PWR_CLK25M_SFT 9 +#define RT5682_PWR_CLK25M_PD (0x0 << 9) +#define RT5682_PWR_CLK25M_PU (0x1 << 9) +#define RT5682_PWR_CLK1M_MASK (0x1 << 8) +#define RT5682_PWR_CLK1M_SFT 8 +#define RT5682_PWR_CLK1M_PD (0x0 << 8) +#define RT5682_PWR_CLK1M_PU (0x1 << 8) + +/* RC Clock Control (0x009f) */ +#define RT5682_POW_IRQ (0x1 << 15) +#define RT5682_POW_JDH (0x1 << 14) +#define RT5682_POW_JDL (0x1 << 13) +#define RT5682_POW_ANA (0x1 << 12) + +/* I2S Master Mode Clock Control 1 (0x00a0) */ +#define RT5682_CLK_SRC_MCLK (0x0) +#define RT5682_CLK_SRC_PLL1 (0x1) +#define RT5682_CLK_SRC_PLL2 (0x2) +#define RT5682_CLK_SRC_SDW (0x3) +#define RT5682_CLK_SRC_RCCLK (0x4) +#define RT5682_I2S_PD_1 (0x0) +#define RT5682_I2S_PD_2 (0x1) +#define RT5682_I2S_PD_3 (0x2) +#define RT5682_I2S_PD_4 (0x3) +#define RT5682_I2S_PD_6 (0x4) +#define RT5682_I2S_PD_8 (0x5) +#define RT5682_I2S_PD_12 (0x6) +#define RT5682_I2S_PD_16 (0x7) +#define RT5682_I2S_PD_24 (0x8) +#define RT5682_I2S_PD_32 (0x9) +#define RT5682_I2S_PD_48 (0xa) +#define RT5682_I2S2_SRC_MASK (0x3 << 4) +#define RT5682_I2S2_SRC_SFT 4 +#define RT5682_I2S2_M_PD_MASK (0xf << 0) +#define RT5682_I2S2_M_PD_SFT 0 + +/* IRQ Control 1 (0x00b6) */ +#define RT5682_JD1_PULSE_EN_MASK (0x1 << 10) +#define RT5682_JD1_PULSE_EN_SFT 10 +#define RT5682_JD1_PULSE_DIS (0x0 << 10) +#define RT5682_JD1_PULSE_EN (0x1 << 10) + +/* IRQ Control 2 (0x00b7) */ +#define RT5682_JD1_EN_MASK (0x1 << 15) +#define RT5682_JD1_EN_SFT 15 +#define RT5682_JD1_DIS (0x0 << 15) +#define RT5682_JD1_EN (0x1 << 15) +#define RT5682_JD1_POL_MASK (0x1 << 13) +#define RT5682_JD1_POL_NOR (0x0 << 13) +#define RT5682_JD1_POL_INV (0x1 << 13) + +/* IRQ Control 3 (0x00b8) */ +#define RT5682_IL_IRQ_MASK (0x1 << 7) +#define RT5682_IL_IRQ_DIS (0x0 << 7) +#define RT5682_IL_IRQ_EN (0x1 << 7) + +/* GPIO Control 1 (0x00c0) */ +#define RT5682_GP1_PIN_MASK (0x3 << 14) +#define RT5682_GP1_PIN_SFT 14 +#define RT5682_GP1_PIN_GPIO1 (0x0 << 14) +#define RT5682_GP1_PIN_IRQ (0x1 << 14) +#define RT5682_GP1_PIN_DMIC_CLK (0x2 << 14) +#define RT5682_GP2_PIN_MASK (0x3 << 12) +#define RT5682_GP2_PIN_SFT 12 +#define RT5682_GP2_PIN_GPIO2 (0x0 << 12) +#define RT5682_GP2_PIN_LRCK2 (0x1 << 12) +#define RT5682_GP2_PIN_DMIC_SDA (0x2 << 12) +#define RT5682_GP3_PIN_MASK (0x3 << 10) +#define RT5682_GP3_PIN_SFT 10 +#define RT5682_GP3_PIN_GPIO3 (0x0 << 10) +#define RT5682_GP3_PIN_BCLK2 (0x1 << 10) +#define RT5682_GP3_PIN_DMIC_CLK (0x2 << 10) +#define RT5682_GP4_PIN_MASK (0x3 << 8) +#define RT5682_GP4_PIN_SFT 8 +#define RT5682_GP4_PIN_GPIO4 (0x0 << 8) +#define RT5682_GP4_PIN_ADCDAT1 (0x1 << 8) +#define RT5682_GP4_PIN_DMIC_CLK (0x2 << 8) +#define RT5682_GP4_PIN_ADCDAT2 (0x3 << 8) +#define RT5682_GP5_PIN_MASK (0x3 << 6) +#define RT5682_GP5_PIN_SFT 6 +#define RT5682_GP5_PIN_GPIO5 (0x0 << 6) +#define RT5682_GP5_PIN_DACDAT1 (0x1 << 6) +#define RT5682_GP5_PIN_DMIC_SDA (0x2 << 6) +#define RT5682_GP6_PIN_MASK (0x1 << 5) +#define RT5682_GP6_PIN_SFT 5 +#define RT5682_GP6_PIN_GPIO6 (0x0 << 5) +#define RT5682_GP6_PIN_LRCK1 (0x1 << 5) + +/* GPIO Control 2 (0x00c1)*/ +#define RT5682_GP1_PF_MASK (0x1 << 15) +#define RT5682_GP1_PF_IN (0x0 << 15) +#define RT5682_GP1_PF_OUT (0x1 << 15) +#define RT5682_GP1_OUT_MASK (0x1 << 14) +#define RT5682_GP1_OUT_L (0x0 << 14) +#define RT5682_GP1_OUT_H (0x1 << 14) +#define RT5682_GP2_PF_MASK (0x1 << 13) +#define RT5682_GP2_PF_IN (0x0 << 13) +#define RT5682_GP2_PF_OUT (0x1 << 13) +#define RT5682_GP2_OUT_MASK (0x1 << 12) +#define RT5682_GP2_OUT_L (0x0 << 12) +#define RT5682_GP2_OUT_H (0x1 << 12) +#define RT5682_GP3_PF_MASK (0x1 << 11) +#define RT5682_GP3_PF_IN (0x0 << 11) +#define RT5682_GP3_PF_OUT (0x1 << 11) +#define RT5682_GP3_OUT_MASK (0x1 << 10) +#define RT5682_GP3_OUT_L (0x0 << 10) +#define RT5682_GP3_OUT_H (0x1 << 10) +#define RT5682_GP4_PF_MASK (0x1 << 9) +#define RT5682_GP4_PF_IN (0x0 << 9) +#define RT5682_GP4_PF_OUT (0x1 << 9) +#define RT5682_GP4_OUT_MASK (0x1 << 8) +#define RT5682_GP4_OUT_L (0x0 << 8) +#define RT5682_GP4_OUT_H (0x1 << 8) +#define RT5682_GP5_PF_MASK (0x1 << 7) +#define RT5682_GP5_PF_IN (0x0 << 7) +#define RT5682_GP5_PF_OUT (0x1 << 7) +#define RT5682_GP5_OUT_MASK (0x1 << 6) +#define RT5682_GP5_OUT_L (0x0 << 6) +#define RT5682_GP5_OUT_H (0x1 << 6) +#define RT5682_GP6_PF_MASK (0x1 << 5) +#define RT5682_GP6_PF_IN (0x0 << 5) +#define RT5682_GP6_PF_OUT (0x1 << 5) +#define RT5682_GP6_OUT_MASK (0x1 << 4) +#define RT5682_GP6_OUT_L (0x0 << 4) +#define RT5682_GP6_OUT_H (0x1 << 4) + + +/* GPIO Status (0x00c2) */ +#define RT5682_GP6_STA (0x1 << 6) +#define RT5682_GP5_STA (0x1 << 5) +#define RT5682_GP4_STA (0x1 << 4) +#define RT5682_GP3_STA (0x1 << 3) +#define RT5682_GP2_STA (0x1 << 2) +#define RT5682_GP1_STA (0x1 << 1) + +/* Soft volume and zero cross control 1 (0x00d9) */ +#define RT5682_SV_MASK (0x1 << 15) +#define RT5682_SV_SFT 15 +#define RT5682_SV_DIS (0x0 << 15) +#define RT5682_SV_EN (0x1 << 15) +#define RT5682_ZCD_MASK (0x1 << 10) +#define RT5682_ZCD_SFT 10 +#define RT5682_ZCD_PD (0x0 << 10) +#define RT5682_ZCD_PU (0x1 << 10) +#define RT5682_SV_DLY_MASK (0xf) +#define RT5682_SV_DLY_SFT 0 + +/* Soft volume and zero cross control 2 (0x00da) */ +#define RT5682_ZCD_BST1_CBJ_MASK (0x1 << 7) +#define RT5682_ZCD_BST1_CBJ_SFT 7 +#define RT5682_ZCD_BST1_CBJ_DIS (0x0 << 7) +#define RT5682_ZCD_BST1_CBJ_EN (0x1 << 7) +#define RT5682_ZCD_RECMIX_MASK (0x1) +#define RT5682_ZCD_RECMIX_SFT 0 +#define RT5682_ZCD_RECMIX_DIS (0x0) +#define RT5682_ZCD_RECMIX_EN (0x1) + +/* 4 Button Inline Command Control 2 (0x00e3) */ +#define RT5682_4BTN_IL_MASK (0x1 << 15) +#define RT5682_4BTN_IL_EN (0x1 << 15) +#define RT5682_4BTN_IL_DIS (0x0 << 15) +#define RT5682_4BTN_IL_RST_MASK (0x1 << 14) +#define RT5682_4BTN_IL_NOR (0x1 << 14) +#define RT5682_4BTN_IL_RST (0x0 << 14) + +/* Analog JD Control (0x00f0) */ +#define RT5682_JDH_RS_MASK (0x1 << 4) +#define RT5682_JDH_NO_PLUG (0x1 << 4) +#define RT5682_JDH_PLUG (0x0 << 4) + +/* Chopper and Clock control for DAC (0x013a)*/ +#define RT5682_CKXEN_DAC1_MASK (0x1 << 13) +#define RT5682_CKXEN_DAC1_SFT 13 +#define RT5682_CKGEN_DAC1_MASK (0x1 << 12) +#define RT5682_CKGEN_DAC1_SFT 12 + +/* Chopper and Clock control for ADC (0x013b)*/ +#define RT5682_CKXEN_ADC1_MASK (0x1 << 13) +#define RT5682_CKXEN_ADC1_SFT 13 +#define RT5682_CKGEN_ADC1_MASK (0x1 << 12) +#define RT5682_CKGEN_ADC1_SFT 12 + +/* Volume test (0x013f)*/ +#define RT5682_SEL_CLK_VOL_MASK (0x1 << 15) +#define RT5682_SEL_CLK_VOL_EN (0x1 << 15) +#define RT5682_SEL_CLK_VOL_DIS (0x0 << 15) + +/* Test Mode Control 1 (0x0145) */ +#define RT5682_AD2DA_LB_MASK (0x1 << 10) +#define RT5682_AD2DA_LB_SFT 10 + +/* Stereo Noise Gate Control 1 (0x0160) */ +#define RT5682_NG2_EN_MASK (0x1 << 15) +#define RT5682_NG2_EN (0x1 << 15) +#define RT5682_NG2_DIS (0x0 << 15) + +/* Stereo1 DAC Silence Detection Control (0x0190) */ +#define RT5682_DEB_STO_DAC_MASK (0x7 << 4) +#define RT5682_DEB_80_MS (0x0 << 4) + +/* SAR ADC Inline Command Control 1 (0x0210) */ +#define RT5682_SAR_BUTT_DET_MASK (0x1 << 15) +#define RT5682_SAR_BUTT_DET_EN (0x1 << 15) +#define RT5682_SAR_BUTT_DET_DIS (0x0 << 15) +#define RT5682_SAR_BUTDET_MODE_MASK (0x1 << 14) +#define RT5682_SAR_BUTDET_POW_SAV (0x1 << 14) +#define RT5682_SAR_BUTDET_POW_NORM (0x0 << 14) +#define RT5682_SAR_BUTDET_RST_MASK (0x1 << 13) +#define RT5682_SAR_BUTDET_RST_NORMAL (0x1 << 13) +#define RT5682_SAR_BUTDET_RST (0x0 << 13) +#define RT5682_SAR_POW_MASK (0x1 << 12) +#define RT5682_SAR_POW_EN (0x1 << 12) +#define RT5682_SAR_POW_DIS (0x0 << 12) +#define RT5682_SAR_RST_MASK (0x1 << 11) +#define RT5682_SAR_RST_NORMAL (0x1 << 11) +#define RT5682_SAR_RST (0x0 << 11) +#define RT5682_SAR_BYPASS_MASK (0x1 << 10) +#define RT5682_SAR_BYPASS_EN (0x1 << 10) +#define RT5682_SAR_BYPASS_DIS (0x0 << 10) +#define RT5682_SAR_SEL_MB1_MASK (0x1 << 9) +#define RT5682_SAR_SEL_MB1_SEL (0x1 << 9) +#define RT5682_SAR_SEL_MB1_NOSEL (0x0 << 9) +#define RT5682_SAR_SEL_MB2_MASK (0x1 << 8) +#define RT5682_SAR_SEL_MB2_SEL (0x1 << 8) +#define RT5682_SAR_SEL_MB2_NOSEL (0x0 << 8) +#define RT5682_SAR_SEL_MODE_MASK (0x1 << 7) +#define RT5682_SAR_SEL_MODE_CMP (0x1 << 7) +#define RT5682_SAR_SEL_MODE_ADC (0x0 << 7) +#define RT5682_SAR_SEL_MB1_MB2_MASK (0x1 << 5) +#define RT5682_SAR_SEL_MB1_MB2_AUTO (0x1 << 5) +#define RT5682_SAR_SEL_MB1_MB2_MANU (0x0 << 5) +#define RT5682_SAR_SEL_SIGNAL_MASK (0x1 << 4) +#define RT5682_SAR_SEL_SIGNAL_AUTO (0x1 << 4) +#define RT5682_SAR_SEL_SIGNAL_MANU (0x0 << 4) + +/* SAR ADC Inline Command Control 13 (0x021c) */ +#define RT5682_SAR_SOUR_MASK (0x3f) +#define RT5682_SAR_SOUR_BTN (0x3f) +#define RT5682_SAR_SOUR_TYPE (0x0) + + +/* System Clock Source */ +enum { + RT5682_SCLK_S_MCLK, + RT5682_SCLK_S_PLL1, + RT5682_SCLK_S_PLL2, + RT5682_SCLK_S_RCCLK, +}; + +/* PLL Source */ +enum { + RT5682_PLL1_S_MCLK, + RT5682_PLL1_S_BCLK1, + RT5682_PLL1_S_RCCLK, +}; + +enum { + RT5682_AIF1, + RT5682_AIF2, + RT5682_AIFS +}; + +/* filter mask */ +enum { + RT5682_DA_STEREO1_FILTER = 0x1, + RT5682_AD_STEREO1_FILTER = (0x1 << 1), +}; + +enum { + RT5682_CLK_SEL_SYS, + RT5682_CLK_SEL_I2S1_ASRC, + RT5682_CLK_SEL_I2S2_ASRC, +}; + +int rt5682_sel_asrc_clk_src(struct snd_soc_component *component, + unsigned int filter_mask, unsigned int clk_src); + +#endif /* __RT5682_H__ */ -- cgit v1.2.3 From a7dc662c6a7b9209df600c64b16d33d72dbf56b1 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Sun, 17 Jun 2018 15:45:29 +0200 Subject: ASoC: codecs: PCM1789: unconditionally flush work Work is guaranteed to be initialized on exit. Drop the unnecessary if statement and always call flush_work. This fixes a warning seen with clang: sound/soc/codecs/pcm1789.c:265:13: warning: address of 'priv->work' will always evaluate to 'true' [-Wpointer-bool-conversion] if (&priv->work) ~~ ~~~~~~^~~~ Signed-off-by: Stefan Agner Signed-off-by: Mark Brown --- sound/soc/codecs/pcm1789.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/pcm1789.c b/sound/soc/codecs/pcm1789.c index 21f15219b3ad..8df6447c76a6 100644 --- a/sound/soc/codecs/pcm1789.c +++ b/sound/soc/codecs/pcm1789.c @@ -262,8 +262,7 @@ int pcm1789_common_exit(struct device *dev) { struct pcm1789_private *priv = dev_get_drvdata(dev); - if (&priv->work) - flush_work(&priv->work); + flush_work(&priv->work); return 0; } -- cgit v1.2.3 From 7f7cca08abf4c6c58ff1037cff5beec5a10a7da3 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 20 Jun 2018 11:56:21 +0100 Subject: ASoC: wm_adsp: Simplify handling of alg offset and length The current code that reads the algorithm list from the DSP is somewhat unclear, it converts directly from bytes to registers using a hard coded divide by 2. Most offsets are usually handled in DSP words within the driver and there is a function specifically for converting from words to register addresses. So update the handling to use these. This also removes the assumption that the registers are 16-bit word addressed, which will no longer be true on some of our newer parts. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 2fcdd84021a5..07c17acc8a4f 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1871,9 +1871,11 @@ static void wm_adsp_ctl_fixup_base(struct wm_adsp *dsp, } static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs, + const struct wm_adsp_region *mem, unsigned int pos, unsigned int len) { void *alg; + unsigned int reg; int ret; __be32 val; @@ -1888,7 +1890,9 @@ static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs, } /* Read the terminator first to validate the length */ - ret = regmap_raw_read(dsp->regmap, pos + len, &val, sizeof(val)); + reg = wm_adsp_region_to_reg(mem, pos + len); + + ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); if (ret != 0) { adsp_err(dsp, "Failed to read algorithm list end: %d\n", ret); @@ -1897,13 +1901,18 @@ static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs, if (be32_to_cpu(val) != 0xbedead) adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbedead\n", - pos + len, be32_to_cpu(val)); + reg, be32_to_cpu(val)); + + /* Convert length from DSP words to bytes */ + len *= sizeof(u32); alg = kcalloc(len, 2, GFP_KERNEL | GFP_DMA); if (!alg) return ERR_PTR(-ENOMEM); - ret = regmap_raw_read(dsp->regmap, pos, alg, len * 2); + reg = wm_adsp_region_to_reg(mem, pos); + + ret = regmap_raw_read(dsp->regmap, reg, alg, len); if (ret != 0) { adsp_err(dsp, "Failed to read algorithm list: %d\n", ret); kfree(alg); @@ -2002,10 +2011,11 @@ static int wm_adsp1_setup_algs(struct wm_adsp *dsp) if (IS_ERR(alg_region)) return PTR_ERR(alg_region); - pos = sizeof(adsp1_id) / 2; - len = (sizeof(*adsp1_alg) * n_algs) / 2; + /* Calculate offset and length in DSP words */ + pos = sizeof(adsp1_id) / sizeof(u32); + len = (sizeof(*adsp1_alg) * n_algs) / sizeof(u32); - adsp1_alg = wm_adsp_read_algs(dsp, n_algs, mem->base + pos, len); + adsp1_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len); if (IS_ERR(adsp1_alg)) return PTR_ERR(adsp1_alg); @@ -2113,10 +2123,11 @@ static int wm_adsp2_setup_algs(struct wm_adsp *dsp) if (IS_ERR(alg_region)) return PTR_ERR(alg_region); - pos = sizeof(adsp2_id) / 2; - len = (sizeof(*adsp2_alg) * n_algs) / 2; + /* Calculate offset and length in DSP words */ + pos = sizeof(adsp2_id) / sizeof(u32); + len = (sizeof(*adsp2_alg) * n_algs) / sizeof(u32); - adsp2_alg = wm_adsp_read_algs(dsp, n_algs, mem->base + pos, len); + adsp2_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len); if (IS_ERR(adsp2_alg)) return PTR_ERR(adsp2_alg); -- cgit v1.2.3 From 1b31de922e28de2bf2078b7a1e341ad4aee6aa03 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 20 Jun 2018 11:56:20 +0100 Subject: ASoC: arizona: Set compressed IRQ to a wake source The current code is not setting the compressed IRQ as a wake source. Normally this doesn't cause any issues as the CODEC IRQ is set as a wake source by the jack detection code and the CODEC only produces a single IRQ line. However if the system is not using jack detection the compressed audio IRQ should still function as a wake source, as such directly set the compressed audio IRQ as a wake source. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l24.c | 8 ++++++++ sound/soc/codecs/wm5102.c | 8 ++++++++ sound/soc/codecs/wm5110.c | 8 ++++++++ 3 files changed, 24 insertions(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index 196e9c343aeb..0da52ead91e0 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -1283,6 +1283,12 @@ static int cs47l24_probe(struct platform_device *pdev) return ret; } + ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 1); + if (ret != 0) + dev_warn(&pdev->dev, + "Failed to set compressed IRQ as a wake source: %d\n", + ret); + arizona_init_common(arizona); ret = arizona_init_vol_limit(arizona); @@ -1306,6 +1312,7 @@ static int cs47l24_probe(struct platform_device *pdev) err_spk_irqs: arizona_free_spk_irqs(arizona); err_dsp_irq: + arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, cs47l24); return ret; @@ -1323,6 +1330,7 @@ static int cs47l24_remove(struct platform_device *pdev) arizona_free_spk_irqs(arizona); + arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, cs47l24); return 0; diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 1ac83388d1b8..a01a0c0e01eb 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -2094,6 +2094,12 @@ static int wm5102_probe(struct platform_device *pdev) return ret; } + ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 1); + if (ret != 0) + dev_warn(&pdev->dev, + "Failed to set compressed IRQ as a wake source: %d\n", + ret); + arizona_init_common(arizona); ret = arizona_init_vol_limit(arizona); @@ -2117,6 +2123,7 @@ static int wm5102_probe(struct platform_device *pdev) err_spk_irqs: arizona_free_spk_irqs(arizona); err_dsp_irq: + arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102); return ret; @@ -2133,6 +2140,7 @@ static int wm5102_remove(struct platform_device *pdev) arizona_free_spk_irqs(arizona); + arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102); return 0; diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index fb9835dcd836..00c735c585d9 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -2455,6 +2455,12 @@ static int wm5110_probe(struct platform_device *pdev) return ret; } + ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 1); + if (ret != 0) + dev_warn(&pdev->dev, + "Failed to set compressed IRQ as a wake source: %d\n", + ret); + arizona_init_common(arizona); ret = arizona_init_vol_limit(arizona); @@ -2478,6 +2484,7 @@ static int wm5110_probe(struct platform_device *pdev) err_spk_irqs: arizona_free_spk_irqs(arizona); err_dsp_irq: + arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5110); return ret; @@ -2496,6 +2503,7 @@ static int wm5110_remove(struct platform_device *pdev) arizona_free_spk_irqs(arizona); + arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5110); return 0; -- cgit v1.2.3 From a98ec93d7e378db21a6cdbc6d55feaba9fb4b999 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 22 Jun 2018 02:23:24 +0000 Subject: ASoC: rt5682: use devm_snd_soc_register_component() Using devm_snd_soc_register_component() and drop all of the code related to .remove hook. Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 61a97301bcfa..baad177908ab 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2630,17 +2630,11 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, } - return snd_soc_register_component(&i2c->dev, &soc_component_dev_rt5682, + return devm_snd_soc_register_component(&i2c->dev, + &soc_component_dev_rt5682, rt5682_dai, ARRAY_SIZE(rt5682_dai)); } -static int rt5682_i2c_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_component(&i2c->dev); - - return 0; -} - static void rt5682_i2c_shutdown(struct i2c_client *client) { struct rt5682_priv *rt5682 = i2c_get_clientdata(client); @@ -2671,7 +2665,6 @@ static struct i2c_driver rt5682_i2c_driver = { .acpi_match_table = ACPI_PTR(rt5682_acpi_match), }, .probe = rt5682_i2c_probe, - .remove = rt5682_i2c_remove, .shutdown = rt5682_i2c_shutdown, .id_table = rt5682_i2c_id, }; -- cgit v1.2.3 From 2854a214f398f2c3315204a05efff11739fec062 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 22 Jun 2018 02:23:34 +0000 Subject: ASoC: rt1305: use devm_snd_soc_register_component() Using devm_snd_soc_register_component() and drop all of the code related to .remove hook. Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- sound/soc/codecs/rt1305.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt1305.c b/sound/soc/codecs/rt1305.c index 421b8fb2fa04..c4452efc7970 100644 --- a/sound/soc/codecs/rt1305.c +++ b/sound/soc/codecs/rt1305.c @@ -1150,17 +1150,11 @@ static int rt1305_i2c_probe(struct i2c_client *i2c, rt1305_reset(rt1305->regmap); rt1305_calibrate(rt1305); - return snd_soc_register_component(&i2c->dev, &soc_component_dev_rt1305, + return devm_snd_soc_register_component(&i2c->dev, + &soc_component_dev_rt1305, rt1305_dai, ARRAY_SIZE(rt1305_dai)); } -static int rt1305_i2c_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_component(&i2c->dev); - - return 0; -} - static void rt1305_i2c_shutdown(struct i2c_client *client) { struct rt1305_priv *rt1305 = i2c_get_clientdata(client); @@ -1180,7 +1174,6 @@ static struct i2c_driver rt1305_i2c_driver = { #endif }, .probe = rt1305_i2c_probe, - .remove = rt1305_i2c_remove, .shutdown = rt1305_i2c_shutdown, .id_table = rt1305_i2c_id, }; -- cgit v1.2.3 From 50c678772a0b3f9dc6b04262f27e2c373fe03a4d Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Sun, 24 Jun 2018 20:14:41 +0200 Subject: ASoC: cx20442: Don't ignore regulator_get() errors. In its current shape, the driver just ignores errors returned by regulator_get() at component_probe(). This doesn't hurt on Amstrad Delta board as long as it registers the codec device at late_initcall, when the regulator which depends on basic-mmio-gpio device (probed as late as at dev_initcall) is already available. Otherwise the driver may end up trying to control a codec which is not powered up. Remove that dependency on initialization order by handling the error. If the regulator is not yet available and -ENODEV is returned, convert it to -EPROBE_DEFER to get another chance. Signed-off-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/codecs/cx20442.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index 07dd33b09596..ab174b5114dc 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -362,8 +362,27 @@ static int cx20442_component_probe(struct snd_soc_component *component) return -ENOMEM; cx20442->por = regulator_get(component->dev, "POR"); - if (IS_ERR(cx20442->por)) - dev_warn(component->dev, "failed to get the regulator"); + if (IS_ERR(cx20442->por)) { + int err = PTR_ERR(cx20442->por); + + dev_warn(component->dev, "failed to get POR supply (%d)", err); + /* + * When running on a non-dt platform and requested regulator + * is not available, regulator_get() never returns + * -EPROBE_DEFER as it is not able to justify if the regulator + * may still appear later. On the other hand, the board can + * still set full constraints flag at late_initcall in order + * to instruct regulator_get() to return a dummy one if + * sufficient. Hence, if we get -ENODEV here, let's convert + * it to -EPROBE_DEFER and wait for the board to decide or + * let Deferred Probe infrastructure handle this error. + */ + if (err == -ENODEV) + err = -EPROBE_DEFER; + kfree(cx20442); + return err; + } + cx20442->tty = NULL; snd_soc_component_set_drvdata(component, cx20442); -- cgit v1.2.3 From 8d881bb6216d28896112bdc0b42f1f21eb6cd4ee Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 26 Jun 2018 14:11:27 +0200 Subject: ASoC: simple-amplifier: rename dio2125 to simple-amplifer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dio2125 is simple enough that we can make it a generic component. Just rename and sed the dio2125 amplifier driver to simple_amplifier. Suggested-by: Nicolò Veronese Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 10 +-- sound/soc/codecs/Makefile | 4 +- sound/soc/codecs/dio2125.c | 120 ----------------------------------- sound/soc/codecs/simple-amplifier.c | 121 ++++++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+), 127 deletions(-) delete mode 100644 sound/soc/codecs/dio2125.c create mode 100644 sound/soc/codecs/simple-amplifier.c (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index f6b8d4bf8796..53c2d726bedf 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -74,7 +74,6 @@ config SND_SOC_ALL_CODECS select SND_SOC_DA7219 if I2C select SND_SOC_DA732X if I2C select SND_SOC_DA9055 if I2C - select SND_SOC_DIO2125 select SND_SOC_DMIC if GPIOLIB select SND_SOC_ES8316 if I2C select SND_SOC_ES8328_SPI if SPI_MASTER @@ -144,6 +143,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_RT5682 if I2C select SND_SOC_SGTL5000 if I2C select SND_SOC_SI476X if MFD_SI476X_CORE + select SND_SOC_SIMPLE_AMPLIFIER select SND_SOC_SIRF_AUDIO_CODEC select SND_SOC_SPDIF select SND_SOC_SSM2305 @@ -573,10 +573,6 @@ config SND_SOC_DA732X config SND_SOC_DA9055 tristate -config SND_SOC_DIO2125 - tristate "Dioo DIO2125 Amplifier" - select GPIOLIB - config SND_SOC_DMIC tristate @@ -897,6 +893,10 @@ config SND_SOC_SIGMADSP_REGMAP tristate select SND_SOC_SIGMADSP +config SND_SOC_SIMPLE_AMPLIFIER + tristate "Simple Audio Amplifier" + select GPIOLIB + config SND_SOC_SIRF_AUDIO_CODEC tristate "SiRF SoC internal audio codec" select REGMAP_MMIO diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index e43d99a039d3..f26ded89a1e5 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -250,9 +250,9 @@ snd-soc-wm9713-objs := wm9713.o snd-soc-wm-hubs-objs := wm_hubs.o snd-soc-zx-aud96p22-objs := zx_aud96p22.o # Amp -snd-soc-dio2125-objs := dio2125.o snd-soc-max9877-objs := max9877.o snd-soc-max98504-objs := max98504.o +snd-soc-simple-amplifier-objs := simple-amplifier.o snd-soc-tpa6130a2-objs := tpa6130a2.o snd-soc-tas2552-objs := tas2552.o @@ -509,7 +509,7 @@ obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o obj-$(CONFIG_SND_SOC_ZX_AUD96P22) += snd-soc-zx-aud96p22.o # Amp -obj-$(CONFIG_SND_SOC_DIO2125) += snd-soc-dio2125.o obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o obj-$(CONFIG_SND_SOC_MAX98504) += snd-soc-max98504.o +obj-$(CONFIG_SND_SOC_SIMPLE_AMPLIFIER) += snd-soc-simple-amplifier.o obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o diff --git a/sound/soc/codecs/dio2125.c b/sound/soc/codecs/dio2125.c deleted file mode 100644 index 09451cd44f9b..000000000000 --- a/sound/soc/codecs/dio2125.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2017 BayLibre, SAS. - * Author: Jerome Brunet - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - */ - -#include -#include -#include - -#define DRV_NAME "dio2125" - -struct dio2125 { - struct gpio_desc *gpiod_enable; -}; - -static int drv_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *control, int event) -{ - struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); - struct dio2125 *priv = snd_soc_component_get_drvdata(c); - int val; - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - val = 1; - break; - case SND_SOC_DAPM_PRE_PMD: - val = 0; - break; - default: - WARN(1, "Unexpected event"); - return -EINVAL; - } - - gpiod_set_value_cansleep(priv->gpiod_enable, val); - - return 0; -} - -static const struct snd_soc_dapm_widget dio2125_dapm_widgets[] = { - SND_SOC_DAPM_INPUT("INL"), - SND_SOC_DAPM_INPUT("INR"), - SND_SOC_DAPM_OUT_DRV_E("DRV", SND_SOC_NOPM, 0, 0, NULL, 0, drv_event, - (SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)), - SND_SOC_DAPM_OUTPUT("OUTL"), - SND_SOC_DAPM_OUTPUT("OUTR"), -}; - -static const struct snd_soc_dapm_route dio2125_dapm_routes[] = { - { "DRV", NULL, "INL" }, - { "DRV", NULL, "INR" }, - { "OUTL", NULL, "DRV" }, - { "OUTR", NULL, "DRV" }, -}; - -static const struct snd_soc_component_driver dio2125_component_driver = { - .dapm_widgets = dio2125_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(dio2125_dapm_widgets), - .dapm_routes = dio2125_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(dio2125_dapm_routes), -}; - -static int dio2125_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct dio2125 *priv; - int err; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - platform_set_drvdata(pdev, priv); - - priv->gpiod_enable = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); - if (IS_ERR(priv->gpiod_enable)) { - err = PTR_ERR(priv->gpiod_enable); - if (err != -EPROBE_DEFER) - dev_err(dev, "Failed to get 'enable' gpio: %d", err); - return err; - } - - return devm_snd_soc_register_component(dev, &dio2125_component_driver, - NULL, 0); -} - -#ifdef CONFIG_OF -static const struct of_device_id dio2125_ids[] = { - { .compatible = "dioo,dio2125", }, - { } -}; -MODULE_DEVICE_TABLE(of, dio2125_ids); -#endif - -static struct platform_driver dio2125_driver = { - .driver = { - .name = DRV_NAME, - .of_match_table = of_match_ptr(dio2125_ids), - }, - .probe = dio2125_probe, -}; - -module_platform_driver(dio2125_driver); - -MODULE_DESCRIPTION("ASoC DIO2125 output driver"); -MODULE_AUTHOR("Jerome Brunet "); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/simple-amplifier.c b/sound/soc/codecs/simple-amplifier.c new file mode 100644 index 000000000000..6c27d4afaf3a --- /dev/null +++ b/sound/soc/codecs/simple-amplifier.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017 BayLibre, SAS. + * Author: Jerome Brunet + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * The full GNU General Public License is included in this distribution + * in the file called COPYING. + */ + +#include +#include +#include + +#define DRV_NAME "simple-amplifier" + +struct simple_amp { + struct gpio_desc *gpiod_enable; +}; + +static int drv_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *control, int event) +{ + struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); + struct simple_amp *priv = snd_soc_component_get_drvdata(c); + int val; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + val = 1; + break; + case SND_SOC_DAPM_PRE_PMD: + val = 0; + break; + default: + WARN(1, "Unexpected event"); + return -EINVAL; + } + + gpiod_set_value_cansleep(priv->gpiod_enable, val); + + return 0; +} + +static const struct snd_soc_dapm_widget simple_amp_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("INL"), + SND_SOC_DAPM_INPUT("INR"), + SND_SOC_DAPM_OUT_DRV_E("DRV", SND_SOC_NOPM, 0, 0, NULL, 0, drv_event, + (SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)), + SND_SOC_DAPM_OUTPUT("OUTL"), + SND_SOC_DAPM_OUTPUT("OUTR"), +}; + +static const struct snd_soc_dapm_route simple_amp_dapm_routes[] = { + { "DRV", NULL, "INL" }, + { "DRV", NULL, "INR" }, + { "OUTL", NULL, "DRV" }, + { "OUTR", NULL, "DRV" }, +}; + +static const struct snd_soc_component_driver simple_amp_component_driver = { + .dapm_widgets = simple_amp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(simple_amp_dapm_widgets), + .dapm_routes = simple_amp_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(simple_amp_dapm_routes), +}; + +static int simple_amp_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct simple_amp *priv; + int err; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + platform_set_drvdata(pdev, priv); + + priv->gpiod_enable = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(priv->gpiod_enable)) { + err = PTR_ERR(priv->gpiod_enable); + if (err != -EPROBE_DEFER) + dev_err(dev, "Failed to get 'enable' gpio: %d", err); + return err; + } + + return devm_snd_soc_register_component(dev, + &simple_amp_component_driver, + NULL, 0); +} + +#ifdef CONFIG_OF +static const struct of_device_id simple_amp_ids[] = { + { .compatible = "dioo,dio2125", }, + { } +}; +MODULE_DEVICE_TABLE(of, simple_amp_ids); +#endif + +static struct platform_driver simple_amp_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = of_match_ptr(simple_amp_ids), + }, + .probe = simple_amp_probe, +}; + +module_platform_driver(simple_amp_driver); + +MODULE_DESCRIPTION("ASoC Simple Audio Amplifier driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 8ed237e83ce9ff4b3964a6b096beb1cbd3397d5a Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 26 Jun 2018 14:11:28 +0200 Subject: ASoC: simple-amplifer: add simple-amplifier compatible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add simple-audio-amplifier to the list of available compatible Suggested-by: Nicolò Veronese Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/simple-amplifier.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/simple-amplifier.c b/sound/soc/codecs/simple-amplifier.c index 6c27d4afaf3a..85524acf3e9c 100644 --- a/sound/soc/codecs/simple-amplifier.c +++ b/sound/soc/codecs/simple-amplifier.c @@ -101,6 +101,7 @@ static int simple_amp_probe(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id simple_amp_ids[] = { { .compatible = "dioo,dio2125", }, + { .compatible = "simple-audio-amplifier", }, { } }; MODULE_DEVICE_TABLE(of, simple_amp_ids); -- cgit v1.2.3 From f516d32262a4c0fef3fccdf2a82671f54f5c1e33 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 27 Jun 2018 09:39:37 +0200 Subject: ASoC: tas517x: add tas5707 support Add support for the tas5707 audio power amplifier. Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 5 ++- sound/soc/codecs/tas571x.c | 110 +++++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/tas571x.h | 16 +++++++ 3 files changed, 130 insertions(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 53c2d726bedf..6d1674699385 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -959,8 +959,11 @@ config SND_SOC_TAS5086 depends on I2C config SND_SOC_TAS571X - tristate "Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 power amplifiers" + tristate "Texas Instruments TAS571x power amplifiers" depends on I2C + help + Enable support for Texas Instruments TAS5707, TAS5711, TAS5717, + TAS5719 and TAS5721 power amplifiers config SND_SOC_TAS5720 tristate "Texas Instruments TAS5720 Mono Audio amplifier" diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index 52f34c94ec25..ca2dfe12344e 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -7,6 +7,9 @@ * TAS5721 support: * Copyright (C) 2016 Petr Kulhavy, Barix AG * + * TAS5707 support: + * Copyright (C) 2018 Jerome Brunet, Baylibre SAS + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -444,6 +447,111 @@ static const struct tas571x_chip tas5711_chip = { .vol_reg_size = 1, }; +static const struct regmap_range tas5707_volatile_regs_range[] = { + regmap_reg_range(TAS571X_CLK_CTRL_REG, TAS571X_ERR_STATUS_REG), + regmap_reg_range(TAS571X_OSC_TRIM_REG, TAS571X_OSC_TRIM_REG), + regmap_reg_range(TAS5707_CH1_BQ0_REG, TAS5707_CH2_BQ6_REG), +}; + +static const struct regmap_access_table tas5707_volatile_regs = { + .yes_ranges = tas5707_volatile_regs_range, + .n_yes_ranges = ARRAY_SIZE(tas5707_volatile_regs_range), + +}; + +static const DECLARE_TLV_DB_SCALE(tas5707_volume_tlv, -7900, 50, 1); + +static const char * const tas5707_volume_slew_step_txt[] = { + "256", "512", "1024", "2048", +}; + +static const unsigned int tas5707_volume_slew_step_values[] = { + 3, 0, 1, 2, +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(tas5707_volume_slew_step_enum, + TAS571X_VOL_CFG_REG, 0, 0x3, + tas5707_volume_slew_step_txt, + tas5707_volume_slew_step_values); + +static const struct snd_kcontrol_new tas5707_controls[] = { + SOC_SINGLE_TLV("Master Volume", + TAS571X_MVOL_REG, + 0, 0xff, 1, tas5707_volume_tlv), + SOC_DOUBLE_R_TLV("Speaker Volume", + TAS571X_CH1_VOL_REG, + TAS571X_CH2_VOL_REG, + 0, 0xff, 1, tas5707_volume_tlv), + SOC_DOUBLE("Speaker Switch", + TAS571X_SOFT_MUTE_REG, + TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT, + 1, 1), + + SOC_ENUM("Slew Rate Steps", tas5707_volume_slew_step_enum), + + BIQUAD_COEFS("CH1 - Biquad 0", TAS5707_CH1_BQ0_REG), + BIQUAD_COEFS("CH1 - Biquad 1", TAS5707_CH1_BQ1_REG), + BIQUAD_COEFS("CH1 - Biquad 2", TAS5707_CH1_BQ2_REG), + BIQUAD_COEFS("CH1 - Biquad 3", TAS5707_CH1_BQ3_REG), + BIQUAD_COEFS("CH1 - Biquad 4", TAS5707_CH1_BQ4_REG), + BIQUAD_COEFS("CH1 - Biquad 5", TAS5707_CH1_BQ5_REG), + BIQUAD_COEFS("CH1 - Biquad 6", TAS5707_CH1_BQ6_REG), + + BIQUAD_COEFS("CH2 - Biquad 0", TAS5707_CH2_BQ0_REG), + BIQUAD_COEFS("CH2 - Biquad 1", TAS5707_CH2_BQ1_REG), + BIQUAD_COEFS("CH2 - Biquad 2", TAS5707_CH2_BQ2_REG), + BIQUAD_COEFS("CH2 - Biquad 3", TAS5707_CH2_BQ3_REG), + BIQUAD_COEFS("CH2 - Biquad 4", TAS5707_CH2_BQ4_REG), + BIQUAD_COEFS("CH2 - Biquad 5", TAS5707_CH2_BQ5_REG), + BIQUAD_COEFS("CH2 - Biquad 6", TAS5707_CH2_BQ6_REG), +}; + +static const struct reg_default tas5707_reg_defaults[] = { + {TAS571X_CLK_CTRL_REG, 0x6c}, + {TAS571X_DEV_ID_REG, 0x70}, + {TAS571X_ERR_STATUS_REG, 0x00}, + {TAS571X_SYS_CTRL_1_REG, 0xa0}, + {TAS571X_SDI_REG, 0x05}, + {TAS571X_SYS_CTRL_2_REG, 0x40}, + {TAS571X_SOFT_MUTE_REG, 0x00}, + {TAS571X_MVOL_REG, 0xff}, + {TAS571X_CH1_VOL_REG, 0x30}, + {TAS571X_CH2_VOL_REG, 0x30}, + {TAS571X_VOL_CFG_REG, 0x91}, + {TAS571X_MODULATION_LIMIT_REG, 0x02}, + {TAS571X_IC_DELAY_CH1_REG, 0xac}, + {TAS571X_IC_DELAY_CH2_REG, 0x54}, + {TAS571X_IC_DELAY_CH3_REG, 0xac}, + {TAS571X_IC_DELAY_CH4_REG, 0x54}, + {TAS571X_START_STOP_PERIOD_REG, 0x0f}, + {TAS571X_OSC_TRIM_REG, 0x82}, + {TAS571X_BKND_ERR_REG, 0x02}, + {TAS571X_INPUT_MUX_REG, 0x17772}, + {TAS571X_PWM_MUX_REG, 0x1021345}, +}; + +static const struct regmap_config tas5707_regmap_config = { + .reg_bits = 8, + .val_bits = 32, + .max_register = 0xff, + .reg_read = tas571x_reg_read, + .reg_write = tas571x_reg_write, + .reg_defaults = tas5707_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tas5707_reg_defaults), + .cache_type = REGCACHE_RBTREE, + .wr_table = &tas571x_write_regs, + .volatile_table = &tas5707_volatile_regs, +}; + +static const struct tas571x_chip tas5707_chip = { + .supply_names = tas5711_supply_names, + .num_supply_names = ARRAY_SIZE(tas5711_supply_names), + .controls = tas5707_controls, + .num_controls = ARRAY_SIZE(tas5707_controls), + .regmap_config = &tas5707_regmap_config, + .vol_reg_size = 1, +}; + static const char *const tas5717_supply_names[] = { "AVDD", "DVDD", @@ -775,6 +883,7 @@ static int tas571x_i2c_remove(struct i2c_client *client) } static const struct of_device_id tas571x_of_match[] = { + { .compatible = "ti,tas5707", .data = &tas5707_chip, }, { .compatible = "ti,tas5711", .data = &tas5711_chip, }, { .compatible = "ti,tas5717", .data = &tas5717_chip, }, { .compatible = "ti,tas5719", .data = &tas5717_chip, }, @@ -784,6 +893,7 @@ static const struct of_device_id tas571x_of_match[] = { MODULE_DEVICE_TABLE(of, tas571x_of_match); static const struct i2c_device_id tas571x_i2c_id[] = { + { "tas5707", (kernel_ulong_t) &tas5707_chip }, { "tas5711", (kernel_ulong_t) &tas5711_chip }, { "tas5717", (kernel_ulong_t) &tas5717_chip }, { "tas5719", (kernel_ulong_t) &tas5717_chip }, diff --git a/sound/soc/codecs/tas571x.h b/sound/soc/codecs/tas571x.h index c45677bc26ad..bd23e89cfe79 100644 --- a/sound/soc/codecs/tas571x.h +++ b/sound/soc/codecs/tas571x.h @@ -53,6 +53,22 @@ #define TAS571X_PWM_MUX_REG 0x25 /* 20-byte biquad registers */ +#define TAS5707_CH1_BQ0_REG 0x29 +#define TAS5707_CH1_BQ1_REG 0x2a +#define TAS5707_CH1_BQ2_REG 0x2b +#define TAS5707_CH1_BQ3_REG 0x2c +#define TAS5707_CH1_BQ4_REG 0x2d +#define TAS5707_CH1_BQ5_REG 0x2e +#define TAS5707_CH1_BQ6_REG 0x2f + +#define TAS5707_CH2_BQ0_REG 0x30 +#define TAS5707_CH2_BQ1_REG 0x31 +#define TAS5707_CH2_BQ2_REG 0x32 +#define TAS5707_CH2_BQ3_REG 0x33 +#define TAS5707_CH2_BQ4_REG 0x34 +#define TAS5707_CH2_BQ5_REG 0x35 +#define TAS5707_CH2_BQ6_REG 0x36 + #define TAS5717_CH1_BQ0_REG 0x26 #define TAS5717_CH1_BQ1_REG 0x27 #define TAS5717_CH1_BQ2_REG 0x28 -- cgit v1.2.3 From 5650729f9a1bbf65b57139d855dabe0a7e6cb494 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 29 Jun 2018 17:09:20 +0200 Subject: ASoC: es7134: remove 64kHz rate from the supported rates 64Khz is actually not supported by the es7134 according to the datasheet Fixes: 9000b59d7a12 ("ASoC: es7134: add es7134 DAC driver") Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/es7134.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/es7134.c b/sound/soc/codecs/es7134.c index 58515bb1a303..2fbb49f5b278 100644 --- a/sound/soc/codecs/es7134.c +++ b/sound/soc/codecs/es7134.c @@ -48,7 +48,11 @@ static struct snd_soc_dai_driver es7134_dai = { .stream_name = "Playback", .channels_min = 2, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = (SNDRV_PCM_RATE_8000_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_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE | -- cgit v1.2.3 From a016b11cc41df06b79c0c226e719d0d88373919c Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 29 Jun 2018 17:09:21 +0200 Subject: ASoC: es7134: check if mclk rate is valid For each supported sample rate, the es7134 can work with several mclk / sample rate ratio. Check if ratio we get is actually OK. Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/es7134.c | 119 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/es7134.c b/sound/soc/codecs/es7134.c index 2fbb49f5b278..698289dc3e22 100644 --- a/sound/soc/codecs/es7134.c +++ b/sound/soc/codecs/es7134.c @@ -17,6 +17,7 @@ * in the file called COPYING. */ +#include #include #include @@ -24,6 +25,77 @@ * The everest 7134 is a very simple DA converter with no register */ +struct es7134_clock_mode { + unsigned int rate_min; + unsigned int rate_max; + unsigned int *mclk_fs; + unsigned int mclk_fs_num; +}; + +struct es7134_chip { + const struct es7134_clock_mode *modes; + unsigned int mode_num; +}; + +struct es7134_data { + unsigned int mclk; + const struct es7134_chip *chip; +}; + +static int es7134_check_mclk(struct snd_soc_dai *dai, + struct es7134_data *priv, + unsigned int rate) +{ + unsigned int mfs = priv->mclk / rate; + int i, j; + + for (i = 0; i < priv->chip->mode_num; i++) { + const struct es7134_clock_mode *mode = &priv->chip->modes[i]; + + if (rate < mode->rate_min || rate > mode->rate_max) + continue; + + for (j = 0; j < mode->mclk_fs_num; j++) { + if (mode->mclk_fs[j] == mfs) + return 0; + } + + dev_err(dai->dev, "unsupported mclk_fs %u for rate %u\n", + mfs, rate); + return -EINVAL; + } + + /* should not happen */ + dev_err(dai->dev, "unsupported rate: %u\n", rate); + return -EINVAL; +} + +static int es7134_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct es7134_data *priv = snd_soc_dai_get_drvdata(dai); + + /* mclk has not been provided, assume it is OK */ + if (!priv->mclk) + return 0; + + return es7134_check_mclk(dai, priv, params_rate(params)); +} + +static int es7134_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct es7134_data *priv = snd_soc_dai_get_drvdata(dai); + + if (dir == SND_SOC_CLOCK_IN && clk_id == 0) { + priv->mclk = freq; + return 0; + } + + return -ENOTSUPP; +} + static int es7134_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { fmt &= (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK | @@ -40,6 +112,8 @@ static int es7134_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) static const struct snd_soc_dai_ops es7134_dai_ops = { .set_fmt = es7134_set_fmt, + .hw_params = es7134_hw_params, + .set_sysclk = es7134_set_sysclk, }; static struct snd_soc_dai_driver es7134_dai = { @@ -62,6 +136,33 @@ static struct snd_soc_dai_driver es7134_dai = { .ops = &es7134_dai_ops, }; +static const struct es7134_clock_mode es7134_modes[] = { + { + /* Single speed mode */ + .rate_min = 8000, + .rate_max = 50000, + .mclk_fs = (unsigned int[]) { 256, 384, 512, 768, 1024 }, + .mclk_fs_num = 5, + }, { + /* Double speed mode */ + .rate_min = 84000, + .rate_max = 100000, + .mclk_fs = (unsigned int[]) { 128, 192, 256, 384, 512 }, + .mclk_fs_num = 5, + }, { + /* Quad speed mode */ + .rate_min = 167000, + .rate_max = 192000, + .mclk_fs = (unsigned int[]) { 128, 192, 256 }, + .mclk_fs_num = 3, + }, +}; + +static const struct es7134_chip es7134_chip = { + .modes = es7134_modes, + .mode_num = ARRAY_SIZE(es7134_modes), +}; + static const struct snd_soc_dapm_widget es7134_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("AOUTL"), SND_SOC_DAPM_OUTPUT("AOUTR"), @@ -86,6 +187,20 @@ static const struct snd_soc_component_driver es7134_component_driver = { static int es7134_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + struct es7134_data *priv; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + platform_set_drvdata(pdev, priv); + + priv->chip = of_device_get_match_data(dev); + if (!priv->chip) { + dev_err(dev, "failed to match device\n"); + return -ENODEV; + } + return devm_snd_soc_register_component(&pdev->dev, &es7134_component_driver, &es7134_dai, 1); @@ -93,8 +208,8 @@ static int es7134_probe(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id es7134_ids[] = { - { .compatible = "everest,es7134", }, - { .compatible = "everest,es7144", }, + { .compatible = "everest,es7134", .data = &es7134_chip }, + { .compatible = "everest,es7144", .data = &es7134_chip }, { } }; MODULE_DEVICE_TABLE(of, es7134_ids); -- cgit v1.2.3 From 424e2b4b3521334812d833eef27df77671428698 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 29 Jun 2018 17:09:23 +0200 Subject: ASoC: es7134: Add VDD and AVDD power supplies Add the VDD and AVDD power supplies to the DAPM graph as some board may need to enable a regulator to turn them on. Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/es7134.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/es7134.c b/sound/soc/codecs/es7134.c index 698289dc3e22..5ad59c38fed1 100644 --- a/sound/soc/codecs/es7134.c +++ b/sound/soc/codecs/es7134.c @@ -167,11 +167,15 @@ static const struct snd_soc_dapm_widget es7134_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("AOUTL"), SND_SOC_DAPM_OUTPUT("AOUTR"), SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("VDD", 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 0, 0), }; static const struct snd_soc_dapm_route es7134_dapm_routes[] = { { "AOUTL", NULL, "DAC" }, { "AOUTR", NULL, "DAC" }, + { "Playback", NULL, "VDD" }, + { "DAC", NULL, "AVDD" }, }; static const struct snd_soc_component_driver es7134_component_driver = { -- cgit v1.2.3 From 2daf3d9962c5a11fb79fe17bae03125df5d60236 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 3 Jul 2018 13:07:25 +0800 Subject: ASoC: rt5682: add button detection mode control We are currently using power saving mode for button detection. However, it will impact the headset recording performance. This patch will switch button detection to normal mode in capture and switch to power saving mode in the end of capture. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index baad177908ab..640d400ca013 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -857,6 +857,8 @@ static int rt5682_button_detect(struct snd_soc_component *component) btn_type = val & 0xfff0; snd_soc_component_write(component, RT5682_4BTN_IL_CMD_1, val); pr_debug("%s btn_type=%x\n", __func__, btn_type); + snd_soc_component_update_bits(component, + RT5682_SAR_IL_CMD_2, 0x10, 0x10); return btn_type; } @@ -1645,6 +1647,8 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { SND_SOC_DAPM_MIXER("Stereo1 ADC MIXR", RT5682_STO1_ADC_DIG_VOL, RT5682_R_MUTE_SFT, 1, rt5682_sto1_adc_r_mix, ARRAY_SIZE(rt5682_sto1_adc_r_mix)), + SND_SOC_DAPM_SUPPLY("BTN Detection Mode", RT5682_SAR_IL_CMD_1, + 14, 1, NULL, 0), /* ADC PGA */ SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), @@ -1807,6 +1811,8 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = { {"Stereo1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux"}, {"Stereo1 ADC MIXR", NULL, "ADC Stereo1 Filter"}, + {"ADC Stereo1 Filter", NULL, "BTN Detection Mode"}, + {"Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL"}, {"Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR"}, -- cgit v1.2.3 From 5f7bdc466c772b3af3145a71724965ecdc03e6bf Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 3 Jul 2018 15:28:45 +0200 Subject: ASoC: es7241: add es7241 codec support Add support for the everest es7241 which is a simple 2 channels analog to digital converter. Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/es7241.c | 322 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 328 insertions(+) create mode 100644 sound/soc/codecs/es7241.c (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 6d1674699385..efb095dbcd71 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -79,6 +79,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_ES8328_SPI if SPI_MASTER select SND_SOC_ES8328_I2C if I2C select SND_SOC_ES7134 + select SND_SOC_ES7241 select SND_SOC_GTM601 select SND_SOC_HDAC_HDMI select SND_SOC_ICS43432 @@ -585,6 +586,9 @@ config SND_SOC_HDMI_CODEC config SND_SOC_ES7134 tristate "Everest Semi ES7134 CODEC" +config SND_SOC_ES7241 + tristate "Everest Semi ES7241 CODEC" + config SND_SOC_ES8316 tristate "Everest Semi ES8316 CODEC" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index f26ded89a1e5..7ae7c85e8219 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -71,6 +71,7 @@ snd-soc-da732x-objs := da732x.o snd-soc-da9055-objs := da9055.o snd-soc-dmic-objs := dmic.o snd-soc-es7134-objs := es7134.o +snd-soc-es7241-objs := es7241.o snd-soc-es8316-objs := es8316.o snd-soc-es8328-objs := es8328.o snd-soc-es8328-i2c-objs := es8328-i2c.o @@ -330,6 +331,7 @@ obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o obj-$(CONFIG_SND_SOC_ES7134) += snd-soc-es7134.o +obj-$(CONFIG_SND_SOC_ES7241) += snd-soc-es7241.o obj-$(CONFIG_SND_SOC_ES8316) += snd-soc-es8316.o obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o diff --git a/sound/soc/codecs/es7241.c b/sound/soc/codecs/es7241.c new file mode 100644 index 000000000000..87991bd4acef --- /dev/null +++ b/sound/soc/codecs/es7241.c @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright (c) 2018 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include + +struct es7241_clock_mode { + unsigned int rate_min; + unsigned int rate_max; + unsigned int *slv_mfs; + unsigned int slv_mfs_num; + unsigned int mst_mfs; + unsigned int mst_m0:1; + unsigned int mst_m1:1; +}; + +struct es7241_chip { + const struct es7241_clock_mode *modes; + unsigned int mode_num; +}; + +struct es7241_data { + struct gpio_desc *reset; + struct gpio_desc *m0; + struct gpio_desc *m1; + unsigned int fmt; + unsigned int mclk; + bool is_slave; + const struct es7241_chip *chip; +}; + +static void es7241_set_mode(struct es7241_data *priv, int m0, int m1) +{ + /* put the device in reset */ + gpiod_set_value_cansleep(priv->reset, 0); + + /* set the mode */ + gpiod_set_value_cansleep(priv->m0, m0); + gpiod_set_value_cansleep(priv->m1, m1); + + /* take the device out of reset - datasheet does not specify a delay */ + gpiod_set_value_cansleep(priv->reset, 1); +} + +static int es7241_set_slave_mode(struct es7241_data *priv, + const struct es7241_clock_mode *mode, + unsigned int mfs) +{ + int j; + + if (!mfs) + goto out_ok; + + for (j = 0; j < mode->slv_mfs_num; j++) { + if (mode->slv_mfs[j] == mfs) + goto out_ok; + } + + return -EINVAL; + +out_ok: + es7241_set_mode(priv, 1, 1); + return 0; +} + +static int es7241_set_master_mode(struct es7241_data *priv, + const struct es7241_clock_mode *mode, + unsigned int mfs) +{ + /* + * We can't really set clock ratio, if the mclk/lrclk is different + * from what we provide, then error out + */ + if (mfs && mfs != mode->mst_mfs) + return -EINVAL; + + es7241_set_mode(priv, mode->mst_m0, mode->mst_m1); + + return 0; +} + +static int es7241_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct es7241_data *priv = snd_soc_dai_get_drvdata(dai); + unsigned int rate = params_rate(params); + unsigned int mfs = priv->mclk / rate; + int i; + + for (i = 0; i < priv->chip->mode_num; i++) { + const struct es7241_clock_mode *mode = &priv->chip->modes[i]; + + if (rate < mode->rate_min || rate >= mode->rate_max) + continue; + + if (priv->is_slave) + return es7241_set_slave_mode(priv, mode, mfs); + else + return es7241_set_master_mode(priv, mode, mfs); + } + + /* should not happen */ + dev_err(dai->dev, "unsupported rate: %u\n", rate); + return -EINVAL; +} + +static int es7241_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct es7241_data *priv = snd_soc_dai_get_drvdata(dai); + + if (dir == SND_SOC_CLOCK_IN && clk_id == 0) { + priv->mclk = freq; + return 0; + } + + return -ENOTSUPP; +} + +static int es7241_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct es7241_data *priv = snd_soc_dai_get_drvdata(dai); + + if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) { + dev_err(dai->dev, "Unsupported dai clock inversion\n"); + return -EINVAL; + } + + if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != priv->fmt) { + dev_err(dai->dev, "Invalid dai format\n"); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + priv->is_slave = true; + break; + case SND_SOC_DAIFMT_CBM_CFM: + priv->is_slave = false; + break; + + default: + dev_err(dai->dev, "Unsupported clock configuration\n"); + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dai_ops es7241_dai_ops = { + .set_fmt = es7241_set_fmt, + .hw_params = es7241_hw_params, + .set_sysclk = es7241_set_sysclk, +}; + +static struct snd_soc_dai_driver es7241_dai = { + .name = "es7241-hifi", + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S24_LE), + }, + .ops = &es7241_dai_ops, +}; + +static const struct es7241_clock_mode es7241_modes[] = { + { + /* Single speed mode */ + .rate_min = 8000, + .rate_max = 50000, + .slv_mfs = (unsigned int[]) { 256, 384, 512, 768, 1024 }, + .slv_mfs_num = 5, + .mst_mfs = 256, + .mst_m0 = 0, + .mst_m1 = 0, + }, { + /* Double speed mode */ + .rate_min = 50000, + .rate_max = 100000, + .slv_mfs = (unsigned int[]) { 128, 192 }, + .slv_mfs_num = 2, + .mst_mfs = 128, + .mst_m0 = 1, + .mst_m1 = 0, + }, { + /* Quad speed mode */ + .rate_min = 100000, + .rate_max = 200000, + .slv_mfs = (unsigned int[]) { 64 }, + .slv_mfs_num = 1, + .mst_mfs = 64, + .mst_m0 = 0, + .mst_m1 = 1, + }, +}; + +static const struct es7241_chip es7241_chip = { + .modes = es7241_modes, + .mode_num = ARRAY_SIZE(es7241_modes), +}; + +static const struct snd_soc_dapm_widget es7241_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("AINL"), + SND_SOC_DAPM_INPUT("AINR"), + SND_SOC_DAPM_DAC("ADC", "Capture", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("VDDP", 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("VDDD", 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("VDDA", 0, 0), +}; + +static const struct snd_soc_dapm_route es7241_dapm_routes[] = { + { "ADC", NULL, "AINL", }, + { "ADC", NULL, "AINR", }, + { "ADC", NULL, "VDDA", }, + { "Capture", NULL, "VDDP", }, + { "Capture", NULL, "VDDD", }, +}; + +static const struct snd_soc_component_driver es7241_component_driver = { + .dapm_widgets = es7241_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(es7241_dapm_widgets), + .dapm_routes = es7241_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(es7241_dapm_routes), + .idle_bias_on = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static void es7241_parse_fmt(struct device *dev, struct es7241_data *priv) +{ + bool is_leftj; + + /* + * The format is given by a pull resistor on the SDOUT pin: + * pull-up for i2s, pull-down for left justified. + */ + is_leftj = of_property_read_bool(dev->of_node, + "everest,sdout-pull-down"); + if (is_leftj) + priv->fmt = SND_SOC_DAIFMT_LEFT_J; + else + priv->fmt = SND_SOC_DAIFMT_I2S; +} + +static int es7241_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct es7241_data *priv; + int err; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + platform_set_drvdata(pdev, priv); + + priv->chip = of_device_get_match_data(dev); + if (!priv->chip) { + dev_err(dev, "failed to match device\n"); + return -ENODEV; + } + + es7241_parse_fmt(dev, priv); + + priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(priv->reset)) { + err = PTR_ERR(priv->reset); + if (err != -EPROBE_DEFER) + dev_err(dev, "Failed to get 'reset' gpio: %d", err); + return err; + } + + priv->m0 = devm_gpiod_get_optional(dev, "m0", GPIOD_OUT_LOW); + if (IS_ERR(priv->m0)) { + err = PTR_ERR(priv->m0); + if (err != -EPROBE_DEFER) + dev_err(dev, "Failed to get 'm0' gpio: %d", err); + return err; + } + + priv->m1 = devm_gpiod_get_optional(dev, "m1", GPIOD_OUT_LOW); + if (IS_ERR(priv->m1)) { + err = PTR_ERR(priv->m1); + if (err != -EPROBE_DEFER) + dev_err(dev, "Failed to get 'm1' gpio: %d", err); + return err; + } + + return devm_snd_soc_register_component(&pdev->dev, + &es7241_component_driver, + &es7241_dai, 1); +} + +#ifdef CONFIG_OF +static const struct of_device_id es7241_ids[] = { + { .compatible = "everest,es7241", .data = &es7241_chip }, + { } +}; +MODULE_DEVICE_TABLE(of, es7241_ids); +#endif + +static struct platform_driver es7241_driver = { + .driver = { + .name = "es7241", + .of_match_table = of_match_ptr(es7241_ids), + }, + .probe = es7241_probe, +}; + +module_platform_driver(es7241_driver); + +MODULE_DESCRIPTION("ASoC ES7241 audio codec driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 30ddfffd10b73d5d960650ea70b33a8ee0562679 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 3 Jul 2018 17:05:59 +0200 Subject: ASoC: es7134: correct required power supplies Drop AVDD in favor of PVDD to match the names used in the datasheet and only claim PVDD on the es7154. The es7134 and es7144 don't have a separate supply for the digital I/O. Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/es7134.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/es7134.c b/sound/soc/codecs/es7134.c index 5ad59c38fed1..80f2936cefed 100644 --- a/sound/soc/codecs/es7134.c +++ b/sound/soc/codecs/es7134.c @@ -35,6 +35,10 @@ struct es7134_clock_mode { struct es7134_chip { const struct es7134_clock_mode *modes; unsigned int mode_num; + const struct snd_soc_dapm_widget *extra_widgets; + unsigned int extra_widget_num; + const struct snd_soc_dapm_route *extra_routes; + unsigned int extra_route_num; }; struct es7134_data { @@ -110,6 +114,34 @@ static int es7134_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } +static int es7134_component_probe(struct snd_soc_component *c) +{ + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(c); + struct es7134_data *priv = snd_soc_component_get_drvdata(c); + const struct es7134_chip *chip = priv->chip; + int ret; + + if (chip->extra_widget_num) { + ret = snd_soc_dapm_new_controls(dapm, chip->extra_widgets, + chip->extra_widget_num); + if (ret) { + dev_err(c->dev, "failed to add extra widgets\n"); + return ret; + } + } + + if (chip->extra_route_num) { + ret = snd_soc_dapm_add_routes(dapm, chip->extra_routes, + chip->extra_route_num); + if (ret) { + dev_err(c->dev, "failed to add extra routes\n"); + return ret; + } + } + + return 0; +} + static const struct snd_soc_dai_ops es7134_dai_ops = { .set_fmt = es7134_set_fmt, .hw_params = es7134_hw_params, @@ -158,9 +190,16 @@ static const struct es7134_clock_mode es7134_modes[] = { }, }; +/* Digital I/O are also supplied by VDD on the es7134 */ +static const struct snd_soc_dapm_route es7134_extra_routes[] = { + { "Playback", NULL, "VDD", } +}; + static const struct es7134_chip es7134_chip = { .modes = es7134_modes, .mode_num = ARRAY_SIZE(es7134_modes), + .extra_routes = es7134_extra_routes, + .extra_route_num = ARRAY_SIZE(es7134_extra_routes), }; static const struct snd_soc_dapm_widget es7134_dapm_widgets[] = { @@ -168,17 +207,16 @@ static const struct snd_soc_dapm_widget es7134_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("AOUTR"), SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("VDD", 0, 0), - SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 0, 0), }; static const struct snd_soc_dapm_route es7134_dapm_routes[] = { { "AOUTL", NULL, "DAC" }, { "AOUTR", NULL, "DAC" }, - { "Playback", NULL, "VDD" }, - { "DAC", NULL, "AVDD" }, + { "DAC", NULL, "VDD" }, }; static const struct snd_soc_component_driver es7134_component_driver = { + .probe = es7134_component_probe, .dapm_widgets = es7134_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(es7134_dapm_widgets), .dapm_routes = es7134_dapm_routes, -- cgit v1.2.3 From 563c263248ff37dcd743549a0c0932fe2bf83980 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 3 Jul 2018 17:06:00 +0200 Subject: ASoC: es7134: add support for the es7154 Add support for the es7154 which is basically an es7134 with an embedded power amplifier and lower maximum sample rate Signed-off-by: Jerome Brunet Signed-off-by: Mark Brown --- sound/soc/codecs/es7134.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/es7134.c b/sound/soc/codecs/es7134.c index 80f2936cefed..6d7bca7b78ca 100644 --- a/sound/soc/codecs/es7134.c +++ b/sound/soc/codecs/es7134.c @@ -33,6 +33,7 @@ struct es7134_clock_mode { }; struct es7134_chip { + struct snd_soc_dai_driver *dai_drv; const struct es7134_clock_mode *modes; unsigned int mode_num; const struct snd_soc_dapm_widget *extra_widgets; @@ -196,6 +197,7 @@ static const struct snd_soc_dapm_route es7134_extra_routes[] = { }; static const struct es7134_chip es7134_chip = { + .dai_drv = &es7134_dai, .modes = es7134_modes, .mode_num = ARRAY_SIZE(es7134_modes), .extra_routes = es7134_extra_routes, @@ -227,6 +229,61 @@ static const struct snd_soc_component_driver es7134_component_driver = { .non_legacy_dai_naming = 1, }; +static struct snd_soc_dai_driver es7154_dai = { + .name = "es7154-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = (SNDRV_PCM_RATE_8000_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S18_3LE | + SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S24_LE), + }, + .ops = &es7134_dai_ops, +}; + +static const struct es7134_clock_mode es7154_modes[] = { + { + /* Single speed mode */ + .rate_min = 8000, + .rate_max = 50000, + .mclk_fs = (unsigned int[]) { 32, 64, 128, 192, 256, + 384, 512, 768, 1024 }, + .mclk_fs_num = 9, + }, { + /* Double speed mode */ + .rate_min = 84000, + .rate_max = 100000, + .mclk_fs = (unsigned int[]) { 128, 192, 256, 384, 512, + 768, 1024}, + .mclk_fs_num = 7, + } +}; + +/* Es7154 has a separate supply for digital I/O */ +static const struct snd_soc_dapm_widget es7154_extra_widgets[] = { + SND_SOC_DAPM_REGULATOR_SUPPLY("PVDD", 0, 0), +}; + +static const struct snd_soc_dapm_route es7154_extra_routes[] = { + { "Playback", NULL, "PVDD", } +}; + +static const struct es7134_chip es7154_chip = { + .dai_drv = &es7154_dai, + .modes = es7154_modes, + .mode_num = ARRAY_SIZE(es7154_modes), + .extra_routes = es7154_extra_routes, + .extra_route_num = ARRAY_SIZE(es7154_extra_routes), + .extra_widgets = es7154_extra_widgets, + .extra_widget_num = ARRAY_SIZE(es7154_extra_widgets), +}; + static int es7134_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -245,13 +302,14 @@ static int es7134_probe(struct platform_device *pdev) return devm_snd_soc_register_component(&pdev->dev, &es7134_component_driver, - &es7134_dai, 1); + priv->chip->dai_drv, 1); } #ifdef CONFIG_OF static const struct of_device_id es7134_ids[] = { { .compatible = "everest,es7134", .data = &es7134_chip }, { .compatible = "everest,es7144", .data = &es7134_chip }, + { .compatible = "everest,es7154", .data = &es7154_chip }, { } }; MODULE_DEVICE_TABLE(of, es7134_ids); -- cgit v1.2.3 From da13ed1d80fe6a4d95043aaf2e0aff292ade5708 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 4 Jul 2018 09:28:28 -0500 Subject: ASoC: nau8825: use 64-bit arithmetic instead of 32-bit Add suffix ULL to constant 256 in order to give the compiler complete information about the proper arithmetic to use. Notice that such constant is used in a context that expects an expression of type u64 (64 bits, unsigned) and the following expression is currently being evaluated using 32-bit arithmetic: 256 * fs * 2 * mclk_src_scaling[i].param Addresses-Coverity-ID: 1339616 ("Unintentional integer overflow") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/nau8825.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index dc6ea4987b7d..b9fed99d8b5e 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -2016,7 +2016,7 @@ static int nau8825_calc_fll_param(unsigned int fll_in, unsigned int fs, fvco_max = 0; fvco_sel = ARRAY_SIZE(mclk_src_scaling); for (i = 0; i < ARRAY_SIZE(mclk_src_scaling); i++) { - fvco = 256 * fs * 2 * mclk_src_scaling[i].param; + fvco = 256ULL * fs * 2 * mclk_src_scaling[i].param; if (fvco > NAU_FVCO_MIN && fvco < NAU_FVCO_MAX && fvco_max < fvco) { fvco_max = fvco; -- cgit v1.2.3 From f7ddff54d0a0f068442414b48bec7f22aa777de7 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 5 Jul 2018 08:06:17 -0500 Subject: ASoC: nau8824: use 64-bit arithmetic instead of 32-bit Add suffix ULL to constant 256 in order to give the compiler complete information about the proper arithmetic to use. Notice that such constant is used in a context that expects an expression of type u64 (64 bits, unsigned) and the following expression is currently being evaluated using 32-bit arithmetic: 256 * fs * 2 * mclk_src_scaling[i].param Addresses-Coverity-ID: 1432039 ("Unintentional integer overflow") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/nau8824.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c index 6bd14453f06e..468d5143e2c4 100644 --- a/sound/soc/codecs/nau8824.c +++ b/sound/soc/codecs/nau8824.c @@ -1274,7 +1274,7 @@ static int nau8824_calc_fll_param(unsigned int fll_in, fvco_max = 0; fvco_sel = ARRAY_SIZE(mclk_src_scaling); for (i = 0; i < ARRAY_SIZE(mclk_src_scaling); i++) { - fvco = 256 * fs * 2 * mclk_src_scaling[i].param; + fvco = 256ULL * fs * 2 * mclk_src_scaling[i].param; if (fvco > NAU_FVCO_MIN && fvco < NAU_FVCO_MAX && fvco_max < fvco) { fvco_max = fvco; -- cgit v1.2.3 From 5bea327962fa296efd16f2d3369dd339ddd7ce6f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 6 Jul 2018 16:19:14 +0300 Subject: ASoC: adau171x1: Connect playback DAI to the DSP The playback DAI is connected to the DSP and the DSP might be sourcing signals from the playback stream. Add a DAPM route between the two to make sure that the playback DAI is powered up, when the DSP is active. Signed-off-by: Lars-Peter Clausen Signed-off-by: Alexandru Ardelean Signed-off-by: Mark Brown --- sound/soc/codecs/adau17x1.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index ae41edd1c406..57169b8ff14e 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c @@ -299,6 +299,7 @@ static const struct snd_soc_dapm_route adau17x1_dsp_dapm_routes[] = { { "DSP", NULL, "Left Decimator" }, { "DSP", NULL, "Right Decimator" }, + { "DSP", NULL, "Playback" }, }; static const struct snd_soc_dapm_route adau17x1_no_dsp_dapm_routes[] = { -- cgit v1.2.3 From 8d2d7bcdc1645dc243f7735278675b083c0e506c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 5 Jul 2018 00:59:31 +0200 Subject: ASoC: rt5651: Fix workqueue cancel vs irq free race on remove On removal we must free the IRQ *before* cancelling the jack-detect work, so that the jack-detect work cannot be rescheduled by the IRQ. Before this commit we were cancelling the jack-detect work from the driver remove callback, while relying on devm to free the IRQ, which happens after the remove callback. This is the wrong order. This commit uses a devm-action to register a devm callback which cancels the work, before requesting the IRQ (devm tears things down in reverse order). This also allows us to remove the now empty remove driver callback. Cc: Carlo Caione Signed-off-by: Hans de Goede Signed-off-by: Mark Brown --- sound/soc/codecs/rt5651.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 6b5669f3e85d..39d2c67cd064 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1696,6 +1696,13 @@ static irqreturn_t rt5651_irq(int irq, void *data) return IRQ_HANDLED; } +static void rt5651_cancel_work(void *data) +{ + struct rt5651_priv *rt5651 = data; + + cancel_work_sync(&rt5651->jack_detect_work); +} + static int rt5651_set_jack(struct snd_soc_component *component, struct snd_soc_jack *hp_jack, void *data) { @@ -2036,6 +2043,11 @@ static int rt5651_i2c_probe(struct i2c_client *i2c, INIT_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work); + /* Make sure work is stopped on probe-error / remove */ + ret = devm_add_action_or_reset(&i2c->dev, rt5651_cancel_work, rt5651); + if (ret) + return ret; + ret = devm_snd_soc_register_component(&i2c->dev, &soc_component_dev_rt5651, rt5651_dai, ARRAY_SIZE(rt5651_dai)); @@ -2043,15 +2055,6 @@ static int rt5651_i2c_probe(struct i2c_client *i2c, return ret; } -static int rt5651_i2c_remove(struct i2c_client *i2c) -{ - struct rt5651_priv *rt5651 = i2c_get_clientdata(i2c); - - cancel_work_sync(&rt5651->jack_detect_work); - - return 0; -} - static struct i2c_driver rt5651_i2c_driver = { .driver = { .name = "rt5651", @@ -2059,7 +2062,6 @@ static struct i2c_driver rt5651_i2c_driver = { .of_match_table = of_match_ptr(rt5651_of_match), }, .probe = rt5651_i2c_probe, - .remove = rt5651_i2c_remove, .id_table = rt5651_i2c_id, }; module_i2c_driver(rt5651_i2c_driver); -- cgit v1.2.3 From 34c906ddacd237511808fb2bbd941e6b91e9095a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 5 Jul 2018 00:59:32 +0200 Subject: ASoC: rt5651: Allow disabling jack-detect by calling set_jack(NULL) Allow the machine driver to disable jack-detect over a suspend/resume by calling snd_soc_component_set_jack(NULL). Note this renames rt5651_set_jack, where all the jack-enable work was done to rt5651_enable_jack_detect. This function can now no longer fail as it does not request the IRQ anymore. It can still be passed an invalid jack source, but that should never happen, so this is now logged and treated as no jack source. Cc: Carlo Caione Signed-off-by: Hans de Goede Signed-off-by: Mark Brown --- sound/soc/codecs/rt5651.c | 55 +++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 19 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 39d2c67cd064..40bd1e70fee7 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1703,14 +1703,10 @@ static void rt5651_cancel_work(void *data) cancel_work_sync(&rt5651->jack_detect_work); } -static int rt5651_set_jack(struct snd_soc_component *component, - struct snd_soc_jack *hp_jack, void *data) +static void rt5651_enable_jack_detect(struct snd_soc_component *component, + struct snd_soc_jack *hp_jack) { struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); - int ret; - - if (!rt5651->irq) - return -EINVAL; /* IRQ output on GPIO1 */ snd_soc_component_update_bits(component, RT5651_GPIO_CTRL1, @@ -1737,10 +1733,10 @@ static int rt5651_set_jack(struct snd_soc_component *component, RT5651_JD2_IRQ_EN, RT5651_JD2_IRQ_EN); break; case RT5651_JD_NULL: - return 0; + return; default: dev_err(component->dev, "Currently only JD1_1 / JD1_2 / JD2 are supported\n"); - return -EINVAL; + return; } /* Enable jack detect power */ @@ -1774,19 +1770,28 @@ static int rt5651_set_jack(struct snd_soc_component *component, RT5651_MB1_OC_STKY_MASK, RT5651_MB1_OC_STKY_EN); rt5651->hp_jack = hp_jack; - - ret = devm_request_threaded_irq(component->dev, rt5651->irq, NULL, - rt5651_irq, - IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING | - IRQF_ONESHOT, "rt5651", rt5651); - if (ret) { - dev_err(component->dev, "Failed to reguest IRQ: %d\n", ret); - return ret; - } - + enable_irq(rt5651->irq); /* sync initial jack state */ queue_work(system_power_efficient_wq, &rt5651->jack_detect_work); +} + +static void rt5651_disable_jack_detect(struct snd_soc_component *component) +{ + struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); + + disable_irq(rt5651->irq); + rt5651_cancel_work(rt5651); + + rt5651->hp_jack = NULL; +} + +static int rt5651_set_jack(struct snd_soc_component *component, + struct snd_soc_jack *jack, void *data) +{ + if (jack) + rt5651_enable_jack_detect(component, jack); + else + rt5651_disable_jack_detect(component); return 0; } @@ -2048,6 +2053,18 @@ static int rt5651_i2c_probe(struct i2c_client *i2c, if (ret) return ret; + ret = devm_request_irq(&i2c->dev, rt5651->irq, rt5651_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING + | IRQF_ONESHOT, "rt5651", rt5651); + if (ret == 0) { + /* Gets re-enabled by rt5651_set_jack() */ + disable_irq(rt5651->irq); + } else { + dev_warn(&i2c->dev, "Failed to reguest IRQ %d: %d\n", + rt5651->irq, ret); + rt5651->irq = -ENXIO; + } + ret = devm_snd_soc_register_component(&i2c->dev, &soc_component_dev_rt5651, rt5651_dai, ARRAY_SIZE(rt5651_dai)); -- cgit v1.2.3 From df1569f2006b157caa944367d0d431eb4ea08624 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 5 Jul 2018 00:59:33 +0200 Subject: ASoC: rt5651: Add button press support Enable button press detection for headsets by using the ovcd IRQ to get notified of button presses. This is modelled after (almost exactly copied from) the button press code for the rt5640 which has identical ovcd hardware. Signed-off-by: Hans de Goede Signed-off-by: Mark Brown --- sound/soc/codecs/rt5651.c | 158 ++++++++++++++++++++++++++++++++++++++++++++-- sound/soc/codecs/rt5651.h | 8 +++ 2 files changed, 159 insertions(+), 7 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 40bd1e70fee7..0462049e739c 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1581,6 +1581,24 @@ static void rt5651_disable_micbias1_for_ovcd(struct snd_soc_component *component snd_soc_dapm_mutex_unlock(dapm); } +static void rt5651_enable_micbias1_ovcd_irq(struct snd_soc_component *component) +{ + struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); + + snd_soc_component_update_bits(component, RT5651_IRQ_CTRL2, + RT5651_IRQ_MB1_OC_MASK, RT5651_IRQ_MB1_OC_NOR); + rt5651->ovcd_irq_enabled = true; +} + +static void rt5651_disable_micbias1_ovcd_irq(struct snd_soc_component *component) +{ + struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); + + snd_soc_component_update_bits(component, RT5651_IRQ_CTRL2, + RT5651_IRQ_MB1_OC_MASK, RT5651_IRQ_MB1_OC_BP); + rt5651->ovcd_irq_enabled = false; +} + static void rt5651_clear_micbias1_ovcd(struct snd_soc_component *component) { snd_soc_component_update_bits(component, RT5651_IRQ_CTRL2, @@ -1622,10 +1640,80 @@ static bool rt5651_jack_inserted(struct snd_soc_component *component) return val == 0; } -/* Jack detect timings */ +/* Jack detect and button-press timings */ #define JACK_SETTLE_TIME 100 /* milli seconds */ #define JACK_DETECT_COUNT 5 #define JACK_DETECT_MAXCOUNT 20 /* Aprox. 2 seconds worth of tries */ +#define JACK_UNPLUG_TIME 80 /* milli seconds */ +#define BP_POLL_TIME 10 /* milli seconds */ +#define BP_POLL_MAXCOUNT 200 /* assume something is wrong after this */ +#define BP_THRESHOLD 3 + +static void rt5651_start_button_press_work(struct snd_soc_component *component) +{ + struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); + + rt5651->poll_count = 0; + rt5651->press_count = 0; + rt5651->release_count = 0; + rt5651->pressed = false; + rt5651->press_reported = false; + rt5651_clear_micbias1_ovcd(component); + schedule_delayed_work(&rt5651->bp_work, msecs_to_jiffies(BP_POLL_TIME)); +} + +static void rt5651_button_press_work(struct work_struct *work) +{ + struct rt5651_priv *rt5651 = + container_of(work, struct rt5651_priv, bp_work.work); + struct snd_soc_component *component = rt5651->component; + + /* Check the jack was not removed underneath us */ + if (!rt5651_jack_inserted(component)) + return; + + if (rt5651_micbias1_ovcd(component)) { + rt5651->release_count = 0; + rt5651->press_count++; + /* Remember till after JACK_UNPLUG_TIME wait */ + if (rt5651->press_count >= BP_THRESHOLD) + rt5651->pressed = true; + rt5651_clear_micbias1_ovcd(component); + } else { + rt5651->press_count = 0; + rt5651->release_count++; + } + + /* + * The pins get temporarily shorted on jack unplug, so we poll for + * at least JACK_UNPLUG_TIME milli-seconds before reporting a press. + */ + rt5651->poll_count++; + if (rt5651->poll_count < (JACK_UNPLUG_TIME / BP_POLL_TIME)) { + schedule_delayed_work(&rt5651->bp_work, + msecs_to_jiffies(BP_POLL_TIME)); + return; + } + + if (rt5651->pressed && !rt5651->press_reported) { + dev_dbg(component->dev, "headset button press\n"); + snd_soc_jack_report(rt5651->hp_jack, SND_JACK_BTN_0, + SND_JACK_BTN_0); + rt5651->press_reported = true; + } + + if (rt5651->release_count >= BP_THRESHOLD) { + if (rt5651->press_reported) { + dev_dbg(component->dev, "headset button release\n"); + snd_soc_jack_report(rt5651->hp_jack, 0, SND_JACK_BTN_0); + } + /* Re-enable OVCD IRQ to detect next press */ + rt5651_enable_micbias1_ovcd_irq(component); + return; /* Stop polling */ + } + + schedule_delayed_work(&rt5651->bp_work, msecs_to_jiffies(BP_POLL_TIME)); +} static int rt5651_detect_headset(struct snd_soc_component *component) { @@ -1676,15 +1764,58 @@ static void rt5651_jack_detect_work(struct work_struct *work) { struct rt5651_priv *rt5651 = container_of(work, struct rt5651_priv, jack_detect_work); + struct snd_soc_component *component = rt5651->component; int report = 0; - if (rt5651_jack_inserted(rt5651->component)) { - rt5651_enable_micbias1_for_ovcd(rt5651->component); - report = rt5651_detect_headset(rt5651->component); - rt5651_disable_micbias1_for_ovcd(rt5651->component); + if (!rt5651_jack_inserted(component)) { + /* Jack removed, or spurious IRQ? */ + if (rt5651->hp_jack->status & SND_JACK_HEADPHONE) { + if (rt5651->hp_jack->status & SND_JACK_MICROPHONE) { + cancel_delayed_work_sync(&rt5651->bp_work); + rt5651_disable_micbias1_ovcd_irq(component); + rt5651_disable_micbias1_for_ovcd(component); + } + snd_soc_jack_report(rt5651->hp_jack, 0, + SND_JACK_HEADSET | SND_JACK_BTN_0); + dev_dbg(component->dev, "jack unplugged\n"); + } + } else if (!(rt5651->hp_jack->status & SND_JACK_HEADPHONE)) { + /* Jack inserted */ + WARN_ON(rt5651->ovcd_irq_enabled); + rt5651_enable_micbias1_for_ovcd(component); + report = rt5651_detect_headset(component); + if (report == SND_JACK_HEADSET) { + /* Enable ovcd IRQ for button press detect. */ + rt5651_enable_micbias1_ovcd_irq(component); + } else { + /* No more need for overcurrent detect. */ + rt5651_disable_micbias1_for_ovcd(component); + } + dev_dbg(component->dev, "detect report %#02x\n", report); + snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET); + } else if (rt5651->ovcd_irq_enabled && rt5651_micbias1_ovcd(component)) { + dev_dbg(component->dev, "OVCD IRQ\n"); + + /* + * The ovcd IRQ keeps firing while the button is pressed, so + * we disable it and start polling the button until released. + * + * The disable will make the IRQ pin 0 again and since we get + * IRQs on both edges (so as to detect both jack plugin and + * unplug) this means we will immediately get another IRQ. + * The ovcd_irq_enabled check above makes the 2ND IRQ a NOP. + */ + rt5651_disable_micbias1_ovcd_irq(component); + rt5651_start_button_press_work(component); + + /* + * If the jack-detect IRQ flag goes high (unplug) after our + * above rt5651_jack_inserted() check and before we have + * disabled the OVCD IRQ, the IRQ pin will stay high and as + * we react to edges, we miss the unplug event -> recheck. + */ + queue_work(system_long_wq, &rt5651->jack_detect_work); } - - snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET); } static irqreturn_t rt5651_irq(int irq, void *data) @@ -1701,6 +1832,7 @@ static void rt5651_cancel_work(void *data) struct rt5651_priv *rt5651 = data; cancel_work_sync(&rt5651->jack_detect_work); + cancel_delayed_work_sync(&rt5651->bp_work); } static void rt5651_enable_jack_detect(struct snd_soc_component *component, @@ -1770,6 +1902,11 @@ static void rt5651_enable_jack_detect(struct snd_soc_component *component, RT5651_MB1_OC_STKY_MASK, RT5651_MB1_OC_STKY_EN); rt5651->hp_jack = hp_jack; + if (rt5651->hp_jack->status & SND_JACK_MICROPHONE) { + rt5651_enable_micbias1_for_ovcd(component); + rt5651_enable_micbias1_ovcd_irq(component); + } + enable_irq(rt5651->irq); /* sync initial jack state */ queue_work(system_power_efficient_wq, &rt5651->jack_detect_work); @@ -1782,6 +1919,12 @@ static void rt5651_disable_jack_detect(struct snd_soc_component *component) disable_irq(rt5651->irq); rt5651_cancel_work(rt5651); + if (rt5651->hp_jack->status & SND_JACK_MICROPHONE) { + rt5651_disable_micbias1_ovcd_irq(component); + rt5651_disable_micbias1_for_ovcd(component); + snd_soc_jack_report(rt5651->hp_jack, 0, SND_JACK_BTN_0); + } + rt5651->hp_jack = NULL; } @@ -2046,6 +2189,7 @@ static int rt5651_i2c_probe(struct i2c_client *i2c, rt5651->irq = i2c->irq; rt5651->hp_mute = 1; + INIT_DELAYED_WORK(&rt5651->bp_work, rt5651_button_press_work); INIT_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work); /* Make sure work is stopped on probe-error / remove */ diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h index 3a0968c53fde..ac6de6fb5414 100644 --- a/sound/soc/codecs/rt5651.h +++ b/sound/soc/codecs/rt5651.h @@ -2071,8 +2071,16 @@ struct rt5651_pll_code { struct rt5651_priv { struct snd_soc_component *component; struct regmap *regmap; + /* Jack and button detect data */ struct snd_soc_jack *hp_jack; struct work_struct jack_detect_work; + struct delayed_work bp_work; + bool ovcd_irq_enabled; + bool pressed; + bool press_reported; + int press_count; + int release_count; + int poll_count; unsigned int jd_src; unsigned int ovcd_th; unsigned int ovcd_sf; -- cgit v1.2.3 From d30e23d69981a4b665f5ce8711335df986576389 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 14 Jul 2018 16:01:06 +0100 Subject: ASoC: hdmi-codec: fix routing Commit 943fa0228252 ("ASoC: hdmi-codec: Use different name for playback streams") broke hdmi-codec's routing between it's output "TX" widget and the S/PDIF or I2S streams by renaming the streams. Whether an error occurs or not is dependent on whether there is another widget called "Playback" registered by some other component - if there is, that widget will be (incorrectly) bound to the HDMI codec's "TX" output widget. If we end up connecting "TX" incorrectly, it can result in components not being started, causing no audio output. Since the I2S and S/PDIF streams now have different names, we can't use a static route at component level to describe the relationship, so arrange to dynamically create the route when the DAI driver is probed. Fixes: 943fa0228252 ("ASoC: hdmi-codec: Use different name for playback streams") Signed-off-by: Russell King Signed-off-by: Mark Brown --- sound/soc/codecs/hdmi-codec.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 6fa11888672d..3e5b12de71bb 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -291,10 +291,6 @@ static const struct snd_soc_dapm_widget hdmi_widgets[] = { SND_SOC_DAPM_OUTPUT("TX"), }; -static const struct snd_soc_dapm_route hdmi_routes[] = { - { "TX", NULL, "Playback" }, -}; - enum { DAI_ID_I2S = 0, DAI_ID_SPDIF, @@ -689,9 +685,23 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd, return snd_ctl_add(rtd->card->snd_card, kctl); } +static int hdmi_dai_probe(struct snd_soc_dai *dai) +{ + struct snd_soc_dapm_context *dapm; + struct snd_soc_dapm_route route = { + .sink = "TX", + .source = dai->driver->playback.stream_name, + }; + + dapm = snd_soc_component_get_dapm(dai->component); + + return snd_soc_dapm_add_routes(dapm, &route, 1); +} + static const struct snd_soc_dai_driver hdmi_i2s_dai = { .name = "i2s-hifi", .id = DAI_ID_I2S, + .probe = hdmi_dai_probe, .playback = { .stream_name = "I2S Playback", .channels_min = 2, @@ -707,6 +717,7 @@ static const 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, + .probe = hdmi_dai_probe, .playback = { .stream_name = "SPDIF Playback", .channels_min = 2, @@ -733,8 +744,6 @@ static int hdmi_of_xlate_dai_id(struct snd_soc_component *component, static const struct snd_soc_component_driver hdmi_driver = { .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_id = hdmi_of_xlate_dai_id, .idle_bias_on = 1, .use_pmdown_time = 1, -- cgit v1.2.3 From bf270262b7b8bb7b48a846c613f74e800abba392 Mon Sep 17 00:00:00 2001 From: Sriram Periyasamy Date: Mon, 16 Jul 2018 15:32:34 +0530 Subject: ASoC: hdac_hdmi: Add documentation for power management Add documentation for power management of HDAC HDMI codec device for various scenarios such as S0/S3, probe and playback use case. Signed-off-by: Sriram Periyasamy Signed-off-by: Sanyog Kale Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 69 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 84f7a7a36e4b..30ccc902e5cf 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -2103,6 +2103,75 @@ static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev) } #ifdef CONFIG_PM +/* + * Power management sequences + * ========================== + * + * The following explains the PM handling of HDAC HDMI with its parent + * device SKL and display power usage + * + * Probe + * ----- + * In SKL probe, + * 1. skl_probe_work() powers up the display (refcount++ -> 1) + * 2. enumerates the codecs on the link + * 3. powers down the display (refcount-- -> 0) + * + * In HDAC HDMI probe, + * 1. hdac_hdmi_dev_probe() powers up the display (refcount++ -> 1) + * 2. probe the codec + * 3. put the HDAC HDMI device to runtime suspend + * 4. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0) + * + * Once children are runtime suspended, SKL device also goes to runtime + * suspend + * + * HDMI Playback + * ------------- + * Open HDMI device, + * 1. skl_runtime_resume() invoked + * 2. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1) + * + * Close HDMI device, + * 1. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0) + * 2. skl_runtime_suspend() invoked + * + * S0/S3 Cycle with playback in progress + * ------------------------------------- + * When the device is opened for playback, the device is runtime active + * already and the display refcount is 1 as explained above. + * + * Entering to S3, + * 1. hdmi_codec_prepare() invoke the runtime resume of codec which just + * increments the PM runtime usage count of the codec since the device + * is in use already + * 2. skl_suspend() powers down the display (refcount-- -> 0) + * + * Wakeup from S3, + * 1. skl_resume() powers up the display (refcount++ -> 1) + * 2. hdmi_codec_complete() invokes the runtime suspend of codec which just + * decrements the PM runtime usage count of the codec since the device + * is in use already + * + * Once playback is stopped, the display refcount is set to 0 as explained + * above in the HDMI playback sequence. The PM handlings are designed in + * such way that to balance the refcount of display power when the codec + * device put to S3 while playback is going on. + * + * S0/S3 Cycle without playback in progress + * ---------------------------------------- + * Entering to S3, + * 1. hdmi_codec_prepare() invoke the runtime resume of codec + * 2. skl_runtime_resume() invoked + * 3. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1) + * 4. skl_suspend() powers down the display (refcount-- -> 0) + * + * Wakeup from S3, + * 1. skl_resume() powers up the display (refcount++ -> 1) + * 2. hdmi_codec_complete() invokes the runtime suspend of codec + * 3. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0) + * 4. skl_runtime_suspend() invoked + */ static int hdac_hdmi_runtime_suspend(struct device *dev) { struct hdac_ext_device *edev = to_hda_ext_device(dev); -- cgit v1.2.3 From 868e49a4a00afaca07d2c450a02e49581eaece6c Mon Sep 17 00:00:00 2001 From: Stuart Henderson Date: Thu, 19 Jul 2018 11:50:37 +0100 Subject: ASoC: wm_adsp: Ensure DSP boot work complete before preloader_put return All controls derived from the loaded firmware should be created prior to returning from the preloader's put function, such that they are immediately available to user-space. Signed-off-by: Stuart Henderson Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index b7b914963c62..4e7f8525449e 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -2672,6 +2672,8 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, snd_soc_dapm_sync(dapm); + flush_work(&dsp->boot_work); + return 0; } EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put); -- cgit v1.2.3 From 517ee74e1b3124b696f293aa4e220418f8125b4c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 Jul 2018 11:50:35 +0100 Subject: ASoC: wm_adsp: Correct algorithm list allocation size Commit 6396bb221514 ("treewide: kzalloc() -> kcalloc()") was overlooked when doing some refactoring to the algorithm list handling, which lead to twice as much buffer being allocated as required for reading the algorithm list. A kcalloc is no longer appropriate since the allocation size is now in bytes not registers, as such change back to kzalloc. Fixes: 7f7cca08abf4 ("ASoC: wm_adsp: Simplify handling of alg offset and length") Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 07c17acc8a4f..99108d18de8d 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1906,7 +1906,7 @@ static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs, /* Convert length from DSP words to bytes */ len *= sizeof(u32); - alg = kcalloc(len, 2, GFP_KERNEL | GFP_DMA); + alg = kzalloc(len, GFP_KERNEL | GFP_DMA); if (!alg) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From b7ede5af62ab6bfad0980fad58e82d3fb56866df Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 Jul 2018 11:50:36 +0100 Subject: ASoC: wm_adsp: Take prefix into account in control name length Currently when creating ALSA control names for the DSP the length of any prefix applied to the CODEC is not taken into account. Whilst this is mostly harmless it does result in ALSA doing the truncation of the control names and printing a warning. It is better to have the driver do the truncation so it can truncate from the start of parameter name itself to give a greater chance of the result maintain a unique name. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 99108d18de8d..eec73c98a141 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1343,6 +1343,9 @@ static int wm_adsp_create_control(struct wm_adsp *dsp, int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2; int skip = 0; + if (dsp->component->name_prefix) + avail -= strlen(dsp->component->name_prefix) + 1; + if (subname_len > avail) skip = subname_len - avail; -- cgit v1.2.3 From 3bbc2705a3d132b9a86a0e4083f82a2b3c9bfdfd Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Thu, 19 Jul 2018 11:50:38 +0100 Subject: ASoC: wm_adsp: Allow up to 8 channels for voice control Newer voice control firmwares can capture multiple audio channels. Allow up to 8 channels for future-proofing. Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index eec73c98a141..aeb1b8c27670 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -418,7 +418,7 @@ static const struct wm_adsp_fw_caps ctrl_caps[] = { { .id = SND_AUDIOCODEC_BESPOKE, .desc = { - .max_ch = 1, + .max_ch = 8, .sample_rates = { 16000 }, .num_sample_rates = 1, .formats = SNDRV_PCM_FMTBIT_S16_LE, -- cgit v1.2.3 From d52ed4b0bc73c1c7816f5b7a36229a95acfc76c8 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Thu, 19 Jul 2018 11:50:39 +0100 Subject: ASoC: wm_adsp: Parse HOST_BUFFER controls Currently the compressed streams in DSP firmwares are identified essentially by looking at a fixed location inside the firmware. This is fragile and also limits things to a single compressed stream. Here a new form of firmware parameter is added, the HOST_BUFFER which identifies a compressed stream from meta-data in the firmware file. This is more robust and allows for the possiblity of using multiple streams per core in the future. Currently the implementation is still limited to a single stream and will use the first HOST_BUFFER parameter encountered. If there aren't any HOST_BUFFER parameters it will fall back to the legacy way of finding the host buffer. Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 66 +++++++++++++++++++++++++++++++++++++++++++++- sound/soc/codecs/wmfw.h | 1 + 2 files changed, 66 insertions(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index aeb1b8c27670..e39b0e0b04df 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1607,6 +1607,15 @@ static int wm_adsp_parse_coeff(struct wm_adsp *dsp, if (ret) return -EINVAL; break; + case WMFW_CTL_TYPE_HOST_BUFFER: + ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk, + WMFW_CTL_FLAG_SYS | + WMFW_CTL_FLAG_VOLATILE | + WMFW_CTL_FLAG_READABLE, + 0); + if (ret) + return -EINVAL; + break; default: adsp_err(dsp, "Unknown control type: %d\n", coeff_blk.ctl_type); @@ -3200,7 +3209,7 @@ static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf, buf->host_buf_ptr + field_offset, data); } -static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf) +static int wm_adsp_legacy_host_buf_addr(struct wm_adsp_compr_buf *buf) { struct wm_adsp_alg_region *alg_region; struct wm_adsp *dsp = buf->dsp; @@ -3239,6 +3248,61 @@ static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf) return 0; } +static struct wm_coeff_ctl * +wm_adsp_find_host_buffer_ctrl(struct wm_adsp_compr_buf *buf) +{ + struct wm_adsp *dsp = buf->dsp; + struct wm_coeff_ctl *ctl; + + list_for_each_entry(ctl, &dsp->ctl_list, list) { + if (ctl->type != WMFW_CTL_TYPE_HOST_BUFFER) + continue; + + if (!ctl->enabled) + continue; + + return ctl; + } + + return NULL; +} + +static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf) +{ + struct wm_adsp *dsp = buf->dsp; + struct wm_coeff_ctl *ctl; + unsigned int reg; + u32 val; + int i, ret; + + ctl = wm_adsp_find_host_buffer_ctrl(buf); + if (!ctl) + return wm_adsp_legacy_host_buf_addr(buf); + + ret = wm_coeff_base_reg(ctl, ®); + if (ret) + return ret; + + for (i = 0; i < 5; ++i) { + ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); + if (ret < 0) + return ret; + + if (val) + break; + + usleep_range(1000, 2000); + } + + if (!val) + return -EIO; + + buf->host_buf_ptr = be32_to_cpu(val); + adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr); + + return 0; +} + static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf) { const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps; diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h index ec78b9da020f..0c3f50acb8b1 100644 --- a/sound/soc/codecs/wmfw.h +++ b/sound/soc/codecs/wmfw.h @@ -29,6 +29,7 @@ /* Non-ALSA coefficient types start at 0x1000 */ #define WMFW_CTL_TYPE_ACKED 0x1000 /* acked control */ #define WMFW_CTL_TYPE_HOSTEVENT 0x1001 /* event control */ +#define WMFW_CTL_TYPE_HOST_BUFFER 0x1002 /* host buffer pointer */ struct wmfw_header { char magic[4]; -- cgit v1.2.3 From eea1662525bd4a158a67ac836b2a1fd9cf77cc81 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 18 Jul 2018 22:55:37 +0200 Subject: ASoC: rt5651: Add IN3 Boost volume control Add a mixer control for the IN3 Boost volume, IN3 is used for the headset mic on most devices, so this is necessary to control the headset mic volume. Signed-off-by: Hans de Goede Signed-off-by: Mark Brown --- sound/soc/codecs/rt5651.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 0462049e739c..985852fd9723 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -331,11 +331,13 @@ static const struct snd_kcontrol_new rt5651_snd_controls[] = { SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5651_DAC2_DIG_VOL, RT5651_L_VOL_SFT, RT5651_R_VOL_SFT, 175, 0, dac_vol_tlv), - /* IN1/IN2 Control */ + /* IN1/IN2/IN3 Control */ SOC_SINGLE_TLV("IN1 Boost", RT5651_IN1_IN2, RT5651_BST_SFT1, 8, 0, bst_tlv), SOC_SINGLE_TLV("IN2 Boost", RT5651_IN1_IN2, RT5651_BST_SFT2, 8, 0, bst_tlv), + SOC_SINGLE_TLV("IN3 Boost", RT5651_IN3, + RT5651_BST_SFT1, 8, 0, bst_tlv), /* INL/INR Volume Control */ SOC_DOUBLE_TLV("IN Capture Volume", RT5651_INL1_INR1_VOL, RT5651_INL_VOL_SFT, RT5651_INR_VOL_SFT, -- cgit v1.2.3 From d96f8bd28cd0bae3e6702ae90df593628ef6906f Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Tue, 24 Jul 2018 15:49:23 +0800 Subject: ASoC: rt5514: Fix the issue of the delay volume applied The patch fixes the issue of the delay volume applied. Signed-off-by: Oder Chiou Signed-off-by: Mark Brown --- sound/soc/codecs/rt5514.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c index 1570b91bf018..dca82dd6e3bf 100644 --- a/sound/soc/codecs/rt5514.c +++ b/sound/soc/codecs/rt5514.c @@ -64,8 +64,8 @@ static const struct reg_sequence rt5514_patch[] = { {RT5514_ANA_CTRL_LDO10, 0x00028604}, {RT5514_ANA_CTRL_ADCFED, 0x00000800}, {RT5514_ASRC_IN_CTRL1, 0x00000003}, - {RT5514_DOWNFILTER0_CTRL3, 0x10000362}, - {RT5514_DOWNFILTER1_CTRL3, 0x10000362}, + {RT5514_DOWNFILTER0_CTRL3, 0x10000352}, + {RT5514_DOWNFILTER1_CTRL3, 0x10000352}, }; static const struct reg_default rt5514_reg[] = { @@ -92,10 +92,10 @@ static const struct reg_default rt5514_reg[] = { {RT5514_ASRC_IN_CTRL1, 0x00000003}, {RT5514_DOWNFILTER0_CTRL1, 0x00020c2f}, {RT5514_DOWNFILTER0_CTRL2, 0x00020c2f}, - {RT5514_DOWNFILTER0_CTRL3, 0x10000362}, + {RT5514_DOWNFILTER0_CTRL3, 0x10000352}, {RT5514_DOWNFILTER1_CTRL1, 0x00020c2f}, {RT5514_DOWNFILTER1_CTRL2, 0x00020c2f}, - {RT5514_DOWNFILTER1_CTRL3, 0x10000362}, + {RT5514_DOWNFILTER1_CTRL3, 0x10000352}, {RT5514_ANA_CTRL_LDO10, 0x00028604}, {RT5514_ANA_CTRL_LDO18_16, 0x02000345}, {RT5514_ANA_CTRL_ADC12, 0x0000a2a8}, -- cgit v1.2.3 From d77a760842751eb620a7e74f74e5a5ad6b3d6cef Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Fri, 20 Jul 2018 09:48:20 +0800 Subject: ASoC: rt5631: add Volume to the name of volume control add Volume to the name of volume control. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5631.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index cf6dce69eb2a..e52e4670cf65 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -229,10 +229,10 @@ static SOC_ENUM_SINGLE_DECL(rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG, static const struct snd_kcontrol_new rt5631_snd_controls[] = { /* MIC */ SOC_ENUM("MIC1 Mode Control", rt5631_mic1_mode_enum), - SOC_SINGLE_TLV("MIC1 Boost", RT5631_MIC_CTRL_2, + SOC_SINGLE_TLV("MIC1 Boost Volume", RT5631_MIC_CTRL_2, RT5631_MIC1_BOOST_SHIFT, 8, 0, mic_bst_tlv), SOC_ENUM("MIC2 Mode Control", rt5631_mic2_mode_enum), - SOC_SINGLE_TLV("MIC2 Boost", RT5631_MIC_CTRL_2, + SOC_SINGLE_TLV("MIC2 Boost Volume", RT5631_MIC_CTRL_2, RT5631_MIC2_BOOST_SHIFT, 8, 0, mic_bst_tlv), /* MONO IN */ SOC_ENUM("MONOIN Mode Control", rt5631_monoin_mode_enum), -- cgit v1.2.3 From 79b8a50813a80ac15fdcdc96674098dee15eaaf5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:17:21 +0200 Subject: ASoC: pcm186x: Declare PCM format with snd_pcm_format_t The PCM format type is with __bitwise, so we should use the dedicated snd_pcm_format_t instead of int. This fixes the sparse warning like: sound/soc/codecs/pcm186x.c:268:44: warning: incorrect type in initializer (different base types) Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/soc/codecs/pcm186x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/pcm186x.c b/sound/soc/codecs/pcm186x.c index 88fde70b1e9e..690c26e7389e 100644 --- a/sound/soc/codecs/pcm186x.c +++ b/sound/soc/codecs/pcm186x.c @@ -265,7 +265,7 @@ static int pcm186x_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct pcm186x_priv *priv = snd_soc_component_get_drvdata(component); unsigned int rate = params_rate(params); - unsigned int format = params_format(params); + snd_pcm_format_t format = params_format(params); unsigned int width = params_width(params); unsigned int channels = params_channels(params); unsigned int div_lrck; -- cgit v1.2.3 From c9c9780d8fa526a124933134a7e4041fa09662f6 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Sat, 28 Jul 2018 14:30:17 +0200 Subject: ASoC: wm8988: fix typo in rate constraints Remove duplicated entry and add missing zero in rate constraints. Signed-off-by: Ladislav Michl Signed-off-by: Mark Brown --- sound/soc/codecs/wm8988.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 62200117444b..6e52c6a8bab3 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -522,7 +522,7 @@ static inline int get_coeff(int mclk, int rate) /* The set of rates we can generate from the above for each SYSCLK */ static const unsigned int rates_12288[] = { - 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000, + 8000, 12000, 16000, 24000, 32000, 48000, 96000, }; static const struct snd_pcm_hw_constraint_list constraints_12288 = { @@ -540,7 +540,7 @@ static const struct snd_pcm_hw_constraint_list constraints_112896 = { }; static const unsigned int rates_12[] = { - 8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000, + 8000, 11025, 12000, 16000, 22050, 24000, 32000, 41100, 48000, 48000, 88235, 96000, }; -- cgit v1.2.3 From fe209b97184f577b70ae0799c2b149be36092f84 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 Jul 2018 07:51:41 +0000 Subject: ASoC: ak4642: convert to SPDX identifiers As original license mentioned, it is GPL-2.0 in SPDX. Then, MODULE_LICENSE() should be "GPL v2" instead of "GPL". See ${LINUX}/include/linux/module.h "GPL" [GNU Public License v2 or later] "GPL v2" [GNU Public License v2] Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/ak4642.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 605055964529..353237025514 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -1,17 +1,13 @@ -/* - * ak4642.c -- AK4642/AK4643 ALSA Soc Audio driver - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Kuninori Morimoto - * - * Based on wm8731.c by Richard Purdie - * Based on ak4535.c by Richard Purdie - * Based on wm8753.c by Liam Girdwood - * - * 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. - */ +// SPDX-License-Identifier: GPL-2.0 +// +// ak4642.c -- AK4642/AK4643 ALSA Soc Audio driver +// +// Copyright (C) 2009 Renesas Solutions Corp. +// Kuninori Morimoto +// +// Based on wm8731.c by Richard Purdie +// Based on ak4535.c by Richard Purdie +// Based on wm8753.c by Liam Girdwood /* ** CAUTION ** * @@ -709,4 +705,4 @@ module_i2c_driver(ak4642_i2c_driver); MODULE_DESCRIPTION("Soc AK4642 driver"); MODULE_AUTHOR("Kuninori Morimoto "); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 7a968dc66aecaaea3424ca2525b758687b39bc0e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 Jul 2018 07:52:15 +0000 Subject: ASoC: ak4554: convert to SPDX identifiers As original license mentioned, it is GPL-2.0 in SPDX. Then, MODULE_LICENSE() should be "GPL v2" instead of "GPL". See ${LINUX}/include/linux/module.h "GPL" [GNU Public License v2 or later] "GPL v2" [GNU Public License v2] Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/ak4554.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/ak4554.c b/sound/soc/codecs/ak4554.c index b7ee13406d93..2fa83a1a84cf 100644 --- a/sound/soc/codecs/ak4554.c +++ b/sound/soc/codecs/ak4554.c @@ -1,13 +1,8 @@ -/* - * ak4554.c - * - * Copyright (C) 2013 Renesas Solutions Corp. - * Kuninori Morimoto - * - * 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. - */ +// SPDX-License-Identifier: GPL-2.0 +// ak4554.c +// +// Copyright (C) 2013 Renesas Solutions Corp. +// Kuninori Morimoto #include #include @@ -97,6 +92,6 @@ static struct platform_driver ak4554_driver = { }; module_platform_driver(ak4554_driver); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("SoC AK4554 driver"); MODULE_AUTHOR("Kuninori Morimoto "); -- cgit v1.2.3 From c0ca5604d43233b0f5cfb793be9638af21f5535d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 Jul 2018 07:52:46 +0000 Subject: ASoC: da7210: convert to SPDX identifiers Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/da7210.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index a664111b7184..e172913d04a4 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -1,19 +1,14 @@ -/* - * DA7210 ALSA Soc codec driver - * - * Copyright (c) 2009 Dialog Semiconductor - * Written by David Chen - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Cleanups by Kuninori Morimoto - * - * Tested on SuperH Ecovec24 board with S16/S24 LE in 48KHz using I2S - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// DA7210 ALSA Soc codec driver +// +// Copyright (c) 2009 Dialog Semiconductor +// Written by David Chen +// +// Copyright (C) 2009 Renesas Solutions Corp. +// Cleanups by Kuninori Morimoto +// +// Tested on SuperH Ecovec24 board with S16/S24 LE in 48KHz using I2S #include #include -- cgit v1.2.3 From e028937c77f44bb38cdbc464afce2bf41d96006b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 Jul 2018 07:53:08 +0000 Subject: ASoC: ak4613: convert to SPDX identifiers Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/ak4613.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index 8523ff9351cf..c1181a20714d 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -1,18 +1,14 @@ -/* - * ak4613.c -- Asahi Kasei ALSA Soc Audio driver - * - * Copyright (C) 2015 Renesas Electronics Corporation - * Kuninori Morimoto - * - * Based on ak4642.c by Kuninori Morimoto - * Based on wm8731.c by Richard Purdie - * Based on ak4535.c by Richard Purdie - * Based on wm8753.c by Liam Girdwood - * - * 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. - */ +// SPDX-License-Identifier: GPL-2.0 +// +// ak4613.c -- Asahi Kasei ALSA Soc Audio driver +// +// Copyright (C) 2015 Renesas Electronics Corporation +// Kuninori Morimoto +// +// Based on ak4642.c by Kuninori Morimoto +// Based on wm8731.c by Richard Purdie +// Based on ak4535.c by Richard Purdie +// Based on wm8753.c by Liam Girdwood #include #include -- cgit v1.2.3 From e57d4ca882e289a2ddc844e82fa33ad1453e9871 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 27 Jul 2018 13:18:00 +0100 Subject: ASoC: wcd9335: add support to wcd9335 codec Qualcomm WCD9335 Codec is a standalone Hi-Fi audio codec IC, It supports both I2S/I2C and SLIMbus audio interfaces. On slimbus interface it supports two data lanes; 16 Tx ports and 8 Rx ports. It has Seven DACs and nine dedicated interpolators, Seven (six audio ADCs, and one VBAT ADC), Multibutton headset control (MBHC), Active noise cancellation and Sidetone paths and processing. This patchset adds very basic support for playback and capture via the 9 interpolators and ADC respectively. Signed-off-by: Srinivas Kandagatla Reviewed-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/wcd9335.c | 1154 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1161 insertions(+) create mode 100644 sound/soc/codecs/wcd9335.c (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index efb095dbcd71..cb09abf18dde 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1066,6 +1066,11 @@ config SND_SOC_UDA1380 tristate depends on I2C +config SND_SOC_WCD9335 + tristate "WCD9335 Codec" + depends on MFD_WCD9335 + tristate + config SND_SOC_WL1273 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 7ae7c85e8219..01410b63daac 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -192,6 +192,7 @@ snd-soc-twl4030-objs := twl4030.o snd-soc-twl6040-objs := twl6040.o snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o +snd-soc-wcd9335-objs := wcd9335.o snd-soc-wl1273-objs := wl1273.o snd-soc-wm-adsp-objs := wm_adsp.o snd-soc-wm0010-objs := wm0010.o @@ -451,6 +452,7 @@ obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o +obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o obj-$(CONFIG_SND_SOC_WM0010) += snd-soc-wm0010.o obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c new file mode 100644 index 000000000000..bd9de5d45fa9 --- /dev/null +++ b/sound/soc/codecs/wcd9335.c @@ -0,0 +1,1154 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +// Copyright (c) 2017-2018, Linaro Limited + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WCD9335_RATES_MASK (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) +/* Fractional Rates */ +#define WCD9335_FRAC_RATES_MASK (SNDRV_PCM_RATE_44100) +#define WCD9335_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE) + +/* slave port water mark level + * (0: 6bytes, 1: 9bytes, 2: 12 bytes, 3: 15 bytes) + */ +#define SLAVE_PORT_WATER_MARK_6BYTES 0 +#define SLAVE_PORT_WATER_MARK_9BYTES 1 +#define SLAVE_PORT_WATER_MARK_12BYTES 2 +#define SLAVE_PORT_WATER_MARK_15BYTES 3 +#define SLAVE_PORT_WATER_MARK_SHIFT 1 +#define SLAVE_PORT_ENABLE 1 +#define SLAVE_PORT_DISABLE 0 +#define WCD9335_SLIM_WATER_MARK_VAL \ + ((SLAVE_PORT_WATER_MARK_12BYTES << SLAVE_PORT_WATER_MARK_SHIFT) | \ + (SLAVE_PORT_ENABLE)) + +#define WCD9335_SLIM_NUM_PORT_REG 3 +#define WCD9335_SLIM_PGD_PORT_INT_TX_EN0 (WCD9335_SLIM_PGD_PORT_INT_EN0 + 2) + +#define WCD9335_MCLK_CLK_12P288MHZ 12288000 +#define WCD9335_MCLK_CLK_9P6MHZ 9600000 + +#define WCD9335_SLIM_CLOSE_TIMEOUT 1000 +#define WCD9335_SLIM_IRQ_OVERFLOW (1 << 0) +#define WCD9335_SLIM_IRQ_UNDERFLOW (1 << 1) +#define WCD9335_SLIM_IRQ_PORT_CLOSED (1 << 2) + +#define WCD9335_NUM_INTERPOLATORS 9 +#define WCD9335_RX_START 16 +#define WCD9335_SLIM_CH_START 128 + +#define WCD9335_SLIM_RX_CH(p) \ + {.port = p + WCD9335_RX_START, .shift = p,} + +/* vout step value */ +#define WCD9335_CALCULATE_VOUT_D(req_mv) (((req_mv - 650) * 10) / 25) + +enum { + WCD9335_RX0 = 0, + WCD9335_RX1, + WCD9335_RX2, + WCD9335_RX3, + WCD9335_RX4, + WCD9335_RX5, + WCD9335_RX6, + WCD9335_RX7, + WCD9335_RX8, + WCD9335_RX9, + WCD9335_RX10, + WCD9335_RX11, + WCD9335_RX12, + WCD9335_RX_MAX, +}; + +enum { + SIDO_SOURCE_INTERNAL = 0, + SIDO_SOURCE_RCO_BG, +}; + +enum wcd9335_sido_voltage { + SIDO_VOLTAGE_SVS_MV = 950, + SIDO_VOLTAGE_NOMINAL_MV = 1100, +}; + +enum { + AIF1_PB = 0, + AIF1_CAP, + AIF2_PB, + AIF2_CAP, + AIF3_PB, + AIF3_CAP, + AIF4_PB, + NUM_CODEC_DAIS, +}; + +enum { + INTn_2_INP_SEL_ZERO = 0, + INTn_2_INP_SEL_RX0, + INTn_2_INP_SEL_RX1, + INTn_2_INP_SEL_RX2, + INTn_2_INP_SEL_RX3, + INTn_2_INP_SEL_RX4, + INTn_2_INP_SEL_RX5, + INTn_2_INP_SEL_RX6, + INTn_2_INP_SEL_RX7, + INTn_2_INP_SEL_PROXIMITY, +}; + +enum { + INTn_1_MIX_INP_SEL_ZERO = 0, + INTn_1_MIX_INP_SEL_DEC0, + INTn_1_MIX_INP_SEL_DEC1, + INTn_1_MIX_INP_SEL_IIR0, + INTn_1_MIX_INP_SEL_IIR1, + INTn_1_MIX_INP_SEL_RX0, + INTn_1_MIX_INP_SEL_RX1, + INTn_1_MIX_INP_SEL_RX2, + INTn_1_MIX_INP_SEL_RX3, + INTn_1_MIX_INP_SEL_RX4, + INTn_1_MIX_INP_SEL_RX5, + INTn_1_MIX_INP_SEL_RX6, + INTn_1_MIX_INP_SEL_RX7, + +}; + +enum wcd_clock_type { + WCD_CLK_OFF, + WCD_CLK_RCO, + WCD_CLK_MCLK, +}; + +struct wcd9335_slim_ch { + u32 ch_num; + u16 port; + u16 shift; + struct list_head list; +}; + +struct wcd_slim_codec_dai_data { + struct list_head slim_ch_list; + struct slim_stream_config sconfig; + struct slim_stream_runtime *sruntime; +}; + +struct wcd9335_codec { + struct device *dev; + struct clk *mclk; + struct clk *native_clk; + u32 mclk_rate; + u8 intf_type; + u8 version; + + struct slim_device *slim; + struct slim_device *slim_ifd; + struct regmap *regmap; + struct regmap *if_regmap; + struct regmap_irq_chip_data *irq_data; + + struct wcd9335_slim_ch rx_chs[WCD9335_RX_MAX]; + u32 num_rx_port; + + int sido_input_src; + enum wcd9335_sido_voltage sido_voltage; + + struct wcd_slim_codec_dai_data dai[NUM_CODEC_DAIS]; + struct snd_soc_component *component; + + int master_bias_users; + int clk_mclk_users; + int clk_rco_users; + int sido_ccl_cnt; + enum wcd_clock_type clk_type; + + u32 hph_mode; +}; + +static const struct wcd9335_slim_ch wcd9335_rx_chs[WCD9335_RX_MAX] = { + WCD9335_SLIM_RX_CH(0), /* 16 */ + WCD9335_SLIM_RX_CH(1), /* 17 */ + WCD9335_SLIM_RX_CH(2), + WCD9335_SLIM_RX_CH(3), + WCD9335_SLIM_RX_CH(4), + WCD9335_SLIM_RX_CH(5), + WCD9335_SLIM_RX_CH(6), + WCD9335_SLIM_RX_CH(7), + WCD9335_SLIM_RX_CH(8), + WCD9335_SLIM_RX_CH(9), + WCD9335_SLIM_RX_CH(10), + WCD9335_SLIM_RX_CH(11), + WCD9335_SLIM_RX_CH(12), +}; + +struct interp_sample_rate { + int rate; + int rate_val; +}; + +static struct interp_sample_rate int_mix_rate_val[] = { + {48000, 0x4}, /* 48K */ + {96000, 0x5}, /* 96K */ + {192000, 0x6}, /* 192K */ +}; + +static struct interp_sample_rate int_prim_rate_val[] = { + {8000, 0x0}, /* 8K */ + {16000, 0x1}, /* 16K */ + {24000, -EINVAL},/* 24K */ + {32000, 0x3}, /* 32K */ + {48000, 0x4}, /* 48K */ + {96000, 0x5}, /* 96K */ + {192000, 0x6}, /* 192K */ + {384000, 0x7}, /* 384K */ + {44100, 0x8}, /* 44.1K */ +}; + +struct wcd9335_reg_mask_val { + u16 reg; + u8 mask; + u8 val; +}; + +static const struct wcd9335_reg_mask_val wcd9335_codec_reg_init_val_2_0[] = { + {WCD9335_RCO_CTRL_2, 0x0F, 0x08}, + {WCD9335_RX_BIAS_FLYB_MID_RST, 0xF0, 0x10}, + {WCD9335_FLYBACK_CTRL_1, 0x20, 0x20}, + {WCD9335_HPH_OCP_CTL, 0xFF, 0x5A}, + {WCD9335_HPH_L_TEST, 0x01, 0x01}, + {WCD9335_HPH_R_TEST, 0x01, 0x01}, + {WCD9335_CDC_BOOST0_BOOST_CFG1, 0x3F, 0x12}, + {WCD9335_CDC_BOOST0_BOOST_CFG2, 0x1C, 0x08}, + {WCD9335_CDC_COMPANDER7_CTL7, 0x1E, 0x18}, + {WCD9335_CDC_BOOST1_BOOST_CFG1, 0x3F, 0x12}, + {WCD9335_CDC_BOOST1_BOOST_CFG2, 0x1C, 0x08}, + {WCD9335_CDC_COMPANDER8_CTL7, 0x1E, 0x18}, + {WCD9335_CDC_TX0_TX_PATH_SEC7, 0xFF, 0x45}, + {WCD9335_CDC_RX0_RX_PATH_SEC0, 0xFC, 0xF4}, + {WCD9335_HPH_REFBUFF_LP_CTL, 0x08, 0x08}, + {WCD9335_HPH_REFBUFF_LP_CTL, 0x06, 0x02}, +}; + +static const struct wcd9335_reg_mask_val wcd9335_codec_reg_init_common_val[] = { + /* Rbuckfly/R_EAR(32) */ + {WCD9335_CDC_CLSH_K2_MSB, 0x0F, 0x00}, + {WCD9335_CDC_CLSH_K2_LSB, 0xFF, 0x60}, + {WCD9335_CPE_SS_DMIC_CFG, 0x80, 0x00}, + {WCD9335_CDC_BOOST0_BOOST_CTL, 0x70, 0x50}, + {WCD9335_CDC_BOOST1_BOOST_CTL, 0x70, 0x50}, + {WCD9335_CDC_RX7_RX_PATH_CFG1, 0x08, 0x08}, + {WCD9335_CDC_RX8_RX_PATH_CFG1, 0x08, 0x08}, + {WCD9335_ANA_LO_1_2, 0x3C, 0X3C}, + {WCD9335_DIFF_LO_COM_SWCAP_REFBUF_FREQ, 0x70, 0x00}, + {WCD9335_DIFF_LO_COM_PA_FREQ, 0x70, 0x40}, + {WCD9335_SOC_MAD_AUDIO_CTL_2, 0x03, 0x03}, + {WCD9335_CDC_TOP_TOP_CFG1, 0x02, 0x02}, + {WCD9335_CDC_TOP_TOP_CFG1, 0x01, 0x01}, + {WCD9335_EAR_CMBUFF, 0x08, 0x00}, + {WCD9335_CDC_TX9_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, + {WCD9335_CDC_TX10_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, + {WCD9335_CDC_TX11_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, + {WCD9335_CDC_TX12_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, + {WCD9335_CDC_COMPANDER7_CTL3, 0x80, 0x80}, + {WCD9335_CDC_COMPANDER8_CTL3, 0x80, 0x80}, + {WCD9335_CDC_COMPANDER7_CTL7, 0x01, 0x01}, + {WCD9335_CDC_COMPANDER8_CTL7, 0x01, 0x01}, + {WCD9335_CDC_RX0_RX_PATH_CFG0, 0x01, 0x01}, + {WCD9335_CDC_RX1_RX_PATH_CFG0, 0x01, 0x01}, + {WCD9335_CDC_RX2_RX_PATH_CFG0, 0x01, 0x01}, + {WCD9335_CDC_RX3_RX_PATH_CFG0, 0x01, 0x01}, + {WCD9335_CDC_RX4_RX_PATH_CFG0, 0x01, 0x01}, + {WCD9335_CDC_RX5_RX_PATH_CFG0, 0x01, 0x01}, + {WCD9335_CDC_RX6_RX_PATH_CFG0, 0x01, 0x01}, + {WCD9335_CDC_RX7_RX_PATH_CFG0, 0x01, 0x01}, + {WCD9335_CDC_RX8_RX_PATH_CFG0, 0x01, 0x01}, + {WCD9335_CDC_RX0_RX_PATH_MIX_CFG, 0x01, 0x01}, + {WCD9335_CDC_RX1_RX_PATH_MIX_CFG, 0x01, 0x01}, + {WCD9335_CDC_RX2_RX_PATH_MIX_CFG, 0x01, 0x01}, + {WCD9335_CDC_RX3_RX_PATH_MIX_CFG, 0x01, 0x01}, + {WCD9335_CDC_RX4_RX_PATH_MIX_CFG, 0x01, 0x01}, + {WCD9335_CDC_RX5_RX_PATH_MIX_CFG, 0x01, 0x01}, + {WCD9335_CDC_RX6_RX_PATH_MIX_CFG, 0x01, 0x01}, + {WCD9335_CDC_RX7_RX_PATH_MIX_CFG, 0x01, 0x01}, + {WCD9335_CDC_RX8_RX_PATH_MIX_CFG, 0x01, 0x01}, + {WCD9335_VBADC_IBIAS_FE, 0x0C, 0x08}, +}; + +static int wcd9335_set_mix_interpolator_rate(struct snd_soc_dai *dai, + int rate_val, + u32 rate) +{ + struct snd_soc_component *component = dai->component; + struct wcd9335_codec *wcd = dev_get_drvdata(component->dev); + struct wcd9335_slim_ch *ch; + int val, j; + + list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list) { + for (j = 0; j < WCD9335_NUM_INTERPOLATORS; j++) { + val = snd_soc_component_read32(component, + WCD9335_CDC_RX_INP_MUX_RX_INT_CFG1(j)) & + WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK; + + if (val == (ch->shift + INTn_2_INP_SEL_RX0)) + snd_soc_component_update_bits(component, + WCD9335_CDC_RX_PATH_MIX_CTL(j), + WCD9335_CDC_MIX_PCM_RATE_MASK, + rate_val); + } + } + + return 0; +} + +static int wcd9335_set_prim_interpolator_rate(struct snd_soc_dai *dai, + u8 rate_val, + u32 rate) +{ + struct snd_soc_component *comp = dai->component; + struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev); + struct wcd9335_slim_ch *ch; + u8 cfg0, cfg1, inp0_sel, inp1_sel, inp2_sel; + int inp, j; + + list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list) { + inp = ch->shift + INTn_1_MIX_INP_SEL_RX0; + /* + * Loop through all interpolator MUX inputs and find out + * to which interpolator input, the slim rx port + * is connected + */ + for (j = 0; j < WCD9335_NUM_INTERPOLATORS; j++) { + cfg0 = snd_soc_component_read32(comp, + WCD9335_CDC_RX_INP_MUX_RX_INT_CFG0(j)); + cfg1 = snd_soc_component_read32(comp, + WCD9335_CDC_RX_INP_MUX_RX_INT_CFG1(j)); + + inp0_sel = cfg0 & WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK; + inp1_sel = (cfg0 >> 4) & WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK; + inp2_sel = (cfg1 >> 4) & WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK; + + if ((inp0_sel == inp) || (inp1_sel == inp) || + (inp2_sel == inp)) { + /* rate is in Hz */ + if ((j == 0) && (rate == 44100)) + dev_info(wcd->dev, + "Cannot set 44.1KHz on INT0\n"); + else + snd_soc_component_update_bits(comp, + WCD9335_CDC_RX_PATH_CTL(j), + WCD9335_CDC_MIX_PCM_RATE_MASK, + rate_val); + } + } + } + + return 0; +} + +static int wcd9335_set_interpolator_rate(struct snd_soc_dai *dai, u32 rate) +{ + int i; + + /* set mixing path rate */ + for (i = 0; i < ARRAY_SIZE(int_mix_rate_val); i++) { + if (rate == int_mix_rate_val[i].rate) { + wcd9335_set_mix_interpolator_rate(dai, + int_mix_rate_val[i].rate_val, rate); + break; + } + } + + /* set primary path sample rate */ + for (i = 0; i < ARRAY_SIZE(int_prim_rate_val); i++) { + if (rate == int_prim_rate_val[i].rate) { + wcd9335_set_prim_interpolator_rate(dai, + int_prim_rate_val[i].rate_val, rate); + break; + } + } + + return 0; +} + +static int wcd9335_slim_set_hw_params(struct wcd9335_codec *wcd, + struct wcd_slim_codec_dai_data *dai_data, + int direction) +{ + struct list_head *slim_ch_list = &dai_data->slim_ch_list; + struct slim_stream_config *cfg = &dai_data->sconfig; + struct wcd9335_slim_ch *ch; + u16 payload = 0; + int ret, i; + + cfg->ch_count = 0; + cfg->direction = direction; + cfg->port_mask = 0; + + /* Configure slave interface device */ + list_for_each_entry(ch, slim_ch_list, list) { + cfg->ch_count++; + payload |= 1 << ch->shift; + cfg->port_mask |= BIT(ch->port); + } + + cfg->chs = kcalloc(cfg->ch_count, sizeof(unsigned int), GFP_KERNEL); + if (!cfg->chs) + return -ENOMEM; + + i = 0; + list_for_each_entry(ch, slim_ch_list, list) { + cfg->chs[i++] = ch->ch_num; + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + /* write to interface device */ + ret = regmap_write(wcd->if_regmap, + WCD9335_SLIM_PGD_RX_PORT_MULTI_CHNL_0(ch->port), + payload); + + if (ret < 0) + goto err; + + /* configure the slave port for water mark and enable*/ + ret = regmap_write(wcd->if_regmap, + WCD9335_SLIM_PGD_RX_PORT_CFG(ch->port), + WCD9335_SLIM_WATER_MARK_VAL); + if (ret < 0) + goto err; + } + } + + dai_data->sruntime = slim_stream_allocate(wcd->slim, "WCD9335-SLIM"); + slim_stream_prepare(dai_data->sruntime, cfg); + + return 0; + +err: + dev_err(wcd->dev, "Error Setting slim hw params\n"); + kfree(cfg->chs); + cfg->chs = NULL; + + return ret; +} + +static int wcd9335_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct wcd9335_codec *wcd; + int ret; + + wcd = snd_soc_component_get_drvdata(dai->component); + + switch (substream->stream) { + case SNDRV_PCM_STREAM_PLAYBACK: + ret = wcd9335_set_interpolator_rate(dai, params_rate(params)); + if (ret) { + dev_err(wcd->dev, "cannot set sample rate: %u\n", + params_rate(params)); + return ret; + } + switch (params_width(params)) { + case 16 ... 24: + wcd->dai[dai->id].sconfig.bps = params_width(params); + break; + default: + dev_err(wcd->dev, "%s: Invalid format 0x%x\n", + __func__, params_width(params)); + return -EINVAL; + } + break; + default: + dev_err(wcd->dev, "Invalid stream type %d\n", + substream->stream); + return -EINVAL; + }; + + wcd->dai[dai->id].sconfig.rate = params_rate(params); + wcd9335_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream); + + return 0; +} + +static int wcd9335_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct wcd_slim_codec_dai_data *dai_data; + struct wcd9335_codec *wcd; + + wcd = snd_soc_component_get_drvdata(dai->component); + dai_data = &wcd->dai[dai->id]; + slim_stream_enable(dai_data->sruntime); + + return 0; +} + +static int wcd9335_set_channel_map(struct snd_soc_dai *dai, + unsigned int tx_num, unsigned int *tx_slot, + unsigned int rx_num, unsigned int *rx_slot) +{ + struct wcd9335_codec *wcd; + int i; + + wcd = snd_soc_component_get_drvdata(dai->component); + + if (!tx_slot || !rx_slot) { + dev_err(wcd->dev, "Invalid tx_slot=%p, rx_slot=%p\n", + tx_slot, rx_slot); + return -EINVAL; + } + + if (wcd->rx_chs) { + wcd->num_rx_port = rx_num; + for (i = 0; i < rx_num; i++) { + wcd->rx_chs[i].ch_num = rx_slot[i]; + INIT_LIST_HEAD(&wcd->rx_chs[i].list); + } + } + + return 0; +} + +static int wcd9335_get_channel_map(struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot) +{ + struct wcd9335_slim_ch *ch; + struct wcd9335_codec *wcd; + int i = 0; + + wcd = snd_soc_component_get_drvdata(dai->component); + + switch (dai->id) { + case AIF1_PB: + case AIF2_PB: + case AIF3_PB: + case AIF4_PB: + if (!rx_slot || !rx_num) { + dev_err(wcd->dev, "Invalid rx_slot %p or rx_num %p\n", + rx_slot, rx_num); + return -EINVAL; + } + + list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list) + rx_slot[i++] = ch->ch_num; + + *rx_num = i; + break; + default: + dev_err(wcd->dev, "Invalid DAI ID %x\n", dai->id); + break; + } + + return 0; +} + +static struct snd_soc_dai_ops wcd9335_dai_ops = { + .hw_params = wcd9335_hw_params, + .prepare = wcd9335_prepare, + .set_channel_map = wcd9335_set_channel_map, + .get_channel_map = wcd9335_get_channel_map, +}; + +static struct snd_soc_dai_driver wcd9335_slim_dais[] = { + [0] = { + .name = "wcd9335_rx1", + .id = AIF1_PB, + .playback = { + .stream_name = "AIF1 Playback", + .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK, + .formats = WCD9335_FORMATS_S16_S24_LE, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &wcd9335_dai_ops, + }, + [1] = { + .name = "wcd9335_tx1", + .id = AIF1_CAP, + .capture = { + .stream_name = "AIF1 Capture", + .rates = WCD9335_RATES_MASK, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &wcd9335_dai_ops, + }, + [2] = { + .name = "wcd9335_rx2", + .id = AIF2_PB, + .playback = { + .stream_name = "AIF2 Playback", + .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK, + .formats = WCD9335_FORMATS_S16_S24_LE, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &wcd9335_dai_ops, + }, + [3] = { + .name = "wcd9335_tx2", + .id = AIF2_CAP, + .capture = { + .stream_name = "AIF2 Capture", + .rates = WCD9335_RATES_MASK, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &wcd9335_dai_ops, + }, + [4] = { + .name = "wcd9335_rx3", + .id = AIF3_PB, + .playback = { + .stream_name = "AIF3 Playback", + .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK, + .formats = WCD9335_FORMATS_S16_S24_LE, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &wcd9335_dai_ops, + }, + [5] = { + .name = "wcd9335_tx3", + .id = AIF3_CAP, + .capture = { + .stream_name = "AIF3 Capture", + .rates = WCD9335_RATES_MASK, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &wcd9335_dai_ops, + }, + [6] = { + .name = "wcd9335_rx4", + .id = AIF4_PB, + .playback = { + .stream_name = "AIF4 Playback", + .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK, + .formats = WCD9335_FORMATS_S16_S24_LE, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &wcd9335_dai_ops, + }, +}; + +static irqreturn_t wcd9335_slimbus_irq(int irq, void *data) +{ + struct wcd9335_codec *wcd = data; + unsigned long status = 0; + int i, j, port_id; + unsigned int val, int_val = 0; + bool tx; + unsigned short reg = 0; + + for (i = WCD9335_SLIM_PGD_PORT_INT_STATUS_RX_0, j = 0; + i <= WCD9335_SLIM_PGD_PORT_INT_STATUS_TX_1; i++, j++) { + regmap_read(wcd->if_regmap, i, &val); + status |= ((u32)val << (8 * j)); + } + + for_each_set_bit(j, &status, 32) { + tx = (j >= 16 ? true : false); + port_id = (tx ? j - 16 : j); + regmap_read(wcd->if_regmap, + WCD9335_SLIM_PGD_PORT_INT_RX_SOURCE0 + j, &val); + if (val) { + if (!tx) + reg = WCD9335_SLIM_PGD_PORT_INT_EN0 + + (port_id / 8); + else + reg = WCD9335_SLIM_PGD_PORT_INT_TX_EN0 + + (port_id / 8); + regmap_read( + wcd->if_regmap, reg, &int_val); + /* + * Ignore interrupts for ports for which the + * interrupts are not specifically enabled. + */ + if (!(int_val & (1 << (port_id % 8)))) + continue; + } + if (val & WCD9335_SLIM_IRQ_OVERFLOW) + dev_err_ratelimited(wcd->dev, + "%s: overflow error on %s port %d, value %x\n", + __func__, (tx ? "TX" : "RX"), port_id, val); + if (val & WCD9335_SLIM_IRQ_UNDERFLOW) + dev_err_ratelimited(wcd->dev, + "%s: underflow error on %s port %d, value %x\n", + __func__, (tx ? "TX" : "RX"), port_id, val); + if ((val & WCD9335_SLIM_IRQ_OVERFLOW) || + (val & WCD9335_SLIM_IRQ_UNDERFLOW)) { + if (!tx) + reg = WCD9335_SLIM_PGD_PORT_INT_EN0 + + (port_id / 8); + else + reg = WCD9335_SLIM_PGD_PORT_INT_TX_EN0 + + (port_id / 8); + regmap_read( + wcd->if_regmap, reg, &int_val); + if (int_val & (1 << (port_id % 8))) { + int_val = int_val ^ (1 << (port_id % 8)); + regmap_write(wcd->if_regmap, + reg, int_val); + } + } + + regmap_write(wcd->if_regmap, + WCD9335_SLIM_PGD_PORT_INT_CLR_RX_0 + (j / 8), + BIT(j % 8)); + } + + return IRQ_HANDLED; +} + +static int wcd9335_setup_irqs(struct wcd9335_codec *wcd) +{ + int slim_irq = regmap_irq_get_virq(wcd->irq_data, WCD9335_IRQ_SLIMBUS); + int i, ret = 0; + + ret = request_threaded_irq(slim_irq, NULL, wcd9335_slimbus_irq, + IRQF_TRIGGER_RISING, "SLIMBus Slave", wcd); + if (ret) { + dev_err(wcd->dev, "Failed to request SLIMBUS irq\n"); + return ret; + } + + /* enable interrupts on all slave ports */ + for (i = 0; i < WCD9335_SLIM_NUM_PORT_REG; i++) + regmap_write(wcd->if_regmap, WCD9335_SLIM_PGD_PORT_INT_EN0 + i, + 0xFF); + + return ret; +} + +static void wcd9335_cdc_sido_ccl_enable(struct wcd9335_codec *wcd, + bool ccl_flag) +{ + struct snd_soc_component *comp = wcd->component; + + if (ccl_flag) { + if (++wcd->sido_ccl_cnt == 1) + snd_soc_component_write(comp, WCD9335_SIDO_SIDO_CCL_10, + WCD9335_SIDO_SIDO_CCL_DEF_VALUE); + } else { + if (wcd->sido_ccl_cnt == 0) { + dev_err(wcd->dev, "sido_ccl already disabled\n"); + return; + } + if (--wcd->sido_ccl_cnt == 0) + snd_soc_component_write(comp, WCD9335_SIDO_SIDO_CCL_10, + WCD9335_SIDO_SIDO_CCL_10_ICHARG_PWR_SEL_C320FF); + } +} + +static int wcd9335_enable_master_bias(struct wcd9335_codec *wcd) +{ + wcd->master_bias_users++; + if (wcd->master_bias_users == 1) { + regmap_update_bits(wcd->regmap, WCD9335_ANA_BIAS, + WCD9335_ANA_BIAS_EN_MASK, + WCD9335_ANA_BIAS_ENABLE); + regmap_update_bits(wcd->regmap, WCD9335_ANA_BIAS, + WCD9335_ANA_BIAS_PRECHRG_EN_MASK, + WCD9335_ANA_BIAS_PRECHRG_ENABLE); + /* + * 1ms delay is required after pre-charge is enabled + * as per HW requirement + */ + usleep_range(1000, 1100); + regmap_update_bits(wcd->regmap, WCD9335_ANA_BIAS, + WCD9335_ANA_BIAS_PRECHRG_EN_MASK, + WCD9335_ANA_BIAS_PRECHRG_DISABLE); + regmap_update_bits(wcd->regmap, WCD9335_ANA_BIAS, + WCD9335_ANA_BIAS_PRECHRG_CTL_MODE, + WCD9335_ANA_BIAS_PRECHRG_CTL_MODE_MANUAL); + } + + return 0; +} + +static int wcd9335_enable_mclk(struct wcd9335_codec *wcd) +{ + /* Enable mclk requires master bias to be enabled first */ + if (wcd->master_bias_users <= 0) + return -EINVAL; + + if (((wcd->clk_mclk_users == 0) && (wcd->clk_type == WCD_CLK_MCLK)) || + ((wcd->clk_mclk_users > 0) && (wcd->clk_type != WCD_CLK_MCLK))) { + dev_err(wcd->dev, "Error enabling MCLK, clk_type: %d\n", + wcd->clk_type); + return -EINVAL; + } + + if (++wcd->clk_mclk_users == 1) { + regmap_update_bits(wcd->regmap, WCD9335_ANA_CLK_TOP, + WCD9335_ANA_CLK_EXT_CLKBUF_EN_MASK, + WCD9335_ANA_CLK_EXT_CLKBUF_ENABLE); + regmap_update_bits(wcd->regmap, WCD9335_ANA_CLK_TOP, + WCD9335_ANA_CLK_MCLK_SRC_MASK, + WCD9335_ANA_CLK_MCLK_SRC_EXTERNAL); + regmap_update_bits(wcd->regmap, WCD9335_ANA_CLK_TOP, + WCD9335_ANA_CLK_MCLK_EN_MASK, + WCD9335_ANA_CLK_MCLK_ENABLE); + regmap_update_bits(wcd->regmap, + WCD9335_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, + WCD9335_CDC_CLK_RST_CTRL_FS_CNT_EN_MASK, + WCD9335_CDC_CLK_RST_CTRL_FS_CNT_ENABLE); + regmap_update_bits(wcd->regmap, + WCD9335_CDC_CLK_RST_CTRL_MCLK_CONTROL, + WCD9335_CDC_CLK_RST_CTRL_MCLK_EN_MASK, + WCD9335_CDC_CLK_RST_CTRL_MCLK_ENABLE); + /* + * 10us sleep is required after clock is enabled + * as per HW requirement + */ + usleep_range(10, 15); + } + + wcd->clk_type = WCD_CLK_MCLK; + + return 0; +} + +static int wcd9335_disable_mclk(struct wcd9335_codec *wcd) +{ + if (wcd->clk_mclk_users <= 0) + return -EINVAL; + + if (--wcd->clk_mclk_users == 0) { + if (wcd->clk_rco_users > 0) { + /* MCLK to RCO switch */ + regmap_update_bits(wcd->regmap, WCD9335_ANA_CLK_TOP, + WCD9335_ANA_CLK_MCLK_SRC_MASK, + WCD9335_ANA_CLK_MCLK_SRC_RCO); + wcd->clk_type = WCD_CLK_RCO; + } else { + regmap_update_bits(wcd->regmap, WCD9335_ANA_CLK_TOP, + WCD9335_ANA_CLK_MCLK_EN_MASK, + WCD9335_ANA_CLK_MCLK_DISABLE); + wcd->clk_type = WCD_CLK_OFF; + } + + regmap_update_bits(wcd->regmap, WCD9335_ANA_CLK_TOP, + WCD9335_ANA_CLK_EXT_CLKBUF_EN_MASK, + WCD9335_ANA_CLK_EXT_CLKBUF_DISABLE); + } + + return 0; +} + +static int wcd9335_disable_master_bias(struct wcd9335_codec *wcd) +{ + if (wcd->master_bias_users <= 0) + return -EINVAL; + + wcd->master_bias_users--; + if (wcd->master_bias_users == 0) { + regmap_update_bits(wcd->regmap, WCD9335_ANA_BIAS, + WCD9335_ANA_BIAS_EN_MASK, + WCD9335_ANA_BIAS_DISABLE); + regmap_update_bits(wcd->regmap, WCD9335_ANA_BIAS, + WCD9335_ANA_BIAS_PRECHRG_CTL_MODE, + WCD9335_ANA_BIAS_PRECHRG_CTL_MODE_MANUAL); + } + return 0; +} + +static int wcd9335_cdc_req_mclk_enable(struct wcd9335_codec *wcd, + bool enable) +{ + int ret = 0; + + if (enable) { + wcd9335_cdc_sido_ccl_enable(wcd, true); + ret = clk_prepare_enable(wcd->mclk); + if (ret) { + dev_err(wcd->dev, "%s: ext clk enable failed\n", + __func__); + goto err; + } + /* get BG */ + wcd9335_enable_master_bias(wcd); + /* get MCLK */ + wcd9335_enable_mclk(wcd); + + } else { + /* put MCLK */ + wcd9335_disable_mclk(wcd); + /* put BG */ + wcd9335_disable_master_bias(wcd); + clk_disable_unprepare(wcd->mclk); + wcd9335_cdc_sido_ccl_enable(wcd, false); + } +err: + return ret; +} + +static void wcd9335_codec_apply_sido_voltage(struct wcd9335_codec *wcd, + enum wcd9335_sido_voltage req_mv) +{ + struct snd_soc_component *comp = wcd->component; + int vout_d_val; + + if (req_mv == wcd->sido_voltage) + return; + + /* compute the vout_d step value */ + vout_d_val = WCD9335_CALCULATE_VOUT_D(req_mv) & + WCD9335_ANA_BUCK_VOUT_MASK; + snd_soc_component_write(comp, WCD9335_ANA_BUCK_VOUT_D, vout_d_val); + snd_soc_component_update_bits(comp, WCD9335_ANA_BUCK_CTL, + WCD9335_ANA_BUCK_CTL_RAMP_START_MASK, + WCD9335_ANA_BUCK_CTL_RAMP_START_ENABLE); + + /* 1 msec sleep required after SIDO Vout_D voltage change */ + usleep_range(1000, 1100); + wcd->sido_voltage = req_mv; + snd_soc_component_update_bits(comp, WCD9335_ANA_BUCK_CTL, + WCD9335_ANA_BUCK_CTL_RAMP_START_MASK, + WCD9335_ANA_BUCK_CTL_RAMP_START_DISABLE); +} + +static int wcd9335_codec_update_sido_voltage(struct wcd9335_codec *wcd, + enum wcd9335_sido_voltage req_mv) +{ + int ret = 0; + + /* enable mclk before setting SIDO voltage */ + ret = wcd9335_cdc_req_mclk_enable(wcd, true); + if (ret) { + dev_err(wcd->dev, "Ext clk enable failed\n"); + goto err; + } + + wcd9335_codec_apply_sido_voltage(wcd, req_mv); + wcd9335_cdc_req_mclk_enable(wcd, false); + +err: + return ret; +} + +static int _wcd9335_codec_enable_mclk(struct snd_soc_component *component, + int enable) +{ + struct wcd9335_codec *wcd = dev_get_drvdata(component->dev); + int ret; + + if (enable) { + ret = wcd9335_cdc_req_mclk_enable(wcd, true); + if (ret) + return ret; + + wcd9335_codec_apply_sido_voltage(wcd, + SIDO_VOLTAGE_NOMINAL_MV); + } else { + wcd9335_codec_update_sido_voltage(wcd, + wcd->sido_voltage); + wcd9335_cdc_req_mclk_enable(wcd, false); + } + + return 0; +} + +static void wcd9335_enable_sido_buck(struct snd_soc_component *component) +{ + struct wcd9335_codec *wcd = dev_get_drvdata(component->dev); + + snd_soc_component_update_bits(component, WCD9335_ANA_RCO, + WCD9335_ANA_RCO_BG_EN_MASK, + WCD9335_ANA_RCO_BG_ENABLE); + snd_soc_component_update_bits(component, WCD9335_ANA_BUCK_CTL, + WCD9335_ANA_BUCK_CTL_VOUT_D_IREF_MASK, + WCD9335_ANA_BUCK_CTL_VOUT_D_IREF_EXT); + /* 100us sleep needed after IREF settings */ + usleep_range(100, 110); + snd_soc_component_update_bits(component, WCD9335_ANA_BUCK_CTL, + WCD9335_ANA_BUCK_CTL_VOUT_D_VREF_MASK, + WCD9335_ANA_BUCK_CTL_VOUT_D_VREF_EXT); + /* 100us sleep needed after VREF settings */ + usleep_range(100, 110); + wcd->sido_input_src = SIDO_SOURCE_RCO_BG; +} + +static int wcd9335_enable_efuse_sensing(struct snd_soc_component *comp) +{ + _wcd9335_codec_enable_mclk(comp, true); + snd_soc_component_update_bits(comp, + WCD9335_CHIP_TIER_CTRL_EFUSE_CTL, + WCD9335_CHIP_TIER_CTRL_EFUSE_EN_MASK, + WCD9335_CHIP_TIER_CTRL_EFUSE_ENABLE); + /* + * 5ms sleep required after enabling efuse control + * before checking the status. + */ + usleep_range(5000, 5500); + + if (!(snd_soc_component_read32(comp, + WCD9335_CHIP_TIER_CTRL_EFUSE_STATUS) & + WCD9335_CHIP_TIER_CTRL_EFUSE_EN_MASK)) + WARN(1, "%s: Efuse sense is not complete\n", __func__); + + wcd9335_enable_sido_buck(comp); + _wcd9335_codec_enable_mclk(comp, false); + + return 0; +} + +static void wcd9335_codec_init(struct snd_soc_component *component) +{ + struct wcd9335_codec *wcd = dev_get_drvdata(component->dev); + int i; + + /* ungate MCLK and set clk rate */ + regmap_update_bits(wcd->regmap, WCD9335_CODEC_RPM_CLK_GATE, + WCD9335_CODEC_RPM_CLK_GATE_MCLK_GATE_MASK, 0); + + regmap_update_bits(wcd->regmap, WCD9335_CODEC_RPM_CLK_MCLK_CFG, + WCD9335_CODEC_RPM_CLK_MCLK_CFG_MCLK_MASK, + WCD9335_CODEC_RPM_CLK_MCLK_CFG_9P6MHZ); + + for (i = 0; i < ARRAY_SIZE(wcd9335_codec_reg_init_common_val); i++) + snd_soc_component_update_bits(component, + wcd9335_codec_reg_init_common_val[i].reg, + wcd9335_codec_reg_init_common_val[i].mask, + wcd9335_codec_reg_init_common_val[i].val); + + if (WCD9335_IS_2_0(wcd->version)) { + for (i = 0; i < ARRAY_SIZE(wcd9335_codec_reg_init_val_2_0); i++) + snd_soc_component_update_bits(component, + wcd9335_codec_reg_init_val_2_0[i].reg, + wcd9335_codec_reg_init_val_2_0[i].mask, + wcd9335_codec_reg_init_val_2_0[i].val); + } + + wcd9335_enable_efuse_sensing(component); +} + +static int wcd9335_codec_probe(struct snd_soc_component *component) +{ + struct wcd9335_codec *wcd = dev_get_drvdata(component->dev); + int i; + + snd_soc_component_init_regmap(component, wcd->regmap); + wcd->component = component; + + wcd9335_codec_init(component); + + for (i = 0; i < NUM_CODEC_DAIS; i++) + INIT_LIST_HEAD(&wcd->dai[i].slim_ch_list); + + return wcd9335_setup_irqs(wcd); +} + +static void wcd9335_codec_remove(struct snd_soc_component *comp) +{ + struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev); + + free_irq(regmap_irq_get_virq(wcd->irq_data, WCD9335_IRQ_SLIMBUS), wcd); +} + +static int wcd9335_codec_set_sysclk(struct snd_soc_component *comp, + int clk_id, int source, + unsigned int freq, int dir) +{ + struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev); + + wcd->mclk_rate = freq; + + if (wcd->mclk_rate == WCD9335_MCLK_CLK_12P288MHZ) + snd_soc_component_update_bits(comp, + WCD9335_CODEC_RPM_CLK_MCLK_CFG, + WCD9335_CODEC_RPM_CLK_MCLK_CFG_MCLK_MASK, + WCD9335_CODEC_RPM_CLK_MCLK_CFG_12P288MHZ); + else if (wcd->mclk_rate == WCD9335_MCLK_CLK_9P6MHZ) + snd_soc_component_update_bits(comp, + WCD9335_CODEC_RPM_CLK_MCLK_CFG, + WCD9335_CODEC_RPM_CLK_MCLK_CFG_MCLK_MASK, + WCD9335_CODEC_RPM_CLK_MCLK_CFG_9P6MHZ); + + return clk_set_rate(wcd->mclk, freq); +} + +static const struct snd_soc_component_driver wcd9335_component_drv = { + .probe = wcd9335_codec_probe, + .remove = wcd9335_codec_remove, + .set_sysclk = wcd9335_codec_set_sysclk, +}; + +static int wcd9335_probe(struct platform_device *pdev) +{ + struct wcd9335 *pdata = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct wcd9335_codec *wcd; + + wcd = devm_kzalloc(dev, sizeof(*wcd), GFP_KERNEL); + if (!wcd) + return -ENOMEM; + + dev_set_drvdata(dev, wcd); + + memcpy(wcd->rx_chs, wcd9335_rx_chs, sizeof(wcd9335_rx_chs)); + + wcd->regmap = pdata->regmap; + wcd->if_regmap = pdata->ifd_regmap; + wcd->slim = pdata->slim; + wcd->slim_ifd = pdata->slim_ifd; + wcd->irq_data = pdata->irq_data; + wcd->version = pdata->version; + wcd->intf_type = pdata->intf_type; + wcd->dev = dev; + wcd->mclk = pdata->mclk; + wcd->native_clk = pdata->native_clk; + wcd->sido_input_src = SIDO_SOURCE_INTERNAL; + wcd->sido_voltage = SIDO_VOLTAGE_NOMINAL_MV; + + return devm_snd_soc_register_component(dev, &wcd9335_component_drv, + wcd9335_slim_dais, + ARRAY_SIZE(wcd9335_slim_dais)); +} + +static struct platform_driver wcd9335_codec_driver = { + .probe = wcd9335_probe, + .driver = { + .name = "wcd9335-codec", + }, +}; +module_platform_driver(wcd9335_codec_driver); +MODULE_DESCRIPTION("WCD9335 Codec driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From c8cb5f775c8dacb605e628a320ded42be3bd9453 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 27 Jul 2018 13:18:01 +0100 Subject: ASoC: wcd9335: add CLASS-H Controller support CLASS-H controller/Amplifier is common accorss Qualcomm WCD codec series. This patchset adds basic CLASS-H controller apis for WCD codecs after wcd9335 to use. Signed-off-by: Srinivas Kandagatla Reviewed-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/codecs/Makefile | 2 +- sound/soc/codecs/wcd-clsh.c | 605 ++++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/wcd-clsh.h | 49 ++++ sound/soc/codecs/wcd9335.c | 10 + 4 files changed, 665 insertions(+), 1 deletion(-) create mode 100644 sound/soc/codecs/wcd-clsh.c create mode 100644 sound/soc/codecs/wcd-clsh.h (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 01410b63daac..e3a3d4694e15 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -192,7 +192,7 @@ snd-soc-twl4030-objs := twl4030.o snd-soc-twl6040-objs := twl6040.o snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o -snd-soc-wcd9335-objs := wcd9335.o +snd-soc-wcd9335-objs := wcd-clsh.o wcd9335.o snd-soc-wl1273-objs := wl1273.o snd-soc-wm-adsp-objs := wm_adsp.o snd-soc-wm0010-objs := wm0010.o diff --git a/sound/soc/codecs/wcd-clsh.c b/sound/soc/codecs/wcd-clsh.c new file mode 100644 index 000000000000..2393456cbd97 --- /dev/null +++ b/sound/soc/codecs/wcd-clsh.c @@ -0,0 +1,605 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +// Copyright (c) 2017-2018, Linaro Limited + +#include +#include +#include +#include +#include +#include +#include "wcd-clsh.h" + +struct wcd_clsh_ctrl { + int state; + int mode; + int flyback_users; + int buck_users; + int clsh_users; + int codec_version; + struct snd_soc_component *comp; +}; + +/* Class-H registers for codecs from and above WCD9335 */ +#define WCD9XXX_A_CDC_RX0_RX_PATH_CFG0 WCD9335_REG(0xB, 0x42) +#define WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK BIT(6) +#define WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE BIT(6) +#define WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE 0 +#define WCD9XXX_A_CDC_RX1_RX_PATH_CFG0 WCD9335_REG(0xB, 0x56) +#define WCD9XXX_A_CDC_RX2_RX_PATH_CFG0 WCD9335_REG(0xB, 0x6A) +#define WCD9XXX_A_CDC_CLSH_K1_MSB WCD9335_REG(0xC, 0x08) +#define WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK GENMASK(3, 0) +#define WCD9XXX_A_CDC_CLSH_K1_LSB WCD9335_REG(0xC, 0x09) +#define WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK GENMASK(7, 0) +#define WCD9XXX_A_ANA_RX_SUPPLIES WCD9335_REG(0x6, 0x08) +#define WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK BIT(1) +#define WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_H 0 +#define WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_AB BIT(1) +#define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK BIT(2) +#define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_UHQA BIT(2) +#define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_DEFAULT 0 +#define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK BIT(3) +#define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_UHQA BIT(3) +#define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_DEFAULT 0 +#define WCD9XXX_A_ANA_RX_VNEG_EN_MASK BIT(6) +#define WCD9XXX_A_ANA_RX_VNEG_EN_SHIFT 6 +#define WCD9XXX_A_ANA_RX_VNEG_ENABLE BIT(6) +#define WCD9XXX_A_ANA_RX_VNEG_DISABLE 0 +#define WCD9XXX_A_ANA_RX_VPOS_EN_MASK BIT(7) +#define WCD9XXX_A_ANA_RX_VPOS_EN_SHIFT 7 +#define WCD9XXX_A_ANA_RX_VPOS_ENABLE BIT(7) +#define WCD9XXX_A_ANA_RX_VPOS_DISABLE 0 +#define WCD9XXX_A_ANA_HPH WCD9335_REG(0x6, 0x09) +#define WCD9XXX_A_ANA_HPH_PWR_LEVEL_MASK GENMASK(3, 2) +#define WCD9XXX_A_ANA_HPH_PWR_LEVEL_UHQA 0x08 +#define WCD9XXX_A_ANA_HPH_PWR_LEVEL_LP 0x04 +#define WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL 0x0 +#define WCD9XXX_A_CDC_CLSH_CRC WCD9335_REG(0xC, 0x01) +#define WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK BIT(0) +#define WCD9XXX_A_CDC_CLSH_CRC_CLK_ENABLE BIT(0) +#define WCD9XXX_A_CDC_CLSH_CRC_CLK_DISABLE 0 +#define WCD9XXX_FLYBACK_EN WCD9335_REG(0x6, 0xA4) +#define WCD9XXX_FLYBACK_EN_DELAY_SEL_MASK GENMASK(6, 5) +#define WCD9XXX_FLYBACK_EN_DELAY_26P25_US 0x40 +#define WCD9XXX_FLYBACK_EN_RESET_BY_EXT_MASK BIT(4) +#define WCD9XXX_FLYBACK_EN_PWDN_WITHOUT_DELAY BIT(4) +#define WCD9XXX_FLYBACK_EN_PWDN_WITH_DELAY 0 +#define WCD9XXX_RX_BIAS_FLYB_BUFF WCD9335_REG(0x6, 0xC7) +#define WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK GENMASK(7, 4) +#define WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK GENMASK(0, 3) +#define WCD9XXX_HPH_L_EN WCD9335_REG(0x6, 0xD3) +#define WCD9XXX_HPH_CONST_SEL_L_MASK GENMASK(7, 3) +#define WCD9XXX_HPH_CONST_SEL_BYPASS 0 +#define WCD9XXX_HPH_CONST_SEL_LP_PATH 0x40 +#define WCD9XXX_HPH_CONST_SEL_HQ_PATH 0x80 +#define WCD9XXX_HPH_R_EN WCD9335_REG(0x6, 0xD6) +#define WCD9XXX_HPH_REFBUFF_UHQA_CTL WCD9335_REG(0x6, 0xDD) +#define WCD9XXX_HPH_REFBUFF_UHQA_GAIN_MASK GENMASK(2, 0) +#define WCD9XXX_CLASSH_CTRL_VCL_2 WCD9335_REG(0x6, 0x9B) +#define WCD9XXX_CLASSH_CTRL_VCL_2_VREF_FILT_1_MASK GENMASK(5, 4) +#define WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_50KOHM 0x20 +#define WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_0KOHM 0x0 +#define WCD9XXX_CDC_RX1_RX_PATH_CTL WCD9335_REG(0xB, 0x55) +#define WCD9XXX_CDC_RX2_RX_PATH_CTL WCD9335_REG(0xB, 0x69) +#define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_CONTROL WCD9335_REG(0xD, 0x41) +#define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_EN_MASK BIT(0) +#define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_11P3_EN_MASK BIT(1) +#define WCD9XXX_CLASSH_CTRL_CCL_1 WCD9335_REG(0x6, 0x9C) +#define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_MASK GENMASK(7, 4) +#define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA 0x50 +#define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_30MA 0x30 + +#define CLSH_REQ_ENABLE true +#define CLSH_REQ_DISABLE false +#define WCD_USLEEP_RANGE 50 + +enum { + DAC_GAIN_0DB = 0, + DAC_GAIN_0P2DB, + DAC_GAIN_0P4DB, + DAC_GAIN_0P6DB, + DAC_GAIN_0P8DB, + DAC_GAIN_M0P2DB, + DAC_GAIN_M0P4DB, + DAC_GAIN_M0P6DB, +}; + +static inline void wcd_enable_clsh_block(struct wcd_clsh_ctrl *ctrl, + bool enable) +{ + struct snd_soc_component *comp = ctrl->comp; + + if ((enable && ++ctrl->clsh_users == 1) || + (!enable && --ctrl->clsh_users == 0)) + snd_soc_component_update_bits(comp, WCD9XXX_A_CDC_CLSH_CRC, + WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK, + enable); + if (ctrl->clsh_users < 0) + ctrl->clsh_users = 0; +} + +static inline bool wcd_clsh_enable_status(struct snd_soc_component *comp) +{ + return snd_soc_component_read32(comp, WCD9XXX_A_CDC_CLSH_CRC) & + WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK; +} + +static inline void wcd_clsh_set_buck_mode(struct snd_soc_component *comp, + int mode) +{ + /* set to HIFI */ + if (mode == CLS_H_HIFI) + snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, + WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK, + WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_UHQA); + else + snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, + WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK, + WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_DEFAULT); +} + +static inline void wcd_clsh_set_flyback_mode(struct snd_soc_component *comp, + int mode) +{ + /* set to HIFI */ + if (mode == CLS_H_HIFI) + snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, + WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK, + WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_UHQA); + else + snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, + WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK, + WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_DEFAULT); +} + +static void wcd_clsh_buck_ctrl(struct wcd_clsh_ctrl *ctrl, + int mode, + bool enable) +{ + struct snd_soc_component *comp = ctrl->comp; + + /* enable/disable buck */ + if ((enable && (++ctrl->buck_users == 1)) || + (!enable && (--ctrl->buck_users == 0))) + snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, + WCD9XXX_A_ANA_RX_VPOS_EN_MASK, + enable << WCD9XXX_A_ANA_RX_VPOS_EN_SHIFT); + /* + * 500us sleep is required after buck enable/disable + * as per HW requirement + */ + usleep_range(500, 500 + WCD_USLEEP_RANGE); +} + +static void wcd_clsh_flyback_ctrl(struct wcd_clsh_ctrl *ctrl, + int mode, + bool enable) +{ + struct snd_soc_component *comp = ctrl->comp; + + int vneg[] = {0x00, 0x40}; + + /* enable/disable flyback */ + if ((enable && (++ctrl->flyback_users == 1)) || + (!enable && (--ctrl->flyback_users == 0))) { + snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, + WCD9XXX_A_ANA_RX_VNEG_EN_MASK, + enable << WCD9XXX_A_ANA_RX_VNEG_EN_SHIFT); + /* 100usec delay is needed as per HW requirement */ + usleep_range(100, 110); + + if (enable && (WCD9335_IS_1_1(ctrl->codec_version))) { + wcd_clsh_set_flyback_mode(comp, CLS_H_HIFI); + snd_soc_component_update_bits(comp, WCD9XXX_FLYBACK_EN, + WCD9XXX_FLYBACK_EN_DELAY_SEL_MASK, + WCD9XXX_FLYBACK_EN_DELAY_26P25_US); + snd_soc_component_update_bits(comp, WCD9XXX_FLYBACK_EN, + WCD9XXX_FLYBACK_EN_RESET_BY_EXT_MASK, + WCD9XXX_FLYBACK_EN_PWDN_WITHOUT_DELAY); + vneg[0] = snd_soc_component_read32(comp, + WCD9XXX_A_ANA_RX_SUPPLIES); + vneg[0] &= ~(0x40); + vneg[1] = vneg[0] | 0x40; + + snd_soc_component_write(comp, + WCD9XXX_A_ANA_RX_SUPPLIES, vneg[0]); + snd_soc_component_write(comp, + WCD9XXX_A_ANA_RX_SUPPLIES, vneg[1]); + /* 500usec delay is needed as per HW requirement */ + usleep_range(500, 510); + snd_soc_component_update_bits(comp, WCD9XXX_FLYBACK_EN, + WCD9XXX_FLYBACK_EN_RESET_BY_EXT_MASK, + WCD9XXX_FLYBACK_EN_PWDN_WITH_DELAY); + wcd_clsh_set_flyback_mode(comp, mode); + } + + } + /* + * 500us sleep is required after flyback enable/disable + * as per HW requirement + */ + usleep_range(500, 500 + WCD_USLEEP_RANGE); +} + +static void wcd_clsh_set_gain_path(struct wcd_clsh_ctrl *ctrl, int mode) +{ + struct snd_soc_component *comp = ctrl->comp; + int val = 0; + + switch (mode) { + case CLS_H_NORMAL: + case CLS_AB: + val = WCD9XXX_HPH_CONST_SEL_BYPASS; + break; + case CLS_H_HIFI: + val = WCD9XXX_HPH_CONST_SEL_HQ_PATH; + break; + case CLS_H_LP: + val = WCD9XXX_HPH_CONST_SEL_LP_PATH; + break; + }; + + snd_soc_component_update_bits(comp, WCD9XXX_HPH_L_EN, + WCD9XXX_HPH_CONST_SEL_L_MASK, + val); + + snd_soc_component_update_bits(comp, WCD9XXX_HPH_R_EN, + WCD9XXX_HPH_CONST_SEL_L_MASK, + val); +} + +static void wcd_clsh_set_hph_mode(struct snd_soc_component *comp, + int mode) +{ + int val = 0, gain = 0, res_val; + int ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA; + + res_val = WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_0KOHM; + switch (mode) { + case CLS_H_NORMAL: + res_val = WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_50KOHM; + val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL; + gain = DAC_GAIN_0DB; + ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA; + break; + case CLS_AB: + val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL; + gain = DAC_GAIN_0DB; + ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA; + break; + case CLS_H_HIFI: + val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_UHQA; + gain = DAC_GAIN_M0P2DB; + ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA; + break; + case CLS_H_LP: + val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_LP; + ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_30MA; + break; + }; + + snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_HPH, + WCD9XXX_A_ANA_HPH_PWR_LEVEL_MASK, val); + snd_soc_component_update_bits(comp, WCD9XXX_CLASSH_CTRL_VCL_2, + WCD9XXX_CLASSH_CTRL_VCL_2_VREF_FILT_1_MASK, + res_val); + if (mode != CLS_H_LP) + snd_soc_component_update_bits(comp, + WCD9XXX_HPH_REFBUFF_UHQA_CTL, + WCD9XXX_HPH_REFBUFF_UHQA_GAIN_MASK, + gain); + snd_soc_component_update_bits(comp, WCD9XXX_CLASSH_CTRL_CCL_1, + WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_MASK, + ipeak); +} + +static void wcd_clsh_set_flyback_current(struct snd_soc_component *comp, + int mode) +{ + + snd_soc_component_update_bits(comp, WCD9XXX_RX_BIAS_FLYB_BUFF, + WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK, 0x0A); + snd_soc_component_update_bits(comp, WCD9XXX_RX_BIAS_FLYB_BUFF, + WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK, 0x0A); + /* Sleep needed to avoid click and pop as per HW requirement */ + usleep_range(100, 110); +} + +static void wcd_clsh_set_buck_regulator_mode(struct snd_soc_component *comp, + int mode) +{ + if (mode == CLS_AB) + snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, + WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK, + WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_AB); + else + snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, + WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK, + WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_H); +} + +static void wcd_clsh_state_lo(struct wcd_clsh_ctrl *ctrl, int req_state, + bool is_enable, int mode) +{ + struct snd_soc_component *comp = ctrl->comp; + + if (mode != CLS_AB) { + dev_err(comp->dev, "%s: LO cannot be in this mode: %d\n", + __func__, mode); + return; + } + + if (is_enable) { + wcd_clsh_set_buck_regulator_mode(comp, mode); + wcd_clsh_set_buck_mode(comp, mode); + wcd_clsh_set_flyback_mode(comp, mode); + wcd_clsh_flyback_ctrl(ctrl, mode, true); + wcd_clsh_set_flyback_current(comp, mode); + wcd_clsh_buck_ctrl(ctrl, mode, true); + } else { + wcd_clsh_buck_ctrl(ctrl, mode, false); + wcd_clsh_flyback_ctrl(ctrl, mode, false); + wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL); + wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL); + wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL); + } +} + +static void wcd_clsh_state_hph_r(struct wcd_clsh_ctrl *ctrl, int req_state, + bool is_enable, int mode) +{ + struct snd_soc_component *comp = ctrl->comp; + + if (mode == CLS_H_NORMAL) { + dev_err(comp->dev, "%s: Normal mode not applicable for hph_r\n", + __func__); + return; + } + + if (is_enable) { + if (mode != CLS_AB) { + wcd_enable_clsh_block(ctrl, true); + /* + * These K1 values depend on the Headphone Impedance + * For now it is assumed to be 16 ohm + */ + snd_soc_component_update_bits(comp, + WCD9XXX_A_CDC_CLSH_K1_MSB, + WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK, + 0x00); + snd_soc_component_update_bits(comp, + WCD9XXX_A_CDC_CLSH_K1_LSB, + WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK, + 0xC0); + snd_soc_component_update_bits(comp, + WCD9XXX_A_CDC_RX2_RX_PATH_CFG0, + WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK, + WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE); + } + wcd_clsh_set_buck_regulator_mode(comp, mode); + wcd_clsh_set_flyback_mode(comp, mode); + wcd_clsh_flyback_ctrl(ctrl, mode, true); + wcd_clsh_set_flyback_current(comp, mode); + wcd_clsh_set_buck_mode(comp, mode); + wcd_clsh_buck_ctrl(ctrl, mode, true); + wcd_clsh_set_hph_mode(comp, mode); + wcd_clsh_set_gain_path(ctrl, mode); + } else { + wcd_clsh_set_hph_mode(comp, CLS_H_NORMAL); + + if (mode != CLS_AB) { + snd_soc_component_update_bits(comp, + WCD9XXX_A_CDC_RX2_RX_PATH_CFG0, + WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK, + WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE); + wcd_enable_clsh_block(ctrl, false); + } + /* buck and flyback set to default mode and disable */ + wcd_clsh_buck_ctrl(ctrl, CLS_H_NORMAL, false); + wcd_clsh_flyback_ctrl(ctrl, CLS_H_NORMAL, false); + wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL); + wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL); + wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL); + } +} + +static void wcd_clsh_state_hph_l(struct wcd_clsh_ctrl *ctrl, int req_state, + bool is_enable, int mode) +{ + struct snd_soc_component *comp = ctrl->comp; + + if (mode == CLS_H_NORMAL) { + dev_err(comp->dev, "%s: Normal mode not applicable for hph_l\n", + __func__); + return; + } + + if (is_enable) { + if (mode != CLS_AB) { + wcd_enable_clsh_block(ctrl, true); + /* + * These K1 values depend on the Headphone Impedance + * For now it is assumed to be 16 ohm + */ + snd_soc_component_update_bits(comp, + WCD9XXX_A_CDC_CLSH_K1_MSB, + WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK, + 0x00); + snd_soc_component_update_bits(comp, + WCD9XXX_A_CDC_CLSH_K1_LSB, + WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK, + 0xC0); + snd_soc_component_update_bits(comp, + WCD9XXX_A_CDC_RX1_RX_PATH_CFG0, + WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK, + WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE); + } + wcd_clsh_set_buck_regulator_mode(comp, mode); + wcd_clsh_set_flyback_mode(comp, mode); + wcd_clsh_flyback_ctrl(ctrl, mode, true); + wcd_clsh_set_flyback_current(comp, mode); + wcd_clsh_set_buck_mode(comp, mode); + wcd_clsh_buck_ctrl(ctrl, mode, true); + wcd_clsh_set_hph_mode(comp, mode); + wcd_clsh_set_gain_path(ctrl, mode); + } else { + wcd_clsh_set_hph_mode(comp, CLS_H_NORMAL); + + if (mode != CLS_AB) { + snd_soc_component_update_bits(comp, + WCD9XXX_A_CDC_RX1_RX_PATH_CFG0, + WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK, + WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE); + wcd_enable_clsh_block(ctrl, false); + } + /* set buck and flyback to Default Mode */ + wcd_clsh_buck_ctrl(ctrl, CLS_H_NORMAL, false); + wcd_clsh_flyback_ctrl(ctrl, CLS_H_NORMAL, false); + wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL); + wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL); + wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL); + } +} + +static void wcd_clsh_state_ear(struct wcd_clsh_ctrl *ctrl, int req_state, + bool is_enable, int mode) +{ + struct snd_soc_component *comp = ctrl->comp; + + if (mode != CLS_H_NORMAL) { + dev_err(comp->dev, "%s: mode: %d cannot be used for EAR\n", + __func__, mode); + return; + } + + if (is_enable) { + wcd_enable_clsh_block(ctrl, true); + snd_soc_component_update_bits(comp, + WCD9XXX_A_CDC_RX0_RX_PATH_CFG0, + WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK, + WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE); + wcd_clsh_set_buck_mode(comp, mode); + wcd_clsh_set_flyback_mode(comp, mode); + wcd_clsh_flyback_ctrl(ctrl, mode, true); + wcd_clsh_set_flyback_current(comp, mode); + wcd_clsh_buck_ctrl(ctrl, mode, true); + } else { + snd_soc_component_update_bits(comp, + WCD9XXX_A_CDC_RX0_RX_PATH_CFG0, + WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK, + WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE); + wcd_enable_clsh_block(ctrl, false); + wcd_clsh_buck_ctrl(ctrl, mode, false); + wcd_clsh_flyback_ctrl(ctrl, mode, false); + wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL); + wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL); + } +} + +static int _wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl, int req_state, + bool is_enable, int mode) +{ + switch (req_state) { + case WCD_CLSH_STATE_EAR: + wcd_clsh_state_ear(ctrl, req_state, is_enable, mode); + break; + case WCD_CLSH_STATE_HPHL: + wcd_clsh_state_hph_l(ctrl, req_state, is_enable, mode); + break; + case WCD_CLSH_STATE_HPHR: + wcd_clsh_state_hph_r(ctrl, req_state, is_enable, mode); + break; + break; + case WCD_CLSH_STATE_LO: + wcd_clsh_state_lo(ctrl, req_state, is_enable, mode); + break; + default: + break; + } + + return 0; +} + +/* + * Function: wcd_clsh_is_state_valid + * Params: state + * Description: + * Provides information on valid states of Class H configuration + */ +static bool wcd_clsh_is_state_valid(int state) +{ + switch (state) { + case WCD_CLSH_STATE_IDLE: + case WCD_CLSH_STATE_EAR: + case WCD_CLSH_STATE_HPHL: + case WCD_CLSH_STATE_HPHR: + case WCD_CLSH_STATE_LO: + return true; + default: + return false; + }; +} + +/* + * Function: wcd_clsh_fsm + * Params: ctrl, req_state, req_type, clsh_event + * Description: + * This function handles PRE DAC and POST DAC conditions of different devices + * and updates class H configuration of different combination of devices + * based on validity of their states. ctrl will contain current + * class h state information + */ +int wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl, + enum wcd_clsh_event clsh_event, + int nstate, + enum wcd_clsh_mode mode) +{ + struct snd_soc_component *comp = ctrl->comp; + + if (nstate == ctrl->state) + return 0; + + if (!wcd_clsh_is_state_valid(nstate)) { + dev_err(comp->dev, "Class-H not a valid new state:\n"); + return -EINVAL; + } + + switch (clsh_event) { + case WCD_CLSH_EVENT_PRE_DAC: + _wcd_clsh_ctrl_set_state(ctrl, nstate, CLSH_REQ_ENABLE, mode); + break; + case WCD_CLSH_EVENT_POST_PA: + _wcd_clsh_ctrl_set_state(ctrl, nstate, CLSH_REQ_DISABLE, mode); + break; + }; + + ctrl->state = nstate; + ctrl->mode = mode; + + return 0; +} + +int wcd_clsh_ctrl_get_state(struct wcd_clsh_ctrl *ctrl) +{ + return ctrl->state; +} + +struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc(struct snd_soc_component *comp, + int version) +{ + struct wcd_clsh_ctrl *ctrl; + + ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) + return ERR_PTR(-ENOMEM); + + ctrl->state = WCD_CLSH_STATE_IDLE; + ctrl->comp = comp; + + return ctrl; +} + +void wcd_clsh_ctrl_free(struct wcd_clsh_ctrl *ctrl) +{ + kfree(ctrl); +} diff --git a/sound/soc/codecs/wcd-clsh.h b/sound/soc/codecs/wcd-clsh.h new file mode 100644 index 000000000000..a902f9893467 --- /dev/null +++ b/sound/soc/codecs/wcd-clsh.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _WCD_CLSH_V2_H_ +#define _WCD_CLSH_V2_H_ +#include + +enum wcd_clsh_event { + WCD_CLSH_EVENT_PRE_DAC = 1, + WCD_CLSH_EVENT_POST_PA, +}; + +/* + * Basic states for Class H state machine. + * represented as a bit mask within a u8 data type + * bit 0: EAR mode + * bit 1: HPH Left mode + * bit 2: HPH Right mode + * bit 3: Lineout mode + */ +#define WCD_CLSH_STATE_IDLE 0 +#define WCD_CLSH_STATE_EAR BIT(0) +#define WCD_CLSH_STATE_HPHL BIT(1) +#define WCD_CLSH_STATE_HPHR BIT(2) +#define WCD_CLSH_STATE_LO BIT(3) +#define WCD_CLSH_STATE_MAX 4 +#define NUM_CLSH_STATES_V2 BIT(WCD_CLSH_STATE_MAX) + +enum wcd_clsh_mode { + CLS_H_NORMAL = 0, /* Class-H Default */ + CLS_H_HIFI, /* Class-H HiFi */ + CLS_H_LP, /* Class-H Low Power */ + CLS_AB, /* Class-AB */ + CLS_H_LOHIFI, /* LoHIFI */ + CLS_NONE, /* None of the above modes */ +}; + +struct wcd_clsh_ctrl; + +extern struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc( + struct snd_soc_component *component, + int version); +extern void wcd_clsh_ctrl_free(struct wcd_clsh_ctrl *ctrl); +extern int wcd_clsh_ctrl_get_state(struct wcd_clsh_ctrl *ctrl); +extern int wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl, + enum wcd_clsh_event event, + int state, + enum wcd_clsh_mode mode); + +#endif /* _WCD_CLSH_V2_H_ */ diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index bd9de5d45fa9..06c73699f16f 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -21,6 +21,7 @@ #include #include #include +#include "wcd-clsh.h" #define WCD9335_RATES_MASK (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ @@ -181,6 +182,7 @@ struct wcd9335_codec { int sido_ccl_cnt; enum wcd_clock_type clk_type; + struct wcd_clsh_ctrl *clsh_ctrl; u32 hph_mode; }; @@ -1066,6 +1068,13 @@ static int wcd9335_codec_probe(struct snd_soc_component *component) int i; snd_soc_component_init_regmap(component, wcd->regmap); + /* Class-H Init*/ + wcd->clsh_ctrl = wcd_clsh_ctrl_alloc(component, wcd->version); + if (IS_ERR(wcd->clsh_ctrl)) + return PTR_ERR(wcd->clsh_ctrl); + + /* Default HPH Mode to Class-H HiFi */ + wcd->hph_mode = CLS_H_HIFI; wcd->component = component; wcd9335_codec_init(component); @@ -1080,6 +1089,7 @@ static void wcd9335_codec_remove(struct snd_soc_component *comp) { struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev); + wcd_clsh_ctrl_free(wcd->clsh_ctrl); free_irq(regmap_irq_get_virq(wcd->irq_data, WCD9335_IRQ_SLIMBUS), wcd); } -- cgit v1.2.3 From d101f9b96ee08f0454989bc3adb10e6cf7f3f953 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 1 Aug 2018 11:47:39 +0100 Subject: ASoC: nau8540: remove redundant variable osrate Variable osrate is being assigned but is never used hence it is redundant and can be removed. Cleans up clang warning: warning: variable 'osrate' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Signed-off-by: Mark Brown --- sound/soc/codecs/nau8540.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/nau8540.c b/sound/soc/codecs/nau8540.c index 17104f8dc1a9..e3c8cd17daf2 100644 --- a/sound/soc/codecs/nau8540.c +++ b/sound/soc/codecs/nau8540.c @@ -362,11 +362,8 @@ static const struct snd_soc_dapm_route nau8540_dapm_routes[] = { static int nau8540_clock_check(struct nau8540 *nau8540, int rate, int osr) { - int osrate; - if (osr >= ARRAY_SIZE(osr_adc_sel)) return -EINVAL; - osrate = osr_adc_sel[osr].osr; if (rate * osr > CLK_ADC_MAX) { dev_err(nau8540->dev, "exceed the maximum frequency of CLK_ADC\n"); -- cgit v1.2.3 From b0a39d356ae1478a5876bb02ba08af155a3a5554 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 1 Aug 2018 14:18:50 +0100 Subject: ASoC: wcd9335: Fix build due to CLASS-H Controller support This reverts commit c8cb5f775c8dac (ASoC: vert "ASoC: wcd9335: add CLASS-H Controller support) due to missing dependencies. Signed-off-by: Mark Brown --- sound/soc/codecs/Makefile | 2 +- sound/soc/codecs/wcd-clsh.c | 605 -------------------------------------------- sound/soc/codecs/wcd-clsh.h | 49 ---- sound/soc/codecs/wcd9335.c | 10 - 4 files changed, 1 insertion(+), 665 deletions(-) delete mode 100644 sound/soc/codecs/wcd-clsh.c delete mode 100644 sound/soc/codecs/wcd-clsh.h (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index e3a3d4694e15..01410b63daac 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -192,7 +192,7 @@ snd-soc-twl4030-objs := twl4030.o snd-soc-twl6040-objs := twl6040.o snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o -snd-soc-wcd9335-objs := wcd-clsh.o wcd9335.o +snd-soc-wcd9335-objs := wcd9335.o snd-soc-wl1273-objs := wl1273.o snd-soc-wm-adsp-objs := wm_adsp.o snd-soc-wm0010-objs := wm0010.o diff --git a/sound/soc/codecs/wcd-clsh.c b/sound/soc/codecs/wcd-clsh.c deleted file mode 100644 index 2393456cbd97..000000000000 --- a/sound/soc/codecs/wcd-clsh.c +++ /dev/null @@ -1,605 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -// Copyright (c) 2017-2018, Linaro Limited - -#include -#include -#include -#include -#include -#include -#include "wcd-clsh.h" - -struct wcd_clsh_ctrl { - int state; - int mode; - int flyback_users; - int buck_users; - int clsh_users; - int codec_version; - struct snd_soc_component *comp; -}; - -/* Class-H registers for codecs from and above WCD9335 */ -#define WCD9XXX_A_CDC_RX0_RX_PATH_CFG0 WCD9335_REG(0xB, 0x42) -#define WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK BIT(6) -#define WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE BIT(6) -#define WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE 0 -#define WCD9XXX_A_CDC_RX1_RX_PATH_CFG0 WCD9335_REG(0xB, 0x56) -#define WCD9XXX_A_CDC_RX2_RX_PATH_CFG0 WCD9335_REG(0xB, 0x6A) -#define WCD9XXX_A_CDC_CLSH_K1_MSB WCD9335_REG(0xC, 0x08) -#define WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK GENMASK(3, 0) -#define WCD9XXX_A_CDC_CLSH_K1_LSB WCD9335_REG(0xC, 0x09) -#define WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK GENMASK(7, 0) -#define WCD9XXX_A_ANA_RX_SUPPLIES WCD9335_REG(0x6, 0x08) -#define WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK BIT(1) -#define WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_H 0 -#define WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_AB BIT(1) -#define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK BIT(2) -#define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_UHQA BIT(2) -#define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_DEFAULT 0 -#define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK BIT(3) -#define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_UHQA BIT(3) -#define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_DEFAULT 0 -#define WCD9XXX_A_ANA_RX_VNEG_EN_MASK BIT(6) -#define WCD9XXX_A_ANA_RX_VNEG_EN_SHIFT 6 -#define WCD9XXX_A_ANA_RX_VNEG_ENABLE BIT(6) -#define WCD9XXX_A_ANA_RX_VNEG_DISABLE 0 -#define WCD9XXX_A_ANA_RX_VPOS_EN_MASK BIT(7) -#define WCD9XXX_A_ANA_RX_VPOS_EN_SHIFT 7 -#define WCD9XXX_A_ANA_RX_VPOS_ENABLE BIT(7) -#define WCD9XXX_A_ANA_RX_VPOS_DISABLE 0 -#define WCD9XXX_A_ANA_HPH WCD9335_REG(0x6, 0x09) -#define WCD9XXX_A_ANA_HPH_PWR_LEVEL_MASK GENMASK(3, 2) -#define WCD9XXX_A_ANA_HPH_PWR_LEVEL_UHQA 0x08 -#define WCD9XXX_A_ANA_HPH_PWR_LEVEL_LP 0x04 -#define WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL 0x0 -#define WCD9XXX_A_CDC_CLSH_CRC WCD9335_REG(0xC, 0x01) -#define WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK BIT(0) -#define WCD9XXX_A_CDC_CLSH_CRC_CLK_ENABLE BIT(0) -#define WCD9XXX_A_CDC_CLSH_CRC_CLK_DISABLE 0 -#define WCD9XXX_FLYBACK_EN WCD9335_REG(0x6, 0xA4) -#define WCD9XXX_FLYBACK_EN_DELAY_SEL_MASK GENMASK(6, 5) -#define WCD9XXX_FLYBACK_EN_DELAY_26P25_US 0x40 -#define WCD9XXX_FLYBACK_EN_RESET_BY_EXT_MASK BIT(4) -#define WCD9XXX_FLYBACK_EN_PWDN_WITHOUT_DELAY BIT(4) -#define WCD9XXX_FLYBACK_EN_PWDN_WITH_DELAY 0 -#define WCD9XXX_RX_BIAS_FLYB_BUFF WCD9335_REG(0x6, 0xC7) -#define WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK GENMASK(7, 4) -#define WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK GENMASK(0, 3) -#define WCD9XXX_HPH_L_EN WCD9335_REG(0x6, 0xD3) -#define WCD9XXX_HPH_CONST_SEL_L_MASK GENMASK(7, 3) -#define WCD9XXX_HPH_CONST_SEL_BYPASS 0 -#define WCD9XXX_HPH_CONST_SEL_LP_PATH 0x40 -#define WCD9XXX_HPH_CONST_SEL_HQ_PATH 0x80 -#define WCD9XXX_HPH_R_EN WCD9335_REG(0x6, 0xD6) -#define WCD9XXX_HPH_REFBUFF_UHQA_CTL WCD9335_REG(0x6, 0xDD) -#define WCD9XXX_HPH_REFBUFF_UHQA_GAIN_MASK GENMASK(2, 0) -#define WCD9XXX_CLASSH_CTRL_VCL_2 WCD9335_REG(0x6, 0x9B) -#define WCD9XXX_CLASSH_CTRL_VCL_2_VREF_FILT_1_MASK GENMASK(5, 4) -#define WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_50KOHM 0x20 -#define WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_0KOHM 0x0 -#define WCD9XXX_CDC_RX1_RX_PATH_CTL WCD9335_REG(0xB, 0x55) -#define WCD9XXX_CDC_RX2_RX_PATH_CTL WCD9335_REG(0xB, 0x69) -#define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_CONTROL WCD9335_REG(0xD, 0x41) -#define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_EN_MASK BIT(0) -#define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_11P3_EN_MASK BIT(1) -#define WCD9XXX_CLASSH_CTRL_CCL_1 WCD9335_REG(0x6, 0x9C) -#define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_MASK GENMASK(7, 4) -#define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA 0x50 -#define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_30MA 0x30 - -#define CLSH_REQ_ENABLE true -#define CLSH_REQ_DISABLE false -#define WCD_USLEEP_RANGE 50 - -enum { - DAC_GAIN_0DB = 0, - DAC_GAIN_0P2DB, - DAC_GAIN_0P4DB, - DAC_GAIN_0P6DB, - DAC_GAIN_0P8DB, - DAC_GAIN_M0P2DB, - DAC_GAIN_M0P4DB, - DAC_GAIN_M0P6DB, -}; - -static inline void wcd_enable_clsh_block(struct wcd_clsh_ctrl *ctrl, - bool enable) -{ - struct snd_soc_component *comp = ctrl->comp; - - if ((enable && ++ctrl->clsh_users == 1) || - (!enable && --ctrl->clsh_users == 0)) - snd_soc_component_update_bits(comp, WCD9XXX_A_CDC_CLSH_CRC, - WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK, - enable); - if (ctrl->clsh_users < 0) - ctrl->clsh_users = 0; -} - -static inline bool wcd_clsh_enable_status(struct snd_soc_component *comp) -{ - return snd_soc_component_read32(comp, WCD9XXX_A_CDC_CLSH_CRC) & - WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK; -} - -static inline void wcd_clsh_set_buck_mode(struct snd_soc_component *comp, - int mode) -{ - /* set to HIFI */ - if (mode == CLS_H_HIFI) - snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, - WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK, - WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_UHQA); - else - snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, - WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK, - WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_DEFAULT); -} - -static inline void wcd_clsh_set_flyback_mode(struct snd_soc_component *comp, - int mode) -{ - /* set to HIFI */ - if (mode == CLS_H_HIFI) - snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, - WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK, - WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_UHQA); - else - snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, - WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK, - WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_DEFAULT); -} - -static void wcd_clsh_buck_ctrl(struct wcd_clsh_ctrl *ctrl, - int mode, - bool enable) -{ - struct snd_soc_component *comp = ctrl->comp; - - /* enable/disable buck */ - if ((enable && (++ctrl->buck_users == 1)) || - (!enable && (--ctrl->buck_users == 0))) - snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, - WCD9XXX_A_ANA_RX_VPOS_EN_MASK, - enable << WCD9XXX_A_ANA_RX_VPOS_EN_SHIFT); - /* - * 500us sleep is required after buck enable/disable - * as per HW requirement - */ - usleep_range(500, 500 + WCD_USLEEP_RANGE); -} - -static void wcd_clsh_flyback_ctrl(struct wcd_clsh_ctrl *ctrl, - int mode, - bool enable) -{ - struct snd_soc_component *comp = ctrl->comp; - - int vneg[] = {0x00, 0x40}; - - /* enable/disable flyback */ - if ((enable && (++ctrl->flyback_users == 1)) || - (!enable && (--ctrl->flyback_users == 0))) { - snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, - WCD9XXX_A_ANA_RX_VNEG_EN_MASK, - enable << WCD9XXX_A_ANA_RX_VNEG_EN_SHIFT); - /* 100usec delay is needed as per HW requirement */ - usleep_range(100, 110); - - if (enable && (WCD9335_IS_1_1(ctrl->codec_version))) { - wcd_clsh_set_flyback_mode(comp, CLS_H_HIFI); - snd_soc_component_update_bits(comp, WCD9XXX_FLYBACK_EN, - WCD9XXX_FLYBACK_EN_DELAY_SEL_MASK, - WCD9XXX_FLYBACK_EN_DELAY_26P25_US); - snd_soc_component_update_bits(comp, WCD9XXX_FLYBACK_EN, - WCD9XXX_FLYBACK_EN_RESET_BY_EXT_MASK, - WCD9XXX_FLYBACK_EN_PWDN_WITHOUT_DELAY); - vneg[0] = snd_soc_component_read32(comp, - WCD9XXX_A_ANA_RX_SUPPLIES); - vneg[0] &= ~(0x40); - vneg[1] = vneg[0] | 0x40; - - snd_soc_component_write(comp, - WCD9XXX_A_ANA_RX_SUPPLIES, vneg[0]); - snd_soc_component_write(comp, - WCD9XXX_A_ANA_RX_SUPPLIES, vneg[1]); - /* 500usec delay is needed as per HW requirement */ - usleep_range(500, 510); - snd_soc_component_update_bits(comp, WCD9XXX_FLYBACK_EN, - WCD9XXX_FLYBACK_EN_RESET_BY_EXT_MASK, - WCD9XXX_FLYBACK_EN_PWDN_WITH_DELAY); - wcd_clsh_set_flyback_mode(comp, mode); - } - - } - /* - * 500us sleep is required after flyback enable/disable - * as per HW requirement - */ - usleep_range(500, 500 + WCD_USLEEP_RANGE); -} - -static void wcd_clsh_set_gain_path(struct wcd_clsh_ctrl *ctrl, int mode) -{ - struct snd_soc_component *comp = ctrl->comp; - int val = 0; - - switch (mode) { - case CLS_H_NORMAL: - case CLS_AB: - val = WCD9XXX_HPH_CONST_SEL_BYPASS; - break; - case CLS_H_HIFI: - val = WCD9XXX_HPH_CONST_SEL_HQ_PATH; - break; - case CLS_H_LP: - val = WCD9XXX_HPH_CONST_SEL_LP_PATH; - break; - }; - - snd_soc_component_update_bits(comp, WCD9XXX_HPH_L_EN, - WCD9XXX_HPH_CONST_SEL_L_MASK, - val); - - snd_soc_component_update_bits(comp, WCD9XXX_HPH_R_EN, - WCD9XXX_HPH_CONST_SEL_L_MASK, - val); -} - -static void wcd_clsh_set_hph_mode(struct snd_soc_component *comp, - int mode) -{ - int val = 0, gain = 0, res_val; - int ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA; - - res_val = WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_0KOHM; - switch (mode) { - case CLS_H_NORMAL: - res_val = WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_50KOHM; - val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL; - gain = DAC_GAIN_0DB; - ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA; - break; - case CLS_AB: - val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL; - gain = DAC_GAIN_0DB; - ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA; - break; - case CLS_H_HIFI: - val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_UHQA; - gain = DAC_GAIN_M0P2DB; - ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA; - break; - case CLS_H_LP: - val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_LP; - ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_30MA; - break; - }; - - snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_HPH, - WCD9XXX_A_ANA_HPH_PWR_LEVEL_MASK, val); - snd_soc_component_update_bits(comp, WCD9XXX_CLASSH_CTRL_VCL_2, - WCD9XXX_CLASSH_CTRL_VCL_2_VREF_FILT_1_MASK, - res_val); - if (mode != CLS_H_LP) - snd_soc_component_update_bits(comp, - WCD9XXX_HPH_REFBUFF_UHQA_CTL, - WCD9XXX_HPH_REFBUFF_UHQA_GAIN_MASK, - gain); - snd_soc_component_update_bits(comp, WCD9XXX_CLASSH_CTRL_CCL_1, - WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_MASK, - ipeak); -} - -static void wcd_clsh_set_flyback_current(struct snd_soc_component *comp, - int mode) -{ - - snd_soc_component_update_bits(comp, WCD9XXX_RX_BIAS_FLYB_BUFF, - WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK, 0x0A); - snd_soc_component_update_bits(comp, WCD9XXX_RX_BIAS_FLYB_BUFF, - WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK, 0x0A); - /* Sleep needed to avoid click and pop as per HW requirement */ - usleep_range(100, 110); -} - -static void wcd_clsh_set_buck_regulator_mode(struct snd_soc_component *comp, - int mode) -{ - if (mode == CLS_AB) - snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, - WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK, - WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_AB); - else - snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, - WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK, - WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_H); -} - -static void wcd_clsh_state_lo(struct wcd_clsh_ctrl *ctrl, int req_state, - bool is_enable, int mode) -{ - struct snd_soc_component *comp = ctrl->comp; - - if (mode != CLS_AB) { - dev_err(comp->dev, "%s: LO cannot be in this mode: %d\n", - __func__, mode); - return; - } - - if (is_enable) { - wcd_clsh_set_buck_regulator_mode(comp, mode); - wcd_clsh_set_buck_mode(comp, mode); - wcd_clsh_set_flyback_mode(comp, mode); - wcd_clsh_flyback_ctrl(ctrl, mode, true); - wcd_clsh_set_flyback_current(comp, mode); - wcd_clsh_buck_ctrl(ctrl, mode, true); - } else { - wcd_clsh_buck_ctrl(ctrl, mode, false); - wcd_clsh_flyback_ctrl(ctrl, mode, false); - wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL); - wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL); - wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL); - } -} - -static void wcd_clsh_state_hph_r(struct wcd_clsh_ctrl *ctrl, int req_state, - bool is_enable, int mode) -{ - struct snd_soc_component *comp = ctrl->comp; - - if (mode == CLS_H_NORMAL) { - dev_err(comp->dev, "%s: Normal mode not applicable for hph_r\n", - __func__); - return; - } - - if (is_enable) { - if (mode != CLS_AB) { - wcd_enable_clsh_block(ctrl, true); - /* - * These K1 values depend on the Headphone Impedance - * For now it is assumed to be 16 ohm - */ - snd_soc_component_update_bits(comp, - WCD9XXX_A_CDC_CLSH_K1_MSB, - WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK, - 0x00); - snd_soc_component_update_bits(comp, - WCD9XXX_A_CDC_CLSH_K1_LSB, - WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK, - 0xC0); - snd_soc_component_update_bits(comp, - WCD9XXX_A_CDC_RX2_RX_PATH_CFG0, - WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK, - WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE); - } - wcd_clsh_set_buck_regulator_mode(comp, mode); - wcd_clsh_set_flyback_mode(comp, mode); - wcd_clsh_flyback_ctrl(ctrl, mode, true); - wcd_clsh_set_flyback_current(comp, mode); - wcd_clsh_set_buck_mode(comp, mode); - wcd_clsh_buck_ctrl(ctrl, mode, true); - wcd_clsh_set_hph_mode(comp, mode); - wcd_clsh_set_gain_path(ctrl, mode); - } else { - wcd_clsh_set_hph_mode(comp, CLS_H_NORMAL); - - if (mode != CLS_AB) { - snd_soc_component_update_bits(comp, - WCD9XXX_A_CDC_RX2_RX_PATH_CFG0, - WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK, - WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE); - wcd_enable_clsh_block(ctrl, false); - } - /* buck and flyback set to default mode and disable */ - wcd_clsh_buck_ctrl(ctrl, CLS_H_NORMAL, false); - wcd_clsh_flyback_ctrl(ctrl, CLS_H_NORMAL, false); - wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL); - wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL); - wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL); - } -} - -static void wcd_clsh_state_hph_l(struct wcd_clsh_ctrl *ctrl, int req_state, - bool is_enable, int mode) -{ - struct snd_soc_component *comp = ctrl->comp; - - if (mode == CLS_H_NORMAL) { - dev_err(comp->dev, "%s: Normal mode not applicable for hph_l\n", - __func__); - return; - } - - if (is_enable) { - if (mode != CLS_AB) { - wcd_enable_clsh_block(ctrl, true); - /* - * These K1 values depend on the Headphone Impedance - * For now it is assumed to be 16 ohm - */ - snd_soc_component_update_bits(comp, - WCD9XXX_A_CDC_CLSH_K1_MSB, - WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK, - 0x00); - snd_soc_component_update_bits(comp, - WCD9XXX_A_CDC_CLSH_K1_LSB, - WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK, - 0xC0); - snd_soc_component_update_bits(comp, - WCD9XXX_A_CDC_RX1_RX_PATH_CFG0, - WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK, - WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE); - } - wcd_clsh_set_buck_regulator_mode(comp, mode); - wcd_clsh_set_flyback_mode(comp, mode); - wcd_clsh_flyback_ctrl(ctrl, mode, true); - wcd_clsh_set_flyback_current(comp, mode); - wcd_clsh_set_buck_mode(comp, mode); - wcd_clsh_buck_ctrl(ctrl, mode, true); - wcd_clsh_set_hph_mode(comp, mode); - wcd_clsh_set_gain_path(ctrl, mode); - } else { - wcd_clsh_set_hph_mode(comp, CLS_H_NORMAL); - - if (mode != CLS_AB) { - snd_soc_component_update_bits(comp, - WCD9XXX_A_CDC_RX1_RX_PATH_CFG0, - WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK, - WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE); - wcd_enable_clsh_block(ctrl, false); - } - /* set buck and flyback to Default Mode */ - wcd_clsh_buck_ctrl(ctrl, CLS_H_NORMAL, false); - wcd_clsh_flyback_ctrl(ctrl, CLS_H_NORMAL, false); - wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL); - wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL); - wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL); - } -} - -static void wcd_clsh_state_ear(struct wcd_clsh_ctrl *ctrl, int req_state, - bool is_enable, int mode) -{ - struct snd_soc_component *comp = ctrl->comp; - - if (mode != CLS_H_NORMAL) { - dev_err(comp->dev, "%s: mode: %d cannot be used for EAR\n", - __func__, mode); - return; - } - - if (is_enable) { - wcd_enable_clsh_block(ctrl, true); - snd_soc_component_update_bits(comp, - WCD9XXX_A_CDC_RX0_RX_PATH_CFG0, - WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK, - WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE); - wcd_clsh_set_buck_mode(comp, mode); - wcd_clsh_set_flyback_mode(comp, mode); - wcd_clsh_flyback_ctrl(ctrl, mode, true); - wcd_clsh_set_flyback_current(comp, mode); - wcd_clsh_buck_ctrl(ctrl, mode, true); - } else { - snd_soc_component_update_bits(comp, - WCD9XXX_A_CDC_RX0_RX_PATH_CFG0, - WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK, - WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE); - wcd_enable_clsh_block(ctrl, false); - wcd_clsh_buck_ctrl(ctrl, mode, false); - wcd_clsh_flyback_ctrl(ctrl, mode, false); - wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL); - wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL); - } -} - -static int _wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl, int req_state, - bool is_enable, int mode) -{ - switch (req_state) { - case WCD_CLSH_STATE_EAR: - wcd_clsh_state_ear(ctrl, req_state, is_enable, mode); - break; - case WCD_CLSH_STATE_HPHL: - wcd_clsh_state_hph_l(ctrl, req_state, is_enable, mode); - break; - case WCD_CLSH_STATE_HPHR: - wcd_clsh_state_hph_r(ctrl, req_state, is_enable, mode); - break; - break; - case WCD_CLSH_STATE_LO: - wcd_clsh_state_lo(ctrl, req_state, is_enable, mode); - break; - default: - break; - } - - return 0; -} - -/* - * Function: wcd_clsh_is_state_valid - * Params: state - * Description: - * Provides information on valid states of Class H configuration - */ -static bool wcd_clsh_is_state_valid(int state) -{ - switch (state) { - case WCD_CLSH_STATE_IDLE: - case WCD_CLSH_STATE_EAR: - case WCD_CLSH_STATE_HPHL: - case WCD_CLSH_STATE_HPHR: - case WCD_CLSH_STATE_LO: - return true; - default: - return false; - }; -} - -/* - * Function: wcd_clsh_fsm - * Params: ctrl, req_state, req_type, clsh_event - * Description: - * This function handles PRE DAC and POST DAC conditions of different devices - * and updates class H configuration of different combination of devices - * based on validity of their states. ctrl will contain current - * class h state information - */ -int wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl, - enum wcd_clsh_event clsh_event, - int nstate, - enum wcd_clsh_mode mode) -{ - struct snd_soc_component *comp = ctrl->comp; - - if (nstate == ctrl->state) - return 0; - - if (!wcd_clsh_is_state_valid(nstate)) { - dev_err(comp->dev, "Class-H not a valid new state:\n"); - return -EINVAL; - } - - switch (clsh_event) { - case WCD_CLSH_EVENT_PRE_DAC: - _wcd_clsh_ctrl_set_state(ctrl, nstate, CLSH_REQ_ENABLE, mode); - break; - case WCD_CLSH_EVENT_POST_PA: - _wcd_clsh_ctrl_set_state(ctrl, nstate, CLSH_REQ_DISABLE, mode); - break; - }; - - ctrl->state = nstate; - ctrl->mode = mode; - - return 0; -} - -int wcd_clsh_ctrl_get_state(struct wcd_clsh_ctrl *ctrl) -{ - return ctrl->state; -} - -struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc(struct snd_soc_component *comp, - int version) -{ - struct wcd_clsh_ctrl *ctrl; - - ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); - if (!ctrl) - return ERR_PTR(-ENOMEM); - - ctrl->state = WCD_CLSH_STATE_IDLE; - ctrl->comp = comp; - - return ctrl; -} - -void wcd_clsh_ctrl_free(struct wcd_clsh_ctrl *ctrl) -{ - kfree(ctrl); -} diff --git a/sound/soc/codecs/wcd-clsh.h b/sound/soc/codecs/wcd-clsh.h deleted file mode 100644 index a902f9893467..000000000000 --- a/sound/soc/codecs/wcd-clsh.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -#ifndef _WCD_CLSH_V2_H_ -#define _WCD_CLSH_V2_H_ -#include - -enum wcd_clsh_event { - WCD_CLSH_EVENT_PRE_DAC = 1, - WCD_CLSH_EVENT_POST_PA, -}; - -/* - * Basic states for Class H state machine. - * represented as a bit mask within a u8 data type - * bit 0: EAR mode - * bit 1: HPH Left mode - * bit 2: HPH Right mode - * bit 3: Lineout mode - */ -#define WCD_CLSH_STATE_IDLE 0 -#define WCD_CLSH_STATE_EAR BIT(0) -#define WCD_CLSH_STATE_HPHL BIT(1) -#define WCD_CLSH_STATE_HPHR BIT(2) -#define WCD_CLSH_STATE_LO BIT(3) -#define WCD_CLSH_STATE_MAX 4 -#define NUM_CLSH_STATES_V2 BIT(WCD_CLSH_STATE_MAX) - -enum wcd_clsh_mode { - CLS_H_NORMAL = 0, /* Class-H Default */ - CLS_H_HIFI, /* Class-H HiFi */ - CLS_H_LP, /* Class-H Low Power */ - CLS_AB, /* Class-AB */ - CLS_H_LOHIFI, /* LoHIFI */ - CLS_NONE, /* None of the above modes */ -}; - -struct wcd_clsh_ctrl; - -extern struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc( - struct snd_soc_component *component, - int version); -extern void wcd_clsh_ctrl_free(struct wcd_clsh_ctrl *ctrl); -extern int wcd_clsh_ctrl_get_state(struct wcd_clsh_ctrl *ctrl); -extern int wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl, - enum wcd_clsh_event event, - int state, - enum wcd_clsh_mode mode); - -#endif /* _WCD_CLSH_V2_H_ */ diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 06c73699f16f..bd9de5d45fa9 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -21,7 +21,6 @@ #include #include #include -#include "wcd-clsh.h" #define WCD9335_RATES_MASK (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ @@ -182,7 +181,6 @@ struct wcd9335_codec { int sido_ccl_cnt; enum wcd_clock_type clk_type; - struct wcd_clsh_ctrl *clsh_ctrl; u32 hph_mode; }; @@ -1068,13 +1066,6 @@ static int wcd9335_codec_probe(struct snd_soc_component *component) int i; snd_soc_component_init_regmap(component, wcd->regmap); - /* Class-H Init*/ - wcd->clsh_ctrl = wcd_clsh_ctrl_alloc(component, wcd->version); - if (IS_ERR(wcd->clsh_ctrl)) - return PTR_ERR(wcd->clsh_ctrl); - - /* Default HPH Mode to Class-H HiFi */ - wcd->hph_mode = CLS_H_HIFI; wcd->component = component; wcd9335_codec_init(component); @@ -1089,7 +1080,6 @@ static void wcd9335_codec_remove(struct snd_soc_component *comp) { struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev); - wcd_clsh_ctrl_free(wcd->clsh_ctrl); free_irq(regmap_irq_get_virq(wcd->irq_data, WCD9335_IRQ_SLIMBUS), wcd); } -- cgit v1.2.3 From b74fd69043262003c5b7ce545e59f5a7234ab290 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 1 Aug 2018 14:22:56 +0100 Subject: ASoC: wcd9335: Fix build This reverts commit e57d4ca882e28 (ASoC: wcd9335: add support to wcd9335 codec) due to build failures caused by missing dependencies. Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 5 - sound/soc/codecs/Makefile | 2 - sound/soc/codecs/wcd9335.c | 1154 -------------------------------------------- 3 files changed, 1161 deletions(-) delete mode 100644 sound/soc/codecs/wcd9335.c (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index cb09abf18dde..efb095dbcd71 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1066,11 +1066,6 @@ config SND_SOC_UDA1380 tristate depends on I2C -config SND_SOC_WCD9335 - tristate "WCD9335 Codec" - depends on MFD_WCD9335 - tristate - config SND_SOC_WL1273 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 01410b63daac..7ae7c85e8219 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -192,7 +192,6 @@ snd-soc-twl4030-objs := twl4030.o snd-soc-twl6040-objs := twl6040.o snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o -snd-soc-wcd9335-objs := wcd9335.o snd-soc-wl1273-objs := wl1273.o snd-soc-wm-adsp-objs := wm_adsp.o snd-soc-wm0010-objs := wm0010.o @@ -452,7 +451,6 @@ obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o -obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o obj-$(CONFIG_SND_SOC_WM0010) += snd-soc-wm0010.o obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c deleted file mode 100644 index bd9de5d45fa9..000000000000 --- a/sound/soc/codecs/wcd9335.c +++ /dev/null @@ -1,1154 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -// Copyright (c) 2017-2018, Linaro Limited - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define WCD9335_RATES_MASK (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ - SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) -/* Fractional Rates */ -#define WCD9335_FRAC_RATES_MASK (SNDRV_PCM_RATE_44100) -#define WCD9335_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S24_LE) - -/* slave port water mark level - * (0: 6bytes, 1: 9bytes, 2: 12 bytes, 3: 15 bytes) - */ -#define SLAVE_PORT_WATER_MARK_6BYTES 0 -#define SLAVE_PORT_WATER_MARK_9BYTES 1 -#define SLAVE_PORT_WATER_MARK_12BYTES 2 -#define SLAVE_PORT_WATER_MARK_15BYTES 3 -#define SLAVE_PORT_WATER_MARK_SHIFT 1 -#define SLAVE_PORT_ENABLE 1 -#define SLAVE_PORT_DISABLE 0 -#define WCD9335_SLIM_WATER_MARK_VAL \ - ((SLAVE_PORT_WATER_MARK_12BYTES << SLAVE_PORT_WATER_MARK_SHIFT) | \ - (SLAVE_PORT_ENABLE)) - -#define WCD9335_SLIM_NUM_PORT_REG 3 -#define WCD9335_SLIM_PGD_PORT_INT_TX_EN0 (WCD9335_SLIM_PGD_PORT_INT_EN0 + 2) - -#define WCD9335_MCLK_CLK_12P288MHZ 12288000 -#define WCD9335_MCLK_CLK_9P6MHZ 9600000 - -#define WCD9335_SLIM_CLOSE_TIMEOUT 1000 -#define WCD9335_SLIM_IRQ_OVERFLOW (1 << 0) -#define WCD9335_SLIM_IRQ_UNDERFLOW (1 << 1) -#define WCD9335_SLIM_IRQ_PORT_CLOSED (1 << 2) - -#define WCD9335_NUM_INTERPOLATORS 9 -#define WCD9335_RX_START 16 -#define WCD9335_SLIM_CH_START 128 - -#define WCD9335_SLIM_RX_CH(p) \ - {.port = p + WCD9335_RX_START, .shift = p,} - -/* vout step value */ -#define WCD9335_CALCULATE_VOUT_D(req_mv) (((req_mv - 650) * 10) / 25) - -enum { - WCD9335_RX0 = 0, - WCD9335_RX1, - WCD9335_RX2, - WCD9335_RX3, - WCD9335_RX4, - WCD9335_RX5, - WCD9335_RX6, - WCD9335_RX7, - WCD9335_RX8, - WCD9335_RX9, - WCD9335_RX10, - WCD9335_RX11, - WCD9335_RX12, - WCD9335_RX_MAX, -}; - -enum { - SIDO_SOURCE_INTERNAL = 0, - SIDO_SOURCE_RCO_BG, -}; - -enum wcd9335_sido_voltage { - SIDO_VOLTAGE_SVS_MV = 950, - SIDO_VOLTAGE_NOMINAL_MV = 1100, -}; - -enum { - AIF1_PB = 0, - AIF1_CAP, - AIF2_PB, - AIF2_CAP, - AIF3_PB, - AIF3_CAP, - AIF4_PB, - NUM_CODEC_DAIS, -}; - -enum { - INTn_2_INP_SEL_ZERO = 0, - INTn_2_INP_SEL_RX0, - INTn_2_INP_SEL_RX1, - INTn_2_INP_SEL_RX2, - INTn_2_INP_SEL_RX3, - INTn_2_INP_SEL_RX4, - INTn_2_INP_SEL_RX5, - INTn_2_INP_SEL_RX6, - INTn_2_INP_SEL_RX7, - INTn_2_INP_SEL_PROXIMITY, -}; - -enum { - INTn_1_MIX_INP_SEL_ZERO = 0, - INTn_1_MIX_INP_SEL_DEC0, - INTn_1_MIX_INP_SEL_DEC1, - INTn_1_MIX_INP_SEL_IIR0, - INTn_1_MIX_INP_SEL_IIR1, - INTn_1_MIX_INP_SEL_RX0, - INTn_1_MIX_INP_SEL_RX1, - INTn_1_MIX_INP_SEL_RX2, - INTn_1_MIX_INP_SEL_RX3, - INTn_1_MIX_INP_SEL_RX4, - INTn_1_MIX_INP_SEL_RX5, - INTn_1_MIX_INP_SEL_RX6, - INTn_1_MIX_INP_SEL_RX7, - -}; - -enum wcd_clock_type { - WCD_CLK_OFF, - WCD_CLK_RCO, - WCD_CLK_MCLK, -}; - -struct wcd9335_slim_ch { - u32 ch_num; - u16 port; - u16 shift; - struct list_head list; -}; - -struct wcd_slim_codec_dai_data { - struct list_head slim_ch_list; - struct slim_stream_config sconfig; - struct slim_stream_runtime *sruntime; -}; - -struct wcd9335_codec { - struct device *dev; - struct clk *mclk; - struct clk *native_clk; - u32 mclk_rate; - u8 intf_type; - u8 version; - - struct slim_device *slim; - struct slim_device *slim_ifd; - struct regmap *regmap; - struct regmap *if_regmap; - struct regmap_irq_chip_data *irq_data; - - struct wcd9335_slim_ch rx_chs[WCD9335_RX_MAX]; - u32 num_rx_port; - - int sido_input_src; - enum wcd9335_sido_voltage sido_voltage; - - struct wcd_slim_codec_dai_data dai[NUM_CODEC_DAIS]; - struct snd_soc_component *component; - - int master_bias_users; - int clk_mclk_users; - int clk_rco_users; - int sido_ccl_cnt; - enum wcd_clock_type clk_type; - - u32 hph_mode; -}; - -static const struct wcd9335_slim_ch wcd9335_rx_chs[WCD9335_RX_MAX] = { - WCD9335_SLIM_RX_CH(0), /* 16 */ - WCD9335_SLIM_RX_CH(1), /* 17 */ - WCD9335_SLIM_RX_CH(2), - WCD9335_SLIM_RX_CH(3), - WCD9335_SLIM_RX_CH(4), - WCD9335_SLIM_RX_CH(5), - WCD9335_SLIM_RX_CH(6), - WCD9335_SLIM_RX_CH(7), - WCD9335_SLIM_RX_CH(8), - WCD9335_SLIM_RX_CH(9), - WCD9335_SLIM_RX_CH(10), - WCD9335_SLIM_RX_CH(11), - WCD9335_SLIM_RX_CH(12), -}; - -struct interp_sample_rate { - int rate; - int rate_val; -}; - -static struct interp_sample_rate int_mix_rate_val[] = { - {48000, 0x4}, /* 48K */ - {96000, 0x5}, /* 96K */ - {192000, 0x6}, /* 192K */ -}; - -static struct interp_sample_rate int_prim_rate_val[] = { - {8000, 0x0}, /* 8K */ - {16000, 0x1}, /* 16K */ - {24000, -EINVAL},/* 24K */ - {32000, 0x3}, /* 32K */ - {48000, 0x4}, /* 48K */ - {96000, 0x5}, /* 96K */ - {192000, 0x6}, /* 192K */ - {384000, 0x7}, /* 384K */ - {44100, 0x8}, /* 44.1K */ -}; - -struct wcd9335_reg_mask_val { - u16 reg; - u8 mask; - u8 val; -}; - -static const struct wcd9335_reg_mask_val wcd9335_codec_reg_init_val_2_0[] = { - {WCD9335_RCO_CTRL_2, 0x0F, 0x08}, - {WCD9335_RX_BIAS_FLYB_MID_RST, 0xF0, 0x10}, - {WCD9335_FLYBACK_CTRL_1, 0x20, 0x20}, - {WCD9335_HPH_OCP_CTL, 0xFF, 0x5A}, - {WCD9335_HPH_L_TEST, 0x01, 0x01}, - {WCD9335_HPH_R_TEST, 0x01, 0x01}, - {WCD9335_CDC_BOOST0_BOOST_CFG1, 0x3F, 0x12}, - {WCD9335_CDC_BOOST0_BOOST_CFG2, 0x1C, 0x08}, - {WCD9335_CDC_COMPANDER7_CTL7, 0x1E, 0x18}, - {WCD9335_CDC_BOOST1_BOOST_CFG1, 0x3F, 0x12}, - {WCD9335_CDC_BOOST1_BOOST_CFG2, 0x1C, 0x08}, - {WCD9335_CDC_COMPANDER8_CTL7, 0x1E, 0x18}, - {WCD9335_CDC_TX0_TX_PATH_SEC7, 0xFF, 0x45}, - {WCD9335_CDC_RX0_RX_PATH_SEC0, 0xFC, 0xF4}, - {WCD9335_HPH_REFBUFF_LP_CTL, 0x08, 0x08}, - {WCD9335_HPH_REFBUFF_LP_CTL, 0x06, 0x02}, -}; - -static const struct wcd9335_reg_mask_val wcd9335_codec_reg_init_common_val[] = { - /* Rbuckfly/R_EAR(32) */ - {WCD9335_CDC_CLSH_K2_MSB, 0x0F, 0x00}, - {WCD9335_CDC_CLSH_K2_LSB, 0xFF, 0x60}, - {WCD9335_CPE_SS_DMIC_CFG, 0x80, 0x00}, - {WCD9335_CDC_BOOST0_BOOST_CTL, 0x70, 0x50}, - {WCD9335_CDC_BOOST1_BOOST_CTL, 0x70, 0x50}, - {WCD9335_CDC_RX7_RX_PATH_CFG1, 0x08, 0x08}, - {WCD9335_CDC_RX8_RX_PATH_CFG1, 0x08, 0x08}, - {WCD9335_ANA_LO_1_2, 0x3C, 0X3C}, - {WCD9335_DIFF_LO_COM_SWCAP_REFBUF_FREQ, 0x70, 0x00}, - {WCD9335_DIFF_LO_COM_PA_FREQ, 0x70, 0x40}, - {WCD9335_SOC_MAD_AUDIO_CTL_2, 0x03, 0x03}, - {WCD9335_CDC_TOP_TOP_CFG1, 0x02, 0x02}, - {WCD9335_CDC_TOP_TOP_CFG1, 0x01, 0x01}, - {WCD9335_EAR_CMBUFF, 0x08, 0x00}, - {WCD9335_CDC_TX9_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, - {WCD9335_CDC_TX10_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, - {WCD9335_CDC_TX11_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, - {WCD9335_CDC_TX12_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, - {WCD9335_CDC_COMPANDER7_CTL3, 0x80, 0x80}, - {WCD9335_CDC_COMPANDER8_CTL3, 0x80, 0x80}, - {WCD9335_CDC_COMPANDER7_CTL7, 0x01, 0x01}, - {WCD9335_CDC_COMPANDER8_CTL7, 0x01, 0x01}, - {WCD9335_CDC_RX0_RX_PATH_CFG0, 0x01, 0x01}, - {WCD9335_CDC_RX1_RX_PATH_CFG0, 0x01, 0x01}, - {WCD9335_CDC_RX2_RX_PATH_CFG0, 0x01, 0x01}, - {WCD9335_CDC_RX3_RX_PATH_CFG0, 0x01, 0x01}, - {WCD9335_CDC_RX4_RX_PATH_CFG0, 0x01, 0x01}, - {WCD9335_CDC_RX5_RX_PATH_CFG0, 0x01, 0x01}, - {WCD9335_CDC_RX6_RX_PATH_CFG0, 0x01, 0x01}, - {WCD9335_CDC_RX7_RX_PATH_CFG0, 0x01, 0x01}, - {WCD9335_CDC_RX8_RX_PATH_CFG0, 0x01, 0x01}, - {WCD9335_CDC_RX0_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD9335_CDC_RX1_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD9335_CDC_RX2_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD9335_CDC_RX3_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD9335_CDC_RX4_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD9335_CDC_RX5_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD9335_CDC_RX6_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD9335_CDC_RX7_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD9335_CDC_RX8_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD9335_VBADC_IBIAS_FE, 0x0C, 0x08}, -}; - -static int wcd9335_set_mix_interpolator_rate(struct snd_soc_dai *dai, - int rate_val, - u32 rate) -{ - struct snd_soc_component *component = dai->component; - struct wcd9335_codec *wcd = dev_get_drvdata(component->dev); - struct wcd9335_slim_ch *ch; - int val, j; - - list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list) { - for (j = 0; j < WCD9335_NUM_INTERPOLATORS; j++) { - val = snd_soc_component_read32(component, - WCD9335_CDC_RX_INP_MUX_RX_INT_CFG1(j)) & - WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK; - - if (val == (ch->shift + INTn_2_INP_SEL_RX0)) - snd_soc_component_update_bits(component, - WCD9335_CDC_RX_PATH_MIX_CTL(j), - WCD9335_CDC_MIX_PCM_RATE_MASK, - rate_val); - } - } - - return 0; -} - -static int wcd9335_set_prim_interpolator_rate(struct snd_soc_dai *dai, - u8 rate_val, - u32 rate) -{ - struct snd_soc_component *comp = dai->component; - struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev); - struct wcd9335_slim_ch *ch; - u8 cfg0, cfg1, inp0_sel, inp1_sel, inp2_sel; - int inp, j; - - list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list) { - inp = ch->shift + INTn_1_MIX_INP_SEL_RX0; - /* - * Loop through all interpolator MUX inputs and find out - * to which interpolator input, the slim rx port - * is connected - */ - for (j = 0; j < WCD9335_NUM_INTERPOLATORS; j++) { - cfg0 = snd_soc_component_read32(comp, - WCD9335_CDC_RX_INP_MUX_RX_INT_CFG0(j)); - cfg1 = snd_soc_component_read32(comp, - WCD9335_CDC_RX_INP_MUX_RX_INT_CFG1(j)); - - inp0_sel = cfg0 & WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK; - inp1_sel = (cfg0 >> 4) & WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK; - inp2_sel = (cfg1 >> 4) & WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK; - - if ((inp0_sel == inp) || (inp1_sel == inp) || - (inp2_sel == inp)) { - /* rate is in Hz */ - if ((j == 0) && (rate == 44100)) - dev_info(wcd->dev, - "Cannot set 44.1KHz on INT0\n"); - else - snd_soc_component_update_bits(comp, - WCD9335_CDC_RX_PATH_CTL(j), - WCD9335_CDC_MIX_PCM_RATE_MASK, - rate_val); - } - } - } - - return 0; -} - -static int wcd9335_set_interpolator_rate(struct snd_soc_dai *dai, u32 rate) -{ - int i; - - /* set mixing path rate */ - for (i = 0; i < ARRAY_SIZE(int_mix_rate_val); i++) { - if (rate == int_mix_rate_val[i].rate) { - wcd9335_set_mix_interpolator_rate(dai, - int_mix_rate_val[i].rate_val, rate); - break; - } - } - - /* set primary path sample rate */ - for (i = 0; i < ARRAY_SIZE(int_prim_rate_val); i++) { - if (rate == int_prim_rate_val[i].rate) { - wcd9335_set_prim_interpolator_rate(dai, - int_prim_rate_val[i].rate_val, rate); - break; - } - } - - return 0; -} - -static int wcd9335_slim_set_hw_params(struct wcd9335_codec *wcd, - struct wcd_slim_codec_dai_data *dai_data, - int direction) -{ - struct list_head *slim_ch_list = &dai_data->slim_ch_list; - struct slim_stream_config *cfg = &dai_data->sconfig; - struct wcd9335_slim_ch *ch; - u16 payload = 0; - int ret, i; - - cfg->ch_count = 0; - cfg->direction = direction; - cfg->port_mask = 0; - - /* Configure slave interface device */ - list_for_each_entry(ch, slim_ch_list, list) { - cfg->ch_count++; - payload |= 1 << ch->shift; - cfg->port_mask |= BIT(ch->port); - } - - cfg->chs = kcalloc(cfg->ch_count, sizeof(unsigned int), GFP_KERNEL); - if (!cfg->chs) - return -ENOMEM; - - i = 0; - list_for_each_entry(ch, slim_ch_list, list) { - cfg->chs[i++] = ch->ch_num; - if (direction == SNDRV_PCM_STREAM_PLAYBACK) { - /* write to interface device */ - ret = regmap_write(wcd->if_regmap, - WCD9335_SLIM_PGD_RX_PORT_MULTI_CHNL_0(ch->port), - payload); - - if (ret < 0) - goto err; - - /* configure the slave port for water mark and enable*/ - ret = regmap_write(wcd->if_regmap, - WCD9335_SLIM_PGD_RX_PORT_CFG(ch->port), - WCD9335_SLIM_WATER_MARK_VAL); - if (ret < 0) - goto err; - } - } - - dai_data->sruntime = slim_stream_allocate(wcd->slim, "WCD9335-SLIM"); - slim_stream_prepare(dai_data->sruntime, cfg); - - return 0; - -err: - dev_err(wcd->dev, "Error Setting slim hw params\n"); - kfree(cfg->chs); - cfg->chs = NULL; - - return ret; -} - -static int wcd9335_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct wcd9335_codec *wcd; - int ret; - - wcd = snd_soc_component_get_drvdata(dai->component); - - switch (substream->stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - ret = wcd9335_set_interpolator_rate(dai, params_rate(params)); - if (ret) { - dev_err(wcd->dev, "cannot set sample rate: %u\n", - params_rate(params)); - return ret; - } - switch (params_width(params)) { - case 16 ... 24: - wcd->dai[dai->id].sconfig.bps = params_width(params); - break; - default: - dev_err(wcd->dev, "%s: Invalid format 0x%x\n", - __func__, params_width(params)); - return -EINVAL; - } - break; - default: - dev_err(wcd->dev, "Invalid stream type %d\n", - substream->stream); - return -EINVAL; - }; - - wcd->dai[dai->id].sconfig.rate = params_rate(params); - wcd9335_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream); - - return 0; -} - -static int wcd9335_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct wcd_slim_codec_dai_data *dai_data; - struct wcd9335_codec *wcd; - - wcd = snd_soc_component_get_drvdata(dai->component); - dai_data = &wcd->dai[dai->id]; - slim_stream_enable(dai_data->sruntime); - - return 0; -} - -static int wcd9335_set_channel_map(struct snd_soc_dai *dai, - unsigned int tx_num, unsigned int *tx_slot, - unsigned int rx_num, unsigned int *rx_slot) -{ - struct wcd9335_codec *wcd; - int i; - - wcd = snd_soc_component_get_drvdata(dai->component); - - if (!tx_slot || !rx_slot) { - dev_err(wcd->dev, "Invalid tx_slot=%p, rx_slot=%p\n", - tx_slot, rx_slot); - return -EINVAL; - } - - if (wcd->rx_chs) { - wcd->num_rx_port = rx_num; - for (i = 0; i < rx_num; i++) { - wcd->rx_chs[i].ch_num = rx_slot[i]; - INIT_LIST_HEAD(&wcd->rx_chs[i].list); - } - } - - return 0; -} - -static int wcd9335_get_channel_map(struct snd_soc_dai *dai, - unsigned int *tx_num, unsigned int *tx_slot, - unsigned int *rx_num, unsigned int *rx_slot) -{ - struct wcd9335_slim_ch *ch; - struct wcd9335_codec *wcd; - int i = 0; - - wcd = snd_soc_component_get_drvdata(dai->component); - - switch (dai->id) { - case AIF1_PB: - case AIF2_PB: - case AIF3_PB: - case AIF4_PB: - if (!rx_slot || !rx_num) { - dev_err(wcd->dev, "Invalid rx_slot %p or rx_num %p\n", - rx_slot, rx_num); - return -EINVAL; - } - - list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list) - rx_slot[i++] = ch->ch_num; - - *rx_num = i; - break; - default: - dev_err(wcd->dev, "Invalid DAI ID %x\n", dai->id); - break; - } - - return 0; -} - -static struct snd_soc_dai_ops wcd9335_dai_ops = { - .hw_params = wcd9335_hw_params, - .prepare = wcd9335_prepare, - .set_channel_map = wcd9335_set_channel_map, - .get_channel_map = wcd9335_get_channel_map, -}; - -static struct snd_soc_dai_driver wcd9335_slim_dais[] = { - [0] = { - .name = "wcd9335_rx1", - .id = AIF1_PB, - .playback = { - .stream_name = "AIF1 Playback", - .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK, - .formats = WCD9335_FORMATS_S16_S24_LE, - .rate_max = 192000, - .rate_min = 8000, - .channels_min = 1, - .channels_max = 2, - }, - .ops = &wcd9335_dai_ops, - }, - [1] = { - .name = "wcd9335_tx1", - .id = AIF1_CAP, - .capture = { - .stream_name = "AIF1 Capture", - .rates = WCD9335_RATES_MASK, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 4, - }, - .ops = &wcd9335_dai_ops, - }, - [2] = { - .name = "wcd9335_rx2", - .id = AIF2_PB, - .playback = { - .stream_name = "AIF2 Playback", - .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK, - .formats = WCD9335_FORMATS_S16_S24_LE, - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 2, - }, - .ops = &wcd9335_dai_ops, - }, - [3] = { - .name = "wcd9335_tx2", - .id = AIF2_CAP, - .capture = { - .stream_name = "AIF2 Capture", - .rates = WCD9335_RATES_MASK, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 4, - }, - .ops = &wcd9335_dai_ops, - }, - [4] = { - .name = "wcd9335_rx3", - .id = AIF3_PB, - .playback = { - .stream_name = "AIF3 Playback", - .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK, - .formats = WCD9335_FORMATS_S16_S24_LE, - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 2, - }, - .ops = &wcd9335_dai_ops, - }, - [5] = { - .name = "wcd9335_tx3", - .id = AIF3_CAP, - .capture = { - .stream_name = "AIF3 Capture", - .rates = WCD9335_RATES_MASK, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 4, - }, - .ops = &wcd9335_dai_ops, - }, - [6] = { - .name = "wcd9335_rx4", - .id = AIF4_PB, - .playback = { - .stream_name = "AIF4 Playback", - .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK, - .formats = WCD9335_FORMATS_S16_S24_LE, - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 2, - }, - .ops = &wcd9335_dai_ops, - }, -}; - -static irqreturn_t wcd9335_slimbus_irq(int irq, void *data) -{ - struct wcd9335_codec *wcd = data; - unsigned long status = 0; - int i, j, port_id; - unsigned int val, int_val = 0; - bool tx; - unsigned short reg = 0; - - for (i = WCD9335_SLIM_PGD_PORT_INT_STATUS_RX_0, j = 0; - i <= WCD9335_SLIM_PGD_PORT_INT_STATUS_TX_1; i++, j++) { - regmap_read(wcd->if_regmap, i, &val); - status |= ((u32)val << (8 * j)); - } - - for_each_set_bit(j, &status, 32) { - tx = (j >= 16 ? true : false); - port_id = (tx ? j - 16 : j); - regmap_read(wcd->if_regmap, - WCD9335_SLIM_PGD_PORT_INT_RX_SOURCE0 + j, &val); - if (val) { - if (!tx) - reg = WCD9335_SLIM_PGD_PORT_INT_EN0 + - (port_id / 8); - else - reg = WCD9335_SLIM_PGD_PORT_INT_TX_EN0 + - (port_id / 8); - regmap_read( - wcd->if_regmap, reg, &int_val); - /* - * Ignore interrupts for ports for which the - * interrupts are not specifically enabled. - */ - if (!(int_val & (1 << (port_id % 8)))) - continue; - } - if (val & WCD9335_SLIM_IRQ_OVERFLOW) - dev_err_ratelimited(wcd->dev, - "%s: overflow error on %s port %d, value %x\n", - __func__, (tx ? "TX" : "RX"), port_id, val); - if (val & WCD9335_SLIM_IRQ_UNDERFLOW) - dev_err_ratelimited(wcd->dev, - "%s: underflow error on %s port %d, value %x\n", - __func__, (tx ? "TX" : "RX"), port_id, val); - if ((val & WCD9335_SLIM_IRQ_OVERFLOW) || - (val & WCD9335_SLIM_IRQ_UNDERFLOW)) { - if (!tx) - reg = WCD9335_SLIM_PGD_PORT_INT_EN0 + - (port_id / 8); - else - reg = WCD9335_SLIM_PGD_PORT_INT_TX_EN0 + - (port_id / 8); - regmap_read( - wcd->if_regmap, reg, &int_val); - if (int_val & (1 << (port_id % 8))) { - int_val = int_val ^ (1 << (port_id % 8)); - regmap_write(wcd->if_regmap, - reg, int_val); - } - } - - regmap_write(wcd->if_regmap, - WCD9335_SLIM_PGD_PORT_INT_CLR_RX_0 + (j / 8), - BIT(j % 8)); - } - - return IRQ_HANDLED; -} - -static int wcd9335_setup_irqs(struct wcd9335_codec *wcd) -{ - int slim_irq = regmap_irq_get_virq(wcd->irq_data, WCD9335_IRQ_SLIMBUS); - int i, ret = 0; - - ret = request_threaded_irq(slim_irq, NULL, wcd9335_slimbus_irq, - IRQF_TRIGGER_RISING, "SLIMBus Slave", wcd); - if (ret) { - dev_err(wcd->dev, "Failed to request SLIMBUS irq\n"); - return ret; - } - - /* enable interrupts on all slave ports */ - for (i = 0; i < WCD9335_SLIM_NUM_PORT_REG; i++) - regmap_write(wcd->if_regmap, WCD9335_SLIM_PGD_PORT_INT_EN0 + i, - 0xFF); - - return ret; -} - -static void wcd9335_cdc_sido_ccl_enable(struct wcd9335_codec *wcd, - bool ccl_flag) -{ - struct snd_soc_component *comp = wcd->component; - - if (ccl_flag) { - if (++wcd->sido_ccl_cnt == 1) - snd_soc_component_write(comp, WCD9335_SIDO_SIDO_CCL_10, - WCD9335_SIDO_SIDO_CCL_DEF_VALUE); - } else { - if (wcd->sido_ccl_cnt == 0) { - dev_err(wcd->dev, "sido_ccl already disabled\n"); - return; - } - if (--wcd->sido_ccl_cnt == 0) - snd_soc_component_write(comp, WCD9335_SIDO_SIDO_CCL_10, - WCD9335_SIDO_SIDO_CCL_10_ICHARG_PWR_SEL_C320FF); - } -} - -static int wcd9335_enable_master_bias(struct wcd9335_codec *wcd) -{ - wcd->master_bias_users++; - if (wcd->master_bias_users == 1) { - regmap_update_bits(wcd->regmap, WCD9335_ANA_BIAS, - WCD9335_ANA_BIAS_EN_MASK, - WCD9335_ANA_BIAS_ENABLE); - regmap_update_bits(wcd->regmap, WCD9335_ANA_BIAS, - WCD9335_ANA_BIAS_PRECHRG_EN_MASK, - WCD9335_ANA_BIAS_PRECHRG_ENABLE); - /* - * 1ms delay is required after pre-charge is enabled - * as per HW requirement - */ - usleep_range(1000, 1100); - regmap_update_bits(wcd->regmap, WCD9335_ANA_BIAS, - WCD9335_ANA_BIAS_PRECHRG_EN_MASK, - WCD9335_ANA_BIAS_PRECHRG_DISABLE); - regmap_update_bits(wcd->regmap, WCD9335_ANA_BIAS, - WCD9335_ANA_BIAS_PRECHRG_CTL_MODE, - WCD9335_ANA_BIAS_PRECHRG_CTL_MODE_MANUAL); - } - - return 0; -} - -static int wcd9335_enable_mclk(struct wcd9335_codec *wcd) -{ - /* Enable mclk requires master bias to be enabled first */ - if (wcd->master_bias_users <= 0) - return -EINVAL; - - if (((wcd->clk_mclk_users == 0) && (wcd->clk_type == WCD_CLK_MCLK)) || - ((wcd->clk_mclk_users > 0) && (wcd->clk_type != WCD_CLK_MCLK))) { - dev_err(wcd->dev, "Error enabling MCLK, clk_type: %d\n", - wcd->clk_type); - return -EINVAL; - } - - if (++wcd->clk_mclk_users == 1) { - regmap_update_bits(wcd->regmap, WCD9335_ANA_CLK_TOP, - WCD9335_ANA_CLK_EXT_CLKBUF_EN_MASK, - WCD9335_ANA_CLK_EXT_CLKBUF_ENABLE); - regmap_update_bits(wcd->regmap, WCD9335_ANA_CLK_TOP, - WCD9335_ANA_CLK_MCLK_SRC_MASK, - WCD9335_ANA_CLK_MCLK_SRC_EXTERNAL); - regmap_update_bits(wcd->regmap, WCD9335_ANA_CLK_TOP, - WCD9335_ANA_CLK_MCLK_EN_MASK, - WCD9335_ANA_CLK_MCLK_ENABLE); - regmap_update_bits(wcd->regmap, - WCD9335_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, - WCD9335_CDC_CLK_RST_CTRL_FS_CNT_EN_MASK, - WCD9335_CDC_CLK_RST_CTRL_FS_CNT_ENABLE); - regmap_update_bits(wcd->regmap, - WCD9335_CDC_CLK_RST_CTRL_MCLK_CONTROL, - WCD9335_CDC_CLK_RST_CTRL_MCLK_EN_MASK, - WCD9335_CDC_CLK_RST_CTRL_MCLK_ENABLE); - /* - * 10us sleep is required after clock is enabled - * as per HW requirement - */ - usleep_range(10, 15); - } - - wcd->clk_type = WCD_CLK_MCLK; - - return 0; -} - -static int wcd9335_disable_mclk(struct wcd9335_codec *wcd) -{ - if (wcd->clk_mclk_users <= 0) - return -EINVAL; - - if (--wcd->clk_mclk_users == 0) { - if (wcd->clk_rco_users > 0) { - /* MCLK to RCO switch */ - regmap_update_bits(wcd->regmap, WCD9335_ANA_CLK_TOP, - WCD9335_ANA_CLK_MCLK_SRC_MASK, - WCD9335_ANA_CLK_MCLK_SRC_RCO); - wcd->clk_type = WCD_CLK_RCO; - } else { - regmap_update_bits(wcd->regmap, WCD9335_ANA_CLK_TOP, - WCD9335_ANA_CLK_MCLK_EN_MASK, - WCD9335_ANA_CLK_MCLK_DISABLE); - wcd->clk_type = WCD_CLK_OFF; - } - - regmap_update_bits(wcd->regmap, WCD9335_ANA_CLK_TOP, - WCD9335_ANA_CLK_EXT_CLKBUF_EN_MASK, - WCD9335_ANA_CLK_EXT_CLKBUF_DISABLE); - } - - return 0; -} - -static int wcd9335_disable_master_bias(struct wcd9335_codec *wcd) -{ - if (wcd->master_bias_users <= 0) - return -EINVAL; - - wcd->master_bias_users--; - if (wcd->master_bias_users == 0) { - regmap_update_bits(wcd->regmap, WCD9335_ANA_BIAS, - WCD9335_ANA_BIAS_EN_MASK, - WCD9335_ANA_BIAS_DISABLE); - regmap_update_bits(wcd->regmap, WCD9335_ANA_BIAS, - WCD9335_ANA_BIAS_PRECHRG_CTL_MODE, - WCD9335_ANA_BIAS_PRECHRG_CTL_MODE_MANUAL); - } - return 0; -} - -static int wcd9335_cdc_req_mclk_enable(struct wcd9335_codec *wcd, - bool enable) -{ - int ret = 0; - - if (enable) { - wcd9335_cdc_sido_ccl_enable(wcd, true); - ret = clk_prepare_enable(wcd->mclk); - if (ret) { - dev_err(wcd->dev, "%s: ext clk enable failed\n", - __func__); - goto err; - } - /* get BG */ - wcd9335_enable_master_bias(wcd); - /* get MCLK */ - wcd9335_enable_mclk(wcd); - - } else { - /* put MCLK */ - wcd9335_disable_mclk(wcd); - /* put BG */ - wcd9335_disable_master_bias(wcd); - clk_disable_unprepare(wcd->mclk); - wcd9335_cdc_sido_ccl_enable(wcd, false); - } -err: - return ret; -} - -static void wcd9335_codec_apply_sido_voltage(struct wcd9335_codec *wcd, - enum wcd9335_sido_voltage req_mv) -{ - struct snd_soc_component *comp = wcd->component; - int vout_d_val; - - if (req_mv == wcd->sido_voltage) - return; - - /* compute the vout_d step value */ - vout_d_val = WCD9335_CALCULATE_VOUT_D(req_mv) & - WCD9335_ANA_BUCK_VOUT_MASK; - snd_soc_component_write(comp, WCD9335_ANA_BUCK_VOUT_D, vout_d_val); - snd_soc_component_update_bits(comp, WCD9335_ANA_BUCK_CTL, - WCD9335_ANA_BUCK_CTL_RAMP_START_MASK, - WCD9335_ANA_BUCK_CTL_RAMP_START_ENABLE); - - /* 1 msec sleep required after SIDO Vout_D voltage change */ - usleep_range(1000, 1100); - wcd->sido_voltage = req_mv; - snd_soc_component_update_bits(comp, WCD9335_ANA_BUCK_CTL, - WCD9335_ANA_BUCK_CTL_RAMP_START_MASK, - WCD9335_ANA_BUCK_CTL_RAMP_START_DISABLE); -} - -static int wcd9335_codec_update_sido_voltage(struct wcd9335_codec *wcd, - enum wcd9335_sido_voltage req_mv) -{ - int ret = 0; - - /* enable mclk before setting SIDO voltage */ - ret = wcd9335_cdc_req_mclk_enable(wcd, true); - if (ret) { - dev_err(wcd->dev, "Ext clk enable failed\n"); - goto err; - } - - wcd9335_codec_apply_sido_voltage(wcd, req_mv); - wcd9335_cdc_req_mclk_enable(wcd, false); - -err: - return ret; -} - -static int _wcd9335_codec_enable_mclk(struct snd_soc_component *component, - int enable) -{ - struct wcd9335_codec *wcd = dev_get_drvdata(component->dev); - int ret; - - if (enable) { - ret = wcd9335_cdc_req_mclk_enable(wcd, true); - if (ret) - return ret; - - wcd9335_codec_apply_sido_voltage(wcd, - SIDO_VOLTAGE_NOMINAL_MV); - } else { - wcd9335_codec_update_sido_voltage(wcd, - wcd->sido_voltage); - wcd9335_cdc_req_mclk_enable(wcd, false); - } - - return 0; -} - -static void wcd9335_enable_sido_buck(struct snd_soc_component *component) -{ - struct wcd9335_codec *wcd = dev_get_drvdata(component->dev); - - snd_soc_component_update_bits(component, WCD9335_ANA_RCO, - WCD9335_ANA_RCO_BG_EN_MASK, - WCD9335_ANA_RCO_BG_ENABLE); - snd_soc_component_update_bits(component, WCD9335_ANA_BUCK_CTL, - WCD9335_ANA_BUCK_CTL_VOUT_D_IREF_MASK, - WCD9335_ANA_BUCK_CTL_VOUT_D_IREF_EXT); - /* 100us sleep needed after IREF settings */ - usleep_range(100, 110); - snd_soc_component_update_bits(component, WCD9335_ANA_BUCK_CTL, - WCD9335_ANA_BUCK_CTL_VOUT_D_VREF_MASK, - WCD9335_ANA_BUCK_CTL_VOUT_D_VREF_EXT); - /* 100us sleep needed after VREF settings */ - usleep_range(100, 110); - wcd->sido_input_src = SIDO_SOURCE_RCO_BG; -} - -static int wcd9335_enable_efuse_sensing(struct snd_soc_component *comp) -{ - _wcd9335_codec_enable_mclk(comp, true); - snd_soc_component_update_bits(comp, - WCD9335_CHIP_TIER_CTRL_EFUSE_CTL, - WCD9335_CHIP_TIER_CTRL_EFUSE_EN_MASK, - WCD9335_CHIP_TIER_CTRL_EFUSE_ENABLE); - /* - * 5ms sleep required after enabling efuse control - * before checking the status. - */ - usleep_range(5000, 5500); - - if (!(snd_soc_component_read32(comp, - WCD9335_CHIP_TIER_CTRL_EFUSE_STATUS) & - WCD9335_CHIP_TIER_CTRL_EFUSE_EN_MASK)) - WARN(1, "%s: Efuse sense is not complete\n", __func__); - - wcd9335_enable_sido_buck(comp); - _wcd9335_codec_enable_mclk(comp, false); - - return 0; -} - -static void wcd9335_codec_init(struct snd_soc_component *component) -{ - struct wcd9335_codec *wcd = dev_get_drvdata(component->dev); - int i; - - /* ungate MCLK and set clk rate */ - regmap_update_bits(wcd->regmap, WCD9335_CODEC_RPM_CLK_GATE, - WCD9335_CODEC_RPM_CLK_GATE_MCLK_GATE_MASK, 0); - - regmap_update_bits(wcd->regmap, WCD9335_CODEC_RPM_CLK_MCLK_CFG, - WCD9335_CODEC_RPM_CLK_MCLK_CFG_MCLK_MASK, - WCD9335_CODEC_RPM_CLK_MCLK_CFG_9P6MHZ); - - for (i = 0; i < ARRAY_SIZE(wcd9335_codec_reg_init_common_val); i++) - snd_soc_component_update_bits(component, - wcd9335_codec_reg_init_common_val[i].reg, - wcd9335_codec_reg_init_common_val[i].mask, - wcd9335_codec_reg_init_common_val[i].val); - - if (WCD9335_IS_2_0(wcd->version)) { - for (i = 0; i < ARRAY_SIZE(wcd9335_codec_reg_init_val_2_0); i++) - snd_soc_component_update_bits(component, - wcd9335_codec_reg_init_val_2_0[i].reg, - wcd9335_codec_reg_init_val_2_0[i].mask, - wcd9335_codec_reg_init_val_2_0[i].val); - } - - wcd9335_enable_efuse_sensing(component); -} - -static int wcd9335_codec_probe(struct snd_soc_component *component) -{ - struct wcd9335_codec *wcd = dev_get_drvdata(component->dev); - int i; - - snd_soc_component_init_regmap(component, wcd->regmap); - wcd->component = component; - - wcd9335_codec_init(component); - - for (i = 0; i < NUM_CODEC_DAIS; i++) - INIT_LIST_HEAD(&wcd->dai[i].slim_ch_list); - - return wcd9335_setup_irqs(wcd); -} - -static void wcd9335_codec_remove(struct snd_soc_component *comp) -{ - struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev); - - free_irq(regmap_irq_get_virq(wcd->irq_data, WCD9335_IRQ_SLIMBUS), wcd); -} - -static int wcd9335_codec_set_sysclk(struct snd_soc_component *comp, - int clk_id, int source, - unsigned int freq, int dir) -{ - struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev); - - wcd->mclk_rate = freq; - - if (wcd->mclk_rate == WCD9335_MCLK_CLK_12P288MHZ) - snd_soc_component_update_bits(comp, - WCD9335_CODEC_RPM_CLK_MCLK_CFG, - WCD9335_CODEC_RPM_CLK_MCLK_CFG_MCLK_MASK, - WCD9335_CODEC_RPM_CLK_MCLK_CFG_12P288MHZ); - else if (wcd->mclk_rate == WCD9335_MCLK_CLK_9P6MHZ) - snd_soc_component_update_bits(comp, - WCD9335_CODEC_RPM_CLK_MCLK_CFG, - WCD9335_CODEC_RPM_CLK_MCLK_CFG_MCLK_MASK, - WCD9335_CODEC_RPM_CLK_MCLK_CFG_9P6MHZ); - - return clk_set_rate(wcd->mclk, freq); -} - -static const struct snd_soc_component_driver wcd9335_component_drv = { - .probe = wcd9335_codec_probe, - .remove = wcd9335_codec_remove, - .set_sysclk = wcd9335_codec_set_sysclk, -}; - -static int wcd9335_probe(struct platform_device *pdev) -{ - struct wcd9335 *pdata = dev_get_drvdata(pdev->dev.parent); - struct device *dev = &pdev->dev; - struct wcd9335_codec *wcd; - - wcd = devm_kzalloc(dev, sizeof(*wcd), GFP_KERNEL); - if (!wcd) - return -ENOMEM; - - dev_set_drvdata(dev, wcd); - - memcpy(wcd->rx_chs, wcd9335_rx_chs, sizeof(wcd9335_rx_chs)); - - wcd->regmap = pdata->regmap; - wcd->if_regmap = pdata->ifd_regmap; - wcd->slim = pdata->slim; - wcd->slim_ifd = pdata->slim_ifd; - wcd->irq_data = pdata->irq_data; - wcd->version = pdata->version; - wcd->intf_type = pdata->intf_type; - wcd->dev = dev; - wcd->mclk = pdata->mclk; - wcd->native_clk = pdata->native_clk; - wcd->sido_input_src = SIDO_SOURCE_INTERNAL; - wcd->sido_voltage = SIDO_VOLTAGE_NOMINAL_MV; - - return devm_snd_soc_register_component(dev, &wcd9335_component_drv, - wcd9335_slim_dais, - ARRAY_SIZE(wcd9335_slim_dais)); -} - -static struct platform_driver wcd9335_codec_driver = { - .probe = wcd9335_probe, - .driver = { - .name = "wcd9335-codec", - }, -}; -module_platform_driver(wcd9335_codec_driver); -MODULE_DESCRIPTION("WCD9335 Codec driver"); -MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 9a73f6a235c2351adc07471519d4980e2fb33bbc Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 14:47:09 -0500 Subject: ASoC: wm8961: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 1271173 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/wm8961.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index f70f563d59f3..68b4cadc308f 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -653,6 +653,7 @@ static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_B: aif |= WM8961_LRP; + /* fall through */ case SND_SOC_DAIFMT_DSP_A: aif |= 3; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -- cgit v1.2.3 From 065dcc270af66acb4226b49f635b41a054b663d4 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 14:49:13 -0500 Subject: ASoC: rt5640: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 1056547 ("Missing break in switch") Addresses-Coverity-ID: 1056548 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/rt5640.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 8bf8d360c25f..27770143ae8f 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -1665,6 +1665,7 @@ static int get_sdp_info(struct snd_soc_component *component, int dai_id) break; case RT5640_IF_113: ret |= RT5640_U_IF1; + /* fall through */ case RT5640_IF_312: case RT5640_IF_213: ret |= RT5640_U_IF2; @@ -1680,6 +1681,7 @@ static int get_sdp_info(struct snd_soc_component *component, int dai_id) break; case RT5640_IF_223: ret |= RT5640_U_IF1; + /* fall through */ case RT5640_IF_123: case RT5640_IF_321: ret |= RT5640_U_IF2; -- cgit v1.2.3 From 43a26bd026dab09a8b28c40e94ba534a52375b20 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 14:50:20 -0500 Subject: ASoC: rt5677: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 1271174 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 8a0181a2db08..922becfee59b 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -4417,6 +4417,7 @@ static int rt5677_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, break; case 25: slot_width_25 = 0x8080; + /* fall through */ case 24: val |= (2 << 8); break; -- cgit v1.2.3 From 85e7e77079f3201799467803f6c8533a9921e32d Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 14:51:18 -0500 Subject: ASoC: wm8955: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 115047 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/wm8955.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index ba44e3d6c1e0..cd204f79647d 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -686,6 +686,7 @@ static int wm8955_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif |= WM8955_LRP; + /* fall through */ case SND_SOC_DAIFMT_DSP_A: aif |= 0x3; break; -- cgit v1.2.3 From 3eb7dbc6d844d2033271434d02ff90ac9b19e393 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 14:51:59 -0500 Subject: ASoC: wm8960: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 115041 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/wm8960.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index c30f5aa392c6..8dc1f3d6a988 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -839,6 +839,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, iface |= 0x000c; break; } + /* fall through */ default: dev_err(component->dev, "unsupported width %d\n", params_width(params)); -- cgit v1.2.3 From da41787b9f319a7a23fcc8cf65c6ad646803962e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 14:52:41 -0500 Subject: ASoC: wm8904: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 115042 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/wm8904.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 9037a35b931d..1965635ec07c 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -1455,6 +1455,7 @@ static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif1 |= 0x3 | WM8904_AIF_LRCLK_INV; + /* fall through */ case SND_SOC_DAIFMT_DSP_A: aif1 |= 0x3; break; -- cgit v1.2.3 From 42ef3c94ff6e8315377c04504f1bce50d1f21738 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 14:53:19 -0500 Subject: ASoC: wm8996: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 146354 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/wm8996.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index d9d206046f8c..78a408236cfb 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -1858,6 +1858,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai, case 24576000: ratediv = WM8996_SYSCLK_DIV; wm8996->sysclk /= 2; + /* fall through */ case 11289600: case 12288000: snd_soc_component_update_bits(component, WM8996_AIF_RATE, -- cgit v1.2.3 From a9531ab151117e976544e0dc74a9bc8cbd01145f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 14:54:03 -0500 Subject: ASoC: wm8962: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 115043 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index a11e9d6bf950..efd8910b1ff7 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2649,6 +2649,7 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif0 |= WM8962_LRCLK_INV | 3; + /* fall through */ case SND_SOC_DAIFMT_DSP_A: aif0 |= 3; -- cgit v1.2.3 From af5d1d5d4ba71164711025e077511ad48d5690e9 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 14:54:45 -0500 Subject: ASoC: wm8995: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 115045 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/wm8995.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 60e227832331..68c99fe37097 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -1465,6 +1465,7 @@ static int wm8995_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif |= WM8995_AIF1_LRCLK_INV; + /* fall through */ case SND_SOC_DAIFMT_DSP_A: aif |= (0x3 << WM8995_AIF1_FMT_SHIFT); break; -- cgit v1.2.3 From 7a2235ef507822679ac89007a6a37b23f30eed56 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 14:55:26 -0500 Subject: ASoC: wm9081: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 1357430 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/wm9081.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 5a0ea7b3c149..399255d1f78a 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -933,6 +933,7 @@ static int wm9081_set_dai_fmt(struct snd_soc_dai *dai, switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif2 |= WM9081_AIF_LRCLK_INV; + /* fall through */ case SND_SOC_DAIFMT_DSP_A: aif2 |= 0x3; break; -- cgit v1.2.3 From 2cea1542859bc812f1ec51ea71c06e927e5b922e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 14:56:16 -0500 Subject: ASoC: wm8994: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 115050 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 7fdfdf3f6e67..62f8c5b9ba92 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2432,6 +2432,7 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_2, WM8994_OPCLK_ENA, 0); } + /* fall through */ default: return -EINVAL; -- cgit v1.2.3 From 038541dae968dbef99edca4b22bbb2a7b4afdc83 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 16:49:02 -0500 Subject: ASoC: max9850: use true and false for boolean values Return statements in functions returning bool should use true or false instead of an integer value. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/max9850.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index 74d7f52c7e73..6e6134589588 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -52,9 +52,9 @@ static bool max9850_volatile_register(struct device *dev, unsigned int reg) switch (reg) { case MAX9850_STATUSA: case MAX9850_STATUSB: - return 1; + return true; default: - return 0; + return false; } } -- cgit v1.2.3 From 508e8641f89cc89554adbec3ce59bcd28a4ced4b Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 16:49:55 -0500 Subject: ASoC: rt5631: use true and false for boolean values Return statements in functions returning bool should use true or false instead of an integer value. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/rt5631.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index e52e4670cf65..865f49ac38dd 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -105,9 +105,9 @@ static bool rt5631_volatile_register(struct device *dev, unsigned int reg) case RT5631_INDEX_ADD: case RT5631_INDEX_DATA: case RT5631_EQ_CTRL: - return 1; + return true; default: - return 0; + return false; } } @@ -164,9 +164,9 @@ static bool rt5631_readable_register(struct device *dev, unsigned int reg) case RT5631_VENDOR_ID: case RT5631_VENDOR_ID1: case RT5631_VENDOR_ID2: - return 1; + return true; default: - return 0; + return false; } } -- cgit v1.2.3 From 10754bfc051256ab922b818de3ddd11391862a5f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 16:50:27 -0500 Subject: ASoC: tda7419: use true and false for boolean values Return statements in functions returning bool should use true or false instead of an integer value. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/tda7419.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/tda7419.c b/sound/soc/codecs/tda7419.c index 225c210ac38f..7f3b79c5a563 100644 --- a/sound/soc/codecs/tda7419.c +++ b/sound/soc/codecs/tda7419.c @@ -142,9 +142,9 @@ struct tda7419_vol_control { static inline bool tda7419_vol_is_stereo(struct tda7419_vol_control *tvc) { if (tvc->reg == tvc->rreg) - return 0; + return false; - return 1; + return true; } static int tda7419_vol_info(struct snd_kcontrol *kcontrol, -- cgit v1.2.3 From 064ee5a370150534e12e5bac4ff81f86528e27ca Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 16:51:01 -0500 Subject: ASoC: wm8990: use true and false for boolean values Return statements in functions returning bool should use true or false instead of an integer value. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8990.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 411b9eee88c2..457bc437ce54 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -40,9 +40,9 @@ static bool wm8990_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { case WM8990_RESET: - return 1; + return true; default: - return 0; + return false; } } -- cgit v1.2.3 From c34c4515286f27e7e99d8a0011b4322d1de6c9bc Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 16:52:01 -0500 Subject: ASoC: cs4270: use true and false for boolean values Return statements in functions returning bool should use true or false instead of an integer value. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 2a7a4168c072..3c266eeb89bf 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -219,7 +219,7 @@ static bool cs4270_reg_is_volatile(struct device *dev, unsigned int reg) { /* Unreadable registers are considered volatile */ if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) - return 1; + return true; return reg == CS4270_CHIPID; } -- cgit v1.2.3 From eb086306bc6b42dc2c538ec2350d44a82d1a835b Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 16:52:35 -0500 Subject: ASoC: wm8996: use true and false for boolean values Return statements in functions returning bool should use true or false instead of an integer value. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8996.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 78a408236cfb..91711f8958c5 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -1498,9 +1498,9 @@ static bool wm8996_readable_register(struct device *dev, unsigned int reg) case WM8996_RIGHT_PDM_SPEAKER: case WM8996_PDM_SPEAKER_MUTE_SEQUENCE: case WM8996_PDM_SPEAKER_VOLUME: - return 1; + return true; default: - return 0; + return false; } } @@ -1522,9 +1522,9 @@ static bool wm8996_volatile_register(struct device *dev, unsigned int reg) case WM8996_MIC_DETECT_3: case WM8996_HEADPHONE_DETECT_1: case WM8996_HEADPHONE_DETECT_2: - return 1; + return true; default: - return 0; + return false; } } -- cgit v1.2.3 From 965afd3c1dbaf293bfa9452aaf0a7e53d78d07f3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 16:53:10 -0500 Subject: ASoC: da7219: use true and false for boolean values Return statements in functions returning bool should use true or false instead of an integer value. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/da7219.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 980a6a8bf56d..c0144f2f8174 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -2143,9 +2143,9 @@ static bool da7219_volatile_register(struct device *dev, unsigned int reg) case DA7219_ACCDET_IRQ_EVENT_B: case DA7219_ACCDET_CONFIG_8: case DA7219_SYSTEM_STATUS: - return 1; + return true; default: - return 0; + return false; } } -- cgit v1.2.3 From bc94c8884e5a94914ec950dfc615563a1253e3f3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 16:53:38 -0500 Subject: ASoC: twl6040: use true and false for boolean values Return statements in functions returning bool should use true or false instead of an integer value. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/twl6040.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index bfd1abd72253..94675da514c8 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -148,7 +148,7 @@ static bool twl6040_can_write_to_chip(struct snd_soc_component *component, case TWL6040_REG_HFRCTL: return priv->dl2_unmuted; default: - return 1; + return true; } } -- cgit v1.2.3 From 1752a35acd8e837463fb7b7d9492b18e2a2ed5e3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 16:54:10 -0500 Subject: ASoC: da7213: use true and false for boolean values Return statements in functions returning bool should use true or false instead of an integer value. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/da7213.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 54cb5f24969f..92d006a5283e 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1140,9 +1140,9 @@ static bool da7213_volatile_register(struct device *dev, unsigned int reg) case DA7213_ALC_OFFSET_AUTO_M_R: case DA7213_ALC_OFFSET_AUTO_U_R: case DA7213_ALC_CIC_OP_LVL_DATA: - return 1; + return true; default: - return 0; + return false; } } -- cgit v1.2.3 From 380ae4ec420304aa59adb36776eaf78aef37192c Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 16:54:54 -0500 Subject: ASoC: wm5100-tables: use true and false for boolean values Return statements in functions returning bool should use true or false instead of an integer value. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm5100-tables.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm5100-tables.c b/sound/soc/codecs/wm5100-tables.c index e239f4bf2460..9e987cf07450 100644 --- a/sound/soc/codecs/wm5100-tables.c +++ b/sound/soc/codecs/wm5100-tables.c @@ -30,7 +30,7 @@ bool wm5100_volatile_register(struct device *dev, unsigned int reg) case WM5100_OUTPUT_STATUS_2: case WM5100_INPUT_ENABLES_STATUS: case WM5100_MIC_DETECT_3: - return 1; + return true; default: if ((reg >= WM5100_DSP1_PM_0 && reg <= WM5100_DSP1_PM_1535) || (reg >= WM5100_DSP1_ZM_0 && reg <= WM5100_DSP1_ZM_2047) || @@ -41,9 +41,9 @@ bool wm5100_volatile_register(struct device *dev, unsigned int reg) (reg >= WM5100_DSP3_PM_0 && reg <= WM5100_DSP3_PM_1535) || (reg >= WM5100_DSP3_ZM_0 && reg <= WM5100_DSP3_ZM_2047) || (reg >= WM5100_DSP3_DM_0 && reg <= WM5100_DSP3_DM_511)) - return 1; + return true; else - return 0; + return false; } } @@ -798,7 +798,7 @@ bool wm5100_readable_register(struct device *dev, unsigned int reg) case WM5100_DSP3_CONTROL_28: case WM5100_DSP3_CONTROL_29: case WM5100_DSP3_CONTROL_30: - return 1; + return true; default: if ((reg >= WM5100_DSP1_PM_0 && reg <= WM5100_DSP1_PM_1535) || (reg >= WM5100_DSP1_ZM_0 && reg <= WM5100_DSP1_ZM_2047) || @@ -809,9 +809,9 @@ bool wm5100_readable_register(struct device *dev, unsigned int reg) (reg >= WM5100_DSP3_PM_0 && reg <= WM5100_DSP3_PM_1535) || (reg >= WM5100_DSP3_ZM_0 && reg <= WM5100_DSP3_ZM_2047) || (reg >= WM5100_DSP3_DM_0 && reg <= WM5100_DSP3_DM_511)) - return 1; + return true; else - return 0; + return false; } } -- cgit v1.2.3 From e1ec62b147c2f2deae66e69ee4f7347dc80123ae Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 16:55:28 -0500 Subject: ASoC: da9055: use true and false for boolean values Return statements in functions returning bool should use true or false instead of an integer value. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/codecs/da9055.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index afdf90c78884..f6a7bf9560e7 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -1041,9 +1041,9 @@ static bool da9055_volatile_register(struct device *dev, case DA9055_HP_R_GAIN_STATUS: case DA9055_LINE_GAIN_STATUS: case DA9055_ALC_CIC_OP_LVL_DATA: - return 1; + return true; default: - return 0; + return false; } } -- cgit v1.2.3 From bee7d3c9f89a1bbe3d5f88ac9d6946de4705731b Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 16:56:02 -0500 Subject: ASoC: wm8903: use true and false for boolean values Return statements in functions returning bool should use true or false instead of an integer value. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8903.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 7b8b6ef2f632..6cb3c153ba19 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -251,10 +251,10 @@ static bool wm8903_volatile_register(struct device *dev, unsigned int reg) case WM8903_DC_SERVO_READBACK_2: case WM8903_DC_SERVO_READBACK_3: case WM8903_DC_SERVO_READBACK_4: - return 1; + return true; default: - return 0; + return false; } } -- cgit v1.2.3 From ad0eaee6195db1db1749dd46b9e6f4466793d178 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 6 Aug 2018 07:14:51 -0500 Subject: ASoC: wm8994: Fix missing break in switch Add missing break statement in order to prevent the code from falling through to the default case. Addresses-Coverity-ID: 115050 ("Missing break in switch") Reported-by: Valdis Kletnieks Signed-off-by: Gustavo A. R. Silva Acked-by: Charles Keepax Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm8994.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 62f8c5b9ba92..14f1b0c0d286 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2432,7 +2432,7 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_2, WM8994_OPCLK_ENA, 0); } - /* fall through */ + break; default: return -EINVAL; -- cgit v1.2.3 From f861e3e28a3016a2064d9f600eaa92a530b732b4 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Tue, 7 Aug 2018 10:19:40 -0700 Subject: ASoC: rt5677: Fix initialization of rt5677_of_match.data The driver expects to find the device id in rt5677_of_match.data, however it is currently assigned to rt5677_of_match.type. Fix this. The problem was found with the help of clang: sound/soc/codecs/rt5677.c:5010:36: warning: expression which evaluates to zero treated as a null pointer constant of type 'const void *' [-Wnon-literal-null-conversion] { .compatible = "realtek,rt5677", RT5677 }, ^~~~~~ Fixes: ddc9e69b9dc2 ("ASoC: rt5677: Hide platform data in the module sources") Signed-off-by: Matthias Kaehlcke Reviewed-by: Guenter Roeck Acked-by: Andy Shevchenko Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 922becfee59b..9b7a1833d331 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -5008,7 +5008,7 @@ static const struct regmap_config rt5677_regmap = { }; static const struct of_device_id rt5677_of_match[] = { - { .compatible = "realtek,rt5677", RT5677 }, + { .compatible = "realtek,rt5677", .data = (const void *)RT5677 }, { } }; MODULE_DEVICE_TABLE(of, rt5677_of_match); -- cgit v1.2.3 From b1470d4ce77c2d60661c7d5325d4fb8063e15ff8 Mon Sep 17 00:00:00 2001 From: Ajit Pandey Date: Tue, 7 Aug 2018 18:30:42 +0100 Subject: ASoC: wm_adsp: Correct DSP pointer for preloader control The offset of the DSP core needs to be taken into account for the DSP preloader control get and put. Currently the dsp->preloaded variable will only ever be read/updated on the first DSP, whilst this doesn't affect the operation of the control the readback will be incorrect. Signed-off-by: Ajit Pandey Signed-off-by: Charles Keepax Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm_adsp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 4e7f8525449e..08dc82770273 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -2643,7 +2643,10 @@ int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); - struct wm_adsp *dsp = snd_soc_component_get_drvdata(component); + struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct wm_adsp *dsp = &dsps[mc->shift - 1]; ucontrol->value.integer.value[0] = dsp->preloaded; @@ -2655,10 +2658,11 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); - struct wm_adsp *dsp = snd_soc_component_get_drvdata(component); + struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; + struct wm_adsp *dsp = &dsps[mc->shift - 1]; char preload[32]; snprintf(preload, ARRAY_SIZE(preload), "DSP%u Preload", mc->shift); -- cgit v1.2.3 From 0717edbdfed61b4c1e8291140f78882d3a481042 Mon Sep 17 00:00:00 2001 From: Ryan Lee Date: Tue, 7 Aug 2018 20:06:38 -0700 Subject: ASoC: max98373: Added software reset register to readable registers Signed-off-by: Ryan Lee Signed-off-by: Mark Brown --- sound/soc/codecs/max98373.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index a92586106932..92b7125ea169 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -488,6 +488,7 @@ static const DECLARE_TLV_DB_RANGE(max98373_bde_gain_tlv, static bool max98373_readable_register(struct device *dev, unsigned int reg) { switch (reg) { + case MAX98373_R2000_SW_RESET: case MAX98373_R2001_INT_RAW1 ... MAX98373_R200C_INT_EN3: case MAX98373_R2010_IRQ_CTRL: case MAX98373_R2014_THERM_WARN_THRESH -- cgit v1.2.3 From 0a047f07525fecfa8f6fccc5d30afff7e816de8d Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 8 Aug 2018 17:13:38 +0100 Subject: ASoC: wm_adsp: Declare firmware controls from codec driver To allow for more flexibility in naming of DSP-type cores move the creation of the firmware controls to the codec drivers instead of having a hardcoded list in wm_adsp. Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l24.c | 3 +++ sound/soc/codecs/wm2200.c | 10 ++++------ sound/soc/codecs/wm5102.c | 2 ++ sound/soc/codecs/wm5110.c | 5 +++++ sound/soc/codecs/wm_adsp.c | 35 +++++++++-------------------------- sound/soc/codecs/wm_adsp.h | 10 +++++++++- 6 files changed, 32 insertions(+), 33 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index 0da52ead91e0..45e50fe3bf25 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -235,6 +235,9 @@ ARIZONA_MIXER_CONTROLS("AIF2TX6", ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), + +WM_ADSP_FW_CONTROL("DSP2", 1), +WM_ADSP_FW_CONTROL("DSP3", 2), }; ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 3663b9fd4d65..deff65161504 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1180,6 +1180,9 @@ SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L, SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT, WM2200_SPK1R_MUTE_SHIFT, 1, 1), SOC_ENUM("RxANC Src", wm2200_rxanc_input_sel), + +WM_ADSP_FW_CONTROL("DSP1", 0), +WM_ADSP_FW_CONTROL("DSP2", 1), }; WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE); @@ -1553,15 +1556,10 @@ static const struct snd_soc_dapm_route wm2200_dapm_routes[] = { static int wm2200_probe(struct snd_soc_component *component) { struct wm2200_priv *wm2200 = snd_soc_component_get_drvdata(component); - int ret; wm2200->component = component; - ret = snd_soc_add_component_controls(component, wm_adsp_fw_controls, 2); - if (ret != 0) - return ret; - - return ret; + return 0; } static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index a01a0c0e01eb..7e817e1877c2 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -985,6 +985,8 @@ ARIZONA_MIXER_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("SLIMTX7", ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("SLIMTX8", ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE), + +WM_ADSP_FW_CONTROL("DSP1", 0), }; ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 00c735c585d9..b0789a03d699 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -927,6 +927,11 @@ ARIZONA_MIXER_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("SLIMTX7", ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("SLIMTX8", ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE), + +WM_ADSP_FW_CONTROL("DSP1", 0), +WM_ADSP_FW_CONTROL("DSP2", 1), +WM_ADSP_FW_CONTROL("DSP3", 2), +WM_ADSP_FW_CONTROL("DSP4", 3), }; ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index e39b0e0b04df..fbd0515c49d7 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -684,8 +684,8 @@ static inline void wm_adsp_debugfs_clear(struct wm_adsp *dsp) } #endif -static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; @@ -695,9 +695,10 @@ static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, return 0; } +EXPORT_SYMBOL_GPL(wm_adsp_fw_get); -static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; @@ -721,8 +722,9 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, return ret; } +EXPORT_SYMBOL_GPL(wm_adsp_fw_put); -static const struct soc_enum wm_adsp_fw_enum[] = { +const struct soc_enum wm_adsp_fw_enum[] = { SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), @@ -731,24 +733,7 @@ static const struct soc_enum wm_adsp_fw_enum[] = { SOC_ENUM_SINGLE(0, 5, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), SOC_ENUM_SINGLE(0, 6, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), }; - -const struct snd_kcontrol_new wm_adsp_fw_controls[] = { - SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], - wm_adsp_fw_get, wm_adsp_fw_put), - SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], - wm_adsp_fw_get, wm_adsp_fw_put), - SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], - wm_adsp_fw_get, wm_adsp_fw_put), - SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3], - wm_adsp_fw_get, wm_adsp_fw_put), - SOC_ENUM_EXT("DSP5 Firmware", wm_adsp_fw_enum[4], - wm_adsp_fw_get, wm_adsp_fw_put), - SOC_ENUM_EXT("DSP6 Firmware", wm_adsp_fw_enum[5], - wm_adsp_fw_get, wm_adsp_fw_put), - SOC_ENUM_EXT("DSP7 Firmware", wm_adsp_fw_enum[6], - wm_adsp_fw_get, wm_adsp_fw_put), -}; -EXPORT_SYMBOL_GPL(wm_adsp_fw_controls); +EXPORT_SYMBOL_GPL(wm_adsp_fw_enum); static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, int type) @@ -2884,9 +2869,7 @@ int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *comp dsp->component = component; - return snd_soc_add_component_controls(component, - &wm_adsp_fw_controls[dsp->num - 1], - 1); + return 0; } EXPORT_SYMBOL_GPL(wm_adsp2_component_probe); diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index bc6d359f0533..8d58cb9d9bb9 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -121,7 +121,11 @@ struct wm_adsp { .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } -extern const struct snd_kcontrol_new wm_adsp_fw_controls[]; +#define WM_ADSP_FW_CONTROL(dspname, num) \ + SOC_ENUM_EXT(dspname " Firmware", wm_adsp_fw_enum[num], \ + wm_adsp_fw_get, wm_adsp_fw_put) + +extern const struct soc_enum wm_adsp_fw_enum[]; int wm_adsp1_init(struct wm_adsp *dsp); int wm_adsp2_init(struct wm_adsp *dsp); @@ -144,6 +148,10 @@ int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream); int wm_adsp_compr_free(struct snd_compr_stream *stream); -- cgit v1.2.3 From 605391d0f4bfdff2f2c6c5477ce0ccf776d8d5c0 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 8 Aug 2018 17:13:39 +0100 Subject: ASoC: wm_adsp: Make DSP name configurable by codec driver Instead of harcoding that a core must always be called "DSPn" add a name member to struct wm_adsp so that the owning codec driver can provide a custom name. This allows for re-use of the wm_adsp driver with parts where the processing cores are named differently. If no name is provided the default DSPn name is used. Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 69 ++++++++++++++++++++++++++++++++-------------- sound/soc/codecs/wm_adsp.h | 2 ++ 2 files changed, 50 insertions(+), 21 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 1c12c78dbcce..f61656070225 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -10,6 +10,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include @@ -35,15 +36,15 @@ #include "wm_adsp.h" #define adsp_crit(_dsp, fmt, ...) \ - dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) + dev_crit(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) #define adsp_err(_dsp, fmt, ...) \ - dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) + dev_err(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) #define adsp_warn(_dsp, fmt, ...) \ - dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) + dev_warn(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) #define adsp_info(_dsp, fmt, ...) \ - dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) + dev_info(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) #define adsp_dbg(_dsp, fmt, ...) \ - dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) + dev_dbg(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) #define ADSP1_CONTROL_1 0x00 #define ADSP1_CONTROL_2 0x02 @@ -608,7 +609,6 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp, struct snd_soc_component *component) { struct dentry *root = NULL; - char *root_name; int i; if (!component->debugfs_root) { @@ -616,13 +616,7 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp, goto err; } - root_name = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!root_name) - goto err; - - snprintf(root_name, PAGE_SIZE, "dsp%d", dsp->num); - root = debugfs_create_dir(root_name, component->debugfs_root); - kfree(root_name); + root = debugfs_create_dir(dsp->name, component->debugfs_root); if (!root) goto err; @@ -1315,12 +1309,12 @@ static int wm_adsp_create_control(struct wm_adsp *dsp, switch (dsp->fw_ver) { case 0: case 1: - snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "DSP%d %s %x", - dsp->num, region_name, alg_region->alg); + snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %x", + dsp->name, region_name, alg_region->alg); break; default: ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, - "DSP%d%c %.12s %x", dsp->num, *region_name, + "%s%c %.12s %x", dsp->name, *region_name, wm_adsp_fw_text[dsp->fw], alg_region->alg); /* Truncate the subname from the start if it is too long */ @@ -1648,7 +1642,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) if (file == NULL) return -ENOMEM; - snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.wmfw", dsp->part, dsp->num, + snprintf(file, PAGE_SIZE, "%s-%s-%s.wmfw", dsp->part, dsp->fwf_name, wm_adsp_fw[dsp->fw].file); file[PAGE_SIZE - 1] = '\0'; @@ -2226,7 +2220,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) if (file == NULL) return -ENOMEM; - snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.bin", dsp->part, dsp->num, + snprintf(file, PAGE_SIZE, "%s-%s-%s.bin", dsp->part, dsp->fwf_name, wm_adsp_fw[dsp->fw].file); file[PAGE_SIZE - 1] = '\0'; @@ -2398,8 +2392,38 @@ out: return ret; } +static int wm_adsp_create_name(struct wm_adsp *dsp) +{ + char *p; + + if (!dsp->name) { + dsp->name = devm_kasprintf(dsp->dev, GFP_KERNEL, "DSP%d", + dsp->num); + if (!dsp->name) + return -ENOMEM; + } + + if (!dsp->fwf_name) { + p = devm_kstrdup(dsp->dev, dsp->name, GFP_KERNEL); + if (!p) + return -ENOMEM; + + dsp->fwf_name = p; + for (; *p != 0; ++p) + *p = tolower(*p); + } + + return 0; +} + int wm_adsp1_init(struct wm_adsp *dsp) { + int ret; + + ret = wm_adsp_create_name(dsp); + if (ret) + return ret; + INIT_LIST_HEAD(&dsp->alg_regions); mutex_init(&dsp->pwr_lock); @@ -2672,7 +2696,7 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, struct wm_adsp *dsp = &dsps[mc->shift - 1]; char preload[32]; - snprintf(preload, ARRAY_SIZE(preload), "DSP%u Preload", mc->shift); + snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name); dsp->preloaded = ucontrol->value.integer.value[0]; @@ -2867,8 +2891,7 @@ int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *comp { char preload[32]; - snprintf(preload, ARRAY_SIZE(preload), "DSP%d Preload", dsp->num); - + snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name); snd_soc_component_disable_pin(component, preload); wm_adsp2_init_debugfs(dsp, component); @@ -2891,6 +2914,10 @@ int wm_adsp2_init(struct wm_adsp *dsp) { int ret; + ret = wm_adsp_create_name(dsp); + if (ret) + return ret; + switch (dsp->rev) { case 0: /* diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 8d58cb9d9bb9..4b8778b0b06c 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -57,6 +57,8 @@ struct wm_adsp_compr_buf; struct wm_adsp { const char *part; + const char *name; + const char *fwf_name; int rev; int num; int type; -- cgit v1.2.3 From 17c81d2f5a59929c73a2a19fd49fe0b068fda76f Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Thu, 9 Aug 2018 10:48:50 +0100 Subject: ASoC: da7219: Add delays to capture path to remove DC offset noise On some platforms it has been noted that a pop noise can be witnessed when capturing audio, mainly for first time after a headset jack has been inserted. This is due to a DC offset in the Mic PGA and so to avoid this delays are required when powering up the capture path. This commit rectifies the problem by adding delays post Mic PGA and post Mixin PGA. The post Mic PGA delay is determined based on Mic Bias voltage, and is only applied the first time after a headset jack is inserted. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown --- sound/soc/codecs/da7219-aad.c | 5 +++++ sound/soc/codecs/da7219.c | 44 +++++++++++++++++++++++++++++++++++++------ sound/soc/codecs/da7219.h | 8 ++++++-- 3 files changed, 49 insertions(+), 8 deletions(-) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index a49ab751a036..2c7d5088e6f2 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -59,6 +59,7 @@ static void da7219_aad_btn_det_work(struct work_struct *work) container_of(work, struct da7219_aad_priv, btn_det_work); struct snd_soc_component *component = da7219_aad->component; struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); u8 statusa, micbias_ctrl; bool micbias_up = false; int retries = 0; @@ -86,6 +87,8 @@ static void da7219_aad_btn_det_work(struct work_struct *work) if (retries >= DA7219_AAD_MICBIAS_CHK_RETRIES) dev_warn(component->dev, "Mic bias status check timed out"); + da7219->micbias_on_event = true; + /* * Mic bias pulse required to enable mic, must be done before enabling * button detection to prevent erroneous button readings. @@ -439,6 +442,8 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1, DA7219_BUTTON_CONFIG_MASK, 0); + da7219->micbias_on_event = false; + /* Disable mic bias */ snd_soc_dapm_disable_pin(dapm, "Mic Bias"); snd_soc_dapm_sync(dapm); diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index c0144f2f8174..e46e9f4bc994 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -768,6 +768,30 @@ static const struct snd_kcontrol_new da7219_st_out_filtr_mix_controls[] = { * DAPM Events */ +static int da7219_mic_pga_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + if (da7219->micbias_on_event) { + /* + * Delay only for first capture after bias enabled to + * avoid possible DC offset related noise. + */ + da7219->micbias_on_event = false; + msleep(da7219->mic_pga_delay); + } + break; + default: + break; + } + + return 0; +} + static int da7219_dai_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -937,12 +961,12 @@ static const struct snd_soc_dapm_widget da7219_dapm_widgets[] = { SND_SOC_DAPM_INPUT("MIC"), /* Input PGAs */ - SND_SOC_DAPM_PGA("Mic PGA", DA7219_MIC_1_CTRL, - DA7219_MIC_1_AMP_EN_SHIFT, DA7219_NO_INVERT, - NULL, 0), - SND_SOC_DAPM_PGA("Mixin PGA", DA7219_MIXIN_L_CTRL, - DA7219_MIXIN_L_AMP_EN_SHIFT, DA7219_NO_INVERT, - NULL, 0), + SND_SOC_DAPM_PGA_E("Mic PGA", DA7219_MIC_1_CTRL, + DA7219_MIC_1_AMP_EN_SHIFT, DA7219_NO_INVERT, + NULL, 0, da7219_mic_pga_event, SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_PGA_E("Mixin PGA", DA7219_MIXIN_L_CTRL, + DA7219_MIXIN_L_AMP_EN_SHIFT, DA7219_NO_INVERT, + NULL, 0, da7219_settling_event, SND_SOC_DAPM_POST_PMU), /* Input Filters */ SND_SOC_DAPM_ADC("ADC", NULL, DA7219_ADC_L_CTRL, DA7219_ADC_L_EN_SHIFT, @@ -1847,6 +1871,14 @@ static void da7219_handle_pdata(struct snd_soc_component *component) snd_soc_component_write(component, DA7219_MICBIAS_CTRL, micbias_lvl); + /* + * Calculate delay required to compensate for DC offset in + * Mic PGA, based on Mic Bias voltage. + */ + da7219->mic_pga_delay = DA7219_MIC_PGA_BASE_DELAY + + (pdata->micbias_lvl * + DA7219_MIC_PGA_OFFSET_DELAY); + /* Mic */ switch (pdata->mic_amp_in_sel) { case DA7219_MIC_AMP_IN_SEL_DIFF: diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h index 1b00023e33cd..3a006862f0e7 100644 --- a/sound/soc/codecs/da7219.h +++ b/sound/soc/codecs/da7219.h @@ -781,8 +781,10 @@ #define DA7219_SYS_STAT_CHECK_DELAY 50 /* Power up/down Delays */ -#define DA7219_SETTLING_DELAY 40 -#define DA7219_MIN_GAIN_DELAY 30 +#define DA7219_SETTLING_DELAY 40 +#define DA7219_MIN_GAIN_DELAY 30 +#define DA7219_MIC_PGA_BASE_DELAY 100 +#define DA7219_MIC_PGA_OFFSET_DELAY 40 enum da7219_clk_src { DA7219_CLKSRC_MCLK = 0, @@ -828,6 +830,8 @@ struct da7219_priv { bool master; bool alc_en; + bool micbias_on_event; + unsigned int mic_pga_delay; u8 gain_ramp_ctrl; }; -- cgit v1.2.3 From f2cf0ef7c0ce141bb38f315c34c56e6ef5667a27 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 8 Aug 2018 14:19:33 -0500 Subject: ASoC: adav80x: mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 1056531 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/adav80x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index db21ecbe0762..8b9ca7e7a682 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -648,6 +648,7 @@ static int adav80x_set_pll(struct snd_soc_component *component, int pll_id, pll_ctrl1 |= ADAV80X_PLL_CTRL1_PLLDIV; break; } + /* fall through */ default: return -EINVAL; } -- cgit v1.2.3