blob: 9953eebcef6bedfa72aac383f26a1b5f66bbfeda [file] [log] [blame]
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301/* Copyright (c) 2013-2014, 2017 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/module.h>
15#include <linux/time.h>
16#include <linux/wait.h>
17#include <linux/platform_device.h>
18#include <linux/slab.h>
19#include <linux/dma-mapping.h>
20#include <sound/core.h>
21#include <sound/soc.h>
22#include <sound/pcm.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053023#include <dsp/q6afe-v2.h>
24#include <dsp/q6voice.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053025
26#include "msm-pcm-q6-v2.h"
27#include "msm-pcm-routing-v2.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053028
29enum {
30 DTMF_IN_RX,
31 DTMF_IN_TX,
32};
33
34enum format {
35 FORMAT_S16_LE = 2
36};
37
38struct dtmf_det_info {
39 char session[MAX_SESSION_NAME_LEN];
40 uint8_t dir;
41 uint16_t high_freq;
42 uint16_t low_freq;
43};
44
45struct dtmf_buf_node {
46 struct list_head list;
47 struct dtmf_det_info dtmf_det_pkt;
48};
49
50enum dtmf_state {
51 DTMF_GEN_RX_STOPPED,
52 DTMF_GEN_RX_STARTED,
53};
54
55#define DTMF_MAX_Q_LEN 10
56#define DTMF_PKT_SIZE sizeof(struct dtmf_det_info)
57
58struct dtmf_drv_info {
59 enum dtmf_state state;
60 struct snd_pcm_substream *capture_substream;
61
62 struct list_head out_queue;
63 struct list_head free_out_queue;
64
65 wait_queue_head_t out_wait;
66
67 struct mutex lock;
68 spinlock_t dsp_lock;
69
70 uint8_t capture_start;
71 uint8_t capture_instance;
72
73 unsigned int pcm_capture_size;
74 unsigned int pcm_capture_count;
75 unsigned int pcm_capture_irq_pos;
76 unsigned int pcm_capture_buf_pos;
77};
78
79static struct snd_pcm_hardware msm_pcm_hardware = {
80 .info = (SNDRV_PCM_INFO_MMAP |
81 SNDRV_PCM_INFO_BLOCK_TRANSFER |
82 SNDRV_PCM_INFO_MMAP_VALID |
83 SNDRV_PCM_INFO_INTERLEAVED),
84 .formats = SNDRV_PCM_FMTBIT_S16_LE,
85 .channels_min = 1,
86 .channels_max = 1,
87 .buffer_bytes_max = (sizeof(struct dtmf_buf_node) * DTMF_MAX_Q_LEN),
88 .period_bytes_min = DTMF_PKT_SIZE,
89 .period_bytes_max = DTMF_PKT_SIZE,
90 .periods_min = DTMF_MAX_Q_LEN,
91 .periods_max = DTMF_MAX_Q_LEN,
92 .fifo_size = 0,
93};
94
95static int msm_dtmf_rx_generate_put(struct snd_kcontrol *kcontrol,
96 struct snd_ctl_elem_value *ucontrol)
97{
98 uint16_t low_freq = ucontrol->value.integer.value[0];
99 uint16_t high_freq = ucontrol->value.integer.value[1];
100 int64_t duration = ucontrol->value.integer.value[2];
101 uint16_t gain = ucontrol->value.integer.value[3];
102
103 pr_debug("%s: low_freq=%d high_freq=%d duration=%d gain=%d\n",
104 __func__, low_freq, high_freq, (int)duration, gain);
105 afe_dtmf_generate_rx(duration, high_freq, low_freq, gain);
106 return 0;
107}
108
109static int msm_dtmf_rx_generate_get(struct snd_kcontrol *kcontrol,
110 struct snd_ctl_elem_value *ucontrol)
111{
112 pr_debug("%s:\n", __func__);
113 ucontrol->value.integer.value[0] = 0;
114 return 0;
115}
116
117static int msm_dtmf_detect_voice_rx_put(struct snd_kcontrol *kcontrol,
118 struct snd_ctl_elem_value *ucontrol)
119{
120 int enable = ucontrol->value.integer.value[0];
121
122 pr_debug("%s: enable=%d\n", __func__, enable);
123 voc_enable_dtmf_rx_detection(voc_get_session_id(VOICE_SESSION_NAME),
124 enable);
125
126 return 0;
127}
128
129static int msm_dtmf_detect_voice_rx_get(struct snd_kcontrol *kcontrol,
130 struct snd_ctl_elem_value *ucontrol)
131{
132 ucontrol->value.integer.value[0] = 0;
133 return 0;
134}
135
136static int msm_dtmf_detect_volte_rx_put(struct snd_kcontrol *kcontrol,
137 struct snd_ctl_elem_value *ucontrol)
138{
139 int enable = ucontrol->value.integer.value[0];
140
141 pr_debug("%s: enable=%d\n", __func__, enable);
142 voc_enable_dtmf_rx_detection(voc_get_session_id(VOLTE_SESSION_NAME),
143 enable);
144
145 return 0;
146}
147
148static int msm_dtmf_detect_volte_rx_get(struct snd_kcontrol *kcontrol,
149 struct snd_ctl_elem_value *ucontrol)
150{
151 ucontrol->value.integer.value[0] = 0;
152 return 0;
153}
154
155static struct snd_kcontrol_new msm_dtmf_controls[] = {
156 SOC_SINGLE_MULTI_EXT("DTMF_Generate Rx Low High Duration Gain",
157 SND_SOC_NOPM, 0, 5000, 0, 4,
158 msm_dtmf_rx_generate_get,
159 msm_dtmf_rx_generate_put),
160 SOC_SINGLE_EXT("DTMF_Detect Rx Voice enable", SND_SOC_NOPM, 0, 1, 0,
161 msm_dtmf_detect_voice_rx_get,
162 msm_dtmf_detect_voice_rx_put),
163 SOC_SINGLE_EXT("DTMF_Detect Rx VoLTE enable", SND_SOC_NOPM, 0, 1, 0,
164 msm_dtmf_detect_volte_rx_get,
165 msm_dtmf_detect_volte_rx_put),
166};
167
168static int msm_pcm_dtmf_probe(struct snd_soc_platform *platform)
169{
170 snd_soc_add_platform_controls(platform, msm_dtmf_controls,
171 ARRAY_SIZE(msm_dtmf_controls));
172 return 0;
173}
174
175static void dtmf_rx_detected_cb(uint8_t *pkt,
176 char *session,
177 void *private_data)
178{
179 struct dtmf_buf_node *buf_node = NULL;
180 struct vss_istream_evt_rx_dtmf_detected *dtmf_det_pkt =
181 (struct vss_istream_evt_rx_dtmf_detected *)pkt;
182 struct dtmf_drv_info *prtd = private_data;
183 unsigned long dsp_flags;
184
185 pr_debug("%s\n", __func__);
186 if (prtd->capture_substream == NULL)
187 return;
188
189 /* Copy dtmf detected info into out_queue. */
190 spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
191 /* discarding dtmf detection info till start is received */
192 if (!list_empty(&prtd->free_out_queue) && prtd->capture_start) {
193 buf_node = list_first_entry(&prtd->free_out_queue,
194 struct dtmf_buf_node, list);
195 list_del(&buf_node->list);
196 buf_node->dtmf_det_pkt.high_freq = dtmf_det_pkt->high_freq;
197 buf_node->dtmf_det_pkt.low_freq = dtmf_det_pkt->low_freq;
198 if (session != NULL)
199 strlcpy(buf_node->dtmf_det_pkt.session,
200 session, MAX_SESSION_NAME_LEN);
201
202 buf_node->dtmf_det_pkt.dir = DTMF_IN_RX;
203 pr_debug("high =%d, low=%d session=%s\n",
204 buf_node->dtmf_det_pkt.high_freq,
205 buf_node->dtmf_det_pkt.low_freq,
206 buf_node->dtmf_det_pkt.session);
207 list_add_tail(&buf_node->list, &prtd->out_queue);
208 prtd->pcm_capture_irq_pos += prtd->pcm_capture_count;
209 spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
210 snd_pcm_period_elapsed(prtd->capture_substream);
211 } else {
212 spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
213 pr_err("DTMF detection pkt in Rx dropped, no free node available\n");
214 }
215
216 wake_up(&prtd->out_wait);
217}
218
219static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
220 int channel, snd_pcm_uframes_t hwoff,
221 void __user *buf, snd_pcm_uframes_t frames)
222{
223 int ret = 0;
224 int count = 0;
225 struct dtmf_buf_node *buf_node = NULL;
226 struct snd_pcm_runtime *runtime = substream->runtime;
227 struct dtmf_drv_info *prtd = runtime->private_data;
228 unsigned long dsp_flags;
229
230 count = frames_to_bytes(runtime, frames);
231
232 ret = wait_event_interruptible_timeout(prtd->out_wait,
233 (!list_empty(&prtd->out_queue)),
234 1 * HZ);
235
236 if (ret > 0) {
237 if (count <= DTMF_PKT_SIZE) {
238 spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
239 buf_node = list_first_entry(&prtd->out_queue,
240 struct dtmf_buf_node, list);
241 list_del(&buf_node->list);
242 spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
243 ret = copy_to_user(buf,
244 &buf_node->dtmf_det_pkt,
245 count);
246 if (ret) {
247 pr_err("%s: Copy to user returned %d\n",
248 __func__, ret);
249 ret = -EFAULT;
250 }
251 spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
252 list_add_tail(&buf_node->list,
253 &prtd->free_out_queue);
254 spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
255
256 } else {
257 pr_err("%s: Read count %d > DTMF_PKT_SIZE\n",
258 __func__, count);
259 ret = -ENOMEM;
260 }
261 } else if (ret == 0) {
262 pr_err("%s: No UL data available\n", __func__);
263 ret = -ETIMEDOUT;
264 } else {
265 pr_err("%s: Read was interrupted\n", __func__);
266 ret = -ERESTARTSYS;
267 }
268 return ret;
269}
270
271static int msm_pcm_copy(struct snd_pcm_substream *substream, int a,
272 snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
273{
274 int ret = 0;
275
276 pr_debug("%s() DTMF\n", __func__);
277
278 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
279 ret = msm_pcm_capture_copy(substream, a, hwoff, buf, frames);
280
281 return ret;
282}
283
284static int msm_pcm_open(struct snd_pcm_substream *substream)
285{
286 struct snd_pcm_runtime *runtime = substream->runtime;
287 struct dtmf_drv_info *prtd = NULL;
288 int ret = 0;
289
290 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
291 prtd = kzalloc(sizeof(struct dtmf_drv_info), GFP_KERNEL);
292
293 if (prtd == NULL) {
294 ret = -ENOMEM;
295 goto done;
296 }
297
298 mutex_init(&prtd->lock);
299 spin_lock_init(&prtd->dsp_lock);
300 init_waitqueue_head(&prtd->out_wait);
301 INIT_LIST_HEAD(&prtd->out_queue);
302 INIT_LIST_HEAD(&prtd->free_out_queue);
303
304 runtime->hw = msm_pcm_hardware;
305
306 ret = snd_pcm_hw_constraint_integer(runtime,
307 SNDRV_PCM_HW_PARAM_PERIODS);
308 if (ret < 0)
309 pr_info("snd_pcm_hw_constraint_integer failed\n");
310
311 prtd->capture_substream = substream;
312 prtd->capture_instance++;
313 runtime->private_data = prtd;
314 }
315
316done:
317 return ret;
318}
319
320static int msm_pcm_close(struct snd_pcm_substream *substream)
321{
322 int ret = 0;
323 struct list_head *ptr = NULL;
324 struct list_head *next = NULL;
325 struct dtmf_buf_node *buf_node = NULL;
326 struct snd_dma_buffer *c_dma_buf;
327 struct snd_pcm_substream *c_substream;
328 struct snd_pcm_runtime *runtime = substream->runtime;
329 struct dtmf_drv_info *prtd = runtime->private_data;
330 unsigned long dsp_flags;
331
332 pr_debug("%s() DTMF\n", __func__);
333
334 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
335 mutex_lock(&prtd->lock);
336 wake_up(&prtd->out_wait);
337
338 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
339 prtd->capture_instance--;
340
341 if (!prtd->capture_instance) {
342 if (prtd->state == DTMF_GEN_RX_STARTED) {
343 prtd->state = DTMF_GEN_RX_STOPPED;
344 voc_disable_dtmf_det_on_active_sessions();
345 voc_register_dtmf_rx_detection_cb(NULL, NULL);
346 }
347 /* release all buffer */
348 /* release out_queue and free_out_queue */
349 pr_debug("release all buffer\n");
350 c_substream = prtd->capture_substream;
351 if (c_substream == NULL) {
352 pr_debug("c_substream is NULL\n");
353 mutex_unlock(&prtd->lock);
354 return -EINVAL;
355 }
356
357 c_dma_buf = &c_substream->dma_buffer;
358 if (c_dma_buf == NULL) {
359 pr_debug("c_dma_buf is NULL.\n");
360 mutex_unlock(&prtd->lock);
361 return -EINVAL;
362 }
363
364 if (c_dma_buf->area != NULL) {
365 spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
366 list_for_each_safe(ptr, next,
367 &prtd->out_queue) {
368 buf_node = list_entry(ptr,
369 struct dtmf_buf_node, list);
370 list_del(&buf_node->list);
371 }
372
373 list_for_each_safe(ptr, next,
374 &prtd->free_out_queue) {
375 buf_node = list_entry(ptr,
376 struct dtmf_buf_node, list);
377 list_del(&buf_node->list);
378 }
379
380 spin_unlock_irqrestore(&prtd->dsp_lock,
381 dsp_flags);
382 dma_free_coherent(c_substream->pcm->card->dev,
383 runtime->hw.buffer_bytes_max,
384 c_dma_buf->area,
385 c_dma_buf->addr);
386 c_dma_buf->area = NULL;
387 }
388 }
389 prtd->capture_substream = NULL;
390 mutex_unlock(&prtd->lock);
391 }
392
393 return ret;
394}
395
396static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
397 struct snd_pcm_hw_params *params)
398{
399 struct snd_pcm_runtime *runtime = substream->runtime;
400 struct dtmf_drv_info *prtd = runtime->private_data;
401 struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
402 struct dtmf_buf_node *buf_node = NULL;
403 int i = 0, offset = 0;
404 int ret = 0;
405
406 pr_debug("%s: DTMF\n", __func__);
407 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
408 mutex_lock(&prtd->lock);
409 dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
410 dma_buf->dev.dev = substream->pcm->card->dev;
411 dma_buf->private_data = NULL;
412
413 dma_buf->area = dma_alloc_coherent(substream->pcm->card->dev,
414 runtime->hw.buffer_bytes_max,
415 &dma_buf->addr, GFP_KERNEL);
416 if (!dma_buf->area) {
417 pr_err("%s:MSM DTMF dma_alloc failed\n", __func__);
418 mutex_unlock(&prtd->lock);
419 return -ENOMEM;
420 }
421
422 dma_buf->bytes = runtime->hw.buffer_bytes_max;
423 memset(dma_buf->area, 0, runtime->hw.buffer_bytes_max);
424
425 for (i = 0; i < DTMF_MAX_Q_LEN; i++) {
426 pr_debug("node =%d\n", i);
427 buf_node = (void *) dma_buf->area + offset;
428 list_add_tail(&buf_node->list,
429 &prtd->free_out_queue);
430 offset = offset + sizeof(struct dtmf_buf_node);
431 }
432
433 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
434 mutex_unlock(&prtd->lock);
435 }
436
437 return ret;
438}
439
440static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
441{
442 struct snd_pcm_runtime *runtime = substream->runtime;
443 struct dtmf_drv_info *prtd = runtime->private_data;
444
445 pr_debug("%s: DTMF\n", __func__);
446 prtd->pcm_capture_size = snd_pcm_lib_buffer_bytes(substream);
447 prtd->pcm_capture_count = snd_pcm_lib_period_bytes(substream);
448 prtd->pcm_capture_irq_pos = 0;
449 prtd->pcm_capture_buf_pos = 0;
450 return 0;
451}
452
453static int msm_pcm_prepare(struct snd_pcm_substream *substream)
454{
455 struct snd_pcm_runtime *runtime = substream->runtime;
456 struct dtmf_drv_info *prtd = runtime->private_data;
457
458 pr_debug("%s: DTMF\n", __func__);
459
460 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
461 mutex_lock(&prtd->lock);
462
463 msm_pcm_capture_prepare(substream);
464
465 if (runtime->format != FORMAT_S16_LE) {
466 pr_err("format:%u doesn't match %d\n",
467 (uint32_t)runtime->format, FORMAT_S16_LE);
468 mutex_unlock(&prtd->lock);
469 return -EINVAL;
470 }
471
472 if (prtd->capture_instance &&
473 (prtd->state != DTMF_GEN_RX_STARTED)) {
474 voc_register_dtmf_rx_detection_cb(dtmf_rx_detected_cb,
475 prtd);
476 prtd->state = DTMF_GEN_RX_STARTED;
477 }
478 mutex_unlock(&prtd->lock);
479 }
480
481 return 0;
482}
483
484static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
485{
486 int ret = 0;
487 struct snd_pcm_runtime *runtime = substream->runtime;
488 struct dtmf_drv_info *prtd = runtime->private_data;
489
490 switch (cmd) {
491 case SNDRV_PCM_TRIGGER_START:
492 case SNDRV_PCM_TRIGGER_RESUME:
493 pr_debug("%s: Trigger start\n", __func__);
494 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
495 prtd->capture_start = 1;
496 break;
497 case SNDRV_PCM_TRIGGER_STOP:
498 pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
499 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
500 prtd->capture_start = 0;
501 break;
502 default:
503 ret = -EINVAL;
504 break;
505 }
506
507 return ret;
508}
509
510static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream)
511{
512 snd_pcm_uframes_t ret = 0;
513 struct snd_pcm_runtime *runtime = substream->runtime;
514 struct dtmf_drv_info *prtd = runtime->private_data;
515
516 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
517 if (prtd->pcm_capture_irq_pos >= prtd->pcm_capture_size)
518 prtd->pcm_capture_irq_pos = 0;
519 ret = bytes_to_frames(runtime, (prtd->pcm_capture_irq_pos));
520 }
521
522 return ret;
523}
524
525static const struct snd_pcm_ops msm_pcm_ops = {
526 .open = msm_pcm_open,
527 .copy = msm_pcm_copy,
528 .hw_params = msm_pcm_hw_params,
529 .close = msm_pcm_close,
530 .prepare = msm_pcm_prepare,
531 .trigger = msm_pcm_trigger,
532 .pointer = msm_pcm_pointer,
533};
534
535static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
536{
537 struct snd_card *card = rtd->card->snd_card;
538 int ret = 0;
539
540 if (!card->dev->coherent_dma_mask)
541 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
542 return ret;
543}
544
545static struct snd_soc_platform_driver msm_soc_platform = {
546 .ops = &msm_pcm_ops,
547 .pcm_new = msm_asoc_pcm_new,
548 .probe = msm_pcm_dtmf_probe,
549};
550
551static int msm_pcm_probe(struct platform_device *pdev)
552{
553 pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
554
555 return snd_soc_register_platform(&pdev->dev,
556 &msm_soc_platform);
557}
558
559static int msm_pcm_remove(struct platform_device *pdev)
560{
561 snd_soc_unregister_platform(&pdev->dev);
562 return 0;
563}
564
565static const struct of_device_id msm_pcm_dtmf_dt_match[] = {
566 {.compatible = "qcom,msm-pcm-dtmf"},
567 {}
568};
569
570MODULE_DEVICE_TABLE(of, msm_pcm_dtmf_dt_match);
571
572
573static struct platform_driver msm_pcm_driver = {
574 .driver = {
575 .name = "msm-pcm-dtmf",
576 .owner = THIS_MODULE,
577 .of_match_table = msm_pcm_dtmf_dt_match,
578 },
579 .probe = msm_pcm_probe,
580 .remove = msm_pcm_remove,
581};
582
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530583int __init msm_pcm_dtmf_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530584{
585 return platform_driver_register(&msm_pcm_driver);
586}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530587
Asish Bhattacharya5faacb32017-12-04 17:23:15 +0530588void msm_pcm_dtmf_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530589{
590 platform_driver_unregister(&msm_pcm_driver);
591}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530592
593MODULE_DESCRIPTION("DTMF platform driver");
594MODULE_LICENSE("GPL v2");