blob: 0b312fe36e915b679dc8f9c8bb280fc36c4d47bf [file] [log] [blame]
Meng Wangac147b72017-10-30 16:46:16 +08001/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13
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>
19#include <linux/wait.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22#include <sound/core.h>
23#include <sound/soc.h>
24#include <sound/soc-dapm.h>
25#include <sound/pcm.h>
26#include <sound/initval.h>
27#include <sound/control.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053028#include <sound/timer.h>
29#include <asm/dma.h>
30#include <linux/dma-mapping.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053031#include <linux/msm_audio.h>
32
33#include <linux/of_device.h>
34#include <sound/tlv.h>
35#include <sound/pcm_params.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053036#include <dsp/msm_audio_ion.h>
37#include <dsp/q6audio-v2.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053038
39#include "msm-pcm-q6-v2.h"
40#include "msm-pcm-routing-v2.h"
41#include "msm-qti-pp-config.h"
42
43enum stream_state {
44 IDLE = 0,
45 STOPPED,
46 RUNNING,
47};
48
49static struct audio_locks the_locks;
50
51#define PCM_MASTER_VOL_MAX_STEPS 0x2000
52static const DECLARE_TLV_DB_LINEAR(msm_pcm_vol_gain, 0,
53 PCM_MASTER_VOL_MAX_STEPS);
54
55struct snd_msm {
56 struct snd_card *card;
57 struct snd_pcm *pcm;
58};
59
60#define CMD_EOS_MIN_TIMEOUT_LENGTH 50
61#define CMD_EOS_TIMEOUT_MULTIPLIER (HZ * 50)
62#define MAX_PB_COPY_RETRIES 3
63
64static struct snd_pcm_hardware msm_pcm_hardware_capture = {
65 .info = (SNDRV_PCM_INFO_MMAP |
66 SNDRV_PCM_INFO_BLOCK_TRANSFER |
67 SNDRV_PCM_INFO_MMAP_VALID |
68 SNDRV_PCM_INFO_INTERLEAVED |
69 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
70 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
71 SNDRV_PCM_FMTBIT_S24_LE |
72 SNDRV_PCM_FMTBIT_S24_3LE |
73 SNDRV_PCM_FMTBIT_S32_LE),
74 .rates = SNDRV_PCM_RATE_8000_384000,
75 .rate_min = 8000,
76 .rate_max = 384000,
77 .channels_min = 1,
78 .channels_max = 4,
79 .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS *
80 CAPTURE_MAX_PERIOD_SIZE,
81 .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
82 .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
83 .periods_min = CAPTURE_MIN_NUM_PERIODS,
84 .periods_max = CAPTURE_MAX_NUM_PERIODS,
85 .fifo_size = 0,
86};
87
88static struct snd_pcm_hardware msm_pcm_hardware_playback = {
89 .info = (SNDRV_PCM_INFO_MMAP |
90 SNDRV_PCM_INFO_BLOCK_TRANSFER |
91 SNDRV_PCM_INFO_MMAP_VALID |
92 SNDRV_PCM_INFO_INTERLEAVED |
93 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
94 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
95 SNDRV_PCM_FMTBIT_S24_LE |
96 SNDRV_PCM_FMTBIT_S24_3LE |
97 SNDRV_PCM_FMTBIT_S32_LE),
98 .rates = SNDRV_PCM_RATE_8000_384000,
99 .rate_min = 8000,
100 .rate_max = 384000,
101 .channels_min = 1,
102 .channels_max = 8,
103 .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS *
104 PLAYBACK_MAX_PERIOD_SIZE,
105 .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
106 .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
107 .periods_min = PLAYBACK_MIN_NUM_PERIODS,
108 .periods_max = PLAYBACK_MAX_NUM_PERIODS,
109 .fifo_size = 0,
110};
111
112/* Conventional and unconventional sample rate supported */
113static unsigned int supported_sample_rates[] = {
114 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
115 88200, 96000, 176400, 192000, 352800, 384000
116};
117
118static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
119 .count = ARRAY_SIZE(supported_sample_rates),
120 .list = supported_sample_rates,
121 .mask = 0,
122};
123
124static void msm_pcm_route_event_handler(enum msm_pcm_routing_event event,
125 void *priv_data)
126{
127 struct msm_audio *prtd = priv_data;
128
129 WARN_ON(!prtd);
130
131 pr_debug("%s: event %x\n", __func__, event);
132
133 switch (event) {
134 case MSM_PCM_RT_EVT_BUF_RECFG:
135 q6asm_cmd(prtd->audio_client, CMD_PAUSE);
136 q6asm_cmd(prtd->audio_client, CMD_FLUSH);
137 q6asm_run(prtd->audio_client, 0, 0, 0);
138 /* fallthrough */
139 default:
140 break;
141 }
142}
143
144static void event_handler(uint32_t opcode,
145 uint32_t token, uint32_t *payload, void *priv)
146{
147 struct msm_audio *prtd = priv;
148 struct snd_pcm_substream *substream = prtd->substream;
149 uint32_t *ptrmem = (uint32_t *)payload;
150 uint32_t idx = 0;
151 uint32_t size = 0;
152 uint8_t buf_index;
153 struct snd_soc_pcm_runtime *rtd;
154 int ret = 0;
155
156 switch (opcode) {
157 case ASM_DATA_EVENT_WRITE_DONE_V2: {
158 pr_debug("ASM_DATA_EVENT_WRITE_DONE_V2\n");
159 pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem);
160 prtd->pcm_irq_pos += prtd->pcm_count;
161 if (atomic_read(&prtd->start))
162 snd_pcm_period_elapsed(substream);
163 atomic_inc(&prtd->out_count);
164 wake_up(&the_locks.write_wait);
165 if (!atomic_read(&prtd->start))
166 break;
167 if (!prtd->mmap_flag || prtd->reset_event)
168 break;
169 if (q6asm_is_cpu_buf_avail_nolock(IN,
170 prtd->audio_client,
171 &size, &idx)) {
172 pr_debug("%s:writing %d bytes of buffer to dsp 2\n",
173 __func__, prtd->pcm_count);
174 q6asm_write_nolock(prtd->audio_client,
175 prtd->pcm_count, 0, 0, NO_TIMESTAMP);
176 }
177 break;
178 }
179 case ASM_DATA_EVENT_RENDERED_EOS:
180 pr_debug("ASM_DATA_EVENT_RENDERED_EOS\n");
181 clear_bit(CMD_EOS, &prtd->cmd_pending);
182 wake_up(&the_locks.eos_wait);
183 break;
184 case ASM_DATA_EVENT_READ_DONE_V2: {
185 pr_debug("ASM_DATA_EVENT_READ_DONE_V2\n");
186 buf_index = q6asm_get_buf_index_from_token(token);
Vignesh Kulothungan3817b182017-12-04 15:56:05 -0800187 if (buf_index >= CAPTURE_MAX_NUM_PERIODS) {
188 pr_err("%s: buffer index %u is out of range.\n",
189 __func__, buf_index);
190 return;
191 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530192 pr_debug("%s: token=0x%08x buf_index=0x%08x\n",
193 __func__, token, buf_index);
194 prtd->in_frame_info[buf_index].size = payload[4];
195 prtd->in_frame_info[buf_index].offset = payload[5];
196 /* assume data size = 0 during flushing */
197 if (prtd->in_frame_info[buf_index].size) {
198 prtd->pcm_irq_pos +=
199 prtd->in_frame_info[buf_index].size;
200 pr_debug("pcm_irq_pos=%d\n", prtd->pcm_irq_pos);
201 if (atomic_read(&prtd->start))
202 snd_pcm_period_elapsed(substream);
203 if (atomic_read(&prtd->in_count) <= prtd->periods)
204 atomic_inc(&prtd->in_count);
205 wake_up(&the_locks.read_wait);
206 if (prtd->mmap_flag &&
207 q6asm_is_cpu_buf_avail_nolock(OUT,
208 prtd->audio_client,
209 &size, &idx) &&
210 (substream->runtime->status->state ==
211 SNDRV_PCM_STATE_RUNNING))
212 q6asm_read_nolock(prtd->audio_client);
213 } else {
214 pr_debug("%s: reclaim flushed buf in_count %x\n",
215 __func__, atomic_read(&prtd->in_count));
216 prtd->pcm_irq_pos += prtd->pcm_count;
217 if (prtd->mmap_flag) {
218 if (q6asm_is_cpu_buf_avail_nolock(OUT,
219 prtd->audio_client,
220 &size, &idx) &&
221 (substream->runtime->status->state ==
222 SNDRV_PCM_STATE_RUNNING))
223 q6asm_read_nolock(prtd->audio_client);
224 } else {
225 atomic_inc(&prtd->in_count);
226 }
227 if (atomic_read(&prtd->in_count) == prtd->periods) {
228 pr_info("%s: reclaimed all bufs\n", __func__);
229 if (atomic_read(&prtd->start))
230 snd_pcm_period_elapsed(substream);
231 wake_up(&the_locks.read_wait);
232 }
233 }
234 break;
235 }
236 case ASM_STREAM_PP_EVENT:
237 case ASM_STREAM_CMD_ENCDEC_EVENTS: {
238 pr_debug("%s: ASM_STREAM_EVENT (0x%x)\n", __func__, opcode);
239 if (!substream) {
240 pr_err("%s: substream is NULL.\n", __func__);
241 return;
242 }
243
244 rtd = substream->private_data;
245 if (!rtd) {
246 pr_err("%s: rtd is NULL\n", __func__);
247 return;
248 }
249
250 ret = msm_adsp_inform_mixer_ctl(rtd, payload);
251 if (ret) {
252 pr_err("%s: failed to inform mixer ctl. err = %d\n",
253 __func__, ret);
254 return;
255 }
256
257 break;
258 }
259 case APR_BASIC_RSP_RESULT: {
260 switch (payload[0]) {
261 case ASM_SESSION_CMD_RUN_V2:
262 if (substream->stream
263 != SNDRV_PCM_STREAM_PLAYBACK) {
264 atomic_set(&prtd->start, 1);
265 break;
266 }
267 if (prtd->mmap_flag) {
268 pr_debug("%s:writing %d bytes of buffer to dsp\n",
269 __func__,
270 prtd->pcm_count);
271 q6asm_write_nolock(prtd->audio_client,
272 prtd->pcm_count,
273 0, 0, NO_TIMESTAMP);
274 } else {
275 while (atomic_read(&prtd->out_needed)) {
276 pr_debug("%s:writing %d bytes of buffer to dsp\n",
277 __func__,
278 prtd->pcm_count);
279 q6asm_write_nolock(prtd->audio_client,
280 prtd->pcm_count,
281 0, 0, NO_TIMESTAMP);
282 atomic_dec(&prtd->out_needed);
283 wake_up(&the_locks.write_wait);
284 };
285 }
286 atomic_set(&prtd->start, 1);
287 break;
288 case ASM_STREAM_CMD_REGISTER_PP_EVENTS:
289 pr_debug("%s: ASM_STREAM_CMD_REGISTER_PP_EVENTS:",
290 __func__);
291 break;
292 default:
293 pr_debug("%s:Payload = [0x%x]stat[0x%x]\n",
294 __func__, payload[0], payload[1]);
295 break;
296 }
297 }
298 break;
299 case RESET_EVENTS:
300 pr_debug("%s RESET_EVENTS\n", __func__);
301 prtd->pcm_irq_pos += prtd->pcm_count;
302 atomic_inc(&prtd->out_count);
303 atomic_inc(&prtd->in_count);
304 prtd->reset_event = true;
305 if (atomic_read(&prtd->start))
306 snd_pcm_period_elapsed(substream);
307 wake_up(&the_locks.eos_wait);
308 wake_up(&the_locks.write_wait);
309 wake_up(&the_locks.read_wait);
310 break;
311 default:
312 pr_debug("Not Supported Event opcode[0x%x]\n", opcode);
313 break;
314 }
315}
316
317static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
318{
319 struct snd_pcm_runtime *runtime = substream->runtime;
320 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
321 struct msm_audio *prtd = runtime->private_data;
322 struct msm_plat_data *pdata;
323 struct snd_pcm_hw_params *params;
324 int ret;
325 uint32_t fmt_type = FORMAT_LINEAR_PCM;
326 uint16_t bits_per_sample;
327 uint16_t sample_word_size;
328
329 pdata = (struct msm_plat_data *)
330 dev_get_drvdata(soc_prtd->platform->dev);
331 if (!pdata) {
332 pr_err("%s: platform data not populated\n", __func__);
333 return -EINVAL;
334 }
335 if (!prtd || !prtd->audio_client) {
336 pr_err("%s: private data null or audio client freed\n",
337 __func__);
338 return -EINVAL;
339 }
340 params = &soc_prtd->dpcm[substream->stream].hw_params;
341
342 pr_debug("%s\n", __func__);
343 prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
344 prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
345 prtd->pcm_irq_pos = 0;
346 /* rate and channels are sent to audio driver */
347 prtd->samp_rate = runtime->rate;
348 prtd->channel_mode = runtime->channels;
349 if (prtd->enabled)
350 return 0;
351
352 prtd->audio_client->perf_mode = pdata->perf_mode;
353 pr_debug("%s: perf: %x\n", __func__, pdata->perf_mode);
354
355 switch (params_format(params)) {
356 case SNDRV_PCM_FORMAT_S32_LE:
357 bits_per_sample = 32;
358 sample_word_size = 32;
359 break;
360 case SNDRV_PCM_FORMAT_S24_LE:
361 bits_per_sample = 24;
362 sample_word_size = 32;
363 break;
364 case SNDRV_PCM_FORMAT_S24_3LE:
365 bits_per_sample = 24;
366 sample_word_size = 24;
367 break;
368 case SNDRV_PCM_FORMAT_S16_LE:
369 default:
370 bits_per_sample = 16;
371 sample_word_size = 16;
372 break;
373 }
374 if (prtd->compress_enable) {
375 fmt_type = FORMAT_GEN_COMPR;
376 pr_debug("%s: Compressed enabled!\n", __func__);
377 ret = q6asm_open_write_compressed(prtd->audio_client, fmt_type,
378 COMPRESSED_PASSTHROUGH_GEN);
379 if (ret < 0) {
380 pr_err("%s: q6asm_open_write_compressed failed (%d)\n",
381 __func__, ret);
382 q6asm_audio_client_free(prtd->audio_client);
383 prtd->audio_client = NULL;
384 return -ENOMEM;
385 }
386 } else {
387 ret = q6asm_open_write_v4(prtd->audio_client,
388 fmt_type, bits_per_sample);
389
390 if (ret < 0) {
391 pr_err("%s: q6asm_open_write_v4 failed (%d)\n",
392 __func__, ret);
393 q6asm_audio_client_free(prtd->audio_client);
394 prtd->audio_client = NULL;
395 return -ENOMEM;
396 }
397
398 ret = q6asm_send_cal(prtd->audio_client);
399 if (ret < 0)
400 pr_debug("%s : Send cal failed : %d", __func__, ret);
401 }
402 pr_debug("%s: session ID %d\n", __func__,
403 prtd->audio_client->session);
404 prtd->session_id = prtd->audio_client->session;
405
406 if (prtd->compress_enable) {
407 ret = msm_pcm_routing_reg_phy_compr_stream(
408 soc_prtd->dai_link->id,
409 prtd->audio_client->perf_mode,
410 prtd->session_id,
411 SNDRV_PCM_STREAM_PLAYBACK,
412 COMPRESSED_PASSTHROUGH_GEN);
413 } else {
414 ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->id,
415 prtd->audio_client->perf_mode,
416 prtd->session_id, substream->stream);
417 }
418 if (ret) {
419 pr_err("%s: stream reg failed ret:%d\n", __func__, ret);
420 return ret;
421 }
422 if (prtd->compress_enable) {
423 ret = q6asm_media_format_block_gen_compr(
424 prtd->audio_client, runtime->rate,
425 runtime->channels, !prtd->set_channel_map,
426 prtd->channel_map, bits_per_sample);
427 } else {
428 ret = q6asm_media_format_block_multi_ch_pcm_v4(
429 prtd->audio_client, runtime->rate,
430 runtime->channels, !prtd->set_channel_map,
431 prtd->channel_map, bits_per_sample,
432 sample_word_size, ASM_LITTLE_ENDIAN,
433 DEFAULT_QF);
434 }
435 if (ret < 0)
436 pr_info("%s: CMD Format block failed\n", __func__);
437
438 atomic_set(&prtd->out_count, runtime->periods);
439
440 prtd->enabled = 1;
441 prtd->cmd_pending = 0;
442 prtd->cmd_interrupt = 0;
443
444 return 0;
445}
446
447static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
448{
449 struct snd_pcm_runtime *runtime = substream->runtime;
450 struct msm_audio *prtd = runtime->private_data;
451 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
452 struct msm_plat_data *pdata;
453 struct snd_pcm_hw_params *params;
454 struct msm_pcm_routing_evt event;
455 int ret = 0;
456 int i = 0;
457 uint16_t bits_per_sample = 16;
458 uint16_t sample_word_size;
459
460 pdata = (struct msm_plat_data *)
461 dev_get_drvdata(soc_prtd->platform->dev);
462 if (!pdata) {
463 pr_err("%s: platform data not populated\n", __func__);
464 return -EINVAL;
465 }
466 if (!prtd || !prtd->audio_client) {
467 pr_err("%s: private data null or audio client freed\n",
468 __func__);
469 return -EINVAL;
470 }
471
472 if (prtd->enabled == IDLE) {
473 pr_debug("%s:perf_mode=%d periods=%d\n", __func__,
474 pdata->perf_mode, runtime->periods);
475 params = &soc_prtd->dpcm[substream->stream].hw_params;
476 if ((params_format(params) == SNDRV_PCM_FORMAT_S24_LE) ||
477 (params_format(params) == SNDRV_PCM_FORMAT_S24_3LE))
478 bits_per_sample = 24;
479 else if (params_format(params) == SNDRV_PCM_FORMAT_S32_LE)
480 bits_per_sample = 32;
481
482 /* ULL mode is not supported in capture path */
483 if (pdata->perf_mode == LEGACY_PCM_MODE)
484 prtd->audio_client->perf_mode = LEGACY_PCM_MODE;
485 else
486 prtd->audio_client->perf_mode = LOW_LATENCY_PCM_MODE;
487
488 pr_debug("%s Opening %d-ch PCM read stream, perf_mode %d\n",
489 __func__, params_channels(params),
490 prtd->audio_client->perf_mode);
491
492 ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM,
Vikram Pandurangac712c172017-11-17 17:36:49 -0800493 bits_per_sample, false, ENC_CFG_ID_NONE);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530494 if (ret < 0) {
495 pr_err("%s: q6asm_open_read failed\n", __func__);
496 q6asm_audio_client_free(prtd->audio_client);
497 prtd->audio_client = NULL;
498 return -ENOMEM;
499 }
500
501 ret = q6asm_send_cal(prtd->audio_client);
502 if (ret < 0)
503 pr_debug("%s : Send cal failed : %d", __func__, ret);
504
505 pr_debug("%s: session ID %d\n",
506 __func__, prtd->audio_client->session);
507 prtd->session_id = prtd->audio_client->session;
508 event.event_func = msm_pcm_route_event_handler;
509 event.priv_data = (void *) prtd;
510 ret = msm_pcm_routing_reg_phy_stream_v2(
511 soc_prtd->dai_link->id,
512 prtd->audio_client->perf_mode,
513 prtd->session_id, substream->stream,
514 event);
515 if (ret) {
516 pr_err("%s: stream reg failed ret:%d\n", __func__, ret);
517 return ret;
518 }
519 }
520
521 prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
522 prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
523 prtd->pcm_irq_pos = 0;
524 /* rate and channels are sent to audio driver */
525 prtd->samp_rate = runtime->rate;
526 prtd->channel_mode = runtime->channels;
527
528 if (prtd->enabled == IDLE || prtd->enabled == STOPPED) {
529 for (i = 0; i < runtime->periods; i++)
530 q6asm_read(prtd->audio_client);
531 prtd->periods = runtime->periods;
532 }
533
534 if (prtd->enabled != IDLE)
535 return 0;
536
537 switch (runtime->format) {
538 case SNDRV_PCM_FORMAT_S32_LE:
539 bits_per_sample = 32;
540 sample_word_size = 32;
541 break;
542 case SNDRV_PCM_FORMAT_S24_LE:
543 bits_per_sample = 24;
544 sample_word_size = 32;
545 break;
546 case SNDRV_PCM_FORMAT_S24_3LE:
547 bits_per_sample = 24;
548 sample_word_size = 24;
549 break;
550 case SNDRV_PCM_FORMAT_S16_LE:
551 default:
552 bits_per_sample = 16;
553 sample_word_size = 16;
554 break;
555 }
556
557 pr_debug("%s: Samp_rate = %d Channel = %d bit width = %d, word size = %d\n",
558 __func__, prtd->samp_rate, prtd->channel_mode,
559 bits_per_sample, sample_word_size);
560 ret = q6asm_enc_cfg_blk_pcm_format_support_v4(prtd->audio_client,
561 prtd->samp_rate,
562 prtd->channel_mode,
563 bits_per_sample,
564 sample_word_size,
565 ASM_LITTLE_ENDIAN,
566 DEFAULT_QF);
567 if (ret < 0)
568 pr_debug("%s: cmd cfg pcm was block failed", __func__);
569
570 prtd->enabled = RUNNING;
571
572 return ret;
573}
574
575static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
576{
577 int ret = 0;
578 struct snd_pcm_runtime *runtime = substream->runtime;
579 struct msm_audio *prtd = runtime->private_data;
580
581 switch (cmd) {
582 case SNDRV_PCM_TRIGGER_START:
583 case SNDRV_PCM_TRIGGER_RESUME:
584 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
585 pr_debug("%s: Trigger start\n", __func__);
586 ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
587 break;
588 case SNDRV_PCM_TRIGGER_STOP:
589 pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
590 atomic_set(&prtd->start, 0);
591 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) {
592 prtd->enabled = STOPPED;
593 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
594 break;
595 }
596 /* pending CMD_EOS isn't expected */
597 WARN_ON_ONCE(test_bit(CMD_EOS, &prtd->cmd_pending));
598 set_bit(CMD_EOS, &prtd->cmd_pending);
599 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
600 if (ret)
601 clear_bit(CMD_EOS, &prtd->cmd_pending);
602 break;
603 case SNDRV_PCM_TRIGGER_SUSPEND:
604 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
605 pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n");
606 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
607 atomic_set(&prtd->start, 0);
608 break;
609 default:
610 ret = -EINVAL;
611 break;
612 }
613
614 return ret;
615}
616
617static int msm_pcm_open(struct snd_pcm_substream *substream)
618{
619 struct snd_pcm_runtime *runtime = substream->runtime;
620 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
621 struct msm_audio *prtd;
Banajit Goswami616e68c2017-10-27 01:31:19 -0700622 struct msm_plat_data *pdata;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530623 int ret = 0;
624
Banajit Goswami616e68c2017-10-27 01:31:19 -0700625 pdata = (struct msm_plat_data *)
626 dev_get_drvdata(soc_prtd->platform->dev);
627 if (!pdata) {
628 pr_err("%s: platform data not populated\n", __func__);
629 return -EINVAL;
630 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530631 prtd = kzalloc(sizeof(struct msm_audio), GFP_KERNEL);
632 if (prtd == NULL)
633 return -ENOMEM;
634
635 prtd->substream = substream;
636 prtd->audio_client = q6asm_audio_client_alloc(
637 (app_cb)event_handler, prtd);
638 if (!prtd->audio_client) {
639 pr_info("%s: Could not allocate memory\n", __func__);
640 kfree(prtd);
641 return -ENOMEM;
642 }
643
644 prtd->audio_client->dev = soc_prtd->platform->dev;
645
646 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
647 runtime->hw = msm_pcm_hardware_playback;
648
649 /* Capture path */
650 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
651 runtime->hw = msm_pcm_hardware_capture;
652 else {
653 pr_err("Invalid Stream type %d\n", substream->stream);
654 return -EINVAL;
655 }
656
657 ret = snd_pcm_hw_constraint_list(runtime, 0,
658 SNDRV_PCM_HW_PARAM_RATE,
659 &constraints_sample_rates);
660 if (ret < 0)
661 pr_info("snd_pcm_hw_constraint_list failed\n");
662 /* Ensure that buffer size is a multiple of period size */
663 ret = snd_pcm_hw_constraint_integer(runtime,
664 SNDRV_PCM_HW_PARAM_PERIODS);
665 if (ret < 0)
666 pr_info("snd_pcm_hw_constraint_integer failed\n");
667
668 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
669 ret = snd_pcm_hw_constraint_minmax(runtime,
670 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
671 PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE,
672 PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE);
673 if (ret < 0) {
674 pr_err("constraint for buffer bytes min max ret = %d\n",
675 ret);
676 }
677 }
678
679 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
680 ret = snd_pcm_hw_constraint_minmax(runtime,
681 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
682 CAPTURE_MIN_NUM_PERIODS * CAPTURE_MIN_PERIOD_SIZE,
683 CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE);
684 if (ret < 0) {
685 pr_err("constraint for buffer bytes min max ret = %d\n",
686 ret);
687 }
688 }
689 ret = snd_pcm_hw_constraint_step(runtime, 0,
690 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
691 if (ret < 0) {
692 pr_err("constraint for period bytes step ret = %d\n",
693 ret);
694 }
695 ret = snd_pcm_hw_constraint_step(runtime, 0,
696 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
697 if (ret < 0) {
698 pr_err("constraint for buffer bytes step ret = %d\n",
699 ret);
700 }
701
702 prtd->enabled = IDLE;
703 prtd->dsp_cnt = 0;
704 prtd->set_channel_map = false;
705 prtd->reset_event = false;
706 runtime->private_data = prtd;
Xiaojun Sangf27e3512018-05-23 17:14:31 +0800707
708 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
709 msm_adsp_init_mixer_ctl_pp_event_queue(soc_prtd);
710
Banajit Goswami616e68c2017-10-27 01:31:19 -0700711 /* Vote to update the Rx thread priority to RT Thread for playback */
712 if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
713 (pdata->perf_mode == LOW_LATENCY_PCM_MODE))
714 apr_start_rx_rt(prtd->audio_client->apr);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530715
716 return 0;
717}
718
719static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
Meng Wangac147b72017-10-30 16:46:16 +0800720 unsigned long hwoff, void __user *buf, unsigned long fbytes)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530721{
722 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530723 int xfer = 0;
724 char *bufptr = NULL;
725 void *data = NULL;
726 uint32_t idx = 0;
727 uint32_t size = 0;
728 uint32_t retries = 0;
729
730 struct snd_pcm_runtime *runtime = substream->runtime;
731 struct msm_audio *prtd = runtime->private_data;
732
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530733 pr_debug("%s: prtd->out_count = %d\n",
734 __func__, atomic_read(&prtd->out_count));
735
736 while ((fbytes > 0) && (retries < MAX_PB_COPY_RETRIES)) {
737 if (prtd->reset_event) {
738 pr_err("%s: In SSR return ENETRESET before wait\n",
739 __func__);
740 return -ENETRESET;
741 }
742
743 ret = wait_event_timeout(the_locks.write_wait,
744 (atomic_read(&prtd->out_count)), 5 * HZ);
745 if (!ret) {
746 pr_err("%s: wait_event_timeout failed\n", __func__);
747 ret = -ETIMEDOUT;
748 goto fail;
749 }
750 ret = 0;
751
752 if (prtd->reset_event) {
753 pr_err("%s: In SSR return ENETRESET after wait\n",
754 __func__);
755 return -ENETRESET;
756 }
757
758 if (!atomic_read(&prtd->out_count)) {
759 pr_err("%s: pcm stopped out_count 0\n", __func__);
760 return 0;
761 }
762
763 data = q6asm_is_cpu_buf_avail(IN, prtd->audio_client, &size,
764 &idx);
765 if (data == NULL) {
766 retries++;
767 continue;
768 } else {
769 retries = 0;
770 }
771
772 if (fbytes > size)
773 xfer = size;
774 else
775 xfer = fbytes;
776
777 bufptr = data;
778 if (bufptr) {
Meng Wangac147b72017-10-30 16:46:16 +0800779 pr_debug("%s:fbytes =%lu: xfer=%d size=%d\n",
780 __func__, fbytes, xfer, size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530781 if (copy_from_user(bufptr, buf, xfer)) {
782 ret = -EFAULT;
783 pr_err("%s: copy_from_user failed\n",
784 __func__);
785 q6asm_cpu_buf_release(IN, prtd->audio_client);
786 goto fail;
787 }
788 buf += xfer;
789 fbytes -= xfer;
Meng Wangac147b72017-10-30 16:46:16 +0800790 pr_debug("%s:fbytes = %lu: xfer=%d\n", __func__,
791 fbytes, xfer);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530792 if (atomic_read(&prtd->start)) {
793 pr_debug("%s:writing %d bytes of buffer to dsp\n",
794 __func__, xfer);
795 ret = q6asm_write(prtd->audio_client, xfer,
796 0, 0, NO_TIMESTAMP);
797 if (ret < 0) {
798 ret = -EFAULT;
799 q6asm_cpu_buf_release(IN,
800 prtd->audio_client);
801 goto fail;
802 }
803 } else
804 atomic_inc(&prtd->out_needed);
805 atomic_dec(&prtd->out_count);
806 }
807 }
808fail:
809 if (retries >= MAX_PB_COPY_RETRIES)
810 ret = -ENOMEM;
811
812 return ret;
813}
814
815static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
816{
817 struct snd_pcm_runtime *runtime = substream->runtime;
818 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
819 struct msm_audio *prtd = runtime->private_data;
Banajit Goswami616e68c2017-10-27 01:31:19 -0700820 struct msm_plat_data *pdata;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530821 uint32_t timeout;
822 int dir = 0;
823 int ret = 0;
824
825 pr_debug("%s: cmd_pending 0x%lx\n", __func__, prtd->cmd_pending);
826
827 if (prtd->audio_client) {
828 dir = IN;
829
Banajit Goswami616e68c2017-10-27 01:31:19 -0700830 /*
831 * Unvote to downgrade the Rx thread priority from
832 * RT Thread for Low-Latency use case.
833 */
834 pdata = (struct msm_plat_data *)
835 dev_get_drvdata(soc_prtd->platform->dev);
836 if (pdata) {
837 if (pdata->perf_mode == LOW_LATENCY_PCM_MODE)
838 apr_end_rx_rt(prtd->audio_client->apr);
839 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530840 /* determine timeout length */
841 if (runtime->frame_bits == 0 || runtime->rate == 0) {
842 timeout = CMD_EOS_MIN_TIMEOUT_LENGTH;
843 } else {
844 timeout = (runtime->period_size *
845 CMD_EOS_TIMEOUT_MULTIPLIER) /
846 ((runtime->frame_bits / 8) *
847 runtime->rate);
848 if (timeout < CMD_EOS_MIN_TIMEOUT_LENGTH)
849 timeout = CMD_EOS_MIN_TIMEOUT_LENGTH;
850 }
851 pr_debug("%s: CMD_EOS timeout is %d\n", __func__, timeout);
852
853 ret = wait_event_timeout(the_locks.eos_wait,
854 !test_bit(CMD_EOS, &prtd->cmd_pending),
855 timeout);
856 if (!ret)
857 pr_err("%s: CMD_EOS failed, cmd_pending 0x%lx\n",
858 __func__, prtd->cmd_pending);
859 q6asm_cmd(prtd->audio_client, CMD_CLOSE);
860 q6asm_audio_client_buf_free_contiguous(dir,
861 prtd->audio_client);
862 q6asm_audio_client_free(prtd->audio_client);
863 }
864 msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
865 SNDRV_PCM_STREAM_PLAYBACK);
866 msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
867 kfree(prtd);
868 runtime->private_data = NULL;
869
870 return 0;
871}
872
873static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
Meng Wangac147b72017-10-30 16:46:16 +0800874 int channel, unsigned long hwoff, void __user *buf,
875 unsigned long fbytes)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530876{
877 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530878 int xfer;
879 char *bufptr;
880 void *data = NULL;
881 static uint32_t idx;
882 static uint32_t size;
883 uint32_t offset = 0;
884 struct snd_pcm_runtime *runtime = substream->runtime;
885 struct msm_audio *prtd = substream->runtime->private_data;
886
887
888 pr_debug("%s\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530889
890 pr_debug("appl_ptr %d\n", (int)runtime->control->appl_ptr);
891 pr_debug("hw_ptr %d\n", (int)runtime->status->hw_ptr);
892 pr_debug("avail_min %d\n", (int)runtime->control->avail_min);
893
894 if (prtd->reset_event) {
895 pr_err("%s: In SSR return ENETRESET before wait\n", __func__);
896 return -ENETRESET;
897 }
898 ret = wait_event_timeout(the_locks.read_wait,
899 (atomic_read(&prtd->in_count)), 5 * HZ);
900 if (!ret) {
901 pr_debug("%s: wait_event_timeout failed\n", __func__);
902 goto fail;
903 }
904 if (prtd->reset_event) {
905 pr_err("%s: In SSR return ENETRESET after wait\n", __func__);
906 return -ENETRESET;
907 }
908 if (!atomic_read(&prtd->in_count)) {
909 pr_debug("%s: pcm stopped in_count 0\n", __func__);
910 return 0;
911 }
912 pr_debug("Checking if valid buffer is available...%pK\n",
913 data);
914 data = q6asm_is_cpu_buf_avail(OUT, prtd->audio_client, &size, &idx);
915 bufptr = data;
916 pr_debug("Size = %d\n", size);
Meng Wangac147b72017-10-30 16:46:16 +0800917 pr_debug("fbytes = %lu\n", fbytes);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530918 pr_debug("idx = %d\n", idx);
919 if (bufptr) {
920 xfer = fbytes;
921 if (xfer > size)
922 xfer = size;
923 offset = prtd->in_frame_info[idx].offset;
924 pr_debug("Offset value = %d\n", offset);
925 if (copy_to_user(buf, bufptr+offset, xfer)) {
926 pr_err("Failed to copy buf to user\n");
927 ret = -EFAULT;
928 q6asm_cpu_buf_release(OUT, prtd->audio_client);
929 goto fail;
930 }
931 fbytes -= xfer;
932 size -= xfer;
933 prtd->in_frame_info[idx].offset += xfer;
Meng Wangac147b72017-10-30 16:46:16 +0800934 pr_debug("%s:fbytes = %lu: size=%d: xfer=%d\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530935 __func__, fbytes, size, xfer);
936 pr_debug(" Sending next buffer to dsp\n");
937 memset(&prtd->in_frame_info[idx], 0,
938 sizeof(struct msm_audio_in_frame_info));
939 atomic_dec(&prtd->in_count);
940 ret = q6asm_read(prtd->audio_client);
941 if (ret < 0) {
942 pr_err("q6asm read failed\n");
943 ret = -EFAULT;
944 q6asm_cpu_buf_release(OUT, prtd->audio_client);
945 goto fail;
946 }
947 } else
948 pr_err("No valid buffer\n");
949
950 pr_debug("Returning from capture_copy... %d\n", ret);
951fail:
952 return ret;
953}
954
955static int msm_pcm_capture_close(struct snd_pcm_substream *substream)
956{
957 struct snd_pcm_runtime *runtime = substream->runtime;
958 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
959 struct msm_audio *prtd = runtime->private_data;
960 int dir = OUT;
961
962 pr_debug("%s\n", __func__);
963 if (prtd->audio_client) {
964 q6asm_cmd(prtd->audio_client, CMD_CLOSE);
965 q6asm_audio_client_buf_free_contiguous(dir,
966 prtd->audio_client);
967 q6asm_audio_client_free(prtd->audio_client);
968 }
969
970 msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
971 SNDRV_PCM_STREAM_CAPTURE);
972 kfree(prtd);
973 runtime->private_data = NULL;
974
975 return 0;
976}
977
978static int msm_pcm_copy(struct snd_pcm_substream *substream, int a,
Meng Wangac147b72017-10-30 16:46:16 +0800979 unsigned long hwoff, void __user *buf, unsigned long fbytes)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530980{
981 int ret = 0;
982
983 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Meng Wangac147b72017-10-30 16:46:16 +0800984 ret = msm_pcm_playback_copy(substream, a, hwoff, buf, fbytes);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530985 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
Meng Wangac147b72017-10-30 16:46:16 +0800986 ret = msm_pcm_capture_copy(substream, a, hwoff, buf, fbytes);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530987 return ret;
988}
989
990static int msm_pcm_close(struct snd_pcm_substream *substream)
991{
992 int ret = 0;
993
994 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
995 ret = msm_pcm_playback_close(substream);
996 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
997 ret = msm_pcm_capture_close(substream);
998 return ret;
999}
1000
1001static int msm_pcm_prepare(struct snd_pcm_substream *substream)
1002{
1003 int ret = 0;
1004
1005 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1006 ret = msm_pcm_playback_prepare(substream);
1007 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
1008 ret = msm_pcm_capture_prepare(substream);
1009 return ret;
1010}
1011
1012static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream)
1013{
1014
1015 struct snd_pcm_runtime *runtime = substream->runtime;
1016 struct msm_audio *prtd = runtime->private_data;
1017
1018 if (prtd->pcm_irq_pos >= prtd->pcm_size)
1019 prtd->pcm_irq_pos = 0;
1020
1021 pr_debug("pcm_irq_pos = %d\n", prtd->pcm_irq_pos);
1022 return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
1023}
1024
1025static int msm_pcm_mmap(struct snd_pcm_substream *substream,
1026 struct vm_area_struct *vma)
1027{
1028 struct snd_pcm_runtime *runtime = substream->runtime;
1029 struct msm_audio *prtd = runtime->private_data;
1030 struct audio_client *ac = prtd->audio_client;
1031 struct audio_port_data *apd = ac->port;
1032 struct audio_buffer *ab;
1033 int dir = -1;
1034
1035 prtd->mmap_flag = 1;
1036
1037 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1038 dir = IN;
1039 else
1040 dir = OUT;
1041 ab = &(apd[dir].buf[0]);
1042
1043 return msm_audio_ion_mmap(ab, vma);
1044}
1045
1046static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
1047 struct snd_pcm_hw_params *params)
1048{
1049 struct snd_pcm_runtime *runtime = substream->runtime;
1050 struct msm_audio *prtd = runtime->private_data;
1051 struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
1052 struct audio_buffer *buf;
1053 int dir, ret;
1054
1055 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1056 dir = IN;
1057 else
1058 dir = OUT;
1059 ret = q6asm_audio_client_buf_alloc_contiguous(dir,
1060 prtd->audio_client,
1061 (params_buffer_bytes(params) / params_periods(params)),
1062 params_periods(params));
1063 if (ret < 0) {
1064 pr_err("Audio Start: Buffer Allocation failed rc = %d\n",
1065 ret);
1066 return -ENOMEM;
1067 }
1068 buf = prtd->audio_client->port[dir].buf;
1069 if (buf == NULL || buf[0].data == NULL)
1070 return -ENOMEM;
1071
1072 pr_debug("%s:buf = %pK\n", __func__, buf);
1073 dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
1074 dma_buf->dev.dev = substream->pcm->card->dev;
1075 dma_buf->private_data = NULL;
1076 dma_buf->area = buf[0].data;
1077 dma_buf->addr = buf[0].phys;
1078 dma_buf->bytes = params_buffer_bytes(params);
1079 if (!dma_buf->area)
1080 return -ENOMEM;
1081
1082 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
1083 return 0;
1084}
1085
1086static const struct snd_pcm_ops msm_pcm_ops = {
1087 .open = msm_pcm_open,
Meng Wangac147b72017-10-30 16:46:16 +08001088 .copy_user = msm_pcm_copy,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301089 .hw_params = msm_pcm_hw_params,
1090 .close = msm_pcm_close,
1091 .ioctl = snd_pcm_lib_ioctl,
1092 .prepare = msm_pcm_prepare,
1093 .trigger = msm_pcm_trigger,
1094 .pointer = msm_pcm_pointer,
1095 .mmap = msm_pcm_mmap,
1096};
1097
1098static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
1099 struct snd_ctl_elem_value *ucontrol)
1100{
1101 struct snd_soc_component *pcm = snd_kcontrol_chip(kcontrol);
1102 struct snd_soc_platform *platform = snd_soc_component_to_platform(pcm);
1103 struct msm_plat_data *pdata = dev_get_drvdata(platform->dev);
1104 struct snd_pcm_substream *substream;
1105 struct msm_audio *prtd;
1106 int ret = 0;
1107 struct msm_adsp_event_data *event_data = NULL;
1108
1109 if (!pdata) {
1110 pr_err("%s pdata is NULL\n", __func__);
1111 ret = -ENODEV;
1112 goto done;
1113 }
1114
1115 substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1116 if (!substream) {
1117 pr_err("%s substream not found\n", __func__);
1118 ret = -EINVAL;
1119 goto done;
1120 }
1121
1122 if (!substream->runtime) {
1123 pr_err("%s substream runtime not found\n", __func__);
1124 ret = -EINVAL;
1125 goto done;
1126 }
1127
1128 prtd = substream->runtime->private_data;
1129 if (prtd->audio_client == NULL) {
1130 pr_err("%s prtd is null.\n", __func__);
1131 ret = -EINVAL;
1132 goto done;
1133 }
1134
1135 event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data;
1136 if ((event_data->event_type < ADSP_STREAM_PP_EVENT) ||
1137 (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) {
1138 pr_err("%s: invalid event_type=%d",
1139 __func__, event_data->event_type);
1140 ret = -EINVAL;
1141 goto done;
1142 }
1143
Xiaojun Sang75642c32018-03-23 08:57:33 +08001144 if (event_data->payload_len > sizeof(ucontrol->value.bytes.data)
1145 - sizeof(struct msm_adsp_event_data)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301146 pr_err("%s param length=%d exceeds limit",
1147 __func__, event_data->payload_len);
1148 ret = -EINVAL;
1149 goto done;
1150 }
1151
1152 ret = q6asm_send_stream_cmd(prtd->audio_client, event_data);
1153 if (ret < 0)
1154 pr_err("%s: failed to send stream event cmd, err = %d\n",
1155 __func__, ret);
1156done:
1157 return ret;
1158}
1159
1160static int msm_pcm_add_audio_adsp_stream_cmd_control(
1161 struct snd_soc_pcm_runtime *rtd)
1162{
1163 const char *mixer_ctl_name = DSP_STREAM_CMD;
1164 const char *deviceNo = "NN";
1165 char *mixer_str = NULL;
1166 int ctl_len = 0, ret = 0;
1167 struct snd_kcontrol_new fe_audio_adsp_stream_cmd_config_control[1] = {
1168 {
1169 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1170 .name = "?",
1171 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1172 .info = msm_adsp_stream_cmd_info,
1173 .put = msm_pcm_adsp_stream_cmd_put,
1174 .private_value = 0,
1175 }
1176 };
1177
1178 if (!rtd) {
1179 pr_err("%s rtd is NULL\n", __func__);
1180 ret = -EINVAL;
1181 goto done;
1182 }
1183
1184 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
1185 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
1186 if (!mixer_str) {
1187 ret = -ENOMEM;
1188 goto done;
1189 }
1190
1191 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
1192 fe_audio_adsp_stream_cmd_config_control[0].name = mixer_str;
1193 fe_audio_adsp_stream_cmd_config_control[0].private_value =
1194 rtd->dai_link->id;
1195 pr_debug("Registering new mixer ctl %s\n", mixer_str);
1196 ret = snd_soc_add_platform_controls(rtd->platform,
1197 fe_audio_adsp_stream_cmd_config_control,
1198 ARRAY_SIZE(fe_audio_adsp_stream_cmd_config_control));
1199 if (ret < 0)
1200 pr_err("%s: failed add ctl %s. err = %d\n",
1201 __func__, mixer_str, ret);
1202
1203 kfree(mixer_str);
1204done:
1205 return ret;
1206}
1207
1208static int msm_pcm_add_audio_adsp_stream_callback_control(
1209 struct snd_soc_pcm_runtime *rtd)
1210{
1211 const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
1212 const char *deviceNo = "NN";
1213 char *mixer_str = NULL;
1214 int ctl_len = 0, ret = 0;
1215 struct snd_kcontrol *kctl;
1216
1217 struct snd_kcontrol_new fe_audio_adsp_callback_config_control[1] = {
1218 {
1219 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1220 .name = "?",
1221 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1222 .info = msm_adsp_stream_callback_info,
1223 .get = msm_adsp_stream_callback_get,
1224 .private_value = 0,
1225 }
1226 };
1227
1228 if (!rtd) {
1229 pr_err("%s NULL rtd\n", __func__);
1230 ret = -EINVAL;
1231 goto done;
1232 }
1233
1234 pr_debug("%s: added new pcm FE with name %s, id %d, cpu dai %s, device no %d\n",
1235 __func__, rtd->dai_link->name, rtd->dai_link->id,
1236 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
1237 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
1238 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
1239 if (!mixer_str) {
1240 ret = -ENOMEM;
1241 goto done;
1242 }
1243
1244 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
1245 fe_audio_adsp_callback_config_control[0].name = mixer_str;
1246 fe_audio_adsp_callback_config_control[0].private_value =
1247 rtd->dai_link->id;
1248 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
1249 ret = snd_soc_add_platform_controls(rtd->platform,
1250 fe_audio_adsp_callback_config_control,
1251 ARRAY_SIZE(fe_audio_adsp_callback_config_control));
1252 if (ret < 0) {
1253 pr_err("%s: failed to add ctl %s. err = %d\n",
1254 __func__, mixer_str, ret);
1255 ret = -EINVAL;
1256 goto free_mixer_str;
1257 }
1258
1259 kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
1260 if (!kctl) {
1261 pr_err("%s: failed to get kctl %s.\n", __func__, mixer_str);
1262 ret = -EINVAL;
1263 goto free_mixer_str;
1264 }
1265
1266 kctl->private_data = NULL;
1267
1268free_mixer_str:
1269 kfree(mixer_str);
1270done:
1271 return ret;
1272}
1273
1274static int msm_pcm_set_volume(struct msm_audio *prtd, uint32_t volume)
1275{
1276 int rc = 0;
1277
1278 if (prtd && prtd->audio_client) {
1279 pr_debug("%s: channels %d volume 0x%x\n", __func__,
1280 prtd->channel_mode, volume);
1281 rc = q6asm_set_volume(prtd->audio_client, volume);
1282 if (rc < 0) {
1283 pr_err("%s: Send Volume command failed rc=%d\n",
1284 __func__, rc);
1285 }
1286 }
1287 return rc;
1288}
1289
1290static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol,
1291 struct snd_ctl_elem_value *ucontrol)
1292{
1293 struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
1294 struct snd_pcm_substream *substream =
1295 vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1296 struct msm_audio *prtd;
1297
1298 pr_debug("%s\n", __func__);
1299 if (!substream) {
1300 pr_err("%s substream not found\n", __func__);
1301 return -ENODEV;
1302 }
1303 if (!substream->runtime) {
Vignesh Kulothungan2ce67842018-09-25 16:40:29 -07001304 pr_debug("%s substream runtime not found\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301305 return 0;
1306 }
1307 prtd = substream->runtime->private_data;
1308 if (prtd)
1309 ucontrol->value.integer.value[0] = prtd->volume;
1310 return 0;
1311}
1312
1313static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol,
1314 struct snd_ctl_elem_value *ucontrol)
1315{
1316 int rc = 0;
1317 struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
1318 struct snd_pcm_substream *substream =
1319 vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1320 struct msm_audio *prtd;
1321 int volume = ucontrol->value.integer.value[0];
1322
1323 pr_debug("%s: volume : 0x%x\n", __func__, volume);
1324 if (!substream) {
1325 pr_err("%s substream not found\n", __func__);
1326 return -ENODEV;
1327 }
1328 if (!substream->runtime) {
1329 pr_err("%s substream runtime not found\n", __func__);
1330 return 0;
1331 }
1332 prtd = substream->runtime->private_data;
1333 if (prtd) {
1334 rc = msm_pcm_set_volume(prtd, volume);
1335 prtd->volume = volume;
1336 }
1337 return rc;
1338}
1339
1340static int msm_pcm_add_volume_control(struct snd_soc_pcm_runtime *rtd)
1341{
1342 int ret = 0;
1343 struct snd_pcm *pcm = rtd->pcm;
1344 struct snd_pcm_volume *volume_info;
1345 struct snd_kcontrol *kctl;
1346
1347 dev_dbg(rtd->dev, "%s, Volume control add\n", __func__);
1348 ret = snd_pcm_add_volume_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1349 NULL, 1, rtd->dai_link->id,
1350 &volume_info);
1351 if (ret < 0) {
1352 pr_err("%s volume control failed ret %d\n", __func__, ret);
1353 return ret;
1354 }
1355 kctl = volume_info->kctl;
1356 kctl->put = msm_pcm_volume_ctl_put;
1357 kctl->get = msm_pcm_volume_ctl_get;
1358 kctl->tlv.p = msm_pcm_vol_gain;
1359 return 0;
1360}
1361
1362static int msm_pcm_compress_ctl_info(struct snd_kcontrol *kcontrol,
1363 struct snd_ctl_elem_info *uinfo)
1364{
1365 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1366 uinfo->count = 1;
1367 uinfo->value.integer.min = 0;
1368 uinfo->value.integer.max = 0x2000;
1369 return 0;
1370}
1371
1372static int msm_pcm_compress_ctl_get(struct snd_kcontrol *kcontrol,
1373 struct snd_ctl_elem_value *ucontrol)
1374{
1375 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
1376 struct snd_soc_platform *platform = snd_soc_component_to_platform(comp);
1377 struct msm_plat_data *pdata = dev_get_drvdata(platform->dev);
1378 struct snd_pcm_substream *substream;
1379 struct msm_audio *prtd;
1380
1381 if (!pdata) {
1382 pr_err("%s pdata is NULL\n", __func__);
1383 return -ENODEV;
1384 }
1385 substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1386 if (!substream) {
1387 pr_err("%s substream not found\n", __func__);
1388 return -EINVAL;
1389 }
1390 if (!substream->runtime) {
Vignesh Kulothungan2ce67842018-09-25 16:40:29 -07001391 pr_debug("%s substream runtime not found\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301392 return 0;
1393 }
1394 prtd = substream->runtime->private_data;
1395 if (prtd)
1396 ucontrol->value.integer.value[0] = prtd->compress_enable;
1397 return 0;
1398}
1399
1400static int msm_pcm_compress_ctl_put(struct snd_kcontrol *kcontrol,
1401 struct snd_ctl_elem_value *ucontrol)
1402{
1403 int rc = 0;
1404 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
1405 struct snd_soc_platform *platform = snd_soc_component_to_platform(comp);
1406 struct msm_plat_data *pdata = dev_get_drvdata(platform->dev);
1407 struct snd_pcm_substream *substream;
1408 struct msm_audio *prtd;
1409 int compress = ucontrol->value.integer.value[0];
1410
1411 if (!pdata) {
1412 pr_err("%s pdata is NULL\n", __func__);
1413 return -ENODEV;
1414 }
1415 substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1416 pr_debug("%s: compress : 0x%x\n", __func__, compress);
1417 if (!substream) {
1418 pr_err("%s substream not found\n", __func__);
1419 return -EINVAL;
1420 }
1421 if (!substream->runtime) {
1422 pr_err("%s substream runtime not found\n", __func__);
1423 return 0;
1424 }
1425 prtd = substream->runtime->private_data;
1426 if (prtd) {
1427 pr_debug("%s: setting compress flag to 0x%x\n",
1428 __func__, compress);
1429 prtd->compress_enable = compress;
1430 }
1431 return rc;
1432}
1433
1434static int msm_pcm_add_compress_control(struct snd_soc_pcm_runtime *rtd)
1435{
1436 const char *mixer_ctl_name = "Playback ";
1437 const char *mixer_ctl_end_name = " Compress";
1438 const char *deviceNo = "NN";
1439 char *mixer_str = NULL;
1440 int ctl_len;
1441 int ret = 0;
1442 struct msm_plat_data *pdata;
1443 struct snd_kcontrol_new pcm_compress_control[1] = {
1444 {
1445 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1446 .name = "?",
1447 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1448 .info = msm_pcm_compress_ctl_info,
1449 .get = msm_pcm_compress_ctl_get,
1450 .put = msm_pcm_compress_ctl_put,
1451 .private_value = 0,
1452 }
1453 };
1454
1455 if (!rtd) {
1456 pr_err("%s: NULL rtd\n", __func__);
1457 return -EINVAL;
1458 }
1459
1460 ctl_len = strlen(mixer_ctl_name) + strlen(deviceNo) +
1461 strlen(mixer_ctl_end_name) + 1;
1462 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
1463
1464 if (!mixer_str)
1465 return -ENOMEM;
1466
1467 snprintf(mixer_str, ctl_len, "%s%d%s", mixer_ctl_name,
1468 rtd->pcm->device, mixer_ctl_end_name);
1469
1470 pcm_compress_control[0].name = mixer_str;
1471 pcm_compress_control[0].private_value = rtd->dai_link->id;
1472 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
1473 pdata = dev_get_drvdata(rtd->platform->dev);
1474 if (pdata) {
1475 if (!pdata->pcm) {
1476 pdata->pcm = rtd->pcm;
1477 snd_soc_add_platform_controls(rtd->platform,
1478 pcm_compress_control,
1479 ARRAY_SIZE
1480 (pcm_compress_control));
1481 pr_debug("%s: add control success plt = %pK\n",
1482 __func__, rtd->platform);
1483 }
1484 } else {
1485 pr_err("%s: NULL pdata\n", __func__);
1486 ret = -EINVAL;
1487 }
1488 kfree(mixer_str);
1489 return ret;
1490}
1491
1492static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
1493 struct snd_ctl_elem_value *ucontrol)
1494{
1495 int i;
1496 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
1497 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1498 struct snd_pcm_substream *substream;
1499 struct msm_audio *prtd;
1500
1501 pr_debug("%s", __func__);
1502 substream = snd_pcm_chmap_substream(info, idx);
1503 if (!substream)
1504 return -ENODEV;
1505 if (!substream->runtime)
1506 return 0;
1507
1508 prtd = substream->runtime->private_data;
1509 if (prtd) {
1510 prtd->set_channel_map = true;
1511 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
1512 prtd->channel_map[i] =
1513 (char)(ucontrol->value.integer.value[i]);
1514 }
1515 return 0;
1516}
1517
1518static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
1519 struct snd_ctl_elem_value *ucontrol)
1520{
1521 int i;
1522 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
1523 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1524 struct snd_pcm_substream *substream;
1525 struct msm_audio *prtd;
1526
1527 pr_debug("%s", __func__);
1528 substream = snd_pcm_chmap_substream(info, idx);
1529 if (!substream)
1530 return -ENODEV;
1531 memset(ucontrol->value.integer.value, 0,
1532 sizeof(ucontrol->value.integer.value));
1533 if (!substream->runtime)
1534 return 0; /* no channels set */
1535
1536 prtd = substream->runtime->private_data;
1537
1538 if (prtd && prtd->set_channel_map == true) {
1539 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
1540 ucontrol->value.integer.value[i] =
1541 (int)prtd->channel_map[i];
1542 } else {
1543 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
1544 ucontrol->value.integer.value[i] = 0;
1545 }
1546
1547 return 0;
1548}
1549
1550static int msm_pcm_add_chmap_controls(struct snd_soc_pcm_runtime *rtd)
1551{
1552 struct snd_pcm *pcm = rtd->pcm;
1553 struct snd_pcm_chmap *chmap_info;
1554 struct snd_kcontrol *kctl;
1555 char device_num[12];
1556 int i, ret = 0;
1557
1558 pr_debug("%s, Channel map cntrl add\n", __func__);
1559 ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1560 snd_pcm_std_chmaps,
1561 PCM_FORMAT_MAX_NUM_CHANNEL, 0,
1562 &chmap_info);
1563 if (ret < 0) {
1564 pr_err("%s, channel map cntrl add failed\n", __func__);
1565 return ret;
1566 }
1567 kctl = chmap_info->kctl;
1568 for (i = 0; i < kctl->count; i++)
1569 kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
1570 snprintf(device_num, sizeof(device_num), "%d", pcm->device);
1571 strlcat(kctl->id.name, device_num, sizeof(kctl->id.name));
1572 pr_debug("%s, Overwriting channel map control name to: %s\n",
1573 __func__, kctl->id.name);
1574 kctl->put = msm_pcm_chmap_ctl_put;
1575 kctl->get = msm_pcm_chmap_ctl_get;
1576 return 0;
1577}
1578
1579static int msm_pcm_playback_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
1580 struct snd_ctl_elem_value *ucontrol)
1581{
1582 u64 fe_id = kcontrol->private_value;
1583 int session_type = SESSION_TYPE_RX;
1584 int be_id = ucontrol->value.integer.value[3];
1585 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
1586 int ret = 0;
1587
1588 cfg_data.app_type = ucontrol->value.integer.value[0];
1589 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
1590 if (ucontrol->value.integer.value[2] != 0)
1591 cfg_data.sample_rate = ucontrol->value.integer.value[2];
1592 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
1593 __func__, fe_id, session_type, be_id,
1594 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
1595 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
1596 be_id, &cfg_data);
1597 if (ret < 0)
1598 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
1599 __func__, ret);
1600
1601 return ret;
1602}
1603
1604static int msm_pcm_playback_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
1605 struct snd_ctl_elem_value *ucontrol)
1606{
1607 u64 fe_id = kcontrol->private_value;
1608 int session_type = SESSION_TYPE_RX;
1609 int be_id = 0;
1610 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
1611 int ret = 0;
1612
1613 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
1614 &be_id, &cfg_data);
1615 if (ret < 0) {
1616 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
1617 __func__, ret);
1618 goto done;
1619 }
1620
1621 ucontrol->value.integer.value[0] = cfg_data.app_type;
1622 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
1623 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
1624 ucontrol->value.integer.value[3] = be_id;
1625 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
1626 __func__, fe_id, session_type, be_id,
1627 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
1628done:
1629 return ret;
1630}
1631
1632static int msm_pcm_capture_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
1633 struct snd_ctl_elem_value *ucontrol)
1634{
1635 u64 fe_id = kcontrol->private_value;
1636 int session_type = SESSION_TYPE_TX;
1637 int be_id = ucontrol->value.integer.value[3];
1638 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
1639 int ret = 0;
1640
1641 cfg_data.app_type = ucontrol->value.integer.value[0];
1642 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
1643 if (ucontrol->value.integer.value[2] != 0)
1644 cfg_data.sample_rate = ucontrol->value.integer.value[2];
1645 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
1646 __func__, fe_id, session_type, be_id,
1647 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
1648 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
1649 be_id, &cfg_data);
1650 if (ret < 0)
1651 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
1652 __func__, ret);
1653
1654 return ret;
1655}
1656
1657static int msm_pcm_capture_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
1658 struct snd_ctl_elem_value *ucontrol)
1659{
1660 u64 fe_id = kcontrol->private_value;
1661 int session_type = SESSION_TYPE_TX;
1662 int be_id = 0;
1663 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
1664 int ret = 0;
1665
1666 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
1667 &be_id, &cfg_data);
1668 if (ret < 0) {
1669 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
1670 __func__, ret);
1671 goto done;
1672 }
1673
1674 ucontrol->value.integer.value[0] = cfg_data.app_type;
1675 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
1676 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
1677 ucontrol->value.integer.value[3] = be_id;
1678 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
1679 __func__, fe_id, session_type, be_id,
1680 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
1681done:
1682 return ret;
1683}
1684
1685static int msm_pcm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd)
1686{
1687 struct snd_pcm *pcm = rtd->pcm;
1688 struct snd_pcm_usr *app_type_info;
1689 struct snd_kcontrol *kctl;
1690 const char *playback_mixer_ctl_name = "Audio Stream";
1691 const char *capture_mixer_ctl_name = "Audio Stream Capture";
1692 const char *deviceNo = "NN";
1693 const char *suffix = "App Type Cfg";
1694 int ctl_len, ret = 0;
1695
1696 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
1697 ctl_len = strlen(playback_mixer_ctl_name) + 1 +
1698 strlen(deviceNo) + 1 + strlen(suffix) + 1;
1699 pr_debug("%s: Playback app type cntrl add\n", __func__);
1700 ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1701 NULL, 1, ctl_len, rtd->dai_link->id,
1702 &app_type_info);
1703 if (ret < 0) {
1704 pr_err("%s: playback app type cntrl add failed: %d\n",
1705 __func__, ret);
1706 return ret;
1707 }
1708 kctl = app_type_info->kctl;
1709 snprintf(kctl->id.name, ctl_len, "%s %d %s",
1710 playback_mixer_ctl_name, rtd->pcm->device, suffix);
1711 kctl->put = msm_pcm_playback_app_type_cfg_ctl_put;
1712 kctl->get = msm_pcm_playback_app_type_cfg_ctl_get;
1713 }
1714
1715 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
1716 ctl_len = strlen(capture_mixer_ctl_name) + 1 +
1717 strlen(deviceNo) + 1 + strlen(suffix) + 1;
1718 pr_debug("%s: Capture app type cntrl add\n", __func__);
1719 ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE,
1720 NULL, 1, ctl_len, rtd->dai_link->id,
1721 &app_type_info);
1722 if (ret < 0) {
1723 pr_err("%s: capture app type cntrl add failed: %d\n",
1724 __func__, ret);
1725 return ret;
1726 }
1727 kctl = app_type_info->kctl;
1728 snprintf(kctl->id.name, ctl_len, "%s %d %s",
1729 capture_mixer_ctl_name, rtd->pcm->device, suffix);
1730 kctl->put = msm_pcm_capture_app_type_cfg_ctl_put;
1731 kctl->get = msm_pcm_capture_app_type_cfg_ctl_get;
1732 }
1733
1734 return 0;
1735}
1736
1737static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd)
1738{
1739 int ret = 0;
1740
1741 pr_debug("%s\n", __func__);
1742 ret = msm_pcm_add_chmap_controls(rtd);
1743 if (ret)
1744 pr_err("%s: pcm add controls failed:%d\n", __func__, ret);
1745 ret = msm_pcm_add_app_type_controls(rtd);
1746 if (ret)
1747 pr_err("%s: pcm add app type controls failed:%d\n",
1748 __func__, ret);
1749 return ret;
1750}
1751
1752static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
1753{
1754 struct snd_card *card = rtd->card->snd_card;
1755 int ret = 0;
1756
1757 if (!card->dev->coherent_dma_mask)
1758 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
1759
1760 ret = msm_pcm_add_controls(rtd);
1761 if (ret) {
1762 pr_err("%s, kctl add failed:%d\n", __func__, ret);
1763 return ret;
1764 }
1765
1766 ret = msm_pcm_add_volume_control(rtd);
1767 if (ret)
1768 pr_err("%s: Could not add pcm Volume Control %d\n",
1769 __func__, ret);
1770
1771 ret = msm_pcm_add_compress_control(rtd);
1772 if (ret)
1773 pr_err("%s: Could not add pcm Compress Control %d\n",
1774 __func__, ret);
1775
1776 ret = msm_pcm_add_audio_adsp_stream_cmd_control(rtd);
1777 if (ret)
1778 pr_err("%s: Could not add pcm ADSP Stream Cmd Control\n",
1779 __func__);
1780
1781 ret = msm_pcm_add_audio_adsp_stream_callback_control(rtd);
1782 if (ret)
1783 pr_err("%s: Could not add pcm ADSP Stream Callback Control\n",
1784 __func__);
1785
1786 return ret;
1787}
1788
1789static snd_pcm_sframes_t msm_pcm_delay_blk(struct snd_pcm_substream *substream,
1790 struct snd_soc_dai *dai)
1791{
1792 struct snd_pcm_runtime *runtime = substream->runtime;
1793 struct msm_audio *prtd = runtime->private_data;
1794 struct audio_client *ac = prtd->audio_client;
1795 snd_pcm_sframes_t frames;
1796 int ret;
1797
1798 ret = q6asm_get_path_delay(prtd->audio_client);
1799 if (ret) {
1800 pr_err("%s: get_path_delay failed, ret=%d\n", __func__, ret);
1801 return 0;
1802 }
1803
1804 /* convert microseconds to frames */
1805 frames = ac->path_delay / 1000 * runtime->rate / 1000;
1806
1807 /* also convert the remainder from the initial division */
1808 frames += ac->path_delay % 1000 * runtime->rate / 1000000;
1809
1810 /* overcompensate for the loss of precision (empirical) */
1811 frames += 2;
1812
1813 return frames;
1814}
1815
1816static struct snd_soc_platform_driver msm_soc_platform = {
1817 .ops = &msm_pcm_ops,
1818 .pcm_new = msm_asoc_pcm_new,
1819 .delay_blk = msm_pcm_delay_blk,
1820};
1821
1822static int msm_pcm_probe(struct platform_device *pdev)
1823{
1824 int rc;
1825 int id;
1826 struct msm_plat_data *pdata;
1827 const char *latency_level;
1828
1829 rc = of_property_read_u32(pdev->dev.of_node,
1830 "qcom,msm-pcm-dsp-id", &id);
1831 if (rc) {
1832 dev_err(&pdev->dev, "%s: qcom,msm-pcm-dsp-id missing in DT node\n",
1833 __func__);
1834 return rc;
1835 }
1836
1837 pdata = kzalloc(sizeof(struct msm_plat_data), GFP_KERNEL);
1838 if (!pdata)
1839 return -ENOMEM;
1840
1841 if (of_property_read_bool(pdev->dev.of_node,
1842 "qcom,msm-pcm-low-latency")) {
1843
1844 pdata->perf_mode = LOW_LATENCY_PCM_MODE;
1845 rc = of_property_read_string(pdev->dev.of_node,
1846 "qcom,latency-level", &latency_level);
1847 if (!rc) {
1848 if (!strcmp(latency_level, "ultra"))
1849 pdata->perf_mode = ULTRA_LOW_LATENCY_PCM_MODE;
1850 else if (!strcmp(latency_level, "ull-pp"))
1851 pdata->perf_mode =
1852 ULL_POST_PROCESSING_PCM_MODE;
1853 }
1854 } else {
1855 pdata->perf_mode = LEGACY_PCM_MODE;
1856 }
1857
1858 dev_set_drvdata(&pdev->dev, pdata);
1859
1860
1861 dev_dbg(&pdev->dev, "%s: dev name %s\n",
1862 __func__, dev_name(&pdev->dev));
1863 return snd_soc_register_platform(&pdev->dev,
1864 &msm_soc_platform);
1865}
1866
1867static int msm_pcm_remove(struct platform_device *pdev)
1868{
1869 struct msm_plat_data *pdata;
1870
1871 pdata = dev_get_drvdata(&pdev->dev);
1872 kfree(pdata);
1873 snd_soc_unregister_platform(&pdev->dev);
1874 return 0;
1875}
1876static const struct of_device_id msm_pcm_dt_match[] = {
1877 {.compatible = "qcom,msm-pcm-dsp"},
1878 {}
1879};
1880MODULE_DEVICE_TABLE(of, msm_pcm_dt_match);
1881
1882static struct platform_driver msm_pcm_driver = {
1883 .driver = {
1884 .name = "msm-pcm-dsp",
1885 .owner = THIS_MODULE,
1886 .of_match_table = msm_pcm_dt_match,
1887 },
1888 .probe = msm_pcm_probe,
1889 .remove = msm_pcm_remove,
1890};
1891
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301892int __init msm_pcm_dsp_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301893{
1894 init_waitqueue_head(&the_locks.enable_wait);
1895 init_waitqueue_head(&the_locks.eos_wait);
1896 init_waitqueue_head(&the_locks.write_wait);
1897 init_waitqueue_head(&the_locks.read_wait);
1898
1899 return platform_driver_register(&msm_pcm_driver);
1900}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301901
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05301902void msm_pcm_dsp_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301903{
1904 platform_driver_unregister(&msm_pcm_driver);
1905}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301906
1907MODULE_DESCRIPTION("PCM module platform driver");
1908MODULE_LICENSE("GPL v2");