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