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