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
pm4125_handle_post_irq(void * data)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
pm4125_reset(struct pm4125_priv * pm4125)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
pm4125_io_init(struct regmap * regmap)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
pm4125_global_mbias_disable(struct snd_soc_component * component)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
pm4125_global_mbias_enable(struct snd_soc_component * component)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
pm4125_rx_clk_enable(struct snd_soc_component * component)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
pm4125_rx_clk_disable(struct snd_soc_component * component)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
pm4125_codec_enable_rxclk(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_codec_hphl_dac_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_codec_hphr_dac_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_codec_ear_lo_dac_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_codec_enable_hphl_wdt_irq(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_codec_enable_hphr_wdt_irq(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_codec_enable_hphr_pa(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_codec_enable_hphl_pa(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_codec_enable_lo_pa(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_codec_enable_ear_pa(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_codec_enable_adc(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_codec_enable_dmic(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_micbias_control(struct snd_soc_component * component,int micb_num,int req,bool is_dapm)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
pm4125_codec_enable_micbias(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_codec_enable_micbias_pullup(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)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
pm4125_connect_port(struct pm4125_sdw_priv * sdw_priv,u8 port_idx,u8 ch_id,bool enable)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
pm4125_get_compander(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)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
pm4125_set_compander(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)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
pm4125_get_swr_port(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)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
pm4125_set_swr_port(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)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
pm4125_mbhc_bias_control(struct snd_soc_component * component,bool enable)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
pm4125_mbhc_program_btn_thr(struct snd_soc_component * component,int * btn_low,int * btn_high,int num_btn,bool is_micbias)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
pm4125_mbhc_init(struct snd_soc_component * component)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
pm4125_mbhc_deinit(struct snd_soc_component * component)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
pm4125_set_micbias_data(struct device * dev,struct pm4125_priv * pm4125)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
pm4125_wd_handle_irq(int irq,void * data)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
pm4125_codec_irq_chip_map(struct irq_domain * irqd,unsigned int virq,irq_hw_number_t hw)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
pm4125_irq_init(struct pm4125_priv * pm4125,struct device * dev)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
pm4125_soc_codec_probe(struct snd_soc_component * component)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
pm4125_soc_codec_remove(struct snd_soc_component * component)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
pm4125_codec_set_jack(struct snd_soc_component * comp,struct snd_soc_jack * jack,void * data)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
pm4125_codec_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)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
pm4125_codec_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)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
pm4125_codec_set_sdw_stream(struct snd_soc_dai * dai,void * stream,int direction)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
pm4125_get_channel_map(const struct snd_soc_dai * dai,unsigned int * tx_num,unsigned int * tx_slot,unsigned int * rx_num,unsigned int * rx_slot)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
pm4125_bind(struct device * dev)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 /* Give the soundwire subdevices some more time to settle */
1509 usleep_range(15000, 15010);
1510
1511 ret = component_bind_all(dev, pm4125);
1512 if (ret) {
1513 dev_err(dev, "Slave bind failed, ret = %d\n", ret);
1514 return ret;
1515 }
1516
1517 pm4125->rxdev = of_sdw_find_device_by_node(pm4125->rxnode);
1518 if (!pm4125->rxdev) {
1519 dev_err(dev, "could not find rxslave with matching of node\n");
1520 ret = -EINVAL;
1521 goto error_unbind_all;
1522 }
1523
1524 pm4125->sdw_priv[AIF1_PB] = dev_get_drvdata(pm4125->rxdev);
1525 pm4125->sdw_priv[AIF1_PB]->pm4125 = pm4125;
1526
1527 pm4125->txdev = of_sdw_find_device_by_node(pm4125->txnode);
1528 if (!pm4125->txdev) {
1529 dev_err(dev, "could not find txslave with matching of node\n");
1530 ret = -EINVAL;
1531 goto error_put_rx;
1532 }
1533
1534 pm4125->sdw_priv[AIF1_CAP] = dev_get_drvdata(pm4125->txdev);
1535 pm4125->sdw_priv[AIF1_CAP]->pm4125 = pm4125;
1536 pm4125->tx_sdw_dev = dev_to_sdw_dev(pm4125->txdev);
1537
1538 /*
1539 * As TX is the main CSR reg interface, which should not be suspended first.
1540 * expicilty add the dependency link
1541 */
1542 devlink = device_link_add(pm4125->rxdev, pm4125->txdev,
1543 DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
1544 if (!devlink) {
1545 dev_err(dev, "Could not devlink TX and RX\n");
1546 ret = -EINVAL;
1547 goto error_put_tx;
1548 }
1549
1550 devlink = device_link_add(dev, pm4125->txdev,
1551 DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
1552 if (!devlink) {
1553 dev_err(dev, "Could not devlink PM4125 and TX\n");
1554 ret = -EINVAL;
1555 goto link_remove_rx_tx;
1556 }
1557
1558 devlink = device_link_add(dev, pm4125->rxdev,
1559 DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
1560 if (!devlink) {
1561 dev_err(dev, "Could not devlink PM4125 and RX\n");
1562 ret = -EINVAL;
1563 goto link_remove_dev_tx;
1564 }
1565
1566 pm4125->regmap = pm4125->sdw_priv[AIF1_CAP]->regmap;
1567 if (!pm4125->regmap) {
1568 dev_err(dev, "could not get TX device regmap\n");
1569 ret = -EINVAL;
1570 goto link_remove_dev_rx;
1571 }
1572
1573 ret = pm4125_irq_init(pm4125, dev);
1574 if (ret) {
1575 dev_err(dev, "IRQ init failed: %d\n", ret);
1576 goto link_remove_dev_rx;
1577 }
1578
1579 pm4125->sdw_priv[AIF1_PB]->slave_irq = pm4125->virq;
1580 pm4125->sdw_priv[AIF1_CAP]->slave_irq = pm4125->virq;
1581
1582 pm4125_set_micbias_data(dev, pm4125);
1583
1584 ret = snd_soc_register_component(dev, &soc_codec_dev_pm4125,
1585 pm4125_dais, ARRAY_SIZE(pm4125_dais));
1586 if (!ret)
1587 return ret;
1588
1589 dev_err(dev, "Codec registration failed\n");
1590
1591 link_remove_dev_rx:
1592 device_link_remove(dev, pm4125->rxdev);
1593 link_remove_dev_tx:
1594 device_link_remove(dev, pm4125->txdev);
1595 link_remove_rx_tx:
1596 device_link_remove(pm4125->rxdev, pm4125->txdev);
1597 error_put_tx:
1598 put_device(pm4125->txdev);
1599 error_put_rx:
1600 put_device(pm4125->rxdev);
1601 error_unbind_all:
1602 component_unbind_all(dev, pm4125);
1603 return ret;
1604 }
1605
pm4125_unbind(struct device * dev)1606 static void pm4125_unbind(struct device *dev)
1607 {
1608 struct pm4125_priv *pm4125 = dev_get_drvdata(dev);
1609
1610 snd_soc_unregister_component(dev);
1611 devm_regmap_del_irq_chip(dev, irq_find_mapping(pm4125->virq, 0),
1612 pm4125->irq_chip);
1613 device_link_remove(dev, pm4125->txdev);
1614 device_link_remove(dev, pm4125->rxdev);
1615 device_link_remove(pm4125->rxdev, pm4125->txdev);
1616
1617 put_device(pm4125->txdev);
1618 put_device(pm4125->rxdev);
1619
1620 component_unbind_all(dev, pm4125);
1621 }
1622
1623 static const struct component_master_ops pm4125_comp_ops = {
1624 .bind = pm4125_bind,
1625 .unbind = pm4125_unbind,
1626 };
1627
pm4125_add_slave_components(struct pm4125_priv * pm4125,struct device * dev,struct component_match ** matchptr)1628 static int pm4125_add_slave_components(struct pm4125_priv *pm4125, struct device *dev,
1629 struct component_match **matchptr)
1630 {
1631 struct device_node *np = dev->of_node;
1632
1633 pm4125->rxnode = of_parse_phandle(np, "qcom,rx-device", 0);
1634 if (!pm4125->rxnode)
1635 return dev_err_probe(dev, -ENODEV, "Couldn't parse phandle to qcom,rx-device\n");
1636 component_match_add_release(dev, matchptr, component_release_of, component_compare_of,
1637 pm4125->rxnode);
1638
1639 pm4125->txnode = of_parse_phandle(np, "qcom,tx-device", 0);
1640 if (!pm4125->txnode)
1641 return dev_err_probe(dev, -ENODEV, "Couldn't parse phandle to qcom,tx-device\n");
1642 component_match_add_release(dev, matchptr, component_release_of, component_compare_of,
1643 pm4125->txnode);
1644
1645 return 0;
1646 }
1647
pm4125_probe(struct platform_device * pdev)1648 static int pm4125_probe(struct platform_device *pdev)
1649 {
1650 struct component_match *match = NULL;
1651 struct device *dev = &pdev->dev;
1652 struct regmap_irq_chip *chip_desc;
1653 struct pm4125_priv *pm4125;
1654 struct wcd_mbhc_config *cfg;
1655 int ret;
1656
1657 pm4125 = devm_kzalloc(dev, sizeof(*pm4125), GFP_KERNEL);
1658 if (!pm4125)
1659 return -ENOMEM;
1660
1661 dev_set_drvdata(dev, pm4125);
1662
1663 chip_desc = devm_kmemdup(dev, &pm4125_regmap_irq_chip,
1664 sizeof(pm4125_regmap_irq_chip),
1665 GFP_KERNEL);
1666 if (!chip_desc)
1667 return -ENOMEM;
1668 chip_desc->irq_drv_data = pm4125;
1669 pm4125->chip_desc = chip_desc;
1670
1671 ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(pm4125_power_supplies),
1672 pm4125_power_supplies);
1673 if (ret)
1674 return dev_err_probe(dev, ret, "Failed to get and enable supplies\n");
1675
1676 pm4125->spmi_regmap = dev_get_regmap(pdev->dev.parent, NULL);
1677 if (!pm4125->spmi_regmap)
1678 return -ENXIO;
1679
1680 pm4125_reset(pm4125);
1681
1682 pm4125->common.dev = dev;
1683 pm4125->common.max_bias = 3;
1684 ret = wcd_dt_parse_micbias_info(&pm4125->common);
1685 if (ret)
1686 return dev_err_probe(dev, ret, "Failed to get micbias\n");
1687
1688 atomic_set(&pm4125->gloal_mbias_cnt, 0);
1689
1690 cfg = &pm4125->mbhc_cfg;
1691 cfg->mbhc_micbias = MIC_BIAS_2;
1692 cfg->anc_micbias = MIC_BIAS_2;
1693 cfg->v_hs_max = WCD_MBHC_HS_V_MAX;
1694 cfg->num_btn = PM4125_MBHC_MAX_BUTTONS;
1695 cfg->micb_mv = pm4125->common.micb_mv[1];
1696 cfg->linein_th = 5000;
1697 cfg->hs_thr = 1700;
1698 cfg->hph_thr = 50;
1699
1700 wcd_dt_parse_mbhc_data(dev, &pm4125->mbhc_cfg);
1701
1702 ret = pm4125_add_slave_components(pm4125, dev, &match);
1703 if (ret)
1704 return ret;
1705
1706 ret = component_master_add_with_match(dev, &pm4125_comp_ops, match);
1707 if (ret)
1708 return ret;
1709
1710 pm_runtime_set_autosuspend_delay(dev, 1000);
1711 pm_runtime_use_autosuspend(dev);
1712 pm_runtime_set_active(dev);
1713 pm_runtime_enable(dev);
1714 pm_runtime_idle(dev);
1715
1716 return 0;
1717 }
1718
pm4125_remove(struct platform_device * pdev)1719 static void pm4125_remove(struct platform_device *pdev)
1720 {
1721 struct device *dev = &pdev->dev;
1722
1723 component_master_del(&pdev->dev, &pm4125_comp_ops);
1724
1725 pm_runtime_disable(dev);
1726 pm_runtime_set_suspended(dev);
1727 pm_runtime_dont_use_autosuspend(dev);
1728 }
1729
1730 static const struct of_device_id pm4125_of_match[] = {
1731 { .compatible = "qcom,pm4125-codec" },
1732 { }
1733 };
1734 MODULE_DEVICE_TABLE(of, pm4125_of_match);
1735
1736 static struct platform_driver pm4125_codec_driver = {
1737 .probe = pm4125_probe,
1738 .remove = pm4125_remove,
1739 .driver = {
1740 .name = "pm4125_codec",
1741 .of_match_table = pm4125_of_match,
1742 .suppress_bind_attrs = true,
1743 },
1744 };
1745
1746 module_platform_driver(pm4125_codec_driver);
1747 MODULE_DESCRIPTION("PM4125 audio codec driver");
1748 MODULE_LICENSE("GPL");
1749