blob: 0f3a8ba893a634b2fea2c26f06e197e328809094 [file] [log] [blame]
Dhanalakshmi Siddani08ca8462019-03-04 22:50:53 +05301 /* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
Raja Mallikdc60da52018-05-21 16:41:24 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "%s: " fmt "\n", __func__
14
15#include <linux/clk.h>
16#include <linux/delay.h>
17#include <linux/gpio.h>
18#include <linux/of_gpio.h>
19#include <linux/platform_device.h>
20#include <linux/slab.h>
21#include <linux/io.h>
22#include <linux/module.h>
23#include <linux/workqueue.h>
24#include <linux/sched.h>
25#include <linux/input.h>
26#include <sound/core.h>
27#include <sound/soc.h>
28#include <sound/soc-dapm.h>
29#include <sound/pcm.h>
30#include <sound/pcm_params.h>
31#include <sound/jack.h>
32#include <sound/info.h>
33#include <dsp/q6afe-v2.h>
34#include <soc/qcom/socinfo.h>
35
36#include "codecs/msm-cdc-pinctrl.h"
37#include "msm-pcm-routing-v2.h"
38
39#include "codecs/wcd9335.h"
40#include "codecs/wsa881x.h"
41
42#define DRV_NAME "apq8009-i2s-wcd"
43
44/* dummy definition of deprecated FE DAI's*/
45enum {
46 MSM_FRONTEND_DAI_CS_VOICE = 39,
47 MSM_FRONTEND_DAI_VOICE2,
48 MSM_FRONTEND_DAI_VOLTE,
49 MSM_FRONTEND_DAI_VOWLAN,
50};
51
52#define BTSCO_RATE_8KHZ 8000
53#define BTSCO_RATE_16KHZ 16000
54
55#define SAMPLING_RATE_8KHZ 8000
56#define SAMPLING_RATE_16KHZ 16000
57#define SAMPLING_RATE_32KHZ 32000
58#define SAMPLING_RATE_48KHZ 48000
59#define SAMPLING_RATE_96KHZ 96000
60#define SAMPLING_RATE_192KHZ 192000
61
62#define PRI_MI2S_ID (1 << 0)
63#define SEC_MI2S_ID (1 << 1)
64#define TER_MI2S_ID (1 << 2)
65#define QUAT_MI2S_ID (1 << 3)
66
67#define LPASS_CSR_GP_IO_MUX_MIC_CTL 0x07702000
68#define LPASS_CSR_GP_IO_MUX_SPKR_CTL 0x07702004
69
70#define WCD9XXX_MBHC_DEF_BUTTONS 8
71#define WCD9XXX_MBHC_DEF_RLOADS 5
72#define DEFAULT_MCLK_RATE 9600000
73
74#define WCD_MBHC_DEF_RLOADS 5
75
76#define LPASS_CSR_GP_LPAIF_PRI_PCM_PRI_MODE_MUXSEL 0x07702008
77
78#define MAX_AUX_CODECS 2
79
80#define DEV_NAME_STR_LEN 32
81
82#define WSA8810_NAME_1 "wsa881x.20170211"
83#define WSA8810_NAME_2 "wsa881x.20170212"
84
85#define TDM_SLOT_OFFSET_MAX 8
86
87enum btsco_rates {
88 RATE_8KHZ_ID,
89 RATE_16KHZ_ID,
90};
91
92enum {
93 PRIMARY_TDM_RX_0,
94 PRIMARY_TDM_TX_0,
95 SECONDARY_TDM_RX_0,
96 SECONDARY_TDM_TX_0,
97 TDM_MAX,
98};
99
100/* TDM default channels */
101static int msm_pri_tdm_rx_0_ch = 8;
102static int msm_pri_tdm_tx_0_ch = 8;
103
104/* TDM default bit format */
105static int msm_pri_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S16_LE;
106static int msm_pri_tdm_tx_0_bit_format = SNDRV_PCM_FORMAT_S16_LE;
107
108/* TDM default sampling rate */
109static int msm_pri_tdm_rx_0_sample_rate = SAMPLING_RATE_48KHZ;
110static int msm_pri_tdm_tx_0_sample_rate = SAMPLING_RATE_48KHZ;
111
112static char const *tdm_ch_text[] = {"One", "Two", "Three", "Four",
113 "Five", "Six", "Seven", "Eight"};
114static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE",
115 "S32_LE"};
116static char const *tdm_sample_rate_text[] = {"KHZ_16", "KHZ_48"};
117
118/* TDM default offset */
119static unsigned int tdm_slot_offset[TDM_MAX][TDM_SLOT_OFFSET_MAX] = {
120 /* PRI_TDM_RX */
121 {0, 4, 8, 12, 16, 20, 24, 28},
122 /* PRI_TDM_TX */
123 {0, 4, 8, 12, 16, 20, 24, 28},
124};
125
126enum {
127 DIG_CDC,
128 ANA_CDC,
129 CODECS_MAX,
130};
131
132enum {
133 PRIM_MI2S = 0,
134 SEC_MI2S,
135 TERT_MI2S,
136 QUAT_MI2S,
137 MI2S_MAX,
138};
139
140struct apq8009_asoc_mach_data {
141 int mclk_freq;
142 atomic_t quat_ref_count;
143 struct device_node *mi2s_gpio_p[MI2S_MAX]; /* used by pinctrl API */
144 struct afe_digital_clk_cfg digital_cdc_clk;
145 void __iomem *vaddr_gpio_mux_spkr_ctl;
146 void __iomem *vaddr_gpio_mux_mic_ctl;
147 void __iomem *vaddr_gpio_mux_quin_ctl;
148 void __iomem *vaddr_gpio_mux_pcm_ctl;
149 struct snd_info_entry *codec_root;
150};
151
152struct apq8009_wsa881x_dev_info {
153 struct device_node *of_node;
154 u32 index;
155};
156
157static struct snd_soc_aux_dev *apq8009_aux_dev;
158static struct snd_soc_codec_conf *apq8009_codec_conf;
159
160static int msm_btsco_rate = BTSCO_RATE_8KHZ;
161static int msm_btsco_ch = 1;
162
163static int msm_mi2s_tx_ch = 2;
Dhanalakshmi Siddani08ca8462019-03-04 22:50:53 +0530164static int msm_afe_lb_tx_ch = 2;
Raja Mallikdc60da52018-05-21 16:41:24 +0530165static int msm_pri_mi2s_rx_ch = 2;
166static int pri_rx_sample_rate = SAMPLING_RATE_48KHZ;
167static int pri_tx_sample_rate = SAMPLING_RATE_48KHZ;
168
169static int msm_proxy_rx_ch = 2;
170static int apq8009_auxpcm_rate = 8000;
171
172static atomic_t pri_mi2s_clk_ref;
173static atomic_t quat_mi2s_clk_ref;
174static atomic_t auxpcm_mi2s_clk_ref;
175static int tdm_i2s_switch_enable = -EINVAL;
176
177static int apq8009_enable_extcodec_ext_clk(struct snd_soc_codec *codec,
178 int enable, bool dapm);
179
180/*
181 * Android L spec
182 * Need to report LINEIN
183 * if R/L channel impedance is larger than 5K ohm
184 */
185
186static struct wcd_mbhc_config wcd_mbhc_cfg = {
187 .read_fw_bin = false,
188 .calibration = NULL,
189 .detect_extn_cable = true,
190 .mono_stero_detection = false,
191 .swap_gnd_mic = NULL,
192 .hs_ext_micbias = false,
193 .key_code[0] = KEY_MEDIA,
194 .key_code[1] = KEY_VOICECOMMAND,
195 .key_code[2] = KEY_VOLUMEUP,
196 .key_code[3] = KEY_VOLUMEDOWN,
197 .key_code[4] = 0,
198 .key_code[5] = 0,
199 .key_code[6] = 0,
200 .key_code[7] = 0,
201 .linein_th = 5000,
202};
203
204static void *def_tasha_mbhc_cal(void)
205{
206 void *tasha_wcd_cal;
207 struct wcd_mbhc_btn_detect_cfg *btn_cfg;
208 u16 *btn_high;
209
210 tasha_wcd_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
211 WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL);
212 if (!tasha_wcd_cal)
213 return NULL;
214
215#define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(tasha_wcd_cal)->X) = (Y))
216 S(v_hs_max, 1500);
217#undef S
218#define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(tasha_wcd_cal)->X) = (Y))
219 S(num_btn, WCD_MBHC_DEF_BUTTONS);
220#undef S
221
222 btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(tasha_wcd_cal);
223 btn_high = ((void *)&btn_cfg->_v_btn_low) +
224 (sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
225
226 btn_high[0] = 75;
227 btn_high[1] = 150;
228 btn_high[2] = 237;
229 btn_high[3] = 450;
230 btn_high[4] = 500;
231 btn_high[5] = 500;
232 btn_high[6] = 500;
233 btn_high[7] = 500;
234
235 return tasha_wcd_cal;
236}
237
238static struct afe_clk_set mi2s_tx_clk = {
239 AFE_API_VERSION_I2S_CONFIG,
240 Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT,
241 Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
242 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
243 Q6AFE_LPASS_CLK_ROOT_DEFAULT,
244 0,
245};
246
247static struct afe_clk_set mi2s_rx_clk = {
248 AFE_API_VERSION_I2S_CONFIG,
249 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
250 Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
251 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
252 Q6AFE_LPASS_CLK_ROOT_DEFAULT,
253 0,
254};
255
256static int mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
257static int mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
258static int rx_bits_per_sample = 16;
259static int tx_bits_per_sample = 16;
260
261static inline int param_is_mask(int p)
262{
263 return ((p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
264 (p <= SNDRV_PCM_HW_PARAM_LAST_MASK));
265}
266
267static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
268{
269 return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
270}
271
272static int apq8009_wsa881x_init(struct snd_soc_component *component)
273{
274 u8 spkleft_ports[WSA881X_MAX_SWR_PORTS] = {100, 101, 102, 106};
275 u8 spkright_ports[WSA881X_MAX_SWR_PORTS] = {103, 104, 105, 107};
276 unsigned int ch_rate[WSA881X_MAX_SWR_PORTS] = {2400, 600, 300, 1200};
277 unsigned int ch_mask[WSA881X_MAX_SWR_PORTS] = {0x1, 0xF, 0x3, 0x3};
278 struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
279 struct apq8009_asoc_mach_data *pdata;
280 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
281
282 if (!codec) {
283 pr_err("%s codec is NULL\n", __func__);
284 return -EINVAL;
285 }
286
287 if (!strcmp(component->name_prefix, "SpkrLeft")) {
288 dev_err(codec->dev, "%s: setting left ch map to codec %s\n",
289 __func__, codec->component.name);
290 wsa881x_set_channel_map(codec, &spkleft_ports[0],
291 WSA881X_MAX_SWR_PORTS, &ch_mask[0],
292 &ch_rate[0]);
293 if (dapm->component) {
294 snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft IN");
295 snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft SPKR");
296 }
297 } else if (!strcmp(component->name_prefix, "SpkrRight")) {
298 dev_err(codec->dev, "%s: setting right ch map to codec %s\n",
299 __func__, codec->component.name);
300 wsa881x_set_channel_map(codec, &spkright_ports[0],
301 WSA881X_MAX_SWR_PORTS, &ch_mask[0],
302 &ch_rate[0]);
303 if (dapm->component) {
304 snd_soc_dapm_ignore_suspend(dapm, "SpkrRight IN");
305 snd_soc_dapm_ignore_suspend(dapm, "SpkrRight SPKR");
306 }
307 } else {
308 dev_err(codec->dev, "%s: wrong codec name %s\n", __func__,
309 codec->component.name);
310 return -EINVAL;
311 }
312
313 pdata = snd_soc_card_get_drvdata(component->card);
314 if (pdata && pdata->codec_root)
315 wsa881x_codec_info_create_codec_entry(pdata->codec_root,
316 codec);
317
318 return 0;
319}
320
321static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned int bit)
322{
323 if (bit >= SNDRV_MASK_MAX)
324 return;
325 if (param_is_mask(n)) {
326 struct snd_mask *m = param_to_mask(p, n);
327
328 m->bits[0] = 0;
329 m->bits[1] = 0;
330 m->bits[bit >> 5] |= (1 << (bit & 31));
331 }
332}
333static int apq8009_mclk_event(struct snd_soc_dapm_widget *w,
334 struct snd_kcontrol *kcontrol, int event);
335
336static const struct snd_soc_dapm_widget apq8009_dapm_widgets[] = {
337
338 SND_SOC_DAPM_SUPPLY_S("MCLK", -1, SND_SOC_NOPM, 0, 0,
339 apq8009_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
340 SND_SOC_DAPM_MIC("Handset Mic", NULL),
341 SND_SOC_DAPM_MIC("Headset Mic", NULL),
342 SND_SOC_DAPM_MIC("Secondary Mic", NULL),
343 SND_SOC_DAPM_MIC("Digital Mic0", NULL),
344 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
345 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
346 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
347};
348
349static struct snd_soc_dapm_route wcd9335_audio_paths[] = {
350 {"MIC BIAS1", NULL, "MCLK"},
351 {"MIC BIAS2", NULL, "MCLK"},
352 {"MIC BIAS3", NULL, "MCLK"},
353 {"MIC BIAS4", NULL, "MCLK"},
354};
355
356static char const *rx_bit_format_text[] = {"S16_LE", "S24_3LE", "S24_LE",
357 "S32_LE"};
358static const char *const mi2s_tx_ch_text[] = {"One", "Two", "Three", "Four"};
359static char const *pri_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
360 "KHZ_192", "KHZ_8",
361 "KHZ_16", "KHZ_32"};
Dhanalakshmi Siddani08ca8462019-03-04 22:50:53 +0530362static const char *const afe_lb_tx_ch_text[] = {"One", "Two"};
Raja Mallikdc60da52018-05-21 16:41:24 +0530363
364static int msm_pri_tdm_rx_0_ch_get(struct snd_kcontrol *kcontrol,
365 struct snd_ctl_elem_value *ucontrol)
366{
367 pr_debug("msm_pri_tdm_rx_0_ch = %d",
368 msm_pri_tdm_rx_0_ch);
369 ucontrol->value.integer.value[0] = msm_pri_tdm_rx_0_ch - 1;
370 return 0;
371}
372
373static int msm_pri_tdm_rx_0_ch_put(struct snd_kcontrol *kcontrol,
374 struct snd_ctl_elem_value *ucontrol)
375{
376 msm_pri_tdm_rx_0_ch = ucontrol->value.integer.value[0] + 1;
377 pr_debug("msm_pri_tdm_rx_0_ch = %d",
378 msm_pri_tdm_rx_0_ch);
379 return 0;
380}
381
382static int msm_pri_tdm_tx_0_ch_get(struct snd_kcontrol *kcontrol,
383 struct snd_ctl_elem_value *ucontrol)
384{
385 pr_debug("msm_pri_tdm_tx_0_ch = %d",
386 msm_pri_tdm_tx_0_ch);
387 ucontrol->value.integer.value[0] = msm_pri_tdm_tx_0_ch - 1;
388 return 0;
389}
390
391static int msm_pri_tdm_tx_0_ch_put(struct snd_kcontrol *kcontrol,
392 struct snd_ctl_elem_value *ucontrol)
393{
394 msm_pri_tdm_tx_0_ch = ucontrol->value.integer.value[0] + 1;
395 pr_debug("msm_pri_tdm_tx_0_ch = %d",
396 msm_pri_tdm_tx_0_ch);
397 return 0;
398}
399
400static int msm_pri_tdm_rx_0_bit_format_get(struct snd_kcontrol *kcontrol,
401 struct snd_ctl_elem_value *ucontrol)
402{
403 switch (msm_pri_tdm_rx_0_bit_format) {
404 case SNDRV_PCM_FORMAT_S32_LE:
405 ucontrol->value.integer.value[0] = 3;
406 break;
407 case SNDRV_PCM_FORMAT_S24_3LE:
408 ucontrol->value.integer.value[0] = 2;
409 break;
410 case SNDRV_PCM_FORMAT_S24_LE:
411 ucontrol->value.integer.value[0] = 1;
412 break;
413 case SNDRV_PCM_FORMAT_S16_LE:
414 default:
415 ucontrol->value.integer.value[0] = 0;
416 break;
417 }
418 pr_debug("msm_pri_tdm_rx_0_bit_format = %ld",
419 ucontrol->value.integer.value[0]);
420 return 0;
421}
422
423static int msm_pri_tdm_rx_0_bit_format_put(struct snd_kcontrol *kcontrol,
424 struct snd_ctl_elem_value *ucontrol)
425{
426 switch (ucontrol->value.integer.value[0]) {
427 case 3:
428 msm_pri_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S32_LE;
429 break;
430 case 2:
431 msm_pri_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
432 break;
433 case 1:
434 msm_pri_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S24_LE;
435 break;
436 case 0:
437 default:
438 msm_pri_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S16_LE;
439 break;
440 }
441 pr_debug("msm_pri_tdm_rx_0_bit_format = %d",
442 msm_pri_tdm_rx_0_bit_format);
443 return 0;
444}
445
446static int msm_pri_tdm_tx_0_bit_format_get(struct snd_kcontrol *kcontrol,
447 struct snd_ctl_elem_value *ucontrol)
448{
449 switch (msm_pri_tdm_tx_0_bit_format) {
450 case SNDRV_PCM_FORMAT_S32_LE:
451 ucontrol->value.integer.value[0] = 3;
452 break;
453 case SNDRV_PCM_FORMAT_S24_3LE:
454 ucontrol->value.integer.value[0] = 2;
455 break;
456 case SNDRV_PCM_FORMAT_S24_LE:
457 ucontrol->value.integer.value[0] = 1;
458 break;
459 case SNDRV_PCM_FORMAT_S16_LE:
460 default:
461 ucontrol->value.integer.value[0] = 0;
462 break;
463 }
464 pr_debug("msm_pri_tdm_tx_0_bit_format = %ld",
465 ucontrol->value.integer.value[0]);
466 return 0;
467}
468
469static int msm_pri_tdm_tx_0_bit_format_put(struct snd_kcontrol *kcontrol,
470 struct snd_ctl_elem_value *ucontrol)
471{
472 switch (ucontrol->value.integer.value[0]) {
473 case 3:
474 msm_pri_tdm_tx_0_bit_format = SNDRV_PCM_FORMAT_S32_LE;
475 break;
476 case 2:
477 msm_pri_tdm_tx_0_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
478 break;
479 case 1:
480 msm_pri_tdm_tx_0_bit_format = SNDRV_PCM_FORMAT_S24_LE;
481 break;
482 case 0:
483 default:
484 msm_pri_tdm_tx_0_bit_format = SNDRV_PCM_FORMAT_S16_LE;
485 break;
486 }
487 pr_debug("msm_pri_tdm_tx_0_bit_format = %d",
488 msm_pri_tdm_tx_0_bit_format);
489 return 0;
490}
491
492static int msm_pri_tdm_rx_0_sample_rate_get(struct snd_kcontrol *kcontrol,
493 struct snd_ctl_elem_value *ucontrol)
494{
495 switch (msm_pri_tdm_rx_0_sample_rate) {
496 case SAMPLING_RATE_16KHZ:
497 ucontrol->value.integer.value[0] = 0;
498 break;
499 case SAMPLING_RATE_48KHZ:
500 default:
501 ucontrol->value.integer.value[0] = 1;
502 break;
503 }
504 pr_debug("msm_pri_tdm_rx_0_sample_rate = %ld",
505 ucontrol->value.integer.value[0]);
506 return 0;
507}
508
509static int msm_pri_tdm_rx_0_sample_rate_put(struct snd_kcontrol *kcontrol,
510 struct snd_ctl_elem_value *ucontrol)
511{
512 switch (ucontrol->value.integer.value[0]) {
513 case 0:
514 msm_pri_tdm_rx_0_sample_rate = SAMPLING_RATE_16KHZ;
515 break;
516 case 1:
517 default:
518 msm_pri_tdm_rx_0_sample_rate = SAMPLING_RATE_48KHZ;
519 break;
520 }
521 pr_debug("msm_pri_tdm_rx_0_sample_rate = %d",
522 msm_pri_tdm_rx_0_sample_rate);
523 return 0;
524}
525
526static int msm_pri_tdm_tx_0_sample_rate_get(struct snd_kcontrol *kcontrol,
527 struct snd_ctl_elem_value *ucontrol)
528{
529 switch (msm_pri_tdm_tx_0_sample_rate) {
530 case SAMPLING_RATE_16KHZ:
531 ucontrol->value.integer.value[0] = 0;
532 break;
533 case SAMPLING_RATE_48KHZ:
534 default:
535 ucontrol->value.integer.value[0] = 1;
536 break;
537 }
538 pr_debug("msm_pri_tdm_tx_0_sample_rate = %ld",
539 ucontrol->value.integer.value[0]);
540 return 0;
541}
542
543static int msm_pri_tdm_tx_0_sample_rate_put(struct snd_kcontrol *kcontrol,
544 struct snd_ctl_elem_value *ucontrol)
545{
546 switch (ucontrol->value.integer.value[0]) {
547 case 0:
548 msm_pri_tdm_tx_0_sample_rate = SAMPLING_RATE_16KHZ;
549 break;
550 case 1:
551 default:
552 msm_pri_tdm_tx_0_sample_rate = SAMPLING_RATE_48KHZ;
553 break;
554 }
555 pr_debug("msm_pri_tdm_tx_0_sample_rate = %d",
556 msm_pri_tdm_tx_0_sample_rate);
557 return 0;
558}
559
560static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
561 struct snd_pcm_hw_params *params)
562{
563 struct snd_interval *rate =
564 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
565
566 struct snd_interval *channels =
567 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
568
569 rate->min = rate->max = apq8009_auxpcm_rate;
570 channels->min = channels->max = 1;
571
572 return 0;
573}
574
575static int msm_pri_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
576 struct snd_pcm_hw_params *params)
577{
578 struct snd_interval *rate = hw_param_interval(params,
579 SNDRV_PCM_HW_PARAM_RATE);
580
581 struct snd_interval *channels = hw_param_interval(params,
582 SNDRV_PCM_HW_PARAM_CHANNELS);
583
584 pr_debug("%s: Number of channels = %d Sample rate = %d\n", __func__,
585 msm_pri_mi2s_rx_ch, pri_rx_sample_rate);
586 rate->min = rate->max = pri_rx_sample_rate;
587 channels->min = channels->max = msm_pri_mi2s_rx_ch;
588
589 return 0;
590}
591
592static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
593 struct snd_pcm_hw_params *params)
594{
595 struct snd_interval *rate = hw_param_interval(params,
596 SNDRV_PCM_HW_PARAM_RATE);
597
598 struct snd_interval *channels = hw_param_interval(params,
599 SNDRV_PCM_HW_PARAM_CHANNELS);
600
601 pr_debug("%s()\n", __func__);
602 rate->min = rate->max = 48000;
603 channels->min = channels->max = 2;
604
605 return 0;
606}
607
608static int mi2s_rx_bit_format_get(struct snd_kcontrol *kcontrol,
609 struct snd_ctl_elem_value *ucontrol)
610{
611
612 switch (mi2s_rx_bit_format) {
613 case SNDRV_PCM_FORMAT_S24_LE:
614 ucontrol->value.integer.value[0] = 2;
615 break;
616
617 case SNDRV_PCM_FORMAT_S24_3LE:
618 ucontrol->value.integer.value[0] = 1;
619 break;
620
621 case SNDRV_PCM_FORMAT_S16_LE:
622 default:
623 ucontrol->value.integer.value[0] = 0;
624 break;
625 }
626
627 pr_debug("%s: mi2s_rx_bit_format = %d, ucontrol value = %ld\n",
628 __func__, mi2s_rx_bit_format,
629 ucontrol->value.integer.value[0]);
630
631 return 0;
632}
633
634static int mi2s_rx_bit_format_put(struct snd_kcontrol *kcontrol,
635 struct snd_ctl_elem_value *ucontrol)
636{
637 switch (ucontrol->value.integer.value[0]) {
638 case 2:
639 mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
640 rx_bits_per_sample = 32;
641 break;
642 case 1:
643 mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
644 rx_bits_per_sample = 32;
645 break;
646 case 0:
647 default:
648 mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
649 rx_bits_per_sample = 16;
650 break;
651 }
652
653 pr_debug("%s: mi2s_rx_bit_format = %d, ucontrol value = %ld\n",
654 __func__, mi2s_rx_bit_format,
655 ucontrol->value.integer.value[0]);
656
657 return 0;
658}
659
660static int mi2s_tx_bit_format_get(struct snd_kcontrol *kcontrol,
661 struct snd_ctl_elem_value *ucontrol)
662{
663
664 switch (mi2s_tx_bit_format) {
665 case SNDRV_PCM_FORMAT_S32_LE:
666 ucontrol->value.integer.value[0] = 3;
667 break;
668
669 case SNDRV_PCM_FORMAT_S24_LE:
670 ucontrol->value.integer.value[0] = 2;
671 break;
672
673 case SNDRV_PCM_FORMAT_S24_3LE:
674 ucontrol->value.integer.value[0] = 1;
675 break;
676
677 case SNDRV_PCM_FORMAT_S16_LE:
678 default:
679 ucontrol->value.integer.value[0] = 0;
680 break;
681 }
682
683 pr_debug("%s: mi2s_tx_bit_format = %d, ucontrol value = %ld\n",
684 __func__, mi2s_tx_bit_format,
685 ucontrol->value.integer.value[0]);
686
687 return 0;
688}
689
690static int mi2s_tx_bit_format_put(struct snd_kcontrol *kcontrol,
691 struct snd_ctl_elem_value *ucontrol)
692{
693 switch (ucontrol->value.integer.value[0]) {
694 case 3:
695 mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S32_LE;
696 tx_bits_per_sample = 32;
697 break;
698 case 2:
699 mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
700 tx_bits_per_sample = 32;
701 break;
702 case 1:
703 mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
704 tx_bits_per_sample = 32;
705 break;
706 case 0:
707 default:
708 mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
709 tx_bits_per_sample = 16;
710 break;
711 }
712
713 pr_debug("%s: mi2s_tx_bit_format = %d, ucontrol value = %ld\n",
714 __func__, mi2s_tx_bit_format,
715 ucontrol->value.integer.value[0]);
716
717 return 0;
718}
719
720static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
721 struct snd_pcm_hw_params *params)
722{
723 struct snd_interval *rate = hw_param_interval(params,
724 SNDRV_PCM_HW_PARAM_RATE);
725
726 struct snd_interval *channels = hw_param_interval(params,
727 SNDRV_PCM_HW_PARAM_CHANNELS);
728
729 rate->min = rate->max = msm_btsco_rate;
730 channels->min = channels->max = msm_btsco_ch;
731
732 return 0;
733}
734
735static int msm_proxy_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
736 struct snd_pcm_hw_params *params)
737{
738 struct snd_interval *rate = hw_param_interval(params,
739 SNDRV_PCM_HW_PARAM_RATE);
740
741 struct snd_interval *channels = hw_param_interval(params,
742 SNDRV_PCM_HW_PARAM_CHANNELS);
743
744 pr_debug("%s: msm_proxy_rx_ch =%d\n", __func__, msm_proxy_rx_ch);
745
746 if (channels->max < 2)
747 channels->min = channels->max = 2;
748 channels->min = channels->max = msm_proxy_rx_ch;
749 rate->min = rate->max = 48000;
750 return 0;
751}
752
753static int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
754 struct snd_pcm_hw_params *params)
755{
756 struct snd_interval *rate = hw_param_interval(params,
757 SNDRV_PCM_HW_PARAM_RATE);
758
759 rate->min = rate->max = 48000;
760 return 0;
761}
762
763static int msm_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
764 struct snd_pcm_hw_params *params)
765{
766 struct snd_interval *rate = hw_param_interval(params,
767 SNDRV_PCM_HW_PARAM_RATE);
768 struct snd_interval *channels = hw_param_interval(params,
769 SNDRV_PCM_HW_PARAM_CHANNELS);
770
771 pr_debug("%s(), channel:%d\n", __func__, msm_mi2s_tx_ch);
772 rate->min = rate->max = 48000;
773 channels->min = channels->max = msm_mi2s_tx_ch;
774
775 return 0;
776}
777
Dhanalakshmi Siddani08ca8462019-03-04 22:50:53 +0530778static int msm_afe_lb_tx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
779 struct snd_pcm_hw_params *params)
780{
781 struct snd_interval *rate = hw_param_interval(params,
782 SNDRV_PCM_HW_PARAM_RATE);
783 struct snd_interval *channels = hw_param_interval(params,
784 SNDRV_PCM_HW_PARAM_CHANNELS);
785
786 pr_debug("%s(), channel: %d\n", __func__, msm_afe_lb_tx_ch);
787 rate->min = rate->max = 48000;
788 channels->min = channels->max = msm_afe_lb_tx_ch;
789
790 return 0;
791}
792
Raja Mallikdc60da52018-05-21 16:41:24 +0530793static int msm_tdm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
794 struct snd_pcm_hw_params *params)
795{
796 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
797 struct snd_interval *rate = hw_param_interval(params,
798 SNDRV_PCM_HW_PARAM_RATE);
799 struct snd_interval *channels = hw_param_interval(params,
800 SNDRV_PCM_HW_PARAM_CHANNELS);
801
802 switch (cpu_dai->id) {
803 case AFE_PORT_ID_PRIMARY_TDM_RX:
804 channels->min = channels->max = msm_pri_tdm_rx_0_ch;
805 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
806 msm_pri_tdm_rx_0_bit_format);
807 rate->min = rate->max = msm_pri_tdm_rx_0_sample_rate;
808 break;
809 case AFE_PORT_ID_PRIMARY_TDM_TX:
810 channels->min = channels->max = msm_pri_tdm_tx_0_ch;
811 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
812 msm_pri_tdm_tx_0_bit_format);
813 rate->min = rate->max = msm_pri_tdm_tx_0_sample_rate;
814 break;
815 default:
816 pr_err("%s: dai id 0x%x not supported", __func__,
817 cpu_dai->id);
818 return -EINVAL;
819 }
820
821 pr_debug("%s: dai id = 0x%x channels = %d rate = %d", __func__,
822 cpu_dai->id, channels->max, rate->max);
823
824 return 0;
825}
826
827static unsigned int tdm_param_set_slot_mask(u16 port_id,
828 int slot_width, int channels)
829{
830 unsigned int slot_mask = 0;
831 int upper, lower, i, j;
832 unsigned int *slot_offset;
833
834 switch (port_id) {
835 case AFE_PORT_ID_PRIMARY_TDM_RX:
836 lower = PRIMARY_TDM_RX_0;
837 upper = PRIMARY_TDM_RX_0;
838 break;
839 case AFE_PORT_ID_PRIMARY_TDM_TX:
840 lower = PRIMARY_TDM_TX_0;
841 upper = PRIMARY_TDM_TX_0;
842 break;
843 default:
844 return slot_mask;
845 }
846
847 for (i = lower; i <= upper; i++) {
848 slot_offset = tdm_slot_offset[i];
849 for (j = 0; j < channels; j++) {
850 if (slot_offset[j] != AFE_SLOT_MAPPING_OFFSET_INVALID)
851 /*
852 * set the mask of active slot according to
853 * the offset table for the group of devices
854 */
855 slot_mask |=
856 (1 << ((slot_offset[j] * 8) / slot_width));
857 else
858 break;
859 }
860 }
861
862 return slot_mask;
863}
864
865static int msm_tdm_snd_hw_params(struct snd_pcm_substream *substream,
866 struct snd_pcm_hw_params *params)
867{
868 struct snd_soc_pcm_runtime *rtd = substream->private_data;
869 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
870 int ret = 0;
871 int channels, slot_width, slots;
872 unsigned int slot_mask;
873 unsigned int *slot_offset;
874 int offset_channels = 0;
875 int i;
876
877 pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id);
878
879 channels = params_channels(params);
880 switch (channels) {
881 case 1:
882 case 2:
883 case 3:
884 case 4:
885 case 6:
886 case 8:
887 switch (params_format(params)) {
888 case SNDRV_PCM_FORMAT_S32_LE:
889 case SNDRV_PCM_FORMAT_S24_LE:
890 case SNDRV_PCM_FORMAT_S24_3LE:
891 case SNDRV_PCM_FORMAT_S16_LE:
892 /*
893 * up to 8 channel HW configuration should
894 * use 32 bit slot width for max support of
895 * stream bit width. (slot_width > bit_width)
896 */
897 slot_width = 32;
898 break;
899 default:
900 pr_err("%s: invalid param format 0x%x\n",
901 __func__, params_format(params));
902 return -EINVAL;
903 }
904 slots = 8;
905 slot_mask = tdm_param_set_slot_mask(cpu_dai->id,
906 slot_width, channels);
907 if (!slot_mask) {
908 pr_err("%s: invalid slot_mask 0x%x\n",
909 __func__, slot_mask);
910 return -EINVAL;
911 }
912 break;
913 default:
914 pr_err("%s: invalid param channels %d\n",
915 __func__, channels);
916 return -EINVAL;
917 }
918
919 switch (cpu_dai->id) {
920 case AFE_PORT_ID_PRIMARY_TDM_RX:
921 slot_offset = tdm_slot_offset[PRIMARY_TDM_RX_0];
922 break;
923 case AFE_PORT_ID_PRIMARY_TDM_TX:
924 slot_offset = tdm_slot_offset[PRIMARY_TDM_TX_0];
925 break;
926 default:
927 pr_err("%s: dai id 0x%x not supported\n",
928 __func__, cpu_dai->id);
929 return -EINVAL;
930 }
931
932 for (i = 0; i < channels; i++) {
933 if (slot_offset[i] != AFE_SLOT_MAPPING_OFFSET_INVALID)
934 offset_channels++;
935 else
936 break;
937 }
938
939 if (offset_channels == 0) {
940 pr_err("%s: slot offset not supported, offset_channels %d\n",
941 __func__, offset_channels);
942 return -EINVAL;
943 }
944
945 if (channels > offset_channels) {
946 pr_err("%s: channels %d exceed offset_channels %d\n",
947 __func__, channels, offset_channels);
948 return -EINVAL;
949 }
950
951 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
952 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, slot_mask,
953 slots, slot_width);
954 if (ret < 0) {
955 pr_err("%s: failed to set tdm slot, err:%d\n",
956 __func__, ret);
957 goto end;
958 }
959
960 ret = snd_soc_dai_set_channel_map(cpu_dai,
961 0, NULL, channels, slot_offset);
962 if (ret < 0) {
963 pr_err("%s: failed to set channel map, err:%d\n",
964 __func__, ret);
965 goto end;
966 }
967 } else {
968 ret = snd_soc_dai_set_tdm_slot(cpu_dai, slot_mask, 0,
969 slots, slot_width);
970 if (ret < 0) {
971 pr_err("%s: failed to set tdm slot, err:%d\n",
972 __func__, ret);
973 goto end;
974 }
975
976 ret = snd_soc_dai_set_channel_map(cpu_dai,
977 channels, slot_offset, 0, NULL);
978 if (ret < 0) {
979 pr_err("%s: failed to set channel map, err:%d\n",
980 __func__, ret);
981 goto end;
982 }
983 }
984
985end:
986 return ret;
987}
988
989static int msm_pri_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol,
990 struct snd_ctl_elem_value *ucontrol)
991{
992 pr_debug("%s: msm_pri_mi2s_rx_ch = %d\n", __func__,
993 msm_pri_mi2s_rx_ch);
994 ucontrol->value.integer.value[0] = msm_pri_mi2s_rx_ch - 1;
995 return 0;
996}
997
998static int msm_pri_mi2s_rx_ch_put(struct snd_kcontrol *kcontrol,
999 struct snd_ctl_elem_value *ucontrol)
1000{
1001 msm_pri_mi2s_rx_ch = ucontrol->value.integer.value[0] + 1;
1002
1003 pr_debug("%s: msm_pri_mi2s_rx_ch = %d\n", __func__, msm_pri_mi2s_rx_ch);
1004 return 1;
1005}
1006
1007static int pri_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
1008 struct snd_ctl_elem_value *ucontrol)
1009{
1010 int sample_rate_val = 0;
1011
1012 switch (pri_rx_sample_rate) {
1013 case SAMPLING_RATE_32KHZ:
1014 sample_rate_val = 5;
1015 break;
1016 case SAMPLING_RATE_16KHZ:
1017 sample_rate_val = 4;
1018 break;
1019 case SAMPLING_RATE_8KHZ:
1020 sample_rate_val = 3;
1021 break;
1022 case SAMPLING_RATE_192KHZ:
1023 sample_rate_val = 2;
1024 break;
1025 case SAMPLING_RATE_96KHZ:
1026 sample_rate_val = 1;
1027 break;
1028 case SAMPLING_RATE_48KHZ:
1029 default:
1030 sample_rate_val = 0;
1031 break;
1032 }
1033
1034 ucontrol->value.integer.value[0] = sample_rate_val;
1035 pr_debug("%s: sample_rate_val = %d\n", __func__,
1036 sample_rate_val);
1037
1038 return 0;
1039}
1040
1041static int pri_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
1042 struct snd_ctl_elem_value *ucontrol)
1043{
1044 switch (ucontrol->value.integer.value[0]) {
1045 case 5:
1046 pri_rx_sample_rate = SAMPLING_RATE_32KHZ;
1047 break;
1048 case 4:
1049 pri_rx_sample_rate = SAMPLING_RATE_16KHZ;
1050 break;
1051 case 3:
1052 pri_rx_sample_rate = SAMPLING_RATE_8KHZ;
1053 break;
1054 case 2:
1055 pri_rx_sample_rate = SAMPLING_RATE_192KHZ;
1056 break;
1057 case 1:
1058 pri_rx_sample_rate = SAMPLING_RATE_96KHZ;
1059 break;
1060 case 0:
1061 default:
1062 pri_rx_sample_rate = SAMPLING_RATE_48KHZ;
1063 }
1064 pr_debug("%s: pri_rx_sample_rate = %d\n", __func__,
1065 pri_rx_sample_rate);
1066 return 0;
1067}
1068
1069static int msm_mi2s_tx_ch_get(struct snd_kcontrol *kcontrol,
1070 struct snd_ctl_elem_value *ucontrol)
1071{
1072 pr_debug("%s: msm_mi2s_tx_ch = %d\n", __func__,
1073 msm_mi2s_tx_ch);
1074 ucontrol->value.integer.value[0] = msm_mi2s_tx_ch - 1;
1075 return 0;
1076}
1077
1078static int msm_mi2s_tx_ch_put(struct snd_kcontrol *kcontrol,
1079 struct snd_ctl_elem_value *ucontrol)
1080{
1081 msm_mi2s_tx_ch = ucontrol->value.integer.value[0] + 1;
1082
1083 pr_debug("%s: msm_mi2s_tx_ch = %d\n", __func__,
1084 msm_mi2s_tx_ch);
1085 return 1;
1086}
1087
Dhanalakshmi Siddani08ca8462019-03-04 22:50:53 +05301088static int msm_afe_loopback_tx_ch_get(struct snd_kcontrol *kcontrol,
1089 struct snd_ctl_elem_value *ucontrol)
1090{
1091 pr_debug("%s: msm_afe_lb_tx_ch = %d\n", __func__,
1092 msm_afe_lb_tx_ch);
1093 ucontrol->value.integer.value[0] = msm_afe_lb_tx_ch - 1;
1094 return 0;
1095}
1096
1097static int msm_afe_loopback_tx_ch_put(struct snd_kcontrol *kcontrol,
1098 struct snd_ctl_elem_value *ucontrol)
1099{
1100 msm_afe_lb_tx_ch = ucontrol->value.integer.value[0] + 1;
1101
1102 pr_debug("%s: msm_afe_lb_tx_ch = %d\n", __func__,
1103 msm_afe_lb_tx_ch);
1104 return 1;
1105}
1106
Raja Mallikdc60da52018-05-21 16:41:24 +05301107static int msm_mi2s_snd_hw_params(struct snd_pcm_substream *substream,
1108 struct snd_pcm_hw_params *params)
1109{
1110 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1111 substream->name, substream->stream);
1112 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, mi2s_rx_bit_format);
1113 return 0;
1114}
1115
1116static int msm_quat_snd_hw_params(struct snd_pcm_substream *substream,
1117 struct snd_pcm_hw_params *params)
1118{
1119 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1120 substream->name, substream->stream);
1121 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, mi2s_tx_bit_format);
1122 return 0;
1123}
1124
1125static int apq8009_get_port_id(int id)
1126{
1127 switch (id) {
1128 case MSM_BACKEND_DAI_PRI_MI2S_RX:
1129 return AFE_PORT_ID_PRIMARY_MI2S_RX;
1130 case MSM_BACKEND_DAI_SECONDARY_MI2S_RX:
1131 return AFE_PORT_ID_SECONDARY_MI2S_RX;
1132 case MSM_BACKEND_DAI_TERTIARY_MI2S_TX:
1133 return AFE_PORT_ID_TERTIARY_MI2S_TX;
1134 case MSM_BACKEND_DAI_QUATERNARY_MI2S_RX:
1135 return AFE_PORT_ID_QUATERNARY_MI2S_RX;
1136 case MSM_BACKEND_DAI_QUATERNARY_MI2S_TX:
1137 return AFE_PORT_ID_QUATERNARY_MI2S_TX;
1138 case MSM_BACKEND_DAI_QUINARY_MI2S_RX:
1139 return AFE_PORT_ID_QUINARY_MI2S_RX;
1140 case MSM_BACKEND_DAI_QUINARY_MI2S_TX:
1141 return AFE_PORT_ID_QUINARY_MI2S_TX;
1142 case MSM_BACKEND_DAI_SENARY_MI2S_TX:
1143 return AFE_PORT_ID_SENARY_MI2S_TX;
1144 default:
1145 pr_err("%s: Invalid be_id: %d\n", __func__, id);
1146 return -EINVAL;
1147 }
1148}
1149
1150static int apq8009_get_clk_id(int port_id)
1151{
1152 switch (port_id) {
1153 case AFE_PORT_ID_PRIMARY_MI2S_RX:
1154 return Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT;
1155 case AFE_PORT_ID_SECONDARY_MI2S_RX:
1156 return Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT;
1157 case AFE_PORT_ID_TERTIARY_MI2S_TX:
1158 return Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT;
1159 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
1160 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
1161 return Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT;
1162 case AFE_PORT_ID_QUINARY_MI2S_RX:
1163 case AFE_PORT_ID_QUINARY_MI2S_TX:
1164 return Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT;
1165 case AFE_PORT_ID_SENARY_MI2S_TX:
1166 return Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT;
1167 default:
1168 pr_err("%s: invalid port_id: 0x%x\n", __func__, port_id);
1169 return -EINVAL;
1170 }
1171}
1172
1173static uint32_t get_mi2s_rx_clk_val(void)
1174{
1175 uint32_t clk_val;
1176
1177 clk_val = pri_rx_sample_rate * rx_bits_per_sample * 2;
1178
1179 return clk_val;
1180}
1181
1182static uint32_t get_mi2s_tx_clk_val(void)
1183{
1184 uint32_t clk_val;
1185
1186 clk_val = pri_tx_sample_rate * tx_bits_per_sample * 2;
1187
1188 return clk_val;
1189}
1190
1191static int ext_mi2s_clk_ctl(struct snd_pcm_substream *substream, bool enable)
1192{
1193 int ret = 0;
1194 int port_id = 0;
1195 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1196 struct snd_soc_codec *codec = rtd->codec;
1197
1198 port_id = apq8009_get_port_id(rtd->dai_link->id);
1199 if (port_id < 0) {
1200 pr_err("%s: Invalid port_id\n", __func__);
1201 return -EINVAL;
1202 }
1203
1204 if (enable) {
1205 apq8009_enable_extcodec_ext_clk(codec, 1, true);
1206 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1207 mi2s_rx_clk.enable = enable;
1208 mi2s_rx_clk.clk_id = apq8009_get_clk_id(port_id);
1209 mi2s_rx_clk.clk_freq_in_hz =
1210 get_mi2s_rx_clk_val();
1211 ret = afe_set_lpass_clock_v2(port_id, &mi2s_rx_clk);
1212 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
1213 mi2s_tx_clk.enable = enable;
1214 mi2s_tx_clk.clk_id = apq8009_get_clk_id(port_id);
1215 mi2s_tx_clk.clk_freq_in_hz =
1216 get_mi2s_tx_clk_val();
1217 ret = afe_set_lpass_clock_v2(port_id, &mi2s_tx_clk);
1218 } else
1219 pr_err("%s:Not valid substream.\n", __func__);
1220
1221 if (ret < 0)
1222 pr_err("%s:afe_set_lpass_clock failed ret=%d\n",
1223 __func__, ret);
1224 } else {
1225 apq8009_enable_extcodec_ext_clk(codec, 0, true);
1226 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1227 mi2s_rx_clk.enable = enable;
1228 mi2s_rx_clk.clk_id = apq8009_get_clk_id(port_id);
1229 mi2s_rx_clk.clk_freq_in_hz = 0;
1230 ret = afe_set_lpass_clock_v2(port_id, &mi2s_rx_clk);
1231 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
1232 mi2s_tx_clk.enable = enable;
1233 mi2s_tx_clk.clk_id = apq8009_get_clk_id(port_id);
1234 mi2s_tx_clk.clk_freq_in_hz = 0;
1235 ret = afe_set_lpass_clock_v2(port_id, &mi2s_tx_clk);
1236 } else
1237 pr_err("%s:Not valid substream %d\n", __func__,
1238 substream->stream);
1239
1240 if (ret < 0)
1241 pr_err("%s:afe_set_lpass_clock failed ret=%d\n",
1242 __func__, ret);
1243 }
1244 return ret;
1245}
1246
1247static int apq8009_enable_extcodec_ext_clk(struct snd_soc_codec *codec,
1248 int enable, bool dapm)
1249{
1250 tasha_cdc_mclk_enable(codec, enable, dapm);
1251 return 0;
1252}
1253
1254static int msm_btsco_rate_get(struct snd_kcontrol *kcontrol,
1255 struct snd_ctl_elem_value *ucontrol)
1256{
1257 pr_debug("%s: msm_btsco_rate = %d", __func__, msm_btsco_rate);
1258 ucontrol->value.integer.value[0] = msm_btsco_rate;
1259 return 0;
1260}
1261
1262static int msm_btsco_rate_put(struct snd_kcontrol *kcontrol,
1263 struct snd_ctl_elem_value *ucontrol)
1264{
1265 switch (ucontrol->value.integer.value[0]) {
1266 case RATE_8KHZ_ID:
1267 msm_btsco_rate = BTSCO_RATE_8KHZ;
1268 break;
1269 case RATE_16KHZ_ID:
1270 msm_btsco_rate = BTSCO_RATE_16KHZ;
1271 break;
1272 default:
1273 msm_btsco_rate = BTSCO_RATE_8KHZ;
1274 break;
1275 }
1276
1277 pr_debug("%s: msm_btsco_rate = %d\n", __func__, msm_btsco_rate);
1278 return 0;
1279}
1280
1281static const struct soc_enum msm_snd_enum[] = {
1282 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_bit_format_text),
1283 rx_bit_format_text),
1284 SOC_ENUM_SINGLE_EXT(4, mi2s_tx_ch_text),
1285 SOC_ENUM_SINGLE_EXT(6, pri_rx_sample_rate_text),
1286 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tdm_ch_text),
1287 tdm_ch_text),
1288 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tdm_bit_format_text),
1289 tdm_bit_format_text),
1290 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tdm_sample_rate_text),
1291 tdm_sample_rate_text),
Dhanalakshmi Siddani08ca8462019-03-04 22:50:53 +05301292 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(afe_lb_tx_ch_text),
1293 afe_lb_tx_ch_text),
Raja Mallikdc60da52018-05-21 16:41:24 +05301294};
1295
1296static const char *const btsco_rate_text[] = {"BTSCO_RATE_8KHZ",
1297 "BTSCO_RATE_16KHZ"};
1298static const struct soc_enum msm_btsco_enum[] = {
1299 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
1300};
1301
1302static const struct snd_kcontrol_new msm_snd_controls[] = {
1303 SOC_ENUM_EXT("MI2S_RX Format", msm_snd_enum[0],
1304 mi2s_rx_bit_format_get, mi2s_rx_bit_format_put),
1305 SOC_ENUM_EXT("MI2S_TX Format", msm_snd_enum[0],
1306 mi2s_tx_bit_format_get, mi2s_tx_bit_format_put),
1307 SOC_ENUM_EXT("MI2S_TX Channels", msm_snd_enum[1],
1308 msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
1309 SOC_ENUM_EXT("MI2S_RX Channels", msm_snd_enum[1],
1310 msm_pri_mi2s_rx_ch_get, msm_pri_mi2s_rx_ch_put),
1311 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
1312 msm_btsco_rate_get, msm_btsco_rate_put),
1313 SOC_ENUM_EXT("MI2S_RX SampleRate", msm_snd_enum[2],
1314 pri_rx_sample_rate_get, pri_rx_sample_rate_put),
1315 SOC_ENUM_EXT("PRI_TDM_RX_0 Channels", msm_snd_enum[3],
1316 msm_pri_tdm_rx_0_ch_get, msm_pri_tdm_rx_0_ch_put),
1317 SOC_ENUM_EXT("PRI_TDM_TX_0 Channels", msm_snd_enum[3],
1318 msm_pri_tdm_tx_0_ch_get, msm_pri_tdm_tx_0_ch_put),
1319 SOC_ENUM_EXT("PRI_TDM_RX_0 Bit Format", msm_snd_enum[4],
1320 msm_pri_tdm_rx_0_bit_format_get,
1321 msm_pri_tdm_rx_0_bit_format_put),
1322 SOC_ENUM_EXT("PRI_TDM_TX_0 Bit Format", msm_snd_enum[4],
1323 msm_pri_tdm_tx_0_bit_format_get,
1324 msm_pri_tdm_tx_0_bit_format_put),
1325 SOC_ENUM_EXT("PRI_TDM_RX_0 SampleRate", msm_snd_enum[5],
1326 msm_pri_tdm_rx_0_sample_rate_get,
1327 msm_pri_tdm_rx_0_sample_rate_put),
1328 SOC_ENUM_EXT("PRI_TDM_TX_0 SampleRate", msm_snd_enum[5],
1329 msm_pri_tdm_tx_0_sample_rate_get,
1330 msm_pri_tdm_tx_0_sample_rate_put),
Dhanalakshmi Siddani08ca8462019-03-04 22:50:53 +05301331 SOC_ENUM_EXT("AFE_LOOPBACK_TX Channels", msm_snd_enum[6],
1332 msm_afe_loopback_tx_ch_get,
1333 msm_afe_loopback_tx_ch_put),
Raja Mallikdc60da52018-05-21 16:41:24 +05301334};
1335
1336static int apq8009_mclk_event(struct snd_soc_dapm_widget *w,
1337 struct snd_kcontrol *kcontrol, int event)
1338{
1339 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1340
1341 pr_debug("%s: event = %d\n", __func__, event);
1342 switch (event) {
1343 case SND_SOC_DAPM_PRE_PMU:
1344 apq8009_enable_extcodec_ext_clk(codec, 1, true);
1345 break;
1346 case SND_SOC_DAPM_POST_PMD:
1347 apq8009_enable_extcodec_ext_clk(codec, 0, true);
1348 break;
1349 }
1350 return 0;
1351}
1352
1353static int msm_prim_auxpcm_startup(struct snd_pcm_substream *substream)
1354{
1355 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1356 struct snd_soc_card *card = rtd->card;
1357 struct apq8009_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
1358 void __iomem *vaddr = NULL;
1359 int val = 0;
1360
1361 pr_debug("%s(): substream = %s\n", __func__, substream->name);
1362
1363 /* mux config to route the AUX MI2S */
1364 vaddr = pdata->vaddr_gpio_mux_mic_ctl;
1365 val = ioread32(vaddr);
1366 val = val | 0x2020002;
1367 iowrite32(val, vaddr);
1368 vaddr = pdata->vaddr_gpio_mux_pcm_ctl;
1369 val = ioread32(vaddr);
1370 val = val | 0x01;
1371 iowrite32(val, vaddr);
1372
1373 return 0;
1374}
1375
1376static int msm_quat_mi2s_snd_startup(struct snd_pcm_substream *substream)
1377{
1378 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1379 struct snd_soc_card *card = rtd->card;
1380 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1381 struct apq8009_asoc_mach_data *pdata =
1382 snd_soc_card_get_drvdata(card);
1383 int ret = 0;
1384 int val = 0;
1385 void __iomem *vaddr = NULL;
1386
1387 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1388 substream->name, substream->stream);
1389 vaddr = pdata->vaddr_gpio_mux_spkr_ctl;
1390 val = ioread32(vaddr);
1391 val = val | 0x00000002;
1392 iowrite32(val, vaddr);
1393
1394 vaddr = pdata->vaddr_gpio_mux_mic_ctl;
1395 val = ioread32(vaddr);
1396 val = val|0x2020002;
1397 iowrite32(val, vaddr);
1398
1399 ret = ext_mi2s_clk_ctl(substream, true);
1400 if (ret < 0) {
1401 pr_err("%s: failed to enable sclk\n", __func__);
1402 return ret;
1403 }
1404
1405 if (atomic_inc_return(&pdata->quat_ref_count) == 1) {
1406 if (pdata->mi2s_gpio_p[QUAT_MI2S]) {
1407 ret = msm_cdc_pinctrl_select_active_state(
1408 pdata->mi2s_gpio_p[QUAT_MI2S]);
1409 if (ret < 0) {
1410 pr_err("%s: failed to activate the quat gpio's state\n",
1411 __func__);
1412 goto err;
1413 }
1414 }
1415 }
1416 if (atomic_inc_return(&quat_mi2s_clk_ref) == 1) {
1417 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
1418 if (ret < 0)
1419 pr_err("%s: set fmt cpu dai failed\n", __func__);
1420 }
1421 return ret;
1422err:
1423 ret = ext_mi2s_clk_ctl(substream, false);
1424 if (ret < 0)
1425 pr_err("%s: failed to disable sclk\n", __func__);
1426 return ret;
1427}
1428
1429static void msm_quat_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
1430{
1431
1432 int ret;
1433 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1434 struct snd_soc_card *card = rtd->card;
1435 struct apq8009_asoc_mach_data *pdata =
1436 snd_soc_card_get_drvdata(card);
1437
1438
1439 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1440 substream->name, substream->stream);
1441 atomic_dec_return(&quat_mi2s_clk_ref);
1442
1443 ret = ext_mi2s_clk_ctl(substream, false);
1444 if (ret < 0)
1445 pr_err("%s: failed to disable sclk\n", __func__);
1446
1447 if (atomic_dec_return(&pdata->quat_ref_count) == 0) {
1448 if (pdata->mi2s_gpio_p[QUAT_MI2S]) {
1449 ret = msm_cdc_pinctrl_select_sleep_state(
1450 pdata->mi2s_gpio_p[QUAT_MI2S]);
1451 if (ret < 0)
1452 pr_err("%s: gpio set cannot be de-activated %sd",
1453 __func__, "quat_i2s");
1454 }
1455 }
1456
1457}
1458
1459static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
1460{
1461 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1462 struct snd_soc_card *card = rtd->card;
1463 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1464 struct apq8009_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
1465 int ret = 0;
1466 int val = 0;
1467 void __iomem *vaddr = NULL;
1468
1469 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1470 substream->name, substream->stream);
1471 vaddr = pdata->vaddr_gpio_mux_spkr_ctl;
1472 val = ioread32(vaddr);
1473 val = val | 0x201C;
1474 iowrite32(val, vaddr);
1475
1476 vaddr = pdata->vaddr_gpio_mux_mic_ctl;
1477 val = ioread32(vaddr);
1478 val = val | 0x00000002;
1479 iowrite32(val, vaddr);
1480
1481 ret = ext_mi2s_clk_ctl(substream, true);
1482 if (ret < 0) {
1483 pr_err("%s: failed to enable sclk\n", __func__);
1484 return ret;
1485 }
1486
1487 if (pdata->mi2s_gpio_p[PRIM_MI2S]) {
1488 ret = msm_cdc_pinctrl_select_active_state(
1489 pdata->mi2s_gpio_p[PRIM_MI2S]);
1490 if (ret < 0) {
1491 pr_err("%s: failed to activate the quat gpio's state\n",
1492 __func__);
1493 goto err;
1494 }
1495 }
1496
1497 if (atomic_inc_return(&pri_mi2s_clk_ref) == 1) {
1498 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
1499 if (ret < 0)
1500 pr_err("%s: set fmt cpu dai failed; ret=%d\n",
1501 __func__, ret);
1502 }
1503 return ret;
1504err:
1505 ret = ext_mi2s_clk_ctl(substream, false);
1506 if (ret < 0)
1507 pr_err("%s: failed to disable sclk\n", __func__);
1508 return ret;
1509}
1510
1511static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
1512{
1513 int ret;
1514 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1515 struct snd_soc_card *card = rtd->card;
1516 struct apq8009_asoc_mach_data *pdata =
1517 snd_soc_card_get_drvdata(card);
1518
1519 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1520 substream->name, substream->stream);
1521
1522 if (atomic_dec_return(&pri_mi2s_clk_ref) == 0) {
1523 ret = ext_mi2s_clk_ctl(substream, false);
1524 if (ret < 0)
1525 pr_err("%s: failed to enable sclk\n", __func__);
1526
1527 if (pdata->mi2s_gpio_p[PRIM_MI2S]) {
1528 ret = msm_cdc_pinctrl_select_sleep_state(
1529 pdata->mi2s_gpio_p[PRIM_MI2S]);
1530 if (ret < 0)
1531 pr_err("%s: gpio set cannot be de-activated %sd",
1532 __func__, "pri_i2s");
1533 }
1534 }
1535}
1536
1537static int msm_tdm_startup(struct snd_pcm_substream *substream)
1538{
1539 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1540 struct snd_soc_card *card = rtd->card;
1541 struct apq8009_asoc_mach_data *pdata =
1542 snd_soc_card_get_drvdata(card);
1543 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1544 int ret = 0, val = 0;
1545
1546 pr_debug("%s: substream = %s stream = %d", __func__,
1547 substream->name, substream->stream);
1548 pr_debug("%s: dai id = 0x%x", __func__, cpu_dai->id);
1549
1550 switch (cpu_dai->id) {
1551 case AFE_PORT_ID_PRIMARY_TDM_RX:
1552 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
1553 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
1554 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
1555 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
1556 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
1557 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
1558 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
1559 case AFE_PORT_ID_PRIMARY_TDM_TX:
1560 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
1561 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
1562 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
1563 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
1564 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
1565 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
1566 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
1567 case AFE_PORT_ID_QUATERNARY_TDM_TX:
1568 /* Configure mux for Primary TDM */
1569 if (pdata->vaddr_gpio_mux_pcm_ctl) {
1570 val = ioread32(pdata->vaddr_gpio_mux_pcm_ctl);
1571 val = val | 0x00000001;
1572 iowrite32(val, pdata->vaddr_gpio_mux_pcm_ctl);
1573 } else {
1574 return -EINVAL;
1575 }
1576 if (pdata->vaddr_gpio_mux_mic_ctl) {
1577 val = ioread32(pdata->vaddr_gpio_mux_mic_ctl);
1578 /*0x1808000 Use this value for slave mode*/
1579 val = val | 0x02020002; /*this is for master mode*/
1580 iowrite32(val, pdata->vaddr_gpio_mux_mic_ctl);
1581 } else {
1582 return -EINVAL;
1583 }
1584
1585 if (atomic_inc_return(&pdata->quat_ref_count) == 1) {
1586 /* Enable I2S switch to turn on TDM mics for SOM*/
1587 if (pdata->mi2s_gpio_p[QUAT_MI2S]) {
1588 ret = msm_cdc_pinctrl_select_active_state(
1589 pdata->mi2s_gpio_p[QUAT_MI2S]);
1590 if (ret < 0)
1591 pr_err("%s: failed to activate quat \
1592 TDM gpio set\n", __func__);
1593 }
1594 }
1595 if (tdm_i2s_switch_enable >= 0)
1596 gpio_direction_output(tdm_i2s_switch_enable, 1);
1597 break;
1598 default:
1599 pr_err("%s: dai id 0x%x not supported", __func__, cpu_dai->id);
1600 break;
1601 return -EINVAL;
1602 }
1603 return ret;
1604}
1605
1606static void msm_tdm_shutdown(struct snd_pcm_substream *substream)
1607{
1608 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1609 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1610 struct snd_soc_card *card = rtd->card;
1611 struct apq8009_asoc_mach_data *pdata =
1612 snd_soc_card_get_drvdata(card);
1613
1614 int ret = 0;
1615
1616 switch (cpu_dai->id) {
1617 case AFE_PORT_ID_PRIMARY_TDM_RX:
1618 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
1619 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
1620 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
1621 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
1622 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
1623 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
1624 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
1625 case AFE_PORT_ID_PRIMARY_TDM_TX:
1626 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
1627 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
1628 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
1629 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
1630 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
1631 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
1632 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
1633 case AFE_PORT_ID_QUATERNARY_TDM_TX:
1634 if (atomic_dec_return(&pdata->quat_ref_count) == 0) {
1635 if (pdata->mi2s_gpio_p[QUAT_MI2S]) {
1636 ret = msm_cdc_pinctrl_select_sleep_state(
1637 pdata->mi2s_gpio_p[QUAT_MI2S]);
1638 if (ret < 0) {
1639 pr_err("%s: gpio set cannot be \
1640 de-activated %s\n",
1641 __func__, "quat_tdm");
1642 return;
1643 }
1644 }
1645 }
1646 if (tdm_i2s_switch_enable >= 0)
1647 gpio_direction_output(tdm_i2s_switch_enable, 0);
1648 break;
1649 default:
1650 break;
1651 }
1652}
1653
1654static int msm_audrx_init_wcd(struct snd_soc_pcm_runtime *rtd)
1655{
1656
1657 struct snd_soc_codec *codec = rtd->codec;
1658 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
1659 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1660 struct snd_soc_component *aux_comp;
1661 struct snd_card *card;
1662 struct snd_info_entry *entry;
1663 struct apq8009_asoc_mach_data *pdata =
1664 snd_soc_card_get_drvdata(rtd->card);
1665 int ret = 0;
1666
1667 pr_debug("%s: dev_name%s\n", __func__, dev_name(cpu_dai->dev));
1668
1669 snd_soc_add_codec_controls(codec, msm_snd_controls,
1670 ARRAY_SIZE(msm_snd_controls));
1671
1672 snd_soc_dapm_new_controls(dapm, apq8009_dapm_widgets,
1673 ARRAY_SIZE(apq8009_dapm_widgets));
1674
1675 snd_soc_dapm_add_routes(dapm, wcd9335_audio_paths,
1676 ARRAY_SIZE(wcd9335_audio_paths));
1677
1678 snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
1679 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic0");
1680 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
1681 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
1682 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic3");
1683
1684 snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
1685 snd_soc_dapm_ignore_suspend(dapm, "DMIC0");
1686 snd_soc_dapm_ignore_suspend(dapm, "DMIC1");
1687 snd_soc_dapm_ignore_suspend(dapm, "DMIC2");
1688 snd_soc_dapm_ignore_suspend(dapm, "DMIC3");
1689 snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT");
1690 snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT");
1691
1692 snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_INPUT");
1693 snd_soc_dapm_ignore_suspend(dapm, "MADINPUT");
1694
1695 snd_soc_dapm_sync(dapm);
1696
1697 /* start mbhc */
1698 wcd_mbhc_cfg.calibration = def_tasha_mbhc_cal();
1699 if (wcd_mbhc_cfg.calibration)
1700 ret = tasha_mbhc_hs_detect(codec, &wcd_mbhc_cfg);
1701 else {
1702 pr_err("%s: wcd_mbhc_cfg calibration is NULL\n",
1703 __func__);
1704 return -ENOMEM;
1705 }
1706
1707 /*
1708 * Send speaker configuration only for WSA8810.
1709 * Defalut configuration is for WSA8815.
1710 */
1711
1712 pr_debug("%s: Number of aux devices: %d\n",
1713 __func__, rtd->card->num_aux_devs);
1714 if (rtd->card->num_aux_devs &&
1715 !list_empty(&rtd->card->aux_comp_list)) {
1716 aux_comp = list_first_entry(&rtd->card->aux_comp_list,
1717 struct snd_soc_component, list_aux);
1718 if (!strcmp(aux_comp->name, WSA8810_NAME_1) ||
1719 !strcmp(aux_comp->name, WSA8810_NAME_2)) {
1720 tasha_set_spkr_mode(rtd->codec, SPKR_MODE_1);
1721 tasha_set_spkr_gain_offset(rtd->codec,
1722 RX_GAIN_OFFSET_M1P5_DB);
1723 }
1724 }
1725
1726 card = rtd->card->snd_card;
1727 entry = snd_info_create_subdir(card->module, "codecs",
1728 card->proc_root);
1729 if (!entry) {
1730 pr_debug("%s: Cannot create codecs module entry\n",
1731 __func__);
1732 return 0;
1733 }
1734 pdata->codec_root = entry;
1735 tasha_codec_info_create_codec_entry(pdata->codec_root,
1736 codec);
1737
1738 return ret;
1739}
1740
1741static struct snd_soc_ops apq8009_quat_mi2s_be_ops = {
1742 .startup = msm_quat_mi2s_snd_startup,
1743 .hw_params = msm_quat_snd_hw_params,
1744 .shutdown = msm_quat_mi2s_snd_shutdown,
1745};
1746
1747static struct snd_soc_ops apq8009_mi2s_be_ops = {
1748 .startup = msm_mi2s_snd_startup,
1749 .hw_params = msm_mi2s_snd_hw_params,
1750 .shutdown = msm_mi2s_snd_shutdown,
1751};
1752
1753static struct snd_soc_ops msm_pri_auxpcm_be_ops = {
1754 .startup = msm_prim_auxpcm_startup,
1755};
1756
1757static struct snd_soc_dai_link msm_afe_rxtx_lb_be_dai_link[] = {
1758 {
1759 .name = LPASS_BE_AFE_LOOPBACK_TX,
1760 .stream_name = "AFE Loopback Capture",
1761 .cpu_dai_name = "msm-dai-q6-dev.24577",
1762 .platform_name = "msm-pcm-routing",
1763 .codec_name = "msm-stub-codec.1",
1764 .codec_dai_name = "msm-stub-tx",
1765 .no_pcm = 1,
1766 .dpcm_capture = 1,
1767 .id = MSM_BACKEND_DAI_AFE_LOOPBACK_TX,
Dhanalakshmi Siddani08ca8462019-03-04 22:50:53 +05301768 .be_hw_params_fixup = msm_afe_lb_tx_hw_params_fixup,
Raja Mallikdc60da52018-05-21 16:41:24 +05301769 .ignore_pmdown_time = 1,
1770 .ignore_suspend = 1,
1771 },
1772};
1773
1774static struct snd_soc_ops msm_tdm_be_ops = {
1775 .startup = msm_tdm_startup,
1776 .hw_params = msm_tdm_snd_hw_params,
1777 .shutdown = msm_tdm_shutdown,
1778};
1779
1780static struct snd_soc_dai_link apq8009_9326_dai[] = {
1781 /* Backend DAI Links */
1782 {
1783 .name = LPASS_BE_QUAT_MI2S_TX,
1784 .stream_name = "Quaternary MI2S Capture",
1785 .cpu_dai_name = "msm-dai-q6-mi2s.3",
1786 .platform_name = "msm-pcm-routing",
1787 .codec_name = "tasha_codec",
1788 .codec_dai_name = "tasha_i2s_tx1",
1789 .no_pcm = 1,
1790 .dpcm_capture = 1,
1791 .id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
1792 .be_hw_params_fixup = msm_tx_be_hw_params_fixup,
1793 .ops = &apq8009_quat_mi2s_be_ops,
1794 .ignore_suspend = 1,
1795 },
1796 {
1797 .name = LPASS_BE_PRI_MI2S_RX,
1798 .stream_name = "Primary MI2S Playback",
1799 .cpu_dai_name = "msm-dai-q6-mi2s.0",
1800 .platform_name = "msm-pcm-routing",
1801 .codec_name = "tasha_codec",
1802 .codec_dai_name = "tasha_i2s_rx1",
1803 .init = &msm_audrx_init_wcd,
1804 .no_pcm = 1,
1805 .dpcm_playback = 1,
1806 .id = MSM_BACKEND_DAI_PRI_MI2S_RX,
1807 .be_hw_params_fixup = msm_pri_rx_be_hw_params_fixup,
1808 .ops = &apq8009_mi2s_be_ops,
1809 .ignore_suspend = 1,
1810 },
1811 { /* FrontEnd DAI Link, CPE Service */
1812 .name = "CPE Listen service",
1813 .stream_name = "CPE Listen Audio Service",
1814 .cpu_dai_name = "CPE_LSM_NOHOST",
1815 .platform_name = "msm-cpe-lsm",
1816 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1817 SND_SOC_DPCM_TRIGGER_POST},
1818 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1819 .dpcm_capture = 1,
1820 .ignore_suspend = 1,
1821 .ignore_pmdown_time = 1,
1822 .codec_dai_name = "tasha_mad1",
1823 .codec_name = "tasha_codec",
1824 },
1825};
1826
1827/* Digital audio interface glue - connects codec <---> CPU */
1828static struct snd_soc_dai_link apq8009_dai[] = {
1829 /* FrontEnd DAI Links */
1830 {/* hw:x,0 */
1831 .name = "APQ8009 Media1",
1832 .stream_name = "MultiMedia1",
1833 .cpu_dai_name = "MultiMedia1",
1834 .platform_name = "msm-pcm-dsp.0",
1835 .dynamic = 1,
1836 .dpcm_playback = 1,
1837 .dpcm_capture = 1,
1838 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1839 SND_SOC_DPCM_TRIGGER_POST},
1840 .codec_dai_name = "snd-soc-dummy-dai",
1841 .codec_name = "snd-soc-dummy",
1842 .ignore_suspend = 1,
1843 /* this dainlink has playback support */
1844 .ignore_pmdown_time = 1,
1845 .id = MSM_FRONTEND_DAI_MULTIMEDIA1
1846 },
1847 {/* hw:x,1 */
1848 .name = "APQ8009 Media2",
1849 .stream_name = "MultiMedia2",
1850 .cpu_dai_name = "MultiMedia2",
1851 .platform_name = "msm-pcm-dsp.0",
1852 .dynamic = 1,
1853 .dpcm_playback = 1,
1854 .dpcm_capture = 1,
1855 .codec_dai_name = "snd-soc-dummy-dai",
1856 .codec_name = "snd-soc-dummy",
1857 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1858 SND_SOC_DPCM_TRIGGER_POST},
1859 .ignore_suspend = 1,
1860 /* this dainlink has playback support */
1861 .ignore_pmdown_time = 1,
1862 .id = MSM_FRONTEND_DAI_MULTIMEDIA2,
1863 },
1864 {/* hw:x,2 */
1865 .name = "Circuit-Switch Voice",
1866 .stream_name = "CS-Voice",
1867 .cpu_dai_name = "VoiceMMode1",
1868 .platform_name = "msm-pcm-voice",
1869 .dynamic = 1,
1870 .dpcm_playback = 1,
1871 .dpcm_capture = 1,
1872 .codec_dai_name = "snd-soc-dummy-dai",
1873 .codec_name = "snd-soc-dummy",
1874 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1875 SND_SOC_DPCM_TRIGGER_POST},
1876 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1877 .ignore_suspend = 1,
1878 /* this dainlink has playback support */
1879 .ignore_pmdown_time = 1,
1880 .id = MSM_FRONTEND_DAI_CS_VOICE,
1881 },
1882 {/* hw:x,3 */
1883 .name = "MSM VoIP",
1884 .stream_name = "VoIP",
1885 .cpu_dai_name = "VoIP",
1886 .platform_name = "msm-voip-dsp",
1887 .dynamic = 1,
1888 .dpcm_playback = 1,
1889 .dpcm_capture = 1,
1890 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1891 SND_SOC_DPCM_TRIGGER_POST},
1892 .codec_dai_name = "snd-soc-dummy-dai",
1893 .codec_name = "snd-soc-dummy",
1894 .ignore_suspend = 1,
1895 /* this dainlink has playback support */
1896 .ignore_pmdown_time = 1,
1897 .id = MSM_FRONTEND_DAI_VOIP,
1898 },
1899 {/* hw:x,4 */
1900 .name = "APQ8009 ULL",
1901 .stream_name = "MultiMedia3",
1902 .cpu_dai_name = "MultiMedia3",
1903 .platform_name = "msm-pcm-dsp.1",
1904 .dynamic = 1,
1905 .dpcm_playback = 1,
1906 .dpcm_capture = 1,
1907 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1908 SND_SOC_DPCM_TRIGGER_POST},
1909 .codec_dai_name = "snd-soc-dummy-dai",
1910 .codec_name = "snd-soc-dummy",
1911 .ignore_suspend = 1,
1912 /* this dainlink has playback support */
1913 .ignore_pmdown_time = 1,
1914 .id = MSM_FRONTEND_DAI_MULTIMEDIA3,
1915 },
1916 /* Hostless PCM purpose */
1917 {/* hw:x,5 */
1918 .name = "Primary MI2S_RX Hostless",
1919 .stream_name = "Primary MI2S_RX Hostless",
1920 .cpu_dai_name = "PRI_MI2S_RX_HOSTLESS",
1921 .platform_name = "msm-pcm-hostless",
1922 .dynamic = 1,
1923 .dpcm_playback = 1,
1924 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1925 SND_SOC_DPCM_TRIGGER_POST},
1926 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1927 .ignore_suspend = 1,
1928 .ignore_pmdown_time = 1,
1929 /* This dainlink has MI2S support */
1930 .codec_dai_name = "snd-soc-dummy-dai",
1931 .codec_name = "snd-soc-dummy",
1932 },
1933 {/* hw:x,6 */
1934 .name = "INT_FM Hostless",
1935 .stream_name = "INT_FM Hostless",
1936 .cpu_dai_name = "INT_FM_HOSTLESS",
1937 .platform_name = "msm-pcm-hostless",
1938 .dynamic = 1,
1939 .dpcm_capture = 1,
1940 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1941 SND_SOC_DPCM_TRIGGER_POST},
1942 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1943 .ignore_suspend = 1,
1944 /* this dainlink has playback support */
1945 .ignore_pmdown_time = 1,
1946 .codec_dai_name = "snd-soc-dummy-dai",
1947 .codec_name = "snd-soc-dummy",
1948 },
1949 {/* hw:x,7 */
1950 .name = "MSM AFE-PCM RX",
1951 .stream_name = "AFE-PROXY RX",
1952 .cpu_dai_name = "msm-dai-q6-dev.241",
1953 .codec_name = "msm-stub-codec.1",
1954 .codec_dai_name = "msm-stub-rx",
1955 .platform_name = "msm-pcm-afe",
1956 .ignore_suspend = 1,
1957 /* this dainlink has playback support */
1958 .ignore_pmdown_time = 1,
1959 },
1960 {/* hw:x,8 */
1961 .name = "MSM AFE-PCM TX",
1962 .stream_name = "AFE-PROXY TX",
1963 .cpu_dai_name = "msm-dai-q6-dev.240",
1964 .codec_name = "msm-stub-codec.1",
1965 .codec_dai_name = "msm-stub-tx",
1966 .platform_name = "msm-pcm-afe",
1967 .ignore_suspend = 1,
1968 },
1969 {/* hw:x,9 */
1970 .name = "APQ8009 Compr",
1971 .stream_name = "COMPR",
1972 .cpu_dai_name = "MultiMedia4",
1973 .platform_name = "msm-compress-dsp",
1974 .dynamic = 1,
1975 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1976 SND_SOC_DPCM_TRIGGER_POST},
1977 .codec_dai_name = "snd-soc-dummy-dai",
1978 .codec_name = "snd-soc-dummy",
1979 .ignore_suspend = 1,
1980 .ignore_pmdown_time = 1,
1981 .dpcm_playback = 1,
1982 .dpcm_capture = 1,
1983 /* this dainlink has playback support */
1984 .id = MSM_FRONTEND_DAI_MULTIMEDIA4,
1985 },
1986 {/* hw:x,10 */
1987 .name = "AUXPCM Hostless",
1988 .stream_name = "AUXPCM Hostless",
1989 .cpu_dai_name = "AUXPCM_HOSTLESS",
1990 .platform_name = "msm-pcm-hostless",
1991 .dynamic = 1,
1992 .dpcm_playback = 1,
1993 .dpcm_capture = 1,
1994 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1995 SND_SOC_DPCM_TRIGGER_POST},
1996 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1997 .ignore_suspend = 1,
1998 /* this dainlink has playback support */
1999 .ignore_pmdown_time = 1,
2000 .codec_dai_name = "snd-soc-dummy-dai",
2001 .codec_name = "snd-soc-dummy",
2002 },
2003 {/* hw:x,11 */
2004 .name = "Tertiary MI2S_TX Hostless",
2005 .stream_name = "Tertiary MI2S_TX Hostless",
2006 .cpu_dai_name = "TERT_MI2S_TX_HOSTLESS",
2007 .platform_name = "msm-pcm-hostless",
2008 .dynamic = 1,
2009 .dpcm_capture = 1,
2010 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2011 SND_SOC_DPCM_TRIGGER_POST},
2012 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2013 .ignore_suspend = 1,
2014 .ignore_pmdown_time = 1, /* dai link has playback support */
2015 .codec_dai_name = "snd-soc-dummy-dai",
2016 .codec_name = "snd-soc-dummy",
2017 },
2018 {/* hw:x,12 */
2019 .name = "APQ8009 LowLatency",
2020 .stream_name = "MultiMedia5",
2021 .cpu_dai_name = "MultiMedia5",
2022 .platform_name = "msm-pcm-dsp.1",
2023 .dynamic = 1,
2024 .dpcm_playback = 1,
2025 .dpcm_capture = 1,
2026 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
2027 ASYNC_DPCM_SND_SOC_HW_PARAMS,
2028 .codec_dai_name = "snd-soc-dummy-dai",
2029 .codec_name = "snd-soc-dummy",
2030 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2031 SND_SOC_DPCM_TRIGGER_POST},
2032 .ignore_suspend = 1,
2033 /* this dainlink has playback support */
2034 .ignore_pmdown_time = 1,
2035 .id = MSM_FRONTEND_DAI_MULTIMEDIA5,
2036 },
2037 {/* hw:x,13 */
2038 .name = "Voice2",
2039 .stream_name = "Voice2",
2040 .cpu_dai_name = "VoiceMMode1",
2041 .platform_name = "msm-pcm-voice",
2042 .dynamic = 1,
2043 .dpcm_playback = 1,
2044 .dpcm_capture = 1,
2045 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2046 SND_SOC_DPCM_TRIGGER_POST},
2047 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2048 .ignore_suspend = 1,
2049 /* this dainlink has playback support */
2050 .ignore_pmdown_time = 1,
2051 .codec_dai_name = "snd-soc-dummy-dai",
2052 .codec_name = "snd-soc-dummy",
2053 .id = MSM_FRONTEND_DAI_VOICE2,
2054 },
2055 {/* hw:x,14 */
2056 .name = "APQ8009 Media9",
2057 .stream_name = "MultiMedia9",
2058 .cpu_dai_name = "MultiMedia9",
2059 .platform_name = "msm-pcm-dsp.0",
2060 .dynamic = 1,
2061 .dpcm_playback = 1,
2062 .dpcm_capture = 1,
2063 .codec_dai_name = "snd-soc-dummy-dai",
2064 .codec_name = "snd-soc-dummy",
2065 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2066 SND_SOC_DPCM_TRIGGER_POST},
2067 .ignore_suspend = 1,
2068 /* This dailink has playback support */
2069 .ignore_pmdown_time = 1,
2070 .id = MSM_FRONTEND_DAI_MULTIMEDIA9,
2071 },
2072 { /* hw:x,15 */
2073 .name = "VoLTE",
2074 .stream_name = "VoLTE",
2075 .cpu_dai_name = "VoiceMMode1",
2076 .platform_name = "msm-pcm-voice",
2077 .dynamic = 1,
2078 .dpcm_playback = 1,
2079 .dpcm_capture = 1,
2080 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2081 SND_SOC_DPCM_TRIGGER_POST},
2082 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2083 .ignore_suspend = 1,
2084 /* this dainlink has playback support */
2085 .ignore_pmdown_time = 1,
2086 .codec_dai_name = "snd-soc-dummy-dai",
2087 .codec_name = "snd-soc-dummy",
2088 .id = MSM_FRONTEND_DAI_VOLTE,
2089 },
2090 { /* hw:x,16 */
2091 .name = "VoWLAN",
2092 .stream_name = "VoWLAN",
2093 .cpu_dai_name = "VoiceMMode1",
2094 .platform_name = "msm-pcm-voice",
2095 .dynamic = 1,
2096 .dpcm_playback = 1,
2097 .dpcm_capture = 1,
2098 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2099 SND_SOC_DPCM_TRIGGER_POST},
2100 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2101 .ignore_suspend = 1,
2102 .ignore_pmdown_time = 1,
2103 .codec_dai_name = "snd-soc-dummy-dai",
2104 .codec_name = "snd-soc-dummy",
2105 .id = MSM_FRONTEND_DAI_VOWLAN,
2106 },
2107 {/* hw:x,17 */
2108 .name = "INT_HFP_BT Hostless",
2109 .stream_name = "INT_HFP_BT Hostless",
2110 .cpu_dai_name = "INT_HFP_BT_HOSTLESS",
2111 .platform_name = "msm-pcm-hostless",
2112 .dynamic = 1,
2113 .dpcm_playback = 1,
2114 .dpcm_capture = 1,
2115 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2116 SND_SOC_DPCM_TRIGGER_POST},
2117 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2118 .ignore_suspend = 1,
2119 /* this dai link has playback support */
2120 .ignore_pmdown_time = 1,
2121 .codec_dai_name = "snd-soc-dummy-dai",
2122 .codec_name = "snd-soc-dummy",
2123 },
2124 {/* hw:x,18 */
2125 .name = "APQ8009 HFP TX",
2126 .stream_name = "MultiMedia6",
2127 .cpu_dai_name = "MultiMedia6",
2128 .platform_name = "msm-pcm-loopback",
2129 .dynamic = 1,
2130 .dpcm_playback = 1,
2131 .dpcm_capture = 1,
2132 .codec_dai_name = "snd-soc-dummy-dai",
2133 .codec_name = "snd-soc-dummy",
2134 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2135 SND_SOC_DPCM_TRIGGER_POST},
2136 .ignore_suspend = 1,
2137 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2138 /* this dai link has playback support */
2139 .ignore_pmdown_time = 1,
2140 .id = MSM_FRONTEND_DAI_MULTIMEDIA6,
2141 },
2142 /* LSM FE */
2143 {/* hw:x,19 */
2144 .name = "Listen 1 Audio Service",
2145 .stream_name = "Listen 1 Audio Service",
2146 .cpu_dai_name = "LSM1",
2147 .platform_name = "msm-lsm-client",
2148 .dynamic = 1,
2149 .dpcm_capture = 1,
2150 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2151 SND_SOC_DPCM_TRIGGER_POST },
2152 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2153 .ignore_suspend = 1,
2154 .ignore_pmdown_time = 1,
2155 .codec_dai_name = "snd-soc-dummy-dai",
2156 .codec_name = "snd-soc-dummy",
2157 .id = MSM_FRONTEND_DAI_LSM1,
2158 },
2159 {/* hw:x,20 */
2160 .name = "Listen 2 Audio Service",
2161 .stream_name = "Listen 2 Audio Service",
2162 .cpu_dai_name = "LSM2",
2163 .platform_name = "msm-lsm-client",
2164 .dynamic = 1,
2165 .dpcm_capture = 1,
2166 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2167 SND_SOC_DPCM_TRIGGER_POST },
2168 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2169 .ignore_suspend = 1,
2170 .ignore_pmdown_time = 1,
2171 .codec_dai_name = "snd-soc-dummy-dai",
2172 .codec_name = "snd-soc-dummy",
2173 .id = MSM_FRONTEND_DAI_LSM2,
2174 },
2175 {/* hw:x,21 */
2176 .name = "Listen 3 Audio Service",
2177 .stream_name = "Listen 3 Audio Service",
2178 .cpu_dai_name = "LSM3",
2179 .platform_name = "msm-lsm-client",
2180 .dynamic = 1,
2181 .dpcm_capture = 1,
2182 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2183 SND_SOC_DPCM_TRIGGER_POST },
2184 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2185 .ignore_suspend = 1,
2186 .ignore_pmdown_time = 1,
2187 .codec_dai_name = "snd-soc-dummy-dai",
2188 .codec_name = "snd-soc-dummy",
2189 .id = MSM_FRONTEND_DAI_LSM3,
2190 },
2191 {/* hw:x,22 */
2192 .name = "Listen 4 Audio Service",
2193 .stream_name = "Listen 4 Audio Service",
2194 .cpu_dai_name = "LSM4",
2195 .platform_name = "msm-lsm-client",
2196 .dynamic = 1,
2197 .dpcm_capture = 1,
2198 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2199 SND_SOC_DPCM_TRIGGER_POST },
2200 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2201 .ignore_suspend = 1,
2202 .ignore_pmdown_time = 1,
2203 .codec_dai_name = "snd-soc-dummy-dai",
2204 .codec_name = "snd-soc-dummy",
2205 .id = MSM_FRONTEND_DAI_LSM4,
2206 },
2207 {/* hw:x,23 */
2208 .name = "Listen 5 Audio Service",
2209 .stream_name = "Listen 5 Audio Service",
2210 .cpu_dai_name = "LSM5",
2211 .platform_name = "msm-lsm-client",
2212 .dynamic = 1,
2213 .dpcm_capture = 1,
2214 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2215 SND_SOC_DPCM_TRIGGER_POST },
2216 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2217 .ignore_suspend = 1,
2218 .ignore_pmdown_time = 1,
2219 .codec_dai_name = "snd-soc-dummy-dai",
2220 .codec_name = "snd-soc-dummy",
2221 .id = MSM_FRONTEND_DAI_LSM5,
2222 },
2223 { /* hw:x,24 */
2224 .name = "APQ8009 Compress2",
2225 .stream_name = "Compress2",
2226 .cpu_dai_name = "MultiMedia7",
2227 .platform_name = "msm-compress-dsp",
2228 .dynamic = 1,
2229 .dpcm_playback = 1,
2230 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2231 SND_SOC_DPCM_TRIGGER_POST},
2232 .codec_dai_name = "snd-soc-dummy-dai",
2233 .codec_name = "snd-soc-dummy",
2234 .ignore_suspend = 1,
2235 .ignore_pmdown_time = 1,
2236 /* this dainlink has playback support */
2237 .id = MSM_FRONTEND_DAI_MULTIMEDIA7,
2238 },
2239 { /* hw:x,25 */
2240 .name = "QUAT_MI2S Hostless",
2241 .stream_name = "QUAT_MI2S Hostless",
2242 .cpu_dai_name = "QUAT_MI2S_RX_HOSTLESS",
2243 .platform_name = "msm-pcm-hostless",
2244 .dynamic = 1,
2245 .dpcm_playback = 1,
2246 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2247 SND_SOC_DPCM_TRIGGER_POST},
2248 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2249 .ignore_suspend = 1,
2250 /* this dainlink has playback support */
2251 .ignore_pmdown_time = 1,
2252 .codec_dai_name = "snd-soc-dummy-dai",
2253 .codec_name = "snd-soc-dummy",
2254 },
2255 { /* hw:x, 26 */
2256 .name = "QCHAT",
2257 .stream_name = "QCHAT",
2258 .cpu_dai_name = "QCHAT",
2259 .platform_name = "msm-pcm-voice",
2260 .dynamic = 1,
2261 .dpcm_playback = 1,
2262 .dpcm_capture = 1,
2263 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2264 SND_SOC_DPCM_TRIGGER_POST},
2265 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2266 .ignore_suspend = 1,
2267 /* this dainlink has playback support */
2268 .ignore_pmdown_time = 1,
2269 .codec_dai_name = "snd-soc-dummy-dai",
2270 .codec_name = "snd-soc-dummy",
2271 .id = MSM_FRONTEND_DAI_QCHAT,
2272 },
2273 /* Primary AUX PCM Backend DAI Links */
2274 {
2275 .name = LPASS_BE_AUXPCM_RX,
2276 .stream_name = "AUX PCM Playback",
2277 .cpu_dai_name = "msm-dai-q6-auxpcm.1",
2278 .platform_name = "msm-pcm-routing",
2279 .codec_name = "msm-stub-codec.1",
2280 .codec_dai_name = "msm-stub-rx",
2281 .no_pcm = 1,
2282 .dpcm_playback = 1,
2283 .id = MSM_BACKEND_DAI_AUXPCM_RX,
2284 .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
2285 .ops = &msm_pri_auxpcm_be_ops,
2286 .ignore_pmdown_time = 1,
2287 .ignore_suspend = 1,
2288 },
2289 {
2290 .name = LPASS_BE_AUXPCM_TX,
2291 .stream_name = "AUX PCM Capture",
2292 .cpu_dai_name = "msm-dai-q6-auxpcm.1",
2293 .platform_name = "msm-pcm-routing",
2294 .codec_name = "msm-stub-codec.1",
2295 .codec_dai_name = "msm-stub-tx",
2296 .no_pcm = 1,
2297 .dpcm_capture = 1,
2298 .id = MSM_BACKEND_DAI_AUXPCM_TX,
2299 .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
2300 .ops = &msm_pri_auxpcm_be_ops,
2301 .ignore_suspend = 1,
2302 },
2303 {
2304 .name = LPASS_BE_INT_BT_SCO_RX,
2305 .stream_name = "Internal BT-SCO Playback",
2306 .cpu_dai_name = "msm-dai-q6-dev.12288",
2307 .platform_name = "msm-pcm-routing",
2308 .codec_name = "msm-stub-codec.1",
2309 .codec_dai_name = "msm-stub-rx",
2310 .no_pcm = 1,
2311 .dpcm_playback = 1,
2312 .id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
2313 .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
2314 /* this dainlink has playback support */
2315 .ignore_pmdown_time = 1,
2316 .ignore_suspend = 1,
2317 },
2318 {
2319 .name = LPASS_BE_INT_BT_SCO_TX,
2320 .stream_name = "Internal BT-SCO Capture",
2321 .cpu_dai_name = "msm-dai-q6-dev.12289",
2322 .platform_name = "msm-pcm-routing",
2323 .codec_name = "msm-stub-codec.1",
2324 .codec_dai_name = "msm-stub-tx",
2325 .no_pcm = 1,
2326 .dpcm_capture = 1,
2327 .id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
2328 .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
2329 .ignore_suspend = 1,
2330 },
2331 {
2332 .name = LPASS_BE_INT_FM_RX,
2333 .stream_name = "Internal FM Playback",
2334 .cpu_dai_name = "msm-dai-q6-dev.12292",
2335 .platform_name = "msm-pcm-routing",
2336 .codec_name = "msm-stub-codec.1",
2337 .codec_dai_name = "msm-stub-rx",
2338 .no_pcm = 1,
2339 .dpcm_playback = 1,
2340 .id = MSM_BACKEND_DAI_INT_FM_RX,
2341 .be_hw_params_fixup = msm_be_hw_params_fixup,
2342 /* this dainlink has playback support */
2343 .ignore_pmdown_time = 1,
2344 .ignore_suspend = 1,
2345 },
2346 {
2347 .name = LPASS_BE_INT_FM_TX,
2348 .stream_name = "Internal FM Capture",
2349 .cpu_dai_name = "msm-dai-q6-dev.12293",
2350 .platform_name = "msm-pcm-routing",
2351 .codec_name = "msm-stub-codec.1",
2352 .codec_dai_name = "msm-stub-tx",
2353 .no_pcm = 1,
2354 .dpcm_capture = 1,
2355 .id = MSM_BACKEND_DAI_INT_FM_TX,
2356 .be_hw_params_fixup = msm_be_hw_params_fixup,
2357 .ignore_suspend = 1,
2358 },
2359 {
2360 .name = LPASS_BE_AFE_PCM_RX,
2361 .stream_name = "AFE Playback",
2362 .cpu_dai_name = "msm-dai-q6-dev.224",
2363 .platform_name = "msm-pcm-routing",
2364 .codec_name = "msm-stub-codec.1",
2365 .codec_dai_name = "msm-stub-rx",
2366 .no_pcm = 1,
2367 .dpcm_playback = 1,
2368 .id = MSM_BACKEND_DAI_AFE_PCM_RX,
2369 .be_hw_params_fixup = msm_proxy_rx_be_hw_params_fixup,
2370 /* this dainlink has playback support */
2371 .ignore_pmdown_time = 1,
2372 .ignore_suspend = 1,
2373 },
2374 {
2375 .name = LPASS_BE_AFE_PCM_TX,
2376 .stream_name = "AFE Capture",
2377 .cpu_dai_name = "msm-dai-q6-dev.225",
2378 .platform_name = "msm-pcm-routing",
2379 .codec_name = "msm-stub-codec.1",
2380 .codec_dai_name = "msm-stub-tx",
2381 .no_pcm = 1,
2382 .dpcm_capture = 1,
2383 .id = MSM_BACKEND_DAI_AFE_PCM_TX,
2384 .be_hw_params_fixup = msm_proxy_tx_be_hw_params_fixup,
2385 .ignore_suspend = 1,
2386 },
2387 /* Incall Record Uplink BACK END DAI Link */
2388 {
2389 .name = LPASS_BE_INCALL_RECORD_TX,
2390 .stream_name = "Voice Uplink Capture",
2391 .cpu_dai_name = "msm-dai-q6-dev.32772",
2392 .platform_name = "msm-pcm-routing",
2393 .codec_name = "msm-stub-codec.1",
2394 .codec_dai_name = "msm-stub-tx",
2395 .no_pcm = 1,
2396 .dpcm_capture = 1,
2397 .id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
2398 .be_hw_params_fixup = msm_be_hw_params_fixup,
2399 .ignore_suspend = 1,
2400 },
2401 /* Incall Record Downlink BACK END DAI Link */
2402 {
2403 .name = LPASS_BE_INCALL_RECORD_RX,
2404 .stream_name = "Voice Downlink Capture",
2405 .cpu_dai_name = "msm-dai-q6-dev.32771",
2406 .platform_name = "msm-pcm-routing",
2407 .codec_name = "msm-stub-codec.1",
2408 .codec_dai_name = "msm-stub-tx",
2409 .no_pcm = 1,
2410 .dpcm_capture = 1,
2411 .id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
2412 .be_hw_params_fixup = msm_be_hw_params_fixup,
2413 .ignore_suspend = 1,
2414 },
2415 /* Incall Music BACK END DAI Link */
2416 {
2417 .name = LPASS_BE_VOICE_PLAYBACK_TX,
2418 .stream_name = "Voice Farend Playback",
2419 .cpu_dai_name = "msm-dai-q6-dev.32773",
2420 .platform_name = "msm-pcm-routing",
2421 .codec_name = "msm-stub-codec.1",
2422 .codec_dai_name = "msm-stub-rx",
2423 .no_pcm = 1,
2424 .dpcm_playback = 1,
2425 .id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
2426 .be_hw_params_fixup = msm_be_hw_params_fixup,
2427 .ignore_suspend = 1,
2428 },
2429 /* Incall Music 2 BACK END DAI Link */
2430 {
2431 .name = LPASS_BE_VOICE2_PLAYBACK_TX,
2432 .stream_name = "Voice2 Farend Playback",
2433 .cpu_dai_name = "msm-dai-q6-dev.32770",
2434 .platform_name = "msm-pcm-routing",
2435 .codec_name = "msm-stub-codec.1",
2436 .codec_dai_name = "msm-stub-rx",
2437 .no_pcm = 1,
2438 .dpcm_playback = 1,
2439 .id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
2440 .be_hw_params_fixup = msm_be_hw_params_fixup,
2441 .ignore_suspend = 1,
2442 },
2443};
2444
2445static struct snd_soc_dai_link msm_tdm_fe_dai[] = {
2446 /* FE TDM DAI links */
2447 {
2448 .name = "Primary TDM RX 0 Hostless",
2449 .stream_name = "Primary TDM RX 0 Hostless",
2450 .cpu_dai_name = "PRI_TDM_RX_0_HOSTLESS",
2451 .platform_name = "msm-pcm-hostless",
2452 .dynamic = 1,
2453 .dpcm_playback = 1,
2454 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2455 SND_SOC_DPCM_TRIGGER_POST},
2456 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2457 .ignore_suspend = 1,
2458 .ignore_pmdown_time = 1,
2459 .codec_dai_name = "snd-soc-dummy-dai",
2460 .codec_name = "snd-soc-dummy",
2461 },
2462 {
2463 .name = "Primary TDM TX 0 Hostless",
2464 .stream_name = "Primary TDM TX 0 Hostless",
2465 .cpu_dai_name = "PRI_TDM_TX_0_HOSTLESS",
2466 .platform_name = "msm-pcm-hostless",
2467 .dynamic = 1,
2468 .dpcm_capture = 1,
2469 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2470 SND_SOC_DPCM_TRIGGER_POST},
2471 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2472 .ignore_suspend = 1,
2473 .ignore_pmdown_time = 1,
2474 .codec_dai_name = "snd-soc-dummy-dai",
2475 .codec_name = "snd-soc-dummy",
2476 },
2477 {
2478 .name = "Secondary TDM RX 0 Hostless",
2479 .stream_name = "Secondary TDM RX 0 Hostless",
2480 .cpu_dai_name = "SEC_TDM_RX_0_HOSTLESS",
2481 .platform_name = "msm-pcm-hostless",
2482 .dynamic = 1,
2483 .dpcm_playback = 1,
2484 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2485 SND_SOC_DPCM_TRIGGER_POST},
2486 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2487 .ignore_suspend = 1,
2488 .ignore_pmdown_time = 1,
2489 .codec_dai_name = "snd-soc-dummy-dai",
2490 .codec_name = "snd-soc-dummy",
2491 },
2492 {
2493 .name = "Secondary TDM TX 0 Hostless",
2494 .stream_name = "Secondary TDM TX 0 Hostless",
2495 .cpu_dai_name = "SEC_TDM_TX_0_HOSTLESS",
2496 .platform_name = "msm-pcm-hostless",
2497 .dynamic = 1,
2498 .dpcm_capture = 1,
2499 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2500 SND_SOC_DPCM_TRIGGER_POST},
2501 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2502 .ignore_suspend = 1,
2503 .ignore_pmdown_time = 1,
2504 .codec_dai_name = "snd-soc-dummy-dai",
2505 .codec_name = "snd-soc-dummy",
2506 },
2507};
2508
2509static struct snd_soc_dai_link msm_tdm_be_dai[] = {
2510 /* TDM be dai links */
2511 {
2512 .name = LPASS_BE_PRI_TDM_RX_0,
2513 .stream_name = "Primary TDM0 Playback",
2514 .cpu_dai_name = "msm-dai-q6-tdm.36864",
2515 .platform_name = "msm-pcm-routing",
2516 .codec_name = "msm-stub-codec.1",
2517 .codec_dai_name = "msm-stub-rx",
2518 .no_pcm = 1,
2519 .dpcm_playback = 1,
2520 .id = MSM_BACKEND_DAI_PRI_TDM_RX_0,
2521 .be_hw_params_fixup = msm_tdm_be_hw_params_fixup,
2522 .ops = &msm_tdm_be_ops,
2523 .ignore_suspend = 1,
2524 },
2525 {
2526 .name = LPASS_BE_PRI_TDM_TX_0,
2527 .stream_name = "Primary TDM0 Capture",
2528 .cpu_dai_name = "msm-dai-q6-tdm.36865",
2529 .platform_name = "msm-pcm-routing",
2530 .codec_name = "msm-stub-codec.1",
2531 .codec_dai_name = "msm-stub-tx",
2532 .no_pcm = 1,
2533 .dpcm_capture = 1,
2534 .id = MSM_BACKEND_DAI_PRI_TDM_TX_0,
2535 .be_hw_params_fixup = msm_tdm_be_hw_params_fixup,
2536 .ops = &msm_tdm_be_ops,
2537 .ignore_suspend = 1,
2538 },
2539};
2540
2541static struct snd_soc_dai_link apq8009_9326_dai_links[
2542 ARRAY_SIZE(apq8009_dai) +
2543 ARRAY_SIZE(msm_tdm_fe_dai) +
2544 ARRAY_SIZE(apq8009_9326_dai) +
2545 ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link) +
2546 ARRAY_SIZE(msm_tdm_be_dai)];
2547
2548static struct snd_soc_card snd_soc_card_9326_apq8009 = {
2549 .name = "apq8009-tashalite-snd-card-tdm",
2550};
2551
2552struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
2553{
2554 struct snd_soc_card *card = &snd_soc_card_9326_apq8009;
2555 int ret, len1, len2, len3;
2556
2557 card->dev = dev;
2558 ret = snd_soc_of_parse_card_name(card, "qcom,model");
2559 if (ret) {
2560 dev_err(dev, "%s: parse card name failed, err:%d\n",
2561 __func__, ret);
2562 return NULL;
2563 }
2564 pr_debug("%s: CARD is %s\n", __func__, card->name);
2565
2566 len1 = ARRAY_SIZE(apq8009_dai);
2567 len2 = len1 + ARRAY_SIZE(msm_tdm_fe_dai);
2568 len3 = len2 + ARRAY_SIZE(apq8009_9326_dai);
2569
2570 memcpy(apq8009_9326_dai_links, apq8009_dai,
2571 sizeof(apq8009_dai));
2572 memcpy(apq8009_9326_dai_links + len1, msm_tdm_fe_dai,
2573 sizeof(msm_tdm_fe_dai));
2574 memcpy(apq8009_9326_dai_links + len2, apq8009_9326_dai,
2575 sizeof(apq8009_9326_dai));
2576
2577 if (of_property_read_bool(dev->of_node, "qcom,afe-rxtx-lb")) {
2578 dev_dbg(dev, "%s(): AFE RX to TX loopback supported\n",
2579 __func__);
2580 memcpy(apq8009_9326_dai_links + len3,
2581 msm_afe_rxtx_lb_be_dai_link,
2582 sizeof(msm_afe_rxtx_lb_be_dai_link));
2583 len3 += ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link);
2584 }
2585
2586 if (of_property_read_bool(dev->of_node, "qcom,tdm-audio-intf")) {
2587 dev_dbg(dev, "%s(): TDM support present\n",
2588 __func__);
2589 memcpy(apq8009_9326_dai_links + len3, msm_tdm_be_dai,
2590 sizeof(msm_tdm_be_dai));
2591 len3 += ARRAY_SIZE(msm_tdm_be_dai);
2592 }
2593
2594 card->dai_link = apq8009_9326_dai_links;
2595 card->num_links = len3;
2596 card->dev = dev;
2597
2598 return card;
2599}
2600
2601static int apq8009_init_wsa_dev(struct platform_device *pdev,
2602 struct snd_soc_card *card)
2603{
2604 struct device_node *wsa_of_node;
2605 u32 wsa_max_devs;
2606 u32 wsa_dev_cnt;
2607 char *dev_name_str = NULL;
2608 struct apq8009_wsa881x_dev_info *wsa881x_dev_info;
2609 const char *wsa_auxdev_name_prefix[1];
2610 int found = 0;
2611 int i;
2612 int ret = 0;
2613
2614 /* Get maximum WSA device count for this platform */
2615 ret = of_property_read_u32(pdev->dev.of_node,
2616 "qcom,wsa-max-devs", &wsa_max_devs);
2617 if (ret) {
2618 dev_dbg(&pdev->dev,
2619 "%s: wsa-max-devs property missing in DT %s, ret = %d\n",
2620 __func__, pdev->dev.of_node->full_name, ret);
2621 card->num_aux_devs = 0;
2622 return 0;
2623 }
2624 if (wsa_max_devs == 0) {
2625 dev_warn(&pdev->dev,
2626 "%s: Max WSA devices is 0 for this target?\n",
2627 __func__);
2628 card->num_aux_devs = 0;
2629 return 0;
2630 }
2631
2632 /* Get count of WSA device phandles for this platform */
2633 wsa_dev_cnt = of_count_phandle_with_args(pdev->dev.of_node,
2634 "qcom,wsa-devs", NULL);
2635 if (wsa_dev_cnt == -ENOENT) {
2636 dev_warn(&pdev->dev, "%s: No wsa device defined in DT.\n",
2637 __func__);
2638 return 0;
2639 } else if (wsa_dev_cnt <= 0) {
2640 dev_err(&pdev->dev,
2641 "%s: Error reading wsa device from DT. wsa_dev_cnt = %d\n",
2642 __func__, wsa_dev_cnt);
2643 return -EINVAL;
2644 }
2645
2646 /*
2647 * Expect total phandles count to be NOT less than maximum possible
2648 * WSA count. However, if it is less, then assign same value to
2649 * max count as well.
2650 */
2651
2652 if (wsa_dev_cnt < wsa_max_devs) {
2653 dev_dbg(&pdev->dev,
2654 "%s: wsa_max_devs = %d cannot exceed wsa_dev_cnt = %d\n",
2655 __func__, wsa_max_devs, wsa_dev_cnt);
2656 wsa_max_devs = wsa_dev_cnt;
2657 }
2658
2659 /* Make sure prefix string passed for each WSA device */
2660 ret = of_property_count_strings(pdev->dev.of_node,
2661 "qcom,wsa-aux-dev-prefix");
2662 if (ret != wsa_dev_cnt) {
2663 dev_err(&pdev->dev,
2664 "%s: expecting %d wsa prefix. Defined only %d in DT\n",
2665 __func__, wsa_dev_cnt, ret);
2666 return -EINVAL;
2667 }
2668
2669 /*
2670 * Alloc mem to store phandle and index info of WSA device, if already
2671 * registered with ALSA core
2672 */
2673 wsa881x_dev_info = devm_kcalloc(&pdev->dev, wsa_max_devs,
2674 sizeof(struct apq8009_wsa881x_dev_info),
2675 GFP_KERNEL);
2676 if (!wsa881x_dev_info)
2677 return -ENOMEM;
2678
2679 /*
2680 * search and check whether all WSA devices are already
2681 * registered with ALSA core or not. If found a node, store
2682 * the node and the index in a local array of struct for later
2683 * use.
2684 */
2685 for (i = 0; i < wsa_dev_cnt; i++) {
2686 wsa_of_node = of_parse_phandle(pdev->dev.of_node,
2687 "qcom,wsa-devs", i);
2688 if (unlikely(!wsa_of_node)) {
2689 /* we should not be here */
2690 dev_err(&pdev->dev,
2691 "%s: wsa dev node is not present\n",
2692 __func__);
2693 return -EINVAL;
2694 }
2695 if (soc_find_component(wsa_of_node, NULL)) {
2696 /* WSA device registered with ALSA core */
2697 wsa881x_dev_info[found].of_node = wsa_of_node;
2698 wsa881x_dev_info[found].index = i;
2699 found++;
2700 if (found == wsa_max_devs)
2701 break;
2702 }
2703 }
2704
2705 if (found < wsa_max_devs) {
2706 dev_dbg(&pdev->dev,
2707 "%s: failed to find %d components. Found only %d\n",
2708 __func__, wsa_max_devs, found);
2709 return -EPROBE_DEFER;
2710 }
2711 dev_err(&pdev->dev,
2712 "%s: found %d wsa881x devices registered with ALSA core\n",
2713 __func__, found);
2714
2715 card->num_aux_devs = wsa_max_devs;
2716 card->num_configs = wsa_max_devs;
2717
2718 /* Alloc array of AUX devs struct */
2719 apq8009_aux_dev = devm_kcalloc(&pdev->dev, card->num_aux_devs,
2720 sizeof(struct snd_soc_aux_dev),
2721 GFP_KERNEL);
2722 if (!apq8009_aux_dev)
2723 return -ENOMEM;
2724
2725 /* Alloc array of codec conf struct */
2726 apq8009_codec_conf = devm_kcalloc(&pdev->dev, card->num_aux_devs,
2727 sizeof(struct snd_soc_codec_conf),
2728 GFP_KERNEL);
2729 if (!apq8009_codec_conf)
2730 return -ENOMEM;
2731
2732 for (i = 0; i < card->num_aux_devs; i++) {
2733 dev_name_str = devm_kzalloc(&pdev->dev, DEV_NAME_STR_LEN,
2734 GFP_KERNEL);
2735 if (!dev_name_str)
2736 return -ENOMEM;
2737
2738 ret = of_property_read_string_index(pdev->dev.of_node,
2739 "qcom,wsa-aux-dev-prefix",
2740 wsa881x_dev_info[i].index,
2741 wsa_auxdev_name_prefix);
2742 if (ret) {
2743 dev_err(&pdev->dev,
2744 "%s: failed to read wsa aux dev prefix, ret = %d\n",
2745 __func__, ret);
2746 return -EINVAL;
2747 }
2748
2749 snprintf(dev_name_str, strlen("wsa881x.%d"), "wsa881x.%d", i);
2750 apq8009_aux_dev[i].name = dev_name_str;
2751 apq8009_aux_dev[i].codec_name = NULL;
2752 apq8009_aux_dev[i].codec_of_node =
2753 wsa881x_dev_info[i].of_node;
2754 apq8009_aux_dev[i].init = apq8009_wsa881x_init;
2755 apq8009_codec_conf[i].dev_name = NULL;
2756 apq8009_codec_conf[i].name_prefix = wsa_auxdev_name_prefix[0];
2757 apq8009_codec_conf[i].of_node =
2758 wsa881x_dev_info[i].of_node;
2759 }
2760 card->codec_conf = apq8009_codec_conf;
2761 card->aux_dev = apq8009_aux_dev;
2762
2763 return 0;
2764}
2765
2766static int apq8009_populate_dai_link_component_of_node(
2767 struct snd_soc_card *card)
2768{
2769 int i, index, ret = 0;
2770 struct device *cdev = card->dev;
2771 struct snd_soc_dai_link *dai_link = card->dai_link;
2772 struct device_node *phandle;
2773
2774 if (!cdev) {
2775 pr_err("%s: Sound card device memory NULL\n", __func__);
2776 return -ENODEV;
2777 }
2778
2779 for (i = 0; i < card->num_links; i++) {
2780 if (dai_link[i].platform_of_node && dai_link[i].cpu_of_node)
2781 continue;
2782
2783 /* populate platform_of_node for snd card dai links */
2784 if (dai_link[i].platform_name &&
2785 !dai_link[i].platform_of_node) {
2786 index = of_property_match_string(cdev->of_node,
2787 "asoc-platform-names",
2788 dai_link[i].platform_name);
2789 if (index < 0) {
2790 pr_err("%s: No match found for platform\n"
2791 "name: %s\n", __func__,
2792 dai_link[i].platform_name);
2793 ret = index;
2794 goto cpu_dai;
2795 }
2796 phandle = of_parse_phandle(cdev->of_node,
2797 "asoc-platform",
2798 index);
2799 if (!phandle) {
2800 pr_err("%s: retrieving phandle for platform %s, index %d failed\n",
2801 __func__, dai_link[i].platform_name,
2802 index);
2803 ret = -ENODEV;
2804 goto err;
2805 }
2806 dai_link[i].platform_of_node = phandle;
2807 dai_link[i].platform_name = NULL;
2808 }
2809cpu_dai:
2810 /* populate cpu_of_node for snd card dai links */
2811 if (dai_link[i].cpu_dai_name && !dai_link[i].cpu_of_node) {
2812 index = of_property_match_string(cdev->of_node,
2813 "asoc-cpu-names",
2814 dai_link[i].cpu_dai_name);
2815 if (index < 0)
2816 goto codec_dai;
2817 phandle = of_parse_phandle(cdev->of_node, "asoc-cpu",
2818 index);
2819 if (!phandle) {
2820 pr_err("%s: retrieving phandle for cpu dai %s failed\n",
2821 __func__, dai_link[i].cpu_dai_name);
2822 ret = -ENODEV;
2823 goto err;
2824 }
2825 dai_link[i].cpu_of_node = phandle;
2826 dai_link[i].cpu_dai_name = NULL;
2827 }
2828codec_dai:
2829 /* populate codec_of_node for snd card dai links */
2830 if (dai_link[i].codec_name && !dai_link[i].codec_of_node) {
2831 index = of_property_match_string(cdev->of_node,
2832 "asoc-codec-names",
2833 dai_link[i].codec_name);
2834 if (index < 0)
2835 continue;
2836 phandle = of_parse_phandle(cdev->of_node, "asoc-codec",
2837 index);
2838 if (!phandle) {
2839 pr_err("%s: retrieving phandle for codec dai %s failed\n",
2840 __func__, dai_link[i].codec_name);
2841 ret = -ENODEV;
2842 goto err;
2843 }
2844 dai_link[i].codec_of_node = phandle;
2845 dai_link[i].codec_name = NULL;
2846 }
2847 }
2848err:
2849 return ret;
2850}
2851
2852static const struct of_device_id apq8009_asoc_machine_of_match[] = {
2853 { .compatible = "qcom,apq8009-audio-i2s-codec",
2854 .data = "tasha_codec"},
2855 {},
2856};
2857
2858static int apq8009_asoc_machine_probe(struct platform_device *pdev)
2859{
2860 struct snd_soc_card *card = NULL;
2861 struct apq8009_asoc_mach_data *pdata = NULL;
2862 const char *hs_micbias_type = "qcom,msm-hs-micbias-type";
2863 const char *mclk = "qcom,msm-mclk-freq";
2864 const struct of_device_id *match;
2865 const char *type = NULL;
2866 int ret = 0, id = 0;
2867
2868 pdata = devm_kzalloc(&pdev->dev,
2869 sizeof(struct apq8009_asoc_mach_data), GFP_KERNEL);
2870 if (!pdata) {
2871 ret = -ENOMEM;
2872 goto err1;
2873 }
2874
2875 card = populate_snd_card_dailinks(&pdev->dev);
2876 if (!card) {
2877 dev_err(&pdev->dev, "%s: Card uninitialized\n",
2878 __func__);
2879 ret = -EPROBE_DEFER;
2880 goto err;
2881 }
2882
2883 card->dev = &pdev->dev;
2884 platform_set_drvdata(pdev, card);
2885 snd_soc_card_set_drvdata(card, pdata);
2886
2887 ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing");
2888 if (ret)
2889 goto err;
2890
2891 match = of_match_node(apq8009_asoc_machine_of_match,
2892 pdev->dev.of_node);
2893 if (!match)
2894 goto err;
2895
2896 pdata->vaddr_gpio_mux_spkr_ctl =
2897 ioremap(LPASS_CSR_GP_IO_MUX_SPKR_CTL, 4);
2898 if (!pdata->vaddr_gpio_mux_spkr_ctl) {
2899 dev_err(&pdev->dev, "%s ioremap failure for addr %x",
2900 __func__, LPASS_CSR_GP_IO_MUX_SPKR_CTL);
2901 ret = -EINVAL;
2902 goto err;
2903 }
2904 pdata->vaddr_gpio_mux_mic_ctl =
2905 ioremap(LPASS_CSR_GP_IO_MUX_MIC_CTL, 4);
2906 if (!pdata->vaddr_gpio_mux_mic_ctl) {
2907 dev_err(&pdev->dev, "%s ioremap failure for addr %x",
2908 __func__, LPASS_CSR_GP_IO_MUX_MIC_CTL);
2909 ret = -EINVAL;
2910 goto err;
2911 }
2912
2913 pdata->vaddr_gpio_mux_pcm_ctl =
2914 ioremap(LPASS_CSR_GP_LPAIF_PRI_PCM_PRI_MODE_MUXSEL, 4);
2915 if (!pdata->vaddr_gpio_mux_pcm_ctl) {
2916 dev_err(&pdev->dev, "%s ioremap failure for addr %x",
2917 __func__,
2918 LPASS_CSR_GP_LPAIF_PRI_PCM_PRI_MODE_MUXSEL);
2919 ret = -EINVAL;
2920 goto err;
2921 }
2922
2923 ret = of_property_read_u32(pdev->dev.of_node, mclk, &id);
2924 if (ret) {
2925 dev_info(&pdev->dev,
2926 "%s: missing %s in dt node\n", __func__, mclk);
2927 id = DEFAULT_MCLK_RATE;
2928 }
2929 pdata->mclk_freq = id;
2930
2931 dev_info(&pdev->dev, "external codec is configured\n");
2932
2933 pdata->mi2s_gpio_p[PRIM_MI2S] = of_parse_phandle(pdev->dev.of_node,
2934 "qcom,pri-mi2s-gpios", 0);
2935 pdata->mi2s_gpio_p[QUAT_MI2S] = of_parse_phandle(pdev->dev.of_node,
2936 "qcom,quat-mi2s-gpios", 0);
2937
2938 ret = of_property_read_string(pdev->dev.of_node,
2939 hs_micbias_type, &type);
2940 if (ret) {
2941 dev_err(&pdev->dev, "%s: missing %s in dt node\n",
2942 __func__, hs_micbias_type);
2943 goto err;
2944 }
2945
2946 atomic_set(&pri_mi2s_clk_ref, 0);
2947 atomic_set(&quat_mi2s_clk_ref, 0);
2948 atomic_set(&auxpcm_mi2s_clk_ref, 0);
2949
2950 ret = apq8009_populate_dai_link_component_of_node(card);
2951 if (ret) {
2952 ret = -EPROBE_DEFER;
2953 goto err;
2954 }
2955 ret = apq8009_init_wsa_dev(pdev, card);
2956 if (ret)
2957 goto err;
2958 ret = snd_soc_register_card(card);
2959 if (ret == -EPROBE_DEFER)
2960 goto err;
2961 else if (ret) {
2962 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
2963 ret);
2964 goto err;
2965 }
2966 atomic_set(&pdata->quat_ref_count, 0);
2967 tdm_i2s_switch_enable = of_get_named_gpio(pdev->dev.of_node,
2968 "qcom,tdm-i2s-switch-enable", 0);
2969 if (tdm_i2s_switch_enable >= 0) {
2970 dev_dbg(&pdev->dev, "%s: tdm switch gpio %d", __func__,
2971 tdm_i2s_switch_enable);
2972 ret = gpio_request(tdm_i2s_switch_enable, "TDM_RESET");
2973 if (ret) {
2974 pr_err("%s: Failed to request gpio\n", __func__);
2975 goto err;
2976 }
2977 } else
2978 dev_err(&pdev->dev, "Looking up %s property in node %s failed\n",
2979 "qcom,tdm-i2s-switch-enable",
2980 pdev->dev.of_node->full_name);
2981
2982 return 0;
2983err:
2984 if (pdata->vaddr_gpio_mux_spkr_ctl)
2985 iounmap(pdata->vaddr_gpio_mux_spkr_ctl);
2986 if (pdata->vaddr_gpio_mux_mic_ctl)
2987 iounmap(pdata->vaddr_gpio_mux_mic_ctl);
2988 if (pdata->vaddr_gpio_mux_pcm_ctl)
2989 iounmap(pdata->vaddr_gpio_mux_pcm_ctl);
2990 devm_kfree(&pdev->dev, pdata);
2991err1:
2992 return ret;
2993}
2994
2995static int apq8009_asoc_machine_remove(struct platform_device *pdev)
2996{
2997 struct snd_soc_card *card = platform_get_drvdata(pdev);
2998 struct apq8009_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
2999
3000 if (pdata->vaddr_gpio_mux_spkr_ctl)
3001 iounmap(pdata->vaddr_gpio_mux_spkr_ctl);
3002 if (pdata->vaddr_gpio_mux_mic_ctl)
3003 iounmap(pdata->vaddr_gpio_mux_mic_ctl);
3004 if (pdata->vaddr_gpio_mux_pcm_ctl)
3005 iounmap(pdata->vaddr_gpio_mux_pcm_ctl);
3006 snd_soc_unregister_card(card);
3007 return 0;
3008}
3009
3010static struct platform_driver apq8009_asoc_machine_driver = {
3011 .driver = {
3012 .name = DRV_NAME,
3013 .owner = THIS_MODULE,
3014 .pm = &snd_soc_pm_ops,
3015 .of_match_table = apq8009_asoc_machine_of_match,
3016 },
3017 .probe = apq8009_asoc_machine_probe,
3018 .remove = apq8009_asoc_machine_remove,
3019};
3020static int __init apq8009_machine_init(void)
3021{
3022 return platform_driver_register(&apq8009_asoc_machine_driver);
3023}
3024module_init(apq8009_machine_init);
3025
3026static void __exit apq8009_machine_exit(void)
3027{
3028 return platform_driver_unregister(&apq8009_asoc_machine_driver);
3029}
3030module_exit(apq8009_machine_exit);
3031
3032MODULE_DESCRIPTION("ALSA SoC msm");
3033MODULE_LICENSE("GPL v2");
3034MODULE_ALIAS("platform:" DRV_NAME);
3035MODULE_DEVICE_TABLE(of, apq8009_asoc_machine_of_match);