blob: d5271865b2f53ccd73cc91d605b52460af00ff79 [file] [log] [blame]
Laxminath Kasam243e2752018-04-12 00:40:19 +05301/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/io.h>
16#include <linux/platform_device.h>
17#include <linux/clk.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20#include <sound/tlv.h>
21#include <soc/swr-wcd.h>
22
23#include "bolero-cdc.h"
24#include "bolero-cdc-registers.h"
25#include "wsa-macro.h"
26#include "../msm-cdc-pinctrl.h"
27
28#define WSA_MACRO_MAX_OFFSET 0x1000
29
30#define WSA_MACRO_RX_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
31 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
32 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
33#define WSA_MACRO_RX_MIX_RATES (SNDRV_PCM_RATE_48000 |\
34 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
35#define WSA_MACRO_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
36 SNDRV_PCM_FMTBIT_S24_LE |\
37 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
38
39#define WSA_MACRO_ECHO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
40 SNDRV_PCM_RATE_48000)
41#define WSA_MACRO_ECHO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
42 SNDRV_PCM_FMTBIT_S24_LE |\
43 SNDRV_PCM_FMTBIT_S24_3LE)
44
45#define NUM_INTERPOLATORS 2
46
47#define WSA_MACRO_MUX_INP_SHFT 0x3
48#define WSA_MACRO_MUX_INP_MASK1 0x38
49#define WSA_MACRO_MUX_INP_MASK2 0x38
50#define WSA_MACRO_MUX_CFG_OFFSET 0x8
51#define WSA_MACRO_MUX_CFG1_OFFSET 0x4
52#define WSA_MACRO_RX_COMP_OFFSET 0x40
Aditya Bavanari4f3d5642018-09-18 22:19:10 +053053#define WSA_MACRO_RX_SOFTCLIP_OFFSET 0x40
Laxminath Kasam243e2752018-04-12 00:40:19 +053054#define WSA_MACRO_RX_PATH_OFFSET 0x80
55#define WSA_MACRO_RX_PATH_CFG3_OFFSET 0x10
56#define WSA_MACRO_RX_PATH_DSMDEM_OFFSET 0x4C
57#define WSA_MACRO_FS_RATE_MASK 0x0F
58
59enum {
60 WSA_MACRO_RX0 = 0,
61 WSA_MACRO_RX1,
62 WSA_MACRO_RX_MIX,
63 WSA_MACRO_RX_MIX0 = WSA_MACRO_RX_MIX,
64 WSA_MACRO_RX_MIX1,
65 WSA_MACRO_RX_MAX,
66};
67
68enum {
69 WSA_MACRO_TX0 = 0,
70 WSA_MACRO_TX1,
71 WSA_MACRO_TX_MAX,
72};
73
74enum {
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +053075 WSA_MACRO_EC0_MUX = 0,
76 WSA_MACRO_EC1_MUX,
77 WSA_MACRO_EC_MUX_MAX,
78};
79
80enum {
Laxminath Kasam243e2752018-04-12 00:40:19 +053081 WSA_MACRO_COMP1, /* SPK_L */
82 WSA_MACRO_COMP2, /* SPK_R */
83 WSA_MACRO_COMP_MAX
84};
85
Aditya Bavanari4f3d5642018-09-18 22:19:10 +053086enum {
87 WSA_MACRO_SOFTCLIP0, /* RX0 */
88 WSA_MACRO_SOFTCLIP1, /* RX1 */
89 WSA_MACRO_SOFTCLIP_MAX
90};
91
Laxminath Kasam243e2752018-04-12 00:40:19 +053092struct interp_sample_rate {
93 int sample_rate;
94 int rate_val;
95};
96
97/*
98 * Structure used to update codec
99 * register defaults after reset
100 */
101struct wsa_macro_reg_mask_val {
102 u16 reg;
103 u8 mask;
104 u8 val;
105};
106
107static struct interp_sample_rate int_prim_sample_rate_val[] = {
108 {8000, 0x0}, /* 8K */
109 {16000, 0x1}, /* 16K */
110 {24000, -EINVAL},/* 24K */
111 {32000, 0x3}, /* 32K */
112 {48000, 0x4}, /* 48K */
113 {96000, 0x5}, /* 96K */
114 {192000, 0x6}, /* 192K */
115 {384000, 0x7}, /* 384K */
116 {44100, 0x8}, /* 44.1K */
117};
118
119static struct interp_sample_rate int_mix_sample_rate_val[] = {
120 {48000, 0x4}, /* 48K */
121 {96000, 0x5}, /* 96K */
122 {192000, 0x6}, /* 192K */
123};
124
125#define WSA_MACRO_SWR_STRING_LEN 80
126
127static int wsa_macro_hw_params(struct snd_pcm_substream *substream,
128 struct snd_pcm_hw_params *params,
129 struct snd_soc_dai *dai);
130static int wsa_macro_get_channel_map(struct snd_soc_dai *dai,
131 unsigned int *tx_num, unsigned int *tx_slot,
132 unsigned int *rx_num, unsigned int *rx_slot);
133/* Hold instance to soundwire platform device */
134struct wsa_macro_swr_ctrl_data {
135 struct platform_device *wsa_swr_pdev;
136};
137
138struct wsa_macro_swr_ctrl_platform_data {
139 void *handle; /* holds codec private data */
140 int (*read)(void *handle, int reg);
141 int (*write)(void *handle, int reg, int val);
142 int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
143 int (*clk)(void *handle, bool enable);
144 int (*handle_irq)(void *handle,
145 irqreturn_t (*swrm_irq_handler)(int irq,
146 void *data),
147 void *swrm_handle,
148 int action);
149};
150
Aditya Bavanari4f3d5642018-09-18 22:19:10 +0530151struct wsa_macro_bcl_pmic_params {
152 u8 id;
153 u8 sid;
154 u8 ppid;
155};
156
Laxminath Kasam243e2752018-04-12 00:40:19 +0530157enum {
Laxminath Kasam59c7a1d2018-08-09 16:11:17 +0530158 WSA_MACRO_AIF_INVALID = 0,
159 WSA_MACRO_AIF1_PB,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530160 WSA_MACRO_AIF_MIX1_PB,
161 WSA_MACRO_AIF_VI,
162 WSA_MACRO_AIF_ECHO,
163 WSA_MACRO_MAX_DAIS,
164};
165
166#define WSA_MACRO_CHILD_DEVICES_MAX 3
167
168/*
169 * @dev: wsa macro device pointer
170 * @comp_enabled: compander enable mixer value set
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +0530171 * @ec_hq: echo HQ enable mixer value set
Laxminath Kasam243e2752018-04-12 00:40:19 +0530172 * @prim_int_users: Users of interpolator
173 * @wsa_mclk_users: WSA MCLK users count
174 * @swr_clk_users: SWR clk users count
175 * @vi_feed_value: VI sense mask
176 * @mclk_lock: to lock mclk operations
177 * @swr_clk_lock: to lock swr master clock operations
178 * @swr_ctrl_data: SoundWire data structure
179 * @swr_plat_data: Soundwire platform data
180 * @wsa_macro_add_child_devices_work: work for adding child devices
181 * @wsa_swr_gpio_p: used by pinctrl API
182 * @wsa_core_clk: MCLK for wsa macro
183 * @wsa_npl_clk: NPL clock for WSA soundwire
184 * @codec: codec handle
185 * @rx_0_count: RX0 interpolation users
186 * @rx_1_count: RX1 interpolation users
187 * @active_ch_mask: channel mask for all AIF DAIs
188 * @active_ch_cnt: channel count of all AIF DAIs
189 * @rx_port_value: mixer ctl value of WSA RX MUXes
190 * @wsa_io_base: Base address of WSA macro addr space
191 */
192struct wsa_macro_priv {
193 struct device *dev;
194 int comp_enabled[WSA_MACRO_COMP_MAX];
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +0530195 int ec_hq[WSA_MACRO_RX1 + 1];
Laxminath Kasam243e2752018-04-12 00:40:19 +0530196 u16 prim_int_users[WSA_MACRO_RX1 + 1];
197 u16 wsa_mclk_users;
198 u16 swr_clk_users;
199 unsigned int vi_feed_value;
200 struct mutex mclk_lock;
201 struct mutex swr_clk_lock;
202 struct wsa_macro_swr_ctrl_data *swr_ctrl_data;
203 struct wsa_macro_swr_ctrl_platform_data swr_plat_data;
204 struct work_struct wsa_macro_add_child_devices_work;
205 struct device_node *wsa_swr_gpio_p;
206 struct clk *wsa_core_clk;
207 struct clk *wsa_npl_clk;
208 struct snd_soc_codec *codec;
209 int rx_0_count;
210 int rx_1_count;
211 unsigned long active_ch_mask[WSA_MACRO_MAX_DAIS];
212 unsigned long active_ch_cnt[WSA_MACRO_MAX_DAIS];
213 int rx_port_value[WSA_MACRO_RX_MAX];
214 char __iomem *wsa_io_base;
215 struct platform_device *pdev_child_devices
216 [WSA_MACRO_CHILD_DEVICES_MAX];
217 int child_count;
218 int ear_spkr_gain;
219 int spkr_gain_offset;
220 int spkr_mode;
Aditya Bavanari4f3d5642018-09-18 22:19:10 +0530221 int is_softclip_on[WSA_MACRO_SOFTCLIP_MAX];
222 int softclip_clk_users[WSA_MACRO_SOFTCLIP_MAX];
223 struct wsa_macro_bcl_pmic_params bcl_pmic_params;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530224};
225
226static int wsa_macro_config_ear_spkr_gain(struct snd_soc_codec *codec,
227 struct wsa_macro_priv *wsa_priv,
228 int event, int gain_reg);
229static struct snd_soc_dai_driver wsa_macro_dai[];
230static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
231
232static const char *const rx_text[] = {
233 "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "DEC0", "DEC1"
234};
235
236static const char *const rx_mix_text[] = {
237 "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1"
238};
239
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +0530240static const char *const rx_mix_ec_text[] = {
241 "ZERO", "RX_MIX_TX0", "RX_MIX_TX1"
242};
243
Laxminath Kasam243e2752018-04-12 00:40:19 +0530244static const char *const rx_mux_text[] = {
245 "ZERO", "AIF1_PB", "AIF_MIX1_PB"
246};
247
Laxminath Kasam6fc2e742018-08-26 23:32:57 +0530248static const char *const rx_sidetone_mix_text[] = {
249 "ZERO", "SRC0"
250};
251
Laxminath Kasam243e2752018-04-12 00:40:19 +0530252static const char * const wsa_macro_ear_spkr_pa_gain_text[] = {
253 "G_DEFAULT", "G_0_DB", "G_1_DB", "G_2_DB", "G_3_DB",
254 "G_4_DB", "G_5_DB", "G_6_DB"
255};
256
257static const char * const wsa_macro_speaker_boost_stage_text[] = {
258 "NO_MAX_STATE", "MAX_STATE_1", "MAX_STATE_2"
259};
260
Aditya Bavanari4f3d5642018-09-18 22:19:10 +0530261static const char * const wsa_macro_vbat_bcl_gsm_mode_text[] = {
262 "OFF", "ON"
263};
264
265static const struct snd_kcontrol_new wsa_int0_vbat_mix_switch[] = {
266 SOC_DAPM_SINGLE("WSA RX0 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
267};
268
269static const struct snd_kcontrol_new wsa_int1_vbat_mix_switch[] = {
270 SOC_DAPM_SINGLE("WSA RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
271};
272
Laxminath Kasam243e2752018-04-12 00:40:19 +0530273static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_ear_spkr_pa_gain_enum,
274 wsa_macro_ear_spkr_pa_gain_text);
275static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_spkr_boost_stage_enum,
276 wsa_macro_speaker_boost_stage_text);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +0530277static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_vbat_bcl_gsm_mode_enum,
278 wsa_macro_vbat_bcl_gsm_mode_text);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530279
280/* RX INT0 */
281static const struct soc_enum rx0_prim_inp0_chain_enum =
282 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0,
283 0, 7, rx_text);
284
285static const struct soc_enum rx0_prim_inp1_chain_enum =
286 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0,
287 3, 7, rx_text);
288
289static const struct soc_enum rx0_prim_inp2_chain_enum =
290 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1,
291 3, 7, rx_text);
292
293static const struct soc_enum rx0_mix_chain_enum =
294 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1,
295 0, 5, rx_mix_text);
296
Laxminath Kasam6fc2e742018-08-26 23:32:57 +0530297static const struct soc_enum rx0_sidetone_mix_enum =
298 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_sidetone_mix_text);
299
Laxminath Kasam243e2752018-04-12 00:40:19 +0530300static const struct snd_kcontrol_new rx0_prim_inp0_mux =
301 SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum);
302
303static const struct snd_kcontrol_new rx0_prim_inp1_mux =
304 SOC_DAPM_ENUM("WSA_RX0 INP1 Mux", rx0_prim_inp1_chain_enum);
305
306static const struct snd_kcontrol_new rx0_prim_inp2_mux =
307 SOC_DAPM_ENUM("WSA_RX0 INP2 Mux", rx0_prim_inp2_chain_enum);
308
309static const struct snd_kcontrol_new rx0_mix_mux =
310 SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum);
311
Laxminath Kasam6fc2e742018-08-26 23:32:57 +0530312static const struct snd_kcontrol_new rx0_sidetone_mix_mux =
313 SOC_DAPM_ENUM("WSA_RX0 SIDETONE MIX Mux", rx0_sidetone_mix_enum);
314
Laxminath Kasam243e2752018-04-12 00:40:19 +0530315/* RX INT1 */
316static const struct soc_enum rx1_prim_inp0_chain_enum =
317 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0,
318 0, 7, rx_text);
319
320static const struct soc_enum rx1_prim_inp1_chain_enum =
321 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0,
322 3, 7, rx_text);
323
324static const struct soc_enum rx1_prim_inp2_chain_enum =
325 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1,
326 3, 7, rx_text);
327
328static const struct soc_enum rx1_mix_chain_enum =
329 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1,
330 0, 5, rx_mix_text);
331
332static const struct snd_kcontrol_new rx1_prim_inp0_mux =
333 SOC_DAPM_ENUM("WSA_RX1 INP0 Mux", rx1_prim_inp0_chain_enum);
334
335static const struct snd_kcontrol_new rx1_prim_inp1_mux =
336 SOC_DAPM_ENUM("WSA_RX1 INP1 Mux", rx1_prim_inp1_chain_enum);
337
338static const struct snd_kcontrol_new rx1_prim_inp2_mux =
339 SOC_DAPM_ENUM("WSA_RX1 INP2 Mux", rx1_prim_inp2_chain_enum);
340
341static const struct snd_kcontrol_new rx1_mix_mux =
342 SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum);
343
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +0530344static const struct soc_enum rx_mix_ec0_enum =
345 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
346 0, 3, rx_mix_ec_text);
347
348static const struct soc_enum rx_mix_ec1_enum =
349 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
350 3, 3, rx_mix_ec_text);
351
352static const struct snd_kcontrol_new rx_mix_ec0_mux =
353 SOC_DAPM_ENUM("WSA RX_MIX EC0_Mux", rx_mix_ec0_enum);
354
355static const struct snd_kcontrol_new rx_mix_ec1_mux =
356 SOC_DAPM_ENUM("WSA RX_MIX EC1_Mux", rx_mix_ec1_enum);
357
Laxminath Kasam243e2752018-04-12 00:40:19 +0530358static struct snd_soc_dai_ops wsa_macro_dai_ops = {
359 .hw_params = wsa_macro_hw_params,
360 .get_channel_map = wsa_macro_get_channel_map,
361};
362
363static struct snd_soc_dai_driver wsa_macro_dai[] = {
364 {
365 .name = "wsa_macro_rx1",
366 .id = WSA_MACRO_AIF1_PB,
367 .playback = {
368 .stream_name = "WSA_AIF1 Playback",
369 .rates = WSA_MACRO_RX_RATES,
370 .formats = WSA_MACRO_RX_FORMATS,
371 .rate_max = 384000,
372 .rate_min = 8000,
373 .channels_min = 1,
374 .channels_max = 2,
375 },
376 .ops = &wsa_macro_dai_ops,
377 },
378 {
379 .name = "wsa_macro_rx_mix",
380 .id = WSA_MACRO_AIF_MIX1_PB,
381 .playback = {
382 .stream_name = "WSA_AIF_MIX1 Playback",
383 .rates = WSA_MACRO_RX_MIX_RATES,
384 .formats = WSA_MACRO_RX_FORMATS,
385 .rate_max = 192000,
386 .rate_min = 48000,
387 .channels_min = 1,
388 .channels_max = 2,
389 },
390 .ops = &wsa_macro_dai_ops,
391 },
392 {
393 .name = "wsa_macro_vifeedback",
394 .id = WSA_MACRO_AIF_VI,
395 .capture = {
396 .stream_name = "WSA_AIF_VI Capture",
Vatsal Buchad1b694d2018-08-31 11:47:32 +0530397 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
398 .formats = WSA_MACRO_RX_FORMATS,
399 .rate_max = 48000,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530400 .rate_min = 8000,
401 .channels_min = 1,
Vatsal Buchad1b694d2018-08-31 11:47:32 +0530402 .channels_max = 4,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530403 },
404 .ops = &wsa_macro_dai_ops,
405 },
406 {
407 .name = "wsa_macro_echo",
408 .id = WSA_MACRO_AIF_ECHO,
409 .capture = {
410 .stream_name = "WSA_AIF_ECHO Capture",
411 .rates = WSA_MACRO_ECHO_RATES,
412 .formats = WSA_MACRO_ECHO_FORMATS,
413 .rate_max = 48000,
414 .rate_min = 8000,
415 .channels_min = 1,
416 .channels_max = 2,
417 },
418 .ops = &wsa_macro_dai_ops,
419 },
420};
421
422static const struct wsa_macro_reg_mask_val wsa_macro_spkr_default[] = {
423 {BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80},
424 {BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x80},
425 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01},
426 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01},
427 {BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x58},
428 {BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x58},
429};
430
431static const struct wsa_macro_reg_mask_val wsa_macro_spkr_mode1[] = {
432 {BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x00},
433 {BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x00},
434 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x00},
435 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x00},
436 {BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x44},
437 {BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x44},
438};
439
440static bool wsa_macro_get_data(struct snd_soc_codec *codec,
441 struct device **wsa_dev,
442 struct wsa_macro_priv **wsa_priv,
443 const char *func_name)
444{
445 *wsa_dev = bolero_get_device_ptr(codec->dev, WSA_MACRO);
446 if (!(*wsa_dev)) {
447 dev_err(codec->dev,
448 "%s: null device for macro!\n", func_name);
449 return false;
450 }
451 *wsa_priv = dev_get_drvdata((*wsa_dev));
452 if (!(*wsa_priv) || !(*wsa_priv)->codec) {
453 dev_err(codec->dev,
454 "%s: priv is null for macro!\n", func_name);
455 return false;
456 }
457 return true;
458}
459
460/**
461 * wsa_macro_set_spkr_gain_offset - offset the speaker path
462 * gain with the given offset value.
463 *
464 * @codec: codec instance
465 * @offset: Indicates speaker path gain offset value.
466 *
467 * Returns 0 on success or -EINVAL on error.
468 */
469int wsa_macro_set_spkr_gain_offset(struct snd_soc_codec *codec, int offset)
470{
471 struct device *wsa_dev = NULL;
472 struct wsa_macro_priv *wsa_priv = NULL;
473
474 if (!codec) {
475 pr_err("%s: NULL codec pointer!\n", __func__);
476 return -EINVAL;
477 }
478
479 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
480 return -EINVAL;
481
482 wsa_priv->spkr_gain_offset = offset;
483 return 0;
484}
485EXPORT_SYMBOL(wsa_macro_set_spkr_gain_offset);
486
487/**
488 * wsa_macro_set_spkr_mode - Configures speaker compander and smartboost
489 * settings based on speaker mode.
490 *
491 * @codec: codec instance
492 * @mode: Indicates speaker configuration mode.
493 *
494 * Returns 0 on success or -EINVAL on error.
495 */
496int wsa_macro_set_spkr_mode(struct snd_soc_codec *codec, int mode)
497{
498 int i;
499 const struct wsa_macro_reg_mask_val *regs;
500 int size;
501 struct device *wsa_dev = NULL;
502 struct wsa_macro_priv *wsa_priv = NULL;
503
504 if (!codec) {
505 pr_err("%s: NULL codec pointer!\n", __func__);
506 return -EINVAL;
507 }
508
509 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
510 return -EINVAL;
511
512 switch (mode) {
Laxminath Kasam21c8b222018-06-21 18:47:22 +0530513 case WSA_MACRO_SPKR_MODE_1:
Laxminath Kasam243e2752018-04-12 00:40:19 +0530514 regs = wsa_macro_spkr_mode1;
515 size = ARRAY_SIZE(wsa_macro_spkr_mode1);
516 break;
517 default:
518 regs = wsa_macro_spkr_default;
519 size = ARRAY_SIZE(wsa_macro_spkr_default);
520 break;
521 }
522
523 wsa_priv->spkr_mode = mode;
524 for (i = 0; i < size; i++)
525 snd_soc_update_bits(codec, regs[i].reg,
526 regs[i].mask, regs[i].val);
527 return 0;
528}
529EXPORT_SYMBOL(wsa_macro_set_spkr_mode);
530
531static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
532 u8 int_prim_fs_rate_reg_val,
533 u32 sample_rate)
534{
535 u8 int_1_mix1_inp;
536 u32 j, port;
537 u16 int_mux_cfg0, int_mux_cfg1;
538 u16 int_fs_reg;
539 u8 int_mux_cfg0_val, int_mux_cfg1_val;
540 u8 inp0_sel, inp1_sel, inp2_sel;
541 struct snd_soc_codec *codec = dai->codec;
542 struct device *wsa_dev = NULL;
543 struct wsa_macro_priv *wsa_priv = NULL;
544
545 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
546 return -EINVAL;
547
548 for_each_set_bit(port, &wsa_priv->active_ch_mask[dai->id],
549 WSA_MACRO_RX_MAX) {
550 int_1_mix1_inp = port;
551 if ((int_1_mix1_inp < WSA_MACRO_RX0) ||
552 (int_1_mix1_inp > WSA_MACRO_RX_MIX1)) {
553 dev_err(wsa_dev,
554 "%s: Invalid RX port, Dai ID is %d\n",
555 __func__, dai->id);
556 return -EINVAL;
557 }
558
559 int_mux_cfg0 = BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0;
560
561 /*
562 * Loop through all interpolator MUX inputs and find out
563 * to which interpolator input, the cdc_dma rx port
564 * is connected
565 */
566 for (j = 0; j < NUM_INTERPOLATORS; j++) {
567 int_mux_cfg1 = int_mux_cfg0 + WSA_MACRO_MUX_CFG1_OFFSET;
568
569 int_mux_cfg0_val = snd_soc_read(codec, int_mux_cfg0);
570 int_mux_cfg1_val = snd_soc_read(codec, int_mux_cfg1);
571 inp0_sel = int_mux_cfg0_val & WSA_MACRO_MUX_INP_MASK1;
572 inp1_sel = (int_mux_cfg0_val >>
573 WSA_MACRO_MUX_INP_SHFT) &
574 WSA_MACRO_MUX_INP_MASK2;
575 inp2_sel = (int_mux_cfg1_val >>
576 WSA_MACRO_MUX_INP_SHFT) &
577 WSA_MACRO_MUX_INP_MASK2;
578 if ((inp0_sel == int_1_mix1_inp) ||
579 (inp1_sel == int_1_mix1_inp) ||
580 (inp2_sel == int_1_mix1_inp)) {
581 int_fs_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL +
582 WSA_MACRO_RX_PATH_OFFSET * j;
583 dev_dbg(wsa_dev,
584 "%s: AIF_PB DAI(%d) connected to INT%u_1\n",
585 __func__, dai->id, j);
586 dev_dbg(wsa_dev,
587 "%s: set INT%u_1 sample rate to %u\n",
588 __func__, j, sample_rate);
589 /* sample_rate is in Hz */
590 snd_soc_update_bits(codec, int_fs_reg,
591 WSA_MACRO_FS_RATE_MASK,
592 int_prim_fs_rate_reg_val);
593 }
594 int_mux_cfg0 += WSA_MACRO_MUX_CFG_OFFSET;
595 }
596 }
597
598 return 0;
599}
600
601static int wsa_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai,
602 u8 int_mix_fs_rate_reg_val,
603 u32 sample_rate)
604{
605 u8 int_2_inp;
606 u32 j, port;
607 u16 int_mux_cfg1, int_fs_reg;
608 u8 int_mux_cfg1_val;
609 struct snd_soc_codec *codec = dai->codec;
610 struct device *wsa_dev = NULL;
611 struct wsa_macro_priv *wsa_priv = NULL;
612
613 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
614 return -EINVAL;
615
616
617 for_each_set_bit(port, &wsa_priv->active_ch_mask[dai->id],
618 WSA_MACRO_RX_MAX) {
619 int_2_inp = port;
620 if ((int_2_inp < WSA_MACRO_RX0) ||
621 (int_2_inp > WSA_MACRO_RX_MIX1)) {
622 dev_err(wsa_dev,
623 "%s: Invalid RX port, Dai ID is %d\n",
624 __func__, dai->id);
625 return -EINVAL;
626 }
627
628 int_mux_cfg1 = BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1;
629 for (j = 0; j < NUM_INTERPOLATORS; j++) {
630 int_mux_cfg1_val = snd_soc_read(codec, int_mux_cfg1) &
631 WSA_MACRO_MUX_INP_MASK1;
632 if (int_mux_cfg1_val == int_2_inp) {
633 int_fs_reg =
634 BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL +
635 WSA_MACRO_RX_PATH_OFFSET * j;
636
637 dev_dbg(wsa_dev,
638 "%s: AIF_PB DAI(%d) connected to INT%u_2\n",
639 __func__, dai->id, j);
640 dev_dbg(wsa_dev,
641 "%s: set INT%u_2 sample rate to %u\n",
642 __func__, j, sample_rate);
643 snd_soc_update_bits(codec, int_fs_reg,
644 WSA_MACRO_FS_RATE_MASK,
645 int_mix_fs_rate_reg_val);
646 }
647 int_mux_cfg1 += WSA_MACRO_MUX_CFG_OFFSET;
648 }
649 }
650 return 0;
651}
652
653static int wsa_macro_set_interpolator_rate(struct snd_soc_dai *dai,
654 u32 sample_rate)
655{
656 int rate_val = 0;
657 int i, ret;
658
659 /* set mixing path rate */
660 for (i = 0; i < ARRAY_SIZE(int_mix_sample_rate_val); i++) {
661 if (sample_rate ==
662 int_mix_sample_rate_val[i].sample_rate) {
663 rate_val =
664 int_mix_sample_rate_val[i].rate_val;
665 break;
666 }
667 }
668 if ((i == ARRAY_SIZE(int_mix_sample_rate_val)) ||
669 (rate_val < 0))
670 goto prim_rate;
671 ret = wsa_macro_set_mix_interpolator_rate(dai,
672 (u8) rate_val, sample_rate);
673prim_rate:
674 /* set primary path sample rate */
675 for (i = 0; i < ARRAY_SIZE(int_prim_sample_rate_val); i++) {
676 if (sample_rate ==
677 int_prim_sample_rate_val[i].sample_rate) {
678 rate_val =
679 int_prim_sample_rate_val[i].rate_val;
680 break;
681 }
682 }
683 if ((i == ARRAY_SIZE(int_prim_sample_rate_val)) ||
684 (rate_val < 0))
685 return -EINVAL;
686 ret = wsa_macro_set_prim_interpolator_rate(dai,
687 (u8) rate_val, sample_rate);
688 return ret;
689}
690
691static int wsa_macro_hw_params(struct snd_pcm_substream *substream,
692 struct snd_pcm_hw_params *params,
693 struct snd_soc_dai *dai)
694{
695 struct snd_soc_codec *codec = dai->codec;
696 int ret;
697
698 dev_dbg(codec->dev,
699 "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
700 dai->name, dai->id, params_rate(params),
701 params_channels(params));
702
703 switch (substream->stream) {
704 case SNDRV_PCM_STREAM_PLAYBACK:
705 ret = wsa_macro_set_interpolator_rate(dai, params_rate(params));
706 if (ret) {
707 dev_err(codec->dev,
708 "%s: cannot set sample rate: %u\n",
709 __func__, params_rate(params));
710 return ret;
711 }
712 break;
713 case SNDRV_PCM_STREAM_CAPTURE:
714 default:
715 break;
716 }
717 return 0;
718}
719
720static int wsa_macro_get_channel_map(struct snd_soc_dai *dai,
721 unsigned int *tx_num, unsigned int *tx_slot,
722 unsigned int *rx_num, unsigned int *rx_slot)
723{
724 struct snd_soc_codec *codec = dai->codec;
725 struct device *wsa_dev = NULL;
726 struct wsa_macro_priv *wsa_priv = NULL;
727
728 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
729 return -EINVAL;
730
731 wsa_priv = dev_get_drvdata(wsa_dev);
732 if (!wsa_priv)
733 return -EINVAL;
734
735 switch (dai->id) {
736 case WSA_MACRO_AIF_VI:
737 case WSA_MACRO_AIF_ECHO:
738 *tx_slot = wsa_priv->active_ch_mask[dai->id];
739 *tx_num = wsa_priv->active_ch_cnt[dai->id];
740 break;
741 case WSA_MACRO_AIF1_PB:
742 case WSA_MACRO_AIF_MIX1_PB:
743 *rx_slot = wsa_priv->active_ch_mask[dai->id];
744 *rx_num = wsa_priv->active_ch_cnt[dai->id];
745 break;
746 default:
747 dev_err(wsa_dev, "%s: Invalid AIF\n", __func__);
748 break;
749 }
750 return 0;
751}
752
753static int wsa_macro_mclk_enable(struct wsa_macro_priv *wsa_priv,
754 bool mclk_enable, bool dapm)
755{
756 struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
757 int ret = 0;
758
759 dev_dbg(wsa_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
760 __func__, mclk_enable, dapm, wsa_priv->wsa_mclk_users);
761
762 mutex_lock(&wsa_priv->mclk_lock);
763 if (mclk_enable) {
764 wsa_priv->wsa_mclk_users++;
765 if (wsa_priv->wsa_mclk_users == 1) {
766 ret = bolero_request_clock(wsa_priv->dev,
767 WSA_MACRO, MCLK_MUX0, true);
768 if (ret < 0) {
769 dev_err(wsa_priv->dev,
770 "%s: wsa request clock enable failed\n",
771 __func__);
772 goto exit;
773 }
774 regcache_mark_dirty(regmap);
775 regcache_sync_region(regmap,
776 WSA_START_OFFSET,
777 WSA_MAX_OFFSET);
778 /* 9.6MHz MCLK, set value 0x00 if other frequency */
779 regmap_update_bits(regmap,
780 BOLERO_CDC_WSA_TOP_FREQ_MCLK, 0x01, 0x01);
781 regmap_update_bits(regmap,
782 BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL,
783 0x01, 0x01);
784 regmap_update_bits(regmap,
785 BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
786 0x01, 0x01);
787 }
788 } else {
789 wsa_priv->wsa_mclk_users--;
790 if (wsa_priv->wsa_mclk_users == 0) {
791 regmap_update_bits(regmap,
792 BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
793 0x01, 0x00);
794 regmap_update_bits(regmap,
795 BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL,
796 0x01, 0x00);
797 bolero_request_clock(wsa_priv->dev,
798 WSA_MACRO, MCLK_MUX0, false);
799 }
800 }
801exit:
802 mutex_unlock(&wsa_priv->mclk_lock);
803 return ret;
804}
805
806static int wsa_macro_mclk_event(struct snd_soc_dapm_widget *w,
807 struct snd_kcontrol *kcontrol, int event)
808{
809 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
810 int ret = 0;
811 struct device *wsa_dev = NULL;
812 struct wsa_macro_priv *wsa_priv = NULL;
813
814 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
815 return -EINVAL;
816
817 dev_dbg(wsa_dev, "%s: event = %d\n", __func__, event);
818 switch (event) {
819 case SND_SOC_DAPM_PRE_PMU:
820 ret = wsa_macro_mclk_enable(wsa_priv, 1, true);
821 break;
822 case SND_SOC_DAPM_POST_PMD:
823 wsa_macro_mclk_enable(wsa_priv, 0, true);
824 break;
825 default:
826 dev_err(wsa_priv->dev,
827 "%s: invalid DAPM event %d\n", __func__, event);
828 ret = -EINVAL;
829 }
830 return ret;
831}
832
833static int wsa_macro_mclk_ctrl(struct device *dev, bool enable)
834{
835 struct wsa_macro_priv *wsa_priv = dev_get_drvdata(dev);
836 int ret = 0;
837
838 if (!wsa_priv)
839 return -EINVAL;
840
841 if (enable) {
842 ret = clk_prepare_enable(wsa_priv->wsa_core_clk);
843 if (ret < 0) {
844 dev_err(dev, "%s:wsa mclk enable failed\n", __func__);
845 goto exit;
846 }
847 ret = clk_prepare_enable(wsa_priv->wsa_npl_clk);
848 if (ret < 0) {
849 dev_err(dev, "%s:wsa npl_clk enable failed\n",
850 __func__);
851 clk_disable_unprepare(wsa_priv->wsa_core_clk);
852 goto exit;
853 }
854 } else {
855 clk_disable_unprepare(wsa_priv->wsa_npl_clk);
856 clk_disable_unprepare(wsa_priv->wsa_core_clk);
857 }
858exit:
859 return ret;
860}
861
Laxminath Kasamfb0d6832018-09-22 01:49:52 +0530862static int wsa_macro_event_handler(struct snd_soc_codec *codec, u16 event,
863 u32 data)
864{
865 struct device *wsa_dev = NULL;
866 struct wsa_macro_priv *wsa_priv = NULL;
867
868 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
869 return -EINVAL;
870
871 switch (event) {
872 case BOLERO_MACRO_EVT_SSR_DOWN:
873 swrm_wcd_notify(
874 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
875 SWR_DEVICE_SSR_DOWN, NULL);
876 swrm_wcd_notify(
877 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
878 SWR_DEVICE_DOWN, NULL);
879 break;
880 case BOLERO_MACRO_EVT_SSR_UP:
881 swrm_wcd_notify(
882 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
883 SWR_DEVICE_SSR_UP, NULL);
884 break;
885 }
886 return 0;
887}
888
Laxminath Kasam243e2752018-04-12 00:40:19 +0530889static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w,
890 struct snd_kcontrol *kcontrol,
891 int event)
892{
893 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
894 struct device *wsa_dev = NULL;
895 struct wsa_macro_priv *wsa_priv = NULL;
896
897 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
898 return -EINVAL;
899
900 switch (event) {
901 case SND_SOC_DAPM_POST_PMU:
902 if (test_bit(WSA_MACRO_TX0,
903 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
904 dev_dbg(wsa_dev, "%s: spkr1 enabled\n", __func__);
905 /* Enable V&I sensing */
906 snd_soc_update_bits(codec,
907 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
908 0x20, 0x20);
909 snd_soc_update_bits(codec,
910 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
911 0x20, 0x20);
912 snd_soc_update_bits(codec,
913 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
914 0x0F, 0x00);
915 snd_soc_update_bits(codec,
916 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
917 0x0F, 0x00);
918 snd_soc_update_bits(codec,
919 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
920 0x10, 0x10);
921 snd_soc_update_bits(codec,
922 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
923 0x10, 0x10);
924 snd_soc_update_bits(codec,
925 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
926 0x20, 0x00);
927 snd_soc_update_bits(codec,
928 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
929 0x20, 0x00);
930 }
931 if (test_bit(WSA_MACRO_TX1,
932 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
933 dev_dbg(wsa_dev, "%s: spkr2 enabled\n", __func__);
934 /* Enable V&I sensing */
935 snd_soc_update_bits(codec,
936 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
937 0x20, 0x20);
938 snd_soc_update_bits(codec,
939 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
940 0x20, 0x20);
941 snd_soc_update_bits(codec,
942 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
943 0x0F, 0x00);
944 snd_soc_update_bits(codec,
945 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
946 0x0F, 0x00);
947 snd_soc_update_bits(codec,
948 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
949 0x10, 0x10);
950 snd_soc_update_bits(codec,
951 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
952 0x10, 0x10);
953 snd_soc_update_bits(codec,
954 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
955 0x20, 0x00);
956 snd_soc_update_bits(codec,
957 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
958 0x20, 0x00);
959 }
960 break;
961 case SND_SOC_DAPM_POST_PMD:
962 if (test_bit(WSA_MACRO_TX0,
963 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
964 /* Disable V&I sensing */
965 snd_soc_update_bits(codec,
966 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
967 0x20, 0x20);
968 snd_soc_update_bits(codec,
969 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
970 0x20, 0x20);
971 dev_dbg(wsa_dev, "%s: spkr1 disabled\n", __func__);
972 snd_soc_update_bits(codec,
973 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
974 0x10, 0x00);
975 snd_soc_update_bits(codec,
976 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
977 0x10, 0x00);
978 }
979 if (test_bit(WSA_MACRO_TX1,
980 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
981 /* Disable V&I sensing */
982 dev_dbg(wsa_dev, "%s: spkr2 disabled\n", __func__);
983 snd_soc_update_bits(codec,
984 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
985 0x20, 0x20);
986 snd_soc_update_bits(codec,
987 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
988 0x20, 0x20);
989 snd_soc_update_bits(codec,
990 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
991 0x10, 0x00);
992 snd_soc_update_bits(codec,
993 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
994 0x10, 0x00);
995 }
996 break;
997 }
998
999 return 0;
1000}
1001
1002static int wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w,
1003 struct snd_kcontrol *kcontrol, int event)
1004{
1005 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1006 u16 gain_reg;
1007 int offset_val = 0;
1008 int val = 0;
1009
1010 dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
1011
1012 switch (w->reg) {
1013 case BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL:
1014 gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_MIX_CTL;
1015 break;
1016 case BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL:
1017 gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_MIX_CTL;
1018 break;
1019 default:
1020 dev_err(codec->dev, "%s: No gain register avail for %s\n",
1021 __func__, w->name);
1022 return 0;
1023 }
1024
1025 switch (event) {
1026 case SND_SOC_DAPM_POST_PMU:
1027 val = snd_soc_read(codec, gain_reg);
1028 val += offset_val;
1029 snd_soc_write(codec, gain_reg, val);
1030 break;
1031 case SND_SOC_DAPM_POST_PMD:
1032 break;
1033 }
1034
1035 return 0;
1036}
1037
1038static void wsa_macro_hd2_control(struct snd_soc_codec *codec,
1039 u16 reg, int event)
1040{
1041 u16 hd2_scale_reg;
1042 u16 hd2_enable_reg = 0;
1043
1044 if (reg == BOLERO_CDC_WSA_RX0_RX_PATH_CTL) {
1045 hd2_scale_reg = BOLERO_CDC_WSA_RX0_RX_PATH_SEC3;
1046 hd2_enable_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG0;
1047 }
1048 if (reg == BOLERO_CDC_WSA_RX1_RX_PATH_CTL) {
1049 hd2_scale_reg = BOLERO_CDC_WSA_RX1_RX_PATH_SEC3;
1050 hd2_enable_reg = BOLERO_CDC_WSA_RX1_RX_PATH_CFG0;
1051 }
1052
1053 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
1054 snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x10);
1055 snd_soc_update_bits(codec, hd2_scale_reg, 0x03, 0x01);
1056 snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x04);
1057 }
1058
1059 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
1060 snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x00);
1061 snd_soc_update_bits(codec, hd2_scale_reg, 0x03, 0x00);
1062 snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x00);
1063 }
1064}
1065
1066static int wsa_macro_enable_swr(struct snd_soc_dapm_widget *w,
1067 struct snd_kcontrol *kcontrol, int event)
1068{
1069 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1070 int ch_cnt;
1071 struct device *wsa_dev = NULL;
1072 struct wsa_macro_priv *wsa_priv = NULL;
1073
1074 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1075 return -EINVAL;
1076
1077 switch (event) {
1078 case SND_SOC_DAPM_PRE_PMU:
1079 if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) &&
1080 !wsa_priv->rx_0_count)
1081 wsa_priv->rx_0_count++;
1082 if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) &&
1083 !wsa_priv->rx_1_count)
1084 wsa_priv->rx_1_count++;
1085 ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
1086
1087 swrm_wcd_notify(
1088 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
1089 SWR_DEVICE_UP, NULL);
1090 swrm_wcd_notify(
1091 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
1092 SWR_SET_NUM_RX_CH, &ch_cnt);
1093 break;
1094 case SND_SOC_DAPM_POST_PMD:
1095 if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) &&
1096 wsa_priv->rx_0_count)
1097 wsa_priv->rx_0_count--;
1098 if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) &&
1099 wsa_priv->rx_1_count)
1100 wsa_priv->rx_1_count--;
1101 ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
1102
1103 swrm_wcd_notify(
1104 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
1105 SWR_SET_NUM_RX_CH, &ch_cnt);
1106 break;
1107 }
1108 dev_dbg(wsa_priv->dev, "%s: current swr ch cnt: %d\n",
1109 __func__, wsa_priv->rx_0_count + wsa_priv->rx_1_count);
1110
1111 return 0;
1112}
1113
1114static int wsa_macro_config_compander(struct snd_soc_codec *codec,
1115 int comp, int event)
1116{
1117 u16 comp_ctl0_reg, rx_path_cfg0_reg;
1118 struct device *wsa_dev = NULL;
1119 struct wsa_macro_priv *wsa_priv = NULL;
1120
1121 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1122 return -EINVAL;
1123
1124 dev_dbg(codec->dev, "%s: event %d compander %d, enabled %d\n",
1125 __func__, event, comp + 1, wsa_priv->comp_enabled[comp]);
1126
1127 if (!wsa_priv->comp_enabled[comp])
1128 return 0;
1129
1130 comp_ctl0_reg = BOLERO_CDC_WSA_COMPANDER0_CTL0 +
1131 (comp * WSA_MACRO_RX_COMP_OFFSET);
1132 rx_path_cfg0_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG0 +
1133 (comp * WSA_MACRO_RX_PATH_OFFSET);
1134
1135 if (SND_SOC_DAPM_EVENT_ON(event)) {
1136 /* Enable Compander Clock */
1137 snd_soc_update_bits(codec, comp_ctl0_reg, 0x01, 0x01);
1138 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x02);
1139 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x00);
1140 snd_soc_update_bits(codec, rx_path_cfg0_reg, 0x02, 0x02);
1141 }
1142
1143 if (SND_SOC_DAPM_EVENT_OFF(event)) {
1144 snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x04);
1145 snd_soc_update_bits(codec, rx_path_cfg0_reg, 0x02, 0x00);
1146 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x02);
1147 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x00);
1148 snd_soc_update_bits(codec, comp_ctl0_reg, 0x01, 0x00);
1149 snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x00);
1150 }
1151
1152 return 0;
1153}
1154
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301155static void wsa_macro_enable_softclip_clk(struct snd_soc_codec *codec,
1156 struct wsa_macro_priv *wsa_priv,
1157 int path,
1158 bool enable)
1159{
1160 u16 softclip_clk_reg = BOLERO_CDC_WSA_SOFTCLIP0_CRC +
1161 (path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
1162 u8 softclip_mux_mask = (1 << path);
1163 u8 softclip_mux_value = (1 << path);
1164
1165 dev_dbg(codec->dev, "%s: path %d, enable %d\n",
1166 __func__, path, enable);
1167 if (enable) {
1168 if (wsa_priv->softclip_clk_users[path] == 0) {
1169 snd_soc_update_bits(codec,
1170 softclip_clk_reg, 0x01, 0x01);
1171 snd_soc_update_bits(codec,
1172 BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
1173 softclip_mux_mask, softclip_mux_value);
1174 }
1175 wsa_priv->softclip_clk_users[path]++;
1176 } else {
1177 wsa_priv->softclip_clk_users[path]--;
1178 if (wsa_priv->softclip_clk_users[path] == 0) {
1179 snd_soc_update_bits(codec,
1180 softclip_clk_reg, 0x01, 0x00);
1181 snd_soc_update_bits(codec,
1182 BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
1183 softclip_mux_mask, 0x00);
1184 }
1185 }
1186}
1187
1188static int wsa_macro_config_softclip(struct snd_soc_codec *codec,
1189 int path, int event)
1190{
1191 u16 softclip_ctrl_reg = 0;
1192 struct device *wsa_dev = NULL;
1193 struct wsa_macro_priv *wsa_priv = NULL;
1194 int softclip_path = 0;
1195
1196 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1197 return -EINVAL;
1198
1199 if (path == WSA_MACRO_COMP1)
1200 softclip_path = WSA_MACRO_SOFTCLIP0;
1201 else if (path == WSA_MACRO_COMP2)
1202 softclip_path = WSA_MACRO_SOFTCLIP1;
1203
1204 dev_dbg(codec->dev, "%s: event %d path %d, enabled %d\n",
1205 __func__, event, softclip_path,
1206 wsa_priv->is_softclip_on[softclip_path]);
1207
1208 if (!wsa_priv->is_softclip_on[softclip_path])
1209 return 0;
1210
1211 softclip_ctrl_reg = BOLERO_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL +
1212 (softclip_path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
1213
1214 if (SND_SOC_DAPM_EVENT_ON(event)) {
1215 /* Enable Softclip clock and mux */
1216 wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
1217 true);
1218 /* Enable Softclip control */
1219 snd_soc_update_bits(codec, softclip_ctrl_reg, 0x01, 0x01);
1220 }
1221
1222 if (SND_SOC_DAPM_EVENT_OFF(event)) {
1223 snd_soc_update_bits(codec, softclip_ctrl_reg, 0x01, 0x00);
1224 wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
1225 false);
1226 }
1227
1228 return 0;
1229}
1230
Laxminath Kasam243e2752018-04-12 00:40:19 +05301231static int wsa_macro_interp_get_primary_reg(u16 reg, u16 *ind)
1232{
1233 u16 prim_int_reg = 0;
1234
1235 switch (reg) {
1236 case BOLERO_CDC_WSA_RX0_RX_PATH_CTL:
1237 case BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL:
1238 prim_int_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
1239 *ind = 0;
1240 break;
1241 case BOLERO_CDC_WSA_RX1_RX_PATH_CTL:
1242 case BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL:
1243 prim_int_reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
1244 *ind = 1;
1245 break;
1246 }
1247
1248 return prim_int_reg;
1249}
1250
1251static int wsa_macro_enable_prim_interpolator(
1252 struct snd_soc_codec *codec,
1253 u16 reg, int event)
1254{
1255 u16 prim_int_reg;
1256 u16 ind = 0;
1257 struct device *wsa_dev = NULL;
1258 struct wsa_macro_priv *wsa_priv = NULL;
1259
1260 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1261 return -EINVAL;
1262
1263 prim_int_reg = wsa_macro_interp_get_primary_reg(reg, &ind);
1264
1265 switch (event) {
1266 case SND_SOC_DAPM_PRE_PMU:
1267 wsa_priv->prim_int_users[ind]++;
1268 if (wsa_priv->prim_int_users[ind] == 1) {
1269 snd_soc_update_bits(codec,
1270 prim_int_reg + WSA_MACRO_RX_PATH_CFG3_OFFSET,
1271 0x03, 0x03);
1272 snd_soc_update_bits(codec, prim_int_reg,
1273 0x10, 0x10);
1274 wsa_macro_hd2_control(codec, prim_int_reg, event);
1275 snd_soc_update_bits(codec,
1276 prim_int_reg + WSA_MACRO_RX_PATH_DSMDEM_OFFSET,
1277 0x1, 0x1);
1278 snd_soc_update_bits(codec, prim_int_reg,
1279 1 << 0x5, 1 << 0x5);
1280 }
1281 if ((reg != prim_int_reg) &&
1282 ((snd_soc_read(codec, prim_int_reg)) & 0x10))
1283 snd_soc_update_bits(codec, reg, 0x10, 0x10);
1284 break;
1285 case SND_SOC_DAPM_POST_PMD:
1286 wsa_priv->prim_int_users[ind]--;
1287 if (wsa_priv->prim_int_users[ind] == 0) {
1288 snd_soc_update_bits(codec, prim_int_reg,
1289 1 << 0x5, 0 << 0x5);
1290 snd_soc_update_bits(codec, prim_int_reg,
1291 0x40, 0x40);
1292 snd_soc_update_bits(codec, prim_int_reg,
1293 0x40, 0x00);
1294 wsa_macro_hd2_control(codec, prim_int_reg, event);
1295 }
1296 break;
1297 }
1298
1299 dev_dbg(codec->dev, "%s: primary interpolator: INT%d, users: %d\n",
1300 __func__, ind, wsa_priv->prim_int_users[ind]);
1301 return 0;
1302}
1303
1304static int wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w,
1305 struct snd_kcontrol *kcontrol,
1306 int event)
1307{
1308 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1309 u16 gain_reg;
1310 u16 reg;
1311 int val;
1312 int offset_val = 0;
1313 struct device *wsa_dev = NULL;
1314 struct wsa_macro_priv *wsa_priv = NULL;
1315
1316 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1317 return -EINVAL;
1318
1319 dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
1320
1321 if (!(strcmp(w->name, "WSA_RX INT0 INTERP"))) {
1322 reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
1323 gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_CTL;
1324 } else if (!(strcmp(w->name, "WSA_RX INT1 INTERP"))) {
1325 reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
1326 gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_CTL;
1327 } else {
1328 dev_err(codec->dev, "%s: Interpolator reg not found\n",
1329 __func__);
1330 return -EINVAL;
1331 }
1332
1333 switch (event) {
1334 case SND_SOC_DAPM_PRE_PMU:
1335 /* Reset if needed */
1336 wsa_macro_enable_prim_interpolator(codec, reg, event);
1337 break;
1338 case SND_SOC_DAPM_POST_PMU:
1339 wsa_macro_config_compander(codec, w->shift, event);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301340 wsa_macro_config_softclip(codec, w->shift, event);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301341 /* apply gain after int clk is enabled */
Laxminath Kasam21c8b222018-06-21 18:47:22 +05301342 if ((wsa_priv->spkr_gain_offset ==
1343 WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
Laxminath Kasam243e2752018-04-12 00:40:19 +05301344 (wsa_priv->comp_enabled[WSA_MACRO_COMP1] ||
1345 wsa_priv->comp_enabled[WSA_MACRO_COMP2]) &&
1346 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL ||
1347 gain_reg == BOLERO_CDC_WSA_RX1_RX_VOL_CTL)) {
1348 snd_soc_update_bits(codec, BOLERO_CDC_WSA_RX0_RX_PATH_SEC1,
1349 0x01, 0x01);
1350 snd_soc_update_bits(codec,
1351 BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC0,
1352 0x01, 0x01);
1353 snd_soc_update_bits(codec, BOLERO_CDC_WSA_RX1_RX_PATH_SEC1,
1354 0x01, 0x01);
1355 snd_soc_update_bits(codec,
1356 BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC0,
1357 0x01, 0x01);
1358 offset_val = -2;
1359 }
1360 val = snd_soc_read(codec, gain_reg);
1361 val += offset_val;
1362 snd_soc_write(codec, gain_reg, val);
1363 wsa_macro_config_ear_spkr_gain(codec, wsa_priv,
1364 event, gain_reg);
1365 break;
1366 case SND_SOC_DAPM_POST_PMD:
1367 wsa_macro_config_compander(codec, w->shift, event);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301368 wsa_macro_config_softclip(codec, w->shift, event);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301369 wsa_macro_enable_prim_interpolator(codec, reg, event);
Laxminath Kasam21c8b222018-06-21 18:47:22 +05301370 if ((wsa_priv->spkr_gain_offset ==
1371 WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
Laxminath Kasam243e2752018-04-12 00:40:19 +05301372 (wsa_priv->comp_enabled[WSA_MACRO_COMP1] ||
1373 wsa_priv->comp_enabled[WSA_MACRO_COMP2]) &&
1374 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL ||
1375 gain_reg == BOLERO_CDC_WSA_RX1_RX_VOL_CTL)) {
1376 snd_soc_update_bits(codec, BOLERO_CDC_WSA_RX0_RX_PATH_SEC1,
1377 0x01, 0x00);
1378 snd_soc_update_bits(codec,
1379 BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC0,
1380 0x01, 0x00);
1381 snd_soc_update_bits(codec, BOLERO_CDC_WSA_RX1_RX_PATH_SEC1,
1382 0x01, 0x00);
1383 snd_soc_update_bits(codec,
1384 BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC0,
1385 0x01, 0x00);
1386 offset_val = 2;
1387 val = snd_soc_read(codec, gain_reg);
1388 val += offset_val;
1389 snd_soc_write(codec, gain_reg, val);
1390 }
1391 wsa_macro_config_ear_spkr_gain(codec, wsa_priv,
1392 event, gain_reg);
1393 break;
1394 }
1395
1396 return 0;
1397}
1398
1399static int wsa_macro_config_ear_spkr_gain(struct snd_soc_codec *codec,
1400 struct wsa_macro_priv *wsa_priv,
1401 int event, int gain_reg)
1402{
1403 int comp_gain_offset, val;
1404
1405 switch (wsa_priv->spkr_mode) {
Laxminath Kasam21c8b222018-06-21 18:47:22 +05301406 /* Compander gain in WSA_MACRO_SPKR_MODE1 case is 12 dB */
1407 case WSA_MACRO_SPKR_MODE_1:
Laxminath Kasam243e2752018-04-12 00:40:19 +05301408 comp_gain_offset = -12;
1409 break;
1410 /* Default case compander gain is 15 dB */
1411 default:
1412 comp_gain_offset = -15;
1413 break;
1414 }
1415
1416 switch (event) {
1417 case SND_SOC_DAPM_POST_PMU:
1418 /* Apply ear spkr gain only if compander is enabled */
1419 if (wsa_priv->comp_enabled[WSA_MACRO_COMP1] &&
1420 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL) &&
1421 (wsa_priv->ear_spkr_gain != 0)) {
1422 /* For example, val is -8(-12+5-1) for 4dB of gain */
1423 val = comp_gain_offset + wsa_priv->ear_spkr_gain - 1;
1424 snd_soc_write(codec, gain_reg, val);
1425
1426 dev_dbg(wsa_priv->dev, "%s: RX0 Volume %d dB\n",
1427 __func__, val);
1428 }
1429 break;
1430 case SND_SOC_DAPM_POST_PMD:
1431 /*
1432 * Reset RX0 volume to 0 dB if compander is enabled and
1433 * ear_spkr_gain is non-zero.
1434 */
1435 if (wsa_priv->comp_enabled[WSA_MACRO_COMP1] &&
1436 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL) &&
1437 (wsa_priv->ear_spkr_gain != 0)) {
1438 snd_soc_write(codec, gain_reg, 0x0);
1439
1440 dev_dbg(wsa_priv->dev, "%s: Reset RX0 Volume to 0 dB\n",
1441 __func__);
1442 }
1443 break;
1444 }
1445
1446 return 0;
1447}
1448
1449static int wsa_macro_spk_boost_event(struct snd_soc_dapm_widget *w,
1450 struct snd_kcontrol *kcontrol,
1451 int event)
1452{
1453 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1454 u16 boost_path_ctl, boost_path_cfg1;
1455 u16 reg, reg_mix;
1456
1457 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
1458
1459 if (!strcmp(w->name, "WSA_RX INT0 CHAIN")) {
1460 boost_path_ctl = BOLERO_CDC_WSA_BOOST0_BOOST_PATH_CTL;
1461 boost_path_cfg1 = BOLERO_CDC_WSA_RX0_RX_PATH_CFG1;
1462 reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
1463 reg_mix = BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL;
1464 } else if (!strcmp(w->name, "WSA_RX INT1 CHAIN")) {
1465 boost_path_ctl = BOLERO_CDC_WSA_BOOST1_BOOST_PATH_CTL;
1466 boost_path_cfg1 = BOLERO_CDC_WSA_RX1_RX_PATH_CFG1;
1467 reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
1468 reg_mix = BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL;
1469 } else {
1470 dev_err(codec->dev, "%s: unknown widget: %s\n",
1471 __func__, w->name);
1472 return -EINVAL;
1473 }
1474
1475 switch (event) {
1476 case SND_SOC_DAPM_PRE_PMU:
1477 snd_soc_update_bits(codec, boost_path_cfg1, 0x01, 0x01);
1478 snd_soc_update_bits(codec, boost_path_ctl, 0x10, 0x10);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301479 if ((snd_soc_read(codec, reg_mix)) & 0x10)
1480 snd_soc_update_bits(codec, reg_mix, 0x10, 0x00);
1481 break;
Laxminath Kasam0c857002018-07-17 23:47:17 +05301482 case SND_SOC_DAPM_POST_PMU:
1483 snd_soc_update_bits(codec, reg, 0x10, 0x00);
1484 break;
Laxminath Kasam243e2752018-04-12 00:40:19 +05301485 case SND_SOC_DAPM_POST_PMD:
1486 snd_soc_update_bits(codec, boost_path_ctl, 0x10, 0x00);
1487 snd_soc_update_bits(codec, boost_path_cfg1, 0x01, 0x00);
1488 break;
1489 }
1490
1491 return 0;
1492}
1493
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301494
1495static int wsa_macro_enable_vbat(struct snd_soc_dapm_widget *w,
1496 struct snd_kcontrol *kcontrol,
1497 int event)
1498{
1499 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1500 struct device *wsa_dev = NULL;
1501 struct wsa_macro_priv *wsa_priv = NULL;
1502 u16 vbat_path_cfg = 0;
1503 int softclip_path = 0;
1504
1505 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1506 return -EINVAL;
1507
1508 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
1509 if (!strcmp(w->name, "WSA_RX INT0 VBAT")) {
1510 vbat_path_cfg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG1;
1511 softclip_path = WSA_MACRO_SOFTCLIP0;
1512 } else if (!strcmp(w->name, "WSA_RX INT1 VBAT")) {
1513 vbat_path_cfg = BOLERO_CDC_WSA_RX1_RX_PATH_CFG1;
1514 softclip_path = WSA_MACRO_SOFTCLIP1;
1515 }
1516
1517 switch (event) {
1518 case SND_SOC_DAPM_PRE_PMU:
1519 /* Enable clock for VBAT block */
1520 snd_soc_update_bits(codec,
1521 BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x10);
1522 /* Enable VBAT block */
1523 snd_soc_update_bits(codec,
1524 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x01);
1525 /* Update interpolator with 384K path */
1526 snd_soc_update_bits(codec, vbat_path_cfg, 0x80, 0x80);
1527 /* Use attenuation mode */
1528 snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
1529 0x02, 0x00);
1530 /*
1531 * BCL block needs softclip clock and mux config to be enabled
1532 */
1533 wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
1534 true);
1535 /* Enable VBAT at channel level */
1536 snd_soc_update_bits(codec, vbat_path_cfg, 0x02, 0x02);
1537 /* Set the ATTK1 gain */
1538 snd_soc_update_bits(codec,
1539 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
1540 0xFF, 0xFF);
1541 snd_soc_update_bits(codec,
1542 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
1543 0xFF, 0x03);
1544 snd_soc_update_bits(codec,
1545 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
1546 0xFF, 0x00);
1547 /* Set the ATTK2 gain */
1548 snd_soc_update_bits(codec,
1549 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
1550 0xFF, 0xFF);
1551 snd_soc_update_bits(codec,
1552 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
1553 0xFF, 0x03);
1554 snd_soc_update_bits(codec,
1555 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
1556 0xFF, 0x00);
1557 /* Set the ATTK3 gain */
1558 snd_soc_update_bits(codec,
1559 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
1560 0xFF, 0xFF);
1561 snd_soc_update_bits(codec,
1562 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
1563 0xFF, 0x03);
1564 snd_soc_update_bits(codec,
1565 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
1566 0xFF, 0x00);
1567 break;
1568
1569 case SND_SOC_DAPM_POST_PMD:
1570 snd_soc_update_bits(codec, vbat_path_cfg, 0x80, 0x00);
1571 snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
1572 0x02, 0x02);
1573 snd_soc_update_bits(codec, vbat_path_cfg, 0x02, 0x00);
1574 snd_soc_update_bits(codec,
1575 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
1576 0xFF, 0x00);
1577 snd_soc_update_bits(codec,
1578 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
1579 0xFF, 0x00);
1580 snd_soc_update_bits(codec,
1581 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
1582 0xFF, 0x00);
1583 snd_soc_update_bits(codec,
1584 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
1585 0xFF, 0x00);
1586 snd_soc_update_bits(codec,
1587 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
1588 0xFF, 0x00);
1589 snd_soc_update_bits(codec,
1590 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
1591 0xFF, 0x00);
1592 snd_soc_update_bits(codec,
1593 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
1594 0xFF, 0x00);
1595 snd_soc_update_bits(codec,
1596 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
1597 0xFF, 0x00);
1598 snd_soc_update_bits(codec,
1599 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
1600 0xFF, 0x00);
1601 wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
1602 false);
1603 snd_soc_update_bits(codec,
1604 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x00);
1605 snd_soc_update_bits(codec,
1606 BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x00);
1607 break;
1608 default:
1609 dev_err(wsa_dev, "%s: Invalid event %d\n", __func__, event);
1610 break;
1611 }
1612 return 0;
1613}
1614
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301615static int wsa_macro_enable_echo(struct snd_soc_dapm_widget *w,
1616 struct snd_kcontrol *kcontrol,
1617 int event)
1618{
1619 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1620 struct device *wsa_dev = NULL;
1621 struct wsa_macro_priv *wsa_priv = NULL;
1622 u16 val, ec_tx = 0, ec_hq_reg;
1623
1624 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1625 return -EINVAL;
1626
1627 dev_dbg(wsa_dev, "%s %d %s\n", __func__, event, w->name);
1628
1629 val = snd_soc_read(codec, BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0);
1630 if (!(strcmp(w->name, "WSA RX_MIX EC0_MUX")))
1631 ec_tx = (val & 0x07) - 1;
1632 else
1633 ec_tx = ((val & 0x38) >> 0x3) - 1;
1634
1635 if (ec_tx < 0 || ec_tx >= (WSA_MACRO_RX1 + 1)) {
1636 dev_err(wsa_dev, "%s: EC mix control not set correctly\n",
1637 __func__);
1638 return -EINVAL;
1639 }
1640 if (wsa_priv->ec_hq[ec_tx]) {
1641 snd_soc_update_bits(codec,
1642 BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
1643 0x1 << ec_tx, 0x1 << ec_tx);
1644 ec_hq_reg = BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL +
1645 0x20 * ec_tx;
1646 snd_soc_update_bits(codec, ec_hq_reg, 0x01, 0x01);
1647 ec_hq_reg = BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0 +
1648 0x20 * ec_tx;
1649 /* default set to 48k */
1650 snd_soc_update_bits(codec, ec_hq_reg, 0x1E, 0x08);
1651 }
1652
1653 return 0;
1654}
1655
1656static int wsa_macro_get_ec_hq(struct snd_kcontrol *kcontrol,
1657 struct snd_ctl_elem_value *ucontrol)
1658{
1659
1660 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1661 int ec_tx = ((struct soc_multi_mixer_control *)
1662 kcontrol->private_value)->shift;
1663 struct device *wsa_dev = NULL;
1664 struct wsa_macro_priv *wsa_priv = NULL;
1665
1666 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1667 return -EINVAL;
1668
1669 ucontrol->value.integer.value[0] = wsa_priv->ec_hq[ec_tx];
1670 return 0;
1671}
1672
1673static int wsa_macro_set_ec_hq(struct snd_kcontrol *kcontrol,
1674 struct snd_ctl_elem_value *ucontrol)
1675{
1676 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1677 int ec_tx = ((struct soc_multi_mixer_control *)
1678 kcontrol->private_value)->shift;
1679 int value = ucontrol->value.integer.value[0];
1680 struct device *wsa_dev = NULL;
1681 struct wsa_macro_priv *wsa_priv = NULL;
1682
1683 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1684 return -EINVAL;
1685
1686 dev_dbg(wsa_dev, "%s: enable current %d, new %d\n",
1687 __func__, wsa_priv->ec_hq[ec_tx], value);
1688 wsa_priv->ec_hq[ec_tx] = value;
1689
1690 return 0;
1691}
1692
Laxminath Kasam243e2752018-04-12 00:40:19 +05301693static int wsa_macro_get_compander(struct snd_kcontrol *kcontrol,
1694 struct snd_ctl_elem_value *ucontrol)
1695{
1696
1697 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1698 int comp = ((struct soc_multi_mixer_control *)
1699 kcontrol->private_value)->shift;
1700 struct device *wsa_dev = NULL;
1701 struct wsa_macro_priv *wsa_priv = NULL;
1702
1703 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1704 return -EINVAL;
1705
1706 ucontrol->value.integer.value[0] = wsa_priv->comp_enabled[comp];
1707 return 0;
1708}
1709
1710static int wsa_macro_set_compander(struct snd_kcontrol *kcontrol,
1711 struct snd_ctl_elem_value *ucontrol)
1712{
1713 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1714 int comp = ((struct soc_multi_mixer_control *)
1715 kcontrol->private_value)->shift;
1716 int value = ucontrol->value.integer.value[0];
1717 struct device *wsa_dev = NULL;
1718 struct wsa_macro_priv *wsa_priv = NULL;
1719
1720 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1721 return -EINVAL;
1722
1723 dev_dbg(codec->dev, "%s: Compander %d enable current %d, new %d\n",
1724 __func__, comp + 1, wsa_priv->comp_enabled[comp], value);
1725 wsa_priv->comp_enabled[comp] = value;
1726
1727 return 0;
1728}
1729
1730static int wsa_macro_ear_spkr_pa_gain_get(struct snd_kcontrol *kcontrol,
1731 struct snd_ctl_elem_value *ucontrol)
1732{
1733 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1734 struct device *wsa_dev = NULL;
1735 struct wsa_macro_priv *wsa_priv = NULL;
1736
1737 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1738 return -EINVAL;
1739
1740 ucontrol->value.integer.value[0] = wsa_priv->ear_spkr_gain;
1741
1742 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
1743 __func__, ucontrol->value.integer.value[0]);
1744
1745 return 0;
1746}
1747
1748static int wsa_macro_ear_spkr_pa_gain_put(struct snd_kcontrol *kcontrol,
1749 struct snd_ctl_elem_value *ucontrol)
1750{
1751 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1752 struct device *wsa_dev = NULL;
1753 struct wsa_macro_priv *wsa_priv = NULL;
1754
1755 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1756 return -EINVAL;
1757
1758 wsa_priv->ear_spkr_gain = ucontrol->value.integer.value[0];
1759
1760 dev_dbg(codec->dev, "%s: gain = %d\n", __func__,
1761 wsa_priv->ear_spkr_gain);
1762
1763 return 0;
1764}
1765
1766static int wsa_macro_spkr_left_boost_stage_get(struct snd_kcontrol *kcontrol,
1767 struct snd_ctl_elem_value *ucontrol)
1768{
1769 u8 bst_state_max = 0;
1770 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1771
1772 bst_state_max = snd_soc_read(codec, BOLERO_CDC_WSA_BOOST0_BOOST_CTL);
1773 bst_state_max = (bst_state_max & 0x0c) >> 2;
1774 ucontrol->value.integer.value[0] = bst_state_max;
1775 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
1776 __func__, ucontrol->value.integer.value[0]);
1777
1778 return 0;
1779}
1780
1781static int wsa_macro_spkr_left_boost_stage_put(struct snd_kcontrol *kcontrol,
1782 struct snd_ctl_elem_value *ucontrol)
1783{
1784 u8 bst_state_max;
1785 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1786
1787 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
1788 __func__, ucontrol->value.integer.value[0]);
1789 bst_state_max = ucontrol->value.integer.value[0] << 2;
1790 snd_soc_update_bits(codec, BOLERO_CDC_WSA_BOOST0_BOOST_CTL,
1791 0x0c, bst_state_max);
1792
1793 return 0;
1794}
1795
1796static int wsa_macro_spkr_right_boost_stage_get(struct snd_kcontrol *kcontrol,
1797 struct snd_ctl_elem_value *ucontrol)
1798{
1799 u8 bst_state_max = 0;
1800 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1801
1802 bst_state_max = snd_soc_read(codec, BOLERO_CDC_WSA_BOOST1_BOOST_CTL);
1803 bst_state_max = (bst_state_max & 0x0c) >> 2;
1804 ucontrol->value.integer.value[0] = bst_state_max;
1805 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
1806 __func__, ucontrol->value.integer.value[0]);
1807
1808 return 0;
1809}
1810
1811static int wsa_macro_spkr_right_boost_stage_put(struct snd_kcontrol *kcontrol,
1812 struct snd_ctl_elem_value *ucontrol)
1813{
1814 u8 bst_state_max;
1815 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1816
1817 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
1818 __func__, ucontrol->value.integer.value[0]);
1819 bst_state_max = ucontrol->value.integer.value[0] << 2;
1820 snd_soc_update_bits(codec, BOLERO_CDC_WSA_BOOST1_BOOST_CTL,
1821 0x0c, bst_state_max);
1822
1823 return 0;
1824}
1825
1826static int wsa_macro_rx_mux_get(struct snd_kcontrol *kcontrol,
1827 struct snd_ctl_elem_value *ucontrol)
1828{
1829 struct snd_soc_dapm_widget *widget =
1830 snd_soc_dapm_kcontrol_widget(kcontrol);
1831 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1832 struct device *wsa_dev = NULL;
1833 struct wsa_macro_priv *wsa_priv = NULL;
1834
1835 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1836 return -EINVAL;
1837
1838 ucontrol->value.integer.value[0] =
1839 wsa_priv->rx_port_value[widget->shift];
1840 return 0;
1841}
1842
1843static int wsa_macro_rx_mux_put(struct snd_kcontrol *kcontrol,
1844 struct snd_ctl_elem_value *ucontrol)
1845{
1846 struct snd_soc_dapm_widget *widget =
1847 snd_soc_dapm_kcontrol_widget(kcontrol);
1848 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1849 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1850 struct snd_soc_dapm_update *update = NULL;
1851 u32 rx_port_value = ucontrol->value.integer.value[0];
1852 u32 bit_input = 0;
1853 u32 aif_rst;
1854 struct device *wsa_dev = NULL;
1855 struct wsa_macro_priv *wsa_priv = NULL;
1856
1857 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1858 return -EINVAL;
1859
1860 aif_rst = wsa_priv->rx_port_value[widget->shift];
1861 if (!rx_port_value) {
1862 if (aif_rst == 0) {
1863 dev_err(wsa_dev, "%s: AIF reset already\n", __func__);
1864 return 0;
1865 }
1866 }
1867 wsa_priv->rx_port_value[widget->shift] = rx_port_value;
1868
1869 bit_input = widget->shift;
1870 if (widget->shift >= WSA_MACRO_RX_MIX)
1871 bit_input %= WSA_MACRO_RX_MIX;
1872
1873 switch (rx_port_value) {
1874 case 0:
1875 clear_bit(bit_input,
Laxminath Kasam59c7a1d2018-08-09 16:11:17 +05301876 &wsa_priv->active_ch_mask[aif_rst]);
1877 wsa_priv->active_ch_cnt[aif_rst]--;
Laxminath Kasam243e2752018-04-12 00:40:19 +05301878 break;
1879 case 1:
1880 case 2:
1881 set_bit(bit_input,
Laxminath Kasam59c7a1d2018-08-09 16:11:17 +05301882 &wsa_priv->active_ch_mask[rx_port_value]);
1883 wsa_priv->active_ch_cnt[rx_port_value]++;
Laxminath Kasam243e2752018-04-12 00:40:19 +05301884 break;
1885 default:
1886 dev_err(wsa_dev,
1887 "%s: Invalid AIF_ID for WSA RX MUX\n", __func__);
1888 return -EINVAL;
1889 }
1890
1891 snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
1892 rx_port_value, e, update);
1893 return 0;
1894}
1895
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301896static int wsa_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol,
1897 struct snd_ctl_elem_value *ucontrol)
1898{
1899 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1900
1901 ucontrol->value.integer.value[0] =
1902 ((snd_soc_read(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG) & 0x04) ?
1903 1 : 0);
1904
1905 dev_dbg(codec->dev, "%s: value: %lu\n", __func__,
1906 ucontrol->value.integer.value[0]);
1907
1908 return 0;
1909}
1910
1911static int wsa_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol,
1912 struct snd_ctl_elem_value *ucontrol)
1913{
1914 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1915
1916 dev_dbg(codec->dev, "%s: value: %lu\n", __func__,
1917 ucontrol->value.integer.value[0]);
1918
1919 /* Set Vbat register configuration for GSM mode bit based on value */
1920 if (ucontrol->value.integer.value[0])
1921 snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
1922 0x04, 0x04);
1923 else
1924 snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
1925 0x04, 0x00);
1926
1927 return 0;
1928}
1929
1930static int wsa_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol,
1931 struct snd_ctl_elem_value *ucontrol)
1932{
1933 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1934 struct device *wsa_dev = NULL;
1935 struct wsa_macro_priv *wsa_priv = NULL;
1936 int path = ((struct soc_multi_mixer_control *)
1937 kcontrol->private_value)->shift;
1938
1939 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1940 return -EINVAL;
1941
1942 ucontrol->value.integer.value[0] = wsa_priv->is_softclip_on[path];
1943
1944 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
1945 __func__, ucontrol->value.integer.value[0]);
1946
1947 return 0;
1948}
1949
1950static int wsa_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol,
1951 struct snd_ctl_elem_value *ucontrol)
1952{
1953 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1954 struct device *wsa_dev = NULL;
1955 struct wsa_macro_priv *wsa_priv = NULL;
1956 int path = ((struct soc_multi_mixer_control *)
1957 kcontrol->private_value)->shift;
1958
1959 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1960 return -EINVAL;
1961
1962 wsa_priv->is_softclip_on[path] = ucontrol->value.integer.value[0];
1963
1964 dev_dbg(codec->dev, "%s: soft clip enable for %d: %d\n", __func__,
1965 path, wsa_priv->is_softclip_on[path]);
1966
1967 return 0;
1968}
1969
Laxminath Kasam243e2752018-04-12 00:40:19 +05301970static const struct snd_kcontrol_new wsa_macro_snd_controls[] = {
1971 SOC_ENUM_EXT("EAR SPKR PA Gain", wsa_macro_ear_spkr_pa_gain_enum,
1972 wsa_macro_ear_spkr_pa_gain_get,
1973 wsa_macro_ear_spkr_pa_gain_put),
1974 SOC_ENUM_EXT("SPKR Left Boost Max State",
1975 wsa_macro_spkr_boost_stage_enum,
1976 wsa_macro_spkr_left_boost_stage_get,
1977 wsa_macro_spkr_left_boost_stage_put),
1978 SOC_ENUM_EXT("SPKR Right Boost Max State",
1979 wsa_macro_spkr_boost_stage_enum,
1980 wsa_macro_spkr_right_boost_stage_get,
1981 wsa_macro_spkr_right_boost_stage_put),
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301982 SOC_ENUM_EXT("GSM mode Enable", wsa_macro_vbat_bcl_gsm_mode_enum,
1983 wsa_macro_vbat_bcl_gsm_mode_func_get,
1984 wsa_macro_vbat_bcl_gsm_mode_func_put),
1985 SOC_SINGLE_EXT("WSA_Softclip0 Enable", SND_SOC_NOPM,
1986 WSA_MACRO_SOFTCLIP0, 1, 0,
1987 wsa_macro_soft_clip_enable_get,
1988 wsa_macro_soft_clip_enable_put),
1989 SOC_SINGLE_EXT("WSA_Softclip1 Enable", SND_SOC_NOPM,
1990 WSA_MACRO_SOFTCLIP1, 1, 0,
1991 wsa_macro_soft_clip_enable_get,
1992 wsa_macro_soft_clip_enable_put),
Laxminath Kasam243e2752018-04-12 00:40:19 +05301993 SOC_SINGLE_SX_TLV("WSA_RX0 Digital Volume",
1994 BOLERO_CDC_WSA_RX0_RX_VOL_CTL,
1995 0, -84, 40, digital_gain),
1996 SOC_SINGLE_SX_TLV("WSA_RX1 Digital Volume",
1997 BOLERO_CDC_WSA_RX1_RX_VOL_CTL,
1998 0, -84, 40, digital_gain),
1999 SOC_SINGLE_EXT("WSA_COMP1 Switch", SND_SOC_NOPM, WSA_MACRO_COMP1, 1, 0,
2000 wsa_macro_get_compander, wsa_macro_set_compander),
2001 SOC_SINGLE_EXT("WSA_COMP2 Switch", SND_SOC_NOPM, WSA_MACRO_COMP2, 1, 0,
2002 wsa_macro_get_compander, wsa_macro_set_compander),
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05302003 SOC_SINGLE_EXT("WSA_RX0 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX0,
2004 1, 0, wsa_macro_get_ec_hq, wsa_macro_set_ec_hq),
2005 SOC_SINGLE_EXT("WSA_RX1 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX1,
2006 1, 0, wsa_macro_get_ec_hq, wsa_macro_set_ec_hq),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302007};
2008
2009static const struct soc_enum rx_mux_enum =
2010 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_mux_text), rx_mux_text);
2011
2012static const struct snd_kcontrol_new rx_mux[WSA_MACRO_RX_MAX] = {
2013 SOC_DAPM_ENUM_EXT("WSA RX0 Mux", rx_mux_enum,
2014 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2015 SOC_DAPM_ENUM_EXT("WSA RX1 Mux", rx_mux_enum,
2016 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2017 SOC_DAPM_ENUM_EXT("WSA RX_MIX0 Mux", rx_mux_enum,
2018 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2019 SOC_DAPM_ENUM_EXT("WSA RX_MIX1 Mux", rx_mux_enum,
2020 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2021};
2022
2023static int wsa_macro_vi_feed_mixer_get(struct snd_kcontrol *kcontrol,
2024 struct snd_ctl_elem_value *ucontrol)
2025{
2026 struct snd_soc_dapm_widget *widget =
2027 snd_soc_dapm_kcontrol_widget(kcontrol);
2028 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
2029 struct soc_multi_mixer_control *mixer =
2030 ((struct soc_multi_mixer_control *)kcontrol->private_value);
2031 u32 dai_id = widget->shift;
2032 u32 spk_tx_id = mixer->shift;
2033 struct device *wsa_dev = NULL;
2034 struct wsa_macro_priv *wsa_priv = NULL;
2035
2036 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
2037 return -EINVAL;
2038
2039 if (test_bit(spk_tx_id, &wsa_priv->active_ch_mask[dai_id]))
2040 ucontrol->value.integer.value[0] = 1;
2041 else
2042 ucontrol->value.integer.value[0] = 0;
2043
2044 return 0;
2045}
2046
2047static int wsa_macro_vi_feed_mixer_put(struct snd_kcontrol *kcontrol,
2048 struct snd_ctl_elem_value *ucontrol)
2049{
2050 struct snd_soc_dapm_widget *widget =
2051 snd_soc_dapm_kcontrol_widget(kcontrol);
2052 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
2053 struct soc_multi_mixer_control *mixer =
2054 ((struct soc_multi_mixer_control *)kcontrol->private_value);
2055 u32 spk_tx_id = mixer->shift;
2056 u32 enable = ucontrol->value.integer.value[0];
2057 struct device *wsa_dev = NULL;
2058 struct wsa_macro_priv *wsa_priv = NULL;
2059
2060 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
2061 return -EINVAL;
2062
2063 wsa_priv->vi_feed_value = ucontrol->value.integer.value[0];
2064
2065 if (enable) {
2066 if (spk_tx_id == WSA_MACRO_TX0 &&
2067 !test_bit(WSA_MACRO_TX0,
2068 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2069 set_bit(WSA_MACRO_TX0,
2070 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2071 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]++;
2072 }
2073 if (spk_tx_id == WSA_MACRO_TX1 &&
2074 !test_bit(WSA_MACRO_TX1,
2075 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2076 set_bit(WSA_MACRO_TX1,
2077 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2078 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]++;
2079 }
2080 } else {
2081 if (spk_tx_id == WSA_MACRO_TX0 &&
2082 test_bit(WSA_MACRO_TX0,
2083 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2084 clear_bit(WSA_MACRO_TX0,
2085 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2086 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]--;
2087 }
2088 if (spk_tx_id == WSA_MACRO_TX1 &&
2089 test_bit(WSA_MACRO_TX1,
2090 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2091 clear_bit(WSA_MACRO_TX1,
2092 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2093 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]--;
2094 }
2095 }
2096 snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
2097
2098 return 0;
2099}
2100
2101static const struct snd_kcontrol_new aif_vi_mixer[] = {
2102 SOC_SINGLE_EXT("WSA_SPKR_VI_1", SND_SOC_NOPM, WSA_MACRO_TX0, 1, 0,
2103 wsa_macro_vi_feed_mixer_get,
2104 wsa_macro_vi_feed_mixer_put),
2105 SOC_SINGLE_EXT("WSA_SPKR_VI_2", SND_SOC_NOPM, WSA_MACRO_TX1, 1, 0,
2106 wsa_macro_vi_feed_mixer_get,
2107 wsa_macro_vi_feed_mixer_put),
2108};
2109
2110static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = {
2111 SND_SOC_DAPM_AIF_IN("WSA AIF1 PB", "WSA_AIF1 Playback", 0,
2112 SND_SOC_NOPM, 0, 0),
2113
2114 SND_SOC_DAPM_AIF_IN("WSA AIF_MIX1 PB", "WSA_AIF_MIX1 Playback", 0,
2115 SND_SOC_NOPM, 0, 0),
2116
2117 SND_SOC_DAPM_AIF_OUT_E("WSA AIF_VI", "WSA_AIF_VI Capture", 0,
2118 SND_SOC_NOPM, WSA_MACRO_AIF_VI, 0,
2119 wsa_macro_enable_vi_feedback,
2120 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2121
2122 SND_SOC_DAPM_AIF_OUT("WSA AIF_ECHO", "WSA_AIF_ECHO Capture", 0,
2123 SND_SOC_NOPM, 0, 0),
2124
2125 SND_SOC_DAPM_MIXER("WSA_AIF_VI Mixer", SND_SOC_NOPM, WSA_MACRO_AIF_VI,
2126 0, aif_vi_mixer, ARRAY_SIZE(aif_vi_mixer)),
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05302127 SND_SOC_DAPM_MUX_E("WSA RX_MIX EC0_MUX", SND_SOC_NOPM,
2128 WSA_MACRO_EC0_MUX, 0,
2129 &rx_mix_ec0_mux, wsa_macro_enable_echo,
2130 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2131 SND_SOC_DAPM_MUX_E("WSA RX_MIX EC1_MUX", SND_SOC_NOPM,
2132 WSA_MACRO_EC1_MUX, 0,
2133 &rx_mix_ec1_mux, wsa_macro_enable_echo,
2134 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302135
2136 SND_SOC_DAPM_MUX("WSA RX0 MUX", SND_SOC_NOPM, WSA_MACRO_RX0, 0,
2137 &rx_mux[WSA_MACRO_RX0]),
2138 SND_SOC_DAPM_MUX("WSA RX1 MUX", SND_SOC_NOPM, WSA_MACRO_RX1, 0,
2139 &rx_mux[WSA_MACRO_RX1]),
2140 SND_SOC_DAPM_MUX("WSA RX_MIX0 MUX", SND_SOC_NOPM, WSA_MACRO_RX_MIX0, 0,
2141 &rx_mux[WSA_MACRO_RX_MIX0]),
2142 SND_SOC_DAPM_MUX("WSA RX_MIX1 MUX", SND_SOC_NOPM, WSA_MACRO_RX_MIX1, 0,
2143 &rx_mux[WSA_MACRO_RX_MIX1]),
2144
2145 SND_SOC_DAPM_MIXER("WSA RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
2146 SND_SOC_DAPM_MIXER("WSA RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
2147 SND_SOC_DAPM_MIXER("WSA RX_MIX0", SND_SOC_NOPM, 0, 0, NULL, 0),
2148 SND_SOC_DAPM_MIXER("WSA RX_MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
2149
2150 SND_SOC_DAPM_MUX_E("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0,
2151 &rx0_prim_inp0_mux, wsa_macro_enable_swr,
2152 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2153 SND_SOC_DAPM_MUX_E("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0,
2154 &rx0_prim_inp1_mux, wsa_macro_enable_swr,
2155 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2156 SND_SOC_DAPM_MUX_E("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0,
2157 &rx0_prim_inp2_mux, wsa_macro_enable_swr,
2158 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2159 SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM, 0, 0,
2160 &rx0_mix_mux, wsa_macro_enable_mix_path,
2161 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2162 SND_SOC_DAPM_MUX_E("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0,
2163 &rx1_prim_inp0_mux, wsa_macro_enable_swr,
2164 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2165 SND_SOC_DAPM_MUX_E("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0,
2166 &rx1_prim_inp1_mux, wsa_macro_enable_swr,
2167 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2168 SND_SOC_DAPM_MUX_E("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0,
2169 &rx1_prim_inp2_mux, wsa_macro_enable_swr,
2170 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2171 SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM, 0, 0,
2172 &rx1_mix_mux, wsa_macro_enable_mix_path,
2173 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2174 SND_SOC_DAPM_MIXER("WSA_RX INT0 MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2175 SND_SOC_DAPM_MIXER("WSA_RX INT1 MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2176 SND_SOC_DAPM_MIXER("WSA_RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2177 SND_SOC_DAPM_MIXER("WSA_RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2178
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302179 SND_SOC_DAPM_MUX_E("WSA_RX0 INT0 SIDETONE MIX",
2180 BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 4, 0,
2181 &rx0_sidetone_mix_mux, wsa_macro_enable_swr,
2182 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2183 SND_SOC_DAPM_INPUT("WSA SRC0_INP"),
2184
2185 SND_SOC_DAPM_INPUT("WSA_TX DEC0_INP"),
2186 SND_SOC_DAPM_INPUT("WSA_TX DEC1_INP"),
2187
Laxminath Kasam243e2752018-04-12 00:40:19 +05302188 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 INTERP", SND_SOC_NOPM,
2189 WSA_MACRO_COMP1, 0, NULL, 0, wsa_macro_enable_interpolator,
2190 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2191 SND_SOC_DAPM_POST_PMD),
2192 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 INTERP", SND_SOC_NOPM,
2193 WSA_MACRO_COMP2, 0, NULL, 0, wsa_macro_enable_interpolator,
2194 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2195 SND_SOC_DAPM_POST_PMD),
2196
2197 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 CHAIN", SND_SOC_NOPM, 0, 0,
2198 NULL, 0, wsa_macro_spk_boost_event,
Laxminath Kasam0c857002018-07-17 23:47:17 +05302199 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2200 SND_SOC_DAPM_POST_PMD),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302201 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 CHAIN", SND_SOC_NOPM, 0, 0,
2202 NULL, 0, wsa_macro_spk_boost_event,
Laxminath Kasam0c857002018-07-17 23:47:17 +05302203 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2204 SND_SOC_DAPM_POST_PMD),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302205
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302206 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 VBAT", SND_SOC_NOPM,
2207 0, 0, wsa_int0_vbat_mix_switch,
2208 ARRAY_SIZE(wsa_int0_vbat_mix_switch),
2209 wsa_macro_enable_vbat,
2210 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2211 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 VBAT", SND_SOC_NOPM,
2212 0, 0, wsa_int1_vbat_mix_switch,
2213 ARRAY_SIZE(wsa_int1_vbat_mix_switch),
2214 wsa_macro_enable_vbat,
2215 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2216
Laxminath Kasam243e2752018-04-12 00:40:19 +05302217 SND_SOC_DAPM_INPUT("VIINPUT_WSA"),
2218
2219 SND_SOC_DAPM_OUTPUT("WSA_SPK1 OUT"),
2220 SND_SOC_DAPM_OUTPUT("WSA_SPK2 OUT"),
2221
2222 SND_SOC_DAPM_SUPPLY_S("WSA_MCLK", 0, SND_SOC_NOPM, 0, 0,
2223 wsa_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2224};
2225
2226static const struct snd_soc_dapm_route wsa_audio_map[] = {
2227 /* VI Feedback */
2228 {"WSA_AIF_VI Mixer", "WSA_SPKR_VI_1", "VIINPUT_WSA"},
2229 {"WSA_AIF_VI Mixer", "WSA_SPKR_VI_2", "VIINPUT_WSA"},
2230 {"WSA AIF_VI", NULL, "WSA_AIF_VI Mixer"},
2231 {"WSA AIF_VI", NULL, "WSA_MCLK"},
2232
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05302233 {"WSA RX_MIX EC0_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
2234 {"WSA RX_MIX EC1_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
2235 {"WSA RX_MIX EC0_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
2236 {"WSA RX_MIX EC1_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
2237 {"WSA AIF_ECHO", NULL, "WSA RX_MIX EC0_MUX"},
2238 {"WSA AIF_ECHO", NULL, "WSA RX_MIX EC1_MUX"},
2239 {"WSA AIF_ECHO", NULL, "WSA_MCLK"},
2240
Laxminath Kasam243e2752018-04-12 00:40:19 +05302241 {"WSA AIF1 PB", NULL, "WSA_MCLK"},
2242 {"WSA AIF_MIX1 PB", NULL, "WSA_MCLK"},
2243
2244 {"WSA RX0 MUX", "AIF1_PB", "WSA AIF1 PB"},
2245 {"WSA RX1 MUX", "AIF1_PB", "WSA AIF1 PB"},
2246 {"WSA RX_MIX0 MUX", "AIF1_PB", "WSA AIF1 PB"},
2247 {"WSA RX_MIX1 MUX", "AIF1_PB", "WSA AIF1 PB"},
2248
2249 {"WSA RX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2250 {"WSA RX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2251 {"WSA RX_MIX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2252 {"WSA RX_MIX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2253
2254 {"WSA RX0", NULL, "WSA RX0 MUX"},
2255 {"WSA RX1", NULL, "WSA RX1 MUX"},
2256 {"WSA RX_MIX0", NULL, "WSA RX_MIX0 MUX"},
2257 {"WSA RX_MIX1", NULL, "WSA RX_MIX1 MUX"},
2258
2259 {"WSA_RX0 INP0", "RX0", "WSA RX0"},
2260 {"WSA_RX0 INP0", "RX1", "WSA RX1"},
2261 {"WSA_RX0 INP0", "RX_MIX0", "WSA RX_MIX0"},
2262 {"WSA_RX0 INP0", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302263 {"WSA_RX0 INP0", "DEC0", "WSA_TX DEC0_INP"},
2264 {"WSA_RX0 INP0", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302265 {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP0"},
2266
2267 {"WSA_RX0 INP1", "RX0", "WSA RX0"},
2268 {"WSA_RX0 INP1", "RX1", "WSA RX1"},
2269 {"WSA_RX0 INP1", "RX_MIX0", "WSA RX_MIX0"},
2270 {"WSA_RX0 INP1", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302271 {"WSA_RX0 INP1", "DEC0", "WSA_TX DEC0_INP"},
2272 {"WSA_RX0 INP1", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302273 {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP1"},
2274
2275 {"WSA_RX0 INP2", "RX0", "WSA RX0"},
2276 {"WSA_RX0 INP2", "RX1", "WSA RX1"},
2277 {"WSA_RX0 INP2", "RX_MIX0", "WSA RX_MIX0"},
2278 {"WSA_RX0 INP2", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302279 {"WSA_RX0 INP2", "DEC0", "WSA_TX DEC0_INP"},
2280 {"WSA_RX0 INP2", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302281 {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP2"},
2282
2283 {"WSA_RX0 MIX INP", "RX0", "WSA RX0"},
2284 {"WSA_RX0 MIX INP", "RX1", "WSA RX1"},
2285 {"WSA_RX0 MIX INP", "RX_MIX0", "WSA RX_MIX0"},
2286 {"WSA_RX0 MIX INP", "RX_MIX1", "WSA RX_MIX1"},
2287 {"WSA_RX INT0 SEC MIX", NULL, "WSA_RX0 MIX INP"},
2288
2289 {"WSA_RX INT0 SEC MIX", NULL, "WSA_RX INT0 MIX"},
2290 {"WSA_RX INT0 INTERP", NULL, "WSA_RX INT0 SEC MIX"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302291 {"WSA_RX0 INT0 SIDETONE MIX", "SRC0", "WSA SRC0_INP"},
2292 {"WSA_RX INT0 INTERP", NULL, "WSA_RX0 INT0 SIDETONE MIX"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302293 {"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 INTERP"},
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302294
2295 {"WSA_RX INT0 VBAT", "WSA RX0 VBAT Enable", "WSA_RX INT0 INTERP"},
2296 {"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 VBAT"},
2297
Laxminath Kasam243e2752018-04-12 00:40:19 +05302298 {"WSA_SPK1 OUT", NULL, "WSA_RX INT0 CHAIN"},
Laxminath Kasamfc281ad2018-08-06 20:19:40 +05302299 {"WSA_SPK1 OUT", NULL, "WSA_MCLK"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302300
2301 {"WSA_RX1 INP0", "RX0", "WSA RX0"},
2302 {"WSA_RX1 INP0", "RX1", "WSA RX1"},
2303 {"WSA_RX1 INP0", "RX_MIX0", "WSA RX_MIX0"},
2304 {"WSA_RX1 INP0", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302305 {"WSA_RX1 INP0", "DEC0", "WSA_TX DEC0_INP"},
2306 {"WSA_RX1 INP0", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302307 {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP0"},
2308
2309 {"WSA_RX1 INP1", "RX0", "WSA RX0"},
2310 {"WSA_RX1 INP1", "RX1", "WSA RX1"},
2311 {"WSA_RX1 INP1", "RX_MIX0", "WSA RX_MIX0"},
2312 {"WSA_RX1 INP1", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302313 {"WSA_RX1 INP1", "DEC0", "WSA_TX DEC0_INP"},
2314 {"WSA_RX1 INP1", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302315 {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP1"},
2316
2317 {"WSA_RX1 INP2", "RX0", "WSA RX0"},
2318 {"WSA_RX1 INP2", "RX1", "WSA RX1"},
2319 {"WSA_RX1 INP2", "RX_MIX0", "WSA RX_MIX0"},
2320 {"WSA_RX1 INP2", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302321 {"WSA_RX1 INP2", "DEC0", "WSA_TX DEC0_INP"},
2322 {"WSA_RX1 INP2", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302323 {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP2"},
2324
2325 {"WSA_RX1 MIX INP", "RX0", "WSA RX0"},
2326 {"WSA_RX1 MIX INP", "RX1", "WSA RX1"},
2327 {"WSA_RX1 MIX INP", "RX_MIX0", "WSA RX_MIX0"},
2328 {"WSA_RX1 MIX INP", "RX_MIX1", "WSA RX_MIX1"},
2329 {"WSA_RX INT1 SEC MIX", NULL, "WSA_RX1 MIX INP"},
2330
2331 {"WSA_RX INT1 SEC MIX", NULL, "WSA_RX INT1 MIX"},
2332 {"WSA_RX INT1 INTERP", NULL, "WSA_RX INT1 SEC MIX"},
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302333
2334 {"WSA_RX INT1 VBAT", "WSA RX1 VBAT Enable", "WSA_RX INT1 INTERP"},
2335 {"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 VBAT"},
2336
Laxminath Kasam243e2752018-04-12 00:40:19 +05302337 {"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 INTERP"},
2338 {"WSA_SPK2 OUT", NULL, "WSA_RX INT1 CHAIN"},
Laxminath Kasamfc281ad2018-08-06 20:19:40 +05302339 {"WSA_SPK2 OUT", NULL, "WSA_MCLK"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302340};
2341
2342static const struct wsa_macro_reg_mask_val wsa_macro_reg_init[] = {
2343 {BOLERO_CDC_WSA_BOOST0_BOOST_CFG1, 0x3F, 0x12},
2344 {BOLERO_CDC_WSA_BOOST0_BOOST_CFG2, 0x1C, 0x08},
2345 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x1E, 0x18},
2346 {BOLERO_CDC_WSA_BOOST1_BOOST_CFG1, 0x3F, 0x12},
2347 {BOLERO_CDC_WSA_BOOST1_BOOST_CFG2, 0x1C, 0x08},
2348 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x1E, 0x18},
2349 {BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x70, 0x58},
2350 {BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x70, 0x58},
2351 {BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08},
2352 {BOLERO_CDC_WSA_RX1_RX_PATH_CFG1, 0x08, 0x08},
2353 {BOLERO_CDC_WSA_TOP_TOP_CFG1, 0x02, 0x02},
2354 {BOLERO_CDC_WSA_TOP_TOP_CFG1, 0x01, 0x01},
2355 {BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2356 {BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2357 {BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2358 {BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2359 {BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80},
2360 {BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x80},
2361 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01},
2362 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01},
2363 {BOLERO_CDC_WSA_RX0_RX_PATH_CFG0, 0x01, 0x01},
2364 {BOLERO_CDC_WSA_RX1_RX_PATH_CFG0, 0x01, 0x01},
2365 {BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CFG, 0x01, 0x01},
2366 {BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CFG, 0x01, 0x01},
2367};
2368
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302369static void wsa_macro_init_bcl_pmic_reg(struct snd_soc_codec *codec)
2370{
2371 struct device *wsa_dev = NULL;
2372 struct wsa_macro_priv *wsa_priv = NULL;
2373
2374 if (!codec) {
2375 pr_err("%s: NULL codec pointer!\n", __func__);
2376 return;
2377 }
2378
2379 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
2380 return;
2381
2382 switch (wsa_priv->bcl_pmic_params.id) {
2383 case 0:
2384 /* Enable ID0 to listen to respective PMIC group interrupts */
2385 snd_soc_update_bits(codec,
2386 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x02, 0x02);
2387 /* Update MC_SID0 */
2388 snd_soc_update_bits(codec,
2389 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1, 0x0F,
2390 wsa_priv->bcl_pmic_params.sid);
2391 /* Update MC_PPID0 */
2392 snd_soc_update_bits(codec,
2393 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2, 0xFF,
2394 wsa_priv->bcl_pmic_params.ppid);
2395 break;
2396 case 1:
2397 /* Enable ID1 to listen to respective PMIC group interrupts */
2398 snd_soc_update_bits(codec,
2399 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x01, 0x01);
2400 /* Update MC_SID1 */
2401 snd_soc_update_bits(codec,
2402 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3, 0x0F,
2403 wsa_priv->bcl_pmic_params.sid);
2404 /* Update MC_PPID1 */
2405 snd_soc_update_bits(codec,
2406 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4, 0xFF,
2407 wsa_priv->bcl_pmic_params.ppid);
2408 break;
2409 default:
2410 dev_err(wsa_dev, "%s: PMIC ID is invalid %d\n",
2411 __func__, wsa_priv->bcl_pmic_params.id);
2412 break;
2413 }
2414}
2415
Laxminath Kasam243e2752018-04-12 00:40:19 +05302416static void wsa_macro_init_reg(struct snd_soc_codec *codec)
2417{
2418 int i;
2419
2420 for (i = 0; i < ARRAY_SIZE(wsa_macro_reg_init); i++)
2421 snd_soc_update_bits(codec,
2422 wsa_macro_reg_init[i].reg,
2423 wsa_macro_reg_init[i].mask,
2424 wsa_macro_reg_init[i].val);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302425
2426 wsa_macro_init_bcl_pmic_reg(codec);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302427}
2428
2429static int wsa_swrm_clock(void *handle, bool enable)
2430{
2431 struct wsa_macro_priv *wsa_priv = (struct wsa_macro_priv *) handle;
2432 struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
2433
2434 mutex_lock(&wsa_priv->swr_clk_lock);
2435
2436 dev_dbg(wsa_priv->dev, "%s: swrm clock %s\n",
2437 __func__, (enable ? "enable" : "disable"));
2438 if (enable) {
2439 wsa_priv->swr_clk_users++;
2440 if (wsa_priv->swr_clk_users == 1) {
2441 wsa_macro_mclk_enable(wsa_priv, 1, true);
2442 regmap_update_bits(regmap,
2443 BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
2444 0x01, 0x01);
2445 regmap_update_bits(regmap,
2446 BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
2447 0x1C, 0x0C);
2448 msm_cdc_pinctrl_select_active_state(
2449 wsa_priv->wsa_swr_gpio_p);
2450 }
2451 } else {
2452 wsa_priv->swr_clk_users--;
2453 if (wsa_priv->swr_clk_users == 0) {
2454 regmap_update_bits(regmap,
2455 BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
2456 0x01, 0x00);
2457 msm_cdc_pinctrl_select_sleep_state(
2458 wsa_priv->wsa_swr_gpio_p);
2459 wsa_macro_mclk_enable(wsa_priv, 0, true);
2460 }
2461 }
2462 dev_dbg(wsa_priv->dev, "%s: swrm clock users %d\n",
2463 __func__, wsa_priv->swr_clk_users);
2464 mutex_unlock(&wsa_priv->swr_clk_lock);
2465 return 0;
2466}
2467
2468static int wsa_macro_init(struct snd_soc_codec *codec)
2469{
2470 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
2471 int ret;
2472 struct device *wsa_dev = NULL;
2473 struct wsa_macro_priv *wsa_priv = NULL;
2474
2475 wsa_dev = bolero_get_device_ptr(codec->dev, WSA_MACRO);
2476 if (!wsa_dev) {
2477 dev_err(codec->dev,
2478 "%s: null device for macro!\n", __func__);
2479 return -EINVAL;
2480 }
2481 wsa_priv = dev_get_drvdata(wsa_dev);
2482 if (!wsa_priv) {
2483 dev_err(codec->dev,
2484 "%s: priv is null for macro!\n", __func__);
2485 return -EINVAL;
2486 }
2487
2488 ret = snd_soc_dapm_new_controls(dapm, wsa_macro_dapm_widgets,
2489 ARRAY_SIZE(wsa_macro_dapm_widgets));
2490 if (ret < 0) {
2491 dev_err(wsa_dev, "%s: Failed to add controls\n", __func__);
2492 return ret;
2493 }
2494
2495 ret = snd_soc_dapm_add_routes(dapm, wsa_audio_map,
2496 ARRAY_SIZE(wsa_audio_map));
2497 if (ret < 0) {
2498 dev_err(wsa_dev, "%s: Failed to add routes\n", __func__);
2499 return ret;
2500 }
2501
2502 ret = snd_soc_dapm_new_widgets(dapm->card);
2503 if (ret < 0) {
2504 dev_err(wsa_dev, "%s: Failed to add widgets\n", __func__);
2505 return ret;
2506 }
2507
2508 ret = snd_soc_add_codec_controls(codec, wsa_macro_snd_controls,
2509 ARRAY_SIZE(wsa_macro_snd_controls));
2510 if (ret < 0) {
2511 dev_err(wsa_dev, "%s: Failed to add snd_ctls\n", __func__);
2512 return ret;
2513 }
2514
2515 wsa_priv->codec = codec;
Laxminath Kasam21c8b222018-06-21 18:47:22 +05302516 wsa_priv->spkr_gain_offset = WSA_MACRO_GAIN_OFFSET_0_DB;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302517 wsa_macro_init_reg(codec);
2518
2519 return 0;
2520}
2521
2522static int wsa_macro_deinit(struct snd_soc_codec *codec)
2523{
2524 struct device *wsa_dev = NULL;
2525 struct wsa_macro_priv *wsa_priv = NULL;
2526
2527 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
2528 return -EINVAL;
2529
2530 wsa_priv->codec = NULL;
2531
2532 return 0;
2533}
2534
2535static void wsa_macro_add_child_devices(struct work_struct *work)
2536{
2537 struct wsa_macro_priv *wsa_priv;
2538 struct platform_device *pdev;
2539 struct device_node *node;
2540 struct wsa_macro_swr_ctrl_data *swr_ctrl_data = NULL, *temp;
2541 int ret;
2542 u16 count = 0, ctrl_num = 0;
2543 struct wsa_macro_swr_ctrl_platform_data *platdata;
2544 char plat_dev_name[WSA_MACRO_SWR_STRING_LEN];
2545
2546 wsa_priv = container_of(work, struct wsa_macro_priv,
2547 wsa_macro_add_child_devices_work);
2548 if (!wsa_priv) {
2549 pr_err("%s: Memory for wsa_priv does not exist\n",
2550 __func__);
2551 return;
2552 }
Laxminath Kasam21c8b222018-06-21 18:47:22 +05302553 if (!wsa_priv->dev || !wsa_priv->dev->of_node) {
Laxminath Kasam243e2752018-04-12 00:40:19 +05302554 dev_err(wsa_priv->dev,
2555 "%s: DT node for wsa_priv does not exist\n", __func__);
2556 return;
2557 }
2558
2559 platdata = &wsa_priv->swr_plat_data;
2560 wsa_priv->child_count = 0;
2561
2562 for_each_available_child_of_node(wsa_priv->dev->of_node, node) {
2563 if (strnstr(node->name, "wsa_swr_master",
2564 strlen("wsa_swr_master")) != NULL)
2565 strlcpy(plat_dev_name, "wsa_swr_ctrl",
2566 (WSA_MACRO_SWR_STRING_LEN - 1));
2567 else if (strnstr(node->name, "msm_cdc_pinctrl",
2568 strlen("msm_cdc_pinctrl")) != NULL)
2569 strlcpy(plat_dev_name, node->name,
2570 (WSA_MACRO_SWR_STRING_LEN - 1));
2571 else
2572 continue;
2573
2574 pdev = platform_device_alloc(plat_dev_name, -1);
2575 if (!pdev) {
2576 dev_err(wsa_priv->dev, "%s: pdev memory alloc failed\n",
2577 __func__);
2578 ret = -ENOMEM;
2579 goto err;
2580 }
2581 pdev->dev.parent = wsa_priv->dev;
2582 pdev->dev.of_node = node;
2583
2584 if (strnstr(node->name, "wsa_swr_master",
2585 strlen("wsa_swr_master")) != NULL) {
2586 ret = platform_device_add_data(pdev, platdata,
2587 sizeof(*platdata));
2588 if (ret) {
2589 dev_err(&pdev->dev,
2590 "%s: cannot add plat data ctrl:%d\n",
2591 __func__, ctrl_num);
2592 goto fail_pdev_add;
2593 }
2594 }
2595
2596 ret = platform_device_add(pdev);
2597 if (ret) {
2598 dev_err(&pdev->dev,
2599 "%s: Cannot add platform device\n",
2600 __func__);
2601 goto fail_pdev_add;
2602 }
2603
2604 if (!strcmp(node->name, "wsa_swr_master")) {
2605 temp = krealloc(swr_ctrl_data,
2606 (ctrl_num + 1) * sizeof(
2607 struct wsa_macro_swr_ctrl_data),
2608 GFP_KERNEL);
2609 if (!temp) {
2610 dev_err(&pdev->dev, "out of memory\n");
2611 ret = -ENOMEM;
2612 goto err;
2613 }
2614 swr_ctrl_data = temp;
2615 swr_ctrl_data[ctrl_num].wsa_swr_pdev = pdev;
2616 ctrl_num++;
2617 dev_dbg(&pdev->dev,
2618 "%s: Added soundwire ctrl device(s)\n",
2619 __func__);
2620 wsa_priv->swr_ctrl_data = swr_ctrl_data;
2621 }
2622 if (wsa_priv->child_count < WSA_MACRO_CHILD_DEVICES_MAX)
2623 wsa_priv->pdev_child_devices[
2624 wsa_priv->child_count++] = pdev;
2625 else
2626 goto err;
2627 }
2628
2629 return;
2630fail_pdev_add:
2631 for (count = 0; count < wsa_priv->child_count; count++)
2632 platform_device_put(wsa_priv->pdev_child_devices[count]);
2633err:
2634 return;
2635}
2636
2637static void wsa_macro_init_ops(struct macro_ops *ops,
2638 char __iomem *wsa_io_base)
2639{
2640 memset(ops, 0, sizeof(struct macro_ops));
2641 ops->init = wsa_macro_init;
2642 ops->exit = wsa_macro_deinit;
2643 ops->io_base = wsa_io_base;
2644 ops->dai_ptr = wsa_macro_dai;
2645 ops->num_dais = ARRAY_SIZE(wsa_macro_dai);
2646 ops->mclk_fn = wsa_macro_mclk_ctrl;
Laxminath Kasamfb0d6832018-09-22 01:49:52 +05302647 ops->event_handler = wsa_macro_event_handler;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302648}
2649
2650static int wsa_macro_probe(struct platform_device *pdev)
2651{
2652 struct macro_ops ops;
2653 struct wsa_macro_priv *wsa_priv;
2654 u32 wsa_base_addr;
2655 char __iomem *wsa_io_base;
2656 int ret = 0;
2657 struct clk *wsa_core_clk, *wsa_npl_clk;
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302658 u8 bcl_pmic_params[3];
Laxminath Kasam243e2752018-04-12 00:40:19 +05302659
2660 wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct wsa_macro_priv),
2661 GFP_KERNEL);
2662 if (!wsa_priv)
2663 return -ENOMEM;
2664
2665 wsa_priv->dev = &pdev->dev;
2666 ret = of_property_read_u32(pdev->dev.of_node, "reg",
2667 &wsa_base_addr);
2668 if (ret) {
2669 dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
2670 __func__, "reg");
2671 return ret;
2672 }
2673 wsa_priv->wsa_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
2674 "qcom,wsa-swr-gpios", 0);
2675 if (!wsa_priv->wsa_swr_gpio_p) {
2676 dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
2677 __func__);
2678 return -EINVAL;
2679 }
2680 wsa_io_base = devm_ioremap(&pdev->dev,
2681 wsa_base_addr, WSA_MACRO_MAX_OFFSET);
2682 if (!wsa_io_base) {
2683 dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
2684 return -EINVAL;
2685 }
2686 wsa_priv->wsa_io_base = wsa_io_base;
2687 INIT_WORK(&wsa_priv->wsa_macro_add_child_devices_work,
2688 wsa_macro_add_child_devices);
2689 wsa_priv->swr_plat_data.handle = (void *) wsa_priv;
2690 wsa_priv->swr_plat_data.read = NULL;
2691 wsa_priv->swr_plat_data.write = NULL;
2692 wsa_priv->swr_plat_data.bulk_write = NULL;
2693 wsa_priv->swr_plat_data.clk = wsa_swrm_clock;
2694 wsa_priv->swr_plat_data.handle_irq = NULL;
2695
2696 /* Register MCLK for wsa macro */
2697 wsa_core_clk = devm_clk_get(&pdev->dev, "wsa_core_clk");
2698 if (IS_ERR(wsa_core_clk)) {
Ramprasad Katkamf83acfb2018-08-11 23:28:57 +05302699 ret = PTR_ERR(wsa_core_clk);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302700 dev_err(&pdev->dev, "%s: clk get %s failed\n",
2701 __func__, "wsa_core_clk");
Ramprasad Katkamf83acfb2018-08-11 23:28:57 +05302702 return ret;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302703 }
2704 wsa_priv->wsa_core_clk = wsa_core_clk;
2705 /* Register npl clk for soundwire */
2706 wsa_npl_clk = devm_clk_get(&pdev->dev, "wsa_npl_clk");
2707 if (IS_ERR(wsa_npl_clk)) {
Ramprasad Katkamf83acfb2018-08-11 23:28:57 +05302708 ret = PTR_ERR(wsa_npl_clk);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302709 dev_err(&pdev->dev, "%s: clk get %s failed\n",
2710 __func__, "wsa_npl_clk");
Ramprasad Katkamf83acfb2018-08-11 23:28:57 +05302711 return ret;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302712 }
2713 wsa_priv->wsa_npl_clk = wsa_npl_clk;
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302714
2715 ret = of_property_read_u8_array(pdev->dev.of_node,
2716 "qcom,wsa-bcl-pmic-params", bcl_pmic_params,
2717 sizeof(bcl_pmic_params));
2718 if (ret) {
2719 dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
2720 __func__, "qcom,wsa-bcl-pmic-params");
2721 } else {
2722 wsa_priv->bcl_pmic_params.id = bcl_pmic_params[0];
2723 wsa_priv->bcl_pmic_params.sid = bcl_pmic_params[1];
2724 wsa_priv->bcl_pmic_params.ppid = bcl_pmic_params[2];
2725 }
2726
Laxminath Kasam243e2752018-04-12 00:40:19 +05302727 dev_set_drvdata(&pdev->dev, wsa_priv);
2728 mutex_init(&wsa_priv->mclk_lock);
2729 mutex_init(&wsa_priv->swr_clk_lock);
2730 wsa_macro_init_ops(&ops, wsa_io_base);
2731 ret = bolero_register_macro(&pdev->dev, WSA_MACRO, &ops);
2732 if (ret < 0) {
2733 dev_err(&pdev->dev, "%s: register macro failed\n", __func__);
2734 goto reg_macro_fail;
2735 }
2736 schedule_work(&wsa_priv->wsa_macro_add_child_devices_work);
2737 return ret;
2738reg_macro_fail:
2739 mutex_destroy(&wsa_priv->mclk_lock);
2740 mutex_destroy(&wsa_priv->swr_clk_lock);
2741 return ret;
2742}
2743
2744static int wsa_macro_remove(struct platform_device *pdev)
2745{
2746 struct wsa_macro_priv *wsa_priv;
2747 u16 count = 0;
2748
2749 wsa_priv = dev_get_drvdata(&pdev->dev);
2750
2751 if (!wsa_priv)
2752 return -EINVAL;
2753
2754 for (count = 0; count < wsa_priv->child_count &&
2755 count < WSA_MACRO_CHILD_DEVICES_MAX; count++)
2756 platform_device_unregister(wsa_priv->pdev_child_devices[count]);
2757
2758 bolero_unregister_macro(&pdev->dev, WSA_MACRO);
2759 mutex_destroy(&wsa_priv->mclk_lock);
2760 mutex_destroy(&wsa_priv->swr_clk_lock);
2761 return 0;
2762}
2763
2764static const struct of_device_id wsa_macro_dt_match[] = {
2765 {.compatible = "qcom,wsa-macro"},
2766 {}
2767};
2768
2769static struct platform_driver wsa_macro_driver = {
2770 .driver = {
2771 .name = "wsa_macro",
2772 .owner = THIS_MODULE,
2773 .of_match_table = wsa_macro_dt_match,
2774 },
2775 .probe = wsa_macro_probe,
2776 .remove = wsa_macro_remove,
2777};
2778
2779module_platform_driver(wsa_macro_driver);
2780
2781MODULE_DESCRIPTION("WSA macro driver");
2782MODULE_LICENSE("GPL v2");