blob: 91accff85fa1439f5b7b1aded3af510d2db8d420 [file] [log] [blame]
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/delay.h>
14#include <linux/of_gpio.h>
15#include <linux/platform_device.h>
16#include <linux/module.h>
17#include <sound/soc.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053020#include <dsp/q6core.h>
21#include <dsp/audio_notifier.h>
22#include "msm-pcm-routing-v2.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053023#include "sdm660-common.h"
24#include "sdm660-external.h"
Laxminath Kasam605b42f2017-08-01 22:02:15 +053025#include "codecs/wcd9335.h"
26#include "codecs/wcd934x/wcd934x.h"
27#include "codecs/wcd934x/wcd934x-mbhc.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053028
29#define SDM660_SPK_ON 1
30#define SDM660_SPK_OFF 0
31
32#define WCD9XXX_MBHC_DEF_BUTTONS 8
33#define WCD9XXX_MBHC_DEF_RLOADS 5
34#define CODEC_EXT_CLK_RATE 9600000
35#define ADSP_STATE_READY_TIMEOUT_MS 3000
36
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053037#define WSA8810_NAME_1 "wsa881x.20170211"
38#define WSA8810_NAME_2 "wsa881x.20170212"
39
40static int msm_ext_spk_control = 1;
41static struct wcd_mbhc_config *wcd_mbhc_cfg_ptr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053042
43struct msm_asoc_wcd93xx_codec {
44 void* (*get_afe_config_fn)(struct snd_soc_codec *codec,
45 enum afe_config_type config_type);
46 void (*mbhc_hs_detect_exit)(struct snd_soc_codec *codec);
47};
48
49static struct msm_asoc_wcd93xx_codec msm_codec_fn;
50static struct platform_device *spdev;
51
52static bool is_initial_boot;
53
54static void *def_ext_mbhc_cal(void);
55
56enum {
57 SLIM_RX_0 = 0,
58 SLIM_RX_1,
59 SLIM_RX_2,
60 SLIM_RX_3,
61 SLIM_RX_4,
62 SLIM_RX_5,
63 SLIM_RX_6,
64 SLIM_RX_7,
65 SLIM_RX_MAX,
66};
67
68enum {
69 SLIM_TX_0 = 0,
70 SLIM_TX_1,
71 SLIM_TX_2,
72 SLIM_TX_3,
73 SLIM_TX_4,
74 SLIM_TX_5,
75 SLIM_TX_6,
76 SLIM_TX_7,
77 SLIM_TX_8,
78 SLIM_TX_MAX,
79};
80
81struct dev_config {
82 u32 sample_rate;
83 u32 bit_format;
84 u32 channels;
85};
86
87/* Default configuration of slimbus channels */
88static struct dev_config slim_rx_cfg[] = {
89 [SLIM_RX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
90 [SLIM_RX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
91 [SLIM_RX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
92 [SLIM_RX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
93 [SLIM_RX_4] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
94 [SLIM_RX_5] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
95 [SLIM_RX_6] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
96 [SLIM_RX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
97};
98
99static struct dev_config slim_tx_cfg[] = {
100 [SLIM_TX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
101 [SLIM_TX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
102 [SLIM_TX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
103 [SLIM_TX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
104 [SLIM_TX_4] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
105 [SLIM_TX_5] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
106 [SLIM_TX_6] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
107 [SLIM_TX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
108 [SLIM_TX_8] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
109};
110
111static int msm_vi_feed_tx_ch = 2;
112static const char *const slim_rx_ch_text[] = {"One", "Two"};
113static const char *const slim_tx_ch_text[] = {"One", "Two", "Three", "Four",
114 "Five", "Six", "Seven",
115 "Eight"};
116static const char *const vi_feed_ch_text[] = {"One", "Two"};
117static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE",
118 "S32_LE"};
119static char const *slim_sample_rate_text[] = {"KHZ_8", "KHZ_16",
120 "KHZ_32", "KHZ_44P1", "KHZ_48",
121 "KHZ_88P2", "KHZ_96", "KHZ_176P4",
122 "KHZ_192", "KHZ_352P8", "KHZ_384"};
123static const char *const spk_function_text[] = {"Off", "On"};
Preetam Singh Ranawat66f1f212017-12-05 15:30:24 +0530124static char const *bt_sample_rate_text[] = {"KHZ_8", "KHZ_16",
125 "KHZ_44P1", "KHZ_48",
126 "KHZ_88P2", "KHZ_96"};
Preetam Singh Ranawatd79190a2018-06-25 15:59:23 +0530127static char const *bt_sample_rate_rx_text[] = {"KHZ_8", "KHZ_16",
128 "KHZ_44P1", "KHZ_48",
129 "KHZ_88P2", "KHZ_96"};
130static char const *bt_sample_rate_tx_text[] = {"KHZ_8", "KHZ_16",
131 "KHZ_44P1", "KHZ_48",
132 "KHZ_88P2", "KHZ_96"};
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530133static SOC_ENUM_SINGLE_EXT_DECL(spk_func_en, spk_function_text);
134static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_chs, slim_rx_ch_text);
135static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_chs, slim_rx_ch_text);
136static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_chs, slim_tx_ch_text);
137static SOC_ENUM_SINGLE_EXT_DECL(slim_1_tx_chs, slim_tx_ch_text);
138static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_chs, slim_rx_ch_text);
139static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_chs, slim_rx_ch_text);
140static SOC_ENUM_SINGLE_EXT_DECL(vi_feed_tx_chs, vi_feed_ch_text);
141static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_format, bit_format_text);
142static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_format, bit_format_text);
143static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_format, bit_format_text);
144static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_format, bit_format_text);
145static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_sample_rate, slim_sample_rate_text);
146static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_sample_rate, slim_sample_rate_text);
147static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text);
148static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_sample_rate, slim_sample_rate_text);
149static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_sample_rate, slim_sample_rate_text);
150static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
Preetam Singh Ranawatd79190a2018-06-25 15:59:23 +0530151static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_rx, bt_sample_rate_rx_text);
152static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_tx, bt_sample_rate_tx_text);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530153
154static int slim_get_sample_rate_val(int sample_rate)
155{
156 int sample_rate_val = 0;
157
158 switch (sample_rate) {
159 case SAMPLING_RATE_8KHZ:
160 sample_rate_val = 0;
161 break;
162 case SAMPLING_RATE_16KHZ:
163 sample_rate_val = 1;
164 break;
165 case SAMPLING_RATE_32KHZ:
166 sample_rate_val = 2;
167 break;
168 case SAMPLING_RATE_44P1KHZ:
169 sample_rate_val = 3;
170 break;
171 case SAMPLING_RATE_48KHZ:
172 sample_rate_val = 4;
173 break;
174 case SAMPLING_RATE_88P2KHZ:
175 sample_rate_val = 5;
176 break;
177 case SAMPLING_RATE_96KHZ:
178 sample_rate_val = 6;
179 break;
180 case SAMPLING_RATE_176P4KHZ:
181 sample_rate_val = 7;
182 break;
183 case SAMPLING_RATE_192KHZ:
184 sample_rate_val = 8;
185 break;
186 case SAMPLING_RATE_352P8KHZ:
187 sample_rate_val = 9;
188 break;
189 case SAMPLING_RATE_384KHZ:
190 sample_rate_val = 10;
191 break;
192 default:
193 sample_rate_val = 4;
194 break;
195 }
196 return sample_rate_val;
197}
198
199static int slim_get_sample_rate(int value)
200{
201 int sample_rate = 0;
202
203 switch (value) {
204 case 0:
205 sample_rate = SAMPLING_RATE_8KHZ;
206 break;
207 case 1:
208 sample_rate = SAMPLING_RATE_16KHZ;
209 break;
210 case 2:
211 sample_rate = SAMPLING_RATE_32KHZ;
212 break;
213 case 3:
214 sample_rate = SAMPLING_RATE_44P1KHZ;
215 break;
216 case 4:
217 sample_rate = SAMPLING_RATE_48KHZ;
218 break;
219 case 5:
220 sample_rate = SAMPLING_RATE_88P2KHZ;
221 break;
222 case 6:
223 sample_rate = SAMPLING_RATE_96KHZ;
224 break;
225 case 7:
226 sample_rate = SAMPLING_RATE_176P4KHZ;
227 break;
228 case 8:
229 sample_rate = SAMPLING_RATE_192KHZ;
230 break;
231 case 9:
232 sample_rate = SAMPLING_RATE_352P8KHZ;
233 break;
234 case 10:
235 sample_rate = SAMPLING_RATE_384KHZ;
236 break;
237 default:
238 sample_rate = SAMPLING_RATE_48KHZ;
239 break;
240 }
241 return sample_rate;
242}
243
244static int slim_get_bit_format_val(int bit_format)
245{
246 int val = 0;
247
248 switch (bit_format) {
249 case SNDRV_PCM_FORMAT_S32_LE:
250 val = 3;
251 break;
252 case SNDRV_PCM_FORMAT_S24_3LE:
253 val = 2;
254 break;
255 case SNDRV_PCM_FORMAT_S24_LE:
256 val = 1;
257 break;
258 case SNDRV_PCM_FORMAT_S16_LE:
259 default:
260 val = 0;
261 break;
262 }
263 return val;
264}
265
266static int slim_get_bit_format(int val)
267{
268 int bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
269
270 switch (val) {
271 case 0:
272 bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
273 break;
274 case 1:
275 bit_fmt = SNDRV_PCM_FORMAT_S24_LE;
276 break;
277 case 2:
278 bit_fmt = SNDRV_PCM_FORMAT_S24_3LE;
279 break;
280 case 3:
281 bit_fmt = SNDRV_PCM_FORMAT_S32_LE;
282 break;
283 default:
284 bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
285 break;
286 }
287 return bit_fmt;
288}
289
290static int slim_get_port_idx(struct snd_kcontrol *kcontrol)
291{
292 int port_id = 0;
293
294 if (strnstr(kcontrol->id.name, "SLIM_0_RX", sizeof("SLIM_0_RX")))
295 port_id = SLIM_RX_0;
296 else if (strnstr(kcontrol->id.name, "SLIM_2_RX", sizeof("SLIM_2_RX")))
297 port_id = SLIM_RX_2;
298 else if (strnstr(kcontrol->id.name, "SLIM_5_RX", sizeof("SLIM_5_RX")))
299 port_id = SLIM_RX_5;
300 else if (strnstr(kcontrol->id.name, "SLIM_6_RX", sizeof("SLIM_6_RX")))
301 port_id = SLIM_RX_6;
302 else if (strnstr(kcontrol->id.name, "SLIM_0_TX", sizeof("SLIM_0_TX")))
303 port_id = SLIM_TX_0;
304 else if (strnstr(kcontrol->id.name, "SLIM_1_TX", sizeof("SLIM_1_TX")))
305 port_id = SLIM_TX_1;
306 else {
307 pr_err("%s: unsupported channel: %s",
308 __func__, kcontrol->id.name);
309 return -EINVAL;
310 }
311
312 return port_id;
313}
314
315static int msm_bt_sample_rate_get(struct snd_kcontrol *kcontrol,
316 struct snd_ctl_elem_value *ucontrol)
317{
318 /*
319 * Slimbus_7_Rx/Tx sample rate values should always be in sync (same)
320 * when used for BT_SCO use case. Return either Rx or Tx sample rate
321 * value.
322 */
323 switch (slim_rx_cfg[SLIM_RX_7].sample_rate) {
Preetam Singh Ranawat66f1f212017-12-05 15:30:24 +0530324 case SAMPLING_RATE_96KHZ:
325 ucontrol->value.integer.value[0] = 5;
326 break;
327 case SAMPLING_RATE_88P2KHZ:
328 ucontrol->value.integer.value[0] = 4;
329 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530330 case SAMPLING_RATE_48KHZ:
Preetam Singh Ranawat66f1f212017-12-05 15:30:24 +0530331 ucontrol->value.integer.value[0] = 3;
332 break;
333 case SAMPLING_RATE_44P1KHZ:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530334 ucontrol->value.integer.value[0] = 2;
335 break;
336 case SAMPLING_RATE_16KHZ:
337 ucontrol->value.integer.value[0] = 1;
338 break;
339 case SAMPLING_RATE_8KHZ:
340 default:
341 ucontrol->value.integer.value[0] = 0;
342 break;
343 }
344 pr_debug("%s: sample rate = %d", __func__,
345 slim_rx_cfg[SLIM_RX_7].sample_rate);
346
347 return 0;
348}
349
350static int msm_bt_sample_rate_put(struct snd_kcontrol *kcontrol,
351 struct snd_ctl_elem_value *ucontrol)
352{
353 switch (ucontrol->value.integer.value[0]) {
354 case 1:
355 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_16KHZ;
356 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_16KHZ;
357 break;
358 case 2:
Preetam Singh Ranawat66f1f212017-12-05 15:30:24 +0530359 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
360 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
361 break;
362 case 3:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530363 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_48KHZ;
364 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_48KHZ;
365 break;
Preetam Singh Ranawat66f1f212017-12-05 15:30:24 +0530366 case 4:
367 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
368 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
369 break;
370 case 5:
371 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_96KHZ;
372 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_96KHZ;
373 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530374 case 0:
375 default:
376 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_8KHZ;
377 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_8KHZ;
378 break;
379 }
380 pr_debug("%s: sample rates: slim7_rx = %d, slim7_tx = %d, value = %d\n",
381 __func__,
382 slim_rx_cfg[SLIM_RX_7].sample_rate,
383 slim_tx_cfg[SLIM_TX_7].sample_rate,
384 ucontrol->value.enumerated.item[0]);
385
386 return 0;
387}
388
Preetam Singh Ranawatd79190a2018-06-25 15:59:23 +0530389static int msm_bt_sample_rate_rx_get(struct snd_kcontrol *kcontrol,
390 struct snd_ctl_elem_value *ucontrol)
391{
392 switch (slim_rx_cfg[SLIM_RX_7].sample_rate) {
393 case SAMPLING_RATE_96KHZ:
394 ucontrol->value.integer.value[0] = 5;
395 break;
396 case SAMPLING_RATE_88P2KHZ:
397 ucontrol->value.integer.value[0] = 4;
398 break;
399 case SAMPLING_RATE_48KHZ:
400 ucontrol->value.integer.value[0] = 3;
401 break;
402 case SAMPLING_RATE_44P1KHZ:
403 ucontrol->value.integer.value[0] = 2;
404 break;
405 case SAMPLING_RATE_16KHZ:
406 ucontrol->value.integer.value[0] = 1;
407 break;
408 case SAMPLING_RATE_8KHZ:
409 default:
410 ucontrol->value.integer.value[0] = 0;
411 break;
412 }
413 pr_debug("%s: sample rate = %d", __func__,
414 slim_rx_cfg[SLIM_RX_7].sample_rate);
415
416 return 0;
417}
418
419static int msm_bt_sample_rate_rx_put(struct snd_kcontrol *kcontrol,
420 struct snd_ctl_elem_value *ucontrol)
421{
422 switch (ucontrol->value.integer.value[0]) {
423 case 1:
424 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_16KHZ;
425 break;
426 case 2:
427 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
428 break;
429 case 3:
430 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_48KHZ;
431 break;
432 case 4:
433 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
434 break;
435 case 5:
436 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_96KHZ;
437 break;
438 case 0:
439 default:
440 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_8KHZ;
441 break;
442 }
443 pr_debug("%s: sample rates: slim7_rx = %d, value = %d\n",
444 __func__,
445 slim_rx_cfg[SLIM_RX_7].sample_rate,
446 ucontrol->value.enumerated.item[0]);
447
448 return 0;
449}
450
451static int msm_bt_sample_rate_tx_get(struct snd_kcontrol *kcontrol,
452 struct snd_ctl_elem_value *ucontrol)
453{
454 switch (slim_tx_cfg[SLIM_TX_7].sample_rate) {
455 case SAMPLING_RATE_96KHZ:
456 ucontrol->value.integer.value[0] = 5;
457 break;
458 case SAMPLING_RATE_88P2KHZ:
459 ucontrol->value.integer.value[0] = 4;
460 break;
461 case SAMPLING_RATE_48KHZ:
462 ucontrol->value.integer.value[0] = 3;
463 break;
464 case SAMPLING_RATE_44P1KHZ:
465 ucontrol->value.integer.value[0] = 2;
466 break;
467 case SAMPLING_RATE_16KHZ:
468 ucontrol->value.integer.value[0] = 1;
469 break;
470 case SAMPLING_RATE_8KHZ:
471 default:
472 ucontrol->value.integer.value[0] = 0;
473 break;
474 }
475 pr_debug("%s: sample rate = %d", __func__,
476 slim_tx_cfg[SLIM_TX_7].sample_rate);
477
478 return 0;
479}
480
481static int msm_bt_sample_rate_tx_put(struct snd_kcontrol *kcontrol,
482 struct snd_ctl_elem_value *ucontrol)
483{
484 switch (ucontrol->value.integer.value[0]) {
485 case 1:
486 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_16KHZ;
487 break;
488 case 2:
489 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
490 break;
491 case 3:
492 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_48KHZ;
493 break;
494 case 4:
495 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
496 break;
497 case 5:
498 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_96KHZ;
499 break;
500 case 0:
501 default:
502 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_8KHZ;
503 break;
504 }
505 pr_debug("%s: sample rates: slim7_tx = %d, value = %d\n",
506 __func__,
507 slim_tx_cfg[SLIM_TX_7].sample_rate,
508 ucontrol->value.enumerated.item[0]);
509
510 return 0;
511}
512
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530513static int slim_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
514 struct snd_ctl_elem_value *ucontrol)
515{
516 int ch_num = slim_get_port_idx(kcontrol);
517
518 if (ch_num < 0)
519 return ch_num;
520
521 ucontrol->value.enumerated.item[0] =
522 slim_get_sample_rate_val(slim_rx_cfg[ch_num].sample_rate);
523
524 pr_debug("%s: slim[%d]_rx_sample_rate = %d, item = %d\n", __func__,
525 ch_num, slim_rx_cfg[ch_num].sample_rate,
526 ucontrol->value.enumerated.item[0]);
527
528 return 0;
529}
530
531static int slim_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
532 struct snd_ctl_elem_value *ucontrol)
533{
534 int ch_num = slim_get_port_idx(kcontrol);
535
536 if (ch_num < 0)
537 return ch_num;
538
539 slim_rx_cfg[ch_num].sample_rate =
540 slim_get_sample_rate(ucontrol->value.enumerated.item[0]);
541
542 pr_debug("%s: slim[%d]_rx_sample_rate = %d, item = %d\n", __func__,
543 ch_num, slim_rx_cfg[ch_num].sample_rate,
544 ucontrol->value.enumerated.item[0]);
545
546 return 0;
547}
548
549static int slim_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
550 struct snd_ctl_elem_value *ucontrol)
551{
552 int ch_num = slim_get_port_idx(kcontrol);
553
554 if (ch_num < 0)
555 return ch_num;
556
557 ucontrol->value.enumerated.item[0] =
558 slim_get_sample_rate_val(slim_tx_cfg[ch_num].sample_rate);
559
560 pr_debug("%s: slim[%d]_tx_sample_rate = %d, item = %d\n", __func__,
561 ch_num, slim_tx_cfg[ch_num].sample_rate,
562 ucontrol->value.enumerated.item[0]);
563
564 return 0;
565}
566
567static int slim_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
568 struct snd_ctl_elem_value *ucontrol)
569{
570 int sample_rate = 0;
571 int ch_num = slim_get_port_idx(kcontrol);
572
573 if (ch_num < 0)
574 return ch_num;
575
576 sample_rate = slim_get_sample_rate(ucontrol->value.enumerated.item[0]);
577 if (sample_rate == SAMPLING_RATE_44P1KHZ) {
578 pr_err("%s: Unsupported sample rate %d: for Tx path\n",
579 __func__, sample_rate);
580 return -EINVAL;
581 }
582 slim_tx_cfg[ch_num].sample_rate = sample_rate;
583
584 pr_debug("%s: slim[%d]_tx_sample_rate = %d, value = %d\n", __func__,
585 ch_num, slim_tx_cfg[ch_num].sample_rate,
586 ucontrol->value.enumerated.item[0]);
587
588 return 0;
589}
590
591static int slim_rx_bit_format_get(struct snd_kcontrol *kcontrol,
592 struct snd_ctl_elem_value *ucontrol)
593{
594 int ch_num = slim_get_port_idx(kcontrol);
595
596 if (ch_num < 0)
597 return ch_num;
598
599 ucontrol->value.enumerated.item[0] =
600 slim_get_bit_format_val(slim_rx_cfg[ch_num].bit_format);
601
602 pr_debug("%s: slim[%d]_rx_bit_format = %d, ucontrol value = %d\n",
603 __func__, ch_num, slim_rx_cfg[ch_num].bit_format,
604 ucontrol->value.enumerated.item[0]);
605
606 return 0;
607}
608
609static int slim_rx_bit_format_put(struct snd_kcontrol *kcontrol,
610 struct snd_ctl_elem_value *ucontrol)
611{
612 int ch_num = slim_get_port_idx(kcontrol);
613
614 if (ch_num < 0)
615 return ch_num;
616
617 slim_rx_cfg[ch_num].bit_format =
618 slim_get_bit_format(ucontrol->value.enumerated.item[0]);
619
620 pr_debug("%s: slim[%d]_rx_bit_format = %d, ucontrol value = %d\n",
621 __func__, ch_num, slim_rx_cfg[ch_num].bit_format,
622 ucontrol->value.enumerated.item[0]);
623
624 return 0;
625}
626
627static int slim_tx_bit_format_get(struct snd_kcontrol *kcontrol,
628 struct snd_ctl_elem_value *ucontrol)
629{
630 int ch_num = slim_get_port_idx(kcontrol);
631
632 if (ch_num < 0)
633 return ch_num;
634
635 ucontrol->value.enumerated.item[0] =
636 slim_get_bit_format_val(slim_tx_cfg[ch_num].bit_format);
637
638 pr_debug("%s: slim[%d]_tx_bit_format = %d, ucontrol value = %d\n",
639 __func__, ch_num, slim_tx_cfg[ch_num].bit_format,
640 ucontrol->value.enumerated.item[0]);
641
642 return 0;
643}
644
645static int slim_tx_bit_format_put(struct snd_kcontrol *kcontrol,
646 struct snd_ctl_elem_value *ucontrol)
647{
648 int ch_num = slim_get_port_idx(kcontrol);
649
650 if (ch_num < 0)
651 return ch_num;
652
653 slim_tx_cfg[ch_num].bit_format =
654 slim_get_bit_format(ucontrol->value.enumerated.item[0]);
655
656 pr_debug("%s: slim[%d]_tx_bit_format = %d, ucontrol value = %d\n",
657 __func__, ch_num, slim_tx_cfg[ch_num].bit_format,
658 ucontrol->value.enumerated.item[0]);
659
660 return 0;
661}
662
663static int msm_slim_rx_ch_get(struct snd_kcontrol *kcontrol,
664 struct snd_ctl_elem_value *ucontrol)
665{
666 int ch_num = slim_get_port_idx(kcontrol);
667
668 if (ch_num < 0)
669 return ch_num;
670
671 pr_debug("%s: msm_slim_[%d]_rx_ch = %d\n", __func__,
672 ch_num, slim_rx_cfg[ch_num].channels);
673 ucontrol->value.enumerated.item[0] = slim_rx_cfg[ch_num].channels - 1;
674
675 return 0;
676}
677
678static int msm_slim_rx_ch_put(struct snd_kcontrol *kcontrol,
679 struct snd_ctl_elem_value *ucontrol)
680{
681 int ch_num = slim_get_port_idx(kcontrol);
682
683 if (ch_num < 0)
684 return ch_num;
685
686 slim_rx_cfg[ch_num].channels = ucontrol->value.enumerated.item[0] + 1;
687 pr_debug("%s: msm_slim_[%d]_rx_ch = %d\n", __func__,
688 ch_num, slim_rx_cfg[ch_num].channels);
689
690 return 1;
691}
692
693static int msm_slim_tx_ch_get(struct snd_kcontrol *kcontrol,
694 struct snd_ctl_elem_value *ucontrol)
695{
696 int ch_num = slim_get_port_idx(kcontrol);
697
698 if (ch_num < 0)
699 return ch_num;
700
701 pr_debug("%s: msm_slim_[%d]_tx_ch = %d\n", __func__,
702 ch_num, slim_tx_cfg[ch_num].channels);
703 ucontrol->value.enumerated.item[0] = slim_tx_cfg[ch_num].channels - 1;
704
705 return 0;
706}
707
708static int msm_slim_tx_ch_put(struct snd_kcontrol *kcontrol,
709 struct snd_ctl_elem_value *ucontrol)
710{
711 int ch_num = slim_get_port_idx(kcontrol);
712
713 if (ch_num < 0)
714 return ch_num;
715
716 slim_tx_cfg[ch_num].channels = ucontrol->value.enumerated.item[0] + 1;
717 pr_debug("%s: msm_slim_[%d]_tx_ch = %d\n", __func__,
718 ch_num, slim_tx_cfg[ch_num].channels);
719
720 return 1;
721}
722
723static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol,
724 struct snd_ctl_elem_value *ucontrol)
725{
726 ucontrol->value.integer.value[0] = msm_vi_feed_tx_ch - 1;
727 pr_debug("%s: msm_vi_feed_tx_ch = %ld\n", __func__,
728 ucontrol->value.integer.value[0]);
729 return 0;
730}
731
732static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol,
733 struct snd_ctl_elem_value *ucontrol)
734{
735 msm_vi_feed_tx_ch = ucontrol->value.integer.value[0] + 1;
736
737 pr_debug("%s: msm_vi_feed_tx_ch = %d\n", __func__, msm_vi_feed_tx_ch);
738 return 1;
739}
740
741static void *def_ext_mbhc_cal(void)
742{
Laxminath Kasam38070be2017-08-17 18:21:59 +0530743 void *wcd_mbhc_cal;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530744 struct wcd_mbhc_btn_detect_cfg *btn_cfg;
745 u16 *btn_high;
746
Laxminath Kasam38070be2017-08-17 18:21:59 +0530747 wcd_mbhc_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530748 WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL);
Laxminath Kasam38070be2017-08-17 18:21:59 +0530749 if (!wcd_mbhc_cal)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530750 return NULL;
751
Laxminath Kasam38070be2017-08-17 18:21:59 +0530752#define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(wcd_mbhc_cal)->X) = (Y))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530753 S(v_hs_max, 1600);
754#undef S
Laxminath Kasam38070be2017-08-17 18:21:59 +0530755#define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal)->X) = (Y))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530756 S(num_btn, WCD_MBHC_DEF_BUTTONS);
757#undef S
758
Laxminath Kasam38070be2017-08-17 18:21:59 +0530759 btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530760 btn_high = ((void *)&btn_cfg->_v_btn_low) +
761 (sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
762
763 btn_high[0] = 75;
764 btn_high[1] = 150;
765 btn_high[2] = 237;
766 btn_high[3] = 500;
767 btn_high[4] = 500;
768 btn_high[5] = 500;
769 btn_high[6] = 500;
770 btn_high[7] = 500;
771
Laxminath Kasam38070be2017-08-17 18:21:59 +0530772 return wcd_mbhc_cal;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530773}
774
775static inline int param_is_mask(int p)
776{
777 return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
778 (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
779}
780
781static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
782{
783 return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
784}
785
786
787static void msm_ext_control(struct snd_soc_codec *codec)
788{
789 struct snd_soc_dapm_context *dapm =
790 snd_soc_codec_get_dapm(codec);
791
792 pr_debug("%s: msm_ext_spk_control = %d", __func__, msm_ext_spk_control);
793 if (msm_ext_spk_control == SDM660_SPK_ON) {
794 snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp");
795 snd_soc_dapm_enable_pin(dapm, "Lineout_3 amp");
796 } else {
797 snd_soc_dapm_disable_pin(dapm, "Lineout_1 amp");
798 snd_soc_dapm_disable_pin(dapm, "Lineout_3 amp");
799 }
800 snd_soc_dapm_sync(dapm);
801}
802
803static int msm_ext_get_spk(struct snd_kcontrol *kcontrol,
804 struct snd_ctl_elem_value *ucontrol)
805{
806 pr_debug("%s: msm_ext_spk_control = %d\n",
807 __func__, msm_ext_spk_control);
808 ucontrol->value.integer.value[0] = msm_ext_spk_control;
809 return 0;
810}
811
812static int msm_ext_set_spk(struct snd_kcontrol *kcontrol,
813 struct snd_ctl_elem_value *ucontrol)
814{
815 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
816
817 pr_debug("%s()\n", __func__);
818 if (msm_ext_spk_control == ucontrol->value.integer.value[0])
819 return 0;
820
821 msm_ext_spk_control = ucontrol->value.integer.value[0];
822 msm_ext_control(codec);
823 return 1;
824}
825
826
827int msm_ext_enable_codec_mclk(struct snd_soc_codec *codec, int enable,
828 bool dapm)
829{
830 int ret;
831
832 pr_debug("%s: enable = %d\n", __func__, enable);
833
834 if (!strcmp(dev_name(codec->dev), "tasha_codec"))
835 ret = tasha_cdc_mclk_enable(codec, enable, dapm);
836 else if (!strcmp(dev_name(codec->dev), "tavil_codec"))
837 ret = tavil_cdc_mclk_enable(codec, enable);
838 else {
839 dev_err(codec->dev, "%s: unknown codec to enable ext clk\n",
840 __func__);
841 ret = -EINVAL;
842 }
843 return ret;
844}
845
846static const struct snd_kcontrol_new msm_snd_controls[] = {
847 SOC_ENUM_EXT("Speaker Function", spk_func_en, msm_ext_get_spk,
848 msm_ext_set_spk),
849 SOC_ENUM_EXT("SLIM_0_RX Channels", slim_0_rx_chs,
850 msm_slim_rx_ch_get, msm_slim_rx_ch_put),
851 SOC_ENUM_EXT("SLIM_2_RX Channels", slim_2_rx_chs,
852 msm_slim_rx_ch_get, msm_slim_rx_ch_put),
853 SOC_ENUM_EXT("SLIM_0_TX Channels", slim_0_tx_chs,
854 msm_slim_tx_ch_get, msm_slim_tx_ch_put),
855 SOC_ENUM_EXT("SLIM_1_TX Channels", slim_1_tx_chs,
856 msm_slim_tx_ch_get, msm_slim_tx_ch_put),
857 SOC_ENUM_EXT("SLIM_5_RX Channels", slim_5_rx_chs,
858 msm_slim_rx_ch_get, msm_slim_rx_ch_put),
859 SOC_ENUM_EXT("SLIM_6_RX Channels", slim_6_rx_chs,
860 msm_slim_rx_ch_get, msm_slim_rx_ch_put),
861 SOC_ENUM_EXT("VI_FEED_TX Channels", vi_feed_tx_chs,
862 msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
863 SOC_ENUM_EXT("SLIM_0_RX Format", slim_0_rx_format,
864 slim_rx_bit_format_get, slim_rx_bit_format_put),
865 SOC_ENUM_EXT("SLIM_5_RX Format", slim_5_rx_format,
866 slim_rx_bit_format_get, slim_rx_bit_format_put),
867 SOC_ENUM_EXT("SLIM_6_RX Format", slim_6_rx_format,
868 slim_rx_bit_format_get, slim_rx_bit_format_put),
869 SOC_ENUM_EXT("SLIM_0_TX Format", slim_0_tx_format,
870 slim_tx_bit_format_get, slim_tx_bit_format_put),
871 SOC_ENUM_EXT("SLIM_0_RX SampleRate", slim_0_rx_sample_rate,
872 slim_rx_sample_rate_get, slim_rx_sample_rate_put),
873 SOC_ENUM_EXT("SLIM_2_RX SampleRate", slim_2_rx_sample_rate,
874 slim_rx_sample_rate_get, slim_rx_sample_rate_put),
875 SOC_ENUM_EXT("SLIM_0_TX SampleRate", slim_0_tx_sample_rate,
876 slim_tx_sample_rate_get, slim_tx_sample_rate_put),
877 SOC_ENUM_EXT("SLIM_5_RX SampleRate", slim_5_rx_sample_rate,
878 slim_rx_sample_rate_get, slim_rx_sample_rate_put),
879 SOC_ENUM_EXT("SLIM_6_RX SampleRate", slim_6_rx_sample_rate,
880 slim_rx_sample_rate_get, slim_rx_sample_rate_put),
881 SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
882 msm_bt_sample_rate_get,
883 msm_bt_sample_rate_put),
Preetam Singh Ranawatd79190a2018-06-25 15:59:23 +0530884 SOC_ENUM_EXT("BT SampleRate RX", bt_sample_rate_rx,
885 msm_bt_sample_rate_rx_get,
886 msm_bt_sample_rate_rx_put),
887 SOC_ENUM_EXT("BT SampleRate TX", bt_sample_rate_tx,
888 msm_bt_sample_rate_tx_get,
889 msm_bt_sample_rate_tx_put),
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530890};
891
Asish Bhattacharya84f7f732017-07-25 16:29:27 +0530892static int msm_slim_get_ch_from_beid(int32_t id)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530893{
894 int ch_id = 0;
895
Asish Bhattacharya84f7f732017-07-25 16:29:27 +0530896 switch (id) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530897 case MSM_BACKEND_DAI_SLIMBUS_0_RX:
898 ch_id = SLIM_RX_0;
899 break;
900 case MSM_BACKEND_DAI_SLIMBUS_1_RX:
901 ch_id = SLIM_RX_1;
902 break;
903 case MSM_BACKEND_DAI_SLIMBUS_2_RX:
904 ch_id = SLIM_RX_2;
905 break;
906 case MSM_BACKEND_DAI_SLIMBUS_3_RX:
907 ch_id = SLIM_RX_3;
908 break;
909 case MSM_BACKEND_DAI_SLIMBUS_4_RX:
910 ch_id = SLIM_RX_4;
911 break;
912 case MSM_BACKEND_DAI_SLIMBUS_6_RX:
913 ch_id = SLIM_RX_6;
914 break;
915 case MSM_BACKEND_DAI_SLIMBUS_0_TX:
916 ch_id = SLIM_TX_0;
917 break;
918 case MSM_BACKEND_DAI_SLIMBUS_3_TX:
919 ch_id = SLIM_TX_3;
920 break;
921 default:
922 ch_id = SLIM_RX_0;
923 break;
924 }
925
926 return ch_id;
927}
928
929static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned int bit)
930{
931 if (bit >= SNDRV_MASK_MAX)
932 return;
933 if (param_is_mask(n)) {
934 struct snd_mask *m = param_to_mask(p, n);
935
936 m->bits[0] = 0;
937 m->bits[1] = 0;
938 m->bits[bit >> 5] |= (1 << (bit & 31));
939 }
940}
941
942/**
943 * msm_ext_be_hw_params_fixup - updates settings of ALSA BE hw params.
944 *
945 * @rtd: runtime dailink instance
946 * @params: HW params of associated backend dailink.
947 *
948 * Returns 0 on success or rc on failure.
949 */
950int msm_ext_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
951 struct snd_pcm_hw_params *params)
952{
953 struct snd_soc_dai_link *dai_link = rtd->dai_link;
954 struct snd_interval *rate = hw_param_interval(params,
955 SNDRV_PCM_HW_PARAM_RATE);
956 struct snd_interval *channels = hw_param_interval(params,
957 SNDRV_PCM_HW_PARAM_CHANNELS);
958 int rc = 0;
959 int idx;
960 void *config = NULL;
961 struct snd_soc_codec *codec = rtd->codec;
962
963 pr_debug("%s: format = %d, rate = %d\n",
964 __func__, params_format(params), params_rate(params));
965
Asish Bhattacharya84f7f732017-07-25 16:29:27 +0530966 switch (dai_link->id) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530967 case MSM_BACKEND_DAI_SLIMBUS_0_RX:
968 case MSM_BACKEND_DAI_SLIMBUS_1_RX:
969 case MSM_BACKEND_DAI_SLIMBUS_2_RX:
970 case MSM_BACKEND_DAI_SLIMBUS_3_RX:
971 case MSM_BACKEND_DAI_SLIMBUS_4_RX:
972 case MSM_BACKEND_DAI_SLIMBUS_6_RX:
Asish Bhattacharya84f7f732017-07-25 16:29:27 +0530973 idx = msm_slim_get_ch_from_beid(dai_link->id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530974 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
975 slim_rx_cfg[idx].bit_format);
976 rate->min = rate->max = slim_rx_cfg[idx].sample_rate;
977 channels->min = channels->max = slim_rx_cfg[idx].channels;
978 break;
979
980 case MSM_BACKEND_DAI_SLIMBUS_0_TX:
981 case MSM_BACKEND_DAI_SLIMBUS_3_TX:
Asish Bhattacharya84f7f732017-07-25 16:29:27 +0530982 idx = msm_slim_get_ch_from_beid(dai_link->id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530983 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
984 slim_tx_cfg[idx].bit_format);
985 rate->min = rate->max = slim_tx_cfg[idx].sample_rate;
986 channels->min = channels->max = slim_tx_cfg[idx].channels;
987 break;
988
989 case MSM_BACKEND_DAI_SLIMBUS_1_TX:
990 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
991 slim_tx_cfg[1].bit_format);
992 rate->min = rate->max = slim_tx_cfg[1].sample_rate;
993 channels->min = channels->max = slim_tx_cfg[1].channels;
994 break;
995
996 case MSM_BACKEND_DAI_SLIMBUS_4_TX:
997 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
998 SNDRV_PCM_FORMAT_S32_LE);
999 rate->min = rate->max = SAMPLING_RATE_8KHZ;
1000 channels->min = channels->max = msm_vi_feed_tx_ch;
1001 break;
1002
1003 case MSM_BACKEND_DAI_SLIMBUS_5_RX:
1004 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
1005 slim_rx_cfg[5].bit_format);
1006 rate->min = rate->max = slim_rx_cfg[5].sample_rate;
1007 channels->min = channels->max = slim_rx_cfg[5].channels;
1008 break;
1009
1010 case MSM_BACKEND_DAI_SLIMBUS_5_TX:
1011 rate->min = rate->max = SAMPLING_RATE_16KHZ;
1012 channels->min = channels->max = 1;
1013
1014 config = msm_codec_fn.get_afe_config_fn(codec,
1015 AFE_SLIMBUS_SLAVE_PORT_CONFIG);
1016 if (config) {
1017 rc = afe_set_config(AFE_SLIMBUS_SLAVE_PORT_CONFIG,
1018 config, SLIMBUS_5_TX);
1019 if (rc)
1020 pr_err("%s: Failed to set slimbus slave port config %d\n",
1021 __func__, rc);
1022 }
1023 break;
1024
1025 case MSM_BACKEND_DAI_SLIMBUS_7_RX:
1026 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
1027 slim_rx_cfg[SLIM_RX_7].bit_format);
1028 rate->min = rate->max = slim_rx_cfg[SLIM_RX_7].sample_rate;
1029 channels->min = channels->max =
1030 slim_rx_cfg[SLIM_RX_7].channels;
1031 break;
1032
1033 case MSM_BACKEND_DAI_SLIMBUS_7_TX:
1034 rate->min = rate->max = slim_tx_cfg[SLIM_TX_7].sample_rate;
1035 channels->min = channels->max =
1036 slim_tx_cfg[SLIM_TX_7].channels;
1037 break;
1038
1039 case MSM_BACKEND_DAI_SLIMBUS_8_TX:
1040 rate->min = rate->max = slim_tx_cfg[SLIM_TX_8].sample_rate;
1041 channels->min = channels->max =
1042 slim_tx_cfg[SLIM_TX_8].channels;
1043 break;
1044
1045 default:
1046 rate->min = rate->max = SAMPLING_RATE_48KHZ;
1047 break;
1048 }
1049 return rc;
1050}
1051EXPORT_SYMBOL(msm_ext_be_hw_params_fixup);
1052
1053/**
1054 * msm_snd_hw_params - hw params ops of backend dailink.
1055 *
1056 * @substream: PCM stream of associated backend dailink.
1057 * @params: HW params of associated backend dailink.
1058 *
1059 * Returns 0 on success or ret on failure.
1060 */
1061int msm_snd_hw_params(struct snd_pcm_substream *substream,
1062 struct snd_pcm_hw_params *params)
1063{
1064 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1065 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1066 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1067 struct snd_soc_dai_link *dai_link = rtd->dai_link;
1068
1069 int ret = 0;
1070 u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
1071 u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
1072 u32 user_set_tx_ch = 0;
1073 u32 rx_ch_count;
1074
1075 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1076 ret = snd_soc_dai_get_channel_map(codec_dai,
1077 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
1078 if (ret < 0) {
1079 pr_err("%s: failed to get codec chan map, err:%d\n",
1080 __func__, ret);
1081 goto err_ch_map;
1082 }
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301083 if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_5_RX) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301084 pr_debug("%s: rx_5_ch=%d\n", __func__,
1085 slim_rx_cfg[5].channels);
1086 rx_ch_count = slim_rx_cfg[5].channels;
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301087 } else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_2_RX) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301088 pr_debug("%s: rx_2_ch=%d\n", __func__,
1089 slim_rx_cfg[2].channels);
1090 rx_ch_count = slim_rx_cfg[2].channels;
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301091 } else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_6_RX) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301092 pr_debug("%s: rx_6_ch=%d\n", __func__,
1093 slim_rx_cfg[6].channels);
1094 rx_ch_count = slim_rx_cfg[6].channels;
1095 } else {
1096 pr_debug("%s: rx_0_ch=%d\n", __func__,
1097 slim_rx_cfg[0].channels);
1098 rx_ch_count = slim_rx_cfg[0].channels;
1099 }
1100 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
1101 rx_ch_count, rx_ch);
1102 if (ret < 0) {
1103 pr_err("%s: failed to set cpu chan map, err:%d\n",
1104 __func__, ret);
1105 goto err_ch_map;
1106 }
1107 } else {
1108 pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
1109 codec_dai->name, codec_dai->id, user_set_tx_ch);
1110 ret = snd_soc_dai_get_channel_map(codec_dai,
1111 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
1112 if (ret < 0) {
1113 pr_err("%s: failed to get codec chan map\n, err:%d\n",
1114 __func__, ret);
1115 goto err_ch_map;
1116 }
1117 /* For <codec>_tx1 case */
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301118 if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_0_TX)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301119 user_set_tx_ch = slim_tx_cfg[0].channels;
1120 /* For <codec>_tx3 case */
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301121 else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_1_TX)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301122 user_set_tx_ch = slim_tx_cfg[1].channels;
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301123 else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_4_TX)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301124 user_set_tx_ch = msm_vi_feed_tx_ch;
1125 else
1126 user_set_tx_ch = tx_ch_cnt;
1127
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301128 pr_debug("%s: msm_slim_0_tx_ch(%d) user_set_tx_ch(%d) tx_ch_cnt(%d), id (%d)\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301129 __func__, slim_tx_cfg[0].channels, user_set_tx_ch,
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301130 tx_ch_cnt, dai_link->id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301131
1132 ret = snd_soc_dai_set_channel_map(cpu_dai,
1133 user_set_tx_ch, tx_ch, 0, 0);
1134 if (ret < 0)
1135 pr_err("%s: failed to set cpu chan map, err:%d\n",
1136 __func__, ret);
1137 }
1138
1139err_ch_map:
1140 return ret;
1141}
1142EXPORT_SYMBOL(msm_snd_hw_params);
1143
1144/**
1145 * msm_ext_slimbus_2_hw_params - hw params ops of slimbus_2 BE.
1146 *
1147 * @substream: PCM stream of associated backend dailink.
1148 * @params: HW params of associated backend dailink.
1149 *
1150 * Returns 0 on success or ret on failure.
1151 */
1152int msm_ext_slimbus_2_hw_params(struct snd_pcm_substream *substream,
1153 struct snd_pcm_hw_params *params)
1154{
1155 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1156 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1157 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1158 int ret = 0;
1159 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
1160 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
1161 unsigned int num_tx_ch = 0;
1162 unsigned int num_rx_ch = 0;
1163
1164 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1165 num_rx_ch = params_channels(params);
1166 pr_debug("%s: %s rx_dai_id = %d num_ch = %d\n", __func__,
1167 codec_dai->name, codec_dai->id, num_rx_ch);
1168 ret = snd_soc_dai_get_channel_map(codec_dai,
1169 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
1170 if (ret < 0) {
1171 pr_err("%s: failed to get codec chan map, err:%d\n",
1172 __func__, ret);
1173 goto end;
1174 }
1175 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
1176 num_rx_ch, rx_ch);
1177 if (ret < 0) {
1178 pr_err("%s: failed to set cpu chan map, err:%d\n",
1179 __func__, ret);
1180 goto end;
1181 }
1182 } else {
1183 num_tx_ch = params_channels(params);
1184 pr_debug("%s: %s tx_dai_id = %d num_ch = %d\n", __func__,
1185 codec_dai->name, codec_dai->id, num_tx_ch);
1186 ret = snd_soc_dai_get_channel_map(codec_dai,
1187 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
1188 if (ret < 0) {
1189 pr_err("%s: failed to get codec chan map, err:%d\n",
1190 __func__, ret);
1191 goto end;
1192 }
1193 ret = snd_soc_dai_set_channel_map(cpu_dai,
1194 num_tx_ch, tx_ch, 0, 0);
1195 if (ret < 0) {
1196 pr_err("%s: failed to set cpu chan map, err:%d\n",
1197 __func__, ret);
1198 goto end;
1199 }
1200 }
1201end:
1202 return ret;
1203}
1204EXPORT_SYMBOL(msm_ext_slimbus_2_hw_params);
1205
1206/**
1207 * msm_snd_cpe_hw_params - hw params ops of CPE backend.
1208 *
1209 * @substream: PCM stream of associated backend dailink.
1210 * @params: HW params of associated backend dailink.
1211 *
1212 * Returns 0 on success or ret on failure.
1213 */
1214int msm_snd_cpe_hw_params(struct snd_pcm_substream *substream,
1215 struct snd_pcm_hw_params *params)
1216{
1217 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1218 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1219 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1220 struct snd_soc_dai_link *dai_link = rtd->dai_link;
1221 int ret = 0;
1222 u32 tx_ch[SLIM_MAX_TX_PORTS];
1223 u32 tx_ch_cnt = 0;
1224
1225 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) {
1226 pr_err("%s: Invalid stream type %d\n",
1227 __func__, substream->stream);
1228 ret = -EINVAL;
1229 goto end;
1230 }
1231
1232 pr_debug("%s: %s_tx_dai_id_%d\n", __func__,
1233 codec_dai->name, codec_dai->id);
1234 ret = snd_soc_dai_get_channel_map(codec_dai,
1235 &tx_ch_cnt, tx_ch, NULL, NULL);
1236 if (ret < 0) {
1237 pr_err("%s: failed to get codec chan map\n, err:%d\n",
1238 __func__, ret);
1239 goto end;
1240 }
1241
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301242 pr_debug("%s: tx_ch_cnt(%d) id %d\n",
1243 __func__, tx_ch_cnt, dai_link->id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301244
1245 ret = snd_soc_dai_set_channel_map(cpu_dai,
1246 tx_ch_cnt, tx_ch, 0, 0);
1247 if (ret < 0) {
1248 pr_err("%s: failed to set cpu chan map, err:%d\n",
1249 __func__, ret);
1250 goto end;
1251 }
1252end:
1253 return ret;
1254}
1255EXPORT_SYMBOL(msm_snd_cpe_hw_params);
1256
1257static int msm_afe_set_config(struct snd_soc_codec *codec)
1258{
1259 int rc;
1260 void *config_data;
1261
1262 pr_debug("%s: enter\n", __func__);
1263
1264 if (!msm_codec_fn.get_afe_config_fn) {
1265 dev_err(codec->dev, "%s: codec get afe config not init'ed\n",
1266 __func__);
1267 return -EINVAL;
1268 }
1269 config_data = msm_codec_fn.get_afe_config_fn(codec,
1270 AFE_CDC_REGISTERS_CONFIG);
1271 if (config_data) {
1272 rc = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
1273 if (rc) {
1274 pr_err("%s: Failed to set codec registers config %d\n",
1275 __func__, rc);
1276 return rc;
1277 }
1278 }
1279
1280 config_data = msm_codec_fn.get_afe_config_fn(codec,
1281 AFE_CDC_REGISTER_PAGE_CONFIG);
1282 if (config_data) {
1283 rc = afe_set_config(AFE_CDC_REGISTER_PAGE_CONFIG, config_data,
1284 0);
1285 if (rc)
1286 pr_err("%s: Failed to set cdc register page config\n",
1287 __func__);
1288 }
1289
1290 config_data = msm_codec_fn.get_afe_config_fn(codec,
1291 AFE_SLIMBUS_SLAVE_CONFIG);
1292 if (config_data) {
1293 rc = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
1294 if (rc) {
1295 pr_err("%s: Failed to set slimbus slave config %d\n",
1296 __func__, rc);
1297 return rc;
1298 }
1299 }
1300
1301 config_data = msm_codec_fn.get_afe_config_fn(codec,
1302 AFE_AANC_VERSION);
1303 if (config_data) {
1304 rc = afe_set_config(AFE_AANC_VERSION, config_data, 0);
1305 if (rc) {
1306 pr_err("%s: Failed to set AANC version %d\n",
1307 __func__, rc);
1308 return rc;
1309 }
1310 }
1311
1312 config_data = msm_codec_fn.get_afe_config_fn(codec,
1313 AFE_CDC_CLIP_REGISTERS_CONFIG);
1314 if (config_data) {
1315 rc = afe_set_config(AFE_CDC_CLIP_REGISTERS_CONFIG,
1316 config_data, 0);
1317 if (rc) {
1318 pr_err("%s: Failed to set clip registers %d\n",
1319 __func__, rc);
1320 return rc;
1321 }
1322 }
1323
1324 config_data = msm_codec_fn.get_afe_config_fn(codec,
1325 AFE_CLIP_BANK_SEL);
1326 if (config_data) {
1327 rc = afe_set_config(AFE_CLIP_BANK_SEL,
1328 config_data, 0);
1329 if (rc) {
1330 pr_err("%s: Failed to set AFE bank selection %d\n",
1331 __func__, rc);
1332 return rc;
1333 }
1334 }
1335
1336 config_data = msm_codec_fn.get_afe_config_fn(codec,
1337 AFE_CDC_REGISTER_PAGE_CONFIG);
1338 if (config_data) {
1339 rc = afe_set_config(AFE_CDC_REGISTER_PAGE_CONFIG, config_data,
1340 0);
1341 if (rc)
1342 pr_err("%s: Failed to set cdc register page config\n",
1343 __func__);
1344 }
1345
1346 return 0;
1347}
1348
1349static void msm_afe_clear_config(void)
1350{
1351 afe_clear_config(AFE_CDC_REGISTERS_CONFIG);
1352 afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
1353}
1354
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301355static int msm_adsp_power_up_config(struct snd_soc_codec *codec,
1356 struct snd_card *card)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301357{
1358 int ret = 0;
1359 unsigned long timeout;
1360 int adsp_ready = 0;
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301361 bool snd_card_online = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301362
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301363 timeout = jiffies +
1364 msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
1365
1366 do {
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301367 if (!snd_card_online) {
1368 snd_card_online = snd_card_is_online_state(card);
1369 pr_debug("%s: Sound card is %s\n", __func__,
1370 snd_card_online ? "Online" : "Offline");
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301371 }
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301372 if (!adsp_ready) {
1373 adsp_ready = q6core_is_adsp_ready();
1374 pr_debug("%s: ADSP Audio is %s\n", __func__,
1375 adsp_ready ? "ready" : "not ready");
1376 }
1377 if (snd_card_online && adsp_ready)
1378 break;
1379
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301380 /*
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301381 * Sound card/ADSP will be coming up after subsystem restart and
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301382 * it might not be fully up when the control reaches
1383 * here. So, wait for 50msec before checking ADSP state
1384 */
1385 msleep(50);
1386 } while (time_after(timeout, jiffies));
1387
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301388 if (!snd_card_online || !adsp_ready) {
1389 pr_err("%s: Timeout. Sound card is %s, ADSP Audio is %s\n",
1390 __func__,
1391 snd_card_online ? "Online" : "Offline",
1392 adsp_ready ? "ready" : "not ready");
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301393 ret = -ETIMEDOUT;
1394 goto err_fail;
1395 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301396
1397 ret = msm_afe_set_config(codec);
1398 if (ret)
1399 pr_err("%s: Failed to set AFE config. err %d\n",
1400 __func__, ret);
1401
1402 return 0;
1403
1404err_fail:
1405 return ret;
1406}
1407
1408static int sdm660_notifier_service_cb(struct notifier_block *this,
1409 unsigned long opcode, void *ptr)
1410{
1411 int ret;
1412 struct snd_soc_card *card = NULL;
1413 const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
1414 struct snd_soc_pcm_runtime *rtd;
1415 struct snd_soc_codec *codec;
1416
1417 pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode);
1418
1419 switch (opcode) {
1420 case AUDIO_NOTIFIER_SERVICE_DOWN:
1421 /*
1422 * Use flag to ignore initial boot notifications
1423 * On initial boot msm_adsp_power_up_config is
1424 * called on init. There is no need to clear
1425 * and set the config again on initial boot.
1426 */
1427 if (is_initial_boot)
1428 break;
1429 msm_afe_clear_config();
1430 break;
1431 case AUDIO_NOTIFIER_SERVICE_UP:
1432 if (is_initial_boot) {
1433 is_initial_boot = false;
1434 break;
1435 }
1436 if (!spdev)
1437 return -EINVAL;
1438
1439 card = platform_get_drvdata(spdev);
1440 rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
1441 if (!rtd) {
1442 dev_err(card->dev,
1443 "%s: snd_soc_get_pcm_runtime for %s failed!\n",
1444 __func__, be_dl_name);
1445 ret = -EINVAL;
1446 goto done;
1447 }
1448 codec = rtd->codec;
1449
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301450 ret = msm_adsp_power_up_config(codec, card->snd_card);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301451 if (ret < 0) {
1452 dev_err(card->dev,
1453 "%s: msm_adsp_power_up_config failed ret = %d!\n",
1454 __func__, ret);
1455 goto done;
1456 }
1457 break;
1458 default:
1459 break;
1460 }
1461done:
1462 return NOTIFY_OK;
1463}
1464
1465static struct notifier_block service_nb = {
1466 .notifier_call = sdm660_notifier_service_cb,
1467 .priority = -INT_MAX,
1468};
1469
1470static int msm_config_hph_en0_gpio(struct snd_soc_codec *codec, bool high)
1471{
1472 struct snd_soc_card *card = codec->component.card;
1473 struct msm_asoc_mach_data *pdata;
1474 int val;
1475
1476 if (!card)
1477 return 0;
1478
1479 pdata = snd_soc_card_get_drvdata(card);
1480 if (!pdata || !gpio_is_valid(pdata->hph_en0_gpio))
1481 return 0;
1482
1483 val = gpio_get_value_cansleep(pdata->hph_en0_gpio);
1484 if ((!!val) == high)
1485 return 0;
1486
1487 gpio_direction_output(pdata->hph_en0_gpio, (int)high);
1488
1489 return 1;
1490}
1491
1492static int msm_snd_enable_codec_ext_tx_clk(struct snd_soc_codec *codec,
1493 int enable, bool dapm)
1494{
1495 int ret = 0;
1496
1497 if (!strcmp(dev_name(codec->dev), "tasha_codec"))
1498 ret = tasha_cdc_mclk_tx_enable(codec, enable, dapm);
1499 else {
1500 dev_err(codec->dev, "%s: unknown codec to enable ext clk\n",
1501 __func__);
1502 ret = -EINVAL;
1503 }
1504 return ret;
1505}
1506
1507static int msm_ext_mclk_tx_event(struct snd_soc_dapm_widget *w,
1508 struct snd_kcontrol *kcontrol, int event)
1509{
1510 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1511
1512 pr_debug("%s: event = %d\n", __func__, event);
1513
1514 switch (event) {
1515 case SND_SOC_DAPM_PRE_PMU:
1516 return msm_snd_enable_codec_ext_tx_clk(codec, 1, true);
1517 case SND_SOC_DAPM_POST_PMD:
1518 return msm_snd_enable_codec_ext_tx_clk(codec, 0, true);
1519 }
1520 return 0;
1521}
1522
1523static int msm_ext_mclk_event(struct snd_soc_dapm_widget *w,
1524 struct snd_kcontrol *kcontrol, int event)
1525{
1526 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1527
1528 pr_debug("%s: event = %d\n", __func__, event);
1529
1530 switch (event) {
1531 case SND_SOC_DAPM_PRE_PMU:
1532 return msm_ext_enable_codec_mclk(codec, 1, true);
1533 case SND_SOC_DAPM_POST_PMD:
1534 return msm_ext_enable_codec_mclk(codec, 0, true);
1535 }
1536 return 0;
1537}
1538
1539static int msm_ext_prepare_hifi(struct msm_asoc_mach_data *pdata)
1540{
1541 int ret = 0;
1542
1543 if (gpio_is_valid(pdata->hph_en1_gpio)) {
1544 pr_debug("%s: hph_en1_gpio request %d\n", __func__,
1545 pdata->hph_en1_gpio);
1546 ret = gpio_request(pdata->hph_en1_gpio, "hph_en1_gpio");
1547 if (ret) {
1548 pr_err("%s: hph_en1_gpio request failed, ret:%d\n",
1549 __func__, ret);
1550 goto err;
1551 }
1552 }
1553 if (gpio_is_valid(pdata->hph_en0_gpio)) {
1554 pr_debug("%s: hph_en0_gpio request %d\n", __func__,
1555 pdata->hph_en0_gpio);
1556 ret = gpio_request(pdata->hph_en0_gpio, "hph_en0_gpio");
1557 if (ret)
1558 pr_err("%s: hph_en0_gpio request failed, ret:%d\n",
1559 __func__, ret);
1560 }
1561
1562err:
1563 return ret;
1564}
1565
1566static const struct snd_soc_dapm_widget msm_dapm_widgets[] = {
1567
1568 SND_SOC_DAPM_SUPPLY_S("MCLK", -1, SND_SOC_NOPM, 0, 0,
1569 msm_ext_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1570
1571 SND_SOC_DAPM_SUPPLY_S("MCLK TX", -1, SND_SOC_NOPM, 0, 0,
1572 msm_ext_mclk_tx_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1573
1574 SND_SOC_DAPM_SPK("Lineout_1 amp", NULL),
1575 SND_SOC_DAPM_SPK("Lineout_3 amp", NULL),
1576 SND_SOC_DAPM_SPK("Lineout_2 amp", NULL),
1577 SND_SOC_DAPM_SPK("Lineout_4 amp", NULL),
1578 SND_SOC_DAPM_MIC("Handset Mic", NULL),
1579 SND_SOC_DAPM_MIC("Headset Mic", NULL),
1580 SND_SOC_DAPM_MIC("Secondary Mic", NULL),
1581 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
1582 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
1583 SND_SOC_DAPM_MIC("Analog Mic4", NULL),
1584 SND_SOC_DAPM_MIC("Analog Mic6", NULL),
1585 SND_SOC_DAPM_MIC("Analog Mic7", NULL),
1586 SND_SOC_DAPM_MIC("Analog Mic8", NULL),
1587
1588 SND_SOC_DAPM_MIC("Digital Mic0", NULL),
1589 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
1590 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
1591 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
1592 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
1593 SND_SOC_DAPM_MIC("Digital Mic5", NULL),
1594 SND_SOC_DAPM_MIC("Digital Mic6", NULL),
1595};
1596
1597static struct snd_soc_dapm_route wcd_audio_paths_tasha[] = {
1598 {"MIC BIAS1", NULL, "MCLK TX"},
1599 {"MIC BIAS2", NULL, "MCLK TX"},
1600 {"MIC BIAS3", NULL, "MCLK TX"},
1601 {"MIC BIAS4", NULL, "MCLK TX"},
1602};
1603
1604static struct snd_soc_dapm_route wcd_audio_paths[] = {
1605 {"MIC BIAS1", NULL, "MCLK"},
1606 {"MIC BIAS2", NULL, "MCLK"},
1607 {"MIC BIAS3", NULL, "MCLK"},
1608 {"MIC BIAS4", NULL, "MCLK"},
1609};
1610
Laxminath Kasam38070be2017-08-17 18:21:59 +05301611int msm_snd_card_tasha_late_probe(struct snd_soc_card *card)
1612{
1613 const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
1614 struct snd_soc_pcm_runtime *rtd;
1615 int ret = 0;
1616 void *mbhc_calibration;
1617
1618 rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
1619 if (!rtd) {
1620 dev_err(card->dev,
1621 "%s: snd_soc_get_pcm_runtime for %s failed!\n",
1622 __func__, be_dl_name);
1623 ret = -EINVAL;
1624 goto err_pcm_runtime;
1625 }
1626
1627 mbhc_calibration = def_ext_mbhc_cal();
1628 if (!mbhc_calibration) {
1629 ret = -ENOMEM;
1630 goto err_mbhc_cal;
1631 }
1632 wcd_mbhc_cfg_ptr->calibration = mbhc_calibration;
1633 ret = tasha_mbhc_hs_detect(rtd->codec, wcd_mbhc_cfg_ptr);
1634 if (ret) {
1635 dev_err(card->dev, "%s: mbhc hs detect failed, err:%d\n",
1636 __func__, ret);
1637 goto err_hs_detect;
1638 }
1639 return 0;
1640
1641err_hs_detect:
1642 kfree(mbhc_calibration);
1643err_mbhc_cal:
1644err_pcm_runtime:
1645 return ret;
1646}
1647
1648int msm_snd_card_tavil_late_probe(struct snd_soc_card *card)
1649{
1650 const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
1651 struct snd_soc_pcm_runtime *rtd;
1652 int ret = 0;
1653 void *mbhc_calibration;
1654
1655 rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
1656 if (!rtd) {
1657 dev_err(card->dev,
1658 "%s: snd_soc_get_pcm_runtime for %s failed!\n",
1659 __func__, be_dl_name);
1660 ret = -EINVAL;
1661 goto err;
1662 }
1663
1664 mbhc_calibration = def_ext_mbhc_cal();
1665 if (!mbhc_calibration) {
1666 ret = -ENOMEM;
1667 goto err;
1668 }
1669 wcd_mbhc_cfg_ptr->calibration = mbhc_calibration;
1670 ret = tavil_mbhc_hs_detect(rtd->codec, wcd_mbhc_cfg_ptr);
1671 if (ret) {
1672 dev_err(card->dev, "%s: mbhc hs detect failed, err:%d\n",
1673 __func__, ret);
1674 goto err_free_mbhc_cal;
1675 }
1676 return 0;
1677
1678err_free_mbhc_cal:
1679 kfree(mbhc_calibration);
1680err:
1681 return ret;
1682}
1683
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301684/**
1685 * msm_audrx_init - Audio init function of sound card instantiate.
1686 *
1687 * @rtd: runtime dailink instance
1688 *
1689 * Returns 0 on success or ret on failure.
1690 */
1691int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
1692{
1693 int ret;
1694 void *config_data;
1695 struct snd_soc_codec *codec = rtd->codec;
1696 struct snd_soc_dapm_context *dapm =
1697 snd_soc_codec_get_dapm(codec);
1698 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1699 struct snd_soc_dai *codec_dai = rtd->codec_dai;
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301700 struct snd_soc_component *aux_comp;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301701 struct snd_card *card;
1702 struct snd_info_entry *entry;
1703 struct msm_asoc_mach_data *pdata =
1704 snd_soc_card_get_drvdata(rtd->card);
1705
1706 /* Codec SLIMBUS configuration
1707 * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
1708 * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
1709 * TX14, TX15, TX16
1710 */
1711 unsigned int rx_ch[TASHA_RX_MAX] = {144, 145, 146, 147, 148, 149, 150,
1712 151, 152, 153, 154, 155, 156};
1713 unsigned int tx_ch[TASHA_TX_MAX] = {128, 129, 130, 131, 132, 133,
1714 134, 135, 136, 137, 138, 139,
1715 140, 141, 142, 143};
1716
1717 /* Tavil Codec SLIMBUS configuration
1718 * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8
1719 * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
1720 * TX14, TX15, TX16
1721 */
1722 unsigned int rx_ch_tavil[WCD934X_RX_MAX] = {144, 145, 146, 147, 148,
1723 149, 150, 151};
1724 unsigned int tx_ch_tavil[WCD934X_TX_MAX] = {128, 129, 130, 131, 132,
1725 133, 134, 135, 136, 137, 138,
1726 139, 140, 141, 142, 143};
1727
1728 pr_debug("%s: dev_name%s\n", __func__, dev_name(cpu_dai->dev));
1729
1730 rtd->pmdown_time = 0;
1731
1732 ret = snd_soc_add_codec_controls(codec, msm_snd_controls,
1733 ARRAY_SIZE(msm_snd_controls));
1734 if (ret < 0) {
1735 pr_err("%s: add_codec_controls failed: %d\n",
1736 __func__, ret);
1737 return ret;
1738 }
1739
1740 ret = snd_soc_add_codec_controls(codec, msm_common_snd_controls,
1741 msm_common_snd_controls_size());
1742 if (ret < 0) {
1743 pr_err("%s: add_common_snd_controls failed: %d\n",
1744 __func__, ret);
1745 return ret;
1746 }
1747
1748 snd_soc_dapm_new_controls(dapm, msm_dapm_widgets,
1749 ARRAY_SIZE(msm_dapm_widgets));
1750
1751 if (!strcmp(dev_name(codec_dai->dev), "tasha_codec"))
1752 snd_soc_dapm_add_routes(dapm, wcd_audio_paths_tasha,
1753 ARRAY_SIZE(wcd_audio_paths_tasha));
1754 else
1755 snd_soc_dapm_add_routes(dapm, wcd_audio_paths,
1756 ARRAY_SIZE(wcd_audio_paths));
1757
1758 snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp");
1759 snd_soc_dapm_enable_pin(dapm, "Lineout_3 amp");
1760 snd_soc_dapm_enable_pin(dapm, "Lineout_2 amp");
1761 snd_soc_dapm_enable_pin(dapm, "Lineout_4 amp");
1762
1763 snd_soc_dapm_ignore_suspend(dapm, "MADINPUT");
1764 snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_INPUT");
1765 snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
1766 snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
1767 snd_soc_dapm_ignore_suspend(dapm, "Secondary Mic");
1768 snd_soc_dapm_ignore_suspend(dapm, "Lineout_1 amp");
1769 snd_soc_dapm_ignore_suspend(dapm, "Lineout_3 amp");
1770 snd_soc_dapm_ignore_suspend(dapm, "Lineout_2 amp");
1771 snd_soc_dapm_ignore_suspend(dapm, "Lineout_4 amp");
1772 snd_soc_dapm_ignore_suspend(dapm, "ANCRight Headset Mic");
1773 snd_soc_dapm_ignore_suspend(dapm, "ANCLeft Headset Mic");
1774 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic0");
1775 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
1776 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
1777 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic3");
1778 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic4");
1779 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic5");
1780 snd_soc_dapm_ignore_suspend(dapm, "Analog Mic4");
1781 snd_soc_dapm_ignore_suspend(dapm, "Analog Mic6");
1782 snd_soc_dapm_ignore_suspend(dapm, "Analog Mic7");
1783 snd_soc_dapm_ignore_suspend(dapm, "Analog Mic8");
1784
1785 snd_soc_dapm_ignore_suspend(dapm, "EAR");
1786 snd_soc_dapm_ignore_suspend(dapm, "LINEOUT1");
1787 snd_soc_dapm_ignore_suspend(dapm, "LINEOUT2");
1788 snd_soc_dapm_ignore_suspend(dapm, "AMIC1");
1789 snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
1790 snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
1791 snd_soc_dapm_ignore_suspend(dapm, "AMIC4");
1792 snd_soc_dapm_ignore_suspend(dapm, "AMIC5");
1793 snd_soc_dapm_ignore_suspend(dapm, "DMIC0");
1794 snd_soc_dapm_ignore_suspend(dapm, "DMIC1");
1795 snd_soc_dapm_ignore_suspend(dapm, "DMIC2");
1796 snd_soc_dapm_ignore_suspend(dapm, "DMIC3");
1797 snd_soc_dapm_ignore_suspend(dapm, "DMIC4");
1798 snd_soc_dapm_ignore_suspend(dapm, "DMIC5");
1799 snd_soc_dapm_ignore_suspend(dapm, "ANC EAR");
1800 snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT");
1801 snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT");
1802 snd_soc_dapm_ignore_suspend(dapm, "HPHL");
1803 snd_soc_dapm_ignore_suspend(dapm, "HPHR");
1804 snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI");
1805 snd_soc_dapm_ignore_suspend(dapm, "VIINPUT");
1806
1807 if (!strcmp(dev_name(codec_dai->dev), "tasha_codec")) {
1808 snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3");
1809 snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4");
1810 snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL");
1811 snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR");
1812 snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1");
1813 snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2");
1814 } else {
1815 snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_OUT1");
1816 snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_OUT2");
1817 }
1818
1819 snd_soc_dapm_sync(dapm);
1820
1821 if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
1822 snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch_tavil),
1823 tx_ch_tavil, ARRAY_SIZE(rx_ch_tavil),
1824 rx_ch_tavil);
1825 } else {
1826 snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
1827 tx_ch, ARRAY_SIZE(rx_ch),
1828 rx_ch);
1829 }
1830
1831 if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
1832 msm_codec_fn.get_afe_config_fn = tavil_get_afe_config;
1833 } else {
1834 msm_codec_fn.get_afe_config_fn = tasha_get_afe_config;
1835 msm_codec_fn.mbhc_hs_detect_exit = tasha_mbhc_hs_detect_exit;
1836 }
1837
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301838 ret = msm_adsp_power_up_config(codec, rtd->card->snd_card);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301839 if (ret) {
1840 pr_err("%s: Failed to set AFE config %d\n", __func__, ret);
1841 goto err_afe_cfg;
1842 }
1843
1844 config_data = msm_codec_fn.get_afe_config_fn(codec,
1845 AFE_AANC_VERSION);
1846 if (config_data) {
1847 ret = afe_set_config(AFE_AANC_VERSION, config_data, 0);
1848 if (ret) {
1849 pr_err("%s: Failed to set aanc version %d\n",
1850 __func__, ret);
1851 goto err_afe_cfg;
1852 }
1853 }
1854
1855 if (!strcmp(dev_name(codec_dai->dev), "tasha_codec")) {
1856 config_data = msm_codec_fn.get_afe_config_fn(codec,
1857 AFE_CDC_CLIP_REGISTERS_CONFIG);
1858 if (config_data) {
1859 ret = afe_set_config(AFE_CDC_CLIP_REGISTERS_CONFIG,
1860 config_data, 0);
1861 if (ret) {
1862 pr_err("%s: Failed to set clip registers %d\n",
1863 __func__, ret);
1864 goto err_afe_cfg;
1865 }
1866 }
1867 config_data = msm_codec_fn.get_afe_config_fn(codec,
1868 AFE_CLIP_BANK_SEL);
1869 if (config_data) {
1870 ret = afe_set_config(AFE_CLIP_BANK_SEL, config_data, 0);
1871 if (ret) {
1872 pr_err("%s: Failed to set AFE bank selection %d\n",
1873 __func__, ret);
1874 goto err_afe_cfg;
1875 }
1876 }
1877 }
1878
1879 /*
1880 * Send speaker configuration only for WSA8810.
1881 * Defalut configuration is for WSA8815.
1882 */
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301883 pr_debug("%s: Number of aux devices: %d\n",
1884 __func__, rtd->card->num_aux_devs);
1885
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301886 if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301887 if (rtd->card->num_aux_devs &&
1888 !list_empty(&rtd->card->aux_comp_list)) {
1889 aux_comp = list_first_entry(&rtd->card->aux_comp_list,
1890 struct snd_soc_component, list_aux);
1891 if (!strcmp(aux_comp->name, WSA8810_NAME_1) ||
1892 !strcmp(aux_comp->name, WSA8810_NAME_2)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301893 tavil_set_spkr_mode(rtd->codec, SPKR_MODE_1);
1894 tavil_set_spkr_gain_offset(rtd->codec,
1895 RX_GAIN_OFFSET_M1P5_DB);
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301896 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301897 }
1898 card = rtd->card->snd_card;
1899 entry = snd_info_create_subdir(card->module, "codecs",
1900 card->proc_root);
1901 if (!entry) {
1902 pr_debug("%s: Cannot create codecs module entry\n",
1903 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301904 goto done;
1905 }
1906 pdata->codec_root = entry;
1907 tavil_codec_info_create_codec_entry(pdata->codec_root, codec);
1908 } else {
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301909 if (rtd->card->num_aux_devs &&
1910 !list_empty(&rtd->card->aux_comp_list)) {
1911 aux_comp = list_first_entry(&rtd->card->aux_comp_list,
1912 struct snd_soc_component, list_aux);
1913 if (!strcmp(aux_comp->name, WSA8810_NAME_1) ||
1914 !strcmp(aux_comp->name, WSA8810_NAME_2)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301915 tasha_set_spkr_mode(rtd->codec, SPKR_MODE_1);
1916 tasha_set_spkr_gain_offset(rtd->codec,
1917 RX_GAIN_OFFSET_M1P5_DB);
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301918 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301919 }
1920 card = rtd->card->snd_card;
1921 entry = snd_info_create_subdir(card->module, "codecs",
1922 card->proc_root);
1923 if (!entry) {
1924 pr_debug("%s: Cannot create codecs module entry\n",
1925 __func__);
Laxminath Kasam38070be2017-08-17 18:21:59 +05301926 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301927 }
1928 pdata->codec_root = entry;
1929 tasha_codec_info_create_codec_entry(pdata->codec_root, codec);
1930 tasha_mbhc_zdet_gpio_ctrl(msm_config_hph_en0_gpio, rtd->codec);
1931 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301932done:
Laxminath Kasam38070be2017-08-17 18:21:59 +05301933 msm_set_codec_reg_done(true);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301934 return 0;
1935
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301936err_afe_cfg:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301937 return ret;
1938}
1939EXPORT_SYMBOL(msm_audrx_init);
1940
1941/**
1942 * msm_ext_register_audio_notifier - register SSR notifier.
1943 */
1944void msm_ext_register_audio_notifier(struct platform_device *pdev)
1945{
1946 int ret;
1947
1948 is_initial_boot = true;
1949 spdev = pdev;
1950 ret = audio_notifier_register("sdm660", AUDIO_NOTIFIER_ADSP_DOMAIN,
1951 &service_nb);
1952 if (ret < 0)
1953 pr_err("%s: Audio notifier register failed ret = %d\n",
1954 __func__, ret);
1955}
1956EXPORT_SYMBOL(msm_ext_register_audio_notifier);
1957
1958/**
1959 * msm_ext_cdc_init - external codec machine specific init.
1960 *
1961 * @pdev: platform device handle
1962 * @pdata: private data of machine driver
1963 * @card: sound card pointer reference
1964 * @mbhc_cfg: MBHC config reference
1965 *
1966 * Returns 0 on success or ret on failure.
1967 */
1968int msm_ext_cdc_init(struct platform_device *pdev,
1969 struct msm_asoc_mach_data *pdata,
1970 struct snd_soc_card **card,
1971 struct wcd_mbhc_config *wcd_mbhc_cfg_ptr1)
1972{
1973 int ret = 0;
1974
1975 wcd_mbhc_cfg_ptr = wcd_mbhc_cfg_ptr1;
1976 pdev->id = 0;
1977 wcd_mbhc_cfg_ptr->moisture_en = true;
1978 wcd_mbhc_cfg_ptr->mbhc_micbias = MIC_BIAS_2;
1979 wcd_mbhc_cfg_ptr->anc_micbias = MIC_BIAS_2;
1980 wcd_mbhc_cfg_ptr->enable_anc_mic_detect = false;
1981
1982 *card = populate_snd_card_dailinks(&pdev->dev, pdata->snd_card_val);
1983 if (!(*card)) {
1984 dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__);
1985 ret = -EPROBE_DEFER;
1986 goto err;
1987 }
1988 platform_set_drvdata(pdev, *card);
1989 snd_soc_card_set_drvdata(*card, pdata);
1990 pdata->hph_en1_gpio = of_get_named_gpio(pdev->dev.of_node,
1991 "qcom,hph-en1-gpio", 0);
1992 if (!gpio_is_valid(pdata->hph_en1_gpio))
1993 pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node,
1994 "qcom,hph-en1-gpio", 0);
1995 if (!gpio_is_valid(pdata->hph_en1_gpio) && (!pdata->hph_en1_gpio_p)) {
1996 dev_dbg(&pdev->dev, "property %s not detected in node %s",
1997 "qcom,hph-en1-gpio", pdev->dev.of_node->full_name);
1998 }
1999
2000 pdata->hph_en0_gpio = of_get_named_gpio(pdev->dev.of_node,
2001 "qcom,hph-en0-gpio", 0);
2002 if (!gpio_is_valid(pdata->hph_en0_gpio))
2003 pdata->hph_en0_gpio_p = of_parse_phandle(pdev->dev.of_node,
2004 "qcom,hph-en0-gpio", 0);
2005 if (!gpio_is_valid(pdata->hph_en0_gpio) && (!pdata->hph_en0_gpio_p)) {
2006 dev_dbg(&pdev->dev, "property %s not detected in node %s",
2007 "qcom,hph-en0-gpio", pdev->dev.of_node->full_name);
2008 }
2009
2010 ret = msm_ext_prepare_hifi(pdata);
2011 if (ret) {
2012 dev_dbg(&pdev->dev, "msm_ext_prepare_hifi failed (%d)\n",
2013 ret);
2014 ret = 0;
2015 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302016err:
2017 return ret;
2018}
2019EXPORT_SYMBOL(msm_ext_cdc_init);