blob: 08900372a2c2f15eb34e10fab74a0ba449d865cf [file] [log] [blame]
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001/*
2 * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/clk.h>
15#include <linux/delay.h>
16#include <linux/gpio.h>
17#include <linux/of_gpio.h>
18#include <linux/platform_device.h>
19#include <linux/slab.h>
20#include <linux/regulator/consumer.h>
21#include <linux/io.h>
22#include <linux/module.h>
23#include <linux/switch.h>
24#include <linux/input.h>
25#include <sound/core.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/pcm.h>
29#include <sound/jack.h>
30#include <sound/q6afe-v2.h>
31#include <sound/q6core.h>
32#include <sound/pcm_params.h>
33#include <sound/info.h>
34#include <device_event.h>
35#include "qdsp6v2/msm-pcm-routing-v2.h"
36#include "../codecs/wcd9xxx-common.h"
37#include "../codecs/wcd9330.h"
38#include "../codecs/wcd9335.h"
39#include "../codecs/wsa881x.h"
40
41#define DRV_NAME "msm8996-asoc-snd"
42
43#define SAMPLING_RATE_8KHZ 8000
44#define SAMPLING_RATE_16KHZ 16000
45#define SAMPLING_RATE_32KHZ 32000
46#define SAMPLING_RATE_48KHZ 48000
47#define SAMPLING_RATE_96KHZ 96000
48#define SAMPLING_RATE_192KHZ 192000
49#define SAMPLING_RATE_44P1KHZ 44100
50
51#define MSM8996_SPK_ON 1
52#define MSM8996_HIFI_ON 1
53
54#define WCD9XXX_MBHC_DEF_BUTTONS 8
55#define WCD9XXX_MBHC_DEF_RLOADS 5
56#define CODEC_EXT_CLK_RATE 9600000
57#define ADSP_STATE_READY_TIMEOUT_MS 3000
58#define DEV_NAME_STR_LEN 32
59
60#define WSA8810_NAME_1 "wsa881x.20170211"
61#define WSA8810_NAME_2 "wsa881x.20170212"
62
63static int slim0_rx_sample_rate = SAMPLING_RATE_48KHZ;
64static int slim0_tx_sample_rate = SAMPLING_RATE_48KHZ;
65static int slim1_tx_sample_rate = SAMPLING_RATE_48KHZ;
66static int slim0_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
67static int slim0_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
68static int slim1_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
69static int hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
70static int msm8996_auxpcm_rate = SAMPLING_RATE_8KHZ;
71static int slim5_rx_sample_rate = SAMPLING_RATE_48KHZ;
72static int slim5_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
73static int slim6_rx_sample_rate = SAMPLING_RATE_48KHZ;
74static int slim6_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
75
76static struct platform_device *spdev;
77static int ext_us_amp_gpio = -1;
78static int msm8996_spk_control = 1;
79static int msm_slim_0_rx_ch = 1;
80static int msm_slim_0_tx_ch = 1;
81static int msm_slim_1_tx_ch = 1;
82static int msm_slim_5_rx_ch = 1;
83static int msm_slim_6_rx_ch = 1;
84static int msm_hifi_control;
85static int msm_vi_feed_tx_ch = 2;
86
87static int msm_hdmi_rx_ch = 2;
88static int msm_proxy_rx_ch = 2;
89static int hdmi_rx_sample_rate = SAMPLING_RATE_48KHZ;
90static int msm_tert_mi2s_tx_ch = 2;
91
92static bool codec_reg_done;
93
94static const char *const hifi_function[] = {"Off", "On"};
95static const char *const pin_states[] = {"Disable", "active"};
96static const char *const spk_function[] = {"Off", "On"};
97static const char *const slim0_rx_ch_text[] = {"One", "Two"};
98static const char *const slim5_rx_ch_text[] = {"One", "Two"};
99static const char *const slim6_rx_ch_text[] = {"One", "Two"};
100static const char *const slim0_tx_ch_text[] = {"One", "Two", "Three", "Four",
101 "Five", "Six", "Seven",
102 "Eight"};
103static const char *const vi_feed_ch_text[] = {"One", "Two"};
104static char const *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five",
105 "Six", "Seven", "Eight"};
106static char const *rx_bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"};
107static char const *slim5_rx_bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"};
108static char const *slim6_rx_bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"};
109static char const *slim0_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
110 "KHZ_192", "KHZ_44P1", "KHZ_8",
111 "KHZ_16", "KHZ_32"};
112static char const *slim5_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
113 "KHZ_192", "KHZ_44P1"};
114static char const *slim6_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
115 "KHZ_192", "KHZ_44P1"};
116static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
117 "Five", "Six", "Seven", "Eight"};
118
119static char const *hdmi_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
120 "KHZ_192"};
121
122static const char *const auxpcm_rate_text[] = {"8000", "16000"};
123static const struct soc_enum msm8996_auxpcm_enum[] = {
124 SOC_ENUM_SINGLE_EXT(2, auxpcm_rate_text),
125};
126
127static struct afe_clk_set mi2s_tx_clk = {
128 AFE_API_VERSION_I2S_CONFIG,
129 Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
130 Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
131 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
132 Q6AFE_LPASS_CLK_ROOT_DEFAULT,
133 0,
134};
135
136struct msm8996_wsa881x_dev_info {
137 struct device_node *of_node;
138 u32 index;
139};
140
141static struct snd_soc_aux_dev *msm8996_aux_dev;
142static struct snd_soc_codec_conf *msm8996_codec_conf;
143
144struct msm8996_asoc_mach_data {
145 u32 mclk_freq;
146 int us_euro_gpio;
147 int hph_en1_gpio;
148 int hph_en0_gpio;
149 struct snd_info_entry *codec_root;
150};
151
152struct msm8996_asoc_wcd93xx_codec {
153 void* (*get_afe_config_fn)(struct snd_soc_codec *codec,
154 enum afe_config_type config_type);
155 void (*mbhc_hs_detect_exit)(struct snd_soc_codec *codec);
156};
157
158static struct msm8996_asoc_wcd93xx_codec msm8996_codec_fn;
159
160struct msm8996_liquid_dock_dev {
161 int dock_plug_gpio;
162 int dock_plug_irq;
163 int dock_plug_det;
164 struct work_struct irq_work;
165 struct switch_dev audio_sdev;
166};
167static struct msm8996_liquid_dock_dev *msm8996_liquid_dock_dev;
168
169static void *adsp_state_notifier;
170static void *def_tasha_mbhc_cal(void);
171static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec,
172 int enable, bool dapm);
173static int msm8996_wsa881x_init(struct snd_soc_component *component);
174
175/*
176 * Need to report LINEIN
177 * if R/L channel impedance is larger than 5K ohm
178 */
179static struct wcd_mbhc_config wcd_mbhc_cfg = {
180 .read_fw_bin = false,
181 .calibration = NULL,
182 .detect_extn_cable = true,
183 .mono_stero_detection = false,
184 .swap_gnd_mic = NULL,
185 .hs_ext_micbias = true,
186 .key_code[0] = KEY_MEDIA,
187 .key_code[1] = KEY_VOICECOMMAND,
188 .key_code[2] = KEY_VOLUMEUP,
189 .key_code[3] = KEY_VOLUMEDOWN,
190 .key_code[4] = 0,
191 .key_code[5] = 0,
192 .key_code[6] = 0,
193 .key_code[7] = 0,
194 .linein_th = 5000,
195 .moisture_en = true,
196 .mbhc_micbias = MIC_BIAS_2,
197 .anc_micbias = MIC_BIAS_2,
198 .enable_anc_mic_detect = false,
199};
200
201static inline int param_is_mask(int p)
202{
203 return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
204 (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
205}
206
207static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p,
208 int n)
209{
210 return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
211}
212
213static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned int bit)
214{
215 if (bit >= SNDRV_MASK_MAX)
216 return;
217 if (param_is_mask(n)) {
218 struct snd_mask *m = param_to_mask(p, n);
219
220 m->bits[0] = 0;
221 m->bits[1] = 0;
222 m->bits[bit >> 5] |= (1 << (bit & 31));
223 }
224}
225
226static void msm8996_liquid_docking_irq_work(struct work_struct *work)
227{
228 struct msm8996_liquid_dock_dev *dock_dev =
229 container_of(work, struct msm8996_liquid_dock_dev,
230 irq_work);
231
232 dock_dev->dock_plug_det =
233 gpio_get_value(dock_dev->dock_plug_gpio);
234
235 switch_set_state(&dock_dev->audio_sdev, dock_dev->dock_plug_det);
236 /* notify to audio daemon */
237 sysfs_notify(&dock_dev->audio_sdev.dev->kobj, NULL, "state");
238}
239
240static irqreturn_t msm8996_liquid_docking_irq_handler(int irq, void *dev)
241{
242 struct msm8996_liquid_dock_dev *dock_dev = dev;
243
244 /* switch speakers should not run in interrupt context */
245 schedule_work(&dock_dev->irq_work);
246 return IRQ_HANDLED;
247}
248
249static int msm8996_liquid_init_docking(void)
250{
251 int ret = 0;
252 int dock_plug_gpio = 0;
253
254 /* plug in docking speaker+plug in device OR unplug one of them */
255 u32 dock_plug_irq_flags = IRQF_TRIGGER_RISING |
256 IRQF_TRIGGER_FALLING |
257 IRQF_SHARED;
258
259 dock_plug_gpio = of_get_named_gpio(spdev->dev.of_node,
260 "qcom,dock-plug-det-irq", 0);
261
262 if (dock_plug_gpio >= 0) {
263 msm8996_liquid_dock_dev =
264 kzalloc(sizeof(*msm8996_liquid_dock_dev), GFP_KERNEL);
265 if (!msm8996_liquid_dock_dev) {
266 ret = -ENOMEM;
267 goto exit;
268 }
269
270 msm8996_liquid_dock_dev->dock_plug_gpio = dock_plug_gpio;
271
272 ret = gpio_request(msm8996_liquid_dock_dev->dock_plug_gpio,
273 "dock-plug-det-irq");
274 if (ret) {
275 pr_err("%s:failed request msm8996_liquid_dock_plug_gpio err = %d\n",
276 __func__, ret);
277 ret = -EINVAL;
278 goto fail_dock_gpio;
279 }
280
281 msm8996_liquid_dock_dev->dock_plug_det =
282 gpio_get_value(
283 msm8996_liquid_dock_dev->dock_plug_gpio);
284 msm8996_liquid_dock_dev->dock_plug_irq =
285 gpio_to_irq(
286 msm8996_liquid_dock_dev->dock_plug_gpio);
287
288 ret = request_irq(msm8996_liquid_dock_dev->dock_plug_irq,
289 msm8996_liquid_docking_irq_handler,
290 dock_plug_irq_flags,
291 "liquid_dock_plug_irq",
292 msm8996_liquid_dock_dev);
293 if (ret < 0) {
294 pr_err("%s: Request Irq Failed err = %d\n",
295 __func__, ret);
296 goto fail_dock_gpio;
297 }
298
299 msm8996_liquid_dock_dev->audio_sdev.name =
300 QC_AUDIO_EXTERNAL_SPK_1_EVENT;
301
302 if (switch_dev_register(
303 &msm8996_liquid_dock_dev->audio_sdev) < 0) {
304 pr_err("%s: dock device register in switch diretory failed\n",
305 __func__);
306 goto fail_switch_dev;
307 }
308
309 INIT_WORK(
310 &msm8996_liquid_dock_dev->irq_work,
311 msm8996_liquid_docking_irq_work);
312 }
313 return 0;
314
315fail_switch_dev:
316 free_irq(msm8996_liquid_dock_dev->dock_plug_irq,
317 msm8996_liquid_dock_dev);
318fail_dock_gpio:
319 gpio_free(msm8996_liquid_dock_dev->dock_plug_gpio);
320exit:
321 kfree(msm8996_liquid_dock_dev);
322 msm8996_liquid_dock_dev = NULL;
323 return ret;
324}
325
326static void msm8996_ext_control(struct snd_soc_codec *codec)
327{
328 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
329
330 pr_debug("%s: msm8996_spk_control = %d", __func__,
331 msm8996_spk_control);
332 if (msm8996_spk_control == MSM8996_SPK_ON) {
333 snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp");
334 snd_soc_dapm_enable_pin(dapm, "Lineout_2 amp");
335 } else {
336 snd_soc_dapm_disable_pin(dapm, "Lineout_1 amp");
337 snd_soc_dapm_disable_pin(dapm, "Lineout_2 amp");
338 }
339 snd_soc_dapm_sync(dapm);
340}
341
342static int msm8996_get_spk(struct snd_kcontrol *kcontrol,
343 struct snd_ctl_elem_value *ucontrol)
344{
345 pr_debug("%s: msm8996_spk_control = %d\n",
346 __func__, msm8996_spk_control);
347 ucontrol->value.integer.value[0] = msm8996_spk_control;
348 return 0;
349}
350
351static int msm8996_set_spk(struct snd_kcontrol *kcontrol,
352 struct snd_ctl_elem_value *ucontrol)
353{
Aditya Bavanaria08d2c82016-12-22 16:41:27 +0530354 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800355
356 pr_debug("%s() ucontrol->value.integer.value[0] = %ld\n",
357 __func__, ucontrol->value.integer.value[0]);
358 if (msm8996_spk_control == ucontrol->value.integer.value[0])
359 return 0;
360
361 msm8996_spk_control = ucontrol->value.integer.value[0];
362 msm8996_ext_control(codec);
363 return 1;
364}
365
366static int msm8996_hifi_ctrl(struct snd_soc_codec *codec)
367{
368 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
369 struct snd_soc_card *card = codec->component.card;
370 struct msm8996_asoc_mach_data *pdata =
371 snd_soc_card_get_drvdata(card);
372
373 pr_debug("%s: msm_hifi_control = %d", __func__,
374 msm_hifi_control);
375 if (pdata->hph_en1_gpio < 0) {
376 pr_err("%s: hph_en1_gpio is invalid\n", __func__);
377 return -EINVAL;
378 }
379 if (msm_hifi_control == MSM8996_HIFI_ON) {
380 gpio_direction_output(pdata->hph_en1_gpio, 1);
381 /* 5msec delay needed as per HW requirement */
382 usleep_range(5000, 5010);
383 } else {
384 gpio_direction_output(pdata->hph_en1_gpio, 0);
385 }
386 snd_soc_dapm_sync(dapm);
387 return 0;
388}
389
390static int msm8996_hifi_get(struct snd_kcontrol *kcontrol,
391 struct snd_ctl_elem_value *ucontrol)
392{
393 pr_debug("%s: msm_hifi_control = %d\n",
394 __func__, msm_hifi_control);
395 ucontrol->value.integer.value[0] = msm_hifi_control;
396 return 0;
397}
398
399static int msm8996_hifi_put(struct snd_kcontrol *kcontrol,
400 struct snd_ctl_elem_value *ucontrol)
401{
402 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
403
404 pr_debug("%s() ucontrol->value.integer.value[0] = %ld\n",
405 __func__, ucontrol->value.integer.value[0]);
406
407 msm_hifi_control = ucontrol->value.integer.value[0];
408 msm8996_hifi_ctrl(codec);
409 return 1;
410}
411
412static int msm8996_ext_us_amp_init(void)
413{
414 int ret = 0;
415
416 ext_us_amp_gpio = of_get_named_gpio(spdev->dev.of_node,
417 "qcom,ext-ult-spk-amp-gpio", 0);
418 if (ext_us_amp_gpio >= 0) {
419 ret = gpio_request(ext_us_amp_gpio, "ext_us_amp_gpio");
420 if (ret) {
421 pr_err("%s: ext_us_amp_gpio request failed, ret:%d\n",
422 __func__, ret);
423 return ret;
424 }
425 gpio_direction_output(ext_us_amp_gpio, 0);
426 }
427 return ret;
428}
429
430static void msm8996_ext_us_amp_enable(u32 on)
431{
432 if (on)
433 gpio_direction_output(ext_us_amp_gpio, 1);
434 else
435 gpio_direction_output(ext_us_amp_gpio, 0);
436
437 pr_debug("%s: US Emitter GPIO enable:%s\n", __func__,
438 on ? "Enable" : "Disable");
439}
440
441static int msm_ext_ultrasound_event(struct snd_soc_dapm_widget *w,
442 struct snd_kcontrol *k, int event)
443{
444 pr_debug("%s()\n", __func__);
445 if (strcmp(w->name, "ultrasound amp")) {
446 if (!gpio_is_valid(ext_us_amp_gpio)) {
447 pr_err("%s: ext_us_amp_gpio isn't configured\n",
448 __func__);
449 return -EINVAL;
450 }
451 if (SND_SOC_DAPM_EVENT_ON(event))
452 msm8996_ext_us_amp_enable(1);
453 else
454 msm8996_ext_us_amp_enable(0);
455 } else {
456 pr_err("%s() Invalid Widget = %s\n",
457 __func__, w->name);
458 return -EINVAL;
459 }
460 return 0;
461}
462
463static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec,
464 int enable, bool dapm)
465{
466 int ret = 0;
467
468 if (!strcmp(dev_name(codec->dev), "tasha_codec")) {
469 ret = tasha_cdc_mclk_enable(codec, enable, dapm);
470 } else {
471 dev_err(codec->dev, "%s: unknown codec to enable ext clk\n",
472 __func__);
473 ret = -EINVAL;
474 }
475
476 return ret;
477}
478
479static int msm8996_mclk_event(struct snd_soc_dapm_widget *w,
480 struct snd_kcontrol *kcontrol, int event)
481{
482 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
483
484 pr_debug("%s: event = %d\n", __func__, event);
485
486 switch (event) {
487 case SND_SOC_DAPM_PRE_PMU:
488 return msm_snd_enable_codec_ext_clk(codec, 1, true);
489 case SND_SOC_DAPM_POST_PMD:
490 return msm_snd_enable_codec_ext_clk(codec, 0, true);
491 }
492 return 0;
493}
494
495static int msm_snd_enable_codec_ext_tx_clk(struct snd_soc_codec *codec,
496 int enable, bool dapm)
497{
498 int ret = 0;
499
500 if (!strcmp(dev_name(codec->dev), "tasha_codec"))
501 ret = tasha_cdc_mclk_tx_enable(codec, enable, dapm);
502 else {
503 dev_err(codec->dev, "%s: unknown codec to enable ext clk\n",
504 __func__);
505 ret = -EINVAL;
506 }
507 return ret;
508}
509
510static int msm8996_mclk_tx_event(struct snd_soc_dapm_widget *w,
511 struct snd_kcontrol *kcontrol, int event)
512{
513 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
514
515 pr_debug("%s: event = %d\n", __func__, event);
516
517 switch (event) {
518 case SND_SOC_DAPM_PRE_PMU:
519 return msm_snd_enable_codec_ext_tx_clk(codec, 1, true);
520 case SND_SOC_DAPM_POST_PMD:
521 return msm_snd_enable_codec_ext_tx_clk(codec, 0, true);
522 }
523 return 0;
524}
525
526static int msm_hifi_ctrl_event(struct snd_soc_dapm_widget *w,
527 struct snd_kcontrol *k, int event)
528{
529 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
530 struct snd_soc_card *card = codec->component.card;
531 struct msm8996_asoc_mach_data *pdata =
532 snd_soc_card_get_drvdata(card);
533 int ret = 0;
534
535 pr_debug("%s: msm_hifi_control = %d", __func__,
536 msm_hifi_control);
537 switch (event) {
538 case SND_SOC_DAPM_POST_PMU:
539 if (msm_hifi_control == MSM8996_HIFI_ON) {
540 if (pdata->hph_en0_gpio < 0) {
541 pr_err("%s: hph_en0_gpio is invalid\n",
542 __func__);
543 ret = -EINVAL;
544 goto err;
545 }
546 gpio_direction_output(pdata->hph_en0_gpio, 1);
547 }
548 break;
549 case SND_SOC_DAPM_PRE_PMD:
550 if (msm_hifi_control == MSM8996_HIFI_ON) {
551 if (pdata->hph_en0_gpio < 0) {
552 pr_err("%s: hph_en0_gpio is invalid\n",
553 __func__);
554 ret = -EINVAL;
555 goto err;
556 }
557 gpio_direction_output(pdata->hph_en0_gpio, 0);
558 }
559 break;
560 }
561err:
562 return ret;
563}
564
565static const struct snd_soc_dapm_widget msm8996_dapm_widgets[] = {
566
567 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
568 msm8996_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
569
570 SND_SOC_DAPM_SUPPLY("MCLK TX", SND_SOC_NOPM, 0, 0,
571 msm8996_mclk_tx_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
572
573 SND_SOC_DAPM_SPK("Lineout_1 amp", NULL),
574 SND_SOC_DAPM_SPK("Lineout_3 amp", NULL),
575 SND_SOC_DAPM_SPK("Lineout_2 amp", NULL),
576 SND_SOC_DAPM_SPK("Lineout_4 amp", NULL),
577 SND_SOC_DAPM_SPK("ultrasound amp", msm_ext_ultrasound_event),
578 SND_SOC_DAPM_SPK("hifi amp", msm_hifi_ctrl_event),
579 SND_SOC_DAPM_MIC("Handset Mic", NULL),
580 SND_SOC_DAPM_MIC("Headset Mic", NULL),
581 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
582 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
583 SND_SOC_DAPM_MIC("Analog Mic4", NULL),
584 SND_SOC_DAPM_MIC("Analog Mic6", NULL),
585 SND_SOC_DAPM_MIC("Analog Mic7", NULL),
586 SND_SOC_DAPM_MIC("Analog Mic8", NULL),
587
588 SND_SOC_DAPM_MIC("Digital Mic0", NULL),
589 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
590 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
591 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
592 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
593 SND_SOC_DAPM_MIC("Digital Mic5", NULL),
594 SND_SOC_DAPM_MIC("Digital Mic6", NULL),
595};
596
597static struct snd_soc_dapm_route wcd9335_audio_paths[] = {
598 {"MIC BIAS1", NULL, "MCLK TX"},
599 {"MIC BIAS2", NULL, "MCLK TX"},
600 {"MIC BIAS3", NULL, "MCLK TX"},
601 {"MIC BIAS4", NULL, "MCLK TX"},
602};
603
604static int slim5_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
605 struct snd_ctl_elem_value *ucontrol)
606{
607 int sample_rate_val = 0;
608
609 switch (slim5_rx_sample_rate) {
610 case SAMPLING_RATE_44P1KHZ:
611 sample_rate_val = 3;
612 break;
613
614 case SAMPLING_RATE_192KHZ:
615 sample_rate_val = 2;
616 break;
617
618 case SAMPLING_RATE_96KHZ:
619 sample_rate_val = 1;
620 break;
621
622 case SAMPLING_RATE_48KHZ:
623 default:
624 sample_rate_val = 0;
625 break;
626 }
627
628 ucontrol->value.integer.value[0] = sample_rate_val;
629 pr_debug("%s: slim5_rx_sample_rate = %d\n", __func__,
630 slim5_rx_sample_rate);
631
632 return 0;
633}
634
635static int slim5_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
636 struct snd_ctl_elem_value *ucontrol)
637{
638 pr_debug("%s: ucontrol value = %ld\n", __func__,
639 ucontrol->value.integer.value[0]);
640
641 switch (ucontrol->value.integer.value[0]) {
642 case 3:
643 slim5_rx_sample_rate = SAMPLING_RATE_44P1KHZ;
644 break;
645 case 2:
646 slim5_rx_sample_rate = SAMPLING_RATE_192KHZ;
647 break;
648 case 1:
649 slim5_rx_sample_rate = SAMPLING_RATE_96KHZ;
650 break;
651 case 0:
652 default:
653 slim5_rx_sample_rate = SAMPLING_RATE_48KHZ;
654 }
655
656 pr_debug("%s: slim5_rx_sample_rate = %d\n", __func__,
657 slim5_rx_sample_rate);
658
659 return 0;
660}
661
662static int slim6_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
663 struct snd_ctl_elem_value *ucontrol)
664{
665 int sample_rate_val = 0;
666
667 switch (slim6_rx_sample_rate) {
668 case SAMPLING_RATE_44P1KHZ:
669 sample_rate_val = 3;
670 break;
671
672 case SAMPLING_RATE_192KHZ:
673 sample_rate_val = 2;
674 break;
675
676 case SAMPLING_RATE_96KHZ:
677 sample_rate_val = 1;
678 break;
679
680 case SAMPLING_RATE_48KHZ:
681 default:
682 sample_rate_val = 0;
683 break;
684 }
685
686 ucontrol->value.integer.value[0] = sample_rate_val;
687 pr_debug("%s: slim6_rx_sample_rate = %d\n", __func__,
688 slim6_rx_sample_rate);
689
690 return 0;
691}
692
693static int slim6_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
694 struct snd_ctl_elem_value *ucontrol)
695{
696 switch (ucontrol->value.integer.value[0]) {
697 case 3:
698 slim6_rx_sample_rate = SAMPLING_RATE_44P1KHZ;
699 break;
700 case 2:
701 slim6_rx_sample_rate = SAMPLING_RATE_192KHZ;
702 break;
703 case 1:
704 slim6_rx_sample_rate = SAMPLING_RATE_96KHZ;
705 break;
706 case 0:
707 default:
708 slim6_rx_sample_rate = SAMPLING_RATE_48KHZ;
709 break;
710 }
711
712 pr_debug("%s: ucontrol value = %ld, slim6_rx_sample_rate = %d\n",
713 __func__, ucontrol->value.integer.value[0],
714 slim6_rx_sample_rate);
715
716 return 0;
717}
718
719static int slim0_tx_bit_format_get(struct snd_kcontrol *kcontrol,
720 struct snd_ctl_elem_value *ucontrol)
721{
722 switch (slim0_tx_bit_format) {
723 case SNDRV_PCM_FORMAT_S24_3LE:
724 ucontrol->value.integer.value[0] = 2;
725 break;
726 case SNDRV_PCM_FORMAT_S24_LE:
727 ucontrol->value.integer.value[0] = 1;
728 break;
729 case SNDRV_PCM_FORMAT_S16_LE:
730 default:
731 ucontrol->value.integer.value[0] = 0;
732 break;
733 }
734
735 pr_debug("%s: slim0_tx_bit_format = %d, ucontrol value = %ld\n",
736 __func__, slim0_tx_bit_format,
737 ucontrol->value.integer.value[0]);
738 return 0;
739}
740
741static int slim0_tx_bit_format_put(struct snd_kcontrol *kcontrol,
742 struct snd_ctl_elem_value *ucontrol)
743{
744 int rc = 0;
745
746 switch (ucontrol->value.integer.value[0]) {
747 case 2:
748 slim0_tx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
749 break;
750 case 1:
751 slim0_tx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
752 break;
753 case 0:
754 slim0_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
755 break;
756 default:
757 pr_err("%s: invalid value %ld\n", __func__,
758 ucontrol->value.integer.value[0]);
759 rc = -EINVAL;
760 break;
761 }
762
763 pr_debug("%s: ucontrol value = %ld, slim0_tx_bit_format = %d\n",
764 __func__, ucontrol->value.integer.value[0],
765 slim0_tx_bit_format);
766
767 return rc;
768}
769
770static int slim0_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
771 struct snd_ctl_elem_value *ucontrol)
772{
773 int sample_rate_val = 0;
774
775 switch (slim0_rx_sample_rate) {
776 case SAMPLING_RATE_32KHZ:
777 sample_rate_val = 6;
778 break;
779
780 case SAMPLING_RATE_16KHZ:
781 sample_rate_val = 5;
782 break;
783
784 case SAMPLING_RATE_8KHZ:
785 sample_rate_val = 4;
786 break;
787
788 case SAMPLING_RATE_44P1KHZ:
789 sample_rate_val = 3;
790 break;
791
792 case SAMPLING_RATE_192KHZ:
793 sample_rate_val = 2;
794 break;
795
796 case SAMPLING_RATE_96KHZ:
797 sample_rate_val = 1;
798 break;
799
800 case SAMPLING_RATE_48KHZ:
801 default:
802 sample_rate_val = 0;
803 break;
804 }
805
806 ucontrol->value.integer.value[0] = sample_rate_val;
807 pr_debug("%s: slim0_rx_sample_rate = %d\n", __func__,
808 slim0_rx_sample_rate);
809
810 return 0;
811}
812
813static int slim0_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
814 struct snd_ctl_elem_value *ucontrol)
815{
816 pr_debug("%s: ucontrol value = %ld\n", __func__,
817 ucontrol->value.integer.value[0]);
818
819 switch (ucontrol->value.integer.value[0]) {
820 case 6:
821 slim0_rx_sample_rate = SAMPLING_RATE_32KHZ;
822 break;
823 case 5:
824 slim0_rx_sample_rate = SAMPLING_RATE_16KHZ;
825 break;
826 case 4:
827 slim0_rx_sample_rate = SAMPLING_RATE_8KHZ;
828 break;
829 case 3:
830 slim0_rx_sample_rate = SAMPLING_RATE_44P1KHZ;
831 break;
832 case 2:
833 slim0_rx_sample_rate = SAMPLING_RATE_192KHZ;
834 break;
835 case 1:
836 slim0_rx_sample_rate = SAMPLING_RATE_96KHZ;
837 break;
838 case 0:
839 default:
840 slim0_rx_sample_rate = SAMPLING_RATE_48KHZ;
841 }
842
843 pr_debug("%s: slim0_rx_sample_rate = %d\n", __func__,
844 slim0_rx_sample_rate);
845
846 return 0;
847}
848
849static int slim0_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
850 struct snd_ctl_elem_value *ucontrol)
851{
852 int sample_rate_val = 0;
853
854 switch (slim0_tx_sample_rate) {
855 case SAMPLING_RATE_192KHZ:
856 sample_rate_val = 2;
857 break;
858 case SAMPLING_RATE_96KHZ:
859 sample_rate_val = 1;
860 break;
861 case SAMPLING_RATE_48KHZ:
862 default:
863 sample_rate_val = 0;
864 break;
865 }
866
867 ucontrol->value.integer.value[0] = sample_rate_val;
868 pr_debug("%s: slim0_tx_sample_rate = %d\n", __func__,
869 slim0_tx_sample_rate);
870 return 0;
871}
872
873static int slim0_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
874 struct snd_ctl_elem_value *ucontrol)
875{
876 int rc = 0;
877
878 pr_debug("%s: ucontrol value = %ld\n", __func__,
879 ucontrol->value.integer.value[0]);
880
881 switch (ucontrol->value.integer.value[0]) {
882 case 2:
883 slim0_tx_sample_rate = SAMPLING_RATE_192KHZ;
884 break;
885 case 1:
886 slim0_tx_sample_rate = SAMPLING_RATE_96KHZ;
887 break;
888 case 0:
889 slim0_tx_sample_rate = SAMPLING_RATE_48KHZ;
890 break;
891 default:
892 rc = -EINVAL;
893 pr_err("%s: invalid sample rate being passed\n", __func__);
894 break;
895 }
896
897 pr_debug("%s: slim0_tx_sample_rate = %d\n", __func__,
898 slim0_tx_sample_rate);
899 return rc;
900}
901
902static int slim5_rx_bit_format_get(struct snd_kcontrol *kcontrol,
903 struct snd_ctl_elem_value *ucontrol)
904{
905
906 switch (slim5_rx_bit_format) {
907 case SNDRV_PCM_FORMAT_S24_3LE:
908 ucontrol->value.integer.value[0] = 2;
909 break;
910
911 case SNDRV_PCM_FORMAT_S24_LE:
912 ucontrol->value.integer.value[0] = 1;
913 break;
914
915 case SNDRV_PCM_FORMAT_S16_LE:
916 default:
917 ucontrol->value.integer.value[0] = 0;
918 break;
919 }
920
921 pr_debug("%s: slim5_rx_bit_format = %d, ucontrol value = %ld\n",
922 __func__, slim5_rx_bit_format,
923 ucontrol->value.integer.value[0]);
924
925 return 0;
926}
927
928static int slim5_rx_bit_format_put(struct snd_kcontrol *kcontrol,
929 struct snd_ctl_elem_value *ucontrol)
930{
931 switch (ucontrol->value.integer.value[0]) {
932 case 2:
933 slim5_rx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
934 break;
935 case 1:
936 slim5_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
937 break;
938 case 0:
939 default:
940 slim5_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
941 break;
942 }
943 return 0;
944}
945
946static int slim6_rx_bit_format_get(struct snd_kcontrol *kcontrol,
947 struct snd_ctl_elem_value *ucontrol)
948{
949
950 switch (slim6_rx_bit_format) {
951 case SNDRV_PCM_FORMAT_S24_3LE:
952 ucontrol->value.integer.value[0] = 2;
953 break;
954
955 case SNDRV_PCM_FORMAT_S24_LE:
956 ucontrol->value.integer.value[0] = 1;
957 break;
958
959 case SNDRV_PCM_FORMAT_S16_LE:
960 default:
961 ucontrol->value.integer.value[0] = 0;
962 break;
963 }
964
965 pr_debug("%s: slim6_rx_bit_format = %d, ucontrol value = %ld\n",
966 __func__, slim6_rx_bit_format,
967 ucontrol->value.integer.value[0]);
968
969 return 0;
970}
971
972static int slim6_rx_bit_format_put(struct snd_kcontrol *kcontrol,
973 struct snd_ctl_elem_value *ucontrol)
974{
975 switch (ucontrol->value.integer.value[0]) {
976 case 2:
977 slim6_rx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
978 break;
979 case 1:
980 slim6_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
981 break;
982 case 0:
983 default:
984 slim6_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
985 break;
986 }
987 return 0;
988}
989
990static int slim0_rx_bit_format_get(struct snd_kcontrol *kcontrol,
991 struct snd_ctl_elem_value *ucontrol)
992{
993
994 switch (slim0_rx_bit_format) {
995 case SNDRV_PCM_FORMAT_S24_3LE:
996 ucontrol->value.integer.value[0] = 2;
997 break;
998
999 case SNDRV_PCM_FORMAT_S24_LE:
1000 ucontrol->value.integer.value[0] = 1;
1001 break;
1002
1003 case SNDRV_PCM_FORMAT_S16_LE:
1004 default:
1005 ucontrol->value.integer.value[0] = 0;
1006 break;
1007 }
1008
1009 pr_debug("%s: slim0_rx_bit_format = %d, ucontrol value = %ld\n",
1010 __func__, slim0_rx_bit_format,
1011 ucontrol->value.integer.value[0]);
1012
1013 return 0;
1014}
1015
1016static int slim0_rx_bit_format_put(struct snd_kcontrol *kcontrol,
1017 struct snd_ctl_elem_value *ucontrol)
1018{
1019 switch (ucontrol->value.integer.value[0]) {
1020 case 2:
1021 slim0_rx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
1022 break;
1023 case 1:
1024 slim0_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
1025 break;
1026 case 0:
1027 default:
1028 slim0_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
1029 break;
1030 }
1031 return 0;
1032}
1033
1034static int msm_slim_5_rx_ch_get(struct snd_kcontrol *kcontrol,
1035 struct snd_ctl_elem_value *ucontrol)
1036{
1037 pr_debug("%s: msm_slim_5_rx_ch = %d\n", __func__,
1038 msm_slim_5_rx_ch);
1039 ucontrol->value.integer.value[0] = msm_slim_5_rx_ch - 1;
1040 return 0;
1041}
1042
1043static int msm_slim_5_rx_ch_put(struct snd_kcontrol *kcontrol,
1044 struct snd_ctl_elem_value *ucontrol)
1045{
1046 msm_slim_5_rx_ch = ucontrol->value.integer.value[0] + 1;
1047 pr_debug("%s: msm_slim_5_rx_ch = %d\n", __func__,
1048 msm_slim_5_rx_ch);
1049 return 1;
1050}
1051
1052static int msm_slim_6_rx_ch_get(struct snd_kcontrol *kcontrol,
1053 struct snd_ctl_elem_value *ucontrol)
1054{
1055 pr_debug("%s: msm_slim_6_rx_ch = %d\n", __func__,
1056 msm_slim_6_rx_ch);
1057 ucontrol->value.integer.value[0] = msm_slim_6_rx_ch - 1;
1058 return 0;
1059}
1060
1061static int msm_slim_6_rx_ch_put(struct snd_kcontrol *kcontrol,
1062 struct snd_ctl_elem_value *ucontrol)
1063{
1064 msm_slim_6_rx_ch = ucontrol->value.integer.value[0] + 1;
1065 pr_debug("%s: msm_slim_6_rx_ch = %d\n", __func__,
1066 msm_slim_6_rx_ch);
1067 return 1;
1068}
1069
1070static int msm_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
1071 struct snd_ctl_elem_value *ucontrol)
1072{
1073 pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
1074 msm_slim_0_rx_ch);
1075 ucontrol->value.integer.value[0] = msm_slim_0_rx_ch - 1;
1076 return 0;
1077}
1078
1079static int msm_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
1080 struct snd_ctl_elem_value *ucontrol)
1081{
1082 msm_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
1083 pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
1084 msm_slim_0_rx_ch);
1085 return 1;
1086}
1087
1088static int msm_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
1089 struct snd_ctl_elem_value *ucontrol)
1090{
1091 pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__,
1092 msm_slim_0_tx_ch);
1093 ucontrol->value.integer.value[0] = msm_slim_0_tx_ch - 1;
1094 return 0;
1095}
1096
1097static int msm_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
1098 struct snd_ctl_elem_value *ucontrol)
1099{
1100 msm_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
1101 pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__, msm_slim_0_tx_ch);
1102 return 1;
1103}
1104
1105static int msm_slim_1_tx_ch_get(struct snd_kcontrol *kcontrol,
1106 struct snd_ctl_elem_value *ucontrol)
1107{
1108 pr_debug("%s: msm_slim_1_tx_ch = %d\n", __func__,
1109 msm_slim_1_tx_ch);
1110 ucontrol->value.integer.value[0] = msm_slim_1_tx_ch - 1;
1111 return 0;
1112}
1113
1114static int msm_slim_1_tx_ch_put(struct snd_kcontrol *kcontrol,
1115 struct snd_ctl_elem_value *ucontrol)
1116{
1117 msm_slim_1_tx_ch = ucontrol->value.integer.value[0] + 1;
1118
1119 pr_debug("%s: msm_slim_1_tx_ch = %d\n", __func__, msm_slim_1_tx_ch);
1120 return 1;
1121}
1122
1123static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol,
1124 struct snd_ctl_elem_value *ucontrol)
1125{
1126 ucontrol->value.integer.value[0] = msm_vi_feed_tx_ch - 1;
1127 pr_debug("%s: msm_vi_feed_tx_ch = %ld\n", __func__,
1128 ucontrol->value.integer.value[0]);
1129 return 0;
1130}
1131
1132static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol,
1133 struct snd_ctl_elem_value *ucontrol)
1134{
1135 msm_vi_feed_tx_ch = ucontrol->value.integer.value[0] + 1;
1136
1137 pr_debug("%s: msm_vi_feed_tx_ch = %d\n", __func__, msm_vi_feed_tx_ch);
1138 return 1;
1139}
1140
1141static int hdmi_rx_bit_format_get(struct snd_kcontrol *kcontrol,
1142 struct snd_ctl_elem_value *ucontrol)
1143{
1144
1145 switch (hdmi_rx_bit_format) {
1146 case SNDRV_PCM_FORMAT_S24_3LE:
1147 ucontrol->value.integer.value[0] = 2;
1148 break;
1149
1150 case SNDRV_PCM_FORMAT_S24_LE:
1151 ucontrol->value.integer.value[0] = 1;
1152 break;
1153
1154 case SNDRV_PCM_FORMAT_S16_LE:
1155 default:
1156 ucontrol->value.integer.value[0] = 0;
1157 break;
1158 }
1159
1160 pr_debug("%s: hdmi_rx_bit_format = %d, ucontrol value = %ld\n",
1161 __func__, hdmi_rx_bit_format,
1162 ucontrol->value.integer.value[0]);
1163
1164 return 0;
1165}
1166
1167static int hdmi_rx_bit_format_put(struct snd_kcontrol *kcontrol,
1168 struct snd_ctl_elem_value *ucontrol)
1169{
1170 switch (ucontrol->value.integer.value[0]) {
1171 case 2:
1172 hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
1173 break;
1174 case 1:
1175 hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
1176 break;
1177 case 0:
1178 default:
1179 hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
1180 break;
1181 }
1182 pr_debug("%s: hdmi_rx_bit_format = %d, ucontrol value = %ld\n",
1183 __func__, hdmi_rx_bit_format,
1184 ucontrol->value.integer.value[0]);
1185 return 0;
1186}
1187
1188static int msm_hdmi_rx_ch_get(struct snd_kcontrol *kcontrol,
1189 struct snd_ctl_elem_value *ucontrol)
1190{
1191 pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__,
1192 msm_hdmi_rx_ch);
1193 ucontrol->value.integer.value[0] = msm_hdmi_rx_ch - 2;
1194
1195 return 0;
1196}
1197
1198static int msm_hdmi_rx_ch_put(struct snd_kcontrol *kcontrol,
1199 struct snd_ctl_elem_value *ucontrol)
1200{
1201 msm_hdmi_rx_ch = ucontrol->value.integer.value[0] + 2;
1202 if (msm_hdmi_rx_ch > 8) {
1203 pr_err("%s: channels %d exceeded 8.Limiting to max chs-8\n",
1204 __func__, msm_hdmi_rx_ch);
1205 msm_hdmi_rx_ch = 8;
1206 }
1207 pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__, msm_hdmi_rx_ch);
1208
1209 return 1;
1210}
1211
1212static int hdmi_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
1213 struct snd_ctl_elem_value *ucontrol)
1214{
1215 int sample_rate_val = 0;
1216
1217 switch (hdmi_rx_sample_rate) {
1218 case SAMPLING_RATE_192KHZ:
1219 sample_rate_val = 2;
1220 break;
1221
1222 case SAMPLING_RATE_96KHZ:
1223 sample_rate_val = 1;
1224 break;
1225
1226 case SAMPLING_RATE_48KHZ:
1227 default:
1228 sample_rate_val = 0;
1229 break;
1230 }
1231
1232 ucontrol->value.integer.value[0] = sample_rate_val;
1233 pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__,
1234 hdmi_rx_sample_rate);
1235
1236 return 0;
1237}
1238
1239static int hdmi_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
1240 struct snd_ctl_elem_value *ucontrol)
1241{
1242 pr_debug("%s: ucontrol value = %ld\n", __func__,
1243 ucontrol->value.integer.value[0]);
1244
1245 switch (ucontrol->value.integer.value[0]) {
1246 case 2:
1247 hdmi_rx_sample_rate = SAMPLING_RATE_192KHZ;
1248 break;
1249 case 1:
1250 hdmi_rx_sample_rate = SAMPLING_RATE_96KHZ;
1251 break;
1252 case 0:
1253 default:
1254 hdmi_rx_sample_rate = SAMPLING_RATE_48KHZ;
1255 }
1256
1257 pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__,
1258 hdmi_rx_sample_rate);
1259
1260 return 0;
1261}
1262
1263static int msm8996_auxpcm_rate_get(struct snd_kcontrol *kcontrol,
1264 struct snd_ctl_elem_value *ucontrol)
1265{
1266 ucontrol->value.integer.value[0] = msm8996_auxpcm_rate;
1267 return 0;
1268}
1269
1270static int msm8996_auxpcm_rate_put(struct snd_kcontrol *kcontrol,
1271 struct snd_ctl_elem_value *ucontrol)
1272{
1273 switch (ucontrol->value.integer.value[0]) {
1274 case 0:
1275 msm8996_auxpcm_rate = SAMPLING_RATE_8KHZ;
1276 break;
1277 case 1:
1278 msm8996_auxpcm_rate = SAMPLING_RATE_16KHZ;
1279 break;
1280 default:
1281 msm8996_auxpcm_rate = SAMPLING_RATE_8KHZ;
1282 break;
1283 }
1284 return 0;
1285}
1286
1287static int msm_proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
1288 struct snd_ctl_elem_value *ucontrol)
1289{
1290 pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__, msm_proxy_rx_ch);
1291 ucontrol->value.integer.value[0] = msm_proxy_rx_ch - 1;
1292 return 0;
1293}
1294
1295static int msm_proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
1296 struct snd_ctl_elem_value *ucontrol)
1297{
1298 msm_proxy_rx_ch = ucontrol->value.integer.value[0] + 1;
1299 pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__, msm_proxy_rx_ch);
1300 return 1;
1301}
1302
1303static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
1304 struct snd_pcm_hw_params *params)
1305{
1306 struct snd_interval *rate =
1307 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
1308
1309 struct snd_interval *channels =
1310 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
1311
1312 rate->min = rate->max = msm8996_auxpcm_rate;
1313 channels->min = channels->max = 1;
1314
1315 return 0;
1316}
1317
1318static int msm_proxy_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1319 struct snd_pcm_hw_params *params)
1320{
1321 struct snd_interval *rate = hw_param_interval(params,
1322 SNDRV_PCM_HW_PARAM_RATE);
1323 struct snd_interval *channels = hw_param_interval(params,
1324 SNDRV_PCM_HW_PARAM_CHANNELS);
1325
1326 pr_debug("%s: msm_proxy_rx_ch =%d\n", __func__, msm_proxy_rx_ch);
1327
1328 if (channels->max < 2)
1329 channels->min = channels->max = 2;
1330 channels->min = channels->max = msm_proxy_rx_ch;
1331 rate->min = rate->max = SAMPLING_RATE_48KHZ;
1332 return 0;
1333}
1334
1335static int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1336 struct snd_pcm_hw_params *params)
1337{
1338 struct snd_interval *rate = hw_param_interval(params,
1339 SNDRV_PCM_HW_PARAM_RATE);
1340
1341 rate->min = rate->max = SAMPLING_RATE_48KHZ;
1342 return 0;
1343}
1344
1345static int msm8996_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1346 struct snd_pcm_hw_params *params)
1347{
1348 struct snd_interval *rate = hw_param_interval(params,
1349 SNDRV_PCM_HW_PARAM_RATE);
1350 struct snd_interval *channels = hw_param_interval(params,
1351 SNDRV_PCM_HW_PARAM_CHANNELS);
1352
1353 pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
1354 channels->min, channels->max);
1355
1356 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
1357 hdmi_rx_bit_format);
1358 if (channels->max < 2)
1359 channels->min = channels->max = 2;
1360 rate->min = rate->max = hdmi_rx_sample_rate;
1361 channels->min = channels->max = msm_hdmi_rx_ch;
1362
1363 return 0;
1364}
1365
1366static int msm_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1367 struct snd_pcm_hw_params *params)
1368{
1369 struct snd_interval *rate = hw_param_interval(params,
1370 SNDRV_PCM_HW_PARAM_RATE);
1371 struct snd_interval *channels = hw_param_interval(params,
1372 SNDRV_PCM_HW_PARAM_CHANNELS);
1373
1374 pr_debug("%s: channel:%d\n", __func__, msm_tert_mi2s_tx_ch);
1375 rate->min = rate->max = SAMPLING_RATE_48KHZ;
1376 channels->min = channels->max = msm_tert_mi2s_tx_ch;
1377 return 0;
1378}
1379
1380static int msm8996_mi2s_snd_startup(struct snd_pcm_substream *substream)
1381{
1382 int ret = 0;
1383 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1384 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1385
1386 pr_debug("%s: substream = %s stream = %d\n", __func__,
1387 substream->name, substream->stream);
1388
1389 mi2s_tx_clk.enable = 1;
1390 ret = afe_set_lpass_clock_v2(AFE_PORT_ID_TERTIARY_MI2S_TX,
1391 &mi2s_tx_clk);
1392 if (ret < 0) {
1393 pr_err("%s: afe lpass clock failed, err:%d\n", __func__, ret);
1394 goto err;
1395 }
1396 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
1397 if (ret < 0)
1398 pr_err("%s: set fmt cpu dai failed, err:%d\n", __func__, ret);
1399err:
1400 return ret;
1401}
1402
1403static void msm8996_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
1404{
1405 int ret = 0;
1406
1407 pr_debug("%s: substream = %s stream = %d\n", __func__,
1408 substream->name, substream->stream);
1409
1410 mi2s_tx_clk.enable = 0;
1411 ret = afe_set_lpass_clock_v2(AFE_PORT_ID_TERTIARY_MI2S_TX,
1412 &mi2s_tx_clk);
1413 if (ret < 0)
1414 pr_err("%s: afe lpass clock failed, err:%d\n", __func__, ret);
1415}
1416
1417static struct snd_soc_ops msm8996_mi2s_be_ops = {
1418 .startup = msm8996_mi2s_snd_startup,
1419 .shutdown = msm8996_mi2s_snd_shutdown,
1420};
1421
1422static int msm_slim_5_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1423 struct snd_pcm_hw_params *params)
1424{
1425 struct snd_interval *rate = hw_param_interval(params,
1426 SNDRV_PCM_HW_PARAM_RATE);
1427 struct snd_interval *channels = hw_param_interval(params,
1428 SNDRV_PCM_HW_PARAM_CHANNELS);
1429
1430 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
1431 slim5_rx_bit_format);
1432 rate->min = rate->max = slim5_rx_sample_rate;
1433 channels->min = channels->max = msm_slim_5_rx_ch;
1434
1435 pr_debug("%s: format = %d, rate = %d, channels = %d\n",
1436 __func__, params_format(params), params_rate(params),
1437 msm_slim_5_rx_ch);
1438
1439 return 0;
1440}
1441
1442static int msm_slim_6_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1443 struct snd_pcm_hw_params *params)
1444{
1445 struct snd_interval *rate = hw_param_interval(params,
1446 SNDRV_PCM_HW_PARAM_RATE);
1447 struct snd_interval *channels = hw_param_interval(params,
1448 SNDRV_PCM_HW_PARAM_CHANNELS);
1449
1450 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
1451 slim6_rx_bit_format);
1452 rate->min = rate->max = slim6_rx_sample_rate;
1453 channels->min = channels->max = msm_slim_6_rx_ch;
1454
1455 pr_debug("%s: format = %d, rate = %d, channels = %d\n",
1456 __func__, params_format(params), params_rate(params),
1457 msm_slim_6_rx_ch);
1458
1459 return 0;
1460}
1461
1462static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1463 struct snd_pcm_hw_params *params)
1464{
1465 struct snd_interval *rate = hw_param_interval(params,
1466 SNDRV_PCM_HW_PARAM_RATE);
1467 struct snd_interval *channels = hw_param_interval(params,
1468 SNDRV_PCM_HW_PARAM_CHANNELS);
1469
1470 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
1471 slim0_rx_bit_format);
1472 rate->min = rate->max = slim0_rx_sample_rate;
1473 channels->min = channels->max = msm_slim_0_rx_ch;
1474
1475 pr_debug("%s: format = %d, rate = %d, channels = %d\n",
1476 __func__, params_format(params), params_rate(params),
1477 msm_slim_0_rx_ch);
1478
1479 return 0;
1480}
1481
1482static int msm_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1483 struct snd_pcm_hw_params *params)
1484{
1485 struct snd_interval *rate = hw_param_interval(params,
1486 SNDRV_PCM_HW_PARAM_RATE);
1487 struct snd_interval *channels = hw_param_interval(params,
1488 SNDRV_PCM_HW_PARAM_CHANNELS);
1489
1490 pr_debug("%s()\n", __func__);
1491 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, slim0_tx_bit_format);
1492 rate->min = rate->max = slim0_tx_sample_rate;
1493 channels->min = channels->max = msm_slim_0_tx_ch;
1494
1495 return 0;
1496}
1497
1498static int msm_slim_1_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1499 struct snd_pcm_hw_params *params)
1500{
1501 struct snd_interval *rate = hw_param_interval(params,
1502 SNDRV_PCM_HW_PARAM_RATE);
1503 struct snd_interval *channels = hw_param_interval(params,
1504 SNDRV_PCM_HW_PARAM_CHANNELS);
1505
1506 pr_debug("%s()\n", __func__);
1507 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, slim1_tx_bit_format);
1508 rate->min = rate->max = slim1_tx_sample_rate;
1509 channels->min = channels->max = msm_slim_1_tx_ch;
1510
1511 return 0;
1512}
1513
1514static int msm_slim_4_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1515 struct snd_pcm_hw_params *params)
1516{
1517 struct snd_interval *rate = hw_param_interval(params,
1518 SNDRV_PCM_HW_PARAM_RATE);
1519
1520 struct snd_interval *channels = hw_param_interval(params,
1521 SNDRV_PCM_HW_PARAM_CHANNELS);
1522
1523 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
1524 SNDRV_PCM_FORMAT_S32_LE);
1525
1526 rate->min = rate->max = SAMPLING_RATE_8KHZ;
1527 channels->min = channels->max = msm_vi_feed_tx_ch;
1528 pr_debug("%s: msm_vi_feed_tx_ch: %d\n", __func__, msm_vi_feed_tx_ch);
1529
1530 return 0;
1531}
1532
1533static int msm_slim_5_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1534 struct snd_pcm_hw_params *params)
1535{
1536 int rc = 0;
1537 void *config = NULL;
1538 struct snd_soc_codec *codec = rtd->codec;
1539 struct snd_interval *rate = hw_param_interval(params,
1540 SNDRV_PCM_HW_PARAM_RATE);
1541 struct snd_interval *channels = hw_param_interval(params,
1542 SNDRV_PCM_HW_PARAM_CHANNELS);
1543
1544 pr_debug("%s: enter\n", __func__);
1545 rate->min = rate->max = SAMPLING_RATE_16KHZ;
1546 channels->min = channels->max = 1;
1547
1548 config = msm8996_codec_fn.get_afe_config_fn(codec,
1549 AFE_SLIMBUS_SLAVE_PORT_CONFIG);
1550 if (config) {
1551 rc = afe_set_config(AFE_SLIMBUS_SLAVE_PORT_CONFIG, config,
1552 SLIMBUS_5_TX);
1553 if (rc) {
1554 pr_err("%s: Failed to set slimbus slave port config %d\n",
1555 __func__, rc);
1556 }
1557 }
1558
1559 return rc;
1560}
1561
1562static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1563 struct snd_pcm_hw_params *params)
1564{
1565 struct snd_interval *rate = hw_param_interval(params,
1566 SNDRV_PCM_HW_PARAM_RATE);
1567
1568 pr_debug("%s:\n", __func__);
1569 rate->min = rate->max = SAMPLING_RATE_48KHZ;
1570 return 0;
1571}
1572
1573static const struct soc_enum msm_snd_enum[] = {
1574 SOC_ENUM_SINGLE_EXT(2, spk_function),
1575 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
1576 SOC_ENUM_SINGLE_EXT(8, slim0_tx_ch_text),
1577 SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
1578 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_bit_format_text),
1579 rx_bit_format_text),
1580 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim0_rx_sample_rate_text),
1581 slim0_rx_sample_rate_text),
1582 SOC_ENUM_SINGLE_EXT(8, proxy_rx_ch_text),
1583 SOC_ENUM_SINGLE_EXT(3, hdmi_rx_sample_rate_text),
1584 SOC_ENUM_SINGLE_EXT(4, slim5_rx_sample_rate_text),
1585 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim5_rx_bit_format_text),
1586 slim5_rx_bit_format_text),
1587 SOC_ENUM_SINGLE_EXT(2, slim5_rx_ch_text),
1588 SOC_ENUM_SINGLE_EXT(2, hifi_function),
1589 SOC_ENUM_SINGLE_EXT(2, vi_feed_ch_text),
1590 SOC_ENUM_SINGLE_EXT(4, slim6_rx_sample_rate_text),
1591 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim6_rx_bit_format_text),
1592 slim6_rx_bit_format_text),
1593 SOC_ENUM_SINGLE_EXT(2, slim6_rx_ch_text),
1594};
1595
1596static const struct snd_kcontrol_new msm_snd_controls[] = {
1597 SOC_ENUM_EXT("Speaker Function", msm_snd_enum[0], msm8996_get_spk,
1598 msm8996_set_spk),
1599 SOC_ENUM_EXT("SLIM_0_RX Channels", msm_snd_enum[1],
1600 msm_slim_0_rx_ch_get, msm_slim_0_rx_ch_put),
1601 SOC_ENUM_EXT("SLIM_5_RX Channels", msm_snd_enum[10],
1602 msm_slim_5_rx_ch_get, msm_slim_5_rx_ch_put),
1603 SOC_ENUM_EXT("SLIM_6_RX Channels", msm_snd_enum[15],
1604 msm_slim_6_rx_ch_get, msm_slim_6_rx_ch_put),
1605 SOC_ENUM_EXT("SLIM_0_TX Channels", msm_snd_enum[2],
1606 msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
1607 SOC_ENUM_EXT("SLIM_1_TX Channels", msm_snd_enum[2],
1608 msm_slim_1_tx_ch_get, msm_slim_1_tx_ch_put),
1609 SOC_ENUM_EXT("AUX PCM SampleRate", msm8996_auxpcm_enum[0],
1610 msm8996_auxpcm_rate_get,
1611 msm8996_auxpcm_rate_put),
1612 SOC_ENUM_EXT("HDMI_RX Channels", msm_snd_enum[3],
1613 msm_hdmi_rx_ch_get, msm_hdmi_rx_ch_put),
1614 SOC_ENUM_EXT("SLIM_0_RX Format", msm_snd_enum[4],
1615 slim0_rx_bit_format_get, slim0_rx_bit_format_put),
1616 SOC_ENUM_EXT("SLIM_5_RX Format", msm_snd_enum[9],
1617 slim5_rx_bit_format_get, slim5_rx_bit_format_put),
1618 SOC_ENUM_EXT("SLIM_6_RX Format", msm_snd_enum[14],
1619 slim6_rx_bit_format_get, slim6_rx_bit_format_put),
1620 SOC_ENUM_EXT("SLIM_0_RX SampleRate", msm_snd_enum[5],
1621 slim0_rx_sample_rate_get, slim0_rx_sample_rate_put),
1622 SOC_ENUM_EXT("SLIM_5_RX SampleRate", msm_snd_enum[8],
1623 slim5_rx_sample_rate_get, slim5_rx_sample_rate_put),
1624 SOC_ENUM_EXT("SLIM_6_RX SampleRate", msm_snd_enum[13],
1625 slim6_rx_sample_rate_get, slim6_rx_sample_rate_put),
1626 SOC_ENUM_EXT("HDMI_RX Bit Format", msm_snd_enum[4],
1627 hdmi_rx_bit_format_get, hdmi_rx_bit_format_put),
1628 SOC_ENUM_EXT("PROXY_RX Channels", msm_snd_enum[6],
1629 msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
1630 SOC_ENUM_EXT("HDMI_RX SampleRate", msm_snd_enum[7],
1631 hdmi_rx_sample_rate_get, hdmi_rx_sample_rate_put),
1632 SOC_ENUM_EXT("SLIM_0_TX SampleRate", msm_snd_enum[5],
1633 slim0_tx_sample_rate_get, slim0_tx_sample_rate_put),
1634 SOC_ENUM_EXT("SLIM_0_TX Format", msm_snd_enum[4],
1635 slim0_tx_bit_format_get, slim0_tx_bit_format_put),
1636 SOC_ENUM_EXT("HiFi Function", msm_snd_enum[11], msm8996_hifi_get,
1637 msm8996_hifi_put),
1638 SOC_ENUM_EXT("VI_FEED_TX Channels", msm_snd_enum[12],
1639 msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
1640};
1641
1642static bool msm8996_swap_gnd_mic(struct snd_soc_codec *codec)
1643{
1644 struct snd_soc_card *card = codec->component.card;
1645 struct msm8996_asoc_mach_data *pdata =
1646 snd_soc_card_get_drvdata(card);
1647 int value = gpio_get_value_cansleep(pdata->us_euro_gpio);
1648
1649 pr_debug("%s: swap select switch %d to %d\n", __func__, value, !value);
1650 gpio_set_value_cansleep(pdata->us_euro_gpio, !value);
1651 return true;
1652}
1653
1654static int msm_afe_set_config(struct snd_soc_codec *codec)
1655{
1656 int rc;
1657 void *config_data = NULL;
1658
1659 pr_debug("%s: enter\n", __func__);
1660
1661 if (!msm8996_codec_fn.get_afe_config_fn) {
1662 dev_err(codec->dev, "%s: codec get afe config not init'ed\n",
1663 __func__);
1664 return -EINVAL;
1665 }
1666
1667 config_data = msm8996_codec_fn.get_afe_config_fn(codec,
1668 AFE_CDC_REGISTERS_CONFIG);
1669 if (config_data) {
1670 rc = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
1671 if (rc) {
1672 pr_err("%s: Failed to set codec registers config %d\n",
1673 __func__, rc);
1674 return rc;
1675 }
1676 }
1677
1678 config_data = msm8996_codec_fn.get_afe_config_fn(codec,
1679 AFE_CDC_REGISTER_PAGE_CONFIG);
1680 if (config_data) {
1681 rc = afe_set_config(AFE_CDC_REGISTER_PAGE_CONFIG, config_data,
1682 0);
1683 if (rc)
1684 pr_err("%s: Failed to set cdc register page config\n",
1685 __func__);
1686 }
1687
1688 config_data = msm8996_codec_fn.get_afe_config_fn(codec,
1689 AFE_SLIMBUS_SLAVE_CONFIG);
1690 if (config_data) {
1691 rc = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
1692 if (rc) {
1693 pr_err("%s: Failed to set slimbus slave config %d\n",
1694 __func__, rc);
1695 return rc;
1696 }
1697 }
1698
1699 return 0;
1700}
1701
1702static void msm_afe_clear_config(void)
1703{
1704 afe_clear_config(AFE_CDC_REGISTERS_CONFIG);
1705 afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
1706}
1707
1708static int msm8996_adsp_state_callback(struct notifier_block *nb,
1709 unsigned long value, void *priv)
1710{
1711 if (value == SUBSYS_BEFORE_SHUTDOWN) {
1712 pr_debug("%s: ADSP is about to shutdown. Clearing AFE config\n",
1713 __func__);
1714 msm_afe_clear_config();
1715 } else if (value == SUBSYS_AFTER_POWERUP) {
1716 pr_debug("%s: ADSP is up\n", __func__);
1717 }
1718
1719 return NOTIFY_OK;
1720}
1721
1722static struct notifier_block adsp_state_notifier_block = {
1723 .notifier_call = msm8996_adsp_state_callback,
1724 .priority = -INT_MAX,
1725};
1726
1727static int msm8996_wcd93xx_codec_up(struct snd_soc_codec *codec)
1728{
1729 int err;
1730 unsigned long timeout;
1731 int adsp_ready = 0;
1732
1733 timeout = jiffies +
1734 msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
1735
1736 do {
1737 if (!q6core_is_adsp_ready()) {
1738 pr_err_ratelimited("%s: ADSP Audio isn't ready\n",
1739 __func__);
1740 /*
1741 * ADSP will be coming up after subsystem restart and
1742 * it might not be fully up when the control reaches
1743 * here. So, wait for 50msec before checking ADSP state
1744 */
1745 msleep(50);
1746 } else {
1747 pr_debug("%s: ADSP Audio is ready\n", __func__);
1748 adsp_ready = 1;
1749 break;
1750 }
1751 } while (time_after(timeout, jiffies));
1752
1753 if (!adsp_ready) {
1754 pr_err("%s: timed out waiting for ADSP Audio\n", __func__);
1755 return -ETIMEDOUT;
1756 }
1757
1758 err = msm_afe_set_config(codec);
1759 if (err)
1760 pr_err("%s: Failed to set AFE config. err %d\n",
1761 __func__, err);
1762 return err;
1763}
1764
1765static int msm8996_tasha_codec_event_cb(struct snd_soc_codec *codec,
1766 enum wcd9335_codec_event codec_event)
1767{
1768 switch (codec_event) {
1769 case WCD9335_CODEC_EVENT_CODEC_UP:
1770 return msm8996_wcd93xx_codec_up(codec);
1771 default:
1772 pr_err("%s: UnSupported codec event %d\n",
1773 __func__, codec_event);
1774 return -EINVAL;
1775 }
1776}
1777
1778static int msm8996_config_hph_en0_gpio(struct snd_soc_codec *codec, bool high)
1779{
1780 struct snd_soc_card *card = codec->component.card;
1781 struct msm8996_asoc_mach_data *pdata;
1782 int val;
1783
1784 if (!card)
1785 return 0;
1786
1787 pdata = snd_soc_card_get_drvdata(card);
1788 if (!pdata || !gpio_is_valid(pdata->hph_en0_gpio))
1789 return 0;
1790
1791 val = gpio_get_value_cansleep(pdata->hph_en0_gpio);
1792 if ((!!val) == high)
1793 return 0;
1794
1795 gpio_direction_output(pdata->hph_en0_gpio, (int)high);
1796
1797 return 1;
1798}
1799
1800static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
1801{
1802 int err;
1803 void *config_data;
1804 struct snd_soc_codec *codec = rtd->codec;
1805 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
1806 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1807 struct snd_soc_dai *codec_dai = rtd->codec_dai;
Banajit Goswamid0684992016-12-16 00:28:16 -08001808 struct snd_soc_component *aux_comp;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001809 void *mbhc_calibration;
1810 struct snd_card *card;
1811 struct snd_info_entry *entry;
1812 struct msm8996_asoc_mach_data *pdata =
1813 snd_soc_card_get_drvdata(rtd->card);
1814
1815 /* Codec SLIMBUS configuration
1816 * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
1817 * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
1818 * TX14, TX15, TX16
1819 */
1820 unsigned int rx_ch[TASHA_RX_MAX] = {144, 145, 146, 147, 148, 149, 150,
1821 151, 152, 153, 154, 155, 156};
1822 unsigned int tx_ch[TASHA_TX_MAX] = {128, 129, 130, 131, 132, 133,
1823 134, 135, 136, 137, 138, 139,
1824 140, 141, 142, 143};
1825
1826 pr_info("%s: dev_name%s\n", __func__, dev_name(cpu_dai->dev));
1827
1828 rtd->pmdown_time = 0;
1829
1830 err = snd_soc_add_codec_controls(codec, msm_snd_controls,
1831 ARRAY_SIZE(msm_snd_controls));
1832 if (err < 0) {
1833 pr_err("%s: add_codec_controls failed, err %d\n",
1834 __func__, err);
1835 return err;
1836 }
1837
1838 err = msm8996_liquid_init_docking();
1839 if (err) {
1840 pr_err("%s: 8996 init Docking stat IRQ failed (%d)\n",
1841 __func__, err);
1842 return err;
1843 }
1844
1845 err = msm8996_ext_us_amp_init();
1846 if (err) {
1847 pr_err("%s: 8996 US Emitter GPIO init failed (%d)\n",
1848 __func__, err);
1849 return err;
1850 }
1851
1852 snd_soc_dapm_new_controls(dapm, msm8996_dapm_widgets,
1853 ARRAY_SIZE(msm8996_dapm_widgets));
1854
1855 snd_soc_dapm_add_routes(dapm, wcd9335_audio_paths,
1856 ARRAY_SIZE(wcd9335_audio_paths));
1857 snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp");
1858 snd_soc_dapm_enable_pin(dapm, "Lineout_3 amp");
1859 snd_soc_dapm_enable_pin(dapm, "Lineout_2 amp");
1860 snd_soc_dapm_enable_pin(dapm, "Lineout_4 amp");
1861
1862 snd_soc_dapm_ignore_suspend(dapm, "Lineout_1 amp");
1863 snd_soc_dapm_ignore_suspend(dapm, "Lineout_3 amp");
1864 snd_soc_dapm_ignore_suspend(dapm, "Lineout_2 amp");
1865 snd_soc_dapm_ignore_suspend(dapm, "Lineout_4 amp");
1866 snd_soc_dapm_ignore_suspend(dapm, "ultrasound amp");
1867 snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
1868 snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
1869 snd_soc_dapm_ignore_suspend(dapm, "ANCRight Headset Mic");
1870 snd_soc_dapm_ignore_suspend(dapm, "ANCLeft Headset Mic");
1871 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
1872 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
1873 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic3");
1874 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic4");
1875 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic5");
1876 snd_soc_dapm_ignore_suspend(dapm, "Analog Mic4");
1877 snd_soc_dapm_ignore_suspend(dapm, "Analog Mic6");
1878 snd_soc_dapm_ignore_suspend(dapm, "Analog Mic7");
1879 snd_soc_dapm_ignore_suspend(dapm, "Analog Mic8");
1880 snd_soc_dapm_ignore_suspend(dapm, "MADINPUT");
1881 snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_INPUT");
1882 snd_soc_dapm_ignore_suspend(dapm, "EAR");
1883 snd_soc_dapm_ignore_suspend(dapm, "LINEOUT1");
1884 snd_soc_dapm_ignore_suspend(dapm, "LINEOUT2");
1885 snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3");
1886 snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4");
1887 snd_soc_dapm_ignore_suspend(dapm, "ANC EAR");
1888 snd_soc_dapm_ignore_suspend(dapm, "AMIC1");
1889 snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
1890 snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
1891 snd_soc_dapm_ignore_suspend(dapm, "AMIC4");
1892 snd_soc_dapm_ignore_suspend(dapm, "AMIC5");
1893 snd_soc_dapm_ignore_suspend(dapm, "AMIC6");
1894 snd_soc_dapm_ignore_suspend(dapm, "DMIC1");
1895 snd_soc_dapm_ignore_suspend(dapm, "DMIC2");
1896 snd_soc_dapm_ignore_suspend(dapm, "DMIC3");
1897 snd_soc_dapm_ignore_suspend(dapm, "DMIC4");
1898 snd_soc_dapm_ignore_suspend(dapm, "DMIC5");
1899 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic0");
1900 snd_soc_dapm_ignore_suspend(dapm, "DMIC0");
1901 snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT");
1902 snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT");
1903 snd_soc_dapm_ignore_suspend(dapm, "HPHL");
1904 snd_soc_dapm_ignore_suspend(dapm, "HPHR");
1905 snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL");
1906 snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR");
1907 snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1");
1908 snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2");
1909 snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI");
1910 snd_soc_dapm_ignore_suspend(dapm, "VIINPUT");
1911
1912 snd_soc_dapm_sync(dapm);
1913
1914 snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
1915 tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
1916
1917 msm8996_codec_fn.get_afe_config_fn = tasha_get_afe_config;
1918 msm8996_codec_fn.mbhc_hs_detect_exit = tasha_mbhc_hs_detect_exit;
1919
1920 err = msm_afe_set_config(codec);
1921 if (err) {
1922 pr_err("%s: Failed to set AFE config %d\n", __func__, err);
1923 goto out;
1924 }
1925
1926 config_data = msm8996_codec_fn.get_afe_config_fn(codec,
1927 AFE_AANC_VERSION);
1928 if (config_data) {
1929 err = afe_set_config(AFE_AANC_VERSION, config_data, 0);
1930 if (err) {
1931 pr_err("%s: Failed to set aanc version %d\n",
1932 __func__, err);
1933 goto out;
1934 }
1935 }
1936 config_data = msm8996_codec_fn.get_afe_config_fn(codec,
1937 AFE_CDC_CLIP_REGISTERS_CONFIG);
1938 if (config_data) {
1939 err = afe_set_config(AFE_CDC_CLIP_REGISTERS_CONFIG,
1940 config_data, 0);
1941 if (err) {
1942 pr_err("%s: Failed to set clip registers %d\n",
1943 __func__, err);
1944 goto out;
1945 }
1946 }
1947 config_data = msm8996_codec_fn.get_afe_config_fn(codec,
1948 AFE_CLIP_BANK_SEL);
1949 if (config_data) {
1950 err = afe_set_config(AFE_CLIP_BANK_SEL, config_data, 0);
1951 if (err) {
1952 pr_err("%s: Failed to set AFE bank selection %d\n",
1953 __func__, err);
1954 goto out;
1955 }
1956 }
1957 /* Start mbhc */
1958 tasha_mbhc_zdet_gpio_ctrl(msm8996_config_hph_en0_gpio, rtd->codec);
1959 mbhc_calibration = def_tasha_mbhc_cal();
1960 if (mbhc_calibration) {
1961 wcd_mbhc_cfg.calibration = mbhc_calibration;
1962 err = tasha_mbhc_hs_detect(codec, &wcd_mbhc_cfg);
1963 if (err) {
1964 pr_err("%s: mbhc hs detect failed, err:%d\n",
1965 __func__, err);
1966 goto out;
1967 }
1968 } else {
1969 pr_err("%s: mbhc_cfg calibration is NULL\n", __func__);
1970 err = -ENOMEM;
1971 goto out;
1972 }
1973 adsp_state_notifier = subsys_notif_register_notifier("adsp",
1974 &adsp_state_notifier_block);
1975 if (!adsp_state_notifier) {
1976 pr_err("%s: Failed to register adsp state notifier\n",
1977 __func__);
1978 err = -EFAULT;
1979 msm8996_codec_fn.mbhc_hs_detect_exit(codec);
1980 goto out;
1981 }
1982
1983 tasha_event_register(msm8996_tasha_codec_event_cb, rtd->codec);
1984
1985 /*
1986 * Send speaker configuration only for WSA8810.
1987 * Defalut configuration is for WSA8815.
1988 */
Banajit Goswamid0684992016-12-16 00:28:16 -08001989 if (!list_empty(&rtd->card->aux_comp_list)) {
1990 aux_comp = list_first_entry(&rtd->card->aux_comp_list,
1991 struct snd_soc_component, list_aux);
1992 if (!strcmp(aux_comp->name, WSA8810_NAME_1) ||
1993 !strcmp(aux_comp->name, WSA8810_NAME_2)) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001994 tasha_set_spkr_mode(rtd->codec, SPKR_MODE_1);
1995 tasha_set_spkr_gain_offset(rtd->codec,
1996 RX_GAIN_OFFSET_M1P5_DB);
Banajit Goswamid0684992016-12-16 00:28:16 -08001997 }
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001998 }
1999 codec_reg_done = true;
2000
2001 card = rtd->card->snd_card;
2002 entry = snd_info_create_subdir(card->module, "codecs",
2003 card->proc_root);
2004 if (!entry) {
2005 pr_debug("%s: Cannot create codecs module entry\n",
2006 __func__);
2007 err = 0;
2008 goto out;
2009 }
2010 pdata->codec_root = entry;
2011 tasha_codec_info_create_codec_entry(pdata->codec_root, codec);
2012
2013 return 0;
2014out:
2015 return err;
2016}
2017
2018static void *def_tasha_mbhc_cal(void)
2019{
2020 void *tasha_wcd_cal;
2021 struct wcd_mbhc_btn_detect_cfg *btn_cfg;
2022 u16 *btn_high;
2023
2024 tasha_wcd_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
2025 WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL);
2026 if (!tasha_wcd_cal)
2027 return NULL;
2028
2029#define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(tasha_wcd_cal)->X) = (Y))
2030 S(v_hs_max, 1500);
2031#undef S
2032#define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(tasha_wcd_cal)->X) = (Y))
2033 S(num_btn, WCD_MBHC_DEF_BUTTONS);
2034#undef S
2035
2036 btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(tasha_wcd_cal);
2037 btn_high = ((void *)&btn_cfg->_v_btn_low) +
2038 (sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
2039
2040 btn_high[0] = 75;
2041 btn_high[1] = 150;
2042 btn_high[2] = 237;
2043 btn_high[3] = 500;
2044 btn_high[4] = 500;
2045 btn_high[5] = 500;
2046 btn_high[6] = 500;
2047 btn_high[7] = 500;
2048
2049 return tasha_wcd_cal;
2050}
2051
2052static int msm_snd_hw_params(struct snd_pcm_substream *substream,
2053 struct snd_pcm_hw_params *params)
2054{
2055 struct snd_soc_pcm_runtime *rtd = substream->private_data;
2056 struct snd_soc_dai *codec_dai = rtd->codec_dai;
2057 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
2058 struct snd_soc_dai_link *dai_link = rtd->dai_link;
2059
2060 int ret = 0;
2061 u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
2062 u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
2063 u32 user_set_tx_ch = 0;
2064 u32 rx_ch_count;
2065
2066 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
2067 ret = snd_soc_dai_get_channel_map(codec_dai,
2068 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
2069 if (ret < 0) {
2070 pr_err("%s: failed to get codec chan map, err:%d\n",
2071 __func__, ret);
2072 goto end;
2073 }
Banajit Goswami9f923c32016-12-16 16:06:25 -08002074 if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_5_RX) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002075 pr_debug("%s: rx_5_ch=%d\n", __func__,
2076 msm_slim_5_rx_ch);
2077 rx_ch_count = msm_slim_5_rx_ch;
Banajit Goswami9f923c32016-12-16 16:06:25 -08002078 } else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_6_RX) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002079 pr_debug("%s: rx_6_ch=%d\n", __func__,
2080 msm_slim_6_rx_ch);
2081 rx_ch_count = msm_slim_6_rx_ch;
2082 } else {
2083 pr_debug("%s: rx_0_ch=%d\n", __func__,
2084 msm_slim_0_rx_ch);
2085 rx_ch_count = msm_slim_0_rx_ch;
2086 }
2087 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
2088 rx_ch_count, rx_ch);
2089 if (ret < 0) {
2090 pr_err("%s: failed to set cpu chan map, err:%d\n",
2091 __func__, ret);
2092 goto end;
2093 }
2094 } else {
2095
2096 pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
2097 codec_dai->name, codec_dai->id, user_set_tx_ch);
2098 ret = snd_soc_dai_get_channel_map(codec_dai,
2099 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
2100 if (ret < 0) {
2101 pr_err("%s: failed to get codec chan map\n, err:%d\n",
2102 __func__, ret);
2103 goto end;
2104 }
2105 /* For <codec>_tx1 case */
Banajit Goswami9f923c32016-12-16 16:06:25 -08002106 if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_0_TX)
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002107 user_set_tx_ch = msm_slim_0_tx_ch;
2108 /* For <codec>_tx3 case */
Banajit Goswami9f923c32016-12-16 16:06:25 -08002109 else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_1_TX)
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002110 user_set_tx_ch = msm_slim_1_tx_ch;
Banajit Goswami9f923c32016-12-16 16:06:25 -08002111 else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_3_TX)
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002112 /* DAI 5 is used for external EC reference from codec.
2113 * Since Rx is fed as reference for EC, the config of
2114 * this DAI is based on that of the Rx path.
2115 */
2116 user_set_tx_ch = msm_slim_0_rx_ch;
Banajit Goswami9f923c32016-12-16 16:06:25 -08002117 else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_4_TX)
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002118 user_set_tx_ch = msm_vi_feed_tx_ch;
2119 else
2120 user_set_tx_ch = tx_ch_cnt;
2121
Banajit Goswami9f923c32016-12-16 16:06:25 -08002122 pr_debug("%s: msm_slim_0_tx_ch(%d) user_set_tx_ch(%d) tx_ch_cnt(%d), BE id (%d)\n",
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002123 __func__, msm_slim_0_tx_ch, user_set_tx_ch,
Banajit Goswami9f923c32016-12-16 16:06:25 -08002124 tx_ch_cnt, dai_link->id);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002125
2126 ret = snd_soc_dai_set_channel_map(cpu_dai,
2127 user_set_tx_ch, tx_ch, 0, 0);
2128 if (ret < 0) {
2129 pr_err("%s: failed to set cpu chan map, err:%d\n",
2130 __func__, ret);
2131 goto end;
2132 }
2133 }
2134end:
2135 return ret;
2136}
2137
2138static int msm_snd_cpe_hw_params(struct snd_pcm_substream *substream,
2139 struct snd_pcm_hw_params *params)
2140{
2141 struct snd_soc_pcm_runtime *rtd = substream->private_data;
2142 struct snd_soc_dai *codec_dai = rtd->codec_dai;
2143 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
2144 struct snd_soc_dai_link *dai_link = rtd->dai_link;
2145
2146 int ret = 0;
2147 u32 tx_ch[SLIM_MAX_TX_PORTS];
2148 u32 tx_ch_cnt = 0;
2149 u32 user_set_tx_ch = 0;
2150
2151 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) {
2152 pr_err("%s: Invalid stream type %d\n",
2153 __func__, substream->stream);
2154 ret = -EINVAL;
2155 goto end;
2156 }
2157
2158 pr_debug("%s: %s_tx_dai_id_%d\n", __func__,
2159 codec_dai->name, codec_dai->id);
2160 ret = snd_soc_dai_get_channel_map(codec_dai,
2161 &tx_ch_cnt, tx_ch, NULL, NULL);
2162 if (ret < 0) {
2163 pr_err("%s: failed to get codec chan map\n, err:%d\n",
2164 __func__, ret);
2165 goto end;
2166 }
2167
2168 user_set_tx_ch = tx_ch_cnt;
2169
Banajit Goswami9f923c32016-12-16 16:06:25 -08002170 pr_debug("%s: tx_ch_cnt(%d) BE id %d\n",
2171 __func__, tx_ch_cnt, dai_link->id);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002172
2173 ret = snd_soc_dai_set_channel_map(cpu_dai,
2174 user_set_tx_ch, tx_ch, 0, 0);
2175 if (ret < 0)
2176 pr_err("%s: failed to set cpu chan map, err:%d\n",
2177 __func__, ret);
2178end:
2179 return ret;
2180}
2181
2182static struct snd_soc_ops msm8996_be_ops = {
2183 .hw_params = msm_snd_hw_params,
2184};
2185
2186static struct snd_soc_ops msm8996_cpe_ops = {
2187 .hw_params = msm_snd_cpe_hw_params,
2188};
2189
2190static int msm8996_slimbus_2_hw_params(struct snd_pcm_substream *substream,
2191 struct snd_pcm_hw_params *params)
2192{
2193 struct snd_soc_pcm_runtime *rtd = substream->private_data;
2194 struct snd_soc_dai *codec_dai = rtd->codec_dai;
2195 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
2196 int ret = 0;
2197 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
2198 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
2199 unsigned int num_tx_ch = 0;
2200 unsigned int num_rx_ch = 0;
2201
2202 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
2203 num_rx_ch = params_channels(params);
2204 pr_debug("%s: %s rx_dai_id = %d num_ch = %d\n", __func__,
2205 codec_dai->name, codec_dai->id, num_rx_ch);
2206 ret = snd_soc_dai_get_channel_map(codec_dai,
2207 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
2208 if (ret < 0) {
2209 pr_err("%s: failed to get codec chan map, err:%d\n",
2210 __func__, ret);
2211 goto end;
2212 }
2213 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
2214 num_rx_ch, rx_ch);
2215 if (ret < 0) {
2216 pr_err("%s: failed to set cpu chan map, err:%d\n",
2217 __func__, ret);
2218 goto end;
2219 }
2220 } else {
2221 num_tx_ch = params_channels(params);
2222 pr_debug("%s: %s tx_dai_id = %d num_ch = %d\n", __func__,
2223 codec_dai->name, codec_dai->id, num_tx_ch);
2224 ret = snd_soc_dai_get_channel_map(codec_dai,
2225 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
2226 if (ret < 0) {
2227 pr_err("%s: failed to get codec chan map, err:%d\n",
2228 __func__, ret);
2229 goto end;
2230 }
2231 ret = snd_soc_dai_set_channel_map(cpu_dai,
2232 num_tx_ch, tx_ch, 0, 0);
2233 if (ret < 0) {
2234 pr_err("%s: failed to set cpu chan map, err:%d\n",
2235 __func__, ret);
2236 goto end;
2237 }
2238 }
2239end:
2240 return ret;
2241}
2242
2243static struct snd_soc_ops msm8996_slimbus_2_be_ops = {
2244 .hw_params = msm8996_slimbus_2_hw_params,
2245};
2246
2247static int msm8996_get_ll_qos_val(struct snd_pcm_runtime *runtime)
2248{
2249 int usecs;
2250
2251 /* take 10% of period time as the deadline */
2252 usecs = (100000 / runtime->rate) * runtime->period_size;
2253 usecs += ((100000 % runtime->rate) * runtime->period_size) /
2254 runtime->rate;
2255
2256 return usecs;
2257}
2258
2259static int msm8996_mm5_prepare(struct snd_pcm_substream *substream)
2260{
2261 if (pm_qos_request_active(&substream->latency_pm_qos_req))
2262 pm_qos_remove_request(&substream->latency_pm_qos_req);
2263 pm_qos_add_request(&substream->latency_pm_qos_req,
2264 PM_QOS_CPU_DMA_LATENCY,
2265 msm8996_get_ll_qos_val(substream->runtime));
2266 return 0;
2267}
2268
2269static struct snd_soc_ops msm8996_mm5_ops = {
2270 .prepare = msm8996_mm5_prepare,
2271};
2272
2273/* Digital audio interface glue - connects codec <---> CPU */
2274static struct snd_soc_dai_link msm8996_common_dai_links[] = {
2275 /* FrontEnd DAI Links */
2276 {
2277 .name = "MSM8996 Media1",
2278 .stream_name = "MultiMedia1",
2279 .cpu_dai_name = "MultiMedia1",
2280 .platform_name = "msm-pcm-dsp.0",
2281 .dynamic = 1,
2282 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
2283 .dpcm_playback = 1,
2284 .dpcm_capture = 1,
2285 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2286 SND_SOC_DPCM_TRIGGER_POST},
2287 .codec_dai_name = "snd-soc-dummy-dai",
2288 .codec_name = "snd-soc-dummy",
2289 .ignore_suspend = 1,
2290 /* this dainlink has playback support */
2291 .ignore_pmdown_time = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08002292 .id = MSM_FRONTEND_DAI_MULTIMEDIA1
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002293 },
2294 {
2295 .name = "MSM8996 Media2",
2296 .stream_name = "MultiMedia2",
2297 .cpu_dai_name = "MultiMedia2",
2298 .platform_name = "msm-pcm-dsp.0",
2299 .dynamic = 1,
2300 .dpcm_playback = 1,
2301 .dpcm_capture = 1,
2302 .codec_dai_name = "snd-soc-dummy-dai",
2303 .codec_name = "snd-soc-dummy",
2304 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2305 SND_SOC_DPCM_TRIGGER_POST},
2306 .ignore_suspend = 1,
2307 /* this dainlink has playback support */
2308 .ignore_pmdown_time = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08002309 .id = MSM_FRONTEND_DAI_MULTIMEDIA2,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002310 },
2311 {
2312 .name = "VoiceMMode1",
2313 .stream_name = "VoiceMMode1",
2314 .cpu_dai_name = "VoiceMMode1",
2315 .platform_name = "msm-pcm-voice",
2316 .dynamic = 1,
2317 .dpcm_playback = 1,
2318 .dpcm_capture = 1,
2319 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2320 SND_SOC_DPCM_TRIGGER_POST},
2321 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2322 .ignore_suspend = 1,
2323 .ignore_pmdown_time = 1,
2324 .codec_dai_name = "snd-soc-dummy-dai",
2325 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002326 .id = MSM_FRONTEND_DAI_VOICEMMODE1,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002327 },
2328 {
2329 .name = "MSM VoIP",
2330 .stream_name = "VoIP",
2331 .cpu_dai_name = "VoIP",
2332 .platform_name = "msm-voip-dsp",
2333 .dynamic = 1,
2334 .dpcm_playback = 1,
2335 .dpcm_capture = 1,
2336 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2337 SND_SOC_DPCM_TRIGGER_POST},
2338 .codec_dai_name = "snd-soc-dummy-dai",
2339 .codec_name = "snd-soc-dummy",
2340 .ignore_suspend = 1,
2341 /* this dainlink has playback support */
2342 .ignore_pmdown_time = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08002343 .id = MSM_FRONTEND_DAI_VOIP,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002344 },
2345 {
2346 .name = "MSM8996 ULL",
2347 .stream_name = "MultiMedia3",
2348 .cpu_dai_name = "MultiMedia3",
2349 .platform_name = "msm-pcm-dsp.2",
2350 .dynamic = 1,
2351 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
2352 .dpcm_playback = 1,
2353 .dpcm_capture = 1,
2354 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2355 SND_SOC_DPCM_TRIGGER_POST},
2356 .codec_dai_name = "snd-soc-dummy-dai",
2357 .codec_name = "snd-soc-dummy",
2358 .ignore_suspend = 1,
2359 /* this dainlink has playback support */
2360 .ignore_pmdown_time = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08002361 .id = MSM_FRONTEND_DAI_MULTIMEDIA3,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002362 },
2363 /* Hostless PCM purpose */
2364 {
2365 .name = "SLIMBUS_0 Hostless",
2366 .stream_name = "SLIMBUS_0 Hostless",
2367 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
2368 .platform_name = "msm-pcm-hostless",
2369 .dynamic = 1,
2370 .dpcm_playback = 1,
2371 .dpcm_capture = 1,
2372 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2373 SND_SOC_DPCM_TRIGGER_POST},
2374 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2375 .ignore_suspend = 1,
2376 /* this dailink has playback support */
2377 .ignore_pmdown_time = 1,
2378 .codec_dai_name = "snd-soc-dummy-dai",
2379 .codec_name = "snd-soc-dummy",
2380 },
2381 {
2382 .name = "Tertiary MI2S TX_Hostless",
2383 .stream_name = "Tertiary MI2S_TX Hostless Capture",
2384 .cpu_dai_name = "TERT_MI2S_TX_HOSTLESS",
2385 .platform_name = "msm-pcm-hostless",
2386 .dynamic = 1,
2387 .dpcm_capture = 1,
2388 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2389 SND_SOC_DPCM_TRIGGER_POST},
2390 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2391 .ignore_suspend = 1,
2392 .ignore_pmdown_time = 1,
2393 .codec_dai_name = "snd-soc-dummy-dai",
2394 .codec_name = "snd-soc-dummy",
2395 },
2396 {
2397 .name = "MSM AFE-PCM RX",
2398 .stream_name = "AFE-PROXY RX",
2399 .cpu_dai_name = "msm-dai-q6-dev.241",
2400 .codec_name = "msm-stub-codec.1",
2401 .codec_dai_name = "msm-stub-rx",
2402 .platform_name = "msm-pcm-afe",
2403 .ignore_suspend = 1,
2404 /* this dainlink has playback support */
2405 .ignore_pmdown_time = 1,
2406 },
2407 {
2408 .name = "MSM AFE-PCM TX",
2409 .stream_name = "AFE-PROXY TX",
2410 .cpu_dai_name = "msm-dai-q6-dev.240",
2411 .codec_name = "msm-stub-codec.1",
2412 .codec_dai_name = "msm-stub-tx",
2413 .platform_name = "msm-pcm-afe",
2414 .ignore_suspend = 1,
2415 },
2416 {
2417 .name = "MSM8996 Compress1",
2418 .stream_name = "Compress1",
2419 .cpu_dai_name = "MultiMedia4",
2420 .platform_name = "msm-compress-dsp",
2421 .dynamic = 1,
2422 .async_ops = ASYNC_DPCM_SND_SOC_HW_PARAMS,
2423 .dpcm_playback = 1,
2424 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2425 SND_SOC_DPCM_TRIGGER_POST},
2426 .codec_dai_name = "snd-soc-dummy-dai",
2427 .codec_name = "snd-soc-dummy",
2428 .ignore_suspend = 1,
2429 .ignore_pmdown_time = 1,
2430 /* this dainlink has playback support */
Banajit Goswami9f923c32016-12-16 16:06:25 -08002431 .id = MSM_FRONTEND_DAI_MULTIMEDIA4,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002432 },
2433 {
2434 .name = "AUXPCM Hostless",
2435 .stream_name = "AUXPCM Hostless",
2436 .cpu_dai_name = "AUXPCM_HOSTLESS",
2437 .platform_name = "msm-pcm-hostless",
2438 .dynamic = 1,
2439 .dpcm_playback = 1,
2440 .dpcm_capture = 1,
2441 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2442 SND_SOC_DPCM_TRIGGER_POST},
2443 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2444 .ignore_suspend = 1,
2445 /* this dainlink has playback support */
2446 .ignore_pmdown_time = 1,
2447 .codec_dai_name = "snd-soc-dummy-dai",
2448 .codec_name = "snd-soc-dummy",
2449 },
2450 {
2451 .name = "SLIMBUS_1 Hostless",
2452 .stream_name = "SLIMBUS_1 Hostless",
2453 .cpu_dai_name = "SLIMBUS1_HOSTLESS",
2454 .platform_name = "msm-pcm-hostless",
2455 .dynamic = 1,
2456 .dpcm_playback = 1,
2457 .dpcm_capture = 1,
2458 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2459 SND_SOC_DPCM_TRIGGER_POST},
2460 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2461 .ignore_suspend = 1,
2462 /* this dailink has playback support */
2463 .ignore_pmdown_time = 1,
2464 .codec_dai_name = "snd-soc-dummy-dai",
2465 .codec_name = "snd-soc-dummy",
2466 },
2467 {
2468 .name = "SLIMBUS_3 Hostless",
2469 .stream_name = "SLIMBUS_3 Hostless",
2470 .cpu_dai_name = "SLIMBUS3_HOSTLESS",
2471 .platform_name = "msm-pcm-hostless",
2472 .dynamic = 1,
2473 .dpcm_playback = 1,
2474 .dpcm_capture = 1,
2475 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2476 SND_SOC_DPCM_TRIGGER_POST},
2477 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2478 .ignore_suspend = 1,
2479 /* this dailink has playback support */
2480 .ignore_pmdown_time = 1,
2481 .codec_dai_name = "snd-soc-dummy-dai",
2482 .codec_name = "snd-soc-dummy",
2483 },
2484 {
2485 .name = "SLIMBUS_4 Hostless",
2486 .stream_name = "SLIMBUS_4 Hostless",
2487 .cpu_dai_name = "SLIMBUS4_HOSTLESS",
2488 .platform_name = "msm-pcm-hostless",
2489 .dynamic = 1,
2490 .dpcm_playback = 1,
2491 .dpcm_capture = 1,
2492 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2493 SND_SOC_DPCM_TRIGGER_POST},
2494 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2495 .ignore_suspend = 1,
2496 /* this dailink has playback support */
2497 .ignore_pmdown_time = 1,
2498 .codec_dai_name = "snd-soc-dummy-dai",
2499 .codec_name = "snd-soc-dummy",
2500 },
2501 {
2502 .name = "VoLTE",
2503 .stream_name = "VoLTE",
2504 .cpu_dai_name = "VoLTE",
2505 .platform_name = "msm-pcm-voice",
2506 .dynamic = 1,
2507 .dpcm_playback = 1,
2508 .dpcm_capture = 1,
2509 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2510 SND_SOC_DPCM_TRIGGER_POST},
2511 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2512 .ignore_suspend = 1,
2513 /* this dainlink has playback support */
2514 .ignore_pmdown_time = 1,
2515 .codec_dai_name = "snd-soc-dummy-dai",
2516 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002517 .id = MSM_FRONTEND_DAI_VOLTE,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002518 },
2519 {
2520 .name = "MSM8996 LowLatency",
2521 .stream_name = "MultiMedia5",
2522 .cpu_dai_name = "MultiMedia5",
2523 .platform_name = "msm-pcm-dsp.1",
2524 .dynamic = 1,
2525 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
2526 .dpcm_playback = 1,
2527 .dpcm_capture = 1,
2528 .codec_dai_name = "snd-soc-dummy-dai",
2529 .codec_name = "snd-soc-dummy",
2530 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2531 SND_SOC_DPCM_TRIGGER_POST},
2532 .ignore_suspend = 1,
2533 /* this dainlink has playback support */
2534 .ignore_pmdown_time = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08002535 .id = MSM_FRONTEND_DAI_MULTIMEDIA5,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002536 .ops = &msm8996_mm5_ops,
2537 },
2538 {
2539 .name = "Listen 1 Audio Service",
2540 .stream_name = "Listen 1 Audio Service",
2541 .cpu_dai_name = "LSM1",
2542 .platform_name = "msm-lsm-client",
2543 .dynamic = 1,
2544 .dpcm_capture = 1,
2545 .trigger = { SND_SOC_DPCM_TRIGGER_POST,
2546 SND_SOC_DPCM_TRIGGER_POST },
2547 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2548 .ignore_suspend = 1,
2549 .ignore_pmdown_time = 1,
2550 .codec_dai_name = "snd-soc-dummy-dai",
2551 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002552 .id = MSM_FRONTEND_DAI_LSM1,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002553 },
2554 /* Multiple Tunnel instances */
2555 {
2556 .name = "MSM8996 Compress2",
2557 .stream_name = "Compress2",
2558 .cpu_dai_name = "MultiMedia7",
2559 .platform_name = "msm-compress-dsp",
2560 .dynamic = 1,
2561 .dpcm_playback = 1,
2562 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2563 SND_SOC_DPCM_TRIGGER_POST},
2564 .codec_dai_name = "snd-soc-dummy-dai",
2565 .codec_name = "snd-soc-dummy",
2566 .ignore_suspend = 1,
2567 .ignore_pmdown_time = 1,
2568 /* this dainlink has playback support */
Banajit Goswami9f923c32016-12-16 16:06:25 -08002569 .id = MSM_FRONTEND_DAI_MULTIMEDIA7,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002570 },
2571 {
2572 .name = "MSM8996 Compress3",
2573 .stream_name = "Compress3",
2574 .cpu_dai_name = "MultiMedia10",
2575 .platform_name = "msm-compress-dsp",
2576 .dynamic = 1,
2577 .dpcm_playback = 1,
2578 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2579 SND_SOC_DPCM_TRIGGER_POST},
2580 .codec_dai_name = "snd-soc-dummy-dai",
2581 .codec_name = "snd-soc-dummy",
2582 .ignore_suspend = 1,
2583 .ignore_pmdown_time = 1,
2584 /* this dainlink has playback support */
Banajit Goswami9f923c32016-12-16 16:06:25 -08002585 .id = MSM_FRONTEND_DAI_MULTIMEDIA10,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002586 },
2587 {
2588 .name = "MSM8996 ULL NOIRQ",
2589 .stream_name = "MM_NOIRQ",
2590 .cpu_dai_name = "MultiMedia8",
2591 .platform_name = "msm-pcm-dsp-noirq",
2592 .dynamic = 1,
2593 .dpcm_playback = 1,
2594 .dpcm_capture = 1,
2595 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2596 SND_SOC_DPCM_TRIGGER_POST},
2597 .codec_dai_name = "snd-soc-dummy-dai",
2598 .codec_name = "snd-soc-dummy",
2599 .ignore_suspend = 1,
2600 .ignore_pmdown_time = 1,
2601 /* this dainlink has playback support */
Banajit Goswami9f923c32016-12-16 16:06:25 -08002602 .id = MSM_FRONTEND_DAI_MULTIMEDIA8,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002603 },
2604 {
2605 .name = "QCHAT",
2606 .stream_name = "QCHAT",
2607 .cpu_dai_name = "QCHAT",
2608 .platform_name = "msm-pcm-voice",
2609 .dynamic = 1,
2610 .dpcm_capture = 1,
2611 .dpcm_playback = 1,
2612 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2613 SND_SOC_DPCM_TRIGGER_POST},
2614 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2615 .ignore_suspend = 1,
2616 /* this dainlink has playback support */
2617 .ignore_pmdown_time = 1,
2618 .codec_dai_name = "snd-soc-dummy-dai",
2619 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002620 .id = MSM_FRONTEND_DAI_QCHAT,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002621 },
2622 /* HDMI Hostless */
2623 {
2624 .name = "HDMI_RX_HOSTLESS",
2625 .stream_name = "HDMI_RX_HOSTLESS",
2626 .cpu_dai_name = "HDMI_HOSTLESS",
2627 .platform_name = "msm-pcm-hostless",
2628 .dynamic = 1,
2629 .dpcm_playback = 1,
2630 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2631 SND_SOC_DPCM_TRIGGER_POST},
2632 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2633 .ignore_suspend = 1,
2634 .ignore_pmdown_time = 1,
2635 .codec_dai_name = "snd-soc-dummy-dai",
2636 .codec_name = "snd-soc-dummy",
2637 },
2638 {
2639 .name = "VoiceMMode2",
2640 .stream_name = "VoiceMMode2",
2641 .cpu_dai_name = "VoiceMMode2",
2642 .platform_name = "msm-pcm-voice",
2643 .dynamic = 1,
2644 .dpcm_playback = 1,
2645 .dpcm_capture = 1,
2646 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2647 SND_SOC_DPCM_TRIGGER_POST},
2648 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2649 .ignore_suspend = 1,
2650 .ignore_pmdown_time = 1,
2651 .codec_dai_name = "snd-soc-dummy-dai",
2652 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002653 .id = MSM_FRONTEND_DAI_VOICEMMODE2,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002654 },
2655 {
2656 .name = "INT_HFP_BT Hostless",
2657 .stream_name = "INT_HFP_BT Hostless",
2658 .cpu_dai_name = "INT_HFP_BT_HOSTLESS",
2659 .platform_name = "msm-pcm-hostless",
2660 .dynamic = 1,
2661 .dpcm_playback = 1,
2662 .dpcm_capture = 1,
2663 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2664 SND_SOC_DPCM_TRIGGER_POST},
2665 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2666 .ignore_suspend = 1,
2667 /* this dainlink has playback support */
2668 .ignore_pmdown_time = 1,
2669 .codec_dai_name = "snd-soc-dummy-dai",
2670 .codec_name = "snd-soc-dummy",
2671 },
2672 {
2673 .name = "MSM8996 HFP TX",
2674 .stream_name = "MultiMedia6",
2675 .cpu_dai_name = "MultiMedia6",
2676 .platform_name = "msm-pcm-loopback",
2677 .dynamic = 1,
2678 .dpcm_playback = 1,
2679 .dpcm_capture = 1,
2680 .codec_dai_name = "snd-soc-dummy-dai",
2681 .codec_name = "snd-soc-dummy",
2682 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2683 SND_SOC_DPCM_TRIGGER_POST},
2684 .ignore_suspend = 1,
2685 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2686 /* this dainlink has playback support */
2687 .ignore_pmdown_time = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08002688 .id = MSM_FRONTEND_DAI_MULTIMEDIA6,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002689 },
2690 /* LSM FE */
2691 {
2692 .name = "Listen 2 Audio Service",
2693 .stream_name = "Listen 2 Audio Service",
2694 .cpu_dai_name = "LSM2",
2695 .platform_name = "msm-lsm-client",
2696 .dynamic = 1,
2697 .dpcm_capture = 1,
2698 .trigger = { SND_SOC_DPCM_TRIGGER_POST,
2699 SND_SOC_DPCM_TRIGGER_POST },
2700 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2701 .ignore_suspend = 1,
2702 .ignore_pmdown_time = 1,
2703 .codec_dai_name = "snd-soc-dummy-dai",
2704 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002705 .id = MSM_FRONTEND_DAI_LSM2,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002706 },
2707 {
2708 .name = "Listen 3 Audio Service",
2709 .stream_name = "Listen 3 Audio Service",
2710 .cpu_dai_name = "LSM3",
2711 .platform_name = "msm-lsm-client",
2712 .dynamic = 1,
2713 .dpcm_capture = 1,
2714 .trigger = { SND_SOC_DPCM_TRIGGER_POST,
2715 SND_SOC_DPCM_TRIGGER_POST },
2716 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2717 .ignore_suspend = 1,
2718 .ignore_pmdown_time = 1,
2719 .codec_dai_name = "snd-soc-dummy-dai",
2720 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002721 .id = MSM_FRONTEND_DAI_LSM3,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002722 },
2723 {
2724 .name = "Listen 4 Audio Service",
2725 .stream_name = "Listen 4 Audio Service",
2726 .cpu_dai_name = "LSM4",
2727 .platform_name = "msm-lsm-client",
2728 .dynamic = 1,
2729 .dpcm_capture = 1,
2730 .trigger = { SND_SOC_DPCM_TRIGGER_POST,
2731 SND_SOC_DPCM_TRIGGER_POST },
2732 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2733 .ignore_suspend = 1,
2734 .ignore_pmdown_time = 1,
2735 .codec_dai_name = "snd-soc-dummy-dai",
2736 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002737 .id = MSM_FRONTEND_DAI_LSM4,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002738 },
2739 {
2740 .name = "Listen 5 Audio Service",
2741 .stream_name = "Listen 5 Audio Service",
2742 .cpu_dai_name = "LSM5",
2743 .platform_name = "msm-lsm-client",
2744 .dynamic = 1,
2745 .dpcm_capture = 1,
2746 .trigger = { SND_SOC_DPCM_TRIGGER_POST,
2747 SND_SOC_DPCM_TRIGGER_POST },
2748 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2749 .ignore_suspend = 1,
2750 .ignore_pmdown_time = 1,
2751 .codec_dai_name = "snd-soc-dummy-dai",
2752 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002753 .id = MSM_FRONTEND_DAI_LSM5,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002754 },
2755 {
2756 .name = "Listen 6 Audio Service",
2757 .stream_name = "Listen 6 Audio Service",
2758 .cpu_dai_name = "LSM6",
2759 .platform_name = "msm-lsm-client",
2760 .dynamic = 1,
2761 .dpcm_capture = 1,
2762 .trigger = { SND_SOC_DPCM_TRIGGER_POST,
2763 SND_SOC_DPCM_TRIGGER_POST },
2764 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2765 .ignore_suspend = 1,
2766 .ignore_pmdown_time = 1,
2767 .codec_dai_name = "snd-soc-dummy-dai",
2768 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002769 .id = MSM_FRONTEND_DAI_LSM6,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002770 },
2771 {
2772 .name = "Listen 7 Audio Service",
2773 .stream_name = "Listen 7 Audio Service",
2774 .cpu_dai_name = "LSM7",
2775 .platform_name = "msm-lsm-client",
2776 .dynamic = 1,
2777 .dpcm_capture = 1,
2778 .trigger = { SND_SOC_DPCM_TRIGGER_POST,
2779 SND_SOC_DPCM_TRIGGER_POST },
2780 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2781 .ignore_suspend = 1,
2782 .ignore_pmdown_time = 1,
2783 .codec_dai_name = "snd-soc-dummy-dai",
2784 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002785 .id = MSM_FRONTEND_DAI_LSM7,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002786 },
2787 {
2788 .name = "Listen 8 Audio Service",
2789 .stream_name = "Listen 8 Audio Service",
2790 .cpu_dai_name = "LSM8",
2791 .platform_name = "msm-lsm-client",
2792 .dynamic = 1,
2793 .dpcm_capture = 1,
2794 .trigger = { SND_SOC_DPCM_TRIGGER_POST,
2795 SND_SOC_DPCM_TRIGGER_POST },
2796 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2797 .ignore_suspend = 1,
2798 .ignore_pmdown_time = 1,
2799 .codec_dai_name = "snd-soc-dummy-dai",
2800 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002801 .id = MSM_FRONTEND_DAI_LSM8,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002802 },
2803 {
2804 .name = "MSM8996 Media9",
2805 .stream_name = "MultiMedia9",
2806 .cpu_dai_name = "MultiMedia9",
2807 .platform_name = "msm-pcm-dsp.0",
2808 .dynamic = 1,
2809 .dpcm_playback = 1,
2810 .dpcm_capture = 1,
2811 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2812 SND_SOC_DPCM_TRIGGER_POST},
2813 .codec_dai_name = "snd-soc-dummy-dai",
2814 .codec_name = "snd-soc-dummy",
2815 .ignore_suspend = 1,
2816 /* this dainlink has playback support */
2817 .ignore_pmdown_time = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08002818 .id = MSM_FRONTEND_DAI_MULTIMEDIA9,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002819 },
2820 {
2821 .name = "VoWLAN",
2822 .stream_name = "VoWLAN",
2823 .cpu_dai_name = "VoWLAN",
2824 .platform_name = "msm-pcm-voice",
2825 .dynamic = 1,
2826 .dpcm_playback = 1,
2827 .dpcm_capture = 1,
2828 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2829 SND_SOC_DPCM_TRIGGER_POST},
2830 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2831 .ignore_suspend = 1,
2832 .ignore_pmdown_time = 1,
2833 .codec_dai_name = "snd-soc-dummy-dai",
2834 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002835 .id = MSM_FRONTEND_DAI_VOWLAN,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002836 },
2837 {
2838 .name = "MSM8996 Compress4",
2839 .stream_name = "Compress4",
2840 .cpu_dai_name = "MultiMedia11",
2841 .platform_name = "msm-compress-dsp",
2842 .dynamic = 1,
2843 .dpcm_playback = 1,
2844 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2845 SND_SOC_DPCM_TRIGGER_POST},
2846 .codec_dai_name = "snd-soc-dummy-dai",
2847 .codec_name = "snd-soc-dummy",
2848 .ignore_suspend = 1,
2849 .ignore_pmdown_time = 1,
2850 /* this dainlink has playback support */
Banajit Goswami9f923c32016-12-16 16:06:25 -08002851 .id = MSM_FRONTEND_DAI_MULTIMEDIA11,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002852 },
2853 {
2854 .name = "MSM8996 Compress5",
2855 .stream_name = "Compress5",
2856 .cpu_dai_name = "MultiMedia12",
2857 .platform_name = "msm-compress-dsp",
2858 .dynamic = 1,
2859 .dpcm_playback = 1,
2860 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2861 SND_SOC_DPCM_TRIGGER_POST},
2862 .codec_dai_name = "snd-soc-dummy-dai",
2863 .codec_name = "snd-soc-dummy",
2864 .ignore_suspend = 1,
2865 .ignore_pmdown_time = 1,
2866 /* this dainlink has playback support */
Banajit Goswami9f923c32016-12-16 16:06:25 -08002867 .id = MSM_FRONTEND_DAI_MULTIMEDIA12,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002868 },
2869 {
2870 .name = "MSM8996 Compress6",
2871 .stream_name = "Compress6",
2872 .cpu_dai_name = "MultiMedia13",
2873 .platform_name = "msm-compress-dsp",
2874 .dynamic = 1,
2875 .dpcm_playback = 1,
2876 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2877 SND_SOC_DPCM_TRIGGER_POST},
2878 .codec_dai_name = "snd-soc-dummy-dai",
2879 .codec_name = "snd-soc-dummy",
2880 .ignore_suspend = 1,
2881 .ignore_pmdown_time = 1,
2882 /* this dainlink has playback support */
Banajit Goswami9f923c32016-12-16 16:06:25 -08002883 .id = MSM_FRONTEND_DAI_MULTIMEDIA13,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002884 },
2885 {
2886 .name = "MSM8996 Compress7",
2887 .stream_name = "Compress7",
2888 .cpu_dai_name = "MultiMedia14",
2889 .platform_name = "msm-compress-dsp",
2890 .dynamic = 1,
2891 .dpcm_playback = 1,
2892 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2893 SND_SOC_DPCM_TRIGGER_POST},
2894 .codec_dai_name = "snd-soc-dummy-dai",
2895 .codec_name = "snd-soc-dummy",
2896 .ignore_suspend = 1,
2897 .ignore_pmdown_time = 1,
2898 /* this dainlink has playback support */
Banajit Goswami9f923c32016-12-16 16:06:25 -08002899 .id = MSM_FRONTEND_DAI_MULTIMEDIA14,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002900 },
2901 {
2902 .name = "MSM8996 Compress8",
2903 .stream_name = "Compress8",
2904 .cpu_dai_name = "MultiMedia15",
2905 .platform_name = "msm-compress-dsp",
2906 .dynamic = 1,
2907 .dpcm_playback = 1,
2908 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2909 SND_SOC_DPCM_TRIGGER_POST},
2910 .codec_dai_name = "snd-soc-dummy-dai",
2911 .codec_name = "snd-soc-dummy",
2912 .ignore_suspend = 1,
2913 .ignore_pmdown_time = 1,
2914 /* this dainlink has playback support */
Banajit Goswami9f923c32016-12-16 16:06:25 -08002915 .id = MSM_FRONTEND_DAI_MULTIMEDIA15,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002916 },
2917 {
Haynes Mathew George829508702017-07-05 15:39:25 -07002918 .name = "MSM8996 ULL NOIRQ_2",
2919 .stream_name = "MM_NOIRQ_2",
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002920 .cpu_dai_name = "MultiMedia16",
Haynes Mathew George829508702017-07-05 15:39:25 -07002921 .platform_name = "msm-pcm-dsp-noirq",
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002922 .dynamic = 1,
2923 .dpcm_playback = 1,
Haynes Mathew George829508702017-07-05 15:39:25 -07002924 .dpcm_capture = 1,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002925 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2926 SND_SOC_DPCM_TRIGGER_POST},
2927 .codec_dai_name = "snd-soc-dummy-dai",
2928 .codec_name = "snd-soc-dummy",
2929 .ignore_suspend = 1,
2930 .ignore_pmdown_time = 1,
2931 /* this dainlink has playback support */
Banajit Goswami9f923c32016-12-16 16:06:25 -08002932 .id = MSM_FRONTEND_DAI_MULTIMEDIA16,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002933 },
2934 {
2935 .name = "Circuit-Switch Voice",
2936 .stream_name = "CS-Voice",
2937 .cpu_dai_name = "CS-VOICE",
2938 .platform_name = "msm-pcm-voice",
2939 .dynamic = 1,
2940 .dpcm_playback = 1,
2941 .dpcm_capture = 1,
2942 .codec_dai_name = "snd-soc-dummy-dai",
2943 .codec_name = "snd-soc-dummy",
2944 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2945 SND_SOC_DPCM_TRIGGER_POST},
2946 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2947 .ignore_suspend = 1,
2948 /* this dainlink has playback support */
2949 .ignore_pmdown_time = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08002950 .id = MSM_FRONTEND_DAI_CS_VOICE,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002951 },
2952 {
2953 .name = "Voice2",
2954 .stream_name = "Voice2",
2955 .cpu_dai_name = "Voice2",
2956 .platform_name = "msm-pcm-voice",
2957 .dynamic = 1,
2958 .dpcm_playback = 1,
2959 .dpcm_capture = 1,
2960 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2961 SND_SOC_DPCM_TRIGGER_POST},
2962 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2963 .ignore_suspend = 1,
2964 /* this dainlink has playback support */
2965 .ignore_pmdown_time = 1,
2966 .codec_dai_name = "snd-soc-dummy-dai",
2967 .codec_name = "snd-soc-dummy",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002968 .id = MSM_FRONTEND_DAI_VOICE2,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002969 },
2970};
2971
2972static struct snd_soc_dai_link msm8996_tasha_fe_dai_links[] = {
2973 {
2974 .name = LPASS_BE_SLIMBUS_4_TX,
2975 .stream_name = "Slimbus4 Capture",
2976 .cpu_dai_name = "msm-dai-q6-dev.16393",
2977 .platform_name = "msm-pcm-hostless",
2978 .codec_name = "tasha_codec",
2979 .codec_dai_name = "tasha_vifeedback",
Banajit Goswami9f923c32016-12-16 16:06:25 -08002980 .id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002981 .be_hw_params_fixup = msm_slim_4_tx_be_hw_params_fixup,
2982 .ops = &msm8996_be_ops,
2983 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2984 .ignore_suspend = 1,
2985 },
2986 /* Ultrasound RX DAI Link */
2987 {
2988 .name = "SLIMBUS_2 Hostless Playback",
2989 .stream_name = "SLIMBUS_2 Hostless Playback",
2990 .cpu_dai_name = "msm-dai-q6-dev.16388",
2991 .platform_name = "msm-pcm-hostless",
2992 .codec_name = "tasha_codec",
2993 .codec_dai_name = "tasha_rx2",
2994 .ignore_suspend = 1,
2995 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2996 .ops = &msm8996_slimbus_2_be_ops,
2997 },
2998 /* Ultrasound TX DAI Link */
2999 {
3000 .name = "SLIMBUS_2 Hostless Capture",
3001 .stream_name = "SLIMBUS_2 Hostless Capture",
3002 .cpu_dai_name = "msm-dai-q6-dev.16389",
3003 .platform_name = "msm-pcm-hostless",
3004 .codec_name = "tasha_codec",
3005 .codec_dai_name = "tasha_tx2",
3006 .ignore_suspend = 1,
3007 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
3008 .ops = &msm8996_slimbus_2_be_ops,
3009 },
3010 /* CPE LSM direct dai-link */
3011 {
3012 .name = "CPE Listen service",
3013 .stream_name = "CPE Listen Audio Service",
3014 .cpu_dai_name = "msm-dai-slim",
3015 .platform_name = "msm-cpe-lsm",
3016 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
3017 SND_SOC_DPCM_TRIGGER_POST},
3018 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
3019 .ignore_suspend = 1,
3020 .ignore_pmdown_time = 1,
3021 .codec_dai_name = "tasha_mad1",
3022 .codec_name = "tasha_codec",
3023 .ops = &msm8996_cpe_ops,
3024 },
3025 /* slimbus rx 6 hostless */
3026 {
3027 .name = "SLIMBUS_6 Hostless Playback",
3028 .stream_name = "SLIMBUS_6 Hostless",
3029 .cpu_dai_name = "SLIMBUS6_HOSTLESS",
3030 .platform_name = "msm-pcm-hostless",
3031 .dynamic = 1,
3032 .dpcm_playback = 1,
3033 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
3034 SND_SOC_DPCM_TRIGGER_POST},
3035 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
3036 .ignore_suspend = 1,
3037 /* this dailink has playback support */
3038 .ignore_pmdown_time = 1,
3039 .codec_dai_name = "snd-soc-dummy-dai",
3040 .codec_name = "snd-soc-dummy",
3041 },
3042 /* CPE LSM EC PP direct dai-link */
3043 {
3044 .name = "CPE Listen service ECPP",
3045 .stream_name = "CPE Listen Audio Service ECPP",
3046 .cpu_dai_name = "CPE_LSM_NOHOST",
3047 .platform_name = "msm-cpe-lsm.3",
3048 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
3049 SND_SOC_DPCM_TRIGGER_POST},
3050 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
3051 .ignore_suspend = 1,
3052 .ignore_pmdown_time = 1,
3053 .codec_dai_name = "tasha_cpe",
3054 .codec_name = "tasha_codec",
3055 },
3056};
3057
3058static struct snd_soc_dai_link msm8996_common_be_dai_links[] = {
3059 /* Backend AFE DAI Links */
3060 {
3061 .name = LPASS_BE_AFE_PCM_RX,
3062 .stream_name = "AFE Playback",
3063 .cpu_dai_name = "msm-dai-q6-dev.224",
3064 .platform_name = "msm-pcm-routing",
3065 .codec_name = "msm-stub-codec.1",
3066 .codec_dai_name = "msm-stub-rx",
3067 .no_pcm = 1,
3068 .dpcm_playback = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003069 .id = MSM_BACKEND_DAI_AFE_PCM_RX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003070 .be_hw_params_fixup = msm_proxy_rx_be_hw_params_fixup,
3071 /* this dainlink has playback support */
3072 .ignore_pmdown_time = 1,
3073 .ignore_suspend = 1,
3074 },
3075 {
3076 .name = LPASS_BE_AFE_PCM_TX,
3077 .stream_name = "AFE Capture",
3078 .cpu_dai_name = "msm-dai-q6-dev.225",
3079 .platform_name = "msm-pcm-routing",
3080 .codec_name = "msm-stub-codec.1",
3081 .codec_dai_name = "msm-stub-tx",
3082 .no_pcm = 1,
3083 .dpcm_capture = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003084 .id = MSM_BACKEND_DAI_AFE_PCM_TX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003085 .be_hw_params_fixup = msm_proxy_tx_be_hw_params_fixup,
3086 .ignore_suspend = 1,
3087 },
3088 /* Primary AUX PCM Backend DAI Links */
3089 {
3090 .name = LPASS_BE_AUXPCM_RX,
3091 .stream_name = "AUX PCM Playback",
3092 .cpu_dai_name = "msm-dai-q6-auxpcm.1",
3093 .platform_name = "msm-pcm-routing",
3094 .codec_name = "msm-stub-codec.1",
3095 .codec_dai_name = "msm-stub-rx",
3096 .no_pcm = 1,
3097 .dpcm_playback = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003098 .id = MSM_BACKEND_DAI_AUXPCM_RX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003099 .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
3100 .ignore_pmdown_time = 1,
3101 .ignore_suspend = 1,
3102 /* this dainlink has playback support */
3103 },
3104 {
3105 .name = LPASS_BE_AUXPCM_TX,
3106 .stream_name = "AUX PCM Capture",
3107 .cpu_dai_name = "msm-dai-q6-auxpcm.1",
3108 .platform_name = "msm-pcm-routing",
3109 .codec_name = "msm-stub-codec.1",
3110 .codec_dai_name = "msm-stub-tx",
3111 .no_pcm = 1,
3112 .dpcm_capture = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003113 .id = MSM_BACKEND_DAI_AUXPCM_TX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003114 .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
3115 .ignore_suspend = 1,
3116 },
3117 /* Incall Record Uplink BACK END DAI Link */
3118 {
3119 .name = LPASS_BE_INCALL_RECORD_TX,
3120 .stream_name = "Voice Uplink Capture",
3121 .cpu_dai_name = "msm-dai-q6-dev.32772",
3122 .platform_name = "msm-pcm-routing",
3123 .codec_name = "msm-stub-codec.1",
3124 .codec_dai_name = "msm-stub-tx",
3125 .no_pcm = 1,
3126 .dpcm_capture = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003127 .id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003128 .be_hw_params_fixup = msm_be_hw_params_fixup,
3129 .ignore_suspend = 1,
3130 },
3131 /* Incall Record Downlink BACK END DAI Link */
3132 {
3133 .name = LPASS_BE_INCALL_RECORD_RX,
3134 .stream_name = "Voice Downlink Capture",
3135 .cpu_dai_name = "msm-dai-q6-dev.32771",
3136 .platform_name = "msm-pcm-routing",
3137 .codec_name = "msm-stub-codec.1",
3138 .codec_dai_name = "msm-stub-tx",
3139 .no_pcm = 1,
3140 .dpcm_capture = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003141 .id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003142 .be_hw_params_fixup = msm_be_hw_params_fixup,
3143 .ignore_suspend = 1,
3144 },
3145 /* Incall Music BACK END DAI Link */
3146 {
3147 .name = LPASS_BE_VOICE_PLAYBACK_TX,
3148 .stream_name = "Voice Farend Playback",
3149 .cpu_dai_name = "msm-dai-q6-dev.32773",
3150 .platform_name = "msm-pcm-routing",
3151 .codec_name = "msm-stub-codec.1",
3152 .codec_dai_name = "msm-stub-rx",
3153 .no_pcm = 1,
3154 .dpcm_playback = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003155 .id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003156 .be_hw_params_fixup = msm_be_hw_params_fixup,
3157 .ignore_suspend = 1,
3158 },
3159 /* Incall Music 2 BACK END DAI Link */
3160 {
3161 .name = LPASS_BE_VOICE2_PLAYBACK_TX,
3162 .stream_name = "Voice2 Farend Playback",
3163 .cpu_dai_name = "msm-dai-q6-dev.32770",
3164 .platform_name = "msm-pcm-routing",
3165 .codec_name = "msm-stub-codec.1",
3166 .codec_dai_name = "msm-stub-rx",
3167 .no_pcm = 1,
3168 .dpcm_playback = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003169 .id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003170 .be_hw_params_fixup = msm_be_hw_params_fixup,
3171 .ignore_suspend = 1,
3172 },
3173 {
3174 .name = LPASS_BE_TERT_MI2S_TX,
3175 .stream_name = "Tertiary MI2S Capture",
3176 .cpu_dai_name = "msm-dai-q6-mi2s.2",
3177 .platform_name = "msm-pcm-routing",
3178 .codec_name = "msm-stub-codec.1",
3179 .codec_dai_name = "msm-stub-tx",
3180 .no_pcm = 1,
3181 .dpcm_capture = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003182 .id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003183 .be_hw_params_fixup = msm_tx_be_hw_params_fixup,
3184 .ops = &msm8996_mi2s_be_ops,
3185 .ignore_suspend = 1,
3186 }
3187};
3188
3189static struct snd_soc_dai_link msm8996_tasha_be_dai_links[] = {
3190 /* Backend DAI Links */
3191 {
3192 .name = LPASS_BE_SLIMBUS_0_RX,
3193 .stream_name = "Slimbus Playback",
3194 .cpu_dai_name = "msm-dai-q6-dev.16384",
3195 .platform_name = "msm-pcm-routing",
3196 .codec_name = "tasha_codec",
3197 .codec_dai_name = "tasha_mix_rx1",
3198 .no_pcm = 1,
3199 .dpcm_playback = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003200 .id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003201 .init = &msm_audrx_init,
3202 .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
3203 /* this dainlink has playback support */
3204 .ignore_pmdown_time = 1,
3205 .ignore_suspend = 1,
3206 .ops = &msm8996_be_ops,
3207 },
3208 {
3209 .name = LPASS_BE_SLIMBUS_0_TX,
3210 .stream_name = "Slimbus Capture",
3211 .cpu_dai_name = "msm-dai-q6-dev.16385",
3212 .platform_name = "msm-pcm-routing",
3213 .codec_name = "tasha_codec",
3214 .codec_dai_name = "tasha_tx1",
3215 .no_pcm = 1,
3216 .dpcm_capture = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003217 .id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003218 .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
3219 .ignore_suspend = 1,
3220 .ops = &msm8996_be_ops,
3221 },
3222 {
3223 .name = LPASS_BE_SLIMBUS_1_RX,
3224 .stream_name = "Slimbus1 Playback",
3225 .cpu_dai_name = "msm-dai-q6-dev.16386",
3226 .platform_name = "msm-pcm-routing",
3227 .codec_name = "tasha_codec",
3228 .codec_dai_name = "tasha_mix_rx1",
3229 .no_pcm = 1,
3230 .dpcm_playback = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003231 .id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003232 .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
3233 .ops = &msm8996_be_ops,
3234 /* dai link has playback support */
3235 .ignore_pmdown_time = 1,
3236 .ignore_suspend = 1,
3237 },
3238 {
3239 .name = LPASS_BE_SLIMBUS_1_TX,
3240 .stream_name = "Slimbus1 Capture",
3241 .cpu_dai_name = "msm-dai-q6-dev.16387",
3242 .platform_name = "msm-pcm-routing",
3243 .codec_name = "tasha_codec",
3244 .codec_dai_name = "tasha_tx3",
3245 .no_pcm = 1,
3246 .dpcm_capture = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003247 .id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003248 .be_hw_params_fixup = msm_slim_1_tx_be_hw_params_fixup,
3249 .ops = &msm8996_be_ops,
3250 .ignore_suspend = 1,
3251 },
3252 {
3253 .name = LPASS_BE_SLIMBUS_3_RX,
3254 .stream_name = "Slimbus3 Playback",
3255 .cpu_dai_name = "msm-dai-q6-dev.16390",
3256 .platform_name = "msm-pcm-routing",
3257 .codec_name = "tasha_codec",
3258 .codec_dai_name = "tasha_mix_rx1",
3259 .no_pcm = 1,
3260 .dpcm_playback = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003261 .id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003262 .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
3263 .ops = &msm8996_be_ops,
3264 /* dai link has playback support */
3265 .ignore_pmdown_time = 1,
3266 .ignore_suspend = 1,
3267 },
3268 {
3269 .name = LPASS_BE_SLIMBUS_3_TX,
3270 .stream_name = "Slimbus3 Capture",
3271 .cpu_dai_name = "msm-dai-q6-dev.16391",
3272 .platform_name = "msm-pcm-routing",
3273 .codec_name = "tasha_codec",
3274 .codec_dai_name = "tasha_tx1",
3275 .no_pcm = 1,
3276 .dpcm_capture = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003277 .id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003278 .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
3279 .ops = &msm8996_be_ops,
3280 .ignore_suspend = 1,
3281 },
3282 {
3283 .name = LPASS_BE_SLIMBUS_4_RX,
3284 .stream_name = "Slimbus4 Playback",
3285 .cpu_dai_name = "msm-dai-q6-dev.16392",
3286 .platform_name = "msm-pcm-routing",
3287 .codec_name = "tasha_codec",
3288 .codec_dai_name = "tasha_mix_rx1",
3289 .no_pcm = 1,
3290 .dpcm_playback = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003291 .id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003292 .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
3293 .ops = &msm8996_be_ops,
3294 /* dai link has playback support */
3295 .ignore_pmdown_time = 1,
3296 .ignore_suspend = 1,
3297 },
3298 {
3299 .name = LPASS_BE_SLIMBUS_5_RX,
3300 .stream_name = "Slimbus5 Playback",
3301 .cpu_dai_name = "msm-dai-q6-dev.16394",
3302 .platform_name = "msm-pcm-routing",
3303 .codec_name = "tasha_codec",
3304 .codec_dai_name = "tasha_rx3",
3305 .no_pcm = 1,
3306 .dpcm_playback = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003307 .id = MSM_BACKEND_DAI_SLIMBUS_5_RX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003308 .be_hw_params_fixup = msm_slim_5_rx_be_hw_params_fixup,
3309 .ops = &msm8996_be_ops,
3310 /* dai link has playback support */
3311 .ignore_pmdown_time = 1,
3312 .ignore_suspend = 1,
3313 },
3314 /* MAD BE */
3315 {
3316 .name = LPASS_BE_SLIMBUS_5_TX,
3317 .stream_name = "Slimbus5 Capture",
3318 .cpu_dai_name = "msm-dai-q6-dev.16395",
3319 .platform_name = "msm-pcm-routing",
3320 .codec_name = "tasha_codec",
3321 .codec_dai_name = "tasha_mad1",
3322 .no_pcm = 1,
3323 .dpcm_capture = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003324 .id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003325 .be_hw_params_fixup = msm_slim_5_tx_be_hw_params_fixup,
3326 .ops = &msm8996_be_ops,
3327 .ignore_suspend = 1,
3328 },
3329 {
3330 .name = LPASS_BE_SLIMBUS_6_RX,
3331 .stream_name = "Slimbus6 Playback",
3332 .cpu_dai_name = "msm-dai-q6-dev.16396",
3333 .platform_name = "msm-pcm-routing",
3334 .codec_name = "tasha_codec",
3335 .codec_dai_name = "tasha_rx4",
3336 .no_pcm = 1,
3337 .dpcm_playback = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003338 .id = MSM_BACKEND_DAI_SLIMBUS_6_RX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003339 .be_hw_params_fixup = msm_slim_6_rx_be_hw_params_fixup,
3340 .ops = &msm8996_be_ops,
3341 /* dai link has playback support */
3342 .ignore_pmdown_time = 1,
3343 .ignore_suspend = 1,
3344 },
3345};
3346
3347static struct snd_soc_dai_link msm8996_hdmi_dai_link[] = {
3348 /* HDMI BACK END DAI Link */
3349 {
3350 .name = LPASS_BE_HDMI,
3351 .stream_name = "HDMI Playback",
3352 .cpu_dai_name = "msm-dai-q6-hdmi.8",
3353 .platform_name = "msm-pcm-routing",
3354 .codec_name = "msm-hdmi-audio-codec-rx",
3355 .codec_dai_name = "msm_hdmi_audio_codec_rx_dai",
3356 .no_pcm = 1,
3357 .dpcm_playback = 1,
Banajit Goswami9f923c32016-12-16 16:06:25 -08003358 .id = MSM_BACKEND_DAI_HDMI_RX,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003359 .be_hw_params_fixup = msm8996_hdmi_be_hw_params_fixup,
3360 .ignore_pmdown_time = 1,
3361 .ignore_suspend = 1,
3362 },
3363};
3364
3365static struct snd_soc_dai_link msm8996_tasha_dai_links[
3366 ARRAY_SIZE(msm8996_common_dai_links) +
3367 ARRAY_SIZE(msm8996_tasha_fe_dai_links) +
3368 ARRAY_SIZE(msm8996_common_be_dai_links) +
3369 ARRAY_SIZE(msm8996_tasha_be_dai_links) +
3370 ARRAY_SIZE(msm8996_hdmi_dai_link)];
3371
3372static int msm8996_wsa881x_init(struct snd_soc_component *component)
3373{
3374 u8 spkleft_ports[WSA881X_MAX_SWR_PORTS] = {100, 101, 102, 106};
3375 u8 spkright_ports[WSA881X_MAX_SWR_PORTS] = {103, 104, 105, 107};
3376 unsigned int ch_rate[WSA881X_MAX_SWR_PORTS] = {2400, 600, 300, 1200};
3377 unsigned int ch_mask[WSA881X_MAX_SWR_PORTS] = {0x1, 0xF, 0x3, 0x3};
3378 struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
3379 struct msm8996_asoc_mach_data *pdata;
3380 struct snd_soc_dapm_context *dapm;
3381
3382 if (!codec) {
3383 pr_err("%s codec is NULL\n", __func__);
3384 return -EINVAL;
3385 }
3386
3387 dapm = snd_soc_codec_get_dapm(codec);
3388
3389 if (!strcmp(component->name_prefix, "SpkrLeft")) {
3390 dev_dbg(codec->dev, "%s: setting left ch map to codec %s\n",
3391 __func__, codec->component.name);
3392 wsa881x_set_channel_map(codec, &spkleft_ports[0],
3393 WSA881X_MAX_SWR_PORTS, &ch_mask[0],
3394 &ch_rate[0]);
3395 if (dapm->component) {
3396 snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft IN");
3397 snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft SPKR");
3398 }
3399 } else if (!strcmp(component->name_prefix, "SpkrRight")) {
3400 dev_dbg(codec->dev, "%s: setting right ch map to codec %s\n",
3401 __func__, codec->component.name);
3402 wsa881x_set_channel_map(codec, &spkright_ports[0],
3403 WSA881X_MAX_SWR_PORTS, &ch_mask[0],
3404 &ch_rate[0]);
3405 if (dapm->component) {
3406 snd_soc_dapm_ignore_suspend(dapm, "SpkrRight IN");
3407 snd_soc_dapm_ignore_suspend(dapm, "SpkrRight SPKR");
3408 }
3409 } else {
3410 dev_err(codec->dev, "%s: wrong codec name %s\n", __func__,
3411 codec->component.name);
3412 return -EINVAL;
3413 }
3414 pdata = snd_soc_card_get_drvdata(component->card);
3415 if (pdata && pdata->codec_root)
3416 wsa881x_codec_info_create_codec_entry(pdata->codec_root,
3417 codec);
3418
3419 return 0;
3420}
3421
3422struct snd_soc_card snd_soc_card_tasha_msm8996 = {
3423 .name = "msm8996-tasha-snd-card",
3424};
3425
3426static int msm8996_populate_dai_link_component_of_node(
3427 struct snd_soc_card *card)
3428{
3429 int i, index, ret = 0;
3430 struct device *cdev = card->dev;
3431 struct snd_soc_dai_link *dai_link = card->dai_link;
3432 struct device_node *np;
3433
3434 if (!cdev) {
3435 pr_err("%s: Sound card device memory NULL\n", __func__);
3436 return -ENODEV;
3437 }
3438
3439 for (i = 0; i < card->num_links; i++) {
3440 if (dai_link[i].platform_of_node && dai_link[i].cpu_of_node)
3441 continue;
3442
3443 /* populate platform_of_node for snd card dai links */
3444 if (dai_link[i].platform_name &&
3445 !dai_link[i].platform_of_node) {
3446 index = of_property_match_string(cdev->of_node,
3447 "asoc-platform-names",
3448 dai_link[i].platform_name);
3449 if (index < 0) {
3450 pr_err("%s: No match found for platform name: %s\n",
3451 __func__, dai_link[i].platform_name);
3452 ret = index;
3453 goto err;
3454 }
3455 np = of_parse_phandle(cdev->of_node, "asoc-platform",
3456 index);
3457 if (!np) {
3458 pr_err("%s: retrieving phandle for platform %s, index %d failed\n",
3459 __func__, dai_link[i].platform_name,
3460 index);
3461 ret = -ENODEV;
3462 goto err;
3463 }
3464 dai_link[i].platform_of_node = np;
3465 dai_link[i].platform_name = NULL;
3466 }
3467
3468 /* populate cpu_of_node for snd card dai links */
3469 if (dai_link[i].cpu_dai_name && !dai_link[i].cpu_of_node) {
3470 index = of_property_match_string(cdev->of_node,
3471 "asoc-cpu-names",
3472 dai_link[i].cpu_dai_name);
3473 if (index >= 0) {
3474 np = of_parse_phandle(cdev->of_node, "asoc-cpu",
3475 index);
3476 if (!np) {
3477 pr_err("%s: retrieving phandle for cpu dai %s failed\n",
3478 __func__,
3479 dai_link[i].cpu_dai_name);
3480 ret = -ENODEV;
3481 goto err;
3482 }
3483 dai_link[i].cpu_of_node = np;
3484 dai_link[i].cpu_dai_name = NULL;
3485 }
3486 }
3487
3488 /* populate codec_of_node for snd card dai links */
3489 if (dai_link[i].codec_name && !dai_link[i].codec_of_node) {
3490 index = of_property_match_string(cdev->of_node,
3491 "asoc-codec-names",
3492 dai_link[i].codec_name);
3493 if (index < 0)
3494 continue;
3495 np = of_parse_phandle(cdev->of_node, "asoc-codec",
3496 index);
3497 if (!np) {
3498 pr_err("%s: retrieving phandle for codec %s failed\n",
3499 __func__, dai_link[i].codec_name);
3500 ret = -ENODEV;
3501 goto err;
3502 }
3503 dai_link[i].codec_of_node = np;
3504 dai_link[i].codec_name = NULL;
3505 }
3506 }
3507
3508err:
3509 return ret;
3510}
3511
3512static int msm8996_prepare_us_euro(struct snd_soc_card *card)
3513{
3514 struct msm8996_asoc_mach_data *pdata =
3515 snd_soc_card_get_drvdata(card);
3516 int ret;
3517
3518 if (pdata->us_euro_gpio >= 0) {
3519 dev_dbg(card->dev, "%s: us_euro gpio request %d", __func__,
3520 pdata->us_euro_gpio);
3521 ret = gpio_request(pdata->us_euro_gpio, "TASHA_CODEC_US_EURO");
3522 if (ret) {
3523 dev_err(card->dev,
3524 "%s: Failed to request codec US/EURO gpio %d error %d\n",
3525 __func__, pdata->us_euro_gpio, ret);
3526 return ret;
3527 }
3528 }
3529
3530 return 0;
3531}
3532
3533static int msm8996_prepare_hifi(struct snd_soc_card *card)
3534{
3535 struct msm8996_asoc_mach_data *pdata =
3536 snd_soc_card_get_drvdata(card);
3537 int ret;
3538
3539 if (gpio_is_valid(pdata->hph_en1_gpio)) {
3540 dev_dbg(card->dev, "%s: hph_en1_gpio request %d\n", __func__,
3541 pdata->hph_en1_gpio);
3542 ret = gpio_request(pdata->hph_en1_gpio, "hph_en1_gpio");
3543 if (ret) {
3544 dev_err(card->dev,
3545 "%s: hph_en1_gpio request failed, ret:%d\n",
3546 __func__, ret);
3547 return ret;
3548 }
3549 }
3550 if (gpio_is_valid(pdata->hph_en0_gpio)) {
3551 dev_dbg(card->dev, "%s: hph_en0_gpio request %d\n", __func__,
3552 pdata->hph_en0_gpio);
3553 ret = gpio_request(pdata->hph_en0_gpio, "hph_en0_gpio");
3554 if (ret) {
3555 dev_err(card->dev,
3556 "%s: hph_en0_gpio request failed, ret:%d\n",
3557 __func__, ret);
3558 return ret;
3559 }
3560 }
3561 return 0;
3562}
3563
3564static const struct of_device_id msm8996_asoc_machine_of_match[] = {
3565 { .compatible = "qcom,msm8996-asoc-snd-tasha",
3566 .data = "tasha_codec"},
3567 {},
3568};
3569
3570static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
3571{
3572 struct snd_soc_card *card = NULL;
3573 struct snd_soc_dai_link *dailink;
3574 int len_1, len_2, len_3, len_4;
3575 const struct of_device_id *match;
3576
3577 match = of_match_node(msm8996_asoc_machine_of_match, dev->of_node);
3578 if (!match) {
3579 dev_err(dev, "%s: No DT match found for sound card\n",
3580 __func__);
3581 return NULL;
3582 }
3583
3584 if (!strcmp(match->data, "tasha_codec")) {
3585 card = &snd_soc_card_tasha_msm8996;
3586 len_1 = ARRAY_SIZE(msm8996_common_dai_links);
3587 len_2 = len_1 + ARRAY_SIZE(msm8996_tasha_fe_dai_links);
3588 len_3 = len_2 + ARRAY_SIZE(msm8996_common_be_dai_links);
3589
3590 memcpy(msm8996_tasha_dai_links,
3591 msm8996_common_dai_links,
3592 sizeof(msm8996_common_dai_links));
3593 memcpy(msm8996_tasha_dai_links + len_1,
3594 msm8996_tasha_fe_dai_links,
3595 sizeof(msm8996_tasha_fe_dai_links));
3596 memcpy(msm8996_tasha_dai_links + len_2,
3597 msm8996_common_be_dai_links,
3598 sizeof(msm8996_common_be_dai_links));
3599 memcpy(msm8996_tasha_dai_links + len_3,
3600 msm8996_tasha_be_dai_links,
3601 sizeof(msm8996_tasha_be_dai_links));
3602
3603 dailink = msm8996_tasha_dai_links;
3604 len_4 = len_3 + ARRAY_SIZE(msm8996_tasha_be_dai_links);
3605 }
3606
3607 if (of_property_read_bool(dev->of_node, "qcom,hdmi-audio-rx")) {
3608 dev_dbg(dev, "%s(): hdmi audio support present\n",
3609 __func__);
3610 memcpy(dailink + len_4, msm8996_hdmi_dai_link,
3611 sizeof(msm8996_hdmi_dai_link));
3612 len_4 += ARRAY_SIZE(msm8996_hdmi_dai_link);
3613 } else {
3614 dev_dbg(dev, "%s(): No hdmi audio support\n", __func__);
3615 }
3616
3617 if (card) {
3618 card->dai_link = dailink;
3619 card->num_links = len_4;
3620 }
3621
3622 return card;
3623}
3624
3625static int msm8996_init_wsa_dev(struct platform_device *pdev,
3626 struct snd_soc_card *card)
3627{
3628 struct device_node *wsa_of_node;
3629 u32 wsa_max_devs;
3630 u32 wsa_dev_cnt;
3631 char *dev_name_str = NULL;
3632 struct msm8996_wsa881x_dev_info *wsa881x_dev_info;
3633 const char *wsa_auxdev_name_prefix[1];
3634 int found = 0;
3635 int i;
3636 int ret;
3637
3638 /* Get maximum WSA device count for this platform */
3639 ret = of_property_read_u32(pdev->dev.of_node,
3640 "qcom,wsa-max-devs", &wsa_max_devs);
3641 if (ret) {
3642 dev_dbg(&pdev->dev,
3643 "%s: wsa-max-devs property missing in DT %s, ret = %d\n",
3644 __func__, pdev->dev.of_node->full_name, ret);
3645 return 0;
3646 }
3647 if (wsa_max_devs == 0) {
3648 dev_warn(&pdev->dev,
3649 "%s: Max WSA devices is 0 for this target?\n",
3650 __func__);
3651 return 0;
3652 }
3653
3654 /* Get count of WSA device phandles for this platform */
3655 wsa_dev_cnt = of_count_phandle_with_args(pdev->dev.of_node,
3656 "qcom,wsa-devs", NULL);
3657 if (wsa_dev_cnt == -ENOENT) {
3658 dev_warn(&pdev->dev, "%s: No wsa device defined in DT.\n",
3659 __func__);
3660 return 0;
3661 } else if (wsa_dev_cnt <= 0) {
3662 dev_err(&pdev->dev,
3663 "%s: Error reading wsa device from DT. wsa_dev_cnt = %d\n",
3664 __func__, wsa_dev_cnt);
3665 return -EINVAL;
3666 }
3667
3668 /*
3669 * Expect total phandles count to be NOT less than maximum possible
3670 * WSA count. However, if it is less, then assign same value to
3671 * max count as well.
3672 */
3673 if (wsa_dev_cnt < wsa_max_devs) {
3674 dev_dbg(&pdev->dev,
3675 "%s: wsa_max_devs = %d cannot exceed wsa_dev_cnt = %d\n",
3676 __func__, wsa_max_devs, wsa_dev_cnt);
3677 wsa_max_devs = wsa_dev_cnt;
3678 }
3679
3680 /* Make sure prefix string passed for each WSA device */
3681 ret = of_property_count_strings(pdev->dev.of_node,
3682 "qcom,wsa-aux-dev-prefix");
3683 if (ret != wsa_dev_cnt) {
3684 dev_err(&pdev->dev,
3685 "%s: expecting %d wsa prefix. Defined only %d in DT\n",
3686 __func__, wsa_dev_cnt, ret);
3687 return -EINVAL;
3688 }
3689
3690 /*
3691 * Alloc mem to store phandle and index info of WSA device, if already
3692 * registered with ALSA core
3693 */
3694 wsa881x_dev_info = devm_kcalloc(&pdev->dev, wsa_max_devs,
3695 sizeof(struct msm8996_wsa881x_dev_info),
3696 GFP_KERNEL);
3697 if (!wsa881x_dev_info)
3698 return -ENOMEM;
3699
3700 /*
3701 * search and check whether all WSA devices are already
3702 * registered with ALSA core or not. If found a node, store
3703 * the node and the index in a local array of struct for later
3704 * use.
3705 */
3706 for (i = 0; i < wsa_dev_cnt; i++) {
3707 wsa_of_node = of_parse_phandle(pdev->dev.of_node,
3708 "qcom,wsa-devs", i);
3709 if (unlikely(!wsa_of_node)) {
3710 /* we should not be here */
3711 dev_err(&pdev->dev,
3712 "%s: wsa dev node is not present\n",
3713 __func__);
3714 return -EINVAL;
3715 }
3716 if (soc_find_component(wsa_of_node, NULL)) {
3717 /* WSA device registered with ALSA core */
3718 wsa881x_dev_info[found].of_node = wsa_of_node;
3719 wsa881x_dev_info[found].index = i;
3720 found++;
3721 if (found == wsa_max_devs)
3722 break;
3723 }
3724 }
3725
3726 if (found < wsa_max_devs) {
3727 dev_dbg(&pdev->dev,
3728 "%s: failed to find %d components. Found only %d\n",
3729 __func__, wsa_max_devs, found);
3730 return -EPROBE_DEFER;
3731 }
3732 dev_info(&pdev->dev,
3733 "%s: found %d wsa881x devices registered with ALSA core\n",
3734 __func__, found);
3735
3736 card->num_aux_devs = wsa_max_devs;
3737 card->num_configs = wsa_max_devs;
3738
3739 /* Alloc array of AUX devs struct */
3740 msm8996_aux_dev = devm_kcalloc(&pdev->dev, card->num_aux_devs,
3741 sizeof(struct snd_soc_aux_dev),
3742 GFP_KERNEL);
3743 if (!msm8996_aux_dev)
3744 return -ENOMEM;
3745
3746 /* Alloc array of codec conf struct */
3747 msm8996_codec_conf = devm_kcalloc(&pdev->dev, card->num_aux_devs,
3748 sizeof(struct snd_soc_codec_conf),
3749 GFP_KERNEL);
3750 if (!msm8996_codec_conf)
3751 return -ENOMEM;
3752
3753 for (i = 0; i < card->num_aux_devs; i++) {
3754 dev_name_str = devm_kzalloc(&pdev->dev, DEV_NAME_STR_LEN,
3755 GFP_KERNEL);
3756 if (!dev_name_str)
3757 return -ENOMEM;
3758
3759 ret = of_property_read_string_index(pdev->dev.of_node,
3760 "qcom,wsa-aux-dev-prefix",
3761 wsa881x_dev_info[i].index,
3762 wsa_auxdev_name_prefix);
3763 if (ret) {
3764 dev_err(&pdev->dev,
3765 "%s: failed to read wsa aux dev prefix, ret = %d\n",
3766 __func__, ret);
3767 return -EINVAL;
3768 }
3769
3770 snprintf(dev_name_str, strlen("wsa881x.%d"), "wsa881x.%d", i);
3771 msm8996_aux_dev[i].name = dev_name_str;
3772 msm8996_aux_dev[i].codec_name = NULL;
3773 msm8996_aux_dev[i].codec_of_node =
3774 wsa881x_dev_info[i].of_node;
3775 msm8996_aux_dev[i].init = msm8996_wsa881x_init;
3776 msm8996_codec_conf[i].dev_name = NULL;
3777 msm8996_codec_conf[i].name_prefix = wsa_auxdev_name_prefix[0];
3778 msm8996_codec_conf[i].of_node =
3779 wsa881x_dev_info[i].of_node;
3780 }
3781 card->codec_conf = msm8996_codec_conf;
3782 card->aux_dev = msm8996_aux_dev;
3783
3784 return 0;
3785}
3786
3787static int msm8996_asoc_machine_probe(struct platform_device *pdev)
3788{
3789 struct snd_soc_card *card;
3790 struct msm8996_asoc_mach_data *pdata;
3791 const char *mbhc_audio_jack_type = NULL;
3792 char *mclk_freq_prop_name;
3793 const struct of_device_id *match;
3794 int ret;
3795
3796 if (!pdev->dev.of_node) {
3797 dev_err(&pdev->dev, "No platform supplied from device tree\n");
3798 return -EINVAL;
3799 }
3800
3801 pdata = devm_kzalloc(&pdev->dev,
3802 sizeof(struct msm8996_asoc_mach_data), GFP_KERNEL);
3803 if (!pdata)
3804 return -ENOMEM;
3805
3806 card = populate_snd_card_dailinks(&pdev->dev);
3807 if (!card) {
3808 dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__);
3809 ret = -EINVAL;
3810 goto err;
3811 }
3812 card->dev = &pdev->dev;
3813 platform_set_drvdata(pdev, card);
3814 snd_soc_card_set_drvdata(card, pdata);
3815
3816 ret = snd_soc_of_parse_card_name(card, "qcom,model");
3817 if (ret) {
3818 dev_err(&pdev->dev, "parse card name failed, err:%d\n",
3819 ret);
3820 goto err;
3821 }
3822
3823 ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing");
3824 if (ret) {
3825 dev_err(&pdev->dev, "parse audio routing failed, err:%d\n",
3826 ret);
3827 goto err;
3828 }
3829
3830 match = of_match_node(msm8996_asoc_machine_of_match,
3831 pdev->dev.of_node);
3832 if (!match) {
3833 dev_err(&pdev->dev, "%s: no matched codec is found.\n",
3834 __func__);
3835 goto err;
3836 }
3837
3838 mclk_freq_prop_name = "qcom,tasha-mclk-clk-freq";
3839
3840 ret = of_property_read_u32(pdev->dev.of_node,
3841 mclk_freq_prop_name, &pdata->mclk_freq);
3842 if (ret) {
3843 dev_err(&pdev->dev,
3844 "Looking up %s property in node %s failed, err%d\n",
3845 mclk_freq_prop_name,
3846 pdev->dev.of_node->full_name, ret);
3847 goto err;
3848 }
3849
3850 if (pdata->mclk_freq != CODEC_EXT_CLK_RATE) {
3851 dev_err(&pdev->dev, "unsupported mclk freq %u\n",
3852 pdata->mclk_freq);
3853 ret = -EINVAL;
3854 goto err;
3855 }
3856
3857 spdev = pdev;
3858
3859 ret = msm8996_populate_dai_link_component_of_node(card);
3860 if (ret) {
3861 ret = -EPROBE_DEFER;
3862 goto err;
3863 }
3864
3865 ret = msm8996_init_wsa_dev(pdev, card);
3866 if (ret)
3867 goto err;
3868
3869 pdata->hph_en1_gpio = of_get_named_gpio(pdev->dev.of_node,
3870 "qcom,hph-en1-gpio", 0);
3871 if (pdata->hph_en1_gpio < 0) {
3872 dev_dbg(&pdev->dev, "%s: %s property not found %d\n",
3873 __func__, "qcom,hph-en1-gpio", pdata->hph_en1_gpio);
3874 }
3875
3876 pdata->hph_en0_gpio = of_get_named_gpio(pdev->dev.of_node,
3877 "qcom,hph-en0-gpio", 0);
3878 if (pdata->hph_en0_gpio < 0) {
3879 dev_dbg(&pdev->dev, "%s: %s property not found %d\n",
3880 __func__, "qcom,hph-en0-gpio", pdata->hph_en0_gpio);
3881 }
3882 ret = msm8996_prepare_hifi(card);
3883 if (ret)
3884 dev_dbg(&pdev->dev, "msm8996_prepare_hifi failed (%d)\n",
3885 ret);
3886
3887 ret = snd_soc_register_card(card);
3888 if (ret == -EPROBE_DEFER) {
3889 if (codec_reg_done)
3890 ret = -EINVAL;
3891 goto err;
3892 } else if (ret) {
3893 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
3894 ret);
3895 goto err;
3896 }
3897 dev_info(&pdev->dev, "Sound card %s registered\n", card->name);
3898
3899 ret = of_property_read_string(pdev->dev.of_node,
3900 "qcom,mbhc-audio-jack-type", &mbhc_audio_jack_type);
3901 if (ret) {
3902 dev_dbg(&pdev->dev, "Looking up %s property in node %s failed",
3903 "qcom,mbhc-audio-jack-type",
3904 pdev->dev.of_node->full_name);
3905 dev_dbg(&pdev->dev, "Jack type properties set to default");
3906 } else {
3907 if (!strcmp(mbhc_audio_jack_type, "4-pole-jack"))
3908 dev_dbg(&pdev->dev, "This hardware has 4 pole jack");
3909 else if (!strcmp(mbhc_audio_jack_type, "5-pole-jack"))
3910 dev_dbg(&pdev->dev, "This hardware has 5 pole jack");
3911 else if (!strcmp(mbhc_audio_jack_type, "6-pole-jack"))
3912 dev_dbg(&pdev->dev, "This hardware has 6 pole jack");
3913 else
3914 dev_dbg(&pdev->dev, "Unknown value, set to default");
3915 }
3916 /*
3917 * Parse US-Euro gpio info from DT. Report no error if us-euro
3918 * entry is not found in DT file as some targets do not support
3919 * US-Euro detection
3920 */
3921 pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
3922 "qcom,us-euro-gpios", 0);
3923 if (pdata->us_euro_gpio < 0) {
3924 dev_info(&pdev->dev, "property %s not detected in node %s",
3925 "qcom,us-euro-gpios",
3926 pdev->dev.of_node->full_name);
3927 } else {
3928 dev_dbg(&pdev->dev, "%s detected %d",
3929 "qcom,us-euro-gpios", pdata->us_euro_gpio);
3930 wcd_mbhc_cfg.swap_gnd_mic = msm8996_swap_gnd_mic;
3931 }
3932
3933 ret = msm8996_prepare_us_euro(card);
3934 if (ret)
3935 dev_info(&pdev->dev, "msm8996_prepare_us_euro failed (%d)\n",
3936 ret);
3937 return 0;
3938err:
3939 if (pdata->us_euro_gpio > 0) {
3940 dev_dbg(&pdev->dev, "%s free us_euro gpio %d\n",
3941 __func__, pdata->us_euro_gpio);
3942 gpio_free(pdata->us_euro_gpio);
3943 pdata->us_euro_gpio = 0;
3944 }
3945 if (pdata->hph_en1_gpio > 0) {
3946 dev_dbg(&pdev->dev, "%s free hph_en1_gpio %d\n",
3947 __func__, pdata->hph_en1_gpio);
3948 gpio_free(pdata->hph_en1_gpio);
3949 pdata->hph_en1_gpio = 0;
3950 }
3951 if (pdata->hph_en0_gpio > 0) {
3952 dev_dbg(&pdev->dev, "%s free hph_en0_gpio %d\n",
3953 __func__, pdata->hph_en0_gpio);
3954 gpio_free(pdata->hph_en0_gpio);
3955 pdata->hph_en0_gpio = 0;
3956 }
3957 devm_kfree(&pdev->dev, pdata);
3958 return ret;
3959}
3960
3961static int msm8996_asoc_machine_remove(struct platform_device *pdev)
3962{
3963 struct snd_soc_card *card = platform_get_drvdata(pdev);
3964 struct msm8996_asoc_mach_data *pdata =
3965 snd_soc_card_get_drvdata(card);
3966
3967 if (gpio_is_valid(ext_us_amp_gpio))
3968 gpio_free(ext_us_amp_gpio);
3969
3970 gpio_free(pdata->us_euro_gpio);
3971 gpio_free(pdata->hph_en1_gpio);
3972 gpio_free(pdata->hph_en0_gpio);
3973
3974 if (msm8996_liquid_dock_dev != NULL) {
3975 switch_dev_unregister(&msm8996_liquid_dock_dev->audio_sdev);
3976
3977 if (msm8996_liquid_dock_dev->dock_plug_irq)
3978 free_irq(msm8996_liquid_dock_dev->dock_plug_irq,
3979 msm8996_liquid_dock_dev);
3980
3981 if (msm8996_liquid_dock_dev->dock_plug_gpio)
3982 gpio_free(msm8996_liquid_dock_dev->dock_plug_gpio);
3983
3984 kfree(msm8996_liquid_dock_dev);
3985 msm8996_liquid_dock_dev = NULL;
3986 }
3987 snd_soc_unregister_card(card);
3988
3989 return 0;
3990}
3991
3992static struct platform_driver msm8996_asoc_machine_driver = {
3993 .driver = {
3994 .name = DRV_NAME,
3995 .owner = THIS_MODULE,
3996 .pm = &snd_soc_pm_ops,
3997 .of_match_table = msm8996_asoc_machine_of_match,
3998 },
3999 .probe = msm8996_asoc_machine_probe,
4000 .remove = msm8996_asoc_machine_remove,
4001};
4002module_platform_driver(msm8996_asoc_machine_driver);
4003
4004MODULE_DESCRIPTION("ALSA SoC msm");
4005MODULE_LICENSE("GPL v2");
4006MODULE_ALIAS("platform:" DRV_NAME);
4007MODULE_DEVICE_TABLE(of, msm8996_asoc_machine_of_match);