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