blob: 4890749186a507bc6ea9158bd2b2589500065f78 [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) &&
830 atomic_read(&prtd->drain)) {
831 pr_debug("RUN ack, wake up & continue pending drain\n");
832
833 if (prtd->last_buffer)
834 prtd->last_buffer = 0;
835
836 prtd->drain_ready = 1;
837 wake_up(&prtd->drain_wait);
838 atomic_set(&prtd->drain, 0);
839 }
840
841 spin_unlock_irqrestore(&prtd->lock, flags);
842 break;
843 case ASM_STREAM_CMD_FLUSH:
844 pr_debug("%s: ASM_STREAM_CMD_FLUSH:", __func__);
845 pr_debug("token 0x%x, stream id %d\n", token,
846 stream_id);
847 prtd->cmd_ack = 1;
848 break;
849 case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:
850 pr_debug("%s: ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:",
851 __func__);
852 pr_debug("token 0x%x, stream id = %d\n", token,
853 stream_id);
854 break;
855 case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
856 pr_debug("%s: ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:",
857 __func__);
858 pr_debug("token = 0x%x, stream id = %d\n", token,
859 stream_id);
860 break;
861 case ASM_STREAM_CMD_CLOSE:
862 pr_debug("%s: ASM_DATA_CMD_CLOSE:", __func__);
863 pr_debug("token 0x%x, stream id %d\n", token,
864 stream_id);
865 /*
866 * wakeup wait for stream avail on stream 3
867 * after stream 1 ends.
868 */
869 if (prtd->next_stream) {
870 pr_debug("%s:CLOSE:wakeup wait for stream\n",
871 __func__);
872 prtd->stream_available = 1;
873 wake_up(&prtd->wait_for_stream_avail);
874 prtd->next_stream = 0;
875 }
876 if (atomic_read(&prtd->close) &&
877 atomic_read(&prtd->wait_on_close)) {
878 prtd->cmd_ack = 1;
879 wake_up(&prtd->close_wait);
880 }
881 atomic_set(&prtd->close, 0);
882 break;
883 case ASM_STREAM_CMD_REGISTER_PP_EVENTS:
884 pr_debug("%s: ASM_STREAM_CMD_REGISTER_PP_EVENTS:",
885 __func__);
886 break;
887 default:
888 break;
889 }
890 break;
891 }
892 case ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3:
893 pr_debug("%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3\n",
894 __func__);
895 break;
896 case RESET_EVENTS:
897 pr_err("%s: Received reset events CB, move to error state",
898 __func__);
899 spin_lock_irqsave(&prtd->lock, flags);
900 /*
901 * Since ADSP is down, let this driver pretend that it copied
902 * all the bytes received, so that next write will be triggered
903 */
904 prtd->copied_total = prtd->bytes_received;
905 snd_compr_fragment_elapsed(cstream);
906 atomic_set(&prtd->error, 1);
907 wake_up(&prtd->drain_wait);
908 if (atomic_cmpxchg(&prtd->eos, 1, 0)) {
909 pr_debug("%s:unblock eos wait queues", __func__);
910 wake_up(&prtd->eos_wait);
911 }
912 spin_unlock_irqrestore(&prtd->lock, flags);
913 break;
914 default:
915 pr_debug("%s: Not Supported Event opcode[0x%x]\n",
916 __func__, opcode);
917 break;
918 }
919}
920
921static int msm_compr_get_partial_drain_delay(int frame_sz, int sample_rate)
922{
923 int delay_time_ms = 0;
924
925 delay_time_ms = ((DSP_NUM_OUTPUT_FRAME_BUFFERED * frame_sz * 1000) /
926 sample_rate) + DSP_PP_BUFFERING_IN_MSEC;
927 delay_time_ms = delay_time_ms > PARTIAL_DRAIN_ACK_EARLY_BY_MSEC ?
928 delay_time_ms - PARTIAL_DRAIN_ACK_EARLY_BY_MSEC : 0;
929
930 pr_debug("%s: frame_sz %d, sample_rate %d, partial drain delay %d\n",
931 __func__, frame_sz, sample_rate, delay_time_ms);
932 return delay_time_ms;
933}
934
935static void populate_codec_list(struct msm_compr_audio *prtd)
936{
937 pr_debug("%s\n", __func__);
938 prtd->compr_cap.direction = SND_COMPRESS_PLAYBACK;
939 prtd->compr_cap.min_fragment_size =
940 COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
941 prtd->compr_cap.max_fragment_size =
942 COMPR_PLAYBACK_MAX_FRAGMENT_SIZE;
943 prtd->compr_cap.min_fragments =
944 COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
945 prtd->compr_cap.max_fragments =
946 COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
947 prtd->compr_cap.num_codecs = 17;
948 prtd->compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
949 prtd->compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
950 prtd->compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
951 prtd->compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3;
952 prtd->compr_cap.codecs[4] = SND_AUDIOCODEC_MP2;
953 prtd->compr_cap.codecs[5] = SND_AUDIOCODEC_PCM;
954 prtd->compr_cap.codecs[6] = SND_AUDIOCODEC_WMA;
955 prtd->compr_cap.codecs[7] = SND_AUDIOCODEC_WMA_PRO;
956 prtd->compr_cap.codecs[8] = SND_AUDIOCODEC_FLAC;
957 prtd->compr_cap.codecs[9] = SND_AUDIOCODEC_VORBIS;
958 prtd->compr_cap.codecs[10] = SND_AUDIOCODEC_ALAC;
959 prtd->compr_cap.codecs[11] = SND_AUDIOCODEC_APE;
960 prtd->compr_cap.codecs[12] = SND_AUDIOCODEC_DTS;
961 prtd->compr_cap.codecs[13] = SND_AUDIOCODEC_DSD;
962 prtd->compr_cap.codecs[14] = SND_AUDIOCODEC_APTX;
963 prtd->compr_cap.codecs[15] = SND_AUDIOCODEC_TRUEHD;
964 prtd->compr_cap.codecs[16] = SND_AUDIOCODEC_IEC61937;
965}
966
967static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
968 int stream_id,
969 bool use_gapless_codec_options)
970{
971 struct snd_compr_runtime *runtime = cstream->runtime;
972 struct msm_compr_audio *prtd = runtime->private_data;
973 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Meng Wangee084a02018-09-04 16:11:58 +0800974 struct snd_soc_component *component =NULL;
975 struct msm_compr_pdata *pdata = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530976 struct asm_aac_cfg aac_cfg;
977 struct asm_wma_cfg wma_cfg;
978 struct asm_wmapro_cfg wma_pro_cfg;
979 struct asm_flac_cfg flac_cfg;
980 struct asm_vorbis_cfg vorbis_cfg;
981 struct asm_alac_cfg alac_cfg;
982 struct asm_ape_cfg ape_cfg;
983 struct asm_dsd_cfg dsd_cfg;
984 struct aptx_dec_bt_addr_cfg aptx_cfg;
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +0530985 struct asm_amrwbplus_cfg amrwbplus_cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530986 union snd_codec_options *codec_options;
987
988 int ret = 0;
989 uint16_t bit_width;
990 bool use_default_chmap = true;
991 char *chmap = NULL;
992 uint16_t sample_word_size;
993
994 pr_debug("%s: use_gapless_codec_options %d\n",
995 __func__, use_gapless_codec_options);
996
Meng Wangee084a02018-09-04 16:11:58 +0800997 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
998 if (!component) {
999 pr_err("%s: component is NULL\n", __func__);
1000 return -EINVAL;
1001 }
1002 pdata = snd_soc_component_get_drvdata(component);
1003
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301004 if (use_gapless_codec_options)
1005 codec_options = &(prtd->gapless_state.codec_options);
1006 else
1007 codec_options = &(prtd->codec_param.codec.options);
1008
1009 if (!codec_options) {
1010 pr_err("%s: codec_options is NULL\n", __func__);
1011 return -EINVAL;
1012 }
1013
1014 switch (prtd->codec) {
1015 case FORMAT_LINEAR_PCM:
1016 pr_debug("SND_AUDIOCODEC_PCM\n");
1017 if (pdata->ch_map[rtd->dai_link->id]) {
1018 use_default_chmap =
1019 !(pdata->ch_map[rtd->dai_link->id]->set_ch_map);
1020 chmap =
1021 pdata->ch_map[rtd->dai_link->id]->channel_map;
1022 }
1023
1024 switch (prtd->codec_param.codec.format) {
1025 case SNDRV_PCM_FORMAT_S32_LE:
1026 bit_width = 32;
1027 sample_word_size = 32;
1028 break;
1029 case SNDRV_PCM_FORMAT_S24_LE:
1030 bit_width = 24;
1031 sample_word_size = 32;
1032 break;
1033 case SNDRV_PCM_FORMAT_S24_3LE:
1034 bit_width = 24;
1035 sample_word_size = 24;
1036 break;
1037 case SNDRV_PCM_FORMAT_S16_LE:
1038 default:
1039 bit_width = 16;
1040 sample_word_size = 16;
1041 break;
1042 }
Dieter Lueckingceef9af2018-09-28 15:09:32 +02001043
1044 if (q6core_get_avcs_api_version_per_service(
1045 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1046 ADSP_ASM_API_VERSION_V2) {
1047 ret = q6asm_media_format_block_pcm_format_support_v5(
1048 prtd->audio_client,
1049 prtd->sample_rate,
1050 prtd->num_channels,
1051 bit_width, stream_id,
1052 use_default_chmap,
1053 chmap,
1054 sample_word_size,
1055 ASM_LITTLE_ENDIAN,
1056 DEFAULT_QF);
1057 } else {
1058 ret = q6asm_media_format_block_pcm_format_support_v4(
1059 prtd->audio_client,
1060 prtd->sample_rate,
1061 prtd->num_channels,
1062 bit_width, stream_id,
1063 use_default_chmap,
1064 chmap,
1065 sample_word_size,
1066 ASM_LITTLE_ENDIAN,
1067 DEFAULT_QF);
1068 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301069 if (ret < 0)
1070 pr_err("%s: CMD Format block failed\n", __func__);
1071
1072 break;
1073 case FORMAT_MP3:
1074 pr_debug("SND_AUDIOCODEC_MP3\n");
1075 /* no media format block needed */
1076 break;
1077 case FORMAT_MPEG4_AAC:
1078 pr_debug("SND_AUDIOCODEC_AAC\n");
1079 memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg));
1080 aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
1081 if (prtd->codec_param.codec.format ==
1082 SND_AUDIOSTREAMFORMAT_MP4ADTS)
1083 aac_cfg.format = 0x0;
1084 else if (prtd->codec_param.codec.format ==
1085 SND_AUDIOSTREAMFORMAT_MP4LATM)
1086 aac_cfg.format = 0x04;
1087 else
1088 aac_cfg.format = 0x03;
1089 aac_cfg.ch_cfg = prtd->num_channels;
1090 aac_cfg.sample_rate = prtd->sample_rate;
1091 ret = q6asm_stream_media_format_block_aac(prtd->audio_client,
1092 &aac_cfg, stream_id);
1093 if (ret < 0)
1094 pr_err("%s: CMD Format block failed\n", __func__);
1095 break;
1096 case FORMAT_AC3:
1097 pr_debug("SND_AUDIOCODEC_AC3\n");
1098 break;
1099 case FORMAT_EAC3:
1100 pr_debug("SND_AUDIOCODEC_EAC3\n");
1101 break;
1102 case FORMAT_WMA_V9:
1103 pr_debug("SND_AUDIOCODEC_WMA\n");
1104 memset(&wma_cfg, 0x0, sizeof(struct asm_wma_cfg));
1105 wma_cfg.format_tag = prtd->codec_param.codec.format;
1106 wma_cfg.ch_cfg = prtd->codec_param.codec.ch_in;
1107 wma_cfg.sample_rate = prtd->sample_rate;
1108 wma_cfg.avg_bytes_per_sec = codec_options->wma.avg_bit_rate/8;
1109 wma_cfg.block_align = codec_options->wma.super_block_align;
1110 wma_cfg.valid_bits_per_sample =
1111 codec_options->wma.bits_per_sample;
1112 wma_cfg.ch_mask = codec_options->wma.channelmask;
1113 wma_cfg.encode_opt = codec_options->wma.encodeopt;
1114 ret = q6asm_media_format_block_wma(prtd->audio_client,
1115 &wma_cfg, stream_id);
1116 if (ret < 0)
1117 pr_err("%s: CMD Format block failed\n", __func__);
1118 break;
1119 case FORMAT_WMA_V10PRO:
1120 pr_debug("SND_AUDIOCODEC_WMA_PRO\n");
1121 memset(&wma_pro_cfg, 0x0, sizeof(struct asm_wmapro_cfg));
1122 wma_pro_cfg.format_tag = prtd->codec_param.codec.format;
1123 wma_pro_cfg.ch_cfg = prtd->codec_param.codec.ch_in;
1124 wma_pro_cfg.sample_rate = prtd->sample_rate;
1125 wma_cfg.avg_bytes_per_sec = codec_options->wma.avg_bit_rate/8;
1126 wma_pro_cfg.block_align = codec_options->wma.super_block_align;
1127 wma_pro_cfg.valid_bits_per_sample =
1128 codec_options->wma.bits_per_sample;
1129 wma_pro_cfg.ch_mask = codec_options->wma.channelmask;
1130 wma_pro_cfg.encode_opt = codec_options->wma.encodeopt;
1131 wma_pro_cfg.adv_encode_opt = codec_options->wma.encodeopt1;
1132 wma_pro_cfg.adv_encode_opt2 = codec_options->wma.encodeopt2;
1133 ret = q6asm_media_format_block_wmapro(prtd->audio_client,
1134 &wma_pro_cfg, stream_id);
1135 if (ret < 0)
1136 pr_err("%s: CMD Format block failed\n", __func__);
1137 break;
1138 case FORMAT_MP2:
1139 pr_debug("%s: SND_AUDIOCODEC_MP2\n", __func__);
1140 break;
1141 case FORMAT_FLAC:
1142 pr_debug("%s: SND_AUDIOCODEC_FLAC\n", __func__);
1143 memset(&flac_cfg, 0x0, sizeof(struct asm_flac_cfg));
1144 flac_cfg.ch_cfg = prtd->num_channels;
1145 flac_cfg.sample_rate = prtd->sample_rate;
1146 flac_cfg.stream_info_present = 1;
1147 flac_cfg.sample_size = codec_options->flac_dec.sample_size;
1148 flac_cfg.min_blk_size = codec_options->flac_dec.min_blk_size;
1149 flac_cfg.max_blk_size = codec_options->flac_dec.max_blk_size;
1150 flac_cfg.max_frame_size =
1151 codec_options->flac_dec.max_frame_size;
1152 flac_cfg.min_frame_size =
1153 codec_options->flac_dec.min_frame_size;
1154
1155 ret = q6asm_stream_media_format_block_flac(prtd->audio_client,
1156 &flac_cfg, stream_id);
1157 if (ret < 0)
1158 pr_err("%s: CMD Format block failed ret %d\n",
1159 __func__, ret);
1160
1161 break;
1162 case FORMAT_VORBIS:
1163 pr_debug("%s: SND_AUDIOCODEC_VORBIS\n", __func__);
1164 memset(&vorbis_cfg, 0x0, sizeof(struct asm_vorbis_cfg));
1165 vorbis_cfg.bit_stream_fmt =
1166 codec_options->vorbis_dec.bit_stream_fmt;
1167
1168 ret = q6asm_stream_media_format_block_vorbis(
1169 prtd->audio_client, &vorbis_cfg,
1170 stream_id);
1171 if (ret < 0)
1172 pr_err("%s: CMD Format block failed ret %d\n",
1173 __func__, ret);
1174
1175 break;
1176 case FORMAT_ALAC:
1177 pr_debug("%s: SND_AUDIOCODEC_ALAC\n", __func__);
1178 memset(&alac_cfg, 0x0, sizeof(struct asm_alac_cfg));
1179 alac_cfg.num_channels = prtd->num_channels;
1180 alac_cfg.sample_rate = prtd->sample_rate;
1181 alac_cfg.frame_length = codec_options->alac.frame_length;
1182 alac_cfg.compatible_version =
1183 codec_options->alac.compatible_version;
1184 alac_cfg.bit_depth = codec_options->alac.bit_depth;
1185 alac_cfg.pb = codec_options->alac.pb;
1186 alac_cfg.mb = codec_options->alac.mb;
1187 alac_cfg.kb = codec_options->alac.kb;
1188 alac_cfg.max_run = codec_options->alac.max_run;
1189 alac_cfg.max_frame_bytes = codec_options->alac.max_frame_bytes;
1190 alac_cfg.avg_bit_rate = codec_options->alac.avg_bit_rate;
1191 alac_cfg.channel_layout_tag =
1192 codec_options->alac.channel_layout_tag;
1193
1194 ret = q6asm_media_format_block_alac(prtd->audio_client,
1195 &alac_cfg, stream_id);
1196 if (ret < 0)
1197 pr_err("%s: CMD Format block failed ret %d\n",
1198 __func__, ret);
1199 break;
1200 case FORMAT_APE:
1201 pr_debug("%s: SND_AUDIOCODEC_APE\n", __func__);
1202 memset(&ape_cfg, 0x0, sizeof(struct asm_ape_cfg));
1203 ape_cfg.num_channels = prtd->num_channels;
1204 ape_cfg.sample_rate = prtd->sample_rate;
1205 ape_cfg.compatible_version =
1206 codec_options->ape.compatible_version;
1207 ape_cfg.compression_level =
1208 codec_options->ape.compression_level;
1209 ape_cfg.format_flags = codec_options->ape.format_flags;
1210 ape_cfg.blocks_per_frame = codec_options->ape.blocks_per_frame;
1211 ape_cfg.final_frame_blocks =
1212 codec_options->ape.final_frame_blocks;
1213 ape_cfg.total_frames = codec_options->ape.total_frames;
1214 ape_cfg.bits_per_sample = codec_options->ape.bits_per_sample;
1215 ape_cfg.seek_table_present =
1216 codec_options->ape.seek_table_present;
1217
1218 ret = q6asm_media_format_block_ape(prtd->audio_client,
1219 &ape_cfg, stream_id);
1220
1221 if (ret < 0)
1222 pr_err("%s: CMD Format block failed ret %d\n",
1223 __func__, ret);
1224 break;
1225 case FORMAT_DTS:
1226 pr_debug("SND_AUDIOCODEC_DTS\n");
1227 /* no media format block needed */
1228 break;
1229 case FORMAT_DSD:
1230 pr_debug("%s: SND_AUDIOCODEC_DSD\n", __func__);
1231 memset(&dsd_cfg, 0x0, sizeof(struct asm_dsd_cfg));
1232 dsd_cfg.num_channels = prtd->num_channels;
1233 dsd_cfg.dsd_data_rate = prtd->sample_rate;
1234 dsd_cfg.num_version = 0;
1235 dsd_cfg.is_bitwise_big_endian = 1;
Sanjana Bc45335a2019-12-06 17:16:36 +05301236 dsd_cfg.dsd_channel_block_size = 1;
1237
1238 if (codec_options->dsd_dec.blk_size == DSD_BLOCK_SIZE_4)
1239 dsd_cfg.dsd_channel_block_size =
1240 codec_options->dsd_dec.blk_size;
1241
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301242 ret = q6asm_media_format_block_dsd(prtd->audio_client,
1243 &dsd_cfg, stream_id);
1244 if (ret < 0)
1245 pr_err("%s: CMD DSD Format block failed ret %d\n",
1246 __func__, ret);
1247 break;
1248 case FORMAT_TRUEHD:
1249 pr_debug("SND_AUDIOCODEC_TRUEHD\n");
1250 /* no media format block needed */
1251 break;
1252 case FORMAT_IEC61937:
1253 pr_debug("SND_AUDIOCODEC_IEC61937\n");
1254 ret = q6asm_media_format_block_iec(prtd->audio_client,
1255 prtd->sample_rate,
1256 prtd->num_channels);
1257 if (ret < 0)
1258 pr_err("%s: CMD IEC61937 Format block failed ret %d\n",
1259 __func__, ret);
1260 break;
1261 case FORMAT_APTX:
1262 pr_debug("SND_AUDIOCODEC_APTX\n");
1263 memset(&aptx_cfg, 0x0, sizeof(struct aptx_dec_bt_addr_cfg));
1264 ret = q6asm_stream_media_format_block_aptx_dec(
1265 prtd->audio_client,
1266 prtd->sample_rate,
1267 stream_id);
1268 if (ret >= 0) {
1269 aptx_cfg.nap = codec_options->aptx_dec.nap;
1270 aptx_cfg.uap = codec_options->aptx_dec.uap;
1271 aptx_cfg.lap = codec_options->aptx_dec.lap;
1272 q6asm_set_aptx_dec_bt_addr(prtd->audio_client,
1273 &aptx_cfg);
1274 } else {
1275 pr_err("%s: CMD Format block failed ret %d\n",
1276 __func__, ret);
1277 }
1278 break;
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +05301279 case FORMAT_AMRNB:
1280 pr_debug("SND_AUDIOCODEC_AMR\n");
1281 /* no media format block needed */
1282 break;
1283 case FORMAT_AMRWB:
1284 pr_debug("SND_AUDIOCODEC_AMRWB\n");
1285 /* no media format block needed */
1286 break;
1287 case FORMAT_AMR_WB_PLUS:
1288 pr_debug("SND_AUDIOCODEC_AMRWBPLUS\n");
1289 memset(&amrwbplus_cfg, 0x0, sizeof(struct asm_amrwbplus_cfg));
1290 amrwbplus_cfg.amr_frame_fmt =
1291 codec_options->amrwbplus.bit_stream_fmt;
1292 ret = q6asm_media_format_block_amrwbplus(
1293 prtd->audio_client,
1294 &amrwbplus_cfg);
1295 if (ret < 0)
1296 pr_err("%s: CMD AMRWBPLUS Format block failed ret %d\n",
1297 __func__, ret);
1298 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301299 default:
1300 pr_debug("%s, unsupported format, skip", __func__);
1301 break;
1302 }
1303 return ret;
1304}
1305
1306static int msm_compr_init_pp_params(struct snd_compr_stream *cstream,
1307 struct audio_client *ac)
1308{
1309 int ret = 0;
1310 struct asm_softvolume_params softvol = {
1311 .period = SOFT_VOLUME_PERIOD,
1312 .step = SOFT_VOLUME_STEP,
1313 .rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
1314 };
1315
1316 switch (ac->topology) {
1317 default:
1318 ret = q6asm_set_softvolume_v2(ac, &softvol,
1319 SOFT_VOLUME_INSTANCE_1);
1320 if (ret < 0)
1321 pr_err("%s: Send SoftVolume Param failed ret=%d\n",
1322 __func__, ret);
1323
1324 break;
1325 }
1326 return ret;
1327}
1328
1329static int msm_compr_configure_dsp_for_playback
1330 (struct snd_compr_stream *cstream)
1331{
1332 struct snd_compr_runtime *runtime = cstream->runtime;
1333 struct msm_compr_audio *prtd = runtime->private_data;
1334 struct snd_soc_pcm_runtime *soc_prtd = cstream->private_data;
1335 uint16_t bits_per_sample = 16;
1336 int dir = IN, ret = 0;
1337 struct audio_client *ac = prtd->audio_client;
1338 uint32_t stream_index;
1339 struct asm_softpause_params softpause = {
1340 .enable = SOFT_PAUSE_ENABLE,
1341 .period = SOFT_PAUSE_PERIOD,
1342 .step = SOFT_PAUSE_STEP,
1343 .rampingcurve = SOFT_PAUSE_CURVE_LINEAR,
1344 };
1345 struct asm_softvolume_params softvol = {
1346 .period = SOFT_VOLUME_PERIOD,
1347 .step = SOFT_VOLUME_STEP,
1348 .rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
1349 };
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05301350 struct snd_kcontrol *kctl;
1351 struct snd_ctl_elem_value kctl_elem_value;
1352 uint16_t target_asm_bit_width = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301353
1354 pr_debug("%s: stream_id %d\n", __func__, ac->stream_id);
1355 stream_index = STREAM_ARRAY_INDEX(ac->stream_id);
1356 if (stream_index >= MAX_NUMBER_OF_STREAMS || stream_index < 0) {
1357 pr_err("%s: Invalid stream index:%d", __func__, stream_index);
1358 return -EINVAL;
1359 }
1360
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05301361 kctl = snd_soc_card_get_kcontrol(soc_prtd->card,
1362 DSP_BIT_WIDTH_MIXER_CTL);
1363 if (kctl) {
1364 kctl->get(kctl, &kctl_elem_value);
1365 target_asm_bit_width = kctl_elem_value.value.integer.value[0];
1366 if (target_asm_bit_width > 0) {
1367 pr_debug("%s enforce ASM bitwidth to %d from %d\n",
1368 __func__,
1369 target_asm_bit_width,
1370 bits_per_sample);
1371 bits_per_sample = target_asm_bit_width;
1372 }
1373 } else {
1374 pr_info("%s: failed to get mixer ctl for %s.\n",
1375 __func__, DSP_BIT_WIDTH_MIXER_CTL);
1376 }
1377
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301378 if ((prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_LE) ||
1379 (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_3LE))
1380 bits_per_sample = 24;
1381 else if (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S32_LE)
1382 bits_per_sample = 32;
1383
1384 if (prtd->compr_passthr != LEGACY_PCM) {
1385 ret = q6asm_open_write_compressed(ac, prtd->codec,
1386 prtd->compr_passthr);
1387 if (ret < 0) {
1388 pr_err("%s:ASM open write err[%d] for compr_type[%d]\n",
1389 __func__, ret, prtd->compr_passthr);
1390 return ret;
1391 }
1392 prtd->gapless_state.stream_opened[stream_index] = 1;
1393
1394 ret = msm_pcm_routing_reg_phy_compr_stream(
1395 soc_prtd->dai_link->id,
1396 ac->perf_mode,
1397 prtd->session_id,
1398 SNDRV_PCM_STREAM_PLAYBACK,
1399 prtd->compr_passthr);
1400 if (ret) {
1401 pr_err("%s: compr stream reg failed:%d\n", __func__,
1402 ret);
1403 return ret;
1404 }
1405 } else {
1406 pr_debug("%s: stream_id %d bits_per_sample %d\n",
1407 __func__, ac->stream_id, bits_per_sample);
Dieter Lueckingceef9af2018-09-28 15:09:32 +02001408
1409 if (q6core_get_avcs_api_version_per_service(
1410 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1411 ADSP_ASM_API_VERSION_V2)
1412 ret = q6asm_stream_open_write_v5(ac,
1413 prtd->codec, bits_per_sample,
1414 ac->stream_id,
1415 prtd->gapless_state.use_dsp_gapless_mode);
1416 else
1417 ret = q6asm_stream_open_write_v4(ac,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301418 prtd->codec, bits_per_sample,
1419 ac->stream_id,
1420 prtd->gapless_state.use_dsp_gapless_mode);
1421 if (ret < 0) {
1422 pr_err("%s:ASM open write err[%d] for compr type[%d]\n",
1423 __func__, ret, prtd->compr_passthr);
1424 return -ENOMEM;
1425 }
1426 prtd->gapless_state.stream_opened[stream_index] = 1;
1427
1428 pr_debug("%s: BE id %d\n", __func__, soc_prtd->dai_link->id);
1429 ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->id,
1430 ac->perf_mode,
1431 prtd->session_id,
1432 SNDRV_PCM_STREAM_PLAYBACK);
1433 if (ret) {
1434 pr_err("%s: stream reg failed:%d\n", __func__, ret);
1435 return ret;
1436 }
1437 }
1438
1439 ret = msm_compr_set_volume(cstream, 0, 0);
1440 if (ret < 0)
1441 pr_err("%s : Set Volume failed : %d", __func__, ret);
1442
1443 if (prtd->compr_passthr != LEGACY_PCM) {
1444 pr_debug("%s : Don't send cal and PP params for compress path",
1445 __func__);
1446 } else {
1447 ret = q6asm_send_cal(ac);
1448 if (ret < 0)
1449 pr_debug("%s : Send cal failed : %d", __func__, ret);
1450
1451 ret = q6asm_set_softpause(ac, &softpause);
1452 if (ret < 0)
1453 pr_err("%s: Send SoftPause Param failed ret=%d\n",
1454 __func__, ret);
1455
1456 ret = q6asm_set_softvolume(ac, &softvol);
1457 if (ret < 0)
1458 pr_err("%s: Send SoftVolume Param failed ret=%d\n",
1459 __func__, ret);
1460 }
1461 ret = q6asm_set_io_mode(ac, (COMPRESSED_STREAM_IO | ASYNC_IO_MODE));
1462 if (ret < 0) {
1463 pr_err("%s: Set IO mode failed\n", __func__);
1464 return -EINVAL;
1465 }
1466
1467 runtime->fragments = prtd->codec_param.buffer.fragments;
1468 runtime->fragment_size = prtd->codec_param.buffer.fragment_size;
1469 pr_debug("allocate %d buffers each of size %d\n",
1470 runtime->fragments,
1471 runtime->fragment_size);
1472 ret = q6asm_audio_client_buf_alloc_contiguous(dir, ac,
1473 runtime->fragment_size,
1474 runtime->fragments);
1475 if (ret < 0) {
1476 pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
1477 return -ENOMEM;
1478 }
1479
1480 prtd->byte_offset = 0;
1481 prtd->copied_total = 0;
1482 prtd->app_pointer = 0;
1483 prtd->bytes_received = 0;
1484 prtd->bytes_sent = 0;
1485 prtd->buffer = ac->port[dir].buf[0].data;
1486 prtd->buffer_paddr = ac->port[dir].buf[0].phys;
1487 prtd->buffer_size = runtime->fragments * runtime->fragment_size;
1488
1489 /* Bit-0 of flags represent timestamp mode */
1490 if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG)
1491 prtd->ts_header_offset = sizeof(struct snd_codec_metadata);
1492 else
1493 prtd->ts_header_offset = 0;
1494
1495 ret = msm_compr_send_media_format_block(cstream, ac->stream_id, false);
1496 if (ret < 0)
1497 pr_err("%s, failed to send media format block\n", __func__);
1498
1499 return ret;
1500}
1501
1502static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
1503{
1504 struct snd_compr_runtime *runtime = cstream->runtime;
1505 struct msm_compr_audio *prtd = runtime->private_data;
1506 struct snd_soc_pcm_runtime *soc_prtd = cstream->private_data;
1507 uint16_t bits_per_sample;
1508 uint16_t sample_word_size;
1509 int dir = OUT, ret = 0;
1510 struct audio_client *ac = prtd->audio_client;
1511 uint32_t stream_index;
Vikram Pandurangac712c172017-11-17 17:36:49 -08001512 uint32_t enc_cfg_id = ENC_CFG_ID_NONE;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301513
1514 switch (prtd->codec_param.codec.format) {
1515 case SNDRV_PCM_FORMAT_S24_LE:
1516 bits_per_sample = 24;
1517 sample_word_size = 32;
1518 break;
1519 case SNDRV_PCM_FORMAT_S24_3LE:
1520 bits_per_sample = 24;
1521 sample_word_size = 24;
1522 break;
1523 case SNDRV_PCM_FORMAT_S32_LE:
1524 bits_per_sample = 32;
1525 sample_word_size = 32;
1526 break;
1527 case SNDRV_PCM_FORMAT_S16_LE:
1528 default:
1529 bits_per_sample = 16;
1530 sample_word_size = 16;
Vikram Pandurangac712c172017-11-17 17:36:49 -08001531 if (prtd->codec == FORMAT_BESPOKE)
1532 enc_cfg_id =
1533 prtd->codec_param.codec.options.generic.reserved[0];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301534 break;
1535 }
1536
Ralf Herz22573552018-06-20 11:30:58 +02001537 pr_debug("%s: stream_id %d bits_per_sample %d compr_passthr %d\n",
1538 __func__, ac->stream_id, bits_per_sample,
1539 prtd->compr_passthr);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301540
Ralf Herz22573552018-06-20 11:30:58 +02001541 if (prtd->compr_passthr != LEGACY_PCM) {
1542 ret = q6asm_open_read_compressed(prtd->audio_client,
1543 prtd->codec, prtd->compr_passthr);
1544 if (ret < 0) {
1545 pr_err("%s:ASM open read err[%d] for compr_type[%d]\n",
1546 __func__, ret, prtd->compr_passthr);
1547 return ret;
1548 }
1549
1550 ret = msm_pcm_routing_reg_phy_compr_stream(
1551 soc_prtd->dai_link->id,
1552 ac->perf_mode,
1553 prtd->session_id,
1554 SNDRV_PCM_STREAM_CAPTURE,
1555 prtd->compr_passthr);
1556 if (ret) {
1557 pr_err("%s: compr stream reg failed:%d\n",
1558 __func__, ret);
1559 return ret;
1560 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301561 } else {
Ralf Herz22573552018-06-20 11:30:58 +02001562 if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG) {
1563 ret = q6asm_open_read_v4(prtd->audio_client,
1564 prtd->codec,
1565 bits_per_sample, true, enc_cfg_id);
1566 } else {
Chaithanya Krishna Bacharaju61b2de62019-06-20 11:40:17 +05301567 if (q6core_get_avcs_api_version_per_service(
1568 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1569 ADSP_ASM_API_VERSION_V2)
1570 ret = q6asm_open_read_v5(prtd->audio_client,
1571 prtd->codec, bits_per_sample,
1572 false, enc_cfg_id);
1573 else
1574 ret = q6asm_open_read_v4(prtd->audio_client,
1575 prtd->codec, bits_per_sample,
1576 false, enc_cfg_id);
Ralf Herz22573552018-06-20 11:30:58 +02001577 }
1578 if (ret < 0) {
1579 pr_err("%s: q6asm_open_read failed:%d\n",
1580 __func__, ret);
1581 return ret;
1582 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301583
Ralf Herz22573552018-06-20 11:30:58 +02001584 ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->id,
1585 ac->perf_mode,
1586 prtd->session_id,
1587 SNDRV_PCM_STREAM_CAPTURE);
1588 if (ret) {
1589 pr_err("%s: stream reg failed:%d\n", __func__, ret);
1590 return ret;
1591 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301592 }
1593
1594 ret = q6asm_set_io_mode(ac, (COMPRESSED_STREAM_IO | ASYNC_IO_MODE));
1595 if (ret < 0) {
1596 pr_err("%s: Set IO mode failed\n", __func__);
1597 return -EINVAL;
1598 }
1599
1600 stream_index = STREAM_ARRAY_INDEX(ac->stream_id);
1601 if (stream_index >= MAX_NUMBER_OF_STREAMS || stream_index < 0) {
1602 pr_err("%s: Invalid stream index:%d", __func__, stream_index);
1603 return -EINVAL;
1604 }
1605
1606 runtime->fragments = prtd->codec_param.buffer.fragments;
1607 runtime->fragment_size = prtd->codec_param.buffer.fragment_size;
1608 pr_debug("%s: allocate %d buffers each of size %d\n",
1609 __func__, runtime->fragments,
1610 runtime->fragment_size);
1611 ret = q6asm_audio_client_buf_alloc_contiguous(dir, ac,
1612 runtime->fragment_size,
1613 runtime->fragments);
1614 if (ret < 0) {
1615 pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
1616 return -ENOMEM;
1617 }
1618
1619 prtd->byte_offset = 0;
1620 prtd->received_total = 0;
1621 prtd->app_pointer = 0;
1622 prtd->bytes_copied = 0;
1623 prtd->bytes_read = 0;
1624 prtd->bytes_read_offset = 0;
1625 prtd->buffer = ac->port[dir].buf[0].data;
1626 prtd->buffer_paddr = ac->port[dir].buf[0].phys;
1627 prtd->buffer_size = runtime->fragments * runtime->fragment_size;
1628
1629 /* Bit-0 of flags represent timestamp mode */
1630 if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG)
1631 prtd->ts_header_offset = sizeof(struct snd_codec_metadata);
1632 else
1633 prtd->ts_header_offset = 0;
1634
1635 pr_debug("%s: sample_rate = %d channels = %d bps = %d sample_word_size = %d\n",
1636 __func__, prtd->sample_rate, prtd->num_channels,
1637 bits_per_sample, sample_word_size);
Vikram Pandurangac712c172017-11-17 17:36:49 -08001638 if (prtd->codec == FORMAT_BESPOKE) {
1639 /*
1640 * For BESPOKE codec, encoder specific config params are
1641 * included as part of generic.
1642 */
1643 ret = q6asm_enc_cfg_blk_custom(prtd->audio_client, prtd->sample_rate,
1644 prtd->num_channels, prtd->codec,
1645 (void *)&prtd->codec_param.codec.options.generic);
Ralf Herz22573552018-06-20 11:30:58 +02001646 } else if (prtd->compr_passthr == LEGACY_PCM) {
Chaithanya Krishna Bacharaju61b2de62019-06-20 11:40:17 +05301647 if (q6core_get_avcs_api_version_per_service(
1648 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1649 ADSP_ASM_API_VERSION_V2)
1650 ret = q6asm_enc_cfg_blk_pcm_format_support_v5(
1651 prtd->audio_client,
1652 prtd->sample_rate, prtd->num_channels,
1653 bits_per_sample, sample_word_size,
1654 ASM_LITTLE_ENDIAN, DEFAULT_QF);
1655 else
1656 ret = q6asm_enc_cfg_blk_pcm_format_support_v4(
1657 prtd->audio_client,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301658 prtd->sample_rate, prtd->num_channels,
Sachin Mohan Gadag7c944232018-01-04 11:04:00 +05301659 bits_per_sample, sample_word_size,
1660 ASM_LITTLE_ENDIAN, DEFAULT_QF);
Vikram Pandurangac712c172017-11-17 17:36:49 -08001661 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301662
1663 return ret;
1664}
1665
1666static int msm_compr_playback_open(struct snd_compr_stream *cstream)
1667{
1668 struct snd_compr_runtime *runtime = cstream->runtime;
1669 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Meng Wangee084a02018-09-04 16:11:58 +08001670 struct snd_soc_component *component = NULL;
Aditya Bavanari9deef912017-11-20 13:31:31 +05301671 struct msm_compr_audio *prtd = NULL;
Meng Wangee084a02018-09-04 16:11:58 +08001672 struct msm_compr_pdata *pdata = NULL;
Ramprasad Katkam17f05162019-04-15 18:37:10 +05301673 enum apr_subsys_state subsys_state;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301674
1675 pr_debug("%s\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08001676 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
1677 if (!component) {
1678 pr_err("%s: component is NULL\n", __func__);
1679 return -EINVAL;
1680 }
1681 pdata = snd_soc_component_get_drvdata(component);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301682 if (pdata->is_in_use[rtd->dai_link->id] == true) {
1683 pr_err("%s: %s is already in use, err: %d\n",
1684 __func__, rtd->dai_link->cpu_dai_name, -EBUSY);
1685 return -EBUSY;
1686 }
Ramprasad Katkam17f05162019-04-15 18:37:10 +05301687
1688 subsys_state = apr_get_subsys_state();
1689 if (subsys_state == APR_SUBSYS_DOWN) {
1690 pr_debug("%s: adsp is down\n", __func__);
1691 return -ENETRESET;
1692 }
1693
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301694 prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL);
1695 if (prtd == NULL) {
1696 pr_err("Failed to allocate memory for msm_compr_audio\n");
1697 return -ENOMEM;
1698 }
1699
1700 runtime->private_data = NULL;
1701 prtd->cstream = cstream;
1702 pdata->cstream[rtd->dai_link->id] = cstream;
1703 pdata->audio_effects[rtd->dai_link->id] =
1704 kzalloc(sizeof(struct msm_compr_audio_effects), GFP_KERNEL);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301705 if (pdata->audio_effects[rtd->dai_link->id] == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301706 pr_err("%s: Could not allocate memory for effects\n", __func__);
1707 pdata->cstream[rtd->dai_link->id] = NULL;
1708 kfree(prtd);
1709 return -ENOMEM;
1710 }
1711 pdata->dec_params[rtd->dai_link->id] =
1712 kzalloc(sizeof(struct msm_compr_dec_params), GFP_KERNEL);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301713 if (pdata->dec_params[rtd->dai_link->id] == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301714 pr_err("%s: Could not allocate memory for dec params\n",
1715 __func__);
1716 kfree(pdata->audio_effects[rtd->dai_link->id]);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301717 pdata->audio_effects[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301718 pdata->cstream[rtd->dai_link->id] = NULL;
1719 kfree(prtd);
1720 return -ENOMEM;
1721 }
1722 prtd->codec = FORMAT_MP3;
1723 prtd->bytes_received = 0;
1724 prtd->bytes_sent = 0;
1725 prtd->copied_total = 0;
1726 prtd->byte_offset = 0;
1727 prtd->sample_rate = 44100;
1728 prtd->num_channels = 2;
1729 prtd->drain_ready = 0;
1730 prtd->last_buffer = 0;
1731 prtd->first_buffer = 1;
1732 prtd->partial_drain_delay = 0;
1733 prtd->next_stream = 0;
1734 memset(&prtd->gapless_state, 0, sizeof(struct msm_compr_gapless_state));
1735 /*
1736 * Update the use_dsp_gapless_mode from gapless struture with the value
1737 * part of platform data.
1738 */
1739 prtd->gapless_state.use_dsp_gapless_mode = pdata->use_dsp_gapless_mode;
1740
1741 pr_debug("%s: gapless mode %d", __func__, pdata->use_dsp_gapless_mode);
1742
1743 spin_lock_init(&prtd->lock);
1744
1745 atomic_set(&prtd->eos, 0);
1746 atomic_set(&prtd->start, 0);
1747 atomic_set(&prtd->drain, 0);
1748 atomic_set(&prtd->xrun, 0);
1749 atomic_set(&prtd->close, 0);
1750 atomic_set(&prtd->wait_on_close, 0);
1751 atomic_set(&prtd->error, 0);
1752
1753 init_waitqueue_head(&prtd->eos_wait);
1754 init_waitqueue_head(&prtd->drain_wait);
1755 init_waitqueue_head(&prtd->close_wait);
1756 init_waitqueue_head(&prtd->wait_for_stream_avail);
1757
1758 runtime->private_data = prtd;
1759 populate_codec_list(prtd);
1760 prtd->audio_client = q6asm_audio_client_alloc(
1761 (app_cb)compr_event_handler, prtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301762 if (prtd->audio_client == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301763 pr_err("%s: Could not allocate memory for client\n", __func__);
1764 kfree(pdata->audio_effects[rtd->dai_link->id]);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301765 pdata->audio_effects[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301766 kfree(pdata->dec_params[rtd->dai_link->id]);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301767 pdata->dec_params[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301768 pdata->cstream[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301769 kfree(prtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301770 runtime->private_data = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301771 return -ENOMEM;
1772 }
1773 pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
1774 prtd->audio_client->perf_mode = false;
1775 prtd->session_id = prtd->audio_client->session;
1776 msm_adsp_init_mixer_ctl_pp_event_queue(rtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301777 pdata->is_in_use[rtd->dai_link->id] = true;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301778 return 0;
1779}
1780
1781static int msm_compr_capture_open(struct snd_compr_stream *cstream)
1782{
1783 struct snd_compr_runtime *runtime = cstream->runtime;
1784 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Meng Wangee084a02018-09-04 16:11:58 +08001785 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301786 struct msm_compr_audio *prtd;
Meng Wangee084a02018-09-04 16:11:58 +08001787 struct msm_compr_pdata *pdata = NULL;
Ramprasad Katkam17f05162019-04-15 18:37:10 +05301788 enum apr_subsys_state subsys_state;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301789
1790 pr_debug("%s\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08001791 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
1792 if (!component) {
1793 pr_err("%s: component is NULL\n", __func__);
1794 return -EINVAL;
1795 }
1796 pdata = snd_soc_component_get_drvdata(component);
1797 if (!pdata) {
1798 pr_err("%s: pdata is NULL\n", __func__);
1799 return -EINVAL;
1800 }
Ramprasad Katkam17f05162019-04-15 18:37:10 +05301801
1802 subsys_state = apr_get_subsys_state();
1803 if (subsys_state == APR_SUBSYS_DOWN) {
1804 pr_debug("%s: adsp is down\n", __func__);
1805 return -ENETRESET;
1806 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301807 prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08001808 if (!prtd) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301809 pr_err("Failed to allocate memory for msm_compr_audio\n");
1810 return -ENOMEM;
1811 }
1812
1813 runtime->private_data = NULL;
1814 prtd->cstream = cstream;
1815 pdata->cstream[rtd->dai_link->id] = cstream;
1816
1817 prtd->audio_client = q6asm_audio_client_alloc(
1818 (app_cb)compr_event_handler, prtd);
1819 if (!prtd->audio_client) {
1820 pr_err("%s: Could not allocate memory for client\n", __func__);
1821 pdata->cstream[rtd->dai_link->id] = NULL;
1822 kfree(prtd);
1823 return -ENOMEM;
1824 }
1825 pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
1826 prtd->audio_client->perf_mode = false;
1827 prtd->session_id = prtd->audio_client->session;
1828 prtd->codec = FORMAT_LINEAR_PCM;
1829 prtd->bytes_copied = 0;
1830 prtd->bytes_read = 0;
1831 prtd->bytes_read_offset = 0;
1832 prtd->received_total = 0;
1833 prtd->byte_offset = 0;
1834 prtd->sample_rate = 48000;
1835 prtd->num_channels = 2;
1836 prtd->first_buffer = 0;
1837
1838 spin_lock_init(&prtd->lock);
1839
1840 atomic_set(&prtd->eos, 0);
1841 atomic_set(&prtd->start, 0);
1842 atomic_set(&prtd->drain, 0);
1843 atomic_set(&prtd->xrun, 0);
1844 atomic_set(&prtd->close, 0);
1845 atomic_set(&prtd->wait_on_close, 0);
1846 atomic_set(&prtd->error, 0);
1847
Xiaojun Sangd57aca02019-03-06 17:03:08 +08001848 init_waitqueue_head(&prtd->eos_wait);
1849 init_waitqueue_head(&prtd->drain_wait);
1850 init_waitqueue_head(&prtd->close_wait);
1851 init_waitqueue_head(&prtd->wait_for_stream_avail);
1852
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301853 runtime->private_data = prtd;
1854
1855 return 0;
1856}
1857
1858static int msm_compr_open(struct snd_compr_stream *cstream)
1859{
1860 int ret = 0;
1861
1862 if (cstream->direction == SND_COMPRESS_PLAYBACK)
1863 ret = msm_compr_playback_open(cstream);
1864 else if (cstream->direction == SND_COMPRESS_CAPTURE)
1865 ret = msm_compr_capture_open(cstream);
1866 return ret;
1867}
1868
1869static int msm_compr_playback_free(struct snd_compr_stream *cstream)
1870{
1871 struct snd_compr_runtime *runtime;
1872 struct msm_compr_audio *prtd;
1873 struct snd_soc_pcm_runtime *soc_prtd;
Meng Wangee084a02018-09-04 16:11:58 +08001874 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301875 struct msm_compr_pdata *pdata;
1876 struct audio_client *ac;
1877 int dir = IN, ret = 0, stream_id;
1878 unsigned long flags;
1879 uint32_t stream_index;
1880
1881 pr_debug("%s\n", __func__);
1882
1883 if (!cstream) {
1884 pr_err("%s cstream is null\n", __func__);
1885 return 0;
1886 }
1887 runtime = cstream->runtime;
1888 soc_prtd = cstream->private_data;
Meng Wang8a2a1042019-03-21 10:14:50 +08001889 if (!runtime || !soc_prtd) {
1890 pr_err("%s runtime or soc_prtd is null\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301891 __func__);
1892 return 0;
1893 }
Meng Wang8a2a1042019-03-21 10:14:50 +08001894 component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
1895 if (!component) {
1896 pr_err("%s component is null\n", __func__);
1897 return 0;
1898 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301899 prtd = runtime->private_data;
1900 if (!prtd) {
1901 pr_err("%s prtd is null\n", __func__);
1902 return 0;
1903 }
1904 prtd->cmd_interrupt = 1;
1905 wake_up(&prtd->drain_wait);
Meng Wangee084a02018-09-04 16:11:58 +08001906 pdata = snd_soc_component_get_drvdata(component);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301907 ac = prtd->audio_client;
1908 if (!pdata || !ac) {
1909 pr_err("%s pdata or ac is null\n", __func__);
1910 return 0;
1911 }
1912 if (atomic_read(&prtd->eos)) {
1913 ret = wait_event_timeout(prtd->eos_wait,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001914 prtd->eos_ack,
1915 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301916 if (!ret)
1917 pr_err("%s: CMD_EOS failed\n", __func__);
1918 }
1919 if (atomic_read(&prtd->close)) {
1920 prtd->cmd_ack = 0;
1921 atomic_set(&prtd->wait_on_close, 1);
1922 ret = wait_event_timeout(prtd->close_wait,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001923 prtd->cmd_ack,
1924 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301925 if (!ret)
1926 pr_err("%s: CMD_CLOSE failed\n", __func__);
1927 }
1928
1929 spin_lock_irqsave(&prtd->lock, flags);
1930 stream_id = ac->stream_id;
1931 stream_index = STREAM_ARRAY_INDEX(NEXT_STREAM_ID(stream_id));
1932
1933 if ((stream_index < MAX_NUMBER_OF_STREAMS && stream_index >= 0) &&
1934 (prtd->gapless_state.stream_opened[stream_index])) {
1935 prtd->gapless_state.stream_opened[stream_index] = 0;
1936 spin_unlock_irqrestore(&prtd->lock, flags);
1937 pr_debug(" close stream %d", NEXT_STREAM_ID(stream_id));
1938 q6asm_stream_cmd(ac, CMD_CLOSE, NEXT_STREAM_ID(stream_id));
1939 spin_lock_irqsave(&prtd->lock, flags);
1940 }
1941
1942 stream_index = STREAM_ARRAY_INDEX(stream_id);
1943 if ((stream_index < MAX_NUMBER_OF_STREAMS && stream_index >= 0) &&
1944 (prtd->gapless_state.stream_opened[stream_index])) {
1945 prtd->gapless_state.stream_opened[stream_index] = 0;
1946 spin_unlock_irqrestore(&prtd->lock, flags);
1947 pr_debug("close stream %d", stream_id);
1948 q6asm_stream_cmd(ac, CMD_CLOSE, stream_id);
1949 spin_lock_irqsave(&prtd->lock, flags);
1950 }
1951 spin_unlock_irqrestore(&prtd->lock, flags);
1952
Ajit Pandeyfa018862019-09-04 14:34:00 +05301953 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301954 pdata->cstream[soc_prtd->dai_link->id] = NULL;
1955 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
1956 msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
1957 SNDRV_PCM_STREAM_PLAYBACK);
1958 }
1959
1960 q6asm_audio_client_buf_free_contiguous(dir, ac);
1961
1962 q6asm_audio_client_free(ac);
1963 msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301964 if (pdata->audio_effects[soc_prtd->dai_link->id] != NULL) {
1965 kfree(pdata->audio_effects[soc_prtd->dai_link->id]);
1966 pdata->audio_effects[soc_prtd->dai_link->id] = NULL;
1967 }
1968 if (pdata->dec_params[soc_prtd->dai_link->id] != NULL) {
1969 kfree(pdata->dec_params[soc_prtd->dai_link->id]);
1970 pdata->dec_params[soc_prtd->dai_link->id] = NULL;
1971 }
1972 pdata->is_in_use[soc_prtd->dai_link->id] = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301973 kfree(prtd);
1974 runtime->private_data = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05301975 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301976
1977 return 0;
1978}
1979
1980static int msm_compr_capture_free(struct snd_compr_stream *cstream)
1981{
1982 struct snd_compr_runtime *runtime;
1983 struct msm_compr_audio *prtd;
1984 struct snd_soc_pcm_runtime *soc_prtd;
Meng Wangee084a02018-09-04 16:11:58 +08001985 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301986 struct msm_compr_pdata *pdata;
1987 struct audio_client *ac;
1988 int dir = OUT, stream_id;
1989 unsigned long flags;
1990 uint32_t stream_index;
1991
1992 if (!cstream) {
1993 pr_err("%s cstream is null\n", __func__);
1994 return 0;
1995 }
1996 runtime = cstream->runtime;
1997 soc_prtd = cstream->private_data;
Meng Wang8a2a1042019-03-21 10:14:50 +08001998 if (!runtime || !soc_prtd) {
1999 pr_err("%s runtime or soc_prtd is null\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302000 return 0;
2001 }
Meng Wang8a2a1042019-03-21 10:14:50 +08002002 component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
2003 if (!component) {
2004 pr_err("%s component is null\n", __func__);
2005 return 0;
2006 }
2007
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302008 prtd = runtime->private_data;
2009 if (!prtd) {
2010 pr_err("%s prtd is null\n", __func__);
2011 return 0;
2012 }
Meng Wangee084a02018-09-04 16:11:58 +08002013 pdata = snd_soc_component_get_drvdata(component);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302014 ac = prtd->audio_client;
2015 if (!pdata || !ac) {
2016 pr_err("%s pdata or ac is null\n", __func__);
2017 return 0;
2018 }
2019
2020 spin_lock_irqsave(&prtd->lock, flags);
2021 stream_id = ac->stream_id;
2022
2023 stream_index = STREAM_ARRAY_INDEX(stream_id);
2024 if ((stream_index < MAX_NUMBER_OF_STREAMS && stream_index >= 0)) {
2025 spin_unlock_irqrestore(&prtd->lock, flags);
2026 pr_debug("close stream %d", stream_id);
2027 q6asm_stream_cmd(ac, CMD_CLOSE, stream_id);
2028 spin_lock_irqsave(&prtd->lock, flags);
2029 }
2030 spin_unlock_irqrestore(&prtd->lock, flags);
2031
Ajit Pandeyfa018862019-09-04 14:34:00 +05302032 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302033 pdata->cstream[soc_prtd->dai_link->id] = NULL;
2034 msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
2035 SNDRV_PCM_STREAM_CAPTURE);
2036
2037 q6asm_audio_client_buf_free_contiguous(dir, ac);
2038
2039 q6asm_audio_client_free(ac);
2040
2041 kfree(prtd);
2042 runtime->private_data = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05302043 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302044
2045 return 0;
2046}
2047
2048static int msm_compr_free(struct snd_compr_stream *cstream)
2049{
2050 int ret = 0;
2051
2052 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2053 ret = msm_compr_playback_free(cstream);
2054 else if (cstream->direction == SND_COMPRESS_CAPTURE)
2055 ret = msm_compr_capture_free(cstream);
2056 return ret;
2057}
2058
2059static bool msm_compr_validate_codec_compr(__u32 codec_id)
2060{
2061 int32_t i;
2062
2063 for (i = 0; i < ARRAY_SIZE(compr_codecs); i++) {
2064 if (compr_codecs[i] == codec_id)
2065 return true;
2066 }
2067 return false;
2068}
2069
2070/* compress stream operations */
2071static int msm_compr_set_params(struct snd_compr_stream *cstream,
2072 struct snd_compr_params *params)
2073{
2074 struct snd_compr_runtime *runtime = cstream->runtime;
2075 struct msm_compr_audio *prtd = runtime->private_data;
2076 int ret = 0, frame_sz = 0;
2077 int i, num_rates;
2078 bool is_format_gapless = false;
2079
2080 pr_debug("%s\n", __func__);
2081
2082 num_rates = sizeof(supported_sample_rates)/sizeof(unsigned int);
2083 for (i = 0; i < num_rates; i++)
2084 if (params->codec.sample_rate == supported_sample_rates[i])
2085 break;
2086 if (i == num_rates)
2087 return -EINVAL;
2088
2089 memcpy(&prtd->codec_param, params, sizeof(struct snd_compr_params));
2090 /* ToDo: remove duplicates */
2091 prtd->num_channels = prtd->codec_param.codec.ch_in;
2092 prtd->sample_rate = prtd->codec_param.codec.sample_rate;
2093 pr_debug("%s: sample_rate %d\n", __func__, prtd->sample_rate);
2094
2095 if ((prtd->codec_param.codec.compr_passthr >= LEGACY_PCM &&
2096 prtd->codec_param.
2097 codec.compr_passthr <= COMPRESSED_PASSTHROUGH_DSD) ||
2098 (prtd->codec_param.
2099 codec.compr_passthr == COMPRESSED_PASSTHROUGH_IEC61937))
2100 prtd->compr_passthr = prtd->codec_param.codec.compr_passthr;
2101 else
2102 prtd->compr_passthr = LEGACY_PCM;
2103 pr_debug("%s: compr_passthr = %d", __func__, prtd->compr_passthr);
2104 if (prtd->compr_passthr != LEGACY_PCM) {
2105 pr_debug("%s: Reset gapless mode playback for compr_type[%d]\n",
2106 __func__, prtd->compr_passthr);
2107 prtd->gapless_state.use_dsp_gapless_mode = 0;
2108 if (!msm_compr_validate_codec_compr(params->codec.id)) {
2109 pr_err("%s codec not supported in passthrough,id =%d\n",
2110 __func__, params->codec.id);
2111 return -EINVAL;
2112 }
2113 }
2114
Deeraj Soman9d125872019-02-05 16:19:56 +05302115 if (params->codec.flags & COMPRESSED_PERF_MODE_FLAG) {
2116 pr_debug("%s: setting perf mode = %d", __func__, LOW_LATENCY_PCM_MODE);
2117 prtd->audio_client->perf_mode = LOW_LATENCY_PCM_MODE;
2118 }
2119
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302120 switch (params->codec.id) {
2121 case SND_AUDIOCODEC_PCM: {
2122 pr_debug("SND_AUDIOCODEC_PCM\n");
2123 prtd->codec = FORMAT_LINEAR_PCM;
2124 is_format_gapless = true;
2125 break;
2126 }
2127
2128 case SND_AUDIOCODEC_MP3: {
2129 pr_debug("SND_AUDIOCODEC_MP3\n");
2130 prtd->codec = FORMAT_MP3;
2131 frame_sz = MP3_OUTPUT_FRAME_SZ;
2132 is_format_gapless = true;
2133 break;
2134 }
2135
2136 case SND_AUDIOCODEC_AAC: {
2137 pr_debug("SND_AUDIOCODEC_AAC\n");
2138 prtd->codec = FORMAT_MPEG4_AAC;
2139 frame_sz = AAC_OUTPUT_FRAME_SZ;
2140 is_format_gapless = true;
2141 break;
2142 }
2143
2144 case SND_AUDIOCODEC_AC3: {
2145 pr_debug("SND_AUDIOCODEC_AC3\n");
2146 prtd->codec = FORMAT_AC3;
2147 frame_sz = AC3_OUTPUT_FRAME_SZ;
2148 is_format_gapless = true;
2149 break;
2150 }
2151
2152 case SND_AUDIOCODEC_EAC3: {
2153 pr_debug("SND_AUDIOCODEC_EAC3\n");
2154 prtd->codec = FORMAT_EAC3;
2155 frame_sz = EAC3_OUTPUT_FRAME_SZ;
2156 is_format_gapless = true;
2157 break;
2158 }
2159
2160 case SND_AUDIOCODEC_MP2: {
2161 pr_debug("SND_AUDIOCODEC_MP2\n");
2162 prtd->codec = FORMAT_MP2;
2163 break;
2164 }
2165
2166 case SND_AUDIOCODEC_WMA: {
2167 pr_debug("SND_AUDIOCODEC_WMA\n");
2168 prtd->codec = FORMAT_WMA_V9;
2169 break;
2170 }
2171
2172 case SND_AUDIOCODEC_WMA_PRO: {
2173 pr_debug("SND_AUDIOCODEC_WMA_PRO\n");
2174 prtd->codec = FORMAT_WMA_V10PRO;
2175 break;
2176 }
2177
2178 case SND_AUDIOCODEC_FLAC: {
2179 pr_debug("%s: SND_AUDIOCODEC_FLAC\n", __func__);
2180 prtd->codec = FORMAT_FLAC;
2181 /*
2182 * DSP bufferring is based on blk size,
2183 * consider mininum buffering to rule out any false wait
2184 */
2185 frame_sz =
2186 prtd->codec_param.codec.options.flac_dec.min_blk_size;
2187 is_format_gapless = true;
2188 break;
2189 }
2190
2191 case SND_AUDIOCODEC_VORBIS: {
2192 pr_debug("%s: SND_AUDIOCODEC_VORBIS\n", __func__);
2193 prtd->codec = FORMAT_VORBIS;
2194 break;
2195 }
2196
2197 case SND_AUDIOCODEC_ALAC: {
2198 pr_debug("%s: SND_AUDIOCODEC_ALAC\n", __func__);
2199 prtd->codec = FORMAT_ALAC;
2200 break;
2201 }
2202
2203 case SND_AUDIOCODEC_APE: {
2204 pr_debug("%s: SND_AUDIOCODEC_APE\n", __func__);
2205 prtd->codec = FORMAT_APE;
2206 break;
2207 }
2208
2209 case SND_AUDIOCODEC_DTS: {
2210 pr_debug("%s: SND_AUDIOCODEC_DTS\n", __func__);
2211 prtd->codec = FORMAT_DTS;
2212 break;
2213 }
2214
2215 case SND_AUDIOCODEC_DSD: {
2216 pr_debug("%s: SND_AUDIOCODEC_DSD\n", __func__);
2217 prtd->codec = FORMAT_DSD;
2218 break;
2219 }
2220
2221 case SND_AUDIOCODEC_TRUEHD: {
2222 pr_debug("%s: SND_AUDIOCODEC_TRUEHD\n", __func__);
2223 prtd->codec = FORMAT_TRUEHD;
2224 break;
2225 }
2226
2227 case SND_AUDIOCODEC_IEC61937: {
2228 pr_debug("%s: SND_AUDIOCODEC_IEC61937\n", __func__);
2229 prtd->codec = FORMAT_IEC61937;
2230 break;
2231 }
2232
2233 case SND_AUDIOCODEC_APTX: {
2234 pr_debug("%s: SND_AUDIOCODEC_APTX\n", __func__);
2235 prtd->codec = FORMAT_APTX;
2236 break;
2237 }
2238
Vikram Pandurangac712c172017-11-17 17:36:49 -08002239 case SND_AUDIOCODEC_BESPOKE: {
2240 pr_debug("%s: SND_AUDIOCODEC_BESPOKE\n", __func__);
2241 prtd->codec = FORMAT_BESPOKE;
2242 break;
2243 }
2244
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +05302245 case SND_AUDIOCODEC_AMR: {
2246 pr_debug("%s:SND_AUDIOCODEC_AMR\n", __func__);
2247 prtd->codec = FORMAT_AMRNB;
2248 break;
2249 }
2250
2251 case SND_AUDIOCODEC_AMRWB: {
2252 pr_debug("%s:SND_AUDIOCODEC_AMRWB\n", __func__);
2253 prtd->codec = FORMAT_AMRWB;
2254 break;
2255 }
2256
2257 case SND_AUDIOCODEC_AMRWBPLUS: {
2258 pr_debug("%s:SND_AUDIOCODEC_AMRWBPLUS\n", __func__);
2259 prtd->codec = FORMAT_AMR_WB_PLUS;
2260 break;
2261 }
2262
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302263 default:
2264 pr_err("codec not supported, id =%d\n", params->codec.id);
2265 return -EINVAL;
2266 }
2267
2268 if (!is_format_gapless)
2269 prtd->gapless_state.use_dsp_gapless_mode = false;
2270
2271 prtd->partial_drain_delay =
2272 msm_compr_get_partial_drain_delay(frame_sz, prtd->sample_rate);
2273
2274 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2275 ret = msm_compr_configure_dsp_for_playback(cstream);
2276 else if (cstream->direction == SND_COMPRESS_CAPTURE)
2277 ret = msm_compr_configure_dsp_for_capture(cstream);
2278
2279 return ret;
2280}
2281
2282static int msm_compr_drain_buffer(struct msm_compr_audio *prtd,
2283 unsigned long *flags)
2284{
2285 int rc = 0;
2286
2287 atomic_set(&prtd->drain, 1);
2288 prtd->drain_ready = 0;
2289 spin_unlock_irqrestore(&prtd->lock, *flags);
2290 pr_debug("%s: wait for buffer to be drained\n", __func__);
2291 rc = wait_event_interruptible(prtd->drain_wait,
2292 prtd->drain_ready ||
2293 prtd->cmd_interrupt ||
2294 atomic_read(&prtd->xrun) ||
2295 atomic_read(&prtd->error));
2296 pr_debug("%s: out of buffer drain wait with ret %d\n", __func__, rc);
2297 spin_lock_irqsave(&prtd->lock, *flags);
2298 if (prtd->cmd_interrupt) {
2299 pr_debug("%s: buffer drain interrupted by flush)\n", __func__);
2300 rc = -EINTR;
2301 prtd->cmd_interrupt = 0;
2302 }
2303 if (atomic_read(&prtd->error)) {
2304 pr_err("%s: Got RESET EVENTS notification, return\n",
2305 __func__);
2306 rc = -ENETRESET;
2307 }
2308 return rc;
2309}
2310
2311static int msm_compr_wait_for_stream_avail(struct msm_compr_audio *prtd,
2312 unsigned long *flags)
2313{
2314 int rc = 0;
2315
2316 pr_debug("next session is already in opened state\n");
2317 prtd->next_stream = 1;
2318 prtd->cmd_interrupt = 0;
2319 spin_unlock_irqrestore(&prtd->lock, *flags);
2320 /*
2321 * Wait for stream to be available, or the wait to be interrupted by
2322 * commands like flush or till a timeout of one second.
2323 */
2324 rc = wait_event_timeout(prtd->wait_for_stream_avail,
2325 prtd->stream_available || prtd->cmd_interrupt, 1 * HZ);
2326 pr_err("%s:prtd->stream_available %d, prtd->cmd_interrupt %d rc %d\n",
2327 __func__, prtd->stream_available, prtd->cmd_interrupt, rc);
2328
2329 spin_lock_irqsave(&prtd->lock, *flags);
2330 if (rc == 0) {
2331 pr_err("%s: wait_for_stream_avail timed out\n",
2332 __func__);
2333 rc = -ETIMEDOUT;
2334 } else if (prtd->cmd_interrupt == 1) {
2335 /*
2336 * This scenario might not happen as we do not allow
2337 * flush in transition state.
2338 */
2339 pr_debug("%s: wait_for_stream_avail interrupted\n", __func__);
2340 prtd->cmd_interrupt = 0;
2341 prtd->stream_available = 0;
2342 rc = -EINTR;
2343 } else {
2344 prtd->stream_available = 0;
2345 rc = 0;
2346 }
2347 pr_debug("%s : rc = %d", __func__, rc);
2348 return rc;
2349}
2350
2351static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
2352{
2353 struct snd_compr_runtime *runtime = cstream->runtime;
2354 struct msm_compr_audio *prtd = runtime->private_data;
2355 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Meng Wangee084a02018-09-04 16:11:58 +08002356 struct snd_soc_component *component = NULL;
2357 struct msm_compr_pdata *pdata = NULL;
2358 uint32_t *volume = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302359 struct audio_client *ac = prtd->audio_client;
2360 unsigned long fe_id = rtd->dai_link->id;
2361 int rc = 0;
2362 int bytes_to_write;
2363 unsigned long flags;
2364 int stream_id;
2365 uint32_t stream_index;
2366 uint16_t bits_per_sample = 16;
2367
Meng Wangee084a02018-09-04 16:11:58 +08002368 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
2369 if (!component) {
2370 pr_err("%s: component is NULL\n", __func__);
2371 return -EINVAL;
2372 }
2373 pdata = snd_soc_component_get_drvdata(component);
2374 if (!pdata) {
2375 pr_err("%s: pdata is NULL\n", __func__);
2376 return -EINVAL;
2377 }
2378 volume = pdata->volume[rtd->dai_link->id];
2379
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302380 spin_lock_irqsave(&prtd->lock, flags);
2381 if (atomic_read(&prtd->error)) {
2382 pr_err("%s Got RESET EVENTS notification, return immediately",
2383 __func__);
2384 spin_unlock_irqrestore(&prtd->lock, flags);
2385 return 0;
2386 }
2387 spin_unlock_irqrestore(&prtd->lock, flags);
2388
2389 switch (cmd) {
2390 case SNDRV_PCM_TRIGGER_START:
2391 pr_debug("%s: SNDRV_PCM_TRIGGER_START\n", __func__);
2392 atomic_set(&prtd->start, 1);
2393
2394 /*
2395 * compr_set_volume and compr_init_pp_params
2396 * are used to configure ASM volume hence not
2397 * needed for compress passthrough playback.
2398 *
2399 * compress passthrough volume is controlled in
2400 * ADM by adm_send_compressed_device_mute()
2401 */
2402 if (prtd->compr_passthr == LEGACY_PCM &&
2403 cstream->direction == SND_COMPRESS_PLAYBACK) {
2404 /* set volume for the stream before RUN */
2405 rc = msm_compr_set_volume(cstream,
2406 volume[0], volume[1]);
2407 if (rc)
2408 pr_err("%s : Set Volume failed : %d\n",
2409 __func__, rc);
2410
2411 rc = msm_compr_init_pp_params(cstream, ac);
2412 if (rc)
2413 pr_err("%s : init PP params failed : %d\n",
2414 __func__, rc);
2415 } else {
2416 msm_compr_read_buffer(prtd);
2417 }
2418 /* issue RUN command for the stream */
2419 q6asm_run_nowait(prtd->audio_client, prtd->run_mode,
2420 prtd->start_delay_msw, prtd->start_delay_lsw);
2421 break;
2422 case SNDRV_PCM_TRIGGER_STOP:
2423 spin_lock_irqsave(&prtd->lock, flags);
2424 pr_debug("%s: SNDRV_PCM_TRIGGER_STOP transition %d\n", __func__,
2425 prtd->gapless_state.gapless_transition);
2426 stream_id = ac->stream_id;
2427 atomic_set(&prtd->start, 0);
2428 if (cstream->direction == SND_COMPRESS_CAPTURE) {
2429 q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
2430 atomic_set(&prtd->xrun, 0);
2431 prtd->received_total = 0;
2432 prtd->bytes_copied = 0;
2433 prtd->bytes_read = 0;
2434 prtd->bytes_read_offset = 0;
2435 prtd->byte_offset = 0;
2436 prtd->app_pointer = 0;
2437 spin_unlock_irqrestore(&prtd->lock, flags);
2438 break;
2439 }
2440 if (prtd->next_stream) {
2441 pr_debug("%s: interrupt next track wait queues\n",
2442 __func__);
2443 prtd->cmd_interrupt = 1;
2444 wake_up(&prtd->wait_for_stream_avail);
2445 prtd->next_stream = 0;
2446 }
2447 if (atomic_read(&prtd->eos)) {
2448 pr_debug("%s: interrupt eos wait queues", __func__);
2449 /*
2450 * Gapless playback does not wait for eos, do not set
2451 * cmd_int and do not wake up eos_wait during gapless
2452 * transition
2453 */
2454 if (!prtd->gapless_state.gapless_transition) {
2455 prtd->cmd_interrupt = 1;
2456 wake_up(&prtd->eos_wait);
2457 }
2458 atomic_set(&prtd->eos, 0);
2459 }
2460 if (atomic_read(&prtd->drain)) {
2461 pr_debug("%s: interrupt drain wait queues", __func__);
2462 prtd->cmd_interrupt = 1;
2463 prtd->drain_ready = 1;
2464 wake_up(&prtd->drain_wait);
2465 atomic_set(&prtd->drain, 0);
2466 }
2467 prtd->last_buffer = 0;
2468 prtd->cmd_ack = 0;
2469 if (!prtd->gapless_state.gapless_transition) {
2470 pr_debug("issue CMD_FLUSH stream_id %d\n", stream_id);
2471 spin_unlock_irqrestore(&prtd->lock, flags);
2472 q6asm_stream_cmd(
2473 prtd->audio_client, CMD_FLUSH, stream_id);
2474 spin_lock_irqsave(&prtd->lock, flags);
2475 } else {
2476 prtd->first_buffer = 0;
2477 }
2478 /* FIXME. only reset if flush was successful */
2479 prtd->byte_offset = 0;
2480 prtd->copied_total = 0;
2481 prtd->app_pointer = 0;
2482 prtd->bytes_received = 0;
2483 prtd->bytes_sent = 0;
2484 prtd->marker_timestamp = 0;
2485
2486 atomic_set(&prtd->xrun, 0);
2487 spin_unlock_irqrestore(&prtd->lock, flags);
2488 break;
2489 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
2490 pr_debug("SNDRV_PCM_TRIGGER_PAUSE_PUSH transition %d\n",
2491 prtd->gapless_state.gapless_transition);
2492 if (!prtd->gapless_state.gapless_transition) {
2493 pr_debug("issue CMD_PAUSE stream_id %d\n",
2494 ac->stream_id);
2495 q6asm_stream_cmd_nowait(ac, CMD_PAUSE, ac->stream_id);
2496 atomic_set(&prtd->start, 0);
2497 }
2498 break;
2499 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
2500 pr_debug("SNDRV_PCM_TRIGGER_PAUSE_RELEASE transition %d\n",
2501 prtd->gapless_state.gapless_transition);
2502 if (!prtd->gapless_state.gapless_transition) {
2503 atomic_set(&prtd->start, 1);
2504 q6asm_run_nowait(prtd->audio_client, prtd->run_mode,
2505 0, 0);
2506 }
2507 break;
2508 case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
2509 pr_debug("%s: SND_COMPR_TRIGGER_PARTIAL_DRAIN\n", __func__);
2510 if (!prtd->gapless_state.use_dsp_gapless_mode) {
2511 pr_debug("%s: set partial drain as drain\n", __func__);
2512 cmd = SND_COMPR_TRIGGER_DRAIN;
2513 }
2514 case SND_COMPR_TRIGGER_DRAIN:
2515 pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__);
2516 /* Make sure all the data is sent to DSP before sending EOS */
2517 spin_lock_irqsave(&prtd->lock, flags);
2518
2519 if (!atomic_read(&prtd->start)) {
2520 pr_err("%s: stream is not in started state\n",
2521 __func__);
2522 rc = -EPERM;
2523 spin_unlock_irqrestore(&prtd->lock, flags);
2524 break;
2525 }
2526 if (prtd->bytes_received > prtd->copied_total) {
2527 pr_debug("%s: wait till all the data is sent to dsp\n",
2528 __func__);
2529 rc = msm_compr_drain_buffer(prtd, &flags);
2530 if (rc || !atomic_read(&prtd->start)) {
2531 if (rc != -ENETRESET)
2532 rc = -EINTR;
2533 spin_unlock_irqrestore(&prtd->lock, flags);
2534 break;
2535 }
2536 /*
2537 * FIXME: Bug.
2538 * Write(32767)
2539 * Start
2540 * Drain <- Indefinite wait
2541 * sol1 : if (prtd->copied_total) then wait?
2542 * sol2 : (prtd->cmd_interrupt || prtd->drain_ready ||
2543 * atomic_read(xrun)
2544 */
2545 bytes_to_write = prtd->bytes_received
2546 - prtd->copied_total;
2547 WARN(bytes_to_write > runtime->fragment_size,
2548 "last write %d cannot be > than fragment_size",
2549 bytes_to_write);
2550
2551 if (bytes_to_write > 0) {
2552 pr_debug("%s: send %d partial bytes at the end",
2553 __func__, bytes_to_write);
2554 atomic_set(&prtd->xrun, 0);
2555 prtd->last_buffer = 1;
2556 msm_compr_send_buffer(prtd);
2557 }
2558 }
2559
2560 if ((cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN) &&
2561 (prtd->gapless_state.set_next_stream_id)) {
2562 /* wait for the last buffer to be returned */
2563
2564 if (prtd->last_buffer) {
2565 pr_debug("%s: last buffer drain\n", __func__);
2566 rc = msm_compr_drain_buffer(prtd, &flags);
2567 if (rc || !atomic_read(&prtd->start)) {
2568 spin_unlock_irqrestore(&prtd->lock,
2569 flags);
2570 break;
2571 }
2572 }
2573 /* send EOS */
2574 prtd->eos_ack = 0;
2575 atomic_set(&prtd->eos, 1);
2576 pr_debug("issue CMD_EOS stream_id %d\n", ac->stream_id);
2577 q6asm_stream_cmd_nowait(ac, CMD_EOS, ac->stream_id);
2578 pr_info("PARTIAL DRAIN, do not wait for EOS ack\n");
2579
2580 /* send a zero length buffer */
2581 atomic_set(&prtd->xrun, 0);
2582 msm_compr_send_buffer(prtd);
2583
2584 /* wait for the zero length buffer to be returned */
2585 pr_debug("%s: zero length buffer drain\n", __func__);
2586 rc = msm_compr_drain_buffer(prtd, &flags);
2587 if (rc || !atomic_read(&prtd->start)) {
2588 spin_unlock_irqrestore(&prtd->lock, flags);
2589 break;
2590 }
2591
2592 /* sleep for additional duration partial drain */
2593 atomic_set(&prtd->drain, 1);
2594 prtd->drain_ready = 0;
2595 pr_debug("%s, additional sleep: %d\n", __func__,
2596 prtd->partial_drain_delay);
2597 spin_unlock_irqrestore(&prtd->lock, flags);
2598 rc = wait_event_timeout(prtd->drain_wait,
2599 prtd->drain_ready || prtd->cmd_interrupt,
2600 msecs_to_jiffies(prtd->partial_drain_delay));
2601 pr_debug("%s: out of additional wait for low sample rate\n",
2602 __func__);
2603 spin_lock_irqsave(&prtd->lock, flags);
2604 if (prtd->cmd_interrupt) {
2605 pr_debug("%s: additional wait interrupted by flush)\n",
2606 __func__);
2607 rc = -EINTR;
2608 prtd->cmd_interrupt = 0;
2609 spin_unlock_irqrestore(&prtd->lock, flags);
2610 break;
2611 }
2612
2613 /* move to next stream and reset vars */
2614 pr_debug("%s: Moving to next stream in gapless\n",
2615 __func__);
2616 ac->stream_id = NEXT_STREAM_ID(ac->stream_id);
2617 prtd->byte_offset = 0;
2618 prtd->app_pointer = 0;
2619 prtd->first_buffer = 1;
2620 prtd->last_buffer = 0;
2621 /*
2622 * Set gapless transition flag only if EOS hasn't been
2623 * acknowledged already.
2624 */
2625 if (atomic_read(&prtd->eos))
2626 prtd->gapless_state.gapless_transition = 1;
2627 prtd->marker_timestamp = 0;
2628
2629 /*
2630 * Don't reset these as these vars map to
2631 * total_bytes_transferred and total_bytes_available
2632 * directly, only total_bytes_transferred will be
2633 * updated in the next avail() ioctl
2634 * prtd->copied_total = 0;
2635 * prtd->bytes_received = 0;
2636 */
2637 atomic_set(&prtd->drain, 0);
2638 atomic_set(&prtd->xrun, 1);
2639 pr_debug("%s: issue CMD_RUN", __func__);
2640 q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
2641 spin_unlock_irqrestore(&prtd->lock, flags);
2642 break;
2643 }
2644 /*
2645 * moving to next stream failed, so reset the gapless state
2646 * set next stream id for the same session so that the same
2647 * stream can be used for gapless playback
2648 */
2649 prtd->gapless_state.set_next_stream_id = false;
2650 prtd->gapless_state.gapless_transition = 0;
2651 pr_debug("%s:CMD_EOS stream_id %d\n", __func__, ac->stream_id);
2652
2653 prtd->eos_ack = 0;
2654 atomic_set(&prtd->eos, 1);
2655 q6asm_stream_cmd_nowait(ac, CMD_EOS, ac->stream_id);
2656
2657 spin_unlock_irqrestore(&prtd->lock, flags);
2658
2659
2660 /* Wait indefinitely for DRAIN. Flush can also signal this*/
2661 rc = wait_event_interruptible(prtd->eos_wait,
2662 (prtd->eos_ack ||
2663 prtd->cmd_interrupt ||
2664 atomic_read(&prtd->error)));
2665
2666 if (rc < 0)
2667 pr_err("%s: EOS wait failed\n", __func__);
2668
2669 pr_debug("%s: SNDRV_COMPRESS_DRAIN out of wait for EOS\n",
2670 __func__);
2671
2672 if (prtd->cmd_interrupt)
2673 rc = -EINTR;
2674
2675 if (atomic_read(&prtd->error)) {
2676 pr_err("%s: Got RESET EVENTS notification, return\n",
2677 __func__);
2678 rc = -ENETRESET;
2679 }
2680
2681 /*FIXME : what if a flush comes while PC is here */
2682 if (rc == 0) {
2683 /*
2684 * Failed to open second stream in DSP for gapless
2685 * so prepare the current stream in session
2686 * for gapless playback
2687 */
2688 spin_lock_irqsave(&prtd->lock, flags);
2689 pr_debug("%s:issue CMD_PAUSE stream_id %d",
2690 __func__, ac->stream_id);
2691 q6asm_stream_cmd_nowait(ac, CMD_PAUSE, ac->stream_id);
2692 prtd->cmd_ack = 0;
2693 spin_unlock_irqrestore(&prtd->lock, flags);
2694
2695 /*
2696 * Cache this time as last known time
2697 */
2698 if (pdata->use_legacy_api)
2699 q6asm_get_session_time_legacy(
2700 prtd->audio_client,
2701 &prtd->marker_timestamp);
2702 else
2703 q6asm_get_session_time(prtd->audio_client,
2704 &prtd->marker_timestamp);
2705
2706 spin_lock_irqsave(&prtd->lock, flags);
2707 /*
2708 * Don't reset these as these vars map to
2709 * total_bytes_transferred and total_bytes_available.
2710 * Just total_bytes_transferred will be updated
2711 * in the next avail() ioctl.
2712 * prtd->copied_total = 0;
2713 * prtd->bytes_received = 0;
2714 * do not reset prtd->bytes_sent as well as the same
2715 * session is used for gapless playback
2716 */
2717 prtd->byte_offset = 0;
2718
2719 prtd->app_pointer = 0;
2720 prtd->first_buffer = 1;
2721 prtd->last_buffer = 0;
2722 atomic_set(&prtd->drain, 0);
2723 atomic_set(&prtd->xrun, 1);
2724 spin_unlock_irqrestore(&prtd->lock, flags);
2725
2726 pr_debug("%s:issue CMD_FLUSH ac->stream_id %d",
2727 __func__, ac->stream_id);
2728 q6asm_stream_cmd(ac, CMD_FLUSH, ac->stream_id);
2729
2730 q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
2731 }
2732 prtd->cmd_interrupt = 0;
2733 break;
2734 case SND_COMPR_TRIGGER_NEXT_TRACK:
2735 if (!prtd->gapless_state.use_dsp_gapless_mode) {
2736 pr_debug("%s: ignore trigger next track\n", __func__);
2737 rc = 0;
2738 break;
2739 }
2740 pr_debug("%s: SND_COMPR_TRIGGER_NEXT_TRACK\n", __func__);
2741 spin_lock_irqsave(&prtd->lock, flags);
2742 rc = 0;
2743 /* next stream in gapless */
2744 stream_id = NEXT_STREAM_ID(ac->stream_id);
2745 /*
2746 * Wait if stream 1 has not completed before honoring next
2747 * track for stream 3. Scenario happens if second clip is
2748 * small and fills in one buffer so next track will be
2749 * called immediately.
2750 */
2751 stream_index = STREAM_ARRAY_INDEX(stream_id);
2752 if (stream_index >= MAX_NUMBER_OF_STREAMS ||
2753 stream_index < 0) {
2754 pr_err("%s: Invalid stream index: %d", __func__,
2755 stream_index);
2756 spin_unlock_irqrestore(&prtd->lock, flags);
2757 rc = -EINVAL;
2758 break;
2759 }
2760
2761 if (prtd->gapless_state.stream_opened[stream_index]) {
2762 if (prtd->gapless_state.gapless_transition) {
2763 rc = msm_compr_wait_for_stream_avail(prtd,
2764 &flags);
2765 } else {
2766 /*
2767 * If session is already opened break out if
2768 * the state is not gapless transition. This
2769 * is when seek happens after the last buffer
2770 * is sent to the driver. Next track would be
2771 * called again after last buffer is sent.
2772 */
2773 pr_debug("next session is in opened state\n");
2774 spin_unlock_irqrestore(&prtd->lock, flags);
2775 break;
2776 }
2777 }
2778 spin_unlock_irqrestore(&prtd->lock, flags);
2779 if (rc < 0) {
2780 /*
2781 * if return type EINTR then reset to zero. Tiny
2782 * compress treats EINTR as error and prevents PARTIAL
2783 * DRAIN. EINTR is not an error. wait for stream avail
2784 * is interrupted by some other command like FLUSH.
2785 */
2786 if (rc == -EINTR) {
2787 pr_debug("%s: EINTR reset rc to 0\n", __func__);
2788 rc = 0;
2789 }
2790 break;
2791 }
2792
2793 if (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_LE)
2794 bits_per_sample = 24;
2795 else if (prtd->codec_param.codec.format ==
2796 SNDRV_PCM_FORMAT_S32_LE)
2797 bits_per_sample = 32;
2798
2799 pr_debug("%s: open_write stream_id %d bits_per_sample %d",
2800 __func__, stream_id, bits_per_sample);
Nidhisha Dhananjayand84669e2019-02-20 11:00:28 +05302801
2802 if (q6core_get_avcs_api_version_per_service(
2803 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
2804 ADSP_ASM_API_VERSION_V2)
2805 rc = q6asm_stream_open_write_v5(prtd->audio_client,
2806 prtd->codec, bits_per_sample,
2807 stream_id,
2808 prtd->gapless_state.use_dsp_gapless_mode);
2809 else
2810 rc = q6asm_stream_open_write_v4(prtd->audio_client,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302811 prtd->codec, bits_per_sample,
2812 stream_id,
2813 prtd->gapless_state.use_dsp_gapless_mode);
2814 if (rc < 0) {
Nidhisha Dhananjayand84669e2019-02-20 11:00:28 +05302815 pr_err("%s: Session out open failed for gapless [%d]\n",
2816 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302817 break;
2818 }
2819
2820 spin_lock_irqsave(&prtd->lock, flags);
2821 prtd->gapless_state.stream_opened[stream_index] = 1;
2822 prtd->gapless_state.set_next_stream_id = true;
2823 spin_unlock_irqrestore(&prtd->lock, flags);
2824
2825 rc = msm_compr_send_media_format_block(cstream,
2826 stream_id, false);
2827 if (rc < 0) {
2828 pr_err("%s, failed to send media format block\n",
2829 __func__);
2830 break;
2831 }
2832 msm_compr_send_dec_params(cstream, pdata->dec_params[fe_id],
2833 stream_id);
2834 break;
2835 }
2836
2837 return rc;
2838}
2839
2840static int msm_compr_pointer(struct snd_compr_stream *cstream,
2841 struct snd_compr_tstamp *arg)
2842{
2843 struct snd_compr_runtime *runtime = cstream->runtime;
2844 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
2845 struct msm_compr_audio *prtd = runtime->private_data;
Meng Wangee084a02018-09-04 16:11:58 +08002846 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302847 struct msm_compr_pdata *pdata = NULL;
2848 struct snd_compr_tstamp tstamp;
2849 uint64_t timestamp = 0;
2850 int rc = 0, first_buffer;
2851 unsigned long flags;
2852 uint32_t gapless_transition;
2853
Meng Wangee084a02018-09-04 16:11:58 +08002854 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
2855 if (!component) {
2856 pr_err("%s: component is NULL\n", __func__);
2857 return -EINVAL;
2858 }
2859 pdata = snd_soc_component_get_drvdata(component);
2860 if (!pdata) {
2861 pr_err("%s: pdata is NULL\n", __func__);
2862 return -EINVAL;
2863 }
2864
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302865 pr_debug("%s\n", __func__);
2866 memset(&tstamp, 0x0, sizeof(struct snd_compr_tstamp));
2867
2868 spin_lock_irqsave(&prtd->lock, flags);
2869 tstamp.sampling_rate = prtd->sample_rate;
2870 tstamp.byte_offset = prtd->byte_offset;
2871 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2872 tstamp.copied_total = prtd->copied_total;
2873 else if (cstream->direction == SND_COMPRESS_CAPTURE)
2874 tstamp.copied_total = prtd->received_total;
2875 first_buffer = prtd->first_buffer;
2876 if (atomic_read(&prtd->error)) {
Vatsal Bucha0527c562017-10-04 20:38:49 +05302877 pr_err_ratelimited("%s Got RESET EVENTS notification, return error\n",
2878 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302879 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2880 runtime->total_bytes_transferred = tstamp.copied_total;
2881 else
2882 runtime->total_bytes_available = tstamp.copied_total;
2883 tstamp.pcm_io_frames = 0;
2884 memcpy(arg, &tstamp, sizeof(struct snd_compr_tstamp));
2885 spin_unlock_irqrestore(&prtd->lock, flags);
2886 return -ENETRESET;
2887 }
2888 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
2889
2890 gapless_transition = prtd->gapless_state.gapless_transition;
2891 spin_unlock_irqrestore(&prtd->lock, flags);
2892 if (gapless_transition)
2893 pr_debug("%s session time in gapless transition",
2894 __func__);
2895 /*
2896 *- Do not query if no buffer has been given.
2897 *- Do not query on a gapless transition.
2898 * Playback for the 2nd stream can start (thus returning time
2899 * starting from 0) before the driver knows about EOS of first
2900 * stream.
2901 */
2902 if (!first_buffer || gapless_transition) {
2903
2904 if (pdata->use_legacy_api)
2905 rc = q6asm_get_session_time_legacy(
2906 prtd->audio_client, &prtd->marker_timestamp);
2907 else
2908 rc = q6asm_get_session_time(
2909 prtd->audio_client, &prtd->marker_timestamp);
2910 if (rc < 0) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302911 if (atomic_read(&prtd->error))
2912 return -ENETRESET;
2913 else
Xiaoyu Yef74e89b2018-01-08 18:09:29 -08002914 return rc;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302915 }
2916 }
2917 } else {
2918 spin_unlock_irqrestore(&prtd->lock, flags);
2919 }
2920 timestamp = prtd->marker_timestamp;
2921
2922 /* DSP returns timestamp in usec */
2923 pr_debug("%s: timestamp = %lld usec\n", __func__, timestamp);
2924 timestamp *= prtd->sample_rate;
2925 tstamp.pcm_io_frames = (snd_pcm_uframes_t)div64_u64(timestamp, 1000000);
2926 memcpy(arg, &tstamp, sizeof(struct snd_compr_tstamp));
2927
2928 return 0;
2929}
2930
2931static int msm_compr_ack(struct snd_compr_stream *cstream,
2932 size_t count)
2933{
2934 struct snd_compr_runtime *runtime = cstream->runtime;
2935 struct msm_compr_audio *prtd = runtime->private_data;
2936 void *src, *dstn;
2937 size_t copy;
2938 unsigned long flags;
2939
2940 WARN(1, "This path is untested");
2941 return -EINVAL;
2942
2943 pr_debug("%s: count = %zd\n", __func__, count);
2944 if (!prtd->buffer) {
2945 pr_err("%s: Buffer is not allocated yet ??\n", __func__);
2946 return -EINVAL;
2947 }
2948 src = runtime->buffer + prtd->app_pointer;
2949 dstn = prtd->buffer + prtd->app_pointer;
2950 if (count < prtd->buffer_size - prtd->app_pointer) {
2951 memcpy(dstn, src, count);
2952 prtd->app_pointer += count;
2953 } else {
2954 copy = prtd->buffer_size - prtd->app_pointer;
2955 memcpy(dstn, src, copy);
2956 memcpy(prtd->buffer, runtime->buffer, count - copy);
2957 prtd->app_pointer = count - copy;
2958 }
2959
2960 /*
2961 * If the stream is started and all the bytes received were
2962 * copied to DSP, the newly received bytes should be
2963 * sent right away
2964 */
2965 spin_lock_irqsave(&prtd->lock, flags);
2966
2967 if (atomic_read(&prtd->start) &&
2968 prtd->bytes_received == prtd->copied_total) {
2969 prtd->bytes_received += count;
2970 msm_compr_send_buffer(prtd);
2971 } else
2972 prtd->bytes_received += count;
2973
2974 spin_unlock_irqrestore(&prtd->lock, flags);
2975
2976 return 0;
2977}
2978
2979static int msm_compr_playback_copy(struct snd_compr_stream *cstream,
2980 char __user *buf, size_t count)
2981{
2982 struct snd_compr_runtime *runtime = cstream->runtime;
2983 struct msm_compr_audio *prtd = runtime->private_data;
2984 void *dstn;
2985 size_t copy;
2986 uint64_t bytes_available = 0;
2987 unsigned long flags;
2988
2989 pr_debug("%s: count = %zd\n", __func__, count);
2990 if (!prtd->buffer) {
2991 pr_err("%s: Buffer is not allocated yet ??", __func__);
2992 return 0;
2993 }
2994
2995 spin_lock_irqsave(&prtd->lock, flags);
2996 if (atomic_read(&prtd->error)) {
2997 pr_err("%s Got RESET EVENTS notification", __func__);
2998 spin_unlock_irqrestore(&prtd->lock, flags);
2999 return -ENETRESET;
3000 }
3001 spin_unlock_irqrestore(&prtd->lock, flags);
3002
3003 dstn = prtd->buffer + prtd->app_pointer;
3004 if (count < prtd->buffer_size - prtd->app_pointer) {
3005 if (copy_from_user(dstn, buf, count))
3006 return -EFAULT;
3007 prtd->app_pointer += count;
3008 } else {
3009 copy = prtd->buffer_size - prtd->app_pointer;
3010 if (copy_from_user(dstn, buf, copy))
3011 return -EFAULT;
3012 if (copy_from_user(prtd->buffer, buf + copy, count - copy))
3013 return -EFAULT;
3014 prtd->app_pointer = count - copy;
3015 }
3016
3017 /*
3018 * If stream is started and there has been an xrun,
3019 * since the available bytes fits fragment_size, copy the data
3020 * right away.
3021 */
3022 spin_lock_irqsave(&prtd->lock, flags);
3023 prtd->bytes_received += count;
3024 if (atomic_read(&prtd->start)) {
3025 if (atomic_read(&prtd->xrun)) {
3026 pr_debug("%s: in xrun, count = %zd\n", __func__, count);
3027 bytes_available = prtd->bytes_received -
3028 prtd->copied_total;
3029 if (bytes_available >= runtime->fragment_size) {
3030 pr_debug("%s: handle xrun, bytes_to_write = %llu\n",
3031 __func__, bytes_available);
3032 atomic_set(&prtd->xrun, 0);
3033 msm_compr_send_buffer(prtd);
3034 } /* else not sufficient data */
3035 } /* writes will continue on the next write_done */
3036 }
3037
3038 spin_unlock_irqrestore(&prtd->lock, flags);
3039
3040 return count;
3041}
3042
3043static int msm_compr_capture_copy(struct snd_compr_stream *cstream,
3044 char __user *buf, size_t count)
3045{
3046 struct snd_compr_runtime *runtime = cstream->runtime;
3047 struct msm_compr_audio *prtd = runtime->private_data;
3048 void *source;
3049 unsigned long flags;
3050
3051 pr_debug("%s: count = %zd\n", __func__, count);
3052 if (!prtd->buffer) {
3053 pr_err("%s: Buffer is not allocated yet ??", __func__);
3054 return 0;
3055 }
3056
3057 spin_lock_irqsave(&prtd->lock, flags);
3058 if (atomic_read(&prtd->error)) {
3059 pr_err("%s Got RESET EVENTS notification", __func__);
3060 spin_unlock_irqrestore(&prtd->lock, flags);
3061 return -ENETRESET;
3062 }
3063
3064 source = prtd->buffer + prtd->app_pointer;
3065 /* check if we have requested amount of data to copy to user*/
3066 if (count <= prtd->received_total - prtd->bytes_copied) {
3067 spin_unlock_irqrestore(&prtd->lock, flags);
3068 if (copy_to_user(buf, source, count)) {
3069 pr_err("copy_to_user failed");
3070 return -EFAULT;
3071 }
3072 spin_lock_irqsave(&prtd->lock, flags);
3073 prtd->app_pointer += count;
3074 if (prtd->app_pointer >= prtd->buffer_size)
3075 prtd->app_pointer -= prtd->buffer_size;
3076 prtd->bytes_copied += count;
3077 }
3078 msm_compr_read_buffer(prtd);
3079
3080 spin_unlock_irqrestore(&prtd->lock, flags);
3081 return count;
3082}
3083
3084static int msm_compr_copy(struct snd_compr_stream *cstream,
3085 char __user *buf, size_t count)
3086{
3087 int ret = 0;
3088
3089 pr_debug(" In %s\n", __func__);
3090 if (cstream->direction == SND_COMPRESS_PLAYBACK)
3091 ret = msm_compr_playback_copy(cstream, buf, count);
3092 else if (cstream->direction == SND_COMPRESS_CAPTURE)
3093 ret = msm_compr_capture_copy(cstream, buf, count);
3094 return ret;
3095}
3096
3097static int msm_compr_get_caps(struct snd_compr_stream *cstream,
3098 struct snd_compr_caps *arg)
3099{
3100 struct snd_compr_runtime *runtime = cstream->runtime;
3101 struct msm_compr_audio *prtd = runtime->private_data;
3102 int ret = 0;
3103
3104 pr_debug("%s\n", __func__);
3105 if ((arg != NULL) && (prtd != NULL)) {
3106 memcpy(arg, &prtd->compr_cap, sizeof(struct snd_compr_caps));
3107 } else {
3108 ret = -EINVAL;
3109 pr_err("%s: arg (0x%pK), prtd (0x%pK)\n", __func__, arg, prtd);
3110 }
3111
3112 return ret;
3113}
3114
3115static int msm_compr_get_codec_caps(struct snd_compr_stream *cstream,
3116 struct snd_compr_codec_caps *codec)
3117{
3118 pr_debug("%s\n", __func__);
3119
3120 switch (codec->codec) {
3121 case SND_AUDIOCODEC_MP3:
3122 codec->num_descriptors = 2;
3123 codec->descriptor[0].max_ch = 2;
3124 memcpy(codec->descriptor[0].sample_rates,
3125 supported_sample_rates,
3126 sizeof(supported_sample_rates));
3127 codec->descriptor[0].num_sample_rates =
3128 sizeof(supported_sample_rates)/sizeof(unsigned int);
3129 codec->descriptor[0].bit_rate[0] = 320; /* 320kbps */
3130 codec->descriptor[0].bit_rate[1] = 128;
3131 codec->descriptor[0].num_bitrates = 2;
3132 codec->descriptor[0].profiles = 0;
3133 codec->descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO;
3134 codec->descriptor[0].formats = 0;
3135 break;
3136 case SND_AUDIOCODEC_AAC:
3137 codec->num_descriptors = 2;
3138 codec->descriptor[1].max_ch = 2;
3139 memcpy(codec->descriptor[1].sample_rates,
3140 supported_sample_rates,
3141 sizeof(supported_sample_rates));
3142 codec->descriptor[1].num_sample_rates =
3143 sizeof(supported_sample_rates)/sizeof(unsigned int);
3144 codec->descriptor[1].bit_rate[0] = 320; /* 320kbps */
3145 codec->descriptor[1].bit_rate[1] = 128;
3146 codec->descriptor[1].num_bitrates = 2;
3147 codec->descriptor[1].profiles = 0;
3148 codec->descriptor[1].modes = 0;
3149 codec->descriptor[1].formats =
3150 (SND_AUDIOSTREAMFORMAT_MP4ADTS |
3151 SND_AUDIOSTREAMFORMAT_RAW);
3152 break;
3153 case SND_AUDIOCODEC_AC3:
3154 case SND_AUDIOCODEC_EAC3:
3155 case SND_AUDIOCODEC_FLAC:
3156 case SND_AUDIOCODEC_VORBIS:
3157 case SND_AUDIOCODEC_ALAC:
3158 case SND_AUDIOCODEC_APE:
3159 case SND_AUDIOCODEC_DTS:
3160 case SND_AUDIOCODEC_DSD:
3161 case SND_AUDIOCODEC_TRUEHD:
3162 case SND_AUDIOCODEC_IEC61937:
3163 case SND_AUDIOCODEC_APTX:
3164 break;
3165 default:
3166 pr_err("%s: Unsupported audio codec %d\n",
3167 __func__, codec->codec);
3168 return -EINVAL;
3169 }
3170
3171 return 0;
3172}
3173
3174static int msm_compr_set_metadata(struct snd_compr_stream *cstream,
3175 struct snd_compr_metadata *metadata)
3176{
3177 struct msm_compr_audio *prtd;
3178 struct audio_client *ac;
3179 pr_debug("%s\n", __func__);
3180
3181 if (!metadata || !cstream)
3182 return -EINVAL;
3183
3184 prtd = cstream->runtime->private_data;
3185 if (!prtd || !prtd->audio_client) {
3186 pr_err("%s: prtd or audio client is NULL\n", __func__);
3187 return -EINVAL;
3188 }
3189
3190 if (((metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) ||
3191 (metadata->key == SNDRV_COMPRESS_ENCODER_DELAY)) &&
3192 (prtd->compr_passthr != LEGACY_PCM)) {
3193 pr_debug("%s: No trailing silence for compress_type[%d]\n",
3194 __func__, prtd->compr_passthr);
3195 return 0;
3196 }
3197
3198 ac = prtd->audio_client;
3199 if (metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) {
3200 pr_debug("%s, got encoder padding %u",
3201 __func__, metadata->value[0]);
3202 prtd->gapless_state.trailing_samples_drop = metadata->value[0];
3203 } else if (metadata->key == SNDRV_COMPRESS_ENCODER_DELAY) {
3204 pr_debug("%s, got encoder delay %u",
3205 __func__, metadata->value[0]);
3206 prtd->gapless_state.initial_samples_drop = metadata->value[0];
3207 } else if (metadata->key == SNDRV_COMPRESS_RENDER_MODE) {
3208 return msm_compr_set_render_mode(prtd, metadata->value[0]);
3209 } else if (metadata->key == SNDRV_COMPRESS_CLK_REC_MODE) {
3210 return msm_compr_set_clk_rec_mode(ac, metadata->value[0]);
3211 } else if (metadata->key == SNDRV_COMPRESS_RENDER_WINDOW) {
3212 return msm_compr_set_render_window(
3213 ac,
3214 metadata->value[0],
3215 metadata->value[1],
3216 metadata->value[2],
3217 metadata->value[3]);
3218 } else if (metadata->key == SNDRV_COMPRESS_START_DELAY) {
3219 prtd->start_delay_lsw = metadata->value[0];
3220 prtd->start_delay_msw = metadata->value[1];
3221 } else if (metadata->key ==
3222 SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK) {
3223 return msm_compr_enable_adjust_session_clock(ac,
3224 metadata->value[0]);
3225 } else if (metadata->key == SNDRV_COMPRESS_ADJUST_SESSION_CLOCK) {
3226 return msm_compr_adjust_session_clock(ac,
3227 metadata->value[0],
3228 metadata->value[1]);
3229 }
3230
3231 return 0;
3232}
3233
3234static int msm_compr_get_metadata(struct snd_compr_stream *cstream,
3235 struct snd_compr_metadata *metadata)
3236{
3237 struct msm_compr_audio *prtd;
3238 struct audio_client *ac;
3239 int ret = -EINVAL;
Surendar Karka38d66472019-03-29 18:08:07 +05303240 uint64_t ses_time = 0, frames = 0, abs_time = 0;
3241 uint64_t *val = NULL;
3242 int64_t av_offset = 0;
3243 int32_t clock_id = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303244
3245 pr_debug("%s\n", __func__);
3246
3247 if (!metadata || !cstream || !cstream->runtime)
3248 return ret;
3249
Surendar Karka38d66472019-03-29 18:08:07 +05303250 if (metadata->key != SNDRV_COMPRESS_PATH_DELAY &&
3251 metadata->key != SNDRV_COMPRESS_DSP_POSITION) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303252 pr_err("%s, unsupported key %d\n", __func__, metadata->key);
3253 return ret;
3254 }
3255
3256 prtd = cstream->runtime->private_data;
3257 if (!prtd || !prtd->audio_client) {
3258 pr_err("%s: prtd or audio client is NULL\n", __func__);
3259 return ret;
3260 }
3261
Surendar Karka38d66472019-03-29 18:08:07 +05303262 switch (metadata->key) {
3263 case SNDRV_COMPRESS_PATH_DELAY:
3264 ac = prtd->audio_client;
3265 ret = q6asm_get_path_delay(prtd->audio_client);
3266 if (ret) {
3267 pr_err("%s: get_path_delay failed, ret=%d\n",
3268 __func__, ret);
3269 return ret;
3270 }
3271
3272 pr_debug("%s, path delay(in us) %u\n", __func__,
3273 ac->path_delay);
3274 metadata->value[0] = ac->path_delay;
3275 break;
3276 case SNDRV_COMPRESS_DSP_POSITION:
3277 clock_id = metadata->value[0];
3278 pr_debug("%s, clock_id %d\n", __func__, clock_id);
3279 ret = q6asm_get_session_time_v2(prtd->audio_client,
3280 &ses_time, &abs_time);
3281 if (ret) {
3282 pr_err("%s: q6asm_get_session_time_v2 failed, ret=%d\n",
3283 __func__, ret);
3284 return ret;
3285 }
3286 frames = div64_u64((ses_time * prtd->sample_rate), 1000000);
3287
3288 ret = avcs_core_query_timer_offset(&av_offset, clock_id);
3289 if (ret) {
3290 pr_err("%s: avcs query failed, ret=%d\n",
3291 __func__, ret);
3292 return ret;
3293 }
3294
3295 val = (uint64_t *) &metadata->value[1];
3296 val[0] = frames;
3297 val[1] = abs_time + av_offset;
3298 pr_debug("%s, vals frames %lld, time %lld, avoff %lld, abst %lld, sess_time %llu sr %d\n",
3299 __func__, val[0], val[1], av_offset, abs_time,
3300 ses_time, prtd->sample_rate);
3301 break;
3302 default:
3303 pr_err("%s, unsupported key %d\n", __func__, metadata->key);
3304 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303305 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303306 return ret;
3307}
3308
3309
3310static int msm_compr_set_next_track_param(struct snd_compr_stream *cstream,
3311 union snd_codec_options *codec_options)
3312{
3313 struct msm_compr_audio *prtd;
3314 struct audio_client *ac;
3315 int ret = 0;
3316
3317 if (!codec_options || !cstream)
3318 return -EINVAL;
3319
3320 prtd = cstream->runtime->private_data;
3321 if (!prtd || !prtd->audio_client) {
3322 pr_err("%s: prtd or audio client is NULL\n", __func__);
3323 return -EINVAL;
3324 }
3325
3326 ac = prtd->audio_client;
3327
3328 pr_debug("%s: got codec options for codec type %u",
3329 __func__, prtd->codec);
3330 switch (prtd->codec) {
3331 case FORMAT_WMA_V9:
3332 case FORMAT_WMA_V10PRO:
3333 case FORMAT_FLAC:
3334 case FORMAT_VORBIS:
3335 case FORMAT_ALAC:
3336 case FORMAT_APE:
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +05303337 case FORMAT_AMRNB:
3338 case FORMAT_AMRWB:
3339 case FORMAT_AMR_WB_PLUS:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303340 memcpy(&(prtd->gapless_state.codec_options),
3341 codec_options,
3342 sizeof(union snd_codec_options));
3343 ret = msm_compr_send_media_format_block(cstream,
3344 ac->stream_id, true);
3345 if (ret < 0) {
3346 pr_err("%s: failed to send media format block\n",
3347 __func__);
3348 }
3349 break;
3350
3351 default:
3352 pr_debug("%s: Ignore sending CMD Format block\n",
3353 __func__);
3354 break;
3355 }
3356
3357 return ret;
3358}
3359
3360static int msm_compr_volume_put(struct snd_kcontrol *kcontrol,
3361 struct snd_ctl_elem_value *ucontrol)
3362{
3363 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3364 unsigned long fe_id = kcontrol->private_value;
3365 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3366 snd_soc_component_get_drvdata(comp);
3367 struct snd_compr_stream *cstream = NULL;
3368 uint32_t *volume = NULL;
3369
3370 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3371 pr_err("%s Received out of bounds fe_id %lu\n",
3372 __func__, fe_id);
3373 return -EINVAL;
3374 }
3375
3376 cstream = pdata->cstream[fe_id];
3377 volume = pdata->volume[fe_id];
3378
3379 volume[0] = ucontrol->value.integer.value[0];
3380 volume[1] = ucontrol->value.integer.value[1];
3381 pr_debug("%s: fe_id %lu left_vol %d right_vol %d\n",
3382 __func__, fe_id, volume[0], volume[1]);
3383 if (cstream)
3384 msm_compr_set_volume(cstream, volume[0], volume[1]);
3385 return 0;
3386}
3387
3388static int msm_compr_volume_get(struct snd_kcontrol *kcontrol,
3389 struct snd_ctl_elem_value *ucontrol)
3390{
3391 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3392 unsigned long fe_id = kcontrol->private_value;
3393
3394 struct msm_compr_pdata *pdata =
3395 snd_soc_component_get_drvdata(comp);
3396 uint32_t *volume = NULL;
3397
3398 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3399 pr_err("%s Received out of bound fe_id %lu\n", __func__, fe_id);
3400 return -EINVAL;
3401 }
3402
3403 volume = pdata->volume[fe_id];
3404 pr_debug("%s: fe_id %lu\n", __func__, fe_id);
3405 ucontrol->value.integer.value[0] = volume[0];
3406 ucontrol->value.integer.value[1] = volume[1];
3407
3408 return 0;
3409}
3410
3411static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
3412 struct snd_ctl_elem_value *ucontrol)
3413{
3414 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3415 unsigned long fe_id = kcontrol->private_value;
3416 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3417 snd_soc_component_get_drvdata(comp);
3418 struct msm_compr_audio_effects *audio_effects = NULL;
3419 struct snd_compr_stream *cstream = NULL;
3420 struct msm_compr_audio *prtd = NULL;
3421 long *values = &(ucontrol->value.integer.value[0]);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303422 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303423 int effects_module;
3424
3425 pr_debug("%s\n", __func__);
3426 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3427 pr_err("%s Received out of bounds fe_id %lu\n",
3428 __func__, fe_id);
3429 return -EINVAL;
3430 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303431
3432 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303433 cstream = pdata->cstream[fe_id];
3434 audio_effects = pdata->audio_effects[fe_id];
3435 if (!cstream || !audio_effects) {
3436 pr_err("%s: stream or effects inactive\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303437 ret = -EINVAL;
3438 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303439 }
3440 prtd = cstream->runtime->private_data;
3441 if (!prtd) {
3442 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303443 ret = -EINVAL;
3444 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303445 }
3446 if (prtd->compr_passthr != LEGACY_PCM) {
3447 pr_debug("%s: No effects for compr_type[%d]\n",
3448 __func__, prtd->compr_passthr);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303449 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303450 }
3451 pr_debug("%s: Effects supported for compr_type[%d]\n",
3452 __func__, prtd->compr_passthr);
3453
3454 effects_module = *values++;
3455 switch (effects_module) {
3456 case VIRTUALIZER_MODULE:
3457 pr_debug("%s: VIRTUALIZER_MODULE\n", __func__);
3458 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3459 prtd->audio_client->topology))
3460 msm_audio_effects_virtualizer_handler(
3461 prtd->audio_client,
3462 &(audio_effects->virtualizer),
3463 values);
3464 break;
3465 case REVERB_MODULE:
3466 pr_debug("%s: REVERB_MODULE\n", __func__);
3467 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3468 prtd->audio_client->topology))
3469 msm_audio_effects_reverb_handler(prtd->audio_client,
3470 &(audio_effects->reverb),
3471 values);
3472 break;
3473 case BASS_BOOST_MODULE:
3474 pr_debug("%s: BASS_BOOST_MODULE\n", __func__);
3475 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3476 prtd->audio_client->topology))
3477 msm_audio_effects_bass_boost_handler(prtd->audio_client,
3478 &(audio_effects->bass_boost),
3479 values);
3480 break;
3481 case PBE_MODULE:
3482 pr_debug("%s: PBE_MODULE\n", __func__);
3483 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3484 prtd->audio_client->topology))
3485 msm_audio_effects_pbe_handler(prtd->audio_client,
3486 &(audio_effects->pbe),
3487 values);
3488 break;
3489 case EQ_MODULE:
3490 pr_debug("%s: EQ_MODULE\n", __func__);
3491 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3492 prtd->audio_client->topology))
3493 msm_audio_effects_popless_eq_handler(prtd->audio_client,
3494 &(audio_effects->equalizer),
3495 values);
3496 break;
3497 case SOFT_VOLUME_MODULE:
3498 pr_debug("%s: SOFT_VOLUME_MODULE\n", __func__);
3499 break;
3500 case SOFT_VOLUME2_MODULE:
3501 pr_debug("%s: SOFT_VOLUME2_MODULE\n", __func__);
3502 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3503 prtd->audio_client->topology))
3504 msm_audio_effects_volume_handler_v2(prtd->audio_client,
3505 &(audio_effects->volume),
3506 values, SOFT_VOLUME_INSTANCE_2);
3507 break;
3508 default:
3509 pr_err("%s Invalid effects config module\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303510 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303511 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303512done:
3513 mutex_unlock(&pdata->lock);
3514 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303515}
3516
3517static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol,
3518 struct snd_ctl_elem_value *ucontrol)
3519{
3520 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3521 unsigned long fe_id = kcontrol->private_value;
3522 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3523 snd_soc_component_get_drvdata(comp);
3524 struct msm_compr_audio_effects *audio_effects = NULL;
3525 struct snd_compr_stream *cstream = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303526 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303527 struct msm_compr_audio *prtd = NULL;
3528
3529 pr_debug("%s\n", __func__);
3530 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3531 pr_err("%s Received out of bounds fe_id %lu\n",
3532 __func__, fe_id);
3533 return -EINVAL;
3534 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303535
3536 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303537 cstream = pdata->cstream[fe_id];
3538 audio_effects = pdata->audio_effects[fe_id];
3539 if (!cstream || !audio_effects) {
Vignesh Kulothungan2ce67842018-09-25 16:40:29 -07003540 pr_debug("%s: stream or effects inactive\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303541 ret = -EINVAL;
3542 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303543 }
3544 prtd = cstream->runtime->private_data;
3545 if (!prtd) {
3546 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303547 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303548 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303549done:
3550 mutex_unlock(&pdata->lock);
3551 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303552}
3553
3554static int msm_compr_query_audio_effect_put(struct snd_kcontrol *kcontrol,
3555 struct snd_ctl_elem_value *ucontrol)
3556{
3557 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3558 unsigned long fe_id = kcontrol->private_value;
3559 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3560 snd_soc_component_get_drvdata(comp);
3561 struct msm_compr_audio_effects *audio_effects = NULL;
3562 struct snd_compr_stream *cstream = NULL;
3563 struct msm_compr_audio *prtd = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303564 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303565 long *values = &(ucontrol->value.integer.value[0]);
3566
3567 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3568 pr_err("%s Received out of bounds fe_id %lu\n",
3569 __func__, fe_id);
3570 return -EINVAL;
3571 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303572
3573 mutex_lock(&pdata->lock);
3574
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303575 cstream = pdata->cstream[fe_id];
3576 audio_effects = pdata->audio_effects[fe_id];
3577 if (!cstream || !audio_effects) {
3578 pr_err("%s: stream or effects inactive\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303579 ret = -EINVAL;
3580 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303581 }
3582 prtd = cstream->runtime->private_data;
3583 if (!prtd) {
3584 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303585 ret = -EINVAL;
3586 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303587 }
3588 if (prtd->compr_passthr != LEGACY_PCM) {
3589 pr_err("%s: No effects for compr_type[%d]\n",
3590 __func__, prtd->compr_passthr);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303591 ret = -EPERM;
3592 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303593 }
3594 audio_effects->query.mod_id = (u32)*values++;
3595 audio_effects->query.parm_id = (u32)*values++;
3596 audio_effects->query.size = (u32)*values++;
3597 audio_effects->query.offset = (u32)*values++;
3598 audio_effects->query.device = (u32)*values++;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303599
3600done:
3601 mutex_unlock(&pdata->lock);
3602 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303603}
3604
3605static int msm_compr_query_audio_effect_get(struct snd_kcontrol *kcontrol,
3606 struct snd_ctl_elem_value *ucontrol)
3607{
3608 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3609 unsigned long fe_id = kcontrol->private_value;
3610 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3611 snd_soc_component_get_drvdata(comp);
3612 struct msm_compr_audio_effects *audio_effects = NULL;
3613 struct snd_compr_stream *cstream = NULL;
3614 struct msm_compr_audio *prtd = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303615 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303616 long *values = &(ucontrol->value.integer.value[0]);
3617
3618 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3619 pr_err("%s Received out of bounds fe_id %lu\n",
3620 __func__, fe_id);
3621 return -EINVAL;
3622 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303623
3624 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303625 cstream = pdata->cstream[fe_id];
3626 audio_effects = pdata->audio_effects[fe_id];
3627 if (!cstream || !audio_effects) {
3628 pr_debug("%s: stream or effects inactive\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303629 ret = -EINVAL;
3630 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303631 }
3632 prtd = cstream->runtime->private_data;
3633 if (!prtd) {
3634 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303635 ret = -EINVAL;
3636 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303637 }
3638 values[0] = (long)audio_effects->query.mod_id;
3639 values[1] = (long)audio_effects->query.parm_id;
3640 values[2] = (long)audio_effects->query.size;
3641 values[3] = (long)audio_effects->query.offset;
3642 values[4] = (long)audio_effects->query.device;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303643done:
3644 mutex_unlock(&pdata->lock);
3645 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303646}
3647
3648static int msm_compr_send_dec_params(struct snd_compr_stream *cstream,
3649 struct msm_compr_dec_params *dec_params,
3650 int stream_id)
3651{
3652
3653 int rc = 0;
3654 struct msm_compr_audio *prtd = NULL;
3655 struct snd_dec_ddp *ddp = &dec_params->ddp_params;
3656
3657 if (!cstream || !dec_params) {
3658 pr_err("%s: stream or dec_params inactive\n", __func__);
3659 rc = -EINVAL;
3660 goto end;
3661 }
3662 prtd = cstream->runtime->private_data;
3663 if (!prtd) {
3664 pr_err("%s: cannot set dec_params\n", __func__);
3665 rc = -EINVAL;
3666 goto end;
3667 }
3668 switch (prtd->codec) {
3669 case FORMAT_MP3:
3670 case FORMAT_MPEG4_AAC:
3671 case FORMAT_TRUEHD:
3672 case FORMAT_IEC61937:
3673 case FORMAT_APTX:
3674 pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
3675 prtd->codec);
3676 break;
3677 case FORMAT_AC3:
3678 case FORMAT_EAC3:
3679 if (prtd->compr_passthr != LEGACY_PCM) {
3680 pr_debug("%s: No DDP param for compr_type[%d]\n",
3681 __func__, prtd->compr_passthr);
3682 break;
3683 }
3684 rc = msm_compr_send_ddp_cfg(prtd->audio_client, ddp, stream_id);
3685 if (rc < 0)
3686 pr_err("%s: DDP CMD CFG failed %d\n", __func__, rc);
3687 break;
3688 default:
3689 break;
3690 }
3691end:
3692 return rc;
3693
3694}
3695static int msm_compr_dec_params_put(struct snd_kcontrol *kcontrol,
3696 struct snd_ctl_elem_value *ucontrol)
3697{
3698 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3699 unsigned long fe_id = kcontrol->private_value;
3700 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3701 snd_soc_component_get_drvdata(comp);
3702 struct msm_compr_dec_params *dec_params = NULL;
3703 struct snd_compr_stream *cstream = NULL;
3704 struct msm_compr_audio *prtd = NULL;
3705 long *values = &(ucontrol->value.integer.value[0]);
3706 int rc = 0;
3707
3708 pr_debug("%s\n", __func__);
3709 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3710 pr_err("%s Received out of bounds fe_id %lu\n",
3711 __func__, fe_id);
3712 rc = -EINVAL;
3713 goto end;
3714 }
3715
3716 cstream = pdata->cstream[fe_id];
3717 dec_params = pdata->dec_params[fe_id];
3718
3719 if (!cstream || !dec_params) {
3720 pr_err("%s: stream or dec_params inactive\n", __func__);
3721 rc = -EINVAL;
3722 goto end;
3723 }
3724 prtd = cstream->runtime->private_data;
3725 if (!prtd) {
3726 pr_err("%s: cannot set dec_params\n", __func__);
3727 rc = -EINVAL;
3728 goto end;
3729 }
3730
Ajit Pandeyfa018862019-09-04 14:34:00 +05303731 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303732 switch (prtd->codec) {
3733 case FORMAT_MP3:
3734 case FORMAT_MPEG4_AAC:
3735 case FORMAT_FLAC:
3736 case FORMAT_VORBIS:
3737 case FORMAT_ALAC:
3738 case FORMAT_APE:
3739 case FORMAT_DTS:
3740 case FORMAT_DSD:
3741 case FORMAT_TRUEHD:
3742 case FORMAT_IEC61937:
3743 case FORMAT_APTX:
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +05303744 case FORMAT_AMRNB:
3745 case FORMAT_AMRWB:
3746 case FORMAT_AMR_WB_PLUS:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303747 pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
3748 prtd->codec);
3749 break;
3750 case FORMAT_AC3:
3751 case FORMAT_EAC3: {
3752 struct snd_dec_ddp *ddp = &dec_params->ddp_params;
3753 int cnt;
3754
3755 if (prtd->compr_passthr != LEGACY_PCM) {
3756 pr_debug("%s: No DDP param for compr_type[%d]\n",
3757 __func__, prtd->compr_passthr);
3758 break;
3759 }
3760
3761 ddp->params_length = (*values++);
3762 if (ddp->params_length > DDP_DEC_MAX_NUM_PARAM) {
3763 pr_err("%s: invalid num of params:: %d\n", __func__,
3764 ddp->params_length);
3765 rc = -EINVAL;
3766 goto end;
3767 }
3768 for (cnt = 0; cnt < ddp->params_length; cnt++) {
3769 ddp->params_id[cnt] = *values++;
3770 ddp->params_value[cnt] = *values++;
3771 }
3772 prtd = cstream->runtime->private_data;
3773 if (prtd && prtd->audio_client)
3774 rc = msm_compr_send_dec_params(cstream, dec_params,
3775 prtd->audio_client->stream_id);
3776 break;
3777 }
3778 default:
3779 break;
3780 }
3781end:
3782 pr_debug("%s: ret %d\n", __func__, rc);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303783 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303784 return rc;
3785}
3786
3787static int msm_compr_dec_params_get(struct snd_kcontrol *kcontrol,
3788 struct snd_ctl_elem_value *ucontrol)
3789{
3790 /* dummy function */
3791 return 0;
3792}
3793
3794static int msm_compr_playback_app_type_cfg_put(struct snd_kcontrol *kcontrol,
3795 struct snd_ctl_elem_value *ucontrol)
3796{
3797 u64 fe_id = kcontrol->private_value;
3798 int session_type = SESSION_TYPE_RX;
3799 int be_id = ucontrol->value.integer.value[3];
3800 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
3801 int ret = 0;
3802
3803 cfg_data.app_type = ucontrol->value.integer.value[0];
3804 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
3805 if (ucontrol->value.integer.value[2] != 0)
3806 cfg_data.sample_rate = ucontrol->value.integer.value[2];
3807 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
3808 __func__, fe_id, session_type, be_id,
3809 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3810 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
3811 be_id, &cfg_data);
3812 if (ret < 0)
3813 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
3814 __func__, ret);
3815
3816 return ret;
3817}
3818
3819static int msm_compr_playback_app_type_cfg_get(struct snd_kcontrol *kcontrol,
3820 struct snd_ctl_elem_value *ucontrol)
3821{
3822 u64 fe_id = kcontrol->private_value;
3823 int session_type = SESSION_TYPE_RX;
3824 int be_id = 0;
3825 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
3826 int ret = 0;
3827
3828 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
3829 &be_id, &cfg_data);
3830 if (ret < 0) {
3831 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
3832 __func__, ret);
3833 goto done;
3834 }
3835
3836 ucontrol->value.integer.value[0] = cfg_data.app_type;
3837 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
3838 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
3839 ucontrol->value.integer.value[3] = be_id;
3840 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
3841 __func__, fe_id, session_type, be_id,
3842 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3843done:
3844 return ret;
3845}
3846
3847static int msm_compr_capture_app_type_cfg_put(struct snd_kcontrol *kcontrol,
3848 struct snd_ctl_elem_value *ucontrol)
3849{
3850 u64 fe_id = kcontrol->private_value;
3851 int session_type = SESSION_TYPE_TX;
3852 int be_id = ucontrol->value.integer.value[3];
3853 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
3854 int ret = 0;
3855
3856 cfg_data.app_type = ucontrol->value.integer.value[0];
3857 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
3858 if (ucontrol->value.integer.value[2] != 0)
3859 cfg_data.sample_rate = ucontrol->value.integer.value[2];
3860 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
3861 __func__, fe_id, session_type, be_id,
3862 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3863 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
3864 be_id, &cfg_data);
3865 if (ret < 0)
3866 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
3867 __func__, ret);
3868
3869 return ret;
3870}
3871
3872static int msm_compr_capture_app_type_cfg_get(struct snd_kcontrol *kcontrol,
3873 struct snd_ctl_elem_value *ucontrol)
3874{
3875 u64 fe_id = kcontrol->private_value;
3876 int session_type = SESSION_TYPE_TX;
3877 int be_id = 0;
3878 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
3879 int ret = 0;
3880
3881 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
3882 &be_id, &cfg_data);
3883 if (ret < 0) {
3884 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
3885 __func__, ret);
3886 goto done;
3887 }
3888
3889 ucontrol->value.integer.value[0] = cfg_data.app_type;
3890 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
3891 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
3892 ucontrol->value.integer.value[3] = be_id;
3893 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
3894 __func__, fe_id, session_type, be_id,
3895 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3896done:
3897 return ret;
3898}
3899
3900static int msm_compr_channel_map_put(struct snd_kcontrol *kcontrol,
3901 struct snd_ctl_elem_value *ucontrol)
3902{
3903 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3904 u64 fe_id = kcontrol->private_value;
3905 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3906 snd_soc_component_get_drvdata(comp);
3907 int rc = 0, i;
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05303908 struct msm_pcm_channel_mixer *chmixer_pspd = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303909
3910 pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
3911
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05303912 if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303913 pr_err("%s Received out of bounds fe_id %llu\n",
3914 __func__, fe_id);
3915 rc = -EINVAL;
3916 goto end;
3917 }
3918
3919 if (pdata->ch_map[fe_id]) {
3920 pdata->ch_map[fe_id]->set_ch_map = true;
Dieter Lueckingceef9af2018-09-28 15:09:32 +02003921 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303922 pdata->ch_map[fe_id]->channel_map[i] =
3923 (char)(ucontrol->value.integer.value[i]);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05303924
3925 /* update chmixer_pspd chmap cached with routing driver as well */
3926 chmixer_pspd = pdata->chmixer_pspd[fe_id];
3927 if (chmixer_pspd && chmixer_pspd->enable) {
3928 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
3929 chmixer_pspd->in_ch_map[i] =
3930 pdata->ch_map[fe_id]->channel_map[i];
3931 chmixer_pspd->override_in_ch_map = true;
3932 msm_pcm_routing_set_channel_mixer_cfg(fe_id,
3933 SESSION_TYPE_RX, chmixer_pspd);
3934 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303935 } else {
3936 pr_debug("%s: no memory for ch_map, default will be set\n",
3937 __func__);
3938 }
3939end:
3940 pr_debug("%s: ret %d\n", __func__, rc);
3941 return rc;
3942}
3943
3944static int msm_compr_channel_map_get(struct snd_kcontrol *kcontrol,
3945 struct snd_ctl_elem_value *ucontrol)
3946{
3947 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3948 u64 fe_id = kcontrol->private_value;
3949 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3950 snd_soc_component_get_drvdata(comp);
3951 int rc = 0, i;
3952
3953 pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05303954 if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303955 pr_err("%s: Received out of bounds fe_id %llu\n",
3956 __func__, fe_id);
3957 rc = -EINVAL;
3958 goto end;
3959 }
3960 if (pdata->ch_map[fe_id]) {
Dieter Lueckingceef9af2018-09-28 15:09:32 +02003961 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303962 ucontrol->value.integer.value[i] =
3963 pdata->ch_map[fe_id]->channel_map[i];
3964 }
3965end:
3966 pr_debug("%s: ret %d\n", __func__, rc);
3967 return rc;
3968}
3969
3970static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
3971 struct snd_ctl_elem_value *ucontrol)
3972{
3973 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3974 unsigned long fe_id = kcontrol->private_value;
3975 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3976 snd_soc_component_get_drvdata(comp);
3977 struct snd_compr_stream *cstream = NULL;
3978 struct msm_compr_audio *prtd;
3979 int ret = 0;
3980 struct msm_adsp_event_data *event_data = NULL;
3981
3982 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3983 pr_err("%s Received invalid fe_id %lu\n",
3984 __func__, fe_id);
3985 ret = -EINVAL;
3986 goto done;
3987 }
3988
3989 cstream = pdata->cstream[fe_id];
3990 if (cstream == NULL) {
3991 pr_err("%s cstream is null\n", __func__);
3992 ret = -EINVAL;
3993 goto done;
3994 }
3995
3996 prtd = cstream->runtime->private_data;
3997 if (!prtd) {
3998 pr_err("%s: prtd is null\n", __func__);
3999 ret = -EINVAL;
4000 goto done;
4001 }
4002
Ajit Pandeyfa018862019-09-04 14:34:00 +05304003 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304004 if (prtd->audio_client == NULL) {
4005 pr_err("%s: audio_client is null\n", __func__);
4006 ret = -EINVAL;
4007 goto done;
4008 }
4009
4010 event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data;
4011 if ((event_data->event_type < ADSP_STREAM_PP_EVENT) ||
4012 (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) {
4013 pr_err("%s: invalid event_type=%d",
4014 __func__, event_data->event_type);
4015 ret = -EINVAL;
4016 goto done;
4017 }
4018
Xiaojun Sang75642c32018-03-23 08:57:33 +08004019 if (event_data->payload_len > sizeof(ucontrol->value.bytes.data)
4020 - sizeof(struct msm_adsp_event_data)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304021 pr_err("%s param length=%d exceeds limit",
4022 __func__, event_data->payload_len);
4023 ret = -EINVAL;
4024 goto done;
4025 }
4026
4027 ret = q6asm_send_stream_cmd(prtd->audio_client, event_data);
4028 if (ret < 0)
4029 pr_err("%s: failed to send stream event cmd, err = %d\n",
4030 __func__, ret);
4031done:
Ajit Pandeyfa018862019-09-04 14:34:00 +05304032 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304033 return ret;
4034}
4035
4036static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
4037 struct snd_ctl_elem_value *ucontrol)
4038{
4039 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4040 unsigned long fe_id = kcontrol->private_value;
4041 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4042 snd_soc_component_get_drvdata(comp);
4043 struct snd_compr_stream *cstream = NULL;
4044 struct msm_compr_audio *prtd;
4045 int fd;
4046 int ret = 0;
4047
4048 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
4049 pr_err("%s Received out of bounds invalid fe_id %lu\n",
4050 __func__, fe_id);
4051 ret = -EINVAL;
4052 goto done;
4053 }
4054
4055 cstream = pdata->cstream[fe_id];
4056 if (cstream == NULL) {
4057 pr_err("%s cstream is null\n", __func__);
4058 ret = -EINVAL;
4059 goto done;
4060 }
4061
4062 prtd = cstream->runtime->private_data;
4063 if (!prtd) {
4064 pr_err("%s: prtd is null\n", __func__);
4065 ret = -EINVAL;
4066 goto done;
4067 }
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);
4100 ret = -EINVAL;
4101 goto done;
4102 }
4103
Ajit Pandeyfa018862019-09-04 14:34:00 +05304104 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304105 cstream = pdata->cstream[fe_id];
4106 if (cstream == NULL) {
4107 pr_err("%s cstream is null\n", __func__);
4108 ret = -EINVAL;
4109 goto done;
4110 }
4111
4112 prtd = cstream->runtime->private_data;
4113 if (!prtd) {
4114 pr_err("%s: prtd is null\n", __func__);
4115 ret = -EINVAL;
4116 goto done;
4117 }
4118
4119 if (prtd->audio_client == NULL) {
4120 pr_err("%s: audio_client is null\n", __func__);
4121 ret = -EINVAL;
4122 goto done;
4123 }
4124
4125 memcpy(&param_length, ucontrol->value.bytes.data,
4126 sizeof(param_length));
4127 if ((param_length + sizeof(param_length))
4128 >= sizeof(ucontrol->value.bytes.data)) {
4129 pr_err("%s param length=%d exceeds limit",
4130 __func__, param_length);
4131 ret = -EINVAL;
4132 goto done;
4133 }
4134
4135 ret = q6asm_send_rtic_event_ack(prtd->audio_client,
4136 ucontrol->value.bytes.data + sizeof(param_length),
4137 param_length);
4138 if (ret < 0)
4139 pr_err("%s: failed to send rtic event ack, err = %d\n",
4140 __func__, ret);
4141done:
Ajit Pandeyfa018862019-09-04 14:34:00 +05304142 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304143 return ret;
4144}
4145
4146static int msm_compr_gapless_put(struct snd_kcontrol *kcontrol,
4147 struct snd_ctl_elem_value *ucontrol)
4148{
4149 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4150 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4151 snd_soc_component_get_drvdata(comp);
4152 pdata->use_dsp_gapless_mode = ucontrol->value.integer.value[0];
4153 pr_debug("%s: value: %ld\n", __func__,
4154 ucontrol->value.integer.value[0]);
4155
4156 return 0;
4157}
4158
4159static int msm_compr_gapless_get(struct snd_kcontrol *kcontrol,
4160 struct snd_ctl_elem_value *ucontrol)
4161{
4162 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4163 struct msm_compr_pdata *pdata =
4164 snd_soc_component_get_drvdata(comp);
4165 pr_debug("%s:gapless mode %d\n", __func__, pdata->use_dsp_gapless_mode);
4166 ucontrol->value.integer.value[0] = pdata->use_dsp_gapless_mode;
4167
4168 return 0;
4169}
4170
4171static const struct snd_kcontrol_new msm_compr_gapless_controls[] = {
4172 SOC_SINGLE_EXT("Compress Gapless Playback",
4173 0, 0, 1, 0,
4174 msm_compr_gapless_get,
4175 msm_compr_gapless_put),
4176};
4177
Meng Wangee084a02018-09-04 16:11:58 +08004178static int msm_compr_probe(struct snd_soc_component *component)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304179{
4180 struct msm_compr_pdata *pdata;
4181 int i;
4182 int rc;
4183 const char *qdsp_version;
4184
4185 pr_debug("%s\n", __func__);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304186 pdata = (struct msm_compr_pdata *) dev_get_drvdata(component->dev);
4187 if (!pdata) {
4188 pr_err("%s platform data not set\n", __func__);
4189 return -EINVAL;
4190 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304191
Meng Wangee084a02018-09-04 16:11:58 +08004192 snd_soc_component_set_drvdata(component, pdata);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304193
4194 for (i = 0; i < MSM_FRONTEND_DAI_MAX; i++) {
4195 pdata->volume[i][0] = COMPRESSED_LR_VOL_MAX_STEPS;
4196 pdata->volume[i][1] = COMPRESSED_LR_VOL_MAX_STEPS;
4197 pdata->audio_effects[i] = NULL;
4198 pdata->dec_params[i] = NULL;
4199 pdata->cstream[i] = NULL;
4200 pdata->ch_map[i] = NULL;
Aditya Bavanari9deef912017-11-20 13:31:31 +05304201 pdata->is_in_use[i] = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304202 }
4203
Meng Wangee084a02018-09-04 16:11:58 +08004204 snd_soc_add_component_controls(component, msm_compr_gapless_controls,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304205 ARRAY_SIZE(msm_compr_gapless_controls));
4206
Meng Wangee084a02018-09-04 16:11:58 +08004207 rc = of_property_read_string(component->dev->of_node,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304208 "qcom,adsp-version", &qdsp_version);
4209 if (!rc) {
4210 if (!strcmp(qdsp_version, "MDSP 1.2"))
4211 pdata->use_legacy_api = true;
4212 else
4213 pdata->use_legacy_api = false;
4214 } else
4215 pdata->use_legacy_api = false;
4216
4217 pr_debug("%s: use legacy api %d\n", __func__, pdata->use_legacy_api);
4218 /*
4219 * use_dsp_gapless_mode part of platform data(pdata) is updated from HAL
4220 * through a mixer control before compress driver is opened. The mixer
4221 * control is used to decide if dsp gapless mode needs to be enabled.
4222 * Gapless is disabled by default.
4223 */
4224 pdata->use_dsp_gapless_mode = false;
4225 return 0;
4226}
4227
4228static int msm_compr_volume_info(struct snd_kcontrol *kcontrol,
4229 struct snd_ctl_elem_info *uinfo)
4230{
4231 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4232 uinfo->count = 2;
4233 uinfo->value.integer.min = 0;
4234 uinfo->value.integer.max = COMPRESSED_LR_VOL_MAX_STEPS;
4235 return 0;
4236}
4237
4238static int msm_compr_audio_effects_config_info(struct snd_kcontrol *kcontrol,
4239 struct snd_ctl_elem_info *uinfo)
4240{
4241 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4242 uinfo->count = MAX_PP_PARAMS_SZ;
4243 uinfo->value.integer.min = 0;
4244 uinfo->value.integer.max = 0xFFFFFFFF;
4245 return 0;
4246}
4247
4248static int msm_compr_query_audio_effect_info(struct snd_kcontrol *kcontrol,
4249 struct snd_ctl_elem_info *uinfo)
4250{
4251 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4252 uinfo->count = 128;
4253 uinfo->value.integer.min = 0;
4254 uinfo->value.integer.max = 0xFFFFFFFF;
4255 return 0;
4256}
4257
4258static int msm_compr_dec_params_info(struct snd_kcontrol *kcontrol,
4259 struct snd_ctl_elem_info *uinfo)
4260{
4261 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4262 uinfo->count = 128;
4263 uinfo->value.integer.min = 0;
4264 uinfo->value.integer.max = 0xFFFFFFFF;
4265 return 0;
4266}
4267
4268static int msm_compr_app_type_cfg_info(struct snd_kcontrol *kcontrol,
4269 struct snd_ctl_elem_info *uinfo)
4270{
4271 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4272 uinfo->count = 5;
4273 uinfo->value.integer.min = 0;
4274 uinfo->value.integer.max = 0xFFFFFFFF;
4275 return 0;
4276}
4277
4278static int msm_compr_channel_map_info(struct snd_kcontrol *kcontrol,
4279 struct snd_ctl_elem_info *uinfo)
4280{
4281 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
Dieter Lueckingceef9af2018-09-28 15:09:32 +02004282 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304283 uinfo->value.integer.min = 0;
Surendar Karka59769532019-08-05 16:02:32 +05304284 /* See PCM_MAX_CHANNEL_MAP in apr_audio-v2.h */
4285 uinfo->value.integer.max = PCM_MAX_CHANNEL_MAP;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304286 return 0;
4287}
4288
4289static int msm_compr_add_volume_control(struct snd_soc_pcm_runtime *rtd)
4290{
Meng Wangee084a02018-09-04 16:11:58 +08004291 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304292 const char *mixer_ctl_name = "Compress Playback";
4293 const char *deviceNo = "NN";
4294 const char *suffix = "Volume";
4295 char *mixer_str = NULL;
4296 int ctl_len;
4297 struct snd_kcontrol_new fe_volume_control[1] = {
4298 {
4299 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4300 .name = "?",
4301 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
4302 SNDRV_CTL_ELEM_ACCESS_READWRITE,
4303 .info = msm_compr_volume_info,
4304 .tlv.p = msm_compr_vol_gain,
4305 .get = msm_compr_volume_get,
4306 .put = msm_compr_volume_put,
4307 .private_value = 0,
4308 }
4309 };
4310
4311 if (!rtd) {
4312 pr_err("%s NULL rtd\n", __func__);
4313 return 0;
4314 }
Meng Wangee084a02018-09-04 16:11:58 +08004315 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4316 if (!component) {
4317 pr_err("%s: component is NULL\n", __func__);
4318 return 0;
4319 }
4320
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304321 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4322 __func__, rtd->dai_link->name, rtd->dai_link->id,
4323 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4324 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
4325 strlen(suffix) + 1;
4326 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4327 if (!mixer_str) {
4328 pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
4329 return 0;
4330 }
4331 snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
4332 rtd->pcm->device, suffix);
4333 fe_volume_control[0].name = mixer_str;
4334 fe_volume_control[0].private_value = rtd->dai_link->id;
4335 pr_debug("Registering new mixer ctl %s", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004336 snd_soc_add_component_controls(component, fe_volume_control,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304337 ARRAY_SIZE(fe_volume_control));
4338 kfree(mixer_str);
4339 return 0;
4340}
4341
4342static int msm_compr_add_audio_effects_control(struct snd_soc_pcm_runtime *rtd)
4343{
Meng Wangee084a02018-09-04 16:11:58 +08004344 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304345 const char *mixer_ctl_name = "Audio Effects Config";
4346 const char *deviceNo = "NN";
4347 char *mixer_str = NULL;
4348 int ctl_len;
4349 struct snd_kcontrol_new fe_audio_effects_config_control[1] = {
4350 {
4351 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4352 .name = "?",
4353 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4354 .info = msm_compr_audio_effects_config_info,
4355 .get = msm_compr_audio_effects_config_get,
4356 .put = msm_compr_audio_effects_config_put,
4357 .private_value = 0,
4358 }
4359 };
4360
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304361 if (!rtd) {
4362 pr_err("%s NULL rtd\n", __func__);
4363 return 0;
4364 }
4365
Meng Wangee084a02018-09-04 16:11:58 +08004366 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4367 if (!component) {
4368 pr_err("%s: component is NULL\n", __func__);
4369 return 0;
4370 }
4371
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304372 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4373 __func__, rtd->dai_link->name, rtd->dai_link->id,
4374 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4375
4376 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4377 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4378
4379 if (!mixer_str)
4380 return 0;
4381
4382 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4383
4384 fe_audio_effects_config_control[0].name = mixer_str;
4385 fe_audio_effects_config_control[0].private_value = rtd->dai_link->id;
4386 pr_debug("Registering new mixer ctl %s\n", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004387 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304388 fe_audio_effects_config_control,
4389 ARRAY_SIZE(fe_audio_effects_config_control));
4390 kfree(mixer_str);
4391 return 0;
4392}
4393
4394static int msm_compr_add_query_audio_effect_control(
4395 struct snd_soc_pcm_runtime *rtd)
4396{
Meng Wangee084a02018-09-04 16:11:58 +08004397 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304398 const char *mixer_ctl_name = "Query Audio Effect Param";
4399 const char *deviceNo = "NN";
4400 char *mixer_str = NULL;
4401 int ctl_len;
4402 struct snd_kcontrol_new fe_query_audio_effect_control[1] = {
4403 {
4404 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4405 .name = "?",
4406 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4407 .info = msm_compr_query_audio_effect_info,
4408 .get = msm_compr_query_audio_effect_get,
4409 .put = msm_compr_query_audio_effect_put,
4410 .private_value = 0,
4411 }
4412 };
4413 if (!rtd) {
4414 pr_err("%s NULL rtd\n", __func__);
4415 return 0;
4416 }
Meng Wangee084a02018-09-04 16:11:58 +08004417
4418 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4419 if (!component) {
4420 pr_err("%s: component is NULL\n", __func__);
4421 return 0;
4422 }
4423
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304424 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4425 __func__, rtd->dai_link->name, rtd->dai_link->id,
4426 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4427 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4428 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4429 if (!mixer_str) {
4430 pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
4431 return 0;
4432 }
4433 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4434 fe_query_audio_effect_control[0].name = mixer_str;
4435 fe_query_audio_effect_control[0].private_value = rtd->dai_link->id;
4436 pr_debug("%s: registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004437 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304438 fe_query_audio_effect_control,
4439 ARRAY_SIZE(fe_query_audio_effect_control));
4440 kfree(mixer_str);
4441 return 0;
4442}
4443
4444static int msm_compr_add_audio_adsp_stream_cmd_control(
4445 struct snd_soc_pcm_runtime *rtd)
4446{
Meng Wangee084a02018-09-04 16:11:58 +08004447 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304448 const char *mixer_ctl_name = DSP_STREAM_CMD;
4449 const char *deviceNo = "NN";
4450 char *mixer_str = NULL;
4451 int ctl_len = 0, ret = 0;
4452 struct snd_kcontrol_new fe_audio_adsp_stream_cmd_config_control[1] = {
4453 {
4454 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4455 .name = "?",
4456 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4457 .info = msm_adsp_stream_cmd_info,
4458 .put = msm_compr_adsp_stream_cmd_put,
4459 .private_value = 0,
4460 }
4461 };
4462
4463 if (!rtd) {
4464 pr_err("%s NULL rtd\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08004465 return -EINVAL;
4466 }
4467
4468 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4469 if (!component) {
4470 pr_err("%s: component is NULL\n", __func__);
4471 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304472 }
4473
4474 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4475 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08004476 if (!mixer_str)
4477 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304478
4479 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4480 fe_audio_adsp_stream_cmd_config_control[0].name = mixer_str;
4481 fe_audio_adsp_stream_cmd_config_control[0].private_value =
4482 rtd->dai_link->id;
4483 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004484 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304485 fe_audio_adsp_stream_cmd_config_control,
4486 ARRAY_SIZE(fe_audio_adsp_stream_cmd_config_control));
4487 if (ret < 0)
4488 pr_err("%s: failed to add ctl %s. err = %d\n",
4489 __func__, mixer_str, ret);
4490
4491 kfree(mixer_str);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304492 return ret;
4493}
4494
4495static int msm_compr_add_audio_adsp_stream_callback_control(
4496 struct snd_soc_pcm_runtime *rtd)
4497{
Meng Wangee084a02018-09-04 16:11:58 +08004498 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304499 const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
4500 const char *deviceNo = "NN";
4501 char *mixer_str = NULL;
4502 int ctl_len = 0, ret = 0;
4503 struct snd_kcontrol *kctl;
4504
4505 struct snd_kcontrol_new fe_audio_adsp_callback_config_control[1] = {
4506 {
4507 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4508 .name = "?",
4509 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4510 .info = msm_adsp_stream_callback_info,
4511 .get = msm_adsp_stream_callback_get,
4512 .private_value = 0,
4513 }
4514 };
4515
4516 if (!rtd) {
4517 pr_err("%s: rtd is NULL\n", __func__);
4518 ret = -EINVAL;
4519 goto done;
4520 }
4521
Meng Wangee084a02018-09-04 16:11:58 +08004522 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4523 if (!component) {
4524 pr_err("%s: component is NULL\n", __func__);
4525 return -EINVAL;
4526 }
4527
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304528 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4529 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4530 if (!mixer_str) {
4531 ret = -ENOMEM;
4532 goto done;
4533 }
4534
4535 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4536 fe_audio_adsp_callback_config_control[0].name = mixer_str;
4537 fe_audio_adsp_callback_config_control[0].private_value =
4538 rtd->dai_link->id;
4539 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004540 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304541 fe_audio_adsp_callback_config_control,
4542 ARRAY_SIZE(fe_audio_adsp_callback_config_control));
4543 if (ret < 0) {
4544 pr_err("%s: failed to add ctl %s. err = %d\n",
4545 __func__, mixer_str, ret);
4546 ret = -EINVAL;
4547 goto free_mixer_str;
4548 }
4549
4550 kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
4551 if (!kctl) {
4552 pr_err("%s: failed to get kctl %s.\n", __func__, mixer_str);
4553 ret = -EINVAL;
4554 goto free_mixer_str;
4555 }
4556
4557 kctl->private_data = NULL;
4558
4559free_mixer_str:
4560 kfree(mixer_str);
4561done:
4562 return ret;
4563}
4564
4565static int msm_compr_add_dec_runtime_params_control(
4566 struct snd_soc_pcm_runtime *rtd)
4567{
Meng Wangee084a02018-09-04 16:11:58 +08004568 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304569 const char *mixer_ctl_name = "Audio Stream";
4570 const char *deviceNo = "NN";
4571 const char *suffix = "Dec Params";
4572 char *mixer_str = NULL;
4573 int ctl_len;
4574 struct snd_kcontrol_new fe_dec_params_control[1] = {
4575 {
4576 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4577 .name = "?",
4578 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4579 .info = msm_compr_dec_params_info,
4580 .get = msm_compr_dec_params_get,
4581 .put = msm_compr_dec_params_put,
4582 .private_value = 0,
4583 }
4584 };
4585
4586 if (!rtd) {
4587 pr_err("%s NULL rtd\n", __func__);
4588 return 0;
4589 }
4590
Meng Wangee084a02018-09-04 16:11:58 +08004591 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4592 if (!component) {
4593 pr_err("%s: component is NULL\n", __func__);
4594 return 0;
4595 }
4596
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304597 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4598 __func__, rtd->dai_link->name, rtd->dai_link->id,
4599 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4600
4601 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
4602 strlen(suffix) + 1;
4603 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4604
4605 if (!mixer_str)
4606 return 0;
4607
4608 snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
4609 rtd->pcm->device, suffix);
4610
4611 fe_dec_params_control[0].name = mixer_str;
4612 fe_dec_params_control[0].private_value = rtd->dai_link->id;
4613 pr_debug("Registering new mixer ctl %s", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004614 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304615 fe_dec_params_control,
4616 ARRAY_SIZE(fe_dec_params_control));
4617 kfree(mixer_str);
4618 return 0;
4619}
4620
4621static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
4622{
Meng Wangee084a02018-09-04 16:11:58 +08004623 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304624 const char *playback_mixer_ctl_name = "Audio Stream";
4625 const char *capture_mixer_ctl_name = "Audio Stream Capture";
4626 const char *deviceNo = "NN";
4627 const char *suffix = "App Type Cfg";
4628 char *mixer_str = NULL;
4629 int ctl_len;
4630 struct snd_kcontrol_new fe_app_type_cfg_control[1] = {
4631 {
4632 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4633 .name = "?",
4634 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4635 .info = msm_compr_app_type_cfg_info,
4636 .put = msm_compr_playback_app_type_cfg_put,
4637 .get = msm_compr_playback_app_type_cfg_get,
4638 .private_value = 0,
4639 }
4640 };
4641
4642 if (!rtd) {
4643 pr_err("%s NULL rtd\n", __func__);
4644 return 0;
4645 }
4646
Meng Wangee084a02018-09-04 16:11:58 +08004647 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4648 if (!component) {
4649 pr_err("%s: component is NULL\n", __func__);
4650 return 0;
4651 }
4652
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304653 pr_debug("%s: added new compr FE ctl with name %s, id %d, cpu dai %s, device no %d\n",
4654 __func__, rtd->dai_link->name, rtd->dai_link->id,
4655 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4656 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
4657 ctl_len = strlen(playback_mixer_ctl_name) + 1 + strlen(deviceNo)
4658 + 1 + strlen(suffix) + 1;
4659 else
4660 ctl_len = strlen(capture_mixer_ctl_name) + 1 + strlen(deviceNo)
4661 + 1 + strlen(suffix) + 1;
4662
4663 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4664
4665 if (!mixer_str)
4666 return 0;
4667
4668 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
4669 snprintf(mixer_str, ctl_len, "%s %d %s",
4670 playback_mixer_ctl_name, rtd->pcm->device, suffix);
4671 else
4672 snprintf(mixer_str, ctl_len, "%s %d %s",
4673 capture_mixer_ctl_name, rtd->pcm->device, suffix);
4674
4675 fe_app_type_cfg_control[0].name = mixer_str;
4676 fe_app_type_cfg_control[0].private_value = rtd->dai_link->id;
4677
4678 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
4679 fe_app_type_cfg_control[0].put =
4680 msm_compr_playback_app_type_cfg_put;
4681 fe_app_type_cfg_control[0].get =
4682 msm_compr_playback_app_type_cfg_get;
4683 } else {
4684 fe_app_type_cfg_control[0].put =
4685 msm_compr_capture_app_type_cfg_put;
4686 fe_app_type_cfg_control[0].get =
4687 msm_compr_capture_app_type_cfg_get;
4688 }
4689 pr_debug("Registering new mixer ctl %s", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004690 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304691 fe_app_type_cfg_control,
4692 ARRAY_SIZE(fe_app_type_cfg_control));
4693 kfree(mixer_str);
4694 return 0;
4695}
4696
4697static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
4698{
Meng Wangee084a02018-09-04 16:11:58 +08004699 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304700 const char *mixer_ctl_name = "Playback Channel Map";
4701 const char *deviceNo = "NN";
4702 char *mixer_str = NULL;
4703 struct msm_compr_pdata *pdata = NULL;
4704 int ctl_len;
4705 struct snd_kcontrol_new fe_channel_map_control[1] = {
4706 {
4707 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4708 .name = "?",
4709 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4710 .info = msm_compr_channel_map_info,
4711 .get = msm_compr_channel_map_get,
4712 .put = msm_compr_channel_map_put,
4713 .private_value = 0,
4714 }
4715 };
4716
4717 if (!rtd) {
4718 pr_err("%s: NULL rtd\n", __func__);
4719 return -EINVAL;
4720 }
4721
Meng Wangee084a02018-09-04 16:11:58 +08004722 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4723 if (!component) {
4724 pr_err("%s: component is NULL\n", __func__);
4725 return -EINVAL;
4726 }
4727
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304728 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4729 __func__, rtd->dai_link->name, rtd->dai_link->id,
4730 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4731
4732 ctl_len = strlen(mixer_ctl_name) + strlen(deviceNo) + 1;
4733 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4734
4735 if (!mixer_str)
4736 return -ENOMEM;
4737
4738 snprintf(mixer_str, ctl_len, "%s%d", mixer_ctl_name, rtd->pcm->device);
4739
4740 fe_channel_map_control[0].name = mixer_str;
4741 fe_channel_map_control[0].private_value = rtd->dai_link->id;
4742 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004743 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304744 fe_channel_map_control,
4745 ARRAY_SIZE(fe_channel_map_control));
4746
Meng Wangee084a02018-09-04 16:11:58 +08004747 pdata = snd_soc_component_get_drvdata(component);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304748 pdata->ch_map[rtd->dai_link->id] =
4749 kzalloc(sizeof(struct msm_compr_ch_map), GFP_KERNEL);
4750 if (!pdata->ch_map[rtd->dai_link->id]) {
4751 pr_err("%s: Could not allocate memory for channel map\n",
4752 __func__);
4753 kfree(mixer_str);
4754 return -ENOMEM;
4755 }
4756 kfree(mixer_str);
4757 return 0;
4758}
4759
4760static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
4761{
Meng Wangee084a02018-09-04 16:11:58 +08004762 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304763 const char *mixer_ctl_name = "Playback ION FD";
4764 const char *deviceNo = "NN";
4765 char *mixer_str = NULL;
4766 int ctl_len = 0, ret = 0;
4767 struct snd_kcontrol_new fe_ion_fd_config_control[1] = {
4768 {
4769 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4770 .name = "?",
4771 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4772 .info = msm_adsp_stream_cmd_info,
4773 .put = msm_compr_ion_fd_map_put,
4774 .private_value = 0,
4775 }
4776 };
4777
4778 if (!rtd) {
4779 pr_err("%s NULL rtd\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08004780 return -EINVAL;
4781 }
4782
4783 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4784 if (!component) {
4785 pr_err("%s: component is NULL\n", __func__);
4786 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304787 }
4788
4789 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4790 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08004791 if (!mixer_str)
4792 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304793
4794 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4795 fe_ion_fd_config_control[0].name = mixer_str;
4796 fe_ion_fd_config_control[0].private_value = rtd->dai_link->id;
4797 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004798 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304799 fe_ion_fd_config_control,
4800 ARRAY_SIZE(fe_ion_fd_config_control));
4801 if (ret < 0)
4802 pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
4803
4804 kfree(mixer_str);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304805 return ret;
4806}
4807
4808static int msm_compr_add_event_ack_cmd_control(struct snd_soc_pcm_runtime *rtd)
4809{
Meng Wangee084a02018-09-04 16:11:58 +08004810 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304811 const char *mixer_ctl_name = "Playback Event Ack";
4812 const char *deviceNo = "NN";
4813 char *mixer_str = NULL;
4814 int ctl_len = 0, ret = 0;
4815 struct snd_kcontrol_new fe_event_ack_config_control[1] = {
4816 {
4817 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4818 .name = "?",
4819 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4820 .info = msm_adsp_stream_cmd_info,
4821 .put = msm_compr_rtic_event_ack_put,
4822 .private_value = 0,
4823 }
4824 };
4825
4826 if (!rtd) {
4827 pr_err("%s NULL rtd\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08004828 return -EINVAL;
4829 }
4830
4831 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4832 if (!component) {
4833 pr_err("%s: component is NULL\n", __func__);
4834 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304835 }
4836
4837 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4838 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08004839 if (!mixer_str)
4840 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304841
4842 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4843 fe_event_ack_config_control[0].name = mixer_str;
4844 fe_event_ack_config_control[0].private_value = rtd->dai_link->id;
4845 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004846 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304847 fe_event_ack_config_control,
4848 ARRAY_SIZE(fe_event_ack_config_control));
4849 if (ret < 0)
4850 pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
4851
4852 kfree(mixer_str);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304853 return ret;
4854}
4855
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304856static struct msm_pcm_channel_mixer *msm_compr_get_chmixer(
4857 struct msm_compr_pdata *pdata, u64 fe_id)
4858{
4859 if (!pdata) {
4860 pr_err("%s: missing pdata\n", __func__);
4861 return NULL;
4862 }
4863
4864 if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
4865 pr_err("%s: invalid FE %llu\n", __func__, fe_id);
4866 return NULL;
4867 }
4868
4869 return pdata->chmixer_pspd[fe_id];
4870}
4871
4872static int msm_compr_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol,
4873 struct snd_ctl_elem_value *ucontrol)
4874{
4875 u64 fe_id = kcontrol->private_value & 0xFF;
4876 int session_type = (kcontrol->private_value >> 8) & 0xFF;
4877 int ret = 0, i = 0, stream_id = 0, be_id = 0;
4878 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4879 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4880 snd_soc_component_get_drvdata(comp);
4881 struct snd_compr_stream *cstream = NULL;
4882 struct msm_compr_audio *prtd = NULL;
4883 struct msm_pcm_channel_mixer *chmixer_pspd = NULL;
4884 u8 asm_ch_map[PCM_FORMAT_MAX_NUM_CHANNEL_V8] = {0};
4885 bool reset_override_out_ch_map = false;
4886 bool reset_override_in_ch_map = false;
4887
4888 if ((session_type != SESSION_TYPE_TX) &&
4889 (session_type != SESSION_TYPE_RX)) {
4890 pr_err("%s: invalid session type %d\n", __func__, session_type);
4891 return -EINVAL;
4892 }
4893
4894 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
4895 if (!chmixer_pspd) {
4896 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
4897 return -EINVAL;
4898 }
4899
4900 chmixer_pspd->enable = ucontrol->value.integer.value[0];
4901 chmixer_pspd->rule = ucontrol->value.integer.value[1];
4902 chmixer_pspd->input_channel = ucontrol->value.integer.value[2];
4903 chmixer_pspd->output_channel = ucontrol->value.integer.value[3];
4904 chmixer_pspd->port_idx = ucontrol->value.integer.value[4];
4905
Erin Yan2f81be22019-04-29 13:42:57 +08004906 if (chmixer_pspd->input_channel < 0 ||
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05304907 chmixer_pspd->input_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8 ||
Erin Yan2f81be22019-04-29 13:42:57 +08004908 chmixer_pspd->output_channel < 0 ||
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05304909 chmixer_pspd->output_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
4910 pr_err("%s: Invalid channels, in %d, out %d\n",
4911 __func__, chmixer_pspd->input_channel,
4912 chmixer_pspd->output_channel);
4913 return -EINVAL;
4914 }
4915
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304916 if (chmixer_pspd->enable) {
4917 if (session_type == SESSION_TYPE_RX &&
4918 !chmixer_pspd->override_in_ch_map) {
4919 if (pdata->ch_map[fe_id]->set_ch_map) {
4920 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4921 chmixer_pspd->in_ch_map[i] =
4922 pdata->ch_map[fe_id]->channel_map[i];
4923 } else {
4924 q6asm_map_channels(asm_ch_map,
4925 chmixer_pspd->input_channel, false);
4926 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4927 chmixer_pspd->in_ch_map[i] = asm_ch_map[i];
4928 }
4929 chmixer_pspd->override_in_ch_map = true;
4930 reset_override_in_ch_map = true;
4931 } else if (session_type == SESSION_TYPE_TX &&
4932 !chmixer_pspd->override_out_ch_map) {
4933 if (pdata->ch_map[fe_id]->set_ch_map) {
4934 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4935 chmixer_pspd->out_ch_map[i] =
4936 pdata->ch_map[fe_id]->channel_map[i];
4937 } else {
4938 q6asm_map_channels(asm_ch_map,
4939 chmixer_pspd->output_channel, false);
4940 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4941 chmixer_pspd->out_ch_map[i] = asm_ch_map[i];
4942 }
4943 chmixer_pspd->override_out_ch_map = true;
4944 reset_override_out_ch_map = true;
4945 }
4946 } else {
4947 chmixer_pspd->override_out_ch_map = false;
4948 chmixer_pspd->override_in_ch_map = false;
4949 }
4950
4951 /* cache value and take effect during adm_open stage */
4952 msm_pcm_routing_set_channel_mixer_cfg(fe_id,
4953 session_type,
4954 chmixer_pspd);
4955
4956 cstream = pdata->cstream[fe_id];
4957 if (chmixer_pspd->enable && cstream && cstream->runtime) {
4958 prtd = cstream->runtime->private_data;
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304959
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05304960 if (prtd && prtd->audio_client) {
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304961 stream_id = prtd->audio_client->session;
4962 be_id = chmixer_pspd->port_idx;
Erin Yan2f81be22019-04-29 13:42:57 +08004963 msm_pcm_routing_set_channel_mixer_runtime(be_id,
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304964 stream_id, session_type, chmixer_pspd);
4965 }
4966 }
4967
4968 if (reset_override_out_ch_map)
4969 chmixer_pspd->override_out_ch_map = false;
4970 if (reset_override_in_ch_map)
4971 chmixer_pspd->override_in_ch_map = false;
4972
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304973 return ret;
4974}
4975
4976static int msm_compr_channel_mixer_cfg_ctl_get(struct snd_kcontrol *kcontrol,
4977 struct snd_ctl_elem_value *ucontrol)
4978{
4979 u64 fe_id = kcontrol->private_value & 0xFF;
4980 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4981 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4982 snd_soc_component_get_drvdata(comp);
4983 struct msm_pcm_channel_mixer *chmixer_pspd;
4984
4985 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
4986 if (!chmixer_pspd) {
4987 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
4988 return -EINVAL;
4989 }
4990
4991 ucontrol->value.integer.value[0] = chmixer_pspd->enable;
4992 ucontrol->value.integer.value[1] = chmixer_pspd->rule;
4993 ucontrol->value.integer.value[2] = chmixer_pspd->input_channel;
4994 ucontrol->value.integer.value[3] = chmixer_pspd->output_channel;
4995 ucontrol->value.integer.value[4] = chmixer_pspd->port_idx;
4996 return 0;
4997}
4998
4999static int msm_compr_channel_mixer_output_map_ctl_put(
5000 struct snd_kcontrol *kcontrol,
5001 struct snd_ctl_elem_value *ucontrol)
5002{
5003 u64 fe_id = kcontrol->private_value & 0xFF;
5004 int i = 0;
5005 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5006 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5007 snd_soc_component_get_drvdata(comp);
5008 struct msm_pcm_channel_mixer *chmixer_pspd;
5009
5010 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5011 if (!chmixer_pspd) {
5012 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5013 return -EINVAL;
5014 }
5015
5016 chmixer_pspd->override_out_ch_map = true;
5017 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5018 chmixer_pspd->out_ch_map[i] =
5019 ucontrol->value.integer.value[i];
5020
5021 return 0;
5022}
5023
5024static int msm_compr_channel_mixer_output_map_ctl_get(
5025 struct snd_kcontrol *kcontrol,
5026 struct snd_ctl_elem_value *ucontrol)
5027{
5028 u64 fe_id = kcontrol->private_value & 0xFF;
5029 int i = 0;
5030 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5031 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5032 snd_soc_component_get_drvdata(comp);
5033 struct msm_pcm_channel_mixer *chmixer_pspd;
5034
5035 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5036 if (!chmixer_pspd) {
5037 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5038 return -EINVAL;
5039 }
5040
5041 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5042 ucontrol->value.integer.value[i] =
5043 chmixer_pspd->out_ch_map[i];
5044 return 0;
5045}
5046
5047static int msm_compr_channel_mixer_input_map_ctl_put(
5048 struct snd_kcontrol *kcontrol,
5049 struct snd_ctl_elem_value *ucontrol)
5050{
5051 u64 fe_id = kcontrol->private_value & 0xFF;
5052 int i = 0;
5053 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5054 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5055 snd_soc_component_get_drvdata(comp);
5056 struct msm_pcm_channel_mixer *chmixer_pspd;
5057
5058 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5059 if (!chmixer_pspd) {
5060 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5061 return -EINVAL;
5062 }
5063
5064 chmixer_pspd->override_in_ch_map = true;
5065 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5066 chmixer_pspd->in_ch_map[i] = ucontrol->value.integer.value[i];
5067
5068 return 0;
5069}
5070
5071static int msm_compr_channel_mixer_input_map_ctl_get(
5072 struct snd_kcontrol *kcontrol,
5073 struct snd_ctl_elem_value *ucontrol)
5074{
5075 u64 fe_id = kcontrol->private_value & 0xFF;
5076 int i = 0;
5077 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5078 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5079 snd_soc_component_get_drvdata(comp);
5080 struct msm_pcm_channel_mixer *chmixer_pspd;
5081
5082 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5083 if (!chmixer_pspd) {
5084 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5085 return -EINVAL;
5086 }
5087
5088 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5089 ucontrol->value.integer.value[i] =
5090 chmixer_pspd->in_ch_map[i];
5091 return 0;
5092}
5093
5094static int msm_compr_channel_mixer_weight_ctl_put(
5095 struct snd_kcontrol *kcontrol,
5096 struct snd_ctl_elem_value *ucontrol)
5097{
5098 u64 fe_id = kcontrol->private_value & 0xFF;
5099 int channel = (kcontrol->private_value >> 16) & 0xFF;
5100 int i = 0;
5101 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5102 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5103 snd_soc_component_get_drvdata(comp);
5104 struct msm_pcm_channel_mixer *chmixer_pspd;
5105
5106 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5107 if (!chmixer_pspd) {
5108 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5109 return -EINVAL;
5110 }
5111
5112 if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
5113 pr_err("%s: invalid channel number %d\n", __func__, channel);
5114 return -EINVAL;
5115 }
5116 channel--;
5117
5118 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5119 chmixer_pspd->channel_weight[channel][i] =
5120 ucontrol->value.integer.value[i];
5121 return 0;
5122}
5123
5124static int msm_compr_channel_mixer_weight_ctl_get(
5125 struct snd_kcontrol *kcontrol,
5126 struct snd_ctl_elem_value *ucontrol)
5127{
5128 u64 fe_id = kcontrol->private_value & 0xFF;
5129 int channel = (kcontrol->private_value >> 16) & 0xFF;
5130 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5131 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5132 snd_soc_component_get_drvdata(comp);
5133 int i = 0;
5134 struct msm_pcm_channel_mixer *chmixer_pspd;
5135
5136 if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
5137 pr_err("%s: invalid channel number %d\n", __func__, channel);
5138 return -EINVAL;
5139 }
5140 channel--;
5141
5142 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5143 if (!chmixer_pspd) {
5144 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5145 return -EINVAL;
5146 }
5147
5148 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5149 ucontrol->value.integer.value[i] =
5150 chmixer_pspd->channel_weight[channel][i];
5151 return 0;
5152}
5153
5154static int msm_compr_add_platform_controls(struct snd_kcontrol_new *kctl,
5155 struct snd_soc_pcm_runtime *rtd, const char *name_prefix,
5156 const char *name_suffix, int session_type, int channels)
5157{
5158 int ret = -EINVAL;
5159 char *mixer_name = NULL;
5160 const char *deviceNo = "NN";
5161 const char *channelNo = "NN";
5162 int ctl_len = 0;
5163 struct snd_soc_component *component = NULL;
5164
5165 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
5166 if (!component) {
5167 pr_err("%s: component is NULL\n", __func__);
5168 return -EINVAL;
5169 }
5170
5171 ctl_len = strlen(name_prefix) + 1 + strlen(deviceNo) + 1 +
5172 strlen(channelNo) + 1 + strlen(name_suffix) + 1;
5173
5174 mixer_name = kzalloc(ctl_len, GFP_KERNEL);
5175 if (mixer_name == NULL)
5176 return -ENOMEM;
5177
5178 if (channels >= 0) {
5179 snprintf(mixer_name, ctl_len, "%s %d %s %d",
5180 name_prefix, rtd->pcm->device, name_suffix, channels);
5181 kctl->private_value = (rtd->dai_link->id) | (channels << 16);
5182 } else {
5183 snprintf(mixer_name, ctl_len, "%s %d %s",
5184 name_prefix, rtd->pcm->device, name_suffix);
5185 kctl->private_value = (rtd->dai_link->id);
5186 }
5187 if (session_type != INVALID_SESSION)
5188 kctl->private_value |= (session_type << 8);
5189
5190 kctl->name = mixer_name;
5191 ret = snd_soc_add_component_controls(component, kctl, 1);
5192 kfree(mixer_name);
5193 return ret;
5194}
5195
5196static int msm_compr_channel_mixer_output_map_info(struct snd_kcontrol *kcontrol,
5197 struct snd_ctl_elem_info *uinfo)
5198{
5199 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5200 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
5201 /* Valid channel map value ranges from 1 to 64 */
5202 uinfo->value.integer.min = 1;
5203 uinfo->value.integer.max = 64;
5204 return 0;
5205}
5206
5207static int msm_compr_add_channel_mixer_output_map_controls(
5208 struct snd_soc_pcm_runtime *rtd)
5209{
5210 const char *playback_mixer_ctl_name = "AudStr";
5211 const char *capture_mixer_ctl_name = "AudStr Capture";
5212 const char *suffix = "ChMixer Output Map";
5213 const char *mixer_ctl_name = NULL;
5214 int ret = 0, session_type = INVALID_SESSION, channel = -1;
5215 struct snd_kcontrol_new channel_mixer_output_map_control = {
5216 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5217 .name = "?",
5218 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5219 .info = msm_compr_channel_mixer_output_map_info,
5220 .put = msm_compr_channel_mixer_output_map_ctl_put,
5221 .get = msm_compr_channel_mixer_output_map_ctl_get,
5222 .private_value = 0,
5223 };
5224
5225 mixer_ctl_name = rtd->compr->direction == SND_COMPRESS_PLAYBACK ?
5226 playback_mixer_ctl_name : capture_mixer_ctl_name ;
5227 ret = msm_compr_add_platform_controls(&channel_mixer_output_map_control,
5228 rtd, mixer_ctl_name, suffix, session_type, channel);
5229 if (ret < 0) {
5230 pr_err("%s: failed add platform ctl, err = %d\n",
5231 __func__, ret);
5232 }
5233
5234 return ret;
5235}
5236
5237static int msm_compr_channel_mixer_input_map_info(struct snd_kcontrol *kcontrol,
5238 struct snd_ctl_elem_info *uinfo)
5239{
5240 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5241 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
5242 /* Valid channel map value ranges from 1 to 64 */
5243 uinfo->value.integer.min = 1;
5244 uinfo->value.integer.max = 64;
5245 return 0;
5246}
5247
5248static int msm_compr_add_channel_mixer_input_map_controls(
5249 struct snd_soc_pcm_runtime *rtd)
5250{
5251 const char *playback_mixer_ctl_name = "AudStr";
5252 const char *capture_mixer_ctl_name = "AudStr Capture";
5253 const char *suffix = "ChMixer Input Map";
5254 const char *mixer_ctl_name = NULL;
5255 int ret = 0, session_type = INVALID_SESSION, channel = -1;
5256 struct snd_kcontrol_new channel_mixer_input_map_control = {
5257 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5258 .name = "?",
5259 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5260 .info = msm_compr_channel_mixer_input_map_info,
5261 .put = msm_compr_channel_mixer_input_map_ctl_put,
5262 .get = msm_compr_channel_mixer_input_map_ctl_get,
5263 .private_value = 0,
5264 };
5265
5266 mixer_ctl_name = rtd->compr->direction == SND_COMPRESS_PLAYBACK ?
5267 playback_mixer_ctl_name : capture_mixer_ctl_name ;
5268 ret = msm_compr_add_platform_controls(&channel_mixer_input_map_control,
5269 rtd, mixer_ctl_name, suffix, session_type, channel);
5270 if (ret < 0) {
5271 pr_err("%s: failed add platform ctl, err = %d\n",
5272 __func__, ret);
5273 }
5274
5275 return ret;
5276}
5277
5278static int msm_compr_channel_mixer_cfg_info(struct snd_kcontrol *kcontrol,
5279 struct snd_ctl_elem_info *uinfo)
5280{
5281 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5282 /* five int values: enable, rule, in_channels, out_channels and port_id */
5283 uinfo->count = 5;
5284 /* Valid range is all positive values to support above controls */
5285 uinfo->value.integer.min = 0;
5286 uinfo->value.integer.max = INT_MAX;
5287 return 0;
5288}
5289
5290static int msm_compr_add_channel_mixer_cfg_controls(
5291 struct snd_soc_pcm_runtime *rtd)
5292{
5293 const char *playback_mixer_ctl_name = "AudStr";
5294 const char *capture_mixer_ctl_name = "AudStr Capture";
5295 const char *suffix = "ChMixer Cfg";
5296 const char *mixer_ctl_name = NULL;
5297 int ret = 0, session_type = INVALID_SESSION, channel = -1;
5298 struct snd_kcontrol_new channel_mixer_cfg_control = {
5299 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5300 .name = "?",
5301 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5302 .info = msm_compr_channel_mixer_cfg_info,
5303 .put = msm_compr_channel_mixer_cfg_ctl_put,
5304 .get = msm_compr_channel_mixer_cfg_ctl_get,
5305 .private_value = 0,
5306 };
5307
5308 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
5309 session_type = SESSION_TYPE_RX;
5310 mixer_ctl_name = playback_mixer_ctl_name;
5311 } else {
5312 session_type = SESSION_TYPE_TX;
5313 mixer_ctl_name = capture_mixer_ctl_name;
5314 }
5315
5316 ret = msm_compr_add_platform_controls(&channel_mixer_cfg_control,
5317 rtd, mixer_ctl_name, suffix, session_type, channel);
5318 if (ret < 0) {
5319 pr_err("%s: failed add platform ctl, err = %d\n",
5320 __func__, ret);
5321 }
5322
5323 return ret;
5324}
5325
5326static int msm_compr_channel_mixer_weight_info(struct snd_kcontrol *kcontrol,
5327 struct snd_ctl_elem_info *uinfo)
5328{
5329 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5330 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
5331 /* Valid range: 0 to 0x4000(Unity) gain weightage */
5332 uinfo->value.integer.min = 0;
5333 uinfo->value.integer.max = 0x4000;
5334 return 0;
5335}
5336
5337static int msm_compr_add_channel_mixer_weight_controls(
5338 struct snd_soc_pcm_runtime *rtd,
5339 int channel)
5340{
5341 const char *playback_mixer_ctl_name = "AudStr";
5342 const char *capture_mixer_ctl_name = "AudStr Capture";
5343 const char *suffix = "ChMixer Weight Ch";
5344 const char *mixer_ctl_name = NULL;
5345 int ret = 0, session_type = INVALID_SESSION;
5346 struct snd_kcontrol_new channel_mixer_weight_control = {
5347 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5348 .name = "?",
5349 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5350 .info = msm_compr_channel_mixer_weight_info,
5351 .put = msm_compr_channel_mixer_weight_ctl_put,
5352 .get = msm_compr_channel_mixer_weight_ctl_get,
5353 .private_value = 0,
5354 };
5355
5356 mixer_ctl_name = rtd->compr->direction == SND_COMPRESS_PLAYBACK ?
5357 playback_mixer_ctl_name : capture_mixer_ctl_name ;
5358 ret = msm_compr_add_platform_controls(&channel_mixer_weight_control,
5359 rtd, mixer_ctl_name, suffix, session_type, channel);
5360 if (ret < 0) {
5361 pr_err("%s: failed add platform ctl, err = %d\n",
5362 __func__, ret);
5363 }
5364
5365 return ret;
5366}
5367
5368static int msm_compr_add_channel_mixer_controls(struct snd_soc_pcm_runtime *rtd)
5369{
5370 int i, ret = 0;
5371 struct msm_compr_pdata *pdata = NULL;
5372 struct snd_soc_component *component = NULL;
5373
5374 if (!rtd) {
5375 pr_err("%s NULL rtd\n", __func__);
5376 return -EINVAL;
5377 }
5378
5379 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
5380 if (!component) {
5381 pr_err("%s: component is NULL\n", __func__);
5382 return -EINVAL;
5383 }
5384
5385 pdata = (struct msm_compr_pdata *)
5386 snd_soc_component_get_drvdata(component);
5387 if (!pdata) {
5388 pr_err("%s: platform data not populated\n", __func__);
5389 return -EINVAL;
5390 }
5391
5392 if (!pdata->chmixer_pspd[rtd->dai_link->id]) {
5393 pdata->chmixer_pspd[rtd->dai_link->id] =
5394 kzalloc(sizeof(struct msm_pcm_channel_mixer), GFP_KERNEL);
5395 if (!pdata->chmixer_pspd[rtd->dai_link->id])
5396 return -ENOMEM;
5397 }
5398
5399 ret = msm_compr_add_channel_mixer_cfg_controls(rtd);
5400 if (ret) {
5401 pr_err("%s: pcm add channel mixer cfg controls failed:%d\n",
5402 __func__, ret);
5403 goto fail;
5404 }
5405 ret = msm_compr_add_channel_mixer_input_map_controls(rtd);
5406 if (ret) {
5407 pr_err("%s: pcm add channel mixer input map controls failed:%d\n",
5408 __func__, ret);
5409 goto fail;
5410 }
5411 ret = msm_compr_add_channel_mixer_output_map_controls(rtd);
5412 if (ret) {
5413 pr_err("%s: pcm add channel mixer output map controls failed:%d\n",
5414 __func__, ret);
5415 goto fail;
5416 }
5417
5418 for (i = 1; i <= PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++) {
5419 ret = msm_compr_add_channel_mixer_weight_controls(rtd, i);
5420 if (ret) {
5421 pr_err("%s: pcm add channel mixer weight controls failed:%d\n",
5422 __func__, ret);
5423 goto fail;
5424 }
5425 }
5426 return 0;
5427
5428fail:
5429 kfree(pdata->chmixer_pspd[rtd->dai_link->id]);
5430 pdata->chmixer_pspd[rtd->dai_link->id] = NULL;
5431 return ret;
5432}
5433
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305434static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
5435{
5436 int rc;
5437
5438 rc = msm_compr_add_volume_control(rtd);
5439 if (rc)
5440 pr_err("%s: Could not add Compr Volume Control\n", __func__);
5441
5442 rc = msm_compr_add_audio_effects_control(rtd);
5443 if (rc)
5444 pr_err("%s: Could not add Compr Audio Effects Control\n",
5445 __func__);
5446
5447 rc = msm_compr_add_audio_adsp_stream_cmd_control(rtd);
5448 if (rc)
5449 pr_err("%s: Could not add Compr ADSP Stream Cmd Control\n",
5450 __func__);
5451
5452 rc = msm_compr_add_audio_adsp_stream_callback_control(rtd);
5453 if (rc)
5454 pr_err("%s: Could not add Compr ADSP Stream Callback Control\n",
5455 __func__);
5456
5457 rc = msm_compr_add_io_fd_cmd_control(rtd);
5458 if (rc)
5459 pr_err("%s: Could not add Compr ion fd Control\n",
5460 __func__);
5461
5462 rc = msm_compr_add_event_ack_cmd_control(rtd);
5463 if (rc)
5464 pr_err("%s: Could not add Compr event ack Control\n",
5465 __func__);
5466
5467 rc = msm_compr_add_query_audio_effect_control(rtd);
5468 if (rc)
5469 pr_err("%s: Could not add Compr Query Audio Effect Control\n",
5470 __func__);
5471
5472 rc = msm_compr_add_dec_runtime_params_control(rtd);
5473 if (rc)
5474 pr_err("%s: Could not add Compr Dec runtime params Control\n",
5475 __func__);
5476 rc = msm_compr_add_app_type_cfg_control(rtd);
5477 if (rc)
5478 pr_err("%s: Could not add Compr App Type Cfg Control\n",
5479 __func__);
5480 rc = msm_compr_add_channel_map_control(rtd);
5481 if (rc)
5482 pr_err("%s: Could not add Compr Channel Map Control\n",
5483 __func__);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305484 rc = msm_compr_add_channel_mixer_controls(rtd);
5485 if (rc)
5486 pr_err("%s: Could not add Compr Channel Mixer Controls\n",
5487 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305488 return 0;
5489}
5490
5491static struct snd_compr_ops msm_compr_ops = {
5492 .open = msm_compr_open,
5493 .free = msm_compr_free,
5494 .trigger = msm_compr_trigger,
5495 .pointer = msm_compr_pointer,
5496 .set_params = msm_compr_set_params,
5497 .set_metadata = msm_compr_set_metadata,
5498 .get_metadata = msm_compr_get_metadata,
5499 .set_next_track_param = msm_compr_set_next_track_param,
5500 .ack = msm_compr_ack,
5501 .copy = msm_compr_copy,
5502 .get_caps = msm_compr_get_caps,
5503 .get_codec_caps = msm_compr_get_codec_caps,
5504};
5505
Meng Wangee084a02018-09-04 16:11:58 +08005506static struct snd_soc_component_driver msm_soc_component = {
5507 .name = DRV_NAME,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305508 .probe = msm_compr_probe,
5509 .compr_ops = &msm_compr_ops,
5510 .pcm_new = msm_compr_new,
5511};
5512
5513static int msm_compr_dev_probe(struct platform_device *pdev)
5514{
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305515 struct msm_compr_pdata *pdata = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305516
5517 pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305518 pdata = (struct msm_compr_pdata *)
5519 kzalloc(sizeof(*pdata), GFP_KERNEL);
5520 if (!pdata)
5521 return -ENOMEM;
Ajit Pandeyfa018862019-09-04 14:34:00 +05305522 mutex_init(&pdata->lock);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305523 dev_set_drvdata(&pdev->dev, pdata);
5524
Meng Wangee084a02018-09-04 16:11:58 +08005525 return snd_soc_register_component(&pdev->dev,
5526 &msm_soc_component, NULL, 0);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305527}
5528
5529static int msm_compr_remove(struct platform_device *pdev)
5530{
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305531 int i = 0;
5532 struct msm_compr_pdata *pdata = NULL;
5533
5534 pdata = dev_get_drvdata(&pdev->dev);
5535 if (pdata) {
5536 for (i = 0; i < MSM_FRONTEND_DAI_MM_SIZE; i++)
5537 kfree(pdata->chmixer_pspd[i]);
5538 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05305539 mutex_destroy(&pdata->lock);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305540 kfree(pdata);
5541
Meng Wangee084a02018-09-04 16:11:58 +08005542 snd_soc_unregister_component(&pdev->dev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305543 return 0;
5544}
5545
5546static const struct of_device_id msm_compr_dt_match[] = {
5547 {.compatible = "qcom,msm-compress-dsp"},
5548 {}
5549};
5550MODULE_DEVICE_TABLE(of, msm_compr_dt_match);
5551
5552static struct platform_driver msm_compr_driver = {
5553 .driver = {
5554 .name = "msm-compress-dsp",
5555 .owner = THIS_MODULE,
5556 .of_match_table = msm_compr_dt_match,
Xiaojun Sang53cd13a2018-06-29 15:14:37 +08005557 .suppress_bind_attrs = true,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305558 },
5559 .probe = msm_compr_dev_probe,
5560 .remove = msm_compr_remove,
5561};
5562
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305563int __init msm_compress_dsp_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305564{
5565 return platform_driver_register(&msm_compr_driver);
5566}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305567
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05305568void msm_compress_dsp_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305569{
5570 platform_driver_unregister(&msm_compr_driver);
5571}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305572
5573MODULE_DESCRIPTION("Compress Offload platform driver");
5574MODULE_LICENSE("GPL v2");