xref: /linux/sound/soc/codecs/pm4125.c (revision b61104e7a6349bd2c2b3e2fb3260d87f15eda8f4)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
3 // Copyright (c) 2025, Linaro Ltd
4 
5 #include <linux/component.h>
6 #include <linux/delay.h>
7 #include <linux/device.h>
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/of.h>
11 #include <linux/platform_device.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/regmap.h>
14 #include <linux/regulator/consumer.h>
15 #include <linux/slab.h>
16 #include <sound/jack.h>
17 #include <sound/pcm.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc.h>
20 #include <sound/soc-dapm.h>
21 #include <sound/tlv.h>
22 
23 #include "pm4125.h"
24 #include "wcd-mbhc-v2.h"
25 
26 #define WCD_MBHC_HS_V_MAX		1600
27 #define PM4125_MBHC_MAX_BUTTONS		8
28 
29 #define PM4125_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
30 		      SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
31 		      SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\
32 		      SNDRV_PCM_RATE_384000)
33 
34 /* Fractional Rates */
35 #define PM4125_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\
36 			   SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800)
37 
38 #define PM4125_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\
39 			SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
40 
41 /* Registers in SPMI addr space */
42 #define PM4125_CODEC_RESET_REG		0xF3DB
43 #define PM4125_CODEC_OFF		0x1
44 #define PM4125_CODEC_ON			0x0
45 #define PM4125_CODEC_FOUNDRY_ID_REG	0x7
46 
47 enum {
48 	HPH_COMP_DELAY,
49 	HPH_PA_DELAY,
50 	AMIC2_BCS_ENABLE,
51 };
52 
53 enum {
54 	AIF1_PB = 0,
55 	AIF1_CAP,
56 	NUM_CODEC_DAIS,
57 };
58 
59 struct pm4125_priv {
60 	struct sdw_slave *tx_sdw_dev;
61 	struct pm4125_sdw_priv *sdw_priv[NUM_CODEC_DAIS];
62 	struct device *txdev;
63 	struct device *rxdev;
64 	struct device_node *rxnode;
65 	struct device_node *txnode;
66 	struct regmap *regmap;
67 	struct regmap *spmi_regmap;
68 	/* mbhc module */
69 	struct wcd_mbhc *wcd_mbhc;
70 	struct wcd_mbhc_config mbhc_cfg;
71 	struct wcd_mbhc_intr intr_ids;
72 	struct wcd_common common;
73 	struct irq_domain *virq;
74 	const struct regmap_irq_chip *chip_desc;
75 	struct regmap_irq_chip_data *irq_chip;
76 	struct snd_soc_jack *jack;
77 	unsigned long status_mask;
78 	s32 micb_ref[PM4125_MAX_MICBIAS];
79 	s32 pullup_ref[PM4125_MAX_MICBIAS];
80 
81 	int hphr_pdm_wd_int;
82 	int hphl_pdm_wd_int;
83 	bool comp1_enable;
84 	bool comp2_enable;
85 
86 	atomic_t gloal_mbias_cnt;
87 };
88 
89 static const char * const pm4125_power_supplies[] = {
90 	"vdd-io", "vdd-cp", "vdd-mic-bias", "vdd-pa-vpos",
91 };
92 
93 static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
94 static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
95 
96 static const struct wcd_mbhc_field pm4125_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {
97 	WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, PM4125_ANA_MBHC_MECH, 0x80),
98 	WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, PM4125_ANA_MBHC_MECH, 0x40),
99 	WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, PM4125_ANA_MBHC_MECH, 0x20),
100 	WCD_MBHC_FIELD(WCD_MBHC_MIC_CLAMP_CTL, PM4125_ANA_MBHC_PLUG_DETECT_CTL, 0x30),
101 	WCD_MBHC_FIELD(WCD_MBHC_ELECT_DETECTION_TYPE, PM4125_ANA_MBHC_ELECT, 0x08),
102 	WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, PM4125_ANA_MBHC_PLUG_DETECT_CTL, 0x1F),
103 	WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, PM4125_ANA_MBHC_MECH, 0x04),
104 	WCD_MBHC_FIELD(WCD_MBHC_HPHL_PLUG_TYPE, PM4125_ANA_MBHC_MECH, 0x10),
105 	WCD_MBHC_FIELD(WCD_MBHC_GND_PLUG_TYPE, PM4125_ANA_MBHC_MECH, 0x08),
106 	WCD_MBHC_FIELD(WCD_MBHC_SW_HPH_LP_100K_TO_GND, PM4125_ANA_MBHC_MECH, 0x01),
107 	WCD_MBHC_FIELD(WCD_MBHC_ELECT_SCHMT_ISRC, PM4125_ANA_MBHC_ELECT, 0x06),
108 	WCD_MBHC_FIELD(WCD_MBHC_FSM_EN, PM4125_ANA_MBHC_ELECT, 0x80),
109 	WCD_MBHC_FIELD(WCD_MBHC_INSREM_DBNC, PM4125_ANA_MBHC_PLUG_DETECT_CTL, 0x0F),
110 	WCD_MBHC_FIELD(WCD_MBHC_BTN_DBNC, PM4125_ANA_MBHC_CTL_1, 0x03),
111 	WCD_MBHC_FIELD(WCD_MBHC_HS_VREF, PM4125_ANA_MBHC_CTL_2, 0x03),
112 	WCD_MBHC_FIELD(WCD_MBHC_HS_COMP_RESULT, PM4125_ANA_MBHC_RESULT_3, 0x08),
113 	WCD_MBHC_FIELD(WCD_MBHC_IN2P_CLAMP_STATE, PM4125_ANA_MBHC_RESULT_3, 0x10),
114 	WCD_MBHC_FIELD(WCD_MBHC_MIC_SCHMT_RESULT, PM4125_ANA_MBHC_RESULT_3, 0x20),
115 	WCD_MBHC_FIELD(WCD_MBHC_HPHL_SCHMT_RESULT, PM4125_ANA_MBHC_RESULT_3, 0x80),
116 	WCD_MBHC_FIELD(WCD_MBHC_HPHR_SCHMT_RESULT, PM4125_ANA_MBHC_RESULT_3, 0x40),
117 	WCD_MBHC_FIELD(WCD_MBHC_BTN_RESULT, PM4125_ANA_MBHC_RESULT_3, 0x07),
118 	WCD_MBHC_FIELD(WCD_MBHC_BTN_ISRC_CTL, PM4125_ANA_MBHC_ELECT, 0x70),
119 	WCD_MBHC_FIELD(WCD_MBHC_ELECT_RESULT, PM4125_ANA_MBHC_RESULT_3, 0xFF),
120 	WCD_MBHC_FIELD(WCD_MBHC_MICB_CTRL, PM4125_ANA_MICBIAS_MICB_1_2_EN, 0xC0),
121 	WCD_MBHC_FIELD(WCD_MBHC_HPHR_PA_EN, PM4125_ANA_HPHPA_CNP_CTL_2, 0x40),
122 	WCD_MBHC_FIELD(WCD_MBHC_HPHL_PA_EN, PM4125_ANA_HPHPA_CNP_CTL_2, 0x80),
123 	WCD_MBHC_FIELD(WCD_MBHC_HPH_PA_EN, PM4125_ANA_HPHPA_CNP_CTL_2, 0xC0),
124 	WCD_MBHC_FIELD(WCD_MBHC_SWCH_LEVEL_REMOVE, PM4125_ANA_MBHC_RESULT_3, 0x10),
125 	WCD_MBHC_FIELD(WCD_MBHC_FSM_STATUS, PM4125_ANA_MBHC_FSM_STATUS, 0x01),
126 	WCD_MBHC_FIELD(WCD_MBHC_MUX_CTL, PM4125_ANA_MBHC_CTL_2, 0x70),
127 	WCD_MBHC_FIELD(WCD_MBHC_MOISTURE_STATUS, PM4125_ANA_MBHC_FSM_STATUS, 0x20),
128 	WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_DET_EN, PM4125_ANA_HPHPA_CNP_CTL_2, 0x01),
129 	WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_DET_EN, PM4125_ANA_HPHPA_CNP_CTL_2, 0x01),
130 	WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_STATUS, PM4125_DIG_SWR_INTR_STATUS_0, 0x80),
131 	WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_STATUS, PM4125_DIG_SWR_INTR_STATUS_0, 0x20),
132 	WCD_MBHC_FIELD(WCD_MBHC_ADC_EN, PM4125_ANA_MBHC_CTL_1, 0x08),
133 	WCD_MBHC_FIELD(WCD_MBHC_ADC_COMPLETE, PM4125_ANA_MBHC_FSM_STATUS, 0x40),
134 	WCD_MBHC_FIELD(WCD_MBHC_ADC_TIMEOUT, PM4125_ANA_MBHC_FSM_STATUS, 0x80),
135 	WCD_MBHC_FIELD(WCD_MBHC_ADC_RESULT, PM4125_ANA_MBHC_ADC_RESULT, 0xFF),
136 	WCD_MBHC_FIELD(WCD_MBHC_MICB2_VOUT, PM4125_ANA_MICBIAS_LDO_1_SETTING, 0x3F),
137 	WCD_MBHC_FIELD(WCD_MBHC_ADC_MODE, PM4125_ANA_MBHC_CTL_1, 0x10),
138 	WCD_MBHC_FIELD(WCD_MBHC_DETECTION_DONE, PM4125_ANA_MBHC_CTL_1, 0x04),
139 	WCD_MBHC_FIELD(WCD_MBHC_ELECT_ISRC_EN, PM4125_ANA_MBHC_ZDET, 0x02),
140 };
141 
142 static const struct regmap_irq pm4125_irqs[PM4125_NUM_IRQS] = {
143 	REGMAP_IRQ_REG(PM4125_IRQ_MBHC_BUTTON_PRESS_DET, 0, BIT(0)),
144 	REGMAP_IRQ_REG(PM4125_IRQ_MBHC_BUTTON_RELEASE_DET, 0, BIT(1)),
145 	REGMAP_IRQ_REG(PM4125_IRQ_MBHC_ELECT_INS_REM_DET, 0, BIT(2)),
146 	REGMAP_IRQ_REG(PM4125_IRQ_MBHC_ELECT_INS_REM_LEG_DET, 0, BIT(3)),
147 	REGMAP_IRQ_REG(PM4125_IRQ_MBHC_SW_DET, 0, BIT(4)),
148 	REGMAP_IRQ_REG(PM4125_IRQ_HPHR_OCP_INT, 0, BIT(5)),
149 	REGMAP_IRQ_REG(PM4125_IRQ_HPHR_CNP_INT, 0, BIT(6)),
150 	REGMAP_IRQ_REG(PM4125_IRQ_HPHL_OCP_INT, 0, BIT(7)),
151 	REGMAP_IRQ_REG(PM4125_IRQ_HPHL_CNP_INT, 1, BIT(0)),
152 	REGMAP_IRQ_REG(PM4125_IRQ_EAR_CNP_INT, 1, BIT(1)),
153 	REGMAP_IRQ_REG(PM4125_IRQ_EAR_SCD_INT, 1, BIT(2)),
154 	REGMAP_IRQ_REG(PM4125_IRQ_AUX_CNP_INT, 1, BIT(3)),
155 	REGMAP_IRQ_REG(PM4125_IRQ_AUX_SCD_INT, 1, BIT(4)),
156 	REGMAP_IRQ_REG(PM4125_IRQ_HPHL_PDM_WD_INT, 1, BIT(5)),
157 	REGMAP_IRQ_REG(PM4125_IRQ_HPHR_PDM_WD_INT, 1, BIT(6)),
158 	REGMAP_IRQ_REG(PM4125_IRQ_AUX_PDM_WD_INT, 1, BIT(7)),
159 	REGMAP_IRQ_REG(PM4125_IRQ_LDORT_SCD_INT, 2, BIT(0)),
160 	REGMAP_IRQ_REG(PM4125_IRQ_MBHC_MOISTURE_INT, 2, BIT(1)),
161 	REGMAP_IRQ_REG(PM4125_IRQ_HPHL_SURGE_DET_INT, 2, BIT(2)),
162 	REGMAP_IRQ_REG(PM4125_IRQ_HPHR_SURGE_DET_INT, 2, BIT(3)),
163 };
164 
165 static int pm4125_handle_post_irq(void *data)
166 {
167 	struct pm4125_priv *pm4125 = (struct pm4125_priv *)data;
168 
169 	regmap_write(pm4125->regmap, PM4125_DIG_SWR_INTR_CLEAR_0, 0);
170 	regmap_write(pm4125->regmap, PM4125_DIG_SWR_INTR_CLEAR_1, 0);
171 	regmap_write(pm4125->regmap, PM4125_DIG_SWR_INTR_CLEAR_2, 0);
172 
173 	return IRQ_HANDLED;
174 }
175 
176 static const u32 pm4125_config_regs[] = {
177 	PM4125_DIG_SWR_INTR_LEVEL_0,
178 };
179 
180 static const struct regmap_irq_chip pm4125_regmap_irq_chip = {
181 	.name = "pm4125",
182 	.irqs = pm4125_irqs,
183 	.num_irqs = ARRAY_SIZE(pm4125_irqs),
184 	.num_regs = 3,
185 	.status_base = PM4125_DIG_SWR_INTR_STATUS_0,
186 	.mask_base = PM4125_DIG_SWR_INTR_MASK_0,
187 	.ack_base = PM4125_DIG_SWR_INTR_CLEAR_0,
188 	.use_ack = 1,
189 	.clear_ack = 1,
190 	.config_base = pm4125_config_regs,
191 	.num_config_bases = ARRAY_SIZE(pm4125_config_regs),
192 	.num_config_regs = 1,
193 	.runtime_pm = true,
194 	.handle_post_irq = pm4125_handle_post_irq,
195 };
196 
197 static void pm4125_reset(struct pm4125_priv *pm4125)
198 {
199 	regmap_write(pm4125->spmi_regmap, PM4125_CODEC_RESET_REG, PM4125_CODEC_OFF);
200 	usleep_range(20, 30);
201 	regmap_write(pm4125->spmi_regmap, PM4125_CODEC_RESET_REG, PM4125_CODEC_ON);
202 	usleep_range(5000, 5010);
203 }
204 
205 static void pm4125_io_init(struct regmap *regmap)
206 {
207 	/* Disable HPH OCP */
208 	regmap_update_bits(regmap, PM4125_ANA_HPHPA_CNP_CTL_2,
209 			   PM4125_ANA_HPHPA_CNP_OCP_EN_L_MASK | PM4125_ANA_HPHPA_CNP_OCP_EN_R_MASK,
210 			   PM4125_ANA_HPHPA_CNP_OCP_DISABLE);
211 
212 	/* Enable surge protection */
213 	regmap_update_bits(regmap, PM4125_ANA_SURGE_EN, PM4125_ANA_SURGE_PROTECTION_HPHL_MASK,
214 			   FIELD_PREP(PM4125_ANA_SURGE_PROTECTION_HPHL_MASK,
215 				      PM4125_ANA_SURGE_PROTECTION_ENABLE));
216 	regmap_update_bits(regmap, PM4125_ANA_SURGE_EN, PM4125_ANA_SURGE_PROTECTION_HPHR_MASK,
217 			   FIELD_PREP(PM4125_ANA_SURGE_PROTECTION_HPHR_MASK,
218 				      PM4125_ANA_SURGE_PROTECTION_ENABLE));
219 
220 	/* Disable mic bias 2 pull down */
221 	regmap_update_bits(regmap, PM4125_ANA_MICBIAS_MICB_1_2_EN,
222 			   PM4125_ANA_MICBIAS_MICB2_PULL_DN_MASK,
223 			   FIELD_PREP(PM4125_ANA_MICBIAS_MICB2_PULL_DN_MASK,
224 				      PM4125_ANA_MICBIAS_MICB_PULL_DISABLE));
225 }
226 
227 static int pm4125_global_mbias_disable(struct snd_soc_component *component)
228 {
229 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
230 
231 	if (atomic_dec_and_test(&pm4125->gloal_mbias_cnt)) {
232 
233 		snd_soc_component_write_field(component, PM4125_ANA_MBIAS_EN,
234 					      PM4125_ANA_MBIAS_EN_V2I_MASK,
235 					      PM4125_ANA_MBIAS_EN_DISABLE);
236 		snd_soc_component_write_field(component, PM4125_ANA_MBIAS_EN,
237 					      PM4125_ANA_MBIAS_EN_GLOBAL_MASK,
238 					      PM4125_ANA_MBIAS_EN_DISABLE);
239 	}
240 
241 	return 0;
242 }
243 
244 static int pm4125_global_mbias_enable(struct snd_soc_component *component)
245 {
246 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
247 
248 	if (atomic_inc_return(&pm4125->gloal_mbias_cnt) == 1) {
249 		snd_soc_component_write_field(component, PM4125_ANA_MBIAS_EN,
250 					      PM4125_ANA_MBIAS_EN_GLOBAL_MASK,
251 					      PM4125_ANA_MBIAS_EN_ENABLE);
252 		snd_soc_component_write_field(component, PM4125_ANA_MBIAS_EN,
253 					      PM4125_ANA_MBIAS_EN_V2I_MASK,
254 					      PM4125_ANA_MBIAS_EN_ENABLE);
255 		usleep_range(1000, 1100);
256 	}
257 
258 	return 0;
259 }
260 
261 static int pm4125_rx_clk_enable(struct snd_soc_component *component)
262 {
263 	pm4125_global_mbias_enable(component);
264 
265 	snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL,
266 				      PM4125_DIG_SWR_ANA_RX_CLK_EN_MASK,
267 				      PM4125_DIG_SWR_RX_CLK_ENABLE);
268 	snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL,
269 				      PM4125_DIG_SWR_ANA_RX_DIV2_CLK_EN_MASK,
270 				      PM4125_DIG_SWR_RX_CLK_ENABLE);
271 	usleep_range(5000, 5100);
272 
273 	snd_soc_component_write_field(component, PM4125_ANA_HPHPA_FSM_CLK,
274 				      PM4125_ANA_HPHPA_FSM_DIV_RATIO_MASK,
275 				      PM4125_ANA_HPHPA_FSM_DIV_RATIO_68);
276 	snd_soc_component_write_field(component, PM4125_ANA_HPHPA_FSM_CLK,
277 				      PM4125_ANA_HPHPA_FSM_CLK_DIV_EN_MASK,
278 				      PM4125_ANA_HPHPA_FSM_CLK_DIV_ENABLE);
279 	snd_soc_component_update_bits(component, PM4125_ANA_NCP_VCTRL, 0x07, 0x06);
280 	snd_soc_component_write_field(component, PM4125_ANA_NCP_EN,
281 				      PM4125_ANA_NCP_ENABLE_MASK,
282 				      PM4125_ANA_NCP_ENABLE);
283 	usleep_range(500, 510);
284 
285 	return 0;
286 }
287 
288 static int pm4125_rx_clk_disable(struct snd_soc_component *component)
289 {
290 
291 	snd_soc_component_write_field(component, PM4125_ANA_HPHPA_FSM_CLK,
292 				      PM4125_ANA_HPHPA_FSM_CLK_DIV_EN_MASK,
293 				      PM4125_ANA_HPHPA_FSM_CLK_DIV_DISABLE);
294 	snd_soc_component_write_field(component, PM4125_ANA_HPHPA_FSM_CLK,
295 				      PM4125_ANA_HPHPA_FSM_DIV_RATIO_MASK,
296 				      0x00);
297 	snd_soc_component_write_field(component, PM4125_ANA_NCP_EN,
298 				      PM4125_ANA_NCP_ENABLE_MASK,
299 				      PM4125_ANA_NCP_DISABLE);
300 	snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL,
301 				      PM4125_DIG_SWR_ANA_RX_DIV2_CLK_EN_MASK,
302 				      PM4125_DIG_SWR_RX_CLK_DISABLE);
303 	snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL,
304 				      PM4125_DIG_SWR_ANA_RX_CLK_EN_MASK,
305 				      PM4125_DIG_SWR_RX_CLK_DISABLE);
306 
307 	pm4125_global_mbias_disable(component);
308 
309 	return 0;
310 }
311 
312 
313 static int pm4125_codec_enable_rxclk(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
314 				     int event)
315 {
316 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
317 
318 	switch (event) {
319 	case SND_SOC_DAPM_PRE_PMU:
320 		pm4125_rx_clk_enable(component);
321 		break;
322 	case SND_SOC_DAPM_POST_PMD:
323 		pm4125_rx_clk_disable(component);
324 		break;
325 	}
326 
327 	return 0;
328 }
329 
330 static int pm4125_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
331 				       struct snd_kcontrol *kcontrol, int event)
332 {
333 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
334 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
335 
336 	switch (event) {
337 	case SND_SOC_DAPM_PRE_PMU:
338 		snd_soc_component_write_field(component, PM4125_ANA_HPHPA_CNP_CTL_1,
339 					      PM4125_ANA_HPHPA_CNP_CTL_1_EN_MASK,
340 					      PM4125_ANA_HPHPA_CNP_CTL_1_EN);
341 		snd_soc_component_write_field(component, PM4125_SWR_HPHPA_HD2,
342 					      PM4125_SWR_HPHPA_HD2_LEFT_MASK,
343 					      PM4125_SWR_HPHPA_HD2_ENABLE);
344 		break;
345 	case SND_SOC_DAPM_POST_PMU:
346 		if (pm4125->comp1_enable) {
347 			snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_COMP_CTL_0,
348 						      PM4125_DIG_SWR_COMP_HPHL_EN_MASK,
349 						      PM4125_DIG_SWR_COMP_ENABLE);
350 
351 			if (pm4125->comp2_enable)
352 				snd_soc_component_write_field(component,
353 							      PM4125_DIG_SWR_CDC_COMP_CTL_0,
354 							      PM4125_DIG_SWR_COMP_HPHR_EN_MASK,
355 							      PM4125_DIG_SWR_COMP_ENABLE);
356 			/*
357 			 * 5ms sleep is required after COMP is enabled as per
358 			 * HW requirement
359 			 */
360 			usleep_range(5000, 5100);
361 		} else {
362 			snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_COMP_CTL_0,
363 						      PM4125_DIG_SWR_COMP_HPHL_EN_MASK,
364 						      PM4125_DIG_SWR_COMP_DISABLE);
365 		}
366 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX0_CTL,
367 					      PM4125_DIG_SWR_DSM_DITHER_EN_MASK,
368 					      PM4125_DIG_SWR_DSM_DITHER_DISABLE);
369 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_GAIN_CTL,
370 					      PM4125_DIG_SWR_RX0_EN_MASK,
371 					      PM4125_DIG_SWR_RX_INPUT_ENABLE);
372 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL,
373 					      PM4125_DIG_SWR_RX0_CLK_EN_MASK,
374 					      PM4125_DIG_SWR_RX_CLK_ENABLE);
375 		break;
376 	case SND_SOC_DAPM_POST_PMD:
377 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL,
378 					      PM4125_DIG_SWR_RX0_CLK_EN_MASK,
379 					      PM4125_DIG_SWR_RX_CLK_DISABLE);
380 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_GAIN_CTL,
381 					      PM4125_DIG_SWR_RX0_EN_MASK,
382 					      PM4125_DIG_SWR_RX_INPUT_DISABLE);
383 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX0_CTL,
384 					      PM4125_DIG_SWR_DSM_DITHER_EN_MASK,
385 					      PM4125_DIG_SWR_DSM_DITHER_ENABLE);
386 		if (pm4125->comp1_enable)
387 			snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_COMP_CTL_0,
388 						      PM4125_DIG_SWR_COMP_HPHL_EN_MASK,
389 						      PM4125_DIG_SWR_COMP_DISABLE);
390 		break;
391 	}
392 
393 	return 0;
394 }
395 
396 static int pm4125_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
397 				       struct snd_kcontrol *kcontrol, int event)
398 {
399 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
400 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
401 
402 	switch (event) {
403 	case SND_SOC_DAPM_PRE_PMU:
404 		snd_soc_component_write_field(component, PM4125_ANA_HPHPA_CNP_CTL_1,
405 					      PM4125_ANA_HPHPA_CNP_CTL_1_EN_MASK,
406 					      PM4125_ANA_HPHPA_CNP_CTL_1_EN);
407 		snd_soc_component_write_field(component, PM4125_SWR_HPHPA_HD2,
408 					      PM4125_SWR_HPHPA_HD2_RIGHT_MASK,
409 					      PM4125_SWR_HPHPA_HD2_ENABLE);
410 		break;
411 	case SND_SOC_DAPM_POST_PMU:
412 		if (pm4125->comp2_enable) {
413 			snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_COMP_CTL_0,
414 						      PM4125_DIG_SWR_COMP_HPHR_EN_MASK,
415 						      PM4125_DIG_SWR_COMP_ENABLE);
416 			if (pm4125->comp1_enable)
417 				snd_soc_component_write_field(component,
418 							      PM4125_DIG_SWR_CDC_COMP_CTL_0,
419 							      PM4125_DIG_SWR_COMP_HPHL_EN_MASK,
420 							      PM4125_DIG_SWR_COMP_ENABLE);
421 			/*
422 			 * 5ms sleep is required after COMP is enabled
423 			 * as per HW requirement
424 			 */
425 			usleep_range(5000, 5100);
426 		} else {
427 			snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_COMP_CTL_0,
428 						      PM4125_DIG_SWR_COMP_HPHR_EN_MASK,
429 						      PM4125_DIG_SWR_COMP_DISABLE);
430 		}
431 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX1_CTL,
432 					      PM4125_DIG_SWR_DSM_DITHER_EN_MASK,
433 					      PM4125_DIG_SWR_DSM_DITHER_DISABLE);
434 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_GAIN_CTL,
435 					      PM4125_DIG_SWR_RX1_EN_MASK,
436 					      PM4125_DIG_SWR_RX_INPUT_ENABLE);
437 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL,
438 					      PM4125_DIG_SWR_RX1_CLK_EN_MASK,
439 					      PM4125_DIG_SWR_RX_CLK_ENABLE);
440 		break;
441 	case SND_SOC_DAPM_POST_PMD:
442 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL,
443 					      PM4125_DIG_SWR_RX1_CLK_EN_MASK,
444 					      PM4125_DIG_SWR_RX_CLK_DISABLE);
445 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_GAIN_CTL,
446 					      PM4125_DIG_SWR_RX1_EN_MASK,
447 					      PM4125_DIG_SWR_RX_INPUT_DISABLE);
448 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX1_CTL,
449 					      PM4125_DIG_SWR_DSM_DITHER_EN_MASK,
450 					      PM4125_DIG_SWR_DSM_DITHER_ENABLE);
451 		if (pm4125->comp2_enable)
452 			snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_COMP_CTL_0,
453 						      PM4125_DIG_SWR_COMP_HPHR_EN_MASK,
454 						      PM4125_DIG_SWR_COMP_DISABLE);
455 		break;
456 	}
457 
458 	return 0;
459 }
460 
461 static int pm4125_codec_ear_lo_dac_event(struct snd_soc_dapm_widget *w,
462 					 struct snd_kcontrol *kcontrol, int event)
463 {
464 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
465 
466 	switch (event) {
467 	case SND_SOC_DAPM_PRE_PMU:
468 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX0_CTL,
469 					      PM4125_DIG_SWR_DSM_DITHER_EN_MASK,
470 					      PM4125_DIG_SWR_DSM_DITHER_DISABLE);
471 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL,
472 					      PM4125_DIG_SWR_RX0_CLK_EN_MASK,
473 					      PM4125_DIG_SWR_RX_CLK_ENABLE);
474 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_GAIN_CTL,
475 					      PM4125_DIG_SWR_RX0_EN_MASK,
476 					      PM4125_DIG_SWR_RX_INPUT_ENABLE);
477 		break;
478 	case SND_SOC_DAPM_POST_PMD:
479 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL,
480 					      PM4125_DIG_SWR_RX0_CLK_EN_MASK,
481 					      PM4125_DIG_SWR_RX_CLK_DISABLE);
482 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_GAIN_CTL,
483 					      PM4125_DIG_SWR_RX0_EN_MASK,
484 					      PM4125_DIG_SWR_RX_INPUT_DISABLE);
485 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX0_CTL,
486 					      PM4125_DIG_SWR_DSM_DITHER_EN_MASK,
487 					      PM4125_DIG_SWR_DSM_DITHER_ENABLE);
488 		break;
489 	}
490 
491 	return 0;
492 }
493 
494 
495 static int pm4125_codec_enable_hphl_wdt_irq(struct snd_soc_dapm_widget *w,
496 					    struct snd_kcontrol *kcontrol, int event)
497 {
498 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
499 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
500 
501 	switch (event) {
502 	case SND_SOC_DAPM_POST_PMU:
503 		usleep_range(5000, 5100);
504 		enable_irq(pm4125->hphl_pdm_wd_int);
505 		break;
506 	case SND_SOC_DAPM_PRE_PMD:
507 		disable_irq_nosync(pm4125->hphl_pdm_wd_int);
508 		break;
509 	}
510 
511 	return 0;
512 }
513 
514 static int pm4125_codec_enable_hphr_wdt_irq(struct snd_soc_dapm_widget *w,
515 					    struct snd_kcontrol *kcontrol, int event)
516 {
517 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
518 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
519 
520 	switch (event) {
521 	case SND_SOC_DAPM_POST_PMU:
522 		usleep_range(5000, 5100);
523 		enable_irq(pm4125->hphr_pdm_wd_int);
524 		break;
525 	case SND_SOC_DAPM_PRE_PMD:
526 		disable_irq_nosync(pm4125->hphr_pdm_wd_int);
527 		break;
528 	}
529 
530 	return 0;
531 }
532 
533 static int pm4125_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
534 				       struct snd_kcontrol *kcontrol, int event)
535 {
536 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
537 
538 	switch (event) {
539 	case SND_SOC_DAPM_PRE_PMU:
540 		usleep_range(200, 210);
541 		snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL1,
542 					      PM4125_WDT_ENABLE_MASK,
543 					      (PM4125_WDT_ENABLE_RX1_M | PM4125_WDT_ENABLE_RX1_L));
544 		break;
545 	case SND_SOC_DAPM_POST_PMD:
546 		usleep_range(5000, 5100);
547 		snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL1,
548 					      PM4125_WDT_ENABLE_MASK, 0x00);
549 		break;
550 	}
551 
552 	return 0;
553 }
554 
555 static int pm4125_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
556 				       struct snd_kcontrol *kcontrol, int event)
557 {
558 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
559 
560 	switch (event) {
561 	case SND_SOC_DAPM_PRE_PMU:
562 		usleep_range(200, 210);
563 		snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL0,
564 					      PM4125_WDT_ENABLE_MASK,
565 					      (PM4125_WDT_ENABLE_RX0_M | PM4125_WDT_ENABLE_RX0_L));
566 		break;
567 	case SND_SOC_DAPM_POST_PMD:
568 		usleep_range(5000, 5100);
569 		snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL0,
570 					      PM4125_WDT_ENABLE_MASK, 0x00);
571 		break;
572 	}
573 
574 	return 0;
575 }
576 
577 static int pm4125_codec_enable_lo_pa(struct snd_soc_dapm_widget *w,
578 				     struct snd_kcontrol *kcontrol, int event)
579 {
580 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
581 
582 	switch (event) {
583 	case SND_SOC_DAPM_PRE_PMU:
584 		snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL_5, 0x04, 0x00);
585 		usleep_range(1000, 1010);
586 		snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL_4, 0x0F, 0x0F);
587 		usleep_range(1000, 1010);
588 		snd_soc_component_write_field(component, PM4125_ANA_COMBOPA_CTL,
589 					      PM4125_ANA_COMBO_PA_SELECT_MASK,
590 					      PM4125_ANA_COMBO_PA_SELECT_LO);
591 		snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL0,
592 					      PM4125_WDT_ENABLE_MASK,
593 					      (PM4125_WDT_ENABLE_RX0_M | PM4125_WDT_ENABLE_RX0_L));
594 		break;
595 	case SND_SOC_DAPM_POST_PMU:
596 		usleep_range(5000, 5010);
597 		snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL_4, 0x0F, 0x04);
598 		break;
599 	case SND_SOC_DAPM_POST_PMD:
600 		usleep_range(2000, 2010);
601 		snd_soc_component_write_field(component, PM4125_ANA_COMBOPA_CTL,
602 					      PM4125_ANA_COMBO_PA_SELECT_MASK,
603 					      PM4125_ANA_COMBO_PA_SELECT_EAR);
604 		usleep_range(5000, 5100);
605 		snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL0,
606 					      PM4125_WDT_ENABLE_MASK, 0x00);
607 		break;
608 	}
609 
610 	return 0;
611 }
612 
613 static int pm4125_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
614 				      struct snd_kcontrol *kcontrol, int event)
615 {
616 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
617 
618 	switch (event) {
619 	case SND_SOC_DAPM_PRE_PMU:
620 		snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL_5, 0x04, 0x00);
621 		usleep_range(1000, 1010);
622 		snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL_4, 0x0F, 0x0F);
623 		usleep_range(1000, 1010);
624 		snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL,
625 					      PM4125_ANA_COMBO_PA_SELECT_MASK,
626 					      PM4125_ANA_COMBO_PA_SELECT_EAR);
627 		snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL0,
628 					      PM4125_WDT_ENABLE_MASK,
629 					      (PM4125_WDT_ENABLE_RX0_M | PM4125_WDT_ENABLE_RX0_L));
630 		break;
631 	case SND_SOC_DAPM_POST_PMU:
632 		usleep_range(5000, 5010);
633 		snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL_4, 0x0F, 0x04);
634 		break;
635 	case SND_SOC_DAPM_POST_PMD:
636 		usleep_range(5000, 5010);
637 		snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL0,
638 					      PM4125_WDT_ENABLE_MASK, 0x00);
639 		break;
640 	}
641 
642 	return 0;
643 }
644 
645 static int pm4125_codec_enable_adc(struct snd_soc_dapm_widget *w,
646 				   struct snd_kcontrol *kcontrol, int event)
647 {
648 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
649 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
650 
651 	switch (event) {
652 	case SND_SOC_DAPM_PRE_PMU:
653 		/* Enable BCS for Headset mic */
654 		if (w->shift == 1 &&
655 			!(snd_soc_component_read(component, PM4125_ANA_TX_AMIC2) & 0x10)) {
656 			set_bit(AMIC2_BCS_ENABLE, &pm4125->status_mask);
657 		}
658 		pm4125_global_mbias_enable(component);
659 		if (w->shift)
660 			snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1,
661 						      PM4125_DIG_SWR_TX_ANA_TXD1_MODE_MASK,
662 						      PM4125_DIG_SWR_TXD_MODE_NORMAL);
663 		else
664 			snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1,
665 						      PM4125_DIG_SWR_TX_ANA_TXD0_MODE_MASK,
666 						      PM4125_DIG_SWR_TXD_MODE_NORMAL);
667 		break;
668 	case SND_SOC_DAPM_POST_PMD:
669 		if (w->shift == 1 && test_bit(AMIC2_BCS_ENABLE, &pm4125->status_mask))
670 			clear_bit(AMIC2_BCS_ENABLE, &pm4125->status_mask);
671 
672 		if (w->shift)
673 			snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1,
674 						      PM4125_DIG_SWR_TX_ANA_TXD1_MODE_MASK,
675 						      0x00);
676 		else
677 			snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1,
678 						      PM4125_DIG_SWR_TX_ANA_TXD0_MODE_MASK,
679 						      0x00);
680 		pm4125_global_mbias_disable(component);
681 		break;
682 	}
683 
684 	return 0;
685 }
686 
687 static int pm4125_codec_enable_dmic(struct snd_soc_dapm_widget *w,
688 				    struct snd_kcontrol *kcontrol, int event)
689 {
690 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
691 	u16 dmic_clk_reg = w->reg;
692 
693 	switch (event) {
694 	case SND_SOC_DAPM_PRE_PMU:
695 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_AMIC_CTL,
696 					      PM4125_DIG_SWR_AMIC_SELECT_MASK,
697 					      PM4125_DIG_SWR_AMIC_SELECT_DMIC1);
698 		snd_soc_component_update_bits(component, dmic_clk_reg,
699 					      PM4125_DIG_SWR_DMIC1_CLK_EN_MASK,
700 					      PM4125_DIG_SWR_DMIC1_CLK_ENABLE);
701 		break;
702 	case SND_SOC_DAPM_POST_PMD:
703 		snd_soc_component_update_bits(component, dmic_clk_reg,
704 					      PM4125_DIG_SWR_DMIC1_CLK_EN_MASK,
705 					      PM4125_DIG_SWR_DMIC1_CLK_DISABLE);
706 		snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_AMIC_CTL,
707 					      PM4125_DIG_SWR_AMIC_SELECT_MASK,
708 					      PM4125_DIG_SWR_AMIC_SELECT_AMIC3);
709 		break;
710 	}
711 
712 	return 0;
713 }
714 
715 static int pm4125_micbias_control(struct snd_soc_component *component, int micb_num, int req,
716 				  bool is_dapm)
717 {
718 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
719 	int micb_index = micb_num - 1;
720 	u16 micb_reg;
721 	u8 pullup_mask = 0, enable_mask = 0;
722 
723 	if ((micb_index < 0) || (micb_index > PM4125_MAX_MICBIAS - 1)) {
724 		dev_err(component->dev, "%s: Invalid micbias index, micb_ind:%d\n",
725 			__func__, micb_index);
726 		return -EINVAL;
727 	}
728 	switch (micb_num) {
729 	case MIC_BIAS_1:
730 		micb_reg = PM4125_ANA_MICBIAS_MICB_1_2_EN;
731 		pullup_mask = PM4125_ANA_MICBIAS_MICB1_PULL_UP_MASK;
732 		enable_mask = 0x40;
733 		break;
734 	case MIC_BIAS_2:
735 		micb_reg = PM4125_ANA_MICBIAS_MICB_1_2_EN;
736 		pullup_mask = PM4125_ANA_MICBIAS_MICB2_PULL_UP_MASK;
737 		enable_mask = 0x04;
738 		break;
739 	case MIC_BIAS_3:
740 		micb_reg = PM4125_ANA_MICBIAS_MICB_3_EN;
741 		pullup_mask = 0x02;
742 		break;
743 	default:
744 		dev_err(component->dev, "%s: Invalid micbias number: %d\n",
745 			__func__, micb_num);
746 		return -EINVAL;
747 	}
748 
749 	switch (req) {
750 	case MICB_PULLUP_ENABLE:
751 		pm4125->pullup_ref[micb_index]++;
752 		if ((pm4125->pullup_ref[micb_index] == 1) &&
753 		    (pm4125->micb_ref[micb_index] == 0))
754 			snd_soc_component_update_bits(component, micb_reg,
755 						      pullup_mask, pullup_mask);
756 		break;
757 	case MICB_PULLUP_DISABLE:
758 		if (pm4125->pullup_ref[micb_index] > 0)
759 			pm4125->pullup_ref[micb_index]--;
760 		if ((pm4125->pullup_ref[micb_index] == 0) &&
761 		    (pm4125->micb_ref[micb_index] == 0))
762 			snd_soc_component_update_bits(component, micb_reg,
763 						      pullup_mask, 0x00);
764 		break;
765 	case MICB_ENABLE:
766 		pm4125->micb_ref[micb_index]++;
767 		if (pm4125->micb_ref[micb_index] == 1) {
768 			pm4125_global_mbias_enable(component);
769 			snd_soc_component_update_bits(component, micb_reg,
770 						      enable_mask, enable_mask);
771 		}
772 		break;
773 	case MICB_DISABLE:
774 		if (pm4125->micb_ref[micb_index] > 0)
775 			pm4125->micb_ref[micb_index]--;
776 		if ((pm4125->micb_ref[micb_index] == 0) &&
777 		    (pm4125->pullup_ref[micb_index] > 0)) {
778 			snd_soc_component_update_bits(component, micb_reg,
779 						      pullup_mask, pullup_mask);
780 			snd_soc_component_update_bits(component, micb_reg,
781 						      enable_mask, 0x00);
782 			pm4125_global_mbias_disable(component);
783 		} else if ((pm4125->micb_ref[micb_index] == 0) &&
784 			   (pm4125->pullup_ref[micb_index] == 0)) {
785 			snd_soc_component_update_bits(component, micb_reg,
786 						      enable_mask, 0x00);
787 			pm4125_global_mbias_disable(component);
788 		}
789 		break;
790 	}
791 
792 	return 0;
793 }
794 
795 static int pm4125_codec_enable_micbias(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
796 				       int event)
797 {
798 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
799 	int micb_num = w->shift;
800 
801 	switch (event) {
802 	case SND_SOC_DAPM_PRE_PMU:
803 		if (micb_num == MIC_BIAS_3)
804 			pm4125_micbias_control(component, micb_num, MICB_PULLUP_ENABLE, true);
805 		else
806 			pm4125_micbias_control(component, micb_num, MICB_ENABLE, true);
807 		break;
808 	case SND_SOC_DAPM_POST_PMU:
809 		usleep_range(1000, 1100);
810 		break;
811 	case SND_SOC_DAPM_POST_PMD:
812 		if (micb_num == MIC_BIAS_3)
813 			pm4125_micbias_control(component, micb_num, MICB_PULLUP_DISABLE, true);
814 		else
815 			pm4125_micbias_control(component, micb_num, MICB_DISABLE, true);
816 		break;
817 	}
818 
819 	return 0;
820 }
821 
822 static int pm4125_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,
823 					      struct snd_kcontrol *kcontrol, int event)
824 {
825 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
826 	int micb_num = w->shift;
827 
828 	switch (event) {
829 	case SND_SOC_DAPM_PRE_PMU:
830 		pm4125_micbias_control(component, micb_num, MICB_PULLUP_ENABLE, true);
831 		break;
832 	case SND_SOC_DAPM_POST_PMU:
833 		usleep_range(1000, 1100);
834 		break;
835 	case SND_SOC_DAPM_POST_PMD:
836 		pm4125_micbias_control(component, micb_num, MICB_PULLUP_DISABLE, true);
837 		break;
838 	}
839 
840 	return 0;
841 }
842 
843 static int pm4125_connect_port(struct pm4125_sdw_priv *sdw_priv, u8 port_idx, u8 ch_id, bool enable)
844 {
845 	struct sdw_port_config *port_config = &sdw_priv->port_config[port_idx - 1];
846 	const struct wcd_sdw_ch_info *ch_info = &sdw_priv->ch_info[ch_id];
847 	struct sdw_slave *sdev = sdw_priv->sdev;
848 	u8 port_num = ch_info->port_num;
849 	u8 ch_mask = ch_info->ch_mask;
850 	u8 mstr_port_num, mstr_ch_mask;
851 
852 	port_config->num = port_num;
853 
854 	mstr_port_num = sdev->m_port_map[port_num];
855 	mstr_ch_mask = ch_info->master_ch_mask;
856 
857 	if (enable) {
858 		port_config->ch_mask |= ch_mask;
859 		sdw_priv->master_channel_map[mstr_port_num] |= mstr_ch_mask;
860 	} else {
861 		port_config->ch_mask &= ~ch_mask;
862 		sdw_priv->master_channel_map[mstr_port_num] &= ~mstr_ch_mask;
863 	}
864 
865 	return 0;
866 }
867 
868 static int pm4125_get_compander(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
869 {
870 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
871 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
872 	struct soc_mixer_control *mc;
873 	bool hphr;
874 
875 	mc = (struct soc_mixer_control *)(kcontrol->private_value);
876 	hphr = mc->shift;
877 
878 	ucontrol->value.integer.value[0] = hphr ? pm4125->comp2_enable : pm4125->comp1_enable;
879 	return 0;
880 }
881 
882 static int pm4125_set_compander(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
883 {
884 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
885 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
886 	struct pm4125_sdw_priv *sdw_priv = pm4125->sdw_priv[AIF1_PB];
887 	int value = ucontrol->value.integer.value[0];
888 	struct soc_mixer_control *mc;
889 	int portidx;
890 	bool hphr;
891 
892 	mc = (struct soc_mixer_control *)(kcontrol->private_value);
893 	hphr = mc->shift;
894 
895 	if (hphr) {
896 		if (value == pm4125->comp2_enable)
897 			return 0;
898 
899 		pm4125->comp2_enable = value;
900 	} else {
901 		if (value == pm4125->comp1_enable)
902 			return 0;
903 
904 		pm4125->comp1_enable = value;
905 	}
906 
907 	portidx = sdw_priv->ch_info[mc->reg].port_num;
908 
909 	pm4125_connect_port(sdw_priv, portidx, mc->reg, value ? true : false);
910 
911 	return 1;
912 }
913 
914 static int pm4125_get_swr_port(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
915 {
916 	struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value;
917 	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
918 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(comp);
919 	struct pm4125_sdw_priv *sdw_priv;
920 	int dai_id = mixer->shift;
921 	int ch_idx = mixer->reg;
922 	int portidx;
923 
924 	sdw_priv = pm4125->sdw_priv[dai_id];
925 	portidx = sdw_priv->ch_info[ch_idx].port_num;
926 
927 	ucontrol->value.integer.value[0] = sdw_priv->port_enable[portidx];
928 
929 	return 0;
930 }
931 
932 static int pm4125_set_swr_port(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
933 {
934 	struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value;
935 	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
936 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(comp);
937 	struct pm4125_sdw_priv *sdw_priv;
938 	int dai_id = mixer->shift;
939 	int ch_idx = mixer->reg;
940 	int portidx;
941 	bool enable;
942 
943 	sdw_priv = pm4125->sdw_priv[dai_id];
944 
945 	portidx = sdw_priv->ch_info[ch_idx].port_num;
946 
947 	enable = ucontrol->value.integer.value[0];
948 
949 	if (enable == sdw_priv->port_enable[portidx]) {
950 		pm4125_connect_port(sdw_priv, portidx, ch_idx, enable);
951 		return 0;
952 	}
953 
954 	sdw_priv->port_enable[portidx] = enable;
955 	pm4125_connect_port(sdw_priv, portidx, ch_idx, enable);
956 
957 	return 1;
958 }
959 
960 static void pm4125_mbhc_bias_control(struct snd_soc_component *component, bool enable)
961 {
962 	snd_soc_component_write_field(component, PM4125_ANA_MBHC_ELECT,
963 				      PM4125_ANA_MBHC_ELECT_BIAS_EN_MASK,
964 				      enable ? PM4125_ANA_MBHC_ELECT_BIAS_ENABLE :
965 					       PM4125_ANA_MBHC_ELECT_BIAS_DISABLE);
966 }
967 
968 static void pm4125_mbhc_program_btn_thr(struct snd_soc_component *component,
969 					int *btn_low, int *btn_high,
970 					int num_btn, bool is_micbias)
971 {
972 	int i, vth;
973 
974 	if (num_btn > WCD_MBHC_DEF_BUTTONS) {
975 		dev_err(component->dev, "%s: invalid number of buttons: %d\n",
976 			__func__, num_btn);
977 		return;
978 	}
979 
980 	for (i = 0; i < num_btn; i++) {
981 		vth = ((btn_high[i] * 2) / 25) & 0x3F;
982 		snd_soc_component_write_field(component, PM4125_ANA_MBHC_BTN0_ZDET_VREF1 + i,
983 					      PM4125_ANA_MBHC_BTN0_THRESHOLD_MASK, vth << 2);
984 	}
985 }
986 
987 static const struct wcd_mbhc_cb mbhc_cb = {
988 	.mbhc_bias = pm4125_mbhc_bias_control,
989 	.set_btn_thr = pm4125_mbhc_program_btn_thr,
990 };
991 
992 static int pm4125_mbhc_init(struct snd_soc_component *component)
993 {
994 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
995 	struct wcd_mbhc_intr *intr_ids = &pm4125->intr_ids;
996 
997 	intr_ids->mbhc_sw_intr = regmap_irq_get_virq(pm4125->irq_chip, PM4125_IRQ_MBHC_SW_DET);
998 
999 	intr_ids->mbhc_btn_press_intr = regmap_irq_get_virq(pm4125->irq_chip,
1000 							    PM4125_IRQ_MBHC_BUTTON_PRESS_DET);
1001 
1002 	intr_ids->mbhc_btn_release_intr = regmap_irq_get_virq(pm4125->irq_chip,
1003 							      PM4125_IRQ_MBHC_BUTTON_RELEASE_DET);
1004 
1005 	intr_ids->mbhc_hs_ins_intr = regmap_irq_get_virq(pm4125->irq_chip,
1006 							 PM4125_IRQ_MBHC_ELECT_INS_REM_LEG_DET);
1007 
1008 	intr_ids->mbhc_hs_rem_intr = regmap_irq_get_virq(pm4125->irq_chip,
1009 							 PM4125_IRQ_MBHC_ELECT_INS_REM_DET);
1010 
1011 	intr_ids->hph_left_ocp = regmap_irq_get_virq(pm4125->irq_chip, PM4125_IRQ_HPHL_OCP_INT);
1012 
1013 	intr_ids->hph_right_ocp = regmap_irq_get_virq(pm4125->irq_chip, PM4125_IRQ_HPHR_OCP_INT);
1014 
1015 	pm4125->wcd_mbhc = wcd_mbhc_init(component, &mbhc_cb, intr_ids, pm4125_mbhc_fields, false);
1016 	if (IS_ERR(pm4125->wcd_mbhc))
1017 		return PTR_ERR(pm4125->wcd_mbhc);
1018 
1019 	return 0;
1020 }
1021 
1022 static void pm4125_mbhc_deinit(struct snd_soc_component *component)
1023 {
1024 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
1025 
1026 	wcd_mbhc_deinit(pm4125->wcd_mbhc);
1027 }
1028 
1029 static const struct snd_kcontrol_new pm4125_snd_controls[] = {
1030 	SOC_SINGLE_EXT("HPHL_COMP Switch", PM4125_COMP_L, 0, 1, 0,
1031 		       pm4125_get_compander, pm4125_set_compander),
1032 	SOC_SINGLE_EXT("HPHR_COMP Switch", PM4125_COMP_R, 1, 1, 0,
1033 		       pm4125_get_compander, pm4125_set_compander),
1034 
1035 	SOC_SINGLE_TLV("HPHL Volume", PM4125_ANA_HPHPA_L_GAIN, 0, 20, 1,
1036 		       line_gain),
1037 	SOC_SINGLE_TLV("HPHR Volume", PM4125_ANA_HPHPA_R_GAIN, 0, 20, 1,
1038 		       line_gain),
1039 	SOC_SINGLE_TLV("ADC1 Volume", PM4125_ANA_TX_AMIC1, 0, 8, 0,
1040 		       analog_gain),
1041 	SOC_SINGLE_TLV("ADC2 Volume", PM4125_ANA_TX_AMIC2, 0, 8, 0,
1042 		       analog_gain),
1043 
1044 	SOC_SINGLE_EXT("HPHL Switch", PM4125_HPH_L, 0, 1, 0,
1045 		       pm4125_get_swr_port, pm4125_set_swr_port),
1046 	SOC_SINGLE_EXT("HPHR Switch", PM4125_HPH_R, 0, 1, 0,
1047 		       pm4125_get_swr_port, pm4125_set_swr_port),
1048 
1049 	SOC_SINGLE_EXT("ADC1 Switch", PM4125_ADC1, 1, 1, 0,
1050 		       pm4125_get_swr_port, pm4125_set_swr_port),
1051 	SOC_SINGLE_EXT("ADC2 Switch", PM4125_ADC2, 1, 1, 0,
1052 		       pm4125_get_swr_port, pm4125_set_swr_port),
1053 };
1054 
1055 static const struct snd_kcontrol_new adc1_switch[] = {
1056 	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
1057 };
1058 
1059 static const struct snd_kcontrol_new adc2_switch[] = {
1060 	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
1061 };
1062 
1063 static const struct snd_kcontrol_new dmic1_switch[] = {
1064 	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
1065 };
1066 
1067 static const struct snd_kcontrol_new dmic2_switch[] = {
1068 	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
1069 };
1070 
1071 static const struct snd_kcontrol_new ear_rdac_switch[] = {
1072 	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
1073 };
1074 
1075 static const struct snd_kcontrol_new lo_rdac_switch[] = {
1076 	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
1077 };
1078 
1079 static const struct snd_kcontrol_new hphl_rdac_switch[] = {
1080 	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
1081 };
1082 
1083 static const struct snd_kcontrol_new hphr_rdac_switch[] = {
1084 	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
1085 };
1086 
1087 static const char * const adc2_mux_text[] = {
1088 	"INP2", "INP3"
1089 };
1090 
1091 static const struct soc_enum adc2_enum = SOC_ENUM_SINGLE(PM4125_ANA_TX_AMIC2, 4,
1092 							 ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
1093 
1094 static const struct snd_kcontrol_new tx_adc2_mux = SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum);
1095 
1096 static const struct snd_soc_dapm_widget pm4125_dapm_widgets[] = {
1097 	/* Input widgets */
1098 	SND_SOC_DAPM_INPUT("AMIC1"),
1099 	SND_SOC_DAPM_INPUT("AMIC2"),
1100 	SND_SOC_DAPM_INPUT("AMIC3"),
1101 	SND_SOC_DAPM_INPUT("IN1_HPHL"),
1102 	SND_SOC_DAPM_INPUT("IN2_HPHR"),
1103 
1104 	/* TX widgets */
1105 	SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0, pm4125_codec_enable_adc,
1106 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1107 	SND_SOC_DAPM_ADC_E("ADC2", NULL, SND_SOC_NOPM, 1, 0, pm4125_codec_enable_adc,
1108 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1109 
1110 	SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0, &tx_adc2_mux),
1111 
1112 	/* TX mixers */
1113 	SND_SOC_DAPM_MIXER("ADC1_MIXER", SND_SOC_NOPM, 0, 0, adc1_switch, ARRAY_SIZE(adc1_switch)),
1114 	SND_SOC_DAPM_MIXER("ADC2_MIXER", SND_SOC_NOPM, 1, 0, adc2_switch, ARRAY_SIZE(adc2_switch)),
1115 
1116 	/* MIC_BIAS widgets */
1117 	SND_SOC_DAPM_SUPPLY("MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0, pm4125_codec_enable_micbias,
1118 			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1119 	SND_SOC_DAPM_SUPPLY("MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0, pm4125_codec_enable_micbias,
1120 			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1121 	SND_SOC_DAPM_SUPPLY("MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0, pm4125_codec_enable_micbias,
1122 			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1123 
1124 	SND_SOC_DAPM_SUPPLY("PA_VPOS", SND_SOC_NOPM, 0, 0, NULL, 0),
1125 
1126 	/* RX widgets */
1127 	SND_SOC_DAPM_PGA_E("EAR PGA", PM4125_ANA_COMBOPA_CTL, 7, 0, NULL, 0,
1128 			   pm4125_codec_enable_ear_pa,
1129 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
1130 			   SND_SOC_DAPM_POST_PMD),
1131 	SND_SOC_DAPM_PGA_E("LO PGA", PM4125_ANA_COMBOPA_CTL, 7, 0, NULL, 0,
1132 			   pm4125_codec_enable_lo_pa,
1133 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
1134 			   SND_SOC_DAPM_POST_PMD),
1135 	SND_SOC_DAPM_PGA_E("HPHL PGA", PM4125_ANA_HPHPA_CNP_CTL_2, 7, 0, NULL, 0,
1136 			   pm4125_codec_enable_hphl_pa,
1137 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1138 	SND_SOC_DAPM_PGA_E("HPHR PGA", PM4125_ANA_HPHPA_CNP_CTL_2, 6, 0, NULL, 0,
1139 			   pm4125_codec_enable_hphr_pa,
1140 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1141 
1142 	SND_SOC_DAPM_DAC_E("RDAC1", NULL, SND_SOC_NOPM, 0, 0, pm4125_codec_hphl_dac_event,
1143 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
1144 			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
1145 	SND_SOC_DAPM_DAC_E("RDAC2", NULL, SND_SOC_NOPM, 0, 0, pm4125_codec_hphr_dac_event,
1146 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
1147 			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
1148 	SND_SOC_DAPM_DAC_E("RDAC3", NULL, SND_SOC_NOPM, 0, 0, pm4125_codec_ear_lo_dac_event,
1149 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
1150 			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
1151 
1152 
1153 	SND_SOC_DAPM_SUPPLY("HPHL_WDT_IRQ", SND_SOC_NOPM, 0, 0, pm4125_codec_enable_hphl_wdt_irq,
1154 			    SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
1155 	SND_SOC_DAPM_SUPPLY("HPHR_WDT_IRQ", SND_SOC_NOPM, 0, 0, pm4125_codec_enable_hphr_wdt_irq,
1156 			    SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
1157 	SND_SOC_DAPM_SUPPLY("RXCLK", SND_SOC_NOPM, 0, 0, pm4125_codec_enable_rxclk,
1158 			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1159 	SND_SOC_DAPM_MIXER_E("RX1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
1160 	SND_SOC_DAPM_MIXER_E("RX2", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
1161 
1162 	/* RX mixer widgets */
1163 	SND_SOC_DAPM_MIXER("EAR_RDAC", SND_SOC_NOPM, 0, 0, ear_rdac_switch,
1164 			   ARRAY_SIZE(ear_rdac_switch)),
1165 	SND_SOC_DAPM_MIXER("LO_RDAC", SND_SOC_NOPM, 0, 0, lo_rdac_switch,
1166 			   ARRAY_SIZE(lo_rdac_switch)),
1167 	SND_SOC_DAPM_MIXER("HPHL_RDAC", SND_SOC_NOPM, 0, 0, hphl_rdac_switch,
1168 			   ARRAY_SIZE(hphl_rdac_switch)),
1169 	SND_SOC_DAPM_MIXER("HPHR_RDAC", SND_SOC_NOPM, 0, 0, hphr_rdac_switch,
1170 			   ARRAY_SIZE(hphr_rdac_switch)),
1171 
1172 	/* TX output widgets */
1173 	SND_SOC_DAPM_OUTPUT("ADC1_OUTPUT"),
1174 	SND_SOC_DAPM_OUTPUT("ADC2_OUTPUT"),
1175 
1176 	/* RX output widgets */
1177 	SND_SOC_DAPM_OUTPUT("EAR"),
1178 	SND_SOC_DAPM_OUTPUT("LO"),
1179 	SND_SOC_DAPM_OUTPUT("HPHL"),
1180 	SND_SOC_DAPM_OUTPUT("HPHR"),
1181 
1182 	/* MIC_BIAS pull up widgets */
1183 	SND_SOC_DAPM_SUPPLY("VA MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0,
1184 			    pm4125_codec_enable_micbias_pullup,
1185 			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1186 	SND_SOC_DAPM_SUPPLY("VA MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0,
1187 			    pm4125_codec_enable_micbias_pullup,
1188 			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1189 	SND_SOC_DAPM_SUPPLY("VA MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0,
1190 			    pm4125_codec_enable_micbias_pullup,
1191 			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1192 
1193 	/* TX widgets */
1194 	SND_SOC_DAPM_ADC_E("DMIC1", NULL, PM4125_DIG_SWR_CDC_DMIC1_CTL, 0, 0,
1195 			   pm4125_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1196 	SND_SOC_DAPM_ADC_E("DMIC2", NULL, PM4125_DIG_SWR_CDC_DMIC1_CTL, 1, 0,
1197 			   pm4125_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1198 
1199 	/* TX mixer widgets */
1200 	SND_SOC_DAPM_MIXER("DMIC1_MIXER", SND_SOC_NOPM, 0, 0, dmic1_switch,
1201 			   ARRAY_SIZE(dmic1_switch)),
1202 	SND_SOC_DAPM_MIXER("DMIC2_MIXER", SND_SOC_NOPM, 1, 0, dmic2_switch,
1203 			   ARRAY_SIZE(dmic2_switch)),
1204 
1205 	/* Output widgets */
1206 	SND_SOC_DAPM_OUTPUT("DMIC1_OUTPUT"),
1207 	SND_SOC_DAPM_OUTPUT("DMIC2_OUTPUT"),
1208 };
1209 
1210 static const struct snd_soc_dapm_route pm4125_audio_map[] = {
1211 	{ "ADC1_OUTPUT", NULL, "ADC1_MIXER" },
1212 	{ "ADC1_MIXER", "Switch", "ADC1" },
1213 	{ "ADC1", NULL, "AMIC1" },
1214 
1215 	{ "ADC2_OUTPUT", NULL, "ADC2_MIXER" },
1216 	{ "ADC2_MIXER", "Switch", "ADC2" },
1217 	{ "ADC2", NULL, "ADC2 MUX" },
1218 	{ "ADC2 MUX", "INP3", "AMIC3" },
1219 	{ "ADC2 MUX", "INP2", "AMIC2" },
1220 
1221 	{ "IN1_HPHL", NULL, "PA_VPOS" },
1222 	{ "RX1", NULL, "IN1_HPHL" },
1223 	{ "RX1", NULL, "RXCLK" },
1224 	{ "RX1", NULL, "HPHL_WDT_IRQ" },
1225 	{ "RDAC1", NULL, "RX1" },
1226 	{ "HPHL_RDAC", "Switch", "RDAC1" },
1227 	{ "HPHL PGA", NULL, "HPHL_RDAC" },
1228 	{ "HPHL", NULL, "HPHL PGA" },
1229 
1230 	{ "IN2_HPHR", NULL, "PA_VPOS" },
1231 	{ "RX2", NULL, "IN2_HPHR" },
1232 	{ "RX2", NULL, "RXCLK" },
1233 	{ "RX2", NULL, "HPHR_WDT_IRQ" },
1234 	{ "RDAC2", NULL, "RX2" },
1235 	{ "HPHR_RDAC", "Switch", "RDAC2" },
1236 	{ "HPHR PGA", NULL, "HPHR_RDAC" },
1237 	{ "HPHR", NULL, "HPHR PGA" },
1238 
1239 	{ "RDAC3", NULL, "RX1" },
1240 	{ "EAR_RDAC", "Switch", "RDAC3" },
1241 	{ "EAR PGA", NULL, "EAR_RDAC" },
1242 	{ "EAR", NULL, "EAR PGA" },
1243 
1244 	{ "LO_RDAC", "Switch", "RDAC3" },
1245 	{ "LO PGA", NULL, "LO_RDAC" },
1246 	{ "LO", NULL, "LO PGA" },
1247 
1248 	{ "DMIC1_OUTPUT", NULL, "DMIC1_MIXER" },
1249 	{ "DMIC1_MIXER", "Switch", "DMIC1" },
1250 
1251 	{ "DMIC2_OUTPUT", NULL, "DMIC2_MIXER" },
1252 	{ "DMIC2_MIXER", "Switch", "DMIC2" },
1253 };
1254 
1255 static int pm4125_set_micbias_data(struct device *dev, struct pm4125_priv *pm4125)
1256 {
1257 	regmap_update_bits(pm4125->regmap, PM4125_ANA_MICBIAS_LDO_1_SETTING,
1258 			   PM4125_ANA_MICBIAS_MICB_OUT_VAL_MASK, pm4125->common.micb_vout[0]);
1259 	return 0;
1260 }
1261 
1262 static irqreturn_t pm4125_wd_handle_irq(int irq, void *data)
1263 {
1264 	/*
1265 	 * HPHR/HPHL Watchdog interrupt threaded handler
1266 	 * Watchdog interrupts are expected to be enabled when switching on the HPHL/R
1267 	 * in order to make sure the interrupts are acked by the regmap_irq handler
1268 	 * io allow PDM sync. We could leave those interrupts masked but we would
1269 	 * not haveany valid way to enable/disable them without violating irq layers.
1270 	 *
1271 	 * The HPHR/HPHL Watchdog interrupts are handled by regmap_irq, so requesting
1272 	 * a threaded handler is the safest way to be able to ack those interrupts
1273 	 * without colliding with the regmap_irq setup.
1274 	 */
1275 	return IRQ_HANDLED;
1276 }
1277 
1278 static const struct irq_chip pm4125_codec_irq_chip = {
1279 	.name = "pm4125_codec",
1280 };
1281 
1282 static int pm4125_codec_irq_chip_map(struct irq_domain *irqd, unsigned int virq,
1283 				     irq_hw_number_t hw)
1284 {
1285 	irq_set_chip_and_handler(virq, &pm4125_codec_irq_chip, handle_simple_irq);
1286 	irq_set_nested_thread(virq, 1);
1287 	irq_set_noprobe(virq);
1288 
1289 	return 0;
1290 }
1291 
1292 static const struct irq_domain_ops pm4125_domain_ops = {
1293 	.map = pm4125_codec_irq_chip_map,
1294 };
1295 
1296 static int pm4125_irq_init(struct pm4125_priv *pm4125, struct device *dev)
1297 {
1298 	pm4125->virq = irq_domain_add_linear(NULL, 1, &pm4125_domain_ops, NULL);
1299 	if (!(pm4125->virq)) {
1300 		dev_err(dev, "%s: Failed to add IRQ domain\n", __func__);
1301 		return -EINVAL;
1302 	}
1303 
1304 	return devm_regmap_add_irq_chip(dev, pm4125->regmap, irq_create_mapping(pm4125->virq, 0),
1305 					IRQF_ONESHOT, 0, pm4125->chip_desc,
1306 					&pm4125->irq_chip);
1307 }
1308 
1309 static int pm4125_soc_codec_probe(struct snd_soc_component *component)
1310 {
1311 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
1312 	struct sdw_slave *tx_sdw_dev = pm4125->tx_sdw_dev;
1313 	struct device *dev = component->dev;
1314 	unsigned long time_left;
1315 	int i, ret;
1316 
1317 	time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete,
1318 						msecs_to_jiffies(5000));
1319 	if (!time_left) {
1320 		dev_err(dev, "soundwire device init timeout\n");
1321 		return -ETIMEDOUT;
1322 	}
1323 
1324 	snd_soc_component_init_regmap(component, pm4125->regmap);
1325 	ret = pm_runtime_resume_and_get(dev);
1326 	if (ret < 0)
1327 		return ret;
1328 
1329 	pm4125_io_init(pm4125->regmap);
1330 
1331 	/* Set all interrupts as edge triggered */
1332 	for (i = 0; i < pm4125_regmap_irq_chip.num_regs; i++)
1333 		regmap_write(pm4125->regmap, (PM4125_DIG_SWR_INTR_LEVEL_0 + i), 0);
1334 
1335 	pm_runtime_put(dev);
1336 
1337 	pm4125->hphr_pdm_wd_int = regmap_irq_get_virq(pm4125->irq_chip, PM4125_IRQ_HPHR_PDM_WD_INT);
1338 	pm4125->hphl_pdm_wd_int = regmap_irq_get_virq(pm4125->irq_chip, PM4125_IRQ_HPHL_PDM_WD_INT);
1339 
1340 	/* Request for watchdog interrupts */
1341 	ret = devm_request_threaded_irq(dev, pm4125->hphr_pdm_wd_int, NULL, pm4125_wd_handle_irq,
1342 					IRQF_ONESHOT | IRQF_TRIGGER_RISING,
1343 					"HPHR PDM WDOG INT", pm4125);
1344 	if (ret)
1345 		dev_err(dev, "Failed to request HPHR wdt interrupt: %d\n", ret);
1346 
1347 	ret = devm_request_threaded_irq(dev, pm4125->hphl_pdm_wd_int, NULL, pm4125_wd_handle_irq,
1348 					IRQF_ONESHOT | IRQF_TRIGGER_RISING,
1349 					"HPHL PDM WDOG INT", pm4125);
1350 	if (ret)
1351 		dev_err(dev, "Failed to request HPHL wdt interrupt: %d\n", ret);
1352 
1353 	disable_irq_nosync(pm4125->hphr_pdm_wd_int);
1354 	disable_irq_nosync(pm4125->hphl_pdm_wd_int);
1355 
1356 	ret = pm4125_mbhc_init(component);
1357 	if (ret)
1358 		dev_err(component->dev, "mbhc initialization failed\n");
1359 
1360 	return ret;
1361 }
1362 
1363 static void pm4125_soc_codec_remove(struct snd_soc_component *component)
1364 {
1365 	struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
1366 
1367 	pm4125_mbhc_deinit(component);
1368 	free_irq(pm4125->hphl_pdm_wd_int, pm4125);
1369 	free_irq(pm4125->hphr_pdm_wd_int, pm4125);
1370 }
1371 
1372 static int pm4125_codec_set_jack(struct snd_soc_component *comp, struct snd_soc_jack *jack,
1373 				 void *data)
1374 {
1375 	struct pm4125_priv *pm4125 = dev_get_drvdata(comp->dev);
1376 	int ret = 0;
1377 
1378 	if (jack)
1379 		ret = wcd_mbhc_start(pm4125->wcd_mbhc, &pm4125->mbhc_cfg, jack);
1380 	else
1381 		wcd_mbhc_stop(pm4125->wcd_mbhc);
1382 
1383 	return ret;
1384 }
1385 
1386 static const struct snd_soc_component_driver soc_codec_dev_pm4125 = {
1387 	.name = "pm4125_codec",
1388 	.probe = pm4125_soc_codec_probe,
1389 	.remove = pm4125_soc_codec_remove,
1390 	.controls = pm4125_snd_controls,
1391 	.num_controls = ARRAY_SIZE(pm4125_snd_controls),
1392 	.dapm_widgets = pm4125_dapm_widgets,
1393 	.num_dapm_widgets = ARRAY_SIZE(pm4125_dapm_widgets),
1394 	.dapm_routes = pm4125_audio_map,
1395 	.num_dapm_routes = ARRAY_SIZE(pm4125_audio_map),
1396 	.set_jack = pm4125_codec_set_jack,
1397 	.endianness = 1,
1398 };
1399 
1400 static int pm4125_codec_hw_params(struct snd_pcm_substream *substream,
1401 				  struct snd_pcm_hw_params *params,
1402 				  struct snd_soc_dai *dai)
1403 {
1404 	struct pm4125_priv *pm4125 = dev_get_drvdata(dai->dev);
1405 	struct pm4125_sdw_priv *sdw_priv = pm4125->sdw_priv[dai->id];
1406 
1407 	return pm4125_sdw_hw_params(sdw_priv, substream, params, dai);
1408 }
1409 
1410 static int pm4125_codec_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
1411 {
1412 	struct pm4125_priv *pm4125 = dev_get_drvdata(dai->dev);
1413 	struct pm4125_sdw_priv *sdw_priv = pm4125->sdw_priv[dai->id];
1414 
1415 	return sdw_stream_remove_slave(sdw_priv->sdev, sdw_priv->sruntime);
1416 }
1417 
1418 static int pm4125_codec_set_sdw_stream(struct snd_soc_dai *dai, void *stream, int direction)
1419 {
1420 	struct pm4125_priv *pm4125 = dev_get_drvdata(dai->dev);
1421 	struct pm4125_sdw_priv *sdw_priv = pm4125->sdw_priv[dai->id];
1422 
1423 	sdw_priv->sruntime = stream;
1424 
1425 	return 0;
1426 }
1427 
1428 static int pm4125_get_channel_map(const struct snd_soc_dai *dai,
1429 				  unsigned int *tx_num, unsigned int *tx_slot,
1430 				  unsigned int *rx_num, unsigned int *rx_slot)
1431 {
1432 	struct pm4125_priv *pm4125 = dev_get_drvdata(dai->dev);
1433 	struct pm4125_sdw_priv *sdw_priv = pm4125->sdw_priv[dai->id];
1434 	int i;
1435 
1436 	switch (dai->id) {
1437 	case AIF1_PB:
1438 		if (!rx_slot || !rx_num) {
1439 			dev_err(dai->dev, "Invalid rx_slot %p or rx_num %p\n", rx_slot, rx_num);
1440 			return -EINVAL;
1441 		}
1442 
1443 		for (i = 0; i < SDW_MAX_PORTS; i++)
1444 			rx_slot[i] = sdw_priv->master_channel_map[i];
1445 
1446 		*rx_num = i;
1447 		break;
1448 	case AIF1_CAP:
1449 		if (!tx_slot || !tx_num) {
1450 			dev_err(dai->dev, "Invalid tx_slot %p or tx_num %p\n", tx_slot, tx_num);
1451 			return -EINVAL;
1452 		}
1453 
1454 		for (i = 0; i < SDW_MAX_PORTS; i++)
1455 			tx_slot[i] = sdw_priv->master_channel_map[i];
1456 
1457 		*tx_num = i;
1458 		break;
1459 	default:
1460 		break;
1461 	}
1462 
1463 	return 0;
1464 }
1465 
1466 static const struct snd_soc_dai_ops pm4125_sdw_dai_ops = {
1467 	.hw_params = pm4125_codec_hw_params,
1468 	.hw_free = pm4125_codec_free,
1469 	.set_stream = pm4125_codec_set_sdw_stream,
1470 	.get_channel_map = pm4125_get_channel_map,
1471 };
1472 
1473 static struct snd_soc_dai_driver pm4125_dais[] = {
1474 	[0] = {
1475 		.name = "pm4125-sdw-rx",
1476 		.playback = {
1477 			.stream_name = "PM4125 AIF Playback",
1478 			.rates = PM4125_RATES | PM4125_FRAC_RATES,
1479 			.formats = PM4125_FORMATS,
1480 			.rate_min = 8000,
1481 			.rate_max = 384000,
1482 			.channels_min = 1,
1483 			.channels_max = 4,
1484 		},
1485 		.ops = &pm4125_sdw_dai_ops,
1486 	},
1487 	[1] = {
1488 		.name = "pm4125-sdw-tx",
1489 		.capture = {
1490 			.stream_name = "PM4125 AIF Capture",
1491 			.rates = PM4125_RATES,
1492 			.formats = PM4125_FORMATS,
1493 			.rate_min = 8000,
1494 			.rate_max = 192000,
1495 			.channels_min = 1,
1496 			.channels_max = 4,
1497 		},
1498 		.ops = &pm4125_sdw_dai_ops,
1499 	},
1500 };
1501 
1502 static int pm4125_bind(struct device *dev)
1503 {
1504 	struct pm4125_priv *pm4125 = dev_get_drvdata(dev);
1505 	struct device_link *devlink;
1506 	int ret;
1507 
1508 	/* Initialize device pointers to NULL for safe cleanup */
1509 	pm4125->rxdev = NULL;
1510 	pm4125->txdev = NULL;
1511 
1512 	/* Give the soundwire subdevices some more time to settle */
1513 	usleep_range(15000, 15010);
1514 
1515 	ret = component_bind_all(dev, pm4125);
1516 	if (ret) {
1517 		dev_err(dev, "Slave bind failed, ret = %d\n", ret);
1518 		return ret;
1519 	}
1520 
1521 	pm4125->rxdev = of_sdw_find_device_by_node(pm4125->rxnode);
1522 	if (!pm4125->rxdev) {
1523 		dev_err(dev, "could not find rxslave with matching of node\n");
1524 		ret = -EINVAL;
1525 		goto error_unbind_all;
1526 	}
1527 
1528 	pm4125->sdw_priv[AIF1_PB] = dev_get_drvdata(pm4125->rxdev);
1529 	pm4125->sdw_priv[AIF1_PB]->pm4125 = pm4125;
1530 
1531 	pm4125->txdev = of_sdw_find_device_by_node(pm4125->txnode);
1532 	if (!pm4125->txdev) {
1533 		dev_err(dev, "could not find txslave with matching of node\n");
1534 		ret = -EINVAL;
1535 		goto error_put_rx;
1536 	}
1537 
1538 	pm4125->sdw_priv[AIF1_CAP] = dev_get_drvdata(pm4125->txdev);
1539 	pm4125->sdw_priv[AIF1_CAP]->pm4125 = pm4125;
1540 
1541 	pm4125->tx_sdw_dev = dev_to_sdw_dev(pm4125->txdev);
1542 	if (!pm4125->tx_sdw_dev) {
1543 		dev_err(dev, "could not get txslave with matching of dev\n");
1544 		ret = -EINVAL;
1545 		goto error_put_tx;
1546 	}
1547 
1548 	/*
1549 	 * As TX is the main CSR reg interface, which should not be suspended first.
1550 	 * expicilty add the dependency link
1551 	 */
1552 	devlink = device_link_add(pm4125->rxdev, pm4125->txdev,
1553 				  DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
1554 	if (!devlink) {
1555 		dev_err(dev, "Could not devlink TX and RX\n");
1556 		ret = -EINVAL;
1557 		goto error_put_tx;
1558 	}
1559 
1560 	devlink = device_link_add(dev, pm4125->txdev,
1561 				  DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
1562 	if (!devlink) {
1563 		dev_err(dev, "Could not devlink PM4125 and TX\n");
1564 		ret = -EINVAL;
1565 		goto link_remove_rx_tx;
1566 	}
1567 
1568 	devlink = device_link_add(dev, pm4125->rxdev,
1569 				  DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
1570 	if (!devlink) {
1571 		dev_err(dev, "Could not devlink PM4125 and RX\n");
1572 		ret = -EINVAL;
1573 		goto link_remove_dev_tx;
1574 	}
1575 
1576 	pm4125->regmap = pm4125->sdw_priv[AIF1_CAP]->regmap;
1577 	if (!pm4125->regmap) {
1578 		dev_err(dev, "could not get TX device regmap\n");
1579 		ret = -EINVAL;
1580 		goto link_remove_dev_rx;
1581 	}
1582 
1583 	ret = pm4125_irq_init(pm4125, dev);
1584 	if (ret) {
1585 		dev_err(dev, "IRQ init failed: %d\n", ret);
1586 		goto link_remove_dev_rx;
1587 	}
1588 
1589 	pm4125->sdw_priv[AIF1_PB]->slave_irq = pm4125->virq;
1590 	pm4125->sdw_priv[AIF1_CAP]->slave_irq = pm4125->virq;
1591 
1592 	pm4125_set_micbias_data(dev, pm4125);
1593 
1594 	ret = snd_soc_register_component(dev, &soc_codec_dev_pm4125,
1595 					 pm4125_dais, ARRAY_SIZE(pm4125_dais));
1596 	if (!ret)
1597 		return ret;
1598 
1599 	dev_err(dev, "Codec registration failed\n");
1600 
1601 link_remove_dev_rx:
1602 	device_link_remove(dev, pm4125->rxdev);
1603 link_remove_dev_tx:
1604 	device_link_remove(dev, pm4125->txdev);
1605 link_remove_rx_tx:
1606 	device_link_remove(pm4125->rxdev, pm4125->txdev);
1607 error_put_tx:
1608 	put_device(pm4125->txdev);
1609 error_put_rx:
1610 	put_device(pm4125->rxdev);
1611 error_unbind_all:
1612 	component_unbind_all(dev, pm4125);
1613 	return ret;
1614 }
1615 
1616 static void pm4125_unbind(struct device *dev)
1617 {
1618 	struct pm4125_priv *pm4125 = dev_get_drvdata(dev);
1619 
1620 	snd_soc_unregister_component(dev);
1621 	devm_regmap_del_irq_chip(dev, irq_find_mapping(pm4125->virq, 0),
1622 				 pm4125->irq_chip);
1623 	device_link_remove(dev, pm4125->txdev);
1624 	device_link_remove(dev, pm4125->rxdev);
1625 	device_link_remove(pm4125->rxdev, pm4125->txdev);
1626 
1627 	/* Release device references acquired in bind */
1628 	if (pm4125->txdev)
1629 		put_device(pm4125->txdev);
1630 	if (pm4125->rxdev)
1631 		put_device(pm4125->rxdev);
1632 
1633 	component_unbind_all(dev, pm4125);
1634 }
1635 
1636 static const struct component_master_ops pm4125_comp_ops = {
1637 	.bind = pm4125_bind,
1638 	.unbind = pm4125_unbind,
1639 };
1640 
1641 static int pm4125_add_slave_components(struct pm4125_priv *pm4125, struct device *dev,
1642 				       struct component_match **matchptr)
1643 {
1644 	struct device_node *np = dev->of_node;
1645 
1646 	pm4125->rxnode = of_parse_phandle(np, "qcom,rx-device", 0);
1647 	if (!pm4125->rxnode)
1648 		return dev_err_probe(dev, -ENODEV, "Couldn't parse phandle to qcom,rx-device\n");
1649 	component_match_add_release(dev, matchptr, component_release_of, component_compare_of,
1650 				    pm4125->rxnode);
1651 
1652 	pm4125->txnode = of_parse_phandle(np, "qcom,tx-device", 0);
1653 	if (!pm4125->txnode)
1654 		return dev_err_probe(dev, -ENODEV, "Couldn't parse phandle to qcom,tx-device\n");
1655 	component_match_add_release(dev, matchptr, component_release_of, component_compare_of,
1656 				    pm4125->txnode);
1657 
1658 	return 0;
1659 }
1660 
1661 static int pm4125_probe(struct platform_device *pdev)
1662 {
1663 	struct component_match *match = NULL;
1664 	struct device *dev = &pdev->dev;
1665 	struct regmap_irq_chip *chip_desc;
1666 	struct pm4125_priv *pm4125;
1667 	struct wcd_mbhc_config *cfg;
1668 	int ret;
1669 
1670 	pm4125 = devm_kzalloc(dev, sizeof(*pm4125), GFP_KERNEL);
1671 	if (!pm4125)
1672 		return -ENOMEM;
1673 
1674 	dev_set_drvdata(dev, pm4125);
1675 
1676 	chip_desc = devm_kmemdup(dev, &pm4125_regmap_irq_chip,
1677 				 sizeof(pm4125_regmap_irq_chip),
1678 				 GFP_KERNEL);
1679 	if (!chip_desc)
1680 		return -ENOMEM;
1681 	chip_desc->irq_drv_data = pm4125;
1682 	pm4125->chip_desc = chip_desc;
1683 
1684 	ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(pm4125_power_supplies),
1685 					     pm4125_power_supplies);
1686 	if (ret)
1687 		return dev_err_probe(dev, ret, "Failed to get and enable supplies\n");
1688 
1689 	pm4125->spmi_regmap = dev_get_regmap(pdev->dev.parent, NULL);
1690 	if (!pm4125->spmi_regmap)
1691 		return -ENXIO;
1692 
1693 	pm4125_reset(pm4125);
1694 
1695 	pm4125->common.dev = dev;
1696 	pm4125->common.max_bias = 3;
1697 	ret = wcd_dt_parse_micbias_info(&pm4125->common);
1698 	if (ret)
1699 		return dev_err_probe(dev, ret, "Failed to get micbias\n");
1700 
1701 	atomic_set(&pm4125->gloal_mbias_cnt, 0);
1702 
1703 	cfg = &pm4125->mbhc_cfg;
1704 	cfg->mbhc_micbias = MIC_BIAS_2;
1705 	cfg->anc_micbias = MIC_BIAS_2;
1706 	cfg->v_hs_max = WCD_MBHC_HS_V_MAX;
1707 	cfg->num_btn = PM4125_MBHC_MAX_BUTTONS;
1708 	cfg->micb_mv = pm4125->common.micb_mv[1];
1709 	cfg->linein_th = 5000;
1710 	cfg->hs_thr = 1700;
1711 	cfg->hph_thr = 50;
1712 
1713 	wcd_dt_parse_mbhc_data(dev, &pm4125->mbhc_cfg);
1714 
1715 	ret = pm4125_add_slave_components(pm4125, dev, &match);
1716 	if (ret)
1717 		return ret;
1718 
1719 	ret = component_master_add_with_match(dev, &pm4125_comp_ops, match);
1720 	if (ret)
1721 		return ret;
1722 
1723 	pm_runtime_set_autosuspend_delay(dev, 1000);
1724 	pm_runtime_use_autosuspend(dev);
1725 	pm_runtime_set_active(dev);
1726 	pm_runtime_enable(dev);
1727 	pm_runtime_idle(dev);
1728 
1729 	return 0;
1730 }
1731 
1732 static void pm4125_remove(struct platform_device *pdev)
1733 {
1734 	struct device *dev = &pdev->dev;
1735 
1736 	component_master_del(&pdev->dev, &pm4125_comp_ops);
1737 
1738 	pm_runtime_disable(dev);
1739 	pm_runtime_set_suspended(dev);
1740 	pm_runtime_dont_use_autosuspend(dev);
1741 }
1742 
1743 static const struct of_device_id pm4125_of_match[] = {
1744 	{ .compatible = "qcom,pm4125-codec" },
1745 	{ }
1746 };
1747 MODULE_DEVICE_TABLE(of, pm4125_of_match);
1748 
1749 static struct platform_driver pm4125_codec_driver = {
1750 	.probe = pm4125_probe,
1751 	.remove = pm4125_remove,
1752 	.driver = {
1753 		.name = "pm4125_codec",
1754 		.of_match_table = pm4125_of_match,
1755 		.suppress_bind_attrs = true,
1756 	},
1757 };
1758 
1759 module_platform_driver(pm4125_codec_driver);
1760 MODULE_DESCRIPTION("PM4125 audio codec driver");
1761 MODULE_LICENSE("GPL");
1762