blob: 8642b3597af10b43a59d16d935eff5071171904f [file] [log] [blame]
Meng Wang43bbb872018-12-10 12:32:05 +08001// SPDX-License-Identifier: GPL-2.0-only
Prasad Kumpatla71fef462020-01-31 21:38:58 +05302/* Copyright (c) 2018-2020, 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>
Sudheer Papothi7601cc62019-03-30 03:00:52 +053010#include <linux/pm_runtime.h>
Laxminath Kasam243e2752018-04-12 00:40:19 +053011#include <sound/soc.h>
12#include <sound/soc-dapm.h>
13#include <sound/tlv.h>
Sudheer Papothia3e969d2018-10-27 06:22:10 +053014#include <soc/swr-common.h>
Laxminath Kasam243e2752018-04-12 00:40:19 +053015#include <soc/swr-wcd.h>
16
Meng Wang11a25cf2018-10-31 14:11:26 +080017#include <asoc/msm-cdc-pinctrl.h>
Laxminath Kasam243e2752018-04-12 00:40:19 +053018#include "bolero-cdc.h"
19#include "bolero-cdc-registers.h"
20#include "wsa-macro.h"
Vidyakumar Athota5d45f4c2019-03-10 22:35:07 -070021#include "bolero-clk-rsc.h"
Laxminath Kasam243e2752018-04-12 00:40:19 +053022
Sudheer Papothi7601cc62019-03-30 03:00:52 +053023#define AUTO_SUSPEND_DELAY 50 /* delay in msec */
Laxminath Kasam243e2752018-04-12 00:40:19 +053024#define WSA_MACRO_MAX_OFFSET 0x1000
25
26#define WSA_MACRO_RX_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
27 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
28 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
29#define WSA_MACRO_RX_MIX_RATES (SNDRV_PCM_RATE_48000 |\
30 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
31#define WSA_MACRO_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
32 SNDRV_PCM_FMTBIT_S24_LE |\
33 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
34
35#define WSA_MACRO_ECHO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
36 SNDRV_PCM_RATE_48000)
37#define WSA_MACRO_ECHO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
38 SNDRV_PCM_FMTBIT_S24_LE |\
39 SNDRV_PCM_FMTBIT_S24_3LE)
40
41#define NUM_INTERPOLATORS 2
42
43#define WSA_MACRO_MUX_INP_SHFT 0x3
Laxminath Kasam793902c2019-12-11 18:16:52 +053044#define WSA_MACRO_MUX_INP_MASK1 0x07
Laxminath Kasam243e2752018-04-12 00:40:19 +053045#define WSA_MACRO_MUX_INP_MASK2 0x38
46#define WSA_MACRO_MUX_CFG_OFFSET 0x8
47#define WSA_MACRO_MUX_CFG1_OFFSET 0x4
48#define WSA_MACRO_RX_COMP_OFFSET 0x40
Aditya Bavanari4f3d5642018-09-18 22:19:10 +053049#define WSA_MACRO_RX_SOFTCLIP_OFFSET 0x40
Laxminath Kasam243e2752018-04-12 00:40:19 +053050#define WSA_MACRO_RX_PATH_OFFSET 0x80
51#define WSA_MACRO_RX_PATH_CFG3_OFFSET 0x10
52#define WSA_MACRO_RX_PATH_DSMDEM_OFFSET 0x4C
53#define WSA_MACRO_FS_RATE_MASK 0x0F
Laxminath Kasam5d9ea8d2018-11-28 14:32:40 +053054#define WSA_MACRO_EC_MIX_TX0_MASK 0x03
55#define WSA_MACRO_EC_MIX_TX1_MASK 0x18
56
Laxminath Kasamf8adb5f2019-08-09 21:47:33 +053057#define WSA_MACRO_MAX_DMA_CH_PER_PORT 0x2
Laxminath Kasam243e2752018-04-12 00:40:19 +053058
59enum {
60 WSA_MACRO_RX0 = 0,
61 WSA_MACRO_RX1,
62 WSA_MACRO_RX_MIX,
63 WSA_MACRO_RX_MIX0 = WSA_MACRO_RX_MIX,
64 WSA_MACRO_RX_MIX1,
65 WSA_MACRO_RX_MAX,
66};
67
68enum {
69 WSA_MACRO_TX0 = 0,
70 WSA_MACRO_TX1,
71 WSA_MACRO_TX_MAX,
72};
73
74enum {
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +053075 WSA_MACRO_EC0_MUX = 0,
76 WSA_MACRO_EC1_MUX,
77 WSA_MACRO_EC_MUX_MAX,
78};
79
80enum {
Laxminath Kasam243e2752018-04-12 00:40:19 +053081 WSA_MACRO_COMP1, /* SPK_L */
82 WSA_MACRO_COMP2, /* SPK_R */
83 WSA_MACRO_COMP_MAX
84};
85
Aditya Bavanari4f3d5642018-09-18 22:19:10 +053086enum {
87 WSA_MACRO_SOFTCLIP0, /* RX0 */
88 WSA_MACRO_SOFTCLIP1, /* RX1 */
89 WSA_MACRO_SOFTCLIP_MAX
90};
91
Laxminath Kasam52ae6582019-08-08 18:00:35 +053092enum {
93 INTn_1_INP_SEL_ZERO = 0,
94 INTn_1_INP_SEL_RX0,
95 INTn_1_INP_SEL_RX1,
96 INTn_1_INP_SEL_RX2,
97 INTn_1_INP_SEL_RX3,
98 INTn_1_INP_SEL_DEC0,
99 INTn_1_INP_SEL_DEC1,
100};
101
Laxminath Kasamf8adb5f2019-08-09 21:47:33 +0530102enum {
103 INTn_2_INP_SEL_ZERO = 0,
104 INTn_2_INP_SEL_RX0,
105 INTn_2_INP_SEL_RX1,
106 INTn_2_INP_SEL_RX2,
107 INTn_2_INP_SEL_RX3,
108};
109
Laxminath Kasam243e2752018-04-12 00:40:19 +0530110struct interp_sample_rate {
111 int sample_rate;
112 int rate_val;
113};
114
115/*
116 * Structure used to update codec
117 * register defaults after reset
118 */
119struct wsa_macro_reg_mask_val {
120 u16 reg;
121 u8 mask;
122 u8 val;
123};
124
125static struct interp_sample_rate int_prim_sample_rate_val[] = {
126 {8000, 0x0}, /* 8K */
127 {16000, 0x1}, /* 16K */
128 {24000, -EINVAL},/* 24K */
129 {32000, 0x3}, /* 32K */
130 {48000, 0x4}, /* 48K */
131 {96000, 0x5}, /* 96K */
132 {192000, 0x6}, /* 192K */
133 {384000, 0x7}, /* 384K */
134 {44100, 0x8}, /* 44.1K */
135};
136
137static struct interp_sample_rate int_mix_sample_rate_val[] = {
138 {48000, 0x4}, /* 48K */
139 {96000, 0x5}, /* 96K */
140 {192000, 0x6}, /* 192K */
141};
142
143#define WSA_MACRO_SWR_STRING_LEN 80
144
145static int wsa_macro_hw_params(struct snd_pcm_substream *substream,
146 struct snd_pcm_hw_params *params,
147 struct snd_soc_dai *dai);
148static int wsa_macro_get_channel_map(struct snd_soc_dai *dai,
149 unsigned int *tx_num, unsigned int *tx_slot,
150 unsigned int *rx_num, unsigned int *rx_slot);
Laxminath Kasam52ae6582019-08-08 18:00:35 +0530151static int wsa_macro_digital_mute(struct snd_soc_dai *dai, int mute);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530152/* Hold instance to soundwire platform device */
153struct wsa_macro_swr_ctrl_data {
154 struct platform_device *wsa_swr_pdev;
155};
156
157struct wsa_macro_swr_ctrl_platform_data {
158 void *handle; /* holds codec private data */
159 int (*read)(void *handle, int reg);
160 int (*write)(void *handle, int reg, int val);
161 int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
162 int (*clk)(void *handle, bool enable);
Karthikeyan Mani8d40a062019-09-05 16:44:49 -0700163 int (*core_vote)(void *handle, bool enable);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530164 int (*handle_irq)(void *handle,
165 irqreturn_t (*swrm_irq_handler)(int irq,
166 void *data),
167 void *swrm_handle,
168 int action);
169};
170
Aditya Bavanari4f3d5642018-09-18 22:19:10 +0530171struct wsa_macro_bcl_pmic_params {
172 u8 id;
173 u8 sid;
174 u8 ppid;
175};
176
Laxminath Kasam243e2752018-04-12 00:40:19 +0530177enum {
Laxminath Kasam59c7a1d2018-08-09 16:11:17 +0530178 WSA_MACRO_AIF_INVALID = 0,
179 WSA_MACRO_AIF1_PB,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530180 WSA_MACRO_AIF_MIX1_PB,
181 WSA_MACRO_AIF_VI,
182 WSA_MACRO_AIF_ECHO,
183 WSA_MACRO_MAX_DAIS,
184};
185
186#define WSA_MACRO_CHILD_DEVICES_MAX 3
187
188/*
189 * @dev: wsa macro device pointer
190 * @comp_enabled: compander enable mixer value set
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +0530191 * @ec_hq: echo HQ enable mixer value set
Laxminath Kasam243e2752018-04-12 00:40:19 +0530192 * @prim_int_users: Users of interpolator
193 * @wsa_mclk_users: WSA MCLK users count
194 * @swr_clk_users: SWR clk users count
195 * @vi_feed_value: VI sense mask
196 * @mclk_lock: to lock mclk operations
197 * @swr_clk_lock: to lock swr master clock operations
198 * @swr_ctrl_data: SoundWire data structure
199 * @swr_plat_data: Soundwire platform data
200 * @wsa_macro_add_child_devices_work: work for adding child devices
201 * @wsa_swr_gpio_p: used by pinctrl API
Meng Wang15c825d2018-09-06 10:49:18 +0800202 * @component: codec handle
Laxminath Kasam243e2752018-04-12 00:40:19 +0530203 * @rx_0_count: RX0 interpolation users
204 * @rx_1_count: RX1 interpolation users
205 * @active_ch_mask: channel mask for all AIF DAIs
206 * @active_ch_cnt: channel count of all AIF DAIs
207 * @rx_port_value: mixer ctl value of WSA RX MUXes
208 * @wsa_io_base: Base address of WSA macro addr space
209 */
210struct wsa_macro_priv {
211 struct device *dev;
212 int comp_enabled[WSA_MACRO_COMP_MAX];
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +0530213 int ec_hq[WSA_MACRO_RX1 + 1];
Laxminath Kasam243e2752018-04-12 00:40:19 +0530214 u16 prim_int_users[WSA_MACRO_RX1 + 1];
215 u16 wsa_mclk_users;
216 u16 swr_clk_users;
Ramprasad Katkam452772a2019-01-07 17:30:36 +0530217 bool dapm_mclk_enable;
Ramprasad Katkama4c747b2018-12-11 19:15:53 +0530218 bool reset_swr;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530219 unsigned int vi_feed_value;
220 struct mutex mclk_lock;
221 struct mutex swr_clk_lock;
222 struct wsa_macro_swr_ctrl_data *swr_ctrl_data;
223 struct wsa_macro_swr_ctrl_platform_data swr_plat_data;
224 struct work_struct wsa_macro_add_child_devices_work;
225 struct device_node *wsa_swr_gpio_p;
Meng Wang15c825d2018-09-06 10:49:18 +0800226 struct snd_soc_component *component;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530227 int rx_0_count;
228 int rx_1_count;
229 unsigned long active_ch_mask[WSA_MACRO_MAX_DAIS];
230 unsigned long active_ch_cnt[WSA_MACRO_MAX_DAIS];
231 int rx_port_value[WSA_MACRO_RX_MAX];
232 char __iomem *wsa_io_base;
233 struct platform_device *pdev_child_devices
234 [WSA_MACRO_CHILD_DEVICES_MAX];
235 int child_count;
236 int ear_spkr_gain;
237 int spkr_gain_offset;
238 int spkr_mode;
Aditya Bavanari4f3d5642018-09-18 22:19:10 +0530239 int is_softclip_on[WSA_MACRO_SOFTCLIP_MAX];
240 int softclip_clk_users[WSA_MACRO_SOFTCLIP_MAX];
241 struct wsa_macro_bcl_pmic_params bcl_pmic_params;
Vidyakumar Athota5d45f4c2019-03-10 22:35:07 -0700242 char __iomem *mclk_mode_muxsel;
243 u16 default_clk_id;
Laxminath Kasam007d2522020-04-23 11:00:44 +0530244 u32 pcm_rate_vi;
Vatsal Buchaf2a71b62019-03-26 16:14:40 +0530245 int wsa_digital_mute_status[WSA_MACRO_RX_MAX];
Laxminath Kasam243e2752018-04-12 00:40:19 +0530246};
247
Meng Wang15c825d2018-09-06 10:49:18 +0800248static int wsa_macro_config_ear_spkr_gain(struct snd_soc_component *component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530249 struct wsa_macro_priv *wsa_priv,
250 int event, int gain_reg);
251static struct snd_soc_dai_driver wsa_macro_dai[];
252static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
253
254static const char *const rx_text[] = {
255 "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "DEC0", "DEC1"
256};
257
258static const char *const rx_mix_text[] = {
259 "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1"
260};
261
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +0530262static const char *const rx_mix_ec_text[] = {
263 "ZERO", "RX_MIX_TX0", "RX_MIX_TX1"
264};
265
Laxminath Kasam243e2752018-04-12 00:40:19 +0530266static const char *const rx_mux_text[] = {
267 "ZERO", "AIF1_PB", "AIF_MIX1_PB"
268};
269
Laxminath Kasam6fc2e742018-08-26 23:32:57 +0530270static const char *const rx_sidetone_mix_text[] = {
271 "ZERO", "SRC0"
272};
273
Laxminath Kasam243e2752018-04-12 00:40:19 +0530274static const char * const wsa_macro_ear_spkr_pa_gain_text[] = {
275 "G_DEFAULT", "G_0_DB", "G_1_DB", "G_2_DB", "G_3_DB",
276 "G_4_DB", "G_5_DB", "G_6_DB"
277};
278
279static const char * const wsa_macro_speaker_boost_stage_text[] = {
280 "NO_MAX_STATE", "MAX_STATE_1", "MAX_STATE_2"
281};
282
Aditya Bavanari4f3d5642018-09-18 22:19:10 +0530283static const char * const wsa_macro_vbat_bcl_gsm_mode_text[] = {
284 "OFF", "ON"
285};
286
287static const struct snd_kcontrol_new wsa_int0_vbat_mix_switch[] = {
288 SOC_DAPM_SINGLE("WSA RX0 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
289};
290
291static const struct snd_kcontrol_new wsa_int1_vbat_mix_switch[] = {
292 SOC_DAPM_SINGLE("WSA RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
293};
294
Laxminath Kasam243e2752018-04-12 00:40:19 +0530295static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_ear_spkr_pa_gain_enum,
296 wsa_macro_ear_spkr_pa_gain_text);
297static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_spkr_boost_stage_enum,
298 wsa_macro_speaker_boost_stage_text);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +0530299static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_vbat_bcl_gsm_mode_enum,
300 wsa_macro_vbat_bcl_gsm_mode_text);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530301
302/* RX INT0 */
303static const struct soc_enum rx0_prim_inp0_chain_enum =
304 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0,
305 0, 7, rx_text);
306
307static const struct soc_enum rx0_prim_inp1_chain_enum =
308 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0,
309 3, 7, rx_text);
310
311static const struct soc_enum rx0_prim_inp2_chain_enum =
312 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1,
313 3, 7, rx_text);
314
315static const struct soc_enum rx0_mix_chain_enum =
316 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1,
317 0, 5, rx_mix_text);
318
Laxminath Kasam6fc2e742018-08-26 23:32:57 +0530319static const struct soc_enum rx0_sidetone_mix_enum =
320 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_sidetone_mix_text);
321
Laxminath Kasam243e2752018-04-12 00:40:19 +0530322static const struct snd_kcontrol_new rx0_prim_inp0_mux =
323 SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum);
324
325static const struct snd_kcontrol_new rx0_prim_inp1_mux =
326 SOC_DAPM_ENUM("WSA_RX0 INP1 Mux", rx0_prim_inp1_chain_enum);
327
328static const struct snd_kcontrol_new rx0_prim_inp2_mux =
329 SOC_DAPM_ENUM("WSA_RX0 INP2 Mux", rx0_prim_inp2_chain_enum);
330
331static const struct snd_kcontrol_new rx0_mix_mux =
332 SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum);
333
Laxminath Kasam6fc2e742018-08-26 23:32:57 +0530334static const struct snd_kcontrol_new rx0_sidetone_mix_mux =
335 SOC_DAPM_ENUM("WSA_RX0 SIDETONE MIX Mux", rx0_sidetone_mix_enum);
336
Laxminath Kasam243e2752018-04-12 00:40:19 +0530337/* RX INT1 */
338static const struct soc_enum rx1_prim_inp0_chain_enum =
339 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0,
340 0, 7, rx_text);
341
342static const struct soc_enum rx1_prim_inp1_chain_enum =
343 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0,
344 3, 7, rx_text);
345
346static const struct soc_enum rx1_prim_inp2_chain_enum =
347 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1,
348 3, 7, rx_text);
349
350static const struct soc_enum rx1_mix_chain_enum =
351 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1,
352 0, 5, rx_mix_text);
353
354static const struct snd_kcontrol_new rx1_prim_inp0_mux =
355 SOC_DAPM_ENUM("WSA_RX1 INP0 Mux", rx1_prim_inp0_chain_enum);
356
357static const struct snd_kcontrol_new rx1_prim_inp1_mux =
358 SOC_DAPM_ENUM("WSA_RX1 INP1 Mux", rx1_prim_inp1_chain_enum);
359
360static const struct snd_kcontrol_new rx1_prim_inp2_mux =
361 SOC_DAPM_ENUM("WSA_RX1 INP2 Mux", rx1_prim_inp2_chain_enum);
362
363static const struct snd_kcontrol_new rx1_mix_mux =
364 SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum);
365
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +0530366static const struct soc_enum rx_mix_ec0_enum =
367 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
368 0, 3, rx_mix_ec_text);
369
370static const struct soc_enum rx_mix_ec1_enum =
371 SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
372 3, 3, rx_mix_ec_text);
373
374static const struct snd_kcontrol_new rx_mix_ec0_mux =
375 SOC_DAPM_ENUM("WSA RX_MIX EC0_Mux", rx_mix_ec0_enum);
376
377static const struct snd_kcontrol_new rx_mix_ec1_mux =
378 SOC_DAPM_ENUM("WSA RX_MIX EC1_Mux", rx_mix_ec1_enum);
379
Laxminath Kasam243e2752018-04-12 00:40:19 +0530380static struct snd_soc_dai_ops wsa_macro_dai_ops = {
381 .hw_params = wsa_macro_hw_params,
382 .get_channel_map = wsa_macro_get_channel_map,
Laxminath Kasam52ae6582019-08-08 18:00:35 +0530383 .digital_mute = wsa_macro_digital_mute,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530384};
385
386static struct snd_soc_dai_driver wsa_macro_dai[] = {
387 {
388 .name = "wsa_macro_rx1",
389 .id = WSA_MACRO_AIF1_PB,
390 .playback = {
391 .stream_name = "WSA_AIF1 Playback",
392 .rates = WSA_MACRO_RX_RATES,
393 .formats = WSA_MACRO_RX_FORMATS,
394 .rate_max = 384000,
395 .rate_min = 8000,
396 .channels_min = 1,
397 .channels_max = 2,
398 },
399 .ops = &wsa_macro_dai_ops,
400 },
401 {
402 .name = "wsa_macro_rx_mix",
403 .id = WSA_MACRO_AIF_MIX1_PB,
404 .playback = {
405 .stream_name = "WSA_AIF_MIX1 Playback",
406 .rates = WSA_MACRO_RX_MIX_RATES,
407 .formats = WSA_MACRO_RX_FORMATS,
408 .rate_max = 192000,
409 .rate_min = 48000,
410 .channels_min = 1,
411 .channels_max = 2,
412 },
413 .ops = &wsa_macro_dai_ops,
414 },
415 {
416 .name = "wsa_macro_vifeedback",
417 .id = WSA_MACRO_AIF_VI,
418 .capture = {
419 .stream_name = "WSA_AIF_VI Capture",
Vatsal Buchad1b694d2018-08-31 11:47:32 +0530420 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
421 .formats = WSA_MACRO_RX_FORMATS,
422 .rate_max = 48000,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530423 .rate_min = 8000,
424 .channels_min = 1,
Vatsal Buchad1b694d2018-08-31 11:47:32 +0530425 .channels_max = 4,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530426 },
427 .ops = &wsa_macro_dai_ops,
428 },
429 {
430 .name = "wsa_macro_echo",
431 .id = WSA_MACRO_AIF_ECHO,
432 .capture = {
433 .stream_name = "WSA_AIF_ECHO Capture",
434 .rates = WSA_MACRO_ECHO_RATES,
435 .formats = WSA_MACRO_ECHO_FORMATS,
436 .rate_max = 48000,
437 .rate_min = 8000,
438 .channels_min = 1,
439 .channels_max = 2,
440 },
441 .ops = &wsa_macro_dai_ops,
442 },
443};
444
445static const struct wsa_macro_reg_mask_val wsa_macro_spkr_default[] = {
446 {BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80},
447 {BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x80},
448 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01},
449 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01},
450 {BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x58},
451 {BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x58},
452};
453
454static const struct wsa_macro_reg_mask_val wsa_macro_spkr_mode1[] = {
455 {BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x00},
456 {BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x00},
457 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x00},
458 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x00},
459 {BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x44},
460 {BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x44},
461};
462
Meng Wang15c825d2018-09-06 10:49:18 +0800463static bool wsa_macro_get_data(struct snd_soc_component *component,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530464 struct device **wsa_dev,
465 struct wsa_macro_priv **wsa_priv,
466 const char *func_name)
467{
Meng Wang15c825d2018-09-06 10:49:18 +0800468 *wsa_dev = bolero_get_device_ptr(component->dev, WSA_MACRO);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530469 if (!(*wsa_dev)) {
Meng Wang15c825d2018-09-06 10:49:18 +0800470 dev_err(component->dev,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530471 "%s: null device for macro!\n", func_name);
472 return false;
473 }
474 *wsa_priv = dev_get_drvdata((*wsa_dev));
Meng Wang15c825d2018-09-06 10:49:18 +0800475 if (!(*wsa_priv) || !(*wsa_priv)->component) {
476 dev_err(component->dev,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530477 "%s: priv is null for macro!\n", func_name);
478 return false;
479 }
480 return true;
481}
482
Sudheer Papothia3e969d2018-10-27 06:22:10 +0530483static int wsa_macro_set_port_map(struct snd_soc_component *component,
484 u32 usecase, u32 size, void *data)
485{
486 struct device *wsa_dev = NULL;
487 struct wsa_macro_priv *wsa_priv = NULL;
488 struct swrm_port_config port_cfg;
489 int ret = 0;
490
491 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
492 return -EINVAL;
493
494 memset(&port_cfg, 0, sizeof(port_cfg));
495 port_cfg.uc = usecase;
496 port_cfg.size = size;
497 port_cfg.params = data;
498
Karthikeyan Mani3bd80a52019-06-04 23:40:16 -0700499 if (wsa_priv->swr_ctrl_data)
500 ret = swrm_wcd_notify(
501 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
502 SWR_SET_PORT_MAP, &port_cfg);
Sudheer Papothia3e969d2018-10-27 06:22:10 +0530503
504 return ret;
505}
506
Laxminath Kasam243e2752018-04-12 00:40:19 +0530507/**
508 * wsa_macro_set_spkr_gain_offset - offset the speaker path
509 * gain with the given offset value.
510 *
Meng Wang15c825d2018-09-06 10:49:18 +0800511 * @component: codec instance
Laxminath Kasam243e2752018-04-12 00:40:19 +0530512 * @offset: Indicates speaker path gain offset value.
513 *
514 * Returns 0 on success or -EINVAL on error.
515 */
Meng Wang15c825d2018-09-06 10:49:18 +0800516int wsa_macro_set_spkr_gain_offset(struct snd_soc_component *component,
517 int offset)
Laxminath Kasam243e2752018-04-12 00:40:19 +0530518{
519 struct device *wsa_dev = NULL;
520 struct wsa_macro_priv *wsa_priv = NULL;
521
Meng Wang15c825d2018-09-06 10:49:18 +0800522 if (!component) {
523 pr_err("%s: NULL component pointer!\n", __func__);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530524 return -EINVAL;
525 }
526
Meng Wang15c825d2018-09-06 10:49:18 +0800527 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +0530528 return -EINVAL;
529
530 wsa_priv->spkr_gain_offset = offset;
531 return 0;
532}
533EXPORT_SYMBOL(wsa_macro_set_spkr_gain_offset);
534
535/**
536 * wsa_macro_set_spkr_mode - Configures speaker compander and smartboost
537 * settings based on speaker mode.
538 *
Meng Wang15c825d2018-09-06 10:49:18 +0800539 * @component: codec instance
Laxminath Kasam243e2752018-04-12 00:40:19 +0530540 * @mode: Indicates speaker configuration mode.
541 *
542 * Returns 0 on success or -EINVAL on error.
543 */
Meng Wang15c825d2018-09-06 10:49:18 +0800544int wsa_macro_set_spkr_mode(struct snd_soc_component *component, int mode)
Laxminath Kasam243e2752018-04-12 00:40:19 +0530545{
546 int i;
547 const struct wsa_macro_reg_mask_val *regs;
548 int size;
549 struct device *wsa_dev = NULL;
550 struct wsa_macro_priv *wsa_priv = NULL;
551
Meng Wang15c825d2018-09-06 10:49:18 +0800552 if (!component) {
Laxminath Kasam243e2752018-04-12 00:40:19 +0530553 pr_err("%s: NULL codec pointer!\n", __func__);
554 return -EINVAL;
555 }
556
Meng Wang15c825d2018-09-06 10:49:18 +0800557 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +0530558 return -EINVAL;
559
560 switch (mode) {
Laxminath Kasam21c8b222018-06-21 18:47:22 +0530561 case WSA_MACRO_SPKR_MODE_1:
Laxminath Kasam243e2752018-04-12 00:40:19 +0530562 regs = wsa_macro_spkr_mode1;
563 size = ARRAY_SIZE(wsa_macro_spkr_mode1);
564 break;
565 default:
566 regs = wsa_macro_spkr_default;
567 size = ARRAY_SIZE(wsa_macro_spkr_default);
568 break;
569 }
570
571 wsa_priv->spkr_mode = mode;
572 for (i = 0; i < size; i++)
Meng Wang15c825d2018-09-06 10:49:18 +0800573 snd_soc_component_update_bits(component, regs[i].reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530574 regs[i].mask, regs[i].val);
575 return 0;
576}
577EXPORT_SYMBOL(wsa_macro_set_spkr_mode);
578
579static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
580 u8 int_prim_fs_rate_reg_val,
581 u32 sample_rate)
582{
583 u8 int_1_mix1_inp;
584 u32 j, port;
585 u16 int_mux_cfg0, int_mux_cfg1;
586 u16 int_fs_reg;
587 u8 int_mux_cfg0_val, int_mux_cfg1_val;
588 u8 inp0_sel, inp1_sel, inp2_sel;
Meng Wang15c825d2018-09-06 10:49:18 +0800589 struct snd_soc_component *component = dai->component;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530590 struct device *wsa_dev = NULL;
591 struct wsa_macro_priv *wsa_priv = NULL;
592
Meng Wang15c825d2018-09-06 10:49:18 +0800593 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +0530594 return -EINVAL;
595
596 for_each_set_bit(port, &wsa_priv->active_ch_mask[dai->id],
597 WSA_MACRO_RX_MAX) {
598 int_1_mix1_inp = port;
599 if ((int_1_mix1_inp < WSA_MACRO_RX0) ||
600 (int_1_mix1_inp > WSA_MACRO_RX_MIX1)) {
601 dev_err(wsa_dev,
602 "%s: Invalid RX port, Dai ID is %d\n",
603 __func__, dai->id);
604 return -EINVAL;
605 }
606
607 int_mux_cfg0 = BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0;
608
609 /*
610 * Loop through all interpolator MUX inputs and find out
611 * to which interpolator input, the cdc_dma rx port
612 * is connected
613 */
614 for (j = 0; j < NUM_INTERPOLATORS; j++) {
615 int_mux_cfg1 = int_mux_cfg0 + WSA_MACRO_MUX_CFG1_OFFSET;
616
Meng Wang15c825d2018-09-06 10:49:18 +0800617 int_mux_cfg0_val = snd_soc_component_read32(component,
618 int_mux_cfg0);
619 int_mux_cfg1_val = snd_soc_component_read32(component,
620 int_mux_cfg1);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530621 inp0_sel = int_mux_cfg0_val & WSA_MACRO_MUX_INP_MASK1;
622 inp1_sel = (int_mux_cfg0_val >>
623 WSA_MACRO_MUX_INP_SHFT) &
Laxminath Kasam793902c2019-12-11 18:16:52 +0530624 WSA_MACRO_MUX_INP_MASK1;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530625 inp2_sel = (int_mux_cfg1_val >>
626 WSA_MACRO_MUX_INP_SHFT) &
Laxminath Kasam793902c2019-12-11 18:16:52 +0530627 WSA_MACRO_MUX_INP_MASK1;
Laxminath Kasamf8adb5f2019-08-09 21:47:33 +0530628 if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) ||
629 (inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) ||
630 (inp2_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0)) {
Laxminath Kasam243e2752018-04-12 00:40:19 +0530631 int_fs_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL +
632 WSA_MACRO_RX_PATH_OFFSET * j;
633 dev_dbg(wsa_dev,
634 "%s: AIF_PB DAI(%d) connected to INT%u_1\n",
635 __func__, dai->id, j);
636 dev_dbg(wsa_dev,
637 "%s: set INT%u_1 sample rate to %u\n",
638 __func__, j, sample_rate);
639 /* sample_rate is in Hz */
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_prim_fs_rate_reg_val);
644 }
645 int_mux_cfg0 += WSA_MACRO_MUX_CFG_OFFSET;
646 }
647 }
648
649 return 0;
650}
651
652static int wsa_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai,
653 u8 int_mix_fs_rate_reg_val,
654 u32 sample_rate)
655{
656 u8 int_2_inp;
657 u32 j, port;
658 u16 int_mux_cfg1, int_fs_reg;
659 u8 int_mux_cfg1_val;
Meng Wang15c825d2018-09-06 10:49:18 +0800660 struct snd_soc_component *component = dai->component;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530661 struct device *wsa_dev = NULL;
662 struct wsa_macro_priv *wsa_priv = NULL;
663
Meng Wang15c825d2018-09-06 10:49:18 +0800664 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +0530665 return -EINVAL;
666
667
668 for_each_set_bit(port, &wsa_priv->active_ch_mask[dai->id],
669 WSA_MACRO_RX_MAX) {
670 int_2_inp = port;
671 if ((int_2_inp < WSA_MACRO_RX0) ||
672 (int_2_inp > WSA_MACRO_RX_MIX1)) {
673 dev_err(wsa_dev,
674 "%s: Invalid RX port, Dai ID is %d\n",
675 __func__, dai->id);
676 return -EINVAL;
677 }
678
679 int_mux_cfg1 = BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1;
680 for (j = 0; j < NUM_INTERPOLATORS; j++) {
Meng Wang15c825d2018-09-06 10:49:18 +0800681 int_mux_cfg1_val = snd_soc_component_read32(component,
682 int_mux_cfg1) &
Laxminath Kasam243e2752018-04-12 00:40:19 +0530683 WSA_MACRO_MUX_INP_MASK1;
Laxminath Kasamf8adb5f2019-08-09 21:47:33 +0530684 if (int_mux_cfg1_val == int_2_inp +
685 INTn_2_INP_SEL_RX0) {
Laxminath Kasam243e2752018-04-12 00:40:19 +0530686 int_fs_reg =
687 BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL +
688 WSA_MACRO_RX_PATH_OFFSET * j;
689
690 dev_dbg(wsa_dev,
691 "%s: AIF_PB DAI(%d) connected to INT%u_2\n",
692 __func__, dai->id, j);
693 dev_dbg(wsa_dev,
694 "%s: set INT%u_2 sample rate to %u\n",
695 __func__, j, sample_rate);
Meng Wang15c825d2018-09-06 10:49:18 +0800696 snd_soc_component_update_bits(component,
697 int_fs_reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530698 WSA_MACRO_FS_RATE_MASK,
699 int_mix_fs_rate_reg_val);
700 }
701 int_mux_cfg1 += WSA_MACRO_MUX_CFG_OFFSET;
702 }
703 }
704 return 0;
705}
706
707static int wsa_macro_set_interpolator_rate(struct snd_soc_dai *dai,
708 u32 sample_rate)
709{
710 int rate_val = 0;
711 int i, ret;
712
713 /* set mixing path rate */
714 for (i = 0; i < ARRAY_SIZE(int_mix_sample_rate_val); i++) {
715 if (sample_rate ==
716 int_mix_sample_rate_val[i].sample_rate) {
717 rate_val =
718 int_mix_sample_rate_val[i].rate_val;
719 break;
720 }
721 }
722 if ((i == ARRAY_SIZE(int_mix_sample_rate_val)) ||
723 (rate_val < 0))
724 goto prim_rate;
725 ret = wsa_macro_set_mix_interpolator_rate(dai,
726 (u8) rate_val, sample_rate);
727prim_rate:
728 /* set primary path sample rate */
729 for (i = 0; i < ARRAY_SIZE(int_prim_sample_rate_val); i++) {
730 if (sample_rate ==
731 int_prim_sample_rate_val[i].sample_rate) {
732 rate_val =
733 int_prim_sample_rate_val[i].rate_val;
734 break;
735 }
736 }
737 if ((i == ARRAY_SIZE(int_prim_sample_rate_val)) ||
738 (rate_val < 0))
739 return -EINVAL;
740 ret = wsa_macro_set_prim_interpolator_rate(dai,
741 (u8) rate_val, sample_rate);
742 return ret;
743}
744
745static int wsa_macro_hw_params(struct snd_pcm_substream *substream,
746 struct snd_pcm_hw_params *params,
747 struct snd_soc_dai *dai)
748{
Meng Wang15c825d2018-09-06 10:49:18 +0800749 struct snd_soc_component *component = dai->component;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530750 int ret;
Laxminath Kasam007d2522020-04-23 11:00:44 +0530751 struct device *wsa_dev = NULL;
752 struct wsa_macro_priv *wsa_priv = NULL;
753
754 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
755 return -EINVAL;
756
757 wsa_priv = dev_get_drvdata(wsa_dev);
758 if (!wsa_priv)
759 return -EINVAL;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530760
Meng Wang15c825d2018-09-06 10:49:18 +0800761 dev_dbg(component->dev,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530762 "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
763 dai->name, dai->id, params_rate(params),
764 params_channels(params));
765
766 switch (substream->stream) {
767 case SNDRV_PCM_STREAM_PLAYBACK:
768 ret = wsa_macro_set_interpolator_rate(dai, params_rate(params));
769 if (ret) {
Meng Wang15c825d2018-09-06 10:49:18 +0800770 dev_err(component->dev,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530771 "%s: cannot set sample rate: %u\n",
772 __func__, params_rate(params));
773 return ret;
774 }
775 break;
776 case SNDRV_PCM_STREAM_CAPTURE:
Laxminath Kasam007d2522020-04-23 11:00:44 +0530777 if (dai->id == WSA_MACRO_AIF_VI)
778 wsa_priv->pcm_rate_vi = params_rate(params);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530779 default:
780 break;
781 }
782 return 0;
783}
784
785static int wsa_macro_get_channel_map(struct snd_soc_dai *dai,
786 unsigned int *tx_num, unsigned int *tx_slot,
787 unsigned int *rx_num, unsigned int *rx_slot)
788{
Meng Wang15c825d2018-09-06 10:49:18 +0800789 struct snd_soc_component *component = dai->component;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530790 struct device *wsa_dev = NULL;
791 struct wsa_macro_priv *wsa_priv = NULL;
Laxminath Kasamf8adb5f2019-08-09 21:47:33 +0530792 u16 val = 0, mask = 0, cnt = 0, temp = 0;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530793
Meng Wang15c825d2018-09-06 10:49:18 +0800794 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +0530795 return -EINVAL;
796
797 wsa_priv = dev_get_drvdata(wsa_dev);
798 if (!wsa_priv)
799 return -EINVAL;
800
801 switch (dai->id) {
802 case WSA_MACRO_AIF_VI:
Laxminath Kasam243e2752018-04-12 00:40:19 +0530803 *tx_slot = wsa_priv->active_ch_mask[dai->id];
804 *tx_num = wsa_priv->active_ch_cnt[dai->id];
805 break;
806 case WSA_MACRO_AIF1_PB:
807 case WSA_MACRO_AIF_MIX1_PB:
Laxminath Kasamf8adb5f2019-08-09 21:47:33 +0530808 for_each_set_bit(temp, &wsa_priv->active_ch_mask[dai->id],
809 WSA_MACRO_RX_MAX) {
810 mask |= (1 << temp);
811 if (++cnt == WSA_MACRO_MAX_DMA_CH_PER_PORT)
812 break;
813 }
814 if (mask & 0x0C)
815 mask = mask >> 0x2;
816 *rx_slot = mask;
817 *rx_num = cnt;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530818 break;
Laxminath Kasam5d9ea8d2018-11-28 14:32:40 +0530819 case WSA_MACRO_AIF_ECHO:
820 val = snd_soc_component_read32(component,
821 BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0);
822 if (val & WSA_MACRO_EC_MIX_TX1_MASK) {
823 mask |= 0x2;
824 cnt++;
825 }
826 if (val & WSA_MACRO_EC_MIX_TX0_MASK) {
827 mask |= 0x1;
828 cnt++;
829 }
830 *tx_slot = mask;
831 *tx_num = cnt;
832 break;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530833 default:
834 dev_err(wsa_dev, "%s: Invalid AIF\n", __func__);
835 break;
836 }
837 return 0;
838}
839
Laxminath Kasam52ae6582019-08-08 18:00:35 +0530840static int wsa_macro_digital_mute(struct snd_soc_dai *dai, int mute)
841{
842 struct snd_soc_component *component = dai->component;
843 struct device *wsa_dev = NULL;
844 struct wsa_macro_priv *wsa_priv = NULL;
845 uint16_t j = 0, reg = 0, mix_reg = 0, dsm_reg = 0;
846 u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
847 u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
848
849 if (mute)
850 return 0;
851
852 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
853 return -EINVAL;
854
855 switch (dai->id) {
856 case WSA_MACRO_AIF1_PB:
857 case WSA_MACRO_AIF_MIX1_PB:
858 for (j = 0; j < NUM_INTERPOLATORS; j++) {
859 reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL +
860 (j * WSA_MACRO_RX_PATH_OFFSET);
861 mix_reg = BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL +
862 (j * WSA_MACRO_RX_PATH_OFFSET);
863 dsm_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL +
864 (j * WSA_MACRO_RX_PATH_OFFSET) +
865 WSA_MACRO_RX_PATH_DSMDEM_OFFSET;
866 int_mux_cfg0 = BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 + j * 8;
867 int_mux_cfg1 = int_mux_cfg0 + 4;
868 int_mux_cfg0_val = snd_soc_component_read32(component,
869 int_mux_cfg0);
870 int_mux_cfg1_val = snd_soc_component_read32(component,
871 int_mux_cfg1);
872 if (snd_soc_component_read32(component, dsm_reg) & 0x01) {
873 if (int_mux_cfg0_val || (int_mux_cfg1_val & 0x38))
874 snd_soc_component_update_bits(component, reg,
875 0x20, 0x20);
Laxminath Kasamf8adb5f2019-08-09 21:47:33 +0530876 if (int_mux_cfg1_val & 0x07) {
877 snd_soc_component_update_bits(component, reg,
878 0x20, 0x20);
Laxminath Kasam52ae6582019-08-08 18:00:35 +0530879 snd_soc_component_update_bits(component,
880 mix_reg, 0x20, 0x20);
Laxminath Kasamf8adb5f2019-08-09 21:47:33 +0530881 }
Laxminath Kasam52ae6582019-08-08 18:00:35 +0530882 }
883 }
Laxminath Kasam069df142019-09-17 23:43:34 +0530884 bolero_wsa_pa_on(wsa_dev);
Laxminath Kasam52ae6582019-08-08 18:00:35 +0530885 break;
886 default:
887 break;
888 }
889 return 0;
890}
Laxminath Kasam243e2752018-04-12 00:40:19 +0530891static int wsa_macro_mclk_enable(struct wsa_macro_priv *wsa_priv,
892 bool mclk_enable, bool dapm)
893{
894 struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
895 int ret = 0;
896
Tanya Dixitab8eba82018-10-05 15:07:37 +0530897 if (regmap == NULL) {
898 dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
899 return -EINVAL;
900 }
901
Laxminath Kasam243e2752018-04-12 00:40:19 +0530902 dev_dbg(wsa_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
903 __func__, mclk_enable, dapm, wsa_priv->wsa_mclk_users);
904
905 mutex_lock(&wsa_priv->mclk_lock);
906 if (mclk_enable) {
Aditya Bavanaric496ed22018-11-16 15:50:40 +0530907 if (wsa_priv->wsa_mclk_users == 0) {
Vidyakumar Athota5d45f4c2019-03-10 22:35:07 -0700908 ret = bolero_clk_rsc_request_clock(wsa_priv->dev,
909 wsa_priv->default_clk_id,
910 wsa_priv->default_clk_id,
911 true);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530912 if (ret < 0) {
Ramprasad Katkam14efed62019-03-07 13:16:50 +0530913 dev_err_ratelimited(wsa_priv->dev,
Laxminath Kasam243e2752018-04-12 00:40:19 +0530914 "%s: wsa request clock enable failed\n",
915 __func__);
916 goto exit;
917 }
Vidyakumar Athota5d45f4c2019-03-10 22:35:07 -0700918 bolero_clk_rsc_fs_gen_request(wsa_priv->dev,
919 true);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530920 regcache_mark_dirty(regmap);
921 regcache_sync_region(regmap,
922 WSA_START_OFFSET,
923 WSA_MAX_OFFSET);
924 /* 9.6MHz MCLK, set value 0x00 if other frequency */
925 regmap_update_bits(regmap,
926 BOLERO_CDC_WSA_TOP_FREQ_MCLK, 0x01, 0x01);
927 regmap_update_bits(regmap,
928 BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL,
929 0x01, 0x01);
930 regmap_update_bits(regmap,
931 BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
932 0x01, 0x01);
933 }
Aditya Bavanaric496ed22018-11-16 15:50:40 +0530934 wsa_priv->wsa_mclk_users++;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530935 } else {
Aditya Bavanaric496ed22018-11-16 15:50:40 +0530936 if (wsa_priv->wsa_mclk_users <= 0) {
937 dev_err(wsa_priv->dev, "%s: clock already disabled\n",
938 __func__);
939 wsa_priv->wsa_mclk_users = 0;
940 goto exit;
941 }
Laxminath Kasam243e2752018-04-12 00:40:19 +0530942 wsa_priv->wsa_mclk_users--;
943 if (wsa_priv->wsa_mclk_users == 0) {
944 regmap_update_bits(regmap,
945 BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
946 0x01, 0x00);
947 regmap_update_bits(regmap,
948 BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL,
949 0x01, 0x00);
Vidyakumar Athota5d45f4c2019-03-10 22:35:07 -0700950 bolero_clk_rsc_fs_gen_request(wsa_priv->dev,
951 false);
952
953 bolero_clk_rsc_request_clock(wsa_priv->dev,
954 wsa_priv->default_clk_id,
955 wsa_priv->default_clk_id,
956 false);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530957 }
958 }
959exit:
960 mutex_unlock(&wsa_priv->mclk_lock);
961 return ret;
962}
963
964static int wsa_macro_mclk_event(struct snd_soc_dapm_widget *w,
965 struct snd_kcontrol *kcontrol, int event)
966{
Meng Wang15c825d2018-09-06 10:49:18 +0800967 struct snd_soc_component *component =
968 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530969 int ret = 0;
970 struct device *wsa_dev = NULL;
971 struct wsa_macro_priv *wsa_priv = NULL;
972
Meng Wang15c825d2018-09-06 10:49:18 +0800973 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +0530974 return -EINVAL;
975
976 dev_dbg(wsa_dev, "%s: event = %d\n", __func__, event);
977 switch (event) {
978 case SND_SOC_DAPM_PRE_PMU:
979 ret = wsa_macro_mclk_enable(wsa_priv, 1, true);
Ramprasad Katkam452772a2019-01-07 17:30:36 +0530980 if (ret)
981 wsa_priv->dapm_mclk_enable = false;
982 else
983 wsa_priv->dapm_mclk_enable = true;
Laxminath Kasam243e2752018-04-12 00:40:19 +0530984 break;
985 case SND_SOC_DAPM_POST_PMD:
Ramprasad Katkam452772a2019-01-07 17:30:36 +0530986 if (wsa_priv->dapm_mclk_enable)
987 wsa_macro_mclk_enable(wsa_priv, 0, true);
Laxminath Kasam243e2752018-04-12 00:40:19 +0530988 break;
989 default:
990 dev_err(wsa_priv->dev,
991 "%s: invalid DAPM event %d\n", __func__, event);
992 ret = -EINVAL;
993 }
994 return ret;
995}
996
Meng Wang15c825d2018-09-06 10:49:18 +0800997static int wsa_macro_event_handler(struct snd_soc_component *component,
998 u16 event, u32 data)
Laxminath Kasamfb0d6832018-09-22 01:49:52 +0530999{
1000 struct device *wsa_dev = NULL;
1001 struct wsa_macro_priv *wsa_priv = NULL;
Meng Wangbd930242019-06-25 09:39:48 +08001002 int ret = 0;
Laxminath Kasamfb0d6832018-09-22 01:49:52 +05301003
Meng Wang15c825d2018-09-06 10:49:18 +08001004 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasamfb0d6832018-09-22 01:49:52 +05301005 return -EINVAL;
1006
1007 switch (event) {
1008 case BOLERO_MACRO_EVT_SSR_DOWN:
Aditya Bavanarif500a1d2019-09-16 18:27:51 -07001009 trace_printk("%s, enter SSR down\n", __func__);
Karthikeyan Mani3bd80a52019-06-04 23:40:16 -07001010 if (wsa_priv->swr_ctrl_data) {
1011 swrm_wcd_notify(
1012 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
Karthikeyan Mani3bd80a52019-06-04 23:40:16 -07001013 SWR_DEVICE_SSR_DOWN, NULL);
1014 }
Aditya Bavanari50ef13e2019-08-09 15:14:43 +05301015 if ((!pm_runtime_enabled(wsa_dev) ||
1016 !pm_runtime_suspended(wsa_dev))) {
1017 ret = bolero_runtime_suspend(wsa_dev);
1018 if (!ret) {
1019 pm_runtime_disable(wsa_dev);
1020 pm_runtime_set_suspended(wsa_dev);
1021 pm_runtime_enable(wsa_dev);
1022 }
1023 }
Laxminath Kasamfb0d6832018-09-22 01:49:52 +05301024 break;
Prasad Kumpatlaefdb3932020-05-13 18:55:32 +05301025 case BOLERO_MACRO_EVT_PRE_SSR_UP:
Meng Wangbd930242019-06-25 09:39:48 +08001026 /* enable&disable WSA_CORE_CLK to reset GFMUX reg */
1027 ret = bolero_clk_rsc_request_clock(wsa_priv->dev,
1028 wsa_priv->default_clk_id,
1029 WSA_CORE_CLK, true);
1030 if (ret < 0)
1031 dev_err_ratelimited(wsa_priv->dev,
1032 "%s, failed to enable clk, ret:%d\n",
1033 __func__, ret);
1034 else
1035 bolero_clk_rsc_request_clock(wsa_priv->dev,
1036 wsa_priv->default_clk_id,
1037 WSA_CORE_CLK, false);
Prasad Kumpatlaefdb3932020-05-13 18:55:32 +05301038 break;
1039 case BOLERO_MACRO_EVT_SSR_UP:
1040 trace_printk("%s, enter SSR up\n", __func__);
1041 /* reset swr after ssr/pdr */
1042 wsa_priv->reset_swr = true;
Karthikeyan Mani3bd80a52019-06-04 23:40:16 -07001043 if (wsa_priv->swr_ctrl_data)
1044 swrm_wcd_notify(
1045 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
1046 SWR_DEVICE_SSR_UP, NULL);
Laxminath Kasamfb0d6832018-09-22 01:49:52 +05301047 break;
Meng Wang8ef0cc22019-05-08 15:12:56 +08001048 case BOLERO_MACRO_EVT_CLK_RESET:
1049 bolero_rsc_clk_reset(wsa_dev, WSA_CORE_CLK);
1050 break;
Laxminath Kasamfb0d6832018-09-22 01:49:52 +05301051 }
1052 return 0;
1053}
1054
Laxminath Kasam243e2752018-04-12 00:40:19 +05301055static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w,
1056 struct snd_kcontrol *kcontrol,
1057 int event)
1058{
Meng Wang15c825d2018-09-06 10:49:18 +08001059 struct snd_soc_component *component =
1060 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301061 struct device *wsa_dev = NULL;
1062 struct wsa_macro_priv *wsa_priv = NULL;
Laxminath Kasam007d2522020-04-23 11:00:44 +05301063 u8 val = 0x0;
Laxminath Kasam243e2752018-04-12 00:40:19 +05301064
Meng Wang15c825d2018-09-06 10:49:18 +08001065 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301066 return -EINVAL;
1067
Laxminath Kasam007d2522020-04-23 11:00:44 +05301068 switch (wsa_priv->pcm_rate_vi) {
1069 case 48000:
1070 val = 0x04;
1071 break;
1072 case 24000:
1073 val = 0x02;
1074 break;
1075 case 8000:
1076 default:
1077 val = 0x00;
1078 break;
1079 }
1080
Laxminath Kasam243e2752018-04-12 00:40:19 +05301081 switch (event) {
1082 case SND_SOC_DAPM_POST_PMU:
1083 if (test_bit(WSA_MACRO_TX0,
1084 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
1085 dev_dbg(wsa_dev, "%s: spkr1 enabled\n", __func__);
1086 /* Enable V&I sensing */
Meng Wang15c825d2018-09-06 10:49:18 +08001087 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301088 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
1089 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +08001090 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301091 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
1092 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +08001093 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301094 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
Laxminath Kasam007d2522020-04-23 11:00:44 +05301095 0x0F, val);
Meng Wang15c825d2018-09-06 10:49:18 +08001096 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301097 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
Laxminath Kasam007d2522020-04-23 11:00:44 +05301098 0x0F, val);
Meng Wang15c825d2018-09-06 10:49:18 +08001099 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301100 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
1101 0x10, 0x10);
Meng Wang15c825d2018-09-06 10:49:18 +08001102 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301103 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
1104 0x10, 0x10);
Meng Wang15c825d2018-09-06 10:49:18 +08001105 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301106 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
1107 0x20, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001108 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301109 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
1110 0x20, 0x00);
1111 }
1112 if (test_bit(WSA_MACRO_TX1,
1113 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
1114 dev_dbg(wsa_dev, "%s: spkr2 enabled\n", __func__);
1115 /* Enable V&I sensing */
Meng Wang15c825d2018-09-06 10:49:18 +08001116 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301117 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
1118 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +08001119 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301120 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
1121 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +08001122 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301123 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
Laxminath Kasam007d2522020-04-23 11:00:44 +05301124 0x0F, val);
Meng Wang15c825d2018-09-06 10:49:18 +08001125 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301126 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
Laxminath Kasam007d2522020-04-23 11:00:44 +05301127 0x0F, val);
Meng Wang15c825d2018-09-06 10:49:18 +08001128 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301129 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
1130 0x10, 0x10);
Meng Wang15c825d2018-09-06 10:49:18 +08001131 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301132 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
1133 0x10, 0x10);
Meng Wang15c825d2018-09-06 10:49:18 +08001134 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301135 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
1136 0x20, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001137 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301138 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
1139 0x20, 0x00);
1140 }
1141 break;
1142 case SND_SOC_DAPM_POST_PMD:
1143 if (test_bit(WSA_MACRO_TX0,
1144 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
1145 /* Disable V&I sensing */
Meng Wang15c825d2018-09-06 10:49:18 +08001146 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301147 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
1148 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +08001149 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301150 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
1151 0x20, 0x20);
1152 dev_dbg(wsa_dev, "%s: spkr1 disabled\n", __func__);
Meng Wang15c825d2018-09-06 10:49:18 +08001153 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301154 BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
1155 0x10, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001156 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301157 BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
1158 0x10, 0x00);
1159 }
1160 if (test_bit(WSA_MACRO_TX1,
1161 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
1162 /* Disable V&I sensing */
1163 dev_dbg(wsa_dev, "%s: spkr2 disabled\n", __func__);
Meng Wang15c825d2018-09-06 10:49:18 +08001164 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301165 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
1166 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +08001167 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301168 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
1169 0x20, 0x20);
Meng Wang15c825d2018-09-06 10:49:18 +08001170 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301171 BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
1172 0x10, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001173 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301174 BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
1175 0x10, 0x00);
1176 }
1177 break;
1178 }
1179
1180 return 0;
1181}
1182
1183static int wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w,
1184 struct snd_kcontrol *kcontrol, int event)
1185{
Meng Wang15c825d2018-09-06 10:49:18 +08001186 struct snd_soc_component *component =
1187 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301188 u16 gain_reg;
1189 int offset_val = 0;
1190 int val = 0;
1191
Meng Wang15c825d2018-09-06 10:49:18 +08001192 dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301193
1194 switch (w->reg) {
1195 case BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL:
1196 gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_MIX_CTL;
1197 break;
1198 case BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL:
1199 gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_MIX_CTL;
1200 break;
1201 default:
Meng Wang15c825d2018-09-06 10:49:18 +08001202 dev_err(component->dev, "%s: No gain register avail for %s\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301203 __func__, w->name);
1204 return 0;
1205 }
1206
1207 switch (event) {
1208 case SND_SOC_DAPM_POST_PMU:
Meng Wang15c825d2018-09-06 10:49:18 +08001209 val = snd_soc_component_read32(component, gain_reg);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301210 val += offset_val;
Meng Wang15c825d2018-09-06 10:49:18 +08001211 snd_soc_component_write(component, gain_reg, val);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301212 break;
1213 case SND_SOC_DAPM_POST_PMD:
Laxminath Kasam52ae6582019-08-08 18:00:35 +05301214 snd_soc_component_update_bits(component,
1215 w->reg, 0x20, 0x00);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301216 break;
1217 }
1218
1219 return 0;
1220}
1221
Meng Wang15c825d2018-09-06 10:49:18 +08001222static void wsa_macro_hd2_control(struct snd_soc_component *component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301223 u16 reg, int event)
1224{
1225 u16 hd2_scale_reg;
1226 u16 hd2_enable_reg = 0;
1227
1228 if (reg == BOLERO_CDC_WSA_RX0_RX_PATH_CTL) {
1229 hd2_scale_reg = BOLERO_CDC_WSA_RX0_RX_PATH_SEC3;
1230 hd2_enable_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG0;
1231 }
1232 if (reg == BOLERO_CDC_WSA_RX1_RX_PATH_CTL) {
1233 hd2_scale_reg = BOLERO_CDC_WSA_RX1_RX_PATH_SEC3;
1234 hd2_enable_reg = BOLERO_CDC_WSA_RX1_RX_PATH_CFG0;
1235 }
1236
1237 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001238 snd_soc_component_update_bits(component, hd2_scale_reg,
1239 0x3C, 0x10);
1240 snd_soc_component_update_bits(component, hd2_scale_reg,
1241 0x03, 0x01);
1242 snd_soc_component_update_bits(component, hd2_enable_reg,
1243 0x04, 0x04);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301244 }
1245
1246 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001247 snd_soc_component_update_bits(component, hd2_enable_reg,
1248 0x04, 0x00);
1249 snd_soc_component_update_bits(component, hd2_scale_reg,
1250 0x03, 0x00);
1251 snd_soc_component_update_bits(component, hd2_scale_reg,
1252 0x3C, 0x00);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301253 }
1254}
1255
1256static int wsa_macro_enable_swr(struct snd_soc_dapm_widget *w,
1257 struct snd_kcontrol *kcontrol, int event)
1258{
Meng Wang15c825d2018-09-06 10:49:18 +08001259 struct snd_soc_component *component =
1260 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301261 int ch_cnt;
1262 struct device *wsa_dev = NULL;
1263 struct wsa_macro_priv *wsa_priv = NULL;
1264
Meng Wang15c825d2018-09-06 10:49:18 +08001265 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301266 return -EINVAL;
1267
1268 switch (event) {
1269 case SND_SOC_DAPM_PRE_PMU:
1270 if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) &&
1271 !wsa_priv->rx_0_count)
1272 wsa_priv->rx_0_count++;
1273 if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) &&
1274 !wsa_priv->rx_1_count)
1275 wsa_priv->rx_1_count++;
1276 ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
1277
Karthikeyan Mani3bd80a52019-06-04 23:40:16 -07001278 if (wsa_priv->swr_ctrl_data) {
1279 swrm_wcd_notify(
1280 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
1281 SWR_DEVICE_UP, NULL);
1282 swrm_wcd_notify(
1283 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
1284 SWR_SET_NUM_RX_CH, &ch_cnt);
1285 }
Laxminath Kasam243e2752018-04-12 00:40:19 +05301286 break;
1287 case SND_SOC_DAPM_POST_PMD:
1288 if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) &&
1289 wsa_priv->rx_0_count)
1290 wsa_priv->rx_0_count--;
1291 if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) &&
1292 wsa_priv->rx_1_count)
1293 wsa_priv->rx_1_count--;
1294 ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
1295
Karthikeyan Mani3bd80a52019-06-04 23:40:16 -07001296 if (wsa_priv->swr_ctrl_data)
1297 swrm_wcd_notify(
1298 wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
1299 SWR_SET_NUM_RX_CH, &ch_cnt);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301300 break;
1301 }
1302 dev_dbg(wsa_priv->dev, "%s: current swr ch cnt: %d\n",
1303 __func__, wsa_priv->rx_0_count + wsa_priv->rx_1_count);
1304
1305 return 0;
1306}
1307
Meng Wang15c825d2018-09-06 10:49:18 +08001308static int wsa_macro_config_compander(struct snd_soc_component *component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301309 int comp, int event)
1310{
1311 u16 comp_ctl0_reg, rx_path_cfg0_reg;
1312 struct device *wsa_dev = NULL;
1313 struct wsa_macro_priv *wsa_priv = NULL;
1314
Meng Wang15c825d2018-09-06 10:49:18 +08001315 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301316 return -EINVAL;
1317
Meng Wang15c825d2018-09-06 10:49:18 +08001318 dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301319 __func__, event, comp + 1, wsa_priv->comp_enabled[comp]);
1320
1321 if (!wsa_priv->comp_enabled[comp])
1322 return 0;
1323
1324 comp_ctl0_reg = BOLERO_CDC_WSA_COMPANDER0_CTL0 +
1325 (comp * WSA_MACRO_RX_COMP_OFFSET);
1326 rx_path_cfg0_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG0 +
1327 (comp * WSA_MACRO_RX_PATH_OFFSET);
1328
1329 if (SND_SOC_DAPM_EVENT_ON(event)) {
1330 /* Enable Compander Clock */
Meng Wang15c825d2018-09-06 10:49:18 +08001331 snd_soc_component_update_bits(component, comp_ctl0_reg,
1332 0x01, 0x01);
1333 snd_soc_component_update_bits(component, comp_ctl0_reg,
1334 0x02, 0x02);
1335 snd_soc_component_update_bits(component, comp_ctl0_reg,
1336 0x02, 0x00);
1337 snd_soc_component_update_bits(component, rx_path_cfg0_reg,
1338 0x02, 0x02);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301339 }
1340
1341 if (SND_SOC_DAPM_EVENT_OFF(event)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001342 snd_soc_component_update_bits(component, comp_ctl0_reg,
1343 0x04, 0x04);
1344 snd_soc_component_update_bits(component, rx_path_cfg0_reg,
1345 0x02, 0x00);
1346 snd_soc_component_update_bits(component, comp_ctl0_reg,
1347 0x02, 0x02);
1348 snd_soc_component_update_bits(component, comp_ctl0_reg,
1349 0x02, 0x00);
1350 snd_soc_component_update_bits(component, comp_ctl0_reg,
1351 0x01, 0x00);
1352 snd_soc_component_update_bits(component, comp_ctl0_reg,
1353 0x04, 0x00);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301354 }
1355
1356 return 0;
1357}
1358
Meng Wang15c825d2018-09-06 10:49:18 +08001359static void wsa_macro_enable_softclip_clk(struct snd_soc_component *component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301360 struct wsa_macro_priv *wsa_priv,
1361 int path,
1362 bool enable)
1363{
1364 u16 softclip_clk_reg = BOLERO_CDC_WSA_SOFTCLIP0_CRC +
1365 (path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
1366 u8 softclip_mux_mask = (1 << path);
1367 u8 softclip_mux_value = (1 << path);
1368
Meng Wang15c825d2018-09-06 10:49:18 +08001369 dev_dbg(component->dev, "%s: path %d, enable %d\n",
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301370 __func__, path, enable);
1371 if (enable) {
1372 if (wsa_priv->softclip_clk_users[path] == 0) {
Meng Wang15c825d2018-09-06 10:49:18 +08001373 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301374 softclip_clk_reg, 0x01, 0x01);
Meng Wang15c825d2018-09-06 10:49:18 +08001375 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301376 BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
1377 softclip_mux_mask, softclip_mux_value);
1378 }
1379 wsa_priv->softclip_clk_users[path]++;
1380 } else {
1381 wsa_priv->softclip_clk_users[path]--;
1382 if (wsa_priv->softclip_clk_users[path] == 0) {
Meng Wang15c825d2018-09-06 10:49:18 +08001383 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301384 softclip_clk_reg, 0x01, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001385 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301386 BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
1387 softclip_mux_mask, 0x00);
1388 }
1389 }
1390}
1391
Meng Wang15c825d2018-09-06 10:49:18 +08001392static int wsa_macro_config_softclip(struct snd_soc_component *component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301393 int path, int event)
1394{
1395 u16 softclip_ctrl_reg = 0;
1396 struct device *wsa_dev = NULL;
1397 struct wsa_macro_priv *wsa_priv = NULL;
1398 int softclip_path = 0;
1399
Meng Wang15c825d2018-09-06 10:49:18 +08001400 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301401 return -EINVAL;
1402
1403 if (path == WSA_MACRO_COMP1)
1404 softclip_path = WSA_MACRO_SOFTCLIP0;
1405 else if (path == WSA_MACRO_COMP2)
1406 softclip_path = WSA_MACRO_SOFTCLIP1;
1407
Meng Wang15c825d2018-09-06 10:49:18 +08001408 dev_dbg(component->dev, "%s: event %d path %d, enabled %d\n",
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301409 __func__, event, softclip_path,
1410 wsa_priv->is_softclip_on[softclip_path]);
1411
1412 if (!wsa_priv->is_softclip_on[softclip_path])
1413 return 0;
1414
1415 softclip_ctrl_reg = BOLERO_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL +
1416 (softclip_path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
1417
1418 if (SND_SOC_DAPM_EVENT_ON(event)) {
1419 /* Enable Softclip clock and mux */
Meng Wang15c825d2018-09-06 10:49:18 +08001420 wsa_macro_enable_softclip_clk(component, wsa_priv,
1421 softclip_path, true);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301422 /* Enable Softclip control */
Meng Wang15c825d2018-09-06 10:49:18 +08001423 snd_soc_component_update_bits(component, softclip_ctrl_reg,
1424 0x01, 0x01);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301425 }
1426
1427 if (SND_SOC_DAPM_EVENT_OFF(event)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001428 snd_soc_component_update_bits(component, softclip_ctrl_reg,
1429 0x01, 0x00);
1430 wsa_macro_enable_softclip_clk(component, wsa_priv,
1431 softclip_path, false);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301432 }
1433
1434 return 0;
1435}
1436
Laxminath Kasam52ae6582019-08-08 18:00:35 +05301437static bool wsa_macro_adie_lb(struct snd_soc_component *component,
1438 int interp_idx)
1439{
1440 u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
1441 u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
1442 u8 int_n_inp0 = 0, int_n_inp1 = 0, int_n_inp2 = 0;
1443
1444 int_mux_cfg0 = BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 + interp_idx * 8;
1445 int_mux_cfg1 = int_mux_cfg0 + 4;
1446 int_mux_cfg0_val = snd_soc_component_read32(component, int_mux_cfg0);
1447 int_mux_cfg1_val = snd_soc_component_read32(component, int_mux_cfg1);
1448
1449 int_n_inp0 = int_mux_cfg0_val & 0x0F;
1450 if (int_n_inp0 == INTn_1_INP_SEL_DEC0 ||
1451 int_n_inp0 == INTn_1_INP_SEL_DEC1)
1452 return true;
1453
1454 int_n_inp1 = int_mux_cfg0_val >> 4;
1455 if (int_n_inp1 == INTn_1_INP_SEL_DEC0 ||
1456 int_n_inp1 == INTn_1_INP_SEL_DEC1)
1457 return true;
1458
1459 int_n_inp2 = int_mux_cfg1_val >> 4;
1460 if (int_n_inp2 == INTn_1_INP_SEL_DEC0 ||
1461 int_n_inp2 == INTn_1_INP_SEL_DEC1)
1462 return true;
1463
1464 return false;
1465}
1466
1467static int wsa_macro_enable_main_path(struct snd_soc_dapm_widget *w,
1468 struct snd_kcontrol *kcontrol,
1469 int event)
1470{
1471 struct snd_soc_component *component =
1472 snd_soc_dapm_to_component(w->dapm);
1473 u16 reg = 0;
Laxminath Kasam069df142019-09-17 23:43:34 +05301474 struct device *wsa_dev = NULL;
1475 struct wsa_macro_priv *wsa_priv = NULL;
1476
1477 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
1478 return -EINVAL;
1479
Laxminath Kasam52ae6582019-08-08 18:00:35 +05301480
1481 reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL +
1482 WSA_MACRO_RX_PATH_OFFSET * w->shift;
1483 switch (event) {
1484 case SND_SOC_DAPM_PRE_PMU:
Laxminath Kasam069df142019-09-17 23:43:34 +05301485 if (wsa_macro_adie_lb(component, w->shift)) {
Laxminath Kasam52ae6582019-08-08 18:00:35 +05301486 snd_soc_component_update_bits(component,
1487 reg, 0x20, 0x20);
Laxminath Kasam069df142019-09-17 23:43:34 +05301488 bolero_wsa_pa_on(wsa_dev);
1489 }
Laxminath Kasam52ae6582019-08-08 18:00:35 +05301490 break;
1491 default:
1492 break;
1493 }
1494 return 0;
1495}
1496
Laxminath Kasam243e2752018-04-12 00:40:19 +05301497static int wsa_macro_interp_get_primary_reg(u16 reg, u16 *ind)
1498{
1499 u16 prim_int_reg = 0;
1500
1501 switch (reg) {
1502 case BOLERO_CDC_WSA_RX0_RX_PATH_CTL:
1503 case BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL:
1504 prim_int_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
1505 *ind = 0;
1506 break;
1507 case BOLERO_CDC_WSA_RX1_RX_PATH_CTL:
1508 case BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL:
1509 prim_int_reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
1510 *ind = 1;
1511 break;
1512 }
1513
1514 return prim_int_reg;
1515}
1516
1517static int wsa_macro_enable_prim_interpolator(
Meng Wang15c825d2018-09-06 10:49:18 +08001518 struct snd_soc_component *component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301519 u16 reg, int event)
1520{
1521 u16 prim_int_reg;
1522 u16 ind = 0;
1523 struct device *wsa_dev = NULL;
1524 struct wsa_macro_priv *wsa_priv = NULL;
1525
Meng Wang15c825d2018-09-06 10:49:18 +08001526 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301527 return -EINVAL;
1528
1529 prim_int_reg = wsa_macro_interp_get_primary_reg(reg, &ind);
1530
1531 switch (event) {
1532 case SND_SOC_DAPM_PRE_PMU:
1533 wsa_priv->prim_int_users[ind]++;
1534 if (wsa_priv->prim_int_users[ind] == 1) {
Meng Wang15c825d2018-09-06 10:49:18 +08001535 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301536 prim_int_reg + WSA_MACRO_RX_PATH_CFG3_OFFSET,
1537 0x03, 0x03);
Meng Wang15c825d2018-09-06 10:49:18 +08001538 snd_soc_component_update_bits(component, prim_int_reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301539 0x10, 0x10);
Meng Wang15c825d2018-09-06 10:49:18 +08001540 wsa_macro_hd2_control(component, prim_int_reg, event);
1541 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301542 prim_int_reg + WSA_MACRO_RX_PATH_DSMDEM_OFFSET,
1543 0x1, 0x1);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301544 }
1545 if ((reg != prim_int_reg) &&
Meng Wang15c825d2018-09-06 10:49:18 +08001546 ((snd_soc_component_read32(
1547 component, prim_int_reg)) & 0x10))
1548 snd_soc_component_update_bits(component, reg,
1549 0x10, 0x10);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301550 break;
1551 case SND_SOC_DAPM_POST_PMD:
1552 wsa_priv->prim_int_users[ind]--;
1553 if (wsa_priv->prim_int_users[ind] == 0) {
Meng Wang15c825d2018-09-06 10:49:18 +08001554 snd_soc_component_update_bits(component, prim_int_reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301555 1 << 0x5, 0 << 0x5);
Laxminath Kasam52ae6582019-08-08 18:00:35 +05301556 snd_soc_component_update_bits(component,
1557 prim_int_reg + WSA_MACRO_RX_PATH_DSMDEM_OFFSET,
1558 0x1, 0x0);
Meng Wang15c825d2018-09-06 10:49:18 +08001559 snd_soc_component_update_bits(component, prim_int_reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301560 0x40, 0x40);
Meng Wang15c825d2018-09-06 10:49:18 +08001561 snd_soc_component_update_bits(component, prim_int_reg,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301562 0x40, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001563 wsa_macro_hd2_control(component, prim_int_reg, event);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301564 }
1565 break;
1566 }
1567
Meng Wang15c825d2018-09-06 10:49:18 +08001568 dev_dbg(component->dev, "%s: primary interpolator: INT%d, users: %d\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301569 __func__, ind, wsa_priv->prim_int_users[ind]);
1570 return 0;
1571}
1572
1573static int wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w,
1574 struct snd_kcontrol *kcontrol,
1575 int event)
1576{
Meng Wang15c825d2018-09-06 10:49:18 +08001577 struct snd_soc_component *component =
1578 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301579 u16 gain_reg;
1580 u16 reg;
1581 int val;
1582 int offset_val = 0;
1583 struct device *wsa_dev = NULL;
1584 struct wsa_macro_priv *wsa_priv = NULL;
1585
Meng Wang15c825d2018-09-06 10:49:18 +08001586 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05301587 return -EINVAL;
1588
Meng Wang15c825d2018-09-06 10:49:18 +08001589 dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301590
1591 if (!(strcmp(w->name, "WSA_RX INT0 INTERP"))) {
1592 reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
1593 gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_CTL;
1594 } else if (!(strcmp(w->name, "WSA_RX INT1 INTERP"))) {
1595 reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
1596 gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_CTL;
1597 } else {
Meng Wang15c825d2018-09-06 10:49:18 +08001598 dev_err(component->dev, "%s: Interpolator reg not found\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301599 __func__);
1600 return -EINVAL;
1601 }
1602
1603 switch (event) {
1604 case SND_SOC_DAPM_PRE_PMU:
1605 /* Reset if needed */
Meng Wang15c825d2018-09-06 10:49:18 +08001606 wsa_macro_enable_prim_interpolator(component, reg, event);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301607 break;
1608 case SND_SOC_DAPM_POST_PMU:
Meng Wang15c825d2018-09-06 10:49:18 +08001609 wsa_macro_config_compander(component, w->shift, event);
1610 wsa_macro_config_softclip(component, w->shift, event);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301611 /* apply gain after int clk is enabled */
Laxminath Kasam21c8b222018-06-21 18:47:22 +05301612 if ((wsa_priv->spkr_gain_offset ==
1613 WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
Laxminath Kasam243e2752018-04-12 00:40:19 +05301614 (wsa_priv->comp_enabled[WSA_MACRO_COMP1] ||
1615 wsa_priv->comp_enabled[WSA_MACRO_COMP2]) &&
1616 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL ||
1617 gain_reg == BOLERO_CDC_WSA_RX1_RX_VOL_CTL)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001618 snd_soc_component_update_bits(component,
1619 BOLERO_CDC_WSA_RX0_RX_PATH_SEC1,
1620 0x01, 0x01);
1621 snd_soc_component_update_bits(component,
1622 BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC0,
1623 0x01, 0x01);
1624 snd_soc_component_update_bits(component,
1625 BOLERO_CDC_WSA_RX1_RX_PATH_SEC1,
1626 0x01, 0x01);
1627 snd_soc_component_update_bits(component,
1628 BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC0,
1629 0x01, 0x01);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301630 offset_val = -2;
1631 }
Meng Wang15c825d2018-09-06 10:49:18 +08001632 val = snd_soc_component_read32(component, gain_reg);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301633 val += offset_val;
Meng Wang15c825d2018-09-06 10:49:18 +08001634 snd_soc_component_write(component, gain_reg, val);
1635 wsa_macro_config_ear_spkr_gain(component, wsa_priv,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301636 event, gain_reg);
1637 break;
1638 case SND_SOC_DAPM_POST_PMD:
Meng Wang15c825d2018-09-06 10:49:18 +08001639 wsa_macro_config_compander(component, w->shift, event);
1640 wsa_macro_config_softclip(component, w->shift, event);
1641 wsa_macro_enable_prim_interpolator(component, reg, event);
Laxminath Kasam21c8b222018-06-21 18:47:22 +05301642 if ((wsa_priv->spkr_gain_offset ==
1643 WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
Laxminath Kasam243e2752018-04-12 00:40:19 +05301644 (wsa_priv->comp_enabled[WSA_MACRO_COMP1] ||
1645 wsa_priv->comp_enabled[WSA_MACRO_COMP2]) &&
1646 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL ||
1647 gain_reg == BOLERO_CDC_WSA_RX1_RX_VOL_CTL)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001648 snd_soc_component_update_bits(component,
1649 BOLERO_CDC_WSA_RX0_RX_PATH_SEC1,
1650 0x01, 0x00);
1651 snd_soc_component_update_bits(component,
1652 BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC0,
1653 0x01, 0x00);
1654 snd_soc_component_update_bits(component,
1655 BOLERO_CDC_WSA_RX1_RX_PATH_SEC1,
1656 0x01, 0x00);
1657 snd_soc_component_update_bits(component,
1658 BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC0,
1659 0x01, 0x00);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301660 offset_val = 2;
Meng Wang15c825d2018-09-06 10:49:18 +08001661 val = snd_soc_component_read32(component, gain_reg);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301662 val += offset_val;
Meng Wang15c825d2018-09-06 10:49:18 +08001663 snd_soc_component_write(component, gain_reg, val);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301664 }
Meng Wang15c825d2018-09-06 10:49:18 +08001665 wsa_macro_config_ear_spkr_gain(component, wsa_priv,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301666 event, gain_reg);
1667 break;
1668 }
1669
1670 return 0;
1671}
1672
Meng Wang15c825d2018-09-06 10:49:18 +08001673static int wsa_macro_config_ear_spkr_gain(struct snd_soc_component *component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05301674 struct wsa_macro_priv *wsa_priv,
1675 int event, int gain_reg)
1676{
1677 int comp_gain_offset, val;
1678
1679 switch (wsa_priv->spkr_mode) {
Laxminath Kasam21c8b222018-06-21 18:47:22 +05301680 /* Compander gain in WSA_MACRO_SPKR_MODE1 case is 12 dB */
1681 case WSA_MACRO_SPKR_MODE_1:
Laxminath Kasam243e2752018-04-12 00:40:19 +05301682 comp_gain_offset = -12;
1683 break;
1684 /* Default case compander gain is 15 dB */
1685 default:
1686 comp_gain_offset = -15;
1687 break;
1688 }
1689
1690 switch (event) {
1691 case SND_SOC_DAPM_POST_PMU:
1692 /* Apply ear spkr gain only if compander is enabled */
1693 if (wsa_priv->comp_enabled[WSA_MACRO_COMP1] &&
1694 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL) &&
1695 (wsa_priv->ear_spkr_gain != 0)) {
1696 /* For example, val is -8(-12+5-1) for 4dB of gain */
1697 val = comp_gain_offset + wsa_priv->ear_spkr_gain - 1;
Meng Wang15c825d2018-09-06 10:49:18 +08001698 snd_soc_component_write(component, gain_reg, val);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301699
1700 dev_dbg(wsa_priv->dev, "%s: RX0 Volume %d dB\n",
1701 __func__, val);
1702 }
1703 break;
1704 case SND_SOC_DAPM_POST_PMD:
1705 /*
1706 * Reset RX0 volume to 0 dB if compander is enabled and
1707 * ear_spkr_gain is non-zero.
1708 */
1709 if (wsa_priv->comp_enabled[WSA_MACRO_COMP1] &&
1710 (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL) &&
1711 (wsa_priv->ear_spkr_gain != 0)) {
Meng Wang15c825d2018-09-06 10:49:18 +08001712 snd_soc_component_write(component, gain_reg, 0x0);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301713
1714 dev_dbg(wsa_priv->dev, "%s: Reset RX0 Volume to 0 dB\n",
1715 __func__);
1716 }
1717 break;
1718 }
1719
1720 return 0;
1721}
1722
1723static int wsa_macro_spk_boost_event(struct snd_soc_dapm_widget *w,
1724 struct snd_kcontrol *kcontrol,
1725 int event)
1726{
Meng Wang15c825d2018-09-06 10:49:18 +08001727 struct snd_soc_component *component =
1728 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301729 u16 boost_path_ctl, boost_path_cfg1;
1730 u16 reg, reg_mix;
1731
Meng Wang15c825d2018-09-06 10:49:18 +08001732 dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301733
1734 if (!strcmp(w->name, "WSA_RX INT0 CHAIN")) {
1735 boost_path_ctl = BOLERO_CDC_WSA_BOOST0_BOOST_PATH_CTL;
1736 boost_path_cfg1 = BOLERO_CDC_WSA_RX0_RX_PATH_CFG1;
1737 reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
1738 reg_mix = BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL;
1739 } else if (!strcmp(w->name, "WSA_RX INT1 CHAIN")) {
1740 boost_path_ctl = BOLERO_CDC_WSA_BOOST1_BOOST_PATH_CTL;
1741 boost_path_cfg1 = BOLERO_CDC_WSA_RX1_RX_PATH_CFG1;
1742 reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
1743 reg_mix = BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL;
1744 } else {
Meng Wang15c825d2018-09-06 10:49:18 +08001745 dev_err(component->dev, "%s: unknown widget: %s\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05301746 __func__, w->name);
1747 return -EINVAL;
1748 }
1749
1750 switch (event) {
1751 case SND_SOC_DAPM_PRE_PMU:
Meng Wang15c825d2018-09-06 10:49:18 +08001752 snd_soc_component_update_bits(component, boost_path_cfg1,
1753 0x01, 0x01);
1754 snd_soc_component_update_bits(component, boost_path_ctl,
1755 0x10, 0x10);
1756 if ((snd_soc_component_read32(component, reg_mix)) & 0x10)
1757 snd_soc_component_update_bits(component, reg_mix,
1758 0x10, 0x00);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301759 break;
Laxminath Kasam0c857002018-07-17 23:47:17 +05301760 case SND_SOC_DAPM_POST_PMU:
Meng Wang15c825d2018-09-06 10:49:18 +08001761 snd_soc_component_update_bits(component, reg, 0x10, 0x00);
Laxminath Kasam0c857002018-07-17 23:47:17 +05301762 break;
Laxminath Kasam243e2752018-04-12 00:40:19 +05301763 case SND_SOC_DAPM_POST_PMD:
Meng Wang15c825d2018-09-06 10:49:18 +08001764 snd_soc_component_update_bits(component, boost_path_ctl,
1765 0x10, 0x00);
1766 snd_soc_component_update_bits(component, boost_path_cfg1,
1767 0x01, 0x00);
Laxminath Kasam243e2752018-04-12 00:40:19 +05301768 break;
1769 }
1770
1771 return 0;
1772}
1773
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301774
1775static int wsa_macro_enable_vbat(struct snd_soc_dapm_widget *w,
1776 struct snd_kcontrol *kcontrol,
1777 int event)
1778{
Meng Wang15c825d2018-09-06 10:49:18 +08001779 struct snd_soc_component *component =
1780 snd_soc_dapm_to_component(w->dapm);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301781 struct device *wsa_dev = NULL;
1782 struct wsa_macro_priv *wsa_priv = NULL;
1783 u16 vbat_path_cfg = 0;
1784 int softclip_path = 0;
1785
Meng Wang15c825d2018-09-06 10:49:18 +08001786 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301787 return -EINVAL;
1788
Meng Wang15c825d2018-09-06 10:49:18 +08001789 dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301790 if (!strcmp(w->name, "WSA_RX INT0 VBAT")) {
1791 vbat_path_cfg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG1;
1792 softclip_path = WSA_MACRO_SOFTCLIP0;
1793 } else if (!strcmp(w->name, "WSA_RX INT1 VBAT")) {
1794 vbat_path_cfg = BOLERO_CDC_WSA_RX1_RX_PATH_CFG1;
1795 softclip_path = WSA_MACRO_SOFTCLIP1;
1796 }
1797
1798 switch (event) {
1799 case SND_SOC_DAPM_PRE_PMU:
1800 /* Enable clock for VBAT block */
Meng Wang15c825d2018-09-06 10:49:18 +08001801 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301802 BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x10);
1803 /* Enable VBAT block */
Meng Wang15c825d2018-09-06 10:49:18 +08001804 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301805 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x01);
1806 /* Update interpolator with 384K path */
Meng Wang15c825d2018-09-06 10:49:18 +08001807 snd_soc_component_update_bits(component, vbat_path_cfg,
1808 0x80, 0x80);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301809 /* Use attenuation mode */
Meng Wang15c825d2018-09-06 10:49:18 +08001810 snd_soc_component_update_bits(component,
1811 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x02, 0x00);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301812 /*
1813 * BCL block needs softclip clock and mux config to be enabled
1814 */
Meng Wang15c825d2018-09-06 10:49:18 +08001815 wsa_macro_enable_softclip_clk(component, wsa_priv,
1816 softclip_path, true);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301817 /* Enable VBAT at channel level */
Meng Wang15c825d2018-09-06 10:49:18 +08001818 snd_soc_component_update_bits(component, vbat_path_cfg,
1819 0x02, 0x02);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301820 /* Set the ATTK1 gain */
Meng Wang15c825d2018-09-06 10:49:18 +08001821 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301822 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
1823 0xFF, 0xFF);
Meng Wang15c825d2018-09-06 10:49:18 +08001824 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301825 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
1826 0xFF, 0x03);
Meng Wang15c825d2018-09-06 10:49:18 +08001827 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301828 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
1829 0xFF, 0x00);
1830 /* Set the ATTK2 gain */
Meng Wang15c825d2018-09-06 10:49:18 +08001831 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301832 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
1833 0xFF, 0xFF);
Meng Wang15c825d2018-09-06 10:49:18 +08001834 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301835 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
1836 0xFF, 0x03);
Meng Wang15c825d2018-09-06 10:49:18 +08001837 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301838 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
1839 0xFF, 0x00);
1840 /* Set the ATTK3 gain */
Meng Wang15c825d2018-09-06 10:49:18 +08001841 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301842 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
1843 0xFF, 0xFF);
Meng Wang15c825d2018-09-06 10:49:18 +08001844 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301845 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
1846 0xFF, 0x03);
Meng Wang15c825d2018-09-06 10:49:18 +08001847 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301848 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
1849 0xFF, 0x00);
1850 break;
1851
1852 case SND_SOC_DAPM_POST_PMD:
Meng Wang15c825d2018-09-06 10:49:18 +08001853 snd_soc_component_update_bits(component, vbat_path_cfg,
1854 0x80, 0x00);
1855 snd_soc_component_update_bits(component,
1856 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
1857 0x02, 0x02);
1858 snd_soc_component_update_bits(component, vbat_path_cfg,
1859 0x02, 0x00);
1860 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301861 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
1862 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001863 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301864 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
1865 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001866 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301867 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
1868 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001869 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301870 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
1871 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001872 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301873 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
1874 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001875 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301876 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
1877 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001878 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301879 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
1880 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001881 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301882 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
1883 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001884 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301885 BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
1886 0xFF, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001887 wsa_macro_enable_softclip_clk(component, wsa_priv,
1888 softclip_path, false);
1889 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301890 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x00);
Meng Wang15c825d2018-09-06 10:49:18 +08001891 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05301892 BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x00);
1893 break;
1894 default:
1895 dev_err(wsa_dev, "%s: Invalid event %d\n", __func__, event);
1896 break;
1897 }
1898 return 0;
1899}
1900
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301901static int wsa_macro_enable_echo(struct snd_soc_dapm_widget *w,
1902 struct snd_kcontrol *kcontrol,
1903 int event)
1904{
Meng Wang15c825d2018-09-06 10:49:18 +08001905 struct snd_soc_component *component =
1906 snd_soc_dapm_to_component(w->dapm);
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301907 struct device *wsa_dev = NULL;
1908 struct wsa_macro_priv *wsa_priv = NULL;
1909 u16 val, ec_tx = 0, ec_hq_reg;
1910
Meng Wang15c825d2018-09-06 10:49:18 +08001911 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301912 return -EINVAL;
1913
1914 dev_dbg(wsa_dev, "%s %d %s\n", __func__, event, w->name);
1915
Meng Wang15c825d2018-09-06 10:49:18 +08001916 val = snd_soc_component_read32(component,
1917 BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0);
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301918 if (!(strcmp(w->name, "WSA RX_MIX EC0_MUX")))
1919 ec_tx = (val & 0x07) - 1;
1920 else
1921 ec_tx = ((val & 0x38) >> 0x3) - 1;
1922
1923 if (ec_tx < 0 || ec_tx >= (WSA_MACRO_RX1 + 1)) {
1924 dev_err(wsa_dev, "%s: EC mix control not set correctly\n",
1925 __func__);
1926 return -EINVAL;
1927 }
1928 if (wsa_priv->ec_hq[ec_tx]) {
Meng Wang15c825d2018-09-06 10:49:18 +08001929 snd_soc_component_update_bits(component,
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301930 BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
1931 0x1 << ec_tx, 0x1 << ec_tx);
1932 ec_hq_reg = BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL +
Laxminath Kasam5d9ea8d2018-11-28 14:32:40 +05301933 0x40 * ec_tx;
Meng Wang15c825d2018-09-06 10:49:18 +08001934 snd_soc_component_update_bits(component, ec_hq_reg, 0x01, 0x01);
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301935 ec_hq_reg = BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0 +
Laxminath Kasam5d9ea8d2018-11-28 14:32:40 +05301936 0x40 * ec_tx;
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301937 /* default set to 48k */
Meng Wang15c825d2018-09-06 10:49:18 +08001938 snd_soc_component_update_bits(component, ec_hq_reg, 0x1E, 0x08);
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301939 }
1940
1941 return 0;
1942}
1943
1944static int wsa_macro_get_ec_hq(struct snd_kcontrol *kcontrol,
1945 struct snd_ctl_elem_value *ucontrol)
1946{
1947
Meng Wang15c825d2018-09-06 10:49:18 +08001948 struct snd_soc_component *component =
1949 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301950 int ec_tx = ((struct soc_multi_mixer_control *)
1951 kcontrol->private_value)->shift;
1952 struct device *wsa_dev = NULL;
1953 struct wsa_macro_priv *wsa_priv = NULL;
1954
Meng Wang15c825d2018-09-06 10:49:18 +08001955 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301956 return -EINVAL;
1957
1958 ucontrol->value.integer.value[0] = wsa_priv->ec_hq[ec_tx];
1959 return 0;
1960}
1961
1962static int wsa_macro_set_ec_hq(struct snd_kcontrol *kcontrol,
1963 struct snd_ctl_elem_value *ucontrol)
1964{
Meng Wang15c825d2018-09-06 10:49:18 +08001965 struct snd_soc_component *component =
1966 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301967 int ec_tx = ((struct soc_multi_mixer_control *)
1968 kcontrol->private_value)->shift;
1969 int value = ucontrol->value.integer.value[0];
1970 struct device *wsa_dev = NULL;
1971 struct wsa_macro_priv *wsa_priv = NULL;
1972
Meng Wang15c825d2018-09-06 10:49:18 +08001973 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05301974 return -EINVAL;
1975
1976 dev_dbg(wsa_dev, "%s: enable current %d, new %d\n",
1977 __func__, wsa_priv->ec_hq[ec_tx], value);
1978 wsa_priv->ec_hq[ec_tx] = value;
1979
1980 return 0;
1981}
1982
Vatsal Buchaf2a71b62019-03-26 16:14:40 +05301983static int wsa_macro_get_rx_mute_status(struct snd_kcontrol *kcontrol,
1984 struct snd_ctl_elem_value *ucontrol)
1985{
1986
1987 struct snd_soc_component *component =
1988 snd_soc_kcontrol_component(kcontrol);
1989 struct device *wsa_dev = NULL;
1990 struct wsa_macro_priv *wsa_priv = NULL;
1991 int wsa_rx_shift = ((struct soc_multi_mixer_control *)
1992 kcontrol->private_value)->shift;
1993
1994 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
1995 return -EINVAL;
1996
1997 ucontrol->value.integer.value[0] =
1998 wsa_priv->wsa_digital_mute_status[wsa_rx_shift];
1999 return 0;
2000}
2001
2002static int wsa_macro_set_rx_mute_status(struct snd_kcontrol *kcontrol,
2003 struct snd_ctl_elem_value *ucontrol)
2004{
2005 struct snd_soc_component *component =
2006 snd_soc_kcontrol_component(kcontrol);
2007 struct device *wsa_dev = NULL;
2008 struct wsa_macro_priv *wsa_priv = NULL;
2009 int value = ucontrol->value.integer.value[0];
2010 int wsa_rx_shift = ((struct soc_multi_mixer_control *)
2011 kcontrol->private_value)->shift;
2012
2013 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
2014 return -EINVAL;
2015
2016 switch (wsa_rx_shift) {
2017 case 0:
2018 snd_soc_component_update_bits(component,
2019 BOLERO_CDC_WSA_RX0_RX_PATH_CTL,
2020 0x10, value << 4);
2021 break;
2022 case 1:
2023 snd_soc_component_update_bits(component,
2024 BOLERO_CDC_WSA_RX1_RX_PATH_CTL,
2025 0x10, value << 4);
2026 break;
2027 case 2:
2028 snd_soc_component_update_bits(component,
2029 BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL,
2030 0x10, value << 4);
2031 break;
2032 case 3:
2033 snd_soc_component_update_bits(component,
2034 BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL,
2035 0x10, value << 4);
2036 break;
2037 default:
2038 pr_err("%s: invalid argument rx_shift = %d\n", __func__,
2039 wsa_rx_shift);
2040 return -EINVAL;
2041 }
2042
2043 dev_dbg(component->dev, "%s: WSA Digital Mute RX %d Enable %d\n",
2044 __func__, wsa_rx_shift, value);
2045 wsa_priv->wsa_digital_mute_status[wsa_rx_shift] = value;
2046 return 0;
2047}
2048
Laxminath Kasam243e2752018-04-12 00:40:19 +05302049static int wsa_macro_get_compander(struct snd_kcontrol *kcontrol,
2050 struct snd_ctl_elem_value *ucontrol)
2051{
2052
Meng Wang15c825d2018-09-06 10:49:18 +08002053 struct snd_soc_component *component =
2054 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302055 int comp = ((struct soc_multi_mixer_control *)
2056 kcontrol->private_value)->shift;
2057 struct device *wsa_dev = NULL;
2058 struct wsa_macro_priv *wsa_priv = NULL;
2059
Meng Wang15c825d2018-09-06 10:49:18 +08002060 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05302061 return -EINVAL;
2062
2063 ucontrol->value.integer.value[0] = wsa_priv->comp_enabled[comp];
2064 return 0;
2065}
2066
2067static int wsa_macro_set_compander(struct snd_kcontrol *kcontrol,
2068 struct snd_ctl_elem_value *ucontrol)
2069{
Meng Wang15c825d2018-09-06 10:49:18 +08002070 struct snd_soc_component *component =
2071 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302072 int comp = ((struct soc_multi_mixer_control *)
2073 kcontrol->private_value)->shift;
2074 int value = ucontrol->value.integer.value[0];
2075 struct device *wsa_dev = NULL;
2076 struct wsa_macro_priv *wsa_priv = NULL;
2077
Meng Wang15c825d2018-09-06 10:49:18 +08002078 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05302079 return -EINVAL;
2080
Meng Wang15c825d2018-09-06 10:49:18 +08002081 dev_dbg(component->dev, "%s: Compander %d enable current %d, new %d\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05302082 __func__, comp + 1, wsa_priv->comp_enabled[comp], value);
2083 wsa_priv->comp_enabled[comp] = value;
2084
2085 return 0;
2086}
2087
2088static int wsa_macro_ear_spkr_pa_gain_get(struct snd_kcontrol *kcontrol,
2089 struct snd_ctl_elem_value *ucontrol)
2090{
Meng Wang15c825d2018-09-06 10:49:18 +08002091 struct snd_soc_component *component =
2092 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302093 struct device *wsa_dev = NULL;
2094 struct wsa_macro_priv *wsa_priv = NULL;
2095
Meng Wang15c825d2018-09-06 10:49:18 +08002096 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05302097 return -EINVAL;
2098
2099 ucontrol->value.integer.value[0] = wsa_priv->ear_spkr_gain;
2100
Meng Wang15c825d2018-09-06 10:49:18 +08002101 dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05302102 __func__, ucontrol->value.integer.value[0]);
2103
2104 return 0;
2105}
2106
2107static int wsa_macro_ear_spkr_pa_gain_put(struct snd_kcontrol *kcontrol,
2108 struct snd_ctl_elem_value *ucontrol)
2109{
Meng Wang15c825d2018-09-06 10:49:18 +08002110 struct snd_soc_component *component =
2111 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302112 struct device *wsa_dev = NULL;
2113 struct wsa_macro_priv *wsa_priv = NULL;
2114
Meng Wang15c825d2018-09-06 10:49:18 +08002115 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05302116 return -EINVAL;
2117
2118 wsa_priv->ear_spkr_gain = ucontrol->value.integer.value[0];
2119
Meng Wang15c825d2018-09-06 10:49:18 +08002120 dev_dbg(component->dev, "%s: gain = %d\n", __func__,
Laxminath Kasam243e2752018-04-12 00:40:19 +05302121 wsa_priv->ear_spkr_gain);
2122
2123 return 0;
2124}
2125
2126static int wsa_macro_spkr_left_boost_stage_get(struct snd_kcontrol *kcontrol,
2127 struct snd_ctl_elem_value *ucontrol)
2128{
2129 u8 bst_state_max = 0;
Meng Wang15c825d2018-09-06 10:49:18 +08002130 struct snd_soc_component *component =
2131 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302132
Meng Wang15c825d2018-09-06 10:49:18 +08002133 bst_state_max = snd_soc_component_read32(component,
2134 BOLERO_CDC_WSA_BOOST0_BOOST_CTL);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302135 bst_state_max = (bst_state_max & 0x0c) >> 2;
2136 ucontrol->value.integer.value[0] = bst_state_max;
Meng Wang15c825d2018-09-06 10:49:18 +08002137 dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05302138 __func__, ucontrol->value.integer.value[0]);
2139
2140 return 0;
2141}
2142
2143static int wsa_macro_spkr_left_boost_stage_put(struct snd_kcontrol *kcontrol,
2144 struct snd_ctl_elem_value *ucontrol)
2145{
2146 u8 bst_state_max;
Meng Wang15c825d2018-09-06 10:49:18 +08002147 struct snd_soc_component *component =
2148 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302149
Meng Wang15c825d2018-09-06 10:49:18 +08002150 dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05302151 __func__, ucontrol->value.integer.value[0]);
2152 bst_state_max = ucontrol->value.integer.value[0] << 2;
Karthikeyan Mani10de3932019-04-15 11:46:57 -07002153 /* bolero does not need to limit the boost levels */
Laxminath Kasam243e2752018-04-12 00:40:19 +05302154
2155 return 0;
2156}
2157
2158static int wsa_macro_spkr_right_boost_stage_get(struct snd_kcontrol *kcontrol,
2159 struct snd_ctl_elem_value *ucontrol)
2160{
2161 u8 bst_state_max = 0;
Meng Wang15c825d2018-09-06 10:49:18 +08002162 struct snd_soc_component *component =
2163 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302164
Meng Wang15c825d2018-09-06 10:49:18 +08002165 bst_state_max = snd_soc_component_read32(component,
2166 BOLERO_CDC_WSA_BOOST1_BOOST_CTL);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302167 bst_state_max = (bst_state_max & 0x0c) >> 2;
2168 ucontrol->value.integer.value[0] = bst_state_max;
Meng Wang15c825d2018-09-06 10:49:18 +08002169 dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05302170 __func__, ucontrol->value.integer.value[0]);
2171
2172 return 0;
2173}
2174
2175static int wsa_macro_spkr_right_boost_stage_put(struct snd_kcontrol *kcontrol,
2176 struct snd_ctl_elem_value *ucontrol)
2177{
2178 u8 bst_state_max;
Meng Wang15c825d2018-09-06 10:49:18 +08002179 struct snd_soc_component *component =
2180 snd_soc_kcontrol_component(kcontrol);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302181
Meng Wang15c825d2018-09-06 10:49:18 +08002182 dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
Laxminath Kasam243e2752018-04-12 00:40:19 +05302183 __func__, ucontrol->value.integer.value[0]);
2184 bst_state_max = ucontrol->value.integer.value[0] << 2;
Karthikeyan Mani10de3932019-04-15 11:46:57 -07002185 /* bolero does not need to limit the boost levels */
Laxminath Kasam243e2752018-04-12 00:40:19 +05302186
2187 return 0;
2188}
2189
2190static int wsa_macro_rx_mux_get(struct snd_kcontrol *kcontrol,
2191 struct snd_ctl_elem_value *ucontrol)
2192{
2193 struct snd_soc_dapm_widget *widget =
2194 snd_soc_dapm_kcontrol_widget(kcontrol);
Meng Wang15c825d2018-09-06 10:49:18 +08002195 struct snd_soc_component *component =
2196 snd_soc_dapm_to_component(widget->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302197 struct device *wsa_dev = NULL;
2198 struct wsa_macro_priv *wsa_priv = NULL;
2199
Meng Wang15c825d2018-09-06 10:49:18 +08002200 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05302201 return -EINVAL;
2202
2203 ucontrol->value.integer.value[0] =
2204 wsa_priv->rx_port_value[widget->shift];
2205 return 0;
2206}
2207
2208static int wsa_macro_rx_mux_put(struct snd_kcontrol *kcontrol,
2209 struct snd_ctl_elem_value *ucontrol)
2210{
2211 struct snd_soc_dapm_widget *widget =
2212 snd_soc_dapm_kcontrol_widget(kcontrol);
Meng Wang15c825d2018-09-06 10:49:18 +08002213 struct snd_soc_component *component =
2214 snd_soc_dapm_to_component(widget->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302215 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2216 struct snd_soc_dapm_update *update = NULL;
2217 u32 rx_port_value = ucontrol->value.integer.value[0];
2218 u32 bit_input = 0;
2219 u32 aif_rst;
2220 struct device *wsa_dev = NULL;
2221 struct wsa_macro_priv *wsa_priv = NULL;
2222
Meng Wang15c825d2018-09-06 10:49:18 +08002223 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05302224 return -EINVAL;
2225
2226 aif_rst = wsa_priv->rx_port_value[widget->shift];
2227 if (!rx_port_value) {
2228 if (aif_rst == 0) {
2229 dev_err(wsa_dev, "%s: AIF reset already\n", __func__);
2230 return 0;
2231 }
Sudheer Papothic0f75b72019-07-16 06:04:10 +05302232 if (aif_rst >= WSA_MACRO_RX_MAX) {
2233 dev_err(wsa_dev, "%s: Invalid AIF reset\n", __func__);
2234 return 0;
2235 }
Laxminath Kasam243e2752018-04-12 00:40:19 +05302236 }
2237 wsa_priv->rx_port_value[widget->shift] = rx_port_value;
2238
2239 bit_input = widget->shift;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302240
Sudheer Papothic0f75b72019-07-16 06:04:10 +05302241 dev_dbg(wsa_dev,
2242 "%s: mux input: %d, mux output: %d, bit: %d\n",
2243 __func__, rx_port_value, widget->shift, bit_input);
2244
Laxminath Kasam243e2752018-04-12 00:40:19 +05302245 switch (rx_port_value) {
2246 case 0:
Sudheer Papothic0f75b72019-07-16 06:04:10 +05302247 if (wsa_priv->active_ch_cnt[aif_rst]) {
2248 clear_bit(bit_input,
2249 &wsa_priv->active_ch_mask[aif_rst]);
2250 wsa_priv->active_ch_cnt[aif_rst]--;
2251 }
Laxminath Kasam243e2752018-04-12 00:40:19 +05302252 break;
2253 case 1:
2254 case 2:
2255 set_bit(bit_input,
Laxminath Kasam59c7a1d2018-08-09 16:11:17 +05302256 &wsa_priv->active_ch_mask[rx_port_value]);
2257 wsa_priv->active_ch_cnt[rx_port_value]++;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302258 break;
2259 default:
2260 dev_err(wsa_dev,
Sudheer Papothic0f75b72019-07-16 06:04:10 +05302261 "%s: Invalid AIF_ID for WSA RX MUX %d\n",
2262 __func__, rx_port_value);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302263 return -EINVAL;
2264 }
2265
2266 snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
2267 rx_port_value, e, update);
2268 return 0;
2269}
2270
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302271static int wsa_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol,
2272 struct snd_ctl_elem_value *ucontrol)
2273{
Meng Wang15c825d2018-09-06 10:49:18 +08002274 struct snd_soc_component *component =
2275 snd_soc_kcontrol_component(kcontrol);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302276
2277 ucontrol->value.integer.value[0] =
Meng Wang15c825d2018-09-06 10:49:18 +08002278 ((snd_soc_component_read32(
2279 component, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG) & 0x04) ?
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302280 1 : 0);
2281
Meng Wang15c825d2018-09-06 10:49:18 +08002282 dev_dbg(component->dev, "%s: value: %lu\n", __func__,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302283 ucontrol->value.integer.value[0]);
2284
2285 return 0;
2286}
2287
2288static int wsa_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol,
2289 struct snd_ctl_elem_value *ucontrol)
2290{
Meng Wang15c825d2018-09-06 10:49:18 +08002291 struct snd_soc_component *component =
2292 snd_soc_kcontrol_component(kcontrol);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302293
Meng Wang15c825d2018-09-06 10:49:18 +08002294 dev_dbg(component->dev, "%s: value: %lu\n", __func__,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302295 ucontrol->value.integer.value[0]);
2296
2297 /* Set Vbat register configuration for GSM mode bit based on value */
2298 if (ucontrol->value.integer.value[0])
Meng Wang15c825d2018-09-06 10:49:18 +08002299 snd_soc_component_update_bits(component,
2300 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
2301 0x04, 0x04);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302302 else
Meng Wang15c825d2018-09-06 10:49:18 +08002303 snd_soc_component_update_bits(component,
2304 BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
2305 0x04, 0x00);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302306
2307 return 0;
2308}
2309
2310static int wsa_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol,
2311 struct snd_ctl_elem_value *ucontrol)
2312{
Meng Wang15c825d2018-09-06 10:49:18 +08002313 struct snd_soc_component *component =
2314 snd_soc_kcontrol_component(kcontrol);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302315 struct device *wsa_dev = NULL;
2316 struct wsa_macro_priv *wsa_priv = NULL;
2317 int path = ((struct soc_multi_mixer_control *)
2318 kcontrol->private_value)->shift;
2319
Meng Wang15c825d2018-09-06 10:49:18 +08002320 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302321 return -EINVAL;
2322
2323 ucontrol->value.integer.value[0] = wsa_priv->is_softclip_on[path];
2324
Meng Wang15c825d2018-09-06 10:49:18 +08002325 dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302326 __func__, ucontrol->value.integer.value[0]);
2327
2328 return 0;
2329}
2330
2331static int wsa_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol,
2332 struct snd_ctl_elem_value *ucontrol)
2333{
Meng Wang15c825d2018-09-06 10:49:18 +08002334 struct snd_soc_component *component =
2335 snd_soc_kcontrol_component(kcontrol);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302336 struct device *wsa_dev = NULL;
2337 struct wsa_macro_priv *wsa_priv = NULL;
2338 int path = ((struct soc_multi_mixer_control *)
2339 kcontrol->private_value)->shift;
2340
Meng Wang15c825d2018-09-06 10:49:18 +08002341 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302342 return -EINVAL;
2343
2344 wsa_priv->is_softclip_on[path] = ucontrol->value.integer.value[0];
2345
Meng Wang15c825d2018-09-06 10:49:18 +08002346 dev_dbg(component->dev, "%s: soft clip enable for %d: %d\n", __func__,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302347 path, wsa_priv->is_softclip_on[path]);
2348
2349 return 0;
2350}
2351
Laxminath Kasam243e2752018-04-12 00:40:19 +05302352static const struct snd_kcontrol_new wsa_macro_snd_controls[] = {
2353 SOC_ENUM_EXT("EAR SPKR PA Gain", wsa_macro_ear_spkr_pa_gain_enum,
2354 wsa_macro_ear_spkr_pa_gain_get,
2355 wsa_macro_ear_spkr_pa_gain_put),
2356 SOC_ENUM_EXT("SPKR Left Boost Max State",
2357 wsa_macro_spkr_boost_stage_enum,
2358 wsa_macro_spkr_left_boost_stage_get,
2359 wsa_macro_spkr_left_boost_stage_put),
2360 SOC_ENUM_EXT("SPKR Right Boost Max State",
2361 wsa_macro_spkr_boost_stage_enum,
2362 wsa_macro_spkr_right_boost_stage_get,
2363 wsa_macro_spkr_right_boost_stage_put),
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302364 SOC_ENUM_EXT("GSM mode Enable", wsa_macro_vbat_bcl_gsm_mode_enum,
2365 wsa_macro_vbat_bcl_gsm_mode_func_get,
2366 wsa_macro_vbat_bcl_gsm_mode_func_put),
2367 SOC_SINGLE_EXT("WSA_Softclip0 Enable", SND_SOC_NOPM,
2368 WSA_MACRO_SOFTCLIP0, 1, 0,
2369 wsa_macro_soft_clip_enable_get,
2370 wsa_macro_soft_clip_enable_put),
2371 SOC_SINGLE_EXT("WSA_Softclip1 Enable", SND_SOC_NOPM,
2372 WSA_MACRO_SOFTCLIP1, 1, 0,
2373 wsa_macro_soft_clip_enable_get,
2374 wsa_macro_soft_clip_enable_put),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302375 SOC_SINGLE_SX_TLV("WSA_RX0 Digital Volume",
2376 BOLERO_CDC_WSA_RX0_RX_VOL_CTL,
2377 0, -84, 40, digital_gain),
2378 SOC_SINGLE_SX_TLV("WSA_RX1 Digital Volume",
2379 BOLERO_CDC_WSA_RX1_RX_VOL_CTL,
2380 0, -84, 40, digital_gain),
Vatsal Buchaf2a71b62019-03-26 16:14:40 +05302381 SOC_SINGLE_EXT("WSA_RX0 Digital Mute", SND_SOC_NOPM, WSA_MACRO_RX0, 1,
2382 0, wsa_macro_get_rx_mute_status,
2383 wsa_macro_set_rx_mute_status),
2384 SOC_SINGLE_EXT("WSA_RX1 Digital Mute", SND_SOC_NOPM, WSA_MACRO_RX1, 1,
2385 0, wsa_macro_get_rx_mute_status,
2386 wsa_macro_set_rx_mute_status),
2387 SOC_SINGLE_EXT("WSA_RX0_MIX Digital Mute", SND_SOC_NOPM,
2388 WSA_MACRO_RX_MIX0, 1, 0, wsa_macro_get_rx_mute_status,
2389 wsa_macro_set_rx_mute_status),
2390 SOC_SINGLE_EXT("WSA_RX1_MIX Digital Mute", SND_SOC_NOPM,
2391 WSA_MACRO_RX_MIX1, 1, 0, wsa_macro_get_rx_mute_status,
2392 wsa_macro_set_rx_mute_status),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302393 SOC_SINGLE_EXT("WSA_COMP1 Switch", SND_SOC_NOPM, WSA_MACRO_COMP1, 1, 0,
2394 wsa_macro_get_compander, wsa_macro_set_compander),
2395 SOC_SINGLE_EXT("WSA_COMP2 Switch", SND_SOC_NOPM, WSA_MACRO_COMP2, 1, 0,
2396 wsa_macro_get_compander, wsa_macro_set_compander),
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05302397 SOC_SINGLE_EXT("WSA_RX0 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX0,
2398 1, 0, wsa_macro_get_ec_hq, wsa_macro_set_ec_hq),
2399 SOC_SINGLE_EXT("WSA_RX1 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX1,
2400 1, 0, wsa_macro_get_ec_hq, wsa_macro_set_ec_hq),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302401};
2402
2403static const struct soc_enum rx_mux_enum =
2404 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_mux_text), rx_mux_text);
2405
2406static const struct snd_kcontrol_new rx_mux[WSA_MACRO_RX_MAX] = {
2407 SOC_DAPM_ENUM_EXT("WSA RX0 Mux", rx_mux_enum,
2408 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2409 SOC_DAPM_ENUM_EXT("WSA RX1 Mux", rx_mux_enum,
2410 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2411 SOC_DAPM_ENUM_EXT("WSA RX_MIX0 Mux", rx_mux_enum,
2412 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2413 SOC_DAPM_ENUM_EXT("WSA RX_MIX1 Mux", rx_mux_enum,
2414 wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
2415};
2416
2417static int wsa_macro_vi_feed_mixer_get(struct snd_kcontrol *kcontrol,
2418 struct snd_ctl_elem_value *ucontrol)
2419{
2420 struct snd_soc_dapm_widget *widget =
2421 snd_soc_dapm_kcontrol_widget(kcontrol);
Meng Wang15c825d2018-09-06 10:49:18 +08002422 struct snd_soc_component *component =
2423 snd_soc_dapm_to_component(widget->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302424 struct soc_multi_mixer_control *mixer =
2425 ((struct soc_multi_mixer_control *)kcontrol->private_value);
2426 u32 dai_id = widget->shift;
2427 u32 spk_tx_id = mixer->shift;
2428 struct device *wsa_dev = NULL;
2429 struct wsa_macro_priv *wsa_priv = NULL;
2430
Meng Wang15c825d2018-09-06 10:49:18 +08002431 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05302432 return -EINVAL;
2433
2434 if (test_bit(spk_tx_id, &wsa_priv->active_ch_mask[dai_id]))
2435 ucontrol->value.integer.value[0] = 1;
2436 else
2437 ucontrol->value.integer.value[0] = 0;
2438
2439 return 0;
2440}
2441
2442static int wsa_macro_vi_feed_mixer_put(struct snd_kcontrol *kcontrol,
2443 struct snd_ctl_elem_value *ucontrol)
2444{
2445 struct snd_soc_dapm_widget *widget =
2446 snd_soc_dapm_kcontrol_widget(kcontrol);
Meng Wang15c825d2018-09-06 10:49:18 +08002447 struct snd_soc_component *component =
2448 snd_soc_dapm_to_component(widget->dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302449 struct soc_multi_mixer_control *mixer =
2450 ((struct soc_multi_mixer_control *)kcontrol->private_value);
2451 u32 spk_tx_id = mixer->shift;
2452 u32 enable = ucontrol->value.integer.value[0];
2453 struct device *wsa_dev = NULL;
2454 struct wsa_macro_priv *wsa_priv = NULL;
2455
Meng Wang15c825d2018-09-06 10:49:18 +08002456 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05302457 return -EINVAL;
2458
2459 wsa_priv->vi_feed_value = ucontrol->value.integer.value[0];
2460
2461 if (enable) {
2462 if (spk_tx_id == WSA_MACRO_TX0 &&
2463 !test_bit(WSA_MACRO_TX0,
2464 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2465 set_bit(WSA_MACRO_TX0,
2466 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2467 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]++;
2468 }
2469 if (spk_tx_id == WSA_MACRO_TX1 &&
2470 !test_bit(WSA_MACRO_TX1,
2471 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2472 set_bit(WSA_MACRO_TX1,
2473 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2474 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]++;
2475 }
2476 } else {
2477 if (spk_tx_id == WSA_MACRO_TX0 &&
2478 test_bit(WSA_MACRO_TX0,
2479 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2480 clear_bit(WSA_MACRO_TX0,
2481 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2482 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]--;
2483 }
2484 if (spk_tx_id == WSA_MACRO_TX1 &&
2485 test_bit(WSA_MACRO_TX1,
2486 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
2487 clear_bit(WSA_MACRO_TX1,
2488 &wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
2489 wsa_priv->active_ch_cnt[WSA_MACRO_AIF_VI]--;
2490 }
2491 }
2492 snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
2493
2494 return 0;
2495}
2496
2497static const struct snd_kcontrol_new aif_vi_mixer[] = {
2498 SOC_SINGLE_EXT("WSA_SPKR_VI_1", SND_SOC_NOPM, WSA_MACRO_TX0, 1, 0,
2499 wsa_macro_vi_feed_mixer_get,
2500 wsa_macro_vi_feed_mixer_put),
2501 SOC_SINGLE_EXT("WSA_SPKR_VI_2", SND_SOC_NOPM, WSA_MACRO_TX1, 1, 0,
2502 wsa_macro_vi_feed_mixer_get,
2503 wsa_macro_vi_feed_mixer_put),
2504};
2505
2506static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = {
2507 SND_SOC_DAPM_AIF_IN("WSA AIF1 PB", "WSA_AIF1 Playback", 0,
2508 SND_SOC_NOPM, 0, 0),
2509
2510 SND_SOC_DAPM_AIF_IN("WSA AIF_MIX1 PB", "WSA_AIF_MIX1 Playback", 0,
2511 SND_SOC_NOPM, 0, 0),
2512
2513 SND_SOC_DAPM_AIF_OUT_E("WSA AIF_VI", "WSA_AIF_VI Capture", 0,
2514 SND_SOC_NOPM, WSA_MACRO_AIF_VI, 0,
2515 wsa_macro_enable_vi_feedback,
2516 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2517
2518 SND_SOC_DAPM_AIF_OUT("WSA AIF_ECHO", "WSA_AIF_ECHO Capture", 0,
2519 SND_SOC_NOPM, 0, 0),
2520
2521 SND_SOC_DAPM_MIXER("WSA_AIF_VI Mixer", SND_SOC_NOPM, WSA_MACRO_AIF_VI,
2522 0, aif_vi_mixer, ARRAY_SIZE(aif_vi_mixer)),
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05302523 SND_SOC_DAPM_MUX_E("WSA RX_MIX EC0_MUX", SND_SOC_NOPM,
2524 WSA_MACRO_EC0_MUX, 0,
2525 &rx_mix_ec0_mux, wsa_macro_enable_echo,
2526 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2527 SND_SOC_DAPM_MUX_E("WSA RX_MIX EC1_MUX", SND_SOC_NOPM,
2528 WSA_MACRO_EC1_MUX, 0,
2529 &rx_mix_ec1_mux, wsa_macro_enable_echo,
2530 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302531
2532 SND_SOC_DAPM_MUX("WSA RX0 MUX", SND_SOC_NOPM, WSA_MACRO_RX0, 0,
2533 &rx_mux[WSA_MACRO_RX0]),
2534 SND_SOC_DAPM_MUX("WSA RX1 MUX", SND_SOC_NOPM, WSA_MACRO_RX1, 0,
2535 &rx_mux[WSA_MACRO_RX1]),
2536 SND_SOC_DAPM_MUX("WSA RX_MIX0 MUX", SND_SOC_NOPM, WSA_MACRO_RX_MIX0, 0,
2537 &rx_mux[WSA_MACRO_RX_MIX0]),
2538 SND_SOC_DAPM_MUX("WSA RX_MIX1 MUX", SND_SOC_NOPM, WSA_MACRO_RX_MIX1, 0,
2539 &rx_mux[WSA_MACRO_RX_MIX1]),
2540
2541 SND_SOC_DAPM_MIXER("WSA RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
2542 SND_SOC_DAPM_MIXER("WSA RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
2543 SND_SOC_DAPM_MIXER("WSA RX_MIX0", SND_SOC_NOPM, 0, 0, NULL, 0),
2544 SND_SOC_DAPM_MIXER("WSA RX_MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
2545
2546 SND_SOC_DAPM_MUX_E("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0,
2547 &rx0_prim_inp0_mux, wsa_macro_enable_swr,
2548 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2549 SND_SOC_DAPM_MUX_E("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0,
2550 &rx0_prim_inp1_mux, wsa_macro_enable_swr,
2551 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2552 SND_SOC_DAPM_MUX_E("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0,
2553 &rx0_prim_inp2_mux, wsa_macro_enable_swr,
2554 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Laxminath Kasam52ae6582019-08-08 18:00:35 +05302555 SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL,
2556 0, 0, &rx0_mix_mux, wsa_macro_enable_mix_path,
Laxminath Kasam243e2752018-04-12 00:40:19 +05302557 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2558 SND_SOC_DAPM_MUX_E("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0,
2559 &rx1_prim_inp0_mux, wsa_macro_enable_swr,
2560 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2561 SND_SOC_DAPM_MUX_E("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0,
2562 &rx1_prim_inp1_mux, wsa_macro_enable_swr,
2563 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2564 SND_SOC_DAPM_MUX_E("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0,
2565 &rx1_prim_inp2_mux, wsa_macro_enable_swr,
2566 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Laxminath Kasam52ae6582019-08-08 18:00:35 +05302567 SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL,
2568 0, 0, &rx1_mix_mux, wsa_macro_enable_mix_path,
Laxminath Kasam243e2752018-04-12 00:40:19 +05302569 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Laxminath Kasam52ae6582019-08-08 18:00:35 +05302570 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 MIX", SND_SOC_NOPM,
2571 0, 0, NULL, 0, wsa_macro_enable_main_path,
2572 SND_SOC_DAPM_PRE_PMU),
2573 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 MIX", SND_SOC_NOPM,
2574 1, 0, NULL, 0, wsa_macro_enable_main_path,
2575 SND_SOC_DAPM_PRE_PMU),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302576 SND_SOC_DAPM_MIXER("WSA_RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2577 SND_SOC_DAPM_MIXER("WSA_RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
2578
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302579 SND_SOC_DAPM_MUX_E("WSA_RX0 INT0 SIDETONE MIX",
2580 BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 4, 0,
2581 &rx0_sidetone_mix_mux, wsa_macro_enable_swr,
2582 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2583 SND_SOC_DAPM_INPUT("WSA SRC0_INP"),
2584
2585 SND_SOC_DAPM_INPUT("WSA_TX DEC0_INP"),
2586 SND_SOC_DAPM_INPUT("WSA_TX DEC1_INP"),
2587
Laxminath Kasam243e2752018-04-12 00:40:19 +05302588 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 INTERP", SND_SOC_NOPM,
2589 WSA_MACRO_COMP1, 0, NULL, 0, wsa_macro_enable_interpolator,
2590 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2591 SND_SOC_DAPM_POST_PMD),
2592 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 INTERP", SND_SOC_NOPM,
2593 WSA_MACRO_COMP2, 0, NULL, 0, wsa_macro_enable_interpolator,
2594 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2595 SND_SOC_DAPM_POST_PMD),
2596
2597 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 CHAIN", SND_SOC_NOPM, 0, 0,
2598 NULL, 0, wsa_macro_spk_boost_event,
Laxminath Kasam0c857002018-07-17 23:47:17 +05302599 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2600 SND_SOC_DAPM_POST_PMD),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302601 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 CHAIN", SND_SOC_NOPM, 0, 0,
2602 NULL, 0, wsa_macro_spk_boost_event,
Laxminath Kasam0c857002018-07-17 23:47:17 +05302603 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2604 SND_SOC_DAPM_POST_PMD),
Laxminath Kasam243e2752018-04-12 00:40:19 +05302605
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302606 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 VBAT", SND_SOC_NOPM,
2607 0, 0, wsa_int0_vbat_mix_switch,
2608 ARRAY_SIZE(wsa_int0_vbat_mix_switch),
2609 wsa_macro_enable_vbat,
2610 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2611 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 VBAT", SND_SOC_NOPM,
2612 0, 0, wsa_int1_vbat_mix_switch,
2613 ARRAY_SIZE(wsa_int1_vbat_mix_switch),
2614 wsa_macro_enable_vbat,
2615 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2616
Laxminath Kasam243e2752018-04-12 00:40:19 +05302617 SND_SOC_DAPM_INPUT("VIINPUT_WSA"),
2618
2619 SND_SOC_DAPM_OUTPUT("WSA_SPK1 OUT"),
2620 SND_SOC_DAPM_OUTPUT("WSA_SPK2 OUT"),
2621
2622 SND_SOC_DAPM_SUPPLY_S("WSA_MCLK", 0, SND_SOC_NOPM, 0, 0,
2623 wsa_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2624};
2625
2626static const struct snd_soc_dapm_route wsa_audio_map[] = {
2627 /* VI Feedback */
2628 {"WSA_AIF_VI Mixer", "WSA_SPKR_VI_1", "VIINPUT_WSA"},
2629 {"WSA_AIF_VI Mixer", "WSA_SPKR_VI_2", "VIINPUT_WSA"},
2630 {"WSA AIF_VI", NULL, "WSA_AIF_VI Mixer"},
2631 {"WSA AIF_VI", NULL, "WSA_MCLK"},
2632
Laxminath Kasam36ab7bb2018-06-18 18:43:46 +05302633 {"WSA RX_MIX EC0_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
2634 {"WSA RX_MIX EC1_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
2635 {"WSA RX_MIX EC0_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
2636 {"WSA RX_MIX EC1_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
2637 {"WSA AIF_ECHO", NULL, "WSA RX_MIX EC0_MUX"},
2638 {"WSA AIF_ECHO", NULL, "WSA RX_MIX EC1_MUX"},
2639 {"WSA AIF_ECHO", NULL, "WSA_MCLK"},
2640
Laxminath Kasam243e2752018-04-12 00:40:19 +05302641 {"WSA AIF1 PB", NULL, "WSA_MCLK"},
2642 {"WSA AIF_MIX1 PB", NULL, "WSA_MCLK"},
2643
2644 {"WSA RX0 MUX", "AIF1_PB", "WSA AIF1 PB"},
2645 {"WSA RX1 MUX", "AIF1_PB", "WSA AIF1 PB"},
2646 {"WSA RX_MIX0 MUX", "AIF1_PB", "WSA AIF1 PB"},
2647 {"WSA RX_MIX1 MUX", "AIF1_PB", "WSA AIF1 PB"},
2648
2649 {"WSA RX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2650 {"WSA RX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2651 {"WSA RX_MIX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2652 {"WSA RX_MIX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
2653
2654 {"WSA RX0", NULL, "WSA RX0 MUX"},
2655 {"WSA RX1", NULL, "WSA RX1 MUX"},
2656 {"WSA RX_MIX0", NULL, "WSA RX_MIX0 MUX"},
2657 {"WSA RX_MIX1", NULL, "WSA RX_MIX1 MUX"},
2658
2659 {"WSA_RX0 INP0", "RX0", "WSA RX0"},
2660 {"WSA_RX0 INP0", "RX1", "WSA RX1"},
2661 {"WSA_RX0 INP0", "RX_MIX0", "WSA RX_MIX0"},
2662 {"WSA_RX0 INP0", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302663 {"WSA_RX0 INP0", "DEC0", "WSA_TX DEC0_INP"},
2664 {"WSA_RX0 INP0", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302665 {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP0"},
2666
2667 {"WSA_RX0 INP1", "RX0", "WSA RX0"},
2668 {"WSA_RX0 INP1", "RX1", "WSA RX1"},
2669 {"WSA_RX0 INP1", "RX_MIX0", "WSA RX_MIX0"},
2670 {"WSA_RX0 INP1", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302671 {"WSA_RX0 INP1", "DEC0", "WSA_TX DEC0_INP"},
2672 {"WSA_RX0 INP1", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302673 {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP1"},
2674
2675 {"WSA_RX0 INP2", "RX0", "WSA RX0"},
2676 {"WSA_RX0 INP2", "RX1", "WSA RX1"},
2677 {"WSA_RX0 INP2", "RX_MIX0", "WSA RX_MIX0"},
2678 {"WSA_RX0 INP2", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302679 {"WSA_RX0 INP2", "DEC0", "WSA_TX DEC0_INP"},
2680 {"WSA_RX0 INP2", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302681 {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP2"},
2682
2683 {"WSA_RX0 MIX INP", "RX0", "WSA RX0"},
2684 {"WSA_RX0 MIX INP", "RX1", "WSA RX1"},
2685 {"WSA_RX0 MIX INP", "RX_MIX0", "WSA RX_MIX0"},
2686 {"WSA_RX0 MIX INP", "RX_MIX1", "WSA RX_MIX1"},
2687 {"WSA_RX INT0 SEC MIX", NULL, "WSA_RX0 MIX INP"},
2688
2689 {"WSA_RX INT0 SEC MIX", NULL, "WSA_RX INT0 MIX"},
2690 {"WSA_RX INT0 INTERP", NULL, "WSA_RX INT0 SEC MIX"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302691 {"WSA_RX0 INT0 SIDETONE MIX", "SRC0", "WSA SRC0_INP"},
2692 {"WSA_RX INT0 INTERP", NULL, "WSA_RX0 INT0 SIDETONE MIX"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302693 {"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 INTERP"},
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302694
2695 {"WSA_RX INT0 VBAT", "WSA RX0 VBAT Enable", "WSA_RX INT0 INTERP"},
2696 {"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 VBAT"},
2697
Laxminath Kasam243e2752018-04-12 00:40:19 +05302698 {"WSA_SPK1 OUT", NULL, "WSA_RX INT0 CHAIN"},
Laxminath Kasamfc281ad2018-08-06 20:19:40 +05302699 {"WSA_SPK1 OUT", NULL, "WSA_MCLK"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302700
2701 {"WSA_RX1 INP0", "RX0", "WSA RX0"},
2702 {"WSA_RX1 INP0", "RX1", "WSA RX1"},
2703 {"WSA_RX1 INP0", "RX_MIX0", "WSA RX_MIX0"},
2704 {"WSA_RX1 INP0", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302705 {"WSA_RX1 INP0", "DEC0", "WSA_TX DEC0_INP"},
2706 {"WSA_RX1 INP0", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302707 {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP0"},
2708
2709 {"WSA_RX1 INP1", "RX0", "WSA RX0"},
2710 {"WSA_RX1 INP1", "RX1", "WSA RX1"},
2711 {"WSA_RX1 INP1", "RX_MIX0", "WSA RX_MIX0"},
2712 {"WSA_RX1 INP1", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302713 {"WSA_RX1 INP1", "DEC0", "WSA_TX DEC0_INP"},
2714 {"WSA_RX1 INP1", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302715 {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP1"},
2716
2717 {"WSA_RX1 INP2", "RX0", "WSA RX0"},
2718 {"WSA_RX1 INP2", "RX1", "WSA RX1"},
2719 {"WSA_RX1 INP2", "RX_MIX0", "WSA RX_MIX0"},
2720 {"WSA_RX1 INP2", "RX_MIX1", "WSA RX_MIX1"},
Laxminath Kasam6fc2e742018-08-26 23:32:57 +05302721 {"WSA_RX1 INP2", "DEC0", "WSA_TX DEC0_INP"},
2722 {"WSA_RX1 INP2", "DEC1", "WSA_TX DEC1_INP"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302723 {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP2"},
2724
2725 {"WSA_RX1 MIX INP", "RX0", "WSA RX0"},
2726 {"WSA_RX1 MIX INP", "RX1", "WSA RX1"},
2727 {"WSA_RX1 MIX INP", "RX_MIX0", "WSA RX_MIX0"},
2728 {"WSA_RX1 MIX INP", "RX_MIX1", "WSA RX_MIX1"},
2729 {"WSA_RX INT1 SEC MIX", NULL, "WSA_RX1 MIX INP"},
2730
2731 {"WSA_RX INT1 SEC MIX", NULL, "WSA_RX INT1 MIX"},
2732 {"WSA_RX INT1 INTERP", NULL, "WSA_RX INT1 SEC MIX"},
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302733
2734 {"WSA_RX INT1 VBAT", "WSA RX1 VBAT Enable", "WSA_RX INT1 INTERP"},
2735 {"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 VBAT"},
2736
Laxminath Kasam243e2752018-04-12 00:40:19 +05302737 {"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 INTERP"},
2738 {"WSA_SPK2 OUT", NULL, "WSA_RX INT1 CHAIN"},
Laxminath Kasamfc281ad2018-08-06 20:19:40 +05302739 {"WSA_SPK2 OUT", NULL, "WSA_MCLK"},
Laxminath Kasam243e2752018-04-12 00:40:19 +05302740};
2741
2742static const struct wsa_macro_reg_mask_val wsa_macro_reg_init[] = {
2743 {BOLERO_CDC_WSA_BOOST0_BOOST_CFG1, 0x3F, 0x12},
2744 {BOLERO_CDC_WSA_BOOST0_BOOST_CFG2, 0x1C, 0x08},
2745 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x1E, 0x18},
2746 {BOLERO_CDC_WSA_BOOST1_BOOST_CFG1, 0x3F, 0x12},
2747 {BOLERO_CDC_WSA_BOOST1_BOOST_CFG2, 0x1C, 0x08},
2748 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x1E, 0x18},
2749 {BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x70, 0x58},
2750 {BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x70, 0x58},
2751 {BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08},
2752 {BOLERO_CDC_WSA_RX1_RX_PATH_CFG1, 0x08, 0x08},
2753 {BOLERO_CDC_WSA_TOP_TOP_CFG1, 0x02, 0x02},
2754 {BOLERO_CDC_WSA_TOP_TOP_CFG1, 0x01, 0x01},
2755 {BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2756 {BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2757 {BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2758 {BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
2759 {BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80},
2760 {BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x80},
2761 {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01},
2762 {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01},
2763 {BOLERO_CDC_WSA_RX0_RX_PATH_CFG0, 0x01, 0x01},
2764 {BOLERO_CDC_WSA_RX1_RX_PATH_CFG0, 0x01, 0x01},
2765 {BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CFG, 0x01, 0x01},
2766 {BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CFG, 0x01, 0x01},
2767};
2768
Meng Wang15c825d2018-09-06 10:49:18 +08002769static void wsa_macro_init_bcl_pmic_reg(struct snd_soc_component *component)
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302770{
2771 struct device *wsa_dev = NULL;
2772 struct wsa_macro_priv *wsa_priv = NULL;
2773
Meng Wang15c825d2018-09-06 10:49:18 +08002774 if (!component) {
2775 pr_err("%s: NULL component pointer!\n", __func__);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302776 return;
2777 }
2778
Meng Wang15c825d2018-09-06 10:49:18 +08002779 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302780 return;
2781
2782 switch (wsa_priv->bcl_pmic_params.id) {
2783 case 0:
2784 /* Enable ID0 to listen to respective PMIC group interrupts */
Meng Wang15c825d2018-09-06 10:49:18 +08002785 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302786 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x02, 0x02);
2787 /* Update MC_SID0 */
Meng Wang15c825d2018-09-06 10:49:18 +08002788 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302789 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1, 0x0F,
2790 wsa_priv->bcl_pmic_params.sid);
2791 /* Update MC_PPID0 */
Meng Wang15c825d2018-09-06 10:49:18 +08002792 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302793 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2, 0xFF,
2794 wsa_priv->bcl_pmic_params.ppid);
2795 break;
2796 case 1:
2797 /* Enable ID1 to listen to respective PMIC group interrupts */
Meng Wang15c825d2018-09-06 10:49:18 +08002798 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302799 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x01, 0x01);
2800 /* Update MC_SID1 */
Meng Wang15c825d2018-09-06 10:49:18 +08002801 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302802 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3, 0x0F,
2803 wsa_priv->bcl_pmic_params.sid);
2804 /* Update MC_PPID1 */
Meng Wang15c825d2018-09-06 10:49:18 +08002805 snd_soc_component_update_bits(component,
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302806 BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4, 0xFF,
2807 wsa_priv->bcl_pmic_params.ppid);
2808 break;
2809 default:
2810 dev_err(wsa_dev, "%s: PMIC ID is invalid %d\n",
2811 __func__, wsa_priv->bcl_pmic_params.id);
2812 break;
2813 }
2814}
2815
Meng Wang15c825d2018-09-06 10:49:18 +08002816static void wsa_macro_init_reg(struct snd_soc_component *component)
Laxminath Kasam243e2752018-04-12 00:40:19 +05302817{
2818 int i;
2819
2820 for (i = 0; i < ARRAY_SIZE(wsa_macro_reg_init); i++)
Meng Wang15c825d2018-09-06 10:49:18 +08002821 snd_soc_component_update_bits(component,
Laxminath Kasam243e2752018-04-12 00:40:19 +05302822 wsa_macro_reg_init[i].reg,
2823 wsa_macro_reg_init[i].mask,
2824 wsa_macro_reg_init[i].val);
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05302825
Meng Wang15c825d2018-09-06 10:49:18 +08002826 wsa_macro_init_bcl_pmic_reg(component);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302827}
2828
Karthikeyan Mani8d40a062019-09-05 16:44:49 -07002829static int wsa_macro_core_vote(void *handle, bool enable)
2830{
2831 struct wsa_macro_priv *wsa_priv = (struct wsa_macro_priv *) handle;
Karthikeyan Mani8d40a062019-09-05 16:44:49 -07002832
2833 if (wsa_priv == NULL) {
2834 pr_err("%s: wsa priv data is NULL\n", __func__);
2835 return -EINVAL;
2836 }
2837 if (enable) {
2838 pm_runtime_get_sync(wsa_priv->dev);
2839 pm_runtime_put_autosuspend(wsa_priv->dev);
2840 pm_runtime_mark_last_busy(wsa_priv->dev);
2841 }
2842
Aditya Bavanarid577af92019-10-03 21:09:19 +05302843 if (bolero_check_core_votes(wsa_priv->dev))
2844 return 0;
2845 else
2846 return -EINVAL;
Karthikeyan Mani8d40a062019-09-05 16:44:49 -07002847}
2848
Laxminath Kasam243e2752018-04-12 00:40:19 +05302849static int wsa_swrm_clock(void *handle, bool enable)
2850{
2851 struct wsa_macro_priv *wsa_priv = (struct wsa_macro_priv *) handle;
2852 struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302853 int ret = 0;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302854
Tanya Dixitab8eba82018-10-05 15:07:37 +05302855 if (regmap == NULL) {
2856 dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
2857 return -EINVAL;
2858 }
2859
Laxminath Kasam243e2752018-04-12 00:40:19 +05302860 mutex_lock(&wsa_priv->swr_clk_lock);
2861
Aditya Bavanarif500a1d2019-09-16 18:27:51 -07002862 trace_printk("%s: %s swrm clock %s\n",
2863 dev_name(wsa_priv->dev), __func__,
2864 (enable ? "enable" : "disable"));
Laxminath Kasam243e2752018-04-12 00:40:19 +05302865 dev_dbg(wsa_priv->dev, "%s: swrm clock %s\n",
2866 __func__, (enable ? "enable" : "disable"));
2867 if (enable) {
Sudheer Papothi7601cc62019-03-30 03:00:52 +05302868 pm_runtime_get_sync(wsa_priv->dev);
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302869 if (wsa_priv->swr_clk_users == 0) {
Karthikeyan Mani8d40a062019-09-05 16:44:49 -07002870 ret = msm_cdc_pinctrl_select_active_state(
Karthikeyan Mani01f1ba42019-02-26 18:48:15 -08002871 wsa_priv->wsa_swr_gpio_p);
Karthikeyan Mani8d40a062019-09-05 16:44:49 -07002872 if (ret < 0) {
2873 dev_err_ratelimited(wsa_priv->dev,
2874 "%s: wsa swr pinctrl enable failed\n",
2875 __func__);
2876 pm_runtime_mark_last_busy(wsa_priv->dev);
2877 pm_runtime_put_autosuspend(wsa_priv->dev);
2878 goto exit;
2879 }
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302880 ret = wsa_macro_mclk_enable(wsa_priv, 1, true);
2881 if (ret < 0) {
Karthikeyan Mani01f1ba42019-02-26 18:48:15 -08002882 msm_cdc_pinctrl_select_sleep_state(
2883 wsa_priv->wsa_swr_gpio_p);
Ramprasad Katkam14efed62019-03-07 13:16:50 +05302884 dev_err_ratelimited(wsa_priv->dev,
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302885 "%s: wsa request clock enable failed\n",
2886 __func__);
Karthikeyan Mani8d40a062019-09-05 16:44:49 -07002887 pm_runtime_mark_last_busy(wsa_priv->dev);
2888 pm_runtime_put_autosuspend(wsa_priv->dev);
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302889 goto exit;
2890 }
Ramprasad Katkama4c747b2018-12-11 19:15:53 +05302891 if (wsa_priv->reset_swr)
2892 regmap_update_bits(regmap,
2893 BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
2894 0x02, 0x02);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302895 regmap_update_bits(regmap,
2896 BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
2897 0x01, 0x01);
Ramprasad Katkama4c747b2018-12-11 19:15:53 +05302898 if (wsa_priv->reset_swr)
2899 regmap_update_bits(regmap,
2900 BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
2901 0x02, 0x00);
2902 wsa_priv->reset_swr = false;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302903 }
Karthikeyan Mani8d40a062019-09-05 16:44:49 -07002904 wsa_priv->swr_clk_users++;
Sudheer Papothi7601cc62019-03-30 03:00:52 +05302905 pm_runtime_mark_last_busy(wsa_priv->dev);
2906 pm_runtime_put_autosuspend(wsa_priv->dev);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302907 } else {
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302908 if (wsa_priv->swr_clk_users <= 0) {
2909 dev_err(wsa_priv->dev, "%s: clock already disabled\n",
2910 __func__);
2911 wsa_priv->swr_clk_users = 0;
2912 goto exit;
2913 }
Laxminath Kasam243e2752018-04-12 00:40:19 +05302914 wsa_priv->swr_clk_users--;
2915 if (wsa_priv->swr_clk_users == 0) {
2916 regmap_update_bits(regmap,
2917 BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
2918 0x01, 0x00);
Karthikeyan Mani01f1ba42019-02-26 18:48:15 -08002919 wsa_macro_mclk_enable(wsa_priv, 0, true);
Karthikeyan Mani8d40a062019-09-05 16:44:49 -07002920 ret = msm_cdc_pinctrl_select_sleep_state(
Laxminath Kasam243e2752018-04-12 00:40:19 +05302921 wsa_priv->wsa_swr_gpio_p);
Karthikeyan Mani8d40a062019-09-05 16:44:49 -07002922 if (ret < 0) {
2923 dev_err_ratelimited(wsa_priv->dev,
2924 "%s: wsa swr pinctrl disable failed\n",
2925 __func__);
2926 goto exit;
2927 }
Laxminath Kasam243e2752018-04-12 00:40:19 +05302928 }
2929 }
Aditya Bavanarif500a1d2019-09-16 18:27:51 -07002930 trace_printk("%s: %s swrm clock users: %d\n",
2931 dev_name(wsa_priv->dev), __func__,
2932 wsa_priv->swr_clk_users);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302933 dev_dbg(wsa_priv->dev, "%s: swrm clock users %d\n",
2934 __func__, wsa_priv->swr_clk_users);
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302935exit:
Laxminath Kasam243e2752018-04-12 00:40:19 +05302936 mutex_unlock(&wsa_priv->swr_clk_lock);
Aditya Bavanaric496ed22018-11-16 15:50:40 +05302937 return ret;
Laxminath Kasam243e2752018-04-12 00:40:19 +05302938}
2939
Meng Wang15c825d2018-09-06 10:49:18 +08002940static int wsa_macro_init(struct snd_soc_component *component)
Laxminath Kasam243e2752018-04-12 00:40:19 +05302941{
Meng Wang15c825d2018-09-06 10:49:18 +08002942 struct snd_soc_dapm_context *dapm =
2943 snd_soc_component_get_dapm(component);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302944 int ret;
2945 struct device *wsa_dev = NULL;
2946 struct wsa_macro_priv *wsa_priv = NULL;
2947
Meng Wang15c825d2018-09-06 10:49:18 +08002948 wsa_dev = bolero_get_device_ptr(component->dev, WSA_MACRO);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302949 if (!wsa_dev) {
Meng Wang15c825d2018-09-06 10:49:18 +08002950 dev_err(component->dev,
Laxminath Kasam243e2752018-04-12 00:40:19 +05302951 "%s: null device for macro!\n", __func__);
2952 return -EINVAL;
2953 }
2954 wsa_priv = dev_get_drvdata(wsa_dev);
2955 if (!wsa_priv) {
Meng Wang15c825d2018-09-06 10:49:18 +08002956 dev_err(component->dev,
Laxminath Kasam243e2752018-04-12 00:40:19 +05302957 "%s: priv is null for macro!\n", __func__);
2958 return -EINVAL;
2959 }
2960
2961 ret = snd_soc_dapm_new_controls(dapm, wsa_macro_dapm_widgets,
2962 ARRAY_SIZE(wsa_macro_dapm_widgets));
2963 if (ret < 0) {
2964 dev_err(wsa_dev, "%s: Failed to add controls\n", __func__);
2965 return ret;
2966 }
2967
2968 ret = snd_soc_dapm_add_routes(dapm, wsa_audio_map,
2969 ARRAY_SIZE(wsa_audio_map));
2970 if (ret < 0) {
2971 dev_err(wsa_dev, "%s: Failed to add routes\n", __func__);
2972 return ret;
2973 }
2974
2975 ret = snd_soc_dapm_new_widgets(dapm->card);
2976 if (ret < 0) {
2977 dev_err(wsa_dev, "%s: Failed to add widgets\n", __func__);
2978 return ret;
2979 }
2980
Meng Wang15c825d2018-09-06 10:49:18 +08002981 ret = snd_soc_add_component_controls(component, wsa_macro_snd_controls,
Laxminath Kasam243e2752018-04-12 00:40:19 +05302982 ARRAY_SIZE(wsa_macro_snd_controls));
2983 if (ret < 0) {
2984 dev_err(wsa_dev, "%s: Failed to add snd_ctls\n", __func__);
2985 return ret;
2986 }
Laxminath Kasam638b5602018-09-24 13:19:52 +05302987 snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF1 Playback");
2988 snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_MIX1 Playback");
2989 snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_VI Capture");
2990 snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_ECHO Capture");
2991 snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK1 OUT");
2992 snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK2 OUT");
2993 snd_soc_dapm_ignore_suspend(dapm, "VIINPUT_WSA");
2994 snd_soc_dapm_ignore_suspend(dapm, "WSA SRC0_INP");
2995 snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC0_INP");
2996 snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC1_INP");
2997 snd_soc_dapm_sync(dapm);
Laxminath Kasam243e2752018-04-12 00:40:19 +05302998
Meng Wang15c825d2018-09-06 10:49:18 +08002999 wsa_priv->component = component;
Laxminath Kasam21c8b222018-06-21 18:47:22 +05303000 wsa_priv->spkr_gain_offset = WSA_MACRO_GAIN_OFFSET_0_DB;
Meng Wang15c825d2018-09-06 10:49:18 +08003001 wsa_macro_init_reg(component);
Laxminath Kasam243e2752018-04-12 00:40:19 +05303002
3003 return 0;
3004}
3005
Meng Wang15c825d2018-09-06 10:49:18 +08003006static int wsa_macro_deinit(struct snd_soc_component *component)
Laxminath Kasam243e2752018-04-12 00:40:19 +05303007{
3008 struct device *wsa_dev = NULL;
3009 struct wsa_macro_priv *wsa_priv = NULL;
3010
Meng Wang15c825d2018-09-06 10:49:18 +08003011 if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
Laxminath Kasam243e2752018-04-12 00:40:19 +05303012 return -EINVAL;
3013
Meng Wang15c825d2018-09-06 10:49:18 +08003014 wsa_priv->component = NULL;
Laxminath Kasam243e2752018-04-12 00:40:19 +05303015
3016 return 0;
3017}
3018
3019static void wsa_macro_add_child_devices(struct work_struct *work)
3020{
3021 struct wsa_macro_priv *wsa_priv;
3022 struct platform_device *pdev;
3023 struct device_node *node;
3024 struct wsa_macro_swr_ctrl_data *swr_ctrl_data = NULL, *temp;
3025 int ret;
3026 u16 count = 0, ctrl_num = 0;
3027 struct wsa_macro_swr_ctrl_platform_data *platdata;
3028 char plat_dev_name[WSA_MACRO_SWR_STRING_LEN];
3029
3030 wsa_priv = container_of(work, struct wsa_macro_priv,
3031 wsa_macro_add_child_devices_work);
3032 if (!wsa_priv) {
3033 pr_err("%s: Memory for wsa_priv does not exist\n",
3034 __func__);
3035 return;
3036 }
Laxminath Kasam21c8b222018-06-21 18:47:22 +05303037 if (!wsa_priv->dev || !wsa_priv->dev->of_node) {
Laxminath Kasam243e2752018-04-12 00:40:19 +05303038 dev_err(wsa_priv->dev,
3039 "%s: DT node for wsa_priv does not exist\n", __func__);
3040 return;
3041 }
3042
3043 platdata = &wsa_priv->swr_plat_data;
3044 wsa_priv->child_count = 0;
3045
3046 for_each_available_child_of_node(wsa_priv->dev->of_node, node) {
3047 if (strnstr(node->name, "wsa_swr_master",
3048 strlen("wsa_swr_master")) != NULL)
3049 strlcpy(plat_dev_name, "wsa_swr_ctrl",
3050 (WSA_MACRO_SWR_STRING_LEN - 1));
3051 else if (strnstr(node->name, "msm_cdc_pinctrl",
3052 strlen("msm_cdc_pinctrl")) != NULL)
3053 strlcpy(plat_dev_name, node->name,
3054 (WSA_MACRO_SWR_STRING_LEN - 1));
3055 else
3056 continue;
3057
3058 pdev = platform_device_alloc(plat_dev_name, -1);
3059 if (!pdev) {
3060 dev_err(wsa_priv->dev, "%s: pdev memory alloc failed\n",
3061 __func__);
3062 ret = -ENOMEM;
3063 goto err;
3064 }
3065 pdev->dev.parent = wsa_priv->dev;
3066 pdev->dev.of_node = node;
3067
3068 if (strnstr(node->name, "wsa_swr_master",
3069 strlen("wsa_swr_master")) != NULL) {
3070 ret = platform_device_add_data(pdev, platdata,
3071 sizeof(*platdata));
3072 if (ret) {
3073 dev_err(&pdev->dev,
3074 "%s: cannot add plat data ctrl:%d\n",
3075 __func__, ctrl_num);
3076 goto fail_pdev_add;
3077 }
3078 }
3079
3080 ret = platform_device_add(pdev);
3081 if (ret) {
3082 dev_err(&pdev->dev,
3083 "%s: Cannot add platform device\n",
3084 __func__);
3085 goto fail_pdev_add;
3086 }
3087
3088 if (!strcmp(node->name, "wsa_swr_master")) {
3089 temp = krealloc(swr_ctrl_data,
3090 (ctrl_num + 1) * sizeof(
3091 struct wsa_macro_swr_ctrl_data),
3092 GFP_KERNEL);
3093 if (!temp) {
3094 dev_err(&pdev->dev, "out of memory\n");
3095 ret = -ENOMEM;
3096 goto err;
3097 }
3098 swr_ctrl_data = temp;
3099 swr_ctrl_data[ctrl_num].wsa_swr_pdev = pdev;
3100 ctrl_num++;
3101 dev_dbg(&pdev->dev,
3102 "%s: Added soundwire ctrl device(s)\n",
3103 __func__);
3104 wsa_priv->swr_ctrl_data = swr_ctrl_data;
3105 }
3106 if (wsa_priv->child_count < WSA_MACRO_CHILD_DEVICES_MAX)
3107 wsa_priv->pdev_child_devices[
3108 wsa_priv->child_count++] = pdev;
3109 else
3110 goto err;
3111 }
3112
3113 return;
3114fail_pdev_add:
3115 for (count = 0; count < wsa_priv->child_count; count++)
3116 platform_device_put(wsa_priv->pdev_child_devices[count]);
3117err:
3118 return;
3119}
3120
3121static void wsa_macro_init_ops(struct macro_ops *ops,
3122 char __iomem *wsa_io_base)
3123{
3124 memset(ops, 0, sizeof(struct macro_ops));
3125 ops->init = wsa_macro_init;
3126 ops->exit = wsa_macro_deinit;
3127 ops->io_base = wsa_io_base;
3128 ops->dai_ptr = wsa_macro_dai;
3129 ops->num_dais = ARRAY_SIZE(wsa_macro_dai);
Laxminath Kasamfb0d6832018-09-22 01:49:52 +05303130 ops->event_handler = wsa_macro_event_handler;
Sudheer Papothia3e969d2018-10-27 06:22:10 +05303131 ops->set_port_map = wsa_macro_set_port_map;
Laxminath Kasam243e2752018-04-12 00:40:19 +05303132}
3133
3134static int wsa_macro_probe(struct platform_device *pdev)
3135{
3136 struct macro_ops ops;
3137 struct wsa_macro_priv *wsa_priv;
Vidyakumar Athota5d45f4c2019-03-10 22:35:07 -07003138 u32 wsa_base_addr, default_clk_id;
Laxminath Kasam243e2752018-04-12 00:40:19 +05303139 char __iomem *wsa_io_base;
3140 int ret = 0;
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05303141 u8 bcl_pmic_params[3];
Karthikeyan Mani3bd80a52019-06-04 23:40:16 -07003142 u32 is_used_wsa_swr_gpio = 1;
3143 const char *is_used_wsa_swr_gpio_dt = "qcom,is-used-swr-gpio";
Laxminath Kasam243e2752018-04-12 00:40:19 +05303144
3145 wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct wsa_macro_priv),
3146 GFP_KERNEL);
3147 if (!wsa_priv)
3148 return -ENOMEM;
3149
3150 wsa_priv->dev = &pdev->dev;
3151 ret = of_property_read_u32(pdev->dev.of_node, "reg",
3152 &wsa_base_addr);
3153 if (ret) {
3154 dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
3155 __func__, "reg");
3156 return ret;
3157 }
Karthikeyan Mani3bd80a52019-06-04 23:40:16 -07003158 if (of_find_property(pdev->dev.of_node, is_used_wsa_swr_gpio_dt,
3159 NULL)) {
3160 ret = of_property_read_u32(pdev->dev.of_node,
3161 is_used_wsa_swr_gpio_dt,
3162 &is_used_wsa_swr_gpio);
3163 if (ret) {
3164 dev_err(&pdev->dev, "%s: error reading %s in dt\n",
3165 __func__, is_used_wsa_swr_gpio_dt);
3166 is_used_wsa_swr_gpio = 1;
3167 }
3168 }
Laxminath Kasam243e2752018-04-12 00:40:19 +05303169 wsa_priv->wsa_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
3170 "qcom,wsa-swr-gpios", 0);
Karthikeyan Mani3bd80a52019-06-04 23:40:16 -07003171 if (!wsa_priv->wsa_swr_gpio_p && is_used_wsa_swr_gpio) {
Laxminath Kasam243e2752018-04-12 00:40:19 +05303172 dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
3173 __func__);
3174 return -EINVAL;
3175 }
Karthikeyan Manib44e4552019-09-09 23:06:04 -07003176 if (msm_cdc_pinctrl_get_state(wsa_priv->wsa_swr_gpio_p) < 0 &&
3177 is_used_wsa_swr_gpio) {
Karthikeyan Mani326536d2019-06-03 13:29:43 -07003178 dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
3179 __func__);
3180 return -EPROBE_DEFER;
3181 }
3182
Laxminath Kasam243e2752018-04-12 00:40:19 +05303183 wsa_io_base = devm_ioremap(&pdev->dev,
3184 wsa_base_addr, WSA_MACRO_MAX_OFFSET);
3185 if (!wsa_io_base) {
3186 dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
3187 return -EINVAL;
3188 }
3189 wsa_priv->wsa_io_base = wsa_io_base;
Ramprasad Katkama4c747b2018-12-11 19:15:53 +05303190 wsa_priv->reset_swr = true;
Laxminath Kasam243e2752018-04-12 00:40:19 +05303191 INIT_WORK(&wsa_priv->wsa_macro_add_child_devices_work,
3192 wsa_macro_add_child_devices);
3193 wsa_priv->swr_plat_data.handle = (void *) wsa_priv;
3194 wsa_priv->swr_plat_data.read = NULL;
3195 wsa_priv->swr_plat_data.write = NULL;
3196 wsa_priv->swr_plat_data.bulk_write = NULL;
3197 wsa_priv->swr_plat_data.clk = wsa_swrm_clock;
Karthikeyan Mani8d40a062019-09-05 16:44:49 -07003198 wsa_priv->swr_plat_data.core_vote = wsa_macro_core_vote;
Laxminath Kasam243e2752018-04-12 00:40:19 +05303199 wsa_priv->swr_plat_data.handle_irq = NULL;
3200
Vidyakumar Athota5d45f4c2019-03-10 22:35:07 -07003201 ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id",
3202 &default_clk_id);
3203 if (ret) {
3204 dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
3205 __func__, "qcom,mux0-clk-id");
3206 default_clk_id = WSA_CORE_CLK;
Laxminath Kasam243e2752018-04-12 00:40:19 +05303207 }
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05303208
3209 ret = of_property_read_u8_array(pdev->dev.of_node,
3210 "qcom,wsa-bcl-pmic-params", bcl_pmic_params,
3211 sizeof(bcl_pmic_params));
3212 if (ret) {
3213 dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
3214 __func__, "qcom,wsa-bcl-pmic-params");
3215 } else {
3216 wsa_priv->bcl_pmic_params.id = bcl_pmic_params[0];
3217 wsa_priv->bcl_pmic_params.sid = bcl_pmic_params[1];
3218 wsa_priv->bcl_pmic_params.ppid = bcl_pmic_params[2];
3219 }
Vidyakumar Athota5d45f4c2019-03-10 22:35:07 -07003220 wsa_priv->default_clk_id = default_clk_id;
Aditya Bavanari4f3d5642018-09-18 22:19:10 +05303221
Laxminath Kasam243e2752018-04-12 00:40:19 +05303222 dev_set_drvdata(&pdev->dev, wsa_priv);
3223 mutex_init(&wsa_priv->mclk_lock);
3224 mutex_init(&wsa_priv->swr_clk_lock);
3225 wsa_macro_init_ops(&ops, wsa_io_base);
Vidyakumar Athota5d45f4c2019-03-10 22:35:07 -07003226 ops.clk_id_req = wsa_priv->default_clk_id;
3227 ops.default_clk_id = wsa_priv->default_clk_id;
Laxminath Kasam243e2752018-04-12 00:40:19 +05303228 ret = bolero_register_macro(&pdev->dev, WSA_MACRO, &ops);
3229 if (ret < 0) {
3230 dev_err(&pdev->dev, "%s: register macro failed\n", __func__);
3231 goto reg_macro_fail;
3232 }
3233 schedule_work(&wsa_priv->wsa_macro_add_child_devices_work);
Sudheer Papothi7601cc62019-03-30 03:00:52 +05303234 pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
3235 pm_runtime_use_autosuspend(&pdev->dev);
3236 pm_runtime_set_suspended(&pdev->dev);
Karthikeyan Mani3d209512019-10-03 13:51:53 -07003237 pm_suspend_ignore_children(&pdev->dev, true);
Sudheer Papothi7601cc62019-03-30 03:00:52 +05303238 pm_runtime_enable(&pdev->dev);
3239
Laxminath Kasam243e2752018-04-12 00:40:19 +05303240 return ret;
3241reg_macro_fail:
3242 mutex_destroy(&wsa_priv->mclk_lock);
3243 mutex_destroy(&wsa_priv->swr_clk_lock);
3244 return ret;
3245}
3246
3247static int wsa_macro_remove(struct platform_device *pdev)
3248{
3249 struct wsa_macro_priv *wsa_priv;
3250 u16 count = 0;
3251
3252 wsa_priv = dev_get_drvdata(&pdev->dev);
3253
3254 if (!wsa_priv)
3255 return -EINVAL;
3256
3257 for (count = 0; count < wsa_priv->child_count &&
3258 count < WSA_MACRO_CHILD_DEVICES_MAX; count++)
3259 platform_device_unregister(wsa_priv->pdev_child_devices[count]);
3260
Sudheer Papothi7601cc62019-03-30 03:00:52 +05303261 pm_runtime_disable(&pdev->dev);
3262 pm_runtime_set_suspended(&pdev->dev);
Laxminath Kasam243e2752018-04-12 00:40:19 +05303263 bolero_unregister_macro(&pdev->dev, WSA_MACRO);
3264 mutex_destroy(&wsa_priv->mclk_lock);
3265 mutex_destroy(&wsa_priv->swr_clk_lock);
3266 return 0;
3267}
3268
3269static const struct of_device_id wsa_macro_dt_match[] = {
3270 {.compatible = "qcom,wsa-macro"},
3271 {}
3272};
3273
Sudheer Papothi7601cc62019-03-30 03:00:52 +05303274static const struct dev_pm_ops bolero_dev_pm_ops = {
Aditya Bavanari4460ed22020-02-20 12:46:51 +05303275 SET_SYSTEM_SLEEP_PM_OPS(
3276 pm_runtime_force_suspend,
3277 pm_runtime_force_resume
3278 )
Sudheer Papothi7601cc62019-03-30 03:00:52 +05303279 SET_RUNTIME_PM_OPS(
3280 bolero_runtime_suspend,
3281 bolero_runtime_resume,
3282 NULL
3283 )
3284};
3285
Laxminath Kasam243e2752018-04-12 00:40:19 +05303286static struct platform_driver wsa_macro_driver = {
3287 .driver = {
3288 .name = "wsa_macro",
3289 .owner = THIS_MODULE,
Sudheer Papothi7601cc62019-03-30 03:00:52 +05303290 .pm = &bolero_dev_pm_ops,
Laxminath Kasam243e2752018-04-12 00:40:19 +05303291 .of_match_table = wsa_macro_dt_match,
Xiaojun Sang53cd13a2018-06-29 15:14:37 +08003292 .suppress_bind_attrs = true,
Laxminath Kasam243e2752018-04-12 00:40:19 +05303293 },
3294 .probe = wsa_macro_probe,
3295 .remove = wsa_macro_remove,
3296};
3297
3298module_platform_driver(wsa_macro_driver);
3299
3300MODULE_DESCRIPTION("WSA macro driver");
3301MODULE_LICENSE("GPL v2");