blob: a92860960143b2b59634efb8e4b9eea02c913d3d [file] [log] [blame]
Sidipotu Ashok5c6855b2019-01-08 15:58:37 +05301/* Copyright (c) 2012-2019, 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
14#include <linux/init.h>
15#include <linux/err.h>
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/time.h>
Ajit Pandey3d7b9a22019-09-05 16:26:01 +053019#include <linux/mutex.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053020#include <linux/wait.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <sound/core.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26#include <sound/pcm.h>
27#include <sound/initval.h>
28#include <sound/control.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053029#include <sound/timer.h>
30#include <asm/dma.h>
31#include <linux/dma-mapping.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053032#include <linux/msm_audio.h>
33
34#include <linux/of_device.h>
35#include <sound/tlv.h>
36#include <sound/pcm_params.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053037#include <dsp/msm_audio_ion.h>
38#include <dsp/q6audio-v2.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053039
40#include "msm-pcm-q6-v2.h"
41#include "msm-pcm-routing-v2.h"
42#include "msm-qti-pp-config.h"
43
44enum stream_state {
45 IDLE = 0,
46 STOPPED,
47 RUNNING,
48};
49
50static struct audio_locks the_locks;
51
52#define PCM_MASTER_VOL_MAX_STEPS 0x2000
53static const DECLARE_TLV_DB_LINEAR(msm_pcm_vol_gain, 0,
54 PCM_MASTER_VOL_MAX_STEPS);
55
56struct snd_msm {
57 struct snd_card *card;
58 struct snd_pcm *pcm;
59};
60
61#define CMD_EOS_MIN_TIMEOUT_LENGTH 50
62#define CMD_EOS_TIMEOUT_MULTIPLIER (HZ * 50)
63#define MAX_PB_COPY_RETRIES 3
64
65static struct snd_pcm_hardware msm_pcm_hardware_capture = {
66 .info = (SNDRV_PCM_INFO_MMAP |
67 SNDRV_PCM_INFO_BLOCK_TRANSFER |
68 SNDRV_PCM_INFO_MMAP_VALID |
69 SNDRV_PCM_INFO_INTERLEAVED |
70 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
71 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
72 SNDRV_PCM_FMTBIT_S24_LE |
73 SNDRV_PCM_FMTBIT_S24_3LE |
74 SNDRV_PCM_FMTBIT_S32_LE),
75 .rates = SNDRV_PCM_RATE_8000_384000,
76 .rate_min = 8000,
77 .rate_max = 384000,
78 .channels_min = 1,
Soumya Managoli760f1482019-05-14 16:41:53 +053079 .channels_max = 8,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053080 .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS *
81 CAPTURE_MAX_PERIOD_SIZE,
82 .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
83 .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
84 .periods_min = CAPTURE_MIN_NUM_PERIODS,
85 .periods_max = CAPTURE_MAX_NUM_PERIODS,
86 .fifo_size = 0,
87};
88
89static struct snd_pcm_hardware msm_pcm_hardware_playback = {
90 .info = (SNDRV_PCM_INFO_MMAP |
91 SNDRV_PCM_INFO_BLOCK_TRANSFER |
92 SNDRV_PCM_INFO_MMAP_VALID |
93 SNDRV_PCM_INFO_INTERLEAVED |
94 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
95 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
96 SNDRV_PCM_FMTBIT_S24_LE |
97 SNDRV_PCM_FMTBIT_S24_3LE |
98 SNDRV_PCM_FMTBIT_S32_LE),
99 .rates = SNDRV_PCM_RATE_8000_384000,
100 .rate_min = 8000,
101 .rate_max = 384000,
102 .channels_min = 1,
103 .channels_max = 8,
104 .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS *
105 PLAYBACK_MAX_PERIOD_SIZE,
106 .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
107 .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
108 .periods_min = PLAYBACK_MIN_NUM_PERIODS,
109 .periods_max = PLAYBACK_MAX_NUM_PERIODS,
110 .fifo_size = 0,
111};
112
113/* Conventional and unconventional sample rate supported */
114static unsigned int supported_sample_rates[] = {
115 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
116 88200, 96000, 176400, 192000, 352800, 384000
117};
118
119static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
120 .count = ARRAY_SIZE(supported_sample_rates),
121 .list = supported_sample_rates,
122 .mask = 0,
123};
124
125static void msm_pcm_route_event_handler(enum msm_pcm_routing_event event,
126 void *priv_data)
127{
128 struct msm_audio *prtd = priv_data;
129
130 WARN_ON(!prtd);
131
132 pr_debug("%s: event %x\n", __func__, event);
133
134 switch (event) {
135 case MSM_PCM_RT_EVT_BUF_RECFG:
136 q6asm_cmd(prtd->audio_client, CMD_PAUSE);
137 q6asm_cmd(prtd->audio_client, CMD_FLUSH);
138 q6asm_run(prtd->audio_client, 0, 0, 0);
139 /* fallthrough */
140 default:
141 break;
142 }
143}
144
145static void event_handler(uint32_t opcode,
146 uint32_t token, uint32_t *payload, void *priv)
147{
148 struct msm_audio *prtd = priv;
149 struct snd_pcm_substream *substream = prtd->substream;
150 uint32_t *ptrmem = (uint32_t *)payload;
151 uint32_t idx = 0;
152 uint32_t size = 0;
153 uint8_t buf_index;
154 struct snd_soc_pcm_runtime *rtd;
155 int ret = 0;
156
157 switch (opcode) {
158 case ASM_DATA_EVENT_WRITE_DONE_V2: {
159 pr_debug("ASM_DATA_EVENT_WRITE_DONE_V2\n");
160 pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem);
161 prtd->pcm_irq_pos += prtd->pcm_count;
162 if (atomic_read(&prtd->start))
163 snd_pcm_period_elapsed(substream);
164 atomic_inc(&prtd->out_count);
165 wake_up(&the_locks.write_wait);
166 if (!atomic_read(&prtd->start))
167 break;
168 if (!prtd->mmap_flag || prtd->reset_event)
169 break;
170 if (q6asm_is_cpu_buf_avail_nolock(IN,
171 prtd->audio_client,
172 &size, &idx)) {
173 pr_debug("%s:writing %d bytes of buffer to dsp 2\n",
174 __func__, prtd->pcm_count);
175 q6asm_write_nolock(prtd->audio_client,
176 prtd->pcm_count, 0, 0, NO_TIMESTAMP);
177 }
178 break;
179 }
180 case ASM_DATA_EVENT_RENDERED_EOS:
181 pr_debug("ASM_DATA_EVENT_RENDERED_EOS\n");
182 clear_bit(CMD_EOS, &prtd->cmd_pending);
183 wake_up(&the_locks.eos_wait);
184 break;
185 case ASM_DATA_EVENT_READ_DONE_V2: {
186 pr_debug("ASM_DATA_EVENT_READ_DONE_V2\n");
187 buf_index = q6asm_get_buf_index_from_token(token);
Vignesh Kulothungan3817b182017-12-04 15:56:05 -0800188 if (buf_index >= CAPTURE_MAX_NUM_PERIODS) {
189 pr_err("%s: buffer index %u is out of range.\n",
190 __func__, buf_index);
191 return;
192 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530193 pr_debug("%s: token=0x%08x buf_index=0x%08x\n",
194 __func__, token, buf_index);
195 prtd->in_frame_info[buf_index].size = payload[4];
196 prtd->in_frame_info[buf_index].offset = payload[5];
197 /* assume data size = 0 during flushing */
198 if (prtd->in_frame_info[buf_index].size) {
199 prtd->pcm_irq_pos +=
200 prtd->in_frame_info[buf_index].size;
201 pr_debug("pcm_irq_pos=%d\n", prtd->pcm_irq_pos);
202 if (atomic_read(&prtd->start))
203 snd_pcm_period_elapsed(substream);
204 if (atomic_read(&prtd->in_count) <= prtd->periods)
205 atomic_inc(&prtd->in_count);
206 wake_up(&the_locks.read_wait);
207 if (prtd->mmap_flag &&
208 q6asm_is_cpu_buf_avail_nolock(OUT,
209 prtd->audio_client,
210 &size, &idx) &&
211 (substream->runtime->status->state ==
212 SNDRV_PCM_STATE_RUNNING))
213 q6asm_read_nolock(prtd->audio_client);
214 } else {
215 pr_debug("%s: reclaim flushed buf in_count %x\n",
216 __func__, atomic_read(&prtd->in_count));
217 prtd->pcm_irq_pos += prtd->pcm_count;
218 if (prtd->mmap_flag) {
219 if (q6asm_is_cpu_buf_avail_nolock(OUT,
220 prtd->audio_client,
221 &size, &idx) &&
222 (substream->runtime->status->state ==
223 SNDRV_PCM_STATE_RUNNING))
224 q6asm_read_nolock(prtd->audio_client);
225 } else {
226 atomic_inc(&prtd->in_count);
227 }
228 if (atomic_read(&prtd->in_count) == prtd->periods) {
229 pr_info("%s: reclaimed all bufs\n", __func__);
230 if (atomic_read(&prtd->start))
231 snd_pcm_period_elapsed(substream);
232 wake_up(&the_locks.read_wait);
233 }
234 }
235 break;
236 }
237 case ASM_STREAM_PP_EVENT:
238 case ASM_STREAM_CMD_ENCDEC_EVENTS: {
239 pr_debug("%s: ASM_STREAM_EVENT (0x%x)\n", __func__, opcode);
240 if (!substream) {
241 pr_err("%s: substream is NULL.\n", __func__);
242 return;
243 }
244
245 rtd = substream->private_data;
246 if (!rtd) {
247 pr_err("%s: rtd is NULL\n", __func__);
248 return;
249 }
250
251 ret = msm_adsp_inform_mixer_ctl(rtd, payload);
252 if (ret) {
253 pr_err("%s: failed to inform mixer ctl. err = %d\n",
254 __func__, ret);
255 return;
256 }
257
258 break;
259 }
260 case APR_BASIC_RSP_RESULT: {
261 switch (payload[0]) {
262 case ASM_SESSION_CMD_RUN_V2:
263 if (substream->stream
264 != SNDRV_PCM_STREAM_PLAYBACK) {
265 atomic_set(&prtd->start, 1);
266 break;
267 }
268 if (prtd->mmap_flag) {
269 pr_debug("%s:writing %d bytes of buffer to dsp\n",
270 __func__,
271 prtd->pcm_count);
272 q6asm_write_nolock(prtd->audio_client,
273 prtd->pcm_count,
274 0, 0, NO_TIMESTAMP);
275 } else {
276 while (atomic_read(&prtd->out_needed)) {
277 pr_debug("%s:writing %d bytes of buffer to dsp\n",
278 __func__,
279 prtd->pcm_count);
280 q6asm_write_nolock(prtd->audio_client,
281 prtd->pcm_count,
282 0, 0, NO_TIMESTAMP);
283 atomic_dec(&prtd->out_needed);
284 wake_up(&the_locks.write_wait);
285 };
286 }
287 atomic_set(&prtd->start, 1);
288 break;
289 case ASM_STREAM_CMD_REGISTER_PP_EVENTS:
290 pr_debug("%s: ASM_STREAM_CMD_REGISTER_PP_EVENTS:",
291 __func__);
292 break;
293 default:
294 pr_debug("%s:Payload = [0x%x]stat[0x%x]\n",
295 __func__, payload[0], payload[1]);
296 break;
297 }
298 }
299 break;
300 case RESET_EVENTS:
301 pr_debug("%s RESET_EVENTS\n", __func__);
302 prtd->pcm_irq_pos += prtd->pcm_count;
303 atomic_inc(&prtd->out_count);
304 atomic_inc(&prtd->in_count);
305 prtd->reset_event = true;
306 if (atomic_read(&prtd->start))
307 snd_pcm_period_elapsed(substream);
308 wake_up(&the_locks.eos_wait);
309 wake_up(&the_locks.write_wait);
310 wake_up(&the_locks.read_wait);
311 break;
312 default:
313 pr_debug("Not Supported Event opcode[0x%x]\n", opcode);
314 break;
315 }
316}
317
318static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
319{
320 struct snd_pcm_runtime *runtime = substream->runtime;
321 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
322 struct msm_audio *prtd = runtime->private_data;
323 struct msm_plat_data *pdata;
324 struct snd_pcm_hw_params *params;
325 int ret;
326 uint32_t fmt_type = FORMAT_LINEAR_PCM;
327 uint16_t bits_per_sample;
328 uint16_t sample_word_size;
329
330 pdata = (struct msm_plat_data *)
331 dev_get_drvdata(soc_prtd->platform->dev);
332 if (!pdata) {
333 pr_err("%s: platform data not populated\n", __func__);
334 return -EINVAL;
335 }
336 if (!prtd || !prtd->audio_client) {
337 pr_err("%s: private data null or audio client freed\n",
338 __func__);
339 return -EINVAL;
340 }
341 params = &soc_prtd->dpcm[substream->stream].hw_params;
342
343 pr_debug("%s\n", __func__);
344 prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
345 prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
346 prtd->pcm_irq_pos = 0;
347 /* rate and channels are sent to audio driver */
348 prtd->samp_rate = runtime->rate;
349 prtd->channel_mode = runtime->channels;
350 if (prtd->enabled)
351 return 0;
352
353 prtd->audio_client->perf_mode = pdata->perf_mode;
354 pr_debug("%s: perf: %x\n", __func__, pdata->perf_mode);
355
356 switch (params_format(params)) {
357 case SNDRV_PCM_FORMAT_S32_LE:
358 bits_per_sample = 32;
359 sample_word_size = 32;
360 break;
361 case SNDRV_PCM_FORMAT_S24_LE:
362 bits_per_sample = 24;
363 sample_word_size = 32;
364 break;
365 case SNDRV_PCM_FORMAT_S24_3LE:
366 bits_per_sample = 24;
367 sample_word_size = 24;
368 break;
369 case SNDRV_PCM_FORMAT_S16_LE:
370 default:
371 bits_per_sample = 16;
372 sample_word_size = 16;
373 break;
374 }
375 if (prtd->compress_enable) {
376 fmt_type = FORMAT_GEN_COMPR;
377 pr_debug("%s: Compressed enabled!\n", __func__);
378 ret = q6asm_open_write_compressed(prtd->audio_client, fmt_type,
379 COMPRESSED_PASSTHROUGH_GEN);
380 if (ret < 0) {
381 pr_err("%s: q6asm_open_write_compressed failed (%d)\n",
382 __func__, ret);
383 q6asm_audio_client_free(prtd->audio_client);
384 prtd->audio_client = NULL;
385 return -ENOMEM;
386 }
387 } else {
388 ret = q6asm_open_write_v4(prtd->audio_client,
389 fmt_type, bits_per_sample);
390
391 if (ret < 0) {
392 pr_err("%s: q6asm_open_write_v4 failed (%d)\n",
393 __func__, ret);
394 q6asm_audio_client_free(prtd->audio_client);
395 prtd->audio_client = NULL;
396 return -ENOMEM;
397 }
398
399 ret = q6asm_send_cal(prtd->audio_client);
400 if (ret < 0)
401 pr_debug("%s : Send cal failed : %d", __func__, ret);
402 }
403 pr_debug("%s: session ID %d\n", __func__,
404 prtd->audio_client->session);
405 prtd->session_id = prtd->audio_client->session;
406
407 if (prtd->compress_enable) {
408 ret = msm_pcm_routing_reg_phy_compr_stream(
409 soc_prtd->dai_link->id,
410 prtd->audio_client->perf_mode,
411 prtd->session_id,
412 SNDRV_PCM_STREAM_PLAYBACK,
413 COMPRESSED_PASSTHROUGH_GEN);
414 } else {
415 ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->id,
416 prtd->audio_client->perf_mode,
417 prtd->session_id, substream->stream);
418 }
419 if (ret) {
420 pr_err("%s: stream reg failed ret:%d\n", __func__, ret);
421 return ret;
422 }
423 if (prtd->compress_enable) {
424 ret = q6asm_media_format_block_gen_compr(
425 prtd->audio_client, runtime->rate,
426 runtime->channels, !prtd->set_channel_map,
427 prtd->channel_map, bits_per_sample);
428 } else {
429 ret = q6asm_media_format_block_multi_ch_pcm_v4(
430 prtd->audio_client, runtime->rate,
431 runtime->channels, !prtd->set_channel_map,
432 prtd->channel_map, bits_per_sample,
433 sample_word_size, ASM_LITTLE_ENDIAN,
434 DEFAULT_QF);
435 }
436 if (ret < 0)
437 pr_info("%s: CMD Format block failed\n", __func__);
438
439 atomic_set(&prtd->out_count, runtime->periods);
440
441 prtd->enabled = 1;
442 prtd->cmd_pending = 0;
443 prtd->cmd_interrupt = 0;
444
445 return 0;
446}
447
448static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
449{
450 struct snd_pcm_runtime *runtime = substream->runtime;
451 struct msm_audio *prtd = runtime->private_data;
452 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
453 struct msm_plat_data *pdata;
454 struct snd_pcm_hw_params *params;
455 struct msm_pcm_routing_evt event;
456 int ret = 0;
457 int i = 0;
458 uint16_t bits_per_sample = 16;
459 uint16_t sample_word_size;
460
461 pdata = (struct msm_plat_data *)
462 dev_get_drvdata(soc_prtd->platform->dev);
463 if (!pdata) {
464 pr_err("%s: platform data not populated\n", __func__);
465 return -EINVAL;
466 }
467 if (!prtd || !prtd->audio_client) {
468 pr_err("%s: private data null or audio client freed\n",
469 __func__);
470 return -EINVAL;
471 }
472
473 if (prtd->enabled == IDLE) {
474 pr_debug("%s:perf_mode=%d periods=%d\n", __func__,
475 pdata->perf_mode, runtime->periods);
476 params = &soc_prtd->dpcm[substream->stream].hw_params;
477 if ((params_format(params) == SNDRV_PCM_FORMAT_S24_LE) ||
478 (params_format(params) == SNDRV_PCM_FORMAT_S24_3LE))
479 bits_per_sample = 24;
480 else if (params_format(params) == SNDRV_PCM_FORMAT_S32_LE)
481 bits_per_sample = 32;
482
483 /* ULL mode is not supported in capture path */
484 if (pdata->perf_mode == LEGACY_PCM_MODE)
485 prtd->audio_client->perf_mode = LEGACY_PCM_MODE;
486 else
487 prtd->audio_client->perf_mode = LOW_LATENCY_PCM_MODE;
488
489 pr_debug("%s Opening %d-ch PCM read stream, perf_mode %d\n",
490 __func__, params_channels(params),
491 prtd->audio_client->perf_mode);
492
493 ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM,
494 bits_per_sample, false);
495 if (ret < 0) {
496 pr_err("%s: q6asm_open_read failed\n", __func__);
497 q6asm_audio_client_free(prtd->audio_client);
498 prtd->audio_client = NULL;
499 return -ENOMEM;
500 }
501
502 ret = q6asm_send_cal(prtd->audio_client);
503 if (ret < 0)
504 pr_debug("%s : Send cal failed : %d", __func__, ret);
505
506 pr_debug("%s: session ID %d\n",
507 __func__, prtd->audio_client->session);
508 prtd->session_id = prtd->audio_client->session;
509 event.event_func = msm_pcm_route_event_handler;
510 event.priv_data = (void *) prtd;
511 ret = msm_pcm_routing_reg_phy_stream_v2(
512 soc_prtd->dai_link->id,
513 prtd->audio_client->perf_mode,
514 prtd->session_id, substream->stream,
515 event);
516 if (ret) {
517 pr_err("%s: stream reg failed ret:%d\n", __func__, ret);
518 return ret;
519 }
520 }
521
522 prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
523 prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
524 prtd->pcm_irq_pos = 0;
525 /* rate and channels are sent to audio driver */
526 prtd->samp_rate = runtime->rate;
527 prtd->channel_mode = runtime->channels;
528
529 if (prtd->enabled == IDLE || prtd->enabled == STOPPED) {
530 for (i = 0; i < runtime->periods; i++)
531 q6asm_read(prtd->audio_client);
532 prtd->periods = runtime->periods;
533 }
534
535 if (prtd->enabled != IDLE)
536 return 0;
537
538 switch (runtime->format) {
539 case SNDRV_PCM_FORMAT_S32_LE:
540 bits_per_sample = 32;
541 sample_word_size = 32;
542 break;
543 case SNDRV_PCM_FORMAT_S24_LE:
544 bits_per_sample = 24;
545 sample_word_size = 32;
546 break;
547 case SNDRV_PCM_FORMAT_S24_3LE:
548 bits_per_sample = 24;
549 sample_word_size = 24;
550 break;
551 case SNDRV_PCM_FORMAT_S16_LE:
552 default:
553 bits_per_sample = 16;
554 sample_word_size = 16;
555 break;
556 }
557
558 pr_debug("%s: Samp_rate = %d Channel = %d bit width = %d, word size = %d\n",
559 __func__, prtd->samp_rate, prtd->channel_mode,
560 bits_per_sample, sample_word_size);
561 ret = q6asm_enc_cfg_blk_pcm_format_support_v4(prtd->audio_client,
562 prtd->samp_rate,
563 prtd->channel_mode,
564 bits_per_sample,
565 sample_word_size,
566 ASM_LITTLE_ENDIAN,
567 DEFAULT_QF);
568 if (ret < 0)
569 pr_debug("%s: cmd cfg pcm was block failed", __func__);
570
571 prtd->enabled = RUNNING;
572
573 return ret;
574}
575
576static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
577{
578 int ret = 0;
579 struct snd_pcm_runtime *runtime = substream->runtime;
580 struct msm_audio *prtd = runtime->private_data;
581
582 switch (cmd) {
583 case SNDRV_PCM_TRIGGER_START:
584 case SNDRV_PCM_TRIGGER_RESUME:
585 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
586 pr_debug("%s: Trigger start\n", __func__);
587 ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
588 break;
589 case SNDRV_PCM_TRIGGER_STOP:
590 pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
591 atomic_set(&prtd->start, 0);
592 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) {
593 prtd->enabled = STOPPED;
594 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
Sidipotu Ashok5c6855b2019-01-08 15:58:37 +0530595 if (!ret)
596 ret = q6asm_cmd_nowait(prtd->audio_client,
597 CMD_FLUSH);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530598 break;
599 }
600 /* pending CMD_EOS isn't expected */
601 WARN_ON_ONCE(test_bit(CMD_EOS, &prtd->cmd_pending));
602 set_bit(CMD_EOS, &prtd->cmd_pending);
603 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
604 if (ret)
605 clear_bit(CMD_EOS, &prtd->cmd_pending);
606 break;
607 case SNDRV_PCM_TRIGGER_SUSPEND:
608 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
609 pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n");
610 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
611 atomic_set(&prtd->start, 0);
612 break;
613 default:
614 ret = -EINVAL;
615 break;
616 }
617
618 return ret;
619}
620
621static int msm_pcm_open(struct snd_pcm_substream *substream)
622{
623 struct snd_pcm_runtime *runtime = substream->runtime;
624 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
625 struct msm_audio *prtd;
Banajit Goswami616e68c2017-10-27 01:31:19 -0700626 struct msm_plat_data *pdata;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530627 int ret = 0;
628
Banajit Goswami616e68c2017-10-27 01:31:19 -0700629 pdata = (struct msm_plat_data *)
630 dev_get_drvdata(soc_prtd->platform->dev);
631 if (!pdata) {
632 pr_err("%s: platform data not populated\n", __func__);
633 return -EINVAL;
634 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530635 prtd = kzalloc(sizeof(struct msm_audio), GFP_KERNEL);
636 if (prtd == NULL)
637 return -ENOMEM;
638
639 prtd->substream = substream;
640 prtd->audio_client = q6asm_audio_client_alloc(
641 (app_cb)event_handler, prtd);
642 if (!prtd->audio_client) {
643 pr_info("%s: Could not allocate memory\n", __func__);
644 kfree(prtd);
Vatsal Bucha321a7442018-06-01 12:05:25 +0530645 prtd = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530646 return -ENOMEM;
647 }
648
649 prtd->audio_client->dev = soc_prtd->platform->dev;
650
651 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
652 runtime->hw = msm_pcm_hardware_playback;
653
654 /* Capture path */
655 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
656 runtime->hw = msm_pcm_hardware_capture;
657 else {
658 pr_err("Invalid Stream type %d\n", substream->stream);
659 return -EINVAL;
660 }
661
662 ret = snd_pcm_hw_constraint_list(runtime, 0,
663 SNDRV_PCM_HW_PARAM_RATE,
664 &constraints_sample_rates);
665 if (ret < 0)
666 pr_info("snd_pcm_hw_constraint_list failed\n");
667 /* Ensure that buffer size is a multiple of period size */
668 ret = snd_pcm_hw_constraint_integer(runtime,
669 SNDRV_PCM_HW_PARAM_PERIODS);
670 if (ret < 0)
671 pr_info("snd_pcm_hw_constraint_integer failed\n");
672
673 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
674 ret = snd_pcm_hw_constraint_minmax(runtime,
675 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
676 PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE,
677 PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE);
678 if (ret < 0) {
679 pr_err("constraint for buffer bytes min max ret = %d\n",
680 ret);
681 }
682 }
683
684 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
685 ret = snd_pcm_hw_constraint_minmax(runtime,
686 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
687 CAPTURE_MIN_NUM_PERIODS * CAPTURE_MIN_PERIOD_SIZE,
688 CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE);
689 if (ret < 0) {
690 pr_err("constraint for buffer bytes min max ret = %d\n",
691 ret);
692 }
693 }
694 ret = snd_pcm_hw_constraint_step(runtime, 0,
695 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
696 if (ret < 0) {
697 pr_err("constraint for period bytes step ret = %d\n",
698 ret);
699 }
700 ret = snd_pcm_hw_constraint_step(runtime, 0,
701 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
702 if (ret < 0) {
703 pr_err("constraint for buffer bytes step ret = %d\n",
704 ret);
705 }
706
707 prtd->enabled = IDLE;
708 prtd->dsp_cnt = 0;
709 prtd->set_channel_map = false;
710 prtd->reset_event = false;
711 runtime->private_data = prtd;
712 msm_adsp_init_mixer_ctl_pp_event_queue(soc_prtd);
Banajit Goswami616e68c2017-10-27 01:31:19 -0700713 /* Vote to update the Rx thread priority to RT Thread for playback */
714 if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
715 (pdata->perf_mode == LOW_LATENCY_PCM_MODE))
716 apr_start_rx_rt(prtd->audio_client->apr);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530717
718 return 0;
719}
720
721static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
722 snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
723{
724 int ret = 0;
725 int fbytes = 0;
726 int xfer = 0;
727 char *bufptr = NULL;
728 void *data = NULL;
729 uint32_t idx = 0;
730 uint32_t size = 0;
731 uint32_t retries = 0;
732
733 struct snd_pcm_runtime *runtime = substream->runtime;
734 struct msm_audio *prtd = runtime->private_data;
735
736 fbytes = frames_to_bytes(runtime, frames);
737 pr_debug("%s: prtd->out_count = %d\n",
738 __func__, atomic_read(&prtd->out_count));
739
740 while ((fbytes > 0) && (retries < MAX_PB_COPY_RETRIES)) {
741 if (prtd->reset_event) {
742 pr_err("%s: In SSR return ENETRESET before wait\n",
743 __func__);
744 return -ENETRESET;
745 }
746
747 ret = wait_event_timeout(the_locks.write_wait,
748 (atomic_read(&prtd->out_count)), 5 * HZ);
749 if (!ret) {
750 pr_err("%s: wait_event_timeout failed\n", __func__);
751 ret = -ETIMEDOUT;
752 goto fail;
753 }
754 ret = 0;
755
756 if (prtd->reset_event) {
757 pr_err("%s: In SSR return ENETRESET after wait\n",
758 __func__);
759 return -ENETRESET;
760 }
761
762 if (!atomic_read(&prtd->out_count)) {
763 pr_err("%s: pcm stopped out_count 0\n", __func__);
764 return 0;
765 }
766
767 data = q6asm_is_cpu_buf_avail(IN, prtd->audio_client, &size,
768 &idx);
769 if (data == NULL) {
770 retries++;
771 continue;
772 } else {
773 retries = 0;
774 }
775
776 if (fbytes > size)
777 xfer = size;
778 else
779 xfer = fbytes;
780
781 bufptr = data;
782 if (bufptr) {
783 pr_debug("%s:fbytes =%d: xfer=%d size=%d\n",
784 __func__, fbytes, xfer, size);
785 if (copy_from_user(bufptr, buf, xfer)) {
786 ret = -EFAULT;
787 pr_err("%s: copy_from_user failed\n",
788 __func__);
789 q6asm_cpu_buf_release(IN, prtd->audio_client);
790 goto fail;
791 }
792 buf += xfer;
793 fbytes -= xfer;
794 pr_debug("%s:fbytes = %d: xfer=%d\n", __func__, fbytes,
795 xfer);
796 if (atomic_read(&prtd->start)) {
797 pr_debug("%s:writing %d bytes of buffer to dsp\n",
798 __func__, xfer);
799 ret = q6asm_write(prtd->audio_client, xfer,
800 0, 0, NO_TIMESTAMP);
801 if (ret < 0) {
802 ret = -EFAULT;
803 q6asm_cpu_buf_release(IN,
804 prtd->audio_client);
805 goto fail;
806 }
807 } else
808 atomic_inc(&prtd->out_needed);
809 atomic_dec(&prtd->out_count);
810 }
811 }
812fail:
813 if (retries >= MAX_PB_COPY_RETRIES)
814 ret = -ENOMEM;
815
816 return ret;
817}
818
819static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
820{
821 struct snd_pcm_runtime *runtime = substream->runtime;
822 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
823 struct msm_audio *prtd = runtime->private_data;
Banajit Goswami616e68c2017-10-27 01:31:19 -0700824 struct msm_plat_data *pdata;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530825 uint32_t timeout;
826 int dir = 0;
827 int ret = 0;
828
829 pr_debug("%s: cmd_pending 0x%lx\n", __func__, prtd->cmd_pending);
830
Ajit Pandey3d7b9a22019-09-05 16:26:01 +0530831 pdata = (struct msm_plat_data *)
832 dev_get_drvdata(soc_prtd->platform->dev);
833 if (!pdata) {
834 pr_err("%s: platform data is NULL\n", __func__);
835 return -EINVAL;
836 }
837
838 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530839 if (prtd->audio_client) {
840 dir = IN;
841
Banajit Goswami616e68c2017-10-27 01:31:19 -0700842 /*
843 * Unvote to downgrade the Rx thread priority from
844 * RT Thread for Low-Latency use case.
845 */
846 pdata = (struct msm_plat_data *)
847 dev_get_drvdata(soc_prtd->platform->dev);
848 if (pdata) {
849 if (pdata->perf_mode == LOW_LATENCY_PCM_MODE)
850 apr_end_rx_rt(prtd->audio_client->apr);
851 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530852 /* determine timeout length */
853 if (runtime->frame_bits == 0 || runtime->rate == 0) {
854 timeout = CMD_EOS_MIN_TIMEOUT_LENGTH;
855 } else {
856 timeout = (runtime->period_size *
857 CMD_EOS_TIMEOUT_MULTIPLIER) /
858 ((runtime->frame_bits / 8) *
859 runtime->rate);
860 if (timeout < CMD_EOS_MIN_TIMEOUT_LENGTH)
861 timeout = CMD_EOS_MIN_TIMEOUT_LENGTH;
862 }
863 pr_debug("%s: CMD_EOS timeout is %d\n", __func__, timeout);
864
865 ret = wait_event_timeout(the_locks.eos_wait,
866 !test_bit(CMD_EOS, &prtd->cmd_pending),
867 timeout);
868 if (!ret)
869 pr_err("%s: CMD_EOS failed, cmd_pending 0x%lx\n",
870 __func__, prtd->cmd_pending);
871 q6asm_cmd(prtd->audio_client, CMD_CLOSE);
872 q6asm_audio_client_buf_free_contiguous(dir,
873 prtd->audio_client);
874 q6asm_audio_client_free(prtd->audio_client);
875 }
876 msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
877 SNDRV_PCM_STREAM_PLAYBACK);
878 msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
879 kfree(prtd);
880 runtime->private_data = NULL;
Ajit Pandey3d7b9a22019-09-05 16:26:01 +0530881 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530882
883 return 0;
884}
885
886static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
887 int channel, snd_pcm_uframes_t hwoff, void __user *buf,
888 snd_pcm_uframes_t frames)
889{
890 int ret = 0;
891 int fbytes = 0;
892 int xfer;
893 char *bufptr;
894 void *data = NULL;
Vignesh Kulothungan60630ed2019-05-22 11:53:08 -0700895 uint32_t idx = 0;
896 uint32_t size = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530897 uint32_t offset = 0;
898 struct snd_pcm_runtime *runtime = substream->runtime;
899 struct msm_audio *prtd = substream->runtime->private_data;
900
901
902 pr_debug("%s\n", __func__);
903 fbytes = frames_to_bytes(runtime, frames);
904
905 pr_debug("appl_ptr %d\n", (int)runtime->control->appl_ptr);
906 pr_debug("hw_ptr %d\n", (int)runtime->status->hw_ptr);
907 pr_debug("avail_min %d\n", (int)runtime->control->avail_min);
908
909 if (prtd->reset_event) {
910 pr_err("%s: In SSR return ENETRESET before wait\n", __func__);
911 return -ENETRESET;
912 }
913 ret = wait_event_timeout(the_locks.read_wait,
914 (atomic_read(&prtd->in_count)), 5 * HZ);
915 if (!ret) {
916 pr_debug("%s: wait_event_timeout failed\n", __func__);
917 goto fail;
918 }
919 if (prtd->reset_event) {
920 pr_err("%s: In SSR return ENETRESET after wait\n", __func__);
921 return -ENETRESET;
922 }
923 if (!atomic_read(&prtd->in_count)) {
924 pr_debug("%s: pcm stopped in_count 0\n", __func__);
925 return 0;
926 }
927 pr_debug("Checking if valid buffer is available...%pK\n",
928 data);
929 data = q6asm_is_cpu_buf_avail(OUT, prtd->audio_client, &size, &idx);
930 bufptr = data;
931 pr_debug("Size = %d\n", size);
932 pr_debug("fbytes = %d\n", fbytes);
933 pr_debug("idx = %d\n", idx);
934 if (bufptr) {
935 xfer = fbytes;
936 if (xfer > size)
937 xfer = size;
938 offset = prtd->in_frame_info[idx].offset;
939 pr_debug("Offset value = %d\n", offset);
940 if (copy_to_user(buf, bufptr+offset, xfer)) {
941 pr_err("Failed to copy buf to user\n");
942 ret = -EFAULT;
943 q6asm_cpu_buf_release(OUT, prtd->audio_client);
944 goto fail;
945 }
946 fbytes -= xfer;
947 size -= xfer;
948 prtd->in_frame_info[idx].offset += xfer;
949 pr_debug("%s:fbytes = %d: size=%d: xfer=%d\n",
950 __func__, fbytes, size, xfer);
951 pr_debug(" Sending next buffer to dsp\n");
952 memset(&prtd->in_frame_info[idx], 0,
953 sizeof(struct msm_audio_in_frame_info));
954 atomic_dec(&prtd->in_count);
955 ret = q6asm_read(prtd->audio_client);
956 if (ret < 0) {
957 pr_err("q6asm read failed\n");
958 ret = -EFAULT;
959 q6asm_cpu_buf_release(OUT, prtd->audio_client);
960 goto fail;
961 }
962 } else
963 pr_err("No valid buffer\n");
964
965 pr_debug("Returning from capture_copy... %d\n", ret);
966fail:
967 return ret;
968}
969
970static int msm_pcm_capture_close(struct snd_pcm_substream *substream)
971{
972 struct snd_pcm_runtime *runtime = substream->runtime;
973 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
974 struct msm_audio *prtd = runtime->private_data;
975 int dir = OUT;
Ajit Pandey3d7b9a22019-09-05 16:26:01 +0530976 struct msm_plat_data *pdata;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530977
978 pr_debug("%s\n", __func__);
Ajit Pandey3d7b9a22019-09-05 16:26:01 +0530979
980 pdata = (struct msm_plat_data *)
981 dev_get_drvdata(soc_prtd->platform->dev);
982 if (!pdata) {
983 pr_err("%s: platform data is NULL\n", __func__);
984 return -EINVAL;
985 }
986
987 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530988 if (prtd->audio_client) {
989 q6asm_cmd(prtd->audio_client, CMD_CLOSE);
990 q6asm_audio_client_buf_free_contiguous(dir,
991 prtd->audio_client);
992 q6asm_audio_client_free(prtd->audio_client);
993 }
994
995 msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
996 SNDRV_PCM_STREAM_CAPTURE);
997 kfree(prtd);
998 runtime->private_data = NULL;
Ajit Pandey3d7b9a22019-09-05 16:26:01 +0530999 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301000
1001 return 0;
1002}
1003
1004static int msm_pcm_copy(struct snd_pcm_substream *substream, int a,
1005 snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
1006{
1007 int ret = 0;
1008
1009 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1010 ret = msm_pcm_playback_copy(substream, a, hwoff, buf, frames);
1011 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
1012 ret = msm_pcm_capture_copy(substream, a, hwoff, buf, frames);
1013 return ret;
1014}
1015
1016static int msm_pcm_close(struct snd_pcm_substream *substream)
1017{
1018 int ret = 0;
1019
1020 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1021 ret = msm_pcm_playback_close(substream);
1022 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
1023 ret = msm_pcm_capture_close(substream);
1024 return ret;
1025}
1026
1027static int msm_pcm_prepare(struct snd_pcm_substream *substream)
1028{
1029 int ret = 0;
1030
1031 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1032 ret = msm_pcm_playback_prepare(substream);
1033 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
1034 ret = msm_pcm_capture_prepare(substream);
1035 return ret;
1036}
1037
1038static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream)
1039{
1040
1041 struct snd_pcm_runtime *runtime = substream->runtime;
1042 struct msm_audio *prtd = runtime->private_data;
1043
1044 if (prtd->pcm_irq_pos >= prtd->pcm_size)
1045 prtd->pcm_irq_pos = 0;
1046
1047 pr_debug("pcm_irq_pos = %d\n", prtd->pcm_irq_pos);
1048 return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
1049}
1050
1051static int msm_pcm_mmap(struct snd_pcm_substream *substream,
1052 struct vm_area_struct *vma)
1053{
1054 struct snd_pcm_runtime *runtime = substream->runtime;
1055 struct msm_audio *prtd = runtime->private_data;
1056 struct audio_client *ac = prtd->audio_client;
1057 struct audio_port_data *apd = ac->port;
1058 struct audio_buffer *ab;
1059 int dir = -1;
1060
1061 prtd->mmap_flag = 1;
1062
1063 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1064 dir = IN;
1065 else
1066 dir = OUT;
1067 ab = &(apd[dir].buf[0]);
1068
1069 return msm_audio_ion_mmap(ab, vma);
1070}
1071
1072static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
1073 struct snd_pcm_hw_params *params)
1074{
1075 struct snd_pcm_runtime *runtime = substream->runtime;
1076 struct msm_audio *prtd = runtime->private_data;
1077 struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
1078 struct audio_buffer *buf;
1079 int dir, ret;
1080
1081 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1082 dir = IN;
1083 else
1084 dir = OUT;
1085 ret = q6asm_audio_client_buf_alloc_contiguous(dir,
1086 prtd->audio_client,
1087 (params_buffer_bytes(params) / params_periods(params)),
1088 params_periods(params));
1089 if (ret < 0) {
1090 pr_err("Audio Start: Buffer Allocation failed rc = %d\n",
1091 ret);
1092 return -ENOMEM;
1093 }
1094 buf = prtd->audio_client->port[dir].buf;
1095 if (buf == NULL || buf[0].data == NULL)
1096 return -ENOMEM;
1097
1098 pr_debug("%s:buf = %pK\n", __func__, buf);
1099 dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
1100 dma_buf->dev.dev = substream->pcm->card->dev;
1101 dma_buf->private_data = NULL;
1102 dma_buf->area = buf[0].data;
1103 dma_buf->addr = buf[0].phys;
1104 dma_buf->bytes = params_buffer_bytes(params);
1105 if (!dma_buf->area)
1106 return -ENOMEM;
1107
1108 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
1109 return 0;
1110}
1111
1112static const struct snd_pcm_ops msm_pcm_ops = {
1113 .open = msm_pcm_open,
1114 .copy = msm_pcm_copy,
1115 .hw_params = msm_pcm_hw_params,
1116 .close = msm_pcm_close,
1117 .ioctl = snd_pcm_lib_ioctl,
1118 .prepare = msm_pcm_prepare,
1119 .trigger = msm_pcm_trigger,
1120 .pointer = msm_pcm_pointer,
1121 .mmap = msm_pcm_mmap,
1122};
1123
1124static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
1125 struct snd_ctl_elem_value *ucontrol)
1126{
1127 struct snd_soc_component *pcm = snd_kcontrol_chip(kcontrol);
1128 struct snd_soc_platform *platform = snd_soc_component_to_platform(pcm);
1129 struct msm_plat_data *pdata = dev_get_drvdata(platform->dev);
1130 struct snd_pcm_substream *substream;
1131 struct msm_audio *prtd;
1132 int ret = 0;
1133 struct msm_adsp_event_data *event_data = NULL;
Aditya Bavanari2e3341d2018-02-23 12:58:57 +05301134 uint64_t actual_payload_len = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301135
1136 if (!pdata) {
1137 pr_err("%s pdata is NULL\n", __func__);
Prasad Kumpatlaade35f02019-10-15 15:06:44 +05301138 return -ENODEV;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301139 }
1140
Prasad Kumpatlaade35f02019-10-15 15:06:44 +05301141 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301142 substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1143 if (!substream) {
1144 pr_err("%s substream not found\n", __func__);
1145 ret = -EINVAL;
1146 goto done;
1147 }
1148
1149 if (!substream->runtime) {
1150 pr_err("%s substream runtime not found\n", __func__);
1151 ret = -EINVAL;
1152 goto done;
1153 }
1154
1155 prtd = substream->runtime->private_data;
Vatsal Bucha321a7442018-06-01 12:05:25 +05301156 if (prtd == NULL) {
1157 pr_err("%s prtd is null.\n", __func__);
1158 ret = -EINVAL;
1159 goto done;
1160 }
1161
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301162 if (prtd->audio_client == NULL) {
1163 pr_err("%s prtd is null.\n", __func__);
1164 ret = -EINVAL;
1165 goto done;
1166 }
1167
1168 event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data;
1169 if ((event_data->event_type < ADSP_STREAM_PP_EVENT) ||
1170 (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) {
1171 pr_err("%s: invalid event_type=%d",
1172 __func__, event_data->event_type);
1173 ret = -EINVAL;
1174 goto done;
1175 }
1176
Aditya Bavanari2e3341d2018-02-23 12:58:57 +05301177 actual_payload_len = sizeof(struct msm_adsp_event_data) +
1178 event_data->payload_len;
1179 if (actual_payload_len >= U32_MAX) {
1180 pr_err("%s payload length 0x%X exceeds limit",
1181 __func__, event_data->payload_len);
1182 ret = -EINVAL;
1183 goto done;
1184 }
1185
Xiaojun Sangae3d8862018-03-23 08:57:33 +08001186 if (event_data->payload_len > sizeof(ucontrol->value.bytes.data)
1187 - sizeof(struct msm_adsp_event_data)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301188 pr_err("%s param length=%d exceeds limit",
1189 __func__, event_data->payload_len);
1190 ret = -EINVAL;
1191 goto done;
1192 }
1193
1194 ret = q6asm_send_stream_cmd(prtd->audio_client, event_data);
1195 if (ret < 0)
1196 pr_err("%s: failed to send stream event cmd, err = %d\n",
1197 __func__, ret);
1198done:
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301199 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301200 return ret;
1201}
1202
1203static int msm_pcm_add_audio_adsp_stream_cmd_control(
1204 struct snd_soc_pcm_runtime *rtd)
1205{
1206 const char *mixer_ctl_name = DSP_STREAM_CMD;
1207 const char *deviceNo = "NN";
1208 char *mixer_str = NULL;
1209 int ctl_len = 0, ret = 0;
1210 struct snd_kcontrol_new fe_audio_adsp_stream_cmd_config_control[1] = {
1211 {
1212 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1213 .name = "?",
1214 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1215 .info = msm_adsp_stream_cmd_info,
1216 .put = msm_pcm_adsp_stream_cmd_put,
1217 .private_value = 0,
1218 }
1219 };
1220
1221 if (!rtd) {
1222 pr_err("%s rtd is NULL\n", __func__);
1223 ret = -EINVAL;
1224 goto done;
1225 }
1226
1227 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
1228 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
1229 if (!mixer_str) {
1230 ret = -ENOMEM;
1231 goto done;
1232 }
1233
1234 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
1235 fe_audio_adsp_stream_cmd_config_control[0].name = mixer_str;
1236 fe_audio_adsp_stream_cmd_config_control[0].private_value =
1237 rtd->dai_link->id;
1238 pr_debug("Registering new mixer ctl %s\n", mixer_str);
1239 ret = snd_soc_add_platform_controls(rtd->platform,
1240 fe_audio_adsp_stream_cmd_config_control,
1241 ARRAY_SIZE(fe_audio_adsp_stream_cmd_config_control));
1242 if (ret < 0)
1243 pr_err("%s: failed add ctl %s. err = %d\n",
1244 __func__, mixer_str, ret);
1245
1246 kfree(mixer_str);
1247done:
1248 return ret;
1249}
1250
1251static int msm_pcm_add_audio_adsp_stream_callback_control(
1252 struct snd_soc_pcm_runtime *rtd)
1253{
1254 const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
1255 const char *deviceNo = "NN";
1256 char *mixer_str = NULL;
1257 int ctl_len = 0, ret = 0;
1258 struct snd_kcontrol *kctl;
1259
1260 struct snd_kcontrol_new fe_audio_adsp_callback_config_control[1] = {
1261 {
1262 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1263 .name = "?",
1264 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1265 .info = msm_adsp_stream_callback_info,
1266 .get = msm_adsp_stream_callback_get,
1267 .private_value = 0,
1268 }
1269 };
1270
1271 if (!rtd) {
1272 pr_err("%s NULL rtd\n", __func__);
1273 ret = -EINVAL;
1274 goto done;
1275 }
1276
1277 pr_debug("%s: added new pcm FE with name %s, id %d, cpu dai %s, device no %d\n",
1278 __func__, rtd->dai_link->name, rtd->dai_link->id,
1279 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
1280 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
1281 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
1282 if (!mixer_str) {
1283 ret = -ENOMEM;
1284 goto done;
1285 }
1286
1287 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
1288 fe_audio_adsp_callback_config_control[0].name = mixer_str;
1289 fe_audio_adsp_callback_config_control[0].private_value =
1290 rtd->dai_link->id;
1291 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
1292 ret = snd_soc_add_platform_controls(rtd->platform,
1293 fe_audio_adsp_callback_config_control,
1294 ARRAY_SIZE(fe_audio_adsp_callback_config_control));
1295 if (ret < 0) {
1296 pr_err("%s: failed to add ctl %s. err = %d\n",
1297 __func__, mixer_str, ret);
1298 ret = -EINVAL;
1299 goto free_mixer_str;
1300 }
1301
1302 kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
1303 if (!kctl) {
1304 pr_err("%s: failed to get kctl %s.\n", __func__, mixer_str);
1305 ret = -EINVAL;
1306 goto free_mixer_str;
1307 }
1308
1309 kctl->private_data = NULL;
1310
1311free_mixer_str:
1312 kfree(mixer_str);
1313done:
1314 return ret;
1315}
1316
1317static int msm_pcm_set_volume(struct msm_audio *prtd, uint32_t volume)
1318{
1319 int rc = 0;
1320
1321 if (prtd && prtd->audio_client) {
1322 pr_debug("%s: channels %d volume 0x%x\n", __func__,
1323 prtd->channel_mode, volume);
1324 rc = q6asm_set_volume(prtd->audio_client, volume);
1325 if (rc < 0) {
1326 pr_err("%s: Send Volume command failed rc=%d\n",
1327 __func__, rc);
1328 }
1329 }
1330 return rc;
1331}
1332
1333static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol,
1334 struct snd_ctl_elem_value *ucontrol)
1335{
1336 struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
Prasad Kumpatlaade35f02019-10-15 15:06:44 +05301337 struct msm_plat_data *pdata = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301338 struct snd_pcm_substream *substream =
Haynes Mathew Georged00e1062018-04-06 18:18:51 -07001339 vol->pcm->streams[vol->stream].substream;
Prasad Kumpatlaade35f02019-10-15 15:06:44 +05301340 struct snd_soc_pcm_runtime *soc_prtd = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301341 struct msm_audio *prtd;
1342
1343 pr_debug("%s\n", __func__);
1344 if (!substream) {
1345 pr_err("%s substream not found\n", __func__);
1346 return -ENODEV;
1347 }
Prasad Kumpatlaade35f02019-10-15 15:06:44 +05301348 soc_prtd = substream->private_data;
1349 if (!substream->runtime || !soc_prtd) {
1350 pr_debug("%s substream runtime or private_data not found\n",
1351 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301352 return 0;
1353 }
Prasad Kumpatlaade35f02019-10-15 15:06:44 +05301354
1355 pdata = (struct msm_plat_data *)
1356 dev_get_drvdata(soc_prtd->platform->dev);
1357 if (!pdata) {
1358 pr_err("%s: pdata not found\n", __func__);
1359 return -ENODEV;
1360 }
1361
1362 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301363 prtd = substream->runtime->private_data;
1364 if (prtd)
1365 ucontrol->value.integer.value[0] = prtd->volume;
Prasad Kumpatlaade35f02019-10-15 15:06:44 +05301366 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301367 return 0;
1368}
1369
1370static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol,
1371 struct snd_ctl_elem_value *ucontrol)
1372{
1373 int rc = 0;
1374 struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
1375 struct snd_pcm_substream *substream =
Haynes Mathew Georged00e1062018-04-06 18:18:51 -07001376 vol->pcm->streams[vol->stream].substream;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301377 struct msm_audio *prtd;
1378 int volume = ucontrol->value.integer.value[0];
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301379 struct msm_plat_data *pdata = NULL;
1380 struct snd_soc_pcm_runtime *soc_prtd = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301381
1382 pr_debug("%s: volume : 0x%x\n", __func__, volume);
1383 if (!substream) {
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301384 pr_err("%s: substream not found\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301385 return -ENODEV;
1386 }
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301387 soc_prtd = substream->private_data;
1388 if (!substream->runtime || !soc_prtd) {
1389 pr_err("%s: substream runtime or private_data not found\n",
1390 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301391 return 0;
1392 }
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301393
1394 pdata = (struct msm_plat_data *)
1395 dev_get_drvdata(soc_prtd->platform->dev);
1396 if (!pdata) {
1397 pr_err("%s: pdata not found\n", __func__);
1398 return -ENODEV;
1399 }
1400
1401 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301402 prtd = substream->runtime->private_data;
1403 if (prtd) {
1404 rc = msm_pcm_set_volume(prtd, volume);
1405 prtd->volume = volume;
1406 }
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301407 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301408 return rc;
1409}
1410
Haynes Mathew Georged00e1062018-04-06 18:18:51 -07001411static int msm_pcm_add_volume_control(struct snd_soc_pcm_runtime *rtd,
1412 int stream)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301413{
1414 int ret = 0;
1415 struct snd_pcm *pcm = rtd->pcm;
1416 struct snd_pcm_volume *volume_info;
1417 struct snd_kcontrol *kctl;
1418
Haynes Mathew Georged00e1062018-04-06 18:18:51 -07001419 dev_dbg(rtd->dev, "%s, volume control add\n", __func__);
1420 ret = snd_pcm_add_volume_ctls(pcm, stream,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301421 NULL, 1, rtd->dai_link->id,
1422 &volume_info);
1423 if (ret < 0) {
1424 pr_err("%s volume control failed ret %d\n", __func__, ret);
1425 return ret;
1426 }
1427 kctl = volume_info->kctl;
1428 kctl->put = msm_pcm_volume_ctl_put;
1429 kctl->get = msm_pcm_volume_ctl_get;
1430 kctl->tlv.p = msm_pcm_vol_gain;
1431 return 0;
1432}
1433
1434static int msm_pcm_compress_ctl_info(struct snd_kcontrol *kcontrol,
1435 struct snd_ctl_elem_info *uinfo)
1436{
1437 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1438 uinfo->count = 1;
1439 uinfo->value.integer.min = 0;
1440 uinfo->value.integer.max = 0x2000;
1441 return 0;
1442}
1443
1444static int msm_pcm_compress_ctl_get(struct snd_kcontrol *kcontrol,
1445 struct snd_ctl_elem_value *ucontrol)
1446{
1447 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
1448 struct snd_soc_platform *platform = snd_soc_component_to_platform(comp);
1449 struct msm_plat_data *pdata = dev_get_drvdata(platform->dev);
1450 struct snd_pcm_substream *substream;
1451 struct msm_audio *prtd;
1452
1453 if (!pdata) {
1454 pr_err("%s pdata is NULL\n", __func__);
1455 return -ENODEV;
1456 }
1457 substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1458 if (!substream) {
1459 pr_err("%s substream not found\n", __func__);
1460 return -EINVAL;
1461 }
1462 if (!substream->runtime) {
1463 pr_err("%s substream runtime not found\n", __func__);
1464 return 0;
1465 }
Prasad Kumpatlaade35f02019-10-15 15:06:44 +05301466 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301467 prtd = substream->runtime->private_data;
1468 if (prtd)
1469 ucontrol->value.integer.value[0] = prtd->compress_enable;
Prasad Kumpatlaade35f02019-10-15 15:06:44 +05301470 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301471 return 0;
1472}
1473
1474static int msm_pcm_compress_ctl_put(struct snd_kcontrol *kcontrol,
1475 struct snd_ctl_elem_value *ucontrol)
1476{
1477 int rc = 0;
1478 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
1479 struct snd_soc_platform *platform = snd_soc_component_to_platform(comp);
1480 struct msm_plat_data *pdata = dev_get_drvdata(platform->dev);
1481 struct snd_pcm_substream *substream;
1482 struct msm_audio *prtd;
1483 int compress = ucontrol->value.integer.value[0];
1484
1485 if (!pdata) {
1486 pr_err("%s pdata is NULL\n", __func__);
1487 return -ENODEV;
1488 }
1489 substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1490 pr_debug("%s: compress : 0x%x\n", __func__, compress);
1491 if (!substream) {
1492 pr_err("%s substream not found\n", __func__);
1493 return -EINVAL;
1494 }
1495 if (!substream->runtime) {
1496 pr_err("%s substream runtime not found\n", __func__);
1497 return 0;
1498 }
Prasad Kumpatlaade35f02019-10-15 15:06:44 +05301499 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301500 prtd = substream->runtime->private_data;
1501 if (prtd) {
1502 pr_debug("%s: setting compress flag to 0x%x\n",
1503 __func__, compress);
1504 prtd->compress_enable = compress;
1505 }
Prasad Kumpatlaade35f02019-10-15 15:06:44 +05301506 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301507 return rc;
1508}
1509
1510static int msm_pcm_add_compress_control(struct snd_soc_pcm_runtime *rtd)
1511{
1512 const char *mixer_ctl_name = "Playback ";
1513 const char *mixer_ctl_end_name = " Compress";
1514 const char *deviceNo = "NN";
1515 char *mixer_str = NULL;
1516 int ctl_len;
1517 int ret = 0;
1518 struct msm_plat_data *pdata;
1519 struct snd_kcontrol_new pcm_compress_control[1] = {
1520 {
1521 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1522 .name = "?",
1523 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1524 .info = msm_pcm_compress_ctl_info,
1525 .get = msm_pcm_compress_ctl_get,
1526 .put = msm_pcm_compress_ctl_put,
1527 .private_value = 0,
1528 }
1529 };
1530
1531 if (!rtd) {
1532 pr_err("%s: NULL rtd\n", __func__);
1533 return -EINVAL;
1534 }
1535
1536 ctl_len = strlen(mixer_ctl_name) + strlen(deviceNo) +
1537 strlen(mixer_ctl_end_name) + 1;
1538 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
1539
1540 if (!mixer_str)
1541 return -ENOMEM;
1542
1543 snprintf(mixer_str, ctl_len, "%s%d%s", mixer_ctl_name,
1544 rtd->pcm->device, mixer_ctl_end_name);
1545
1546 pcm_compress_control[0].name = mixer_str;
1547 pcm_compress_control[0].private_value = rtd->dai_link->id;
1548 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
1549 pdata = dev_get_drvdata(rtd->platform->dev);
1550 if (pdata) {
1551 if (!pdata->pcm) {
1552 pdata->pcm = rtd->pcm;
1553 snd_soc_add_platform_controls(rtd->platform,
1554 pcm_compress_control,
1555 ARRAY_SIZE
1556 (pcm_compress_control));
1557 pr_debug("%s: add control success plt = %pK\n",
1558 __func__, rtd->platform);
1559 }
1560 } else {
1561 pr_err("%s: NULL pdata\n", __func__);
1562 ret = -EINVAL;
1563 }
1564 kfree(mixer_str);
1565 return ret;
1566}
1567
1568static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
1569 struct snd_ctl_elem_value *ucontrol)
1570{
1571 int i;
1572 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
1573 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1574 struct snd_pcm_substream *substream;
1575 struct msm_audio *prtd;
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301576 struct snd_soc_pcm_runtime *rtd = NULL;
1577 struct msm_plat_data *pdata = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301578
1579 pr_debug("%s", __func__);
1580 substream = snd_pcm_chmap_substream(info, idx);
1581 if (!substream)
1582 return -ENODEV;
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301583
1584 rtd = substream->private_data;
1585 if (rtd) {
1586 pdata = (struct msm_plat_data *)
1587 dev_get_drvdata(rtd->platform->dev);
1588 if (!pdata) {
1589 pr_err("%s: pdata not found\n", __func__);
1590 return -ENODEV;
1591 }
1592 }
1593
1594 if (!substream->runtime || !rtd)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301595 return 0;
1596
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301597 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301598 prtd = substream->runtime->private_data;
1599 if (prtd) {
1600 prtd->set_channel_map = true;
1601 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
1602 prtd->channel_map[i] =
1603 (char)(ucontrol->value.integer.value[i]);
1604 }
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301605 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301606 return 0;
1607}
1608
1609static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
1610 struct snd_ctl_elem_value *ucontrol)
1611{
1612 int i;
1613 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
1614 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1615 struct snd_pcm_substream *substream;
1616 struct msm_audio *prtd;
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301617 struct snd_soc_pcm_runtime *rtd = NULL;
1618 struct msm_plat_data *pdata = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301619
1620 pr_debug("%s", __func__);
1621 substream = snd_pcm_chmap_substream(info, idx);
1622 if (!substream)
1623 return -ENODEV;
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301624
1625 rtd = substream->private_data;
1626 if (rtd) {
1627 pdata = (struct msm_plat_data *)
1628 dev_get_drvdata(rtd->platform->dev);
1629 if (!pdata) {
1630 pr_err("%s: pdata not found\n", __func__);
1631 return -ENODEV;
1632 }
1633 }
1634
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301635 memset(ucontrol->value.integer.value, 0,
1636 sizeof(ucontrol->value.integer.value));
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301637 if (!substream->runtime || !rtd)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301638 return 0; /* no channels set */
1639
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301640 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301641 prtd = substream->runtime->private_data;
1642
1643 if (prtd && prtd->set_channel_map == true) {
1644 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
1645 ucontrol->value.integer.value[i] =
1646 (int)prtd->channel_map[i];
1647 } else {
1648 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
1649 ucontrol->value.integer.value[i] = 0;
1650 }
1651
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05301652 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301653 return 0;
1654}
1655
1656static int msm_pcm_add_chmap_controls(struct snd_soc_pcm_runtime *rtd)
1657{
1658 struct snd_pcm *pcm = rtd->pcm;
1659 struct snd_pcm_chmap *chmap_info;
1660 struct snd_kcontrol *kctl;
1661 char device_num[12];
1662 int i, ret = 0;
1663
1664 pr_debug("%s, Channel map cntrl add\n", __func__);
1665 ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1666 snd_pcm_std_chmaps,
1667 PCM_FORMAT_MAX_NUM_CHANNEL, 0,
1668 &chmap_info);
1669 if (ret < 0) {
1670 pr_err("%s, channel map cntrl add failed\n", __func__);
1671 return ret;
1672 }
1673 kctl = chmap_info->kctl;
1674 for (i = 0; i < kctl->count; i++)
1675 kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
1676 snprintf(device_num, sizeof(device_num), "%d", pcm->device);
1677 strlcat(kctl->id.name, device_num, sizeof(kctl->id.name));
1678 pr_debug("%s, Overwriting channel map control name to: %s\n",
1679 __func__, kctl->id.name);
1680 kctl->put = msm_pcm_chmap_ctl_put;
1681 kctl->get = msm_pcm_chmap_ctl_get;
1682 return 0;
1683}
1684
1685static int msm_pcm_playback_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
1686 struct snd_ctl_elem_value *ucontrol)
1687{
1688 u64 fe_id = kcontrol->private_value;
1689 int session_type = SESSION_TYPE_RX;
1690 int be_id = ucontrol->value.integer.value[3];
1691 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
1692 int ret = 0;
1693
1694 cfg_data.app_type = ucontrol->value.integer.value[0];
1695 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
1696 if (ucontrol->value.integer.value[2] != 0)
1697 cfg_data.sample_rate = ucontrol->value.integer.value[2];
1698 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
1699 __func__, fe_id, session_type, be_id,
1700 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
1701 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
1702 be_id, &cfg_data);
1703 if (ret < 0)
1704 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
1705 __func__, ret);
1706
1707 return ret;
1708}
1709
1710static int msm_pcm_playback_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
1711 struct snd_ctl_elem_value *ucontrol)
1712{
1713 u64 fe_id = kcontrol->private_value;
1714 int session_type = SESSION_TYPE_RX;
1715 int be_id = 0;
1716 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
1717 int ret = 0;
1718
1719 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
1720 &be_id, &cfg_data);
1721 if (ret < 0) {
1722 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
1723 __func__, ret);
1724 goto done;
1725 }
1726
1727 ucontrol->value.integer.value[0] = cfg_data.app_type;
1728 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
1729 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
1730 ucontrol->value.integer.value[3] = be_id;
1731 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
1732 __func__, fe_id, session_type, be_id,
1733 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
1734done:
1735 return ret;
1736}
1737
1738static int msm_pcm_capture_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
1739 struct snd_ctl_elem_value *ucontrol)
1740{
1741 u64 fe_id = kcontrol->private_value;
1742 int session_type = SESSION_TYPE_TX;
1743 int be_id = ucontrol->value.integer.value[3];
1744 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
1745 int ret = 0;
1746
1747 cfg_data.app_type = ucontrol->value.integer.value[0];
1748 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
1749 if (ucontrol->value.integer.value[2] != 0)
1750 cfg_data.sample_rate = ucontrol->value.integer.value[2];
1751 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
1752 __func__, fe_id, session_type, be_id,
1753 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
1754 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
1755 be_id, &cfg_data);
1756 if (ret < 0)
1757 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
1758 __func__, ret);
1759
1760 return ret;
1761}
1762
1763static int msm_pcm_capture_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
1764 struct snd_ctl_elem_value *ucontrol)
1765{
1766 u64 fe_id = kcontrol->private_value;
1767 int session_type = SESSION_TYPE_TX;
1768 int be_id = 0;
1769 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
1770 int ret = 0;
1771
1772 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
1773 &be_id, &cfg_data);
1774 if (ret < 0) {
1775 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
1776 __func__, ret);
1777 goto done;
1778 }
1779
1780 ucontrol->value.integer.value[0] = cfg_data.app_type;
1781 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
1782 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
1783 ucontrol->value.integer.value[3] = be_id;
1784 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
1785 __func__, fe_id, session_type, be_id,
1786 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
1787done:
1788 return ret;
1789}
1790
1791static int msm_pcm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd)
1792{
1793 struct snd_pcm *pcm = rtd->pcm;
1794 struct snd_pcm_usr *app_type_info;
1795 struct snd_kcontrol *kctl;
1796 const char *playback_mixer_ctl_name = "Audio Stream";
1797 const char *capture_mixer_ctl_name = "Audio Stream Capture";
1798 const char *deviceNo = "NN";
1799 const char *suffix = "App Type Cfg";
1800 int ctl_len, ret = 0;
1801
1802 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
1803 ctl_len = strlen(playback_mixer_ctl_name) + 1 +
1804 strlen(deviceNo) + 1 + strlen(suffix) + 1;
1805 pr_debug("%s: Playback app type cntrl add\n", __func__);
1806 ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1807 NULL, 1, ctl_len, rtd->dai_link->id,
1808 &app_type_info);
1809 if (ret < 0) {
1810 pr_err("%s: playback app type cntrl add failed: %d\n",
1811 __func__, ret);
1812 return ret;
1813 }
1814 kctl = app_type_info->kctl;
1815 snprintf(kctl->id.name, ctl_len, "%s %d %s",
1816 playback_mixer_ctl_name, rtd->pcm->device, suffix);
1817 kctl->put = msm_pcm_playback_app_type_cfg_ctl_put;
1818 kctl->get = msm_pcm_playback_app_type_cfg_ctl_get;
1819 }
1820
1821 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
1822 ctl_len = strlen(capture_mixer_ctl_name) + 1 +
1823 strlen(deviceNo) + 1 + strlen(suffix) + 1;
1824 pr_debug("%s: Capture app type cntrl add\n", __func__);
1825 ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE,
1826 NULL, 1, ctl_len, rtd->dai_link->id,
1827 &app_type_info);
1828 if (ret < 0) {
1829 pr_err("%s: capture app type cntrl add failed: %d\n",
1830 __func__, ret);
1831 return ret;
1832 }
1833 kctl = app_type_info->kctl;
1834 snprintf(kctl->id.name, ctl_len, "%s %d %s",
1835 capture_mixer_ctl_name, rtd->pcm->device, suffix);
1836 kctl->put = msm_pcm_capture_app_type_cfg_ctl_put;
1837 kctl->get = msm_pcm_capture_app_type_cfg_ctl_get;
1838 }
1839
1840 return 0;
1841}
1842
Dhanalakshmi Siddani040e0262018-11-26 23:01:26 +05301843static int msm_pcm_chmix_cfg_ctl_info(struct snd_kcontrol *kcontrol,
1844 struct snd_ctl_elem_info *uinfo)
1845{
1846 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1847 uinfo->count = 128;
1848 uinfo->value.integer.min = 0;
1849 uinfo->value.integer.max = 0xFFFFFFFF;
1850 return 0;
1851}
1852
1853static int msm_pcm_chmix_cfg_ctl_put(struct snd_kcontrol *kcontrol,
1854 struct snd_ctl_elem_value *ucontrol)
1855{
1856 struct snd_soc_component *usr_info = snd_kcontrol_chip(kcontrol);
1857 struct snd_soc_platform *platform;
1858 struct msm_plat_data *pdata;
1859 struct snd_pcm_substream *substream;
1860 struct msm_audio *prtd;
1861 u64 fe_id = kcontrol->private_value;
1862 int ip_channel_cnt, op_channel_cnt;
1863 int i, index = 0, ret = 0;
1864 int ch_coeff[PCM_FORMAT_MAX_NUM_CHANNEL * PCM_FORMAT_MAX_NUM_CHANNEL];
1865 bool use_default_chmap = true;
1866 char *ch_map = NULL;
1867
1868 pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
1869 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
1870 pr_err("%s: Received out of bounds fe_id %llu\n",
1871 __func__, fe_id);
1872 ret = -EINVAL;
1873 goto done;
1874 }
1875
1876 if (!usr_info) {
1877 pr_err("%s: usr_info is null\n", __func__);
1878 ret = -EINVAL;
1879 goto done;
1880 }
1881 platform = snd_soc_component_to_platform(usr_info);
1882 if (!platform) {
1883 pr_err("%s: platform is null\n", __func__);
1884 ret = -EINVAL;
1885 goto done;
1886 }
1887 pdata = dev_get_drvdata(platform->dev);
1888 if (!pdata) {
1889 pr_err("%s: pdata is null\n", __func__);
1890 ret = -EINVAL;
1891 goto done;
1892 }
1893 substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1894
1895 if (!substream) {
1896 pr_err("%s substream not found\n", __func__);
1897 return -ENODEV;
1898 }
1899 if (!substream->runtime) {
1900 pr_err("%s substream runtime not found\n", __func__);
1901 ret = -EINVAL;
1902 goto done;
1903 }
1904 prtd = substream->runtime->private_data;
1905 if (!prtd) {
1906 pr_err("%s: stream inactive\n", __func__);
1907 ret = -EINVAL;
1908 goto done;
1909 }
1910 use_default_chmap = !prtd->set_channel_map;
1911 ch_map = prtd->channel_map;
1912 ip_channel_cnt = ucontrol->value.integer.value[index++];
1913 op_channel_cnt = ucontrol->value.integer.value[index++];
1914 /*
1915 * wght coeff of first out channel corresponding to each in channel
1916 * are sent followed by second out channel for each in channel etc.
1917 */
1918 memset(ch_coeff, 0, sizeof(ch_coeff));
1919 for (i = 0; i < op_channel_cnt * ip_channel_cnt; i++) {
1920 ch_coeff[i] =
1921 ucontrol->value.integer.value[index++];
1922 }
1923
1924 msm_pcm_routing_send_chmix_cfg(fe_id, ip_channel_cnt, op_channel_cnt,
1925 ch_coeff, SESSION_TYPE_RX, use_default_chmap, ch_map);
1926done:
1927 return ret;
1928}
1929
1930static int msm_pcm_chmix_cfg_ctl_get(struct snd_kcontrol *kcontrol,
1931 struct snd_ctl_elem_value *ucontrol)
1932{
1933 return 0;
1934}
1935
1936static int msm_pcm_add_chmix_cfg_controls(struct snd_soc_pcm_runtime *rtd)
1937{
1938 const char *mixer_ctl_name = "Audio Stream";
1939 const char *deviceNo = "NN";
1940 const char *suffix = "Channel Mix Cfg";
1941 char *mixer_str = NULL;
1942 int ctl_len = 0;
1943 struct msm_plat_data *pdata;
1944 struct snd_kcontrol_new chmix_cfg_controls[1] = {
1945 {
1946 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1947 .name = "?",
1948 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1949 .info = msm_pcm_chmix_cfg_ctl_info,
1950 .get = msm_pcm_chmix_cfg_ctl_get,
1951 .put = msm_pcm_chmix_cfg_ctl_put,
1952 .private_value = 0,
1953 }
1954 };
1955
1956 if (!rtd) {
1957 pr_err("%s: NULL rtd\n", __func__);
1958 return -EINVAL;
1959 }
1960
1961 ctl_len = strlen(mixer_ctl_name) + 1 +
1962 strlen(deviceNo) + 1 + strlen(suffix) + 1;
1963 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
1964 if (!mixer_str)
1965 return -ENOMEM;
1966
1967 snprintf(mixer_str, ctl_len, "%s %d %s",
1968 mixer_ctl_name, rtd->pcm->device, suffix);
1969 chmix_cfg_controls[0].name = mixer_str;
1970 chmix_cfg_controls[0].private_value = rtd->dai_link->id;
1971 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
1972 pdata = dev_get_drvdata(rtd->platform->dev);
1973 if (pdata) {
1974 if (!pdata->pcm)
1975 pdata->pcm = rtd->pcm;
1976 snd_soc_add_platform_controls(rtd->platform,
1977 chmix_cfg_controls,
1978 ARRAY_SIZE(chmix_cfg_controls));
1979 } else {
1980 pr_err("%s: NULL pdata\n", __func__);
1981 return -EINVAL;
1982 }
1983 kfree(mixer_str);
1984 return 0;
1985}
1986
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301987static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd)
1988{
1989 int ret = 0;
1990
1991 pr_debug("%s\n", __func__);
1992 ret = msm_pcm_add_chmap_controls(rtd);
1993 if (ret)
1994 pr_err("%s: pcm add controls failed:%d\n", __func__, ret);
1995 ret = msm_pcm_add_app_type_controls(rtd);
1996 if (ret)
1997 pr_err("%s: pcm add app type controls failed:%d\n",
1998 __func__, ret);
Dhanalakshmi Siddani040e0262018-11-26 23:01:26 +05301999 ret = msm_pcm_add_chmix_cfg_controls(rtd);
2000 if (ret)
2001 pr_err("%s: add chmix cfg controls failed:%d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302002 return ret;
2003}
2004
2005static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
2006{
2007 struct snd_card *card = rtd->card->snd_card;
2008 int ret = 0;
2009
2010 if (!card->dev->coherent_dma_mask)
2011 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
2012
2013 ret = msm_pcm_add_controls(rtd);
2014 if (ret) {
2015 pr_err("%s, kctl add failed:%d\n", __func__, ret);
2016 return ret;
2017 }
2018
Haynes Mathew Georged00e1062018-04-06 18:18:51 -07002019 ret = msm_pcm_add_volume_control(rtd, SNDRV_PCM_STREAM_PLAYBACK);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302020 if (ret)
2021 pr_err("%s: Could not add pcm Volume Control %d\n",
2022 __func__, ret);
Haynes Mathew Georged00e1062018-04-06 18:18:51 -07002023 ret = msm_pcm_add_volume_control(rtd, SNDRV_PCM_STREAM_CAPTURE);
2024 if (ret)
2025 pr_err("%s: Could not add pcm Volume Control %d\n",
2026 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302027 ret = msm_pcm_add_compress_control(rtd);
2028 if (ret)
2029 pr_err("%s: Could not add pcm Compress Control %d\n",
2030 __func__, ret);
2031
2032 ret = msm_pcm_add_audio_adsp_stream_cmd_control(rtd);
2033 if (ret)
2034 pr_err("%s: Could not add pcm ADSP Stream Cmd Control\n",
2035 __func__);
2036
2037 ret = msm_pcm_add_audio_adsp_stream_callback_control(rtd);
2038 if (ret)
2039 pr_err("%s: Could not add pcm ADSP Stream Callback Control\n",
2040 __func__);
2041
2042 return ret;
2043}
2044
2045static snd_pcm_sframes_t msm_pcm_delay_blk(struct snd_pcm_substream *substream,
2046 struct snd_soc_dai *dai)
2047{
2048 struct snd_pcm_runtime *runtime = substream->runtime;
2049 struct msm_audio *prtd = runtime->private_data;
2050 struct audio_client *ac = prtd->audio_client;
2051 snd_pcm_sframes_t frames;
2052 int ret;
2053
2054 ret = q6asm_get_path_delay(prtd->audio_client);
2055 if (ret) {
2056 pr_err("%s: get_path_delay failed, ret=%d\n", __func__, ret);
2057 return 0;
2058 }
2059
2060 /* convert microseconds to frames */
2061 frames = ac->path_delay / 1000 * runtime->rate / 1000;
2062
2063 /* also convert the remainder from the initial division */
2064 frames += ac->path_delay % 1000 * runtime->rate / 1000000;
2065
2066 /* overcompensate for the loss of precision (empirical) */
2067 frames += 2;
2068
2069 return frames;
2070}
2071
2072static struct snd_soc_platform_driver msm_soc_platform = {
2073 .ops = &msm_pcm_ops,
2074 .pcm_new = msm_asoc_pcm_new,
2075 .delay_blk = msm_pcm_delay_blk,
2076};
2077
2078static int msm_pcm_probe(struct platform_device *pdev)
2079{
2080 int rc;
2081 int id;
2082 struct msm_plat_data *pdata;
2083 const char *latency_level;
2084
2085 rc = of_property_read_u32(pdev->dev.of_node,
2086 "qcom,msm-pcm-dsp-id", &id);
2087 if (rc) {
2088 dev_err(&pdev->dev, "%s: qcom,msm-pcm-dsp-id missing in DT node\n",
2089 __func__);
2090 return rc;
2091 }
2092
2093 pdata = kzalloc(sizeof(struct msm_plat_data), GFP_KERNEL);
2094 if (!pdata)
2095 return -ENOMEM;
2096
2097 if (of_property_read_bool(pdev->dev.of_node,
2098 "qcom,msm-pcm-low-latency")) {
2099
2100 pdata->perf_mode = LOW_LATENCY_PCM_MODE;
2101 rc = of_property_read_string(pdev->dev.of_node,
2102 "qcom,latency-level", &latency_level);
2103 if (!rc) {
2104 if (!strcmp(latency_level, "ultra"))
2105 pdata->perf_mode = ULTRA_LOW_LATENCY_PCM_MODE;
2106 else if (!strcmp(latency_level, "ull-pp"))
2107 pdata->perf_mode =
2108 ULL_POST_PROCESSING_PCM_MODE;
2109 }
2110 } else {
2111 pdata->perf_mode = LEGACY_PCM_MODE;
2112 }
2113
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05302114 mutex_init(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302115 dev_set_drvdata(&pdev->dev, pdata);
2116
2117
2118 dev_dbg(&pdev->dev, "%s: dev name %s\n",
2119 __func__, dev_name(&pdev->dev));
2120 return snd_soc_register_platform(&pdev->dev,
2121 &msm_soc_platform);
2122}
2123
2124static int msm_pcm_remove(struct platform_device *pdev)
2125{
2126 struct msm_plat_data *pdata;
2127
2128 pdata = dev_get_drvdata(&pdev->dev);
Ajit Pandey3d7b9a22019-09-05 16:26:01 +05302129 mutex_destroy(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302130 kfree(pdata);
2131 snd_soc_unregister_platform(&pdev->dev);
2132 return 0;
2133}
2134static const struct of_device_id msm_pcm_dt_match[] = {
2135 {.compatible = "qcom,msm-pcm-dsp"},
2136 {}
2137};
2138MODULE_DEVICE_TABLE(of, msm_pcm_dt_match);
2139
2140static struct platform_driver msm_pcm_driver = {
2141 .driver = {
2142 .name = "msm-pcm-dsp",
2143 .owner = THIS_MODULE,
2144 .of_match_table = msm_pcm_dt_match,
2145 },
2146 .probe = msm_pcm_probe,
2147 .remove = msm_pcm_remove,
2148};
2149
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302150int __init msm_pcm_dsp_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302151{
2152 init_waitqueue_head(&the_locks.enable_wait);
2153 init_waitqueue_head(&the_locks.eos_wait);
2154 init_waitqueue_head(&the_locks.write_wait);
2155 init_waitqueue_head(&the_locks.read_wait);
2156
2157 return platform_driver_register(&msm_pcm_driver);
2158}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302159
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05302160void msm_pcm_dsp_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302161{
2162 platform_driver_unregister(&msm_pcm_driver);
2163}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302164
2165MODULE_DESCRIPTION("PCM module platform driver");
2166MODULE_LICENSE("GPL v2");