blob: 7fe586fa18208235eea9bf574918b7c1d0429cde [file] [log] [blame]
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301/*
Meng Wangb6afa8c2017-11-30 17:55:05 +08002 * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303 * Author: Brian Swetland <swetland@google.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15#include <linux/fs.h>
16#include <linux/mutex.h>
17#include <linux/wait.h>
18#include <linux/miscdevice.h>
19#include <linux/uaccess.h>
20#include <linux/sched.h>
21#include <linux/dma-mapping.h>
22#include <linux/miscdevice.h>
23#include <linux/delay.h>
24#include <linux/slab.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053025
26#include <linux/debugfs.h>
27#include <linux/time.h>
28#include <linux/atomic.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053029#include <linux/mm.h>
30
31#include <asm/ioctls.h>
32
33#include <linux/memory.h>
34
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053035#include <sound/compress_params.h>
36
Laxminath Kasam605b42f2017-08-01 22:02:15 +053037#include <dsp/msm_audio_ion.h>
38#include <dsp/apr_audio-v2.h>
39#include <dsp/audio_cal_utils.h>
40#include <dsp/q6asm-v2.h>
41#include <dsp/q6audio-v2.h>
42#include "adsp_err.h"
43
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053044#define TRUE 0x01
45#define FALSE 0x00
46#define SESSION_MAX 8
47
48enum {
49 ASM_TOPOLOGY_CAL = 0,
50 ASM_CUSTOM_TOP_CAL,
51 ASM_AUDSTRM_CAL,
52 ASM_RTAC_APR_CAL,
53 ASM_MAX_CAL_TYPES
54};
55
56union asm_token_struct {
57 struct {
58 u8 stream_id;
59 u8 session_id;
60 u8 buf_index;
61 u8 flags;
62 } _token;
63 u32 token;
64} __packed;
65
66
67enum {
68 ASM_DIRECTION_OFFSET,
69 ASM_CMD_NO_WAIT_OFFSET,
70 /*
71 * Offset is limited to 7 because flags is stored in u8
72 * field in asm_token_structure defined above. The offset
73 * starts from 0.
74 */
75 ASM_MAX_OFFSET = 7,
76};
77
78enum {
79 WAIT_CMD,
80 NO_WAIT_CMD
81};
82
83#define ASM_SET_BIT(n, x) (n |= 1 << x)
84#define ASM_TEST_BIT(n, x) ((n >> x) & 1)
85
86/* TODO, combine them together */
87static DEFINE_MUTEX(session_lock);
88struct asm_mmap {
89 atomic_t ref_cnt;
90 void *apr;
91};
92
93static struct asm_mmap this_mmap;
Meng Wang9730cdd2017-09-26 12:48:31 +080094
95struct audio_session {
96 struct audio_client *ac;
97 spinlock_t session_lock;
98};
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053099/* session id: 0 reserved */
Meng Wang9730cdd2017-09-26 12:48:31 +0800100static struct audio_session session[ASM_ACTIVE_STREAMS_ALLOWED + 1];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530101
102struct asm_buffer_node {
103 struct list_head list;
104 phys_addr_t buf_phys_addr;
105 uint32_t mmap_hdl;
106};
107static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv);
108static int32_t q6asm_callback(struct apr_client_data *data, void *priv);
109static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
110 uint32_t pkt_size, uint32_t cmd_flg);
111static void q6asm_add_hdr_custom_topology(struct audio_client *ac,
112 struct apr_hdr *hdr,
113 uint32_t pkt_size);
114static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
115 uint32_t pkt_size, uint32_t cmd_flg);
116static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
117 uint32_t bufsz, uint32_t bufcnt,
118 bool is_contiguous);
119static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir);
120static void q6asm_reset_buf_state(struct audio_client *ac);
121
122static int q6asm_map_channels(u8 *channel_mapping, uint32_t channels,
123 bool use_back_flavor);
124void *q6asm_mmap_apr_reg(void);
125
126static int q6asm_is_valid_session(struct apr_client_data *data, void *priv);
127static int q6asm_get_asm_topology_cal(void);
128static int q6asm_get_asm_app_type_cal(void);
129
130/* for ASM custom topology */
131static struct cal_type_data *cal_data[ASM_MAX_CAL_TYPES];
132static struct audio_buffer common_buf[2];
133static struct audio_client common_client;
134static int set_custom_topology;
135static int topology_map_handle;
136
137struct generic_get_data_ {
138 int valid;
139 int is_inband;
140 int size_in_ints;
141 int ints[];
142};
143static struct generic_get_data_ *generic_get_data;
144
145#ifdef CONFIG_DEBUG_FS
146#define OUT_BUFFER_SIZE 56
147#define IN_BUFFER_SIZE 24
148
149static struct timeval out_cold_tv;
150static struct timeval out_warm_tv;
151static struct timeval out_cont_tv;
152static struct timeval in_cont_tv;
153static long out_enable_flag;
154static long in_enable_flag;
155static struct dentry *out_dentry;
156static struct dentry *in_dentry;
157static int in_cont_index;
158/*This var is used to keep track of first write done for cold output latency */
159static int out_cold_index;
160static char *out_buffer;
161static char *in_buffer;
162
163static uint32_t adsp_reg_event_opcode[] = {
164 ASM_STREAM_CMD_REGISTER_PP_EVENTS,
165 ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS,
166 ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE };
167
168static uint32_t adsp_raise_event_opcode[] = {
169 ASM_STREAM_PP_EVENT,
170 ASM_STREAM_CMD_ENCDEC_EVENTS,
171 ASM_IEC_61937_MEDIA_FMT_EVENT };
172
173static int is_adsp_reg_event(uint32_t cmd)
174{
175 int i;
176
177 for (i = 0; i < ARRAY_SIZE(adsp_reg_event_opcode); i++) {
178 if (cmd == adsp_reg_event_opcode[i])
179 return i;
180 }
181 return -EINVAL;
182}
183
184static int is_adsp_raise_event(uint32_t cmd)
185{
186 int i;
187
188 for (i = 0; i < ARRAY_SIZE(adsp_raise_event_opcode); i++) {
189 if (cmd == adsp_raise_event_opcode[i])
190 return i;
191 }
192 return -EINVAL;
193}
194
195static inline void q6asm_set_flag_in_token(union asm_token_struct *asm_token,
196 int flag, int flag_offset)
197{
198 if (flag)
199 ASM_SET_BIT(asm_token->_token.flags, flag_offset);
200}
201
202static inline int q6asm_get_flag_from_token(union asm_token_struct *asm_token,
203 int flag_offset)
204{
205 return ASM_TEST_BIT(asm_token->_token.flags, flag_offset);
206}
207
208static inline void q6asm_update_token(u32 *token, u8 session_id, u8 stream_id,
209 u8 buf_index, u8 dir, u8 nowait_flag)
210{
211 union asm_token_struct asm_token;
212
213 asm_token.token = 0;
214 asm_token._token.session_id = session_id;
215 asm_token._token.stream_id = stream_id;
216 asm_token._token.buf_index = buf_index;
217 q6asm_set_flag_in_token(&asm_token, dir, ASM_DIRECTION_OFFSET);
218 q6asm_set_flag_in_token(&asm_token, nowait_flag,
219 ASM_CMD_NO_WAIT_OFFSET);
220 *token = asm_token.token;
221}
222
223static inline uint32_t q6asm_get_pcm_format_id(uint32_t media_format_block_ver)
224{
225 uint32_t pcm_format_id;
226
227 switch (media_format_block_ver) {
228 case PCM_MEDIA_FORMAT_V4:
229 pcm_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V4;
230 break;
231 case PCM_MEDIA_FORMAT_V3:
232 pcm_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3;
233 break;
234 case PCM_MEDIA_FORMAT_V2:
235 default:
236 pcm_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
237 break;
238 }
239 return pcm_format_id;
240}
241
242/*
243 * q6asm_get_buf_index_from_token:
244 * Retrieve buffer index from token.
245 *
246 * @token: token value sent to ASM service on q6.
247 * Returns buffer index in the read/write commands.
248 */
249uint8_t q6asm_get_buf_index_from_token(uint32_t token)
250{
251 union asm_token_struct asm_token;
252
253 asm_token.token = token;
254 return asm_token._token.buf_index;
255}
256EXPORT_SYMBOL(q6asm_get_buf_index_from_token);
257
258/*
259 * q6asm_get_stream_id_from_token:
260 * Retrieve stream id from token.
261 *
262 * @token: token value sent to ASM service on q6.
263 * Returns stream id.
264 */
265uint8_t q6asm_get_stream_id_from_token(uint32_t token)
266{
267 union asm_token_struct asm_token;
268
269 asm_token.token = token;
270 return asm_token._token.stream_id;
271}
272EXPORT_SYMBOL(q6asm_get_stream_id_from_token);
273
274static int audio_output_latency_dbgfs_open(struct inode *inode,
275 struct file *file)
276{
277 file->private_data = inode->i_private;
278 return 0;
279}
280static ssize_t audio_output_latency_dbgfs_read(struct file *file,
281 char __user *buf, size_t count, loff_t *ppos)
282{
283 if (out_buffer == NULL) {
284 pr_err("%s: out_buffer is null\n", __func__);
285 return 0;
286 }
Karthikeyan Mani1dfff342018-02-15 17:46:25 -0800287 if (count < OUT_BUFFER_SIZE) {
288 pr_err("%s: read size %d exceeds buf size %zd\n", __func__,
289 OUT_BUFFER_SIZE, count);
290 return 0;
291 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530292 snprintf(out_buffer, OUT_BUFFER_SIZE, "%ld,%ld,%ld,%ld,%ld,%ld,",
293 out_cold_tv.tv_sec, out_cold_tv.tv_usec, out_warm_tv.tv_sec,
294 out_warm_tv.tv_usec, out_cont_tv.tv_sec, out_cont_tv.tv_usec);
295 return simple_read_from_buffer(buf, OUT_BUFFER_SIZE, ppos,
296 out_buffer, OUT_BUFFER_SIZE);
297}
298static ssize_t audio_output_latency_dbgfs_write(struct file *file,
299 const char __user *buf, size_t count, loff_t *ppos)
300{
301 char *temp;
302
303 if (count > 2*sizeof(char)) {
304 pr_err("%s: err count is more %zd\n", __func__, count);
305 return -EINVAL;
306 }
307 temp = kmalloc(2*sizeof(char), GFP_KERNEL);
308
309 out_cold_index = 0;
310
311 if (temp) {
312 if (copy_from_user(temp, buf, 2*sizeof(char))) {
313 pr_err("%s: copy from user failed for size %zd\n",
314 __func__, 2*sizeof(char));
315 kfree(temp);
316 return -EFAULT;
317 }
318 if (!kstrtol(temp, 10, &out_enable_flag)) {
319 kfree(temp);
320 return count;
321 }
322 kfree(temp);
323 }
324 return -EINVAL;
325}
326static const struct file_operations audio_output_latency_debug_fops = {
327 .open = audio_output_latency_dbgfs_open,
328 .read = audio_output_latency_dbgfs_read,
329 .write = audio_output_latency_dbgfs_write
330};
331static int audio_input_latency_dbgfs_open(struct inode *inode,
332 struct file *file)
333{
334 file->private_data = inode->i_private;
335 return 0;
336}
337static ssize_t audio_input_latency_dbgfs_read(struct file *file,
338 char __user *buf, size_t count, loff_t *ppos)
339{
340 if (in_buffer == NULL) {
341 pr_err("%s: in_buffer is null\n", __func__);
342 return 0;
343 }
Karthikeyan Mani1dfff342018-02-15 17:46:25 -0800344 if (count < IN_BUFFER_SIZE) {
345 pr_err("%s: read size %d exceeds buf size %zd\n", __func__,
346 IN_BUFFER_SIZE, count);
347 return 0;
348 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530349 snprintf(in_buffer, IN_BUFFER_SIZE, "%ld,%ld,",
350 in_cont_tv.tv_sec, in_cont_tv.tv_usec);
351 return simple_read_from_buffer(buf, IN_BUFFER_SIZE, ppos,
352 in_buffer, IN_BUFFER_SIZE);
353}
354static ssize_t audio_input_latency_dbgfs_write(struct file *file,
355 const char __user *buf, size_t count, loff_t *ppos)
356{
357 char *temp;
358
359 if (count > 2*sizeof(char)) {
360 pr_err("%s: err count is more %zd\n", __func__, count);
361 return -EINVAL;
362 }
363 temp = kmalloc(2*sizeof(char), GFP_KERNEL);
364
365 if (temp) {
366 if (copy_from_user(temp, buf, 2*sizeof(char))) {
367 pr_err("%s: copy from user failed for size %zd\n",
368 __func__, 2*sizeof(char));
369 kfree(temp);
370 return -EFAULT;
371 }
372 if (!kstrtol(temp, 10, &in_enable_flag)) {
373 kfree(temp);
374 return count;
375 }
376 kfree(temp);
377 }
378 return -EINVAL;
379}
380static const struct file_operations audio_input_latency_debug_fops = {
381 .open = audio_input_latency_dbgfs_open,
382 .read = audio_input_latency_dbgfs_read,
383 .write = audio_input_latency_dbgfs_write
384};
385
386static void config_debug_fs_write_cb(void)
387{
388 if (out_enable_flag) {
389 /* For first Write done log the time and reset
390 * out_cold_index
391 */
392 if (out_cold_index != 1) {
393 do_gettimeofday(&out_cold_tv);
394 pr_debug("COLD: apr_send_pkt at %ld sec %ld microsec\n",
395 out_cold_tv.tv_sec,
396 out_cold_tv.tv_usec);
397 out_cold_index = 1;
398 }
399 pr_debug("%s: out_enable_flag %ld\n",
400 __func__, out_enable_flag);
401 }
402}
403static void config_debug_fs_read_cb(void)
404{
405 if (in_enable_flag) {
406 /* when in_cont_index == 7, DSP would be
407 * writing into the 8th 512 byte buffer and this
408 * timestamp is tapped here.Once done it then writes
409 * to 9th 512 byte buffer.These two buffers(8th, 9th)
410 * reach the test application in 5th iteration and that
411 * timestamp is tapped at user level. The difference
412 * of these two timestamps gives us the time between
413 * the time at which dsp started filling the sample
414 * required and when it reached the test application.
415 * Hence continuous input latency
416 */
417 if (in_cont_index == 7) {
418 do_gettimeofday(&in_cont_tv);
419 pr_info("%s: read buffer at %ld sec %ld microsec\n",
420 __func__,
421 in_cont_tv.tv_sec, in_cont_tv.tv_usec);
422 }
423 in_cont_index++;
424 }
425}
426
427static void config_debug_fs_reset_index(void)
428{
429 in_cont_index = 0;
430}
431
432static void config_debug_fs_run(void)
433{
434 if (out_enable_flag) {
435 do_gettimeofday(&out_cold_tv);
436 pr_debug("%s: COLD apr_send_pkt at %ld sec %ld microsec\n",
437 __func__, out_cold_tv.tv_sec, out_cold_tv.tv_usec);
438 }
439}
440
441static void config_debug_fs_write(struct audio_buffer *ab)
442{
443 if (out_enable_flag) {
444 char zero_pattern[2] = {0x00, 0x00};
445 /* If First two byte is non zero and last two byte
446 * is zero then it is warm output pattern
447 */
448 if ((strcmp(((char *)ab->data), zero_pattern)) &&
449 (!strcmp(((char *)ab->data + 2), zero_pattern))) {
450 do_gettimeofday(&out_warm_tv);
451 pr_debug("%s: WARM:apr_send_pkt at %ld sec %ld microsec\n",
452 __func__,
453 out_warm_tv.tv_sec,
454 out_warm_tv.tv_usec);
455 pr_debug("%s: Warm Pattern Matched\n", __func__);
456 }
457 /* If First two byte is zero and last two byte is
458 * non zero then it is cont output pattern
459 */
460 else if ((!strcmp(((char *)ab->data), zero_pattern))
461 && (strcmp(((char *)ab->data + 2), zero_pattern))) {
462 do_gettimeofday(&out_cont_tv);
463 pr_debug("%s: CONT:apr_send_pkt at %ld sec %ld microsec\n",
464 __func__,
465 out_cont_tv.tv_sec,
466 out_cont_tv.tv_usec);
467 pr_debug("%s: Cont Pattern Matched\n", __func__);
468 }
469 }
470}
471static void config_debug_fs_init(void)
472{
473 out_buffer = kzalloc(OUT_BUFFER_SIZE, GFP_KERNEL);
474 if (out_buffer == NULL)
475 goto outbuf_fail;
476
477 in_buffer = kzalloc(IN_BUFFER_SIZE, GFP_KERNEL);
478 if (in_buffer == NULL)
479 goto inbuf_fail;
480
481 out_dentry = debugfs_create_file("audio_out_latency_measurement_node",
482 0664,
483 NULL, NULL, &audio_output_latency_debug_fops);
484 if (IS_ERR(out_dentry)) {
485 pr_err("%s: debugfs_create_file failed\n", __func__);
486 goto file_fail;
487 }
488 in_dentry = debugfs_create_file("audio_in_latency_measurement_node",
489 0664,
490 NULL, NULL, &audio_input_latency_debug_fops);
491 if (IS_ERR(in_dentry)) {
492 pr_err("%s: debugfs_create_file failed\n", __func__);
493 goto file_fail;
494 }
495 return;
496file_fail:
497 kfree(in_buffer);
498inbuf_fail:
499 kfree(out_buffer);
500outbuf_fail:
501 in_buffer = NULL;
502 out_buffer = NULL;
503}
504#else
505static void config_debug_fs_write(struct audio_buffer *ab)
506{
507}
508static void config_debug_fs_run(void)
509{
510}
511static void config_debug_fs_reset_index(void)
512{
513}
514static void config_debug_fs_read_cb(void)
515{
516}
517static void config_debug_fs_write_cb(void)
518{
519}
520static void config_debug_fs_init(void)
521{
522}
523#endif
524
525int q6asm_mmap_apr_dereg(void)
526{
527 int c;
528
529 c = atomic_sub_return(1, &this_mmap.ref_cnt);
530 if (c == 0) {
531 apr_deregister(this_mmap.apr);
532 common_client.mmap_apr = NULL;
533 pr_debug("%s: APR De-Register common port\n", __func__);
534 } else if (c < 0) {
535 pr_err("%s: APR Common Port Already Closed %d\n",
536 __func__, c);
537 atomic_set(&this_mmap.ref_cnt, 0);
538 }
539
540 return 0;
541}
542
543static int q6asm_session_alloc(struct audio_client *ac)
544{
545 int n;
546
547 for (n = 1; n <= ASM_ACTIVE_STREAMS_ALLOWED; n++) {
Meng Wang9730cdd2017-09-26 12:48:31 +0800548 if (!(session[n].ac)) {
549 session[n].ac = ac;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530550 return n;
551 }
552 }
553 pr_err("%s: session not available\n", __func__);
554 return -ENOMEM;
555}
556
Meng Wang9730cdd2017-09-26 12:48:31 +0800557static int q6asm_get_session_id_from_audio_client(struct audio_client *ac)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530558{
559 int n;
560
561 for (n = 1; n <= ASM_ACTIVE_STREAMS_ALLOWED; n++) {
Meng Wang9730cdd2017-09-26 12:48:31 +0800562 if (session[n].ac == ac)
563 return n;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530564 }
565 return 0;
566}
567
Meng Wang9730cdd2017-09-26 12:48:31 +0800568static bool q6asm_is_valid_audio_client(struct audio_client *ac)
569{
570 return q6asm_get_session_id_from_audio_client(ac) ? 1 : 0;
571}
572
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530573static void q6asm_session_free(struct audio_client *ac)
574{
Meng Wang9730cdd2017-09-26 12:48:31 +0800575 int session_id;
Meng Wangb6afa8c2017-11-30 17:55:05 +0800576 unsigned long flags;
Meng Wang9730cdd2017-09-26 12:48:31 +0800577
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530578 pr_debug("%s: sessionid[%d]\n", __func__, ac->session);
Meng Wang9730cdd2017-09-26 12:48:31 +0800579 session_id = ac->session;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530580 rtac_remove_popp_from_adm_devices(ac->session);
Meng Wangb6afa8c2017-11-30 17:55:05 +0800581 spin_lock_irqsave(&(session[session_id].session_lock), flags);
Meng Wang9730cdd2017-09-26 12:48:31 +0800582 session[ac->session].ac = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530583 ac->session = 0;
584 ac->perf_mode = LEGACY_PCM_MODE;
585 ac->fptr_cache_ops = NULL;
Meng Wang9730cdd2017-09-26 12:48:31 +0800586 ac->cb = NULL;
587 ac->priv = NULL;
588 kfree(ac);
589 ac = NULL;
Meng Wangb6afa8c2017-11-30 17:55:05 +0800590 spin_unlock_irqrestore(&(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530591}
592
593static uint32_t q6asm_get_next_buf(struct audio_client *ac,
594 uint32_t curr_buf, uint32_t max_buf_cnt)
595{
596 dev_vdbg(ac->dev, "%s: curr_buf = %d, max_buf_cnt = %d\n",
597 __func__, curr_buf, max_buf_cnt);
598 curr_buf += 1;
599 return (curr_buf >= max_buf_cnt) ? 0 : curr_buf;
600}
601
602static int q6asm_map_cal_memory(int32_t cal_type,
603 struct cal_block_data *cal_block)
604{
605 int result = 0;
606 struct asm_buffer_node *buf_node = NULL;
607 struct list_head *ptr, *next;
608
609 if (cal_block == NULL) {
610 pr_err("%s: cal_block is NULL!\n",
611 __func__);
612 goto done;
613 }
614
615 if (cal_block->cal_data.paddr == 0) {
616 pr_debug("%s: No address to map!\n",
617 __func__);
618 goto done;
619 }
620
621 common_client.mmap_apr = q6asm_mmap_apr_reg();
622 if (common_client.mmap_apr == NULL) {
623 pr_err("%s: q6asm_mmap_apr_reg failed\n",
624 __func__);
625 result = -EPERM;
626 goto done;
627 }
628 common_client.apr = common_client.mmap_apr;
629 if (cal_block->map_data.map_size == 0) {
630 pr_debug("%s: map size is 0!\n",
631 __func__);
632 goto done;
633 }
634
635 /* Use second asm buf to map memory */
636 if (common_client.port[IN].buf == NULL) {
637 pr_err("%s: common buf is NULL\n",
638 __func__);
639 result = -EINVAL;
640 goto done;
641 }
642
643 common_client.port[IN].buf->phys = cal_block->cal_data.paddr;
644
645 result = q6asm_memory_map_regions(&common_client,
646 IN, cal_block->map_data.map_size, 1, 1);
647 if (result < 0) {
648 pr_err("%s: mmap did not work! size = %zd result %d\n",
649 __func__,
650 cal_block->map_data.map_size, result);
651 pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n",
652 __func__,
653 &cal_block->cal_data.paddr,
654 cal_block->map_data.map_size);
655 goto done;
656 }
657
658 list_for_each_safe(ptr, next,
659 &common_client.port[IN].mem_map_handle) {
660 buf_node = list_entry(ptr, struct asm_buffer_node,
661 list);
662 if (buf_node->buf_phys_addr == cal_block->cal_data.paddr) {
663 cal_block->map_data.q6map_handle = buf_node->mmap_hdl;
664 break;
665 }
666 }
667done:
668 return result;
669}
670
671static int remap_cal_data(int32_t cal_type, struct cal_block_data *cal_block)
672{
673 int ret = 0;
674
675 if (cal_block->map_data.ion_client == NULL) {
676 pr_err("%s: No ION allocation for cal type %d!\n",
677 __func__, cal_type);
678 ret = -EINVAL;
679 goto done;
680 }
681
682 if ((cal_block->map_data.map_size > 0) &&
683 (cal_block->map_data.q6map_handle == 0)) {
684
685 ret = q6asm_map_cal_memory(cal_type, cal_block);
686 if (ret < 0) {
687 pr_err("%s: mmap did not work! size = %zd ret %d\n",
688 __func__, cal_block->map_data.map_size, ret);
689 goto done;
690 }
691 }
692done:
693 return ret;
694}
695
696static int q6asm_unmap_cal_memory(int32_t cal_type,
697 struct cal_block_data *cal_block)
698{
699 int result = 0;
700 int result2 = 0;
701
702 if (cal_block == NULL) {
703 pr_err("%s: cal_block is NULL!\n",
704 __func__);
705 result = -EINVAL;
706 goto done;
707 }
708
709 if (cal_block->map_data.q6map_handle == 0) {
710 pr_debug("%s: No address to unmap!\n",
711 __func__);
712 result = -EINVAL;
713 goto done;
714 }
715
716 if (common_client.mmap_apr == NULL) {
717 common_client.mmap_apr = q6asm_mmap_apr_reg();
718 if (common_client.mmap_apr == NULL) {
719 pr_err("%s: q6asm_mmap_apr_reg failed\n",
720 __func__);
721 result = -EPERM;
722 goto done;
723 }
724 }
725
726 result2 = q6asm_memory_unmap_regions(&common_client, IN);
727 if (result2 < 0) {
728 pr_err("%s: unmap failed, err %d\n",
729 __func__, result2);
730 result = result2;
731 }
732
733 cal_block->map_data.q6map_handle = 0;
734done:
735 return result;
736}
737
738int q6asm_unmap_cal_data(int cal_type, struct cal_block_data *cal_block)
739{
740 int ret = 0;
741
742 if ((cal_block->map_data.map_size > 0) &&
743 (cal_block->map_data.q6map_handle != 0)) {
744
745 ret = q6asm_unmap_cal_memory(cal_type, cal_block);
746 if (ret < 0) {
747 pr_err("%s: unmap did not work! size = %zd ret %d\n",
748 __func__, cal_block->map_data.map_size, ret);
749 goto done;
750 }
751 }
752done:
753 return ret;
754}
755
756int send_asm_custom_topology(struct audio_client *ac)
757{
758 struct cal_block_data *cal_block = NULL;
759 struct cmd_set_topologies asm_top;
760 int result = 0;
761 int result1 = 0;
762
763 if (cal_data[ASM_CUSTOM_TOP_CAL] == NULL)
764 goto done;
765
766 mutex_lock(&cal_data[ASM_CUSTOM_TOP_CAL]->lock);
767 if (!set_custom_topology)
768 goto unlock;
769 set_custom_topology = 0;
770
771 cal_block = cal_utils_get_only_cal_block(cal_data[ASM_CUSTOM_TOP_CAL]);
772 if (cal_block == NULL)
773 goto unlock;
774
775 if (cal_block->cal_data.size == 0) {
776 pr_debug("%s: No cal to send!\n", __func__);
777 goto unlock;
778 }
779
780 pr_debug("%s: Sending cal_index %d\n", __func__, ASM_CUSTOM_TOP_CAL);
781
782 result = remap_cal_data(ASM_CUST_TOPOLOGY_CAL_TYPE, cal_block);
783 if (result) {
784 pr_err("%s: Remap_cal_data failed for cal %d!\n",
785 __func__, ASM_CUSTOM_TOP_CAL);
786 goto unlock;
787 }
788
789 q6asm_add_hdr_custom_topology(ac, &asm_top.hdr, sizeof(asm_top));
790 atomic_set(&ac->mem_state, -1);
791 asm_top.hdr.opcode = ASM_CMD_ADD_TOPOLOGIES;
792 asm_top.payload_addr_lsw = lower_32_bits(cal_block->cal_data.paddr);
793 asm_top.payload_addr_msw = msm_audio_populate_upper_32_bits(
794 cal_block->cal_data.paddr);
795 asm_top.mem_map_handle = cal_block->map_data.q6map_handle;
796 asm_top.payload_size = cal_block->cal_data.size;
797
798 pr_debug("%s: Sending ASM_CMD_ADD_TOPOLOGIES payload = %pK, size = %d, map handle = 0x%x\n",
799 __func__, &cal_block->cal_data.paddr,
800 asm_top.payload_size, asm_top.mem_map_handle);
801
802 result = apr_send_pkt(ac->apr, (uint32_t *) &asm_top);
803 if (result < 0) {
804 pr_err("%s: Set topologies failed result %d\n",
805 __func__, result);
806 pr_debug("%s: Set topologies failed payload = 0x%pK\n",
807 __func__, &cal_block->cal_data.paddr);
808 goto unmap;
809
810 }
811
812 result = wait_event_timeout(ac->mem_wait,
813 (atomic_read(&ac->mem_state) >= 0), 5*HZ);
814 if (!result) {
815 pr_err("%s: Set topologies failed timeout\n", __func__);
816 pr_debug("%s: Set topologies failed after timedout payload = 0x%pK\n",
817 __func__, &cal_block->cal_data.paddr);
818 result = -ETIMEDOUT;
819 goto unmap;
820 }
821 if (atomic_read(&ac->mem_state) > 0) {
822 pr_err("%s: DSP returned error[%s]\n",
823 __func__, adsp_err_get_err_str(
824 atomic_read(&ac->mem_state)));
825 result = adsp_err_get_lnx_err_code(
826 atomic_read(&ac->mem_state));
827 goto unmap;
828 }
829
830unmap:
831 result1 = q6asm_unmap_cal_memory(ASM_CUST_TOPOLOGY_CAL_TYPE,
832 cal_block);
833 if (result1 < 0) {
834 result = result1;
835 pr_debug("%s: unmap cal failed! %d\n", __func__, result);
836 }
837unlock:
838 mutex_unlock(&cal_data[ASM_CUSTOM_TOP_CAL]->lock);
839done:
840 return result;
841}
842
843int q6asm_map_rtac_block(struct rtac_cal_block_data *cal_block)
844{
845 int result = 0;
846 struct asm_buffer_node *buf_node = NULL;
847 struct list_head *ptr, *next;
848
849 pr_debug("%s:\n", __func__);
850
851 if (cal_block == NULL) {
852 pr_err("%s: cal_block is NULL!\n",
853 __func__);
854 result = -EINVAL;
855 goto done;
856 }
857
858 if (cal_block->cal_data.paddr == 0) {
859 pr_debug("%s: No address to map!\n",
860 __func__);
861 result = -EINVAL;
862 goto done;
863 }
864
865 if (common_client.mmap_apr == NULL) {
866 common_client.mmap_apr = q6asm_mmap_apr_reg();
867 if (common_client.mmap_apr == NULL) {
868 pr_err("%s: q6asm_mmap_apr_reg failed\n",
869 __func__);
870 result = -EPERM;
871 goto done;
872 }
873 }
874
875 if (cal_block->map_data.map_size == 0) {
876 pr_debug("%s: map size is 0!\n",
877 __func__);
878 result = -EINVAL;
879 goto done;
880 }
881
882 /* Use second asm buf to map memory */
883 if (common_client.port[OUT].buf == NULL) {
884 pr_err("%s: common buf is NULL\n",
885 __func__);
886 result = -EINVAL;
887 goto done;
888 }
889
890 common_client.port[OUT].buf->phys = cal_block->cal_data.paddr;
891
892 result = q6asm_memory_map_regions(&common_client,
893 OUT, cal_block->map_data.map_size, 1, 1);
894 if (result < 0) {
895 pr_err("%s: mmap did not work! size = %d result %d\n",
896 __func__,
897 cal_block->map_data.map_size, result);
898 pr_debug("%s: mmap did not work! addr = 0x%pK, size = %d\n",
899 __func__,
900 &cal_block->cal_data.paddr,
901 cal_block->map_data.map_size);
902 goto done;
903 }
904
905 list_for_each_safe(ptr, next,
906 &common_client.port[OUT].mem_map_handle) {
907 buf_node = list_entry(ptr, struct asm_buffer_node,
908 list);
909 if (buf_node->buf_phys_addr == cal_block->cal_data.paddr) {
910 cal_block->map_data.map_handle = buf_node->mmap_hdl;
911 break;
912 }
913 }
914done:
915 return result;
916}
917
918int q6asm_unmap_rtac_block(uint32_t *mem_map_handle)
919{
920 int result = 0;
921 int result2 = 0;
922
923 pr_debug("%s:\n", __func__);
924
925 if (mem_map_handle == NULL) {
926 pr_debug("%s: Map handle is NULL, nothing to unmap\n",
927 __func__);
928 goto done;
929 }
930
931 if (*mem_map_handle == 0) {
932 pr_debug("%s: Map handle is 0, nothing to unmap\n",
933 __func__);
934 goto done;
935 }
936
937 if (common_client.mmap_apr == NULL) {
938 common_client.mmap_apr = q6asm_mmap_apr_reg();
939 if (common_client.mmap_apr == NULL) {
940 pr_err("%s: q6asm_mmap_apr_reg failed\n",
941 __func__);
942 result = -EPERM;
943 goto done;
944 }
945 }
946
947
948 result2 = q6asm_memory_unmap_regions(&common_client, OUT);
949 if (result2 < 0) {
950 pr_err("%s: unmap failed, err %d\n",
951 __func__, result2);
952 result = result2;
953 } else {
954 mem_map_handle = 0;
955 }
956
957 result2 = q6asm_mmap_apr_dereg();
958 if (result2 < 0) {
959 pr_err("%s: q6asm_mmap_apr_dereg failed, err %d\n",
960 __func__, result2);
961 result = result2;
962 }
963done:
964 return result;
965}
966
967int q6asm_audio_client_buf_free(unsigned int dir,
968 struct audio_client *ac)
969{
970 struct audio_port_data *port;
971 int cnt = 0;
972 int rc = 0;
973
974 pr_debug("%s: Session id %d\n", __func__, ac->session);
975 mutex_lock(&ac->cmd_lock);
976 if (ac->io_mode & SYNC_IO_MODE) {
977 port = &ac->port[dir];
978 if (!port->buf) {
979 pr_err("%s: buf NULL\n", __func__);
980 mutex_unlock(&ac->cmd_lock);
981 return 0;
982 }
983 cnt = port->max_buf_cnt - 1;
984
985 if (cnt >= 0) {
986 rc = q6asm_memory_unmap_regions(ac, dir);
987 if (rc < 0)
988 pr_err("%s: Memory_unmap_regions failed %d\n",
989 __func__, rc);
990 }
991
992 while (cnt >= 0) {
993 if (port->buf[cnt].data) {
994 if (!rc || atomic_read(&ac->reset))
995 msm_audio_ion_free(
996 port->buf[cnt].client,
997 port->buf[cnt].handle);
998
999 port->buf[cnt].client = NULL;
1000 port->buf[cnt].handle = NULL;
1001 port->buf[cnt].data = NULL;
1002 port->buf[cnt].phys = 0;
1003 --(port->max_buf_cnt);
1004 }
1005 --cnt;
1006 }
1007 kfree(port->buf);
1008 port->buf = NULL;
1009 }
1010 mutex_unlock(&ac->cmd_lock);
1011 return 0;
1012}
1013
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301014/**
1015 * q6asm_audio_client_buf_free_contiguous -
1016 * frees the memory buffers for ASM
1017 *
1018 * @dir: RX or TX direction
1019 * @ac: audio client handle
1020 *
1021 * Returns 0 on success or error on failure
1022 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301023int q6asm_audio_client_buf_free_contiguous(unsigned int dir,
1024 struct audio_client *ac)
1025{
1026 struct audio_port_data *port;
1027 int cnt = 0;
1028 int rc = 0;
1029
1030 pr_debug("%s: Session id %d\n", __func__, ac->session);
1031 mutex_lock(&ac->cmd_lock);
1032 port = &ac->port[dir];
1033 if (!port->buf) {
1034 mutex_unlock(&ac->cmd_lock);
1035 return 0;
1036 }
1037 cnt = port->max_buf_cnt - 1;
1038
1039 if (cnt >= 0) {
1040 rc = q6asm_memory_unmap(ac, port->buf[0].phys, dir);
1041 if (rc < 0)
1042 pr_err("%s: Memory_unmap_regions failed %d\n",
1043 __func__, rc);
1044 }
1045
1046 if (port->buf[0].data) {
1047 pr_debug("%s: data[%pK]phys[%pK][%pK] , client[%pK] handle[%pK]\n",
1048 __func__,
1049 port->buf[0].data,
1050 &port->buf[0].phys,
1051 &port->buf[0].phys,
1052 port->buf[0].client,
1053 port->buf[0].handle);
1054 if (!rc || atomic_read(&ac->reset))
1055 msm_audio_ion_free(port->buf[0].client,
1056 port->buf[0].handle);
1057 port->buf[0].client = NULL;
1058 port->buf[0].handle = NULL;
1059 }
1060
1061 while (cnt >= 0) {
1062 port->buf[cnt].data = NULL;
1063 port->buf[cnt].phys = 0;
1064 cnt--;
1065 }
1066 port->max_buf_cnt = 0;
1067 kfree(port->buf);
1068 port->buf = NULL;
1069 mutex_unlock(&ac->cmd_lock);
1070 return 0;
1071}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301072EXPORT_SYMBOL(q6asm_audio_client_buf_free_contiguous);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301073
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301074/**
1075 * q6asm_audio_client_free -
1076 * frees the audio client for ASM
1077 *
1078 * @ac: audio client handle
1079 *
1080 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301081void q6asm_audio_client_free(struct audio_client *ac)
1082{
1083 int loopcnt;
1084 struct audio_port_data *port;
1085
1086 if (!ac) {
1087 pr_err("%s: ac %pK\n", __func__, ac);
1088 return;
1089 }
1090 if (!ac->session) {
1091 pr_err("%s: ac session invalid\n", __func__);
1092 return;
1093 }
1094
1095 mutex_lock(&session_lock);
1096
1097 pr_debug("%s: Session id %d\n", __func__, ac->session);
1098 if (ac->io_mode & SYNC_IO_MODE) {
1099 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
1100 port = &ac->port[loopcnt];
1101 if (!port->buf)
1102 continue;
1103 pr_debug("%s: loopcnt = %d\n",
1104 __func__, loopcnt);
1105 q6asm_audio_client_buf_free(loopcnt, ac);
1106 }
1107 }
1108
1109 rtac_set_asm_handle(ac->session, NULL);
1110 apr_deregister(ac->apr2);
1111 apr_deregister(ac->apr);
1112 q6asm_mmap_apr_dereg();
1113 ac->apr2 = NULL;
1114 ac->apr = NULL;
1115 ac->mmap_apr = NULL;
1116 q6asm_session_free(ac);
1117
1118 pr_debug("%s: APR De-Register\n", __func__);
1119
1120/*done:*/
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301121 mutex_unlock(&session_lock);
1122}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301123EXPORT_SYMBOL(q6asm_audio_client_free);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301124
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301125/**
1126 * q6asm_set_io_mode -
1127 * Update IO mode for ASM
1128 *
1129 * @ac: audio client handle
1130 * @mode1: IO mode to update
1131 *
1132 * Returns 0 on success or error on failure
1133 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301134int q6asm_set_io_mode(struct audio_client *ac, uint32_t mode1)
1135{
1136 uint32_t mode;
1137 int ret = 0;
1138
1139 if (ac == NULL) {
1140 pr_err("%s: APR handle NULL\n", __func__);
1141 return -EINVAL;
1142 }
1143
1144 ac->io_mode &= 0xFF00;
1145 mode = (mode1 & 0xF);
1146
1147 pr_debug("%s: ac->mode after anding with FF00:0x%x,\n",
1148 __func__, ac->io_mode);
1149
1150 if ((mode == ASYNC_IO_MODE) || (mode == SYNC_IO_MODE)) {
1151 ac->io_mode |= mode1;
1152 pr_debug("%s: Set Mode to 0x%x\n", __func__, ac->io_mode);
1153 } else {
1154 pr_err("%s: Not an valid IO Mode:%d\n", __func__, ac->io_mode);
1155 ret = -EINVAL;
1156 }
1157
1158 return ret;
1159}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301160EXPORT_SYMBOL(q6asm_set_io_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301161
1162void *q6asm_mmap_apr_reg(void)
1163{
1164 if ((atomic_read(&this_mmap.ref_cnt) == 0) ||
1165 (this_mmap.apr == NULL)) {
1166 this_mmap.apr = apr_register("ADSP", "ASM",
1167 (apr_fn)q6asm_srvc_callback,
1168 0x0FFFFFFFF, &this_mmap);
1169 if (this_mmap.apr == NULL) {
1170 pr_debug("%s: Unable to register APR ASM common port\n",
1171 __func__);
1172 goto fail;
1173 }
1174 }
1175 atomic_inc(&this_mmap.ref_cnt);
1176
1177 return this_mmap.apr;
1178fail:
1179 return NULL;
1180}
1181
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301182/**
1183 * q6asm_send_stream_cmd -
1184 * command to send for ASM stream
1185 *
1186 * @ac: audio client handle
1187 * @data: event data
1188 *
1189 * Returns 0 on success or error on failure
1190 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301191int q6asm_send_stream_cmd(struct audio_client *ac,
1192 struct msm_adsp_event_data *data)
1193{
1194 char *asm_params = NULL;
1195 struct apr_hdr hdr;
Aditya Bavanari2e3341d2018-02-23 12:58:57 +05301196 int rc;
1197 uint32_t sz = 0;
1198 uint64_t actual_sz = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301199
1200 if (!data || !ac) {
1201 pr_err("%s: %s is NULL\n", __func__,
1202 (!data) ? "data" : "ac");
1203 rc = -EINVAL;
1204 goto done;
1205 }
1206
1207 if (data->event_type >= ARRAY_SIZE(adsp_reg_event_opcode)) {
1208 pr_err("%s: event %u out of boundary of array size of (%lu)\n",
1209 __func__, data->event_type,
1210 (long)ARRAY_SIZE(adsp_reg_event_opcode));
1211 rc = -EINVAL;
1212 goto done;
1213 }
1214
Aditya Bavanari2e3341d2018-02-23 12:58:57 +05301215 actual_sz = sizeof(struct apr_hdr) + data->payload_len;
1216 if (actual_sz > U32_MAX) {
1217 pr_err("%s: payload size 0x%X exceeds limit\n",
1218 __func__, data->payload_len);
1219 rc = -EINVAL;
1220 goto done;
1221 }
1222
1223 sz = (uint32_t)actual_sz;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301224 asm_params = kzalloc(sz, GFP_KERNEL);
1225 if (!asm_params) {
1226 rc = -ENOMEM;
1227 goto done;
1228 }
1229
1230 q6asm_add_hdr_async(ac, &hdr, sz, TRUE);
1231 atomic_set(&ac->cmd_state_pp, -1);
1232 hdr.opcode = adsp_reg_event_opcode[data->event_type];
1233 memcpy(asm_params, &hdr, sizeof(struct apr_hdr));
1234 memcpy(asm_params + sizeof(struct apr_hdr),
1235 data->payload, data->payload_len);
1236 rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
1237 if (rc < 0) {
1238 pr_err("%s: stream event cmd apr pkt failed\n", __func__);
1239 rc = -EINVAL;
1240 goto fail_send_param;
1241 }
1242
1243 rc = wait_event_timeout(ac->cmd_wait,
1244 (atomic_read(&ac->cmd_state_pp) >= 0), 1 * HZ);
1245 if (!rc) {
1246 pr_err("%s: timeout for stream event cmd resp\n", __func__);
1247 rc = -ETIMEDOUT;
1248 goto fail_send_param;
1249 }
1250
1251 if (atomic_read(&ac->cmd_state_pp) > 0) {
1252 pr_err("%s: DSP returned error[%s] for stream event cmd\n",
1253 __func__, adsp_err_get_err_str(
1254 atomic_read(&ac->cmd_state_pp)));
1255 rc = adsp_err_get_lnx_err_code(
1256 atomic_read(&ac->cmd_state_pp));
1257 goto fail_send_param;
1258 }
1259
1260 rc = 0;
1261fail_send_param:
1262 kfree(asm_params);
1263done:
1264 return rc;
1265}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301266EXPORT_SYMBOL(q6asm_send_stream_cmd);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301267
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301268/**
1269 * q6asm_audio_client_alloc -
1270 * Alloc audio client for ASM
1271 *
1272 * @cb: callback fn
1273 * @priv: private data
1274 *
1275 * Returns ac pointer on success or NULL on failure
1276 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301277struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv)
1278{
1279 struct audio_client *ac;
1280 int n;
1281 int lcnt = 0;
1282 int rc = 0;
1283
1284 ac = kzalloc(sizeof(struct audio_client), GFP_KERNEL);
1285 if (!ac)
1286 return NULL;
1287
1288 mutex_lock(&session_lock);
1289 n = q6asm_session_alloc(ac);
1290 if (n <= 0) {
1291 pr_err("%s: ASM Session alloc fail n=%d\n", __func__, n);
1292 mutex_unlock(&session_lock);
Meng Wang9730cdd2017-09-26 12:48:31 +08001293 kfree(ac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301294 goto fail_session;
1295 }
1296 ac->session = n;
1297 ac->cb = cb;
1298 ac->path_delay = UINT_MAX;
1299 ac->priv = priv;
1300 ac->io_mode = SYNC_IO_MODE;
1301 ac->perf_mode = LEGACY_PCM_MODE;
1302 ac->fptr_cache_ops = NULL;
1303 /* DSP expects stream id from 1 */
1304 ac->stream_id = 1;
1305 ac->apr = apr_register("ADSP", "ASM",
1306 (apr_fn)q6asm_callback,
1307 ((ac->session) << 8 | 0x0001),
1308 ac);
1309
1310 if (ac->apr == NULL) {
1311 pr_err("%s: Registration with APR failed\n", __func__);
1312 mutex_unlock(&session_lock);
1313 goto fail_apr1;
1314 }
1315 ac->apr2 = apr_register("ADSP", "ASM",
1316 (apr_fn)q6asm_callback,
1317 ((ac->session) << 8 | 0x0002),
1318 ac);
1319
1320 if (ac->apr2 == NULL) {
1321 pr_err("%s: Registration with APR-2 failed\n", __func__);
1322 mutex_unlock(&session_lock);
1323 goto fail_apr2;
1324 }
1325
1326 rtac_set_asm_handle(n, ac->apr);
1327
1328 pr_debug("%s: Registering the common port with APR\n", __func__);
1329 ac->mmap_apr = q6asm_mmap_apr_reg();
1330 if (ac->mmap_apr == NULL) {
1331 mutex_unlock(&session_lock);
1332 goto fail_mmap;
1333 }
1334
1335 init_waitqueue_head(&ac->cmd_wait);
1336 init_waitqueue_head(&ac->time_wait);
1337 init_waitqueue_head(&ac->mem_wait);
1338 atomic_set(&ac->time_flag, 1);
1339 atomic_set(&ac->reset, 0);
1340 INIT_LIST_HEAD(&ac->port[0].mem_map_handle);
1341 INIT_LIST_HEAD(&ac->port[1].mem_map_handle);
1342 pr_debug("%s: mem_map_handle list init'ed\n", __func__);
1343 mutex_init(&ac->cmd_lock);
1344 for (lcnt = 0; lcnt <= OUT; lcnt++) {
1345 mutex_init(&ac->port[lcnt].lock);
1346 spin_lock_init(&ac->port[lcnt].dsp_lock);
1347 }
1348 atomic_set(&ac->cmd_state, 0);
1349 atomic_set(&ac->cmd_state_pp, 0);
1350 atomic_set(&ac->mem_state, 0);
1351
1352 rc = send_asm_custom_topology(ac);
1353 if (rc < 0) {
1354 mutex_unlock(&session_lock);
1355 goto fail_mmap;
1356 }
1357
1358 pr_debug("%s: session[%d]\n", __func__, ac->session);
1359
1360 mutex_unlock(&session_lock);
1361
1362 return ac;
1363fail_mmap:
1364 apr_deregister(ac->apr2);
1365fail_apr2:
1366 apr_deregister(ac->apr);
1367fail_apr1:
1368 q6asm_session_free(ac);
1369fail_session:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301370 return NULL;
1371}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301372EXPORT_SYMBOL(q6asm_audio_client_alloc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301373
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301374/**
1375 * q6asm_get_audio_client -
1376 * Retrieve audio client for ASM
1377 *
1378 * @session_id: ASM session id
1379 *
1380 * Returns valid pointer on success or NULL on failure
1381 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301382struct audio_client *q6asm_get_audio_client(int session_id)
1383{
1384 if (session_id == ASM_CONTROL_SESSION)
1385 return &common_client;
1386
1387 if ((session_id <= 0) || (session_id > ASM_ACTIVE_STREAMS_ALLOWED)) {
1388 pr_err("%s: invalid session: %d\n", __func__, session_id);
1389 goto err;
1390 }
1391
Meng Wang9730cdd2017-09-26 12:48:31 +08001392 if (!(session[session_id].ac)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301393 pr_err("%s: session not active: %d\n", __func__, session_id);
1394 goto err;
1395 }
Meng Wang9730cdd2017-09-26 12:48:31 +08001396 return session[session_id].ac;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301397err:
1398 return NULL;
1399}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301400EXPORT_SYMBOL(q6asm_get_audio_client);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301401
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301402/**
1403 * q6asm_audio_client_buf_alloc -
1404 * Allocs memory from ION for ASM
1405 *
1406 * @dir: RX or TX direction
1407 * @ac: Audio client handle
1408 * @bufsz: size of each buffer
1409 * @bufcnt: number of buffers to alloc
1410 *
1411 * Returns 0 on success or error on failure
1412 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301413int q6asm_audio_client_buf_alloc(unsigned int dir,
1414 struct audio_client *ac,
1415 unsigned int bufsz,
1416 uint32_t bufcnt)
1417{
1418 int cnt = 0;
1419 int rc = 0;
1420 struct audio_buffer *buf;
1421 size_t len;
1422
1423 if (!(ac) || !(bufsz) || ((dir != IN) && (dir != OUT))) {
1424 pr_err("%s: ac %pK bufsz %d dir %d\n", __func__, ac, bufsz,
1425 dir);
1426 return -EINVAL;
1427 }
1428
1429 pr_debug("%s: session[%d]bufsz[%d]bufcnt[%d]\n", __func__, ac->session,
1430 bufsz, bufcnt);
1431
1432 if (ac->session <= 0 || ac->session > 8) {
1433 pr_err("%s: Session ID is invalid, session = %d\n", __func__,
1434 ac->session);
1435 goto fail;
1436 }
1437
1438 if (ac->io_mode & SYNC_IO_MODE) {
1439 if (ac->port[dir].buf) {
1440 pr_debug("%s: buffer already allocated\n", __func__);
1441 return 0;
1442 }
1443 mutex_lock(&ac->cmd_lock);
1444 if (bufcnt > (U32_MAX/sizeof(struct audio_buffer))) {
1445 pr_err("%s: Buffer size overflows", __func__);
1446 mutex_unlock(&ac->cmd_lock);
1447 goto fail;
1448 }
1449 buf = kzalloc(((sizeof(struct audio_buffer))*bufcnt),
1450 GFP_KERNEL);
1451
1452 if (!buf) {
1453 mutex_unlock(&ac->cmd_lock);
1454 goto fail;
1455 }
1456
1457 ac->port[dir].buf = buf;
1458
1459 while (cnt < bufcnt) {
1460 if (bufsz > 0) {
1461 if (!buf[cnt].data) {
1462 rc = msm_audio_ion_alloc("asm_client",
1463 &buf[cnt].client, &buf[cnt].handle,
1464 bufsz,
1465 (ion_phys_addr_t *)&buf[cnt].phys,
1466 &len,
1467 &buf[cnt].data);
1468 if (rc) {
1469 pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
1470 __func__, rc);
1471 mutex_unlock(&ac->cmd_lock);
1472 goto fail;
1473 }
1474
1475 buf[cnt].used = 1;
1476 buf[cnt].size = bufsz;
1477 buf[cnt].actual_size = bufsz;
1478 pr_debug("%s: data[%pK]phys[%pK][%pK]\n",
1479 __func__,
1480 buf[cnt].data,
1481 &buf[cnt].phys,
1482 &buf[cnt].phys);
1483 cnt++;
1484 }
1485 }
1486 }
1487 ac->port[dir].max_buf_cnt = cnt;
1488
1489 mutex_unlock(&ac->cmd_lock);
1490 rc = q6asm_memory_map_regions(ac, dir, bufsz, cnt, 0);
1491 if (rc < 0) {
1492 pr_err("%s: CMD Memory_map_regions failed %d for size %d\n",
1493 __func__, rc, bufsz);
1494 goto fail;
1495 }
1496 }
1497 return 0;
1498fail:
1499 q6asm_audio_client_buf_free(dir, ac);
1500 return -EINVAL;
1501}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301502EXPORT_SYMBOL(q6asm_audio_client_buf_alloc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301503
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301504/**
1505 * q6asm_audio_client_buf_alloc_contiguous -
1506 * Alloc contiguous memory from ION for ASM
1507 *
1508 * @dir: RX or TX direction
1509 * @ac: Audio client handle
1510 * @bufsz: size of each buffer
1511 * @bufcnt: number of buffers to alloc
1512 *
1513 * Returns 0 on success or error on failure
1514 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301515int q6asm_audio_client_buf_alloc_contiguous(unsigned int dir,
1516 struct audio_client *ac,
1517 unsigned int bufsz,
1518 unsigned int bufcnt)
1519{
1520 int cnt = 0;
1521 int rc = 0;
1522 struct audio_buffer *buf;
1523 size_t len;
1524 int bytes_to_alloc;
1525
1526 if (!(ac) || ((dir != IN) && (dir != OUT))) {
1527 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
1528 return -EINVAL;
1529 }
1530
1531 pr_debug("%s: session[%d]bufsz[%d]bufcnt[%d]\n",
1532 __func__, ac->session,
1533 bufsz, bufcnt);
1534
1535 if (ac->session <= 0 || ac->session > 8) {
1536 pr_err("%s: Session ID is invalid, session = %d\n", __func__,
1537 ac->session);
1538 goto fail;
1539 }
1540
1541 if (ac->port[dir].buf) {
1542 pr_err("%s: buffer already allocated\n", __func__);
1543 return 0;
1544 }
1545 mutex_lock(&ac->cmd_lock);
1546 buf = kzalloc(((sizeof(struct audio_buffer))*bufcnt),
1547 GFP_KERNEL);
1548
1549 if (!buf) {
1550 pr_err("%s: buffer allocation failed\n", __func__);
1551 mutex_unlock(&ac->cmd_lock);
1552 goto fail;
1553 }
1554
1555 ac->port[dir].buf = buf;
1556
1557 /* check for integer overflow */
1558 if ((bufcnt > 0) && ((INT_MAX / bufcnt) < bufsz)) {
1559 pr_err("%s: integer overflow\n", __func__);
1560 mutex_unlock(&ac->cmd_lock);
1561 goto fail;
1562 }
1563 bytes_to_alloc = bufsz * bufcnt;
1564
1565 /* The size to allocate should be multiple of 4K bytes */
1566 bytes_to_alloc = PAGE_ALIGN(bytes_to_alloc);
1567
1568 rc = msm_audio_ion_alloc("asm_client", &buf[0].client, &buf[0].handle,
1569 bytes_to_alloc,
1570 (ion_phys_addr_t *)&buf[0].phys, &len,
1571 &buf[0].data);
1572 if (rc) {
1573 pr_err("%s: Audio ION alloc is failed, rc = %d\n",
1574 __func__, rc);
1575 mutex_unlock(&ac->cmd_lock);
1576 goto fail;
1577 }
1578
1579 buf[0].used = dir ^ 1;
1580 buf[0].size = bufsz;
1581 buf[0].actual_size = bufsz;
1582 cnt = 1;
1583 while (cnt < bufcnt) {
1584 if (bufsz > 0) {
1585 buf[cnt].data = buf[0].data + (cnt * bufsz);
1586 buf[cnt].phys = buf[0].phys + (cnt * bufsz);
1587 if (!buf[cnt].data) {
1588 pr_err("%s: Buf alloc failed\n",
1589 __func__);
1590 mutex_unlock(&ac->cmd_lock);
1591 goto fail;
1592 }
1593 buf[cnt].used = dir ^ 1;
1594 buf[cnt].size = bufsz;
1595 buf[cnt].actual_size = bufsz;
1596 pr_debug("%s: data[%pK]phys[%pK][%pK]\n",
1597 __func__,
1598 buf[cnt].data,
1599 &buf[cnt].phys,
1600 &buf[cnt].phys);
1601 }
1602 cnt++;
1603 }
1604 ac->port[dir].max_buf_cnt = cnt;
1605 mutex_unlock(&ac->cmd_lock);
1606 rc = q6asm_memory_map_regions(ac, dir, bufsz, cnt, 1);
1607 if (rc < 0) {
1608 pr_err("%s: CMD Memory_map_regions failed %d for size %d\n",
1609 __func__, rc, bufsz);
1610 goto fail;
1611 }
1612 return 0;
1613fail:
1614 q6asm_audio_client_buf_free_contiguous(dir, ac);
1615 return -EINVAL;
1616}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301617EXPORT_SYMBOL(q6asm_audio_client_buf_alloc_contiguous);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301618
1619static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
1620{
1621 uint32_t dir = 0;
1622 uint32_t i = IN;
1623 uint32_t *payload;
1624 unsigned long dsp_flags;
Meng Wangb6afa8c2017-11-30 17:55:05 +08001625 unsigned long flags = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301626 struct asm_buffer_node *buf_node = NULL;
1627 struct list_head *ptr, *next;
1628 union asm_token_struct asm_token;
1629
1630 struct audio_client *ac = NULL;
1631 struct audio_port_data *port;
1632
Meng Wang9730cdd2017-09-26 12:48:31 +08001633 int session_id;
1634
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301635 if (!data) {
1636 pr_err("%s: Invalid CB\n", __func__);
1637 return 0;
1638 }
1639
1640 payload = data->payload;
1641
1642 if (data->opcode == RESET_EVENTS) {
1643 pr_debug("%s: Reset event is received: %d %d apr[%pK]\n",
1644 __func__,
1645 data->reset_event,
1646 data->reset_proc,
1647 this_mmap.apr);
1648 atomic_set(&this_mmap.ref_cnt, 0);
1649 apr_reset(this_mmap.apr);
1650 this_mmap.apr = NULL;
1651 for (; i <= OUT; i++) {
1652 list_for_each_safe(ptr, next,
1653 &common_client.port[i].mem_map_handle) {
1654 buf_node = list_entry(ptr,
1655 struct asm_buffer_node,
1656 list);
1657 if (buf_node->buf_phys_addr ==
1658 common_client.port[i].buf->phys) {
1659 list_del(&buf_node->list);
1660 kfree(buf_node);
1661 }
1662 }
1663 pr_debug("%s: Clearing custom topology\n", __func__);
1664 }
1665
1666 cal_utils_clear_cal_block_q6maps(ASM_MAX_CAL_TYPES, cal_data);
1667 common_client.mmap_apr = NULL;
1668 mutex_lock(&cal_data[ASM_CUSTOM_TOP_CAL]->lock);
1669 set_custom_topology = 1;
1670 mutex_unlock(&cal_data[ASM_CUSTOM_TOP_CAL]->lock);
1671 topology_map_handle = 0;
1672 rtac_clear_mapping(ASM_RTAC_CAL);
1673 return 0;
1674 }
1675 asm_token.token = data->token;
Meng Wang9730cdd2017-09-26 12:48:31 +08001676 session_id = asm_token._token.session_id;
1677
1678 if ((session_id > 0 && session_id <= ASM_ACTIVE_STREAMS_ALLOWED))
Meng Wangb6afa8c2017-11-30 17:55:05 +08001679 spin_lock_irqsave(&(session[session_id].session_lock), flags);
Meng Wang9730cdd2017-09-26 12:48:31 +08001680
1681 ac = q6asm_get_audio_client(session_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301682 dir = q6asm_get_flag_from_token(&asm_token, ASM_DIRECTION_OFFSET);
1683
1684 if (!ac) {
1685 pr_debug("%s: session[%d] already freed\n",
Meng Wang9730cdd2017-09-26 12:48:31 +08001686 __func__, session_id);
1687 if ((session_id > 0 &&
1688 session_id <= ASM_ACTIVE_STREAMS_ALLOWED))
Meng Wangb6afa8c2017-11-30 17:55:05 +08001689 spin_unlock_irqrestore(
1690 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301691 return 0;
1692 }
1693
1694 if (data->payload_size > sizeof(int)) {
1695 pr_debug("%s:ptr0[0x%x]ptr1[0x%x]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]sid[%d]dir[%d]\n",
1696 __func__, payload[0], payload[1], data->opcode,
1697 data->token, data->payload_size, data->src_port,
1698 data->dest_port, asm_token._token.session_id, dir);
1699 pr_debug("%s:Payload = [0x%x] status[0x%x]\n",
1700 __func__, payload[0], payload[1]);
1701 } else if (data->payload_size == sizeof(int)) {
1702 pr_debug("%s:ptr0[0x%x]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]sid[%d]dir[%d]\n",
1703 __func__, payload[0], data->opcode,
1704 data->token, data->payload_size, data->src_port,
1705 data->dest_port, asm_token._token.session_id, dir);
1706 pr_debug("%s:Payload = [0x%x]\n",
1707 __func__, payload[0]);
1708 }
1709
1710 if (data->opcode == APR_BASIC_RSP_RESULT) {
1711 switch (payload[0]) {
1712 case ASM_CMD_SHARED_MEM_MAP_REGIONS:
1713 case ASM_CMD_SHARED_MEM_UNMAP_REGIONS:
1714 case ASM_CMD_ADD_TOPOLOGIES:
1715 if (payload[1] != 0) {
1716 pr_err("%s: cmd = 0x%x returned error = 0x%x sid:%d\n",
1717 __func__, payload[0], payload[1],
1718 asm_token._token.session_id);
1719 if (payload[0] ==
1720 ASM_CMD_SHARED_MEM_UNMAP_REGIONS)
1721 atomic_set(&ac->unmap_cb_success, 0);
1722
1723 atomic_set(&ac->mem_state, payload[1]);
1724 wake_up(&ac->mem_wait);
1725 } else {
1726 if (payload[0] ==
1727 ASM_CMD_SHARED_MEM_UNMAP_REGIONS)
1728 atomic_set(&ac->unmap_cb_success, 1);
1729 }
1730
1731 if (atomic_cmpxchg(&ac->mem_state, -1, 0) == -1)
1732 wake_up(&ac->mem_wait);
1733 dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x]\n",
1734 __func__, payload[0], payload[1]);
1735 break;
1736 default:
1737 pr_debug("%s: command[0x%x] not expecting rsp\n",
1738 __func__, payload[0]);
1739 break;
1740 }
Meng Wang9730cdd2017-09-26 12:48:31 +08001741 if ((session_id > 0 &&
1742 session_id <= ASM_ACTIVE_STREAMS_ALLOWED))
Meng Wangb6afa8c2017-11-30 17:55:05 +08001743 spin_unlock_irqrestore(
1744 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301745 return 0;
1746 }
1747
1748 port = &ac->port[dir];
1749
1750 switch (data->opcode) {
1751 case ASM_CMDRSP_SHARED_MEM_MAP_REGIONS:{
1752 pr_debug("%s:PL#0[0x%x] dir=0x%x s_id=0x%x\n",
1753 __func__, payload[0], dir, asm_token._token.session_id);
1754 spin_lock_irqsave(&port->dsp_lock, dsp_flags);
1755 if (atomic_cmpxchg(&ac->mem_state, -1, 0) == -1) {
1756 ac->port[dir].tmp_hdl = payload[0];
1757 wake_up(&ac->mem_wait);
1758 }
1759 spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
1760 break;
1761 }
1762 case ASM_CMD_SHARED_MEM_UNMAP_REGIONS:{
1763 pr_debug("%s: PL#0[0x%x]PL#1 [0x%x]\n",
1764 __func__, payload[0], payload[1]);
1765 spin_lock_irqsave(&port->dsp_lock, dsp_flags);
1766 if (atomic_cmpxchg(&ac->mem_state, -1, 0) == -1)
1767 wake_up(&ac->mem_wait);
1768 spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
1769
1770 break;
1771 }
1772 default:
1773 pr_debug("%s: command[0x%x]success [0x%x]\n",
1774 __func__, payload[0], payload[1]);
1775 }
1776 if (ac->cb)
1777 ac->cb(data->opcode, data->token,
1778 data->payload, ac->priv);
Meng Wang9730cdd2017-09-26 12:48:31 +08001779 if ((session_id > 0 && session_id <= ASM_ACTIVE_STREAMS_ALLOWED))
Meng Wangb6afa8c2017-11-30 17:55:05 +08001780 spin_unlock_irqrestore(
1781 &(session[session_id].session_lock), flags);
Meng Wang9730cdd2017-09-26 12:48:31 +08001782
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301783 return 0;
1784}
1785
1786static void q6asm_process_mtmx_get_param_rsp(struct audio_client *ac,
1787 struct asm_mtmx_strtr_get_params_cmdrsp *cmdrsp)
1788{
1789 struct asm_session_mtmx_strtr_param_session_time_v3_t *time;
1790
1791 if (cmdrsp->err_code) {
1792 dev_err_ratelimited(ac->dev,
1793 "%s: err=%x, mod_id=%x, param_id=%x\n",
1794 __func__, cmdrsp->err_code,
1795 cmdrsp->param_info.module_id,
1796 cmdrsp->param_info.param_id);
1797 return;
1798 }
1799 dev_dbg_ratelimited(ac->dev,
1800 "%s: mod_id=%x, param_id=%x\n", __func__,
1801 cmdrsp->param_info.module_id,
1802 cmdrsp->param_info.param_id);
1803
1804 switch (cmdrsp->param_info.module_id) {
1805 case ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC:
1806 switch (cmdrsp->param_info.param_id) {
1807 case ASM_SESSION_MTMX_STRTR_PARAM_SESSION_TIME_V3:
1808 time = &cmdrsp->param_data.session_time;
1809 dev_vdbg(ac->dev, "%s: GET_TIME_V3, time_lsw=%x, time_msw=%x\n",
1810 __func__, time->session_time_lsw,
1811 time->session_time_msw);
1812 ac->time_stamp = (uint64_t)(((uint64_t)
1813 time->session_time_msw << 32) |
1814 time->session_time_lsw);
1815 if (time->flags &
1816 ASM_SESSION_MTMX_STRTR_PARAM_STIME_TSTMP_FLG_BMASK)
1817 dev_warn_ratelimited(ac->dev,
1818 "%s: recv inval tstmp\n",
1819 __func__);
1820 if (atomic_cmpxchg(&ac->time_flag, 1, 0))
1821 wake_up(&ac->time_wait);
1822
1823 break;
1824 default:
1825 dev_err(ac->dev, "%s: unexpected param_id %x\n",
1826 __func__, cmdrsp->param_info.param_id);
1827 break;
1828 }
1829 break;
1830 default:
1831 dev_err(ac->dev, "%s: unexpected mod_id %x\n", __func__,
1832 cmdrsp->param_info.module_id);
1833 break;
1834 }
1835}
1836
1837static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
1838{
1839 int i = 0;
1840 struct audio_client *ac = (struct audio_client *)priv;
1841 unsigned long dsp_flags;
1842 uint32_t *payload;
1843 uint32_t wakeup_flag = 1;
1844 int32_t ret = 0;
1845 union asm_token_struct asm_token;
1846 uint8_t buf_index;
1847 struct msm_adsp_event_data *pp_event_package = NULL;
1848 uint32_t payload_size = 0;
Meng Wangb6afa8c2017-11-30 17:55:05 +08001849 unsigned long flags;
Meng Wang9730cdd2017-09-26 12:48:31 +08001850 int session_id;
1851
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301852 if (ac == NULL) {
1853 pr_err("%s: ac NULL\n", __func__);
1854 return -EINVAL;
1855 }
1856 if (data == NULL) {
1857 pr_err("%s: data NULL\n", __func__);
1858 return -EINVAL;
1859 }
Meng Wang9730cdd2017-09-26 12:48:31 +08001860
1861 session_id = q6asm_get_session_id_from_audio_client(ac);
1862 if (session_id <= 0 || session_id > ASM_ACTIVE_STREAMS_ALLOWED) {
1863 pr_err("%s: Session ID is invalid, session = %d\n", __func__,
1864 session_id);
1865 return -EINVAL;
1866 }
Meng Wangb6afa8c2017-11-30 17:55:05 +08001867 spin_lock_irqsave(&(session[session_id].session_lock), flags);
Meng Wang9730cdd2017-09-26 12:48:31 +08001868
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301869 if (!q6asm_is_valid_audio_client(ac)) {
1870 pr_err("%s: audio client pointer is invalid, ac = %pK\n",
1871 __func__, ac);
Meng Wangb6afa8c2017-11-30 17:55:05 +08001872 spin_unlock_irqrestore(
1873 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301874 return -EINVAL;
1875 }
1876
1877 payload = data->payload;
1878 asm_token.token = data->token;
1879 if (q6asm_get_flag_from_token(&asm_token, ASM_CMD_NO_WAIT_OFFSET)) {
1880 pr_debug("%s: No wait command opcode[0x%x] cmd_opcode:%x\n",
1881 __func__, data->opcode, payload ? payload[0] : 0);
1882 wakeup_flag = 0;
1883 }
1884
1885 if (data->opcode == RESET_EVENTS) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301886 atomic_set(&ac->reset, 1);
1887 if (ac->apr == NULL) {
1888 ac->apr = ac->apr2;
1889 ac->apr2 = NULL;
1890 }
1891 pr_debug("%s: Reset event is received: %d %d apr[%pK]\n",
1892 __func__,
1893 data->reset_event, data->reset_proc, ac->apr);
1894 if (ac->cb)
1895 ac->cb(data->opcode, data->token,
1896 (uint32_t *)data->payload, ac->priv);
1897 apr_reset(ac->apr);
1898 ac->apr = NULL;
1899 atomic_set(&ac->time_flag, 0);
1900 atomic_set(&ac->cmd_state, 0);
1901 atomic_set(&ac->mem_state, 0);
1902 atomic_set(&ac->cmd_state_pp, 0);
1903 wake_up(&ac->time_wait);
1904 wake_up(&ac->cmd_wait);
1905 wake_up(&ac->mem_wait);
Meng Wangb6afa8c2017-11-30 17:55:05 +08001906 spin_unlock_irqrestore(
1907 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301908 return 0;
1909 }
1910
1911 dev_vdbg(ac->dev, "%s: session[%d]opcode[0x%x] token[0x%x]payload_size[%d] src[%d] dest[%d]\n",
1912 __func__,
1913 ac->session, data->opcode,
1914 data->token, data->payload_size, data->src_port,
1915 data->dest_port);
1916 if ((data->opcode != ASM_DATA_EVENT_RENDERED_EOS) &&
1917 (data->opcode != ASM_DATA_EVENT_EOS) &&
1918 (data->opcode != ASM_SESSION_EVENT_RX_UNDERFLOW)) {
1919 if (payload == NULL) {
1920 pr_err("%s: payload is null\n", __func__);
Meng Wangb6afa8c2017-11-30 17:55:05 +08001921 spin_unlock_irqrestore(
1922 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301923 return -EINVAL;
1924 }
1925 dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x] opcode 0x%x\n",
1926 __func__, payload[0], payload[1], data->opcode);
1927 }
1928 if (data->opcode == APR_BASIC_RSP_RESULT) {
1929 switch (payload[0]) {
1930 case ASM_STREAM_CMD_SET_PP_PARAMS_V2:
1931 if (rtac_make_asm_callback(ac->session, payload,
1932 data->payload_size))
1933 break;
1934 case ASM_SESSION_CMD_PAUSE:
1935 case ASM_SESSION_CMD_SUSPEND:
1936 case ASM_DATA_CMD_EOS:
1937 case ASM_STREAM_CMD_CLOSE:
1938 case ASM_STREAM_CMD_FLUSH:
1939 case ASM_SESSION_CMD_RUN_V2:
1940 case ASM_SESSION_CMD_REGISTER_FORX_OVERFLOW_EVENTS:
1941 case ASM_STREAM_CMD_FLUSH_READBUFS:
1942 pr_debug("%s: session %d opcode 0x%x token 0x%x Payload = [0x%x] src %d dest %d\n",
1943 __func__, ac->session, data->opcode, data->token,
1944 payload[0], data->src_port, data->dest_port);
1945 ret = q6asm_is_valid_session(data, priv);
1946 if (ret != 0) {
1947 pr_err("%s: session invalid %d\n", __func__, ret);
Meng Wangb6afa8c2017-11-30 17:55:05 +08001948 spin_unlock_irqrestore(
1949 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301950 return ret;
1951 }
1952 case ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2:
1953 case ASM_STREAM_CMD_OPEN_READ_V3:
1954 case ASM_STREAM_CMD_OPEN_WRITE_V3:
1955 case ASM_STREAM_CMD_OPEN_PULL_MODE_WRITE:
1956 case ASM_STREAM_CMD_OPEN_PUSH_MODE_READ:
1957 case ASM_STREAM_CMD_OPEN_READWRITE_V2:
1958 case ASM_STREAM_CMD_OPEN_LOOPBACK_V2:
1959 case ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK:
1960 case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2:
1961 case ASM_DATA_CMD_IEC_60958_MEDIA_FMT:
1962 case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
1963 case ASM_STREAM_CMD_SET_ENCDEC_PARAM_V2:
1964 case ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS:
1965 case ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE:
1966 case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:
1967 case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
1968 case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS:
1969 case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
1970 pr_debug("%s: session %d opcode 0x%x token 0x%x Payload = [0x%x] stat 0x%x src %d dest %d\n",
1971 __func__, ac->session,
1972 data->opcode, data->token,
1973 payload[0], payload[1],
1974 data->src_port, data->dest_port);
1975 if (payload[1] != 0) {
1976 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
1977 __func__, payload[0], payload[1]);
1978 if (wakeup_flag) {
1979 if ((is_adsp_reg_event(payload[0]) >= 0)
1980 || (payload[0] ==
1981 ASM_STREAM_CMD_SET_PP_PARAMS_V2))
1982 atomic_set(&ac->cmd_state_pp,
1983 payload[1]);
1984 else
1985 atomic_set(&ac->cmd_state,
1986 payload[1]);
1987 wake_up(&ac->cmd_wait);
1988 }
Meng Wangb6afa8c2017-11-30 17:55:05 +08001989 spin_unlock_irqrestore(
1990 &(session[session_id].session_lock),
1991 flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301992 return 0;
1993 }
1994 if ((is_adsp_reg_event(payload[0]) >= 0) ||
1995 (payload[0] == ASM_STREAM_CMD_SET_PP_PARAMS_V2)) {
1996 if (atomic_read(&ac->cmd_state_pp) &&
1997 wakeup_flag) {
1998 atomic_set(&ac->cmd_state_pp, 0);
1999 wake_up(&ac->cmd_wait);
2000 }
2001 } else {
2002 if (atomic_read(&ac->cmd_state) &&
2003 wakeup_flag) {
2004 atomic_set(&ac->cmd_state, 0);
2005 wake_up(&ac->cmd_wait);
2006 }
2007 }
2008 if (ac->cb)
2009 ac->cb(data->opcode, data->token,
2010 (uint32_t *)data->payload, ac->priv);
2011 break;
2012 case ASM_CMD_ADD_TOPOLOGIES:
2013 pr_debug("%s:Payload = [0x%x]stat[0x%x]\n",
2014 __func__, payload[0], payload[1]);
2015 if (payload[1] != 0) {
2016 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
2017 __func__, payload[0], payload[1]);
2018 if (wakeup_flag) {
2019 atomic_set(&ac->mem_state, payload[1]);
2020 wake_up(&ac->mem_wait);
2021 }
Meng Wangb6afa8c2017-11-30 17:55:05 +08002022 spin_unlock_irqrestore(
2023 &(session[session_id].session_lock),
2024 flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302025 return 0;
2026 }
2027 if (atomic_read(&ac->mem_state) && wakeup_flag) {
2028 atomic_set(&ac->mem_state, 0);
2029 wake_up(&ac->mem_wait);
2030 }
2031 if (ac->cb)
2032 ac->cb(data->opcode, data->token,
2033 (uint32_t *)data->payload, ac->priv);
2034 break;
2035 case ASM_DATA_EVENT_WATERMARK: {
2036 pr_debug("%s: Watermark opcode[0x%x] status[0x%x]",
2037 __func__, payload[0], payload[1]);
2038 break;
2039 }
2040 case ASM_STREAM_CMD_GET_PP_PARAMS_V2:
2041 pr_debug("%s: ASM_STREAM_CMD_GET_PP_PARAMS_V2 session %d opcode 0x%x token 0x%x src %d dest %d\n",
2042 __func__, ac->session,
2043 data->opcode, data->token,
2044 data->src_port, data->dest_port);
2045 /* Should only come here if there is an APR */
2046 /* error or malformed APR packet. Otherwise */
2047 /* response will be returned as */
2048 /* ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2 */
2049 if (payload[1] != 0) {
2050 pr_err("%s: ASM get param error = %d, resuming\n",
2051 __func__, payload[1]);
2052 rtac_make_asm_callback(ac->session, payload,
2053 data->payload_size);
2054 }
2055 break;
2056 case ASM_STREAM_CMD_REGISTER_PP_EVENTS:
2057 pr_debug("%s: ASM_STREAM_CMD_REGISTER_PP_EVENTS session %d opcode 0x%x token 0x%x src %d dest %d\n",
2058 __func__, ac->session,
2059 data->opcode, data->token,
2060 data->src_port, data->dest_port);
2061 if (payload[1] != 0)
2062 pr_err("%s: ASM get param error = %d, resuming\n",
2063 __func__, payload[1]);
2064 atomic_set(&ac->cmd_state_pp, payload[1]);
2065 wake_up(&ac->cmd_wait);
2066 break;
2067 default:
2068 pr_debug("%s: command[0x%x] not expecting rsp\n",
2069 __func__, payload[0]);
2070 break;
2071 }
Meng Wang9730cdd2017-09-26 12:48:31 +08002072
Meng Wangb6afa8c2017-11-30 17:55:05 +08002073 spin_unlock_irqrestore(
2074 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302075 return 0;
2076 }
2077
2078 switch (data->opcode) {
2079 case ASM_DATA_EVENT_WRITE_DONE_V2:{
2080 struct audio_port_data *port = &ac->port[IN];
2081
2082 dev_vdbg(ac->dev, "%s: Rxed opcode[0x%x] status[0x%x] token[%d]",
2083 __func__, payload[0], payload[1],
2084 data->token);
2085 if (ac->io_mode & SYNC_IO_MODE) {
2086 if (port->buf == NULL) {
2087 pr_err("%s: Unexpected Write Done\n",
2088 __func__);
Meng Wangb6afa8c2017-11-30 17:55:05 +08002089 spin_unlock_irqrestore(
2090 &(session[session_id].session_lock),
2091 flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302092 return -EINVAL;
2093 }
2094 spin_lock_irqsave(&port->dsp_lock, dsp_flags);
2095 buf_index = asm_token._token.buf_index;
2096 if (lower_32_bits(port->buf[buf_index].phys) !=
2097 payload[0] ||
2098 msm_audio_populate_upper_32_bits(
2099 port->buf[buf_index].phys) != payload[1]) {
2100 pr_debug("%s: Expected addr %pK\n",
2101 __func__, &port->buf[buf_index].phys);
2102 pr_err("%s: rxedl[0x%x] rxedu [0x%x]\n",
2103 __func__, payload[0], payload[1]);
2104 spin_unlock_irqrestore(&port->dsp_lock,
2105 dsp_flags);
Meng Wangb6afa8c2017-11-30 17:55:05 +08002106 spin_unlock_irqrestore(
2107 &(session[session_id].session_lock),
2108 flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302109 return -EINVAL;
2110 }
2111 port->buf[buf_index].used = 1;
2112 spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
2113
2114 config_debug_fs_write_cb();
2115
2116 for (i = 0; i < port->max_buf_cnt; i++)
2117 dev_vdbg(ac->dev, "%s %d\n",
2118 __func__, port->buf[i].used);
2119
2120 }
2121 break;
2122 }
2123 case ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2:
2124 pr_debug("%s: ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2 session %d opcode 0x%x token 0x%x src %d dest %d\n",
2125 __func__, ac->session, data->opcode,
2126 data->token,
2127 data->src_port, data->dest_port);
2128 if (payload[0] != 0) {
2129 pr_err("%s: ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2 returned error = 0x%x\n",
2130 __func__, payload[0]);
2131 } else if (generic_get_data) {
2132 generic_get_data->valid = 1;
2133 if (generic_get_data->is_inband) {
2134 pr_debug("%s: payload[1] = 0x%x, payload[2]=0x%x, payload[3]=0x%x\n",
2135 __func__, payload[1], payload[2], payload[3]);
2136 generic_get_data->size_in_ints = payload[3]>>2;
2137 for (i = 0; i < payload[3]>>2; i++) {
2138 generic_get_data->ints[i] =
2139 payload[4+i];
2140 pr_debug("%s: ASM callback val %i = %i\n",
2141 __func__, i, payload[4+i]);
2142 }
2143 pr_debug("%s: callback size in ints = %i\n",
2144 __func__,
2145 generic_get_data->size_in_ints);
2146 }
2147 if (atomic_read(&ac->cmd_state) && wakeup_flag) {
2148 atomic_set(&ac->cmd_state, 0);
2149 wake_up(&ac->cmd_wait);
2150 }
2151 break;
2152 }
2153 rtac_make_asm_callback(ac->session, payload,
2154 data->payload_size);
2155 break;
2156 case ASM_DATA_EVENT_READ_DONE_V2:{
2157
2158 struct audio_port_data *port = &ac->port[OUT];
2159
2160 config_debug_fs_read_cb();
2161
2162 dev_vdbg(ac->dev, "%s: ReadDone: status=%d buff_add=0x%x act_size=%d offset=%d\n",
2163 __func__, payload[READDONE_IDX_STATUS],
2164 payload[READDONE_IDX_BUFADD_LSW],
2165 payload[READDONE_IDX_SIZE],
2166 payload[READDONE_IDX_OFFSET]);
2167
2168 dev_vdbg(ac->dev, "%s: ReadDone:msw_ts=%d lsw_ts=%d memmap_hdl=0x%x flags=%d id=%d num=%d\n",
2169 __func__, payload[READDONE_IDX_MSW_TS],
2170 payload[READDONE_IDX_LSW_TS],
2171 payload[READDONE_IDX_MEMMAP_HDL],
2172 payload[READDONE_IDX_FLAGS],
2173 payload[READDONE_IDX_SEQ_ID],
2174 payload[READDONE_IDX_NUMFRAMES]);
2175
2176 if (ac->io_mode & SYNC_IO_MODE) {
2177 if (port->buf == NULL) {
2178 pr_err("%s: Unexpected Write Done\n", __func__);
Meng Wangb6afa8c2017-11-30 17:55:05 +08002179 spin_unlock_irqrestore(
2180 &(session[session_id].session_lock),
2181 flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302182 return -EINVAL;
2183 }
2184 spin_lock_irqsave(&port->dsp_lock, dsp_flags);
2185 buf_index = asm_token._token.buf_index;
2186 port->buf[buf_index].used = 0;
2187 if (lower_32_bits(port->buf[buf_index].phys) !=
2188 payload[READDONE_IDX_BUFADD_LSW] ||
2189 msm_audio_populate_upper_32_bits(
2190 port->buf[buf_index].phys) !=
2191 payload[READDONE_IDX_BUFADD_MSW]) {
2192 dev_vdbg(ac->dev, "%s: Expected addr %pK\n",
2193 __func__, &port->buf[buf_index].phys);
2194 pr_err("%s: rxedl[0x%x] rxedu[0x%x]\n",
2195 __func__,
2196 payload[READDONE_IDX_BUFADD_LSW],
2197 payload[READDONE_IDX_BUFADD_MSW]);
2198 spin_unlock_irqrestore(&port->dsp_lock,
2199 dsp_flags);
2200 break;
2201 }
2202 port->buf[buf_index].actual_size =
2203 payload[READDONE_IDX_SIZE];
2204 spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
2205 }
2206 break;
2207 }
2208 case ASM_DATA_EVENT_EOS:
2209 case ASM_DATA_EVENT_RENDERED_EOS:
2210 pr_debug("%s: EOS ACK received: rxed session %d opcode 0x%x token 0x%x src %d dest %d\n",
2211 __func__, ac->session,
2212 data->opcode, data->token,
2213 data->src_port, data->dest_port);
2214 break;
2215 case ASM_SESSION_EVENTX_OVERFLOW:
2216 pr_debug("%s: ASM_SESSION_EVENTX_OVERFLOW session %d opcode 0x%x token 0x%x src %d dest %d\n",
2217 __func__, ac->session,
2218 data->opcode, data->token,
2219 data->src_port, data->dest_port);
2220 break;
2221 case ASM_SESSION_EVENT_RX_UNDERFLOW:
2222 pr_debug("%s: ASM_SESSION_EVENT_RX_UNDERFLOW session %d opcode 0x%x token 0x%x src %d dest %d\n",
2223 __func__, ac->session,
2224 data->opcode, data->token,
2225 data->src_port, data->dest_port);
2226 break;
2227 case ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3:
2228 dev_vdbg(ac->dev, "%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3, payload[0] = %d, payload[1] = %d, payload[2] = %d\n",
2229 __func__,
2230 payload[0], payload[1], payload[2]);
2231 ac->time_stamp = (uint64_t)(((uint64_t)payload[2] << 32) |
2232 payload[1]);
2233 if (atomic_cmpxchg(&ac->time_flag, 1, 0))
2234 wake_up(&ac->time_wait);
2235 break;
2236 case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
2237 case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY:
2238 pr_debug("%s: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY session %d opcode 0x%x token 0x%x src %d dest %d\n",
2239 __func__, ac->session,
2240 data->opcode, data->token,
2241 data->src_port, data->dest_port);
2242 pr_debug("%s: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, payload[0] = %d, payload[1] = %d, payload[2] = %d, payload[3] = %d\n",
2243 __func__,
2244 payload[0], payload[1], payload[2],
2245 payload[3]);
2246 break;
2247 case ASM_SESSION_CMDRSP_GET_MTMX_STRTR_PARAMS_V2:
2248 q6asm_process_mtmx_get_param_rsp(ac, (void *) payload);
2249 break;
2250 case ASM_STREAM_PP_EVENT:
2251 case ASM_STREAM_CMD_ENCDEC_EVENTS:
2252 case ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE:
2253 pr_debug("%s: ASM_STREAM_EVENT payload[0][0x%x] payload[1][0x%x]",
2254 __func__, payload[0], payload[1]);
2255 i = is_adsp_raise_event(data->opcode);
Meng Wang9730cdd2017-09-26 12:48:31 +08002256 if (i < 0) {
Meng Wangb6afa8c2017-11-30 17:55:05 +08002257 spin_unlock_irqrestore(
2258 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302259 return 0;
Meng Wang9730cdd2017-09-26 12:48:31 +08002260 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302261
2262 /* repack payload for asm_stream_pp_event
2263 * package is composed of event type + size + actual payload
2264 */
2265 payload_size = data->payload_size;
Xiaojun Sangae3d8862018-03-23 08:57:33 +08002266 if (payload_size > UINT_MAX
2267 - sizeof(struct msm_adsp_event_data)) {
2268 pr_err("%s: payload size = %d exceeds limit.\n",
2269 __func__, payload_size);
2270 spin_unlock(&(session[session_id].session_lock));
2271 return -EINVAL;
2272 }
2273
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302274 pp_event_package = kzalloc(payload_size
2275 + sizeof(struct msm_adsp_event_data),
2276 GFP_ATOMIC);
Meng Wang9730cdd2017-09-26 12:48:31 +08002277 if (!pp_event_package) {
Meng Wangb6afa8c2017-11-30 17:55:05 +08002278 spin_unlock_irqrestore(
2279 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302280 return -ENOMEM;
Meng Wang9730cdd2017-09-26 12:48:31 +08002281 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302282
2283 pp_event_package->event_type = i;
2284 pp_event_package->payload_len = payload_size;
2285 memcpy((void *)pp_event_package->payload,
2286 data->payload, payload_size);
2287 ac->cb(data->opcode, data->token,
2288 (void *)pp_event_package, ac->priv);
2289 kfree(pp_event_package);
Meng Wangb6afa8c2017-11-30 17:55:05 +08002290 spin_unlock_irqrestore(
2291 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302292 return 0;
2293 case ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2:
2294 pr_debug("%s: ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2 sesion %d status 0x%x msw %u lsw %u\n",
2295 __func__, ac->session, payload[0], payload[2],
2296 payload[1]);
2297 wake_up(&ac->cmd_wait);
2298 break;
2299 case ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2:
2300 pr_debug("%s: ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2 session %d status 0x%x msw %u lsw %u\n",
2301 __func__, ac->session, payload[0], payload[2],
2302 payload[1]);
2303 if (payload[0] == 0) {
2304 atomic_set(&ac->cmd_state, 0);
2305 /* ignore msw, as a delay that large shouldn't happen */
2306 ac->path_delay = payload[1];
2307 } else {
2308 atomic_set(&ac->cmd_state, payload[0]);
2309 ac->path_delay = UINT_MAX;
2310 }
2311 wake_up(&ac->cmd_wait);
2312 break;
2313 }
2314 if (ac->cb)
2315 ac->cb(data->opcode, data->token,
2316 data->payload, ac->priv);
Meng Wangb6afa8c2017-11-30 17:55:05 +08002317 spin_unlock_irqrestore(
2318 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302319 return 0;
2320}
2321
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302322/**
2323 * q6asm_is_cpu_buf_avail -
2324 * retrieve next CPU buf avail
2325 *
2326 * @dir: RX or TX direction
2327 * @ac: Audio client handle
2328 * @size: size pointer to be updated with size of buffer
2329 * @index: index pointer to be updated with
2330 * CPU buffer index available
2331 *
2332 * Returns buffer pointer on success or NULL on failure
2333 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302334void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size,
2335 uint32_t *index)
2336{
2337 void *data;
2338 unsigned char idx;
2339 struct audio_port_data *port;
2340
2341 if (!ac || ((dir != IN) && (dir != OUT))) {
2342 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
2343 return NULL;
2344 }
2345
2346 if (ac->io_mode & SYNC_IO_MODE) {
2347 port = &ac->port[dir];
2348
2349 mutex_lock(&port->lock);
2350 idx = port->cpu_buf;
2351 if (port->buf == NULL) {
2352 pr_err("%s: Buffer pointer null\n", __func__);
2353 mutex_unlock(&port->lock);
2354 return NULL;
2355 }
2356 /* dir 0: used = 0 means buf in use
2357 * dir 1: used = 1 means buf in use
2358 */
2359 if (port->buf[idx].used == dir) {
2360 /* To make it more robust, we could loop and get the
2361 * next avail buf, its risky though
2362 */
2363 pr_err("%s: Next buf idx[0x%x] not available, dir[%d]\n",
2364 __func__, idx, dir);
2365 mutex_unlock(&port->lock);
2366 return NULL;
2367 }
2368 *size = port->buf[idx].actual_size;
2369 *index = port->cpu_buf;
2370 data = port->buf[idx].data;
2371 dev_vdbg(ac->dev, "%s: session[%d]index[%d] data[%pK]size[%d]\n",
2372 __func__,
2373 ac->session,
2374 port->cpu_buf,
2375 data, *size);
2376 /* By default increase the cpu_buf cnt
2377 * user accesses this function,increase cpu
2378 * buf(to avoid another api)
2379 */
2380 port->buf[idx].used = dir;
2381 port->cpu_buf = q6asm_get_next_buf(ac, port->cpu_buf,
2382 port->max_buf_cnt);
2383 mutex_unlock(&port->lock);
2384 return data;
2385 }
2386 return NULL;
2387}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302388EXPORT_SYMBOL(q6asm_is_cpu_buf_avail);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302389
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302390/**
2391 * q6asm_cpu_buf_release -
2392 * releases cpu buffer for ASM
2393 *
2394 * @dir: RX or TX direction
2395 * @ac: Audio client handle
2396 *
2397 * Returns 0 on success or error on failure
2398 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302399int q6asm_cpu_buf_release(int dir, struct audio_client *ac)
2400{
2401 struct audio_port_data *port;
2402 int ret = 0;
2403 int idx;
2404
2405 if (!ac || ((dir != IN) && (dir != OUT))) {
2406 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
2407 ret = -EINVAL;
2408 goto exit;
2409 }
2410
2411 if (ac->io_mode & SYNC_IO_MODE) {
2412 port = &ac->port[dir];
2413 mutex_lock(&port->lock);
2414 idx = port->cpu_buf;
2415 if (port->cpu_buf == 0) {
2416 port->cpu_buf = port->max_buf_cnt - 1;
2417 } else if (port->cpu_buf < port->max_buf_cnt) {
2418 port->cpu_buf = port->cpu_buf - 1;
2419 } else {
2420 pr_err("%s: buffer index(%d) out of range\n",
2421 __func__, port->cpu_buf);
2422 ret = -EINVAL;
2423 mutex_unlock(&port->lock);
2424 goto exit;
2425 }
2426 port->buf[port->cpu_buf].used = dir ^ 1;
2427 mutex_unlock(&port->lock);
2428 }
2429exit:
2430 return ret;
2431}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302432EXPORT_SYMBOL(q6asm_cpu_buf_release);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302433
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302434/**
2435 * q6asm_is_cpu_buf_avail_nolock -
2436 * retrieve next CPU buf avail without lock acquire
2437 *
2438 * @dir: RX or TX direction
2439 * @ac: Audio client handle
2440 * @size: size pointer to be updated with size of buffer
2441 * @index: index pointer to be updated with
2442 * CPU buffer index available
2443 *
2444 * Returns buffer pointer on success or NULL on failure
2445 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302446void *q6asm_is_cpu_buf_avail_nolock(int dir, struct audio_client *ac,
2447 uint32_t *size, uint32_t *index)
2448{
2449 void *data;
2450 unsigned char idx;
2451 struct audio_port_data *port;
2452
2453 if (!ac || ((dir != IN) && (dir != OUT))) {
2454 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
2455 return NULL;
2456 }
2457
2458 port = &ac->port[dir];
2459
2460 idx = port->cpu_buf;
2461 if (port->buf == NULL) {
2462 pr_err("%s: Buffer pointer null\n", __func__);
2463 return NULL;
2464 }
2465 /*
2466 * dir 0: used = 0 means buf in use
2467 * dir 1: used = 1 means buf in use
2468 */
2469 if (port->buf[idx].used == dir) {
2470 /*
2471 * To make it more robust, we could loop and get the
2472 * next avail buf, its risky though
2473 */
2474 pr_err("%s: Next buf idx[0x%x] not available, dir[%d]\n",
2475 __func__, idx, dir);
2476 return NULL;
2477 }
2478 *size = port->buf[idx].actual_size;
2479 *index = port->cpu_buf;
2480 data = port->buf[idx].data;
2481 dev_vdbg(ac->dev, "%s: session[%d]index[%d] data[%pK]size[%d]\n",
2482 __func__, ac->session, port->cpu_buf,
2483 data, *size);
2484 /*
2485 * By default increase the cpu_buf cnt
2486 * user accesses this function,increase cpu
2487 * buf(to avoid another api)
2488 */
2489 port->buf[idx].used = dir;
2490 port->cpu_buf = q6asm_get_next_buf(ac, port->cpu_buf,
2491 port->max_buf_cnt);
2492 return data;
2493}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302494EXPORT_SYMBOL(q6asm_is_cpu_buf_avail_nolock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302495
2496int q6asm_is_dsp_buf_avail(int dir, struct audio_client *ac)
2497{
2498 int ret = -1;
2499 struct audio_port_data *port;
2500 uint32_t idx;
2501
2502 if (!ac || (dir != OUT)) {
2503 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
2504 return ret;
2505 }
2506
2507 if (ac->io_mode & SYNC_IO_MODE) {
2508 port = &ac->port[dir];
2509
2510 mutex_lock(&port->lock);
2511 idx = port->dsp_buf;
2512
2513 if (port->buf[idx].used == (dir ^ 1)) {
2514 /* To make it more robust, we could loop and get the
2515 * next avail buf, its risky though
2516 */
2517 pr_err("%s: Next buf idx[0x%x] not available, dir[%d]\n",
2518 __func__, idx, dir);
2519 mutex_unlock(&port->lock);
2520 return ret;
2521 }
2522 dev_vdbg(ac->dev, "%s: session[%d]dsp_buf=%d cpu_buf=%d\n",
2523 __func__,
2524 ac->session, port->dsp_buf, port->cpu_buf);
2525 ret = ((port->dsp_buf != port->cpu_buf) ? 0 : -1);
2526 mutex_unlock(&port->lock);
2527 }
2528 return ret;
2529}
2530
2531static void __q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
2532 uint32_t pkt_size, uint32_t cmd_flg, uint32_t stream_id)
2533{
Meng Wangb6afa8c2017-11-30 17:55:05 +08002534 unsigned long flags;
2535
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302536 dev_vdbg(ac->dev, "%s: pkt_size=%d cmd_flg=%d session=%d stream_id=%d\n",
2537 __func__, pkt_size, cmd_flg, ac->session, stream_id);
2538 mutex_lock(&ac->cmd_lock);
Meng Wangb6afa8c2017-11-30 17:55:05 +08002539 spin_lock_irqsave(&(session[ac->session].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302540 if (ac->apr == NULL) {
2541 pr_err("%s: AC APR handle NULL", __func__);
Meng Wangb6afa8c2017-11-30 17:55:05 +08002542 spin_unlock_irqrestore(
2543 &(session[ac->session].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302544 mutex_unlock(&ac->cmd_lock);
2545 return;
2546 }
2547
2548 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2549 APR_HDR_LEN(sizeof(struct apr_hdr)),
2550 APR_PKT_VER);
2551 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
2552 hdr->src_domain = APR_DOMAIN_APPS;
2553 hdr->dest_svc = APR_SVC_ASM;
2554 hdr->dest_domain = APR_DOMAIN_ADSP;
2555 hdr->src_port = ((ac->session << 8) & 0xFF00) | (stream_id);
2556 hdr->dest_port = ((ac->session << 8) & 0xFF00) | (stream_id);
2557 if (cmd_flg)
2558 q6asm_update_token(&hdr->token,
2559 ac->session,
2560 0, /* Stream ID is NA */
2561 0, /* Buffer index is NA */
2562 0, /* Direction flag is NA */
2563 WAIT_CMD);
2564
2565 hdr->pkt_size = pkt_size;
Meng Wangb6afa8c2017-11-30 17:55:05 +08002566 spin_unlock_irqrestore(
2567 &(session[ac->session].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302568 mutex_unlock(&ac->cmd_lock);
2569}
2570
2571static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
2572 uint32_t pkt_size, uint32_t cmd_flg)
2573{
2574 __q6asm_add_hdr(ac, hdr, pkt_size, cmd_flg, ac->stream_id);
2575}
2576
2577static void q6asm_stream_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
2578 uint32_t pkt_size, uint32_t cmd_flg, int32_t stream_id)
2579{
2580 __q6asm_add_hdr(ac, hdr, pkt_size, cmd_flg, stream_id);
2581}
2582
2583static void __q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
2584 uint32_t pkt_size, uint32_t cmd_flg,
2585 uint32_t stream_id, u8 no_wait_flag)
2586{
2587 dev_vdbg(ac->dev, "%s: pkt_size = %d, cmd_flg = %d, session = %d stream_id=%d\n",
2588 __func__, pkt_size, cmd_flg, ac->session, stream_id);
2589 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2590 APR_HDR_LEN(sizeof(struct apr_hdr)),
2591 APR_PKT_VER);
2592 if (ac->apr == NULL) {
2593 pr_err("%s: AC APR is NULL", __func__);
2594 return;
2595 }
2596 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
2597 hdr->src_domain = APR_DOMAIN_APPS;
2598 hdr->dest_svc = APR_SVC_ASM;
2599 hdr->dest_domain = APR_DOMAIN_ADSP;
2600 hdr->src_port = ((ac->session << 8) & 0xFF00) | (stream_id);
2601 hdr->dest_port = ((ac->session << 8) & 0xFF00) | (stream_id);
2602 if (cmd_flg) {
2603 q6asm_update_token(&hdr->token,
2604 ac->session,
2605 0, /* Stream ID is NA */
2606 0, /* Buffer index is NA */
2607 0, /* Direction flag is NA */
2608 no_wait_flag);
2609
2610 }
2611 hdr->pkt_size = pkt_size;
2612}
2613
2614static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
2615 uint32_t pkt_size, uint32_t cmd_flg)
2616{
2617 __q6asm_add_hdr_async(ac, hdr, pkt_size, cmd_flg,
2618 ac->stream_id, WAIT_CMD);
2619}
2620
2621static void q6asm_stream_add_hdr_async(struct audio_client *ac,
2622 struct apr_hdr *hdr, uint32_t pkt_size,
2623 uint32_t cmd_flg, int32_t stream_id)
2624{
2625 __q6asm_add_hdr_async(ac, hdr, pkt_size, cmd_flg,
2626 stream_id, NO_WAIT_CMD);
2627}
2628
2629static void q6asm_add_hdr_custom_topology(struct audio_client *ac,
2630 struct apr_hdr *hdr,
2631 uint32_t pkt_size)
2632{
2633 pr_debug("%s: pkt_size=%d session=%d\n",
2634 __func__, pkt_size, ac->session);
2635 if (ac->apr == NULL) {
2636 pr_err("%s: AC APR handle NULL\n", __func__);
2637 return;
2638 }
2639
2640 mutex_lock(&ac->cmd_lock);
2641 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2642 APR_HDR_LEN(sizeof(struct apr_hdr)),
2643 APR_PKT_VER);
2644 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
2645 hdr->src_domain = APR_DOMAIN_APPS;
2646 hdr->dest_svc = APR_SVC_ASM;
2647 hdr->dest_domain = APR_DOMAIN_ADSP;
2648 hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01;
2649 hdr->dest_port = 0;
2650 q6asm_update_token(&hdr->token,
2651 ac->session,
2652 0, /* Stream ID is NA */
2653 0, /* Buffer index is NA */
2654 0, /* Direction flag is NA */
2655 WAIT_CMD);
2656 hdr->pkt_size = pkt_size;
2657 mutex_unlock(&ac->cmd_lock);
2658}
2659
2660static void q6asm_add_mmaphdr(struct audio_client *ac, struct apr_hdr *hdr,
2661 u32 pkt_size, int dir)
2662{
2663 pr_debug("%s: pkt size=%d\n",
2664 __func__, pkt_size);
2665 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2666 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2667 hdr->src_port = 0;
2668 hdr->dest_port = 0;
2669 q6asm_update_token(&hdr->token,
2670 ac->session,
2671 0, /* Stream ID is NA */
2672 0, /* Buffer index is NA */
2673 dir,
2674 WAIT_CMD);
2675 hdr->pkt_size = pkt_size;
2676}
2677
2678static int __q6asm_open_read(struct audio_client *ac,
2679 uint32_t format, uint16_t bits_per_sample,
2680 uint32_t pcm_format_block_ver,
2681 bool ts_mode)
2682{
2683 int rc = 0x00;
2684 struct asm_stream_cmd_open_read_v3 open;
2685
2686 config_debug_fs_reset_index();
2687
2688 if (ac == NULL) {
2689 pr_err("%s: APR handle NULL\n", __func__);
2690 return -EINVAL;
2691 }
2692 if (ac->apr == NULL) {
2693 pr_err("%s: AC APR handle NULL\n", __func__);
2694 return -EINVAL;
2695 }
2696 pr_debug("%s: session[%d]\n", __func__, ac->session);
2697
2698 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
2699 atomic_set(&ac->cmd_state, -1);
2700 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ_V3;
2701 /* Stream prio : High, provide meta info with encoded frames */
2702 open.src_endpointype = ASM_END_POINT_DEVICE_MATRIX;
2703
2704 open.preprocopo_id = q6asm_get_asm_topology_cal();
2705 open.bits_per_sample = bits_per_sample;
2706 open.mode_flags = 0x0;
2707
2708 ac->topology = open.preprocopo_id;
2709 ac->app_type = q6asm_get_asm_app_type_cal();
2710 if (ac->perf_mode == LOW_LATENCY_PCM_MODE) {
2711 open.mode_flags |= ASM_LOW_LATENCY_TX_STREAM_SESSION <<
2712 ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ;
2713 } else {
2714 open.mode_flags |= ASM_LEGACY_STREAM_SESSION <<
2715 ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ;
2716 }
2717
2718 switch (format) {
2719 case FORMAT_LINEAR_PCM:
2720 open.mode_flags |= 0x00;
2721 open.enc_cfg_id = q6asm_get_pcm_format_id(pcm_format_block_ver);
2722 if (ts_mode)
2723 open.mode_flags |= ABSOLUTE_TIMESTAMP_ENABLE;
2724 break;
2725 case FORMAT_MPEG4_AAC:
2726 open.mode_flags |= BUFFER_META_ENABLE;
2727 open.enc_cfg_id = ASM_MEDIA_FMT_AAC_V2;
2728 break;
2729 case FORMAT_G711_ALAW_FS:
2730 open.mode_flags |= BUFFER_META_ENABLE;
2731 open.enc_cfg_id = ASM_MEDIA_FMT_G711_ALAW_FS;
2732 break;
2733 case FORMAT_G711_MLAW_FS:
2734 open.mode_flags |= BUFFER_META_ENABLE;
2735 open.enc_cfg_id = ASM_MEDIA_FMT_G711_MLAW_FS;
2736 break;
2737 case FORMAT_V13K:
2738 open.mode_flags |= BUFFER_META_ENABLE;
2739 open.enc_cfg_id = ASM_MEDIA_FMT_V13K_FS;
2740 break;
2741 case FORMAT_EVRC:
2742 open.mode_flags |= BUFFER_META_ENABLE;
2743 open.enc_cfg_id = ASM_MEDIA_FMT_EVRC_FS;
2744 break;
2745 case FORMAT_AMRNB:
2746 open.mode_flags |= BUFFER_META_ENABLE;
2747 open.enc_cfg_id = ASM_MEDIA_FMT_AMRNB_FS;
2748 break;
2749 case FORMAT_AMRWB:
2750 open.mode_flags |= BUFFER_META_ENABLE;
2751 open.enc_cfg_id = ASM_MEDIA_FMT_AMRWB_FS;
2752 break;
2753 default:
2754 pr_err("%s: Invalid format 0x%x\n",
2755 __func__, format);
2756 rc = -EINVAL;
2757 goto fail_cmd;
2758 }
2759 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
2760 if (rc < 0) {
2761 pr_err("%s: open failed op[0x%x]rc[%d]\n",
2762 __func__, open.hdr.opcode, rc);
2763 rc = -EINVAL;
2764 goto fail_cmd;
2765 }
2766 rc = wait_event_timeout(ac->cmd_wait,
2767 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
2768 if (!rc) {
2769 pr_err("%s: timeout. waited for open read\n",
2770 __func__);
2771 rc = -ETIMEDOUT;
2772 goto fail_cmd;
2773 }
2774 if (atomic_read(&ac->cmd_state) > 0) {
2775 pr_err("%s: DSP returned error[%s]\n",
2776 __func__, adsp_err_get_err_str(
2777 atomic_read(&ac->cmd_state)));
2778 rc = adsp_err_get_lnx_err_code(
2779 atomic_read(&ac->cmd_state));
2780 goto fail_cmd;
2781 }
2782
2783 ac->io_mode |= TUN_READ_IO_MODE;
2784
2785 return 0;
2786fail_cmd:
2787 return rc;
2788}
2789
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302790/**
2791 * q6asm_open_read -
2792 * command to open ASM in read mode
2793 *
2794 * @ac: Audio client handle
2795 * @format: capture format for ASM
2796 *
2797 * Returns 0 on success or error on failure
2798 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302799int q6asm_open_read(struct audio_client *ac,
2800 uint32_t format)
2801{
2802 return __q6asm_open_read(ac, format, 16,
2803 PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/,
2804 false/*ts_mode*/);
2805}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302806EXPORT_SYMBOL(q6asm_open_read);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302807
2808int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
2809 uint16_t bits_per_sample)
2810{
2811 return __q6asm_open_read(ac, format, bits_per_sample,
2812 PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/,
2813 false/*ts_mode*/);
2814}
2815
2816/*
2817 * asm_open_read_v3 - Opens audio capture session
2818 *
2819 * @ac: Client session handle
2820 * @format: encoder format
2821 * @bits_per_sample: bit width of capture session
2822 */
2823int q6asm_open_read_v3(struct audio_client *ac, uint32_t format,
2824 uint16_t bits_per_sample)
2825{
2826 return __q6asm_open_read(ac, format, bits_per_sample,
2827 PCM_MEDIA_FORMAT_V3/*media fmt block ver*/,
2828 false/*ts_mode*/);
2829}
2830EXPORT_SYMBOL(q6asm_open_read_v3);
2831
2832/*
2833 * asm_open_read_v4 - Opens audio capture session
2834 *
2835 * @ac: Client session handle
2836 * @format: encoder format
2837 * @bits_per_sample: bit width of capture session
2838 * @ts_mode: timestamp mode
2839 */
2840int q6asm_open_read_v4(struct audio_client *ac, uint32_t format,
2841 uint16_t bits_per_sample, bool ts_mode)
2842{
2843 return __q6asm_open_read(ac, format, bits_per_sample,
2844 PCM_MEDIA_FORMAT_V4 /*media fmt block ver*/,
2845 ts_mode);
2846}
2847EXPORT_SYMBOL(q6asm_open_read_v4);
2848
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302849/**
2850 * q6asm_open_write_compressed -
2851 * command to open ASM in compressed write mode
2852 *
2853 * @ac: Audio client handle
2854 * @format: playback format for ASM
2855 * @passthrough_flag: flag to indicate passthrough option
2856 *
2857 * Returns 0 on success or error on failure
2858 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302859int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format,
2860 uint32_t passthrough_flag)
2861{
2862 int rc = 0;
2863 struct asm_stream_cmd_open_write_compressed open;
2864
2865 if (ac == NULL) {
2866 pr_err("%s: ac[%pK] NULL\n", __func__, ac);
2867 rc = -EINVAL;
2868 goto fail_cmd;
2869 }
2870
2871 if (ac->apr == NULL) {
2872 pr_err("%s: APR handle[%pK] NULL\n", __func__, ac->apr);
2873 rc = -EINVAL;
2874 goto fail_cmd;
2875 }
2876 pr_debug("%s: session[%d] wr_format[0x%x]", __func__, ac->session,
2877 format);
2878
2879 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
2880 open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED;
2881 atomic_set(&ac->cmd_state, -1);
2882
2883 switch (format) {
2884 case FORMAT_AC3:
2885 open.fmt_id = ASM_MEDIA_FMT_AC3;
2886 break;
2887 case FORMAT_EAC3:
2888 open.fmt_id = ASM_MEDIA_FMT_EAC3;
2889 break;
2890 case FORMAT_DTS:
2891 open.fmt_id = ASM_MEDIA_FMT_DTS;
2892 break;
2893 case FORMAT_DSD:
2894 open.fmt_id = ASM_MEDIA_FMT_DSD;
2895 break;
2896 case FORMAT_GEN_COMPR:
2897 open.fmt_id = ASM_MEDIA_FMT_GENERIC_COMPRESSED;
2898 break;
2899 case FORMAT_TRUEHD:
2900 open.fmt_id = ASM_MEDIA_FMT_TRUEHD;
2901 break;
2902 case FORMAT_IEC61937:
2903 open.fmt_id = ASM_MEDIA_FMT_IEC;
2904 break;
2905 default:
2906 pr_err("%s: Invalid format[%d]\n", __func__, format);
2907 rc = -EINVAL;
2908 goto fail_cmd;
2909 }
2910 /* Below flag indicates the DSP that Compressed audio input
2911 * stream is not IEC 61937 or IEC 60958 packetizied
2912 */
2913 if (passthrough_flag == COMPRESSED_PASSTHROUGH ||
2914 passthrough_flag == COMPRESSED_PASSTHROUGH_DSD ||
2915 passthrough_flag == COMPRESSED_PASSTHROUGH_GEN) {
2916 open.flags = 0x0;
2917 pr_debug("%s: Flag 0 COMPRESSED_PASSTHROUGH\n", __func__);
2918 } else if (passthrough_flag == COMPRESSED_PASSTHROUGH_CONVERT) {
2919 open.flags = 0x8;
2920 pr_debug("%s: Flag 8 - COMPRESSED_PASSTHROUGH_CONVERT\n",
2921 __func__);
2922 } else if (passthrough_flag == COMPRESSED_PASSTHROUGH_IEC61937) {
2923 open.flags = 0x1;
2924 pr_debug("%s: Flag 1 - COMPRESSED_PASSTHROUGH_IEC61937\n",
2925 __func__);
2926 } else {
2927 pr_err("%s: Invalid passthrough type[%d]\n",
2928 __func__, passthrough_flag);
2929 rc = -EINVAL;
2930 goto fail_cmd;
2931 }
2932 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
2933 if (rc < 0) {
2934 pr_err("%s: open failed op[0x%x]rc[%d]\n",
2935 __func__, open.hdr.opcode, rc);
2936 rc = -EINVAL;
2937 goto fail_cmd;
2938 }
2939 rc = wait_event_timeout(ac->cmd_wait,
2940 (atomic_read(&ac->cmd_state) >= 0), 1*HZ);
2941 if (!rc) {
2942 pr_err("%s: timeout. waited for OPEN_WRITE_COMPR rc[%d]\n",
2943 __func__, rc);
2944 rc = -ETIMEDOUT;
2945 goto fail_cmd;
2946 }
2947
2948 if (atomic_read(&ac->cmd_state) > 0) {
2949 pr_err("%s: DSP returned error[%s]\n",
2950 __func__, adsp_err_get_err_str(
2951 atomic_read(&ac->cmd_state)));
2952 rc = adsp_err_get_lnx_err_code(
2953 atomic_read(&ac->cmd_state));
2954 goto fail_cmd;
2955 }
2956
2957 return 0;
2958
2959fail_cmd:
2960 return rc;
2961}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302962EXPORT_SYMBOL(q6asm_open_write_compressed);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302963
2964static int __q6asm_open_write(struct audio_client *ac, uint32_t format,
2965 uint16_t bits_per_sample, uint32_t stream_id,
2966 bool is_gapless_mode,
2967 uint32_t pcm_format_block_ver)
2968{
2969 int rc = 0x00;
2970 struct asm_stream_cmd_open_write_v3 open;
2971
2972 if (ac == NULL) {
2973 pr_err("%s: APR handle NULL\n", __func__);
2974 return -EINVAL;
2975 }
2976 if (ac->apr == NULL) {
2977 pr_err("%s: AC APR handle NULL\n", __func__);
2978 return -EINVAL;
2979 }
2980
2981 dev_vdbg(ac->dev, "%s: session[%d] wr_format[0x%x]\n",
2982 __func__, ac->session, format);
2983
2984 q6asm_stream_add_hdr(ac, &open.hdr, sizeof(open), TRUE, stream_id);
2985 atomic_set(&ac->cmd_state, -1);
2986 /*
2987 * Updated the token field with stream/session for compressed playback
2988 * Platform driver must know the the stream with which the command is
2989 * associated
2990 */
2991 if (ac->io_mode & COMPRESSED_STREAM_IO)
2992 q6asm_update_token(&open.hdr.token,
2993 ac->session,
2994 stream_id,
2995 0, /* Buffer index is NA */
2996 0, /* Direction flag is NA */
2997 WAIT_CMD);
2998
2999 dev_vdbg(ac->dev, "%s: token = 0x%x, stream_id %d, session 0x%x\n",
3000 __func__, open.hdr.token, stream_id, ac->session);
3001 open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3;
3002 open.mode_flags = 0x00;
3003 if (ac->perf_mode == ULL_POST_PROCESSING_PCM_MODE)
3004 open.mode_flags |= ASM_ULL_POST_PROCESSING_STREAM_SESSION;
3005 else if (ac->perf_mode == ULTRA_LOW_LATENCY_PCM_MODE)
3006 open.mode_flags |= ASM_ULTRA_LOW_LATENCY_STREAM_SESSION;
3007 else if (ac->perf_mode == LOW_LATENCY_PCM_MODE)
3008 open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION;
3009 else {
3010 open.mode_flags |= ASM_LEGACY_STREAM_SESSION;
3011 if (is_gapless_mode)
3012 open.mode_flags |= 1 << ASM_SHIFT_GAPLESS_MODE_FLAG;
3013 }
3014
3015 /* source endpoint : matrix */
3016 open.sink_endpointype = ASM_END_POINT_DEVICE_MATRIX;
3017 open.bits_per_sample = bits_per_sample;
3018
3019 open.postprocopo_id = q6asm_get_asm_topology_cal();
3020 if (ac->perf_mode != LEGACY_PCM_MODE)
3021 open.postprocopo_id = ASM_STREAM_POSTPROCOPO_ID_NONE;
3022
3023 pr_debug("%s: perf_mode %d asm_topology 0x%x bps %d\n", __func__,
3024 ac->perf_mode, open.postprocopo_id, open.bits_per_sample);
3025
3026 /*
3027 * For Gapless playback it will use the same session for next stream,
3028 * So use the same topology
3029 */
3030 if (!ac->topology) {
3031 ac->topology = open.postprocopo_id;
3032 ac->app_type = q6asm_get_asm_app_type_cal();
3033 }
3034 switch (format) {
3035 case FORMAT_LINEAR_PCM:
3036 open.dec_fmt_id = q6asm_get_pcm_format_id(pcm_format_block_ver);
3037 break;
3038 case FORMAT_MPEG4_AAC:
3039 open.dec_fmt_id = ASM_MEDIA_FMT_AAC_V2;
3040 break;
3041 case FORMAT_MPEG4_MULTI_AAC:
3042 open.dec_fmt_id = ASM_MEDIA_FMT_AAC_V2;
3043 break;
3044 case FORMAT_WMA_V9:
3045 open.dec_fmt_id = ASM_MEDIA_FMT_WMA_V9_V2;
3046 break;
3047 case FORMAT_WMA_V10PRO:
3048 open.dec_fmt_id = ASM_MEDIA_FMT_WMA_V10PRO_V2;
3049 break;
3050 case FORMAT_MP3:
3051 open.dec_fmt_id = ASM_MEDIA_FMT_MP3;
3052 break;
3053 case FORMAT_AC3:
3054 open.dec_fmt_id = ASM_MEDIA_FMT_AC3;
3055 break;
3056 case FORMAT_EAC3:
3057 open.dec_fmt_id = ASM_MEDIA_FMT_EAC3;
3058 break;
3059 case FORMAT_MP2:
3060 open.dec_fmt_id = ASM_MEDIA_FMT_MP2;
3061 break;
3062 case FORMAT_FLAC:
3063 open.dec_fmt_id = ASM_MEDIA_FMT_FLAC;
3064 break;
3065 case FORMAT_ALAC:
3066 open.dec_fmt_id = ASM_MEDIA_FMT_ALAC;
3067 break;
3068 case FORMAT_VORBIS:
3069 open.dec_fmt_id = ASM_MEDIA_FMT_VORBIS;
3070 break;
3071 case FORMAT_APE:
3072 open.dec_fmt_id = ASM_MEDIA_FMT_APE;
3073 break;
3074 case FORMAT_DSD:
3075 open.dec_fmt_id = ASM_MEDIA_FMT_DSD;
3076 break;
3077 case FORMAT_APTX:
3078 open.dec_fmt_id = ASM_MEDIA_FMT_APTX;
3079 break;
3080 case FORMAT_GEN_COMPR:
3081 open.dec_fmt_id = ASM_MEDIA_FMT_GENERIC_COMPRESSED;
3082 break;
3083 default:
3084 pr_err("%s: Invalid format 0x%x\n", __func__, format);
3085 rc = -EINVAL;
3086 goto fail_cmd;
3087 }
3088 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
3089 if (rc < 0) {
3090 pr_err("%s: open failed op[0x%x]rc[%d]\n",
3091 __func__, open.hdr.opcode, rc);
3092 rc = -EINVAL;
3093 goto fail_cmd;
3094 }
3095 rc = wait_event_timeout(ac->cmd_wait,
3096 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
3097 if (!rc) {
3098 pr_err("%s: timeout. waited for open write\n", __func__);
3099 rc = -ETIMEDOUT;
3100 goto fail_cmd;
3101 }
3102 if (atomic_read(&ac->cmd_state) > 0) {
3103 pr_err("%s: DSP returned error[%s]\n",
3104 __func__, adsp_err_get_err_str(
3105 atomic_read(&ac->cmd_state)));
3106 rc = adsp_err_get_lnx_err_code(
3107 atomic_read(&ac->cmd_state));
3108 goto fail_cmd;
3109 }
3110 ac->io_mode |= TUN_WRITE_IO_MODE;
3111
3112 return 0;
3113fail_cmd:
3114 return rc;
3115}
3116
3117int q6asm_open_write(struct audio_client *ac, uint32_t format)
3118{
3119 return __q6asm_open_write(ac, format, 16, ac->stream_id,
3120 false /*gapless*/,
3121 PCM_MEDIA_FORMAT_V2 /*pcm_format_block_ver*/);
3122}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303123EXPORT_SYMBOL(q6asm_open_write);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303124
3125int q6asm_open_write_v2(struct audio_client *ac, uint32_t format,
3126 uint16_t bits_per_sample)
3127{
3128 return __q6asm_open_write(ac, format, bits_per_sample,
3129 ac->stream_id, false /*gapless*/,
3130 PCM_MEDIA_FORMAT_V2 /*pcm_format_block_ver*/);
3131}
3132
3133/*
3134 * q6asm_open_write_v3 - Opens audio playback session
3135 *
3136 * @ac: Client session handle
3137 * @format: decoder format
3138 * @bits_per_sample: bit width of playback session
3139 */
3140int q6asm_open_write_v3(struct audio_client *ac, uint32_t format,
3141 uint16_t bits_per_sample)
3142{
3143 return __q6asm_open_write(ac, format, bits_per_sample,
3144 ac->stream_id, false /*gapless*/,
3145 PCM_MEDIA_FORMAT_V3 /*pcm_format_block_ver*/);
3146}
3147EXPORT_SYMBOL(q6asm_open_write_v3);
3148
3149/*
3150 * q6asm_open_write_v4 - Opens audio playback session
3151 *
3152 * @ac: Client session handle
3153 * @format: decoder format
3154 * @bits_per_sample: bit width of playback session
3155 */
3156int q6asm_open_write_v4(struct audio_client *ac, uint32_t format,
3157 uint16_t bits_per_sample)
3158{
3159 return __q6asm_open_write(ac, format, bits_per_sample,
3160 ac->stream_id, false /*gapless*/,
3161 PCM_MEDIA_FORMAT_V4 /*pcm_format_block_ver*/);
3162}
3163EXPORT_SYMBOL(q6asm_open_write_v4);
3164
3165int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format,
3166 uint16_t bits_per_sample, int32_t stream_id,
3167 bool is_gapless_mode)
3168{
3169 return __q6asm_open_write(ac, format, bits_per_sample,
3170 stream_id, is_gapless_mode,
3171 PCM_MEDIA_FORMAT_V2 /*pcm_format_block_ver*/);
3172}
3173
3174/*
3175 * q6asm_stream_open_write_v3 - Creates audio stream for playback
3176 *
3177 * @ac: Client session handle
3178 * @format: asm playback format
3179 * @bits_per_sample: bit width of requested stream
3180 * @stream_id: stream id of stream to be associated with this session
3181 * @is_gapless_mode: true if gapless mode needs to be enabled
3182 */
3183int q6asm_stream_open_write_v3(struct audio_client *ac, uint32_t format,
3184 uint16_t bits_per_sample, int32_t stream_id,
3185 bool is_gapless_mode)
3186{
3187 return __q6asm_open_write(ac, format, bits_per_sample,
3188 stream_id, is_gapless_mode,
3189 PCM_MEDIA_FORMAT_V3 /*pcm_format_block_ver*/);
3190}
3191EXPORT_SYMBOL(q6asm_stream_open_write_v3);
3192
3193/*
3194 * q6asm_stream_open_write_v4 - Creates audio stream for playback
3195 *
3196 * @ac: Client session handle
3197 * @format: asm playback format
3198 * @bits_per_sample: bit width of requested stream
3199 * @stream_id: stream id of stream to be associated with this session
3200 * @is_gapless_mode: true if gapless mode needs to be enabled
3201 */
3202int q6asm_stream_open_write_v4(struct audio_client *ac, uint32_t format,
3203 uint16_t bits_per_sample, int32_t stream_id,
3204 bool is_gapless_mode)
3205{
3206 return __q6asm_open_write(ac, format, bits_per_sample,
3207 stream_id, is_gapless_mode,
3208 PCM_MEDIA_FORMAT_V4 /*pcm_format_block_ver*/);
3209}
3210EXPORT_SYMBOL(q6asm_stream_open_write_v4);
3211
3212static int __q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format,
3213 uint32_t wr_format, bool is_meta_data_mode,
3214 uint32_t bits_per_sample,
3215 bool overwrite_topology, int topology)
3216{
3217 int rc = 0x00;
3218 struct asm_stream_cmd_open_readwrite_v2 open;
3219
3220 if (ac == NULL) {
3221 pr_err("%s: APR handle NULL\n", __func__);
3222 return -EINVAL;
3223 }
3224 if (ac->apr == NULL) {
3225 pr_err("%s: AC APR handle NULL\n", __func__);
3226 return -EINVAL;
3227 }
3228 pr_debug("%s: session[%d]\n", __func__, ac->session);
3229 pr_debug("%s: wr_format[0x%x]rd_format[0x%x]\n",
3230 __func__, wr_format, rd_format);
3231
3232 ac->io_mode |= NT_MODE;
3233 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
3234 atomic_set(&ac->cmd_state, -1);
3235 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READWRITE_V2;
3236
3237 open.mode_flags = is_meta_data_mode ? BUFFER_META_ENABLE : 0;
3238 open.bits_per_sample = bits_per_sample;
3239 /* source endpoint : matrix */
3240 open.postprocopo_id = q6asm_get_asm_topology_cal();
3241
3242 open.postprocopo_id = overwrite_topology ?
3243 topology : open.postprocopo_id;
3244 ac->topology = open.postprocopo_id;
3245 ac->app_type = q6asm_get_asm_app_type_cal();
3246
3247
3248 switch (wr_format) {
3249 case FORMAT_LINEAR_PCM:
3250 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
3251 open.dec_fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
3252 break;
3253 case FORMAT_MPEG4_AAC:
3254 open.dec_fmt_id = ASM_MEDIA_FMT_AAC_V2;
3255 break;
3256 case FORMAT_MPEG4_MULTI_AAC:
3257 open.dec_fmt_id = ASM_MEDIA_FMT_AAC_V2;
3258 break;
3259 case FORMAT_WMA_V9:
3260 open.dec_fmt_id = ASM_MEDIA_FMT_WMA_V9_V2;
3261 break;
3262 case FORMAT_WMA_V10PRO:
3263 open.dec_fmt_id = ASM_MEDIA_FMT_WMA_V10PRO_V2;
3264 break;
3265 case FORMAT_AMRNB:
3266 open.dec_fmt_id = ASM_MEDIA_FMT_AMRNB_FS;
3267 break;
3268 case FORMAT_AMRWB:
3269 open.dec_fmt_id = ASM_MEDIA_FMT_AMRWB_FS;
3270 break;
3271 case FORMAT_AMR_WB_PLUS:
3272 open.dec_fmt_id = ASM_MEDIA_FMT_AMR_WB_PLUS_V2;
3273 break;
3274 case FORMAT_V13K:
3275 open.dec_fmt_id = ASM_MEDIA_FMT_V13K_FS;
3276 break;
3277 case FORMAT_EVRC:
3278 open.dec_fmt_id = ASM_MEDIA_FMT_EVRC_FS;
3279 break;
3280 case FORMAT_EVRCB:
3281 open.dec_fmt_id = ASM_MEDIA_FMT_EVRCB_FS;
3282 break;
3283 case FORMAT_EVRCWB:
3284 open.dec_fmt_id = ASM_MEDIA_FMT_EVRCWB_FS;
3285 break;
3286 case FORMAT_MP3:
3287 open.dec_fmt_id = ASM_MEDIA_FMT_MP3;
3288 break;
3289 case FORMAT_ALAC:
3290 open.dec_fmt_id = ASM_MEDIA_FMT_ALAC;
3291 break;
3292 case FORMAT_APE:
3293 open.dec_fmt_id = ASM_MEDIA_FMT_APE;
3294 break;
3295 case FORMAT_DSD:
3296 open.dec_fmt_id = ASM_MEDIA_FMT_DSD;
3297 break;
3298 case FORMAT_G711_ALAW_FS:
3299 open.dec_fmt_id = ASM_MEDIA_FMT_G711_ALAW_FS;
3300 break;
3301 case FORMAT_G711_MLAW_FS:
3302 open.dec_fmt_id = ASM_MEDIA_FMT_G711_MLAW_FS;
3303 break;
3304 default:
3305 pr_err("%s: Invalid format 0x%x\n",
3306 __func__, wr_format);
3307 rc = -EINVAL;
3308 goto fail_cmd;
3309 }
3310
3311 switch (rd_format) {
3312 case FORMAT_LINEAR_PCM:
3313 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
3314 open.enc_cfg_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
3315 break;
3316 case FORMAT_MPEG4_AAC:
3317 open.enc_cfg_id = ASM_MEDIA_FMT_AAC_V2;
3318 break;
3319 case FORMAT_G711_ALAW_FS:
3320 open.enc_cfg_id = ASM_MEDIA_FMT_G711_ALAW_FS;
3321 break;
3322 case FORMAT_G711_MLAW_FS:
3323 open.enc_cfg_id = ASM_MEDIA_FMT_G711_MLAW_FS;
3324 break;
3325 case FORMAT_V13K:
3326 open.enc_cfg_id = ASM_MEDIA_FMT_V13K_FS;
3327 break;
3328 case FORMAT_EVRC:
3329 open.enc_cfg_id = ASM_MEDIA_FMT_EVRC_FS;
3330 break;
3331 case FORMAT_AMRNB:
3332 open.enc_cfg_id = ASM_MEDIA_FMT_AMRNB_FS;
3333 break;
3334 case FORMAT_AMRWB:
3335 open.enc_cfg_id = ASM_MEDIA_FMT_AMRWB_FS;
3336 break;
3337 case FORMAT_ALAC:
3338 open.enc_cfg_id = ASM_MEDIA_FMT_ALAC;
3339 break;
3340 case FORMAT_APE:
3341 open.enc_cfg_id = ASM_MEDIA_FMT_APE;
3342 break;
3343 default:
3344 pr_err("%s: Invalid format 0x%x\n",
3345 __func__, rd_format);
3346 rc = -EINVAL;
3347 goto fail_cmd;
3348 }
3349 dev_vdbg(ac->dev, "%s: rdformat[0x%x]wrformat[0x%x]\n", __func__,
3350 open.enc_cfg_id, open.dec_fmt_id);
3351
3352 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
3353 if (rc < 0) {
3354 pr_err("%s: open failed op[0x%x]rc[%d]\n",
3355 __func__, open.hdr.opcode, rc);
3356 rc = -EINVAL;
3357 goto fail_cmd;
3358 }
3359 rc = wait_event_timeout(ac->cmd_wait,
3360 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
3361 if (!rc) {
3362 pr_err("%s: timeout. waited for open read-write\n",
3363 __func__);
3364 rc = -ETIMEDOUT;
3365 goto fail_cmd;
3366 }
3367 if (atomic_read(&ac->cmd_state) > 0) {
3368 pr_err("%s: DSP returned error[%s]\n",
3369 __func__, adsp_err_get_err_str(
3370 atomic_read(&ac->cmd_state)));
3371 rc = adsp_err_get_lnx_err_code(
3372 atomic_read(&ac->cmd_state));
3373 goto fail_cmd;
3374 }
3375
3376 return 0;
3377fail_cmd:
3378 return rc;
3379}
3380
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303381/**
3382 * q6asm_open_read_write -
3383 * command to open ASM in read/write mode
3384 *
3385 * @ac: Audio client handle
3386 * @rd_format: capture format for ASM
3387 * @wr_format: playback format for ASM
3388 *
3389 * Returns 0 on success or error on failure
3390 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303391int q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format,
3392 uint32_t wr_format)
3393{
3394 return __q6asm_open_read_write(ac, rd_format, wr_format,
3395 true/*meta data mode*/,
3396 16 /*bits_per_sample*/,
3397 false /*overwrite_topology*/, 0);
3398}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303399EXPORT_SYMBOL(q6asm_open_read_write);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303400
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303401/**
3402 * q6asm_open_read_write_v2 -
3403 * command to open ASM in bi-directional read/write mode
3404 *
3405 * @ac: Audio client handle
3406 * @rd_format: capture format for ASM
3407 * @wr_format: playback format for ASM
3408 * @is_meta_data_mode: mode to indicate if meta data present
3409 * @bits_per_sample: number of bits per sample
3410 * @overwrite_topology: topology to be overwritten flag
3411 * @topology: Topology for ASM
3412 *
3413 * Returns 0 on success or error on failure
3414 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303415int q6asm_open_read_write_v2(struct audio_client *ac, uint32_t rd_format,
3416 uint32_t wr_format, bool is_meta_data_mode,
3417 uint32_t bits_per_sample, bool overwrite_topology,
3418 int topology)
3419{
3420 return __q6asm_open_read_write(ac, rd_format, wr_format,
3421 is_meta_data_mode, bits_per_sample,
3422 overwrite_topology, topology);
3423}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303424EXPORT_SYMBOL(q6asm_open_read_write_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303425
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303426/**
3427 * q6asm_open_loopback_v2 -
3428 * command to open ASM in loopback mode
3429 *
3430 * @ac: Audio client handle
3431 * @bits_per_sample: number of bits per sample
3432 *
3433 * Returns 0 on success or error on failure
3434 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303435int q6asm_open_loopback_v2(struct audio_client *ac, uint16_t bits_per_sample)
3436{
3437 int rc = 0x00;
3438
3439 if (ac == NULL) {
3440 pr_err("%s: APR handle NULL\n", __func__);
3441 return -EINVAL;
3442 }
3443 if (ac->apr == NULL) {
3444 pr_err("%s: AC APR handle NULL\n", __func__);
3445 return -EINVAL;
3446 }
3447 pr_debug("%s: session[%d]\n", __func__, ac->session);
3448
3449 if (ac->perf_mode == LOW_LATENCY_PCM_MODE) {
3450 struct asm_stream_cmd_open_transcode_loopback_t open;
3451
3452 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
3453 atomic_set(&ac->cmd_state, -1);
3454 open.hdr.opcode = ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK;
3455
3456 open.mode_flags = 0;
3457 open.src_endpoint_type = 0;
3458 open.sink_endpoint_type = 0;
3459 open.src_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
3460 open.sink_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
3461 /* source endpoint : matrix */
3462 open.audproc_topo_id = q6asm_get_asm_topology_cal();
3463
3464 ac->app_type = q6asm_get_asm_app_type_cal();
3465 if (ac->perf_mode == LOW_LATENCY_PCM_MODE)
3466 open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION;
3467 else
3468 open.mode_flags |= ASM_LEGACY_STREAM_SESSION;
3469 ac->topology = open.audproc_topo_id;
3470 open.bits_per_sample = bits_per_sample;
3471 open.reserved = 0;
3472 pr_debug("%s: opening a transcode_loopback with mode_flags =[%d] session[%d]\n",
3473 __func__, open.mode_flags, ac->session);
3474
3475 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
3476 if (rc < 0) {
3477 pr_err("%s: open failed op[0x%x]rc[%d]\n",
3478 __func__, open.hdr.opcode, rc);
3479 rc = -EINVAL;
3480 goto fail_cmd;
3481 }
3482 } else {/*if(ac->perf_mode == LEGACY_PCM_MODE)*/
3483 struct asm_stream_cmd_open_loopback_v2 open;
3484
3485 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
3486 atomic_set(&ac->cmd_state, -1);
3487 open.hdr.opcode = ASM_STREAM_CMD_OPEN_LOOPBACK_V2;
3488
3489 open.mode_flags = 0;
3490 open.src_endpointype = 0;
3491 open.sink_endpointype = 0;
3492 /* source endpoint : matrix */
3493 open.postprocopo_id = q6asm_get_asm_topology_cal();
3494
3495 ac->app_type = q6asm_get_asm_app_type_cal();
3496 ac->topology = open.postprocopo_id;
3497 open.bits_per_sample = bits_per_sample;
3498 open.reserved = 0;
3499 pr_debug("%s: opening a loopback_v2 with mode_flags =[%d] session[%d]\n",
3500 __func__, open.mode_flags, ac->session);
3501
3502 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
3503 if (rc < 0) {
3504 pr_err("%s: open failed op[0x%x]rc[%d]\n",
3505 __func__, open.hdr.opcode, rc);
3506 rc = -EINVAL;
3507 goto fail_cmd;
3508 }
3509 }
3510 rc = wait_event_timeout(ac->cmd_wait,
3511 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
3512 if (!rc) {
3513 pr_err("%s: timeout. waited for open_loopback\n",
3514 __func__);
3515 rc = -ETIMEDOUT;
3516 goto fail_cmd;
3517 }
3518 if (atomic_read(&ac->cmd_state) > 0) {
3519 pr_err("%s: DSP returned error[%s]\n",
3520 __func__, adsp_err_get_err_str(
3521 atomic_read(&ac->cmd_state)));
3522 rc = adsp_err_get_lnx_err_code(
3523 atomic_read(&ac->cmd_state));
3524 goto fail_cmd;
3525 }
3526
3527 return 0;
3528fail_cmd:
3529 return rc;
3530}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303531EXPORT_SYMBOL(q6asm_open_loopback_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303532
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303533/**
3534 * q6asm_open_transcode_loopback -
3535 * command to open ASM in transcode loopback mode
3536 *
3537 * @ac: Audio client handle
3538 * @bits_per_sample: number of bits per sample
3539 * @source_format: Format of clip
3540 * @sink_format: end device supported format
3541 *
3542 * Returns 0 on success or error on failure
3543 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303544int q6asm_open_transcode_loopback(struct audio_client *ac,
3545 uint16_t bits_per_sample,
3546 uint32_t source_format, uint32_t sink_format)
3547{
3548 int rc = 0x00;
3549 struct asm_stream_cmd_open_transcode_loopback_t open;
3550
3551 if (ac == NULL) {
3552 pr_err("%s: APR handle NULL\n", __func__);
3553 return -EINVAL;
3554 }
3555 if (ac->apr == NULL) {
3556 pr_err("%s: AC APR handle NULL\n", __func__);
3557 return -EINVAL;
3558 }
3559
3560 pr_debug("%s: session[%d]\n", __func__, ac->session);
3561
3562 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
3563 atomic_set(&ac->cmd_state, -1);
3564 open.hdr.opcode = ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK;
3565
3566 open.mode_flags = 0;
3567 open.src_endpoint_type = 0;
3568 open.sink_endpoint_type = 0;
3569 switch (source_format) {
3570 case FORMAT_LINEAR_PCM:
3571 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
3572 open.src_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3;
3573 break;
3574 case FORMAT_AC3:
3575 open.src_format_id = ASM_MEDIA_FMT_AC3;
3576 break;
3577 case FORMAT_EAC3:
3578 open.src_format_id = ASM_MEDIA_FMT_EAC3;
3579 break;
3580 default:
3581 pr_err("%s: Unsupported src fmt [%d]\n",
3582 __func__, source_format);
3583 return -EINVAL;
3584 }
3585 switch (sink_format) {
3586 case FORMAT_LINEAR_PCM:
3587 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
3588 open.sink_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3;
3589 break;
3590 default:
3591 pr_err("%s: Unsupported sink fmt [%d]\n",
3592 __func__, sink_format);
3593 return -EINVAL;
3594 }
3595
3596 /* source endpoint : matrix */
3597 open.audproc_topo_id = q6asm_get_asm_topology_cal();
3598
3599 ac->app_type = q6asm_get_asm_app_type_cal();
3600 if (ac->perf_mode == LOW_LATENCY_PCM_MODE)
3601 open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION;
3602 else
3603 open.mode_flags |= ASM_LEGACY_STREAM_SESSION;
3604 ac->topology = open.audproc_topo_id;
3605 open.bits_per_sample = bits_per_sample;
3606 open.reserved = 0;
3607 pr_debug("%s: opening a transcode_loopback with mode_flags =[%d] session[%d]\n",
3608 __func__, open.mode_flags, ac->session);
3609
3610 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
3611 if (rc < 0) {
3612 pr_err("%s: open failed op[0x%x]rc[%d]\n",
3613 __func__, open.hdr.opcode, rc);
3614 rc = -EINVAL;
3615 goto fail_cmd;
3616 }
3617 rc = wait_event_timeout(ac->cmd_wait,
3618 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
3619 if (!rc) {
3620 pr_err("%s: timeout. waited for open_transcode_loopback\n",
3621 __func__);
3622 rc = -ETIMEDOUT;
3623 goto fail_cmd;
3624 }
3625 if (atomic_read(&ac->cmd_state) > 0) {
3626 pr_err("%s: DSP returned error[%s]\n",
3627 __func__, adsp_err_get_err_str(
3628 atomic_read(&ac->cmd_state)));
3629 rc = adsp_err_get_lnx_err_code(
3630 atomic_read(&ac->cmd_state));
3631 goto fail_cmd;
3632 }
3633
3634 return 0;
3635fail_cmd:
3636 return rc;
3637}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303638EXPORT_SYMBOL(q6asm_open_transcode_loopback);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303639
3640static
3641int q6asm_set_shared_circ_buff(struct audio_client *ac,
3642 struct asm_stream_cmd_open_shared_io *open,
3643 int bufsz, int bufcnt,
3644 int dir)
3645{
3646 struct audio_buffer *buf_circ;
3647 int bytes_to_alloc, rc;
3648 size_t len;
3649
Aditya Bavanaria8aea172017-09-13 11:37:53 +05303650 mutex_lock(&ac->cmd_lock);
3651
3652 if (ac->port[dir].buf) {
3653 pr_err("%s: Buffer already allocated\n", __func__);
3654 rc = -EINVAL;
Aditya Bavanaria8aea172017-09-13 11:37:53 +05303655 goto done;
3656 }
3657
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303658 buf_circ = kzalloc(sizeof(struct audio_buffer), GFP_KERNEL);
3659
3660 if (!buf_circ) {
3661 rc = -ENOMEM;
3662 goto done;
3663 }
3664
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303665 bytes_to_alloc = bufsz * bufcnt;
3666 bytes_to_alloc = PAGE_ALIGN(bytes_to_alloc);
3667
3668 rc = msm_audio_ion_alloc("audio_client", &buf_circ->client,
3669 &buf_circ->handle, bytes_to_alloc,
3670 (ion_phys_addr_t *)&buf_circ->phys,
3671 &len, &buf_circ->data);
3672
3673 if (rc) {
3674 pr_err("%s: Audio ION alloc is failed, rc = %d\n", __func__,
3675 rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303676 kfree(buf_circ);
3677 goto done;
3678 }
3679
Aditya Bavanaria8aea172017-09-13 11:37:53 +05303680 ac->port[dir].buf = buf_circ;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303681 buf_circ->used = dir ^ 1;
3682 buf_circ->size = bytes_to_alloc;
3683 buf_circ->actual_size = bytes_to_alloc;
3684 memset(buf_circ->data, 0, buf_circ->actual_size);
3685
3686 ac->port[dir].max_buf_cnt = 1;
3687
3688 open->shared_circ_buf_mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
3689 open->shared_circ_buf_num_regions = 1;
3690 open->shared_circ_buf_property_flag = 0x00;
3691 open->shared_circ_buf_start_phy_addr_lsw =
3692 lower_32_bits(buf_circ->phys);
3693 open->shared_circ_buf_start_phy_addr_msw =
3694 msm_audio_populate_upper_32_bits(buf_circ->phys);
3695 open->shared_circ_buf_size = bufsz * bufcnt;
3696
3697 open->map_region_circ_buf.shm_addr_lsw = lower_32_bits(buf_circ->phys);
3698 open->map_region_circ_buf.shm_addr_msw =
3699 msm_audio_populate_upper_32_bits(buf_circ->phys);
3700 open->map_region_circ_buf.mem_size_bytes = bytes_to_alloc;
3701
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303702done:
Xiaoyu Yef423ab12017-11-22 11:38:29 -08003703 mutex_unlock(&ac->cmd_lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303704 return rc;
3705}
3706
3707
3708static
3709int q6asm_set_shared_pos_buff(struct audio_client *ac,
3710 struct asm_stream_cmd_open_shared_io *open,
3711 int dir)
3712{
3713 struct audio_buffer *buf_pos = &ac->shared_pos_buf;
3714 int rc;
3715 size_t len;
3716 int bytes_to_alloc = sizeof(struct asm_shared_position_buffer);
3717
3718 mutex_lock(&ac->cmd_lock);
3719
3720 bytes_to_alloc = PAGE_ALIGN(bytes_to_alloc);
3721
3722 rc = msm_audio_ion_alloc("audio_client", &buf_pos->client,
3723 &buf_pos->handle, bytes_to_alloc,
3724 (ion_phys_addr_t *)&buf_pos->phys, &len,
3725 &buf_pos->data);
3726
3727 if (rc) {
3728 pr_err("%s: Audio pos buf ION alloc is failed, rc = %d\n",
3729 __func__, rc);
3730 goto done;
3731 }
3732
3733 buf_pos->used = dir ^ 1;
3734 buf_pos->size = bytes_to_alloc;
3735 buf_pos->actual_size = bytes_to_alloc;
3736
3737 open->shared_pos_buf_mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
3738 open->shared_pos_buf_num_regions = 1;
3739 open->shared_pos_buf_property_flag = 0x00;
3740 open->shared_pos_buf_phy_addr_lsw = lower_32_bits(buf_pos->phys);
3741 open->shared_pos_buf_phy_addr_msw =
3742 msm_audio_populate_upper_32_bits(buf_pos->phys);
3743
3744 open->map_region_pos_buf.shm_addr_lsw = lower_32_bits(buf_pos->phys);
3745 open->map_region_pos_buf.shm_addr_msw =
3746 msm_audio_populate_upper_32_bits(buf_pos->phys);
3747 open->map_region_pos_buf.mem_size_bytes = bytes_to_alloc;
3748
3749done:
3750 mutex_unlock(&ac->cmd_lock);
3751 return rc;
3752}
3753
3754/*
3755 * q6asm_open_shared_io: Open an ASM session for pull mode (playback)
3756 * or push mode (capture).
3757 * parameters
3758 * config - session parameters (channels, bits_per_sample, sr)
3759 * dir - stream direction (IN for playback, OUT for capture)
3760 * returns 0 if successful, error code otherwise
3761 */
3762int q6asm_open_shared_io(struct audio_client *ac,
3763 struct shared_io_config *config,
3764 int dir)
3765{
3766 struct asm_stream_cmd_open_shared_io *open;
3767 u8 *channel_mapping;
3768 int i, size_of_open, num_watermarks, bufsz, bufcnt, rc, flags = 0;
3769
3770 if (!ac || !config)
3771 return -EINVAL;
3772
3773 bufsz = config->bufsz;
3774 bufcnt = config->bufcnt;
3775 num_watermarks = 0;
3776
3777 ac->config = *config;
3778
3779 if (ac->session <= 0 || ac->session > SESSION_MAX) {
3780 pr_err("%s: Session %d is out of bounds\n",
3781 __func__, ac->session);
3782 return -EINVAL;
3783 }
3784
3785 size_of_open = sizeof(struct asm_stream_cmd_open_shared_io) +
3786 (sizeof(struct asm_shared_watermark_level) * num_watermarks);
3787
3788 open = kzalloc(PAGE_ALIGN(size_of_open), GFP_KERNEL);
3789 if (!open)
3790 return -ENOMEM;
3791
3792 q6asm_stream_add_hdr(ac, &open->hdr, size_of_open, TRUE,
3793 ac->stream_id);
3794
3795 atomic_set(&ac->cmd_state, 1);
3796
3797 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x, perf %d\n",
3798 __func__, open->hdr.token, ac->stream_id, ac->session,
3799 ac->perf_mode);
3800
3801 open->hdr.opcode =
3802 dir == IN ? ASM_STREAM_CMD_OPEN_PULL_MODE_WRITE :
3803 ASM_STREAM_CMD_OPEN_PUSH_MODE_READ;
3804
3805 pr_debug("%s perf_mode %d\n", __func__, ac->perf_mode);
3806 if (dir == IN)
3807 if (ac->perf_mode == ULL_POST_PROCESSING_PCM_MODE)
3808 flags = 4 << ASM_SHIFT_STREAM_PERF_FLAG_PULL_MODE_WRITE;
3809 else if (ac->perf_mode == ULTRA_LOW_LATENCY_PCM_MODE)
3810 flags = 2 << ASM_SHIFT_STREAM_PERF_FLAG_PULL_MODE_WRITE;
3811 else if (ac->perf_mode == LOW_LATENCY_PCM_MODE)
3812 flags = 1 << ASM_SHIFT_STREAM_PERF_FLAG_PULL_MODE_WRITE;
3813 else
3814 pr_err("Invalid perf mode for pull write\n");
3815 else
3816 if (ac->perf_mode == LOW_LATENCY_PCM_MODE)
3817 flags = ASM_LOW_LATENCY_TX_STREAM_SESSION <<
3818 ASM_SHIFT_STREAM_PERF_FLAG_PUSH_MODE_READ;
3819 else
3820 pr_err("Invalid perf mode for push read\n");
3821
3822 if (flags == 0) {
3823 pr_err("%s: Invalid mode[%d]\n", __func__,
3824 ac->perf_mode);
3825 kfree(open);
3826 return -EINVAL;
3827
3828 }
3829
3830 pr_debug("open.mode_flags = 0x%x\n", flags);
3831 open->mode_flags = flags;
3832 open->endpoint_type = ASM_END_POINT_DEVICE_MATRIX;
3833 open->topo_bits_per_sample = config->bits_per_sample;
3834
3835 open->topo_id = q6asm_get_asm_topology_cal();
3836
3837 if (config->format == FORMAT_LINEAR_PCM)
3838 open->fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3;
3839 else {
3840 pr_err("%s: Invalid format[%d]\n", __func__, config->format);
3841 rc = -EINVAL;
3842 goto done;
3843 }
3844
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303845 rc = q6asm_set_shared_circ_buff(ac, open, bufsz, bufcnt, dir);
3846
3847 if (rc)
3848 goto done;
3849
3850 ac->port[dir].tmp_hdl = 0;
3851
3852 rc = q6asm_set_shared_pos_buff(ac, open, dir);
3853
3854 if (rc)
3855 goto done;
3856
3857 /* asm_multi_channel_pcm_fmt_blk_v3 */
3858 open->fmt.num_channels = config->channels;
3859 open->fmt.bits_per_sample = config->bits_per_sample;
3860 open->fmt.sample_rate = config->rate;
3861 open->fmt.is_signed = 1;
3862 open->fmt.sample_word_size = config->sample_word_size;
3863
3864 channel_mapping = open->fmt.channel_mapping;
3865
3866 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
3867
3868 rc = q6asm_map_channels(channel_mapping, config->channels, false);
3869 if (rc) {
3870 pr_err("%s: Map channels failed, ret: %d\n", __func__, rc);
3871 goto done;
3872 }
3873
3874 open->num_watermark_levels = num_watermarks;
3875 for (i = 0; i < num_watermarks; i++) {
3876 open->watermark[i].watermark_level_bytes = i *
3877 ((bufsz * bufcnt) / num_watermarks);
3878 pr_debug("%s: Watermark level set for %i\n",
3879 __func__,
3880 open->watermark[i].watermark_level_bytes);
3881 }
3882
3883 rc = apr_send_pkt(ac->apr, (uint32_t *) open);
3884 if (rc < 0) {
3885 pr_err("%s: Open failed op[0x%x]rc[%d]\n",
3886 __func__, open->hdr.opcode, rc);
3887 goto done;
3888 }
3889
3890 pr_debug("%s: sent open apr pkt\n", __func__);
3891 rc = wait_event_timeout(ac->cmd_wait,
3892 (atomic_read(&ac->cmd_state) <= 0), 5*HZ);
3893 if (!rc) {
3894 pr_err("%s: Timeout. Waited for open write apr pkt rc[%d]\n",
3895 __func__, rc);
3896 rc = -ETIMEDOUT;
3897 goto done;
3898 }
3899
3900 if (atomic_read(&ac->cmd_state) < 0) {
3901 pr_err("%s: DSP returned error [%d]\n", __func__,
3902 atomic_read(&ac->cmd_state));
3903 rc = -EINVAL;
3904 goto done;
3905 }
3906
3907 ac->io_mode |= TUN_WRITE_IO_MODE;
3908 rc = 0;
3909done:
3910 kfree(open);
3911 return rc;
3912}
3913EXPORT_SYMBOL(q6asm_open_shared_io);
3914
3915/*
3916 * q6asm_shared_io_buf: Returns handle to the shared circular buffer being
3917 * used for pull/push mode.
3918 * parameters
3919 * dir - used to identify input/output port
3920 * returns buffer handle
3921 */
3922struct audio_buffer *q6asm_shared_io_buf(struct audio_client *ac,
3923 int dir)
3924{
3925 struct audio_port_data *port;
3926
3927 if (!ac) {
3928 pr_err("%s: ac is null\n", __func__);
3929 return NULL;
3930 }
3931 port = &ac->port[dir];
3932 return port->buf;
3933}
3934EXPORT_SYMBOL(q6asm_shared_io_buf);
3935
3936/*
3937 * q6asm_shared_io_free: Frees memory allocated for a pull/push session
3938 * parameters
3939 * dir - port direction
3940 * returns 0 if successful, error otherwise
3941 */
3942int q6asm_shared_io_free(struct audio_client *ac, int dir)
3943{
3944 struct audio_port_data *port;
3945
3946 if (!ac) {
3947 pr_err("%s: audio client is null\n", __func__);
3948 return -EINVAL;
3949 }
3950 port = &ac->port[dir];
3951 mutex_lock(&ac->cmd_lock);
3952 if (port->buf && port->buf->data) {
3953 msm_audio_ion_free(port->buf->client, port->buf->handle);
3954 port->buf->client = NULL;
3955 port->buf->handle = NULL;
3956 port->max_buf_cnt = 0;
3957 kfree(port->buf);
3958 port->buf = NULL;
3959 }
3960 if (ac->shared_pos_buf.data) {
3961 msm_audio_ion_free(ac->shared_pos_buf.client,
3962 ac->shared_pos_buf.handle);
3963 ac->shared_pos_buf.client = NULL;
3964 ac->shared_pos_buf.handle = NULL;
3965 }
3966 mutex_unlock(&ac->cmd_lock);
3967 return 0;
3968}
3969EXPORT_SYMBOL(q6asm_shared_io_free);
3970
3971/*
3972 * q6asm_get_shared_pos: Returns current read index/write index as observed
3973 * by the DSP. Note that this is an offset and iterates from [0,BUF_SIZE - 1]
3974 * parameters - (all output)
3975 * read_index - offset
3976 * wall_clk_msw1 - ADSP wallclock msw
3977 * wall_clk_lsw1 - ADSP wallclock lsw
3978 * returns 0 if successful, -EAGAIN if DSP failed to update after some
3979 * retries
3980 */
3981int q6asm_get_shared_pos(struct audio_client *ac, uint32_t *read_index,
3982 uint32_t *wall_clk_msw1, uint32_t *wall_clk_lsw1)
3983{
3984 struct asm_shared_position_buffer *pos_buf;
3985 uint32_t frame_cnt1, frame_cnt2;
3986 int i, j;
3987
3988 if (!ac) {
3989 pr_err("%s: audio client is null\n", __func__);
3990 return -EINVAL;
3991 }
3992
3993 pos_buf = ac->shared_pos_buf.data;
3994
3995 /* always try to get the latest update in the shared pos buffer */
3996 for (i = 0; i < 2; i++) {
3997 /* retry until there is an update from DSP */
3998 for (j = 0; j < 5; j++) {
3999 frame_cnt1 = pos_buf->frame_counter;
4000 if (frame_cnt1 != 0)
4001 break;
4002 }
4003
4004 *wall_clk_msw1 = pos_buf->wall_clock_us_msw;
4005 *wall_clk_lsw1 = pos_buf->wall_clock_us_lsw;
4006 *read_index = pos_buf->index;
4007 frame_cnt2 = pos_buf->frame_counter;
4008
4009 if (frame_cnt1 != frame_cnt2)
4010 continue;
4011 return 0;
4012 }
4013 pr_err("%s out of tries trying to get a good read, try again\n",
4014 __func__);
4015 return -EAGAIN;
4016}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304017EXPORT_SYMBOL(q6asm_get_shared_pos);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304018
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304019/**
4020 * q6asm_run -
4021 * command to set ASM to run state
4022 *
4023 * @ac: Audio client handle
4024 * @flags: Flags for session
4025 * @msw_ts: upper 32bits timestamp
4026 * @lsw_ts: lower 32bits timestamp
4027 *
4028 * Returns 0 on success or error on failure
4029 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304030int q6asm_run(struct audio_client *ac, uint32_t flags,
4031 uint32_t msw_ts, uint32_t lsw_ts)
4032{
4033 struct asm_session_cmd_run_v2 run;
4034 int rc;
4035
4036 if (ac == NULL) {
4037 pr_err("%s: APR handle NULL\n", __func__);
4038 return -EINVAL;
4039 }
4040 if (ac->apr == NULL) {
4041 pr_err("%s: AC APR handle NULL\n", __func__);
4042 return -EINVAL;
4043 }
4044 pr_debug("%s: session[%d]\n", __func__, ac->session);
4045
4046 q6asm_add_hdr(ac, &run.hdr, sizeof(run), TRUE);
4047 atomic_set(&ac->cmd_state, -1);
4048
4049 run.hdr.opcode = ASM_SESSION_CMD_RUN_V2;
4050 run.flags = flags;
4051 run.time_lsw = lsw_ts;
4052 run.time_msw = msw_ts;
4053
4054 config_debug_fs_run();
4055
4056 rc = apr_send_pkt(ac->apr, (uint32_t *) &run);
4057 if (rc < 0) {
4058 pr_err("%s: Commmand run failed[%d]",
4059 __func__, rc);
4060 rc = -EINVAL;
4061 goto fail_cmd;
4062 }
4063
4064 rc = wait_event_timeout(ac->cmd_wait,
4065 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4066 if (!rc) {
4067 pr_err("%s: timeout. waited for run success",
4068 __func__);
4069 rc = -ETIMEDOUT;
4070 goto fail_cmd;
4071 }
4072 if (atomic_read(&ac->cmd_state) > 0) {
4073 pr_err("%s: DSP returned error[%s]\n",
4074 __func__, adsp_err_get_err_str(
4075 atomic_read(&ac->cmd_state)));
4076 rc = adsp_err_get_lnx_err_code(
4077 atomic_read(&ac->cmd_state));
4078 goto fail_cmd;
4079 }
4080
4081 return 0;
4082fail_cmd:
4083 return rc;
4084}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304085EXPORT_SYMBOL(q6asm_run);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304086
4087static int __q6asm_run_nowait(struct audio_client *ac, uint32_t flags,
4088 uint32_t msw_ts, uint32_t lsw_ts, uint32_t stream_id)
4089{
4090 struct asm_session_cmd_run_v2 run;
4091 int rc;
4092
4093 if (ac == NULL) {
4094 pr_err("%s: APR handle NULL\n", __func__);
4095 return -EINVAL;
4096 }
4097 if (ac->apr == NULL) {
4098 pr_err("%s: AC APR handle NULL\n", __func__);
4099 return -EINVAL;
4100 }
4101 pr_debug("%s: session[%d]\n", __func__, ac->session);
4102
4103 q6asm_stream_add_hdr_async(ac, &run.hdr, sizeof(run), TRUE, stream_id);
4104 atomic_set(&ac->cmd_state, 1);
4105 run.hdr.opcode = ASM_SESSION_CMD_RUN_V2;
4106 run.flags = flags;
4107 run.time_lsw = lsw_ts;
4108 run.time_msw = msw_ts;
4109
4110 rc = apr_send_pkt(ac->apr, (uint32_t *) &run);
4111 if (rc < 0) {
4112 pr_err("%s: Commmand run failed[%d]", __func__, rc);
4113 return -EINVAL;
4114 }
4115 return 0;
4116}
4117
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304118/**
4119 * q6asm_run_nowait -
4120 * command to set ASM to run state with no wait for ack
4121 *
4122 * @ac: Audio client handle
4123 * @flags: Flags for session
4124 * @msw_ts: upper 32bits timestamp
4125 * @lsw_ts: lower 32bits timestamp
4126 *
4127 * Returns 0 on success or error on failure
4128 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304129int q6asm_run_nowait(struct audio_client *ac, uint32_t flags,
4130 uint32_t msw_ts, uint32_t lsw_ts)
4131{
4132 return __q6asm_run_nowait(ac, flags, msw_ts, lsw_ts, ac->stream_id);
4133}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304134EXPORT_SYMBOL(q6asm_run_nowait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304135
4136int q6asm_stream_run_nowait(struct audio_client *ac, uint32_t flags,
4137 uint32_t msw_ts, uint32_t lsw_ts, uint32_t stream_id)
4138{
4139 return __q6asm_run_nowait(ac, flags, msw_ts, lsw_ts, stream_id);
4140}
4141
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304142/**
4143 * q6asm_enc_cfg_blk_aac -
4144 * command to set encode cfg block for aac
4145 *
4146 * @ac: Audio client handle
4147 * @frames_per_buf: number of frames per buffer
4148 * @sample_rate: Sample rate
4149 * @channels: number of ASM channels
4150 * @bit_rate: Bit rate info
4151 * @mode: mode of AAC stream encode
4152 * @format: aac format flag
4153 *
4154 * Returns 0 on success or error on failure
4155 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304156int q6asm_enc_cfg_blk_aac(struct audio_client *ac,
4157 uint32_t frames_per_buf,
4158 uint32_t sample_rate, uint32_t channels,
4159 uint32_t bit_rate, uint32_t mode, uint32_t format)
4160{
4161 struct asm_aac_enc_cfg_v2 enc_cfg;
4162 int rc = 0;
4163
4164 pr_debug("%s: session[%d]frames[%d]SR[%d]ch[%d]bitrate[%d]mode[%d] format[%d]\n",
4165 __func__, ac->session, frames_per_buf,
4166 sample_rate, channels, bit_rate, mode, format);
4167
4168 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
4169 atomic_set(&ac->cmd_state, -1);
4170
4171 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4172 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
4173 enc_cfg.encdec.param_size = sizeof(struct asm_aac_enc_cfg_v2) -
4174 sizeof(struct asm_stream_cmd_set_encdec_param);
4175 enc_cfg.encblk.frames_per_buf = frames_per_buf;
4176 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
4177 sizeof(struct asm_enc_cfg_blk_param_v2);
4178 enc_cfg.bit_rate = bit_rate;
4179 enc_cfg.enc_mode = mode;
4180 enc_cfg.aac_fmt_flag = format;
4181 enc_cfg.channel_cfg = channels;
4182 enc_cfg.sample_rate = sample_rate;
4183
4184 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
4185 if (rc < 0) {
4186 pr_err("%s: Comamnd %d failed %d\n",
4187 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
4188 rc = -EINVAL;
4189 goto fail_cmd;
4190 }
4191 rc = wait_event_timeout(ac->cmd_wait,
4192 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4193 if (!rc) {
4194 pr_err("%s: timeout. waited for FORMAT_UPDATE\n",
4195 __func__);
4196 rc = -ETIMEDOUT;
4197 goto fail_cmd;
4198 }
4199 if (atomic_read(&ac->cmd_state) > 0) {
4200 pr_err("%s: DSP returned error[%s]\n",
4201 __func__, adsp_err_get_err_str(
4202 atomic_read(&ac->cmd_state)));
4203 rc = adsp_err_get_lnx_err_code(
4204 atomic_read(&ac->cmd_state));
4205 goto fail_cmd;
4206 }
4207 return 0;
4208fail_cmd:
4209 return rc;
4210}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304211EXPORT_SYMBOL(q6asm_enc_cfg_blk_aac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304212
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304213/**
4214 * q6asm_enc_cfg_blk_g711 -
4215 * command to set encode cfg block for g711
4216 *
4217 * @ac: Audio client handle
4218 * @frames_per_buf: number of frames per buffer
4219 * @sample_rate: Sample rate
4220 *
4221 * Returns 0 on success or error on failure
4222 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304223int q6asm_enc_cfg_blk_g711(struct audio_client *ac,
4224 uint32_t frames_per_buf,
4225 uint32_t sample_rate)
4226{
4227 struct asm_g711_enc_cfg_v2 enc_cfg;
4228 int rc = 0;
4229
4230 pr_debug("%s: session[%d]frames[%d]SR[%d]\n",
4231 __func__, ac->session, frames_per_buf,
4232 sample_rate);
4233
4234 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
4235 atomic_set(&ac->cmd_state, -1);
4236
4237 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4238 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
4239 enc_cfg.encdec.param_size = sizeof(struct asm_g711_enc_cfg_v2) -
4240 sizeof(struct asm_stream_cmd_set_encdec_param);
4241 enc_cfg.encblk.frames_per_buf = frames_per_buf;
4242 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
4243 sizeof(struct asm_enc_cfg_blk_param_v2);
4244 enc_cfg.sample_rate = sample_rate;
4245
4246 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
4247 if (rc < 0) {
4248 pr_err("%s: Comamnd %d failed %d\n",
4249 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
4250 rc = -EINVAL;
4251 goto fail_cmd;
4252 }
4253 rc = wait_event_timeout(ac->cmd_wait,
4254 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4255 if (!rc) {
4256 pr_err("%s: timeout. waited for FORMAT_UPDATE\n",
4257 __func__);
4258 rc = -ETIMEDOUT;
4259 goto fail_cmd;
4260 }
4261 if (atomic_read(&ac->cmd_state) > 0) {
4262 pr_err("%s: DSP returned error[%s]\n",
4263 __func__, adsp_err_get_err_str(
4264 atomic_read(&ac->cmd_state)));
4265 rc = adsp_err_get_lnx_err_code(
4266 atomic_read(&ac->cmd_state));
4267 goto fail_cmd;
4268 }
4269 return 0;
4270fail_cmd:
4271 return rc;
4272}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304273EXPORT_SYMBOL(q6asm_enc_cfg_blk_g711);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304274
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304275/**
4276 * q6asm_set_encdec_chan_map -
4277 * command to set encdec channel map
4278 *
4279 * @ac: Audio client handle
4280 * @channels: number of channels
4281 *
4282 * Returns 0 on success or error on failure
4283 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304284int q6asm_set_encdec_chan_map(struct audio_client *ac,
4285 uint32_t num_channels)
4286{
4287 struct asm_dec_out_chan_map_param chan_map;
4288 u8 *channel_mapping;
4289 int rc = 0;
4290
4291 pr_debug("%s: Session %d, num_channels = %d\n",
4292 __func__, ac->session, num_channels);
4293 q6asm_add_hdr(ac, &chan_map.hdr, sizeof(chan_map), TRUE);
4294 atomic_set(&ac->cmd_state, -1);
4295 chan_map.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4296 chan_map.encdec.param_id = ASM_PARAM_ID_DEC_OUTPUT_CHAN_MAP;
4297 chan_map.encdec.param_size = sizeof(struct asm_dec_out_chan_map_param) -
4298 (sizeof(struct apr_hdr) +
4299 sizeof(struct asm_stream_cmd_set_encdec_param));
4300 chan_map.num_channels = num_channels;
4301 channel_mapping = chan_map.channel_mapping;
4302 memset(channel_mapping, PCM_CHANNEL_NULL, MAX_CHAN_MAP_CHANNELS);
4303
4304 if (q6asm_map_channels(channel_mapping, num_channels, false)) {
4305 pr_err("%s: map channels failed %d\n", __func__, num_channels);
4306 return -EINVAL;
4307 }
4308
4309 rc = apr_send_pkt(ac->apr, (uint32_t *) &chan_map);
4310 if (rc < 0) {
4311 pr_err("%s: Command opcode[0x%x]paramid[0x%x] failed %d\n",
4312 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM,
4313 ASM_PARAM_ID_DEC_OUTPUT_CHAN_MAP, rc);
4314 goto fail_cmd;
4315 }
4316 rc = wait_event_timeout(ac->cmd_wait,
4317 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4318 if (!rc) {
4319 pr_err("%s: timeout opcode[0x%x]\n", __func__,
4320 chan_map.hdr.opcode);
4321 rc = -ETIMEDOUT;
4322 goto fail_cmd;
4323 }
4324 if (atomic_read(&ac->cmd_state) > 0) {
4325 pr_err("%s: DSP returned error[%s]\n",
4326 __func__, adsp_err_get_err_str(
4327 atomic_read(&ac->cmd_state)));
4328 rc = adsp_err_get_lnx_err_code(
4329 atomic_read(&ac->cmd_state));
4330 goto fail_cmd;
4331 }
4332 return 0;
4333fail_cmd:
4334 return rc;
4335}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304336EXPORT_SYMBOL(q6asm_set_encdec_chan_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304337
4338/*
4339 * q6asm_enc_cfg_blk_pcm_v4 - sends encoder configuration parameters
4340 *
4341 * @ac: Client session handle
4342 * @rate: sample rate
4343 * @channels: number of channels
4344 * @bits_per_sample: bit width of encoder session
4345 * @use_default_chmap: true if default channel map to be used
4346 * @use_back_flavor: to configure back left and right channel
4347 * @channel_map: input channel map
4348 * @sample_word_size: Size in bits of the word that holds a sample of a channel
4349 * @endianness: endianness of the pcm data
4350 * @mode: Mode to provide additional info about the pcm input data
4351 */
4352int q6asm_enc_cfg_blk_pcm_v4(struct audio_client *ac,
4353 uint32_t rate, uint32_t channels,
4354 uint16_t bits_per_sample, bool use_default_chmap,
4355 bool use_back_flavor, u8 *channel_map,
4356 uint16_t sample_word_size, uint16_t endianness,
4357 uint16_t mode)
4358{
4359 struct asm_multi_channel_pcm_enc_cfg_v4 enc_cfg;
4360 struct asm_enc_cfg_blk_param_v2 enc_fg_blk;
4361 u8 *channel_mapping;
4362 u32 frames_per_buf = 0;
4363 int rc;
4364
4365 if (!use_default_chmap && (channel_map == NULL)) {
4366 pr_err("%s: No valid chan map and can't use default\n",
4367 __func__);
4368 rc = -EINVAL;
4369 goto fail_cmd;
4370 }
4371
4372 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
4373 ac->session, rate, channels,
4374 bits_per_sample, sample_word_size);
4375
4376 memset(&enc_cfg, 0, sizeof(enc_cfg));
4377 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
4378 atomic_set(&ac->cmd_state, -1);
4379 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4380 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
4381 enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) -
4382 sizeof(enc_cfg.encdec);
4383 enc_cfg.encblk.frames_per_buf = frames_per_buf;
4384 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
4385 sizeof(enc_fg_blk);
4386 enc_cfg.num_channels = channels;
4387 enc_cfg.bits_per_sample = bits_per_sample;
4388 enc_cfg.sample_rate = rate;
4389 enc_cfg.is_signed = 1;
4390 enc_cfg.sample_word_size = sample_word_size;
4391 enc_cfg.endianness = endianness;
4392 enc_cfg.mode = mode;
4393 channel_mapping = enc_cfg.channel_mapping;
4394
4395 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
4396
4397 if (use_default_chmap) {
4398 pr_debug("%s: setting default channel map for %d channels",
4399 __func__, channels);
4400 if (q6asm_map_channels(channel_mapping, channels,
4401 use_back_flavor)) {
4402 pr_err("%s: map channels failed %d\n",
4403 __func__, channels);
4404 rc = -EINVAL;
4405 goto fail_cmd;
4406 }
4407 } else {
4408 pr_debug("%s: Using pre-defined channel map", __func__);
4409 memcpy(channel_mapping, channel_map,
4410 PCM_FORMAT_MAX_NUM_CHANNEL);
4411 }
4412
4413 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
4414 if (rc < 0) {
4415 pr_err("%s: Command open failed %d\n", __func__, rc);
4416 goto fail_cmd;
4417 }
4418 rc = wait_event_timeout(ac->cmd_wait,
4419 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4420 if (!rc) {
4421 pr_err("%s: timeout opcode[0x%x]\n",
4422 __func__, enc_cfg.hdr.opcode);
4423 rc = -ETIMEDOUT;
4424 goto fail_cmd;
4425 }
4426 if (atomic_read(&ac->cmd_state) > 0) {
4427 pr_err("%s: DSP returned error[%s]\n",
4428 __func__, adsp_err_get_err_str(
4429 atomic_read(&ac->cmd_state)));
4430 rc = adsp_err_get_lnx_err_code(
4431 atomic_read(&ac->cmd_state));
4432 goto fail_cmd;
4433 }
4434 return 0;
4435fail_cmd:
4436 return rc;
4437}
4438EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v4);
4439
4440/*
4441 * q6asm_enc_cfg_blk_pcm_v3 - sends encoder configuration parameters
4442 *
4443 * @ac: Client session handle
4444 * @rate: sample rate
4445 * @channels: number of channels
4446 * @bits_per_sample: bit width of encoder session
4447 * @use_default_chmap: true if default channel map to be used
4448 * @use_back_flavor: to configure back left and right channel
4449 * @channel_map: input channel map
4450 * @sample_word_size: Size in bits of the word that holds a sample of a channel
4451 */
4452int q6asm_enc_cfg_blk_pcm_v3(struct audio_client *ac,
4453 uint32_t rate, uint32_t channels,
4454 uint16_t bits_per_sample, bool use_default_chmap,
4455 bool use_back_flavor, u8 *channel_map,
4456 uint16_t sample_word_size)
4457{
4458 struct asm_multi_channel_pcm_enc_cfg_v3 enc_cfg;
4459 struct asm_enc_cfg_blk_param_v2 enc_fg_blk;
4460 u8 *channel_mapping;
4461 u32 frames_per_buf = 0;
4462 int rc;
4463
4464 if (!use_default_chmap && (channel_map == NULL)) {
4465 pr_err("%s: No valid chan map and can't use default\n",
4466 __func__);
4467 rc = -EINVAL;
4468 goto fail_cmd;
4469 }
4470
4471 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
4472 ac->session, rate, channels,
4473 bits_per_sample, sample_word_size);
4474
4475 memset(&enc_cfg, 0, sizeof(enc_cfg));
4476 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
4477 atomic_set(&ac->cmd_state, -1);
4478 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4479 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
4480 enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) -
4481 sizeof(enc_cfg.encdec);
4482 enc_cfg.encblk.frames_per_buf = frames_per_buf;
4483 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
4484 sizeof(enc_fg_blk);
4485 enc_cfg.num_channels = channels;
4486 enc_cfg.bits_per_sample = bits_per_sample;
4487 enc_cfg.sample_rate = rate;
4488 enc_cfg.is_signed = 1;
4489 enc_cfg.sample_word_size = sample_word_size;
4490 channel_mapping = enc_cfg.channel_mapping;
4491
4492 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
4493
4494 if (use_default_chmap) {
4495 pr_debug("%s: setting default channel map for %d channels",
4496 __func__, channels);
4497 if (q6asm_map_channels(channel_mapping, channels,
4498 use_back_flavor)) {
4499 pr_err("%s: map channels failed %d\n",
4500 __func__, channels);
4501 rc = -EINVAL;
4502 goto fail_cmd;
4503 }
4504 } else {
4505 pr_debug("%s: Using pre-defined channel map", __func__);
4506 memcpy(channel_mapping, channel_map,
4507 PCM_FORMAT_MAX_NUM_CHANNEL);
4508 }
4509
4510 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
4511 if (rc < 0) {
4512 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
4513 goto fail_cmd;
4514 }
4515 rc = wait_event_timeout(ac->cmd_wait,
4516 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4517 if (!rc) {
4518 pr_err("%s: timeout opcode[0x%x]\n",
4519 __func__, enc_cfg.hdr.opcode);
4520 rc = -ETIMEDOUT;
4521 goto fail_cmd;
4522 }
4523 if (atomic_read(&ac->cmd_state) > 0) {
4524 pr_err("%s: DSP returned error[%s]\n",
4525 __func__, adsp_err_get_err_str(
4526 atomic_read(&ac->cmd_state)));
4527 rc = adsp_err_get_lnx_err_code(
4528 atomic_read(&ac->cmd_state));
4529 goto fail_cmd;
4530 }
4531 return 0;
4532fail_cmd:
4533 return rc;
4534}
4535EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v3);
4536
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304537/**
4538 * q6asm_enc_cfg_blk_pcm_v2 -
4539 * command to set encode config block for pcm_v2
4540 *
4541 * @ac: Audio client handle
4542 * @rate: sample rate
4543 * @channels: number of channels
4544 * @bits_per_sample: number of bits per sample
4545 * @use_default_chmap: Flag indicating to use default ch_map or not
4546 * @use_back_flavor: back flavor flag
4547 * @channel_map: Custom channel map settings
4548 *
4549 * Returns 0 on success or error on failure
4550 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304551int q6asm_enc_cfg_blk_pcm_v2(struct audio_client *ac,
4552 uint32_t rate, uint32_t channels, uint16_t bits_per_sample,
4553 bool use_default_chmap, bool use_back_flavor, u8 *channel_map)
4554{
4555 struct asm_multi_channel_pcm_enc_cfg_v2 enc_cfg;
4556 u8 *channel_mapping;
4557 u32 frames_per_buf = 0;
4558
4559 int rc = 0;
4560
4561 if (!use_default_chmap && (channel_map == NULL)) {
4562 pr_err("%s: No valid chan map and can't use default\n",
4563 __func__);
4564 return -EINVAL;
4565 }
4566
4567 pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
4568 ac->session, rate, channels);
4569
4570 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
4571 atomic_set(&ac->cmd_state, -1);
4572 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4573 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
4574 enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) -
4575 sizeof(enc_cfg.encdec);
4576 enc_cfg.encblk.frames_per_buf = frames_per_buf;
4577 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
4578 sizeof(struct asm_enc_cfg_blk_param_v2);
4579
4580 enc_cfg.num_channels = channels;
4581 enc_cfg.bits_per_sample = bits_per_sample;
4582 enc_cfg.sample_rate = rate;
4583 enc_cfg.is_signed = 1;
4584 channel_mapping = enc_cfg.channel_mapping;
4585
4586 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
4587
4588 if (use_default_chmap) {
4589 pr_debug("%s: setting default channel map for %d channels",
4590 __func__, channels);
4591 if (q6asm_map_channels(channel_mapping, channels,
4592 use_back_flavor)) {
4593 pr_err("%s: map channels failed %d\n",
4594 __func__, channels);
4595 return -EINVAL;
4596 }
4597 } else {
4598 pr_debug("%s: Using pre-defined channel map", __func__);
4599 memcpy(channel_mapping, channel_map,
4600 PCM_FORMAT_MAX_NUM_CHANNEL);
4601 }
4602
4603 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
4604 if (rc < 0) {
4605 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
4606 rc = -EINVAL;
4607 goto fail_cmd;
4608 }
4609 rc = wait_event_timeout(ac->cmd_wait,
4610 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4611 if (!rc) {
4612 pr_err("%s: timeout opcode[0x%x]\n",
4613 __func__, enc_cfg.hdr.opcode);
4614 rc = -ETIMEDOUT;
4615 goto fail_cmd;
4616 }
4617 if (atomic_read(&ac->cmd_state) > 0) {
4618 pr_err("%s: DSP returned error[%s]\n",
4619 __func__, adsp_err_get_err_str(
4620 atomic_read(&ac->cmd_state)));
4621 rc = adsp_err_get_lnx_err_code(
4622 atomic_read(&ac->cmd_state));
4623 goto fail_cmd;
4624 }
4625 return 0;
4626fail_cmd:
4627 return rc;
4628}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304629EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304630
4631static int __q6asm_enc_cfg_blk_pcm_v4(struct audio_client *ac,
4632 uint32_t rate, uint32_t channels,
4633 uint16_t bits_per_sample,
4634 uint16_t sample_word_size,
4635 uint16_t endianness,
4636 uint16_t mode)
4637{
4638 return q6asm_enc_cfg_blk_pcm_v4(ac, rate, channels,
4639 bits_per_sample, true, false, NULL,
4640 sample_word_size, endianness, mode);
4641}
4642
4643static int __q6asm_enc_cfg_blk_pcm_v3(struct audio_client *ac,
4644 uint32_t rate, uint32_t channels,
4645 uint16_t bits_per_sample,
4646 uint16_t sample_word_size)
4647{
4648 return q6asm_enc_cfg_blk_pcm_v3(ac, rate, channels,
4649 bits_per_sample, true, false, NULL,
4650 sample_word_size);
4651}
4652
4653static int __q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
4654 uint32_t rate, uint32_t channels, uint16_t bits_per_sample)
4655{
4656 return q6asm_enc_cfg_blk_pcm_v2(ac, rate, channels,
4657 bits_per_sample, true, false, NULL);
4658}
4659
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304660/**
4661 * q6asm_enc_cfg_blk_pcm -
4662 * command to set encode config block for pcm
4663 *
4664 * @ac: Audio client handle
4665 * @rate: sample rate
4666 * @channels: number of channels
4667 *
4668 * Returns 0 on success or error on failure
4669 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304670int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
4671 uint32_t rate, uint32_t channels)
4672{
4673 return __q6asm_enc_cfg_blk_pcm(ac, rate, channels, 16);
4674}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304675EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304676
4677int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac,
4678 uint32_t rate, uint32_t channels, uint16_t bits_per_sample)
4679{
4680 return __q6asm_enc_cfg_blk_pcm(ac, rate, channels, bits_per_sample);
4681}
4682
4683/*
4684 * q6asm_enc_cfg_blk_pcm_format_support_v3 - sends encoder configuration
4685 * parameters
4686 *
4687 * @ac: Client session handle
4688 * @rate: sample rate
4689 * @channels: number of channels
4690 * @bits_per_sample: bit width of encoder session
4691 * @sample_word_size: Size in bits of the word that holds a sample of a channel
4692 */
4693int q6asm_enc_cfg_blk_pcm_format_support_v3(struct audio_client *ac,
4694 uint32_t rate, uint32_t channels,
4695 uint16_t bits_per_sample,
4696 uint16_t sample_word_size)
4697{
4698 return __q6asm_enc_cfg_blk_pcm_v3(ac, rate, channels,
4699 bits_per_sample, sample_word_size);
4700}
4701EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v3);
4702
4703/*
4704 * q6asm_enc_cfg_blk_pcm_format_support_v4 - sends encoder configuration
4705 * parameters
4706 *
4707 * @ac: Client session handle
4708 * @rate: sample rate
4709 * @channels: number of channels
4710 * @bits_per_sample: bit width of encoder session
4711 * @sample_word_size: Size in bits of the word that holds a sample of a channel
4712 * @endianness: endianness of the pcm data
4713 * @mode: Mode to provide additional info about the pcm input data
4714 */
4715int q6asm_enc_cfg_blk_pcm_format_support_v4(struct audio_client *ac,
4716 uint32_t rate, uint32_t channels,
4717 uint16_t bits_per_sample,
4718 uint16_t sample_word_size,
4719 uint16_t endianness,
4720 uint16_t mode)
4721{
4722 return __q6asm_enc_cfg_blk_pcm_v4(ac, rate, channels,
4723 bits_per_sample, sample_word_size,
4724 endianness, mode);
4725}
4726EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v4);
4727
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304728/**
4729 * q6asm_enc_cfg_blk_pcm_native -
4730 * command to set encode config block for pcm_native
4731 *
4732 * @ac: Audio client handle
4733 * @rate: sample rate
4734 * @channels: number of channels
4735 *
4736 * Returns 0 on success or error on failure
4737 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304738int q6asm_enc_cfg_blk_pcm_native(struct audio_client *ac,
4739 uint32_t rate, uint32_t channels)
4740{
4741 struct asm_multi_channel_pcm_enc_cfg_v2 enc_cfg;
4742 u8 *channel_mapping;
4743 u32 frames_per_buf = 0;
4744
4745 int rc = 0;
4746
4747 pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
4748 ac->session, rate, channels);
4749
4750 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
4751 atomic_set(&ac->cmd_state, -1);
4752 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4753 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
4754 enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) -
4755 sizeof(enc_cfg.encdec);
4756 enc_cfg.encblk.frames_per_buf = frames_per_buf;
4757 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
4758 sizeof(struct asm_enc_cfg_blk_param_v2);
4759
4760 enc_cfg.num_channels = 0;/*channels;*/
4761 enc_cfg.bits_per_sample = 16;
4762 enc_cfg.sample_rate = 0;/*rate;*/
4763 enc_cfg.is_signed = 1;
4764 channel_mapping = enc_cfg.channel_mapping;
4765
4766
4767 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
4768
4769 if (q6asm_map_channels(channel_mapping, channels, false)) {
4770 pr_err("%s: map channels failed %d\n", __func__, channels);
4771 return -EINVAL;
4772 }
4773
4774 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
4775 if (rc < 0) {
4776 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
4777 rc = -EINVAL;
4778 goto fail_cmd;
4779 }
4780 rc = wait_event_timeout(ac->cmd_wait,
4781 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4782 if (!rc) {
4783 pr_err("%s: timeout opcode[0x%x]\n",
4784 __func__, enc_cfg.hdr.opcode);
4785 rc = -ETIMEDOUT;
4786 goto fail_cmd;
4787 }
4788 if (atomic_read(&ac->cmd_state) > 0) {
4789 pr_err("%s: DSP returned error[%s]\n",
4790 __func__, adsp_err_get_err_str(
4791 atomic_read(&ac->cmd_state)));
4792 rc = adsp_err_get_lnx_err_code(
4793 atomic_read(&ac->cmd_state));
4794 goto fail_cmd;
4795 }
4796 return 0;
4797fail_cmd:
4798 return rc;
4799}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304800EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_native);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304801
4802static int q6asm_map_channels(u8 *channel_mapping, uint32_t channels,
4803 bool use_back_flavor)
4804{
4805 u8 *lchannel_mapping;
4806
4807 lchannel_mapping = channel_mapping;
4808 pr_debug("%s: channels passed: %d\n", __func__, channels);
4809 if (channels == 1) {
4810 lchannel_mapping[0] = PCM_CHANNEL_FC;
4811 } else if (channels == 2) {
4812 lchannel_mapping[0] = PCM_CHANNEL_FL;
4813 lchannel_mapping[1] = PCM_CHANNEL_FR;
4814 } else if (channels == 3) {
4815 lchannel_mapping[0] = PCM_CHANNEL_FL;
4816 lchannel_mapping[1] = PCM_CHANNEL_FR;
4817 lchannel_mapping[2] = PCM_CHANNEL_FC;
4818 } else if (channels == 4) {
4819 lchannel_mapping[0] = PCM_CHANNEL_FL;
4820 lchannel_mapping[1] = PCM_CHANNEL_FR;
4821 lchannel_mapping[2] = use_back_flavor ?
4822 PCM_CHANNEL_LB : PCM_CHANNEL_LS;
4823 lchannel_mapping[3] = use_back_flavor ?
4824 PCM_CHANNEL_RB : PCM_CHANNEL_RS;
4825 } else if (channels == 5) {
4826 lchannel_mapping[0] = PCM_CHANNEL_FL;
4827 lchannel_mapping[1] = PCM_CHANNEL_FR;
4828 lchannel_mapping[2] = PCM_CHANNEL_FC;
4829 lchannel_mapping[3] = use_back_flavor ?
4830 PCM_CHANNEL_LB : PCM_CHANNEL_LS;
4831 lchannel_mapping[4] = use_back_flavor ?
4832 PCM_CHANNEL_RB : PCM_CHANNEL_RS;
4833 } else if (channels == 6) {
4834 lchannel_mapping[0] = PCM_CHANNEL_FL;
4835 lchannel_mapping[1] = PCM_CHANNEL_FR;
4836 lchannel_mapping[2] = PCM_CHANNEL_FC;
4837 lchannel_mapping[3] = PCM_CHANNEL_LFE;
4838 lchannel_mapping[4] = use_back_flavor ?
4839 PCM_CHANNEL_LB : PCM_CHANNEL_LS;
4840 lchannel_mapping[5] = use_back_flavor ?
4841 PCM_CHANNEL_RB : PCM_CHANNEL_RS;
4842 } else if (channels == 7) {
4843 /*
4844 * Configured for 5.1 channel mapping + 1 channel for debug
4845 * Can be customized based on DSP.
4846 */
4847 lchannel_mapping[0] = PCM_CHANNEL_FL;
4848 lchannel_mapping[1] = PCM_CHANNEL_FR;
4849 lchannel_mapping[2] = PCM_CHANNEL_FC;
4850 lchannel_mapping[3] = PCM_CHANNEL_LFE;
4851 lchannel_mapping[4] = use_back_flavor ?
4852 PCM_CHANNEL_LB : PCM_CHANNEL_LS;
4853 lchannel_mapping[5] = use_back_flavor ?
4854 PCM_CHANNEL_RB : PCM_CHANNEL_RS;
4855 lchannel_mapping[6] = PCM_CHANNEL_CS;
4856 } else if (channels == 8) {
4857 lchannel_mapping[0] = PCM_CHANNEL_FL;
4858 lchannel_mapping[1] = PCM_CHANNEL_FR;
4859 lchannel_mapping[2] = PCM_CHANNEL_FC;
4860 lchannel_mapping[3] = PCM_CHANNEL_LFE;
4861 lchannel_mapping[4] = PCM_CHANNEL_LB;
4862 lchannel_mapping[5] = PCM_CHANNEL_RB;
4863 lchannel_mapping[6] = PCM_CHANNEL_LS;
4864 lchannel_mapping[7] = PCM_CHANNEL_RS;
4865 } else {
4866 pr_err("%s: ERROR.unsupported num_ch = %u\n",
4867 __func__, channels);
4868 return -EINVAL;
4869 }
4870 return 0;
4871}
4872
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304873/**
4874 * q6asm_enable_sbrps -
4875 * command to enable sbrps for ASM
4876 *
4877 * @ac: Audio client handle
4878 * @sbr_ps_enable: flag for sbr_ps enable or disable
4879 *
4880 * Returns 0 on success or error on failure
4881 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304882int q6asm_enable_sbrps(struct audio_client *ac,
4883 uint32_t sbr_ps_enable)
4884{
4885 struct asm_aac_sbr_ps_flag_param sbrps;
4886 u32 frames_per_buf = 0;
4887
4888 int rc = 0;
4889
4890 pr_debug("%s: Session %d\n", __func__, ac->session);
4891
4892 q6asm_add_hdr(ac, &sbrps.hdr, sizeof(sbrps), TRUE);
4893 atomic_set(&ac->cmd_state, -1);
4894
4895 sbrps.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4896 sbrps.encdec.param_id = ASM_PARAM_ID_AAC_SBR_PS_FLAG;
4897 sbrps.encdec.param_size = sizeof(struct asm_aac_sbr_ps_flag_param) -
4898 sizeof(struct asm_stream_cmd_set_encdec_param);
4899 sbrps.encblk.frames_per_buf = frames_per_buf;
4900 sbrps.encblk.enc_cfg_blk_size = sbrps.encdec.param_size -
4901 sizeof(struct asm_enc_cfg_blk_param_v2);
4902
4903 sbrps.sbr_ps_flag = sbr_ps_enable;
4904
4905 rc = apr_send_pkt(ac->apr, (uint32_t *) &sbrps);
4906 if (rc < 0) {
4907 pr_err("%s: Command opcode[0x%x]paramid[0x%x] failed %d\n",
4908 __func__,
4909 ASM_STREAM_CMD_SET_ENCDEC_PARAM,
4910 ASM_PARAM_ID_AAC_SBR_PS_FLAG, rc);
4911 rc = -EINVAL;
4912 goto fail_cmd;
4913 }
4914 rc = wait_event_timeout(ac->cmd_wait,
4915 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4916 if (!rc) {
4917 pr_err("%s: timeout opcode[0x%x] ", __func__, sbrps.hdr.opcode);
4918 rc = -ETIMEDOUT;
4919 goto fail_cmd;
4920 }
4921 if (atomic_read(&ac->cmd_state) > 0) {
4922 pr_err("%s: DSP returned error[%s]\n",
4923 __func__, adsp_err_get_err_str(
4924 atomic_read(&ac->cmd_state)));
4925 rc = adsp_err_get_lnx_err_code(
4926 atomic_read(&ac->cmd_state));
4927 goto fail_cmd;
4928 }
4929 return 0;
4930fail_cmd:
4931 return rc;
4932}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304933EXPORT_SYMBOL(q6asm_enable_sbrps);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304934
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304935/**
4936 * q6asm_cfg_dual_mono_aac -
4937 * command to set config for dual mono aac
4938 *
4939 * @ac: Audio client handle
4940 * @sce_left: left sce val
4941 * @sce_right: right sce val
4942 *
4943 * Returns 0 on success or error on failure
4944 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304945int q6asm_cfg_dual_mono_aac(struct audio_client *ac,
4946 uint16_t sce_left, uint16_t sce_right)
4947{
4948 struct asm_aac_dual_mono_mapping_param dual_mono;
4949
4950 int rc = 0;
4951
4952 pr_debug("%s: Session %d, sce_left = %d, sce_right = %d\n",
4953 __func__, ac->session, sce_left, sce_right);
4954
4955 q6asm_add_hdr(ac, &dual_mono.hdr, sizeof(dual_mono), TRUE);
4956 atomic_set(&ac->cmd_state, -1);
4957
4958 dual_mono.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4959 dual_mono.encdec.param_id = ASM_PARAM_ID_AAC_DUAL_MONO_MAPPING;
4960 dual_mono.encdec.param_size = sizeof(dual_mono.left_channel_sce) +
4961 sizeof(dual_mono.right_channel_sce);
4962 dual_mono.left_channel_sce = sce_left;
4963 dual_mono.right_channel_sce = sce_right;
4964
4965 rc = apr_send_pkt(ac->apr, (uint32_t *) &dual_mono);
4966 if (rc < 0) {
4967 pr_err("%s: Command opcode[0x%x]paramid[0x%x] failed %d\n",
4968 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM,
4969 ASM_PARAM_ID_AAC_DUAL_MONO_MAPPING, rc);
4970 rc = -EINVAL;
4971 goto fail_cmd;
4972 }
4973 rc = wait_event_timeout(ac->cmd_wait,
4974 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4975 if (!rc) {
4976 pr_err("%s: timeout opcode[0x%x]\n", __func__,
4977 dual_mono.hdr.opcode);
4978 rc = -ETIMEDOUT;
4979 goto fail_cmd;
4980 }
4981 if (atomic_read(&ac->cmd_state) > 0) {
4982 pr_err("%s: DSP returned error[%s]\n",
4983 __func__, adsp_err_get_err_str(
4984 atomic_read(&ac->cmd_state)));
4985 rc = adsp_err_get_lnx_err_code(
4986 atomic_read(&ac->cmd_state));
4987 goto fail_cmd;
4988 }
4989 return 0;
4990fail_cmd:
4991 return rc;
4992}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304993EXPORT_SYMBOL(q6asm_cfg_dual_mono_aac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304994
4995/* Support for selecting stereo mixing coefficients for B family not done */
4996int q6asm_cfg_aac_sel_mix_coef(struct audio_client *ac, uint32_t mix_coeff)
4997{
4998 struct asm_aac_stereo_mix_coeff_selection_param_v2 aac_mix_coeff;
4999 int rc = 0;
5000
5001 q6asm_add_hdr(ac, &aac_mix_coeff.hdr, sizeof(aac_mix_coeff), TRUE);
5002 atomic_set(&ac->cmd_state, -1);
5003 aac_mix_coeff.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
5004 aac_mix_coeff.param_id =
5005 ASM_PARAM_ID_AAC_STEREO_MIX_COEFF_SELECTION_FLAG_V2;
5006 aac_mix_coeff.param_size =
5007 sizeof(struct asm_aac_stereo_mix_coeff_selection_param_v2);
5008 aac_mix_coeff.aac_stereo_mix_coeff_flag = mix_coeff;
5009 pr_debug("%s: mix_coeff = %u\n", __func__, mix_coeff);
5010 rc = apr_send_pkt(ac->apr, (uint32_t *) &aac_mix_coeff);
5011 if (rc < 0) {
5012 pr_err("%s: Command opcode[0x%x]paramid[0x%x] failed %d\n",
5013 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM,
5014 ASM_PARAM_ID_AAC_STEREO_MIX_COEFF_SELECTION_FLAG_V2,
5015 rc);
5016 rc = -EINVAL;
5017 goto fail_cmd;
5018 }
5019 rc = wait_event_timeout(ac->cmd_wait,
5020 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5021 if (!rc) {
5022 pr_err("%s: timeout opcode[0x%x]\n",
5023 __func__, aac_mix_coeff.hdr.opcode);
5024 rc = -ETIMEDOUT;
5025 goto fail_cmd;
5026 }
5027 if (atomic_read(&ac->cmd_state) > 0) {
5028 pr_err("%s: DSP returned error[%s]\n",
5029 __func__, adsp_err_get_err_str(
5030 atomic_read(&ac->cmd_state)));
5031 rc = adsp_err_get_lnx_err_code(
5032 atomic_read(&ac->cmd_state));
5033 goto fail_cmd;
5034 }
5035 return 0;
5036fail_cmd:
5037 return rc;
5038}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305039EXPORT_SYMBOL(q6asm_cfg_aac_sel_mix_coef);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305040
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305041/**
5042 * q6asm_enc_cfg_blk_qcelp -
5043 * command to set encode config block for QCELP
5044 *
5045 * @ac: Audio client handle
5046 * @frames_per_buf: Number of frames per buffer
5047 * @min_rate: Minimum Enc rate
5048 * @max_rate: Maximum Enc rate
5049 * reduced_rate_level: Reduced rate level
5050 * @rate_modulation_cmd: rate modulation command
5051 *
5052 * Returns 0 on success or error on failure
5053 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305054int q6asm_enc_cfg_blk_qcelp(struct audio_client *ac, uint32_t frames_per_buf,
5055 uint16_t min_rate, uint16_t max_rate,
5056 uint16_t reduced_rate_level, uint16_t rate_modulation_cmd)
5057{
5058 struct asm_v13k_enc_cfg enc_cfg;
5059 int rc = 0;
5060
5061 pr_debug("%s: session[%d]frames[%d]min_rate[0x%4x]max_rate[0x%4x] reduced_rate_level[0x%4x]rate_modulation_cmd[0x%4x]\n",
5062 __func__,
5063 ac->session, frames_per_buf, min_rate, max_rate,
5064 reduced_rate_level, rate_modulation_cmd);
5065
5066 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
5067 atomic_set(&ac->cmd_state, -1);
5068 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
5069 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
5070 enc_cfg.encdec.param_size = sizeof(struct asm_v13k_enc_cfg) -
5071 sizeof(struct asm_stream_cmd_set_encdec_param);
5072 enc_cfg.encblk.frames_per_buf = frames_per_buf;
5073 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
5074 sizeof(struct asm_enc_cfg_blk_param_v2);
5075
5076 enc_cfg.min_rate = min_rate;
5077 enc_cfg.max_rate = max_rate;
5078 enc_cfg.reduced_rate_cmd = reduced_rate_level;
5079 enc_cfg.rate_mod_cmd = rate_modulation_cmd;
5080
5081 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
5082 if (rc < 0) {
5083 pr_err("%s: Comamnd %d failed %d\n",
5084 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
5085 rc = -EINVAL;
5086 goto fail_cmd;
5087 }
5088 rc = wait_event_timeout(ac->cmd_wait,
5089 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5090 if (!rc) {
5091 pr_err("%s: timeout. waited for setencdec v13k resp\n",
5092 __func__);
5093 rc = -ETIMEDOUT;
5094 goto fail_cmd;
5095 }
5096 if (atomic_read(&ac->cmd_state) > 0) {
5097 pr_err("%s: DSP returned error[%s]\n",
5098 __func__, adsp_err_get_err_str(
5099 atomic_read(&ac->cmd_state)));
5100 rc = adsp_err_get_lnx_err_code(
5101 atomic_read(&ac->cmd_state));
5102 goto fail_cmd;
5103 }
5104 return 0;
5105fail_cmd:
5106 return rc;
5107}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305108EXPORT_SYMBOL(q6asm_enc_cfg_blk_qcelp);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305109
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305110/**
5111 * q6asm_enc_cfg_blk_evrc -
5112 * command to set encode config block for EVRC
5113 *
5114 * @ac: Audio client handle
5115 * @frames_per_buf: Number of frames per buffer
5116 * @min_rate: Minimum Enc rate
5117 * @max_rate: Maximum Enc rate
5118 * @rate_modulation_cmd: rate modulation command
5119 *
5120 * Returns 0 on success or error on failure
5121 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305122int q6asm_enc_cfg_blk_evrc(struct audio_client *ac, uint32_t frames_per_buf,
5123 uint16_t min_rate, uint16_t max_rate,
5124 uint16_t rate_modulation_cmd)
5125{
5126 struct asm_evrc_enc_cfg enc_cfg;
5127 int rc = 0;
5128
5129 pr_debug("%s: session[%d]frames[%d]min_rate[0x%4x]max_rate[0x%4x] rate_modulation_cmd[0x%4x]\n",
5130 __func__, ac->session,
5131 frames_per_buf, min_rate, max_rate, rate_modulation_cmd);
5132
5133 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
5134 atomic_set(&ac->cmd_state, -1);
5135 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
5136 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
5137 enc_cfg.encdec.param_size = sizeof(struct asm_evrc_enc_cfg) -
5138 sizeof(struct asm_stream_cmd_set_encdec_param);
5139 enc_cfg.encblk.frames_per_buf = frames_per_buf;
5140 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
5141 sizeof(struct asm_enc_cfg_blk_param_v2);
5142
5143 enc_cfg.min_rate = min_rate;
5144 enc_cfg.max_rate = max_rate;
5145 enc_cfg.rate_mod_cmd = rate_modulation_cmd;
5146 enc_cfg.reserved = 0;
5147
5148 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
5149 if (rc < 0) {
5150 pr_err("%s: Comamnd %d failed %d\n",
5151 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
5152 rc = -EINVAL;
5153 goto fail_cmd;
5154 }
5155 rc = wait_event_timeout(ac->cmd_wait,
5156 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5157 if (!rc) {
5158 pr_err("%s: timeout. waited for encdec evrc\n", __func__);
5159 rc = -ETIMEDOUT;
5160 goto fail_cmd;
5161 }
5162 if (atomic_read(&ac->cmd_state) > 0) {
5163 pr_err("%s: DSP returned error[%s]\n",
5164 __func__, adsp_err_get_err_str(
5165 atomic_read(&ac->cmd_state)));
5166 rc = adsp_err_get_lnx_err_code(
5167 atomic_read(&ac->cmd_state));
5168 goto fail_cmd;
5169 }
5170 return 0;
5171fail_cmd:
5172 return rc;
5173}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305174EXPORT_SYMBOL(q6asm_enc_cfg_blk_evrc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305175
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305176/**
5177 * q6asm_enc_cfg_blk_amrnb -
5178 * command to set encode config block for AMRNB
5179 *
5180 * @ac: Audio client handle
5181 * @frames_per_buf: Number of frames per buffer
5182 * @band_mode: Band mode used
5183 * @dtx_enable: DTX en flag
5184 *
5185 * Returns 0 on success or error on failure
5186 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305187int q6asm_enc_cfg_blk_amrnb(struct audio_client *ac, uint32_t frames_per_buf,
5188 uint16_t band_mode, uint16_t dtx_enable)
5189{
5190 struct asm_amrnb_enc_cfg enc_cfg;
5191 int rc = 0;
5192
5193 pr_debug("%s: session[%d]frames[%d]band_mode[0x%4x]dtx_enable[0x%4x]\n",
5194 __func__, ac->session, frames_per_buf, band_mode, dtx_enable);
5195
5196 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
5197 atomic_set(&ac->cmd_state, -1);
5198 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
5199 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
5200 enc_cfg.encdec.param_size = sizeof(struct asm_amrnb_enc_cfg) -
5201 sizeof(struct asm_stream_cmd_set_encdec_param);
5202 enc_cfg.encblk.frames_per_buf = frames_per_buf;
5203 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
5204 sizeof(struct asm_enc_cfg_blk_param_v2);
5205
5206 enc_cfg.enc_mode = band_mode;
5207 enc_cfg.dtx_mode = dtx_enable;
5208
5209 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
5210 if (rc < 0) {
5211 pr_err("%s: Comamnd %d failed %d\n",
5212 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
5213 rc = -EINVAL;
5214 goto fail_cmd;
5215 }
5216 rc = wait_event_timeout(ac->cmd_wait,
5217 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5218 if (!rc) {
5219 pr_err("%s: timeout. waited for set encdec amrnb\n", __func__);
5220 rc = -ETIMEDOUT;
5221 goto fail_cmd;
5222 }
5223 if (atomic_read(&ac->cmd_state) > 0) {
5224 pr_err("%s: DSP returned error[%s]\n",
5225 __func__, adsp_err_get_err_str(
5226 atomic_read(&ac->cmd_state)));
5227 rc = adsp_err_get_lnx_err_code(
5228 atomic_read(&ac->cmd_state));
5229 goto fail_cmd;
5230 }
5231 return 0;
5232fail_cmd:
5233 return rc;
5234}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305235EXPORT_SYMBOL(q6asm_enc_cfg_blk_amrnb);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305236
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305237/**
5238 * q6asm_enc_cfg_blk_amrwb -
5239 * command to set encode config block for AMRWB
5240 *
5241 * @ac: Audio client handle
5242 * @frames_per_buf: Number of frames per buffer
5243 * @band_mode: Band mode used
5244 * @dtx_enable: DTX en flag
5245 *
5246 * Returns 0 on success or error on failure
5247 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305248int q6asm_enc_cfg_blk_amrwb(struct audio_client *ac, uint32_t frames_per_buf,
5249 uint16_t band_mode, uint16_t dtx_enable)
5250{
5251 struct asm_amrwb_enc_cfg enc_cfg;
5252 int rc = 0;
5253
5254 pr_debug("%s: session[%d]frames[%d]band_mode[0x%4x]dtx_enable[0x%4x]\n",
5255 __func__, ac->session, frames_per_buf, band_mode, dtx_enable);
5256
5257 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
5258 atomic_set(&ac->cmd_state, -1);
5259 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
5260 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
5261 enc_cfg.encdec.param_size = sizeof(struct asm_amrwb_enc_cfg) -
5262 sizeof(struct asm_stream_cmd_set_encdec_param);
5263 enc_cfg.encblk.frames_per_buf = frames_per_buf;
5264 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
5265 sizeof(struct asm_enc_cfg_blk_param_v2);
5266
5267 enc_cfg.enc_mode = band_mode;
5268 enc_cfg.dtx_mode = dtx_enable;
5269
5270 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
5271 if (rc < 0) {
5272 pr_err("%s: Comamnd %d failed %d\n",
5273 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
5274 rc = -EINVAL;
5275 goto fail_cmd;
5276 }
5277 rc = wait_event_timeout(ac->cmd_wait,
5278 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5279 if (!rc) {
5280 pr_err("%s: timeout. waited for FORMAT_UPDATE\n", __func__);
5281 rc = -ETIMEDOUT;
5282 goto fail_cmd;
5283 }
5284 if (atomic_read(&ac->cmd_state) > 0) {
5285 pr_err("%s: DSP returned error[%s]\n",
5286 __func__, adsp_err_get_err_str(
5287 atomic_read(&ac->cmd_state)));
5288 rc = adsp_err_get_lnx_err_code(
5289 atomic_read(&ac->cmd_state));
5290 goto fail_cmd;
5291 }
5292 return 0;
5293fail_cmd:
5294 return rc;
5295}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305296EXPORT_SYMBOL(q6asm_enc_cfg_blk_amrwb);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305297
5298
5299static int __q6asm_media_format_block_pcm(struct audio_client *ac,
5300 uint32_t rate, uint32_t channels,
5301 uint16_t bits_per_sample, int stream_id,
5302 bool use_default_chmap, char *channel_map)
5303{
5304 struct asm_multi_channel_pcm_fmt_blk_v2 fmt;
5305 u8 *channel_mapping;
5306 int rc = 0;
5307
5308 pr_debug("%s: session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
5309 channels);
5310
5311 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
5312 atomic_set(&ac->cmd_state, -1);
5313 /*
5314 * Updated the token field with stream/session for compressed playback
5315 * Platform driver must know the the stream with which the command is
5316 * associated
5317 */
5318 if (ac->io_mode & COMPRESSED_STREAM_IO)
5319 q6asm_update_token(&fmt.hdr.token,
5320 ac->session,
5321 stream_id,
5322 0, /* Buffer index is NA */
5323 0, /* Direction flag is NA */
5324 WAIT_CMD);
5325
5326 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
5327 __func__, fmt.hdr.token, stream_id, ac->session);
5328
5329 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5330 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5331 sizeof(fmt.fmt_blk);
5332 fmt.num_channels = channels;
5333 fmt.bits_per_sample = bits_per_sample;
5334 fmt.sample_rate = rate;
5335 fmt.is_signed = 1;
5336
5337 channel_mapping = fmt.channel_mapping;
5338
5339 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5340
5341 if (use_default_chmap) {
5342 if (q6asm_map_channels(channel_mapping, channels, false)) {
5343 pr_err("%s: map channels failed %d\n",
5344 __func__, channels);
5345 return -EINVAL;
5346 }
5347 } else {
5348 memcpy(channel_mapping, channel_map,
5349 PCM_FORMAT_MAX_NUM_CHANNEL);
5350 }
5351
5352 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
5353 if (rc < 0) {
5354 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
5355 rc = -EINVAL;
5356 goto fail_cmd;
5357 }
5358 rc = wait_event_timeout(ac->cmd_wait,
5359 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5360 if (!rc) {
5361 pr_err("%s: timeout. waited for format update\n", __func__);
5362 rc = -ETIMEDOUT;
5363 goto fail_cmd;
5364 }
5365 if (atomic_read(&ac->cmd_state) > 0) {
5366 pr_err("%s: DSP returned error[%s]\n",
5367 __func__, adsp_err_get_err_str(
5368 atomic_read(&ac->cmd_state)));
5369 rc = adsp_err_get_lnx_err_code(
5370 atomic_read(&ac->cmd_state));
5371 goto fail_cmd;
5372 }
5373 return 0;
5374fail_cmd:
5375 return rc;
5376}
5377
5378static int __q6asm_media_format_block_pcm_v3(struct audio_client *ac,
5379 uint32_t rate, uint32_t channels,
5380 uint16_t bits_per_sample,
5381 int stream_id,
5382 bool use_default_chmap,
5383 char *channel_map,
5384 uint16_t sample_word_size)
5385{
5386 struct asm_multi_channel_pcm_fmt_blk_param_v3 fmt;
5387 u8 *channel_mapping;
5388 int rc;
5389
5390 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
5391 ac->session, rate, channels,
5392 bits_per_sample, sample_word_size);
5393
5394 memset(&fmt, 0, sizeof(fmt));
5395 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
5396 atomic_set(&ac->cmd_state, -1);
5397 /*
5398 * Updated the token field with stream/session for compressed playback
5399 * Platform driver must know the the stream with which the command is
5400 * associated
5401 */
5402 if (ac->io_mode & COMPRESSED_STREAM_IO)
5403 fmt.hdr.token = ((ac->session << 8) & 0xFFFF00) |
5404 (stream_id & 0xFF);
5405
5406 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
5407 __func__, fmt.hdr.token, stream_id, ac->session);
5408
5409 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5410 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5411 sizeof(fmt.fmt_blk);
5412 fmt.param.num_channels = channels;
5413 fmt.param.bits_per_sample = bits_per_sample;
5414 fmt.param.sample_rate = rate;
5415 fmt.param.is_signed = 1;
5416 fmt.param.sample_word_size = sample_word_size;
5417 channel_mapping = fmt.param.channel_mapping;
5418
5419 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5420
5421 if (use_default_chmap) {
5422 if (q6asm_map_channels(channel_mapping, channels, false)) {
5423 pr_err("%s: map channels failed %d\n",
5424 __func__, channels);
5425 rc = -EINVAL;
5426 goto fail_cmd;
5427 }
5428 } else {
5429 memcpy(channel_mapping, channel_map,
5430 PCM_FORMAT_MAX_NUM_CHANNEL);
5431 }
5432
5433 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
5434 if (rc < 0) {
5435 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
5436 rc = -EINVAL;
5437 goto fail_cmd;
5438 }
5439 rc = wait_event_timeout(ac->cmd_wait,
5440 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5441 if (!rc) {
5442 pr_err("%s: timeout. waited for format update\n", __func__);
5443 rc = -ETIMEDOUT;
5444 goto fail_cmd;
5445 }
5446 if (atomic_read(&ac->cmd_state) > 0) {
5447 pr_err("%s: DSP returned error[%s]\n",
5448 __func__, adsp_err_get_err_str(
5449 atomic_read(&ac->cmd_state)));
5450 rc = adsp_err_get_lnx_err_code(
5451 atomic_read(&ac->cmd_state));
5452 goto fail_cmd;
5453 }
5454 return 0;
5455fail_cmd:
5456 return rc;
5457}
5458
5459static int __q6asm_media_format_block_pcm_v4(struct audio_client *ac,
5460 uint32_t rate, uint32_t channels,
5461 uint16_t bits_per_sample,
5462 int stream_id,
5463 bool use_default_chmap,
5464 char *channel_map,
5465 uint16_t sample_word_size,
5466 uint16_t endianness,
5467 uint16_t mode)
5468{
5469 struct asm_multi_channel_pcm_fmt_blk_param_v4 fmt;
5470 u8 *channel_mapping;
5471 int rc;
5472
5473 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
5474 ac->session, rate, channels,
5475 bits_per_sample, sample_word_size);
5476
5477 memset(&fmt, 0, sizeof(fmt));
5478 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
5479 atomic_set(&ac->cmd_state, -1);
5480 /*
5481 * Updated the token field with stream/session for compressed playback
5482 * Platform driver must know the the stream with which the command is
5483 * associated
5484 */
5485 if (ac->io_mode & COMPRESSED_STREAM_IO)
5486 fmt.hdr.token = ((ac->session << 8) & 0xFFFF00) |
5487 (stream_id & 0xFF);
5488
5489 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
5490 __func__, fmt.hdr.token, stream_id, ac->session);
5491
5492 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5493 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5494 sizeof(fmt.fmt_blk);
5495 fmt.param.num_channels = channels;
5496 fmt.param.bits_per_sample = bits_per_sample;
5497 fmt.param.sample_rate = rate;
5498 fmt.param.is_signed = 1;
5499 fmt.param.sample_word_size = sample_word_size;
5500 fmt.param.endianness = endianness;
5501 fmt.param.mode = mode;
5502 channel_mapping = fmt.param.channel_mapping;
5503
5504 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5505
5506 if (use_default_chmap) {
5507 if (q6asm_map_channels(channel_mapping, channels, false)) {
5508 pr_err("%s: map channels failed %d\n",
5509 __func__, channels);
5510 rc = -EINVAL;
5511 goto fail_cmd;
5512 }
5513 } else {
5514 memcpy(channel_mapping, channel_map,
5515 PCM_FORMAT_MAX_NUM_CHANNEL);
5516 }
5517
5518 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
5519 if (rc < 0) {
5520 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
5521 rc = -EINVAL;
5522 goto fail_cmd;
5523 }
5524 rc = wait_event_timeout(ac->cmd_wait,
5525 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5526 if (!rc) {
5527 pr_err("%s: timeout. waited for format update\n", __func__);
5528 rc = -ETIMEDOUT;
5529 goto fail_cmd;
5530 }
5531 if (atomic_read(&ac->cmd_state) > 0) {
5532 pr_err("%s: DSP returned error[%s]\n",
5533 __func__, adsp_err_get_err_str(
5534 atomic_read(&ac->cmd_state)));
5535 rc = adsp_err_get_lnx_err_code(
5536 atomic_read(&ac->cmd_state));
5537 goto fail_cmd;
5538 }
5539 return 0;
5540fail_cmd:
5541 return rc;
5542}
5543
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305544/**
5545 * q6asm_media_format_block_pcm -
5546 * command to set mediafmt block for PCM on ASM stream
5547 *
5548 * @ac: Audio client handle
5549 * @rate: sample rate
5550 * @channels: number of ASM channels
5551 *
5552 * Returns 0 on success or error on failure
5553 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305554int q6asm_media_format_block_pcm(struct audio_client *ac,
5555 uint32_t rate, uint32_t channels)
5556{
5557 return __q6asm_media_format_block_pcm(ac, rate,
5558 channels, 16, ac->stream_id,
5559 true, NULL);
5560}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305561EXPORT_SYMBOL(q6asm_media_format_block_pcm);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305562
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305563/**
5564 * q6asm_media_format_block_pcm_format_support -
5565 * command to set mediafmt block for PCM format support
5566 *
5567 * @ac: Audio client handle
5568 * @rate: sample rate
5569 * @channels: number of ASM channels
5570 * @bits_per_sample: number of bits per sample
5571 *
5572 * Returns 0 on success or error on failure
5573 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305574int q6asm_media_format_block_pcm_format_support(struct audio_client *ac,
5575 uint32_t rate, uint32_t channels,
5576 uint16_t bits_per_sample)
5577{
5578 return __q6asm_media_format_block_pcm(ac, rate,
5579 channels, bits_per_sample, ac->stream_id,
5580 true, NULL);
5581}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305582EXPORT_SYMBOL(q6asm_media_format_block_pcm_format_support);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305583
5584int q6asm_media_format_block_pcm_format_support_v2(struct audio_client *ac,
5585 uint32_t rate, uint32_t channels,
5586 uint16_t bits_per_sample, int stream_id,
5587 bool use_default_chmap, char *channel_map)
5588{
5589 if (!use_default_chmap && (channel_map == NULL)) {
5590 pr_err("%s: No valid chan map and can't use default\n",
5591 __func__);
5592 return -EINVAL;
5593 }
5594 return __q6asm_media_format_block_pcm(ac, rate,
5595 channels, bits_per_sample, stream_id,
5596 use_default_chmap, channel_map);
5597}
5598
5599/*
5600 * q6asm_media_format_block_pcm_format_support_v3- sends pcm decoder
5601 * configuration parameters
5602 *
5603 * @ac: Client session handle
5604 * @rate: sample rate
5605 * @channels: number of channels
5606 * @bits_per_sample: bit width of encoder session
5607 * @stream_id: stream id of stream to be associated with this session
5608 * @use_default_chmap: true if default channel map to be used
5609 * @channel_map: input channel map
5610 * @sample_word_size: Size in bits of the word that holds a sample of a channel
5611 */
5612int q6asm_media_format_block_pcm_format_support_v3(struct audio_client *ac,
5613 uint32_t rate,
5614 uint32_t channels,
5615 uint16_t bits_per_sample,
5616 int stream_id,
5617 bool use_default_chmap,
5618 char *channel_map,
5619 uint16_t sample_word_size)
5620{
5621 if (!use_default_chmap && (channel_map == NULL)) {
5622 pr_err("%s: No valid chan map and can't use default\n",
5623 __func__);
5624 return -EINVAL;
5625 }
5626 return __q6asm_media_format_block_pcm_v3(ac, rate,
5627 channels, bits_per_sample, stream_id,
5628 use_default_chmap, channel_map,
5629 sample_word_size);
5630
5631}
5632EXPORT_SYMBOL(q6asm_media_format_block_pcm_format_support_v3);
5633
5634/*
5635 * q6asm_media_format_block_pcm_format_support_v4- sends pcm decoder
5636 * configuration parameters
5637 *
5638 * @ac: Client session handle
5639 * @rate: sample rate
5640 * @channels: number of channels
5641 * @bits_per_sample: bit width of encoder session
5642 * @stream_id: stream id of stream to be associated with this session
5643 * @use_default_chmap: true if default channel map to be used
5644 * @channel_map: input channel map
5645 * @sample_word_size: Size in bits of the word that holds a sample of a channel
5646 * @endianness: endianness of the pcm data
5647 * @mode: Mode to provide additional info about the pcm input data
5648 */
5649int q6asm_media_format_block_pcm_format_support_v4(struct audio_client *ac,
5650 uint32_t rate,
5651 uint32_t channels,
5652 uint16_t bits_per_sample,
5653 int stream_id,
5654 bool use_default_chmap,
5655 char *channel_map,
5656 uint16_t sample_word_size,
5657 uint16_t endianness,
5658 uint16_t mode)
5659{
5660 if (!use_default_chmap && (channel_map == NULL)) {
5661 pr_err("%s: No valid chan map and can't use default\n",
5662 __func__);
5663 return -EINVAL;
5664 }
5665 return __q6asm_media_format_block_pcm_v4(ac, rate,
5666 channels, bits_per_sample, stream_id,
5667 use_default_chmap, channel_map,
5668 sample_word_size, endianness,
5669 mode);
5670
5671}
5672EXPORT_SYMBOL(q6asm_media_format_block_pcm_format_support_v4);
5673
5674
5675static int __q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
5676 uint32_t rate, uint32_t channels,
5677 bool use_default_chmap, char *channel_map,
5678 uint16_t bits_per_sample)
5679{
5680 struct asm_multi_channel_pcm_fmt_blk_v2 fmt;
5681 u8 *channel_mapping;
5682 int rc = 0;
5683
5684 pr_debug("%s: session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
5685 channels);
5686
5687 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
5688 atomic_set(&ac->cmd_state, -1);
5689
5690 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5691 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5692 sizeof(fmt.fmt_blk);
5693 fmt.num_channels = channels;
5694 fmt.bits_per_sample = bits_per_sample;
5695 fmt.sample_rate = rate;
5696 fmt.is_signed = 1;
5697
5698 channel_mapping = fmt.channel_mapping;
5699
5700 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5701
5702 if (use_default_chmap) {
5703 if (q6asm_map_channels(channel_mapping, channels, false)) {
5704 pr_err("%s: map channels failed %d\n",
5705 __func__, channels);
5706 return -EINVAL;
5707 }
5708 } else {
5709 memcpy(channel_mapping, channel_map,
5710 PCM_FORMAT_MAX_NUM_CHANNEL);
5711 }
5712
5713 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
5714 if (rc < 0) {
5715 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
5716 rc = -EINVAL;
5717 goto fail_cmd;
5718 }
5719 rc = wait_event_timeout(ac->cmd_wait,
5720 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5721 if (!rc) {
5722 pr_err("%s: timeout. waited for format update\n", __func__);
5723 rc = -ETIMEDOUT;
5724 goto fail_cmd;
5725 }
5726 if (atomic_read(&ac->cmd_state) > 0) {
5727 pr_err("%s: DSP returned error[%s]\n",
5728 __func__, adsp_err_get_err_str(
5729 atomic_read(&ac->cmd_state)));
5730 rc = adsp_err_get_lnx_err_code(
5731 atomic_read(&ac->cmd_state));
5732 goto fail_cmd;
5733 }
5734 return 0;
5735fail_cmd:
5736 return rc;
5737}
5738
5739static int __q6asm_media_format_block_multi_ch_pcm_v3(struct audio_client *ac,
5740 uint32_t rate,
5741 uint32_t channels,
5742 bool use_default_chmap,
5743 char *channel_map,
5744 uint16_t bits_per_sample,
5745 uint16_t sample_word_size)
5746{
5747 struct asm_multi_channel_pcm_fmt_blk_param_v3 fmt;
5748 u8 *channel_mapping;
5749 int rc;
5750
5751 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
5752 ac->session, rate, channels,
5753 bits_per_sample, sample_word_size);
5754
5755 memset(&fmt, 0, sizeof(fmt));
5756 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
5757 atomic_set(&ac->cmd_state, -1);
5758
5759 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5760 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5761 sizeof(fmt.fmt_blk);
5762 fmt.param.num_channels = channels;
5763 fmt.param.bits_per_sample = bits_per_sample;
5764 fmt.param.sample_rate = rate;
5765 fmt.param.is_signed = 1;
5766 fmt.param.sample_word_size = sample_word_size;
5767 channel_mapping = fmt.param.channel_mapping;
5768
5769 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5770
5771 if (use_default_chmap) {
5772 if (q6asm_map_channels(channel_mapping, channels, false)) {
5773 pr_err("%s: map channels failed %d\n",
5774 __func__, channels);
5775 rc = -EINVAL;
5776 goto fail_cmd;
5777 }
5778 } else {
5779 memcpy(channel_mapping, channel_map,
5780 PCM_FORMAT_MAX_NUM_CHANNEL);
5781 }
5782
5783 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
5784 if (rc < 0) {
5785 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
5786 goto fail_cmd;
5787 }
5788 rc = wait_event_timeout(ac->cmd_wait,
5789 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5790 if (!rc) {
5791 pr_err("%s: timeout. waited for format update\n", __func__);
5792 rc = -ETIMEDOUT;
5793 goto fail_cmd;
5794 }
5795 if (atomic_read(&ac->cmd_state) > 0) {
5796 pr_err("%s: DSP returned error[%s]\n",
5797 __func__, adsp_err_get_err_str(
5798 atomic_read(&ac->cmd_state)));
5799 rc = adsp_err_get_lnx_err_code(
5800 atomic_read(&ac->cmd_state));
5801 goto fail_cmd;
5802 }
5803 return 0;
5804fail_cmd:
5805 return rc;
5806}
5807
5808static int __q6asm_media_format_block_multi_ch_pcm_v4(struct audio_client *ac,
5809 uint32_t rate,
5810 uint32_t channels,
5811 bool use_default_chmap,
5812 char *channel_map,
5813 uint16_t bits_per_sample,
5814 uint16_t sample_word_size,
5815 uint16_t endianness,
5816 uint16_t mode)
5817{
5818 struct asm_multi_channel_pcm_fmt_blk_param_v4 fmt;
5819 u8 *channel_mapping;
5820 int rc;
5821
5822 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
5823 ac->session, rate, channels,
5824 bits_per_sample, sample_word_size);
5825
5826 memset(&fmt, 0, sizeof(fmt));
5827 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
5828 atomic_set(&ac->cmd_state, -1);
5829
5830 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5831 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5832 sizeof(fmt.fmt_blk);
5833 fmt.param.num_channels = channels;
5834 fmt.param.bits_per_sample = bits_per_sample;
5835 fmt.param.sample_rate = rate;
5836 fmt.param.is_signed = 1;
5837 fmt.param.sample_word_size = sample_word_size;
5838 fmt.param.endianness = endianness;
5839 fmt.param.mode = mode;
5840 channel_mapping = fmt.param.channel_mapping;
5841
5842 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5843
5844 if (use_default_chmap) {
5845 if (q6asm_map_channels(channel_mapping, channels, false)) {
5846 pr_err("%s: map channels failed %d\n",
5847 __func__, channels);
5848 rc = -EINVAL;
5849 goto fail_cmd;
5850 }
5851 } else {
5852 memcpy(channel_mapping, channel_map,
5853 PCM_FORMAT_MAX_NUM_CHANNEL);
5854 }
5855
5856 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
5857 if (rc < 0) {
5858 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
5859 goto fail_cmd;
5860 }
5861 rc = wait_event_timeout(ac->cmd_wait,
5862 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5863 if (!rc) {
5864 pr_err("%s: timeout. waited for format update\n", __func__);
5865 rc = -ETIMEDOUT;
5866 goto fail_cmd;
5867 }
5868 if (atomic_read(&ac->cmd_state) > 0) {
5869 pr_err("%s: DSP returned error[%s]\n",
5870 __func__, adsp_err_get_err_str(
5871 atomic_read(&ac->cmd_state)));
5872 rc = adsp_err_get_lnx_err_code(
5873 atomic_read(&ac->cmd_state));
5874 goto fail_cmd;
5875 }
5876 return 0;
5877fail_cmd:
5878 return rc;
5879}
5880
5881int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
5882 uint32_t rate, uint32_t channels,
5883 bool use_default_chmap, char *channel_map)
5884{
5885 return __q6asm_media_format_block_multi_ch_pcm(ac, rate,
5886 channels, use_default_chmap, channel_map, 16);
5887}
5888
5889int q6asm_media_format_block_multi_ch_pcm_v2(
5890 struct audio_client *ac,
5891 uint32_t rate, uint32_t channels,
5892 bool use_default_chmap, char *channel_map,
5893 uint16_t bits_per_sample)
5894{
5895 return __q6asm_media_format_block_multi_ch_pcm(ac, rate,
5896 channels, use_default_chmap, channel_map,
5897 bits_per_sample);
5898}
5899
5900/*
5901 * q6asm_media_format_block_multi_ch_pcm_v3 - sends pcm decoder configuration
5902 * parameters
5903 *
5904 * @ac: Client session handle
5905 * @rate: sample rate
5906 * @channels: number of channels
5907 * @bits_per_sample: bit width of encoder session
5908 * @use_default_chmap: true if default channel map to be used
5909 * @channel_map: input channel map
5910 * @sample_word_size: Size in bits of the word that holds a sample of a channel
5911 */
5912int q6asm_media_format_block_multi_ch_pcm_v3(struct audio_client *ac,
5913 uint32_t rate, uint32_t channels,
5914 bool use_default_chmap,
5915 char *channel_map,
5916 uint16_t bits_per_sample,
5917 uint16_t sample_word_size)
5918{
5919 return __q6asm_media_format_block_multi_ch_pcm_v3(ac, rate, channels,
5920 use_default_chmap,
5921 channel_map,
5922 bits_per_sample,
5923 sample_word_size);
5924}
5925EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v3);
5926
5927/*
5928 * q6asm_media_format_block_multi_ch_pcm_v4 - sends pcm decoder configuration
5929 * parameters
5930 *
5931 * @ac: Client session handle
5932 * @rate: sample rate
5933 * @channels: number of channels
5934 * @bits_per_sample: bit width of encoder session
5935 * @use_default_chmap: true if default channel map to be used
5936 * @channel_map: input channel map
5937 * @sample_word_size: Size in bits of the word that holds a sample of a channel
5938 * @endianness: endianness of the pcm data
5939 * @mode: Mode to provide additional info about the pcm input data
5940 */
5941int q6asm_media_format_block_multi_ch_pcm_v4(struct audio_client *ac,
5942 uint32_t rate, uint32_t channels,
5943 bool use_default_chmap,
5944 char *channel_map,
5945 uint16_t bits_per_sample,
5946 uint16_t sample_word_size,
5947 uint16_t endianness,
5948 uint16_t mode)
5949{
5950 return __q6asm_media_format_block_multi_ch_pcm_v4(ac, rate, channels,
5951 use_default_chmap,
5952 channel_map,
5953 bits_per_sample,
5954 sample_word_size,
5955 endianness,
5956 mode);
5957}
5958EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v4);
5959
5960/*
5961 * q6asm_media_format_block_gen_compr - set up generic compress format params
5962 *
5963 * @ac: Client session handle
5964 * @rate: sample rate
5965 * @channels: number of channels
5966 * @use_default_chmap: true if default channel map to be used
5967 * @channel_map: input channel map
5968 * @bits_per_sample: bit width of gen compress stream
5969 */
5970int q6asm_media_format_block_gen_compr(struct audio_client *ac,
5971 uint32_t rate, uint32_t channels,
5972 bool use_default_chmap, char *channel_map,
5973 uint16_t bits_per_sample)
5974{
5975 struct asm_generic_compressed_fmt_blk_t fmt;
5976 u8 *channel_mapping;
5977 int rc = 0;
5978
5979 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]\n",
5980 __func__, ac->session, rate,
5981 channels, bits_per_sample);
5982
5983 memset(&fmt, 0, sizeof(fmt));
5984 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
5985
5986 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5987 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5988 sizeof(fmt.fmt_blk);
5989 fmt.num_channels = channels;
5990 fmt.bits_per_sample = bits_per_sample;
5991 fmt.sampling_rate = rate;
5992
5993 channel_mapping = fmt.channel_mapping;
5994
5995 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5996
5997 if (use_default_chmap) {
5998 if (q6asm_map_channels(channel_mapping, channels, false)) {
5999 pr_err("%s: map channels failed %d\n",
6000 __func__, channels);
6001 return -EINVAL;
6002 }
6003 } else {
6004 memcpy(channel_mapping, channel_map,
6005 PCM_FORMAT_MAX_NUM_CHANNEL);
6006 }
6007
6008 atomic_set(&ac->cmd_state, -1);
6009 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6010 if (rc < 0) {
6011 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
6012 rc = -EINVAL;
6013 goto fail_cmd;
6014 }
6015 rc = wait_event_timeout(ac->cmd_wait,
6016 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6017 if (!rc) {
6018 pr_err("%s: timeout. waited for format update\n", __func__);
6019 rc = -ETIMEDOUT;
6020 goto fail_cmd;
6021 }
6022
6023 if (atomic_read(&ac->cmd_state) > 0) {
6024 pr_err("%s: DSP returned error[%s]\n",
6025 __func__, adsp_err_get_err_str(
6026 atomic_read(&ac->cmd_state)));
6027 rc = adsp_err_get_lnx_err_code(
6028 atomic_read(&ac->cmd_state));
6029 }
6030 return 0;
6031fail_cmd:
6032 return rc;
6033}
6034EXPORT_SYMBOL(q6asm_media_format_block_gen_compr);
6035
6036
6037/*
6038 * q6asm_media_format_block_iec - set up IEC61937 (compressed) or IEC60958
6039 * (pcm) format params. Both audio standards
6040 * use the same format and are used for
6041 * HDMI or SPDIF.
6042 *
6043 * @ac: Client session handle
6044 * @rate: sample rate
6045 * @channels: number of channels
6046 */
6047int q6asm_media_format_block_iec(struct audio_client *ac,
6048 uint32_t rate, uint32_t channels)
6049{
6050 struct asm_iec_compressed_fmt_blk_t fmt;
6051 int rc = 0;
6052
6053 pr_debug("%s: session[%d]rate[%d]ch[%d]\n",
6054 __func__, ac->session, rate,
6055 channels);
6056
6057 memset(&fmt, 0, sizeof(fmt));
6058 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
6059
6060 fmt.hdr.opcode = ASM_DATA_CMD_IEC_60958_MEDIA_FMT;
6061 fmt.num_channels = channels;
6062 fmt.sampling_rate = rate;
6063
6064 atomic_set(&ac->cmd_state, -1);
6065 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6066 if (rc < 0) {
6067 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
6068 rc = -EINVAL;
6069 goto fail_cmd;
6070 }
6071 rc = wait_event_timeout(ac->cmd_wait,
6072 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6073 if (!rc) {
6074 pr_err("%s: timeout. waited for format update\n", __func__);
6075 rc = -ETIMEDOUT;
6076 goto fail_cmd;
6077 }
6078
6079 if (atomic_read(&ac->cmd_state) > 0) {
6080 pr_err("%s: DSP returned error[%s]\n",
6081 __func__, adsp_err_get_err_str(
6082 atomic_read(&ac->cmd_state)));
6083 rc = adsp_err_get_lnx_err_code(
6084 atomic_read(&ac->cmd_state));
6085 }
6086 return 0;
6087fail_cmd:
6088 return rc;
6089}
6090EXPORT_SYMBOL(q6asm_media_format_block_iec);
6091
6092static int __q6asm_media_format_block_multi_aac(struct audio_client *ac,
6093 struct asm_aac_cfg *cfg, int stream_id)
6094{
6095 struct asm_aac_fmt_blk_v2 fmt;
6096 int rc = 0;
6097
6098 pr_debug("%s: session[%d]rate[%d]ch[%d]\n", __func__, ac->session,
6099 cfg->sample_rate, cfg->ch_cfg);
6100
6101 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6102 atomic_set(&ac->cmd_state, -1);
6103 /*
6104 * Updated the token field with stream/session for compressed playback
6105 * Platform driver must know the the stream with which the command is
6106 * associated
6107 */
6108 if (ac->io_mode & COMPRESSED_STREAM_IO)
6109 q6asm_update_token(&fmt.hdr.token,
6110 ac->session,
6111 stream_id,
6112 0, /* Buffer index is NA */
6113 0, /* Direction flag is NA */
6114 WAIT_CMD);
6115
6116 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
6117 __func__, fmt.hdr.token, stream_id, ac->session);
6118 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6119 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6120 sizeof(fmt.fmt_blk);
6121 fmt.aac_fmt_flag = cfg->format;
6122 fmt.audio_objype = cfg->aot;
6123 /* If zero, PCE is assumed to be available in bitstream*/
6124 fmt.total_size_of_PCE_bits = 0;
6125 fmt.channel_config = cfg->ch_cfg;
6126 fmt.sample_rate = cfg->sample_rate;
6127
6128 pr_debug("%s: format=0x%x cfg_size=%d aac-cfg=0x%x aot=%d ch=%d sr=%d\n",
6129 __func__, fmt.aac_fmt_flag, fmt.fmt_blk.fmt_blk_size,
6130 fmt.aac_fmt_flag,
6131 fmt.audio_objype,
6132 fmt.channel_config,
6133 fmt.sample_rate);
6134 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6135 if (rc < 0) {
6136 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
6137 rc = -EINVAL;
6138 goto fail_cmd;
6139 }
6140 rc = wait_event_timeout(ac->cmd_wait,
6141 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6142 if (!rc) {
6143 pr_err("%s: timeout. waited for FORMAT_UPDATE\n", __func__);
6144 rc = -ETIMEDOUT;
6145 goto fail_cmd;
6146 }
6147 if (atomic_read(&ac->cmd_state) > 0) {
6148 pr_err("%s: DSP returned error[%s]\n",
6149 __func__, adsp_err_get_err_str(
6150 atomic_read(&ac->cmd_state)));
6151 rc = adsp_err_get_lnx_err_code(
6152 atomic_read(&ac->cmd_state));
6153 goto fail_cmd;
6154 }
6155 return 0;
6156fail_cmd:
6157 return rc;
6158}
6159
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306160/**
6161 * q6asm_media_format_block_multi_aac -
6162 * command to set mediafmt block for multi_aac on ASM stream
6163 *
6164 * @ac: Audio client handle
6165 * @cfg: multi_aac config
6166 *
6167 * Returns 0 on success or error on failure
6168 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306169int q6asm_media_format_block_multi_aac(struct audio_client *ac,
6170 struct asm_aac_cfg *cfg)
6171{
6172 return __q6asm_media_format_block_multi_aac(ac, cfg, ac->stream_id);
6173}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306174EXPORT_SYMBOL(q6asm_media_format_block_multi_aac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306175
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306176/**
6177 * q6asm_media_format_block_aac -
6178 * command to set mediafmt block for aac on ASM
6179 *
6180 * @ac: Audio client handle
6181 * @cfg: aac config
6182 *
6183 * Returns 0 on success or error on failure
6184 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306185int q6asm_media_format_block_aac(struct audio_client *ac,
6186 struct asm_aac_cfg *cfg)
6187{
6188 return __q6asm_media_format_block_multi_aac(ac, cfg, ac->stream_id);
6189}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306190EXPORT_SYMBOL(q6asm_media_format_block_aac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306191
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306192/**
6193 * q6asm_stream_media_format_block_aac -
6194 * command to set mediafmt block for aac on ASM stream
6195 *
6196 * @ac: Audio client handle
6197 * @cfg: aac config
6198 * @stream_id: stream ID info
6199 *
6200 * Returns 0 on success or error on failure
6201 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306202int q6asm_stream_media_format_block_aac(struct audio_client *ac,
6203 struct asm_aac_cfg *cfg, int stream_id)
6204{
6205 return __q6asm_media_format_block_multi_aac(ac, cfg, stream_id);
6206}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306207EXPORT_SYMBOL(q6asm_stream_media_format_block_aac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306208
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306209/**
6210 * q6asm_media_format_block_wma -
6211 * command to set mediafmt block for wma on ASM stream
6212 *
6213 * @ac: Audio client handle
6214 * @cfg: wma config
6215 * @stream_id: stream ID info
6216 *
6217 * Returns 0 on success or error on failure
6218 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306219int q6asm_media_format_block_wma(struct audio_client *ac,
6220 void *cfg, int stream_id)
6221{
6222 struct asm_wmastdv9_fmt_blk_v2 fmt;
6223 struct asm_wma_cfg *wma_cfg = (struct asm_wma_cfg *)cfg;
6224 int rc = 0;
6225
6226 pr_debug("session[%d]format_tag[0x%4x] rate[%d] ch[0x%4x] bps[%d], balign[0x%4x], bit_sample[0x%4x], ch_msk[%d], enc_opt[0x%4x]\n",
6227 ac->session, wma_cfg->format_tag, wma_cfg->sample_rate,
6228 wma_cfg->ch_cfg, wma_cfg->avg_bytes_per_sec,
6229 wma_cfg->block_align, wma_cfg->valid_bits_per_sample,
6230 wma_cfg->ch_mask, wma_cfg->encode_opt);
6231
6232 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6233 atomic_set(&ac->cmd_state, -1);
6234
6235 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6236 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6237 sizeof(fmt.fmtblk);
6238 fmt.fmtag = wma_cfg->format_tag;
6239 fmt.num_channels = wma_cfg->ch_cfg;
6240 fmt.sample_rate = wma_cfg->sample_rate;
6241 fmt.avg_bytes_per_sec = wma_cfg->avg_bytes_per_sec;
6242 fmt.blk_align = wma_cfg->block_align;
6243 fmt.bits_per_sample =
6244 wma_cfg->valid_bits_per_sample;
6245 fmt.channel_mask = wma_cfg->ch_mask;
6246 fmt.enc_options = wma_cfg->encode_opt;
6247
6248 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6249 if (rc < 0) {
6250 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
6251 rc = -EINVAL;
6252 goto fail_cmd;
6253 }
6254 rc = wait_event_timeout(ac->cmd_wait,
6255 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6256 if (!rc) {
6257 pr_err("%s: timeout. waited for FORMAT_UPDATE\n", __func__);
6258 rc = -ETIMEDOUT;
6259 goto fail_cmd;
6260 }
6261 if (atomic_read(&ac->cmd_state) > 0) {
6262 pr_err("%s: DSP returned error[%s]\n",
6263 __func__, adsp_err_get_err_str(
6264 atomic_read(&ac->cmd_state)));
6265 rc = adsp_err_get_lnx_err_code(
6266 atomic_read(&ac->cmd_state));
6267 goto fail_cmd;
6268 }
6269 return 0;
6270fail_cmd:
6271 return rc;
6272}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306273EXPORT_SYMBOL(q6asm_media_format_block_wma);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306274
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306275/**
6276 * q6asm_media_format_block_wmapro -
6277 * command to set mediafmt block for wmapro on ASM stream
6278 *
6279 * @ac: Audio client handle
6280 * @cfg: wmapro config
6281 * @stream_id: stream ID info
6282 *
6283 * Returns 0 on success or error on failure
6284 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306285int q6asm_media_format_block_wmapro(struct audio_client *ac,
6286 void *cfg, int stream_id)
6287{
6288 struct asm_wmaprov10_fmt_blk_v2 fmt;
6289 struct asm_wmapro_cfg *wmapro_cfg = (struct asm_wmapro_cfg *)cfg;
6290 int rc = 0;
6291
6292 pr_debug("%s: session[%d]format_tag[0x%4x] rate[%d] ch[0x%4x] bps[%d], balign[0x%4x], bit_sample[0x%4x], ch_msk[%d], enc_opt[0x%4x], adv_enc_opt[0x%4x], adv_enc_opt2[0x%8x]\n",
6293 __func__,
6294 ac->session, wmapro_cfg->format_tag, wmapro_cfg->sample_rate,
6295 wmapro_cfg->ch_cfg, wmapro_cfg->avg_bytes_per_sec,
6296 wmapro_cfg->block_align, wmapro_cfg->valid_bits_per_sample,
6297 wmapro_cfg->ch_mask, wmapro_cfg->encode_opt,
6298 wmapro_cfg->adv_encode_opt, wmapro_cfg->adv_encode_opt2);
6299
6300 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6301 atomic_set(&ac->cmd_state, -1);
6302
6303 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6304 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6305 sizeof(fmt.fmtblk);
6306
6307 fmt.fmtag = wmapro_cfg->format_tag;
6308 fmt.num_channels = wmapro_cfg->ch_cfg;
6309 fmt.sample_rate = wmapro_cfg->sample_rate;
6310 fmt.avg_bytes_per_sec =
6311 wmapro_cfg->avg_bytes_per_sec;
6312 fmt.blk_align = wmapro_cfg->block_align;
6313 fmt.bits_per_sample = wmapro_cfg->valid_bits_per_sample;
6314 fmt.channel_mask = wmapro_cfg->ch_mask;
6315 fmt.enc_options = wmapro_cfg->encode_opt;
6316 fmt.usAdvancedEncodeOpt = wmapro_cfg->adv_encode_opt;
6317 fmt.advanced_enc_options2 = wmapro_cfg->adv_encode_opt2;
6318
6319 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6320 if (rc < 0) {
6321 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
6322 rc = -EINVAL;
6323 goto fail_cmd;
6324 }
6325 rc = wait_event_timeout(ac->cmd_wait,
6326 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6327 if (!rc) {
6328 pr_err("%s: timeout. waited for FORMAT_UPDATE\n", __func__);
6329 rc = -ETIMEDOUT;
6330 goto fail_cmd;
6331 }
6332 if (atomic_read(&ac->cmd_state) > 0) {
6333 pr_err("%s: DSP returned error[%s]\n",
6334 __func__, adsp_err_get_err_str(
6335 atomic_read(&ac->cmd_state)));
6336 rc = adsp_err_get_lnx_err_code(
6337 atomic_read(&ac->cmd_state));
6338 goto fail_cmd;
6339 }
6340 return 0;
6341fail_cmd:
6342 return rc;
6343}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306344EXPORT_SYMBOL(q6asm_media_format_block_wmapro);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306345
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306346/**
6347 * q6asm_media_format_block_amrwbplus -
6348 * command to set mediafmt block for amrwbplus on ASM stream
6349 *
6350 * @ac: Audio client handle
6351 * @cfg: amrwbplus config
6352 * @stream_id: stream ID info
6353 *
6354 * Returns 0 on success or error on failure
6355 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306356int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
6357 struct asm_amrwbplus_cfg *cfg)
6358{
6359 struct asm_amrwbplus_fmt_blk_v2 fmt;
6360 int rc = 0;
6361
6362 pr_debug("%s: session[%d]band-mode[%d]frame-fmt[%d]ch[%d]\n",
6363 __func__,
6364 ac->session,
6365 cfg->amr_band_mode,
6366 cfg->amr_frame_fmt,
6367 cfg->num_channels);
6368
6369 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
6370 atomic_set(&ac->cmd_state, -1);
6371
6372 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6373 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6374 sizeof(fmt.fmtblk);
6375 fmt.amr_frame_fmt = cfg->amr_frame_fmt;
6376
6377 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6378 if (rc < 0) {
6379 pr_err("%s: Comamnd media format update failed.. %d\n",
6380 __func__, rc);
6381 rc = -EINVAL;
6382 goto fail_cmd;
6383 }
6384 rc = wait_event_timeout(ac->cmd_wait,
6385 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6386 if (!rc) {
6387 pr_err("%s: timeout. waited for FORMAT_UPDATE\n", __func__);
6388 rc = -ETIMEDOUT;
6389 goto fail_cmd;
6390 }
6391 if (atomic_read(&ac->cmd_state) > 0) {
6392 pr_err("%s: DSP returned error[%s]\n",
6393 __func__, adsp_err_get_err_str(
6394 atomic_read(&ac->cmd_state)));
6395 rc = adsp_err_get_lnx_err_code(
6396 atomic_read(&ac->cmd_state));
6397 goto fail_cmd;
6398 }
6399 return 0;
6400fail_cmd:
6401 return rc;
6402}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306403EXPORT_SYMBOL(q6asm_media_format_block_amrwbplus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306404
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306405/**
6406 * q6asm_stream_media_format_block_flac -
6407 * command to set mediafmt block for flac on ASM stream
6408 *
6409 * @ac: Audio client handle
6410 * @cfg: FLAC config
6411 * @stream_id: stream ID info
6412 *
6413 * Returns 0 on success or error on failure
6414 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306415int q6asm_stream_media_format_block_flac(struct audio_client *ac,
6416 struct asm_flac_cfg *cfg, int stream_id)
6417{
6418 struct asm_flac_fmt_blk_v2 fmt;
6419 int rc = 0;
6420
6421 pr_debug("%s :session[%d] rate[%d] ch[%d] size[%d] stream_id[%d]\n",
6422 __func__, ac->session, cfg->sample_rate, cfg->ch_cfg,
6423 cfg->sample_size, stream_id);
6424
6425 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6426 atomic_set(&ac->cmd_state, -1);
6427
6428 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6429 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6430 sizeof(fmt.fmtblk);
6431
6432 fmt.is_stream_info_present = cfg->stream_info_present;
6433 fmt.num_channels = cfg->ch_cfg;
6434 fmt.min_blk_size = cfg->min_blk_size;
6435 fmt.max_blk_size = cfg->max_blk_size;
6436 fmt.sample_rate = cfg->sample_rate;
6437 fmt.min_frame_size = cfg->min_frame_size;
6438 fmt.max_frame_size = cfg->max_frame_size;
6439 fmt.sample_size = cfg->sample_size;
6440
6441 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6442 if (rc < 0) {
6443 pr_err("%s :Comamnd media format update failed %d\n",
6444 __func__, rc);
6445 goto fail_cmd;
6446 }
6447 rc = wait_event_timeout(ac->cmd_wait,
6448 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6449 if (!rc) {
6450 pr_err("%s :timeout. waited for FORMAT_UPDATE\n", __func__);
6451 rc = -ETIMEDOUT;
6452 goto fail_cmd;
6453 }
6454
6455 if (atomic_read(&ac->cmd_state) > 0) {
6456 pr_err("%s: DSP returned error[%s]\n",
6457 __func__, adsp_err_get_err_str(
6458 atomic_read(&ac->cmd_state)));
6459 rc = adsp_err_get_lnx_err_code(
6460 atomic_read(&ac->cmd_state));
6461 goto fail_cmd;
6462 }
6463 return 0;
6464fail_cmd:
6465 return rc;
6466}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306467EXPORT_SYMBOL(q6asm_stream_media_format_block_flac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306468
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306469/**
6470 * q6asm_media_format_block_alac -
6471 * command to set mediafmt block for alac on ASM stream
6472 *
6473 * @ac: Audio client handle
6474 * @cfg: ALAC config
6475 * @stream_id: stream ID info
6476 *
6477 * Returns 0 on success or error on failure
6478 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306479int q6asm_media_format_block_alac(struct audio_client *ac,
6480 struct asm_alac_cfg *cfg, int stream_id)
6481{
6482 struct asm_alac_fmt_blk_v2 fmt;
6483 int rc = 0;
6484
6485 pr_debug("%s :session[%d]rate[%d]ch[%d]\n", __func__,
6486 ac->session, cfg->sample_rate, cfg->num_channels);
6487
6488 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6489 atomic_set(&ac->cmd_state, -1);
6490
6491 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6492 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6493 sizeof(fmt.fmtblk);
6494
6495 fmt.frame_length = cfg->frame_length;
6496 fmt.compatible_version = cfg->compatible_version;
6497 fmt.bit_depth = cfg->bit_depth;
6498 fmt.pb = cfg->pb;
6499 fmt.mb = cfg->mb;
6500 fmt.kb = cfg->kb;
6501 fmt.num_channels = cfg->num_channels;
6502 fmt.max_run = cfg->max_run;
6503 fmt.max_frame_bytes = cfg->max_frame_bytes;
6504 fmt.avg_bit_rate = cfg->avg_bit_rate;
6505 fmt.sample_rate = cfg->sample_rate;
6506 fmt.channel_layout_tag = cfg->channel_layout_tag;
6507
6508 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6509 if (rc < 0) {
6510 pr_err("%s :Comamnd media format update failed %d\n",
6511 __func__, rc);
6512 goto fail_cmd;
6513 }
6514 rc = wait_event_timeout(ac->cmd_wait,
6515 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6516 if (!rc) {
6517 pr_err("%s :timeout. waited for FORMAT_UPDATE\n", __func__);
6518 rc = -ETIMEDOUT;
6519 goto fail_cmd;
6520 }
6521
6522 if (atomic_read(&ac->cmd_state) > 0) {
6523 pr_err("%s: DSP returned error[%s]\n",
6524 __func__, adsp_err_get_err_str(
6525 atomic_read(&ac->cmd_state)));
6526 rc = adsp_err_get_lnx_err_code(
6527 atomic_read(&ac->cmd_state));
6528 goto fail_cmd;
6529 }
6530 return 0;
6531fail_cmd:
6532 return rc;
6533}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306534EXPORT_SYMBOL(q6asm_media_format_block_alac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306535
6536/*
6537 * q6asm_media_format_block_g711 - sends g711 decoder configuration
6538 * parameters
6539 * @ac: Client session handle
6540 * @cfg: Audio stream manager configuration parameters
6541 * @stream_id: Stream id
6542 */
6543int q6asm_media_format_block_g711(struct audio_client *ac,
6544 struct asm_g711_dec_cfg *cfg, int stream_id)
6545{
6546 struct asm_g711_dec_fmt_blk_v2 fmt;
6547 int rc = 0;
6548
6549 if (!ac) {
6550 pr_err("%s: audio client is null\n", __func__);
6551 return -EINVAL;
6552 }
6553 if (!cfg) {
6554 pr_err("%s: Invalid ASM config\n", __func__);
6555 return -EINVAL;
6556 }
6557
6558 if (stream_id <= 0) {
6559 pr_err("%s: Invalid stream id\n", __func__);
6560 return -EINVAL;
6561 }
6562
6563 pr_debug("%s :session[%d]rate[%d]\n", __func__,
6564 ac->session, cfg->sample_rate);
6565
6566 memset(&fmt, 0, sizeof(struct asm_g711_dec_fmt_blk_v2));
6567
6568 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6569 atomic_set(&ac->cmd_state, -1);
6570
6571 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6572 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6573 sizeof(fmt.fmtblk);
6574
6575 fmt.sample_rate = cfg->sample_rate;
6576
6577 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6578 if (rc < 0) {
6579 pr_err("%s :Command media format update failed %d\n",
6580 __func__, rc);
6581 goto fail_cmd;
6582 }
6583 rc = wait_event_timeout(ac->cmd_wait,
6584 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6585 if (!rc) {
6586 pr_err("%s :timeout. waited for FORMAT_UPDATE\n", __func__);
6587 rc = -ETIMEDOUT;
6588 goto fail_cmd;
6589 }
6590
6591 if (atomic_read(&ac->cmd_state) > 0) {
6592 pr_err("%s: DSP returned error[%s]\n",
6593 __func__, adsp_err_get_err_str(
6594 atomic_read(&ac->cmd_state)));
6595 rc = adsp_err_get_lnx_err_code(
6596 atomic_read(&ac->cmd_state));
6597 goto fail_cmd;
6598 }
6599 return 0;
6600fail_cmd:
6601 return rc;
6602}
6603EXPORT_SYMBOL(q6asm_media_format_block_g711);
6604
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306605/**
6606 * q6asm_stream_media_format_block_vorbis -
6607 * command to set mediafmt block for vorbis on ASM stream
6608 *
6609 * @ac: Audio client handle
6610 * @cfg: vorbis config
6611 * @stream_id: stream ID info
6612 *
6613 * Returns 0 on success or error on failure
6614 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306615int q6asm_stream_media_format_block_vorbis(struct audio_client *ac,
6616 struct asm_vorbis_cfg *cfg, int stream_id)
6617{
6618 struct asm_vorbis_fmt_blk_v2 fmt;
6619 int rc = 0;
6620
6621 pr_debug("%s :session[%d] bit_stream_fmt[%d] stream_id[%d]\n",
6622 __func__, ac->session, cfg->bit_stream_fmt, stream_id);
6623
6624 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6625 atomic_set(&ac->cmd_state, -1);
6626
6627 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6628 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6629 sizeof(fmt.fmtblk);
6630
6631 fmt.bit_stream_fmt = cfg->bit_stream_fmt;
6632
6633 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6634 if (rc < 0) {
6635 pr_err("%s :Comamnd media format update failed %d\n",
6636 __func__, rc);
6637 goto fail_cmd;
6638 }
6639 rc = wait_event_timeout(ac->cmd_wait,
6640 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6641 if (!rc) {
6642 pr_err("%s :timeout. waited for FORMAT_UPDATE\n", __func__);
6643 rc = -ETIMEDOUT;
6644 goto fail_cmd;
6645 }
6646
6647 if (atomic_read(&ac->cmd_state) > 0) {
6648 pr_err("%s: DSP returned error[%s]\n",
6649 __func__, adsp_err_get_err_str(
6650 atomic_read(&ac->cmd_state)));
6651 rc = adsp_err_get_lnx_err_code(
6652 atomic_read(&ac->cmd_state));
6653 goto fail_cmd;
6654 }
6655 return 0;
6656fail_cmd:
6657 return rc;
6658}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306659EXPORT_SYMBOL(q6asm_stream_media_format_block_vorbis);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306660
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306661/**
6662 * q6asm_media_format_block_ape -
6663 * command to set mediafmt block for APE on ASM stream
6664 *
6665 * @ac: Audio client handle
6666 * @cfg: APE config
6667 * @stream_id: stream ID info
6668 *
6669 * Returns 0 on success or error on failure
6670 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306671int q6asm_media_format_block_ape(struct audio_client *ac,
6672 struct asm_ape_cfg *cfg, int stream_id)
6673{
6674 struct asm_ape_fmt_blk_v2 fmt;
6675 int rc = 0;
6676
6677 pr_debug("%s :session[%d]rate[%d]ch[%d]\n", __func__,
6678 ac->session, cfg->sample_rate, cfg->num_channels);
6679
6680 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6681 atomic_set(&ac->cmd_state, -1);
6682
6683 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6684 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6685 sizeof(fmt.fmtblk);
6686
6687 fmt.compatible_version = cfg->compatible_version;
6688 fmt.compression_level = cfg->compression_level;
6689 fmt.format_flags = cfg->format_flags;
6690 fmt.blocks_per_frame = cfg->blocks_per_frame;
6691 fmt.final_frame_blocks = cfg->final_frame_blocks;
6692 fmt.total_frames = cfg->total_frames;
6693 fmt.bits_per_sample = cfg->bits_per_sample;
6694 fmt.num_channels = cfg->num_channels;
6695 fmt.sample_rate = cfg->sample_rate;
6696 fmt.seek_table_present = cfg->seek_table_present;
6697
6698 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6699 if (rc < 0) {
6700 pr_err("%s :Comamnd media format update failed %d\n",
6701 __func__, rc);
6702 goto fail_cmd;
6703 }
6704 rc = wait_event_timeout(ac->cmd_wait,
6705 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6706 if (!rc) {
6707 pr_err("%s :timeout. waited for FORMAT_UPDATE\n", __func__);
6708 rc = -ETIMEDOUT;
6709 goto fail_cmd;
6710 }
6711
6712 if (atomic_read(&ac->cmd_state) > 0) {
6713 pr_err("%s: DSP returned error[%s]\n",
6714 __func__, adsp_err_get_err_str(
6715 atomic_read(&ac->cmd_state)));
6716 rc = adsp_err_get_lnx_err_code(
6717 atomic_read(&ac->cmd_state));
6718 goto fail_cmd;
6719 }
6720 return 0;
6721fail_cmd:
6722 return rc;
6723}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306724EXPORT_SYMBOL(q6asm_media_format_block_ape);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306725
6726/*
6727 * q6asm_media_format_block_dsd- Sends DSD Decoder
6728 * configuration parameters
6729 *
6730 * @ac: Client session handle
6731 * @cfg: DSD Media Format Configuration.
6732 * @stream_id: stream id of stream to be associated with this session
6733 *
6734 * Return 0 on success or negative error code on failure
6735 */
6736int q6asm_media_format_block_dsd(struct audio_client *ac,
6737 struct asm_dsd_cfg *cfg, int stream_id)
6738{
6739 struct asm_dsd_fmt_blk_v2 fmt;
6740 int rc;
6741
6742 pr_debug("%s: session[%d] data_rate[%d] ch[%d]\n", __func__,
6743 ac->session, cfg->dsd_data_rate, cfg->num_channels);
6744
6745 memset(&fmt, 0, sizeof(fmt));
6746 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6747
6748 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6749 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6750 sizeof(fmt.fmtblk);
6751
6752 fmt.num_version = cfg->num_version;
6753 fmt.is_bitwise_big_endian = cfg->is_bitwise_big_endian;
6754 fmt.dsd_channel_block_size = cfg->dsd_channel_block_size;
6755 fmt.num_channels = cfg->num_channels;
6756 fmt.dsd_data_rate = cfg->dsd_data_rate;
6757 atomic_set(&ac->cmd_state, -1);
6758 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6759 if (rc < 0) {
6760 pr_err("%s: Command DSD media format update failed, err: %d\n",
6761 __func__, rc);
6762 goto done;
6763 }
6764 rc = wait_event_timeout(ac->cmd_wait,
6765 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6766 if (!rc) {
6767 pr_err("%s: timeout. waited for DSD FORMAT_UPDATE\n", __func__);
6768 rc = -ETIMEDOUT;
6769 goto done;
6770 }
6771
6772 if (atomic_read(&ac->cmd_state) > 0) {
6773 pr_err("%s: DSP returned error[%s]\n",
6774 __func__, adsp_err_get_err_str(
6775 atomic_read(&ac->cmd_state)));
6776 rc = adsp_err_get_lnx_err_code(
6777 atomic_read(&ac->cmd_state));
6778 goto done;
6779 }
6780 return 0;
6781done:
6782 return rc;
6783}
6784EXPORT_SYMBOL(q6asm_media_format_block_dsd);
6785
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306786/**
6787 * q6asm_stream_media_format_block_aptx_dec -
6788 * command to set mediafmt block for APTX dec on ASM stream
6789 *
6790 * @ac: Audio client handle
6791 * @srate: sample rate
6792 * @stream_id: stream ID info
6793 *
6794 * Returns 0 on success or error on failure
6795 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306796int q6asm_stream_media_format_block_aptx_dec(struct audio_client *ac,
6797 uint32_t srate, int stream_id)
6798{
6799 struct asm_aptx_dec_fmt_blk_v2 aptx_fmt;
6800 int rc = 0;
6801
6802 if (!ac->session) {
6803 pr_err("%s: ac session invalid\n", __func__);
6804 rc = -EINVAL;
6805 goto fail_cmd;
6806 }
6807 pr_debug("%s :session[%d] rate[%d] stream_id[%d]\n",
6808 __func__, ac->session, srate, stream_id);
6809
6810 q6asm_stream_add_hdr(ac, &aptx_fmt.hdr, sizeof(aptx_fmt), TRUE,
6811 stream_id);
6812 atomic_set(&ac->cmd_state, -1);
6813
6814 aptx_fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6815 aptx_fmt.fmtblk.fmt_blk_size = sizeof(aptx_fmt) - sizeof(aptx_fmt.hdr) -
6816 sizeof(aptx_fmt.fmtblk);
6817
6818 aptx_fmt.sample_rate = srate;
6819
6820 rc = apr_send_pkt(ac->apr, (uint32_t *) &aptx_fmt);
6821 if (rc < 0) {
6822 pr_err("%s :Comamnd media format update failed %d\n",
6823 __func__, rc);
6824 goto fail_cmd;
6825 }
6826 rc = wait_event_timeout(ac->cmd_wait,
6827 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6828 if (!rc) {
6829 pr_err("%s :timeout. waited for FORMAT_UPDATE\n", __func__);
6830 rc = -ETIMEDOUT;
6831 goto fail_cmd;
6832 }
6833
6834 if (atomic_read(&ac->cmd_state) > 0) {
6835 pr_err("%s: DSP returned error[%s]\n",
6836 __func__, adsp_err_get_err_str(
6837 atomic_read(&ac->cmd_state)));
6838 rc = adsp_err_get_lnx_err_code(
6839 atomic_read(&ac->cmd_state));
6840 goto fail_cmd;
6841 }
6842 rc = 0;
6843fail_cmd:
6844 return rc;
6845}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306846EXPORT_SYMBOL(q6asm_stream_media_format_block_aptx_dec);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306847
6848static int __q6asm_ds1_set_endp_params(struct audio_client *ac, int param_id,
6849 int param_value, int stream_id)
6850{
6851 struct asm_dec_ddp_endp_param_v2 ddp_cfg;
6852 int rc = 0;
6853
6854 pr_debug("%s: session[%d] stream[%d],param_id[%d]param_value[%d]",
6855 __func__, ac->session, stream_id, param_id, param_value);
6856
6857 q6asm_stream_add_hdr(ac, &ddp_cfg.hdr, sizeof(ddp_cfg), TRUE,
6858 stream_id);
6859 atomic_set(&ac->cmd_state, -1);
6860 /*
6861 * Updated the token field with stream/session for compressed playback
6862 * Platform driver must know the stream with which the command is
6863 * associated
6864 */
6865 if (ac->io_mode & COMPRESSED_STREAM_IO)
6866 q6asm_update_token(&ddp_cfg.hdr.token,
6867 ac->session,
6868 stream_id,
6869 0, /* Buffer index is NA */
6870 0, /* Direction flag is NA */
6871 WAIT_CMD);
6872 ddp_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
6873 ddp_cfg.encdec.param_id = param_id;
6874 ddp_cfg.encdec.param_size = sizeof(struct asm_dec_ddp_endp_param_v2) -
6875 (sizeof(struct apr_hdr) +
6876 sizeof(struct asm_stream_cmd_set_encdec_param));
6877 ddp_cfg.endp_param_value = param_value;
6878 rc = apr_send_pkt(ac->apr, (uint32_t *) &ddp_cfg);
6879 if (rc < 0) {
6880 pr_err("%s: Command opcode[0x%x] failed %d\n",
6881 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
6882 goto fail_cmd;
6883 }
6884 rc = wait_event_timeout(ac->cmd_wait,
6885 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6886 if (!rc) {
6887 pr_err("%s: timeout opcode[0x%x]\n", __func__,
6888 ddp_cfg.hdr.opcode);
6889 rc = -ETIMEDOUT;
6890 goto fail_cmd;
6891 }
6892 if (atomic_read(&ac->cmd_state) > 0) {
6893 pr_err("%s: DSP returned error[%s]\n",
6894 __func__, adsp_err_get_err_str(
6895 atomic_read(&ac->cmd_state)));
6896 rc = adsp_err_get_lnx_err_code(
6897 atomic_read(&ac->cmd_state));
6898 goto fail_cmd;
6899 }
6900 return 0;
6901fail_cmd:
6902 return rc;
6903}
6904
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306905/**
6906 * q6asm_ds1_set_endp_params -
6907 * command to set DS1 params for ASM
6908 *
6909 * @ac: Audio client handle
6910 * @param_id: param id
6911 * @param_value: value of param
6912 *
6913 * Returns 0 on success or error on failure
6914 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306915int q6asm_ds1_set_endp_params(struct audio_client *ac,
6916 int param_id, int param_value)
6917{
6918 return __q6asm_ds1_set_endp_params(ac, param_id, param_value,
6919 ac->stream_id);
6920}
6921
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306922/**
6923 * q6asm_ds1_set_stream_endp_params -
6924 * command to set DS1 params for ASM stream
6925 *
6926 * @ac: Audio client handle
6927 * @param_id: param id
6928 * @param_value: value of param
6929 * @stream_id: stream ID info
6930 *
6931 * Returns 0 on success or error on failure
6932 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306933int q6asm_ds1_set_stream_endp_params(struct audio_client *ac,
6934 int param_id, int param_value,
6935 int stream_id)
6936{
6937 return __q6asm_ds1_set_endp_params(ac, param_id, param_value,
6938 stream_id);
6939}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306940EXPORT_SYMBOL(q6asm_ds1_set_stream_endp_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306941
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306942/**
6943 * q6asm_memory_map -
6944 * command to send memory map for ASM
6945 *
6946 * @ac: Audio client handle
6947 * @buf_add: buffer address to map
6948 * @dir: RX or TX session
6949 * @bufsz: size of each buffer
6950 * @bufcnt: buffer count
6951 *
6952 * Returns 0 on success or error on failure
6953 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306954int q6asm_memory_map(struct audio_client *ac, phys_addr_t buf_add, int dir,
6955 uint32_t bufsz, uint32_t bufcnt)
6956{
6957 struct avs_cmd_shared_mem_map_regions *mmap_regions = NULL;
6958 struct avs_shared_map_region_payload *mregions = NULL;
6959 struct audio_port_data *port = NULL;
6960 void *mmap_region_cmd = NULL;
6961 void *payload = NULL;
6962 struct asm_buffer_node *buffer_node = NULL;
6963 int rc = 0;
6964 int cmd_size = 0;
6965
6966 if (!ac) {
6967 pr_err("%s: APR handle NULL\n", __func__);
6968 return -EINVAL;
6969 }
6970 if (ac->mmap_apr == NULL) {
6971 pr_err("%s: mmap APR handle NULL\n", __func__);
6972 return -EINVAL;
6973 }
6974 pr_debug("%s: Session[%d]\n", __func__, ac->session);
6975
6976 buffer_node = kmalloc(sizeof(struct asm_buffer_node), GFP_KERNEL);
6977 if (!buffer_node)
6978 return -ENOMEM;
6979
6980 cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions)
6981 + sizeof(struct avs_shared_map_region_payload) * bufcnt;
6982
6983 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
6984 if (mmap_region_cmd == NULL) {
6985 rc = -EINVAL;
6986 kfree(buffer_node);
6987 return rc;
6988 }
6989 mmap_regions = (struct avs_cmd_shared_mem_map_regions *)
6990 mmap_region_cmd;
6991 q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size, dir);
6992 atomic_set(&ac->mem_state, -1);
6993 mmap_regions->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS;
6994 mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
6995 mmap_regions->num_regions = bufcnt & 0x00ff;
6996 mmap_regions->property_flag = 0x00;
6997 payload = ((u8 *) mmap_region_cmd +
6998 sizeof(struct avs_cmd_shared_mem_map_regions));
6999 mregions = (struct avs_shared_map_region_payload *)payload;
7000
7001 ac->port[dir].tmp_hdl = 0;
7002 port = &ac->port[dir];
7003 pr_debug("%s: buf_add 0x%pK, bufsz: %d\n", __func__,
7004 &buf_add, bufsz);
7005 mregions->shm_addr_lsw = lower_32_bits(buf_add);
7006 mregions->shm_addr_msw = msm_audio_populate_upper_32_bits(buf_add);
7007 mregions->mem_size_bytes = bufsz;
7008 ++mregions;
7009
7010 rc = apr_send_pkt(ac->mmap_apr, (uint32_t *) mmap_region_cmd);
7011 if (rc < 0) {
7012 pr_err("%s: mmap op[0x%x]rc[%d]\n", __func__,
7013 mmap_regions->hdr.opcode, rc);
7014 rc = -EINVAL;
7015 kfree(buffer_node);
7016 goto fail_cmd;
7017 }
7018
7019 rc = wait_event_timeout(ac->mem_wait,
7020 (atomic_read(&ac->mem_state) >= 0 &&
7021 ac->port[dir].tmp_hdl), 5*HZ);
7022 if (!rc) {
7023 pr_err("%s: timeout. waited for memory_map\n", __func__);
7024 rc = -ETIMEDOUT;
7025 kfree(buffer_node);
7026 goto fail_cmd;
7027 }
7028 if (atomic_read(&ac->mem_state) > 0) {
7029 pr_err("%s: DSP returned error[%s] for memory_map\n",
7030 __func__, adsp_err_get_err_str(
7031 atomic_read(&ac->mem_state)));
7032 rc = adsp_err_get_lnx_err_code(
7033 atomic_read(&ac->mem_state));
7034 kfree(buffer_node);
7035 goto fail_cmd;
7036 }
7037 buffer_node->buf_phys_addr = buf_add;
7038 buffer_node->mmap_hdl = ac->port[dir].tmp_hdl;
7039 list_add_tail(&buffer_node->list, &ac->port[dir].mem_map_handle);
7040 ac->port[dir].tmp_hdl = 0;
7041 rc = 0;
7042
7043fail_cmd:
7044 kfree(mmap_region_cmd);
7045 return rc;
7046}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307047EXPORT_SYMBOL(q6asm_memory_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307048
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307049/**
7050 * q6asm_memory_unmap -
7051 * command to send memory unmap for ASM
7052 *
7053 * @ac: Audio client handle
7054 * @buf_add: buffer address to unmap
7055 * @dir: RX or TX session
7056 *
7057 * Returns 0 on success or error on failure
7058 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307059int q6asm_memory_unmap(struct audio_client *ac, phys_addr_t buf_add, int dir)
7060{
7061 struct avs_cmd_shared_mem_unmap_regions mem_unmap;
7062 struct asm_buffer_node *buf_node = NULL;
7063 struct list_head *ptr, *next;
7064
7065 int rc = 0;
7066
7067 if (!ac) {
7068 pr_err("%s: APR handle NULL\n", __func__);
7069 return -EINVAL;
7070 }
7071 if (this_mmap.apr == NULL) {
7072 pr_err("%s: APR handle NULL\n", __func__);
7073 return -EINVAL;
7074 }
7075 pr_debug("%s: Session[%d]\n", __func__, ac->session);
7076
7077 q6asm_add_mmaphdr(ac, &mem_unmap.hdr,
7078 sizeof(struct avs_cmd_shared_mem_unmap_regions),
7079 dir);
7080 atomic_set(&ac->mem_state, -1);
7081 mem_unmap.hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS;
7082 mem_unmap.mem_map_handle = 0;
7083 list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
7084 buf_node = list_entry(ptr, struct asm_buffer_node,
7085 list);
7086 if (buf_node->buf_phys_addr == buf_add) {
7087 pr_debug("%s: Found the element\n", __func__);
7088 mem_unmap.mem_map_handle = buf_node->mmap_hdl;
7089 break;
7090 }
7091 }
7092 pr_debug("%s: mem_unmap-mem_map_handle: 0x%x\n",
7093 __func__, mem_unmap.mem_map_handle);
7094
7095 if (mem_unmap.mem_map_handle == 0) {
7096 pr_err("%s: Do not send null mem handle to DSP\n", __func__);
7097 rc = 0;
7098 goto fail_cmd;
7099 }
7100 rc = apr_send_pkt(ac->mmap_apr, (uint32_t *) &mem_unmap);
7101 if (rc < 0) {
7102 pr_err("%s: mem_unmap op[0x%x]rc[%d]\n", __func__,
7103 mem_unmap.hdr.opcode, rc);
7104 rc = -EINVAL;
7105 goto fail_cmd;
7106 }
7107
7108 rc = wait_event_timeout(ac->mem_wait,
7109 (atomic_read(&ac->mem_state) >= 0), 5 * HZ);
7110 if (!rc) {
7111 pr_err("%s: timeout. waited for memory_unmap of handle 0x%x\n",
7112 __func__, mem_unmap.mem_map_handle);
7113 rc = -ETIMEDOUT;
7114 goto fail_cmd;
7115 } else if (atomic_read(&ac->mem_state) > 0) {
7116 pr_err("%s DSP returned error [%s] map handle 0x%x\n",
7117 __func__, adsp_err_get_err_str(
7118 atomic_read(&ac->mem_state)),
7119 mem_unmap.mem_map_handle);
7120 rc = adsp_err_get_lnx_err_code(
7121 atomic_read(&ac->mem_state));
7122 goto fail_cmd;
7123 } else if (atomic_read(&ac->unmap_cb_success) == 0) {
7124 pr_err("%s: Error in mem unmap callback of handle 0x%x\n",
7125 __func__, mem_unmap.mem_map_handle);
7126 rc = -EINVAL;
7127 goto fail_cmd;
7128 }
7129
7130 rc = 0;
7131fail_cmd:
7132 list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
7133 buf_node = list_entry(ptr, struct asm_buffer_node,
7134 list);
7135 if (buf_node->buf_phys_addr == buf_add) {
7136 list_del(&buf_node->list);
7137 kfree(buf_node);
7138 break;
7139 }
7140 }
7141 return rc;
7142}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307143EXPORT_SYMBOL(q6asm_memory_unmap);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307144
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307145/**
7146 * q6asm_memory_map_regions -
7147 * command to send memory map regions for ASM
7148 *
7149 * @ac: Audio client handle
7150 * @dir: RX or TX session
7151 * @bufsz: size of each buffer
7152 * @bufcnt: buffer count
7153 * @is_contiguous: alloc contiguous mem or not
7154 *
7155 * Returns 0 on success or error on failure
7156 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307157static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
7158 uint32_t bufsz, uint32_t bufcnt,
7159 bool is_contiguous)
7160{
7161 struct avs_cmd_shared_mem_map_regions *mmap_regions = NULL;
7162 struct avs_shared_map_region_payload *mregions = NULL;
7163 struct audio_port_data *port = NULL;
7164 struct audio_buffer *ab = NULL;
7165 void *mmap_region_cmd = NULL;
7166 void *payload = NULL;
7167 struct asm_buffer_node *buffer_node = NULL;
7168 int rc = 0;
7169 int i = 0;
7170 uint32_t cmd_size = 0;
7171 uint32_t bufcnt_t;
7172 uint32_t bufsz_t;
7173
7174 if (!ac) {
7175 pr_err("%s: APR handle NULL\n", __func__);
7176 return -EINVAL;
7177 }
7178 if (ac->mmap_apr == NULL) {
7179 pr_err("%s: mmap APR handle NULL\n", __func__);
7180 return -EINVAL;
7181 }
7182 pr_debug("%s: Session[%d]\n", __func__, ac->session);
7183
7184 bufcnt_t = (is_contiguous) ? 1 : bufcnt;
7185 bufsz_t = (is_contiguous) ? (bufsz * bufcnt) : bufsz;
7186
7187 if (is_contiguous) {
7188 /* The size to memory map should be multiple of 4K bytes */
7189 bufsz_t = PAGE_ALIGN(bufsz_t);
7190 }
7191
7192 if (bufcnt_t > (UINT_MAX
7193 - sizeof(struct avs_cmd_shared_mem_map_regions))
7194 / sizeof(struct avs_shared_map_region_payload)) {
7195 pr_err("%s: Unsigned Integer Overflow. bufcnt_t = %u\n",
7196 __func__, bufcnt_t);
7197 return -EINVAL;
7198 }
7199
7200 cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions)
7201 + (sizeof(struct avs_shared_map_region_payload)
7202 * bufcnt_t);
7203
7204
7205 if (bufcnt > (UINT_MAX / sizeof(struct asm_buffer_node))) {
7206 pr_err("%s: Unsigned Integer Overflow. bufcnt = %u\n",
7207 __func__, bufcnt);
7208 return -EINVAL;
7209 }
7210
7211 buffer_node = kzalloc(sizeof(struct asm_buffer_node) * bufcnt,
7212 GFP_KERNEL);
7213 if (!buffer_node)
7214 return -ENOMEM;
7215
7216 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
7217 if (mmap_region_cmd == NULL) {
7218 rc = -EINVAL;
7219 kfree(buffer_node);
7220 return rc;
7221 }
7222 mmap_regions = (struct avs_cmd_shared_mem_map_regions *)
7223 mmap_region_cmd;
7224 q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size, dir);
7225 atomic_set(&ac->mem_state, -1);
7226 pr_debug("%s: mmap_region=0x%pK token=0x%x\n", __func__,
7227 mmap_regions, ((ac->session << 8) | dir));
7228
7229 mmap_regions->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS;
7230 mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
7231 mmap_regions->num_regions = bufcnt_t; /*bufcnt & 0x00ff; */
7232 mmap_regions->property_flag = 0x00;
7233 pr_debug("%s: map_regions->nregions = %d\n", __func__,
7234 mmap_regions->num_regions);
7235 payload = ((u8 *) mmap_region_cmd +
7236 sizeof(struct avs_cmd_shared_mem_map_regions));
7237 mregions = (struct avs_shared_map_region_payload *)payload;
7238
7239 ac->port[dir].tmp_hdl = 0;
7240 port = &ac->port[dir];
7241 for (i = 0; i < bufcnt_t; i++) {
7242 ab = &port->buf[i];
7243 mregions->shm_addr_lsw = lower_32_bits(ab->phys);
7244 mregions->shm_addr_msw =
7245 msm_audio_populate_upper_32_bits(ab->phys);
7246 mregions->mem_size_bytes = bufsz_t;
7247 ++mregions;
7248 }
7249
7250 rc = apr_send_pkt(ac->mmap_apr, (uint32_t *) mmap_region_cmd);
7251 if (rc < 0) {
7252 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
7253 mmap_regions->hdr.opcode, rc);
7254 rc = -EINVAL;
7255 kfree(buffer_node);
7256 goto fail_cmd;
7257 }
7258
7259 rc = wait_event_timeout(ac->mem_wait,
7260 (atomic_read(&ac->mem_state) >= 0)
7261 , 5*HZ);
7262 if (!rc) {
7263 pr_err("%s: timeout. waited for memory_map\n", __func__);
7264 rc = -ETIMEDOUT;
7265 kfree(buffer_node);
7266 goto fail_cmd;
7267 }
7268 if (atomic_read(&ac->mem_state) > 0) {
7269 pr_err("%s DSP returned error for memory_map [%s]\n",
7270 __func__, adsp_err_get_err_str(
7271 atomic_read(&ac->mem_state)));
7272 rc = adsp_err_get_lnx_err_code(
7273 atomic_read(&ac->mem_state));
7274 kfree(buffer_node);
7275 goto fail_cmd;
7276 }
7277 mutex_lock(&ac->cmd_lock);
7278
7279 for (i = 0; i < bufcnt; i++) {
7280 ab = &port->buf[i];
7281 buffer_node[i].buf_phys_addr = ab->phys;
7282 buffer_node[i].mmap_hdl = ac->port[dir].tmp_hdl;
7283 list_add_tail(&buffer_node[i].list,
7284 &ac->port[dir].mem_map_handle);
7285 pr_debug("%s: i=%d, bufadd[i] = 0x%pK, maphdl[i] = 0x%x\n",
7286 __func__, i, &buffer_node[i].buf_phys_addr,
7287 buffer_node[i].mmap_hdl);
7288 }
7289 ac->port[dir].tmp_hdl = 0;
7290 mutex_unlock(&ac->cmd_lock);
7291 rc = 0;
7292fail_cmd:
7293 kfree(mmap_region_cmd);
7294 return rc;
7295}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307296EXPORT_SYMBOL(q6asm_memory_map_regions);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307297
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307298/**
7299 * q6asm_memory_unmap_regions -
7300 * command to send memory unmap regions for ASM
7301 *
7302 * @ac: Audio client handle
7303 * @dir: RX or TX session
7304 *
7305 * Returns 0 on success or error on failure
7306 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307307static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir)
7308{
7309 struct avs_cmd_shared_mem_unmap_regions mem_unmap;
7310 struct audio_port_data *port = NULL;
7311 struct asm_buffer_node *buf_node = NULL;
7312 struct list_head *ptr, *next;
7313 phys_addr_t buf_add;
7314 int rc = 0;
7315 int cmd_size = 0;
7316
7317 if (!ac) {
7318 pr_err("%s: APR handle NULL\n", __func__);
7319 return -EINVAL;
7320 }
7321 if (ac->mmap_apr == NULL) {
7322 pr_err("%s: mmap APR handle NULL\n", __func__);
7323 return -EINVAL;
7324 }
7325 pr_debug("%s: Session[%d]\n", __func__, ac->session);
7326
7327 cmd_size = sizeof(struct avs_cmd_shared_mem_unmap_regions);
7328 q6asm_add_mmaphdr(ac, &mem_unmap.hdr, cmd_size, dir);
7329 atomic_set(&ac->mem_state, -1);
7330 port = &ac->port[dir];
7331 buf_add = port->buf->phys;
7332 mem_unmap.hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS;
7333 mem_unmap.mem_map_handle = 0;
7334 list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
7335 buf_node = list_entry(ptr, struct asm_buffer_node,
7336 list);
7337 if (buf_node->buf_phys_addr == buf_add) {
7338 pr_debug("%s: Found the element\n", __func__);
7339 mem_unmap.mem_map_handle = buf_node->mmap_hdl;
7340 break;
7341 }
7342 }
7343
7344 pr_debug("%s: mem_unmap-mem_map_handle: 0x%x\n",
7345 __func__, mem_unmap.mem_map_handle);
7346
7347 if (mem_unmap.mem_map_handle == 0) {
7348 pr_err("%s: Do not send null mem handle to DSP\n", __func__);
7349 rc = 0;
7350 goto fail_cmd;
7351 }
7352 rc = apr_send_pkt(ac->mmap_apr, (uint32_t *) &mem_unmap);
7353 if (rc < 0) {
7354 pr_err("mmap_regions op[0x%x]rc[%d]\n",
7355 mem_unmap.hdr.opcode, rc);
7356 goto fail_cmd;
7357 }
7358
7359 rc = wait_event_timeout(ac->mem_wait,
7360 (atomic_read(&ac->mem_state) >= 0), 5*HZ);
7361 if (!rc) {
7362 pr_err("%s: timeout. waited for memory_unmap of handle 0x%x\n",
7363 __func__, mem_unmap.mem_map_handle);
7364 rc = -ETIMEDOUT;
7365 goto fail_cmd;
7366 } else if (atomic_read(&ac->mem_state) > 0) {
7367 pr_err("%s: DSP returned error[%s]\n",
7368 __func__, adsp_err_get_err_str(
7369 atomic_read(&ac->mem_state)));
7370 rc = adsp_err_get_lnx_err_code(
7371 atomic_read(&ac->mem_state));
7372 goto fail_cmd;
7373 } else if (atomic_read(&ac->unmap_cb_success) == 0) {
7374 pr_err("%s: Error in mem unmap callback of handle 0x%x\n",
7375 __func__, mem_unmap.mem_map_handle);
7376 rc = -EINVAL;
7377 goto fail_cmd;
7378 }
7379 rc = 0;
7380
7381fail_cmd:
7382 list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
7383 buf_node = list_entry(ptr, struct asm_buffer_node,
7384 list);
7385 if (buf_node->buf_phys_addr == buf_add) {
7386 list_del(&buf_node->list);
7387 kfree(buf_node);
7388 break;
7389 }
7390 }
7391 return rc;
7392}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307393EXPORT_SYMBOL(q6asm_memory_unmap_regions);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307394
7395int q6asm_set_lrgain(struct audio_client *ac, int left_gain, int right_gain)
7396{
7397 struct asm_volume_ctrl_multichannel_gain multi_ch_gain;
7398 int sz = 0;
7399 int rc = 0;
7400
7401 if (ac == NULL) {
7402 pr_err("%s: APR handle NULL\n", __func__);
7403 rc = -EINVAL;
7404 goto fail_cmd;
7405 }
7406 if (ac->apr == NULL) {
7407 pr_err("%s: AC APR handle NULL\n", __func__);
7408 rc = -EINVAL;
7409 goto fail_cmd;
7410 }
7411
7412 memset(&multi_ch_gain, 0, sizeof(multi_ch_gain));
7413 sz = sizeof(struct asm_volume_ctrl_multichannel_gain);
7414 q6asm_add_hdr_async(ac, &multi_ch_gain.hdr, sz, TRUE);
7415 atomic_set(&ac->cmd_state_pp, -1);
7416 multi_ch_gain.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
7417 multi_ch_gain.param.data_payload_addr_lsw = 0;
7418 multi_ch_gain.param.data_payload_addr_msw = 0;
7419 multi_ch_gain.param.mem_map_handle = 0;
7420 multi_ch_gain.param.data_payload_size = sizeof(multi_ch_gain) -
7421 sizeof(multi_ch_gain.hdr) - sizeof(multi_ch_gain.param);
7422 multi_ch_gain.data.module_id = ASM_MODULE_ID_VOL_CTRL;
7423 multi_ch_gain.data.param_id = ASM_PARAM_ID_MULTICHANNEL_GAIN;
7424 multi_ch_gain.data.param_size = multi_ch_gain.param.data_payload_size -
7425 sizeof(multi_ch_gain.data);
7426 multi_ch_gain.data.reserved = 0;
7427 multi_ch_gain.gain_data[0].channeltype = PCM_CHANNEL_FL;
7428 multi_ch_gain.gain_data[0].gain = left_gain << 15;
7429 multi_ch_gain.gain_data[1].channeltype = PCM_CHANNEL_FR;
7430 multi_ch_gain.gain_data[1].gain = right_gain << 15;
7431 multi_ch_gain.num_channels = 2;
7432 rc = apr_send_pkt(ac->apr, (uint32_t *) &multi_ch_gain);
7433 if (rc < 0) {
7434 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
7435 __func__, multi_ch_gain.data.param_id, rc);
7436 rc = -EINVAL;
7437 goto fail_cmd;
7438 }
7439
7440 rc = wait_event_timeout(ac->cmd_wait,
7441 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
7442 if (!rc) {
7443 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
7444 multi_ch_gain.data.param_id);
7445 rc = -ETIMEDOUT;
7446 goto fail_cmd;
7447 }
7448 if (atomic_read(&ac->cmd_state_pp) > 0) {
7449 pr_err("%s: DSP returned error[%s] , set-params paramid[0x%x]\n",
7450 __func__, adsp_err_get_err_str(
7451 atomic_read(&ac->cmd_state_pp)),
7452 multi_ch_gain.data.param_id);
7453 rc = adsp_err_get_lnx_err_code(
7454 atomic_read(&ac->cmd_state_pp));
7455 goto fail_cmd;
7456 }
7457 rc = 0;
7458fail_cmd:
7459 return rc;
7460}
7461
7462/*
7463 * q6asm_set_multich_gain: set multiple channel gains on an ASM session
7464 * @ac: audio client handle
7465 * @channels: number of channels caller intends to set gains
7466 * @gains: list of gains of audio channels
7467 * @ch_map: list of channel mapping. Only valid if use_default is false
7468 * @use_default: flag to indicate whether to use default mapping
7469 */
7470int q6asm_set_multich_gain(struct audio_client *ac, uint32_t channels,
7471 uint32_t *gains, uint8_t *ch_map, bool use_default)
7472{
7473 struct asm_volume_ctrl_multichannel_gain multich_gain;
7474 int sz = 0;
7475 int rc = 0;
7476 int i;
7477 u8 default_chmap[VOLUME_CONTROL_MAX_CHANNELS];
7478
7479 if (ac == NULL) {
7480 pr_err("%s: ac is NULL\n", __func__);
7481 rc = -EINVAL;
7482 goto done;
7483 }
7484 if (ac->apr == NULL) {
7485 dev_err(ac->dev, "%s: AC APR handle NULL\n", __func__);
7486 rc = -EINVAL;
7487 goto done;
7488 }
7489 if (gains == NULL) {
7490 dev_err(ac->dev, "%s: gain_list is NULL\n", __func__);
7491 rc = -EINVAL;
7492 goto done;
7493 }
7494 if (channels > VOLUME_CONTROL_MAX_CHANNELS) {
7495 dev_err(ac->dev, "%s: Invalid channel count %d\n",
7496 __func__, channels);
7497 rc = -EINVAL;
7498 goto done;
7499 }
7500 if (!use_default && ch_map == NULL) {
7501 dev_err(ac->dev, "%s: NULL channel map\n", __func__);
7502 rc = -EINVAL;
7503 goto done;
7504 }
7505
7506 memset(&multich_gain, 0, sizeof(multich_gain));
7507 sz = sizeof(struct asm_volume_ctrl_multichannel_gain);
7508 q6asm_add_hdr_async(ac, &multich_gain.hdr, sz, TRUE);
7509 atomic_set(&ac->cmd_state_pp, -1);
7510 multich_gain.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
7511 multich_gain.param.data_payload_addr_lsw = 0;
7512 multich_gain.param.data_payload_addr_msw = 0;
7513 multich_gain.param.mem_map_handle = 0;
7514 multich_gain.param.data_payload_size = sizeof(multich_gain) -
7515 sizeof(multich_gain.hdr) - sizeof(multich_gain.param);
7516 multich_gain.data.module_id = ASM_MODULE_ID_VOL_CTRL;
7517 multich_gain.data.param_id = ASM_PARAM_ID_MULTICHANNEL_GAIN;
7518 multich_gain.data.param_size = multich_gain.param.data_payload_size -
7519 sizeof(multich_gain.data);
7520 multich_gain.data.reserved = 0;
7521
7522 if (use_default) {
7523 rc = q6asm_map_channels(default_chmap, channels, false);
7524 if (rc < 0)
7525 goto done;
7526 for (i = 0; i < channels; i++) {
7527 multich_gain.gain_data[i].channeltype =
7528 default_chmap[i];
7529 multich_gain.gain_data[i].gain = gains[i] << 15;
7530 }
7531 } else {
7532 for (i = 0; i < channels; i++) {
7533 multich_gain.gain_data[i].channeltype = ch_map[i];
7534 multich_gain.gain_data[i].gain = gains[i] << 15;
7535 }
7536 }
7537 multich_gain.num_channels = channels;
7538
7539 rc = apr_send_pkt(ac->apr, (uint32_t *) &multich_gain);
7540 if (rc < 0) {
7541 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
7542 __func__, multich_gain.data.param_id, rc);
7543 goto done;
7544 }
7545
7546 rc = wait_event_timeout(ac->cmd_wait,
7547 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
7548 if (!rc) {
7549 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
7550 multich_gain.data.param_id);
7551 rc = -EINVAL;
7552 goto done;
7553 }
7554 if (atomic_read(&ac->cmd_state_pp) > 0) {
7555 pr_err("%s: DSP returned error[%d] , set-params paramid[0x%x]\n",
7556 __func__, atomic_read(&ac->cmd_state_pp),
7557 multich_gain.data.param_id);
7558 rc = -EINVAL;
7559 goto done;
7560 }
7561 rc = 0;
7562done:
7563 return rc;
7564}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307565EXPORT_SYMBOL(q6asm_set_multich_gain);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307566
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307567/**
7568 * q6asm_set_mute -
7569 * command to set mute for ASM
7570 *
7571 * @ac: Audio client handle
7572 * @muteflag: mute value
7573 *
7574 * Returns 0 on success or error on failure
7575 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307576int q6asm_set_mute(struct audio_client *ac, int muteflag)
7577{
7578 struct asm_volume_ctrl_mute_config mute;
7579 int sz = 0;
7580 int rc = 0;
7581
7582 if (ac == NULL) {
7583 pr_err("%s: APR handle NULL\n", __func__);
7584 rc = -EINVAL;
7585 goto fail_cmd;
7586 }
7587 if (ac->apr == NULL) {
7588 pr_err("%s: AC APR handle NULL\n", __func__);
7589 rc = -EINVAL;
7590 goto fail_cmd;
7591 }
7592
7593 sz = sizeof(struct asm_volume_ctrl_mute_config);
7594 q6asm_add_hdr_async(ac, &mute.hdr, sz, TRUE);
7595 atomic_set(&ac->cmd_state_pp, -1);
7596 mute.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
7597 mute.param.data_payload_addr_lsw = 0;
7598 mute.param.data_payload_addr_msw = 0;
7599 mute.param.mem_map_handle = 0;
7600 mute.param.data_payload_size = sizeof(mute) -
7601 sizeof(mute.hdr) - sizeof(mute.param);
7602 mute.data.module_id = ASM_MODULE_ID_VOL_CTRL;
7603 mute.data.param_id = ASM_PARAM_ID_VOL_CTRL_MUTE_CONFIG;
7604 mute.data.param_size = mute.param.data_payload_size - sizeof(mute.data);
7605 mute.data.reserved = 0;
7606 mute.mute_flag = muteflag;
7607
7608 rc = apr_send_pkt(ac->apr, (uint32_t *) &mute);
7609 if (rc < 0) {
7610 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
7611 __func__, mute.data.param_id, rc);
7612 rc = -EINVAL;
7613 goto fail_cmd;
7614 }
7615
7616 rc = wait_event_timeout(ac->cmd_wait,
7617 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
7618 if (!rc) {
7619 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
7620 mute.data.param_id);
7621 rc = -ETIMEDOUT;
7622 goto fail_cmd;
7623 }
7624 if (atomic_read(&ac->cmd_state_pp) > 0) {
7625 pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
7626 __func__, adsp_err_get_err_str(
7627 atomic_read(&ac->cmd_state_pp)),
7628 mute.data.param_id);
7629 rc = adsp_err_get_lnx_err_code(
7630 atomic_read(&ac->cmd_state_pp));
7631 goto fail_cmd;
7632 }
7633 rc = 0;
7634fail_cmd:
7635 return rc;
7636}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307637EXPORT_SYMBOL(q6asm_set_mute);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307638
7639static int __q6asm_set_volume(struct audio_client *ac, int volume, int instance)
7640{
7641 struct asm_volume_ctrl_master_gain vol;
7642 int sz = 0;
7643 int rc = 0;
7644 int module_id;
7645
7646 if (ac == NULL) {
7647 pr_err("%s: APR handle NULL\n", __func__);
7648 rc = -EINVAL;
7649 goto fail_cmd;
7650 }
7651 if (ac->apr == NULL) {
7652 pr_err("%s: AC APR handle NULL\n", __func__);
7653 rc = -EINVAL;
7654 goto fail_cmd;
7655 }
7656
7657 switch (instance) {
7658 case SOFT_VOLUME_INSTANCE_2:
7659 module_id = ASM_MODULE_ID_VOL_CTRL2;
7660 break;
7661 case SOFT_VOLUME_INSTANCE_1:
7662 default:
7663 module_id = ASM_MODULE_ID_VOL_CTRL;
7664 break;
7665 }
7666
7667 sz = sizeof(struct asm_volume_ctrl_master_gain);
7668 q6asm_add_hdr_async(ac, &vol.hdr, sz, TRUE);
7669 atomic_set(&ac->cmd_state_pp, -1);
7670 vol.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
7671 vol.param.data_payload_addr_lsw = 0;
7672 vol.param.data_payload_addr_msw = 0;
7673 vol.param.mem_map_handle = 0;
7674 vol.param.data_payload_size = sizeof(vol) -
7675 sizeof(vol.hdr) - sizeof(vol.param);
7676 vol.data.module_id = module_id;
7677 vol.data.param_id = ASM_PARAM_ID_VOL_CTRL_MASTER_GAIN;
7678 vol.data.param_size = vol.param.data_payload_size - sizeof(vol.data);
7679 vol.data.reserved = 0;
7680 vol.master_gain = volume;
7681
7682 rc = apr_send_pkt(ac->apr, (uint32_t *) &vol);
7683 if (rc < 0) {
7684 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
7685 __func__, vol.data.param_id, rc);
7686 rc = -EINVAL;
7687 goto fail_cmd;
7688 }
7689
7690 rc = wait_event_timeout(ac->cmd_wait,
7691 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
7692 if (!rc) {
7693 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
7694 vol.data.param_id);
7695 rc = -ETIMEDOUT;
7696 goto fail_cmd;
7697 }
7698 if (atomic_read(&ac->cmd_state_pp) > 0) {
7699 pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
7700 __func__, adsp_err_get_err_str(
7701 atomic_read(&ac->cmd_state_pp)),
7702 vol.data.param_id);
7703 rc = adsp_err_get_lnx_err_code(
7704 atomic_read(&ac->cmd_state_pp));
7705 goto fail_cmd;
7706 }
7707
7708 rc = 0;
7709fail_cmd:
7710 return rc;
7711}
7712
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307713/**
7714 * q6asm_set_volume -
7715 * command to set volume for ASM
7716 *
7717 * @ac: Audio client handle
7718 * @volume: volume level
7719 *
7720 * Returns 0 on success or error on failure
7721 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307722int q6asm_set_volume(struct audio_client *ac, int volume)
7723{
7724 return __q6asm_set_volume(ac, volume, SOFT_VOLUME_INSTANCE_1);
7725}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307726EXPORT_SYMBOL(q6asm_set_volume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307727
7728int q6asm_set_volume_v2(struct audio_client *ac, int volume, int instance)
7729{
7730 return __q6asm_set_volume(ac, volume, instance);
7731}
7732
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307733/**
7734 * q6asm_set_aptx_dec_bt_addr -
7735 * command to aptx decoder BT addr for ASM
7736 *
7737 * @ac: Audio client handle
7738 * @cfg: APTX decoder bt addr config
7739 *
7740 * Returns 0 on success or error on failure
7741 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307742int q6asm_set_aptx_dec_bt_addr(struct audio_client *ac,
7743 struct aptx_dec_bt_addr_cfg *cfg)
7744{
7745 struct aptx_dec_bt_dev_addr paylod;
7746 int sz = 0;
7747 int rc = 0;
7748
7749 pr_debug("%s: BT addr nap %d, uap %d, lap %d\n", __func__, cfg->nap,
7750 cfg->uap, cfg->lap);
7751
7752 if (ac == NULL) {
7753 pr_err("%s: AC handle NULL\n", __func__);
7754 rc = -EINVAL;
7755 goto fail_cmd;
7756 }
7757 if (ac->apr == NULL) {
7758 pr_err("%s: AC APR handle NULL\n", __func__);
7759 rc = -EINVAL;
7760 goto fail_cmd;
7761 }
7762
7763 sz = sizeof(struct aptx_dec_bt_dev_addr);
7764 q6asm_add_hdr_async(ac, &paylod.hdr, sz, TRUE);
7765 atomic_set(&ac->cmd_state, -1);
7766 paylod.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
7767 paylod.encdec.param_id = APTX_DECODER_BT_ADDRESS;
7768 paylod.encdec.param_size = sz - sizeof(paylod.hdr)
7769 - sizeof(paylod.encdec);
7770 paylod.bt_addr_cfg.lap = cfg->lap;
7771 paylod.bt_addr_cfg.uap = cfg->uap;
7772 paylod.bt_addr_cfg.nap = cfg->nap;
7773
7774 rc = apr_send_pkt(ac->apr, (uint32_t *) &paylod);
7775 if (rc < 0) {
7776 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
7777 __func__, paylod.encdec.param_id, rc);
7778 rc = -EINVAL;
7779 goto fail_cmd;
7780 }
7781
7782 rc = wait_event_timeout(ac->cmd_wait,
7783 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
7784 if (!rc) {
7785 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
7786 paylod.encdec.param_id);
7787 rc = -ETIMEDOUT;
7788 goto fail_cmd;
7789 }
7790 if (atomic_read(&ac->cmd_state) > 0) {
7791 pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
7792 __func__, adsp_err_get_err_str(
7793 atomic_read(&ac->cmd_state)),
7794 paylod.encdec.param_id);
7795 rc = adsp_err_get_lnx_err_code(
7796 atomic_read(&ac->cmd_state));
7797 goto fail_cmd;
7798 }
7799 pr_debug("%s: set BT addr is success\n", __func__);
7800 rc = 0;
7801fail_cmd:
7802 return rc;
7803}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307804EXPORT_SYMBOL(q6asm_set_aptx_dec_bt_addr);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307805
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307806/**
7807 * q6asm_send_ion_fd -
7808 * command to send ION memory map for ASM
7809 *
7810 * @ac: Audio client handle
7811 * @fd: ION file desc
7812 *
7813 * Returns 0 on success or error on failure
7814 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307815int q6asm_send_ion_fd(struct audio_client *ac, int fd)
7816{
7817 struct ion_client *client;
7818 struct ion_handle *handle;
7819 ion_phys_addr_t paddr;
7820 size_t pa_len = 0;
7821 void *vaddr;
7822 int ret;
7823 int sz = 0;
7824 struct avs_rtic_shared_mem_addr shm;
7825
7826 if (ac == NULL) {
7827 pr_err("%s: APR handle NULL\n", __func__);
7828 ret = -EINVAL;
7829 goto fail_cmd;
7830 }
7831 if (ac->apr == NULL) {
7832 pr_err("%s: AC APR handle NULL\n", __func__);
7833 ret = -EINVAL;
7834 goto fail_cmd;
7835 }
7836
7837 ret = msm_audio_ion_import("audio_mem_client",
7838 &client,
7839 &handle,
7840 fd,
7841 NULL,
7842 0,
7843 &paddr,
7844 &pa_len,
7845 &vaddr);
7846 if (ret) {
7847 pr_err("%s: audio ION import failed, rc = %d\n",
7848 __func__, ret);
7849 ret = -ENOMEM;
7850 goto fail_cmd;
7851 }
7852 /* get payload length */
7853 sz = sizeof(struct avs_rtic_shared_mem_addr);
7854 q6asm_add_hdr_async(ac, &shm.hdr, sz, TRUE);
7855 atomic_set(&ac->cmd_state, -1);
7856 shm.shm_buf_addr_lsw = lower_32_bits(paddr);
7857 shm.shm_buf_addr_msw = msm_audio_populate_upper_32_bits(paddr);
7858 shm.buf_size = pa_len;
7859 shm.shm_buf_num_regions = 1;
7860 shm.shm_buf_mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
7861 shm.shm_buf_flag = 0x00;
7862 shm.encdec.param_id = AVS_PARAM_ID_RTIC_SHARED_MEMORY_ADDR;
7863 shm.encdec.param_size = sizeof(struct avs_rtic_shared_mem_addr) -
7864 sizeof(struct apr_hdr) -
7865 sizeof(struct asm_stream_cmd_set_encdec_param_v2);
7866 shm.encdec.service_id = OUT;
7867 shm.encdec.reserved = 0;
7868 shm.map_region.shm_addr_lsw = shm.shm_buf_addr_lsw;
7869 shm.map_region.shm_addr_msw = shm.shm_buf_addr_msw;
7870 shm.map_region.mem_size_bytes = pa_len;
7871 shm.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM_V2;
7872 ret = apr_send_pkt(ac->apr, (uint32_t *) &shm);
7873 if (ret < 0) {
7874 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
7875 __func__, shm.encdec.param_id, ret);
7876 ret = -EINVAL;
7877 goto fail_cmd;
7878 }
7879
7880 ret = wait_event_timeout(ac->cmd_wait,
7881 (atomic_read(&ac->cmd_state) >= 0), 1*HZ);
7882 if (!ret) {
7883 pr_err("%s: timeout, shm.encdec paramid[0x%x]\n", __func__,
7884 shm.encdec.param_id);
7885 ret = -ETIMEDOUT;
7886 goto fail_cmd;
7887 }
7888 if (atomic_read(&ac->cmd_state) > 0) {
7889 pr_err("%s: DSP returned error[%s] shm.encdec paramid[0x%x]\n",
7890 __func__,
7891 adsp_err_get_err_str(atomic_read(&ac->cmd_state)),
7892 shm.encdec.param_id);
7893 ret = adsp_err_get_lnx_err_code(atomic_read(&ac->cmd_state));
7894 goto fail_cmd;
7895 }
7896 ret = 0;
7897fail_cmd:
7898 return ret;
7899}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307900EXPORT_SYMBOL(q6asm_send_ion_fd);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307901
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307902/**
7903 * q6asm_send_rtic_event_ack -
7904 * command to send RTIC event ack
7905 *
7906 * @ac: Audio client handle
7907 * @param: params for event ack
7908 * @params_length: length of params
7909 *
7910 * Returns 0 on success or error on failure
7911 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307912int q6asm_send_rtic_event_ack(struct audio_client *ac,
7913 void *param, uint32_t params_length)
7914{
7915 char *asm_params = NULL;
7916 int sz, rc;
7917 struct avs_param_rtic_event_ack ack;
7918
7919 if (!param || !ac) {
7920 pr_err("%s: %s is NULL\n", __func__,
7921 (!param) ? "param" : "ac");
7922 rc = -EINVAL;
7923 goto done;
7924 }
7925
7926 sz = sizeof(struct avs_param_rtic_event_ack) + params_length;
7927 asm_params = kzalloc(sz, GFP_KERNEL);
7928 if (!asm_params) {
7929 rc = -ENOMEM;
7930 goto done;
7931 }
7932
7933 q6asm_add_hdr_async(ac, &ack.hdr,
7934 sizeof(struct avs_param_rtic_event_ack) +
7935 params_length, TRUE);
7936 atomic_set(&ac->cmd_state, -1);
7937 ack.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM_V2;
7938 ack.encdec.param_id = AVS_PARAM_ID_RTIC_EVENT_ACK;
7939 ack.encdec.param_size = params_length;
7940 ack.encdec.reserved = 0;
7941 ack.encdec.service_id = OUT;
7942 memcpy(asm_params, &ack, sizeof(struct avs_param_rtic_event_ack));
7943 memcpy(asm_params + sizeof(struct avs_param_rtic_event_ack),
7944 param, params_length);
7945 rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
7946 if (rc < 0) {
7947 pr_err("%s: apr pkt failed for rtic event ack\n", __func__);
7948 rc = -EINVAL;
7949 goto fail_send_param;
7950 }
7951
7952 rc = wait_event_timeout(ac->cmd_wait,
7953 (atomic_read(&ac->cmd_state) >= 0), 1 * HZ);
7954 if (!rc) {
7955 pr_err("%s: timeout for rtic event ack cmd\n", __func__);
7956 rc = -ETIMEDOUT;
7957 goto fail_send_param;
7958 }
7959
7960 if (atomic_read(&ac->cmd_state) > 0) {
7961 pr_err("%s: DSP returned error[%s] for rtic event ack cmd\n",
7962 __func__, adsp_err_get_err_str(
7963 atomic_read(&ac->cmd_state)));
7964 rc = adsp_err_get_lnx_err_code(
7965 atomic_read(&ac->cmd_state));
7966 goto fail_send_param;
7967 }
7968 rc = 0;
7969
7970fail_send_param:
7971 kfree(asm_params);
7972done:
7973 return rc;
7974}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307975EXPORT_SYMBOL(q6asm_send_rtic_event_ack);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307976
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307977/**
7978 * q6asm_set_softpause -
7979 * command to set pause for ASM
7980 *
7981 * @ac: Audio client handle
7982 * @pause_param: params for pause
7983 *
7984 * Returns 0 on success or error on failure
7985 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307986int q6asm_set_softpause(struct audio_client *ac,
7987 struct asm_softpause_params *pause_param)
7988{
7989 struct asm_soft_pause_params softpause;
7990 int sz = 0;
7991 int rc = 0;
7992
7993 if (ac == NULL) {
7994 pr_err("%s: APR handle NULL\n", __func__);
7995 rc = -EINVAL;
7996 goto fail_cmd;
7997 }
7998 if (ac->apr == NULL) {
7999 pr_err("%s: AC APR handle NULL\n", __func__);
8000 rc = -EINVAL;
8001 goto fail_cmd;
8002 }
8003
8004 sz = sizeof(struct asm_soft_pause_params);
8005 q6asm_add_hdr_async(ac, &softpause.hdr, sz, TRUE);
8006 atomic_set(&ac->cmd_state_pp, -1);
8007 softpause.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
8008
8009 softpause.param.data_payload_addr_lsw = 0;
8010 softpause.param.data_payload_addr_msw = 0;
8011 softpause.param.mem_map_handle = 0;
8012 softpause.param.data_payload_size = sizeof(softpause) -
8013 sizeof(softpause.hdr) - sizeof(softpause.param);
8014 softpause.data.module_id = ASM_MODULE_ID_VOL_CTRL;
8015 softpause.data.param_id = ASM_PARAM_ID_SOFT_PAUSE_PARAMETERS;
8016 softpause.data.param_size = softpause.param.data_payload_size -
8017 sizeof(softpause.data);
8018 softpause.data.reserved = 0;
8019 softpause.enable_flag = pause_param->enable;
8020 softpause.period = pause_param->period;
8021 softpause.step = pause_param->step;
8022 softpause.ramping_curve = pause_param->rampingcurve;
8023
8024 rc = apr_send_pkt(ac->apr, (uint32_t *) &softpause);
8025 if (rc < 0) {
8026 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
8027 __func__, softpause.data.param_id, rc);
8028 rc = -EINVAL;
8029 goto fail_cmd;
8030 }
8031
8032 rc = wait_event_timeout(ac->cmd_wait,
8033 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
8034 if (!rc) {
8035 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
8036 softpause.data.param_id);
8037 rc = -ETIMEDOUT;
8038 goto fail_cmd;
8039 }
8040 if (atomic_read(&ac->cmd_state_pp) > 0) {
8041 pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
8042 __func__, adsp_err_get_err_str(
8043 atomic_read(&ac->cmd_state_pp)),
8044 softpause.data.param_id);
8045 rc = adsp_err_get_lnx_err_code(
8046 atomic_read(&ac->cmd_state_pp));
8047 goto fail_cmd;
8048 }
8049 rc = 0;
8050fail_cmd:
8051 return rc;
8052}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308053EXPORT_SYMBOL(q6asm_set_softpause);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308054
8055static int __q6asm_set_softvolume(struct audio_client *ac,
8056 struct asm_softvolume_params *softvol_param,
8057 int instance)
8058{
8059 struct asm_soft_step_volume_params softvol;
8060 int sz = 0;
8061 int rc = 0;
8062 int module_id;
8063
8064 if (ac == NULL) {
8065 pr_err("%s: APR handle NULL\n", __func__);
8066 rc = -EINVAL;
8067 goto fail_cmd;
8068 }
8069 if (ac->apr == NULL) {
8070 pr_err("%s: AC APR handle NULL\n", __func__);
8071 rc = -EINVAL;
8072 goto fail_cmd;
8073 }
8074
8075 switch (instance) {
8076 case SOFT_VOLUME_INSTANCE_2:
8077 module_id = ASM_MODULE_ID_VOL_CTRL2;
8078 break;
8079 case SOFT_VOLUME_INSTANCE_1:
8080 default:
8081 module_id = ASM_MODULE_ID_VOL_CTRL;
8082 break;
8083 }
8084
8085 sz = sizeof(struct asm_soft_step_volume_params);
8086 q6asm_add_hdr_async(ac, &softvol.hdr, sz, TRUE);
8087 atomic_set(&ac->cmd_state_pp, -1);
8088 softvol.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
8089 softvol.param.data_payload_addr_lsw = 0;
8090 softvol.param.data_payload_addr_msw = 0;
8091 softvol.param.mem_map_handle = 0;
8092 softvol.param.data_payload_size = sizeof(softvol) -
8093 sizeof(softvol.hdr) - sizeof(softvol.param);
8094 softvol.data.module_id = module_id;
8095 softvol.data.param_id = ASM_PARAM_ID_SOFT_VOL_STEPPING_PARAMETERS;
8096 softvol.data.param_size = softvol.param.data_payload_size -
8097 sizeof(softvol.data);
8098 softvol.data.reserved = 0;
8099 softvol.period = softvol_param->period;
8100 softvol.step = softvol_param->step;
8101 softvol.ramping_curve = softvol_param->rampingcurve;
8102
8103 rc = apr_send_pkt(ac->apr, (uint32_t *) &softvol);
8104 if (rc < 0) {
8105 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
8106 __func__, softvol.data.param_id, rc);
8107 rc = -EINVAL;
8108 goto fail_cmd;
8109 }
8110
8111 rc = wait_event_timeout(ac->cmd_wait,
8112 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
8113 if (!rc) {
8114 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
8115 softvol.data.param_id);
8116 rc = -ETIMEDOUT;
8117 goto fail_cmd;
8118 }
8119 if (atomic_read(&ac->cmd_state_pp) > 0) {
8120 pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
8121 __func__, adsp_err_get_err_str(
8122 atomic_read(&ac->cmd_state_pp)),
8123 softvol.data.param_id);
8124 rc = adsp_err_get_lnx_err_code(
8125 atomic_read(&ac->cmd_state_pp));
8126 goto fail_cmd;
8127 }
8128 rc = 0;
8129fail_cmd:
8130 return rc;
8131}
8132
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308133/**
8134 * q6asm_set_softvolume -
8135 * command to set softvolume for ASM
8136 *
8137 * @ac: Audio client handle
8138 * @softvol_param: params for softvol
8139 *
8140 * Returns 0 on success or error on failure
8141 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308142int q6asm_set_softvolume(struct audio_client *ac,
8143 struct asm_softvolume_params *softvol_param)
8144{
8145 return __q6asm_set_softvolume(ac, softvol_param,
8146 SOFT_VOLUME_INSTANCE_1);
8147}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308148EXPORT_SYMBOL(q6asm_set_softvolume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308149
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308150/**
8151 * q6asm_set_softvolume_v2 -
8152 * command to set softvolume V2 for ASM
8153 *
8154 * @ac: Audio client handle
8155 * @softvol_param: params for softvol
8156 * @instance: instance to apply softvol
8157 *
8158 * Returns 0 on success or error on failure
8159 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308160int q6asm_set_softvolume_v2(struct audio_client *ac,
8161 struct asm_softvolume_params *softvol_param,
8162 int instance)
8163{
8164 return __q6asm_set_softvolume(ac, softvol_param, instance);
8165}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308166EXPORT_SYMBOL(q6asm_set_softvolume_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308167
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308168/**
8169 * q6asm_equalizer -
8170 * command to set equalizer for ASM
8171 *
8172 * @ac: Audio client handle
8173 * @eq_p: Equalizer params
8174 *
8175 * Returns 0 on success or error on failure
8176 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308177int q6asm_equalizer(struct audio_client *ac, void *eq_p)
8178{
8179 struct asm_eq_params eq;
8180 struct msm_audio_eq_stream_config *eq_params = NULL;
8181 int i = 0;
8182 int sz = 0;
8183 int rc = 0;
8184
8185 if (ac == NULL) {
8186 pr_err("%s: APR handle NULL\n", __func__);
8187 rc = -EINVAL;
8188 goto fail_cmd;
8189 }
8190 if (ac->apr == NULL) {
8191 pr_err("%s: AC APR handle NULL\n", __func__);
8192 rc = -EINVAL;
8193 goto fail_cmd;
8194 }
8195
8196 if (eq_p == NULL) {
8197 pr_err("%s: [%d]: Invalid Eq param\n", __func__, ac->session);
8198 rc = -EINVAL;
8199 goto fail_cmd;
8200 }
8201 sz = sizeof(struct asm_eq_params);
8202 eq_params = (struct msm_audio_eq_stream_config *) eq_p;
8203 q6asm_add_hdr(ac, &eq.hdr, sz, TRUE);
8204 atomic_set(&ac->cmd_state_pp, -1);
8205
8206 eq.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
8207 eq.param.data_payload_addr_lsw = 0;
8208 eq.param.data_payload_addr_msw = 0;
8209 eq.param.mem_map_handle = 0;
8210 eq.param.data_payload_size = sizeof(eq) -
8211 sizeof(eq.hdr) - sizeof(eq.param);
8212 eq.data.module_id = ASM_MODULE_ID_EQUALIZER;
8213 eq.data.param_id = ASM_PARAM_ID_EQUALIZER_PARAMETERS;
8214 eq.data.param_size = eq.param.data_payload_size - sizeof(eq.data);
8215 eq.enable_flag = eq_params->enable;
8216 eq.num_bands = eq_params->num_bands;
8217
8218 pr_debug("%s: enable:%d numbands:%d\n", __func__, eq_params->enable,
8219 eq_params->num_bands);
8220 for (i = 0; i < eq_params->num_bands; i++) {
8221 eq.eq_bands[i].band_idx =
8222 eq_params->eq_bands[i].band_idx;
8223 eq.eq_bands[i].filterype =
8224 eq_params->eq_bands[i].filter_type;
8225 eq.eq_bands[i].center_freq_hz =
8226 eq_params->eq_bands[i].center_freq_hz;
8227 eq.eq_bands[i].filter_gain =
8228 eq_params->eq_bands[i].filter_gain;
8229 eq.eq_bands[i].q_factor =
8230 eq_params->eq_bands[i].q_factor;
8231 pr_debug("%s: filter_type:%u bandnum:%d\n", __func__,
8232 eq_params->eq_bands[i].filter_type, i);
8233 pr_debug("%s: center_freq_hz:%u bandnum:%d\n", __func__,
8234 eq_params->eq_bands[i].center_freq_hz, i);
8235 pr_debug("%s: filter_gain:%d bandnum:%d\n", __func__,
8236 eq_params->eq_bands[i].filter_gain, i);
8237 pr_debug("%s: q_factor:%d bandnum:%d\n", __func__,
8238 eq_params->eq_bands[i].q_factor, i);
8239 }
8240 rc = apr_send_pkt(ac->apr, (uint32_t *)&eq);
8241 if (rc < 0) {
8242 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
8243 __func__, eq.data.param_id, rc);
8244 rc = -EINVAL;
8245 goto fail_cmd;
8246 }
8247
8248 rc = wait_event_timeout(ac->cmd_wait,
8249 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
8250 if (!rc) {
8251 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
8252 eq.data.param_id);
8253 rc = -ETIMEDOUT;
8254 goto fail_cmd;
8255 }
8256 if (atomic_read(&ac->cmd_state_pp) > 0) {
8257 pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
8258 __func__, adsp_err_get_err_str(
8259 atomic_read(&ac->cmd_state_pp)),
8260 eq.data.param_id);
8261 rc = adsp_err_get_lnx_err_code(
8262 atomic_read(&ac->cmd_state_pp));
8263 goto fail_cmd;
8264 }
8265 rc = 0;
8266fail_cmd:
8267 return rc;
8268}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308269EXPORT_SYMBOL(q6asm_equalizer);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308270
8271static int __q6asm_read(struct audio_client *ac, bool is_custom_len_reqd,
8272 int len)
8273{
8274 struct asm_data_cmd_read_v2 read;
8275 struct asm_buffer_node *buf_node = NULL;
8276 struct list_head *ptr, *next;
8277 struct audio_buffer *ab;
8278 int dsp_buf;
8279 struct audio_port_data *port;
8280 int rc;
8281
8282 if (ac == NULL) {
8283 pr_err("%s: APR handle NULL\n", __func__);
8284 return -EINVAL;
8285 }
8286 if (ac->apr == NULL) {
8287 pr_err("%s: AC APR handle NULL\n", __func__);
8288 return -EINVAL;
8289 }
8290
8291 if (ac->io_mode & SYNC_IO_MODE) {
8292 port = &ac->port[OUT];
8293
8294 q6asm_add_hdr(ac, &read.hdr, sizeof(read), FALSE);
8295
8296 mutex_lock(&port->lock);
8297
8298 dsp_buf = port->dsp_buf;
8299 if (port->buf == NULL) {
8300 pr_err("%s: buf is NULL\n", __func__);
8301 mutex_unlock(&port->lock);
8302 return -EINVAL;
8303 }
8304 ab = &port->buf[dsp_buf];
8305
8306 dev_vdbg(ac->dev, "%s: session[%d]dsp-buf[%d][%pK]cpu_buf[%d][%pK]\n",
8307 __func__,
8308 ac->session,
8309 dsp_buf,
8310 port->buf[dsp_buf].data,
8311 port->cpu_buf,
8312 &port->buf[port->cpu_buf].phys);
8313
8314 read.hdr.opcode = ASM_DATA_CMD_READ_V2;
8315 read.buf_addr_lsw = lower_32_bits(ab->phys);
8316 read.buf_addr_msw = msm_audio_populate_upper_32_bits(ab->phys);
8317
8318 list_for_each_safe(ptr, next, &ac->port[OUT].mem_map_handle) {
8319 buf_node = list_entry(ptr, struct asm_buffer_node,
8320 list);
Vignesh Kulothunganc894ac42018-01-04 13:49:12 -08008321 if (buf_node->buf_phys_addr == ab->phys) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308322 read.mem_map_handle = buf_node->mmap_hdl;
Vignesh Kulothunganc894ac42018-01-04 13:49:12 -08008323 break;
8324 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308325 }
8326 dev_vdbg(ac->dev, "memory_map handle in q6asm_read: [%0x]:",
8327 read.mem_map_handle);
8328 read.buf_size = is_custom_len_reqd ? len : ab->size;
8329 read.seq_id = port->dsp_buf;
8330 q6asm_update_token(&read.hdr.token,
8331 0, /* Session ID is NA */
8332 0, /* Stream ID is NA */
8333 port->dsp_buf,
8334 0, /* Direction flag is NA */
8335 WAIT_CMD);
8336 port->dsp_buf = q6asm_get_next_buf(ac, port->dsp_buf,
8337 port->max_buf_cnt);
8338 mutex_unlock(&port->lock);
8339 dev_vdbg(ac->dev, "%s: buf add[%pK] token[0x%x] uid[%d]\n",
8340 __func__, &ab->phys, read.hdr.token,
8341 read.seq_id);
8342 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
8343 if (rc < 0) {
8344 pr_err("%s: read op[0x%x]rc[%d]\n",
8345 __func__, read.hdr.opcode, rc);
8346 goto fail_cmd;
8347 }
8348 return 0;
8349 }
8350fail_cmd:
8351 return -EINVAL;
8352}
8353
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308354/**
8355 * q6asm_read -
8356 * command to read buffer data from DSP
8357 *
8358 * @ac: Audio client handle
8359 *
8360 * Returns 0 on success or error on failure
8361 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308362int q6asm_read(struct audio_client *ac)
8363{
8364 return __q6asm_read(ac, false/*is_custom_len_reqd*/, 0);
8365}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308366EXPORT_SYMBOL(q6asm_read);
8367
8368
8369/**
8370 * q6asm_read_v2 -
8371 * command to read buffer data from DSP
8372 *
8373 * @ac: Audio client handle
8374 * @len: buffer size to read
8375 *
8376 * Returns 0 on success or error on failure
8377 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308378int q6asm_read_v2(struct audio_client *ac, uint32_t len)
8379{
8380 return __q6asm_read(ac, true /*is_custom_len_reqd*/, len);
8381}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308382EXPORT_SYMBOL(q6asm_read_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308383
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308384/**
8385 * q6asm_read_nolock -
8386 * command to read buffer data from DSP
8387 * with no wait for ack.
8388 *
8389 * @ac: Audio client handle
8390 *
8391 * Returns 0 on success or error on failure
8392 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308393int q6asm_read_nolock(struct audio_client *ac)
8394{
8395 struct asm_data_cmd_read_v2 read;
8396 struct asm_buffer_node *buf_node = NULL;
8397 struct list_head *ptr, *next;
8398 struct audio_buffer *ab;
8399 int dsp_buf;
8400 struct audio_port_data *port;
8401 int rc;
8402
8403 if (ac == NULL) {
8404 pr_err("%s: APR handle NULL\n", __func__);
8405 return -EINVAL;
8406 }
8407 if (ac->apr == NULL) {
8408 pr_err("%s: AC APR handle NULL\n", __func__);
8409 return -EINVAL;
8410 }
8411
8412 if (ac->io_mode & SYNC_IO_MODE) {
8413 port = &ac->port[OUT];
8414
8415 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
8416
8417
8418 dsp_buf = port->dsp_buf;
8419 ab = &port->buf[dsp_buf];
8420
8421 dev_vdbg(ac->dev, "%s: session[%d]dsp-buf[%d][%pK]cpu_buf[%d][%pK]\n",
8422 __func__,
8423 ac->session,
8424 dsp_buf,
8425 port->buf[dsp_buf].data,
8426 port->cpu_buf,
8427 &port->buf[port->cpu_buf].phys);
8428
8429 read.hdr.opcode = ASM_DATA_CMD_READ_V2;
8430 read.buf_addr_lsw = lower_32_bits(ab->phys);
8431 read.buf_addr_msw = msm_audio_populate_upper_32_bits(ab->phys);
8432 read.buf_size = ab->size;
8433 read.seq_id = port->dsp_buf;
8434 q6asm_update_token(&read.hdr.token,
8435 0, /* Session ID is NA */
8436 0, /* Stream ID is NA */
8437 port->dsp_buf,
8438 0, /* Direction flag is NA */
8439 WAIT_CMD);
8440
8441 list_for_each_safe(ptr, next, &ac->port[OUT].mem_map_handle) {
8442 buf_node = list_entry(ptr, struct asm_buffer_node,
8443 list);
8444 if (buf_node->buf_phys_addr == ab->phys) {
8445 read.mem_map_handle = buf_node->mmap_hdl;
8446 break;
8447 }
8448 }
8449
8450 port->dsp_buf = q6asm_get_next_buf(ac, port->dsp_buf,
8451 port->max_buf_cnt);
8452 dev_vdbg(ac->dev, "%s: buf add[%pK] token[0x%x] uid[%d]\n",
8453 __func__, &ab->phys, read.hdr.token,
8454 read.seq_id);
8455 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
8456 if (rc < 0) {
8457 pr_err("%s: read op[0x%x]rc[%d]\n",
8458 __func__, read.hdr.opcode, rc);
8459 goto fail_cmd;
8460 }
8461 return 0;
8462 }
8463fail_cmd:
8464 return -EINVAL;
8465}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308466EXPORT_SYMBOL(q6asm_read_nolock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308467
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308468/**
8469 * q6asm_async_write -
8470 * command to write DSP buffer
8471 *
8472 * @ac: Audio client handle
8473 * @param: params for async write
8474 *
8475 * Returns 0 on success or error on failure
8476 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308477int q6asm_async_write(struct audio_client *ac,
8478 struct audio_aio_write_param *param)
8479{
8480 int rc = 0;
8481 struct asm_data_cmd_write_v2 write;
8482 struct asm_buffer_node *buf_node = NULL;
8483 struct list_head *ptr, *next;
8484 struct audio_buffer *ab;
8485 struct audio_port_data *port;
8486 phys_addr_t lbuf_phys_addr;
8487 u32 liomode;
8488 u32 io_compressed;
8489 u32 io_compressed_stream;
8490
8491 if (ac == NULL) {
8492 pr_err("%s: APR handle NULL\n", __func__);
8493 return -EINVAL;
8494 }
8495 if (ac->apr == NULL) {
8496 pr_err("%s: AC APR handle NULL\n", __func__);
8497 return -EINVAL;
8498 }
8499
8500 q6asm_stream_add_hdr_async(
8501 ac, &write.hdr, sizeof(write), TRUE, ac->stream_id);
8502 port = &ac->port[IN];
8503 ab = &port->buf[port->dsp_buf];
8504
8505 /* Pass session id as token for AIO scheme */
8506 write.hdr.token = param->uid;
8507 write.hdr.opcode = ASM_DATA_CMD_WRITE_V2;
8508 write.buf_addr_lsw = lower_32_bits(param->paddr);
8509 write.buf_addr_msw = msm_audio_populate_upper_32_bits(param->paddr);
8510 write.buf_size = param->len;
8511 write.timestamp_msw = param->msw_ts;
8512 write.timestamp_lsw = param->lsw_ts;
8513 liomode = (ASYNC_IO_MODE | NT_MODE);
8514 io_compressed = (ASYNC_IO_MODE | COMPRESSED_IO);
8515 io_compressed_stream = (ASYNC_IO_MODE | COMPRESSED_STREAM_IO);
8516
8517 if (ac->io_mode == liomode)
8518 lbuf_phys_addr = (param->paddr - 32);
8519 else if (ac->io_mode == io_compressed ||
8520 ac->io_mode == io_compressed_stream)
8521 lbuf_phys_addr = (param->paddr - param->metadata_len);
8522 else {
8523 if (param->flags & SET_TIMESTAMP)
8524 lbuf_phys_addr = param->paddr -
8525 sizeof(struct snd_codec_metadata);
8526 else
8527 lbuf_phys_addr = param->paddr;
8528 }
8529 dev_vdbg(ac->dev, "%s: token[0x%x], buf_addr[%pK], buf_size[0x%x], ts_msw[0x%x], ts_lsw[0x%x], lbuf_phys_addr: 0x[%pK]\n",
8530 __func__,
8531 write.hdr.token, &param->paddr,
8532 write.buf_size, write.timestamp_msw,
8533 write.timestamp_lsw, &lbuf_phys_addr);
8534
8535 /* Use 0xFF00 for disabling timestamps */
8536 if (param->flags == 0xFF00)
8537 write.flags = (0x00000000 | (param->flags & 0x800000FF));
8538 else
8539 write.flags = (0x80000000 | param->flags);
8540 write.flags |= param->last_buffer << ASM_SHIFT_LAST_BUFFER_FLAG;
8541 write.seq_id = param->uid;
8542 list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) {
8543 buf_node = list_entry(ptr, struct asm_buffer_node,
8544 list);
8545 if (buf_node->buf_phys_addr == lbuf_phys_addr) {
8546 write.mem_map_handle = buf_node->mmap_hdl;
8547 break;
8548 }
8549 }
8550
8551 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
8552 if (rc < 0) {
8553 pr_err("%s: write op[0x%x]rc[%d]\n", __func__,
8554 write.hdr.opcode, rc);
8555 goto fail_cmd;
8556 }
8557 return 0;
8558fail_cmd:
8559 return -EINVAL;
8560}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308561EXPORT_SYMBOL(q6asm_async_write);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308562
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308563/**
8564 * q6asm_async_read -
8565 * command to read DSP buffer
8566 *
8567 * @ac: Audio client handle
8568 * @param: params for async read
8569 *
8570 * Returns 0 on success or error on failure
8571 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308572int q6asm_async_read(struct audio_client *ac,
8573 struct audio_aio_read_param *param)
8574{
8575 int rc = 0;
8576 struct asm_data_cmd_read_v2 read;
8577 struct asm_buffer_node *buf_node = NULL;
8578 struct list_head *ptr, *next;
8579 phys_addr_t lbuf_phys_addr;
8580 u32 liomode;
8581 u32 io_compressed;
8582 int dir = 0;
8583
8584 if (ac == NULL) {
8585 pr_err("%s: APR handle NULL\n", __func__);
8586 return -EINVAL;
8587 }
8588 if (ac->apr == NULL) {
8589 pr_err("%s: AC APR handle NULL\n", __func__);
8590 return -EINVAL;
8591 }
8592
8593 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
8594
8595 /* Pass session id as token for AIO scheme */
8596 read.hdr.token = param->uid;
8597 read.hdr.opcode = ASM_DATA_CMD_READ_V2;
8598 read.buf_addr_lsw = lower_32_bits(param->paddr);
8599 read.buf_addr_msw = msm_audio_populate_upper_32_bits(param->paddr);
8600 read.buf_size = param->len;
8601 read.seq_id = param->uid;
8602 liomode = (NT_MODE | ASYNC_IO_MODE);
8603 io_compressed = (ASYNC_IO_MODE | COMPRESSED_IO);
8604 if (ac->io_mode == liomode) {
8605 lbuf_phys_addr = (param->paddr - 32);
8606 /*legacy wma driver case*/
8607 dir = IN;
8608 } else if (ac->io_mode == io_compressed) {
8609 lbuf_phys_addr = (param->paddr - 64);
8610 dir = OUT;
8611 } else {
8612 if (param->flags & COMPRESSED_TIMESTAMP_FLAG)
8613 lbuf_phys_addr = param->paddr -
8614 sizeof(struct snd_codec_metadata);
8615 else
8616 lbuf_phys_addr = param->paddr;
8617 dir = OUT;
8618 }
8619
8620 list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
8621 buf_node = list_entry(ptr, struct asm_buffer_node,
8622 list);
8623 if (buf_node->buf_phys_addr == lbuf_phys_addr) {
8624 read.mem_map_handle = buf_node->mmap_hdl;
8625 break;
8626 }
8627 }
8628
8629 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
8630 if (rc < 0) {
8631 pr_err("%s: read op[0x%x]rc[%d]\n", __func__,
8632 read.hdr.opcode, rc);
8633 goto fail_cmd;
8634 }
8635 return 0;
8636fail_cmd:
8637 return -EINVAL;
8638}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308639EXPORT_SYMBOL(q6asm_async_read);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308640
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308641/**
8642 * q6asm_write -
8643 * command to write buffer data to DSP
8644 *
8645 * @ac: Audio client handle
8646 * @len: buffer size
8647 * @msw_ts: upper 32bits of timestamp
8648 * @lsw_ts: lower 32bits of timestamp
8649 * @flags: Flags for timestamp mode
8650 *
8651 * Returns 0 on success or error on failure
8652 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308653int q6asm_write(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
8654 uint32_t lsw_ts, uint32_t flags)
8655{
8656 int rc = 0;
8657 struct asm_data_cmd_write_v2 write;
8658 struct asm_buffer_node *buf_node = NULL;
8659 struct audio_port_data *port;
8660 struct audio_buffer *ab;
8661 int dsp_buf = 0;
8662
8663 if (ac == NULL) {
8664 pr_err("%s: APR handle NULL\n", __func__);
8665 return -EINVAL;
8666 }
8667 if (ac->apr == NULL) {
8668 pr_err("%s: AC APR handle NULL\n", __func__);
8669 return -EINVAL;
8670 }
8671
8672 dev_vdbg(ac->dev, "%s: session[%d] len=%d\n",
8673 __func__, ac->session, len);
8674 if (ac->io_mode & SYNC_IO_MODE) {
8675 port = &ac->port[IN];
8676
8677 q6asm_add_hdr(ac, &write.hdr, sizeof(write),
8678 FALSE);
8679 mutex_lock(&port->lock);
8680
8681 dsp_buf = port->dsp_buf;
8682 ab = &port->buf[dsp_buf];
8683
8684 q6asm_update_token(&write.hdr.token,
8685 0, /* Session ID is NA */
8686 0, /* Stream ID is NA */
8687 port->dsp_buf,
8688 0, /* Direction flag is NA */
8689 NO_WAIT_CMD);
8690 write.hdr.opcode = ASM_DATA_CMD_WRITE_V2;
8691 write.buf_addr_lsw = lower_32_bits(ab->phys);
8692 write.buf_addr_msw = msm_audio_populate_upper_32_bits(ab->phys);
8693 write.buf_size = len;
8694 write.seq_id = port->dsp_buf;
8695 write.timestamp_lsw = lsw_ts;
8696 write.timestamp_msw = msw_ts;
8697 /* Use 0xFF00 for disabling timestamps */
8698 if (flags == 0xFF00)
8699 write.flags = (0x00000000 | (flags & 0x800000FF));
8700 else
8701 write.flags = (0x80000000 | flags);
8702 port->dsp_buf = q6asm_get_next_buf(ac, port->dsp_buf,
8703 port->max_buf_cnt);
8704 buf_node = list_first_entry(&ac->port[IN].mem_map_handle,
8705 struct asm_buffer_node,
8706 list);
8707 write.mem_map_handle = buf_node->mmap_hdl;
8708
8709 dev_vdbg(ac->dev, "%s: ab->phys[%pK]bufadd[0x%x] token[0x%x]buf_id[0x%x]buf_size[0x%x]mmaphdl[0x%x]"
8710 , __func__,
8711 &ab->phys,
8712 write.buf_addr_lsw,
8713 write.hdr.token,
8714 write.seq_id,
8715 write.buf_size,
8716 write.mem_map_handle);
8717 mutex_unlock(&port->lock);
8718
8719 config_debug_fs_write(ab);
8720
8721 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
8722 if (rc < 0) {
8723 pr_err("%s: write op[0x%x]rc[%d]\n",
8724 __func__, write.hdr.opcode, rc);
8725 goto fail_cmd;
8726 }
8727 return 0;
8728 }
8729fail_cmd:
8730 return -EINVAL;
8731}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308732EXPORT_SYMBOL(q6asm_write);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308733
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308734/**
8735 * q6asm_write_nolock -
8736 * command to write buffer data to DSP
8737 * with no wait for ack.
8738 *
8739 * @ac: Audio client handle
8740 * @len: buffer size
8741 * @msw_ts: upper 32bits of timestamp
8742 * @lsw_ts: lower 32bits of timestamp
8743 * @flags: Flags for timestamp mode
8744 *
8745 * Returns 0 on success or error on failure
8746 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308747int q6asm_write_nolock(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
8748 uint32_t lsw_ts, uint32_t flags)
8749{
8750 int rc = 0;
8751 struct asm_data_cmd_write_v2 write;
8752 struct asm_buffer_node *buf_node = NULL;
8753 struct audio_port_data *port;
8754 struct audio_buffer *ab;
8755 int dsp_buf = 0;
8756
8757 if (ac == NULL) {
8758 pr_err("%s: APR handle NULL\n", __func__);
8759 return -EINVAL;
8760 }
8761 if (ac->apr == NULL) {
8762 pr_err("%s: AC APR handle NULL\n", __func__);
8763 return -EINVAL;
8764 }
8765
8766 dev_vdbg(ac->dev, "%s: session[%d] len=%d\n",
8767 __func__, ac->session, len);
8768 if (ac->io_mode & SYNC_IO_MODE) {
8769 port = &ac->port[IN];
8770
8771 q6asm_add_hdr_async(ac, &write.hdr, sizeof(write),
8772 FALSE);
8773
8774 dsp_buf = port->dsp_buf;
8775 ab = &port->buf[dsp_buf];
8776
8777 q6asm_update_token(&write.hdr.token,
8778 0, /* Session ID is NA */
8779 0, /* Stream ID is NA */
8780 port->dsp_buf,
8781 0, /* Direction flag is NA */
8782 NO_WAIT_CMD);
8783
8784 write.hdr.opcode = ASM_DATA_CMD_WRITE_V2;
8785 write.buf_addr_lsw = lower_32_bits(ab->phys);
8786 write.buf_addr_msw = msm_audio_populate_upper_32_bits(ab->phys);
8787 write.buf_size = len;
8788 write.seq_id = port->dsp_buf;
8789 write.timestamp_lsw = lsw_ts;
8790 write.timestamp_msw = msw_ts;
8791 buf_node = list_first_entry(&ac->port[IN].mem_map_handle,
8792 struct asm_buffer_node,
8793 list);
8794 write.mem_map_handle = buf_node->mmap_hdl;
8795 /* Use 0xFF00 for disabling timestamps */
8796 if (flags == 0xFF00)
8797 write.flags = (0x00000000 | (flags & 0x800000FF));
8798 else
8799 write.flags = (0x80000000 | flags);
8800 port->dsp_buf = q6asm_get_next_buf(ac, port->dsp_buf,
8801 port->max_buf_cnt);
8802
8803 dev_vdbg(ac->dev, "%s: ab->phys[%pK]bufadd[0x%x]token[0x%x] buf_id[0x%x]buf_size[0x%x]mmaphdl[0x%x]"
8804 , __func__,
8805 &ab->phys,
8806 write.buf_addr_lsw,
8807 write.hdr.token,
8808 write.seq_id,
8809 write.buf_size,
8810 write.mem_map_handle);
8811
8812 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
8813 if (rc < 0) {
8814 pr_err("%s: write op[0x%x]rc[%d]\n",
8815 __func__, write.hdr.opcode, rc);
8816 goto fail_cmd;
8817 }
8818 return 0;
8819 }
8820fail_cmd:
8821 return -EINVAL;
8822}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308823EXPORT_SYMBOL(q6asm_write_nolock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308824
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308825/**
8826 * q6asm_get_session_time -
8827 * command to retrieve timestamp info
8828 *
8829 * @ac: Audio client handle
8830 * @tstamp: pointer to fill with timestamp info
8831 *
8832 * Returns 0 on success or error on failure
8833 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308834int q6asm_get_session_time(struct audio_client *ac, uint64_t *tstamp)
8835{
8836 struct asm_mtmx_strtr_get_params mtmx_params;
8837 int rc;
8838
8839 if (ac == NULL) {
8840 pr_err("%s: APR handle NULL\n", __func__);
8841 return -EINVAL;
8842 }
8843 if (ac->apr == NULL) {
8844 pr_err("%s: AC APR handle NULL\n", __func__);
8845 return -EINVAL;
8846 }
8847 if (tstamp == NULL) {
8848 pr_err("%s: tstamp NULL\n", __func__);
8849 return -EINVAL;
8850 }
8851
8852 q6asm_add_hdr(ac, &mtmx_params.hdr, sizeof(mtmx_params), TRUE);
8853 mtmx_params.hdr.opcode = ASM_SESSION_CMD_GET_MTMX_STRTR_PARAMS_V2;
8854 mtmx_params.param_info.data_payload_addr_lsw = 0;
8855 mtmx_params.param_info.data_payload_addr_msw = 0;
8856 mtmx_params.param_info.mem_map_handle = 0;
8857 mtmx_params.param_info.direction = (ac->io_mode & TUN_READ_IO_MODE
8858 ? 1 : 0);
8859 mtmx_params.param_info.module_id =
8860 ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
8861 mtmx_params.param_info.param_id =
8862 ASM_SESSION_MTMX_STRTR_PARAM_SESSION_TIME_V3;
8863 mtmx_params.param_info.param_max_size =
8864 sizeof(struct asm_stream_param_data_v2) +
8865 sizeof(struct asm_session_mtmx_strtr_param_session_time_v3_t);
8866 atomic_set(&ac->time_flag, 1);
8867
8868 dev_vdbg(ac->dev, "%s: session[%d]opcode[0x%x]\n", __func__,
8869 ac->session, mtmx_params.hdr.opcode);
8870 rc = apr_send_pkt(ac->apr, (uint32_t *) &mtmx_params);
8871 if (rc < 0) {
8872 pr_err("%s: Commmand 0x%x failed %d\n", __func__,
8873 mtmx_params.hdr.opcode, rc);
8874 goto fail_cmd;
8875 }
8876 rc = wait_event_timeout(ac->time_wait,
8877 (atomic_read(&ac->time_flag) == 0), 5*HZ);
8878 if (!rc) {
8879 pr_err("%s: timeout in getting session time from DSP\n",
8880 __func__);
8881 goto fail_cmd;
8882 }
8883
8884 *tstamp = ac->time_stamp;
8885 return 0;
8886
8887fail_cmd:
8888 return -EINVAL;
8889}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308890EXPORT_SYMBOL(q6asm_get_session_time);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308891
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308892/**
8893 * q6asm_get_session_time_legacy -
8894 * command to retrieve timestamp info
8895 *
8896 * @ac: Audio client handle
8897 * @tstamp: pointer to fill with timestamp info
8898 *
8899 * Returns 0 on success or error on failure
8900 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308901int q6asm_get_session_time_legacy(struct audio_client *ac, uint64_t *tstamp)
8902{
8903 struct apr_hdr hdr;
8904 int rc;
8905
8906 if (ac == NULL) {
8907 pr_err("%s: APR handle NULL\n", __func__);
8908 return -EINVAL;
8909 }
8910 if (ac->apr == NULL) {
8911 pr_err("%s: AC APR handle NULL\n", __func__);
8912 return -EINVAL;
8913 }
8914 if (tstamp == NULL) {
8915 pr_err("%s: tstamp NULL\n", __func__);
8916 return -EINVAL;
8917 }
8918
8919 q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
8920 hdr.opcode = ASM_SESSION_CMD_GET_SESSIONTIME_V3;
8921 atomic_set(&ac->time_flag, 1);
8922
8923 dev_vdbg(ac->dev, "%s: session[%d]opcode[0x%x]\n", __func__,
8924 ac->session,
8925 hdr.opcode);
8926 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
8927 if (rc < 0) {
8928 pr_err("%s: Commmand 0x%x failed %d\n",
8929 __func__, hdr.opcode, rc);
8930 goto fail_cmd;
8931 }
8932 rc = wait_event_timeout(ac->time_wait,
8933 (atomic_read(&ac->time_flag) == 0), 5*HZ);
8934 if (!rc) {
8935 pr_err("%s: timeout in getting session time from DSP\n",
8936 __func__);
8937 goto fail_cmd;
8938 }
8939
8940 *tstamp = ac->time_stamp;
8941 return 0;
8942
8943fail_cmd:
8944 return -EINVAL;
8945}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308946EXPORT_SYMBOL(q6asm_get_session_time_legacy);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308947
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308948/**
8949 * q6asm_send_audio_effects_params -
8950 * command to send audio effects params
8951 *
8952 * @ac: Audio client handle
8953 * @params: audio effects params
8954 * @params_length: size of params
8955 *
8956 * Returns 0 on success or error on failure
8957 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308958int q6asm_send_audio_effects_params(struct audio_client *ac, char *params,
8959 uint32_t params_length)
8960{
8961 char *asm_params = NULL;
8962 struct apr_hdr hdr;
8963 struct asm_stream_cmd_set_pp_params_v2 payload_params;
8964 int sz, rc;
8965
8966 pr_debug("%s:\n", __func__);
8967 if (!ac) {
8968 pr_err("%s: APR handle NULL\n", __func__);
8969 return -EINVAL;
8970 }
8971 if (ac->apr == NULL) {
8972 pr_err("%s: AC APR handle NULL\n", __func__);
8973 return -EINVAL;
8974 }
8975 if (params == NULL) {
8976 pr_err("%s: params NULL\n", __func__);
8977 return -EINVAL;
8978 }
8979 sz = sizeof(struct apr_hdr) +
8980 sizeof(struct asm_stream_cmd_set_pp_params_v2) +
8981 params_length;
8982 asm_params = kzalloc(sz, GFP_KERNEL);
8983 if (!asm_params) {
8984 pr_err("%s, asm params memory alloc failed", __func__);
8985 return -ENOMEM;
8986 }
8987 q6asm_add_hdr_async(ac, &hdr, (sizeof(struct apr_hdr) +
8988 sizeof(struct asm_stream_cmd_set_pp_params_v2) +
8989 params_length), TRUE);
8990 atomic_set(&ac->cmd_state_pp, -1);
8991 hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
8992 payload_params.data_payload_addr_lsw = 0;
8993 payload_params.data_payload_addr_msw = 0;
8994 payload_params.mem_map_handle = 0;
8995 payload_params.data_payload_size = params_length;
8996 memcpy(((u8 *)asm_params), &hdr, sizeof(struct apr_hdr));
8997 memcpy(((u8 *)asm_params + sizeof(struct apr_hdr)), &payload_params,
8998 sizeof(struct asm_stream_cmd_set_pp_params_v2));
8999 memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) +
9000 sizeof(struct asm_stream_cmd_set_pp_params_v2)),
9001 params, params_length);
9002 rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
9003 if (rc < 0) {
9004 pr_err("%s: audio effects set-params send failed\n", __func__);
9005 rc = -EINVAL;
9006 goto fail_send_param;
9007 }
9008 rc = wait_event_timeout(ac->cmd_wait,
9009 (atomic_read(&ac->cmd_state_pp) >= 0), 1*HZ);
9010 if (!rc) {
9011 pr_err("%s: timeout, audio effects set-params\n", __func__);
9012 rc = -ETIMEDOUT;
9013 goto fail_send_param;
9014 }
9015 if (atomic_read(&ac->cmd_state_pp) > 0) {
9016 pr_err("%s: DSP returned error[%s] set-params\n",
9017 __func__, adsp_err_get_err_str(
9018 atomic_read(&ac->cmd_state_pp)));
9019 rc = adsp_err_get_lnx_err_code(
9020 atomic_read(&ac->cmd_state_pp));
9021 goto fail_send_param;
9022 }
9023
9024 rc = 0;
9025fail_send_param:
9026 kfree(asm_params);
9027 return rc;
9028}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309029EXPORT_SYMBOL(q6asm_send_audio_effects_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309030
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309031/**
9032 * q6asm_send_mtmx_strtr_window -
9033 * command to send matrix for window params
9034 *
9035 * @ac: Audio client handle
9036 * @window_param: window params
9037 * @param_id: param id for window
9038 *
9039 * Returns 0 on success or error on failure
9040 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309041int q6asm_send_mtmx_strtr_window(struct audio_client *ac,
9042 struct asm_session_mtmx_strtr_param_window_v2_t *window_param,
9043 uint32_t param_id)
9044{
9045 struct asm_mtmx_strtr_params matrix;
9046 int sz = 0;
9047 int rc = 0;
9048
9049 pr_debug("%s: Window lsw is %d, window msw is %d\n", __func__,
9050 window_param->window_lsw, window_param->window_msw);
9051
9052 if (!ac) {
9053 pr_err("%s: audio client handle is NULL\n", __func__);
9054 rc = -EINVAL;
9055 goto fail_cmd;
9056 }
9057
9058 if (ac->apr == NULL) {
9059 pr_err("%s: ac->apr is NULL", __func__);
9060 rc = -EINVAL;
9061 goto fail_cmd;
9062 }
9063
9064 sz = sizeof(struct asm_mtmx_strtr_params);
9065 q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE);
9066 atomic_set(&ac->cmd_state, -1);
9067 matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2;
9068
9069 matrix.param.data_payload_addr_lsw = 0;
9070 matrix.param.data_payload_addr_msw = 0;
9071 matrix.param.mem_map_handle = 0;
9072 matrix.param.data_payload_size =
9073 sizeof(struct asm_stream_param_data_v2) +
9074 sizeof(struct asm_session_mtmx_strtr_param_window_v2_t);
9075 matrix.param.direction = 0; /* RX */
9076 matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
9077 matrix.data.param_id = param_id;
9078 matrix.data.param_size =
9079 sizeof(struct asm_session_mtmx_strtr_param_window_v2_t);
9080 matrix.data.reserved = 0;
9081 memcpy(&(matrix.config.window_param),
9082 window_param,
9083 sizeof(struct asm_session_mtmx_strtr_param_window_v2_t));
9084
9085 rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
9086 if (rc < 0) {
9087 pr_err("%s: Render window start send failed paramid [0x%x]\n",
9088 __func__, matrix.data.param_id);
9089 rc = -EINVAL;
9090 goto fail_cmd;
9091 }
9092
9093 rc = wait_event_timeout(ac->cmd_wait,
9094 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
9095 if (!rc) {
9096 pr_err("%s: timeout, Render window start paramid[0x%x]\n",
9097 __func__, matrix.data.param_id);
9098 rc = -ETIMEDOUT;
9099 goto fail_cmd;
9100 }
9101
9102 if (atomic_read(&ac->cmd_state) > 0) {
9103 pr_err("%s: DSP returned error[%s]\n",
9104 __func__, adsp_err_get_err_str(
9105 atomic_read(&ac->cmd_state)));
9106 rc = adsp_err_get_lnx_err_code(
9107 atomic_read(&ac->cmd_state));
9108 goto fail_cmd;
9109 }
9110 rc = 0;
9111fail_cmd:
9112 return rc;
9113}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309114EXPORT_SYMBOL(q6asm_send_mtmx_strtr_window);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309115
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309116/**
9117 * q6asm_send_mtmx_strtr_render_mode -
9118 * command to send matrix for render mode
9119 *
9120 * @ac: Audio client handle
9121 * @render_mode: rendering mode
9122 *
9123 * Returns 0 on success or error on failure
9124 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309125int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac,
9126 uint32_t render_mode)
9127{
9128 struct asm_mtmx_strtr_params matrix;
9129 struct asm_session_mtmx_strtr_param_render_mode_t render_param;
9130 int sz = 0;
9131 int rc = 0;
9132
9133 pr_debug("%s: render mode is %d\n", __func__, render_mode);
9134
9135 if (!ac) {
9136 pr_err("%s: audio client handle is NULL\n", __func__);
9137 rc = -EINVAL;
9138 goto exit;
9139 }
9140
9141 if (ac->apr == NULL) {
9142 pr_err("%s: ac->apr is NULL\n", __func__);
9143 rc = -EINVAL;
9144 goto exit;
9145 }
9146
9147 if ((render_mode != ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT) &&
9148 (render_mode != ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC)) {
9149 pr_err("%s: Invalid render mode %d\n", __func__, render_mode);
9150 rc = -EINVAL;
9151 goto exit;
9152 }
9153
9154 memset(&render_param, 0,
9155 sizeof(struct asm_session_mtmx_strtr_param_render_mode_t));
9156 render_param.flags = render_mode;
9157
9158 memset(&matrix, 0, sizeof(struct asm_mtmx_strtr_params));
9159 sz = sizeof(struct asm_mtmx_strtr_params);
9160 q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE);
9161 atomic_set(&ac->cmd_state, -1);
9162 matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2;
9163
9164 matrix.param.data_payload_addr_lsw = 0;
9165 matrix.param.data_payload_addr_msw = 0;
9166 matrix.param.mem_map_handle = 0;
9167 matrix.param.data_payload_size =
9168 sizeof(struct asm_stream_param_data_v2) +
9169 sizeof(struct asm_session_mtmx_strtr_param_render_mode_t);
9170 matrix.param.direction = 0; /* RX */
9171 matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
9172 matrix.data.param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_MODE_CMD;
9173 matrix.data.param_size =
9174 sizeof(struct asm_session_mtmx_strtr_param_render_mode_t);
9175 matrix.data.reserved = 0;
9176 memcpy(&(matrix.config.render_param),
9177 &render_param,
9178 sizeof(struct asm_session_mtmx_strtr_param_render_mode_t));
9179
9180 rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
9181 if (rc < 0) {
9182 pr_err("%s: Render mode send failed paramid [0x%x]\n",
9183 __func__, matrix.data.param_id);
9184 rc = -EINVAL;
9185 goto exit;
9186 }
9187
9188 rc = wait_event_timeout(ac->cmd_wait,
9189 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
9190 if (!rc) {
9191 pr_err("%s: timeout, Render mode send paramid [0x%x]\n",
9192 __func__, matrix.data.param_id);
9193 rc = -ETIMEDOUT;
9194 goto exit;
9195 }
9196
9197 if (atomic_read(&ac->cmd_state) > 0) {
9198 pr_err("%s: DSP returned error[%s]\n",
9199 __func__, adsp_err_get_err_str(
9200 atomic_read(&ac->cmd_state)));
9201 rc = adsp_err_get_lnx_err_code(
9202 atomic_read(&ac->cmd_state));
9203 goto exit;
9204 }
9205 rc = 0;
9206exit:
9207 return rc;
9208}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309209EXPORT_SYMBOL(q6asm_send_mtmx_strtr_render_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309210
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309211/**
9212 * q6asm_send_mtmx_strtr_clk_rec_mode -
9213 * command to send matrix for clock rec
9214 *
9215 * @ac: Audio client handle
9216 * @clk_rec_mode: mode for clock rec
9217 *
9218 * Returns 0 on success or error on failure
9219 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309220int q6asm_send_mtmx_strtr_clk_rec_mode(struct audio_client *ac,
9221 uint32_t clk_rec_mode)
9222{
9223 struct asm_mtmx_strtr_params matrix;
9224 struct asm_session_mtmx_strtr_param_clk_rec_t clk_rec_param;
9225 int sz = 0;
9226 int rc = 0;
9227
9228 pr_debug("%s: clk rec mode is %d\n", __func__, clk_rec_mode);
9229
9230 if (!ac) {
9231 pr_err("%s: audio client handle is NULL\n", __func__);
9232 rc = -EINVAL;
9233 goto exit;
9234 }
9235
9236 if (ac->apr == NULL) {
9237 pr_err("%s: ac->apr is NULL\n", __func__);
9238 rc = -EINVAL;
9239 goto exit;
9240 }
9241
9242 if ((clk_rec_mode != ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_NONE) &&
9243 (clk_rec_mode != ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_AUTO)) {
9244 pr_err("%s: Invalid clk rec mode %d\n", __func__, clk_rec_mode);
9245 rc = -EINVAL;
9246 goto exit;
9247 }
9248
9249 memset(&clk_rec_param, 0,
9250 sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t));
9251 clk_rec_param.flags = clk_rec_mode;
9252
9253 memset(&matrix, 0, sizeof(struct asm_mtmx_strtr_params));
9254 sz = sizeof(struct asm_mtmx_strtr_params);
9255 q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE);
9256 atomic_set(&ac->cmd_state, -1);
9257 matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2;
9258
9259 matrix.param.data_payload_addr_lsw = 0;
9260 matrix.param.data_payload_addr_msw = 0;
9261 matrix.param.mem_map_handle = 0;
9262 matrix.param.data_payload_size =
9263 sizeof(struct asm_stream_param_data_v2) +
9264 sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t);
9265 matrix.param.direction = 0; /* RX */
9266 matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
9267 matrix.data.param_id = ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_CMD;
9268 matrix.data.param_size =
9269 sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t);
9270 matrix.data.reserved = 0;
9271 memcpy(&(matrix.config.clk_rec_param),
9272 &clk_rec_param,
9273 sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t));
9274
9275 rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
9276 if (rc < 0) {
9277 pr_err("%s: clk rec mode send failed paramid [0x%x]\n",
9278 __func__, matrix.data.param_id);
9279 rc = -EINVAL;
9280 goto exit;
9281 }
9282
9283 rc = wait_event_timeout(ac->cmd_wait,
9284 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
9285 if (!rc) {
9286 pr_err("%s: timeout, clk rec mode send paramid [0x%x]\n",
9287 __func__, matrix.data.param_id);
9288 rc = -ETIMEDOUT;
9289 goto exit;
9290 }
9291
9292 if (atomic_read(&ac->cmd_state) > 0) {
9293 pr_err("%s: DSP returned error[%s]\n",
9294 __func__, adsp_err_get_err_str(
9295 atomic_read(&ac->cmd_state)));
9296 rc = adsp_err_get_lnx_err_code(
9297 atomic_read(&ac->cmd_state));
9298 goto exit;
9299 }
9300 rc = 0;
9301exit:
9302 return rc;
9303}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309304EXPORT_SYMBOL(q6asm_send_mtmx_strtr_clk_rec_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309305
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309306/**
9307 * q6asm_send_mtmx_strtr_enable_adjust_session_clock -
9308 * command to send matrix for adjust time
9309 *
9310 * @ac: Audio client handle
9311 * @enable: flag to adjust time or not
9312 *
9313 * Returns 0 on success or error on failure
9314 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309315int q6asm_send_mtmx_strtr_enable_adjust_session_clock(struct audio_client *ac,
9316 bool enable)
9317{
9318 struct asm_mtmx_strtr_params matrix;
9319 struct asm_session_mtmx_param_adjust_session_time_ctl_t adjust_time;
9320 int sz = 0;
9321 int rc = 0;
9322
9323 pr_debug("%s: adjust session enable %d\n", __func__, enable);
9324
9325 if (!ac) {
9326 pr_err("%s: audio client handle is NULL\n", __func__);
9327 rc = -EINVAL;
9328 goto exit;
9329 }
9330
9331 if (ac->apr == NULL) {
9332 pr_err("%s: ac->apr is NULL\n", __func__);
9333 rc = -EINVAL;
9334 goto exit;
9335 }
9336
9337 adjust_time.enable = enable;
9338 memset(&matrix, 0, sizeof(struct asm_mtmx_strtr_params));
9339 sz = sizeof(struct asm_mtmx_strtr_params);
9340 q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE);
9341 atomic_set(&ac->cmd_state, -1);
9342 matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2;
9343
9344 matrix.param.data_payload_addr_lsw = 0;
9345 matrix.param.data_payload_addr_msw = 0;
9346 matrix.param.mem_map_handle = 0;
9347 matrix.param.data_payload_size =
9348 sizeof(struct asm_stream_param_data_v2) +
9349 sizeof(struct asm_session_mtmx_param_adjust_session_time_ctl_t);
9350 matrix.param.direction = 0; /* RX */
9351 matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
9352 matrix.data.param_id = ASM_SESSION_MTMX_PARAM_ADJUST_SESSION_TIME_CTL;
9353 matrix.data.param_size =
9354 sizeof(struct asm_session_mtmx_param_adjust_session_time_ctl_t);
9355 matrix.data.reserved = 0;
9356 matrix.config.adj_time_param.enable = adjust_time.enable;
9357
9358 rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
9359 if (rc < 0) {
9360 pr_err("%s: enable adjust session failed failed paramid [0x%x]\n",
9361 __func__, matrix.data.param_id);
9362 rc = -EINVAL;
9363 goto exit;
9364 }
9365
9366 rc = wait_event_timeout(ac->cmd_wait,
9367 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
9368 if (!rc) {
9369 pr_err("%s: enable adjust session failed failed paramid [0x%x]\n",
9370 __func__, matrix.data.param_id);
9371 rc = -ETIMEDOUT;
9372 goto exit;
9373 }
9374
9375 if (atomic_read(&ac->cmd_state) > 0) {
9376 pr_err("%s: DSP returned error[%s]\n",
9377 __func__, adsp_err_get_err_str(
9378 atomic_read(&ac->cmd_state)));
9379 rc = adsp_err_get_lnx_err_code(
9380 atomic_read(&ac->cmd_state));
9381 goto exit;
9382 }
9383 rc = 0;
9384exit:
9385 return rc;
9386}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309387EXPORT_SYMBOL(q6asm_send_mtmx_strtr_enable_adjust_session_clock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309388
9389
9390static int __q6asm_cmd(struct audio_client *ac, int cmd, uint32_t stream_id)
9391{
9392 struct apr_hdr hdr;
9393 int rc;
9394 atomic_t *state;
9395 int cnt = 0;
9396
9397 if (!ac) {
9398 pr_err("%s: APR handle NULL\n", __func__);
9399 return -EINVAL;
9400 }
9401 if (ac->apr == NULL) {
9402 pr_err("%s: AC APR handle NULL\n", __func__);
9403 return -EINVAL;
9404 }
9405 q6asm_stream_add_hdr(ac, &hdr, sizeof(hdr), TRUE, stream_id);
9406 atomic_set(&ac->cmd_state, -1);
9407 /*
9408 * Updated the token field with stream/session for compressed playback
9409 * Platform driver must know the the stream with which the command is
9410 * associated
9411 */
9412 if (ac->io_mode & COMPRESSED_STREAM_IO)
9413 q6asm_update_token(&hdr.token,
9414 ac->session,
9415 stream_id,
9416 0, /* Buffer index is NA */
9417 0, /* Direction flag is NA */
9418 WAIT_CMD);
9419 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
9420 __func__, hdr.token, stream_id, ac->session);
9421 switch (cmd) {
9422 case CMD_PAUSE:
9423 pr_debug("%s: CMD_PAUSE\n", __func__);
9424 hdr.opcode = ASM_SESSION_CMD_PAUSE;
9425 state = &ac->cmd_state;
9426 break;
9427 case CMD_SUSPEND:
9428 pr_debug("%s: CMD_SUSPEND\n", __func__);
9429 hdr.opcode = ASM_SESSION_CMD_SUSPEND;
9430 state = &ac->cmd_state;
9431 break;
9432 case CMD_FLUSH:
9433 pr_debug("%s: CMD_FLUSH\n", __func__);
9434 hdr.opcode = ASM_STREAM_CMD_FLUSH;
9435 state = &ac->cmd_state;
9436 break;
9437 case CMD_OUT_FLUSH:
9438 pr_debug("%s: CMD_OUT_FLUSH\n", __func__);
9439 hdr.opcode = ASM_STREAM_CMD_FLUSH_READBUFS;
9440 state = &ac->cmd_state;
9441 break;
9442 case CMD_EOS:
9443 pr_debug("%s: CMD_EOS\n", __func__);
9444 hdr.opcode = ASM_DATA_CMD_EOS;
9445 atomic_set(&ac->cmd_state, 0);
9446 state = &ac->cmd_state;
9447 break;
9448 case CMD_CLOSE:
9449 pr_debug("%s: CMD_CLOSE\n", __func__);
9450 hdr.opcode = ASM_STREAM_CMD_CLOSE;
9451 state = &ac->cmd_state;
9452 break;
9453 default:
9454 pr_err("%s: Invalid format[%d]\n", __func__, cmd);
9455 rc = -EINVAL;
9456 goto fail_cmd;
9457 }
9458 pr_debug("%s: session[%d]opcode[0x%x]\n", __func__,
9459 ac->session,
9460 hdr.opcode);
9461 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
9462 if (rc < 0) {
9463 pr_err("%s: Commmand 0x%x failed %d\n",
9464 __func__, hdr.opcode, rc);
9465 rc = -EINVAL;
9466 goto fail_cmd;
9467 }
9468 rc = wait_event_timeout(ac->cmd_wait, (atomic_read(state) >= 0), 5*HZ);
9469 if (!rc) {
9470 pr_err("%s: timeout. waited for response opcode[0x%x]\n",
9471 __func__, hdr.opcode);
9472 rc = -ETIMEDOUT;
9473 goto fail_cmd;
9474 }
9475 if (atomic_read(state) > 0) {
9476 pr_err("%s: DSP returned error[%s] opcode %d\n",
9477 __func__, adsp_err_get_err_str(
9478 atomic_read(state)),
9479 hdr.opcode);
9480 rc = adsp_err_get_lnx_err_code(atomic_read(state));
9481 goto fail_cmd;
9482 }
9483
9484 if (cmd == CMD_FLUSH)
9485 q6asm_reset_buf_state(ac);
9486 if (cmd == CMD_CLOSE) {
9487 /* check if DSP return all buffers */
9488 if (ac->port[IN].buf) {
9489 for (cnt = 0; cnt < ac->port[IN].max_buf_cnt;
9490 cnt++) {
9491 if (ac->port[IN].buf[cnt].used == IN) {
9492 dev_vdbg(ac->dev, "Write Buf[%d] not returned\n",
9493 cnt);
9494 }
9495 }
9496 }
9497 if (ac->port[OUT].buf) {
9498 for (cnt = 0; cnt < ac->port[OUT].max_buf_cnt; cnt++) {
9499 if (ac->port[OUT].buf[cnt].used == OUT) {
9500 dev_vdbg(ac->dev, "Read Buf[%d] not returned\n",
9501 cnt);
9502 }
9503 }
9504 }
9505 }
9506 return 0;
9507fail_cmd:
9508 return rc;
9509}
9510
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309511/**
9512 * q6asm_cmd -
9513 * Function used to send commands for
9514 * ASM with wait for ack.
9515 *
9516 * @ac: Audio client handle
9517 * @cmd: command to send
9518 *
9519 * Returns 0 on success or error on failure
9520 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309521int q6asm_cmd(struct audio_client *ac, int cmd)
9522{
9523 return __q6asm_cmd(ac, cmd, ac->stream_id);
9524}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309525EXPORT_SYMBOL(q6asm_cmd);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309526
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309527/**
9528 * q6asm_stream_cmd -
9529 * Function used to send commands for
9530 * ASM stream with wait for ack.
9531 *
9532 * @ac: Audio client handle
9533 * @cmd: command to send
9534 * @stream_id: Stream ID
9535 *
9536 * Returns 0 on success or error on failure
9537 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309538int q6asm_stream_cmd(struct audio_client *ac, int cmd, uint32_t stream_id)
9539{
9540 return __q6asm_cmd(ac, cmd, stream_id);
9541}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309542EXPORT_SYMBOL(q6asm_stream_cmd);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309543
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309544/**
9545 * q6asm_cmd_nowait -
9546 * Function used to send commands for
9547 * ASM stream without wait for ack.
9548 *
9549 * @ac: Audio client handle
9550 * @cmd: command to send
9551 * @stream_id: Stream ID
9552 *
9553 * Returns 0 on success or error on failure
9554 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309555static int __q6asm_cmd_nowait(struct audio_client *ac, int cmd,
9556 uint32_t stream_id)
9557{
9558 struct apr_hdr hdr;
9559 int rc;
9560
9561 if (!ac) {
9562 pr_err("%s: APR handle NULL\n", __func__);
9563 return -EINVAL;
9564 }
9565 if (ac->apr == NULL) {
9566 pr_err("%s: AC APR handle NULL\n", __func__);
9567 return -EINVAL;
9568 }
9569 q6asm_stream_add_hdr_async(ac, &hdr, sizeof(hdr), TRUE, stream_id);
9570 atomic_set(&ac->cmd_state, 1);
9571 /*
9572 * Updated the token field with stream/session for compressed playback
9573 * Platform driver must know the the stream with which the command is
9574 * associated
9575 */
9576 if (ac->io_mode & COMPRESSED_STREAM_IO)
9577 q6asm_update_token(&hdr.token,
9578 ac->session,
9579 stream_id,
9580 0, /* Buffer index is NA */
9581 0, /* Direction flag is NA */
9582 NO_WAIT_CMD);
9583
9584 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
9585 __func__, hdr.token, stream_id, ac->session);
9586 switch (cmd) {
9587 case CMD_PAUSE:
9588 pr_debug("%s: CMD_PAUSE\n", __func__);
9589 hdr.opcode = ASM_SESSION_CMD_PAUSE;
9590 break;
9591 case CMD_EOS:
9592 pr_debug("%s: CMD_EOS\n", __func__);
9593 hdr.opcode = ASM_DATA_CMD_EOS;
9594 break;
9595 case CMD_CLOSE:
9596 pr_debug("%s: CMD_CLOSE\n", __func__);
9597 hdr.opcode = ASM_STREAM_CMD_CLOSE;
9598 break;
9599 default:
9600 pr_err("%s: Invalid format[%d]\n", __func__, cmd);
9601 goto fail_cmd;
9602 }
9603 pr_debug("%s: session[%d]opcode[0x%x]\n", __func__,
9604 ac->session,
9605 hdr.opcode);
9606
9607 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
9608 if (rc < 0) {
9609 pr_err("%s: Commmand 0x%x failed %d\n",
9610 __func__, hdr.opcode, rc);
9611 goto fail_cmd;
9612 }
9613 return 0;
9614fail_cmd:
9615 return -EINVAL;
9616}
9617
9618int q6asm_cmd_nowait(struct audio_client *ac, int cmd)
9619{
9620 pr_debug("%s: stream_id: %d\n", __func__, ac->stream_id);
9621 return __q6asm_cmd_nowait(ac, cmd, ac->stream_id);
9622}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309623EXPORT_SYMBOL(q6asm_cmd_nowait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309624
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309625/**
9626 * q6asm_stream_cmd_nowait -
9627 * Function used to send commands for
9628 * ASM stream without wait for ack.
9629 *
9630 * @ac: Audio client handle
9631 * @cmd: command to send
9632 * @stream_id: Stream ID
9633 *
9634 * Returns 0 on success or error on failure
9635 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309636int q6asm_stream_cmd_nowait(struct audio_client *ac, int cmd,
9637 uint32_t stream_id)
9638{
9639 pr_debug("%s: stream_id: %d\n", __func__, stream_id);
9640 return __q6asm_cmd_nowait(ac, cmd, stream_id);
9641}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309642EXPORT_SYMBOL(q6asm_stream_cmd_nowait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309643
9644int __q6asm_send_meta_data(struct audio_client *ac, uint32_t stream_id,
9645 uint32_t initial_samples, uint32_t trailing_samples)
9646{
9647 struct asm_data_cmd_remove_silence silence;
9648 int rc = 0;
9649
9650 if (!ac) {
9651 pr_err("%s: APR handle NULL\n", __func__);
9652 return -EINVAL;
9653 }
9654 if (ac->apr == NULL) {
9655 pr_err("%s: AC APR handle NULL\n", __func__);
9656 return -EINVAL;
9657 }
9658 pr_debug("%s: session[%d]\n", __func__, ac->session);
9659 q6asm_stream_add_hdr_async(ac, &silence.hdr, sizeof(silence), TRUE,
9660 stream_id);
9661
9662 /*
9663 * Updated the token field with stream/session for compressed playback
9664 * Platform driver must know the the stream with which the command is
9665 * associated
9666 */
9667 if (ac->io_mode & COMPRESSED_STREAM_IO)
9668 q6asm_update_token(&silence.hdr.token,
9669 ac->session,
9670 stream_id,
9671 0, /* Buffer index is NA */
9672 0, /* Direction flag is NA */
9673 NO_WAIT_CMD);
9674 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
9675 __func__, silence.hdr.token, stream_id, ac->session);
9676
9677 silence.hdr.opcode = ASM_DATA_CMD_REMOVE_INITIAL_SILENCE;
9678 silence.num_samples_to_remove = initial_samples;
9679
9680 rc = apr_send_pkt(ac->apr, (uint32_t *) &silence);
9681 if (rc < 0) {
9682 pr_err("%s: Commmand silence failed[%d]", __func__, rc);
9683
9684 goto fail_cmd;
9685 }
9686
9687 silence.hdr.opcode = ASM_DATA_CMD_REMOVE_TRAILING_SILENCE;
9688 silence.num_samples_to_remove = trailing_samples;
9689
9690
9691 rc = apr_send_pkt(ac->apr, (uint32_t *) &silence);
9692 if (rc < 0) {
9693 pr_err("%s: Commmand silence failed[%d]", __func__, rc);
9694 goto fail_cmd;
9695 }
9696
9697 return 0;
9698fail_cmd:
9699 return -EINVAL;
9700}
9701
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309702/**
9703 * q6asm_stream_send_meta_data -
9704 * command to send meta data for stream
9705 *
9706 * @ac: Audio client handle
9707 * @stream_id: Stream ID
9708 * @initial_samples: Initial samples of stream
9709 * @trailing_samples: Trailing samples of stream
9710 *
9711 * Returns 0 on success or error on failure
9712 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309713int q6asm_stream_send_meta_data(struct audio_client *ac, uint32_t stream_id,
9714 uint32_t initial_samples, uint32_t trailing_samples)
9715{
9716 return __q6asm_send_meta_data(ac, stream_id, initial_samples,
9717 trailing_samples);
9718}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309719EXPORT_SYMBOL(q6asm_stream_send_meta_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309720
9721int q6asm_send_meta_data(struct audio_client *ac, uint32_t initial_samples,
9722 uint32_t trailing_samples)
9723{
9724 return __q6asm_send_meta_data(ac, ac->stream_id, initial_samples,
9725 trailing_samples);
9726}
9727
9728static void q6asm_reset_buf_state(struct audio_client *ac)
9729{
9730 int cnt = 0;
9731 int loopcnt = 0;
9732 int used;
9733 struct audio_port_data *port = NULL;
9734
9735 if (ac->io_mode & SYNC_IO_MODE) {
9736 used = (ac->io_mode & TUN_WRITE_IO_MODE ? 1 : 0);
9737 mutex_lock(&ac->cmd_lock);
9738 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
9739 port = &ac->port[loopcnt];
9740 cnt = port->max_buf_cnt - 1;
9741 port->dsp_buf = 0;
9742 port->cpu_buf = 0;
9743 while (cnt >= 0) {
9744 if (!port->buf)
9745 continue;
9746 port->buf[cnt].used = used;
9747 cnt--;
9748 }
9749 }
9750 mutex_unlock(&ac->cmd_lock);
9751 }
9752}
9753
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309754/**
9755 * q6asm_reg_tx_overflow -
9756 * command to register for TX overflow events
9757 *
9758 * @ac: Audio client handle
9759 * @enable: flag to enable or disable events
9760 *
9761 * Returns 0 on success or error on failure
9762 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309763int q6asm_reg_tx_overflow(struct audio_client *ac, uint16_t enable)
9764{
9765 struct asm_session_cmd_regx_overflow tx_overflow;
9766 int rc;
9767
9768 if (!ac) {
9769 pr_err("%s: APR handle NULL\n", __func__);
9770 return -EINVAL;
9771 }
9772 if (ac->apr == NULL) {
9773 pr_err("%s: AC APR handle NULL\n", __func__);
9774 return -EINVAL;
9775 }
9776 pr_debug("%s: session[%d]enable[%d]\n", __func__,
9777 ac->session, enable);
9778 q6asm_add_hdr(ac, &tx_overflow.hdr, sizeof(tx_overflow), TRUE);
9779 atomic_set(&ac->cmd_state, -1);
9780
9781 tx_overflow.hdr.opcode =
9782 ASM_SESSION_CMD_REGISTER_FORX_OVERFLOW_EVENTS;
9783 /* tx overflow event: enable */
9784 tx_overflow.enable_flag = enable;
9785
9786 rc = apr_send_pkt(ac->apr, (uint32_t *) &tx_overflow);
9787 if (rc < 0) {
9788 pr_err("%s: tx overflow op[0x%x]rc[%d]\n",
9789 __func__, tx_overflow.hdr.opcode, rc);
9790 rc = -EINVAL;
9791 goto fail_cmd;
9792 }
9793 rc = wait_event_timeout(ac->cmd_wait,
9794 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
9795 if (!rc) {
9796 pr_err("%s: timeout. waited for tx overflow\n", __func__);
9797 rc = -ETIMEDOUT;
9798 goto fail_cmd;
9799 }
9800 if (atomic_read(&ac->cmd_state) > 0) {
9801 pr_err("%s: DSP returned error[%s]\n",
9802 __func__, adsp_err_get_err_str(
9803 atomic_read(&ac->cmd_state)));
9804 rc = adsp_err_get_lnx_err_code(
9805 atomic_read(&ac->cmd_state));
9806 goto fail_cmd;
9807 }
9808
9809 return 0;
9810fail_cmd:
9811 return rc;
9812}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309813EXPORT_SYMBOL(q6asm_reg_tx_overflow);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309814
9815int q6asm_reg_rx_underflow(struct audio_client *ac, uint16_t enable)
9816{
9817 struct asm_session_cmd_rgstr_rx_underflow rx_underflow;
9818 int rc;
9819
9820 if (!ac) {
9821 pr_err("%s: AC APR handle NULL\n", __func__);
9822 return -EINVAL;
9823 }
9824 if (ac->apr == NULL) {
9825 pr_err("%s: APR handle NULL\n", __func__);
9826 return -EINVAL;
9827 }
9828 pr_debug("%s: session[%d]enable[%d]\n", __func__,
9829 ac->session, enable);
9830 q6asm_add_hdr_async(ac, &rx_underflow.hdr, sizeof(rx_underflow), FALSE);
9831
9832 rx_underflow.hdr.opcode =
9833 ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS;
9834 /* tx overflow event: enable */
9835 rx_underflow.enable_flag = enable;
9836
9837 rc = apr_send_pkt(ac->apr, (uint32_t *) &rx_underflow);
9838 if (rc < 0) {
9839 pr_err("%s: tx overflow op[0x%x]rc[%d]\n",
9840 __func__, rx_underflow.hdr.opcode, rc);
9841 goto fail_cmd;
9842 }
9843 return 0;
9844fail_cmd:
9845 return -EINVAL;
9846}
9847
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309848/**
9849 * q6asm_adjust_session_clock -
9850 * command to adjust session clock
9851 *
9852 * @ac: Audio client handle
9853 * @adjust_time_lsw: lower 32bits
9854 * @adjust_time_msw: upper 32bits
9855 *
9856 * Returns 0 on success or error on failure
9857 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309858int q6asm_adjust_session_clock(struct audio_client *ac,
9859 uint32_t adjust_time_lsw,
9860 uint32_t adjust_time_msw)
9861{
9862 int rc = 0;
9863 int sz = 0;
9864 struct asm_session_cmd_adjust_session_clock_v2 adjust_clock;
9865
9866 pr_debug("%s: adjust_time_lsw is %x, adjust_time_msw is %x\n", __func__,
9867 adjust_time_lsw, adjust_time_msw);
9868
9869 if (!ac) {
9870 pr_err("%s: audio client handle is NULL\n", __func__);
9871 rc = -EINVAL;
9872 goto fail_cmd;
9873 }
9874
9875 if (ac->apr == NULL) {
9876 pr_err("%s: ac->apr is NULL", __func__);
9877 rc = -EINVAL;
9878 goto fail_cmd;
9879 }
9880
9881 sz = sizeof(struct asm_session_cmd_adjust_session_clock_v2);
9882 q6asm_add_hdr(ac, &adjust_clock.hdr, sz, TRUE);
9883 atomic_set(&ac->cmd_state, -1);
9884 adjust_clock.hdr.opcode = ASM_SESSION_CMD_ADJUST_SESSION_CLOCK_V2;
9885
9886 adjust_clock.adjustime_lsw = adjust_time_lsw;
9887 adjust_clock.adjustime_msw = adjust_time_msw;
9888
9889
9890 rc = apr_send_pkt(ac->apr, (uint32_t *) &adjust_clock);
9891 if (rc < 0) {
9892 pr_err("%s: adjust_clock send failed paramid [0x%x]\n",
9893 __func__, adjust_clock.hdr.opcode);
9894 rc = -EINVAL;
9895 goto fail_cmd;
9896 }
9897
9898 rc = wait_event_timeout(ac->cmd_wait,
9899 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
9900 if (!rc) {
9901 pr_err("%s: timeout, adjust_clock paramid[0x%x]\n",
9902 __func__, adjust_clock.hdr.opcode);
9903 rc = -ETIMEDOUT;
9904 goto fail_cmd;
9905 }
9906
9907 if (atomic_read(&ac->cmd_state) > 0) {
9908 pr_err("%s: DSP returned error[%s]\n",
9909 __func__, adsp_err_get_err_str(
9910 atomic_read(&ac->cmd_state)));
9911 rc = adsp_err_get_lnx_err_code(
9912 atomic_read(&ac->cmd_state));
9913 goto fail_cmd;
9914 }
9915 rc = 0;
9916fail_cmd:
9917 return rc;
9918}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309919EXPORT_SYMBOL(q6asm_adjust_session_clock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309920
9921/*
9922 * q6asm_get_path_delay() - get the path delay for an audio session
9923 * @ac: audio client handle
9924 *
9925 * Retrieves the current audio DSP path delay for the given audio session.
9926 *
9927 * Return: 0 on success, error code otherwise
9928 */
9929int q6asm_get_path_delay(struct audio_client *ac)
9930{
9931 int rc = 0;
9932 struct apr_hdr hdr;
9933
9934 if (!ac || ac->apr == NULL) {
9935 pr_err("%s: invalid audio client\n", __func__);
9936 return -EINVAL;
9937 }
9938
9939 hdr.opcode = ASM_SESSION_CMD_GET_PATH_DELAY_V2;
9940 q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
9941 atomic_set(&ac->cmd_state, -1);
9942
9943 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
9944 if (rc < 0) {
9945 pr_err("%s: Commmand 0x%x failed %d\n", __func__,
9946 hdr.opcode, rc);
9947 return rc;
9948 }
9949
9950 rc = wait_event_timeout(ac->cmd_wait,
9951 (atomic_read(&ac->cmd_state) >= 0), 5 * HZ);
9952 if (!rc) {
9953 pr_err("%s: timeout. waited for response opcode[0x%x]\n",
9954 __func__, hdr.opcode);
9955 return -ETIMEDOUT;
9956 }
9957
9958 if (atomic_read(&ac->cmd_state) > 0) {
9959 pr_err("%s: DSP returned error[%s]\n",
9960 __func__, adsp_err_get_err_str(
9961 atomic_read(&ac->cmd_state)));
9962 rc = adsp_err_get_lnx_err_code(
9963 atomic_read(&ac->cmd_state));
9964 return rc;
9965 }
9966
9967 return 0;
9968}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309969EXPORT_SYMBOL(q6asm_get_path_delay);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309970
9971int q6asm_get_apr_service_id(int session_id)
9972{
9973 pr_debug("%s:\n", __func__);
9974
9975 if (session_id <= 0 || session_id > ASM_ACTIVE_STREAMS_ALLOWED) {
9976 pr_err("%s: invalid session_id = %d\n", __func__, session_id);
9977 return -EINVAL;
9978 }
9979
Meng Wang9730cdd2017-09-26 12:48:31 +08009980 return ((struct apr_svc *)(session[session_id].ac)->apr)->id;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309981}
9982
9983int q6asm_get_asm_topology(int session_id)
9984{
9985 int topology = -EINVAL;
9986
9987 if (session_id <= 0 || session_id > ASM_ACTIVE_STREAMS_ALLOWED) {
9988 pr_err("%s: invalid session_id = %d\n", __func__, session_id);
9989 goto done;
9990 }
Meng Wang9730cdd2017-09-26 12:48:31 +08009991 if (session[session_id].ac == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309992 pr_err("%s: session not created for session id = %d\n",
9993 __func__, session_id);
9994 goto done;
9995 }
Meng Wang9730cdd2017-09-26 12:48:31 +08009996 topology = (session[session_id].ac)->topology;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309997done:
9998 return topology;
9999}
10000
10001int q6asm_get_asm_app_type(int session_id)
10002{
10003 int app_type = -EINVAL;
10004
10005 if (session_id <= 0 || session_id > ASM_ACTIVE_STREAMS_ALLOWED) {
10006 pr_err("%s: invalid session_id = %d\n", __func__, session_id);
10007 goto done;
10008 }
Meng Wang9730cdd2017-09-26 12:48:31 +080010009 if (session[session_id].ac == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010010 pr_err("%s: session not created for session id = %d\n",
10011 __func__, session_id);
10012 goto done;
10013 }
Meng Wang9730cdd2017-09-26 12:48:31 +080010014 app_type = (session[session_id].ac)->app_type;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010015done:
10016 return app_type;
10017}
10018
10019static int q6asm_get_asm_topology_cal(void)
10020{
10021 int topology = DEFAULT_POPP_TOPOLOGY;
10022 struct cal_block_data *cal_block = NULL;
10023
10024 if (cal_data[ASM_TOPOLOGY_CAL] == NULL)
10025 goto done;
10026
10027 mutex_lock(&cal_data[ASM_TOPOLOGY_CAL]->lock);
10028 cal_block = cal_utils_get_only_cal_block(cal_data[ASM_TOPOLOGY_CAL]);
10029 if (cal_block == NULL)
10030 goto unlock;
10031
10032 topology = ((struct audio_cal_info_asm_top *)
10033 cal_block->cal_info)->topology;
10034unlock:
10035 mutex_unlock(&cal_data[ASM_TOPOLOGY_CAL]->lock);
10036done:
10037 pr_debug("%s: Using topology %d\n", __func__, topology);
10038 return topology;
10039}
10040
10041static int q6asm_get_asm_app_type_cal(void)
10042{
10043 int app_type = DEFAULT_APP_TYPE;
10044 struct cal_block_data *cal_block = NULL;
10045
10046 if (cal_data[ASM_TOPOLOGY_CAL] == NULL)
10047 goto done;
10048
10049 mutex_lock(&cal_data[ASM_TOPOLOGY_CAL]->lock);
10050 cal_block = cal_utils_get_only_cal_block(cal_data[ASM_TOPOLOGY_CAL]);
10051 if (cal_block == NULL)
10052 goto unlock;
10053
10054 app_type = ((struct audio_cal_info_asm_top *)
10055 cal_block->cal_info)->app_type;
10056
10057 if (app_type == 0)
10058 app_type = DEFAULT_APP_TYPE;
10059unlock:
10060 mutex_unlock(&cal_data[ASM_TOPOLOGY_CAL]->lock);
10061done:
10062 pr_debug("%s: Using app_type %d\n", __func__, app_type);
10063 return app_type;
10064}
10065
Laxminath Kasam8b1366a2017-10-05 01:44:16 +053010066/**
10067 * q6asm_send_cal -
10068 * command to send ASM calibration
10069 *
10070 * @ac: Audio client handle
10071 *
10072 * Returns 0 on success or error on failure
10073 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010074int q6asm_send_cal(struct audio_client *ac)
10075{
10076 struct cal_block_data *cal_block = NULL;
10077 struct apr_hdr hdr;
10078 char *asm_params = NULL;
10079 struct asm_stream_cmd_set_pp_params_v2 payload_params;
10080 int sz, rc = -EINVAL;
10081
10082 pr_debug("%s:\n", __func__);
10083
10084 if (!ac) {
10085 pr_err("%s: APR handle NULL\n", __func__);
10086 goto done;
10087 }
10088 if (ac->apr == NULL) {
10089 pr_err("%s: AC APR handle NULL\n", __func__);
10090 goto done;
10091 }
10092 if (ac->io_mode & NT_MODE) {
10093 pr_debug("%s: called for NT MODE, exiting\n", __func__);
10094 goto done;
10095 }
10096
10097 if (cal_data[ASM_AUDSTRM_CAL] == NULL)
10098 goto done;
10099
10100 if (ac->perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) {
10101 rc = 0; /* no cal is required, not error case */
10102 goto done;
10103 }
10104
10105 mutex_lock(&cal_data[ASM_AUDSTRM_CAL]->lock);
10106 cal_block = cal_utils_get_only_cal_block(cal_data[ASM_AUDSTRM_CAL]);
10107 if (cal_block == NULL) {
10108 pr_err("%s: cal_block is NULL\n",
10109 __func__);
10110 goto unlock;
10111 }
10112
10113 if (cal_block->cal_data.size == 0) {
10114 rc = 0; /* not error case */
10115 pr_debug("%s: cal_data.size is 0, don't send cal data\n",
10116 __func__);
10117 goto unlock;
10118 }
10119
10120 rc = remap_cal_data(ASM_AUDSTRM_CAL_TYPE, cal_block);
10121 if (rc) {
10122 pr_err("%s: Remap_cal_data failed for cal %d!\n",
10123 __func__, ASM_AUDSTRM_CAL);
10124 goto unlock;
10125 }
10126
10127 sz = sizeof(struct apr_hdr) +
10128 sizeof(struct asm_stream_cmd_set_pp_params_v2);
10129 asm_params = kzalloc(sz, GFP_KERNEL);
10130 if (!asm_params) {
10131 pr_err("%s, asm params memory alloc failed", __func__);
10132 rc = -ENOMEM;
10133 goto unlock;
10134 }
10135
10136 /* asm_stream_cmd_set_pp_params_v2 has no APR header in it */
10137 q6asm_add_hdr_async(ac, &hdr, (sizeof(struct apr_hdr) +
10138 sizeof(struct asm_stream_cmd_set_pp_params_v2)), TRUE);
10139
10140 atomic_set(&ac->cmd_state_pp, -1);
10141 hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
10142 payload_params.data_payload_addr_lsw =
10143 lower_32_bits(cal_block->cal_data.paddr);
10144 payload_params.data_payload_addr_msw =
10145 msm_audio_populate_upper_32_bits(
10146 cal_block->cal_data.paddr);
10147 payload_params.mem_map_handle = cal_block->map_data.q6map_handle;
10148 payload_params.data_payload_size = cal_block->cal_data.size;
10149 memcpy(((u8 *)asm_params), &hdr, sizeof(struct apr_hdr));
10150 memcpy(((u8 *)asm_params + sizeof(struct apr_hdr)), &payload_params,
10151 sizeof(struct asm_stream_cmd_set_pp_params_v2));
10152
10153 pr_debug("%s: phyaddr lsw = %x msw = %x, maphdl = %x calsize = %d\n",
10154 __func__, payload_params.data_payload_addr_lsw,
10155 payload_params.data_payload_addr_msw,
10156 payload_params.mem_map_handle,
10157 payload_params.data_payload_size);
10158
10159 rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
10160 if (rc < 0) {
10161 pr_err("%s: audio audstrm cal send failed\n", __func__);
10162 rc = -EINVAL;
10163 goto free;
10164 }
10165 rc = wait_event_timeout(ac->cmd_wait,
10166 (atomic_read(&ac->cmd_state_pp) >= 0), 5 * HZ);
10167 if (!rc) {
10168 pr_err("%s: timeout, audio audstrm cal send\n", __func__);
10169 rc = -ETIMEDOUT;
10170 goto free;
10171 }
10172 if (atomic_read(&ac->cmd_state_pp) > 0) {
10173 pr_err("%s: DSP returned error[%d] audio audstrm cal send\n",
10174 __func__, atomic_read(&ac->cmd_state_pp));
10175 rc = -EINVAL;
10176 goto free;
10177 }
10178
10179 rc = 0;
10180
10181free:
10182 kfree(asm_params);
10183unlock:
10184 mutex_unlock(&cal_data[ASM_AUDSTRM_CAL]->lock);
10185done:
10186 return rc;
10187}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +053010188EXPORT_SYMBOL(q6asm_send_cal);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010189
10190static int get_cal_type_index(int32_t cal_type)
10191{
10192 int ret = -EINVAL;
10193
10194 switch (cal_type) {
10195 case ASM_TOPOLOGY_CAL_TYPE:
10196 ret = ASM_TOPOLOGY_CAL;
10197 break;
10198 case ASM_CUST_TOPOLOGY_CAL_TYPE:
10199 ret = ASM_CUSTOM_TOP_CAL;
10200 break;
10201 case ASM_AUDSTRM_CAL_TYPE:
10202 ret = ASM_AUDSTRM_CAL;
10203 break;
10204 case ASM_RTAC_APR_CAL_TYPE:
10205 ret = ASM_RTAC_APR_CAL;
10206 break;
10207 default:
10208 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
10209 }
10210 return ret;
10211}
10212
10213static int q6asm_alloc_cal(int32_t cal_type,
10214 size_t data_size, void *data)
10215{
10216 int ret = 0;
10217 int cal_index;
10218
10219 pr_debug("%s:\n", __func__);
10220
10221 cal_index = get_cal_type_index(cal_type);
10222 if (cal_index < 0) {
10223 pr_err("%s: could not get cal index %d!\n",
10224 __func__, cal_index);
10225 ret = -EINVAL;
10226 goto done;
10227 }
10228
10229 ret = cal_utils_alloc_cal(data_size, data,
10230 cal_data[cal_index], 0, NULL);
10231 if (ret < 0) {
10232 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
10233 __func__, ret, cal_type);
10234 ret = -EINVAL;
10235 goto done;
10236 }
10237done:
10238 return ret;
10239}
10240
10241static int q6asm_dealloc_cal(int32_t cal_type,
10242 size_t data_size, void *data)
10243{
10244 int ret = 0;
10245 int cal_index;
10246
10247 pr_debug("%s:\n", __func__);
10248
10249 cal_index = get_cal_type_index(cal_type);
10250 if (cal_index < 0) {
10251 pr_err("%s: could not get cal index %d!\n",
10252 __func__, cal_index);
10253 ret = -EINVAL;
10254 goto done;
10255 }
10256
10257 ret = cal_utils_dealloc_cal(data_size, data,
10258 cal_data[cal_index]);
10259 if (ret < 0) {
10260 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
10261 __func__, ret, cal_type);
10262 ret = -EINVAL;
10263 goto done;
10264 }
10265done:
10266 return ret;
10267}
10268
10269static int q6asm_set_cal(int32_t cal_type,
10270 size_t data_size, void *data)
10271{
10272 int ret = 0;
10273 int cal_index;
10274
10275 pr_debug("%s:\n", __func__);
10276
10277 cal_index = get_cal_type_index(cal_type);
10278 if (cal_index < 0) {
10279 pr_err("%s: could not get cal index %d!\n",
10280 __func__, cal_index);
10281 ret = -EINVAL;
10282 goto done;
10283 }
10284
10285 ret = cal_utils_set_cal(data_size, data,
10286 cal_data[cal_index], 0, NULL);
10287 if (ret < 0) {
10288 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
10289 __func__, ret, cal_type);
10290 ret = -EINVAL;
10291 goto done;
10292 }
10293
10294 if (cal_index == ASM_CUSTOM_TOP_CAL) {
10295 mutex_lock(&cal_data[ASM_CUSTOM_TOP_CAL]->lock);
10296 set_custom_topology = 1;
10297 mutex_unlock(&cal_data[ASM_CUSTOM_TOP_CAL]->lock);
10298 }
10299done:
10300 return ret;
10301}
10302
10303static void q6asm_delete_cal_data(void)
10304{
10305 pr_debug("%s:\n", __func__);
10306 cal_utils_destroy_cal_types(ASM_MAX_CAL_TYPES, cal_data);
10307}
10308
10309static int q6asm_init_cal_data(void)
10310{
10311 int ret = 0;
10312 struct cal_type_info cal_type_info[] = {
10313 {{ASM_TOPOLOGY_CAL_TYPE,
10314 {NULL, NULL, NULL,
10315 q6asm_set_cal, NULL, NULL} },
10316 {NULL, NULL, cal_utils_match_buf_num} },
10317
10318 {{ASM_CUST_TOPOLOGY_CAL_TYPE,
10319 {q6asm_alloc_cal, q6asm_dealloc_cal, NULL,
10320 q6asm_set_cal, NULL, NULL} },
10321 {NULL, q6asm_unmap_cal_memory, cal_utils_match_buf_num} },
10322
10323 {{ASM_AUDSTRM_CAL_TYPE,
10324 {q6asm_alloc_cal, q6asm_dealloc_cal, NULL,
10325 q6asm_set_cal, NULL, NULL} },
10326 {NULL, q6asm_unmap_cal_memory, cal_utils_match_buf_num} },
10327
10328 {{ASM_RTAC_APR_CAL_TYPE,
10329 {NULL, NULL, NULL, NULL, NULL, NULL} },
10330 {NULL, NULL, cal_utils_match_buf_num} }
10331 };
10332 pr_debug("%s\n", __func__);
10333
10334 ret = cal_utils_create_cal_types(ASM_MAX_CAL_TYPES, cal_data,
10335 cal_type_info);
10336 if (ret < 0) {
10337 pr_err("%s: could not create cal type! %d\n",
10338 __func__, ret);
10339 ret = -EINVAL;
10340 goto err;
10341 }
10342
10343 return ret;
10344err:
10345 q6asm_delete_cal_data();
10346 return ret;
10347}
10348
10349static int q6asm_is_valid_session(struct apr_client_data *data, void *priv)
10350{
10351 struct audio_client *ac = (struct audio_client *)priv;
10352 union asm_token_struct asm_token;
10353
10354 asm_token.token = data->token;
10355 if (asm_token._token.session_id != ac->session) {
10356 pr_err("%s: Invalid session[%d] rxed expected[%d]",
10357 __func__, asm_token._token.session_id, ac->session);
10358 return -EINVAL;
10359 }
10360 return 0;
10361}
10362
Laxminath Kasam8b1366a2017-10-05 01:44:16 +053010363int __init q6asm_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010364{
10365 int lcnt, ret;
10366
10367 pr_debug("%s:\n", __func__);
10368
Meng Wang9730cdd2017-09-26 12:48:31 +080010369 memset(session, 0, sizeof(struct audio_session) *
10370 (ASM_ACTIVE_STREAMS_ALLOWED + 1));
10371 for (lcnt = 0; lcnt <= ASM_ACTIVE_STREAMS_ALLOWED; lcnt++)
10372 spin_lock_init(&(session[lcnt].session_lock));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010373 set_custom_topology = 1;
10374
10375 /*setup common client used for cal mem map */
10376 common_client.session = ASM_CONTROL_SESSION;
10377 common_client.port[0].buf = &common_buf[0];
10378 common_client.port[1].buf = &common_buf[1];
10379 init_waitqueue_head(&common_client.cmd_wait);
10380 init_waitqueue_head(&common_client.time_wait);
10381 init_waitqueue_head(&common_client.mem_wait);
10382 atomic_set(&common_client.time_flag, 1);
10383 INIT_LIST_HEAD(&common_client.port[0].mem_map_handle);
10384 INIT_LIST_HEAD(&common_client.port[1].mem_map_handle);
10385 mutex_init(&common_client.cmd_lock);
10386 for (lcnt = 0; lcnt <= OUT; lcnt++) {
10387 mutex_init(&common_client.port[lcnt].lock);
10388 spin_lock_init(&common_client.port[lcnt].dsp_lock);
10389 }
10390 atomic_set(&common_client.cmd_state, 0);
10391 atomic_set(&common_client.mem_state, 0);
10392
10393 ret = q6asm_init_cal_data();
10394 if (ret)
10395 pr_err("%s: could not init cal data! ret %d\n",
10396 __func__, ret);
10397
10398 config_debug_fs_init();
10399
10400 return 0;
10401}
10402
Asish Bhattacharya5faacb32017-12-04 17:23:15 +053010403void q6asm_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010404{
10405 q6asm_delete_cal_data();
10406}