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