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