blob: ca1d2aa33c7a10285dd038e51992151de37aff65 [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"
Dhanalakshmi Siddani7ce33bb2018-11-28 22:01:53 +053025#include "codecs/msm-cdc-pinctrl.h"
Laxminath Kasam605b42f2017-08-01 22:02:15 +053026#include "codecs/wcd9335.h"
27#include "codecs/wcd934x/wcd934x.h"
28#include "codecs/wcd934x/wcd934x-mbhc.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053029
30#define SDM660_SPK_ON 1
31#define SDM660_SPK_OFF 0
32
33#define WCD9XXX_MBHC_DEF_BUTTONS 8
34#define WCD9XXX_MBHC_DEF_RLOADS 5
35#define CODEC_EXT_CLK_RATE 9600000
36#define ADSP_STATE_READY_TIMEOUT_MS 3000
37
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053038#define WSA8810_NAME_1 "wsa881x.20170211"
39#define WSA8810_NAME_2 "wsa881x.20170212"
40
Dhanalakshmi Siddani7ce33bb2018-11-28 22:01:53 +053041#define MSM_HIFI_ON 1
42
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053043static int msm_ext_spk_control = 1;
44static struct wcd_mbhc_config *wcd_mbhc_cfg_ptr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053045
46struct msm_asoc_wcd93xx_codec {
47 void* (*get_afe_config_fn)(struct snd_soc_codec *codec,
48 enum afe_config_type config_type);
49 void (*mbhc_hs_detect_exit)(struct snd_soc_codec *codec);
50};
51
52static struct msm_asoc_wcd93xx_codec msm_codec_fn;
53static struct platform_device *spdev;
Dhanalakshmi Siddani7ce33bb2018-11-28 22:01:53 +053054static int msm_hifi_control;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053055
56static bool is_initial_boot;
57
58static void *def_ext_mbhc_cal(void);
59
60enum {
61 SLIM_RX_0 = 0,
62 SLIM_RX_1,
63 SLIM_RX_2,
64 SLIM_RX_3,
65 SLIM_RX_4,
66 SLIM_RX_5,
67 SLIM_RX_6,
68 SLIM_RX_7,
69 SLIM_RX_MAX,
70};
71
72enum {
73 SLIM_TX_0 = 0,
74 SLIM_TX_1,
75 SLIM_TX_2,
76 SLIM_TX_3,
77 SLIM_TX_4,
78 SLIM_TX_5,
79 SLIM_TX_6,
80 SLIM_TX_7,
81 SLIM_TX_8,
82 SLIM_TX_MAX,
83};
84
85struct dev_config {
86 u32 sample_rate;
87 u32 bit_format;
88 u32 channels;
89};
90
91/* Default configuration of slimbus channels */
92static struct dev_config slim_rx_cfg[] = {
93 [SLIM_RX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
94 [SLIM_RX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
95 [SLIM_RX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
96 [SLIM_RX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
97 [SLIM_RX_4] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
98 [SLIM_RX_5] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
99 [SLIM_RX_6] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
100 [SLIM_RX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
101};
102
103static struct dev_config slim_tx_cfg[] = {
104 [SLIM_TX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
105 [SLIM_TX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
106 [SLIM_TX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
107 [SLIM_TX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
108 [SLIM_TX_4] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
109 [SLIM_TX_5] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
110 [SLIM_TX_6] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
111 [SLIM_TX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
112 [SLIM_TX_8] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
113};
114
Surendar Karka813c3d22018-11-05 13:46:17 +0530115static struct snd_soc_jack linein_jack;
116
117static struct snd_soc_jack_pin linein_jack_pins[] = {
118 {
119 .pin = "Linein",
120 .mask = SND_JACK_LINEIN,
121 },
122};
123
124static struct snd_soc_jack_gpio linein_jack_gpio = {
125 .name = "Linein detection",
126 .report = SND_JACK_LINEIN,
127 .debounce_time = 800,
128};
129
130static struct snd_soc_jack lineout_jack;
131
132static struct snd_soc_jack_pin lineout_jack_pins[] = {
133 {
134 .pin = "Lineout",
135 .mask = SND_JACK_LINEOUT,
136 },
137};
138
139static struct snd_soc_jack_gpio lineout_jack_gpio = {
140 .name = "Lineout detection",
141 .report = SND_JACK_LINEOUT,
142 .debounce_time = 800,
143};
144
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530145static int msm_vi_feed_tx_ch = 2;
Dhanalakshmi Siddani7ce33bb2018-11-28 22:01:53 +0530146static const char *const slim_rx_ch_text[] = {"One", "Two", "Three", "Four",
147 "Five", "Six", "Seven",
148 "Eight"};
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530149static const char *const slim_tx_ch_text[] = {"One", "Two", "Three", "Four",
150 "Five", "Six", "Seven",
151 "Eight"};
152static const char *const vi_feed_ch_text[] = {"One", "Two"};
153static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE",
154 "S32_LE"};
155static char const *slim_sample_rate_text[] = {"KHZ_8", "KHZ_16",
156 "KHZ_32", "KHZ_44P1", "KHZ_48",
157 "KHZ_88P2", "KHZ_96", "KHZ_176P4",
158 "KHZ_192", "KHZ_352P8", "KHZ_384"};
159static const char *const spk_function_text[] = {"Off", "On"};
Preetam Singh Ranawat66f1f212017-12-05 15:30:24 +0530160static char const *bt_sample_rate_text[] = {"KHZ_8", "KHZ_16",
161 "KHZ_44P1", "KHZ_48",
162 "KHZ_88P2", "KHZ_96"};
Preetam Singh Ranawatd79190a2018-06-25 15:59:23 +0530163static char const *bt_sample_rate_rx_text[] = {"KHZ_8", "KHZ_16",
164 "KHZ_44P1", "KHZ_48",
165 "KHZ_88P2", "KHZ_96"};
166static char const *bt_sample_rate_tx_text[] = {"KHZ_8", "KHZ_16",
167 "KHZ_44P1", "KHZ_48",
168 "KHZ_88P2", "KHZ_96"};
Dhanalakshmi Siddani7ce33bb2018-11-28 22:01:53 +0530169static const char *const hifi_text[] = {"Off", "On"};
170
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530171static SOC_ENUM_SINGLE_EXT_DECL(spk_func_en, spk_function_text);
172static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_chs, slim_rx_ch_text);
173static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_chs, slim_rx_ch_text);
174static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_chs, slim_tx_ch_text);
175static SOC_ENUM_SINGLE_EXT_DECL(slim_1_tx_chs, slim_tx_ch_text);
176static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_chs, slim_rx_ch_text);
177static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_chs, slim_rx_ch_text);
178static SOC_ENUM_SINGLE_EXT_DECL(vi_feed_tx_chs, vi_feed_ch_text);
179static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_format, bit_format_text);
180static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_format, bit_format_text);
181static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_format, bit_format_text);
182static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_format, bit_format_text);
183static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_sample_rate, slim_sample_rate_text);
184static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_sample_rate, slim_sample_rate_text);
185static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text);
186static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_sample_rate, slim_sample_rate_text);
187static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_sample_rate, slim_sample_rate_text);
188static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
Preetam Singh Ranawatd79190a2018-06-25 15:59:23 +0530189static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_rx, bt_sample_rate_rx_text);
190static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_tx, bt_sample_rate_tx_text);
Dhanalakshmi Siddani7ce33bb2018-11-28 22:01:53 +0530191static SOC_ENUM_SINGLE_EXT_DECL(hifi_function, hifi_text);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530192
193static int slim_get_sample_rate_val(int sample_rate)
194{
195 int sample_rate_val = 0;
196
197 switch (sample_rate) {
198 case SAMPLING_RATE_8KHZ:
199 sample_rate_val = 0;
200 break;
201 case SAMPLING_RATE_16KHZ:
202 sample_rate_val = 1;
203 break;
204 case SAMPLING_RATE_32KHZ:
205 sample_rate_val = 2;
206 break;
207 case SAMPLING_RATE_44P1KHZ:
208 sample_rate_val = 3;
209 break;
210 case SAMPLING_RATE_48KHZ:
211 sample_rate_val = 4;
212 break;
213 case SAMPLING_RATE_88P2KHZ:
214 sample_rate_val = 5;
215 break;
216 case SAMPLING_RATE_96KHZ:
217 sample_rate_val = 6;
218 break;
219 case SAMPLING_RATE_176P4KHZ:
220 sample_rate_val = 7;
221 break;
222 case SAMPLING_RATE_192KHZ:
223 sample_rate_val = 8;
224 break;
225 case SAMPLING_RATE_352P8KHZ:
226 sample_rate_val = 9;
227 break;
228 case SAMPLING_RATE_384KHZ:
229 sample_rate_val = 10;
230 break;
231 default:
232 sample_rate_val = 4;
233 break;
234 }
235 return sample_rate_val;
236}
237
238static int slim_get_sample_rate(int value)
239{
240 int sample_rate = 0;
241
242 switch (value) {
243 case 0:
244 sample_rate = SAMPLING_RATE_8KHZ;
245 break;
246 case 1:
247 sample_rate = SAMPLING_RATE_16KHZ;
248 break;
249 case 2:
250 sample_rate = SAMPLING_RATE_32KHZ;
251 break;
252 case 3:
253 sample_rate = SAMPLING_RATE_44P1KHZ;
254 break;
255 case 4:
256 sample_rate = SAMPLING_RATE_48KHZ;
257 break;
258 case 5:
259 sample_rate = SAMPLING_RATE_88P2KHZ;
260 break;
261 case 6:
262 sample_rate = SAMPLING_RATE_96KHZ;
263 break;
264 case 7:
265 sample_rate = SAMPLING_RATE_176P4KHZ;
266 break;
267 case 8:
268 sample_rate = SAMPLING_RATE_192KHZ;
269 break;
270 case 9:
271 sample_rate = SAMPLING_RATE_352P8KHZ;
272 break;
273 case 10:
274 sample_rate = SAMPLING_RATE_384KHZ;
275 break;
276 default:
277 sample_rate = SAMPLING_RATE_48KHZ;
278 break;
279 }
280 return sample_rate;
281}
282
283static int slim_get_bit_format_val(int bit_format)
284{
285 int val = 0;
286
287 switch (bit_format) {
288 case SNDRV_PCM_FORMAT_S32_LE:
289 val = 3;
290 break;
291 case SNDRV_PCM_FORMAT_S24_3LE:
292 val = 2;
293 break;
294 case SNDRV_PCM_FORMAT_S24_LE:
295 val = 1;
296 break;
297 case SNDRV_PCM_FORMAT_S16_LE:
298 default:
299 val = 0;
300 break;
301 }
302 return val;
303}
304
305static int slim_get_bit_format(int val)
306{
307 int bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
308
309 switch (val) {
310 case 0:
311 bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
312 break;
313 case 1:
314 bit_fmt = SNDRV_PCM_FORMAT_S24_LE;
315 break;
316 case 2:
317 bit_fmt = SNDRV_PCM_FORMAT_S24_3LE;
318 break;
319 case 3:
320 bit_fmt = SNDRV_PCM_FORMAT_S32_LE;
321 break;
322 default:
323 bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
324 break;
325 }
326 return bit_fmt;
327}
328
329static int slim_get_port_idx(struct snd_kcontrol *kcontrol)
330{
331 int port_id = 0;
332
333 if (strnstr(kcontrol->id.name, "SLIM_0_RX", sizeof("SLIM_0_RX")))
334 port_id = SLIM_RX_0;
335 else if (strnstr(kcontrol->id.name, "SLIM_2_RX", sizeof("SLIM_2_RX")))
336 port_id = SLIM_RX_2;
337 else if (strnstr(kcontrol->id.name, "SLIM_5_RX", sizeof("SLIM_5_RX")))
338 port_id = SLIM_RX_5;
339 else if (strnstr(kcontrol->id.name, "SLIM_6_RX", sizeof("SLIM_6_RX")))
340 port_id = SLIM_RX_6;
341 else if (strnstr(kcontrol->id.name, "SLIM_0_TX", sizeof("SLIM_0_TX")))
342 port_id = SLIM_TX_0;
343 else if (strnstr(kcontrol->id.name, "SLIM_1_TX", sizeof("SLIM_1_TX")))
344 port_id = SLIM_TX_1;
345 else {
346 pr_err("%s: unsupported channel: %s",
347 __func__, kcontrol->id.name);
348 return -EINVAL;
349 }
350
351 return port_id;
352}
353
354static int msm_bt_sample_rate_get(struct snd_kcontrol *kcontrol,
355 struct snd_ctl_elem_value *ucontrol)
356{
357 /*
358 * Slimbus_7_Rx/Tx sample rate values should always be in sync (same)
359 * when used for BT_SCO use case. Return either Rx or Tx sample rate
360 * value.
361 */
362 switch (slim_rx_cfg[SLIM_RX_7].sample_rate) {
Preetam Singh Ranawat66f1f212017-12-05 15:30:24 +0530363 case SAMPLING_RATE_96KHZ:
364 ucontrol->value.integer.value[0] = 5;
365 break;
366 case SAMPLING_RATE_88P2KHZ:
367 ucontrol->value.integer.value[0] = 4;
368 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530369 case SAMPLING_RATE_48KHZ:
Preetam Singh Ranawat66f1f212017-12-05 15:30:24 +0530370 ucontrol->value.integer.value[0] = 3;
371 break;
372 case SAMPLING_RATE_44P1KHZ:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530373 ucontrol->value.integer.value[0] = 2;
374 break;
375 case SAMPLING_RATE_16KHZ:
376 ucontrol->value.integer.value[0] = 1;
377 break;
378 case SAMPLING_RATE_8KHZ:
379 default:
380 ucontrol->value.integer.value[0] = 0;
381 break;
382 }
383 pr_debug("%s: sample rate = %d", __func__,
384 slim_rx_cfg[SLIM_RX_7].sample_rate);
385
386 return 0;
387}
388
389static int msm_bt_sample_rate_put(struct snd_kcontrol *kcontrol,
390 struct snd_ctl_elem_value *ucontrol)
391{
392 switch (ucontrol->value.integer.value[0]) {
393 case 1:
394 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_16KHZ;
395 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_16KHZ;
396 break;
397 case 2:
Preetam Singh Ranawat66f1f212017-12-05 15:30:24 +0530398 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
399 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
400 break;
401 case 3:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530402 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_48KHZ;
403 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_48KHZ;
404 break;
Preetam Singh Ranawat66f1f212017-12-05 15:30:24 +0530405 case 4:
406 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
407 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
408 break;
409 case 5:
410 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_96KHZ;
411 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_96KHZ;
412 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530413 case 0:
414 default:
415 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_8KHZ;
416 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_8KHZ;
417 break;
418 }
419 pr_debug("%s: sample rates: slim7_rx = %d, slim7_tx = %d, value = %d\n",
420 __func__,
421 slim_rx_cfg[SLIM_RX_7].sample_rate,
422 slim_tx_cfg[SLIM_TX_7].sample_rate,
423 ucontrol->value.enumerated.item[0]);
424
425 return 0;
426}
427
Preetam Singh Ranawatd79190a2018-06-25 15:59:23 +0530428static int msm_bt_sample_rate_rx_get(struct snd_kcontrol *kcontrol,
429 struct snd_ctl_elem_value *ucontrol)
430{
431 switch (slim_rx_cfg[SLIM_RX_7].sample_rate) {
432 case SAMPLING_RATE_96KHZ:
433 ucontrol->value.integer.value[0] = 5;
434 break;
435 case SAMPLING_RATE_88P2KHZ:
436 ucontrol->value.integer.value[0] = 4;
437 break;
438 case SAMPLING_RATE_48KHZ:
439 ucontrol->value.integer.value[0] = 3;
440 break;
441 case SAMPLING_RATE_44P1KHZ:
442 ucontrol->value.integer.value[0] = 2;
443 break;
444 case SAMPLING_RATE_16KHZ:
445 ucontrol->value.integer.value[0] = 1;
446 break;
447 case SAMPLING_RATE_8KHZ:
448 default:
449 ucontrol->value.integer.value[0] = 0;
450 break;
451 }
452 pr_debug("%s: sample rate = %d", __func__,
453 slim_rx_cfg[SLIM_RX_7].sample_rate);
454
455 return 0;
456}
457
458static int msm_bt_sample_rate_rx_put(struct snd_kcontrol *kcontrol,
459 struct snd_ctl_elem_value *ucontrol)
460{
461 switch (ucontrol->value.integer.value[0]) {
462 case 1:
463 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_16KHZ;
464 break;
465 case 2:
466 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
467 break;
468 case 3:
469 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_48KHZ;
470 break;
471 case 4:
472 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
473 break;
474 case 5:
475 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_96KHZ;
476 break;
477 case 0:
478 default:
479 slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_8KHZ;
480 break;
481 }
482 pr_debug("%s: sample rates: slim7_rx = %d, value = %d\n",
483 __func__,
484 slim_rx_cfg[SLIM_RX_7].sample_rate,
485 ucontrol->value.enumerated.item[0]);
486
487 return 0;
488}
489
490static int msm_bt_sample_rate_tx_get(struct snd_kcontrol *kcontrol,
491 struct snd_ctl_elem_value *ucontrol)
492{
493 switch (slim_tx_cfg[SLIM_TX_7].sample_rate) {
494 case SAMPLING_RATE_96KHZ:
495 ucontrol->value.integer.value[0] = 5;
496 break;
497 case SAMPLING_RATE_88P2KHZ:
498 ucontrol->value.integer.value[0] = 4;
499 break;
500 case SAMPLING_RATE_48KHZ:
501 ucontrol->value.integer.value[0] = 3;
502 break;
503 case SAMPLING_RATE_44P1KHZ:
504 ucontrol->value.integer.value[0] = 2;
505 break;
506 case SAMPLING_RATE_16KHZ:
507 ucontrol->value.integer.value[0] = 1;
508 break;
509 case SAMPLING_RATE_8KHZ:
510 default:
511 ucontrol->value.integer.value[0] = 0;
512 break;
513 }
514 pr_debug("%s: sample rate = %d", __func__,
515 slim_tx_cfg[SLIM_TX_7].sample_rate);
516
517 return 0;
518}
519
520static int msm_bt_sample_rate_tx_put(struct snd_kcontrol *kcontrol,
521 struct snd_ctl_elem_value *ucontrol)
522{
523 switch (ucontrol->value.integer.value[0]) {
524 case 1:
525 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_16KHZ;
526 break;
527 case 2:
528 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
529 break;
530 case 3:
531 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_48KHZ;
532 break;
533 case 4:
534 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
535 break;
536 case 5:
537 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_96KHZ;
538 break;
539 case 0:
540 default:
541 slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_8KHZ;
542 break;
543 }
544 pr_debug("%s: sample rates: slim7_tx = %d, value = %d\n",
545 __func__,
546 slim_tx_cfg[SLIM_TX_7].sample_rate,
547 ucontrol->value.enumerated.item[0]);
548
549 return 0;
550}
551
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530552static int slim_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
553 struct snd_ctl_elem_value *ucontrol)
554{
555 int ch_num = slim_get_port_idx(kcontrol);
556
557 if (ch_num < 0)
558 return ch_num;
559
560 ucontrol->value.enumerated.item[0] =
561 slim_get_sample_rate_val(slim_rx_cfg[ch_num].sample_rate);
562
563 pr_debug("%s: slim[%d]_rx_sample_rate = %d, item = %d\n", __func__,
564 ch_num, slim_rx_cfg[ch_num].sample_rate,
565 ucontrol->value.enumerated.item[0]);
566
567 return 0;
568}
569
570static int slim_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
571 struct snd_ctl_elem_value *ucontrol)
572{
573 int ch_num = slim_get_port_idx(kcontrol);
574
575 if (ch_num < 0)
576 return ch_num;
577
578 slim_rx_cfg[ch_num].sample_rate =
579 slim_get_sample_rate(ucontrol->value.enumerated.item[0]);
580
581 pr_debug("%s: slim[%d]_rx_sample_rate = %d, item = %d\n", __func__,
582 ch_num, slim_rx_cfg[ch_num].sample_rate,
583 ucontrol->value.enumerated.item[0]);
584
585 return 0;
586}
587
588static int slim_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
589 struct snd_ctl_elem_value *ucontrol)
590{
591 int ch_num = slim_get_port_idx(kcontrol);
592
593 if (ch_num < 0)
594 return ch_num;
595
596 ucontrol->value.enumerated.item[0] =
597 slim_get_sample_rate_val(slim_tx_cfg[ch_num].sample_rate);
598
599 pr_debug("%s: slim[%d]_tx_sample_rate = %d, item = %d\n", __func__,
600 ch_num, slim_tx_cfg[ch_num].sample_rate,
601 ucontrol->value.enumerated.item[0]);
602
603 return 0;
604}
605
606static int slim_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
607 struct snd_ctl_elem_value *ucontrol)
608{
609 int sample_rate = 0;
610 int ch_num = slim_get_port_idx(kcontrol);
611
612 if (ch_num < 0)
613 return ch_num;
614
615 sample_rate = slim_get_sample_rate(ucontrol->value.enumerated.item[0]);
616 if (sample_rate == SAMPLING_RATE_44P1KHZ) {
617 pr_err("%s: Unsupported sample rate %d: for Tx path\n",
618 __func__, sample_rate);
619 return -EINVAL;
620 }
621 slim_tx_cfg[ch_num].sample_rate = sample_rate;
622
623 pr_debug("%s: slim[%d]_tx_sample_rate = %d, value = %d\n", __func__,
624 ch_num, slim_tx_cfg[ch_num].sample_rate,
625 ucontrol->value.enumerated.item[0]);
626
627 return 0;
628}
629
630static int slim_rx_bit_format_get(struct snd_kcontrol *kcontrol,
631 struct snd_ctl_elem_value *ucontrol)
632{
633 int ch_num = slim_get_port_idx(kcontrol);
634
635 if (ch_num < 0)
636 return ch_num;
637
638 ucontrol->value.enumerated.item[0] =
639 slim_get_bit_format_val(slim_rx_cfg[ch_num].bit_format);
640
641 pr_debug("%s: slim[%d]_rx_bit_format = %d, ucontrol value = %d\n",
642 __func__, ch_num, slim_rx_cfg[ch_num].bit_format,
643 ucontrol->value.enumerated.item[0]);
644
645 return 0;
646}
647
648static int slim_rx_bit_format_put(struct snd_kcontrol *kcontrol,
649 struct snd_ctl_elem_value *ucontrol)
650{
651 int ch_num = slim_get_port_idx(kcontrol);
652
653 if (ch_num < 0)
654 return ch_num;
655
656 slim_rx_cfg[ch_num].bit_format =
657 slim_get_bit_format(ucontrol->value.enumerated.item[0]);
658
659 pr_debug("%s: slim[%d]_rx_bit_format = %d, ucontrol value = %d\n",
660 __func__, ch_num, slim_rx_cfg[ch_num].bit_format,
661 ucontrol->value.enumerated.item[0]);
662
663 return 0;
664}
665
666static int slim_tx_bit_format_get(struct snd_kcontrol *kcontrol,
667 struct snd_ctl_elem_value *ucontrol)
668{
669 int ch_num = slim_get_port_idx(kcontrol);
670
671 if (ch_num < 0)
672 return ch_num;
673
674 ucontrol->value.enumerated.item[0] =
675 slim_get_bit_format_val(slim_tx_cfg[ch_num].bit_format);
676
677 pr_debug("%s: slim[%d]_tx_bit_format = %d, ucontrol value = %d\n",
678 __func__, ch_num, slim_tx_cfg[ch_num].bit_format,
679 ucontrol->value.enumerated.item[0]);
680
681 return 0;
682}
683
684static int slim_tx_bit_format_put(struct snd_kcontrol *kcontrol,
685 struct snd_ctl_elem_value *ucontrol)
686{
687 int ch_num = slim_get_port_idx(kcontrol);
688
689 if (ch_num < 0)
690 return ch_num;
691
692 slim_tx_cfg[ch_num].bit_format =
693 slim_get_bit_format(ucontrol->value.enumerated.item[0]);
694
695 pr_debug("%s: slim[%d]_tx_bit_format = %d, ucontrol value = %d\n",
696 __func__, ch_num, slim_tx_cfg[ch_num].bit_format,
697 ucontrol->value.enumerated.item[0]);
698
699 return 0;
700}
701
702static int msm_slim_rx_ch_get(struct snd_kcontrol *kcontrol,
703 struct snd_ctl_elem_value *ucontrol)
704{
705 int ch_num = slim_get_port_idx(kcontrol);
706
707 if (ch_num < 0)
708 return ch_num;
709
710 pr_debug("%s: msm_slim_[%d]_rx_ch = %d\n", __func__,
711 ch_num, slim_rx_cfg[ch_num].channels);
712 ucontrol->value.enumerated.item[0] = slim_rx_cfg[ch_num].channels - 1;
713
714 return 0;
715}
716
717static int msm_slim_rx_ch_put(struct snd_kcontrol *kcontrol,
718 struct snd_ctl_elem_value *ucontrol)
719{
720 int ch_num = slim_get_port_idx(kcontrol);
721
722 if (ch_num < 0)
723 return ch_num;
724
725 slim_rx_cfg[ch_num].channels = ucontrol->value.enumerated.item[0] + 1;
726 pr_debug("%s: msm_slim_[%d]_rx_ch = %d\n", __func__,
727 ch_num, slim_rx_cfg[ch_num].channels);
728
729 return 1;
730}
731
732static int msm_slim_tx_ch_get(struct snd_kcontrol *kcontrol,
733 struct snd_ctl_elem_value *ucontrol)
734{
735 int ch_num = slim_get_port_idx(kcontrol);
736
737 if (ch_num < 0)
738 return ch_num;
739
740 pr_debug("%s: msm_slim_[%d]_tx_ch = %d\n", __func__,
741 ch_num, slim_tx_cfg[ch_num].channels);
742 ucontrol->value.enumerated.item[0] = slim_tx_cfg[ch_num].channels - 1;
743
744 return 0;
745}
746
747static int msm_slim_tx_ch_put(struct snd_kcontrol *kcontrol,
748 struct snd_ctl_elem_value *ucontrol)
749{
750 int ch_num = slim_get_port_idx(kcontrol);
751
752 if (ch_num < 0)
753 return ch_num;
754
755 slim_tx_cfg[ch_num].channels = ucontrol->value.enumerated.item[0] + 1;
756 pr_debug("%s: msm_slim_[%d]_tx_ch = %d\n", __func__,
757 ch_num, slim_tx_cfg[ch_num].channels);
758
759 return 1;
760}
761
762static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol,
763 struct snd_ctl_elem_value *ucontrol)
764{
765 ucontrol->value.integer.value[0] = msm_vi_feed_tx_ch - 1;
766 pr_debug("%s: msm_vi_feed_tx_ch = %ld\n", __func__,
767 ucontrol->value.integer.value[0]);
768 return 0;
769}
770
771static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol,
772 struct snd_ctl_elem_value *ucontrol)
773{
774 msm_vi_feed_tx_ch = ucontrol->value.integer.value[0] + 1;
775
776 pr_debug("%s: msm_vi_feed_tx_ch = %d\n", __func__, msm_vi_feed_tx_ch);
777 return 1;
778}
779
Dhanalakshmi Siddani7ce33bb2018-11-28 22:01:53 +0530780static int msm_hifi_ctrl(struct snd_soc_codec *codec)
781{
782 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
783 struct snd_soc_card *card = codec->component.card;
784 struct msm_asoc_mach_data *pdata =
785 snd_soc_card_get_drvdata(card);
786
787 pr_debug("%s: msm_hifi_control = %d\n", __func__,
788 msm_hifi_control);
789
790 if (!pdata || !pdata->hph_en1_gpio_p) {
791 pr_err("%s: hph_en1_gpio is invalid\n", __func__);
792 return -EINVAL;
793 }
794 if (msm_hifi_control == MSM_HIFI_ON) {
795 msm_cdc_pinctrl_select_active_state(pdata->hph_en1_gpio_p);
796 /* 5msec delay needed as per HW requirement */
797 usleep_range(5000, 5010);
798 } else {
799 msm_cdc_pinctrl_select_sleep_state(pdata->hph_en1_gpio_p);
800 }
801 snd_soc_dapm_sync(dapm);
802
803 return 0;
804}
805
806static int msm_hifi_get(struct snd_kcontrol *kcontrol,
807 struct snd_ctl_elem_value *ucontrol)
808{
809 pr_debug("%s: msm_hifi_control = %d\n",
810 __func__, msm_hifi_control);
811 ucontrol->value.integer.value[0] = msm_hifi_control;
812
813 return 0;
814}
815
816static int msm_hifi_put(struct snd_kcontrol *kcontrol,
817 struct snd_ctl_elem_value *ucontrol)
818{
819 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
820
821 pr_debug("%s() ucontrol->value.integer.value[0] = %ld\n",
822 __func__, ucontrol->value.integer.value[0]);
823
824 msm_hifi_control = ucontrol->value.integer.value[0];
825 msm_hifi_ctrl(codec);
826
827 return 0;
828}
829
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530830static void *def_ext_mbhc_cal(void)
831{
Laxminath Kasam38070be2017-08-17 18:21:59 +0530832 void *wcd_mbhc_cal;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530833 struct wcd_mbhc_btn_detect_cfg *btn_cfg;
834 u16 *btn_high;
835
Laxminath Kasam38070be2017-08-17 18:21:59 +0530836 wcd_mbhc_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530837 WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL);
Laxminath Kasam38070be2017-08-17 18:21:59 +0530838 if (!wcd_mbhc_cal)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530839 return NULL;
840
Laxminath Kasam38070be2017-08-17 18:21:59 +0530841#define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(wcd_mbhc_cal)->X) = (Y))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530842 S(v_hs_max, 1600);
843#undef S
Laxminath Kasam38070be2017-08-17 18:21:59 +0530844#define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal)->X) = (Y))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530845 S(num_btn, WCD_MBHC_DEF_BUTTONS);
846#undef S
847
Laxminath Kasam38070be2017-08-17 18:21:59 +0530848 btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530849 btn_high = ((void *)&btn_cfg->_v_btn_low) +
850 (sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
851
852 btn_high[0] = 75;
853 btn_high[1] = 150;
854 btn_high[2] = 237;
855 btn_high[3] = 500;
856 btn_high[4] = 500;
857 btn_high[5] = 500;
858 btn_high[6] = 500;
859 btn_high[7] = 500;
860
Laxminath Kasam38070be2017-08-17 18:21:59 +0530861 return wcd_mbhc_cal;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530862}
863
864static inline int param_is_mask(int p)
865{
866 return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
867 (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
868}
869
870static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
871{
872 return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
873}
874
875
876static void msm_ext_control(struct snd_soc_codec *codec)
877{
878 struct snd_soc_dapm_context *dapm =
879 snd_soc_codec_get_dapm(codec);
880
881 pr_debug("%s: msm_ext_spk_control = %d", __func__, msm_ext_spk_control);
882 if (msm_ext_spk_control == SDM660_SPK_ON) {
883 snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp");
884 snd_soc_dapm_enable_pin(dapm, "Lineout_3 amp");
885 } else {
886 snd_soc_dapm_disable_pin(dapm, "Lineout_1 amp");
887 snd_soc_dapm_disable_pin(dapm, "Lineout_3 amp");
888 }
889 snd_soc_dapm_sync(dapm);
890}
891
892static int msm_ext_get_spk(struct snd_kcontrol *kcontrol,
893 struct snd_ctl_elem_value *ucontrol)
894{
895 pr_debug("%s: msm_ext_spk_control = %d\n",
896 __func__, msm_ext_spk_control);
897 ucontrol->value.integer.value[0] = msm_ext_spk_control;
898 return 0;
899}
900
901static int msm_ext_set_spk(struct snd_kcontrol *kcontrol,
902 struct snd_ctl_elem_value *ucontrol)
903{
904 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
905
906 pr_debug("%s()\n", __func__);
907 if (msm_ext_spk_control == ucontrol->value.integer.value[0])
908 return 0;
909
910 msm_ext_spk_control = ucontrol->value.integer.value[0];
911 msm_ext_control(codec);
912 return 1;
913}
914
915
916int msm_ext_enable_codec_mclk(struct snd_soc_codec *codec, int enable,
917 bool dapm)
918{
919 int ret;
920
921 pr_debug("%s: enable = %d\n", __func__, enable);
922
923 if (!strcmp(dev_name(codec->dev), "tasha_codec"))
924 ret = tasha_cdc_mclk_enable(codec, enable, dapm);
925 else if (!strcmp(dev_name(codec->dev), "tavil_codec"))
926 ret = tavil_cdc_mclk_enable(codec, enable);
927 else {
928 dev_err(codec->dev, "%s: unknown codec to enable ext clk\n",
929 __func__);
930 ret = -EINVAL;
931 }
932 return ret;
933}
934
935static const struct snd_kcontrol_new msm_snd_controls[] = {
936 SOC_ENUM_EXT("Speaker Function", spk_func_en, msm_ext_get_spk,
937 msm_ext_set_spk),
938 SOC_ENUM_EXT("SLIM_0_RX Channels", slim_0_rx_chs,
939 msm_slim_rx_ch_get, msm_slim_rx_ch_put),
940 SOC_ENUM_EXT("SLIM_2_RX Channels", slim_2_rx_chs,
941 msm_slim_rx_ch_get, msm_slim_rx_ch_put),
942 SOC_ENUM_EXT("SLIM_0_TX Channels", slim_0_tx_chs,
943 msm_slim_tx_ch_get, msm_slim_tx_ch_put),
944 SOC_ENUM_EXT("SLIM_1_TX Channels", slim_1_tx_chs,
945 msm_slim_tx_ch_get, msm_slim_tx_ch_put),
946 SOC_ENUM_EXT("SLIM_5_RX Channels", slim_5_rx_chs,
947 msm_slim_rx_ch_get, msm_slim_rx_ch_put),
948 SOC_ENUM_EXT("SLIM_6_RX Channels", slim_6_rx_chs,
949 msm_slim_rx_ch_get, msm_slim_rx_ch_put),
950 SOC_ENUM_EXT("VI_FEED_TX Channels", vi_feed_tx_chs,
951 msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
952 SOC_ENUM_EXT("SLIM_0_RX Format", slim_0_rx_format,
953 slim_rx_bit_format_get, slim_rx_bit_format_put),
954 SOC_ENUM_EXT("SLIM_5_RX Format", slim_5_rx_format,
955 slim_rx_bit_format_get, slim_rx_bit_format_put),
956 SOC_ENUM_EXT("SLIM_6_RX Format", slim_6_rx_format,
957 slim_rx_bit_format_get, slim_rx_bit_format_put),
958 SOC_ENUM_EXT("SLIM_0_TX Format", slim_0_tx_format,
959 slim_tx_bit_format_get, slim_tx_bit_format_put),
960 SOC_ENUM_EXT("SLIM_0_RX SampleRate", slim_0_rx_sample_rate,
961 slim_rx_sample_rate_get, slim_rx_sample_rate_put),
962 SOC_ENUM_EXT("SLIM_2_RX SampleRate", slim_2_rx_sample_rate,
963 slim_rx_sample_rate_get, slim_rx_sample_rate_put),
964 SOC_ENUM_EXT("SLIM_0_TX SampleRate", slim_0_tx_sample_rate,
965 slim_tx_sample_rate_get, slim_tx_sample_rate_put),
966 SOC_ENUM_EXT("SLIM_5_RX SampleRate", slim_5_rx_sample_rate,
967 slim_rx_sample_rate_get, slim_rx_sample_rate_put),
968 SOC_ENUM_EXT("SLIM_6_RX SampleRate", slim_6_rx_sample_rate,
969 slim_rx_sample_rate_get, slim_rx_sample_rate_put),
970 SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
971 msm_bt_sample_rate_get,
972 msm_bt_sample_rate_put),
Preetam Singh Ranawatd79190a2018-06-25 15:59:23 +0530973 SOC_ENUM_EXT("BT SampleRate RX", bt_sample_rate_rx,
974 msm_bt_sample_rate_rx_get,
975 msm_bt_sample_rate_rx_put),
976 SOC_ENUM_EXT("BT SampleRate TX", bt_sample_rate_tx,
977 msm_bt_sample_rate_tx_get,
978 msm_bt_sample_rate_tx_put),
Dhanalakshmi Siddani7ce33bb2018-11-28 22:01:53 +0530979 SOC_ENUM_EXT("HiFi Function", hifi_function, msm_hifi_get,
980 msm_hifi_put),
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530981};
982
Asish Bhattacharya84f7f732017-07-25 16:29:27 +0530983static int msm_slim_get_ch_from_beid(int32_t id)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530984{
985 int ch_id = 0;
986
Asish Bhattacharya84f7f732017-07-25 16:29:27 +0530987 switch (id) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530988 case MSM_BACKEND_DAI_SLIMBUS_0_RX:
989 ch_id = SLIM_RX_0;
990 break;
991 case MSM_BACKEND_DAI_SLIMBUS_1_RX:
992 ch_id = SLIM_RX_1;
993 break;
994 case MSM_BACKEND_DAI_SLIMBUS_2_RX:
995 ch_id = SLIM_RX_2;
996 break;
997 case MSM_BACKEND_DAI_SLIMBUS_3_RX:
998 ch_id = SLIM_RX_3;
999 break;
1000 case MSM_BACKEND_DAI_SLIMBUS_4_RX:
1001 ch_id = SLIM_RX_4;
1002 break;
1003 case MSM_BACKEND_DAI_SLIMBUS_6_RX:
1004 ch_id = SLIM_RX_6;
1005 break;
1006 case MSM_BACKEND_DAI_SLIMBUS_0_TX:
1007 ch_id = SLIM_TX_0;
1008 break;
1009 case MSM_BACKEND_DAI_SLIMBUS_3_TX:
1010 ch_id = SLIM_TX_3;
1011 break;
1012 default:
1013 ch_id = SLIM_RX_0;
1014 break;
1015 }
1016
1017 return ch_id;
1018}
1019
1020static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned int bit)
1021{
1022 if (bit >= SNDRV_MASK_MAX)
1023 return;
1024 if (param_is_mask(n)) {
1025 struct snd_mask *m = param_to_mask(p, n);
1026
1027 m->bits[0] = 0;
1028 m->bits[1] = 0;
1029 m->bits[bit >> 5] |= (1 << (bit & 31));
1030 }
1031}
1032
1033/**
1034 * msm_ext_be_hw_params_fixup - updates settings of ALSA BE hw params.
1035 *
1036 * @rtd: runtime dailink instance
1037 * @params: HW params of associated backend dailink.
1038 *
1039 * Returns 0 on success or rc on failure.
1040 */
1041int msm_ext_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1042 struct snd_pcm_hw_params *params)
1043{
1044 struct snd_soc_dai_link *dai_link = rtd->dai_link;
1045 struct snd_interval *rate = hw_param_interval(params,
1046 SNDRV_PCM_HW_PARAM_RATE);
1047 struct snd_interval *channels = hw_param_interval(params,
1048 SNDRV_PCM_HW_PARAM_CHANNELS);
1049 int rc = 0;
1050 int idx;
1051 void *config = NULL;
1052 struct snd_soc_codec *codec = rtd->codec;
1053
1054 pr_debug("%s: format = %d, rate = %d\n",
1055 __func__, params_format(params), params_rate(params));
1056
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301057 switch (dai_link->id) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301058 case MSM_BACKEND_DAI_SLIMBUS_0_RX:
1059 case MSM_BACKEND_DAI_SLIMBUS_1_RX:
1060 case MSM_BACKEND_DAI_SLIMBUS_2_RX:
1061 case MSM_BACKEND_DAI_SLIMBUS_3_RX:
1062 case MSM_BACKEND_DAI_SLIMBUS_4_RX:
1063 case MSM_BACKEND_DAI_SLIMBUS_6_RX:
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301064 idx = msm_slim_get_ch_from_beid(dai_link->id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301065 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
1066 slim_rx_cfg[idx].bit_format);
1067 rate->min = rate->max = slim_rx_cfg[idx].sample_rate;
1068 channels->min = channels->max = slim_rx_cfg[idx].channels;
1069 break;
1070
1071 case MSM_BACKEND_DAI_SLIMBUS_0_TX:
1072 case MSM_BACKEND_DAI_SLIMBUS_3_TX:
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301073 idx = msm_slim_get_ch_from_beid(dai_link->id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301074 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
1075 slim_tx_cfg[idx].bit_format);
1076 rate->min = rate->max = slim_tx_cfg[idx].sample_rate;
1077 channels->min = channels->max = slim_tx_cfg[idx].channels;
1078 break;
1079
1080 case MSM_BACKEND_DAI_SLIMBUS_1_TX:
1081 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
1082 slim_tx_cfg[1].bit_format);
1083 rate->min = rate->max = slim_tx_cfg[1].sample_rate;
1084 channels->min = channels->max = slim_tx_cfg[1].channels;
1085 break;
1086
1087 case MSM_BACKEND_DAI_SLIMBUS_4_TX:
1088 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
1089 SNDRV_PCM_FORMAT_S32_LE);
1090 rate->min = rate->max = SAMPLING_RATE_8KHZ;
1091 channels->min = channels->max = msm_vi_feed_tx_ch;
1092 break;
1093
1094 case MSM_BACKEND_DAI_SLIMBUS_5_RX:
1095 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
1096 slim_rx_cfg[5].bit_format);
1097 rate->min = rate->max = slim_rx_cfg[5].sample_rate;
1098 channels->min = channels->max = slim_rx_cfg[5].channels;
1099 break;
1100
1101 case MSM_BACKEND_DAI_SLIMBUS_5_TX:
1102 rate->min = rate->max = SAMPLING_RATE_16KHZ;
1103 channels->min = channels->max = 1;
1104
1105 config = msm_codec_fn.get_afe_config_fn(codec,
1106 AFE_SLIMBUS_SLAVE_PORT_CONFIG);
1107 if (config) {
1108 rc = afe_set_config(AFE_SLIMBUS_SLAVE_PORT_CONFIG,
1109 config, SLIMBUS_5_TX);
1110 if (rc)
1111 pr_err("%s: Failed to set slimbus slave port config %d\n",
1112 __func__, rc);
1113 }
1114 break;
1115
1116 case MSM_BACKEND_DAI_SLIMBUS_7_RX:
1117 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
1118 slim_rx_cfg[SLIM_RX_7].bit_format);
1119 rate->min = rate->max = slim_rx_cfg[SLIM_RX_7].sample_rate;
1120 channels->min = channels->max =
1121 slim_rx_cfg[SLIM_RX_7].channels;
1122 break;
1123
1124 case MSM_BACKEND_DAI_SLIMBUS_7_TX:
1125 rate->min = rate->max = slim_tx_cfg[SLIM_TX_7].sample_rate;
1126 channels->min = channels->max =
1127 slim_tx_cfg[SLIM_TX_7].channels;
1128 break;
1129
1130 case MSM_BACKEND_DAI_SLIMBUS_8_TX:
1131 rate->min = rate->max = slim_tx_cfg[SLIM_TX_8].sample_rate;
1132 channels->min = channels->max =
1133 slim_tx_cfg[SLIM_TX_8].channels;
1134 break;
1135
1136 default:
1137 rate->min = rate->max = SAMPLING_RATE_48KHZ;
1138 break;
1139 }
1140 return rc;
1141}
1142EXPORT_SYMBOL(msm_ext_be_hw_params_fixup);
1143
1144/**
1145 * msm_snd_hw_params - hw params ops of backend dailink.
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_snd_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 struct snd_soc_dai_link *dai_link = rtd->dai_link;
1159
1160 int ret = 0;
1161 u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
1162 u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
1163 u32 user_set_tx_ch = 0;
1164 u32 rx_ch_count;
1165
1166 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1167 ret = snd_soc_dai_get_channel_map(codec_dai,
1168 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
1169 if (ret < 0) {
1170 pr_err("%s: failed to get codec chan map, err:%d\n",
1171 __func__, ret);
1172 goto err_ch_map;
1173 }
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301174 if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_5_RX) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301175 pr_debug("%s: rx_5_ch=%d\n", __func__,
1176 slim_rx_cfg[5].channels);
1177 rx_ch_count = slim_rx_cfg[5].channels;
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301178 } else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_2_RX) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301179 pr_debug("%s: rx_2_ch=%d\n", __func__,
1180 slim_rx_cfg[2].channels);
1181 rx_ch_count = slim_rx_cfg[2].channels;
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301182 } else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_6_RX) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301183 pr_debug("%s: rx_6_ch=%d\n", __func__,
1184 slim_rx_cfg[6].channels);
1185 rx_ch_count = slim_rx_cfg[6].channels;
1186 } else {
1187 pr_debug("%s: rx_0_ch=%d\n", __func__,
1188 slim_rx_cfg[0].channels);
1189 rx_ch_count = slim_rx_cfg[0].channels;
1190 }
1191 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
1192 rx_ch_count, rx_ch);
1193 if (ret < 0) {
1194 pr_err("%s: failed to set cpu chan map, err:%d\n",
1195 __func__, ret);
1196 goto err_ch_map;
1197 }
1198 } else {
1199 pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
1200 codec_dai->name, codec_dai->id, user_set_tx_ch);
1201 ret = snd_soc_dai_get_channel_map(codec_dai,
1202 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
1203 if (ret < 0) {
1204 pr_err("%s: failed to get codec chan map\n, err:%d\n",
1205 __func__, ret);
1206 goto err_ch_map;
1207 }
1208 /* For <codec>_tx1 case */
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301209 if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_0_TX)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301210 user_set_tx_ch = slim_tx_cfg[0].channels;
1211 /* For <codec>_tx3 case */
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301212 else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_1_TX)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301213 user_set_tx_ch = slim_tx_cfg[1].channels;
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301214 else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_4_TX)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301215 user_set_tx_ch = msm_vi_feed_tx_ch;
1216 else
1217 user_set_tx_ch = tx_ch_cnt;
1218
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301219 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 +05301220 __func__, slim_tx_cfg[0].channels, user_set_tx_ch,
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301221 tx_ch_cnt, dai_link->id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301222
1223 ret = snd_soc_dai_set_channel_map(cpu_dai,
1224 user_set_tx_ch, tx_ch, 0, 0);
1225 if (ret < 0)
1226 pr_err("%s: failed to set cpu chan map, err:%d\n",
1227 __func__, ret);
1228 }
1229
1230err_ch_map:
1231 return ret;
1232}
1233EXPORT_SYMBOL(msm_snd_hw_params);
1234
1235/**
1236 * msm_ext_slimbus_2_hw_params - hw params ops of slimbus_2 BE.
1237 *
1238 * @substream: PCM stream of associated backend dailink.
1239 * @params: HW params of associated backend dailink.
1240 *
1241 * Returns 0 on success or ret on failure.
1242 */
1243int msm_ext_slimbus_2_hw_params(struct snd_pcm_substream *substream,
1244 struct snd_pcm_hw_params *params)
1245{
1246 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1247 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1248 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1249 int ret = 0;
1250 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
1251 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
1252 unsigned int num_tx_ch = 0;
1253 unsigned int num_rx_ch = 0;
1254
1255 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1256 num_rx_ch = params_channels(params);
1257 pr_debug("%s: %s rx_dai_id = %d num_ch = %d\n", __func__,
1258 codec_dai->name, codec_dai->id, num_rx_ch);
1259 ret = snd_soc_dai_get_channel_map(codec_dai,
1260 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
1261 if (ret < 0) {
1262 pr_err("%s: failed to get codec chan map, err:%d\n",
1263 __func__, ret);
1264 goto end;
1265 }
1266 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
1267 num_rx_ch, rx_ch);
1268 if (ret < 0) {
1269 pr_err("%s: failed to set cpu chan map, err:%d\n",
1270 __func__, ret);
1271 goto end;
1272 }
1273 } else {
1274 num_tx_ch = params_channels(params);
1275 pr_debug("%s: %s tx_dai_id = %d num_ch = %d\n", __func__,
1276 codec_dai->name, codec_dai->id, num_tx_ch);
1277 ret = snd_soc_dai_get_channel_map(codec_dai,
1278 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
1279 if (ret < 0) {
1280 pr_err("%s: failed to get codec chan map, err:%d\n",
1281 __func__, ret);
1282 goto end;
1283 }
1284 ret = snd_soc_dai_set_channel_map(cpu_dai,
1285 num_tx_ch, tx_ch, 0, 0);
1286 if (ret < 0) {
1287 pr_err("%s: failed to set cpu chan map, err:%d\n",
1288 __func__, ret);
1289 goto end;
1290 }
1291 }
1292end:
1293 return ret;
1294}
1295EXPORT_SYMBOL(msm_ext_slimbus_2_hw_params);
1296
1297/**
1298 * msm_snd_cpe_hw_params - hw params ops of CPE backend.
1299 *
1300 * @substream: PCM stream of associated backend dailink.
1301 * @params: HW params of associated backend dailink.
1302 *
1303 * Returns 0 on success or ret on failure.
1304 */
1305int msm_snd_cpe_hw_params(struct snd_pcm_substream *substream,
1306 struct snd_pcm_hw_params *params)
1307{
1308 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1309 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1310 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1311 struct snd_soc_dai_link *dai_link = rtd->dai_link;
1312 int ret = 0;
1313 u32 tx_ch[SLIM_MAX_TX_PORTS];
1314 u32 tx_ch_cnt = 0;
1315
1316 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) {
1317 pr_err("%s: Invalid stream type %d\n",
1318 __func__, substream->stream);
1319 ret = -EINVAL;
1320 goto end;
1321 }
1322
1323 pr_debug("%s: %s_tx_dai_id_%d\n", __func__,
1324 codec_dai->name, codec_dai->id);
1325 ret = snd_soc_dai_get_channel_map(codec_dai,
1326 &tx_ch_cnt, tx_ch, NULL, NULL);
1327 if (ret < 0) {
1328 pr_err("%s: failed to get codec chan map\n, err:%d\n",
1329 __func__, ret);
1330 goto end;
1331 }
1332
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301333 pr_debug("%s: tx_ch_cnt(%d) id %d\n",
1334 __func__, tx_ch_cnt, dai_link->id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301335
1336 ret = snd_soc_dai_set_channel_map(cpu_dai,
1337 tx_ch_cnt, tx_ch, 0, 0);
1338 if (ret < 0) {
1339 pr_err("%s: failed to set cpu chan map, err:%d\n",
1340 __func__, ret);
1341 goto end;
1342 }
1343end:
1344 return ret;
1345}
1346EXPORT_SYMBOL(msm_snd_cpe_hw_params);
1347
1348static int msm_afe_set_config(struct snd_soc_codec *codec)
1349{
1350 int rc;
1351 void *config_data;
1352
1353 pr_debug("%s: enter\n", __func__);
1354
1355 if (!msm_codec_fn.get_afe_config_fn) {
1356 dev_err(codec->dev, "%s: codec get afe config not init'ed\n",
1357 __func__);
1358 return -EINVAL;
1359 }
1360 config_data = msm_codec_fn.get_afe_config_fn(codec,
1361 AFE_CDC_REGISTERS_CONFIG);
1362 if (config_data) {
1363 rc = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
1364 if (rc) {
1365 pr_err("%s: Failed to set codec registers config %d\n",
1366 __func__, rc);
1367 return rc;
1368 }
1369 }
1370
1371 config_data = msm_codec_fn.get_afe_config_fn(codec,
1372 AFE_CDC_REGISTER_PAGE_CONFIG);
1373 if (config_data) {
1374 rc = afe_set_config(AFE_CDC_REGISTER_PAGE_CONFIG, config_data,
1375 0);
1376 if (rc)
1377 pr_err("%s: Failed to set cdc register page config\n",
1378 __func__);
1379 }
1380
1381 config_data = msm_codec_fn.get_afe_config_fn(codec,
1382 AFE_SLIMBUS_SLAVE_CONFIG);
1383 if (config_data) {
1384 rc = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
1385 if (rc) {
1386 pr_err("%s: Failed to set slimbus slave config %d\n",
1387 __func__, rc);
1388 return rc;
1389 }
1390 }
1391
1392 config_data = msm_codec_fn.get_afe_config_fn(codec,
1393 AFE_AANC_VERSION);
1394 if (config_data) {
1395 rc = afe_set_config(AFE_AANC_VERSION, config_data, 0);
1396 if (rc) {
1397 pr_err("%s: Failed to set AANC version %d\n",
1398 __func__, rc);
1399 return rc;
1400 }
1401 }
1402
1403 config_data = msm_codec_fn.get_afe_config_fn(codec,
1404 AFE_CDC_CLIP_REGISTERS_CONFIG);
1405 if (config_data) {
1406 rc = afe_set_config(AFE_CDC_CLIP_REGISTERS_CONFIG,
1407 config_data, 0);
1408 if (rc) {
1409 pr_err("%s: Failed to set clip registers %d\n",
1410 __func__, rc);
1411 return rc;
1412 }
1413 }
1414
1415 config_data = msm_codec_fn.get_afe_config_fn(codec,
1416 AFE_CLIP_BANK_SEL);
1417 if (config_data) {
1418 rc = afe_set_config(AFE_CLIP_BANK_SEL,
1419 config_data, 0);
1420 if (rc) {
1421 pr_err("%s: Failed to set AFE bank selection %d\n",
1422 __func__, rc);
1423 return rc;
1424 }
1425 }
1426
1427 config_data = msm_codec_fn.get_afe_config_fn(codec,
1428 AFE_CDC_REGISTER_PAGE_CONFIG);
1429 if (config_data) {
1430 rc = afe_set_config(AFE_CDC_REGISTER_PAGE_CONFIG, config_data,
1431 0);
1432 if (rc)
1433 pr_err("%s: Failed to set cdc register page config\n",
1434 __func__);
1435 }
1436
1437 return 0;
1438}
1439
1440static void msm_afe_clear_config(void)
1441{
1442 afe_clear_config(AFE_CDC_REGISTERS_CONFIG);
1443 afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
1444}
1445
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301446static int msm_adsp_power_up_config(struct snd_soc_codec *codec,
1447 struct snd_card *card)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301448{
1449 int ret = 0;
1450 unsigned long timeout;
1451 int adsp_ready = 0;
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301452 bool snd_card_online = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301453
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301454 timeout = jiffies +
1455 msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
1456
1457 do {
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301458 if (!snd_card_online) {
1459 snd_card_online = snd_card_is_online_state(card);
1460 pr_debug("%s: Sound card is %s\n", __func__,
1461 snd_card_online ? "Online" : "Offline");
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301462 }
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301463 if (!adsp_ready) {
1464 adsp_ready = q6core_is_adsp_ready();
1465 pr_debug("%s: ADSP Audio is %s\n", __func__,
1466 adsp_ready ? "ready" : "not ready");
1467 }
1468 if (snd_card_online && adsp_ready)
1469 break;
1470
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301471 /*
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301472 * Sound card/ADSP will be coming up after subsystem restart and
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301473 * it might not be fully up when the control reaches
1474 * here. So, wait for 50msec before checking ADSP state
1475 */
1476 msleep(50);
1477 } while (time_after(timeout, jiffies));
1478
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301479 if (!snd_card_online || !adsp_ready) {
1480 pr_err("%s: Timeout. Sound card is %s, ADSP Audio is %s\n",
1481 __func__,
1482 snd_card_online ? "Online" : "Offline",
1483 adsp_ready ? "ready" : "not ready");
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301484 ret = -ETIMEDOUT;
1485 goto err_fail;
1486 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301487
1488 ret = msm_afe_set_config(codec);
1489 if (ret)
1490 pr_err("%s: Failed to set AFE config. err %d\n",
1491 __func__, ret);
1492
1493 return 0;
1494
1495err_fail:
1496 return ret;
1497}
1498
1499static int sdm660_notifier_service_cb(struct notifier_block *this,
1500 unsigned long opcode, void *ptr)
1501{
1502 int ret;
1503 struct snd_soc_card *card = NULL;
1504 const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
1505 struct snd_soc_pcm_runtime *rtd;
1506 struct snd_soc_codec *codec;
1507
1508 pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode);
1509
1510 switch (opcode) {
1511 case AUDIO_NOTIFIER_SERVICE_DOWN:
1512 /*
1513 * Use flag to ignore initial boot notifications
1514 * On initial boot msm_adsp_power_up_config is
1515 * called on init. There is no need to clear
1516 * and set the config again on initial boot.
1517 */
1518 if (is_initial_boot)
1519 break;
1520 msm_afe_clear_config();
1521 break;
1522 case AUDIO_NOTIFIER_SERVICE_UP:
1523 if (is_initial_boot) {
1524 is_initial_boot = false;
1525 break;
1526 }
1527 if (!spdev)
1528 return -EINVAL;
1529
1530 card = platform_get_drvdata(spdev);
1531 rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
1532 if (!rtd) {
1533 dev_err(card->dev,
1534 "%s: snd_soc_get_pcm_runtime for %s failed!\n",
1535 __func__, be_dl_name);
1536 ret = -EINVAL;
1537 goto done;
1538 }
1539 codec = rtd->codec;
1540
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301541 ret = msm_adsp_power_up_config(codec, card->snd_card);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301542 if (ret < 0) {
1543 dev_err(card->dev,
1544 "%s: msm_adsp_power_up_config failed ret = %d!\n",
1545 __func__, ret);
1546 goto done;
1547 }
1548 break;
1549 default:
1550 break;
1551 }
1552done:
1553 return NOTIFY_OK;
1554}
1555
1556static struct notifier_block service_nb = {
1557 .notifier_call = sdm660_notifier_service_cb,
1558 .priority = -INT_MAX,
1559};
1560
1561static int msm_config_hph_en0_gpio(struct snd_soc_codec *codec, bool high)
1562{
1563 struct snd_soc_card *card = codec->component.card;
1564 struct msm_asoc_mach_data *pdata;
1565 int val;
1566
1567 if (!card)
1568 return 0;
1569
1570 pdata = snd_soc_card_get_drvdata(card);
1571 if (!pdata || !gpio_is_valid(pdata->hph_en0_gpio))
1572 return 0;
1573
1574 val = gpio_get_value_cansleep(pdata->hph_en0_gpio);
1575 if ((!!val) == high)
1576 return 0;
1577
1578 gpio_direction_output(pdata->hph_en0_gpio, (int)high);
1579
1580 return 1;
1581}
1582
1583static int msm_snd_enable_codec_ext_tx_clk(struct snd_soc_codec *codec,
1584 int enable, bool dapm)
1585{
1586 int ret = 0;
1587
1588 if (!strcmp(dev_name(codec->dev), "tasha_codec"))
1589 ret = tasha_cdc_mclk_tx_enable(codec, enable, dapm);
1590 else {
1591 dev_err(codec->dev, "%s: unknown codec to enable ext clk\n",
1592 __func__);
1593 ret = -EINVAL;
1594 }
1595 return ret;
1596}
1597
1598static int msm_ext_mclk_tx_event(struct snd_soc_dapm_widget *w,
1599 struct snd_kcontrol *kcontrol, int event)
1600{
1601 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1602
1603 pr_debug("%s: event = %d\n", __func__, event);
1604
1605 switch (event) {
1606 case SND_SOC_DAPM_PRE_PMU:
1607 return msm_snd_enable_codec_ext_tx_clk(codec, 1, true);
1608 case SND_SOC_DAPM_POST_PMD:
1609 return msm_snd_enable_codec_ext_tx_clk(codec, 0, true);
1610 }
1611 return 0;
1612}
1613
1614static int msm_ext_mclk_event(struct snd_soc_dapm_widget *w,
1615 struct snd_kcontrol *kcontrol, int event)
1616{
1617 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1618
1619 pr_debug("%s: event = %d\n", __func__, event);
1620
1621 switch (event) {
1622 case SND_SOC_DAPM_PRE_PMU:
1623 return msm_ext_enable_codec_mclk(codec, 1, true);
1624 case SND_SOC_DAPM_POST_PMD:
1625 return msm_ext_enable_codec_mclk(codec, 0, true);
1626 }
1627 return 0;
1628}
1629
Dhanalakshmi Siddani7ce33bb2018-11-28 22:01:53 +05301630static int msm_hifi_ctrl_event(struct snd_soc_dapm_widget *w,
1631 struct snd_kcontrol *k, int event)
1632{
1633 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1634 struct snd_soc_card *card = codec->component.card;
1635 struct msm_asoc_mach_data *pdata =
1636 snd_soc_card_get_drvdata(card);
1637
1638 pr_debug("%s: msm_hifi_control = %d\n", __func__, msm_hifi_control);
1639
1640 if (!pdata || !pdata->hph_en0_gpio_p) {
1641 pr_err("%s: hph_en0_gpio is invalid\n", __func__);
1642 return -EINVAL;
1643 }
1644
1645 if (msm_hifi_control != MSM_HIFI_ON) {
1646 pr_debug("%s: HiFi mixer control is not set\n",
1647 __func__);
1648 return 0;
1649 }
1650
1651 switch (event) {
1652 case SND_SOC_DAPM_POST_PMU:
1653 msm_cdc_pinctrl_select_active_state(pdata->hph_en0_gpio_p);
1654 break;
1655 case SND_SOC_DAPM_PRE_PMD:
1656 msm_cdc_pinctrl_select_sleep_state(pdata->hph_en0_gpio_p);
1657 break;
1658 }
1659
1660 return 0;
1661}
1662
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301663static int msm_ext_prepare_hifi(struct msm_asoc_mach_data *pdata)
1664{
1665 int ret = 0;
1666
1667 if (gpio_is_valid(pdata->hph_en1_gpio)) {
1668 pr_debug("%s: hph_en1_gpio request %d\n", __func__,
1669 pdata->hph_en1_gpio);
1670 ret = gpio_request(pdata->hph_en1_gpio, "hph_en1_gpio");
1671 if (ret) {
1672 pr_err("%s: hph_en1_gpio request failed, ret:%d\n",
1673 __func__, ret);
1674 goto err;
1675 }
1676 }
1677 if (gpio_is_valid(pdata->hph_en0_gpio)) {
1678 pr_debug("%s: hph_en0_gpio request %d\n", __func__,
1679 pdata->hph_en0_gpio);
1680 ret = gpio_request(pdata->hph_en0_gpio, "hph_en0_gpio");
1681 if (ret)
1682 pr_err("%s: hph_en0_gpio request failed, ret:%d\n",
1683 __func__, ret);
1684 }
1685
1686err:
1687 return ret;
1688}
1689
1690static const struct snd_soc_dapm_widget msm_dapm_widgets[] = {
1691
1692 SND_SOC_DAPM_SUPPLY_S("MCLK", -1, SND_SOC_NOPM, 0, 0,
1693 msm_ext_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1694
1695 SND_SOC_DAPM_SUPPLY_S("MCLK TX", -1, SND_SOC_NOPM, 0, 0,
1696 msm_ext_mclk_tx_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1697
1698 SND_SOC_DAPM_SPK("Lineout_1 amp", NULL),
1699 SND_SOC_DAPM_SPK("Lineout_3 amp", NULL),
1700 SND_SOC_DAPM_SPK("Lineout_2 amp", NULL),
1701 SND_SOC_DAPM_SPK("Lineout_4 amp", NULL),
Dhanalakshmi Siddani7ce33bb2018-11-28 22:01:53 +05301702 SND_SOC_DAPM_SPK("hifi amp", msm_hifi_ctrl_event),
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301703 SND_SOC_DAPM_MIC("Handset Mic", NULL),
1704 SND_SOC_DAPM_MIC("Headset Mic", NULL),
1705 SND_SOC_DAPM_MIC("Secondary Mic", NULL),
1706 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
1707 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
1708 SND_SOC_DAPM_MIC("Analog Mic4", NULL),
1709 SND_SOC_DAPM_MIC("Analog Mic6", NULL),
1710 SND_SOC_DAPM_MIC("Analog Mic7", NULL),
1711 SND_SOC_DAPM_MIC("Analog Mic8", NULL),
1712
1713 SND_SOC_DAPM_MIC("Digital Mic0", NULL),
1714 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
1715 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
1716 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
1717 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
1718 SND_SOC_DAPM_MIC("Digital Mic5", NULL),
1719 SND_SOC_DAPM_MIC("Digital Mic6", NULL),
Surendar Karka813c3d22018-11-05 13:46:17 +05301720 SND_SOC_DAPM_HP("Lineout", NULL),
1721 SND_SOC_DAPM_MIC("Linein", NULL),
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301722};
1723
1724static struct snd_soc_dapm_route wcd_audio_paths_tasha[] = {
1725 {"MIC BIAS1", NULL, "MCLK TX"},
1726 {"MIC BIAS2", NULL, "MCLK TX"},
1727 {"MIC BIAS3", NULL, "MCLK TX"},
1728 {"MIC BIAS4", NULL, "MCLK TX"},
1729};
1730
1731static struct snd_soc_dapm_route wcd_audio_paths[] = {
1732 {"MIC BIAS1", NULL, "MCLK"},
1733 {"MIC BIAS2", NULL, "MCLK"},
1734 {"MIC BIAS3", NULL, "MCLK"},
1735 {"MIC BIAS4", NULL, "MCLK"},
1736};
1737
Laxminath Kasam38070be2017-08-17 18:21:59 +05301738int msm_snd_card_tasha_late_probe(struct snd_soc_card *card)
1739{
1740 const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
1741 struct snd_soc_pcm_runtime *rtd;
1742 int ret = 0;
1743 void *mbhc_calibration;
1744
1745 rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
1746 if (!rtd) {
1747 dev_err(card->dev,
1748 "%s: snd_soc_get_pcm_runtime for %s failed!\n",
1749 __func__, be_dl_name);
1750 ret = -EINVAL;
1751 goto err_pcm_runtime;
1752 }
1753
1754 mbhc_calibration = def_ext_mbhc_cal();
1755 if (!mbhc_calibration) {
1756 ret = -ENOMEM;
1757 goto err_mbhc_cal;
1758 }
1759 wcd_mbhc_cfg_ptr->calibration = mbhc_calibration;
1760 ret = tasha_mbhc_hs_detect(rtd->codec, wcd_mbhc_cfg_ptr);
1761 if (ret) {
1762 dev_err(card->dev, "%s: mbhc hs detect failed, err:%d\n",
1763 __func__, ret);
1764 goto err_hs_detect;
1765 }
1766 return 0;
1767
1768err_hs_detect:
1769 kfree(mbhc_calibration);
1770err_mbhc_cal:
1771err_pcm_runtime:
1772 return ret;
1773}
1774
1775int msm_snd_card_tavil_late_probe(struct snd_soc_card *card)
1776{
1777 const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
1778 struct snd_soc_pcm_runtime *rtd;
1779 int ret = 0;
1780 void *mbhc_calibration;
1781
1782 rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
1783 if (!rtd) {
1784 dev_err(card->dev,
1785 "%s: snd_soc_get_pcm_runtime for %s failed!\n",
1786 __func__, be_dl_name);
1787 ret = -EINVAL;
1788 goto err;
1789 }
1790
1791 mbhc_calibration = def_ext_mbhc_cal();
1792 if (!mbhc_calibration) {
1793 ret = -ENOMEM;
1794 goto err;
1795 }
1796 wcd_mbhc_cfg_ptr->calibration = mbhc_calibration;
1797 ret = tavil_mbhc_hs_detect(rtd->codec, wcd_mbhc_cfg_ptr);
1798 if (ret) {
1799 dev_err(card->dev, "%s: mbhc hs detect failed, err:%d\n",
1800 __func__, ret);
1801 goto err_free_mbhc_cal;
1802 }
1803 return 0;
1804
1805err_free_mbhc_cal:
1806 kfree(mbhc_calibration);
1807err:
1808 return ret;
1809}
1810
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301811/**
1812 * msm_audrx_init - Audio init function of sound card instantiate.
1813 *
1814 * @rtd: runtime dailink instance
1815 *
1816 * Returns 0 on success or ret on failure.
1817 */
1818int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
1819{
1820 int ret;
1821 void *config_data;
1822 struct snd_soc_codec *codec = rtd->codec;
1823 struct snd_soc_dapm_context *dapm =
1824 snd_soc_codec_get_dapm(codec);
1825 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1826 struct snd_soc_dai *codec_dai = rtd->codec_dai;
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301827 struct snd_soc_component *aux_comp;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301828 struct snd_card *card;
1829 struct snd_info_entry *entry;
1830 struct msm_asoc_mach_data *pdata =
1831 snd_soc_card_get_drvdata(rtd->card);
1832
1833 /* Codec SLIMBUS configuration
1834 * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
1835 * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
1836 * TX14, TX15, TX16
1837 */
1838 unsigned int rx_ch[TASHA_RX_MAX] = {144, 145, 146, 147, 148, 149, 150,
1839 151, 152, 153, 154, 155, 156};
1840 unsigned int tx_ch[TASHA_TX_MAX] = {128, 129, 130, 131, 132, 133,
1841 134, 135, 136, 137, 138, 139,
1842 140, 141, 142, 143};
1843
1844 /* Tavil Codec SLIMBUS configuration
1845 * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8
1846 * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
1847 * TX14, TX15, TX16
1848 */
1849 unsigned int rx_ch_tavil[WCD934X_RX_MAX] = {144, 145, 146, 147, 148,
1850 149, 150, 151};
1851 unsigned int tx_ch_tavil[WCD934X_TX_MAX] = {128, 129, 130, 131, 132,
1852 133, 134, 135, 136, 137, 138,
1853 139, 140, 141, 142, 143};
1854
1855 pr_debug("%s: dev_name%s\n", __func__, dev_name(cpu_dai->dev));
1856
1857 rtd->pmdown_time = 0;
1858
1859 ret = snd_soc_add_codec_controls(codec, msm_snd_controls,
1860 ARRAY_SIZE(msm_snd_controls));
1861 if (ret < 0) {
1862 pr_err("%s: add_codec_controls failed: %d\n",
1863 __func__, ret);
1864 return ret;
1865 }
1866
1867 ret = snd_soc_add_codec_controls(codec, msm_common_snd_controls,
1868 msm_common_snd_controls_size());
1869 if (ret < 0) {
1870 pr_err("%s: add_common_snd_controls failed: %d\n",
1871 __func__, ret);
1872 return ret;
1873 }
1874
1875 snd_soc_dapm_new_controls(dapm, msm_dapm_widgets,
1876 ARRAY_SIZE(msm_dapm_widgets));
1877
1878 if (!strcmp(dev_name(codec_dai->dev), "tasha_codec"))
1879 snd_soc_dapm_add_routes(dapm, wcd_audio_paths_tasha,
1880 ARRAY_SIZE(wcd_audio_paths_tasha));
1881 else
1882 snd_soc_dapm_add_routes(dapm, wcd_audio_paths,
1883 ARRAY_SIZE(wcd_audio_paths));
1884
1885 snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp");
1886 snd_soc_dapm_enable_pin(dapm, "Lineout_3 amp");
1887 snd_soc_dapm_enable_pin(dapm, "Lineout_2 amp");
1888 snd_soc_dapm_enable_pin(dapm, "Lineout_4 amp");
1889
1890 snd_soc_dapm_ignore_suspend(dapm, "MADINPUT");
1891 snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_INPUT");
1892 snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
1893 snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
1894 snd_soc_dapm_ignore_suspend(dapm, "Secondary Mic");
1895 snd_soc_dapm_ignore_suspend(dapm, "Lineout_1 amp");
1896 snd_soc_dapm_ignore_suspend(dapm, "Lineout_3 amp");
1897 snd_soc_dapm_ignore_suspend(dapm, "Lineout_2 amp");
1898 snd_soc_dapm_ignore_suspend(dapm, "Lineout_4 amp");
1899 snd_soc_dapm_ignore_suspend(dapm, "ANCRight Headset Mic");
1900 snd_soc_dapm_ignore_suspend(dapm, "ANCLeft Headset Mic");
1901 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic0");
1902 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
1903 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
1904 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic3");
1905 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic4");
1906 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic5");
1907 snd_soc_dapm_ignore_suspend(dapm, "Analog Mic4");
1908 snd_soc_dapm_ignore_suspend(dapm, "Analog Mic6");
1909 snd_soc_dapm_ignore_suspend(dapm, "Analog Mic7");
1910 snd_soc_dapm_ignore_suspend(dapm, "Analog Mic8");
1911
1912 snd_soc_dapm_ignore_suspend(dapm, "EAR");
1913 snd_soc_dapm_ignore_suspend(dapm, "LINEOUT1");
1914 snd_soc_dapm_ignore_suspend(dapm, "LINEOUT2");
1915 snd_soc_dapm_ignore_suspend(dapm, "AMIC1");
1916 snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
1917 snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
1918 snd_soc_dapm_ignore_suspend(dapm, "AMIC4");
1919 snd_soc_dapm_ignore_suspend(dapm, "AMIC5");
1920 snd_soc_dapm_ignore_suspend(dapm, "DMIC0");
1921 snd_soc_dapm_ignore_suspend(dapm, "DMIC1");
1922 snd_soc_dapm_ignore_suspend(dapm, "DMIC2");
1923 snd_soc_dapm_ignore_suspend(dapm, "DMIC3");
1924 snd_soc_dapm_ignore_suspend(dapm, "DMIC4");
1925 snd_soc_dapm_ignore_suspend(dapm, "DMIC5");
1926 snd_soc_dapm_ignore_suspend(dapm, "ANC EAR");
1927 snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT");
1928 snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT");
1929 snd_soc_dapm_ignore_suspend(dapm, "HPHL");
1930 snd_soc_dapm_ignore_suspend(dapm, "HPHR");
1931 snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI");
1932 snd_soc_dapm_ignore_suspend(dapm, "VIINPUT");
1933
1934 if (!strcmp(dev_name(codec_dai->dev), "tasha_codec")) {
1935 snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3");
1936 snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4");
1937 snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL");
1938 snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR");
1939 snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1");
1940 snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2");
1941 } else {
1942 snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_OUT1");
1943 snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_OUT2");
1944 }
1945
1946 snd_soc_dapm_sync(dapm);
1947
1948 if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
1949 snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch_tavil),
1950 tx_ch_tavil, ARRAY_SIZE(rx_ch_tavil),
1951 rx_ch_tavil);
1952 } else {
1953 snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
1954 tx_ch, ARRAY_SIZE(rx_ch),
1955 rx_ch);
1956 }
1957
1958 if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
1959 msm_codec_fn.get_afe_config_fn = tavil_get_afe_config;
1960 } else {
1961 msm_codec_fn.get_afe_config_fn = tasha_get_afe_config;
1962 msm_codec_fn.mbhc_hs_detect_exit = tasha_mbhc_hs_detect_exit;
1963 }
1964
Aditya Bavanarid61b84d2018-01-03 13:24:06 +05301965 ret = msm_adsp_power_up_config(codec, rtd->card->snd_card);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301966 if (ret) {
1967 pr_err("%s: Failed to set AFE config %d\n", __func__, ret);
1968 goto err_afe_cfg;
1969 }
1970
1971 config_data = msm_codec_fn.get_afe_config_fn(codec,
1972 AFE_AANC_VERSION);
1973 if (config_data) {
1974 ret = afe_set_config(AFE_AANC_VERSION, config_data, 0);
1975 if (ret) {
1976 pr_err("%s: Failed to set aanc version %d\n",
1977 __func__, ret);
1978 goto err_afe_cfg;
1979 }
1980 }
1981
1982 if (!strcmp(dev_name(codec_dai->dev), "tasha_codec")) {
1983 config_data = msm_codec_fn.get_afe_config_fn(codec,
1984 AFE_CDC_CLIP_REGISTERS_CONFIG);
1985 if (config_data) {
1986 ret = afe_set_config(AFE_CDC_CLIP_REGISTERS_CONFIG,
1987 config_data, 0);
1988 if (ret) {
1989 pr_err("%s: Failed to set clip registers %d\n",
1990 __func__, ret);
1991 goto err_afe_cfg;
1992 }
1993 }
1994 config_data = msm_codec_fn.get_afe_config_fn(codec,
1995 AFE_CLIP_BANK_SEL);
1996 if (config_data) {
1997 ret = afe_set_config(AFE_CLIP_BANK_SEL, config_data, 0);
1998 if (ret) {
1999 pr_err("%s: Failed to set AFE bank selection %d\n",
2000 __func__, ret);
2001 goto err_afe_cfg;
2002 }
2003 }
2004 }
2005
2006 /*
2007 * Send speaker configuration only for WSA8810.
2008 * Defalut configuration is for WSA8815.
2009 */
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05302010 pr_debug("%s: Number of aux devices: %d\n",
2011 __func__, rtd->card->num_aux_devs);
2012
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302013 if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05302014 if (rtd->card->num_aux_devs &&
2015 !list_empty(&rtd->card->aux_comp_list)) {
2016 aux_comp = list_first_entry(&rtd->card->aux_comp_list,
2017 struct snd_soc_component, list_aux);
2018 if (!strcmp(aux_comp->name, WSA8810_NAME_1) ||
2019 !strcmp(aux_comp->name, WSA8810_NAME_2)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302020 tavil_set_spkr_mode(rtd->codec, SPKR_MODE_1);
2021 tavil_set_spkr_gain_offset(rtd->codec,
2022 RX_GAIN_OFFSET_M1P5_DB);
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05302023 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302024 }
2025 card = rtd->card->snd_card;
2026 entry = snd_info_create_subdir(card->module, "codecs",
2027 card->proc_root);
2028 if (!entry) {
2029 pr_debug("%s: Cannot create codecs module entry\n",
2030 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302031 goto done;
2032 }
2033 pdata->codec_root = entry;
2034 tavil_codec_info_create_codec_entry(pdata->codec_root, codec);
2035 } else {
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05302036 if (rtd->card->num_aux_devs &&
2037 !list_empty(&rtd->card->aux_comp_list)) {
2038 aux_comp = list_first_entry(&rtd->card->aux_comp_list,
2039 struct snd_soc_component, list_aux);
2040 if (!strcmp(aux_comp->name, WSA8810_NAME_1) ||
2041 !strcmp(aux_comp->name, WSA8810_NAME_2)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302042 tasha_set_spkr_mode(rtd->codec, SPKR_MODE_1);
2043 tasha_set_spkr_gain_offset(rtd->codec,
2044 RX_GAIN_OFFSET_M1P5_DB);
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05302045 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302046 }
2047 card = rtd->card->snd_card;
2048 entry = snd_info_create_subdir(card->module, "codecs",
2049 card->proc_root);
2050 if (!entry) {
2051 pr_debug("%s: Cannot create codecs module entry\n",
2052 __func__);
Laxminath Kasam38070be2017-08-17 18:21:59 +05302053 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302054 }
2055 pdata->codec_root = entry;
2056 tasha_codec_info_create_codec_entry(pdata->codec_root, codec);
2057 tasha_mbhc_zdet_gpio_ctrl(msm_config_hph_en0_gpio, rtd->codec);
2058 }
Surendar Karka813c3d22018-11-05 13:46:17 +05302059
2060 if (gpio_is_valid(pdata->gpio_linein_det)) {
2061 snd_soc_card_jack_new(rtd->card, "Linein", SND_JACK_LINEIN,
2062 &linein_jack, linein_jack_pins,
2063 ARRAY_SIZE(linein_jack_pins));
2064
2065 linein_jack_gpio.invert = pdata->linein_det_swh;
2066 linein_jack_gpio.gpio = pdata->gpio_linein_det;
2067 snd_soc_jack_add_gpios(&linein_jack, 1, &linein_jack_gpio);
2068 }
2069
2070 if (gpio_is_valid(pdata->gpio_lineout_det)) {
2071 snd_soc_card_jack_new(rtd->card, "Lineout", SND_JACK_LINEOUT,
2072 &lineout_jack, lineout_jack_pins,
2073 ARRAY_SIZE(lineout_jack_pins));
2074
2075 lineout_jack_gpio.invert = pdata->lineout_det_swh;
2076 lineout_jack_gpio.gpio = pdata->gpio_lineout_det;
2077 snd_soc_jack_add_gpios(&lineout_jack, 1, &lineout_jack_gpio);
2078 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302079done:
Laxminath Kasam38070be2017-08-17 18:21:59 +05302080 msm_set_codec_reg_done(true);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302081 return 0;
2082
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302083err_afe_cfg:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302084 return ret;
2085}
2086EXPORT_SYMBOL(msm_audrx_init);
2087
2088/**
2089 * msm_ext_register_audio_notifier - register SSR notifier.
2090 */
2091void msm_ext_register_audio_notifier(struct platform_device *pdev)
2092{
2093 int ret;
2094
2095 is_initial_boot = true;
2096 spdev = pdev;
2097 ret = audio_notifier_register("sdm660", AUDIO_NOTIFIER_ADSP_DOMAIN,
2098 &service_nb);
2099 if (ret < 0)
2100 pr_err("%s: Audio notifier register failed ret = %d\n",
2101 __func__, ret);
2102}
2103EXPORT_SYMBOL(msm_ext_register_audio_notifier);
2104
2105/**
2106 * msm_ext_cdc_init - external codec machine specific init.
2107 *
2108 * @pdev: platform device handle
2109 * @pdata: private data of machine driver
2110 * @card: sound card pointer reference
2111 * @mbhc_cfg: MBHC config reference
2112 *
2113 * Returns 0 on success or ret on failure.
2114 */
2115int msm_ext_cdc_init(struct platform_device *pdev,
2116 struct msm_asoc_mach_data *pdata,
2117 struct snd_soc_card **card,
2118 struct wcd_mbhc_config *wcd_mbhc_cfg_ptr1)
2119{
2120 int ret = 0;
2121
2122 wcd_mbhc_cfg_ptr = wcd_mbhc_cfg_ptr1;
2123 pdev->id = 0;
2124 wcd_mbhc_cfg_ptr->moisture_en = true;
2125 wcd_mbhc_cfg_ptr->mbhc_micbias = MIC_BIAS_2;
2126 wcd_mbhc_cfg_ptr->anc_micbias = MIC_BIAS_2;
2127 wcd_mbhc_cfg_ptr->enable_anc_mic_detect = false;
2128
2129 *card = populate_snd_card_dailinks(&pdev->dev, pdata->snd_card_val);
2130 if (!(*card)) {
2131 dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__);
2132 ret = -EPROBE_DEFER;
2133 goto err;
2134 }
2135 platform_set_drvdata(pdev, *card);
2136 snd_soc_card_set_drvdata(*card, pdata);
2137 pdata->hph_en1_gpio = of_get_named_gpio(pdev->dev.of_node,
2138 "qcom,hph-en1-gpio", 0);
2139 if (!gpio_is_valid(pdata->hph_en1_gpio))
2140 pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node,
2141 "qcom,hph-en1-gpio", 0);
2142 if (!gpio_is_valid(pdata->hph_en1_gpio) && (!pdata->hph_en1_gpio_p)) {
2143 dev_dbg(&pdev->dev, "property %s not detected in node %s",
2144 "qcom,hph-en1-gpio", pdev->dev.of_node->full_name);
2145 }
2146
2147 pdata->hph_en0_gpio = of_get_named_gpio(pdev->dev.of_node,
2148 "qcom,hph-en0-gpio", 0);
2149 if (!gpio_is_valid(pdata->hph_en0_gpio))
2150 pdata->hph_en0_gpio_p = of_parse_phandle(pdev->dev.of_node,
2151 "qcom,hph-en0-gpio", 0);
2152 if (!gpio_is_valid(pdata->hph_en0_gpio) && (!pdata->hph_en0_gpio_p)) {
2153 dev_dbg(&pdev->dev, "property %s not detected in node %s",
2154 "qcom,hph-en0-gpio", pdev->dev.of_node->full_name);
2155 }
2156
Surendar Karka813c3d22018-11-05 13:46:17 +05302157 ret = of_property_read_u32(pdev->dev.of_node, "qcom,linein-det-swh",
2158 &pdata->linein_det_swh);
2159 if (ret) {
2160 dev_dbg(&pdev->dev, "%s: missing %s in dt node\n",
2161 __func__, "qcom,linein-det-swh");
2162 }
2163
2164 ret = of_property_read_u32(pdev->dev.of_node, "qcom,lineout-det-swh",
2165 &pdata->lineout_det_swh);
2166 if (ret) {
2167 dev_dbg(&pdev->dev, "%s: missing %s in dt node\n",
2168 __func__, "qcom,lineout-det-swh");
2169 }
2170
2171 pdata->gpio_linein_det = of_get_named_gpio(pdev->dev.of_node,
2172 "qcom,linein-det-gpio", 0);
2173 if (pdata->gpio_linein_det < 0) {
2174 dev_dbg(&pdev->dev, "property %s not detected in node %s\n",
2175 "qcom,linein-det-gpio", pdev->dev.of_node->full_name);
2176 }
2177
2178 pdata->gpio_lineout_det = of_get_named_gpio(pdev->dev.of_node,
2179 "qcom,lineout-det-gpio", 0);
2180 if (pdata->gpio_lineout_det < 0) {
2181 dev_dbg(&pdev->dev, "property %s not detected in node %s\n",
2182 "qcom,lineout-det-gpio", pdev->dev.of_node->full_name);
2183 }
2184
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302185 ret = msm_ext_prepare_hifi(pdata);
2186 if (ret) {
2187 dev_dbg(&pdev->dev, "msm_ext_prepare_hifi failed (%d)\n",
2188 ret);
2189 ret = 0;
2190 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302191err:
2192 return ret;
2193}
2194EXPORT_SYMBOL(msm_ext_cdc_init);