blob: b34202cb1d13ea717a6b46bc0ed617e2496cacd8 [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,
Surendar Karkafc93c482019-10-31 11:05:59 +0530228 uint32_t render_mode, int dir) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530229 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
Surendar Karkafc93c482019-10-31 11:05:59 +0530253 ret = q6asm_send_mtmx_strtr_render_mode(ac, render_mode, dir);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530254 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
Surendar Karkafc93c482019-10-31 11:05:59 +0530327static int msm_compr_set_ttp_offset(struct audio_client *ac,
328 uint32_t offset_lsw, uint32_t offset_msw, int dir)
329{
330 int ret = -EINVAL;
331 struct asm_session_mtmx_strtr_param_ttp_offset_t ttp_offset;
332 uint32_t param_id;
333
334 pr_debug("%s, ttp offset lsw 0x%x ttp offset msw 0x%x\n",
335 __func__, offset_lsw, offset_msw);
336
337 memset(&ttp_offset, 0,
338 sizeof(struct asm_session_mtmx_strtr_param_ttp_offset_t));
339 ttp_offset.ttp_offset_lsw = offset_lsw;
340 ttp_offset.ttp_offset_msw = offset_msw;
341 param_id = ASM_SESSION_MTMX_STRTR_PARAM_TTP_OFFSET;
342 ret = q6asm_send_mtmx_strtr_ttp_offset(ac, &ttp_offset, param_id, dir);
343 if (ret)
344 pr_err("%s, ttp offset can't be set error %d\n", __func__,
345 ret);
346
347 return ret;
348}
349
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530350static int msm_compr_enable_adjust_session_clock(struct audio_client *ac,
351 bool enable)
352{
353 int ret;
354
355 pr_debug("%s, enable adjust_session %d\n", __func__, enable);
356
357 ret = q6asm_send_mtmx_strtr_enable_adjust_session_clock(ac, enable);
358 if (ret)
359 pr_err("%s, adjust session clock can't be set error %d\n",
360 __func__, ret);
361
362 return ret;
363}
364
365static int msm_compr_adjust_session_clock(struct audio_client *ac,
366 uint32_t adjust_session_lsw, uint32_t adjust_session_msw)
367{
368 int ret;
369
370 pr_debug("%s, adjust_session_time_msw 0x%x adjust_session_time_lsw 0x%x\n",
371 __func__, adjust_session_msw, adjust_session_lsw);
372
373 ret = q6asm_adjust_session_clock(ac,
374 adjust_session_lsw,
375 adjust_session_msw);
376 if (ret)
377 pr_err("%s, adjust session clock can't be set error %d\n",
378 __func__, ret);
379
380 return ret;
381}
382
383static int msm_compr_set_volume(struct snd_compr_stream *cstream,
384 uint32_t volume_l, uint32_t volume_r)
385{
386 struct msm_compr_audio *prtd;
387 int rc = 0;
388 uint32_t avg_vol, gain_list[VOLUME_CONTROL_MAX_CHANNELS];
389 uint32_t num_channels;
390 struct snd_soc_pcm_runtime *rtd;
Meng Wangee084a02018-09-04 16:11:58 +0800391 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530392 struct msm_compr_pdata *pdata;
393 bool use_default = true;
394 u8 *chmap = NULL;
395
396 pr_debug("%s: volume_l %d volume_r %d\n",
397 __func__, volume_l, volume_r);
398 if (!cstream || !cstream->runtime) {
399 pr_err("%s: session not active\n", __func__);
400 return -EPERM;
401 }
402 rtd = cstream->private_data;
403 prtd = cstream->runtime->private_data;
404
Meng Wang8a2a1042019-03-21 10:14:50 +0800405 if (!rtd || !prtd || !prtd->audio_client) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530406 pr_err("%s: invalid rtd, prtd or audio client", __func__);
407 return rc;
408 }
Meng Wang8a2a1042019-03-21 10:14:50 +0800409 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
410 if (!component) {
411 pr_err("%s: invalid component\n", __func__);
412 return rc;
413 }
414
Meng Wangee084a02018-09-04 16:11:58 +0800415 pdata = snd_soc_component_get_drvdata(component);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530416
417 if (prtd->compr_passthr != LEGACY_PCM) {
418 pr_debug("%s: No volume config for passthrough %d\n",
419 __func__, prtd->compr_passthr);
420 return rc;
421 }
422
423 use_default = !(pdata->ch_map[rtd->dai_link->id]->set_ch_map);
424 chmap = pdata->ch_map[rtd->dai_link->id]->channel_map;
425 num_channels = prtd->num_channels;
426
427 if (prtd->num_channels > 2) {
428 /*
429 * Currently the left and right gains are averaged an applied
430 * to all channels. This might not be desirable. But currently,
431 * there exists no API in userspace to send a list of gains for
432 * each channel either. If such an API does become available,
433 * the mixer control must be updated to accept more than 2
434 * channel gains.
435 *
436 */
437 avg_vol = (volume_l + volume_r) / 2;
438 rc = q6asm_set_volume(prtd->audio_client, avg_vol);
439 } else {
440 gain_list[0] = volume_l;
441 gain_list[1] = volume_r;
yidongh98526ef2017-09-05 17:57:55 +0800442 gain_list[2] = volume_l;
Surendar Karka4bb89982019-10-01 13:51:11 +0530443 if (use_default)
444 num_channels = 3;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530445 rc = q6asm_set_multich_gain(prtd->audio_client, num_channels,
446 gain_list, chmap, use_default);
447 }
448
449 if (rc < 0)
450 pr_err("%s: Send vol gain command failed rc=%d\n",
451 __func__, rc);
452
453 return rc;
454}
455
456static int msm_compr_send_ddp_cfg(struct audio_client *ac,
457 struct snd_dec_ddp *ddp,
458 int stream_id)
459{
460 int i, rc;
461
462 pr_debug("%s\n", __func__);
463 for (i = 0; i < ddp->params_length; i++) {
464 rc = q6asm_ds1_set_stream_endp_params(ac, ddp->params_id[i],
465 ddp->params_value[i],
466 stream_id);
467 if (rc) {
468 pr_err("sending params_id: %d failed\n",
469 ddp->params_id[i]);
470 return rc;
471 }
472 }
473 return 0;
474}
475
476static int msm_compr_send_buffer(struct msm_compr_audio *prtd)
477{
478 int buffer_length;
479 uint64_t bytes_available;
480 struct audio_aio_write_param param;
481 struct snd_codec_metadata *buff_addr;
482
483 if (!atomic_read(&prtd->start)) {
484 pr_err("%s: stream is not in started state\n", __func__);
485 return -EINVAL;
486 }
487
488
489 if (atomic_read(&prtd->xrun)) {
490 WARN(1, "%s called while xrun is true", __func__);
491 return -EPERM;
492 }
493
494 pr_debug("%s: bytes_received = %llu copied_total = %llu\n",
495 __func__, prtd->bytes_received, prtd->copied_total);
496 if (prtd->first_buffer && prtd->gapless_state.use_dsp_gapless_mode &&
497 prtd->compr_passthr == LEGACY_PCM)
498 q6asm_stream_send_meta_data(prtd->audio_client,
499 prtd->audio_client->stream_id,
500 prtd->gapless_state.initial_samples_drop,
501 prtd->gapless_state.trailing_samples_drop);
502
503 buffer_length = prtd->codec_param.buffer.fragment_size;
504 bytes_available = prtd->bytes_received - prtd->copied_total;
505 if (bytes_available < prtd->codec_param.buffer.fragment_size)
506 buffer_length = bytes_available;
507
508 if (prtd->byte_offset + buffer_length > prtd->buffer_size) {
509 buffer_length = (prtd->buffer_size - prtd->byte_offset);
510 pr_debug("%s: wrap around situation, send partial data %d now",
511 __func__, buffer_length);
512 }
513
514 if (buffer_length) {
515 param.paddr = prtd->buffer_paddr + prtd->byte_offset;
516 WARN(prtd->byte_offset % 32 != 0, "offset %x not multiple of 32\n",
517 prtd->byte_offset);
518 } else {
519 param.paddr = prtd->buffer_paddr;
520 }
521 param.len = buffer_length;
522 if (prtd->ts_header_offset) {
523 buff_addr = (struct snd_codec_metadata *)
524 (prtd->buffer + prtd->byte_offset);
525 param.len = buff_addr->length;
526 param.msw_ts = (uint32_t)
527 ((buff_addr->timestamp & 0xFFFFFFFF00000000LL) >> 32);
528 param.lsw_ts = (uint32_t) (buff_addr->timestamp & 0xFFFFFFFFLL);
529 param.paddr += prtd->ts_header_offset;
530 param.flags = SET_TIMESTAMP;
531 param.metadata_len = prtd->ts_header_offset;
532 } else {
533 param.msw_ts = 0;
534 param.lsw_ts = 0;
535 param.flags = NO_TIMESTAMP;
536 param.metadata_len = 0;
537 }
538 param.uid = buffer_length;
539 param.last_buffer = prtd->last_buffer;
540
541 pr_debug("%s: sending %d bytes to DSP byte_offset = %d\n",
542 __func__, param.len, prtd->byte_offset);
543 if (q6asm_async_write(prtd->audio_client, &param) < 0) {
544 pr_err("%s:q6asm_async_write failed\n", __func__);
545 } else {
546 prtd->bytes_sent += buffer_length;
547 if (prtd->first_buffer)
548 prtd->first_buffer = 0;
549 }
550
551 return 0;
552}
553
554static int msm_compr_read_buffer(struct msm_compr_audio *prtd)
555{
556 int buffer_length;
557 uint64_t bytes_available;
558 uint64_t buffer_sent;
559 struct audio_aio_read_param param;
560 int ret;
561
562 if (!atomic_read(&prtd->start)) {
563 pr_err("%s: stream is not in started state\n", __func__);
564 return -EINVAL;
565 }
566
567 buffer_length = prtd->codec_param.buffer.fragment_size -
568 prtd->ts_header_offset;
569 bytes_available = prtd->received_total - prtd->bytes_copied;
570 buffer_sent = prtd->bytes_read - prtd->bytes_copied;
571 if (buffer_sent + buffer_length + prtd->ts_header_offset
572 > prtd->buffer_size) {
573 pr_debug(" %s : Buffer is Full bytes_available: %llu\n",
574 __func__, bytes_available);
575 return 0;
576 }
577
578 memset(&param, 0x0, sizeof(struct audio_aio_read_param));
579 param.paddr = prtd->buffer_paddr + prtd->bytes_read_offset +
580 prtd->ts_header_offset;
581 param.len = buffer_length;
582 param.uid = buffer_length;
583 param.flags = prtd->codec_param.codec.flags;
584
585 pr_debug("%s: reading %d bytes from DSP byte_offset = %llu\n",
586 __func__, buffer_length, prtd->bytes_read);
587 ret = q6asm_async_read(prtd->audio_client, &param);
588 if (ret < 0) {
589 pr_err("%s: q6asm_async_read failed - %d\n",
590 __func__, ret);
591 return ret;
592 }
Ralf Herz22573552018-06-20 11:30:58 +0200593 prtd->bytes_read += buffer_length + prtd->ts_header_offset;
Vikram Panduranga82c2c2c2018-01-10 18:04:54 -0800594 prtd->bytes_read_offset += buffer_length + prtd->ts_header_offset;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530595 if (prtd->bytes_read_offset >= prtd->buffer_size)
596 prtd->bytes_read_offset -= prtd->buffer_size;
597
598 return 0;
599}
600
601static void compr_event_handler(uint32_t opcode,
602 uint32_t token, uint32_t *payload, void *priv)
603{
604 struct msm_compr_audio *prtd = priv;
605 struct snd_compr_stream *cstream;
606 struct audio_client *ac;
607 uint32_t chan_mode = 0;
608 uint32_t sample_rate = 0;
609 uint64_t bytes_available;
610 int stream_id;
611 uint32_t stream_index;
612 unsigned long flags;
613 uint64_t read_size;
614 uint32_t *buff_addr;
615 struct snd_soc_pcm_runtime *rtd;
616 int ret = 0;
617
618 if (!prtd) {
619 pr_err("%s: prtd is NULL\n", __func__);
620 return;
621 }
622 cstream = prtd->cstream;
623 if (!cstream) {
624 pr_err("%s: cstream is NULL\n", __func__);
625 return;
626 }
627
628 ac = prtd->audio_client;
629
630 /*
631 * Token for rest of the compressed commands use to set
632 * session id, stream id, dir etc.
633 */
634 stream_id = q6asm_get_stream_id_from_token(token);
635
636 pr_debug("%s opcode =%08x\n", __func__, opcode);
637 switch (opcode) {
638 case ASM_DATA_EVENT_WRITE_DONE_V2:
639 spin_lock_irqsave(&prtd->lock, flags);
640
641 if (payload[3]) {
642 pr_err("%s: WRITE FAILED w/ err 0x%x !, paddr 0x%x, byte_offset=%d,copied_total=%llu,token=%d\n",
643 __func__,
644 payload[3],
645 payload[0],
646 prtd->byte_offset,
647 prtd->copied_total, token);
648
649 if (atomic_cmpxchg(&prtd->drain, 1, 0) &&
650 prtd->last_buffer) {
651 pr_debug("%s: wake up on drain\n", __func__);
652 prtd->drain_ready = 1;
653 wake_up(&prtd->drain_wait);
654 prtd->last_buffer = 0;
655 } else {
656 atomic_set(&prtd->start, 0);
657 }
658 } else {
659 pr_debug("ASM_DATA_EVENT_WRITE_DONE_V2 offset %d, length %d\n",
660 prtd->byte_offset, token);
661 }
662
663 /*
664 * Token for WRITE command represents the amount of data
665 * written to ADSP in the last write, update offset and
666 * total copied data accordingly.
667 */
668 if (prtd->ts_header_offset) {
669 /* Always assume that the data will be sent to DSP on
670 * frame boundary.
671 * i.e, one frame of userspace write will result in
672 * one kernel write to DSP. This is needed as
673 * timestamp will be sent per frame.
674 */
675 prtd->byte_offset +=
676 prtd->codec_param.buffer.fragment_size;
677 prtd->copied_total +=
678 prtd->codec_param.buffer.fragment_size;
679 } else {
680 prtd->byte_offset += token;
681 prtd->copied_total += token;
682 }
683 if (prtd->byte_offset >= prtd->buffer_size)
684 prtd->byte_offset -= prtd->buffer_size;
685
686 snd_compr_fragment_elapsed(cstream);
687
688 if (!atomic_read(&prtd->start)) {
689 /* Writes must be restarted from _copy() */
690 pr_debug("write_done received while not started, treat as xrun");
691 atomic_set(&prtd->xrun, 1);
692 spin_unlock_irqrestore(&prtd->lock, flags);
693 break;
694 }
695
696 bytes_available = prtd->bytes_received - prtd->copied_total;
697 if (bytes_available < cstream->runtime->fragment_size) {
698 pr_debug("WRITE_DONE Insufficient data to send. break out\n");
699 atomic_set(&prtd->xrun, 1);
700
701 if (prtd->last_buffer)
702 prtd->last_buffer = 0;
703 if (atomic_read(&prtd->drain)) {
704 pr_debug("wake up on drain\n");
705 prtd->drain_ready = 1;
706 wake_up(&prtd->drain_wait);
707 atomic_set(&prtd->drain, 0);
708 }
709 } else if ((bytes_available == cstream->runtime->fragment_size)
710 && atomic_read(&prtd->drain)) {
711 prtd->last_buffer = 1;
712 msm_compr_send_buffer(prtd);
713 prtd->last_buffer = 0;
714 } else
715 msm_compr_send_buffer(prtd);
716
717 spin_unlock_irqrestore(&prtd->lock, flags);
718 break;
719
720 case ASM_DATA_EVENT_READ_DONE_V2:
721 spin_lock_irqsave(&prtd->lock, flags);
722
723 pr_debug("ASM_DATA_EVENT_READ_DONE_V2 offset %d, length %d\n",
724 prtd->byte_offset, payload[4]);
725
726 if (prtd->ts_header_offset) {
727 /* Update the header for received buffer */
728 buff_addr = prtd->buffer + prtd->byte_offset;
Ralf Herz22573552018-06-20 11:30:58 +0200729 /* Write the actual length of the received buffer */
730 *buff_addr = payload[4];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530731 buff_addr++;
732 /* Write the offset */
733 *buff_addr = prtd->ts_header_offset;
734 buff_addr++;
735 /* Write the TS LSW */
736 *buff_addr = payload[CAPTURE_META_DATA_TS_OFFSET_LSW];
737 buff_addr++;
738 /* Write the TS MSW */
739 *buff_addr = payload[CAPTURE_META_DATA_TS_OFFSET_MSW];
740 }
741 /* Always assume read_size is same as fragment_size */
742 read_size = prtd->codec_param.buffer.fragment_size;
743 prtd->byte_offset += read_size;
744 prtd->received_total += read_size;
745 if (prtd->byte_offset >= prtd->buffer_size)
746 prtd->byte_offset -= prtd->buffer_size;
747
748 snd_compr_fragment_elapsed(cstream);
749
750 if (!atomic_read(&prtd->start)) {
751 pr_debug("read_done received while not started, treat as xrun");
752 atomic_set(&prtd->xrun, 1);
753 spin_unlock_irqrestore(&prtd->lock, flags);
754 break;
755 }
756 msm_compr_read_buffer(prtd);
757
758 spin_unlock_irqrestore(&prtd->lock, flags);
759 break;
760
761 case ASM_DATA_EVENT_RENDERED_EOS:
762 spin_lock_irqsave(&prtd->lock, flags);
763 pr_debug("%s: ASM_DATA_CMDRSP_EOS token 0x%x,stream id %d\n",
764 __func__, token, stream_id);
765 if (atomic_read(&prtd->eos) &&
766 !prtd->gapless_state.set_next_stream_id) {
767 pr_debug("ASM_DATA_CMDRSP_EOS wake up\n");
768 prtd->eos_ack = 1;
769 wake_up(&prtd->eos_wait);
770 }
771 atomic_set(&prtd->eos, 0);
772 stream_index = STREAM_ARRAY_INDEX(stream_id);
773 if (stream_index >= MAX_NUMBER_OF_STREAMS ||
774 stream_index < 0) {
775 pr_err("%s: Invalid stream index %d", __func__,
776 stream_index);
777 spin_unlock_irqrestore(&prtd->lock, flags);
778 break;
779 }
780
781 if (prtd->gapless_state.set_next_stream_id &&
782 prtd->gapless_state.stream_opened[stream_index]) {
783 pr_debug("%s: CMD_CLOSE stream_id %d\n",
784 __func__, stream_id);
785 q6asm_stream_cmd_nowait(ac, CMD_CLOSE, stream_id);
786 atomic_set(&prtd->close, 1);
787 prtd->gapless_state.stream_opened[stream_index] = 0;
788 prtd->gapless_state.set_next_stream_id = false;
789 }
790 if (prtd->gapless_state.gapless_transition)
791 prtd->gapless_state.gapless_transition = 0;
792 spin_unlock_irqrestore(&prtd->lock, flags);
793 break;
794 case ASM_STREAM_PP_EVENT:
795 case ASM_STREAM_CMD_ENCDEC_EVENTS:
796 pr_debug("%s: ASM_STREAM_EVENT(0x%x)\n", __func__, opcode);
797 rtd = cstream->private_data;
798 if (!rtd) {
799 pr_err("%s: rtd is NULL\n", __func__);
800 return;
801 }
802
803 ret = msm_adsp_inform_mixer_ctl(rtd, payload);
804 if (ret) {
805 pr_err("%s: failed to inform mixer ctrl. err = %d\n",
806 __func__, ret);
807 return;
808 }
809 break;
810 case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
811 case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY: {
812 pr_debug("ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY\n");
813 chan_mode = payload[1] >> 16;
814 sample_rate = payload[2] >> 16;
815 if (prtd && (chan_mode != prtd->num_channels ||
816 sample_rate != prtd->sample_rate)) {
817 prtd->num_channels = chan_mode;
818 prtd->sample_rate = sample_rate;
819 }
820 }
821 /* Fallthrough here */
822 case APR_BASIC_RSP_RESULT: {
823 switch (payload[0]) {
824 case ASM_SESSION_CMD_RUN_V2:
825 /* check if the first buffer need to be sent to DSP */
826 pr_debug("ASM_SESSION_CMD_RUN_V2\n");
827
828 /* FIXME: A state is a better way, dealing with this */
829 spin_lock_irqsave(&prtd->lock, flags);
830
831 if (cstream->direction == SND_COMPRESS_CAPTURE) {
832 atomic_set(&prtd->start, 1);
833 msm_compr_read_buffer(prtd);
834 spin_unlock_irqrestore(&prtd->lock, flags);
835 break;
836 }
837
838 if (!prtd->bytes_sent) {
839 bytes_available = prtd->bytes_received -
840 prtd->copied_total;
841 if (bytes_available <
842 cstream->runtime->fragment_size) {
843 pr_debug("CMD_RUN_V2 Insufficient data to send. break out\n");
844 atomic_set(&prtd->xrun, 1);
845 } else {
846 msm_compr_send_buffer(prtd);
847 }
848 }
849
850 /*
851 * The condition below ensures playback finishes in the
852 * follow cornercase
853 * WRITE(last buffer)
854 * WAIT_FOR_DRAIN
855 * PAUSE
856 * WRITE_DONE(X)
857 * RESUME
858 */
859 if ((prtd->copied_total == prtd->bytes_sent) &&
Weiyin Jiang7b51a252019-11-26 03:33:12 +0800860 atomic_read(&prtd->drain)) {
861 bytes_available = prtd->bytes_received - prtd->copied_total;
862 if (bytes_available < cstream->runtime->fragment_size) {
863 pr_debug("%s: RUN ack, wake up & continue pending drain\n",
864 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530865
Weiyin Jiang7b51a252019-11-26 03:33:12 +0800866 if (prtd->last_buffer)
867 prtd->last_buffer = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530868
Weiyin Jiang7b51a252019-11-26 03:33:12 +0800869 prtd->drain_ready = 1;
870 wake_up(&prtd->drain_wait);
871 atomic_set(&prtd->drain, 0);
872 } else if (atomic_read(&prtd->xrun)) {
873 pr_debug("%s: RUN ack, continue write cycle\n", __func__);
874 atomic_set(&prtd->xrun, 0);
875 msm_compr_send_buffer(prtd);
876 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530877 }
878
879 spin_unlock_irqrestore(&prtd->lock, flags);
880 break;
881 case ASM_STREAM_CMD_FLUSH:
882 pr_debug("%s: ASM_STREAM_CMD_FLUSH:", __func__);
883 pr_debug("token 0x%x, stream id %d\n", token,
884 stream_id);
885 prtd->cmd_ack = 1;
886 break;
887 case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:
888 pr_debug("%s: ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:",
889 __func__);
890 pr_debug("token 0x%x, stream id = %d\n", token,
891 stream_id);
892 break;
893 case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
894 pr_debug("%s: ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:",
895 __func__);
896 pr_debug("token = 0x%x, stream id = %d\n", token,
897 stream_id);
898 break;
899 case ASM_STREAM_CMD_CLOSE:
900 pr_debug("%s: ASM_DATA_CMD_CLOSE:", __func__);
901 pr_debug("token 0x%x, stream id %d\n", token,
902 stream_id);
903 /*
904 * wakeup wait for stream avail on stream 3
905 * after stream 1 ends.
906 */
907 if (prtd->next_stream) {
908 pr_debug("%s:CLOSE:wakeup wait for stream\n",
909 __func__);
910 prtd->stream_available = 1;
911 wake_up(&prtd->wait_for_stream_avail);
912 prtd->next_stream = 0;
913 }
914 if (atomic_read(&prtd->close) &&
915 atomic_read(&prtd->wait_on_close)) {
916 prtd->cmd_ack = 1;
917 wake_up(&prtd->close_wait);
918 }
919 atomic_set(&prtd->close, 0);
920 break;
921 case ASM_STREAM_CMD_REGISTER_PP_EVENTS:
922 pr_debug("%s: ASM_STREAM_CMD_REGISTER_PP_EVENTS:",
923 __func__);
924 break;
925 default:
926 break;
927 }
928 break;
929 }
930 case ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3:
931 pr_debug("%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3\n",
932 __func__);
933 break;
934 case RESET_EVENTS:
935 pr_err("%s: Received reset events CB, move to error state",
936 __func__);
937 spin_lock_irqsave(&prtd->lock, flags);
938 /*
939 * Since ADSP is down, let this driver pretend that it copied
940 * all the bytes received, so that next write will be triggered
941 */
942 prtd->copied_total = prtd->bytes_received;
943 snd_compr_fragment_elapsed(cstream);
944 atomic_set(&prtd->error, 1);
945 wake_up(&prtd->drain_wait);
946 if (atomic_cmpxchg(&prtd->eos, 1, 0)) {
947 pr_debug("%s:unblock eos wait queues", __func__);
948 wake_up(&prtd->eos_wait);
949 }
950 spin_unlock_irqrestore(&prtd->lock, flags);
951 break;
952 default:
953 pr_debug("%s: Not Supported Event opcode[0x%x]\n",
954 __func__, opcode);
955 break;
956 }
957}
958
959static int msm_compr_get_partial_drain_delay(int frame_sz, int sample_rate)
960{
961 int delay_time_ms = 0;
962
963 delay_time_ms = ((DSP_NUM_OUTPUT_FRAME_BUFFERED * frame_sz * 1000) /
964 sample_rate) + DSP_PP_BUFFERING_IN_MSEC;
965 delay_time_ms = delay_time_ms > PARTIAL_DRAIN_ACK_EARLY_BY_MSEC ?
966 delay_time_ms - PARTIAL_DRAIN_ACK_EARLY_BY_MSEC : 0;
967
968 pr_debug("%s: frame_sz %d, sample_rate %d, partial drain delay %d\n",
969 __func__, frame_sz, sample_rate, delay_time_ms);
970 return delay_time_ms;
971}
972
973static void populate_codec_list(struct msm_compr_audio *prtd)
974{
975 pr_debug("%s\n", __func__);
976 prtd->compr_cap.direction = SND_COMPRESS_PLAYBACK;
977 prtd->compr_cap.min_fragment_size =
978 COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
979 prtd->compr_cap.max_fragment_size =
980 COMPR_PLAYBACK_MAX_FRAGMENT_SIZE;
981 prtd->compr_cap.min_fragments =
982 COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
983 prtd->compr_cap.max_fragments =
984 COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
985 prtd->compr_cap.num_codecs = 17;
986 prtd->compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
987 prtd->compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
988 prtd->compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
989 prtd->compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3;
990 prtd->compr_cap.codecs[4] = SND_AUDIOCODEC_MP2;
991 prtd->compr_cap.codecs[5] = SND_AUDIOCODEC_PCM;
992 prtd->compr_cap.codecs[6] = SND_AUDIOCODEC_WMA;
993 prtd->compr_cap.codecs[7] = SND_AUDIOCODEC_WMA_PRO;
994 prtd->compr_cap.codecs[8] = SND_AUDIOCODEC_FLAC;
995 prtd->compr_cap.codecs[9] = SND_AUDIOCODEC_VORBIS;
996 prtd->compr_cap.codecs[10] = SND_AUDIOCODEC_ALAC;
997 prtd->compr_cap.codecs[11] = SND_AUDIOCODEC_APE;
998 prtd->compr_cap.codecs[12] = SND_AUDIOCODEC_DTS;
999 prtd->compr_cap.codecs[13] = SND_AUDIOCODEC_DSD;
1000 prtd->compr_cap.codecs[14] = SND_AUDIOCODEC_APTX;
1001 prtd->compr_cap.codecs[15] = SND_AUDIOCODEC_TRUEHD;
1002 prtd->compr_cap.codecs[16] = SND_AUDIOCODEC_IEC61937;
1003}
1004
1005static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
1006 int stream_id,
1007 bool use_gapless_codec_options)
1008{
1009 struct snd_compr_runtime *runtime = cstream->runtime;
1010 struct msm_compr_audio *prtd = runtime->private_data;
1011 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Meng Wangee084a02018-09-04 16:11:58 +08001012 struct snd_soc_component *component =NULL;
1013 struct msm_compr_pdata *pdata = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301014 struct asm_aac_cfg aac_cfg;
1015 struct asm_wma_cfg wma_cfg;
1016 struct asm_wmapro_cfg wma_pro_cfg;
1017 struct asm_flac_cfg flac_cfg;
1018 struct asm_vorbis_cfg vorbis_cfg;
1019 struct asm_alac_cfg alac_cfg;
1020 struct asm_ape_cfg ape_cfg;
1021 struct asm_dsd_cfg dsd_cfg;
1022 struct aptx_dec_bt_addr_cfg aptx_cfg;
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +05301023 struct asm_amrwbplus_cfg amrwbplus_cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301024 union snd_codec_options *codec_options;
1025
1026 int ret = 0;
1027 uint16_t bit_width;
1028 bool use_default_chmap = true;
1029 char *chmap = NULL;
1030 uint16_t sample_word_size;
1031
1032 pr_debug("%s: use_gapless_codec_options %d\n",
1033 __func__, use_gapless_codec_options);
1034
Meng Wangee084a02018-09-04 16:11:58 +08001035 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
1036 if (!component) {
1037 pr_err("%s: component is NULL\n", __func__);
1038 return -EINVAL;
1039 }
1040 pdata = snd_soc_component_get_drvdata(component);
1041
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301042 if (use_gapless_codec_options)
1043 codec_options = &(prtd->gapless_state.codec_options);
1044 else
1045 codec_options = &(prtd->codec_param.codec.options);
1046
1047 if (!codec_options) {
1048 pr_err("%s: codec_options is NULL\n", __func__);
1049 return -EINVAL;
1050 }
1051
1052 switch (prtd->codec) {
1053 case FORMAT_LINEAR_PCM:
1054 pr_debug("SND_AUDIOCODEC_PCM\n");
1055 if (pdata->ch_map[rtd->dai_link->id]) {
1056 use_default_chmap =
1057 !(pdata->ch_map[rtd->dai_link->id]->set_ch_map);
1058 chmap =
1059 pdata->ch_map[rtd->dai_link->id]->channel_map;
1060 }
1061
1062 switch (prtd->codec_param.codec.format) {
1063 case SNDRV_PCM_FORMAT_S32_LE:
1064 bit_width = 32;
1065 sample_word_size = 32;
1066 break;
1067 case SNDRV_PCM_FORMAT_S24_LE:
1068 bit_width = 24;
1069 sample_word_size = 32;
1070 break;
1071 case SNDRV_PCM_FORMAT_S24_3LE:
1072 bit_width = 24;
1073 sample_word_size = 24;
1074 break;
1075 case SNDRV_PCM_FORMAT_S16_LE:
1076 default:
1077 bit_width = 16;
1078 sample_word_size = 16;
1079 break;
1080 }
Dieter Lueckingceef9af2018-09-28 15:09:32 +02001081
1082 if (q6core_get_avcs_api_version_per_service(
1083 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1084 ADSP_ASM_API_VERSION_V2) {
1085 ret = q6asm_media_format_block_pcm_format_support_v5(
1086 prtd->audio_client,
1087 prtd->sample_rate,
1088 prtd->num_channels,
1089 bit_width, stream_id,
1090 use_default_chmap,
1091 chmap,
1092 sample_word_size,
1093 ASM_LITTLE_ENDIAN,
1094 DEFAULT_QF);
1095 } else {
1096 ret = q6asm_media_format_block_pcm_format_support_v4(
1097 prtd->audio_client,
1098 prtd->sample_rate,
1099 prtd->num_channels,
1100 bit_width, stream_id,
1101 use_default_chmap,
1102 chmap,
1103 sample_word_size,
1104 ASM_LITTLE_ENDIAN,
1105 DEFAULT_QF);
1106 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301107 if (ret < 0)
1108 pr_err("%s: CMD Format block failed\n", __func__);
1109
1110 break;
1111 case FORMAT_MP3:
1112 pr_debug("SND_AUDIOCODEC_MP3\n");
1113 /* no media format block needed */
1114 break;
1115 case FORMAT_MPEG4_AAC:
1116 pr_debug("SND_AUDIOCODEC_AAC\n");
1117 memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg));
1118 aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
1119 if (prtd->codec_param.codec.format ==
1120 SND_AUDIOSTREAMFORMAT_MP4ADTS)
1121 aac_cfg.format = 0x0;
1122 else if (prtd->codec_param.codec.format ==
1123 SND_AUDIOSTREAMFORMAT_MP4LATM)
1124 aac_cfg.format = 0x04;
1125 else
1126 aac_cfg.format = 0x03;
1127 aac_cfg.ch_cfg = prtd->num_channels;
1128 aac_cfg.sample_rate = prtd->sample_rate;
1129 ret = q6asm_stream_media_format_block_aac(prtd->audio_client,
1130 &aac_cfg, stream_id);
1131 if (ret < 0)
1132 pr_err("%s: CMD Format block failed\n", __func__);
1133 break;
1134 case FORMAT_AC3:
1135 pr_debug("SND_AUDIOCODEC_AC3\n");
1136 break;
1137 case FORMAT_EAC3:
1138 pr_debug("SND_AUDIOCODEC_EAC3\n");
1139 break;
1140 case FORMAT_WMA_V9:
1141 pr_debug("SND_AUDIOCODEC_WMA\n");
1142 memset(&wma_cfg, 0x0, sizeof(struct asm_wma_cfg));
1143 wma_cfg.format_tag = prtd->codec_param.codec.format;
1144 wma_cfg.ch_cfg = prtd->codec_param.codec.ch_in;
1145 wma_cfg.sample_rate = prtd->sample_rate;
1146 wma_cfg.avg_bytes_per_sec = codec_options->wma.avg_bit_rate/8;
1147 wma_cfg.block_align = codec_options->wma.super_block_align;
1148 wma_cfg.valid_bits_per_sample =
1149 codec_options->wma.bits_per_sample;
1150 wma_cfg.ch_mask = codec_options->wma.channelmask;
1151 wma_cfg.encode_opt = codec_options->wma.encodeopt;
1152 ret = q6asm_media_format_block_wma(prtd->audio_client,
1153 &wma_cfg, stream_id);
1154 if (ret < 0)
1155 pr_err("%s: CMD Format block failed\n", __func__);
1156 break;
1157 case FORMAT_WMA_V10PRO:
1158 pr_debug("SND_AUDIOCODEC_WMA_PRO\n");
1159 memset(&wma_pro_cfg, 0x0, sizeof(struct asm_wmapro_cfg));
1160 wma_pro_cfg.format_tag = prtd->codec_param.codec.format;
1161 wma_pro_cfg.ch_cfg = prtd->codec_param.codec.ch_in;
1162 wma_pro_cfg.sample_rate = prtd->sample_rate;
1163 wma_cfg.avg_bytes_per_sec = codec_options->wma.avg_bit_rate/8;
1164 wma_pro_cfg.block_align = codec_options->wma.super_block_align;
1165 wma_pro_cfg.valid_bits_per_sample =
1166 codec_options->wma.bits_per_sample;
1167 wma_pro_cfg.ch_mask = codec_options->wma.channelmask;
1168 wma_pro_cfg.encode_opt = codec_options->wma.encodeopt;
1169 wma_pro_cfg.adv_encode_opt = codec_options->wma.encodeopt1;
1170 wma_pro_cfg.adv_encode_opt2 = codec_options->wma.encodeopt2;
1171 ret = q6asm_media_format_block_wmapro(prtd->audio_client,
1172 &wma_pro_cfg, stream_id);
1173 if (ret < 0)
1174 pr_err("%s: CMD Format block failed\n", __func__);
1175 break;
1176 case FORMAT_MP2:
1177 pr_debug("%s: SND_AUDIOCODEC_MP2\n", __func__);
1178 break;
1179 case FORMAT_FLAC:
1180 pr_debug("%s: SND_AUDIOCODEC_FLAC\n", __func__);
1181 memset(&flac_cfg, 0x0, sizeof(struct asm_flac_cfg));
1182 flac_cfg.ch_cfg = prtd->num_channels;
1183 flac_cfg.sample_rate = prtd->sample_rate;
1184 flac_cfg.stream_info_present = 1;
1185 flac_cfg.sample_size = codec_options->flac_dec.sample_size;
1186 flac_cfg.min_blk_size = codec_options->flac_dec.min_blk_size;
1187 flac_cfg.max_blk_size = codec_options->flac_dec.max_blk_size;
1188 flac_cfg.max_frame_size =
1189 codec_options->flac_dec.max_frame_size;
1190 flac_cfg.min_frame_size =
1191 codec_options->flac_dec.min_frame_size;
1192
1193 ret = q6asm_stream_media_format_block_flac(prtd->audio_client,
1194 &flac_cfg, stream_id);
1195 if (ret < 0)
1196 pr_err("%s: CMD Format block failed ret %d\n",
1197 __func__, ret);
1198
1199 break;
1200 case FORMAT_VORBIS:
1201 pr_debug("%s: SND_AUDIOCODEC_VORBIS\n", __func__);
1202 memset(&vorbis_cfg, 0x0, sizeof(struct asm_vorbis_cfg));
1203 vorbis_cfg.bit_stream_fmt =
1204 codec_options->vorbis_dec.bit_stream_fmt;
1205
1206 ret = q6asm_stream_media_format_block_vorbis(
1207 prtd->audio_client, &vorbis_cfg,
1208 stream_id);
1209 if (ret < 0)
1210 pr_err("%s: CMD Format block failed ret %d\n",
1211 __func__, ret);
1212
1213 break;
1214 case FORMAT_ALAC:
1215 pr_debug("%s: SND_AUDIOCODEC_ALAC\n", __func__);
1216 memset(&alac_cfg, 0x0, sizeof(struct asm_alac_cfg));
1217 alac_cfg.num_channels = prtd->num_channels;
1218 alac_cfg.sample_rate = prtd->sample_rate;
1219 alac_cfg.frame_length = codec_options->alac.frame_length;
1220 alac_cfg.compatible_version =
1221 codec_options->alac.compatible_version;
1222 alac_cfg.bit_depth = codec_options->alac.bit_depth;
1223 alac_cfg.pb = codec_options->alac.pb;
1224 alac_cfg.mb = codec_options->alac.mb;
1225 alac_cfg.kb = codec_options->alac.kb;
1226 alac_cfg.max_run = codec_options->alac.max_run;
1227 alac_cfg.max_frame_bytes = codec_options->alac.max_frame_bytes;
1228 alac_cfg.avg_bit_rate = codec_options->alac.avg_bit_rate;
1229 alac_cfg.channel_layout_tag =
1230 codec_options->alac.channel_layout_tag;
1231
1232 ret = q6asm_media_format_block_alac(prtd->audio_client,
1233 &alac_cfg, stream_id);
1234 if (ret < 0)
1235 pr_err("%s: CMD Format block failed ret %d\n",
1236 __func__, ret);
1237 break;
1238 case FORMAT_APE:
1239 pr_debug("%s: SND_AUDIOCODEC_APE\n", __func__);
1240 memset(&ape_cfg, 0x0, sizeof(struct asm_ape_cfg));
1241 ape_cfg.num_channels = prtd->num_channels;
1242 ape_cfg.sample_rate = prtd->sample_rate;
1243 ape_cfg.compatible_version =
1244 codec_options->ape.compatible_version;
1245 ape_cfg.compression_level =
1246 codec_options->ape.compression_level;
1247 ape_cfg.format_flags = codec_options->ape.format_flags;
1248 ape_cfg.blocks_per_frame = codec_options->ape.blocks_per_frame;
1249 ape_cfg.final_frame_blocks =
1250 codec_options->ape.final_frame_blocks;
1251 ape_cfg.total_frames = codec_options->ape.total_frames;
1252 ape_cfg.bits_per_sample = codec_options->ape.bits_per_sample;
1253 ape_cfg.seek_table_present =
1254 codec_options->ape.seek_table_present;
1255
1256 ret = q6asm_media_format_block_ape(prtd->audio_client,
1257 &ape_cfg, stream_id);
1258
1259 if (ret < 0)
1260 pr_err("%s: CMD Format block failed ret %d\n",
1261 __func__, ret);
1262 break;
1263 case FORMAT_DTS:
1264 pr_debug("SND_AUDIOCODEC_DTS\n");
1265 /* no media format block needed */
1266 break;
1267 case FORMAT_DSD:
1268 pr_debug("%s: SND_AUDIOCODEC_DSD\n", __func__);
1269 memset(&dsd_cfg, 0x0, sizeof(struct asm_dsd_cfg));
1270 dsd_cfg.num_channels = prtd->num_channels;
1271 dsd_cfg.dsd_data_rate = prtd->sample_rate;
1272 dsd_cfg.num_version = 0;
1273 dsd_cfg.is_bitwise_big_endian = 1;
1274 dsd_cfg.dsd_channel_block_size = 1;
Sanjana Bc45335a2019-12-06 17:16:36 +05301275
1276 if (codec_options->dsd_dec.blk_size == DSD_BLOCK_SIZE_4)
1277 dsd_cfg.dsd_channel_block_size =
1278 codec_options->dsd_dec.blk_size;
1279
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301280 ret = q6asm_media_format_block_dsd(prtd->audio_client,
1281 &dsd_cfg, stream_id);
1282 if (ret < 0)
1283 pr_err("%s: CMD DSD Format block failed ret %d\n",
1284 __func__, ret);
1285 break;
1286 case FORMAT_TRUEHD:
1287 pr_debug("SND_AUDIOCODEC_TRUEHD\n");
1288 /* no media format block needed */
1289 break;
1290 case FORMAT_IEC61937:
1291 pr_debug("SND_AUDIOCODEC_IEC61937\n");
1292 ret = q6asm_media_format_block_iec(prtd->audio_client,
1293 prtd->sample_rate,
1294 prtd->num_channels);
1295 if (ret < 0)
1296 pr_err("%s: CMD IEC61937 Format block failed ret %d\n",
1297 __func__, ret);
1298 break;
1299 case FORMAT_APTX:
1300 pr_debug("SND_AUDIOCODEC_APTX\n");
1301 memset(&aptx_cfg, 0x0, sizeof(struct aptx_dec_bt_addr_cfg));
1302 ret = q6asm_stream_media_format_block_aptx_dec(
1303 prtd->audio_client,
1304 prtd->sample_rate,
1305 stream_id);
1306 if (ret >= 0) {
1307 aptx_cfg.nap = codec_options->aptx_dec.nap;
1308 aptx_cfg.uap = codec_options->aptx_dec.uap;
1309 aptx_cfg.lap = codec_options->aptx_dec.lap;
1310 q6asm_set_aptx_dec_bt_addr(prtd->audio_client,
1311 &aptx_cfg);
1312 } else {
1313 pr_err("%s: CMD Format block failed ret %d\n",
1314 __func__, ret);
1315 }
1316 break;
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +05301317 case FORMAT_AMRNB:
1318 pr_debug("SND_AUDIOCODEC_AMR\n");
1319 /* no media format block needed */
1320 break;
1321 case FORMAT_AMRWB:
1322 pr_debug("SND_AUDIOCODEC_AMRWB\n");
1323 /* no media format block needed */
1324 break;
1325 case FORMAT_AMR_WB_PLUS:
1326 pr_debug("SND_AUDIOCODEC_AMRWBPLUS\n");
1327 memset(&amrwbplus_cfg, 0x0, sizeof(struct asm_amrwbplus_cfg));
1328 amrwbplus_cfg.amr_frame_fmt =
1329 codec_options->amrwbplus.bit_stream_fmt;
1330 ret = q6asm_media_format_block_amrwbplus(
1331 prtd->audio_client,
1332 &amrwbplus_cfg);
1333 if (ret < 0)
1334 pr_err("%s: CMD AMRWBPLUS Format block failed ret %d\n",
1335 __func__, ret);
1336 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301337 default:
1338 pr_debug("%s, unsupported format, skip", __func__);
1339 break;
1340 }
1341 return ret;
1342}
1343
1344static int msm_compr_init_pp_params(struct snd_compr_stream *cstream,
1345 struct audio_client *ac)
1346{
1347 int ret = 0;
1348 struct asm_softvolume_params softvol = {
1349 .period = SOFT_VOLUME_PERIOD,
1350 .step = SOFT_VOLUME_STEP,
1351 .rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
1352 };
1353
1354 switch (ac->topology) {
1355 default:
1356 ret = q6asm_set_softvolume_v2(ac, &softvol,
1357 SOFT_VOLUME_INSTANCE_1);
1358 if (ret < 0)
1359 pr_err("%s: Send SoftVolume Param failed ret=%d\n",
1360 __func__, ret);
1361
1362 break;
1363 }
1364 return ret;
1365}
1366
1367static int msm_compr_configure_dsp_for_playback
1368 (struct snd_compr_stream *cstream)
1369{
1370 struct snd_compr_runtime *runtime = cstream->runtime;
1371 struct msm_compr_audio *prtd = runtime->private_data;
1372 struct snd_soc_pcm_runtime *soc_prtd = cstream->private_data;
1373 uint16_t bits_per_sample = 16;
1374 int dir = IN, ret = 0;
1375 struct audio_client *ac = prtd->audio_client;
1376 uint32_t stream_index;
1377 struct asm_softpause_params softpause = {
1378 .enable = SOFT_PAUSE_ENABLE,
1379 .period = SOFT_PAUSE_PERIOD,
1380 .step = SOFT_PAUSE_STEP,
1381 .rampingcurve = SOFT_PAUSE_CURVE_LINEAR,
1382 };
1383 struct asm_softvolume_params softvol = {
1384 .period = SOFT_VOLUME_PERIOD,
1385 .step = SOFT_VOLUME_STEP,
1386 .rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
1387 };
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05301388 struct snd_kcontrol *kctl;
1389 struct snd_ctl_elem_value kctl_elem_value;
1390 uint16_t target_asm_bit_width = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301391
1392 pr_debug("%s: stream_id %d\n", __func__, ac->stream_id);
1393 stream_index = STREAM_ARRAY_INDEX(ac->stream_id);
1394 if (stream_index >= MAX_NUMBER_OF_STREAMS || stream_index < 0) {
1395 pr_err("%s: Invalid stream index:%d", __func__, stream_index);
1396 return -EINVAL;
1397 }
1398
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05301399 kctl = snd_soc_card_get_kcontrol(soc_prtd->card,
1400 DSP_BIT_WIDTH_MIXER_CTL);
1401 if (kctl) {
1402 kctl->get(kctl, &kctl_elem_value);
1403 target_asm_bit_width = kctl_elem_value.value.integer.value[0];
1404 if (target_asm_bit_width > 0) {
1405 pr_debug("%s enforce ASM bitwidth to %d from %d\n",
1406 __func__,
1407 target_asm_bit_width,
1408 bits_per_sample);
1409 bits_per_sample = target_asm_bit_width;
1410 }
1411 } else {
1412 pr_info("%s: failed to get mixer ctl for %s.\n",
1413 __func__, DSP_BIT_WIDTH_MIXER_CTL);
1414 }
1415
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301416 if ((prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_LE) ||
1417 (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_3LE))
1418 bits_per_sample = 24;
1419 else if (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S32_LE)
1420 bits_per_sample = 32;
1421
1422 if (prtd->compr_passthr != LEGACY_PCM) {
1423 ret = q6asm_open_write_compressed(ac, prtd->codec,
1424 prtd->compr_passthr);
1425 if (ret < 0) {
1426 pr_err("%s:ASM open write err[%d] for compr_type[%d]\n",
1427 __func__, ret, prtd->compr_passthr);
1428 return ret;
1429 }
1430 prtd->gapless_state.stream_opened[stream_index] = 1;
1431
1432 ret = msm_pcm_routing_reg_phy_compr_stream(
1433 soc_prtd->dai_link->id,
1434 ac->perf_mode,
1435 prtd->session_id,
1436 SNDRV_PCM_STREAM_PLAYBACK,
1437 prtd->compr_passthr);
1438 if (ret) {
1439 pr_err("%s: compr stream reg failed:%d\n", __func__,
1440 ret);
1441 return ret;
1442 }
1443 } else {
1444 pr_debug("%s: stream_id %d bits_per_sample %d\n",
1445 __func__, ac->stream_id, bits_per_sample);
Dieter Lueckingceef9af2018-09-28 15:09:32 +02001446
1447 if (q6core_get_avcs_api_version_per_service(
1448 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1449 ADSP_ASM_API_VERSION_V2)
1450 ret = q6asm_stream_open_write_v5(ac,
1451 prtd->codec, bits_per_sample,
1452 ac->stream_id,
1453 prtd->gapless_state.use_dsp_gapless_mode);
1454 else
1455 ret = q6asm_stream_open_write_v4(ac,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301456 prtd->codec, bits_per_sample,
1457 ac->stream_id,
1458 prtd->gapless_state.use_dsp_gapless_mode);
1459 if (ret < 0) {
1460 pr_err("%s:ASM open write err[%d] for compr type[%d]\n",
1461 __func__, ret, prtd->compr_passthr);
1462 return -ENOMEM;
1463 }
1464 prtd->gapless_state.stream_opened[stream_index] = 1;
1465
1466 pr_debug("%s: BE id %d\n", __func__, soc_prtd->dai_link->id);
1467 ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->id,
1468 ac->perf_mode,
1469 prtd->session_id,
1470 SNDRV_PCM_STREAM_PLAYBACK);
1471 if (ret) {
1472 pr_err("%s: stream reg failed:%d\n", __func__, ret);
1473 return ret;
1474 }
1475 }
1476
1477 ret = msm_compr_set_volume(cstream, 0, 0);
1478 if (ret < 0)
1479 pr_err("%s : Set Volume failed : %d", __func__, ret);
1480
1481 if (prtd->compr_passthr != LEGACY_PCM) {
1482 pr_debug("%s : Don't send cal and PP params for compress path",
1483 __func__);
1484 } else {
1485 ret = q6asm_send_cal(ac);
1486 if (ret < 0)
1487 pr_debug("%s : Send cal failed : %d", __func__, ret);
1488
1489 ret = q6asm_set_softpause(ac, &softpause);
1490 if (ret < 0)
1491 pr_err("%s: Send SoftPause Param failed ret=%d\n",
1492 __func__, ret);
1493
1494 ret = q6asm_set_softvolume(ac, &softvol);
1495 if (ret < 0)
1496 pr_err("%s: Send SoftVolume Param failed ret=%d\n",
1497 __func__, ret);
1498 }
1499 ret = q6asm_set_io_mode(ac, (COMPRESSED_STREAM_IO | ASYNC_IO_MODE));
1500 if (ret < 0) {
1501 pr_err("%s: Set IO mode failed\n", __func__);
1502 return -EINVAL;
1503 }
1504
1505 runtime->fragments = prtd->codec_param.buffer.fragments;
1506 runtime->fragment_size = prtd->codec_param.buffer.fragment_size;
1507 pr_debug("allocate %d buffers each of size %d\n",
1508 runtime->fragments,
1509 runtime->fragment_size);
1510 ret = q6asm_audio_client_buf_alloc_contiguous(dir, ac,
1511 runtime->fragment_size,
1512 runtime->fragments);
1513 if (ret < 0) {
1514 pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
1515 return -ENOMEM;
1516 }
1517
1518 prtd->byte_offset = 0;
1519 prtd->copied_total = 0;
1520 prtd->app_pointer = 0;
1521 prtd->bytes_received = 0;
1522 prtd->bytes_sent = 0;
1523 prtd->buffer = ac->port[dir].buf[0].data;
1524 prtd->buffer_paddr = ac->port[dir].buf[0].phys;
1525 prtd->buffer_size = runtime->fragments * runtime->fragment_size;
1526
1527 /* Bit-0 of flags represent timestamp mode */
1528 if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG)
1529 prtd->ts_header_offset = sizeof(struct snd_codec_metadata);
1530 else
1531 prtd->ts_header_offset = 0;
1532
1533 ret = msm_compr_send_media_format_block(cstream, ac->stream_id, false);
1534 if (ret < 0)
1535 pr_err("%s, failed to send media format block\n", __func__);
1536
1537 return ret;
1538}
1539
1540static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
1541{
1542 struct snd_compr_runtime *runtime = cstream->runtime;
1543 struct msm_compr_audio *prtd = runtime->private_data;
1544 struct snd_soc_pcm_runtime *soc_prtd = cstream->private_data;
1545 uint16_t bits_per_sample;
1546 uint16_t sample_word_size;
1547 int dir = OUT, ret = 0;
1548 struct audio_client *ac = prtd->audio_client;
1549 uint32_t stream_index;
Vikram Pandurangac712c172017-11-17 17:36:49 -08001550 uint32_t enc_cfg_id = ENC_CFG_ID_NONE;
Surendar Karkaafd3e122019-10-31 10:55:40 +05301551 bool compress_ts = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301552
1553 switch (prtd->codec_param.codec.format) {
1554 case SNDRV_PCM_FORMAT_S24_LE:
1555 bits_per_sample = 24;
1556 sample_word_size = 32;
1557 break;
1558 case SNDRV_PCM_FORMAT_S24_3LE:
1559 bits_per_sample = 24;
1560 sample_word_size = 24;
1561 break;
1562 case SNDRV_PCM_FORMAT_S32_LE:
1563 bits_per_sample = 32;
1564 sample_word_size = 32;
1565 break;
1566 case SNDRV_PCM_FORMAT_S16_LE:
1567 default:
1568 bits_per_sample = 16;
1569 sample_word_size = 16;
Vikram Pandurangac712c172017-11-17 17:36:49 -08001570 if (prtd->codec == FORMAT_BESPOKE)
1571 enc_cfg_id =
1572 prtd->codec_param.codec.options.generic.reserved[0];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301573 break;
1574 }
1575
Ralf Herz22573552018-06-20 11:30:58 +02001576 pr_debug("%s: stream_id %d bits_per_sample %d compr_passthr %d\n",
1577 __func__, ac->stream_id, bits_per_sample,
1578 prtd->compr_passthr);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301579
Ralf Herz22573552018-06-20 11:30:58 +02001580 if (prtd->compr_passthr != LEGACY_PCM) {
1581 ret = q6asm_open_read_compressed(prtd->audio_client,
1582 prtd->codec, prtd->compr_passthr);
1583 if (ret < 0) {
1584 pr_err("%s:ASM open read err[%d] for compr_type[%d]\n",
1585 __func__, ret, prtd->compr_passthr);
1586 return ret;
1587 }
1588
1589 ret = msm_pcm_routing_reg_phy_compr_stream(
1590 soc_prtd->dai_link->id,
1591 ac->perf_mode,
1592 prtd->session_id,
1593 SNDRV_PCM_STREAM_CAPTURE,
1594 prtd->compr_passthr);
1595 if (ret) {
1596 pr_err("%s: compr stream reg failed:%d\n",
1597 __func__, ret);
1598 return ret;
1599 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301600 } else {
Surendar Karkaafd3e122019-10-31 10:55:40 +05301601 if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG)
1602 compress_ts = true;
1603
1604 if (q6core_get_avcs_api_version_per_service(
1605 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1606 ADSP_ASM_API_VERSION_V2)
1607 ret = q6asm_open_read_v5(prtd->audio_client,
1608 prtd->codec, bits_per_sample,
1609 compress_ts, enc_cfg_id);
1610 else
Ralf Herz22573552018-06-20 11:30:58 +02001611 ret = q6asm_open_read_v4(prtd->audio_client,
Surendar Karkaafd3e122019-10-31 10:55:40 +05301612 prtd->codec, bits_per_sample,
1613 compress_ts, enc_cfg_id);
Ralf Herz22573552018-06-20 11:30:58 +02001614 if (ret < 0) {
1615 pr_err("%s: q6asm_open_read failed:%d\n",
1616 __func__, ret);
1617 return ret;
1618 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301619
Ralf Herz22573552018-06-20 11:30:58 +02001620 ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->id,
1621 ac->perf_mode,
1622 prtd->session_id,
1623 SNDRV_PCM_STREAM_CAPTURE);
1624 if (ret) {
1625 pr_err("%s: stream reg failed:%d\n", __func__, ret);
1626 return ret;
1627 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301628 }
1629
1630 ret = q6asm_set_io_mode(ac, (COMPRESSED_STREAM_IO | ASYNC_IO_MODE));
1631 if (ret < 0) {
1632 pr_err("%s: Set IO mode failed\n", __func__);
1633 return -EINVAL;
1634 }
1635
1636 stream_index = STREAM_ARRAY_INDEX(ac->stream_id);
1637 if (stream_index >= MAX_NUMBER_OF_STREAMS || stream_index < 0) {
1638 pr_err("%s: Invalid stream index:%d", __func__, stream_index);
1639 return -EINVAL;
1640 }
1641
1642 runtime->fragments = prtd->codec_param.buffer.fragments;
1643 runtime->fragment_size = prtd->codec_param.buffer.fragment_size;
1644 pr_debug("%s: allocate %d buffers each of size %d\n",
1645 __func__, runtime->fragments,
1646 runtime->fragment_size);
1647 ret = q6asm_audio_client_buf_alloc_contiguous(dir, ac,
1648 runtime->fragment_size,
1649 runtime->fragments);
1650 if (ret < 0) {
1651 pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
1652 return -ENOMEM;
1653 }
1654
1655 prtd->byte_offset = 0;
1656 prtd->received_total = 0;
1657 prtd->app_pointer = 0;
1658 prtd->bytes_copied = 0;
1659 prtd->bytes_read = 0;
1660 prtd->bytes_read_offset = 0;
1661 prtd->buffer = ac->port[dir].buf[0].data;
1662 prtd->buffer_paddr = ac->port[dir].buf[0].phys;
1663 prtd->buffer_size = runtime->fragments * runtime->fragment_size;
1664
1665 /* Bit-0 of flags represent timestamp mode */
1666 if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG)
1667 prtd->ts_header_offset = sizeof(struct snd_codec_metadata);
1668 else
1669 prtd->ts_header_offset = 0;
1670
1671 pr_debug("%s: sample_rate = %d channels = %d bps = %d sample_word_size = %d\n",
1672 __func__, prtd->sample_rate, prtd->num_channels,
1673 bits_per_sample, sample_word_size);
Vikram Pandurangac712c172017-11-17 17:36:49 -08001674 if (prtd->codec == FORMAT_BESPOKE) {
1675 /*
1676 * For BESPOKE codec, encoder specific config params are
1677 * included as part of generic.
1678 */
1679 ret = q6asm_enc_cfg_blk_custom(prtd->audio_client, prtd->sample_rate,
1680 prtd->num_channels, prtd->codec,
1681 (void *)&prtd->codec_param.codec.options.generic);
Ralf Herz22573552018-06-20 11:30:58 +02001682 } else if (prtd->compr_passthr == LEGACY_PCM) {
Chaithanya Krishna Bacharaju61b2de62019-06-20 11:40:17 +05301683 if (q6core_get_avcs_api_version_per_service(
1684 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
1685 ADSP_ASM_API_VERSION_V2)
1686 ret = q6asm_enc_cfg_blk_pcm_format_support_v5(
1687 prtd->audio_client,
1688 prtd->sample_rate, prtd->num_channels,
1689 bits_per_sample, sample_word_size,
1690 ASM_LITTLE_ENDIAN, DEFAULT_QF);
1691 else
1692 ret = q6asm_enc_cfg_blk_pcm_format_support_v4(
1693 prtd->audio_client,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301694 prtd->sample_rate, prtd->num_channels,
Sachin Mohan Gadag7c944232018-01-04 11:04:00 +05301695 bits_per_sample, sample_word_size,
1696 ASM_LITTLE_ENDIAN, DEFAULT_QF);
Vikram Pandurangac712c172017-11-17 17:36:49 -08001697 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301698
1699 return ret;
1700}
1701
1702static int msm_compr_playback_open(struct snd_compr_stream *cstream)
1703{
1704 struct snd_compr_runtime *runtime = cstream->runtime;
1705 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Meng Wangee084a02018-09-04 16:11:58 +08001706 struct snd_soc_component *component = NULL;
Aditya Bavanari9deef912017-11-20 13:31:31 +05301707 struct msm_compr_audio *prtd = NULL;
Meng Wangee084a02018-09-04 16:11:58 +08001708 struct msm_compr_pdata *pdata = NULL;
Ramprasad Katkam17f05162019-04-15 18:37:10 +05301709 enum apr_subsys_state subsys_state;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301710
1711 pr_debug("%s\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08001712 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
1713 if (!component) {
1714 pr_err("%s: component is NULL\n", __func__);
1715 return -EINVAL;
1716 }
1717 pdata = snd_soc_component_get_drvdata(component);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301718 if (pdata->is_in_use[rtd->dai_link->id] == true) {
1719 pr_err("%s: %s is already in use, err: %d\n",
1720 __func__, rtd->dai_link->cpu_dai_name, -EBUSY);
1721 return -EBUSY;
1722 }
Ramprasad Katkam17f05162019-04-15 18:37:10 +05301723
1724 subsys_state = apr_get_subsys_state();
1725 if (subsys_state == APR_SUBSYS_DOWN) {
1726 pr_debug("%s: adsp is down\n", __func__);
1727 return -ENETRESET;
1728 }
1729
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301730 prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL);
1731 if (prtd == NULL) {
1732 pr_err("Failed to allocate memory for msm_compr_audio\n");
1733 return -ENOMEM;
1734 }
1735
1736 runtime->private_data = NULL;
1737 prtd->cstream = cstream;
1738 pdata->cstream[rtd->dai_link->id] = cstream;
1739 pdata->audio_effects[rtd->dai_link->id] =
1740 kzalloc(sizeof(struct msm_compr_audio_effects), GFP_KERNEL);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301741 if (pdata->audio_effects[rtd->dai_link->id] == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301742 pr_err("%s: Could not allocate memory for effects\n", __func__);
1743 pdata->cstream[rtd->dai_link->id] = NULL;
1744 kfree(prtd);
1745 return -ENOMEM;
1746 }
1747 pdata->dec_params[rtd->dai_link->id] =
1748 kzalloc(sizeof(struct msm_compr_dec_params), GFP_KERNEL);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301749 if (pdata->dec_params[rtd->dai_link->id] == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301750 pr_err("%s: Could not allocate memory for dec params\n",
1751 __func__);
1752 kfree(pdata->audio_effects[rtd->dai_link->id]);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301753 pdata->audio_effects[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301754 pdata->cstream[rtd->dai_link->id] = NULL;
1755 kfree(prtd);
1756 return -ENOMEM;
1757 }
1758 prtd->codec = FORMAT_MP3;
1759 prtd->bytes_received = 0;
1760 prtd->bytes_sent = 0;
1761 prtd->copied_total = 0;
1762 prtd->byte_offset = 0;
1763 prtd->sample_rate = 44100;
1764 prtd->num_channels = 2;
1765 prtd->drain_ready = 0;
1766 prtd->last_buffer = 0;
1767 prtd->first_buffer = 1;
1768 prtd->partial_drain_delay = 0;
1769 prtd->next_stream = 0;
1770 memset(&prtd->gapless_state, 0, sizeof(struct msm_compr_gapless_state));
1771 /*
1772 * Update the use_dsp_gapless_mode from gapless struture with the value
1773 * part of platform data.
1774 */
1775 prtd->gapless_state.use_dsp_gapless_mode = pdata->use_dsp_gapless_mode;
1776
1777 pr_debug("%s: gapless mode %d", __func__, pdata->use_dsp_gapless_mode);
1778
1779 spin_lock_init(&prtd->lock);
1780
1781 atomic_set(&prtd->eos, 0);
1782 atomic_set(&prtd->start, 0);
1783 atomic_set(&prtd->drain, 0);
1784 atomic_set(&prtd->xrun, 0);
1785 atomic_set(&prtd->close, 0);
1786 atomic_set(&prtd->wait_on_close, 0);
1787 atomic_set(&prtd->error, 0);
1788
1789 init_waitqueue_head(&prtd->eos_wait);
1790 init_waitqueue_head(&prtd->drain_wait);
1791 init_waitqueue_head(&prtd->close_wait);
1792 init_waitqueue_head(&prtd->wait_for_stream_avail);
1793
1794 runtime->private_data = prtd;
1795 populate_codec_list(prtd);
1796 prtd->audio_client = q6asm_audio_client_alloc(
1797 (app_cb)compr_event_handler, prtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301798 if (prtd->audio_client == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301799 pr_err("%s: Could not allocate memory for client\n", __func__);
1800 kfree(pdata->audio_effects[rtd->dai_link->id]);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301801 pdata->audio_effects[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301802 kfree(pdata->dec_params[rtd->dai_link->id]);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301803 pdata->dec_params[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301804 pdata->cstream[rtd->dai_link->id] = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301805 kfree(prtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301806 runtime->private_data = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301807 return -ENOMEM;
1808 }
1809 pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
1810 prtd->audio_client->perf_mode = false;
1811 prtd->session_id = prtd->audio_client->session;
1812 msm_adsp_init_mixer_ctl_pp_event_queue(rtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05301813 pdata->is_in_use[rtd->dai_link->id] = true;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301814 return 0;
1815}
1816
1817static int msm_compr_capture_open(struct snd_compr_stream *cstream)
1818{
1819 struct snd_compr_runtime *runtime = cstream->runtime;
1820 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Meng Wangee084a02018-09-04 16:11:58 +08001821 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301822 struct msm_compr_audio *prtd;
Meng Wangee084a02018-09-04 16:11:58 +08001823 struct msm_compr_pdata *pdata = NULL;
Ramprasad Katkam17f05162019-04-15 18:37:10 +05301824 enum apr_subsys_state subsys_state;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301825
1826 pr_debug("%s\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08001827 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
1828 if (!component) {
1829 pr_err("%s: component is NULL\n", __func__);
1830 return -EINVAL;
1831 }
1832 pdata = snd_soc_component_get_drvdata(component);
1833 if (!pdata) {
1834 pr_err("%s: pdata is NULL\n", __func__);
1835 return -EINVAL;
1836 }
Ramprasad Katkam17f05162019-04-15 18:37:10 +05301837
1838 subsys_state = apr_get_subsys_state();
1839 if (subsys_state == APR_SUBSYS_DOWN) {
1840 pr_debug("%s: adsp is down\n", __func__);
1841 return -ENETRESET;
1842 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301843 prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08001844 if (!prtd) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301845 pr_err("Failed to allocate memory for msm_compr_audio\n");
1846 return -ENOMEM;
1847 }
1848
1849 runtime->private_data = NULL;
1850 prtd->cstream = cstream;
1851 pdata->cstream[rtd->dai_link->id] = cstream;
1852
1853 prtd->audio_client = q6asm_audio_client_alloc(
1854 (app_cb)compr_event_handler, prtd);
1855 if (!prtd->audio_client) {
1856 pr_err("%s: Could not allocate memory for client\n", __func__);
1857 pdata->cstream[rtd->dai_link->id] = NULL;
1858 kfree(prtd);
1859 return -ENOMEM;
1860 }
1861 pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
1862 prtd->audio_client->perf_mode = false;
1863 prtd->session_id = prtd->audio_client->session;
1864 prtd->codec = FORMAT_LINEAR_PCM;
1865 prtd->bytes_copied = 0;
1866 prtd->bytes_read = 0;
1867 prtd->bytes_read_offset = 0;
1868 prtd->received_total = 0;
1869 prtd->byte_offset = 0;
1870 prtd->sample_rate = 48000;
1871 prtd->num_channels = 2;
1872 prtd->first_buffer = 0;
1873
1874 spin_lock_init(&prtd->lock);
1875
1876 atomic_set(&prtd->eos, 0);
1877 atomic_set(&prtd->start, 0);
1878 atomic_set(&prtd->drain, 0);
1879 atomic_set(&prtd->xrun, 0);
1880 atomic_set(&prtd->close, 0);
1881 atomic_set(&prtd->wait_on_close, 0);
1882 atomic_set(&prtd->error, 0);
1883
Xiaojun Sangd57aca02019-03-06 17:03:08 +08001884 init_waitqueue_head(&prtd->eos_wait);
1885 init_waitqueue_head(&prtd->drain_wait);
1886 init_waitqueue_head(&prtd->close_wait);
1887 init_waitqueue_head(&prtd->wait_for_stream_avail);
1888
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301889 runtime->private_data = prtd;
1890
1891 return 0;
1892}
1893
1894static int msm_compr_open(struct snd_compr_stream *cstream)
1895{
1896 int ret = 0;
1897
1898 if (cstream->direction == SND_COMPRESS_PLAYBACK)
1899 ret = msm_compr_playback_open(cstream);
1900 else if (cstream->direction == SND_COMPRESS_CAPTURE)
1901 ret = msm_compr_capture_open(cstream);
1902 return ret;
1903}
1904
1905static int msm_compr_playback_free(struct snd_compr_stream *cstream)
1906{
1907 struct snd_compr_runtime *runtime;
1908 struct msm_compr_audio *prtd;
1909 struct snd_soc_pcm_runtime *soc_prtd;
Meng Wangee084a02018-09-04 16:11:58 +08001910 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301911 struct msm_compr_pdata *pdata;
1912 struct audio_client *ac;
1913 int dir = IN, ret = 0, stream_id;
1914 unsigned long flags;
1915 uint32_t stream_index;
1916
1917 pr_debug("%s\n", __func__);
1918
1919 if (!cstream) {
1920 pr_err("%s cstream is null\n", __func__);
1921 return 0;
1922 }
1923 runtime = cstream->runtime;
1924 soc_prtd = cstream->private_data;
Meng Wang8a2a1042019-03-21 10:14:50 +08001925 if (!runtime || !soc_prtd) {
1926 pr_err("%s runtime or soc_prtd is null\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301927 __func__);
1928 return 0;
1929 }
Meng Wang8a2a1042019-03-21 10:14:50 +08001930 component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
1931 if (!component) {
1932 pr_err("%s component is null\n", __func__);
1933 return 0;
1934 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301935 prtd = runtime->private_data;
1936 if (!prtd) {
1937 pr_err("%s prtd is null\n", __func__);
1938 return 0;
1939 }
1940 prtd->cmd_interrupt = 1;
1941 wake_up(&prtd->drain_wait);
Meng Wangee084a02018-09-04 16:11:58 +08001942 pdata = snd_soc_component_get_drvdata(component);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301943 ac = prtd->audio_client;
1944 if (!pdata || !ac) {
1945 pr_err("%s pdata or ac is null\n", __func__);
1946 return 0;
1947 }
1948 if (atomic_read(&prtd->eos)) {
1949 ret = wait_event_timeout(prtd->eos_wait,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001950 prtd->eos_ack,
1951 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301952 if (!ret)
1953 pr_err("%s: CMD_EOS failed\n", __func__);
1954 }
1955 if (atomic_read(&prtd->close)) {
1956 prtd->cmd_ack = 0;
1957 atomic_set(&prtd->wait_on_close, 1);
1958 ret = wait_event_timeout(prtd->close_wait,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001959 prtd->cmd_ack,
1960 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301961 if (!ret)
1962 pr_err("%s: CMD_CLOSE failed\n", __func__);
1963 }
1964
1965 spin_lock_irqsave(&prtd->lock, flags);
1966 stream_id = ac->stream_id;
1967 stream_index = STREAM_ARRAY_INDEX(NEXT_STREAM_ID(stream_id));
1968
1969 if ((stream_index < MAX_NUMBER_OF_STREAMS && stream_index >= 0) &&
1970 (prtd->gapless_state.stream_opened[stream_index])) {
1971 prtd->gapless_state.stream_opened[stream_index] = 0;
1972 spin_unlock_irqrestore(&prtd->lock, flags);
1973 pr_debug(" close stream %d", NEXT_STREAM_ID(stream_id));
1974 q6asm_stream_cmd(ac, CMD_CLOSE, NEXT_STREAM_ID(stream_id));
1975 spin_lock_irqsave(&prtd->lock, flags);
1976 }
1977
1978 stream_index = STREAM_ARRAY_INDEX(stream_id);
1979 if ((stream_index < MAX_NUMBER_OF_STREAMS && stream_index >= 0) &&
1980 (prtd->gapless_state.stream_opened[stream_index])) {
1981 prtd->gapless_state.stream_opened[stream_index] = 0;
1982 spin_unlock_irqrestore(&prtd->lock, flags);
1983 pr_debug("close stream %d", stream_id);
1984 q6asm_stream_cmd(ac, CMD_CLOSE, stream_id);
1985 spin_lock_irqsave(&prtd->lock, flags);
1986 }
1987 spin_unlock_irqrestore(&prtd->lock, flags);
1988
Ajit Pandeyfa018862019-09-04 14:34:00 +05301989 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301990 pdata->cstream[soc_prtd->dai_link->id] = NULL;
1991 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
1992 msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
1993 SNDRV_PCM_STREAM_PLAYBACK);
1994 }
1995
1996 q6asm_audio_client_buf_free_contiguous(dir, ac);
1997
1998 q6asm_audio_client_free(ac);
1999 msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
Aditya Bavanari9deef912017-11-20 13:31:31 +05302000 if (pdata->audio_effects[soc_prtd->dai_link->id] != NULL) {
2001 kfree(pdata->audio_effects[soc_prtd->dai_link->id]);
2002 pdata->audio_effects[soc_prtd->dai_link->id] = NULL;
2003 }
2004 if (pdata->dec_params[soc_prtd->dai_link->id] != NULL) {
2005 kfree(pdata->dec_params[soc_prtd->dai_link->id]);
2006 pdata->dec_params[soc_prtd->dai_link->id] = NULL;
2007 }
Preetam Singh Ranawat1ac295b2020-04-22 16:57:02 +05302008 if (pdata->ch_map[soc_prtd->dai_link->id]) {
2009 pdata->ch_map[soc_prtd->dai_link->id]->set_ch_map = false;
2010 }
Aditya Bavanari9deef912017-11-20 13:31:31 +05302011 pdata->is_in_use[soc_prtd->dai_link->id] = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302012 kfree(prtd);
2013 runtime->private_data = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05302014 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302015
2016 return 0;
2017}
2018
2019static int msm_compr_capture_free(struct snd_compr_stream *cstream)
2020{
2021 struct snd_compr_runtime *runtime;
2022 struct msm_compr_audio *prtd;
2023 struct snd_soc_pcm_runtime *soc_prtd;
Meng Wangee084a02018-09-04 16:11:58 +08002024 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302025 struct msm_compr_pdata *pdata;
2026 struct audio_client *ac;
2027 int dir = OUT, stream_id;
2028 unsigned long flags;
2029 uint32_t stream_index;
2030
2031 if (!cstream) {
2032 pr_err("%s cstream is null\n", __func__);
2033 return 0;
2034 }
2035 runtime = cstream->runtime;
2036 soc_prtd = cstream->private_data;
Meng Wang8a2a1042019-03-21 10:14:50 +08002037 if (!runtime || !soc_prtd) {
2038 pr_err("%s runtime or soc_prtd is null\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302039 return 0;
2040 }
Meng Wang8a2a1042019-03-21 10:14:50 +08002041 component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
2042 if (!component) {
2043 pr_err("%s component is null\n", __func__);
2044 return 0;
2045 }
2046
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302047 prtd = runtime->private_data;
2048 if (!prtd) {
2049 pr_err("%s prtd is null\n", __func__);
2050 return 0;
2051 }
Meng Wangee084a02018-09-04 16:11:58 +08002052 pdata = snd_soc_component_get_drvdata(component);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302053 ac = prtd->audio_client;
2054 if (!pdata || !ac) {
2055 pr_err("%s pdata or ac is null\n", __func__);
2056 return 0;
2057 }
2058
2059 spin_lock_irqsave(&prtd->lock, flags);
2060 stream_id = ac->stream_id;
2061
2062 stream_index = STREAM_ARRAY_INDEX(stream_id);
2063 if ((stream_index < MAX_NUMBER_OF_STREAMS && stream_index >= 0)) {
2064 spin_unlock_irqrestore(&prtd->lock, flags);
2065 pr_debug("close stream %d", stream_id);
2066 q6asm_stream_cmd(ac, CMD_CLOSE, stream_id);
2067 spin_lock_irqsave(&prtd->lock, flags);
2068 }
2069 spin_unlock_irqrestore(&prtd->lock, flags);
2070
Ajit Pandeyfa018862019-09-04 14:34:00 +05302071 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302072 pdata->cstream[soc_prtd->dai_link->id] = NULL;
2073 msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
2074 SNDRV_PCM_STREAM_CAPTURE);
2075
2076 q6asm_audio_client_buf_free_contiguous(dir, ac);
2077
2078 q6asm_audio_client_free(ac);
2079
2080 kfree(prtd);
2081 runtime->private_data = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05302082 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302083
2084 return 0;
2085}
2086
2087static int msm_compr_free(struct snd_compr_stream *cstream)
2088{
2089 int ret = 0;
2090
2091 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2092 ret = msm_compr_playback_free(cstream);
2093 else if (cstream->direction == SND_COMPRESS_CAPTURE)
2094 ret = msm_compr_capture_free(cstream);
2095 return ret;
2096}
2097
2098static bool msm_compr_validate_codec_compr(__u32 codec_id)
2099{
2100 int32_t i;
2101
2102 for (i = 0; i < ARRAY_SIZE(compr_codecs); i++) {
2103 if (compr_codecs[i] == codec_id)
2104 return true;
2105 }
2106 return false;
2107}
2108
2109/* compress stream operations */
2110static int msm_compr_set_params(struct snd_compr_stream *cstream,
2111 struct snd_compr_params *params)
2112{
2113 struct snd_compr_runtime *runtime = cstream->runtime;
2114 struct msm_compr_audio *prtd = runtime->private_data;
2115 int ret = 0, frame_sz = 0;
2116 int i, num_rates;
2117 bool is_format_gapless = false;
2118
2119 pr_debug("%s\n", __func__);
2120
2121 num_rates = sizeof(supported_sample_rates)/sizeof(unsigned int);
2122 for (i = 0; i < num_rates; i++)
2123 if (params->codec.sample_rate == supported_sample_rates[i])
2124 break;
2125 if (i == num_rates)
2126 return -EINVAL;
2127
2128 memcpy(&prtd->codec_param, params, sizeof(struct snd_compr_params));
2129 /* ToDo: remove duplicates */
2130 prtd->num_channels = prtd->codec_param.codec.ch_in;
2131 prtd->sample_rate = prtd->codec_param.codec.sample_rate;
2132 pr_debug("%s: sample_rate %d\n", __func__, prtd->sample_rate);
2133
2134 if ((prtd->codec_param.codec.compr_passthr >= LEGACY_PCM &&
2135 prtd->codec_param.
2136 codec.compr_passthr <= COMPRESSED_PASSTHROUGH_DSD) ||
2137 (prtd->codec_param.
2138 codec.compr_passthr == COMPRESSED_PASSTHROUGH_IEC61937))
2139 prtd->compr_passthr = prtd->codec_param.codec.compr_passthr;
2140 else
2141 prtd->compr_passthr = LEGACY_PCM;
2142 pr_debug("%s: compr_passthr = %d", __func__, prtd->compr_passthr);
2143 if (prtd->compr_passthr != LEGACY_PCM) {
2144 pr_debug("%s: Reset gapless mode playback for compr_type[%d]\n",
2145 __func__, prtd->compr_passthr);
2146 prtd->gapless_state.use_dsp_gapless_mode = 0;
2147 if (!msm_compr_validate_codec_compr(params->codec.id)) {
2148 pr_err("%s codec not supported in passthrough,id =%d\n",
2149 __func__, params->codec.id);
2150 return -EINVAL;
2151 }
2152 }
2153
Deeraj Soman9d125872019-02-05 16:19:56 +05302154 if (params->codec.flags & COMPRESSED_PERF_MODE_FLAG) {
2155 pr_debug("%s: setting perf mode = %d", __func__, LOW_LATENCY_PCM_MODE);
2156 prtd->audio_client->perf_mode = LOW_LATENCY_PCM_MODE;
2157 }
2158
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302159 switch (params->codec.id) {
2160 case SND_AUDIOCODEC_PCM: {
2161 pr_debug("SND_AUDIOCODEC_PCM\n");
2162 prtd->codec = FORMAT_LINEAR_PCM;
2163 is_format_gapless = true;
2164 break;
2165 }
2166
2167 case SND_AUDIOCODEC_MP3: {
2168 pr_debug("SND_AUDIOCODEC_MP3\n");
2169 prtd->codec = FORMAT_MP3;
2170 frame_sz = MP3_OUTPUT_FRAME_SZ;
2171 is_format_gapless = true;
2172 break;
2173 }
2174
2175 case SND_AUDIOCODEC_AAC: {
2176 pr_debug("SND_AUDIOCODEC_AAC\n");
2177 prtd->codec = FORMAT_MPEG4_AAC;
2178 frame_sz = AAC_OUTPUT_FRAME_SZ;
2179 is_format_gapless = true;
2180 break;
2181 }
2182
2183 case SND_AUDIOCODEC_AC3: {
2184 pr_debug("SND_AUDIOCODEC_AC3\n");
2185 prtd->codec = FORMAT_AC3;
2186 frame_sz = AC3_OUTPUT_FRAME_SZ;
2187 is_format_gapless = true;
2188 break;
2189 }
2190
2191 case SND_AUDIOCODEC_EAC3: {
2192 pr_debug("SND_AUDIOCODEC_EAC3\n");
2193 prtd->codec = FORMAT_EAC3;
2194 frame_sz = EAC3_OUTPUT_FRAME_SZ;
2195 is_format_gapless = true;
2196 break;
2197 }
2198
2199 case SND_AUDIOCODEC_MP2: {
2200 pr_debug("SND_AUDIOCODEC_MP2\n");
2201 prtd->codec = FORMAT_MP2;
2202 break;
2203 }
2204
2205 case SND_AUDIOCODEC_WMA: {
2206 pr_debug("SND_AUDIOCODEC_WMA\n");
2207 prtd->codec = FORMAT_WMA_V9;
2208 break;
2209 }
2210
2211 case SND_AUDIOCODEC_WMA_PRO: {
2212 pr_debug("SND_AUDIOCODEC_WMA_PRO\n");
2213 prtd->codec = FORMAT_WMA_V10PRO;
2214 break;
2215 }
2216
2217 case SND_AUDIOCODEC_FLAC: {
2218 pr_debug("%s: SND_AUDIOCODEC_FLAC\n", __func__);
2219 prtd->codec = FORMAT_FLAC;
2220 /*
2221 * DSP bufferring is based on blk size,
2222 * consider mininum buffering to rule out any false wait
2223 */
2224 frame_sz =
2225 prtd->codec_param.codec.options.flac_dec.min_blk_size;
2226 is_format_gapless = true;
2227 break;
2228 }
2229
2230 case SND_AUDIOCODEC_VORBIS: {
2231 pr_debug("%s: SND_AUDIOCODEC_VORBIS\n", __func__);
2232 prtd->codec = FORMAT_VORBIS;
2233 break;
2234 }
2235
2236 case SND_AUDIOCODEC_ALAC: {
2237 pr_debug("%s: SND_AUDIOCODEC_ALAC\n", __func__);
2238 prtd->codec = FORMAT_ALAC;
2239 break;
2240 }
2241
2242 case SND_AUDIOCODEC_APE: {
2243 pr_debug("%s: SND_AUDIOCODEC_APE\n", __func__);
2244 prtd->codec = FORMAT_APE;
2245 break;
2246 }
2247
2248 case SND_AUDIOCODEC_DTS: {
2249 pr_debug("%s: SND_AUDIOCODEC_DTS\n", __func__);
2250 prtd->codec = FORMAT_DTS;
2251 break;
2252 }
2253
2254 case SND_AUDIOCODEC_DSD: {
2255 pr_debug("%s: SND_AUDIOCODEC_DSD\n", __func__);
2256 prtd->codec = FORMAT_DSD;
2257 break;
2258 }
2259
2260 case SND_AUDIOCODEC_TRUEHD: {
2261 pr_debug("%s: SND_AUDIOCODEC_TRUEHD\n", __func__);
2262 prtd->codec = FORMAT_TRUEHD;
2263 break;
2264 }
2265
2266 case SND_AUDIOCODEC_IEC61937: {
2267 pr_debug("%s: SND_AUDIOCODEC_IEC61937\n", __func__);
2268 prtd->codec = FORMAT_IEC61937;
2269 break;
2270 }
2271
2272 case SND_AUDIOCODEC_APTX: {
2273 pr_debug("%s: SND_AUDIOCODEC_APTX\n", __func__);
2274 prtd->codec = FORMAT_APTX;
2275 break;
2276 }
2277
Vikram Pandurangac712c172017-11-17 17:36:49 -08002278 case SND_AUDIOCODEC_BESPOKE: {
2279 pr_debug("%s: SND_AUDIOCODEC_BESPOKE\n", __func__);
2280 prtd->codec = FORMAT_BESPOKE;
2281 break;
2282 }
2283
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +05302284 case SND_AUDIOCODEC_AMR: {
2285 pr_debug("%s:SND_AUDIOCODEC_AMR\n", __func__);
2286 prtd->codec = FORMAT_AMRNB;
2287 break;
2288 }
2289
2290 case SND_AUDIOCODEC_AMRWB: {
2291 pr_debug("%s:SND_AUDIOCODEC_AMRWB\n", __func__);
2292 prtd->codec = FORMAT_AMRWB;
2293 break;
2294 }
2295
2296 case SND_AUDIOCODEC_AMRWBPLUS: {
2297 pr_debug("%s:SND_AUDIOCODEC_AMRWBPLUS\n", __func__);
2298 prtd->codec = FORMAT_AMR_WB_PLUS;
2299 break;
2300 }
2301
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302302 default:
2303 pr_err("codec not supported, id =%d\n", params->codec.id);
2304 return -EINVAL;
2305 }
2306
2307 if (!is_format_gapless)
2308 prtd->gapless_state.use_dsp_gapless_mode = false;
2309
2310 prtd->partial_drain_delay =
2311 msm_compr_get_partial_drain_delay(frame_sz, prtd->sample_rate);
2312
2313 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2314 ret = msm_compr_configure_dsp_for_playback(cstream);
2315 else if (cstream->direction == SND_COMPRESS_CAPTURE)
2316 ret = msm_compr_configure_dsp_for_capture(cstream);
2317
2318 return ret;
2319}
2320
2321static int msm_compr_drain_buffer(struct msm_compr_audio *prtd,
2322 unsigned long *flags)
2323{
2324 int rc = 0;
2325
2326 atomic_set(&prtd->drain, 1);
2327 prtd->drain_ready = 0;
2328 spin_unlock_irqrestore(&prtd->lock, *flags);
2329 pr_debug("%s: wait for buffer to be drained\n", __func__);
2330 rc = wait_event_interruptible(prtd->drain_wait,
2331 prtd->drain_ready ||
2332 prtd->cmd_interrupt ||
2333 atomic_read(&prtd->xrun) ||
2334 atomic_read(&prtd->error));
2335 pr_debug("%s: out of buffer drain wait with ret %d\n", __func__, rc);
2336 spin_lock_irqsave(&prtd->lock, *flags);
2337 if (prtd->cmd_interrupt) {
2338 pr_debug("%s: buffer drain interrupted by flush)\n", __func__);
2339 rc = -EINTR;
2340 prtd->cmd_interrupt = 0;
2341 }
2342 if (atomic_read(&prtd->error)) {
2343 pr_err("%s: Got RESET EVENTS notification, return\n",
2344 __func__);
2345 rc = -ENETRESET;
2346 }
2347 return rc;
2348}
2349
2350static int msm_compr_wait_for_stream_avail(struct msm_compr_audio *prtd,
2351 unsigned long *flags)
2352{
2353 int rc = 0;
2354
2355 pr_debug("next session is already in opened state\n");
2356 prtd->next_stream = 1;
2357 prtd->cmd_interrupt = 0;
2358 spin_unlock_irqrestore(&prtd->lock, *flags);
2359 /*
2360 * Wait for stream to be available, or the wait to be interrupted by
2361 * commands like flush or till a timeout of one second.
2362 */
2363 rc = wait_event_timeout(prtd->wait_for_stream_avail,
2364 prtd->stream_available || prtd->cmd_interrupt, 1 * HZ);
2365 pr_err("%s:prtd->stream_available %d, prtd->cmd_interrupt %d rc %d\n",
2366 __func__, prtd->stream_available, prtd->cmd_interrupt, rc);
2367
2368 spin_lock_irqsave(&prtd->lock, *flags);
2369 if (rc == 0) {
2370 pr_err("%s: wait_for_stream_avail timed out\n",
2371 __func__);
2372 rc = -ETIMEDOUT;
2373 } else if (prtd->cmd_interrupt == 1) {
2374 /*
2375 * This scenario might not happen as we do not allow
2376 * flush in transition state.
2377 */
2378 pr_debug("%s: wait_for_stream_avail interrupted\n", __func__);
2379 prtd->cmd_interrupt = 0;
2380 prtd->stream_available = 0;
2381 rc = -EINTR;
2382 } else {
2383 prtd->stream_available = 0;
2384 rc = 0;
2385 }
2386 pr_debug("%s : rc = %d", __func__, rc);
2387 return rc;
2388}
2389
2390static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
2391{
2392 struct snd_compr_runtime *runtime = cstream->runtime;
2393 struct msm_compr_audio *prtd = runtime->private_data;
2394 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Meng Wangee084a02018-09-04 16:11:58 +08002395 struct snd_soc_component *component = NULL;
2396 struct msm_compr_pdata *pdata = NULL;
2397 uint32_t *volume = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302398 struct audio_client *ac = prtd->audio_client;
2399 unsigned long fe_id = rtd->dai_link->id;
2400 int rc = 0;
2401 int bytes_to_write;
2402 unsigned long flags;
2403 int stream_id;
2404 uint32_t stream_index;
2405 uint16_t bits_per_sample = 16;
2406
Meng Wangee084a02018-09-04 16:11:58 +08002407 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
2408 if (!component) {
2409 pr_err("%s: component is NULL\n", __func__);
2410 return -EINVAL;
2411 }
2412 pdata = snd_soc_component_get_drvdata(component);
2413 if (!pdata) {
2414 pr_err("%s: pdata is NULL\n", __func__);
2415 return -EINVAL;
2416 }
2417 volume = pdata->volume[rtd->dai_link->id];
2418
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302419 spin_lock_irqsave(&prtd->lock, flags);
2420 if (atomic_read(&prtd->error)) {
2421 pr_err("%s Got RESET EVENTS notification, return immediately",
2422 __func__);
2423 spin_unlock_irqrestore(&prtd->lock, flags);
2424 return 0;
2425 }
2426 spin_unlock_irqrestore(&prtd->lock, flags);
2427
2428 switch (cmd) {
2429 case SNDRV_PCM_TRIGGER_START:
2430 pr_debug("%s: SNDRV_PCM_TRIGGER_START\n", __func__);
2431 atomic_set(&prtd->start, 1);
2432
2433 /*
2434 * compr_set_volume and compr_init_pp_params
2435 * are used to configure ASM volume hence not
2436 * needed for compress passthrough playback.
2437 *
2438 * compress passthrough volume is controlled in
2439 * ADM by adm_send_compressed_device_mute()
2440 */
2441 if (prtd->compr_passthr == LEGACY_PCM &&
2442 cstream->direction == SND_COMPRESS_PLAYBACK) {
2443 /* set volume for the stream before RUN */
2444 rc = msm_compr_set_volume(cstream,
2445 volume[0], volume[1]);
2446 if (rc)
2447 pr_err("%s : Set Volume failed : %d\n",
2448 __func__, rc);
2449
2450 rc = msm_compr_init_pp_params(cstream, ac);
2451 if (rc)
2452 pr_err("%s : init PP params failed : %d\n",
2453 __func__, rc);
2454 } else {
2455 msm_compr_read_buffer(prtd);
2456 }
2457 /* issue RUN command for the stream */
2458 q6asm_run_nowait(prtd->audio_client, prtd->run_mode,
2459 prtd->start_delay_msw, prtd->start_delay_lsw);
2460 break;
2461 case SNDRV_PCM_TRIGGER_STOP:
2462 spin_lock_irqsave(&prtd->lock, flags);
2463 pr_debug("%s: SNDRV_PCM_TRIGGER_STOP transition %d\n", __func__,
2464 prtd->gapless_state.gapless_transition);
2465 stream_id = ac->stream_id;
2466 atomic_set(&prtd->start, 0);
2467 if (cstream->direction == SND_COMPRESS_CAPTURE) {
2468 q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
2469 atomic_set(&prtd->xrun, 0);
2470 prtd->received_total = 0;
2471 prtd->bytes_copied = 0;
2472 prtd->bytes_read = 0;
2473 prtd->bytes_read_offset = 0;
2474 prtd->byte_offset = 0;
2475 prtd->app_pointer = 0;
2476 spin_unlock_irqrestore(&prtd->lock, flags);
2477 break;
2478 }
2479 if (prtd->next_stream) {
2480 pr_debug("%s: interrupt next track wait queues\n",
2481 __func__);
2482 prtd->cmd_interrupt = 1;
2483 wake_up(&prtd->wait_for_stream_avail);
2484 prtd->next_stream = 0;
2485 }
2486 if (atomic_read(&prtd->eos)) {
2487 pr_debug("%s: interrupt eos wait queues", __func__);
2488 /*
2489 * Gapless playback does not wait for eos, do not set
2490 * cmd_int and do not wake up eos_wait during gapless
2491 * transition
2492 */
2493 if (!prtd->gapless_state.gapless_transition) {
2494 prtd->cmd_interrupt = 1;
2495 wake_up(&prtd->eos_wait);
2496 }
2497 atomic_set(&prtd->eos, 0);
2498 }
2499 if (atomic_read(&prtd->drain)) {
2500 pr_debug("%s: interrupt drain wait queues", __func__);
2501 prtd->cmd_interrupt = 1;
2502 prtd->drain_ready = 1;
2503 wake_up(&prtd->drain_wait);
2504 atomic_set(&prtd->drain, 0);
2505 }
2506 prtd->last_buffer = 0;
2507 prtd->cmd_ack = 0;
2508 if (!prtd->gapless_state.gapless_transition) {
2509 pr_debug("issue CMD_FLUSH stream_id %d\n", stream_id);
2510 spin_unlock_irqrestore(&prtd->lock, flags);
2511 q6asm_stream_cmd(
2512 prtd->audio_client, CMD_FLUSH, stream_id);
2513 spin_lock_irqsave(&prtd->lock, flags);
2514 } else {
2515 prtd->first_buffer = 0;
2516 }
2517 /* FIXME. only reset if flush was successful */
2518 prtd->byte_offset = 0;
2519 prtd->copied_total = 0;
2520 prtd->app_pointer = 0;
2521 prtd->bytes_received = 0;
2522 prtd->bytes_sent = 0;
2523 prtd->marker_timestamp = 0;
2524
2525 atomic_set(&prtd->xrun, 0);
2526 spin_unlock_irqrestore(&prtd->lock, flags);
2527 break;
2528 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
2529 pr_debug("SNDRV_PCM_TRIGGER_PAUSE_PUSH transition %d\n",
2530 prtd->gapless_state.gapless_transition);
2531 if (!prtd->gapless_state.gapless_transition) {
2532 pr_debug("issue CMD_PAUSE stream_id %d\n",
2533 ac->stream_id);
2534 q6asm_stream_cmd_nowait(ac, CMD_PAUSE, ac->stream_id);
2535 atomic_set(&prtd->start, 0);
2536 }
2537 break;
2538 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
2539 pr_debug("SNDRV_PCM_TRIGGER_PAUSE_RELEASE transition %d\n",
2540 prtd->gapless_state.gapless_transition);
2541 if (!prtd->gapless_state.gapless_transition) {
2542 atomic_set(&prtd->start, 1);
2543 q6asm_run_nowait(prtd->audio_client, prtd->run_mode,
2544 0, 0);
2545 }
2546 break;
2547 case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
2548 pr_debug("%s: SND_COMPR_TRIGGER_PARTIAL_DRAIN\n", __func__);
2549 if (!prtd->gapless_state.use_dsp_gapless_mode) {
2550 pr_debug("%s: set partial drain as drain\n", __func__);
2551 cmd = SND_COMPR_TRIGGER_DRAIN;
2552 }
2553 case SND_COMPR_TRIGGER_DRAIN:
2554 pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__);
2555 /* Make sure all the data is sent to DSP before sending EOS */
2556 spin_lock_irqsave(&prtd->lock, flags);
2557
2558 if (!atomic_read(&prtd->start)) {
2559 pr_err("%s: stream is not in started state\n",
2560 __func__);
2561 rc = -EPERM;
2562 spin_unlock_irqrestore(&prtd->lock, flags);
2563 break;
2564 }
2565 if (prtd->bytes_received > prtd->copied_total) {
2566 pr_debug("%s: wait till all the data is sent to dsp\n",
2567 __func__);
2568 rc = msm_compr_drain_buffer(prtd, &flags);
2569 if (rc || !atomic_read(&prtd->start)) {
2570 if (rc != -ENETRESET)
2571 rc = -EINTR;
2572 spin_unlock_irqrestore(&prtd->lock, flags);
2573 break;
2574 }
2575 /*
2576 * FIXME: Bug.
2577 * Write(32767)
2578 * Start
2579 * Drain <- Indefinite wait
2580 * sol1 : if (prtd->copied_total) then wait?
2581 * sol2 : (prtd->cmd_interrupt || prtd->drain_ready ||
2582 * atomic_read(xrun)
2583 */
2584 bytes_to_write = prtd->bytes_received
2585 - prtd->copied_total;
2586 WARN(bytes_to_write > runtime->fragment_size,
2587 "last write %d cannot be > than fragment_size",
2588 bytes_to_write);
2589
2590 if (bytes_to_write > 0) {
2591 pr_debug("%s: send %d partial bytes at the end",
2592 __func__, bytes_to_write);
2593 atomic_set(&prtd->xrun, 0);
2594 prtd->last_buffer = 1;
2595 msm_compr_send_buffer(prtd);
2596 }
2597 }
2598
2599 if ((cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN) &&
2600 (prtd->gapless_state.set_next_stream_id)) {
2601 /* wait for the last buffer to be returned */
2602
2603 if (prtd->last_buffer) {
2604 pr_debug("%s: last buffer drain\n", __func__);
2605 rc = msm_compr_drain_buffer(prtd, &flags);
2606 if (rc || !atomic_read(&prtd->start)) {
2607 spin_unlock_irqrestore(&prtd->lock,
2608 flags);
2609 break;
2610 }
2611 }
2612 /* send EOS */
2613 prtd->eos_ack = 0;
2614 atomic_set(&prtd->eos, 1);
2615 pr_debug("issue CMD_EOS stream_id %d\n", ac->stream_id);
2616 q6asm_stream_cmd_nowait(ac, CMD_EOS, ac->stream_id);
2617 pr_info("PARTIAL DRAIN, do not wait for EOS ack\n");
2618
2619 /* send a zero length buffer */
2620 atomic_set(&prtd->xrun, 0);
2621 msm_compr_send_buffer(prtd);
2622
2623 /* wait for the zero length buffer to be returned */
2624 pr_debug("%s: zero length buffer drain\n", __func__);
2625 rc = msm_compr_drain_buffer(prtd, &flags);
2626 if (rc || !atomic_read(&prtd->start)) {
2627 spin_unlock_irqrestore(&prtd->lock, flags);
2628 break;
2629 }
2630
2631 /* sleep for additional duration partial drain */
2632 atomic_set(&prtd->drain, 1);
2633 prtd->drain_ready = 0;
2634 pr_debug("%s, additional sleep: %d\n", __func__,
2635 prtd->partial_drain_delay);
2636 spin_unlock_irqrestore(&prtd->lock, flags);
2637 rc = wait_event_timeout(prtd->drain_wait,
2638 prtd->drain_ready || prtd->cmd_interrupt,
2639 msecs_to_jiffies(prtd->partial_drain_delay));
2640 pr_debug("%s: out of additional wait for low sample rate\n",
2641 __func__);
2642 spin_lock_irqsave(&prtd->lock, flags);
2643 if (prtd->cmd_interrupt) {
2644 pr_debug("%s: additional wait interrupted by flush)\n",
2645 __func__);
2646 rc = -EINTR;
2647 prtd->cmd_interrupt = 0;
2648 spin_unlock_irqrestore(&prtd->lock, flags);
2649 break;
2650 }
2651
2652 /* move to next stream and reset vars */
2653 pr_debug("%s: Moving to next stream in gapless\n",
2654 __func__);
2655 ac->stream_id = NEXT_STREAM_ID(ac->stream_id);
2656 prtd->byte_offset = 0;
2657 prtd->app_pointer = 0;
2658 prtd->first_buffer = 1;
2659 prtd->last_buffer = 0;
2660 /*
2661 * Set gapless transition flag only if EOS hasn't been
2662 * acknowledged already.
2663 */
2664 if (atomic_read(&prtd->eos))
2665 prtd->gapless_state.gapless_transition = 1;
2666 prtd->marker_timestamp = 0;
2667
2668 /*
2669 * Don't reset these as these vars map to
2670 * total_bytes_transferred and total_bytes_available
2671 * directly, only total_bytes_transferred will be
2672 * updated in the next avail() ioctl
2673 * prtd->copied_total = 0;
2674 * prtd->bytes_received = 0;
2675 */
2676 atomic_set(&prtd->drain, 0);
2677 atomic_set(&prtd->xrun, 1);
2678 pr_debug("%s: issue CMD_RUN", __func__);
2679 q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
2680 spin_unlock_irqrestore(&prtd->lock, flags);
2681 break;
2682 }
2683 /*
2684 * moving to next stream failed, so reset the gapless state
2685 * set next stream id for the same session so that the same
2686 * stream can be used for gapless playback
2687 */
2688 prtd->gapless_state.set_next_stream_id = false;
2689 prtd->gapless_state.gapless_transition = 0;
2690 pr_debug("%s:CMD_EOS stream_id %d\n", __func__, ac->stream_id);
2691
2692 prtd->eos_ack = 0;
2693 atomic_set(&prtd->eos, 1);
2694 q6asm_stream_cmd_nowait(ac, CMD_EOS, ac->stream_id);
2695
2696 spin_unlock_irqrestore(&prtd->lock, flags);
2697
2698
2699 /* Wait indefinitely for DRAIN. Flush can also signal this*/
2700 rc = wait_event_interruptible(prtd->eos_wait,
2701 (prtd->eos_ack ||
2702 prtd->cmd_interrupt ||
2703 atomic_read(&prtd->error)));
2704
2705 if (rc < 0)
2706 pr_err("%s: EOS wait failed\n", __func__);
2707
2708 pr_debug("%s: SNDRV_COMPRESS_DRAIN out of wait for EOS\n",
2709 __func__);
2710
2711 if (prtd->cmd_interrupt)
2712 rc = -EINTR;
2713
2714 if (atomic_read(&prtd->error)) {
2715 pr_err("%s: Got RESET EVENTS notification, return\n",
2716 __func__);
2717 rc = -ENETRESET;
2718 }
2719
2720 /*FIXME : what if a flush comes while PC is here */
2721 if (rc == 0) {
2722 /*
2723 * Failed to open second stream in DSP for gapless
2724 * so prepare the current stream in session
2725 * for gapless playback
2726 */
2727 spin_lock_irqsave(&prtd->lock, flags);
2728 pr_debug("%s:issue CMD_PAUSE stream_id %d",
2729 __func__, ac->stream_id);
2730 q6asm_stream_cmd_nowait(ac, CMD_PAUSE, ac->stream_id);
2731 prtd->cmd_ack = 0;
2732 spin_unlock_irqrestore(&prtd->lock, flags);
2733
2734 /*
2735 * Cache this time as last known time
2736 */
2737 if (pdata->use_legacy_api)
2738 q6asm_get_session_time_legacy(
2739 prtd->audio_client,
2740 &prtd->marker_timestamp);
2741 else
2742 q6asm_get_session_time(prtd->audio_client,
2743 &prtd->marker_timestamp);
2744
2745 spin_lock_irqsave(&prtd->lock, flags);
2746 /*
2747 * Don't reset these as these vars map to
2748 * total_bytes_transferred and total_bytes_available.
2749 * Just total_bytes_transferred will be updated
2750 * in the next avail() ioctl.
2751 * prtd->copied_total = 0;
2752 * prtd->bytes_received = 0;
2753 * do not reset prtd->bytes_sent as well as the same
2754 * session is used for gapless playback
2755 */
2756 prtd->byte_offset = 0;
2757
2758 prtd->app_pointer = 0;
2759 prtd->first_buffer = 1;
2760 prtd->last_buffer = 0;
2761 atomic_set(&prtd->drain, 0);
2762 atomic_set(&prtd->xrun, 1);
2763 spin_unlock_irqrestore(&prtd->lock, flags);
2764
2765 pr_debug("%s:issue CMD_FLUSH ac->stream_id %d",
2766 __func__, ac->stream_id);
2767 q6asm_stream_cmd(ac, CMD_FLUSH, ac->stream_id);
2768
2769 q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
2770 }
2771 prtd->cmd_interrupt = 0;
2772 break;
2773 case SND_COMPR_TRIGGER_NEXT_TRACK:
2774 if (!prtd->gapless_state.use_dsp_gapless_mode) {
2775 pr_debug("%s: ignore trigger next track\n", __func__);
2776 rc = 0;
2777 break;
2778 }
2779 pr_debug("%s: SND_COMPR_TRIGGER_NEXT_TRACK\n", __func__);
2780 spin_lock_irqsave(&prtd->lock, flags);
2781 rc = 0;
2782 /* next stream in gapless */
2783 stream_id = NEXT_STREAM_ID(ac->stream_id);
2784 /*
2785 * Wait if stream 1 has not completed before honoring next
2786 * track for stream 3. Scenario happens if second clip is
2787 * small and fills in one buffer so next track will be
2788 * called immediately.
2789 */
2790 stream_index = STREAM_ARRAY_INDEX(stream_id);
2791 if (stream_index >= MAX_NUMBER_OF_STREAMS ||
2792 stream_index < 0) {
2793 pr_err("%s: Invalid stream index: %d", __func__,
2794 stream_index);
2795 spin_unlock_irqrestore(&prtd->lock, flags);
2796 rc = -EINVAL;
2797 break;
2798 }
2799
2800 if (prtd->gapless_state.stream_opened[stream_index]) {
2801 if (prtd->gapless_state.gapless_transition) {
2802 rc = msm_compr_wait_for_stream_avail(prtd,
2803 &flags);
2804 } else {
2805 /*
2806 * If session is already opened break out if
2807 * the state is not gapless transition. This
2808 * is when seek happens after the last buffer
2809 * is sent to the driver. Next track would be
2810 * called again after last buffer is sent.
2811 */
2812 pr_debug("next session is in opened state\n");
2813 spin_unlock_irqrestore(&prtd->lock, flags);
2814 break;
2815 }
2816 }
2817 spin_unlock_irqrestore(&prtd->lock, flags);
2818 if (rc < 0) {
2819 /*
2820 * if return type EINTR then reset to zero. Tiny
2821 * compress treats EINTR as error and prevents PARTIAL
2822 * DRAIN. EINTR is not an error. wait for stream avail
2823 * is interrupted by some other command like FLUSH.
2824 */
2825 if (rc == -EINTR) {
2826 pr_debug("%s: EINTR reset rc to 0\n", __func__);
2827 rc = 0;
2828 }
2829 break;
2830 }
2831
2832 if (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_LE)
2833 bits_per_sample = 24;
2834 else if (prtd->codec_param.codec.format ==
2835 SNDRV_PCM_FORMAT_S32_LE)
2836 bits_per_sample = 32;
2837
2838 pr_debug("%s: open_write stream_id %d bits_per_sample %d",
2839 __func__, stream_id, bits_per_sample);
Nidhisha Dhananjayand84669e2019-02-20 11:00:28 +05302840
2841 if (q6core_get_avcs_api_version_per_service(
2842 APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
2843 ADSP_ASM_API_VERSION_V2)
2844 rc = q6asm_stream_open_write_v5(prtd->audio_client,
2845 prtd->codec, bits_per_sample,
2846 stream_id,
2847 prtd->gapless_state.use_dsp_gapless_mode);
2848 else
2849 rc = q6asm_stream_open_write_v4(prtd->audio_client,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302850 prtd->codec, bits_per_sample,
2851 stream_id,
2852 prtd->gapless_state.use_dsp_gapless_mode);
2853 if (rc < 0) {
Nidhisha Dhananjayand84669e2019-02-20 11:00:28 +05302854 pr_err("%s: Session out open failed for gapless [%d]\n",
2855 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302856 break;
2857 }
2858
2859 spin_lock_irqsave(&prtd->lock, flags);
2860 prtd->gapless_state.stream_opened[stream_index] = 1;
2861 prtd->gapless_state.set_next_stream_id = true;
2862 spin_unlock_irqrestore(&prtd->lock, flags);
2863
2864 rc = msm_compr_send_media_format_block(cstream,
2865 stream_id, false);
2866 if (rc < 0) {
2867 pr_err("%s, failed to send media format block\n",
2868 __func__);
2869 break;
2870 }
2871 msm_compr_send_dec_params(cstream, pdata->dec_params[fe_id],
2872 stream_id);
2873 break;
2874 }
2875
2876 return rc;
2877}
2878
2879static int msm_compr_pointer(struct snd_compr_stream *cstream,
2880 struct snd_compr_tstamp *arg)
2881{
2882 struct snd_compr_runtime *runtime = cstream->runtime;
2883 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
2884 struct msm_compr_audio *prtd = runtime->private_data;
Meng Wangee084a02018-09-04 16:11:58 +08002885 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302886 struct msm_compr_pdata *pdata = NULL;
2887 struct snd_compr_tstamp tstamp;
2888 uint64_t timestamp = 0;
2889 int rc = 0, first_buffer;
2890 unsigned long flags;
2891 uint32_t gapless_transition;
2892
Meng Wangee084a02018-09-04 16:11:58 +08002893 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
2894 if (!component) {
2895 pr_err("%s: component is NULL\n", __func__);
2896 return -EINVAL;
2897 }
2898 pdata = snd_soc_component_get_drvdata(component);
2899 if (!pdata) {
2900 pr_err("%s: pdata is NULL\n", __func__);
2901 return -EINVAL;
2902 }
2903
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302904 pr_debug("%s\n", __func__);
2905 memset(&tstamp, 0x0, sizeof(struct snd_compr_tstamp));
2906
2907 spin_lock_irqsave(&prtd->lock, flags);
2908 tstamp.sampling_rate = prtd->sample_rate;
2909 tstamp.byte_offset = prtd->byte_offset;
2910 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2911 tstamp.copied_total = prtd->copied_total;
2912 else if (cstream->direction == SND_COMPRESS_CAPTURE)
2913 tstamp.copied_total = prtd->received_total;
2914 first_buffer = prtd->first_buffer;
2915 if (atomic_read(&prtd->error)) {
Vatsal Bucha0527c562017-10-04 20:38:49 +05302916 pr_err_ratelimited("%s Got RESET EVENTS notification, return error\n",
2917 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302918 if (cstream->direction == SND_COMPRESS_PLAYBACK)
2919 runtime->total_bytes_transferred = tstamp.copied_total;
2920 else
2921 runtime->total_bytes_available = tstamp.copied_total;
2922 tstamp.pcm_io_frames = 0;
2923 memcpy(arg, &tstamp, sizeof(struct snd_compr_tstamp));
2924 spin_unlock_irqrestore(&prtd->lock, flags);
2925 return -ENETRESET;
2926 }
2927 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
2928
2929 gapless_transition = prtd->gapless_state.gapless_transition;
2930 spin_unlock_irqrestore(&prtd->lock, flags);
2931 if (gapless_transition)
2932 pr_debug("%s session time in gapless transition",
2933 __func__);
2934 /*
2935 *- Do not query if no buffer has been given.
2936 *- Do not query on a gapless transition.
2937 * Playback for the 2nd stream can start (thus returning time
2938 * starting from 0) before the driver knows about EOS of first
2939 * stream.
2940 */
2941 if (!first_buffer || gapless_transition) {
2942
2943 if (pdata->use_legacy_api)
2944 rc = q6asm_get_session_time_legacy(
2945 prtd->audio_client, &prtd->marker_timestamp);
2946 else
2947 rc = q6asm_get_session_time(
2948 prtd->audio_client, &prtd->marker_timestamp);
2949 if (rc < 0) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302950 if (atomic_read(&prtd->error))
2951 return -ENETRESET;
2952 else
Xiaoyu Yef74e89b2018-01-08 18:09:29 -08002953 return rc;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302954 }
2955 }
2956 } else {
2957 spin_unlock_irqrestore(&prtd->lock, flags);
2958 }
2959 timestamp = prtd->marker_timestamp;
2960
2961 /* DSP returns timestamp in usec */
2962 pr_debug("%s: timestamp = %lld usec\n", __func__, timestamp);
2963 timestamp *= prtd->sample_rate;
2964 tstamp.pcm_io_frames = (snd_pcm_uframes_t)div64_u64(timestamp, 1000000);
2965 memcpy(arg, &tstamp, sizeof(struct snd_compr_tstamp));
2966
2967 return 0;
2968}
2969
2970static int msm_compr_ack(struct snd_compr_stream *cstream,
2971 size_t count)
2972{
2973 struct snd_compr_runtime *runtime = cstream->runtime;
2974 struct msm_compr_audio *prtd = runtime->private_data;
2975 void *src, *dstn;
2976 size_t copy;
2977 unsigned long flags;
2978
2979 WARN(1, "This path is untested");
2980 return -EINVAL;
2981
2982 pr_debug("%s: count = %zd\n", __func__, count);
2983 if (!prtd->buffer) {
2984 pr_err("%s: Buffer is not allocated yet ??\n", __func__);
2985 return -EINVAL;
2986 }
2987 src = runtime->buffer + prtd->app_pointer;
2988 dstn = prtd->buffer + prtd->app_pointer;
2989 if (count < prtd->buffer_size - prtd->app_pointer) {
2990 memcpy(dstn, src, count);
2991 prtd->app_pointer += count;
2992 } else {
2993 copy = prtd->buffer_size - prtd->app_pointer;
2994 memcpy(dstn, src, copy);
2995 memcpy(prtd->buffer, runtime->buffer, count - copy);
2996 prtd->app_pointer = count - copy;
2997 }
2998
2999 /*
3000 * If the stream is started and all the bytes received were
3001 * copied to DSP, the newly received bytes should be
3002 * sent right away
3003 */
3004 spin_lock_irqsave(&prtd->lock, flags);
3005
3006 if (atomic_read(&prtd->start) &&
3007 prtd->bytes_received == prtd->copied_total) {
3008 prtd->bytes_received += count;
3009 msm_compr_send_buffer(prtd);
3010 } else
3011 prtd->bytes_received += count;
3012
3013 spin_unlock_irqrestore(&prtd->lock, flags);
3014
3015 return 0;
3016}
3017
3018static int msm_compr_playback_copy(struct snd_compr_stream *cstream,
3019 char __user *buf, size_t count)
3020{
3021 struct snd_compr_runtime *runtime = cstream->runtime;
3022 struct msm_compr_audio *prtd = runtime->private_data;
3023 void *dstn;
3024 size_t copy;
3025 uint64_t bytes_available = 0;
3026 unsigned long flags;
3027
3028 pr_debug("%s: count = %zd\n", __func__, count);
3029 if (!prtd->buffer) {
3030 pr_err("%s: Buffer is not allocated yet ??", __func__);
3031 return 0;
3032 }
3033
3034 spin_lock_irqsave(&prtd->lock, flags);
3035 if (atomic_read(&prtd->error)) {
3036 pr_err("%s Got RESET EVENTS notification", __func__);
3037 spin_unlock_irqrestore(&prtd->lock, flags);
3038 return -ENETRESET;
3039 }
3040 spin_unlock_irqrestore(&prtd->lock, flags);
3041
3042 dstn = prtd->buffer + prtd->app_pointer;
3043 if (count < prtd->buffer_size - prtd->app_pointer) {
3044 if (copy_from_user(dstn, buf, count))
3045 return -EFAULT;
3046 prtd->app_pointer += count;
3047 } else {
3048 copy = prtd->buffer_size - prtd->app_pointer;
3049 if (copy_from_user(dstn, buf, copy))
3050 return -EFAULT;
3051 if (copy_from_user(prtd->buffer, buf + copy, count - copy))
3052 return -EFAULT;
3053 prtd->app_pointer = count - copy;
3054 }
3055
3056 /*
3057 * If stream is started and there has been an xrun,
3058 * since the available bytes fits fragment_size, copy the data
3059 * right away.
3060 */
3061 spin_lock_irqsave(&prtd->lock, flags);
3062 prtd->bytes_received += count;
3063 if (atomic_read(&prtd->start)) {
3064 if (atomic_read(&prtd->xrun)) {
3065 pr_debug("%s: in xrun, count = %zd\n", __func__, count);
3066 bytes_available = prtd->bytes_received -
3067 prtd->copied_total;
3068 if (bytes_available >= runtime->fragment_size) {
3069 pr_debug("%s: handle xrun, bytes_to_write = %llu\n",
3070 __func__, bytes_available);
3071 atomic_set(&prtd->xrun, 0);
3072 msm_compr_send_buffer(prtd);
3073 } /* else not sufficient data */
3074 } /* writes will continue on the next write_done */
3075 }
3076
3077 spin_unlock_irqrestore(&prtd->lock, flags);
3078
3079 return count;
3080}
3081
3082static int msm_compr_capture_copy(struct snd_compr_stream *cstream,
3083 char __user *buf, size_t count)
3084{
3085 struct snd_compr_runtime *runtime = cstream->runtime;
3086 struct msm_compr_audio *prtd = runtime->private_data;
3087 void *source;
3088 unsigned long flags;
3089
3090 pr_debug("%s: count = %zd\n", __func__, count);
3091 if (!prtd->buffer) {
3092 pr_err("%s: Buffer is not allocated yet ??", __func__);
3093 return 0;
3094 }
3095
3096 spin_lock_irqsave(&prtd->lock, flags);
3097 if (atomic_read(&prtd->error)) {
3098 pr_err("%s Got RESET EVENTS notification", __func__);
3099 spin_unlock_irqrestore(&prtd->lock, flags);
3100 return -ENETRESET;
3101 }
3102
3103 source = prtd->buffer + prtd->app_pointer;
3104 /* check if we have requested amount of data to copy to user*/
3105 if (count <= prtd->received_total - prtd->bytes_copied) {
3106 spin_unlock_irqrestore(&prtd->lock, flags);
3107 if (copy_to_user(buf, source, count)) {
3108 pr_err("copy_to_user failed");
3109 return -EFAULT;
3110 }
3111 spin_lock_irqsave(&prtd->lock, flags);
3112 prtd->app_pointer += count;
3113 if (prtd->app_pointer >= prtd->buffer_size)
3114 prtd->app_pointer -= prtd->buffer_size;
3115 prtd->bytes_copied += count;
3116 }
3117 msm_compr_read_buffer(prtd);
3118
3119 spin_unlock_irqrestore(&prtd->lock, flags);
3120 return count;
3121}
3122
3123static int msm_compr_copy(struct snd_compr_stream *cstream,
3124 char __user *buf, size_t count)
3125{
3126 int ret = 0;
3127
3128 pr_debug(" In %s\n", __func__);
3129 if (cstream->direction == SND_COMPRESS_PLAYBACK)
3130 ret = msm_compr_playback_copy(cstream, buf, count);
3131 else if (cstream->direction == SND_COMPRESS_CAPTURE)
3132 ret = msm_compr_capture_copy(cstream, buf, count);
3133 return ret;
3134}
3135
3136static int msm_compr_get_caps(struct snd_compr_stream *cstream,
3137 struct snd_compr_caps *arg)
3138{
3139 struct snd_compr_runtime *runtime = cstream->runtime;
3140 struct msm_compr_audio *prtd = runtime->private_data;
3141 int ret = 0;
3142
3143 pr_debug("%s\n", __func__);
3144 if ((arg != NULL) && (prtd != NULL)) {
3145 memcpy(arg, &prtd->compr_cap, sizeof(struct snd_compr_caps));
3146 } else {
3147 ret = -EINVAL;
3148 pr_err("%s: arg (0x%pK), prtd (0x%pK)\n", __func__, arg, prtd);
3149 }
3150
3151 return ret;
3152}
3153
3154static int msm_compr_get_codec_caps(struct snd_compr_stream *cstream,
3155 struct snd_compr_codec_caps *codec)
3156{
3157 pr_debug("%s\n", __func__);
3158
3159 switch (codec->codec) {
3160 case SND_AUDIOCODEC_MP3:
3161 codec->num_descriptors = 2;
3162 codec->descriptor[0].max_ch = 2;
3163 memcpy(codec->descriptor[0].sample_rates,
3164 supported_sample_rates,
3165 sizeof(supported_sample_rates));
3166 codec->descriptor[0].num_sample_rates =
3167 sizeof(supported_sample_rates)/sizeof(unsigned int);
3168 codec->descriptor[0].bit_rate[0] = 320; /* 320kbps */
3169 codec->descriptor[0].bit_rate[1] = 128;
3170 codec->descriptor[0].num_bitrates = 2;
3171 codec->descriptor[0].profiles = 0;
3172 codec->descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO;
3173 codec->descriptor[0].formats = 0;
3174 break;
3175 case SND_AUDIOCODEC_AAC:
3176 codec->num_descriptors = 2;
3177 codec->descriptor[1].max_ch = 2;
3178 memcpy(codec->descriptor[1].sample_rates,
3179 supported_sample_rates,
3180 sizeof(supported_sample_rates));
3181 codec->descriptor[1].num_sample_rates =
3182 sizeof(supported_sample_rates)/sizeof(unsigned int);
3183 codec->descriptor[1].bit_rate[0] = 320; /* 320kbps */
3184 codec->descriptor[1].bit_rate[1] = 128;
3185 codec->descriptor[1].num_bitrates = 2;
3186 codec->descriptor[1].profiles = 0;
3187 codec->descriptor[1].modes = 0;
3188 codec->descriptor[1].formats =
3189 (SND_AUDIOSTREAMFORMAT_MP4ADTS |
3190 SND_AUDIOSTREAMFORMAT_RAW);
3191 break;
3192 case SND_AUDIOCODEC_AC3:
3193 case SND_AUDIOCODEC_EAC3:
3194 case SND_AUDIOCODEC_FLAC:
3195 case SND_AUDIOCODEC_VORBIS:
3196 case SND_AUDIOCODEC_ALAC:
3197 case SND_AUDIOCODEC_APE:
3198 case SND_AUDIOCODEC_DTS:
3199 case SND_AUDIOCODEC_DSD:
3200 case SND_AUDIOCODEC_TRUEHD:
3201 case SND_AUDIOCODEC_IEC61937:
3202 case SND_AUDIOCODEC_APTX:
3203 break;
3204 default:
3205 pr_err("%s: Unsupported audio codec %d\n",
3206 __func__, codec->codec);
3207 return -EINVAL;
3208 }
3209
3210 return 0;
3211}
3212
3213static int msm_compr_set_metadata(struct snd_compr_stream *cstream,
3214 struct snd_compr_metadata *metadata)
3215{
3216 struct msm_compr_audio *prtd;
3217 struct audio_client *ac;
3218 pr_debug("%s\n", __func__);
3219
3220 if (!metadata || !cstream)
3221 return -EINVAL;
3222
3223 prtd = cstream->runtime->private_data;
3224 if (!prtd || !prtd->audio_client) {
3225 pr_err("%s: prtd or audio client is NULL\n", __func__);
3226 return -EINVAL;
3227 }
3228
3229 if (((metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) ||
3230 (metadata->key == SNDRV_COMPRESS_ENCODER_DELAY)) &&
3231 (prtd->compr_passthr != LEGACY_PCM)) {
3232 pr_debug("%s: No trailing silence for compress_type[%d]\n",
3233 __func__, prtd->compr_passthr);
3234 return 0;
3235 }
3236
3237 ac = prtd->audio_client;
3238 if (metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) {
3239 pr_debug("%s, got encoder padding %u",
3240 __func__, metadata->value[0]);
3241 prtd->gapless_state.trailing_samples_drop = metadata->value[0];
3242 } else if (metadata->key == SNDRV_COMPRESS_ENCODER_DELAY) {
3243 pr_debug("%s, got encoder delay %u",
3244 __func__, metadata->value[0]);
3245 prtd->gapless_state.initial_samples_drop = metadata->value[0];
3246 } else if (metadata->key == SNDRV_COMPRESS_RENDER_MODE) {
Surendar Karkafc93c482019-10-31 11:05:59 +05303247 return msm_compr_set_render_mode(prtd, metadata->value[0],
3248 cstream->direction);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303249 } else if (metadata->key == SNDRV_COMPRESS_CLK_REC_MODE) {
3250 return msm_compr_set_clk_rec_mode(ac, metadata->value[0]);
3251 } else if (metadata->key == SNDRV_COMPRESS_RENDER_WINDOW) {
3252 return msm_compr_set_render_window(
3253 ac,
3254 metadata->value[0],
3255 metadata->value[1],
3256 metadata->value[2],
3257 metadata->value[3]);
3258 } else if (metadata->key == SNDRV_COMPRESS_START_DELAY) {
3259 prtd->start_delay_lsw = metadata->value[0];
3260 prtd->start_delay_msw = metadata->value[1];
3261 } else if (metadata->key ==
3262 SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK) {
3263 return msm_compr_enable_adjust_session_clock(ac,
3264 metadata->value[0]);
3265 } else if (metadata->key == SNDRV_COMPRESS_ADJUST_SESSION_CLOCK) {
3266 return msm_compr_adjust_session_clock(ac,
3267 metadata->value[0],
3268 metadata->value[1]);
Surendar Karkafc93c482019-10-31 11:05:59 +05303269 } else if (metadata->key == SNDRV_COMPRESS_IN_TTP_OFFSET) {
3270 return msm_compr_set_ttp_offset(ac, metadata->value[0],
3271 metadata->value[1], cstream->direction);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303272 }
3273
3274 return 0;
3275}
3276
3277static int msm_compr_get_metadata(struct snd_compr_stream *cstream,
3278 struct snd_compr_metadata *metadata)
3279{
3280 struct msm_compr_audio *prtd;
3281 struct audio_client *ac;
3282 int ret = -EINVAL;
Surendar Karka38d66472019-03-29 18:08:07 +05303283 uint64_t ses_time = 0, frames = 0, abs_time = 0;
3284 uint64_t *val = NULL;
3285 int64_t av_offset = 0;
3286 int32_t clock_id = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303287
3288 pr_debug("%s\n", __func__);
3289
3290 if (!metadata || !cstream || !cstream->runtime)
3291 return ret;
3292
Surendar Karka38d66472019-03-29 18:08:07 +05303293 if (metadata->key != SNDRV_COMPRESS_PATH_DELAY &&
3294 metadata->key != SNDRV_COMPRESS_DSP_POSITION) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303295 pr_err("%s, unsupported key %d\n", __func__, metadata->key);
3296 return ret;
3297 }
3298
3299 prtd = cstream->runtime->private_data;
3300 if (!prtd || !prtd->audio_client) {
3301 pr_err("%s: prtd or audio client is NULL\n", __func__);
3302 return ret;
3303 }
3304
Surendar Karka38d66472019-03-29 18:08:07 +05303305 switch (metadata->key) {
3306 case SNDRV_COMPRESS_PATH_DELAY:
3307 ac = prtd->audio_client;
3308 ret = q6asm_get_path_delay(prtd->audio_client);
3309 if (ret) {
3310 pr_err("%s: get_path_delay failed, ret=%d\n",
3311 __func__, ret);
3312 return ret;
3313 }
3314
3315 pr_debug("%s, path delay(in us) %u\n", __func__,
3316 ac->path_delay);
3317 metadata->value[0] = ac->path_delay;
3318 break;
3319 case SNDRV_COMPRESS_DSP_POSITION:
3320 clock_id = metadata->value[0];
3321 pr_debug("%s, clock_id %d\n", __func__, clock_id);
3322 ret = q6asm_get_session_time_v2(prtd->audio_client,
3323 &ses_time, &abs_time);
3324 if (ret) {
3325 pr_err("%s: q6asm_get_session_time_v2 failed, ret=%d\n",
3326 __func__, ret);
3327 return ret;
3328 }
3329 frames = div64_u64((ses_time * prtd->sample_rate), 1000000);
3330
3331 ret = avcs_core_query_timer_offset(&av_offset, clock_id);
3332 if (ret) {
3333 pr_err("%s: avcs query failed, ret=%d\n",
3334 __func__, ret);
3335 return ret;
3336 }
3337
3338 val = (uint64_t *) &metadata->value[1];
3339 val[0] = frames;
3340 val[1] = abs_time + av_offset;
3341 pr_debug("%s, vals frames %lld, time %lld, avoff %lld, abst %lld, sess_time %llu sr %d\n",
3342 __func__, val[0], val[1], av_offset, abs_time,
3343 ses_time, prtd->sample_rate);
3344 break;
3345 default:
3346 pr_err("%s, unsupported key %d\n", __func__, metadata->key);
3347 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303348 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303349 return ret;
3350}
3351
3352
3353static int msm_compr_set_next_track_param(struct snd_compr_stream *cstream,
3354 union snd_codec_options *codec_options)
3355{
3356 struct msm_compr_audio *prtd;
3357 struct audio_client *ac;
3358 int ret = 0;
3359
3360 if (!codec_options || !cstream)
3361 return -EINVAL;
3362
3363 prtd = cstream->runtime->private_data;
3364 if (!prtd || !prtd->audio_client) {
3365 pr_err("%s: prtd or audio client is NULL\n", __func__);
3366 return -EINVAL;
3367 }
3368
3369 ac = prtd->audio_client;
3370
3371 pr_debug("%s: got codec options for codec type %u",
3372 __func__, prtd->codec);
3373 switch (prtd->codec) {
3374 case FORMAT_WMA_V9:
3375 case FORMAT_WMA_V10PRO:
3376 case FORMAT_FLAC:
3377 case FORMAT_VORBIS:
3378 case FORMAT_ALAC:
3379 case FORMAT_APE:
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +05303380 case FORMAT_AMRNB:
3381 case FORMAT_AMRWB:
3382 case FORMAT_AMR_WB_PLUS:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303383 memcpy(&(prtd->gapless_state.codec_options),
3384 codec_options,
3385 sizeof(union snd_codec_options));
3386 ret = msm_compr_send_media_format_block(cstream,
3387 ac->stream_id, true);
3388 if (ret < 0) {
3389 pr_err("%s: failed to send media format block\n",
3390 __func__);
3391 }
3392 break;
3393
3394 default:
3395 pr_debug("%s: Ignore sending CMD Format block\n",
3396 __func__);
3397 break;
3398 }
3399
3400 return ret;
3401}
3402
3403static int msm_compr_volume_put(struct snd_kcontrol *kcontrol,
3404 struct snd_ctl_elem_value *ucontrol)
3405{
3406 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3407 unsigned long fe_id = kcontrol->private_value;
3408 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3409 snd_soc_component_get_drvdata(comp);
3410 struct snd_compr_stream *cstream = NULL;
3411 uint32_t *volume = NULL;
3412
3413 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3414 pr_err("%s Received out of bounds fe_id %lu\n",
3415 __func__, fe_id);
3416 return -EINVAL;
3417 }
3418
3419 cstream = pdata->cstream[fe_id];
3420 volume = pdata->volume[fe_id];
3421
3422 volume[0] = ucontrol->value.integer.value[0];
3423 volume[1] = ucontrol->value.integer.value[1];
3424 pr_debug("%s: fe_id %lu left_vol %d right_vol %d\n",
3425 __func__, fe_id, volume[0], volume[1]);
3426 if (cstream)
3427 msm_compr_set_volume(cstream, volume[0], volume[1]);
3428 return 0;
3429}
3430
3431static int msm_compr_volume_get(struct snd_kcontrol *kcontrol,
3432 struct snd_ctl_elem_value *ucontrol)
3433{
3434 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3435 unsigned long fe_id = kcontrol->private_value;
3436
3437 struct msm_compr_pdata *pdata =
3438 snd_soc_component_get_drvdata(comp);
3439 uint32_t *volume = NULL;
3440
3441 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3442 pr_err("%s Received out of bound fe_id %lu\n", __func__, fe_id);
3443 return -EINVAL;
3444 }
3445
3446 volume = pdata->volume[fe_id];
3447 pr_debug("%s: fe_id %lu\n", __func__, fe_id);
3448 ucontrol->value.integer.value[0] = volume[0];
3449 ucontrol->value.integer.value[1] = volume[1];
3450
3451 return 0;
3452}
3453
3454static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
3455 struct snd_ctl_elem_value *ucontrol)
3456{
3457 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3458 unsigned long fe_id = kcontrol->private_value;
3459 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3460 snd_soc_component_get_drvdata(comp);
3461 struct msm_compr_audio_effects *audio_effects = NULL;
3462 struct snd_compr_stream *cstream = NULL;
3463 struct msm_compr_audio *prtd = NULL;
3464 long *values = &(ucontrol->value.integer.value[0]);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303465 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303466 int effects_module;
3467
3468 pr_debug("%s\n", __func__);
3469 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3470 pr_err("%s Received out of bounds fe_id %lu\n",
3471 __func__, fe_id);
3472 return -EINVAL;
3473 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303474
3475 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303476 cstream = pdata->cstream[fe_id];
3477 audio_effects = pdata->audio_effects[fe_id];
3478 if (!cstream || !audio_effects) {
3479 pr_err("%s: stream or effects inactive\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303480 ret = -EINVAL;
3481 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303482 }
3483 prtd = cstream->runtime->private_data;
3484 if (!prtd) {
3485 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303486 ret = -EINVAL;
3487 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303488 }
3489 if (prtd->compr_passthr != LEGACY_PCM) {
3490 pr_debug("%s: No effects for compr_type[%d]\n",
3491 __func__, prtd->compr_passthr);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303492 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303493 }
3494 pr_debug("%s: Effects supported for compr_type[%d]\n",
3495 __func__, prtd->compr_passthr);
3496
3497 effects_module = *values++;
3498 switch (effects_module) {
3499 case VIRTUALIZER_MODULE:
3500 pr_debug("%s: VIRTUALIZER_MODULE\n", __func__);
3501 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3502 prtd->audio_client->topology))
3503 msm_audio_effects_virtualizer_handler(
3504 prtd->audio_client,
3505 &(audio_effects->virtualizer),
3506 values);
3507 break;
3508 case REVERB_MODULE:
3509 pr_debug("%s: REVERB_MODULE\n", __func__);
3510 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3511 prtd->audio_client->topology))
3512 msm_audio_effects_reverb_handler(prtd->audio_client,
3513 &(audio_effects->reverb),
3514 values);
3515 break;
3516 case BASS_BOOST_MODULE:
3517 pr_debug("%s: BASS_BOOST_MODULE\n", __func__);
3518 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3519 prtd->audio_client->topology))
3520 msm_audio_effects_bass_boost_handler(prtd->audio_client,
3521 &(audio_effects->bass_boost),
3522 values);
3523 break;
3524 case PBE_MODULE:
3525 pr_debug("%s: PBE_MODULE\n", __func__);
3526 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3527 prtd->audio_client->topology))
3528 msm_audio_effects_pbe_handler(prtd->audio_client,
3529 &(audio_effects->pbe),
3530 values);
3531 break;
3532 case EQ_MODULE:
3533 pr_debug("%s: EQ_MODULE\n", __func__);
3534 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3535 prtd->audio_client->topology))
3536 msm_audio_effects_popless_eq_handler(prtd->audio_client,
3537 &(audio_effects->equalizer),
3538 values);
3539 break;
3540 case SOFT_VOLUME_MODULE:
3541 pr_debug("%s: SOFT_VOLUME_MODULE\n", __func__);
3542 break;
3543 case SOFT_VOLUME2_MODULE:
3544 pr_debug("%s: SOFT_VOLUME2_MODULE\n", __func__);
3545 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3546 prtd->audio_client->topology))
3547 msm_audio_effects_volume_handler_v2(prtd->audio_client,
3548 &(audio_effects->volume),
3549 values, SOFT_VOLUME_INSTANCE_2);
3550 break;
3551 default:
3552 pr_err("%s Invalid effects config module\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303553 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303554 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303555done:
3556 mutex_unlock(&pdata->lock);
3557 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303558}
3559
3560static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol,
3561 struct snd_ctl_elem_value *ucontrol)
3562{
3563 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3564 unsigned long fe_id = kcontrol->private_value;
3565 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3566 snd_soc_component_get_drvdata(comp);
3567 struct msm_compr_audio_effects *audio_effects = NULL;
3568 struct snd_compr_stream *cstream = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303569 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303570 struct msm_compr_audio *prtd = NULL;
3571
3572 pr_debug("%s\n", __func__);
3573 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3574 pr_err("%s Received out of bounds fe_id %lu\n",
3575 __func__, fe_id);
3576 return -EINVAL;
3577 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303578
3579 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303580 cstream = pdata->cstream[fe_id];
3581 audio_effects = pdata->audio_effects[fe_id];
3582 if (!cstream || !audio_effects) {
Vignesh Kulothungan2ce67842018-09-25 16:40:29 -07003583 pr_debug("%s: stream or effects inactive\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303584 ret = -EINVAL;
3585 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303586 }
3587 prtd = cstream->runtime->private_data;
3588 if (!prtd) {
3589 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303590 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303591 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303592done:
3593 mutex_unlock(&pdata->lock);
3594 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303595}
3596
3597static int msm_compr_query_audio_effect_put(struct snd_kcontrol *kcontrol,
3598 struct snd_ctl_elem_value *ucontrol)
3599{
3600 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3601 unsigned long fe_id = kcontrol->private_value;
3602 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3603 snd_soc_component_get_drvdata(comp);
3604 struct msm_compr_audio_effects *audio_effects = NULL;
3605 struct snd_compr_stream *cstream = NULL;
3606 struct msm_compr_audio *prtd = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303607 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303608 long *values = &(ucontrol->value.integer.value[0]);
3609
3610 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3611 pr_err("%s Received out of bounds fe_id %lu\n",
3612 __func__, fe_id);
3613 return -EINVAL;
3614 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303615
3616 mutex_lock(&pdata->lock);
3617
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303618 cstream = pdata->cstream[fe_id];
3619 audio_effects = pdata->audio_effects[fe_id];
3620 if (!cstream || !audio_effects) {
3621 pr_err("%s: stream or effects inactive\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303622 ret = -EINVAL;
3623 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303624 }
3625 prtd = cstream->runtime->private_data;
3626 if (!prtd) {
3627 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303628 ret = -EINVAL;
3629 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303630 }
3631 if (prtd->compr_passthr != LEGACY_PCM) {
3632 pr_err("%s: No effects for compr_type[%d]\n",
3633 __func__, prtd->compr_passthr);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303634 ret = -EPERM;
3635 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303636 }
3637 audio_effects->query.mod_id = (u32)*values++;
3638 audio_effects->query.parm_id = (u32)*values++;
3639 audio_effects->query.size = (u32)*values++;
3640 audio_effects->query.offset = (u32)*values++;
3641 audio_effects->query.device = (u32)*values++;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303642
3643done:
3644 mutex_unlock(&pdata->lock);
3645 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303646}
3647
3648static int msm_compr_query_audio_effect_get(struct snd_kcontrol *kcontrol,
3649 struct snd_ctl_elem_value *ucontrol)
3650{
3651 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3652 unsigned long fe_id = kcontrol->private_value;
3653 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3654 snd_soc_component_get_drvdata(comp);
3655 struct msm_compr_audio_effects *audio_effects = NULL;
3656 struct snd_compr_stream *cstream = NULL;
3657 struct msm_compr_audio *prtd = NULL;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303658 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303659 long *values = &(ucontrol->value.integer.value[0]);
3660
3661 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3662 pr_err("%s Received out of bounds fe_id %lu\n",
3663 __func__, fe_id);
3664 return -EINVAL;
3665 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05303666
3667 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303668 cstream = pdata->cstream[fe_id];
3669 audio_effects = pdata->audio_effects[fe_id];
3670 if (!cstream || !audio_effects) {
3671 pr_debug("%s: stream or effects inactive\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303672 ret = -EINVAL;
3673 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303674 }
3675 prtd = cstream->runtime->private_data;
3676 if (!prtd) {
3677 pr_err("%s: cannot set audio effects\n", __func__);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303678 ret = -EINVAL;
3679 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303680 }
3681 values[0] = (long)audio_effects->query.mod_id;
3682 values[1] = (long)audio_effects->query.parm_id;
3683 values[2] = (long)audio_effects->query.size;
3684 values[3] = (long)audio_effects->query.offset;
3685 values[4] = (long)audio_effects->query.device;
Ajit Pandeyfa018862019-09-04 14:34:00 +05303686done:
3687 mutex_unlock(&pdata->lock);
3688 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303689}
3690
3691static int msm_compr_send_dec_params(struct snd_compr_stream *cstream,
3692 struct msm_compr_dec_params *dec_params,
3693 int stream_id)
3694{
3695
3696 int rc = 0;
3697 struct msm_compr_audio *prtd = NULL;
3698 struct snd_dec_ddp *ddp = &dec_params->ddp_params;
3699
3700 if (!cstream || !dec_params) {
3701 pr_err("%s: stream or dec_params inactive\n", __func__);
3702 rc = -EINVAL;
3703 goto end;
3704 }
3705 prtd = cstream->runtime->private_data;
3706 if (!prtd) {
3707 pr_err("%s: cannot set dec_params\n", __func__);
3708 rc = -EINVAL;
3709 goto end;
3710 }
3711 switch (prtd->codec) {
3712 case FORMAT_MP3:
3713 case FORMAT_MPEG4_AAC:
3714 case FORMAT_TRUEHD:
3715 case FORMAT_IEC61937:
3716 case FORMAT_APTX:
3717 pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
3718 prtd->codec);
3719 break;
3720 case FORMAT_AC3:
3721 case FORMAT_EAC3:
3722 if (prtd->compr_passthr != LEGACY_PCM) {
3723 pr_debug("%s: No DDP param for compr_type[%d]\n",
3724 __func__, prtd->compr_passthr);
3725 break;
3726 }
3727 rc = msm_compr_send_ddp_cfg(prtd->audio_client, ddp, stream_id);
3728 if (rc < 0)
3729 pr_err("%s: DDP CMD CFG failed %d\n", __func__, rc);
3730 break;
3731 default:
3732 break;
3733 }
3734end:
3735 return rc;
3736
3737}
3738static int msm_compr_dec_params_put(struct snd_kcontrol *kcontrol,
3739 struct snd_ctl_elem_value *ucontrol)
3740{
3741 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3742 unsigned long fe_id = kcontrol->private_value;
3743 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3744 snd_soc_component_get_drvdata(comp);
3745 struct msm_compr_dec_params *dec_params = NULL;
3746 struct snd_compr_stream *cstream = NULL;
3747 struct msm_compr_audio *prtd = NULL;
3748 long *values = &(ucontrol->value.integer.value[0]);
3749 int rc = 0;
3750
3751 pr_debug("%s\n", __func__);
3752 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3753 pr_err("%s Received out of bounds fe_id %lu\n",
3754 __func__, fe_id);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05303755 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303756 }
3757
3758 cstream = pdata->cstream[fe_id];
3759 dec_params = pdata->dec_params[fe_id];
3760
3761 if (!cstream || !dec_params) {
3762 pr_err("%s: stream or dec_params inactive\n", __func__);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05303763 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303764 }
3765 prtd = cstream->runtime->private_data;
3766 if (!prtd) {
3767 pr_err("%s: cannot set dec_params\n", __func__);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05303768 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303769 }
3770
Ajit Pandeyfa018862019-09-04 14:34:00 +05303771 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303772 switch (prtd->codec) {
3773 case FORMAT_MP3:
3774 case FORMAT_MPEG4_AAC:
3775 case FORMAT_FLAC:
3776 case FORMAT_VORBIS:
3777 case FORMAT_ALAC:
3778 case FORMAT_APE:
3779 case FORMAT_DTS:
3780 case FORMAT_DSD:
3781 case FORMAT_TRUEHD:
3782 case FORMAT_IEC61937:
3783 case FORMAT_APTX:
Asish Bhattacharya7e3391b2019-06-30 19:57:09 +05303784 case FORMAT_AMRNB:
3785 case FORMAT_AMRWB:
3786 case FORMAT_AMR_WB_PLUS:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303787 pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
3788 prtd->codec);
3789 break;
3790 case FORMAT_AC3:
3791 case FORMAT_EAC3: {
3792 struct snd_dec_ddp *ddp = &dec_params->ddp_params;
3793 int cnt;
3794
3795 if (prtd->compr_passthr != LEGACY_PCM) {
3796 pr_debug("%s: No DDP param for compr_type[%d]\n",
3797 __func__, prtd->compr_passthr);
3798 break;
3799 }
3800
3801 ddp->params_length = (*values++);
3802 if (ddp->params_length > DDP_DEC_MAX_NUM_PARAM) {
3803 pr_err("%s: invalid num of params:: %d\n", __func__,
3804 ddp->params_length);
3805 rc = -EINVAL;
3806 goto end;
3807 }
3808 for (cnt = 0; cnt < ddp->params_length; cnt++) {
3809 ddp->params_id[cnt] = *values++;
3810 ddp->params_value[cnt] = *values++;
3811 }
3812 prtd = cstream->runtime->private_data;
3813 if (prtd && prtd->audio_client)
3814 rc = msm_compr_send_dec_params(cstream, dec_params,
3815 prtd->audio_client->stream_id);
3816 break;
3817 }
3818 default:
3819 break;
3820 }
3821end:
3822 pr_debug("%s: ret %d\n", __func__, rc);
Ajit Pandeyfa018862019-09-04 14:34:00 +05303823 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303824 return rc;
3825}
3826
3827static int msm_compr_dec_params_get(struct snd_kcontrol *kcontrol,
3828 struct snd_ctl_elem_value *ucontrol)
3829{
3830 /* dummy function */
3831 return 0;
3832}
3833
3834static int msm_compr_playback_app_type_cfg_put(struct snd_kcontrol *kcontrol,
3835 struct snd_ctl_elem_value *ucontrol)
3836{
3837 u64 fe_id = kcontrol->private_value;
3838 int session_type = SESSION_TYPE_RX;
3839 int be_id = ucontrol->value.integer.value[3];
3840 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
3841 int ret = 0;
3842
3843 cfg_data.app_type = ucontrol->value.integer.value[0];
3844 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
3845 if (ucontrol->value.integer.value[2] != 0)
3846 cfg_data.sample_rate = ucontrol->value.integer.value[2];
3847 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
3848 __func__, fe_id, session_type, be_id,
3849 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3850 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
3851 be_id, &cfg_data);
3852 if (ret < 0)
3853 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
3854 __func__, ret);
3855
3856 return ret;
3857}
3858
3859static int msm_compr_playback_app_type_cfg_get(struct snd_kcontrol *kcontrol,
3860 struct snd_ctl_elem_value *ucontrol)
3861{
3862 u64 fe_id = kcontrol->private_value;
3863 int session_type = SESSION_TYPE_RX;
3864 int be_id = 0;
3865 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
3866 int ret = 0;
3867
3868 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
3869 &be_id, &cfg_data);
3870 if (ret < 0) {
3871 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
3872 __func__, ret);
3873 goto done;
3874 }
3875
3876 ucontrol->value.integer.value[0] = cfg_data.app_type;
3877 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
3878 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
3879 ucontrol->value.integer.value[3] = be_id;
3880 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
3881 __func__, fe_id, session_type, be_id,
3882 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3883done:
3884 return ret;
3885}
3886
3887static int msm_compr_capture_app_type_cfg_put(struct snd_kcontrol *kcontrol,
3888 struct snd_ctl_elem_value *ucontrol)
3889{
3890 u64 fe_id = kcontrol->private_value;
3891 int session_type = SESSION_TYPE_TX;
3892 int be_id = ucontrol->value.integer.value[3];
3893 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
3894 int ret = 0;
3895
3896 cfg_data.app_type = ucontrol->value.integer.value[0];
3897 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
3898 if (ucontrol->value.integer.value[2] != 0)
3899 cfg_data.sample_rate = ucontrol->value.integer.value[2];
3900 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
3901 __func__, fe_id, session_type, be_id,
3902 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3903 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
3904 be_id, &cfg_data);
3905 if (ret < 0)
3906 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
3907 __func__, ret);
3908
3909 return ret;
3910}
3911
3912static int msm_compr_capture_app_type_cfg_get(struct snd_kcontrol *kcontrol,
3913 struct snd_ctl_elem_value *ucontrol)
3914{
3915 u64 fe_id = kcontrol->private_value;
3916 int session_type = SESSION_TYPE_TX;
3917 int be_id = 0;
3918 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
3919 int ret = 0;
3920
3921 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
3922 &be_id, &cfg_data);
3923 if (ret < 0) {
3924 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
3925 __func__, ret);
3926 goto done;
3927 }
3928
3929 ucontrol->value.integer.value[0] = cfg_data.app_type;
3930 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
3931 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
3932 ucontrol->value.integer.value[3] = be_id;
3933 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
3934 __func__, fe_id, session_type, be_id,
3935 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3936done:
3937 return ret;
3938}
3939
3940static int msm_compr_channel_map_put(struct snd_kcontrol *kcontrol,
3941 struct snd_ctl_elem_value *ucontrol)
3942{
3943 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3944 u64 fe_id = kcontrol->private_value;
3945 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3946 snd_soc_component_get_drvdata(comp);
3947 int rc = 0, i;
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05303948 struct msm_pcm_channel_mixer *chmixer_pspd = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303949
3950 pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
3951
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05303952 if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303953 pr_err("%s Received out of bounds fe_id %llu\n",
3954 __func__, fe_id);
3955 rc = -EINVAL;
3956 goto end;
3957 }
3958
3959 if (pdata->ch_map[fe_id]) {
3960 pdata->ch_map[fe_id]->set_ch_map = true;
Dieter Lueckingceef9af2018-09-28 15:09:32 +02003961 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303962 pdata->ch_map[fe_id]->channel_map[i] =
3963 (char)(ucontrol->value.integer.value[i]);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05303964
3965 /* update chmixer_pspd chmap cached with routing driver as well */
3966 chmixer_pspd = pdata->chmixer_pspd[fe_id];
3967 if (chmixer_pspd && chmixer_pspd->enable) {
3968 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
3969 chmixer_pspd->in_ch_map[i] =
3970 pdata->ch_map[fe_id]->channel_map[i];
3971 chmixer_pspd->override_in_ch_map = true;
3972 msm_pcm_routing_set_channel_mixer_cfg(fe_id,
3973 SESSION_TYPE_RX, chmixer_pspd);
3974 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303975 } else {
3976 pr_debug("%s: no memory for ch_map, default will be set\n",
3977 __func__);
3978 }
3979end:
3980 pr_debug("%s: ret %d\n", __func__, rc);
3981 return rc;
3982}
3983
3984static int msm_compr_channel_map_get(struct snd_kcontrol *kcontrol,
3985 struct snd_ctl_elem_value *ucontrol)
3986{
3987 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3988 u64 fe_id = kcontrol->private_value;
3989 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3990 snd_soc_component_get_drvdata(comp);
3991 int rc = 0, i;
3992
3993 pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05303994 if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303995 pr_err("%s: Received out of bounds fe_id %llu\n",
3996 __func__, fe_id);
3997 rc = -EINVAL;
3998 goto end;
3999 }
4000 if (pdata->ch_map[fe_id]) {
Dieter Lueckingceef9af2018-09-28 15:09:32 +02004001 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304002 ucontrol->value.integer.value[i] =
4003 pdata->ch_map[fe_id]->channel_map[i];
4004 }
4005end:
4006 pr_debug("%s: ret %d\n", __func__, rc);
4007 return rc;
4008}
4009
4010static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
4011 struct snd_ctl_elem_value *ucontrol)
4012{
4013 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4014 unsigned long fe_id = kcontrol->private_value;
4015 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4016 snd_soc_component_get_drvdata(comp);
4017 struct snd_compr_stream *cstream = NULL;
4018 struct msm_compr_audio *prtd;
4019 int ret = 0;
4020 struct msm_adsp_event_data *event_data = NULL;
4021
4022 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
4023 pr_err("%s Received invalid fe_id %lu\n",
4024 __func__, fe_id);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05304025 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304026 }
4027
4028 cstream = pdata->cstream[fe_id];
4029 if (cstream == NULL) {
4030 pr_err("%s cstream is null\n", __func__);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05304031 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304032 }
4033
4034 prtd = cstream->runtime->private_data;
4035 if (!prtd) {
4036 pr_err("%s: prtd is null\n", __func__);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05304037 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304038 }
4039
Ajit Pandeyfa018862019-09-04 14:34:00 +05304040 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304041 if (prtd->audio_client == NULL) {
4042 pr_err("%s: audio_client is null\n", __func__);
4043 ret = -EINVAL;
4044 goto done;
4045 }
4046
4047 event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data;
4048 if ((event_data->event_type < ADSP_STREAM_PP_EVENT) ||
4049 (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) {
4050 pr_err("%s: invalid event_type=%d",
4051 __func__, event_data->event_type);
4052 ret = -EINVAL;
4053 goto done;
4054 }
4055
Xiaojun Sang75642c32018-03-23 08:57:33 +08004056 if (event_data->payload_len > sizeof(ucontrol->value.bytes.data)
4057 - sizeof(struct msm_adsp_event_data)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304058 pr_err("%s param length=%d exceeds limit",
4059 __func__, event_data->payload_len);
4060 ret = -EINVAL;
4061 goto done;
4062 }
4063
4064 ret = q6asm_send_stream_cmd(prtd->audio_client, event_data);
4065 if (ret < 0)
4066 pr_err("%s: failed to send stream event cmd, err = %d\n",
4067 __func__, ret);
4068done:
Ajit Pandeyfa018862019-09-04 14:34:00 +05304069 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304070 return ret;
4071}
4072
4073static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
4074 struct snd_ctl_elem_value *ucontrol)
4075{
4076 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4077 unsigned long fe_id = kcontrol->private_value;
4078 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4079 snd_soc_component_get_drvdata(comp);
4080 struct snd_compr_stream *cstream = NULL;
4081 struct msm_compr_audio *prtd;
4082 int fd;
4083 int ret = 0;
4084
4085 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
4086 pr_err("%s Received out of bounds invalid fe_id %lu\n",
4087 __func__, fe_id);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05304088 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304089 }
4090
4091 cstream = pdata->cstream[fe_id];
4092 if (cstream == NULL) {
4093 pr_err("%s cstream is null\n", __func__);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05304094 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304095 }
4096
4097 prtd = cstream->runtime->private_data;
4098 if (!prtd) {
4099 pr_err("%s: prtd is null\n", __func__);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05304100 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304101 }
4102
Ajit Pandeyfa018862019-09-04 14:34:00 +05304103 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304104 if (prtd->audio_client == NULL) {
4105 pr_err("%s: audio_client is null\n", __func__);
4106 ret = -EINVAL;
4107 goto done;
4108 }
4109
4110 memcpy(&fd, ucontrol->value.bytes.data, sizeof(fd));
4111 ret = q6asm_send_ion_fd(prtd->audio_client, fd);
4112 if (ret < 0)
4113 pr_err("%s: failed to register ion fd\n", __func__);
4114done:
Ajit Pandeyfa018862019-09-04 14:34:00 +05304115 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304116 return ret;
4117}
4118
4119static int msm_compr_rtic_event_ack_put(struct snd_kcontrol *kcontrol,
4120 struct snd_ctl_elem_value *ucontrol)
4121{
4122 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4123 unsigned long fe_id = kcontrol->private_value;
4124 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4125 snd_soc_component_get_drvdata(comp);
4126 struct snd_compr_stream *cstream = NULL;
4127 struct msm_compr_audio *prtd;
4128 int ret = 0;
4129 int param_length = 0;
4130
4131 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
4132 pr_err("%s Received invalid fe_id %lu\n",
4133 __func__, fe_id);
Ajit Pandey9adf04c2019-10-24 13:45:11 +05304134 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304135 }
4136
Ajit Pandeyfa018862019-09-04 14:34:00 +05304137 mutex_lock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304138 cstream = pdata->cstream[fe_id];
4139 if (cstream == NULL) {
4140 pr_err("%s cstream is null\n", __func__);
4141 ret = -EINVAL;
4142 goto done;
4143 }
4144
4145 prtd = cstream->runtime->private_data;
4146 if (!prtd) {
4147 pr_err("%s: prtd is null\n", __func__);
4148 ret = -EINVAL;
4149 goto done;
4150 }
4151
4152 if (prtd->audio_client == NULL) {
4153 pr_err("%s: audio_client is null\n", __func__);
4154 ret = -EINVAL;
4155 goto done;
4156 }
4157
4158 memcpy(&param_length, ucontrol->value.bytes.data,
4159 sizeof(param_length));
4160 if ((param_length + sizeof(param_length))
4161 >= sizeof(ucontrol->value.bytes.data)) {
4162 pr_err("%s param length=%d exceeds limit",
4163 __func__, param_length);
4164 ret = -EINVAL;
4165 goto done;
4166 }
4167
4168 ret = q6asm_send_rtic_event_ack(prtd->audio_client,
4169 ucontrol->value.bytes.data + sizeof(param_length),
4170 param_length);
4171 if (ret < 0)
4172 pr_err("%s: failed to send rtic event ack, err = %d\n",
4173 __func__, ret);
4174done:
Ajit Pandeyfa018862019-09-04 14:34:00 +05304175 mutex_unlock(&pdata->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304176 return ret;
4177}
4178
4179static int msm_compr_gapless_put(struct snd_kcontrol *kcontrol,
4180 struct snd_ctl_elem_value *ucontrol)
4181{
4182 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4183 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4184 snd_soc_component_get_drvdata(comp);
4185 pdata->use_dsp_gapless_mode = ucontrol->value.integer.value[0];
4186 pr_debug("%s: value: %ld\n", __func__,
4187 ucontrol->value.integer.value[0]);
4188
4189 return 0;
4190}
4191
4192static int msm_compr_gapless_get(struct snd_kcontrol *kcontrol,
4193 struct snd_ctl_elem_value *ucontrol)
4194{
4195 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4196 struct msm_compr_pdata *pdata =
4197 snd_soc_component_get_drvdata(comp);
4198 pr_debug("%s:gapless mode %d\n", __func__, pdata->use_dsp_gapless_mode);
4199 ucontrol->value.integer.value[0] = pdata->use_dsp_gapless_mode;
4200
4201 return 0;
4202}
4203
4204static const struct snd_kcontrol_new msm_compr_gapless_controls[] = {
4205 SOC_SINGLE_EXT("Compress Gapless Playback",
4206 0, 0, 1, 0,
4207 msm_compr_gapless_get,
4208 msm_compr_gapless_put),
4209};
4210
Meng Wangee084a02018-09-04 16:11:58 +08004211static int msm_compr_probe(struct snd_soc_component *component)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304212{
4213 struct msm_compr_pdata *pdata;
4214 int i;
4215 int rc;
4216 const char *qdsp_version;
4217
4218 pr_debug("%s\n", __func__);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304219 pdata = (struct msm_compr_pdata *) dev_get_drvdata(component->dev);
4220 if (!pdata) {
4221 pr_err("%s platform data not set\n", __func__);
4222 return -EINVAL;
4223 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304224
Meng Wangee084a02018-09-04 16:11:58 +08004225 snd_soc_component_set_drvdata(component, pdata);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304226
4227 for (i = 0; i < MSM_FRONTEND_DAI_MAX; i++) {
4228 pdata->volume[i][0] = COMPRESSED_LR_VOL_MAX_STEPS;
4229 pdata->volume[i][1] = COMPRESSED_LR_VOL_MAX_STEPS;
4230 pdata->audio_effects[i] = NULL;
4231 pdata->dec_params[i] = NULL;
4232 pdata->cstream[i] = NULL;
4233 pdata->ch_map[i] = NULL;
Aditya Bavanari9deef912017-11-20 13:31:31 +05304234 pdata->is_in_use[i] = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304235 }
4236
Meng Wangee084a02018-09-04 16:11:58 +08004237 snd_soc_add_component_controls(component, msm_compr_gapless_controls,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304238 ARRAY_SIZE(msm_compr_gapless_controls));
4239
Meng Wangee084a02018-09-04 16:11:58 +08004240 rc = of_property_read_string(component->dev->of_node,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304241 "qcom,adsp-version", &qdsp_version);
4242 if (!rc) {
4243 if (!strcmp(qdsp_version, "MDSP 1.2"))
4244 pdata->use_legacy_api = true;
4245 else
4246 pdata->use_legacy_api = false;
4247 } else
4248 pdata->use_legacy_api = false;
4249
4250 pr_debug("%s: use legacy api %d\n", __func__, pdata->use_legacy_api);
4251 /*
4252 * use_dsp_gapless_mode part of platform data(pdata) is updated from HAL
4253 * through a mixer control before compress driver is opened. The mixer
4254 * control is used to decide if dsp gapless mode needs to be enabled.
4255 * Gapless is disabled by default.
4256 */
4257 pdata->use_dsp_gapless_mode = false;
4258 return 0;
4259}
4260
4261static int msm_compr_volume_info(struct snd_kcontrol *kcontrol,
4262 struct snd_ctl_elem_info *uinfo)
4263{
4264 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4265 uinfo->count = 2;
4266 uinfo->value.integer.min = 0;
4267 uinfo->value.integer.max = COMPRESSED_LR_VOL_MAX_STEPS;
4268 return 0;
4269}
4270
4271static int msm_compr_audio_effects_config_info(struct snd_kcontrol *kcontrol,
4272 struct snd_ctl_elem_info *uinfo)
4273{
4274 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4275 uinfo->count = MAX_PP_PARAMS_SZ;
4276 uinfo->value.integer.min = 0;
4277 uinfo->value.integer.max = 0xFFFFFFFF;
4278 return 0;
4279}
4280
4281static int msm_compr_query_audio_effect_info(struct snd_kcontrol *kcontrol,
4282 struct snd_ctl_elem_info *uinfo)
4283{
4284 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4285 uinfo->count = 128;
4286 uinfo->value.integer.min = 0;
4287 uinfo->value.integer.max = 0xFFFFFFFF;
4288 return 0;
4289}
4290
4291static int msm_compr_dec_params_info(struct snd_kcontrol *kcontrol,
4292 struct snd_ctl_elem_info *uinfo)
4293{
4294 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4295 uinfo->count = 128;
4296 uinfo->value.integer.min = 0;
4297 uinfo->value.integer.max = 0xFFFFFFFF;
4298 return 0;
4299}
4300
4301static int msm_compr_app_type_cfg_info(struct snd_kcontrol *kcontrol,
4302 struct snd_ctl_elem_info *uinfo)
4303{
4304 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4305 uinfo->count = 5;
4306 uinfo->value.integer.min = 0;
4307 uinfo->value.integer.max = 0xFFFFFFFF;
4308 return 0;
4309}
4310
4311static int msm_compr_channel_map_info(struct snd_kcontrol *kcontrol,
4312 struct snd_ctl_elem_info *uinfo)
4313{
4314 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
Dieter Lueckingceef9af2018-09-28 15:09:32 +02004315 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304316 uinfo->value.integer.min = 0;
Surendar Karka59769532019-08-05 16:02:32 +05304317 /* See PCM_MAX_CHANNEL_MAP in apr_audio-v2.h */
4318 uinfo->value.integer.max = PCM_MAX_CHANNEL_MAP;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304319 return 0;
4320}
4321
4322static int msm_compr_add_volume_control(struct snd_soc_pcm_runtime *rtd)
4323{
Meng Wangee084a02018-09-04 16:11:58 +08004324 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304325 const char *mixer_ctl_name = "Compress Playback";
4326 const char *deviceNo = "NN";
4327 const char *suffix = "Volume";
4328 char *mixer_str = NULL;
4329 int ctl_len;
4330 struct snd_kcontrol_new fe_volume_control[1] = {
4331 {
4332 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4333 .name = "?",
4334 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
4335 SNDRV_CTL_ELEM_ACCESS_READWRITE,
4336 .info = msm_compr_volume_info,
4337 .tlv.p = msm_compr_vol_gain,
4338 .get = msm_compr_volume_get,
4339 .put = msm_compr_volume_put,
4340 .private_value = 0,
4341 }
4342 };
4343
4344 if (!rtd) {
4345 pr_err("%s NULL rtd\n", __func__);
4346 return 0;
4347 }
Meng Wangee084a02018-09-04 16:11:58 +08004348 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4349 if (!component) {
4350 pr_err("%s: component is NULL\n", __func__);
4351 return 0;
4352 }
4353
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304354 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4355 __func__, rtd->dai_link->name, rtd->dai_link->id,
4356 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4357 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
4358 strlen(suffix) + 1;
4359 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4360 if (!mixer_str) {
4361 pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
4362 return 0;
4363 }
4364 snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
4365 rtd->pcm->device, suffix);
4366 fe_volume_control[0].name = mixer_str;
4367 fe_volume_control[0].private_value = rtd->dai_link->id;
4368 pr_debug("Registering new mixer ctl %s", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004369 snd_soc_add_component_controls(component, fe_volume_control,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304370 ARRAY_SIZE(fe_volume_control));
4371 kfree(mixer_str);
4372 return 0;
4373}
4374
4375static int msm_compr_add_audio_effects_control(struct snd_soc_pcm_runtime *rtd)
4376{
Meng Wangee084a02018-09-04 16:11:58 +08004377 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304378 const char *mixer_ctl_name = "Audio Effects Config";
4379 const char *deviceNo = "NN";
4380 char *mixer_str = NULL;
4381 int ctl_len;
4382 struct snd_kcontrol_new fe_audio_effects_config_control[1] = {
4383 {
4384 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4385 .name = "?",
4386 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4387 .info = msm_compr_audio_effects_config_info,
4388 .get = msm_compr_audio_effects_config_get,
4389 .put = msm_compr_audio_effects_config_put,
4390 .private_value = 0,
4391 }
4392 };
4393
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304394 if (!rtd) {
4395 pr_err("%s NULL rtd\n", __func__);
4396 return 0;
4397 }
4398
Meng Wangee084a02018-09-04 16:11:58 +08004399 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4400 if (!component) {
4401 pr_err("%s: component is NULL\n", __func__);
4402 return 0;
4403 }
4404
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304405 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4406 __func__, rtd->dai_link->name, rtd->dai_link->id,
4407 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4408
4409 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4410 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4411
4412 if (!mixer_str)
4413 return 0;
4414
4415 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4416
4417 fe_audio_effects_config_control[0].name = mixer_str;
4418 fe_audio_effects_config_control[0].private_value = rtd->dai_link->id;
4419 pr_debug("Registering new mixer ctl %s\n", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004420 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304421 fe_audio_effects_config_control,
4422 ARRAY_SIZE(fe_audio_effects_config_control));
4423 kfree(mixer_str);
4424 return 0;
4425}
4426
4427static int msm_compr_add_query_audio_effect_control(
4428 struct snd_soc_pcm_runtime *rtd)
4429{
Meng Wangee084a02018-09-04 16:11:58 +08004430 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304431 const char *mixer_ctl_name = "Query Audio Effect Param";
4432 const char *deviceNo = "NN";
4433 char *mixer_str = NULL;
4434 int ctl_len;
4435 struct snd_kcontrol_new fe_query_audio_effect_control[1] = {
4436 {
4437 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4438 .name = "?",
4439 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4440 .info = msm_compr_query_audio_effect_info,
4441 .get = msm_compr_query_audio_effect_get,
4442 .put = msm_compr_query_audio_effect_put,
4443 .private_value = 0,
4444 }
4445 };
4446 if (!rtd) {
4447 pr_err("%s NULL rtd\n", __func__);
4448 return 0;
4449 }
Meng Wangee084a02018-09-04 16:11:58 +08004450
4451 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4452 if (!component) {
4453 pr_err("%s: component is NULL\n", __func__);
4454 return 0;
4455 }
4456
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304457 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4458 __func__, rtd->dai_link->name, rtd->dai_link->id,
4459 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4460 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4461 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4462 if (!mixer_str) {
4463 pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
4464 return 0;
4465 }
4466 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4467 fe_query_audio_effect_control[0].name = mixer_str;
4468 fe_query_audio_effect_control[0].private_value = rtd->dai_link->id;
4469 pr_debug("%s: registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004470 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304471 fe_query_audio_effect_control,
4472 ARRAY_SIZE(fe_query_audio_effect_control));
4473 kfree(mixer_str);
4474 return 0;
4475}
4476
4477static int msm_compr_add_audio_adsp_stream_cmd_control(
4478 struct snd_soc_pcm_runtime *rtd)
4479{
Meng Wangee084a02018-09-04 16:11:58 +08004480 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304481 const char *mixer_ctl_name = DSP_STREAM_CMD;
4482 const char *deviceNo = "NN";
4483 char *mixer_str = NULL;
4484 int ctl_len = 0, ret = 0;
4485 struct snd_kcontrol_new fe_audio_adsp_stream_cmd_config_control[1] = {
4486 {
4487 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4488 .name = "?",
4489 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4490 .info = msm_adsp_stream_cmd_info,
4491 .put = msm_compr_adsp_stream_cmd_put,
4492 .private_value = 0,
4493 }
4494 };
4495
4496 if (!rtd) {
4497 pr_err("%s NULL rtd\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08004498 return -EINVAL;
4499 }
4500
4501 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4502 if (!component) {
4503 pr_err("%s: component is NULL\n", __func__);
4504 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304505 }
4506
4507 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4508 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08004509 if (!mixer_str)
4510 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304511
4512 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4513 fe_audio_adsp_stream_cmd_config_control[0].name = mixer_str;
4514 fe_audio_adsp_stream_cmd_config_control[0].private_value =
4515 rtd->dai_link->id;
4516 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004517 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304518 fe_audio_adsp_stream_cmd_config_control,
4519 ARRAY_SIZE(fe_audio_adsp_stream_cmd_config_control));
4520 if (ret < 0)
4521 pr_err("%s: failed to add ctl %s. err = %d\n",
4522 __func__, mixer_str, ret);
4523
4524 kfree(mixer_str);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304525 return ret;
4526}
4527
4528static int msm_compr_add_audio_adsp_stream_callback_control(
4529 struct snd_soc_pcm_runtime *rtd)
4530{
Meng Wangee084a02018-09-04 16:11:58 +08004531 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304532 const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
4533 const char *deviceNo = "NN";
4534 char *mixer_str = NULL;
4535 int ctl_len = 0, ret = 0;
4536 struct snd_kcontrol *kctl;
4537
4538 struct snd_kcontrol_new fe_audio_adsp_callback_config_control[1] = {
4539 {
4540 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4541 .name = "?",
4542 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4543 .info = msm_adsp_stream_callback_info,
4544 .get = msm_adsp_stream_callback_get,
4545 .private_value = 0,
4546 }
4547 };
4548
4549 if (!rtd) {
4550 pr_err("%s: rtd is NULL\n", __func__);
4551 ret = -EINVAL;
4552 goto done;
4553 }
4554
Meng Wangee084a02018-09-04 16:11:58 +08004555 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4556 if (!component) {
4557 pr_err("%s: component is NULL\n", __func__);
4558 return -EINVAL;
4559 }
4560
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304561 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4562 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4563 if (!mixer_str) {
4564 ret = -ENOMEM;
4565 goto done;
4566 }
4567
4568 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4569 fe_audio_adsp_callback_config_control[0].name = mixer_str;
4570 fe_audio_adsp_callback_config_control[0].private_value =
4571 rtd->dai_link->id;
4572 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004573 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304574 fe_audio_adsp_callback_config_control,
4575 ARRAY_SIZE(fe_audio_adsp_callback_config_control));
4576 if (ret < 0) {
4577 pr_err("%s: failed to add ctl %s. err = %d\n",
4578 __func__, mixer_str, ret);
4579 ret = -EINVAL;
4580 goto free_mixer_str;
4581 }
4582
4583 kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
4584 if (!kctl) {
4585 pr_err("%s: failed to get kctl %s.\n", __func__, mixer_str);
4586 ret = -EINVAL;
4587 goto free_mixer_str;
4588 }
4589
4590 kctl->private_data = NULL;
4591
4592free_mixer_str:
4593 kfree(mixer_str);
4594done:
4595 return ret;
4596}
4597
4598static int msm_compr_add_dec_runtime_params_control(
4599 struct snd_soc_pcm_runtime *rtd)
4600{
Meng Wangee084a02018-09-04 16:11:58 +08004601 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304602 const char *mixer_ctl_name = "Audio Stream";
4603 const char *deviceNo = "NN";
4604 const char *suffix = "Dec Params";
4605 char *mixer_str = NULL;
4606 int ctl_len;
4607 struct snd_kcontrol_new fe_dec_params_control[1] = {
4608 {
4609 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4610 .name = "?",
4611 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4612 .info = msm_compr_dec_params_info,
4613 .get = msm_compr_dec_params_get,
4614 .put = msm_compr_dec_params_put,
4615 .private_value = 0,
4616 }
4617 };
4618
4619 if (!rtd) {
4620 pr_err("%s NULL rtd\n", __func__);
4621 return 0;
4622 }
4623
Meng Wangee084a02018-09-04 16:11:58 +08004624 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4625 if (!component) {
4626 pr_err("%s: component is NULL\n", __func__);
4627 return 0;
4628 }
4629
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304630 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4631 __func__, rtd->dai_link->name, rtd->dai_link->id,
4632 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4633
4634 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
4635 strlen(suffix) + 1;
4636 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4637
4638 if (!mixer_str)
4639 return 0;
4640
4641 snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
4642 rtd->pcm->device, suffix);
4643
4644 fe_dec_params_control[0].name = mixer_str;
4645 fe_dec_params_control[0].private_value = rtd->dai_link->id;
4646 pr_debug("Registering new mixer ctl %s", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004647 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304648 fe_dec_params_control,
4649 ARRAY_SIZE(fe_dec_params_control));
4650 kfree(mixer_str);
4651 return 0;
4652}
4653
4654static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
4655{
Meng Wangee084a02018-09-04 16:11:58 +08004656 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304657 const char *playback_mixer_ctl_name = "Audio Stream";
4658 const char *capture_mixer_ctl_name = "Audio Stream Capture";
4659 const char *deviceNo = "NN";
4660 const char *suffix = "App Type Cfg";
4661 char *mixer_str = NULL;
4662 int ctl_len;
4663 struct snd_kcontrol_new fe_app_type_cfg_control[1] = {
4664 {
4665 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4666 .name = "?",
4667 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4668 .info = msm_compr_app_type_cfg_info,
4669 .put = msm_compr_playback_app_type_cfg_put,
4670 .get = msm_compr_playback_app_type_cfg_get,
4671 .private_value = 0,
4672 }
4673 };
4674
4675 if (!rtd) {
4676 pr_err("%s NULL rtd\n", __func__);
4677 return 0;
4678 }
4679
Meng Wangee084a02018-09-04 16:11:58 +08004680 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4681 if (!component) {
4682 pr_err("%s: component is NULL\n", __func__);
4683 return 0;
4684 }
4685
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304686 pr_debug("%s: added new compr FE ctl with name %s, id %d, cpu dai %s, device no %d\n",
4687 __func__, rtd->dai_link->name, rtd->dai_link->id,
4688 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4689 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
4690 ctl_len = strlen(playback_mixer_ctl_name) + 1 + strlen(deviceNo)
4691 + 1 + strlen(suffix) + 1;
4692 else
4693 ctl_len = strlen(capture_mixer_ctl_name) + 1 + strlen(deviceNo)
4694 + 1 + strlen(suffix) + 1;
4695
4696 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4697
4698 if (!mixer_str)
4699 return 0;
4700
4701 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
4702 snprintf(mixer_str, ctl_len, "%s %d %s",
4703 playback_mixer_ctl_name, rtd->pcm->device, suffix);
4704 else
4705 snprintf(mixer_str, ctl_len, "%s %d %s",
4706 capture_mixer_ctl_name, rtd->pcm->device, suffix);
4707
4708 fe_app_type_cfg_control[0].name = mixer_str;
4709 fe_app_type_cfg_control[0].private_value = rtd->dai_link->id;
4710
4711 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
4712 fe_app_type_cfg_control[0].put =
4713 msm_compr_playback_app_type_cfg_put;
4714 fe_app_type_cfg_control[0].get =
4715 msm_compr_playback_app_type_cfg_get;
4716 } else {
4717 fe_app_type_cfg_control[0].put =
4718 msm_compr_capture_app_type_cfg_put;
4719 fe_app_type_cfg_control[0].get =
4720 msm_compr_capture_app_type_cfg_get;
4721 }
4722 pr_debug("Registering new mixer ctl %s", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004723 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304724 fe_app_type_cfg_control,
4725 ARRAY_SIZE(fe_app_type_cfg_control));
4726 kfree(mixer_str);
4727 return 0;
4728}
4729
4730static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
4731{
Meng Wangee084a02018-09-04 16:11:58 +08004732 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304733 const char *mixer_ctl_name = "Playback Channel Map";
4734 const char *deviceNo = "NN";
4735 char *mixer_str = NULL;
4736 struct msm_compr_pdata *pdata = NULL;
4737 int ctl_len;
4738 struct snd_kcontrol_new fe_channel_map_control[1] = {
4739 {
4740 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4741 .name = "?",
4742 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4743 .info = msm_compr_channel_map_info,
4744 .get = msm_compr_channel_map_get,
4745 .put = msm_compr_channel_map_put,
4746 .private_value = 0,
4747 }
4748 };
4749
4750 if (!rtd) {
4751 pr_err("%s: NULL rtd\n", __func__);
4752 return -EINVAL;
4753 }
4754
Meng Wangee084a02018-09-04 16:11:58 +08004755 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4756 if (!component) {
4757 pr_err("%s: component is NULL\n", __func__);
4758 return -EINVAL;
4759 }
4760
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304761 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4762 __func__, rtd->dai_link->name, rtd->dai_link->id,
4763 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4764
4765 ctl_len = strlen(mixer_ctl_name) + strlen(deviceNo) + 1;
4766 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4767
4768 if (!mixer_str)
4769 return -ENOMEM;
4770
4771 snprintf(mixer_str, ctl_len, "%s%d", mixer_ctl_name, rtd->pcm->device);
4772
4773 fe_channel_map_control[0].name = mixer_str;
4774 fe_channel_map_control[0].private_value = rtd->dai_link->id;
4775 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004776 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304777 fe_channel_map_control,
4778 ARRAY_SIZE(fe_channel_map_control));
4779
Meng Wangee084a02018-09-04 16:11:58 +08004780 pdata = snd_soc_component_get_drvdata(component);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304781 pdata->ch_map[rtd->dai_link->id] =
4782 kzalloc(sizeof(struct msm_compr_ch_map), GFP_KERNEL);
4783 if (!pdata->ch_map[rtd->dai_link->id]) {
4784 pr_err("%s: Could not allocate memory for channel map\n",
4785 __func__);
4786 kfree(mixer_str);
4787 return -ENOMEM;
4788 }
4789 kfree(mixer_str);
4790 return 0;
4791}
4792
4793static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
4794{
Meng Wangee084a02018-09-04 16:11:58 +08004795 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304796 const char *mixer_ctl_name = "Playback ION FD";
4797 const char *deviceNo = "NN";
4798 char *mixer_str = NULL;
4799 int ctl_len = 0, ret = 0;
4800 struct snd_kcontrol_new fe_ion_fd_config_control[1] = {
4801 {
4802 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4803 .name = "?",
4804 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4805 .info = msm_adsp_stream_cmd_info,
4806 .put = msm_compr_ion_fd_map_put,
4807 .private_value = 0,
4808 }
4809 };
4810
4811 if (!rtd) {
4812 pr_err("%s NULL rtd\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08004813 return -EINVAL;
4814 }
4815
4816 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4817 if (!component) {
4818 pr_err("%s: component is NULL\n", __func__);
4819 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304820 }
4821
4822 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4823 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08004824 if (!mixer_str)
4825 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304826
4827 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4828 fe_ion_fd_config_control[0].name = mixer_str;
4829 fe_ion_fd_config_control[0].private_value = rtd->dai_link->id;
4830 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004831 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304832 fe_ion_fd_config_control,
4833 ARRAY_SIZE(fe_ion_fd_config_control));
4834 if (ret < 0)
4835 pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
4836
4837 kfree(mixer_str);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304838 return ret;
4839}
4840
4841static int msm_compr_add_event_ack_cmd_control(struct snd_soc_pcm_runtime *rtd)
4842{
Meng Wangee084a02018-09-04 16:11:58 +08004843 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304844 const char *mixer_ctl_name = "Playback Event Ack";
4845 const char *deviceNo = "NN";
4846 char *mixer_str = NULL;
4847 int ctl_len = 0, ret = 0;
4848 struct snd_kcontrol_new fe_event_ack_config_control[1] = {
4849 {
4850 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4851 .name = "?",
4852 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4853 .info = msm_adsp_stream_cmd_info,
4854 .put = msm_compr_rtic_event_ack_put,
4855 .private_value = 0,
4856 }
4857 };
4858
4859 if (!rtd) {
4860 pr_err("%s NULL rtd\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08004861 return -EINVAL;
4862 }
4863
4864 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4865 if (!component) {
4866 pr_err("%s: component is NULL\n", __func__);
4867 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304868 }
4869
4870 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4871 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08004872 if (!mixer_str)
4873 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304874
4875 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4876 fe_event_ack_config_control[0].name = mixer_str;
4877 fe_event_ack_config_control[0].private_value = rtd->dai_link->id;
4878 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004879 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304880 fe_event_ack_config_control,
4881 ARRAY_SIZE(fe_event_ack_config_control));
4882 if (ret < 0)
4883 pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
4884
4885 kfree(mixer_str);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304886 return ret;
4887}
4888
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304889static struct msm_pcm_channel_mixer *msm_compr_get_chmixer(
4890 struct msm_compr_pdata *pdata, u64 fe_id)
4891{
4892 if (!pdata) {
4893 pr_err("%s: missing pdata\n", __func__);
4894 return NULL;
4895 }
4896
4897 if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
4898 pr_err("%s: invalid FE %llu\n", __func__, fe_id);
4899 return NULL;
4900 }
4901
4902 return pdata->chmixer_pspd[fe_id];
4903}
4904
4905static int msm_compr_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol,
4906 struct snd_ctl_elem_value *ucontrol)
4907{
4908 u64 fe_id = kcontrol->private_value & 0xFF;
4909 int session_type = (kcontrol->private_value >> 8) & 0xFF;
4910 int ret = 0, i = 0, stream_id = 0, be_id = 0;
4911 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4912 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4913 snd_soc_component_get_drvdata(comp);
4914 struct snd_compr_stream *cstream = NULL;
4915 struct msm_compr_audio *prtd = NULL;
4916 struct msm_pcm_channel_mixer *chmixer_pspd = NULL;
4917 u8 asm_ch_map[PCM_FORMAT_MAX_NUM_CHANNEL_V8] = {0};
4918 bool reset_override_out_ch_map = false;
4919 bool reset_override_in_ch_map = false;
4920
4921 if ((session_type != SESSION_TYPE_TX) &&
4922 (session_type != SESSION_TYPE_RX)) {
4923 pr_err("%s: invalid session type %d\n", __func__, session_type);
4924 return -EINVAL;
4925 }
4926
4927 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
4928 if (!chmixer_pspd) {
4929 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
4930 return -EINVAL;
4931 }
4932
4933 chmixer_pspd->enable = ucontrol->value.integer.value[0];
4934 chmixer_pspd->rule = ucontrol->value.integer.value[1];
4935 chmixer_pspd->input_channel = ucontrol->value.integer.value[2];
4936 chmixer_pspd->output_channel = ucontrol->value.integer.value[3];
4937 chmixer_pspd->port_idx = ucontrol->value.integer.value[4];
4938
Erin Yan2f81be22019-04-29 13:42:57 +08004939 if (chmixer_pspd->input_channel < 0 ||
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05304940 chmixer_pspd->input_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8 ||
Erin Yan2f81be22019-04-29 13:42:57 +08004941 chmixer_pspd->output_channel < 0 ||
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05304942 chmixer_pspd->output_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
4943 pr_err("%s: Invalid channels, in %d, out %d\n",
4944 __func__, chmixer_pspd->input_channel,
4945 chmixer_pspd->output_channel);
4946 return -EINVAL;
4947 }
4948
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304949 if (chmixer_pspd->enable) {
4950 if (session_type == SESSION_TYPE_RX &&
4951 !chmixer_pspd->override_in_ch_map) {
4952 if (pdata->ch_map[fe_id]->set_ch_map) {
4953 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4954 chmixer_pspd->in_ch_map[i] =
4955 pdata->ch_map[fe_id]->channel_map[i];
4956 } else {
4957 q6asm_map_channels(asm_ch_map,
4958 chmixer_pspd->input_channel, false);
4959 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4960 chmixer_pspd->in_ch_map[i] = asm_ch_map[i];
4961 }
4962 chmixer_pspd->override_in_ch_map = true;
4963 reset_override_in_ch_map = true;
4964 } else if (session_type == SESSION_TYPE_TX &&
4965 !chmixer_pspd->override_out_ch_map) {
4966 if (pdata->ch_map[fe_id]->set_ch_map) {
4967 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4968 chmixer_pspd->out_ch_map[i] =
4969 pdata->ch_map[fe_id]->channel_map[i];
4970 } else {
4971 q6asm_map_channels(asm_ch_map,
4972 chmixer_pspd->output_channel, false);
4973 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4974 chmixer_pspd->out_ch_map[i] = asm_ch_map[i];
4975 }
4976 chmixer_pspd->override_out_ch_map = true;
4977 reset_override_out_ch_map = true;
4978 }
4979 } else {
4980 chmixer_pspd->override_out_ch_map = false;
4981 chmixer_pspd->override_in_ch_map = false;
4982 }
4983
4984 /* cache value and take effect during adm_open stage */
4985 msm_pcm_routing_set_channel_mixer_cfg(fe_id,
4986 session_type,
4987 chmixer_pspd);
4988
4989 cstream = pdata->cstream[fe_id];
4990 if (chmixer_pspd->enable && cstream && cstream->runtime) {
4991 prtd = cstream->runtime->private_data;
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304992
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05304993 if (prtd && prtd->audio_client) {
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304994 stream_id = prtd->audio_client->session;
4995 be_id = chmixer_pspd->port_idx;
Erin Yan2f81be22019-04-29 13:42:57 +08004996 msm_pcm_routing_set_channel_mixer_runtime(be_id,
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304997 stream_id, session_type, chmixer_pspd);
4998 }
4999 }
5000
5001 if (reset_override_out_ch_map)
5002 chmixer_pspd->override_out_ch_map = false;
5003 if (reset_override_in_ch_map)
5004 chmixer_pspd->override_in_ch_map = false;
5005
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305006 return ret;
5007}
5008
5009static int msm_compr_channel_mixer_cfg_ctl_get(struct snd_kcontrol *kcontrol,
5010 struct snd_ctl_elem_value *ucontrol)
5011{
5012 u64 fe_id = kcontrol->private_value & 0xFF;
5013 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5014 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5015 snd_soc_component_get_drvdata(comp);
5016 struct msm_pcm_channel_mixer *chmixer_pspd;
5017
5018 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5019 if (!chmixer_pspd) {
5020 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5021 return -EINVAL;
5022 }
5023
5024 ucontrol->value.integer.value[0] = chmixer_pspd->enable;
5025 ucontrol->value.integer.value[1] = chmixer_pspd->rule;
5026 ucontrol->value.integer.value[2] = chmixer_pspd->input_channel;
5027 ucontrol->value.integer.value[3] = chmixer_pspd->output_channel;
5028 ucontrol->value.integer.value[4] = chmixer_pspd->port_idx;
5029 return 0;
5030}
5031
5032static int msm_compr_channel_mixer_output_map_ctl_put(
5033 struct snd_kcontrol *kcontrol,
5034 struct snd_ctl_elem_value *ucontrol)
5035{
5036 u64 fe_id = kcontrol->private_value & 0xFF;
5037 int i = 0;
5038 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5039 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5040 snd_soc_component_get_drvdata(comp);
5041 struct msm_pcm_channel_mixer *chmixer_pspd;
5042
5043 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5044 if (!chmixer_pspd) {
5045 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5046 return -EINVAL;
5047 }
5048
5049 chmixer_pspd->override_out_ch_map = true;
5050 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5051 chmixer_pspd->out_ch_map[i] =
5052 ucontrol->value.integer.value[i];
5053
5054 return 0;
5055}
5056
5057static int msm_compr_channel_mixer_output_map_ctl_get(
5058 struct snd_kcontrol *kcontrol,
5059 struct snd_ctl_elem_value *ucontrol)
5060{
5061 u64 fe_id = kcontrol->private_value & 0xFF;
5062 int i = 0;
5063 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5064 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5065 snd_soc_component_get_drvdata(comp);
5066 struct msm_pcm_channel_mixer *chmixer_pspd;
5067
5068 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5069 if (!chmixer_pspd) {
5070 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5071 return -EINVAL;
5072 }
5073
5074 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5075 ucontrol->value.integer.value[i] =
5076 chmixer_pspd->out_ch_map[i];
5077 return 0;
5078}
5079
5080static int msm_compr_channel_mixer_input_map_ctl_put(
5081 struct snd_kcontrol *kcontrol,
5082 struct snd_ctl_elem_value *ucontrol)
5083{
5084 u64 fe_id = kcontrol->private_value & 0xFF;
5085 int i = 0;
5086 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5087 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5088 snd_soc_component_get_drvdata(comp);
5089 struct msm_pcm_channel_mixer *chmixer_pspd;
5090
5091 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5092 if (!chmixer_pspd) {
5093 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5094 return -EINVAL;
5095 }
5096
5097 chmixer_pspd->override_in_ch_map = true;
5098 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5099 chmixer_pspd->in_ch_map[i] = ucontrol->value.integer.value[i];
5100
5101 return 0;
5102}
5103
5104static int msm_compr_channel_mixer_input_map_ctl_get(
5105 struct snd_kcontrol *kcontrol,
5106 struct snd_ctl_elem_value *ucontrol)
5107{
5108 u64 fe_id = kcontrol->private_value & 0xFF;
5109 int i = 0;
5110 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5111 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5112 snd_soc_component_get_drvdata(comp);
5113 struct msm_pcm_channel_mixer *chmixer_pspd;
5114
5115 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5116 if (!chmixer_pspd) {
5117 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5118 return -EINVAL;
5119 }
5120
5121 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5122 ucontrol->value.integer.value[i] =
5123 chmixer_pspd->in_ch_map[i];
5124 return 0;
5125}
5126
5127static int msm_compr_channel_mixer_weight_ctl_put(
5128 struct snd_kcontrol *kcontrol,
5129 struct snd_ctl_elem_value *ucontrol)
5130{
5131 u64 fe_id = kcontrol->private_value & 0xFF;
5132 int channel = (kcontrol->private_value >> 16) & 0xFF;
5133 int i = 0;
5134 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5135 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5136 snd_soc_component_get_drvdata(comp);
5137 struct msm_pcm_channel_mixer *chmixer_pspd;
5138
5139 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5140 if (!chmixer_pspd) {
5141 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5142 return -EINVAL;
5143 }
5144
5145 if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
5146 pr_err("%s: invalid channel number %d\n", __func__, channel);
5147 return -EINVAL;
5148 }
5149 channel--;
5150
5151 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5152 chmixer_pspd->channel_weight[channel][i] =
5153 ucontrol->value.integer.value[i];
5154 return 0;
5155}
5156
5157static int msm_compr_channel_mixer_weight_ctl_get(
5158 struct snd_kcontrol *kcontrol,
5159 struct snd_ctl_elem_value *ucontrol)
5160{
5161 u64 fe_id = kcontrol->private_value & 0xFF;
5162 int channel = (kcontrol->private_value >> 16) & 0xFF;
5163 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
5164 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
5165 snd_soc_component_get_drvdata(comp);
5166 int i = 0;
5167 struct msm_pcm_channel_mixer *chmixer_pspd;
5168
5169 if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
5170 pr_err("%s: invalid channel number %d\n", __func__, channel);
5171 return -EINVAL;
5172 }
5173 channel--;
5174
5175 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
5176 if (!chmixer_pspd) {
5177 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
5178 return -EINVAL;
5179 }
5180
5181 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
5182 ucontrol->value.integer.value[i] =
5183 chmixer_pspd->channel_weight[channel][i];
5184 return 0;
5185}
5186
5187static int msm_compr_add_platform_controls(struct snd_kcontrol_new *kctl,
5188 struct snd_soc_pcm_runtime *rtd, const char *name_prefix,
5189 const char *name_suffix, int session_type, int channels)
5190{
5191 int ret = -EINVAL;
5192 char *mixer_name = NULL;
5193 const char *deviceNo = "NN";
5194 const char *channelNo = "NN";
5195 int ctl_len = 0;
5196 struct snd_soc_component *component = NULL;
5197
5198 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
5199 if (!component) {
5200 pr_err("%s: component is NULL\n", __func__);
5201 return -EINVAL;
5202 }
5203
5204 ctl_len = strlen(name_prefix) + 1 + strlen(deviceNo) + 1 +
5205 strlen(channelNo) + 1 + strlen(name_suffix) + 1;
5206
5207 mixer_name = kzalloc(ctl_len, GFP_KERNEL);
5208 if (mixer_name == NULL)
5209 return -ENOMEM;
5210
5211 if (channels >= 0) {
5212 snprintf(mixer_name, ctl_len, "%s %d %s %d",
5213 name_prefix, rtd->pcm->device, name_suffix, channels);
5214 kctl->private_value = (rtd->dai_link->id) | (channels << 16);
5215 } else {
5216 snprintf(mixer_name, ctl_len, "%s %d %s",
5217 name_prefix, rtd->pcm->device, name_suffix);
5218 kctl->private_value = (rtd->dai_link->id);
5219 }
5220 if (session_type != INVALID_SESSION)
5221 kctl->private_value |= (session_type << 8);
5222
5223 kctl->name = mixer_name;
5224 ret = snd_soc_add_component_controls(component, kctl, 1);
5225 kfree(mixer_name);
5226 return ret;
5227}
5228
5229static int msm_compr_channel_mixer_output_map_info(struct snd_kcontrol *kcontrol,
5230 struct snd_ctl_elem_info *uinfo)
5231{
5232 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5233 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
5234 /* Valid channel map value ranges from 1 to 64 */
5235 uinfo->value.integer.min = 1;
5236 uinfo->value.integer.max = 64;
5237 return 0;
5238}
5239
5240static int msm_compr_add_channel_mixer_output_map_controls(
5241 struct snd_soc_pcm_runtime *rtd)
5242{
5243 const char *playback_mixer_ctl_name = "AudStr";
5244 const char *capture_mixer_ctl_name = "AudStr Capture";
5245 const char *suffix = "ChMixer Output Map";
5246 const char *mixer_ctl_name = NULL;
5247 int ret = 0, session_type = INVALID_SESSION, channel = -1;
5248 struct snd_kcontrol_new channel_mixer_output_map_control = {
5249 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5250 .name = "?",
5251 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5252 .info = msm_compr_channel_mixer_output_map_info,
5253 .put = msm_compr_channel_mixer_output_map_ctl_put,
5254 .get = msm_compr_channel_mixer_output_map_ctl_get,
5255 .private_value = 0,
5256 };
5257
5258 mixer_ctl_name = rtd->compr->direction == SND_COMPRESS_PLAYBACK ?
5259 playback_mixer_ctl_name : capture_mixer_ctl_name ;
5260 ret = msm_compr_add_platform_controls(&channel_mixer_output_map_control,
5261 rtd, mixer_ctl_name, suffix, session_type, channel);
5262 if (ret < 0) {
5263 pr_err("%s: failed add platform ctl, err = %d\n",
5264 __func__, ret);
5265 }
5266
5267 return ret;
5268}
5269
5270static int msm_compr_channel_mixer_input_map_info(struct snd_kcontrol *kcontrol,
5271 struct snd_ctl_elem_info *uinfo)
5272{
5273 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5274 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
5275 /* Valid channel map value ranges from 1 to 64 */
5276 uinfo->value.integer.min = 1;
5277 uinfo->value.integer.max = 64;
5278 return 0;
5279}
5280
5281static int msm_compr_add_channel_mixer_input_map_controls(
5282 struct snd_soc_pcm_runtime *rtd)
5283{
5284 const char *playback_mixer_ctl_name = "AudStr";
5285 const char *capture_mixer_ctl_name = "AudStr Capture";
5286 const char *suffix = "ChMixer Input Map";
5287 const char *mixer_ctl_name = NULL;
5288 int ret = 0, session_type = INVALID_SESSION, channel = -1;
5289 struct snd_kcontrol_new channel_mixer_input_map_control = {
5290 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5291 .name = "?",
5292 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5293 .info = msm_compr_channel_mixer_input_map_info,
5294 .put = msm_compr_channel_mixer_input_map_ctl_put,
5295 .get = msm_compr_channel_mixer_input_map_ctl_get,
5296 .private_value = 0,
5297 };
5298
5299 mixer_ctl_name = rtd->compr->direction == SND_COMPRESS_PLAYBACK ?
5300 playback_mixer_ctl_name : capture_mixer_ctl_name ;
5301 ret = msm_compr_add_platform_controls(&channel_mixer_input_map_control,
5302 rtd, mixer_ctl_name, suffix, session_type, channel);
5303 if (ret < 0) {
5304 pr_err("%s: failed add platform ctl, err = %d\n",
5305 __func__, ret);
5306 }
5307
5308 return ret;
5309}
5310
5311static int msm_compr_channel_mixer_cfg_info(struct snd_kcontrol *kcontrol,
5312 struct snd_ctl_elem_info *uinfo)
5313{
5314 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5315 /* five int values: enable, rule, in_channels, out_channels and port_id */
5316 uinfo->count = 5;
5317 /* Valid range is all positive values to support above controls */
5318 uinfo->value.integer.min = 0;
5319 uinfo->value.integer.max = INT_MAX;
5320 return 0;
5321}
5322
5323static int msm_compr_add_channel_mixer_cfg_controls(
5324 struct snd_soc_pcm_runtime *rtd)
5325{
5326 const char *playback_mixer_ctl_name = "AudStr";
5327 const char *capture_mixer_ctl_name = "AudStr Capture";
5328 const char *suffix = "ChMixer Cfg";
5329 const char *mixer_ctl_name = NULL;
5330 int ret = 0, session_type = INVALID_SESSION, channel = -1;
5331 struct snd_kcontrol_new channel_mixer_cfg_control = {
5332 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5333 .name = "?",
5334 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5335 .info = msm_compr_channel_mixer_cfg_info,
5336 .put = msm_compr_channel_mixer_cfg_ctl_put,
5337 .get = msm_compr_channel_mixer_cfg_ctl_get,
5338 .private_value = 0,
5339 };
5340
5341 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
5342 session_type = SESSION_TYPE_RX;
5343 mixer_ctl_name = playback_mixer_ctl_name;
5344 } else {
5345 session_type = SESSION_TYPE_TX;
5346 mixer_ctl_name = capture_mixer_ctl_name;
5347 }
5348
5349 ret = msm_compr_add_platform_controls(&channel_mixer_cfg_control,
5350 rtd, mixer_ctl_name, suffix, session_type, channel);
5351 if (ret < 0) {
5352 pr_err("%s: failed add platform ctl, err = %d\n",
5353 __func__, ret);
5354 }
5355
5356 return ret;
5357}
5358
5359static int msm_compr_channel_mixer_weight_info(struct snd_kcontrol *kcontrol,
5360 struct snd_ctl_elem_info *uinfo)
5361{
5362 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5363 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
5364 /* Valid range: 0 to 0x4000(Unity) gain weightage */
5365 uinfo->value.integer.min = 0;
5366 uinfo->value.integer.max = 0x4000;
5367 return 0;
5368}
5369
5370static int msm_compr_add_channel_mixer_weight_controls(
5371 struct snd_soc_pcm_runtime *rtd,
5372 int channel)
5373{
5374 const char *playback_mixer_ctl_name = "AudStr";
5375 const char *capture_mixer_ctl_name = "AudStr Capture";
5376 const char *suffix = "ChMixer Weight Ch";
5377 const char *mixer_ctl_name = NULL;
5378 int ret = 0, session_type = INVALID_SESSION;
5379 struct snd_kcontrol_new channel_mixer_weight_control = {
5380 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5381 .name = "?",
5382 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5383 .info = msm_compr_channel_mixer_weight_info,
5384 .put = msm_compr_channel_mixer_weight_ctl_put,
5385 .get = msm_compr_channel_mixer_weight_ctl_get,
5386 .private_value = 0,
5387 };
5388
5389 mixer_ctl_name = rtd->compr->direction == SND_COMPRESS_PLAYBACK ?
5390 playback_mixer_ctl_name : capture_mixer_ctl_name ;
5391 ret = msm_compr_add_platform_controls(&channel_mixer_weight_control,
5392 rtd, mixer_ctl_name, suffix, session_type, channel);
5393 if (ret < 0) {
5394 pr_err("%s: failed add platform ctl, err = %d\n",
5395 __func__, ret);
5396 }
5397
5398 return ret;
5399}
5400
5401static int msm_compr_add_channel_mixer_controls(struct snd_soc_pcm_runtime *rtd)
5402{
5403 int i, ret = 0;
5404 struct msm_compr_pdata *pdata = NULL;
5405 struct snd_soc_component *component = NULL;
5406
5407 if (!rtd) {
5408 pr_err("%s NULL rtd\n", __func__);
5409 return -EINVAL;
5410 }
5411
5412 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
5413 if (!component) {
5414 pr_err("%s: component is NULL\n", __func__);
5415 return -EINVAL;
5416 }
5417
5418 pdata = (struct msm_compr_pdata *)
5419 snd_soc_component_get_drvdata(component);
5420 if (!pdata) {
5421 pr_err("%s: platform data not populated\n", __func__);
5422 return -EINVAL;
5423 }
5424
5425 if (!pdata->chmixer_pspd[rtd->dai_link->id]) {
5426 pdata->chmixer_pspd[rtd->dai_link->id] =
5427 kzalloc(sizeof(struct msm_pcm_channel_mixer), GFP_KERNEL);
5428 if (!pdata->chmixer_pspd[rtd->dai_link->id])
5429 return -ENOMEM;
5430 }
5431
5432 ret = msm_compr_add_channel_mixer_cfg_controls(rtd);
5433 if (ret) {
5434 pr_err("%s: pcm add channel mixer cfg controls failed:%d\n",
5435 __func__, ret);
5436 goto fail;
5437 }
5438 ret = msm_compr_add_channel_mixer_input_map_controls(rtd);
5439 if (ret) {
5440 pr_err("%s: pcm add channel mixer input map controls failed:%d\n",
5441 __func__, ret);
5442 goto fail;
5443 }
5444 ret = msm_compr_add_channel_mixer_output_map_controls(rtd);
5445 if (ret) {
5446 pr_err("%s: pcm add channel mixer output map controls failed:%d\n",
5447 __func__, ret);
5448 goto fail;
5449 }
5450
5451 for (i = 1; i <= PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++) {
5452 ret = msm_compr_add_channel_mixer_weight_controls(rtd, i);
5453 if (ret) {
5454 pr_err("%s: pcm add channel mixer weight controls failed:%d\n",
5455 __func__, ret);
5456 goto fail;
5457 }
5458 }
5459 return 0;
5460
5461fail:
5462 kfree(pdata->chmixer_pspd[rtd->dai_link->id]);
5463 pdata->chmixer_pspd[rtd->dai_link->id] = NULL;
5464 return ret;
5465}
5466
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305467static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
5468{
5469 int rc;
5470
5471 rc = msm_compr_add_volume_control(rtd);
5472 if (rc)
5473 pr_err("%s: Could not add Compr Volume Control\n", __func__);
5474
5475 rc = msm_compr_add_audio_effects_control(rtd);
5476 if (rc)
5477 pr_err("%s: Could not add Compr Audio Effects Control\n",
5478 __func__);
5479
5480 rc = msm_compr_add_audio_adsp_stream_cmd_control(rtd);
5481 if (rc)
5482 pr_err("%s: Could not add Compr ADSP Stream Cmd Control\n",
5483 __func__);
5484
5485 rc = msm_compr_add_audio_adsp_stream_callback_control(rtd);
5486 if (rc)
5487 pr_err("%s: Could not add Compr ADSP Stream Callback Control\n",
5488 __func__);
5489
5490 rc = msm_compr_add_io_fd_cmd_control(rtd);
5491 if (rc)
5492 pr_err("%s: Could not add Compr ion fd Control\n",
5493 __func__);
5494
5495 rc = msm_compr_add_event_ack_cmd_control(rtd);
5496 if (rc)
5497 pr_err("%s: Could not add Compr event ack Control\n",
5498 __func__);
5499
5500 rc = msm_compr_add_query_audio_effect_control(rtd);
5501 if (rc)
5502 pr_err("%s: Could not add Compr Query Audio Effect Control\n",
5503 __func__);
5504
5505 rc = msm_compr_add_dec_runtime_params_control(rtd);
5506 if (rc)
5507 pr_err("%s: Could not add Compr Dec runtime params Control\n",
5508 __func__);
5509 rc = msm_compr_add_app_type_cfg_control(rtd);
5510 if (rc)
5511 pr_err("%s: Could not add Compr App Type Cfg Control\n",
5512 __func__);
5513 rc = msm_compr_add_channel_map_control(rtd);
5514 if (rc)
5515 pr_err("%s: Could not add Compr Channel Map Control\n",
5516 __func__);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305517 rc = msm_compr_add_channel_mixer_controls(rtd);
5518 if (rc)
5519 pr_err("%s: Could not add Compr Channel Mixer Controls\n",
5520 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305521 return 0;
5522}
5523
5524static struct snd_compr_ops msm_compr_ops = {
5525 .open = msm_compr_open,
5526 .free = msm_compr_free,
5527 .trigger = msm_compr_trigger,
5528 .pointer = msm_compr_pointer,
5529 .set_params = msm_compr_set_params,
5530 .set_metadata = msm_compr_set_metadata,
5531 .get_metadata = msm_compr_get_metadata,
5532 .set_next_track_param = msm_compr_set_next_track_param,
5533 .ack = msm_compr_ack,
5534 .copy = msm_compr_copy,
5535 .get_caps = msm_compr_get_caps,
5536 .get_codec_caps = msm_compr_get_codec_caps,
5537};
5538
Meng Wangee084a02018-09-04 16:11:58 +08005539static struct snd_soc_component_driver msm_soc_component = {
5540 .name = DRV_NAME,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305541 .probe = msm_compr_probe,
5542 .compr_ops = &msm_compr_ops,
5543 .pcm_new = msm_compr_new,
5544};
5545
5546static int msm_compr_dev_probe(struct platform_device *pdev)
5547{
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305548 struct msm_compr_pdata *pdata = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305549
5550 pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305551 pdata = (struct msm_compr_pdata *)
5552 kzalloc(sizeof(*pdata), GFP_KERNEL);
5553 if (!pdata)
5554 return -ENOMEM;
Ajit Pandeyfa018862019-09-04 14:34:00 +05305555 mutex_init(&pdata->lock);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305556 dev_set_drvdata(&pdev->dev, pdata);
5557
Meng Wangee084a02018-09-04 16:11:58 +08005558 return snd_soc_register_component(&pdev->dev,
5559 &msm_soc_component, NULL, 0);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305560}
5561
5562static int msm_compr_remove(struct platform_device *pdev)
5563{
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305564 int i = 0;
5565 struct msm_compr_pdata *pdata = NULL;
5566
5567 pdata = dev_get_drvdata(&pdev->dev);
5568 if (pdata) {
5569 for (i = 0; i < MSM_FRONTEND_DAI_MM_SIZE; i++)
5570 kfree(pdata->chmixer_pspd[i]);
5571 }
Ajit Pandeyfa018862019-09-04 14:34:00 +05305572 mutex_destroy(&pdata->lock);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305573 kfree(pdata);
5574
Meng Wangee084a02018-09-04 16:11:58 +08005575 snd_soc_unregister_component(&pdev->dev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305576 return 0;
5577}
5578
5579static const struct of_device_id msm_compr_dt_match[] = {
5580 {.compatible = "qcom,msm-compress-dsp"},
5581 {}
5582};
5583MODULE_DEVICE_TABLE(of, msm_compr_dt_match);
5584
5585static struct platform_driver msm_compr_driver = {
5586 .driver = {
5587 .name = "msm-compress-dsp",
5588 .owner = THIS_MODULE,
5589 .of_match_table = msm_compr_dt_match,
Xiaojun Sang53cd13a2018-06-29 15:14:37 +08005590 .suppress_bind_attrs = true,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305591 },
5592 .probe = msm_compr_dev_probe,
5593 .remove = msm_compr_remove,
5594};
5595
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305596int __init msm_compress_dsp_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305597{
5598 return platform_driver_register(&msm_compr_driver);
5599}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305600
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05305601void msm_compress_dsp_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305602{
5603 platform_driver_unregister(&msm_compr_driver);
5604}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305605
5606MODULE_DESCRIPTION("Compress Offload platform driver");
5607MODULE_LICENSE("GPL v2");