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