blob: d9e0927bc0341df4ecded0658b3c418dafe22b1b [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;
3156
3157 pr_debug("%s\n", __func__);
3158
3159 if (!metadata || !cstream || !cstream->runtime)
3160 return ret;
3161
3162 if (metadata->key != SNDRV_COMPRESS_PATH_DELAY) {
3163 pr_err("%s, unsupported key %d\n", __func__, metadata->key);
3164 return ret;
3165 }
3166
3167 prtd = cstream->runtime->private_data;
3168 if (!prtd || !prtd->audio_client) {
3169 pr_err("%s: prtd or audio client is NULL\n", __func__);
3170 return ret;
3171 }
3172
3173 ac = prtd->audio_client;
3174 ret = q6asm_get_path_delay(prtd->audio_client);
3175 if (ret) {
3176 pr_err("%s: get_path_delay failed, ret=%d\n", __func__, ret);
3177 return ret;
3178 }
3179
3180 pr_debug("%s, path delay(in us) %u\n", __func__, ac->path_delay);
3181
3182 metadata->value[0] = ac->path_delay;
3183
3184 return ret;
3185}
3186
3187
3188static int msm_compr_set_next_track_param(struct snd_compr_stream *cstream,
3189 union snd_codec_options *codec_options)
3190{
3191 struct msm_compr_audio *prtd;
3192 struct audio_client *ac;
3193 int ret = 0;
3194
3195 if (!codec_options || !cstream)
3196 return -EINVAL;
3197
3198 prtd = cstream->runtime->private_data;
3199 if (!prtd || !prtd->audio_client) {
3200 pr_err("%s: prtd or audio client is NULL\n", __func__);
3201 return -EINVAL;
3202 }
3203
3204 ac = prtd->audio_client;
3205
3206 pr_debug("%s: got codec options for codec type %u",
3207 __func__, prtd->codec);
3208 switch (prtd->codec) {
3209 case FORMAT_WMA_V9:
3210 case FORMAT_WMA_V10PRO:
3211 case FORMAT_FLAC:
3212 case FORMAT_VORBIS:
3213 case FORMAT_ALAC:
3214 case FORMAT_APE:
3215 memcpy(&(prtd->gapless_state.codec_options),
3216 codec_options,
3217 sizeof(union snd_codec_options));
3218 ret = msm_compr_send_media_format_block(cstream,
3219 ac->stream_id, true);
3220 if (ret < 0) {
3221 pr_err("%s: failed to send media format block\n",
3222 __func__);
3223 }
3224 break;
3225
3226 default:
3227 pr_debug("%s: Ignore sending CMD Format block\n",
3228 __func__);
3229 break;
3230 }
3231
3232 return ret;
3233}
3234
3235static int msm_compr_volume_put(struct snd_kcontrol *kcontrol,
3236 struct snd_ctl_elem_value *ucontrol)
3237{
3238 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3239 unsigned long fe_id = kcontrol->private_value;
3240 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3241 snd_soc_component_get_drvdata(comp);
3242 struct snd_compr_stream *cstream = NULL;
3243 uint32_t *volume = NULL;
3244
3245 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3246 pr_err("%s Received out of bounds fe_id %lu\n",
3247 __func__, fe_id);
3248 return -EINVAL;
3249 }
3250
3251 cstream = pdata->cstream[fe_id];
3252 volume = pdata->volume[fe_id];
3253
3254 volume[0] = ucontrol->value.integer.value[0];
3255 volume[1] = ucontrol->value.integer.value[1];
3256 pr_debug("%s: fe_id %lu left_vol %d right_vol %d\n",
3257 __func__, fe_id, volume[0], volume[1]);
3258 if (cstream)
3259 msm_compr_set_volume(cstream, volume[0], volume[1]);
3260 return 0;
3261}
3262
3263static int msm_compr_volume_get(struct snd_kcontrol *kcontrol,
3264 struct snd_ctl_elem_value *ucontrol)
3265{
3266 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3267 unsigned long fe_id = kcontrol->private_value;
3268
3269 struct msm_compr_pdata *pdata =
3270 snd_soc_component_get_drvdata(comp);
3271 uint32_t *volume = NULL;
3272
3273 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3274 pr_err("%s Received out of bound fe_id %lu\n", __func__, fe_id);
3275 return -EINVAL;
3276 }
3277
3278 volume = pdata->volume[fe_id];
3279 pr_debug("%s: fe_id %lu\n", __func__, fe_id);
3280 ucontrol->value.integer.value[0] = volume[0];
3281 ucontrol->value.integer.value[1] = volume[1];
3282
3283 return 0;
3284}
3285
3286static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
3287 struct snd_ctl_elem_value *ucontrol)
3288{
3289 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3290 unsigned long fe_id = kcontrol->private_value;
3291 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3292 snd_soc_component_get_drvdata(comp);
3293 struct msm_compr_audio_effects *audio_effects = NULL;
3294 struct snd_compr_stream *cstream = NULL;
3295 struct msm_compr_audio *prtd = NULL;
3296 long *values = &(ucontrol->value.integer.value[0]);
3297 int effects_module;
3298
3299 pr_debug("%s\n", __func__);
3300 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3301 pr_err("%s Received out of bounds fe_id %lu\n",
3302 __func__, fe_id);
3303 return -EINVAL;
3304 }
3305 cstream = pdata->cstream[fe_id];
3306 audio_effects = pdata->audio_effects[fe_id];
3307 if (!cstream || !audio_effects) {
3308 pr_err("%s: stream or effects inactive\n", __func__);
3309 return -EINVAL;
3310 }
3311 prtd = cstream->runtime->private_data;
3312 if (!prtd) {
3313 pr_err("%s: cannot set audio effects\n", __func__);
3314 return -EINVAL;
3315 }
3316 if (prtd->compr_passthr != LEGACY_PCM) {
3317 pr_debug("%s: No effects for compr_type[%d]\n",
3318 __func__, prtd->compr_passthr);
3319 return 0;
3320 }
3321 pr_debug("%s: Effects supported for compr_type[%d]\n",
3322 __func__, prtd->compr_passthr);
3323
3324 effects_module = *values++;
3325 switch (effects_module) {
3326 case VIRTUALIZER_MODULE:
3327 pr_debug("%s: VIRTUALIZER_MODULE\n", __func__);
3328 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3329 prtd->audio_client->topology))
3330 msm_audio_effects_virtualizer_handler(
3331 prtd->audio_client,
3332 &(audio_effects->virtualizer),
3333 values);
3334 break;
3335 case REVERB_MODULE:
3336 pr_debug("%s: REVERB_MODULE\n", __func__);
3337 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3338 prtd->audio_client->topology))
3339 msm_audio_effects_reverb_handler(prtd->audio_client,
3340 &(audio_effects->reverb),
3341 values);
3342 break;
3343 case BASS_BOOST_MODULE:
3344 pr_debug("%s: BASS_BOOST_MODULE\n", __func__);
3345 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3346 prtd->audio_client->topology))
3347 msm_audio_effects_bass_boost_handler(prtd->audio_client,
3348 &(audio_effects->bass_boost),
3349 values);
3350 break;
3351 case PBE_MODULE:
3352 pr_debug("%s: PBE_MODULE\n", __func__);
3353 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3354 prtd->audio_client->topology))
3355 msm_audio_effects_pbe_handler(prtd->audio_client,
3356 &(audio_effects->pbe),
3357 values);
3358 break;
3359 case EQ_MODULE:
3360 pr_debug("%s: EQ_MODULE\n", __func__);
3361 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3362 prtd->audio_client->topology))
3363 msm_audio_effects_popless_eq_handler(prtd->audio_client,
3364 &(audio_effects->equalizer),
3365 values);
3366 break;
3367 case SOFT_VOLUME_MODULE:
3368 pr_debug("%s: SOFT_VOLUME_MODULE\n", __func__);
3369 break;
3370 case SOFT_VOLUME2_MODULE:
3371 pr_debug("%s: SOFT_VOLUME2_MODULE\n", __func__);
3372 if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
3373 prtd->audio_client->topology))
3374 msm_audio_effects_volume_handler_v2(prtd->audio_client,
3375 &(audio_effects->volume),
3376 values, SOFT_VOLUME_INSTANCE_2);
3377 break;
3378 default:
3379 pr_err("%s Invalid effects config module\n", __func__);
3380 return -EINVAL;
3381 }
3382 return 0;
3383}
3384
3385static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol,
3386 struct snd_ctl_elem_value *ucontrol)
3387{
3388 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3389 unsigned long fe_id = kcontrol->private_value;
3390 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3391 snd_soc_component_get_drvdata(comp);
3392 struct msm_compr_audio_effects *audio_effects = NULL;
3393 struct snd_compr_stream *cstream = NULL;
3394 struct msm_compr_audio *prtd = NULL;
3395
3396 pr_debug("%s\n", __func__);
3397 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3398 pr_err("%s Received out of bounds fe_id %lu\n",
3399 __func__, fe_id);
3400 return -EINVAL;
3401 }
3402 cstream = pdata->cstream[fe_id];
3403 audio_effects = pdata->audio_effects[fe_id];
3404 if (!cstream || !audio_effects) {
Vignesh Kulothungan2ce67842018-09-25 16:40:29 -07003405 pr_debug("%s: stream or effects inactive\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303406 return -EINVAL;
3407 }
3408 prtd = cstream->runtime->private_data;
3409 if (!prtd) {
3410 pr_err("%s: cannot set audio effects\n", __func__);
3411 return -EINVAL;
3412 }
3413
3414 return 0;
3415}
3416
3417static int msm_compr_query_audio_effect_put(struct snd_kcontrol *kcontrol,
3418 struct snd_ctl_elem_value *ucontrol)
3419{
3420 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3421 unsigned long fe_id = kcontrol->private_value;
3422 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3423 snd_soc_component_get_drvdata(comp);
3424 struct msm_compr_audio_effects *audio_effects = NULL;
3425 struct snd_compr_stream *cstream = NULL;
3426 struct msm_compr_audio *prtd = NULL;
3427 long *values = &(ucontrol->value.integer.value[0]);
3428
3429 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3430 pr_err("%s Received out of bounds fe_id %lu\n",
3431 __func__, fe_id);
3432 return -EINVAL;
3433 }
3434 cstream = pdata->cstream[fe_id];
3435 audio_effects = pdata->audio_effects[fe_id];
3436 if (!cstream || !audio_effects) {
3437 pr_err("%s: stream or effects inactive\n", __func__);
3438 return -EINVAL;
3439 }
3440 prtd = cstream->runtime->private_data;
3441 if (!prtd) {
3442 pr_err("%s: cannot set audio effects\n", __func__);
3443 return -EINVAL;
3444 }
3445 if (prtd->compr_passthr != LEGACY_PCM) {
3446 pr_err("%s: No effects for compr_type[%d]\n",
3447 __func__, prtd->compr_passthr);
3448 return -EPERM;
3449 }
3450 audio_effects->query.mod_id = (u32)*values++;
3451 audio_effects->query.parm_id = (u32)*values++;
3452 audio_effects->query.size = (u32)*values++;
3453 audio_effects->query.offset = (u32)*values++;
3454 audio_effects->query.device = (u32)*values++;
3455 return 0;
3456}
3457
3458static int msm_compr_query_audio_effect_get(struct snd_kcontrol *kcontrol,
3459 struct snd_ctl_elem_value *ucontrol)
3460{
3461 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3462 unsigned long fe_id = kcontrol->private_value;
3463 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3464 snd_soc_component_get_drvdata(comp);
3465 struct msm_compr_audio_effects *audio_effects = NULL;
3466 struct snd_compr_stream *cstream = NULL;
3467 struct msm_compr_audio *prtd = NULL;
3468 long *values = &(ucontrol->value.integer.value[0]);
3469
3470 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3471 pr_err("%s Received out of bounds fe_id %lu\n",
3472 __func__, fe_id);
3473 return -EINVAL;
3474 }
3475 cstream = pdata->cstream[fe_id];
3476 audio_effects = pdata->audio_effects[fe_id];
3477 if (!cstream || !audio_effects) {
3478 pr_debug("%s: stream or effects inactive\n", __func__);
3479 return -EINVAL;
3480 }
3481 prtd = cstream->runtime->private_data;
3482 if (!prtd) {
3483 pr_err("%s: cannot set audio effects\n", __func__);
3484 return -EINVAL;
3485 }
3486 values[0] = (long)audio_effects->query.mod_id;
3487 values[1] = (long)audio_effects->query.parm_id;
3488 values[2] = (long)audio_effects->query.size;
3489 values[3] = (long)audio_effects->query.offset;
3490 values[4] = (long)audio_effects->query.device;
3491 return 0;
3492}
3493
3494static int msm_compr_send_dec_params(struct snd_compr_stream *cstream,
3495 struct msm_compr_dec_params *dec_params,
3496 int stream_id)
3497{
3498
3499 int rc = 0;
3500 struct msm_compr_audio *prtd = NULL;
3501 struct snd_dec_ddp *ddp = &dec_params->ddp_params;
3502
3503 if (!cstream || !dec_params) {
3504 pr_err("%s: stream or dec_params inactive\n", __func__);
3505 rc = -EINVAL;
3506 goto end;
3507 }
3508 prtd = cstream->runtime->private_data;
3509 if (!prtd) {
3510 pr_err("%s: cannot set dec_params\n", __func__);
3511 rc = -EINVAL;
3512 goto end;
3513 }
3514 switch (prtd->codec) {
3515 case FORMAT_MP3:
3516 case FORMAT_MPEG4_AAC:
3517 case FORMAT_TRUEHD:
3518 case FORMAT_IEC61937:
3519 case FORMAT_APTX:
3520 pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
3521 prtd->codec);
3522 break;
3523 case FORMAT_AC3:
3524 case FORMAT_EAC3:
3525 if (prtd->compr_passthr != LEGACY_PCM) {
3526 pr_debug("%s: No DDP param for compr_type[%d]\n",
3527 __func__, prtd->compr_passthr);
3528 break;
3529 }
3530 rc = msm_compr_send_ddp_cfg(prtd->audio_client, ddp, stream_id);
3531 if (rc < 0)
3532 pr_err("%s: DDP CMD CFG failed %d\n", __func__, rc);
3533 break;
3534 default:
3535 break;
3536 }
3537end:
3538 return rc;
3539
3540}
3541static int msm_compr_dec_params_put(struct snd_kcontrol *kcontrol,
3542 struct snd_ctl_elem_value *ucontrol)
3543{
3544 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3545 unsigned long fe_id = kcontrol->private_value;
3546 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3547 snd_soc_component_get_drvdata(comp);
3548 struct msm_compr_dec_params *dec_params = NULL;
3549 struct snd_compr_stream *cstream = NULL;
3550 struct msm_compr_audio *prtd = NULL;
3551 long *values = &(ucontrol->value.integer.value[0]);
3552 int rc = 0;
3553
3554 pr_debug("%s\n", __func__);
3555 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3556 pr_err("%s Received out of bounds fe_id %lu\n",
3557 __func__, fe_id);
3558 rc = -EINVAL;
3559 goto end;
3560 }
3561
3562 cstream = pdata->cstream[fe_id];
3563 dec_params = pdata->dec_params[fe_id];
3564
3565 if (!cstream || !dec_params) {
3566 pr_err("%s: stream or dec_params inactive\n", __func__);
3567 rc = -EINVAL;
3568 goto end;
3569 }
3570 prtd = cstream->runtime->private_data;
3571 if (!prtd) {
3572 pr_err("%s: cannot set dec_params\n", __func__);
3573 rc = -EINVAL;
3574 goto end;
3575 }
3576
3577 switch (prtd->codec) {
3578 case FORMAT_MP3:
3579 case FORMAT_MPEG4_AAC:
3580 case FORMAT_FLAC:
3581 case FORMAT_VORBIS:
3582 case FORMAT_ALAC:
3583 case FORMAT_APE:
3584 case FORMAT_DTS:
3585 case FORMAT_DSD:
3586 case FORMAT_TRUEHD:
3587 case FORMAT_IEC61937:
3588 case FORMAT_APTX:
3589 pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
3590 prtd->codec);
3591 break;
3592 case FORMAT_AC3:
3593 case FORMAT_EAC3: {
3594 struct snd_dec_ddp *ddp = &dec_params->ddp_params;
3595 int cnt;
3596
3597 if (prtd->compr_passthr != LEGACY_PCM) {
3598 pr_debug("%s: No DDP param for compr_type[%d]\n",
3599 __func__, prtd->compr_passthr);
3600 break;
3601 }
3602
3603 ddp->params_length = (*values++);
3604 if (ddp->params_length > DDP_DEC_MAX_NUM_PARAM) {
3605 pr_err("%s: invalid num of params:: %d\n", __func__,
3606 ddp->params_length);
3607 rc = -EINVAL;
3608 goto end;
3609 }
3610 for (cnt = 0; cnt < ddp->params_length; cnt++) {
3611 ddp->params_id[cnt] = *values++;
3612 ddp->params_value[cnt] = *values++;
3613 }
3614 prtd = cstream->runtime->private_data;
3615 if (prtd && prtd->audio_client)
3616 rc = msm_compr_send_dec_params(cstream, dec_params,
3617 prtd->audio_client->stream_id);
3618 break;
3619 }
3620 default:
3621 break;
3622 }
3623end:
3624 pr_debug("%s: ret %d\n", __func__, rc);
3625 return rc;
3626}
3627
3628static int msm_compr_dec_params_get(struct snd_kcontrol *kcontrol,
3629 struct snd_ctl_elem_value *ucontrol)
3630{
3631 /* dummy function */
3632 return 0;
3633}
3634
3635static int msm_compr_playback_app_type_cfg_put(struct snd_kcontrol *kcontrol,
3636 struct snd_ctl_elem_value *ucontrol)
3637{
3638 u64 fe_id = kcontrol->private_value;
3639 int session_type = SESSION_TYPE_RX;
3640 int be_id = ucontrol->value.integer.value[3];
3641 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
3642 int ret = 0;
3643
3644 cfg_data.app_type = ucontrol->value.integer.value[0];
3645 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
3646 if (ucontrol->value.integer.value[2] != 0)
3647 cfg_data.sample_rate = ucontrol->value.integer.value[2];
3648 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
3649 __func__, fe_id, session_type, be_id,
3650 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3651 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
3652 be_id, &cfg_data);
3653 if (ret < 0)
3654 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
3655 __func__, ret);
3656
3657 return ret;
3658}
3659
3660static int msm_compr_playback_app_type_cfg_get(struct snd_kcontrol *kcontrol,
3661 struct snd_ctl_elem_value *ucontrol)
3662{
3663 u64 fe_id = kcontrol->private_value;
3664 int session_type = SESSION_TYPE_RX;
3665 int be_id = 0;
3666 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
3667 int ret = 0;
3668
3669 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
3670 &be_id, &cfg_data);
3671 if (ret < 0) {
3672 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
3673 __func__, ret);
3674 goto done;
3675 }
3676
3677 ucontrol->value.integer.value[0] = cfg_data.app_type;
3678 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
3679 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
3680 ucontrol->value.integer.value[3] = be_id;
3681 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
3682 __func__, fe_id, session_type, be_id,
3683 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3684done:
3685 return ret;
3686}
3687
3688static int msm_compr_capture_app_type_cfg_put(struct snd_kcontrol *kcontrol,
3689 struct snd_ctl_elem_value *ucontrol)
3690{
3691 u64 fe_id = kcontrol->private_value;
3692 int session_type = SESSION_TYPE_TX;
3693 int be_id = ucontrol->value.integer.value[3];
3694 struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
3695 int ret = 0;
3696
3697 cfg_data.app_type = ucontrol->value.integer.value[0];
3698 cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
3699 if (ucontrol->value.integer.value[2] != 0)
3700 cfg_data.sample_rate = ucontrol->value.integer.value[2];
3701 pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
3702 __func__, fe_id, session_type, be_id,
3703 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3704 ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
3705 be_id, &cfg_data);
3706 if (ret < 0)
3707 pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
3708 __func__, ret);
3709
3710 return ret;
3711}
3712
3713static int msm_compr_capture_app_type_cfg_get(struct snd_kcontrol *kcontrol,
3714 struct snd_ctl_elem_value *ucontrol)
3715{
3716 u64 fe_id = kcontrol->private_value;
3717 int session_type = SESSION_TYPE_TX;
3718 int be_id = 0;
3719 struct msm_pcm_stream_app_type_cfg cfg_data = {0};
3720 int ret = 0;
3721
3722 ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
3723 &be_id, &cfg_data);
3724 if (ret < 0) {
3725 pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
3726 __func__, ret);
3727 goto done;
3728 }
3729
3730 ucontrol->value.integer.value[0] = cfg_data.app_type;
3731 ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
3732 ucontrol->value.integer.value[2] = cfg_data.sample_rate;
3733 ucontrol->value.integer.value[3] = be_id;
3734 pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
3735 __func__, fe_id, session_type, be_id,
3736 cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
3737done:
3738 return ret;
3739}
3740
3741static int msm_compr_channel_map_put(struct snd_kcontrol *kcontrol,
3742 struct snd_ctl_elem_value *ucontrol)
3743{
3744 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3745 u64 fe_id = kcontrol->private_value;
3746 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3747 snd_soc_component_get_drvdata(comp);
3748 int rc = 0, i;
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05303749 struct msm_pcm_channel_mixer *chmixer_pspd = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303750
3751 pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
3752
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05303753 if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303754 pr_err("%s Received out of bounds fe_id %llu\n",
3755 __func__, fe_id);
3756 rc = -EINVAL;
3757 goto end;
3758 }
3759
3760 if (pdata->ch_map[fe_id]) {
3761 pdata->ch_map[fe_id]->set_ch_map = true;
Dieter Lueckingceef9af2018-09-28 15:09:32 +02003762 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303763 pdata->ch_map[fe_id]->channel_map[i] =
3764 (char)(ucontrol->value.integer.value[i]);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05303765
3766 /* update chmixer_pspd chmap cached with routing driver as well */
3767 chmixer_pspd = pdata->chmixer_pspd[fe_id];
3768 if (chmixer_pspd && chmixer_pspd->enable) {
3769 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
3770 chmixer_pspd->in_ch_map[i] =
3771 pdata->ch_map[fe_id]->channel_map[i];
3772 chmixer_pspd->override_in_ch_map = true;
3773 msm_pcm_routing_set_channel_mixer_cfg(fe_id,
3774 SESSION_TYPE_RX, chmixer_pspd);
3775 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303776 } else {
3777 pr_debug("%s: no memory for ch_map, default will be set\n",
3778 __func__);
3779 }
3780end:
3781 pr_debug("%s: ret %d\n", __func__, rc);
3782 return rc;
3783}
3784
3785static int msm_compr_channel_map_get(struct snd_kcontrol *kcontrol,
3786 struct snd_ctl_elem_value *ucontrol)
3787{
3788 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3789 u64 fe_id = kcontrol->private_value;
3790 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3791 snd_soc_component_get_drvdata(comp);
3792 int rc = 0, i;
3793
3794 pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05303795 if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303796 pr_err("%s: Received out of bounds fe_id %llu\n",
3797 __func__, fe_id);
3798 rc = -EINVAL;
3799 goto end;
3800 }
3801 if (pdata->ch_map[fe_id]) {
Dieter Lueckingceef9af2018-09-28 15:09:32 +02003802 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303803 ucontrol->value.integer.value[i] =
3804 pdata->ch_map[fe_id]->channel_map[i];
3805 }
3806end:
3807 pr_debug("%s: ret %d\n", __func__, rc);
3808 return rc;
3809}
3810
3811static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
3812 struct snd_ctl_elem_value *ucontrol)
3813{
3814 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3815 unsigned long fe_id = kcontrol->private_value;
3816 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3817 snd_soc_component_get_drvdata(comp);
3818 struct snd_compr_stream *cstream = NULL;
3819 struct msm_compr_audio *prtd;
3820 int ret = 0;
3821 struct msm_adsp_event_data *event_data = NULL;
3822
3823 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3824 pr_err("%s Received invalid fe_id %lu\n",
3825 __func__, fe_id);
3826 ret = -EINVAL;
3827 goto done;
3828 }
3829
3830 cstream = pdata->cstream[fe_id];
3831 if (cstream == NULL) {
3832 pr_err("%s cstream is null\n", __func__);
3833 ret = -EINVAL;
3834 goto done;
3835 }
3836
3837 prtd = cstream->runtime->private_data;
3838 if (!prtd) {
3839 pr_err("%s: prtd is null\n", __func__);
3840 ret = -EINVAL;
3841 goto done;
3842 }
3843
3844 if (prtd->audio_client == NULL) {
3845 pr_err("%s: audio_client is null\n", __func__);
3846 ret = -EINVAL;
3847 goto done;
3848 }
3849
3850 event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data;
3851 if ((event_data->event_type < ADSP_STREAM_PP_EVENT) ||
3852 (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) {
3853 pr_err("%s: invalid event_type=%d",
3854 __func__, event_data->event_type);
3855 ret = -EINVAL;
3856 goto done;
3857 }
3858
Xiaojun Sang75642c32018-03-23 08:57:33 +08003859 if (event_data->payload_len > sizeof(ucontrol->value.bytes.data)
3860 - sizeof(struct msm_adsp_event_data)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303861 pr_err("%s param length=%d exceeds limit",
3862 __func__, event_data->payload_len);
3863 ret = -EINVAL;
3864 goto done;
3865 }
3866
3867 ret = q6asm_send_stream_cmd(prtd->audio_client, event_data);
3868 if (ret < 0)
3869 pr_err("%s: failed to send stream event cmd, err = %d\n",
3870 __func__, ret);
3871done:
3872 return ret;
3873}
3874
3875static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
3876 struct snd_ctl_elem_value *ucontrol)
3877{
3878 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3879 unsigned long fe_id = kcontrol->private_value;
3880 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3881 snd_soc_component_get_drvdata(comp);
3882 struct snd_compr_stream *cstream = NULL;
3883 struct msm_compr_audio *prtd;
3884 int fd;
3885 int ret = 0;
3886
3887 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3888 pr_err("%s Received out of bounds invalid fe_id %lu\n",
3889 __func__, fe_id);
3890 ret = -EINVAL;
3891 goto done;
3892 }
3893
3894 cstream = pdata->cstream[fe_id];
3895 if (cstream == NULL) {
3896 pr_err("%s cstream is null\n", __func__);
3897 ret = -EINVAL;
3898 goto done;
3899 }
3900
3901 prtd = cstream->runtime->private_data;
3902 if (!prtd) {
3903 pr_err("%s: prtd is null\n", __func__);
3904 ret = -EINVAL;
3905 goto done;
3906 }
3907
3908 if (prtd->audio_client == NULL) {
3909 pr_err("%s: audio_client is null\n", __func__);
3910 ret = -EINVAL;
3911 goto done;
3912 }
3913
3914 memcpy(&fd, ucontrol->value.bytes.data, sizeof(fd));
3915 ret = q6asm_send_ion_fd(prtd->audio_client, fd);
3916 if (ret < 0)
3917 pr_err("%s: failed to register ion fd\n", __func__);
3918done:
3919 return ret;
3920}
3921
3922static int msm_compr_rtic_event_ack_put(struct snd_kcontrol *kcontrol,
3923 struct snd_ctl_elem_value *ucontrol)
3924{
3925 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3926 unsigned long fe_id = kcontrol->private_value;
3927 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3928 snd_soc_component_get_drvdata(comp);
3929 struct snd_compr_stream *cstream = NULL;
3930 struct msm_compr_audio *prtd;
3931 int ret = 0;
3932 int param_length = 0;
3933
3934 if (fe_id >= MSM_FRONTEND_DAI_MAX) {
3935 pr_err("%s Received invalid fe_id %lu\n",
3936 __func__, fe_id);
3937 ret = -EINVAL;
3938 goto done;
3939 }
3940
3941 cstream = pdata->cstream[fe_id];
3942 if (cstream == NULL) {
3943 pr_err("%s cstream is null\n", __func__);
3944 ret = -EINVAL;
3945 goto done;
3946 }
3947
3948 prtd = cstream->runtime->private_data;
3949 if (!prtd) {
3950 pr_err("%s: prtd is null\n", __func__);
3951 ret = -EINVAL;
3952 goto done;
3953 }
3954
3955 if (prtd->audio_client == NULL) {
3956 pr_err("%s: audio_client is null\n", __func__);
3957 ret = -EINVAL;
3958 goto done;
3959 }
3960
3961 memcpy(&param_length, ucontrol->value.bytes.data,
3962 sizeof(param_length));
3963 if ((param_length + sizeof(param_length))
3964 >= sizeof(ucontrol->value.bytes.data)) {
3965 pr_err("%s param length=%d exceeds limit",
3966 __func__, param_length);
3967 ret = -EINVAL;
3968 goto done;
3969 }
3970
3971 ret = q6asm_send_rtic_event_ack(prtd->audio_client,
3972 ucontrol->value.bytes.data + sizeof(param_length),
3973 param_length);
3974 if (ret < 0)
3975 pr_err("%s: failed to send rtic event ack, err = %d\n",
3976 __func__, ret);
3977done:
3978 return ret;
3979}
3980
3981static int msm_compr_gapless_put(struct snd_kcontrol *kcontrol,
3982 struct snd_ctl_elem_value *ucontrol)
3983{
3984 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3985 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
3986 snd_soc_component_get_drvdata(comp);
3987 pdata->use_dsp_gapless_mode = ucontrol->value.integer.value[0];
3988 pr_debug("%s: value: %ld\n", __func__,
3989 ucontrol->value.integer.value[0]);
3990
3991 return 0;
3992}
3993
3994static int msm_compr_gapless_get(struct snd_kcontrol *kcontrol,
3995 struct snd_ctl_elem_value *ucontrol)
3996{
3997 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
3998 struct msm_compr_pdata *pdata =
3999 snd_soc_component_get_drvdata(comp);
4000 pr_debug("%s:gapless mode %d\n", __func__, pdata->use_dsp_gapless_mode);
4001 ucontrol->value.integer.value[0] = pdata->use_dsp_gapless_mode;
4002
4003 return 0;
4004}
4005
4006static const struct snd_kcontrol_new msm_compr_gapless_controls[] = {
4007 SOC_SINGLE_EXT("Compress Gapless Playback",
4008 0, 0, 1, 0,
4009 msm_compr_gapless_get,
4010 msm_compr_gapless_put),
4011};
4012
Meng Wangee084a02018-09-04 16:11:58 +08004013static int msm_compr_probe(struct snd_soc_component *component)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304014{
4015 struct msm_compr_pdata *pdata;
4016 int i;
4017 int rc;
4018 const char *qdsp_version;
4019
4020 pr_debug("%s\n", __func__);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304021 pdata = (struct msm_compr_pdata *) dev_get_drvdata(component->dev);
4022 if (!pdata) {
4023 pr_err("%s platform data not set\n", __func__);
4024 return -EINVAL;
4025 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304026
Meng Wangee084a02018-09-04 16:11:58 +08004027 snd_soc_component_set_drvdata(component, pdata);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304028
4029 for (i = 0; i < MSM_FRONTEND_DAI_MAX; i++) {
4030 pdata->volume[i][0] = COMPRESSED_LR_VOL_MAX_STEPS;
4031 pdata->volume[i][1] = COMPRESSED_LR_VOL_MAX_STEPS;
4032 pdata->audio_effects[i] = NULL;
4033 pdata->dec_params[i] = NULL;
4034 pdata->cstream[i] = NULL;
4035 pdata->ch_map[i] = NULL;
Aditya Bavanari9deef912017-11-20 13:31:31 +05304036 pdata->is_in_use[i] = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304037 }
4038
Meng Wangee084a02018-09-04 16:11:58 +08004039 snd_soc_add_component_controls(component, msm_compr_gapless_controls,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304040 ARRAY_SIZE(msm_compr_gapless_controls));
4041
Meng Wangee084a02018-09-04 16:11:58 +08004042 rc = of_property_read_string(component->dev->of_node,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304043 "qcom,adsp-version", &qdsp_version);
4044 if (!rc) {
4045 if (!strcmp(qdsp_version, "MDSP 1.2"))
4046 pdata->use_legacy_api = true;
4047 else
4048 pdata->use_legacy_api = false;
4049 } else
4050 pdata->use_legacy_api = false;
4051
4052 pr_debug("%s: use legacy api %d\n", __func__, pdata->use_legacy_api);
4053 /*
4054 * use_dsp_gapless_mode part of platform data(pdata) is updated from HAL
4055 * through a mixer control before compress driver is opened. The mixer
4056 * control is used to decide if dsp gapless mode needs to be enabled.
4057 * Gapless is disabled by default.
4058 */
4059 pdata->use_dsp_gapless_mode = false;
4060 return 0;
4061}
4062
4063static int msm_compr_volume_info(struct snd_kcontrol *kcontrol,
4064 struct snd_ctl_elem_info *uinfo)
4065{
4066 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4067 uinfo->count = 2;
4068 uinfo->value.integer.min = 0;
4069 uinfo->value.integer.max = COMPRESSED_LR_VOL_MAX_STEPS;
4070 return 0;
4071}
4072
4073static int msm_compr_audio_effects_config_info(struct snd_kcontrol *kcontrol,
4074 struct snd_ctl_elem_info *uinfo)
4075{
4076 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4077 uinfo->count = MAX_PP_PARAMS_SZ;
4078 uinfo->value.integer.min = 0;
4079 uinfo->value.integer.max = 0xFFFFFFFF;
4080 return 0;
4081}
4082
4083static int msm_compr_query_audio_effect_info(struct snd_kcontrol *kcontrol,
4084 struct snd_ctl_elem_info *uinfo)
4085{
4086 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4087 uinfo->count = 128;
4088 uinfo->value.integer.min = 0;
4089 uinfo->value.integer.max = 0xFFFFFFFF;
4090 return 0;
4091}
4092
4093static int msm_compr_dec_params_info(struct snd_kcontrol *kcontrol,
4094 struct snd_ctl_elem_info *uinfo)
4095{
4096 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4097 uinfo->count = 128;
4098 uinfo->value.integer.min = 0;
4099 uinfo->value.integer.max = 0xFFFFFFFF;
4100 return 0;
4101}
4102
4103static int msm_compr_app_type_cfg_info(struct snd_kcontrol *kcontrol,
4104 struct snd_ctl_elem_info *uinfo)
4105{
4106 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4107 uinfo->count = 5;
4108 uinfo->value.integer.min = 0;
4109 uinfo->value.integer.max = 0xFFFFFFFF;
4110 return 0;
4111}
4112
4113static int msm_compr_channel_map_info(struct snd_kcontrol *kcontrol,
4114 struct snd_ctl_elem_info *uinfo)
4115{
4116 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
Dieter Lueckingceef9af2018-09-28 15:09:32 +02004117 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304118 uinfo->value.integer.min = 0;
Ralf Herz49c325c2018-12-20 11:23:22 +01004119 /* See PCM_CHANNEL_UNUSED=47 in apr_audio-v2.h */
4120 uinfo->value.integer.max = 47;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304121 return 0;
4122}
4123
4124static int msm_compr_add_volume_control(struct snd_soc_pcm_runtime *rtd)
4125{
Meng Wangee084a02018-09-04 16:11:58 +08004126 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304127 const char *mixer_ctl_name = "Compress Playback";
4128 const char *deviceNo = "NN";
4129 const char *suffix = "Volume";
4130 char *mixer_str = NULL;
4131 int ctl_len;
4132 struct snd_kcontrol_new fe_volume_control[1] = {
4133 {
4134 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4135 .name = "?",
4136 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
4137 SNDRV_CTL_ELEM_ACCESS_READWRITE,
4138 .info = msm_compr_volume_info,
4139 .tlv.p = msm_compr_vol_gain,
4140 .get = msm_compr_volume_get,
4141 .put = msm_compr_volume_put,
4142 .private_value = 0,
4143 }
4144 };
4145
4146 if (!rtd) {
4147 pr_err("%s NULL rtd\n", __func__);
4148 return 0;
4149 }
Meng Wangee084a02018-09-04 16:11:58 +08004150 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4151 if (!component) {
4152 pr_err("%s: component is NULL\n", __func__);
4153 return 0;
4154 }
4155
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304156 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4157 __func__, rtd->dai_link->name, rtd->dai_link->id,
4158 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4159 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
4160 strlen(suffix) + 1;
4161 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4162 if (!mixer_str) {
4163 pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
4164 return 0;
4165 }
4166 snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
4167 rtd->pcm->device, suffix);
4168 fe_volume_control[0].name = mixer_str;
4169 fe_volume_control[0].private_value = rtd->dai_link->id;
4170 pr_debug("Registering new mixer ctl %s", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004171 snd_soc_add_component_controls(component, fe_volume_control,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304172 ARRAY_SIZE(fe_volume_control));
4173 kfree(mixer_str);
4174 return 0;
4175}
4176
4177static int msm_compr_add_audio_effects_control(struct snd_soc_pcm_runtime *rtd)
4178{
Meng Wangee084a02018-09-04 16:11:58 +08004179 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304180 const char *mixer_ctl_name = "Audio Effects Config";
4181 const char *deviceNo = "NN";
4182 char *mixer_str = NULL;
4183 int ctl_len;
4184 struct snd_kcontrol_new fe_audio_effects_config_control[1] = {
4185 {
4186 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4187 .name = "?",
4188 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4189 .info = msm_compr_audio_effects_config_info,
4190 .get = msm_compr_audio_effects_config_get,
4191 .put = msm_compr_audio_effects_config_put,
4192 .private_value = 0,
4193 }
4194 };
4195
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304196 if (!rtd) {
4197 pr_err("%s NULL rtd\n", __func__);
4198 return 0;
4199 }
4200
Meng Wangee084a02018-09-04 16:11:58 +08004201 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4202 if (!component) {
4203 pr_err("%s: component is NULL\n", __func__);
4204 return 0;
4205 }
4206
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304207 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4208 __func__, rtd->dai_link->name, rtd->dai_link->id,
4209 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4210
4211 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4212 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4213
4214 if (!mixer_str)
4215 return 0;
4216
4217 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4218
4219 fe_audio_effects_config_control[0].name = mixer_str;
4220 fe_audio_effects_config_control[0].private_value = rtd->dai_link->id;
4221 pr_debug("Registering new mixer ctl %s\n", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004222 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304223 fe_audio_effects_config_control,
4224 ARRAY_SIZE(fe_audio_effects_config_control));
4225 kfree(mixer_str);
4226 return 0;
4227}
4228
4229static int msm_compr_add_query_audio_effect_control(
4230 struct snd_soc_pcm_runtime *rtd)
4231{
Meng Wangee084a02018-09-04 16:11:58 +08004232 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304233 const char *mixer_ctl_name = "Query Audio Effect Param";
4234 const char *deviceNo = "NN";
4235 char *mixer_str = NULL;
4236 int ctl_len;
4237 struct snd_kcontrol_new fe_query_audio_effect_control[1] = {
4238 {
4239 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4240 .name = "?",
4241 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4242 .info = msm_compr_query_audio_effect_info,
4243 .get = msm_compr_query_audio_effect_get,
4244 .put = msm_compr_query_audio_effect_put,
4245 .private_value = 0,
4246 }
4247 };
4248 if (!rtd) {
4249 pr_err("%s NULL rtd\n", __func__);
4250 return 0;
4251 }
Meng Wangee084a02018-09-04 16:11:58 +08004252
4253 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4254 if (!component) {
4255 pr_err("%s: component is NULL\n", __func__);
4256 return 0;
4257 }
4258
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304259 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4260 __func__, rtd->dai_link->name, rtd->dai_link->id,
4261 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4262 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4263 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4264 if (!mixer_str) {
4265 pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
4266 return 0;
4267 }
4268 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4269 fe_query_audio_effect_control[0].name = mixer_str;
4270 fe_query_audio_effect_control[0].private_value = rtd->dai_link->id;
4271 pr_debug("%s: registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004272 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304273 fe_query_audio_effect_control,
4274 ARRAY_SIZE(fe_query_audio_effect_control));
4275 kfree(mixer_str);
4276 return 0;
4277}
4278
4279static int msm_compr_add_audio_adsp_stream_cmd_control(
4280 struct snd_soc_pcm_runtime *rtd)
4281{
Meng Wangee084a02018-09-04 16:11:58 +08004282 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304283 const char *mixer_ctl_name = DSP_STREAM_CMD;
4284 const char *deviceNo = "NN";
4285 char *mixer_str = NULL;
4286 int ctl_len = 0, ret = 0;
4287 struct snd_kcontrol_new fe_audio_adsp_stream_cmd_config_control[1] = {
4288 {
4289 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4290 .name = "?",
4291 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4292 .info = msm_adsp_stream_cmd_info,
4293 .put = msm_compr_adsp_stream_cmd_put,
4294 .private_value = 0,
4295 }
4296 };
4297
4298 if (!rtd) {
4299 pr_err("%s NULL rtd\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08004300 return -EINVAL;
4301 }
4302
4303 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4304 if (!component) {
4305 pr_err("%s: component is NULL\n", __func__);
4306 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304307 }
4308
4309 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4310 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08004311 if (!mixer_str)
4312 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304313
4314 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4315 fe_audio_adsp_stream_cmd_config_control[0].name = mixer_str;
4316 fe_audio_adsp_stream_cmd_config_control[0].private_value =
4317 rtd->dai_link->id;
4318 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004319 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304320 fe_audio_adsp_stream_cmd_config_control,
4321 ARRAY_SIZE(fe_audio_adsp_stream_cmd_config_control));
4322 if (ret < 0)
4323 pr_err("%s: failed to add ctl %s. err = %d\n",
4324 __func__, mixer_str, ret);
4325
4326 kfree(mixer_str);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304327 return ret;
4328}
4329
4330static int msm_compr_add_audio_adsp_stream_callback_control(
4331 struct snd_soc_pcm_runtime *rtd)
4332{
Meng Wangee084a02018-09-04 16:11:58 +08004333 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304334 const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
4335 const char *deviceNo = "NN";
4336 char *mixer_str = NULL;
4337 int ctl_len = 0, ret = 0;
4338 struct snd_kcontrol *kctl;
4339
4340 struct snd_kcontrol_new fe_audio_adsp_callback_config_control[1] = {
4341 {
4342 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4343 .name = "?",
4344 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4345 .info = msm_adsp_stream_callback_info,
4346 .get = msm_adsp_stream_callback_get,
4347 .private_value = 0,
4348 }
4349 };
4350
4351 if (!rtd) {
4352 pr_err("%s: rtd is NULL\n", __func__);
4353 ret = -EINVAL;
4354 goto done;
4355 }
4356
Meng Wangee084a02018-09-04 16:11:58 +08004357 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4358 if (!component) {
4359 pr_err("%s: component is NULL\n", __func__);
4360 return -EINVAL;
4361 }
4362
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304363 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4364 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4365 if (!mixer_str) {
4366 ret = -ENOMEM;
4367 goto done;
4368 }
4369
4370 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4371 fe_audio_adsp_callback_config_control[0].name = mixer_str;
4372 fe_audio_adsp_callback_config_control[0].private_value =
4373 rtd->dai_link->id;
4374 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004375 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304376 fe_audio_adsp_callback_config_control,
4377 ARRAY_SIZE(fe_audio_adsp_callback_config_control));
4378 if (ret < 0) {
4379 pr_err("%s: failed to add ctl %s. err = %d\n",
4380 __func__, mixer_str, ret);
4381 ret = -EINVAL;
4382 goto free_mixer_str;
4383 }
4384
4385 kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
4386 if (!kctl) {
4387 pr_err("%s: failed to get kctl %s.\n", __func__, mixer_str);
4388 ret = -EINVAL;
4389 goto free_mixer_str;
4390 }
4391
4392 kctl->private_data = NULL;
4393
4394free_mixer_str:
4395 kfree(mixer_str);
4396done:
4397 return ret;
4398}
4399
4400static int msm_compr_add_dec_runtime_params_control(
4401 struct snd_soc_pcm_runtime *rtd)
4402{
Meng Wangee084a02018-09-04 16:11:58 +08004403 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304404 const char *mixer_ctl_name = "Audio Stream";
4405 const char *deviceNo = "NN";
4406 const char *suffix = "Dec Params";
4407 char *mixer_str = NULL;
4408 int ctl_len;
4409 struct snd_kcontrol_new fe_dec_params_control[1] = {
4410 {
4411 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4412 .name = "?",
4413 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4414 .info = msm_compr_dec_params_info,
4415 .get = msm_compr_dec_params_get,
4416 .put = msm_compr_dec_params_put,
4417 .private_value = 0,
4418 }
4419 };
4420
4421 if (!rtd) {
4422 pr_err("%s NULL rtd\n", __func__);
4423 return 0;
4424 }
4425
Meng Wangee084a02018-09-04 16:11:58 +08004426 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4427 if (!component) {
4428 pr_err("%s: component is NULL\n", __func__);
4429 return 0;
4430 }
4431
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304432 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4433 __func__, rtd->dai_link->name, rtd->dai_link->id,
4434 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4435
4436 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
4437 strlen(suffix) + 1;
4438 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4439
4440 if (!mixer_str)
4441 return 0;
4442
4443 snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
4444 rtd->pcm->device, suffix);
4445
4446 fe_dec_params_control[0].name = mixer_str;
4447 fe_dec_params_control[0].private_value = rtd->dai_link->id;
4448 pr_debug("Registering new mixer ctl %s", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004449 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304450 fe_dec_params_control,
4451 ARRAY_SIZE(fe_dec_params_control));
4452 kfree(mixer_str);
4453 return 0;
4454}
4455
4456static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
4457{
Meng Wangee084a02018-09-04 16:11:58 +08004458 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304459 const char *playback_mixer_ctl_name = "Audio Stream";
4460 const char *capture_mixer_ctl_name = "Audio Stream Capture";
4461 const char *deviceNo = "NN";
4462 const char *suffix = "App Type Cfg";
4463 char *mixer_str = NULL;
4464 int ctl_len;
4465 struct snd_kcontrol_new fe_app_type_cfg_control[1] = {
4466 {
4467 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4468 .name = "?",
4469 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4470 .info = msm_compr_app_type_cfg_info,
4471 .put = msm_compr_playback_app_type_cfg_put,
4472 .get = msm_compr_playback_app_type_cfg_get,
4473 .private_value = 0,
4474 }
4475 };
4476
4477 if (!rtd) {
4478 pr_err("%s NULL rtd\n", __func__);
4479 return 0;
4480 }
4481
Meng Wangee084a02018-09-04 16:11:58 +08004482 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4483 if (!component) {
4484 pr_err("%s: component is NULL\n", __func__);
4485 return 0;
4486 }
4487
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304488 pr_debug("%s: added new compr FE ctl with name %s, id %d, cpu dai %s, device no %d\n",
4489 __func__, rtd->dai_link->name, rtd->dai_link->id,
4490 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4491 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
4492 ctl_len = strlen(playback_mixer_ctl_name) + 1 + strlen(deviceNo)
4493 + 1 + strlen(suffix) + 1;
4494 else
4495 ctl_len = strlen(capture_mixer_ctl_name) + 1 + strlen(deviceNo)
4496 + 1 + strlen(suffix) + 1;
4497
4498 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4499
4500 if (!mixer_str)
4501 return 0;
4502
4503 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
4504 snprintf(mixer_str, ctl_len, "%s %d %s",
4505 playback_mixer_ctl_name, rtd->pcm->device, suffix);
4506 else
4507 snprintf(mixer_str, ctl_len, "%s %d %s",
4508 capture_mixer_ctl_name, rtd->pcm->device, suffix);
4509
4510 fe_app_type_cfg_control[0].name = mixer_str;
4511 fe_app_type_cfg_control[0].private_value = rtd->dai_link->id;
4512
4513 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
4514 fe_app_type_cfg_control[0].put =
4515 msm_compr_playback_app_type_cfg_put;
4516 fe_app_type_cfg_control[0].get =
4517 msm_compr_playback_app_type_cfg_get;
4518 } else {
4519 fe_app_type_cfg_control[0].put =
4520 msm_compr_capture_app_type_cfg_put;
4521 fe_app_type_cfg_control[0].get =
4522 msm_compr_capture_app_type_cfg_get;
4523 }
4524 pr_debug("Registering new mixer ctl %s", mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004525 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304526 fe_app_type_cfg_control,
4527 ARRAY_SIZE(fe_app_type_cfg_control));
4528 kfree(mixer_str);
4529 return 0;
4530}
4531
4532static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
4533{
Meng Wangee084a02018-09-04 16:11:58 +08004534 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304535 const char *mixer_ctl_name = "Playback Channel Map";
4536 const char *deviceNo = "NN";
4537 char *mixer_str = NULL;
4538 struct msm_compr_pdata *pdata = NULL;
4539 int ctl_len;
4540 struct snd_kcontrol_new fe_channel_map_control[1] = {
4541 {
4542 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4543 .name = "?",
4544 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4545 .info = msm_compr_channel_map_info,
4546 .get = msm_compr_channel_map_get,
4547 .put = msm_compr_channel_map_put,
4548 .private_value = 0,
4549 }
4550 };
4551
4552 if (!rtd) {
4553 pr_err("%s: NULL rtd\n", __func__);
4554 return -EINVAL;
4555 }
4556
Meng Wangee084a02018-09-04 16:11:58 +08004557 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4558 if (!component) {
4559 pr_err("%s: component is NULL\n", __func__);
4560 return -EINVAL;
4561 }
4562
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304563 pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
4564 __func__, rtd->dai_link->name, rtd->dai_link->id,
4565 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
4566
4567 ctl_len = strlen(mixer_ctl_name) + strlen(deviceNo) + 1;
4568 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
4569
4570 if (!mixer_str)
4571 return -ENOMEM;
4572
4573 snprintf(mixer_str, ctl_len, "%s%d", mixer_ctl_name, rtd->pcm->device);
4574
4575 fe_channel_map_control[0].name = mixer_str;
4576 fe_channel_map_control[0].private_value = rtd->dai_link->id;
4577 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004578 snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304579 fe_channel_map_control,
4580 ARRAY_SIZE(fe_channel_map_control));
4581
Meng Wangee084a02018-09-04 16:11:58 +08004582 pdata = snd_soc_component_get_drvdata(component);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304583 pdata->ch_map[rtd->dai_link->id] =
4584 kzalloc(sizeof(struct msm_compr_ch_map), GFP_KERNEL);
4585 if (!pdata->ch_map[rtd->dai_link->id]) {
4586 pr_err("%s: Could not allocate memory for channel map\n",
4587 __func__);
4588 kfree(mixer_str);
4589 return -ENOMEM;
4590 }
4591 kfree(mixer_str);
4592 return 0;
4593}
4594
4595static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
4596{
Meng Wangee084a02018-09-04 16:11:58 +08004597 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304598 const char *mixer_ctl_name = "Playback ION FD";
4599 const char *deviceNo = "NN";
4600 char *mixer_str = NULL;
4601 int ctl_len = 0, ret = 0;
4602 struct snd_kcontrol_new fe_ion_fd_config_control[1] = {
4603 {
4604 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4605 .name = "?",
4606 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4607 .info = msm_adsp_stream_cmd_info,
4608 .put = msm_compr_ion_fd_map_put,
4609 .private_value = 0,
4610 }
4611 };
4612
4613 if (!rtd) {
4614 pr_err("%s NULL rtd\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08004615 return -EINVAL;
4616 }
4617
4618 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4619 if (!component) {
4620 pr_err("%s: component is NULL\n", __func__);
4621 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304622 }
4623
4624 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4625 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08004626 if (!mixer_str)
4627 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304628
4629 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4630 fe_ion_fd_config_control[0].name = mixer_str;
4631 fe_ion_fd_config_control[0].private_value = rtd->dai_link->id;
4632 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004633 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304634 fe_ion_fd_config_control,
4635 ARRAY_SIZE(fe_ion_fd_config_control));
4636 if (ret < 0)
4637 pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
4638
4639 kfree(mixer_str);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304640 return ret;
4641}
4642
4643static int msm_compr_add_event_ack_cmd_control(struct snd_soc_pcm_runtime *rtd)
4644{
Meng Wangee084a02018-09-04 16:11:58 +08004645 struct snd_soc_component *component = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304646 const char *mixer_ctl_name = "Playback Event Ack";
4647 const char *deviceNo = "NN";
4648 char *mixer_str = NULL;
4649 int ctl_len = 0, ret = 0;
4650 struct snd_kcontrol_new fe_event_ack_config_control[1] = {
4651 {
4652 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4653 .name = "?",
4654 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4655 .info = msm_adsp_stream_cmd_info,
4656 .put = msm_compr_rtic_event_ack_put,
4657 .private_value = 0,
4658 }
4659 };
4660
4661 if (!rtd) {
4662 pr_err("%s NULL rtd\n", __func__);
Meng Wangee084a02018-09-04 16:11:58 +08004663 return -EINVAL;
4664 }
4665
4666 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
4667 if (!component) {
4668 pr_err("%s: component is NULL\n", __func__);
4669 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304670 }
4671
4672 ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
4673 mixer_str = kzalloc(ctl_len, GFP_KERNEL);
Meng Wangee084a02018-09-04 16:11:58 +08004674 if (!mixer_str)
4675 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304676
4677 snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
4678 fe_event_ack_config_control[0].name = mixer_str;
4679 fe_event_ack_config_control[0].private_value = rtd->dai_link->id;
4680 pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
Meng Wangee084a02018-09-04 16:11:58 +08004681 ret = snd_soc_add_component_controls(component,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304682 fe_event_ack_config_control,
4683 ARRAY_SIZE(fe_event_ack_config_control));
4684 if (ret < 0)
4685 pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
4686
4687 kfree(mixer_str);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304688 return ret;
4689}
4690
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304691static struct msm_pcm_channel_mixer *msm_compr_get_chmixer(
4692 struct msm_compr_pdata *pdata, u64 fe_id)
4693{
4694 if (!pdata) {
4695 pr_err("%s: missing pdata\n", __func__);
4696 return NULL;
4697 }
4698
4699 if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
4700 pr_err("%s: invalid FE %llu\n", __func__, fe_id);
4701 return NULL;
4702 }
4703
4704 return pdata->chmixer_pspd[fe_id];
4705}
4706
4707static int msm_compr_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol,
4708 struct snd_ctl_elem_value *ucontrol)
4709{
4710 u64 fe_id = kcontrol->private_value & 0xFF;
4711 int session_type = (kcontrol->private_value >> 8) & 0xFF;
4712 int ret = 0, i = 0, stream_id = 0, be_id = 0;
4713 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4714 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4715 snd_soc_component_get_drvdata(comp);
4716 struct snd_compr_stream *cstream = NULL;
4717 struct msm_compr_audio *prtd = NULL;
4718 struct msm_pcm_channel_mixer *chmixer_pspd = NULL;
4719 u8 asm_ch_map[PCM_FORMAT_MAX_NUM_CHANNEL_V8] = {0};
4720 bool reset_override_out_ch_map = false;
4721 bool reset_override_in_ch_map = false;
4722
4723 if ((session_type != SESSION_TYPE_TX) &&
4724 (session_type != SESSION_TYPE_RX)) {
4725 pr_err("%s: invalid session type %d\n", __func__, session_type);
4726 return -EINVAL;
4727 }
4728
4729 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
4730 if (!chmixer_pspd) {
4731 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
4732 return -EINVAL;
4733 }
4734
4735 chmixer_pspd->enable = ucontrol->value.integer.value[0];
4736 chmixer_pspd->rule = ucontrol->value.integer.value[1];
4737 chmixer_pspd->input_channel = ucontrol->value.integer.value[2];
4738 chmixer_pspd->output_channel = ucontrol->value.integer.value[3];
4739 chmixer_pspd->port_idx = ucontrol->value.integer.value[4];
4740
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05304741 if (chmixer_pspd->input_channel <= 0 ||
4742 chmixer_pspd->input_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8 ||
4743 chmixer_pspd->output_channel <= 0 ||
4744 chmixer_pspd->output_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
4745 pr_err("%s: Invalid channels, in %d, out %d\n",
4746 __func__, chmixer_pspd->input_channel,
4747 chmixer_pspd->output_channel);
4748 return -EINVAL;
4749 }
4750
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304751 if (chmixer_pspd->enable) {
4752 if (session_type == SESSION_TYPE_RX &&
4753 !chmixer_pspd->override_in_ch_map) {
4754 if (pdata->ch_map[fe_id]->set_ch_map) {
4755 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4756 chmixer_pspd->in_ch_map[i] =
4757 pdata->ch_map[fe_id]->channel_map[i];
4758 } else {
4759 q6asm_map_channels(asm_ch_map,
4760 chmixer_pspd->input_channel, false);
4761 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4762 chmixer_pspd->in_ch_map[i] = asm_ch_map[i];
4763 }
4764 chmixer_pspd->override_in_ch_map = true;
4765 reset_override_in_ch_map = true;
4766 } else if (session_type == SESSION_TYPE_TX &&
4767 !chmixer_pspd->override_out_ch_map) {
4768 if (pdata->ch_map[fe_id]->set_ch_map) {
4769 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4770 chmixer_pspd->out_ch_map[i] =
4771 pdata->ch_map[fe_id]->channel_map[i];
4772 } else {
4773 q6asm_map_channels(asm_ch_map,
4774 chmixer_pspd->output_channel, false);
4775 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4776 chmixer_pspd->out_ch_map[i] = asm_ch_map[i];
4777 }
4778 chmixer_pspd->override_out_ch_map = true;
4779 reset_override_out_ch_map = true;
4780 }
4781 } else {
4782 chmixer_pspd->override_out_ch_map = false;
4783 chmixer_pspd->override_in_ch_map = false;
4784 }
4785
4786 /* cache value and take effect during adm_open stage */
4787 msm_pcm_routing_set_channel_mixer_cfg(fe_id,
4788 session_type,
4789 chmixer_pspd);
4790
4791 cstream = pdata->cstream[fe_id];
4792 if (chmixer_pspd->enable && cstream && cstream->runtime) {
4793 prtd = cstream->runtime->private_data;
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304794
Dhananjay Kumarf682acd2019-03-01 17:07:10 +05304795 if (prtd && prtd->audio_client) {
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304796 stream_id = prtd->audio_client->session;
4797 be_id = chmixer_pspd->port_idx;
4798 ret = msm_pcm_routing_set_channel_mixer_runtime(be_id,
4799 stream_id, session_type, chmixer_pspd);
4800 }
4801 }
4802
4803 if (reset_override_out_ch_map)
4804 chmixer_pspd->override_out_ch_map = false;
4805 if (reset_override_in_ch_map)
4806 chmixer_pspd->override_in_ch_map = false;
4807
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05304808 return ret;
4809}
4810
4811static int msm_compr_channel_mixer_cfg_ctl_get(struct snd_kcontrol *kcontrol,
4812 struct snd_ctl_elem_value *ucontrol)
4813{
4814 u64 fe_id = kcontrol->private_value & 0xFF;
4815 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4816 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4817 snd_soc_component_get_drvdata(comp);
4818 struct msm_pcm_channel_mixer *chmixer_pspd;
4819
4820 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
4821 if (!chmixer_pspd) {
4822 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
4823 return -EINVAL;
4824 }
4825
4826 ucontrol->value.integer.value[0] = chmixer_pspd->enable;
4827 ucontrol->value.integer.value[1] = chmixer_pspd->rule;
4828 ucontrol->value.integer.value[2] = chmixer_pspd->input_channel;
4829 ucontrol->value.integer.value[3] = chmixer_pspd->output_channel;
4830 ucontrol->value.integer.value[4] = chmixer_pspd->port_idx;
4831 return 0;
4832}
4833
4834static int msm_compr_channel_mixer_output_map_ctl_put(
4835 struct snd_kcontrol *kcontrol,
4836 struct snd_ctl_elem_value *ucontrol)
4837{
4838 u64 fe_id = kcontrol->private_value & 0xFF;
4839 int i = 0;
4840 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4841 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4842 snd_soc_component_get_drvdata(comp);
4843 struct msm_pcm_channel_mixer *chmixer_pspd;
4844
4845 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
4846 if (!chmixer_pspd) {
4847 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
4848 return -EINVAL;
4849 }
4850
4851 chmixer_pspd->override_out_ch_map = true;
4852 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4853 chmixer_pspd->out_ch_map[i] =
4854 ucontrol->value.integer.value[i];
4855
4856 return 0;
4857}
4858
4859static int msm_compr_channel_mixer_output_map_ctl_get(
4860 struct snd_kcontrol *kcontrol,
4861 struct snd_ctl_elem_value *ucontrol)
4862{
4863 u64 fe_id = kcontrol->private_value & 0xFF;
4864 int i = 0;
4865 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4866 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4867 snd_soc_component_get_drvdata(comp);
4868 struct msm_pcm_channel_mixer *chmixer_pspd;
4869
4870 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
4871 if (!chmixer_pspd) {
4872 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
4873 return -EINVAL;
4874 }
4875
4876 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4877 ucontrol->value.integer.value[i] =
4878 chmixer_pspd->out_ch_map[i];
4879 return 0;
4880}
4881
4882static int msm_compr_channel_mixer_input_map_ctl_put(
4883 struct snd_kcontrol *kcontrol,
4884 struct snd_ctl_elem_value *ucontrol)
4885{
4886 u64 fe_id = kcontrol->private_value & 0xFF;
4887 int i = 0;
4888 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4889 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4890 snd_soc_component_get_drvdata(comp);
4891 struct msm_pcm_channel_mixer *chmixer_pspd;
4892
4893 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
4894 if (!chmixer_pspd) {
4895 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
4896 return -EINVAL;
4897 }
4898
4899 chmixer_pspd->override_in_ch_map = true;
4900 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4901 chmixer_pspd->in_ch_map[i] = ucontrol->value.integer.value[i];
4902
4903 return 0;
4904}
4905
4906static int msm_compr_channel_mixer_input_map_ctl_get(
4907 struct snd_kcontrol *kcontrol,
4908 struct snd_ctl_elem_value *ucontrol)
4909{
4910 u64 fe_id = kcontrol->private_value & 0xFF;
4911 int i = 0;
4912 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4913 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4914 snd_soc_component_get_drvdata(comp);
4915 struct msm_pcm_channel_mixer *chmixer_pspd;
4916
4917 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
4918 if (!chmixer_pspd) {
4919 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
4920 return -EINVAL;
4921 }
4922
4923 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4924 ucontrol->value.integer.value[i] =
4925 chmixer_pspd->in_ch_map[i];
4926 return 0;
4927}
4928
4929static int msm_compr_channel_mixer_weight_ctl_put(
4930 struct snd_kcontrol *kcontrol,
4931 struct snd_ctl_elem_value *ucontrol)
4932{
4933 u64 fe_id = kcontrol->private_value & 0xFF;
4934 int channel = (kcontrol->private_value >> 16) & 0xFF;
4935 int i = 0;
4936 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4937 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4938 snd_soc_component_get_drvdata(comp);
4939 struct msm_pcm_channel_mixer *chmixer_pspd;
4940
4941 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
4942 if (!chmixer_pspd) {
4943 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
4944 return -EINVAL;
4945 }
4946
4947 if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
4948 pr_err("%s: invalid channel number %d\n", __func__, channel);
4949 return -EINVAL;
4950 }
4951 channel--;
4952
4953 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4954 chmixer_pspd->channel_weight[channel][i] =
4955 ucontrol->value.integer.value[i];
4956 return 0;
4957}
4958
4959static int msm_compr_channel_mixer_weight_ctl_get(
4960 struct snd_kcontrol *kcontrol,
4961 struct snd_ctl_elem_value *ucontrol)
4962{
4963 u64 fe_id = kcontrol->private_value & 0xFF;
4964 int channel = (kcontrol->private_value >> 16) & 0xFF;
4965 struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
4966 struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
4967 snd_soc_component_get_drvdata(comp);
4968 int i = 0;
4969 struct msm_pcm_channel_mixer *chmixer_pspd;
4970
4971 if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
4972 pr_err("%s: invalid channel number %d\n", __func__, channel);
4973 return -EINVAL;
4974 }
4975 channel--;
4976
4977 chmixer_pspd = msm_compr_get_chmixer(pdata, fe_id);
4978 if (!chmixer_pspd) {
4979 pr_err("%s: invalid chmixer_pspd in pdata", __func__);
4980 return -EINVAL;
4981 }
4982
4983 for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
4984 ucontrol->value.integer.value[i] =
4985 chmixer_pspd->channel_weight[channel][i];
4986 return 0;
4987}
4988
4989static int msm_compr_add_platform_controls(struct snd_kcontrol_new *kctl,
4990 struct snd_soc_pcm_runtime *rtd, const char *name_prefix,
4991 const char *name_suffix, int session_type, int channels)
4992{
4993 int ret = -EINVAL;
4994 char *mixer_name = NULL;
4995 const char *deviceNo = "NN";
4996 const char *channelNo = "NN";
4997 int ctl_len = 0;
4998 struct snd_soc_component *component = NULL;
4999
5000 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
5001 if (!component) {
5002 pr_err("%s: component is NULL\n", __func__);
5003 return -EINVAL;
5004 }
5005
5006 ctl_len = strlen(name_prefix) + 1 + strlen(deviceNo) + 1 +
5007 strlen(channelNo) + 1 + strlen(name_suffix) + 1;
5008
5009 mixer_name = kzalloc(ctl_len, GFP_KERNEL);
5010 if (mixer_name == NULL)
5011 return -ENOMEM;
5012
5013 if (channels >= 0) {
5014 snprintf(mixer_name, ctl_len, "%s %d %s %d",
5015 name_prefix, rtd->pcm->device, name_suffix, channels);
5016 kctl->private_value = (rtd->dai_link->id) | (channels << 16);
5017 } else {
5018 snprintf(mixer_name, ctl_len, "%s %d %s",
5019 name_prefix, rtd->pcm->device, name_suffix);
5020 kctl->private_value = (rtd->dai_link->id);
5021 }
5022 if (session_type != INVALID_SESSION)
5023 kctl->private_value |= (session_type << 8);
5024
5025 kctl->name = mixer_name;
5026 ret = snd_soc_add_component_controls(component, kctl, 1);
5027 kfree(mixer_name);
5028 return ret;
5029}
5030
5031static int msm_compr_channel_mixer_output_map_info(struct snd_kcontrol *kcontrol,
5032 struct snd_ctl_elem_info *uinfo)
5033{
5034 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5035 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
5036 /* Valid channel map value ranges from 1 to 64 */
5037 uinfo->value.integer.min = 1;
5038 uinfo->value.integer.max = 64;
5039 return 0;
5040}
5041
5042static int msm_compr_add_channel_mixer_output_map_controls(
5043 struct snd_soc_pcm_runtime *rtd)
5044{
5045 const char *playback_mixer_ctl_name = "AudStr";
5046 const char *capture_mixer_ctl_name = "AudStr Capture";
5047 const char *suffix = "ChMixer Output Map";
5048 const char *mixer_ctl_name = NULL;
5049 int ret = 0, session_type = INVALID_SESSION, channel = -1;
5050 struct snd_kcontrol_new channel_mixer_output_map_control = {
5051 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5052 .name = "?",
5053 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5054 .info = msm_compr_channel_mixer_output_map_info,
5055 .put = msm_compr_channel_mixer_output_map_ctl_put,
5056 .get = msm_compr_channel_mixer_output_map_ctl_get,
5057 .private_value = 0,
5058 };
5059
5060 mixer_ctl_name = rtd->compr->direction == SND_COMPRESS_PLAYBACK ?
5061 playback_mixer_ctl_name : capture_mixer_ctl_name ;
5062 ret = msm_compr_add_platform_controls(&channel_mixer_output_map_control,
5063 rtd, mixer_ctl_name, suffix, session_type, channel);
5064 if (ret < 0) {
5065 pr_err("%s: failed add platform ctl, err = %d\n",
5066 __func__, ret);
5067 }
5068
5069 return ret;
5070}
5071
5072static int msm_compr_channel_mixer_input_map_info(struct snd_kcontrol *kcontrol,
5073 struct snd_ctl_elem_info *uinfo)
5074{
5075 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5076 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
5077 /* Valid channel map value ranges from 1 to 64 */
5078 uinfo->value.integer.min = 1;
5079 uinfo->value.integer.max = 64;
5080 return 0;
5081}
5082
5083static int msm_compr_add_channel_mixer_input_map_controls(
5084 struct snd_soc_pcm_runtime *rtd)
5085{
5086 const char *playback_mixer_ctl_name = "AudStr";
5087 const char *capture_mixer_ctl_name = "AudStr Capture";
5088 const char *suffix = "ChMixer Input Map";
5089 const char *mixer_ctl_name = NULL;
5090 int ret = 0, session_type = INVALID_SESSION, channel = -1;
5091 struct snd_kcontrol_new channel_mixer_input_map_control = {
5092 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5093 .name = "?",
5094 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5095 .info = msm_compr_channel_mixer_input_map_info,
5096 .put = msm_compr_channel_mixer_input_map_ctl_put,
5097 .get = msm_compr_channel_mixer_input_map_ctl_get,
5098 .private_value = 0,
5099 };
5100
5101 mixer_ctl_name = rtd->compr->direction == SND_COMPRESS_PLAYBACK ?
5102 playback_mixer_ctl_name : capture_mixer_ctl_name ;
5103 ret = msm_compr_add_platform_controls(&channel_mixer_input_map_control,
5104 rtd, mixer_ctl_name, suffix, session_type, channel);
5105 if (ret < 0) {
5106 pr_err("%s: failed add platform ctl, err = %d\n",
5107 __func__, ret);
5108 }
5109
5110 return ret;
5111}
5112
5113static int msm_compr_channel_mixer_cfg_info(struct snd_kcontrol *kcontrol,
5114 struct snd_ctl_elem_info *uinfo)
5115{
5116 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5117 /* five int values: enable, rule, in_channels, out_channels and port_id */
5118 uinfo->count = 5;
5119 /* Valid range is all positive values to support above controls */
5120 uinfo->value.integer.min = 0;
5121 uinfo->value.integer.max = INT_MAX;
5122 return 0;
5123}
5124
5125static int msm_compr_add_channel_mixer_cfg_controls(
5126 struct snd_soc_pcm_runtime *rtd)
5127{
5128 const char *playback_mixer_ctl_name = "AudStr";
5129 const char *capture_mixer_ctl_name = "AudStr Capture";
5130 const char *suffix = "ChMixer Cfg";
5131 const char *mixer_ctl_name = NULL;
5132 int ret = 0, session_type = INVALID_SESSION, channel = -1;
5133 struct snd_kcontrol_new channel_mixer_cfg_control = {
5134 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5135 .name = "?",
5136 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5137 .info = msm_compr_channel_mixer_cfg_info,
5138 .put = msm_compr_channel_mixer_cfg_ctl_put,
5139 .get = msm_compr_channel_mixer_cfg_ctl_get,
5140 .private_value = 0,
5141 };
5142
5143 if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
5144 session_type = SESSION_TYPE_RX;
5145 mixer_ctl_name = playback_mixer_ctl_name;
5146 } else {
5147 session_type = SESSION_TYPE_TX;
5148 mixer_ctl_name = capture_mixer_ctl_name;
5149 }
5150
5151 ret = msm_compr_add_platform_controls(&channel_mixer_cfg_control,
5152 rtd, mixer_ctl_name, suffix, session_type, channel);
5153 if (ret < 0) {
5154 pr_err("%s: failed add platform ctl, err = %d\n",
5155 __func__, ret);
5156 }
5157
5158 return ret;
5159}
5160
5161static int msm_compr_channel_mixer_weight_info(struct snd_kcontrol *kcontrol,
5162 struct snd_ctl_elem_info *uinfo)
5163{
5164 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5165 uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
5166 /* Valid range: 0 to 0x4000(Unity) gain weightage */
5167 uinfo->value.integer.min = 0;
5168 uinfo->value.integer.max = 0x4000;
5169 return 0;
5170}
5171
5172static int msm_compr_add_channel_mixer_weight_controls(
5173 struct snd_soc_pcm_runtime *rtd,
5174 int channel)
5175{
5176 const char *playback_mixer_ctl_name = "AudStr";
5177 const char *capture_mixer_ctl_name = "AudStr Capture";
5178 const char *suffix = "ChMixer Weight Ch";
5179 const char *mixer_ctl_name = NULL;
5180 int ret = 0, session_type = INVALID_SESSION;
5181 struct snd_kcontrol_new channel_mixer_weight_control = {
5182 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5183 .name = "?",
5184 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
5185 .info = msm_compr_channel_mixer_weight_info,
5186 .put = msm_compr_channel_mixer_weight_ctl_put,
5187 .get = msm_compr_channel_mixer_weight_ctl_get,
5188 .private_value = 0,
5189 };
5190
5191 mixer_ctl_name = rtd->compr->direction == SND_COMPRESS_PLAYBACK ?
5192 playback_mixer_ctl_name : capture_mixer_ctl_name ;
5193 ret = msm_compr_add_platform_controls(&channel_mixer_weight_control,
5194 rtd, mixer_ctl_name, suffix, session_type, channel);
5195 if (ret < 0) {
5196 pr_err("%s: failed add platform ctl, err = %d\n",
5197 __func__, ret);
5198 }
5199
5200 return ret;
5201}
5202
5203static int msm_compr_add_channel_mixer_controls(struct snd_soc_pcm_runtime *rtd)
5204{
5205 int i, ret = 0;
5206 struct msm_compr_pdata *pdata = NULL;
5207 struct snd_soc_component *component = NULL;
5208
5209 if (!rtd) {
5210 pr_err("%s NULL rtd\n", __func__);
5211 return -EINVAL;
5212 }
5213
5214 component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
5215 if (!component) {
5216 pr_err("%s: component is NULL\n", __func__);
5217 return -EINVAL;
5218 }
5219
5220 pdata = (struct msm_compr_pdata *)
5221 snd_soc_component_get_drvdata(component);
5222 if (!pdata) {
5223 pr_err("%s: platform data not populated\n", __func__);
5224 return -EINVAL;
5225 }
5226
5227 if (!pdata->chmixer_pspd[rtd->dai_link->id]) {
5228 pdata->chmixer_pspd[rtd->dai_link->id] =
5229 kzalloc(sizeof(struct msm_pcm_channel_mixer), GFP_KERNEL);
5230 if (!pdata->chmixer_pspd[rtd->dai_link->id])
5231 return -ENOMEM;
5232 }
5233
5234 ret = msm_compr_add_channel_mixer_cfg_controls(rtd);
5235 if (ret) {
5236 pr_err("%s: pcm add channel mixer cfg controls failed:%d\n",
5237 __func__, ret);
5238 goto fail;
5239 }
5240 ret = msm_compr_add_channel_mixer_input_map_controls(rtd);
5241 if (ret) {
5242 pr_err("%s: pcm add channel mixer input map controls failed:%d\n",
5243 __func__, ret);
5244 goto fail;
5245 }
5246 ret = msm_compr_add_channel_mixer_output_map_controls(rtd);
5247 if (ret) {
5248 pr_err("%s: pcm add channel mixer output map controls failed:%d\n",
5249 __func__, ret);
5250 goto fail;
5251 }
5252
5253 for (i = 1; i <= PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++) {
5254 ret = msm_compr_add_channel_mixer_weight_controls(rtd, i);
5255 if (ret) {
5256 pr_err("%s: pcm add channel mixer weight controls failed:%d\n",
5257 __func__, ret);
5258 goto fail;
5259 }
5260 }
5261 return 0;
5262
5263fail:
5264 kfree(pdata->chmixer_pspd[rtd->dai_link->id]);
5265 pdata->chmixer_pspd[rtd->dai_link->id] = NULL;
5266 return ret;
5267}
5268
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305269static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
5270{
5271 int rc;
5272
5273 rc = msm_compr_add_volume_control(rtd);
5274 if (rc)
5275 pr_err("%s: Could not add Compr Volume Control\n", __func__);
5276
5277 rc = msm_compr_add_audio_effects_control(rtd);
5278 if (rc)
5279 pr_err("%s: Could not add Compr Audio Effects Control\n",
5280 __func__);
5281
5282 rc = msm_compr_add_audio_adsp_stream_cmd_control(rtd);
5283 if (rc)
5284 pr_err("%s: Could not add Compr ADSP Stream Cmd Control\n",
5285 __func__);
5286
5287 rc = msm_compr_add_audio_adsp_stream_callback_control(rtd);
5288 if (rc)
5289 pr_err("%s: Could not add Compr ADSP Stream Callback Control\n",
5290 __func__);
5291
5292 rc = msm_compr_add_io_fd_cmd_control(rtd);
5293 if (rc)
5294 pr_err("%s: Could not add Compr ion fd Control\n",
5295 __func__);
5296
5297 rc = msm_compr_add_event_ack_cmd_control(rtd);
5298 if (rc)
5299 pr_err("%s: Could not add Compr event ack Control\n",
5300 __func__);
5301
5302 rc = msm_compr_add_query_audio_effect_control(rtd);
5303 if (rc)
5304 pr_err("%s: Could not add Compr Query Audio Effect Control\n",
5305 __func__);
5306
5307 rc = msm_compr_add_dec_runtime_params_control(rtd);
5308 if (rc)
5309 pr_err("%s: Could not add Compr Dec runtime params Control\n",
5310 __func__);
5311 rc = msm_compr_add_app_type_cfg_control(rtd);
5312 if (rc)
5313 pr_err("%s: Could not add Compr App Type Cfg Control\n",
5314 __func__);
5315 rc = msm_compr_add_channel_map_control(rtd);
5316 if (rc)
5317 pr_err("%s: Could not add Compr Channel Map Control\n",
5318 __func__);
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305319 rc = msm_compr_add_channel_mixer_controls(rtd);
5320 if (rc)
5321 pr_err("%s: Could not add Compr Channel Mixer Controls\n",
5322 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305323 return 0;
5324}
5325
5326static struct snd_compr_ops msm_compr_ops = {
5327 .open = msm_compr_open,
5328 .free = msm_compr_free,
5329 .trigger = msm_compr_trigger,
5330 .pointer = msm_compr_pointer,
5331 .set_params = msm_compr_set_params,
5332 .set_metadata = msm_compr_set_metadata,
5333 .get_metadata = msm_compr_get_metadata,
5334 .set_next_track_param = msm_compr_set_next_track_param,
5335 .ack = msm_compr_ack,
5336 .copy = msm_compr_copy,
5337 .get_caps = msm_compr_get_caps,
5338 .get_codec_caps = msm_compr_get_codec_caps,
5339};
5340
Meng Wangee084a02018-09-04 16:11:58 +08005341static struct snd_soc_component_driver msm_soc_component = {
5342 .name = DRV_NAME,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305343 .probe = msm_compr_probe,
5344 .compr_ops = &msm_compr_ops,
5345 .pcm_new = msm_compr_new,
5346};
5347
5348static int msm_compr_dev_probe(struct platform_device *pdev)
5349{
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305350 struct msm_compr_pdata *pdata = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305351
5352 pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305353 pdata = (struct msm_compr_pdata *)
5354 kzalloc(sizeof(*pdata), GFP_KERNEL);
5355 if (!pdata)
5356 return -ENOMEM;
5357 dev_set_drvdata(&pdev->dev, pdata);
5358
Meng Wangee084a02018-09-04 16:11:58 +08005359 return snd_soc_register_component(&pdev->dev,
5360 &msm_soc_component, NULL, 0);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305361}
5362
5363static int msm_compr_remove(struct platform_device *pdev)
5364{
Dhananjay Kumar807f7e92018-12-11 18:10:08 +05305365 int i = 0;
5366 struct msm_compr_pdata *pdata = NULL;
5367
5368 pdata = dev_get_drvdata(&pdev->dev);
5369 if (pdata) {
5370 for (i = 0; i < MSM_FRONTEND_DAI_MM_SIZE; i++)
5371 kfree(pdata->chmixer_pspd[i]);
5372 }
5373 kfree(pdata);
5374
Meng Wangee084a02018-09-04 16:11:58 +08005375 snd_soc_unregister_component(&pdev->dev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305376 return 0;
5377}
5378
5379static const struct of_device_id msm_compr_dt_match[] = {
5380 {.compatible = "qcom,msm-compress-dsp"},
5381 {}
5382};
5383MODULE_DEVICE_TABLE(of, msm_compr_dt_match);
5384
5385static struct platform_driver msm_compr_driver = {
5386 .driver = {
5387 .name = "msm-compress-dsp",
5388 .owner = THIS_MODULE,
5389 .of_match_table = msm_compr_dt_match,
Xiaojun Sang53cd13a2018-06-29 15:14:37 +08005390 .suppress_bind_attrs = true,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305391 },
5392 .probe = msm_compr_dev_probe,
5393 .remove = msm_compr_remove,
5394};
5395
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305396int __init msm_compress_dsp_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305397{
5398 return platform_driver_register(&msm_compr_driver);
5399}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305400
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05305401void msm_compress_dsp_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305402{
5403 platform_driver_unregister(&msm_compr_driver);
5404}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305405
5406MODULE_DESCRIPTION("Compress Offload platform driver");
5407MODULE_LICENSE("GPL v2");