blob: 2cd1b4360e4685369c6746e8f70d49406a6d4d44 [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
Tanya Dixitab8eba82018-10-05 15:07:37 +0530759 if (regmap == NULL) {
760 dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
761 return -EINVAL;
762 }
763
Laxminath Kasam243e2752018-04-12 00:40:19 +0530764 dev_dbg(wsa_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
765 __func__, mclk_enable, dapm, wsa_priv->wsa_mclk_users);
766
767 mutex_lock(&wsa_priv->mclk_lock);
768 if (mclk_enable) {
Aditya Bavanaric496ed22018-11-16 15:50:40 +0530769 if (wsa_priv->wsa_mclk_users == 0) {
Laxminath Kasam243e2752018-04-12 00:40:19 +0530770 ret = bolero_request_clock(wsa_priv->dev,
771 WSA_MACRO, MCLK_MUX0, true);
772 if (ret < 0) {
773 dev_err(wsa_priv->dev,
774 "%s: wsa request clock enable failed\n",
775 __func__);
776 goto exit;
777 }
778 regcache_mark_dirty(regmap);
779 regcache_sync_region(regmap,
780 WSA_START_OFFSET,
781 WSA_MAX_OFFSET);
782 /* 9.6MHz MCLK, set value 0x00 if other frequency */
783 regmap_update_bits(regmap,
784 BOLERO_CDC_WSA_TOP_FREQ_MCLK, 0x01, 0x01);
785 regmap_update_bits(regmap,
786 BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL,
787 0x01, 0x01);
788 regmap_update_bits(regmap,
789 BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
790 0x01, 0x01);
791 }
Aditya Bavanaric496ed22018-11-16 15:50:40 +0530792 wsa_priv->wsa_mclk_users++;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530793 } else {
Aditya Bavanaric496ed22018-11-16 15:50:40 +0530794 if (wsa_priv->wsa_mclk_users <= 0) {
795 dev_err(wsa_priv->dev, "%s: clock already disabled\n",
796 __func__);
797 wsa_priv->wsa_mclk_users = 0;
798 goto exit;
799 }
Laxminath Kasam243e2752018-04-12 00:40:19 +0530800 wsa_priv->wsa_mclk_users--;
801 if (wsa_priv->wsa_mclk_users == 0) {
802 regmap_update_bits(regmap,
803 BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
804 0x01, 0x00);
805 regmap_update_bits(regmap,
806 BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL,
807 0x01, 0x00);
808 bolero_request_clock(wsa_priv->dev,
809 WSA_MACRO, MCLK_MUX0, false);
810 }
811 }
812exit:
813 mutex_unlock(&wsa_priv->mclk_lock);
814 return ret;
815}
816
817static int wsa_macro_mclk_event(struct snd_soc_dapm_widget *w,
818 struct snd_kcontrol *kcontrol, int event)
819{
820 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
821 int ret = 0;
822 struct device *wsa_dev = NULL;
823 struct wsa_macro_priv *wsa_priv = NULL;
824
825 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
826 return -EINVAL;
827
828 dev_dbg(wsa_dev, "%s: event = %d\n", __func__, event);
829 switch (event) {
830 case SND_SOC_DAPM_PRE_PMU:
831 ret = wsa_macro_mclk_enable(wsa_priv, 1, true);
832 break;
833 case SND_SOC_DAPM_POST_PMD:
834 wsa_macro_mclk_enable(wsa_priv, 0, true);
835 break;
836 default:
837 dev_err(wsa_priv->dev,
838 "%s: invalid DAPM event %d\n", __func__, event);
839 ret = -EINVAL;
840 }
841 return ret;
842}
843
844static int wsa_macro_mclk_ctrl(struct device *dev, bool enable)
845{
846 struct wsa_macro_priv *wsa_priv = dev_get_drvdata(dev);
847 int ret = 0;
848
849 if (!wsa_priv)
850 return -EINVAL;
851
852 if (enable) {
853 ret = clk_prepare_enable(wsa_priv->wsa_core_clk);
854 if (ret < 0) {
855 dev_err(dev, "%s:wsa mclk enable failed\n", __func__);
856 goto exit;
857 }
858 ret = clk_prepare_enable(wsa_priv->wsa_npl_clk);
859 if (ret < 0) {
860 dev_err(dev, "%s:wsa npl_clk enable failed\n",
861 __func__);
862 clk_disable_unprepare(wsa_priv->wsa_core_clk);
863 goto exit;
864 }
865 } else {
866 clk_disable_unprepare(wsa_priv->wsa_npl_clk);
867 clk_disable_unprepare(wsa_priv->wsa_core_clk);
868 }
869exit:
870 return ret;
871}
872
Laxminath Kasamfb0d6832018-09-22 01:49:52 +0530873static int wsa_macro_event_handler(struct snd_soc_codec *codec, u16 event,
874 u32 data)
875{
876 struct device *wsa_dev = NULL;
877 struct wsa_macro_priv *wsa_priv = NULL;
878
879 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
880 return -EINVAL;
881
882 switch (event) {
883 case BOLERO_MACRO_EVT_SSR_DOWN:
884 swrm_wcd_notify(
885 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
886 SWR_DEVICE_SSR_DOWN, NULL);
887 swrm_wcd_notify(
888 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
889 SWR_DEVICE_DOWN, NULL);
890 break;
891 case BOLERO_MACRO_EVT_SSR_UP:
892 swrm_wcd_notify(
893 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
894 SWR_DEVICE_SSR_UP, NULL);
895 break;
896 }
897 return 0;
898}
899
Laxminath Kasam243e2752018-04-12 00:40:19 +0530900static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w,
901 struct snd_kcontrol *kcontrol,
902 int event)
903{
904 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
905 struct device *wsa_dev = NULL;
906 struct wsa_macro_priv *wsa_priv = NULL;
907
908 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
909 return -EINVAL;
910
911 switch (event) {
912 case SND_SOC_DAPM_POST_PMU:
913 if (test_bit(WSA_MACRO_TX0,
914 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
915 dev_dbg(wsa_dev, "%s: spkr1 enabled\n", __func__);
916 /* Enable V&I sensing */
917 snd_soc_update_bits(codec,
918 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
919 0x20, 0x20);
920 snd_soc_update_bits(codec,
921 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
922 0x20, 0x20);
923 snd_soc_update_bits(codec,
924 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
925 0x0F, 0x00);
926 snd_soc_update_bits(codec,
927 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
928 0x0F, 0x00);
929 snd_soc_update_bits(codec,
930 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
931 0x10, 0x10);
932 snd_soc_update_bits(codec,
933 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
934 0x10, 0x10);
935 snd_soc_update_bits(codec,
936 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
937 0x20, 0x00);
938 snd_soc_update_bits(codec,
939 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
940 0x20, 0x00);
941 }
942 if (test_bit(WSA_MACRO_TX1,
943 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
944 dev_dbg(wsa_dev, "%s: spkr2 enabled\n", __func__);
945 /* Enable V&I sensing */
946 snd_soc_update_bits(codec,
947 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
948 0x20, 0x20);
949 snd_soc_update_bits(codec,
950 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
951 0x20, 0x20);
952 snd_soc_update_bits(codec,
953 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
954 0x0F, 0x00);
955 snd_soc_update_bits(codec,
956 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
957 0x0F, 0x00);
958 snd_soc_update_bits(codec,
959 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
960 0x10, 0x10);
961 snd_soc_update_bits(codec,
962 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
963 0x10, 0x10);
964 snd_soc_update_bits(codec,
965 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
966 0x20, 0x00);
967 snd_soc_update_bits(codec,
968 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
969 0x20, 0x00);
970 }
971 break;
972 case SND_SOC_DAPM_POST_PMD:
973 if (test_bit(WSA_MACRO_TX0,
974 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
975 /* Disable V&I sensing */
976 snd_soc_update_bits(codec,
977 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
978 0x20, 0x20);
979 snd_soc_update_bits(codec,
980 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
981 0x20, 0x20);
982 dev_dbg(wsa_dev, "%s: spkr1 disabled\n", __func__);
983 snd_soc_update_bits(codec,
984 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
985 0x10, 0x00);
986 snd_soc_update_bits(codec,
987 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
988 0x10, 0x00);
989 }
990 if (test_bit(WSA_MACRO_TX1,
991 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
992 /* Disable V&I sensing */
993 dev_dbg(wsa_dev, "%s: spkr2 disabled\n", __func__);
994 snd_soc_update_bits(codec,
995 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
996 0x20, 0x20);
997 snd_soc_update_bits(codec,
998 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
999 0x20, 0x20);
1000 snd_soc_update_bits(codec,
1001 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
1002 0x10, 0x00);
1003 snd_soc_update_bits(codec,
1004 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
1005 0x10, 0x00);
1006 }
1007 break;
1008 }
1009
1010 return 0;
1011}
1012
1013static int wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w,
1014 struct snd_kcontrol *kcontrol, int event)
1015{
1016 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1017 u16 gain_reg;
1018 int offset_val = 0;
1019 int val = 0;
1020
1021 dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
1022
1023 switch (w->reg) {
1024 case BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL:
1025 gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_MIX_CTL;
1026 break;
1027 case BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL:
1028 gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_MIX_CTL;
1029 break;
1030 default:
1031 dev_err(codec->dev, "%s: No gain register avail for %s\n",
1032 __func__, w->name);
1033 return 0;
1034 }
1035
1036 switch (event) {
1037 case SND_SOC_DAPM_POST_PMU:
1038 val = snd_soc_read(codec, gain_reg);
1039 val += offset_val;
1040 snd_soc_write(codec, gain_reg, val);
1041 break;
1042 case SND_SOC_DAPM_POST_PMD:
1043 break;
1044 }
1045
1046 return 0;
1047}
1048
1049static void wsa_macro_hd2_control(struct snd_soc_codec *codec,
1050 u16 reg, int event)
1051{
1052 u16 hd2_scale_reg;
1053 u16 hd2_enable_reg = 0;
1054
1055 if (reg == BOLERO_CDC_WSA_RX0_RX_PATH_CTL) {
1056 hd2_scale_reg = BOLERO_CDC_WSA_RX0_RX_PATH_SEC3;
1057 hd2_enable_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG0;
1058 }
1059 if (reg == BOLERO_CDC_WSA_RX1_RX_PATH_CTL) {
1060 hd2_scale_reg = BOLERO_CDC_WSA_RX1_RX_PATH_SEC3;
1061 hd2_enable_reg = BOLERO_CDC_WSA_RX1_RX_PATH_CFG0;
1062 }
1063
1064 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
1065 snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x10);
1066 snd_soc_update_bits(codec, hd2_scale_reg, 0x03, 0x01);
1067 snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x04);
1068 }
1069
1070 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
1071 snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x00);
1072 snd_soc_update_bits(codec, hd2_scale_reg, 0x03, 0x00);
1073 snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x00);
1074 }
1075}
1076
1077static int wsa_macro_enable_swr(struct snd_soc_dapm_widget *w,
1078 struct snd_kcontrol *kcontrol, int event)
1079{
1080 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1081 int ch_cnt;
1082 struct device *wsa_dev = NULL;
1083 struct wsa_macro_priv *wsa_priv = NULL;
1084
1085 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1086 return -EINVAL;
1087
1088 switch (event) {
1089 case SND_SOC_DAPM_PRE_PMU:
1090 if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) &&
1091 !wsa_priv->rx_0_count)
1092 wsa_priv->rx_0_count++;
1093 if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) &&
1094 !wsa_priv->rx_1_count)
1095 wsa_priv->rx_1_count++;
1096 ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
1097
1098 swrm_wcd_notify(
1099 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
1100 SWR_DEVICE_UP, NULL);
1101 swrm_wcd_notify(
1102 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
1103 SWR_SET_NUM_RX_CH, &ch_cnt);
1104 break;
1105 case SND_SOC_DAPM_POST_PMD:
1106 if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) &&
1107 wsa_priv->rx_0_count)
1108 wsa_priv->rx_0_count--;
1109 if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) &&
1110 wsa_priv->rx_1_count)
1111 wsa_priv->rx_1_count--;
1112 ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
1113
1114 swrm_wcd_notify(
1115 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
1116 SWR_SET_NUM_RX_CH, &ch_cnt);
1117 break;
1118 }
1119 dev_dbg(wsa_priv->dev, "%s: current swr ch cnt: %d\n",
1120 __func__, wsa_priv->rx_0_count + wsa_priv->rx_1_count);
1121
1122 return 0;
1123}
1124
1125static int wsa_macro_config_compander(struct snd_soc_codec *codec,
1126 int comp, int event)
1127{
1128 u16 comp_ctl0_reg, rx_path_cfg0_reg;
1129 struct device *wsa_dev = NULL;
1130 struct wsa_macro_priv *wsa_priv = NULL;
1131
1132 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1133 return -EINVAL;
1134
1135 dev_dbg(codec->dev, "%s: event %d compander %d, enabled %d\n",
1136 __func__, event, comp + 1, wsa_priv->comp_enabled[comp]);
1137
1138 if (!wsa_priv->comp_enabled[comp])
1139 return 0;
1140
1141 comp_ctl0_reg = BOLERO_CDC_WSA_COMPANDER0_CTL0 +
1142 (comp * WSA_MACRO_RX_COMP_OFFSET);
1143 rx_path_cfg0_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG0 +
1144 (comp * WSA_MACRO_RX_PATH_OFFSET);
1145
1146 if (SND_SOC_DAPM_EVENT_ON(event)) {
1147 /* Enable Compander Clock */
1148 snd_soc_update_bits(codec, comp_ctl0_reg, 0x01, 0x01);
1149 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x02);
1150 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x00);
1151 snd_soc_update_bits(codec, rx_path_cfg0_reg, 0x02, 0x02);
1152 }
1153
1154 if (SND_SOC_DAPM_EVENT_OFF(event)) {
1155 snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x04);
1156 snd_soc_update_bits(codec, rx_path_cfg0_reg, 0x02, 0x00);
1157 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x02);
1158 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x00);
1159 snd_soc_update_bits(codec, comp_ctl0_reg, 0x01, 0x00);
1160 snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x00);
1161 }
1162
1163 return 0;
1164}
1165
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301166static void wsa_macro_enable_softclip_clk(struct snd_soc_codec *codec,
1167 struct wsa_macro_priv *wsa_priv,
1168 int path,
1169 bool enable)
1170{
1171 u16 softclip_clk_reg = BOLERO_CDC_WSA_SOFTCLIP0_CRC +
1172 (path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
1173 u8 softclip_mux_mask = (1 << path);
1174 u8 softclip_mux_value = (1 << path);
1175
1176 dev_dbg(codec->dev, "%s: path %d, enable %d\n",
1177 __func__, path, enable);
1178 if (enable) {
1179 if (wsa_priv->softclip_clk_users[path] == 0) {
1180 snd_soc_update_bits(codec,
1181 softclip_clk_reg, 0x01, 0x01);
1182 snd_soc_update_bits(codec,
1183 BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
1184 softclip_mux_mask, softclip_mux_value);
1185 }
1186 wsa_priv->softclip_clk_users[path]++;
1187 } else {
1188 wsa_priv->softclip_clk_users[path]--;
1189 if (wsa_priv->softclip_clk_users[path] == 0) {
1190 snd_soc_update_bits(codec,
1191 softclip_clk_reg, 0x01, 0x00);
1192 snd_soc_update_bits(codec,
1193 BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
1194 softclip_mux_mask, 0x00);
1195 }
1196 }
1197}
1198
1199static int wsa_macro_config_softclip(struct snd_soc_codec *codec,
1200 int path, int event)
1201{
1202 u16 softclip_ctrl_reg = 0;
1203 struct device *wsa_dev = NULL;
1204 struct wsa_macro_priv *wsa_priv = NULL;
1205 int softclip_path = 0;
1206
1207 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1208 return -EINVAL;
1209
1210 if (path == WSA_MACRO_COMP1)
1211 softclip_path = WSA_MACRO_SOFTCLIP0;
1212 else if (path == WSA_MACRO_COMP2)
1213 softclip_path = WSA_MACRO_SOFTCLIP1;
1214
1215 dev_dbg(codec->dev, "%s: event %d path %d, enabled %d\n",
1216 __func__, event, softclip_path,
1217 wsa_priv->is_softclip_on[softclip_path]);
1218
1219 if (!wsa_priv->is_softclip_on[softclip_path])
1220 return 0;
1221
1222 softclip_ctrl_reg = BOLERO_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL +
1223 (softclip_path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
1224
1225 if (SND_SOC_DAPM_EVENT_ON(event)) {
1226 /* Enable Softclip clock and mux */
1227 wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
1228 true);
1229 /* Enable Softclip control */
1230 snd_soc_update_bits(codec, softclip_ctrl_reg, 0x01, 0x01);
1231 }
1232
1233 if (SND_SOC_DAPM_EVENT_OFF(event)) {
1234 snd_soc_update_bits(codec, softclip_ctrl_reg, 0x01, 0x00);
1235 wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
1236 false);
1237 }
1238
1239 return 0;
1240}
1241
Laxminath Kasam243e2752018-04-12 00:40:19 +05301242static int wsa_macro_interp_get_primary_reg(u16 reg, u16 *ind)
1243{
1244 u16 prim_int_reg = 0;
1245
1246 switch (reg) {
1247 case BOLERO_CDC_WSA_RX0_RX_PATH_CTL:
1248 case BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL:
1249 prim_int_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
1250 *ind = 0;
1251 break;
1252 case BOLERO_CDC_WSA_RX1_RX_PATH_CTL:
1253 case BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL:
1254 prim_int_reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
1255 *ind = 1;
1256 break;
1257 }
1258
1259 return prim_int_reg;
1260}
1261
1262static int wsa_macro_enable_prim_interpolator(
1263 struct snd_soc_codec *codec,
1264 u16 reg, int event)
1265{
1266 u16 prim_int_reg;
1267 u16 ind = 0;
1268 struct device *wsa_dev = NULL;
1269 struct wsa_macro_priv *wsa_priv = NULL;
1270
1271 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1272 return -EINVAL;
1273
1274 prim_int_reg = wsa_macro_interp_get_primary_reg(reg, &ind);
1275
1276 switch (event) {
1277 case SND_SOC_DAPM_PRE_PMU:
1278 wsa_priv->prim_int_users[ind]++;
1279 if (wsa_priv->prim_int_users[ind] == 1) {
1280 snd_soc_update_bits(codec,
1281 prim_int_reg + WSA_MACRO_RX_PATH_CFG3_OFFSET,
1282 0x03, 0x03);
1283 snd_soc_update_bits(codec, prim_int_reg,
1284 0x10, 0x10);
1285 wsa_macro_hd2_control(codec, prim_int_reg, event);
1286 snd_soc_update_bits(codec,
1287 prim_int_reg + WSA_MACRO_RX_PATH_DSMDEM_OFFSET,
1288 0x1, 0x1);
1289 snd_soc_update_bits(codec, prim_int_reg,
1290 1 << 0x5, 1 << 0x5);
1291 }
1292 if ((reg != prim_int_reg) &&
1293 ((snd_soc_read(codec, prim_int_reg)) & 0x10))
1294 snd_soc_update_bits(codec, reg, 0x10, 0x10);
1295 break;
1296 case SND_SOC_DAPM_POST_PMD:
1297 wsa_priv->prim_int_users[ind]--;
1298 if (wsa_priv->prim_int_users[ind] == 0) {
1299 snd_soc_update_bits(codec, prim_int_reg,
1300 1 << 0x5, 0 << 0x5);
1301 snd_soc_update_bits(codec, prim_int_reg,
1302 0x40, 0x40);
1303 snd_soc_update_bits(codec, prim_int_reg,
1304 0x40, 0x00);
1305 wsa_macro_hd2_control(codec, prim_int_reg, event);
1306 }
1307 break;
1308 }
1309
1310 dev_dbg(codec->dev, "%s: primary interpolator: INT%d, users: %d\n",
1311 __func__, ind, wsa_priv->prim_int_users[ind]);
1312 return 0;
1313}
1314
1315static int wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w,
1316 struct snd_kcontrol *kcontrol,
1317 int event)
1318{
1319 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1320 u16 gain_reg;
1321 u16 reg;
1322 int val;
1323 int offset_val = 0;
1324 struct device *wsa_dev = NULL;
1325 struct wsa_macro_priv *wsa_priv = NULL;
1326
1327 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1328 return -EINVAL;
1329
1330 dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
1331
1332 if (!(strcmp(w->name, "WSA_RX INT0 INTERP"))) {
1333 reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
1334 gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_CTL;
1335 } else if (!(strcmp(w->name, "WSA_RX INT1 INTERP"))) {
1336 reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
1337 gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_CTL;
1338 } else {
1339 dev_err(codec->dev, "%s: Interpolator reg not found\n",
1340 __func__);
1341 return -EINVAL;
1342 }
1343
1344 switch (event) {
1345 case SND_SOC_DAPM_PRE_PMU:
1346 /* Reset if needed */
1347 wsa_macro_enable_prim_interpolator(codec, reg, event);
1348 break;
1349 case SND_SOC_DAPM_POST_PMU:
1350 wsa_macro_config_compander(codec, w->shift, event);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301351 wsa_macro_config_softclip(codec, w->shift, event);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301352 /* apply gain after int clk is enabled */
Laxminath Kasam21c8b222018-06-21 18:47:22 +05301353 if ((wsa_priv->spkr_gain_offset ==
1354 WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
Laxminath Kasam243e2752018-04-12 00:40:19 +05301355 (wsa_priv->comp_enabled[WSA_MACRO_COMP1] ||
1356 wsa_priv->comp_enabled[WSA_MACRO_COMP2]) &&
1357 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL ||
1358 gain_reg == BOLERO_CDC_WSA_RX1_RX_VOL_CTL)) {
1359 snd_soc_update_bits(codec, BOLERO_CDC_WSA_RX0_RX_PATH_SEC1,
1360 0x01, 0x01);
1361 snd_soc_update_bits(codec,
1362 BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC0,
1363 0x01, 0x01);
1364 snd_soc_update_bits(codec, BOLERO_CDC_WSA_RX1_RX_PATH_SEC1,
1365 0x01, 0x01);
1366 snd_soc_update_bits(codec,
1367 BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC0,
1368 0x01, 0x01);
1369 offset_val = -2;
1370 }
1371 val = snd_soc_read(codec, gain_reg);
1372 val += offset_val;
1373 snd_soc_write(codec, gain_reg, val);
1374 wsa_macro_config_ear_spkr_gain(codec, wsa_priv,
1375 event, gain_reg);
1376 break;
1377 case SND_SOC_DAPM_POST_PMD:
1378 wsa_macro_config_compander(codec, w->shift, event);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301379 wsa_macro_config_softclip(codec, w->shift, event);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301380 wsa_macro_enable_prim_interpolator(codec, reg, event);
Laxminath Kasam21c8b222018-06-21 18:47:22 +05301381 if ((wsa_priv->spkr_gain_offset ==
1382 WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
Laxminath Kasam243e2752018-04-12 00:40:19 +05301383 (wsa_priv->comp_enabled[WSA_MACRO_COMP1] ||
1384 wsa_priv->comp_enabled[WSA_MACRO_COMP2]) &&
1385 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL ||
1386 gain_reg == BOLERO_CDC_WSA_RX1_RX_VOL_CTL)) {
1387 snd_soc_update_bits(codec, BOLERO_CDC_WSA_RX0_RX_PATH_SEC1,
1388 0x01, 0x00);
1389 snd_soc_update_bits(codec,
1390 BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC0,
1391 0x01, 0x00);
1392 snd_soc_update_bits(codec, BOLERO_CDC_WSA_RX1_RX_PATH_SEC1,
1393 0x01, 0x00);
1394 snd_soc_update_bits(codec,
1395 BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC0,
1396 0x01, 0x00);
1397 offset_val = 2;
1398 val = snd_soc_read(codec, gain_reg);
1399 val += offset_val;
1400 snd_soc_write(codec, gain_reg, val);
1401 }
1402 wsa_macro_config_ear_spkr_gain(codec, wsa_priv,
1403 event, gain_reg);
1404 break;
1405 }
1406
1407 return 0;
1408}
1409
1410static int wsa_macro_config_ear_spkr_gain(struct snd_soc_codec *codec,
1411 struct wsa_macro_priv *wsa_priv,
1412 int event, int gain_reg)
1413{
1414 int comp_gain_offset, val;
1415
1416 switch (wsa_priv->spkr_mode) {
Laxminath Kasam21c8b222018-06-21 18:47:22 +05301417 /* Compander gain in WSA_MACRO_SPKR_MODE1 case is 12 dB */
1418 case WSA_MACRO_SPKR_MODE_1:
Laxminath Kasam243e2752018-04-12 00:40:19 +05301419 comp_gain_offset = -12;
1420 break;
1421 /* Default case compander gain is 15 dB */
1422 default:
1423 comp_gain_offset = -15;
1424 break;
1425 }
1426
1427 switch (event) {
1428 case SND_SOC_DAPM_POST_PMU:
1429 /* Apply ear spkr gain only if compander is enabled */
1430 if (wsa_priv->comp_enabled[WSA_MACRO_COMP1] &&
1431 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL) &&
1432 (wsa_priv->ear_spkr_gain != 0)) {
1433 /* For example, val is -8(-12+5-1) for 4dB of gain */
1434 val = comp_gain_offset + wsa_priv->ear_spkr_gain - 1;
1435 snd_soc_write(codec, gain_reg, val);
1436
1437 dev_dbg(wsa_priv->dev, "%s: RX0 Volume %d dB\n",
1438 __func__, val);
1439 }
1440 break;
1441 case SND_SOC_DAPM_POST_PMD:
1442 /*
1443 * Reset RX0 volume to 0 dB if compander is enabled and
1444 * ear_spkr_gain is non-zero.
1445 */
1446 if (wsa_priv->comp_enabled[WSA_MACRO_COMP1] &&
1447 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL) &&
1448 (wsa_priv->ear_spkr_gain != 0)) {
1449 snd_soc_write(codec, gain_reg, 0x0);
1450
1451 dev_dbg(wsa_priv->dev, "%s: Reset RX0 Volume to 0 dB\n",
1452 __func__);
1453 }
1454 break;
1455 }
1456
1457 return 0;
1458}
1459
1460static int wsa_macro_spk_boost_event(struct snd_soc_dapm_widget *w,
1461 struct snd_kcontrol *kcontrol,
1462 int event)
1463{
1464 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1465 u16 boost_path_ctl, boost_path_cfg1;
1466 u16 reg, reg_mix;
1467
1468 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
1469
1470 if (!strcmp(w->name, "WSA_RX INT0 CHAIN")) {
1471 boost_path_ctl = BOLERO_CDC_WSA_BOOST0_BOOST_PATH_CTL;
1472 boost_path_cfg1 = BOLERO_CDC_WSA_RX0_RX_PATH_CFG1;
1473 reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
1474 reg_mix = BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL;
1475 } else if (!strcmp(w->name, "WSA_RX INT1 CHAIN")) {
1476 boost_path_ctl = BOLERO_CDC_WSA_BOOST1_BOOST_PATH_CTL;
1477 boost_path_cfg1 = BOLERO_CDC_WSA_RX1_RX_PATH_CFG1;
1478 reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
1479 reg_mix = BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL;
1480 } else {
1481 dev_err(codec->dev, "%s: unknown widget: %s\n",
1482 __func__, w->name);
1483 return -EINVAL;
1484 }
1485
1486 switch (event) {
1487 case SND_SOC_DAPM_PRE_PMU:
1488 snd_soc_update_bits(codec, boost_path_cfg1, 0x01, 0x01);
1489 snd_soc_update_bits(codec, boost_path_ctl, 0x10, 0x10);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301490 if ((snd_soc_read(codec, reg_mix)) & 0x10)
1491 snd_soc_update_bits(codec, reg_mix, 0x10, 0x00);
1492 break;
Laxminath Kasam0c857002018-07-17 23:47:17 +05301493 case SND_SOC_DAPM_POST_PMU:
1494 snd_soc_update_bits(codec, reg, 0x10, 0x00);
1495 break;
Laxminath Kasam243e2752018-04-12 00:40:19 +05301496 case SND_SOC_DAPM_POST_PMD:
1497 snd_soc_update_bits(codec, boost_path_ctl, 0x10, 0x00);
1498 snd_soc_update_bits(codec, boost_path_cfg1, 0x01, 0x00);
1499 break;
1500 }
1501
1502 return 0;
1503}
1504
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301505
1506static int wsa_macro_enable_vbat(struct snd_soc_dapm_widget *w,
1507 struct snd_kcontrol *kcontrol,
1508 int event)
1509{
1510 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1511 struct device *wsa_dev = NULL;
1512 struct wsa_macro_priv *wsa_priv = NULL;
1513 u16 vbat_path_cfg = 0;
1514 int softclip_path = 0;
1515
1516 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1517 return -EINVAL;
1518
1519 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
1520 if (!strcmp(w->name, "WSA_RX INT0 VBAT")) {
1521 vbat_path_cfg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG1;
1522 softclip_path = WSA_MACRO_SOFTCLIP0;
1523 } else if (!strcmp(w->name, "WSA_RX INT1 VBAT")) {
1524 vbat_path_cfg = BOLERO_CDC_WSA_RX1_RX_PATH_CFG1;
1525 softclip_path = WSA_MACRO_SOFTCLIP1;
1526 }
1527
1528 switch (event) {
1529 case SND_SOC_DAPM_PRE_PMU:
1530 /* Enable clock for VBAT block */
1531 snd_soc_update_bits(codec,
1532 BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x10);
1533 /* Enable VBAT block */
1534 snd_soc_update_bits(codec,
1535 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x01);
1536 /* Update interpolator with 384K path */
1537 snd_soc_update_bits(codec, vbat_path_cfg, 0x80, 0x80);
1538 /* Use attenuation mode */
1539 snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
1540 0x02, 0x00);
1541 /*
1542 * BCL block needs softclip clock and mux config to be enabled
1543 */
1544 wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
1545 true);
1546 /* Enable VBAT at channel level */
1547 snd_soc_update_bits(codec, vbat_path_cfg, 0x02, 0x02);
1548 /* Set the ATTK1 gain */
1549 snd_soc_update_bits(codec,
1550 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
1551 0xFF, 0xFF);
1552 snd_soc_update_bits(codec,
1553 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
1554 0xFF, 0x03);
1555 snd_soc_update_bits(codec,
1556 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
1557 0xFF, 0x00);
1558 /* Set the ATTK2 gain */
1559 snd_soc_update_bits(codec,
1560 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
1561 0xFF, 0xFF);
1562 snd_soc_update_bits(codec,
1563 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
1564 0xFF, 0x03);
1565 snd_soc_update_bits(codec,
1566 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
1567 0xFF, 0x00);
1568 /* Set the ATTK3 gain */
1569 snd_soc_update_bits(codec,
1570 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
1571 0xFF, 0xFF);
1572 snd_soc_update_bits(codec,
1573 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
1574 0xFF, 0x03);
1575 snd_soc_update_bits(codec,
1576 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
1577 0xFF, 0x00);
1578 break;
1579
1580 case SND_SOC_DAPM_POST_PMD:
1581 snd_soc_update_bits(codec, vbat_path_cfg, 0x80, 0x00);
1582 snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
1583 0x02, 0x02);
1584 snd_soc_update_bits(codec, vbat_path_cfg, 0x02, 0x00);
1585 snd_soc_update_bits(codec,
1586 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
1587 0xFF, 0x00);
1588 snd_soc_update_bits(codec,
1589 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
1590 0xFF, 0x00);
1591 snd_soc_update_bits(codec,
1592 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
1593 0xFF, 0x00);
1594 snd_soc_update_bits(codec,
1595 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
1596 0xFF, 0x00);
1597 snd_soc_update_bits(codec,
1598 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
1599 0xFF, 0x00);
1600 snd_soc_update_bits(codec,
1601 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
1602 0xFF, 0x00);
1603 snd_soc_update_bits(codec,
1604 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
1605 0xFF, 0x00);
1606 snd_soc_update_bits(codec,
1607 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
1608 0xFF, 0x00);
1609 snd_soc_update_bits(codec,
1610 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
1611 0xFF, 0x00);
1612 wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
1613 false);
1614 snd_soc_update_bits(codec,
1615 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x00);
1616 snd_soc_update_bits(codec,
1617 BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x00);
1618 break;
1619 default:
1620 dev_err(wsa_dev, "%s: Invalid event %d\n", __func__, event);
1621 break;
1622 }
1623 return 0;
1624}
1625
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301626static int wsa_macro_enable_echo(struct snd_soc_dapm_widget *w,
1627 struct snd_kcontrol *kcontrol,
1628 int event)
1629{
1630 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1631 struct device *wsa_dev = NULL;
1632 struct wsa_macro_priv *wsa_priv = NULL;
1633 u16 val, ec_tx = 0, ec_hq_reg;
1634
1635 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1636 return -EINVAL;
1637
1638 dev_dbg(wsa_dev, "%s %d %s\n", __func__, event, w->name);
1639
1640 val = snd_soc_read(codec, BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0);
1641 if (!(strcmp(w->name, "WSA RX_MIX EC0_MUX")))
1642 ec_tx = (val & 0x07) - 1;
1643 else
1644 ec_tx = ((val & 0x38) >> 0x3) - 1;
1645
1646 if (ec_tx < 0 || ec_tx >= (WSA_MACRO_RX1 + 1)) {
1647 dev_err(wsa_dev, "%s: EC mix control not set correctly\n",
1648 __func__);
1649 return -EINVAL;
1650 }
1651 if (wsa_priv->ec_hq[ec_tx]) {
1652 snd_soc_update_bits(codec,
1653 BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
1654 0x1 << ec_tx, 0x1 << ec_tx);
1655 ec_hq_reg = BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL +
1656 0x20 * ec_tx;
1657 snd_soc_update_bits(codec, ec_hq_reg, 0x01, 0x01);
1658 ec_hq_reg = BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0 +
1659 0x20 * ec_tx;
1660 /* default set to 48k */
1661 snd_soc_update_bits(codec, ec_hq_reg, 0x1E, 0x08);
1662 }
1663
1664 return 0;
1665}
1666
1667static int wsa_macro_get_ec_hq(struct snd_kcontrol *kcontrol,
1668 struct snd_ctl_elem_value *ucontrol)
1669{
1670
1671 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1672 int ec_tx = ((struct soc_multi_mixer_control *)
1673 kcontrol->private_value)->shift;
1674 struct device *wsa_dev = NULL;
1675 struct wsa_macro_priv *wsa_priv = NULL;
1676
1677 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1678 return -EINVAL;
1679
1680 ucontrol->value.integer.value[0] = wsa_priv->ec_hq[ec_tx];
1681 return 0;
1682}
1683
1684static int wsa_macro_set_ec_hq(struct snd_kcontrol *kcontrol,
1685 struct snd_ctl_elem_value *ucontrol)
1686{
1687 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1688 int ec_tx = ((struct soc_multi_mixer_control *)
1689 kcontrol->private_value)->shift;
1690 int value = ucontrol->value.integer.value[0];
1691 struct device *wsa_dev = NULL;
1692 struct wsa_macro_priv *wsa_priv = NULL;
1693
1694 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1695 return -EINVAL;
1696
1697 dev_dbg(wsa_dev, "%s: enable current %d, new %d\n",
1698 __func__, wsa_priv->ec_hq[ec_tx], value);
1699 wsa_priv->ec_hq[ec_tx] = value;
1700
1701 return 0;
1702}
1703
Laxminath Kasam243e2752018-04-12 00:40:19 +05301704static int wsa_macro_get_compander(struct snd_kcontrol *kcontrol,
1705 struct snd_ctl_elem_value *ucontrol)
1706{
1707
1708 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1709 int comp = ((struct soc_multi_mixer_control *)
1710 kcontrol->private_value)->shift;
1711 struct device *wsa_dev = NULL;
1712 struct wsa_macro_priv *wsa_priv = NULL;
1713
1714 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1715 return -EINVAL;
1716
1717 ucontrol->value.integer.value[0] = wsa_priv->comp_enabled[comp];
1718 return 0;
1719}
1720
1721static int wsa_macro_set_compander(struct snd_kcontrol *kcontrol,
1722 struct snd_ctl_elem_value *ucontrol)
1723{
1724 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1725 int comp = ((struct soc_multi_mixer_control *)
1726 kcontrol->private_value)->shift;
1727 int value = ucontrol->value.integer.value[0];
1728 struct device *wsa_dev = NULL;
1729 struct wsa_macro_priv *wsa_priv = NULL;
1730
1731 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1732 return -EINVAL;
1733
1734 dev_dbg(codec->dev, "%s: Compander %d enable current %d, new %d\n",
1735 __func__, comp + 1, wsa_priv->comp_enabled[comp], value);
1736 wsa_priv->comp_enabled[comp] = value;
1737
1738 return 0;
1739}
1740
1741static int wsa_macro_ear_spkr_pa_gain_get(struct snd_kcontrol *kcontrol,
1742 struct snd_ctl_elem_value *ucontrol)
1743{
1744 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1745 struct device *wsa_dev = NULL;
1746 struct wsa_macro_priv *wsa_priv = NULL;
1747
1748 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1749 return -EINVAL;
1750
1751 ucontrol->value.integer.value[0] = wsa_priv->ear_spkr_gain;
1752
1753 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
1754 __func__, ucontrol->value.integer.value[0]);
1755
1756 return 0;
1757}
1758
1759static int wsa_macro_ear_spkr_pa_gain_put(struct snd_kcontrol *kcontrol,
1760 struct snd_ctl_elem_value *ucontrol)
1761{
1762 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1763 struct device *wsa_dev = NULL;
1764 struct wsa_macro_priv *wsa_priv = NULL;
1765
1766 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1767 return -EINVAL;
1768
1769 wsa_priv->ear_spkr_gain = ucontrol->value.integer.value[0];
1770
1771 dev_dbg(codec->dev, "%s: gain = %d\n", __func__,
1772 wsa_priv->ear_spkr_gain);
1773
1774 return 0;
1775}
1776
1777static int wsa_macro_spkr_left_boost_stage_get(struct snd_kcontrol *kcontrol,
1778 struct snd_ctl_elem_value *ucontrol)
1779{
1780 u8 bst_state_max = 0;
1781 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1782
1783 bst_state_max = snd_soc_read(codec, BOLERO_CDC_WSA_BOOST0_BOOST_CTL);
1784 bst_state_max = (bst_state_max & 0x0c) >> 2;
1785 ucontrol->value.integer.value[0] = bst_state_max;
1786 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
1787 __func__, ucontrol->value.integer.value[0]);
1788
1789 return 0;
1790}
1791
1792static int wsa_macro_spkr_left_boost_stage_put(struct snd_kcontrol *kcontrol,
1793 struct snd_ctl_elem_value *ucontrol)
1794{
1795 u8 bst_state_max;
1796 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1797
1798 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
1799 __func__, ucontrol->value.integer.value[0]);
1800 bst_state_max = ucontrol->value.integer.value[0] << 2;
1801 snd_soc_update_bits(codec, BOLERO_CDC_WSA_BOOST0_BOOST_CTL,
1802 0x0c, bst_state_max);
1803
1804 return 0;
1805}
1806
1807static int wsa_macro_spkr_right_boost_stage_get(struct snd_kcontrol *kcontrol,
1808 struct snd_ctl_elem_value *ucontrol)
1809{
1810 u8 bst_state_max = 0;
1811 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1812
1813 bst_state_max = snd_soc_read(codec, BOLERO_CDC_WSA_BOOST1_BOOST_CTL);
1814 bst_state_max = (bst_state_max & 0x0c) >> 2;
1815 ucontrol->value.integer.value[0] = bst_state_max;
1816 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
1817 __func__, ucontrol->value.integer.value[0]);
1818
1819 return 0;
1820}
1821
1822static int wsa_macro_spkr_right_boost_stage_put(struct snd_kcontrol *kcontrol,
1823 struct snd_ctl_elem_value *ucontrol)
1824{
1825 u8 bst_state_max;
1826 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1827
1828 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
1829 __func__, ucontrol->value.integer.value[0]);
1830 bst_state_max = ucontrol->value.integer.value[0] << 2;
1831 snd_soc_update_bits(codec, BOLERO_CDC_WSA_BOOST1_BOOST_CTL,
1832 0x0c, bst_state_max);
1833
1834 return 0;
1835}
1836
1837static int wsa_macro_rx_mux_get(struct snd_kcontrol *kcontrol,
1838 struct snd_ctl_elem_value *ucontrol)
1839{
1840 struct snd_soc_dapm_widget *widget =
1841 snd_soc_dapm_kcontrol_widget(kcontrol);
1842 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1843 struct device *wsa_dev = NULL;
1844 struct wsa_macro_priv *wsa_priv = NULL;
1845
1846 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1847 return -EINVAL;
1848
1849 ucontrol->value.integer.value[0] =
1850 wsa_priv->rx_port_value[widget->shift];
1851 return 0;
1852}
1853
1854static int wsa_macro_rx_mux_put(struct snd_kcontrol *kcontrol,
1855 struct snd_ctl_elem_value *ucontrol)
1856{
1857 struct snd_soc_dapm_widget *widget =
1858 snd_soc_dapm_kcontrol_widget(kcontrol);
1859 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1860 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1861 struct snd_soc_dapm_update *update = NULL;
1862 u32 rx_port_value = ucontrol->value.integer.value[0];
1863 u32 bit_input = 0;
1864 u32 aif_rst;
1865 struct device *wsa_dev = NULL;
1866 struct wsa_macro_priv *wsa_priv = NULL;
1867
1868 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1869 return -EINVAL;
1870
1871 aif_rst = wsa_priv->rx_port_value[widget->shift];
1872 if (!rx_port_value) {
1873 if (aif_rst == 0) {
1874 dev_err(wsa_dev, "%s: AIF reset already\n", __func__);
1875 return 0;
1876 }
1877 }
1878 wsa_priv->rx_port_value[widget->shift] = rx_port_value;
1879
1880 bit_input = widget->shift;
1881 if (widget->shift >= WSA_MACRO_RX_MIX)
1882 bit_input %= WSA_MACRO_RX_MIX;
1883
1884 switch (rx_port_value) {
1885 case 0:
1886 clear_bit(bit_input,
Laxminath Kasam59c7a1d2018-08-09 16:11:17 +05301887 &wsa_priv->active_ch_mask[aif_rst]);
1888 wsa_priv->active_ch_cnt[aif_rst]--;
Laxminath Kasam243e2752018-04-12 00:40:19 +05301889 break;
1890 case 1:
1891 case 2:
1892 set_bit(bit_input,
Laxminath Kasam59c7a1d2018-08-09 16:11:17 +05301893 &wsa_priv->active_ch_mask[rx_port_value]);
1894 wsa_priv->active_ch_cnt[rx_port_value]++;
Laxminath Kasam243e2752018-04-12 00:40:19 +05301895 break;
1896 default:
1897 dev_err(wsa_dev,
1898 "%s: Invalid AIF_ID for WSA RX MUX\n", __func__);
1899 return -EINVAL;
1900 }
1901
1902 snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
1903 rx_port_value, e, update);
1904 return 0;
1905}
1906
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301907static int wsa_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol,
1908 struct snd_ctl_elem_value *ucontrol)
1909{
1910 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1911
1912 ucontrol->value.integer.value[0] =
1913 ((snd_soc_read(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG) & 0x04) ?
1914 1 : 0);
1915
1916 dev_dbg(codec->dev, "%s: value: %lu\n", __func__,
1917 ucontrol->value.integer.value[0]);
1918
1919 return 0;
1920}
1921
1922static int wsa_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol,
1923 struct snd_ctl_elem_value *ucontrol)
1924{
1925 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1926
1927 dev_dbg(codec->dev, "%s: value: %lu\n", __func__,
1928 ucontrol->value.integer.value[0]);
1929
1930 /* Set Vbat register configuration for GSM mode bit based on value */
1931 if (ucontrol->value.integer.value[0])
1932 snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
1933 0x04, 0x04);
1934 else
1935 snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
1936 0x04, 0x00);
1937
1938 return 0;
1939}
1940
1941static int wsa_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol,
1942 struct snd_ctl_elem_value *ucontrol)
1943{
1944 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1945 struct device *wsa_dev = NULL;
1946 struct wsa_macro_priv *wsa_priv = NULL;
1947 int path = ((struct soc_multi_mixer_control *)
1948 kcontrol->private_value)->shift;
1949
1950 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1951 return -EINVAL;
1952
1953 ucontrol->value.integer.value[0] = wsa_priv->is_softclip_on[path];
1954
1955 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
1956 __func__, ucontrol->value.integer.value[0]);
1957
1958 return 0;
1959}
1960
1961static int wsa_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol,
1962 struct snd_ctl_elem_value *ucontrol)
1963{
1964 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1965 struct device *wsa_dev = NULL;
1966 struct wsa_macro_priv *wsa_priv = NULL;
1967 int path = ((struct soc_multi_mixer_control *)
1968 kcontrol->private_value)->shift;
1969
1970 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
1971 return -EINVAL;
1972
1973 wsa_priv->is_softclip_on[path] = ucontrol->value.integer.value[0];
1974
1975 dev_dbg(codec->dev, "%s: soft clip enable for %d: %d\n", __func__,
1976 path, wsa_priv->is_softclip_on[path]);
1977
1978 return 0;
1979}
1980
Laxminath Kasam243e2752018-04-12 00:40:19 +05301981static const struct snd_kcontrol_new wsa_macro_snd_controls[] = {
1982 SOC_ENUM_EXT("EAR SPKR PA Gain", wsa_macro_ear_spkr_pa_gain_enum,
1983 wsa_macro_ear_spkr_pa_gain_get,
1984 wsa_macro_ear_spkr_pa_gain_put),
1985 SOC_ENUM_EXT("SPKR Left Boost Max State",
1986 wsa_macro_spkr_boost_stage_enum,
1987 wsa_macro_spkr_left_boost_stage_get,
1988 wsa_macro_spkr_left_boost_stage_put),
1989 SOC_ENUM_EXT("SPKR Right Boost Max State",
1990 wsa_macro_spkr_boost_stage_enum,
1991 wsa_macro_spkr_right_boost_stage_get,
1992 wsa_macro_spkr_right_boost_stage_put),
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301993 SOC_ENUM_EXT("GSM mode Enable", wsa_macro_vbat_bcl_gsm_mode_enum,
1994 wsa_macro_vbat_bcl_gsm_mode_func_get,
1995 wsa_macro_vbat_bcl_gsm_mode_func_put),
1996 SOC_SINGLE_EXT("WSA_Softclip0 Enable", SND_SOC_NOPM,
1997 WSA_MACRO_SOFTCLIP0, 1, 0,
1998 wsa_macro_soft_clip_enable_get,
1999 wsa_macro_soft_clip_enable_put),
2000 SOC_SINGLE_EXT("WSA_Softclip1 Enable", SND_SOC_NOPM,
2001 WSA_MACRO_SOFTCLIP1, 1, 0,
2002 wsa_macro_soft_clip_enable_get,
2003 wsa_macro_soft_clip_enable_put),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302004 SOC_SINGLE_SX_TLV("WSA_RX0 Digital Volume",
2005 BOLERO_CDC_WSA_RX0_RX_VOL_CTL,
2006 0, -84, 40, digital_gain),
2007 SOC_SINGLE_SX_TLV("WSA_RX1 Digital Volume",
2008 BOLERO_CDC_WSA_RX1_RX_VOL_CTL,
2009 0, -84, 40, digital_gain),
2010 SOC_SINGLE_EXT("WSA_COMP1 Switch", SND_SOC_NOPM, WSA_MACRO_COMP1, 1, 0,
2011 wsa_macro_get_compander, wsa_macro_set_compander),
2012 SOC_SINGLE_EXT("WSA_COMP2 Switch", SND_SOC_NOPM, WSA_MACRO_COMP2, 1, 0,
2013 wsa_macro_get_compander, wsa_macro_set_compander),
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05302014 SOC_SINGLE_EXT("WSA_RX0 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX0,
2015 1, 0, wsa_macro_get_ec_hq, wsa_macro_set_ec_hq),
2016 SOC_SINGLE_EXT("WSA_RX1 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX1,
2017 1, 0, wsa_macro_get_ec_hq, wsa_macro_set_ec_hq),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302018};
2019
2020static const struct soc_enum rx_mux_enum =
2021 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_mux_text), rx_mux_text);
2022
2023static const struct snd_kcontrol_new rx_mux[WSA_MACRO_RX_MAX] = {
2024 SOC_DAPM_ENUM_EXT("WSA RX0 Mux", rx_mux_enum,
2025 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2026 SOC_DAPM_ENUM_EXT("WSA RX1 Mux", rx_mux_enum,
2027 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2028 SOC_DAPM_ENUM_EXT("WSA RX_MIX0 Mux", rx_mux_enum,
2029 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2030 SOC_DAPM_ENUM_EXT("WSA RX_MIX1 Mux", rx_mux_enum,
2031 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2032};
2033
2034static int wsa_macro_vi_feed_mixer_get(struct snd_kcontrol *kcontrol,
2035 struct snd_ctl_elem_value *ucontrol)
2036{
2037 struct snd_soc_dapm_widget *widget =
2038 snd_soc_dapm_kcontrol_widget(kcontrol);
2039 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
2040 struct soc_multi_mixer_control *mixer =
2041 ((struct soc_multi_mixer_control *)kcontrol->private_value);
2042 u32 dai_id = widget->shift;
2043 u32 spk_tx_id = mixer->shift;
2044 struct device *wsa_dev = NULL;
2045 struct wsa_macro_priv *wsa_priv = NULL;
2046
2047 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
2048 return -EINVAL;
2049
2050 if (test_bit(spk_tx_id, &wsa_priv->active_ch_mask[dai_id]))
2051 ucontrol->value.integer.value[0] = 1;
2052 else
2053 ucontrol->value.integer.value[0] = 0;
2054
2055 return 0;
2056}
2057
2058static int wsa_macro_vi_feed_mixer_put(struct snd_kcontrol *kcontrol,
2059 struct snd_ctl_elem_value *ucontrol)
2060{
2061 struct snd_soc_dapm_widget *widget =
2062 snd_soc_dapm_kcontrol_widget(kcontrol);
2063 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
2064 struct soc_multi_mixer_control *mixer =
2065 ((struct soc_multi_mixer_control *)kcontrol->private_value);
2066 u32 spk_tx_id = mixer->shift;
2067 u32 enable = ucontrol->value.integer.value[0];
2068 struct device *wsa_dev = NULL;
2069 struct wsa_macro_priv *wsa_priv = NULL;
2070
2071 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
2072 return -EINVAL;
2073
2074 wsa_priv->vi_feed_value = ucontrol->value.integer.value[0];
2075
2076 if (enable) {
2077 if (spk_tx_id == WSA_MACRO_TX0 &&
2078 !test_bit(WSA_MACRO_TX0,
2079 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2080 set_bit(WSA_MACRO_TX0,
2081 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2082 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]++;
2083 }
2084 if (spk_tx_id == WSA_MACRO_TX1 &&
2085 !test_bit(WSA_MACRO_TX1,
2086 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2087 set_bit(WSA_MACRO_TX1,
2088 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2089 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]++;
2090 }
2091 } else {
2092 if (spk_tx_id == WSA_MACRO_TX0 &&
2093 test_bit(WSA_MACRO_TX0,
2094 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2095 clear_bit(WSA_MACRO_TX0,
2096 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2097 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]--;
2098 }
2099 if (spk_tx_id == WSA_MACRO_TX1 &&
2100 test_bit(WSA_MACRO_TX1,
2101 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2102 clear_bit(WSA_MACRO_TX1,
2103 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2104 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]--;
2105 }
2106 }
2107 snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
2108
2109 return 0;
2110}
2111
2112static const struct snd_kcontrol_new aif_vi_mixer[] = {
2113 SOC_SINGLE_EXT("WSA_SPKR_VI_1", SND_SOC_NOPM, WSA_MACRO_TX0, 1, 0,
2114 wsa_macro_vi_feed_mixer_get,
2115 wsa_macro_vi_feed_mixer_put),
2116 SOC_SINGLE_EXT("WSA_SPKR_VI_2", SND_SOC_NOPM, WSA_MACRO_TX1, 1, 0,
2117 wsa_macro_vi_feed_mixer_get,
2118 wsa_macro_vi_feed_mixer_put),
2119};
2120
2121static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = {
2122 SND_SOC_DAPM_AIF_IN("WSA AIF1 PB", "WSA_AIF1 Playback", 0,
2123 SND_SOC_NOPM, 0, 0),
2124
2125 SND_SOC_DAPM_AIF_IN("WSA AIF_MIX1 PB", "WSA_AIF_MIX1 Playback", 0,
2126 SND_SOC_NOPM, 0, 0),
2127
2128 SND_SOC_DAPM_AIF_OUT_E("WSA AIF_VI", "WSA_AIF_VI Capture", 0,
2129 SND_SOC_NOPM, WSA_MACRO_AIF_VI, 0,
2130 wsa_macro_enable_vi_feedback,
2131 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2132
2133 SND_SOC_DAPM_AIF_OUT("WSA AIF_ECHO", "WSA_AIF_ECHO Capture", 0,
2134 SND_SOC_NOPM, 0, 0),
2135
2136 SND_SOC_DAPM_MIXER("WSA_AIF_VI Mixer", SND_SOC_NOPM, WSA_MACRO_AIF_VI,
2137 0, aif_vi_mixer, ARRAY_SIZE(aif_vi_mixer)),
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05302138 SND_SOC_DAPM_MUX_E("WSA RX_MIX EC0_MUX", SND_SOC_NOPM,
2139 WSA_MACRO_EC0_MUX, 0,
2140 &rx_mix_ec0_mux, wsa_macro_enable_echo,
2141 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2142 SND_SOC_DAPM_MUX_E("WSA RX_MIX EC1_MUX", SND_SOC_NOPM,
2143 WSA_MACRO_EC1_MUX, 0,
2144 &rx_mix_ec1_mux, wsa_macro_enable_echo,
2145 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302146
2147 SND_SOC_DAPM_MUX("WSA RX0 MUX", SND_SOC_NOPM, WSA_MACRO_RX0, 0,
2148 &rx_mux[WSA_MACRO_RX0]),
2149 SND_SOC_DAPM_MUX("WSA RX1 MUX", SND_SOC_NOPM, WSA_MACRO_RX1, 0,
2150 &rx_mux[WSA_MACRO_RX1]),
2151 SND_SOC_DAPM_MUX("WSA RX_MIX0 MUX", SND_SOC_NOPM, WSA_MACRO_RX_MIX0, 0,
2152 &rx_mux[WSA_MACRO_RX_MIX0]),
2153 SND_SOC_DAPM_MUX("WSA RX_MIX1 MUX", SND_SOC_NOPM, WSA_MACRO_RX_MIX1, 0,
2154 &rx_mux[WSA_MACRO_RX_MIX1]),
2155
2156 SND_SOC_DAPM_MIXER("WSA RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
2157 SND_SOC_DAPM_MIXER("WSA RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
2158 SND_SOC_DAPM_MIXER("WSA RX_MIX0", SND_SOC_NOPM, 0, 0, NULL, 0),
2159 SND_SOC_DAPM_MIXER("WSA RX_MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
2160
2161 SND_SOC_DAPM_MUX_E("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0,
2162 &rx0_prim_inp0_mux, wsa_macro_enable_swr,
2163 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2164 SND_SOC_DAPM_MUX_E("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0,
2165 &rx0_prim_inp1_mux, wsa_macro_enable_swr,
2166 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2167 SND_SOC_DAPM_MUX_E("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0,
2168 &rx0_prim_inp2_mux, wsa_macro_enable_swr,
2169 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2170 SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM, 0, 0,
2171 &rx0_mix_mux, wsa_macro_enable_mix_path,
2172 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2173 SND_SOC_DAPM_MUX_E("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0,
2174 &rx1_prim_inp0_mux, wsa_macro_enable_swr,
2175 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2176 SND_SOC_DAPM_MUX_E("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0,
2177 &rx1_prim_inp1_mux, wsa_macro_enable_swr,
2178 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2179 SND_SOC_DAPM_MUX_E("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0,
2180 &rx1_prim_inp2_mux, wsa_macro_enable_swr,
2181 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2182 SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM, 0, 0,
2183 &rx1_mix_mux, wsa_macro_enable_mix_path,
2184 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2185 SND_SOC_DAPM_MIXER("WSA_RX INT0 MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2186 SND_SOC_DAPM_MIXER("WSA_RX INT1 MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2187 SND_SOC_DAPM_MIXER("WSA_RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2188 SND_SOC_DAPM_MIXER("WSA_RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2189
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302190 SND_SOC_DAPM_MUX_E("WSA_RX0 INT0 SIDETONE MIX",
2191 BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 4, 0,
2192 &rx0_sidetone_mix_mux, wsa_macro_enable_swr,
2193 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2194 SND_SOC_DAPM_INPUT("WSA SRC0_INP"),
2195
2196 SND_SOC_DAPM_INPUT("WSA_TX DEC0_INP"),
2197 SND_SOC_DAPM_INPUT("WSA_TX DEC1_INP"),
2198
Laxminath Kasam243e2752018-04-12 00:40:19 +05302199 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 INTERP", SND_SOC_NOPM,
2200 WSA_MACRO_COMP1, 0, NULL, 0, wsa_macro_enable_interpolator,
2201 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2202 SND_SOC_DAPM_POST_PMD),
2203 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 INTERP", SND_SOC_NOPM,
2204 WSA_MACRO_COMP2, 0, NULL, 0, wsa_macro_enable_interpolator,
2205 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2206 SND_SOC_DAPM_POST_PMD),
2207
2208 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 CHAIN", SND_SOC_NOPM, 0, 0,
2209 NULL, 0, wsa_macro_spk_boost_event,
Laxminath Kasam0c857002018-07-17 23:47:17 +05302210 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2211 SND_SOC_DAPM_POST_PMD),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302212 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 CHAIN", SND_SOC_NOPM, 0, 0,
2213 NULL, 0, wsa_macro_spk_boost_event,
Laxminath Kasam0c857002018-07-17 23:47:17 +05302214 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2215 SND_SOC_DAPM_POST_PMD),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302216
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302217 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 VBAT", SND_SOC_NOPM,
2218 0, 0, wsa_int0_vbat_mix_switch,
2219 ARRAY_SIZE(wsa_int0_vbat_mix_switch),
2220 wsa_macro_enable_vbat,
2221 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2222 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 VBAT", SND_SOC_NOPM,
2223 0, 0, wsa_int1_vbat_mix_switch,
2224 ARRAY_SIZE(wsa_int1_vbat_mix_switch),
2225 wsa_macro_enable_vbat,
2226 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2227
Laxminath Kasam243e2752018-04-12 00:40:19 +05302228 SND_SOC_DAPM_INPUT("VIINPUT_WSA"),
2229
2230 SND_SOC_DAPM_OUTPUT("WSA_SPK1 OUT"),
2231 SND_SOC_DAPM_OUTPUT("WSA_SPK2 OUT"),
2232
2233 SND_SOC_DAPM_SUPPLY_S("WSA_MCLK", 0, SND_SOC_NOPM, 0, 0,
2234 wsa_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2235};
2236
2237static const struct snd_soc_dapm_route wsa_audio_map[] = {
2238 /* VI Feedback */
2239 {"WSA_AIF_VI Mixer", "WSA_SPKR_VI_1", "VIINPUT_WSA"},
2240 {"WSA_AIF_VI Mixer", "WSA_SPKR_VI_2", "VIINPUT_WSA"},
2241 {"WSA AIF_VI", NULL, "WSA_AIF_VI Mixer"},
2242 {"WSA AIF_VI", NULL, "WSA_MCLK"},
2243
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05302244 {"WSA RX_MIX EC0_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
2245 {"WSA RX_MIX EC1_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
2246 {"WSA RX_MIX EC0_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
2247 {"WSA RX_MIX EC1_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
2248 {"WSA AIF_ECHO", NULL, "WSA RX_MIX EC0_MUX"},
2249 {"WSA AIF_ECHO", NULL, "WSA RX_MIX EC1_MUX"},
2250 {"WSA AIF_ECHO", NULL, "WSA_MCLK"},
2251
Laxminath Kasam243e2752018-04-12 00:40:19 +05302252 {"WSA AIF1 PB", NULL, "WSA_MCLK"},
2253 {"WSA AIF_MIX1 PB", NULL, "WSA_MCLK"},
2254
2255 {"WSA RX0 MUX", "AIF1_PB", "WSA AIF1 PB"},
2256 {"WSA RX1 MUX", "AIF1_PB", "WSA AIF1 PB"},
2257 {"WSA RX_MIX0 MUX", "AIF1_PB", "WSA AIF1 PB"},
2258 {"WSA RX_MIX1 MUX", "AIF1_PB", "WSA AIF1 PB"},
2259
2260 {"WSA RX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2261 {"WSA RX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2262 {"WSA RX_MIX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2263 {"WSA RX_MIX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2264
2265 {"WSA RX0", NULL, "WSA RX0 MUX"},
2266 {"WSA RX1", NULL, "WSA RX1 MUX"},
2267 {"WSA RX_MIX0", NULL, "WSA RX_MIX0 MUX"},
2268 {"WSA RX_MIX1", NULL, "WSA RX_MIX1 MUX"},
2269
2270 {"WSA_RX0 INP0", "RX0", "WSA RX0"},
2271 {"WSA_RX0 INP0", "RX1", "WSA RX1"},
2272 {"WSA_RX0 INP0", "RX_MIX0", "WSA RX_MIX0"},
2273 {"WSA_RX0 INP0", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302274 {"WSA_RX0 INP0", "DEC0", "WSA_TX DEC0_INP"},
2275 {"WSA_RX0 INP0", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302276 {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP0"},
2277
2278 {"WSA_RX0 INP1", "RX0", "WSA RX0"},
2279 {"WSA_RX0 INP1", "RX1", "WSA RX1"},
2280 {"WSA_RX0 INP1", "RX_MIX0", "WSA RX_MIX0"},
2281 {"WSA_RX0 INP1", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302282 {"WSA_RX0 INP1", "DEC0", "WSA_TX DEC0_INP"},
2283 {"WSA_RX0 INP1", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302284 {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP1"},
2285
2286 {"WSA_RX0 INP2", "RX0", "WSA RX0"},
2287 {"WSA_RX0 INP2", "RX1", "WSA RX1"},
2288 {"WSA_RX0 INP2", "RX_MIX0", "WSA RX_MIX0"},
2289 {"WSA_RX0 INP2", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302290 {"WSA_RX0 INP2", "DEC0", "WSA_TX DEC0_INP"},
2291 {"WSA_RX0 INP2", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302292 {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP2"},
2293
2294 {"WSA_RX0 MIX INP", "RX0", "WSA RX0"},
2295 {"WSA_RX0 MIX INP", "RX1", "WSA RX1"},
2296 {"WSA_RX0 MIX INP", "RX_MIX0", "WSA RX_MIX0"},
2297 {"WSA_RX0 MIX INP", "RX_MIX1", "WSA RX_MIX1"},
2298 {"WSA_RX INT0 SEC MIX", NULL, "WSA_RX0 MIX INP"},
2299
2300 {"WSA_RX INT0 SEC MIX", NULL, "WSA_RX INT0 MIX"},
2301 {"WSA_RX INT0 INTERP", NULL, "WSA_RX INT0 SEC MIX"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302302 {"WSA_RX0 INT0 SIDETONE MIX", "SRC0", "WSA SRC0_INP"},
2303 {"WSA_RX INT0 INTERP", NULL, "WSA_RX0 INT0 SIDETONE MIX"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302304 {"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 INTERP"},
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302305
2306 {"WSA_RX INT0 VBAT", "WSA RX0 VBAT Enable", "WSA_RX INT0 INTERP"},
2307 {"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 VBAT"},
2308
Laxminath Kasam243e2752018-04-12 00:40:19 +05302309 {"WSA_SPK1 OUT", NULL, "WSA_RX INT0 CHAIN"},
Laxminath Kasamfc281ad2018-08-06 20:19:40 +05302310 {"WSA_SPK1 OUT", NULL, "WSA_MCLK"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302311
2312 {"WSA_RX1 INP0", "RX0", "WSA RX0"},
2313 {"WSA_RX1 INP0", "RX1", "WSA RX1"},
2314 {"WSA_RX1 INP0", "RX_MIX0", "WSA RX_MIX0"},
2315 {"WSA_RX1 INP0", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302316 {"WSA_RX1 INP0", "DEC0", "WSA_TX DEC0_INP"},
2317 {"WSA_RX1 INP0", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302318 {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP0"},
2319
2320 {"WSA_RX1 INP1", "RX0", "WSA RX0"},
2321 {"WSA_RX1 INP1", "RX1", "WSA RX1"},
2322 {"WSA_RX1 INP1", "RX_MIX0", "WSA RX_MIX0"},
2323 {"WSA_RX1 INP1", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302324 {"WSA_RX1 INP1", "DEC0", "WSA_TX DEC0_INP"},
2325 {"WSA_RX1 INP1", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302326 {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP1"},
2327
2328 {"WSA_RX1 INP2", "RX0", "WSA RX0"},
2329 {"WSA_RX1 INP2", "RX1", "WSA RX1"},
2330 {"WSA_RX1 INP2", "RX_MIX0", "WSA RX_MIX0"},
2331 {"WSA_RX1 INP2", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302332 {"WSA_RX1 INP2", "DEC0", "WSA_TX DEC0_INP"},
2333 {"WSA_RX1 INP2", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302334 {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP2"},
2335
2336 {"WSA_RX1 MIX INP", "RX0", "WSA RX0"},
2337 {"WSA_RX1 MIX INP", "RX1", "WSA RX1"},
2338 {"WSA_RX1 MIX INP", "RX_MIX0", "WSA RX_MIX0"},
2339 {"WSA_RX1 MIX INP", "RX_MIX1", "WSA RX_MIX1"},
2340 {"WSA_RX INT1 SEC MIX", NULL, "WSA_RX1 MIX INP"},
2341
2342 {"WSA_RX INT1 SEC MIX", NULL, "WSA_RX INT1 MIX"},
2343 {"WSA_RX INT1 INTERP", NULL, "WSA_RX INT1 SEC MIX"},
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302344
2345 {"WSA_RX INT1 VBAT", "WSA RX1 VBAT Enable", "WSA_RX INT1 INTERP"},
2346 {"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 VBAT"},
2347
Laxminath Kasam243e2752018-04-12 00:40:19 +05302348 {"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 INTERP"},
2349 {"WSA_SPK2 OUT", NULL, "WSA_RX INT1 CHAIN"},
Laxminath Kasamfc281ad2018-08-06 20:19:40 +05302350 {"WSA_SPK2 OUT", NULL, "WSA_MCLK"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302351};
2352
2353static const struct wsa_macro_reg_mask_val wsa_macro_reg_init[] = {
2354 {BOLERO_CDC_WSA_BOOST0_BOOST_CFG1, 0x3F, 0x12},
2355 {BOLERO_CDC_WSA_BOOST0_BOOST_CFG2, 0x1C, 0x08},
2356 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x1E, 0x18},
2357 {BOLERO_CDC_WSA_BOOST1_BOOST_CFG1, 0x3F, 0x12},
2358 {BOLERO_CDC_WSA_BOOST1_BOOST_CFG2, 0x1C, 0x08},
2359 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x1E, 0x18},
2360 {BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x70, 0x58},
2361 {BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x70, 0x58},
2362 {BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08},
2363 {BOLERO_CDC_WSA_RX1_RX_PATH_CFG1, 0x08, 0x08},
2364 {BOLERO_CDC_WSA_TOP_TOP_CFG1, 0x02, 0x02},
2365 {BOLERO_CDC_WSA_TOP_TOP_CFG1, 0x01, 0x01},
2366 {BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2367 {BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2368 {BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2369 {BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2370 {BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80},
2371 {BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x80},
2372 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01},
2373 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01},
2374 {BOLERO_CDC_WSA_RX0_RX_PATH_CFG0, 0x01, 0x01},
2375 {BOLERO_CDC_WSA_RX1_RX_PATH_CFG0, 0x01, 0x01},
2376 {BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CFG, 0x01, 0x01},
2377 {BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CFG, 0x01, 0x01},
2378};
2379
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302380static void wsa_macro_init_bcl_pmic_reg(struct snd_soc_codec *codec)
2381{
2382 struct device *wsa_dev = NULL;
2383 struct wsa_macro_priv *wsa_priv = NULL;
2384
2385 if (!codec) {
2386 pr_err("%s: NULL codec pointer!\n", __func__);
2387 return;
2388 }
2389
2390 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
2391 return;
2392
2393 switch (wsa_priv->bcl_pmic_params.id) {
2394 case 0:
2395 /* Enable ID0 to listen to respective PMIC group interrupts */
2396 snd_soc_update_bits(codec,
2397 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x02, 0x02);
2398 /* Update MC_SID0 */
2399 snd_soc_update_bits(codec,
2400 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1, 0x0F,
2401 wsa_priv->bcl_pmic_params.sid);
2402 /* Update MC_PPID0 */
2403 snd_soc_update_bits(codec,
2404 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2, 0xFF,
2405 wsa_priv->bcl_pmic_params.ppid);
2406 break;
2407 case 1:
2408 /* Enable ID1 to listen to respective PMIC group interrupts */
2409 snd_soc_update_bits(codec,
2410 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x01, 0x01);
2411 /* Update MC_SID1 */
2412 snd_soc_update_bits(codec,
2413 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3, 0x0F,
2414 wsa_priv->bcl_pmic_params.sid);
2415 /* Update MC_PPID1 */
2416 snd_soc_update_bits(codec,
2417 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4, 0xFF,
2418 wsa_priv->bcl_pmic_params.ppid);
2419 break;
2420 default:
2421 dev_err(wsa_dev, "%s: PMIC ID is invalid %d\n",
2422 __func__, wsa_priv->bcl_pmic_params.id);
2423 break;
2424 }
2425}
2426
Laxminath Kasam243e2752018-04-12 00:40:19 +05302427static void wsa_macro_init_reg(struct snd_soc_codec *codec)
2428{
2429 int i;
2430
2431 for (i = 0; i < ARRAY_SIZE(wsa_macro_reg_init); i++)
2432 snd_soc_update_bits(codec,
2433 wsa_macro_reg_init[i].reg,
2434 wsa_macro_reg_init[i].mask,
2435 wsa_macro_reg_init[i].val);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302436
2437 wsa_macro_init_bcl_pmic_reg(codec);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302438}
2439
2440static int wsa_swrm_clock(void *handle, bool enable)
2441{
2442 struct wsa_macro_priv *wsa_priv = (struct wsa_macro_priv *) handle;
2443 struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302444 int ret = 0;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302445
Tanya Dixitab8eba82018-10-05 15:07:37 +05302446 if (regmap == NULL) {
2447 dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
2448 return -EINVAL;
2449 }
2450
Laxminath Kasam243e2752018-04-12 00:40:19 +05302451 mutex_lock(&wsa_priv->swr_clk_lock);
2452
2453 dev_dbg(wsa_priv->dev, "%s: swrm clock %s\n",
2454 __func__, (enable ? "enable" : "disable"));
2455 if (enable) {
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302456 if (wsa_priv->swr_clk_users == 0) {
2457 ret = wsa_macro_mclk_enable(wsa_priv, 1, true);
2458 if (ret < 0) {
2459 dev_err(wsa_priv->dev,
2460 "%s: wsa request clock enable failed\n",
2461 __func__);
2462 goto exit;
2463 }
Laxminath Kasam243e2752018-04-12 00:40:19 +05302464 regmap_update_bits(regmap,
2465 BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
2466 0x01, 0x01);
2467 regmap_update_bits(regmap,
2468 BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
2469 0x1C, 0x0C);
2470 msm_cdc_pinctrl_select_active_state(
2471 wsa_priv->wsa_swr_gpio_p);
2472 }
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302473 wsa_priv->swr_clk_users++;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302474 } else {
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302475 if (wsa_priv->swr_clk_users <= 0) {
2476 dev_err(wsa_priv->dev, "%s: clock already disabled\n",
2477 __func__);
2478 wsa_priv->swr_clk_users = 0;
2479 goto exit;
2480 }
Laxminath Kasam243e2752018-04-12 00:40:19 +05302481 wsa_priv->swr_clk_users--;
2482 if (wsa_priv->swr_clk_users == 0) {
2483 regmap_update_bits(regmap,
2484 BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
2485 0x01, 0x00);
2486 msm_cdc_pinctrl_select_sleep_state(
2487 wsa_priv->wsa_swr_gpio_p);
2488 wsa_macro_mclk_enable(wsa_priv, 0, true);
2489 }
2490 }
2491 dev_dbg(wsa_priv->dev, "%s: swrm clock users %d\n",
2492 __func__, wsa_priv->swr_clk_users);
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302493exit:
Laxminath Kasam243e2752018-04-12 00:40:19 +05302494 mutex_unlock(&wsa_priv->swr_clk_lock);
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302495 return ret;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302496}
2497
2498static int wsa_macro_init(struct snd_soc_codec *codec)
2499{
2500 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
2501 int ret;
2502 struct device *wsa_dev = NULL;
2503 struct wsa_macro_priv *wsa_priv = NULL;
2504
2505 wsa_dev = bolero_get_device_ptr(codec->dev, WSA_MACRO);
2506 if (!wsa_dev) {
2507 dev_err(codec->dev,
2508 "%s: null device for macro!\n", __func__);
2509 return -EINVAL;
2510 }
2511 wsa_priv = dev_get_drvdata(wsa_dev);
2512 if (!wsa_priv) {
2513 dev_err(codec->dev,
2514 "%s: priv is null for macro!\n", __func__);
2515 return -EINVAL;
2516 }
2517
2518 ret = snd_soc_dapm_new_controls(dapm, wsa_macro_dapm_widgets,
2519 ARRAY_SIZE(wsa_macro_dapm_widgets));
2520 if (ret < 0) {
2521 dev_err(wsa_dev, "%s: Failed to add controls\n", __func__);
2522 return ret;
2523 }
2524
2525 ret = snd_soc_dapm_add_routes(dapm, wsa_audio_map,
2526 ARRAY_SIZE(wsa_audio_map));
2527 if (ret < 0) {
2528 dev_err(wsa_dev, "%s: Failed to add routes\n", __func__);
2529 return ret;
2530 }
2531
2532 ret = snd_soc_dapm_new_widgets(dapm->card);
2533 if (ret < 0) {
2534 dev_err(wsa_dev, "%s: Failed to add widgets\n", __func__);
2535 return ret;
2536 }
2537
2538 ret = snd_soc_add_codec_controls(codec, wsa_macro_snd_controls,
2539 ARRAY_SIZE(wsa_macro_snd_controls));
2540 if (ret < 0) {
2541 dev_err(wsa_dev, "%s: Failed to add snd_ctls\n", __func__);
2542 return ret;
2543 }
Laxminath Kasam638b5602018-09-24 13:19:52 +05302544 snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF1 Playback");
2545 snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_MIX1 Playback");
2546 snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_VI Capture");
2547 snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_ECHO Capture");
2548 snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK1 OUT");
2549 snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK2 OUT");
2550 snd_soc_dapm_ignore_suspend(dapm, "VIINPUT_WSA");
2551 snd_soc_dapm_ignore_suspend(dapm, "WSA SRC0_INP");
2552 snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC0_INP");
2553 snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC1_INP");
2554 snd_soc_dapm_sync(dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302555
2556 wsa_priv->codec = codec;
Laxminath Kasam21c8b222018-06-21 18:47:22 +05302557 wsa_priv->spkr_gain_offset = WSA_MACRO_GAIN_OFFSET_0_DB;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302558 wsa_macro_init_reg(codec);
2559
2560 return 0;
2561}
2562
2563static int wsa_macro_deinit(struct snd_soc_codec *codec)
2564{
2565 struct device *wsa_dev = NULL;
2566 struct wsa_macro_priv *wsa_priv = NULL;
2567
2568 if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
2569 return -EINVAL;
2570
2571 wsa_priv->codec = NULL;
2572
2573 return 0;
2574}
2575
2576static void wsa_macro_add_child_devices(struct work_struct *work)
2577{
2578 struct wsa_macro_priv *wsa_priv;
2579 struct platform_device *pdev;
2580 struct device_node *node;
2581 struct wsa_macro_swr_ctrl_data *swr_ctrl_data = NULL, *temp;
2582 int ret;
2583 u16 count = 0, ctrl_num = 0;
2584 struct wsa_macro_swr_ctrl_platform_data *platdata;
2585 char plat_dev_name[WSA_MACRO_SWR_STRING_LEN];
2586
2587 wsa_priv = container_of(work, struct wsa_macro_priv,
2588 wsa_macro_add_child_devices_work);
2589 if (!wsa_priv) {
2590 pr_err("%s: Memory for wsa_priv does not exist\n",
2591 __func__);
2592 return;
2593 }
Laxminath Kasam21c8b222018-06-21 18:47:22 +05302594 if (!wsa_priv->dev || !wsa_priv->dev->of_node) {
Laxminath Kasam243e2752018-04-12 00:40:19 +05302595 dev_err(wsa_priv->dev,
2596 "%s: DT node for wsa_priv does not exist\n", __func__);
2597 return;
2598 }
2599
2600 platdata = &wsa_priv->swr_plat_data;
2601 wsa_priv->child_count = 0;
2602
2603 for_each_available_child_of_node(wsa_priv->dev->of_node, node) {
2604 if (strnstr(node->name, "wsa_swr_master",
2605 strlen("wsa_swr_master")) != NULL)
2606 strlcpy(plat_dev_name, "wsa_swr_ctrl",
2607 (WSA_MACRO_SWR_STRING_LEN - 1));
2608 else if (strnstr(node->name, "msm_cdc_pinctrl",
2609 strlen("msm_cdc_pinctrl")) != NULL)
2610 strlcpy(plat_dev_name, node->name,
2611 (WSA_MACRO_SWR_STRING_LEN - 1));
2612 else
2613 continue;
2614
2615 pdev = platform_device_alloc(plat_dev_name, -1);
2616 if (!pdev) {
2617 dev_err(wsa_priv->dev, "%s: pdev memory alloc failed\n",
2618 __func__);
2619 ret = -ENOMEM;
2620 goto err;
2621 }
2622 pdev->dev.parent = wsa_priv->dev;
2623 pdev->dev.of_node = node;
2624
2625 if (strnstr(node->name, "wsa_swr_master",
2626 strlen("wsa_swr_master")) != NULL) {
2627 ret = platform_device_add_data(pdev, platdata,
2628 sizeof(*platdata));
2629 if (ret) {
2630 dev_err(&pdev->dev,
2631 "%s: cannot add plat data ctrl:%d\n",
2632 __func__, ctrl_num);
2633 goto fail_pdev_add;
2634 }
2635 }
2636
2637 ret = platform_device_add(pdev);
2638 if (ret) {
2639 dev_err(&pdev->dev,
2640 "%s: Cannot add platform device\n",
2641 __func__);
2642 goto fail_pdev_add;
2643 }
2644
2645 if (!strcmp(node->name, "wsa_swr_master")) {
2646 temp = krealloc(swr_ctrl_data,
2647 (ctrl_num + 1) * sizeof(
2648 struct wsa_macro_swr_ctrl_data),
2649 GFP_KERNEL);
2650 if (!temp) {
2651 dev_err(&pdev->dev, "out of memory\n");
2652 ret = -ENOMEM;
2653 goto err;
2654 }
2655 swr_ctrl_data = temp;
2656 swr_ctrl_data[ctrl_num].wsa_swr_pdev = pdev;
2657 ctrl_num++;
2658 dev_dbg(&pdev->dev,
2659 "%s: Added soundwire ctrl device(s)\n",
2660 __func__);
2661 wsa_priv->swr_ctrl_data = swr_ctrl_data;
2662 }
2663 if (wsa_priv->child_count < WSA_MACRO_CHILD_DEVICES_MAX)
2664 wsa_priv->pdev_child_devices[
2665 wsa_priv->child_count++] = pdev;
2666 else
2667 goto err;
2668 }
2669
2670 return;
2671fail_pdev_add:
2672 for (count = 0; count < wsa_priv->child_count; count++)
2673 platform_device_put(wsa_priv->pdev_child_devices[count]);
2674err:
2675 return;
2676}
2677
2678static void wsa_macro_init_ops(struct macro_ops *ops,
2679 char __iomem *wsa_io_base)
2680{
2681 memset(ops, 0, sizeof(struct macro_ops));
2682 ops->init = wsa_macro_init;
2683 ops->exit = wsa_macro_deinit;
2684 ops->io_base = wsa_io_base;
2685 ops->dai_ptr = wsa_macro_dai;
2686 ops->num_dais = ARRAY_SIZE(wsa_macro_dai);
2687 ops->mclk_fn = wsa_macro_mclk_ctrl;
Laxminath Kasamfb0d6832018-09-22 01:49:52 +05302688 ops->event_handler = wsa_macro_event_handler;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302689}
2690
2691static int wsa_macro_probe(struct platform_device *pdev)
2692{
2693 struct macro_ops ops;
2694 struct wsa_macro_priv *wsa_priv;
2695 u32 wsa_base_addr;
2696 char __iomem *wsa_io_base;
2697 int ret = 0;
2698 struct clk *wsa_core_clk, *wsa_npl_clk;
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302699 u8 bcl_pmic_params[3];
Laxminath Kasam243e2752018-04-12 00:40:19 +05302700
2701 wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct wsa_macro_priv),
2702 GFP_KERNEL);
2703 if (!wsa_priv)
2704 return -ENOMEM;
2705
2706 wsa_priv->dev = &pdev->dev;
2707 ret = of_property_read_u32(pdev->dev.of_node, "reg",
2708 &wsa_base_addr);
2709 if (ret) {
2710 dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
2711 __func__, "reg");
2712 return ret;
2713 }
2714 wsa_priv->wsa_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
2715 "qcom,wsa-swr-gpios", 0);
2716 if (!wsa_priv->wsa_swr_gpio_p) {
2717 dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
2718 __func__);
2719 return -EINVAL;
2720 }
2721 wsa_io_base = devm_ioremap(&pdev->dev,
2722 wsa_base_addr, WSA_MACRO_MAX_OFFSET);
2723 if (!wsa_io_base) {
2724 dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
2725 return -EINVAL;
2726 }
2727 wsa_priv->wsa_io_base = wsa_io_base;
2728 INIT_WORK(&wsa_priv->wsa_macro_add_child_devices_work,
2729 wsa_macro_add_child_devices);
2730 wsa_priv->swr_plat_data.handle = (void *) wsa_priv;
2731 wsa_priv->swr_plat_data.read = NULL;
2732 wsa_priv->swr_plat_data.write = NULL;
2733 wsa_priv->swr_plat_data.bulk_write = NULL;
2734 wsa_priv->swr_plat_data.clk = wsa_swrm_clock;
2735 wsa_priv->swr_plat_data.handle_irq = NULL;
2736
2737 /* Register MCLK for wsa macro */
2738 wsa_core_clk = devm_clk_get(&pdev->dev, "wsa_core_clk");
2739 if (IS_ERR(wsa_core_clk)) {
Ramprasad Katkamf83acfb2018-08-11 23:28:57 +05302740 ret = PTR_ERR(wsa_core_clk);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302741 dev_err(&pdev->dev, "%s: clk get %s failed\n",
2742 __func__, "wsa_core_clk");
Ramprasad Katkamf83acfb2018-08-11 23:28:57 +05302743 return ret;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302744 }
2745 wsa_priv->wsa_core_clk = wsa_core_clk;
2746 /* Register npl clk for soundwire */
2747 wsa_npl_clk = devm_clk_get(&pdev->dev, "wsa_npl_clk");
2748 if (IS_ERR(wsa_npl_clk)) {
Ramprasad Katkamf83acfb2018-08-11 23:28:57 +05302749 ret = PTR_ERR(wsa_npl_clk);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302750 dev_err(&pdev->dev, "%s: clk get %s failed\n",
2751 __func__, "wsa_npl_clk");
Ramprasad Katkamf83acfb2018-08-11 23:28:57 +05302752 return ret;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302753 }
2754 wsa_priv->wsa_npl_clk = wsa_npl_clk;
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302755
2756 ret = of_property_read_u8_array(pdev->dev.of_node,
2757 "qcom,wsa-bcl-pmic-params", bcl_pmic_params,
2758 sizeof(bcl_pmic_params));
2759 if (ret) {
2760 dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
2761 __func__, "qcom,wsa-bcl-pmic-params");
2762 } else {
2763 wsa_priv->bcl_pmic_params.id = bcl_pmic_params[0];
2764 wsa_priv->bcl_pmic_params.sid = bcl_pmic_params[1];
2765 wsa_priv->bcl_pmic_params.ppid = bcl_pmic_params[2];
2766 }
2767
Laxminath Kasam243e2752018-04-12 00:40:19 +05302768 dev_set_drvdata(&pdev->dev, wsa_priv);
2769 mutex_init(&wsa_priv->mclk_lock);
2770 mutex_init(&wsa_priv->swr_clk_lock);
2771 wsa_macro_init_ops(&ops, wsa_io_base);
2772 ret = bolero_register_macro(&pdev->dev, WSA_MACRO, &ops);
2773 if (ret < 0) {
2774 dev_err(&pdev->dev, "%s: register macro failed\n", __func__);
2775 goto reg_macro_fail;
2776 }
2777 schedule_work(&wsa_priv->wsa_macro_add_child_devices_work);
2778 return ret;
2779reg_macro_fail:
2780 mutex_destroy(&wsa_priv->mclk_lock);
2781 mutex_destroy(&wsa_priv->swr_clk_lock);
2782 return ret;
2783}
2784
2785static int wsa_macro_remove(struct platform_device *pdev)
2786{
2787 struct wsa_macro_priv *wsa_priv;
2788 u16 count = 0;
2789
2790 wsa_priv = dev_get_drvdata(&pdev->dev);
2791
2792 if (!wsa_priv)
2793 return -EINVAL;
2794
2795 for (count = 0; count < wsa_priv->child_count &&
2796 count < WSA_MACRO_CHILD_DEVICES_MAX; count++)
2797 platform_device_unregister(wsa_priv->pdev_child_devices[count]);
2798
2799 bolero_unregister_macro(&pdev->dev, WSA_MACRO);
2800 mutex_destroy(&wsa_priv->mclk_lock);
2801 mutex_destroy(&wsa_priv->swr_clk_lock);
2802 return 0;
2803}
2804
2805static const struct of_device_id wsa_macro_dt_match[] = {
2806 {.compatible = "qcom,wsa-macro"},
2807 {}
2808};
2809
2810static struct platform_driver wsa_macro_driver = {
2811 .driver = {
2812 .name = "wsa_macro",
2813 .owner = THIS_MODULE,
2814 .of_match_table = wsa_macro_dt_match,
2815 },
2816 .probe = wsa_macro_probe,
2817 .remove = wsa_macro_remove,
2818};
2819
2820module_platform_driver(wsa_macro_driver);
2821
2822MODULE_DESCRIPTION("WSA macro driver");
2823MODULE_LICENSE("GPL v2");