blob: d761d942bd7b654e066aa134c3ddfa88753760bd [file] [log] [blame]
Meng Wang43bbb872018-12-10 12:32:05 +08001// SPDX-License-Identifier: GPL-2.0-only
Laxminath Kasam243e2752018-04-12 00:40:19 +05302/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
Laxminath Kasam243e2752018-04-12 00:40:19 +05303 */
4
5#include <linux/module.h>
6#include <linux/init.h>
7#include <linux/io.h>
8#include <linux/platform_device.h>
9#include <linux/clk.h>
10#include <sound/soc.h>
11#include <sound/soc-dapm.h>
12#include <sound/tlv.h>
13#include <soc/swr-wcd.h>
14
15#include "bolero-cdc.h"
16#include "bolero-cdc-registers.h"
17#include "wsa-macro.h"
18#include "../msm-cdc-pinctrl.h"
19
20#define WSA_MACRO_MAX_OFFSET 0x1000
21
22#define WSA_MACRO_RX_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
23 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
24 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
25#define WSA_MACRO_RX_MIX_RATES (SNDRV_PCM_RATE_48000 |\
26 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
27#define WSA_MACRO_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
28 SNDRV_PCM_FMTBIT_S24_LE |\
29 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
30
31#define WSA_MACRO_ECHO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
32 SNDRV_PCM_RATE_48000)
33#define WSA_MACRO_ECHO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
34 SNDRV_PCM_FMTBIT_S24_LE |\
35 SNDRV_PCM_FMTBIT_S24_3LE)
36
37#define NUM_INTERPOLATORS 2
38
39#define WSA_MACRO_MUX_INP_SHFT 0x3
40#define WSA_MACRO_MUX_INP_MASK1 0x38
41#define WSA_MACRO_MUX_INP_MASK2 0x38
42#define WSA_MACRO_MUX_CFG_OFFSET 0x8
43#define WSA_MACRO_MUX_CFG1_OFFSET 0x4
44#define WSA_MACRO_RX_COMP_OFFSET 0x40
Aditya Bavanari4f3d5642018-09-18 22:19:10 +053045#define WSA_MACRO_RX_SOFTCLIP_OFFSET 0x40
Laxminath Kasam243e2752018-04-12 00:40:19 +053046#define WSA_MACRO_RX_PATH_OFFSET 0x80
47#define WSA_MACRO_RX_PATH_CFG3_OFFSET 0x10
48#define WSA_MACRO_RX_PATH_DSMDEM_OFFSET 0x4C
49#define WSA_MACRO_FS_RATE_MASK 0x0F
50
51enum {
52 WSA_MACRO_RX0 = 0,
53 WSA_MACRO_RX1,
54 WSA_MACRO_RX_MIX,
55 WSA_MACRO_RX_MIX0 = WSA_MACRO_RX_MIX,
56 WSA_MACRO_RX_MIX1,
57 WSA_MACRO_RX_MAX,
58};
59
60enum {
61 WSA_MACRO_TX0 = 0,
62 WSA_MACRO_TX1,
63 WSA_MACRO_TX_MAX,
64};
65
66enum {
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +053067 WSA_MACRO_EC0_MUX = 0,
68 WSA_MACRO_EC1_MUX,
69 WSA_MACRO_EC_MUX_MAX,
70};
71
72enum {
Laxminath Kasam243e2752018-04-12 00:40:19 +053073 WSA_MACRO_COMP1, /* SPK_L */
74 WSA_MACRO_COMP2, /* SPK_R */
75 WSA_MACRO_COMP_MAX
76};
77
Aditya Bavanari4f3d5642018-09-18 22:19:10 +053078enum {
79 WSA_MACRO_SOFTCLIP0, /* RX0 */
80 WSA_MACRO_SOFTCLIP1, /* RX1 */
81 WSA_MACRO_SOFTCLIP_MAX
82};
83
Laxminath Kasam243e2752018-04-12 00:40:19 +053084struct interp_sample_rate {
85 int sample_rate;
86 int rate_val;
87};
88
89/*
90 * Structure used to update codec
91 * register defaults after reset
92 */
93struct wsa_macro_reg_mask_val {
94 u16 reg;
95 u8 mask;
96 u8 val;
97};
98
99static struct interp_sample_rate int_prim_sample_rate_val[] = {
100 {8000, 0x0}, /* 8K */
101 {16000, 0x1}, /* 16K */
102 {24000, -EINVAL},/* 24K */
103 {32000, 0x3}, /* 32K */
104 {48000, 0x4}, /* 48K */
105 {96000, 0x5}, /* 96K */
106 {192000, 0x6}, /* 192K */
107 {384000, 0x7}, /* 384K */
108 {44100, 0x8}, /* 44.1K */
109};
110
111static struct interp_sample_rate int_mix_sample_rate_val[] = {
112 {48000, 0x4}, /* 48K */
113 {96000, 0x5}, /* 96K */
114 {192000, 0x6}, /* 192K */
115};
116
117#define WSA_MACRO_SWR_STRING_LEN 80
118
119static int wsa_macro_hw_params(struct snd_pcm_substream *substream,
120 struct snd_pcm_hw_params *params,
121 struct snd_soc_dai *dai);
122static int wsa_macro_get_channel_map(struct snd_soc_dai *dai,
123 unsigned int *tx_num, unsigned int *tx_slot,
124 unsigned int *rx_num, unsigned int *rx_slot);
125/* Hold instance to soundwire platform device */
126struct wsa_macro_swr_ctrl_data {
127 struct platform_device *wsa_swr_pdev;
128};
129
130struct wsa_macro_swr_ctrl_platform_data {
131 void *handle; /* holds codec private data */
132 int (*read)(void *handle, int reg);
133 int (*write)(void *handle, int reg, int val);
134 int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
135 int (*clk)(void *handle, bool enable);
136 int (*handle_irq)(void *handle,
137 irqreturn_t (*swrm_irq_handler)(int irq,
138 void *data),
139 void *swrm_handle,
140 int action);
141};
142
Aditya Bavanari4f3d5642018-09-18 22:19:10 +0530143struct wsa_macro_bcl_pmic_params {
144 u8 id;
145 u8 sid;
146 u8 ppid;
147};
148
Laxminath Kasam243e2752018-04-12 00:40:19 +0530149enum {
Laxminath Kasam59c7a1d2018-08-09 16:11:17 +0530150 WSA_MACRO_AIF_INVALID = 0,
151 WSA_MACRO_AIF1_PB,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530152 WSA_MACRO_AIF_MIX1_PB,
153 WSA_MACRO_AIF_VI,
154 WSA_MACRO_AIF_ECHO,
155 WSA_MACRO_MAX_DAIS,
156};
157
158#define WSA_MACRO_CHILD_DEVICES_MAX 3
159
160/*
161 * @dev: wsa macro device pointer
162 * @comp_enabled: compander enable mixer value set
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +0530163 * @ec_hq: echo HQ enable mixer value set
Laxminath Kasam243e2752018-04-12 00:40:19 +0530164 * @prim_int_users: Users of interpolator
165 * @wsa_mclk_users: WSA MCLK users count
166 * @swr_clk_users: SWR clk users count
167 * @vi_feed_value: VI sense mask
168 * @mclk_lock: to lock mclk operations
169 * @swr_clk_lock: to lock swr master clock operations
170 * @swr_ctrl_data: SoundWire data structure
171 * @swr_plat_data: Soundwire platform data
172 * @wsa_macro_add_child_devices_work: work for adding child devices
173 * @wsa_swr_gpio_p: used by pinctrl API
174 * @wsa_core_clk: MCLK for wsa macro
175 * @wsa_npl_clk: NPL clock for WSA soundwire
Meng Wang15c825d2018-09-06 10:49:18 +0800176 * @component: codec handle
Laxminath Kasam243e2752018-04-12 00:40:19 +0530177 * @rx_0_count: RX0 interpolation users
178 * @rx_1_count: RX1 interpolation users
179 * @active_ch_mask: channel mask for all AIF DAIs
180 * @active_ch_cnt: channel count of all AIF DAIs
181 * @rx_port_value: mixer ctl value of WSA RX MUXes
182 * @wsa_io_base: Base address of WSA macro addr space
183 */
184struct wsa_macro_priv {
185 struct device *dev;
186 int comp_enabled[WSA_MACRO_COMP_MAX];
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +0530187 int ec_hq[WSA_MACRO_RX1 + 1];
Laxminath Kasam243e2752018-04-12 00:40:19 +0530188 u16 prim_int_users[WSA_MACRO_RX1 + 1];
189 u16 wsa_mclk_users;
190 u16 swr_clk_users;
191 unsigned int vi_feed_value;
192 struct mutex mclk_lock;
193 struct mutex swr_clk_lock;
194 struct wsa_macro_swr_ctrl_data *swr_ctrl_data;
195 struct wsa_macro_swr_ctrl_platform_data swr_plat_data;
196 struct work_struct wsa_macro_add_child_devices_work;
197 struct device_node *wsa_swr_gpio_p;
198 struct clk *wsa_core_clk;
199 struct clk *wsa_npl_clk;
Meng Wang15c825d2018-09-06 10:49:18 +0800200 struct snd_soc_component *component;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530201 int rx_0_count;
202 int rx_1_count;
203 unsigned long active_ch_mask[WSA_MACRO_MAX_DAIS];
204 unsigned long active_ch_cnt[WSA_MACRO_MAX_DAIS];
205 int rx_port_value[WSA_MACRO_RX_MAX];
206 char __iomem *wsa_io_base;
207 struct platform_device *pdev_child_devices
208 [WSA_MACRO_CHILD_DEVICES_MAX];
209 int child_count;
210 int ear_spkr_gain;
211 int spkr_gain_offset;
212 int spkr_mode;
Aditya Bavanari4f3d5642018-09-18 22:19:10 +0530213 int is_softclip_on[WSA_MACRO_SOFTCLIP_MAX];
214 int softclip_clk_users[WSA_MACRO_SOFTCLIP_MAX];
215 struct wsa_macro_bcl_pmic_params bcl_pmic_params;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530216};
217
Meng Wang15c825d2018-09-06 10:49:18 +0800218static int wsa_macro_config_ear_spkr_gain(struct snd_soc_component *component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530219 struct wsa_macro_priv *wsa_priv,
220 int event, int gain_reg);
221static struct snd_soc_dai_driver wsa_macro_dai[];
222static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
223
224static const char *const rx_text[] = {
225 "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "DEC0", "DEC1"
226};
227
228static const char *const rx_mix_text[] = {
229 "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1"
230};
231
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +0530232static const char *const rx_mix_ec_text[] = {
233 "ZERO", "RX_MIX_TX0", "RX_MIX_TX1"
234};
235
Laxminath Kasam243e2752018-04-12 00:40:19 +0530236static const char *const rx_mux_text[] = {
237 "ZERO", "AIF1_PB", "AIF_MIX1_PB"
238};
239
Laxminath Kasam6fc2e742018-08-26 23:32:57 +0530240static const char *const rx_sidetone_mix_text[] = {
241 "ZERO", "SRC0"
242};
243
Laxminath Kasam243e2752018-04-12 00:40:19 +0530244static const char * const wsa_macro_ear_spkr_pa_gain_text[] = {
245 "G_DEFAULT", "G_0_DB", "G_1_DB", "G_2_DB", "G_3_DB",
246 "G_4_DB", "G_5_DB", "G_6_DB"
247};
248
249static const char * const wsa_macro_speaker_boost_stage_text[] = {
250 "NO_MAX_STATE", "MAX_STATE_1", "MAX_STATE_2"
251};
252
Aditya Bavanari4f3d5642018-09-18 22:19:10 +0530253static const char * const wsa_macro_vbat_bcl_gsm_mode_text[] = {
254 "OFF", "ON"
255};
256
257static const struct snd_kcontrol_new wsa_int0_vbat_mix_switch[] = {
258 SOC_DAPM_SINGLE("WSA RX0 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
259};
260
261static const struct snd_kcontrol_new wsa_int1_vbat_mix_switch[] = {
262 SOC_DAPM_SINGLE("WSA RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
263};
264
Laxminath Kasam243e2752018-04-12 00:40:19 +0530265static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_ear_spkr_pa_gain_enum,
266 wsa_macro_ear_spkr_pa_gain_text);
267static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_spkr_boost_stage_enum,
268 wsa_macro_speaker_boost_stage_text);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +0530269static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_vbat_bcl_gsm_mode_enum,
270 wsa_macro_vbat_bcl_gsm_mode_text);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530271
272/* RX INT0 */
273static const struct soc_enum rx0_prim_inp0_chain_enum =
274 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0,
275 0, 7, rx_text);
276
277static const struct soc_enum rx0_prim_inp1_chain_enum =
278 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0,
279 3, 7, rx_text);
280
281static const struct soc_enum rx0_prim_inp2_chain_enum =
282 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1,
283 3, 7, rx_text);
284
285static const struct soc_enum rx0_mix_chain_enum =
286 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1,
287 0, 5, rx_mix_text);
288
Laxminath Kasam6fc2e742018-08-26 23:32:57 +0530289static const struct soc_enum rx0_sidetone_mix_enum =
290 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_sidetone_mix_text);
291
Laxminath Kasam243e2752018-04-12 00:40:19 +0530292static const struct snd_kcontrol_new rx0_prim_inp0_mux =
293 SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum);
294
295static const struct snd_kcontrol_new rx0_prim_inp1_mux =
296 SOC_DAPM_ENUM("WSA_RX0 INP1 Mux", rx0_prim_inp1_chain_enum);
297
298static const struct snd_kcontrol_new rx0_prim_inp2_mux =
299 SOC_DAPM_ENUM("WSA_RX0 INP2 Mux", rx0_prim_inp2_chain_enum);
300
301static const struct snd_kcontrol_new rx0_mix_mux =
302 SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum);
303
Laxminath Kasam6fc2e742018-08-26 23:32:57 +0530304static const struct snd_kcontrol_new rx0_sidetone_mix_mux =
305 SOC_DAPM_ENUM("WSA_RX0 SIDETONE MIX Mux", rx0_sidetone_mix_enum);
306
Laxminath Kasam243e2752018-04-12 00:40:19 +0530307/* RX INT1 */
308static const struct soc_enum rx1_prim_inp0_chain_enum =
309 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0,
310 0, 7, rx_text);
311
312static const struct soc_enum rx1_prim_inp1_chain_enum =
313 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0,
314 3, 7, rx_text);
315
316static const struct soc_enum rx1_prim_inp2_chain_enum =
317 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1,
318 3, 7, rx_text);
319
320static const struct soc_enum rx1_mix_chain_enum =
321 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1,
322 0, 5, rx_mix_text);
323
324static const struct snd_kcontrol_new rx1_prim_inp0_mux =
325 SOC_DAPM_ENUM("WSA_RX1 INP0 Mux", rx1_prim_inp0_chain_enum);
326
327static const struct snd_kcontrol_new rx1_prim_inp1_mux =
328 SOC_DAPM_ENUM("WSA_RX1 INP1 Mux", rx1_prim_inp1_chain_enum);
329
330static const struct snd_kcontrol_new rx1_prim_inp2_mux =
331 SOC_DAPM_ENUM("WSA_RX1 INP2 Mux", rx1_prim_inp2_chain_enum);
332
333static const struct snd_kcontrol_new rx1_mix_mux =
334 SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum);
335
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +0530336static const struct soc_enum rx_mix_ec0_enum =
337 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
338 0, 3, rx_mix_ec_text);
339
340static const struct soc_enum rx_mix_ec1_enum =
341 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
342 3, 3, rx_mix_ec_text);
343
344static const struct snd_kcontrol_new rx_mix_ec0_mux =
345 SOC_DAPM_ENUM("WSA RX_MIX EC0_Mux", rx_mix_ec0_enum);
346
347static const struct snd_kcontrol_new rx_mix_ec1_mux =
348 SOC_DAPM_ENUM("WSA RX_MIX EC1_Mux", rx_mix_ec1_enum);
349
Laxminath Kasam243e2752018-04-12 00:40:19 +0530350static struct snd_soc_dai_ops wsa_macro_dai_ops = {
351 .hw_params = wsa_macro_hw_params,
352 .get_channel_map = wsa_macro_get_channel_map,
353};
354
355static struct snd_soc_dai_driver wsa_macro_dai[] = {
356 {
357 .name = "wsa_macro_rx1",
358 .id = WSA_MACRO_AIF1_PB,
359 .playback = {
360 .stream_name = "WSA_AIF1 Playback",
361 .rates = WSA_MACRO_RX_RATES,
362 .formats = WSA_MACRO_RX_FORMATS,
363 .rate_max = 384000,
364 .rate_min = 8000,
365 .channels_min = 1,
366 .channels_max = 2,
367 },
368 .ops = &wsa_macro_dai_ops,
369 },
370 {
371 .name = "wsa_macro_rx_mix",
372 .id = WSA_MACRO_AIF_MIX1_PB,
373 .playback = {
374 .stream_name = "WSA_AIF_MIX1 Playback",
375 .rates = WSA_MACRO_RX_MIX_RATES,
376 .formats = WSA_MACRO_RX_FORMATS,
377 .rate_max = 192000,
378 .rate_min = 48000,
379 .channels_min = 1,
380 .channels_max = 2,
381 },
382 .ops = &wsa_macro_dai_ops,
383 },
384 {
385 .name = "wsa_macro_vifeedback",
386 .id = WSA_MACRO_AIF_VI,
387 .capture = {
388 .stream_name = "WSA_AIF_VI Capture",
Vatsal Buchad1b694d2018-08-31 11:47:32 +0530389 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
390 .formats = WSA_MACRO_RX_FORMATS,
391 .rate_max = 48000,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530392 .rate_min = 8000,
393 .channels_min = 1,
Vatsal Buchad1b694d2018-08-31 11:47:32 +0530394 .channels_max = 4,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530395 },
396 .ops = &wsa_macro_dai_ops,
397 },
398 {
399 .name = "wsa_macro_echo",
400 .id = WSA_MACRO_AIF_ECHO,
401 .capture = {
402 .stream_name = "WSA_AIF_ECHO Capture",
403 .rates = WSA_MACRO_ECHO_RATES,
404 .formats = WSA_MACRO_ECHO_FORMATS,
405 .rate_max = 48000,
406 .rate_min = 8000,
407 .channels_min = 1,
408 .channels_max = 2,
409 },
410 .ops = &wsa_macro_dai_ops,
411 },
412};
413
414static const struct wsa_macro_reg_mask_val wsa_macro_spkr_default[] = {
415 {BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80},
416 {BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x80},
417 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01},
418 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01},
419 {BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x58},
420 {BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x58},
421};
422
423static const struct wsa_macro_reg_mask_val wsa_macro_spkr_mode1[] = {
424 {BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x00},
425 {BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x00},
426 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x00},
427 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x00},
428 {BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x44},
429 {BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x44},
430};
431
Meng Wang15c825d2018-09-06 10:49:18 +0800432static bool wsa_macro_get_data(struct snd_soc_component *component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530433 struct device **wsa_dev,
434 struct wsa_macro_priv **wsa_priv,
435 const char *func_name)
436{
Meng Wang15c825d2018-09-06 10:49:18 +0800437 *wsa_dev = bolero_get_device_ptr(component->dev, WSA_MACRO);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530438 if (!(*wsa_dev)) {
Meng Wang15c825d2018-09-06 10:49:18 +0800439 dev_err(component->dev,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530440 "%s: null device for macro!\n", func_name);
441 return false;
442 }
443 *wsa_priv = dev_get_drvdata((*wsa_dev));
Meng Wang15c825d2018-09-06 10:49:18 +0800444 if (!(*wsa_priv) || !(*wsa_priv)->component) {
445 dev_err(component->dev,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530446 "%s: priv is null for macro!\n", func_name);
447 return false;
448 }
449 return true;
450}
451
452/**
453 * wsa_macro_set_spkr_gain_offset - offset the speaker path
454 * gain with the given offset value.
455 *
Meng Wang15c825d2018-09-06 10:49:18 +0800456 * @component: codec instance
Laxminath Kasam243e2752018-04-12 00:40:19 +0530457 * @offset: Indicates speaker path gain offset value.
458 *
459 * Returns 0 on success or -EINVAL on error.
460 */
Meng Wang15c825d2018-09-06 10:49:18 +0800461int wsa_macro_set_spkr_gain_offset(struct snd_soc_component *component,
462 int offset)
Laxminath Kasam243e2752018-04-12 00:40:19 +0530463{
464 struct device *wsa_dev = NULL;
465 struct wsa_macro_priv *wsa_priv = NULL;
466
Meng Wang15c825d2018-09-06 10:49:18 +0800467 if (!component) {
468 pr_err("%s: NULL component pointer!\n", __func__);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530469 return -EINVAL;
470 }
471
Meng Wang15c825d2018-09-06 10:49:18 +0800472 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +0530473 return -EINVAL;
474
475 wsa_priv->spkr_gain_offset = offset;
476 return 0;
477}
478EXPORT_SYMBOL(wsa_macro_set_spkr_gain_offset);
479
480/**
481 * wsa_macro_set_spkr_mode - Configures speaker compander and smartboost
482 * settings based on speaker mode.
483 *
Meng Wang15c825d2018-09-06 10:49:18 +0800484 * @component: codec instance
Laxminath Kasam243e2752018-04-12 00:40:19 +0530485 * @mode: Indicates speaker configuration mode.
486 *
487 * Returns 0 on success or -EINVAL on error.
488 */
Meng Wang15c825d2018-09-06 10:49:18 +0800489int wsa_macro_set_spkr_mode(struct snd_soc_component *component, int mode)
Laxminath Kasam243e2752018-04-12 00:40:19 +0530490{
491 int i;
492 const struct wsa_macro_reg_mask_val *regs;
493 int size;
494 struct device *wsa_dev = NULL;
495 struct wsa_macro_priv *wsa_priv = NULL;
496
Meng Wang15c825d2018-09-06 10:49:18 +0800497 if (!component) {
Laxminath Kasam243e2752018-04-12 00:40:19 +0530498 pr_err("%s: NULL codec pointer!\n", __func__);
499 return -EINVAL;
500 }
501
Meng Wang15c825d2018-09-06 10:49:18 +0800502 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +0530503 return -EINVAL;
504
505 switch (mode) {
Laxminath Kasam21c8b222018-06-21 18:47:22 +0530506 case WSA_MACRO_SPKR_MODE_1:
Laxminath Kasam243e2752018-04-12 00:40:19 +0530507 regs = wsa_macro_spkr_mode1;
508 size = ARRAY_SIZE(wsa_macro_spkr_mode1);
509 break;
510 default:
511 regs = wsa_macro_spkr_default;
512 size = ARRAY_SIZE(wsa_macro_spkr_default);
513 break;
514 }
515
516 wsa_priv->spkr_mode = mode;
517 for (i = 0; i < size; i++)
Meng Wang15c825d2018-09-06 10:49:18 +0800518 snd_soc_component_update_bits(component, regs[i].reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530519 regs[i].mask, regs[i].val);
520 return 0;
521}
522EXPORT_SYMBOL(wsa_macro_set_spkr_mode);
523
524static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
525 u8 int_prim_fs_rate_reg_val,
526 u32 sample_rate)
527{
528 u8 int_1_mix1_inp;
529 u32 j, port;
530 u16 int_mux_cfg0, int_mux_cfg1;
531 u16 int_fs_reg;
532 u8 int_mux_cfg0_val, int_mux_cfg1_val;
533 u8 inp0_sel, inp1_sel, inp2_sel;
Meng Wang15c825d2018-09-06 10:49:18 +0800534 struct snd_soc_component *component = dai->component;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530535 struct device *wsa_dev = NULL;
536 struct wsa_macro_priv *wsa_priv = NULL;
537
Meng Wang15c825d2018-09-06 10:49:18 +0800538 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +0530539 return -EINVAL;
540
541 for_each_set_bit(port, &wsa_priv->active_ch_mask[dai->id],
542 WSA_MACRO_RX_MAX) {
543 int_1_mix1_inp = port;
544 if ((int_1_mix1_inp < WSA_MACRO_RX0) ||
545 (int_1_mix1_inp > WSA_MACRO_RX_MIX1)) {
546 dev_err(wsa_dev,
547 "%s: Invalid RX port, Dai ID is %d\n",
548 __func__, dai->id);
549 return -EINVAL;
550 }
551
552 int_mux_cfg0 = BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0;
553
554 /*
555 * Loop through all interpolator MUX inputs and find out
556 * to which interpolator input, the cdc_dma rx port
557 * is connected
558 */
559 for (j = 0; j < NUM_INTERPOLATORS; j++) {
560 int_mux_cfg1 = int_mux_cfg0 + WSA_MACRO_MUX_CFG1_OFFSET;
561
Meng Wang15c825d2018-09-06 10:49:18 +0800562 int_mux_cfg0_val = snd_soc_component_read32(component,
563 int_mux_cfg0);
564 int_mux_cfg1_val = snd_soc_component_read32(component,
565 int_mux_cfg1);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530566 inp0_sel = int_mux_cfg0_val & WSA_MACRO_MUX_INP_MASK1;
567 inp1_sel = (int_mux_cfg0_val >>
568 WSA_MACRO_MUX_INP_SHFT) &
569 WSA_MACRO_MUX_INP_MASK2;
570 inp2_sel = (int_mux_cfg1_val >>
571 WSA_MACRO_MUX_INP_SHFT) &
572 WSA_MACRO_MUX_INP_MASK2;
573 if ((inp0_sel == int_1_mix1_inp) ||
574 (inp1_sel == int_1_mix1_inp) ||
575 (inp2_sel == int_1_mix1_inp)) {
576 int_fs_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL +
577 WSA_MACRO_RX_PATH_OFFSET * j;
578 dev_dbg(wsa_dev,
579 "%s: AIF_PB DAI(%d) connected to INT%u_1\n",
580 __func__, dai->id, j);
581 dev_dbg(wsa_dev,
582 "%s: set INT%u_1 sample rate to %u\n",
583 __func__, j, sample_rate);
584 /* sample_rate is in Hz */
Meng Wang15c825d2018-09-06 10:49:18 +0800585 snd_soc_component_update_bits(component,
586 int_fs_reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530587 WSA_MACRO_FS_RATE_MASK,
588 int_prim_fs_rate_reg_val);
589 }
590 int_mux_cfg0 += WSA_MACRO_MUX_CFG_OFFSET;
591 }
592 }
593
594 return 0;
595}
596
597static int wsa_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai,
598 u8 int_mix_fs_rate_reg_val,
599 u32 sample_rate)
600{
601 u8 int_2_inp;
602 u32 j, port;
603 u16 int_mux_cfg1, int_fs_reg;
604 u8 int_mux_cfg1_val;
Meng Wang15c825d2018-09-06 10:49:18 +0800605 struct snd_soc_component *component = dai->component;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530606 struct device *wsa_dev = NULL;
607 struct wsa_macro_priv *wsa_priv = NULL;
608
Meng Wang15c825d2018-09-06 10:49:18 +0800609 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +0530610 return -EINVAL;
611
612
613 for_each_set_bit(port, &wsa_priv->active_ch_mask[dai->id],
614 WSA_MACRO_RX_MAX) {
615 int_2_inp = port;
616 if ((int_2_inp < WSA_MACRO_RX0) ||
617 (int_2_inp > WSA_MACRO_RX_MIX1)) {
618 dev_err(wsa_dev,
619 "%s: Invalid RX port, Dai ID is %d\n",
620 __func__, dai->id);
621 return -EINVAL;
622 }
623
624 int_mux_cfg1 = BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1;
625 for (j = 0; j < NUM_INTERPOLATORS; j++) {
Meng Wang15c825d2018-09-06 10:49:18 +0800626 int_mux_cfg1_val = snd_soc_component_read32(component,
627 int_mux_cfg1) &
Laxminath Kasam243e2752018-04-12 00:40:19 +0530628 WSA_MACRO_MUX_INP_MASK1;
629 if (int_mux_cfg1_val == int_2_inp) {
630 int_fs_reg =
631 BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL +
632 WSA_MACRO_RX_PATH_OFFSET * j;
633
634 dev_dbg(wsa_dev,
635 "%s: AIF_PB DAI(%d) connected to INT%u_2\n",
636 __func__, dai->id, j);
637 dev_dbg(wsa_dev,
638 "%s: set INT%u_2 sample rate to %u\n",
639 __func__, j, sample_rate);
Meng Wang15c825d2018-09-06 10:49:18 +0800640 snd_soc_component_update_bits(component,
641 int_fs_reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530642 WSA_MACRO_FS_RATE_MASK,
643 int_mix_fs_rate_reg_val);
644 }
645 int_mux_cfg1 += WSA_MACRO_MUX_CFG_OFFSET;
646 }
647 }
648 return 0;
649}
650
651static int wsa_macro_set_interpolator_rate(struct snd_soc_dai *dai,
652 u32 sample_rate)
653{
654 int rate_val = 0;
655 int i, ret;
656
657 /* set mixing path rate */
658 for (i = 0; i < ARRAY_SIZE(int_mix_sample_rate_val); i++) {
659 if (sample_rate ==
660 int_mix_sample_rate_val[i].sample_rate) {
661 rate_val =
662 int_mix_sample_rate_val[i].rate_val;
663 break;
664 }
665 }
666 if ((i == ARRAY_SIZE(int_mix_sample_rate_val)) ||
667 (rate_val < 0))
668 goto prim_rate;
669 ret = wsa_macro_set_mix_interpolator_rate(dai,
670 (u8) rate_val, sample_rate);
671prim_rate:
672 /* set primary path sample rate */
673 for (i = 0; i < ARRAY_SIZE(int_prim_sample_rate_val); i++) {
674 if (sample_rate ==
675 int_prim_sample_rate_val[i].sample_rate) {
676 rate_val =
677 int_prim_sample_rate_val[i].rate_val;
678 break;
679 }
680 }
681 if ((i == ARRAY_SIZE(int_prim_sample_rate_val)) ||
682 (rate_val < 0))
683 return -EINVAL;
684 ret = wsa_macro_set_prim_interpolator_rate(dai,
685 (u8) rate_val, sample_rate);
686 return ret;
687}
688
689static int wsa_macro_hw_params(struct snd_pcm_substream *substream,
690 struct snd_pcm_hw_params *params,
691 struct snd_soc_dai *dai)
692{
Meng Wang15c825d2018-09-06 10:49:18 +0800693 struct snd_soc_component *component = dai->component;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530694 int ret;
695
Meng Wang15c825d2018-09-06 10:49:18 +0800696 dev_dbg(component->dev,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530697 "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
698 dai->name, dai->id, params_rate(params),
699 params_channels(params));
700
701 switch (substream->stream) {
702 case SNDRV_PCM_STREAM_PLAYBACK:
703 ret = wsa_macro_set_interpolator_rate(dai, params_rate(params));
704 if (ret) {
Meng Wang15c825d2018-09-06 10:49:18 +0800705 dev_err(component->dev,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530706 "%s: cannot set sample rate: %u\n",
707 __func__, params_rate(params));
708 return ret;
709 }
710 break;
711 case SNDRV_PCM_STREAM_CAPTURE:
712 default:
713 break;
714 }
715 return 0;
716}
717
718static int wsa_macro_get_channel_map(struct snd_soc_dai *dai,
719 unsigned int *tx_num, unsigned int *tx_slot,
720 unsigned int *rx_num, unsigned int *rx_slot)
721{
Meng Wang15c825d2018-09-06 10:49:18 +0800722 struct snd_soc_component *component = dai->component;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530723 struct device *wsa_dev = NULL;
724 struct wsa_macro_priv *wsa_priv = NULL;
725
Meng Wang15c825d2018-09-06 10:49:18 +0800726 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +0530727 return -EINVAL;
728
729 wsa_priv = dev_get_drvdata(wsa_dev);
730 if (!wsa_priv)
731 return -EINVAL;
732
733 switch (dai->id) {
734 case WSA_MACRO_AIF_VI:
735 case WSA_MACRO_AIF_ECHO:
736 *tx_slot = wsa_priv->active_ch_mask[dai->id];
737 *tx_num = wsa_priv->active_ch_cnt[dai->id];
738 break;
739 case WSA_MACRO_AIF1_PB:
740 case WSA_MACRO_AIF_MIX1_PB:
741 *rx_slot = wsa_priv->active_ch_mask[dai->id];
742 *rx_num = wsa_priv->active_ch_cnt[dai->id];
743 break;
744 default:
745 dev_err(wsa_dev, "%s: Invalid AIF\n", __func__);
746 break;
747 }
748 return 0;
749}
750
751static int wsa_macro_mclk_enable(struct wsa_macro_priv *wsa_priv,
752 bool mclk_enable, bool dapm)
753{
754 struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
755 int ret = 0;
756
Tanya Dixitab8eba82018-10-05 15:07:37 +0530757 if (regmap == NULL) {
758 dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
759 return -EINVAL;
760 }
761
Laxminath Kasam243e2752018-04-12 00:40:19 +0530762 dev_dbg(wsa_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
763 __func__, mclk_enable, dapm, wsa_priv->wsa_mclk_users);
764
765 mutex_lock(&wsa_priv->mclk_lock);
766 if (mclk_enable) {
Aditya Bavanaric496ed22018-11-16 15:50:40 +0530767 if (wsa_priv->wsa_mclk_users == 0) {
Laxminath Kasam243e2752018-04-12 00:40:19 +0530768 ret = bolero_request_clock(wsa_priv->dev,
769 WSA_MACRO, MCLK_MUX0, true);
770 if (ret < 0) {
771 dev_err(wsa_priv->dev,
772 "%s: wsa request clock enable failed\n",
773 __func__);
774 goto exit;
775 }
776 regcache_mark_dirty(regmap);
777 regcache_sync_region(regmap,
778 WSA_START_OFFSET,
779 WSA_MAX_OFFSET);
780 /* 9.6MHz MCLK, set value 0x00 if other frequency */
781 regmap_update_bits(regmap,
782 BOLERO_CDC_WSA_TOP_FREQ_MCLK, 0x01, 0x01);
783 regmap_update_bits(regmap,
784 BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL,
785 0x01, 0x01);
786 regmap_update_bits(regmap,
787 BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
788 0x01, 0x01);
789 }
Aditya Bavanaric496ed22018-11-16 15:50:40 +0530790 wsa_priv->wsa_mclk_users++;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530791 } else {
Aditya Bavanaric496ed22018-11-16 15:50:40 +0530792 if (wsa_priv->wsa_mclk_users <= 0) {
793 dev_err(wsa_priv->dev, "%s: clock already disabled\n",
794 __func__);
795 wsa_priv->wsa_mclk_users = 0;
796 goto exit;
797 }
Laxminath Kasam243e2752018-04-12 00:40:19 +0530798 wsa_priv->wsa_mclk_users--;
799 if (wsa_priv->wsa_mclk_users == 0) {
800 regmap_update_bits(regmap,
801 BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
802 0x01, 0x00);
803 regmap_update_bits(regmap,
804 BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL,
805 0x01, 0x00);
806 bolero_request_clock(wsa_priv->dev,
807 WSA_MACRO, MCLK_MUX0, false);
808 }
809 }
810exit:
811 mutex_unlock(&wsa_priv->mclk_lock);
812 return ret;
813}
814
815static int wsa_macro_mclk_event(struct snd_soc_dapm_widget *w,
816 struct snd_kcontrol *kcontrol, int event)
817{
Meng Wang15c825d2018-09-06 10:49:18 +0800818 struct snd_soc_component *component =
819 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530820 int ret = 0;
821 struct device *wsa_dev = NULL;
822 struct wsa_macro_priv *wsa_priv = NULL;
823
Meng Wang15c825d2018-09-06 10:49:18 +0800824 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +0530825 return -EINVAL;
826
827 dev_dbg(wsa_dev, "%s: event = %d\n", __func__, event);
828 switch (event) {
829 case SND_SOC_DAPM_PRE_PMU:
830 ret = wsa_macro_mclk_enable(wsa_priv, 1, true);
831 break;
832 case SND_SOC_DAPM_POST_PMD:
833 wsa_macro_mclk_enable(wsa_priv, 0, true);
834 break;
835 default:
836 dev_err(wsa_priv->dev,
837 "%s: invalid DAPM event %d\n", __func__, event);
838 ret = -EINVAL;
839 }
840 return ret;
841}
842
843static int wsa_macro_mclk_ctrl(struct device *dev, bool enable)
844{
845 struct wsa_macro_priv *wsa_priv = dev_get_drvdata(dev);
846 int ret = 0;
847
848 if (!wsa_priv)
849 return -EINVAL;
850
851 if (enable) {
852 ret = clk_prepare_enable(wsa_priv->wsa_core_clk);
853 if (ret < 0) {
854 dev_err(dev, "%s:wsa mclk enable failed\n", __func__);
855 goto exit;
856 }
857 ret = clk_prepare_enable(wsa_priv->wsa_npl_clk);
858 if (ret < 0) {
859 dev_err(dev, "%s:wsa npl_clk enable failed\n",
860 __func__);
861 clk_disable_unprepare(wsa_priv->wsa_core_clk);
862 goto exit;
863 }
864 } else {
865 clk_disable_unprepare(wsa_priv->wsa_npl_clk);
866 clk_disable_unprepare(wsa_priv->wsa_core_clk);
867 }
868exit:
869 return ret;
870}
871
Meng Wang15c825d2018-09-06 10:49:18 +0800872static int wsa_macro_event_handler(struct snd_soc_component *component,
873 u16 event, u32 data)
Laxminath Kasamfb0d6832018-09-22 01:49:52 +0530874{
875 struct device *wsa_dev = NULL;
876 struct wsa_macro_priv *wsa_priv = NULL;
877
Meng Wang15c825d2018-09-06 10:49:18 +0800878 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasamfb0d6832018-09-22 01:49:52 +0530879 return -EINVAL;
880
881 switch (event) {
882 case BOLERO_MACRO_EVT_SSR_DOWN:
883 swrm_wcd_notify(
884 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
885 SWR_DEVICE_SSR_DOWN, NULL);
886 swrm_wcd_notify(
887 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
888 SWR_DEVICE_DOWN, NULL);
889 break;
890 case BOLERO_MACRO_EVT_SSR_UP:
891 swrm_wcd_notify(
892 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
893 SWR_DEVICE_SSR_UP, NULL);
894 break;
895 }
896 return 0;
897}
898
Laxminath Kasam243e2752018-04-12 00:40:19 +0530899static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w,
900 struct snd_kcontrol *kcontrol,
901 int event)
902{
Meng Wang15c825d2018-09-06 10:49:18 +0800903 struct snd_soc_component *component =
904 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530905 struct device *wsa_dev = NULL;
906 struct wsa_macro_priv *wsa_priv = NULL;
907
Meng Wang15c825d2018-09-06 10:49:18 +0800908 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +0530909 return -EINVAL;
910
911 switch (event) {
912 case SND_SOC_DAPM_POST_PMU:
913 if (test_bit(WSA_MACRO_TX0,
914 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
915 dev_dbg(wsa_dev, "%s: spkr1 enabled\n", __func__);
916 /* Enable V&I sensing */
Meng Wang15c825d2018-09-06 10:49:18 +0800917 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530918 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
919 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +0800920 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530921 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
922 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +0800923 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530924 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
925 0x0F, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +0800926 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530927 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
928 0x0F, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +0800929 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530930 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
931 0x10, 0x10);
Meng Wang15c825d2018-09-06 10:49:18 +0800932 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530933 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
934 0x10, 0x10);
Meng Wang15c825d2018-09-06 10:49:18 +0800935 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530936 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
937 0x20, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +0800938 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530939 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
940 0x20, 0x00);
941 }
942 if (test_bit(WSA_MACRO_TX1,
943 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
944 dev_dbg(wsa_dev, "%s: spkr2 enabled\n", __func__);
945 /* Enable V&I sensing */
Meng Wang15c825d2018-09-06 10:49:18 +0800946 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530947 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
948 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +0800949 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530950 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
951 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +0800952 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530953 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
954 0x0F, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +0800955 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530956 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
957 0x0F, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +0800958 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530959 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
960 0x10, 0x10);
Meng Wang15c825d2018-09-06 10:49:18 +0800961 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530962 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
963 0x10, 0x10);
Meng Wang15c825d2018-09-06 10:49:18 +0800964 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530965 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
966 0x20, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +0800967 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530968 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
969 0x20, 0x00);
970 }
971 break;
972 case SND_SOC_DAPM_POST_PMD:
973 if (test_bit(WSA_MACRO_TX0,
974 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
975 /* Disable V&I sensing */
Meng Wang15c825d2018-09-06 10:49:18 +0800976 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530977 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
978 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +0800979 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530980 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
981 0x20, 0x20);
982 dev_dbg(wsa_dev, "%s: spkr1 disabled\n", __func__);
Meng Wang15c825d2018-09-06 10:49:18 +0800983 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530984 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
985 0x10, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +0800986 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530987 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
988 0x10, 0x00);
989 }
990 if (test_bit(WSA_MACRO_TX1,
991 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
992 /* Disable V&I sensing */
993 dev_dbg(wsa_dev, "%s: spkr2 disabled\n", __func__);
Meng Wang15c825d2018-09-06 10:49:18 +0800994 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530995 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
996 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +0800997 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530998 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
999 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +08001000 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301001 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
1002 0x10, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001003 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301004 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
1005 0x10, 0x00);
1006 }
1007 break;
1008 }
1009
1010 return 0;
1011}
1012
1013static int wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w,
1014 struct snd_kcontrol *kcontrol, int event)
1015{
Meng Wang15c825d2018-09-06 10:49:18 +08001016 struct snd_soc_component *component =
1017 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301018 u16 gain_reg;
1019 int offset_val = 0;
1020 int val = 0;
1021
Meng Wang15c825d2018-09-06 10:49:18 +08001022 dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301023
1024 switch (w->reg) {
1025 case BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL:
1026 gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_MIX_CTL;
1027 break;
1028 case BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL:
1029 gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_MIX_CTL;
1030 break;
1031 default:
Meng Wang15c825d2018-09-06 10:49:18 +08001032 dev_err(component->dev, "%s: No gain register avail for %s\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301033 __func__, w->name);
1034 return 0;
1035 }
1036
1037 switch (event) {
1038 case SND_SOC_DAPM_POST_PMU:
Meng Wang15c825d2018-09-06 10:49:18 +08001039 val = snd_soc_component_read32(component, gain_reg);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301040 val += offset_val;
Meng Wang15c825d2018-09-06 10:49:18 +08001041 snd_soc_component_write(component, gain_reg, val);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301042 break;
1043 case SND_SOC_DAPM_POST_PMD:
1044 break;
1045 }
1046
1047 return 0;
1048}
1049
Meng Wang15c825d2018-09-06 10:49:18 +08001050static void wsa_macro_hd2_control(struct snd_soc_component *component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301051 u16 reg, int event)
1052{
1053 u16 hd2_scale_reg;
1054 u16 hd2_enable_reg = 0;
1055
1056 if (reg == BOLERO_CDC_WSA_RX0_RX_PATH_CTL) {
1057 hd2_scale_reg = BOLERO_CDC_WSA_RX0_RX_PATH_SEC3;
1058 hd2_enable_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG0;
1059 }
1060 if (reg == BOLERO_CDC_WSA_RX1_RX_PATH_CTL) {
1061 hd2_scale_reg = BOLERO_CDC_WSA_RX1_RX_PATH_SEC3;
1062 hd2_enable_reg = BOLERO_CDC_WSA_RX1_RX_PATH_CFG0;
1063 }
1064
1065 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001066 snd_soc_component_update_bits(component, hd2_scale_reg,
1067 0x3C, 0x10);
1068 snd_soc_component_update_bits(component, hd2_scale_reg,
1069 0x03, 0x01);
1070 snd_soc_component_update_bits(component, hd2_enable_reg,
1071 0x04, 0x04);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301072 }
1073
1074 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001075 snd_soc_component_update_bits(component, hd2_enable_reg,
1076 0x04, 0x00);
1077 snd_soc_component_update_bits(component, hd2_scale_reg,
1078 0x03, 0x00);
1079 snd_soc_component_update_bits(component, hd2_scale_reg,
1080 0x3C, 0x00);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301081 }
1082}
1083
1084static int wsa_macro_enable_swr(struct snd_soc_dapm_widget *w,
1085 struct snd_kcontrol *kcontrol, int event)
1086{
Meng Wang15c825d2018-09-06 10:49:18 +08001087 struct snd_soc_component *component =
1088 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301089 int ch_cnt;
1090 struct device *wsa_dev = NULL;
1091 struct wsa_macro_priv *wsa_priv = NULL;
1092
Meng Wang15c825d2018-09-06 10:49:18 +08001093 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301094 return -EINVAL;
1095
1096 switch (event) {
1097 case SND_SOC_DAPM_PRE_PMU:
1098 if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) &&
1099 !wsa_priv->rx_0_count)
1100 wsa_priv->rx_0_count++;
1101 if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) &&
1102 !wsa_priv->rx_1_count)
1103 wsa_priv->rx_1_count++;
1104 ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
1105
1106 swrm_wcd_notify(
1107 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
1108 SWR_DEVICE_UP, NULL);
1109 swrm_wcd_notify(
1110 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
1111 SWR_SET_NUM_RX_CH, &ch_cnt);
1112 break;
1113 case SND_SOC_DAPM_POST_PMD:
1114 if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) &&
1115 wsa_priv->rx_0_count)
1116 wsa_priv->rx_0_count--;
1117 if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) &&
1118 wsa_priv->rx_1_count)
1119 wsa_priv->rx_1_count--;
1120 ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
1121
1122 swrm_wcd_notify(
1123 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
1124 SWR_SET_NUM_RX_CH, &ch_cnt);
1125 break;
1126 }
1127 dev_dbg(wsa_priv->dev, "%s: current swr ch cnt: %d\n",
1128 __func__, wsa_priv->rx_0_count + wsa_priv->rx_1_count);
1129
1130 return 0;
1131}
1132
Meng Wang15c825d2018-09-06 10:49:18 +08001133static int wsa_macro_config_compander(struct snd_soc_component *component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301134 int comp, int event)
1135{
1136 u16 comp_ctl0_reg, rx_path_cfg0_reg;
1137 struct device *wsa_dev = NULL;
1138 struct wsa_macro_priv *wsa_priv = NULL;
1139
Meng Wang15c825d2018-09-06 10:49:18 +08001140 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301141 return -EINVAL;
1142
Meng Wang15c825d2018-09-06 10:49:18 +08001143 dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301144 __func__, event, comp + 1, wsa_priv->comp_enabled[comp]);
1145
1146 if (!wsa_priv->comp_enabled[comp])
1147 return 0;
1148
1149 comp_ctl0_reg = BOLERO_CDC_WSA_COMPANDER0_CTL0 +
1150 (comp * WSA_MACRO_RX_COMP_OFFSET);
1151 rx_path_cfg0_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG0 +
1152 (comp * WSA_MACRO_RX_PATH_OFFSET);
1153
1154 if (SND_SOC_DAPM_EVENT_ON(event)) {
1155 /* Enable Compander Clock */
Meng Wang15c825d2018-09-06 10:49:18 +08001156 snd_soc_component_update_bits(component, comp_ctl0_reg,
1157 0x01, 0x01);
1158 snd_soc_component_update_bits(component, comp_ctl0_reg,
1159 0x02, 0x02);
1160 snd_soc_component_update_bits(component, comp_ctl0_reg,
1161 0x02, 0x00);
1162 snd_soc_component_update_bits(component, rx_path_cfg0_reg,
1163 0x02, 0x02);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301164 }
1165
1166 if (SND_SOC_DAPM_EVENT_OFF(event)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001167 snd_soc_component_update_bits(component, comp_ctl0_reg,
1168 0x04, 0x04);
1169 snd_soc_component_update_bits(component, rx_path_cfg0_reg,
1170 0x02, 0x00);
1171 snd_soc_component_update_bits(component, comp_ctl0_reg,
1172 0x02, 0x02);
1173 snd_soc_component_update_bits(component, comp_ctl0_reg,
1174 0x02, 0x00);
1175 snd_soc_component_update_bits(component, comp_ctl0_reg,
1176 0x01, 0x00);
1177 snd_soc_component_update_bits(component, comp_ctl0_reg,
1178 0x04, 0x00);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301179 }
1180
1181 return 0;
1182}
1183
Meng Wang15c825d2018-09-06 10:49:18 +08001184static void wsa_macro_enable_softclip_clk(struct snd_soc_component *component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301185 struct wsa_macro_priv *wsa_priv,
1186 int path,
1187 bool enable)
1188{
1189 u16 softclip_clk_reg = BOLERO_CDC_WSA_SOFTCLIP0_CRC +
1190 (path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
1191 u8 softclip_mux_mask = (1 << path);
1192 u8 softclip_mux_value = (1 << path);
1193
Meng Wang15c825d2018-09-06 10:49:18 +08001194 dev_dbg(component->dev, "%s: path %d, enable %d\n",
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301195 __func__, path, enable);
1196 if (enable) {
1197 if (wsa_priv->softclip_clk_users[path] == 0) {
Meng Wang15c825d2018-09-06 10:49:18 +08001198 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301199 softclip_clk_reg, 0x01, 0x01);
Meng Wang15c825d2018-09-06 10:49:18 +08001200 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301201 BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
1202 softclip_mux_mask, softclip_mux_value);
1203 }
1204 wsa_priv->softclip_clk_users[path]++;
1205 } else {
1206 wsa_priv->softclip_clk_users[path]--;
1207 if (wsa_priv->softclip_clk_users[path] == 0) {
Meng Wang15c825d2018-09-06 10:49:18 +08001208 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301209 softclip_clk_reg, 0x01, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001210 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301211 BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
1212 softclip_mux_mask, 0x00);
1213 }
1214 }
1215}
1216
Meng Wang15c825d2018-09-06 10:49:18 +08001217static int wsa_macro_config_softclip(struct snd_soc_component *component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301218 int path, int event)
1219{
1220 u16 softclip_ctrl_reg = 0;
1221 struct device *wsa_dev = NULL;
1222 struct wsa_macro_priv *wsa_priv = NULL;
1223 int softclip_path = 0;
1224
Meng Wang15c825d2018-09-06 10:49:18 +08001225 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301226 return -EINVAL;
1227
1228 if (path == WSA_MACRO_COMP1)
1229 softclip_path = WSA_MACRO_SOFTCLIP0;
1230 else if (path == WSA_MACRO_COMP2)
1231 softclip_path = WSA_MACRO_SOFTCLIP1;
1232
Meng Wang15c825d2018-09-06 10:49:18 +08001233 dev_dbg(component->dev, "%s: event %d path %d, enabled %d\n",
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301234 __func__, event, softclip_path,
1235 wsa_priv->is_softclip_on[softclip_path]);
1236
1237 if (!wsa_priv->is_softclip_on[softclip_path])
1238 return 0;
1239
1240 softclip_ctrl_reg = BOLERO_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL +
1241 (softclip_path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
1242
1243 if (SND_SOC_DAPM_EVENT_ON(event)) {
1244 /* Enable Softclip clock and mux */
Meng Wang15c825d2018-09-06 10:49:18 +08001245 wsa_macro_enable_softclip_clk(component, wsa_priv,
1246 softclip_path, true);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301247 /* Enable Softclip control */
Meng Wang15c825d2018-09-06 10:49:18 +08001248 snd_soc_component_update_bits(component, softclip_ctrl_reg,
1249 0x01, 0x01);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301250 }
1251
1252 if (SND_SOC_DAPM_EVENT_OFF(event)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001253 snd_soc_component_update_bits(component, softclip_ctrl_reg,
1254 0x01, 0x00);
1255 wsa_macro_enable_softclip_clk(component, wsa_priv,
1256 softclip_path, false);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301257 }
1258
1259 return 0;
1260}
1261
Laxminath Kasam243e2752018-04-12 00:40:19 +05301262static int wsa_macro_interp_get_primary_reg(u16 reg, u16 *ind)
1263{
1264 u16 prim_int_reg = 0;
1265
1266 switch (reg) {
1267 case BOLERO_CDC_WSA_RX0_RX_PATH_CTL:
1268 case BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL:
1269 prim_int_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
1270 *ind = 0;
1271 break;
1272 case BOLERO_CDC_WSA_RX1_RX_PATH_CTL:
1273 case BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL:
1274 prim_int_reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
1275 *ind = 1;
1276 break;
1277 }
1278
1279 return prim_int_reg;
1280}
1281
1282static int wsa_macro_enable_prim_interpolator(
Meng Wang15c825d2018-09-06 10:49:18 +08001283 struct snd_soc_component *component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301284 u16 reg, int event)
1285{
1286 u16 prim_int_reg;
1287 u16 ind = 0;
1288 struct device *wsa_dev = NULL;
1289 struct wsa_macro_priv *wsa_priv = NULL;
1290
Meng Wang15c825d2018-09-06 10:49:18 +08001291 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301292 return -EINVAL;
1293
1294 prim_int_reg = wsa_macro_interp_get_primary_reg(reg, &ind);
1295
1296 switch (event) {
1297 case SND_SOC_DAPM_PRE_PMU:
1298 wsa_priv->prim_int_users[ind]++;
1299 if (wsa_priv->prim_int_users[ind] == 1) {
Meng Wang15c825d2018-09-06 10:49:18 +08001300 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301301 prim_int_reg + WSA_MACRO_RX_PATH_CFG3_OFFSET,
1302 0x03, 0x03);
Meng Wang15c825d2018-09-06 10:49:18 +08001303 snd_soc_component_update_bits(component, prim_int_reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301304 0x10, 0x10);
Meng Wang15c825d2018-09-06 10:49:18 +08001305 wsa_macro_hd2_control(component, prim_int_reg, event);
1306 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301307 prim_int_reg + WSA_MACRO_RX_PATH_DSMDEM_OFFSET,
1308 0x1, 0x1);
Meng Wang15c825d2018-09-06 10:49:18 +08001309 snd_soc_component_update_bits(component, prim_int_reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301310 1 << 0x5, 1 << 0x5);
1311 }
1312 if ((reg != prim_int_reg) &&
Meng Wang15c825d2018-09-06 10:49:18 +08001313 ((snd_soc_component_read32(
1314 component, prim_int_reg)) & 0x10))
1315 snd_soc_component_update_bits(component, reg,
1316 0x10, 0x10);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301317 break;
1318 case SND_SOC_DAPM_POST_PMD:
1319 wsa_priv->prim_int_users[ind]--;
1320 if (wsa_priv->prim_int_users[ind] == 0) {
Meng Wang15c825d2018-09-06 10:49:18 +08001321 snd_soc_component_update_bits(component, prim_int_reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301322 1 << 0x5, 0 << 0x5);
Meng Wang15c825d2018-09-06 10:49:18 +08001323 snd_soc_component_update_bits(component, prim_int_reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301324 0x40, 0x40);
Meng Wang15c825d2018-09-06 10:49:18 +08001325 snd_soc_component_update_bits(component, prim_int_reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301326 0x40, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001327 wsa_macro_hd2_control(component, prim_int_reg, event);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301328 }
1329 break;
1330 }
1331
Meng Wang15c825d2018-09-06 10:49:18 +08001332 dev_dbg(component->dev, "%s: primary interpolator: INT%d, users: %d\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301333 __func__, ind, wsa_priv->prim_int_users[ind]);
1334 return 0;
1335}
1336
1337static int wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w,
1338 struct snd_kcontrol *kcontrol,
1339 int event)
1340{
Meng Wang15c825d2018-09-06 10:49:18 +08001341 struct snd_soc_component *component =
1342 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301343 u16 gain_reg;
1344 u16 reg;
1345 int val;
1346 int offset_val = 0;
1347 struct device *wsa_dev = NULL;
1348 struct wsa_macro_priv *wsa_priv = NULL;
1349
Meng Wang15c825d2018-09-06 10:49:18 +08001350 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301351 return -EINVAL;
1352
Meng Wang15c825d2018-09-06 10:49:18 +08001353 dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301354
1355 if (!(strcmp(w->name, "WSA_RX INT0 INTERP"))) {
1356 reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
1357 gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_CTL;
1358 } else if (!(strcmp(w->name, "WSA_RX INT1 INTERP"))) {
1359 reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
1360 gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_CTL;
1361 } else {
Meng Wang15c825d2018-09-06 10:49:18 +08001362 dev_err(component->dev, "%s: Interpolator reg not found\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301363 __func__);
1364 return -EINVAL;
1365 }
1366
1367 switch (event) {
1368 case SND_SOC_DAPM_PRE_PMU:
1369 /* Reset if needed */
Meng Wang15c825d2018-09-06 10:49:18 +08001370 wsa_macro_enable_prim_interpolator(component, reg, event);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301371 break;
1372 case SND_SOC_DAPM_POST_PMU:
Meng Wang15c825d2018-09-06 10:49:18 +08001373 wsa_macro_config_compander(component, w->shift, event);
1374 wsa_macro_config_softclip(component, w->shift, event);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301375 /* apply gain after int clk is enabled */
Laxminath Kasam21c8b222018-06-21 18:47:22 +05301376 if ((wsa_priv->spkr_gain_offset ==
1377 WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
Laxminath Kasam243e2752018-04-12 00:40:19 +05301378 (wsa_priv->comp_enabled[WSA_MACRO_COMP1] ||
1379 wsa_priv->comp_enabled[WSA_MACRO_COMP2]) &&
1380 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL ||
1381 gain_reg == BOLERO_CDC_WSA_RX1_RX_VOL_CTL)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001382 snd_soc_component_update_bits(component,
1383 BOLERO_CDC_WSA_RX0_RX_PATH_SEC1,
1384 0x01, 0x01);
1385 snd_soc_component_update_bits(component,
1386 BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC0,
1387 0x01, 0x01);
1388 snd_soc_component_update_bits(component,
1389 BOLERO_CDC_WSA_RX1_RX_PATH_SEC1,
1390 0x01, 0x01);
1391 snd_soc_component_update_bits(component,
1392 BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC0,
1393 0x01, 0x01);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301394 offset_val = -2;
1395 }
Meng Wang15c825d2018-09-06 10:49:18 +08001396 val = snd_soc_component_read32(component, gain_reg);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301397 val += offset_val;
Meng Wang15c825d2018-09-06 10:49:18 +08001398 snd_soc_component_write(component, gain_reg, val);
1399 wsa_macro_config_ear_spkr_gain(component, wsa_priv,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301400 event, gain_reg);
1401 break;
1402 case SND_SOC_DAPM_POST_PMD:
Meng Wang15c825d2018-09-06 10:49:18 +08001403 wsa_macro_config_compander(component, w->shift, event);
1404 wsa_macro_config_softclip(component, w->shift, event);
1405 wsa_macro_enable_prim_interpolator(component, reg, event);
Laxminath Kasam21c8b222018-06-21 18:47:22 +05301406 if ((wsa_priv->spkr_gain_offset ==
1407 WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
Laxminath Kasam243e2752018-04-12 00:40:19 +05301408 (wsa_priv->comp_enabled[WSA_MACRO_COMP1] ||
1409 wsa_priv->comp_enabled[WSA_MACRO_COMP2]) &&
1410 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL ||
1411 gain_reg == BOLERO_CDC_WSA_RX1_RX_VOL_CTL)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001412 snd_soc_component_update_bits(component,
1413 BOLERO_CDC_WSA_RX0_RX_PATH_SEC1,
1414 0x01, 0x00);
1415 snd_soc_component_update_bits(component,
1416 BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC0,
1417 0x01, 0x00);
1418 snd_soc_component_update_bits(component,
1419 BOLERO_CDC_WSA_RX1_RX_PATH_SEC1,
1420 0x01, 0x00);
1421 snd_soc_component_update_bits(component,
1422 BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC0,
1423 0x01, 0x00);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301424 offset_val = 2;
Meng Wang15c825d2018-09-06 10:49:18 +08001425 val = snd_soc_component_read32(component, gain_reg);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301426 val += offset_val;
Meng Wang15c825d2018-09-06 10:49:18 +08001427 snd_soc_component_write(component, gain_reg, val);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301428 }
Meng Wang15c825d2018-09-06 10:49:18 +08001429 wsa_macro_config_ear_spkr_gain(component, wsa_priv,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301430 event, gain_reg);
1431 break;
1432 }
1433
1434 return 0;
1435}
1436
Meng Wang15c825d2018-09-06 10:49:18 +08001437static int wsa_macro_config_ear_spkr_gain(struct snd_soc_component *component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301438 struct wsa_macro_priv *wsa_priv,
1439 int event, int gain_reg)
1440{
1441 int comp_gain_offset, val;
1442
1443 switch (wsa_priv->spkr_mode) {
Laxminath Kasam21c8b222018-06-21 18:47:22 +05301444 /* Compander gain in WSA_MACRO_SPKR_MODE1 case is 12 dB */
1445 case WSA_MACRO_SPKR_MODE_1:
Laxminath Kasam243e2752018-04-12 00:40:19 +05301446 comp_gain_offset = -12;
1447 break;
1448 /* Default case compander gain is 15 dB */
1449 default:
1450 comp_gain_offset = -15;
1451 break;
1452 }
1453
1454 switch (event) {
1455 case SND_SOC_DAPM_POST_PMU:
1456 /* Apply ear spkr gain only if compander is enabled */
1457 if (wsa_priv->comp_enabled[WSA_MACRO_COMP1] &&
1458 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL) &&
1459 (wsa_priv->ear_spkr_gain != 0)) {
1460 /* For example, val is -8(-12+5-1) for 4dB of gain */
1461 val = comp_gain_offset + wsa_priv->ear_spkr_gain - 1;
Meng Wang15c825d2018-09-06 10:49:18 +08001462 snd_soc_component_write(component, gain_reg, val);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301463
1464 dev_dbg(wsa_priv->dev, "%s: RX0 Volume %d dB\n",
1465 __func__, val);
1466 }
1467 break;
1468 case SND_SOC_DAPM_POST_PMD:
1469 /*
1470 * Reset RX0 volume to 0 dB if compander is enabled and
1471 * ear_spkr_gain is non-zero.
1472 */
1473 if (wsa_priv->comp_enabled[WSA_MACRO_COMP1] &&
1474 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL) &&
1475 (wsa_priv->ear_spkr_gain != 0)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001476 snd_soc_component_write(component, gain_reg, 0x0);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301477
1478 dev_dbg(wsa_priv->dev, "%s: Reset RX0 Volume to 0 dB\n",
1479 __func__);
1480 }
1481 break;
1482 }
1483
1484 return 0;
1485}
1486
1487static int wsa_macro_spk_boost_event(struct snd_soc_dapm_widget *w,
1488 struct snd_kcontrol *kcontrol,
1489 int event)
1490{
Meng Wang15c825d2018-09-06 10:49:18 +08001491 struct snd_soc_component *component =
1492 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301493 u16 boost_path_ctl, boost_path_cfg1;
1494 u16 reg, reg_mix;
1495
Meng Wang15c825d2018-09-06 10:49:18 +08001496 dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301497
1498 if (!strcmp(w->name, "WSA_RX INT0 CHAIN")) {
1499 boost_path_ctl = BOLERO_CDC_WSA_BOOST0_BOOST_PATH_CTL;
1500 boost_path_cfg1 = BOLERO_CDC_WSA_RX0_RX_PATH_CFG1;
1501 reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
1502 reg_mix = BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL;
1503 } else if (!strcmp(w->name, "WSA_RX INT1 CHAIN")) {
1504 boost_path_ctl = BOLERO_CDC_WSA_BOOST1_BOOST_PATH_CTL;
1505 boost_path_cfg1 = BOLERO_CDC_WSA_RX1_RX_PATH_CFG1;
1506 reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
1507 reg_mix = BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL;
1508 } else {
Meng Wang15c825d2018-09-06 10:49:18 +08001509 dev_err(component->dev, "%s: unknown widget: %s\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301510 __func__, w->name);
1511 return -EINVAL;
1512 }
1513
1514 switch (event) {
1515 case SND_SOC_DAPM_PRE_PMU:
Meng Wang15c825d2018-09-06 10:49:18 +08001516 snd_soc_component_update_bits(component, boost_path_cfg1,
1517 0x01, 0x01);
1518 snd_soc_component_update_bits(component, boost_path_ctl,
1519 0x10, 0x10);
1520 if ((snd_soc_component_read32(component, reg_mix)) & 0x10)
1521 snd_soc_component_update_bits(component, reg_mix,
1522 0x10, 0x00);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301523 break;
Laxminath Kasam0c857002018-07-17 23:47:17 +05301524 case SND_SOC_DAPM_POST_PMU:
Meng Wang15c825d2018-09-06 10:49:18 +08001525 snd_soc_component_update_bits(component, reg, 0x10, 0x00);
Laxminath Kasam0c857002018-07-17 23:47:17 +05301526 break;
Laxminath Kasam243e2752018-04-12 00:40:19 +05301527 case SND_SOC_DAPM_POST_PMD:
Meng Wang15c825d2018-09-06 10:49:18 +08001528 snd_soc_component_update_bits(component, boost_path_ctl,
1529 0x10, 0x00);
1530 snd_soc_component_update_bits(component, boost_path_cfg1,
1531 0x01, 0x00);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301532 break;
1533 }
1534
1535 return 0;
1536}
1537
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301538
1539static int wsa_macro_enable_vbat(struct snd_soc_dapm_widget *w,
1540 struct snd_kcontrol *kcontrol,
1541 int event)
1542{
Meng Wang15c825d2018-09-06 10:49:18 +08001543 struct snd_soc_component *component =
1544 snd_soc_dapm_to_component(w->dapm);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301545 struct device *wsa_dev = NULL;
1546 struct wsa_macro_priv *wsa_priv = NULL;
1547 u16 vbat_path_cfg = 0;
1548 int softclip_path = 0;
1549
Meng Wang15c825d2018-09-06 10:49:18 +08001550 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301551 return -EINVAL;
1552
Meng Wang15c825d2018-09-06 10:49:18 +08001553 dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301554 if (!strcmp(w->name, "WSA_RX INT0 VBAT")) {
1555 vbat_path_cfg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG1;
1556 softclip_path = WSA_MACRO_SOFTCLIP0;
1557 } else if (!strcmp(w->name, "WSA_RX INT1 VBAT")) {
1558 vbat_path_cfg = BOLERO_CDC_WSA_RX1_RX_PATH_CFG1;
1559 softclip_path = WSA_MACRO_SOFTCLIP1;
1560 }
1561
1562 switch (event) {
1563 case SND_SOC_DAPM_PRE_PMU:
1564 /* Enable clock for VBAT block */
Meng Wang15c825d2018-09-06 10:49:18 +08001565 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301566 BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x10);
1567 /* Enable VBAT block */
Meng Wang15c825d2018-09-06 10:49:18 +08001568 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301569 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x01);
1570 /* Update interpolator with 384K path */
Meng Wang15c825d2018-09-06 10:49:18 +08001571 snd_soc_component_update_bits(component, vbat_path_cfg,
1572 0x80, 0x80);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301573 /* Use attenuation mode */
Meng Wang15c825d2018-09-06 10:49:18 +08001574 snd_soc_component_update_bits(component,
1575 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x02, 0x00);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301576 /*
1577 * BCL block needs softclip clock and mux config to be enabled
1578 */
Meng Wang15c825d2018-09-06 10:49:18 +08001579 wsa_macro_enable_softclip_clk(component, wsa_priv,
1580 softclip_path, true);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301581 /* Enable VBAT at channel level */
Meng Wang15c825d2018-09-06 10:49:18 +08001582 snd_soc_component_update_bits(component, vbat_path_cfg,
1583 0x02, 0x02);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301584 /* Set the ATTK1 gain */
Meng Wang15c825d2018-09-06 10:49:18 +08001585 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301586 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
1587 0xFF, 0xFF);
Meng Wang15c825d2018-09-06 10:49:18 +08001588 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301589 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
1590 0xFF, 0x03);
Meng Wang15c825d2018-09-06 10:49:18 +08001591 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301592 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
1593 0xFF, 0x00);
1594 /* Set the ATTK2 gain */
Meng Wang15c825d2018-09-06 10:49:18 +08001595 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301596 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
1597 0xFF, 0xFF);
Meng Wang15c825d2018-09-06 10:49:18 +08001598 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301599 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
1600 0xFF, 0x03);
Meng Wang15c825d2018-09-06 10:49:18 +08001601 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301602 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
1603 0xFF, 0x00);
1604 /* Set the ATTK3 gain */
Meng Wang15c825d2018-09-06 10:49:18 +08001605 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301606 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
1607 0xFF, 0xFF);
Meng Wang15c825d2018-09-06 10:49:18 +08001608 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301609 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
1610 0xFF, 0x03);
Meng Wang15c825d2018-09-06 10:49:18 +08001611 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301612 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
1613 0xFF, 0x00);
1614 break;
1615
1616 case SND_SOC_DAPM_POST_PMD:
Meng Wang15c825d2018-09-06 10:49:18 +08001617 snd_soc_component_update_bits(component, vbat_path_cfg,
1618 0x80, 0x00);
1619 snd_soc_component_update_bits(component,
1620 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
1621 0x02, 0x02);
1622 snd_soc_component_update_bits(component, vbat_path_cfg,
1623 0x02, 0x00);
1624 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301625 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
1626 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001627 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301628 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
1629 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001630 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301631 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
1632 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001633 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301634 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
1635 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001636 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301637 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
1638 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001639 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301640 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
1641 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001642 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301643 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
1644 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001645 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301646 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
1647 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001648 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301649 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
1650 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001651 wsa_macro_enable_softclip_clk(component, wsa_priv,
1652 softclip_path, false);
1653 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301654 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001655 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301656 BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x00);
1657 break;
1658 default:
1659 dev_err(wsa_dev, "%s: Invalid event %d\n", __func__, event);
1660 break;
1661 }
1662 return 0;
1663}
1664
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301665static int wsa_macro_enable_echo(struct snd_soc_dapm_widget *w,
1666 struct snd_kcontrol *kcontrol,
1667 int event)
1668{
Meng Wang15c825d2018-09-06 10:49:18 +08001669 struct snd_soc_component *component =
1670 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301671 struct device *wsa_dev = NULL;
1672 struct wsa_macro_priv *wsa_priv = NULL;
1673 u16 val, ec_tx = 0, ec_hq_reg;
1674
Meng Wang15c825d2018-09-06 10:49:18 +08001675 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301676 return -EINVAL;
1677
1678 dev_dbg(wsa_dev, "%s %d %s\n", __func__, event, w->name);
1679
Meng Wang15c825d2018-09-06 10:49:18 +08001680 val = snd_soc_component_read32(component,
1681 BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0);
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301682 if (!(strcmp(w->name, "WSA RX_MIX EC0_MUX")))
1683 ec_tx = (val & 0x07) - 1;
1684 else
1685 ec_tx = ((val & 0x38) >> 0x3) - 1;
1686
1687 if (ec_tx < 0 || ec_tx >= (WSA_MACRO_RX1 + 1)) {
1688 dev_err(wsa_dev, "%s: EC mix control not set correctly\n",
1689 __func__);
1690 return -EINVAL;
1691 }
1692 if (wsa_priv->ec_hq[ec_tx]) {
Meng Wang15c825d2018-09-06 10:49:18 +08001693 snd_soc_component_update_bits(component,
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301694 BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
1695 0x1 << ec_tx, 0x1 << ec_tx);
1696 ec_hq_reg = BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL +
1697 0x20 * ec_tx;
Meng Wang15c825d2018-09-06 10:49:18 +08001698 snd_soc_component_update_bits(component, ec_hq_reg, 0x01, 0x01);
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301699 ec_hq_reg = BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0 +
1700 0x20 * ec_tx;
1701 /* default set to 48k */
Meng Wang15c825d2018-09-06 10:49:18 +08001702 snd_soc_component_update_bits(component, ec_hq_reg, 0x1E, 0x08);
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301703 }
1704
1705 return 0;
1706}
1707
1708static int wsa_macro_get_ec_hq(struct snd_kcontrol *kcontrol,
1709 struct snd_ctl_elem_value *ucontrol)
1710{
1711
Meng Wang15c825d2018-09-06 10:49:18 +08001712 struct snd_soc_component *component =
1713 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301714 int ec_tx = ((struct soc_multi_mixer_control *)
1715 kcontrol->private_value)->shift;
1716 struct device *wsa_dev = NULL;
1717 struct wsa_macro_priv *wsa_priv = NULL;
1718
Meng Wang15c825d2018-09-06 10:49:18 +08001719 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301720 return -EINVAL;
1721
1722 ucontrol->value.integer.value[0] = wsa_priv->ec_hq[ec_tx];
1723 return 0;
1724}
1725
1726static int wsa_macro_set_ec_hq(struct snd_kcontrol *kcontrol,
1727 struct snd_ctl_elem_value *ucontrol)
1728{
Meng Wang15c825d2018-09-06 10:49:18 +08001729 struct snd_soc_component *component =
1730 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301731 int ec_tx = ((struct soc_multi_mixer_control *)
1732 kcontrol->private_value)->shift;
1733 int value = ucontrol->value.integer.value[0];
1734 struct device *wsa_dev = NULL;
1735 struct wsa_macro_priv *wsa_priv = NULL;
1736
Meng Wang15c825d2018-09-06 10:49:18 +08001737 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301738 return -EINVAL;
1739
1740 dev_dbg(wsa_dev, "%s: enable current %d, new %d\n",
1741 __func__, wsa_priv->ec_hq[ec_tx], value);
1742 wsa_priv->ec_hq[ec_tx] = value;
1743
1744 return 0;
1745}
1746
Laxminath Kasam243e2752018-04-12 00:40:19 +05301747static int wsa_macro_get_compander(struct snd_kcontrol *kcontrol,
1748 struct snd_ctl_elem_value *ucontrol)
1749{
1750
Meng Wang15c825d2018-09-06 10:49:18 +08001751 struct snd_soc_component *component =
1752 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301753 int comp = ((struct soc_multi_mixer_control *)
1754 kcontrol->private_value)->shift;
1755 struct device *wsa_dev = NULL;
1756 struct wsa_macro_priv *wsa_priv = NULL;
1757
Meng Wang15c825d2018-09-06 10:49:18 +08001758 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301759 return -EINVAL;
1760
1761 ucontrol->value.integer.value[0] = wsa_priv->comp_enabled[comp];
1762 return 0;
1763}
1764
1765static int wsa_macro_set_compander(struct snd_kcontrol *kcontrol,
1766 struct snd_ctl_elem_value *ucontrol)
1767{
Meng Wang15c825d2018-09-06 10:49:18 +08001768 struct snd_soc_component *component =
1769 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301770 int comp = ((struct soc_multi_mixer_control *)
1771 kcontrol->private_value)->shift;
1772 int value = ucontrol->value.integer.value[0];
1773 struct device *wsa_dev = NULL;
1774 struct wsa_macro_priv *wsa_priv = NULL;
1775
Meng Wang15c825d2018-09-06 10:49:18 +08001776 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301777 return -EINVAL;
1778
Meng Wang15c825d2018-09-06 10:49:18 +08001779 dev_dbg(component->dev, "%s: Compander %d enable current %d, new %d\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301780 __func__, comp + 1, wsa_priv->comp_enabled[comp], value);
1781 wsa_priv->comp_enabled[comp] = value;
1782
1783 return 0;
1784}
1785
1786static int wsa_macro_ear_spkr_pa_gain_get(struct snd_kcontrol *kcontrol,
1787 struct snd_ctl_elem_value *ucontrol)
1788{
Meng Wang15c825d2018-09-06 10:49:18 +08001789 struct snd_soc_component *component =
1790 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301791 struct device *wsa_dev = NULL;
1792 struct wsa_macro_priv *wsa_priv = NULL;
1793
Meng Wang15c825d2018-09-06 10:49:18 +08001794 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301795 return -EINVAL;
1796
1797 ucontrol->value.integer.value[0] = wsa_priv->ear_spkr_gain;
1798
Meng Wang15c825d2018-09-06 10:49:18 +08001799 dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301800 __func__, ucontrol->value.integer.value[0]);
1801
1802 return 0;
1803}
1804
1805static int wsa_macro_ear_spkr_pa_gain_put(struct snd_kcontrol *kcontrol,
1806 struct snd_ctl_elem_value *ucontrol)
1807{
Meng Wang15c825d2018-09-06 10:49:18 +08001808 struct snd_soc_component *component =
1809 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301810 struct device *wsa_dev = NULL;
1811 struct wsa_macro_priv *wsa_priv = NULL;
1812
Meng Wang15c825d2018-09-06 10:49:18 +08001813 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301814 return -EINVAL;
1815
1816 wsa_priv->ear_spkr_gain = ucontrol->value.integer.value[0];
1817
Meng Wang15c825d2018-09-06 10:49:18 +08001818 dev_dbg(component->dev, "%s: gain = %d\n", __func__,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301819 wsa_priv->ear_spkr_gain);
1820
1821 return 0;
1822}
1823
1824static int wsa_macro_spkr_left_boost_stage_get(struct snd_kcontrol *kcontrol,
1825 struct snd_ctl_elem_value *ucontrol)
1826{
1827 u8 bst_state_max = 0;
Meng Wang15c825d2018-09-06 10:49:18 +08001828 struct snd_soc_component *component =
1829 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301830
Meng Wang15c825d2018-09-06 10:49:18 +08001831 bst_state_max = snd_soc_component_read32(component,
1832 BOLERO_CDC_WSA_BOOST0_BOOST_CTL);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301833 bst_state_max = (bst_state_max & 0x0c) >> 2;
1834 ucontrol->value.integer.value[0] = bst_state_max;
Meng Wang15c825d2018-09-06 10:49:18 +08001835 dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301836 __func__, ucontrol->value.integer.value[0]);
1837
1838 return 0;
1839}
1840
1841static int wsa_macro_spkr_left_boost_stage_put(struct snd_kcontrol *kcontrol,
1842 struct snd_ctl_elem_value *ucontrol)
1843{
1844 u8 bst_state_max;
Meng Wang15c825d2018-09-06 10:49:18 +08001845 struct snd_soc_component *component =
1846 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301847
Meng Wang15c825d2018-09-06 10:49:18 +08001848 dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301849 __func__, ucontrol->value.integer.value[0]);
1850 bst_state_max = ucontrol->value.integer.value[0] << 2;
Meng Wang15c825d2018-09-06 10:49:18 +08001851 snd_soc_component_update_bits(component,
1852 BOLERO_CDC_WSA_BOOST0_BOOST_CTL,
1853 0x0c, bst_state_max);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301854
1855 return 0;
1856}
1857
1858static int wsa_macro_spkr_right_boost_stage_get(struct snd_kcontrol *kcontrol,
1859 struct snd_ctl_elem_value *ucontrol)
1860{
1861 u8 bst_state_max = 0;
Meng Wang15c825d2018-09-06 10:49:18 +08001862 struct snd_soc_component *component =
1863 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301864
Meng Wang15c825d2018-09-06 10:49:18 +08001865 bst_state_max = snd_soc_component_read32(component,
1866 BOLERO_CDC_WSA_BOOST1_BOOST_CTL);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301867 bst_state_max = (bst_state_max & 0x0c) >> 2;
1868 ucontrol->value.integer.value[0] = bst_state_max;
Meng Wang15c825d2018-09-06 10:49:18 +08001869 dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301870 __func__, ucontrol->value.integer.value[0]);
1871
1872 return 0;
1873}
1874
1875static int wsa_macro_spkr_right_boost_stage_put(struct snd_kcontrol *kcontrol,
1876 struct snd_ctl_elem_value *ucontrol)
1877{
1878 u8 bst_state_max;
Meng Wang15c825d2018-09-06 10:49:18 +08001879 struct snd_soc_component *component =
1880 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301881
Meng Wang15c825d2018-09-06 10:49:18 +08001882 dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301883 __func__, ucontrol->value.integer.value[0]);
1884 bst_state_max = ucontrol->value.integer.value[0] << 2;
Meng Wang15c825d2018-09-06 10:49:18 +08001885 snd_soc_component_update_bits(component,
1886 BOLERO_CDC_WSA_BOOST1_BOOST_CTL,
1887 0x0c, bst_state_max);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301888
1889 return 0;
1890}
1891
1892static int wsa_macro_rx_mux_get(struct snd_kcontrol *kcontrol,
1893 struct snd_ctl_elem_value *ucontrol)
1894{
1895 struct snd_soc_dapm_widget *widget =
1896 snd_soc_dapm_kcontrol_widget(kcontrol);
Meng Wang15c825d2018-09-06 10:49:18 +08001897 struct snd_soc_component *component =
1898 snd_soc_dapm_to_component(widget->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301899 struct device *wsa_dev = NULL;
1900 struct wsa_macro_priv *wsa_priv = NULL;
1901
Meng Wang15c825d2018-09-06 10:49:18 +08001902 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301903 return -EINVAL;
1904
1905 ucontrol->value.integer.value[0] =
1906 wsa_priv->rx_port_value[widget->shift];
1907 return 0;
1908}
1909
1910static int wsa_macro_rx_mux_put(struct snd_kcontrol *kcontrol,
1911 struct snd_ctl_elem_value *ucontrol)
1912{
1913 struct snd_soc_dapm_widget *widget =
1914 snd_soc_dapm_kcontrol_widget(kcontrol);
Meng Wang15c825d2018-09-06 10:49:18 +08001915 struct snd_soc_component *component =
1916 snd_soc_dapm_to_component(widget->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301917 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1918 struct snd_soc_dapm_update *update = NULL;
1919 u32 rx_port_value = ucontrol->value.integer.value[0];
1920 u32 bit_input = 0;
1921 u32 aif_rst;
1922 struct device *wsa_dev = NULL;
1923 struct wsa_macro_priv *wsa_priv = NULL;
1924
Meng Wang15c825d2018-09-06 10:49:18 +08001925 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301926 return -EINVAL;
1927
1928 aif_rst = wsa_priv->rx_port_value[widget->shift];
1929 if (!rx_port_value) {
1930 if (aif_rst == 0) {
1931 dev_err(wsa_dev, "%s: AIF reset already\n", __func__);
1932 return 0;
1933 }
1934 }
1935 wsa_priv->rx_port_value[widget->shift] = rx_port_value;
1936
1937 bit_input = widget->shift;
1938 if (widget->shift >= WSA_MACRO_RX_MIX)
1939 bit_input %= WSA_MACRO_RX_MIX;
1940
1941 switch (rx_port_value) {
1942 case 0:
1943 clear_bit(bit_input,
Laxminath Kasam59c7a1d2018-08-09 16:11:17 +05301944 &wsa_priv->active_ch_mask[aif_rst]);
1945 wsa_priv->active_ch_cnt[aif_rst]--;
Laxminath Kasam243e2752018-04-12 00:40:19 +05301946 break;
1947 case 1:
1948 case 2:
1949 set_bit(bit_input,
Laxminath Kasam59c7a1d2018-08-09 16:11:17 +05301950 &wsa_priv->active_ch_mask[rx_port_value]);
1951 wsa_priv->active_ch_cnt[rx_port_value]++;
Laxminath Kasam243e2752018-04-12 00:40:19 +05301952 break;
1953 default:
1954 dev_err(wsa_dev,
1955 "%s: Invalid AIF_ID for WSA RX MUX\n", __func__);
1956 return -EINVAL;
1957 }
1958
1959 snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
1960 rx_port_value, e, update);
1961 return 0;
1962}
1963
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301964static int wsa_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol,
1965 struct snd_ctl_elem_value *ucontrol)
1966{
Meng Wang15c825d2018-09-06 10:49:18 +08001967 struct snd_soc_component *component =
1968 snd_soc_kcontrol_component(kcontrol);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301969
1970 ucontrol->value.integer.value[0] =
Meng Wang15c825d2018-09-06 10:49:18 +08001971 ((snd_soc_component_read32(
1972 component, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG) & 0x04) ?
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301973 1 : 0);
1974
Meng Wang15c825d2018-09-06 10:49:18 +08001975 dev_dbg(component->dev, "%s: value: %lu\n", __func__,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301976 ucontrol->value.integer.value[0]);
1977
1978 return 0;
1979}
1980
1981static int wsa_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol,
1982 struct snd_ctl_elem_value *ucontrol)
1983{
Meng Wang15c825d2018-09-06 10:49:18 +08001984 struct snd_soc_component *component =
1985 snd_soc_kcontrol_component(kcontrol);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301986
Meng Wang15c825d2018-09-06 10:49:18 +08001987 dev_dbg(component->dev, "%s: value: %lu\n", __func__,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301988 ucontrol->value.integer.value[0]);
1989
1990 /* Set Vbat register configuration for GSM mode bit based on value */
1991 if (ucontrol->value.integer.value[0])
Meng Wang15c825d2018-09-06 10:49:18 +08001992 snd_soc_component_update_bits(component,
1993 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
1994 0x04, 0x04);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301995 else
Meng Wang15c825d2018-09-06 10:49:18 +08001996 snd_soc_component_update_bits(component,
1997 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
1998 0x04, 0x00);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301999
2000 return 0;
2001}
2002
2003static int wsa_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol,
2004 struct snd_ctl_elem_value *ucontrol)
2005{
Meng Wang15c825d2018-09-06 10:49:18 +08002006 struct snd_soc_component *component =
2007 snd_soc_kcontrol_component(kcontrol);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302008 struct device *wsa_dev = NULL;
2009 struct wsa_macro_priv *wsa_priv = NULL;
2010 int path = ((struct soc_multi_mixer_control *)
2011 kcontrol->private_value)->shift;
2012
Meng Wang15c825d2018-09-06 10:49:18 +08002013 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302014 return -EINVAL;
2015
2016 ucontrol->value.integer.value[0] = wsa_priv->is_softclip_on[path];
2017
Meng Wang15c825d2018-09-06 10:49:18 +08002018 dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302019 __func__, ucontrol->value.integer.value[0]);
2020
2021 return 0;
2022}
2023
2024static int wsa_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol,
2025 struct snd_ctl_elem_value *ucontrol)
2026{
Meng Wang15c825d2018-09-06 10:49:18 +08002027 struct snd_soc_component *component =
2028 snd_soc_kcontrol_component(kcontrol);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302029 struct device *wsa_dev = NULL;
2030 struct wsa_macro_priv *wsa_priv = NULL;
2031 int path = ((struct soc_multi_mixer_control *)
2032 kcontrol->private_value)->shift;
2033
Meng Wang15c825d2018-09-06 10:49:18 +08002034 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302035 return -EINVAL;
2036
2037 wsa_priv->is_softclip_on[path] = ucontrol->value.integer.value[0];
2038
Meng Wang15c825d2018-09-06 10:49:18 +08002039 dev_dbg(component->dev, "%s: soft clip enable for %d: %d\n", __func__,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302040 path, wsa_priv->is_softclip_on[path]);
2041
2042 return 0;
2043}
2044
Laxminath Kasam243e2752018-04-12 00:40:19 +05302045static const struct snd_kcontrol_new wsa_macro_snd_controls[] = {
2046 SOC_ENUM_EXT("EAR SPKR PA Gain", wsa_macro_ear_spkr_pa_gain_enum,
2047 wsa_macro_ear_spkr_pa_gain_get,
2048 wsa_macro_ear_spkr_pa_gain_put),
2049 SOC_ENUM_EXT("SPKR Left Boost Max State",
2050 wsa_macro_spkr_boost_stage_enum,
2051 wsa_macro_spkr_left_boost_stage_get,
2052 wsa_macro_spkr_left_boost_stage_put),
2053 SOC_ENUM_EXT("SPKR Right Boost Max State",
2054 wsa_macro_spkr_boost_stage_enum,
2055 wsa_macro_spkr_right_boost_stage_get,
2056 wsa_macro_spkr_right_boost_stage_put),
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302057 SOC_ENUM_EXT("GSM mode Enable", wsa_macro_vbat_bcl_gsm_mode_enum,
2058 wsa_macro_vbat_bcl_gsm_mode_func_get,
2059 wsa_macro_vbat_bcl_gsm_mode_func_put),
2060 SOC_SINGLE_EXT("WSA_Softclip0 Enable", SND_SOC_NOPM,
2061 WSA_MACRO_SOFTCLIP0, 1, 0,
2062 wsa_macro_soft_clip_enable_get,
2063 wsa_macro_soft_clip_enable_put),
2064 SOC_SINGLE_EXT("WSA_Softclip1 Enable", SND_SOC_NOPM,
2065 WSA_MACRO_SOFTCLIP1, 1, 0,
2066 wsa_macro_soft_clip_enable_get,
2067 wsa_macro_soft_clip_enable_put),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302068 SOC_SINGLE_SX_TLV("WSA_RX0 Digital Volume",
2069 BOLERO_CDC_WSA_RX0_RX_VOL_CTL,
2070 0, -84, 40, digital_gain),
2071 SOC_SINGLE_SX_TLV("WSA_RX1 Digital Volume",
2072 BOLERO_CDC_WSA_RX1_RX_VOL_CTL,
2073 0, -84, 40, digital_gain),
2074 SOC_SINGLE_EXT("WSA_COMP1 Switch", SND_SOC_NOPM, WSA_MACRO_COMP1, 1, 0,
2075 wsa_macro_get_compander, wsa_macro_set_compander),
2076 SOC_SINGLE_EXT("WSA_COMP2 Switch", SND_SOC_NOPM, WSA_MACRO_COMP2, 1, 0,
2077 wsa_macro_get_compander, wsa_macro_set_compander),
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05302078 SOC_SINGLE_EXT("WSA_RX0 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX0,
2079 1, 0, wsa_macro_get_ec_hq, wsa_macro_set_ec_hq),
2080 SOC_SINGLE_EXT("WSA_RX1 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX1,
2081 1, 0, wsa_macro_get_ec_hq, wsa_macro_set_ec_hq),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302082};
2083
2084static const struct soc_enum rx_mux_enum =
2085 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_mux_text), rx_mux_text);
2086
2087static const struct snd_kcontrol_new rx_mux[WSA_MACRO_RX_MAX] = {
2088 SOC_DAPM_ENUM_EXT("WSA RX0 Mux", rx_mux_enum,
2089 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2090 SOC_DAPM_ENUM_EXT("WSA RX1 Mux", rx_mux_enum,
2091 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2092 SOC_DAPM_ENUM_EXT("WSA RX_MIX0 Mux", rx_mux_enum,
2093 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2094 SOC_DAPM_ENUM_EXT("WSA RX_MIX1 Mux", rx_mux_enum,
2095 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2096};
2097
2098static int wsa_macro_vi_feed_mixer_get(struct snd_kcontrol *kcontrol,
2099 struct snd_ctl_elem_value *ucontrol)
2100{
2101 struct snd_soc_dapm_widget *widget =
2102 snd_soc_dapm_kcontrol_widget(kcontrol);
Meng Wang15c825d2018-09-06 10:49:18 +08002103 struct snd_soc_component *component =
2104 snd_soc_dapm_to_component(widget->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302105 struct soc_multi_mixer_control *mixer =
2106 ((struct soc_multi_mixer_control *)kcontrol->private_value);
2107 u32 dai_id = widget->shift;
2108 u32 spk_tx_id = mixer->shift;
2109 struct device *wsa_dev = NULL;
2110 struct wsa_macro_priv *wsa_priv = NULL;
2111
Meng Wang15c825d2018-09-06 10:49:18 +08002112 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05302113 return -EINVAL;
2114
2115 if (test_bit(spk_tx_id, &wsa_priv->active_ch_mask[dai_id]))
2116 ucontrol->value.integer.value[0] = 1;
2117 else
2118 ucontrol->value.integer.value[0] = 0;
2119
2120 return 0;
2121}
2122
2123static int wsa_macro_vi_feed_mixer_put(struct snd_kcontrol *kcontrol,
2124 struct snd_ctl_elem_value *ucontrol)
2125{
2126 struct snd_soc_dapm_widget *widget =
2127 snd_soc_dapm_kcontrol_widget(kcontrol);
Meng Wang15c825d2018-09-06 10:49:18 +08002128 struct snd_soc_component *component =
2129 snd_soc_dapm_to_component(widget->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302130 struct soc_multi_mixer_control *mixer =
2131 ((struct soc_multi_mixer_control *)kcontrol->private_value);
2132 u32 spk_tx_id = mixer->shift;
2133 u32 enable = ucontrol->value.integer.value[0];
2134 struct device *wsa_dev = NULL;
2135 struct wsa_macro_priv *wsa_priv = NULL;
2136
Meng Wang15c825d2018-09-06 10:49:18 +08002137 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05302138 return -EINVAL;
2139
2140 wsa_priv->vi_feed_value = ucontrol->value.integer.value[0];
2141
2142 if (enable) {
2143 if (spk_tx_id == WSA_MACRO_TX0 &&
2144 !test_bit(WSA_MACRO_TX0,
2145 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2146 set_bit(WSA_MACRO_TX0,
2147 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2148 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]++;
2149 }
2150 if (spk_tx_id == WSA_MACRO_TX1 &&
2151 !test_bit(WSA_MACRO_TX1,
2152 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2153 set_bit(WSA_MACRO_TX1,
2154 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2155 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]++;
2156 }
2157 } else {
2158 if (spk_tx_id == WSA_MACRO_TX0 &&
2159 test_bit(WSA_MACRO_TX0,
2160 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2161 clear_bit(WSA_MACRO_TX0,
2162 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2163 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]--;
2164 }
2165 if (spk_tx_id == WSA_MACRO_TX1 &&
2166 test_bit(WSA_MACRO_TX1,
2167 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2168 clear_bit(WSA_MACRO_TX1,
2169 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2170 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]--;
2171 }
2172 }
2173 snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
2174
2175 return 0;
2176}
2177
2178static const struct snd_kcontrol_new aif_vi_mixer[] = {
2179 SOC_SINGLE_EXT("WSA_SPKR_VI_1", SND_SOC_NOPM, WSA_MACRO_TX0, 1, 0,
2180 wsa_macro_vi_feed_mixer_get,
2181 wsa_macro_vi_feed_mixer_put),
2182 SOC_SINGLE_EXT("WSA_SPKR_VI_2", SND_SOC_NOPM, WSA_MACRO_TX1, 1, 0,
2183 wsa_macro_vi_feed_mixer_get,
2184 wsa_macro_vi_feed_mixer_put),
2185};
2186
2187static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = {
2188 SND_SOC_DAPM_AIF_IN("WSA AIF1 PB", "WSA_AIF1 Playback", 0,
2189 SND_SOC_NOPM, 0, 0),
2190
2191 SND_SOC_DAPM_AIF_IN("WSA AIF_MIX1 PB", "WSA_AIF_MIX1 Playback", 0,
2192 SND_SOC_NOPM, 0, 0),
2193
2194 SND_SOC_DAPM_AIF_OUT_E("WSA AIF_VI", "WSA_AIF_VI Capture", 0,
2195 SND_SOC_NOPM, WSA_MACRO_AIF_VI, 0,
2196 wsa_macro_enable_vi_feedback,
2197 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2198
2199 SND_SOC_DAPM_AIF_OUT("WSA AIF_ECHO", "WSA_AIF_ECHO Capture", 0,
2200 SND_SOC_NOPM, 0, 0),
2201
2202 SND_SOC_DAPM_MIXER("WSA_AIF_VI Mixer", SND_SOC_NOPM, WSA_MACRO_AIF_VI,
2203 0, aif_vi_mixer, ARRAY_SIZE(aif_vi_mixer)),
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05302204 SND_SOC_DAPM_MUX_E("WSA RX_MIX EC0_MUX", SND_SOC_NOPM,
2205 WSA_MACRO_EC0_MUX, 0,
2206 &rx_mix_ec0_mux, wsa_macro_enable_echo,
2207 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2208 SND_SOC_DAPM_MUX_E("WSA RX_MIX EC1_MUX", SND_SOC_NOPM,
2209 WSA_MACRO_EC1_MUX, 0,
2210 &rx_mix_ec1_mux, wsa_macro_enable_echo,
2211 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302212
2213 SND_SOC_DAPM_MUX("WSA RX0 MUX", SND_SOC_NOPM, WSA_MACRO_RX0, 0,
2214 &rx_mux[WSA_MACRO_RX0]),
2215 SND_SOC_DAPM_MUX("WSA RX1 MUX", SND_SOC_NOPM, WSA_MACRO_RX1, 0,
2216 &rx_mux[WSA_MACRO_RX1]),
2217 SND_SOC_DAPM_MUX("WSA RX_MIX0 MUX", SND_SOC_NOPM, WSA_MACRO_RX_MIX0, 0,
2218 &rx_mux[WSA_MACRO_RX_MIX0]),
2219 SND_SOC_DAPM_MUX("WSA RX_MIX1 MUX", SND_SOC_NOPM, WSA_MACRO_RX_MIX1, 0,
2220 &rx_mux[WSA_MACRO_RX_MIX1]),
2221
2222 SND_SOC_DAPM_MIXER("WSA RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
2223 SND_SOC_DAPM_MIXER("WSA RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
2224 SND_SOC_DAPM_MIXER("WSA RX_MIX0", SND_SOC_NOPM, 0, 0, NULL, 0),
2225 SND_SOC_DAPM_MIXER("WSA RX_MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
2226
2227 SND_SOC_DAPM_MUX_E("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0,
2228 &rx0_prim_inp0_mux, wsa_macro_enable_swr,
2229 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2230 SND_SOC_DAPM_MUX_E("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0,
2231 &rx0_prim_inp1_mux, wsa_macro_enable_swr,
2232 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2233 SND_SOC_DAPM_MUX_E("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0,
2234 &rx0_prim_inp2_mux, wsa_macro_enable_swr,
2235 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2236 SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM, 0, 0,
2237 &rx0_mix_mux, wsa_macro_enable_mix_path,
2238 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2239 SND_SOC_DAPM_MUX_E("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0,
2240 &rx1_prim_inp0_mux, wsa_macro_enable_swr,
2241 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2242 SND_SOC_DAPM_MUX_E("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0,
2243 &rx1_prim_inp1_mux, wsa_macro_enable_swr,
2244 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2245 SND_SOC_DAPM_MUX_E("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0,
2246 &rx1_prim_inp2_mux, wsa_macro_enable_swr,
2247 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2248 SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM, 0, 0,
2249 &rx1_mix_mux, wsa_macro_enable_mix_path,
2250 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2251 SND_SOC_DAPM_MIXER("WSA_RX INT0 MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2252 SND_SOC_DAPM_MIXER("WSA_RX INT1 MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2253 SND_SOC_DAPM_MIXER("WSA_RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2254 SND_SOC_DAPM_MIXER("WSA_RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2255
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302256 SND_SOC_DAPM_MUX_E("WSA_RX0 INT0 SIDETONE MIX",
2257 BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 4, 0,
2258 &rx0_sidetone_mix_mux, wsa_macro_enable_swr,
2259 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2260 SND_SOC_DAPM_INPUT("WSA SRC0_INP"),
2261
2262 SND_SOC_DAPM_INPUT("WSA_TX DEC0_INP"),
2263 SND_SOC_DAPM_INPUT("WSA_TX DEC1_INP"),
2264
Laxminath Kasam243e2752018-04-12 00:40:19 +05302265 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 INTERP", SND_SOC_NOPM,
2266 WSA_MACRO_COMP1, 0, NULL, 0, wsa_macro_enable_interpolator,
2267 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2268 SND_SOC_DAPM_POST_PMD),
2269 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 INTERP", SND_SOC_NOPM,
2270 WSA_MACRO_COMP2, 0, NULL, 0, wsa_macro_enable_interpolator,
2271 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2272 SND_SOC_DAPM_POST_PMD),
2273
2274 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 CHAIN", SND_SOC_NOPM, 0, 0,
2275 NULL, 0, wsa_macro_spk_boost_event,
Laxminath Kasam0c857002018-07-17 23:47:17 +05302276 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2277 SND_SOC_DAPM_POST_PMD),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302278 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 CHAIN", SND_SOC_NOPM, 0, 0,
2279 NULL, 0, wsa_macro_spk_boost_event,
Laxminath Kasam0c857002018-07-17 23:47:17 +05302280 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2281 SND_SOC_DAPM_POST_PMD),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302282
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302283 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 VBAT", SND_SOC_NOPM,
2284 0, 0, wsa_int0_vbat_mix_switch,
2285 ARRAY_SIZE(wsa_int0_vbat_mix_switch),
2286 wsa_macro_enable_vbat,
2287 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2288 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 VBAT", SND_SOC_NOPM,
2289 0, 0, wsa_int1_vbat_mix_switch,
2290 ARRAY_SIZE(wsa_int1_vbat_mix_switch),
2291 wsa_macro_enable_vbat,
2292 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2293
Laxminath Kasam243e2752018-04-12 00:40:19 +05302294 SND_SOC_DAPM_INPUT("VIINPUT_WSA"),
2295
2296 SND_SOC_DAPM_OUTPUT("WSA_SPK1 OUT"),
2297 SND_SOC_DAPM_OUTPUT("WSA_SPK2 OUT"),
2298
2299 SND_SOC_DAPM_SUPPLY_S("WSA_MCLK", 0, SND_SOC_NOPM, 0, 0,
2300 wsa_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2301};
2302
2303static const struct snd_soc_dapm_route wsa_audio_map[] = {
2304 /* VI Feedback */
2305 {"WSA_AIF_VI Mixer", "WSA_SPKR_VI_1", "VIINPUT_WSA"},
2306 {"WSA_AIF_VI Mixer", "WSA_SPKR_VI_2", "VIINPUT_WSA"},
2307 {"WSA AIF_VI", NULL, "WSA_AIF_VI Mixer"},
2308 {"WSA AIF_VI", NULL, "WSA_MCLK"},
2309
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05302310 {"WSA RX_MIX EC0_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
2311 {"WSA RX_MIX EC1_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
2312 {"WSA RX_MIX EC0_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
2313 {"WSA RX_MIX EC1_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
2314 {"WSA AIF_ECHO", NULL, "WSA RX_MIX EC0_MUX"},
2315 {"WSA AIF_ECHO", NULL, "WSA RX_MIX EC1_MUX"},
2316 {"WSA AIF_ECHO", NULL, "WSA_MCLK"},
2317
Laxminath Kasam243e2752018-04-12 00:40:19 +05302318 {"WSA AIF1 PB", NULL, "WSA_MCLK"},
2319 {"WSA AIF_MIX1 PB", NULL, "WSA_MCLK"},
2320
2321 {"WSA RX0 MUX", "AIF1_PB", "WSA AIF1 PB"},
2322 {"WSA RX1 MUX", "AIF1_PB", "WSA AIF1 PB"},
2323 {"WSA RX_MIX0 MUX", "AIF1_PB", "WSA AIF1 PB"},
2324 {"WSA RX_MIX1 MUX", "AIF1_PB", "WSA AIF1 PB"},
2325
2326 {"WSA RX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2327 {"WSA RX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2328 {"WSA RX_MIX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2329 {"WSA RX_MIX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2330
2331 {"WSA RX0", NULL, "WSA RX0 MUX"},
2332 {"WSA RX1", NULL, "WSA RX1 MUX"},
2333 {"WSA RX_MIX0", NULL, "WSA RX_MIX0 MUX"},
2334 {"WSA RX_MIX1", NULL, "WSA RX_MIX1 MUX"},
2335
2336 {"WSA_RX0 INP0", "RX0", "WSA RX0"},
2337 {"WSA_RX0 INP0", "RX1", "WSA RX1"},
2338 {"WSA_RX0 INP0", "RX_MIX0", "WSA RX_MIX0"},
2339 {"WSA_RX0 INP0", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302340 {"WSA_RX0 INP0", "DEC0", "WSA_TX DEC0_INP"},
2341 {"WSA_RX0 INP0", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302342 {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP0"},
2343
2344 {"WSA_RX0 INP1", "RX0", "WSA RX0"},
2345 {"WSA_RX0 INP1", "RX1", "WSA RX1"},
2346 {"WSA_RX0 INP1", "RX_MIX0", "WSA RX_MIX0"},
2347 {"WSA_RX0 INP1", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302348 {"WSA_RX0 INP1", "DEC0", "WSA_TX DEC0_INP"},
2349 {"WSA_RX0 INP1", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302350 {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP1"},
2351
2352 {"WSA_RX0 INP2", "RX0", "WSA RX0"},
2353 {"WSA_RX0 INP2", "RX1", "WSA RX1"},
2354 {"WSA_RX0 INP2", "RX_MIX0", "WSA RX_MIX0"},
2355 {"WSA_RX0 INP2", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302356 {"WSA_RX0 INP2", "DEC0", "WSA_TX DEC0_INP"},
2357 {"WSA_RX0 INP2", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302358 {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP2"},
2359
2360 {"WSA_RX0 MIX INP", "RX0", "WSA RX0"},
2361 {"WSA_RX0 MIX INP", "RX1", "WSA RX1"},
2362 {"WSA_RX0 MIX INP", "RX_MIX0", "WSA RX_MIX0"},
2363 {"WSA_RX0 MIX INP", "RX_MIX1", "WSA RX_MIX1"},
2364 {"WSA_RX INT0 SEC MIX", NULL, "WSA_RX0 MIX INP"},
2365
2366 {"WSA_RX INT0 SEC MIX", NULL, "WSA_RX INT0 MIX"},
2367 {"WSA_RX INT0 INTERP", NULL, "WSA_RX INT0 SEC MIX"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302368 {"WSA_RX0 INT0 SIDETONE MIX", "SRC0", "WSA SRC0_INP"},
2369 {"WSA_RX INT0 INTERP", NULL, "WSA_RX0 INT0 SIDETONE MIX"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302370 {"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 INTERP"},
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302371
2372 {"WSA_RX INT0 VBAT", "WSA RX0 VBAT Enable", "WSA_RX INT0 INTERP"},
2373 {"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 VBAT"},
2374
Laxminath Kasam243e2752018-04-12 00:40:19 +05302375 {"WSA_SPK1 OUT", NULL, "WSA_RX INT0 CHAIN"},
Laxminath Kasamfc281ad2018-08-06 20:19:40 +05302376 {"WSA_SPK1 OUT", NULL, "WSA_MCLK"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302377
2378 {"WSA_RX1 INP0", "RX0", "WSA RX0"},
2379 {"WSA_RX1 INP0", "RX1", "WSA RX1"},
2380 {"WSA_RX1 INP0", "RX_MIX0", "WSA RX_MIX0"},
2381 {"WSA_RX1 INP0", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302382 {"WSA_RX1 INP0", "DEC0", "WSA_TX DEC0_INP"},
2383 {"WSA_RX1 INP0", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302384 {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP0"},
2385
2386 {"WSA_RX1 INP1", "RX0", "WSA RX0"},
2387 {"WSA_RX1 INP1", "RX1", "WSA RX1"},
2388 {"WSA_RX1 INP1", "RX_MIX0", "WSA RX_MIX0"},
2389 {"WSA_RX1 INP1", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302390 {"WSA_RX1 INP1", "DEC0", "WSA_TX DEC0_INP"},
2391 {"WSA_RX1 INP1", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302392 {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP1"},
2393
2394 {"WSA_RX1 INP2", "RX0", "WSA RX0"},
2395 {"WSA_RX1 INP2", "RX1", "WSA RX1"},
2396 {"WSA_RX1 INP2", "RX_MIX0", "WSA RX_MIX0"},
2397 {"WSA_RX1 INP2", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302398 {"WSA_RX1 INP2", "DEC0", "WSA_TX DEC0_INP"},
2399 {"WSA_RX1 INP2", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302400 {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP2"},
2401
2402 {"WSA_RX1 MIX INP", "RX0", "WSA RX0"},
2403 {"WSA_RX1 MIX INP", "RX1", "WSA RX1"},
2404 {"WSA_RX1 MIX INP", "RX_MIX0", "WSA RX_MIX0"},
2405 {"WSA_RX1 MIX INP", "RX_MIX1", "WSA RX_MIX1"},
2406 {"WSA_RX INT1 SEC MIX", NULL, "WSA_RX1 MIX INP"},
2407
2408 {"WSA_RX INT1 SEC MIX", NULL, "WSA_RX INT1 MIX"},
2409 {"WSA_RX INT1 INTERP", NULL, "WSA_RX INT1 SEC MIX"},
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302410
2411 {"WSA_RX INT1 VBAT", "WSA RX1 VBAT Enable", "WSA_RX INT1 INTERP"},
2412 {"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 VBAT"},
2413
Laxminath Kasam243e2752018-04-12 00:40:19 +05302414 {"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 INTERP"},
2415 {"WSA_SPK2 OUT", NULL, "WSA_RX INT1 CHAIN"},
Laxminath Kasamfc281ad2018-08-06 20:19:40 +05302416 {"WSA_SPK2 OUT", NULL, "WSA_MCLK"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302417};
2418
2419static const struct wsa_macro_reg_mask_val wsa_macro_reg_init[] = {
2420 {BOLERO_CDC_WSA_BOOST0_BOOST_CFG1, 0x3F, 0x12},
2421 {BOLERO_CDC_WSA_BOOST0_BOOST_CFG2, 0x1C, 0x08},
2422 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x1E, 0x18},
2423 {BOLERO_CDC_WSA_BOOST1_BOOST_CFG1, 0x3F, 0x12},
2424 {BOLERO_CDC_WSA_BOOST1_BOOST_CFG2, 0x1C, 0x08},
2425 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x1E, 0x18},
2426 {BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x70, 0x58},
2427 {BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x70, 0x58},
2428 {BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08},
2429 {BOLERO_CDC_WSA_RX1_RX_PATH_CFG1, 0x08, 0x08},
2430 {BOLERO_CDC_WSA_TOP_TOP_CFG1, 0x02, 0x02},
2431 {BOLERO_CDC_WSA_TOP_TOP_CFG1, 0x01, 0x01},
2432 {BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2433 {BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2434 {BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2435 {BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2436 {BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80},
2437 {BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x80},
2438 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01},
2439 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01},
2440 {BOLERO_CDC_WSA_RX0_RX_PATH_CFG0, 0x01, 0x01},
2441 {BOLERO_CDC_WSA_RX1_RX_PATH_CFG0, 0x01, 0x01},
2442 {BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CFG, 0x01, 0x01},
2443 {BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CFG, 0x01, 0x01},
2444};
2445
Meng Wang15c825d2018-09-06 10:49:18 +08002446static void wsa_macro_init_bcl_pmic_reg(struct snd_soc_component *component)
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302447{
2448 struct device *wsa_dev = NULL;
2449 struct wsa_macro_priv *wsa_priv = NULL;
2450
Meng Wang15c825d2018-09-06 10:49:18 +08002451 if (!component) {
2452 pr_err("%s: NULL component pointer!\n", __func__);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302453 return;
2454 }
2455
Meng Wang15c825d2018-09-06 10:49:18 +08002456 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302457 return;
2458
2459 switch (wsa_priv->bcl_pmic_params.id) {
2460 case 0:
2461 /* Enable ID0 to listen to respective PMIC group interrupts */
Meng Wang15c825d2018-09-06 10:49:18 +08002462 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302463 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x02, 0x02);
2464 /* Update MC_SID0 */
Meng Wang15c825d2018-09-06 10:49:18 +08002465 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302466 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1, 0x0F,
2467 wsa_priv->bcl_pmic_params.sid);
2468 /* Update MC_PPID0 */
Meng Wang15c825d2018-09-06 10:49:18 +08002469 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302470 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2, 0xFF,
2471 wsa_priv->bcl_pmic_params.ppid);
2472 break;
2473 case 1:
2474 /* Enable ID1 to listen to respective PMIC group interrupts */
Meng Wang15c825d2018-09-06 10:49:18 +08002475 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302476 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x01, 0x01);
2477 /* Update MC_SID1 */
Meng Wang15c825d2018-09-06 10:49:18 +08002478 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302479 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3, 0x0F,
2480 wsa_priv->bcl_pmic_params.sid);
2481 /* Update MC_PPID1 */
Meng Wang15c825d2018-09-06 10:49:18 +08002482 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302483 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4, 0xFF,
2484 wsa_priv->bcl_pmic_params.ppid);
2485 break;
2486 default:
2487 dev_err(wsa_dev, "%s: PMIC ID is invalid %d\n",
2488 __func__, wsa_priv->bcl_pmic_params.id);
2489 break;
2490 }
2491}
2492
Meng Wang15c825d2018-09-06 10:49:18 +08002493static void wsa_macro_init_reg(struct snd_soc_component *component)
Laxminath Kasam243e2752018-04-12 00:40:19 +05302494{
2495 int i;
2496
2497 for (i = 0; i < ARRAY_SIZE(wsa_macro_reg_init); i++)
Meng Wang15c825d2018-09-06 10:49:18 +08002498 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05302499 wsa_macro_reg_init[i].reg,
2500 wsa_macro_reg_init[i].mask,
2501 wsa_macro_reg_init[i].val);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302502
Meng Wang15c825d2018-09-06 10:49:18 +08002503 wsa_macro_init_bcl_pmic_reg(component);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302504}
2505
2506static int wsa_swrm_clock(void *handle, bool enable)
2507{
2508 struct wsa_macro_priv *wsa_priv = (struct wsa_macro_priv *) handle;
2509 struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302510 int ret = 0;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302511
Tanya Dixitab8eba82018-10-05 15:07:37 +05302512 if (regmap == NULL) {
2513 dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
2514 return -EINVAL;
2515 }
2516
Laxminath Kasam243e2752018-04-12 00:40:19 +05302517 mutex_lock(&wsa_priv->swr_clk_lock);
2518
2519 dev_dbg(wsa_priv->dev, "%s: swrm clock %s\n",
2520 __func__, (enable ? "enable" : "disable"));
2521 if (enable) {
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302522 if (wsa_priv->swr_clk_users == 0) {
2523 ret = wsa_macro_mclk_enable(wsa_priv, 1, true);
2524 if (ret < 0) {
2525 dev_err(wsa_priv->dev,
2526 "%s: wsa request clock enable failed\n",
2527 __func__);
2528 goto exit;
2529 }
Laxminath Kasam243e2752018-04-12 00:40:19 +05302530 regmap_update_bits(regmap,
2531 BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
2532 0x01, 0x01);
2533 regmap_update_bits(regmap,
2534 BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
2535 0x1C, 0x0C);
2536 msm_cdc_pinctrl_select_active_state(
2537 wsa_priv->wsa_swr_gpio_p);
2538 }
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302539 wsa_priv->swr_clk_users++;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302540 } else {
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302541 if (wsa_priv->swr_clk_users <= 0) {
2542 dev_err(wsa_priv->dev, "%s: clock already disabled\n",
2543 __func__);
2544 wsa_priv->swr_clk_users = 0;
2545 goto exit;
2546 }
Laxminath Kasam243e2752018-04-12 00:40:19 +05302547 wsa_priv->swr_clk_users--;
2548 if (wsa_priv->swr_clk_users == 0) {
2549 regmap_update_bits(regmap,
2550 BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
2551 0x01, 0x00);
2552 msm_cdc_pinctrl_select_sleep_state(
2553 wsa_priv->wsa_swr_gpio_p);
2554 wsa_macro_mclk_enable(wsa_priv, 0, true);
2555 }
2556 }
2557 dev_dbg(wsa_priv->dev, "%s: swrm clock users %d\n",
2558 __func__, wsa_priv->swr_clk_users);
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302559exit:
Laxminath Kasam243e2752018-04-12 00:40:19 +05302560 mutex_unlock(&wsa_priv->swr_clk_lock);
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302561 return ret;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302562}
2563
Meng Wang15c825d2018-09-06 10:49:18 +08002564static int wsa_macro_init(struct snd_soc_component *component)
Laxminath Kasam243e2752018-04-12 00:40:19 +05302565{
Meng Wang15c825d2018-09-06 10:49:18 +08002566 struct snd_soc_dapm_context *dapm =
2567 snd_soc_component_get_dapm(component);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302568 int ret;
2569 struct device *wsa_dev = NULL;
2570 struct wsa_macro_priv *wsa_priv = NULL;
2571
Meng Wang15c825d2018-09-06 10:49:18 +08002572 wsa_dev = bolero_get_device_ptr(component->dev, WSA_MACRO);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302573 if (!wsa_dev) {
Meng Wang15c825d2018-09-06 10:49:18 +08002574 dev_err(component->dev,
Laxminath Kasam243e2752018-04-12 00:40:19 +05302575 "%s: null device for macro!\n", __func__);
2576 return -EINVAL;
2577 }
2578 wsa_priv = dev_get_drvdata(wsa_dev);
2579 if (!wsa_priv) {
Meng Wang15c825d2018-09-06 10:49:18 +08002580 dev_err(component->dev,
Laxminath Kasam243e2752018-04-12 00:40:19 +05302581 "%s: priv is null for macro!\n", __func__);
2582 return -EINVAL;
2583 }
2584
2585 ret = snd_soc_dapm_new_controls(dapm, wsa_macro_dapm_widgets,
2586 ARRAY_SIZE(wsa_macro_dapm_widgets));
2587 if (ret < 0) {
2588 dev_err(wsa_dev, "%s: Failed to add controls\n", __func__);
2589 return ret;
2590 }
2591
2592 ret = snd_soc_dapm_add_routes(dapm, wsa_audio_map,
2593 ARRAY_SIZE(wsa_audio_map));
2594 if (ret < 0) {
2595 dev_err(wsa_dev, "%s: Failed to add routes\n", __func__);
2596 return ret;
2597 }
2598
2599 ret = snd_soc_dapm_new_widgets(dapm->card);
2600 if (ret < 0) {
2601 dev_err(wsa_dev, "%s: Failed to add widgets\n", __func__);
2602 return ret;
2603 }
2604
Meng Wang15c825d2018-09-06 10:49:18 +08002605 ret = snd_soc_add_component_controls(component, wsa_macro_snd_controls,
Laxminath Kasam243e2752018-04-12 00:40:19 +05302606 ARRAY_SIZE(wsa_macro_snd_controls));
2607 if (ret < 0) {
2608 dev_err(wsa_dev, "%s: Failed to add snd_ctls\n", __func__);
2609 return ret;
2610 }
Laxminath Kasam638b5602018-09-24 13:19:52 +05302611 snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF1 Playback");
2612 snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_MIX1 Playback");
2613 snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_VI Capture");
2614 snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_ECHO Capture");
2615 snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK1 OUT");
2616 snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK2 OUT");
2617 snd_soc_dapm_ignore_suspend(dapm, "VIINPUT_WSA");
2618 snd_soc_dapm_ignore_suspend(dapm, "WSA SRC0_INP");
2619 snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC0_INP");
2620 snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC1_INP");
2621 snd_soc_dapm_sync(dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302622
Meng Wang15c825d2018-09-06 10:49:18 +08002623 wsa_priv->component = component;
Laxminath Kasam21c8b222018-06-21 18:47:22 +05302624 wsa_priv->spkr_gain_offset = WSA_MACRO_GAIN_OFFSET_0_DB;
Meng Wang15c825d2018-09-06 10:49:18 +08002625 wsa_macro_init_reg(component);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302626
2627 return 0;
2628}
2629
Meng Wang15c825d2018-09-06 10:49:18 +08002630static int wsa_macro_deinit(struct snd_soc_component *component)
Laxminath Kasam243e2752018-04-12 00:40:19 +05302631{
2632 struct device *wsa_dev = NULL;
2633 struct wsa_macro_priv *wsa_priv = NULL;
2634
Meng Wang15c825d2018-09-06 10:49:18 +08002635 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05302636 return -EINVAL;
2637
Meng Wang15c825d2018-09-06 10:49:18 +08002638 wsa_priv->component = NULL;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302639
2640 return 0;
2641}
2642
2643static void wsa_macro_add_child_devices(struct work_struct *work)
2644{
2645 struct wsa_macro_priv *wsa_priv;
2646 struct platform_device *pdev;
2647 struct device_node *node;
2648 struct wsa_macro_swr_ctrl_data *swr_ctrl_data = NULL, *temp;
2649 int ret;
2650 u16 count = 0, ctrl_num = 0;
2651 struct wsa_macro_swr_ctrl_platform_data *platdata;
2652 char plat_dev_name[WSA_MACRO_SWR_STRING_LEN];
2653
2654 wsa_priv = container_of(work, struct wsa_macro_priv,
2655 wsa_macro_add_child_devices_work);
2656 if (!wsa_priv) {
2657 pr_err("%s: Memory for wsa_priv does not exist\n",
2658 __func__);
2659 return;
2660 }
Laxminath Kasam21c8b222018-06-21 18:47:22 +05302661 if (!wsa_priv->dev || !wsa_priv->dev->of_node) {
Laxminath Kasam243e2752018-04-12 00:40:19 +05302662 dev_err(wsa_priv->dev,
2663 "%s: DT node for wsa_priv does not exist\n", __func__);
2664 return;
2665 }
2666
2667 platdata = &wsa_priv->swr_plat_data;
2668 wsa_priv->child_count = 0;
2669
2670 for_each_available_child_of_node(wsa_priv->dev->of_node, node) {
2671 if (strnstr(node->name, "wsa_swr_master",
2672 strlen("wsa_swr_master")) != NULL)
2673 strlcpy(plat_dev_name, "wsa_swr_ctrl",
2674 (WSA_MACRO_SWR_STRING_LEN - 1));
2675 else if (strnstr(node->name, "msm_cdc_pinctrl",
2676 strlen("msm_cdc_pinctrl")) != NULL)
2677 strlcpy(plat_dev_name, node->name,
2678 (WSA_MACRO_SWR_STRING_LEN - 1));
2679 else
2680 continue;
2681
2682 pdev = platform_device_alloc(plat_dev_name, -1);
2683 if (!pdev) {
2684 dev_err(wsa_priv->dev, "%s: pdev memory alloc failed\n",
2685 __func__);
2686 ret = -ENOMEM;
2687 goto err;
2688 }
2689 pdev->dev.parent = wsa_priv->dev;
2690 pdev->dev.of_node = node;
2691
2692 if (strnstr(node->name, "wsa_swr_master",
2693 strlen("wsa_swr_master")) != NULL) {
2694 ret = platform_device_add_data(pdev, platdata,
2695 sizeof(*platdata));
2696 if (ret) {
2697 dev_err(&pdev->dev,
2698 "%s: cannot add plat data ctrl:%d\n",
2699 __func__, ctrl_num);
2700 goto fail_pdev_add;
2701 }
2702 }
2703
2704 ret = platform_device_add(pdev);
2705 if (ret) {
2706 dev_err(&pdev->dev,
2707 "%s: Cannot add platform device\n",
2708 __func__);
2709 goto fail_pdev_add;
2710 }
2711
2712 if (!strcmp(node->name, "wsa_swr_master")) {
2713 temp = krealloc(swr_ctrl_data,
2714 (ctrl_num + 1) * sizeof(
2715 struct wsa_macro_swr_ctrl_data),
2716 GFP_KERNEL);
2717 if (!temp) {
2718 dev_err(&pdev->dev, "out of memory\n");
2719 ret = -ENOMEM;
2720 goto err;
2721 }
2722 swr_ctrl_data = temp;
2723 swr_ctrl_data[ctrl_num].wsa_swr_pdev = pdev;
2724 ctrl_num++;
2725 dev_dbg(&pdev->dev,
2726 "%s: Added soundwire ctrl device(s)\n",
2727 __func__);
2728 wsa_priv->swr_ctrl_data = swr_ctrl_data;
2729 }
2730 if (wsa_priv->child_count < WSA_MACRO_CHILD_DEVICES_MAX)
2731 wsa_priv->pdev_child_devices[
2732 wsa_priv->child_count++] = pdev;
2733 else
2734 goto err;
2735 }
2736
2737 return;
2738fail_pdev_add:
2739 for (count = 0; count < wsa_priv->child_count; count++)
2740 platform_device_put(wsa_priv->pdev_child_devices[count]);
2741err:
2742 return;
2743}
2744
2745static void wsa_macro_init_ops(struct macro_ops *ops,
2746 char __iomem *wsa_io_base)
2747{
2748 memset(ops, 0, sizeof(struct macro_ops));
2749 ops->init = wsa_macro_init;
2750 ops->exit = wsa_macro_deinit;
2751 ops->io_base = wsa_io_base;
2752 ops->dai_ptr = wsa_macro_dai;
2753 ops->num_dais = ARRAY_SIZE(wsa_macro_dai);
2754 ops->mclk_fn = wsa_macro_mclk_ctrl;
Laxminath Kasamfb0d6832018-09-22 01:49:52 +05302755 ops->event_handler = wsa_macro_event_handler;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302756}
2757
2758static int wsa_macro_probe(struct platform_device *pdev)
2759{
2760 struct macro_ops ops;
2761 struct wsa_macro_priv *wsa_priv;
2762 u32 wsa_base_addr;
2763 char __iomem *wsa_io_base;
2764 int ret = 0;
2765 struct clk *wsa_core_clk, *wsa_npl_clk;
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302766 u8 bcl_pmic_params[3];
Laxminath Kasam243e2752018-04-12 00:40:19 +05302767
2768 wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct wsa_macro_priv),
2769 GFP_KERNEL);
2770 if (!wsa_priv)
2771 return -ENOMEM;
2772
2773 wsa_priv->dev = &pdev->dev;
2774 ret = of_property_read_u32(pdev->dev.of_node, "reg",
2775 &wsa_base_addr);
2776 if (ret) {
2777 dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
2778 __func__, "reg");
2779 return ret;
2780 }
2781 wsa_priv->wsa_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
2782 "qcom,wsa-swr-gpios", 0);
2783 if (!wsa_priv->wsa_swr_gpio_p) {
2784 dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
2785 __func__);
2786 return -EINVAL;
2787 }
2788 wsa_io_base = devm_ioremap(&pdev->dev,
2789 wsa_base_addr, WSA_MACRO_MAX_OFFSET);
2790 if (!wsa_io_base) {
2791 dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
2792 return -EINVAL;
2793 }
2794 wsa_priv->wsa_io_base = wsa_io_base;
2795 INIT_WORK(&wsa_priv->wsa_macro_add_child_devices_work,
2796 wsa_macro_add_child_devices);
2797 wsa_priv->swr_plat_data.handle = (void *) wsa_priv;
2798 wsa_priv->swr_plat_data.read = NULL;
2799 wsa_priv->swr_plat_data.write = NULL;
2800 wsa_priv->swr_plat_data.bulk_write = NULL;
2801 wsa_priv->swr_plat_data.clk = wsa_swrm_clock;
2802 wsa_priv->swr_plat_data.handle_irq = NULL;
2803
2804 /* Register MCLK for wsa macro */
2805 wsa_core_clk = devm_clk_get(&pdev->dev, "wsa_core_clk");
2806 if (IS_ERR(wsa_core_clk)) {
Ramprasad Katkamf83acfb2018-08-11 23:28:57 +05302807 ret = PTR_ERR(wsa_core_clk);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302808 dev_err(&pdev->dev, "%s: clk get %s failed\n",
2809 __func__, "wsa_core_clk");
Ramprasad Katkamf83acfb2018-08-11 23:28:57 +05302810 return ret;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302811 }
2812 wsa_priv->wsa_core_clk = wsa_core_clk;
2813 /* Register npl clk for soundwire */
2814 wsa_npl_clk = devm_clk_get(&pdev->dev, "wsa_npl_clk");
2815 if (IS_ERR(wsa_npl_clk)) {
Ramprasad Katkamf83acfb2018-08-11 23:28:57 +05302816 ret = PTR_ERR(wsa_npl_clk);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302817 dev_err(&pdev->dev, "%s: clk get %s failed\n",
2818 __func__, "wsa_npl_clk");
Ramprasad Katkamf83acfb2018-08-11 23:28:57 +05302819 return ret;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302820 }
2821 wsa_priv->wsa_npl_clk = wsa_npl_clk;
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302822
2823 ret = of_property_read_u8_array(pdev->dev.of_node,
2824 "qcom,wsa-bcl-pmic-params", bcl_pmic_params,
2825 sizeof(bcl_pmic_params));
2826 if (ret) {
2827 dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
2828 __func__, "qcom,wsa-bcl-pmic-params");
2829 } else {
2830 wsa_priv->bcl_pmic_params.id = bcl_pmic_params[0];
2831 wsa_priv->bcl_pmic_params.sid = bcl_pmic_params[1];
2832 wsa_priv->bcl_pmic_params.ppid = bcl_pmic_params[2];
2833 }
2834
Laxminath Kasam243e2752018-04-12 00:40:19 +05302835 dev_set_drvdata(&pdev->dev, wsa_priv);
2836 mutex_init(&wsa_priv->mclk_lock);
2837 mutex_init(&wsa_priv->swr_clk_lock);
2838 wsa_macro_init_ops(&ops, wsa_io_base);
2839 ret = bolero_register_macro(&pdev->dev, WSA_MACRO, &ops);
2840 if (ret < 0) {
2841 dev_err(&pdev->dev, "%s: register macro failed\n", __func__);
2842 goto reg_macro_fail;
2843 }
2844 schedule_work(&wsa_priv->wsa_macro_add_child_devices_work);
2845 return ret;
2846reg_macro_fail:
2847 mutex_destroy(&wsa_priv->mclk_lock);
2848 mutex_destroy(&wsa_priv->swr_clk_lock);
2849 return ret;
2850}
2851
2852static int wsa_macro_remove(struct platform_device *pdev)
2853{
2854 struct wsa_macro_priv *wsa_priv;
2855 u16 count = 0;
2856
2857 wsa_priv = dev_get_drvdata(&pdev->dev);
2858
2859 if (!wsa_priv)
2860 return -EINVAL;
2861
2862 for (count = 0; count < wsa_priv->child_count &&
2863 count < WSA_MACRO_CHILD_DEVICES_MAX; count++)
2864 platform_device_unregister(wsa_priv->pdev_child_devices[count]);
2865
2866 bolero_unregister_macro(&pdev->dev, WSA_MACRO);
2867 mutex_destroy(&wsa_priv->mclk_lock);
2868 mutex_destroy(&wsa_priv->swr_clk_lock);
2869 return 0;
2870}
2871
2872static const struct of_device_id wsa_macro_dt_match[] = {
2873 {.compatible = "qcom,wsa-macro"},
2874 {}
2875};
2876
2877static struct platform_driver wsa_macro_driver = {
2878 .driver = {
2879 .name = "wsa_macro",
2880 .owner = THIS_MODULE,
2881 .of_match_table = wsa_macro_dt_match,
2882 },
2883 .probe = wsa_macro_probe,
2884 .remove = wsa_macro_remove,
2885};
2886
2887module_platform_driver(wsa_macro_driver);
2888
2889MODULE_DESCRIPTION("WSA macro driver");
2890MODULE_LICENSE("GPL v2");