[alsa-devel] [RFC v1 0/9] ASoC: Add support to Qualcomm msm8x16-wcd codec
This patchset aims at adding msm8x16-wcd codec support. msm8x16-wcd codec is found in Qualcomm msm8916 and apq8016 processors. This codec IP is split in to two parts(Digital & Analog), Analog part is integrated in to PMIC PM8916 and the digital part is integrated into Application processor. Register access to the analog part is done via SPMI interface to PMIC, and registers on the Application processor are memory mapped. Data transfer between Analog and Digital Die is done via a internal bus called PDM.
I did split the driver into sensible patches to easy the review process. Most of this driver is ported from downstream Andriod v3.10 kernel. Jack support and Headset button detection code is not added in to this series.
This codec support: - 3 Microphones: Primary Mic(Handset mic), Headset Mic and Secondary Mic. - 2 Digital Microphones. - 2 Mic Bias Circuits. - Earpiece - Headset - Loud Speaker. - Jack Detect. - Headset Button detection circuit.
Tested this code on v4.5-rc4 with lpass driver capture support patches for Headset (Mic and speakers), Secondary Mic and Loudspeaker on DB410C. DMIC should work too.
Thanks, srini
Srinivas Kandagatla (9): ASoC: msm8x176: Add Device Tree bindings. ASoC: msm8x16: add driver structure ASoC: msm8x16: add codec registers definitions ASoC: msm8x16: add ranges for default, readonly ASoC: msm8x16: add codec intialization setup ASoC: msm8x16: add codec dais ASoC: msm8x16: Add sound mixer controls. ASoC: msm8x16: add dapm widgets ASoC: msm8x16: add dapm routes
.../devicetree/bindings/sound/qcom,msm8x16-wcd.txt | 91 + include/dt-bindings/sound/msm8x16-wcd.h | 7 + sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 3 +- sound/soc/codecs/msm8x16-wcd-registers.h | 518 +++++ sound/soc/codecs/msm8x16-wcd.c | 2132 ++++++++++++++++++++ sound/soc/codecs/msm8x16-wcd.h | 764 +++++++ 7 files changed, 3518 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/sound/qcom,msm8x16-wcd.txt create mode 100644 include/dt-bindings/sound/msm8x16-wcd.h create mode 100644 sound/soc/codecs/msm8x16-wcd-registers.h create mode 100644 sound/soc/codecs/msm8x16-wcd.c create mode 100644 sound/soc/codecs/msm8x16-wcd.h
This patch adds DT bindings required for msm8x16 codec which is integrated in msm8916 and apq8016 SOCs.
Codec IP is divided into two parts, first analog which is integrated in pmic pm8916 and secondly digital part which is integrated into application processor. Codec register controls are also split across pmic an lpass. Analog part is controlled via spmi bus to pmic, registers on the Application processor are memory mapped.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- .../devicetree/bindings/sound/qcom,msm8x16-wcd.txt | 91 ++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,msm8x16-wcd.txt
diff --git a/Documentation/devicetree/bindings/sound/qcom,msm8x16-wcd.txt b/Documentation/devicetree/bindings/sound/qcom,msm8x16-wcd.txt new file mode 100644 index 0000000..42d3f66 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,msm8x16-wcd.txt @@ -0,0 +1,91 @@ +msm8x16 audio CODEC aka Tombak audio CODEC + +Codec IP is divided into two parts, first analog which is integrated in pmic pm8916 +and secondly digital part which is integrated into application processor. Codec register +controls are also split across pmic an lpass. Analog part is controlled via spmi bus to pmic. + +## Bindings for codec core on pmic: + +Required properties + - compatible = "qcom,msm8x16-wcd-codec"; + - reg: represents the slave base address provided to the peripheral. + - interrupt-parent : The parent interrupt controller. + - interrupts: List of interrupts in given SPMI peripheral. + - interrupt-names: Names specified to above list of interrupts in same + order + - vddio-supply: phandle to VDD_CDC_IO regulator device tree node. + - vdd-tx-rx-supply: phandle to VDD_CDC_TX/RX/CX regulator device tree node. + - vdda-cp-supply: phandle of VDD_CP charge pump supply's regulator device tree node. + - vdda-hph-supply: phandle of VDD_HPH supply's regulator device tree node. + - vdd-micbias-supply: phandle of VDD_MICBIAS supply's regulator device tree + node. +- qcom,lpass-codec-core: phandle to syscon node of lpass code core. + +Optional Properties: +- qcom,micbias1-ext-cap: present if micbias1 has external capacitor connected. +- qcom,micbias2-ext-cap: present if micbias2 has external capacitor connected. + +## Bindings codec core on lpass: + +Required properties + - compatible: should be "syscon" follwed by "qcom,msm8x16-lpass-codec" + - reg: represents the lpass codec core register map. + +Example: + +spmi_bus { + ... + msm8x16_wcd_codec@f000{ + compatible = "qcom,msm8x16-wcd-codec"; + reg = <0xf000 0x200>; + reg-names = "pmic-codec-core"; + clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>; + clock-names = "mclk"; + interrupt-parent = <&spmi_bus>; + interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>, + <0x1 0xf0 0x1 IRQ_TYPE_NONE>, + <0x1 0xf0 0x2 IRQ_TYPE_NONE>, + <0x1 0xf0 0x3 IRQ_TYPE_NONE>, + <0x1 0xf0 0x4 IRQ_TYPE_NONE>, + <0x1 0xf0 0x5 IRQ_TYPE_NONE>, + <0x1 0xf0 0x6 IRQ_TYPE_NONE>, + <0x1 0xf0 0x7 IRQ_TYPE_NONE>, + <0x1 0xf1 0x0 IRQ_TYPE_NONE>, + <0x1 0xf1 0x1 IRQ_TYPE_NONE>, + <0x1 0xf1 0x2 IRQ_TYPE_NONE>, + <0x1 0xf1 0x3 IRQ_TYPE_NONE>, + <0x1 0xf1 0x4 IRQ_TYPE_NONE>, + <0x1 0xf1 0x5 IRQ_TYPE_NONE>; + interrupt-names = "spk_cnp_int", + "spk_clip_int", + "spk_ocp_int", + "ins_rem_det1", + "but_rel_det", + "but_press_det", + "ins_rem_det", + "mbhc_int", + "ear_ocp_int", + "hphr_ocp_int", + "hphl_ocp_det", + "ear_cnp_int", + "hphr_cnp_int", + "hphl_cnp_int"; + + vddio-supply = <&pm8916_l5>; + vdd-cp-supply = <&pm8916_s4>; + vdd-hph-supply = <&pm8916_s4>; + vdd-tx-rx-supply = <&pm8916_l5> + vdd-micbias-supply = <&pm8916_l13>; + qcom,lpass-codec-core = <&lpass_codec>; + #sound-dai-cells = <1>; + }; +}; + +soc { + ... + lpass_codec_core: lpass-codec{ + compatible = "syscon", "qcom,msm8x16-lpass-codec"; + reg = <0x0771c000 0x400>; + }; + +};
On Tue, Feb 16, 2016 at 05:32:30PM +0000, Srinivas Kandagatla wrote:
This patch adds DT bindings required for msm8x16 codec which is integrated in msm8916 and apq8016 SOCs.
Codec IP is divided into two parts, first analog which is integrated in pmic pm8916 and secondly digital part which is integrated into application processor. Codec register controls are also split across pmic an lpass. Analog part is controlled via spmi bus to pmic, registers on the Application processor are memory mapped.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org
.../devicetree/bindings/sound/qcom,msm8x16-wcd.txt | 91 ++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,msm8x16-wcd.txt
diff --git a/Documentation/devicetree/bindings/sound/qcom,msm8x16-wcd.txt b/Documentation/devicetree/bindings/sound/qcom,msm8x16-wcd.txt new file mode 100644 index 0000000..42d3f66 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,msm8x16-wcd.txt @@ -0,0 +1,91 @@ +msm8x16 audio CODEC aka Tombak audio CODEC
+Codec IP is divided into two parts, first analog which is integrated in pmic pm8916 +and secondly digital part which is integrated into application processor. Codec register +controls are also split across pmic an lpass. Analog part is controlled via spmi bus to pmic.
+## Bindings for codec core on pmic:
+Required properties
- compatible = "qcom,msm8x16-wcd-codec";
Wildcard bindings are frowned upon generally.
Have separate comaptible strings, perhaps with one as a fallback for the other.
- reg: represents the slave base address provided to the peripheral.
- interrupt-parent : The parent interrupt controller.
- interrupts: List of interrupts in given SPMI peripheral.
- interrupt-names: Names specified to above list of interrupts in same
order
You must explicitly describe the set of interrupt-names for the binding.
- vddio-supply: phandle to VDD_CDC_IO regulator device tree node.
- vdd-tx-rx-supply: phandle to VDD_CDC_TX/RX/CX regulator device tree node.
- vdda-cp-supply: phandle of VDD_CP charge pump supply's regulator device tree node.
- vdda-hph-supply: phandle of VDD_HPH supply's regulator device tree node.
- vdd-micbias-supply: phandle of VDD_MICBIAS supply's regulator device tree
node.
+- qcom,lpass-codec-core: phandle to syscon node of lpass code core.
+Optional Properties: +- qcom,micbias1-ext-cap: present if micbias1 has external capacitor connected. +- qcom,micbias2-ext-cap: present if micbias2 has external capacitor connected.
+## Bindings codec core on lpass:
+Required properties
- compatible: should be "syscon" follwed by "qcom,msm8x16-lpass-codec"
This should be the other way around. "syscon" should be the fallback as it is the least specific. Likewise for the example.
Again, wildcard bindings are generally frowned upon.
Mark.
Thanks for the review,
On 16/02/16 18:58, Mark Rutland wrote:
On Tue, Feb 16, 2016 at 05:32:30PM +0000, Srinivas Kandagatla wrote:
This patch adds DT bindings required for msm8x16 codec which is integrated in msm8916 and apq8016 SOCs.
Codec IP is divided into two parts, first analog which is integrated in pmic pm8916 and secondly digital part which is integrated into application processor. Codec register controls are also split across pmic an lpass. Analog part is controlled via spmi bus to pmic, registers on the Application processor are memory mapped.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org
.../devicetree/bindings/sound/qcom,msm8x16-wcd.txt | 91 ++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,msm8x16-wcd.txt
diff --git a/Documentation/devicetree/bindings/sound/qcom,msm8x16-wcd.txt b/Documentation/devicetree/bindings/sound/qcom,msm8x16-wcd.txt new file mode 100644 index 0000000..42d3f66 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,msm8x16-wcd.txt @@ -0,0 +1,91 @@ +msm8x16 audio CODEC aka Tombak audio CODEC
+Codec IP is divided into two parts, first analog which is integrated in pmic pm8916 +and secondly digital part which is integrated into application processor. Codec register +controls are also split across pmic an lpass. Analog part is controlled via spmi bus to pmic.
+## Bindings for codec core on pmic:
+Required properties
- compatible = "qcom,msm8x16-wcd-codec";
Wildcard bindings are frowned upon generally.
Have separate comaptible strings, perhaps with one as a fallback for the other.
Ok, Will add soc specific compatible strings without wildcards in next version.
- reg: represents the slave base address provided to the peripheral.
- interrupt-parent : The parent interrupt controller.
- interrupts: List of interrupts in given SPMI peripheral.
- interrupt-names: Names specified to above list of interrupts in same
order
You must explicitly describe the set of interrupt-names for the binding.
I will do that.
- vddio-supply: phandle to VDD_CDC_IO regulator device tree node.
- vdd-tx-rx-supply: phandle to VDD_CDC_TX/RX/CX regulator device tree node.
- vdda-cp-supply: phandle of VDD_CP charge pump supply's regulator device tree node.
- vdda-hph-supply: phandle of VDD_HPH supply's regulator device tree node.
- vdd-micbias-supply: phandle of VDD_MICBIAS supply's regulator device tree
node.
+- qcom,lpass-codec-core: phandle to syscon node of lpass code core.
+Optional Properties: +- qcom,micbias1-ext-cap: present if micbias1 has external capacitor connected. +- qcom,micbias2-ext-cap: present if micbias2 has external capacitor connected.
+## Bindings codec core on lpass:
+Required properties
- compatible: should be "syscon" follwed by "qcom,msm8x16-lpass-codec"
This should be the other way around. "syscon" should be the fallback as it is the least specific. Likewise for the example.
Yep, will change the order and remove the wildcard in the compatible string.
Again, wildcard bindings are generally frowned upon.
Mark.
This patch adds device driver structure for msm8x16 codec.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/codecs/Kconfig | 4 ++ sound/soc/codecs/Makefile | 3 +- sound/soc/codecs/msm8x16-wcd.c | 152 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 sound/soc/codecs/msm8x16-wcd.c
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 62b62fe..2611d3f 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -528,6 +528,10 @@ config SND_SOC_MAX98925 config SND_SOC_MAX9850 tristate
+config SND_SOC_MSM8x16_WCD + tristate "Qualcomm MSM8x16 WCD" + depends on SPMI && MFD_SYSCON + config SND_SOC_PCM1681 tristate "Texas Instruments PCM1681 CODEC" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 5f7b002..40ffae7 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -78,6 +78,7 @@ snd-soc-max98925-objs := max98925.o snd-soc-max9850-objs := max9850.o snd-soc-mc13783-objs := mc13783.o snd-soc-ml26124-objs := ml26124.o +snd-soc-msm8x16-objs := msm8x16-wcd.o snd-soc-nau8825-objs := nau8825.o snd-soc-hdmi-codec-objs := hdmi-codec.o snd-soc-pcm1681-objs := pcm1681.o @@ -195,7 +196,6 @@ snd-soc-wm9705-objs := wm9705.o snd-soc-wm9712-objs := wm9712.o snd-soc-wm9713-objs := wm9713.o snd-soc-wm-hubs-objs := wm_hubs.o - # Amp snd-soc-max9877-objs := max9877.o snd-soc-tpa6130a2-objs := tpa6130a2.o @@ -283,6 +283,7 @@ obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o +obj-$(CONFIG_SND_SOC_MSM8x16_WCD) +=snd-soc-msm8x16.o obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c new file mode 100644 index 0000000..99217ab --- /dev/null +++ b/sound/soc/codecs/msm8x16-wcd.c @@ -0,0 +1,152 @@ + +#include <linux/module.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/regulator/consumer.h> +#include <linux/types.h> +#include <linux/clk.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> +#include <sound/soc.h> + +struct msm8x16_wcd_chip { + struct regmap *analog_map; + struct regmap *digital_map; + unsigned int analog_base; + u16 pmic_rev; + u16 codec_version; + + struct clk *mclk; + struct regulator *vddio; + struct regulator *vdd_cp; + struct regulator *vdd_hph; + struct regulator *vdd_tx_rx; + struct regulator *vdd_micbias; + + u32 mute_mask; + u32 rx_bias_count; + bool spk_boost_set; + bool ear_pa_boost_set; + bool micbias1_cap_mode; + bool micbias2_cap_mode; +}; + + +static int msm8x16_wcd_codec_parse_dt(struct platform_device *pdev, + struct msm8x16_wcd_chip *chip) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int ret; + struct regulator_bulk_data regs[5]; + const char *ext1_cap = "qcom,micbias1-ext-cap"; + const char *ext2_cap = "qcom,micbias2-ext-cap"; + + u32 res[2]; + + ret = of_property_read_u32_array(np, "reg", res, 2); + if (ret < 0) + return ret; + + + chip->micbias1_cap_mode = + (of_property_read_bool(pdev->dev.of_node, ext1_cap) ? + MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP); + + chip->micbias2_cap_mode = + (of_property_read_bool(pdev->dev.of_node, ext2_cap) ? + MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP); + + chip->analog_base = res[0]; + + chip->digital_map = syscon_regmap_lookup_by_phandle(np, + "qcom,lpass-codec-core"); + if (IS_ERR(chip->digital_map)) + return PTR_ERR(chip->digital_map); + + chip->mclk = devm_clk_get(dev, "mclk"); + if (IS_ERR(chip->mclk)) { + dev_err(dev, "failed to get mclk\n"); + return PTR_ERR(chip->mclk); + } + + regs[0].supply = "vddio"; + regs[1].supply = "vdd-cp"; + regs[2].supply = "vdd-hph"; + regs[3].supply = "vdd-tx-rx"; + regs[4].supply = "vdd-micbias"; + + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(regs), regs); + if (ret) { + dev_err(dev, "Failed to get regulator supplies %d\n", ret); + return ret; + } + chip->vddio = regs[0].consumer; + chip->vdd_cp = regs[1].consumer; + chip->vdd_hph = regs[2].consumer; + chip->vdd_tx_rx = regs[3].consumer; + chip->vdd_micbias = regs[4].consumer; + + return 0; +} + +static struct snd_soc_dai_driver msm8x16_wcd_codec_dai[] = { +}; + +static struct snd_soc_codec_driver msm8x16_wcd_codec = { +}; + +static int msm8x16_wcd_probe(struct platform_device *pdev) +{ + struct msm8x16_wcd_chip *chip; + struct device *dev = &pdev->dev; + int ret; + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->analog_map = dev_get_regmap(dev->parent, NULL); + if (!chip->analog_map) + return -ENXIO; + + ret = msm8x16_wcd_codec_parse_dt(pdev, chip); + if (IS_ERR_VALUE(ret)) + return ret; + + clk_prepare_enable(chip->mclk); + + dev_set_drvdata(dev, chip); + + return snd_soc_register_codec(dev, &msm8x16_wcd_codec, + msm8x16_wcd_codec_dai, + ARRAY_SIZE(msm8x16_wcd_codec_dai)); +} + +static int msm8x16_wcd_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static const struct of_device_id msm8x16_wcd_match_table[] = { + { .compatible = "qcom,msm8x16-wcd-codec" }, + { } +}; +MODULE_DEVICE_TABLE(of, msm8x16_wcd_match_table); + +static struct platform_driver msm8x16_wcd_driver = { + .driver = { + .name = "msm8x16-wcd-codec", + .of_match_table = msm8x16_wcd_match_table, + }, + .probe = msm8x16_wcd_probe, + .remove = msm8x16_wcd_remove, +}; +module_platform_driver(msm8x16_wcd_driver); + +MODULE_ALIAS("platform:spmi-wcd-codec"); +MODULE_DESCRIPTION("SPMI PMIC WCD codec driver"); +MODULE_LICENSE("GPL v2");
On Tue, Feb 16, 2016 at 05:32:41PM +0000, Srinivas Kandagatla wrote:
@@ -195,7 +196,6 @@ snd-soc-wm9705-objs := wm9705.o snd-soc-wm9712-objs := wm9712.o snd-soc-wm9713-objs := wm9713.o snd-soc-wm-hubs-objs := wm_hubs.o
# Amp snd-soc-max9877-objs := max9877.o snd-soc-tpa6130a2-objs := tpa6130a2.o
Random whitespace change here.
- chip->micbias1_cap_mode =
(of_property_read_bool(pdev->dev.of_node, ext1_cap) ?
MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
Please don't abuse the ternery operator, write code as though people were going to read it.
- regs[0].supply = "vddio";
- regs[1].supply = "vdd-cp";
- regs[2].supply = "vdd-hph";
- regs[3].supply = "vdd-tx-rx";
- regs[4].supply = "vdd-micbias";
- ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(regs), regs);
- if (ret) {
dev_err(dev, "Failed to get regulator supplies %d\n", ret);
return ret;
- }
- chip->vddio = regs[0].consumer;
- chip->vdd_cp = regs[1].consumer;
- chip->vdd_hph = regs[2].consumer;
- chip->vdd_tx_rx = regs[3].consumer;
- chip->vdd_micbias = regs[4].consumer;
Are you *sure* you should be using regulator_bulk_get() here if you never use the regulators en masse again?
+static struct snd_soc_dai_driver msm8x16_wcd_codec_dai[] = { +};
+static struct snd_soc_codec_driver msm8x16_wcd_codec = { +};
Both empty? It seems this CODEC does nothing so may as well not have a driver...
- clk_prepare_enable(chip->mclk);
Error checking.
This patch adds codec register definitions which are found in both PMIC and application processor memory map.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/codecs/msm8x16-wcd-registers.h | 518 +++++++++++++++++++++++++++++++ 1 file changed, 518 insertions(+) create mode 100644 sound/soc/codecs/msm8x16-wcd-registers.h
diff --git a/sound/soc/codecs/msm8x16-wcd-registers.h b/sound/soc/codecs/msm8x16-wcd-registers.h new file mode 100644 index 0000000..feda84c --- /dev/null +++ b/sound/soc/codecs/msm8x16-wcd-registers.h @@ -0,0 +1,518 @@ + /* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef MSM8X16_WCD_REGISTERS_H +#define MSM8X16_WCD_REGISTERS_H + +#define MSM8X16_WCD_A_DIGITAL_REVISION1 (0x000) +#define MSM8X16_WCD_A_DIGITAL_REVISION1__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_REVISION2 (0x001) +#define MSM8X16_WCD_A_DIGITAL_REVISION2__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_PERPH_TYPE (0x004) +#define MSM8X16_WCD_A_DIGITAL_PERPH_TYPE__POR (0x23) +#define MSM8X16_WCD_A_DIGITAL_PERPH_SUBTYPE (0x005) +#define MSM8X16_WCD_A_DIGITAL_PERPH_SUBTYPE__POR (0x01) +#define MSM8X16_WCD_A_DIGITAL_INT_RT_STS (0x010) +#define MSM8X16_WCD_A_DIGITAL_INT_RT_STS__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_INT_SET_TYPE (0x011) +#define MSM8X16_WCD_A_DIGITAL_INT_SET_TYPE__POR (0xFF) +#define MSM8X16_WCD_A_DIGITAL_INT_POLARITY_HIGH (0x012) +#define MSM8X16_WCD_A_DIGITAL_INT_POLARITY_HIGH__POR (0xFF) +#define MSM8X16_WCD_A_DIGITAL_INT_POLARITY_LOW (0x013) +#define MSM8X16_WCD_A_DIGITAL_INT_POLARITY_LOW__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_INT_LATCHED_CLR (0x014) +#define MSM8X16_WCD_A_DIGITAL_INT_LATCHED_CLR__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_INT_EN_SET (0x015) +#define MSM8X16_WCD_A_DIGITAL_INT_EN_SET__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_INT_EN_CLR (0x016) +#define MSM8X16_WCD_A_DIGITAL_INT_EN_CLR__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_INT_LATCHED_STS (0x018) +#define MSM8X16_WCD_A_DIGITAL_INT_LATCHED_STS__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_INT_PENDING_STS (0x019) +#define MSM8X16_WCD_A_DIGITAL_INT_PENDING_STS__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_INT_MID_SEL (0x01A) +#define MSM8X16_WCD_A_DIGITAL_INT_MID_SEL__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_INT_PRIORITY (0x01B) +#define MSM8X16_WCD_A_DIGITAL_INT_PRIORITY__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_GPIO_MODE (0x040) +#define MSM8X16_WCD_A_DIGITAL_GPIO_MODE__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_PIN_CTL_OE (0x041) +#define MSM8X16_WCD_A_DIGITAL_PIN_CTL_OE__POR (0x01) +#define MSM8X16_WCD_A_DIGITAL_PIN_CTL_DATA (0x042) +#define MSM8X16_WCD_A_DIGITAL_PIN_CTL_DATA__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_PIN_STATUS (0x043) +#define MSM8X16_WCD_A_DIGITAL_PIN_STATUS__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_HDRIVE_CTL (0x044) +#define MSM8X16_WCD_A_DIGITAL_HDRIVE_CTL__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_CDC_RST_CTL (0x046) +#define MSM8X16_WCD_A_DIGITAL_CDC_RST_CTL__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_CDC_TOP_CLK_CTL (0x048) +#define MSM8X16_WCD_A_DIGITAL_CDC_TOP_CLK_CTL__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_CDC_ANA_CLK_CTL (0x049) +#define MSM8X16_WCD_A_DIGITAL_CDC_ANA_CLK_CTL__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL (0x04A) +#define MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX1_CTL (0x050) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX1_CTL__POR (0x02) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX2_CTL (0x051) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX2_CTL__POR (0x02) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_HPHR_DAC_CTL (0x052) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_HPHR_DAC_CTL__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX1_CTL (0x053) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX1_CTL__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX2_CTL (0x054) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX2_CTL__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX3_CTL (0x055) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX3_CTL__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX_LB_CTL (0x056) +#define MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX_LB_CTL__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL1 (0x058) +#define MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL1__POR (0x7C) +#define MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL2 (0x059) +#define MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL2__POR (0x7C) +#define MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL3 (0x05A) +#define MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL3__POR (0x7C) +#define MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA0 (0x05B) +#define MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA0__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA1 (0x05C) +#define MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA1__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA2 (0x05D) +#define MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA2__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA3 (0x05E) +#define MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA3__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_DIG_DEBUG_CTL (0x068) +#define MSM8X16_WCD_A_DIGITAL_DIG_DEBUG_CTL__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_DIG_DEBUG_EN (0x069) +#define MSM8X16_WCD_A_DIGITAL_DIG_DEBUG_EN__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_SPARE_0 (0x070) +#define MSM8X16_WCD_A_DIGITAL_SPARE_0__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_SPARE_1 (0x071) +#define MSM8X16_WCD_A_DIGITAL_SPARE_1__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_SPARE_2 (0x072) +#define MSM8X16_WCD_A_DIGITAL_SPARE_2__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_SEC_ACCESS (0x0D0) +#define MSM8X16_WCD_A_DIGITAL_SEC_ACCESS__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_PERPH_RESET_CTL1 (0x0D8) +#define MSM8X16_WCD_A_DIGITAL_PERPH_RESET_CTL1__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_PERPH_RESET_CTL2 (0x0D9) +#define MSM8X16_WCD_A_DIGITAL_PERPH_RESET_CTL2__POR (0x01) +#define MSM8X16_WCD_A_DIGITAL_PERPH_RESET_CTL3 (0x0DA) +#define MSM8X16_WCD_A_DIGITAL_PERPH_RESET_CTL3__POR (0x05) +#define MSM8X16_WCD_A_DIGITAL_PERPH_RESET_CTL4 (0x0DB) +#define MSM8X16_WCD_A_DIGITAL_PERPH_RESET_CTL4__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_INT_TEST1 (0x0E0) +#define MSM8X16_WCD_A_DIGITAL_INT_TEST1__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_INT_TEST_VAL (0x0E1) +#define MSM8X16_WCD_A_DIGITAL_INT_TEST_VAL__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_TRIM_NUM (0x0F0) +#define MSM8X16_WCD_A_DIGITAL_TRIM_NUM__POR (0x00) +#define MSM8X16_WCD_A_DIGITAL_TRIM_CTRL (0x0F1) +#define MSM8X16_WCD_A_DIGITAL_TRIM_CTRL__POR (0x00) + +#define MSM8X16_WCD_A_ANALOG_REVISION1 (0x100) +#define MSM8X16_WCD_A_ANALOG_REVISION1__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_REVISION2 (0x101) +#define MSM8X16_WCD_A_ANALOG_REVISION2__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_REVISION3 (0x102) +#define MSM8X16_WCD_A_ANALOG_REVISION3__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_REVISION4 (0x103) +#define MSM8X16_WCD_A_ANALOG_REVISION4__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_PERPH_TYPE (0x104) +#define MSM8X16_WCD_A_ANALOG_PERPH_TYPE__POR (0x23) +#define MSM8X16_WCD_A_ANALOG_PERPH_SUBTYPE (0x105) +#define MSM8X16_WCD_A_ANALOG_PERPH_SUBTYPE__POR (0x09) +#define MSM8X16_WCD_A_ANALOG_INT_RT_STS (0x110) +#define MSM8X16_WCD_A_ANALOG_INT_RT_STS__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_INT_SET_TYPE (0x111) +#define MSM8X16_WCD_A_ANALOG_INT_SET_TYPE__POR (0x3F) +#define MSM8X16_WCD_A_ANALOG_INT_POLARITY_HIGH (0x112) +#define MSM8X16_WCD_A_ANALOG_INT_POLARITY_HIGH__POR (0x3F) +#define MSM8X16_WCD_A_ANALOG_INT_POLARITY_LOW (0x113) +#define MSM8X16_WCD_A_ANALOG_INT_POLARITY_LOW__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_INT_LATCHED_CLR (0x114) +#define MSM8X16_WCD_A_ANALOG_INT_LATCHED_CLR__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_INT_EN_SET (0x115) +#define MSM8X16_WCD_A_ANALOG_INT_EN_SET__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_INT_EN_CLR (0x116) +#define MSM8X16_WCD_A_ANALOG_INT_EN_CLR__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_INT_LATCHED_STS (0x118) +#define MSM8X16_WCD_A_ANALOG_INT_LATCHED_STS__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_INT_PENDING_STS (0x119) +#define MSM8X16_WCD_A_ANALOG_INT_PENDING_STS__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_INT_MID_SEL (0x11A) +#define MSM8X16_WCD_A_ANALOG_INT_MID_SEL__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_INT_PRIORITY (0x11B) +#define MSM8X16_WCD_A_ANALOG_INT_PRIORITY__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_MICB_1_EN (0x140) +#define MSM8X16_WCD_A_ANALOG_MICB_1_EN__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_MICB_1_VAL (0x141) +#define MSM8X16_WCD_A_ANALOG_MICB_1_VAL__POR (0x20) +#define MSM8X16_WCD_A_ANALOG_MICB_1_CTL (0x142) +#define MSM8X16_WCD_A_ANALOG_MICB_1_CTL__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_MICB_1_INT_RBIAS (0x143) +#define MSM8X16_WCD_A_ANALOG_MICB_1_INT_RBIAS__POR (0x49) +#define MSM8X16_WCD_A_ANALOG_MICB_2_EN (0x144) +#define MSM8X16_WCD_A_ANALOG_MICB_2_EN__POR (0x20) +#define MSM8X16_WCD_A_ANALOG_TX_1_2_ATEST_CTL_2 (0x145) +#define MSM8X16_WCD_A_ANALOG_TX_1_2_ATEST_CTL_2__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_MASTER_BIAS_CTL (0x146) +#define MSM8X16_WCD_A_ANALOG_MASTER_BIAS_CTL__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_1 (0x147) +#define MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_1__POR (0x35) +#define MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_2 (0x150) +#define MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_2__POR (0x08) +#define MSM8X16_WCD_A_ANALOG_MBHC_FSM_CTL (0x151) +#define MSM8X16_WCD_A_ANALOG_MBHC_FSM_CTL__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_MBHC_DBNC_TIMER (0x152) +#define MSM8X16_WCD_A_ANALOG_MBHC_DBNC_TIMER__POR (0x98) +#define MSM8X16_WCD_A_ANALOG_MBHC_BTN0_ZDETL_CTL (0x153) +#define MSM8X16_WCD_A_ANALOG_MBHC_BTN0_ZDETL_CTL__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_MBHC_BTN1_ZDETM_CTL (0x154) +#define MSM8X16_WCD_A_ANALOG_MBHC_BTN1_ZDETM_CTL__POR (0x20) +#define MSM8X16_WCD_A_ANALOG_MBHC_BTN2_ZDETH_CTL (0x155) +#define MSM8X16_WCD_A_ANALOG_MBHC_BTN2_ZDETH_CTL__POR (0x40) +#define MSM8X16_WCD_A_ANALOG_MBHC_BTN3_CTL (0x156) +#define MSM8X16_WCD_A_ANALOG_MBHC_BTN3_CTL__POR (0x61) +#define MSM8X16_WCD_A_ANALOG_MBHC_BTN4_CTL (0x157) +#define MSM8X16_WCD_A_ANALOG_MBHC_BTN4_CTL__POR (0x80) +#define MSM8X16_WCD_A_ANALOG_MBHC_BTN_RESULT (0x158) +#define MSM8X16_WCD_A_ANALOG_MBHC_BTN_RESULT__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_MBHC_ZDET_ELECT_RESULT (0x159) +#define MSM8X16_WCD_A_ANALOG_MBHC_ZDET_ELECT_RESULT__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_TX_1_EN (0x160) +#define MSM8X16_WCD_A_ANALOG_TX_1_EN__POR (0x03) +#define MSM8X16_WCD_A_ANALOG_TX_2_EN (0x161) +#define MSM8X16_WCD_A_ANALOG_TX_2_EN__POR (0x03) +#define MSM8X16_WCD_A_ANALOG_TX_1_2_TEST_CTL_1 (0x162) +#define MSM8X16_WCD_A_ANALOG_TX_1_2_TEST_CTL_1__POR (0xBF) +#define MSM8X16_WCD_A_ANALOG_TX_1_2_TEST_CTL_2 (0x163) +#define MSM8X16_WCD_A_ANALOG_TX_1_2_TEST_CTL_2__POR (0x8C) +#define MSM8X16_WCD_A_ANALOG_TX_1_2_ATEST_CTL (0x164) +#define MSM8X16_WCD_A_ANALOG_TX_1_2_ATEST_CTL__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_TX_1_2_OPAMP_BIAS (0x165) +#define MSM8X16_WCD_A_ANALOG_TX_1_2_OPAMP_BIAS__POR (0x6B) +#define MSM8X16_WCD_A_ANALOG_TX_1_2_TXFE_CLKDIV (0x166) +#define MSM8X16_WCD_A_ANALOG_TX_1_2_TXFE_CLKDIV__POR (0x51) +#define MSM8X16_WCD_A_ANALOG_TX_3_EN (0x167) +#define MSM8X16_WCD_A_ANALOG_TX_3_EN__POR (0x02) +#define MSM8X16_WCD_A_ANALOG_NCP_EN (0x180) +#define MSM8X16_WCD_A_ANALOG_NCP_EN__POR (0x26) +#define MSM8X16_WCD_A_ANALOG_NCP_CLK (0x181) +#define MSM8X16_WCD_A_ANALOG_NCP_CLK__POR (0x23) +#define MSM8X16_WCD_A_ANALOG_NCP_DEGLITCH (0x182) +#define MSM8X16_WCD_A_ANALOG_NCP_DEGLITCH__POR (0x5B) +#define MSM8X16_WCD_A_ANALOG_NCP_FBCTRL (0x183) +#define MSM8X16_WCD_A_ANALOG_NCP_FBCTRL__POR (0x08) +#define MSM8X16_WCD_A_ANALOG_NCP_BIAS (0x184) +#define MSM8X16_WCD_A_ANALOG_NCP_BIAS__POR (0x29) +#define MSM8X16_WCD_A_ANALOG_NCP_VCTRL (0x185) +#define MSM8X16_WCD_A_ANALOG_NCP_VCTRL__POR (0x24) +#define MSM8X16_WCD_A_ANALOG_NCP_TEST (0x186) +#define MSM8X16_WCD_A_ANALOG_NCP_TEST__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_NCP_CLIM_ADDR (0x187) +#define MSM8X16_WCD_A_ANALOG_NCP_CLIM_ADDR__POR (0xD5) +#define MSM8X16_WCD_A_ANALOG_RX_CLOCK_DIVIDER (0x190) +#define MSM8X16_WCD_A_ANALOG_RX_CLOCK_DIVIDER__POR (0xE8) +#define MSM8X16_WCD_A_ANALOG_RX_COM_OCP_CTL (0x191) +#define MSM8X16_WCD_A_ANALOG_RX_COM_OCP_CTL__POR (0xCF) +#define MSM8X16_WCD_A_ANALOG_RX_COM_OCP_COUNT (0x192) +#define MSM8X16_WCD_A_ANALOG_RX_COM_OCP_COUNT__POR (0x6E) +#define MSM8X16_WCD_A_ANALOG_RX_COM_BIAS_DAC (0x193) +#define MSM8X16_WCD_A_ANALOG_RX_COM_BIAS_DAC__POR (0x10) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_PA (0x194) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_PA__POR (0x5A) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_LDO_OCP (0x195) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_LDO_OCP__POR (0x69) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_CNP (0x196) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_CNP__POR (0x29) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_EN (0x197) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_EN__POR (0x80) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_WG_CTL (0x198) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_WG_CTL__POR (0xDA) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_WG_TIME (0x199) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_WG_TIME__POR (0x16) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_L_TEST (0x19A) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_L_TEST__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_L_PA_DAC_CTL (0x19B) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_L_PA_DAC_CTL__POR (0x20) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_R_TEST (0x19C) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_R_TEST__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_R_PA_DAC_CTL (0x19D) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_R_PA_DAC_CTL__POR (0x20) +#define MSM8X16_WCD_A_ANALOG_RX_EAR_CTL (0x19E) +#define MSM8X16_WCD_A_ANALOG_RX_EAR_CTL___POR (0x12) +#define MSM8X16_WCD_A_ANALOG_RX_ATEST (0x19F) +#define MSM8X16_WCD_A_ANALOG_RX_ATEST__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_STATUS (0x1A0) +#define MSM8X16_WCD_A_ANALOG_RX_HPH_STATUS__POR (0x0C) +#define MSM8X16_WCD_A_ANALOG_RX_EAR_STATUS (0x1A1) +#define MSM8X16_WCD_A_ANALOG_RX_EAR_STATUS__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_SPKR_DAC_CTL (0x1B0) +#define MSM8X16_WCD_A_ANALOG_SPKR_DAC_CTL__POR (0x83) +#define MSM8X16_WCD_A_ANALOG_SPKR_DRV_CLIP_DET (0x1B1) +#define MSM8X16_WCD_A_ANALOG_SPKR_DRV_CLIP_DET__POR (0x91) +#define MSM8X16_WCD_A_ANALOG_SPKR_DRV_CTL (0x1B2) +#define MSM8X16_WCD_A_ANALOG_SPKR_DRV_CTL__POR (0x29) +#define MSM8X16_WCD_A_ANALOG_SPKR_ANA_BIAS_SET (0x1B3) +#define MSM8X16_WCD_A_ANALOG_SPKR_ANA_BIAS_SET__POR (0x4D) +#define MSM8X16_WCD_A_ANALOG_SPKR_OCP_CTL (0x1B4) +#define MSM8X16_WCD_A_ANALOG_SPKR_OCP_CTL__POR (0xE1) +#define MSM8X16_WCD_A_ANALOG_SPKR_PWRSTG_CTL (0x1B5) +#define MSM8X16_WCD_A_ANALOG_SPKR_PWRSTG_CTL__POR (0x1E) +#define MSM8X16_WCD_A_ANALOG_SPKR_DRV_MISC (0x1B6) +#define MSM8X16_WCD_A_ANALOG_SPKR_DRV_MISC__POR (0xCB) +#define MSM8X16_WCD_A_ANALOG_SPKR_DRV_DBG (0x1B7) +#define MSM8X16_WCD_A_ANALOG_SPKR_DRV_DBG__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_CURRENT_LIMIT (0x1C0) +#define MSM8X16_WCD_A_ANALOG_CURRENT_LIMIT__POR (0x02) +#define MSM8X16_WCD_A_ANALOG_OUTPUT_VOLTAGE (0x1C1) +#define MSM8X16_WCD_A_ANALOG_OUTPUT_VOLTAGE__POR (0x14) +#define MSM8X16_WCD_A_ANALOG_BYPASS_MODE (0x1C2) +#define MSM8X16_WCD_A_ANALOG_BYPASS_MODE__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_BOOST_EN_CTL (0x1C3) +#define MSM8X16_WCD_A_ANALOG_BOOST_EN_CTL__POR (0x1F) +#define MSM8X16_WCD_A_ANALOG_SLOPE_COMP_IP_ZERO (0x1C4) +#define MSM8X16_WCD_A_ANALOG_SLOPE_COMP_IP_ZERO__POR (0x8C) +#define MSM8X16_WCD_A_ANALOG_RDSON_MAX_DUTY_CYCLE (0x1C5) +#define MSM8X16_WCD_A_ANALOG_RDSON_MAX_DUTY_CYCLE__POR (0xC0) +#define MSM8X16_WCD_A_ANALOG_BOOST_TEST1_1 (0x1C6) +#define MSM8X16_WCD_A_ANALOG_BOOST_TEST1_1__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_BOOST_TEST_2 (0x1C7) +#define MSM8X16_WCD_A_ANALOG_BOOST_TEST_2__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_SPKR_SAR_STATUS (0x1C8) +#define MSM8X16_WCD_A_ANALOG_SPKR_SAR_STATUS__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_SPKR_DRV_STATUS (0x1C9) +#define MSM8X16_WCD_A_ANALOG_SPKR_DRV_STATUS__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_PBUS_ADD_CSR (0x1CE) +#define MSM8X16_WCD_A_ANALOG_PBUS_ADD_CSR__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_PBUS_ADD_SEL (0x1CF) +#define MSM8X16_WCD_A_ANALOG_PBUS_ADD_SEL__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_SEC_ACCESS (0x1D0) +#define MSM8X16_WCD_A_ANALOG_SEC_ACCESS__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_PERPH_RESET_CTL1 (0x1D8) +#define MSM8X16_WCD_A_ANALOG_PERPH_RESET_CTL1__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_PERPH_RESET_CTL2 (0x1D9) +#define MSM8X16_WCD_A_ANALOG_PERPH_RESET_CTL2__POR (0x01) +#define MSM8X16_WCD_A_ANALOG_PERPH_RESET_CTL3 (0x1DA) +#define MSM8X16_WCD_A_ANALOG_PERPH_RESET_CTL3__POR (0x05) +#define MSM8X16_WCD_A_ANALOG_PERPH_RESET_CTL4 (0x1DB) +#define MSM8X16_WCD_A_ANALOG_PERPH_RESET_CTL4__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_INT_TEST1 (0x1E0) +#define MSM8X16_WCD_A_ANALOG_INT_TEST1__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_INT_TEST_VAL (0x1E1) +#define MSM8X16_WCD_A_ANALOG_INT_TEST_VAL__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_TRIM_NUM (0x1F0) +#define MSM8X16_WCD_A_ANALOG_TRIM_NUM__POR (0x04) +#define MSM8X16_WCD_A_ANALOG_TRIM_CTRL1 (0x1F1) +#define MSM8X16_WCD_A_ANALOG_TRIM_CTRL1__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_TRIM_CTRL2 (0x1F2) +#define MSM8X16_WCD_A_ANALOG_TRIM_CTRL2__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_TRIM_CTRL3 (0x1F3) +#define MSM8X16_WCD_A_ANALOG_TRIM_CTRL3__POR (0x00) +#define MSM8X16_WCD_A_ANALOG_TRIM_CTRL4 (0x1F4) +#define MSM8X16_WCD_A_ANALOG_TRIM_CTRL4__POR (0x00) + +/* Digital part */ +#define MSM8X16_WCD_A_CDC_CLK_RX_RESET_CTL (0x200) +#define MSM8X16_WCD_A_CDC_CLK_RX_RESET_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CLK_TX_RESET_B1_CTL (0x204) +#define MSM8X16_WCD_A_CDC_CLK_TX_RESET_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CLK_DMIC_B1_CTL (0x208) +#define MSM8X16_WCD_A_CDC_CLK_DMIC_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CLK_RX_I2S_CTL (0x20C) +#define MSM8X16_WCD_A_CDC_CLK_RX_I2S_CTL__POR (0x13) +#define MSM8X16_WCD_A_CDC_CLK_TX_I2S_CTL (0x210) +#define MSM8X16_WCD_A_CDC_CLK_TX_I2S_CTL__POR (0x13) +#define MSM8X16_WCD_A_CDC_CLK_OTHR_RESET_B1_CTL (0x214) +#define MSM8X16_WCD_A_CDC_CLK_OTHR_RESET_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL (0x218) +#define MSM8X16_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CLK_OTHR_CTL (0x21C) +#define MSM8X16_WCD_A_CDC_CLK_OTHR_CTL__POR (0x04) +#define MSM8X16_WCD_A_CDC_CLK_RX_B1_CTL (0x220) +#define MSM8X16_WCD_A_CDC_CLK_RX_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CLK_MCLK_CTL (0x224) +#define MSM8X16_WCD_A_CDC_CLK_MCLK_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CLK_PDM_CTL (0x228) +#define MSM8X16_WCD_A_CDC_CLK_PDM_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CLK_SD_CTL (0x22C) +#define MSM8X16_WCD_A_CDC_CLK_SD_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX1_B1_CTL (0x240) +#define MSM8X16_WCD_A_CDC_RX1_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX2_B1_CTL (0x260) +#define MSM8X16_WCD_A_CDC_RX2_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX3_B1_CTL (0x280) +#define MSM8X16_WCD_A_CDC_RX3_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX1_B2_CTL (0x244) +#define MSM8X16_WCD_A_CDC_RX1_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX2_B2_CTL (0x264) +#define MSM8X16_WCD_A_CDC_RX2_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX3_B2_CTL (0x284) +#define MSM8X16_WCD_A_CDC_RX3_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX1_B3_CTL (0x248) +#define MSM8X16_WCD_A_CDC_RX1_B3_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX2_B3_CTL (0x268) +#define MSM8X16_WCD_A_CDC_RX2_B3_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX3_B3_CTL (0x288) +#define MSM8X16_WCD_A_CDC_RX3_B3_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX1_B4_CTL (0x24C) +#define MSM8X16_WCD_A_CDC_RX1_B4_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX2_B4_CTL (0x26C) +#define MSM8X16_WCD_A_CDC_RX2_B4_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX3_B4_CTL (0x28C) +#define MSM8X16_WCD_A_CDC_RX3_B4_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX1_B5_CTL (0x250) +#define MSM8X16_WCD_A_CDC_RX1_B5_CTL__POR (0x68) +#define MSM8X16_WCD_A_CDC_RX2_B5_CTL (0x270) +#define MSM8X16_WCD_A_CDC_RX2_B5_CTL__POR (0x68) +#define MSM8X16_WCD_A_CDC_RX3_B5_CTL (0x290) +#define MSM8X16_WCD_A_CDC_RX3_B5_CTL__POR (0x68) +#define MSM8X16_WCD_A_CDC_RX1_B6_CTL (0x254) +#define MSM8X16_WCD_A_CDC_RX1_B6_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX2_B6_CTL (0x274) +#define MSM8X16_WCD_A_CDC_RX2_B6_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX3_B6_CTL (0x294) +#define MSM8X16_WCD_A_CDC_RX3_B6_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX1_VOL_CTL_B1_CTL (0x258) +#define MSM8X16_WCD_A_CDC_RX1_VOL_CTL_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX2_VOL_CTL_B1_CTL (0x278) +#define MSM8X16_WCD_A_CDC_RX2_VOL_CTL_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX3_VOL_CTL_B1_CTL (0x298) +#define MSM8X16_WCD_A_CDC_RX3_VOL_CTL_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX1_VOL_CTL_B2_CTL (0x25C) +#define MSM8X16_WCD_A_CDC_RX1_VOL_CTL_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX2_VOL_CTL_B2_CTL (0x27C) +#define MSM8X16_WCD_A_CDC_RX2_VOL_CTL_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_RX3_VOL_CTL_B2_CTL (0x29C) +#define MSM8X16_WCD_A_CDC_RX3_VOL_CTL_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_TOP_GAIN_UPDATE (0x2A0) +#define MSM8X16_WCD_A_CDC_TOP_GAIN_UPDATE__POR (0x00) +#define MSM8X16_WCD_A_CDC_TOP_CTL (0x2A4) +#define MSM8X16_WCD_A_CDC_TOP_CTL__POR (0x01) +#define MSM8X16_WCD_A_CDC_DEBUG_DESER1_CTL (0x2E0) +#define MSM8X16_WCD_A_CDC_DEBUG_DESER1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_DEBUG_DESER2_CTL (0x2E4) +#define MSM8X16_WCD_A_CDC_DEBUG_DESER2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_DEBUG_B1_CTL_CFG (0x2E8) +#define MSM8X16_WCD_A_CDC_DEBUG_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_DEBUG_B2_CTL_CFG (0x2EC) +#define MSM8X16_WCD_A_CDC_DEBUG_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_DEBUG_B3_CTL_CFG (0x2F0) +#define MSM8X16_WCD_A_CDC_DEBUG_B3_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B1_CTL (0x300) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B1_CTL (0x340) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B2_CTL (0x304) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B2_CTL (0x344) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B3_CTL (0x308) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B3_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B3_CTL (0x348) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B3_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B4_CTL (0x30C) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B4_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B4_CTL (0x34C) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B4_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B5_CTL (0x310) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B5_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B5_CTL (0x350) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B5_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B6_CTL (0x314) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B6_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B6_CTL (0x354) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B6_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B7_CTL (0x318) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B7_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B7_CTL (0x358) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B7_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B8_CTL (0x31C) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_B8_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B8_CTL (0x35C) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_B8_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR1_CTL (0x320) +#define MSM8X16_WCD_A_CDC_IIR1_CTL__POR (0x40) +#define MSM8X16_WCD_A_CDC_IIR2_CTL (0x360) +#define MSM8X16_WCD_A_CDC_IIR2_CTL__POR (0x40) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_TIMER_CTL (0x324) +#define MSM8X16_WCD_A_CDC_IIR1_GAIN_TIMER_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_TIMER_CTL (0x364) +#define MSM8X16_WCD_A_CDC_IIR2_GAIN_TIMER_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR1_COEF_B1_CTL (0x328) +#define MSM8X16_WCD_A_CDC_IIR1_COEF_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR2_COEF_B1_CTL (0x368) +#define MSM8X16_WCD_A_CDC_IIR2_COEF_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR1_COEF_B2_CTL (0x32C) +#define MSM8X16_WCD_A_CDC_IIR1_COEF_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_IIR2_COEF_B2_CTL (0x36C) +#define MSM8X16_WCD_A_CDC_IIR2_COEF_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_RX1_B1_CTL (0x380) +#define MSM8X16_WCD_A_CDC_CONN_RX1_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_RX1_B2_CTL (0x384) +#define MSM8X16_WCD_A_CDC_CONN_RX1_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_RX1_B3_CTL (0x388) +#define MSM8X16_WCD_A_CDC_CONN_RX1_B3_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_RX2_B1_CTL (0x38C) +#define MSM8X16_WCD_A_CDC_CONN_RX2_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_RX2_B2_CTL (0x390) +#define MSM8X16_WCD_A_CDC_CONN_RX2_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_RX2_B3_CTL (0x394) +#define MSM8X16_WCD_A_CDC_CONN_RX2_B3_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_RX3_B1_CTL (0x398) +#define MSM8X16_WCD_A_CDC_CONN_RX3_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_RX3_B2_CTL (0x39C) +#define MSM8X16_WCD_A_CDC_CONN_RX3_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_TX_B1_CTL (0x3A0) +#define MSM8X16_WCD_A_CDC_CONN_TX_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_EQ1_B1_CTL (0x3A8) +#define MSM8X16_WCD_A_CDC_CONN_EQ1_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_EQ1_B2_CTL (0x3AC) +#define MSM8X16_WCD_A_CDC_CONN_EQ1_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_EQ1_B3_CTL (0x3B0) +#define MSM8X16_WCD_A_CDC_CONN_EQ1_B3_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_EQ1_B4_CTL (0x3B4) +#define MSM8X16_WCD_A_CDC_CONN_EQ1_B4_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_EQ2_B1_CTL (0x3B8) +#define MSM8X16_WCD_A_CDC_CONN_EQ2_B1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_EQ2_B2_CTL (0x3BC) +#define MSM8X16_WCD_A_CDC_CONN_EQ2_B2_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_EQ2_B3_CTL (0x3C0) +#define MSM8X16_WCD_A_CDC_CONN_EQ2_B3_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_EQ2_B4_CTL (0x3C4) +#define MSM8X16_WCD_A_CDC_CONN_EQ2_B4_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_CONN_TX_I2S_SD1_CTL (0x3C8) +#define MSM8X16_WCD_A_CDC_CONN_TX_I2S_SD1_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_TX1_VOL_CTL_TIMER (0x480) +#define MSM8X16_WCD_A_CDC_TX1_VOL_CTL_TIMER__POR (0x00) +#define MSM8X16_WCD_A_CDC_TX2_VOL_CTL_TIMER (0x4A0) +#define MSM8X16_WCD_A_CDC_TX2_VOL_CTL_TIMER__POR (0x00) +#define MSM8X16_WCD_A_CDC_TX1_VOL_CTL_GAIN (0x484) +#define MSM8X16_WCD_A_CDC_TX1_VOL_CTL_GAIN__POR (0x00) +#define MSM8X16_WCD_A_CDC_TX2_VOL_CTL_GAIN (0x4A4) +#define MSM8X16_WCD_A_CDC_TX2_VOL_CTL_GAIN__POR (0x00) +#define MSM8X16_WCD_A_CDC_TX1_VOL_CTL_CFG (0x488) +#define MSM8X16_WCD_A_CDC_TX1_VOL_CTL_CFG__POR (0x00) +#define MSM8X16_WCD_A_CDC_TX2_VOL_CTL_CFG (0x4A8) +#define MSM8X16_WCD_A_CDC_TX2_VOL_CTL_CFG__POR (0x00) +#define MSM8X16_WCD_A_CDC_TX1_MUX_CTL (0x48C) +#define MSM8X16_WCD_A_CDC_TX1_MUX_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_TX2_MUX_CTL (0x4AC) +#define MSM8X16_WCD_A_CDC_TX2_MUX_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_TX1_CLK_FS_CTL (0x490) +#define MSM8X16_WCD_A_CDC_TX1_CLK_FS_CTL__POR (0x03) +#define MSM8X16_WCD_A_CDC_TX2_CLK_FS_CTL (0x4B0) +#define MSM8X16_WCD_A_CDC_TX2_CLK_FS_CTL__POR (0x03) +#define MSM8X16_WCD_A_CDC_TX1_DMIC_CTL (0x494) +#define MSM8X16_WCD_A_CDC_TX1_DMIC_CTL__POR (0x00) +#define MSM8X16_WCD_A_CDC_TX2_DMIC_CTL (0x4B4) +#define MSM8X16_WCD_A_CDC_TX2_DMIC_CTL__POR (0x00) +#endif
This patch add register ranges for readonly, default and reset register values.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/codecs/msm8x16-wcd.c | 95 ++++++ sound/soc/codecs/msm8x16-wcd.h | 753 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 848 insertions(+) create mode 100644 sound/soc/codecs/msm8x16-wcd.h
diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c index 99217ab..3598e48 100644 --- a/sound/soc/codecs/msm8x16-wcd.c +++ b/sound/soc/codecs/msm8x16-wcd.c @@ -11,6 +11,9 @@ #include <linux/mfd/syscon.h> #include <sound/soc.h>
+#include "msm8x16-wcd-registers.h" +#include "msm8x16-wcd.h" + struct msm8x16_wcd_chip { struct regmap *analog_map; struct regmap *digital_map; @@ -33,6 +36,93 @@ struct msm8x16_wcd_chip { bool micbias2_cap_mode; };
+static int msm8x16_wcd_volatile(struct snd_soc_codec *codec, unsigned int reg) +{ + return msm8x16_wcd_reg_readonly[reg]; +} + +static int msm8x16_wcd_readable(struct snd_soc_codec *ssc, unsigned int reg) +{ + return msm8x16_wcd_reg_readable[reg]; +} + +static int __msm8x16_wcd_reg_write(struct snd_soc_codec *codec, + unsigned short reg, u8 val) +{ + int ret = -EINVAL; + struct msm8x16_wcd_chip *chip = dev_get_drvdata(codec->dev); + + if (MSM8X16_WCD_IS_TOMBAK_REG(reg)) { + ret = regmap_write(chip->analog_map, + chip->analog_base + reg, val); + } else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) { + u32 temp = val & 0x000000FF; + u16 offset = (reg ^ 0x0200) & 0x0FFF; + + ret = regmap_write(chip->digital_map, offset, temp); + } + + return ret; +} + +static int msm8x16_wcd_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + if (reg == SND_SOC_NOPM) + return 0; + + WARN_ON(reg > MSM8X16_WCD_MAX_REGISTER); + if (!msm8x16_wcd_volatile(codec, reg)) + msm8x16_wcd_reset_reg_defaults[reg] = value; + + return __msm8x16_wcd_reg_write(codec, reg, (u8)value); +} + +static int __msm8x16_wcd_reg_read(struct snd_soc_codec *codec, + unsigned short reg) +{ + int ret = -EINVAL; + u32 temp = 0; + struct msm8x16_wcd_chip *chip = dev_get_drvdata(codec->dev); + + if (MSM8X16_WCD_IS_TOMBAK_REG(reg)) { + ret = regmap_read(chip->analog_map, + chip->analog_base + reg, &temp); + } else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) { + u32 val; + u16 offset = (reg ^ 0x0200) & 0x0FFF; + + ret = regmap_read(chip->digital_map, offset, &val); + temp = (u8)val; + } + + if (ret < 0) { + dev_err(codec->dev, + "%s: codec read failed for reg 0x%x\n", + __func__, reg); + return ret; + } + + return temp; +} + +static unsigned int msm8x16_wcd_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + unsigned int val; + + WARN_ON(reg > MSM8X16_WCD_MAX_REGISTER); + + if (!msm8x16_wcd_volatile(codec, reg) && + msm8x16_wcd_readable(codec, reg) && + reg < codec->driver->reg_cache_size) { + return msm8x16_wcd_reset_reg_defaults[reg]; + } + + val = __msm8x16_wcd_reg_read(codec, reg); + + return val; +}
static int msm8x16_wcd_codec_parse_dt(struct platform_device *pdev, struct msm8x16_wcd_chip *chip) @@ -96,6 +186,11 @@ static struct snd_soc_dai_driver msm8x16_wcd_codec_dai[] = { };
static struct snd_soc_codec_driver msm8x16_wcd_codec = { + .read = msm8x16_wcd_read, + .write = msm8x16_wcd_write, + .reg_cache_size = MSM8X16_WCD_NUM_REGISTERS, + .reg_cache_default = msm8x16_wcd_reset_reg_defaults, + .reg_word_size = 1, };
static int msm8x16_wcd_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/msm8x16-wcd.h b/sound/soc/codecs/msm8x16-wcd.h new file mode 100644 index 0000000..db82f58 --- /dev/null +++ b/sound/soc/codecs/msm8x16-wcd.h @@ -0,0 +1,753 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef MSM8X16_WCD_H +#define MSM8X16_WCD_H + +#include "msm8x16-wcd.h" + +#define MSM8X16_WCD_NUM_REGISTERS 0x6FF +#define MSM8X16_WCD_MAX_REGISTER (MSM8X16_WCD_NUM_REGISTERS-1) + +#define MSM8X16_WCD_IS_DIGITAL_REG(reg) \ + (((reg >= 0x200) && (reg <= 0x4FF)) ? 1 : 0) +#define MSM8X16_WCD_IS_TOMBAK_REG(reg) \ + (((reg >= 0x000) && (reg <= 0x1FF)) ? 1 : 0) + +const u8 msm8x16_wcd_reg_readable[MSM8X16_WCD_NUM_REGISTERS] = { + [MSM8X16_WCD_A_DIGITAL_REVISION1] = 1, + [MSM8X16_WCD_A_DIGITAL_REVISION2] = 1, + [MSM8X16_WCD_A_DIGITAL_PERPH_TYPE] = 1, + [MSM8X16_WCD_A_DIGITAL_PERPH_SUBTYPE] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_RT_STS] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_SET_TYPE] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_POLARITY_HIGH] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_POLARITY_LOW] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_EN_SET] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_EN_CLR] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_LATCHED_STS] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_PENDING_STS] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_MID_SEL] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_PRIORITY] = 1, + [MSM8X16_WCD_A_DIGITAL_GPIO_MODE] = 1, + [MSM8X16_WCD_A_DIGITAL_PIN_CTL_OE] = 1, + [MSM8X16_WCD_A_DIGITAL_PIN_CTL_DATA] = 1, + [MSM8X16_WCD_A_DIGITAL_PIN_STATUS] = 1, + [MSM8X16_WCD_A_DIGITAL_HDRIVE_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_RST_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_TOP_CLK_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_ANA_CLK_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX1_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX2_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_HPHR_DAC_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX1_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX2_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX3_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX_LB_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL1] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL2] = 1, + [MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL3] = 1, + [MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA0] = 1, + [MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA1] = 1, + [MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA2] = 1, + [MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA3] = 1, + [MSM8X16_WCD_A_DIGITAL_DIG_DEBUG_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_SPARE_0] = 1, + [MSM8X16_WCD_A_DIGITAL_SPARE_1] = 1, + [MSM8X16_WCD_A_DIGITAL_SPARE_2] = 1, + [MSM8X16_WCD_A_ANALOG_REVISION1] = 1, + [MSM8X16_WCD_A_ANALOG_REVISION2] = 1, + [MSM8X16_WCD_A_ANALOG_REVISION3] = 1, + [MSM8X16_WCD_A_ANALOG_REVISION4] = 1, + [MSM8X16_WCD_A_ANALOG_PERPH_TYPE] = 1, + [MSM8X16_WCD_A_ANALOG_PERPH_SUBTYPE] = 1, + [MSM8X16_WCD_A_ANALOG_INT_RT_STS] = 1, + [MSM8X16_WCD_A_ANALOG_INT_SET_TYPE] = 1, + [MSM8X16_WCD_A_ANALOG_INT_POLARITY_HIGH] = 1, + [MSM8X16_WCD_A_ANALOG_INT_POLARITY_LOW] = 1, + [MSM8X16_WCD_A_ANALOG_INT_EN_SET] = 1, + [MSM8X16_WCD_A_ANALOG_INT_EN_CLR] = 1, + [MSM8X16_WCD_A_ANALOG_INT_LATCHED_STS] = 1, + [MSM8X16_WCD_A_ANALOG_INT_PENDING_STS] = 1, + [MSM8X16_WCD_A_ANALOG_INT_MID_SEL] = 1, + [MSM8X16_WCD_A_ANALOG_INT_PRIORITY] = 1, + [MSM8X16_WCD_A_ANALOG_MICB_1_EN] = 1, + [MSM8X16_WCD_A_ANALOG_MICB_1_VAL] = 1, + [MSM8X16_WCD_A_ANALOG_MICB_1_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_MICB_1_INT_RBIAS] = 1, + [MSM8X16_WCD_A_ANALOG_MICB_2_EN] = 1, + [MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_1] = 1, + [MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_2] = 1, + [MSM8X16_WCD_A_ANALOG_MBHC_FSM_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_MBHC_DBNC_TIMER] = 1, + [MSM8X16_WCD_A_ANALOG_MBHC_BTN0_ZDETL_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_MBHC_BTN1_ZDETM_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_MBHC_BTN2_ZDETH_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_MBHC_BTN3_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_MBHC_BTN4_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_MBHC_BTN_RESULT] = 1, + [MSM8X16_WCD_A_ANALOG_MBHC_ZDET_ELECT_RESULT] = 1, + [MSM8X16_WCD_A_ANALOG_TX_1_EN] = 1, + [MSM8X16_WCD_A_ANALOG_TX_2_EN] = 1, + [MSM8X16_WCD_A_ANALOG_TX_1_2_TEST_CTL_1] = 1, + [MSM8X16_WCD_A_ANALOG_TX_1_2_TEST_CTL_2] = 1, + [MSM8X16_WCD_A_ANALOG_TX_1_2_ATEST_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_TX_1_2_OPAMP_BIAS] = 1, + [MSM8X16_WCD_A_ANALOG_TX_1_2_TXFE_CLKDIV] = 1, + [MSM8X16_WCD_A_ANALOG_TX_3_EN] = 1, + [MSM8X16_WCD_A_ANALOG_NCP_EN] = 1, + [MSM8X16_WCD_A_ANALOG_NCP_CLK] = 1, + [MSM8X16_WCD_A_ANALOG_NCP_DEGLITCH] = 1, + [MSM8X16_WCD_A_ANALOG_NCP_FBCTRL] = 1, + [MSM8X16_WCD_A_ANALOG_NCP_BIAS] = 1, + [MSM8X16_WCD_A_ANALOG_NCP_VCTRL] = 1, + [MSM8X16_WCD_A_ANALOG_NCP_TEST] = 1, + [MSM8X16_WCD_A_ANALOG_RX_CLOCK_DIVIDER] = 1, + [MSM8X16_WCD_A_ANALOG_RX_COM_OCP_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_RX_COM_OCP_COUNT] = 1, + [MSM8X16_WCD_A_ANALOG_RX_COM_BIAS_DAC] = 1, + [MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_PA] = 1, + [MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_LDO_OCP] = 1, + [MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_CNP] = 1, + [MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_EN] = 1, + [MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_WG_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_WG_TIME] = 1, + [MSM8X16_WCD_A_ANALOG_RX_HPH_L_TEST] = 1, + [MSM8X16_WCD_A_ANALOG_RX_HPH_L_PA_DAC_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_RX_HPH_R_TEST] = 1, + [MSM8X16_WCD_A_ANALOG_RX_HPH_R_PA_DAC_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_RX_EAR_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_RX_ATEST] = 1, + [MSM8X16_WCD_A_ANALOG_RX_HPH_STATUS] = 1, + [MSM8X16_WCD_A_ANALOG_RX_EAR_STATUS] = 1, + [MSM8X16_WCD_A_ANALOG_SPKR_DAC_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_SPKR_DRV_CLIP_DET] = 1, + [MSM8X16_WCD_A_ANALOG_SPKR_DRV_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_SPKR_ANA_BIAS_SET] = 1, + [MSM8X16_WCD_A_ANALOG_SPKR_OCP_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_SPKR_PWRSTG_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_SPKR_DRV_MISC] = 1, + [MSM8X16_WCD_A_ANALOG_SPKR_DRV_DBG] = 1, + [MSM8X16_WCD_A_ANALOG_CURRENT_LIMIT] = 1, + [MSM8X16_WCD_A_ANALOG_OUTPUT_VOLTAGE] = 1, + [MSM8X16_WCD_A_ANALOG_BYPASS_MODE] = 1, + [MSM8X16_WCD_A_ANALOG_BOOST_EN_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_SLOPE_COMP_IP_ZERO] = 1, + [MSM8X16_WCD_A_ANALOG_RDSON_MAX_DUTY_CYCLE] = 1, + [MSM8X16_WCD_A_ANALOG_BOOST_TEST1_1] = 1, + [MSM8X16_WCD_A_ANALOG_BOOST_TEST_2] = 1, + [MSM8X16_WCD_A_ANALOG_SPKR_SAR_STATUS] = 1, + [MSM8X16_WCD_A_ANALOG_SPKR_DRV_STATUS] = 1, + [MSM8X16_WCD_A_ANALOG_PBUS_ADD_CSR] = 1, + [MSM8X16_WCD_A_ANALOG_PBUS_ADD_SEL] = 1, + [MSM8X16_WCD_A_CDC_CLK_RX_RESET_CTL] = 1, + [MSM8X16_WCD_A_CDC_CLK_TX_RESET_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_CLK_DMIC_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_CLK_RX_I2S_CTL] = 1, + [MSM8X16_WCD_A_CDC_CLK_TX_I2S_CTL] = 1, + [MSM8X16_WCD_A_CDC_CLK_OTHR_RESET_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_CLK_OTHR_CTL] = 1, + [MSM8X16_WCD_A_CDC_CLK_RX_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_CLK_MCLK_CTL] = 1, + [MSM8X16_WCD_A_CDC_CLK_PDM_CTL] = 1, + [MSM8X16_WCD_A_CDC_CLK_SD_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX1_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX2_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX3_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX1_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX2_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX3_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX1_B3_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX2_B3_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX3_B3_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX1_B4_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX2_B4_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX3_B4_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX1_B5_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX2_B5_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX3_B5_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX1_B6_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX2_B6_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX3_B6_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX1_VOL_CTL_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX2_VOL_CTL_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX3_VOL_CTL_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX1_VOL_CTL_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX2_VOL_CTL_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX3_VOL_CTL_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_TOP_GAIN_UPDATE] = 1, + [MSM8X16_WCD_A_CDC_TOP_CTL] = 1, + [MSM8X16_WCD_A_CDC_DEBUG_DESER1_CTL] = 1, + [MSM8X16_WCD_A_CDC_DEBUG_DESER2_CTL] = 1, + [MSM8X16_WCD_A_CDC_DEBUG_B1_CTL_CFG] = 1, + [MSM8X16_WCD_A_CDC_DEBUG_B2_CTL_CFG] = 1, + [MSM8X16_WCD_A_CDC_DEBUG_B3_CTL_CFG] = 1, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B3_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B3_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B4_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B4_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B5_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B5_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B6_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B6_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B7_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B7_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B8_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B8_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR1_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR2_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_TIMER_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_TIMER_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR1_COEF_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR2_COEF_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR1_COEF_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR2_COEF_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_RX1_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_RX1_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_RX1_B3_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_RX2_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_RX2_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_RX2_B3_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_RX3_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_RX3_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_TX_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_EQ1_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_EQ1_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_EQ1_B3_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_EQ1_B4_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_EQ2_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_EQ2_B2_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_EQ2_B3_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_EQ2_B4_CTL] = 1, + [MSM8X16_WCD_A_CDC_CONN_TX_I2S_SD1_CTL] = 1, + [MSM8X16_WCD_A_CDC_TX1_VOL_CTL_TIMER] = 1, + [MSM8X16_WCD_A_CDC_TX2_VOL_CTL_TIMER] = 1, + [MSM8X16_WCD_A_CDC_TX1_VOL_CTL_GAIN] = 1, + [MSM8X16_WCD_A_CDC_TX2_VOL_CTL_GAIN] = 1, + [MSM8X16_WCD_A_CDC_TX1_VOL_CTL_CFG] = 1, + [MSM8X16_WCD_A_CDC_TX2_VOL_CTL_CFG] = 1, + [MSM8X16_WCD_A_CDC_TX1_MUX_CTL] = 1, + [MSM8X16_WCD_A_CDC_TX2_MUX_CTL] = 1, + [MSM8X16_WCD_A_CDC_TX1_CLK_FS_CTL] = 1, + [MSM8X16_WCD_A_CDC_TX2_CLK_FS_CTL] = 1, + [MSM8X16_WCD_A_CDC_TX1_DMIC_CTL] = 1, + [MSM8X16_WCD_A_CDC_TX2_DMIC_CTL] = 1, + [MSM8X16_WCD_A_ANALOG_MASTER_BIAS_CTL] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_LATCHED_CLR] = 1, + [MSM8X16_WCD_A_ANALOG_INT_LATCHED_CLR] = 1, + [MSM8X16_WCD_A_ANALOG_NCP_CLIM_ADDR] = 1, + [MSM8X16_WCD_A_DIGITAL_SEC_ACCESS] = 1, + [MSM8X16_WCD_A_DIGITAL_PERPH_RESET_CTL3] = 1, + [MSM8X16_WCD_A_ANALOG_SEC_ACCESS] = 1, +}; + +const u8 msm8x16_wcd_reg_readonly[MSM8X16_WCD_NUM_REGISTERS] = { + [MSM8X16_WCD_A_DIGITAL_REVISION1] = 1, + [MSM8X16_WCD_A_DIGITAL_REVISION2] = 1, + [MSM8X16_WCD_A_DIGITAL_PERPH_TYPE] = 1, + [MSM8X16_WCD_A_DIGITAL_PERPH_SUBTYPE] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_RT_STS] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_SET_TYPE] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_POLARITY_HIGH] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_POLARITY_LOW] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_LATCHED_STS] = 1, + [MSM8X16_WCD_A_DIGITAL_INT_PENDING_STS] = 1, + [MSM8X16_WCD_A_DIGITAL_PIN_STATUS] = 1, + [MSM8X16_WCD_A_ANALOG_REVISION1] = 1, + [MSM8X16_WCD_A_ANALOG_REVISION2] = 1, + [MSM8X16_WCD_A_ANALOG_REVISION3] = 1, + [MSM8X16_WCD_A_ANALOG_REVISION4] = 1, + [MSM8X16_WCD_A_ANALOG_PERPH_TYPE] = 1, + [MSM8X16_WCD_A_ANALOG_PERPH_SUBTYPE] = 1, + [MSM8X16_WCD_A_ANALOG_INT_RT_STS] = 1, + [MSM8X16_WCD_A_ANALOG_INT_SET_TYPE] = 1, + [MSM8X16_WCD_A_ANALOG_INT_POLARITY_HIGH] = 1, + [MSM8X16_WCD_A_ANALOG_INT_POLARITY_LOW] = 1, + [MSM8X16_WCD_A_ANALOG_INT_LATCHED_STS] = 1, + [MSM8X16_WCD_A_ANALOG_INT_PENDING_STS] = 1, + [MSM8X16_WCD_A_ANALOG_MBHC_BTN_RESULT] = 1, + [MSM8X16_WCD_A_ANALOG_MBHC_ZDET_ELECT_RESULT] = 1, + [MSM8X16_WCD_A_ANALOG_RX_HPH_STATUS] = 1, + [MSM8X16_WCD_A_ANALOG_RX_EAR_STATUS] = 1, + [MSM8X16_WCD_A_ANALOG_SPKR_SAR_STATUS] = 1, + [MSM8X16_WCD_A_ANALOG_SPKR_DRV_STATUS] = 1, + [MSM8X16_WCD_A_CDC_RX1_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX2_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX3_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX1_B6_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX2_B6_CTL] = 1, + [MSM8X16_WCD_A_CDC_RX3_B6_CTL] = 1, + [MSM8X16_WCD_A_CDC_TX1_VOL_CTL_CFG] = 1, + [MSM8X16_WCD_A_CDC_TX2_VOL_CTL_CFG] = 1, + [MSM8X16_WCD_A_CDC_IIR1_COEF_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_IIR2_COEF_B1_CTL] = 1, + [MSM8X16_WCD_A_CDC_CLK_MCLK_CTL] = 1, + [MSM8X16_WCD_A_CDC_CLK_PDM_CTL] = 1, +}; + +u8 msm8x16_wcd_reset_reg_defaults[MSM8X16_WCD_NUM_REGISTERS] = { + [MSM8X16_WCD_A_DIGITAL_REVISION1] = + MSM8X16_WCD_A_DIGITAL_REVISION1__POR, + [MSM8X16_WCD_A_DIGITAL_REVISION2] = + MSM8X16_WCD_A_DIGITAL_REVISION2__POR, + [MSM8X16_WCD_A_DIGITAL_PERPH_TYPE] = + MSM8X16_WCD_A_DIGITAL_PERPH_TYPE__POR, + [MSM8X16_WCD_A_DIGITAL_PERPH_SUBTYPE] = + MSM8X16_WCD_A_DIGITAL_PERPH_SUBTYPE__POR, + [MSM8X16_WCD_A_DIGITAL_INT_RT_STS] = + MSM8X16_WCD_A_DIGITAL_INT_RT_STS__POR, + [MSM8X16_WCD_A_DIGITAL_INT_SET_TYPE] = + MSM8X16_WCD_A_DIGITAL_INT_SET_TYPE__POR, + [MSM8X16_WCD_A_DIGITAL_INT_POLARITY_HIGH] = + MSM8X16_WCD_A_DIGITAL_INT_POLARITY_HIGH__POR, + [MSM8X16_WCD_A_DIGITAL_INT_POLARITY_LOW] = + MSM8X16_WCD_A_DIGITAL_INT_POLARITY_LOW__POR, + [MSM8X16_WCD_A_DIGITAL_INT_LATCHED_CLR] = + MSM8X16_WCD_A_DIGITAL_INT_LATCHED_CLR__POR, + [MSM8X16_WCD_A_DIGITAL_INT_EN_SET] = + MSM8X16_WCD_A_DIGITAL_INT_EN_SET__POR, + [MSM8X16_WCD_A_DIGITAL_INT_EN_CLR] = + MSM8X16_WCD_A_DIGITAL_INT_EN_CLR__POR, + [MSM8X16_WCD_A_DIGITAL_INT_LATCHED_STS] = + MSM8X16_WCD_A_DIGITAL_INT_LATCHED_STS__POR, + [MSM8X16_WCD_A_DIGITAL_INT_PENDING_STS] = + MSM8X16_WCD_A_DIGITAL_INT_PENDING_STS__POR, + [MSM8X16_WCD_A_DIGITAL_INT_MID_SEL] = + MSM8X16_WCD_A_DIGITAL_INT_MID_SEL__POR, + [MSM8X16_WCD_A_DIGITAL_INT_PRIORITY] = + MSM8X16_WCD_A_DIGITAL_INT_PRIORITY__POR, + [MSM8X16_WCD_A_DIGITAL_GPIO_MODE] = + MSM8X16_WCD_A_DIGITAL_GPIO_MODE__POR, + [MSM8X16_WCD_A_DIGITAL_PIN_CTL_OE] = + MSM8X16_WCD_A_DIGITAL_PIN_CTL_OE__POR, + [MSM8X16_WCD_A_DIGITAL_PIN_CTL_DATA] = + MSM8X16_WCD_A_DIGITAL_PIN_CTL_DATA__POR, + [MSM8X16_WCD_A_DIGITAL_PIN_STATUS] = + MSM8X16_WCD_A_DIGITAL_PIN_STATUS__POR, + [MSM8X16_WCD_A_DIGITAL_HDRIVE_CTL] = + MSM8X16_WCD_A_DIGITAL_HDRIVE_CTL__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_RST_CTL] = + MSM8X16_WCD_A_DIGITAL_CDC_RST_CTL__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_TOP_CLK_CTL] = + MSM8X16_WCD_A_DIGITAL_CDC_TOP_CLK_CTL__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_ANA_CLK_CTL] = + MSM8X16_WCD_A_DIGITAL_CDC_ANA_CLK_CTL__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL] = + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX1_CTL] = + MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX1_CTL__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX2_CTL] = + MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX2_CTL__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_HPHR_DAC_CTL] = + MSM8X16_WCD_A_DIGITAL_CDC_CONN_HPHR_DAC_CTL__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX1_CTL] = + MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX1_CTL__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX2_CTL] = + MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX2_CTL__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX3_CTL] = + MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX3_CTL__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX_LB_CTL] = + MSM8X16_WCD_A_DIGITAL_CDC_CONN_RX_LB_CTL__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL1] = + MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL1__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL2] = + MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL2__POR, + [MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL3] = + MSM8X16_WCD_A_DIGITAL_CDC_RX_CTL3__POR, + [MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA0] = + MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA0__POR, + [MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA1] = + MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA1__POR, + [MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA2] = + MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA2__POR, + [MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA3] = + MSM8X16_WCD_A_DIGITAL_DEM_BYPASS_DATA3__POR, + [MSM8X16_WCD_A_DIGITAL_SPARE_0] = + MSM8X16_WCD_A_DIGITAL_SPARE_0__POR, + [MSM8X16_WCD_A_DIGITAL_SPARE_1] = + MSM8X16_WCD_A_DIGITAL_SPARE_1__POR, + [MSM8X16_WCD_A_DIGITAL_SPARE_2] = + MSM8X16_WCD_A_DIGITAL_SPARE_2__POR, + [MSM8X16_WCD_A_ANALOG_REVISION1] = + MSM8X16_WCD_A_ANALOG_REVISION1__POR, + [MSM8X16_WCD_A_ANALOG_REVISION2] = + MSM8X16_WCD_A_ANALOG_REVISION2__POR, + [MSM8X16_WCD_A_ANALOG_REVISION3] = + MSM8X16_WCD_A_ANALOG_REVISION3__POR, + [MSM8X16_WCD_A_ANALOG_REVISION4] = + MSM8X16_WCD_A_ANALOG_REVISION4__POR, + [MSM8X16_WCD_A_ANALOG_PERPH_TYPE] = + MSM8X16_WCD_A_ANALOG_PERPH_TYPE__POR, + [MSM8X16_WCD_A_ANALOG_PERPH_SUBTYPE] = + MSM8X16_WCD_A_ANALOG_PERPH_SUBTYPE__POR, + [MSM8X16_WCD_A_ANALOG_INT_RT_STS] = + MSM8X16_WCD_A_ANALOG_INT_RT_STS__POR, + [MSM8X16_WCD_A_ANALOG_INT_SET_TYPE] = + MSM8X16_WCD_A_ANALOG_INT_SET_TYPE__POR, + [MSM8X16_WCD_A_ANALOG_INT_POLARITY_HIGH] = + MSM8X16_WCD_A_ANALOG_INT_POLARITY_HIGH__POR, + [MSM8X16_WCD_A_ANALOG_INT_POLARITY_LOW] = + MSM8X16_WCD_A_ANALOG_INT_POLARITY_LOW__POR, + [MSM8X16_WCD_A_ANALOG_INT_LATCHED_CLR] = + MSM8X16_WCD_A_ANALOG_INT_LATCHED_CLR__POR, + [MSM8X16_WCD_A_ANALOG_INT_EN_SET] = + MSM8X16_WCD_A_ANALOG_INT_EN_SET__POR, + [MSM8X16_WCD_A_ANALOG_INT_EN_CLR] = + MSM8X16_WCD_A_ANALOG_INT_EN_CLR__POR, + [MSM8X16_WCD_A_ANALOG_INT_LATCHED_STS] = + MSM8X16_WCD_A_ANALOG_INT_LATCHED_STS__POR, + [MSM8X16_WCD_A_ANALOG_INT_PENDING_STS] = + MSM8X16_WCD_A_ANALOG_INT_PENDING_STS__POR, + [MSM8X16_WCD_A_ANALOG_INT_MID_SEL] = + MSM8X16_WCD_A_ANALOG_INT_MID_SEL__POR, + [MSM8X16_WCD_A_ANALOG_INT_PRIORITY] = + MSM8X16_WCD_A_ANALOG_INT_PRIORITY__POR, + [MSM8X16_WCD_A_ANALOG_MICB_1_EN] = + MSM8X16_WCD_A_ANALOG_MICB_1_EN__POR, + [MSM8X16_WCD_A_ANALOG_MICB_1_VAL] = + MSM8X16_WCD_A_ANALOG_MICB_1_VAL__POR, + [MSM8X16_WCD_A_ANALOG_MICB_1_CTL] = + MSM8X16_WCD_A_ANALOG_MICB_1_CTL__POR, + [MSM8X16_WCD_A_ANALOG_MICB_1_INT_RBIAS] = + MSM8X16_WCD_A_ANALOG_MICB_1_INT_RBIAS__POR, + [MSM8X16_WCD_A_ANALOG_MICB_2_EN] = + MSM8X16_WCD_A_ANALOG_MICB_2_EN__POR, + [MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_1] = + MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_1__POR, + [MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_2] = + MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_2__POR, + [MSM8X16_WCD_A_ANALOG_MBHC_FSM_CTL] = + MSM8X16_WCD_A_ANALOG_MBHC_FSM_CTL__POR, + [MSM8X16_WCD_A_ANALOG_MBHC_DBNC_TIMER] = + MSM8X16_WCD_A_ANALOG_MBHC_DBNC_TIMER__POR, + [MSM8X16_WCD_A_ANALOG_MBHC_BTN0_ZDETL_CTL] = + MSM8X16_WCD_A_ANALOG_MBHC_BTN0_ZDETL_CTL__POR, + [MSM8X16_WCD_A_ANALOG_MBHC_BTN1_ZDETM_CTL] = + MSM8X16_WCD_A_ANALOG_MBHC_BTN1_ZDETM_CTL__POR, + [MSM8X16_WCD_A_ANALOG_MBHC_BTN2_ZDETH_CTL] = + MSM8X16_WCD_A_ANALOG_MBHC_BTN2_ZDETH_CTL__POR, + [MSM8X16_WCD_A_ANALOG_MBHC_BTN3_CTL] = + MSM8X16_WCD_A_ANALOG_MBHC_BTN3_CTL__POR, + [MSM8X16_WCD_A_ANALOG_MBHC_BTN4_CTL] = + MSM8X16_WCD_A_ANALOG_MBHC_BTN4_CTL__POR, + [MSM8X16_WCD_A_ANALOG_MBHC_BTN_RESULT] = + MSM8X16_WCD_A_ANALOG_MBHC_BTN_RESULT__POR, + [MSM8X16_WCD_A_ANALOG_MBHC_ZDET_ELECT_RESULT] = + MSM8X16_WCD_A_ANALOG_MBHC_ZDET_ELECT_RESULT__POR, + [MSM8X16_WCD_A_ANALOG_TX_1_EN] = + MSM8X16_WCD_A_ANALOG_TX_1_EN__POR, + [MSM8X16_WCD_A_ANALOG_TX_2_EN] = + MSM8X16_WCD_A_ANALOG_TX_2_EN__POR, + [MSM8X16_WCD_A_ANALOG_TX_1_2_TEST_CTL_1] = + MSM8X16_WCD_A_ANALOG_TX_1_2_TEST_CTL_1__POR, + [MSM8X16_WCD_A_ANALOG_TX_1_2_TEST_CTL_2] = + MSM8X16_WCD_A_ANALOG_TX_1_2_TEST_CTL_2__POR, + [MSM8X16_WCD_A_ANALOG_TX_1_2_ATEST_CTL] = + MSM8X16_WCD_A_ANALOG_TX_1_2_ATEST_CTL__POR, + [MSM8X16_WCD_A_ANALOG_TX_1_2_OPAMP_BIAS] = + MSM8X16_WCD_A_ANALOG_TX_1_2_OPAMP_BIAS__POR, + [MSM8X16_WCD_A_ANALOG_TX_1_2_TXFE_CLKDIV] = + MSM8X16_WCD_A_ANALOG_TX_1_2_TXFE_CLKDIV__POR, + [MSM8X16_WCD_A_ANALOG_TX_3_EN] = + MSM8X16_WCD_A_ANALOG_TX_3_EN__POR, + [MSM8X16_WCD_A_ANALOG_NCP_EN] = + MSM8X16_WCD_A_ANALOG_NCP_EN__POR, + [MSM8X16_WCD_A_ANALOG_NCP_CLK] = + MSM8X16_WCD_A_ANALOG_NCP_CLK__POR, + [MSM8X16_WCD_A_ANALOG_NCP_DEGLITCH] = + MSM8X16_WCD_A_ANALOG_NCP_DEGLITCH__POR, + [MSM8X16_WCD_A_ANALOG_NCP_FBCTRL] = + MSM8X16_WCD_A_ANALOG_NCP_FBCTRL__POR, + [MSM8X16_WCD_A_ANALOG_NCP_BIAS] = + MSM8X16_WCD_A_ANALOG_NCP_BIAS__POR, + [MSM8X16_WCD_A_ANALOG_NCP_VCTRL] = + MSM8X16_WCD_A_ANALOG_NCP_VCTRL__POR, + [MSM8X16_WCD_A_ANALOG_NCP_TEST] = + MSM8X16_WCD_A_ANALOG_NCP_TEST__POR, + [MSM8X16_WCD_A_ANALOG_RX_CLOCK_DIVIDER] = + MSM8X16_WCD_A_ANALOG_RX_CLOCK_DIVIDER__POR, + [MSM8X16_WCD_A_ANALOG_RX_COM_OCP_CTL] = + MSM8X16_WCD_A_ANALOG_RX_COM_OCP_CTL__POR, + [MSM8X16_WCD_A_ANALOG_RX_COM_OCP_COUNT] = + MSM8X16_WCD_A_ANALOG_RX_COM_OCP_COUNT__POR, + [MSM8X16_WCD_A_ANALOG_RX_COM_BIAS_DAC] = + MSM8X16_WCD_A_ANALOG_RX_COM_BIAS_DAC__POR, + [MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_PA] = + MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_PA__POR, + [MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_LDO_OCP] = + MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_LDO_OCP__POR, + [MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_CNP] = + MSM8X16_WCD_A_ANALOG_RX_HPH_BIAS_CNP__POR, + [MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_EN] = + MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_EN__POR, + [MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_WG_CTL] = + MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_WG_CTL__POR, + [MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_WG_TIME] = + MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_WG_TIME__POR, + [MSM8X16_WCD_A_ANALOG_RX_HPH_L_TEST] = + MSM8X16_WCD_A_ANALOG_RX_HPH_L_TEST__POR, + [MSM8X16_WCD_A_ANALOG_RX_HPH_L_PA_DAC_CTL] = + MSM8X16_WCD_A_ANALOG_RX_HPH_L_PA_DAC_CTL__POR, + [MSM8X16_WCD_A_ANALOG_RX_HPH_R_TEST] = + MSM8X16_WCD_A_ANALOG_RX_HPH_R_TEST__POR, + [MSM8X16_WCD_A_ANALOG_RX_HPH_R_PA_DAC_CTL] = + MSM8X16_WCD_A_ANALOG_RX_HPH_R_PA_DAC_CTL__POR, + [MSM8X16_WCD_A_ANALOG_RX_EAR_CTL] = + MSM8X16_WCD_A_ANALOG_RX_EAR_CTL___POR, + [MSM8X16_WCD_A_ANALOG_RX_ATEST] = + MSM8X16_WCD_A_ANALOG_RX_ATEST__POR, + [MSM8X16_WCD_A_ANALOG_RX_HPH_STATUS] = + MSM8X16_WCD_A_ANALOG_RX_HPH_STATUS__POR, + [MSM8X16_WCD_A_ANALOG_RX_EAR_STATUS] = + MSM8X16_WCD_A_ANALOG_RX_EAR_STATUS__POR, + [MSM8X16_WCD_A_ANALOG_SPKR_DAC_CTL] = + MSM8X16_WCD_A_ANALOG_SPKR_DAC_CTL__POR, + [MSM8X16_WCD_A_ANALOG_SPKR_DRV_CLIP_DET] = + MSM8X16_WCD_A_ANALOG_SPKR_DRV_CLIP_DET__POR, + [MSM8X16_WCD_A_ANALOG_SPKR_DRV_CTL] = + MSM8X16_WCD_A_ANALOG_SPKR_DRV_CTL__POR, + [MSM8X16_WCD_A_ANALOG_SPKR_ANA_BIAS_SET] = + MSM8X16_WCD_A_ANALOG_SPKR_ANA_BIAS_SET__POR, + [MSM8X16_WCD_A_ANALOG_SPKR_OCP_CTL] = + MSM8X16_WCD_A_ANALOG_SPKR_OCP_CTL__POR, + [MSM8X16_WCD_A_ANALOG_SPKR_PWRSTG_CTL] = + MSM8X16_WCD_A_ANALOG_SPKR_PWRSTG_CTL__POR, + [MSM8X16_WCD_A_ANALOG_SPKR_DRV_MISC] = + MSM8X16_WCD_A_ANALOG_SPKR_DRV_MISC__POR, + [MSM8X16_WCD_A_ANALOG_SPKR_DRV_DBG] = + MSM8X16_WCD_A_ANALOG_SPKR_DRV_DBG__POR, + [MSM8X16_WCD_A_ANALOG_CURRENT_LIMIT] = + MSM8X16_WCD_A_ANALOG_CURRENT_LIMIT__POR, + [MSM8X16_WCD_A_ANALOG_OUTPUT_VOLTAGE] = + MSM8X16_WCD_A_ANALOG_OUTPUT_VOLTAGE__POR, + [MSM8X16_WCD_A_ANALOG_BYPASS_MODE] = + MSM8X16_WCD_A_ANALOG_BYPASS_MODE__POR, + [MSM8X16_WCD_A_ANALOG_BOOST_EN_CTL] = + MSM8X16_WCD_A_ANALOG_BOOST_EN_CTL__POR, + [MSM8X16_WCD_A_ANALOG_SLOPE_COMP_IP_ZERO] = + MSM8X16_WCD_A_ANALOG_SLOPE_COMP_IP_ZERO__POR, + [MSM8X16_WCD_A_ANALOG_RDSON_MAX_DUTY_CYCLE] = + MSM8X16_WCD_A_ANALOG_RDSON_MAX_DUTY_CYCLE__POR, + [MSM8X16_WCD_A_ANALOG_BOOST_TEST1_1] = + MSM8X16_WCD_A_ANALOG_BOOST_TEST1_1__POR, + [MSM8X16_WCD_A_ANALOG_BOOST_TEST_2] = + MSM8X16_WCD_A_ANALOG_BOOST_TEST_2__POR, + [MSM8X16_WCD_A_ANALOG_SPKR_SAR_STATUS] = + MSM8X16_WCD_A_ANALOG_SPKR_SAR_STATUS__POR, + [MSM8X16_WCD_A_ANALOG_SPKR_DRV_STATUS] = + MSM8X16_WCD_A_ANALOG_SPKR_DRV_STATUS__POR, + [MSM8X16_WCD_A_ANALOG_PBUS_ADD_CSR] = + MSM8X16_WCD_A_ANALOG_PBUS_ADD_CSR__POR, + [MSM8X16_WCD_A_ANALOG_PBUS_ADD_SEL] = + MSM8X16_WCD_A_ANALOG_PBUS_ADD_SEL__POR, + [MSM8X16_WCD_A_CDC_CLK_RX_RESET_CTL] = + MSM8X16_WCD_A_CDC_CLK_RX_RESET_CTL__POR, + [MSM8X16_WCD_A_CDC_CLK_TX_RESET_B1_CTL] = + MSM8X16_WCD_A_CDC_CLK_TX_RESET_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_CLK_DMIC_B1_CTL] = + MSM8X16_WCD_A_CDC_CLK_DMIC_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_CLK_RX_I2S_CTL] = + MSM8X16_WCD_A_CDC_CLK_RX_I2S_CTL__POR, + [MSM8X16_WCD_A_CDC_CLK_TX_I2S_CTL] = + MSM8X16_WCD_A_CDC_CLK_TX_I2S_CTL__POR, + [MSM8X16_WCD_A_CDC_CLK_OTHR_RESET_B1_CTL] = + MSM8X16_WCD_A_CDC_CLK_OTHR_RESET_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL] = + MSM8X16_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_CLK_OTHR_CTL] = + MSM8X16_WCD_A_CDC_CLK_OTHR_CTL__POR, + [MSM8X16_WCD_A_CDC_CLK_RX_B1_CTL] = + MSM8X16_WCD_A_CDC_CLK_RX_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_CLK_MCLK_CTL] = + MSM8X16_WCD_A_CDC_CLK_MCLK_CTL__POR, + [MSM8X16_WCD_A_CDC_CLK_PDM_CTL] = + MSM8X16_WCD_A_CDC_CLK_PDM_CTL__POR, + [MSM8X16_WCD_A_CDC_CLK_SD_CTL] = + MSM8X16_WCD_A_CDC_CLK_SD_CTL__POR, + [MSM8X16_WCD_A_CDC_RX1_B1_CTL] = + MSM8X16_WCD_A_CDC_RX1_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_RX2_B1_CTL] = + MSM8X16_WCD_A_CDC_RX2_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_RX3_B1_CTL] = + MSM8X16_WCD_A_CDC_RX3_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_RX1_B2_CTL] = + MSM8X16_WCD_A_CDC_RX1_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_RX2_B2_CTL] = + MSM8X16_WCD_A_CDC_RX2_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_RX3_B2_CTL] = + MSM8X16_WCD_A_CDC_RX3_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_RX1_B3_CTL] = + MSM8X16_WCD_A_CDC_RX1_B3_CTL__POR, + [MSM8X16_WCD_A_CDC_RX2_B3_CTL] = + MSM8X16_WCD_A_CDC_RX2_B3_CTL__POR, + [MSM8X16_WCD_A_CDC_RX3_B3_CTL] = + MSM8X16_WCD_A_CDC_RX3_B3_CTL__POR, + [MSM8X16_WCD_A_CDC_RX1_B4_CTL] = + MSM8X16_WCD_A_CDC_RX1_B4_CTL__POR, + [MSM8X16_WCD_A_CDC_RX2_B4_CTL] = + MSM8X16_WCD_A_CDC_RX2_B4_CTL__POR, + [MSM8X16_WCD_A_CDC_RX3_B4_CTL] = + MSM8X16_WCD_A_CDC_RX3_B4_CTL__POR, + [MSM8X16_WCD_A_CDC_RX1_B5_CTL] = + MSM8X16_WCD_A_CDC_RX1_B5_CTL__POR, + [MSM8X16_WCD_A_CDC_RX2_B5_CTL] = + MSM8X16_WCD_A_CDC_RX2_B5_CTL__POR, + [MSM8X16_WCD_A_CDC_RX3_B5_CTL] = + MSM8X16_WCD_A_CDC_RX3_B5_CTL__POR, + [MSM8X16_WCD_A_CDC_RX1_B6_CTL] = + MSM8X16_WCD_A_CDC_RX1_B6_CTL__POR, + [MSM8X16_WCD_A_CDC_RX2_B6_CTL] = + MSM8X16_WCD_A_CDC_RX2_B6_CTL__POR, + [MSM8X16_WCD_A_CDC_RX3_B6_CTL] = + MSM8X16_WCD_A_CDC_RX3_B6_CTL__POR, + [MSM8X16_WCD_A_CDC_RX1_VOL_CTL_B1_CTL] = + MSM8X16_WCD_A_CDC_RX1_VOL_CTL_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_RX2_VOL_CTL_B1_CTL] = + MSM8X16_WCD_A_CDC_RX2_VOL_CTL_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_RX3_VOL_CTL_B1_CTL] = + MSM8X16_WCD_A_CDC_RX3_VOL_CTL_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_RX1_VOL_CTL_B2_CTL] = + MSM8X16_WCD_A_CDC_RX1_VOL_CTL_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_RX2_VOL_CTL_B2_CTL] = + MSM8X16_WCD_A_CDC_RX2_VOL_CTL_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_RX3_VOL_CTL_B2_CTL] = + MSM8X16_WCD_A_CDC_RX3_VOL_CTL_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_TOP_GAIN_UPDATE] = + MSM8X16_WCD_A_CDC_TOP_GAIN_UPDATE__POR, + [MSM8X16_WCD_A_CDC_TOP_CTL] = + MSM8X16_WCD_A_CDC_TOP_CTL__POR, + [MSM8X16_WCD_A_CDC_DEBUG_DESER1_CTL] = + MSM8X16_WCD_A_CDC_DEBUG_DESER1_CTL__POR, + [MSM8X16_WCD_A_CDC_DEBUG_DESER2_CTL] = + MSM8X16_WCD_A_CDC_DEBUG_DESER2_CTL__POR, + [MSM8X16_WCD_A_CDC_DEBUG_B1_CTL_CFG] = + MSM8X16_WCD_A_CDC_DEBUG_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_DEBUG_B2_CTL_CFG] = + MSM8X16_WCD_A_CDC_DEBUG_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_DEBUG_B3_CTL_CFG] = + MSM8X16_WCD_A_CDC_DEBUG_B3_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B1_CTL] = + MSM8X16_WCD_A_CDC_IIR1_GAIN_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B1_CTL] = + MSM8X16_WCD_A_CDC_IIR2_GAIN_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B2_CTL] = + MSM8X16_WCD_A_CDC_IIR1_GAIN_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B2_CTL] = + MSM8X16_WCD_A_CDC_IIR2_GAIN_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B3_CTL] = + MSM8X16_WCD_A_CDC_IIR1_GAIN_B3_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B3_CTL] = + MSM8X16_WCD_A_CDC_IIR2_GAIN_B3_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B4_CTL] = + MSM8X16_WCD_A_CDC_IIR1_GAIN_B4_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B4_CTL] = + MSM8X16_WCD_A_CDC_IIR2_GAIN_B4_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B5_CTL] = + MSM8X16_WCD_A_CDC_IIR1_GAIN_B5_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B5_CTL] = + MSM8X16_WCD_A_CDC_IIR2_GAIN_B5_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B6_CTL] = + MSM8X16_WCD_A_CDC_IIR1_GAIN_B6_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B6_CTL] = + MSM8X16_WCD_A_CDC_IIR2_GAIN_B6_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B7_CTL] = + MSM8X16_WCD_A_CDC_IIR1_GAIN_B7_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B7_CTL] = + MSM8X16_WCD_A_CDC_IIR2_GAIN_B7_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_B8_CTL] = + MSM8X16_WCD_A_CDC_IIR1_GAIN_B8_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_B8_CTL] = + MSM8X16_WCD_A_CDC_IIR2_GAIN_B8_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR1_CTL] = + MSM8X16_WCD_A_CDC_IIR1_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR2_CTL] = + MSM8X16_WCD_A_CDC_IIR2_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR1_GAIN_TIMER_CTL] = + MSM8X16_WCD_A_CDC_IIR1_GAIN_TIMER_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR2_GAIN_TIMER_CTL] = + MSM8X16_WCD_A_CDC_IIR2_GAIN_TIMER_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR1_COEF_B1_CTL] = + MSM8X16_WCD_A_CDC_IIR1_COEF_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR2_COEF_B1_CTL] = + MSM8X16_WCD_A_CDC_IIR2_COEF_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR1_COEF_B2_CTL] = + MSM8X16_WCD_A_CDC_IIR1_COEF_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_IIR2_COEF_B2_CTL] = + MSM8X16_WCD_A_CDC_IIR2_COEF_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_RX1_B1_CTL] = + MSM8X16_WCD_A_CDC_CONN_RX1_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_RX1_B2_CTL] = + MSM8X16_WCD_A_CDC_CONN_RX1_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_RX1_B3_CTL] = + MSM8X16_WCD_A_CDC_CONN_RX1_B3_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_RX2_B1_CTL] = + MSM8X16_WCD_A_CDC_CONN_RX2_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_RX2_B2_CTL] = + MSM8X16_WCD_A_CDC_CONN_RX2_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_RX2_B3_CTL] = + MSM8X16_WCD_A_CDC_CONN_RX2_B3_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_RX3_B1_CTL] = + MSM8X16_WCD_A_CDC_CONN_RX3_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_RX3_B2_CTL] = + MSM8X16_WCD_A_CDC_CONN_RX3_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_TX_B1_CTL] = + MSM8X16_WCD_A_CDC_CONN_TX_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_EQ1_B1_CTL] = + MSM8X16_WCD_A_CDC_CONN_EQ1_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_EQ1_B2_CTL] = + MSM8X16_WCD_A_CDC_CONN_EQ1_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_EQ1_B3_CTL] = + MSM8X16_WCD_A_CDC_CONN_EQ1_B3_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_EQ1_B4_CTL] = + MSM8X16_WCD_A_CDC_CONN_EQ1_B4_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_EQ2_B1_CTL] = + MSM8X16_WCD_A_CDC_CONN_EQ2_B1_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_EQ2_B2_CTL] = + MSM8X16_WCD_A_CDC_CONN_EQ2_B2_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_EQ2_B3_CTL] = + MSM8X16_WCD_A_CDC_CONN_EQ2_B3_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_EQ2_B4_CTL] = + MSM8X16_WCD_A_CDC_CONN_EQ2_B4_CTL__POR, + [MSM8X16_WCD_A_CDC_CONN_TX_I2S_SD1_CTL] = + MSM8X16_WCD_A_CDC_CONN_TX_I2S_SD1_CTL__POR, + [MSM8X16_WCD_A_CDC_TX1_VOL_CTL_TIMER] = + MSM8X16_WCD_A_CDC_TX1_VOL_CTL_TIMER__POR, + [MSM8X16_WCD_A_CDC_TX2_VOL_CTL_TIMER] = + MSM8X16_WCD_A_CDC_TX2_VOL_CTL_TIMER__POR, + [MSM8X16_WCD_A_CDC_TX1_VOL_CTL_GAIN] = + MSM8X16_WCD_A_CDC_TX1_VOL_CTL_GAIN__POR, + [MSM8X16_WCD_A_CDC_TX2_VOL_CTL_GAIN] = + MSM8X16_WCD_A_CDC_TX2_VOL_CTL_GAIN__POR, + [MSM8X16_WCD_A_CDC_TX1_VOL_CTL_CFG] = + MSM8X16_WCD_A_CDC_TX1_VOL_CTL_CFG__POR, + [MSM8X16_WCD_A_CDC_TX2_VOL_CTL_CFG] = + MSM8X16_WCD_A_CDC_TX2_VOL_CTL_CFG__POR, + [MSM8X16_WCD_A_CDC_TX1_MUX_CTL] = + MSM8X16_WCD_A_CDC_TX1_MUX_CTL__POR, + [MSM8X16_WCD_A_CDC_TX2_MUX_CTL] = + MSM8X16_WCD_A_CDC_TX2_MUX_CTL__POR, + [MSM8X16_WCD_A_CDC_TX1_CLK_FS_CTL] = + MSM8X16_WCD_A_CDC_TX1_CLK_FS_CTL__POR, + [MSM8X16_WCD_A_CDC_TX2_CLK_FS_CTL] = + MSM8X16_WCD_A_CDC_TX2_CLK_FS_CTL__POR, + [MSM8X16_WCD_A_CDC_TX1_DMIC_CTL] = + MSM8X16_WCD_A_CDC_TX1_DMIC_CTL__POR, + [MSM8X16_WCD_A_CDC_TX2_DMIC_CTL] = + MSM8X16_WCD_A_CDC_TX2_DMIC_CTL__POR, +}; + +#endif /* MSM8X16_WCD_H */
On Tue, Feb 16, 2016 at 05:32:56PM +0000, Srinivas Kandagatla wrote:
This patch add register ranges for readonly, default and reset register values.
This split of the patches is really not helping at all. The patches cross reference each other which makes things harder to follow and it's not like things can be treated independently or there are detaile changelogs explaining everything separately.
+static int __msm8x16_wcd_reg_write(struct snd_soc_codec *codec,
unsigned short reg, u8 val)
+{
- int ret = -EINVAL;
- struct msm8x16_wcd_chip *chip = dev_get_drvdata(codec->dev);
- if (MSM8X16_WCD_IS_TOMBAK_REG(reg)) {
ret = regmap_write(chip->analog_map,
chip->analog_base + reg, val);
- } else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) {
u32 temp = val & 0x000000FF;
u16 offset = (reg ^ 0x0200) & 0x0FFF;
ret = regmap_write(chip->digital_map, offset, temp);
- }
- return ret;
+}
I don't really know what this is supposed to be doing but it looks like something is wrong. It seems that it's trying to munge two different register maps together in some undocumented reason.
+static int msm8x16_wcd_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
+{
- if (reg == SND_SOC_NOPM)
return 0;
- WARN_ON(reg > MSM8X16_WCD_MAX_REGISTER);
- if (!msm8x16_wcd_volatile(codec, reg))
msm8x16_wcd_reset_reg_defaults[reg] = value;
This appears to be obviously confused. We're writing to a global variable as part of the write routine, and worse that global variable is called _reg_defaults which suggests that it's supposed to be the register default values not what appears to be a cache implemented outside of the existing generic cache code.
- return __msm8x16_wcd_reg_write(codec, reg, (u8)value);
+}
It's also not clear why this is a separate wrapper function.
This patch adds codec hardware intialization code.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/codecs/msm8x16-wcd.c | 180 +++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/msm8x16-wcd.h | 11 +++ 2 files changed, 191 insertions(+)
diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c index 3598e48..bc8b38a 100644 --- a/sound/soc/codecs/msm8x16-wcd.c +++ b/sound/soc/codecs/msm8x16-wcd.c @@ -2,6 +2,7 @@ #include <linux/module.h> #include <linux/err.h> #include <linux/kernel.h> +#include <linux/delay.h> #include <linux/regulator/consumer.h> #include <linux/types.h> #include <linux/clk.h> @@ -14,6 +15,10 @@ #include "msm8x16-wcd-registers.h" #include "msm8x16-wcd.h"
+/* Cap mode for micbias */ +#define MICBIAS_EXT_BYP_CAP 0x00 +#define MICBIAS_NO_EXT_BYP_CAP 0x01 + struct msm8x16_wcd_chip { struct regmap *analog_map; struct regmap *digital_map; @@ -124,6 +129,33 @@ static unsigned int msm8x16_wcd_read(struct snd_soc_codec *codec, return val; }
+static void msm8x16_wcd_configure_cap(struct snd_soc_codec *codec, + bool micbias1, bool micbias2) +{ + struct msm8x16_wcd_chip *wcd = snd_soc_codec_get_drvdata(codec); + + if (micbias1 && micbias2) { + if ((wcd->micbias1_cap_mode == MICBIAS_EXT_BYP_CAP) || + (wcd->micbias2_cap_mode == MICBIAS_EXT_BYP_CAP)) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_MICB_1_EN, + 0x40, (MICBIAS_EXT_BYP_CAP << 6)); + else + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_MICB_1_EN, + 0x40, (MICBIAS_NO_EXT_BYP_CAP << 6)); + } else if (micbias2) { + snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_MICB_1_EN, + 0x40, (wcd->micbias2_cap_mode << 6)); + } else if (micbias1) { + snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_MICB_1_EN, + 0x40, (wcd->micbias1_cap_mode << 6)); + } else { + snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_MICB_1_EN, + 0x40, 0x00); + } +} + static int msm8x16_wcd_codec_parse_dt(struct platform_device *pdev, struct msm8x16_wcd_chip *chip) { @@ -181,11 +213,159 @@ static int msm8x16_wcd_codec_parse_dt(struct platform_device *pdev,
return 0; } +#define VDDIO_VOL_MIN 1800000 /* uV */ +#define VDDIO_VOL_MAX 1800000 /* uV */ + +static int msm8x16_wcd_codec_enable_clock_block(struct snd_soc_codec *codec, + int enable) +{ + struct msm8x16_wcd_chip *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + unsigned long mclk_rate; + + if (enable) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_CLK_MCLK_CTL, 0x01, 0x01); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_CLK_PDM_CTL, 0x03, 0x03); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_MASTER_BIAS_CTL, 0x30, 0x30); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_RST_CTL, 0x80, 0x80); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_TOP_CLK_CTL, 0x0C, 0x0C); + + mclk_rate = clk_get_rate(msm8x16_wcd->mclk); + + if (mclk_rate == 12288000) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_TOP_CTL, 0x01, 0x00); + else if (mclk_rate == 9600000) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_TOP_CTL, 0x01, 0x01); + } else { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_TOP_CLK_CTL, 0x0C, 0x00); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_CLK_PDM_CTL, 0x03, 0x00); + + } + return 0; +} + +static const struct msm8x16_wcd_reg_mask_val wcd_reg_defaults[] = { + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_ANALOG_SPKR_DAC_CTL, 0x03), + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_ANALOG_CURRENT_LIMIT, 0x82), + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_ANALOG_SPKR_OCP_CTL, 0xE1), +}; + +static const struct msm8x16_wcd_reg_mask_val wcd_reg_defaults_2_0[] = { + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_DIGITAL_PERPH_RESET_CTL3, 0x0F), + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_ANALOG_TX_1_2_OPAMP_BIAS, 0x4B), + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_ANALOG_NCP_FBCTRL, 0x28), + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_ANALOG_SPKR_DRV_CTL, 0x69), + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_ANALOG_SPKR_DRV_DBG, 0x01), + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_ANALOG_BOOST_EN_CTL, 0x5F), + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_ANALOG_SLOPE_COMP_IP_ZERO, 0x88), + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_ANALOG_PERPH_RESET_CTL3, 0x0F), + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_ANALOG_CURRENT_LIMIT, 0x82), + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_ANALOG_SPKR_DAC_CTL, 0x03), + MSM8X16_WCD_REG_VAL(MSM8X16_WCD_A_ANALOG_SPKR_OCP_CTL, 0xE1), +}; + +static const struct msm8x16_wcd_reg_mask_val + msm8x16_wcd_codec_reg_init_val[] = { + + /* Initialize current threshold to 350MA + * number of wait and run cycles to 4096 + */ + {MSM8X16_WCD_A_ANALOG_RX_COM_OCP_CTL, 0xFF, 0xD1}, + {MSM8X16_WCD_A_ANALOG_RX_COM_OCP_COUNT, 0xFF, 0xFF}, +}; + +static int msm8x16_wcd_device_up(struct snd_soc_codec *codec) +{ + struct msm8x16_wcd_chip *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + u32 reg; + + snd_soc_write(codec, MSM8X16_WCD_A_DIGITAL_PERPH_RESET_CTL4, 0x01); + snd_soc_write(codec, MSM8X16_WCD_A_ANALOG_PERPH_RESET_CTL4, 0x01); + + for (reg = 0; reg < ARRAY_SIZE(msm8x16_wcd_reset_reg_defaults); reg++) + if (msm8x16_wcd_reg_readable[reg]) + msm8x16_wcd_write(codec, + reg, msm8x16_wcd_reset_reg_defaults[reg]); + + /* delay is required to make sure sound card state updated */ + usleep_range(5000, 5100); + + for (reg = 0; reg < ARRAY_SIZE(msm8x16_wcd_codec_reg_init_val); reg++) + snd_soc_update_bits(codec, + msm8x16_wcd_codec_reg_init_val[reg].reg, + msm8x16_wcd_codec_reg_init_val[reg].mask, + msm8x16_wcd_codec_reg_init_val[reg].val); + + if (TOMBAK_IS_1_0(msm8x16_wcd->pmic_rev)) { + for (reg = 0; reg < ARRAY_SIZE(wcd_reg_defaults); reg++) + snd_soc_write(codec, wcd_reg_defaults[reg].reg, + wcd_reg_defaults[reg].val); + } else { + for (reg = 0; reg < ARRAY_SIZE(wcd_reg_defaults_2_0); reg++) + snd_soc_write(codec, wcd_reg_defaults_2_0[reg].reg, + wcd_reg_defaults_2_0[reg].val); + } + + msm8x16_wcd_codec_enable_clock_block(codec, 1); + + return 0; +} + +static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec) +{ + struct msm8x16_wcd_chip *chip = dev_get_drvdata(codec->dev); + int err; + + regulator_set_voltage(chip->vddio, VDDIO_VOL_MIN, VDDIO_VOL_MAX); + err = regulator_enable(chip->vddio); + if (err < 0) { + dev_err(codec->dev, "failed to enable VDDIO regulator\n"); + return err; + } + + err = regulator_enable(chip->vdd_tx_rx); + if (err < 0) { + dev_err(codec->dev, "failed to enable VDD_TX_RX regulator\n"); + return err; + } + + snd_soc_codec_set_drvdata(codec, chip); + + chip->pmic_rev = snd_soc_read(codec, MSM8X16_WCD_A_DIGITAL_REVISION1); + dev_info(codec->dev, "%s :PMIC REV: %d", __func__, chip->pmic_rev); + + chip->codec_version = snd_soc_read(codec, + MSM8X16_WCD_A_DIGITAL_PERPH_SUBTYPE); + dev_info(codec->dev, "%s :CODEC Version: %d", __func__, + chip->codec_version); + + msm8x16_wcd_device_up(codec); + + /* Set initial cap mode */ + msm8x16_wcd_configure_cap(codec, false, false); + + return 0; +} + +static int msm8x16_wcd_codec_remove(struct snd_soc_codec *codec) +{ + return 0; +};
static struct snd_soc_dai_driver msm8x16_wcd_codec_dai[] = { };
static struct snd_soc_codec_driver msm8x16_wcd_codec = { + .probe = msm8x16_wcd_codec_probe, + .remove = msm8x16_wcd_codec_remove, .read = msm8x16_wcd_read, .write = msm8x16_wcd_write, .reg_cache_size = MSM8X16_WCD_NUM_REGISTERS, diff --git a/sound/soc/codecs/msm8x16-wcd.h b/sound/soc/codecs/msm8x16-wcd.h index db82f58..bfb6c88 100644 --- a/sound/soc/codecs/msm8x16-wcd.h +++ b/sound/soc/codecs/msm8x16-wcd.h @@ -16,12 +16,23 @@
#define MSM8X16_WCD_NUM_REGISTERS 0x6FF #define MSM8X16_WCD_MAX_REGISTER (MSM8X16_WCD_NUM_REGISTERS-1) +#define MSM8X16_WCD_REG_VAL(reg, val) {reg, 0, val}
#define MSM8X16_WCD_IS_DIGITAL_REG(reg) \ (((reg >= 0x200) && (reg <= 0x4FF)) ? 1 : 0) #define MSM8X16_WCD_IS_TOMBAK_REG(reg) \ (((reg >= 0x000) && (reg <= 0x1FF)) ? 1 : 0)
+#define TOMBAK_VERSION_1_0 0 +#define TOMBAK_IS_1_0(ver) \ + ((ver == TOMBAK_VERSION_1_0) ? 1 : 0) + +struct msm8x16_wcd_reg_mask_val { + u16 reg; + u8 mask; + u8 val; +}; + const u8 msm8x16_wcd_reg_readable[MSM8X16_WCD_NUM_REGISTERS] = { [MSM8X16_WCD_A_DIGITAL_REVISION1] = 1, [MSM8X16_WCD_A_DIGITAL_REVISION2] = 1,
On Tue, Feb 16, 2016 at 05:33:03PM +0000, Srinivas Kandagatla wrote:
- if (micbias1 && micbias2) {
if ((wcd->micbias1_cap_mode == MICBIAS_EXT_BYP_CAP) ||
(wcd->micbias2_cap_mode == MICBIAS_EXT_BYP_CAP))
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MICB_1_EN,
0x40, (MICBIAS_EXT_BYP_CAP << 6));
else
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MICB_1_EN,
0x40, (MICBIAS_NO_EXT_BYP_CAP << 6));
This is a bit of an exciting combination of magic numbers and #defines.
+#define VDDIO_VOL_MIN 1800000 /* uV */ +#define VDDIO_VOL_MAX 1800000 /* uV */
mclk_rate = clk_get_rate(msm8x16_wcd->mclk);
if (mclk_rate == 12288000)
snd_soc_update_bits(codec,
MSM8X16_WCD_A_CDC_TOP_CTL, 0x01, 0x00);
else if (mclk_rate == 9600000)
snd_soc_update_bits(codec,
MSM8X16_WCD_A_CDC_TOP_CTL, 0x01, 0x01);
This looks like it should be a switch statement.
+static const struct msm8x16_wcd_reg_mask_val
- msm8x16_wcd_codec_reg_init_val[] = {
We use these tables...
- snd_soc_write(codec, MSM8X16_WCD_A_DIGITAL_PERPH_RESET_CTL4, 0x01);
- snd_soc_write(codec, MSM8X16_WCD_A_ANALOG_PERPH_RESET_CTL4, 0x01);
- for (reg = 0; reg < ARRAY_SIZE(msm8x16_wcd_reset_reg_defaults); reg++)
if (msm8x16_wcd_reg_readable[reg])
msm8x16_wcd_write(codec,
reg, msm8x16_wcd_reset_reg_defaults[reg]);
...and also sequences of explicit register writes somewhat at random as far as I can see. What is going on?
- /* delay is required to make sure sound card state updated */
- usleep_range(5000, 5100);
- for (reg = 0; reg < ARRAY_SIZE(msm8x16_wcd_codec_reg_init_val); reg++)
snd_soc_update_bits(codec,
msm8x16_wcd_codec_reg_init_val[reg].reg,
msm8x16_wcd_codec_reg_init_val[reg].mask,
msm8x16_wcd_codec_reg_init_val[reg].val);
It looks like you need delays in the table. Perhaps using the regmap sequence code might be a better fit?
- msm8x16_wcd_codec_enable_clock_block(codec, 1);
Separate enable and disable functions if you are going to do this though with one caller each it's not clear why this is a separate function.
+static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec) +{
- struct msm8x16_wcd_chip *chip = dev_get_drvdata(codec->dev);
- int err;
- regulator_set_voltage(chip->vddio, VDDIO_VOL_MIN, VDDIO_VOL_MAX);
Why are we doing a _set_voltage() here? We never vary the voltage, we support only one value and apparently we don't even care if it worked.
- err = regulator_enable(chip->vddio);
- if (err < 0) {
dev_err(codec->dev, "failed to enable VDDIO regulator\n");
return err;
- }
- err = regulator_enable(chip->vdd_tx_rx);
- if (err < 0) {
dev_err(codec->dev, "failed to enable VDD_TX_RX regulator\n");
return err;
- }
These two look like they should be handled with bulk operations (the bit getting the regulators is in a completely different patch...). There's also no disable code.
- chip->pmic_rev = snd_soc_read(codec, MSM8X16_WCD_A_DIGITAL_REVISION1);
- dev_info(codec->dev, "%s :PMIC REV: %d", __func__, chip->pmic_rev);
Please format the log messages so the look like normal kernel output.
This patch adds two codec DAI's one Playback and other capture on the i2s bus.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- include/dt-bindings/sound/msm8x16-wcd.h | 7 ++ sound/soc/codecs/msm8x16-wcd.c | 180 ++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 include/dt-bindings/sound/msm8x16-wcd.h
diff --git a/include/dt-bindings/sound/msm8x16-wcd.h b/include/dt-bindings/sound/msm8x16-wcd.h new file mode 100644 index 0000000..f3257ab --- /dev/null +++ b/include/dt-bindings/sound/msm8x16-wcd.h @@ -0,0 +1,7 @@ +#ifndef __DT_MSM8x16_WCD_H +#define __DT_MSM8x16_WCD_H + +#define MSM8x16_WCD_PLAYBACK_DAI 0 +#define MSM8x16_WCD_CAPTURE_DAI 1 + +#endif /* __DT_MSM8x16_WCD_H */ diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c index bc8b38a..4bc8274 100644 --- a/sound/soc/codecs/msm8x16-wcd.c +++ b/sound/soc/codecs/msm8x16-wcd.c @@ -11,9 +11,17 @@ #include <linux/regmap.h> #include <linux/mfd/syscon.h> #include <sound/soc.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h>
#include "msm8x16-wcd-registers.h" #include "msm8x16-wcd.h" +#include "dt-bindings/sound/msm8x16-wcd.h" + +#define MSM8X16_WCD_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000) +#define MSM8X16_WCD_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE)
/* Cap mode for micbias */ #define MICBIAS_EXT_BYP_CAP 0x00 @@ -282,6 +290,19 @@ static const struct msm8x16_wcd_reg_mask_val {MSM8X16_WCD_A_ANALOG_RX_COM_OCP_COUNT, 0xFF, 0xFF}, };
+static int msm8x16_wcd_set_interpolator_rate(struct snd_soc_dai *dai, + u8 rx_fs_rate_reg_val, u32 sample_rate) +{ + return 0; +} + +static int msm8x16_wcd_set_decimator_rate(struct snd_soc_dai *dai, + u8 tx_fs_rate_reg_val, u32 sample_rate) +{ + + return 0; +} + static int msm8x16_wcd_device_up(struct snd_soc_codec *codec) { struct msm8x16_wcd_chip *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); @@ -360,7 +381,166 @@ static int msm8x16_wcd_codec_remove(struct snd_soc_codec *codec) return 0; };
+static int msm8x16_wcd_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return 0; +} + +static void msm8x16_wcd_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ +} + +static int msm8x16_wcd_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + u8 tx_fs_rate, rx_fs_rate; + int ret; + + switch (params_rate(params)) { + case 8000: + tx_fs_rate = 0x00; + rx_fs_rate = 0x00; + break; + case 16000: + tx_fs_rate = 0x01; + rx_fs_rate = 0x20; + break; + case 32000: + tx_fs_rate = 0x02; + rx_fs_rate = 0x40; + break; + case 48000: + tx_fs_rate = 0x03; + rx_fs_rate = 0x60; + break; + case 96000: + tx_fs_rate = 0x04; + rx_fs_rate = 0x80; + break; + case 192000: + tx_fs_rate = 0x05; + rx_fs_rate = 0xA0; + break; + default: + dev_err(dai->codec->dev, + "%s: Invalid sampling rate %d\n", __func__, + params_rate(params)); + return -EINVAL; + } + + switch (substream->stream) { + case SNDRV_PCM_STREAM_CAPTURE: + snd_soc_update_bits(dai->codec, + MSM8X16_WCD_A_CDC_CLK_TX_I2S_CTL, + 0x07, tx_fs_rate); + ret = msm8x16_wcd_set_decimator_rate(dai, tx_fs_rate, + params_rate(params)); + if (ret < 0) { + dev_err(dai->codec->dev, + "%s: set decimator rate failed %d\n", __func__, + ret); + return ret; + } + break; + case SNDRV_PCM_STREAM_PLAYBACK: + ret = msm8x16_wcd_set_interpolator_rate(dai, rx_fs_rate, + params_rate(params)); + if (ret < 0) { + dev_err(dai->codec->dev, + "%s: set decimator rate failed %d\n", __func__, + ret); + return ret; + } + break; + default: + dev_err(dai->codec->dev, + "%s: Invalid stream type %d\n", __func__, + substream->stream); + return -EINVAL; + } + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + snd_soc_update_bits(dai->codec, + MSM8X16_WCD_A_CDC_CLK_TX_I2S_CTL, 0x20, 0x20); + snd_soc_update_bits(dai->codec, + MSM8X16_WCD_A_CDC_CLK_RX_I2S_CTL, 0x20, 0x20); + break; + case SNDRV_PCM_FORMAT_S24_LE: + snd_soc_update_bits(dai->codec, + MSM8X16_WCD_A_CDC_CLK_TX_I2S_CTL, 0x20, 0x00); + snd_soc_update_bits(dai->codec, + MSM8X16_WCD_A_CDC_CLK_RX_I2S_CTL, 0x20, 0x00); + break; + default: + dev_err(dai->dev, "%s: wrong format selected\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int msm8x16_wcd_set_dai_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + return 0; +} + +static int msm8x16_wcd_set_channel_map(struct snd_soc_dai *dai, + unsigned int tx_num, unsigned int *tx_slot, + unsigned int rx_num, unsigned int *rx_slot) + +{ + return 0; +} + +static int msm8x16_wcd_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + return 0; +} + +static struct snd_soc_dai_ops msm8x16_wcd_dai_ops = { + .startup = msm8x16_wcd_startup, + .shutdown = msm8x16_wcd_shutdown, + .hw_params = msm8x16_wcd_hw_params, + .set_sysclk = msm8x16_wcd_set_dai_sysclk, + .set_fmt = msm8x16_wcd_set_dai_fmt, + .set_channel_map = msm8x16_wcd_set_channel_map, +}; + static struct snd_soc_dai_driver msm8x16_wcd_codec_dai[] = { + [0] = { + .name = "msm8x16_wcd_i2s_rx1", + .id = MSM8x16_WCD_PLAYBACK_DAI, + .playback = { + .stream_name = "AIF1 Playback", + .rates = MSM8X16_WCD_RATES, + .formats = MSM8X16_WCD_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 3, + }, + .ops = &msm8x16_wcd_dai_ops, + }, + [1] = { + .name = "msm8x16_wcd_i2s_tx1", + .id = MSM8x16_WCD_CAPTURE_DAI, + .capture = { + .stream_name = "AIF1 Capture", + .rates = MSM8X16_WCD_RATES, + .formats = MSM8X16_WCD_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &msm8x16_wcd_dai_ops, + }, };
static struct snd_soc_codec_driver msm8x16_wcd_codec = {
On Tue, Feb 16, 2016 at 05:33:10PM +0000, Srinivas Kandagatla wrote:
+static int msm8x16_wcd_set_interpolator_rate(struct snd_soc_dai *dai,
- u8 rx_fs_rate_reg_val, u32 sample_rate)
+{
- return 0;
+}
Don't include empty functions, just remove them.
This patch adds basic mixer controls found in the codec.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/codecs/msm8x16-wcd.c | 99 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+)
diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c index 4bc8274..4bf3b81 100644 --- a/sound/soc/codecs/msm8x16-wcd.c +++ b/sound/soc/codecs/msm8x16-wcd.c @@ -13,6 +13,7 @@ #include <sound/soc.h> #include <sound/pcm.h> #include <sound/pcm_params.h> +#include <sound/tlv.h>
#include "msm8x16-wcd-registers.h" #include "msm8x16-wcd.h" @@ -49,6 +50,29 @@ struct msm8x16_wcd_chip { bool micbias2_cap_mode; };
+static const char * const msm8x16_wcd_spk_boost_ctrl_text[] = { + "DISABLE", "ENABLE"}; + +/*cut of frequency for high pass filter*/ +static const char * const cf_text[] = { + "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz" +}; + +static const struct soc_enum msm8x16_wcd_spk_boost_ctl_enum[] = { + SOC_ENUM_SINGLE_EXT(2, msm8x16_wcd_spk_boost_ctrl_text), +}; +static const struct soc_enum cf_rxmix1_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_RX1_B4_CTL, 0, 3, cf_text); + +static const struct soc_enum cf_rxmix2_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_RX2_B4_CTL, 0, 3, cf_text); + +static const struct soc_enum cf_rxmix3_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_RX3_B4_CTL, 0, 3, cf_text); + +static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0); +static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1); + static int msm8x16_wcd_volatile(struct snd_soc_codec *codec, unsigned int reg) { return msm8x16_wcd_reg_readonly[reg]; @@ -164,6 +188,79 @@ static void msm8x16_wcd_configure_cap(struct snd_soc_codec *codec, } }
+static int msm8x16_wcd_spk_boost_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct msm8x16_wcd_chip *msm8x16_wcd = dev_get_drvdata(codec->dev); + + if (msm8x16_wcd->spk_boost_set == false) { + ucontrol->value.integer.value[0] = 0; + } else if (msm8x16_wcd->spk_boost_set == true) { + ucontrol->value.integer.value[0] = 1; + } else { + dev_err(codec->dev, "%s: ERROR: Unsupported Speaker Boost = %d\n", + __func__, msm8x16_wcd->spk_boost_set); + return -EINVAL; + } + + return 0; +} + +static int msm8x16_wcd_spk_boost_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct msm8x16_wcd_chip *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + + switch (ucontrol->value.integer.value[0]) { + case 0: + msm8x16_wcd->spk_boost_set = false; + break; + case 1: + msm8x16_wcd->spk_boost_set = true; + break; + default: + return -EINVAL; + } + return 0; +} + +static const struct snd_kcontrol_new msm8x16_wcd_snd_controls[] = { + + SOC_ENUM_EXT("Speaker Boost", msm8x16_wcd_spk_boost_ctl_enum[0], + msm8x16_wcd_spk_boost_get, msm8x16_wcd_spk_boost_set), + + SOC_SINGLE_TLV("ADC1 Volume", MSM8X16_WCD_A_ANALOG_TX_1_EN, 3, + 8, 0, analog_gain), + SOC_SINGLE_TLV("ADC2 Volume", MSM8X16_WCD_A_ANALOG_TX_2_EN, 3, + 8, 0, analog_gain), + SOC_SINGLE_TLV("ADC3 Volume", MSM8X16_WCD_A_ANALOG_TX_3_EN, 3, + 8, 0, analog_gain), + + SOC_SINGLE_SX_TLV("RX1 Digital Volume", + MSM8X16_WCD_A_CDC_RX1_VOL_CTL_B2_CTL, + 0, -84, 40, digital_gain), + SOC_SINGLE_SX_TLV("RX2 Digital Volume", + MSM8X16_WCD_A_CDC_RX2_VOL_CTL_B2_CTL, + 0, -84, 40, digital_gain), + SOC_SINGLE_SX_TLV("RX3 Digital Volume", + MSM8X16_WCD_A_CDC_RX3_VOL_CTL_B2_CTL, + 0, -84, 40, digital_gain), + + SOC_SINGLE("RX1 HPF Switch", + MSM8X16_WCD_A_CDC_RX1_B5_CTL, 2, 1, 0), + SOC_SINGLE("RX2 HPF Switch", + MSM8X16_WCD_A_CDC_RX2_B5_CTL, 2, 1, 0), + SOC_SINGLE("RX3 HPF Switch", + MSM8X16_WCD_A_CDC_RX3_B5_CTL, 2, 1, 0), + + SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum), + SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum), + SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum), +}; + + static int msm8x16_wcd_codec_parse_dt(struct platform_device *pdev, struct msm8x16_wcd_chip *chip) { @@ -551,6 +648,8 @@ static struct snd_soc_codec_driver msm8x16_wcd_codec = { .reg_cache_size = MSM8X16_WCD_NUM_REGISTERS, .reg_cache_default = msm8x16_wcd_reset_reg_defaults, .reg_word_size = 1, + .controls = msm8x16_wcd_snd_controls, + .num_controls = ARRAY_SIZE(msm8x16_wcd_snd_controls), };
static int msm8x16_wcd_probe(struct platform_device *pdev)
On Tue, Feb 16, 2016 at 05:33:28PM +0000, Srinivas Kandagatla wrote:
+static const char * const msm8x16_wcd_spk_boost_ctrl_text[] = {
"DISABLE", "ENABLE"};
On/off switches should be presented to usersrpace as on/off switches with "Switch" at the end of their name not as SHOUTING enums. The indentation and brace placement are also weird here.
I'm going to stop reviewing at this point. It really feels like this code could benefit from taking a look at some modern CODEC drivers and following the ways they do things, there appear to be a lot of these issues throughout the series.
Thanks for your comments on the patch series.
On 16/02/16 20:21, Mark Brown wrote:
On Tue, Feb 16, 2016 at 05:33:28PM +0000, Srinivas Kandagatla wrote:
+static const char * const msm8x16_wcd_spk_boost_ctrl_text[] = {
"DISABLE", "ENABLE"};
On/off switches should be presented to usersrpace as on/off switches with "Switch" at the end of their name not as SHOUTING enums. The indentation and brace placement are also weird here.
I'm going to stop reviewing at this point. It really feels like this code could benefit from taking a look at some modern CODEC drivers and following the ways they do things, there appear to be a lot of these issues throughout the series.
I totally agree with you on this and all the comments in the patchset, TBH this driver was forward ported from msm-3.10 Andriod kernel, My Idea was to retain most of code bits from that driver but it looks its a very bad Idea to start with.
I will relook into the modern codec drivers and rewrite the driver to be inline with them.
Thanks, srini
On Wed, Feb 17, 2016 at 10:58:02AM +0000, Srinivas Kandagatla wrote:
I will relook into the modern codec drivers and rewrite the driver to be inline with them.
It probably doesn't need a complete rewrite but it does need a review and update to meet modern standards.
This patch adds all the dapm widgets in digital and analog die of the codec.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/codecs/msm8x16-wcd.c | 1278 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1278 insertions(+)
diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c index 4bf3b81..f1ae55d 100644 --- a/sound/soc/codecs/msm8x16-wcd.c +++ b/sound/soc/codecs/msm8x16-wcd.c @@ -24,10 +24,19 @@ #define MSM8X16_WCD_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ SNDRV_PCM_FMTBIT_S24_LE)
+/* cut off freq of 3DB 150HZ */ +#define CF_MIN_3DB_150HZ 0x2 + /* Cap mode for micbias */ #define MICBIAS_EXT_BYP_CAP 0x00 #define MICBIAS_NO_EXT_BYP_CAP 0x01
+/* Internal status on mute_mask to track mute on different sinks */ +#define MUTE_MASK_HPHL_PA_DISABLE BIT(1) +#define MUTE_MASK_HPHR_PA_DISABLE BIT(2) +#define MUTE_MASK_EAR_PA_DISABLE BIT(3) +#define MUTE_MASK_SPKR_PA_DISABLE BIT(4) + struct msm8x16_wcd_chip { struct regmap *analog_map; struct regmap *digital_map; @@ -58,6 +67,38 @@ static const char * const cf_text[] = { "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz" };
+static const char * const rx_mix1_text[] = { + "ZERO", "IIR1", "IIR2", "RX1", "RX2", "RX3" +}; + +static const char * const rx_mix2_text[] = { + "ZERO", "IIR1", "IIR2" +}; + +static const char * const dec_mux_text[] = { + "ZERO", "ADC1", "ADC2", "ADC3", "DMIC1", "DMIC2" +}; + +static const char * const adc2_mux_text[] = { + "ZERO", "INP2", "INP3" +}; + +static const char * const rdac2_mux_text[] = { + "ZERO", "RX2", "RX1" +}; + +static const char * const iir_inp1_text[] = { + "ZERO", "DEC1", "DEC2", "RX1", "RX2", "RX3" +}; + +static const char * const iir1_inp1_text[] = { + "ZERO", "DEC1", "DEC2", "RX1", "RX2", "RX3" +}; + +static const char * const hph_text[] = { + "ZERO", "Switch", +}; + static const struct soc_enum msm8x16_wcd_spk_boost_ctl_enum[] = { SOC_ENUM_SINGLE_EXT(2, msm8x16_wcd_spk_boost_ctrl_text), }; @@ -70,9 +111,164 @@ static const struct soc_enum cf_rxmix2_enum = static const struct soc_enum cf_rxmix3_enum = SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_RX3_B4_CTL, 0, 3, cf_text);
+/* RX1 MIX1 */ +static const struct soc_enum rx_mix1_inp1_chain_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_RX1_B1_CTL, + 0, 6, rx_mix1_text); + +static const struct soc_enum rx_mix1_inp2_chain_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_RX1_B1_CTL, + 3, 6, rx_mix1_text); + +static const struct soc_enum rx_mix1_inp3_chain_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_RX1_B2_CTL, + 0, 6, rx_mix1_text); +/* RX1 MIX2 */ +static const struct soc_enum rx_mix2_inp1_chain_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_RX1_B3_CTL, + 0, 3, rx_mix2_text); + +/* RX2 MIX1 */ +static const struct soc_enum rx2_mix1_inp1_chain_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_RX2_B1_CTL, + 0, 6, rx_mix1_text); + +static const struct soc_enum rx2_mix1_inp2_chain_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_RX2_B1_CTL, + 3, 6, rx_mix1_text); + +static const struct soc_enum rx2_mix1_inp3_chain_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_RX2_B1_CTL, + 0, 6, rx_mix1_text); + +/* RX2 MIX2 */ +static const struct soc_enum rx2_mix2_inp1_chain_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_RX2_B3_CTL, + 0, 3, rx_mix2_text); + +/* RX3 MIX1 */ +static const struct soc_enum rx3_mix1_inp1_chain_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_RX3_B1_CTL, + 0, 6, rx_mix1_text); + +static const struct soc_enum rx3_mix1_inp2_chain_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_RX3_B1_CTL, + 3, 6, rx_mix1_text); + +static const struct soc_enum rx3_mix1_inp3_chain_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_RX3_B1_CTL, + 0, 6, rx_mix1_text); + +/* DEC */ +static const struct soc_enum dec1_mux_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_TX_B1_CTL, + 0, 6, dec_mux_text); + +static const struct soc_enum dec2_mux_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_TX_B1_CTL, + 3, 6, dec_mux_text); + +static const struct soc_enum rdac2_mux_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_DIGITAL_CDC_CONN_HPHR_DAC_CTL, + 0, 3, rdac2_mux_text); + +static const struct soc_enum iir1_inp1_mux_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_EQ1_B1_CTL, + 0, 6, iir_inp1_text); + +static const struct soc_enum iir2_inp1_mux_enum = + SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_EQ2_B1_CTL, + 0, 6, iir_inp1_text); + +static const struct soc_enum adc2_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adc2_mux_text), adc2_mux_text); + +static const struct soc_enum hph_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(hph_text), hph_text); + +static const struct snd_kcontrol_new ear_pa_switch[] = { + SOC_DAPM_SINGLE("Switch", + MSM8X16_WCD_A_ANALOG_RX_EAR_CTL, 5, 1, 0) +}; + +static const struct snd_kcontrol_new spkr_switch[] = { + SOC_DAPM_SINGLE("Switch", + MSM8X16_WCD_A_ANALOG_SPKR_DAC_CTL, 7, 1, 0) +}; + +static const struct snd_kcontrol_new dec1_mux = + SOC_DAPM_ENUM("DEC1 MUX Mux", dec1_mux_enum); + +static const struct snd_kcontrol_new dec2_mux = + SOC_DAPM_ENUM("DEC2 MUX Mux", dec2_mux_enum); + +static const struct snd_kcontrol_new rdac2_mux = + SOC_DAPM_ENUM("RDAC2 MUX Mux", rdac2_mux_enum); + +static const struct snd_kcontrol_new iir1_inp1_mux = + SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum); + +static const struct snd_kcontrol_new iir2_inp1_mux = + SOC_DAPM_ENUM("IIR2 INP1 Mux", iir2_inp1_mux_enum); + +static const struct snd_kcontrol_new tx_adc2_mux = + SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum); + +static const struct snd_kcontrol_new rx_mix1_inp1_mux = + SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum); + +static const struct snd_kcontrol_new rx_mix1_inp2_mux = + SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum); + +static const struct snd_kcontrol_new rx_mix1_inp3_mux = + SOC_DAPM_ENUM("RX1 MIX1 INP3 Mux", rx_mix1_inp3_chain_enum); + +static const struct snd_kcontrol_new rx2_mix1_inp1_mux = + SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum); + +static const struct snd_kcontrol_new rx2_mix1_inp2_mux = + SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum); + +static const struct snd_kcontrol_new rx2_mix1_inp3_mux = + SOC_DAPM_ENUM("RX2 MIX1 INP3 Mux", rx2_mix1_inp3_chain_enum); + +static const struct snd_kcontrol_new rx3_mix1_inp1_mux = + SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum); + +static const struct snd_kcontrol_new rx3_mix1_inp2_mux = + SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum); + +static const struct snd_kcontrol_new rx3_mix1_inp3_mux = + SOC_DAPM_ENUM("RX3 MIX1 INP3 Mux", rx3_mix1_inp3_chain_enum); + +static const struct snd_kcontrol_new rx1_mix2_inp1_mux = + SOC_DAPM_ENUM("RX1 MIX2 INP1 Mux", rx_mix2_inp1_chain_enum); + +static const struct snd_kcontrol_new rx2_mix2_inp1_mux = + SOC_DAPM_ENUM("RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum); + +static const struct snd_kcontrol_new hphl_mux[] = { + SOC_DAPM_ENUM("HPHL", hph_enum) +}; + +static const struct snd_kcontrol_new hphr_mux[] = { + SOC_DAPM_ENUM("HPHR", hph_enum) +}; + static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0); static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
+static unsigned long rx_digital_gain_reg[] = { + MSM8X16_WCD_A_CDC_RX1_VOL_CTL_B2_CTL, + MSM8X16_WCD_A_CDC_RX2_VOL_CTL_B2_CTL, + MSM8X16_WCD_A_CDC_RX3_VOL_CTL_B2_CTL, +}; + +static unsigned long tx_digital_gain_reg[] = { + MSM8X16_WCD_A_CDC_TX1_VOL_CTL_GAIN, + MSM8X16_WCD_A_CDC_TX2_VOL_CTL_GAIN, +}; + static int msm8x16_wcd_volatile(struct snd_soc_codec *codec, unsigned int reg) { return msm8x16_wcd_reg_readonly[reg]; @@ -260,6 +456,1086 @@ static const struct snd_kcontrol_new msm8x16_wcd_snd_controls[] = { SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum), };
+static int msm8x16_wcd_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct msm8x16_wcd_chip *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_RX_EAR_CTL, + 0x80, 0x80); + break; + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_RX_EAR_CTL, + 0x40, 0x40); + usleep_range(7000, 7100); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_RX1_B6_CTL, 0x01, 0x00); + break; + case SND_SOC_DAPM_PRE_PMD: + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_RX1_B6_CTL, 0x01, 0x01); + msleep(20); + msm8x16_wcd->mute_mask |= MUTE_MASK_EAR_PA_DISABLE; + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_RX_EAR_CTL, + 0x40, 0x00); + usleep_range(7000, 7100); + /* + * Reset pa select bit from ear to hph after ear pa + * is disabled to reduce ear turn off pop + */ + snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_RX_EAR_CTL, + 0x80, 0x00); + break; + } + return 0; +} + +static int msm8x16_wcd_hph_pa_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct msm8x16_wcd_chip *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (w->shift == 5) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_RX_HPH_L_TEST, 0x04, 0x04); + } else if (w->shift == 4) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_RX_HPH_R_TEST, 0x04, 0x04); + } + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_NCP_FBCTRL, 0x20, 0x20); + break; + + case SND_SOC_DAPM_POST_PMU: + usleep_range(4000, 4100); + if (w->shift == 5) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_RX1_B6_CTL, 0x01, 0x00); + else if (w->shift == 4) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_RX2_B6_CTL, 0x01, 0x00); + usleep_range(10000, 10100); + break; + + case SND_SOC_DAPM_PRE_PMD: + if (w->shift == 5) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_RX1_B6_CTL, 0x01, 0x01); + msleep(20); + msm8x16_wcd->mute_mask |= MUTE_MASK_HPHL_PA_DISABLE; + } else if (w->shift == 4) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_RX2_B6_CTL, 0x01, 0x01); + msleep(20); + msm8x16_wcd->mute_mask |= MUTE_MASK_HPHR_PA_DISABLE; + } + break; + case SND_SOC_DAPM_POST_PMD: + if (w->shift == 5) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_RX_HPH_L_TEST, 0x04, 0x00); + + } else if (w->shift == 4) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_RX_HPH_R_TEST, 0x04, 0x00); + } + usleep_range(4000, 4100); + + usleep_range(1000, 1100); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, 0x40, 0x40); + usleep_range(10000, 10100); + break; + } + return 0; +} + +static int msm8x16_wcd_hphl_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_RX_HPH_L_PA_DAC_CTL, 0x02, 0x02); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x01); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_ANA_CLK_CTL, 0x02, 0x02); + break; + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_RX_HPH_L_PA_DAC_CTL, 0x02, 0x00); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_ANA_CLK_CTL, 0x02, 0x00); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x00); + break; + } + return 0; +} + +static int msm8x16_wcd_codec_enable_spk_pa(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct msm8x16_wcd_chip *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_SPKR_PWRSTG_CTL, 0x01, 0x01); + if (!msm8x16_wcd->spk_boost_set) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_SPKR_DAC_CTL, 0x10, 0x10); + usleep_range(1000, 1100); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_SPKR_PWRSTG_CTL, 0xE0, 0xE0); + if (!TOMBAK_IS_1_0(msm8x16_wcd->pmic_rev)) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_RX_EAR_CTL, 0x01, 0x01); + break; + case SND_SOC_DAPM_POST_PMU: + usleep_range(1000, 1100); + if (msm8x16_wcd->spk_boost_set) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_SPKR_DRV_CTL, 0xEF, 0xEF); + else + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_SPKR_DAC_CTL, 0x10, 0x00); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_RX3_B6_CTL, 0x01, 0x00); + snd_soc_update_bits(codec, w->reg, 0x80, 0x80); + break; + case SND_SOC_DAPM_PRE_PMD: + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_RX3_B6_CTL, 0x01, 0x01); + msleep(20); + msm8x16_wcd->mute_mask |= MUTE_MASK_SPKR_PA_DISABLE; + snd_soc_update_bits(codec, w->reg, 0x80, 0x00); + if (msm8x16_wcd->spk_boost_set) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_SPKR_DRV_CTL, 0xEF, 0x00); + else + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_SPKR_DAC_CTL, 0x10, 0x00); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_SPKR_PWRSTG_CTL, 0xE0, 0x00); + if (!TOMBAK_IS_1_0(msm8x16_wcd->pmic_rev)) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_RX_EAR_CTL, 0x01, 0x00); + usleep_range(1000, 1100); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_SPKR_PWRSTG_CTL, 0x01, 0x00); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x00); + break; + } + return 0; +} + +static int msm8x16_wcd_codec_enable_dig_clk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct msm8x16_wcd_chip *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (w->shift == 2) + snd_soc_update_bits(codec, w->reg, 0x80, 0x80); + if (msm8x16_wcd->spk_boost_set) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_SEC_ACCESS, + 0xA5, 0xA5); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_PERPH_RESET_CTL3, + 0x0F, 0x0F); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_CURRENT_LIMIT, + 0x82, 0x82); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 0x20, 0x20); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_BOOST_EN_CTL, + 0xDF, 0xDF); + usleep_range(1000, 1100); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_CURRENT_LIMIT, + 0x83, 0x83); + } else if (msm8x16_wcd->ear_pa_boost_set) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_SEC_ACCESS, + 0xA5, 0xA5); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_PERPH_RESET_CTL3, + 0x07, 0x07); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_BYPASS_MODE, + 0x40, 0x40); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_BYPASS_MODE, + 0x80, 0x80); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_BYPASS_MODE, + 0x02, 0x02); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_BOOST_EN_CTL, + 0xDF, 0xDF); + } else { + snd_soc_update_bits(codec, w->reg, 1<<w->shift, + 1<<w->shift); + } + break; + case SND_SOC_DAPM_POST_PMD: + if (msm8x16_wcd->spk_boost_set) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_BOOST_EN_CTL, + 0xDF, 0x5F); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 0x20, 0x00); + } else if (msm8x16_wcd->ear_pa_boost_set) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_BOOST_EN_CTL, + 0x80, 0x00); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_BYPASS_MODE, + 0x80, 0x00); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_BYPASS_MODE, + 0x02, 0x00); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_BYPASS_MODE, + 0x40, 0x00); + } else { + snd_soc_update_bits(codec, w->reg, 1<<w->shift, 0x00); + } + break; + } + return 0; +} + +static int msm8x16_wcd_codec_enable_rx_chain(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 0x80, 0x80); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 0x80, 0x00); + snd_soc_update_bits(codec, w->reg, + 1 << w->shift, 0x00); + msleep(20); + break; + } + return 0; +} + +static int msm8x16_wcd_codec_enable_on_demand_supply( + struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + int ret = 0; + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct msm8x16_wcd_chip *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = regulator_enable(msm8x16_wcd->vdd_micbias); + if (ret) + dev_err(codec->dev, "%s: Failed to enable vdd micbias\n", + __func__); + break; + case SND_SOC_DAPM_POST_PMD: + ret = regulator_disable(msm8x16_wcd->vdd_micbias); + if (ret) + dev_err(codec->dev, "%s: Failed to disable vdd-micbias\n", + __func__); + break; + default: + break; + } + + return ret; +} + +static int msm8x16_wcd_codec_enable_charge_pump(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct msm8x16_wcd_chip *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (!(strcmp(w->name, "EAR CP"))) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 0x80, 0x80); + else + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 0xC0, 0xC0); + break; + case SND_SOC_DAPM_POST_PMU: + usleep_range(1000, 1100); + break; + case SND_SOC_DAPM_POST_PMD: + usleep_range(1000, 1100); + if (!(strcmp(w->name, "EAR CP"))) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 0x80, 0x00); + else { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 0x40, 0x00); + if (msm8x16_wcd->rx_bias_count == 0) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 0x80, 0x00); + } + break; + } + return 0; +} + +static int msm8x16_wcd_codec_enable_rx_bias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct msm8x16_wcd_chip *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + msm8x16_wcd->rx_bias_count++; + if (msm8x16_wcd->rx_bias_count == 1) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_RX_COM_BIAS_DAC, + 0x81, 0x81); + break; + case SND_SOC_DAPM_POST_PMD: + msm8x16_wcd->rx_bias_count--; + if (msm8x16_wcd->rx_bias_count == 0) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_RX_COM_BIAS_DAC, + 0x81, 0x00); + break; + } + + return 0; +} + +static void msm8x16_wcd_micbias2_enable(struct snd_soc_codec *codec, bool on) +{ + if (on) { + snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_MICB_1_CTL, + 0x60, 0x60); + snd_soc_write(codec, MSM8X16_WCD_A_ANALOG_MICB_1_VAL, + 0xC0); + /* + * Special headset needs MICBIAS as 2.7V so wait for + * 50 msec for the MICBIAS to reach 2.7 volts. + */ + msleep(50); + snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_MICB_1_CTL, + 0x60, 0x00); + } +} + +static int msm8x16_wcd_codec_enable_micbias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct msm8x16_wcd_chip *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + u16 micb_int_reg; + char *internal1_text = "Internal1"; + char *internal2_text = "Internal2"; + char *internal3_text = "Internal3"; + char *external2_text = "External2"; + char *external_text = "External"; + bool micbias2; + + switch (w->reg) { + case MSM8X16_WCD_A_ANALOG_MICB_1_EN: + case MSM8X16_WCD_A_ANALOG_MICB_2_EN: + micb_int_reg = MSM8X16_WCD_A_ANALOG_MICB_1_INT_RBIAS; + break; + default: + dev_err(codec->dev, + "%s: Error, invalid micbias register 0x%x\n", + __func__, w->reg); + return -EINVAL; + } + + micbias2 = (snd_soc_read(codec, MSM8X16_WCD_A_ANALOG_MICB_2_EN) & 0x80); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (strnstr(w->name, internal1_text, 30)) { + snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x80); + } else if (strnstr(w->name, internal2_text, 30)) { + snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x10); + snd_soc_update_bits(codec, w->reg, 0x60, 0x00); + } else if (strnstr(w->name, internal3_text, 30)) { + snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x2); + } + if (!strnstr(w->name, external_text, 30)) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_MICB_1_EN, 0x05, 0x04); + if (w->reg == MSM8X16_WCD_A_ANALOG_MICB_1_EN) + msm8x16_wcd_configure_cap(codec, true, micbias2); + + break; + case SND_SOC_DAPM_POST_PMU: + usleep_range(20000, 20100); + if (strnstr(w->name, internal1_text, 30)) { + snd_soc_update_bits(codec, micb_int_reg, 0x40, 0x40); + } else if (strnstr(w->name, internal2_text, 30)) { + snd_soc_update_bits(codec, micb_int_reg, 0x08, 0x08); + msm8x16_wcd_micbias2_enable(codec, true); + msm8x16_wcd_configure_cap(codec, false, true); + regmap_write(msm8x16_wcd->analog_map, 0xf144, 0x95); + } else if (strnstr(w->name, internal3_text, 30)) { + snd_soc_update_bits(codec, micb_int_reg, 0x01, 0x01); + } else if (strnstr(w->name, external2_text, 30)) { + msm8x16_wcd_micbias2_enable(codec, true); + } + break; + case SND_SOC_DAPM_POST_PMD: + if (strnstr(w->name, internal1_text, 30)) { + snd_soc_update_bits(codec, micb_int_reg, 0xC0, 0x40); + } else if (strnstr(w->name, internal2_text, 30)) { + msm8x16_wcd_micbias2_enable(codec, false); + } else if (strnstr(w->name, internal3_text, 30)) { + snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0); + } else if (strnstr(w->name, external2_text, 30)) { + msm8x16_wcd_micbias2_enable(codec, false); + break; + } + if (w->reg == MSM8X16_WCD_A_ANALOG_MICB_1_EN) + msm8x16_wcd_configure_cap(codec, false, micbias2); + break; + } + + return 0; +} + +static void msm8x16_wcd_codec_enable_adc_block(struct snd_soc_codec *codec, + int enable) +{ + + if (enable) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_ANA_CLK_CTL, + 0x20, 0x20); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 0x10, 0x10); + } else { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 0x10, 0x00); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_ANA_CLK_CTL, + 0x20, 0x0); + } +} + +static int msm8x16_wcd_codec_enable_adc(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + u16 adc_reg; + u8 init_bit_shift; + + adc_reg = MSM8X16_WCD_A_ANALOG_TX_1_2_TEST_CTL_2; + + if (w->reg == MSM8X16_WCD_A_ANALOG_TX_1_EN) + init_bit_shift = 5; + else if ((w->reg == MSM8X16_WCD_A_ANALOG_TX_2_EN) || + (w->reg == MSM8X16_WCD_A_ANALOG_TX_3_EN)) + init_bit_shift = 4; + else { + dev_err(codec->dev, "%s: Error, invalid adc register\n", + __func__); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + msm8x16_wcd_codec_enable_adc_block(codec, 1); + if (w->reg == MSM8X16_WCD_A_ANALOG_TX_2_EN) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_MICB_1_CTL, 0x02, 0x02); + /* + * Add delay of 10 ms to give sufficient time for the voltage + * to shoot up and settle so that the txfe init does not + * happen when the input voltage is changing too much. + */ + usleep_range(10000, 10010); + snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, + 1 << init_bit_shift); + if (w->reg == MSM8X16_WCD_A_ANALOG_TX_1_EN) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX1_CTL, + 0x03, 0x00); + else if ((w->reg == MSM8X16_WCD_A_ANALOG_TX_2_EN) || + (w->reg == MSM8X16_WCD_A_ANALOG_TX_3_EN)) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX2_CTL, + 0x03, 0x00); + usleep_range(1000, 1100); + break; + case SND_SOC_DAPM_POST_PMU: + /* + * Add delay of 12 ms before deasserting the init + * to reduce the tx pop + */ + usleep_range(12000, 12010); + snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00); + usleep_range(1000, 1100); + break; + case SND_SOC_DAPM_POST_PMD: + msm8x16_wcd_codec_enable_adc_block(codec, 0); + if (w->reg == MSM8X16_WCD_A_ANALOG_TX_2_EN) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_MICB_1_CTL, 0x02, 0x00); + if (w->reg == MSM8X16_WCD_A_ANALOG_TX_1_EN) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX1_CTL, + 0x03, 0x02); + else if ((w->reg == MSM8X16_WCD_A_ANALOG_TX_2_EN) || + (w->reg == MSM8X16_WCD_A_ANALOG_TX_3_EN)) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_CONN_TX2_CTL, + 0x03, 0x02); + + break; + } + return 0; +} + +static int msm8x16_wcd_hphr_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_RX_HPH_R_PA_DAC_CTL, 0x02, 0x02); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, 0x02, 0x02); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_ANA_CLK_CTL, 0x01, 0x01); + break; + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_RX_HPH_R_PA_DAC_CTL, 0x02, 0x00); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_ANA_CLK_CTL, 0x01, 0x00); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, 0x02, 0x00); + break; + } + return 0; +} + +static int msm8x16_wcd_codec_enable_interpolator(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct msm8x16_wcd_chip *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* apply the digital gain after the interpolator is enabled*/ + if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg)) + snd_soc_write(codec, + rx_digital_gain_reg[w->shift], + snd_soc_read(codec, + rx_digital_gain_reg[w->shift]) + ); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_CLK_RX_RESET_CTL, + 1 << w->shift, 1 << w->shift); + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_CLK_RX_RESET_CTL, + 1 << w->shift, 0x0); + /* + * disable the mute enabled during the PMD of this device + */ + if (msm8x16_wcd->mute_mask & MUTE_MASK_HPHL_PA_DISABLE) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_RX1_B6_CTL, 0x01, 0x00); + msm8x16_wcd->mute_mask &= ~(MUTE_MASK_HPHL_PA_DISABLE); + } + if (msm8x16_wcd->mute_mask & MUTE_MASK_HPHR_PA_DISABLE) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_RX2_B6_CTL, 0x01, 0x00); + msm8x16_wcd->mute_mask &= ~(MUTE_MASK_HPHR_PA_DISABLE); + } + if (msm8x16_wcd->mute_mask & MUTE_MASK_SPKR_PA_DISABLE) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_RX3_B6_CTL, 0x01, 0x00); + msm8x16_wcd->mute_mask &= ~(MUTE_MASK_SPKR_PA_DISABLE); + } + if (msm8x16_wcd->mute_mask & MUTE_MASK_EAR_PA_DISABLE) { + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_RX1_B6_CTL, 0x01, 0x00); + msm8x16_wcd->mute_mask &= ~(MUTE_MASK_EAR_PA_DISABLE); + } + } + return 0; +} + +static int msm8x16_wcd_codec_enable_dec(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + unsigned int decimator; + char *dec_name = NULL; + char *widget_name = NULL; + char *temp; + int ret = 0; + u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg; + u8 dec_hpf_cut_of_freq; + int offset; + char *dec_num; + + widget_name = kstrndup(w->name, 15, GFP_KERNEL); + if (!widget_name) + return -ENOMEM; + temp = widget_name; + + dec_name = strsep(&widget_name, " "); + widget_name = temp; + if (!dec_name) { + dev_err(codec->dev, + "%s: Invalid decimator = %s\n", __func__, w->name); + ret = -EINVAL; + goto out; + } + + dec_num = strpbrk(dec_name, "12"); + if (dec_num == NULL) { + dev_err(codec->dev, "%s: Invalid Decimator\n", __func__); + ret = -EINVAL; + goto out; + } + + ret = kstrtouint(dec_num, 10, &decimator); + if (ret < 0) { + dev_err(codec->dev, + "%s: Invalid decimator = %s\n", __func__, dec_name); + ret = -EINVAL; + goto out; + } + + dev_err(codec->dev, + "%s(): widget = %s dec_name = %s decimator = %u\n", __func__, + w->name, dec_name, decimator); + + if (w->reg == MSM8X16_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL) { + dec_reset_reg = MSM8X16_WCD_A_CDC_CLK_TX_RESET_B1_CTL; + offset = 0; + } else { + dev_err(codec->dev, "%s: Error, incorrect dec\n", __func__); + ret = -EINVAL; + goto out; + } + + tx_vol_ctl_reg = MSM8X16_WCD_A_CDC_TX1_VOL_CTL_CFG + + 32 * (decimator - 1); + tx_mux_ctl_reg = MSM8X16_WCD_A_CDC_TX1_MUX_CTL + + 32 * (decimator - 1); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Enableable TX digital mute */ + snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01); + dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg); + dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4; + if (dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ) { + /* set cut of freq to CF_MIN_3DB_150HZ (0x1) */ + snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30, + CF_MIN_3DB_150HZ << 4); + } + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_TX_1_2_TXFE_CLKDIV, + 0xFF, 0x42); + + break; + case SND_SOC_DAPM_POST_PMU: + /* enable HPF */ + snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x00); + /* apply the digital gain after the decimator is enabled*/ + if ((w->shift) < ARRAY_SIZE(tx_digital_gain_reg)) + snd_soc_write(codec, + tx_digital_gain_reg[w->shift + offset], + snd_soc_read(codec, + tx_digital_gain_reg[w->shift + offset]) + ); + snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00); + break; + case SND_SOC_DAPM_PRE_PMD: + snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01); + msleep(20); + snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, + 1 << w->shift); + snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0); + snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08); + snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00); + break; + } + +out: + kfree(widget_name); + return ret; +} + +static s32 g_dmic_clk_cnt; +static int msm8x16_wcd_codec_enable_dmic(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + u8 dmic_clk_en; + u16 dmic_clk_reg; + s32 *dmic_clk_cnt; + unsigned int dmic; + int ret; + char *dec_num = strpbrk(w->name, "12"); + + if (dec_num == NULL) { + dev_err(codec->dev, "%s: Invalid DMIC\n", __func__); + return -EINVAL; + } + + ret = kstrtouint(dec_num, 10, &dmic); + if (ret < 0) { + dev_err(codec->dev, + "%s: Invalid DMIC line on the codec\n", __func__); + return -EINVAL; + } + + switch (dmic) { + case 1: + case 2: + dmic_clk_en = 0x01; + dmic_clk_cnt = &g_dmic_clk_cnt; + dmic_clk_reg = MSM8X16_WCD_A_CDC_CLK_DMIC_B1_CTL; + break; + default: + dev_err(codec->dev, "%s: Invalid DMIC Selection\n", __func__); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + (*dmic_clk_cnt)++; + if (*dmic_clk_cnt == 1) { + snd_soc_update_bits(codec, dmic_clk_reg, + 0x0E, 0x02); + snd_soc_update_bits(codec, dmic_clk_reg, + dmic_clk_en, dmic_clk_en); + } + if (dmic == 1) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_TX1_DMIC_CTL, 0x07, 0x01); + if (dmic == 2) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_CDC_TX2_DMIC_CTL, 0x07, 0x01); + break; + case SND_SOC_DAPM_POST_PMD: + (*dmic_clk_cnt)--; + if (*dmic_clk_cnt == 0) + snd_soc_update_bits(codec, dmic_clk_reg, + dmic_clk_en, 0); + break; + } + return 0; +} + +static const struct snd_soc_dapm_widget msm8x16_wcd_dapm_widgets[] = { + /*RX stuff */ + SND_SOC_DAPM_OUTPUT("EAR"), + + SND_SOC_DAPM_PGA_E("EAR PA", SND_SOC_NOPM, + 0, 0, NULL, 0, msm8x16_wcd_codec_enable_ear_pa, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MIXER("EAR_S", SND_SOC_NOPM, 0, 0, + ear_pa_switch, ARRAY_SIZE(ear_pa_switch)), + + SND_SOC_DAPM_AIF_IN("I2S RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_IN("I2S RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_IN("I2S RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_SUPPLY("INT_LDO_H", SND_SOC_NOPM, 1, 0, NULL, 0), + + SND_SOC_DAPM_OUTPUT("HEADPHONE"), + SND_SOC_DAPM_PGA_E("HPHL PA", MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_EN, + 5, 0, NULL, 0, + msm8x16_wcd_hph_pa_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX("HPHL", SND_SOC_NOPM, 0, 0, hphl_mux), + + SND_SOC_DAPM_MIXER_E("HPHL DAC", + MSM8X16_WCD_A_ANALOG_RX_HPH_L_PA_DAC_CTL, 3, 0, NULL, + 0, msm8x16_wcd_hphl_dac_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_PGA_E("HPHR PA", MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_EN, + 4, 0, NULL, 0, + msm8x16_wcd_hph_pa_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX("HPHR", SND_SOC_NOPM, 0, 0, hphr_mux), + + SND_SOC_DAPM_MIXER_E("HPHR DAC", + MSM8X16_WCD_A_ANALOG_RX_HPH_R_PA_DAC_CTL, 3, 0, NULL, + 0, msm8x16_wcd_hphr_dac_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER("SPK DAC", SND_SOC_NOPM, 0, 0, + spkr_switch, ARRAY_SIZE(spkr_switch)), + + /* Speaker */ + SND_SOC_DAPM_OUTPUT("SPK_OUT"), + + SND_SOC_DAPM_PGA_E("SPK PA", MSM8X16_WCD_A_ANALOG_SPKR_DRV_CTL, + 6, 0, NULL, 0, msm8x16_wcd_codec_enable_spk_pa, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER_E("RX1 MIX1", + MSM8X16_WCD_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL, 0, + msm8x16_wcd_codec_enable_interpolator, + SND_SOC_DAPM_PRE_REG| + SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD| + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER_E("RX2 MIX1", + MSM8X16_WCD_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL, 0, + msm8x16_wcd_codec_enable_interpolator, + SND_SOC_DAPM_PRE_REG| + SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER_E("RX1 MIX2", + MSM8X16_WCD_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL, + 0, msm8x16_wcd_codec_enable_interpolator, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MIXER_E("RX2 MIX2", + MSM8X16_WCD_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL, + 0, msm8x16_wcd_codec_enable_interpolator, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MIXER_E("RX3 MIX1", + MSM8X16_WCD_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL, + 0, msm8x16_wcd_codec_enable_interpolator, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY("RX1 CLK", MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("RX2 CLK", MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 1, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("RX3 CLK", MSM8X16_WCD_A_DIGITAL_CDC_DIG_CLK_CTL, + 2, 0, msm8x16_wcd_codec_enable_dig_clk, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MIXER_E("RX1 CHAIN", MSM8X16_WCD_A_CDC_RX1_B6_CTL, 0, 0, + NULL, 0, + msm8x16_wcd_codec_enable_rx_chain, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MIXER_E("RX2 CHAIN", MSM8X16_WCD_A_CDC_RX2_B6_CTL, 0, 0, + NULL, 0, + msm8x16_wcd_codec_enable_rx_chain, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MIXER_E("RX3 CHAIN", MSM8X16_WCD_A_CDC_RX3_B6_CTL, 0, 0, + NULL, 0, + msm8x16_wcd_codec_enable_rx_chain, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0, + &rx_mix1_inp1_mux), + SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0, + &rx_mix1_inp2_mux), + SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0, + &rx_mix1_inp3_mux), + + SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0, + &rx2_mix1_inp1_mux), + SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0, + &rx2_mix1_inp2_mux), + SND_SOC_DAPM_MUX("RX2 MIX1 INP3", SND_SOC_NOPM, 0, 0, + &rx2_mix1_inp3_mux), + + SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0, + &rx3_mix1_inp1_mux), + SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0, + &rx3_mix1_inp2_mux), + SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0, + &rx3_mix1_inp3_mux), + + SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0, + &rx1_mix2_inp1_mux), + SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0, + &rx2_mix2_inp1_mux), + + SND_SOC_DAPM_SUPPLY("MICBIAS_REGULATOR", SND_SOC_NOPM, + 0, 0, + msm8x16_wcd_codec_enable_on_demand_supply, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY("CP", MSM8X16_WCD_A_ANALOG_NCP_EN, 0, 0, + msm8x16_wcd_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY("EAR CP", MSM8X16_WCD_A_ANALOG_NCP_EN, 4, 0, + msm8x16_wcd_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, + 0, 0, msm8x16_wcd_codec_enable_rx_bias, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY("SPK_RX_BIAS", SND_SOC_NOPM, 0, 0, + msm8x16_wcd_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + /* TX */ + SND_SOC_DAPM_SUPPLY_S("CDC_CONN", -2, MSM8X16_WCD_A_CDC_CLK_OTHR_CTL, + 2, 0, NULL, 0), + + SND_SOC_DAPM_INPUT("AMIC1"), + SND_SOC_DAPM_SUPPLY("MIC BIAS Internal1", + MSM8X16_WCD_A_ANALOG_MICB_1_EN, 7, 0, + msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("MIC BIAS Internal2", + MSM8X16_WCD_A_ANALOG_MICB_2_EN, 7, 0, + msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("MIC BIAS Internal3", + MSM8X16_WCD_A_ANALOG_MICB_1_EN, 7, 0, + msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM8X16_WCD_A_ANALOG_TX_1_EN, 7, 0, + msm8x16_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_ADC_E("ADC2_INP2", + NULL, MSM8X16_WCD_A_ANALOG_TX_2_EN, 7, 0, + msm8x16_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_ADC_E("ADC2_INP3", + NULL, MSM8X16_WCD_A_ANALOG_TX_3_EN, 7, 0, + msm8x16_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER("ADC2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("ADC3", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0, + &tx_adc2_mux), + + SND_SOC_DAPM_SUPPLY("MIC BIAS External", + MSM8X16_WCD_A_ANALOG_MICB_1_EN, 7, 0, + msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY("MIC BIAS External2", + MSM8X16_WCD_A_ANALOG_MICB_2_EN, 7, 0, + msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_INPUT("AMIC3"), + + SND_SOC_DAPM_MUX_E("DEC1 MUX", + MSM8X16_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0, + &dec1_mux, msm8x16_wcd_codec_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("DEC2 MUX", + MSM8X16_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0, + &dec2_mux, msm8x16_wcd_codec_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX("RDAC2 MUX", SND_SOC_NOPM, 0, 0, &rdac2_mux), + + SND_SOC_DAPM_INPUT("AMIC2"), + + SND_SOC_DAPM_AIF_OUT("I2S TX1", "AIF1 Capture", 0, SND_SOC_NOPM, + 0, 0), + SND_SOC_DAPM_AIF_OUT("I2S TX2", "AIF1 Capture", 0, SND_SOC_NOPM, + 0, 0), + SND_SOC_DAPM_AIF_OUT("I2S TX3", "AIF1 Capture", 0, SND_SOC_NOPM, + 0, 0), + + /* Digital Mic Inputs */ + SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0, + msm8x16_wcd_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0, + msm8x16_wcd_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + /* Sidetone */ + SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux), + SND_SOC_DAPM_PGA("IIR1", + MSM8X16_WCD_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0), + + SND_SOC_DAPM_MUX("IIR2 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp1_mux), + SND_SOC_DAPM_PGA("IIR2", + MSM8X16_WCD_A_CDC_CLK_SD_CTL, 1, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", + MSM8X16_WCD_A_CDC_CLK_RX_I2S_CTL, 4, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", + MSM8X16_WCD_A_CDC_CLK_TX_I2S_CTL, 4, 0, + NULL, 0), +};
static int msm8x16_wcd_codec_parse_dt(struct platform_device *pdev, struct msm8x16_wcd_chip *chip) @@ -650,6 +1926,8 @@ static struct snd_soc_codec_driver msm8x16_wcd_codec = { .reg_word_size = 1, .controls = msm8x16_wcd_snd_controls, .num_controls = ARRAY_SIZE(msm8x16_wcd_snd_controls), + .dapm_widgets = msm8x16_wcd_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(msm8x16_wcd_dapm_widgets), };
static int msm8x16_wcd_probe(struct platform_device *pdev)
This patch adds basic dapm routes to the codec driver, other routes are configured based on the board wiring.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/codecs/msm8x16-wcd.c | 148 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+)
diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c index f1ae55d..1a73c57 100644 --- a/sound/soc/codecs/msm8x16-wcd.c +++ b/sound/soc/codecs/msm8x16-wcd.c @@ -1876,6 +1876,152 @@ static int msm8x16_wcd_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) return 0; }
+static const struct snd_soc_dapm_route audio_map[] = { + {"RX_I2S_CLK", NULL, "CDC_CONN"}, + {"I2S RX1", NULL, "RX_I2S_CLK"}, + {"I2S RX2", NULL, "RX_I2S_CLK"}, + {"I2S RX3", NULL, "RX_I2S_CLK"}, + + {"I2S TX1", NULL, "TX_I2S_CLK"}, + {"I2S TX2", NULL, "TX_I2S_CLK"}, + + {"I2S TX1", NULL, "DEC1 MUX"}, + {"I2S TX2", NULL, "DEC2 MUX"}, + + /* RDAC Connections */ + {"HPHR DAC", NULL, "RDAC2 MUX"}, + {"RDAC2 MUX", "RX1", "RX1 CHAIN"}, + {"RDAC2 MUX", "RX2", "RX2 CHAIN"}, + + /* Earpiece (RX MIX1) */ + {"EAR", NULL, "EAR_S"}, + {"EAR_S", "Switch", "EAR PA"}, + {"EAR PA", NULL, "RX_BIAS"}, + {"EAR PA", NULL, "HPHL DAC"}, + {"EAR PA", NULL, "HPHR DAC"}, + {"EAR PA", NULL, "EAR CP"}, + + /* Headset (RX MIX1 and RX MIX2) */ + {"HEADPHONE", NULL, "HPHL PA"}, + {"HEADPHONE", NULL, "HPHR PA"}, + + {"HPHL PA", NULL, "HPHL"}, + {"HPHR PA", NULL, "HPHR"}, + {"HPHL", "Switch", "HPHL DAC"}, + {"HPHR", "Switch", "HPHR DAC"}, + {"HPHL PA", NULL, "CP"}, + {"HPHL PA", NULL, "RX_BIAS"}, + {"HPHR PA", NULL, "CP"}, + {"HPHR PA", NULL, "RX_BIAS"}, + {"HPHL DAC", NULL, "RX1 CHAIN"}, + + {"SPK_OUT", NULL, "SPK PA"}, + {"SPK PA", NULL, "SPK_RX_BIAS"}, + {"SPK PA", NULL, "SPK DAC"}, + {"SPK DAC", "Switch", "RX3 CHAIN"}, + {"SPK DAC", NULL, "VDD_SPKDRV"}, + + {"RX1 CHAIN", NULL, "RX1 CLK"}, + {"RX2 CHAIN", NULL, "RX2 CLK"}, + {"RX3 CHAIN", NULL, "RX3 CLK"}, + {"RX1 CHAIN", NULL, "RX1 MIX2"}, + {"RX2 CHAIN", NULL, "RX2 MIX2"}, + {"RX3 CHAIN", NULL, "RX3 MIX1"}, + + {"RX1 MIX1", NULL, "RX1 MIX1 INP1"}, + {"RX1 MIX1", NULL, "RX1 MIX1 INP2"}, + {"RX1 MIX1", NULL, "RX1 MIX1 INP3"}, + {"RX2 MIX1", NULL, "RX2 MIX1 INP1"}, + {"RX2 MIX1", NULL, "RX2 MIX1 INP2"}, + {"RX3 MIX1", NULL, "RX3 MIX1 INP1"}, + {"RX3 MIX1", NULL, "RX3 MIX1 INP2"}, + {"RX1 MIX2", NULL, "RX1 MIX1"}, + {"RX1 MIX2", NULL, "RX1 MIX2 INP1"}, + {"RX2 MIX2", NULL, "RX2 MIX1"}, + {"RX2 MIX2", NULL, "RX2 MIX2 INP1"}, + + {"RX1 MIX1 INP1", "RX1", "I2S RX1"}, + {"RX1 MIX1 INP1", "RX2", "I2S RX2"}, + {"RX1 MIX1 INP1", "RX3", "I2S RX3"}, + {"RX1 MIX1 INP1", "IIR1", "IIR1"}, + {"RX1 MIX1 INP1", "IIR2", "IIR2"}, + {"RX1 MIX1 INP2", "RX1", "I2S RX1"}, + {"RX1 MIX1 INP2", "RX2", "I2S RX2"}, + {"RX1 MIX1 INP2", "RX3", "I2S RX3"}, + {"RX1 MIX1 INP2", "IIR1", "IIR1"}, + {"RX1 MIX1 INP2", "IIR2", "IIR2"}, + {"RX1 MIX1 INP3", "RX1", "I2S RX1"}, + {"RX1 MIX1 INP3", "RX2", "I2S RX2"}, + {"RX1 MIX1 INP3", "RX3", "I2S RX3"}, + + {"RX2 MIX1 INP1", "RX1", "I2S RX1"}, + {"RX2 MIX1 INP1", "RX2", "I2S RX2"}, + {"RX2 MIX1 INP1", "RX3", "I2S RX3"}, + {"RX2 MIX1 INP1", "IIR1", "IIR1"}, + {"RX2 MIX1 INP1", "IIR2", "IIR2"}, + {"RX2 MIX1 INP2", "RX1", "I2S RX1"}, + {"RX2 MIX1 INP2", "RX2", "I2S RX2"}, + {"RX2 MIX1 INP2", "RX3", "I2S RX3"}, + {"RX2 MIX1 INP2", "IIR1", "IIR1"}, + {"RX2 MIX1 INP2", "IIR2", "IIR2"}, + + {"RX3 MIX1 INP1", "RX1", "I2S RX1"}, + {"RX3 MIX1 INP1", "RX2", "I2S RX2"}, + {"RX3 MIX1 INP1", "RX3", "I2S RX3"}, + {"RX3 MIX1 INP1", "IIR1", "IIR1"}, + {"RX3 MIX1 INP1", "IIR2", "IIR2"}, + {"RX3 MIX1 INP2", "RX1", "I2S RX1"}, + {"RX3 MIX1 INP2", "RX2", "I2S RX2"}, + {"RX3 MIX1 INP2", "RX3", "I2S RX3"}, + {"RX3 MIX1 INP2", "IIR1", "IIR1"}, + {"RX3 MIX1 INP2", "IIR2", "IIR2"}, + + {"RX1 MIX2 INP1", "IIR1", "IIR1"}, + {"RX2 MIX2 INP1", "IIR1", "IIR1"}, + {"RX1 MIX2 INP1", "IIR2", "IIR2"}, + {"RX2 MIX2 INP1", "IIR2", "IIR2"}, + + /* Decimator Inputs */ + {"DEC1 MUX", "DMIC1", "DMIC1"}, + {"DEC1 MUX", "DMIC2", "DMIC2"}, + {"DEC1 MUX", "ADC1", "ADC1"}, + {"DEC1 MUX", "ADC2", "ADC2"}, + {"DEC1 MUX", "ADC3", "ADC3"}, + {"DEC1 MUX", NULL, "CDC_CONN"}, + + {"DEC2 MUX", "DMIC1", "DMIC1"}, + {"DEC2 MUX", "DMIC2", "DMIC2"}, + {"DEC2 MUX", "ADC1", "ADC1"}, + {"DEC2 MUX", "ADC2", "ADC2"}, + {"DEC2 MUX", "ADC3", "ADC3"}, + {"DEC2 MUX", NULL, "CDC_CONN"}, + + /* ADC Connections */ + {"ADC2", NULL, "ADC2 MUX"}, + {"ADC3", NULL, "ADC2 MUX"}, + {"ADC2 MUX", "INP2", "ADC2_INP2"}, + {"ADC2 MUX", "INP3", "ADC2_INP3"}, + + {"ADC1", NULL, "AMIC1"}, + {"ADC2_INP2", NULL, "AMIC2"}, + {"ADC2_INP3", NULL, "AMIC3"}, + + {"IIR1", NULL, "IIR1 INP1 MUX"}, + {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"}, + {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"}, + {"IIR2", NULL, "IIR2 INP1 MUX"}, + {"IIR2 INP1 MUX", "DEC1", "DEC1 MUX"}, + {"IIR2 INP1 MUX", "DEC2", "DEC2 MUX"}, + {"MIC BIAS Internal1", NULL, "INT_LDO_H"}, + {"MIC BIAS Internal2", NULL, "INT_LDO_H"}, + {"MIC BIAS External", NULL, "INT_LDO_H"}, + {"MIC BIAS External2", NULL, "INT_LDO_H"}, + {"MIC BIAS Internal1", NULL, "MICBIAS_REGULATOR"}, + {"MIC BIAS Internal2", NULL, "MICBIAS_REGULATOR"}, + {"MIC BIAS External", NULL, "MICBIAS_REGULATOR"}, + {"MIC BIAS External2", NULL, "MICBIAS_REGULATOR"}, +}; + static struct snd_soc_dai_ops msm8x16_wcd_dai_ops = { .startup = msm8x16_wcd_startup, .shutdown = msm8x16_wcd_shutdown, @@ -1928,6 +2074,8 @@ static struct snd_soc_codec_driver msm8x16_wcd_codec = { .num_controls = ARRAY_SIZE(msm8x16_wcd_snd_controls), .dapm_widgets = msm8x16_wcd_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(msm8x16_wcd_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), };
static int msm8x16_wcd_probe(struct platform_device *pdev)
participants (3)
-
Mark Brown
-
Mark Rutland
-
Srinivas Kandagatla