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