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