aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt5
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-analog.txt85
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-digital.txt20
-rw-r--r--drivers/regulator/rk808-regulator.c9
-rw-r--r--include/sound/soc.h32
-rw-r--r--sound/soc/codecs/Kconfig7
-rw-r--r--sound/soc/codecs/Makefile5
-rw-r--r--sound/soc/codecs/msm8916-wcd-analog.c890
-rw-r--r--sound/soc/codecs/msm8916-wcd-digital.c923
-rw-r--r--sound/soc/pxa/corgi.c6
-rw-r--r--sound/soc/pxa/magician.c2
-rw-r--r--sound/soc/pxa/mioa701_wm9713.c2
-rw-r--r--sound/soc/pxa/poodle.c4
-rw-r--r--sound/soc/pxa/pxa-ssp.h6
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.h3
-rw-r--r--sound/soc/pxa/spitz.c6
-rw-r--r--sound/soc/pxa/tosa.c6
-rw-r--r--sound/soc/qcom/apq8016_sbc.c11
-rw-r--r--sound/soc/qcom/lpass-platform.c46
-rw-r--r--sound/soc/qcom/storm.c2
-rw-r--r--sound/soc/soc-core.c41
21 files changed, 2012 insertions, 99 deletions
diff --git a/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt
index d9d8635ff94c..6a4aadc4ce06 100644
--- a/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt
+++ b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt
@@ -44,8 +44,7 @@ Required dai-link subnodes:
44Required CPU/CODEC subnodes properties: 44Required CPU/CODEC subnodes properties:
45 45
46-link-name : Name of the dai link. 46-link-name : Name of the dai link.
47-sound-dai : phandle and port of CPU/CODEC 47-sound-dai : phandle/s and port of CPU/CODEC
48-capture-dai : phandle and port of CPU/CODEC
49 48
50Example: 49Example:
51 50
@@ -73,7 +72,7 @@ sound: sound {
73 sound-dai = <&lpass MI2S_PRIMARY>; 72 sound-dai = <&lpass MI2S_PRIMARY>;
74 }; 73 };
75 codec { 74 codec {
76 sound-dai = <&wcd_codec 0>; 75 sound-dai = <&lpass_codec 0>, <&wcd_codec 0>;
77 }; 76 };
78 }; 77 };
79 78
diff --git a/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-analog.txt b/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-analog.txt
new file mode 100644
index 000000000000..ccb401cfef9d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-analog.txt
@@ -0,0 +1,85 @@
1msm8916 analog audio CODEC
2
3Bindings for codec Analog IP which is integrated in pmic pm8916,
4
5## Bindings for codec core on pmic:
6
7Required properties
8 - compatible = "qcom,pm8916-wcd-analog-codec";
9 - reg: represents the slave base address provided to the peripheral.
10 - interrupt-parent : The parent interrupt controller.
11 - interrupts: List of interrupts in given SPMI peripheral.
12 - interrupt-names: Names specified to above list of interrupts in same
13 order. List of supported interrupt names are:
14 "cdc_spk_cnp_int" - Speaker click and pop interrupt.
15 "cdc_spk_clip_int" - Speaker clip interrupt.
16 "cdc_spk_ocp_int" - Speaker over current protect interrupt.
17 "mbhc_ins_rem_det1" - jack insert removal detect interrupt 1.
18 "mbhc_but_rel_det" - button release interrupt.
19 "mbhc_but_press_det" - button press event
20 "mbhc_ins_rem_det" - jack insert removal detect interrupt.
21 "mbhc_switch_int" - multi button headset interrupt.
22 "cdc_ear_ocp_int" - Earphone over current protect interrupt.
23 "cdc_hphr_ocp_int" - Headphone R over current protect interrupt.
24 "cdc_hphl_ocp_det" - Headphone L over current protect interrupt.
25 "cdc_ear_cnp_int" - earphone cnp interrupt.
26 "cdc_hphr_cnp_int" - hphr click and pop interrupt.
27 "cdc_hphl_cnp_int" - hphl click and pop interrupt.
28
29 - clocks: Handle to mclk.
30 - clock-names: should be "mclk"
31 - vdd-cdc-io-supply: phandle to VDD_CDC_IO regulator DT node.
32 - vdd-cdc-tx-rx-cx-supply: phandle to VDD_CDC_TX/RX/CX regulator DT node.
33 - vdd-micbias-supply: phandle of VDD_MICBIAS supply's regulator DT node.
34
35Optional Properties:
36- qcom,micbias1-ext-cap: boolean, present if micbias1 has external capacitor
37 connected.
38- qcom,micbias2-ext-cap: boolean, present if micbias2 has external capacitor
39 connected.
40
41Example:
42
43spmi_bus {
44 ...
45 audio-codec@f000{
46 compatible = "qcom,pm8916-wcd-analog-codec";
47 reg = <0xf000 0x200>;
48 reg-names = "pmic-codec-core";
49 clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>;
50 clock-names = "mclk";
51 interrupt-parent = <&spmi_bus>;
52 interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
53 <0x1 0xf0 0x1 IRQ_TYPE_NONE>,
54 <0x1 0xf0 0x2 IRQ_TYPE_NONE>,
55 <0x1 0xf0 0x3 IRQ_TYPE_NONE>,
56 <0x1 0xf0 0x4 IRQ_TYPE_NONE>,
57 <0x1 0xf0 0x5 IRQ_TYPE_NONE>,
58 <0x1 0xf0 0x6 IRQ_TYPE_NONE>,
59 <0x1 0xf0 0x7 IRQ_TYPE_NONE>,
60 <0x1 0xf1 0x0 IRQ_TYPE_NONE>,
61 <0x1 0xf1 0x1 IRQ_TYPE_NONE>,
62 <0x1 0xf1 0x2 IRQ_TYPE_NONE>,
63 <0x1 0xf1 0x3 IRQ_TYPE_NONE>,
64 <0x1 0xf1 0x4 IRQ_TYPE_NONE>,
65 <0x1 0xf1 0x5 IRQ_TYPE_NONE>;
66 interrupt-names = "cdc_spk_cnp_int",
67 "cdc_spk_clip_int",
68 "cdc_spk_ocp_int",
69 "mbhc_ins_rem_det1",
70 "mbhc_but_rel_det",
71 "mbhc_but_press_det",
72 "mbhc_ins_rem_det",
73 "mbhc_switch_int",
74 "cdc_ear_ocp_int",
75 "cdc_hphr_ocp_int",
76 "cdc_hphl_ocp_det",
77 "cdc_ear_cnp_int",
78 "cdc_hphr_cnp_int",
79 "cdc_hphl_cnp_int";
80 VDD-CDC-IO-supply = <&pm8916_l5>;
81 VDD-CDC-TX-RX-CX-supply = <&pm8916_l5>;
82 VDD-MICBIAS-supply = <&pm8916_l13>;
83 #sound-dai-cells = <1>;
84 };
85};
diff --git a/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-digital.txt b/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-digital.txt
new file mode 100644
index 000000000000..1c8e4cb25176
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-digital.txt
@@ -0,0 +1,20 @@
1msm8916 digital audio CODEC
2
3## Bindings for codec core in lpass:
4
5Required properties
6 - compatible = "qcom,msm8916-wcd-digital-codec";
7 - reg: address space for lpass codec.
8 - clocks: Handle to mclk and ahbclk
9 - clock-names: should be "mclk", "ahbix-clk".
10
11Example:
12
13audio-codec@771c000{
14 compatible = "qcom,msm8916-wcd-digital-codec";
15 reg = <0x0771c000 0x400>;
16 clocks = <&gcc GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK>,
17 <&gcc GCC_CODEC_DIGCODEC_CLK>;
18 clock-names = "ahbix-clk", "mclk";
19 #sound-dai-cells = <1>;
20};
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index 3314bf299a51..fb44d5215e30 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -120,7 +120,7 @@ static const struct regulator_linear_range rk808_ldo3_voltage_ranges[] = {
120static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev) 120static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev)
121{ 121{
122 struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev); 122 struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
123 int id = rdev->desc->id - RK808_ID_DCDC1; 123 int id = rdev_get_id(rdev);
124 struct gpio_desc *gpio = pdata->dvs_gpio[id]; 124 struct gpio_desc *gpio = pdata->dvs_gpio[id];
125 unsigned int val; 125 unsigned int val;
126 int ret; 126 int ret;
@@ -193,7 +193,7 @@ static int rk808_buck1_2_set_voltage_sel(struct regulator_dev *rdev,
193 unsigned sel) 193 unsigned sel)
194{ 194{
195 struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev); 195 struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
196 int id = rdev->desc->id - RK808_ID_DCDC1; 196 int id = rdev_get_id(rdev);
197 struct gpio_desc *gpio = pdata->dvs_gpio[id]; 197 struct gpio_desc *gpio = pdata->dvs_gpio[id];
198 unsigned int reg = rdev->desc->vsel_reg; 198 unsigned int reg = rdev->desc->vsel_reg;
199 unsigned old_sel; 199 unsigned old_sel;
@@ -232,7 +232,7 @@ static int rk808_buck1_2_set_voltage_time_sel(struct regulator_dev *rdev,
232 unsigned int new_selector) 232 unsigned int new_selector)
233{ 233{
234 struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev); 234 struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
235 int id = rdev->desc->id - RK808_ID_DCDC1; 235 int id = rdev_get_id(rdev);
236 struct gpio_desc *gpio = pdata->dvs_gpio[id]; 236 struct gpio_desc *gpio = pdata->dvs_gpio[id];
237 237
238 /* if there is no dvs1/2 pin, we don't need wait extra time here. */ 238 /* if there is no dvs1/2 pin, we don't need wait extra time here. */
@@ -245,8 +245,7 @@ static int rk808_buck1_2_set_voltage_time_sel(struct regulator_dev *rdev,
245static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) 245static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
246{ 246{
247 unsigned int ramp_value = RK808_RAMP_RATE_10MV_PER_US; 247 unsigned int ramp_value = RK808_RAMP_RATE_10MV_PER_US;
248 unsigned int reg = rk808_buck_config_regs[rdev->desc->id - 248 unsigned int reg = rk808_buck_config_regs[rdev_get_id(rdev)];
249 RK808_ID_DCDC1];
250 249
251 switch (ramp_delay) { 250 switch (ramp_delay) {
252 case 1 ... 2000: 251 case 1 ... 2000:
diff --git a/include/sound/soc.h b/include/sound/soc.h
index bd2227ad64a9..42339c0f3532 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1644,25 +1644,43 @@ static inline struct snd_soc_platform *snd_soc_kcontrol_platform(
1644int snd_soc_util_init(void); 1644int snd_soc_util_init(void);
1645void snd_soc_util_exit(void); 1645void snd_soc_util_exit(void);
1646 1646
1647int snd_soc_of_parse_card_name(struct snd_soc_card *card, 1647#define snd_soc_of_parse_card_name(card, propname) \
1648 const char *propname); 1648 snd_soc_of_parse_card_name_from_node(card, NULL, propname)
1649int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, 1649int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card,
1650 const char *propname); 1650 struct device_node *np,
1651 const char *propname);
1652#define snd_soc_of_parse_audio_simple_widgets(card, propname)\
1653 snd_soc_of_parse_audio_simple_widgets_from_node(card, NULL, propname)
1654int snd_soc_of_parse_audio_simple_widgets_from_node(struct snd_soc_card *card,
1655 struct device_node *np,
1656 const char *propname);
1657
1651int snd_soc_of_parse_tdm_slot(struct device_node *np, 1658int snd_soc_of_parse_tdm_slot(struct device_node *np,
1652 unsigned int *tx_mask, 1659 unsigned int *tx_mask,
1653 unsigned int *rx_mask, 1660 unsigned int *rx_mask,
1654 unsigned int *slots, 1661 unsigned int *slots,
1655 unsigned int *slot_width); 1662 unsigned int *slot_width);
1656void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card, 1663#define snd_soc_of_parse_audio_prefix(card, codec_conf, of_node, propname) \
1664 snd_soc_of_parse_audio_prefix_from_node(card, NULL, codec_conf, \
1665 of_node, propname)
1666void snd_soc_of_parse_audio_prefix_from_node(struct snd_soc_card *card,
1667 struct device_node *np,
1657 struct snd_soc_codec_conf *codec_conf, 1668 struct snd_soc_codec_conf *codec_conf,
1658 struct device_node *of_node, 1669 struct device_node *of_node,
1659 const char *propname); 1670 const char *propname);
1660int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, 1671
1661 const char *propname); 1672#define snd_soc_of_parse_audio_routing(card, propname) \
1673 snd_soc_of_parse_audio_routing_from_node(card, NULL, propname)
1674int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card,
1675 struct device_node *np,
1676 const char *propname);
1677
1662unsigned int snd_soc_of_parse_daifmt(struct device_node *np, 1678unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
1663 const char *prefix, 1679 const char *prefix,
1664 struct device_node **bitclkmaster, 1680 struct device_node **bitclkmaster,
1665 struct device_node **framemaster); 1681 struct device_node **framemaster);
1682int snd_soc_get_dai_name(struct of_phandle_args *args,
1683 const char **dai_name);
1666int snd_soc_of_get_dai_name(struct device_node *of_node, 1684int snd_soc_of_get_dai_name(struct device_node *of_node,
1667 const char **dai_name); 1685 const char **dai_name);
1668int snd_soc_of_get_dai_link_codecs(struct device *dev, 1686int snd_soc_of_get_dai_link_codecs(struct device *dev,
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index fb96959665fa..b70ae9abbc80 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -592,6 +592,13 @@ config SND_SOC_MAX9860
592 depends on I2C 592 depends on I2C
593 select REGMAP_I2C 593 select REGMAP_I2C
594 594
595config SND_SOC_MSM8916_WCD_ANALOG
596 tristate "Qualcomm MSM8916 WCD Analog Codec"
597 depends on SPMI || COMPILE_TEST
598
599config SND_SOC_MSM8916_WCD_DIGITAL
600 tristate "Qualcomm MSM8916 WCD DIGITAL Codec"
601
595config SND_SOC_PCM1681 602config SND_SOC_PCM1681
596 tristate "Texas Instruments PCM1681 CODEC" 603 tristate "Texas Instruments PCM1681 CODEC"
597 depends on I2C 604 depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 4bcafc345248..0abfa80afe2f 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -88,6 +88,8 @@ snd-soc-max9850-objs := max9850.o
88snd-soc-max9860-objs := max9860.o 88snd-soc-max9860-objs := max9860.o
89snd-soc-mc13783-objs := mc13783.o 89snd-soc-mc13783-objs := mc13783.o
90snd-soc-ml26124-objs := ml26124.o 90snd-soc-ml26124-objs := ml26124.o
91snd-soc-msm8916-analog-objs := msm8916-wcd-analog.o
92snd-soc-msm8916-digital-objs := msm8916-wcd-digital.o
91snd-soc-nau8810-objs := nau8810.o 93snd-soc-nau8810-objs := nau8810.o
92snd-soc-nau8825-objs := nau8825.o 94snd-soc-nau8825-objs := nau8825.o
93snd-soc-hdmi-codec-objs := hdmi-codec.o 95snd-soc-hdmi-codec-objs := hdmi-codec.o
@@ -216,7 +218,6 @@ snd-soc-wm9705-objs := wm9705.o
216snd-soc-wm9712-objs := wm9712.o 218snd-soc-wm9712-objs := wm9712.o
217snd-soc-wm9713-objs := wm9713.o 219snd-soc-wm9713-objs := wm9713.o
218snd-soc-wm-hubs-objs := wm_hubs.o 220snd-soc-wm-hubs-objs := wm_hubs.o
219
220# Amp 221# Amp
221snd-soc-max9877-objs := max9877.o 222snd-soc-max9877-objs := max9877.o
222snd-soc-max98504-objs := max98504.o 223snd-soc-max98504-objs := max98504.o
@@ -314,6 +315,8 @@ obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
314obj-$(CONFIG_SND_SOC_MAX9860) += snd-soc-max9860.o 315obj-$(CONFIG_SND_SOC_MAX9860) += snd-soc-max9860.o
315obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o 316obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
316obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o 317obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
318obj-$(CONFIG_SND_SOC_MSM8916_WCD_ANALOG) +=snd-soc-msm8916-analog.o
319obj-$(CONFIG_SND_SOC_MSM8916_WCD_DIGITAL) +=snd-soc-msm8916-digital.o
317obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o 320obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o
318obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o 321obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o
319obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o 322obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c
new file mode 100644
index 000000000000..d8e8590746af
--- /dev/null
+++ b/sound/soc/codecs/msm8916-wcd-analog.c
@@ -0,0 +1,890 @@
1#include <linux/module.h>
2#include <linux/err.h>
3#include <linux/kernel.h>
4#include <linux/delay.h>
5#include <linux/regulator/consumer.h>
6#include <linux/types.h>
7#include <linux/clk.h>
8#include <linux/of.h>
9#include <linux/platform_device.h>
10#include <linux/regmap.h>
11#include <sound/soc.h>
12#include <sound/pcm.h>
13#include <sound/pcm_params.h>
14#include <sound/tlv.h>
15
16#define CDC_D_REVISION1 (0xf000)
17#define CDC_D_PERPH_SUBTYPE (0xf005)
18#define CDC_D_CDC_RST_CTL (0xf046)
19#define RST_CTL_DIG_SW_RST_N_MASK BIT(7)
20#define RST_CTL_DIG_SW_RST_N_RESET 0
21#define RST_CTL_DIG_SW_RST_N_REMOVE_RESET BIT(7)
22
23#define CDC_D_CDC_TOP_CLK_CTL (0xf048)
24#define TOP_CLK_CTL_A_MCLK_MCLK2_EN_MASK (BIT(2) | BIT(3))
25#define TOP_CLK_CTL_A_MCLK_EN_ENABLE BIT(2)
26#define TOP_CLK_CTL_A_MCLK2_EN_ENABLE BIT(3)
27
28#define CDC_D_CDC_ANA_CLK_CTL (0xf049)
29#define ANA_CLK_CTL_EAR_HPHR_CLK_EN_MASK BIT(0)
30#define ANA_CLK_CTL_EAR_HPHR_CLK_EN BIT(0)
31#define ANA_CLK_CTL_EAR_HPHL_CLK_EN BIT(1)
32#define ANA_CLK_CTL_SPKR_CLK_EN_MASK BIT(4)
33#define ANA_CLK_CTL_SPKR_CLK_EN BIT(4)
34#define ANA_CLK_CTL_TXA_CLK25_EN BIT(5)
35
36#define CDC_D_CDC_DIG_CLK_CTL (0xf04A)
37#define DIG_CLK_CTL_RXD1_CLK_EN BIT(0)
38#define DIG_CLK_CTL_RXD2_CLK_EN BIT(1)
39#define DIG_CLK_CTL_RXD3_CLK_EN BIT(3)
40#define DIG_CLK_CTL_TXD_CLK_EN BIT(4)
41#define DIG_CLK_CTL_NCP_CLK_EN_MASK BIT(6)
42#define DIG_CLK_CTL_NCP_CLK_EN BIT(6)
43#define DIG_CLK_CTL_RXD_PDM_CLK_EN_MASK BIT(7)
44#define DIG_CLK_CTL_RXD_PDM_CLK_EN BIT(7)
45
46#define CDC_D_CDC_CONN_TX1_CTL (0xf050)
47#define CONN_TX1_SERIAL_TX1_MUX GENMASK(1, 0)
48#define CONN_TX1_SERIAL_TX1_ADC_1 0x0
49#define CONN_TX1_SERIAL_TX1_RX_PDM_LB 0x1
50#define CONN_TX1_SERIAL_TX1_ZERO 0x2
51
52#define CDC_D_CDC_CONN_TX2_CTL (0xf051)
53#define CONN_TX2_SERIAL_TX2_MUX GENMASK(1, 0)
54#define CONN_TX2_SERIAL_TX2_ADC_2 0x0
55#define CONN_TX2_SERIAL_TX2_RX_PDM_LB 0x1
56#define CONN_TX2_SERIAL_TX2_ZERO 0x2
57#define CDC_D_CDC_CONN_HPHR_DAC_CTL (0xf052)
58#define CDC_D_CDC_CONN_RX1_CTL (0xf053)
59#define CDC_D_CDC_CONN_RX2_CTL (0xf054)
60#define CDC_D_CDC_CONN_RX3_CTL (0xf055)
61#define CDC_D_CDC_CONN_RX_LB_CTL (0xf056)
62#define CDC_D_SEC_ACCESS (0xf0D0)
63#define CDC_D_PERPH_RESET_CTL3 (0xf0DA)
64#define CDC_D_PERPH_RESET_CTL4 (0xf0DB)
65#define CDC_A_REVISION1 (0xf100)
66#define CDC_A_REVISION2 (0xf101)
67#define CDC_A_REVISION3 (0xf102)
68#define CDC_A_REVISION4 (0xf103)
69#define CDC_A_PERPH_TYPE (0xf104)
70#define CDC_A_PERPH_SUBTYPE (0xf105)
71#define CDC_A_INT_RT_STS (0xf110)
72#define CDC_A_INT_SET_TYPE (0xf111)
73#define CDC_A_INT_POLARITY_HIGH (0xf112)
74#define CDC_A_INT_POLARITY_LOW (0xf113)
75#define CDC_A_INT_LATCHED_CLR (0xf114)
76#define CDC_A_INT_EN_SET (0xf115)
77#define CDC_A_INT_EN_CLR (0xf116)
78#define CDC_A_INT_LATCHED_STS (0xf118)
79#define CDC_A_INT_PENDING_STS (0xf119)
80#define CDC_A_INT_MID_SEL (0xf11A)
81#define CDC_A_INT_PRIORITY (0xf11B)
82#define CDC_A_MICB_1_EN (0xf140)
83#define MICB_1_EN_MICB_ENABLE BIT(7)
84#define MICB_1_EN_BYP_CAP_MASK BIT(6)
85#define MICB_1_EN_NO_EXT_BYP_CAP BIT(6)
86#define MICB_1_EN_EXT_BYP_CAP 0
87#define MICB_1_EN_PULL_DOWN_EN_MASK BIT(5)
88#define MICB_1_EN_PULL_DOWN_EN_ENABLE BIT(5)
89#define MICB_1_EN_OPA_STG2_TAIL_CURR_MASK GENMASK(3, 1)
90#define MICB_1_EN_OPA_STG2_TAIL_CURR_1_60UA (0x4)
91#define MICB_1_EN_PULL_UP_EN_MASK BIT(4)
92#define MICB_1_EN_TX3_GND_SEL_MASK BIT(0)
93#define MICB_1_EN_TX3_GND_SEL_TX_GND 0
94
95#define CDC_A_MICB_1_VAL (0xf141)
96#define MICB_1_VAL_MICB_OUT_VAL_MASK GENMASK(7, 3)
97#define MICB_1_VAL_MICB_OUT_VAL_V2P70V ((0x16) << 3)
98#define CDC_A_MICB_1_CTL (0xf142)
99
100#define MICB_1_CTL_CFILT_REF_SEL_MASK BIT(1)
101#define MICB_1_CTL_CFILT_REF_SEL_HPF_REF BIT(1)
102#define MICB_1_CTL_EXT_PRECHARG_EN_MASK BIT(5)
103#define MICB_1_CTL_EXT_PRECHARG_EN_ENABLE BIT(5)
104#define MICB_1_CTL_INT_PRECHARG_BYP_MASK BIT(6)
105#define MICB_1_CTL_INT_PRECHARG_BYP_EXT_PRECHRG_SEL BIT(6)
106
107#define CDC_A_MICB_1_INT_RBIAS (0xf143)
108#define MICB_1_INT_TX1_INT_RBIAS_EN_MASK BIT(7)
109#define MICB_1_INT_TX1_INT_RBIAS_EN_ENABLE BIT(7)
110#define MICB_1_INT_TX1_INT_RBIAS_EN_DISABLE 0
111
112#define MICB_1_INT_TX1_INT_PULLUP_EN_MASK BIT(6)
113#define MICB_1_INT_TX1_INT_PULLUP_EN_TX1N_TO_MICBIAS BIT(6)
114#define MICB_1_INT_TX1_INT_PULLUP_EN_TX1N_TO_GND 0
115
116#define MICB_1_INT_TX2_INT_RBIAS_EN_MASK BIT(4)
117#define MICB_1_INT_TX2_INT_RBIAS_EN_ENABLE BIT(4)
118#define MICB_1_INT_TX2_INT_RBIAS_EN_DISABLE 0
119#define MICB_1_INT_TX2_INT_PULLUP_EN_MASK BIT(3)
120#define MICB_1_INT_TX2_INT_PULLUP_EN_TX1N_TO_MICBIAS BIT(3)
121#define MICB_1_INT_TX2_INT_PULLUP_EN_TX1N_TO_GND 0
122
123#define MICB_1_INT_TX3_INT_RBIAS_EN_MASK BIT(1)
124#define MICB_1_INT_TX3_INT_RBIAS_EN_ENABLE BIT(1)
125#define MICB_1_INT_TX3_INT_RBIAS_EN_DISABLE 0
126#define MICB_1_INT_TX3_INT_PULLUP_EN_MASK BIT(0)
127#define MICB_1_INT_TX3_INT_PULLUP_EN_TX1N_TO_MICBIAS BIT(0)
128#define MICB_1_INT_TX3_INT_PULLUP_EN_TX1N_TO_GND 0
129
130#define CDC_A_MICB_2_EN (0xf144)
131#define CDC_A_TX_1_2_ATEST_CTL_2 (0xf145)
132#define CDC_A_MASTER_BIAS_CTL (0xf146)
133#define CDC_A_TX_1_EN (0xf160)
134#define CDC_A_TX_2_EN (0xf161)
135#define CDC_A_TX_1_2_TEST_CTL_1 (0xf162)
136#define CDC_A_TX_1_2_TEST_CTL_2 (0xf163)
137#define CDC_A_TX_1_2_ATEST_CTL (0xf164)
138#define CDC_A_TX_1_2_OPAMP_BIAS (0xf165)
139#define CDC_A_TX_3_EN (0xf167)
140#define CDC_A_NCP_EN (0xf180)
141#define CDC_A_NCP_CLK (0xf181)
142#define CDC_A_NCP_FBCTRL (0xf183)
143#define CDC_A_NCP_FBCTRL_FB_CLK_INV_MASK BIT(5)
144#define CDC_A_NCP_FBCTRL_FB_CLK_INV BIT(5)
145#define CDC_A_NCP_BIAS (0xf184)
146#define CDC_A_NCP_VCTRL (0xf185)
147#define CDC_A_NCP_TEST (0xf186)
148#define CDC_A_NCP_CLIM_ADDR (0xf187)
149#define CDC_A_RX_CLOCK_DIVIDER (0xf190)
150#define CDC_A_RX_COM_OCP_CTL (0xf191)
151#define CDC_A_RX_COM_OCP_COUNT (0xf192)
152#define CDC_A_RX_COM_BIAS_DAC (0xf193)
153#define RX_COM_BIAS_DAC_RX_BIAS_EN_MASK BIT(7)
154#define RX_COM_BIAS_DAC_RX_BIAS_EN_ENABLE BIT(7)
155#define RX_COM_BIAS_DAC_DAC_REF_EN_MASK BIT(0)
156#define RX_COM_BIAS_DAC_DAC_REF_EN_ENABLE BIT(0)
157
158#define CDC_A_RX_HPH_BIAS_PA (0xf194)
159#define CDC_A_RX_HPH_BIAS_LDO_OCP (0xf195)
160#define CDC_A_RX_HPH_BIAS_CNP (0xf196)
161#define CDC_A_RX_HPH_CNP_EN (0xf197)
162#define CDC_A_RX_HPH_L_PA_DAC_CTL (0xf19B)
163#define RX_HPA_L_PA_DAC_CTL_DATA_RESET_MASK BIT(1)
164#define RX_HPA_L_PA_DAC_CTL_DATA_RESET_RESET BIT(1)
165#define CDC_A_RX_HPH_R_PA_DAC_CTL (0xf19D)
166#define RX_HPH_R_PA_DAC_CTL_DATA_RESET BIT(1)
167#define RX_HPH_R_PA_DAC_CTL_DATA_RESET_MASK BIT(1)
168
169#define CDC_A_RX_EAR_CTL (0xf19E)
170#define RX_EAR_CTL_SPK_VBAT_LDO_EN_MASK BIT(0)
171#define RX_EAR_CTL_SPK_VBAT_LDO_EN_ENABLE BIT(0)
172
173#define CDC_A_SPKR_DAC_CTL (0xf1B0)
174#define SPKR_DAC_CTL_DAC_RESET_MASK BIT(4)
175#define SPKR_DAC_CTL_DAC_RESET_NORMAL 0
176
177#define CDC_A_SPKR_DRV_CTL (0xf1B2)
178#define SPKR_DRV_CTL_DEF_MASK 0xEF
179#define SPKR_DRV_CLASSD_PA_EN_MASK BIT(7)
180#define SPKR_DRV_CLASSD_PA_EN_ENABLE BIT(7)
181#define SPKR_DRV_CAL_EN BIT(6)
182#define SPKR_DRV_SETTLE_EN BIT(5)
183#define SPKR_DRV_FW_EN BIT(3)
184#define SPKR_DRV_BOOST_SET BIT(2)
185#define SPKR_DRV_CMFB_SET BIT(1)
186#define SPKR_DRV_GAIN_SET BIT(0)
187#define SPKR_DRV_CTL_DEF_VAL (SPKR_DRV_CLASSD_PA_EN_ENABLE | \
188 SPKR_DRV_CAL_EN | SPKR_DRV_SETTLE_EN | \
189 SPKR_DRV_FW_EN | SPKR_DRV_BOOST_SET | \
190 SPKR_DRV_CMFB_SET | SPKR_DRV_GAIN_SET)
191#define CDC_A_SPKR_OCP_CTL (0xf1B4)
192#define CDC_A_SPKR_PWRSTG_CTL (0xf1B5)
193#define SPKR_PWRSTG_CTL_DAC_EN_MASK BIT(0)
194#define SPKR_PWRSTG_CTL_DAC_EN BIT(0)
195#define SPKR_PWRSTG_CTL_MASK 0xE0
196#define SPKR_PWRSTG_CTL_BBM_MASK BIT(7)
197#define SPKR_PWRSTG_CTL_BBM_EN BIT(7)
198#define SPKR_PWRSTG_CTL_HBRDGE_EN_MASK BIT(6)
199#define SPKR_PWRSTG_CTL_HBRDGE_EN BIT(6)
200#define SPKR_PWRSTG_CTL_CLAMP_EN_MASK BIT(5)
201#define SPKR_PWRSTG_CTL_CLAMP_EN BIT(5)
202
203#define CDC_A_SPKR_DRV_DBG (0xf1B7)
204#define CDC_A_CURRENT_LIMIT (0xf1C0)
205#define CDC_A_BOOST_EN_CTL (0xf1C3)
206#define CDC_A_SLOPE_COMP_IP_ZERO (0xf1C4)
207#define CDC_A_SEC_ACCESS (0xf1D0)
208#define CDC_A_PERPH_RESET_CTL3 (0xf1DA)
209#define CDC_A_PERPH_RESET_CTL4 (0xf1DB)
210
211#define MSM8916_WCD_ANALOG_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
212 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
213#define MSM8916_WCD_ANALOG_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
214 SNDRV_PCM_FMTBIT_S24_LE)
215
216static const char * const supply_names[] = {
217 "vdd-cdc-io",
218 "vdd-cdc-tx-rx-cx",
219};
220
221struct pm8916_wcd_analog_priv {
222 u16 pmic_rev;
223 u16 codec_version;
224 struct clk *mclk;
225 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
226 bool micbias1_cap_mode;
227 bool micbias2_cap_mode;
228};
229
230static const char *const adc2_mux_text[] = { "ZERO", "INP2", "INP3" };
231static const char *const rdac2_mux_text[] = { "ZERO", "RX2", "RX1" };
232static const char *const hph_text[] = { "ZERO", "Switch", };
233
234static const struct soc_enum hph_enum = SOC_ENUM_SINGLE_VIRT(
235 ARRAY_SIZE(hph_text), hph_text);
236
237static const struct snd_kcontrol_new hphl_mux = SOC_DAPM_ENUM("HPHL", hph_enum);
238static const struct snd_kcontrol_new hphr_mux = SOC_DAPM_ENUM("HPHR", hph_enum);
239
240/* ADC2 MUX */
241static const struct soc_enum adc2_enum = SOC_ENUM_SINGLE_VIRT(
242 ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
243
244/* RDAC2 MUX */
245static const struct soc_enum rdac2_mux_enum = SOC_ENUM_SINGLE(
246 CDC_D_CDC_CONN_HPHR_DAC_CTL, 0, 3, rdac2_mux_text);
247
248static const struct snd_kcontrol_new spkr_switch[] = {
249 SOC_DAPM_SINGLE("Switch", CDC_A_SPKR_DAC_CTL, 7, 1, 0)
250};
251
252static const struct snd_kcontrol_new rdac2_mux = SOC_DAPM_ENUM(
253 "RDAC2 MUX Mux", rdac2_mux_enum);
254static const struct snd_kcontrol_new tx_adc2_mux = SOC_DAPM_ENUM(
255 "ADC2 MUX Mux", adc2_enum);
256
257/* Analog Gain control 0 dB to +24 dB in 6 dB steps */
258static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 600, 0);
259
260static const struct snd_kcontrol_new pm8916_wcd_analog_snd_controls[] = {
261 SOC_SINGLE_TLV("ADC1 Volume", CDC_A_TX_1_EN, 3, 8, 0, analog_gain),
262 SOC_SINGLE_TLV("ADC2 Volume", CDC_A_TX_2_EN, 3, 8, 0, analog_gain),
263 SOC_SINGLE_TLV("ADC3 Volume", CDC_A_TX_3_EN, 3, 8, 0, analog_gain),
264};
265
266static void pm8916_wcd_analog_micbias_enable(struct snd_soc_codec *codec)
267{
268 snd_soc_update_bits(codec, CDC_A_MICB_1_CTL,
269 MICB_1_CTL_EXT_PRECHARG_EN_MASK |
270 MICB_1_CTL_INT_PRECHARG_BYP_MASK,
271 MICB_1_CTL_INT_PRECHARG_BYP_EXT_PRECHRG_SEL
272 | MICB_1_CTL_EXT_PRECHARG_EN_ENABLE);
273
274 snd_soc_write(codec, CDC_A_MICB_1_VAL, MICB_1_VAL_MICB_OUT_VAL_V2P70V);
275 /*
276 * Special headset needs MICBIAS as 2.7V so wait for
277 * 50 msec for the MICBIAS to reach 2.7 volts.
278 */
279 msleep(50);
280 snd_soc_update_bits(codec, CDC_A_MICB_1_CTL,
281 MICB_1_CTL_EXT_PRECHARG_EN_MASK |
282 MICB_1_CTL_INT_PRECHARG_BYP_MASK, 0);
283
284}
285
286static int pm8916_wcd_analog_enable_micbias_ext(struct snd_soc_codec
287 *codec, int event,
288 int reg, u32 cap_mode)
289{
290 switch (event) {
291 case SND_SOC_DAPM_POST_PMU:
292 pm8916_wcd_analog_micbias_enable(codec);
293 snd_soc_update_bits(codec, CDC_A_MICB_1_EN,
294 MICB_1_EN_BYP_CAP_MASK, cap_mode);
295 break;
296 }
297
298 return 0;
299}
300
301static int pm8916_wcd_analog_enable_micbias_int(struct snd_soc_codec
302 *codec, int event,
303 int reg, u32 cap_mode)
304{
305
306 switch (event) {
307 case SND_SOC_DAPM_PRE_PMU:
308 snd_soc_update_bits(codec, CDC_A_MICB_1_INT_RBIAS,
309 MICB_1_INT_TX2_INT_RBIAS_EN_MASK,
310 MICB_1_INT_TX2_INT_RBIAS_EN_ENABLE);
311 snd_soc_update_bits(codec, reg, MICB_1_EN_PULL_DOWN_EN_MASK, 0);
312 snd_soc_update_bits(codec, CDC_A_MICB_1_EN,
313 MICB_1_EN_OPA_STG2_TAIL_CURR_MASK,
314 MICB_1_EN_OPA_STG2_TAIL_CURR_1_60UA);
315
316 break;
317 case SND_SOC_DAPM_POST_PMU:
318 pm8916_wcd_analog_micbias_enable(codec);
319 snd_soc_update_bits(codec, CDC_A_MICB_1_EN,
320 MICB_1_EN_BYP_CAP_MASK, cap_mode);
321 break;
322 }
323
324 return 0;
325}
326
327static int pm8916_wcd_analog_enable_micbias_ext1(struct
328 snd_soc_dapm_widget
329 *w, struct snd_kcontrol
330 *kcontrol, int event)
331{
332 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
333 struct pm8916_wcd_analog_priv *wcd = snd_soc_codec_get_drvdata(codec);
334
335 return pm8916_wcd_analog_enable_micbias_ext(codec, event, w->reg,
336 wcd->micbias1_cap_mode);
337}
338
339static int pm8916_wcd_analog_enable_micbias_ext2(struct
340 snd_soc_dapm_widget
341 *w, struct snd_kcontrol
342 *kcontrol, int event)
343{
344 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
345 struct pm8916_wcd_analog_priv *wcd = snd_soc_codec_get_drvdata(codec);
346
347 return pm8916_wcd_analog_enable_micbias_ext(codec, event, w->reg,
348 wcd->micbias2_cap_mode);
349
350}
351
352static int pm8916_wcd_analog_enable_micbias_int1(struct
353 snd_soc_dapm_widget
354 *w, struct snd_kcontrol
355 *kcontrol, int event)
356{
357 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
358 struct pm8916_wcd_analog_priv *wcd = snd_soc_codec_get_drvdata(codec);
359
360 return pm8916_wcd_analog_enable_micbias_int(codec, event, w->reg,
361 wcd->micbias1_cap_mode);
362}
363
364static int pm8916_wcd_analog_enable_micbias_int2(struct
365 snd_soc_dapm_widget
366 *w, struct snd_kcontrol
367 *kcontrol, int event)
368{
369 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
370 struct pm8916_wcd_analog_priv *wcd = snd_soc_codec_get_drvdata(codec);
371
372 return pm8916_wcd_analog_enable_micbias_int(codec, event, w->reg,
373 wcd->micbias2_cap_mode);
374}
375
376static int pm8916_wcd_analog_enable_adc(struct snd_soc_dapm_widget *w,
377 struct snd_kcontrol *kcontrol,
378 int event)
379{
380 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
381 u16 adc_reg = CDC_A_TX_1_2_TEST_CTL_2;
382 u8 init_bit_shift;
383
384 if (w->reg == CDC_A_TX_1_EN)
385 init_bit_shift = 5;
386 else
387 init_bit_shift = 4;
388
389 switch (event) {
390 case SND_SOC_DAPM_PRE_PMU:
391 if (w->reg == CDC_A_TX_2_EN)
392 snd_soc_update_bits(codec, CDC_A_MICB_1_CTL,
393 MICB_1_CTL_CFILT_REF_SEL_MASK,
394 MICB_1_CTL_CFILT_REF_SEL_HPF_REF);
395 /*
396 * Add delay of 10 ms to give sufficient time for the voltage
397 * to shoot up and settle so that the txfe init does not
398 * happen when the input voltage is changing too much.
399 */
400 usleep_range(10000, 10010);
401 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
402 1 << init_bit_shift);
403 switch (w->reg) {
404 case CDC_A_TX_1_EN:
405 snd_soc_update_bits(codec, CDC_D_CDC_CONN_TX1_CTL,
406 CONN_TX1_SERIAL_TX1_MUX,
407 CONN_TX1_SERIAL_TX1_ADC_1);
408 break;
409 case CDC_A_TX_2_EN:
410 case CDC_A_TX_3_EN:
411 snd_soc_update_bits(codec, CDC_D_CDC_CONN_TX2_CTL,
412 CONN_TX2_SERIAL_TX2_MUX,
413 CONN_TX2_SERIAL_TX2_ADC_2);
414 break;
415 }
416 break;
417 case SND_SOC_DAPM_POST_PMU:
418 /*
419 * Add delay of 12 ms before deasserting the init
420 * to reduce the tx pop
421 */
422 usleep_range(12000, 12010);
423 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
424 break;
425 case SND_SOC_DAPM_POST_PMD:
426 switch (w->reg) {
427 case CDC_A_TX_1_EN:
428 snd_soc_update_bits(codec, CDC_D_CDC_CONN_TX1_CTL,
429 CONN_TX1_SERIAL_TX1_MUX,
430 CONN_TX1_SERIAL_TX1_ZERO);
431 break;
432 case CDC_A_TX_2_EN:
433 snd_soc_update_bits(codec, CDC_A_MICB_1_CTL,
434 MICB_1_CTL_CFILT_REF_SEL_MASK, 0);
435 case CDC_A_TX_3_EN:
436 snd_soc_update_bits(codec, CDC_D_CDC_CONN_TX2_CTL,
437 CONN_TX2_SERIAL_TX2_MUX,
438 CONN_TX2_SERIAL_TX2_ZERO);
439 break;
440 }
441
442
443 break;
444 }
445 return 0;
446}
447
448static int pm8916_wcd_analog_enable_spk_pa(struct snd_soc_dapm_widget *w,
449 struct snd_kcontrol *kcontrol,
450 int event)
451{
452 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
453
454 switch (event) {
455 case SND_SOC_DAPM_PRE_PMU:
456 snd_soc_update_bits(codec, CDC_A_SPKR_PWRSTG_CTL,
457 SPKR_PWRSTG_CTL_DAC_EN_MASK |
458 SPKR_PWRSTG_CTL_BBM_MASK |
459 SPKR_PWRSTG_CTL_HBRDGE_EN_MASK |
460 SPKR_PWRSTG_CTL_CLAMP_EN_MASK,
461 SPKR_PWRSTG_CTL_DAC_EN|
462 SPKR_PWRSTG_CTL_BBM_EN |
463 SPKR_PWRSTG_CTL_HBRDGE_EN |
464 SPKR_PWRSTG_CTL_CLAMP_EN);
465
466 snd_soc_update_bits(codec, CDC_A_RX_EAR_CTL,
467 RX_EAR_CTL_SPK_VBAT_LDO_EN_MASK,
468 RX_EAR_CTL_SPK_VBAT_LDO_EN_ENABLE);
469 break;
470 case SND_SOC_DAPM_POST_PMU:
471 snd_soc_update_bits(codec, CDC_A_SPKR_DRV_CTL,
472 SPKR_DRV_CTL_DEF_MASK,
473 SPKR_DRV_CTL_DEF_VAL);
474 snd_soc_update_bits(codec, w->reg,
475 SPKR_DRV_CLASSD_PA_EN_MASK,
476 SPKR_DRV_CLASSD_PA_EN_ENABLE);
477 break;
478 case SND_SOC_DAPM_POST_PMD:
479 snd_soc_update_bits(codec, CDC_A_SPKR_PWRSTG_CTL,
480 SPKR_PWRSTG_CTL_DAC_EN_MASK|
481 SPKR_PWRSTG_CTL_BBM_MASK |
482 SPKR_PWRSTG_CTL_HBRDGE_EN_MASK |
483 SPKR_PWRSTG_CTL_CLAMP_EN_MASK, 0);
484
485 snd_soc_update_bits(codec, CDC_A_SPKR_DAC_CTL,
486 SPKR_DAC_CTL_DAC_RESET_MASK,
487 SPKR_DAC_CTL_DAC_RESET_NORMAL);
488 snd_soc_update_bits(codec, CDC_A_RX_EAR_CTL,
489 RX_EAR_CTL_SPK_VBAT_LDO_EN_MASK, 0);
490 break;
491 }
492 return 0;
493}
494
495static const struct reg_default wcd_reg_defaults_2_0[] = {
496 {CDC_A_RX_COM_OCP_CTL, 0xD1},
497 {CDC_A_RX_COM_OCP_COUNT, 0xFF},
498 {CDC_D_SEC_ACCESS, 0xA5},
499 {CDC_D_PERPH_RESET_CTL3, 0x0F},
500 {CDC_A_TX_1_2_OPAMP_BIAS, 0x4F},
501 {CDC_A_NCP_FBCTRL, 0x28},
502 {CDC_A_SPKR_DRV_CTL, 0x69},
503 {CDC_A_SPKR_DRV_DBG, 0x01},
504 {CDC_A_BOOST_EN_CTL, 0x5F},
505 {CDC_A_SLOPE_COMP_IP_ZERO, 0x88},
506 {CDC_A_SEC_ACCESS, 0xA5},
507 {CDC_A_PERPH_RESET_CTL3, 0x0F},
508 {CDC_A_CURRENT_LIMIT, 0x82},
509 {CDC_A_SPKR_DAC_CTL, 0x03},
510 {CDC_A_SPKR_OCP_CTL, 0xE1},
511 {CDC_A_MASTER_BIAS_CTL, 0x30},
512};
513
514static int pm8916_wcd_analog_probe(struct snd_soc_codec *codec)
515{
516 struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(codec->dev);
517 int err, reg;
518
519 err = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
520 if (err != 0) {
521 dev_err(codec->dev, "failed to enable regulators (%d)\n", err);
522 return err;
523 }
524
525 snd_soc_codec_set_drvdata(codec, priv);
526 priv->pmic_rev = snd_soc_read(codec, CDC_D_REVISION1);
527 priv->codec_version = snd_soc_read(codec, CDC_D_PERPH_SUBTYPE);
528
529 dev_info(codec->dev, "PMIC REV: %d\t CODEC Version: %d\n",
530 priv->pmic_rev, priv->codec_version);
531
532 snd_soc_write(codec, CDC_D_PERPH_RESET_CTL4, 0x01);
533 snd_soc_write(codec, CDC_A_PERPH_RESET_CTL4, 0x01);
534
535 for (reg = 0; reg < ARRAY_SIZE(wcd_reg_defaults_2_0); reg++)
536 snd_soc_write(codec, wcd_reg_defaults_2_0[reg].reg,
537 wcd_reg_defaults_2_0[reg].def);
538
539 return 0;
540}
541
542static int pm8916_wcd_analog_remove(struct snd_soc_codec *codec)
543{
544 struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(codec->dev);
545
546 return regulator_bulk_disable(ARRAY_SIZE(priv->supplies),
547 priv->supplies);
548}
549
550static const struct snd_soc_dapm_route pm8916_wcd_analog_audio_map[] = {
551
552 {"PDM_RX1", NULL, "PDM Playback"},
553 {"PDM_RX2", NULL, "PDM Playback"},
554 {"PDM_RX3", NULL, "PDM Playback"},
555 {"PDM Capture", NULL, "PDM_TX"},
556
557 /* ADC Connections */
558 {"PDM_TX", NULL, "ADC2"},
559 {"PDM_TX", NULL, "ADC3"},
560 {"ADC2", NULL, "ADC2 MUX"},
561 {"ADC3", NULL, "ADC2 MUX"},
562 {"ADC2 MUX", "INP2", "ADC2_INP2"},
563 {"ADC2 MUX", "INP3", "ADC2_INP3"},
564
565 {"PDM_TX", NULL, "ADC1"},
566 {"ADC1", NULL, "AMIC1"},
567 {"ADC2_INP2", NULL, "AMIC2"},
568 {"ADC2_INP3", NULL, "AMIC3"},
569
570 /* RDAC Connections */
571 {"HPHR DAC", NULL, "RDAC2 MUX"},
572 {"RDAC2 MUX", "RX1", "PDM_RX1"},
573 {"RDAC2 MUX", "RX2", "PDM_RX2"},
574 {"HPHL DAC", NULL, "PDM_RX1"},
575 {"PDM_RX1", NULL, "RXD1_CLK"},
576 {"PDM_RX2", NULL, "RXD2_CLK"},
577 {"PDM_RX3", NULL, "RXD3_CLK"},
578
579 {"PDM_RX1", NULL, "RXD_PDM_CLK"},
580 {"PDM_RX2", NULL, "RXD_PDM_CLK"},
581 {"PDM_RX3", NULL, "RXD_PDM_CLK"},
582
583 {"ADC1", NULL, "TXD_CLK"},
584 {"ADC2", NULL, "TXD_CLK"},
585 {"ADC3", NULL, "TXD_CLK"},
586
587 {"ADC1", NULL, "TXA_CLK25"},
588 {"ADC2", NULL, "TXA_CLK25"},
589 {"ADC3", NULL, "TXA_CLK25"},
590
591 {"PDM_RX1", NULL, "A_MCLK2"},
592 {"PDM_RX2", NULL, "A_MCLK2"},
593 {"PDM_RX3", NULL, "A_MCLK2"},
594
595 {"PDM_TX", NULL, "A_MCLK2"},
596 {"A_MCLK2", NULL, "A_MCLK"},
597
598 /* Headset (RX MIX1 and RX MIX2) */
599 {"HEADPHONE", NULL, "HPHL PA"},
600 {"HEADPHONE", NULL, "HPHR PA"},
601
602 {"HPHL PA", NULL, "EAR_HPHL_CLK"},
603 {"HPHR PA", NULL, "EAR_HPHR_CLK"},
604
605 {"CP", NULL, "NCP_CLK"},
606
607 {"HPHL PA", NULL, "HPHL"},
608 {"HPHR PA", NULL, "HPHR"},
609 {"HPHL PA", NULL, "CP"},
610 {"HPHL PA", NULL, "RX_BIAS"},
611 {"HPHR PA", NULL, "CP"},
612 {"HPHR PA", NULL, "RX_BIAS"},
613 {"HPHL", "Switch", "HPHL DAC"},
614 {"HPHR", "Switch", "HPHR DAC"},
615
616 {"RX_BIAS", NULL, "DAC_REF"},
617
618 {"SPK_OUT", NULL, "SPK PA"},
619 {"SPK PA", NULL, "RX_BIAS"},
620 {"SPK PA", NULL, "SPKR_CLK"},
621 {"SPK PA", NULL, "SPK DAC"},
622 {"SPK DAC", "Switch", "PDM_RX3"},
623
624 {"MIC BIAS Internal1", NULL, "INT_LDO_H"},
625 {"MIC BIAS Internal2", NULL, "INT_LDO_H"},
626 {"MIC BIAS External1", NULL, "INT_LDO_H"},
627 {"MIC BIAS External2", NULL, "INT_LDO_H"},
628 {"MIC BIAS Internal1", NULL, "vdd-micbias"},
629 {"MIC BIAS Internal2", NULL, "vdd-micbias"},
630 {"MIC BIAS External1", NULL, "vdd-micbias"},
631 {"MIC BIAS External2", NULL, "vdd-micbias"},
632};
633
634static const struct snd_soc_dapm_widget pm8916_wcd_analog_dapm_widgets[] = {
635
636 SND_SOC_DAPM_AIF_IN("PDM_RX1", NULL, 0, SND_SOC_NOPM, 0, 0),
637 SND_SOC_DAPM_AIF_IN("PDM_RX2", NULL, 0, SND_SOC_NOPM, 0, 0),
638 SND_SOC_DAPM_AIF_IN("PDM_RX3", NULL, 0, SND_SOC_NOPM, 0, 0),
639 SND_SOC_DAPM_AIF_OUT("PDM_TX", NULL, 0, SND_SOC_NOPM, 0, 0),
640
641 SND_SOC_DAPM_INPUT("AMIC1"),
642 SND_SOC_DAPM_INPUT("AMIC3"),
643 SND_SOC_DAPM_INPUT("AMIC2"),
644 SND_SOC_DAPM_OUTPUT("HEADPHONE"),
645
646 /* RX stuff */
647 SND_SOC_DAPM_SUPPLY("INT_LDO_H", SND_SOC_NOPM, 1, 0, NULL, 0),
648
649 SND_SOC_DAPM_PGA("HPHL PA", CDC_A_RX_HPH_CNP_EN, 5, 0, NULL, 0),
650 SND_SOC_DAPM_MUX("HPHL", SND_SOC_NOPM, 0, 0, &hphl_mux),
651 SND_SOC_DAPM_MIXER("HPHL DAC", CDC_A_RX_HPH_L_PA_DAC_CTL, 3, 0, NULL,
652 0),
653 SND_SOC_DAPM_PGA("HPHR PA", CDC_A_RX_HPH_CNP_EN, 4, 0, NULL, 0),
654 SND_SOC_DAPM_MUX("HPHR", SND_SOC_NOPM, 0, 0, &hphr_mux),
655 SND_SOC_DAPM_MIXER("HPHR DAC", CDC_A_RX_HPH_R_PA_DAC_CTL, 3, 0, NULL,
656 0),
657 SND_SOC_DAPM_MIXER("SPK DAC", SND_SOC_NOPM, 0, 0,
658 spkr_switch, ARRAY_SIZE(spkr_switch)),
659
660 /* Speaker */
661 SND_SOC_DAPM_OUTPUT("SPK_OUT"),
662 SND_SOC_DAPM_PGA_E("SPK PA", CDC_A_SPKR_DRV_CTL,
663 6, 0, NULL, 0,
664 pm8916_wcd_analog_enable_spk_pa,
665 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
666 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
667 SND_SOC_DAPM_REGULATOR_SUPPLY("vdd-micbias", 0, 0),
668 SND_SOC_DAPM_SUPPLY("CP", CDC_A_NCP_EN, 0, 0, NULL, 0),
669
670 SND_SOC_DAPM_SUPPLY("DAC_REF", CDC_A_RX_COM_BIAS_DAC, 0, 0, NULL, 0),
671 SND_SOC_DAPM_SUPPLY("RX_BIAS", CDC_A_RX_COM_BIAS_DAC, 7, 0, NULL, 0),
672
673 /* TX */
674 SND_SOC_DAPM_SUPPLY("MIC BIAS Internal1", CDC_A_MICB_1_EN, 7, 0,
675 pm8916_wcd_analog_enable_micbias_int1,
676 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
677 SND_SOC_DAPM_POST_PMD),
678 SND_SOC_DAPM_SUPPLY("MIC BIAS Internal2", CDC_A_MICB_2_EN, 7, 0,
679 pm8916_wcd_analog_enable_micbias_int2,
680 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
681 SND_SOC_DAPM_POST_PMD),
682
683 SND_SOC_DAPM_SUPPLY("MIC BIAS External1", CDC_A_MICB_1_EN, 7, 0,
684 pm8916_wcd_analog_enable_micbias_ext1,
685 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
686 SND_SOC_DAPM_SUPPLY("MIC BIAS External2", CDC_A_MICB_2_EN, 7, 0,
687 pm8916_wcd_analog_enable_micbias_ext2,
688 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
689
690 SND_SOC_DAPM_ADC_E("ADC1", NULL, CDC_A_TX_1_EN, 7, 0,
691 pm8916_wcd_analog_enable_adc,
692 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
693 SND_SOC_DAPM_POST_PMD),
694 SND_SOC_DAPM_ADC_E("ADC2_INP2", NULL, CDC_A_TX_2_EN, 7, 0,
695 pm8916_wcd_analog_enable_adc,
696 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
697 SND_SOC_DAPM_POST_PMD),
698 SND_SOC_DAPM_ADC_E("ADC2_INP3", NULL, CDC_A_TX_3_EN, 7, 0,
699 pm8916_wcd_analog_enable_adc,
700 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
701 SND_SOC_DAPM_POST_PMD),
702
703 SND_SOC_DAPM_MIXER("ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
704 SND_SOC_DAPM_MIXER("ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
705
706 SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0, &tx_adc2_mux),
707 SND_SOC_DAPM_MUX("RDAC2 MUX", SND_SOC_NOPM, 0, 0, &rdac2_mux),
708
709 /* Analog path clocks */
710 SND_SOC_DAPM_SUPPLY("EAR_HPHR_CLK", CDC_D_CDC_ANA_CLK_CTL, 0, 0, NULL,
711 0),
712 SND_SOC_DAPM_SUPPLY("EAR_HPHL_CLK", CDC_D_CDC_ANA_CLK_CTL, 1, 0, NULL,
713 0),
714 SND_SOC_DAPM_SUPPLY("SPKR_CLK", CDC_D_CDC_ANA_CLK_CTL, 4, 0, NULL, 0),
715 SND_SOC_DAPM_SUPPLY("TXA_CLK25", CDC_D_CDC_ANA_CLK_CTL, 5, 0, NULL, 0),
716
717 /* Digital path clocks */
718
719 SND_SOC_DAPM_SUPPLY("RXD1_CLK", CDC_D_CDC_DIG_CLK_CTL, 0, 0, NULL, 0),
720 SND_SOC_DAPM_SUPPLY("RXD2_CLK", CDC_D_CDC_DIG_CLK_CTL, 1, 0, NULL, 0),
721 SND_SOC_DAPM_SUPPLY("RXD3_CLK", CDC_D_CDC_DIG_CLK_CTL, 2, 0, NULL, 0),
722
723 SND_SOC_DAPM_SUPPLY("TXD_CLK", CDC_D_CDC_DIG_CLK_CTL, 4, 0, NULL, 0),
724 SND_SOC_DAPM_SUPPLY("NCP_CLK", CDC_D_CDC_DIG_CLK_CTL, 6, 0, NULL, 0),
725 SND_SOC_DAPM_SUPPLY("RXD_PDM_CLK", CDC_D_CDC_DIG_CLK_CTL, 7, 0, NULL,
726 0),
727
728 /* System Clock source */
729 SND_SOC_DAPM_SUPPLY("A_MCLK", CDC_D_CDC_TOP_CLK_CTL, 2, 0, NULL, 0),
730 /* TX ADC and RX DAC Clock source. */
731 SND_SOC_DAPM_SUPPLY("A_MCLK2", CDC_D_CDC_TOP_CLK_CTL, 3, 0, NULL, 0),
732};
733
734static struct regmap *pm8916_get_regmap(struct device *dev)
735{
736 return dev_get_regmap(dev->parent, NULL);
737}
738
739static int pm8916_wcd_analog_startup(struct snd_pcm_substream *substream,
740 struct snd_soc_dai *dai)
741{
742 snd_soc_update_bits(dai->codec, CDC_D_CDC_RST_CTL,
743 RST_CTL_DIG_SW_RST_N_MASK,
744 RST_CTL_DIG_SW_RST_N_REMOVE_RESET);
745
746 return 0;
747}
748
749static void pm8916_wcd_analog_shutdown(struct snd_pcm_substream *substream,
750 struct snd_soc_dai *dai)
751{
752 snd_soc_update_bits(dai->codec, CDC_D_CDC_RST_CTL,
753 RST_CTL_DIG_SW_RST_N_MASK, 0);
754}
755
756static struct snd_soc_dai_ops pm8916_wcd_analog_dai_ops = {
757 .startup = pm8916_wcd_analog_startup,
758 .shutdown = pm8916_wcd_analog_shutdown,
759};
760
761static struct snd_soc_dai_driver pm8916_wcd_analog_dai[] = {
762 [0] = {
763 .name = "pm8916_wcd_analog_pdm_rx",
764 .id = 0,
765 .playback = {
766 .stream_name = "PDM Playback",
767 .rates = MSM8916_WCD_ANALOG_RATES,
768 .formats = MSM8916_WCD_ANALOG_FORMATS,
769 .channels_min = 1,
770 .channels_max = 3,
771 },
772 .ops = &pm8916_wcd_analog_dai_ops,
773 },
774 [1] = {
775 .name = "pm8916_wcd_analog_pdm_tx",
776 .id = 1,
777 .capture = {
778 .stream_name = "PDM Capture",
779 .rates = MSM8916_WCD_ANALOG_RATES,
780 .formats = MSM8916_WCD_ANALOG_FORMATS,
781 .channels_min = 1,
782 .channels_max = 4,
783 },
784 .ops = &pm8916_wcd_analog_dai_ops,
785 },
786};
787
788static struct snd_soc_codec_driver pm8916_wcd_analog = {
789 .probe = pm8916_wcd_analog_probe,
790 .remove = pm8916_wcd_analog_remove,
791 .get_regmap = pm8916_get_regmap,
792 .component_driver = {
793 .controls = pm8916_wcd_analog_snd_controls,
794 .num_controls = ARRAY_SIZE(pm8916_wcd_analog_snd_controls),
795 .dapm_widgets = pm8916_wcd_analog_dapm_widgets,
796 .num_dapm_widgets = ARRAY_SIZE(pm8916_wcd_analog_dapm_widgets),
797 .dapm_routes = pm8916_wcd_analog_audio_map,
798 .num_dapm_routes = ARRAY_SIZE(pm8916_wcd_analog_audio_map),
799 },
800};
801
802static int pm8916_wcd_analog_parse_dt(struct device *dev,
803 struct pm8916_wcd_analog_priv *priv)
804{
805
806 if (of_property_read_bool(dev->of_node, "qcom,micbias1-ext-cap"))
807 priv->micbias1_cap_mode = MICB_1_EN_EXT_BYP_CAP;
808 else
809 priv->micbias1_cap_mode = MICB_1_EN_NO_EXT_BYP_CAP;
810
811 if (of_property_read_bool(dev->of_node, "qcom,micbias2-ext-cap"))
812 priv->micbias2_cap_mode = MICB_1_EN_EXT_BYP_CAP;
813 else
814 priv->micbias2_cap_mode = MICB_1_EN_NO_EXT_BYP_CAP;
815
816 return 0;
817}
818
819static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
820{
821 struct pm8916_wcd_analog_priv *priv;
822 struct device *dev = &pdev->dev;
823 int ret, i;
824
825 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
826 if (!priv)
827 return -ENOMEM;
828
829 ret = pm8916_wcd_analog_parse_dt(dev, priv);
830 if (ret < 0)
831 return ret;
832
833 priv->mclk = devm_clk_get(dev, "mclk");
834 if (IS_ERR(priv->mclk)) {
835 dev_err(dev, "failed to get mclk\n");
836 return PTR_ERR(priv->mclk);
837 }
838
839 for (i = 0; i < ARRAY_SIZE(supply_names); i++)
840 priv->supplies[i].supply = supply_names[i];
841
842 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
843 priv->supplies);
844 if (ret) {
845 dev_err(dev, "Failed to get regulator supplies %d\n", ret);
846 return ret;
847 }
848
849 ret = clk_prepare_enable(priv->mclk);
850 if (ret < 0) {
851 dev_err(dev, "failed to enable mclk %d\n", ret);
852 return ret;
853 }
854
855 dev_set_drvdata(dev, priv);
856
857 return snd_soc_register_codec(dev, &pm8916_wcd_analog,
858 pm8916_wcd_analog_dai,
859 ARRAY_SIZE(pm8916_wcd_analog_dai));
860}
861
862static int pm8916_wcd_analog_spmi_remove(struct platform_device *pdev)
863{
864 struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(&pdev->dev);
865
866 snd_soc_unregister_codec(&pdev->dev);
867 clk_disable_unprepare(priv->mclk);
868
869 return 0;
870}
871
872static const struct of_device_id pm8916_wcd_analog_spmi_match_table[] = {
873 { .compatible = "qcom,pm8916-wcd-analog-codec", },
874 { }
875};
876
877static struct platform_driver pm8916_wcd_analog_spmi_driver = {
878 .driver = {
879 .name = "qcom,pm8916-wcd-spmi-codec",
880 .of_match_table = pm8916_wcd_analog_spmi_match_table,
881 },
882 .probe = pm8916_wcd_analog_spmi_probe,
883 .remove = pm8916_wcd_analog_spmi_remove,
884};
885
886module_platform_driver(pm8916_wcd_analog_spmi_driver);
887
888MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
889MODULE_DESCRIPTION("PMIC PM8916 WCD Analog Codec driver");
890MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c
new file mode 100644
index 000000000000..f690442af8c9
--- /dev/null
+++ b/sound/soc/codecs/msm8916-wcd-digital.c
@@ -0,0 +1,923 @@
1/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/module.h>
14#include <linux/err.h>
15#include <linux/kernel.h>
16#include <linux/delay.h>
17#include <linux/types.h>
18#include <linux/clk.h>
19#include <linux/of.h>
20#include <linux/platform_device.h>
21#include <linux/regmap.h>
22#include <linux/mfd/syscon.h>
23#include <sound/soc.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/tlv.h>
27
28#define LPASS_CDC_CLK_RX_RESET_CTL (0x000)
29#define LPASS_CDC_CLK_TX_RESET_B1_CTL (0x004)
30#define CLK_RX_RESET_B1_CTL_TX1_RESET_MASK BIT(0)
31#define CLK_RX_RESET_B1_CTL_TX2_RESET_MASK BIT(1)
32#define LPASS_CDC_CLK_DMIC_B1_CTL (0x008)
33#define DMIC_B1_CTL_DMIC0_CLK_SEL_MASK GENMASK(3, 1)
34#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV2 (0x0 << 1)
35#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV3 (0x1 << 1)
36#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV4 (0x2 << 1)
37#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV6 (0x3 << 1)
38#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV16 (0x4 << 1)
39#define DMIC_B1_CTL_DMIC0_CLK_EN_MASK BIT(0)
40#define DMIC_B1_CTL_DMIC0_CLK_EN_ENABLE BIT(0)
41
42#define LPASS_CDC_CLK_RX_I2S_CTL (0x00C)
43#define RX_I2S_CTL_RX_I2S_MODE_MASK BIT(5)
44#define RX_I2S_CTL_RX_I2S_MODE_16 BIT(5)
45#define RX_I2S_CTL_RX_I2S_MODE_32 0
46#define RX_I2S_CTL_RX_I2S_FS_RATE_MASK GENMASK(2, 0)
47#define RX_I2S_CTL_RX_I2S_FS_RATE_F_8_KHZ 0x0
48#define RX_I2S_CTL_RX_I2S_FS_RATE_F_16_KHZ 0x1
49#define RX_I2S_CTL_RX_I2S_FS_RATE_F_32_KHZ 0x2
50#define RX_I2S_CTL_RX_I2S_FS_RATE_F_48_KHZ 0x3
51#define RX_I2S_CTL_RX_I2S_FS_RATE_F_96_KHZ 0x4
52#define RX_I2S_CTL_RX_I2S_FS_RATE_F_192_KHZ 0x5
53#define LPASS_CDC_CLK_TX_I2S_CTL (0x010)
54#define TX_I2S_CTL_TX_I2S_MODE_MASK BIT(5)
55#define TX_I2S_CTL_TX_I2S_MODE_16 BIT(5)
56#define TX_I2S_CTL_TX_I2S_MODE_32 0
57#define TX_I2S_CTL_TX_I2S_FS_RATE_MASK GENMASK(2, 0)
58#define TX_I2S_CTL_TX_I2S_FS_RATE_F_8_KHZ 0x0
59#define TX_I2S_CTL_TX_I2S_FS_RATE_F_16_KHZ 0x1
60#define TX_I2S_CTL_TX_I2S_FS_RATE_F_32_KHZ 0x2
61#define TX_I2S_CTL_TX_I2S_FS_RATE_F_48_KHZ 0x3
62#define TX_I2S_CTL_TX_I2S_FS_RATE_F_96_KHZ 0x4
63#define TX_I2S_CTL_TX_I2S_FS_RATE_F_192_KHZ 0x5
64
65#define LPASS_CDC_CLK_OTHR_RESET_B1_CTL (0x014)
66#define LPASS_CDC_CLK_TX_CLK_EN_B1_CTL (0x018)
67#define LPASS_CDC_CLK_OTHR_CTL (0x01C)
68#define LPASS_CDC_CLK_RX_B1_CTL (0x020)
69#define LPASS_CDC_CLK_MCLK_CTL (0x024)
70#define MCLK_CTL_MCLK_EN_MASK BIT(0)
71#define MCLK_CTL_MCLK_EN_ENABLE BIT(0)
72#define MCLK_CTL_MCLK_EN_DISABLE 0
73#define LPASS_CDC_CLK_PDM_CTL (0x028)
74#define LPASS_CDC_CLK_PDM_CTL_PDM_EN_MASK BIT(0)
75#define LPASS_CDC_CLK_PDM_CTL_PDM_EN BIT(0)
76#define LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_MASK BIT(1)
77#define LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_FB BIT(1)
78#define LPASS_CDC_CLK_PDM_CTL_PDM_CLK_PDM_CLK 0
79
80#define LPASS_CDC_CLK_SD_CTL (0x02C)
81#define LPASS_CDC_RX1_B1_CTL (0x040)
82#define LPASS_CDC_RX2_B1_CTL (0x060)
83#define LPASS_CDC_RX3_B1_CTL (0x080)
84#define LPASS_CDC_RX1_B2_CTL (0x044)
85#define LPASS_CDC_RX2_B2_CTL (0x064)
86#define LPASS_CDC_RX3_B2_CTL (0x084)
87#define LPASS_CDC_RX1_B3_CTL (0x048)
88#define LPASS_CDC_RX2_B3_CTL (0x068)
89#define LPASS_CDC_RX3_B3_CTL (0x088)
90#define LPASS_CDC_RX1_B4_CTL (0x04C)
91#define LPASS_CDC_RX2_B4_CTL (0x06C)
92#define LPASS_CDC_RX3_B4_CTL (0x08C)
93#define LPASS_CDC_RX1_B5_CTL (0x050)
94#define LPASS_CDC_RX2_B5_CTL (0x070)
95#define LPASS_CDC_RX3_B5_CTL (0x090)
96#define LPASS_CDC_RX1_B6_CTL (0x054)
97#define RXn_B6_CTL_MUTE_MASK BIT(0)
98#define RXn_B6_CTL_MUTE_ENABLE BIT(0)
99#define RXn_B6_CTL_MUTE_DISABLE 0
100#define LPASS_CDC_RX2_B6_CTL (0x074)
101#define LPASS_CDC_RX3_B6_CTL (0x094)
102#define LPASS_CDC_RX1_VOL_CTL_B1_CTL (0x058)
103#define LPASS_CDC_RX2_VOL_CTL_B1_CTL (0x078)
104#define LPASS_CDC_RX3_VOL_CTL_B1_CTL (0x098)
105#define LPASS_CDC_RX1_VOL_CTL_B2_CTL (0x05C)
106#define LPASS_CDC_RX2_VOL_CTL_B2_CTL (0x07C)
107#define LPASS_CDC_RX3_VOL_CTL_B2_CTL (0x09C)
108#define LPASS_CDC_TOP_GAIN_UPDATE (0x0A0)
109#define LPASS_CDC_TOP_CTL (0x0A4)
110#define TOP_CTL_DIG_MCLK_FREQ_MASK BIT(0)
111#define TOP_CTL_DIG_MCLK_FREQ_F_12_288MHZ 0
112#define TOP_CTL_DIG_MCLK_FREQ_F_9_6MHZ BIT(0)
113
114#define LPASS_CDC_DEBUG_DESER1_CTL (0x0E0)
115#define LPASS_CDC_DEBUG_DESER2_CTL (0x0E4)
116#define LPASS_CDC_DEBUG_B1_CTL_CFG (0x0E8)
117#define LPASS_CDC_DEBUG_B2_CTL_CFG (0x0EC)
118#define LPASS_CDC_DEBUG_B3_CTL_CFG (0x0F0)
119#define LPASS_CDC_IIR1_GAIN_B1_CTL (0x100)
120#define LPASS_CDC_IIR2_GAIN_B1_CTL (0x140)
121#define LPASS_CDC_IIR1_GAIN_B2_CTL (0x104)
122#define LPASS_CDC_IIR2_GAIN_B2_CTL (0x144)
123#define LPASS_CDC_IIR1_GAIN_B3_CTL (0x108)
124#define LPASS_CDC_IIR2_GAIN_B3_CTL (0x148)
125#define LPASS_CDC_IIR1_GAIN_B4_CTL (0x10C)
126#define LPASS_CDC_IIR2_GAIN_B4_CTL (0x14C)
127#define LPASS_CDC_IIR1_GAIN_B5_CTL (0x110)
128#define LPASS_CDC_IIR2_GAIN_B5_CTL (0x150)
129#define LPASS_CDC_IIR1_GAIN_B6_CTL (0x114)
130#define LPASS_CDC_IIR2_GAIN_B6_CTL (0x154)
131#define LPASS_CDC_IIR1_GAIN_B7_CTL (0x118)
132#define LPASS_CDC_IIR2_GAIN_B7_CTL (0x158)
133#define LPASS_CDC_IIR1_GAIN_B8_CTL (0x11C)
134#define LPASS_CDC_IIR2_GAIN_B8_CTL (0x15C)
135#define LPASS_CDC_IIR1_CTL (0x120)
136#define LPASS_CDC_IIR2_CTL (0x160)
137#define LPASS_CDC_IIR1_GAIN_TIMER_CTL (0x124)
138#define LPASS_CDC_IIR2_GAIN_TIMER_CTL (0x164)
139#define LPASS_CDC_IIR1_COEF_B1_CTL (0x128)
140#define LPASS_CDC_IIR2_COEF_B1_CTL (0x168)
141#define LPASS_CDC_IIR1_COEF_B2_CTL (0x12C)
142#define LPASS_CDC_IIR2_COEF_B2_CTL (0x16C)
143#define LPASS_CDC_CONN_RX1_B1_CTL (0x180)
144#define LPASS_CDC_CONN_RX1_B2_CTL (0x184)
145#define LPASS_CDC_CONN_RX1_B3_CTL (0x188)
146#define LPASS_CDC_CONN_RX2_B1_CTL (0x18C)
147#define LPASS_CDC_CONN_RX2_B2_CTL (0x190)
148#define LPASS_CDC_CONN_RX2_B3_CTL (0x194)
149#define LPASS_CDC_CONN_RX3_B1_CTL (0x198)
150#define LPASS_CDC_CONN_RX3_B2_CTL (0x19C)
151#define LPASS_CDC_CONN_TX_B1_CTL (0x1A0)
152#define LPASS_CDC_CONN_EQ1_B1_CTL (0x1A8)
153#define LPASS_CDC_CONN_EQ1_B2_CTL (0x1AC)
154#define LPASS_CDC_CONN_EQ1_B3_CTL (0x1B0)
155#define LPASS_CDC_CONN_EQ1_B4_CTL (0x1B4)
156#define LPASS_CDC_CONN_EQ2_B1_CTL (0x1B8)
157#define LPASS_CDC_CONN_EQ2_B2_CTL (0x1BC)
158#define LPASS_CDC_CONN_EQ2_B3_CTL (0x1C0)
159#define LPASS_CDC_CONN_EQ2_B4_CTL (0x1C4)
160#define LPASS_CDC_CONN_TX_I2S_SD1_CTL (0x1C8)
161#define LPASS_CDC_TX1_VOL_CTL_TIMER (0x280)
162#define LPASS_CDC_TX2_VOL_CTL_TIMER (0x2A0)
163#define LPASS_CDC_TX1_VOL_CTL_GAIN (0x284)
164#define LPASS_CDC_TX2_VOL_CTL_GAIN (0x2A4)
165#define LPASS_CDC_TX1_VOL_CTL_CFG (0x288)
166#define TX_VOL_CTL_CFG_MUTE_EN_MASK BIT(0)
167#define TX_VOL_CTL_CFG_MUTE_EN_ENABLE BIT(0)
168
169#define LPASS_CDC_TX2_VOL_CTL_CFG (0x2A8)
170#define LPASS_CDC_TX1_MUX_CTL (0x28C)
171#define TX_MUX_CTL_CUT_OFF_FREQ_MASK GENMASK(5, 4)
172#define TX_MUX_CTL_CUT_OFF_FREQ_SHIFT 4
173#define TX_MUX_CTL_CF_NEG_3DB_4HZ (0x0 << 4)
174#define TX_MUX_CTL_CF_NEG_3DB_75HZ (0x1 << 4)
175#define TX_MUX_CTL_CF_NEG_3DB_150HZ (0x2 << 4)
176#define TX_MUX_CTL_HPF_BP_SEL_MASK BIT(3)
177#define TX_MUX_CTL_HPF_BP_SEL_BYPASS BIT(3)
178#define TX_MUX_CTL_HPF_BP_SEL_NO_BYPASS 0
179
180#define LPASS_CDC_TX2_MUX_CTL (0x2AC)
181#define LPASS_CDC_TX1_CLK_FS_CTL (0x290)
182#define LPASS_CDC_TX2_CLK_FS_CTL (0x2B0)
183#define LPASS_CDC_TX1_DMIC_CTL (0x294)
184#define LPASS_CDC_TX2_DMIC_CTL (0x2B4)
185#define TXN_DMIC_CTL_CLK_SEL_MASK GENMASK(2, 0)
186#define TXN_DMIC_CTL_CLK_SEL_DIV2 0x0
187#define TXN_DMIC_CTL_CLK_SEL_DIV3 0x1
188#define TXN_DMIC_CTL_CLK_SEL_DIV4 0x2
189#define TXN_DMIC_CTL_CLK_SEL_DIV6 0x3
190#define TXN_DMIC_CTL_CLK_SEL_DIV16 0x4
191
192#define MSM8916_WCD_DIGITAL_RATES (SNDRV_PCM_RATE_8000 | \
193 SNDRV_PCM_RATE_16000 | \
194 SNDRV_PCM_RATE_32000 | \
195 SNDRV_PCM_RATE_48000)
196#define MSM8916_WCD_DIGITAL_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
197 SNDRV_PCM_FMTBIT_S24_LE)
198
199struct msm8916_wcd_digital_priv {
200 struct clk *ahbclk, *mclk;
201};
202
203static const unsigned long rx_gain_reg[] = {
204 LPASS_CDC_RX1_VOL_CTL_B2_CTL,
205 LPASS_CDC_RX2_VOL_CTL_B2_CTL,
206 LPASS_CDC_RX3_VOL_CTL_B2_CTL,
207};
208
209static const unsigned long tx_gain_reg[] = {
210 LPASS_CDC_TX1_VOL_CTL_GAIN,
211 LPASS_CDC_TX2_VOL_CTL_GAIN,
212};
213
214static const char *const rx_mix1_text[] = {
215 "ZERO", "IIR1", "IIR2", "RX1", "RX2", "RX3"
216};
217
218static const char *const dec_mux_text[] = {
219 "ZERO", "ADC1", "ADC2", "ADC3", "DMIC1", "DMIC2"
220};
221static const char *const rx_mix2_text[] = { "ZERO", "IIR1", "IIR2" };
222static const char *const adc2_mux_text[] = { "ZERO", "INP2", "INP3" };
223
224/* RX1 MIX1 */
225static const struct soc_enum rx_mix1_inp_enum[] = {
226 SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B1_CTL, 0, 6, rx_mix1_text),
227 SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B1_CTL, 3, 6, rx_mix1_text),
228 SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B2_CTL, 0, 6, rx_mix1_text),
229};
230
231/* RX1 MIX2 */
232static const struct soc_enum rx_mix2_inp1_chain_enum = SOC_ENUM_SINGLE(
233 LPASS_CDC_CONN_RX1_B3_CTL, 0, 3, rx_mix2_text);
234
235/* RX2 MIX1 */
236static const struct soc_enum rx2_mix1_inp_enum[] = {
237 SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B1_CTL, 0, 6, rx_mix1_text),
238 SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B1_CTL, 3, 6, rx_mix1_text),
239 SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B1_CTL, 0, 6, rx_mix1_text),
240};
241
242/* RX2 MIX2 */
243static const struct soc_enum rx2_mix2_inp1_chain_enum = SOC_ENUM_SINGLE(
244 LPASS_CDC_CONN_RX2_B3_CTL, 0, 3, rx_mix2_text);
245
246/* RX3 MIX1 */
247static const struct soc_enum rx3_mix1_inp_enum[] = {
248 SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B1_CTL, 0, 6, rx_mix1_text),
249 SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B1_CTL, 3, 6, rx_mix1_text),
250 SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B1_CTL, 0, 6, rx_mix1_text),
251};
252
253/* DEC */
254static const struct soc_enum dec1_mux_enum = SOC_ENUM_SINGLE(
255 LPASS_CDC_CONN_TX_B1_CTL, 0, 6, dec_mux_text);
256static const struct soc_enum dec2_mux_enum = SOC_ENUM_SINGLE(
257 LPASS_CDC_CONN_TX_B1_CTL, 3, 6, dec_mux_text);
258
259/* RDAC2 MUX */
260static const struct snd_kcontrol_new dec1_mux = SOC_DAPM_ENUM(
261 "DEC1 MUX Mux", dec1_mux_enum);
262static const struct snd_kcontrol_new dec2_mux = SOC_DAPM_ENUM(
263 "DEC2 MUX Mux", dec2_mux_enum);
264static const struct snd_kcontrol_new rx_mix1_inp1_mux = SOC_DAPM_ENUM(
265 "RX1 MIX1 INP1 Mux", rx_mix1_inp_enum[0]);
266static const struct snd_kcontrol_new rx_mix1_inp2_mux = SOC_DAPM_ENUM(
267 "RX1 MIX1 INP2 Mux", rx_mix1_inp_enum[1]);
268static const struct snd_kcontrol_new rx_mix1_inp3_mux = SOC_DAPM_ENUM(
269 "RX1 MIX1 INP3 Mux", rx_mix1_inp_enum[2]);
270static const struct snd_kcontrol_new rx2_mix1_inp1_mux = SOC_DAPM_ENUM(
271 "RX2 MIX1 INP1 Mux", rx2_mix1_inp_enum[0]);
272static const struct snd_kcontrol_new rx2_mix1_inp2_mux = SOC_DAPM_ENUM(
273 "RX2 MIX1 INP2 Mux", rx2_mix1_inp_enum[1]);
274static const struct snd_kcontrol_new rx2_mix1_inp3_mux = SOC_DAPM_ENUM(
275 "RX2 MIX1 INP3 Mux", rx2_mix1_inp_enum[2]);
276static const struct snd_kcontrol_new rx3_mix1_inp1_mux = SOC_DAPM_ENUM(
277 "RX3 MIX1 INP1 Mux", rx3_mix1_inp_enum[0]);
278static const struct snd_kcontrol_new rx3_mix1_inp2_mux = SOC_DAPM_ENUM(
279 "RX3 MIX1 INP2 Mux", rx3_mix1_inp_enum[1]);
280static const struct snd_kcontrol_new rx3_mix1_inp3_mux = SOC_DAPM_ENUM(
281 "RX3 MIX1 INP3 Mux", rx3_mix1_inp_enum[2]);
282
283/* Digital Gain control -38.4 dB to +38.4 dB in 0.3 dB steps */
284static const DECLARE_TLV_DB_SCALE(digital_gain, -3840, 30, 0);
285
286/* Cutoff Freq for High Pass Filter at -3dB */
287static const char * const hpf_cutoff_text[] = {
288 "4Hz", "75Hz", "150Hz",
289};
290
291static SOC_ENUM_SINGLE_DECL(tx1_hpf_cutoff_enum, LPASS_CDC_TX1_MUX_CTL, 4,
292 hpf_cutoff_text);
293static SOC_ENUM_SINGLE_DECL(tx2_hpf_cutoff_enum, LPASS_CDC_TX2_MUX_CTL, 4,
294 hpf_cutoff_text);
295
296/* cut off for dc blocker inside rx chain */
297static const char * const dc_blocker_cutoff_text[] = {
298 "4Hz", "75Hz", "150Hz",
299};
300
301static SOC_ENUM_SINGLE_DECL(rx1_dcb_cutoff_enum, LPASS_CDC_RX1_B4_CTL, 0,
302 dc_blocker_cutoff_text);
303static SOC_ENUM_SINGLE_DECL(rx2_dcb_cutoff_enum, LPASS_CDC_RX2_B4_CTL, 0,
304 dc_blocker_cutoff_text);
305static SOC_ENUM_SINGLE_DECL(rx3_dcb_cutoff_enum, LPASS_CDC_RX3_B4_CTL, 0,
306 dc_blocker_cutoff_text);
307
308static const struct snd_kcontrol_new msm8916_wcd_digital_snd_controls[] = {
309 SOC_SINGLE_S8_TLV("RX1 Digital Volume", LPASS_CDC_RX1_VOL_CTL_B2_CTL,
310 -128, 127, digital_gain),
311 SOC_SINGLE_S8_TLV("RX2 Digital Volume", LPASS_CDC_RX2_VOL_CTL_B2_CTL,
312 -128, 127, digital_gain),
313 SOC_SINGLE_S8_TLV("RX3 Digital Volume", LPASS_CDC_RX3_VOL_CTL_B2_CTL,
314 -128, 127, digital_gain),
315 SOC_SINGLE_S8_TLV("TX1 Digital Volume", LPASS_CDC_TX1_VOL_CTL_GAIN,
316 -128, 127, digital_gain),
317 SOC_SINGLE_S8_TLV("TX2 Digital Volume", LPASS_CDC_TX2_VOL_CTL_GAIN,
318 -128, 127, digital_gain),
319 SOC_ENUM("TX1 HPF Cutoff", tx1_hpf_cutoff_enum),
320 SOC_ENUM("TX2 HPF Cutoff", tx2_hpf_cutoff_enum),
321 SOC_SINGLE("TX1 HPF Switch", LPASS_CDC_TX1_MUX_CTL, 3, 1, 0),
322 SOC_SINGLE("TX2 HPF Switch", LPASS_CDC_TX2_MUX_CTL, 3, 1, 0),
323 SOC_ENUM("RX1 DCB Cutoff", rx1_dcb_cutoff_enum),
324 SOC_ENUM("RX2 DCB Cutoff", rx2_dcb_cutoff_enum),
325 SOC_ENUM("RX3 DCB Cutoff", rx3_dcb_cutoff_enum),
326 SOC_SINGLE("RX1 DCB Switch", LPASS_CDC_RX1_B5_CTL, 2, 1, 0),
327 SOC_SINGLE("RX2 DCB Switch", LPASS_CDC_RX2_B5_CTL, 2, 1, 0),
328 SOC_SINGLE("RX3 DCB Switch", LPASS_CDC_RX3_B5_CTL, 2, 1, 0),
329 SOC_SINGLE("RX1 Mute Switch", LPASS_CDC_RX1_B6_CTL, 0, 1, 0),
330 SOC_SINGLE("RX2 Mute Switch", LPASS_CDC_RX2_B6_CTL, 0, 1, 0),
331 SOC_SINGLE("RX3 Mute Switch", LPASS_CDC_RX3_B6_CTL, 0, 1, 0),
332};
333
334static int msm8916_wcd_digital_enable_interpolator(
335 struct snd_soc_dapm_widget *w,
336 struct snd_kcontrol *kcontrol,
337 int event)
338{
339 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
340
341 switch (event) {
342 case SND_SOC_DAPM_POST_PMU:
343 /* apply the digital gain after the interpolator is enabled */
344 usleep_range(10000, 10100);
345 snd_soc_write(codec, rx_gain_reg[w->shift],
346 snd_soc_read(codec, rx_gain_reg[w->shift]));
347 break;
348 }
349 return 0;
350}
351
352static int msm8916_wcd_digital_enable_dec(struct snd_soc_dapm_widget *w,
353 struct snd_kcontrol *kcontrol,
354 int event)
355{
356 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
357 unsigned int decimator = w->shift + 1;
358 u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
359 u8 dec_hpf_cut_of_freq;
360
361 dec_reset_reg = LPASS_CDC_CLK_TX_RESET_B1_CTL;
362 tx_vol_ctl_reg = LPASS_CDC_TX1_VOL_CTL_CFG + 32 * (decimator - 1);
363 tx_mux_ctl_reg = LPASS_CDC_TX1_MUX_CTL + 32 * (decimator - 1);
364
365 switch (event) {
366 case SND_SOC_DAPM_PRE_PMU:
367 /* Enable TX digital mute */
368 snd_soc_update_bits(codec, tx_vol_ctl_reg,
369 TX_VOL_CTL_CFG_MUTE_EN_MASK,
370 TX_VOL_CTL_CFG_MUTE_EN_ENABLE);
371 dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg) &
372 TX_MUX_CTL_CUT_OFF_FREQ_MASK;
373 dec_hpf_cut_of_freq >>= TX_MUX_CTL_CUT_OFF_FREQ_SHIFT;
374 if (dec_hpf_cut_of_freq != TX_MUX_CTL_CF_NEG_3DB_150HZ) {
375 /* set cut of freq to CF_MIN_3DB_150HZ (0x1) */
376 snd_soc_update_bits(codec, tx_mux_ctl_reg,
377 TX_MUX_CTL_CUT_OFF_FREQ_MASK,
378 TX_MUX_CTL_CF_NEG_3DB_150HZ);
379 }
380 break;
381 case SND_SOC_DAPM_POST_PMU:
382 /* enable HPF */
383 snd_soc_update_bits(codec, tx_mux_ctl_reg,
384 TX_MUX_CTL_HPF_BP_SEL_MASK,
385 TX_MUX_CTL_HPF_BP_SEL_NO_BYPASS);
386 /* apply the digital gain after the decimator is enabled */
387 snd_soc_write(codec, tx_gain_reg[w->shift],
388 snd_soc_read(codec, tx_gain_reg[w->shift]));
389 snd_soc_update_bits(codec, tx_vol_ctl_reg,
390 TX_VOL_CTL_CFG_MUTE_EN_MASK, 0);
391 break;
392 case SND_SOC_DAPM_PRE_PMD:
393 snd_soc_update_bits(codec, tx_vol_ctl_reg,
394 TX_VOL_CTL_CFG_MUTE_EN_MASK,
395 TX_VOL_CTL_CFG_MUTE_EN_ENABLE);
396 snd_soc_update_bits(codec, tx_mux_ctl_reg,
397 TX_MUX_CTL_HPF_BP_SEL_MASK,
398 TX_MUX_CTL_HPF_BP_SEL_BYPASS);
399 break;
400 case SND_SOC_DAPM_POST_PMD:
401 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
402 1 << w->shift);
403 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
404 snd_soc_update_bits(codec, tx_mux_ctl_reg,
405 TX_MUX_CTL_HPF_BP_SEL_MASK,
406 TX_MUX_CTL_HPF_BP_SEL_BYPASS);
407 snd_soc_update_bits(codec, tx_vol_ctl_reg,
408 TX_VOL_CTL_CFG_MUTE_EN_MASK, 0);
409 break;
410 }
411
412 return 0;
413}
414
415static int msm8916_wcd_digital_enable_dmic(struct snd_soc_dapm_widget *w,
416 struct snd_kcontrol *kcontrol,
417 int event)
418{
419 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
420 unsigned int dmic;
421 int ret;
422 /* get dmic number out of widget name */
423 char *dmic_num = strpbrk(w->name, "12");
424
425 if (dmic_num == NULL) {
426 dev_err(codec->dev, "Invalid DMIC\n");
427 return -EINVAL;
428 }
429 ret = kstrtouint(dmic_num, 10, &dmic);
430 if (ret < 0 || dmic > 2) {
431 dev_err(codec->dev, "Invalid DMIC line on the codec\n");
432 return -EINVAL;
433 }
434
435 switch (event) {
436 case SND_SOC_DAPM_PRE_PMU:
437 snd_soc_update_bits(codec, LPASS_CDC_CLK_DMIC_B1_CTL,
438 DMIC_B1_CTL_DMIC0_CLK_SEL_MASK,
439 DMIC_B1_CTL_DMIC0_CLK_SEL_DIV3);
440 switch (dmic) {
441 case 1:
442 snd_soc_update_bits(codec, LPASS_CDC_TX1_DMIC_CTL,
443 TXN_DMIC_CTL_CLK_SEL_MASK,
444 TXN_DMIC_CTL_CLK_SEL_DIV3);
445 break;
446 case 2:
447 snd_soc_update_bits(codec, LPASS_CDC_TX2_DMIC_CTL,
448 TXN_DMIC_CTL_CLK_SEL_MASK,
449 TXN_DMIC_CTL_CLK_SEL_DIV3);
450 break;
451 }
452 break;
453 }
454
455 return 0;
456}
457
458static const struct snd_soc_dapm_widget msm8916_wcd_digital_dapm_widgets[] = {
459 /*RX stuff */
460 SND_SOC_DAPM_AIF_IN("I2S RX1", NULL, 0, SND_SOC_NOPM, 0, 0),
461 SND_SOC_DAPM_AIF_IN("I2S RX2", NULL, 0, SND_SOC_NOPM, 0, 0),
462 SND_SOC_DAPM_AIF_IN("I2S RX3", NULL, 0, SND_SOC_NOPM, 0, 0),
463
464 SND_SOC_DAPM_OUTPUT("PDM_RX1"),
465 SND_SOC_DAPM_OUTPUT("PDM_RX2"),
466 SND_SOC_DAPM_OUTPUT("PDM_RX3"),
467
468 SND_SOC_DAPM_INPUT("LPASS_PDM_TX"),
469
470 SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
471 SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
472 SND_SOC_DAPM_MIXER("RX3 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
473
474 /* Interpolator */
475 SND_SOC_DAPM_MIXER_E("RX1 INT", LPASS_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
476 0, msm8916_wcd_digital_enable_interpolator,
477 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
478 SND_SOC_DAPM_MIXER_E("RX2 INT", LPASS_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
479 0, msm8916_wcd_digital_enable_interpolator,
480 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
481 SND_SOC_DAPM_MIXER_E("RX3 INT", LPASS_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
482 0, msm8916_wcd_digital_enable_interpolator,
483 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
484 SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
485 &rx_mix1_inp1_mux),
486 SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
487 &rx_mix1_inp2_mux),
488 SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
489 &rx_mix1_inp3_mux),
490 SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
491 &rx2_mix1_inp1_mux),
492 SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
493 &rx2_mix1_inp2_mux),
494 SND_SOC_DAPM_MUX("RX2 MIX1 INP3", SND_SOC_NOPM, 0, 0,
495 &rx2_mix1_inp3_mux),
496 SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
497 &rx3_mix1_inp1_mux),
498 SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
499 &rx3_mix1_inp2_mux),
500 SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0,
501 &rx3_mix1_inp3_mux),
502
503 /* TX */
504 SND_SOC_DAPM_MIXER("ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
505 SND_SOC_DAPM_MIXER("ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
506 SND_SOC_DAPM_MIXER("ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
507
508 SND_SOC_DAPM_MUX_E("DEC1 MUX", LPASS_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
509 &dec1_mux, msm8916_wcd_digital_enable_dec,
510 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
511 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
512 SND_SOC_DAPM_MUX_E("DEC2 MUX", LPASS_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
513 &dec2_mux, msm8916_wcd_digital_enable_dec,
514 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
515 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
516 SND_SOC_DAPM_AIF_OUT("I2S TX1", NULL, 0, SND_SOC_NOPM, 0, 0),
517 SND_SOC_DAPM_AIF_OUT("I2S TX2", NULL, 0, SND_SOC_NOPM, 0, 0),
518 SND_SOC_DAPM_AIF_OUT("I2S TX3", NULL, 0, SND_SOC_NOPM, 0, 0),
519
520 /* Digital Mic Inputs */
521 SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
522 msm8916_wcd_digital_enable_dmic,
523 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
524 SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
525 msm8916_wcd_digital_enable_dmic,
526 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
527 SND_SOC_DAPM_SUPPLY("DMIC_CLK", LPASS_CDC_CLK_DMIC_B1_CTL, 0, 0,
528 NULL, 0),
529 SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", LPASS_CDC_CLK_RX_I2S_CTL,
530 4, 0, NULL, 0),
531 SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", LPASS_CDC_CLK_TX_I2S_CTL, 4, 0,
532 NULL, 0),
533
534 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0, NULL, 0),
535 SND_SOC_DAPM_SUPPLY("PDM_CLK", LPASS_CDC_CLK_PDM_CTL, 0, 0, NULL, 0),
536 /* Connectivity Clock */
537 SND_SOC_DAPM_SUPPLY_S("CDC_CONN", -2, LPASS_CDC_CLK_OTHR_CTL, 2, 0,
538 NULL, 0),
539
540};
541
542static int msm8916_wcd_digital_get_clks(struct platform_device *pdev,
543 struct msm8916_wcd_digital_priv *priv)
544{
545 struct device *dev = &pdev->dev;
546
547 priv->ahbclk = devm_clk_get(dev, "ahbix-clk");
548 if (IS_ERR(priv->ahbclk)) {
549 dev_err(dev, "failed to get ahbix clk\n");
550 return PTR_ERR(priv->ahbclk);
551 }
552
553 priv->mclk = devm_clk_get(dev, "mclk");
554 if (IS_ERR(priv->mclk)) {
555 dev_err(dev, "failed to get mclk\n");
556 return PTR_ERR(priv->mclk);
557 }
558
559 return 0;
560}
561
562static int msm8916_wcd_digital_codec_probe(struct snd_soc_codec *codec)
563{
564 struct msm8916_wcd_digital_priv *priv = dev_get_drvdata(codec->dev);
565
566 snd_soc_codec_set_drvdata(codec, priv);
567
568 return 0;
569}
570
571static int msm8916_wcd_digital_hw_params(struct snd_pcm_substream *substream,
572 struct snd_pcm_hw_params *params,
573 struct snd_soc_dai *dai)
574{
575 u8 tx_fs_rate;
576 u8 rx_fs_rate;
577
578 switch (params_rate(params)) {
579 case 8000:
580 tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_8_KHZ;
581 rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_8_KHZ;
582 break;
583 case 16000:
584 tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_16_KHZ;
585 rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_16_KHZ;
586 break;
587 case 32000:
588 tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_32_KHZ;
589 rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_32_KHZ;
590 break;
591 case 48000:
592 tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_48_KHZ;
593 rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_48_KHZ;
594 break;
595 default:
596 dev_err(dai->codec->dev, "Invalid sampling rate %d\n",
597 params_rate(params));
598 return -EINVAL;
599 }
600
601 switch (substream->stream) {
602 case SNDRV_PCM_STREAM_CAPTURE:
603 snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_TX_I2S_CTL,
604 TX_I2S_CTL_TX_I2S_FS_RATE_MASK, tx_fs_rate);
605 break;
606 case SNDRV_PCM_STREAM_PLAYBACK:
607 snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_RX_I2S_CTL,
608 RX_I2S_CTL_RX_I2S_FS_RATE_MASK, rx_fs_rate);
609 break;
610 default:
611 return -EINVAL;
612 }
613
614 switch (params_format(params)) {
615 case SNDRV_PCM_FORMAT_S16_LE:
616 snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_TX_I2S_CTL,
617 TX_I2S_CTL_TX_I2S_MODE_MASK,
618 TX_I2S_CTL_TX_I2S_MODE_16);
619 snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_RX_I2S_CTL,
620 RX_I2S_CTL_RX_I2S_MODE_MASK,
621 RX_I2S_CTL_RX_I2S_MODE_16);
622 break;
623 case SNDRV_PCM_FORMAT_S24_LE:
624 snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_TX_I2S_CTL,
625 TX_I2S_CTL_TX_I2S_MODE_MASK,
626 TX_I2S_CTL_TX_I2S_MODE_32);
627 snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_RX_I2S_CTL,
628 RX_I2S_CTL_RX_I2S_MODE_MASK,
629 RX_I2S_CTL_RX_I2S_MODE_32);
630 break;
631 default:
632 dev_err(dai->dev, "%s: wrong format selected\n", __func__);
633 return -EINVAL;
634 }
635
636 return 0;
637}
638
639static const struct snd_soc_dapm_route msm8916_wcd_digital_audio_map[] = {
640
641 {"I2S RX1", NULL, "AIF1 Playback"},
642 {"I2S RX2", NULL, "AIF1 Playback"},
643 {"I2S RX3", NULL, "AIF1 Playback"},
644
645 {"AIF1 Capture", NULL, "I2S TX1"},
646 {"AIF1 Capture", NULL, "I2S TX2"},
647 {"AIF1 Capture", NULL, "I2S TX3"},
648
649 /* Decimator Inputs */
650 {"DEC1 MUX", "DMIC1", "DMIC1"},
651 {"DEC1 MUX", "DMIC2", "DMIC2"},
652 {"DEC1 MUX", "ADC1", "ADC1"},
653 {"DEC1 MUX", "ADC2", "ADC2"},
654 {"DEC1 MUX", "ADC3", "ADC3"},
655 {"DEC1 MUX", NULL, "CDC_CONN"},
656
657 {"DEC2 MUX", "DMIC1", "DMIC1"},
658 {"DEC2 MUX", "DMIC2", "DMIC2"},
659 {"DEC2 MUX", "ADC1", "ADC1"},
660 {"DEC2 MUX", "ADC2", "ADC2"},
661 {"DEC2 MUX", "ADC3", "ADC3"},
662 {"DEC2 MUX", NULL, "CDC_CONN"},
663
664 {"DMIC1", NULL, "DMIC_CLK"},
665 {"DMIC2", NULL, "DMIC_CLK"},
666
667 {"I2S TX1", NULL, "DEC1 MUX"},
668 {"I2S TX2", NULL, "DEC2 MUX"},
669
670 {"I2S TX1", NULL, "TX_I2S_CLK"},
671 {"I2S TX2", NULL, "TX_I2S_CLK"},
672
673 {"TX_I2S_CLK", NULL, "MCLK"},
674 {"TX_I2S_CLK", NULL, "PDM_CLK"},
675
676 {"ADC1", NULL, "LPASS_PDM_TX"},
677 {"ADC2", NULL, "LPASS_PDM_TX"},
678 {"ADC3", NULL, "LPASS_PDM_TX"},
679
680 {"I2S RX1", NULL, "RX_I2S_CLK"},
681 {"I2S RX2", NULL, "RX_I2S_CLK"},
682 {"I2S RX3", NULL, "RX_I2S_CLK"},
683
684 {"RX_I2S_CLK", NULL, "PDM_CLK"},
685 {"RX_I2S_CLK", NULL, "MCLK"},
686 {"RX_I2S_CLK", NULL, "CDC_CONN"},
687
688 /* RX1 PATH.. */
689 {"PDM_RX1", NULL, "RX1 INT"},
690 {"RX1 INT", NULL, "RX1 MIX1"},
691
692 {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
693 {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
694 {"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
695
696 {"RX1 MIX1 INP1", "RX1", "I2S RX1"},
697 {"RX1 MIX1 INP1", "RX2", "I2S RX2"},
698 {"RX1 MIX1 INP1", "RX3", "I2S RX3"},
699
700 {"RX1 MIX1 INP2", "RX1", "I2S RX1"},
701 {"RX1 MIX1 INP2", "RX2", "I2S RX2"},
702 {"RX1 MIX1 INP2", "RX3", "I2S RX3"},
703
704 {"RX1 MIX1 INP3", "RX1", "I2S RX1"},
705 {"RX1 MIX1 INP3", "RX2", "I2S RX2"},
706 {"RX1 MIX1 INP3", "RX3", "I2S RX3"},
707
708 /* RX2 PATH */
709 {"PDM_RX2", NULL, "RX2 INT"},
710 {"RX2 INT", NULL, "RX2 MIX1"},
711
712 {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
713 {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
714 {"RX2 MIX1", NULL, "RX2 MIX1 INP3"},
715
716 {"RX2 MIX1 INP1", "RX1", "I2S RX1"},
717 {"RX2 MIX1 INP1", "RX2", "I2S RX2"},
718 {"RX2 MIX1 INP1", "RX3", "I2S RX3"},
719
720 {"RX2 MIX1 INP2", "RX1", "I2S RX1"},
721 {"RX2 MIX1 INP2", "RX2", "I2S RX2"},
722 {"RX2 MIX1 INP2", "RX3", "I2S RX3"},
723
724 {"RX2 MIX1 INP3", "RX1", "I2S RX1"},
725 {"RX2 MIX1 INP3", "RX2", "I2S RX2"},
726 {"RX2 MIX1 INP3", "RX3", "I2S RX3"},
727
728 /* RX3 PATH */
729 {"PDM_RX3", NULL, "RX3 INT"},
730 {"RX3 INT", NULL, "RX3 MIX1"},
731
732 {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
733 {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
734 {"RX3 MIX1", NULL, "RX3 MIX1 INP3"},
735
736 {"RX3 MIX1 INP1", "RX1", "I2S RX1"},
737 {"RX3 MIX1 INP1", "RX2", "I2S RX2"},
738 {"RX3 MIX1 INP1", "RX3", "I2S RX3"},
739
740 {"RX3 MIX1 INP2", "RX1", "I2S RX1"},
741 {"RX3 MIX1 INP2", "RX2", "I2S RX2"},
742 {"RX3 MIX1 INP2", "RX3", "I2S RX3"},
743
744 {"RX3 MIX1 INP3", "RX1", "I2S RX1"},
745 {"RX3 MIX1 INP3", "RX2", "I2S RX2"},
746 {"RX3 MIX1 INP3", "RX3", "I2S RX3"},
747
748};
749
750static int msm8916_wcd_digital_startup(struct snd_pcm_substream *substream,
751 struct snd_soc_dai *dai)
752{
753 struct snd_soc_codec *codec = dai->codec;
754 struct msm8916_wcd_digital_priv *msm8916_wcd;
755 unsigned long mclk_rate;
756
757 msm8916_wcd = snd_soc_codec_get_drvdata(codec);
758 snd_soc_update_bits(codec, LPASS_CDC_CLK_MCLK_CTL,
759 MCLK_CTL_MCLK_EN_MASK,
760 MCLK_CTL_MCLK_EN_ENABLE);
761 snd_soc_update_bits(codec, LPASS_CDC_CLK_PDM_CTL,
762 LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_MASK,
763 LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_FB);
764
765 mclk_rate = clk_get_rate(msm8916_wcd->mclk);
766 switch (mclk_rate) {
767 case 12288000:
768 snd_soc_update_bits(codec, LPASS_CDC_TOP_CTL,
769 TOP_CTL_DIG_MCLK_FREQ_MASK,
770 TOP_CTL_DIG_MCLK_FREQ_F_12_288MHZ);
771 break;
772 case 9600000:
773 snd_soc_update_bits(codec, LPASS_CDC_TOP_CTL,
774 TOP_CTL_DIG_MCLK_FREQ_MASK,
775 TOP_CTL_DIG_MCLK_FREQ_F_9_6MHZ);
776 break;
777 default:
778 dev_err(codec->dev, "Invalid mclk rate %ld\n", mclk_rate);
779 break;
780 }
781 return 0;
782}
783
784static void msm8916_wcd_digital_shutdown(struct snd_pcm_substream *substream,
785 struct snd_soc_dai *dai)
786{
787 snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_PDM_CTL,
788 LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_MASK, 0);
789}
790
791static struct snd_soc_dai_ops msm8916_wcd_digital_dai_ops = {
792 .startup = msm8916_wcd_digital_startup,
793 .shutdown = msm8916_wcd_digital_shutdown,
794 .hw_params = msm8916_wcd_digital_hw_params,
795};
796
797static struct snd_soc_dai_driver msm8916_wcd_digital_dai[] = {
798 [0] = {
799 .name = "msm8916_wcd_digital_i2s_rx1",
800 .id = 0,
801 .playback = {
802 .stream_name = "AIF1 Playback",
803 .rates = MSM8916_WCD_DIGITAL_RATES,
804 .formats = MSM8916_WCD_DIGITAL_FORMATS,
805 .channels_min = 1,
806 .channels_max = 3,
807 },
808 .ops = &msm8916_wcd_digital_dai_ops,
809 },
810 [1] = {
811 .name = "msm8916_wcd_digital_i2s_tx1",
812 .id = 1,
813 .capture = {
814 .stream_name = "AIF1 Capture",
815 .rates = MSM8916_WCD_DIGITAL_RATES,
816 .formats = MSM8916_WCD_DIGITAL_FORMATS,
817 .channels_min = 1,
818 .channels_max = 4,
819 },
820 .ops = &msm8916_wcd_digital_dai_ops,
821 },
822};
823
824static struct snd_soc_codec_driver msm8916_wcd_digital = {
825 .probe = msm8916_wcd_digital_codec_probe,
826 .component_driver = {
827 .controls = msm8916_wcd_digital_snd_controls,
828 .num_controls = ARRAY_SIZE(msm8916_wcd_digital_snd_controls),
829 .dapm_widgets = msm8916_wcd_digital_dapm_widgets,
830 .num_dapm_widgets =
831 ARRAY_SIZE(msm8916_wcd_digital_dapm_widgets),
832 .dapm_routes = msm8916_wcd_digital_audio_map,
833 .num_dapm_routes = ARRAY_SIZE(msm8916_wcd_digital_audio_map),
834 },
835};
836
837static const struct regmap_config msm8916_codec_regmap_config = {
838 .reg_bits = 32,
839 .reg_stride = 4,
840 .val_bits = 32,
841 .max_register = LPASS_CDC_TX2_DMIC_CTL,
842 .cache_type = REGCACHE_FLAT,
843};
844
845static int msm8916_wcd_digital_probe(struct platform_device *pdev)
846{
847 struct msm8916_wcd_digital_priv *priv;
848 struct device *dev = &pdev->dev;
849 void __iomem *base;
850 struct resource *mem_res;
851 struct regmap *digital_map;
852 int ret;
853
854 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
855 if (!priv)
856 return -ENOMEM;
857
858 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
859 base = devm_ioremap_resource(&pdev->dev, mem_res);
860 if (IS_ERR(base))
861 return PTR_ERR(base);
862
863 digital_map =
864 devm_regmap_init_mmio(&pdev->dev, base,
865 &msm8916_codec_regmap_config);
866 if (IS_ERR(digital_map))
867 return PTR_ERR(digital_map);
868
869 ret = msm8916_wcd_digital_get_clks(pdev, priv);
870 if (ret < 0)
871 return ret;
872
873 ret = clk_prepare_enable(priv->ahbclk);
874 if (ret < 0) {
875 dev_err(dev, "failed to enable ahbclk %d\n", ret);
876 return ret;
877 }
878
879 ret = clk_prepare_enable(priv->mclk);
880 if (ret < 0) {
881 dev_err(dev, "failed to enable mclk %d\n", ret);
882 return ret;
883 }
884
885 dev_set_drvdata(dev, priv);
886
887 return snd_soc_register_codec(dev, &msm8916_wcd_digital,
888 msm8916_wcd_digital_dai,
889 ARRAY_SIZE(msm8916_wcd_digital_dai));
890}
891
892static int msm8916_wcd_digital_remove(struct platform_device *pdev)
893{
894 struct msm8916_wcd_digital_priv *priv = dev_get_drvdata(&pdev->dev);
895
896 snd_soc_unregister_codec(&pdev->dev);
897 clk_disable_unprepare(priv->mclk);
898 clk_disable_unprepare(priv->ahbclk);
899
900 return 0;
901}
902
903static const struct of_device_id msm8916_wcd_digital_match_table[] = {
904 { .compatible = "qcom,msm8916-wcd-digital-codec" },
905 { }
906};
907
908MODULE_DEVICE_TABLE(of, msm8916_wcd_digital_match_table);
909
910static struct platform_driver msm8916_wcd_digital_driver = {
911 .driver = {
912 .name = "msm8916-wcd-digital-codec",
913 .of_match_table = msm8916_wcd_digital_match_table,
914 },
915 .probe = msm8916_wcd_digital_probe,
916 .remove = msm8916_wcd_digital_remove,
917};
918
919module_platform_driver(msm8916_wcd_digital_driver);
920
921MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
922MODULE_DESCRIPTION("MSM8916 WCD Digital Codec driver");
923MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index dcbb7aa9830c..311774e9ca46 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -244,9 +244,9 @@ static const struct snd_soc_dapm_route corgi_audio_map[] = {
244 {"MICIN", NULL, "Line Jack"}, 244 {"MICIN", NULL, "Line Jack"},
245}; 245};
246 246
247static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", 247static const char * const jack_function[] = {"Headphone", "Mic", "Line",
248 "Off"}; 248 "Headset", "Off"};
249static const char *spk_function[] = {"On", "Off"}; 249static const char * const spk_function[] = {"On", "Off"};
250static const struct soc_enum corgi_enum[] = { 250static const struct soc_enum corgi_enum[] = {
251 SOC_ENUM_SINGLE_EXT(5, jack_function), 251 SOC_ENUM_SINGLE_EXT(5, jack_function),
252 SOC_ENUM_SINGLE_EXT(2, spk_function), 252 SOC_ENUM_SINGLE_EXT(2, spk_function),
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
index 62b8377a9d2b..2d4d4455fe87 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -376,7 +376,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
376 {"VINM", NULL, "Call Mic"}, 376 {"VINM", NULL, "Call Mic"},
377}; 377};
378 378
379static const char *input_select[] = {"Call Mic", "Headset Mic"}; 379static const char * const input_select[] = {"Call Mic", "Headset Mic"};
380static const struct soc_enum magician_in_sel_enum = 380static const struct soc_enum magician_in_sel_enum =
381 SOC_ENUM_SINGLE_EXT(2, input_select); 381 SOC_ENUM_SINGLE_EXT(2, input_select);
382 382
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
index d1661fa6ee08..0fe0abec8fc4 100644
--- a/sound/soc/pxa/mioa701_wm9713.c
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -187,7 +187,7 @@ static int mioa701_wm9713_probe(struct platform_device *pdev)
187 mioa701.dev = &pdev->dev; 187 mioa701.dev = &pdev->dev;
188 rc = devm_snd_soc_register_card(&pdev->dev, &mioa701); 188 rc = devm_snd_soc_register_card(&pdev->dev, &mioa701);
189 if (!rc) 189 if (!rc)
190 dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will" 190 dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will "
191 "lead to overheating and possible destruction of your device." 191 "lead to overheating and possible destruction of your device."
192 " Do not use without a good knowledge of mio's board design!\n"); 192 " Do not use without a good knowledge of mio's board design!\n");
193 return rc; 193 return rc;
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index 4b3b714f5ee7..a879aba0691f 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -209,8 +209,8 @@ static const struct snd_soc_dapm_route poodle_audio_map[] = {
209 {"MICIN", NULL, "Microphone"}, 209 {"MICIN", NULL, "Microphone"},
210}; 210};
211 211
212static const char *jack_function[] = {"Off", "Headphone"}; 212static const char * const jack_function[] = {"Off", "Headphone"};
213static const char *spk_function[] = {"Off", "On"}; 213static const char * const spk_function[] = {"Off", "On"};
214static const struct soc_enum poodle_enum[] = { 214static const struct soc_enum poodle_enum[] = {
215 SOC_ENUM_SINGLE_EXT(2, jack_function), 215 SOC_ENUM_SINGLE_EXT(2, jack_function),
216 SOC_ENUM_SINGLE_EXT(2, spk_function), 216 SOC_ENUM_SINGLE_EXT(2, spk_function),
diff --git a/sound/soc/pxa/pxa-ssp.h b/sound/soc/pxa/pxa-ssp.h
index bc79da221c0d..abf6ec080258 100644
--- a/sound/soc/pxa/pxa-ssp.h
+++ b/sound/soc/pxa/pxa-ssp.h
@@ -9,12 +9,6 @@
9#ifndef _PXA_SSP_H 9#ifndef _PXA_SSP_H
10#define _PXA_SSP_H 10#define _PXA_SSP_H
11 11
12/* pxa DAI SSP IDs */
13#define PXA_DAI_SSP1 0
14#define PXA_DAI_SSP2 1
15#define PXA_DAI_SSP3 2
16#define PXA_DAI_SSP4 3
17
18/* SSP clock sources */ 12/* SSP clock sources */
19#define PXA_SSP_CLK_PLL 0 13#define PXA_SSP_CLK_PLL 0
20#define PXA_SSP_CLK_EXT 1 14#define PXA_SSP_CLK_EXT 1
diff --git a/sound/soc/pxa/pxa2xx-i2s.h b/sound/soc/pxa/pxa2xx-i2s.h
index 070f3c6059fe..7e218e2105a9 100644
--- a/sound/soc/pxa/pxa2xx-i2s.h
+++ b/sound/soc/pxa/pxa2xx-i2s.h
@@ -9,9 +9,6 @@
9#ifndef _PXA2XX_I2S_H 9#ifndef _PXA2XX_I2S_H
10#define _PXA2XX_I2S_H 10#define _PXA2XX_I2S_H
11 11
12/* pxa2xx DAI ID's */
13#define PXA2XX_DAI_I2S 0
14
15/* I2S clock */ 12/* I2S clock */
16#define PXA2XX_I2S_SYSCLK 0 13#define PXA2XX_I2S_SYSCLK 0
17 14
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index 0e02634c8b7f..07d77cddac60 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -241,9 +241,9 @@ static const struct snd_soc_dapm_route spitz_audio_map[] = {
241 {"LINPUT1", NULL, "Line Jack"}, 241 {"LINPUT1", NULL, "Line Jack"},
242}; 242};
243 243
244static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", 244static const char * const jack_function[] = {"Headphone", "Mic", "Line",
245 "Off"}; 245 "Headset", "Off"};
246static const char *spk_function[] = {"On", "Off"}; 246static const char * const spk_function[] = {"On", "Off"};
247static const struct soc_enum spitz_enum[] = { 247static const struct soc_enum spitz_enum[] = {
248 SOC_ENUM_SINGLE_EXT(5, jack_function), 248 SOC_ENUM_SINGLE_EXT(5, jack_function),
249 SOC_ENUM_SINGLE_EXT(2, spk_function), 249 SOC_ENUM_SINGLE_EXT(2, spk_function),
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index c508f024ecfb..08b0cf50e91a 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -170,9 +170,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
170 {"Mic Bias", NULL, "Headset Jack"}, 170 {"Mic Bias", NULL, "Headset Jack"},
171}; 171};
172 172
173static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", 173static const char * const jack_function[] = {"Headphone", "Mic", "Line",
174 "Off"}; 174 "Headset", "Off"};
175static const char *spk_function[] = {"On", "Off"}; 175static const char * const spk_function[] = {"On", "Off"};
176static const struct soc_enum tosa_enum[] = { 176static const struct soc_enum tosa_enum[] = {
177 SOC_ENUM_SINGLE_EXT(5, jack_function), 177 SOC_ENUM_SINGLE_EXT(5, jack_function),
178 SOC_ENUM_SINGLE_EXT(2, spk_function), 178 SOC_ENUM_SINGLE_EXT(2, spk_function),
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c
index 07f91e918b23..d084d7468299 100644
--- a/sound/soc/qcom/apq8016_sbc.c
+++ b/sound/soc/qcom/apq8016_sbc.c
@@ -123,20 +123,15 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card)
123 return ERR_PTR(-EINVAL); 123 return ERR_PTR(-EINVAL);
124 } 124 }
125 125
126 link->codec_of_node = of_parse_phandle(codec, "sound-dai", 0);
127 if (!link->codec_of_node) {
128 dev_err(card->dev, "error getting codec phandle\n");
129 return ERR_PTR(-EINVAL);
130 }
131
132 ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name); 126 ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name);
133 if (ret) { 127 if (ret) {
134 dev_err(card->dev, "error getting cpu dai name\n"); 128 dev_err(card->dev, "error getting cpu dai name\n");
135 return ERR_PTR(ret); 129 return ERR_PTR(ret);
136 } 130 }
137 131
138 ret = snd_soc_of_get_dai_name(codec, &link->codec_dai_name); 132 ret = snd_soc_of_get_dai_link_codecs(dev, codec, link);
139 if (ret) { 133
134 if (ret < 0) {
140 dev_err(card->dev, "error getting codec dai name\n"); 135 dev_err(card->dev, "error getting codec dai name\n");
141 return ERR_PTR(ret); 136 return ERR_PTR(ret);
142 } 137 }
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
index 420d200f9a05..dd5bdd0da730 100644
--- a/sound/soc/qcom/lpass-platform.c
+++ b/sound/soc/qcom/lpass-platform.c
@@ -25,8 +25,7 @@
25#include "lpass.h" 25#include "lpass.h"
26 26
27struct lpass_pcm_data { 27struct lpass_pcm_data {
28 int rdma_ch; 28 int dma_ch;
29 int wrdma_ch;
30 int i2s_port; 29 int i2s_port;
31}; 30};
32 31
@@ -95,10 +94,7 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
95 return ret; 94 return ret;
96 } 95 }
97 96
98 if (dir == SNDRV_PCM_STREAM_PLAYBACK) 97 data->dma_ch = dma_ch;
99 data->rdma_ch = dma_ch;
100 else
101 data->wrdma_ch = dma_ch;
102 98
103 snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware); 99 snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware);
104 100
@@ -125,20 +121,12 @@ static int lpass_platform_pcmops_close(struct snd_pcm_substream *substream)
125 snd_soc_platform_get_drvdata(soc_runtime->platform); 121 snd_soc_platform_get_drvdata(soc_runtime->platform);
126 struct lpass_variant *v = drvdata->variant; 122 struct lpass_variant *v = drvdata->variant;
127 struct lpass_pcm_data *data; 123 struct lpass_pcm_data *data;
128 int dma_ch, dir = substream->stream;
129 124
130 data = runtime->private_data; 125 data = runtime->private_data;
131 v = drvdata->variant; 126 v = drvdata->variant;
132 127 drvdata->substream[data->dma_ch] = NULL;
133 if (dir == SNDRV_PCM_STREAM_PLAYBACK)
134 dma_ch = data->rdma_ch;
135 else
136 dma_ch = data->wrdma_ch;
137
138 drvdata->substream[dma_ch] = NULL;
139
140 if (v->free_dma_channel) 128 if (v->free_dma_channel)
141 v->free_dma_channel(drvdata, dma_ch); 129 v->free_dma_channel(drvdata, data->dma_ch);
142 130
143 return 0; 131 return 0;
144} 132}
@@ -159,10 +147,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
159 int bitwidth; 147 int bitwidth;
160 int ret, dma_port = pcm_data->i2s_port + v->dmactl_audif_start; 148 int ret, dma_port = pcm_data->i2s_port + v->dmactl_audif_start;
161 149
162 if (dir == SNDRV_PCM_STREAM_PLAYBACK) 150 ch = pcm_data->dma_ch;
163 ch = pcm_data->rdma_ch;
164 else
165 ch = pcm_data->wrdma_ch;
166 151
167 bitwidth = snd_pcm_format_width(format); 152 bitwidth = snd_pcm_format_width(format);
168 if (bitwidth < 0) { 153 if (bitwidth < 0) {
@@ -249,11 +234,7 @@ static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream)
249 unsigned int reg; 234 unsigned int reg;
250 int ret; 235 int ret;
251 236
252 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 237 reg = LPAIF_DMACTL_REG(v, pcm_data->dma_ch, substream->stream);
253 reg = LPAIF_RDMACTL_REG(v, pcm_data->rdma_ch);
254 else
255 reg = LPAIF_WRDMACTL_REG(v, pcm_data->wrdma_ch);
256
257 ret = regmap_write(drvdata->lpaif_map, reg, 0); 238 ret = regmap_write(drvdata->lpaif_map, reg, 0);
258 if (ret) 239 if (ret)
259 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 240 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
@@ -273,10 +254,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
273 struct lpass_variant *v = drvdata->variant; 254 struct lpass_variant *v = drvdata->variant;
274 int ret, ch, dir = substream->stream; 255 int ret, ch, dir = substream->stream;
275 256
276 if (dir == SNDRV_PCM_STREAM_PLAYBACK) 257 ch = pcm_data->dma_ch;
277 ch = pcm_data->rdma_ch;
278 else
279 ch = pcm_data->wrdma_ch;
280 258
281 ret = regmap_write(drvdata->lpaif_map, 259 ret = regmap_write(drvdata->lpaif_map,
282 LPAIF_DMABASE_REG(v, ch, dir), 260 LPAIF_DMABASE_REG(v, ch, dir),
@@ -328,10 +306,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
328 struct lpass_variant *v = drvdata->variant; 306 struct lpass_variant *v = drvdata->variant;
329 int ret, ch, dir = substream->stream; 307 int ret, ch, dir = substream->stream;
330 308
331 if (dir == SNDRV_PCM_STREAM_PLAYBACK) 309 ch = pcm_data->dma_ch;
332 ch = pcm_data->rdma_ch;
333 else
334 ch = pcm_data->wrdma_ch;
335 310
336 switch (cmd) { 311 switch (cmd) {
337 case SNDRV_PCM_TRIGGER_START: 312 case SNDRV_PCM_TRIGGER_START:
@@ -406,10 +381,7 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
406 unsigned int base_addr, curr_addr; 381 unsigned int base_addr, curr_addr;
407 int ret, ch, dir = substream->stream; 382 int ret, ch, dir = substream->stream;
408 383
409 if (dir == SNDRV_PCM_STREAM_PLAYBACK) 384 ch = pcm_data->dma_ch;
410 ch = pcm_data->rdma_ch;
411 else
412 ch = pcm_data->wrdma_ch;
413 385
414 ret = regmap_read(drvdata->lpaif_map, 386 ret = regmap_read(drvdata->lpaif_map,
415 LPAIF_DMABASE_REG(v, ch, dir), &base_addr); 387 LPAIF_DMABASE_REG(v, ch, dir), &base_addr);
diff --git a/sound/soc/qcom/storm.c b/sound/soc/qcom/storm.c
index 2d833bffdba0..8fcac2ac3aa6 100644
--- a/sound/soc/qcom/storm.c
+++ b/sound/soc/qcom/storm.c
@@ -58,7 +58,7 @@ static int storm_ops_hw_params(struct snd_pcm_substream *substream,
58 return 0; 58 return 0;
59} 59}
60 60
61static struct snd_soc_ops storm_soc_ops = { 61static const struct snd_soc_ops storm_soc_ops = {
62 .hw_params = storm_ops_hw_params, 62 .hw_params = storm_ops_hw_params,
63}; 63};
64 64
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 7c3bf160a1a1..ce8e665a9c89 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3450,10 +3450,10 @@ found:
3450EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); 3450EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
3451 3451
3452/* Retrieve a card's name from device tree */ 3452/* Retrieve a card's name from device tree */
3453int snd_soc_of_parse_card_name(struct snd_soc_card *card, 3453int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card,
3454 const char *propname) 3454 struct device_node *np,
3455 const char *propname)
3455{ 3456{
3456 struct device_node *np;
3457 int ret; 3457 int ret;
3458 3458
3459 if (!card->dev) { 3459 if (!card->dev) {
@@ -3461,7 +3461,8 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card,
3461 return -EINVAL; 3461 return -EINVAL;
3462 } 3462 }
3463 3463
3464 np = card->dev->of_node; 3464 if (!np)
3465 np = card->dev->of_node;
3465 3466
3466 ret = of_property_read_string_index(np, propname, 0, &card->name); 3467 ret = of_property_read_string_index(np, propname, 0, &card->name);
3467 /* 3468 /*
@@ -3478,7 +3479,7 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card,
3478 3479
3479 return 0; 3480 return 0;
3480} 3481}
3481EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name); 3482EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name_from_node);
3482 3483
3483static const struct snd_soc_dapm_widget simple_widgets[] = { 3484static const struct snd_soc_dapm_widget simple_widgets[] = {
3484 SND_SOC_DAPM_MIC("Microphone", NULL), 3485 SND_SOC_DAPM_MIC("Microphone", NULL),
@@ -3487,14 +3488,17 @@ static const struct snd_soc_dapm_widget simple_widgets[] = {
3487 SND_SOC_DAPM_SPK("Speaker", NULL), 3488 SND_SOC_DAPM_SPK("Speaker", NULL),
3488}; 3489};
3489 3490
3490int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, 3491int snd_soc_of_parse_audio_simple_widgets_from_node(struct snd_soc_card *card,
3492 struct device_node *np,
3491 const char *propname) 3493 const char *propname)
3492{ 3494{
3493 struct device_node *np = card->dev->of_node;
3494 struct snd_soc_dapm_widget *widgets; 3495 struct snd_soc_dapm_widget *widgets;
3495 const char *template, *wname; 3496 const char *template, *wname;
3496 int i, j, num_widgets, ret; 3497 int i, j, num_widgets, ret;
3497 3498
3499 if (!np)
3500 np = card->dev->of_node;
3501
3498 num_widgets = of_property_count_strings(np, propname); 3502 num_widgets = of_property_count_strings(np, propname);
3499 if (num_widgets < 0) { 3503 if (num_widgets < 0) {
3500 dev_err(card->dev, 3504 dev_err(card->dev,
@@ -3565,7 +3569,7 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
3565 3569
3566 return 0; 3570 return 0;
3567} 3571}
3568EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets); 3572EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets_from_node);
3569 3573
3570static int snd_soc_of_get_slot_mask(struct device_node *np, 3574static int snd_soc_of_get_slot_mask(struct device_node *np,
3571 const char *prop_name, 3575 const char *prop_name,
@@ -3621,15 +3625,18 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np,
3621} 3625}
3622EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); 3626EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot);
3623 3627
3624void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card, 3628void snd_soc_of_parse_audio_prefix_from_node(struct snd_soc_card *card,
3629 struct device_node *np,
3625 struct snd_soc_codec_conf *codec_conf, 3630 struct snd_soc_codec_conf *codec_conf,
3626 struct device_node *of_node, 3631 struct device_node *of_node,
3627 const char *propname) 3632 const char *propname)
3628{ 3633{
3629 struct device_node *np = card->dev->of_node;
3630 const char *str; 3634 const char *str;
3631 int ret; 3635 int ret;
3632 3636
3637 if (!np)
3638 np = card->dev->of_node;
3639
3633 ret = of_property_read_string(np, propname, &str); 3640 ret = of_property_read_string(np, propname, &str);
3634 if (ret < 0) { 3641 if (ret < 0) {
3635 /* no prefix is not error */ 3642 /* no prefix is not error */
@@ -3639,16 +3646,19 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
3639 codec_conf->of_node = of_node; 3646 codec_conf->of_node = of_node;
3640 codec_conf->name_prefix = str; 3647 codec_conf->name_prefix = str;
3641} 3648}
3642EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix); 3649EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix_from_node);
3643 3650
3644int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, 3651int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card,
3652 struct device_node *np,
3645 const char *propname) 3653 const char *propname)
3646{ 3654{
3647 struct device_node *np = card->dev->of_node;
3648 int num_routes; 3655 int num_routes;
3649 struct snd_soc_dapm_route *routes; 3656 struct snd_soc_dapm_route *routes;
3650 int i, ret; 3657 int i, ret;
3651 3658
3659 if (!np)
3660 np = card->dev->of_node;
3661
3652 num_routes = of_property_count_strings(np, propname); 3662 num_routes = of_property_count_strings(np, propname);
3653 if (num_routes < 0 || num_routes & 1) { 3663 if (num_routes < 0 || num_routes & 1) {
3654 dev_err(card->dev, 3664 dev_err(card->dev,
@@ -3695,7 +3705,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
3695 3705
3696 return 0; 3706 return 0;
3697} 3707}
3698EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing); 3708EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing_from_node);
3699 3709
3700unsigned int snd_soc_of_parse_daifmt(struct device_node *np, 3710unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
3701 const char *prefix, 3711 const char *prefix,
@@ -3810,7 +3820,7 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
3810} 3820}
3811EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); 3821EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt);
3812 3822
3813static int snd_soc_get_dai_name(struct of_phandle_args *args, 3823int snd_soc_get_dai_name(struct of_phandle_args *args,
3814 const char **dai_name) 3824 const char **dai_name)
3815{ 3825{
3816 struct snd_soc_component *pos; 3826 struct snd_soc_component *pos;
@@ -3862,6 +3872,7 @@ static int snd_soc_get_dai_name(struct of_phandle_args *args,
3862 mutex_unlock(&client_mutex); 3872 mutex_unlock(&client_mutex);
3863 return ret; 3873 return ret;
3864} 3874}
3875EXPORT_SYMBOL_GPL(snd_soc_get_dai_name);
3865 3876
3866int snd_soc_of_get_dai_name(struct device_node *of_node, 3877int snd_soc_of_get_dai_name(struct device_node *of_node,
3867 const char **dai_name) 3878 const char **dai_name)