OSDN Git Service

treewide: Fix code issues detected using GCC 8
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / sound / soc / msm / qdsp6v2 / msm-pcm-voice-v2.c
1 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 and
5  * only version 2 as published by the Free Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  */
12
13 #include <linux/init.h>
14 #include <linux/err.h>
15 #include <linux/module.h>
16 #include <linux/time.h>
17 #include <linux/wait.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
20 #include <linux/dma-mapping.h>
21 #include <sound/core.h>
22 #include <sound/soc.h>
23 #include <sound/soc-dapm.h>
24 #include <sound/pcm.h>
25 #include <sound/initval.h>
26 #include <sound/control.h>
27 #include <asm/dma.h>
28 #include <linux/of_device.h>
29
30 #include "msm-pcm-voice-v2.h"
31 #include "msm-qti-pp-config.h"
32 #include "q6voice.h"
33
34 struct msm_dtmf_detected_event_data {
35         uint32_t event_type;
36         uint32_t payload_len;
37         struct vss_istream_evt_rx_dtmf_detected dtmf_payload;
38 };
39
40 static struct msm_voice voice_info[VOICE_SESSION_INDEX_MAX];
41
42 static struct snd_pcm_hardware msm_pcm_hardware = {
43
44         .info =                 (SNDRV_PCM_INFO_INTERLEAVED |
45                                 SNDRV_PCM_INFO_PAUSE |
46                                 SNDRV_PCM_INFO_RESUME),
47         .formats =              SNDRV_PCM_FMTBIT_S16_LE,
48         .rates =                SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
49         .rate_min =             8000,
50         .rate_max =             16000,
51         .channels_min =         1,
52         .channels_max =         1,
53
54         .buffer_bytes_max =     4096 * 2,
55         .period_bytes_min =     2048,
56         .period_bytes_max =     4096,
57         .periods_min =          2,
58         .periods_max =          4,
59
60         .fifo_size =            0,
61 };
62
63 static int is_valid_session_id(uint32_t session_id)
64 {
65         int idx = 0;
66
67         switch (session_id) {
68         case VOICE_SESSION_VSID:
69         case VOICE2_SESSION_VSID:
70         case VOLTE_SESSION_VSID:
71         case QCHAT_SESSION_VSID:
72         case VOWLAN_SESSION_VSID:
73         case VOICEMMODE1_VSID:
74         case VOICEMMODE2_VSID:
75         case ALL_SESSION_VSID:
76                 idx = 1;
77                 break;
78         default:
79                 pr_debug("%s: Invalid session_id : %x\n", __func__, session_id);
80                 break;
81         }
82         return idx;
83 }
84
85 static int get_idx_for_session(uint32_t session_id)
86 {
87         int idx = 0;
88
89         switch (session_id) {
90         case VOICE_SESSION_VSID:
91                 idx = VOICE_SESSION_INDEX;
92                 break;
93         case VOICE2_SESSION_VSID:
94                 idx = VOICE2_SESSION_INDEX;
95                 break;
96         case VOLTE_SESSION_VSID:
97                 idx = VOLTE_SESSION_INDEX;
98                 break;
99         case QCHAT_SESSION_VSID:
100                 idx = QCHAT_SESSION_INDEX;
101                 break;
102         case VOWLAN_SESSION_VSID:
103                 idx = VOWLAN_SESSION_INDEX;
104                 break;
105         case VOICEMMODE1_VSID:
106                 idx = VOICEMMODE1_INDEX;
107                 break;
108         case VOICEMMODE2_VSID:
109                 idx = VOICEMMODE2_INDEX;
110                 break;
111         case ALL_SESSION_VSID:
112                 idx = VOICE_SESSION_INDEX_MAX - 1;
113                 break;
114         default:
115                 pr_err("%s: Invalid session_id : %x\n", __func__, session_id);
116                 break;
117         }
118
119         return idx;
120 }
121
122 static bool is_volte(struct msm_voice *pvolte)
123 {
124         if (pvolte == &voice_info[VOLTE_SESSION_INDEX])
125                 return true;
126         else
127                 return false;
128 }
129
130 static bool is_voice2(struct msm_voice *pvoice2)
131 {
132         if (pvoice2 == &voice_info[VOICE2_SESSION_INDEX])
133                 return true;
134         else
135                 return false;
136 }
137
138 static bool is_qchat(struct msm_voice *pqchat)
139 {
140         if (pqchat == &voice_info[QCHAT_SESSION_INDEX])
141                 return true;
142         else
143                 return false;
144 }
145
146 static bool is_vowlan(struct msm_voice *pvowlan)
147 {
148         if (pvowlan == &voice_info[VOWLAN_SESSION_INDEX])
149                 return true;
150         else
151                 return false;
152 }
153
154 static bool is_voicemmode1(struct msm_voice *pvoicemmode1)
155 {
156         if (pvoicemmode1 == &voice_info[VOICEMMODE1_INDEX])
157                 return true;
158         else
159                 return false;
160 }
161
162 static bool is_voicemmode2(struct msm_voice *pvoicemmode2)
163 {
164         if (pvoicemmode2 == &voice_info[VOICEMMODE2_INDEX])
165                 return true;
166         else
167                 return false;
168 }
169
170 static uint32_t get_session_id(struct msm_voice *pvoc)
171 {
172         uint32_t session_id = 0;
173
174         if (is_volte(pvoc))
175                 session_id = voc_get_session_id(VOLTE_SESSION_NAME);
176         else if (is_voice2(pvoc))
177                 session_id = voc_get_session_id(VOICE2_SESSION_NAME);
178         else if (is_qchat(pvoc))
179                 session_id = voc_get_session_id(QCHAT_SESSION_NAME);
180         else if (is_vowlan(pvoc))
181                 session_id = voc_get_session_id(VOWLAN_SESSION_NAME);
182         else if (is_voicemmode1(pvoc))
183                 session_id = voc_get_session_id(VOICEMMODE1_NAME);
184         else if (is_voicemmode2(pvoc))
185                 session_id = voc_get_session_id(VOICEMMODE2_NAME);
186         else
187                 session_id = voc_get_session_id(VOICE_SESSION_NAME);
188
189         return session_id;
190 }
191
192 static void dtmf_rx_detected_evt_hdlr(uint8_t *pkt,
193                                 char *session,
194                                 void *private_data)
195 {
196         int ret = 0;
197         struct snd_soc_pcm_runtime *soc_prtd = private_data;
198         struct msm_dtmf_detected_event_data event_data = {ADSP_STREAM_PP_EVENT,
199                 sizeof(struct vss_istream_evt_rx_dtmf_detected),
200                 {0} };
201
202         if (!pkt) {
203                 pr_err("%s: packet is NULL\n",
204                         __func__);
205                 return;
206         }
207
208         if (!private_data) {
209                 pr_err("%s: private_data is NULL\n",
210                         __func__);
211                 return;
212         }
213
214         memcpy(&event_data.dtmf_payload, pkt,
215                 sizeof(struct vss_istream_evt_rx_dtmf_detected));
216
217         ret = msm_adsp_inform_mixer_ctl(soc_prtd, (uint32_t *)&event_data);
218         if (ret) {
219                 pr_err("%s: failed to inform mixer ctl. err = %d\n",
220                         __func__, ret);
221                 return;
222         }
223 }
224
225 static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
226 {
227         struct snd_pcm_runtime *runtime = substream->runtime;
228         struct msm_voice *prtd = runtime->private_data;
229
230         pr_debug("%s\n", __func__);
231
232         if (!prtd->playback_start)
233                 prtd->playback_start = 1;
234
235         return 0;
236 }
237
238 static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
239 {
240         struct snd_pcm_runtime *runtime = substream->runtime;
241         struct msm_voice *prtd = runtime->private_data;
242
243         pr_debug("%s\n", __func__);
244
245         if (!prtd->capture_start)
246                 prtd->capture_start = 1;
247
248         return 0;
249 }
250 static int msm_pcm_open(struct snd_pcm_substream *substream)
251 {
252         struct snd_pcm_runtime *runtime = substream->runtime;
253         struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
254         struct msm_voice *voice;
255
256         if (!strncmp("VoLTE", substream->pcm->id, 5)) {
257                 voice = &voice_info[VOLTE_SESSION_INDEX];
258                 pr_debug("%s: Open VoLTE Substream Id=%s\n",
259                          __func__, substream->pcm->id);
260         } else if (!strncmp("Voice2", substream->pcm->id, 6)) {
261                 voice = &voice_info[VOICE2_SESSION_INDEX];
262                 pr_debug("%s: Open Voice2 Substream Id=%s\n",
263                          __func__, substream->pcm->id);
264         } else if (!strncmp("QCHAT", substream->pcm->id, 5)) {
265                 voice = &voice_info[QCHAT_SESSION_INDEX];
266                 pr_debug("%s: Open QCHAT Substream Id=%s\n",
267                          __func__, substream->pcm->id);
268         } else if (!strncmp("VoWLAN", substream->pcm->id, 6)) {
269                 voice = &voice_info[VOWLAN_SESSION_INDEX];
270                 pr_debug("%s: Open VoWLAN Substream Id=%s\n",
271                          __func__, substream->pcm->id);
272         } else if (!strncmp("VoiceMMode1", substream->pcm->id, 11)) {
273                 voice = &voice_info[VOICEMMODE1_INDEX];
274                 pr_debug("%s: Open VoiceMMode1 Substream Id=%s\n",
275                          __func__, substream->pcm->id);
276         } else if (!strncmp("VoiceMMode2", substream->pcm->id, 11)) {
277                 voice = &voice_info[VOICEMMODE2_INDEX];
278                 pr_debug("%s: Open VoiceMMode2 Substream Id=%s\n",
279                          __func__, substream->pcm->id);
280         } else {
281                 voice = &voice_info[VOICE_SESSION_INDEX];
282                 pr_debug("%s: Open VOICE Substream Id=%s\n",
283                          __func__, substream->pcm->id);
284         }
285         mutex_lock(&voice->lock);
286
287         runtime->hw = msm_pcm_hardware;
288
289         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
290                 voice->playback_substream = substream;
291         else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
292                 voice->capture_substream = substream;
293
294         voice->instance++;
295         pr_debug("%s: Instance = %d, Stream ID = %s\n",
296                         __func__ , voice->instance, substream->pcm->id);
297         runtime->private_data = voice;
298
299         mutex_unlock(&voice->lock);
300         msm_adsp_init_mixer_ctl_pp_event_queue(soc_prtd);
301         return 0;
302 }
303 static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
304 {
305         struct snd_pcm_runtime *runtime = substream->runtime;
306         struct msm_voice *prtd = runtime->private_data;
307
308         pr_debug("%s\n", __func__);
309
310         if (prtd->playback_start)
311                 prtd->playback_start = 0;
312
313         prtd->playback_substream = NULL;
314
315         return 0;
316 }
317 static int msm_pcm_capture_close(struct snd_pcm_substream *substream)
318 {
319         struct snd_pcm_runtime *runtime = substream->runtime;
320         struct msm_voice *prtd = runtime->private_data;
321
322         pr_debug("%s\n", __func__);
323
324         if (prtd->capture_start)
325                 prtd->capture_start = 0;
326         prtd->capture_substream = NULL;
327
328         return 0;
329 }
330 static int msm_pcm_close(struct snd_pcm_substream *substream)
331 {
332
333         struct snd_pcm_runtime *runtime = substream->runtime;
334         struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
335         struct msm_voice *prtd = runtime->private_data;
336         uint32_t session_id = 0;
337         int ret = 0;
338
339         mutex_lock(&prtd->lock);
340         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
341                 ret = msm_pcm_playback_close(substream);
342         else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
343                 ret = msm_pcm_capture_close(substream);
344
345         prtd->instance--;
346         if (!prtd->playback_start && !prtd->capture_start) {
347                 pr_debug("end voice call\n");
348
349                 session_id = get_session_id(prtd);
350                 if (session_id)
351                         voc_end_voice_call(session_id);
352         }
353         mutex_unlock(&prtd->lock);
354         msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
355
356         return ret;
357 }
358 static int msm_pcm_prepare(struct snd_pcm_substream *substream)
359 {
360         int ret = 0;
361         struct snd_pcm_runtime *runtime = substream->runtime;
362         struct msm_voice *prtd = runtime->private_data;
363         uint32_t session_id = 0;
364
365         mutex_lock(&prtd->lock);
366
367         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
368                 ret = msm_pcm_playback_prepare(substream);
369         else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
370                 ret = msm_pcm_capture_prepare(substream);
371
372         if (prtd->playback_start && prtd->capture_start) {
373                 session_id = get_session_id(prtd);
374                 if (session_id)
375                         voc_start_voice_call(session_id);
376         }
377         mutex_unlock(&prtd->lock);
378
379         return ret;
380 }
381
382 static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
383                                 struct snd_pcm_hw_params *params)
384 {
385
386         pr_debug("%s: Voice\n", __func__);
387
388         snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
389
390         return 0;
391 }
392
393 static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
394 {
395         int ret = 0;
396         struct snd_pcm_runtime *runtime = substream->runtime;
397         struct msm_voice *prtd = runtime->private_data;
398         uint32_t session_id = 0;
399
400         pr_debug("%s: cmd = %d\n", __func__, cmd);
401
402         session_id = get_session_id(prtd);
403
404         switch (cmd) {
405         case SNDRV_PCM_TRIGGER_START:
406         case SNDRV_PCM_TRIGGER_STOP:
407                 pr_debug("Start & Stop Voice call not handled in Trigger.\n");
408         break;
409         case SNDRV_PCM_TRIGGER_RESUME:
410         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
411                 pr_debug("%s: resume call session_id = %d\n", __func__,
412                          session_id);
413                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
414                         ret = msm_pcm_playback_prepare(substream);
415                 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
416                         ret = msm_pcm_capture_prepare(substream);
417                 if (prtd->playback_start && prtd->capture_start) {
418                         if (session_id)
419                                 voc_resume_voice_call(session_id);
420                 }
421         break;
422         case SNDRV_PCM_TRIGGER_SUSPEND:
423         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
424                 pr_debug("%s: pause call session_id=%d\n",
425                          __func__, session_id);
426                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
427                         if (prtd->playback_start)
428                                 prtd->playback_start = 0;
429                 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
430                         if (prtd->capture_start)
431                                 prtd->capture_start = 0;
432                 }
433                 if (session_id)
434                         voc_standby_voice_call(session_id);
435                 break;
436         default:
437                 ret = -EINVAL;
438         break;
439         }
440         return ret;
441 }
442
443 static int msm_pcm_ioctl(struct snd_pcm_substream *substream,
444                          unsigned int cmd, void *arg)
445 {
446         struct snd_pcm_runtime *runtime = substream->runtime;
447         struct msm_voice *prtd = runtime->private_data;
448         uint32_t session_id = get_session_id(prtd);
449         enum voice_lch_mode lch_mode;
450         int ret = 0;
451
452         switch (cmd) {
453         case SNDRV_VOICE_IOCTL_LCH:
454                 if (copy_from_user(&lch_mode, (void *)arg,
455                                    sizeof(enum voice_lch_mode))) {
456                         pr_err("%s: Copy from user failed, size %zd\n",
457                                 __func__, sizeof(enum voice_lch_mode));
458
459                         ret = -EFAULT;
460                         break;
461                 }
462
463                 pr_debug("%s: %s lch_mode:%d\n",
464                          __func__, substream->pcm->id, lch_mode);
465
466                 switch (lch_mode) {
467                 case VOICE_LCH_START:
468                 case VOICE_LCH_STOP:
469                         ret = voc_set_lch(session_id, lch_mode);
470                         break;
471
472                 default:
473                         pr_err("%s: Invalid LCH MODE %d\n", __func__, lch_mode);
474
475                         ret = -EFAULT;
476                 }
477
478                 break;
479         default:
480                 pr_debug("%s: Falling into default snd_lib_ioctl cmd 0x%x\n",
481                          __func__, cmd);
482
483                 ret = snd_pcm_lib_ioctl(substream, cmd, arg);
484                 break;
485         }
486
487         if (!ret)
488                 pr_debug("%s: ret %d\n", __func__, ret);
489         else
490                 pr_err("%s: cmd 0x%x failed %d\n", __func__, cmd, ret);
491
492         return ret;
493 }
494
495 static int msm_voice_sidetone_put(struct snd_kcontrol *kcontrol,
496                                         struct snd_ctl_elem_value *ucontrol)
497 {
498         int ret;
499         int sidetone_enable = ucontrol->value.integer.value[0];
500         uint32_t session_id = ALL_SESSION_VSID;
501
502         if (sidetone_enable < 0) {
503                 pr_err("%s: Invalid arguments sidetone enable %d\n",
504                          __func__, sidetone_enable);
505                 ret = -EINVAL;
506                 return ret;
507         }
508         ret = voc_set_afe_sidetone(session_id, sidetone_enable);
509         pr_debug("%s: AFE Sidetone enable=%d session_id=0x%x ret=%d\n",
510                  __func__, sidetone_enable, session_id, ret);
511         return ret;
512 }
513
514 static int msm_voice_sidetone_get(struct snd_kcontrol *kcontrol,
515                                         struct snd_ctl_elem_value *ucontrol)
516 {
517
518         ucontrol->value.integer.value[0] = voc_get_afe_sidetone();
519         return 0;
520 }
521
522 static int msm_voice_gain_put(struct snd_kcontrol *kcontrol,
523                               struct snd_ctl_elem_value *ucontrol)
524 {
525         int ret = 0;
526         int volume = ucontrol->value.integer.value[0];
527         uint32_t session_id = ucontrol->value.integer.value[1];
528         int ramp_duration = ucontrol->value.integer.value[2];
529
530         if ((volume < 0) || (ramp_duration < 0)
531                 || (ramp_duration > MAX_RAMP_DURATION)) {
532                 pr_err(" %s Invalid arguments", __func__);
533
534                 ret = -EINVAL;
535                 goto done;
536         }
537
538         pr_debug("%s: volume: %d session_id: %#x ramp_duration: %d\n", __func__,
539                 volume, session_id, ramp_duration);
540
541         voc_set_rx_vol_step(session_id, RX_PATH, volume, ramp_duration);
542
543 done:
544         return ret;
545 }
546
547 static int msm_voice_mute_put(struct snd_kcontrol *kcontrol,
548                               struct snd_ctl_elem_value *ucontrol)
549 {
550         int ret = 0;
551         int mute = ucontrol->value.integer.value[0];
552         uint32_t session_id = ucontrol->value.integer.value[1];
553         int ramp_duration = ucontrol->value.integer.value[2];
554
555         if ((mute < 0) || (mute > 1) || (ramp_duration < 0)
556                 || (ramp_duration > MAX_RAMP_DURATION)) {
557                 pr_err(" %s Invalid arguments", __func__);
558
559                 ret = -EINVAL;
560                 goto done;
561         }
562
563         pr_debug("%s: mute=%d session_id=%#x ramp_duration=%d\n", __func__,
564                 mute, session_id, ramp_duration);
565
566         ret = voc_set_tx_mute(session_id, TX_PATH, mute, ramp_duration);
567
568 done:
569         return ret;
570 }
571
572 static int msm_voice_tx_device_mute_put(struct snd_kcontrol *kcontrol,
573                                         struct snd_ctl_elem_value *ucontrol)
574 {
575         int ret = 0;
576         int mute = ucontrol->value.integer.value[0];
577         uint32_t session_id = ucontrol->value.integer.value[1];
578         int ramp_duration = ucontrol->value.integer.value[2];
579
580         if ((mute < 0) || (mute > 1) || (ramp_duration < 0) ||
581             (ramp_duration > MAX_RAMP_DURATION)) {
582                 pr_err(" %s Invalid arguments", __func__);
583
584                 ret = -EINVAL;
585                 goto done;
586         }
587
588         pr_debug("%s: mute=%d session_id=%#x ramp_duration=%d\n", __func__,
589                  mute, session_id, ramp_duration);
590
591         ret = voc_set_device_mute(session_id, VSS_IVOLUME_DIRECTION_TX,
592                                   mute, ramp_duration);
593
594 done:
595         return ret;
596 }
597
598 static int msm_voice_rx_device_mute_put(struct snd_kcontrol *kcontrol,
599                                         struct snd_ctl_elem_value *ucontrol)
600 {
601         int ret = 0;
602         int mute = ucontrol->value.integer.value[0];
603         uint32_t session_id = ucontrol->value.integer.value[1];
604         int ramp_duration = ucontrol->value.integer.value[2];
605
606         if ((mute < 0) || (mute > 1) || (ramp_duration < 0) ||
607             (ramp_duration > MAX_RAMP_DURATION)) {
608                 pr_err(" %s Invalid arguments", __func__);
609
610                 ret = -EINVAL;
611                 goto done;
612         }
613
614         pr_debug("%s: mute=%d session_id=%#x ramp_duration=%d\n", __func__,
615                  mute, session_id, ramp_duration);
616
617         voc_set_device_mute(session_id, VSS_IVOLUME_DIRECTION_RX,
618                             mute, ramp_duration);
619
620 done:
621         return ret;
622 }
623
624
625
626 static const char const *tty_mode[] = {"OFF", "HCO", "VCO", "FULL"};
627 static const struct soc_enum msm_tty_mode_enum[] = {
628                 SOC_ENUM_SINGLE_EXT(4, tty_mode),
629 };
630
631 static int msm_voice_tty_mode_get(struct snd_kcontrol *kcontrol,
632                                 struct snd_ctl_elem_value *ucontrol)
633 {
634         ucontrol->value.integer.value[0] =
635                 voc_get_tty_mode(voc_get_session_id(VOICE_SESSION_NAME));
636         return 0;
637 }
638
639 static int msm_voice_tty_mode_put(struct snd_kcontrol *kcontrol,
640                                 struct snd_ctl_elem_value *ucontrol)
641 {
642         int tty_mode = ucontrol->value.integer.value[0];
643
644         pr_debug("%s: tty_mode=%d\n", __func__, tty_mode);
645
646         voc_set_tty_mode(voc_get_session_id(VOICE_SESSION_NAME), tty_mode);
647         voc_set_tty_mode(voc_get_session_id(VOICE2_SESSION_NAME), tty_mode);
648         voc_set_tty_mode(voc_get_session_id(VOLTE_SESSION_NAME), tty_mode);
649         voc_set_tty_mode(voc_get_session_id(VOWLAN_SESSION_NAME), tty_mode);
650         voc_set_tty_mode(voc_get_session_id(VOICEMMODE1_NAME), tty_mode);
651         voc_set_tty_mode(voc_get_session_id(VOICEMMODE2_NAME), tty_mode);
652
653         return 0;
654 }
655
656 static int msm_voice_slowtalk_put(struct snd_kcontrol *kcontrol,
657                         struct snd_ctl_elem_value *ucontrol)
658 {
659         int st_enable = ucontrol->value.integer.value[0];
660         uint32_t session_id = ucontrol->value.integer.value[1];
661         struct module_instance_info mod_inst_info = {0};
662
663         pr_debug("%s: st enable=%d session_id=%#x\n", __func__, st_enable,
664                  session_id);
665
666         mod_inst_info.module_id = MODULE_ID_VOICE_MODULE_ST;
667         mod_inst_info.instance_id = INSTANCE_ID_0;
668         voc_set_pp_enable(session_id, mod_inst_info, st_enable);
669
670         return 0;
671 }
672
673 static int msm_voice_hd_voice_put(struct snd_kcontrol *kcontrol,
674                                   struct snd_ctl_elem_value *ucontrol)
675 {
676         int ret = 0;
677         uint32_t hd_enable = ucontrol->value.integer.value[0];
678         uint32_t session_id = ucontrol->value.integer.value[1];
679
680         pr_debug("%s: HD Voice enable=%d session_id=%#x\n", __func__, hd_enable,
681                  session_id);
682
683         ret = voc_set_hd_enable(session_id, hd_enable);
684
685         return ret;
686 }
687
688 static int msm_dtmf_detect_rx_vsid_put(struct snd_kcontrol *kcontrol,
689                                         struct snd_ctl_elem_value *ucontrol)
690 {
691         uint32_t session_id = ucontrol->value.integer.value[0];
692         uint32_t enable = ucontrol->value.integer.value[1];
693
694         if (enable)
695                 enable = 1;
696
697         pr_debug("%s: sess_id=%d enable=%d\n", __func__, session_id, enable);
698
699         return voc_enable_dtmf_rx_detection(session_id, enable);
700 }
701
702 static int msm_dtmf_detect_rx_vsid_cb_put(struct snd_kcontrol *kcontrol,
703                                         struct snd_ctl_elem_value *ucontrol)
704 {
705         struct msm_voice *dtmf_voice_info = NULL;
706         uint32_t session_id = ucontrol->value.integer.value[0];
707         uint32_t enable = ucontrol->value.integer.value[1];
708
709         if (!is_valid_session_id(session_id)) {
710                 pr_err(" %s Invalid session_id : %x\n", __func__, session_id);
711                 return -EINVAL;
712         }
713
714         if (enable)
715                 enable = 1;
716
717         pr_debug("%s: enable dtmf detect cb =%d for session_id=%d\n",
718                 __func__, enable, session_id);
719
720         dtmf_voice_info = &voice_info[get_idx_for_session(session_id)];
721         voc_register_dtmf_rx_detection_cb
722                 ((dtmf_rx_det_cb_fn) dtmf_rx_detected_evt_hdlr,
723                 (void *) dtmf_voice_info->capture_substream->private_data);
724
725         return 0;
726 }
727
728 static int msm_voice_topology_disable_put(struct snd_kcontrol *kcontrol,
729                                           struct snd_ctl_elem_value *ucontrol)
730 {
731         int ret = 0;
732         int disable = ucontrol->value.integer.value[0];
733         uint32_t session_id = ucontrol->value.integer.value[1];
734
735         if ((disable < 0) || (disable > 1)) {
736                 pr_err(" %s Invalid arguments: %d\n", __func__, disable);
737
738                 ret = -EINVAL;
739                 goto done;
740         }
741         pr_debug("%s: disable = %d, session_id = %d\n", __func__, disable,
742                  session_id);
743
744         ret = voc_disable_topology(session_id, disable);
745
746 done:
747         return ret;
748 }
749
750 static int msm_voice_cvd_version_info(struct snd_kcontrol *kcontrol,
751                                       struct snd_ctl_elem_info *uinfo)
752 {
753         int ret = 0;
754
755         pr_debug("%s:\n", __func__);
756
757         uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
758         uinfo->count = CVD_VERSION_STRING_MAX_SIZE;
759
760         return ret;
761 }
762
763 static int msm_voice_cvd_version_get(struct snd_kcontrol *kcontrol,
764                                      struct snd_ctl_elem_value *ucontrol)
765 {
766         char cvd_version[CVD_VERSION_STRING_MAX_SIZE] = CVD_VERSION_DEFAULT;
767         int ret;
768
769         pr_debug("%s:\n", __func__);
770
771         ret = voc_get_cvd_version(cvd_version);
772
773         if (ret)
774                 pr_err("%s: Error retrieving CVD version, error:%d\n",
775                         __func__, ret);
776
777         memcpy(ucontrol->value.bytes.data, cvd_version, sizeof(cvd_version));
778
779         return 0;
780 }
781
782 static struct snd_kcontrol_new msm_voice_controls[] = {
783         SOC_SINGLE_MULTI_EXT("Voice Rx Device Mute", SND_SOC_NOPM, 0, VSID_MAX,
784                                 0, 3, NULL, msm_voice_rx_device_mute_put),
785         SOC_SINGLE_MULTI_EXT("Voice Tx Device Mute", SND_SOC_NOPM, 0, VSID_MAX,
786                                 0, 3, NULL, msm_voice_tx_device_mute_put),
787         SOC_SINGLE_MULTI_EXT("Voice Tx Mute", SND_SOC_NOPM, 0, VSID_MAX,
788                                 0, 3, NULL, msm_voice_mute_put),
789         SOC_SINGLE_MULTI_EXT("Voice Rx Gain", SND_SOC_NOPM, 0, VSID_MAX, 0, 3,
790                                 NULL, msm_voice_gain_put),
791         SOC_ENUM_EXT("TTY Mode", msm_tty_mode_enum[0], msm_voice_tty_mode_get,
792                                 msm_voice_tty_mode_put),
793         SOC_SINGLE_MULTI_EXT("Slowtalk Enable", SND_SOC_NOPM, 0, VSID_MAX, 0, 2,
794                                 NULL, msm_voice_slowtalk_put),
795         SOC_SINGLE_MULTI_EXT("Voice Topology Disable", SND_SOC_NOPM, 0,
796                              VSID_MAX, 0, 2, NULL,
797                              msm_voice_topology_disable_put),
798         SOC_SINGLE_MULTI_EXT("HD Voice Enable", SND_SOC_NOPM, 0, VSID_MAX, 0, 2,
799                              NULL, msm_voice_hd_voice_put),
800         SOC_SINGLE_MULTI_EXT("DTMF_Detect Rx VSID enable",
801                                 SND_SOC_NOPM, 0, VSID_MAX, 0, 2,
802                                 NULL, msm_dtmf_detect_rx_vsid_put),
803         SOC_SINGLE_MULTI_EXT("DTMF_Detect Rx Callback VSID enable",
804                                 SND_SOC_NOPM, 0, VSID_MAX, 0, 2,
805                                 NULL, msm_dtmf_detect_rx_vsid_cb_put),
806         {
807                 .access = SNDRV_CTL_ELEM_ACCESS_READ,
808                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
809                 .name   = "CVD Version",
810                 .info   = msm_voice_cvd_version_info,
811                 .get    = msm_voice_cvd_version_get,
812         },
813         SOC_SINGLE_MULTI_EXT("Voice Sidetone Enable", SND_SOC_NOPM, 0, 1, 0, 1,
814                              msm_voice_sidetone_get, msm_voice_sidetone_put),
815
816 };
817
818 static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
819                                           struct snd_ctl_elem_value *ucontrol)
820 {
821         return 0;
822 }
823
824 static int msm_pcm_add_voice_adsp_stream_cmd_control(
825                         struct snd_soc_pcm_runtime *rtd)
826 {
827         const char *mixer_ctl_name = DSP_STREAM_CMD;
828         const char *deviceNo = "NN";
829         char *mixer_str = NULL;
830         int ctl_len = 0, ret = 0;
831         struct snd_kcontrol_new fe_voice_adsp_stream_cmd_config_control[1] = {
832                 {
833                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
834                 .name = "?",
835                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
836                 .info = msm_adsp_stream_cmd_info,
837                 .put = msm_pcm_adsp_stream_cmd_put,
838                 .private_value = 0,
839                 }
840         };
841
842         if (!rtd) {
843                 pr_err("%s rtd is NULL\n", __func__);
844                 return -EINVAL;
845         }
846
847         ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
848         mixer_str = kzalloc(ctl_len, GFP_KERNEL);
849         if (!mixer_str)
850                 return -ENOMEM;
851
852         snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
853         fe_voice_adsp_stream_cmd_config_control[0].name = mixer_str;
854         fe_voice_adsp_stream_cmd_config_control[0].private_value =
855                 rtd->dai_link->be_id;
856         pr_debug("Registering new mixer ctl %s\n", mixer_str);
857         ret = snd_soc_add_platform_controls(rtd->platform,
858                 fe_voice_adsp_stream_cmd_config_control,
859                 ARRAY_SIZE(fe_voice_adsp_stream_cmd_config_control));
860         if (ret < 0)
861                 pr_err("%s: failed add ctl %s. err = %d\n",
862                         __func__, mixer_str, ret);
863
864         kfree(mixer_str);
865         return ret;
866 }
867
868 static int msm_pcm_add_voice_adsp_stream_callback_control(
869                         struct snd_soc_pcm_runtime *rtd)
870 {
871         const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
872         const char *deviceNo = "NN";
873         char *mixer_str = NULL;
874         int ctl_len = 0, ret = 0;
875         struct snd_kcontrol *kctl;
876
877         struct snd_kcontrol_new fe_voice_adsp_callback_config_control[1] = {
878                 {
879                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
880                 .name = "?",
881                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
882                 .info = msm_adsp_stream_callback_info,
883                 .get = msm_adsp_stream_callback_get,
884                 .private_value = 0,
885                 }
886         };
887
888         if (!rtd) {
889                 pr_err("%s NULL rtd\n", __func__);
890                 return -EINVAL;
891         }
892
893         pr_debug("%s: added new pcm FE with name %s, id %d, cpu dai %s, device no %d\n",
894                  __func__, rtd->dai_link->name, rtd->dai_link->be_id,
895                  rtd->dai_link->cpu_dai_name, rtd->pcm->device);
896         ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
897         mixer_str = kzalloc(ctl_len, GFP_KERNEL);
898         if (!mixer_str)
899                 return -ENOMEM;
900
901         snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
902         fe_voice_adsp_callback_config_control[0].name = mixer_str;
903         fe_voice_adsp_callback_config_control[0].private_value =
904                 rtd->dai_link->be_id;
905         pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
906         ret = snd_soc_add_platform_controls(rtd->platform,
907                         fe_voice_adsp_callback_config_control,
908                         ARRAY_SIZE(fe_voice_adsp_callback_config_control));
909         if (ret < 0) {
910                 pr_err("%s: failed to add ctl %s. err = %d\n",
911                         __func__, mixer_str, ret);
912                 ret = -EINVAL;
913                 goto free_mixer_str;
914         }
915
916         kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
917         if (!kctl) {
918                 pr_err("%s: failed to get kctl %s.\n", __func__, mixer_str);
919                 ret = -EINVAL;
920                 goto free_mixer_str;
921         }
922
923         kctl->private_data = NULL;
924
925 free_mixer_str:
926         kfree(mixer_str);
927         return ret;
928 }
929
930 static struct snd_pcm_ops msm_pcm_ops = {
931         .open                   = msm_pcm_open,
932         .hw_params              = msm_pcm_hw_params,
933         .close                  = msm_pcm_close,
934         .prepare                = msm_pcm_prepare,
935         .trigger                = msm_pcm_trigger,
936         .ioctl                  = msm_pcm_ioctl,
937         .compat_ioctl           = msm_pcm_ioctl,
938 };
939
940
941 static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
942 {
943         struct snd_card *card = rtd->card->snd_card;
944         int ret = 0;
945
946         if (!card->dev->coherent_dma_mask)
947                 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
948
949         ret = msm_pcm_add_voice_adsp_stream_cmd_control(rtd);
950         if (ret)
951                 pr_err("%s: Could not add pcm ADSP Stream Cmd Control\n",
952                         __func__);
953
954         ret = msm_pcm_add_voice_adsp_stream_callback_control(rtd);
955         if (ret)
956                 pr_err("%s: Could not add pcm ADSP Stream Callback Control\n",
957                         __func__);
958
959         return ret;
960 }
961
962 static int msm_pcm_voice_probe(struct snd_soc_platform *platform)
963 {
964         snd_soc_add_platform_controls(platform, msm_voice_controls,
965                                         ARRAY_SIZE(msm_voice_controls));
966
967         return 0;
968 }
969
970 static struct snd_soc_platform_driver msm_soc_platform = {
971         .ops            = &msm_pcm_ops,
972         .pcm_new        = msm_asoc_pcm_new,
973         .probe          = msm_pcm_voice_probe,
974 };
975
976 static int msm_pcm_probe(struct platform_device *pdev)
977 {
978         int rc;
979         bool destroy_cvd = false;
980         bool vote_bms = false;
981         const char *is_destroy_cvd = "qcom,destroy-cvd";
982         const char *is_vote_bms = "qcom,vote-bms";
983
984         if (!is_voc_initialized()) {
985                 pr_debug("%s: voice module not initialized yet, deferring probe()\n",
986                        __func__);
987
988                 rc = -EPROBE_DEFER;
989                 goto done;
990         }
991
992         rc = voc_alloc_cal_shared_memory();
993         if (rc == -EPROBE_DEFER) {
994                 pr_debug("%s: memory allocation for calibration deferred %d\n",
995                          __func__, rc);
996
997                 goto done;
998         } else if (rc < 0) {
999                 pr_err("%s: memory allocation for calibration failed %d\n",
1000                        __func__, rc);
1001         }
1002
1003         pr_debug("%s: dev name %s\n",
1004                         __func__, dev_name(&pdev->dev));
1005         destroy_cvd = of_property_read_bool(pdev->dev.of_node,
1006                                                 is_destroy_cvd);
1007         voc_set_destroy_cvd_flag(destroy_cvd);
1008
1009         vote_bms = of_property_read_bool(pdev->dev.of_node,
1010                                          is_vote_bms);
1011         voc_set_vote_bms_flag(vote_bms);
1012
1013         rc = snd_soc_register_platform(&pdev->dev,
1014                                        &msm_soc_platform);
1015
1016 done:
1017         return rc;
1018 }
1019
1020 static int msm_pcm_remove(struct platform_device *pdev)
1021 {
1022         snd_soc_unregister_platform(&pdev->dev);
1023         return 0;
1024 }
1025
1026 static const struct of_device_id msm_voice_dt_match[] = {
1027         {.compatible = "qcom,msm-pcm-voice"},
1028         {}
1029 };
1030 MODULE_DEVICE_TABLE(of, msm_voice_dt_match);
1031
1032 static struct platform_driver msm_pcm_driver = {
1033         .driver = {
1034                 .name = "msm-pcm-voice",
1035                 .owner = THIS_MODULE,
1036                 .of_match_table = msm_voice_dt_match,
1037         },
1038         .probe = msm_pcm_probe,
1039         .remove = msm_pcm_remove,
1040 };
1041
1042 static int __init msm_soc_platform_init(void)
1043 {
1044         int i = 0;
1045
1046         memset(&voice_info, 0, sizeof(voice_info));
1047
1048         for (i = 0; i < VOICE_SESSION_INDEX_MAX; i++)
1049                 mutex_init(&voice_info[i].lock);
1050
1051         return platform_driver_register(&msm_pcm_driver);
1052 }
1053 module_init(msm_soc_platform_init);
1054
1055 static void __exit msm_soc_platform_exit(void)
1056 {
1057         platform_driver_unregister(&msm_pcm_driver);
1058 }
1059 module_exit(msm_soc_platform_exit);
1060
1061 MODULE_DESCRIPTION("Voice PCM module platform driver");
1062 MODULE_LICENSE("GPL v2");