blob: 3cacfc0589b54c7c6e8d1239d2e4f13ff8482157 [file] [log] [blame]
Ajit Pandey9a5480e2019-10-24 13:45:11 +05301/* Copyright (c) 2012-2020, 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/math64.h>
20#include <linux/wait.h>
Ajit Pandey233bdea2019-09-04 14:34:00 +053021#include <linux/mutex.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053022#include <linux/platform_device.h>
23#include <linux/slab.h>
24#include <sound/core.h>
25#include <sound/soc.h>
26#include <sound/soc-dapm.h>
27#include <sound/pcm.h>
28#include <sound/initval.h>
29#include <sound/control.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053030#include <sound/pcm_params.h>
31#include <sound/audio_effects.h>
32#include <asm/dma.h>
33#include <linux/dma-mapping.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053034#include <linux/msm_audio.h>
35
36#include <sound/timer.h>
37#include <sound/tlv.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053038#include <sound/compress_params.h>
39#include <sound/compress_offload.h>
40#include <sound/compress_driver.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053041
42#include <dsp/msm_audio_ion.h>
43#include <dsp/apr_audio-v2.h>
44#include <dsp/q6asm-v2.h>
Dieter Lueckingba7644d2018-09-28 15:09:32 +020045#include <dsp/q6core.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053046#include <dsp/msm-audio-effects-q6-v2.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053047#include "msm-pcm-routing-v2.h"
48#include "msm-qti-pp-config.h"
49
50#define DSP_PP_BUFFERING_IN_MSEC 25
51#define PARTIAL_DRAIN_ACK_EARLY_BY_MSEC 150
52#define MP3_OUTPUT_FRAME_SZ 1152
53#define AAC_OUTPUT_FRAME_SZ 1024
54#define AC3_OUTPUT_FRAME_SZ 1536
55#define EAC3_OUTPUT_FRAME_SZ 1536
56#define DSP_NUM_OUTPUT_FRAME_BUFFERED 2
57#define FLAC_BLK_SIZE_LIMIT 65535
58
59/* Timestamp mode payload offsets */
60#define CAPTURE_META_DATA_TS_OFFSET_LSW 6
61#define CAPTURE_META_DATA_TS_OFFSET_MSW 7
62
63/* decoder parameter length */
64#define DDP_DEC_MAX_NUM_PARAM 18
65
66/* Default values used if user space does not set */
67#define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024)
68#define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
69#define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4)
70#define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4)
71
72#define COMPRESSED_LR_VOL_MAX_STEPS 0x2000
73const DECLARE_TLV_DB_LINEAR(msm_compr_vol_gain, 0,
74 COMPRESSED_LR_VOL_MAX_STEPS);
75
76/* Stream id switches between 1 and 2 */
77#define NEXT_STREAM_ID(stream_id) ((stream_id & 1) + 1)
78
79#define STREAM_ARRAY_INDEX(stream_id) (stream_id - 1)
80
81#define MAX_NUMBER_OF_STREAMS 2
82
83struct msm_compr_gapless_state {
84 bool set_next_stream_id;
85 int32_t stream_opened[MAX_NUMBER_OF_STREAMS];
86 uint32_t initial_samples_drop;
87 uint32_t trailing_samples_drop;
88 uint32_t gapless_transition;
89 bool use_dsp_gapless_mode;
90 union snd_codec_options codec_options;
91};
92
93static unsigned int supported_sample_rates[] = {
94 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000,
95 88200, 96000, 128000, 144000, 176400, 192000, 352800, 384000, 2822400,
96 5644800
97};
98
99struct msm_compr_pdata {
100 struct snd_compr_stream *cstream[MSM_FRONTEND_DAI_MAX];
101 uint32_t volume[MSM_FRONTEND_DAI_MAX][2]; /* For both L & R */
102 struct msm_compr_audio_effects *audio_effects[MSM_FRONTEND_DAI_MAX];
103 bool use_dsp_gapless_mode;
104 bool use_legacy_api; /* indicates use older asm apis*/
105 struct msm_compr_dec_params *dec_params[MSM_FRONTEND_DAI_MAX];
106 struct msm_compr_ch_map *ch_map[MSM_FRONTEND_DAI_MAX];
Aditya Bavanari9deef912017-11-20 13:31:31 +0530107 bool is_in_use[MSM_FRONTEND_DAI_MAX];
Ajit Pandey233bdea2019-09-04 14:34:00 +0530108 struct mutex lock;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530109};
110
111struct msm_compr_audio {
112 struct snd_compr_stream *cstream;
113 struct snd_compr_caps compr_cap;
114 struct snd_compr_codec_caps codec_caps;
115 struct snd_compr_params codec_param;
116 struct audio_client *audio_client;
117
118 uint32_t codec;
119 uint32_t compr_passthr;
120 void *buffer; /* virtual address */
121 phys_addr_t buffer_paddr; /* physical address */
122 uint32_t app_pointer;
123 uint32_t buffer_size;
124 uint32_t byte_offset;
125 uint64_t copied_total; /* bytes consumed by DSP */
126 uint64_t bytes_received; /* from userspace */
127 uint64_t bytes_sent; /* to DSP */
128
129 uint64_t received_total; /* bytes received from DSP */
130 uint64_t bytes_copied; /* to userspace */
131 uint64_t bytes_read; /* from DSP */
132 uint32_t bytes_read_offset; /* bytes read offset */
133
134 uint32_t ts_header_offset; /* holds the timestamp header offset */
135
136 int32_t first_buffer;
137 int32_t last_buffer;
138 int32_t partial_drain_delay;
139
140 uint16_t session_id;
141
142 uint32_t sample_rate;
143 uint32_t num_channels;
144
145 /*
146 * convention - commands coming from the same thread
147 * can use the common cmd_ack var. Others (e.g drain/EOS)
148 * must use separate vars to track command status.
149 */
150 uint32_t cmd_ack;
151 uint32_t cmd_interrupt;
152 uint32_t drain_ready;
153 uint32_t eos_ack;
154
155 uint32_t stream_available;
156 uint32_t next_stream;
157
158 uint32_t run_mode;
159 uint32_t start_delay_lsw;
160 uint32_t start_delay_msw;
161
162 uint64_t marker_timestamp;
163
164 struct msm_compr_gapless_state gapless_state;
165
166 atomic_t start;
167 atomic_t eos;
168 atomic_t drain;
169 atomic_t xrun;
170 atomic_t close;
171 atomic_t wait_on_close;
172 atomic_t error;
173
174 wait_queue_head_t eos_wait;
175 wait_queue_head_t drain_wait;
176 wait_queue_head_t close_wait;
177 wait_queue_head_t wait_for_stream_avail;
178
179 spinlock_t lock;
180};
181
182const u32 compr_codecs[] = {
183 SND_AUDIOCODEC_AC3, SND_AUDIOCODEC_EAC3, SND_AUDIOCODEC_DTS,
184 SND_AUDIOCODEC_DSD, SND_AUDIOCODEC_TRUEHD, SND_AUDIOCODEC_IEC61937};
185
186struct query_audio_effect {
187 uint32_t mod_id;
188 uint32_t parm_id;
189 uint32_t size;
190 uint32_t offset;
191 uint32_t device;
192};
193
194struct msm_compr_audio_effects {
195 struct bass_boost_params bass_boost;
196 struct pbe_params pbe;
197 struct virtualizer_params virtualizer;
198 struct reverb_params reverb;
199 struct eq_params equalizer;
200 struct soft_volume_params volume;
201 struct query_audio_effect query;
202};
203
204struct msm_compr_dec_params {
205 struct snd_dec_ddp ddp_params;
206};
207
208struct msm_compr_ch_map {
209 bool set_ch_map;
Dieter Lueckingba7644d2018-09-28 15:09:32 +0200210 char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530211};
212
213static int msm_compr_send_dec_params(struct snd_compr_stream *cstream,
214 struct msm_compr_dec_params *dec_params,
215 int stream_id);
216
217static int msm_compr_set_render_mode(struct msm_compr_audio *prtd,
218 uint32_t render_mode) {
219 int ret = -EINVAL;
220 struct audio_client *ac = prtd->audio_client;
221
222 pr_debug("%s, got render mode %u\n", __func__, render_mode);
223
224 if (render_mode == SNDRV_COMPRESS_RENDER_MODE_AUDIO_MASTER) {
225 render_mode = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT;
226 } else if (render_mode == SNDRV_COMPRESS_RENDER_MODE_STC_MASTER) {
227 render_mode = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC;
228 prtd->run_mode = ASM_SESSION_CMD_RUN_STARTIME_RUN_WITH_DELAY;
229 } else {
230 pr_err("%s, Invalid render mode %u\n", __func__,
231 render_mode);
232 ret = -EINVAL;
233 goto exit;
234 }
235
236 ret = q6asm_send_mtmx_strtr_render_mode(ac, render_mode);
237 if (ret) {
238 pr_err("%s, Render mode can't be set error %d\n", __func__,
239 ret);
240 }
241exit:
242 return ret;
243}
244
245static int msm_compr_set_clk_rec_mode(struct audio_client *ac,
246 uint32_t clk_rec_mode) {
247 int ret = -EINVAL;
248
249 pr_debug("%s, got clk rec mode %u\n", __func__, clk_rec_mode);
250
251 if (clk_rec_mode == SNDRV_COMPRESS_CLK_REC_MODE_NONE) {
252 clk_rec_mode = ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_NONE;
253 } else if (clk_rec_mode == SNDRV_COMPRESS_CLK_REC_MODE_AUTO) {
254 clk_rec_mode = ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_AUTO;
255 } else {
256 pr_err("%s, Invalid clk rec_mode mode %u\n", __func__,
257 clk_rec_mode);
258 ret = -EINVAL;
259 goto exit;
260 }
261
262 ret = q6asm_send_mtmx_strtr_clk_rec_mode(ac, clk_rec_mode);
263 if (ret) {
264 pr_err("%s, clk rec mode can't be set, error %d\n", __func__,
265 ret);
266 }
267
268exit:
269 return ret;
270}
271
272static int msm_compr_set_render_window(struct audio_client *ac,
273 uint32_t ws_lsw, uint32_t ws_msw,
274 uint32_t we_lsw, uint32_t we_msw)
275{
276 int ret = -EINVAL;
277 struct asm_session_mtmx_strtr_param_window_v2_t asm_mtmx_strtr_window;
278 uint32_t param_id;
279
280 pr_debug("%s, ws_lsw 0x%x ws_msw 0x%x we_lsw 0x%x we_ms 0x%x\n",
281 __func__, ws_lsw, ws_msw, we_lsw, we_msw);
282
283 memset(&asm_mtmx_strtr_window, 0,
284 sizeof(struct asm_session_mtmx_strtr_param_window_v2_t));
285 asm_mtmx_strtr_window.window_lsw = ws_lsw;
286 asm_mtmx_strtr_window.window_msw = ws_msw;
287 param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_WINDOW_START_V2;
288 ret = q6asm_send_mtmx_strtr_window(ac, &asm_mtmx_strtr_window,
289 param_id);
290 if (ret) {
291 pr_err("%s, start window can't be set error %d\n", __func__,
292 ret);
293 goto exit;
294 }
295
296 asm_mtmx_strtr_window.window_lsw = we_lsw;
297 asm_mtmx_strtr_window.window_msw = we_msw;
298 param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_WINDOW_END_V2;
299 ret = q6asm_send_mtmx_strtr_window(ac, &asm_mtmx_strtr_window,
300 param_id);
301 if (ret) {
302 pr_err("%s, end window can't be set error %d\n", __func__,
303 ret);
304 }
305
306exit:
307 return ret;
308}
309
310static int msm_compr_enable_adjust_session_clock(struct audio_client *ac,
311 bool enable)
312{
313 int ret;
314
315 pr_debug("%s, enable adjust_session %d\n", __func__, enable);
316
317 ret = q6asm_send_mtmx_strtr_enable_adjust_session_clock(ac, enable);
318 if (ret)
319 pr_err("%s, adjust session clock can't be set error %d\n",
320 __func__, ret);
321
322 return ret;
323}
324
325static int msm_compr_adjust_session_clock(struct audio_client *ac,
326 uint32_t adjust_session_lsw, uint32_t adjust_session_msw)
327{
328 int ret;
329
330 pr_debug("%s, adjust_session_time_msw 0x%x adjust_session_time_lsw 0x%x\n",
331 __func__, adjust_session_msw, adjust_session_lsw);
332
333 ret = q6asm_adjust_session_clock(ac,
334 adjust_session_lsw,
335 adjust_session_msw);
336 if (ret)
337 pr_err("%s, adjust session clock can't be set error %d\n",
338 __func__, ret);
339
340 return ret;
341}
342
343static int msm_compr_set_volume(struct snd_compr_stream *cstream,
344 uint32_t volume_l, uint32_t volume_r)
345{
346 struct msm_compr_audio *prtd;
347 int rc = 0;
348 uint32_t avg_vol, gain_list[VOLUME_CONTROL_MAX_CHANNELS];
349 uint32_t num_channels;
350 struct snd_soc_pcm_runtime *rtd;
351 struct msm_compr_pdata *pdata;
352 bool use_default = true;
353 u8 *chmap = NULL;
354
355 pr_debug("%s: volume_l %d volume_r %d\n",
356 __func__, volume_l, volume_r);
357 if (!cstream || !cstream->runtime) {
358 pr_err("%s: session not active\n", __func__);
359 return -EPERM;
360 }
361 rtd = cstream->private_data;
362 prtd = cstream->runtime->private_data;
363
364 if (!rtd || !rtd->platform || !prtd || !prtd->audio_client) {
365 pr_err("%s: invalid rtd, prtd or audio client", __func__);
366 return rc;
367 }
368 pdata = snd_soc_platform_get_drvdata(rtd->platform);
369
370 if (prtd->compr_passthr != LEGACY_PCM) {
371 pr_debug("%s: No volume config for passthrough %d\n",
372 __func__, prtd->compr_passthr);
373 return rc;
374 }
375
376 use_default = !(pdata->ch_map[rtd->dai_link->id]->set_ch_map);
377 chmap = pdata->ch_map[rtd->dai_link->id]->channel_map;
378 num_channels = prtd->num_channels;
379
380 if (prtd->num_channels > 2) {
381 /*
382 * Currently the left and right gains are averaged an applied
383 * to all channels. This might not be desirable. But currently,
384 * there exists no API in userspace to send a list of gains for
385 * each channel either. If such an API does become available,
386 * the mixer control must be updated to accept more than 2
387 * channel gains.
388 *
389 */
390 avg_vol = (volume_l + volume_r) / 2;
391 rc = q6asm_set_volume(prtd->audio_client, avg_vol);
392 } else {
393 gain_list[0] = volume_l;
394 gain_list[1] = volume_r;
yidongh98526ef2017-09-05 17:57:55 +0800395 gain_list[2] = volume_l;
396 num_channels = 3;
397 use_default = true;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530398 rc = q6asm_set_multich_gain(prtd->audio_client, num_channels,
399 gain_list, chmap, use_default);
400 }
401
402 if (rc < 0)
403 pr_err("%s: Send vol gain command failed rc=%d\n",
404 __func__, rc);
405
406 return rc;
407}
408
409static int msm_compr_send_ddp_cfg(struct audio_client *ac,
410 struct snd_dec_ddp *ddp,
411 int stream_id)
412{
413 int i, rc;
414
415 pr_debug("%s\n", __func__);
416 for (i = 0; i < ddp->params_length; i++) {
417 rc = q6asm_ds1_set_stream_endp_params(ac, ddp->params_id[i],
418 ddp->params_value[i],
419 stream_id);
420 if (rc) {
421 pr_err("sending params_id: %d failed\n",
422 ddp->params_id[i]);
423 return rc;
424 }
425 }
426 return 0;
427}
428
429static int msm_compr_send_buffer(struct msm_compr_audio *prtd)
430{
431 int buffer_length;
432 uint64_t bytes_available;
433 struct audio_aio_write_param param;
434 struct snd_codec_metadata *buff_addr;
435
436 if (!atomic_read(&prtd->start)) {
437 pr_err("%s: stream is not in started state\n", __func__);
438 return -EINVAL;
439 }
440
441
442 if (atomic_read(&prtd->xrun)) {
443 WARN(1, "%s called while xrun is true", __func__);
444 return -EPERM;
445 }
446
447 pr_debug("%s: bytes_received = %llu copied_total = %llu\n",
448 __func__, prtd->bytes_received, prtd->copied_total);
449 if (prtd->first_buffer && prtd->gapless_state.use_dsp_gapless_mode &&
450 prtd->compr_passthr == LEGACY_PCM)
451 q6asm_stream_send_meta_data(prtd->audio_client,
452 prtd->audio_client->stream_id,
453 prtd->gapless_state.initial_samples_drop,
454 prtd->gapless_state.trailing_samples_drop);
455
456 buffer_length = prtd->codec_param.buffer.fragment_size;
457 bytes_available = prtd->bytes_received - prtd->copied_total;
458 if (bytes_available < prtd->codec_param.buffer.fragment_size)
459 buffer_length = bytes_available;
460
461 if (prtd->byte_offset + buffer_length > prtd->buffer_size) {
462 buffer_length = (prtd->buffer_size - prtd->byte_offset);
463 pr_debug("%s: wrap around situation, send partial data %d now",
464 __func__, buffer_length);
465 }
466
467 if (buffer_length) {
468 param.paddr = prtd->buffer_paddr + prtd->byte_offset;
469 WARN(prtd->byte_offset % 32 != 0, "offset %x not multiple of 32\n",
470 prtd->byte_offset);
471 } else {
472 param.paddr = prtd->buffer_paddr;
473 }
474 param.len = buffer_length;
475 if (prtd->ts_header_offset) {
476 buff_addr = (struct snd_codec_metadata *)
477 (prtd->buffer + prtd->byte_offset);
478 param.len = buff_addr->length;
479 param.msw_ts = (uint32_t)
480 ((buff_addr->timestamp & 0xFFFFFFFF00000000LL) >> 32);
481 param.lsw_ts = (uint32_t) (buff_addr->timestamp & 0xFFFFFFFFLL);
482 param.paddr += prtd->ts_header_offset;
483 param.flags = SET_TIMESTAMP;
484 param.metadata_len = prtd->ts_header_offset;
485 } else {
486 param.msw_ts = 0;
487 param.lsw_ts = 0;
488 param.flags = NO_TIMESTAMP;
489 param.metadata_len = 0;
490 }
491 param.uid = buffer_length;
492 param.last_buffer = prtd->last_buffer;
493
494 pr_debug("%s: sending %d bytes to DSP byte_offset = %d\n",
495 __func__, param.len, prtd->byte_offset);
496 if (q6asm_async_write(prtd->audio_client, &param) < 0) {
497 pr_err("%s:q6asm_async_write failed\n", __func__);
498 } else {
499 prtd->bytes_sent += buffer_length;
500 if (prtd->first_buffer)
501 prtd->first_buffer = 0;
502 }
503
504 return 0;
505}
506
507static int msm_compr_read_buffer(struct msm_compr_audio *prtd)
508{
509 int buffer_length;
510 uint64_t bytes_available;
511 uint64_t buffer_sent;
512 struct audio_aio_read_param param;
513 int ret;
514
515 if (!atomic_read(&prtd->start)) {
516 pr_err("%s: stream is not in started state\n", __func__);
517 return -EINVAL;
518 }
519
520 buffer_length = prtd->codec_param.buffer.fragment_size -
521 prtd->ts_header_offset;
522 bytes_available = prtd->received_total - prtd->bytes_copied;
523 buffer_sent = prtd->bytes_read - prtd->bytes_copied;
524 if (buffer_sent + buffer_length + prtd->ts_header_offset
525 > prtd->buffer_size) {
526 pr_debug(" %s : Buffer is Full bytes_available: %llu\n",
527 __func__, bytes_available);
528 return 0;
529 }
530
531 memset(&param, 0x0, sizeof(struct audio_aio_read_param));
532 param.paddr = prtd->buffer_paddr + prtd->bytes_read_offset +
533 prtd->ts_header_offset;
534 param.len = buffer_length;
535 param.uid = buffer_length;
536 param.flags = prtd->codec_param.codec.flags;
537
538 pr_debug("%s: reading %d bytes from DSP byte_offset = %llu\n",
539 __func__, buffer_length, prtd->bytes_read);
540 ret = q6asm_async_read(prtd->audio_client, &param);
541 if (ret < 0) {
542 pr_err("%s: q6asm_async_read failed - %d\n",
543 __func__, ret);
544 return ret;
545 }
Sachin Mohan Gadag3a52de72018-07-05 15:48:12 +0530546 prtd->bytes_read += buffer_length + prtd->ts_header_offset;
Vikram Panduranga40b0ec62018-01-10 18:04:54 -0800547 prtd->bytes_read_offset += buffer_length + prtd->ts_header_offset;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530548 if (prtd->bytes_read_offset >= prtd->buffer_size)
549 prtd->bytes_read_offset -= prtd->buffer_size;
550
551 return 0;
552}
553
554static void compr_event_handler(uint32_t opcode,
555 uint32_t token, uint32_t *payload, void *priv)
556{
557 struct msm_compr_audio *prtd = priv;
558 struct snd_compr_stream *cstream;
559 struct audio_client *ac;
560 uint32_t chan_mode = 0;
561 uint32_t sample_rate = 0;
562 uint64_t bytes_available;
563 int stream_id;
564 uint32_t stream_index;
565 unsigned long flags;
566 uint64_t read_size;
567 uint32_t *buff_addr;
568 struct snd_soc_pcm_runtime *rtd;
569 int ret = 0;
570
571 if (!prtd) {
572 pr_err("%s: prtd is NULL\n", __func__);
573 return;
574 }
575 cstream = prtd->cstream;
576 if (!cstream) {
577 pr_err("%s: cstream is NULL\n", __func__);
578 return;
579 }
580
581 ac = prtd->audio_client;
582
583 /*
584 * Token for rest of the compressed commands use to set
585 * session id, stream id, dir etc.
586 */
587 stream_id = q6asm_get_stream_id_from_token(token);
588
589 pr_debug("%s opcode =%08x\n", __func__, opcode);
590 switch (opcode) {
591 case ASM_DATA_EVENT_WRITE_DONE_V2:
592 spin_lock_irqsave(&prtd->lock, flags);
593
594 if (payload[3]) {
595 pr_err("%s: WRITE FAILED w/ err 0x%x !, paddr 0x%x, byte_offset=%d,copied_total=%llu,token=%d\n",
596 __func__,
597 payload[3],
598 payload[0],
599 prtd->byte_offset,
600 prtd->copied_total, token);
601
602 if (atomic_cmpxchg(&prtd->drain, 1, 0) &&
603 prtd->last_buffer) {
604 pr_debug("%s: wake up on drain\n", __func__);
605 prtd->drain_ready = 1;
606 wake_up(&prtd->drain_wait);
607 prtd->last_buffer = 0;
608 } else {
609 atomic_set(&prtd->start, 0);
610 }
611 } else {
612 pr_debug("ASM_DATA_EVENT_WRITE_DONE_V2 offset %d, length %d\n",
613 prtd->byte_offset, token);
614 }
615
616 /*
617 * Token for WRITE command represents the amount of data
618 * written to ADSP in the last write, update offset and
619 * total copied data accordingly.
620 */
621 if (prtd->ts_header_offset) {
622 /* Always assume that the data will be sent to DSP on
623 * frame boundary.
624 * i.e, one frame of userspace write will result in
625 * one kernel write to DSP. This is needed as
626 * timestamp will be sent per frame.
627 */
628 prtd->byte_offset +=
629 prtd->codec_param.buffer.fragment_size;
630 prtd->copied_total +=
631 prtd->codec_param.buffer.fragment_size;
632 } else {
633 prtd->byte_offset += token;
634 prtd->copied_total += token;
635 }
636 if (prtd->byte_offset >= prtd->buffer_size)
637 prtd->byte_offset -= prtd->buffer_size;
638
639 snd_compr_fragment_elapsed(cstream);
640
641 if (!atomic_read(&prtd->start)) {
642 /* Writes must be restarted from _copy() */
643 pr_debug("write_done received while not started, treat as xrun");
644 atomic_set(&prtd->xrun, 1);
645 spin_unlock_irqrestore(&prtd->lock, flags);
646 break;
647 }
648
649 bytes_available = prtd->bytes_received - prtd->copied_total;
650 if (bytes_available < cstream->runtime->fragment_size) {
651 pr_debug("WRITE_DONE Insufficient data to send. break out\n");
652 atomic_set(&prtd->xrun, 1);
653
654 if (prtd->last_buffer)
655 prtd->last_buffer = 0;
656 if (atomic_read(&prtd->drain)) {
657 pr_debug("wake up on drain\n");
658 prtd->drain_ready = 1;
659 wake_up(&prtd->drain_wait);
660 atomic_set(&prtd->drain, 0);
661 }
662 } else if ((bytes_available == cstream->runtime->fragment_size)
663 && atomic_read(&prtd->drain)) {
664 prtd->last_buffer = 1;
665 msm_compr_send_buffer(prtd);
666 prtd->last_buffer = 0;
667 } else
668 msm_compr_send_buffer(prtd);
669
670 spin_unlock_irqrestore(&prtd->lock, flags);
671 break;
672
673 case ASM_DATA_EVENT_READ_DONE_V2:
674 spin_lock_irqsave(&prtd->lock, flags);
675
676 pr_debug("ASM_DATA_EVENT_READ_DONE_V2 offset %d, length %d\n",
677 prtd->byte_offset, payload[4]);
678
679 if (prtd->ts_header_offset) {
680 /* Update the header for received buffer */
681 buff_addr = prtd->buffer + prtd->byte_offset;
682 /* Write the length of the buffer */
683 *buff_addr = prtd->codec_param.buffer.fragment_size
684 - prtd->ts_header_offset;
685 buff_addr++;
686 /* Write the offset */
687 *buff_addr = prtd->ts_header_offset;
688 buff_addr++;
689 /* Write the TS LSW */
690 *buff_addr = payload[CAPTURE_META_DATA_TS_OFFSET_LSW];
691 buff_addr++;
692 /* Write the TS MSW */
693 *buff_addr = payload[CAPTURE_META_DATA_TS_OFFSET_MSW];
694 }
695 /* Always assume read_size is same as fragment_size */
696 read_size = prtd->codec_param.buffer.fragment_size;
697 prtd->byte_offset += read_size;
698 prtd->received_total += read_size;
699 if (prtd->byte_offset >= prtd->buffer_size)
700 prtd->byte_offset -= prtd->buffer_size;
701
702 snd_compr_fragment_elapsed(cstream);
703
704 if (!atomic_read(&prtd->start)) {
705 pr_debug("read_done received while not started, treat as xrun");
706 atomic_set(&prtd->xrun, 1);
707 spin_unlock_irqrestore(&prtd->lock, flags);
708 break;
709 }
710 msm_compr_read_buffer(prtd);
711
712 spin_unlock_irqrestore(&prtd->lock, flags);
713 break;
714
715 case ASM_DATA_EVENT_RENDERED_EOS:
716 spin_lock_irqsave(&prtd->lock, flags);
717 pr_debug("%s: ASM_DATA_CMDRSP_EOS token 0x%x,stream id %d\n",
718 __func__, token, stream_id);
719 if (atomic_read(&prtd->eos) &&
720 !prtd->gapless_state.set_next_stream_id) {
721 pr_debug("ASM_DATA_CMDRSP_EOS wake up\n");
722 prtd->eos_ack = 1;
723 wake_up(&prtd->eos_wait);
724 }
725 atomic_set(&prtd->eos, 0);
726 stream_index = STREAM_ARRAY_INDEX(stream_id);
727 if (stream_index >= MAX_NUMBER_OF_STREAMS ||
728 stream_index < 0) {
729 pr_err("%s: Invalid stream index %d", __func__,
730 stream_index);
731 spin_unlock_irqrestore(&prtd->lock, flags);
732 break;
733 }
734
735 if (prtd->gapless_state.set_next_stream_id &&
736 prtd->gapless_state.stream_opened[stream_index]) {
737 pr_debug("%s: CMD_CLOSE stream_id %d\n",
738 __func__, stream_id);
739 q6asm_stream_cmd_nowait(ac, CMD_CLOSE, stream_id);
740 atomic_set(&prtd->close, 1);
741 prtd->gapless_state.stream_opened[stream_index] = 0;
742 prtd->gapless_state.set_next_stream_id = false;
743 }
744 if (prtd->gapless_state.gapless_transition)
745 prtd->gapless_state.gapless_transition = 0;
746 spin_unlock_irqrestore(&prtd->lock, flags);
747 break;
748 case ASM_STREAM_PP_EVENT:
749 case ASM_STREAM_CMD_ENCDEC_EVENTS:
750 pr_debug("%s: ASM_STREAM_EVENT(0x%x)\n", __func__, opcode);
751 rtd = cstream->private_data;
752 if (!rtd) {
753 pr_err("%s: rtd is NULL\n", __func__);
754 return;
755 }
756
757 ret = msm_adsp_inform_mixer_ctl(rtd, payload);
758 if (ret) {
759 pr_err("%s: failed to inform mixer ctrl. err = %d\n",
760 __func__, ret);
761 return;
762 }
763 break;
764 case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
765 case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY: {
766 pr_debug("ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY\n");
767 chan_mode = payload[1] >> 16;
768 sample_rate = payload[2] >> 16;
769 if (prtd && (chan_mode != prtd->num_channels ||
770 sample_rate != prtd->sample_rate)) {
771 prtd->num_channels = chan_mode;
772 prtd->sample_rate = sample_rate;
773 }
774 }
775 /* Fallthrough here */
776 case APR_BASIC_RSP_RESULT: {
777 switch (payload[0]) {
778 case ASM_SESSION_CMD_RUN_V2:
779 /* check if the first buffer need to be sent to DSP */
780 pr_debug("ASM_SESSION_CMD_RUN_V2\n");
781
782 /* FIXME: A state is a better way, dealing with this */
783 spin_lock_irqsave(&prtd->lock, flags);
784
785 if (cstream->direction == SND_COMPRESS_CAPTURE) {
786 atomic_set(&prtd->start, 1);
787 msm_compr_read_buffer(prtd);
788 spin_unlock_irqrestore(&prtd->lock, flags);
789 break;
790 }
791
792 if (!prtd->bytes_sent) {
793 bytes_available = prtd->bytes_received -
794 prtd->copied_total;
795 if (bytes_available <
796 cstream->runtime->fragment_size) {
797 pr_debug("CMD_RUN_V2 Insufficient data to send. break out\n");
798 atomic_set(&prtd->xrun, 1);
799 } else {
800 msm_compr_send_buffer(prtd);
801 }
802 }
803
804 /*
805 * The condition below ensures playback finishes in the
806 * follow cornercase
807 * WRITE(last buffer)
808 * WAIT_FOR_DRAIN
809 * PAUSE
810 * WRITE_DONE(X)
811 * RESUME
812 */
813 if ((prtd->copied_total == prtd->bytes_sent) &&
814 atomic_read(&prtd->drain)) {
815 pr_debug("RUN ack, wake up & continue pending drain\n");
816
817 if (prtd->last_buffer)
818 prtd->last_buffer = 0;
819
820 prtd->drain_ready = 1;
821 wake_up(&prtd->drain_wait);
822 atomic_set(&prtd->drain, 0);
823 }
824
825 spin_unlock_irqrestore(&prtd->lock, flags);
826 break;
827 case ASM_STREAM_CMD_FLUSH:
828 pr_debug("%s: ASM_STREAM_CMD_FLUSH:", __func__);
829 pr_debug("token 0x%x, stream id %d\n", token,
830 stream_id);
831 prtd->cmd_ack = 1;
832 break;
833 case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:
834 pr_debug("%s: ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:",
835 __func__);
836 pr_debug("token 0x%x, stream id = %d\n", token,
837 stream_id);
838 break;
839 case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
840 pr_debug("%s: ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:",
841 __func__);
842 pr_debug("token = 0x%x, stream id = %d\n", token,
843 stream_id);
844 break;
845 case ASM_STREAM_CMD_CLOSE:
846 pr_debug("%s: ASM_DATA_CMD_CLOSE:", __func__);
847 pr_debug("token 0x%x, stream id %d\n", token,
848 stream_id);
849 /*
850 * wakeup wait for stream avail on stream 3
851 * after stream 1 ends.
852 */
853 if (prtd->next_stream) {
854 pr_debug("%s:CLOSE:wakeup wait for stream\n",
855 __func__);
856 prtd->stream_available = 1;
857 wake_up(&prtd->wait_for_stream_avail);
858 prtd->next_stream = 0;
859 }
860 if (atomic_read(&prtd->close) &&
861 atomic_read(&prtd->wait_on_close)) {
862 prtd->cmd_ack = 1;
863 wake_up(&prtd->close_wait);
864 }
865 atomic_set(&prtd->close, 0);
866 break;
867 case ASM_STREAM_CMD_REGISTER_PP_EVENTS:
868 pr_debug("%s: ASM_STREAM_CMD_REGISTER_PP_EVENTS:",
869 __func__);
870 break;
871 default:
872 break;
873 }
874 break;
875 }
876 case ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3:
877 pr_debug("%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3\n",
878 __func__);
879 break;
880 case RESET_EVENTS:
881 pr_err("%s: Received reset events CB, move to error state",
882 __func__);
883 spin_lock_irqsave(&prtd->lock, flags);
884 /*
885 * Since ADSP is down, let this driver pretend that it copied
886 * all the bytes received, so that next write will be triggered
887 */
888 prtd->copied_total = prtd->bytes_received;
889 snd_compr_fragment_elapsed(cstream);
890 atomic_set(&prtd->error, 1);
891 wake_up(&prtd->drain_wait);
892 if (atomic_cmpxchg(&prtd->eos, 1, 0)) {
893 pr_debug("%s:unblock eos wait queues", __func__);
894 wake_up(&prtd->eos_wait);
895 }
896 spin_unlock_irqrestore(&prtd->lock, flags);
897 break;
898 default:
899 pr_debug("%s: Not Supported Event opcode[0x%x]\n",
900 __func__, opcode);
901 break;
902 }
903}
904
905static int msm_compr_get_partial_drain_delay(int frame_sz, int sample_rate)
906{
907 int delay_time_ms = 0;
908
909 delay_time_ms = ((DSP_NUM_OUTPUT_FRAME_BUFFERED * frame_sz * 1000) /
910 sample_rate) + DSP_PP_BUFFERING_IN_MSEC;
911 delay_time_ms = delay_time_ms > PARTIAL_DRAIN_ACK_EARLY_BY_MSEC ?
912 delay_time_ms - PARTIAL_DRAIN_ACK_EARLY_BY_MSEC : 0;
913
914 pr_debug("%s: frame_sz %d, sample_rate %d, partial drain delay %d\n",
915 __func__, frame_sz, sample_rate, delay_time_ms);
916 return delay_time_ms;
917}
918
919static void populate_codec_list(struct msm_compr_audio *prtd)
920{
921 pr_debug("%s\n", __func__);
922 prtd->compr_cap.direction = SND_COMPRESS_PLAYBACK;
923 prtd->compr_cap.min_fragment_size =
924 COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
925 prtd->compr_cap.max_fragment_size =
926 COMPR_PLAYBACK_MAX_FRAGMENT_SIZE;
927 prtd->compr_cap.min_fragments =
928 COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
929 prtd->compr_cap.max_fragments =
930 COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
931 prtd->compr_cap.num_codecs = 17;
932 prtd->compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
933 prtd->compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
934 prtd->compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
935 prtd->compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3;
936 prtd->compr_cap.codecs[4] = SND_AUDIOCODEC_MP2;
937 prtd->compr_cap.codecs[5] = SND_AUDIOCODEC_PCM;
938 prtd->compr_cap.codecs[6] = SND_AUDIOCODEC_WMA;
939 prtd->compr_cap.codecs[7] = SND_AUDIOCODEC_WMA_PRO;
940 prtd->compr_cap.codecs[8] = SND_AUDIOCODEC_FLAC;
941 prtd->compr_cap.codecs[9] = SND_AUDIOCODEC_VORBIS;
942 prtd->compr_cap.codecs[10] = SND_AUDIOCODEC_ALAC;
943 prtd->compr_cap.codecs[11] = SND_AUDIOCODEC_APE;
944 prtd->compr_cap.codecs[12] = SND_AUDIOCODEC_DTS;
945 prtd->compr_cap.codecs[13] = SND_AUDIOCODEC_DSD;
946 prtd->compr_cap.codecs[14] = SND_AUDIOCODEC_APTX;
947 prtd->compr_cap.codecs[15] = SND_AUDIOCODEC_TRUEHD;
948 prtd->compr_cap.codecs[16] = SND_AUDIOCODEC_IEC61937;
949}
950
951static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
952 int stream_id,
953 bool use_gapless_codec_options)
954{
955 struct snd_compr_runtime *runtime = cstream->runtime;
956 struct msm_compr_audio *prtd = runtime->private_data;
957 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
958 struct msm_compr_pdata *pdata =
959 snd_soc_platform_get_drvdata(rtd->platform);
960 struct asm_aac_cfg aac_cfg;
961 struct asm_wma_cfg wma_cfg;
962 struct asm_wmapro_cfg wma_pro_cfg;
963 struct asm_flac_cfg flac_cfg;
964 struct asm_vorbis_cfg vorbis_cfg;
965 struct asm_alac_cfg alac_cfg;
966 struct asm_ape_cfg ape_cfg;
967 struct asm_dsd_cfg dsd_cfg;
968 struct aptx_dec_bt_addr_cfg aptx_cfg;
969 union snd_codec_options *codec_options;
970
971 int ret = 0;
972 uint16_t bit_width;
973 bool use_default_chmap = true;
974 char *chmap = NULL;
975 uint16_t sample_word_size;
976
977 pr_debug("%s: use_gapless_codec_options %d\n",
978 __func__, use_gapless_codec_options);
979
980 if (use_gapless_codec_options)
981 codec_options = &(prtd->gapless_state.codec_options);
982 else
983 codec_options = &(prtd->codec_param.codec.options);
984
985 if (!codec_options) {
986 pr_err("%s: codec_options is NULL\n", __func__);
987 return -EINVAL;
988 }
989
990 switch (prtd->codec) {
991 case FORMAT_LINEAR_PCM:
992 pr_debug("SND_AUDIOCODEC_PCM\n");
993 if (pdata->ch_map[rtd->dai_link->id]) {
994 use_default_chmap =
995 !(pdata->ch_map[rtd->dai_link->id]->set_ch_map);
996 chmap =
997 pdata->ch_map[rtd->dai_link->id]->channel_map;
998 }
999
1000 switch (prtd->codec_param.codec.format) {
1001 case SNDRV_PCM_FORMAT_S32_LE:
1002 bit_width = 32;
1003 sample_word_size = 32;
1004 break;
1005 case SNDRV_PCM_FORMAT_S24_LE:
1006 bit_width = 24;
1007 sample_word_size = 32;
1008 break;
1009 case SNDRV_PCM_FORMAT_S24_3LE:
1010 bit_width = 24;
1011 sample_word_size = 24;
1012 break;
1013 case SNDRV_PCM_FORMAT_S16_LE:
1014 default:
1015 bit_width = 16;
1016 sample_word_size = 16;
1017 break;
1018 }
Dieter Lueckingba7644d2018-09-28 15:09:32 +02001019
1020 if (q6core_get_avcs_api_version_per_service(
1021 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1022 ADSP_ASM_API_VERSION_V2) {
1023 ret = q6asm_media_format_block_pcm_format_support_v5(
1024 prtd->audio_client,
1025 prtd->sample_rate,
1026 prtd->num_channels,
1027 bit_width, stream_id,
1028 use_default_chmap,
1029 chmap,
1030 sample_word_size,
1031 ASM_LITTLE_ENDIAN,
1032 DEFAULT_QF);
1033 } else {
1034 ret = q6asm_media_format_block_pcm_format_support_v4(
1035 prtd->audio_client,
1036 prtd->sample_rate,
1037 prtd->num_channels,
1038 bit_width, stream_id,
1039 use_default_chmap,
1040 chmap,
1041 sample_word_size,
1042 ASM_LITTLE_ENDIAN,
1043 DEFAULT_QF);
1044 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301045 if (ret < 0)
1046 pr_err("%s: CMD Format block failed\n", __func__);
1047
1048 break;
1049 case FORMAT_MP3:
1050 pr_debug("SND_AUDIOCODEC_MP3\n");
1051 /* no media format block needed */
1052 break;
1053 case FORMAT_MPEG4_AAC:
1054 pr_debug("SND_AUDIOCODEC_AAC\n");
1055 memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg));
1056 aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
1057 if (prtd->codec_param.codec.format ==
1058 SND_AUDIOSTREAMFORMAT_MP4ADTS)
1059 aac_cfg.format = 0x0;
1060 else if (prtd->codec_param.codec.format ==
1061 SND_AUDIOSTREAMFORMAT_MP4LATM)
1062 aac_cfg.format = 0x04;
1063 else
1064 aac_cfg.format = 0x03;
1065 aac_cfg.ch_cfg = prtd->num_channels;
1066 aac_cfg.sample_rate = prtd->sample_rate;
1067 ret = q6asm_stream_media_format_block_aac(prtd->audio_client,
1068 &aac_cfg, stream_id);
1069 if (ret < 0)
1070 pr_err("%s: CMD Format block failed\n", __func__);
1071 break;
1072 case FORMAT_AC3:
1073 pr_debug("SND_AUDIOCODEC_AC3\n");
1074 break;
1075 case FORMAT_EAC3:
1076 pr_debug("SND_AUDIOCODEC_EAC3\n");
1077 break;
1078 case FORMAT_WMA_V9:
1079 pr_debug("SND_AUDIOCODEC_WMA\n");
1080 memset(&wma_cfg, 0x0, sizeof(struct asm_wma_cfg));
1081 wma_cfg.format_tag = prtd->codec_param.codec.format;
1082 wma_cfg.ch_cfg = prtd->codec_param.codec.ch_in;
1083 wma_cfg.sample_rate = prtd->sample_rate;
1084 wma_cfg.avg_bytes_per_sec = codec_options->wma.avg_bit_rate/8;
1085 wma_cfg.block_align = codec_options->wma.super_block_align;
1086 wma_cfg.valid_bits_per_sample =
1087 codec_options->wma.bits_per_sample;
1088 wma_cfg.ch_mask = codec_options->wma.channelmask;
1089 wma_cfg.encode_opt = codec_options->wma.encodeopt;
1090 ret = q6asm_media_format_block_wma(prtd->audio_client,
1091 &wma_cfg, stream_id);
1092 if (ret < 0)
1093 pr_err("%s: CMD Format block failed\n", __func__);
1094 break;
1095 case FORMAT_WMA_V10PRO:
1096 pr_debug("SND_AUDIOCODEC_WMA_PRO\n");
1097 memset(&wma_pro_cfg, 0x0, sizeof(struct asm_wmapro_cfg));
1098 wma_pro_cfg.format_tag = prtd->codec_param.codec.format;
1099 wma_pro_cfg.ch_cfg = prtd->codec_param.codec.ch_in;
1100 wma_pro_cfg.sample_rate = prtd->sample_rate;
1101 wma_cfg.avg_bytes_per_sec = codec_options->wma.avg_bit_rate/8;
1102 wma_pro_cfg.block_align = codec_options->wma.super_block_align;
1103 wma_pro_cfg.valid_bits_per_sample =
1104 codec_options->wma.bits_per_sample;
1105 wma_pro_cfg.ch_mask = codec_options->wma.channelmask;
1106 wma_pro_cfg.encode_opt = codec_options->wma.encodeopt;
1107 wma_pro_cfg.adv_encode_opt = codec_options->wma.encodeopt1;
1108 wma_pro_cfg.adv_encode_opt2 = codec_options->wma.encodeopt2;
1109 ret = q6asm_media_format_block_wmapro(prtd->audio_client,
1110 &wma_pro_cfg, stream_id);
1111 if (ret < 0)
1112 pr_err("%s: CMD Format block failed\n", __func__);
1113 break;
1114 case FORMAT_MP2:
1115 pr_debug("%s: SND_AUDIOCODEC_MP2\n", __func__);
1116 break;
1117 case FORMAT_FLAC:
1118 pr_debug("%s: SND_AUDIOCODEC_FLAC\n", __func__);
1119 memset(&flac_cfg, 0x0, sizeof(struct asm_flac_cfg));
1120 flac_cfg.ch_cfg = prtd->num_channels;
1121 flac_cfg.sample_rate = prtd->sample_rate;
1122 flac_cfg.stream_info_present = 1;
1123 flac_cfg.sample_size = codec_options->flac_dec.sample_size;
1124 flac_cfg.min_blk_size = codec_options->flac_dec.min_blk_size;
1125 flac_cfg.max_blk_size = codec_options->flac_dec.max_blk_size;
1126 flac_cfg.max_frame_size =
1127 codec_options->flac_dec.max_frame_size;
1128 flac_cfg.min_frame_size =
1129 codec_options->flac_dec.min_frame_size;
1130
1131 ret = q6asm_stream_media_format_block_flac(prtd->audio_client,
1132 &flac_cfg, stream_id);
1133 if (ret < 0)
1134 pr_err("%s: CMD Format block failed ret %d\n",
1135 __func__, ret);
1136
1137 break;
1138 case FORMAT_VORBIS:
1139 pr_debug("%s: SND_AUDIOCODEC_VORBIS\n", __func__);
1140 memset(&vorbis_cfg, 0x0, sizeof(struct asm_vorbis_cfg));
1141 vorbis_cfg.bit_stream_fmt =
1142 codec_options->vorbis_dec.bit_stream_fmt;
1143
1144 ret = q6asm_stream_media_format_block_vorbis(
1145 prtd->audio_client, &vorbis_cfg,
1146 stream_id);
1147 if (ret < 0)
1148 pr_err("%s: CMD Format block failed ret %d\n",
1149 __func__, ret);
1150
1151 break;
1152 case FORMAT_ALAC:
1153 pr_debug("%s: SND_AUDIOCODEC_ALAC\n", __func__);
1154 memset(&alac_cfg, 0x0, sizeof(struct asm_alac_cfg));
1155 alac_cfg.num_channels = prtd->num_channels;
1156 alac_cfg.sample_rate = prtd->sample_rate;
1157 alac_cfg.frame_length = codec_options->alac.frame_length;
1158 alac_cfg.compatible_version =
1159 codec_options->alac.compatible_version;
1160 alac_cfg.bit_depth = codec_options->alac.bit_depth;
1161 alac_cfg.pb = codec_options->alac.pb;
1162 alac_cfg.mb = codec_options->alac.mb;
1163 alac_cfg.kb = codec_options->alac.kb;
1164 alac_cfg.max_run = codec_options->alac.max_run;
1165 alac_cfg.max_frame_bytes = codec_options->alac.max_frame_bytes;
1166 alac_cfg.avg_bit_rate = codec_options->alac.avg_bit_rate;
1167 alac_cfg.channel_layout_tag =
1168 codec_options->alac.channel_layout_tag;
1169
1170 ret = q6asm_media_format_block_alac(prtd->audio_client,
1171 &alac_cfg, stream_id);
1172 if (ret < 0)
1173 pr_err("%s: CMD Format block failed ret %d\n",
1174 __func__, ret);
1175 break;
1176 case FORMAT_APE:
1177 pr_debug("%s: SND_AUDIOCODEC_APE\n", __func__);
1178 memset(&ape_cfg, 0x0, sizeof(struct asm_ape_cfg));
1179 ape_cfg.num_channels = prtd->num_channels;
1180 ape_cfg.sample_rate = prtd->sample_rate;
1181 ape_cfg.compatible_version =
1182 codec_options->ape.compatible_version;
1183 ape_cfg.compression_level =
1184 codec_options->ape.compression_level;
1185 ape_cfg.format_flags = codec_options->ape.format_flags;
1186 ape_cfg.blocks_per_frame = codec_options->ape.blocks_per_frame;
1187 ape_cfg.final_frame_blocks =
1188 codec_options->ape.final_frame_blocks;
1189 ape_cfg.total_frames = codec_options->ape.total_frames;
1190 ape_cfg.bits_per_sample = codec_options->ape.bits_per_sample;
1191 ape_cfg.seek_table_present =
1192 codec_options->ape.seek_table_present;
1193
1194 ret = q6asm_media_format_block_ape(prtd->audio_client,
1195 &ape_cfg, stream_id);
1196
1197 if (ret < 0)
1198 pr_err("%s: CMD Format block failed ret %d\n",
1199 __func__, ret);
1200 break;
1201 case FORMAT_DTS:
1202 pr_debug("SND_AUDIOCODEC_DTS\n");
1203 /* no media format block needed */
1204 break;
1205 case FORMAT_DSD:
1206 pr_debug("%s: SND_AUDIOCODEC_DSD\n", __func__);
1207 memset(&dsd_cfg, 0x0, sizeof(struct asm_dsd_cfg));
1208 dsd_cfg.num_channels = prtd->num_channels;
1209 dsd_cfg.dsd_data_rate = prtd->sample_rate;
1210 dsd_cfg.num_version = 0;
1211 dsd_cfg.is_bitwise_big_endian = 1;
1212 dsd_cfg.dsd_channel_block_size = 1;
1213 ret = q6asm_media_format_block_dsd(prtd->audio_client,
1214 &dsd_cfg, stream_id);
1215 if (ret < 0)
1216 pr_err("%s: CMD DSD Format block failed ret %d\n",
1217 __func__, ret);
1218 break;
1219 case FORMAT_TRUEHD:
1220 pr_debug("SND_AUDIOCODEC_TRUEHD\n");
1221 /* no media format block needed */
1222 break;
1223 case FORMAT_IEC61937:
1224 pr_debug("SND_AUDIOCODEC_IEC61937\n");
1225 ret = q6asm_media_format_block_iec(prtd->audio_client,
1226 prtd->sample_rate,
1227 prtd->num_channels);
1228 if (ret < 0)
1229 pr_err("%s: CMD IEC61937 Format block failed ret %d\n",
1230 __func__, ret);
1231 break;
1232 case FORMAT_APTX:
1233 pr_debug("SND_AUDIOCODEC_APTX\n");
1234 memset(&aptx_cfg, 0x0, sizeof(struct aptx_dec_bt_addr_cfg));
1235 ret = q6asm_stream_media_format_block_aptx_dec(
1236 prtd->audio_client,
1237 prtd->sample_rate,
1238 stream_id);
1239 if (ret >= 0) {
1240 aptx_cfg.nap = codec_options->aptx_dec.nap;
1241 aptx_cfg.uap = codec_options->aptx_dec.uap;
1242 aptx_cfg.lap = codec_options->aptx_dec.lap;
1243 q6asm_set_aptx_dec_bt_addr(prtd->audio_client,
1244 &aptx_cfg);
1245 } else {
1246 pr_err("%s: CMD Format block failed ret %d\n",
1247 __func__, ret);
1248 }
1249 break;
1250 default:
1251 pr_debug("%s, unsupported format, skip", __func__);
1252 break;
1253 }
1254 return ret;
1255}
1256
1257static int msm_compr_init_pp_params(struct snd_compr_stream *cstream,
1258 struct audio_client *ac)
1259{
1260 int ret = 0;
1261 struct asm_softvolume_params softvol = {
1262 .period = SOFT_VOLUME_PERIOD,
1263 .step = SOFT_VOLUME_STEP,
1264 .rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
1265 };
1266
1267 switch (ac->topology) {
1268 default:
1269 ret = q6asm_set_softvolume_v2(ac, &softvol,
1270 SOFT_VOLUME_INSTANCE_1);
1271 if (ret < 0)
1272 pr_err("%s: Send SoftVolume Param failed ret=%d\n",
1273 __func__, ret);
1274
1275 break;
1276 }
1277 return ret;
1278}
1279
1280static int msm_compr_configure_dsp_for_playback
1281 (struct snd_compr_stream *cstream)
1282{
1283 struct snd_compr_runtime *runtime = cstream->runtime;
1284 struct msm_compr_audio *prtd = runtime->private_data;
1285 struct snd_soc_pcm_runtime *soc_prtd = cstream->private_data;
1286 uint16_t bits_per_sample = 16;
1287 int dir = IN, ret = 0;
1288 struct audio_client *ac = prtd->audio_client;
1289 uint32_t stream_index;
1290 struct asm_softpause_params softpause = {
1291 .enable = SOFT_PAUSE_ENABLE,
1292 .period = SOFT_PAUSE_PERIOD,
1293 .step = SOFT_PAUSE_STEP,
1294 .rampingcurve = SOFT_PAUSE_CURVE_LINEAR,
1295 };
1296 struct asm_softvolume_params softvol = {
1297 .period = SOFT_VOLUME_PERIOD,
1298 .step = SOFT_VOLUME_STEP,
1299 .rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
1300 };
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05301301 struct snd_kcontrol *kctl;
1302 struct snd_ctl_elem_value kctl_elem_value;
1303 uint16_t target_asm_bit_width = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301304
1305 pr_debug("%s: stream_id %d\n", __func__, ac->stream_id);
1306 stream_index = STREAM_ARRAY_INDEX(ac->stream_id);
1307 if (stream_index >= MAX_NUMBER_OF_STREAMS || stream_index < 0) {
1308 pr_err("%s: Invalid stream index:%d", __func__, stream_index);
1309 return -EINVAL;
1310 }
1311
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05301312 kctl = snd_soc_card_get_kcontrol(soc_prtd->card,
1313 DSP_BIT_WIDTH_MIXER_CTL);
1314 if (kctl) {
1315 kctl->get(kctl, &kctl_elem_value);
1316 target_asm_bit_width = kctl_elem_value.value.integer.value[0];
1317 if (target_asm_bit_width > 0) {
1318 pr_debug("%s enforce ASM bitwidth to %d from %d\n",
1319 __func__,
1320 target_asm_bit_width,
1321 bits_per_sample);
1322 bits_per_sample = target_asm_bit_width;
1323 }
1324 } else {
1325 pr_info("%s: failed to get mixer ctl for %s.\n",
1326 __func__, DSP_BIT_WIDTH_MIXER_CTL);
1327 }
1328
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301329 if ((prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_LE) ||
1330 (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_3LE))
1331 bits_per_sample = 24;
1332 else if (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S32_LE)
1333 bits_per_sample = 32;
1334
1335 if (prtd->compr_passthr != LEGACY_PCM) {
1336 ret = q6asm_open_write_compressed(ac, prtd->codec,
1337 prtd->compr_passthr);
1338 if (ret < 0) {
1339 pr_err("%s:ASM open write err[%d] for compr_type[%d]\n",
1340 __func__, ret, prtd->compr_passthr);
1341 return ret;
1342 }
1343 prtd->gapless_state.stream_opened[stream_index] = 1;
1344
1345 ret = msm_pcm_routing_reg_phy_compr_stream(
1346 soc_prtd->dai_link->id,
1347 ac->perf_mode,
1348 prtd->session_id,
1349 SNDRV_PCM_STREAM_PLAYBACK,
1350 prtd->compr_passthr);
1351 if (ret) {
1352 pr_err("%s: compr stream reg failed:%d\n", __func__,
1353 ret);
1354 return ret;
1355 }
1356 } else {
1357 pr_debug("%s: stream_id %d bits_per_sample %d\n",
1358 __func__, ac->stream_id, bits_per_sample);
Dieter Lueckingba7644d2018-09-28 15:09:32 +02001359
1360 if (q6core_get_avcs_api_version_per_service(
1361 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1362 ADSP_ASM_API_VERSION_V2)
1363 ret = q6asm_stream_open_write_v5(ac,
1364 prtd->codec, bits_per_sample,
1365 ac->stream_id,
1366 prtd->gapless_state.use_dsp_gapless_mode);
1367 else
1368 ret = q6asm_stream_open_write_v4(ac,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301369 prtd->codec, bits_per_sample,
1370 ac->stream_id,
1371 prtd->gapless_state.use_dsp_gapless_mode);
1372 if (ret < 0) {
1373 pr_err("%s:ASM open write err[%d] for compr type[%d]\n",
1374 __func__, ret, prtd->compr_passthr);
1375 return -ENOMEM;
1376 }
1377 prtd->gapless_state.stream_opened[stream_index] = 1;
1378
1379 pr_debug("%s: BE id %d\n", __func__, soc_prtd->dai_link->id);
1380 ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->id,
1381 ac->perf_mode,
1382 prtd->session_id,
1383 SNDRV_PCM_STREAM_PLAYBACK);
1384 if (ret) {
1385 pr_err("%s: stream reg failed:%d\n", __func__, ret);
1386 return ret;
1387 }
1388 }
1389
1390 ret = msm_compr_set_volume(cstream, 0, 0);
1391 if (ret < 0)
1392 pr_err("%s : Set Volume failed : %d", __func__, ret);
1393
1394 if (prtd->compr_passthr != LEGACY_PCM) {
1395 pr_debug("%s : Don't send cal and PP params for compress path",
1396 __func__);
1397 } else {
1398 ret = q6asm_send_cal(ac);
1399 if (ret < 0)
1400 pr_debug("%s : Send cal failed : %d", __func__, ret);
1401
1402 ret = q6asm_set_softpause(ac, &softpause);
1403 if (ret < 0)
1404 pr_err("%s: Send SoftPause Param failed ret=%d\n",
1405 __func__, ret);
1406
1407 ret = q6asm_set_softvolume(ac, &softvol);
1408 if (ret < 0)
1409 pr_err("%s: Send SoftVolume Param failed ret=%d\n",
1410 __func__, ret);
1411 }
1412 ret = q6asm_set_io_mode(ac, (COMPRESSED_STREAM_IO | ASYNC_IO_MODE));
1413 if (ret < 0) {
1414 pr_err("%s: Set IO mode failed\n", __func__);
1415 return -EINVAL;
1416 }
1417
1418 runtime->fragments = prtd->codec_param.buffer.fragments;
1419 runtime->fragment_size = prtd->codec_param.buffer.fragment_size;
1420 pr_debug("allocate %d buffers each of size %d\n",
1421 runtime->fragments,
1422 runtime->fragment_size);
1423 ret = q6asm_audio_client_buf_alloc_contiguous(dir, ac,
1424 runtime->fragment_size,
1425 runtime->fragments);
1426 if (ret < 0) {
1427 pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
1428 return -ENOMEM;
1429 }
1430
1431 prtd->byte_offset = 0;
1432 prtd->copied_total = 0;
1433 prtd->app_pointer = 0;
1434 prtd->bytes_received = 0;
1435 prtd->bytes_sent = 0;
1436 prtd->buffer = ac->port[dir].buf[0].data;
1437 prtd->buffer_paddr = ac->port[dir].buf[0].phys;
1438 prtd->buffer_size = runtime->fragments * runtime->fragment_size;
1439
1440 /* Bit-0 of flags represent timestamp mode */
1441 if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG)
1442 prtd->ts_header_offset = sizeof(struct snd_codec_metadata);
1443 else
1444 prtd->ts_header_offset = 0;
1445
1446 ret = msm_compr_send_media_format_block(cstream, ac->stream_id, false);
1447 if (ret < 0)
1448 pr_err("%s, failed to send media format block\n", __func__);
1449
1450 return ret;
1451}
1452
1453static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
1454{
1455 struct snd_compr_runtime *runtime = cstream->runtime;
1456 struct msm_compr_audio *prtd = runtime->private_data;
1457 struct snd_soc_pcm_runtime *soc_prtd = cstream->private_data;
1458 uint16_t bits_per_sample;
1459 uint16_t sample_word_size;
1460 int dir = OUT, ret = 0;
1461 struct audio_client *ac = prtd->audio_client;
1462 uint32_t stream_index;
1463
1464 switch (prtd->codec_param.codec.format) {
1465 case SNDRV_PCM_FORMAT_S24_LE:
1466 bits_per_sample = 24;
1467 sample_word_size = 32;
1468 break;
1469 case SNDRV_PCM_FORMAT_S24_3LE:
1470 bits_per_sample = 24;
1471 sample_word_size = 24;
1472 break;
1473 case SNDRV_PCM_FORMAT_S32_LE:
1474 bits_per_sample = 32;
1475 sample_word_size = 32;
1476 break;
1477 case SNDRV_PCM_FORMAT_S16_LE:
1478 default:
1479 bits_per_sample = 16;
1480 sample_word_size = 16;
1481 break;
1482 }
1483
1484 pr_debug("%s: stream_id %d bits_per_sample %d\n",
1485 __func__, ac->stream_id, bits_per_sample);
1486
1487 if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG) {
1488 ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM,
1489 bits_per_sample, true);
1490 } else {
1491 ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM,
1492 bits_per_sample, false);
1493 }
1494 if (ret < 0) {
1495 pr_err("%s: q6asm_open_read failed:%d\n", __func__, ret);
1496 return ret;
1497 }
1498
1499 ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->id,
1500 ac->perf_mode,
1501 prtd->session_id,
1502 SNDRV_PCM_STREAM_CAPTURE);
1503 if (ret) {
1504 pr_err("%s: stream reg failed:%d\n", __func__, ret);
1505 return ret;
1506 }
1507
1508 ret = q6asm_set_io_mode(ac, (COMPRESSED_STREAM_IO | ASYNC_IO_MODE));
1509 if (ret < 0) {
1510 pr_err("%s: Set IO mode failed\n", __func__);
1511 return -EINVAL;
1512 }
1513
1514 stream_index = STREAM_ARRAY_INDEX(ac->stream_id);
1515 if (stream_index >= MAX_NUMBER_OF_STREAMS || stream_index < 0) {
1516 pr_err("%s: Invalid stream index:%d", __func__, stream_index);
1517 return -EINVAL;
1518 }
1519
1520 runtime->fragments = prtd->codec_param.buffer.fragments;
1521 runtime->fragment_size = prtd->codec_param.buffer.fragment_size;
1522 pr_debug("%s: allocate %d buffers each of size %d\n",
1523 __func__, runtime->fragments,
1524 runtime->fragment_size);
1525 ret = q6asm_audio_client_buf_alloc_contiguous(dir, ac,
1526 runtime->fragment_size,
1527 runtime->fragments);
1528 if (ret < 0) {
1529 pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
1530 return -ENOMEM;
1531 }
1532
1533 prtd->byte_offset = 0;
1534 prtd->received_total = 0;
1535 prtd->app_pointer = 0;
1536 prtd->bytes_copied = 0;
1537 prtd->bytes_read = 0;
1538 prtd->bytes_read_offset = 0;
1539 prtd->buffer = ac->port[dir].buf[0].data;
1540 prtd->buffer_paddr = ac->port[dir].buf[0].phys;
1541 prtd->buffer_size = runtime->fragments * runtime->fragment_size;
1542
1543 /* Bit-0 of flags represent timestamp mode */
1544 if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG)
1545 prtd->ts_header_offset = sizeof(struct snd_codec_metadata);
1546 else
1547 prtd->ts_header_offset = 0;
1548
1549 pr_debug("%s: sample_rate = %d channels = %d bps = %d sample_word_size = %d\n",
1550 __func__, prtd->sample_rate, prtd->num_channels,
1551 bits_per_sample, sample_word_size);
Sachin Mohan Gadag265d94d2018-01-04 11:04:00 +05301552 ret = q6asm_enc_cfg_blk_pcm_format_support_v4(prtd->audio_client,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301553 prtd->sample_rate, prtd->num_channels,
Sachin Mohan Gadag265d94d2018-01-04 11:04:00 +05301554 bits_per_sample, sample_word_size,
1555 ASM_LITTLE_ENDIAN, DEFAULT_QF);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301556
1557 return ret;
1558}
1559
1560static int msm_compr_playback_open(struct snd_compr_stream *cstream)
1561{
1562 struct snd_compr_runtime *runtime = cstream->runtime;
1563 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Aditya Bavanari9deef912017-11-20 13:31:31 +05301564 struct msm_compr_audio *prtd = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301565 struct msm_compr_pdata *pdata =
1566 snd_soc_platform_get_drvdata(rtd->platform);
1567
1568 pr_debug("%s\n", __func__);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301569 if (pdata->is_in_use[rtd->dai_link->id] == true) {
1570 pr_err("%s: %s is already in use, err: %d\n",
1571 __func__, rtd->dai_link->cpu_dai_name, -EBUSY);
1572 return -EBUSY;
1573 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301574 prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL);
1575 if (prtd == NULL) {
1576 pr_err("Failed to allocate memory for msm_compr_audio\n");
1577 return -ENOMEM;
1578 }
1579
1580 runtime->private_data = NULL;
1581 prtd->cstream = cstream;
1582 pdata->cstream[rtd->dai_link->id] = cstream;
1583 pdata->audio_effects[rtd->dai_link->id] =
1584 kzalloc(sizeof(struct msm_compr_audio_effects), GFP_KERNEL);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301585 if (pdata->audio_effects[rtd->dai_link->id] == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301586 pr_err("%s: Could not allocate memory for effects\n", __func__);
1587 pdata->cstream[rtd->dai_link->id] = NULL;
1588 kfree(prtd);
1589 return -ENOMEM;
1590 }
1591 pdata->dec_params[rtd->dai_link->id] =
1592 kzalloc(sizeof(struct msm_compr_dec_params), GFP_KERNEL);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301593 if (pdata->dec_params[rtd->dai_link->id] == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301594 pr_err("%s: Could not allocate memory for dec params\n",
1595 __func__);
1596 kfree(pdata->audio_effects[rtd->dai_link->id]);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301597 pdata->audio_effects[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301598 pdata->cstream[rtd->dai_link->id] = NULL;
1599 kfree(prtd);
1600 return -ENOMEM;
1601 }
1602 prtd->codec = FORMAT_MP3;
1603 prtd->bytes_received = 0;
1604 prtd->bytes_sent = 0;
1605 prtd->copied_total = 0;
1606 prtd->byte_offset = 0;
1607 prtd->sample_rate = 44100;
1608 prtd->num_channels = 2;
1609 prtd->drain_ready = 0;
1610 prtd->last_buffer = 0;
1611 prtd->first_buffer = 1;
1612 prtd->partial_drain_delay = 0;
1613 prtd->next_stream = 0;
1614 memset(&prtd->gapless_state, 0, sizeof(struct msm_compr_gapless_state));
1615 /*
1616 * Update the use_dsp_gapless_mode from gapless struture with the value
1617 * part of platform data.
1618 */
1619 prtd->gapless_state.use_dsp_gapless_mode = pdata->use_dsp_gapless_mode;
1620
1621 pr_debug("%s: gapless mode %d", __func__, pdata->use_dsp_gapless_mode);
1622
1623 spin_lock_init(&prtd->lock);
1624
1625 atomic_set(&prtd->eos, 0);
1626 atomic_set(&prtd->start, 0);
1627 atomic_set(&prtd->drain, 0);
1628 atomic_set(&prtd->xrun, 0);
1629 atomic_set(&prtd->close, 0);
1630 atomic_set(&prtd->wait_on_close, 0);
1631 atomic_set(&prtd->error, 0);
1632
1633 init_waitqueue_head(&prtd->eos_wait);
1634 init_waitqueue_head(&prtd->drain_wait);
1635 init_waitqueue_head(&prtd->close_wait);
1636 init_waitqueue_head(&prtd->wait_for_stream_avail);
1637
1638 runtime->private_data = prtd;
1639 populate_codec_list(prtd);
1640 prtd->audio_client = q6asm_audio_client_alloc(
1641 (app_cb)compr_event_handler, prtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301642 if (prtd->audio_client == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301643 pr_err("%s: Could not allocate memory for client\n", __func__);
1644 kfree(pdata->audio_effects[rtd->dai_link->id]);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301645 pdata->audio_effects[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301646 kfree(pdata->dec_params[rtd->dai_link->id]);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301647 pdata->dec_params[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301648 pdata->cstream[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301649 kfree(prtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301650 runtime->private_data = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301651 return -ENOMEM;
1652 }
1653 pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
1654 prtd->audio_client->perf_mode = false;
1655 prtd->session_id = prtd->audio_client->session;
1656 msm_adsp_init_mixer_ctl_pp_event_queue(rtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301657 pdata->is_in_use[rtd->dai_link->id] = true;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301658 return 0;
1659}
1660
1661static int msm_compr_capture_open(struct snd_compr_stream *cstream)
1662{
1663 struct snd_compr_runtime *runtime = cstream->runtime;
1664 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
1665 struct msm_compr_audio *prtd;
1666 struct msm_compr_pdata *pdata =
1667 snd_soc_platform_get_drvdata(rtd->platform);
1668
1669 pr_debug("%s\n", __func__);
1670 prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL);
1671 if (prtd == NULL) {
1672 pr_err("Failed to allocate memory for msm_compr_audio\n");
1673 return -ENOMEM;
1674 }
1675
1676 runtime->private_data = NULL;
1677 prtd->cstream = cstream;
1678 pdata->cstream[rtd->dai_link->id] = cstream;
1679
1680 prtd->audio_client = q6asm_audio_client_alloc(
1681 (app_cb)compr_event_handler, prtd);
1682 if (!prtd->audio_client) {
1683 pr_err("%s: Could not allocate memory for client\n", __func__);
1684 pdata->cstream[rtd->dai_link->id] = NULL;
1685 kfree(prtd);
1686 return -ENOMEM;
1687 }
1688 pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
1689 prtd->audio_client->perf_mode = false;
1690 prtd->session_id = prtd->audio_client->session;
1691 prtd->codec = FORMAT_LINEAR_PCM;
1692 prtd->bytes_copied = 0;
1693 prtd->bytes_read = 0;
1694 prtd->bytes_read_offset = 0;
1695 prtd->received_total = 0;
1696 prtd->byte_offset = 0;
1697 prtd->sample_rate = 48000;
1698 prtd->num_channels = 2;
1699 prtd->first_buffer = 0;
1700
1701 spin_lock_init(&prtd->lock);
1702
1703 atomic_set(&prtd->eos, 0);
1704 atomic_set(&prtd->start, 0);
1705 atomic_set(&prtd->drain, 0);
1706 atomic_set(&prtd->xrun, 0);
1707 atomic_set(&prtd->close, 0);
1708 atomic_set(&prtd->wait_on_close, 0);
1709 atomic_set(&prtd->error, 0);
1710
1711 runtime->private_data = prtd;
1712
1713 return 0;
1714}
1715
1716static int msm_compr_open(struct snd_compr_stream *cstream)
1717{
1718 int ret = 0;
1719
1720 if (cstream->direction == SND_COMPRESS_PLAYBACK)
1721 ret = msm_compr_playback_open(cstream);
1722 else if (cstream->direction == SND_COMPRESS_CAPTURE)
1723 ret = msm_compr_capture_open(cstream);
1724 return ret;
1725}
1726
1727static int msm_compr_playback_free(struct snd_compr_stream *cstream)
1728{
1729 struct snd_compr_runtime *runtime;
1730 struct msm_compr_audio *prtd;
1731 struct snd_soc_pcm_runtime *soc_prtd;
1732 struct msm_compr_pdata *pdata;
1733 struct audio_client *ac;
1734 int dir = IN, ret = 0, stream_id;
1735 unsigned long flags;
1736 uint32_t stream_index;
1737
1738 pr_debug("%s\n", __func__);
1739
1740 if (!cstream) {
1741 pr_err("%s cstream is null\n", __func__);
1742 return 0;
1743 }
1744 runtime = cstream->runtime;
1745 soc_prtd = cstream->private_data;
1746 if (!runtime || !soc_prtd || !(soc_prtd->platform)) {
1747 pr_err("%s runtime or soc_prtd or platform is null\n",
1748 __func__);
1749 return 0;
1750 }
1751 prtd = runtime->private_data;
1752 if (!prtd) {
1753 pr_err("%s prtd is null\n", __func__);
1754 return 0;
1755 }
1756 prtd->cmd_interrupt = 1;
1757 wake_up(&prtd->drain_wait);
1758 pdata = snd_soc_platform_get_drvdata(soc_prtd->platform);
1759 ac = prtd->audio_client;
1760 if (!pdata || !ac) {
1761 pr_err("%s pdata or ac is null\n", __func__);
1762 return 0;
1763 }
1764 if (atomic_read(&prtd->eos)) {
1765 ret = wait_event_timeout(prtd->eos_wait,
1766 prtd->eos_ack, 5 * HZ);
1767 if (!ret)
1768 pr_err("%s: CMD_EOS failed\n", __func__);
1769 }
1770 if (atomic_read(&prtd->close)) {
1771 prtd->cmd_ack = 0;
1772 atomic_set(&prtd->wait_on_close, 1);
1773 ret = wait_event_timeout(prtd->close_wait,
1774 prtd->cmd_ack, 5 * HZ);
1775 if (!ret)
1776 pr_err("%s: CMD_CLOSE failed\n", __func__);
1777 }
1778
1779 spin_lock_irqsave(&prtd->lock, flags);
1780 stream_id = ac->stream_id;
1781 stream_index = STREAM_ARRAY_INDEX(NEXT_STREAM_ID(stream_id));
1782
1783 if ((stream_index < MAX_NUMBER_OF_STREAMS && stream_index >= 0) &&
1784 (prtd->gapless_state.stream_opened[stream_index])) {
1785 prtd->gapless_state.stream_opened[stream_index] = 0;
1786 spin_unlock_irqrestore(&prtd->lock, flags);
1787 pr_debug(" close stream %d", NEXT_STREAM_ID(stream_id));
1788 q6asm_stream_cmd(ac, CMD_CLOSE, NEXT_STREAM_ID(stream_id));
1789 spin_lock_irqsave(&prtd->lock, flags);
1790 }
1791
1792 stream_index = STREAM_ARRAY_INDEX(stream_id);
1793 if ((stream_index < MAX_NUMBER_OF_STREAMS && stream_index >= 0) &&
1794 (prtd->gapless_state.stream_opened[stream_index])) {
1795 prtd->gapless_state.stream_opened[stream_index] = 0;
1796 spin_unlock_irqrestore(&prtd->lock, flags);
1797 pr_debug("close stream %d", stream_id);
1798 q6asm_stream_cmd(ac, CMD_CLOSE, stream_id);
1799 spin_lock_irqsave(&prtd->lock, flags);
1800 }
1801 spin_unlock_irqrestore(&prtd->lock, flags);
1802
Ajit Pandey233bdea2019-09-04 14:34:00 +05301803 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301804 pdata->cstream[soc_prtd->dai_link->id] = NULL;
1805 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
1806 msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
1807 SNDRV_PCM_STREAM_PLAYBACK);
1808 }
1809
1810 q6asm_audio_client_buf_free_contiguous(dir, ac);
1811
1812 q6asm_audio_client_free(ac);
1813 msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301814 if (pdata->audio_effects[soc_prtd->dai_link->id] != NULL) {
1815 kfree(pdata->audio_effects[soc_prtd->dai_link->id]);
1816 pdata->audio_effects[soc_prtd->dai_link->id] = NULL;
1817 }
1818 if (pdata->dec_params[soc_prtd->dai_link->id] != NULL) {
1819 kfree(pdata->dec_params[soc_prtd->dai_link->id]);
1820 pdata->dec_params[soc_prtd->dai_link->id] = NULL;
1821 }
1822 pdata->is_in_use[soc_prtd->dai_link->id] = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301823 kfree(prtd);
1824 runtime->private_data = NULL;
Ajit Pandey233bdea2019-09-04 14:34:00 +05301825 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301826
1827 return 0;
1828}
1829
1830static int msm_compr_capture_free(struct snd_compr_stream *cstream)
1831{
1832 struct snd_compr_runtime *runtime;
1833 struct msm_compr_audio *prtd;
1834 struct snd_soc_pcm_runtime *soc_prtd;
1835 struct msm_compr_pdata *pdata;
1836 struct audio_client *ac;
1837 int dir = OUT, stream_id;
1838 unsigned long flags;
1839 uint32_t stream_index;
1840
1841 if (!cstream) {
1842 pr_err("%s cstream is null\n", __func__);
1843 return 0;
1844 }
1845 runtime = cstream->runtime;
1846 soc_prtd = cstream->private_data;
1847 if (!runtime || !soc_prtd || !(soc_prtd->platform)) {
1848 pr_err("%s runtime or soc_prtd or platform is null\n",
1849 __func__);
1850 return 0;
1851 }
1852 prtd = runtime->private_data;
1853 if (!prtd) {
1854 pr_err("%s prtd is null\n", __func__);
1855 return 0;
1856 }
1857 pdata = snd_soc_platform_get_drvdata(soc_prtd->platform);
1858 ac = prtd->audio_client;
1859 if (!pdata || !ac) {
1860 pr_err("%s pdata or ac is null\n", __func__);
1861 return 0;
1862 }
1863
1864 spin_lock_irqsave(&prtd->lock, flags);
1865 stream_id = ac->stream_id;
1866
1867 stream_index = STREAM_ARRAY_INDEX(stream_id);
1868 if ((stream_index < MAX_NUMBER_OF_STREAMS && stream_index >= 0)) {
1869 spin_unlock_irqrestore(&prtd->lock, flags);
1870 pr_debug("close stream %d", stream_id);
1871 q6asm_stream_cmd(ac, CMD_CLOSE, stream_id);
1872 spin_lock_irqsave(&prtd->lock, flags);
1873 }
1874 spin_unlock_irqrestore(&prtd->lock, flags);
1875
Ajit Pandey233bdea2019-09-04 14:34:00 +05301876 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301877 pdata->cstream[soc_prtd->dai_link->id] = NULL;
1878 msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
1879 SNDRV_PCM_STREAM_CAPTURE);
1880
1881 q6asm_audio_client_buf_free_contiguous(dir, ac);
1882
1883 q6asm_audio_client_free(ac);
1884
1885 kfree(prtd);
1886 runtime->private_data = NULL;
Ajit Pandey233bdea2019-09-04 14:34:00 +05301887 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301888
1889 return 0;
1890}
1891
1892static int msm_compr_free(struct snd_compr_stream *cstream)
1893{
1894 int ret = 0;
1895
1896 if (cstream->direction == SND_COMPRESS_PLAYBACK)
1897 ret = msm_compr_playback_free(cstream);
1898 else if (cstream->direction == SND_COMPRESS_CAPTURE)
1899 ret = msm_compr_capture_free(cstream);
1900 return ret;
1901}
1902
1903static bool msm_compr_validate_codec_compr(__u32 codec_id)
1904{
1905 int32_t i;
1906
1907 for (i = 0; i < ARRAY_SIZE(compr_codecs); i++) {
1908 if (compr_codecs[i] == codec_id)
1909 return true;
1910 }
1911 return false;
1912}
1913
1914/* compress stream operations */
1915static int msm_compr_set_params(struct snd_compr_stream *cstream,
1916 struct snd_compr_params *params)
1917{
1918 struct snd_compr_runtime *runtime = cstream->runtime;
1919 struct msm_compr_audio *prtd = runtime->private_data;
1920 int ret = 0, frame_sz = 0;
1921 int i, num_rates;
1922 bool is_format_gapless = false;
1923
1924 pr_debug("%s\n", __func__);
1925
1926 num_rates = sizeof(supported_sample_rates)/sizeof(unsigned int);
1927 for (i = 0; i < num_rates; i++)
1928 if (params->codec.sample_rate == supported_sample_rates[i])
1929 break;
1930 if (i == num_rates)
1931 return -EINVAL;
1932
1933 memcpy(&prtd->codec_param, params, sizeof(struct snd_compr_params));
1934 /* ToDo: remove duplicates */
1935 prtd->num_channels = prtd->codec_param.codec.ch_in;
1936 prtd->sample_rate = prtd->codec_param.codec.sample_rate;
1937 pr_debug("%s: sample_rate %d\n", __func__, prtd->sample_rate);
1938
1939 if ((prtd->codec_param.codec.compr_passthr >= LEGACY_PCM &&
1940 prtd->codec_param.
1941 codec.compr_passthr <= COMPRESSED_PASSTHROUGH_DSD) ||
1942 (prtd->codec_param.
1943 codec.compr_passthr == COMPRESSED_PASSTHROUGH_IEC61937))
1944 prtd->compr_passthr = prtd->codec_param.codec.compr_passthr;
1945 else
1946 prtd->compr_passthr = LEGACY_PCM;
1947 pr_debug("%s: compr_passthr = %d", __func__, prtd->compr_passthr);
1948 if (prtd->compr_passthr != LEGACY_PCM) {
1949 pr_debug("%s: Reset gapless mode playback for compr_type[%d]\n",
1950 __func__, prtd->compr_passthr);
1951 prtd->gapless_state.use_dsp_gapless_mode = 0;
1952 if (!msm_compr_validate_codec_compr(params->codec.id)) {
1953 pr_err("%s codec not supported in passthrough,id =%d\n",
1954 __func__, params->codec.id);
1955 return -EINVAL;
1956 }
1957 }
1958
1959 switch (params->codec.id) {
1960 case SND_AUDIOCODEC_PCM: {
1961 pr_debug("SND_AUDIOCODEC_PCM\n");
1962 prtd->codec = FORMAT_LINEAR_PCM;
1963 is_format_gapless = true;
1964 break;
1965 }
1966
1967 case SND_AUDIOCODEC_MP3: {
1968 pr_debug("SND_AUDIOCODEC_MP3\n");
1969 prtd->codec = FORMAT_MP3;
1970 frame_sz = MP3_OUTPUT_FRAME_SZ;
1971 is_format_gapless = true;
1972 break;
1973 }
1974
1975 case SND_AUDIOCODEC_AAC: {
1976 pr_debug("SND_AUDIOCODEC_AAC\n");
1977 prtd->codec = FORMAT_MPEG4_AAC;
1978 frame_sz = AAC_OUTPUT_FRAME_SZ;
1979 is_format_gapless = true;
1980 break;
1981 }
1982
1983 case SND_AUDIOCODEC_AC3: {
1984 pr_debug("SND_AUDIOCODEC_AC3\n");
1985 prtd->codec = FORMAT_AC3;
1986 frame_sz = AC3_OUTPUT_FRAME_SZ;
1987 is_format_gapless = true;
1988 break;
1989 }
1990
1991 case SND_AUDIOCODEC_EAC3: {
1992 pr_debug("SND_AUDIOCODEC_EAC3\n");
1993 prtd->codec = FORMAT_EAC3;
1994 frame_sz = EAC3_OUTPUT_FRAME_SZ;
1995 is_format_gapless = true;
1996 break;
1997 }
1998
1999 case SND_AUDIOCODEC_MP2: {
2000 pr_debug("SND_AUDIOCODEC_MP2\n");
2001 prtd->codec = FORMAT_MP2;
2002 break;
2003 }
2004
2005 case SND_AUDIOCODEC_WMA: {
2006 pr_debug("SND_AUDIOCODEC_WMA\n");
2007 prtd->codec = FORMAT_WMA_V9;
2008 break;
2009 }
2010
2011 case SND_AUDIOCODEC_WMA_PRO: {
2012 pr_debug("SND_AUDIOCODEC_WMA_PRO\n");
2013 prtd->codec = FORMAT_WMA_V10PRO;
2014 break;
2015 }
2016
2017 case SND_AUDIOCODEC_FLAC: {
2018 pr_debug("%s: SND_AUDIOCODEC_FLAC\n", __func__);
2019 prtd->codec = FORMAT_FLAC;
2020 /*
2021 * DSP bufferring is based on blk size,
2022 * consider mininum buffering to rule out any false wait
2023 */
2024 frame_sz =
2025 prtd->codec_param.codec.options.flac_dec.min_blk_size;
2026 is_format_gapless = true;
2027 break;
2028 }
2029
2030 case SND_AUDIOCODEC_VORBIS: {
2031 pr_debug("%s: SND_AUDIOCODEC_VORBIS\n", __func__);
2032 prtd->codec = FORMAT_VORBIS;
2033 break;
2034 }
2035
2036 case SND_AUDIOCODEC_ALAC: {
2037 pr_debug("%s: SND_AUDIOCODEC_ALAC\n", __func__);
2038 prtd->codec = FORMAT_ALAC;
2039 break;
2040 }
2041
2042 case SND_AUDIOCODEC_APE: {
2043 pr_debug("%s: SND_AUDIOCODEC_APE\n", __func__);
2044 prtd->codec = FORMAT_APE;
2045 break;
2046 }
2047
2048 case SND_AUDIOCODEC_DTS: {
2049 pr_debug("%s: SND_AUDIOCODEC_DTS\n", __func__);
2050 prtd->codec = FORMAT_DTS;
2051 break;
2052 }
2053
2054 case SND_AUDIOCODEC_DSD: {
2055 pr_debug("%s: SND_AUDIOCODEC_DSD\n", __func__);
2056 prtd->codec = FORMAT_DSD;
2057 break;
2058 }
2059
2060 case SND_AUDIOCODEC_TRUEHD: {
2061 pr_debug("%s: SND_AUDIOCODEC_TRUEHD\n", __func__);
2062 prtd->codec = FORMAT_TRUEHD;
2063 break;
2064 }
2065
2066 case SND_AUDIOCODEC_IEC61937: {
2067 pr_debug("%s: SND_AUDIOCODEC_IEC61937\n", __func__);
2068 prtd->codec = FORMAT_IEC61937;
2069 break;
2070 }
2071
2072 case SND_AUDIOCODEC_APTX: {
2073 pr_debug("%s: SND_AUDIOCODEC_APTX\n", __func__);
2074 prtd->codec = FORMAT_APTX;
2075 break;
2076 }
2077
2078 default:
2079 pr_err("codec not supported, id =%d\n", params->codec.id);
2080 return -EINVAL;
2081 }
2082
2083 if (!is_format_gapless)
2084 prtd->gapless_state.use_dsp_gapless_mode = false;
2085
2086 prtd->partial_drain_delay =
2087 msm_compr_get_partial_drain_delay(frame_sz, prtd->sample_rate);
2088
2089 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2090 ret = msm_compr_configure_dsp_for_playback(cstream);
2091 else if (cstream->direction == SND_COMPRESS_CAPTURE)
2092 ret = msm_compr_configure_dsp_for_capture(cstream);
2093
2094 return ret;
2095}
2096
2097static int msm_compr_drain_buffer(struct msm_compr_audio *prtd,
2098 unsigned long *flags)
2099{
2100 int rc = 0;
2101
2102 atomic_set(&prtd->drain, 1);
2103 prtd->drain_ready = 0;
2104 spin_unlock_irqrestore(&prtd->lock, *flags);
2105 pr_debug("%s: wait for buffer to be drained\n", __func__);
2106 rc = wait_event_interruptible(prtd->drain_wait,
2107 prtd->drain_ready ||
2108 prtd->cmd_interrupt ||
2109 atomic_read(&prtd->xrun) ||
2110 atomic_read(&prtd->error));
2111 pr_debug("%s: out of buffer drain wait with ret %d\n", __func__, rc);
2112 spin_lock_irqsave(&prtd->lock, *flags);
2113 if (prtd->cmd_interrupt) {
2114 pr_debug("%s: buffer drain interrupted by flush)\n", __func__);
2115 rc = -EINTR;
2116 prtd->cmd_interrupt = 0;
2117 }
2118 if (atomic_read(&prtd->error)) {
2119 pr_err("%s: Got RESET EVENTS notification, return\n",
2120 __func__);
2121 rc = -ENETRESET;
2122 }
2123 return rc;
2124}
2125
2126static int msm_compr_wait_for_stream_avail(struct msm_compr_audio *prtd,
2127 unsigned long *flags)
2128{
2129 int rc = 0;
2130
2131 pr_debug("next session is already in opened state\n");
2132 prtd->next_stream = 1;
2133 prtd->cmd_interrupt = 0;
2134 spin_unlock_irqrestore(&prtd->lock, *flags);
2135 /*
2136 * Wait for stream to be available, or the wait to be interrupted by
2137 * commands like flush or till a timeout of one second.
2138 */
2139 rc = wait_event_timeout(prtd->wait_for_stream_avail,
2140 prtd->stream_available || prtd->cmd_interrupt, 1 * HZ);
2141 pr_err("%s:prtd->stream_available %d, prtd->cmd_interrupt %d rc %d\n",
2142 __func__, prtd->stream_available, prtd->cmd_interrupt, rc);
2143
2144 spin_lock_irqsave(&prtd->lock, *flags);
2145 if (rc == 0) {
2146 pr_err("%s: wait_for_stream_avail timed out\n",
2147 __func__);
2148 rc = -ETIMEDOUT;
2149 } else if (prtd->cmd_interrupt == 1) {
2150 /*
2151 * This scenario might not happen as we do not allow
2152 * flush in transition state.
2153 */
2154 pr_debug("%s: wait_for_stream_avail interrupted\n", __func__);
2155 prtd->cmd_interrupt = 0;
2156 prtd->stream_available = 0;
2157 rc = -EINTR;
2158 } else {
2159 prtd->stream_available = 0;
2160 rc = 0;
2161 }
2162 pr_debug("%s : rc = %d", __func__, rc);
2163 return rc;
2164}
2165
2166static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
2167{
2168 struct snd_compr_runtime *runtime = cstream->runtime;
2169 struct msm_compr_audio *prtd = runtime->private_data;
2170 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
2171 struct msm_compr_pdata *pdata =
2172 snd_soc_platform_get_drvdata(rtd->platform);
2173 uint32_t *volume = pdata->volume[rtd->dai_link->id];
2174 struct audio_client *ac = prtd->audio_client;
2175 unsigned long fe_id = rtd->dai_link->id;
2176 int rc = 0;
2177 int bytes_to_write;
2178 unsigned long flags;
2179 int stream_id;
2180 uint32_t stream_index;
2181 uint16_t bits_per_sample = 16;
2182
2183 spin_lock_irqsave(&prtd->lock, flags);
2184 if (atomic_read(&prtd->error)) {
2185 pr_err("%s Got RESET EVENTS notification, return immediately",
2186 __func__);
2187 spin_unlock_irqrestore(&prtd->lock, flags);
2188 return 0;
2189 }
2190 spin_unlock_irqrestore(&prtd->lock, flags);
2191
2192 switch (cmd) {
2193 case SNDRV_PCM_TRIGGER_START:
2194 pr_debug("%s: SNDRV_PCM_TRIGGER_START\n", __func__);
2195 atomic_set(&prtd->start, 1);
2196
2197 /*
2198 * compr_set_volume and compr_init_pp_params
2199 * are used to configure ASM volume hence not
2200 * needed for compress passthrough playback.
2201 *
2202 * compress passthrough volume is controlled in
2203 * ADM by adm_send_compressed_device_mute()
2204 */
2205 if (prtd->compr_passthr == LEGACY_PCM &&
2206 cstream->direction == SND_COMPRESS_PLAYBACK) {
2207 /* set volume for the stream before RUN */
2208 rc = msm_compr_set_volume(cstream,
2209 volume[0], volume[1]);
2210 if (rc)
2211 pr_err("%s : Set Volume failed : %d\n",
2212 __func__, rc);
2213
2214 rc = msm_compr_init_pp_params(cstream, ac);
2215 if (rc)
2216 pr_err("%s : init PP params failed : %d\n",
2217 __func__, rc);
2218 } else {
2219 msm_compr_read_buffer(prtd);
2220 }
2221 /* issue RUN command for the stream */
2222 q6asm_run_nowait(prtd->audio_client, prtd->run_mode,
2223 prtd->start_delay_msw, prtd->start_delay_lsw);
2224 break;
2225 case SNDRV_PCM_TRIGGER_STOP:
2226 spin_lock_irqsave(&prtd->lock, flags);
2227 pr_debug("%s: SNDRV_PCM_TRIGGER_STOP transition %d\n", __func__,
2228 prtd->gapless_state.gapless_transition);
2229 stream_id = ac->stream_id;
2230 atomic_set(&prtd->start, 0);
2231 if (cstream->direction == SND_COMPRESS_CAPTURE) {
2232 q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
2233 atomic_set(&prtd->xrun, 0);
2234 prtd->received_total = 0;
2235 prtd->bytes_copied = 0;
2236 prtd->bytes_read = 0;
2237 prtd->bytes_read_offset = 0;
2238 prtd->byte_offset = 0;
2239 prtd->app_pointer = 0;
2240 spin_unlock_irqrestore(&prtd->lock, flags);
2241 break;
2242 }
2243 if (prtd->next_stream) {
2244 pr_debug("%s: interrupt next track wait queues\n",
2245 __func__);
2246 prtd->cmd_interrupt = 1;
2247 wake_up(&prtd->wait_for_stream_avail);
2248 prtd->next_stream = 0;
2249 }
2250 if (atomic_read(&prtd->eos)) {
2251 pr_debug("%s: interrupt eos wait queues", __func__);
2252 /*
2253 * Gapless playback does not wait for eos, do not set
2254 * cmd_int and do not wake up eos_wait during gapless
2255 * transition
2256 */
2257 if (!prtd->gapless_state.gapless_transition) {
2258 prtd->cmd_interrupt = 1;
2259 wake_up(&prtd->eos_wait);
2260 }
2261 atomic_set(&prtd->eos, 0);
2262 }
2263 if (atomic_read(&prtd->drain)) {
2264 pr_debug("%s: interrupt drain wait queues", __func__);
2265 prtd->cmd_interrupt = 1;
2266 prtd->drain_ready = 1;
2267 wake_up(&prtd->drain_wait);
2268 atomic_set(&prtd->drain, 0);
2269 }
2270 prtd->last_buffer = 0;
2271 prtd->cmd_ack = 0;
2272 if (!prtd->gapless_state.gapless_transition) {
2273 pr_debug("issue CMD_FLUSH stream_id %d\n", stream_id);
2274 spin_unlock_irqrestore(&prtd->lock, flags);
2275 q6asm_stream_cmd(
2276 prtd->audio_client, CMD_FLUSH, stream_id);
2277 spin_lock_irqsave(&prtd->lock, flags);
2278 } else {
2279 prtd->first_buffer = 0;
2280 }
2281 /* FIXME. only reset if flush was successful */
2282 prtd->byte_offset = 0;
2283 prtd->copied_total = 0;
2284 prtd->app_pointer = 0;
2285 prtd->bytes_received = 0;
2286 prtd->bytes_sent = 0;
2287 prtd->marker_timestamp = 0;
2288
2289 atomic_set(&prtd->xrun, 0);
2290 spin_unlock_irqrestore(&prtd->lock, flags);
2291 break;
2292 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
2293 pr_debug("SNDRV_PCM_TRIGGER_PAUSE_PUSH transition %d\n",
2294 prtd->gapless_state.gapless_transition);
2295 if (!prtd->gapless_state.gapless_transition) {
2296 pr_debug("issue CMD_PAUSE stream_id %d\n",
2297 ac->stream_id);
2298 q6asm_stream_cmd_nowait(ac, CMD_PAUSE, ac->stream_id);
2299 atomic_set(&prtd->start, 0);
2300 }
2301 break;
2302 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
2303 pr_debug("SNDRV_PCM_TRIGGER_PAUSE_RELEASE transition %d\n",
2304 prtd->gapless_state.gapless_transition);
2305 if (!prtd->gapless_state.gapless_transition) {
2306 atomic_set(&prtd->start, 1);
2307 q6asm_run_nowait(prtd->audio_client, prtd->run_mode,
2308 0, 0);
2309 }
2310 break;
2311 case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
2312 pr_debug("%s: SND_COMPR_TRIGGER_PARTIAL_DRAIN\n", __func__);
2313 if (!prtd->gapless_state.use_dsp_gapless_mode) {
2314 pr_debug("%s: set partial drain as drain\n", __func__);
2315 cmd = SND_COMPR_TRIGGER_DRAIN;
2316 }
2317 case SND_COMPR_TRIGGER_DRAIN:
2318 pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__);
2319 /* Make sure all the data is sent to DSP before sending EOS */
2320 spin_lock_irqsave(&prtd->lock, flags);
2321
2322 if (!atomic_read(&prtd->start)) {
2323 pr_err("%s: stream is not in started state\n",
2324 __func__);
2325 rc = -EPERM;
2326 spin_unlock_irqrestore(&prtd->lock, flags);
2327 break;
2328 }
2329 if (prtd->bytes_received > prtd->copied_total) {
2330 pr_debug("%s: wait till all the data is sent to dsp\n",
2331 __func__);
2332 rc = msm_compr_drain_buffer(prtd, &flags);
2333 if (rc || !atomic_read(&prtd->start)) {
2334 if (rc != -ENETRESET)
2335 rc = -EINTR;
2336 spin_unlock_irqrestore(&prtd->lock, flags);
2337 break;
2338 }
2339 /*
2340 * FIXME: Bug.
2341 * Write(32767)
2342 * Start
2343 * Drain <- Indefinite wait
2344 * sol1 : if (prtd->copied_total) then wait?
2345 * sol2 : (prtd->cmd_interrupt || prtd->drain_ready ||
2346 * atomic_read(xrun)
2347 */
2348 bytes_to_write = prtd->bytes_received
2349 - prtd->copied_total;
2350 WARN(bytes_to_write > runtime->fragment_size,
2351 "last write %d cannot be > than fragment_size",
2352 bytes_to_write);
2353
2354 if (bytes_to_write > 0) {
2355 pr_debug("%s: send %d partial bytes at the end",
2356 __func__, bytes_to_write);
2357 atomic_set(&prtd->xrun, 0);
2358 prtd->last_buffer = 1;
2359 msm_compr_send_buffer(prtd);
2360 }
2361 }
2362
2363 if ((cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN) &&
2364 (prtd->gapless_state.set_next_stream_id)) {
2365 /* wait for the last buffer to be returned */
2366
2367 if (prtd->last_buffer) {
2368 pr_debug("%s: last buffer drain\n", __func__);
2369 rc = msm_compr_drain_buffer(prtd, &flags);
2370 if (rc || !atomic_read(&prtd->start)) {
2371 spin_unlock_irqrestore(&prtd->lock,
2372 flags);
2373 break;
2374 }
2375 }
2376 /* send EOS */
2377 prtd->eos_ack = 0;
2378 atomic_set(&prtd->eos, 1);
2379 pr_debug("issue CMD_EOS stream_id %d\n", ac->stream_id);
2380 q6asm_stream_cmd_nowait(ac, CMD_EOS, ac->stream_id);
2381 pr_info("PARTIAL DRAIN, do not wait for EOS ack\n");
2382
2383 /* send a zero length buffer */
2384 atomic_set(&prtd->xrun, 0);
2385 msm_compr_send_buffer(prtd);
2386
2387 /* wait for the zero length buffer to be returned */
2388 pr_debug("%s: zero length buffer drain\n", __func__);
2389 rc = msm_compr_drain_buffer(prtd, &flags);
2390 if (rc || !atomic_read(&prtd->start)) {
2391 spin_unlock_irqrestore(&prtd->lock, flags);
2392 break;
2393 }
2394
2395 /* sleep for additional duration partial drain */
2396 atomic_set(&prtd->drain, 1);
2397 prtd->drain_ready = 0;
2398 pr_debug("%s, additional sleep: %d\n", __func__,
2399 prtd->partial_drain_delay);
2400 spin_unlock_irqrestore(&prtd->lock, flags);
2401 rc = wait_event_timeout(prtd->drain_wait,
2402 prtd->drain_ready || prtd->cmd_interrupt,
2403 msecs_to_jiffies(prtd->partial_drain_delay));
2404 pr_debug("%s: out of additional wait for low sample rate\n",
2405 __func__);
2406 spin_lock_irqsave(&prtd->lock, flags);
2407 if (prtd->cmd_interrupt) {
2408 pr_debug("%s: additional wait interrupted by flush)\n",
2409 __func__);
2410 rc = -EINTR;
2411 prtd->cmd_interrupt = 0;
2412 spin_unlock_irqrestore(&prtd->lock, flags);
2413 break;
2414 }
2415
2416 /* move to next stream and reset vars */
2417 pr_debug("%s: Moving to next stream in gapless\n",
2418 __func__);
2419 ac->stream_id = NEXT_STREAM_ID(ac->stream_id);
2420 prtd->byte_offset = 0;
2421 prtd->app_pointer = 0;
2422 prtd->first_buffer = 1;
2423 prtd->last_buffer = 0;
2424 /*
2425 * Set gapless transition flag only if EOS hasn't been
2426 * acknowledged already.
2427 */
2428 if (atomic_read(&prtd->eos))
2429 prtd->gapless_state.gapless_transition = 1;
2430 prtd->marker_timestamp = 0;
2431
2432 /*
2433 * Don't reset these as these vars map to
2434 * total_bytes_transferred and total_bytes_available
2435 * directly, only total_bytes_transferred will be
2436 * updated in the next avail() ioctl
2437 * prtd->copied_total = 0;
2438 * prtd->bytes_received = 0;
2439 */
2440 atomic_set(&prtd->drain, 0);
2441 atomic_set(&prtd->xrun, 1);
2442 pr_debug("%s: issue CMD_RUN", __func__);
2443 q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
2444 spin_unlock_irqrestore(&prtd->lock, flags);
2445 break;
2446 }
2447 /*
2448 * moving to next stream failed, so reset the gapless state
2449 * set next stream id for the same session so that the same
2450 * stream can be used for gapless playback
2451 */
2452 prtd->gapless_state.set_next_stream_id = false;
2453 prtd->gapless_state.gapless_transition = 0;
2454 pr_debug("%s:CMD_EOS stream_id %d\n", __func__, ac->stream_id);
2455
2456 prtd->eos_ack = 0;
2457 atomic_set(&prtd->eos, 1);
2458 q6asm_stream_cmd_nowait(ac, CMD_EOS, ac->stream_id);
2459
2460 spin_unlock_irqrestore(&prtd->lock, flags);
2461
2462
2463 /* Wait indefinitely for DRAIN. Flush can also signal this*/
2464 rc = wait_event_interruptible(prtd->eos_wait,
2465 (prtd->eos_ack ||
2466 prtd->cmd_interrupt ||
2467 atomic_read(&prtd->error)));
2468
2469 if (rc < 0)
2470 pr_err("%s: EOS wait failed\n", __func__);
2471
2472 pr_debug("%s: SNDRV_COMPRESS_DRAIN out of wait for EOS\n",
2473 __func__);
2474
2475 if (prtd->cmd_interrupt)
2476 rc = -EINTR;
2477
2478 if (atomic_read(&prtd->error)) {
2479 pr_err("%s: Got RESET EVENTS notification, return\n",
2480 __func__);
2481 rc = -ENETRESET;
2482 }
2483
2484 /*FIXME : what if a flush comes while PC is here */
2485 if (rc == 0) {
2486 /*
2487 * Failed to open second stream in DSP for gapless
2488 * so prepare the current stream in session
2489 * for gapless playback
2490 */
2491 spin_lock_irqsave(&prtd->lock, flags);
2492 pr_debug("%s:issue CMD_PAUSE stream_id %d",
2493 __func__, ac->stream_id);
2494 q6asm_stream_cmd_nowait(ac, CMD_PAUSE, ac->stream_id);
2495 prtd->cmd_ack = 0;
2496 spin_unlock_irqrestore(&prtd->lock, flags);
2497
2498 /*
2499 * Cache this time as last known time
2500 */
2501 if (pdata->use_legacy_api)
2502 q6asm_get_session_time_legacy(
2503 prtd->audio_client,
2504 &prtd->marker_timestamp);
2505 else
2506 q6asm_get_session_time(prtd->audio_client,
2507 &prtd->marker_timestamp);
2508
2509 spin_lock_irqsave(&prtd->lock, flags);
2510 /*
2511 * Don't reset these as these vars map to
2512 * total_bytes_transferred and total_bytes_available.
2513 * Just total_bytes_transferred will be updated
2514 * in the next avail() ioctl.
2515 * prtd->copied_total = 0;
2516 * prtd->bytes_received = 0;
2517 * do not reset prtd->bytes_sent as well as the same
2518 * session is used for gapless playback
2519 */
2520 prtd->byte_offset = 0;
2521
2522 prtd->app_pointer = 0;
2523 prtd->first_buffer = 1;
2524 prtd->last_buffer = 0;
2525 atomic_set(&prtd->drain, 0);
2526 atomic_set(&prtd->xrun, 1);
2527 spin_unlock_irqrestore(&prtd->lock, flags);
2528
2529 pr_debug("%s:issue CMD_FLUSH ac->stream_id %d",
2530 __func__, ac->stream_id);
2531 q6asm_stream_cmd(ac, CMD_FLUSH, ac->stream_id);
2532
2533 q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
2534 }
2535 prtd->cmd_interrupt = 0;
2536 break;
2537 case SND_COMPR_TRIGGER_NEXT_TRACK:
2538 if (!prtd->gapless_state.use_dsp_gapless_mode) {
2539 pr_debug("%s: ignore trigger next track\n", __func__);
2540 rc = 0;
2541 break;
2542 }
2543 pr_debug("%s: SND_COMPR_TRIGGER_NEXT_TRACK\n", __func__);
2544 spin_lock_irqsave(&prtd->lock, flags);
2545 rc = 0;
2546 /* next stream in gapless */
2547 stream_id = NEXT_STREAM_ID(ac->stream_id);
2548 /*
2549 * Wait if stream 1 has not completed before honoring next
2550 * track for stream 3. Scenario happens if second clip is
2551 * small and fills in one buffer so next track will be
2552 * called immediately.
2553 */
2554 stream_index = STREAM_ARRAY_INDEX(stream_id);
2555 if (stream_index >= MAX_NUMBER_OF_STREAMS ||
2556 stream_index < 0) {
2557 pr_err("%s: Invalid stream index: %d", __func__,
2558 stream_index);
2559 spin_unlock_irqrestore(&prtd->lock, flags);
2560 rc = -EINVAL;
2561 break;
2562 }
2563
2564 if (prtd->gapless_state.stream_opened[stream_index]) {
2565 if (prtd->gapless_state.gapless_transition) {
2566 rc = msm_compr_wait_for_stream_avail(prtd,
2567 &flags);
2568 } else {
2569 /*
2570 * If session is already opened break out if
2571 * the state is not gapless transition. This
2572 * is when seek happens after the last buffer
2573 * is sent to the driver. Next track would be
2574 * called again after last buffer is sent.
2575 */
2576 pr_debug("next session is in opened state\n");
2577 spin_unlock_irqrestore(&prtd->lock, flags);
2578 break;
2579 }
2580 }
2581 spin_unlock_irqrestore(&prtd->lock, flags);
2582 if (rc < 0) {
2583 /*
2584 * if return type EINTR then reset to zero. Tiny
2585 * compress treats EINTR as error and prevents PARTIAL
2586 * DRAIN. EINTR is not an error. wait for stream avail
2587 * is interrupted by some other command like FLUSH.
2588 */
2589 if (rc == -EINTR) {
2590 pr_debug("%s: EINTR reset rc to 0\n", __func__);
2591 rc = 0;
2592 }
2593 break;
2594 }
2595
2596 if (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_LE)
2597 bits_per_sample = 24;
2598 else if (prtd->codec_param.codec.format ==
2599 SNDRV_PCM_FORMAT_S32_LE)
2600 bits_per_sample = 32;
2601
2602 pr_debug("%s: open_write stream_id %d bits_per_sample %d",
2603 __func__, stream_id, bits_per_sample);
2604 rc = q6asm_stream_open_write_v4(prtd->audio_client,
2605 prtd->codec, bits_per_sample,
2606 stream_id,
2607 prtd->gapless_state.use_dsp_gapless_mode);
2608 if (rc < 0) {
2609 pr_err("%s: Session out open failed for gapless\n",
2610 __func__);
2611 break;
2612 }
2613
2614 spin_lock_irqsave(&prtd->lock, flags);
2615 prtd->gapless_state.stream_opened[stream_index] = 1;
2616 prtd->gapless_state.set_next_stream_id = true;
2617 spin_unlock_irqrestore(&prtd->lock, flags);
2618
2619 rc = msm_compr_send_media_format_block(cstream,
2620 stream_id, false);
2621 if (rc < 0) {
2622 pr_err("%s, failed to send media format block\n",
2623 __func__);
2624 break;
2625 }
2626 msm_compr_send_dec_params(cstream, pdata->dec_params[fe_id],
2627 stream_id);
2628 break;
2629 }
2630
2631 return rc;
2632}
2633
2634static int msm_compr_pointer(struct snd_compr_stream *cstream,
2635 struct snd_compr_tstamp *arg)
2636{
2637 struct snd_compr_runtime *runtime = cstream->runtime;
2638 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
2639 struct msm_compr_audio *prtd = runtime->private_data;
2640 struct msm_compr_pdata *pdata = NULL;
2641 struct snd_compr_tstamp tstamp;
2642 uint64_t timestamp = 0;
2643 int rc = 0, first_buffer;
2644 unsigned long flags;
2645 uint32_t gapless_transition;
2646
2647 pdata = snd_soc_platform_get_drvdata(rtd->platform);
2648 pr_debug("%s\n", __func__);
2649 memset(&tstamp, 0x0, sizeof(struct snd_compr_tstamp));
2650
2651 spin_lock_irqsave(&prtd->lock, flags);
2652 tstamp.sampling_rate = prtd->sample_rate;
2653 tstamp.byte_offset = prtd->byte_offset;
2654 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2655 tstamp.copied_total = prtd->copied_total;
2656 else if (cstream->direction == SND_COMPRESS_CAPTURE)
2657 tstamp.copied_total = prtd->received_total;
2658 first_buffer = prtd->first_buffer;
2659 if (atomic_read(&prtd->error)) {
Vatsal Bucha0527c562017-10-04 20:38:49 +05302660 pr_err_ratelimited("%s Got RESET EVENTS notification, return error\n",
2661 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302662 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2663 runtime->total_bytes_transferred = tstamp.copied_total;
2664 else
2665 runtime->total_bytes_available = tstamp.copied_total;
2666 tstamp.pcm_io_frames = 0;
2667 memcpy(arg, &tstamp, sizeof(struct snd_compr_tstamp));
2668 spin_unlock_irqrestore(&prtd->lock, flags);
2669 return -ENETRESET;
2670 }
2671 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
2672
2673 gapless_transition = prtd->gapless_state.gapless_transition;
2674 spin_unlock_irqrestore(&prtd->lock, flags);
2675 if (gapless_transition)
2676 pr_debug("%s session time in gapless transition",
2677 __func__);
2678 /*
2679 *- Do not query if no buffer has been given.
2680 *- Do not query on a gapless transition.
2681 * Playback for the 2nd stream can start (thus returning time
2682 * starting from 0) before the driver knows about EOS of first
2683 * stream.
2684 */
2685 if (!first_buffer || gapless_transition) {
2686
2687 if (pdata->use_legacy_api)
2688 rc = q6asm_get_session_time_legacy(
2689 prtd->audio_client, &prtd->marker_timestamp);
2690 else
2691 rc = q6asm_get_session_time(
2692 prtd->audio_client, &prtd->marker_timestamp);
2693 if (rc < 0) {
2694 pr_err("%s: Get Session Time return =%lld\n",
2695 __func__, timestamp);
2696 if (atomic_read(&prtd->error))
2697 return -ENETRESET;
2698 else
2699 return -EAGAIN;
2700 }
2701 }
2702 } else {
2703 spin_unlock_irqrestore(&prtd->lock, flags);
2704 }
2705 timestamp = prtd->marker_timestamp;
2706
2707 /* DSP returns timestamp in usec */
2708 pr_debug("%s: timestamp = %lld usec\n", __func__, timestamp);
2709 timestamp *= prtd->sample_rate;
2710 tstamp.pcm_io_frames = (snd_pcm_uframes_t)div64_u64(timestamp, 1000000);
2711 memcpy(arg, &tstamp, sizeof(struct snd_compr_tstamp));
2712
2713 return 0;
2714}
2715
2716static int msm_compr_ack(struct snd_compr_stream *cstream,
2717 size_t count)
2718{
2719 struct snd_compr_runtime *runtime = cstream->runtime;
2720 struct msm_compr_audio *prtd = runtime->private_data;
2721 void *src, *dstn;
2722 size_t copy;
2723 unsigned long flags;
2724
2725 WARN(1, "This path is untested");
2726 return -EINVAL;
2727
2728 pr_debug("%s: count = %zd\n", __func__, count);
2729 if (!prtd->buffer) {
2730 pr_err("%s: Buffer is not allocated yet ??\n", __func__);
2731 return -EINVAL;
2732 }
2733 src = runtime->buffer + prtd->app_pointer;
2734 dstn = prtd->buffer + prtd->app_pointer;
2735 if (count < prtd->buffer_size - prtd->app_pointer) {
2736 memcpy(dstn, src, count);
2737 prtd->app_pointer += count;
2738 } else {
2739 copy = prtd->buffer_size - prtd->app_pointer;
2740 memcpy(dstn, src, copy);
2741 memcpy(prtd->buffer, runtime->buffer, count - copy);
2742 prtd->app_pointer = count - copy;
2743 }
2744
2745 /*
2746 * If the stream is started and all the bytes received were
2747 * copied to DSP, the newly received bytes should be
2748 * sent right away
2749 */
2750 spin_lock_irqsave(&prtd->lock, flags);
2751
2752 if (atomic_read(&prtd->start) &&
2753 prtd->bytes_received == prtd->copied_total) {
2754 prtd->bytes_received += count;
2755 msm_compr_send_buffer(prtd);
2756 } else
2757 prtd->bytes_received += count;
2758
2759 spin_unlock_irqrestore(&prtd->lock, flags);
2760
2761 return 0;
2762}
2763
2764static int msm_compr_playback_copy(struct snd_compr_stream *cstream,
2765 char __user *buf, size_t count)
2766{
2767 struct snd_compr_runtime *runtime = cstream->runtime;
2768 struct msm_compr_audio *prtd = runtime->private_data;
2769 void *dstn;
2770 size_t copy;
2771 uint64_t bytes_available = 0;
2772 unsigned long flags;
2773
2774 pr_debug("%s: count = %zd\n", __func__, count);
2775 if (!prtd->buffer) {
2776 pr_err("%s: Buffer is not allocated yet ??", __func__);
2777 return 0;
2778 }
2779
2780 spin_lock_irqsave(&prtd->lock, flags);
2781 if (atomic_read(&prtd->error)) {
2782 pr_err("%s Got RESET EVENTS notification", __func__);
2783 spin_unlock_irqrestore(&prtd->lock, flags);
2784 return -ENETRESET;
2785 }
2786 spin_unlock_irqrestore(&prtd->lock, flags);
2787
2788 dstn = prtd->buffer + prtd->app_pointer;
2789 if (count < prtd->buffer_size - prtd->app_pointer) {
2790 if (copy_from_user(dstn, buf, count))
2791 return -EFAULT;
2792 prtd->app_pointer += count;
2793 } else {
2794 copy = prtd->buffer_size - prtd->app_pointer;
2795 if (copy_from_user(dstn, buf, copy))
2796 return -EFAULT;
2797 if (copy_from_user(prtd->buffer, buf + copy, count - copy))
2798 return -EFAULT;
2799 prtd->app_pointer = count - copy;
2800 }
2801
2802 /*
2803 * If stream is started and there has been an xrun,
2804 * since the available bytes fits fragment_size, copy the data
2805 * right away.
2806 */
2807 spin_lock_irqsave(&prtd->lock, flags);
2808 prtd->bytes_received += count;
2809 if (atomic_read(&prtd->start)) {
2810 if (atomic_read(&prtd->xrun)) {
2811 pr_debug("%s: in xrun, count = %zd\n", __func__, count);
2812 bytes_available = prtd->bytes_received -
2813 prtd->copied_total;
2814 if (bytes_available >= runtime->fragment_size) {
2815 pr_debug("%s: handle xrun, bytes_to_write = %llu\n",
2816 __func__, bytes_available);
2817 atomic_set(&prtd->xrun, 0);
2818 msm_compr_send_buffer(prtd);
2819 } /* else not sufficient data */
2820 } /* writes will continue on the next write_done */
2821 }
2822
2823 spin_unlock_irqrestore(&prtd->lock, flags);
2824
2825 return count;
2826}
2827
2828static int msm_compr_capture_copy(struct snd_compr_stream *cstream,
2829 char __user *buf, size_t count)
2830{
2831 struct snd_compr_runtime *runtime = cstream->runtime;
2832 struct msm_compr_audio *prtd = runtime->private_data;
2833 void *source;
2834 unsigned long flags;
2835
2836 pr_debug("%s: count = %zd\n", __func__, count);
2837 if (!prtd->buffer) {
2838 pr_err("%s: Buffer is not allocated yet ??", __func__);
2839 return 0;
2840 }
2841
2842 spin_lock_irqsave(&prtd->lock, flags);
2843 if (atomic_read(&prtd->error)) {
2844 pr_err("%s Got RESET EVENTS notification", __func__);
2845 spin_unlock_irqrestore(&prtd->lock, flags);
2846 return -ENETRESET;
2847 }
2848
2849 source = prtd->buffer + prtd->app_pointer;
2850 /* check if we have requested amount of data to copy to user*/
2851 if (count <= prtd->received_total - prtd->bytes_copied) {
2852 spin_unlock_irqrestore(&prtd->lock, flags);
2853 if (copy_to_user(buf, source, count)) {
2854 pr_err("copy_to_user failed");
2855 return -EFAULT;
2856 }
2857 spin_lock_irqsave(&prtd->lock, flags);
2858 prtd->app_pointer += count;
2859 if (prtd->app_pointer >= prtd->buffer_size)
2860 prtd->app_pointer -= prtd->buffer_size;
2861 prtd->bytes_copied += count;
2862 }
2863 msm_compr_read_buffer(prtd);
2864
2865 spin_unlock_irqrestore(&prtd->lock, flags);
2866 return count;
2867}
2868
2869static int msm_compr_copy(struct snd_compr_stream *cstream,
2870 char __user *buf, size_t count)
2871{
2872 int ret = 0;
2873
2874 pr_debug(" In %s\n", __func__);
2875 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2876 ret = msm_compr_playback_copy(cstream, buf, count);
2877 else if (cstream->direction == SND_COMPRESS_CAPTURE)
2878 ret = msm_compr_capture_copy(cstream, buf, count);
2879 return ret;
2880}
2881
2882static int msm_compr_get_caps(struct snd_compr_stream *cstream,
2883 struct snd_compr_caps *arg)
2884{
2885 struct snd_compr_runtime *runtime = cstream->runtime;
2886 struct msm_compr_audio *prtd = runtime->private_data;
2887 int ret = 0;
2888
2889 pr_debug("%s\n", __func__);
2890 if ((arg != NULL) && (prtd != NULL)) {
2891 memcpy(arg, &prtd->compr_cap, sizeof(struct snd_compr_caps));
2892 } else {
2893 ret = -EINVAL;
2894 pr_err("%s: arg (0x%pK), prtd (0x%pK)\n", __func__, arg, prtd);
2895 }
2896
2897 return ret;
2898}
2899
2900static int msm_compr_get_codec_caps(struct snd_compr_stream *cstream,
2901 struct snd_compr_codec_caps *codec)
2902{
2903 pr_debug("%s\n", __func__);
2904
2905 switch (codec->codec) {
2906 case SND_AUDIOCODEC_MP3:
2907 codec->num_descriptors = 2;
2908 codec->descriptor[0].max_ch = 2;
2909 memcpy(codec->descriptor[0].sample_rates,
2910 supported_sample_rates,
2911 sizeof(supported_sample_rates));
2912 codec->descriptor[0].num_sample_rates =
2913 sizeof(supported_sample_rates)/sizeof(unsigned int);
2914 codec->descriptor[0].bit_rate[0] = 320; /* 320kbps */
2915 codec->descriptor[0].bit_rate[1] = 128;
2916 codec->descriptor[0].num_bitrates = 2;
2917 codec->descriptor[0].profiles = 0;
2918 codec->descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO;
2919 codec->descriptor[0].formats = 0;
2920 break;
2921 case SND_AUDIOCODEC_AAC:
2922 codec->num_descriptors = 2;
2923 codec->descriptor[1].max_ch = 2;
2924 memcpy(codec->descriptor[1].sample_rates,
2925 supported_sample_rates,
2926 sizeof(supported_sample_rates));
2927 codec->descriptor[1].num_sample_rates =
2928 sizeof(supported_sample_rates)/sizeof(unsigned int);
2929 codec->descriptor[1].bit_rate[0] = 320; /* 320kbps */
2930 codec->descriptor[1].bit_rate[1] = 128;
2931 codec->descriptor[1].num_bitrates = 2;
2932 codec->descriptor[1].profiles = 0;
2933 codec->descriptor[1].modes = 0;
2934 codec->descriptor[1].formats =
2935 (SND_AUDIOSTREAMFORMAT_MP4ADTS |
2936 SND_AUDIOSTREAMFORMAT_RAW);
2937 break;
2938 case SND_AUDIOCODEC_AC3:
2939 case SND_AUDIOCODEC_EAC3:
2940 case SND_AUDIOCODEC_FLAC:
2941 case SND_AUDIOCODEC_VORBIS:
2942 case SND_AUDIOCODEC_ALAC:
2943 case SND_AUDIOCODEC_APE:
2944 case SND_AUDIOCODEC_DTS:
2945 case SND_AUDIOCODEC_DSD:
2946 case SND_AUDIOCODEC_TRUEHD:
2947 case SND_AUDIOCODEC_IEC61937:
2948 case SND_AUDIOCODEC_APTX:
2949 break;
2950 default:
2951 pr_err("%s: Unsupported audio codec %d\n",
2952 __func__, codec->codec);
2953 return -EINVAL;
2954 }
2955
2956 return 0;
2957}
2958
2959static int msm_compr_set_metadata(struct snd_compr_stream *cstream,
2960 struct snd_compr_metadata *metadata)
2961{
2962 struct msm_compr_audio *prtd;
2963 struct audio_client *ac;
2964 pr_debug("%s\n", __func__);
2965
2966 if (!metadata || !cstream)
2967 return -EINVAL;
2968
2969 prtd = cstream->runtime->private_data;
2970 if (!prtd || !prtd->audio_client) {
2971 pr_err("%s: prtd or audio client is NULL\n", __func__);
2972 return -EINVAL;
2973 }
2974
2975 if (((metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) ||
2976 (metadata->key == SNDRV_COMPRESS_ENCODER_DELAY)) &&
2977 (prtd->compr_passthr != LEGACY_PCM)) {
2978 pr_debug("%s: No trailing silence for compress_type[%d]\n",
2979 __func__, prtd->compr_passthr);
2980 return 0;
2981 }
2982
2983 ac = prtd->audio_client;
2984 if (metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) {
2985 pr_debug("%s, got encoder padding %u",
2986 __func__, metadata->value[0]);
2987 prtd->gapless_state.trailing_samples_drop = metadata->value[0];
2988 } else if (metadata->key == SNDRV_COMPRESS_ENCODER_DELAY) {
2989 pr_debug("%s, got encoder delay %u",
2990 __func__, metadata->value[0]);
2991 prtd->gapless_state.initial_samples_drop = metadata->value[0];
2992 } else if (metadata->key == SNDRV_COMPRESS_RENDER_MODE) {
2993 return msm_compr_set_render_mode(prtd, metadata->value[0]);
2994 } else if (metadata->key == SNDRV_COMPRESS_CLK_REC_MODE) {
2995 return msm_compr_set_clk_rec_mode(ac, metadata->value[0]);
2996 } else if (metadata->key == SNDRV_COMPRESS_RENDER_WINDOW) {
2997 return msm_compr_set_render_window(
2998 ac,
2999 metadata->value[0],
3000 metadata->value[1],
3001 metadata->value[2],
3002 metadata->value[3]);
3003 } else if (metadata->key == SNDRV_COMPRESS_START_DELAY) {
3004 prtd->start_delay_lsw = metadata->value[0];
3005 prtd->start_delay_msw = metadata->value[1];
3006 } else if (metadata->key ==
3007 SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK) {
3008 return msm_compr_enable_adjust_session_clock(ac,
3009 metadata->value[0]);
3010 } else if (metadata->key == SNDRV_COMPRESS_ADJUST_SESSION_CLOCK) {
3011 return msm_compr_adjust_session_clock(ac,
3012 metadata->value[0],
3013 metadata->value[1]);
3014 }
3015
3016 return 0;
3017}
3018
3019static int msm_compr_get_metadata(struct snd_compr_stream *cstream,
3020 struct snd_compr_metadata *metadata)
3021{
3022 struct msm_compr_audio *prtd;
3023 struct audio_client *ac;
3024 int ret = -EINVAL;
3025
3026 pr_debug("%s\n", __func__);
3027
3028 if (!metadata || !cstream || !cstream->runtime)
3029 return ret;
3030
3031 if (metadata->key != SNDRV_COMPRESS_PATH_DELAY) {
3032 pr_err("%s, unsupported key %d\n", __func__, metadata->key);
3033 return ret;
3034 }
3035
3036 prtd = cstream->runtime->private_data;
3037 if (!prtd || !prtd->audio_client) {
3038 pr_err("%s: prtd or audio client is NULL\n", __func__);
3039 return ret;
3040 }
3041
3042 ac = prtd->audio_client;
3043 ret = q6asm_get_path_delay(prtd->audio_client);
3044 if (ret) {
3045 pr_err("%s: get_path_delay failed, ret=%d\n", __func__, ret);
3046 return ret;
3047 }
3048
3049 pr_debug("%s, path delay(in us) %u\n", __func__, ac->path_delay);
3050
3051 metadata->value[0] = ac->path_delay;
3052
3053 return ret;
3054}
3055
3056
3057static int msm_compr_set_next_track_param(struct snd_compr_stream *cstream,
3058 union snd_codec_options *codec_options)
3059{
3060 struct msm_compr_audio *prtd;
3061 struct audio_client *ac;
3062 int ret = 0;
3063
3064 if (!codec_options || !cstream)
3065 return -EINVAL;
3066
3067 prtd = cstream->runtime->private_data;
3068 if (!prtd || !prtd->audio_client) {
3069 pr_err("%s: prtd or audio client is NULL\n", __func__);
3070 return -EINVAL;
3071 }
3072
3073 ac = prtd->audio_client;
3074
3075 pr_debug("%s: got codec options for codec type %u",
3076 __func__, prtd->codec);
3077 switch (prtd->codec) {
3078 case FORMAT_WMA_V9:
3079 case FORMAT_WMA_V10PRO:
3080 case FORMAT_FLAC:
3081 case FORMAT_VORBIS:
3082 case FORMAT_ALAC:
3083 case FORMAT_APE:
3084 memcpy(&(prtd->gapless_state.codec_options),
3085 codec_options,
3086 sizeof(union snd_codec_options));
3087 ret = msm_compr_send_media_format_block(cstream,
3088 ac->stream_id, true);
3089 if (ret < 0) {
3090 pr_err("%s: failed to send media format block\n",
3091 __func__);
3092 }
3093 break;
3094
3095 default:
3096 pr_debug("%s: Ignore sending CMD Format block\n",
3097 __func__);
3098 break;
3099 }
3100
3101 return ret;
3102}
3103
3104static int msm_compr_volume_put(struct snd_kcontrol *kcontrol,
3105 struct snd_ctl_elem_value *ucontrol)
3106{
3107 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3108 unsigned long fe_id = kcontrol->private_value;
3109 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3110 snd_soc_component_get_drvdata(comp);
3111 struct snd_compr_stream *cstream = NULL;
3112 uint32_t *volume = NULL;
3113
3114 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3115 pr_err("%s Received out of bounds fe_id %lu\n",
3116 __func__, fe_id);
3117 return -EINVAL;
3118 }
3119
3120 cstream = pdata->cstream[fe_id];
3121 volume = pdata->volume[fe_id];
3122
3123 volume[0] = ucontrol->value.integer.value[0];
3124 volume[1] = ucontrol->value.integer.value[1];
3125 pr_debug("%s: fe_id %lu left_vol %d right_vol %d\n",
3126 __func__, fe_id, volume[0], volume[1]);
3127 if (cstream)
3128 msm_compr_set_volume(cstream, volume[0], volume[1]);
3129 return 0;
3130}
3131
3132static int msm_compr_volume_get(struct snd_kcontrol *kcontrol,
3133 struct snd_ctl_elem_value *ucontrol)
3134{
3135 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3136 unsigned long fe_id = kcontrol->private_value;
3137
3138 struct msm_compr_pdata *pdata =
3139 snd_soc_component_get_drvdata(comp);
3140 uint32_t *volume = NULL;
3141
3142 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3143 pr_err("%s Received out of bound fe_id %lu\n", __func__, fe_id);
3144 return -EINVAL;
3145 }
3146
3147 volume = pdata->volume[fe_id];
3148 pr_debug("%s: fe_id %lu\n", __func__, fe_id);
3149 ucontrol->value.integer.value[0] = volume[0];
3150 ucontrol->value.integer.value[1] = volume[1];
3151
3152 return 0;
3153}
3154
3155static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
3156 struct snd_ctl_elem_value *ucontrol)
3157{
3158 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3159 unsigned long fe_id = kcontrol->private_value;
3160 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3161 snd_soc_component_get_drvdata(comp);
3162 struct msm_compr_audio_effects *audio_effects = NULL;
3163 struct snd_compr_stream *cstream = NULL;
3164 struct msm_compr_audio *prtd = NULL;
3165 long *values = &(ucontrol->value.integer.value[0]);
Ajit Pandey233bdea2019-09-04 14:34:00 +05303166 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303167 int effects_module;
3168
3169 pr_debug("%s\n", __func__);
3170 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3171 pr_err("%s Received out of bounds fe_id %lu\n",
3172 __func__, fe_id);
3173 return -EINVAL;
3174 }
Ajit Pandey233bdea2019-09-04 14:34:00 +05303175
3176 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303177 cstream = pdata->cstream[fe_id];
3178 audio_effects = pdata->audio_effects[fe_id];
3179 if (!cstream || !audio_effects) {
3180 pr_err("%s: stream or effects inactive\n", __func__);
Ajit Pandey233bdea2019-09-04 14:34:00 +05303181 ret = -EINVAL;
3182 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303183 }
3184 prtd = cstream->runtime->private_data;
3185 if (!prtd) {
3186 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandey233bdea2019-09-04 14:34:00 +05303187 ret = -EINVAL;
3188 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303189 }
3190 if (prtd->compr_passthr != LEGACY_PCM) {
3191 pr_debug("%s: No effects for compr_type[%d]\n",
3192 __func__, prtd->compr_passthr);
Ajit Pandey233bdea2019-09-04 14:34:00 +05303193 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303194 }
3195 pr_debug("%s: Effects supported for compr_type[%d]\n",
3196 __func__, prtd->compr_passthr);
3197
3198 effects_module = *values++;
3199 switch (effects_module) {
3200 case VIRTUALIZER_MODULE:
3201 pr_debug("%s: VIRTUALIZER_MODULE\n", __func__);
3202 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3203 prtd->audio_client->topology))
3204 msm_audio_effects_virtualizer_handler(
3205 prtd->audio_client,
3206 &(audio_effects->virtualizer),
3207 values);
3208 break;
3209 case REVERB_MODULE:
3210 pr_debug("%s: REVERB_MODULE\n", __func__);
3211 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3212 prtd->audio_client->topology))
3213 msm_audio_effects_reverb_handler(prtd->audio_client,
3214 &(audio_effects->reverb),
3215 values);
3216 break;
3217 case BASS_BOOST_MODULE:
3218 pr_debug("%s: BASS_BOOST_MODULE\n", __func__);
3219 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3220 prtd->audio_client->topology))
3221 msm_audio_effects_bass_boost_handler(prtd->audio_client,
3222 &(audio_effects->bass_boost),
3223 values);
3224 break;
3225 case PBE_MODULE:
3226 pr_debug("%s: PBE_MODULE\n", __func__);
3227 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3228 prtd->audio_client->topology))
3229 msm_audio_effects_pbe_handler(prtd->audio_client,
3230 &(audio_effects->pbe),
3231 values);
3232 break;
3233 case EQ_MODULE:
3234 pr_debug("%s: EQ_MODULE\n", __func__);
3235 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3236 prtd->audio_client->topology))
3237 msm_audio_effects_popless_eq_handler(prtd->audio_client,
3238 &(audio_effects->equalizer),
3239 values);
3240 break;
3241 case SOFT_VOLUME_MODULE:
3242 pr_debug("%s: SOFT_VOLUME_MODULE\n", __func__);
3243 break;
3244 case SOFT_VOLUME2_MODULE:
3245 pr_debug("%s: SOFT_VOLUME2_MODULE\n", __func__);
3246 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3247 prtd->audio_client->topology))
3248 msm_audio_effects_volume_handler_v2(prtd->audio_client,
3249 &(audio_effects->volume),
3250 values, SOFT_VOLUME_INSTANCE_2);
3251 break;
3252 default:
3253 pr_err("%s Invalid effects config module\n", __func__);
Ajit Pandey233bdea2019-09-04 14:34:00 +05303254 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303255 }
Ajit Pandey233bdea2019-09-04 14:34:00 +05303256done:
3257 mutex_unlock(&pdata->lock);
3258 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303259}
3260
3261static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol,
3262 struct snd_ctl_elem_value *ucontrol)
3263{
3264 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3265 unsigned long fe_id = kcontrol->private_value;
3266 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3267 snd_soc_component_get_drvdata(comp);
3268 struct msm_compr_audio_effects *audio_effects = NULL;
3269 struct snd_compr_stream *cstream = NULL;
Ajit Pandey233bdea2019-09-04 14:34:00 +05303270 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303271 struct msm_compr_audio *prtd = NULL;
3272
3273 pr_debug("%s\n", __func__);
3274 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3275 pr_err("%s Received out of bounds fe_id %lu\n",
3276 __func__, fe_id);
3277 return -EINVAL;
3278 }
Ajit Pandey233bdea2019-09-04 14:34:00 +05303279
3280 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303281 cstream = pdata->cstream[fe_id];
3282 audio_effects = pdata->audio_effects[fe_id];
3283 if (!cstream || !audio_effects) {
Ajit Pandey233bdea2019-09-04 14:34:00 +05303284 pr_debug("%s: stream or effects inactive\n", __func__);
3285 ret = -EINVAL;
3286 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303287 }
3288 prtd = cstream->runtime->private_data;
3289 if (!prtd) {
3290 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandey233bdea2019-09-04 14:34:00 +05303291 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303292 }
Ajit Pandey233bdea2019-09-04 14:34:00 +05303293done:
3294 mutex_unlock(&pdata->lock);
3295 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303296}
3297
3298static int msm_compr_query_audio_effect_put(struct snd_kcontrol *kcontrol,
3299 struct snd_ctl_elem_value *ucontrol)
3300{
3301 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3302 unsigned long fe_id = kcontrol->private_value;
3303 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3304 snd_soc_component_get_drvdata(comp);
3305 struct msm_compr_audio_effects *audio_effects = NULL;
3306 struct snd_compr_stream *cstream = NULL;
3307 struct msm_compr_audio *prtd = NULL;
Ajit Pandey233bdea2019-09-04 14:34:00 +05303308 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303309 long *values = &(ucontrol->value.integer.value[0]);
3310
3311 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3312 pr_err("%s Received out of bounds fe_id %lu\n",
3313 __func__, fe_id);
3314 return -EINVAL;
3315 }
Ajit Pandey233bdea2019-09-04 14:34:00 +05303316
3317 mutex_lock(&pdata->lock);
3318
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303319 cstream = pdata->cstream[fe_id];
3320 audio_effects = pdata->audio_effects[fe_id];
3321 if (!cstream || !audio_effects) {
3322 pr_err("%s: stream or effects inactive\n", __func__);
Ajit Pandey233bdea2019-09-04 14:34:00 +05303323 ret = -EINVAL;
3324 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303325 }
3326 prtd = cstream->runtime->private_data;
3327 if (!prtd) {
3328 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandey233bdea2019-09-04 14:34:00 +05303329 ret = -EINVAL;
3330 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303331 }
3332 if (prtd->compr_passthr != LEGACY_PCM) {
3333 pr_err("%s: No effects for compr_type[%d]\n",
3334 __func__, prtd->compr_passthr);
Ajit Pandey233bdea2019-09-04 14:34:00 +05303335 ret = -EPERM;
3336 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303337 }
3338 audio_effects->query.mod_id = (u32)*values++;
3339 audio_effects->query.parm_id = (u32)*values++;
3340 audio_effects->query.size = (u32)*values++;
3341 audio_effects->query.offset = (u32)*values++;
3342 audio_effects->query.device = (u32)*values++;
Ajit Pandey233bdea2019-09-04 14:34:00 +05303343
3344done:
3345 mutex_unlock(&pdata->lock);
3346 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303347}
3348
3349static int msm_compr_query_audio_effect_get(struct snd_kcontrol *kcontrol,
3350 struct snd_ctl_elem_value *ucontrol)
3351{
3352 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3353 unsigned long fe_id = kcontrol->private_value;
3354 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3355 snd_soc_component_get_drvdata(comp);
3356 struct msm_compr_audio_effects *audio_effects = NULL;
3357 struct snd_compr_stream *cstream = NULL;
3358 struct msm_compr_audio *prtd = NULL;
Ajit Pandey233bdea2019-09-04 14:34:00 +05303359 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303360 long *values = &(ucontrol->value.integer.value[0]);
3361
3362 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3363 pr_err("%s Received out of bounds fe_id %lu\n",
3364 __func__, fe_id);
3365 return -EINVAL;
3366 }
Ajit Pandey233bdea2019-09-04 14:34:00 +05303367
3368 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303369 cstream = pdata->cstream[fe_id];
3370 audio_effects = pdata->audio_effects[fe_id];
3371 if (!cstream || !audio_effects) {
3372 pr_debug("%s: stream or effects inactive\n", __func__);
Ajit Pandey233bdea2019-09-04 14:34:00 +05303373 ret = -EINVAL;
3374 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303375 }
3376 prtd = cstream->runtime->private_data;
3377 if (!prtd) {
3378 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandey233bdea2019-09-04 14:34:00 +05303379 ret = -EINVAL;
3380 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303381 }
3382 values[0] = (long)audio_effects->query.mod_id;
3383 values[1] = (long)audio_effects->query.parm_id;
3384 values[2] = (long)audio_effects->query.size;
3385 values[3] = (long)audio_effects->query.offset;
3386 values[4] = (long)audio_effects->query.device;
Ajit Pandey233bdea2019-09-04 14:34:00 +05303387done:
3388 mutex_unlock(&pdata->lock);
3389 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303390}
3391
3392static int msm_compr_send_dec_params(struct snd_compr_stream *cstream,
3393 struct msm_compr_dec_params *dec_params,
3394 int stream_id)
3395{
3396
3397 int rc = 0;
3398 struct msm_compr_audio *prtd = NULL;
3399 struct snd_dec_ddp *ddp = &dec_params->ddp_params;
3400
3401 if (!cstream || !dec_params) {
3402 pr_err("%s: stream or dec_params inactive\n", __func__);
3403 rc = -EINVAL;
3404 goto end;
3405 }
3406 prtd = cstream->runtime->private_data;
3407 if (!prtd) {
3408 pr_err("%s: cannot set dec_params\n", __func__);
3409 rc = -EINVAL;
3410 goto end;
3411 }
3412 switch (prtd->codec) {
3413 case FORMAT_MP3:
3414 case FORMAT_MPEG4_AAC:
3415 case FORMAT_TRUEHD:
3416 case FORMAT_IEC61937:
3417 case FORMAT_APTX:
3418 pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
3419 prtd->codec);
3420 break;
3421 case FORMAT_AC3:
3422 case FORMAT_EAC3:
3423 if (prtd->compr_passthr != LEGACY_PCM) {
3424 pr_debug("%s: No DDP param for compr_type[%d]\n",
3425 __func__, prtd->compr_passthr);
3426 break;
3427 }
3428 rc = msm_compr_send_ddp_cfg(prtd->audio_client, ddp, stream_id);
3429 if (rc < 0)
3430 pr_err("%s: DDP CMD CFG failed %d\n", __func__, rc);
3431 break;
3432 default:
3433 break;
3434 }
3435end:
3436 return rc;
3437
3438}
3439static int msm_compr_dec_params_put(struct snd_kcontrol *kcontrol,
3440 struct snd_ctl_elem_value *ucontrol)
3441{
3442 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3443 unsigned long fe_id = kcontrol->private_value;
3444 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3445 snd_soc_component_get_drvdata(comp);
3446 struct msm_compr_dec_params *dec_params = NULL;
3447 struct snd_compr_stream *cstream = NULL;
3448 struct msm_compr_audio *prtd = NULL;
3449 long *values = &(ucontrol->value.integer.value[0]);
3450 int rc = 0;
3451
3452 pr_debug("%s\n", __func__);
3453 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3454 pr_err("%s Received out of bounds fe_id %lu\n",
3455 __func__, fe_id);
Ajit Pandey9a5480e2019-10-24 13:45:11 +05303456 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303457 }
3458
3459 cstream = pdata->cstream[fe_id];
3460 dec_params = pdata->dec_params[fe_id];
3461
3462 if (!cstream || !dec_params) {
3463 pr_err("%s: stream or dec_params inactive\n", __func__);
Ajit Pandey9a5480e2019-10-24 13:45:11 +05303464 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303465 }
3466 prtd = cstream->runtime->private_data;
3467 if (!prtd) {
3468 pr_err("%s: cannot set dec_params\n", __func__);
Ajit Pandey9a5480e2019-10-24 13:45:11 +05303469 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303470 }
3471
Ajit Pandey233bdea2019-09-04 14:34:00 +05303472 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303473 switch (prtd->codec) {
3474 case FORMAT_MP3:
3475 case FORMAT_MPEG4_AAC:
3476 case FORMAT_FLAC:
3477 case FORMAT_VORBIS:
3478 case FORMAT_ALAC:
3479 case FORMAT_APE:
3480 case FORMAT_DTS:
3481 case FORMAT_DSD:
3482 case FORMAT_TRUEHD:
3483 case FORMAT_IEC61937:
3484 case FORMAT_APTX:
3485 pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
3486 prtd->codec);
3487 break;
3488 case FORMAT_AC3:
3489 case FORMAT_EAC3: {
3490 struct snd_dec_ddp *ddp = &dec_params->ddp_params;
3491 int cnt;
3492
3493 if (prtd->compr_passthr != LEGACY_PCM) {
3494 pr_debug("%s: No DDP param for compr_type[%d]\n",
3495 __func__, prtd->compr_passthr);
3496 break;
3497 }
3498
3499 ddp->params_length = (*values++);
3500 if (ddp->params_length > DDP_DEC_MAX_NUM_PARAM) {
3501 pr_err("%s: invalid num of params:: %d\n", __func__,
3502 ddp->params_length);
3503 rc = -EINVAL;
Ajit Pandey233bdea2019-09-04 14:34:00 +05303504 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303505 goto end;
3506 }
3507 for (cnt = 0; cnt < ddp->params_length; cnt++) {
3508 ddp->params_id[cnt] = *values++;
3509 ddp->params_value[cnt] = *values++;
3510 }
3511 prtd = cstream->runtime->private_data;
3512 if (prtd && prtd->audio_client)
3513 rc = msm_compr_send_dec_params(cstream, dec_params,
3514 prtd->audio_client->stream_id);
3515 break;
3516 }
3517 default:
3518 break;
3519 }
Ajit Pandey233bdea2019-09-04 14:34:00 +05303520 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303521end:
3522 pr_debug("%s: ret %d\n", __func__, rc);
3523 return rc;
3524}
3525
3526static int msm_compr_dec_params_get(struct snd_kcontrol *kcontrol,
3527 struct snd_ctl_elem_value *ucontrol)
3528{
3529 /* dummy function */
3530 return 0;
3531}
3532
3533static int msm_compr_playback_app_type_cfg_put(struct snd_kcontrol *kcontrol,
3534 struct snd_ctl_elem_value *ucontrol)
3535{
3536 u64 fe_id = kcontrol->private_value;
3537 int session_type = SESSION_TYPE_RX;
3538 int be_id = ucontrol->value.integer.value[3];
3539 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
3540 int ret = 0;
3541
3542 cfg_data.app_type = ucontrol->value.integer.value[0];
3543 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
3544 if (ucontrol->value.integer.value[2] != 0)
3545 cfg_data.sample_rate = ucontrol->value.integer.value[2];
3546 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
3547 __func__, fe_id, session_type, be_id,
3548 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3549 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
3550 be_id, &cfg_data);
3551 if (ret < 0)
3552 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
3553 __func__, ret);
3554
3555 return ret;
3556}
3557
3558static int msm_compr_playback_app_type_cfg_get(struct snd_kcontrol *kcontrol,
3559 struct snd_ctl_elem_value *ucontrol)
3560{
3561 u64 fe_id = kcontrol->private_value;
3562 int session_type = SESSION_TYPE_RX;
3563 int be_id = 0;
3564 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
3565 int ret = 0;
3566
3567 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
3568 &be_id, &cfg_data);
3569 if (ret < 0) {
3570 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
3571 __func__, ret);
3572 goto done;
3573 }
3574
3575 ucontrol->value.integer.value[0] = cfg_data.app_type;
3576 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
3577 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
3578 ucontrol->value.integer.value[3] = be_id;
3579 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
3580 __func__, fe_id, session_type, be_id,
3581 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3582done:
3583 return ret;
3584}
3585
3586static int msm_compr_capture_app_type_cfg_put(struct snd_kcontrol *kcontrol,
3587 struct snd_ctl_elem_value *ucontrol)
3588{
3589 u64 fe_id = kcontrol->private_value;
3590 int session_type = SESSION_TYPE_TX;
3591 int be_id = ucontrol->value.integer.value[3];
3592 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
3593 int ret = 0;
3594
3595 cfg_data.app_type = ucontrol->value.integer.value[0];
3596 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
3597 if (ucontrol->value.integer.value[2] != 0)
3598 cfg_data.sample_rate = ucontrol->value.integer.value[2];
3599 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
3600 __func__, fe_id, session_type, be_id,
3601 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3602 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
3603 be_id, &cfg_data);
3604 if (ret < 0)
3605 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
3606 __func__, ret);
3607
3608 return ret;
3609}
3610
3611static int msm_compr_capture_app_type_cfg_get(struct snd_kcontrol *kcontrol,
3612 struct snd_ctl_elem_value *ucontrol)
3613{
3614 u64 fe_id = kcontrol->private_value;
3615 int session_type = SESSION_TYPE_TX;
3616 int be_id = 0;
3617 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
3618 int ret = 0;
3619
3620 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
3621 &be_id, &cfg_data);
3622 if (ret < 0) {
3623 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
3624 __func__, ret);
3625 goto done;
3626 }
3627
3628 ucontrol->value.integer.value[0] = cfg_data.app_type;
3629 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
3630 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
3631 ucontrol->value.integer.value[3] = be_id;
3632 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
3633 __func__, fe_id, session_type, be_id,
3634 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3635done:
3636 return ret;
3637}
3638
3639static int msm_compr_channel_map_put(struct snd_kcontrol *kcontrol,
3640 struct snd_ctl_elem_value *ucontrol)
3641{
3642 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3643 u64 fe_id = kcontrol->private_value;
3644 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3645 snd_soc_component_get_drvdata(comp);
3646 int rc = 0, i;
3647
3648 pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
3649
3650 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3651 pr_err("%s Received out of bounds fe_id %llu\n",
3652 __func__, fe_id);
3653 rc = -EINVAL;
3654 goto end;
3655 }
3656
3657 if (pdata->ch_map[fe_id]) {
3658 pdata->ch_map[fe_id]->set_ch_map = true;
Dieter Lueckingba7644d2018-09-28 15:09:32 +02003659 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303660 pdata->ch_map[fe_id]->channel_map[i] =
3661 (char)(ucontrol->value.integer.value[i]);
3662 } else {
3663 pr_debug("%s: no memory for ch_map, default will be set\n",
3664 __func__);
3665 }
3666end:
3667 pr_debug("%s: ret %d\n", __func__, rc);
3668 return rc;
3669}
3670
3671static int msm_compr_channel_map_get(struct snd_kcontrol *kcontrol,
3672 struct snd_ctl_elem_value *ucontrol)
3673{
3674 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3675 u64 fe_id = kcontrol->private_value;
3676 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3677 snd_soc_component_get_drvdata(comp);
3678 int rc = 0, i;
3679
3680 pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
3681 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3682 pr_err("%s: Received out of bounds fe_id %llu\n",
3683 __func__, fe_id);
3684 rc = -EINVAL;
3685 goto end;
3686 }
3687 if (pdata->ch_map[fe_id]) {
Dieter Lueckingba7644d2018-09-28 15:09:32 +02003688 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303689 ucontrol->value.integer.value[i] =
3690 pdata->ch_map[fe_id]->channel_map[i];
3691 }
3692end:
3693 pr_debug("%s: ret %d\n", __func__, rc);
3694 return rc;
3695}
3696
3697static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
3698 struct snd_ctl_elem_value *ucontrol)
3699{
3700 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3701 unsigned long fe_id = kcontrol->private_value;
3702 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3703 snd_soc_component_get_drvdata(comp);
3704 struct snd_compr_stream *cstream = NULL;
3705 struct msm_compr_audio *prtd;
3706 int ret = 0;
3707 struct msm_adsp_event_data *event_data = NULL;
Aditya Bavanari2e3341d2018-02-23 12:58:57 +05303708 uint64_t actual_payload_len = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303709
Ajit Pandey233bdea2019-09-04 14:34:00 +05303710 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303711 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3712 pr_err("%s Received invalid fe_id %lu\n",
3713 __func__, fe_id);
3714 ret = -EINVAL;
3715 goto done;
3716 }
3717
3718 cstream = pdata->cstream[fe_id];
3719 if (cstream == NULL) {
3720 pr_err("%s cstream is null\n", __func__);
3721 ret = -EINVAL;
3722 goto done;
3723 }
3724
3725 prtd = cstream->runtime->private_data;
3726 if (!prtd) {
3727 pr_err("%s: prtd is null\n", __func__);
3728 ret = -EINVAL;
3729 goto done;
3730 }
3731
3732 if (prtd->audio_client == NULL) {
3733 pr_err("%s: audio_client is null\n", __func__);
3734 ret = -EINVAL;
3735 goto done;
3736 }
3737
3738 event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data;
3739 if ((event_data->event_type < ADSP_STREAM_PP_EVENT) ||
3740 (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) {
3741 pr_err("%s: invalid event_type=%d",
3742 __func__, event_data->event_type);
3743 ret = -EINVAL;
3744 goto done;
3745 }
3746
Aditya Bavanari2e3341d2018-02-23 12:58:57 +05303747 actual_payload_len = sizeof(struct msm_adsp_event_data) +
3748 event_data->payload_len;
3749 if (actual_payload_len >= U32_MAX) {
3750 pr_err("%s payload length 0x%X exceeds limit",
3751 __func__, event_data->payload_len);
3752 ret = -EINVAL;
3753 goto done;
3754 }
3755
Xiaojun Sangae3d8862018-03-23 08:57:33 +08003756 if (event_data->payload_len > sizeof(ucontrol->value.bytes.data)
3757 - sizeof(struct msm_adsp_event_data)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303758 pr_err("%s param length=%d exceeds limit",
3759 __func__, event_data->payload_len);
3760 ret = -EINVAL;
3761 goto done;
3762 }
3763
3764 ret = q6asm_send_stream_cmd(prtd->audio_client, event_data);
3765 if (ret < 0)
3766 pr_err("%s: failed to send stream event cmd, err = %d\n",
3767 __func__, ret);
3768done:
Ajit Pandey233bdea2019-09-04 14:34:00 +05303769 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303770 return ret;
3771}
3772
3773static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
3774 struct snd_ctl_elem_value *ucontrol)
3775{
3776 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3777 unsigned long fe_id = kcontrol->private_value;
3778 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3779 snd_soc_component_get_drvdata(comp);
3780 struct snd_compr_stream *cstream = NULL;
3781 struct msm_compr_audio *prtd;
3782 int fd;
3783 int ret = 0;
3784
Ajit Pandey233bdea2019-09-04 14:34:00 +05303785 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303786 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3787 pr_err("%s Received out of bounds invalid fe_id %lu\n",
3788 __func__, fe_id);
3789 ret = -EINVAL;
3790 goto done;
3791 }
3792
3793 cstream = pdata->cstream[fe_id];
3794 if (cstream == NULL) {
3795 pr_err("%s cstream is null\n", __func__);
3796 ret = -EINVAL;
3797 goto done;
3798 }
3799
3800 prtd = cstream->runtime->private_data;
3801 if (!prtd) {
3802 pr_err("%s: prtd is null\n", __func__);
3803 ret = -EINVAL;
3804 goto done;
3805 }
3806
3807 if (prtd->audio_client == NULL) {
3808 pr_err("%s: audio_client is null\n", __func__);
3809 ret = -EINVAL;
3810 goto done;
3811 }
3812
3813 memcpy(&fd, ucontrol->value.bytes.data, sizeof(fd));
3814 ret = q6asm_send_ion_fd(prtd->audio_client, fd);
3815 if (ret < 0)
3816 pr_err("%s: failed to register ion fd\n", __func__);
3817done:
Ajit Pandey233bdea2019-09-04 14:34:00 +05303818 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303819 return ret;
3820}
3821
3822static int msm_compr_rtic_event_ack_put(struct snd_kcontrol *kcontrol,
3823 struct snd_ctl_elem_value *ucontrol)
3824{
3825 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3826 unsigned long fe_id = kcontrol->private_value;
3827 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3828 snd_soc_component_get_drvdata(comp);
3829 struct snd_compr_stream *cstream = NULL;
3830 struct msm_compr_audio *prtd;
3831 int ret = 0;
3832 int param_length = 0;
3833
Ajit Pandey233bdea2019-09-04 14:34:00 +05303834 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303835 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3836 pr_err("%s Received invalid fe_id %lu\n",
3837 __func__, fe_id);
3838 ret = -EINVAL;
3839 goto done;
3840 }
3841
3842 cstream = pdata->cstream[fe_id];
3843 if (cstream == NULL) {
3844 pr_err("%s cstream is null\n", __func__);
3845 ret = -EINVAL;
3846 goto done;
3847 }
3848
3849 prtd = cstream->runtime->private_data;
3850 if (!prtd) {
3851 pr_err("%s: prtd is null\n", __func__);
3852 ret = -EINVAL;
3853 goto done;
3854 }
3855
3856 if (prtd->audio_client == NULL) {
3857 pr_err("%s: audio_client is null\n", __func__);
3858 ret = -EINVAL;
3859 goto done;
3860 }
3861
3862 memcpy(&param_length, ucontrol->value.bytes.data,
3863 sizeof(param_length));
3864 if ((param_length + sizeof(param_length))
3865 >= sizeof(ucontrol->value.bytes.data)) {
3866 pr_err("%s param length=%d exceeds limit",
3867 __func__, param_length);
3868 ret = -EINVAL;
3869 goto done;
3870 }
3871
3872 ret = q6asm_send_rtic_event_ack(prtd->audio_client,
3873 ucontrol->value.bytes.data + sizeof(param_length),
3874 param_length);
3875 if (ret < 0)
3876 pr_err("%s: failed to send rtic event ack, err = %d\n",
3877 __func__, ret);
3878done:
Ajit Pandey233bdea2019-09-04 14:34:00 +05303879 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303880 return ret;
3881}
3882
3883static int msm_compr_gapless_put(struct snd_kcontrol *kcontrol,
3884 struct snd_ctl_elem_value *ucontrol)
3885{
3886 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3887 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3888 snd_soc_component_get_drvdata(comp);
3889 pdata->use_dsp_gapless_mode = ucontrol->value.integer.value[0];
3890 pr_debug("%s: value: %ld\n", __func__,
3891 ucontrol->value.integer.value[0]);
3892
3893 return 0;
3894}
3895
3896static int msm_compr_gapless_get(struct snd_kcontrol *kcontrol,
3897 struct snd_ctl_elem_value *ucontrol)
3898{
3899 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3900 struct msm_compr_pdata *pdata =
3901 snd_soc_component_get_drvdata(comp);
3902 pr_debug("%s:gapless mode %d\n", __func__, pdata->use_dsp_gapless_mode);
3903 ucontrol->value.integer.value[0] = pdata->use_dsp_gapless_mode;
3904
3905 return 0;
3906}
3907
3908static const struct snd_kcontrol_new msm_compr_gapless_controls[] = {
3909 SOC_SINGLE_EXT("Compress Gapless Playback",
3910 0, 0, 1, 0,
3911 msm_compr_gapless_get,
3912 msm_compr_gapless_put),
3913};
3914
3915static int msm_compr_probe(struct snd_soc_platform *platform)
3916{
3917 struct msm_compr_pdata *pdata;
3918 int i;
3919 int rc;
3920 const char *qdsp_version;
3921
3922 pr_debug("%s\n", __func__);
3923 pdata = (struct msm_compr_pdata *)
3924 kzalloc(sizeof(*pdata), GFP_KERNEL);
3925 if (!pdata)
3926 return -ENOMEM;
3927
Ajit Pandey233bdea2019-09-04 14:34:00 +05303928 mutex_init(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303929 snd_soc_platform_set_drvdata(platform, pdata);
3930
3931 for (i = 0; i < MSM_FRONTEND_DAI_MAX; i++) {
3932 pdata->volume[i][0] = COMPRESSED_LR_VOL_MAX_STEPS;
3933 pdata->volume[i][1] = COMPRESSED_LR_VOL_MAX_STEPS;
3934 pdata->audio_effects[i] = NULL;
3935 pdata->dec_params[i] = NULL;
3936 pdata->cstream[i] = NULL;
3937 pdata->ch_map[i] = NULL;
Aditya Bavanari9deef912017-11-20 13:31:31 +05303938 pdata->is_in_use[i] = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303939 }
3940
3941 snd_soc_add_platform_controls(platform, msm_compr_gapless_controls,
3942 ARRAY_SIZE(msm_compr_gapless_controls));
3943
3944 rc = of_property_read_string(platform->dev->of_node,
3945 "qcom,adsp-version", &qdsp_version);
3946 if (!rc) {
3947 if (!strcmp(qdsp_version, "MDSP 1.2"))
3948 pdata->use_legacy_api = true;
3949 else
3950 pdata->use_legacy_api = false;
3951 } else
3952 pdata->use_legacy_api = false;
3953
3954 pr_debug("%s: use legacy api %d\n", __func__, pdata->use_legacy_api);
3955 /*
3956 * use_dsp_gapless_mode part of platform data(pdata) is updated from HAL
3957 * through a mixer control before compress driver is opened. The mixer
3958 * control is used to decide if dsp gapless mode needs to be enabled.
3959 * Gapless is disabled by default.
3960 */
3961 pdata->use_dsp_gapless_mode = false;
3962 return 0;
3963}
3964
Dhanalakshmi Siddani040e0262018-11-26 23:01:26 +05303965static int msm_compr_chmix_cfg_ctl_info(struct snd_kcontrol *kcontrol,
3966 struct snd_ctl_elem_info *uinfo)
3967{
3968 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3969 uinfo->count = 128;
3970 uinfo->value.integer.min = 0;
3971 uinfo->value.integer.max = 0xFFFFFFFF;
Ajit Pandey233bdea2019-09-04 14:34:00 +05303972
3973 return 0;
3974}
3975
3976static int msm_compr_remove(struct snd_soc_platform *platform)
3977{
3978
3979 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3980 snd_soc_platform_get_drvdata(platform);
3981 if (!pdata) {
3982 pr_err("%s pdata is null\n", __func__);
3983 return -ENOMEM;
3984 }
3985
3986 mutex_destroy(&pdata->lock);
3987 kfree(pdata);
3988
Dhanalakshmi Siddani040e0262018-11-26 23:01:26 +05303989 return 0;
3990}
3991
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303992static int msm_compr_volume_info(struct snd_kcontrol *kcontrol,
3993 struct snd_ctl_elem_info *uinfo)
3994{
3995 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3996 uinfo->count = 2;
3997 uinfo->value.integer.min = 0;
3998 uinfo->value.integer.max = COMPRESSED_LR_VOL_MAX_STEPS;
3999 return 0;
4000}
4001
4002static int msm_compr_audio_effects_config_info(struct snd_kcontrol *kcontrol,
4003 struct snd_ctl_elem_info *uinfo)
4004{
4005 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4006 uinfo->count = MAX_PP_PARAMS_SZ;
4007 uinfo->value.integer.min = 0;
4008 uinfo->value.integer.max = 0xFFFFFFFF;
4009 return 0;
4010}
4011
4012static int msm_compr_query_audio_effect_info(struct snd_kcontrol *kcontrol,
4013 struct snd_ctl_elem_info *uinfo)
4014{
4015 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4016 uinfo->count = 128;
4017 uinfo->value.integer.min = 0;
4018 uinfo->value.integer.max = 0xFFFFFFFF;
4019 return 0;
4020}
4021
4022static int msm_compr_dec_params_info(struct snd_kcontrol *kcontrol,
4023 struct snd_ctl_elem_info *uinfo)
4024{
4025 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4026 uinfo->count = 128;
4027 uinfo->value.integer.min = 0;
4028 uinfo->value.integer.max = 0xFFFFFFFF;
4029 return 0;
4030}
4031
4032static int msm_compr_app_type_cfg_info(struct snd_kcontrol *kcontrol,
4033 struct snd_ctl_elem_info *uinfo)
4034{
4035 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4036 uinfo->count = 5;
4037 uinfo->value.integer.min = 0;
4038 uinfo->value.integer.max = 0xFFFFFFFF;
4039 return 0;
4040}
4041
4042static int msm_compr_channel_map_info(struct snd_kcontrol *kcontrol,
4043 struct snd_ctl_elem_info *uinfo)
4044{
4045 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
Dieter Lueckingba7644d2018-09-28 15:09:32 +02004046 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304047 uinfo->value.integer.min = 0;
Dieter Lueckingba7644d2018-09-28 15:09:32 +02004048 /* See PCM_CHANNEL_RSD=34 in apr_audio-v2.h */
4049 uinfo->value.integer.max = 34;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304050 return 0;
4051}
4052
4053static int msm_compr_add_volume_control(struct snd_soc_pcm_runtime *rtd)
4054{
4055 const char *mixer_ctl_name = "Compress Playback";
4056 const char *deviceNo = "NN";
4057 const char *suffix = "Volume";
4058 char *mixer_str = NULL;
4059 int ctl_len;
4060 struct snd_kcontrol_new fe_volume_control[1] = {
4061 {
4062 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4063 .name = "?",
4064 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
4065 SNDRV_CTL_ELEM_ACCESS_READWRITE,
4066 .info = msm_compr_volume_info,
4067 .tlv.p = msm_compr_vol_gain,
4068 .get = msm_compr_volume_get,
4069 .put = msm_compr_volume_put,
4070 .private_value = 0,
4071 }
4072 };
4073
4074 if (!rtd) {
4075 pr_err("%s NULL rtd\n", __func__);
4076 return 0;
4077 }
4078 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4079 __func__, rtd->dai_link->name, rtd->dai_link->id,
4080 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4081 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
4082 strlen(suffix) + 1;
4083 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4084 if (!mixer_str) {
4085 pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
4086 return 0;
4087 }
4088 snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
4089 rtd->pcm->device, suffix);
4090 fe_volume_control[0].name = mixer_str;
4091 fe_volume_control[0].private_value = rtd->dai_link->id;
4092 pr_debug("Registering new mixer ctl %s", mixer_str);
4093 snd_soc_add_platform_controls(rtd->platform, fe_volume_control,
4094 ARRAY_SIZE(fe_volume_control));
4095 kfree(mixer_str);
4096 return 0;
4097}
4098
4099static int msm_compr_add_audio_effects_control(struct snd_soc_pcm_runtime *rtd)
4100{
4101 const char *mixer_ctl_name = "Audio Effects Config";
4102 const char *deviceNo = "NN";
4103 char *mixer_str = NULL;
4104 int ctl_len;
4105 struct snd_kcontrol_new fe_audio_effects_config_control[1] = {
4106 {
4107 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4108 .name = "?",
4109 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4110 .info = msm_compr_audio_effects_config_info,
4111 .get = msm_compr_audio_effects_config_get,
4112 .put = msm_compr_audio_effects_config_put,
4113 .private_value = 0,
4114 }
4115 };
4116
4117
4118 if (!rtd) {
4119 pr_err("%s NULL rtd\n", __func__);
4120 return 0;
4121 }
4122
4123 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4124 __func__, rtd->dai_link->name, rtd->dai_link->id,
4125 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4126
4127 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4128 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4129
4130 if (!mixer_str)
4131 return 0;
4132
4133 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4134
4135 fe_audio_effects_config_control[0].name = mixer_str;
4136 fe_audio_effects_config_control[0].private_value = rtd->dai_link->id;
4137 pr_debug("Registering new mixer ctl %s\n", mixer_str);
4138 snd_soc_add_platform_controls(rtd->platform,
4139 fe_audio_effects_config_control,
4140 ARRAY_SIZE(fe_audio_effects_config_control));
4141 kfree(mixer_str);
4142 return 0;
4143}
4144
4145static int msm_compr_add_query_audio_effect_control(
4146 struct snd_soc_pcm_runtime *rtd)
4147{
4148 const char *mixer_ctl_name = "Query Audio Effect Param";
4149 const char *deviceNo = "NN";
4150 char *mixer_str = NULL;
4151 int ctl_len;
4152 struct snd_kcontrol_new fe_query_audio_effect_control[1] = {
4153 {
4154 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4155 .name = "?",
4156 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4157 .info = msm_compr_query_audio_effect_info,
4158 .get = msm_compr_query_audio_effect_get,
4159 .put = msm_compr_query_audio_effect_put,
4160 .private_value = 0,
4161 }
4162 };
4163 if (!rtd) {
4164 pr_err("%s NULL rtd\n", __func__);
4165 return 0;
4166 }
4167 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4168 __func__, rtd->dai_link->name, rtd->dai_link->id,
4169 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4170 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4171 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4172 if (!mixer_str) {
4173 pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
4174 return 0;
4175 }
4176 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4177 fe_query_audio_effect_control[0].name = mixer_str;
4178 fe_query_audio_effect_control[0].private_value = rtd->dai_link->id;
4179 pr_debug("%s: registering new mixer ctl %s\n", __func__, mixer_str);
4180 snd_soc_add_platform_controls(rtd->platform,
4181 fe_query_audio_effect_control,
4182 ARRAY_SIZE(fe_query_audio_effect_control));
4183 kfree(mixer_str);
4184 return 0;
4185}
4186
4187static int msm_compr_add_audio_adsp_stream_cmd_control(
4188 struct snd_soc_pcm_runtime *rtd)
4189{
4190 const char *mixer_ctl_name = DSP_STREAM_CMD;
4191 const char *deviceNo = "NN";
4192 char *mixer_str = NULL;
4193 int ctl_len = 0, ret = 0;
4194 struct snd_kcontrol_new fe_audio_adsp_stream_cmd_config_control[1] = {
4195 {
4196 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4197 .name = "?",
4198 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4199 .info = msm_adsp_stream_cmd_info,
4200 .put = msm_compr_adsp_stream_cmd_put,
4201 .private_value = 0,
4202 }
4203 };
4204
4205 if (!rtd) {
4206 pr_err("%s NULL rtd\n", __func__);
4207 ret = -EINVAL;
4208 goto done;
4209 }
4210
4211 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4212 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4213 if (!mixer_str) {
4214 ret = -ENOMEM;
4215 goto done;
4216 }
4217
4218 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4219 fe_audio_adsp_stream_cmd_config_control[0].name = mixer_str;
4220 fe_audio_adsp_stream_cmd_config_control[0].private_value =
4221 rtd->dai_link->id;
4222 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
4223 ret = snd_soc_add_platform_controls(rtd->platform,
4224 fe_audio_adsp_stream_cmd_config_control,
4225 ARRAY_SIZE(fe_audio_adsp_stream_cmd_config_control));
4226 if (ret < 0)
4227 pr_err("%s: failed to add ctl %s. err = %d\n",
4228 __func__, mixer_str, ret);
4229
4230 kfree(mixer_str);
4231done:
4232 return ret;
4233}
4234
4235static int msm_compr_add_audio_adsp_stream_callback_control(
4236 struct snd_soc_pcm_runtime *rtd)
4237{
4238 const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
4239 const char *deviceNo = "NN";
4240 char *mixer_str = NULL;
4241 int ctl_len = 0, ret = 0;
4242 struct snd_kcontrol *kctl;
4243
4244 struct snd_kcontrol_new fe_audio_adsp_callback_config_control[1] = {
4245 {
4246 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4247 .name = "?",
4248 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4249 .info = msm_adsp_stream_callback_info,
4250 .get = msm_adsp_stream_callback_get,
4251 .private_value = 0,
4252 }
4253 };
4254
4255 if (!rtd) {
4256 pr_err("%s: rtd is NULL\n", __func__);
4257 ret = -EINVAL;
4258 goto done;
4259 }
4260
4261 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4262 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4263 if (!mixer_str) {
4264 ret = -ENOMEM;
4265 goto done;
4266 }
4267
4268 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4269 fe_audio_adsp_callback_config_control[0].name = mixer_str;
4270 fe_audio_adsp_callback_config_control[0].private_value =
4271 rtd->dai_link->id;
4272 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
4273 ret = snd_soc_add_platform_controls(rtd->platform,
4274 fe_audio_adsp_callback_config_control,
4275 ARRAY_SIZE(fe_audio_adsp_callback_config_control));
4276 if (ret < 0) {
4277 pr_err("%s: failed to add ctl %s. err = %d\n",
4278 __func__, mixer_str, ret);
4279 ret = -EINVAL;
4280 goto free_mixer_str;
4281 }
4282
4283 kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
4284 if (!kctl) {
4285 pr_err("%s: failed to get kctl %s.\n", __func__, mixer_str);
4286 ret = -EINVAL;
4287 goto free_mixer_str;
4288 }
4289
4290 kctl->private_data = NULL;
4291
4292free_mixer_str:
4293 kfree(mixer_str);
4294done:
4295 return ret;
4296}
4297
4298static int msm_compr_add_dec_runtime_params_control(
4299 struct snd_soc_pcm_runtime *rtd)
4300{
4301 const char *mixer_ctl_name = "Audio Stream";
4302 const char *deviceNo = "NN";
4303 const char *suffix = "Dec Params";
4304 char *mixer_str = NULL;
4305 int ctl_len;
4306 struct snd_kcontrol_new fe_dec_params_control[1] = {
4307 {
4308 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4309 .name = "?",
4310 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4311 .info = msm_compr_dec_params_info,
4312 .get = msm_compr_dec_params_get,
4313 .put = msm_compr_dec_params_put,
4314 .private_value = 0,
4315 }
4316 };
4317
4318 if (!rtd) {
4319 pr_err("%s NULL rtd\n", __func__);
4320 return 0;
4321 }
4322
4323 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4324 __func__, rtd->dai_link->name, rtd->dai_link->id,
4325 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4326
4327 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
4328 strlen(suffix) + 1;
4329 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4330
4331 if (!mixer_str)
4332 return 0;
4333
4334 snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
4335 rtd->pcm->device, suffix);
4336
4337 fe_dec_params_control[0].name = mixer_str;
4338 fe_dec_params_control[0].private_value = rtd->dai_link->id;
4339 pr_debug("Registering new mixer ctl %s", mixer_str);
4340 snd_soc_add_platform_controls(rtd->platform,
4341 fe_dec_params_control,
4342 ARRAY_SIZE(fe_dec_params_control));
4343 kfree(mixer_str);
4344 return 0;
4345}
4346
4347static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
4348{
4349 const char *playback_mixer_ctl_name = "Audio Stream";
4350 const char *capture_mixer_ctl_name = "Audio Stream Capture";
4351 const char *deviceNo = "NN";
4352 const char *suffix = "App Type Cfg";
4353 char *mixer_str = NULL;
4354 int ctl_len;
4355 struct snd_kcontrol_new fe_app_type_cfg_control[1] = {
4356 {
4357 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4358 .name = "?",
4359 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4360 .info = msm_compr_app_type_cfg_info,
4361 .put = msm_compr_playback_app_type_cfg_put,
4362 .get = msm_compr_playback_app_type_cfg_get,
4363 .private_value = 0,
4364 }
4365 };
4366
4367 if (!rtd) {
4368 pr_err("%s NULL rtd\n", __func__);
4369 return 0;
4370 }
4371
4372 pr_debug("%s: added new compr FE ctl with name %s, id %d, cpu dai %s, device no %d\n",
4373 __func__, rtd->dai_link->name, rtd->dai_link->id,
4374 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4375 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
4376 ctl_len = strlen(playback_mixer_ctl_name) + 1 + strlen(deviceNo)
4377 + 1 + strlen(suffix) + 1;
4378 else
4379 ctl_len = strlen(capture_mixer_ctl_name) + 1 + strlen(deviceNo)
4380 + 1 + strlen(suffix) + 1;
4381
4382 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4383
4384 if (!mixer_str)
4385 return 0;
4386
4387 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
4388 snprintf(mixer_str, ctl_len, "%s %d %s",
4389 playback_mixer_ctl_name, rtd->pcm->device, suffix);
4390 else
4391 snprintf(mixer_str, ctl_len, "%s %d %s",
4392 capture_mixer_ctl_name, rtd->pcm->device, suffix);
4393
4394 fe_app_type_cfg_control[0].name = mixer_str;
4395 fe_app_type_cfg_control[0].private_value = rtd->dai_link->id;
4396
4397 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
4398 fe_app_type_cfg_control[0].put =
4399 msm_compr_playback_app_type_cfg_put;
4400 fe_app_type_cfg_control[0].get =
4401 msm_compr_playback_app_type_cfg_get;
4402 } else {
4403 fe_app_type_cfg_control[0].put =
4404 msm_compr_capture_app_type_cfg_put;
4405 fe_app_type_cfg_control[0].get =
4406 msm_compr_capture_app_type_cfg_get;
4407 }
4408 pr_debug("Registering new mixer ctl %s", mixer_str);
4409 snd_soc_add_platform_controls(rtd->platform,
4410 fe_app_type_cfg_control,
4411 ARRAY_SIZE(fe_app_type_cfg_control));
4412 kfree(mixer_str);
4413 return 0;
4414}
4415
Dhanalakshmi Siddani040e0262018-11-26 23:01:26 +05304416static int msm_compr_chmix_cfg_ctl_put(struct snd_kcontrol *kcontrol,
4417 struct snd_ctl_elem_value *ucontrol)
4418{
4419 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4420 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4421 snd_soc_component_get_drvdata(comp);
4422 struct snd_compr_stream *cstream = NULL;
4423 struct snd_soc_pcm_runtime *rtd = NULL;
4424 u64 fe_id = kcontrol->private_value;
4425 int ip_channel_cnt, op_channel_cnt;
4426 int i, index = 0;
4427 int ch_coeff[PCM_FORMAT_MAX_NUM_CHANNEL * PCM_FORMAT_MAX_NUM_CHANNEL];
4428 bool use_default_chmap = true;
4429 char *chmap = NULL;
4430
4431 pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
4432 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
4433 pr_err("%s: Received out of bounds fe_id %llu\n",
4434 __func__, fe_id);
4435 return -EINVAL;
4436 }
4437 cstream = pdata->cstream[fe_id];
4438 if (!cstream) {
4439 pr_err("%s: stream inactive\n", __func__);
4440 return -EINVAL;
4441 }
4442 rtd = cstream->private_data;
4443 if (!rtd) {
4444 pr_err("%s: stream inactive\n", __func__);
4445 return -EINVAL;
4446 }
4447
4448 use_default_chmap = !(pdata->ch_map[rtd->dai_link->id]->set_ch_map);
4449 chmap = pdata->ch_map[rtd->dai_link->id]->channel_map;
4450
4451 ip_channel_cnt = ucontrol->value.integer.value[index++];
4452 op_channel_cnt = ucontrol->value.integer.value[index++];
4453 /*
4454 * wght coeff of first out channel corresponding to each in channel
4455 * are sent followed by second out channel for each in channel etc.
4456 */
4457 memset(ch_coeff, 0, sizeof(ch_coeff));
4458 for (i = 0; i < op_channel_cnt * ip_channel_cnt; i++) {
4459 ch_coeff[i] =
4460 ucontrol->value.integer.value[index++];
4461 }
4462
4463 msm_pcm_routing_send_chmix_cfg(fe_id, ip_channel_cnt, op_channel_cnt,
4464 ch_coeff, SESSION_TYPE_RX, use_default_chmap, chmap);
4465
4466 return 0;
4467}
4468
4469static int msm_compr_chmix_cfg_ctl_get(struct snd_kcontrol *kcontrol,
4470 struct snd_ctl_elem_value *ucontrol)
4471{
4472 return 0;
4473}
4474
4475static int msm_compr_add_chmix_cfg_controls(struct snd_soc_pcm_runtime *rtd)
4476{
4477 const char *mixer_ctl_name = "Audio Stream";
4478 const char *deviceNo = "NN";
4479 const char *suffix = "Channel Mix Cfg";
4480 int ctl_len;
4481 char *mixer_str = NULL;
4482 struct snd_kcontrol_new chmix_cfg_controls[1] = {
4483 {
4484 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4485 .name = "?",
4486 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4487 .info = msm_compr_chmix_cfg_ctl_info,
4488 .get = msm_compr_chmix_cfg_ctl_get,
4489 .put = msm_compr_chmix_cfg_ctl_put,
4490 .private_value = 0,
4491 }
4492 };
4493
4494 if (!rtd) {
4495 pr_err("%s NULL rtd\n", __func__);
4496 return -EINVAL;
4497 }
4498
4499 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4500 __func__, rtd->dai_link->name, rtd->dai_link->id,
4501 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4502
4503 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
4504 strlen(suffix) + 1;
4505 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4506 if (!mixer_str)
4507 return -ENOMEM;
4508
4509 snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
4510 rtd->pcm->device, suffix);
4511
4512 chmix_cfg_controls[0].name = mixer_str;
4513 chmix_cfg_controls[0].private_value = rtd->dai_link->id;
4514 pr_debug("%s: Registering new mixer ctl %s", __func__, mixer_str);
4515 snd_soc_add_platform_controls(rtd->platform,
4516 chmix_cfg_controls,
4517 ARRAY_SIZE(chmix_cfg_controls));
4518 kfree(mixer_str);
4519 return 0;
4520}
4521
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304522static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
4523{
4524 const char *mixer_ctl_name = "Playback Channel Map";
4525 const char *deviceNo = "NN";
4526 char *mixer_str = NULL;
4527 struct msm_compr_pdata *pdata = NULL;
4528 int ctl_len;
4529 struct snd_kcontrol_new fe_channel_map_control[1] = {
4530 {
4531 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4532 .name = "?",
4533 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4534 .info = msm_compr_channel_map_info,
4535 .get = msm_compr_channel_map_get,
4536 .put = msm_compr_channel_map_put,
4537 .private_value = 0,
4538 }
4539 };
4540
4541 if (!rtd) {
4542 pr_err("%s: NULL rtd\n", __func__);
4543 return -EINVAL;
4544 }
4545
4546 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4547 __func__, rtd->dai_link->name, rtd->dai_link->id,
4548 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4549
4550 ctl_len = strlen(mixer_ctl_name) + strlen(deviceNo) + 1;
4551 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4552
4553 if (!mixer_str)
4554 return -ENOMEM;
4555
4556 snprintf(mixer_str, ctl_len, "%s%d", mixer_ctl_name, rtd->pcm->device);
4557
4558 fe_channel_map_control[0].name = mixer_str;
4559 fe_channel_map_control[0].private_value = rtd->dai_link->id;
4560 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
4561 snd_soc_add_platform_controls(rtd->platform,
4562 fe_channel_map_control,
4563 ARRAY_SIZE(fe_channel_map_control));
4564
4565 pdata = snd_soc_platform_get_drvdata(rtd->platform);
4566 pdata->ch_map[rtd->dai_link->id] =
4567 kzalloc(sizeof(struct msm_compr_ch_map), GFP_KERNEL);
4568 if (!pdata->ch_map[rtd->dai_link->id]) {
4569 pr_err("%s: Could not allocate memory for channel map\n",
4570 __func__);
4571 kfree(mixer_str);
4572 return -ENOMEM;
4573 }
4574 kfree(mixer_str);
4575 return 0;
4576}
4577
4578static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
4579{
4580 const char *mixer_ctl_name = "Playback ION FD";
4581 const char *deviceNo = "NN";
4582 char *mixer_str = NULL;
4583 int ctl_len = 0, ret = 0;
4584 struct snd_kcontrol_new fe_ion_fd_config_control[1] = {
4585 {
4586 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4587 .name = "?",
4588 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4589 .info = msm_adsp_stream_cmd_info,
4590 .put = msm_compr_ion_fd_map_put,
4591 .private_value = 0,
4592 }
4593 };
4594
4595 if (!rtd) {
4596 pr_err("%s NULL rtd\n", __func__);
4597 ret = -EINVAL;
4598 goto done;
4599 }
4600
4601 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4602 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4603 if (!mixer_str) {
4604 ret = -ENOMEM;
4605 goto done;
4606 }
4607
4608 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4609 fe_ion_fd_config_control[0].name = mixer_str;
4610 fe_ion_fd_config_control[0].private_value = rtd->dai_link->id;
4611 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
4612 ret = snd_soc_add_platform_controls(rtd->platform,
4613 fe_ion_fd_config_control,
4614 ARRAY_SIZE(fe_ion_fd_config_control));
4615 if (ret < 0)
4616 pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
4617
4618 kfree(mixer_str);
4619done:
4620 return ret;
4621}
4622
4623static int msm_compr_add_event_ack_cmd_control(struct snd_soc_pcm_runtime *rtd)
4624{
4625 const char *mixer_ctl_name = "Playback Event Ack";
4626 const char *deviceNo = "NN";
4627 char *mixer_str = NULL;
4628 int ctl_len = 0, ret = 0;
4629 struct snd_kcontrol_new fe_event_ack_config_control[1] = {
4630 {
4631 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4632 .name = "?",
4633 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4634 .info = msm_adsp_stream_cmd_info,
4635 .put = msm_compr_rtic_event_ack_put,
4636 .private_value = 0,
4637 }
4638 };
4639
4640 if (!rtd) {
4641 pr_err("%s NULL rtd\n", __func__);
4642 ret = -EINVAL;
4643 goto done;
4644 }
4645
4646 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4647 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4648 if (!mixer_str) {
4649 ret = -ENOMEM;
4650 goto done;
4651 }
4652
4653 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4654 fe_event_ack_config_control[0].name = mixer_str;
4655 fe_event_ack_config_control[0].private_value = rtd->dai_link->id;
4656 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
4657 ret = snd_soc_add_platform_controls(rtd->platform,
4658 fe_event_ack_config_control,
4659 ARRAY_SIZE(fe_event_ack_config_control));
4660 if (ret < 0)
4661 pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
4662
4663 kfree(mixer_str);
4664done:
4665 return ret;
4666}
4667
4668static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
4669{
4670 int rc;
4671
4672 rc = msm_compr_add_volume_control(rtd);
4673 if (rc)
4674 pr_err("%s: Could not add Compr Volume Control\n", __func__);
4675
4676 rc = msm_compr_add_audio_effects_control(rtd);
4677 if (rc)
4678 pr_err("%s: Could not add Compr Audio Effects Control\n",
4679 __func__);
4680
4681 rc = msm_compr_add_audio_adsp_stream_cmd_control(rtd);
4682 if (rc)
4683 pr_err("%s: Could not add Compr ADSP Stream Cmd Control\n",
4684 __func__);
4685
4686 rc = msm_compr_add_audio_adsp_stream_callback_control(rtd);
4687 if (rc)
4688 pr_err("%s: Could not add Compr ADSP Stream Callback Control\n",
4689 __func__);
4690
4691 rc = msm_compr_add_io_fd_cmd_control(rtd);
4692 if (rc)
4693 pr_err("%s: Could not add Compr ion fd Control\n",
4694 __func__);
4695
4696 rc = msm_compr_add_event_ack_cmd_control(rtd);
4697 if (rc)
4698 pr_err("%s: Could not add Compr event ack Control\n",
4699 __func__);
4700
4701 rc = msm_compr_add_query_audio_effect_control(rtd);
4702 if (rc)
4703 pr_err("%s: Could not add Compr Query Audio Effect Control\n",
4704 __func__);
4705
4706 rc = msm_compr_add_dec_runtime_params_control(rtd);
4707 if (rc)
4708 pr_err("%s: Could not add Compr Dec runtime params Control\n",
4709 __func__);
4710 rc = msm_compr_add_app_type_cfg_control(rtd);
4711 if (rc)
4712 pr_err("%s: Could not add Compr App Type Cfg Control\n",
4713 __func__);
4714 rc = msm_compr_add_channel_map_control(rtd);
4715 if (rc)
4716 pr_err("%s: Could not add Compr Channel Map Control\n",
4717 __func__);
Dhanalakshmi Siddani040e0262018-11-26 23:01:26 +05304718 rc = msm_compr_add_chmix_cfg_controls(rtd);
4719 if (rc)
4720 pr_err("%s: add chmix cfg controls failed:%d\n", __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304721 return 0;
4722}
4723
4724static struct snd_compr_ops msm_compr_ops = {
4725 .open = msm_compr_open,
4726 .free = msm_compr_free,
4727 .trigger = msm_compr_trigger,
4728 .pointer = msm_compr_pointer,
4729 .set_params = msm_compr_set_params,
4730 .set_metadata = msm_compr_set_metadata,
4731 .get_metadata = msm_compr_get_metadata,
4732 .set_next_track_param = msm_compr_set_next_track_param,
4733 .ack = msm_compr_ack,
4734 .copy = msm_compr_copy,
4735 .get_caps = msm_compr_get_caps,
4736 .get_codec_caps = msm_compr_get_codec_caps,
4737};
4738
4739static struct snd_soc_platform_driver msm_soc_platform = {
4740 .probe = msm_compr_probe,
4741 .compr_ops = &msm_compr_ops,
4742 .pcm_new = msm_compr_new,
Ajit Pandey233bdea2019-09-04 14:34:00 +05304743 .remove = msm_compr_remove,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304744};
4745
4746static int msm_compr_dev_probe(struct platform_device *pdev)
4747{
4748
4749 pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
4750 return snd_soc_register_platform(&pdev->dev,
4751 &msm_soc_platform);
4752}
4753
Ajit Pandey233bdea2019-09-04 14:34:00 +05304754static int msm_compr_dev_remove(struct platform_device *pdev)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304755{
4756 snd_soc_unregister_platform(&pdev->dev);
4757 return 0;
4758}
4759
4760static const struct of_device_id msm_compr_dt_match[] = {
4761 {.compatible = "qcom,msm-compress-dsp"},
4762 {}
4763};
4764MODULE_DEVICE_TABLE(of, msm_compr_dt_match);
4765
4766static struct platform_driver msm_compr_driver = {
4767 .driver = {
4768 .name = "msm-compress-dsp",
4769 .owner = THIS_MODULE,
4770 .of_match_table = msm_compr_dt_match,
4771 },
4772 .probe = msm_compr_dev_probe,
Ajit Pandey233bdea2019-09-04 14:34:00 +05304773 .remove = msm_compr_dev_remove,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304774};
4775
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304776int __init msm_compress_dsp_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304777{
4778 return platform_driver_register(&msm_compr_driver);
4779}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304780
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05304781void msm_compress_dsp_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304782{
4783 platform_driver_unregister(&msm_compr_driver);
4784}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304785
4786MODULE_DESCRIPTION("Compress Offload platform driver");
4787MODULE_LICENSE("GPL v2");