blob: cd779ccb7cdf459a4590d21401c8c0de9368827c [file] [log] [blame]
Meng Wang43bbb872018-12-10 12:32:05 +08001// SPDX-License-Identifier: GPL-2.0-only
Sanjana B61518cf2019-11-12 23:09:27 +05302/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303 */
4
5
6#include <linux/init.h>
7#include <linux/err.h>
8#include <linux/module.h>
9#include <linux/moduleparam.h>
10#include <linux/time.h>
11#include <linux/math64.h>
12#include <linux/wait.h>
Ajit Pandeyfa018862019-09-04 14:34:00 +053013#include <linux/mutex.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053014#include <linux/platform_device.h>
15#include <linux/slab.h>
16#include <sound/core.h>
17#include <sound/soc.h>
18#include <sound/soc-dapm.h>
19#include <sound/pcm.h>
20#include <sound/initval.h>
21#include <sound/control.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053022#include <sound/pcm_params.h>
23#include <sound/audio_effects.h>
24#include <asm/dma.h>
25#include <linux/dma-mapping.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053026#include <linux/msm_audio.h>
27
28#include <sound/timer.h>
29#include <sound/tlv.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053030#include <sound/compress_params.h>
31#include <sound/compress_offload.h>
32#include <sound/compress_driver.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053033
34#include <dsp/msm_audio_ion.h>
35#include <dsp/apr_audio-v2.h>
36#include <dsp/q6asm-v2.h>
Dieter Lueckingceef9af2018-09-28 15:09:32 +020037#include <dsp/q6core.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053038#include <dsp/msm-audio-effects-q6-v2.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053039#include "msm-pcm-routing-v2.h"
40#include "msm-qti-pp-config.h"
41
Meng Wangee084a02018-09-04 16:11:58 +080042#define DRV_NAME "msm-compress-q6-v2"
43
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -070044#define TIMEOUT_MS 1000
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053045#define DSP_PP_BUFFERING_IN_MSEC 25
46#define PARTIAL_DRAIN_ACK_EARLY_BY_MSEC 150
47#define MP3_OUTPUT_FRAME_SZ 1152
48#define AAC_OUTPUT_FRAME_SZ 1024
49#define AC3_OUTPUT_FRAME_SZ 1536
50#define EAC3_OUTPUT_FRAME_SZ 1536
51#define DSP_NUM_OUTPUT_FRAME_BUFFERED 2
52#define FLAC_BLK_SIZE_LIMIT 65535
53
54/* Timestamp mode payload offsets */
55#define CAPTURE_META_DATA_TS_OFFSET_LSW 6
56#define CAPTURE_META_DATA_TS_OFFSET_MSW 7
57
58/* decoder parameter length */
59#define DDP_DEC_MAX_NUM_PARAM 18
60
61/* Default values used if user space does not set */
62#define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024)
63#define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
64#define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4)
65#define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4)
66
67#define COMPRESSED_LR_VOL_MAX_STEPS 0x2000
68const DECLARE_TLV_DB_LINEAR(msm_compr_vol_gain, 0,
69 COMPRESSED_LR_VOL_MAX_STEPS);
70
71/* Stream id switches between 1 and 2 */
72#define NEXT_STREAM_ID(stream_id) ((stream_id & 1) + 1)
73
74#define STREAM_ARRAY_INDEX(stream_id) (stream_id - 1)
75
76#define MAX_NUMBER_OF_STREAMS 2
77
Meng Wang1b52b572018-08-07 16:28:06 +080078#define SND_DEC_DDP_MAX_PARAMS 18
79
Deeraj Soman9d125872019-02-05 16:19:56 +053080#ifndef COMPRESSED_PERF_MODE_FLAG
81#define COMPRESSED_PERF_MODE_FLAG 0
82#endif
83
Sanjana Bc45335a2019-12-06 17:16:36 +053084#define DSD_BLOCK_SIZE_4 4
85
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053086struct msm_compr_gapless_state {
87 bool set_next_stream_id;
88 int32_t stream_opened[MAX_NUMBER_OF_STREAMS];
89 uint32_t initial_samples_drop;
90 uint32_t trailing_samples_drop;
91 uint32_t gapless_transition;
92 bool use_dsp_gapless_mode;
93 union snd_codec_options codec_options;
94};
95
96static unsigned int supported_sample_rates[] = {
97 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000,
98 88200, 96000, 128000, 144000, 176400, 192000, 352800, 384000, 2822400,
99 5644800
100};
101
102struct msm_compr_pdata {
103 struct snd_compr_stream *cstream[MSM_FRONTEND_DAI_MAX];
104 uint32_t volume[MSM_FRONTEND_DAI_MAX][2]; /* For both L & R */
105 struct msm_compr_audio_effects *audio_effects[MSM_FRONTEND_DAI_MAX];
106 bool use_dsp_gapless_mode;
107 bool use_legacy_api; /* indicates use older asm apis*/
108 struct msm_compr_dec_params *dec_params[MSM_FRONTEND_DAI_MAX];
109 struct msm_compr_ch_map *ch_map[MSM_FRONTEND_DAI_MAX];
Aditya Bavanari9deef912017-11-20 13:31:31 +0530110 bool is_in_use[MSM_FRONTEND_DAI_MAX];
Dhananjay Kumar807f7e92018-12-11 18:10:08 +0530111 struct msm_pcm_channel_mixer *chmixer_pspd[MSM_FRONTEND_DAI_MM_SIZE];
Ajit Pandeyfa018862019-09-04 14:34:00 +0530112 struct mutex lock;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530113};
114
115struct msm_compr_audio {
116 struct snd_compr_stream *cstream;
117 struct snd_compr_caps compr_cap;
118 struct snd_compr_codec_caps codec_caps;
119 struct snd_compr_params codec_param;
120 struct audio_client *audio_client;
121
122 uint32_t codec;
123 uint32_t compr_passthr;
124 void *buffer; /* virtual address */
125 phys_addr_t buffer_paddr; /* physical address */
126 uint32_t app_pointer;
127 uint32_t buffer_size;
128 uint32_t byte_offset;
129 uint64_t copied_total; /* bytes consumed by DSP */
130 uint64_t bytes_received; /* from userspace */
131 uint64_t bytes_sent; /* to DSP */
132
133 uint64_t received_total; /* bytes received from DSP */
134 uint64_t bytes_copied; /* to userspace */
135 uint64_t bytes_read; /* from DSP */
136 uint32_t bytes_read_offset; /* bytes read offset */
137
138 uint32_t ts_header_offset; /* holds the timestamp header offset */
139
140 int32_t first_buffer;
141 int32_t last_buffer;
142 int32_t partial_drain_delay;
143
144 uint16_t session_id;
145
146 uint32_t sample_rate;
147 uint32_t num_channels;
148
149 /*
150 * convention - commands coming from the same thread
151 * can use the common cmd_ack var. Others (e.g drain/EOS)
152 * must use separate vars to track command status.
153 */
154 uint32_t cmd_ack;
155 uint32_t cmd_interrupt;
156 uint32_t drain_ready;
157 uint32_t eos_ack;
158
159 uint32_t stream_available;
160 uint32_t next_stream;
161
162 uint32_t run_mode;
163 uint32_t start_delay_lsw;
164 uint32_t start_delay_msw;
165
166 uint64_t marker_timestamp;
167
168 struct msm_compr_gapless_state gapless_state;
169
170 atomic_t start;
171 atomic_t eos;
172 atomic_t drain;
173 atomic_t xrun;
174 atomic_t close;
175 atomic_t wait_on_close;
176 atomic_t error;
177
178 wait_queue_head_t eos_wait;
179 wait_queue_head_t drain_wait;
180 wait_queue_head_t close_wait;
181 wait_queue_head_t wait_for_stream_avail;
182
183 spinlock_t lock;
184};
185
186const u32 compr_codecs[] = {
187 SND_AUDIOCODEC_AC3, SND_AUDIOCODEC_EAC3, SND_AUDIOCODEC_DTS,
188 SND_AUDIOCODEC_DSD, SND_AUDIOCODEC_TRUEHD, SND_AUDIOCODEC_IEC61937};
189
190struct query_audio_effect {
191 uint32_t mod_id;
192 uint32_t parm_id;
193 uint32_t size;
194 uint32_t offset;
195 uint32_t device;
196};
197
198struct msm_compr_audio_effects {
199 struct bass_boost_params bass_boost;
200 struct pbe_params pbe;
201 struct virtualizer_params virtualizer;
202 struct reverb_params reverb;
203 struct eq_params equalizer;
204 struct soft_volume_params volume;
205 struct query_audio_effect query;
206};
207
Meng Wang1b52b572018-08-07 16:28:06 +0800208struct snd_dec_ddp {
209 __u32 params_length;
210 __u32 params_id[SND_DEC_DDP_MAX_PARAMS];
211 __u32 params_value[SND_DEC_DDP_MAX_PARAMS];
212} __attribute__((packed, aligned(4)));
213
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530214struct msm_compr_dec_params {
215 struct snd_dec_ddp ddp_params;
216};
217
218struct msm_compr_ch_map {
219 bool set_ch_map;
Dieter Lueckingceef9af2018-09-28 15:09:32 +0200220 char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530221};
222
223static int msm_compr_send_dec_params(struct snd_compr_stream *cstream,
224 struct msm_compr_dec_params *dec_params,
225 int stream_id);
226
227static int msm_compr_set_render_mode(struct msm_compr_audio *prtd,
228 uint32_t render_mode) {
229 int ret = -EINVAL;
230 struct audio_client *ac = prtd->audio_client;
231
232 pr_debug("%s, got render mode %u\n", __func__, render_mode);
233
234 if (render_mode == SNDRV_COMPRESS_RENDER_MODE_AUDIO_MASTER) {
235 render_mode = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT;
236 } else if (render_mode == SNDRV_COMPRESS_RENDER_MODE_STC_MASTER) {
237 render_mode = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC;
238 prtd->run_mode = ASM_SESSION_CMD_RUN_STARTIME_RUN_WITH_DELAY;
239 } else {
240 pr_err("%s, Invalid render mode %u\n", __func__,
241 render_mode);
242 ret = -EINVAL;
243 goto exit;
244 }
245
246 ret = q6asm_send_mtmx_strtr_render_mode(ac, render_mode);
247 if (ret) {
248 pr_err("%s, Render mode can't be set error %d\n", __func__,
249 ret);
250 }
251exit:
252 return ret;
253}
254
255static int msm_compr_set_clk_rec_mode(struct audio_client *ac,
256 uint32_t clk_rec_mode) {
257 int ret = -EINVAL;
258
259 pr_debug("%s, got clk rec mode %u\n", __func__, clk_rec_mode);
260
261 if (clk_rec_mode == SNDRV_COMPRESS_CLK_REC_MODE_NONE) {
262 clk_rec_mode = ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_NONE;
263 } else if (clk_rec_mode == SNDRV_COMPRESS_CLK_REC_MODE_AUTO) {
264 clk_rec_mode = ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_AUTO;
265 } else {
266 pr_err("%s, Invalid clk rec_mode mode %u\n", __func__,
267 clk_rec_mode);
268 ret = -EINVAL;
269 goto exit;
270 }
271
272 ret = q6asm_send_mtmx_strtr_clk_rec_mode(ac, clk_rec_mode);
273 if (ret) {
274 pr_err("%s, clk rec mode can't be set, error %d\n", __func__,
275 ret);
276 }
277
278exit:
279 return ret;
280}
281
282static int msm_compr_set_render_window(struct audio_client *ac,
283 uint32_t ws_lsw, uint32_t ws_msw,
284 uint32_t we_lsw, uint32_t we_msw)
285{
286 int ret = -EINVAL;
287 struct asm_session_mtmx_strtr_param_window_v2_t asm_mtmx_strtr_window;
288 uint32_t param_id;
289
290 pr_debug("%s, ws_lsw 0x%x ws_msw 0x%x we_lsw 0x%x we_ms 0x%x\n",
291 __func__, ws_lsw, ws_msw, we_lsw, we_msw);
292
293 memset(&asm_mtmx_strtr_window, 0,
294 sizeof(struct asm_session_mtmx_strtr_param_window_v2_t));
295 asm_mtmx_strtr_window.window_lsw = ws_lsw;
296 asm_mtmx_strtr_window.window_msw = ws_msw;
297 param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_WINDOW_START_V2;
298 ret = q6asm_send_mtmx_strtr_window(ac, &asm_mtmx_strtr_window,
299 param_id);
300 if (ret) {
301 pr_err("%s, start window can't be set error %d\n", __func__,
302 ret);
303 goto exit;
304 }
305
306 asm_mtmx_strtr_window.window_lsw = we_lsw;
307 asm_mtmx_strtr_window.window_msw = we_msw;
308 param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_WINDOW_END_V2;
309 ret = q6asm_send_mtmx_strtr_window(ac, &asm_mtmx_strtr_window,
310 param_id);
311 if (ret) {
312 pr_err("%s, end window can't be set error %d\n", __func__,
313 ret);
314 }
315
316exit:
317 return ret;
318}
319
320static int msm_compr_enable_adjust_session_clock(struct audio_client *ac,
321 bool enable)
322{
323 int ret;
324
325 pr_debug("%s, enable adjust_session %d\n", __func__, enable);
326
327 ret = q6asm_send_mtmx_strtr_enable_adjust_session_clock(ac, enable);
328 if (ret)
329 pr_err("%s, adjust session clock can't be set error %d\n",
330 __func__, ret);
331
332 return ret;
333}
334
335static int msm_compr_adjust_session_clock(struct audio_client *ac,
336 uint32_t adjust_session_lsw, uint32_t adjust_session_msw)
337{
338 int ret;
339
340 pr_debug("%s, adjust_session_time_msw 0x%x adjust_session_time_lsw 0x%x\n",
341 __func__, adjust_session_msw, adjust_session_lsw);
342
343 ret = q6asm_adjust_session_clock(ac,
344 adjust_session_lsw,
345 adjust_session_msw);
346 if (ret)
347 pr_err("%s, adjust session clock can't be set error %d\n",
348 __func__, ret);
349
350 return ret;
351}
352
353static int msm_compr_set_volume(struct snd_compr_stream *cstream,
354 uint32_t volume_l, uint32_t volume_r)
355{
356 struct msm_compr_audio *prtd;
357 int rc = 0;
358 uint32_t avg_vol, gain_list[VOLUME_CONTROL_MAX_CHANNELS];
359 uint32_t num_channels;
360 struct snd_soc_pcm_runtime *rtd;
Meng Wangee084a02018-09-04 16:11:58 +0800361 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530362 struct msm_compr_pdata *pdata;
363 bool use_default = true;
364 u8 *chmap = NULL;
365
366 pr_debug("%s: volume_l %d volume_r %d\n",
367 __func__, volume_l, volume_r);
368 if (!cstream || !cstream->runtime) {
369 pr_err("%s: session not active\n", __func__);
370 return -EPERM;
371 }
372 rtd = cstream->private_data;
373 prtd = cstream->runtime->private_data;
374
Meng Wang8a2a1042019-03-21 10:14:50 +0800375 if (!rtd || !prtd || !prtd->audio_client) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530376 pr_err("%s: invalid rtd, prtd or audio client", __func__);
377 return rc;
378 }
Meng Wang8a2a1042019-03-21 10:14:50 +0800379 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
380 if (!component) {
381 pr_err("%s: invalid component\n", __func__);
382 return rc;
383 }
384
Meng Wangee084a02018-09-04 16:11:58 +0800385 pdata = snd_soc_component_get_drvdata(component);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530386
387 if (prtd->compr_passthr != LEGACY_PCM) {
388 pr_debug("%s: No volume config for passthrough %d\n",
389 __func__, prtd->compr_passthr);
390 return rc;
391 }
392
393 use_default = !(pdata->ch_map[rtd->dai_link->id]->set_ch_map);
394 chmap = pdata->ch_map[rtd->dai_link->id]->channel_map;
395 num_channels = prtd->num_channels;
396
397 if (prtd->num_channels > 2) {
398 /*
399 * Currently the left and right gains are averaged an applied
400 * to all channels. This might not be desirable. But currently,
401 * there exists no API in userspace to send a list of gains for
402 * each channel either. If such an API does become available,
403 * the mixer control must be updated to accept more than 2
404 * channel gains.
405 *
406 */
407 avg_vol = (volume_l + volume_r) / 2;
408 rc = q6asm_set_volume(prtd->audio_client, avg_vol);
409 } else {
410 gain_list[0] = volume_l;
411 gain_list[1] = volume_r;
yidongh98526ef2017-09-05 17:57:55 +0800412 gain_list[2] = volume_l;
Surendar Karka4bb89982019-10-01 13:51:11 +0530413 if (use_default)
414 num_channels = 3;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530415 rc = q6asm_set_multich_gain(prtd->audio_client, num_channels,
416 gain_list, chmap, use_default);
417 }
418
419 if (rc < 0)
420 pr_err("%s: Send vol gain command failed rc=%d\n",
421 __func__, rc);
422
423 return rc;
424}
425
426static int msm_compr_send_ddp_cfg(struct audio_client *ac,
427 struct snd_dec_ddp *ddp,
428 int stream_id)
429{
430 int i, rc;
431
432 pr_debug("%s\n", __func__);
433 for (i = 0; i < ddp->params_length; i++) {
434 rc = q6asm_ds1_set_stream_endp_params(ac, ddp->params_id[i],
435 ddp->params_value[i],
436 stream_id);
437 if (rc) {
438 pr_err("sending params_id: %d failed\n",
439 ddp->params_id[i]);
440 return rc;
441 }
442 }
443 return 0;
444}
445
446static int msm_compr_send_buffer(struct msm_compr_audio *prtd)
447{
448 int buffer_length;
449 uint64_t bytes_available;
450 struct audio_aio_write_param param;
451 struct snd_codec_metadata *buff_addr;
452
453 if (!atomic_read(&prtd->start)) {
454 pr_err("%s: stream is not in started state\n", __func__);
455 return -EINVAL;
456 }
457
458
459 if (atomic_read(&prtd->xrun)) {
460 WARN(1, "%s called while xrun is true", __func__);
461 return -EPERM;
462 }
463
464 pr_debug("%s: bytes_received = %llu copied_total = %llu\n",
465 __func__, prtd->bytes_received, prtd->copied_total);
466 if (prtd->first_buffer && prtd->gapless_state.use_dsp_gapless_mode &&
467 prtd->compr_passthr == LEGACY_PCM)
468 q6asm_stream_send_meta_data(prtd->audio_client,
469 prtd->audio_client->stream_id,
470 prtd->gapless_state.initial_samples_drop,
471 prtd->gapless_state.trailing_samples_drop);
472
473 buffer_length = prtd->codec_param.buffer.fragment_size;
474 bytes_available = prtd->bytes_received - prtd->copied_total;
475 if (bytes_available < prtd->codec_param.buffer.fragment_size)
476 buffer_length = bytes_available;
477
478 if (prtd->byte_offset + buffer_length > prtd->buffer_size) {
479 buffer_length = (prtd->buffer_size - prtd->byte_offset);
480 pr_debug("%s: wrap around situation, send partial data %d now",
481 __func__, buffer_length);
482 }
483
484 if (buffer_length) {
485 param.paddr = prtd->buffer_paddr + prtd->byte_offset;
486 WARN(prtd->byte_offset % 32 != 0, "offset %x not multiple of 32\n",
487 prtd->byte_offset);
488 } else {
489 param.paddr = prtd->buffer_paddr;
490 }
491 param.len = buffer_length;
492 if (prtd->ts_header_offset) {
493 buff_addr = (struct snd_codec_metadata *)
494 (prtd->buffer + prtd->byte_offset);
495 param.len = buff_addr->length;
496 param.msw_ts = (uint32_t)
497 ((buff_addr->timestamp & 0xFFFFFFFF00000000LL) >> 32);
498 param.lsw_ts = (uint32_t) (buff_addr->timestamp & 0xFFFFFFFFLL);
499 param.paddr += prtd->ts_header_offset;
500 param.flags = SET_TIMESTAMP;
501 param.metadata_len = prtd->ts_header_offset;
502 } else {
503 param.msw_ts = 0;
504 param.lsw_ts = 0;
505 param.flags = NO_TIMESTAMP;
506 param.metadata_len = 0;
507 }
508 param.uid = buffer_length;
509 param.last_buffer = prtd->last_buffer;
510
511 pr_debug("%s: sending %d bytes to DSP byte_offset = %d\n",
512 __func__, param.len, prtd->byte_offset);
513 if (q6asm_async_write(prtd->audio_client, &param) < 0) {
514 pr_err("%s:q6asm_async_write failed\n", __func__);
515 } else {
516 prtd->bytes_sent += buffer_length;
517 if (prtd->first_buffer)
518 prtd->first_buffer = 0;
519 }
520
521 return 0;
522}
523
524static int msm_compr_read_buffer(struct msm_compr_audio *prtd)
525{
526 int buffer_length;
527 uint64_t bytes_available;
528 uint64_t buffer_sent;
529 struct audio_aio_read_param param;
530 int ret;
531
532 if (!atomic_read(&prtd->start)) {
533 pr_err("%s: stream is not in started state\n", __func__);
534 return -EINVAL;
535 }
536
537 buffer_length = prtd->codec_param.buffer.fragment_size -
538 prtd->ts_header_offset;
539 bytes_available = prtd->received_total - prtd->bytes_copied;
540 buffer_sent = prtd->bytes_read - prtd->bytes_copied;
541 if (buffer_sent + buffer_length + prtd->ts_header_offset
542 > prtd->buffer_size) {
543 pr_debug(" %s : Buffer is Full bytes_available: %llu\n",
544 __func__, bytes_available);
545 return 0;
546 }
547
548 memset(&param, 0x0, sizeof(struct audio_aio_read_param));
549 param.paddr = prtd->buffer_paddr + prtd->bytes_read_offset +
550 prtd->ts_header_offset;
551 param.len = buffer_length;
552 param.uid = buffer_length;
553 param.flags = prtd->codec_param.codec.flags;
554
555 pr_debug("%s: reading %d bytes from DSP byte_offset = %llu\n",
556 __func__, buffer_length, prtd->bytes_read);
557 ret = q6asm_async_read(prtd->audio_client, &param);
558 if (ret < 0) {
559 pr_err("%s: q6asm_async_read failed - %d\n",
560 __func__, ret);
561 return ret;
562 }
Ralf Herz22573552018-06-20 11:30:58 +0200563 prtd->bytes_read += buffer_length + prtd->ts_header_offset;
Vikram Panduranga82c2c2c2018-01-10 18:04:54 -0800564 prtd->bytes_read_offset += buffer_length + prtd->ts_header_offset;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530565 if (prtd->bytes_read_offset >= prtd->buffer_size)
566 prtd->bytes_read_offset -= prtd->buffer_size;
567
568 return 0;
569}
570
571static void compr_event_handler(uint32_t opcode,
572 uint32_t token, uint32_t *payload, void *priv)
573{
574 struct msm_compr_audio *prtd = priv;
575 struct snd_compr_stream *cstream;
576 struct audio_client *ac;
577 uint32_t chan_mode = 0;
578 uint32_t sample_rate = 0;
579 uint64_t bytes_available;
580 int stream_id;
581 uint32_t stream_index;
582 unsigned long flags;
583 uint64_t read_size;
584 uint32_t *buff_addr;
585 struct snd_soc_pcm_runtime *rtd;
586 int ret = 0;
587
588 if (!prtd) {
589 pr_err("%s: prtd is NULL\n", __func__);
590 return;
591 }
592 cstream = prtd->cstream;
593 if (!cstream) {
594 pr_err("%s: cstream is NULL\n", __func__);
595 return;
596 }
597
598 ac = prtd->audio_client;
599
600 /*
601 * Token for rest of the compressed commands use to set
602 * session id, stream id, dir etc.
603 */
604 stream_id = q6asm_get_stream_id_from_token(token);
605
606 pr_debug("%s opcode =%08x\n", __func__, opcode);
607 switch (opcode) {
608 case ASM_DATA_EVENT_WRITE_DONE_V2:
609 spin_lock_irqsave(&prtd->lock, flags);
610
611 if (payload[3]) {
612 pr_err("%s: WRITE FAILED w/ err 0x%x !, paddr 0x%x, byte_offset=%d,copied_total=%llu,token=%d\n",
613 __func__,
614 payload[3],
615 payload[0],
616 prtd->byte_offset,
617 prtd->copied_total, token);
618
619 if (atomic_cmpxchg(&prtd->drain, 1, 0) &&
620 prtd->last_buffer) {
621 pr_debug("%s: wake up on drain\n", __func__);
622 prtd->drain_ready = 1;
623 wake_up(&prtd->drain_wait);
624 prtd->last_buffer = 0;
625 } else {
626 atomic_set(&prtd->start, 0);
627 }
628 } else {
629 pr_debug("ASM_DATA_EVENT_WRITE_DONE_V2 offset %d, length %d\n",
630 prtd->byte_offset, token);
631 }
632
633 /*
634 * Token for WRITE command represents the amount of data
635 * written to ADSP in the last write, update offset and
636 * total copied data accordingly.
637 */
638 if (prtd->ts_header_offset) {
639 /* Always assume that the data will be sent to DSP on
640 * frame boundary.
641 * i.e, one frame of userspace write will result in
642 * one kernel write to DSP. This is needed as
643 * timestamp will be sent per frame.
644 */
645 prtd->byte_offset +=
646 prtd->codec_param.buffer.fragment_size;
647 prtd->copied_total +=
648 prtd->codec_param.buffer.fragment_size;
649 } else {
650 prtd->byte_offset += token;
651 prtd->copied_total += token;
652 }
653 if (prtd->byte_offset >= prtd->buffer_size)
654 prtd->byte_offset -= prtd->buffer_size;
655
656 snd_compr_fragment_elapsed(cstream);
657
658 if (!atomic_read(&prtd->start)) {
659 /* Writes must be restarted from _copy() */
660 pr_debug("write_done received while not started, treat as xrun");
661 atomic_set(&prtd->xrun, 1);
662 spin_unlock_irqrestore(&prtd->lock, flags);
663 break;
664 }
665
666 bytes_available = prtd->bytes_received - prtd->copied_total;
667 if (bytes_available < cstream->runtime->fragment_size) {
668 pr_debug("WRITE_DONE Insufficient data to send. break out\n");
669 atomic_set(&prtd->xrun, 1);
670
671 if (prtd->last_buffer)
672 prtd->last_buffer = 0;
673 if (atomic_read(&prtd->drain)) {
674 pr_debug("wake up on drain\n");
675 prtd->drain_ready = 1;
676 wake_up(&prtd->drain_wait);
677 atomic_set(&prtd->drain, 0);
678 }
679 } else if ((bytes_available == cstream->runtime->fragment_size)
680 && atomic_read(&prtd->drain)) {
681 prtd->last_buffer = 1;
682 msm_compr_send_buffer(prtd);
683 prtd->last_buffer = 0;
684 } else
685 msm_compr_send_buffer(prtd);
686
687 spin_unlock_irqrestore(&prtd->lock, flags);
688 break;
689
690 case ASM_DATA_EVENT_READ_DONE_V2:
691 spin_lock_irqsave(&prtd->lock, flags);
692
693 pr_debug("ASM_DATA_EVENT_READ_DONE_V2 offset %d, length %d\n",
694 prtd->byte_offset, payload[4]);
695
696 if (prtd->ts_header_offset) {
697 /* Update the header for received buffer */
698 buff_addr = prtd->buffer + prtd->byte_offset;
Ralf Herz22573552018-06-20 11:30:58 +0200699 /* Write the actual length of the received buffer */
700 *buff_addr = payload[4];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530701 buff_addr++;
702 /* Write the offset */
703 *buff_addr = prtd->ts_header_offset;
704 buff_addr++;
705 /* Write the TS LSW */
706 *buff_addr = payload[CAPTURE_META_DATA_TS_OFFSET_LSW];
707 buff_addr++;
708 /* Write the TS MSW */
709 *buff_addr = payload[CAPTURE_META_DATA_TS_OFFSET_MSW];
710 }
711 /* Always assume read_size is same as fragment_size */
712 read_size = prtd->codec_param.buffer.fragment_size;
713 prtd->byte_offset += read_size;
714 prtd->received_total += read_size;
715 if (prtd->byte_offset >= prtd->buffer_size)
716 prtd->byte_offset -= prtd->buffer_size;
717
718 snd_compr_fragment_elapsed(cstream);
719
720 if (!atomic_read(&prtd->start)) {
721 pr_debug("read_done received while not started, treat as xrun");
722 atomic_set(&prtd->xrun, 1);
723 spin_unlock_irqrestore(&prtd->lock, flags);
724 break;
725 }
726 msm_compr_read_buffer(prtd);
727
728 spin_unlock_irqrestore(&prtd->lock, flags);
729 break;
730
731 case ASM_DATA_EVENT_RENDERED_EOS:
732 spin_lock_irqsave(&prtd->lock, flags);
733 pr_debug("%s: ASM_DATA_CMDRSP_EOS token 0x%x,stream id %d\n",
734 __func__, token, stream_id);
735 if (atomic_read(&prtd->eos) &&
736 !prtd->gapless_state.set_next_stream_id) {
737 pr_debug("ASM_DATA_CMDRSP_EOS wake up\n");
738 prtd->eos_ack = 1;
739 wake_up(&prtd->eos_wait);
740 }
741 atomic_set(&prtd->eos, 0);
742 stream_index = STREAM_ARRAY_INDEX(stream_id);
743 if (stream_index >= MAX_NUMBER_OF_STREAMS ||
744 stream_index < 0) {
745 pr_err("%s: Invalid stream index %d", __func__,
746 stream_index);
747 spin_unlock_irqrestore(&prtd->lock, flags);
748 break;
749 }
750
751 if (prtd->gapless_state.set_next_stream_id &&
752 prtd->gapless_state.stream_opened[stream_index]) {
753 pr_debug("%s: CMD_CLOSE stream_id %d\n",
754 __func__, stream_id);
755 q6asm_stream_cmd_nowait(ac, CMD_CLOSE, stream_id);
756 atomic_set(&prtd->close, 1);
757 prtd->gapless_state.stream_opened[stream_index] = 0;
758 prtd->gapless_state.set_next_stream_id = false;
759 }
760 if (prtd->gapless_state.gapless_transition)
761 prtd->gapless_state.gapless_transition = 0;
762 spin_unlock_irqrestore(&prtd->lock, flags);
763 break;
764 case ASM_STREAM_PP_EVENT:
765 case ASM_STREAM_CMD_ENCDEC_EVENTS:
766 pr_debug("%s: ASM_STREAM_EVENT(0x%x)\n", __func__, opcode);
767 rtd = cstream->private_data;
768 if (!rtd) {
769 pr_err("%s: rtd is NULL\n", __func__);
770 return;
771 }
772
773 ret = msm_adsp_inform_mixer_ctl(rtd, payload);
774 if (ret) {
775 pr_err("%s: failed to inform mixer ctrl. err = %d\n",
776 __func__, ret);
777 return;
778 }
779 break;
780 case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
781 case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY: {
782 pr_debug("ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY\n");
783 chan_mode = payload[1] >> 16;
784 sample_rate = payload[2] >> 16;
785 if (prtd && (chan_mode != prtd->num_channels ||
786 sample_rate != prtd->sample_rate)) {
787 prtd->num_channels = chan_mode;
788 prtd->sample_rate = sample_rate;
789 }
790 }
791 /* Fallthrough here */
792 case APR_BASIC_RSP_RESULT: {
793 switch (payload[0]) {
794 case ASM_SESSION_CMD_RUN_V2:
795 /* check if the first buffer need to be sent to DSP */
796 pr_debug("ASM_SESSION_CMD_RUN_V2\n");
797
798 /* FIXME: A state is a better way, dealing with this */
799 spin_lock_irqsave(&prtd->lock, flags);
800
801 if (cstream->direction == SND_COMPRESS_CAPTURE) {
802 atomic_set(&prtd->start, 1);
803 msm_compr_read_buffer(prtd);
804 spin_unlock_irqrestore(&prtd->lock, flags);
805 break;
806 }
807
808 if (!prtd->bytes_sent) {
809 bytes_available = prtd->bytes_received -
810 prtd->copied_total;
811 if (bytes_available <
812 cstream->runtime->fragment_size) {
813 pr_debug("CMD_RUN_V2 Insufficient data to send. break out\n");
814 atomic_set(&prtd->xrun, 1);
815 } else {
816 msm_compr_send_buffer(prtd);
817 }
818 }
819
820 /*
821 * The condition below ensures playback finishes in the
822 * follow cornercase
823 * WRITE(last buffer)
824 * WAIT_FOR_DRAIN
825 * PAUSE
826 * WRITE_DONE(X)
827 * RESUME
828 */
829 if ((prtd->copied_total == prtd->bytes_sent) &&
Weiyin Jiang7b51a252019-11-26 03:33:12 +0800830 atomic_read(&prtd->drain)) {
831 bytes_available = prtd->bytes_received - prtd->copied_total;
832 if (bytes_available < cstream->runtime->fragment_size) {
833 pr_debug("%s: RUN ack, wake up & continue pending drain\n",
834 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530835
Weiyin Jiang7b51a252019-11-26 03:33:12 +0800836 if (prtd->last_buffer)
837 prtd->last_buffer = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530838
Weiyin Jiang7b51a252019-11-26 03:33:12 +0800839 prtd->drain_ready = 1;
840 wake_up(&prtd->drain_wait);
841 atomic_set(&prtd->drain, 0);
842 } else if (atomic_read(&prtd->xrun)) {
843 pr_debug("%s: RUN ack, continue write cycle\n", __func__);
844 atomic_set(&prtd->xrun, 0);
845 msm_compr_send_buffer(prtd);
846 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530847 }
848
849 spin_unlock_irqrestore(&prtd->lock, flags);
850 break;
851 case ASM_STREAM_CMD_FLUSH:
852 pr_debug("%s: ASM_STREAM_CMD_FLUSH:", __func__);
853 pr_debug("token 0x%x, stream id %d\n", token,
854 stream_id);
855 prtd->cmd_ack = 1;
856 break;
857 case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:
858 pr_debug("%s: ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:",
859 __func__);
860 pr_debug("token 0x%x, stream id = %d\n", token,
861 stream_id);
862 break;
863 case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
864 pr_debug("%s: ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:",
865 __func__);
866 pr_debug("token = 0x%x, stream id = %d\n", token,
867 stream_id);
868 break;
869 case ASM_STREAM_CMD_CLOSE:
870 pr_debug("%s: ASM_DATA_CMD_CLOSE:", __func__);
871 pr_debug("token 0x%x, stream id %d\n", token,
872 stream_id);
873 /*
874 * wakeup wait for stream avail on stream 3
875 * after stream 1 ends.
876 */
877 if (prtd->next_stream) {
878 pr_debug("%s:CLOSE:wakeup wait for stream\n",
879 __func__);
880 prtd->stream_available = 1;
881 wake_up(&prtd->wait_for_stream_avail);
882 prtd->next_stream = 0;
883 }
884 if (atomic_read(&prtd->close) &&
885 atomic_read(&prtd->wait_on_close)) {
886 prtd->cmd_ack = 1;
887 wake_up(&prtd->close_wait);
888 }
889 atomic_set(&prtd->close, 0);
890 break;
891 case ASM_STREAM_CMD_REGISTER_PP_EVENTS:
892 pr_debug("%s: ASM_STREAM_CMD_REGISTER_PP_EVENTS:",
893 __func__);
894 break;
895 default:
896 break;
897 }
898 break;
899 }
900 case ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3:
901 pr_debug("%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3\n",
902 __func__);
903 break;
904 case RESET_EVENTS:
905 pr_err("%s: Received reset events CB, move to error state",
906 __func__);
907 spin_lock_irqsave(&prtd->lock, flags);
908 /*
909 * Since ADSP is down, let this driver pretend that it copied
910 * all the bytes received, so that next write will be triggered
911 */
912 prtd->copied_total = prtd->bytes_received;
913 snd_compr_fragment_elapsed(cstream);
914 atomic_set(&prtd->error, 1);
915 wake_up(&prtd->drain_wait);
916 if (atomic_cmpxchg(&prtd->eos, 1, 0)) {
917 pr_debug("%s:unblock eos wait queues", __func__);
918 wake_up(&prtd->eos_wait);
919 }
920 spin_unlock_irqrestore(&prtd->lock, flags);
921 break;
922 default:
923 pr_debug("%s: Not Supported Event opcode[0x%x]\n",
924 __func__, opcode);
925 break;
926 }
927}
928
929static int msm_compr_get_partial_drain_delay(int frame_sz, int sample_rate)
930{
931 int delay_time_ms = 0;
932
933 delay_time_ms = ((DSP_NUM_OUTPUT_FRAME_BUFFERED * frame_sz * 1000) /
934 sample_rate) + DSP_PP_BUFFERING_IN_MSEC;
935 delay_time_ms = delay_time_ms > PARTIAL_DRAIN_ACK_EARLY_BY_MSEC ?
936 delay_time_ms - PARTIAL_DRAIN_ACK_EARLY_BY_MSEC : 0;
937
938 pr_debug("%s: frame_sz %d, sample_rate %d, partial drain delay %d\n",
939 __func__, frame_sz, sample_rate, delay_time_ms);
940 return delay_time_ms;
941}
942
943static void populate_codec_list(struct msm_compr_audio *prtd)
944{
945 pr_debug("%s\n", __func__);
946 prtd->compr_cap.direction = SND_COMPRESS_PLAYBACK;
947 prtd->compr_cap.min_fragment_size =
948 COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
949 prtd->compr_cap.max_fragment_size =
950 COMPR_PLAYBACK_MAX_FRAGMENT_SIZE;
951 prtd->compr_cap.min_fragments =
952 COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
953 prtd->compr_cap.max_fragments =
954 COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
955 prtd->compr_cap.num_codecs = 17;
956 prtd->compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
957 prtd->compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
958 prtd->compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
959 prtd->compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3;
960 prtd->compr_cap.codecs[4] = SND_AUDIOCODEC_MP2;
961 prtd->compr_cap.codecs[5] = SND_AUDIOCODEC_PCM;
962 prtd->compr_cap.codecs[6] = SND_AUDIOCODEC_WMA;
963 prtd->compr_cap.codecs[7] = SND_AUDIOCODEC_WMA_PRO;
964 prtd->compr_cap.codecs[8] = SND_AUDIOCODEC_FLAC;
965 prtd->compr_cap.codecs[9] = SND_AUDIOCODEC_VORBIS;
966 prtd->compr_cap.codecs[10] = SND_AUDIOCODEC_ALAC;
967 prtd->compr_cap.codecs[11] = SND_AUDIOCODEC_APE;
968 prtd->compr_cap.codecs[12] = SND_AUDIOCODEC_DTS;
969 prtd->compr_cap.codecs[13] = SND_AUDIOCODEC_DSD;
970 prtd->compr_cap.codecs[14] = SND_AUDIOCODEC_APTX;
971 prtd->compr_cap.codecs[15] = SND_AUDIOCODEC_TRUEHD;
972 prtd->compr_cap.codecs[16] = SND_AUDIOCODEC_IEC61937;
973}
974
975static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
976 int stream_id,
977 bool use_gapless_codec_options)
978{
979 struct snd_compr_runtime *runtime = cstream->runtime;
980 struct msm_compr_audio *prtd = runtime->private_data;
981 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Meng Wangee084a02018-09-04 16:11:58 +0800982 struct snd_soc_component *component =NULL;
983 struct msm_compr_pdata *pdata = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530984 struct asm_aac_cfg aac_cfg;
985 struct asm_wma_cfg wma_cfg;
986 struct asm_wmapro_cfg wma_pro_cfg;
987 struct asm_flac_cfg flac_cfg;
988 struct asm_vorbis_cfg vorbis_cfg;
989 struct asm_alac_cfg alac_cfg;
990 struct asm_ape_cfg ape_cfg;
991 struct asm_dsd_cfg dsd_cfg;
992 struct aptx_dec_bt_addr_cfg aptx_cfg;
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +0530993 struct asm_amrwbplus_cfg amrwbplus_cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530994 union snd_codec_options *codec_options;
995
996 int ret = 0;
997 uint16_t bit_width;
998 bool use_default_chmap = true;
999 char *chmap = NULL;
1000 uint16_t sample_word_size;
1001
1002 pr_debug("%s: use_gapless_codec_options %d\n",
1003 __func__, use_gapless_codec_options);
1004
Meng Wangee084a02018-09-04 16:11:58 +08001005 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
1006 if (!component) {
1007 pr_err("%s: component is NULL\n", __func__);
1008 return -EINVAL;
1009 }
1010 pdata = snd_soc_component_get_drvdata(component);
1011
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301012 if (use_gapless_codec_options)
1013 codec_options = &(prtd->gapless_state.codec_options);
1014 else
1015 codec_options = &(prtd->codec_param.codec.options);
1016
1017 if (!codec_options) {
1018 pr_err("%s: codec_options is NULL\n", __func__);
1019 return -EINVAL;
1020 }
1021
1022 switch (prtd->codec) {
1023 case FORMAT_LINEAR_PCM:
1024 pr_debug("SND_AUDIOCODEC_PCM\n");
1025 if (pdata->ch_map[rtd->dai_link->id]) {
1026 use_default_chmap =
1027 !(pdata->ch_map[rtd->dai_link->id]->set_ch_map);
1028 chmap =
1029 pdata->ch_map[rtd->dai_link->id]->channel_map;
1030 }
1031
1032 switch (prtd->codec_param.codec.format) {
1033 case SNDRV_PCM_FORMAT_S32_LE:
1034 bit_width = 32;
1035 sample_word_size = 32;
1036 break;
1037 case SNDRV_PCM_FORMAT_S24_LE:
1038 bit_width = 24;
1039 sample_word_size = 32;
1040 break;
1041 case SNDRV_PCM_FORMAT_S24_3LE:
1042 bit_width = 24;
1043 sample_word_size = 24;
1044 break;
1045 case SNDRV_PCM_FORMAT_S16_LE:
1046 default:
1047 bit_width = 16;
1048 sample_word_size = 16;
1049 break;
1050 }
Dieter Lueckingceef9af2018-09-28 15:09:32 +02001051
1052 if (q6core_get_avcs_api_version_per_service(
1053 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1054 ADSP_ASM_API_VERSION_V2) {
1055 ret = q6asm_media_format_block_pcm_format_support_v5(
1056 prtd->audio_client,
1057 prtd->sample_rate,
1058 prtd->num_channels,
1059 bit_width, stream_id,
1060 use_default_chmap,
1061 chmap,
1062 sample_word_size,
1063 ASM_LITTLE_ENDIAN,
1064 DEFAULT_QF);
1065 } else {
1066 ret = q6asm_media_format_block_pcm_format_support_v4(
1067 prtd->audio_client,
1068 prtd->sample_rate,
1069 prtd->num_channels,
1070 bit_width, stream_id,
1071 use_default_chmap,
1072 chmap,
1073 sample_word_size,
1074 ASM_LITTLE_ENDIAN,
1075 DEFAULT_QF);
1076 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301077 if (ret < 0)
1078 pr_err("%s: CMD Format block failed\n", __func__);
1079
1080 break;
1081 case FORMAT_MP3:
1082 pr_debug("SND_AUDIOCODEC_MP3\n");
1083 /* no media format block needed */
1084 break;
1085 case FORMAT_MPEG4_AAC:
1086 pr_debug("SND_AUDIOCODEC_AAC\n");
1087 memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg));
1088 aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
1089 if (prtd->codec_param.codec.format ==
1090 SND_AUDIOSTREAMFORMAT_MP4ADTS)
1091 aac_cfg.format = 0x0;
1092 else if (prtd->codec_param.codec.format ==
1093 SND_AUDIOSTREAMFORMAT_MP4LATM)
1094 aac_cfg.format = 0x04;
1095 else
1096 aac_cfg.format = 0x03;
1097 aac_cfg.ch_cfg = prtd->num_channels;
1098 aac_cfg.sample_rate = prtd->sample_rate;
1099 ret = q6asm_stream_media_format_block_aac(prtd->audio_client,
1100 &aac_cfg, stream_id);
1101 if (ret < 0)
1102 pr_err("%s: CMD Format block failed\n", __func__);
1103 break;
1104 case FORMAT_AC3:
1105 pr_debug("SND_AUDIOCODEC_AC3\n");
1106 break;
1107 case FORMAT_EAC3:
1108 pr_debug("SND_AUDIOCODEC_EAC3\n");
1109 break;
1110 case FORMAT_WMA_V9:
1111 pr_debug("SND_AUDIOCODEC_WMA\n");
1112 memset(&wma_cfg, 0x0, sizeof(struct asm_wma_cfg));
1113 wma_cfg.format_tag = prtd->codec_param.codec.format;
1114 wma_cfg.ch_cfg = prtd->codec_param.codec.ch_in;
1115 wma_cfg.sample_rate = prtd->sample_rate;
1116 wma_cfg.avg_bytes_per_sec = codec_options->wma.avg_bit_rate/8;
1117 wma_cfg.block_align = codec_options->wma.super_block_align;
1118 wma_cfg.valid_bits_per_sample =
1119 codec_options->wma.bits_per_sample;
1120 wma_cfg.ch_mask = codec_options->wma.channelmask;
1121 wma_cfg.encode_opt = codec_options->wma.encodeopt;
1122 ret = q6asm_media_format_block_wma(prtd->audio_client,
1123 &wma_cfg, stream_id);
1124 if (ret < 0)
1125 pr_err("%s: CMD Format block failed\n", __func__);
1126 break;
1127 case FORMAT_WMA_V10PRO:
1128 pr_debug("SND_AUDIOCODEC_WMA_PRO\n");
1129 memset(&wma_pro_cfg, 0x0, sizeof(struct asm_wmapro_cfg));
1130 wma_pro_cfg.format_tag = prtd->codec_param.codec.format;
1131 wma_pro_cfg.ch_cfg = prtd->codec_param.codec.ch_in;
1132 wma_pro_cfg.sample_rate = prtd->sample_rate;
1133 wma_cfg.avg_bytes_per_sec = codec_options->wma.avg_bit_rate/8;
1134 wma_pro_cfg.block_align = codec_options->wma.super_block_align;
1135 wma_pro_cfg.valid_bits_per_sample =
1136 codec_options->wma.bits_per_sample;
1137 wma_pro_cfg.ch_mask = codec_options->wma.channelmask;
1138 wma_pro_cfg.encode_opt = codec_options->wma.encodeopt;
1139 wma_pro_cfg.adv_encode_opt = codec_options->wma.encodeopt1;
1140 wma_pro_cfg.adv_encode_opt2 = codec_options->wma.encodeopt2;
1141 ret = q6asm_media_format_block_wmapro(prtd->audio_client,
1142 &wma_pro_cfg, stream_id);
1143 if (ret < 0)
1144 pr_err("%s: CMD Format block failed\n", __func__);
1145 break;
1146 case FORMAT_MP2:
1147 pr_debug("%s: SND_AUDIOCODEC_MP2\n", __func__);
1148 break;
1149 case FORMAT_FLAC:
1150 pr_debug("%s: SND_AUDIOCODEC_FLAC\n", __func__);
1151 memset(&flac_cfg, 0x0, sizeof(struct asm_flac_cfg));
1152 flac_cfg.ch_cfg = prtd->num_channels;
1153 flac_cfg.sample_rate = prtd->sample_rate;
1154 flac_cfg.stream_info_present = 1;
1155 flac_cfg.sample_size = codec_options->flac_dec.sample_size;
1156 flac_cfg.min_blk_size = codec_options->flac_dec.min_blk_size;
1157 flac_cfg.max_blk_size = codec_options->flac_dec.max_blk_size;
1158 flac_cfg.max_frame_size =
1159 codec_options->flac_dec.max_frame_size;
1160 flac_cfg.min_frame_size =
1161 codec_options->flac_dec.min_frame_size;
1162
1163 ret = q6asm_stream_media_format_block_flac(prtd->audio_client,
1164 &flac_cfg, stream_id);
1165 if (ret < 0)
1166 pr_err("%s: CMD Format block failed ret %d\n",
1167 __func__, ret);
1168
1169 break;
1170 case FORMAT_VORBIS:
1171 pr_debug("%s: SND_AUDIOCODEC_VORBIS\n", __func__);
1172 memset(&vorbis_cfg, 0x0, sizeof(struct asm_vorbis_cfg));
1173 vorbis_cfg.bit_stream_fmt =
1174 codec_options->vorbis_dec.bit_stream_fmt;
1175
1176 ret = q6asm_stream_media_format_block_vorbis(
1177 prtd->audio_client, &vorbis_cfg,
1178 stream_id);
1179 if (ret < 0)
1180 pr_err("%s: CMD Format block failed ret %d\n",
1181 __func__, ret);
1182
1183 break;
1184 case FORMAT_ALAC:
1185 pr_debug("%s: SND_AUDIOCODEC_ALAC\n", __func__);
1186 memset(&alac_cfg, 0x0, sizeof(struct asm_alac_cfg));
1187 alac_cfg.num_channels = prtd->num_channels;
1188 alac_cfg.sample_rate = prtd->sample_rate;
1189 alac_cfg.frame_length = codec_options->alac.frame_length;
1190 alac_cfg.compatible_version =
1191 codec_options->alac.compatible_version;
1192 alac_cfg.bit_depth = codec_options->alac.bit_depth;
1193 alac_cfg.pb = codec_options->alac.pb;
1194 alac_cfg.mb = codec_options->alac.mb;
1195 alac_cfg.kb = codec_options->alac.kb;
1196 alac_cfg.max_run = codec_options->alac.max_run;
1197 alac_cfg.max_frame_bytes = codec_options->alac.max_frame_bytes;
1198 alac_cfg.avg_bit_rate = codec_options->alac.avg_bit_rate;
1199 alac_cfg.channel_layout_tag =
1200 codec_options->alac.channel_layout_tag;
1201
1202 ret = q6asm_media_format_block_alac(prtd->audio_client,
1203 &alac_cfg, stream_id);
1204 if (ret < 0)
1205 pr_err("%s: CMD Format block failed ret %d\n",
1206 __func__, ret);
1207 break;
1208 case FORMAT_APE:
1209 pr_debug("%s: SND_AUDIOCODEC_APE\n", __func__);
1210 memset(&ape_cfg, 0x0, sizeof(struct asm_ape_cfg));
1211 ape_cfg.num_channels = prtd->num_channels;
1212 ape_cfg.sample_rate = prtd->sample_rate;
1213 ape_cfg.compatible_version =
1214 codec_options->ape.compatible_version;
1215 ape_cfg.compression_level =
1216 codec_options->ape.compression_level;
1217 ape_cfg.format_flags = codec_options->ape.format_flags;
1218 ape_cfg.blocks_per_frame = codec_options->ape.blocks_per_frame;
1219 ape_cfg.final_frame_blocks =
1220 codec_options->ape.final_frame_blocks;
1221 ape_cfg.total_frames = codec_options->ape.total_frames;
1222 ape_cfg.bits_per_sample = codec_options->ape.bits_per_sample;
1223 ape_cfg.seek_table_present =
1224 codec_options->ape.seek_table_present;
1225
1226 ret = q6asm_media_format_block_ape(prtd->audio_client,
1227 &ape_cfg, stream_id);
1228
1229 if (ret < 0)
1230 pr_err("%s: CMD Format block failed ret %d\n",
1231 __func__, ret);
1232 break;
1233 case FORMAT_DTS:
1234 pr_debug("SND_AUDIOCODEC_DTS\n");
1235 /* no media format block needed */
1236 break;
1237 case FORMAT_DSD:
1238 pr_debug("%s: SND_AUDIOCODEC_DSD\n", __func__);
1239 memset(&dsd_cfg, 0x0, sizeof(struct asm_dsd_cfg));
1240 dsd_cfg.num_channels = prtd->num_channels;
1241 dsd_cfg.dsd_data_rate = prtd->sample_rate;
1242 dsd_cfg.num_version = 0;
1243 dsd_cfg.is_bitwise_big_endian = 1;
1244 dsd_cfg.dsd_channel_block_size = 1;
Sanjana Bc45335a2019-12-06 17:16:36 +05301245
1246 if (codec_options->dsd_dec.blk_size == DSD_BLOCK_SIZE_4)
1247 dsd_cfg.dsd_channel_block_size =
1248 codec_options->dsd_dec.blk_size;
1249
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301250 ret = q6asm_media_format_block_dsd(prtd->audio_client,
1251 &dsd_cfg, stream_id);
1252 if (ret < 0)
1253 pr_err("%s: CMD DSD Format block failed ret %d\n",
1254 __func__, ret);
1255 break;
1256 case FORMAT_TRUEHD:
1257 pr_debug("SND_AUDIOCODEC_TRUEHD\n");
1258 /* no media format block needed */
1259 break;
1260 case FORMAT_IEC61937:
1261 pr_debug("SND_AUDIOCODEC_IEC61937\n");
1262 ret = q6asm_media_format_block_iec(prtd->audio_client,
1263 prtd->sample_rate,
1264 prtd->num_channels);
1265 if (ret < 0)
1266 pr_err("%s: CMD IEC61937 Format block failed ret %d\n",
1267 __func__, ret);
1268 break;
1269 case FORMAT_APTX:
1270 pr_debug("SND_AUDIOCODEC_APTX\n");
1271 memset(&aptx_cfg, 0x0, sizeof(struct aptx_dec_bt_addr_cfg));
1272 ret = q6asm_stream_media_format_block_aptx_dec(
1273 prtd->audio_client,
1274 prtd->sample_rate,
1275 stream_id);
1276 if (ret >= 0) {
1277 aptx_cfg.nap = codec_options->aptx_dec.nap;
1278 aptx_cfg.uap = codec_options->aptx_dec.uap;
1279 aptx_cfg.lap = codec_options->aptx_dec.lap;
1280 q6asm_set_aptx_dec_bt_addr(prtd->audio_client,
1281 &aptx_cfg);
1282 } else {
1283 pr_err("%s: CMD Format block failed ret %d\n",
1284 __func__, ret);
1285 }
1286 break;
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +05301287 case FORMAT_AMRNB:
1288 pr_debug("SND_AUDIOCODEC_AMR\n");
1289 /* no media format block needed */
1290 break;
1291 case FORMAT_AMRWB:
1292 pr_debug("SND_AUDIOCODEC_AMRWB\n");
1293 /* no media format block needed */
1294 break;
1295 case FORMAT_AMR_WB_PLUS:
1296 pr_debug("SND_AUDIOCODEC_AMRWBPLUS\n");
1297 memset(&amrwbplus_cfg, 0x0, sizeof(struct asm_amrwbplus_cfg));
1298 amrwbplus_cfg.amr_frame_fmt =
1299 codec_options->amrwbplus.bit_stream_fmt;
1300 ret = q6asm_media_format_block_amrwbplus(
1301 prtd->audio_client,
1302 &amrwbplus_cfg);
1303 if (ret < 0)
1304 pr_err("%s: CMD AMRWBPLUS Format block failed ret %d\n",
1305 __func__, ret);
1306 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301307 default:
1308 pr_debug("%s, unsupported format, skip", __func__);
1309 break;
1310 }
1311 return ret;
1312}
1313
1314static int msm_compr_init_pp_params(struct snd_compr_stream *cstream,
1315 struct audio_client *ac)
1316{
1317 int ret = 0;
1318 struct asm_softvolume_params softvol = {
1319 .period = SOFT_VOLUME_PERIOD,
1320 .step = SOFT_VOLUME_STEP,
1321 .rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
1322 };
1323
1324 switch (ac->topology) {
1325 default:
1326 ret = q6asm_set_softvolume_v2(ac, &softvol,
1327 SOFT_VOLUME_INSTANCE_1);
1328 if (ret < 0)
1329 pr_err("%s: Send SoftVolume Param failed ret=%d\n",
1330 __func__, ret);
1331
1332 break;
1333 }
1334 return ret;
1335}
1336
1337static int msm_compr_configure_dsp_for_playback
1338 (struct snd_compr_stream *cstream)
1339{
1340 struct snd_compr_runtime *runtime = cstream->runtime;
1341 struct msm_compr_audio *prtd = runtime->private_data;
1342 struct snd_soc_pcm_runtime *soc_prtd = cstream->private_data;
1343 uint16_t bits_per_sample = 16;
1344 int dir = IN, ret = 0;
1345 struct audio_client *ac = prtd->audio_client;
1346 uint32_t stream_index;
1347 struct asm_softpause_params softpause = {
1348 .enable = SOFT_PAUSE_ENABLE,
1349 .period = SOFT_PAUSE_PERIOD,
1350 .step = SOFT_PAUSE_STEP,
1351 .rampingcurve = SOFT_PAUSE_CURVE_LINEAR,
1352 };
1353 struct asm_softvolume_params softvol = {
1354 .period = SOFT_VOLUME_PERIOD,
1355 .step = SOFT_VOLUME_STEP,
1356 .rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
1357 };
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05301358 struct snd_kcontrol *kctl;
1359 struct snd_ctl_elem_value kctl_elem_value;
1360 uint16_t target_asm_bit_width = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301361
1362 pr_debug("%s: stream_id %d\n", __func__, ac->stream_id);
1363 stream_index = STREAM_ARRAY_INDEX(ac->stream_id);
1364 if (stream_index >= MAX_NUMBER_OF_STREAMS || stream_index < 0) {
1365 pr_err("%s: Invalid stream index:%d", __func__, stream_index);
1366 return -EINVAL;
1367 }
1368
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05301369 kctl = snd_soc_card_get_kcontrol(soc_prtd->card,
1370 DSP_BIT_WIDTH_MIXER_CTL);
1371 if (kctl) {
1372 kctl->get(kctl, &kctl_elem_value);
1373 target_asm_bit_width = kctl_elem_value.value.integer.value[0];
1374 if (target_asm_bit_width > 0) {
1375 pr_debug("%s enforce ASM bitwidth to %d from %d\n",
1376 __func__,
1377 target_asm_bit_width,
1378 bits_per_sample);
1379 bits_per_sample = target_asm_bit_width;
1380 }
1381 } else {
1382 pr_info("%s: failed to get mixer ctl for %s.\n",
1383 __func__, DSP_BIT_WIDTH_MIXER_CTL);
1384 }
1385
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301386 if ((prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_LE) ||
1387 (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_3LE))
1388 bits_per_sample = 24;
1389 else if (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S32_LE)
1390 bits_per_sample = 32;
1391
1392 if (prtd->compr_passthr != LEGACY_PCM) {
1393 ret = q6asm_open_write_compressed(ac, prtd->codec,
1394 prtd->compr_passthr);
1395 if (ret < 0) {
1396 pr_err("%s:ASM open write err[%d] for compr_type[%d]\n",
1397 __func__, ret, prtd->compr_passthr);
1398 return ret;
1399 }
1400 prtd->gapless_state.stream_opened[stream_index] = 1;
1401
1402 ret = msm_pcm_routing_reg_phy_compr_stream(
1403 soc_prtd->dai_link->id,
1404 ac->perf_mode,
1405 prtd->session_id,
1406 SNDRV_PCM_STREAM_PLAYBACK,
1407 prtd->compr_passthr);
1408 if (ret) {
1409 pr_err("%s: compr stream reg failed:%d\n", __func__,
1410 ret);
1411 return ret;
1412 }
1413 } else {
1414 pr_debug("%s: stream_id %d bits_per_sample %d\n",
1415 __func__, ac->stream_id, bits_per_sample);
Dieter Lueckingceef9af2018-09-28 15:09:32 +02001416
1417 if (q6core_get_avcs_api_version_per_service(
1418 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1419 ADSP_ASM_API_VERSION_V2)
1420 ret = q6asm_stream_open_write_v5(ac,
1421 prtd->codec, bits_per_sample,
1422 ac->stream_id,
1423 prtd->gapless_state.use_dsp_gapless_mode);
1424 else
1425 ret = q6asm_stream_open_write_v4(ac,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301426 prtd->codec, bits_per_sample,
1427 ac->stream_id,
1428 prtd->gapless_state.use_dsp_gapless_mode);
1429 if (ret < 0) {
1430 pr_err("%s:ASM open write err[%d] for compr type[%d]\n",
1431 __func__, ret, prtd->compr_passthr);
1432 return -ENOMEM;
1433 }
1434 prtd->gapless_state.stream_opened[stream_index] = 1;
1435
1436 pr_debug("%s: BE id %d\n", __func__, soc_prtd->dai_link->id);
1437 ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->id,
1438 ac->perf_mode,
1439 prtd->session_id,
1440 SNDRV_PCM_STREAM_PLAYBACK);
1441 if (ret) {
1442 pr_err("%s: stream reg failed:%d\n", __func__, ret);
1443 return ret;
1444 }
1445 }
1446
1447 ret = msm_compr_set_volume(cstream, 0, 0);
1448 if (ret < 0)
1449 pr_err("%s : Set Volume failed : %d", __func__, ret);
1450
1451 if (prtd->compr_passthr != LEGACY_PCM) {
1452 pr_debug("%s : Don't send cal and PP params for compress path",
1453 __func__);
1454 } else {
1455 ret = q6asm_send_cal(ac);
1456 if (ret < 0)
1457 pr_debug("%s : Send cal failed : %d", __func__, ret);
1458
1459 ret = q6asm_set_softpause(ac, &softpause);
1460 if (ret < 0)
1461 pr_err("%s: Send SoftPause Param failed ret=%d\n",
1462 __func__, ret);
1463
1464 ret = q6asm_set_softvolume(ac, &softvol);
1465 if (ret < 0)
1466 pr_err("%s: Send SoftVolume Param failed ret=%d\n",
1467 __func__, ret);
1468 }
1469 ret = q6asm_set_io_mode(ac, (COMPRESSED_STREAM_IO | ASYNC_IO_MODE));
1470 if (ret < 0) {
1471 pr_err("%s: Set IO mode failed\n", __func__);
1472 return -EINVAL;
1473 }
1474
1475 runtime->fragments = prtd->codec_param.buffer.fragments;
1476 runtime->fragment_size = prtd->codec_param.buffer.fragment_size;
1477 pr_debug("allocate %d buffers each of size %d\n",
1478 runtime->fragments,
1479 runtime->fragment_size);
1480 ret = q6asm_audio_client_buf_alloc_contiguous(dir, ac,
1481 runtime->fragment_size,
1482 runtime->fragments);
1483 if (ret < 0) {
1484 pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
1485 return -ENOMEM;
1486 }
1487
1488 prtd->byte_offset = 0;
1489 prtd->copied_total = 0;
1490 prtd->app_pointer = 0;
1491 prtd->bytes_received = 0;
1492 prtd->bytes_sent = 0;
1493 prtd->buffer = ac->port[dir].buf[0].data;
1494 prtd->buffer_paddr = ac->port[dir].buf[0].phys;
1495 prtd->buffer_size = runtime->fragments * runtime->fragment_size;
1496
1497 /* Bit-0 of flags represent timestamp mode */
1498 if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG)
1499 prtd->ts_header_offset = sizeof(struct snd_codec_metadata);
1500 else
1501 prtd->ts_header_offset = 0;
1502
1503 ret = msm_compr_send_media_format_block(cstream, ac->stream_id, false);
1504 if (ret < 0)
1505 pr_err("%s, failed to send media format block\n", __func__);
1506
1507 return ret;
1508}
1509
1510static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
1511{
1512 struct snd_compr_runtime *runtime = cstream->runtime;
1513 struct msm_compr_audio *prtd = runtime->private_data;
1514 struct snd_soc_pcm_runtime *soc_prtd = cstream->private_data;
1515 uint16_t bits_per_sample;
1516 uint16_t sample_word_size;
1517 int dir = OUT, ret = 0;
1518 struct audio_client *ac = prtd->audio_client;
1519 uint32_t stream_index;
Vikram Pandurangac712c172017-11-17 17:36:49 -08001520 uint32_t enc_cfg_id = ENC_CFG_ID_NONE;
Surendar Karkaafd3e122019-10-31 10:55:40 +05301521 bool compress_ts = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301522
1523 switch (prtd->codec_param.codec.format) {
1524 case SNDRV_PCM_FORMAT_S24_LE:
1525 bits_per_sample = 24;
1526 sample_word_size = 32;
1527 break;
1528 case SNDRV_PCM_FORMAT_S24_3LE:
1529 bits_per_sample = 24;
1530 sample_word_size = 24;
1531 break;
1532 case SNDRV_PCM_FORMAT_S32_LE:
1533 bits_per_sample = 32;
1534 sample_word_size = 32;
1535 break;
1536 case SNDRV_PCM_FORMAT_S16_LE:
1537 default:
1538 bits_per_sample = 16;
1539 sample_word_size = 16;
Vikram Pandurangac712c172017-11-17 17:36:49 -08001540 if (prtd->codec == FORMAT_BESPOKE)
1541 enc_cfg_id =
1542 prtd->codec_param.codec.options.generic.reserved[0];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301543 break;
1544 }
1545
Ralf Herz22573552018-06-20 11:30:58 +02001546 pr_debug("%s: stream_id %d bits_per_sample %d compr_passthr %d\n",
1547 __func__, ac->stream_id, bits_per_sample,
1548 prtd->compr_passthr);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301549
Ralf Herz22573552018-06-20 11:30:58 +02001550 if (prtd->compr_passthr != LEGACY_PCM) {
1551 ret = q6asm_open_read_compressed(prtd->audio_client,
1552 prtd->codec, prtd->compr_passthr);
1553 if (ret < 0) {
1554 pr_err("%s:ASM open read err[%d] for compr_type[%d]\n",
1555 __func__, ret, prtd->compr_passthr);
1556 return ret;
1557 }
1558
1559 ret = msm_pcm_routing_reg_phy_compr_stream(
1560 soc_prtd->dai_link->id,
1561 ac->perf_mode,
1562 prtd->session_id,
1563 SNDRV_PCM_STREAM_CAPTURE,
1564 prtd->compr_passthr);
1565 if (ret) {
1566 pr_err("%s: compr stream reg failed:%d\n",
1567 __func__, ret);
1568 return ret;
1569 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301570 } else {
Surendar Karkaafd3e122019-10-31 10:55:40 +05301571 if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG)
1572 compress_ts = true;
1573
1574 if (q6core_get_avcs_api_version_per_service(
1575 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1576 ADSP_ASM_API_VERSION_V2)
1577 ret = q6asm_open_read_v5(prtd->audio_client,
1578 prtd->codec, bits_per_sample,
1579 compress_ts, enc_cfg_id);
1580 else
Ralf Herz22573552018-06-20 11:30:58 +02001581 ret = q6asm_open_read_v4(prtd->audio_client,
Surendar Karkaafd3e122019-10-31 10:55:40 +05301582 prtd->codec, bits_per_sample,
1583 compress_ts, enc_cfg_id);
Ralf Herz22573552018-06-20 11:30:58 +02001584 if (ret < 0) {
1585 pr_err("%s: q6asm_open_read failed:%d\n",
1586 __func__, ret);
1587 return ret;
1588 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301589
Ralf Herz22573552018-06-20 11:30:58 +02001590 ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->id,
1591 ac->perf_mode,
1592 prtd->session_id,
1593 SNDRV_PCM_STREAM_CAPTURE);
1594 if (ret) {
1595 pr_err("%s: stream reg failed:%d\n", __func__, ret);
1596 return ret;
1597 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301598 }
1599
1600 ret = q6asm_set_io_mode(ac, (COMPRESSED_STREAM_IO | ASYNC_IO_MODE));
1601 if (ret < 0) {
1602 pr_err("%s: Set IO mode failed\n", __func__);
1603 return -EINVAL;
1604 }
1605
1606 stream_index = STREAM_ARRAY_INDEX(ac->stream_id);
1607 if (stream_index >= MAX_NUMBER_OF_STREAMS || stream_index < 0) {
1608 pr_err("%s: Invalid stream index:%d", __func__, stream_index);
1609 return -EINVAL;
1610 }
1611
1612 runtime->fragments = prtd->codec_param.buffer.fragments;
1613 runtime->fragment_size = prtd->codec_param.buffer.fragment_size;
1614 pr_debug("%s: allocate %d buffers each of size %d\n",
1615 __func__, runtime->fragments,
1616 runtime->fragment_size);
1617 ret = q6asm_audio_client_buf_alloc_contiguous(dir, ac,
1618 runtime->fragment_size,
1619 runtime->fragments);
1620 if (ret < 0) {
1621 pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
1622 return -ENOMEM;
1623 }
1624
1625 prtd->byte_offset = 0;
1626 prtd->received_total = 0;
1627 prtd->app_pointer = 0;
1628 prtd->bytes_copied = 0;
1629 prtd->bytes_read = 0;
1630 prtd->bytes_read_offset = 0;
1631 prtd->buffer = ac->port[dir].buf[0].data;
1632 prtd->buffer_paddr = ac->port[dir].buf[0].phys;
1633 prtd->buffer_size = runtime->fragments * runtime->fragment_size;
1634
1635 /* Bit-0 of flags represent timestamp mode */
1636 if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG)
1637 prtd->ts_header_offset = sizeof(struct snd_codec_metadata);
1638 else
1639 prtd->ts_header_offset = 0;
1640
1641 pr_debug("%s: sample_rate = %d channels = %d bps = %d sample_word_size = %d\n",
1642 __func__, prtd->sample_rate, prtd->num_channels,
1643 bits_per_sample, sample_word_size);
Vikram Pandurangac712c172017-11-17 17:36:49 -08001644 if (prtd->codec == FORMAT_BESPOKE) {
1645 /*
1646 * For BESPOKE codec, encoder specific config params are
1647 * included as part of generic.
1648 */
1649 ret = q6asm_enc_cfg_blk_custom(prtd->audio_client, prtd->sample_rate,
1650 prtd->num_channels, prtd->codec,
1651 (void *)&prtd->codec_param.codec.options.generic);
Ralf Herz22573552018-06-20 11:30:58 +02001652 } else if (prtd->compr_passthr == LEGACY_PCM) {
Chaithanya Krishna Bacharaju61b2de62019-06-20 11:40:17 +05301653 if (q6core_get_avcs_api_version_per_service(
1654 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1655 ADSP_ASM_API_VERSION_V2)
1656 ret = q6asm_enc_cfg_blk_pcm_format_support_v5(
1657 prtd->audio_client,
1658 prtd->sample_rate, prtd->num_channels,
1659 bits_per_sample, sample_word_size,
1660 ASM_LITTLE_ENDIAN, DEFAULT_QF);
1661 else
1662 ret = q6asm_enc_cfg_blk_pcm_format_support_v4(
1663 prtd->audio_client,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301664 prtd->sample_rate, prtd->num_channels,
Sachin Mohan Gadag7c944232018-01-04 11:04:00 +05301665 bits_per_sample, sample_word_size,
1666 ASM_LITTLE_ENDIAN, DEFAULT_QF);
Vikram Pandurangac712c172017-11-17 17:36:49 -08001667 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301668
1669 return ret;
1670}
1671
1672static int msm_compr_playback_open(struct snd_compr_stream *cstream)
1673{
1674 struct snd_compr_runtime *runtime = cstream->runtime;
1675 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Meng Wangee084a02018-09-04 16:11:58 +08001676 struct snd_soc_component *component = NULL;
Aditya Bavanari9deef912017-11-20 13:31:31 +05301677 struct msm_compr_audio *prtd = NULL;
Meng Wangee084a02018-09-04 16:11:58 +08001678 struct msm_compr_pdata *pdata = NULL;
Ramprasad Katkam17f05162019-04-15 18:37:10 +05301679 enum apr_subsys_state subsys_state;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301680
1681 pr_debug("%s\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08001682 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
1683 if (!component) {
1684 pr_err("%s: component is NULL\n", __func__);
1685 return -EINVAL;
1686 }
1687 pdata = snd_soc_component_get_drvdata(component);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301688 if (pdata->is_in_use[rtd->dai_link->id] == true) {
1689 pr_err("%s: %s is already in use, err: %d\n",
1690 __func__, rtd->dai_link->cpu_dai_name, -EBUSY);
1691 return -EBUSY;
1692 }
Ramprasad Katkam17f05162019-04-15 18:37:10 +05301693
1694 subsys_state = apr_get_subsys_state();
1695 if (subsys_state == APR_SUBSYS_DOWN) {
1696 pr_debug("%s: adsp is down\n", __func__);
1697 return -ENETRESET;
1698 }
1699
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301700 prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL);
1701 if (prtd == NULL) {
1702 pr_err("Failed to allocate memory for msm_compr_audio\n");
1703 return -ENOMEM;
1704 }
1705
1706 runtime->private_data = NULL;
1707 prtd->cstream = cstream;
1708 pdata->cstream[rtd->dai_link->id] = cstream;
1709 pdata->audio_effects[rtd->dai_link->id] =
1710 kzalloc(sizeof(struct msm_compr_audio_effects), GFP_KERNEL);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301711 if (pdata->audio_effects[rtd->dai_link->id] == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301712 pr_err("%s: Could not allocate memory for effects\n", __func__);
1713 pdata->cstream[rtd->dai_link->id] = NULL;
1714 kfree(prtd);
1715 return -ENOMEM;
1716 }
1717 pdata->dec_params[rtd->dai_link->id] =
1718 kzalloc(sizeof(struct msm_compr_dec_params), GFP_KERNEL);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301719 if (pdata->dec_params[rtd->dai_link->id] == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301720 pr_err("%s: Could not allocate memory for dec params\n",
1721 __func__);
1722 kfree(pdata->audio_effects[rtd->dai_link->id]);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301723 pdata->audio_effects[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301724 pdata->cstream[rtd->dai_link->id] = NULL;
1725 kfree(prtd);
1726 return -ENOMEM;
1727 }
1728 prtd->codec = FORMAT_MP3;
1729 prtd->bytes_received = 0;
1730 prtd->bytes_sent = 0;
1731 prtd->copied_total = 0;
1732 prtd->byte_offset = 0;
1733 prtd->sample_rate = 44100;
1734 prtd->num_channels = 2;
1735 prtd->drain_ready = 0;
1736 prtd->last_buffer = 0;
1737 prtd->first_buffer = 1;
1738 prtd->partial_drain_delay = 0;
1739 prtd->next_stream = 0;
1740 memset(&prtd->gapless_state, 0, sizeof(struct msm_compr_gapless_state));
1741 /*
1742 * Update the use_dsp_gapless_mode from gapless struture with the value
1743 * part of platform data.
1744 */
1745 prtd->gapless_state.use_dsp_gapless_mode = pdata->use_dsp_gapless_mode;
1746
1747 pr_debug("%s: gapless mode %d", __func__, pdata->use_dsp_gapless_mode);
1748
1749 spin_lock_init(&prtd->lock);
1750
1751 atomic_set(&prtd->eos, 0);
1752 atomic_set(&prtd->start, 0);
1753 atomic_set(&prtd->drain, 0);
1754 atomic_set(&prtd->xrun, 0);
1755 atomic_set(&prtd->close, 0);
1756 atomic_set(&prtd->wait_on_close, 0);
1757 atomic_set(&prtd->error, 0);
1758
1759 init_waitqueue_head(&prtd->eos_wait);
1760 init_waitqueue_head(&prtd->drain_wait);
1761 init_waitqueue_head(&prtd->close_wait);
1762 init_waitqueue_head(&prtd->wait_for_stream_avail);
1763
1764 runtime->private_data = prtd;
1765 populate_codec_list(prtd);
1766 prtd->audio_client = q6asm_audio_client_alloc(
1767 (app_cb)compr_event_handler, prtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301768 if (prtd->audio_client == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301769 pr_err("%s: Could not allocate memory for client\n", __func__);
1770 kfree(pdata->audio_effects[rtd->dai_link->id]);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301771 pdata->audio_effects[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301772 kfree(pdata->dec_params[rtd->dai_link->id]);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301773 pdata->dec_params[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301774 pdata->cstream[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301775 kfree(prtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301776 runtime->private_data = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301777 return -ENOMEM;
1778 }
1779 pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
1780 prtd->audio_client->perf_mode = false;
1781 prtd->session_id = prtd->audio_client->session;
1782 msm_adsp_init_mixer_ctl_pp_event_queue(rtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301783 pdata->is_in_use[rtd->dai_link->id] = true;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301784 return 0;
1785}
1786
1787static int msm_compr_capture_open(struct snd_compr_stream *cstream)
1788{
1789 struct snd_compr_runtime *runtime = cstream->runtime;
1790 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Meng Wangee084a02018-09-04 16:11:58 +08001791 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301792 struct msm_compr_audio *prtd;
Meng Wangee084a02018-09-04 16:11:58 +08001793 struct msm_compr_pdata *pdata = NULL;
Ramprasad Katkam17f05162019-04-15 18:37:10 +05301794 enum apr_subsys_state subsys_state;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301795
1796 pr_debug("%s\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08001797 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
1798 if (!component) {
1799 pr_err("%s: component is NULL\n", __func__);
1800 return -EINVAL;
1801 }
1802 pdata = snd_soc_component_get_drvdata(component);
1803 if (!pdata) {
1804 pr_err("%s: pdata is NULL\n", __func__);
1805 return -EINVAL;
1806 }
Ramprasad Katkam17f05162019-04-15 18:37:10 +05301807
1808 subsys_state = apr_get_subsys_state();
1809 if (subsys_state == APR_SUBSYS_DOWN) {
1810 pr_debug("%s: adsp is down\n", __func__);
1811 return -ENETRESET;
1812 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301813 prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08001814 if (!prtd) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301815 pr_err("Failed to allocate memory for msm_compr_audio\n");
1816 return -ENOMEM;
1817 }
1818
1819 runtime->private_data = NULL;
1820 prtd->cstream = cstream;
1821 pdata->cstream[rtd->dai_link->id] = cstream;
1822
1823 prtd->audio_client = q6asm_audio_client_alloc(
1824 (app_cb)compr_event_handler, prtd);
1825 if (!prtd->audio_client) {
1826 pr_err("%s: Could not allocate memory for client\n", __func__);
1827 pdata->cstream[rtd->dai_link->id] = NULL;
1828 kfree(prtd);
1829 return -ENOMEM;
1830 }
1831 pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
1832 prtd->audio_client->perf_mode = false;
1833 prtd->session_id = prtd->audio_client->session;
1834 prtd->codec = FORMAT_LINEAR_PCM;
1835 prtd->bytes_copied = 0;
1836 prtd->bytes_read = 0;
1837 prtd->bytes_read_offset = 0;
1838 prtd->received_total = 0;
1839 prtd->byte_offset = 0;
1840 prtd->sample_rate = 48000;
1841 prtd->num_channels = 2;
1842 prtd->first_buffer = 0;
1843
1844 spin_lock_init(&prtd->lock);
1845
1846 atomic_set(&prtd->eos, 0);
1847 atomic_set(&prtd->start, 0);
1848 atomic_set(&prtd->drain, 0);
1849 atomic_set(&prtd->xrun, 0);
1850 atomic_set(&prtd->close, 0);
1851 atomic_set(&prtd->wait_on_close, 0);
1852 atomic_set(&prtd->error, 0);
1853
Xiaojun Sangd57aca02019-03-06 17:03:08 +08001854 init_waitqueue_head(&prtd->eos_wait);
1855 init_waitqueue_head(&prtd->drain_wait);
1856 init_waitqueue_head(&prtd->close_wait);
1857 init_waitqueue_head(&prtd->wait_for_stream_avail);
1858
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301859 runtime->private_data = prtd;
1860
1861 return 0;
1862}
1863
1864static int msm_compr_open(struct snd_compr_stream *cstream)
1865{
1866 int ret = 0;
1867
1868 if (cstream->direction == SND_COMPRESS_PLAYBACK)
1869 ret = msm_compr_playback_open(cstream);
1870 else if (cstream->direction == SND_COMPRESS_CAPTURE)
1871 ret = msm_compr_capture_open(cstream);
1872 return ret;
1873}
1874
1875static int msm_compr_playback_free(struct snd_compr_stream *cstream)
1876{
1877 struct snd_compr_runtime *runtime;
1878 struct msm_compr_audio *prtd;
1879 struct snd_soc_pcm_runtime *soc_prtd;
Meng Wangee084a02018-09-04 16:11:58 +08001880 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301881 struct msm_compr_pdata *pdata;
1882 struct audio_client *ac;
1883 int dir = IN, ret = 0, stream_id;
1884 unsigned long flags;
1885 uint32_t stream_index;
1886
1887 pr_debug("%s\n", __func__);
1888
1889 if (!cstream) {
1890 pr_err("%s cstream is null\n", __func__);
1891 return 0;
1892 }
1893 runtime = cstream->runtime;
1894 soc_prtd = cstream->private_data;
Meng Wang8a2a1042019-03-21 10:14:50 +08001895 if (!runtime || !soc_prtd) {
1896 pr_err("%s runtime or soc_prtd is null\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301897 __func__);
1898 return 0;
1899 }
Meng Wang8a2a1042019-03-21 10:14:50 +08001900 component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
1901 if (!component) {
1902 pr_err("%s component is null\n", __func__);
1903 return 0;
1904 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301905 prtd = runtime->private_data;
1906 if (!prtd) {
1907 pr_err("%s prtd is null\n", __func__);
1908 return 0;
1909 }
1910 prtd->cmd_interrupt = 1;
1911 wake_up(&prtd->drain_wait);
Meng Wangee084a02018-09-04 16:11:58 +08001912 pdata = snd_soc_component_get_drvdata(component);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301913 ac = prtd->audio_client;
1914 if (!pdata || !ac) {
1915 pr_err("%s pdata or ac is null\n", __func__);
1916 return 0;
1917 }
1918 if (atomic_read(&prtd->eos)) {
1919 ret = wait_event_timeout(prtd->eos_wait,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001920 prtd->eos_ack,
1921 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301922 if (!ret)
1923 pr_err("%s: CMD_EOS failed\n", __func__);
1924 }
1925 if (atomic_read(&prtd->close)) {
1926 prtd->cmd_ack = 0;
1927 atomic_set(&prtd->wait_on_close, 1);
1928 ret = wait_event_timeout(prtd->close_wait,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001929 prtd->cmd_ack,
1930 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301931 if (!ret)
1932 pr_err("%s: CMD_CLOSE failed\n", __func__);
1933 }
1934
1935 spin_lock_irqsave(&prtd->lock, flags);
1936 stream_id = ac->stream_id;
1937 stream_index = STREAM_ARRAY_INDEX(NEXT_STREAM_ID(stream_id));
1938
1939 if ((stream_index < MAX_NUMBER_OF_STREAMS && stream_index >= 0) &&
1940 (prtd->gapless_state.stream_opened[stream_index])) {
1941 prtd->gapless_state.stream_opened[stream_index] = 0;
1942 spin_unlock_irqrestore(&prtd->lock, flags);
1943 pr_debug(" close stream %d", NEXT_STREAM_ID(stream_id));
1944 q6asm_stream_cmd(ac, CMD_CLOSE, NEXT_STREAM_ID(stream_id));
1945 spin_lock_irqsave(&prtd->lock, flags);
1946 }
1947
1948 stream_index = STREAM_ARRAY_INDEX(stream_id);
1949 if ((stream_index < MAX_NUMBER_OF_STREAMS && stream_index >= 0) &&
1950 (prtd->gapless_state.stream_opened[stream_index])) {
1951 prtd->gapless_state.stream_opened[stream_index] = 0;
1952 spin_unlock_irqrestore(&prtd->lock, flags);
1953 pr_debug("close stream %d", stream_id);
1954 q6asm_stream_cmd(ac, CMD_CLOSE, stream_id);
1955 spin_lock_irqsave(&prtd->lock, flags);
1956 }
1957 spin_unlock_irqrestore(&prtd->lock, flags);
1958
Ajit Pandeyfa018862019-09-04 14:34:00 +05301959 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301960 pdata->cstream[soc_prtd->dai_link->id] = NULL;
1961 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
1962 msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
1963 SNDRV_PCM_STREAM_PLAYBACK);
1964 }
1965
1966 q6asm_audio_client_buf_free_contiguous(dir, ac);
1967
1968 q6asm_audio_client_free(ac);
1969 msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301970 if (pdata->audio_effects[soc_prtd->dai_link->id] != NULL) {
1971 kfree(pdata->audio_effects[soc_prtd->dai_link->id]);
1972 pdata->audio_effects[soc_prtd->dai_link->id] = NULL;
1973 }
1974 if (pdata->dec_params[soc_prtd->dai_link->id] != NULL) {
1975 kfree(pdata->dec_params[soc_prtd->dai_link->id]);
1976 pdata->dec_params[soc_prtd->dai_link->id] = NULL;
1977 }
Preetam Singh Ranawat1ac295b2020-04-22 16:57:02 +05301978 if (pdata->ch_map[soc_prtd->dai_link->id]) {
1979 pdata->ch_map[soc_prtd->dai_link->id]->set_ch_map = false;
1980 }
Aditya Bavanari9deef912017-11-20 13:31:31 +05301981 pdata->is_in_use[soc_prtd->dai_link->id] = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301982 kfree(prtd);
1983 runtime->private_data = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05301984 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301985
1986 return 0;
1987}
1988
1989static int msm_compr_capture_free(struct snd_compr_stream *cstream)
1990{
1991 struct snd_compr_runtime *runtime;
1992 struct msm_compr_audio *prtd;
1993 struct snd_soc_pcm_runtime *soc_prtd;
Meng Wangee084a02018-09-04 16:11:58 +08001994 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301995 struct msm_compr_pdata *pdata;
1996 struct audio_client *ac;
1997 int dir = OUT, stream_id;
1998 unsigned long flags;
1999 uint32_t stream_index;
2000
2001 if (!cstream) {
2002 pr_err("%s cstream is null\n", __func__);
2003 return 0;
2004 }
2005 runtime = cstream->runtime;
2006 soc_prtd = cstream->private_data;
Meng Wang8a2a1042019-03-21 10:14:50 +08002007 if (!runtime || !soc_prtd) {
2008 pr_err("%s runtime or soc_prtd is null\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302009 return 0;
2010 }
Meng Wang8a2a1042019-03-21 10:14:50 +08002011 component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
2012 if (!component) {
2013 pr_err("%s component is null\n", __func__);
2014 return 0;
2015 }
2016
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302017 prtd = runtime->private_data;
2018 if (!prtd) {
2019 pr_err("%s prtd is null\n", __func__);
2020 return 0;
2021 }
Meng Wangee084a02018-09-04 16:11:58 +08002022 pdata = snd_soc_component_get_drvdata(component);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302023 ac = prtd->audio_client;
2024 if (!pdata || !ac) {
2025 pr_err("%s pdata or ac is null\n", __func__);
2026 return 0;
2027 }
2028
2029 spin_lock_irqsave(&prtd->lock, flags);
2030 stream_id = ac->stream_id;
2031
2032 stream_index = STREAM_ARRAY_INDEX(stream_id);
2033 if ((stream_index < MAX_NUMBER_OF_STREAMS && stream_index >= 0)) {
2034 spin_unlock_irqrestore(&prtd->lock, flags);
2035 pr_debug("close stream %d", stream_id);
2036 q6asm_stream_cmd(ac, CMD_CLOSE, stream_id);
2037 spin_lock_irqsave(&prtd->lock, flags);
2038 }
2039 spin_unlock_irqrestore(&prtd->lock, flags);
2040
Ajit Pandeyfa018862019-09-04 14:34:00 +05302041 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302042 pdata->cstream[soc_prtd->dai_link->id] = NULL;
2043 msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
2044 SNDRV_PCM_STREAM_CAPTURE);
2045
2046 q6asm_audio_client_buf_free_contiguous(dir, ac);
2047
2048 q6asm_audio_client_free(ac);
2049
2050 kfree(prtd);
2051 runtime->private_data = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05302052 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302053
2054 return 0;
2055}
2056
2057static int msm_compr_free(struct snd_compr_stream *cstream)
2058{
2059 int ret = 0;
2060
2061 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2062 ret = msm_compr_playback_free(cstream);
2063 else if (cstream->direction == SND_COMPRESS_CAPTURE)
2064 ret = msm_compr_capture_free(cstream);
2065 return ret;
2066}
2067
2068static bool msm_compr_validate_codec_compr(__u32 codec_id)
2069{
2070 int32_t i;
2071
2072 for (i = 0; i < ARRAY_SIZE(compr_codecs); i++) {
2073 if (compr_codecs[i] == codec_id)
2074 return true;
2075 }
2076 return false;
2077}
2078
2079/* compress stream operations */
2080static int msm_compr_set_params(struct snd_compr_stream *cstream,
2081 struct snd_compr_params *params)
2082{
2083 struct snd_compr_runtime *runtime = cstream->runtime;
2084 struct msm_compr_audio *prtd = runtime->private_data;
2085 int ret = 0, frame_sz = 0;
2086 int i, num_rates;
2087 bool is_format_gapless = false;
2088
2089 pr_debug("%s\n", __func__);
2090
2091 num_rates = sizeof(supported_sample_rates)/sizeof(unsigned int);
2092 for (i = 0; i < num_rates; i++)
2093 if (params->codec.sample_rate == supported_sample_rates[i])
2094 break;
2095 if (i == num_rates)
2096 return -EINVAL;
2097
2098 memcpy(&prtd->codec_param, params, sizeof(struct snd_compr_params));
2099 /* ToDo: remove duplicates */
2100 prtd->num_channels = prtd->codec_param.codec.ch_in;
2101 prtd->sample_rate = prtd->codec_param.codec.sample_rate;
2102 pr_debug("%s: sample_rate %d\n", __func__, prtd->sample_rate);
2103
2104 if ((prtd->codec_param.codec.compr_passthr >= LEGACY_PCM &&
2105 prtd->codec_param.
2106 codec.compr_passthr <= COMPRESSED_PASSTHROUGH_DSD) ||
2107 (prtd->codec_param.
2108 codec.compr_passthr == COMPRESSED_PASSTHROUGH_IEC61937))
2109 prtd->compr_passthr = prtd->codec_param.codec.compr_passthr;
2110 else
2111 prtd->compr_passthr = LEGACY_PCM;
2112 pr_debug("%s: compr_passthr = %d", __func__, prtd->compr_passthr);
2113 if (prtd->compr_passthr != LEGACY_PCM) {
2114 pr_debug("%s: Reset gapless mode playback for compr_type[%d]\n",
2115 __func__, prtd->compr_passthr);
2116 prtd->gapless_state.use_dsp_gapless_mode = 0;
2117 if (!msm_compr_validate_codec_compr(params->codec.id)) {
2118 pr_err("%s codec not supported in passthrough,id =%d\n",
2119 __func__, params->codec.id);
2120 return -EINVAL;
2121 }
2122 }
2123
Deeraj Soman9d125872019-02-05 16:19:56 +05302124 if (params->codec.flags & COMPRESSED_PERF_MODE_FLAG) {
2125 pr_debug("%s: setting perf mode = %d", __func__, LOW_LATENCY_PCM_MODE);
2126 prtd->audio_client->perf_mode = LOW_LATENCY_PCM_MODE;
2127 }
2128
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302129 switch (params->codec.id) {
2130 case SND_AUDIOCODEC_PCM: {
2131 pr_debug("SND_AUDIOCODEC_PCM\n");
2132 prtd->codec = FORMAT_LINEAR_PCM;
2133 is_format_gapless = true;
2134 break;
2135 }
2136
2137 case SND_AUDIOCODEC_MP3: {
2138 pr_debug("SND_AUDIOCODEC_MP3\n");
2139 prtd->codec = FORMAT_MP3;
2140 frame_sz = MP3_OUTPUT_FRAME_SZ;
2141 is_format_gapless = true;
2142 break;
2143 }
2144
2145 case SND_AUDIOCODEC_AAC: {
2146 pr_debug("SND_AUDIOCODEC_AAC\n");
2147 prtd->codec = FORMAT_MPEG4_AAC;
2148 frame_sz = AAC_OUTPUT_FRAME_SZ;
2149 is_format_gapless = true;
2150 break;
2151 }
2152
2153 case SND_AUDIOCODEC_AC3: {
2154 pr_debug("SND_AUDIOCODEC_AC3\n");
2155 prtd->codec = FORMAT_AC3;
2156 frame_sz = AC3_OUTPUT_FRAME_SZ;
2157 is_format_gapless = true;
2158 break;
2159 }
2160
2161 case SND_AUDIOCODEC_EAC3: {
2162 pr_debug("SND_AUDIOCODEC_EAC3\n");
2163 prtd->codec = FORMAT_EAC3;
2164 frame_sz = EAC3_OUTPUT_FRAME_SZ;
2165 is_format_gapless = true;
2166 break;
2167 }
2168
2169 case SND_AUDIOCODEC_MP2: {
2170 pr_debug("SND_AUDIOCODEC_MP2\n");
2171 prtd->codec = FORMAT_MP2;
2172 break;
2173 }
2174
2175 case SND_AUDIOCODEC_WMA: {
2176 pr_debug("SND_AUDIOCODEC_WMA\n");
2177 prtd->codec = FORMAT_WMA_V9;
2178 break;
2179 }
2180
2181 case SND_AUDIOCODEC_WMA_PRO: {
2182 pr_debug("SND_AUDIOCODEC_WMA_PRO\n");
2183 prtd->codec = FORMAT_WMA_V10PRO;
2184 break;
2185 }
2186
2187 case SND_AUDIOCODEC_FLAC: {
2188 pr_debug("%s: SND_AUDIOCODEC_FLAC\n", __func__);
2189 prtd->codec = FORMAT_FLAC;
2190 /*
2191 * DSP bufferring is based on blk size,
2192 * consider mininum buffering to rule out any false wait
2193 */
2194 frame_sz =
2195 prtd->codec_param.codec.options.flac_dec.min_blk_size;
2196 is_format_gapless = true;
2197 break;
2198 }
2199
2200 case SND_AUDIOCODEC_VORBIS: {
2201 pr_debug("%s: SND_AUDIOCODEC_VORBIS\n", __func__);
2202 prtd->codec = FORMAT_VORBIS;
2203 break;
2204 }
2205
2206 case SND_AUDIOCODEC_ALAC: {
2207 pr_debug("%s: SND_AUDIOCODEC_ALAC\n", __func__);
2208 prtd->codec = FORMAT_ALAC;
2209 break;
2210 }
2211
2212 case SND_AUDIOCODEC_APE: {
2213 pr_debug("%s: SND_AUDIOCODEC_APE\n", __func__);
2214 prtd->codec = FORMAT_APE;
2215 break;
2216 }
2217
2218 case SND_AUDIOCODEC_DTS: {
2219 pr_debug("%s: SND_AUDIOCODEC_DTS\n", __func__);
2220 prtd->codec = FORMAT_DTS;
2221 break;
2222 }
2223
2224 case SND_AUDIOCODEC_DSD: {
2225 pr_debug("%s: SND_AUDIOCODEC_DSD\n", __func__);
2226 prtd->codec = FORMAT_DSD;
2227 break;
2228 }
2229
2230 case SND_AUDIOCODEC_TRUEHD: {
2231 pr_debug("%s: SND_AUDIOCODEC_TRUEHD\n", __func__);
2232 prtd->codec = FORMAT_TRUEHD;
2233 break;
2234 }
2235
2236 case SND_AUDIOCODEC_IEC61937: {
2237 pr_debug("%s: SND_AUDIOCODEC_IEC61937\n", __func__);
2238 prtd->codec = FORMAT_IEC61937;
2239 break;
2240 }
2241
2242 case SND_AUDIOCODEC_APTX: {
2243 pr_debug("%s: SND_AUDIOCODEC_APTX\n", __func__);
2244 prtd->codec = FORMAT_APTX;
2245 break;
2246 }
2247
Vikram Pandurangac712c172017-11-17 17:36:49 -08002248 case SND_AUDIOCODEC_BESPOKE: {
2249 pr_debug("%s: SND_AUDIOCODEC_BESPOKE\n", __func__);
2250 prtd->codec = FORMAT_BESPOKE;
2251 break;
2252 }
2253
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +05302254 case SND_AUDIOCODEC_AMR: {
2255 pr_debug("%s:SND_AUDIOCODEC_AMR\n", __func__);
2256 prtd->codec = FORMAT_AMRNB;
2257 break;
2258 }
2259
2260 case SND_AUDIOCODEC_AMRWB: {
2261 pr_debug("%s:SND_AUDIOCODEC_AMRWB\n", __func__);
2262 prtd->codec = FORMAT_AMRWB;
2263 break;
2264 }
2265
2266 case SND_AUDIOCODEC_AMRWBPLUS: {
2267 pr_debug("%s:SND_AUDIOCODEC_AMRWBPLUS\n", __func__);
2268 prtd->codec = FORMAT_AMR_WB_PLUS;
2269 break;
2270 }
2271
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302272 default:
2273 pr_err("codec not supported, id =%d\n", params->codec.id);
2274 return -EINVAL;
2275 }
2276
2277 if (!is_format_gapless)
2278 prtd->gapless_state.use_dsp_gapless_mode = false;
2279
2280 prtd->partial_drain_delay =
2281 msm_compr_get_partial_drain_delay(frame_sz, prtd->sample_rate);
2282
2283 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2284 ret = msm_compr_configure_dsp_for_playback(cstream);
2285 else if (cstream->direction == SND_COMPRESS_CAPTURE)
2286 ret = msm_compr_configure_dsp_for_capture(cstream);
2287
2288 return ret;
2289}
2290
2291static int msm_compr_drain_buffer(struct msm_compr_audio *prtd,
2292 unsigned long *flags)
2293{
2294 int rc = 0;
2295
2296 atomic_set(&prtd->drain, 1);
2297 prtd->drain_ready = 0;
2298 spin_unlock_irqrestore(&prtd->lock, *flags);
2299 pr_debug("%s: wait for buffer to be drained\n", __func__);
2300 rc = wait_event_interruptible(prtd->drain_wait,
2301 prtd->drain_ready ||
2302 prtd->cmd_interrupt ||
2303 atomic_read(&prtd->xrun) ||
2304 atomic_read(&prtd->error));
2305 pr_debug("%s: out of buffer drain wait with ret %d\n", __func__, rc);
2306 spin_lock_irqsave(&prtd->lock, *flags);
2307 if (prtd->cmd_interrupt) {
2308 pr_debug("%s: buffer drain interrupted by flush)\n", __func__);
2309 rc = -EINTR;
2310 prtd->cmd_interrupt = 0;
2311 }
2312 if (atomic_read(&prtd->error)) {
2313 pr_err("%s: Got RESET EVENTS notification, return\n",
2314 __func__);
2315 rc = -ENETRESET;
2316 }
2317 return rc;
2318}
2319
2320static int msm_compr_wait_for_stream_avail(struct msm_compr_audio *prtd,
2321 unsigned long *flags)
2322{
2323 int rc = 0;
2324
2325 pr_debug("next session is already in opened state\n");
2326 prtd->next_stream = 1;
2327 prtd->cmd_interrupt = 0;
2328 spin_unlock_irqrestore(&prtd->lock, *flags);
2329 /*
2330 * Wait for stream to be available, or the wait to be interrupted by
2331 * commands like flush or till a timeout of one second.
2332 */
2333 rc = wait_event_timeout(prtd->wait_for_stream_avail,
2334 prtd->stream_available || prtd->cmd_interrupt, 1 * HZ);
2335 pr_err("%s:prtd->stream_available %d, prtd->cmd_interrupt %d rc %d\n",
2336 __func__, prtd->stream_available, prtd->cmd_interrupt, rc);
2337
2338 spin_lock_irqsave(&prtd->lock, *flags);
2339 if (rc == 0) {
2340 pr_err("%s: wait_for_stream_avail timed out\n",
2341 __func__);
2342 rc = -ETIMEDOUT;
2343 } else if (prtd->cmd_interrupt == 1) {
2344 /*
2345 * This scenario might not happen as we do not allow
2346 * flush in transition state.
2347 */
2348 pr_debug("%s: wait_for_stream_avail interrupted\n", __func__);
2349 prtd->cmd_interrupt = 0;
2350 prtd->stream_available = 0;
2351 rc = -EINTR;
2352 } else {
2353 prtd->stream_available = 0;
2354 rc = 0;
2355 }
2356 pr_debug("%s : rc = %d", __func__, rc);
2357 return rc;
2358}
2359
2360static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
2361{
2362 struct snd_compr_runtime *runtime = cstream->runtime;
2363 struct msm_compr_audio *prtd = runtime->private_data;
2364 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Meng Wangee084a02018-09-04 16:11:58 +08002365 struct snd_soc_component *component = NULL;
2366 struct msm_compr_pdata *pdata = NULL;
2367 uint32_t *volume = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302368 struct audio_client *ac = prtd->audio_client;
2369 unsigned long fe_id = rtd->dai_link->id;
2370 int rc = 0;
2371 int bytes_to_write;
2372 unsigned long flags;
2373 int stream_id;
2374 uint32_t stream_index;
2375 uint16_t bits_per_sample = 16;
2376
Meng Wangee084a02018-09-04 16:11:58 +08002377 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
2378 if (!component) {
2379 pr_err("%s: component is NULL\n", __func__);
2380 return -EINVAL;
2381 }
2382 pdata = snd_soc_component_get_drvdata(component);
2383 if (!pdata) {
2384 pr_err("%s: pdata is NULL\n", __func__);
2385 return -EINVAL;
2386 }
2387 volume = pdata->volume[rtd->dai_link->id];
2388
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302389 spin_lock_irqsave(&prtd->lock, flags);
2390 if (atomic_read(&prtd->error)) {
2391 pr_err("%s Got RESET EVENTS notification, return immediately",
2392 __func__);
2393 spin_unlock_irqrestore(&prtd->lock, flags);
2394 return 0;
2395 }
2396 spin_unlock_irqrestore(&prtd->lock, flags);
2397
2398 switch (cmd) {
2399 case SNDRV_PCM_TRIGGER_START:
2400 pr_debug("%s: SNDRV_PCM_TRIGGER_START\n", __func__);
2401 atomic_set(&prtd->start, 1);
2402
2403 /*
2404 * compr_set_volume and compr_init_pp_params
2405 * are used to configure ASM volume hence not
2406 * needed for compress passthrough playback.
2407 *
2408 * compress passthrough volume is controlled in
2409 * ADM by adm_send_compressed_device_mute()
2410 */
2411 if (prtd->compr_passthr == LEGACY_PCM &&
2412 cstream->direction == SND_COMPRESS_PLAYBACK) {
2413 /* set volume for the stream before RUN */
2414 rc = msm_compr_set_volume(cstream,
2415 volume[0], volume[1]);
2416 if (rc)
2417 pr_err("%s : Set Volume failed : %d\n",
2418 __func__, rc);
2419
2420 rc = msm_compr_init_pp_params(cstream, ac);
2421 if (rc)
2422 pr_err("%s : init PP params failed : %d\n",
2423 __func__, rc);
2424 } else {
2425 msm_compr_read_buffer(prtd);
2426 }
2427 /* issue RUN command for the stream */
2428 q6asm_run_nowait(prtd->audio_client, prtd->run_mode,
2429 prtd->start_delay_msw, prtd->start_delay_lsw);
2430 break;
2431 case SNDRV_PCM_TRIGGER_STOP:
2432 spin_lock_irqsave(&prtd->lock, flags);
2433 pr_debug("%s: SNDRV_PCM_TRIGGER_STOP transition %d\n", __func__,
2434 prtd->gapless_state.gapless_transition);
2435 stream_id = ac->stream_id;
2436 atomic_set(&prtd->start, 0);
2437 if (cstream->direction == SND_COMPRESS_CAPTURE) {
2438 q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
2439 atomic_set(&prtd->xrun, 0);
2440 prtd->received_total = 0;
2441 prtd->bytes_copied = 0;
2442 prtd->bytes_read = 0;
2443 prtd->bytes_read_offset = 0;
2444 prtd->byte_offset = 0;
2445 prtd->app_pointer = 0;
2446 spin_unlock_irqrestore(&prtd->lock, flags);
2447 break;
2448 }
2449 if (prtd->next_stream) {
2450 pr_debug("%s: interrupt next track wait queues\n",
2451 __func__);
2452 prtd->cmd_interrupt = 1;
2453 wake_up(&prtd->wait_for_stream_avail);
2454 prtd->next_stream = 0;
2455 }
2456 if (atomic_read(&prtd->eos)) {
2457 pr_debug("%s: interrupt eos wait queues", __func__);
2458 /*
2459 * Gapless playback does not wait for eos, do not set
2460 * cmd_int and do not wake up eos_wait during gapless
2461 * transition
2462 */
2463 if (!prtd->gapless_state.gapless_transition) {
2464 prtd->cmd_interrupt = 1;
2465 wake_up(&prtd->eos_wait);
2466 }
2467 atomic_set(&prtd->eos, 0);
2468 }
2469 if (atomic_read(&prtd->drain)) {
2470 pr_debug("%s: interrupt drain wait queues", __func__);
2471 prtd->cmd_interrupt = 1;
2472 prtd->drain_ready = 1;
2473 wake_up(&prtd->drain_wait);
2474 atomic_set(&prtd->drain, 0);
2475 }
2476 prtd->last_buffer = 0;
2477 prtd->cmd_ack = 0;
2478 if (!prtd->gapless_state.gapless_transition) {
2479 pr_debug("issue CMD_FLUSH stream_id %d\n", stream_id);
2480 spin_unlock_irqrestore(&prtd->lock, flags);
2481 q6asm_stream_cmd(
2482 prtd->audio_client, CMD_FLUSH, stream_id);
2483 spin_lock_irqsave(&prtd->lock, flags);
2484 } else {
2485 prtd->first_buffer = 0;
2486 }
2487 /* FIXME. only reset if flush was successful */
2488 prtd->byte_offset = 0;
2489 prtd->copied_total = 0;
2490 prtd->app_pointer = 0;
2491 prtd->bytes_received = 0;
2492 prtd->bytes_sent = 0;
2493 prtd->marker_timestamp = 0;
2494
2495 atomic_set(&prtd->xrun, 0);
2496 spin_unlock_irqrestore(&prtd->lock, flags);
2497 break;
2498 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
2499 pr_debug("SNDRV_PCM_TRIGGER_PAUSE_PUSH transition %d\n",
2500 prtd->gapless_state.gapless_transition);
2501 if (!prtd->gapless_state.gapless_transition) {
2502 pr_debug("issue CMD_PAUSE stream_id %d\n",
2503 ac->stream_id);
2504 q6asm_stream_cmd_nowait(ac, CMD_PAUSE, ac->stream_id);
2505 atomic_set(&prtd->start, 0);
2506 }
2507 break;
2508 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
2509 pr_debug("SNDRV_PCM_TRIGGER_PAUSE_RELEASE transition %d\n",
2510 prtd->gapless_state.gapless_transition);
2511 if (!prtd->gapless_state.gapless_transition) {
2512 atomic_set(&prtd->start, 1);
2513 q6asm_run_nowait(prtd->audio_client, prtd->run_mode,
2514 0, 0);
2515 }
2516 break;
2517 case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
2518 pr_debug("%s: SND_COMPR_TRIGGER_PARTIAL_DRAIN\n", __func__);
2519 if (!prtd->gapless_state.use_dsp_gapless_mode) {
2520 pr_debug("%s: set partial drain as drain\n", __func__);
2521 cmd = SND_COMPR_TRIGGER_DRAIN;
2522 }
2523 case SND_COMPR_TRIGGER_DRAIN:
2524 pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__);
2525 /* Make sure all the data is sent to DSP before sending EOS */
2526 spin_lock_irqsave(&prtd->lock, flags);
2527
2528 if (!atomic_read(&prtd->start)) {
2529 pr_err("%s: stream is not in started state\n",
2530 __func__);
2531 rc = -EPERM;
2532 spin_unlock_irqrestore(&prtd->lock, flags);
2533 break;
2534 }
2535 if (prtd->bytes_received > prtd->copied_total) {
2536 pr_debug("%s: wait till all the data is sent to dsp\n",
2537 __func__);
2538 rc = msm_compr_drain_buffer(prtd, &flags);
2539 if (rc || !atomic_read(&prtd->start)) {
2540 if (rc != -ENETRESET)
2541 rc = -EINTR;
2542 spin_unlock_irqrestore(&prtd->lock, flags);
2543 break;
2544 }
2545 /*
2546 * FIXME: Bug.
2547 * Write(32767)
2548 * Start
2549 * Drain <- Indefinite wait
2550 * sol1 : if (prtd->copied_total) then wait?
2551 * sol2 : (prtd->cmd_interrupt || prtd->drain_ready ||
2552 * atomic_read(xrun)
2553 */
2554 bytes_to_write = prtd->bytes_received
2555 - prtd->copied_total;
2556 WARN(bytes_to_write > runtime->fragment_size,
2557 "last write %d cannot be > than fragment_size",
2558 bytes_to_write);
2559
2560 if (bytes_to_write > 0) {
2561 pr_debug("%s: send %d partial bytes at the end",
2562 __func__, bytes_to_write);
2563 atomic_set(&prtd->xrun, 0);
2564 prtd->last_buffer = 1;
2565 msm_compr_send_buffer(prtd);
2566 }
2567 }
2568
2569 if ((cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN) &&
2570 (prtd->gapless_state.set_next_stream_id)) {
2571 /* wait for the last buffer to be returned */
2572
2573 if (prtd->last_buffer) {
2574 pr_debug("%s: last buffer drain\n", __func__);
2575 rc = msm_compr_drain_buffer(prtd, &flags);
2576 if (rc || !atomic_read(&prtd->start)) {
2577 spin_unlock_irqrestore(&prtd->lock,
2578 flags);
2579 break;
2580 }
2581 }
2582 /* send EOS */
2583 prtd->eos_ack = 0;
2584 atomic_set(&prtd->eos, 1);
2585 pr_debug("issue CMD_EOS stream_id %d\n", ac->stream_id);
2586 q6asm_stream_cmd_nowait(ac, CMD_EOS, ac->stream_id);
2587 pr_info("PARTIAL DRAIN, do not wait for EOS ack\n");
2588
2589 /* send a zero length buffer */
2590 atomic_set(&prtd->xrun, 0);
2591 msm_compr_send_buffer(prtd);
2592
2593 /* wait for the zero length buffer to be returned */
2594 pr_debug("%s: zero length buffer drain\n", __func__);
2595 rc = msm_compr_drain_buffer(prtd, &flags);
2596 if (rc || !atomic_read(&prtd->start)) {
2597 spin_unlock_irqrestore(&prtd->lock, flags);
2598 break;
2599 }
2600
2601 /* sleep for additional duration partial drain */
2602 atomic_set(&prtd->drain, 1);
2603 prtd->drain_ready = 0;
2604 pr_debug("%s, additional sleep: %d\n", __func__,
2605 prtd->partial_drain_delay);
2606 spin_unlock_irqrestore(&prtd->lock, flags);
2607 rc = wait_event_timeout(prtd->drain_wait,
2608 prtd->drain_ready || prtd->cmd_interrupt,
2609 msecs_to_jiffies(prtd->partial_drain_delay));
2610 pr_debug("%s: out of additional wait for low sample rate\n",
2611 __func__);
2612 spin_lock_irqsave(&prtd->lock, flags);
2613 if (prtd->cmd_interrupt) {
2614 pr_debug("%s: additional wait interrupted by flush)\n",
2615 __func__);
2616 rc = -EINTR;
2617 prtd->cmd_interrupt = 0;
2618 spin_unlock_irqrestore(&prtd->lock, flags);
2619 break;
2620 }
2621
2622 /* move to next stream and reset vars */
2623 pr_debug("%s: Moving to next stream in gapless\n",
2624 __func__);
2625 ac->stream_id = NEXT_STREAM_ID(ac->stream_id);
2626 prtd->byte_offset = 0;
2627 prtd->app_pointer = 0;
2628 prtd->first_buffer = 1;
2629 prtd->last_buffer = 0;
2630 /*
2631 * Set gapless transition flag only if EOS hasn't been
2632 * acknowledged already.
2633 */
2634 if (atomic_read(&prtd->eos))
2635 prtd->gapless_state.gapless_transition = 1;
2636 prtd->marker_timestamp = 0;
2637
2638 /*
2639 * Don't reset these as these vars map to
2640 * total_bytes_transferred and total_bytes_available
2641 * directly, only total_bytes_transferred will be
2642 * updated in the next avail() ioctl
2643 * prtd->copied_total = 0;
2644 * prtd->bytes_received = 0;
2645 */
2646 atomic_set(&prtd->drain, 0);
2647 atomic_set(&prtd->xrun, 1);
2648 pr_debug("%s: issue CMD_RUN", __func__);
2649 q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
2650 spin_unlock_irqrestore(&prtd->lock, flags);
2651 break;
2652 }
2653 /*
2654 * moving to next stream failed, so reset the gapless state
2655 * set next stream id for the same session so that the same
2656 * stream can be used for gapless playback
2657 */
2658 prtd->gapless_state.set_next_stream_id = false;
2659 prtd->gapless_state.gapless_transition = 0;
2660 pr_debug("%s:CMD_EOS stream_id %d\n", __func__, ac->stream_id);
2661
2662 prtd->eos_ack = 0;
2663 atomic_set(&prtd->eos, 1);
2664 q6asm_stream_cmd_nowait(ac, CMD_EOS, ac->stream_id);
2665
2666 spin_unlock_irqrestore(&prtd->lock, flags);
2667
2668
2669 /* Wait indefinitely for DRAIN. Flush can also signal this*/
2670 rc = wait_event_interruptible(prtd->eos_wait,
2671 (prtd->eos_ack ||
2672 prtd->cmd_interrupt ||
2673 atomic_read(&prtd->error)));
2674
2675 if (rc < 0)
2676 pr_err("%s: EOS wait failed\n", __func__);
2677
2678 pr_debug("%s: SNDRV_COMPRESS_DRAIN out of wait for EOS\n",
2679 __func__);
2680
2681 if (prtd->cmd_interrupt)
2682 rc = -EINTR;
2683
2684 if (atomic_read(&prtd->error)) {
2685 pr_err("%s: Got RESET EVENTS notification, return\n",
2686 __func__);
2687 rc = -ENETRESET;
2688 }
2689
2690 /*FIXME : what if a flush comes while PC is here */
2691 if (rc == 0) {
2692 /*
2693 * Failed to open second stream in DSP for gapless
2694 * so prepare the current stream in session
2695 * for gapless playback
2696 */
2697 spin_lock_irqsave(&prtd->lock, flags);
2698 pr_debug("%s:issue CMD_PAUSE stream_id %d",
2699 __func__, ac->stream_id);
2700 q6asm_stream_cmd_nowait(ac, CMD_PAUSE, ac->stream_id);
2701 prtd->cmd_ack = 0;
2702 spin_unlock_irqrestore(&prtd->lock, flags);
2703
2704 /*
2705 * Cache this time as last known time
2706 */
2707 if (pdata->use_legacy_api)
2708 q6asm_get_session_time_legacy(
2709 prtd->audio_client,
2710 &prtd->marker_timestamp);
2711 else
2712 q6asm_get_session_time(prtd->audio_client,
2713 &prtd->marker_timestamp);
2714
2715 spin_lock_irqsave(&prtd->lock, flags);
2716 /*
2717 * Don't reset these as these vars map to
2718 * total_bytes_transferred and total_bytes_available.
2719 * Just total_bytes_transferred will be updated
2720 * in the next avail() ioctl.
2721 * prtd->copied_total = 0;
2722 * prtd->bytes_received = 0;
2723 * do not reset prtd->bytes_sent as well as the same
2724 * session is used for gapless playback
2725 */
2726 prtd->byte_offset = 0;
2727
2728 prtd->app_pointer = 0;
2729 prtd->first_buffer = 1;
2730 prtd->last_buffer = 0;
2731 atomic_set(&prtd->drain, 0);
2732 atomic_set(&prtd->xrun, 1);
2733 spin_unlock_irqrestore(&prtd->lock, flags);
2734
2735 pr_debug("%s:issue CMD_FLUSH ac->stream_id %d",
2736 __func__, ac->stream_id);
2737 q6asm_stream_cmd(ac, CMD_FLUSH, ac->stream_id);
2738
2739 q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
2740 }
2741 prtd->cmd_interrupt = 0;
2742 break;
2743 case SND_COMPR_TRIGGER_NEXT_TRACK:
2744 if (!prtd->gapless_state.use_dsp_gapless_mode) {
2745 pr_debug("%s: ignore trigger next track\n", __func__);
2746 rc = 0;
2747 break;
2748 }
2749 pr_debug("%s: SND_COMPR_TRIGGER_NEXT_TRACK\n", __func__);
2750 spin_lock_irqsave(&prtd->lock, flags);
2751 rc = 0;
2752 /* next stream in gapless */
2753 stream_id = NEXT_STREAM_ID(ac->stream_id);
2754 /*
2755 * Wait if stream 1 has not completed before honoring next
2756 * track for stream 3. Scenario happens if second clip is
2757 * small and fills in one buffer so next track will be
2758 * called immediately.
2759 */
2760 stream_index = STREAM_ARRAY_INDEX(stream_id);
2761 if (stream_index >= MAX_NUMBER_OF_STREAMS ||
2762 stream_index < 0) {
2763 pr_err("%s: Invalid stream index: %d", __func__,
2764 stream_index);
2765 spin_unlock_irqrestore(&prtd->lock, flags);
2766 rc = -EINVAL;
2767 break;
2768 }
2769
2770 if (prtd->gapless_state.stream_opened[stream_index]) {
2771 if (prtd->gapless_state.gapless_transition) {
2772 rc = msm_compr_wait_for_stream_avail(prtd,
2773 &flags);
2774 } else {
2775 /*
2776 * If session is already opened break out if
2777 * the state is not gapless transition. This
2778 * is when seek happens after the last buffer
2779 * is sent to the driver. Next track would be
2780 * called again after last buffer is sent.
2781 */
2782 pr_debug("next session is in opened state\n");
2783 spin_unlock_irqrestore(&prtd->lock, flags);
2784 break;
2785 }
2786 }
2787 spin_unlock_irqrestore(&prtd->lock, flags);
2788 if (rc < 0) {
2789 /*
2790 * if return type EINTR then reset to zero. Tiny
2791 * compress treats EINTR as error and prevents PARTIAL
2792 * DRAIN. EINTR is not an error. wait for stream avail
2793 * is interrupted by some other command like FLUSH.
2794 */
2795 if (rc == -EINTR) {
2796 pr_debug("%s: EINTR reset rc to 0\n", __func__);
2797 rc = 0;
2798 }
2799 break;
2800 }
2801
2802 if (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_LE)
2803 bits_per_sample = 24;
2804 else if (prtd->codec_param.codec.format ==
2805 SNDRV_PCM_FORMAT_S32_LE)
2806 bits_per_sample = 32;
2807
2808 pr_debug("%s: open_write stream_id %d bits_per_sample %d",
2809 __func__, stream_id, bits_per_sample);
Nidhisha Dhananjayand84669e2019-02-20 11:00:28 +05302810
2811 if (q6core_get_avcs_api_version_per_service(
2812 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
2813 ADSP_ASM_API_VERSION_V2)
2814 rc = q6asm_stream_open_write_v5(prtd->audio_client,
2815 prtd->codec, bits_per_sample,
2816 stream_id,
2817 prtd->gapless_state.use_dsp_gapless_mode);
2818 else
2819 rc = q6asm_stream_open_write_v4(prtd->audio_client,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302820 prtd->codec, bits_per_sample,
2821 stream_id,
2822 prtd->gapless_state.use_dsp_gapless_mode);
2823 if (rc < 0) {
Nidhisha Dhananjayand84669e2019-02-20 11:00:28 +05302824 pr_err("%s: Session out open failed for gapless [%d]\n",
2825 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302826 break;
2827 }
2828
2829 spin_lock_irqsave(&prtd->lock, flags);
2830 prtd->gapless_state.stream_opened[stream_index] = 1;
2831 prtd->gapless_state.set_next_stream_id = true;
2832 spin_unlock_irqrestore(&prtd->lock, flags);
2833
2834 rc = msm_compr_send_media_format_block(cstream,
2835 stream_id, false);
2836 if (rc < 0) {
2837 pr_err("%s, failed to send media format block\n",
2838 __func__);
2839 break;
2840 }
2841 msm_compr_send_dec_params(cstream, pdata->dec_params[fe_id],
2842 stream_id);
2843 break;
2844 }
2845
2846 return rc;
2847}
2848
2849static int msm_compr_pointer(struct snd_compr_stream *cstream,
2850 struct snd_compr_tstamp *arg)
2851{
2852 struct snd_compr_runtime *runtime = cstream->runtime;
2853 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
2854 struct msm_compr_audio *prtd = runtime->private_data;
Meng Wangee084a02018-09-04 16:11:58 +08002855 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302856 struct msm_compr_pdata *pdata = NULL;
2857 struct snd_compr_tstamp tstamp;
2858 uint64_t timestamp = 0;
2859 int rc = 0, first_buffer;
2860 unsigned long flags;
2861 uint32_t gapless_transition;
2862
Meng Wangee084a02018-09-04 16:11:58 +08002863 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
2864 if (!component) {
2865 pr_err("%s: component is NULL\n", __func__);
2866 return -EINVAL;
2867 }
2868 pdata = snd_soc_component_get_drvdata(component);
2869 if (!pdata) {
2870 pr_err("%s: pdata is NULL\n", __func__);
2871 return -EINVAL;
2872 }
2873
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302874 pr_debug("%s\n", __func__);
2875 memset(&tstamp, 0x0, sizeof(struct snd_compr_tstamp));
2876
2877 spin_lock_irqsave(&prtd->lock, flags);
2878 tstamp.sampling_rate = prtd->sample_rate;
2879 tstamp.byte_offset = prtd->byte_offset;
2880 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2881 tstamp.copied_total = prtd->copied_total;
2882 else if (cstream->direction == SND_COMPRESS_CAPTURE)
2883 tstamp.copied_total = prtd->received_total;
2884 first_buffer = prtd->first_buffer;
2885 if (atomic_read(&prtd->error)) {
Vatsal Bucha0527c562017-10-04 20:38:49 +05302886 pr_err_ratelimited("%s Got RESET EVENTS notification, return error\n",
2887 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302888 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2889 runtime->total_bytes_transferred = tstamp.copied_total;
2890 else
2891 runtime->total_bytes_available = tstamp.copied_total;
2892 tstamp.pcm_io_frames = 0;
2893 memcpy(arg, &tstamp, sizeof(struct snd_compr_tstamp));
2894 spin_unlock_irqrestore(&prtd->lock, flags);
2895 return -ENETRESET;
2896 }
2897 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
2898
2899 gapless_transition = prtd->gapless_state.gapless_transition;
2900 spin_unlock_irqrestore(&prtd->lock, flags);
2901 if (gapless_transition)
2902 pr_debug("%s session time in gapless transition",
2903 __func__);
2904 /*
2905 *- Do not query if no buffer has been given.
2906 *- Do not query on a gapless transition.
2907 * Playback for the 2nd stream can start (thus returning time
2908 * starting from 0) before the driver knows about EOS of first
2909 * stream.
2910 */
2911 if (!first_buffer || gapless_transition) {
2912
2913 if (pdata->use_legacy_api)
2914 rc = q6asm_get_session_time_legacy(
2915 prtd->audio_client, &prtd->marker_timestamp);
2916 else
2917 rc = q6asm_get_session_time(
2918 prtd->audio_client, &prtd->marker_timestamp);
2919 if (rc < 0) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302920 if (atomic_read(&prtd->error))
2921 return -ENETRESET;
2922 else
Xiaoyu Yef74e89b2018-01-08 18:09:29 -08002923 return rc;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302924 }
2925 }
2926 } else {
2927 spin_unlock_irqrestore(&prtd->lock, flags);
2928 }
2929 timestamp = prtd->marker_timestamp;
2930
2931 /* DSP returns timestamp in usec */
2932 pr_debug("%s: timestamp = %lld usec\n", __func__, timestamp);
2933 timestamp *= prtd->sample_rate;
2934 tstamp.pcm_io_frames = (snd_pcm_uframes_t)div64_u64(timestamp, 1000000);
2935 memcpy(arg, &tstamp, sizeof(struct snd_compr_tstamp));
2936
2937 return 0;
2938}
2939
2940static int msm_compr_ack(struct snd_compr_stream *cstream,
2941 size_t count)
2942{
2943 struct snd_compr_runtime *runtime = cstream->runtime;
2944 struct msm_compr_audio *prtd = runtime->private_data;
2945 void *src, *dstn;
2946 size_t copy;
2947 unsigned long flags;
2948
2949 WARN(1, "This path is untested");
2950 return -EINVAL;
2951
2952 pr_debug("%s: count = %zd\n", __func__, count);
2953 if (!prtd->buffer) {
2954 pr_err("%s: Buffer is not allocated yet ??\n", __func__);
2955 return -EINVAL;
2956 }
2957 src = runtime->buffer + prtd->app_pointer;
2958 dstn = prtd->buffer + prtd->app_pointer;
2959 if (count < prtd->buffer_size - prtd->app_pointer) {
2960 memcpy(dstn, src, count);
2961 prtd->app_pointer += count;
2962 } else {
2963 copy = prtd->buffer_size - prtd->app_pointer;
2964 memcpy(dstn, src, copy);
2965 memcpy(prtd->buffer, runtime->buffer, count - copy);
2966 prtd->app_pointer = count - copy;
2967 }
2968
2969 /*
2970 * If the stream is started and all the bytes received were
2971 * copied to DSP, the newly received bytes should be
2972 * sent right away
2973 */
2974 spin_lock_irqsave(&prtd->lock, flags);
2975
2976 if (atomic_read(&prtd->start) &&
2977 prtd->bytes_received == prtd->copied_total) {
2978 prtd->bytes_received += count;
2979 msm_compr_send_buffer(prtd);
2980 } else
2981 prtd->bytes_received += count;
2982
2983 spin_unlock_irqrestore(&prtd->lock, flags);
2984
2985 return 0;
2986}
2987
2988static int msm_compr_playback_copy(struct snd_compr_stream *cstream,
2989 char __user *buf, size_t count)
2990{
2991 struct snd_compr_runtime *runtime = cstream->runtime;
2992 struct msm_compr_audio *prtd = runtime->private_data;
2993 void *dstn;
2994 size_t copy;
2995 uint64_t bytes_available = 0;
2996 unsigned long flags;
2997
2998 pr_debug("%s: count = %zd\n", __func__, count);
2999 if (!prtd->buffer) {
3000 pr_err("%s: Buffer is not allocated yet ??", __func__);
3001 return 0;
3002 }
3003
3004 spin_lock_irqsave(&prtd->lock, flags);
3005 if (atomic_read(&prtd->error)) {
3006 pr_err("%s Got RESET EVENTS notification", __func__);
3007 spin_unlock_irqrestore(&prtd->lock, flags);
3008 return -ENETRESET;
3009 }
3010 spin_unlock_irqrestore(&prtd->lock, flags);
3011
3012 dstn = prtd->buffer + prtd->app_pointer;
3013 if (count < prtd->buffer_size - prtd->app_pointer) {
3014 if (copy_from_user(dstn, buf, count))
3015 return -EFAULT;
3016 prtd->app_pointer += count;
3017 } else {
3018 copy = prtd->buffer_size - prtd->app_pointer;
3019 if (copy_from_user(dstn, buf, copy))
3020 return -EFAULT;
3021 if (copy_from_user(prtd->buffer, buf + copy, count - copy))
3022 return -EFAULT;
3023 prtd->app_pointer = count - copy;
3024 }
3025
3026 /*
3027 * If stream is started and there has been an xrun,
3028 * since the available bytes fits fragment_size, copy the data
3029 * right away.
3030 */
3031 spin_lock_irqsave(&prtd->lock, flags);
3032 prtd->bytes_received += count;
3033 if (atomic_read(&prtd->start)) {
3034 if (atomic_read(&prtd->xrun)) {
3035 pr_debug("%s: in xrun, count = %zd\n", __func__, count);
3036 bytes_available = prtd->bytes_received -
3037 prtd->copied_total;
3038 if (bytes_available >= runtime->fragment_size) {
3039 pr_debug("%s: handle xrun, bytes_to_write = %llu\n",
3040 __func__, bytes_available);
3041 atomic_set(&prtd->xrun, 0);
3042 msm_compr_send_buffer(prtd);
3043 } /* else not sufficient data */
3044 } /* writes will continue on the next write_done */
3045 }
3046
3047 spin_unlock_irqrestore(&prtd->lock, flags);
3048
3049 return count;
3050}
3051
3052static int msm_compr_capture_copy(struct snd_compr_stream *cstream,
3053 char __user *buf, size_t count)
3054{
3055 struct snd_compr_runtime *runtime = cstream->runtime;
3056 struct msm_compr_audio *prtd = runtime->private_data;
3057 void *source;
3058 unsigned long flags;
3059
3060 pr_debug("%s: count = %zd\n", __func__, count);
3061 if (!prtd->buffer) {
3062 pr_err("%s: Buffer is not allocated yet ??", __func__);
3063 return 0;
3064 }
3065
3066 spin_lock_irqsave(&prtd->lock, flags);
3067 if (atomic_read(&prtd->error)) {
3068 pr_err("%s Got RESET EVENTS notification", __func__);
3069 spin_unlock_irqrestore(&prtd->lock, flags);
3070 return -ENETRESET;
3071 }
3072
3073 source = prtd->buffer + prtd->app_pointer;
3074 /* check if we have requested amount of data to copy to user*/
3075 if (count <= prtd->received_total - prtd->bytes_copied) {
3076 spin_unlock_irqrestore(&prtd->lock, flags);
3077 if (copy_to_user(buf, source, count)) {
3078 pr_err("copy_to_user failed");
3079 return -EFAULT;
3080 }
3081 spin_lock_irqsave(&prtd->lock, flags);
3082 prtd->app_pointer += count;
3083 if (prtd->app_pointer >= prtd->buffer_size)
3084 prtd->app_pointer -= prtd->buffer_size;
3085 prtd->bytes_copied += count;
3086 }
3087 msm_compr_read_buffer(prtd);
3088
3089 spin_unlock_irqrestore(&prtd->lock, flags);
3090 return count;
3091}
3092
3093static int msm_compr_copy(struct snd_compr_stream *cstream,
3094 char __user *buf, size_t count)
3095{
3096 int ret = 0;
3097
3098 pr_debug(" In %s\n", __func__);
3099 if (cstream->direction == SND_COMPRESS_PLAYBACK)
3100 ret = msm_compr_playback_copy(cstream, buf, count);
3101 else if (cstream->direction == SND_COMPRESS_CAPTURE)
3102 ret = msm_compr_capture_copy(cstream, buf, count);
3103 return ret;
3104}
3105
3106static int msm_compr_get_caps(struct snd_compr_stream *cstream,
3107 struct snd_compr_caps *arg)
3108{
3109 struct snd_compr_runtime *runtime = cstream->runtime;
3110 struct msm_compr_audio *prtd = runtime->private_data;
3111 int ret = 0;
3112
3113 pr_debug("%s\n", __func__);
3114 if ((arg != NULL) && (prtd != NULL)) {
3115 memcpy(arg, &prtd->compr_cap, sizeof(struct snd_compr_caps));
3116 } else {
3117 ret = -EINVAL;
3118 pr_err("%s: arg (0x%pK), prtd (0x%pK)\n", __func__, arg, prtd);
3119 }
3120
3121 return ret;
3122}
3123
3124static int msm_compr_get_codec_caps(struct snd_compr_stream *cstream,
3125 struct snd_compr_codec_caps *codec)
3126{
3127 pr_debug("%s\n", __func__);
3128
3129 switch (codec->codec) {
3130 case SND_AUDIOCODEC_MP3:
3131 codec->num_descriptors = 2;
3132 codec->descriptor[0].max_ch = 2;
3133 memcpy(codec->descriptor[0].sample_rates,
3134 supported_sample_rates,
3135 sizeof(supported_sample_rates));
3136 codec->descriptor[0].num_sample_rates =
3137 sizeof(supported_sample_rates)/sizeof(unsigned int);
3138 codec->descriptor[0].bit_rate[0] = 320; /* 320kbps */
3139 codec->descriptor[0].bit_rate[1] = 128;
3140 codec->descriptor[0].num_bitrates = 2;
3141 codec->descriptor[0].profiles = 0;
3142 codec->descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO;
3143 codec->descriptor[0].formats = 0;
3144 break;
3145 case SND_AUDIOCODEC_AAC:
3146 codec->num_descriptors = 2;
3147 codec->descriptor[1].max_ch = 2;
3148 memcpy(codec->descriptor[1].sample_rates,
3149 supported_sample_rates,
3150 sizeof(supported_sample_rates));
3151 codec->descriptor[1].num_sample_rates =
3152 sizeof(supported_sample_rates)/sizeof(unsigned int);
3153 codec->descriptor[1].bit_rate[0] = 320; /* 320kbps */
3154 codec->descriptor[1].bit_rate[1] = 128;
3155 codec->descriptor[1].num_bitrates = 2;
3156 codec->descriptor[1].profiles = 0;
3157 codec->descriptor[1].modes = 0;
3158 codec->descriptor[1].formats =
3159 (SND_AUDIOSTREAMFORMAT_MP4ADTS |
3160 SND_AUDIOSTREAMFORMAT_RAW);
3161 break;
3162 case SND_AUDIOCODEC_AC3:
3163 case SND_AUDIOCODEC_EAC3:
3164 case SND_AUDIOCODEC_FLAC:
3165 case SND_AUDIOCODEC_VORBIS:
3166 case SND_AUDIOCODEC_ALAC:
3167 case SND_AUDIOCODEC_APE:
3168 case SND_AUDIOCODEC_DTS:
3169 case SND_AUDIOCODEC_DSD:
3170 case SND_AUDIOCODEC_TRUEHD:
3171 case SND_AUDIOCODEC_IEC61937:
3172 case SND_AUDIOCODEC_APTX:
3173 break;
3174 default:
3175 pr_err("%s: Unsupported audio codec %d\n",
3176 __func__, codec->codec);
3177 return -EINVAL;
3178 }
3179
3180 return 0;
3181}
3182
3183static int msm_compr_set_metadata(struct snd_compr_stream *cstream,
3184 struct snd_compr_metadata *metadata)
3185{
3186 struct msm_compr_audio *prtd;
3187 struct audio_client *ac;
3188 pr_debug("%s\n", __func__);
3189
3190 if (!metadata || !cstream)
3191 return -EINVAL;
3192
3193 prtd = cstream->runtime->private_data;
3194 if (!prtd || !prtd->audio_client) {
3195 pr_err("%s: prtd or audio client is NULL\n", __func__);
3196 return -EINVAL;
3197 }
3198
3199 if (((metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) ||
3200 (metadata->key == SNDRV_COMPRESS_ENCODER_DELAY)) &&
3201 (prtd->compr_passthr != LEGACY_PCM)) {
3202 pr_debug("%s: No trailing silence for compress_type[%d]\n",
3203 __func__, prtd->compr_passthr);
3204 return 0;
3205 }
3206
3207 ac = prtd->audio_client;
3208 if (metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) {
3209 pr_debug("%s, got encoder padding %u",
3210 __func__, metadata->value[0]);
3211 prtd->gapless_state.trailing_samples_drop = metadata->value[0];
3212 } else if (metadata->key == SNDRV_COMPRESS_ENCODER_DELAY) {
3213 pr_debug("%s, got encoder delay %u",
3214 __func__, metadata->value[0]);
3215 prtd->gapless_state.initial_samples_drop = metadata->value[0];
3216 } else if (metadata->key == SNDRV_COMPRESS_RENDER_MODE) {
3217 return msm_compr_set_render_mode(prtd, metadata->value[0]);
3218 } else if (metadata->key == SNDRV_COMPRESS_CLK_REC_MODE) {
3219 return msm_compr_set_clk_rec_mode(ac, metadata->value[0]);
3220 } else if (metadata->key == SNDRV_COMPRESS_RENDER_WINDOW) {
3221 return msm_compr_set_render_window(
3222 ac,
3223 metadata->value[0],
3224 metadata->value[1],
3225 metadata->value[2],
3226 metadata->value[3]);
3227 } else if (metadata->key == SNDRV_COMPRESS_START_DELAY) {
3228 prtd->start_delay_lsw = metadata->value[0];
3229 prtd->start_delay_msw = metadata->value[1];
3230 } else if (metadata->key ==
3231 SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK) {
3232 return msm_compr_enable_adjust_session_clock(ac,
3233 metadata->value[0]);
3234 } else if (metadata->key == SNDRV_COMPRESS_ADJUST_SESSION_CLOCK) {
3235 return msm_compr_adjust_session_clock(ac,
3236 metadata->value[0],
3237 metadata->value[1]);
3238 }
3239
3240 return 0;
3241}
3242
3243static int msm_compr_get_metadata(struct snd_compr_stream *cstream,
3244 struct snd_compr_metadata *metadata)
3245{
3246 struct msm_compr_audio *prtd;
3247 struct audio_client *ac;
3248 int ret = -EINVAL;
Surendar Karka38d66472019-03-29 18:08:07 +05303249 uint64_t ses_time = 0, frames = 0, abs_time = 0;
3250 uint64_t *val = NULL;
3251 int64_t av_offset = 0;
3252 int32_t clock_id = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303253
3254 pr_debug("%s\n", __func__);
3255
3256 if (!metadata || !cstream || !cstream->runtime)
3257 return ret;
3258
Surendar Karka38d66472019-03-29 18:08:07 +05303259 if (metadata->key != SNDRV_COMPRESS_PATH_DELAY &&
3260 metadata->key != SNDRV_COMPRESS_DSP_POSITION) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303261 pr_err("%s, unsupported key %d\n", __func__, metadata->key);
3262 return ret;
3263 }
3264
3265 prtd = cstream->runtime->private_data;
3266 if (!prtd || !prtd->audio_client) {
3267 pr_err("%s: prtd or audio client is NULL\n", __func__);
3268 return ret;
3269 }
3270
Surendar Karka38d66472019-03-29 18:08:07 +05303271 switch (metadata->key) {
3272 case SNDRV_COMPRESS_PATH_DELAY:
3273 ac = prtd->audio_client;
3274 ret = q6asm_get_path_delay(prtd->audio_client);
3275 if (ret) {
3276 pr_err("%s: get_path_delay failed, ret=%d\n",
3277 __func__, ret);
3278 return ret;
3279 }
3280
3281 pr_debug("%s, path delay(in us) %u\n", __func__,
3282 ac->path_delay);
3283 metadata->value[0] = ac->path_delay;
3284 break;
3285 case SNDRV_COMPRESS_DSP_POSITION:
3286 clock_id = metadata->value[0];
3287 pr_debug("%s, clock_id %d\n", __func__, clock_id);
3288 ret = q6asm_get_session_time_v2(prtd->audio_client,
3289 &ses_time, &abs_time);
3290 if (ret) {
3291 pr_err("%s: q6asm_get_session_time_v2 failed, ret=%d\n",
3292 __func__, ret);
3293 return ret;
3294 }
3295 frames = div64_u64((ses_time * prtd->sample_rate), 1000000);
3296
3297 ret = avcs_core_query_timer_offset(&av_offset, clock_id);
3298 if (ret) {
3299 pr_err("%s: avcs query failed, ret=%d\n",
3300 __func__, ret);
3301 return ret;
3302 }
3303
3304 val = (uint64_t *) &metadata->value[1];
3305 val[0] = frames;
3306 val[1] = abs_time + av_offset;
3307 pr_debug("%s, vals frames %lld, time %lld, avoff %lld, abst %lld, sess_time %llu sr %d\n",
3308 __func__, val[0], val[1], av_offset, abs_time,
3309 ses_time, prtd->sample_rate);
3310 break;
3311 default:
3312 pr_err("%s, unsupported key %d\n", __func__, metadata->key);
3313 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303314 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303315 return ret;
3316}
3317
3318
3319static int msm_compr_set_next_track_param(struct snd_compr_stream *cstream,
3320 union snd_codec_options *codec_options)
3321{
3322 struct msm_compr_audio *prtd;
3323 struct audio_client *ac;
3324 int ret = 0;
3325
3326 if (!codec_options || !cstream)
3327 return -EINVAL;
3328
3329 prtd = cstream->runtime->private_data;
3330 if (!prtd || !prtd->audio_client) {
3331 pr_err("%s: prtd or audio client is NULL\n", __func__);
3332 return -EINVAL;
3333 }
3334
3335 ac = prtd->audio_client;
3336
3337 pr_debug("%s: got codec options for codec type %u",
3338 __func__, prtd->codec);
3339 switch (prtd->codec) {
3340 case FORMAT_WMA_V9:
3341 case FORMAT_WMA_V10PRO:
3342 case FORMAT_FLAC:
3343 case FORMAT_VORBIS:
3344 case FORMAT_ALAC:
3345 case FORMAT_APE:
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +05303346 case FORMAT_AMRNB:
3347 case FORMAT_AMRWB:
3348 case FORMAT_AMR_WB_PLUS:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303349 memcpy(&(prtd->gapless_state.codec_options),
3350 codec_options,
3351 sizeof(union snd_codec_options));
3352 ret = msm_compr_send_media_format_block(cstream,
3353 ac->stream_id, true);
3354 if (ret < 0) {
3355 pr_err("%s: failed to send media format block\n",
3356 __func__);
3357 }
3358 break;
3359
3360 default:
3361 pr_debug("%s: Ignore sending CMD Format block\n",
3362 __func__);
3363 break;
3364 }
3365
3366 return ret;
3367}
3368
3369static int msm_compr_volume_put(struct snd_kcontrol *kcontrol,
3370 struct snd_ctl_elem_value *ucontrol)
3371{
3372 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3373 unsigned long fe_id = kcontrol->private_value;
3374 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3375 snd_soc_component_get_drvdata(comp);
3376 struct snd_compr_stream *cstream = NULL;
3377 uint32_t *volume = NULL;
3378
3379 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3380 pr_err("%s Received out of bounds fe_id %lu\n",
3381 __func__, fe_id);
3382 return -EINVAL;
3383 }
3384
3385 cstream = pdata->cstream[fe_id];
3386 volume = pdata->volume[fe_id];
3387
3388 volume[0] = ucontrol->value.integer.value[0];
3389 volume[1] = ucontrol->value.integer.value[1];
3390 pr_debug("%s: fe_id %lu left_vol %d right_vol %d\n",
3391 __func__, fe_id, volume[0], volume[1]);
3392 if (cstream)
3393 msm_compr_set_volume(cstream, volume[0], volume[1]);
3394 return 0;
3395}
3396
3397static int msm_compr_volume_get(struct snd_kcontrol *kcontrol,
3398 struct snd_ctl_elem_value *ucontrol)
3399{
3400 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3401 unsigned long fe_id = kcontrol->private_value;
3402
3403 struct msm_compr_pdata *pdata =
3404 snd_soc_component_get_drvdata(comp);
3405 uint32_t *volume = NULL;
3406
3407 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3408 pr_err("%s Received out of bound fe_id %lu\n", __func__, fe_id);
3409 return -EINVAL;
3410 }
3411
3412 volume = pdata->volume[fe_id];
3413 pr_debug("%s: fe_id %lu\n", __func__, fe_id);
3414 ucontrol->value.integer.value[0] = volume[0];
3415 ucontrol->value.integer.value[1] = volume[1];
3416
3417 return 0;
3418}
3419
3420static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
3421 struct snd_ctl_elem_value *ucontrol)
3422{
3423 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3424 unsigned long fe_id = kcontrol->private_value;
3425 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3426 snd_soc_component_get_drvdata(comp);
3427 struct msm_compr_audio_effects *audio_effects = NULL;
3428 struct snd_compr_stream *cstream = NULL;
3429 struct msm_compr_audio *prtd = NULL;
3430 long *values = &(ucontrol->value.integer.value[0]);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303431 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303432 int effects_module;
3433
3434 pr_debug("%s\n", __func__);
3435 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3436 pr_err("%s Received out of bounds fe_id %lu\n",
3437 __func__, fe_id);
3438 return -EINVAL;
3439 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303440
3441 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303442 cstream = pdata->cstream[fe_id];
3443 audio_effects = pdata->audio_effects[fe_id];
3444 if (!cstream || !audio_effects) {
3445 pr_err("%s: stream or effects inactive\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303446 ret = -EINVAL;
3447 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303448 }
3449 prtd = cstream->runtime->private_data;
3450 if (!prtd) {
3451 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303452 ret = -EINVAL;
3453 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303454 }
3455 if (prtd->compr_passthr != LEGACY_PCM) {
3456 pr_debug("%s: No effects for compr_type[%d]\n",
3457 __func__, prtd->compr_passthr);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303458 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303459 }
3460 pr_debug("%s: Effects supported for compr_type[%d]\n",
3461 __func__, prtd->compr_passthr);
3462
3463 effects_module = *values++;
3464 switch (effects_module) {
3465 case VIRTUALIZER_MODULE:
3466 pr_debug("%s: VIRTUALIZER_MODULE\n", __func__);
3467 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3468 prtd->audio_client->topology))
3469 msm_audio_effects_virtualizer_handler(
3470 prtd->audio_client,
3471 &(audio_effects->virtualizer),
3472 values);
3473 break;
3474 case REVERB_MODULE:
3475 pr_debug("%s: REVERB_MODULE\n", __func__);
3476 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3477 prtd->audio_client->topology))
3478 msm_audio_effects_reverb_handler(prtd->audio_client,
3479 &(audio_effects->reverb),
3480 values);
3481 break;
3482 case BASS_BOOST_MODULE:
3483 pr_debug("%s: BASS_BOOST_MODULE\n", __func__);
3484 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3485 prtd->audio_client->topology))
3486 msm_audio_effects_bass_boost_handler(prtd->audio_client,
3487 &(audio_effects->bass_boost),
3488 values);
3489 break;
3490 case PBE_MODULE:
3491 pr_debug("%s: PBE_MODULE\n", __func__);
3492 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3493 prtd->audio_client->topology))
3494 msm_audio_effects_pbe_handler(prtd->audio_client,
3495 &(audio_effects->pbe),
3496 values);
3497 break;
3498 case EQ_MODULE:
3499 pr_debug("%s: EQ_MODULE\n", __func__);
3500 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3501 prtd->audio_client->topology))
3502 msm_audio_effects_popless_eq_handler(prtd->audio_client,
3503 &(audio_effects->equalizer),
3504 values);
3505 break;
3506 case SOFT_VOLUME_MODULE:
3507 pr_debug("%s: SOFT_VOLUME_MODULE\n", __func__);
3508 break;
3509 case SOFT_VOLUME2_MODULE:
3510 pr_debug("%s: SOFT_VOLUME2_MODULE\n", __func__);
3511 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3512 prtd->audio_client->topology))
3513 msm_audio_effects_volume_handler_v2(prtd->audio_client,
3514 &(audio_effects->volume),
3515 values, SOFT_VOLUME_INSTANCE_2);
3516 break;
3517 default:
3518 pr_err("%s Invalid effects config module\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303519 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303520 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303521done:
3522 mutex_unlock(&pdata->lock);
3523 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303524}
3525
3526static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol,
3527 struct snd_ctl_elem_value *ucontrol)
3528{
3529 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3530 unsigned long fe_id = kcontrol->private_value;
3531 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3532 snd_soc_component_get_drvdata(comp);
3533 struct msm_compr_audio_effects *audio_effects = NULL;
3534 struct snd_compr_stream *cstream = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303535 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303536 struct msm_compr_audio *prtd = NULL;
3537
3538 pr_debug("%s\n", __func__);
3539 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3540 pr_err("%s Received out of bounds fe_id %lu\n",
3541 __func__, fe_id);
3542 return -EINVAL;
3543 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303544
3545 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303546 cstream = pdata->cstream[fe_id];
3547 audio_effects = pdata->audio_effects[fe_id];
3548 if (!cstream || !audio_effects) {
Vignesh Kulothungan2ce67842018-09-25 16:40:29 -07003549 pr_debug("%s: stream or effects inactive\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303550 ret = -EINVAL;
3551 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303552 }
3553 prtd = cstream->runtime->private_data;
3554 if (!prtd) {
3555 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303556 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303557 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303558done:
3559 mutex_unlock(&pdata->lock);
3560 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303561}
3562
3563static int msm_compr_query_audio_effect_put(struct snd_kcontrol *kcontrol,
3564 struct snd_ctl_elem_value *ucontrol)
3565{
3566 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3567 unsigned long fe_id = kcontrol->private_value;
3568 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3569 snd_soc_component_get_drvdata(comp);
3570 struct msm_compr_audio_effects *audio_effects = NULL;
3571 struct snd_compr_stream *cstream = NULL;
3572 struct msm_compr_audio *prtd = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303573 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303574 long *values = &(ucontrol->value.integer.value[0]);
3575
3576 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3577 pr_err("%s Received out of bounds fe_id %lu\n",
3578 __func__, fe_id);
3579 return -EINVAL;
3580 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303581
3582 mutex_lock(&pdata->lock);
3583
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303584 cstream = pdata->cstream[fe_id];
3585 audio_effects = pdata->audio_effects[fe_id];
3586 if (!cstream || !audio_effects) {
3587 pr_err("%s: stream or effects inactive\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303588 ret = -EINVAL;
3589 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303590 }
3591 prtd = cstream->runtime->private_data;
3592 if (!prtd) {
3593 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303594 ret = -EINVAL;
3595 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303596 }
3597 if (prtd->compr_passthr != LEGACY_PCM) {
3598 pr_err("%s: No effects for compr_type[%d]\n",
3599 __func__, prtd->compr_passthr);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303600 ret = -EPERM;
3601 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303602 }
3603 audio_effects->query.mod_id = (u32)*values++;
3604 audio_effects->query.parm_id = (u32)*values++;
3605 audio_effects->query.size = (u32)*values++;
3606 audio_effects->query.offset = (u32)*values++;
3607 audio_effects->query.device = (u32)*values++;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303608
3609done:
3610 mutex_unlock(&pdata->lock);
3611 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303612}
3613
3614static int msm_compr_query_audio_effect_get(struct snd_kcontrol *kcontrol,
3615 struct snd_ctl_elem_value *ucontrol)
3616{
3617 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3618 unsigned long fe_id = kcontrol->private_value;
3619 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3620 snd_soc_component_get_drvdata(comp);
3621 struct msm_compr_audio_effects *audio_effects = NULL;
3622 struct snd_compr_stream *cstream = NULL;
3623 struct msm_compr_audio *prtd = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303624 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303625 long *values = &(ucontrol->value.integer.value[0]);
3626
3627 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3628 pr_err("%s Received out of bounds fe_id %lu\n",
3629 __func__, fe_id);
3630 return -EINVAL;
3631 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303632
3633 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303634 cstream = pdata->cstream[fe_id];
3635 audio_effects = pdata->audio_effects[fe_id];
3636 if (!cstream || !audio_effects) {
3637 pr_debug("%s: stream or effects inactive\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303638 ret = -EINVAL;
3639 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303640 }
3641 prtd = cstream->runtime->private_data;
3642 if (!prtd) {
3643 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303644 ret = -EINVAL;
3645 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303646 }
3647 values[0] = (long)audio_effects->query.mod_id;
3648 values[1] = (long)audio_effects->query.parm_id;
3649 values[2] = (long)audio_effects->query.size;
3650 values[3] = (long)audio_effects->query.offset;
3651 values[4] = (long)audio_effects->query.device;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303652done:
3653 mutex_unlock(&pdata->lock);
3654 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303655}
3656
3657static int msm_compr_send_dec_params(struct snd_compr_stream *cstream,
3658 struct msm_compr_dec_params *dec_params,
3659 int stream_id)
3660{
3661
3662 int rc = 0;
3663 struct msm_compr_audio *prtd = NULL;
3664 struct snd_dec_ddp *ddp = &dec_params->ddp_params;
3665
3666 if (!cstream || !dec_params) {
3667 pr_err("%s: stream or dec_params inactive\n", __func__);
3668 rc = -EINVAL;
3669 goto end;
3670 }
3671 prtd = cstream->runtime->private_data;
3672 if (!prtd) {
3673 pr_err("%s: cannot set dec_params\n", __func__);
3674 rc = -EINVAL;
3675 goto end;
3676 }
3677 switch (prtd->codec) {
3678 case FORMAT_MP3:
3679 case FORMAT_MPEG4_AAC:
3680 case FORMAT_TRUEHD:
3681 case FORMAT_IEC61937:
3682 case FORMAT_APTX:
3683 pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
3684 prtd->codec);
3685 break;
3686 case FORMAT_AC3:
3687 case FORMAT_EAC3:
3688 if (prtd->compr_passthr != LEGACY_PCM) {
3689 pr_debug("%s: No DDP param for compr_type[%d]\n",
3690 __func__, prtd->compr_passthr);
3691 break;
3692 }
3693 rc = msm_compr_send_ddp_cfg(prtd->audio_client, ddp, stream_id);
3694 if (rc < 0)
3695 pr_err("%s: DDP CMD CFG failed %d\n", __func__, rc);
3696 break;
3697 default:
3698 break;
3699 }
3700end:
3701 return rc;
3702
3703}
3704static int msm_compr_dec_params_put(struct snd_kcontrol *kcontrol,
3705 struct snd_ctl_elem_value *ucontrol)
3706{
3707 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3708 unsigned long fe_id = kcontrol->private_value;
3709 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3710 snd_soc_component_get_drvdata(comp);
3711 struct msm_compr_dec_params *dec_params = NULL;
3712 struct snd_compr_stream *cstream = NULL;
3713 struct msm_compr_audio *prtd = NULL;
3714 long *values = &(ucontrol->value.integer.value[0]);
3715 int rc = 0;
3716
3717 pr_debug("%s\n", __func__);
3718 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3719 pr_err("%s Received out of bounds fe_id %lu\n",
3720 __func__, fe_id);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05303721 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303722 }
3723
3724 cstream = pdata->cstream[fe_id];
3725 dec_params = pdata->dec_params[fe_id];
3726
3727 if (!cstream || !dec_params) {
3728 pr_err("%s: stream or dec_params inactive\n", __func__);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05303729 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303730 }
3731 prtd = cstream->runtime->private_data;
3732 if (!prtd) {
3733 pr_err("%s: cannot set dec_params\n", __func__);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05303734 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303735 }
3736
Ajit Pandeyfa018862019-09-04 14:34:00 +05303737 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303738 switch (prtd->codec) {
3739 case FORMAT_MP3:
3740 case FORMAT_MPEG4_AAC:
3741 case FORMAT_FLAC:
3742 case FORMAT_VORBIS:
3743 case FORMAT_ALAC:
3744 case FORMAT_APE:
3745 case FORMAT_DTS:
3746 case FORMAT_DSD:
3747 case FORMAT_TRUEHD:
3748 case FORMAT_IEC61937:
3749 case FORMAT_APTX:
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +05303750 case FORMAT_AMRNB:
3751 case FORMAT_AMRWB:
3752 case FORMAT_AMR_WB_PLUS:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303753 pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
3754 prtd->codec);
3755 break;
3756 case FORMAT_AC3:
3757 case FORMAT_EAC3: {
3758 struct snd_dec_ddp *ddp = &dec_params->ddp_params;
3759 int cnt;
3760
3761 if (prtd->compr_passthr != LEGACY_PCM) {
3762 pr_debug("%s: No DDP param for compr_type[%d]\n",
3763 __func__, prtd->compr_passthr);
3764 break;
3765 }
3766
3767 ddp->params_length = (*values++);
3768 if (ddp->params_length > DDP_DEC_MAX_NUM_PARAM) {
3769 pr_err("%s: invalid num of params:: %d\n", __func__,
3770 ddp->params_length);
3771 rc = -EINVAL;
3772 goto end;
3773 }
3774 for (cnt = 0; cnt < ddp->params_length; cnt++) {
3775 ddp->params_id[cnt] = *values++;
3776 ddp->params_value[cnt] = *values++;
3777 }
3778 prtd = cstream->runtime->private_data;
3779 if (prtd && prtd->audio_client)
3780 rc = msm_compr_send_dec_params(cstream, dec_params,
3781 prtd->audio_client->stream_id);
3782 break;
3783 }
3784 default:
3785 break;
3786 }
3787end:
3788 pr_debug("%s: ret %d\n", __func__, rc);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303789 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303790 return rc;
3791}
3792
3793static int msm_compr_dec_params_get(struct snd_kcontrol *kcontrol,
3794 struct snd_ctl_elem_value *ucontrol)
3795{
3796 /* dummy function */
3797 return 0;
3798}
3799
3800static int msm_compr_playback_app_type_cfg_put(struct snd_kcontrol *kcontrol,
3801 struct snd_ctl_elem_value *ucontrol)
3802{
3803 u64 fe_id = kcontrol->private_value;
3804 int session_type = SESSION_TYPE_RX;
3805 int be_id = ucontrol->value.integer.value[3];
3806 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
3807 int ret = 0;
3808
3809 cfg_data.app_type = ucontrol->value.integer.value[0];
3810 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
3811 if (ucontrol->value.integer.value[2] != 0)
3812 cfg_data.sample_rate = ucontrol->value.integer.value[2];
3813 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
3814 __func__, fe_id, session_type, be_id,
3815 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3816 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
3817 be_id, &cfg_data);
3818 if (ret < 0)
3819 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
3820 __func__, ret);
3821
3822 return ret;
3823}
3824
3825static int msm_compr_playback_app_type_cfg_get(struct snd_kcontrol *kcontrol,
3826 struct snd_ctl_elem_value *ucontrol)
3827{
3828 u64 fe_id = kcontrol->private_value;
3829 int session_type = SESSION_TYPE_RX;
3830 int be_id = 0;
3831 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
3832 int ret = 0;
3833
3834 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
3835 &be_id, &cfg_data);
3836 if (ret < 0) {
3837 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
3838 __func__, ret);
3839 goto done;
3840 }
3841
3842 ucontrol->value.integer.value[0] = cfg_data.app_type;
3843 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
3844 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
3845 ucontrol->value.integer.value[3] = be_id;
3846 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
3847 __func__, fe_id, session_type, be_id,
3848 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3849done:
3850 return ret;
3851}
3852
3853static int msm_compr_capture_app_type_cfg_put(struct snd_kcontrol *kcontrol,
3854 struct snd_ctl_elem_value *ucontrol)
3855{
3856 u64 fe_id = kcontrol->private_value;
3857 int session_type = SESSION_TYPE_TX;
3858 int be_id = ucontrol->value.integer.value[3];
3859 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
3860 int ret = 0;
3861
3862 cfg_data.app_type = ucontrol->value.integer.value[0];
3863 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
3864 if (ucontrol->value.integer.value[2] != 0)
3865 cfg_data.sample_rate = ucontrol->value.integer.value[2];
3866 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
3867 __func__, fe_id, session_type, be_id,
3868 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3869 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
3870 be_id, &cfg_data);
3871 if (ret < 0)
3872 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
3873 __func__, ret);
3874
3875 return ret;
3876}
3877
3878static int msm_compr_capture_app_type_cfg_get(struct snd_kcontrol *kcontrol,
3879 struct snd_ctl_elem_value *ucontrol)
3880{
3881 u64 fe_id = kcontrol->private_value;
3882 int session_type = SESSION_TYPE_TX;
3883 int be_id = 0;
3884 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
3885 int ret = 0;
3886
3887 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
3888 &be_id, &cfg_data);
3889 if (ret < 0) {
3890 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
3891 __func__, ret);
3892 goto done;
3893 }
3894
3895 ucontrol->value.integer.value[0] = cfg_data.app_type;
3896 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
3897 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
3898 ucontrol->value.integer.value[3] = be_id;
3899 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
3900 __func__, fe_id, session_type, be_id,
3901 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3902done:
3903 return ret;
3904}
3905
3906static int msm_compr_channel_map_put(struct snd_kcontrol *kcontrol,
3907 struct snd_ctl_elem_value *ucontrol)
3908{
3909 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3910 u64 fe_id = kcontrol->private_value;
3911 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3912 snd_soc_component_get_drvdata(comp);
3913 int rc = 0, i;
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05303914 struct msm_pcm_channel_mixer *chmixer_pspd = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303915
3916 pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
3917
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05303918 if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303919 pr_err("%s Received out of bounds fe_id %llu\n",
3920 __func__, fe_id);
3921 rc = -EINVAL;
3922 goto end;
3923 }
3924
3925 if (pdata->ch_map[fe_id]) {
3926 pdata->ch_map[fe_id]->set_ch_map = true;
Dieter Lueckingceef9af2018-09-28 15:09:32 +02003927 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303928 pdata->ch_map[fe_id]->channel_map[i] =
3929 (char)(ucontrol->value.integer.value[i]);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05303930
3931 /* update chmixer_pspd chmap cached with routing driver as well */
3932 chmixer_pspd = pdata->chmixer_pspd[fe_id];
3933 if (chmixer_pspd && chmixer_pspd->enable) {
3934 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
3935 chmixer_pspd->in_ch_map[i] =
3936 pdata->ch_map[fe_id]->channel_map[i];
3937 chmixer_pspd->override_in_ch_map = true;
3938 msm_pcm_routing_set_channel_mixer_cfg(fe_id,
3939 SESSION_TYPE_RX, chmixer_pspd);
3940 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303941 } else {
3942 pr_debug("%s: no memory for ch_map, default will be set\n",
3943 __func__);
3944 }
3945end:
3946 pr_debug("%s: ret %d\n", __func__, rc);
3947 return rc;
3948}
3949
3950static int msm_compr_channel_map_get(struct snd_kcontrol *kcontrol,
3951 struct snd_ctl_elem_value *ucontrol)
3952{
3953 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3954 u64 fe_id = kcontrol->private_value;
3955 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3956 snd_soc_component_get_drvdata(comp);
3957 int rc = 0, i;
3958
3959 pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05303960 if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303961 pr_err("%s: Received out of bounds fe_id %llu\n",
3962 __func__, fe_id);
3963 rc = -EINVAL;
3964 goto end;
3965 }
3966 if (pdata->ch_map[fe_id]) {
Dieter Lueckingceef9af2018-09-28 15:09:32 +02003967 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303968 ucontrol->value.integer.value[i] =
3969 pdata->ch_map[fe_id]->channel_map[i];
3970 }
3971end:
3972 pr_debug("%s: ret %d\n", __func__, rc);
3973 return rc;
3974}
3975
3976static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
3977 struct snd_ctl_elem_value *ucontrol)
3978{
3979 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3980 unsigned long fe_id = kcontrol->private_value;
3981 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3982 snd_soc_component_get_drvdata(comp);
3983 struct snd_compr_stream *cstream = NULL;
3984 struct msm_compr_audio *prtd;
3985 int ret = 0;
3986 struct msm_adsp_event_data *event_data = NULL;
3987
3988 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3989 pr_err("%s Received invalid fe_id %lu\n",
3990 __func__, fe_id);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05303991 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303992 }
3993
3994 cstream = pdata->cstream[fe_id];
3995 if (cstream == NULL) {
3996 pr_err("%s cstream is null\n", __func__);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05303997 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303998 }
3999
4000 prtd = cstream->runtime->private_data;
4001 if (!prtd) {
4002 pr_err("%s: prtd is null\n", __func__);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05304003 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304004 }
4005
Ajit Pandeyfa018862019-09-04 14:34:00 +05304006 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304007 if (prtd->audio_client == NULL) {
4008 pr_err("%s: audio_client is null\n", __func__);
4009 ret = -EINVAL;
4010 goto done;
4011 }
4012
4013 event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data;
4014 if ((event_data->event_type < ADSP_STREAM_PP_EVENT) ||
4015 (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) {
4016 pr_err("%s: invalid event_type=%d",
4017 __func__, event_data->event_type);
4018 ret = -EINVAL;
4019 goto done;
4020 }
4021
Xiaojun Sang75642c32018-03-23 08:57:33 +08004022 if (event_data->payload_len > sizeof(ucontrol->value.bytes.data)
4023 - sizeof(struct msm_adsp_event_data)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304024 pr_err("%s param length=%d exceeds limit",
4025 __func__, event_data->payload_len);
4026 ret = -EINVAL;
4027 goto done;
4028 }
4029
4030 ret = q6asm_send_stream_cmd(prtd->audio_client, event_data);
4031 if (ret < 0)
4032 pr_err("%s: failed to send stream event cmd, err = %d\n",
4033 __func__, ret);
4034done:
Ajit Pandeyfa018862019-09-04 14:34:00 +05304035 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304036 return ret;
4037}
4038
4039static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
4040 struct snd_ctl_elem_value *ucontrol)
4041{
4042 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4043 unsigned long fe_id = kcontrol->private_value;
4044 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4045 snd_soc_component_get_drvdata(comp);
4046 struct snd_compr_stream *cstream = NULL;
4047 struct msm_compr_audio *prtd;
4048 int fd;
4049 int ret = 0;
4050
4051 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
4052 pr_err("%s Received out of bounds invalid fe_id %lu\n",
4053 __func__, fe_id);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05304054 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304055 }
4056
4057 cstream = pdata->cstream[fe_id];
4058 if (cstream == NULL) {
4059 pr_err("%s cstream is null\n", __func__);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05304060 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304061 }
4062
4063 prtd = cstream->runtime->private_data;
4064 if (!prtd) {
4065 pr_err("%s: prtd is null\n", __func__);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05304066 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304067 }
4068
Ajit Pandeyfa018862019-09-04 14:34:00 +05304069 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304070 if (prtd->audio_client == NULL) {
4071 pr_err("%s: audio_client is null\n", __func__);
4072 ret = -EINVAL;
4073 goto done;
4074 }
4075
4076 memcpy(&fd, ucontrol->value.bytes.data, sizeof(fd));
4077 ret = q6asm_send_ion_fd(prtd->audio_client, fd);
4078 if (ret < 0)
4079 pr_err("%s: failed to register ion fd\n", __func__);
4080done:
Ajit Pandeyfa018862019-09-04 14:34:00 +05304081 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304082 return ret;
4083}
4084
4085static int msm_compr_rtic_event_ack_put(struct snd_kcontrol *kcontrol,
4086 struct snd_ctl_elem_value *ucontrol)
4087{
4088 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4089 unsigned long fe_id = kcontrol->private_value;
4090 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4091 snd_soc_component_get_drvdata(comp);
4092 struct snd_compr_stream *cstream = NULL;
4093 struct msm_compr_audio *prtd;
4094 int ret = 0;
4095 int param_length = 0;
4096
4097 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
4098 pr_err("%s Received invalid fe_id %lu\n",
4099 __func__, fe_id);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05304100 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304101 }
4102
Ajit Pandeyfa018862019-09-04 14:34:00 +05304103 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304104 cstream = pdata->cstream[fe_id];
4105 if (cstream == NULL) {
4106 pr_err("%s cstream is null\n", __func__);
4107 ret = -EINVAL;
4108 goto done;
4109 }
4110
4111 prtd = cstream->runtime->private_data;
4112 if (!prtd) {
4113 pr_err("%s: prtd is null\n", __func__);
4114 ret = -EINVAL;
4115 goto done;
4116 }
4117
4118 if (prtd->audio_client == NULL) {
4119 pr_err("%s: audio_client is null\n", __func__);
4120 ret = -EINVAL;
4121 goto done;
4122 }
4123
4124 memcpy(&param_length, ucontrol->value.bytes.data,
4125 sizeof(param_length));
4126 if ((param_length + sizeof(param_length))
4127 >= sizeof(ucontrol->value.bytes.data)) {
4128 pr_err("%s param length=%d exceeds limit",
4129 __func__, param_length);
4130 ret = -EINVAL;
4131 goto done;
4132 }
4133
4134 ret = q6asm_send_rtic_event_ack(prtd->audio_client,
4135 ucontrol->value.bytes.data + sizeof(param_length),
4136 param_length);
4137 if (ret < 0)
4138 pr_err("%s: failed to send rtic event ack, err = %d\n",
4139 __func__, ret);
4140done:
Ajit Pandeyfa018862019-09-04 14:34:00 +05304141 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304142 return ret;
4143}
4144
4145static int msm_compr_gapless_put(struct snd_kcontrol *kcontrol,
4146 struct snd_ctl_elem_value *ucontrol)
4147{
4148 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4149 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4150 snd_soc_component_get_drvdata(comp);
4151 pdata->use_dsp_gapless_mode = ucontrol->value.integer.value[0];
4152 pr_debug("%s: value: %ld\n", __func__,
4153 ucontrol->value.integer.value[0]);
4154
4155 return 0;
4156}
4157
4158static int msm_compr_gapless_get(struct snd_kcontrol *kcontrol,
4159 struct snd_ctl_elem_value *ucontrol)
4160{
4161 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4162 struct msm_compr_pdata *pdata =
4163 snd_soc_component_get_drvdata(comp);
4164 pr_debug("%s:gapless mode %d\n", __func__, pdata->use_dsp_gapless_mode);
4165 ucontrol->value.integer.value[0] = pdata->use_dsp_gapless_mode;
4166
4167 return 0;
4168}
4169
4170static const struct snd_kcontrol_new msm_compr_gapless_controls[] = {
4171 SOC_SINGLE_EXT("Compress Gapless Playback",
4172 0, 0, 1, 0,
4173 msm_compr_gapless_get,
4174 msm_compr_gapless_put),
4175};
4176
Meng Wangee084a02018-09-04 16:11:58 +08004177static int msm_compr_probe(struct snd_soc_component *component)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304178{
4179 struct msm_compr_pdata *pdata;
4180 int i;
4181 int rc;
4182 const char *qdsp_version;
4183
4184 pr_debug("%s\n", __func__);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304185 pdata = (struct msm_compr_pdata *) dev_get_drvdata(component->dev);
4186 if (!pdata) {
4187 pr_err("%s platform data not set\n", __func__);
4188 return -EINVAL;
4189 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304190
Meng Wangee084a02018-09-04 16:11:58 +08004191 snd_soc_component_set_drvdata(component, pdata);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304192
4193 for (i = 0; i < MSM_FRONTEND_DAI_MAX; i++) {
4194 pdata->volume[i][0] = COMPRESSED_LR_VOL_MAX_STEPS;
4195 pdata->volume[i][1] = COMPRESSED_LR_VOL_MAX_STEPS;
4196 pdata->audio_effects[i] = NULL;
4197 pdata->dec_params[i] = NULL;
4198 pdata->cstream[i] = NULL;
4199 pdata->ch_map[i] = NULL;
Aditya Bavanari9deef912017-11-20 13:31:31 +05304200 pdata->is_in_use[i] = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304201 }
4202
Meng Wangee084a02018-09-04 16:11:58 +08004203 snd_soc_add_component_controls(component, msm_compr_gapless_controls,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304204 ARRAY_SIZE(msm_compr_gapless_controls));
4205
Meng Wangee084a02018-09-04 16:11:58 +08004206 rc = of_property_read_string(component->dev->of_node,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304207 "qcom,adsp-version", &qdsp_version);
4208 if (!rc) {
4209 if (!strcmp(qdsp_version, "MDSP 1.2"))
4210 pdata->use_legacy_api = true;
4211 else
4212 pdata->use_legacy_api = false;
4213 } else
4214 pdata->use_legacy_api = false;
4215
4216 pr_debug("%s: use legacy api %d\n", __func__, pdata->use_legacy_api);
4217 /*
4218 * use_dsp_gapless_mode part of platform data(pdata) is updated from HAL
4219 * through a mixer control before compress driver is opened. The mixer
4220 * control is used to decide if dsp gapless mode needs to be enabled.
4221 * Gapless is disabled by default.
4222 */
4223 pdata->use_dsp_gapless_mode = false;
4224 return 0;
4225}
4226
4227static int msm_compr_volume_info(struct snd_kcontrol *kcontrol,
4228 struct snd_ctl_elem_info *uinfo)
4229{
4230 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4231 uinfo->count = 2;
4232 uinfo->value.integer.min = 0;
4233 uinfo->value.integer.max = COMPRESSED_LR_VOL_MAX_STEPS;
4234 return 0;
4235}
4236
4237static int msm_compr_audio_effects_config_info(struct snd_kcontrol *kcontrol,
4238 struct snd_ctl_elem_info *uinfo)
4239{
4240 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4241 uinfo->count = MAX_PP_PARAMS_SZ;
4242 uinfo->value.integer.min = 0;
4243 uinfo->value.integer.max = 0xFFFFFFFF;
4244 return 0;
4245}
4246
4247static int msm_compr_query_audio_effect_info(struct snd_kcontrol *kcontrol,
4248 struct snd_ctl_elem_info *uinfo)
4249{
4250 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4251 uinfo->count = 128;
4252 uinfo->value.integer.min = 0;
4253 uinfo->value.integer.max = 0xFFFFFFFF;
4254 return 0;
4255}
4256
4257static int msm_compr_dec_params_info(struct snd_kcontrol *kcontrol,
4258 struct snd_ctl_elem_info *uinfo)
4259{
4260 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4261 uinfo->count = 128;
4262 uinfo->value.integer.min = 0;
4263 uinfo->value.integer.max = 0xFFFFFFFF;
4264 return 0;
4265}
4266
4267static int msm_compr_app_type_cfg_info(struct snd_kcontrol *kcontrol,
4268 struct snd_ctl_elem_info *uinfo)
4269{
4270 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4271 uinfo->count = 5;
4272 uinfo->value.integer.min = 0;
4273 uinfo->value.integer.max = 0xFFFFFFFF;
4274 return 0;
4275}
4276
4277static int msm_compr_channel_map_info(struct snd_kcontrol *kcontrol,
4278 struct snd_ctl_elem_info *uinfo)
4279{
4280 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
Dieter Lueckingceef9af2018-09-28 15:09:32 +02004281 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304282 uinfo->value.integer.min = 0;
Surendar Karka59769532019-08-05 16:02:32 +05304283 /* See PCM_MAX_CHANNEL_MAP in apr_audio-v2.h */
4284 uinfo->value.integer.max = PCM_MAX_CHANNEL_MAP;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304285 return 0;
4286}
4287
4288static int msm_compr_add_volume_control(struct snd_soc_pcm_runtime *rtd)
4289{
Meng Wangee084a02018-09-04 16:11:58 +08004290 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304291 const char *mixer_ctl_name = "Compress Playback";
4292 const char *deviceNo = "NN";
4293 const char *suffix = "Volume";
4294 char *mixer_str = NULL;
4295 int ctl_len;
4296 struct snd_kcontrol_new fe_volume_control[1] = {
4297 {
4298 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4299 .name = "?",
4300 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
4301 SNDRV_CTL_ELEM_ACCESS_READWRITE,
4302 .info = msm_compr_volume_info,
4303 .tlv.p = msm_compr_vol_gain,
4304 .get = msm_compr_volume_get,
4305 .put = msm_compr_volume_put,
4306 .private_value = 0,
4307 }
4308 };
4309
4310 if (!rtd) {
4311 pr_err("%s NULL rtd\n", __func__);
4312 return 0;
4313 }
Meng Wangee084a02018-09-04 16:11:58 +08004314 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4315 if (!component) {
4316 pr_err("%s: component is NULL\n", __func__);
4317 return 0;
4318 }
4319
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304320 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4321 __func__, rtd->dai_link->name, rtd->dai_link->id,
4322 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4323 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
4324 strlen(suffix) + 1;
4325 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4326 if (!mixer_str) {
4327 pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
4328 return 0;
4329 }
4330 snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
4331 rtd->pcm->device, suffix);
4332 fe_volume_control[0].name = mixer_str;
4333 fe_volume_control[0].private_value = rtd->dai_link->id;
4334 pr_debug("Registering new mixer ctl %s", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004335 snd_soc_add_component_controls(component, fe_volume_control,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304336 ARRAY_SIZE(fe_volume_control));
4337 kfree(mixer_str);
4338 return 0;
4339}
4340
4341static int msm_compr_add_audio_effects_control(struct snd_soc_pcm_runtime *rtd)
4342{
Meng Wangee084a02018-09-04 16:11:58 +08004343 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304344 const char *mixer_ctl_name = "Audio Effects Config";
4345 const char *deviceNo = "NN";
4346 char *mixer_str = NULL;
4347 int ctl_len;
4348 struct snd_kcontrol_new fe_audio_effects_config_control[1] = {
4349 {
4350 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4351 .name = "?",
4352 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4353 .info = msm_compr_audio_effects_config_info,
4354 .get = msm_compr_audio_effects_config_get,
4355 .put = msm_compr_audio_effects_config_put,
4356 .private_value = 0,
4357 }
4358 };
4359
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304360 if (!rtd) {
4361 pr_err("%s NULL rtd\n", __func__);
4362 return 0;
4363 }
4364
Meng Wangee084a02018-09-04 16:11:58 +08004365 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4366 if (!component) {
4367 pr_err("%s: component is NULL\n", __func__);
4368 return 0;
4369 }
4370
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304371 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4372 __func__, rtd->dai_link->name, rtd->dai_link->id,
4373 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4374
4375 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4376 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4377
4378 if (!mixer_str)
4379 return 0;
4380
4381 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4382
4383 fe_audio_effects_config_control[0].name = mixer_str;
4384 fe_audio_effects_config_control[0].private_value = rtd->dai_link->id;
4385 pr_debug("Registering new mixer ctl %s\n", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004386 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304387 fe_audio_effects_config_control,
4388 ARRAY_SIZE(fe_audio_effects_config_control));
4389 kfree(mixer_str);
4390 return 0;
4391}
4392
4393static int msm_compr_add_query_audio_effect_control(
4394 struct snd_soc_pcm_runtime *rtd)
4395{
Meng Wangee084a02018-09-04 16:11:58 +08004396 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304397 const char *mixer_ctl_name = "Query Audio Effect Param";
4398 const char *deviceNo = "NN";
4399 char *mixer_str = NULL;
4400 int ctl_len;
4401 struct snd_kcontrol_new fe_query_audio_effect_control[1] = {
4402 {
4403 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4404 .name = "?",
4405 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4406 .info = msm_compr_query_audio_effect_info,
4407 .get = msm_compr_query_audio_effect_get,
4408 .put = msm_compr_query_audio_effect_put,
4409 .private_value = 0,
4410 }
4411 };
4412 if (!rtd) {
4413 pr_err("%s NULL rtd\n", __func__);
4414 return 0;
4415 }
Meng Wangee084a02018-09-04 16:11:58 +08004416
4417 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4418 if (!component) {
4419 pr_err("%s: component is NULL\n", __func__);
4420 return 0;
4421 }
4422
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304423 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4424 __func__, rtd->dai_link->name, rtd->dai_link->id,
4425 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4426 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4427 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4428 if (!mixer_str) {
4429 pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
4430 return 0;
4431 }
4432 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4433 fe_query_audio_effect_control[0].name = mixer_str;
4434 fe_query_audio_effect_control[0].private_value = rtd->dai_link->id;
4435 pr_debug("%s: registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004436 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304437 fe_query_audio_effect_control,
4438 ARRAY_SIZE(fe_query_audio_effect_control));
4439 kfree(mixer_str);
4440 return 0;
4441}
4442
4443static int msm_compr_add_audio_adsp_stream_cmd_control(
4444 struct snd_soc_pcm_runtime *rtd)
4445{
Meng Wangee084a02018-09-04 16:11:58 +08004446 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304447 const char *mixer_ctl_name = DSP_STREAM_CMD;
4448 const char *deviceNo = "NN";
4449 char *mixer_str = NULL;
4450 int ctl_len = 0, ret = 0;
4451 struct snd_kcontrol_new fe_audio_adsp_stream_cmd_config_control[1] = {
4452 {
4453 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4454 .name = "?",
4455 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4456 .info = msm_adsp_stream_cmd_info,
4457 .put = msm_compr_adsp_stream_cmd_put,
4458 .private_value = 0,
4459 }
4460 };
4461
4462 if (!rtd) {
4463 pr_err("%s NULL rtd\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08004464 return -EINVAL;
4465 }
4466
4467 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4468 if (!component) {
4469 pr_err("%s: component is NULL\n", __func__);
4470 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304471 }
4472
4473 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4474 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08004475 if (!mixer_str)
4476 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304477
4478 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4479 fe_audio_adsp_stream_cmd_config_control[0].name = mixer_str;
4480 fe_audio_adsp_stream_cmd_config_control[0].private_value =
4481 rtd->dai_link->id;
4482 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004483 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304484 fe_audio_adsp_stream_cmd_config_control,
4485 ARRAY_SIZE(fe_audio_adsp_stream_cmd_config_control));
4486 if (ret < 0)
4487 pr_err("%s: failed to add ctl %s. err = %d\n",
4488 __func__, mixer_str, ret);
4489
4490 kfree(mixer_str);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304491 return ret;
4492}
4493
4494static int msm_compr_add_audio_adsp_stream_callback_control(
4495 struct snd_soc_pcm_runtime *rtd)
4496{
Meng Wangee084a02018-09-04 16:11:58 +08004497 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304498 const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
4499 const char *deviceNo = "NN";
4500 char *mixer_str = NULL;
4501 int ctl_len = 0, ret = 0;
4502 struct snd_kcontrol *kctl;
4503
4504 struct snd_kcontrol_new fe_audio_adsp_callback_config_control[1] = {
4505 {
4506 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4507 .name = "?",
4508 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4509 .info = msm_adsp_stream_callback_info,
4510 .get = msm_adsp_stream_callback_get,
4511 .private_value = 0,
4512 }
4513 };
4514
4515 if (!rtd) {
4516 pr_err("%s: rtd is NULL\n", __func__);
4517 ret = -EINVAL;
4518 goto done;
4519 }
4520
Meng Wangee084a02018-09-04 16:11:58 +08004521 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4522 if (!component) {
4523 pr_err("%s: component is NULL\n", __func__);
4524 return -EINVAL;
4525 }
4526
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304527 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4528 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4529 if (!mixer_str) {
4530 ret = -ENOMEM;
4531 goto done;
4532 }
4533
4534 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4535 fe_audio_adsp_callback_config_control[0].name = mixer_str;
4536 fe_audio_adsp_callback_config_control[0].private_value =
4537 rtd->dai_link->id;
4538 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004539 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304540 fe_audio_adsp_callback_config_control,
4541 ARRAY_SIZE(fe_audio_adsp_callback_config_control));
4542 if (ret < 0) {
4543 pr_err("%s: failed to add ctl %s. err = %d\n",
4544 __func__, mixer_str, ret);
4545 ret = -EINVAL;
4546 goto free_mixer_str;
4547 }
4548
4549 kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
4550 if (!kctl) {
4551 pr_err("%s: failed to get kctl %s.\n", __func__, mixer_str);
4552 ret = -EINVAL;
4553 goto free_mixer_str;
4554 }
4555
4556 kctl->private_data = NULL;
4557
4558free_mixer_str:
4559 kfree(mixer_str);
4560done:
4561 return ret;
4562}
4563
4564static int msm_compr_add_dec_runtime_params_control(
4565 struct snd_soc_pcm_runtime *rtd)
4566{
Meng Wangee084a02018-09-04 16:11:58 +08004567 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304568 const char *mixer_ctl_name = "Audio Stream";
4569 const char *deviceNo = "NN";
4570 const char *suffix = "Dec Params";
4571 char *mixer_str = NULL;
4572 int ctl_len;
4573 struct snd_kcontrol_new fe_dec_params_control[1] = {
4574 {
4575 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4576 .name = "?",
4577 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4578 .info = msm_compr_dec_params_info,
4579 .get = msm_compr_dec_params_get,
4580 .put = msm_compr_dec_params_put,
4581 .private_value = 0,
4582 }
4583 };
4584
4585 if (!rtd) {
4586 pr_err("%s NULL rtd\n", __func__);
4587 return 0;
4588 }
4589
Meng Wangee084a02018-09-04 16:11:58 +08004590 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4591 if (!component) {
4592 pr_err("%s: component is NULL\n", __func__);
4593 return 0;
4594 }
4595
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304596 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4597 __func__, rtd->dai_link->name, rtd->dai_link->id,
4598 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4599
4600 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
4601 strlen(suffix) + 1;
4602 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4603
4604 if (!mixer_str)
4605 return 0;
4606
4607 snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
4608 rtd->pcm->device, suffix);
4609
4610 fe_dec_params_control[0].name = mixer_str;
4611 fe_dec_params_control[0].private_value = rtd->dai_link->id;
4612 pr_debug("Registering new mixer ctl %s", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004613 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304614 fe_dec_params_control,
4615 ARRAY_SIZE(fe_dec_params_control));
4616 kfree(mixer_str);
4617 return 0;
4618}
4619
4620static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
4621{
Meng Wangee084a02018-09-04 16:11:58 +08004622 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304623 const char *playback_mixer_ctl_name = "Audio Stream";
4624 const char *capture_mixer_ctl_name = "Audio Stream Capture";
4625 const char *deviceNo = "NN";
4626 const char *suffix = "App Type Cfg";
4627 char *mixer_str = NULL;
4628 int ctl_len;
4629 struct snd_kcontrol_new fe_app_type_cfg_control[1] = {
4630 {
4631 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4632 .name = "?",
4633 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4634 .info = msm_compr_app_type_cfg_info,
4635 .put = msm_compr_playback_app_type_cfg_put,
4636 .get = msm_compr_playback_app_type_cfg_get,
4637 .private_value = 0,
4638 }
4639 };
4640
4641 if (!rtd) {
4642 pr_err("%s NULL rtd\n", __func__);
4643 return 0;
4644 }
4645
Meng Wangee084a02018-09-04 16:11:58 +08004646 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4647 if (!component) {
4648 pr_err("%s: component is NULL\n", __func__);
4649 return 0;
4650 }
4651
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304652 pr_debug("%s: added new compr FE ctl with name %s, id %d, cpu dai %s, device no %d\n",
4653 __func__, rtd->dai_link->name, rtd->dai_link->id,
4654 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4655 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
4656 ctl_len = strlen(playback_mixer_ctl_name) + 1 + strlen(deviceNo)
4657 + 1 + strlen(suffix) + 1;
4658 else
4659 ctl_len = strlen(capture_mixer_ctl_name) + 1 + strlen(deviceNo)
4660 + 1 + strlen(suffix) + 1;
4661
4662 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4663
4664 if (!mixer_str)
4665 return 0;
4666
4667 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
4668 snprintf(mixer_str, ctl_len, "%s %d %s",
4669 playback_mixer_ctl_name, rtd->pcm->device, suffix);
4670 else
4671 snprintf(mixer_str, ctl_len, "%s %d %s",
4672 capture_mixer_ctl_name, rtd->pcm->device, suffix);
4673
4674 fe_app_type_cfg_control[0].name = mixer_str;
4675 fe_app_type_cfg_control[0].private_value = rtd->dai_link->id;
4676
4677 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
4678 fe_app_type_cfg_control[0].put =
4679 msm_compr_playback_app_type_cfg_put;
4680 fe_app_type_cfg_control[0].get =
4681 msm_compr_playback_app_type_cfg_get;
4682 } else {
4683 fe_app_type_cfg_control[0].put =
4684 msm_compr_capture_app_type_cfg_put;
4685 fe_app_type_cfg_control[0].get =
4686 msm_compr_capture_app_type_cfg_get;
4687 }
4688 pr_debug("Registering new mixer ctl %s", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004689 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304690 fe_app_type_cfg_control,
4691 ARRAY_SIZE(fe_app_type_cfg_control));
4692 kfree(mixer_str);
4693 return 0;
4694}
4695
4696static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
4697{
Meng Wangee084a02018-09-04 16:11:58 +08004698 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304699 const char *mixer_ctl_name = "Playback Channel Map";
4700 const char *deviceNo = "NN";
4701 char *mixer_str = NULL;
4702 struct msm_compr_pdata *pdata = NULL;
4703 int ctl_len;
4704 struct snd_kcontrol_new fe_channel_map_control[1] = {
4705 {
4706 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4707 .name = "?",
4708 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4709 .info = msm_compr_channel_map_info,
4710 .get = msm_compr_channel_map_get,
4711 .put = msm_compr_channel_map_put,
4712 .private_value = 0,
4713 }
4714 };
4715
4716 if (!rtd) {
4717 pr_err("%s: NULL rtd\n", __func__);
4718 return -EINVAL;
4719 }
4720
Meng Wangee084a02018-09-04 16:11:58 +08004721 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4722 if (!component) {
4723 pr_err("%s: component is NULL\n", __func__);
4724 return -EINVAL;
4725 }
4726
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304727 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4728 __func__, rtd->dai_link->name, rtd->dai_link->id,
4729 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4730
4731 ctl_len = strlen(mixer_ctl_name) + strlen(deviceNo) + 1;
4732 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4733
4734 if (!mixer_str)
4735 return -ENOMEM;
4736
4737 snprintf(mixer_str, ctl_len, "%s%d", mixer_ctl_name, rtd->pcm->device);
4738
4739 fe_channel_map_control[0].name = mixer_str;
4740 fe_channel_map_control[0].private_value = rtd->dai_link->id;
4741 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004742 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304743 fe_channel_map_control,
4744 ARRAY_SIZE(fe_channel_map_control));
4745
Meng Wangee084a02018-09-04 16:11:58 +08004746 pdata = snd_soc_component_get_drvdata(component);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304747 pdata->ch_map[rtd->dai_link->id] =
4748 kzalloc(sizeof(struct msm_compr_ch_map), GFP_KERNEL);
4749 if (!pdata->ch_map[rtd->dai_link->id]) {
4750 pr_err("%s: Could not allocate memory for channel map\n",
4751 __func__);
4752 kfree(mixer_str);
4753 return -ENOMEM;
4754 }
4755 kfree(mixer_str);
4756 return 0;
4757}
4758
4759static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
4760{
Meng Wangee084a02018-09-04 16:11:58 +08004761 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304762 const char *mixer_ctl_name = "Playback ION FD";
4763 const char *deviceNo = "NN";
4764 char *mixer_str = NULL;
4765 int ctl_len = 0, ret = 0;
4766 struct snd_kcontrol_new fe_ion_fd_config_control[1] = {
4767 {
4768 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4769 .name = "?",
4770 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4771 .info = msm_adsp_stream_cmd_info,
4772 .put = msm_compr_ion_fd_map_put,
4773 .private_value = 0,
4774 }
4775 };
4776
4777 if (!rtd) {
4778 pr_err("%s NULL rtd\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08004779 return -EINVAL;
4780 }
4781
4782 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4783 if (!component) {
4784 pr_err("%s: component is NULL\n", __func__);
4785 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304786 }
4787
4788 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4789 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08004790 if (!mixer_str)
4791 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304792
4793 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4794 fe_ion_fd_config_control[0].name = mixer_str;
4795 fe_ion_fd_config_control[0].private_value = rtd->dai_link->id;
4796 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004797 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304798 fe_ion_fd_config_control,
4799 ARRAY_SIZE(fe_ion_fd_config_control));
4800 if (ret < 0)
4801 pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
4802
4803 kfree(mixer_str);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304804 return ret;
4805}
4806
4807static int msm_compr_add_event_ack_cmd_control(struct snd_soc_pcm_runtime *rtd)
4808{
Meng Wangee084a02018-09-04 16:11:58 +08004809 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304810 const char *mixer_ctl_name = "Playback Event Ack";
4811 const char *deviceNo = "NN";
4812 char *mixer_str = NULL;
4813 int ctl_len = 0, ret = 0;
4814 struct snd_kcontrol_new fe_event_ack_config_control[1] = {
4815 {
4816 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4817 .name = "?",
4818 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4819 .info = msm_adsp_stream_cmd_info,
4820 .put = msm_compr_rtic_event_ack_put,
4821 .private_value = 0,
4822 }
4823 };
4824
4825 if (!rtd) {
4826 pr_err("%s NULL rtd\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08004827 return -EINVAL;
4828 }
4829
4830 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4831 if (!component) {
4832 pr_err("%s: component is NULL\n", __func__);
4833 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304834 }
4835
4836 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4837 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08004838 if (!mixer_str)
4839 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304840
4841 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4842 fe_event_ack_config_control[0].name = mixer_str;
4843 fe_event_ack_config_control[0].private_value = rtd->dai_link->id;
4844 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004845 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304846 fe_event_ack_config_control,
4847 ARRAY_SIZE(fe_event_ack_config_control));
4848 if (ret < 0)
4849 pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
4850
4851 kfree(mixer_str);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304852 return ret;
4853}
4854
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304855static struct msm_pcm_channel_mixer *msm_compr_get_chmixer(
4856 struct msm_compr_pdata *pdata, u64 fe_id)
4857{
4858 if (!pdata) {
4859 pr_err("%s: missing pdata\n", __func__);
4860 return NULL;
4861 }
4862
4863 if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
4864 pr_err("%s: invalid FE %llu\n", __func__, fe_id);
4865 return NULL;
4866 }
4867
4868 return pdata->chmixer_pspd[fe_id];
4869}
4870
4871static int msm_compr_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol,
4872 struct snd_ctl_elem_value *ucontrol)
4873{
4874 u64 fe_id = kcontrol->private_value & 0xFF;
4875 int session_type = (kcontrol->private_value >> 8) & 0xFF;
4876 int ret = 0, i = 0, stream_id = 0, be_id = 0;
4877 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4878 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4879 snd_soc_component_get_drvdata(comp);
4880 struct snd_compr_stream *cstream = NULL;
4881 struct msm_compr_audio *prtd = NULL;
4882 struct msm_pcm_channel_mixer *chmixer_pspd = NULL;
4883 u8 asm_ch_map[PCM_FORMAT_MAX_NUM_CHANNEL_V8] = {0};
4884 bool reset_override_out_ch_map = false;
4885 bool reset_override_in_ch_map = false;
4886
4887 if ((session_type != SESSION_TYPE_TX) &&
4888 (session_type != SESSION_TYPE_RX)) {
4889 pr_err("%s: invalid session type %d\n", __func__, session_type);
4890 return -EINVAL;
4891 }
4892
4893 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
4894 if (!chmixer_pspd) {
4895 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
4896 return -EINVAL;
4897 }
4898
4899 chmixer_pspd->enable = ucontrol->value.integer.value[0];
4900 chmixer_pspd->rule = ucontrol->value.integer.value[1];
4901 chmixer_pspd->input_channel = ucontrol->value.integer.value[2];
4902 chmixer_pspd->output_channel = ucontrol->value.integer.value[3];
4903 chmixer_pspd->port_idx = ucontrol->value.integer.value[4];
4904
Erin Yan2f81be22019-04-29 13:42:57 +08004905 if (chmixer_pspd->input_channel < 0 ||
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05304906 chmixer_pspd->input_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8 ||
Erin Yan2f81be22019-04-29 13:42:57 +08004907 chmixer_pspd->output_channel < 0 ||
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05304908 chmixer_pspd->output_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
4909 pr_err("%s: Invalid channels, in %d, out %d\n",
4910 __func__, chmixer_pspd->input_channel,
4911 chmixer_pspd->output_channel);
4912 return -EINVAL;
4913 }
4914
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304915 if (chmixer_pspd->enable) {
4916 if (session_type == SESSION_TYPE_RX &&
4917 !chmixer_pspd->override_in_ch_map) {
4918 if (pdata->ch_map[fe_id]->set_ch_map) {
4919 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4920 chmixer_pspd->in_ch_map[i] =
4921 pdata->ch_map[fe_id]->channel_map[i];
4922 } else {
4923 q6asm_map_channels(asm_ch_map,
4924 chmixer_pspd->input_channel, false);
4925 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4926 chmixer_pspd->in_ch_map[i] = asm_ch_map[i];
4927 }
4928 chmixer_pspd->override_in_ch_map = true;
4929 reset_override_in_ch_map = true;
4930 } else if (session_type == SESSION_TYPE_TX &&
4931 !chmixer_pspd->override_out_ch_map) {
4932 if (pdata->ch_map[fe_id]->set_ch_map) {
4933 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4934 chmixer_pspd->out_ch_map[i] =
4935 pdata->ch_map[fe_id]->channel_map[i];
4936 } else {
4937 q6asm_map_channels(asm_ch_map,
4938 chmixer_pspd->output_channel, false);
4939 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4940 chmixer_pspd->out_ch_map[i] = asm_ch_map[i];
4941 }
4942 chmixer_pspd->override_out_ch_map = true;
4943 reset_override_out_ch_map = true;
4944 }
4945 } else {
4946 chmixer_pspd->override_out_ch_map = false;
4947 chmixer_pspd->override_in_ch_map = false;
4948 }
4949
4950 /* cache value and take effect during adm_open stage */
4951 msm_pcm_routing_set_channel_mixer_cfg(fe_id,
4952 session_type,
4953 chmixer_pspd);
4954
4955 cstream = pdata->cstream[fe_id];
4956 if (chmixer_pspd->enable && cstream && cstream->runtime) {
4957 prtd = cstream->runtime->private_data;
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304958
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05304959 if (prtd && prtd->audio_client) {
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304960 stream_id = prtd->audio_client->session;
4961 be_id = chmixer_pspd->port_idx;
Erin Yan2f81be22019-04-29 13:42:57 +08004962 msm_pcm_routing_set_channel_mixer_runtime(be_id,
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304963 stream_id, session_type, chmixer_pspd);
4964 }
4965 }
4966
4967 if (reset_override_out_ch_map)
4968 chmixer_pspd->override_out_ch_map = false;
4969 if (reset_override_in_ch_map)
4970 chmixer_pspd->override_in_ch_map = false;
4971
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304972 return ret;
4973}
4974
4975static int msm_compr_channel_mixer_cfg_ctl_get(struct snd_kcontrol *kcontrol,
4976 struct snd_ctl_elem_value *ucontrol)
4977{
4978 u64 fe_id = kcontrol->private_value & 0xFF;
4979 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4980 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4981 snd_soc_component_get_drvdata(comp);
4982 struct msm_pcm_channel_mixer *chmixer_pspd;
4983
4984 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
4985 if (!chmixer_pspd) {
4986 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
4987 return -EINVAL;
4988 }
4989
4990 ucontrol->value.integer.value[0] = chmixer_pspd->enable;
4991 ucontrol->value.integer.value[1] = chmixer_pspd->rule;
4992 ucontrol->value.integer.value[2] = chmixer_pspd->input_channel;
4993 ucontrol->value.integer.value[3] = chmixer_pspd->output_channel;
4994 ucontrol->value.integer.value[4] = chmixer_pspd->port_idx;
4995 return 0;
4996}
4997
4998static int msm_compr_channel_mixer_output_map_ctl_put(
4999 struct snd_kcontrol *kcontrol,
5000 struct snd_ctl_elem_value *ucontrol)
5001{
5002 u64 fe_id = kcontrol->private_value & 0xFF;
5003 int i = 0;
5004 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5005 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5006 snd_soc_component_get_drvdata(comp);
5007 struct msm_pcm_channel_mixer *chmixer_pspd;
5008
5009 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5010 if (!chmixer_pspd) {
5011 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5012 return -EINVAL;
5013 }
5014
5015 chmixer_pspd->override_out_ch_map = true;
5016 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5017 chmixer_pspd->out_ch_map[i] =
5018 ucontrol->value.integer.value[i];
5019
5020 return 0;
5021}
5022
5023static int msm_compr_channel_mixer_output_map_ctl_get(
5024 struct snd_kcontrol *kcontrol,
5025 struct snd_ctl_elem_value *ucontrol)
5026{
5027 u64 fe_id = kcontrol->private_value & 0xFF;
5028 int i = 0;
5029 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5030 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5031 snd_soc_component_get_drvdata(comp);
5032 struct msm_pcm_channel_mixer *chmixer_pspd;
5033
5034 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5035 if (!chmixer_pspd) {
5036 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5037 return -EINVAL;
5038 }
5039
5040 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5041 ucontrol->value.integer.value[i] =
5042 chmixer_pspd->out_ch_map[i];
5043 return 0;
5044}
5045
5046static int msm_compr_channel_mixer_input_map_ctl_put(
5047 struct snd_kcontrol *kcontrol,
5048 struct snd_ctl_elem_value *ucontrol)
5049{
5050 u64 fe_id = kcontrol->private_value & 0xFF;
5051 int i = 0;
5052 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5053 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5054 snd_soc_component_get_drvdata(comp);
5055 struct msm_pcm_channel_mixer *chmixer_pspd;
5056
5057 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5058 if (!chmixer_pspd) {
5059 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5060 return -EINVAL;
5061 }
5062
5063 chmixer_pspd->override_in_ch_map = true;
5064 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5065 chmixer_pspd->in_ch_map[i] = ucontrol->value.integer.value[i];
5066
5067 return 0;
5068}
5069
5070static int msm_compr_channel_mixer_input_map_ctl_get(
5071 struct snd_kcontrol *kcontrol,
5072 struct snd_ctl_elem_value *ucontrol)
5073{
5074 u64 fe_id = kcontrol->private_value & 0xFF;
5075 int i = 0;
5076 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5077 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5078 snd_soc_component_get_drvdata(comp);
5079 struct msm_pcm_channel_mixer *chmixer_pspd;
5080
5081 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5082 if (!chmixer_pspd) {
5083 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5084 return -EINVAL;
5085 }
5086
5087 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5088 ucontrol->value.integer.value[i] =
5089 chmixer_pspd->in_ch_map[i];
5090 return 0;
5091}
5092
5093static int msm_compr_channel_mixer_weight_ctl_put(
5094 struct snd_kcontrol *kcontrol,
5095 struct snd_ctl_elem_value *ucontrol)
5096{
5097 u64 fe_id = kcontrol->private_value & 0xFF;
5098 int channel = (kcontrol->private_value >> 16) & 0xFF;
5099 int i = 0;
5100 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5101 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5102 snd_soc_component_get_drvdata(comp);
5103 struct msm_pcm_channel_mixer *chmixer_pspd;
5104
5105 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5106 if (!chmixer_pspd) {
5107 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5108 return -EINVAL;
5109 }
5110
5111 if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
5112 pr_err("%s: invalid channel number %d\n", __func__, channel);
5113 return -EINVAL;
5114 }
5115 channel--;
5116
5117 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5118 chmixer_pspd->channel_weight[channel][i] =
5119 ucontrol->value.integer.value[i];
5120 return 0;
5121}
5122
5123static int msm_compr_channel_mixer_weight_ctl_get(
5124 struct snd_kcontrol *kcontrol,
5125 struct snd_ctl_elem_value *ucontrol)
5126{
5127 u64 fe_id = kcontrol->private_value & 0xFF;
5128 int channel = (kcontrol->private_value >> 16) & 0xFF;
5129 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5130 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5131 snd_soc_component_get_drvdata(comp);
5132 int i = 0;
5133 struct msm_pcm_channel_mixer *chmixer_pspd;
5134
5135 if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
5136 pr_err("%s: invalid channel number %d\n", __func__, channel);
5137 return -EINVAL;
5138 }
5139 channel--;
5140
5141 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5142 if (!chmixer_pspd) {
5143 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5144 return -EINVAL;
5145 }
5146
5147 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5148 ucontrol->value.integer.value[i] =
5149 chmixer_pspd->channel_weight[channel][i];
5150 return 0;
5151}
5152
5153static int msm_compr_add_platform_controls(struct snd_kcontrol_new *kctl,
5154 struct snd_soc_pcm_runtime *rtd, const char *name_prefix,
5155 const char *name_suffix, int session_type, int channels)
5156{
5157 int ret = -EINVAL;
5158 char *mixer_name = NULL;
5159 const char *deviceNo = "NN";
5160 const char *channelNo = "NN";
5161 int ctl_len = 0;
5162 struct snd_soc_component *component = NULL;
5163
5164 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
5165 if (!component) {
5166 pr_err("%s: component is NULL\n", __func__);
5167 return -EINVAL;
5168 }
5169
5170 ctl_len = strlen(name_prefix) + 1 + strlen(deviceNo) + 1 +
5171 strlen(channelNo) + 1 + strlen(name_suffix) + 1;
5172
5173 mixer_name = kzalloc(ctl_len, GFP_KERNEL);
5174 if (mixer_name == NULL)
5175 return -ENOMEM;
5176
5177 if (channels >= 0) {
5178 snprintf(mixer_name, ctl_len, "%s %d %s %d",
5179 name_prefix, rtd->pcm->device, name_suffix, channels);
5180 kctl->private_value = (rtd->dai_link->id) | (channels << 16);
5181 } else {
5182 snprintf(mixer_name, ctl_len, "%s %d %s",
5183 name_prefix, rtd->pcm->device, name_suffix);
5184 kctl->private_value = (rtd->dai_link->id);
5185 }
5186 if (session_type != INVALID_SESSION)
5187 kctl->private_value |= (session_type << 8);
5188
5189 kctl->name = mixer_name;
5190 ret = snd_soc_add_component_controls(component, kctl, 1);
5191 kfree(mixer_name);
5192 return ret;
5193}
5194
5195static int msm_compr_channel_mixer_output_map_info(struct snd_kcontrol *kcontrol,
5196 struct snd_ctl_elem_info *uinfo)
5197{
5198 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5199 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
5200 /* Valid channel map value ranges from 1 to 64 */
5201 uinfo->value.integer.min = 1;
5202 uinfo->value.integer.max = 64;
5203 return 0;
5204}
5205
5206static int msm_compr_add_channel_mixer_output_map_controls(
5207 struct snd_soc_pcm_runtime *rtd)
5208{
5209 const char *playback_mixer_ctl_name = "AudStr";
5210 const char *capture_mixer_ctl_name = "AudStr Capture";
5211 const char *suffix = "ChMixer Output Map";
5212 const char *mixer_ctl_name = NULL;
5213 int ret = 0, session_type = INVALID_SESSION, channel = -1;
5214 struct snd_kcontrol_new channel_mixer_output_map_control = {
5215 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5216 .name = "?",
5217 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5218 .info = msm_compr_channel_mixer_output_map_info,
5219 .put = msm_compr_channel_mixer_output_map_ctl_put,
5220 .get = msm_compr_channel_mixer_output_map_ctl_get,
5221 .private_value = 0,
5222 };
5223
5224 mixer_ctl_name = rtd->compr->direction == SND_COMPRESS_PLAYBACK ?
5225 playback_mixer_ctl_name : capture_mixer_ctl_name ;
5226 ret = msm_compr_add_platform_controls(&channel_mixer_output_map_control,
5227 rtd, mixer_ctl_name, suffix, session_type, channel);
5228 if (ret < 0) {
5229 pr_err("%s: failed add platform ctl, err = %d\n",
5230 __func__, ret);
5231 }
5232
5233 return ret;
5234}
5235
5236static int msm_compr_channel_mixer_input_map_info(struct snd_kcontrol *kcontrol,
5237 struct snd_ctl_elem_info *uinfo)
5238{
5239 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5240 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
5241 /* Valid channel map value ranges from 1 to 64 */
5242 uinfo->value.integer.min = 1;
5243 uinfo->value.integer.max = 64;
5244 return 0;
5245}
5246
5247static int msm_compr_add_channel_mixer_input_map_controls(
5248 struct snd_soc_pcm_runtime *rtd)
5249{
5250 const char *playback_mixer_ctl_name = "AudStr";
5251 const char *capture_mixer_ctl_name = "AudStr Capture";
5252 const char *suffix = "ChMixer Input Map";
5253 const char *mixer_ctl_name = NULL;
5254 int ret = 0, session_type = INVALID_SESSION, channel = -1;
5255 struct snd_kcontrol_new channel_mixer_input_map_control = {
5256 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5257 .name = "?",
5258 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5259 .info = msm_compr_channel_mixer_input_map_info,
5260 .put = msm_compr_channel_mixer_input_map_ctl_put,
5261 .get = msm_compr_channel_mixer_input_map_ctl_get,
5262 .private_value = 0,
5263 };
5264
5265 mixer_ctl_name = rtd->compr->direction == SND_COMPRESS_PLAYBACK ?
5266 playback_mixer_ctl_name : capture_mixer_ctl_name ;
5267 ret = msm_compr_add_platform_controls(&channel_mixer_input_map_control,
5268 rtd, mixer_ctl_name, suffix, session_type, channel);
5269 if (ret < 0) {
5270 pr_err("%s: failed add platform ctl, err = %d\n",
5271 __func__, ret);
5272 }
5273
5274 return ret;
5275}
5276
5277static int msm_compr_channel_mixer_cfg_info(struct snd_kcontrol *kcontrol,
5278 struct snd_ctl_elem_info *uinfo)
5279{
5280 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5281 /* five int values: enable, rule, in_channels, out_channels and port_id */
5282 uinfo->count = 5;
5283 /* Valid range is all positive values to support above controls */
5284 uinfo->value.integer.min = 0;
5285 uinfo->value.integer.max = INT_MAX;
5286 return 0;
5287}
5288
5289static int msm_compr_add_channel_mixer_cfg_controls(
5290 struct snd_soc_pcm_runtime *rtd)
5291{
5292 const char *playback_mixer_ctl_name = "AudStr";
5293 const char *capture_mixer_ctl_name = "AudStr Capture";
5294 const char *suffix = "ChMixer Cfg";
5295 const char *mixer_ctl_name = NULL;
5296 int ret = 0, session_type = INVALID_SESSION, channel = -1;
5297 struct snd_kcontrol_new channel_mixer_cfg_control = {
5298 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5299 .name = "?",
5300 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5301 .info = msm_compr_channel_mixer_cfg_info,
5302 .put = msm_compr_channel_mixer_cfg_ctl_put,
5303 .get = msm_compr_channel_mixer_cfg_ctl_get,
5304 .private_value = 0,
5305 };
5306
5307 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
5308 session_type = SESSION_TYPE_RX;
5309 mixer_ctl_name = playback_mixer_ctl_name;
5310 } else {
5311 session_type = SESSION_TYPE_TX;
5312 mixer_ctl_name = capture_mixer_ctl_name;
5313 }
5314
5315 ret = msm_compr_add_platform_controls(&channel_mixer_cfg_control,
5316 rtd, mixer_ctl_name, suffix, session_type, channel);
5317 if (ret < 0) {
5318 pr_err("%s: failed add platform ctl, err = %d\n",
5319 __func__, ret);
5320 }
5321
5322 return ret;
5323}
5324
5325static int msm_compr_channel_mixer_weight_info(struct snd_kcontrol *kcontrol,
5326 struct snd_ctl_elem_info *uinfo)
5327{
5328 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5329 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
5330 /* Valid range: 0 to 0x4000(Unity) gain weightage */
5331 uinfo->value.integer.min = 0;
5332 uinfo->value.integer.max = 0x4000;
5333 return 0;
5334}
5335
5336static int msm_compr_add_channel_mixer_weight_controls(
5337 struct snd_soc_pcm_runtime *rtd,
5338 int channel)
5339{
5340 const char *playback_mixer_ctl_name = "AudStr";
5341 const char *capture_mixer_ctl_name = "AudStr Capture";
5342 const char *suffix = "ChMixer Weight Ch";
5343 const char *mixer_ctl_name = NULL;
5344 int ret = 0, session_type = INVALID_SESSION;
5345 struct snd_kcontrol_new channel_mixer_weight_control = {
5346 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5347 .name = "?",
5348 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5349 .info = msm_compr_channel_mixer_weight_info,
5350 .put = msm_compr_channel_mixer_weight_ctl_put,
5351 .get = msm_compr_channel_mixer_weight_ctl_get,
5352 .private_value = 0,
5353 };
5354
5355 mixer_ctl_name = rtd->compr->direction == SND_COMPRESS_PLAYBACK ?
5356 playback_mixer_ctl_name : capture_mixer_ctl_name ;
5357 ret = msm_compr_add_platform_controls(&channel_mixer_weight_control,
5358 rtd, mixer_ctl_name, suffix, session_type, channel);
5359 if (ret < 0) {
5360 pr_err("%s: failed add platform ctl, err = %d\n",
5361 __func__, ret);
5362 }
5363
5364 return ret;
5365}
5366
5367static int msm_compr_add_channel_mixer_controls(struct snd_soc_pcm_runtime *rtd)
5368{
5369 int i, ret = 0;
5370 struct msm_compr_pdata *pdata = NULL;
5371 struct snd_soc_component *component = NULL;
5372
5373 if (!rtd) {
5374 pr_err("%s NULL rtd\n", __func__);
5375 return -EINVAL;
5376 }
5377
5378 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
5379 if (!component) {
5380 pr_err("%s: component is NULL\n", __func__);
5381 return -EINVAL;
5382 }
5383
5384 pdata = (struct msm_compr_pdata *)
5385 snd_soc_component_get_drvdata(component);
5386 if (!pdata) {
5387 pr_err("%s: platform data not populated\n", __func__);
5388 return -EINVAL;
5389 }
5390
5391 if (!pdata->chmixer_pspd[rtd->dai_link->id]) {
5392 pdata->chmixer_pspd[rtd->dai_link->id] =
5393 kzalloc(sizeof(struct msm_pcm_channel_mixer), GFP_KERNEL);
5394 if (!pdata->chmixer_pspd[rtd->dai_link->id])
5395 return -ENOMEM;
5396 }
5397
5398 ret = msm_compr_add_channel_mixer_cfg_controls(rtd);
5399 if (ret) {
5400 pr_err("%s: pcm add channel mixer cfg controls failed:%d\n",
5401 __func__, ret);
5402 goto fail;
5403 }
5404 ret = msm_compr_add_channel_mixer_input_map_controls(rtd);
5405 if (ret) {
5406 pr_err("%s: pcm add channel mixer input map controls failed:%d\n",
5407 __func__, ret);
5408 goto fail;
5409 }
5410 ret = msm_compr_add_channel_mixer_output_map_controls(rtd);
5411 if (ret) {
5412 pr_err("%s: pcm add channel mixer output map controls failed:%d\n",
5413 __func__, ret);
5414 goto fail;
5415 }
5416
5417 for (i = 1; i <= PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++) {
5418 ret = msm_compr_add_channel_mixer_weight_controls(rtd, i);
5419 if (ret) {
5420 pr_err("%s: pcm add channel mixer weight controls failed:%d\n",
5421 __func__, ret);
5422 goto fail;
5423 }
5424 }
5425 return 0;
5426
5427fail:
5428 kfree(pdata->chmixer_pspd[rtd->dai_link->id]);
5429 pdata->chmixer_pspd[rtd->dai_link->id] = NULL;
5430 return ret;
5431}
5432
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305433static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
5434{
5435 int rc;
5436
5437 rc = msm_compr_add_volume_control(rtd);
5438 if (rc)
5439 pr_err("%s: Could not add Compr Volume Control\n", __func__);
5440
5441 rc = msm_compr_add_audio_effects_control(rtd);
5442 if (rc)
5443 pr_err("%s: Could not add Compr Audio Effects Control\n",
5444 __func__);
5445
5446 rc = msm_compr_add_audio_adsp_stream_cmd_control(rtd);
5447 if (rc)
5448 pr_err("%s: Could not add Compr ADSP Stream Cmd Control\n",
5449 __func__);
5450
5451 rc = msm_compr_add_audio_adsp_stream_callback_control(rtd);
5452 if (rc)
5453 pr_err("%s: Could not add Compr ADSP Stream Callback Control\n",
5454 __func__);
5455
5456 rc = msm_compr_add_io_fd_cmd_control(rtd);
5457 if (rc)
5458 pr_err("%s: Could not add Compr ion fd Control\n",
5459 __func__);
5460
5461 rc = msm_compr_add_event_ack_cmd_control(rtd);
5462 if (rc)
5463 pr_err("%s: Could not add Compr event ack Control\n",
5464 __func__);
5465
5466 rc = msm_compr_add_query_audio_effect_control(rtd);
5467 if (rc)
5468 pr_err("%s: Could not add Compr Query Audio Effect Control\n",
5469 __func__);
5470
5471 rc = msm_compr_add_dec_runtime_params_control(rtd);
5472 if (rc)
5473 pr_err("%s: Could not add Compr Dec runtime params Control\n",
5474 __func__);
5475 rc = msm_compr_add_app_type_cfg_control(rtd);
5476 if (rc)
5477 pr_err("%s: Could not add Compr App Type Cfg Control\n",
5478 __func__);
5479 rc = msm_compr_add_channel_map_control(rtd);
5480 if (rc)
5481 pr_err("%s: Could not add Compr Channel Map Control\n",
5482 __func__);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305483 rc = msm_compr_add_channel_mixer_controls(rtd);
5484 if (rc)
5485 pr_err("%s: Could not add Compr Channel Mixer Controls\n",
5486 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305487 return 0;
5488}
5489
5490static struct snd_compr_ops msm_compr_ops = {
5491 .open = msm_compr_open,
5492 .free = msm_compr_free,
5493 .trigger = msm_compr_trigger,
5494 .pointer = msm_compr_pointer,
5495 .set_params = msm_compr_set_params,
5496 .set_metadata = msm_compr_set_metadata,
5497 .get_metadata = msm_compr_get_metadata,
5498 .set_next_track_param = msm_compr_set_next_track_param,
5499 .ack = msm_compr_ack,
5500 .copy = msm_compr_copy,
5501 .get_caps = msm_compr_get_caps,
5502 .get_codec_caps = msm_compr_get_codec_caps,
5503};
5504
Meng Wangee084a02018-09-04 16:11:58 +08005505static struct snd_soc_component_driver msm_soc_component = {
5506 .name = DRV_NAME,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305507 .probe = msm_compr_probe,
5508 .compr_ops = &msm_compr_ops,
5509 .pcm_new = msm_compr_new,
5510};
5511
5512static int msm_compr_dev_probe(struct platform_device *pdev)
5513{
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305514 struct msm_compr_pdata *pdata = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305515
5516 pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305517 pdata = (struct msm_compr_pdata *)
5518 kzalloc(sizeof(*pdata), GFP_KERNEL);
5519 if (!pdata)
5520 return -ENOMEM;
Ajit Pandeyfa018862019-09-04 14:34:00 +05305521 mutex_init(&pdata->lock);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305522 dev_set_drvdata(&pdev->dev, pdata);
5523
Meng Wangee084a02018-09-04 16:11:58 +08005524 return snd_soc_register_component(&pdev->dev,
5525 &msm_soc_component, NULL, 0);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305526}
5527
5528static int msm_compr_remove(struct platform_device *pdev)
5529{
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305530 int i = 0;
5531 struct msm_compr_pdata *pdata = NULL;
5532
5533 pdata = dev_get_drvdata(&pdev->dev);
5534 if (pdata) {
5535 for (i = 0; i < MSM_FRONTEND_DAI_MM_SIZE; i++)
5536 kfree(pdata->chmixer_pspd[i]);
5537 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05305538 mutex_destroy(&pdata->lock);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305539 kfree(pdata);
5540
Meng Wangee084a02018-09-04 16:11:58 +08005541 snd_soc_unregister_component(&pdev->dev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305542 return 0;
5543}
5544
5545static const struct of_device_id msm_compr_dt_match[] = {
5546 {.compatible = "qcom,msm-compress-dsp"},
5547 {}
5548};
5549MODULE_DEVICE_TABLE(of, msm_compr_dt_match);
5550
5551static struct platform_driver msm_compr_driver = {
5552 .driver = {
5553 .name = "msm-compress-dsp",
5554 .owner = THIS_MODULE,
5555 .of_match_table = msm_compr_dt_match,
Xiaojun Sang53cd13a2018-06-29 15:14:37 +08005556 .suppress_bind_attrs = true,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305557 },
5558 .probe = msm_compr_dev_probe,
5559 .remove = msm_compr_remove,
5560};
5561
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305562int __init msm_compress_dsp_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305563{
5564 return platform_driver_register(&msm_compr_driver);
5565}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305566
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05305567void msm_compress_dsp_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305568{
5569 platform_driver_unregister(&msm_compr_driver);
5570}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305571
5572MODULE_DESCRIPTION("Compress Offload platform driver");
5573MODULE_LICENSE("GPL v2");