blob: 9fb5d6b6abb0551e59a1707599ea751c75294c3e [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;
2266 pp_event_package = kzalloc(payload_size
2267 + sizeof(struct msm_adsp_event_data),
2268 GFP_ATOMIC);
Meng Wang9730cdd2017-09-26 12:48:31 +08002269 if (!pp_event_package) {
Meng Wangb6afa8c2017-11-30 17:55:05 +08002270 spin_unlock_irqrestore(
2271 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302272 return -ENOMEM;
Meng Wang9730cdd2017-09-26 12:48:31 +08002273 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302274
2275 pp_event_package->event_type = i;
2276 pp_event_package->payload_len = payload_size;
2277 memcpy((void *)pp_event_package->payload,
2278 data->payload, payload_size);
2279 ac->cb(data->opcode, data->token,
2280 (void *)pp_event_package, ac->priv);
2281 kfree(pp_event_package);
Meng Wangb6afa8c2017-11-30 17:55:05 +08002282 spin_unlock_irqrestore(
2283 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302284 return 0;
2285 case ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2:
2286 pr_debug("%s: ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2 sesion %d status 0x%x msw %u lsw %u\n",
2287 __func__, ac->session, payload[0], payload[2],
2288 payload[1]);
2289 wake_up(&ac->cmd_wait);
2290 break;
2291 case ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2:
2292 pr_debug("%s: ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2 session %d status 0x%x msw %u lsw %u\n",
2293 __func__, ac->session, payload[0], payload[2],
2294 payload[1]);
2295 if (payload[0] == 0) {
2296 atomic_set(&ac->cmd_state, 0);
2297 /* ignore msw, as a delay that large shouldn't happen */
2298 ac->path_delay = payload[1];
2299 } else {
2300 atomic_set(&ac->cmd_state, payload[0]);
2301 ac->path_delay = UINT_MAX;
2302 }
2303 wake_up(&ac->cmd_wait);
2304 break;
2305 }
2306 if (ac->cb)
2307 ac->cb(data->opcode, data->token,
2308 data->payload, ac->priv);
Meng Wangb6afa8c2017-11-30 17:55:05 +08002309 spin_unlock_irqrestore(
2310 &(session[session_id].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302311 return 0;
2312}
2313
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302314/**
2315 * q6asm_is_cpu_buf_avail -
2316 * retrieve next CPU buf avail
2317 *
2318 * @dir: RX or TX direction
2319 * @ac: Audio client handle
2320 * @size: size pointer to be updated with size of buffer
2321 * @index: index pointer to be updated with
2322 * CPU buffer index available
2323 *
2324 * Returns buffer pointer on success or NULL on failure
2325 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302326void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size,
2327 uint32_t *index)
2328{
2329 void *data;
2330 unsigned char idx;
2331 struct audio_port_data *port;
2332
2333 if (!ac || ((dir != IN) && (dir != OUT))) {
2334 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
2335 return NULL;
2336 }
2337
2338 if (ac->io_mode & SYNC_IO_MODE) {
2339 port = &ac->port[dir];
2340
2341 mutex_lock(&port->lock);
2342 idx = port->cpu_buf;
2343 if (port->buf == NULL) {
2344 pr_err("%s: Buffer pointer null\n", __func__);
2345 mutex_unlock(&port->lock);
2346 return NULL;
2347 }
2348 /* dir 0: used = 0 means buf in use
2349 * dir 1: used = 1 means buf in use
2350 */
2351 if (port->buf[idx].used == dir) {
2352 /* To make it more robust, we could loop and get the
2353 * next avail buf, its risky though
2354 */
2355 pr_err("%s: Next buf idx[0x%x] not available, dir[%d]\n",
2356 __func__, idx, dir);
2357 mutex_unlock(&port->lock);
2358 return NULL;
2359 }
2360 *size = port->buf[idx].actual_size;
2361 *index = port->cpu_buf;
2362 data = port->buf[idx].data;
2363 dev_vdbg(ac->dev, "%s: session[%d]index[%d] data[%pK]size[%d]\n",
2364 __func__,
2365 ac->session,
2366 port->cpu_buf,
2367 data, *size);
2368 /* By default increase the cpu_buf cnt
2369 * user accesses this function,increase cpu
2370 * buf(to avoid another api)
2371 */
2372 port->buf[idx].used = dir;
2373 port->cpu_buf = q6asm_get_next_buf(ac, port->cpu_buf,
2374 port->max_buf_cnt);
2375 mutex_unlock(&port->lock);
2376 return data;
2377 }
2378 return NULL;
2379}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302380EXPORT_SYMBOL(q6asm_is_cpu_buf_avail);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302381
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302382/**
2383 * q6asm_cpu_buf_release -
2384 * releases cpu buffer for ASM
2385 *
2386 * @dir: RX or TX direction
2387 * @ac: Audio client handle
2388 *
2389 * Returns 0 on success or error on failure
2390 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302391int q6asm_cpu_buf_release(int dir, struct audio_client *ac)
2392{
2393 struct audio_port_data *port;
2394 int ret = 0;
2395 int idx;
2396
2397 if (!ac || ((dir != IN) && (dir != OUT))) {
2398 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
2399 ret = -EINVAL;
2400 goto exit;
2401 }
2402
2403 if (ac->io_mode & SYNC_IO_MODE) {
2404 port = &ac->port[dir];
2405 mutex_lock(&port->lock);
2406 idx = port->cpu_buf;
2407 if (port->cpu_buf == 0) {
2408 port->cpu_buf = port->max_buf_cnt - 1;
2409 } else if (port->cpu_buf < port->max_buf_cnt) {
2410 port->cpu_buf = port->cpu_buf - 1;
2411 } else {
2412 pr_err("%s: buffer index(%d) out of range\n",
2413 __func__, port->cpu_buf);
2414 ret = -EINVAL;
2415 mutex_unlock(&port->lock);
2416 goto exit;
2417 }
2418 port->buf[port->cpu_buf].used = dir ^ 1;
2419 mutex_unlock(&port->lock);
2420 }
2421exit:
2422 return ret;
2423}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302424EXPORT_SYMBOL(q6asm_cpu_buf_release);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302425
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302426/**
2427 * q6asm_is_cpu_buf_avail_nolock -
2428 * retrieve next CPU buf avail without lock acquire
2429 *
2430 * @dir: RX or TX direction
2431 * @ac: Audio client handle
2432 * @size: size pointer to be updated with size of buffer
2433 * @index: index pointer to be updated with
2434 * CPU buffer index available
2435 *
2436 * Returns buffer pointer on success or NULL on failure
2437 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302438void *q6asm_is_cpu_buf_avail_nolock(int dir, struct audio_client *ac,
2439 uint32_t *size, uint32_t *index)
2440{
2441 void *data;
2442 unsigned char idx;
2443 struct audio_port_data *port;
2444
2445 if (!ac || ((dir != IN) && (dir != OUT))) {
2446 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
2447 return NULL;
2448 }
2449
2450 port = &ac->port[dir];
2451
2452 idx = port->cpu_buf;
2453 if (port->buf == NULL) {
2454 pr_err("%s: Buffer pointer null\n", __func__);
2455 return NULL;
2456 }
2457 /*
2458 * dir 0: used = 0 means buf in use
2459 * dir 1: used = 1 means buf in use
2460 */
2461 if (port->buf[idx].used == dir) {
2462 /*
2463 * To make it more robust, we could loop and get the
2464 * next avail buf, its risky though
2465 */
2466 pr_err("%s: Next buf idx[0x%x] not available, dir[%d]\n",
2467 __func__, idx, dir);
2468 return NULL;
2469 }
2470 *size = port->buf[idx].actual_size;
2471 *index = port->cpu_buf;
2472 data = port->buf[idx].data;
2473 dev_vdbg(ac->dev, "%s: session[%d]index[%d] data[%pK]size[%d]\n",
2474 __func__, ac->session, port->cpu_buf,
2475 data, *size);
2476 /*
2477 * By default increase the cpu_buf cnt
2478 * user accesses this function,increase cpu
2479 * buf(to avoid another api)
2480 */
2481 port->buf[idx].used = dir;
2482 port->cpu_buf = q6asm_get_next_buf(ac, port->cpu_buf,
2483 port->max_buf_cnt);
2484 return data;
2485}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302486EXPORT_SYMBOL(q6asm_is_cpu_buf_avail_nolock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302487
2488int q6asm_is_dsp_buf_avail(int dir, struct audio_client *ac)
2489{
2490 int ret = -1;
2491 struct audio_port_data *port;
2492 uint32_t idx;
2493
2494 if (!ac || (dir != OUT)) {
2495 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
2496 return ret;
2497 }
2498
2499 if (ac->io_mode & SYNC_IO_MODE) {
2500 port = &ac->port[dir];
2501
2502 mutex_lock(&port->lock);
2503 idx = port->dsp_buf;
2504
2505 if (port->buf[idx].used == (dir ^ 1)) {
2506 /* To make it more robust, we could loop and get the
2507 * next avail buf, its risky though
2508 */
2509 pr_err("%s: Next buf idx[0x%x] not available, dir[%d]\n",
2510 __func__, idx, dir);
2511 mutex_unlock(&port->lock);
2512 return ret;
2513 }
2514 dev_vdbg(ac->dev, "%s: session[%d]dsp_buf=%d cpu_buf=%d\n",
2515 __func__,
2516 ac->session, port->dsp_buf, port->cpu_buf);
2517 ret = ((port->dsp_buf != port->cpu_buf) ? 0 : -1);
2518 mutex_unlock(&port->lock);
2519 }
2520 return ret;
2521}
2522
2523static void __q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
2524 uint32_t pkt_size, uint32_t cmd_flg, uint32_t stream_id)
2525{
Meng Wangb6afa8c2017-11-30 17:55:05 +08002526 unsigned long flags;
2527
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302528 dev_vdbg(ac->dev, "%s: pkt_size=%d cmd_flg=%d session=%d stream_id=%d\n",
2529 __func__, pkt_size, cmd_flg, ac->session, stream_id);
2530 mutex_lock(&ac->cmd_lock);
Meng Wangb6afa8c2017-11-30 17:55:05 +08002531 spin_lock_irqsave(&(session[ac->session].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302532 if (ac->apr == NULL) {
2533 pr_err("%s: AC APR handle NULL", __func__);
Meng Wangb6afa8c2017-11-30 17:55:05 +08002534 spin_unlock_irqrestore(
2535 &(session[ac->session].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302536 mutex_unlock(&ac->cmd_lock);
2537 return;
2538 }
2539
2540 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2541 APR_HDR_LEN(sizeof(struct apr_hdr)),
2542 APR_PKT_VER);
2543 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
2544 hdr->src_domain = APR_DOMAIN_APPS;
2545 hdr->dest_svc = APR_SVC_ASM;
2546 hdr->dest_domain = APR_DOMAIN_ADSP;
2547 hdr->src_port = ((ac->session << 8) & 0xFF00) | (stream_id);
2548 hdr->dest_port = ((ac->session << 8) & 0xFF00) | (stream_id);
2549 if (cmd_flg)
2550 q6asm_update_token(&hdr->token,
2551 ac->session,
2552 0, /* Stream ID is NA */
2553 0, /* Buffer index is NA */
2554 0, /* Direction flag is NA */
2555 WAIT_CMD);
2556
2557 hdr->pkt_size = pkt_size;
Meng Wangb6afa8c2017-11-30 17:55:05 +08002558 spin_unlock_irqrestore(
2559 &(session[ac->session].session_lock), flags);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302560 mutex_unlock(&ac->cmd_lock);
2561}
2562
2563static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
2564 uint32_t pkt_size, uint32_t cmd_flg)
2565{
2566 __q6asm_add_hdr(ac, hdr, pkt_size, cmd_flg, ac->stream_id);
2567}
2568
2569static void q6asm_stream_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
2570 uint32_t pkt_size, uint32_t cmd_flg, int32_t stream_id)
2571{
2572 __q6asm_add_hdr(ac, hdr, pkt_size, cmd_flg, stream_id);
2573}
2574
2575static void __q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
2576 uint32_t pkt_size, uint32_t cmd_flg,
2577 uint32_t stream_id, u8 no_wait_flag)
2578{
2579 dev_vdbg(ac->dev, "%s: pkt_size = %d, cmd_flg = %d, session = %d stream_id=%d\n",
2580 __func__, pkt_size, cmd_flg, ac->session, stream_id);
2581 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2582 APR_HDR_LEN(sizeof(struct apr_hdr)),
2583 APR_PKT_VER);
2584 if (ac->apr == NULL) {
2585 pr_err("%s: AC APR is NULL", __func__);
2586 return;
2587 }
2588 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
2589 hdr->src_domain = APR_DOMAIN_APPS;
2590 hdr->dest_svc = APR_SVC_ASM;
2591 hdr->dest_domain = APR_DOMAIN_ADSP;
2592 hdr->src_port = ((ac->session << 8) & 0xFF00) | (stream_id);
2593 hdr->dest_port = ((ac->session << 8) & 0xFF00) | (stream_id);
2594 if (cmd_flg) {
2595 q6asm_update_token(&hdr->token,
2596 ac->session,
2597 0, /* Stream ID is NA */
2598 0, /* Buffer index is NA */
2599 0, /* Direction flag is NA */
2600 no_wait_flag);
2601
2602 }
2603 hdr->pkt_size = pkt_size;
2604}
2605
2606static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
2607 uint32_t pkt_size, uint32_t cmd_flg)
2608{
2609 __q6asm_add_hdr_async(ac, hdr, pkt_size, cmd_flg,
2610 ac->stream_id, WAIT_CMD);
2611}
2612
2613static void q6asm_stream_add_hdr_async(struct audio_client *ac,
2614 struct apr_hdr *hdr, uint32_t pkt_size,
2615 uint32_t cmd_flg, int32_t stream_id)
2616{
2617 __q6asm_add_hdr_async(ac, hdr, pkt_size, cmd_flg,
2618 stream_id, NO_WAIT_CMD);
2619}
2620
2621static void q6asm_add_hdr_custom_topology(struct audio_client *ac,
2622 struct apr_hdr *hdr,
2623 uint32_t pkt_size)
2624{
2625 pr_debug("%s: pkt_size=%d session=%d\n",
2626 __func__, pkt_size, ac->session);
2627 if (ac->apr == NULL) {
2628 pr_err("%s: AC APR handle NULL\n", __func__);
2629 return;
2630 }
2631
2632 mutex_lock(&ac->cmd_lock);
2633 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2634 APR_HDR_LEN(sizeof(struct apr_hdr)),
2635 APR_PKT_VER);
2636 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
2637 hdr->src_domain = APR_DOMAIN_APPS;
2638 hdr->dest_svc = APR_SVC_ASM;
2639 hdr->dest_domain = APR_DOMAIN_ADSP;
2640 hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01;
2641 hdr->dest_port = 0;
2642 q6asm_update_token(&hdr->token,
2643 ac->session,
2644 0, /* Stream ID is NA */
2645 0, /* Buffer index is NA */
2646 0, /* Direction flag is NA */
2647 WAIT_CMD);
2648 hdr->pkt_size = pkt_size;
2649 mutex_unlock(&ac->cmd_lock);
2650}
2651
2652static void q6asm_add_mmaphdr(struct audio_client *ac, struct apr_hdr *hdr,
2653 u32 pkt_size, int dir)
2654{
2655 pr_debug("%s: pkt size=%d\n",
2656 __func__, pkt_size);
2657 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2658 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2659 hdr->src_port = 0;
2660 hdr->dest_port = 0;
2661 q6asm_update_token(&hdr->token,
2662 ac->session,
2663 0, /* Stream ID is NA */
2664 0, /* Buffer index is NA */
2665 dir,
2666 WAIT_CMD);
2667 hdr->pkt_size = pkt_size;
2668}
2669
2670static int __q6asm_open_read(struct audio_client *ac,
2671 uint32_t format, uint16_t bits_per_sample,
2672 uint32_t pcm_format_block_ver,
2673 bool ts_mode)
2674{
2675 int rc = 0x00;
2676 struct asm_stream_cmd_open_read_v3 open;
2677
2678 config_debug_fs_reset_index();
2679
2680 if (ac == NULL) {
2681 pr_err("%s: APR handle NULL\n", __func__);
2682 return -EINVAL;
2683 }
2684 if (ac->apr == NULL) {
2685 pr_err("%s: AC APR handle NULL\n", __func__);
2686 return -EINVAL;
2687 }
2688 pr_debug("%s: session[%d]\n", __func__, ac->session);
2689
2690 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
2691 atomic_set(&ac->cmd_state, -1);
2692 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ_V3;
2693 /* Stream prio : High, provide meta info with encoded frames */
2694 open.src_endpointype = ASM_END_POINT_DEVICE_MATRIX;
2695
2696 open.preprocopo_id = q6asm_get_asm_topology_cal();
2697 open.bits_per_sample = bits_per_sample;
2698 open.mode_flags = 0x0;
2699
2700 ac->topology = open.preprocopo_id;
2701 ac->app_type = q6asm_get_asm_app_type_cal();
2702 if (ac->perf_mode == LOW_LATENCY_PCM_MODE) {
2703 open.mode_flags |= ASM_LOW_LATENCY_TX_STREAM_SESSION <<
2704 ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ;
2705 } else {
2706 open.mode_flags |= ASM_LEGACY_STREAM_SESSION <<
2707 ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ;
2708 }
2709
2710 switch (format) {
2711 case FORMAT_LINEAR_PCM:
2712 open.mode_flags |= 0x00;
2713 open.enc_cfg_id = q6asm_get_pcm_format_id(pcm_format_block_ver);
2714 if (ts_mode)
2715 open.mode_flags |= ABSOLUTE_TIMESTAMP_ENABLE;
2716 break;
2717 case FORMAT_MPEG4_AAC:
2718 open.mode_flags |= BUFFER_META_ENABLE;
2719 open.enc_cfg_id = ASM_MEDIA_FMT_AAC_V2;
2720 break;
2721 case FORMAT_G711_ALAW_FS:
2722 open.mode_flags |= BUFFER_META_ENABLE;
2723 open.enc_cfg_id = ASM_MEDIA_FMT_G711_ALAW_FS;
2724 break;
2725 case FORMAT_G711_MLAW_FS:
2726 open.mode_flags |= BUFFER_META_ENABLE;
2727 open.enc_cfg_id = ASM_MEDIA_FMT_G711_MLAW_FS;
2728 break;
2729 case FORMAT_V13K:
2730 open.mode_flags |= BUFFER_META_ENABLE;
2731 open.enc_cfg_id = ASM_MEDIA_FMT_V13K_FS;
2732 break;
2733 case FORMAT_EVRC:
2734 open.mode_flags |= BUFFER_META_ENABLE;
2735 open.enc_cfg_id = ASM_MEDIA_FMT_EVRC_FS;
2736 break;
2737 case FORMAT_AMRNB:
2738 open.mode_flags |= BUFFER_META_ENABLE;
2739 open.enc_cfg_id = ASM_MEDIA_FMT_AMRNB_FS;
2740 break;
2741 case FORMAT_AMRWB:
2742 open.mode_flags |= BUFFER_META_ENABLE;
2743 open.enc_cfg_id = ASM_MEDIA_FMT_AMRWB_FS;
2744 break;
2745 default:
2746 pr_err("%s: Invalid format 0x%x\n",
2747 __func__, format);
2748 rc = -EINVAL;
2749 goto fail_cmd;
2750 }
2751 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
2752 if (rc < 0) {
2753 pr_err("%s: open failed op[0x%x]rc[%d]\n",
2754 __func__, open.hdr.opcode, rc);
2755 rc = -EINVAL;
2756 goto fail_cmd;
2757 }
2758 rc = wait_event_timeout(ac->cmd_wait,
2759 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
2760 if (!rc) {
2761 pr_err("%s: timeout. waited for open read\n",
2762 __func__);
2763 rc = -ETIMEDOUT;
2764 goto fail_cmd;
2765 }
2766 if (atomic_read(&ac->cmd_state) > 0) {
2767 pr_err("%s: DSP returned error[%s]\n",
2768 __func__, adsp_err_get_err_str(
2769 atomic_read(&ac->cmd_state)));
2770 rc = adsp_err_get_lnx_err_code(
2771 atomic_read(&ac->cmd_state));
2772 goto fail_cmd;
2773 }
2774
2775 ac->io_mode |= TUN_READ_IO_MODE;
2776
2777 return 0;
2778fail_cmd:
2779 return rc;
2780}
2781
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302782/**
2783 * q6asm_open_read -
2784 * command to open ASM in read mode
2785 *
2786 * @ac: Audio client handle
2787 * @format: capture format for ASM
2788 *
2789 * Returns 0 on success or error on failure
2790 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302791int q6asm_open_read(struct audio_client *ac,
2792 uint32_t format)
2793{
2794 return __q6asm_open_read(ac, format, 16,
2795 PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/,
2796 false/*ts_mode*/);
2797}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302798EXPORT_SYMBOL(q6asm_open_read);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302799
2800int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
2801 uint16_t bits_per_sample)
2802{
2803 return __q6asm_open_read(ac, format, bits_per_sample,
2804 PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/,
2805 false/*ts_mode*/);
2806}
2807
2808/*
2809 * asm_open_read_v3 - Opens audio capture session
2810 *
2811 * @ac: Client session handle
2812 * @format: encoder format
2813 * @bits_per_sample: bit width of capture session
2814 */
2815int q6asm_open_read_v3(struct audio_client *ac, uint32_t format,
2816 uint16_t bits_per_sample)
2817{
2818 return __q6asm_open_read(ac, format, bits_per_sample,
2819 PCM_MEDIA_FORMAT_V3/*media fmt block ver*/,
2820 false/*ts_mode*/);
2821}
2822EXPORT_SYMBOL(q6asm_open_read_v3);
2823
2824/*
2825 * asm_open_read_v4 - Opens audio capture session
2826 *
2827 * @ac: Client session handle
2828 * @format: encoder format
2829 * @bits_per_sample: bit width of capture session
2830 * @ts_mode: timestamp mode
2831 */
2832int q6asm_open_read_v4(struct audio_client *ac, uint32_t format,
2833 uint16_t bits_per_sample, bool ts_mode)
2834{
2835 return __q6asm_open_read(ac, format, bits_per_sample,
2836 PCM_MEDIA_FORMAT_V4 /*media fmt block ver*/,
2837 ts_mode);
2838}
2839EXPORT_SYMBOL(q6asm_open_read_v4);
2840
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302841/**
2842 * q6asm_open_write_compressed -
2843 * command to open ASM in compressed write mode
2844 *
2845 * @ac: Audio client handle
2846 * @format: playback format for ASM
2847 * @passthrough_flag: flag to indicate passthrough option
2848 *
2849 * Returns 0 on success or error on failure
2850 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302851int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format,
2852 uint32_t passthrough_flag)
2853{
2854 int rc = 0;
2855 struct asm_stream_cmd_open_write_compressed open;
2856
2857 if (ac == NULL) {
2858 pr_err("%s: ac[%pK] NULL\n", __func__, ac);
2859 rc = -EINVAL;
2860 goto fail_cmd;
2861 }
2862
2863 if (ac->apr == NULL) {
2864 pr_err("%s: APR handle[%pK] NULL\n", __func__, ac->apr);
2865 rc = -EINVAL;
2866 goto fail_cmd;
2867 }
2868 pr_debug("%s: session[%d] wr_format[0x%x]", __func__, ac->session,
2869 format);
2870
2871 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
2872 open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED;
2873 atomic_set(&ac->cmd_state, -1);
2874
2875 switch (format) {
2876 case FORMAT_AC3:
2877 open.fmt_id = ASM_MEDIA_FMT_AC3;
2878 break;
2879 case FORMAT_EAC3:
2880 open.fmt_id = ASM_MEDIA_FMT_EAC3;
2881 break;
2882 case FORMAT_DTS:
2883 open.fmt_id = ASM_MEDIA_FMT_DTS;
2884 break;
2885 case FORMAT_DSD:
2886 open.fmt_id = ASM_MEDIA_FMT_DSD;
2887 break;
2888 case FORMAT_GEN_COMPR:
2889 open.fmt_id = ASM_MEDIA_FMT_GENERIC_COMPRESSED;
2890 break;
2891 case FORMAT_TRUEHD:
2892 open.fmt_id = ASM_MEDIA_FMT_TRUEHD;
2893 break;
2894 case FORMAT_IEC61937:
2895 open.fmt_id = ASM_MEDIA_FMT_IEC;
2896 break;
2897 default:
2898 pr_err("%s: Invalid format[%d]\n", __func__, format);
2899 rc = -EINVAL;
2900 goto fail_cmd;
2901 }
2902 /* Below flag indicates the DSP that Compressed audio input
2903 * stream is not IEC 61937 or IEC 60958 packetizied
2904 */
2905 if (passthrough_flag == COMPRESSED_PASSTHROUGH ||
2906 passthrough_flag == COMPRESSED_PASSTHROUGH_DSD ||
2907 passthrough_flag == COMPRESSED_PASSTHROUGH_GEN) {
2908 open.flags = 0x0;
2909 pr_debug("%s: Flag 0 COMPRESSED_PASSTHROUGH\n", __func__);
2910 } else if (passthrough_flag == COMPRESSED_PASSTHROUGH_CONVERT) {
2911 open.flags = 0x8;
2912 pr_debug("%s: Flag 8 - COMPRESSED_PASSTHROUGH_CONVERT\n",
2913 __func__);
2914 } else if (passthrough_flag == COMPRESSED_PASSTHROUGH_IEC61937) {
2915 open.flags = 0x1;
2916 pr_debug("%s: Flag 1 - COMPRESSED_PASSTHROUGH_IEC61937\n",
2917 __func__);
2918 } else {
2919 pr_err("%s: Invalid passthrough type[%d]\n",
2920 __func__, passthrough_flag);
2921 rc = -EINVAL;
2922 goto fail_cmd;
2923 }
2924 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
2925 if (rc < 0) {
2926 pr_err("%s: open failed op[0x%x]rc[%d]\n",
2927 __func__, open.hdr.opcode, rc);
2928 rc = -EINVAL;
2929 goto fail_cmd;
2930 }
2931 rc = wait_event_timeout(ac->cmd_wait,
2932 (atomic_read(&ac->cmd_state) >= 0), 1*HZ);
2933 if (!rc) {
2934 pr_err("%s: timeout. waited for OPEN_WRITE_COMPR rc[%d]\n",
2935 __func__, rc);
2936 rc = -ETIMEDOUT;
2937 goto fail_cmd;
2938 }
2939
2940 if (atomic_read(&ac->cmd_state) > 0) {
2941 pr_err("%s: DSP returned error[%s]\n",
2942 __func__, adsp_err_get_err_str(
2943 atomic_read(&ac->cmd_state)));
2944 rc = adsp_err_get_lnx_err_code(
2945 atomic_read(&ac->cmd_state));
2946 goto fail_cmd;
2947 }
2948
2949 return 0;
2950
2951fail_cmd:
2952 return rc;
2953}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302954EXPORT_SYMBOL(q6asm_open_write_compressed);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302955
2956static int __q6asm_open_write(struct audio_client *ac, uint32_t format,
2957 uint16_t bits_per_sample, uint32_t stream_id,
2958 bool is_gapless_mode,
2959 uint32_t pcm_format_block_ver)
2960{
2961 int rc = 0x00;
2962 struct asm_stream_cmd_open_write_v3 open;
2963
2964 if (ac == NULL) {
2965 pr_err("%s: APR handle NULL\n", __func__);
2966 return -EINVAL;
2967 }
2968 if (ac->apr == NULL) {
2969 pr_err("%s: AC APR handle NULL\n", __func__);
2970 return -EINVAL;
2971 }
2972
2973 dev_vdbg(ac->dev, "%s: session[%d] wr_format[0x%x]\n",
2974 __func__, ac->session, format);
2975
2976 q6asm_stream_add_hdr(ac, &open.hdr, sizeof(open), TRUE, stream_id);
2977 atomic_set(&ac->cmd_state, -1);
2978 /*
2979 * Updated the token field with stream/session for compressed playback
2980 * Platform driver must know the the stream with which the command is
2981 * associated
2982 */
2983 if (ac->io_mode & COMPRESSED_STREAM_IO)
2984 q6asm_update_token(&open.hdr.token,
2985 ac->session,
2986 stream_id,
2987 0, /* Buffer index is NA */
2988 0, /* Direction flag is NA */
2989 WAIT_CMD);
2990
2991 dev_vdbg(ac->dev, "%s: token = 0x%x, stream_id %d, session 0x%x\n",
2992 __func__, open.hdr.token, stream_id, ac->session);
2993 open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3;
2994 open.mode_flags = 0x00;
2995 if (ac->perf_mode == ULL_POST_PROCESSING_PCM_MODE)
2996 open.mode_flags |= ASM_ULL_POST_PROCESSING_STREAM_SESSION;
2997 else if (ac->perf_mode == ULTRA_LOW_LATENCY_PCM_MODE)
2998 open.mode_flags |= ASM_ULTRA_LOW_LATENCY_STREAM_SESSION;
2999 else if (ac->perf_mode == LOW_LATENCY_PCM_MODE)
3000 open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION;
3001 else {
3002 open.mode_flags |= ASM_LEGACY_STREAM_SESSION;
3003 if (is_gapless_mode)
3004 open.mode_flags |= 1 << ASM_SHIFT_GAPLESS_MODE_FLAG;
3005 }
3006
3007 /* source endpoint : matrix */
3008 open.sink_endpointype = ASM_END_POINT_DEVICE_MATRIX;
3009 open.bits_per_sample = bits_per_sample;
3010
3011 open.postprocopo_id = q6asm_get_asm_topology_cal();
3012 if (ac->perf_mode != LEGACY_PCM_MODE)
3013 open.postprocopo_id = ASM_STREAM_POSTPROCOPO_ID_NONE;
3014
3015 pr_debug("%s: perf_mode %d asm_topology 0x%x bps %d\n", __func__,
3016 ac->perf_mode, open.postprocopo_id, open.bits_per_sample);
3017
3018 /*
3019 * For Gapless playback it will use the same session for next stream,
3020 * So use the same topology
3021 */
3022 if (!ac->topology) {
3023 ac->topology = open.postprocopo_id;
3024 ac->app_type = q6asm_get_asm_app_type_cal();
3025 }
3026 switch (format) {
3027 case FORMAT_LINEAR_PCM:
3028 open.dec_fmt_id = q6asm_get_pcm_format_id(pcm_format_block_ver);
3029 break;
3030 case FORMAT_MPEG4_AAC:
3031 open.dec_fmt_id = ASM_MEDIA_FMT_AAC_V2;
3032 break;
3033 case FORMAT_MPEG4_MULTI_AAC:
3034 open.dec_fmt_id = ASM_MEDIA_FMT_AAC_V2;
3035 break;
3036 case FORMAT_WMA_V9:
3037 open.dec_fmt_id = ASM_MEDIA_FMT_WMA_V9_V2;
3038 break;
3039 case FORMAT_WMA_V10PRO:
3040 open.dec_fmt_id = ASM_MEDIA_FMT_WMA_V10PRO_V2;
3041 break;
3042 case FORMAT_MP3:
3043 open.dec_fmt_id = ASM_MEDIA_FMT_MP3;
3044 break;
3045 case FORMAT_AC3:
3046 open.dec_fmt_id = ASM_MEDIA_FMT_AC3;
3047 break;
3048 case FORMAT_EAC3:
3049 open.dec_fmt_id = ASM_MEDIA_FMT_EAC3;
3050 break;
3051 case FORMAT_MP2:
3052 open.dec_fmt_id = ASM_MEDIA_FMT_MP2;
3053 break;
3054 case FORMAT_FLAC:
3055 open.dec_fmt_id = ASM_MEDIA_FMT_FLAC;
3056 break;
3057 case FORMAT_ALAC:
3058 open.dec_fmt_id = ASM_MEDIA_FMT_ALAC;
3059 break;
3060 case FORMAT_VORBIS:
3061 open.dec_fmt_id = ASM_MEDIA_FMT_VORBIS;
3062 break;
3063 case FORMAT_APE:
3064 open.dec_fmt_id = ASM_MEDIA_FMT_APE;
3065 break;
3066 case FORMAT_DSD:
3067 open.dec_fmt_id = ASM_MEDIA_FMT_DSD;
3068 break;
3069 case FORMAT_APTX:
3070 open.dec_fmt_id = ASM_MEDIA_FMT_APTX;
3071 break;
3072 case FORMAT_GEN_COMPR:
3073 open.dec_fmt_id = ASM_MEDIA_FMT_GENERIC_COMPRESSED;
3074 break;
3075 default:
3076 pr_err("%s: Invalid format 0x%x\n", __func__, format);
3077 rc = -EINVAL;
3078 goto fail_cmd;
3079 }
3080 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
3081 if (rc < 0) {
3082 pr_err("%s: open failed op[0x%x]rc[%d]\n",
3083 __func__, open.hdr.opcode, rc);
3084 rc = -EINVAL;
3085 goto fail_cmd;
3086 }
3087 rc = wait_event_timeout(ac->cmd_wait,
3088 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
3089 if (!rc) {
3090 pr_err("%s: timeout. waited for open write\n", __func__);
3091 rc = -ETIMEDOUT;
3092 goto fail_cmd;
3093 }
3094 if (atomic_read(&ac->cmd_state) > 0) {
3095 pr_err("%s: DSP returned error[%s]\n",
3096 __func__, adsp_err_get_err_str(
3097 atomic_read(&ac->cmd_state)));
3098 rc = adsp_err_get_lnx_err_code(
3099 atomic_read(&ac->cmd_state));
3100 goto fail_cmd;
3101 }
3102 ac->io_mode |= TUN_WRITE_IO_MODE;
3103
3104 return 0;
3105fail_cmd:
3106 return rc;
3107}
3108
3109int q6asm_open_write(struct audio_client *ac, uint32_t format)
3110{
3111 return __q6asm_open_write(ac, format, 16, ac->stream_id,
3112 false /*gapless*/,
3113 PCM_MEDIA_FORMAT_V2 /*pcm_format_block_ver*/);
3114}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303115EXPORT_SYMBOL(q6asm_open_write);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303116
3117int q6asm_open_write_v2(struct audio_client *ac, uint32_t format,
3118 uint16_t bits_per_sample)
3119{
3120 return __q6asm_open_write(ac, format, bits_per_sample,
3121 ac->stream_id, false /*gapless*/,
3122 PCM_MEDIA_FORMAT_V2 /*pcm_format_block_ver*/);
3123}
3124
3125/*
3126 * q6asm_open_write_v3 - Opens audio playback session
3127 *
3128 * @ac: Client session handle
3129 * @format: decoder format
3130 * @bits_per_sample: bit width of playback session
3131 */
3132int q6asm_open_write_v3(struct audio_client *ac, uint32_t format,
3133 uint16_t bits_per_sample)
3134{
3135 return __q6asm_open_write(ac, format, bits_per_sample,
3136 ac->stream_id, false /*gapless*/,
3137 PCM_MEDIA_FORMAT_V3 /*pcm_format_block_ver*/);
3138}
3139EXPORT_SYMBOL(q6asm_open_write_v3);
3140
3141/*
3142 * q6asm_open_write_v4 - Opens audio playback session
3143 *
3144 * @ac: Client session handle
3145 * @format: decoder format
3146 * @bits_per_sample: bit width of playback session
3147 */
3148int q6asm_open_write_v4(struct audio_client *ac, uint32_t format,
3149 uint16_t bits_per_sample)
3150{
3151 return __q6asm_open_write(ac, format, bits_per_sample,
3152 ac->stream_id, false /*gapless*/,
3153 PCM_MEDIA_FORMAT_V4 /*pcm_format_block_ver*/);
3154}
3155EXPORT_SYMBOL(q6asm_open_write_v4);
3156
3157int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format,
3158 uint16_t bits_per_sample, int32_t stream_id,
3159 bool is_gapless_mode)
3160{
3161 return __q6asm_open_write(ac, format, bits_per_sample,
3162 stream_id, is_gapless_mode,
3163 PCM_MEDIA_FORMAT_V2 /*pcm_format_block_ver*/);
3164}
3165
3166/*
3167 * q6asm_stream_open_write_v3 - Creates audio stream for playback
3168 *
3169 * @ac: Client session handle
3170 * @format: asm playback format
3171 * @bits_per_sample: bit width of requested stream
3172 * @stream_id: stream id of stream to be associated with this session
3173 * @is_gapless_mode: true if gapless mode needs to be enabled
3174 */
3175int q6asm_stream_open_write_v3(struct audio_client *ac, uint32_t format,
3176 uint16_t bits_per_sample, int32_t stream_id,
3177 bool is_gapless_mode)
3178{
3179 return __q6asm_open_write(ac, format, bits_per_sample,
3180 stream_id, is_gapless_mode,
3181 PCM_MEDIA_FORMAT_V3 /*pcm_format_block_ver*/);
3182}
3183EXPORT_SYMBOL(q6asm_stream_open_write_v3);
3184
3185/*
3186 * q6asm_stream_open_write_v4 - Creates audio stream for playback
3187 *
3188 * @ac: Client session handle
3189 * @format: asm playback format
3190 * @bits_per_sample: bit width of requested stream
3191 * @stream_id: stream id of stream to be associated with this session
3192 * @is_gapless_mode: true if gapless mode needs to be enabled
3193 */
3194int q6asm_stream_open_write_v4(struct audio_client *ac, uint32_t format,
3195 uint16_t bits_per_sample, int32_t stream_id,
3196 bool is_gapless_mode)
3197{
3198 return __q6asm_open_write(ac, format, bits_per_sample,
3199 stream_id, is_gapless_mode,
3200 PCM_MEDIA_FORMAT_V4 /*pcm_format_block_ver*/);
3201}
3202EXPORT_SYMBOL(q6asm_stream_open_write_v4);
3203
3204static int __q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format,
3205 uint32_t wr_format, bool is_meta_data_mode,
3206 uint32_t bits_per_sample,
3207 bool overwrite_topology, int topology)
3208{
3209 int rc = 0x00;
3210 struct asm_stream_cmd_open_readwrite_v2 open;
3211
3212 if (ac == NULL) {
3213 pr_err("%s: APR handle NULL\n", __func__);
3214 return -EINVAL;
3215 }
3216 if (ac->apr == NULL) {
3217 pr_err("%s: AC APR handle NULL\n", __func__);
3218 return -EINVAL;
3219 }
3220 pr_debug("%s: session[%d]\n", __func__, ac->session);
3221 pr_debug("%s: wr_format[0x%x]rd_format[0x%x]\n",
3222 __func__, wr_format, rd_format);
3223
3224 ac->io_mode |= NT_MODE;
3225 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
3226 atomic_set(&ac->cmd_state, -1);
3227 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READWRITE_V2;
3228
3229 open.mode_flags = is_meta_data_mode ? BUFFER_META_ENABLE : 0;
3230 open.bits_per_sample = bits_per_sample;
3231 /* source endpoint : matrix */
3232 open.postprocopo_id = q6asm_get_asm_topology_cal();
3233
3234 open.postprocopo_id = overwrite_topology ?
3235 topology : open.postprocopo_id;
3236 ac->topology = open.postprocopo_id;
3237 ac->app_type = q6asm_get_asm_app_type_cal();
3238
3239
3240 switch (wr_format) {
3241 case FORMAT_LINEAR_PCM:
3242 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
3243 open.dec_fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
3244 break;
3245 case FORMAT_MPEG4_AAC:
3246 open.dec_fmt_id = ASM_MEDIA_FMT_AAC_V2;
3247 break;
3248 case FORMAT_MPEG4_MULTI_AAC:
3249 open.dec_fmt_id = ASM_MEDIA_FMT_AAC_V2;
3250 break;
3251 case FORMAT_WMA_V9:
3252 open.dec_fmt_id = ASM_MEDIA_FMT_WMA_V9_V2;
3253 break;
3254 case FORMAT_WMA_V10PRO:
3255 open.dec_fmt_id = ASM_MEDIA_FMT_WMA_V10PRO_V2;
3256 break;
3257 case FORMAT_AMRNB:
3258 open.dec_fmt_id = ASM_MEDIA_FMT_AMRNB_FS;
3259 break;
3260 case FORMAT_AMRWB:
3261 open.dec_fmt_id = ASM_MEDIA_FMT_AMRWB_FS;
3262 break;
3263 case FORMAT_AMR_WB_PLUS:
3264 open.dec_fmt_id = ASM_MEDIA_FMT_AMR_WB_PLUS_V2;
3265 break;
3266 case FORMAT_V13K:
3267 open.dec_fmt_id = ASM_MEDIA_FMT_V13K_FS;
3268 break;
3269 case FORMAT_EVRC:
3270 open.dec_fmt_id = ASM_MEDIA_FMT_EVRC_FS;
3271 break;
3272 case FORMAT_EVRCB:
3273 open.dec_fmt_id = ASM_MEDIA_FMT_EVRCB_FS;
3274 break;
3275 case FORMAT_EVRCWB:
3276 open.dec_fmt_id = ASM_MEDIA_FMT_EVRCWB_FS;
3277 break;
3278 case FORMAT_MP3:
3279 open.dec_fmt_id = ASM_MEDIA_FMT_MP3;
3280 break;
3281 case FORMAT_ALAC:
3282 open.dec_fmt_id = ASM_MEDIA_FMT_ALAC;
3283 break;
3284 case FORMAT_APE:
3285 open.dec_fmt_id = ASM_MEDIA_FMT_APE;
3286 break;
3287 case FORMAT_DSD:
3288 open.dec_fmt_id = ASM_MEDIA_FMT_DSD;
3289 break;
3290 case FORMAT_G711_ALAW_FS:
3291 open.dec_fmt_id = ASM_MEDIA_FMT_G711_ALAW_FS;
3292 break;
3293 case FORMAT_G711_MLAW_FS:
3294 open.dec_fmt_id = ASM_MEDIA_FMT_G711_MLAW_FS;
3295 break;
3296 default:
3297 pr_err("%s: Invalid format 0x%x\n",
3298 __func__, wr_format);
3299 rc = -EINVAL;
3300 goto fail_cmd;
3301 }
3302
3303 switch (rd_format) {
3304 case FORMAT_LINEAR_PCM:
3305 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
3306 open.enc_cfg_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
3307 break;
3308 case FORMAT_MPEG4_AAC:
3309 open.enc_cfg_id = ASM_MEDIA_FMT_AAC_V2;
3310 break;
3311 case FORMAT_G711_ALAW_FS:
3312 open.enc_cfg_id = ASM_MEDIA_FMT_G711_ALAW_FS;
3313 break;
3314 case FORMAT_G711_MLAW_FS:
3315 open.enc_cfg_id = ASM_MEDIA_FMT_G711_MLAW_FS;
3316 break;
3317 case FORMAT_V13K:
3318 open.enc_cfg_id = ASM_MEDIA_FMT_V13K_FS;
3319 break;
3320 case FORMAT_EVRC:
3321 open.enc_cfg_id = ASM_MEDIA_FMT_EVRC_FS;
3322 break;
3323 case FORMAT_AMRNB:
3324 open.enc_cfg_id = ASM_MEDIA_FMT_AMRNB_FS;
3325 break;
3326 case FORMAT_AMRWB:
3327 open.enc_cfg_id = ASM_MEDIA_FMT_AMRWB_FS;
3328 break;
3329 case FORMAT_ALAC:
3330 open.enc_cfg_id = ASM_MEDIA_FMT_ALAC;
3331 break;
3332 case FORMAT_APE:
3333 open.enc_cfg_id = ASM_MEDIA_FMT_APE;
3334 break;
3335 default:
3336 pr_err("%s: Invalid format 0x%x\n",
3337 __func__, rd_format);
3338 rc = -EINVAL;
3339 goto fail_cmd;
3340 }
3341 dev_vdbg(ac->dev, "%s: rdformat[0x%x]wrformat[0x%x]\n", __func__,
3342 open.enc_cfg_id, open.dec_fmt_id);
3343
3344 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
3345 if (rc < 0) {
3346 pr_err("%s: open failed op[0x%x]rc[%d]\n",
3347 __func__, open.hdr.opcode, rc);
3348 rc = -EINVAL;
3349 goto fail_cmd;
3350 }
3351 rc = wait_event_timeout(ac->cmd_wait,
3352 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
3353 if (!rc) {
3354 pr_err("%s: timeout. waited for open read-write\n",
3355 __func__);
3356 rc = -ETIMEDOUT;
3357 goto fail_cmd;
3358 }
3359 if (atomic_read(&ac->cmd_state) > 0) {
3360 pr_err("%s: DSP returned error[%s]\n",
3361 __func__, adsp_err_get_err_str(
3362 atomic_read(&ac->cmd_state)));
3363 rc = adsp_err_get_lnx_err_code(
3364 atomic_read(&ac->cmd_state));
3365 goto fail_cmd;
3366 }
3367
3368 return 0;
3369fail_cmd:
3370 return rc;
3371}
3372
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303373/**
3374 * q6asm_open_read_write -
3375 * command to open ASM in read/write mode
3376 *
3377 * @ac: Audio client handle
3378 * @rd_format: capture format for ASM
3379 * @wr_format: playback format for ASM
3380 *
3381 * Returns 0 on success or error on failure
3382 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303383int q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format,
3384 uint32_t wr_format)
3385{
3386 return __q6asm_open_read_write(ac, rd_format, wr_format,
3387 true/*meta data mode*/,
3388 16 /*bits_per_sample*/,
3389 false /*overwrite_topology*/, 0);
3390}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303391EXPORT_SYMBOL(q6asm_open_read_write);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303392
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303393/**
3394 * q6asm_open_read_write_v2 -
3395 * command to open ASM in bi-directional read/write mode
3396 *
3397 * @ac: Audio client handle
3398 * @rd_format: capture format for ASM
3399 * @wr_format: playback format for ASM
3400 * @is_meta_data_mode: mode to indicate if meta data present
3401 * @bits_per_sample: number of bits per sample
3402 * @overwrite_topology: topology to be overwritten flag
3403 * @topology: Topology for ASM
3404 *
3405 * Returns 0 on success or error on failure
3406 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303407int q6asm_open_read_write_v2(struct audio_client *ac, uint32_t rd_format,
3408 uint32_t wr_format, bool is_meta_data_mode,
3409 uint32_t bits_per_sample, bool overwrite_topology,
3410 int topology)
3411{
3412 return __q6asm_open_read_write(ac, rd_format, wr_format,
3413 is_meta_data_mode, bits_per_sample,
3414 overwrite_topology, topology);
3415}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303416EXPORT_SYMBOL(q6asm_open_read_write_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303417
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303418/**
3419 * q6asm_open_loopback_v2 -
3420 * command to open ASM in loopback mode
3421 *
3422 * @ac: Audio client handle
3423 * @bits_per_sample: number of bits per sample
3424 *
3425 * Returns 0 on success or error on failure
3426 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303427int q6asm_open_loopback_v2(struct audio_client *ac, uint16_t bits_per_sample)
3428{
3429 int rc = 0x00;
3430
3431 if (ac == NULL) {
3432 pr_err("%s: APR handle NULL\n", __func__);
3433 return -EINVAL;
3434 }
3435 if (ac->apr == NULL) {
3436 pr_err("%s: AC APR handle NULL\n", __func__);
3437 return -EINVAL;
3438 }
3439 pr_debug("%s: session[%d]\n", __func__, ac->session);
3440
3441 if (ac->perf_mode == LOW_LATENCY_PCM_MODE) {
3442 struct asm_stream_cmd_open_transcode_loopback_t open;
3443
3444 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
3445 atomic_set(&ac->cmd_state, -1);
3446 open.hdr.opcode = ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK;
3447
3448 open.mode_flags = 0;
3449 open.src_endpoint_type = 0;
3450 open.sink_endpoint_type = 0;
3451 open.src_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
3452 open.sink_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
3453 /* source endpoint : matrix */
3454 open.audproc_topo_id = q6asm_get_asm_topology_cal();
3455
3456 ac->app_type = q6asm_get_asm_app_type_cal();
3457 if (ac->perf_mode == LOW_LATENCY_PCM_MODE)
3458 open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION;
3459 else
3460 open.mode_flags |= ASM_LEGACY_STREAM_SESSION;
3461 ac->topology = open.audproc_topo_id;
3462 open.bits_per_sample = bits_per_sample;
3463 open.reserved = 0;
3464 pr_debug("%s: opening a transcode_loopback with mode_flags =[%d] session[%d]\n",
3465 __func__, open.mode_flags, ac->session);
3466
3467 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
3468 if (rc < 0) {
3469 pr_err("%s: open failed op[0x%x]rc[%d]\n",
3470 __func__, open.hdr.opcode, rc);
3471 rc = -EINVAL;
3472 goto fail_cmd;
3473 }
3474 } else {/*if(ac->perf_mode == LEGACY_PCM_MODE)*/
3475 struct asm_stream_cmd_open_loopback_v2 open;
3476
3477 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
3478 atomic_set(&ac->cmd_state, -1);
3479 open.hdr.opcode = ASM_STREAM_CMD_OPEN_LOOPBACK_V2;
3480
3481 open.mode_flags = 0;
3482 open.src_endpointype = 0;
3483 open.sink_endpointype = 0;
3484 /* source endpoint : matrix */
3485 open.postprocopo_id = q6asm_get_asm_topology_cal();
3486
3487 ac->app_type = q6asm_get_asm_app_type_cal();
3488 ac->topology = open.postprocopo_id;
3489 open.bits_per_sample = bits_per_sample;
3490 open.reserved = 0;
3491 pr_debug("%s: opening a loopback_v2 with mode_flags =[%d] session[%d]\n",
3492 __func__, open.mode_flags, ac->session);
3493
3494 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
3495 if (rc < 0) {
3496 pr_err("%s: open failed op[0x%x]rc[%d]\n",
3497 __func__, open.hdr.opcode, rc);
3498 rc = -EINVAL;
3499 goto fail_cmd;
3500 }
3501 }
3502 rc = wait_event_timeout(ac->cmd_wait,
3503 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
3504 if (!rc) {
3505 pr_err("%s: timeout. waited for open_loopback\n",
3506 __func__);
3507 rc = -ETIMEDOUT;
3508 goto fail_cmd;
3509 }
3510 if (atomic_read(&ac->cmd_state) > 0) {
3511 pr_err("%s: DSP returned error[%s]\n",
3512 __func__, adsp_err_get_err_str(
3513 atomic_read(&ac->cmd_state)));
3514 rc = adsp_err_get_lnx_err_code(
3515 atomic_read(&ac->cmd_state));
3516 goto fail_cmd;
3517 }
3518
3519 return 0;
3520fail_cmd:
3521 return rc;
3522}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303523EXPORT_SYMBOL(q6asm_open_loopback_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303524
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303525/**
3526 * q6asm_open_transcode_loopback -
3527 * command to open ASM in transcode loopback mode
3528 *
3529 * @ac: Audio client handle
3530 * @bits_per_sample: number of bits per sample
3531 * @source_format: Format of clip
3532 * @sink_format: end device supported format
3533 *
3534 * Returns 0 on success or error on failure
3535 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303536int q6asm_open_transcode_loopback(struct audio_client *ac,
3537 uint16_t bits_per_sample,
3538 uint32_t source_format, uint32_t sink_format)
3539{
3540 int rc = 0x00;
3541 struct asm_stream_cmd_open_transcode_loopback_t open;
3542
3543 if (ac == NULL) {
3544 pr_err("%s: APR handle NULL\n", __func__);
3545 return -EINVAL;
3546 }
3547 if (ac->apr == NULL) {
3548 pr_err("%s: AC APR handle NULL\n", __func__);
3549 return -EINVAL;
3550 }
3551
3552 pr_debug("%s: session[%d]\n", __func__, ac->session);
3553
3554 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
3555 atomic_set(&ac->cmd_state, -1);
3556 open.hdr.opcode = ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK;
3557
3558 open.mode_flags = 0;
3559 open.src_endpoint_type = 0;
3560 open.sink_endpoint_type = 0;
3561 switch (source_format) {
3562 case FORMAT_LINEAR_PCM:
3563 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
3564 open.src_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3;
3565 break;
3566 case FORMAT_AC3:
3567 open.src_format_id = ASM_MEDIA_FMT_AC3;
3568 break;
3569 case FORMAT_EAC3:
3570 open.src_format_id = ASM_MEDIA_FMT_EAC3;
3571 break;
3572 default:
3573 pr_err("%s: Unsupported src fmt [%d]\n",
3574 __func__, source_format);
3575 return -EINVAL;
3576 }
3577 switch (sink_format) {
3578 case FORMAT_LINEAR_PCM:
3579 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
3580 open.sink_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3;
3581 break;
3582 default:
3583 pr_err("%s: Unsupported sink fmt [%d]\n",
3584 __func__, sink_format);
3585 return -EINVAL;
3586 }
3587
3588 /* source endpoint : matrix */
3589 open.audproc_topo_id = q6asm_get_asm_topology_cal();
3590
3591 ac->app_type = q6asm_get_asm_app_type_cal();
3592 if (ac->perf_mode == LOW_LATENCY_PCM_MODE)
3593 open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION;
3594 else
3595 open.mode_flags |= ASM_LEGACY_STREAM_SESSION;
3596 ac->topology = open.audproc_topo_id;
3597 open.bits_per_sample = bits_per_sample;
3598 open.reserved = 0;
3599 pr_debug("%s: opening a transcode_loopback with mode_flags =[%d] session[%d]\n",
3600 __func__, open.mode_flags, ac->session);
3601
3602 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
3603 if (rc < 0) {
3604 pr_err("%s: open failed op[0x%x]rc[%d]\n",
3605 __func__, open.hdr.opcode, rc);
3606 rc = -EINVAL;
3607 goto fail_cmd;
3608 }
3609 rc = wait_event_timeout(ac->cmd_wait,
3610 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
3611 if (!rc) {
3612 pr_err("%s: timeout. waited for open_transcode_loopback\n",
3613 __func__);
3614 rc = -ETIMEDOUT;
3615 goto fail_cmd;
3616 }
3617 if (atomic_read(&ac->cmd_state) > 0) {
3618 pr_err("%s: DSP returned error[%s]\n",
3619 __func__, adsp_err_get_err_str(
3620 atomic_read(&ac->cmd_state)));
3621 rc = adsp_err_get_lnx_err_code(
3622 atomic_read(&ac->cmd_state));
3623 goto fail_cmd;
3624 }
3625
3626 return 0;
3627fail_cmd:
3628 return rc;
3629}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303630EXPORT_SYMBOL(q6asm_open_transcode_loopback);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303631
3632static
3633int q6asm_set_shared_circ_buff(struct audio_client *ac,
3634 struct asm_stream_cmd_open_shared_io *open,
3635 int bufsz, int bufcnt,
3636 int dir)
3637{
3638 struct audio_buffer *buf_circ;
3639 int bytes_to_alloc, rc;
3640 size_t len;
3641
Aditya Bavanaria8aea172017-09-13 11:37:53 +05303642 mutex_lock(&ac->cmd_lock);
3643
3644 if (ac->port[dir].buf) {
3645 pr_err("%s: Buffer already allocated\n", __func__);
3646 rc = -EINVAL;
Aditya Bavanaria8aea172017-09-13 11:37:53 +05303647 goto done;
3648 }
3649
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303650 buf_circ = kzalloc(sizeof(struct audio_buffer), GFP_KERNEL);
3651
3652 if (!buf_circ) {
3653 rc = -ENOMEM;
3654 goto done;
3655 }
3656
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303657 bytes_to_alloc = bufsz * bufcnt;
3658 bytes_to_alloc = PAGE_ALIGN(bytes_to_alloc);
3659
3660 rc = msm_audio_ion_alloc("audio_client", &buf_circ->client,
3661 &buf_circ->handle, bytes_to_alloc,
3662 (ion_phys_addr_t *)&buf_circ->phys,
3663 &len, &buf_circ->data);
3664
3665 if (rc) {
3666 pr_err("%s: Audio ION alloc is failed, rc = %d\n", __func__,
3667 rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303668 kfree(buf_circ);
3669 goto done;
3670 }
3671
Aditya Bavanaria8aea172017-09-13 11:37:53 +05303672 ac->port[dir].buf = buf_circ;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303673 buf_circ->used = dir ^ 1;
3674 buf_circ->size = bytes_to_alloc;
3675 buf_circ->actual_size = bytes_to_alloc;
3676 memset(buf_circ->data, 0, buf_circ->actual_size);
3677
3678 ac->port[dir].max_buf_cnt = 1;
3679
3680 open->shared_circ_buf_mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
3681 open->shared_circ_buf_num_regions = 1;
3682 open->shared_circ_buf_property_flag = 0x00;
3683 open->shared_circ_buf_start_phy_addr_lsw =
3684 lower_32_bits(buf_circ->phys);
3685 open->shared_circ_buf_start_phy_addr_msw =
3686 msm_audio_populate_upper_32_bits(buf_circ->phys);
3687 open->shared_circ_buf_size = bufsz * bufcnt;
3688
3689 open->map_region_circ_buf.shm_addr_lsw = lower_32_bits(buf_circ->phys);
3690 open->map_region_circ_buf.shm_addr_msw =
3691 msm_audio_populate_upper_32_bits(buf_circ->phys);
3692 open->map_region_circ_buf.mem_size_bytes = bytes_to_alloc;
3693
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303694done:
Xiaoyu Yef423ab12017-11-22 11:38:29 -08003695 mutex_unlock(&ac->cmd_lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303696 return rc;
3697}
3698
3699
3700static
3701int q6asm_set_shared_pos_buff(struct audio_client *ac,
3702 struct asm_stream_cmd_open_shared_io *open,
3703 int dir)
3704{
3705 struct audio_buffer *buf_pos = &ac->shared_pos_buf;
3706 int rc;
3707 size_t len;
3708 int bytes_to_alloc = sizeof(struct asm_shared_position_buffer);
3709
3710 mutex_lock(&ac->cmd_lock);
3711
3712 bytes_to_alloc = PAGE_ALIGN(bytes_to_alloc);
3713
3714 rc = msm_audio_ion_alloc("audio_client", &buf_pos->client,
3715 &buf_pos->handle, bytes_to_alloc,
3716 (ion_phys_addr_t *)&buf_pos->phys, &len,
3717 &buf_pos->data);
3718
3719 if (rc) {
3720 pr_err("%s: Audio pos buf ION alloc is failed, rc = %d\n",
3721 __func__, rc);
3722 goto done;
3723 }
3724
3725 buf_pos->used = dir ^ 1;
3726 buf_pos->size = bytes_to_alloc;
3727 buf_pos->actual_size = bytes_to_alloc;
3728
3729 open->shared_pos_buf_mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
3730 open->shared_pos_buf_num_regions = 1;
3731 open->shared_pos_buf_property_flag = 0x00;
3732 open->shared_pos_buf_phy_addr_lsw = lower_32_bits(buf_pos->phys);
3733 open->shared_pos_buf_phy_addr_msw =
3734 msm_audio_populate_upper_32_bits(buf_pos->phys);
3735
3736 open->map_region_pos_buf.shm_addr_lsw = lower_32_bits(buf_pos->phys);
3737 open->map_region_pos_buf.shm_addr_msw =
3738 msm_audio_populate_upper_32_bits(buf_pos->phys);
3739 open->map_region_pos_buf.mem_size_bytes = bytes_to_alloc;
3740
3741done:
3742 mutex_unlock(&ac->cmd_lock);
3743 return rc;
3744}
3745
3746/*
3747 * q6asm_open_shared_io: Open an ASM session for pull mode (playback)
3748 * or push mode (capture).
3749 * parameters
3750 * config - session parameters (channels, bits_per_sample, sr)
3751 * dir - stream direction (IN for playback, OUT for capture)
3752 * returns 0 if successful, error code otherwise
3753 */
3754int q6asm_open_shared_io(struct audio_client *ac,
3755 struct shared_io_config *config,
3756 int dir)
3757{
3758 struct asm_stream_cmd_open_shared_io *open;
3759 u8 *channel_mapping;
3760 int i, size_of_open, num_watermarks, bufsz, bufcnt, rc, flags = 0;
3761
3762 if (!ac || !config)
3763 return -EINVAL;
3764
3765 bufsz = config->bufsz;
3766 bufcnt = config->bufcnt;
3767 num_watermarks = 0;
3768
3769 ac->config = *config;
3770
3771 if (ac->session <= 0 || ac->session > SESSION_MAX) {
3772 pr_err("%s: Session %d is out of bounds\n",
3773 __func__, ac->session);
3774 return -EINVAL;
3775 }
3776
3777 size_of_open = sizeof(struct asm_stream_cmd_open_shared_io) +
3778 (sizeof(struct asm_shared_watermark_level) * num_watermarks);
3779
3780 open = kzalloc(PAGE_ALIGN(size_of_open), GFP_KERNEL);
3781 if (!open)
3782 return -ENOMEM;
3783
3784 q6asm_stream_add_hdr(ac, &open->hdr, size_of_open, TRUE,
3785 ac->stream_id);
3786
3787 atomic_set(&ac->cmd_state, 1);
3788
3789 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x, perf %d\n",
3790 __func__, open->hdr.token, ac->stream_id, ac->session,
3791 ac->perf_mode);
3792
3793 open->hdr.opcode =
3794 dir == IN ? ASM_STREAM_CMD_OPEN_PULL_MODE_WRITE :
3795 ASM_STREAM_CMD_OPEN_PUSH_MODE_READ;
3796
3797 pr_debug("%s perf_mode %d\n", __func__, ac->perf_mode);
3798 if (dir == IN)
3799 if (ac->perf_mode == ULL_POST_PROCESSING_PCM_MODE)
3800 flags = 4 << ASM_SHIFT_STREAM_PERF_FLAG_PULL_MODE_WRITE;
3801 else if (ac->perf_mode == ULTRA_LOW_LATENCY_PCM_MODE)
3802 flags = 2 << ASM_SHIFT_STREAM_PERF_FLAG_PULL_MODE_WRITE;
3803 else if (ac->perf_mode == LOW_LATENCY_PCM_MODE)
3804 flags = 1 << ASM_SHIFT_STREAM_PERF_FLAG_PULL_MODE_WRITE;
3805 else
3806 pr_err("Invalid perf mode for pull write\n");
3807 else
3808 if (ac->perf_mode == LOW_LATENCY_PCM_MODE)
3809 flags = ASM_LOW_LATENCY_TX_STREAM_SESSION <<
3810 ASM_SHIFT_STREAM_PERF_FLAG_PUSH_MODE_READ;
3811 else
3812 pr_err("Invalid perf mode for push read\n");
3813
3814 if (flags == 0) {
3815 pr_err("%s: Invalid mode[%d]\n", __func__,
3816 ac->perf_mode);
3817 kfree(open);
3818 return -EINVAL;
3819
3820 }
3821
3822 pr_debug("open.mode_flags = 0x%x\n", flags);
3823 open->mode_flags = flags;
3824 open->endpoint_type = ASM_END_POINT_DEVICE_MATRIX;
3825 open->topo_bits_per_sample = config->bits_per_sample;
3826
3827 open->topo_id = q6asm_get_asm_topology_cal();
3828
3829 if (config->format == FORMAT_LINEAR_PCM)
3830 open->fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3;
3831 else {
3832 pr_err("%s: Invalid format[%d]\n", __func__, config->format);
3833 rc = -EINVAL;
3834 goto done;
3835 }
3836
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303837 rc = q6asm_set_shared_circ_buff(ac, open, bufsz, bufcnt, dir);
3838
3839 if (rc)
3840 goto done;
3841
3842 ac->port[dir].tmp_hdl = 0;
3843
3844 rc = q6asm_set_shared_pos_buff(ac, open, dir);
3845
3846 if (rc)
3847 goto done;
3848
3849 /* asm_multi_channel_pcm_fmt_blk_v3 */
3850 open->fmt.num_channels = config->channels;
3851 open->fmt.bits_per_sample = config->bits_per_sample;
3852 open->fmt.sample_rate = config->rate;
3853 open->fmt.is_signed = 1;
3854 open->fmt.sample_word_size = config->sample_word_size;
3855
3856 channel_mapping = open->fmt.channel_mapping;
3857
3858 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
3859
3860 rc = q6asm_map_channels(channel_mapping, config->channels, false);
3861 if (rc) {
3862 pr_err("%s: Map channels failed, ret: %d\n", __func__, rc);
3863 goto done;
3864 }
3865
3866 open->num_watermark_levels = num_watermarks;
3867 for (i = 0; i < num_watermarks; i++) {
3868 open->watermark[i].watermark_level_bytes = i *
3869 ((bufsz * bufcnt) / num_watermarks);
3870 pr_debug("%s: Watermark level set for %i\n",
3871 __func__,
3872 open->watermark[i].watermark_level_bytes);
3873 }
3874
3875 rc = apr_send_pkt(ac->apr, (uint32_t *) open);
3876 if (rc < 0) {
3877 pr_err("%s: Open failed op[0x%x]rc[%d]\n",
3878 __func__, open->hdr.opcode, rc);
3879 goto done;
3880 }
3881
3882 pr_debug("%s: sent open apr pkt\n", __func__);
3883 rc = wait_event_timeout(ac->cmd_wait,
3884 (atomic_read(&ac->cmd_state) <= 0), 5*HZ);
3885 if (!rc) {
3886 pr_err("%s: Timeout. Waited for open write apr pkt rc[%d]\n",
3887 __func__, rc);
3888 rc = -ETIMEDOUT;
3889 goto done;
3890 }
3891
3892 if (atomic_read(&ac->cmd_state) < 0) {
3893 pr_err("%s: DSP returned error [%d]\n", __func__,
3894 atomic_read(&ac->cmd_state));
3895 rc = -EINVAL;
3896 goto done;
3897 }
3898
3899 ac->io_mode |= TUN_WRITE_IO_MODE;
3900 rc = 0;
3901done:
3902 kfree(open);
3903 return rc;
3904}
3905EXPORT_SYMBOL(q6asm_open_shared_io);
3906
3907/*
3908 * q6asm_shared_io_buf: Returns handle to the shared circular buffer being
3909 * used for pull/push mode.
3910 * parameters
3911 * dir - used to identify input/output port
3912 * returns buffer handle
3913 */
3914struct audio_buffer *q6asm_shared_io_buf(struct audio_client *ac,
3915 int dir)
3916{
3917 struct audio_port_data *port;
3918
3919 if (!ac) {
3920 pr_err("%s: ac is null\n", __func__);
3921 return NULL;
3922 }
3923 port = &ac->port[dir];
3924 return port->buf;
3925}
3926EXPORT_SYMBOL(q6asm_shared_io_buf);
3927
3928/*
3929 * q6asm_shared_io_free: Frees memory allocated for a pull/push session
3930 * parameters
3931 * dir - port direction
3932 * returns 0 if successful, error otherwise
3933 */
3934int q6asm_shared_io_free(struct audio_client *ac, int dir)
3935{
3936 struct audio_port_data *port;
3937
3938 if (!ac) {
3939 pr_err("%s: audio client is null\n", __func__);
3940 return -EINVAL;
3941 }
3942 port = &ac->port[dir];
3943 mutex_lock(&ac->cmd_lock);
3944 if (port->buf && port->buf->data) {
3945 msm_audio_ion_free(port->buf->client, port->buf->handle);
3946 port->buf->client = NULL;
3947 port->buf->handle = NULL;
3948 port->max_buf_cnt = 0;
3949 kfree(port->buf);
3950 port->buf = NULL;
3951 }
3952 if (ac->shared_pos_buf.data) {
3953 msm_audio_ion_free(ac->shared_pos_buf.client,
3954 ac->shared_pos_buf.handle);
3955 ac->shared_pos_buf.client = NULL;
3956 ac->shared_pos_buf.handle = NULL;
3957 }
3958 mutex_unlock(&ac->cmd_lock);
3959 return 0;
3960}
3961EXPORT_SYMBOL(q6asm_shared_io_free);
3962
3963/*
3964 * q6asm_get_shared_pos: Returns current read index/write index as observed
3965 * by the DSP. Note that this is an offset and iterates from [0,BUF_SIZE - 1]
3966 * parameters - (all output)
3967 * read_index - offset
3968 * wall_clk_msw1 - ADSP wallclock msw
3969 * wall_clk_lsw1 - ADSP wallclock lsw
3970 * returns 0 if successful, -EAGAIN if DSP failed to update after some
3971 * retries
3972 */
3973int q6asm_get_shared_pos(struct audio_client *ac, uint32_t *read_index,
3974 uint32_t *wall_clk_msw1, uint32_t *wall_clk_lsw1)
3975{
3976 struct asm_shared_position_buffer *pos_buf;
3977 uint32_t frame_cnt1, frame_cnt2;
3978 int i, j;
3979
3980 if (!ac) {
3981 pr_err("%s: audio client is null\n", __func__);
3982 return -EINVAL;
3983 }
3984
3985 pos_buf = ac->shared_pos_buf.data;
3986
3987 /* always try to get the latest update in the shared pos buffer */
3988 for (i = 0; i < 2; i++) {
3989 /* retry until there is an update from DSP */
3990 for (j = 0; j < 5; j++) {
3991 frame_cnt1 = pos_buf->frame_counter;
3992 if (frame_cnt1 != 0)
3993 break;
3994 }
3995
3996 *wall_clk_msw1 = pos_buf->wall_clock_us_msw;
3997 *wall_clk_lsw1 = pos_buf->wall_clock_us_lsw;
3998 *read_index = pos_buf->index;
3999 frame_cnt2 = pos_buf->frame_counter;
4000
4001 if (frame_cnt1 != frame_cnt2)
4002 continue;
4003 return 0;
4004 }
4005 pr_err("%s out of tries trying to get a good read, try again\n",
4006 __func__);
4007 return -EAGAIN;
4008}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304009EXPORT_SYMBOL(q6asm_get_shared_pos);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304010
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304011/**
4012 * q6asm_run -
4013 * command to set ASM to run state
4014 *
4015 * @ac: Audio client handle
4016 * @flags: Flags for session
4017 * @msw_ts: upper 32bits timestamp
4018 * @lsw_ts: lower 32bits timestamp
4019 *
4020 * Returns 0 on success or error on failure
4021 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304022int q6asm_run(struct audio_client *ac, uint32_t flags,
4023 uint32_t msw_ts, uint32_t lsw_ts)
4024{
4025 struct asm_session_cmd_run_v2 run;
4026 int rc;
4027
4028 if (ac == NULL) {
4029 pr_err("%s: APR handle NULL\n", __func__);
4030 return -EINVAL;
4031 }
4032 if (ac->apr == NULL) {
4033 pr_err("%s: AC APR handle NULL\n", __func__);
4034 return -EINVAL;
4035 }
4036 pr_debug("%s: session[%d]\n", __func__, ac->session);
4037
4038 q6asm_add_hdr(ac, &run.hdr, sizeof(run), TRUE);
4039 atomic_set(&ac->cmd_state, -1);
4040
4041 run.hdr.opcode = ASM_SESSION_CMD_RUN_V2;
4042 run.flags = flags;
4043 run.time_lsw = lsw_ts;
4044 run.time_msw = msw_ts;
4045
4046 config_debug_fs_run();
4047
4048 rc = apr_send_pkt(ac->apr, (uint32_t *) &run);
4049 if (rc < 0) {
4050 pr_err("%s: Commmand run failed[%d]",
4051 __func__, rc);
4052 rc = -EINVAL;
4053 goto fail_cmd;
4054 }
4055
4056 rc = wait_event_timeout(ac->cmd_wait,
4057 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4058 if (!rc) {
4059 pr_err("%s: timeout. waited for run success",
4060 __func__);
4061 rc = -ETIMEDOUT;
4062 goto fail_cmd;
4063 }
4064 if (atomic_read(&ac->cmd_state) > 0) {
4065 pr_err("%s: DSP returned error[%s]\n",
4066 __func__, adsp_err_get_err_str(
4067 atomic_read(&ac->cmd_state)));
4068 rc = adsp_err_get_lnx_err_code(
4069 atomic_read(&ac->cmd_state));
4070 goto fail_cmd;
4071 }
4072
4073 return 0;
4074fail_cmd:
4075 return rc;
4076}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304077EXPORT_SYMBOL(q6asm_run);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304078
4079static int __q6asm_run_nowait(struct audio_client *ac, uint32_t flags,
4080 uint32_t msw_ts, uint32_t lsw_ts, uint32_t stream_id)
4081{
4082 struct asm_session_cmd_run_v2 run;
4083 int rc;
4084
4085 if (ac == NULL) {
4086 pr_err("%s: APR handle NULL\n", __func__);
4087 return -EINVAL;
4088 }
4089 if (ac->apr == NULL) {
4090 pr_err("%s: AC APR handle NULL\n", __func__);
4091 return -EINVAL;
4092 }
4093 pr_debug("%s: session[%d]\n", __func__, ac->session);
4094
4095 q6asm_stream_add_hdr_async(ac, &run.hdr, sizeof(run), TRUE, stream_id);
4096 atomic_set(&ac->cmd_state, 1);
4097 run.hdr.opcode = ASM_SESSION_CMD_RUN_V2;
4098 run.flags = flags;
4099 run.time_lsw = lsw_ts;
4100 run.time_msw = msw_ts;
4101
4102 rc = apr_send_pkt(ac->apr, (uint32_t *) &run);
4103 if (rc < 0) {
4104 pr_err("%s: Commmand run failed[%d]", __func__, rc);
4105 return -EINVAL;
4106 }
4107 return 0;
4108}
4109
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304110/**
4111 * q6asm_run_nowait -
4112 * command to set ASM to run state with no wait for ack
4113 *
4114 * @ac: Audio client handle
4115 * @flags: Flags for session
4116 * @msw_ts: upper 32bits timestamp
4117 * @lsw_ts: lower 32bits timestamp
4118 *
4119 * Returns 0 on success or error on failure
4120 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304121int q6asm_run_nowait(struct audio_client *ac, uint32_t flags,
4122 uint32_t msw_ts, uint32_t lsw_ts)
4123{
4124 return __q6asm_run_nowait(ac, flags, msw_ts, lsw_ts, ac->stream_id);
4125}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304126EXPORT_SYMBOL(q6asm_run_nowait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304127
4128int q6asm_stream_run_nowait(struct audio_client *ac, uint32_t flags,
4129 uint32_t msw_ts, uint32_t lsw_ts, uint32_t stream_id)
4130{
4131 return __q6asm_run_nowait(ac, flags, msw_ts, lsw_ts, stream_id);
4132}
4133
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304134/**
4135 * q6asm_enc_cfg_blk_aac -
4136 * command to set encode cfg block for aac
4137 *
4138 * @ac: Audio client handle
4139 * @frames_per_buf: number of frames per buffer
4140 * @sample_rate: Sample rate
4141 * @channels: number of ASM channels
4142 * @bit_rate: Bit rate info
4143 * @mode: mode of AAC stream encode
4144 * @format: aac format flag
4145 *
4146 * Returns 0 on success or error on failure
4147 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304148int q6asm_enc_cfg_blk_aac(struct audio_client *ac,
4149 uint32_t frames_per_buf,
4150 uint32_t sample_rate, uint32_t channels,
4151 uint32_t bit_rate, uint32_t mode, uint32_t format)
4152{
4153 struct asm_aac_enc_cfg_v2 enc_cfg;
4154 int rc = 0;
4155
4156 pr_debug("%s: session[%d]frames[%d]SR[%d]ch[%d]bitrate[%d]mode[%d] format[%d]\n",
4157 __func__, ac->session, frames_per_buf,
4158 sample_rate, channels, bit_rate, mode, format);
4159
4160 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
4161 atomic_set(&ac->cmd_state, -1);
4162
4163 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4164 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
4165 enc_cfg.encdec.param_size = sizeof(struct asm_aac_enc_cfg_v2) -
4166 sizeof(struct asm_stream_cmd_set_encdec_param);
4167 enc_cfg.encblk.frames_per_buf = frames_per_buf;
4168 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
4169 sizeof(struct asm_enc_cfg_blk_param_v2);
4170 enc_cfg.bit_rate = bit_rate;
4171 enc_cfg.enc_mode = mode;
4172 enc_cfg.aac_fmt_flag = format;
4173 enc_cfg.channel_cfg = channels;
4174 enc_cfg.sample_rate = sample_rate;
4175
4176 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
4177 if (rc < 0) {
4178 pr_err("%s: Comamnd %d failed %d\n",
4179 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
4180 rc = -EINVAL;
4181 goto fail_cmd;
4182 }
4183 rc = wait_event_timeout(ac->cmd_wait,
4184 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4185 if (!rc) {
4186 pr_err("%s: timeout. waited for FORMAT_UPDATE\n",
4187 __func__);
4188 rc = -ETIMEDOUT;
4189 goto fail_cmd;
4190 }
4191 if (atomic_read(&ac->cmd_state) > 0) {
4192 pr_err("%s: DSP returned error[%s]\n",
4193 __func__, adsp_err_get_err_str(
4194 atomic_read(&ac->cmd_state)));
4195 rc = adsp_err_get_lnx_err_code(
4196 atomic_read(&ac->cmd_state));
4197 goto fail_cmd;
4198 }
4199 return 0;
4200fail_cmd:
4201 return rc;
4202}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304203EXPORT_SYMBOL(q6asm_enc_cfg_blk_aac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304204
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304205/**
4206 * q6asm_enc_cfg_blk_g711 -
4207 * command to set encode cfg block for g711
4208 *
4209 * @ac: Audio client handle
4210 * @frames_per_buf: number of frames per buffer
4211 * @sample_rate: Sample rate
4212 *
4213 * Returns 0 on success or error on failure
4214 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304215int q6asm_enc_cfg_blk_g711(struct audio_client *ac,
4216 uint32_t frames_per_buf,
4217 uint32_t sample_rate)
4218{
4219 struct asm_g711_enc_cfg_v2 enc_cfg;
4220 int rc = 0;
4221
4222 pr_debug("%s: session[%d]frames[%d]SR[%d]\n",
4223 __func__, ac->session, frames_per_buf,
4224 sample_rate);
4225
4226 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
4227 atomic_set(&ac->cmd_state, -1);
4228
4229 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4230 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
4231 enc_cfg.encdec.param_size = sizeof(struct asm_g711_enc_cfg_v2) -
4232 sizeof(struct asm_stream_cmd_set_encdec_param);
4233 enc_cfg.encblk.frames_per_buf = frames_per_buf;
4234 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
4235 sizeof(struct asm_enc_cfg_blk_param_v2);
4236 enc_cfg.sample_rate = sample_rate;
4237
4238 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
4239 if (rc < 0) {
4240 pr_err("%s: Comamnd %d failed %d\n",
4241 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
4242 rc = -EINVAL;
4243 goto fail_cmd;
4244 }
4245 rc = wait_event_timeout(ac->cmd_wait,
4246 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4247 if (!rc) {
4248 pr_err("%s: timeout. waited for FORMAT_UPDATE\n",
4249 __func__);
4250 rc = -ETIMEDOUT;
4251 goto fail_cmd;
4252 }
4253 if (atomic_read(&ac->cmd_state) > 0) {
4254 pr_err("%s: DSP returned error[%s]\n",
4255 __func__, adsp_err_get_err_str(
4256 atomic_read(&ac->cmd_state)));
4257 rc = adsp_err_get_lnx_err_code(
4258 atomic_read(&ac->cmd_state));
4259 goto fail_cmd;
4260 }
4261 return 0;
4262fail_cmd:
4263 return rc;
4264}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304265EXPORT_SYMBOL(q6asm_enc_cfg_blk_g711);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304266
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304267/**
4268 * q6asm_set_encdec_chan_map -
4269 * command to set encdec channel map
4270 *
4271 * @ac: Audio client handle
4272 * @channels: number of channels
4273 *
4274 * Returns 0 on success or error on failure
4275 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304276int q6asm_set_encdec_chan_map(struct audio_client *ac,
4277 uint32_t num_channels)
4278{
4279 struct asm_dec_out_chan_map_param chan_map;
4280 u8 *channel_mapping;
4281 int rc = 0;
4282
4283 pr_debug("%s: Session %d, num_channels = %d\n",
4284 __func__, ac->session, num_channels);
4285 q6asm_add_hdr(ac, &chan_map.hdr, sizeof(chan_map), TRUE);
4286 atomic_set(&ac->cmd_state, -1);
4287 chan_map.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4288 chan_map.encdec.param_id = ASM_PARAM_ID_DEC_OUTPUT_CHAN_MAP;
4289 chan_map.encdec.param_size = sizeof(struct asm_dec_out_chan_map_param) -
4290 (sizeof(struct apr_hdr) +
4291 sizeof(struct asm_stream_cmd_set_encdec_param));
4292 chan_map.num_channels = num_channels;
4293 channel_mapping = chan_map.channel_mapping;
4294 memset(channel_mapping, PCM_CHANNEL_NULL, MAX_CHAN_MAP_CHANNELS);
4295
4296 if (q6asm_map_channels(channel_mapping, num_channels, false)) {
4297 pr_err("%s: map channels failed %d\n", __func__, num_channels);
4298 return -EINVAL;
4299 }
4300
4301 rc = apr_send_pkt(ac->apr, (uint32_t *) &chan_map);
4302 if (rc < 0) {
4303 pr_err("%s: Command opcode[0x%x]paramid[0x%x] failed %d\n",
4304 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM,
4305 ASM_PARAM_ID_DEC_OUTPUT_CHAN_MAP, rc);
4306 goto fail_cmd;
4307 }
4308 rc = wait_event_timeout(ac->cmd_wait,
4309 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4310 if (!rc) {
4311 pr_err("%s: timeout opcode[0x%x]\n", __func__,
4312 chan_map.hdr.opcode);
4313 rc = -ETIMEDOUT;
4314 goto fail_cmd;
4315 }
4316 if (atomic_read(&ac->cmd_state) > 0) {
4317 pr_err("%s: DSP returned error[%s]\n",
4318 __func__, adsp_err_get_err_str(
4319 atomic_read(&ac->cmd_state)));
4320 rc = adsp_err_get_lnx_err_code(
4321 atomic_read(&ac->cmd_state));
4322 goto fail_cmd;
4323 }
4324 return 0;
4325fail_cmd:
4326 return rc;
4327}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304328EXPORT_SYMBOL(q6asm_set_encdec_chan_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304329
4330/*
4331 * q6asm_enc_cfg_blk_pcm_v4 - sends encoder configuration parameters
4332 *
4333 * @ac: Client session handle
4334 * @rate: sample rate
4335 * @channels: number of channels
4336 * @bits_per_sample: bit width of encoder session
4337 * @use_default_chmap: true if default channel map to be used
4338 * @use_back_flavor: to configure back left and right channel
4339 * @channel_map: input channel map
4340 * @sample_word_size: Size in bits of the word that holds a sample of a channel
4341 * @endianness: endianness of the pcm data
4342 * @mode: Mode to provide additional info about the pcm input data
4343 */
4344int q6asm_enc_cfg_blk_pcm_v4(struct audio_client *ac,
4345 uint32_t rate, uint32_t channels,
4346 uint16_t bits_per_sample, bool use_default_chmap,
4347 bool use_back_flavor, u8 *channel_map,
4348 uint16_t sample_word_size, uint16_t endianness,
4349 uint16_t mode)
4350{
4351 struct asm_multi_channel_pcm_enc_cfg_v4 enc_cfg;
4352 struct asm_enc_cfg_blk_param_v2 enc_fg_blk;
4353 u8 *channel_mapping;
4354 u32 frames_per_buf = 0;
4355 int rc;
4356
4357 if (!use_default_chmap && (channel_map == NULL)) {
4358 pr_err("%s: No valid chan map and can't use default\n",
4359 __func__);
4360 rc = -EINVAL;
4361 goto fail_cmd;
4362 }
4363
4364 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
4365 ac->session, rate, channels,
4366 bits_per_sample, sample_word_size);
4367
4368 memset(&enc_cfg, 0, sizeof(enc_cfg));
4369 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
4370 atomic_set(&ac->cmd_state, -1);
4371 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4372 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
4373 enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) -
4374 sizeof(enc_cfg.encdec);
4375 enc_cfg.encblk.frames_per_buf = frames_per_buf;
4376 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
4377 sizeof(enc_fg_blk);
4378 enc_cfg.num_channels = channels;
4379 enc_cfg.bits_per_sample = bits_per_sample;
4380 enc_cfg.sample_rate = rate;
4381 enc_cfg.is_signed = 1;
4382 enc_cfg.sample_word_size = sample_word_size;
4383 enc_cfg.endianness = endianness;
4384 enc_cfg.mode = mode;
4385 channel_mapping = enc_cfg.channel_mapping;
4386
4387 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
4388
4389 if (use_default_chmap) {
4390 pr_debug("%s: setting default channel map for %d channels",
4391 __func__, channels);
4392 if (q6asm_map_channels(channel_mapping, channels,
4393 use_back_flavor)) {
4394 pr_err("%s: map channels failed %d\n",
4395 __func__, channels);
4396 rc = -EINVAL;
4397 goto fail_cmd;
4398 }
4399 } else {
4400 pr_debug("%s: Using pre-defined channel map", __func__);
4401 memcpy(channel_mapping, channel_map,
4402 PCM_FORMAT_MAX_NUM_CHANNEL);
4403 }
4404
4405 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
4406 if (rc < 0) {
4407 pr_err("%s: Command open failed %d\n", __func__, rc);
4408 goto fail_cmd;
4409 }
4410 rc = wait_event_timeout(ac->cmd_wait,
4411 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4412 if (!rc) {
4413 pr_err("%s: timeout opcode[0x%x]\n",
4414 __func__, enc_cfg.hdr.opcode);
4415 rc = -ETIMEDOUT;
4416 goto fail_cmd;
4417 }
4418 if (atomic_read(&ac->cmd_state) > 0) {
4419 pr_err("%s: DSP returned error[%s]\n",
4420 __func__, adsp_err_get_err_str(
4421 atomic_read(&ac->cmd_state)));
4422 rc = adsp_err_get_lnx_err_code(
4423 atomic_read(&ac->cmd_state));
4424 goto fail_cmd;
4425 }
4426 return 0;
4427fail_cmd:
4428 return rc;
4429}
4430EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v4);
4431
4432/*
4433 * q6asm_enc_cfg_blk_pcm_v3 - sends encoder configuration parameters
4434 *
4435 * @ac: Client session handle
4436 * @rate: sample rate
4437 * @channels: number of channels
4438 * @bits_per_sample: bit width of encoder session
4439 * @use_default_chmap: true if default channel map to be used
4440 * @use_back_flavor: to configure back left and right channel
4441 * @channel_map: input channel map
4442 * @sample_word_size: Size in bits of the word that holds a sample of a channel
4443 */
4444int q6asm_enc_cfg_blk_pcm_v3(struct audio_client *ac,
4445 uint32_t rate, uint32_t channels,
4446 uint16_t bits_per_sample, bool use_default_chmap,
4447 bool use_back_flavor, u8 *channel_map,
4448 uint16_t sample_word_size)
4449{
4450 struct asm_multi_channel_pcm_enc_cfg_v3 enc_cfg;
4451 struct asm_enc_cfg_blk_param_v2 enc_fg_blk;
4452 u8 *channel_mapping;
4453 u32 frames_per_buf = 0;
4454 int rc;
4455
4456 if (!use_default_chmap && (channel_map == NULL)) {
4457 pr_err("%s: No valid chan map and can't use default\n",
4458 __func__);
4459 rc = -EINVAL;
4460 goto fail_cmd;
4461 }
4462
4463 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
4464 ac->session, rate, channels,
4465 bits_per_sample, sample_word_size);
4466
4467 memset(&enc_cfg, 0, sizeof(enc_cfg));
4468 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
4469 atomic_set(&ac->cmd_state, -1);
4470 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4471 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
4472 enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) -
4473 sizeof(enc_cfg.encdec);
4474 enc_cfg.encblk.frames_per_buf = frames_per_buf;
4475 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
4476 sizeof(enc_fg_blk);
4477 enc_cfg.num_channels = channels;
4478 enc_cfg.bits_per_sample = bits_per_sample;
4479 enc_cfg.sample_rate = rate;
4480 enc_cfg.is_signed = 1;
4481 enc_cfg.sample_word_size = sample_word_size;
4482 channel_mapping = enc_cfg.channel_mapping;
4483
4484 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
4485
4486 if (use_default_chmap) {
4487 pr_debug("%s: setting default channel map for %d channels",
4488 __func__, channels);
4489 if (q6asm_map_channels(channel_mapping, channels,
4490 use_back_flavor)) {
4491 pr_err("%s: map channels failed %d\n",
4492 __func__, channels);
4493 rc = -EINVAL;
4494 goto fail_cmd;
4495 }
4496 } else {
4497 pr_debug("%s: Using pre-defined channel map", __func__);
4498 memcpy(channel_mapping, channel_map,
4499 PCM_FORMAT_MAX_NUM_CHANNEL);
4500 }
4501
4502 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
4503 if (rc < 0) {
4504 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
4505 goto fail_cmd;
4506 }
4507 rc = wait_event_timeout(ac->cmd_wait,
4508 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4509 if (!rc) {
4510 pr_err("%s: timeout opcode[0x%x]\n",
4511 __func__, enc_cfg.hdr.opcode);
4512 rc = -ETIMEDOUT;
4513 goto fail_cmd;
4514 }
4515 if (atomic_read(&ac->cmd_state) > 0) {
4516 pr_err("%s: DSP returned error[%s]\n",
4517 __func__, adsp_err_get_err_str(
4518 atomic_read(&ac->cmd_state)));
4519 rc = adsp_err_get_lnx_err_code(
4520 atomic_read(&ac->cmd_state));
4521 goto fail_cmd;
4522 }
4523 return 0;
4524fail_cmd:
4525 return rc;
4526}
4527EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v3);
4528
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304529/**
4530 * q6asm_enc_cfg_blk_pcm_v2 -
4531 * command to set encode config block for pcm_v2
4532 *
4533 * @ac: Audio client handle
4534 * @rate: sample rate
4535 * @channels: number of channels
4536 * @bits_per_sample: number of bits per sample
4537 * @use_default_chmap: Flag indicating to use default ch_map or not
4538 * @use_back_flavor: back flavor flag
4539 * @channel_map: Custom channel map settings
4540 *
4541 * Returns 0 on success or error on failure
4542 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304543int q6asm_enc_cfg_blk_pcm_v2(struct audio_client *ac,
4544 uint32_t rate, uint32_t channels, uint16_t bits_per_sample,
4545 bool use_default_chmap, bool use_back_flavor, u8 *channel_map)
4546{
4547 struct asm_multi_channel_pcm_enc_cfg_v2 enc_cfg;
4548 u8 *channel_mapping;
4549 u32 frames_per_buf = 0;
4550
4551 int rc = 0;
4552
4553 if (!use_default_chmap && (channel_map == NULL)) {
4554 pr_err("%s: No valid chan map and can't use default\n",
4555 __func__);
4556 return -EINVAL;
4557 }
4558
4559 pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
4560 ac->session, rate, channels);
4561
4562 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
4563 atomic_set(&ac->cmd_state, -1);
4564 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4565 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
4566 enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) -
4567 sizeof(enc_cfg.encdec);
4568 enc_cfg.encblk.frames_per_buf = frames_per_buf;
4569 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
4570 sizeof(struct asm_enc_cfg_blk_param_v2);
4571
4572 enc_cfg.num_channels = channels;
4573 enc_cfg.bits_per_sample = bits_per_sample;
4574 enc_cfg.sample_rate = rate;
4575 enc_cfg.is_signed = 1;
4576 channel_mapping = enc_cfg.channel_mapping;
4577
4578 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
4579
4580 if (use_default_chmap) {
4581 pr_debug("%s: setting default channel map for %d channels",
4582 __func__, channels);
4583 if (q6asm_map_channels(channel_mapping, channels,
4584 use_back_flavor)) {
4585 pr_err("%s: map channels failed %d\n",
4586 __func__, channels);
4587 return -EINVAL;
4588 }
4589 } else {
4590 pr_debug("%s: Using pre-defined channel map", __func__);
4591 memcpy(channel_mapping, channel_map,
4592 PCM_FORMAT_MAX_NUM_CHANNEL);
4593 }
4594
4595 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
4596 if (rc < 0) {
4597 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
4598 rc = -EINVAL;
4599 goto fail_cmd;
4600 }
4601 rc = wait_event_timeout(ac->cmd_wait,
4602 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4603 if (!rc) {
4604 pr_err("%s: timeout opcode[0x%x]\n",
4605 __func__, enc_cfg.hdr.opcode);
4606 rc = -ETIMEDOUT;
4607 goto fail_cmd;
4608 }
4609 if (atomic_read(&ac->cmd_state) > 0) {
4610 pr_err("%s: DSP returned error[%s]\n",
4611 __func__, adsp_err_get_err_str(
4612 atomic_read(&ac->cmd_state)));
4613 rc = adsp_err_get_lnx_err_code(
4614 atomic_read(&ac->cmd_state));
4615 goto fail_cmd;
4616 }
4617 return 0;
4618fail_cmd:
4619 return rc;
4620}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304621EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304622
4623static int __q6asm_enc_cfg_blk_pcm_v4(struct audio_client *ac,
4624 uint32_t rate, uint32_t channels,
4625 uint16_t bits_per_sample,
4626 uint16_t sample_word_size,
4627 uint16_t endianness,
4628 uint16_t mode)
4629{
4630 return q6asm_enc_cfg_blk_pcm_v4(ac, rate, channels,
4631 bits_per_sample, true, false, NULL,
4632 sample_word_size, endianness, mode);
4633}
4634
4635static int __q6asm_enc_cfg_blk_pcm_v3(struct audio_client *ac,
4636 uint32_t rate, uint32_t channels,
4637 uint16_t bits_per_sample,
4638 uint16_t sample_word_size)
4639{
4640 return q6asm_enc_cfg_blk_pcm_v3(ac, rate, channels,
4641 bits_per_sample, true, false, NULL,
4642 sample_word_size);
4643}
4644
4645static int __q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
4646 uint32_t rate, uint32_t channels, uint16_t bits_per_sample)
4647{
4648 return q6asm_enc_cfg_blk_pcm_v2(ac, rate, channels,
4649 bits_per_sample, true, false, NULL);
4650}
4651
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304652/**
4653 * q6asm_enc_cfg_blk_pcm -
4654 * command to set encode config block for pcm
4655 *
4656 * @ac: Audio client handle
4657 * @rate: sample rate
4658 * @channels: number of channels
4659 *
4660 * Returns 0 on success or error on failure
4661 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304662int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
4663 uint32_t rate, uint32_t channels)
4664{
4665 return __q6asm_enc_cfg_blk_pcm(ac, rate, channels, 16);
4666}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304667EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304668
4669int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac,
4670 uint32_t rate, uint32_t channels, uint16_t bits_per_sample)
4671{
4672 return __q6asm_enc_cfg_blk_pcm(ac, rate, channels, bits_per_sample);
4673}
4674
4675/*
4676 * q6asm_enc_cfg_blk_pcm_format_support_v3 - sends encoder configuration
4677 * parameters
4678 *
4679 * @ac: Client session handle
4680 * @rate: sample rate
4681 * @channels: number of channels
4682 * @bits_per_sample: bit width of encoder session
4683 * @sample_word_size: Size in bits of the word that holds a sample of a channel
4684 */
4685int q6asm_enc_cfg_blk_pcm_format_support_v3(struct audio_client *ac,
4686 uint32_t rate, uint32_t channels,
4687 uint16_t bits_per_sample,
4688 uint16_t sample_word_size)
4689{
4690 return __q6asm_enc_cfg_blk_pcm_v3(ac, rate, channels,
4691 bits_per_sample, sample_word_size);
4692}
4693EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v3);
4694
4695/*
4696 * q6asm_enc_cfg_blk_pcm_format_support_v4 - sends encoder configuration
4697 * parameters
4698 *
4699 * @ac: Client session handle
4700 * @rate: sample rate
4701 * @channels: number of channels
4702 * @bits_per_sample: bit width of encoder session
4703 * @sample_word_size: Size in bits of the word that holds a sample of a channel
4704 * @endianness: endianness of the pcm data
4705 * @mode: Mode to provide additional info about the pcm input data
4706 */
4707int q6asm_enc_cfg_blk_pcm_format_support_v4(struct audio_client *ac,
4708 uint32_t rate, uint32_t channels,
4709 uint16_t bits_per_sample,
4710 uint16_t sample_word_size,
4711 uint16_t endianness,
4712 uint16_t mode)
4713{
4714 return __q6asm_enc_cfg_blk_pcm_v4(ac, rate, channels,
4715 bits_per_sample, sample_word_size,
4716 endianness, mode);
4717}
4718EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v4);
4719
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304720/**
4721 * q6asm_enc_cfg_blk_pcm_native -
4722 * command to set encode config block for pcm_native
4723 *
4724 * @ac: Audio client handle
4725 * @rate: sample rate
4726 * @channels: number of channels
4727 *
4728 * Returns 0 on success or error on failure
4729 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304730int q6asm_enc_cfg_blk_pcm_native(struct audio_client *ac,
4731 uint32_t rate, uint32_t channels)
4732{
4733 struct asm_multi_channel_pcm_enc_cfg_v2 enc_cfg;
4734 u8 *channel_mapping;
4735 u32 frames_per_buf = 0;
4736
4737 int rc = 0;
4738
4739 pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
4740 ac->session, rate, channels);
4741
4742 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
4743 atomic_set(&ac->cmd_state, -1);
4744 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4745 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
4746 enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) -
4747 sizeof(enc_cfg.encdec);
4748 enc_cfg.encblk.frames_per_buf = frames_per_buf;
4749 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
4750 sizeof(struct asm_enc_cfg_blk_param_v2);
4751
4752 enc_cfg.num_channels = 0;/*channels;*/
4753 enc_cfg.bits_per_sample = 16;
4754 enc_cfg.sample_rate = 0;/*rate;*/
4755 enc_cfg.is_signed = 1;
4756 channel_mapping = enc_cfg.channel_mapping;
4757
4758
4759 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
4760
4761 if (q6asm_map_channels(channel_mapping, channels, false)) {
4762 pr_err("%s: map channels failed %d\n", __func__, channels);
4763 return -EINVAL;
4764 }
4765
4766 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
4767 if (rc < 0) {
4768 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
4769 rc = -EINVAL;
4770 goto fail_cmd;
4771 }
4772 rc = wait_event_timeout(ac->cmd_wait,
4773 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4774 if (!rc) {
4775 pr_err("%s: timeout opcode[0x%x]\n",
4776 __func__, enc_cfg.hdr.opcode);
4777 rc = -ETIMEDOUT;
4778 goto fail_cmd;
4779 }
4780 if (atomic_read(&ac->cmd_state) > 0) {
4781 pr_err("%s: DSP returned error[%s]\n",
4782 __func__, adsp_err_get_err_str(
4783 atomic_read(&ac->cmd_state)));
4784 rc = adsp_err_get_lnx_err_code(
4785 atomic_read(&ac->cmd_state));
4786 goto fail_cmd;
4787 }
4788 return 0;
4789fail_cmd:
4790 return rc;
4791}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304792EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_native);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304793
4794static int q6asm_map_channels(u8 *channel_mapping, uint32_t channels,
4795 bool use_back_flavor)
4796{
4797 u8 *lchannel_mapping;
4798
4799 lchannel_mapping = channel_mapping;
4800 pr_debug("%s: channels passed: %d\n", __func__, channels);
4801 if (channels == 1) {
4802 lchannel_mapping[0] = PCM_CHANNEL_FC;
4803 } else if (channels == 2) {
4804 lchannel_mapping[0] = PCM_CHANNEL_FL;
4805 lchannel_mapping[1] = PCM_CHANNEL_FR;
4806 } else if (channels == 3) {
4807 lchannel_mapping[0] = PCM_CHANNEL_FL;
4808 lchannel_mapping[1] = PCM_CHANNEL_FR;
4809 lchannel_mapping[2] = PCM_CHANNEL_FC;
4810 } else if (channels == 4) {
4811 lchannel_mapping[0] = PCM_CHANNEL_FL;
4812 lchannel_mapping[1] = PCM_CHANNEL_FR;
4813 lchannel_mapping[2] = use_back_flavor ?
4814 PCM_CHANNEL_LB : PCM_CHANNEL_LS;
4815 lchannel_mapping[3] = use_back_flavor ?
4816 PCM_CHANNEL_RB : PCM_CHANNEL_RS;
4817 } else if (channels == 5) {
4818 lchannel_mapping[0] = PCM_CHANNEL_FL;
4819 lchannel_mapping[1] = PCM_CHANNEL_FR;
4820 lchannel_mapping[2] = PCM_CHANNEL_FC;
4821 lchannel_mapping[3] = use_back_flavor ?
4822 PCM_CHANNEL_LB : PCM_CHANNEL_LS;
4823 lchannel_mapping[4] = use_back_flavor ?
4824 PCM_CHANNEL_RB : PCM_CHANNEL_RS;
4825 } else if (channels == 6) {
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] = PCM_CHANNEL_LFE;
4830 lchannel_mapping[4] = use_back_flavor ?
4831 PCM_CHANNEL_LB : PCM_CHANNEL_LS;
4832 lchannel_mapping[5] = use_back_flavor ?
4833 PCM_CHANNEL_RB : PCM_CHANNEL_RS;
4834 } else if (channels == 7) {
4835 /*
4836 * Configured for 5.1 channel mapping + 1 channel for debug
4837 * Can be customized based on DSP.
4838 */
4839 lchannel_mapping[0] = PCM_CHANNEL_FL;
4840 lchannel_mapping[1] = PCM_CHANNEL_FR;
4841 lchannel_mapping[2] = PCM_CHANNEL_FC;
4842 lchannel_mapping[3] = PCM_CHANNEL_LFE;
4843 lchannel_mapping[4] = use_back_flavor ?
4844 PCM_CHANNEL_LB : PCM_CHANNEL_LS;
4845 lchannel_mapping[5] = use_back_flavor ?
4846 PCM_CHANNEL_RB : PCM_CHANNEL_RS;
4847 lchannel_mapping[6] = PCM_CHANNEL_CS;
4848 } else if (channels == 8) {
4849 lchannel_mapping[0] = PCM_CHANNEL_FL;
4850 lchannel_mapping[1] = PCM_CHANNEL_FR;
4851 lchannel_mapping[2] = PCM_CHANNEL_FC;
4852 lchannel_mapping[3] = PCM_CHANNEL_LFE;
4853 lchannel_mapping[4] = PCM_CHANNEL_LB;
4854 lchannel_mapping[5] = PCM_CHANNEL_RB;
4855 lchannel_mapping[6] = PCM_CHANNEL_LS;
4856 lchannel_mapping[7] = PCM_CHANNEL_RS;
4857 } else {
4858 pr_err("%s: ERROR.unsupported num_ch = %u\n",
4859 __func__, channels);
4860 return -EINVAL;
4861 }
4862 return 0;
4863}
4864
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304865/**
4866 * q6asm_enable_sbrps -
4867 * command to enable sbrps for ASM
4868 *
4869 * @ac: Audio client handle
4870 * @sbr_ps_enable: flag for sbr_ps enable or disable
4871 *
4872 * Returns 0 on success or error on failure
4873 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304874int q6asm_enable_sbrps(struct audio_client *ac,
4875 uint32_t sbr_ps_enable)
4876{
4877 struct asm_aac_sbr_ps_flag_param sbrps;
4878 u32 frames_per_buf = 0;
4879
4880 int rc = 0;
4881
4882 pr_debug("%s: Session %d\n", __func__, ac->session);
4883
4884 q6asm_add_hdr(ac, &sbrps.hdr, sizeof(sbrps), TRUE);
4885 atomic_set(&ac->cmd_state, -1);
4886
4887 sbrps.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4888 sbrps.encdec.param_id = ASM_PARAM_ID_AAC_SBR_PS_FLAG;
4889 sbrps.encdec.param_size = sizeof(struct asm_aac_sbr_ps_flag_param) -
4890 sizeof(struct asm_stream_cmd_set_encdec_param);
4891 sbrps.encblk.frames_per_buf = frames_per_buf;
4892 sbrps.encblk.enc_cfg_blk_size = sbrps.encdec.param_size -
4893 sizeof(struct asm_enc_cfg_blk_param_v2);
4894
4895 sbrps.sbr_ps_flag = sbr_ps_enable;
4896
4897 rc = apr_send_pkt(ac->apr, (uint32_t *) &sbrps);
4898 if (rc < 0) {
4899 pr_err("%s: Command opcode[0x%x]paramid[0x%x] failed %d\n",
4900 __func__,
4901 ASM_STREAM_CMD_SET_ENCDEC_PARAM,
4902 ASM_PARAM_ID_AAC_SBR_PS_FLAG, rc);
4903 rc = -EINVAL;
4904 goto fail_cmd;
4905 }
4906 rc = wait_event_timeout(ac->cmd_wait,
4907 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4908 if (!rc) {
4909 pr_err("%s: timeout opcode[0x%x] ", __func__, sbrps.hdr.opcode);
4910 rc = -ETIMEDOUT;
4911 goto fail_cmd;
4912 }
4913 if (atomic_read(&ac->cmd_state) > 0) {
4914 pr_err("%s: DSP returned error[%s]\n",
4915 __func__, adsp_err_get_err_str(
4916 atomic_read(&ac->cmd_state)));
4917 rc = adsp_err_get_lnx_err_code(
4918 atomic_read(&ac->cmd_state));
4919 goto fail_cmd;
4920 }
4921 return 0;
4922fail_cmd:
4923 return rc;
4924}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304925EXPORT_SYMBOL(q6asm_enable_sbrps);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304926
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304927/**
4928 * q6asm_cfg_dual_mono_aac -
4929 * command to set config for dual mono aac
4930 *
4931 * @ac: Audio client handle
4932 * @sce_left: left sce val
4933 * @sce_right: right sce val
4934 *
4935 * Returns 0 on success or error on failure
4936 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304937int q6asm_cfg_dual_mono_aac(struct audio_client *ac,
4938 uint16_t sce_left, uint16_t sce_right)
4939{
4940 struct asm_aac_dual_mono_mapping_param dual_mono;
4941
4942 int rc = 0;
4943
4944 pr_debug("%s: Session %d, sce_left = %d, sce_right = %d\n",
4945 __func__, ac->session, sce_left, sce_right);
4946
4947 q6asm_add_hdr(ac, &dual_mono.hdr, sizeof(dual_mono), TRUE);
4948 atomic_set(&ac->cmd_state, -1);
4949
4950 dual_mono.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4951 dual_mono.encdec.param_id = ASM_PARAM_ID_AAC_DUAL_MONO_MAPPING;
4952 dual_mono.encdec.param_size = sizeof(dual_mono.left_channel_sce) +
4953 sizeof(dual_mono.right_channel_sce);
4954 dual_mono.left_channel_sce = sce_left;
4955 dual_mono.right_channel_sce = sce_right;
4956
4957 rc = apr_send_pkt(ac->apr, (uint32_t *) &dual_mono);
4958 if (rc < 0) {
4959 pr_err("%s: Command opcode[0x%x]paramid[0x%x] failed %d\n",
4960 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM,
4961 ASM_PARAM_ID_AAC_DUAL_MONO_MAPPING, rc);
4962 rc = -EINVAL;
4963 goto fail_cmd;
4964 }
4965 rc = wait_event_timeout(ac->cmd_wait,
4966 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
4967 if (!rc) {
4968 pr_err("%s: timeout opcode[0x%x]\n", __func__,
4969 dual_mono.hdr.opcode);
4970 rc = -ETIMEDOUT;
4971 goto fail_cmd;
4972 }
4973 if (atomic_read(&ac->cmd_state) > 0) {
4974 pr_err("%s: DSP returned error[%s]\n",
4975 __func__, adsp_err_get_err_str(
4976 atomic_read(&ac->cmd_state)));
4977 rc = adsp_err_get_lnx_err_code(
4978 atomic_read(&ac->cmd_state));
4979 goto fail_cmd;
4980 }
4981 return 0;
4982fail_cmd:
4983 return rc;
4984}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304985EXPORT_SYMBOL(q6asm_cfg_dual_mono_aac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304986
4987/* Support for selecting stereo mixing coefficients for B family not done */
4988int q6asm_cfg_aac_sel_mix_coef(struct audio_client *ac, uint32_t mix_coeff)
4989{
4990 struct asm_aac_stereo_mix_coeff_selection_param_v2 aac_mix_coeff;
4991 int rc = 0;
4992
4993 q6asm_add_hdr(ac, &aac_mix_coeff.hdr, sizeof(aac_mix_coeff), TRUE);
4994 atomic_set(&ac->cmd_state, -1);
4995 aac_mix_coeff.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
4996 aac_mix_coeff.param_id =
4997 ASM_PARAM_ID_AAC_STEREO_MIX_COEFF_SELECTION_FLAG_V2;
4998 aac_mix_coeff.param_size =
4999 sizeof(struct asm_aac_stereo_mix_coeff_selection_param_v2);
5000 aac_mix_coeff.aac_stereo_mix_coeff_flag = mix_coeff;
5001 pr_debug("%s: mix_coeff = %u\n", __func__, mix_coeff);
5002 rc = apr_send_pkt(ac->apr, (uint32_t *) &aac_mix_coeff);
5003 if (rc < 0) {
5004 pr_err("%s: Command opcode[0x%x]paramid[0x%x] failed %d\n",
5005 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM,
5006 ASM_PARAM_ID_AAC_STEREO_MIX_COEFF_SELECTION_FLAG_V2,
5007 rc);
5008 rc = -EINVAL;
5009 goto fail_cmd;
5010 }
5011 rc = wait_event_timeout(ac->cmd_wait,
5012 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5013 if (!rc) {
5014 pr_err("%s: timeout opcode[0x%x]\n",
5015 __func__, aac_mix_coeff.hdr.opcode);
5016 rc = -ETIMEDOUT;
5017 goto fail_cmd;
5018 }
5019 if (atomic_read(&ac->cmd_state) > 0) {
5020 pr_err("%s: DSP returned error[%s]\n",
5021 __func__, adsp_err_get_err_str(
5022 atomic_read(&ac->cmd_state)));
5023 rc = adsp_err_get_lnx_err_code(
5024 atomic_read(&ac->cmd_state));
5025 goto fail_cmd;
5026 }
5027 return 0;
5028fail_cmd:
5029 return rc;
5030}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305031EXPORT_SYMBOL(q6asm_cfg_aac_sel_mix_coef);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305032
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305033/**
5034 * q6asm_enc_cfg_blk_qcelp -
5035 * command to set encode config block for QCELP
5036 *
5037 * @ac: Audio client handle
5038 * @frames_per_buf: Number of frames per buffer
5039 * @min_rate: Minimum Enc rate
5040 * @max_rate: Maximum Enc rate
5041 * reduced_rate_level: Reduced rate level
5042 * @rate_modulation_cmd: rate modulation command
5043 *
5044 * Returns 0 on success or error on failure
5045 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305046int q6asm_enc_cfg_blk_qcelp(struct audio_client *ac, uint32_t frames_per_buf,
5047 uint16_t min_rate, uint16_t max_rate,
5048 uint16_t reduced_rate_level, uint16_t rate_modulation_cmd)
5049{
5050 struct asm_v13k_enc_cfg enc_cfg;
5051 int rc = 0;
5052
5053 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",
5054 __func__,
5055 ac->session, frames_per_buf, min_rate, max_rate,
5056 reduced_rate_level, rate_modulation_cmd);
5057
5058 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
5059 atomic_set(&ac->cmd_state, -1);
5060 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
5061 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
5062 enc_cfg.encdec.param_size = sizeof(struct asm_v13k_enc_cfg) -
5063 sizeof(struct asm_stream_cmd_set_encdec_param);
5064 enc_cfg.encblk.frames_per_buf = frames_per_buf;
5065 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
5066 sizeof(struct asm_enc_cfg_blk_param_v2);
5067
5068 enc_cfg.min_rate = min_rate;
5069 enc_cfg.max_rate = max_rate;
5070 enc_cfg.reduced_rate_cmd = reduced_rate_level;
5071 enc_cfg.rate_mod_cmd = rate_modulation_cmd;
5072
5073 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
5074 if (rc < 0) {
5075 pr_err("%s: Comamnd %d failed %d\n",
5076 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
5077 rc = -EINVAL;
5078 goto fail_cmd;
5079 }
5080 rc = wait_event_timeout(ac->cmd_wait,
5081 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5082 if (!rc) {
5083 pr_err("%s: timeout. waited for setencdec v13k resp\n",
5084 __func__);
5085 rc = -ETIMEDOUT;
5086 goto fail_cmd;
5087 }
5088 if (atomic_read(&ac->cmd_state) > 0) {
5089 pr_err("%s: DSP returned error[%s]\n",
5090 __func__, adsp_err_get_err_str(
5091 atomic_read(&ac->cmd_state)));
5092 rc = adsp_err_get_lnx_err_code(
5093 atomic_read(&ac->cmd_state));
5094 goto fail_cmd;
5095 }
5096 return 0;
5097fail_cmd:
5098 return rc;
5099}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305100EXPORT_SYMBOL(q6asm_enc_cfg_blk_qcelp);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305101
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305102/**
5103 * q6asm_enc_cfg_blk_evrc -
5104 * command to set encode config block for EVRC
5105 *
5106 * @ac: Audio client handle
5107 * @frames_per_buf: Number of frames per buffer
5108 * @min_rate: Minimum Enc rate
5109 * @max_rate: Maximum Enc rate
5110 * @rate_modulation_cmd: rate modulation command
5111 *
5112 * Returns 0 on success or error on failure
5113 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305114int q6asm_enc_cfg_blk_evrc(struct audio_client *ac, uint32_t frames_per_buf,
5115 uint16_t min_rate, uint16_t max_rate,
5116 uint16_t rate_modulation_cmd)
5117{
5118 struct asm_evrc_enc_cfg enc_cfg;
5119 int rc = 0;
5120
5121 pr_debug("%s: session[%d]frames[%d]min_rate[0x%4x]max_rate[0x%4x] rate_modulation_cmd[0x%4x]\n",
5122 __func__, ac->session,
5123 frames_per_buf, min_rate, max_rate, rate_modulation_cmd);
5124
5125 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
5126 atomic_set(&ac->cmd_state, -1);
5127 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
5128 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
5129 enc_cfg.encdec.param_size = sizeof(struct asm_evrc_enc_cfg) -
5130 sizeof(struct asm_stream_cmd_set_encdec_param);
5131 enc_cfg.encblk.frames_per_buf = frames_per_buf;
5132 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
5133 sizeof(struct asm_enc_cfg_blk_param_v2);
5134
5135 enc_cfg.min_rate = min_rate;
5136 enc_cfg.max_rate = max_rate;
5137 enc_cfg.rate_mod_cmd = rate_modulation_cmd;
5138 enc_cfg.reserved = 0;
5139
5140 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
5141 if (rc < 0) {
5142 pr_err("%s: Comamnd %d failed %d\n",
5143 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
5144 rc = -EINVAL;
5145 goto fail_cmd;
5146 }
5147 rc = wait_event_timeout(ac->cmd_wait,
5148 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5149 if (!rc) {
5150 pr_err("%s: timeout. waited for encdec evrc\n", __func__);
5151 rc = -ETIMEDOUT;
5152 goto fail_cmd;
5153 }
5154 if (atomic_read(&ac->cmd_state) > 0) {
5155 pr_err("%s: DSP returned error[%s]\n",
5156 __func__, adsp_err_get_err_str(
5157 atomic_read(&ac->cmd_state)));
5158 rc = adsp_err_get_lnx_err_code(
5159 atomic_read(&ac->cmd_state));
5160 goto fail_cmd;
5161 }
5162 return 0;
5163fail_cmd:
5164 return rc;
5165}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305166EXPORT_SYMBOL(q6asm_enc_cfg_blk_evrc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305167
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305168/**
5169 * q6asm_enc_cfg_blk_amrnb -
5170 * command to set encode config block for AMRNB
5171 *
5172 * @ac: Audio client handle
5173 * @frames_per_buf: Number of frames per buffer
5174 * @band_mode: Band mode used
5175 * @dtx_enable: DTX en flag
5176 *
5177 * Returns 0 on success or error on failure
5178 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305179int q6asm_enc_cfg_blk_amrnb(struct audio_client *ac, uint32_t frames_per_buf,
5180 uint16_t band_mode, uint16_t dtx_enable)
5181{
5182 struct asm_amrnb_enc_cfg enc_cfg;
5183 int rc = 0;
5184
5185 pr_debug("%s: session[%d]frames[%d]band_mode[0x%4x]dtx_enable[0x%4x]\n",
5186 __func__, ac->session, frames_per_buf, band_mode, dtx_enable);
5187
5188 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
5189 atomic_set(&ac->cmd_state, -1);
5190 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
5191 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
5192 enc_cfg.encdec.param_size = sizeof(struct asm_amrnb_enc_cfg) -
5193 sizeof(struct asm_stream_cmd_set_encdec_param);
5194 enc_cfg.encblk.frames_per_buf = frames_per_buf;
5195 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
5196 sizeof(struct asm_enc_cfg_blk_param_v2);
5197
5198 enc_cfg.enc_mode = band_mode;
5199 enc_cfg.dtx_mode = dtx_enable;
5200
5201 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
5202 if (rc < 0) {
5203 pr_err("%s: Comamnd %d failed %d\n",
5204 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
5205 rc = -EINVAL;
5206 goto fail_cmd;
5207 }
5208 rc = wait_event_timeout(ac->cmd_wait,
5209 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5210 if (!rc) {
5211 pr_err("%s: timeout. waited for set encdec amrnb\n", __func__);
5212 rc = -ETIMEDOUT;
5213 goto fail_cmd;
5214 }
5215 if (atomic_read(&ac->cmd_state) > 0) {
5216 pr_err("%s: DSP returned error[%s]\n",
5217 __func__, adsp_err_get_err_str(
5218 atomic_read(&ac->cmd_state)));
5219 rc = adsp_err_get_lnx_err_code(
5220 atomic_read(&ac->cmd_state));
5221 goto fail_cmd;
5222 }
5223 return 0;
5224fail_cmd:
5225 return rc;
5226}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305227EXPORT_SYMBOL(q6asm_enc_cfg_blk_amrnb);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305228
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305229/**
5230 * q6asm_enc_cfg_blk_amrwb -
5231 * command to set encode config block for AMRWB
5232 *
5233 * @ac: Audio client handle
5234 * @frames_per_buf: Number of frames per buffer
5235 * @band_mode: Band mode used
5236 * @dtx_enable: DTX en flag
5237 *
5238 * Returns 0 on success or error on failure
5239 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305240int q6asm_enc_cfg_blk_amrwb(struct audio_client *ac, uint32_t frames_per_buf,
5241 uint16_t band_mode, uint16_t dtx_enable)
5242{
5243 struct asm_amrwb_enc_cfg enc_cfg;
5244 int rc = 0;
5245
5246 pr_debug("%s: session[%d]frames[%d]band_mode[0x%4x]dtx_enable[0x%4x]\n",
5247 __func__, ac->session, frames_per_buf, band_mode, dtx_enable);
5248
5249 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
5250 atomic_set(&ac->cmd_state, -1);
5251 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
5252 enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
5253 enc_cfg.encdec.param_size = sizeof(struct asm_amrwb_enc_cfg) -
5254 sizeof(struct asm_stream_cmd_set_encdec_param);
5255 enc_cfg.encblk.frames_per_buf = frames_per_buf;
5256 enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
5257 sizeof(struct asm_enc_cfg_blk_param_v2);
5258
5259 enc_cfg.enc_mode = band_mode;
5260 enc_cfg.dtx_mode = dtx_enable;
5261
5262 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
5263 if (rc < 0) {
5264 pr_err("%s: Comamnd %d failed %d\n",
5265 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
5266 rc = -EINVAL;
5267 goto fail_cmd;
5268 }
5269 rc = wait_event_timeout(ac->cmd_wait,
5270 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5271 if (!rc) {
5272 pr_err("%s: timeout. waited for FORMAT_UPDATE\n", __func__);
5273 rc = -ETIMEDOUT;
5274 goto fail_cmd;
5275 }
5276 if (atomic_read(&ac->cmd_state) > 0) {
5277 pr_err("%s: DSP returned error[%s]\n",
5278 __func__, adsp_err_get_err_str(
5279 atomic_read(&ac->cmd_state)));
5280 rc = adsp_err_get_lnx_err_code(
5281 atomic_read(&ac->cmd_state));
5282 goto fail_cmd;
5283 }
5284 return 0;
5285fail_cmd:
5286 return rc;
5287}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305288EXPORT_SYMBOL(q6asm_enc_cfg_blk_amrwb);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305289
5290
5291static int __q6asm_media_format_block_pcm(struct audio_client *ac,
5292 uint32_t rate, uint32_t channels,
5293 uint16_t bits_per_sample, int stream_id,
5294 bool use_default_chmap, char *channel_map)
5295{
5296 struct asm_multi_channel_pcm_fmt_blk_v2 fmt;
5297 u8 *channel_mapping;
5298 int rc = 0;
5299
5300 pr_debug("%s: session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
5301 channels);
5302
5303 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
5304 atomic_set(&ac->cmd_state, -1);
5305 /*
5306 * Updated the token field with stream/session for compressed playback
5307 * Platform driver must know the the stream with which the command is
5308 * associated
5309 */
5310 if (ac->io_mode & COMPRESSED_STREAM_IO)
5311 q6asm_update_token(&fmt.hdr.token,
5312 ac->session,
5313 stream_id,
5314 0, /* Buffer index is NA */
5315 0, /* Direction flag is NA */
5316 WAIT_CMD);
5317
5318 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
5319 __func__, fmt.hdr.token, stream_id, ac->session);
5320
5321 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5322 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5323 sizeof(fmt.fmt_blk);
5324 fmt.num_channels = channels;
5325 fmt.bits_per_sample = bits_per_sample;
5326 fmt.sample_rate = rate;
5327 fmt.is_signed = 1;
5328
5329 channel_mapping = fmt.channel_mapping;
5330
5331 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5332
5333 if (use_default_chmap) {
5334 if (q6asm_map_channels(channel_mapping, channels, false)) {
5335 pr_err("%s: map channels failed %d\n",
5336 __func__, channels);
5337 return -EINVAL;
5338 }
5339 } else {
5340 memcpy(channel_mapping, channel_map,
5341 PCM_FORMAT_MAX_NUM_CHANNEL);
5342 }
5343
5344 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
5345 if (rc < 0) {
5346 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
5347 rc = -EINVAL;
5348 goto fail_cmd;
5349 }
5350 rc = wait_event_timeout(ac->cmd_wait,
5351 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5352 if (!rc) {
5353 pr_err("%s: timeout. waited for format update\n", __func__);
5354 rc = -ETIMEDOUT;
5355 goto fail_cmd;
5356 }
5357 if (atomic_read(&ac->cmd_state) > 0) {
5358 pr_err("%s: DSP returned error[%s]\n",
5359 __func__, adsp_err_get_err_str(
5360 atomic_read(&ac->cmd_state)));
5361 rc = adsp_err_get_lnx_err_code(
5362 atomic_read(&ac->cmd_state));
5363 goto fail_cmd;
5364 }
5365 return 0;
5366fail_cmd:
5367 return rc;
5368}
5369
5370static int __q6asm_media_format_block_pcm_v3(struct audio_client *ac,
5371 uint32_t rate, uint32_t channels,
5372 uint16_t bits_per_sample,
5373 int stream_id,
5374 bool use_default_chmap,
5375 char *channel_map,
5376 uint16_t sample_word_size)
5377{
5378 struct asm_multi_channel_pcm_fmt_blk_param_v3 fmt;
5379 u8 *channel_mapping;
5380 int rc;
5381
5382 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
5383 ac->session, rate, channels,
5384 bits_per_sample, sample_word_size);
5385
5386 memset(&fmt, 0, sizeof(fmt));
5387 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
5388 atomic_set(&ac->cmd_state, -1);
5389 /*
5390 * Updated the token field with stream/session for compressed playback
5391 * Platform driver must know the the stream with which the command is
5392 * associated
5393 */
5394 if (ac->io_mode & COMPRESSED_STREAM_IO)
5395 fmt.hdr.token = ((ac->session << 8) & 0xFFFF00) |
5396 (stream_id & 0xFF);
5397
5398 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
5399 __func__, fmt.hdr.token, stream_id, ac->session);
5400
5401 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5402 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5403 sizeof(fmt.fmt_blk);
5404 fmt.param.num_channels = channels;
5405 fmt.param.bits_per_sample = bits_per_sample;
5406 fmt.param.sample_rate = rate;
5407 fmt.param.is_signed = 1;
5408 fmt.param.sample_word_size = sample_word_size;
5409 channel_mapping = fmt.param.channel_mapping;
5410
5411 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5412
5413 if (use_default_chmap) {
5414 if (q6asm_map_channels(channel_mapping, channels, false)) {
5415 pr_err("%s: map channels failed %d\n",
5416 __func__, channels);
5417 rc = -EINVAL;
5418 goto fail_cmd;
5419 }
5420 } else {
5421 memcpy(channel_mapping, channel_map,
5422 PCM_FORMAT_MAX_NUM_CHANNEL);
5423 }
5424
5425 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
5426 if (rc < 0) {
5427 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
5428 rc = -EINVAL;
5429 goto fail_cmd;
5430 }
5431 rc = wait_event_timeout(ac->cmd_wait,
5432 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5433 if (!rc) {
5434 pr_err("%s: timeout. waited for format update\n", __func__);
5435 rc = -ETIMEDOUT;
5436 goto fail_cmd;
5437 }
5438 if (atomic_read(&ac->cmd_state) > 0) {
5439 pr_err("%s: DSP returned error[%s]\n",
5440 __func__, adsp_err_get_err_str(
5441 atomic_read(&ac->cmd_state)));
5442 rc = adsp_err_get_lnx_err_code(
5443 atomic_read(&ac->cmd_state));
5444 goto fail_cmd;
5445 }
5446 return 0;
5447fail_cmd:
5448 return rc;
5449}
5450
5451static int __q6asm_media_format_block_pcm_v4(struct audio_client *ac,
5452 uint32_t rate, uint32_t channels,
5453 uint16_t bits_per_sample,
5454 int stream_id,
5455 bool use_default_chmap,
5456 char *channel_map,
5457 uint16_t sample_word_size,
5458 uint16_t endianness,
5459 uint16_t mode)
5460{
5461 struct asm_multi_channel_pcm_fmt_blk_param_v4 fmt;
5462 u8 *channel_mapping;
5463 int rc;
5464
5465 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
5466 ac->session, rate, channels,
5467 bits_per_sample, sample_word_size);
5468
5469 memset(&fmt, 0, sizeof(fmt));
5470 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
5471 atomic_set(&ac->cmd_state, -1);
5472 /*
5473 * Updated the token field with stream/session for compressed playback
5474 * Platform driver must know the the stream with which the command is
5475 * associated
5476 */
5477 if (ac->io_mode & COMPRESSED_STREAM_IO)
5478 fmt.hdr.token = ((ac->session << 8) & 0xFFFF00) |
5479 (stream_id & 0xFF);
5480
5481 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
5482 __func__, fmt.hdr.token, stream_id, ac->session);
5483
5484 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5485 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5486 sizeof(fmt.fmt_blk);
5487 fmt.param.num_channels = channels;
5488 fmt.param.bits_per_sample = bits_per_sample;
5489 fmt.param.sample_rate = rate;
5490 fmt.param.is_signed = 1;
5491 fmt.param.sample_word_size = sample_word_size;
5492 fmt.param.endianness = endianness;
5493 fmt.param.mode = mode;
5494 channel_mapping = fmt.param.channel_mapping;
5495
5496 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5497
5498 if (use_default_chmap) {
5499 if (q6asm_map_channels(channel_mapping, channels, false)) {
5500 pr_err("%s: map channels failed %d\n",
5501 __func__, channels);
5502 rc = -EINVAL;
5503 goto fail_cmd;
5504 }
5505 } else {
5506 memcpy(channel_mapping, channel_map,
5507 PCM_FORMAT_MAX_NUM_CHANNEL);
5508 }
5509
5510 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
5511 if (rc < 0) {
5512 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
5513 rc = -EINVAL;
5514 goto fail_cmd;
5515 }
5516 rc = wait_event_timeout(ac->cmd_wait,
5517 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5518 if (!rc) {
5519 pr_err("%s: timeout. waited for format update\n", __func__);
5520 rc = -ETIMEDOUT;
5521 goto fail_cmd;
5522 }
5523 if (atomic_read(&ac->cmd_state) > 0) {
5524 pr_err("%s: DSP returned error[%s]\n",
5525 __func__, adsp_err_get_err_str(
5526 atomic_read(&ac->cmd_state)));
5527 rc = adsp_err_get_lnx_err_code(
5528 atomic_read(&ac->cmd_state));
5529 goto fail_cmd;
5530 }
5531 return 0;
5532fail_cmd:
5533 return rc;
5534}
5535
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305536/**
5537 * q6asm_media_format_block_pcm -
5538 * command to set mediafmt block for PCM on ASM stream
5539 *
5540 * @ac: Audio client handle
5541 * @rate: sample rate
5542 * @channels: number of ASM channels
5543 *
5544 * Returns 0 on success or error on failure
5545 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305546int q6asm_media_format_block_pcm(struct audio_client *ac,
5547 uint32_t rate, uint32_t channels)
5548{
5549 return __q6asm_media_format_block_pcm(ac, rate,
5550 channels, 16, ac->stream_id,
5551 true, NULL);
5552}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305553EXPORT_SYMBOL(q6asm_media_format_block_pcm);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305554
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305555/**
5556 * q6asm_media_format_block_pcm_format_support -
5557 * command to set mediafmt block for PCM format support
5558 *
5559 * @ac: Audio client handle
5560 * @rate: sample rate
5561 * @channels: number of ASM channels
5562 * @bits_per_sample: number of bits per sample
5563 *
5564 * Returns 0 on success or error on failure
5565 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305566int q6asm_media_format_block_pcm_format_support(struct audio_client *ac,
5567 uint32_t rate, uint32_t channels,
5568 uint16_t bits_per_sample)
5569{
5570 return __q6asm_media_format_block_pcm(ac, rate,
5571 channels, bits_per_sample, ac->stream_id,
5572 true, NULL);
5573}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305574EXPORT_SYMBOL(q6asm_media_format_block_pcm_format_support);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305575
5576int q6asm_media_format_block_pcm_format_support_v2(struct audio_client *ac,
5577 uint32_t rate, uint32_t channels,
5578 uint16_t bits_per_sample, int stream_id,
5579 bool use_default_chmap, char *channel_map)
5580{
5581 if (!use_default_chmap && (channel_map == NULL)) {
5582 pr_err("%s: No valid chan map and can't use default\n",
5583 __func__);
5584 return -EINVAL;
5585 }
5586 return __q6asm_media_format_block_pcm(ac, rate,
5587 channels, bits_per_sample, stream_id,
5588 use_default_chmap, channel_map);
5589}
5590
5591/*
5592 * q6asm_media_format_block_pcm_format_support_v3- sends pcm decoder
5593 * configuration parameters
5594 *
5595 * @ac: Client session handle
5596 * @rate: sample rate
5597 * @channels: number of channels
5598 * @bits_per_sample: bit width of encoder session
5599 * @stream_id: stream id of stream to be associated with this session
5600 * @use_default_chmap: true if default channel map to be used
5601 * @channel_map: input channel map
5602 * @sample_word_size: Size in bits of the word that holds a sample of a channel
5603 */
5604int q6asm_media_format_block_pcm_format_support_v3(struct audio_client *ac,
5605 uint32_t rate,
5606 uint32_t channels,
5607 uint16_t bits_per_sample,
5608 int stream_id,
5609 bool use_default_chmap,
5610 char *channel_map,
5611 uint16_t sample_word_size)
5612{
5613 if (!use_default_chmap && (channel_map == NULL)) {
5614 pr_err("%s: No valid chan map and can't use default\n",
5615 __func__);
5616 return -EINVAL;
5617 }
5618 return __q6asm_media_format_block_pcm_v3(ac, rate,
5619 channels, bits_per_sample, stream_id,
5620 use_default_chmap, channel_map,
5621 sample_word_size);
5622
5623}
5624EXPORT_SYMBOL(q6asm_media_format_block_pcm_format_support_v3);
5625
5626/*
5627 * q6asm_media_format_block_pcm_format_support_v4- sends pcm decoder
5628 * configuration parameters
5629 *
5630 * @ac: Client session handle
5631 * @rate: sample rate
5632 * @channels: number of channels
5633 * @bits_per_sample: bit width of encoder session
5634 * @stream_id: stream id of stream to be associated with this session
5635 * @use_default_chmap: true if default channel map to be used
5636 * @channel_map: input channel map
5637 * @sample_word_size: Size in bits of the word that holds a sample of a channel
5638 * @endianness: endianness of the pcm data
5639 * @mode: Mode to provide additional info about the pcm input data
5640 */
5641int q6asm_media_format_block_pcm_format_support_v4(struct audio_client *ac,
5642 uint32_t rate,
5643 uint32_t channels,
5644 uint16_t bits_per_sample,
5645 int stream_id,
5646 bool use_default_chmap,
5647 char *channel_map,
5648 uint16_t sample_word_size,
5649 uint16_t endianness,
5650 uint16_t mode)
5651{
5652 if (!use_default_chmap && (channel_map == NULL)) {
5653 pr_err("%s: No valid chan map and can't use default\n",
5654 __func__);
5655 return -EINVAL;
5656 }
5657 return __q6asm_media_format_block_pcm_v4(ac, rate,
5658 channels, bits_per_sample, stream_id,
5659 use_default_chmap, channel_map,
5660 sample_word_size, endianness,
5661 mode);
5662
5663}
5664EXPORT_SYMBOL(q6asm_media_format_block_pcm_format_support_v4);
5665
5666
5667static int __q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
5668 uint32_t rate, uint32_t channels,
5669 bool use_default_chmap, char *channel_map,
5670 uint16_t bits_per_sample)
5671{
5672 struct asm_multi_channel_pcm_fmt_blk_v2 fmt;
5673 u8 *channel_mapping;
5674 int rc = 0;
5675
5676 pr_debug("%s: session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
5677 channels);
5678
5679 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
5680 atomic_set(&ac->cmd_state, -1);
5681
5682 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5683 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5684 sizeof(fmt.fmt_blk);
5685 fmt.num_channels = channels;
5686 fmt.bits_per_sample = bits_per_sample;
5687 fmt.sample_rate = rate;
5688 fmt.is_signed = 1;
5689
5690 channel_mapping = fmt.channel_mapping;
5691
5692 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5693
5694 if (use_default_chmap) {
5695 if (q6asm_map_channels(channel_mapping, channels, false)) {
5696 pr_err("%s: map channels failed %d\n",
5697 __func__, channels);
5698 return -EINVAL;
5699 }
5700 } else {
5701 memcpy(channel_mapping, channel_map,
5702 PCM_FORMAT_MAX_NUM_CHANNEL);
5703 }
5704
5705 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
5706 if (rc < 0) {
5707 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
5708 rc = -EINVAL;
5709 goto fail_cmd;
5710 }
5711 rc = wait_event_timeout(ac->cmd_wait,
5712 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5713 if (!rc) {
5714 pr_err("%s: timeout. waited for format update\n", __func__);
5715 rc = -ETIMEDOUT;
5716 goto fail_cmd;
5717 }
5718 if (atomic_read(&ac->cmd_state) > 0) {
5719 pr_err("%s: DSP returned error[%s]\n",
5720 __func__, adsp_err_get_err_str(
5721 atomic_read(&ac->cmd_state)));
5722 rc = adsp_err_get_lnx_err_code(
5723 atomic_read(&ac->cmd_state));
5724 goto fail_cmd;
5725 }
5726 return 0;
5727fail_cmd:
5728 return rc;
5729}
5730
5731static int __q6asm_media_format_block_multi_ch_pcm_v3(struct audio_client *ac,
5732 uint32_t rate,
5733 uint32_t channels,
5734 bool use_default_chmap,
5735 char *channel_map,
5736 uint16_t bits_per_sample,
5737 uint16_t sample_word_size)
5738{
5739 struct asm_multi_channel_pcm_fmt_blk_param_v3 fmt;
5740 u8 *channel_mapping;
5741 int rc;
5742
5743 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
5744 ac->session, rate, channels,
5745 bits_per_sample, sample_word_size);
5746
5747 memset(&fmt, 0, sizeof(fmt));
5748 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
5749 atomic_set(&ac->cmd_state, -1);
5750
5751 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5752 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5753 sizeof(fmt.fmt_blk);
5754 fmt.param.num_channels = channels;
5755 fmt.param.bits_per_sample = bits_per_sample;
5756 fmt.param.sample_rate = rate;
5757 fmt.param.is_signed = 1;
5758 fmt.param.sample_word_size = sample_word_size;
5759 channel_mapping = fmt.param.channel_mapping;
5760
5761 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5762
5763 if (use_default_chmap) {
5764 if (q6asm_map_channels(channel_mapping, channels, false)) {
5765 pr_err("%s: map channels failed %d\n",
5766 __func__, channels);
5767 rc = -EINVAL;
5768 goto fail_cmd;
5769 }
5770 } else {
5771 memcpy(channel_mapping, channel_map,
5772 PCM_FORMAT_MAX_NUM_CHANNEL);
5773 }
5774
5775 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
5776 if (rc < 0) {
5777 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
5778 goto fail_cmd;
5779 }
5780 rc = wait_event_timeout(ac->cmd_wait,
5781 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5782 if (!rc) {
5783 pr_err("%s: timeout. waited for format update\n", __func__);
5784 rc = -ETIMEDOUT;
5785 goto fail_cmd;
5786 }
5787 if (atomic_read(&ac->cmd_state) > 0) {
5788 pr_err("%s: DSP returned error[%s]\n",
5789 __func__, adsp_err_get_err_str(
5790 atomic_read(&ac->cmd_state)));
5791 rc = adsp_err_get_lnx_err_code(
5792 atomic_read(&ac->cmd_state));
5793 goto fail_cmd;
5794 }
5795 return 0;
5796fail_cmd:
5797 return rc;
5798}
5799
5800static int __q6asm_media_format_block_multi_ch_pcm_v4(struct audio_client *ac,
5801 uint32_t rate,
5802 uint32_t channels,
5803 bool use_default_chmap,
5804 char *channel_map,
5805 uint16_t bits_per_sample,
5806 uint16_t sample_word_size,
5807 uint16_t endianness,
5808 uint16_t mode)
5809{
5810 struct asm_multi_channel_pcm_fmt_blk_param_v4 fmt;
5811 u8 *channel_mapping;
5812 int rc;
5813
5814 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
5815 ac->session, rate, channels,
5816 bits_per_sample, sample_word_size);
5817
5818 memset(&fmt, 0, sizeof(fmt));
5819 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
5820 atomic_set(&ac->cmd_state, -1);
5821
5822 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5823 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5824 sizeof(fmt.fmt_blk);
5825 fmt.param.num_channels = channels;
5826 fmt.param.bits_per_sample = bits_per_sample;
5827 fmt.param.sample_rate = rate;
5828 fmt.param.is_signed = 1;
5829 fmt.param.sample_word_size = sample_word_size;
5830 fmt.param.endianness = endianness;
5831 fmt.param.mode = mode;
5832 channel_mapping = fmt.param.channel_mapping;
5833
5834 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5835
5836 if (use_default_chmap) {
5837 if (q6asm_map_channels(channel_mapping, channels, false)) {
5838 pr_err("%s: map channels failed %d\n",
5839 __func__, channels);
5840 rc = -EINVAL;
5841 goto fail_cmd;
5842 }
5843 } else {
5844 memcpy(channel_mapping, channel_map,
5845 PCM_FORMAT_MAX_NUM_CHANNEL);
5846 }
5847
5848 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
5849 if (rc < 0) {
5850 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
5851 goto fail_cmd;
5852 }
5853 rc = wait_event_timeout(ac->cmd_wait,
5854 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
5855 if (!rc) {
5856 pr_err("%s: timeout. waited for format update\n", __func__);
5857 rc = -ETIMEDOUT;
5858 goto fail_cmd;
5859 }
5860 if (atomic_read(&ac->cmd_state) > 0) {
5861 pr_err("%s: DSP returned error[%s]\n",
5862 __func__, adsp_err_get_err_str(
5863 atomic_read(&ac->cmd_state)));
5864 rc = adsp_err_get_lnx_err_code(
5865 atomic_read(&ac->cmd_state));
5866 goto fail_cmd;
5867 }
5868 return 0;
5869fail_cmd:
5870 return rc;
5871}
5872
5873int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
5874 uint32_t rate, uint32_t channels,
5875 bool use_default_chmap, char *channel_map)
5876{
5877 return __q6asm_media_format_block_multi_ch_pcm(ac, rate,
5878 channels, use_default_chmap, channel_map, 16);
5879}
5880
5881int q6asm_media_format_block_multi_ch_pcm_v2(
5882 struct audio_client *ac,
5883 uint32_t rate, uint32_t channels,
5884 bool use_default_chmap, char *channel_map,
5885 uint16_t bits_per_sample)
5886{
5887 return __q6asm_media_format_block_multi_ch_pcm(ac, rate,
5888 channels, use_default_chmap, channel_map,
5889 bits_per_sample);
5890}
5891
5892/*
5893 * q6asm_media_format_block_multi_ch_pcm_v3 - sends pcm decoder configuration
5894 * parameters
5895 *
5896 * @ac: Client session handle
5897 * @rate: sample rate
5898 * @channels: number of channels
5899 * @bits_per_sample: bit width of encoder session
5900 * @use_default_chmap: true if default channel map to be used
5901 * @channel_map: input channel map
5902 * @sample_word_size: Size in bits of the word that holds a sample of a channel
5903 */
5904int q6asm_media_format_block_multi_ch_pcm_v3(struct audio_client *ac,
5905 uint32_t rate, uint32_t channels,
5906 bool use_default_chmap,
5907 char *channel_map,
5908 uint16_t bits_per_sample,
5909 uint16_t sample_word_size)
5910{
5911 return __q6asm_media_format_block_multi_ch_pcm_v3(ac, rate, channels,
5912 use_default_chmap,
5913 channel_map,
5914 bits_per_sample,
5915 sample_word_size);
5916}
5917EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v3);
5918
5919/*
5920 * q6asm_media_format_block_multi_ch_pcm_v4 - sends pcm decoder configuration
5921 * parameters
5922 *
5923 * @ac: Client session handle
5924 * @rate: sample rate
5925 * @channels: number of channels
5926 * @bits_per_sample: bit width of encoder session
5927 * @use_default_chmap: true if default channel map to be used
5928 * @channel_map: input channel map
5929 * @sample_word_size: Size in bits of the word that holds a sample of a channel
5930 * @endianness: endianness of the pcm data
5931 * @mode: Mode to provide additional info about the pcm input data
5932 */
5933int q6asm_media_format_block_multi_ch_pcm_v4(struct audio_client *ac,
5934 uint32_t rate, uint32_t channels,
5935 bool use_default_chmap,
5936 char *channel_map,
5937 uint16_t bits_per_sample,
5938 uint16_t sample_word_size,
5939 uint16_t endianness,
5940 uint16_t mode)
5941{
5942 return __q6asm_media_format_block_multi_ch_pcm_v4(ac, rate, channels,
5943 use_default_chmap,
5944 channel_map,
5945 bits_per_sample,
5946 sample_word_size,
5947 endianness,
5948 mode);
5949}
5950EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v4);
5951
5952/*
5953 * q6asm_media_format_block_gen_compr - set up generic compress format params
5954 *
5955 * @ac: Client session handle
5956 * @rate: sample rate
5957 * @channels: number of channels
5958 * @use_default_chmap: true if default channel map to be used
5959 * @channel_map: input channel map
5960 * @bits_per_sample: bit width of gen compress stream
5961 */
5962int q6asm_media_format_block_gen_compr(struct audio_client *ac,
5963 uint32_t rate, uint32_t channels,
5964 bool use_default_chmap, char *channel_map,
5965 uint16_t bits_per_sample)
5966{
5967 struct asm_generic_compressed_fmt_blk_t fmt;
5968 u8 *channel_mapping;
5969 int rc = 0;
5970
5971 pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]\n",
5972 __func__, ac->session, rate,
5973 channels, bits_per_sample);
5974
5975 memset(&fmt, 0, sizeof(fmt));
5976 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
5977
5978 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
5979 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
5980 sizeof(fmt.fmt_blk);
5981 fmt.num_channels = channels;
5982 fmt.bits_per_sample = bits_per_sample;
5983 fmt.sampling_rate = rate;
5984
5985 channel_mapping = fmt.channel_mapping;
5986
5987 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
5988
5989 if (use_default_chmap) {
5990 if (q6asm_map_channels(channel_mapping, channels, false)) {
5991 pr_err("%s: map channels failed %d\n",
5992 __func__, channels);
5993 return -EINVAL;
5994 }
5995 } else {
5996 memcpy(channel_mapping, channel_map,
5997 PCM_FORMAT_MAX_NUM_CHANNEL);
5998 }
5999
6000 atomic_set(&ac->cmd_state, -1);
6001 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6002 if (rc < 0) {
6003 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
6004 rc = -EINVAL;
6005 goto fail_cmd;
6006 }
6007 rc = wait_event_timeout(ac->cmd_wait,
6008 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6009 if (!rc) {
6010 pr_err("%s: timeout. waited for format update\n", __func__);
6011 rc = -ETIMEDOUT;
6012 goto fail_cmd;
6013 }
6014
6015 if (atomic_read(&ac->cmd_state) > 0) {
6016 pr_err("%s: DSP returned error[%s]\n",
6017 __func__, adsp_err_get_err_str(
6018 atomic_read(&ac->cmd_state)));
6019 rc = adsp_err_get_lnx_err_code(
6020 atomic_read(&ac->cmd_state));
6021 }
6022 return 0;
6023fail_cmd:
6024 return rc;
6025}
6026EXPORT_SYMBOL(q6asm_media_format_block_gen_compr);
6027
6028
6029/*
6030 * q6asm_media_format_block_iec - set up IEC61937 (compressed) or IEC60958
6031 * (pcm) format params. Both audio standards
6032 * use the same format and are used for
6033 * HDMI or SPDIF.
6034 *
6035 * @ac: Client session handle
6036 * @rate: sample rate
6037 * @channels: number of channels
6038 */
6039int q6asm_media_format_block_iec(struct audio_client *ac,
6040 uint32_t rate, uint32_t channels)
6041{
6042 struct asm_iec_compressed_fmt_blk_t fmt;
6043 int rc = 0;
6044
6045 pr_debug("%s: session[%d]rate[%d]ch[%d]\n",
6046 __func__, ac->session, rate,
6047 channels);
6048
6049 memset(&fmt, 0, sizeof(fmt));
6050 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
6051
6052 fmt.hdr.opcode = ASM_DATA_CMD_IEC_60958_MEDIA_FMT;
6053 fmt.num_channels = channels;
6054 fmt.sampling_rate = rate;
6055
6056 atomic_set(&ac->cmd_state, -1);
6057 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6058 if (rc < 0) {
6059 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
6060 rc = -EINVAL;
6061 goto fail_cmd;
6062 }
6063 rc = wait_event_timeout(ac->cmd_wait,
6064 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6065 if (!rc) {
6066 pr_err("%s: timeout. waited for format update\n", __func__);
6067 rc = -ETIMEDOUT;
6068 goto fail_cmd;
6069 }
6070
6071 if (atomic_read(&ac->cmd_state) > 0) {
6072 pr_err("%s: DSP returned error[%s]\n",
6073 __func__, adsp_err_get_err_str(
6074 atomic_read(&ac->cmd_state)));
6075 rc = adsp_err_get_lnx_err_code(
6076 atomic_read(&ac->cmd_state));
6077 }
6078 return 0;
6079fail_cmd:
6080 return rc;
6081}
6082EXPORT_SYMBOL(q6asm_media_format_block_iec);
6083
6084static int __q6asm_media_format_block_multi_aac(struct audio_client *ac,
6085 struct asm_aac_cfg *cfg, int stream_id)
6086{
6087 struct asm_aac_fmt_blk_v2 fmt;
6088 int rc = 0;
6089
6090 pr_debug("%s: session[%d]rate[%d]ch[%d]\n", __func__, ac->session,
6091 cfg->sample_rate, cfg->ch_cfg);
6092
6093 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6094 atomic_set(&ac->cmd_state, -1);
6095 /*
6096 * Updated the token field with stream/session for compressed playback
6097 * Platform driver must know the the stream with which the command is
6098 * associated
6099 */
6100 if (ac->io_mode & COMPRESSED_STREAM_IO)
6101 q6asm_update_token(&fmt.hdr.token,
6102 ac->session,
6103 stream_id,
6104 0, /* Buffer index is NA */
6105 0, /* Direction flag is NA */
6106 WAIT_CMD);
6107
6108 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
6109 __func__, fmt.hdr.token, stream_id, ac->session);
6110 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6111 fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6112 sizeof(fmt.fmt_blk);
6113 fmt.aac_fmt_flag = cfg->format;
6114 fmt.audio_objype = cfg->aot;
6115 /* If zero, PCE is assumed to be available in bitstream*/
6116 fmt.total_size_of_PCE_bits = 0;
6117 fmt.channel_config = cfg->ch_cfg;
6118 fmt.sample_rate = cfg->sample_rate;
6119
6120 pr_debug("%s: format=0x%x cfg_size=%d aac-cfg=0x%x aot=%d ch=%d sr=%d\n",
6121 __func__, fmt.aac_fmt_flag, fmt.fmt_blk.fmt_blk_size,
6122 fmt.aac_fmt_flag,
6123 fmt.audio_objype,
6124 fmt.channel_config,
6125 fmt.sample_rate);
6126 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6127 if (rc < 0) {
6128 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
6129 rc = -EINVAL;
6130 goto fail_cmd;
6131 }
6132 rc = wait_event_timeout(ac->cmd_wait,
6133 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6134 if (!rc) {
6135 pr_err("%s: timeout. waited for FORMAT_UPDATE\n", __func__);
6136 rc = -ETIMEDOUT;
6137 goto fail_cmd;
6138 }
6139 if (atomic_read(&ac->cmd_state) > 0) {
6140 pr_err("%s: DSP returned error[%s]\n",
6141 __func__, adsp_err_get_err_str(
6142 atomic_read(&ac->cmd_state)));
6143 rc = adsp_err_get_lnx_err_code(
6144 atomic_read(&ac->cmd_state));
6145 goto fail_cmd;
6146 }
6147 return 0;
6148fail_cmd:
6149 return rc;
6150}
6151
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306152/**
6153 * q6asm_media_format_block_multi_aac -
6154 * command to set mediafmt block for multi_aac on ASM stream
6155 *
6156 * @ac: Audio client handle
6157 * @cfg: multi_aac config
6158 *
6159 * Returns 0 on success or error on failure
6160 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306161int q6asm_media_format_block_multi_aac(struct audio_client *ac,
6162 struct asm_aac_cfg *cfg)
6163{
6164 return __q6asm_media_format_block_multi_aac(ac, cfg, ac->stream_id);
6165}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306166EXPORT_SYMBOL(q6asm_media_format_block_multi_aac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306167
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306168/**
6169 * q6asm_media_format_block_aac -
6170 * command to set mediafmt block for aac on ASM
6171 *
6172 * @ac: Audio client handle
6173 * @cfg: aac config
6174 *
6175 * Returns 0 on success or error on failure
6176 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306177int q6asm_media_format_block_aac(struct audio_client *ac,
6178 struct asm_aac_cfg *cfg)
6179{
6180 return __q6asm_media_format_block_multi_aac(ac, cfg, ac->stream_id);
6181}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306182EXPORT_SYMBOL(q6asm_media_format_block_aac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306183
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306184/**
6185 * q6asm_stream_media_format_block_aac -
6186 * command to set mediafmt block for aac on ASM stream
6187 *
6188 * @ac: Audio client handle
6189 * @cfg: aac config
6190 * @stream_id: stream ID info
6191 *
6192 * Returns 0 on success or error on failure
6193 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306194int q6asm_stream_media_format_block_aac(struct audio_client *ac,
6195 struct asm_aac_cfg *cfg, int stream_id)
6196{
6197 return __q6asm_media_format_block_multi_aac(ac, cfg, stream_id);
6198}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306199EXPORT_SYMBOL(q6asm_stream_media_format_block_aac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306200
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306201/**
6202 * q6asm_media_format_block_wma -
6203 * command to set mediafmt block for wma on ASM stream
6204 *
6205 * @ac: Audio client handle
6206 * @cfg: wma config
6207 * @stream_id: stream ID info
6208 *
6209 * Returns 0 on success or error on failure
6210 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306211int q6asm_media_format_block_wma(struct audio_client *ac,
6212 void *cfg, int stream_id)
6213{
6214 struct asm_wmastdv9_fmt_blk_v2 fmt;
6215 struct asm_wma_cfg *wma_cfg = (struct asm_wma_cfg *)cfg;
6216 int rc = 0;
6217
6218 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",
6219 ac->session, wma_cfg->format_tag, wma_cfg->sample_rate,
6220 wma_cfg->ch_cfg, wma_cfg->avg_bytes_per_sec,
6221 wma_cfg->block_align, wma_cfg->valid_bits_per_sample,
6222 wma_cfg->ch_mask, wma_cfg->encode_opt);
6223
6224 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6225 atomic_set(&ac->cmd_state, -1);
6226
6227 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6228 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6229 sizeof(fmt.fmtblk);
6230 fmt.fmtag = wma_cfg->format_tag;
6231 fmt.num_channels = wma_cfg->ch_cfg;
6232 fmt.sample_rate = wma_cfg->sample_rate;
6233 fmt.avg_bytes_per_sec = wma_cfg->avg_bytes_per_sec;
6234 fmt.blk_align = wma_cfg->block_align;
6235 fmt.bits_per_sample =
6236 wma_cfg->valid_bits_per_sample;
6237 fmt.channel_mask = wma_cfg->ch_mask;
6238 fmt.enc_options = wma_cfg->encode_opt;
6239
6240 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6241 if (rc < 0) {
6242 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
6243 rc = -EINVAL;
6244 goto fail_cmd;
6245 }
6246 rc = wait_event_timeout(ac->cmd_wait,
6247 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6248 if (!rc) {
6249 pr_err("%s: timeout. waited for FORMAT_UPDATE\n", __func__);
6250 rc = -ETIMEDOUT;
6251 goto fail_cmd;
6252 }
6253 if (atomic_read(&ac->cmd_state) > 0) {
6254 pr_err("%s: DSP returned error[%s]\n",
6255 __func__, adsp_err_get_err_str(
6256 atomic_read(&ac->cmd_state)));
6257 rc = adsp_err_get_lnx_err_code(
6258 atomic_read(&ac->cmd_state));
6259 goto fail_cmd;
6260 }
6261 return 0;
6262fail_cmd:
6263 return rc;
6264}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306265EXPORT_SYMBOL(q6asm_media_format_block_wma);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306266
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306267/**
6268 * q6asm_media_format_block_wmapro -
6269 * command to set mediafmt block for wmapro on ASM stream
6270 *
6271 * @ac: Audio client handle
6272 * @cfg: wmapro config
6273 * @stream_id: stream ID info
6274 *
6275 * Returns 0 on success or error on failure
6276 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306277int q6asm_media_format_block_wmapro(struct audio_client *ac,
6278 void *cfg, int stream_id)
6279{
6280 struct asm_wmaprov10_fmt_blk_v2 fmt;
6281 struct asm_wmapro_cfg *wmapro_cfg = (struct asm_wmapro_cfg *)cfg;
6282 int rc = 0;
6283
6284 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",
6285 __func__,
6286 ac->session, wmapro_cfg->format_tag, wmapro_cfg->sample_rate,
6287 wmapro_cfg->ch_cfg, wmapro_cfg->avg_bytes_per_sec,
6288 wmapro_cfg->block_align, wmapro_cfg->valid_bits_per_sample,
6289 wmapro_cfg->ch_mask, wmapro_cfg->encode_opt,
6290 wmapro_cfg->adv_encode_opt, wmapro_cfg->adv_encode_opt2);
6291
6292 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6293 atomic_set(&ac->cmd_state, -1);
6294
6295 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6296 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6297 sizeof(fmt.fmtblk);
6298
6299 fmt.fmtag = wmapro_cfg->format_tag;
6300 fmt.num_channels = wmapro_cfg->ch_cfg;
6301 fmt.sample_rate = wmapro_cfg->sample_rate;
6302 fmt.avg_bytes_per_sec =
6303 wmapro_cfg->avg_bytes_per_sec;
6304 fmt.blk_align = wmapro_cfg->block_align;
6305 fmt.bits_per_sample = wmapro_cfg->valid_bits_per_sample;
6306 fmt.channel_mask = wmapro_cfg->ch_mask;
6307 fmt.enc_options = wmapro_cfg->encode_opt;
6308 fmt.usAdvancedEncodeOpt = wmapro_cfg->adv_encode_opt;
6309 fmt.advanced_enc_options2 = wmapro_cfg->adv_encode_opt2;
6310
6311 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6312 if (rc < 0) {
6313 pr_err("%s: Comamnd open failed %d\n", __func__, rc);
6314 rc = -EINVAL;
6315 goto fail_cmd;
6316 }
6317 rc = wait_event_timeout(ac->cmd_wait,
6318 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6319 if (!rc) {
6320 pr_err("%s: timeout. waited for FORMAT_UPDATE\n", __func__);
6321 rc = -ETIMEDOUT;
6322 goto fail_cmd;
6323 }
6324 if (atomic_read(&ac->cmd_state) > 0) {
6325 pr_err("%s: DSP returned error[%s]\n",
6326 __func__, adsp_err_get_err_str(
6327 atomic_read(&ac->cmd_state)));
6328 rc = adsp_err_get_lnx_err_code(
6329 atomic_read(&ac->cmd_state));
6330 goto fail_cmd;
6331 }
6332 return 0;
6333fail_cmd:
6334 return rc;
6335}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306336EXPORT_SYMBOL(q6asm_media_format_block_wmapro);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306337
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306338/**
6339 * q6asm_media_format_block_amrwbplus -
6340 * command to set mediafmt block for amrwbplus on ASM stream
6341 *
6342 * @ac: Audio client handle
6343 * @cfg: amrwbplus config
6344 * @stream_id: stream ID info
6345 *
6346 * Returns 0 on success or error on failure
6347 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306348int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
6349 struct asm_amrwbplus_cfg *cfg)
6350{
6351 struct asm_amrwbplus_fmt_blk_v2 fmt;
6352 int rc = 0;
6353
6354 pr_debug("%s: session[%d]band-mode[%d]frame-fmt[%d]ch[%d]\n",
6355 __func__,
6356 ac->session,
6357 cfg->amr_band_mode,
6358 cfg->amr_frame_fmt,
6359 cfg->num_channels);
6360
6361 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
6362 atomic_set(&ac->cmd_state, -1);
6363
6364 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6365 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6366 sizeof(fmt.fmtblk);
6367 fmt.amr_frame_fmt = cfg->amr_frame_fmt;
6368
6369 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6370 if (rc < 0) {
6371 pr_err("%s: Comamnd media format update failed.. %d\n",
6372 __func__, rc);
6373 rc = -EINVAL;
6374 goto fail_cmd;
6375 }
6376 rc = wait_event_timeout(ac->cmd_wait,
6377 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6378 if (!rc) {
6379 pr_err("%s: timeout. waited for FORMAT_UPDATE\n", __func__);
6380 rc = -ETIMEDOUT;
6381 goto fail_cmd;
6382 }
6383 if (atomic_read(&ac->cmd_state) > 0) {
6384 pr_err("%s: DSP returned error[%s]\n",
6385 __func__, adsp_err_get_err_str(
6386 atomic_read(&ac->cmd_state)));
6387 rc = adsp_err_get_lnx_err_code(
6388 atomic_read(&ac->cmd_state));
6389 goto fail_cmd;
6390 }
6391 return 0;
6392fail_cmd:
6393 return rc;
6394}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306395EXPORT_SYMBOL(q6asm_media_format_block_amrwbplus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306396
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306397/**
6398 * q6asm_stream_media_format_block_flac -
6399 * command to set mediafmt block for flac on ASM stream
6400 *
6401 * @ac: Audio client handle
6402 * @cfg: FLAC config
6403 * @stream_id: stream ID info
6404 *
6405 * Returns 0 on success or error on failure
6406 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306407int q6asm_stream_media_format_block_flac(struct audio_client *ac,
6408 struct asm_flac_cfg *cfg, int stream_id)
6409{
6410 struct asm_flac_fmt_blk_v2 fmt;
6411 int rc = 0;
6412
6413 pr_debug("%s :session[%d] rate[%d] ch[%d] size[%d] stream_id[%d]\n",
6414 __func__, ac->session, cfg->sample_rate, cfg->ch_cfg,
6415 cfg->sample_size, stream_id);
6416
6417 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6418 atomic_set(&ac->cmd_state, -1);
6419
6420 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6421 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6422 sizeof(fmt.fmtblk);
6423
6424 fmt.is_stream_info_present = cfg->stream_info_present;
6425 fmt.num_channels = cfg->ch_cfg;
6426 fmt.min_blk_size = cfg->min_blk_size;
6427 fmt.max_blk_size = cfg->max_blk_size;
6428 fmt.sample_rate = cfg->sample_rate;
6429 fmt.min_frame_size = cfg->min_frame_size;
6430 fmt.max_frame_size = cfg->max_frame_size;
6431 fmt.sample_size = cfg->sample_size;
6432
6433 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6434 if (rc < 0) {
6435 pr_err("%s :Comamnd media format update failed %d\n",
6436 __func__, rc);
6437 goto fail_cmd;
6438 }
6439 rc = wait_event_timeout(ac->cmd_wait,
6440 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6441 if (!rc) {
6442 pr_err("%s :timeout. waited for FORMAT_UPDATE\n", __func__);
6443 rc = -ETIMEDOUT;
6444 goto fail_cmd;
6445 }
6446
6447 if (atomic_read(&ac->cmd_state) > 0) {
6448 pr_err("%s: DSP returned error[%s]\n",
6449 __func__, adsp_err_get_err_str(
6450 atomic_read(&ac->cmd_state)));
6451 rc = adsp_err_get_lnx_err_code(
6452 atomic_read(&ac->cmd_state));
6453 goto fail_cmd;
6454 }
6455 return 0;
6456fail_cmd:
6457 return rc;
6458}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306459EXPORT_SYMBOL(q6asm_stream_media_format_block_flac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306460
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306461/**
6462 * q6asm_media_format_block_alac -
6463 * command to set mediafmt block for alac on ASM stream
6464 *
6465 * @ac: Audio client handle
6466 * @cfg: ALAC config
6467 * @stream_id: stream ID info
6468 *
6469 * Returns 0 on success or error on failure
6470 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306471int q6asm_media_format_block_alac(struct audio_client *ac,
6472 struct asm_alac_cfg *cfg, int stream_id)
6473{
6474 struct asm_alac_fmt_blk_v2 fmt;
6475 int rc = 0;
6476
6477 pr_debug("%s :session[%d]rate[%d]ch[%d]\n", __func__,
6478 ac->session, cfg->sample_rate, cfg->num_channels);
6479
6480 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6481 atomic_set(&ac->cmd_state, -1);
6482
6483 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6484 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6485 sizeof(fmt.fmtblk);
6486
6487 fmt.frame_length = cfg->frame_length;
6488 fmt.compatible_version = cfg->compatible_version;
6489 fmt.bit_depth = cfg->bit_depth;
6490 fmt.pb = cfg->pb;
6491 fmt.mb = cfg->mb;
6492 fmt.kb = cfg->kb;
6493 fmt.num_channels = cfg->num_channels;
6494 fmt.max_run = cfg->max_run;
6495 fmt.max_frame_bytes = cfg->max_frame_bytes;
6496 fmt.avg_bit_rate = cfg->avg_bit_rate;
6497 fmt.sample_rate = cfg->sample_rate;
6498 fmt.channel_layout_tag = cfg->channel_layout_tag;
6499
6500 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6501 if (rc < 0) {
6502 pr_err("%s :Comamnd media format update failed %d\n",
6503 __func__, rc);
6504 goto fail_cmd;
6505 }
6506 rc = wait_event_timeout(ac->cmd_wait,
6507 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6508 if (!rc) {
6509 pr_err("%s :timeout. waited for FORMAT_UPDATE\n", __func__);
6510 rc = -ETIMEDOUT;
6511 goto fail_cmd;
6512 }
6513
6514 if (atomic_read(&ac->cmd_state) > 0) {
6515 pr_err("%s: DSP returned error[%s]\n",
6516 __func__, adsp_err_get_err_str(
6517 atomic_read(&ac->cmd_state)));
6518 rc = adsp_err_get_lnx_err_code(
6519 atomic_read(&ac->cmd_state));
6520 goto fail_cmd;
6521 }
6522 return 0;
6523fail_cmd:
6524 return rc;
6525}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306526EXPORT_SYMBOL(q6asm_media_format_block_alac);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306527
6528/*
6529 * q6asm_media_format_block_g711 - sends g711 decoder configuration
6530 * parameters
6531 * @ac: Client session handle
6532 * @cfg: Audio stream manager configuration parameters
6533 * @stream_id: Stream id
6534 */
6535int q6asm_media_format_block_g711(struct audio_client *ac,
6536 struct asm_g711_dec_cfg *cfg, int stream_id)
6537{
6538 struct asm_g711_dec_fmt_blk_v2 fmt;
6539 int rc = 0;
6540
6541 if (!ac) {
6542 pr_err("%s: audio client is null\n", __func__);
6543 return -EINVAL;
6544 }
6545 if (!cfg) {
6546 pr_err("%s: Invalid ASM config\n", __func__);
6547 return -EINVAL;
6548 }
6549
6550 if (stream_id <= 0) {
6551 pr_err("%s: Invalid stream id\n", __func__);
6552 return -EINVAL;
6553 }
6554
6555 pr_debug("%s :session[%d]rate[%d]\n", __func__,
6556 ac->session, cfg->sample_rate);
6557
6558 memset(&fmt, 0, sizeof(struct asm_g711_dec_fmt_blk_v2));
6559
6560 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6561 atomic_set(&ac->cmd_state, -1);
6562
6563 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6564 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6565 sizeof(fmt.fmtblk);
6566
6567 fmt.sample_rate = cfg->sample_rate;
6568
6569 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6570 if (rc < 0) {
6571 pr_err("%s :Command media format update failed %d\n",
6572 __func__, rc);
6573 goto fail_cmd;
6574 }
6575 rc = wait_event_timeout(ac->cmd_wait,
6576 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6577 if (!rc) {
6578 pr_err("%s :timeout. waited for FORMAT_UPDATE\n", __func__);
6579 rc = -ETIMEDOUT;
6580 goto fail_cmd;
6581 }
6582
6583 if (atomic_read(&ac->cmd_state) > 0) {
6584 pr_err("%s: DSP returned error[%s]\n",
6585 __func__, adsp_err_get_err_str(
6586 atomic_read(&ac->cmd_state)));
6587 rc = adsp_err_get_lnx_err_code(
6588 atomic_read(&ac->cmd_state));
6589 goto fail_cmd;
6590 }
6591 return 0;
6592fail_cmd:
6593 return rc;
6594}
6595EXPORT_SYMBOL(q6asm_media_format_block_g711);
6596
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306597/**
6598 * q6asm_stream_media_format_block_vorbis -
6599 * command to set mediafmt block for vorbis on ASM stream
6600 *
6601 * @ac: Audio client handle
6602 * @cfg: vorbis config
6603 * @stream_id: stream ID info
6604 *
6605 * Returns 0 on success or error on failure
6606 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306607int q6asm_stream_media_format_block_vorbis(struct audio_client *ac,
6608 struct asm_vorbis_cfg *cfg, int stream_id)
6609{
6610 struct asm_vorbis_fmt_blk_v2 fmt;
6611 int rc = 0;
6612
6613 pr_debug("%s :session[%d] bit_stream_fmt[%d] stream_id[%d]\n",
6614 __func__, ac->session, cfg->bit_stream_fmt, stream_id);
6615
6616 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6617 atomic_set(&ac->cmd_state, -1);
6618
6619 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6620 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6621 sizeof(fmt.fmtblk);
6622
6623 fmt.bit_stream_fmt = cfg->bit_stream_fmt;
6624
6625 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6626 if (rc < 0) {
6627 pr_err("%s :Comamnd media format update failed %d\n",
6628 __func__, rc);
6629 goto fail_cmd;
6630 }
6631 rc = wait_event_timeout(ac->cmd_wait,
6632 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6633 if (!rc) {
6634 pr_err("%s :timeout. waited for FORMAT_UPDATE\n", __func__);
6635 rc = -ETIMEDOUT;
6636 goto fail_cmd;
6637 }
6638
6639 if (atomic_read(&ac->cmd_state) > 0) {
6640 pr_err("%s: DSP returned error[%s]\n",
6641 __func__, adsp_err_get_err_str(
6642 atomic_read(&ac->cmd_state)));
6643 rc = adsp_err_get_lnx_err_code(
6644 atomic_read(&ac->cmd_state));
6645 goto fail_cmd;
6646 }
6647 return 0;
6648fail_cmd:
6649 return rc;
6650}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306651EXPORT_SYMBOL(q6asm_stream_media_format_block_vorbis);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306652
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306653/**
6654 * q6asm_media_format_block_ape -
6655 * command to set mediafmt block for APE on ASM stream
6656 *
6657 * @ac: Audio client handle
6658 * @cfg: APE config
6659 * @stream_id: stream ID info
6660 *
6661 * Returns 0 on success or error on failure
6662 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306663int q6asm_media_format_block_ape(struct audio_client *ac,
6664 struct asm_ape_cfg *cfg, int stream_id)
6665{
6666 struct asm_ape_fmt_blk_v2 fmt;
6667 int rc = 0;
6668
6669 pr_debug("%s :session[%d]rate[%d]ch[%d]\n", __func__,
6670 ac->session, cfg->sample_rate, cfg->num_channels);
6671
6672 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6673 atomic_set(&ac->cmd_state, -1);
6674
6675 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6676 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6677 sizeof(fmt.fmtblk);
6678
6679 fmt.compatible_version = cfg->compatible_version;
6680 fmt.compression_level = cfg->compression_level;
6681 fmt.format_flags = cfg->format_flags;
6682 fmt.blocks_per_frame = cfg->blocks_per_frame;
6683 fmt.final_frame_blocks = cfg->final_frame_blocks;
6684 fmt.total_frames = cfg->total_frames;
6685 fmt.bits_per_sample = cfg->bits_per_sample;
6686 fmt.num_channels = cfg->num_channels;
6687 fmt.sample_rate = cfg->sample_rate;
6688 fmt.seek_table_present = cfg->seek_table_present;
6689
6690 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6691 if (rc < 0) {
6692 pr_err("%s :Comamnd media format update failed %d\n",
6693 __func__, rc);
6694 goto fail_cmd;
6695 }
6696 rc = wait_event_timeout(ac->cmd_wait,
6697 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6698 if (!rc) {
6699 pr_err("%s :timeout. waited for FORMAT_UPDATE\n", __func__);
6700 rc = -ETIMEDOUT;
6701 goto fail_cmd;
6702 }
6703
6704 if (atomic_read(&ac->cmd_state) > 0) {
6705 pr_err("%s: DSP returned error[%s]\n",
6706 __func__, adsp_err_get_err_str(
6707 atomic_read(&ac->cmd_state)));
6708 rc = adsp_err_get_lnx_err_code(
6709 atomic_read(&ac->cmd_state));
6710 goto fail_cmd;
6711 }
6712 return 0;
6713fail_cmd:
6714 return rc;
6715}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306716EXPORT_SYMBOL(q6asm_media_format_block_ape);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306717
6718/*
6719 * q6asm_media_format_block_dsd- Sends DSD Decoder
6720 * configuration parameters
6721 *
6722 * @ac: Client session handle
6723 * @cfg: DSD Media Format Configuration.
6724 * @stream_id: stream id of stream to be associated with this session
6725 *
6726 * Return 0 on success or negative error code on failure
6727 */
6728int q6asm_media_format_block_dsd(struct audio_client *ac,
6729 struct asm_dsd_cfg *cfg, int stream_id)
6730{
6731 struct asm_dsd_fmt_blk_v2 fmt;
6732 int rc;
6733
6734 pr_debug("%s: session[%d] data_rate[%d] ch[%d]\n", __func__,
6735 ac->session, cfg->dsd_data_rate, cfg->num_channels);
6736
6737 memset(&fmt, 0, sizeof(fmt));
6738 q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
6739
6740 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6741 fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
6742 sizeof(fmt.fmtblk);
6743
6744 fmt.num_version = cfg->num_version;
6745 fmt.is_bitwise_big_endian = cfg->is_bitwise_big_endian;
6746 fmt.dsd_channel_block_size = cfg->dsd_channel_block_size;
6747 fmt.num_channels = cfg->num_channels;
6748 fmt.dsd_data_rate = cfg->dsd_data_rate;
6749 atomic_set(&ac->cmd_state, -1);
6750 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
6751 if (rc < 0) {
6752 pr_err("%s: Command DSD media format update failed, err: %d\n",
6753 __func__, rc);
6754 goto done;
6755 }
6756 rc = wait_event_timeout(ac->cmd_wait,
6757 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6758 if (!rc) {
6759 pr_err("%s: timeout. waited for DSD FORMAT_UPDATE\n", __func__);
6760 rc = -ETIMEDOUT;
6761 goto done;
6762 }
6763
6764 if (atomic_read(&ac->cmd_state) > 0) {
6765 pr_err("%s: DSP returned error[%s]\n",
6766 __func__, adsp_err_get_err_str(
6767 atomic_read(&ac->cmd_state)));
6768 rc = adsp_err_get_lnx_err_code(
6769 atomic_read(&ac->cmd_state));
6770 goto done;
6771 }
6772 return 0;
6773done:
6774 return rc;
6775}
6776EXPORT_SYMBOL(q6asm_media_format_block_dsd);
6777
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306778/**
6779 * q6asm_stream_media_format_block_aptx_dec -
6780 * command to set mediafmt block for APTX dec on ASM stream
6781 *
6782 * @ac: Audio client handle
6783 * @srate: sample rate
6784 * @stream_id: stream ID info
6785 *
6786 * Returns 0 on success or error on failure
6787 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306788int q6asm_stream_media_format_block_aptx_dec(struct audio_client *ac,
6789 uint32_t srate, int stream_id)
6790{
6791 struct asm_aptx_dec_fmt_blk_v2 aptx_fmt;
6792 int rc = 0;
6793
6794 if (!ac->session) {
6795 pr_err("%s: ac session invalid\n", __func__);
6796 rc = -EINVAL;
6797 goto fail_cmd;
6798 }
6799 pr_debug("%s :session[%d] rate[%d] stream_id[%d]\n",
6800 __func__, ac->session, srate, stream_id);
6801
6802 q6asm_stream_add_hdr(ac, &aptx_fmt.hdr, sizeof(aptx_fmt), TRUE,
6803 stream_id);
6804 atomic_set(&ac->cmd_state, -1);
6805
6806 aptx_fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
6807 aptx_fmt.fmtblk.fmt_blk_size = sizeof(aptx_fmt) - sizeof(aptx_fmt.hdr) -
6808 sizeof(aptx_fmt.fmtblk);
6809
6810 aptx_fmt.sample_rate = srate;
6811
6812 rc = apr_send_pkt(ac->apr, (uint32_t *) &aptx_fmt);
6813 if (rc < 0) {
6814 pr_err("%s :Comamnd media format update failed %d\n",
6815 __func__, rc);
6816 goto fail_cmd;
6817 }
6818 rc = wait_event_timeout(ac->cmd_wait,
6819 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6820 if (!rc) {
6821 pr_err("%s :timeout. waited for FORMAT_UPDATE\n", __func__);
6822 rc = -ETIMEDOUT;
6823 goto fail_cmd;
6824 }
6825
6826 if (atomic_read(&ac->cmd_state) > 0) {
6827 pr_err("%s: DSP returned error[%s]\n",
6828 __func__, adsp_err_get_err_str(
6829 atomic_read(&ac->cmd_state)));
6830 rc = adsp_err_get_lnx_err_code(
6831 atomic_read(&ac->cmd_state));
6832 goto fail_cmd;
6833 }
6834 rc = 0;
6835fail_cmd:
6836 return rc;
6837}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306838EXPORT_SYMBOL(q6asm_stream_media_format_block_aptx_dec);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306839
6840static int __q6asm_ds1_set_endp_params(struct audio_client *ac, int param_id,
6841 int param_value, int stream_id)
6842{
6843 struct asm_dec_ddp_endp_param_v2 ddp_cfg;
6844 int rc = 0;
6845
6846 pr_debug("%s: session[%d] stream[%d],param_id[%d]param_value[%d]",
6847 __func__, ac->session, stream_id, param_id, param_value);
6848
6849 q6asm_stream_add_hdr(ac, &ddp_cfg.hdr, sizeof(ddp_cfg), TRUE,
6850 stream_id);
6851 atomic_set(&ac->cmd_state, -1);
6852 /*
6853 * Updated the token field with stream/session for compressed playback
6854 * Platform driver must know the stream with which the command is
6855 * associated
6856 */
6857 if (ac->io_mode & COMPRESSED_STREAM_IO)
6858 q6asm_update_token(&ddp_cfg.hdr.token,
6859 ac->session,
6860 stream_id,
6861 0, /* Buffer index is NA */
6862 0, /* Direction flag is NA */
6863 WAIT_CMD);
6864 ddp_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
6865 ddp_cfg.encdec.param_id = param_id;
6866 ddp_cfg.encdec.param_size = sizeof(struct asm_dec_ddp_endp_param_v2) -
6867 (sizeof(struct apr_hdr) +
6868 sizeof(struct asm_stream_cmd_set_encdec_param));
6869 ddp_cfg.endp_param_value = param_value;
6870 rc = apr_send_pkt(ac->apr, (uint32_t *) &ddp_cfg);
6871 if (rc < 0) {
6872 pr_err("%s: Command opcode[0x%x] failed %d\n",
6873 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, rc);
6874 goto fail_cmd;
6875 }
6876 rc = wait_event_timeout(ac->cmd_wait,
6877 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
6878 if (!rc) {
6879 pr_err("%s: timeout opcode[0x%x]\n", __func__,
6880 ddp_cfg.hdr.opcode);
6881 rc = -ETIMEDOUT;
6882 goto fail_cmd;
6883 }
6884 if (atomic_read(&ac->cmd_state) > 0) {
6885 pr_err("%s: DSP returned error[%s]\n",
6886 __func__, adsp_err_get_err_str(
6887 atomic_read(&ac->cmd_state)));
6888 rc = adsp_err_get_lnx_err_code(
6889 atomic_read(&ac->cmd_state));
6890 goto fail_cmd;
6891 }
6892 return 0;
6893fail_cmd:
6894 return rc;
6895}
6896
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306897/**
6898 * q6asm_ds1_set_endp_params -
6899 * command to set DS1 params for ASM
6900 *
6901 * @ac: Audio client handle
6902 * @param_id: param id
6903 * @param_value: value of param
6904 *
6905 * Returns 0 on success or error on failure
6906 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306907int q6asm_ds1_set_endp_params(struct audio_client *ac,
6908 int param_id, int param_value)
6909{
6910 return __q6asm_ds1_set_endp_params(ac, param_id, param_value,
6911 ac->stream_id);
6912}
6913
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306914/**
6915 * q6asm_ds1_set_stream_endp_params -
6916 * command to set DS1 params for ASM stream
6917 *
6918 * @ac: Audio client handle
6919 * @param_id: param id
6920 * @param_value: value of param
6921 * @stream_id: stream ID info
6922 *
6923 * Returns 0 on success or error on failure
6924 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306925int q6asm_ds1_set_stream_endp_params(struct audio_client *ac,
6926 int param_id, int param_value,
6927 int stream_id)
6928{
6929 return __q6asm_ds1_set_endp_params(ac, param_id, param_value,
6930 stream_id);
6931}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306932EXPORT_SYMBOL(q6asm_ds1_set_stream_endp_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306933
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306934/**
6935 * q6asm_memory_map -
6936 * command to send memory map for ASM
6937 *
6938 * @ac: Audio client handle
6939 * @buf_add: buffer address to map
6940 * @dir: RX or TX session
6941 * @bufsz: size of each buffer
6942 * @bufcnt: buffer count
6943 *
6944 * Returns 0 on success or error on failure
6945 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306946int q6asm_memory_map(struct audio_client *ac, phys_addr_t buf_add, int dir,
6947 uint32_t bufsz, uint32_t bufcnt)
6948{
6949 struct avs_cmd_shared_mem_map_regions *mmap_regions = NULL;
6950 struct avs_shared_map_region_payload *mregions = NULL;
6951 struct audio_port_data *port = NULL;
6952 void *mmap_region_cmd = NULL;
6953 void *payload = NULL;
6954 struct asm_buffer_node *buffer_node = NULL;
6955 int rc = 0;
6956 int cmd_size = 0;
6957
6958 if (!ac) {
6959 pr_err("%s: APR handle NULL\n", __func__);
6960 return -EINVAL;
6961 }
6962 if (ac->mmap_apr == NULL) {
6963 pr_err("%s: mmap APR handle NULL\n", __func__);
6964 return -EINVAL;
6965 }
6966 pr_debug("%s: Session[%d]\n", __func__, ac->session);
6967
6968 buffer_node = kmalloc(sizeof(struct asm_buffer_node), GFP_KERNEL);
6969 if (!buffer_node)
6970 return -ENOMEM;
6971
6972 cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions)
6973 + sizeof(struct avs_shared_map_region_payload) * bufcnt;
6974
6975 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
6976 if (mmap_region_cmd == NULL) {
6977 rc = -EINVAL;
6978 kfree(buffer_node);
6979 return rc;
6980 }
6981 mmap_regions = (struct avs_cmd_shared_mem_map_regions *)
6982 mmap_region_cmd;
6983 q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size, dir);
6984 atomic_set(&ac->mem_state, -1);
6985 mmap_regions->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS;
6986 mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
6987 mmap_regions->num_regions = bufcnt & 0x00ff;
6988 mmap_regions->property_flag = 0x00;
6989 payload = ((u8 *) mmap_region_cmd +
6990 sizeof(struct avs_cmd_shared_mem_map_regions));
6991 mregions = (struct avs_shared_map_region_payload *)payload;
6992
6993 ac->port[dir].tmp_hdl = 0;
6994 port = &ac->port[dir];
6995 pr_debug("%s: buf_add 0x%pK, bufsz: %d\n", __func__,
6996 &buf_add, bufsz);
6997 mregions->shm_addr_lsw = lower_32_bits(buf_add);
6998 mregions->shm_addr_msw = msm_audio_populate_upper_32_bits(buf_add);
6999 mregions->mem_size_bytes = bufsz;
7000 ++mregions;
7001
7002 rc = apr_send_pkt(ac->mmap_apr, (uint32_t *) mmap_region_cmd);
7003 if (rc < 0) {
7004 pr_err("%s: mmap op[0x%x]rc[%d]\n", __func__,
7005 mmap_regions->hdr.opcode, rc);
7006 rc = -EINVAL;
7007 kfree(buffer_node);
7008 goto fail_cmd;
7009 }
7010
7011 rc = wait_event_timeout(ac->mem_wait,
7012 (atomic_read(&ac->mem_state) >= 0 &&
7013 ac->port[dir].tmp_hdl), 5*HZ);
7014 if (!rc) {
7015 pr_err("%s: timeout. waited for memory_map\n", __func__);
7016 rc = -ETIMEDOUT;
7017 kfree(buffer_node);
7018 goto fail_cmd;
7019 }
7020 if (atomic_read(&ac->mem_state) > 0) {
7021 pr_err("%s: DSP returned error[%s] for memory_map\n",
7022 __func__, adsp_err_get_err_str(
7023 atomic_read(&ac->mem_state)));
7024 rc = adsp_err_get_lnx_err_code(
7025 atomic_read(&ac->mem_state));
7026 kfree(buffer_node);
7027 goto fail_cmd;
7028 }
7029 buffer_node->buf_phys_addr = buf_add;
7030 buffer_node->mmap_hdl = ac->port[dir].tmp_hdl;
7031 list_add_tail(&buffer_node->list, &ac->port[dir].mem_map_handle);
7032 ac->port[dir].tmp_hdl = 0;
7033 rc = 0;
7034
7035fail_cmd:
7036 kfree(mmap_region_cmd);
7037 return rc;
7038}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307039EXPORT_SYMBOL(q6asm_memory_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307040
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307041/**
7042 * q6asm_memory_unmap -
7043 * command to send memory unmap for ASM
7044 *
7045 * @ac: Audio client handle
7046 * @buf_add: buffer address to unmap
7047 * @dir: RX or TX session
7048 *
7049 * Returns 0 on success or error on failure
7050 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307051int q6asm_memory_unmap(struct audio_client *ac, phys_addr_t buf_add, int dir)
7052{
7053 struct avs_cmd_shared_mem_unmap_regions mem_unmap;
7054 struct asm_buffer_node *buf_node = NULL;
7055 struct list_head *ptr, *next;
7056
7057 int rc = 0;
7058
7059 if (!ac) {
7060 pr_err("%s: APR handle NULL\n", __func__);
7061 return -EINVAL;
7062 }
7063 if (this_mmap.apr == NULL) {
7064 pr_err("%s: APR handle NULL\n", __func__);
7065 return -EINVAL;
7066 }
7067 pr_debug("%s: Session[%d]\n", __func__, ac->session);
7068
7069 q6asm_add_mmaphdr(ac, &mem_unmap.hdr,
7070 sizeof(struct avs_cmd_shared_mem_unmap_regions),
7071 dir);
7072 atomic_set(&ac->mem_state, -1);
7073 mem_unmap.hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS;
7074 mem_unmap.mem_map_handle = 0;
7075 list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
7076 buf_node = list_entry(ptr, struct asm_buffer_node,
7077 list);
7078 if (buf_node->buf_phys_addr == buf_add) {
7079 pr_debug("%s: Found the element\n", __func__);
7080 mem_unmap.mem_map_handle = buf_node->mmap_hdl;
7081 break;
7082 }
7083 }
7084 pr_debug("%s: mem_unmap-mem_map_handle: 0x%x\n",
7085 __func__, mem_unmap.mem_map_handle);
7086
7087 if (mem_unmap.mem_map_handle == 0) {
7088 pr_err("%s: Do not send null mem handle to DSP\n", __func__);
7089 rc = 0;
7090 goto fail_cmd;
7091 }
7092 rc = apr_send_pkt(ac->mmap_apr, (uint32_t *) &mem_unmap);
7093 if (rc < 0) {
7094 pr_err("%s: mem_unmap op[0x%x]rc[%d]\n", __func__,
7095 mem_unmap.hdr.opcode, rc);
7096 rc = -EINVAL;
7097 goto fail_cmd;
7098 }
7099
7100 rc = wait_event_timeout(ac->mem_wait,
7101 (atomic_read(&ac->mem_state) >= 0), 5 * HZ);
7102 if (!rc) {
7103 pr_err("%s: timeout. waited for memory_unmap of handle 0x%x\n",
7104 __func__, mem_unmap.mem_map_handle);
7105 rc = -ETIMEDOUT;
7106 goto fail_cmd;
7107 } else if (atomic_read(&ac->mem_state) > 0) {
7108 pr_err("%s DSP returned error [%s] map handle 0x%x\n",
7109 __func__, adsp_err_get_err_str(
7110 atomic_read(&ac->mem_state)),
7111 mem_unmap.mem_map_handle);
7112 rc = adsp_err_get_lnx_err_code(
7113 atomic_read(&ac->mem_state));
7114 goto fail_cmd;
7115 } else if (atomic_read(&ac->unmap_cb_success) == 0) {
7116 pr_err("%s: Error in mem unmap callback of handle 0x%x\n",
7117 __func__, mem_unmap.mem_map_handle);
7118 rc = -EINVAL;
7119 goto fail_cmd;
7120 }
7121
7122 rc = 0;
7123fail_cmd:
7124 list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
7125 buf_node = list_entry(ptr, struct asm_buffer_node,
7126 list);
7127 if (buf_node->buf_phys_addr == buf_add) {
7128 list_del(&buf_node->list);
7129 kfree(buf_node);
7130 break;
7131 }
7132 }
7133 return rc;
7134}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307135EXPORT_SYMBOL(q6asm_memory_unmap);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307136
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307137/**
7138 * q6asm_memory_map_regions -
7139 * command to send memory map regions for ASM
7140 *
7141 * @ac: Audio client handle
7142 * @dir: RX or TX session
7143 * @bufsz: size of each buffer
7144 * @bufcnt: buffer count
7145 * @is_contiguous: alloc contiguous mem or not
7146 *
7147 * Returns 0 on success or error on failure
7148 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307149static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
7150 uint32_t bufsz, uint32_t bufcnt,
7151 bool is_contiguous)
7152{
7153 struct avs_cmd_shared_mem_map_regions *mmap_regions = NULL;
7154 struct avs_shared_map_region_payload *mregions = NULL;
7155 struct audio_port_data *port = NULL;
7156 struct audio_buffer *ab = NULL;
7157 void *mmap_region_cmd = NULL;
7158 void *payload = NULL;
7159 struct asm_buffer_node *buffer_node = NULL;
7160 int rc = 0;
7161 int i = 0;
7162 uint32_t cmd_size = 0;
7163 uint32_t bufcnt_t;
7164 uint32_t bufsz_t;
7165
7166 if (!ac) {
7167 pr_err("%s: APR handle NULL\n", __func__);
7168 return -EINVAL;
7169 }
7170 if (ac->mmap_apr == NULL) {
7171 pr_err("%s: mmap APR handle NULL\n", __func__);
7172 return -EINVAL;
7173 }
7174 pr_debug("%s: Session[%d]\n", __func__, ac->session);
7175
7176 bufcnt_t = (is_contiguous) ? 1 : bufcnt;
7177 bufsz_t = (is_contiguous) ? (bufsz * bufcnt) : bufsz;
7178
7179 if (is_contiguous) {
7180 /* The size to memory map should be multiple of 4K bytes */
7181 bufsz_t = PAGE_ALIGN(bufsz_t);
7182 }
7183
7184 if (bufcnt_t > (UINT_MAX
7185 - sizeof(struct avs_cmd_shared_mem_map_regions))
7186 / sizeof(struct avs_shared_map_region_payload)) {
7187 pr_err("%s: Unsigned Integer Overflow. bufcnt_t = %u\n",
7188 __func__, bufcnt_t);
7189 return -EINVAL;
7190 }
7191
7192 cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions)
7193 + (sizeof(struct avs_shared_map_region_payload)
7194 * bufcnt_t);
7195
7196
7197 if (bufcnt > (UINT_MAX / sizeof(struct asm_buffer_node))) {
7198 pr_err("%s: Unsigned Integer Overflow. bufcnt = %u\n",
7199 __func__, bufcnt);
7200 return -EINVAL;
7201 }
7202
7203 buffer_node = kzalloc(sizeof(struct asm_buffer_node) * bufcnt,
7204 GFP_KERNEL);
7205 if (!buffer_node)
7206 return -ENOMEM;
7207
7208 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
7209 if (mmap_region_cmd == NULL) {
7210 rc = -EINVAL;
7211 kfree(buffer_node);
7212 return rc;
7213 }
7214 mmap_regions = (struct avs_cmd_shared_mem_map_regions *)
7215 mmap_region_cmd;
7216 q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size, dir);
7217 atomic_set(&ac->mem_state, -1);
7218 pr_debug("%s: mmap_region=0x%pK token=0x%x\n", __func__,
7219 mmap_regions, ((ac->session << 8) | dir));
7220
7221 mmap_regions->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS;
7222 mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
7223 mmap_regions->num_regions = bufcnt_t; /*bufcnt & 0x00ff; */
7224 mmap_regions->property_flag = 0x00;
7225 pr_debug("%s: map_regions->nregions = %d\n", __func__,
7226 mmap_regions->num_regions);
7227 payload = ((u8 *) mmap_region_cmd +
7228 sizeof(struct avs_cmd_shared_mem_map_regions));
7229 mregions = (struct avs_shared_map_region_payload *)payload;
7230
7231 ac->port[dir].tmp_hdl = 0;
7232 port = &ac->port[dir];
7233 for (i = 0; i < bufcnt_t; i++) {
7234 ab = &port->buf[i];
7235 mregions->shm_addr_lsw = lower_32_bits(ab->phys);
7236 mregions->shm_addr_msw =
7237 msm_audio_populate_upper_32_bits(ab->phys);
7238 mregions->mem_size_bytes = bufsz_t;
7239 ++mregions;
7240 }
7241
7242 rc = apr_send_pkt(ac->mmap_apr, (uint32_t *) mmap_region_cmd);
7243 if (rc < 0) {
7244 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
7245 mmap_regions->hdr.opcode, rc);
7246 rc = -EINVAL;
7247 kfree(buffer_node);
7248 goto fail_cmd;
7249 }
7250
7251 rc = wait_event_timeout(ac->mem_wait,
7252 (atomic_read(&ac->mem_state) >= 0)
7253 , 5*HZ);
7254 if (!rc) {
7255 pr_err("%s: timeout. waited for memory_map\n", __func__);
7256 rc = -ETIMEDOUT;
7257 kfree(buffer_node);
7258 goto fail_cmd;
7259 }
7260 if (atomic_read(&ac->mem_state) > 0) {
7261 pr_err("%s DSP returned error for memory_map [%s]\n",
7262 __func__, adsp_err_get_err_str(
7263 atomic_read(&ac->mem_state)));
7264 rc = adsp_err_get_lnx_err_code(
7265 atomic_read(&ac->mem_state));
7266 kfree(buffer_node);
7267 goto fail_cmd;
7268 }
7269 mutex_lock(&ac->cmd_lock);
7270
7271 for (i = 0; i < bufcnt; i++) {
7272 ab = &port->buf[i];
7273 buffer_node[i].buf_phys_addr = ab->phys;
7274 buffer_node[i].mmap_hdl = ac->port[dir].tmp_hdl;
7275 list_add_tail(&buffer_node[i].list,
7276 &ac->port[dir].mem_map_handle);
7277 pr_debug("%s: i=%d, bufadd[i] = 0x%pK, maphdl[i] = 0x%x\n",
7278 __func__, i, &buffer_node[i].buf_phys_addr,
7279 buffer_node[i].mmap_hdl);
7280 }
7281 ac->port[dir].tmp_hdl = 0;
7282 mutex_unlock(&ac->cmd_lock);
7283 rc = 0;
7284fail_cmd:
7285 kfree(mmap_region_cmd);
7286 return rc;
7287}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307288EXPORT_SYMBOL(q6asm_memory_map_regions);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307289
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307290/**
7291 * q6asm_memory_unmap_regions -
7292 * command to send memory unmap regions for ASM
7293 *
7294 * @ac: Audio client handle
7295 * @dir: RX or TX session
7296 *
7297 * Returns 0 on success or error on failure
7298 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307299static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir)
7300{
7301 struct avs_cmd_shared_mem_unmap_regions mem_unmap;
7302 struct audio_port_data *port = NULL;
7303 struct asm_buffer_node *buf_node = NULL;
7304 struct list_head *ptr, *next;
7305 phys_addr_t buf_add;
7306 int rc = 0;
7307 int cmd_size = 0;
7308
7309 if (!ac) {
7310 pr_err("%s: APR handle NULL\n", __func__);
7311 return -EINVAL;
7312 }
7313 if (ac->mmap_apr == NULL) {
7314 pr_err("%s: mmap APR handle NULL\n", __func__);
7315 return -EINVAL;
7316 }
7317 pr_debug("%s: Session[%d]\n", __func__, ac->session);
7318
7319 cmd_size = sizeof(struct avs_cmd_shared_mem_unmap_regions);
7320 q6asm_add_mmaphdr(ac, &mem_unmap.hdr, cmd_size, dir);
7321 atomic_set(&ac->mem_state, -1);
7322 port = &ac->port[dir];
7323 buf_add = port->buf->phys;
7324 mem_unmap.hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS;
7325 mem_unmap.mem_map_handle = 0;
7326 list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
7327 buf_node = list_entry(ptr, struct asm_buffer_node,
7328 list);
7329 if (buf_node->buf_phys_addr == buf_add) {
7330 pr_debug("%s: Found the element\n", __func__);
7331 mem_unmap.mem_map_handle = buf_node->mmap_hdl;
7332 break;
7333 }
7334 }
7335
7336 pr_debug("%s: mem_unmap-mem_map_handle: 0x%x\n",
7337 __func__, mem_unmap.mem_map_handle);
7338
7339 if (mem_unmap.mem_map_handle == 0) {
7340 pr_err("%s: Do not send null mem handle to DSP\n", __func__);
7341 rc = 0;
7342 goto fail_cmd;
7343 }
7344 rc = apr_send_pkt(ac->mmap_apr, (uint32_t *) &mem_unmap);
7345 if (rc < 0) {
7346 pr_err("mmap_regions op[0x%x]rc[%d]\n",
7347 mem_unmap.hdr.opcode, rc);
7348 goto fail_cmd;
7349 }
7350
7351 rc = wait_event_timeout(ac->mem_wait,
7352 (atomic_read(&ac->mem_state) >= 0), 5*HZ);
7353 if (!rc) {
7354 pr_err("%s: timeout. waited for memory_unmap of handle 0x%x\n",
7355 __func__, mem_unmap.mem_map_handle);
7356 rc = -ETIMEDOUT;
7357 goto fail_cmd;
7358 } else if (atomic_read(&ac->mem_state) > 0) {
7359 pr_err("%s: DSP returned error[%s]\n",
7360 __func__, adsp_err_get_err_str(
7361 atomic_read(&ac->mem_state)));
7362 rc = adsp_err_get_lnx_err_code(
7363 atomic_read(&ac->mem_state));
7364 goto fail_cmd;
7365 } else if (atomic_read(&ac->unmap_cb_success) == 0) {
7366 pr_err("%s: Error in mem unmap callback of handle 0x%x\n",
7367 __func__, mem_unmap.mem_map_handle);
7368 rc = -EINVAL;
7369 goto fail_cmd;
7370 }
7371 rc = 0;
7372
7373fail_cmd:
7374 list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
7375 buf_node = list_entry(ptr, struct asm_buffer_node,
7376 list);
7377 if (buf_node->buf_phys_addr == buf_add) {
7378 list_del(&buf_node->list);
7379 kfree(buf_node);
7380 break;
7381 }
7382 }
7383 return rc;
7384}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307385EXPORT_SYMBOL(q6asm_memory_unmap_regions);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307386
7387int q6asm_set_lrgain(struct audio_client *ac, int left_gain, int right_gain)
7388{
7389 struct asm_volume_ctrl_multichannel_gain multi_ch_gain;
7390 int sz = 0;
7391 int rc = 0;
7392
7393 if (ac == NULL) {
7394 pr_err("%s: APR handle NULL\n", __func__);
7395 rc = -EINVAL;
7396 goto fail_cmd;
7397 }
7398 if (ac->apr == NULL) {
7399 pr_err("%s: AC APR handle NULL\n", __func__);
7400 rc = -EINVAL;
7401 goto fail_cmd;
7402 }
7403
7404 memset(&multi_ch_gain, 0, sizeof(multi_ch_gain));
7405 sz = sizeof(struct asm_volume_ctrl_multichannel_gain);
7406 q6asm_add_hdr_async(ac, &multi_ch_gain.hdr, sz, TRUE);
7407 atomic_set(&ac->cmd_state_pp, -1);
7408 multi_ch_gain.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
7409 multi_ch_gain.param.data_payload_addr_lsw = 0;
7410 multi_ch_gain.param.data_payload_addr_msw = 0;
7411 multi_ch_gain.param.mem_map_handle = 0;
7412 multi_ch_gain.param.data_payload_size = sizeof(multi_ch_gain) -
7413 sizeof(multi_ch_gain.hdr) - sizeof(multi_ch_gain.param);
7414 multi_ch_gain.data.module_id = ASM_MODULE_ID_VOL_CTRL;
7415 multi_ch_gain.data.param_id = ASM_PARAM_ID_MULTICHANNEL_GAIN;
7416 multi_ch_gain.data.param_size = multi_ch_gain.param.data_payload_size -
7417 sizeof(multi_ch_gain.data);
7418 multi_ch_gain.data.reserved = 0;
7419 multi_ch_gain.gain_data[0].channeltype = PCM_CHANNEL_FL;
7420 multi_ch_gain.gain_data[0].gain = left_gain << 15;
7421 multi_ch_gain.gain_data[1].channeltype = PCM_CHANNEL_FR;
7422 multi_ch_gain.gain_data[1].gain = right_gain << 15;
7423 multi_ch_gain.num_channels = 2;
7424 rc = apr_send_pkt(ac->apr, (uint32_t *) &multi_ch_gain);
7425 if (rc < 0) {
7426 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
7427 __func__, multi_ch_gain.data.param_id, rc);
7428 rc = -EINVAL;
7429 goto fail_cmd;
7430 }
7431
7432 rc = wait_event_timeout(ac->cmd_wait,
7433 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
7434 if (!rc) {
7435 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
7436 multi_ch_gain.data.param_id);
7437 rc = -ETIMEDOUT;
7438 goto fail_cmd;
7439 }
7440 if (atomic_read(&ac->cmd_state_pp) > 0) {
7441 pr_err("%s: DSP returned error[%s] , set-params paramid[0x%x]\n",
7442 __func__, adsp_err_get_err_str(
7443 atomic_read(&ac->cmd_state_pp)),
7444 multi_ch_gain.data.param_id);
7445 rc = adsp_err_get_lnx_err_code(
7446 atomic_read(&ac->cmd_state_pp));
7447 goto fail_cmd;
7448 }
7449 rc = 0;
7450fail_cmd:
7451 return rc;
7452}
7453
7454/*
7455 * q6asm_set_multich_gain: set multiple channel gains on an ASM session
7456 * @ac: audio client handle
7457 * @channels: number of channels caller intends to set gains
7458 * @gains: list of gains of audio channels
7459 * @ch_map: list of channel mapping. Only valid if use_default is false
7460 * @use_default: flag to indicate whether to use default mapping
7461 */
7462int q6asm_set_multich_gain(struct audio_client *ac, uint32_t channels,
7463 uint32_t *gains, uint8_t *ch_map, bool use_default)
7464{
7465 struct asm_volume_ctrl_multichannel_gain multich_gain;
7466 int sz = 0;
7467 int rc = 0;
7468 int i;
7469 u8 default_chmap[VOLUME_CONTROL_MAX_CHANNELS];
7470
7471 if (ac == NULL) {
7472 pr_err("%s: ac is NULL\n", __func__);
7473 rc = -EINVAL;
7474 goto done;
7475 }
7476 if (ac->apr == NULL) {
7477 dev_err(ac->dev, "%s: AC APR handle NULL\n", __func__);
7478 rc = -EINVAL;
7479 goto done;
7480 }
7481 if (gains == NULL) {
7482 dev_err(ac->dev, "%s: gain_list is NULL\n", __func__);
7483 rc = -EINVAL;
7484 goto done;
7485 }
7486 if (channels > VOLUME_CONTROL_MAX_CHANNELS) {
7487 dev_err(ac->dev, "%s: Invalid channel count %d\n",
7488 __func__, channels);
7489 rc = -EINVAL;
7490 goto done;
7491 }
7492 if (!use_default && ch_map == NULL) {
7493 dev_err(ac->dev, "%s: NULL channel map\n", __func__);
7494 rc = -EINVAL;
7495 goto done;
7496 }
7497
7498 memset(&multich_gain, 0, sizeof(multich_gain));
7499 sz = sizeof(struct asm_volume_ctrl_multichannel_gain);
7500 q6asm_add_hdr_async(ac, &multich_gain.hdr, sz, TRUE);
7501 atomic_set(&ac->cmd_state_pp, -1);
7502 multich_gain.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
7503 multich_gain.param.data_payload_addr_lsw = 0;
7504 multich_gain.param.data_payload_addr_msw = 0;
7505 multich_gain.param.mem_map_handle = 0;
7506 multich_gain.param.data_payload_size = sizeof(multich_gain) -
7507 sizeof(multich_gain.hdr) - sizeof(multich_gain.param);
7508 multich_gain.data.module_id = ASM_MODULE_ID_VOL_CTRL;
7509 multich_gain.data.param_id = ASM_PARAM_ID_MULTICHANNEL_GAIN;
7510 multich_gain.data.param_size = multich_gain.param.data_payload_size -
7511 sizeof(multich_gain.data);
7512 multich_gain.data.reserved = 0;
7513
7514 if (use_default) {
7515 rc = q6asm_map_channels(default_chmap, channels, false);
7516 if (rc < 0)
7517 goto done;
7518 for (i = 0; i < channels; i++) {
7519 multich_gain.gain_data[i].channeltype =
7520 default_chmap[i];
7521 multich_gain.gain_data[i].gain = gains[i] << 15;
7522 }
7523 } else {
7524 for (i = 0; i < channels; i++) {
7525 multich_gain.gain_data[i].channeltype = ch_map[i];
7526 multich_gain.gain_data[i].gain = gains[i] << 15;
7527 }
7528 }
7529 multich_gain.num_channels = channels;
7530
7531 rc = apr_send_pkt(ac->apr, (uint32_t *) &multich_gain);
7532 if (rc < 0) {
7533 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
7534 __func__, multich_gain.data.param_id, rc);
7535 goto done;
7536 }
7537
7538 rc = wait_event_timeout(ac->cmd_wait,
7539 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
7540 if (!rc) {
7541 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
7542 multich_gain.data.param_id);
7543 rc = -EINVAL;
7544 goto done;
7545 }
7546 if (atomic_read(&ac->cmd_state_pp) > 0) {
7547 pr_err("%s: DSP returned error[%d] , set-params paramid[0x%x]\n",
7548 __func__, atomic_read(&ac->cmd_state_pp),
7549 multich_gain.data.param_id);
7550 rc = -EINVAL;
7551 goto done;
7552 }
7553 rc = 0;
7554done:
7555 return rc;
7556}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307557EXPORT_SYMBOL(q6asm_set_multich_gain);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307558
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307559/**
7560 * q6asm_set_mute -
7561 * command to set mute for ASM
7562 *
7563 * @ac: Audio client handle
7564 * @muteflag: mute value
7565 *
7566 * Returns 0 on success or error on failure
7567 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307568int q6asm_set_mute(struct audio_client *ac, int muteflag)
7569{
7570 struct asm_volume_ctrl_mute_config mute;
7571 int sz = 0;
7572 int rc = 0;
7573
7574 if (ac == NULL) {
7575 pr_err("%s: APR handle NULL\n", __func__);
7576 rc = -EINVAL;
7577 goto fail_cmd;
7578 }
7579 if (ac->apr == NULL) {
7580 pr_err("%s: AC APR handle NULL\n", __func__);
7581 rc = -EINVAL;
7582 goto fail_cmd;
7583 }
7584
7585 sz = sizeof(struct asm_volume_ctrl_mute_config);
7586 q6asm_add_hdr_async(ac, &mute.hdr, sz, TRUE);
7587 atomic_set(&ac->cmd_state_pp, -1);
7588 mute.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
7589 mute.param.data_payload_addr_lsw = 0;
7590 mute.param.data_payload_addr_msw = 0;
7591 mute.param.mem_map_handle = 0;
7592 mute.param.data_payload_size = sizeof(mute) -
7593 sizeof(mute.hdr) - sizeof(mute.param);
7594 mute.data.module_id = ASM_MODULE_ID_VOL_CTRL;
7595 mute.data.param_id = ASM_PARAM_ID_VOL_CTRL_MUTE_CONFIG;
7596 mute.data.param_size = mute.param.data_payload_size - sizeof(mute.data);
7597 mute.data.reserved = 0;
7598 mute.mute_flag = muteflag;
7599
7600 rc = apr_send_pkt(ac->apr, (uint32_t *) &mute);
7601 if (rc < 0) {
7602 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
7603 __func__, mute.data.param_id, rc);
7604 rc = -EINVAL;
7605 goto fail_cmd;
7606 }
7607
7608 rc = wait_event_timeout(ac->cmd_wait,
7609 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
7610 if (!rc) {
7611 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
7612 mute.data.param_id);
7613 rc = -ETIMEDOUT;
7614 goto fail_cmd;
7615 }
7616 if (atomic_read(&ac->cmd_state_pp) > 0) {
7617 pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
7618 __func__, adsp_err_get_err_str(
7619 atomic_read(&ac->cmd_state_pp)),
7620 mute.data.param_id);
7621 rc = adsp_err_get_lnx_err_code(
7622 atomic_read(&ac->cmd_state_pp));
7623 goto fail_cmd;
7624 }
7625 rc = 0;
7626fail_cmd:
7627 return rc;
7628}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307629EXPORT_SYMBOL(q6asm_set_mute);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307630
7631static int __q6asm_set_volume(struct audio_client *ac, int volume, int instance)
7632{
7633 struct asm_volume_ctrl_master_gain vol;
7634 int sz = 0;
7635 int rc = 0;
7636 int module_id;
7637
7638 if (ac == NULL) {
7639 pr_err("%s: APR handle NULL\n", __func__);
7640 rc = -EINVAL;
7641 goto fail_cmd;
7642 }
7643 if (ac->apr == NULL) {
7644 pr_err("%s: AC APR handle NULL\n", __func__);
7645 rc = -EINVAL;
7646 goto fail_cmd;
7647 }
7648
7649 switch (instance) {
7650 case SOFT_VOLUME_INSTANCE_2:
7651 module_id = ASM_MODULE_ID_VOL_CTRL2;
7652 break;
7653 case SOFT_VOLUME_INSTANCE_1:
7654 default:
7655 module_id = ASM_MODULE_ID_VOL_CTRL;
7656 break;
7657 }
7658
7659 sz = sizeof(struct asm_volume_ctrl_master_gain);
7660 q6asm_add_hdr_async(ac, &vol.hdr, sz, TRUE);
7661 atomic_set(&ac->cmd_state_pp, -1);
7662 vol.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
7663 vol.param.data_payload_addr_lsw = 0;
7664 vol.param.data_payload_addr_msw = 0;
7665 vol.param.mem_map_handle = 0;
7666 vol.param.data_payload_size = sizeof(vol) -
7667 sizeof(vol.hdr) - sizeof(vol.param);
7668 vol.data.module_id = module_id;
7669 vol.data.param_id = ASM_PARAM_ID_VOL_CTRL_MASTER_GAIN;
7670 vol.data.param_size = vol.param.data_payload_size - sizeof(vol.data);
7671 vol.data.reserved = 0;
7672 vol.master_gain = volume;
7673
7674 rc = apr_send_pkt(ac->apr, (uint32_t *) &vol);
7675 if (rc < 0) {
7676 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
7677 __func__, vol.data.param_id, rc);
7678 rc = -EINVAL;
7679 goto fail_cmd;
7680 }
7681
7682 rc = wait_event_timeout(ac->cmd_wait,
7683 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
7684 if (!rc) {
7685 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
7686 vol.data.param_id);
7687 rc = -ETIMEDOUT;
7688 goto fail_cmd;
7689 }
7690 if (atomic_read(&ac->cmd_state_pp) > 0) {
7691 pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
7692 __func__, adsp_err_get_err_str(
7693 atomic_read(&ac->cmd_state_pp)),
7694 vol.data.param_id);
7695 rc = adsp_err_get_lnx_err_code(
7696 atomic_read(&ac->cmd_state_pp));
7697 goto fail_cmd;
7698 }
7699
7700 rc = 0;
7701fail_cmd:
7702 return rc;
7703}
7704
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307705/**
7706 * q6asm_set_volume -
7707 * command to set volume for ASM
7708 *
7709 * @ac: Audio client handle
7710 * @volume: volume level
7711 *
7712 * Returns 0 on success or error on failure
7713 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307714int q6asm_set_volume(struct audio_client *ac, int volume)
7715{
7716 return __q6asm_set_volume(ac, volume, SOFT_VOLUME_INSTANCE_1);
7717}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307718EXPORT_SYMBOL(q6asm_set_volume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307719
7720int q6asm_set_volume_v2(struct audio_client *ac, int volume, int instance)
7721{
7722 return __q6asm_set_volume(ac, volume, instance);
7723}
7724
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307725/**
7726 * q6asm_set_aptx_dec_bt_addr -
7727 * command to aptx decoder BT addr for ASM
7728 *
7729 * @ac: Audio client handle
7730 * @cfg: APTX decoder bt addr config
7731 *
7732 * Returns 0 on success or error on failure
7733 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307734int q6asm_set_aptx_dec_bt_addr(struct audio_client *ac,
7735 struct aptx_dec_bt_addr_cfg *cfg)
7736{
7737 struct aptx_dec_bt_dev_addr paylod;
7738 int sz = 0;
7739 int rc = 0;
7740
7741 pr_debug("%s: BT addr nap %d, uap %d, lap %d\n", __func__, cfg->nap,
7742 cfg->uap, cfg->lap);
7743
7744 if (ac == NULL) {
7745 pr_err("%s: AC handle NULL\n", __func__);
7746 rc = -EINVAL;
7747 goto fail_cmd;
7748 }
7749 if (ac->apr == NULL) {
7750 pr_err("%s: AC APR handle NULL\n", __func__);
7751 rc = -EINVAL;
7752 goto fail_cmd;
7753 }
7754
7755 sz = sizeof(struct aptx_dec_bt_dev_addr);
7756 q6asm_add_hdr_async(ac, &paylod.hdr, sz, TRUE);
7757 atomic_set(&ac->cmd_state, -1);
7758 paylod.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
7759 paylod.encdec.param_id = APTX_DECODER_BT_ADDRESS;
7760 paylod.encdec.param_size = sz - sizeof(paylod.hdr)
7761 - sizeof(paylod.encdec);
7762 paylod.bt_addr_cfg.lap = cfg->lap;
7763 paylod.bt_addr_cfg.uap = cfg->uap;
7764 paylod.bt_addr_cfg.nap = cfg->nap;
7765
7766 rc = apr_send_pkt(ac->apr, (uint32_t *) &paylod);
7767 if (rc < 0) {
7768 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
7769 __func__, paylod.encdec.param_id, rc);
7770 rc = -EINVAL;
7771 goto fail_cmd;
7772 }
7773
7774 rc = wait_event_timeout(ac->cmd_wait,
7775 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
7776 if (!rc) {
7777 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
7778 paylod.encdec.param_id);
7779 rc = -ETIMEDOUT;
7780 goto fail_cmd;
7781 }
7782 if (atomic_read(&ac->cmd_state) > 0) {
7783 pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
7784 __func__, adsp_err_get_err_str(
7785 atomic_read(&ac->cmd_state)),
7786 paylod.encdec.param_id);
7787 rc = adsp_err_get_lnx_err_code(
7788 atomic_read(&ac->cmd_state));
7789 goto fail_cmd;
7790 }
7791 pr_debug("%s: set BT addr is success\n", __func__);
7792 rc = 0;
7793fail_cmd:
7794 return rc;
7795}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307796EXPORT_SYMBOL(q6asm_set_aptx_dec_bt_addr);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307797
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307798/**
7799 * q6asm_send_ion_fd -
7800 * command to send ION memory map for ASM
7801 *
7802 * @ac: Audio client handle
7803 * @fd: ION file desc
7804 *
7805 * Returns 0 on success or error on failure
7806 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307807int q6asm_send_ion_fd(struct audio_client *ac, int fd)
7808{
7809 struct ion_client *client;
7810 struct ion_handle *handle;
7811 ion_phys_addr_t paddr;
7812 size_t pa_len = 0;
7813 void *vaddr;
7814 int ret;
7815 int sz = 0;
7816 struct avs_rtic_shared_mem_addr shm;
7817
7818 if (ac == NULL) {
7819 pr_err("%s: APR handle NULL\n", __func__);
7820 ret = -EINVAL;
7821 goto fail_cmd;
7822 }
7823 if (ac->apr == NULL) {
7824 pr_err("%s: AC APR handle NULL\n", __func__);
7825 ret = -EINVAL;
7826 goto fail_cmd;
7827 }
7828
7829 ret = msm_audio_ion_import("audio_mem_client",
7830 &client,
7831 &handle,
7832 fd,
7833 NULL,
7834 0,
7835 &paddr,
7836 &pa_len,
7837 &vaddr);
7838 if (ret) {
7839 pr_err("%s: audio ION import failed, rc = %d\n",
7840 __func__, ret);
7841 ret = -ENOMEM;
7842 goto fail_cmd;
7843 }
7844 /* get payload length */
7845 sz = sizeof(struct avs_rtic_shared_mem_addr);
7846 q6asm_add_hdr_async(ac, &shm.hdr, sz, TRUE);
7847 atomic_set(&ac->cmd_state, -1);
7848 shm.shm_buf_addr_lsw = lower_32_bits(paddr);
7849 shm.shm_buf_addr_msw = msm_audio_populate_upper_32_bits(paddr);
7850 shm.buf_size = pa_len;
7851 shm.shm_buf_num_regions = 1;
7852 shm.shm_buf_mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
7853 shm.shm_buf_flag = 0x00;
7854 shm.encdec.param_id = AVS_PARAM_ID_RTIC_SHARED_MEMORY_ADDR;
7855 shm.encdec.param_size = sizeof(struct avs_rtic_shared_mem_addr) -
7856 sizeof(struct apr_hdr) -
7857 sizeof(struct asm_stream_cmd_set_encdec_param_v2);
7858 shm.encdec.service_id = OUT;
7859 shm.encdec.reserved = 0;
7860 shm.map_region.shm_addr_lsw = shm.shm_buf_addr_lsw;
7861 shm.map_region.shm_addr_msw = shm.shm_buf_addr_msw;
7862 shm.map_region.mem_size_bytes = pa_len;
7863 shm.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM_V2;
7864 ret = apr_send_pkt(ac->apr, (uint32_t *) &shm);
7865 if (ret < 0) {
7866 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
7867 __func__, shm.encdec.param_id, ret);
7868 ret = -EINVAL;
7869 goto fail_cmd;
7870 }
7871
7872 ret = wait_event_timeout(ac->cmd_wait,
7873 (atomic_read(&ac->cmd_state) >= 0), 1*HZ);
7874 if (!ret) {
7875 pr_err("%s: timeout, shm.encdec paramid[0x%x]\n", __func__,
7876 shm.encdec.param_id);
7877 ret = -ETIMEDOUT;
7878 goto fail_cmd;
7879 }
7880 if (atomic_read(&ac->cmd_state) > 0) {
7881 pr_err("%s: DSP returned error[%s] shm.encdec paramid[0x%x]\n",
7882 __func__,
7883 adsp_err_get_err_str(atomic_read(&ac->cmd_state)),
7884 shm.encdec.param_id);
7885 ret = adsp_err_get_lnx_err_code(atomic_read(&ac->cmd_state));
7886 goto fail_cmd;
7887 }
7888 ret = 0;
7889fail_cmd:
7890 return ret;
7891}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307892EXPORT_SYMBOL(q6asm_send_ion_fd);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307893
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307894/**
7895 * q6asm_send_rtic_event_ack -
7896 * command to send RTIC event ack
7897 *
7898 * @ac: Audio client handle
7899 * @param: params for event ack
7900 * @params_length: length of params
7901 *
7902 * Returns 0 on success or error on failure
7903 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307904int q6asm_send_rtic_event_ack(struct audio_client *ac,
7905 void *param, uint32_t params_length)
7906{
7907 char *asm_params = NULL;
7908 int sz, rc;
7909 struct avs_param_rtic_event_ack ack;
7910
7911 if (!param || !ac) {
7912 pr_err("%s: %s is NULL\n", __func__,
7913 (!param) ? "param" : "ac");
7914 rc = -EINVAL;
7915 goto done;
7916 }
7917
7918 sz = sizeof(struct avs_param_rtic_event_ack) + params_length;
7919 asm_params = kzalloc(sz, GFP_KERNEL);
7920 if (!asm_params) {
7921 rc = -ENOMEM;
7922 goto done;
7923 }
7924
7925 q6asm_add_hdr_async(ac, &ack.hdr,
7926 sizeof(struct avs_param_rtic_event_ack) +
7927 params_length, TRUE);
7928 atomic_set(&ac->cmd_state, -1);
7929 ack.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM_V2;
7930 ack.encdec.param_id = AVS_PARAM_ID_RTIC_EVENT_ACK;
7931 ack.encdec.param_size = params_length;
7932 ack.encdec.reserved = 0;
7933 ack.encdec.service_id = OUT;
7934 memcpy(asm_params, &ack, sizeof(struct avs_param_rtic_event_ack));
7935 memcpy(asm_params + sizeof(struct avs_param_rtic_event_ack),
7936 param, params_length);
7937 rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
7938 if (rc < 0) {
7939 pr_err("%s: apr pkt failed for rtic event ack\n", __func__);
7940 rc = -EINVAL;
7941 goto fail_send_param;
7942 }
7943
7944 rc = wait_event_timeout(ac->cmd_wait,
7945 (atomic_read(&ac->cmd_state) >= 0), 1 * HZ);
7946 if (!rc) {
7947 pr_err("%s: timeout for rtic event ack cmd\n", __func__);
7948 rc = -ETIMEDOUT;
7949 goto fail_send_param;
7950 }
7951
7952 if (atomic_read(&ac->cmd_state) > 0) {
7953 pr_err("%s: DSP returned error[%s] for rtic event ack cmd\n",
7954 __func__, adsp_err_get_err_str(
7955 atomic_read(&ac->cmd_state)));
7956 rc = adsp_err_get_lnx_err_code(
7957 atomic_read(&ac->cmd_state));
7958 goto fail_send_param;
7959 }
7960 rc = 0;
7961
7962fail_send_param:
7963 kfree(asm_params);
7964done:
7965 return rc;
7966}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307967EXPORT_SYMBOL(q6asm_send_rtic_event_ack);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307968
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307969/**
7970 * q6asm_set_softpause -
7971 * command to set pause for ASM
7972 *
7973 * @ac: Audio client handle
7974 * @pause_param: params for pause
7975 *
7976 * Returns 0 on success or error on failure
7977 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307978int q6asm_set_softpause(struct audio_client *ac,
7979 struct asm_softpause_params *pause_param)
7980{
7981 struct asm_soft_pause_params softpause;
7982 int sz = 0;
7983 int rc = 0;
7984
7985 if (ac == NULL) {
7986 pr_err("%s: APR handle NULL\n", __func__);
7987 rc = -EINVAL;
7988 goto fail_cmd;
7989 }
7990 if (ac->apr == NULL) {
7991 pr_err("%s: AC APR handle NULL\n", __func__);
7992 rc = -EINVAL;
7993 goto fail_cmd;
7994 }
7995
7996 sz = sizeof(struct asm_soft_pause_params);
7997 q6asm_add_hdr_async(ac, &softpause.hdr, sz, TRUE);
7998 atomic_set(&ac->cmd_state_pp, -1);
7999 softpause.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
8000
8001 softpause.param.data_payload_addr_lsw = 0;
8002 softpause.param.data_payload_addr_msw = 0;
8003 softpause.param.mem_map_handle = 0;
8004 softpause.param.data_payload_size = sizeof(softpause) -
8005 sizeof(softpause.hdr) - sizeof(softpause.param);
8006 softpause.data.module_id = ASM_MODULE_ID_VOL_CTRL;
8007 softpause.data.param_id = ASM_PARAM_ID_SOFT_PAUSE_PARAMETERS;
8008 softpause.data.param_size = softpause.param.data_payload_size -
8009 sizeof(softpause.data);
8010 softpause.data.reserved = 0;
8011 softpause.enable_flag = pause_param->enable;
8012 softpause.period = pause_param->period;
8013 softpause.step = pause_param->step;
8014 softpause.ramping_curve = pause_param->rampingcurve;
8015
8016 rc = apr_send_pkt(ac->apr, (uint32_t *) &softpause);
8017 if (rc < 0) {
8018 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
8019 __func__, softpause.data.param_id, rc);
8020 rc = -EINVAL;
8021 goto fail_cmd;
8022 }
8023
8024 rc = wait_event_timeout(ac->cmd_wait,
8025 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
8026 if (!rc) {
8027 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
8028 softpause.data.param_id);
8029 rc = -ETIMEDOUT;
8030 goto fail_cmd;
8031 }
8032 if (atomic_read(&ac->cmd_state_pp) > 0) {
8033 pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
8034 __func__, adsp_err_get_err_str(
8035 atomic_read(&ac->cmd_state_pp)),
8036 softpause.data.param_id);
8037 rc = adsp_err_get_lnx_err_code(
8038 atomic_read(&ac->cmd_state_pp));
8039 goto fail_cmd;
8040 }
8041 rc = 0;
8042fail_cmd:
8043 return rc;
8044}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308045EXPORT_SYMBOL(q6asm_set_softpause);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308046
8047static int __q6asm_set_softvolume(struct audio_client *ac,
8048 struct asm_softvolume_params *softvol_param,
8049 int instance)
8050{
8051 struct asm_soft_step_volume_params softvol;
8052 int sz = 0;
8053 int rc = 0;
8054 int module_id;
8055
8056 if (ac == NULL) {
8057 pr_err("%s: APR handle NULL\n", __func__);
8058 rc = -EINVAL;
8059 goto fail_cmd;
8060 }
8061 if (ac->apr == NULL) {
8062 pr_err("%s: AC APR handle NULL\n", __func__);
8063 rc = -EINVAL;
8064 goto fail_cmd;
8065 }
8066
8067 switch (instance) {
8068 case SOFT_VOLUME_INSTANCE_2:
8069 module_id = ASM_MODULE_ID_VOL_CTRL2;
8070 break;
8071 case SOFT_VOLUME_INSTANCE_1:
8072 default:
8073 module_id = ASM_MODULE_ID_VOL_CTRL;
8074 break;
8075 }
8076
8077 sz = sizeof(struct asm_soft_step_volume_params);
8078 q6asm_add_hdr_async(ac, &softvol.hdr, sz, TRUE);
8079 atomic_set(&ac->cmd_state_pp, -1);
8080 softvol.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
8081 softvol.param.data_payload_addr_lsw = 0;
8082 softvol.param.data_payload_addr_msw = 0;
8083 softvol.param.mem_map_handle = 0;
8084 softvol.param.data_payload_size = sizeof(softvol) -
8085 sizeof(softvol.hdr) - sizeof(softvol.param);
8086 softvol.data.module_id = module_id;
8087 softvol.data.param_id = ASM_PARAM_ID_SOFT_VOL_STEPPING_PARAMETERS;
8088 softvol.data.param_size = softvol.param.data_payload_size -
8089 sizeof(softvol.data);
8090 softvol.data.reserved = 0;
8091 softvol.period = softvol_param->period;
8092 softvol.step = softvol_param->step;
8093 softvol.ramping_curve = softvol_param->rampingcurve;
8094
8095 rc = apr_send_pkt(ac->apr, (uint32_t *) &softvol);
8096 if (rc < 0) {
8097 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
8098 __func__, softvol.data.param_id, rc);
8099 rc = -EINVAL;
8100 goto fail_cmd;
8101 }
8102
8103 rc = wait_event_timeout(ac->cmd_wait,
8104 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
8105 if (!rc) {
8106 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
8107 softvol.data.param_id);
8108 rc = -ETIMEDOUT;
8109 goto fail_cmd;
8110 }
8111 if (atomic_read(&ac->cmd_state_pp) > 0) {
8112 pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
8113 __func__, adsp_err_get_err_str(
8114 atomic_read(&ac->cmd_state_pp)),
8115 softvol.data.param_id);
8116 rc = adsp_err_get_lnx_err_code(
8117 atomic_read(&ac->cmd_state_pp));
8118 goto fail_cmd;
8119 }
8120 rc = 0;
8121fail_cmd:
8122 return rc;
8123}
8124
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308125/**
8126 * q6asm_set_softvolume -
8127 * command to set softvolume for ASM
8128 *
8129 * @ac: Audio client handle
8130 * @softvol_param: params for softvol
8131 *
8132 * Returns 0 on success or error on failure
8133 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308134int q6asm_set_softvolume(struct audio_client *ac,
8135 struct asm_softvolume_params *softvol_param)
8136{
8137 return __q6asm_set_softvolume(ac, softvol_param,
8138 SOFT_VOLUME_INSTANCE_1);
8139}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308140EXPORT_SYMBOL(q6asm_set_softvolume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308141
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308142/**
8143 * q6asm_set_softvolume_v2 -
8144 * command to set softvolume V2 for ASM
8145 *
8146 * @ac: Audio client handle
8147 * @softvol_param: params for softvol
8148 * @instance: instance to apply softvol
8149 *
8150 * Returns 0 on success or error on failure
8151 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308152int q6asm_set_softvolume_v2(struct audio_client *ac,
8153 struct asm_softvolume_params *softvol_param,
8154 int instance)
8155{
8156 return __q6asm_set_softvolume(ac, softvol_param, instance);
8157}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308158EXPORT_SYMBOL(q6asm_set_softvolume_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308159
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308160/**
8161 * q6asm_equalizer -
8162 * command to set equalizer for ASM
8163 *
8164 * @ac: Audio client handle
8165 * @eq_p: Equalizer params
8166 *
8167 * Returns 0 on success or error on failure
8168 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308169int q6asm_equalizer(struct audio_client *ac, void *eq_p)
8170{
8171 struct asm_eq_params eq;
8172 struct msm_audio_eq_stream_config *eq_params = NULL;
8173 int i = 0;
8174 int sz = 0;
8175 int rc = 0;
8176
8177 if (ac == NULL) {
8178 pr_err("%s: APR handle NULL\n", __func__);
8179 rc = -EINVAL;
8180 goto fail_cmd;
8181 }
8182 if (ac->apr == NULL) {
8183 pr_err("%s: AC APR handle NULL\n", __func__);
8184 rc = -EINVAL;
8185 goto fail_cmd;
8186 }
8187
8188 if (eq_p == NULL) {
8189 pr_err("%s: [%d]: Invalid Eq param\n", __func__, ac->session);
8190 rc = -EINVAL;
8191 goto fail_cmd;
8192 }
8193 sz = sizeof(struct asm_eq_params);
8194 eq_params = (struct msm_audio_eq_stream_config *) eq_p;
8195 q6asm_add_hdr(ac, &eq.hdr, sz, TRUE);
8196 atomic_set(&ac->cmd_state_pp, -1);
8197
8198 eq.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
8199 eq.param.data_payload_addr_lsw = 0;
8200 eq.param.data_payload_addr_msw = 0;
8201 eq.param.mem_map_handle = 0;
8202 eq.param.data_payload_size = sizeof(eq) -
8203 sizeof(eq.hdr) - sizeof(eq.param);
8204 eq.data.module_id = ASM_MODULE_ID_EQUALIZER;
8205 eq.data.param_id = ASM_PARAM_ID_EQUALIZER_PARAMETERS;
8206 eq.data.param_size = eq.param.data_payload_size - sizeof(eq.data);
8207 eq.enable_flag = eq_params->enable;
8208 eq.num_bands = eq_params->num_bands;
8209
8210 pr_debug("%s: enable:%d numbands:%d\n", __func__, eq_params->enable,
8211 eq_params->num_bands);
8212 for (i = 0; i < eq_params->num_bands; i++) {
8213 eq.eq_bands[i].band_idx =
8214 eq_params->eq_bands[i].band_idx;
8215 eq.eq_bands[i].filterype =
8216 eq_params->eq_bands[i].filter_type;
8217 eq.eq_bands[i].center_freq_hz =
8218 eq_params->eq_bands[i].center_freq_hz;
8219 eq.eq_bands[i].filter_gain =
8220 eq_params->eq_bands[i].filter_gain;
8221 eq.eq_bands[i].q_factor =
8222 eq_params->eq_bands[i].q_factor;
8223 pr_debug("%s: filter_type:%u bandnum:%d\n", __func__,
8224 eq_params->eq_bands[i].filter_type, i);
8225 pr_debug("%s: center_freq_hz:%u bandnum:%d\n", __func__,
8226 eq_params->eq_bands[i].center_freq_hz, i);
8227 pr_debug("%s: filter_gain:%d bandnum:%d\n", __func__,
8228 eq_params->eq_bands[i].filter_gain, i);
8229 pr_debug("%s: q_factor:%d bandnum:%d\n", __func__,
8230 eq_params->eq_bands[i].q_factor, i);
8231 }
8232 rc = apr_send_pkt(ac->apr, (uint32_t *)&eq);
8233 if (rc < 0) {
8234 pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
8235 __func__, eq.data.param_id, rc);
8236 rc = -EINVAL;
8237 goto fail_cmd;
8238 }
8239
8240 rc = wait_event_timeout(ac->cmd_wait,
8241 (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
8242 if (!rc) {
8243 pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
8244 eq.data.param_id);
8245 rc = -ETIMEDOUT;
8246 goto fail_cmd;
8247 }
8248 if (atomic_read(&ac->cmd_state_pp) > 0) {
8249 pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
8250 __func__, adsp_err_get_err_str(
8251 atomic_read(&ac->cmd_state_pp)),
8252 eq.data.param_id);
8253 rc = adsp_err_get_lnx_err_code(
8254 atomic_read(&ac->cmd_state_pp));
8255 goto fail_cmd;
8256 }
8257 rc = 0;
8258fail_cmd:
8259 return rc;
8260}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308261EXPORT_SYMBOL(q6asm_equalizer);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308262
8263static int __q6asm_read(struct audio_client *ac, bool is_custom_len_reqd,
8264 int len)
8265{
8266 struct asm_data_cmd_read_v2 read;
8267 struct asm_buffer_node *buf_node = NULL;
8268 struct list_head *ptr, *next;
8269 struct audio_buffer *ab;
8270 int dsp_buf;
8271 struct audio_port_data *port;
8272 int rc;
8273
8274 if (ac == NULL) {
8275 pr_err("%s: APR handle NULL\n", __func__);
8276 return -EINVAL;
8277 }
8278 if (ac->apr == NULL) {
8279 pr_err("%s: AC APR handle NULL\n", __func__);
8280 return -EINVAL;
8281 }
8282
8283 if (ac->io_mode & SYNC_IO_MODE) {
8284 port = &ac->port[OUT];
8285
8286 q6asm_add_hdr(ac, &read.hdr, sizeof(read), FALSE);
8287
8288 mutex_lock(&port->lock);
8289
8290 dsp_buf = port->dsp_buf;
8291 if (port->buf == NULL) {
8292 pr_err("%s: buf is NULL\n", __func__);
8293 mutex_unlock(&port->lock);
8294 return -EINVAL;
8295 }
8296 ab = &port->buf[dsp_buf];
8297
8298 dev_vdbg(ac->dev, "%s: session[%d]dsp-buf[%d][%pK]cpu_buf[%d][%pK]\n",
8299 __func__,
8300 ac->session,
8301 dsp_buf,
8302 port->buf[dsp_buf].data,
8303 port->cpu_buf,
8304 &port->buf[port->cpu_buf].phys);
8305
8306 read.hdr.opcode = ASM_DATA_CMD_READ_V2;
8307 read.buf_addr_lsw = lower_32_bits(ab->phys);
8308 read.buf_addr_msw = msm_audio_populate_upper_32_bits(ab->phys);
8309
8310 list_for_each_safe(ptr, next, &ac->port[OUT].mem_map_handle) {
8311 buf_node = list_entry(ptr, struct asm_buffer_node,
8312 list);
Vignesh Kulothunganc894ac42018-01-04 13:49:12 -08008313 if (buf_node->buf_phys_addr == ab->phys) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308314 read.mem_map_handle = buf_node->mmap_hdl;
Vignesh Kulothunganc894ac42018-01-04 13:49:12 -08008315 break;
8316 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308317 }
8318 dev_vdbg(ac->dev, "memory_map handle in q6asm_read: [%0x]:",
8319 read.mem_map_handle);
8320 read.buf_size = is_custom_len_reqd ? len : ab->size;
8321 read.seq_id = port->dsp_buf;
8322 q6asm_update_token(&read.hdr.token,
8323 0, /* Session ID is NA */
8324 0, /* Stream ID is NA */
8325 port->dsp_buf,
8326 0, /* Direction flag is NA */
8327 WAIT_CMD);
8328 port->dsp_buf = q6asm_get_next_buf(ac, port->dsp_buf,
8329 port->max_buf_cnt);
8330 mutex_unlock(&port->lock);
8331 dev_vdbg(ac->dev, "%s: buf add[%pK] token[0x%x] uid[%d]\n",
8332 __func__, &ab->phys, read.hdr.token,
8333 read.seq_id);
8334 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
8335 if (rc < 0) {
8336 pr_err("%s: read op[0x%x]rc[%d]\n",
8337 __func__, read.hdr.opcode, rc);
8338 goto fail_cmd;
8339 }
8340 return 0;
8341 }
8342fail_cmd:
8343 return -EINVAL;
8344}
8345
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308346/**
8347 * q6asm_read -
8348 * command to read buffer data from DSP
8349 *
8350 * @ac: Audio client handle
8351 *
8352 * Returns 0 on success or error on failure
8353 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308354int q6asm_read(struct audio_client *ac)
8355{
8356 return __q6asm_read(ac, false/*is_custom_len_reqd*/, 0);
8357}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308358EXPORT_SYMBOL(q6asm_read);
8359
8360
8361/**
8362 * q6asm_read_v2 -
8363 * command to read buffer data from DSP
8364 *
8365 * @ac: Audio client handle
8366 * @len: buffer size to read
8367 *
8368 * Returns 0 on success or error on failure
8369 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308370int q6asm_read_v2(struct audio_client *ac, uint32_t len)
8371{
8372 return __q6asm_read(ac, true /*is_custom_len_reqd*/, len);
8373}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308374EXPORT_SYMBOL(q6asm_read_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308375
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308376/**
8377 * q6asm_read_nolock -
8378 * command to read buffer data from DSP
8379 * with no wait for ack.
8380 *
8381 * @ac: Audio client handle
8382 *
8383 * Returns 0 on success or error on failure
8384 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308385int q6asm_read_nolock(struct audio_client *ac)
8386{
8387 struct asm_data_cmd_read_v2 read;
8388 struct asm_buffer_node *buf_node = NULL;
8389 struct list_head *ptr, *next;
8390 struct audio_buffer *ab;
8391 int dsp_buf;
8392 struct audio_port_data *port;
8393 int rc;
8394
8395 if (ac == NULL) {
8396 pr_err("%s: APR handle NULL\n", __func__);
8397 return -EINVAL;
8398 }
8399 if (ac->apr == NULL) {
8400 pr_err("%s: AC APR handle NULL\n", __func__);
8401 return -EINVAL;
8402 }
8403
8404 if (ac->io_mode & SYNC_IO_MODE) {
8405 port = &ac->port[OUT];
8406
8407 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
8408
8409
8410 dsp_buf = port->dsp_buf;
8411 ab = &port->buf[dsp_buf];
8412
8413 dev_vdbg(ac->dev, "%s: session[%d]dsp-buf[%d][%pK]cpu_buf[%d][%pK]\n",
8414 __func__,
8415 ac->session,
8416 dsp_buf,
8417 port->buf[dsp_buf].data,
8418 port->cpu_buf,
8419 &port->buf[port->cpu_buf].phys);
8420
8421 read.hdr.opcode = ASM_DATA_CMD_READ_V2;
8422 read.buf_addr_lsw = lower_32_bits(ab->phys);
8423 read.buf_addr_msw = msm_audio_populate_upper_32_bits(ab->phys);
8424 read.buf_size = ab->size;
8425 read.seq_id = port->dsp_buf;
8426 q6asm_update_token(&read.hdr.token,
8427 0, /* Session ID is NA */
8428 0, /* Stream ID is NA */
8429 port->dsp_buf,
8430 0, /* Direction flag is NA */
8431 WAIT_CMD);
8432
8433 list_for_each_safe(ptr, next, &ac->port[OUT].mem_map_handle) {
8434 buf_node = list_entry(ptr, struct asm_buffer_node,
8435 list);
8436 if (buf_node->buf_phys_addr == ab->phys) {
8437 read.mem_map_handle = buf_node->mmap_hdl;
8438 break;
8439 }
8440 }
8441
8442 port->dsp_buf = q6asm_get_next_buf(ac, port->dsp_buf,
8443 port->max_buf_cnt);
8444 dev_vdbg(ac->dev, "%s: buf add[%pK] token[0x%x] uid[%d]\n",
8445 __func__, &ab->phys, read.hdr.token,
8446 read.seq_id);
8447 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
8448 if (rc < 0) {
8449 pr_err("%s: read op[0x%x]rc[%d]\n",
8450 __func__, read.hdr.opcode, rc);
8451 goto fail_cmd;
8452 }
8453 return 0;
8454 }
8455fail_cmd:
8456 return -EINVAL;
8457}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308458EXPORT_SYMBOL(q6asm_read_nolock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308459
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308460/**
8461 * q6asm_async_write -
8462 * command to write DSP buffer
8463 *
8464 * @ac: Audio client handle
8465 * @param: params for async write
8466 *
8467 * Returns 0 on success or error on failure
8468 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308469int q6asm_async_write(struct audio_client *ac,
8470 struct audio_aio_write_param *param)
8471{
8472 int rc = 0;
8473 struct asm_data_cmd_write_v2 write;
8474 struct asm_buffer_node *buf_node = NULL;
8475 struct list_head *ptr, *next;
8476 struct audio_buffer *ab;
8477 struct audio_port_data *port;
8478 phys_addr_t lbuf_phys_addr;
8479 u32 liomode;
8480 u32 io_compressed;
8481 u32 io_compressed_stream;
8482
8483 if (ac == NULL) {
8484 pr_err("%s: APR handle NULL\n", __func__);
8485 return -EINVAL;
8486 }
8487 if (ac->apr == NULL) {
8488 pr_err("%s: AC APR handle NULL\n", __func__);
8489 return -EINVAL;
8490 }
8491
8492 q6asm_stream_add_hdr_async(
8493 ac, &write.hdr, sizeof(write), TRUE, ac->stream_id);
8494 port = &ac->port[IN];
8495 ab = &port->buf[port->dsp_buf];
8496
8497 /* Pass session id as token for AIO scheme */
8498 write.hdr.token = param->uid;
8499 write.hdr.opcode = ASM_DATA_CMD_WRITE_V2;
8500 write.buf_addr_lsw = lower_32_bits(param->paddr);
8501 write.buf_addr_msw = msm_audio_populate_upper_32_bits(param->paddr);
8502 write.buf_size = param->len;
8503 write.timestamp_msw = param->msw_ts;
8504 write.timestamp_lsw = param->lsw_ts;
8505 liomode = (ASYNC_IO_MODE | NT_MODE);
8506 io_compressed = (ASYNC_IO_MODE | COMPRESSED_IO);
8507 io_compressed_stream = (ASYNC_IO_MODE | COMPRESSED_STREAM_IO);
8508
8509 if (ac->io_mode == liomode)
8510 lbuf_phys_addr = (param->paddr - 32);
8511 else if (ac->io_mode == io_compressed ||
8512 ac->io_mode == io_compressed_stream)
8513 lbuf_phys_addr = (param->paddr - param->metadata_len);
8514 else {
8515 if (param->flags & SET_TIMESTAMP)
8516 lbuf_phys_addr = param->paddr -
8517 sizeof(struct snd_codec_metadata);
8518 else
8519 lbuf_phys_addr = param->paddr;
8520 }
8521 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",
8522 __func__,
8523 write.hdr.token, &param->paddr,
8524 write.buf_size, write.timestamp_msw,
8525 write.timestamp_lsw, &lbuf_phys_addr);
8526
8527 /* Use 0xFF00 for disabling timestamps */
8528 if (param->flags == 0xFF00)
8529 write.flags = (0x00000000 | (param->flags & 0x800000FF));
8530 else
8531 write.flags = (0x80000000 | param->flags);
8532 write.flags |= param->last_buffer << ASM_SHIFT_LAST_BUFFER_FLAG;
8533 write.seq_id = param->uid;
8534 list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) {
8535 buf_node = list_entry(ptr, struct asm_buffer_node,
8536 list);
8537 if (buf_node->buf_phys_addr == lbuf_phys_addr) {
8538 write.mem_map_handle = buf_node->mmap_hdl;
8539 break;
8540 }
8541 }
8542
8543 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
8544 if (rc < 0) {
8545 pr_err("%s: write op[0x%x]rc[%d]\n", __func__,
8546 write.hdr.opcode, rc);
8547 goto fail_cmd;
8548 }
8549 return 0;
8550fail_cmd:
8551 return -EINVAL;
8552}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308553EXPORT_SYMBOL(q6asm_async_write);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308554
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308555/**
8556 * q6asm_async_read -
8557 * command to read DSP buffer
8558 *
8559 * @ac: Audio client handle
8560 * @param: params for async read
8561 *
8562 * Returns 0 on success or error on failure
8563 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308564int q6asm_async_read(struct audio_client *ac,
8565 struct audio_aio_read_param *param)
8566{
8567 int rc = 0;
8568 struct asm_data_cmd_read_v2 read;
8569 struct asm_buffer_node *buf_node = NULL;
8570 struct list_head *ptr, *next;
8571 phys_addr_t lbuf_phys_addr;
8572 u32 liomode;
8573 u32 io_compressed;
8574 int dir = 0;
8575
8576 if (ac == NULL) {
8577 pr_err("%s: APR handle NULL\n", __func__);
8578 return -EINVAL;
8579 }
8580 if (ac->apr == NULL) {
8581 pr_err("%s: AC APR handle NULL\n", __func__);
8582 return -EINVAL;
8583 }
8584
8585 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
8586
8587 /* Pass session id as token for AIO scheme */
8588 read.hdr.token = param->uid;
8589 read.hdr.opcode = ASM_DATA_CMD_READ_V2;
8590 read.buf_addr_lsw = lower_32_bits(param->paddr);
8591 read.buf_addr_msw = msm_audio_populate_upper_32_bits(param->paddr);
8592 read.buf_size = param->len;
8593 read.seq_id = param->uid;
8594 liomode = (NT_MODE | ASYNC_IO_MODE);
8595 io_compressed = (ASYNC_IO_MODE | COMPRESSED_IO);
8596 if (ac->io_mode == liomode) {
8597 lbuf_phys_addr = (param->paddr - 32);
8598 /*legacy wma driver case*/
8599 dir = IN;
8600 } else if (ac->io_mode == io_compressed) {
8601 lbuf_phys_addr = (param->paddr - 64);
8602 dir = OUT;
8603 } else {
8604 if (param->flags & COMPRESSED_TIMESTAMP_FLAG)
8605 lbuf_phys_addr = param->paddr -
8606 sizeof(struct snd_codec_metadata);
8607 else
8608 lbuf_phys_addr = param->paddr;
8609 dir = OUT;
8610 }
8611
8612 list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
8613 buf_node = list_entry(ptr, struct asm_buffer_node,
8614 list);
8615 if (buf_node->buf_phys_addr == lbuf_phys_addr) {
8616 read.mem_map_handle = buf_node->mmap_hdl;
8617 break;
8618 }
8619 }
8620
8621 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
8622 if (rc < 0) {
8623 pr_err("%s: read op[0x%x]rc[%d]\n", __func__,
8624 read.hdr.opcode, rc);
8625 goto fail_cmd;
8626 }
8627 return 0;
8628fail_cmd:
8629 return -EINVAL;
8630}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308631EXPORT_SYMBOL(q6asm_async_read);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308632
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308633/**
8634 * q6asm_write -
8635 * command to write buffer data to DSP
8636 *
8637 * @ac: Audio client handle
8638 * @len: buffer size
8639 * @msw_ts: upper 32bits of timestamp
8640 * @lsw_ts: lower 32bits of timestamp
8641 * @flags: Flags for timestamp mode
8642 *
8643 * Returns 0 on success or error on failure
8644 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308645int q6asm_write(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
8646 uint32_t lsw_ts, uint32_t flags)
8647{
8648 int rc = 0;
8649 struct asm_data_cmd_write_v2 write;
8650 struct asm_buffer_node *buf_node = NULL;
8651 struct audio_port_data *port;
8652 struct audio_buffer *ab;
8653 int dsp_buf = 0;
8654
8655 if (ac == NULL) {
8656 pr_err("%s: APR handle NULL\n", __func__);
8657 return -EINVAL;
8658 }
8659 if (ac->apr == NULL) {
8660 pr_err("%s: AC APR handle NULL\n", __func__);
8661 return -EINVAL;
8662 }
8663
8664 dev_vdbg(ac->dev, "%s: session[%d] len=%d\n",
8665 __func__, ac->session, len);
8666 if (ac->io_mode & SYNC_IO_MODE) {
8667 port = &ac->port[IN];
8668
8669 q6asm_add_hdr(ac, &write.hdr, sizeof(write),
8670 FALSE);
8671 mutex_lock(&port->lock);
8672
8673 dsp_buf = port->dsp_buf;
8674 ab = &port->buf[dsp_buf];
8675
8676 q6asm_update_token(&write.hdr.token,
8677 0, /* Session ID is NA */
8678 0, /* Stream ID is NA */
8679 port->dsp_buf,
8680 0, /* Direction flag is NA */
8681 NO_WAIT_CMD);
8682 write.hdr.opcode = ASM_DATA_CMD_WRITE_V2;
8683 write.buf_addr_lsw = lower_32_bits(ab->phys);
8684 write.buf_addr_msw = msm_audio_populate_upper_32_bits(ab->phys);
8685 write.buf_size = len;
8686 write.seq_id = port->dsp_buf;
8687 write.timestamp_lsw = lsw_ts;
8688 write.timestamp_msw = msw_ts;
8689 /* Use 0xFF00 for disabling timestamps */
8690 if (flags == 0xFF00)
8691 write.flags = (0x00000000 | (flags & 0x800000FF));
8692 else
8693 write.flags = (0x80000000 | flags);
8694 port->dsp_buf = q6asm_get_next_buf(ac, port->dsp_buf,
8695 port->max_buf_cnt);
8696 buf_node = list_first_entry(&ac->port[IN].mem_map_handle,
8697 struct asm_buffer_node,
8698 list);
8699 write.mem_map_handle = buf_node->mmap_hdl;
8700
8701 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]"
8702 , __func__,
8703 &ab->phys,
8704 write.buf_addr_lsw,
8705 write.hdr.token,
8706 write.seq_id,
8707 write.buf_size,
8708 write.mem_map_handle);
8709 mutex_unlock(&port->lock);
8710
8711 config_debug_fs_write(ab);
8712
8713 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
8714 if (rc < 0) {
8715 pr_err("%s: write op[0x%x]rc[%d]\n",
8716 __func__, write.hdr.opcode, rc);
8717 goto fail_cmd;
8718 }
8719 return 0;
8720 }
8721fail_cmd:
8722 return -EINVAL;
8723}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308724EXPORT_SYMBOL(q6asm_write);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308725
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308726/**
8727 * q6asm_write_nolock -
8728 * command to write buffer data to DSP
8729 * with no wait for ack.
8730 *
8731 * @ac: Audio client handle
8732 * @len: buffer size
8733 * @msw_ts: upper 32bits of timestamp
8734 * @lsw_ts: lower 32bits of timestamp
8735 * @flags: Flags for timestamp mode
8736 *
8737 * Returns 0 on success or error on failure
8738 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308739int q6asm_write_nolock(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
8740 uint32_t lsw_ts, uint32_t flags)
8741{
8742 int rc = 0;
8743 struct asm_data_cmd_write_v2 write;
8744 struct asm_buffer_node *buf_node = NULL;
8745 struct audio_port_data *port;
8746 struct audio_buffer *ab;
8747 int dsp_buf = 0;
8748
8749 if (ac == NULL) {
8750 pr_err("%s: APR handle NULL\n", __func__);
8751 return -EINVAL;
8752 }
8753 if (ac->apr == NULL) {
8754 pr_err("%s: AC APR handle NULL\n", __func__);
8755 return -EINVAL;
8756 }
8757
8758 dev_vdbg(ac->dev, "%s: session[%d] len=%d\n",
8759 __func__, ac->session, len);
8760 if (ac->io_mode & SYNC_IO_MODE) {
8761 port = &ac->port[IN];
8762
8763 q6asm_add_hdr_async(ac, &write.hdr, sizeof(write),
8764 FALSE);
8765
8766 dsp_buf = port->dsp_buf;
8767 ab = &port->buf[dsp_buf];
8768
8769 q6asm_update_token(&write.hdr.token,
8770 0, /* Session ID is NA */
8771 0, /* Stream ID is NA */
8772 port->dsp_buf,
8773 0, /* Direction flag is NA */
8774 NO_WAIT_CMD);
8775
8776 write.hdr.opcode = ASM_DATA_CMD_WRITE_V2;
8777 write.buf_addr_lsw = lower_32_bits(ab->phys);
8778 write.buf_addr_msw = msm_audio_populate_upper_32_bits(ab->phys);
8779 write.buf_size = len;
8780 write.seq_id = port->dsp_buf;
8781 write.timestamp_lsw = lsw_ts;
8782 write.timestamp_msw = msw_ts;
8783 buf_node = list_first_entry(&ac->port[IN].mem_map_handle,
8784 struct asm_buffer_node,
8785 list);
8786 write.mem_map_handle = buf_node->mmap_hdl;
8787 /* Use 0xFF00 for disabling timestamps */
8788 if (flags == 0xFF00)
8789 write.flags = (0x00000000 | (flags & 0x800000FF));
8790 else
8791 write.flags = (0x80000000 | flags);
8792 port->dsp_buf = q6asm_get_next_buf(ac, port->dsp_buf,
8793 port->max_buf_cnt);
8794
8795 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]"
8796 , __func__,
8797 &ab->phys,
8798 write.buf_addr_lsw,
8799 write.hdr.token,
8800 write.seq_id,
8801 write.buf_size,
8802 write.mem_map_handle);
8803
8804 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
8805 if (rc < 0) {
8806 pr_err("%s: write op[0x%x]rc[%d]\n",
8807 __func__, write.hdr.opcode, rc);
8808 goto fail_cmd;
8809 }
8810 return 0;
8811 }
8812fail_cmd:
8813 return -EINVAL;
8814}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308815EXPORT_SYMBOL(q6asm_write_nolock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308816
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308817/**
8818 * q6asm_get_session_time -
8819 * command to retrieve timestamp info
8820 *
8821 * @ac: Audio client handle
8822 * @tstamp: pointer to fill with timestamp info
8823 *
8824 * Returns 0 on success or error on failure
8825 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308826int q6asm_get_session_time(struct audio_client *ac, uint64_t *tstamp)
8827{
8828 struct asm_mtmx_strtr_get_params mtmx_params;
8829 int rc;
8830
8831 if (ac == NULL) {
8832 pr_err("%s: APR handle NULL\n", __func__);
8833 return -EINVAL;
8834 }
8835 if (ac->apr == NULL) {
8836 pr_err("%s: AC APR handle NULL\n", __func__);
8837 return -EINVAL;
8838 }
8839 if (tstamp == NULL) {
8840 pr_err("%s: tstamp NULL\n", __func__);
8841 return -EINVAL;
8842 }
8843
8844 q6asm_add_hdr(ac, &mtmx_params.hdr, sizeof(mtmx_params), TRUE);
8845 mtmx_params.hdr.opcode = ASM_SESSION_CMD_GET_MTMX_STRTR_PARAMS_V2;
8846 mtmx_params.param_info.data_payload_addr_lsw = 0;
8847 mtmx_params.param_info.data_payload_addr_msw = 0;
8848 mtmx_params.param_info.mem_map_handle = 0;
8849 mtmx_params.param_info.direction = (ac->io_mode & TUN_READ_IO_MODE
8850 ? 1 : 0);
8851 mtmx_params.param_info.module_id =
8852 ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
8853 mtmx_params.param_info.param_id =
8854 ASM_SESSION_MTMX_STRTR_PARAM_SESSION_TIME_V3;
8855 mtmx_params.param_info.param_max_size =
8856 sizeof(struct asm_stream_param_data_v2) +
8857 sizeof(struct asm_session_mtmx_strtr_param_session_time_v3_t);
8858 atomic_set(&ac->time_flag, 1);
8859
8860 dev_vdbg(ac->dev, "%s: session[%d]opcode[0x%x]\n", __func__,
8861 ac->session, mtmx_params.hdr.opcode);
8862 rc = apr_send_pkt(ac->apr, (uint32_t *) &mtmx_params);
8863 if (rc < 0) {
8864 pr_err("%s: Commmand 0x%x failed %d\n", __func__,
8865 mtmx_params.hdr.opcode, rc);
8866 goto fail_cmd;
8867 }
8868 rc = wait_event_timeout(ac->time_wait,
8869 (atomic_read(&ac->time_flag) == 0), 5*HZ);
8870 if (!rc) {
8871 pr_err("%s: timeout in getting session time from DSP\n",
8872 __func__);
8873 goto fail_cmd;
8874 }
8875
8876 *tstamp = ac->time_stamp;
8877 return 0;
8878
8879fail_cmd:
8880 return -EINVAL;
8881}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308882EXPORT_SYMBOL(q6asm_get_session_time);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308883
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308884/**
8885 * q6asm_get_session_time_legacy -
8886 * command to retrieve timestamp info
8887 *
8888 * @ac: Audio client handle
8889 * @tstamp: pointer to fill with timestamp info
8890 *
8891 * Returns 0 on success or error on failure
8892 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308893int q6asm_get_session_time_legacy(struct audio_client *ac, uint64_t *tstamp)
8894{
8895 struct apr_hdr hdr;
8896 int rc;
8897
8898 if (ac == NULL) {
8899 pr_err("%s: APR handle NULL\n", __func__);
8900 return -EINVAL;
8901 }
8902 if (ac->apr == NULL) {
8903 pr_err("%s: AC APR handle NULL\n", __func__);
8904 return -EINVAL;
8905 }
8906 if (tstamp == NULL) {
8907 pr_err("%s: tstamp NULL\n", __func__);
8908 return -EINVAL;
8909 }
8910
8911 q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
8912 hdr.opcode = ASM_SESSION_CMD_GET_SESSIONTIME_V3;
8913 atomic_set(&ac->time_flag, 1);
8914
8915 dev_vdbg(ac->dev, "%s: session[%d]opcode[0x%x]\n", __func__,
8916 ac->session,
8917 hdr.opcode);
8918 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
8919 if (rc < 0) {
8920 pr_err("%s: Commmand 0x%x failed %d\n",
8921 __func__, hdr.opcode, rc);
8922 goto fail_cmd;
8923 }
8924 rc = wait_event_timeout(ac->time_wait,
8925 (atomic_read(&ac->time_flag) == 0), 5*HZ);
8926 if (!rc) {
8927 pr_err("%s: timeout in getting session time from DSP\n",
8928 __func__);
8929 goto fail_cmd;
8930 }
8931
8932 *tstamp = ac->time_stamp;
8933 return 0;
8934
8935fail_cmd:
8936 return -EINVAL;
8937}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308938EXPORT_SYMBOL(q6asm_get_session_time_legacy);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308939
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308940/**
8941 * q6asm_send_audio_effects_params -
8942 * command to send audio effects params
8943 *
8944 * @ac: Audio client handle
8945 * @params: audio effects params
8946 * @params_length: size of params
8947 *
8948 * Returns 0 on success or error on failure
8949 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308950int q6asm_send_audio_effects_params(struct audio_client *ac, char *params,
8951 uint32_t params_length)
8952{
8953 char *asm_params = NULL;
8954 struct apr_hdr hdr;
8955 struct asm_stream_cmd_set_pp_params_v2 payload_params;
8956 int sz, rc;
8957
8958 pr_debug("%s:\n", __func__);
8959 if (!ac) {
8960 pr_err("%s: APR handle NULL\n", __func__);
8961 return -EINVAL;
8962 }
8963 if (ac->apr == NULL) {
8964 pr_err("%s: AC APR handle NULL\n", __func__);
8965 return -EINVAL;
8966 }
8967 if (params == NULL) {
8968 pr_err("%s: params NULL\n", __func__);
8969 return -EINVAL;
8970 }
8971 sz = sizeof(struct apr_hdr) +
8972 sizeof(struct asm_stream_cmd_set_pp_params_v2) +
8973 params_length;
8974 asm_params = kzalloc(sz, GFP_KERNEL);
8975 if (!asm_params) {
8976 pr_err("%s, asm params memory alloc failed", __func__);
8977 return -ENOMEM;
8978 }
8979 q6asm_add_hdr_async(ac, &hdr, (sizeof(struct apr_hdr) +
8980 sizeof(struct asm_stream_cmd_set_pp_params_v2) +
8981 params_length), TRUE);
8982 atomic_set(&ac->cmd_state_pp, -1);
8983 hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
8984 payload_params.data_payload_addr_lsw = 0;
8985 payload_params.data_payload_addr_msw = 0;
8986 payload_params.mem_map_handle = 0;
8987 payload_params.data_payload_size = params_length;
8988 memcpy(((u8 *)asm_params), &hdr, sizeof(struct apr_hdr));
8989 memcpy(((u8 *)asm_params + sizeof(struct apr_hdr)), &payload_params,
8990 sizeof(struct asm_stream_cmd_set_pp_params_v2));
8991 memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) +
8992 sizeof(struct asm_stream_cmd_set_pp_params_v2)),
8993 params, params_length);
8994 rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
8995 if (rc < 0) {
8996 pr_err("%s: audio effects set-params send failed\n", __func__);
8997 rc = -EINVAL;
8998 goto fail_send_param;
8999 }
9000 rc = wait_event_timeout(ac->cmd_wait,
9001 (atomic_read(&ac->cmd_state_pp) >= 0), 1*HZ);
9002 if (!rc) {
9003 pr_err("%s: timeout, audio effects set-params\n", __func__);
9004 rc = -ETIMEDOUT;
9005 goto fail_send_param;
9006 }
9007 if (atomic_read(&ac->cmd_state_pp) > 0) {
9008 pr_err("%s: DSP returned error[%s] set-params\n",
9009 __func__, adsp_err_get_err_str(
9010 atomic_read(&ac->cmd_state_pp)));
9011 rc = adsp_err_get_lnx_err_code(
9012 atomic_read(&ac->cmd_state_pp));
9013 goto fail_send_param;
9014 }
9015
9016 rc = 0;
9017fail_send_param:
9018 kfree(asm_params);
9019 return rc;
9020}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309021EXPORT_SYMBOL(q6asm_send_audio_effects_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309022
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309023/**
9024 * q6asm_send_mtmx_strtr_window -
9025 * command to send matrix for window params
9026 *
9027 * @ac: Audio client handle
9028 * @window_param: window params
9029 * @param_id: param id for window
9030 *
9031 * Returns 0 on success or error on failure
9032 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309033int q6asm_send_mtmx_strtr_window(struct audio_client *ac,
9034 struct asm_session_mtmx_strtr_param_window_v2_t *window_param,
9035 uint32_t param_id)
9036{
9037 struct asm_mtmx_strtr_params matrix;
9038 int sz = 0;
9039 int rc = 0;
9040
9041 pr_debug("%s: Window lsw is %d, window msw is %d\n", __func__,
9042 window_param->window_lsw, window_param->window_msw);
9043
9044 if (!ac) {
9045 pr_err("%s: audio client handle is NULL\n", __func__);
9046 rc = -EINVAL;
9047 goto fail_cmd;
9048 }
9049
9050 if (ac->apr == NULL) {
9051 pr_err("%s: ac->apr is NULL", __func__);
9052 rc = -EINVAL;
9053 goto fail_cmd;
9054 }
9055
9056 sz = sizeof(struct asm_mtmx_strtr_params);
9057 q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE);
9058 atomic_set(&ac->cmd_state, -1);
9059 matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2;
9060
9061 matrix.param.data_payload_addr_lsw = 0;
9062 matrix.param.data_payload_addr_msw = 0;
9063 matrix.param.mem_map_handle = 0;
9064 matrix.param.data_payload_size =
9065 sizeof(struct asm_stream_param_data_v2) +
9066 sizeof(struct asm_session_mtmx_strtr_param_window_v2_t);
9067 matrix.param.direction = 0; /* RX */
9068 matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
9069 matrix.data.param_id = param_id;
9070 matrix.data.param_size =
9071 sizeof(struct asm_session_mtmx_strtr_param_window_v2_t);
9072 matrix.data.reserved = 0;
9073 memcpy(&(matrix.config.window_param),
9074 window_param,
9075 sizeof(struct asm_session_mtmx_strtr_param_window_v2_t));
9076
9077 rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
9078 if (rc < 0) {
9079 pr_err("%s: Render window start send failed paramid [0x%x]\n",
9080 __func__, matrix.data.param_id);
9081 rc = -EINVAL;
9082 goto fail_cmd;
9083 }
9084
9085 rc = wait_event_timeout(ac->cmd_wait,
9086 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
9087 if (!rc) {
9088 pr_err("%s: timeout, Render window start paramid[0x%x]\n",
9089 __func__, matrix.data.param_id);
9090 rc = -ETIMEDOUT;
9091 goto fail_cmd;
9092 }
9093
9094 if (atomic_read(&ac->cmd_state) > 0) {
9095 pr_err("%s: DSP returned error[%s]\n",
9096 __func__, adsp_err_get_err_str(
9097 atomic_read(&ac->cmd_state)));
9098 rc = adsp_err_get_lnx_err_code(
9099 atomic_read(&ac->cmd_state));
9100 goto fail_cmd;
9101 }
9102 rc = 0;
9103fail_cmd:
9104 return rc;
9105}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309106EXPORT_SYMBOL(q6asm_send_mtmx_strtr_window);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309107
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309108/**
9109 * q6asm_send_mtmx_strtr_render_mode -
9110 * command to send matrix for render mode
9111 *
9112 * @ac: Audio client handle
9113 * @render_mode: rendering mode
9114 *
9115 * Returns 0 on success or error on failure
9116 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309117int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac,
9118 uint32_t render_mode)
9119{
9120 struct asm_mtmx_strtr_params matrix;
9121 struct asm_session_mtmx_strtr_param_render_mode_t render_param;
9122 int sz = 0;
9123 int rc = 0;
9124
9125 pr_debug("%s: render mode is %d\n", __func__, render_mode);
9126
9127 if (!ac) {
9128 pr_err("%s: audio client handle is NULL\n", __func__);
9129 rc = -EINVAL;
9130 goto exit;
9131 }
9132
9133 if (ac->apr == NULL) {
9134 pr_err("%s: ac->apr is NULL\n", __func__);
9135 rc = -EINVAL;
9136 goto exit;
9137 }
9138
9139 if ((render_mode != ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT) &&
9140 (render_mode != ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC)) {
9141 pr_err("%s: Invalid render mode %d\n", __func__, render_mode);
9142 rc = -EINVAL;
9143 goto exit;
9144 }
9145
9146 memset(&render_param, 0,
9147 sizeof(struct asm_session_mtmx_strtr_param_render_mode_t));
9148 render_param.flags = render_mode;
9149
9150 memset(&matrix, 0, sizeof(struct asm_mtmx_strtr_params));
9151 sz = sizeof(struct asm_mtmx_strtr_params);
9152 q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE);
9153 atomic_set(&ac->cmd_state, -1);
9154 matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2;
9155
9156 matrix.param.data_payload_addr_lsw = 0;
9157 matrix.param.data_payload_addr_msw = 0;
9158 matrix.param.mem_map_handle = 0;
9159 matrix.param.data_payload_size =
9160 sizeof(struct asm_stream_param_data_v2) +
9161 sizeof(struct asm_session_mtmx_strtr_param_render_mode_t);
9162 matrix.param.direction = 0; /* RX */
9163 matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
9164 matrix.data.param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_MODE_CMD;
9165 matrix.data.param_size =
9166 sizeof(struct asm_session_mtmx_strtr_param_render_mode_t);
9167 matrix.data.reserved = 0;
9168 memcpy(&(matrix.config.render_param),
9169 &render_param,
9170 sizeof(struct asm_session_mtmx_strtr_param_render_mode_t));
9171
9172 rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
9173 if (rc < 0) {
9174 pr_err("%s: Render mode send failed paramid [0x%x]\n",
9175 __func__, matrix.data.param_id);
9176 rc = -EINVAL;
9177 goto exit;
9178 }
9179
9180 rc = wait_event_timeout(ac->cmd_wait,
9181 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
9182 if (!rc) {
9183 pr_err("%s: timeout, Render mode send paramid [0x%x]\n",
9184 __func__, matrix.data.param_id);
9185 rc = -ETIMEDOUT;
9186 goto exit;
9187 }
9188
9189 if (atomic_read(&ac->cmd_state) > 0) {
9190 pr_err("%s: DSP returned error[%s]\n",
9191 __func__, adsp_err_get_err_str(
9192 atomic_read(&ac->cmd_state)));
9193 rc = adsp_err_get_lnx_err_code(
9194 atomic_read(&ac->cmd_state));
9195 goto exit;
9196 }
9197 rc = 0;
9198exit:
9199 return rc;
9200}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309201EXPORT_SYMBOL(q6asm_send_mtmx_strtr_render_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309202
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309203/**
9204 * q6asm_send_mtmx_strtr_clk_rec_mode -
9205 * command to send matrix for clock rec
9206 *
9207 * @ac: Audio client handle
9208 * @clk_rec_mode: mode for clock rec
9209 *
9210 * Returns 0 on success or error on failure
9211 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309212int q6asm_send_mtmx_strtr_clk_rec_mode(struct audio_client *ac,
9213 uint32_t clk_rec_mode)
9214{
9215 struct asm_mtmx_strtr_params matrix;
9216 struct asm_session_mtmx_strtr_param_clk_rec_t clk_rec_param;
9217 int sz = 0;
9218 int rc = 0;
9219
9220 pr_debug("%s: clk rec mode is %d\n", __func__, clk_rec_mode);
9221
9222 if (!ac) {
9223 pr_err("%s: audio client handle is NULL\n", __func__);
9224 rc = -EINVAL;
9225 goto exit;
9226 }
9227
9228 if (ac->apr == NULL) {
9229 pr_err("%s: ac->apr is NULL\n", __func__);
9230 rc = -EINVAL;
9231 goto exit;
9232 }
9233
9234 if ((clk_rec_mode != ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_NONE) &&
9235 (clk_rec_mode != ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_AUTO)) {
9236 pr_err("%s: Invalid clk rec mode %d\n", __func__, clk_rec_mode);
9237 rc = -EINVAL;
9238 goto exit;
9239 }
9240
9241 memset(&clk_rec_param, 0,
9242 sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t));
9243 clk_rec_param.flags = clk_rec_mode;
9244
9245 memset(&matrix, 0, sizeof(struct asm_mtmx_strtr_params));
9246 sz = sizeof(struct asm_mtmx_strtr_params);
9247 q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE);
9248 atomic_set(&ac->cmd_state, -1);
9249 matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2;
9250
9251 matrix.param.data_payload_addr_lsw = 0;
9252 matrix.param.data_payload_addr_msw = 0;
9253 matrix.param.mem_map_handle = 0;
9254 matrix.param.data_payload_size =
9255 sizeof(struct asm_stream_param_data_v2) +
9256 sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t);
9257 matrix.param.direction = 0; /* RX */
9258 matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
9259 matrix.data.param_id = ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_CMD;
9260 matrix.data.param_size =
9261 sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t);
9262 matrix.data.reserved = 0;
9263 memcpy(&(matrix.config.clk_rec_param),
9264 &clk_rec_param,
9265 sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t));
9266
9267 rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
9268 if (rc < 0) {
9269 pr_err("%s: clk rec mode send failed paramid [0x%x]\n",
9270 __func__, matrix.data.param_id);
9271 rc = -EINVAL;
9272 goto exit;
9273 }
9274
9275 rc = wait_event_timeout(ac->cmd_wait,
9276 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
9277 if (!rc) {
9278 pr_err("%s: timeout, clk rec mode send paramid [0x%x]\n",
9279 __func__, matrix.data.param_id);
9280 rc = -ETIMEDOUT;
9281 goto exit;
9282 }
9283
9284 if (atomic_read(&ac->cmd_state) > 0) {
9285 pr_err("%s: DSP returned error[%s]\n",
9286 __func__, adsp_err_get_err_str(
9287 atomic_read(&ac->cmd_state)));
9288 rc = adsp_err_get_lnx_err_code(
9289 atomic_read(&ac->cmd_state));
9290 goto exit;
9291 }
9292 rc = 0;
9293exit:
9294 return rc;
9295}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309296EXPORT_SYMBOL(q6asm_send_mtmx_strtr_clk_rec_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309297
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309298/**
9299 * q6asm_send_mtmx_strtr_enable_adjust_session_clock -
9300 * command to send matrix for adjust time
9301 *
9302 * @ac: Audio client handle
9303 * @enable: flag to adjust time or not
9304 *
9305 * Returns 0 on success or error on failure
9306 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309307int q6asm_send_mtmx_strtr_enable_adjust_session_clock(struct audio_client *ac,
9308 bool enable)
9309{
9310 struct asm_mtmx_strtr_params matrix;
9311 struct asm_session_mtmx_param_adjust_session_time_ctl_t adjust_time;
9312 int sz = 0;
9313 int rc = 0;
9314
9315 pr_debug("%s: adjust session enable %d\n", __func__, enable);
9316
9317 if (!ac) {
9318 pr_err("%s: audio client handle is NULL\n", __func__);
9319 rc = -EINVAL;
9320 goto exit;
9321 }
9322
9323 if (ac->apr == NULL) {
9324 pr_err("%s: ac->apr is NULL\n", __func__);
9325 rc = -EINVAL;
9326 goto exit;
9327 }
9328
9329 adjust_time.enable = enable;
9330 memset(&matrix, 0, sizeof(struct asm_mtmx_strtr_params));
9331 sz = sizeof(struct asm_mtmx_strtr_params);
9332 q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE);
9333 atomic_set(&ac->cmd_state, -1);
9334 matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2;
9335
9336 matrix.param.data_payload_addr_lsw = 0;
9337 matrix.param.data_payload_addr_msw = 0;
9338 matrix.param.mem_map_handle = 0;
9339 matrix.param.data_payload_size =
9340 sizeof(struct asm_stream_param_data_v2) +
9341 sizeof(struct asm_session_mtmx_param_adjust_session_time_ctl_t);
9342 matrix.param.direction = 0; /* RX */
9343 matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
9344 matrix.data.param_id = ASM_SESSION_MTMX_PARAM_ADJUST_SESSION_TIME_CTL;
9345 matrix.data.param_size =
9346 sizeof(struct asm_session_mtmx_param_adjust_session_time_ctl_t);
9347 matrix.data.reserved = 0;
9348 matrix.config.adj_time_param.enable = adjust_time.enable;
9349
9350 rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
9351 if (rc < 0) {
9352 pr_err("%s: enable adjust session failed failed paramid [0x%x]\n",
9353 __func__, matrix.data.param_id);
9354 rc = -EINVAL;
9355 goto exit;
9356 }
9357
9358 rc = wait_event_timeout(ac->cmd_wait,
9359 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
9360 if (!rc) {
9361 pr_err("%s: enable adjust session failed failed paramid [0x%x]\n",
9362 __func__, matrix.data.param_id);
9363 rc = -ETIMEDOUT;
9364 goto exit;
9365 }
9366
9367 if (atomic_read(&ac->cmd_state) > 0) {
9368 pr_err("%s: DSP returned error[%s]\n",
9369 __func__, adsp_err_get_err_str(
9370 atomic_read(&ac->cmd_state)));
9371 rc = adsp_err_get_lnx_err_code(
9372 atomic_read(&ac->cmd_state));
9373 goto exit;
9374 }
9375 rc = 0;
9376exit:
9377 return rc;
9378}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309379EXPORT_SYMBOL(q6asm_send_mtmx_strtr_enable_adjust_session_clock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309380
9381
9382static int __q6asm_cmd(struct audio_client *ac, int cmd, uint32_t stream_id)
9383{
9384 struct apr_hdr hdr;
9385 int rc;
9386 atomic_t *state;
9387 int cnt = 0;
9388
9389 if (!ac) {
9390 pr_err("%s: APR handle NULL\n", __func__);
9391 return -EINVAL;
9392 }
9393 if (ac->apr == NULL) {
9394 pr_err("%s: AC APR handle NULL\n", __func__);
9395 return -EINVAL;
9396 }
9397 q6asm_stream_add_hdr(ac, &hdr, sizeof(hdr), TRUE, stream_id);
9398 atomic_set(&ac->cmd_state, -1);
9399 /*
9400 * Updated the token field with stream/session for compressed playback
9401 * Platform driver must know the the stream with which the command is
9402 * associated
9403 */
9404 if (ac->io_mode & COMPRESSED_STREAM_IO)
9405 q6asm_update_token(&hdr.token,
9406 ac->session,
9407 stream_id,
9408 0, /* Buffer index is NA */
9409 0, /* Direction flag is NA */
9410 WAIT_CMD);
9411 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
9412 __func__, hdr.token, stream_id, ac->session);
9413 switch (cmd) {
9414 case CMD_PAUSE:
9415 pr_debug("%s: CMD_PAUSE\n", __func__);
9416 hdr.opcode = ASM_SESSION_CMD_PAUSE;
9417 state = &ac->cmd_state;
9418 break;
9419 case CMD_SUSPEND:
9420 pr_debug("%s: CMD_SUSPEND\n", __func__);
9421 hdr.opcode = ASM_SESSION_CMD_SUSPEND;
9422 state = &ac->cmd_state;
9423 break;
9424 case CMD_FLUSH:
9425 pr_debug("%s: CMD_FLUSH\n", __func__);
9426 hdr.opcode = ASM_STREAM_CMD_FLUSH;
9427 state = &ac->cmd_state;
9428 break;
9429 case CMD_OUT_FLUSH:
9430 pr_debug("%s: CMD_OUT_FLUSH\n", __func__);
9431 hdr.opcode = ASM_STREAM_CMD_FLUSH_READBUFS;
9432 state = &ac->cmd_state;
9433 break;
9434 case CMD_EOS:
9435 pr_debug("%s: CMD_EOS\n", __func__);
9436 hdr.opcode = ASM_DATA_CMD_EOS;
9437 atomic_set(&ac->cmd_state, 0);
9438 state = &ac->cmd_state;
9439 break;
9440 case CMD_CLOSE:
9441 pr_debug("%s: CMD_CLOSE\n", __func__);
9442 hdr.opcode = ASM_STREAM_CMD_CLOSE;
9443 state = &ac->cmd_state;
9444 break;
9445 default:
9446 pr_err("%s: Invalid format[%d]\n", __func__, cmd);
9447 rc = -EINVAL;
9448 goto fail_cmd;
9449 }
9450 pr_debug("%s: session[%d]opcode[0x%x]\n", __func__,
9451 ac->session,
9452 hdr.opcode);
9453 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
9454 if (rc < 0) {
9455 pr_err("%s: Commmand 0x%x failed %d\n",
9456 __func__, hdr.opcode, rc);
9457 rc = -EINVAL;
9458 goto fail_cmd;
9459 }
9460 rc = wait_event_timeout(ac->cmd_wait, (atomic_read(state) >= 0), 5*HZ);
9461 if (!rc) {
9462 pr_err("%s: timeout. waited for response opcode[0x%x]\n",
9463 __func__, hdr.opcode);
9464 rc = -ETIMEDOUT;
9465 goto fail_cmd;
9466 }
9467 if (atomic_read(state) > 0) {
9468 pr_err("%s: DSP returned error[%s] opcode %d\n",
9469 __func__, adsp_err_get_err_str(
9470 atomic_read(state)),
9471 hdr.opcode);
9472 rc = adsp_err_get_lnx_err_code(atomic_read(state));
9473 goto fail_cmd;
9474 }
9475
9476 if (cmd == CMD_FLUSH)
9477 q6asm_reset_buf_state(ac);
9478 if (cmd == CMD_CLOSE) {
9479 /* check if DSP return all buffers */
9480 if (ac->port[IN].buf) {
9481 for (cnt = 0; cnt < ac->port[IN].max_buf_cnt;
9482 cnt++) {
9483 if (ac->port[IN].buf[cnt].used == IN) {
9484 dev_vdbg(ac->dev, "Write Buf[%d] not returned\n",
9485 cnt);
9486 }
9487 }
9488 }
9489 if (ac->port[OUT].buf) {
9490 for (cnt = 0; cnt < ac->port[OUT].max_buf_cnt; cnt++) {
9491 if (ac->port[OUT].buf[cnt].used == OUT) {
9492 dev_vdbg(ac->dev, "Read Buf[%d] not returned\n",
9493 cnt);
9494 }
9495 }
9496 }
9497 }
9498 return 0;
9499fail_cmd:
9500 return rc;
9501}
9502
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309503/**
9504 * q6asm_cmd -
9505 * Function used to send commands for
9506 * ASM with wait for ack.
9507 *
9508 * @ac: Audio client handle
9509 * @cmd: command to send
9510 *
9511 * Returns 0 on success or error on failure
9512 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309513int q6asm_cmd(struct audio_client *ac, int cmd)
9514{
9515 return __q6asm_cmd(ac, cmd, ac->stream_id);
9516}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309517EXPORT_SYMBOL(q6asm_cmd);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309518
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309519/**
9520 * q6asm_stream_cmd -
9521 * Function used to send commands for
9522 * ASM stream with wait for ack.
9523 *
9524 * @ac: Audio client handle
9525 * @cmd: command to send
9526 * @stream_id: Stream ID
9527 *
9528 * Returns 0 on success or error on failure
9529 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309530int q6asm_stream_cmd(struct audio_client *ac, int cmd, uint32_t stream_id)
9531{
9532 return __q6asm_cmd(ac, cmd, stream_id);
9533}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309534EXPORT_SYMBOL(q6asm_stream_cmd);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309535
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309536/**
9537 * q6asm_cmd_nowait -
9538 * Function used to send commands for
9539 * ASM stream without wait for ack.
9540 *
9541 * @ac: Audio client handle
9542 * @cmd: command to send
9543 * @stream_id: Stream ID
9544 *
9545 * Returns 0 on success or error on failure
9546 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309547static int __q6asm_cmd_nowait(struct audio_client *ac, int cmd,
9548 uint32_t stream_id)
9549{
9550 struct apr_hdr hdr;
9551 int rc;
9552
9553 if (!ac) {
9554 pr_err("%s: APR handle NULL\n", __func__);
9555 return -EINVAL;
9556 }
9557 if (ac->apr == NULL) {
9558 pr_err("%s: AC APR handle NULL\n", __func__);
9559 return -EINVAL;
9560 }
9561 q6asm_stream_add_hdr_async(ac, &hdr, sizeof(hdr), TRUE, stream_id);
9562 atomic_set(&ac->cmd_state, 1);
9563 /*
9564 * Updated the token field with stream/session for compressed playback
9565 * Platform driver must know the the stream with which the command is
9566 * associated
9567 */
9568 if (ac->io_mode & COMPRESSED_STREAM_IO)
9569 q6asm_update_token(&hdr.token,
9570 ac->session,
9571 stream_id,
9572 0, /* Buffer index is NA */
9573 0, /* Direction flag is NA */
9574 NO_WAIT_CMD);
9575
9576 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
9577 __func__, hdr.token, stream_id, ac->session);
9578 switch (cmd) {
9579 case CMD_PAUSE:
9580 pr_debug("%s: CMD_PAUSE\n", __func__);
9581 hdr.opcode = ASM_SESSION_CMD_PAUSE;
9582 break;
9583 case CMD_EOS:
9584 pr_debug("%s: CMD_EOS\n", __func__);
9585 hdr.opcode = ASM_DATA_CMD_EOS;
9586 break;
9587 case CMD_CLOSE:
9588 pr_debug("%s: CMD_CLOSE\n", __func__);
9589 hdr.opcode = ASM_STREAM_CMD_CLOSE;
9590 break;
9591 default:
9592 pr_err("%s: Invalid format[%d]\n", __func__, cmd);
9593 goto fail_cmd;
9594 }
9595 pr_debug("%s: session[%d]opcode[0x%x]\n", __func__,
9596 ac->session,
9597 hdr.opcode);
9598
9599 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
9600 if (rc < 0) {
9601 pr_err("%s: Commmand 0x%x failed %d\n",
9602 __func__, hdr.opcode, rc);
9603 goto fail_cmd;
9604 }
9605 return 0;
9606fail_cmd:
9607 return -EINVAL;
9608}
9609
9610int q6asm_cmd_nowait(struct audio_client *ac, int cmd)
9611{
9612 pr_debug("%s: stream_id: %d\n", __func__, ac->stream_id);
9613 return __q6asm_cmd_nowait(ac, cmd, ac->stream_id);
9614}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309615EXPORT_SYMBOL(q6asm_cmd_nowait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309616
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309617/**
9618 * q6asm_stream_cmd_nowait -
9619 * Function used to send commands for
9620 * ASM stream without wait for ack.
9621 *
9622 * @ac: Audio client handle
9623 * @cmd: command to send
9624 * @stream_id: Stream ID
9625 *
9626 * Returns 0 on success or error on failure
9627 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309628int q6asm_stream_cmd_nowait(struct audio_client *ac, int cmd,
9629 uint32_t stream_id)
9630{
9631 pr_debug("%s: stream_id: %d\n", __func__, stream_id);
9632 return __q6asm_cmd_nowait(ac, cmd, stream_id);
9633}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309634EXPORT_SYMBOL(q6asm_stream_cmd_nowait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309635
9636int __q6asm_send_meta_data(struct audio_client *ac, uint32_t stream_id,
9637 uint32_t initial_samples, uint32_t trailing_samples)
9638{
9639 struct asm_data_cmd_remove_silence silence;
9640 int rc = 0;
9641
9642 if (!ac) {
9643 pr_err("%s: APR handle NULL\n", __func__);
9644 return -EINVAL;
9645 }
9646 if (ac->apr == NULL) {
9647 pr_err("%s: AC APR handle NULL\n", __func__);
9648 return -EINVAL;
9649 }
9650 pr_debug("%s: session[%d]\n", __func__, ac->session);
9651 q6asm_stream_add_hdr_async(ac, &silence.hdr, sizeof(silence), TRUE,
9652 stream_id);
9653
9654 /*
9655 * Updated the token field with stream/session for compressed playback
9656 * Platform driver must know the the stream with which the command is
9657 * associated
9658 */
9659 if (ac->io_mode & COMPRESSED_STREAM_IO)
9660 q6asm_update_token(&silence.hdr.token,
9661 ac->session,
9662 stream_id,
9663 0, /* Buffer index is NA */
9664 0, /* Direction flag is NA */
9665 NO_WAIT_CMD);
9666 pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
9667 __func__, silence.hdr.token, stream_id, ac->session);
9668
9669 silence.hdr.opcode = ASM_DATA_CMD_REMOVE_INITIAL_SILENCE;
9670 silence.num_samples_to_remove = initial_samples;
9671
9672 rc = apr_send_pkt(ac->apr, (uint32_t *) &silence);
9673 if (rc < 0) {
9674 pr_err("%s: Commmand silence failed[%d]", __func__, rc);
9675
9676 goto fail_cmd;
9677 }
9678
9679 silence.hdr.opcode = ASM_DATA_CMD_REMOVE_TRAILING_SILENCE;
9680 silence.num_samples_to_remove = trailing_samples;
9681
9682
9683 rc = apr_send_pkt(ac->apr, (uint32_t *) &silence);
9684 if (rc < 0) {
9685 pr_err("%s: Commmand silence failed[%d]", __func__, rc);
9686 goto fail_cmd;
9687 }
9688
9689 return 0;
9690fail_cmd:
9691 return -EINVAL;
9692}
9693
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309694/**
9695 * q6asm_stream_send_meta_data -
9696 * command to send meta data for stream
9697 *
9698 * @ac: Audio client handle
9699 * @stream_id: Stream ID
9700 * @initial_samples: Initial samples of stream
9701 * @trailing_samples: Trailing samples of stream
9702 *
9703 * Returns 0 on success or error on failure
9704 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309705int q6asm_stream_send_meta_data(struct audio_client *ac, uint32_t stream_id,
9706 uint32_t initial_samples, uint32_t trailing_samples)
9707{
9708 return __q6asm_send_meta_data(ac, stream_id, initial_samples,
9709 trailing_samples);
9710}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309711EXPORT_SYMBOL(q6asm_stream_send_meta_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309712
9713int q6asm_send_meta_data(struct audio_client *ac, uint32_t initial_samples,
9714 uint32_t trailing_samples)
9715{
9716 return __q6asm_send_meta_data(ac, ac->stream_id, initial_samples,
9717 trailing_samples);
9718}
9719
9720static void q6asm_reset_buf_state(struct audio_client *ac)
9721{
9722 int cnt = 0;
9723 int loopcnt = 0;
9724 int used;
9725 struct audio_port_data *port = NULL;
9726
9727 if (ac->io_mode & SYNC_IO_MODE) {
9728 used = (ac->io_mode & TUN_WRITE_IO_MODE ? 1 : 0);
9729 mutex_lock(&ac->cmd_lock);
9730 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
9731 port = &ac->port[loopcnt];
9732 cnt = port->max_buf_cnt - 1;
9733 port->dsp_buf = 0;
9734 port->cpu_buf = 0;
9735 while (cnt >= 0) {
9736 if (!port->buf)
9737 continue;
9738 port->buf[cnt].used = used;
9739 cnt--;
9740 }
9741 }
9742 mutex_unlock(&ac->cmd_lock);
9743 }
9744}
9745
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309746/**
9747 * q6asm_reg_tx_overflow -
9748 * command to register for TX overflow events
9749 *
9750 * @ac: Audio client handle
9751 * @enable: flag to enable or disable events
9752 *
9753 * Returns 0 on success or error on failure
9754 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309755int q6asm_reg_tx_overflow(struct audio_client *ac, uint16_t enable)
9756{
9757 struct asm_session_cmd_regx_overflow tx_overflow;
9758 int rc;
9759
9760 if (!ac) {
9761 pr_err("%s: APR handle NULL\n", __func__);
9762 return -EINVAL;
9763 }
9764 if (ac->apr == NULL) {
9765 pr_err("%s: AC APR handle NULL\n", __func__);
9766 return -EINVAL;
9767 }
9768 pr_debug("%s: session[%d]enable[%d]\n", __func__,
9769 ac->session, enable);
9770 q6asm_add_hdr(ac, &tx_overflow.hdr, sizeof(tx_overflow), TRUE);
9771 atomic_set(&ac->cmd_state, -1);
9772
9773 tx_overflow.hdr.opcode =
9774 ASM_SESSION_CMD_REGISTER_FORX_OVERFLOW_EVENTS;
9775 /* tx overflow event: enable */
9776 tx_overflow.enable_flag = enable;
9777
9778 rc = apr_send_pkt(ac->apr, (uint32_t *) &tx_overflow);
9779 if (rc < 0) {
9780 pr_err("%s: tx overflow op[0x%x]rc[%d]\n",
9781 __func__, tx_overflow.hdr.opcode, rc);
9782 rc = -EINVAL;
9783 goto fail_cmd;
9784 }
9785 rc = wait_event_timeout(ac->cmd_wait,
9786 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
9787 if (!rc) {
9788 pr_err("%s: timeout. waited for tx overflow\n", __func__);
9789 rc = -ETIMEDOUT;
9790 goto fail_cmd;
9791 }
9792 if (atomic_read(&ac->cmd_state) > 0) {
9793 pr_err("%s: DSP returned error[%s]\n",
9794 __func__, adsp_err_get_err_str(
9795 atomic_read(&ac->cmd_state)));
9796 rc = adsp_err_get_lnx_err_code(
9797 atomic_read(&ac->cmd_state));
9798 goto fail_cmd;
9799 }
9800
9801 return 0;
9802fail_cmd:
9803 return rc;
9804}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309805EXPORT_SYMBOL(q6asm_reg_tx_overflow);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309806
9807int q6asm_reg_rx_underflow(struct audio_client *ac, uint16_t enable)
9808{
9809 struct asm_session_cmd_rgstr_rx_underflow rx_underflow;
9810 int rc;
9811
9812 if (!ac) {
9813 pr_err("%s: AC APR handle NULL\n", __func__);
9814 return -EINVAL;
9815 }
9816 if (ac->apr == NULL) {
9817 pr_err("%s: APR handle NULL\n", __func__);
9818 return -EINVAL;
9819 }
9820 pr_debug("%s: session[%d]enable[%d]\n", __func__,
9821 ac->session, enable);
9822 q6asm_add_hdr_async(ac, &rx_underflow.hdr, sizeof(rx_underflow), FALSE);
9823
9824 rx_underflow.hdr.opcode =
9825 ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS;
9826 /* tx overflow event: enable */
9827 rx_underflow.enable_flag = enable;
9828
9829 rc = apr_send_pkt(ac->apr, (uint32_t *) &rx_underflow);
9830 if (rc < 0) {
9831 pr_err("%s: tx overflow op[0x%x]rc[%d]\n",
9832 __func__, rx_underflow.hdr.opcode, rc);
9833 goto fail_cmd;
9834 }
9835 return 0;
9836fail_cmd:
9837 return -EINVAL;
9838}
9839
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309840/**
9841 * q6asm_adjust_session_clock -
9842 * command to adjust session clock
9843 *
9844 * @ac: Audio client handle
9845 * @adjust_time_lsw: lower 32bits
9846 * @adjust_time_msw: upper 32bits
9847 *
9848 * Returns 0 on success or error on failure
9849 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309850int q6asm_adjust_session_clock(struct audio_client *ac,
9851 uint32_t adjust_time_lsw,
9852 uint32_t adjust_time_msw)
9853{
9854 int rc = 0;
9855 int sz = 0;
9856 struct asm_session_cmd_adjust_session_clock_v2 adjust_clock;
9857
9858 pr_debug("%s: adjust_time_lsw is %x, adjust_time_msw is %x\n", __func__,
9859 adjust_time_lsw, adjust_time_msw);
9860
9861 if (!ac) {
9862 pr_err("%s: audio client handle is NULL\n", __func__);
9863 rc = -EINVAL;
9864 goto fail_cmd;
9865 }
9866
9867 if (ac->apr == NULL) {
9868 pr_err("%s: ac->apr is NULL", __func__);
9869 rc = -EINVAL;
9870 goto fail_cmd;
9871 }
9872
9873 sz = sizeof(struct asm_session_cmd_adjust_session_clock_v2);
9874 q6asm_add_hdr(ac, &adjust_clock.hdr, sz, TRUE);
9875 atomic_set(&ac->cmd_state, -1);
9876 adjust_clock.hdr.opcode = ASM_SESSION_CMD_ADJUST_SESSION_CLOCK_V2;
9877
9878 adjust_clock.adjustime_lsw = adjust_time_lsw;
9879 adjust_clock.adjustime_msw = adjust_time_msw;
9880
9881
9882 rc = apr_send_pkt(ac->apr, (uint32_t *) &adjust_clock);
9883 if (rc < 0) {
9884 pr_err("%s: adjust_clock send failed paramid [0x%x]\n",
9885 __func__, adjust_clock.hdr.opcode);
9886 rc = -EINVAL;
9887 goto fail_cmd;
9888 }
9889
9890 rc = wait_event_timeout(ac->cmd_wait,
9891 (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
9892 if (!rc) {
9893 pr_err("%s: timeout, adjust_clock paramid[0x%x]\n",
9894 __func__, adjust_clock.hdr.opcode);
9895 rc = -ETIMEDOUT;
9896 goto fail_cmd;
9897 }
9898
9899 if (atomic_read(&ac->cmd_state) > 0) {
9900 pr_err("%s: DSP returned error[%s]\n",
9901 __func__, adsp_err_get_err_str(
9902 atomic_read(&ac->cmd_state)));
9903 rc = adsp_err_get_lnx_err_code(
9904 atomic_read(&ac->cmd_state));
9905 goto fail_cmd;
9906 }
9907 rc = 0;
9908fail_cmd:
9909 return rc;
9910}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309911EXPORT_SYMBOL(q6asm_adjust_session_clock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309912
9913/*
9914 * q6asm_get_path_delay() - get the path delay for an audio session
9915 * @ac: audio client handle
9916 *
9917 * Retrieves the current audio DSP path delay for the given audio session.
9918 *
9919 * Return: 0 on success, error code otherwise
9920 */
9921int q6asm_get_path_delay(struct audio_client *ac)
9922{
9923 int rc = 0;
9924 struct apr_hdr hdr;
9925
9926 if (!ac || ac->apr == NULL) {
9927 pr_err("%s: invalid audio client\n", __func__);
9928 return -EINVAL;
9929 }
9930
9931 hdr.opcode = ASM_SESSION_CMD_GET_PATH_DELAY_V2;
9932 q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
9933 atomic_set(&ac->cmd_state, -1);
9934
9935 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
9936 if (rc < 0) {
9937 pr_err("%s: Commmand 0x%x failed %d\n", __func__,
9938 hdr.opcode, rc);
9939 return rc;
9940 }
9941
9942 rc = wait_event_timeout(ac->cmd_wait,
9943 (atomic_read(&ac->cmd_state) >= 0), 5 * HZ);
9944 if (!rc) {
9945 pr_err("%s: timeout. waited for response opcode[0x%x]\n",
9946 __func__, hdr.opcode);
9947 return -ETIMEDOUT;
9948 }
9949
9950 if (atomic_read(&ac->cmd_state) > 0) {
9951 pr_err("%s: DSP returned error[%s]\n",
9952 __func__, adsp_err_get_err_str(
9953 atomic_read(&ac->cmd_state)));
9954 rc = adsp_err_get_lnx_err_code(
9955 atomic_read(&ac->cmd_state));
9956 return rc;
9957 }
9958
9959 return 0;
9960}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309961EXPORT_SYMBOL(q6asm_get_path_delay);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309962
9963int q6asm_get_apr_service_id(int session_id)
9964{
9965 pr_debug("%s:\n", __func__);
9966
9967 if (session_id <= 0 || session_id > ASM_ACTIVE_STREAMS_ALLOWED) {
9968 pr_err("%s: invalid session_id = %d\n", __func__, session_id);
9969 return -EINVAL;
9970 }
9971
Meng Wang9730cdd2017-09-26 12:48:31 +08009972 return ((struct apr_svc *)(session[session_id].ac)->apr)->id;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309973}
9974
9975int q6asm_get_asm_topology(int session_id)
9976{
9977 int topology = -EINVAL;
9978
9979 if (session_id <= 0 || session_id > ASM_ACTIVE_STREAMS_ALLOWED) {
9980 pr_err("%s: invalid session_id = %d\n", __func__, session_id);
9981 goto done;
9982 }
Meng Wang9730cdd2017-09-26 12:48:31 +08009983 if (session[session_id].ac == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309984 pr_err("%s: session not created for session id = %d\n",
9985 __func__, session_id);
9986 goto done;
9987 }
Meng Wang9730cdd2017-09-26 12:48:31 +08009988 topology = (session[session_id].ac)->topology;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309989done:
9990 return topology;
9991}
9992
9993int q6asm_get_asm_app_type(int session_id)
9994{
9995 int app_type = -EINVAL;
9996
9997 if (session_id <= 0 || session_id > ASM_ACTIVE_STREAMS_ALLOWED) {
9998 pr_err("%s: invalid session_id = %d\n", __func__, session_id);
9999 goto done;
10000 }
Meng Wang9730cdd2017-09-26 12:48:31 +080010001 if (session[session_id].ac == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010002 pr_err("%s: session not created for session id = %d\n",
10003 __func__, session_id);
10004 goto done;
10005 }
Meng Wang9730cdd2017-09-26 12:48:31 +080010006 app_type = (session[session_id].ac)->app_type;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010007done:
10008 return app_type;
10009}
10010
10011static int q6asm_get_asm_topology_cal(void)
10012{
10013 int topology = DEFAULT_POPP_TOPOLOGY;
10014 struct cal_block_data *cal_block = NULL;
10015
10016 if (cal_data[ASM_TOPOLOGY_CAL] == NULL)
10017 goto done;
10018
10019 mutex_lock(&cal_data[ASM_TOPOLOGY_CAL]->lock);
10020 cal_block = cal_utils_get_only_cal_block(cal_data[ASM_TOPOLOGY_CAL]);
10021 if (cal_block == NULL)
10022 goto unlock;
10023
10024 topology = ((struct audio_cal_info_asm_top *)
10025 cal_block->cal_info)->topology;
10026unlock:
10027 mutex_unlock(&cal_data[ASM_TOPOLOGY_CAL]->lock);
10028done:
10029 pr_debug("%s: Using topology %d\n", __func__, topology);
10030 return topology;
10031}
10032
10033static int q6asm_get_asm_app_type_cal(void)
10034{
10035 int app_type = DEFAULT_APP_TYPE;
10036 struct cal_block_data *cal_block = NULL;
10037
10038 if (cal_data[ASM_TOPOLOGY_CAL] == NULL)
10039 goto done;
10040
10041 mutex_lock(&cal_data[ASM_TOPOLOGY_CAL]->lock);
10042 cal_block = cal_utils_get_only_cal_block(cal_data[ASM_TOPOLOGY_CAL]);
10043 if (cal_block == NULL)
10044 goto unlock;
10045
10046 app_type = ((struct audio_cal_info_asm_top *)
10047 cal_block->cal_info)->app_type;
10048
10049 if (app_type == 0)
10050 app_type = DEFAULT_APP_TYPE;
10051unlock:
10052 mutex_unlock(&cal_data[ASM_TOPOLOGY_CAL]->lock);
10053done:
10054 pr_debug("%s: Using app_type %d\n", __func__, app_type);
10055 return app_type;
10056}
10057
Laxminath Kasam8b1366a2017-10-05 01:44:16 +053010058/**
10059 * q6asm_send_cal -
10060 * command to send ASM calibration
10061 *
10062 * @ac: Audio client handle
10063 *
10064 * Returns 0 on success or error on failure
10065 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010066int q6asm_send_cal(struct audio_client *ac)
10067{
10068 struct cal_block_data *cal_block = NULL;
10069 struct apr_hdr hdr;
10070 char *asm_params = NULL;
10071 struct asm_stream_cmd_set_pp_params_v2 payload_params;
10072 int sz, rc = -EINVAL;
10073
10074 pr_debug("%s:\n", __func__);
10075
10076 if (!ac) {
10077 pr_err("%s: APR handle NULL\n", __func__);
10078 goto done;
10079 }
10080 if (ac->apr == NULL) {
10081 pr_err("%s: AC APR handle NULL\n", __func__);
10082 goto done;
10083 }
10084 if (ac->io_mode & NT_MODE) {
10085 pr_debug("%s: called for NT MODE, exiting\n", __func__);
10086 goto done;
10087 }
10088
10089 if (cal_data[ASM_AUDSTRM_CAL] == NULL)
10090 goto done;
10091
10092 if (ac->perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) {
10093 rc = 0; /* no cal is required, not error case */
10094 goto done;
10095 }
10096
10097 mutex_lock(&cal_data[ASM_AUDSTRM_CAL]->lock);
10098 cal_block = cal_utils_get_only_cal_block(cal_data[ASM_AUDSTRM_CAL]);
10099 if (cal_block == NULL) {
10100 pr_err("%s: cal_block is NULL\n",
10101 __func__);
10102 goto unlock;
10103 }
10104
10105 if (cal_block->cal_data.size == 0) {
10106 rc = 0; /* not error case */
10107 pr_debug("%s: cal_data.size is 0, don't send cal data\n",
10108 __func__);
10109 goto unlock;
10110 }
10111
10112 rc = remap_cal_data(ASM_AUDSTRM_CAL_TYPE, cal_block);
10113 if (rc) {
10114 pr_err("%s: Remap_cal_data failed for cal %d!\n",
10115 __func__, ASM_AUDSTRM_CAL);
10116 goto unlock;
10117 }
10118
10119 sz = sizeof(struct apr_hdr) +
10120 sizeof(struct asm_stream_cmd_set_pp_params_v2);
10121 asm_params = kzalloc(sz, GFP_KERNEL);
10122 if (!asm_params) {
10123 pr_err("%s, asm params memory alloc failed", __func__);
10124 rc = -ENOMEM;
10125 goto unlock;
10126 }
10127
10128 /* asm_stream_cmd_set_pp_params_v2 has no APR header in it */
10129 q6asm_add_hdr_async(ac, &hdr, (sizeof(struct apr_hdr) +
10130 sizeof(struct asm_stream_cmd_set_pp_params_v2)), TRUE);
10131
10132 atomic_set(&ac->cmd_state_pp, -1);
10133 hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
10134 payload_params.data_payload_addr_lsw =
10135 lower_32_bits(cal_block->cal_data.paddr);
10136 payload_params.data_payload_addr_msw =
10137 msm_audio_populate_upper_32_bits(
10138 cal_block->cal_data.paddr);
10139 payload_params.mem_map_handle = cal_block->map_data.q6map_handle;
10140 payload_params.data_payload_size = cal_block->cal_data.size;
10141 memcpy(((u8 *)asm_params), &hdr, sizeof(struct apr_hdr));
10142 memcpy(((u8 *)asm_params + sizeof(struct apr_hdr)), &payload_params,
10143 sizeof(struct asm_stream_cmd_set_pp_params_v2));
10144
10145 pr_debug("%s: phyaddr lsw = %x msw = %x, maphdl = %x calsize = %d\n",
10146 __func__, payload_params.data_payload_addr_lsw,
10147 payload_params.data_payload_addr_msw,
10148 payload_params.mem_map_handle,
10149 payload_params.data_payload_size);
10150
10151 rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
10152 if (rc < 0) {
10153 pr_err("%s: audio audstrm cal send failed\n", __func__);
10154 rc = -EINVAL;
10155 goto free;
10156 }
10157 rc = wait_event_timeout(ac->cmd_wait,
10158 (atomic_read(&ac->cmd_state_pp) >= 0), 5 * HZ);
10159 if (!rc) {
10160 pr_err("%s: timeout, audio audstrm cal send\n", __func__);
10161 rc = -ETIMEDOUT;
10162 goto free;
10163 }
10164 if (atomic_read(&ac->cmd_state_pp) > 0) {
10165 pr_err("%s: DSP returned error[%d] audio audstrm cal send\n",
10166 __func__, atomic_read(&ac->cmd_state_pp));
10167 rc = -EINVAL;
10168 goto free;
10169 }
10170
10171 rc = 0;
10172
10173free:
10174 kfree(asm_params);
10175unlock:
10176 mutex_unlock(&cal_data[ASM_AUDSTRM_CAL]->lock);
10177done:
10178 return rc;
10179}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +053010180EXPORT_SYMBOL(q6asm_send_cal);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010181
10182static int get_cal_type_index(int32_t cal_type)
10183{
10184 int ret = -EINVAL;
10185
10186 switch (cal_type) {
10187 case ASM_TOPOLOGY_CAL_TYPE:
10188 ret = ASM_TOPOLOGY_CAL;
10189 break;
10190 case ASM_CUST_TOPOLOGY_CAL_TYPE:
10191 ret = ASM_CUSTOM_TOP_CAL;
10192 break;
10193 case ASM_AUDSTRM_CAL_TYPE:
10194 ret = ASM_AUDSTRM_CAL;
10195 break;
10196 case ASM_RTAC_APR_CAL_TYPE:
10197 ret = ASM_RTAC_APR_CAL;
10198 break;
10199 default:
10200 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
10201 }
10202 return ret;
10203}
10204
10205static int q6asm_alloc_cal(int32_t cal_type,
10206 size_t data_size, void *data)
10207{
10208 int ret = 0;
10209 int cal_index;
10210
10211 pr_debug("%s:\n", __func__);
10212
10213 cal_index = get_cal_type_index(cal_type);
10214 if (cal_index < 0) {
10215 pr_err("%s: could not get cal index %d!\n",
10216 __func__, cal_index);
10217 ret = -EINVAL;
10218 goto done;
10219 }
10220
10221 ret = cal_utils_alloc_cal(data_size, data,
10222 cal_data[cal_index], 0, NULL);
10223 if (ret < 0) {
10224 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
10225 __func__, ret, cal_type);
10226 ret = -EINVAL;
10227 goto done;
10228 }
10229done:
10230 return ret;
10231}
10232
10233static int q6asm_dealloc_cal(int32_t cal_type,
10234 size_t data_size, void *data)
10235{
10236 int ret = 0;
10237 int cal_index;
10238
10239 pr_debug("%s:\n", __func__);
10240
10241 cal_index = get_cal_type_index(cal_type);
10242 if (cal_index < 0) {
10243 pr_err("%s: could not get cal index %d!\n",
10244 __func__, cal_index);
10245 ret = -EINVAL;
10246 goto done;
10247 }
10248
10249 ret = cal_utils_dealloc_cal(data_size, data,
10250 cal_data[cal_index]);
10251 if (ret < 0) {
10252 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
10253 __func__, ret, cal_type);
10254 ret = -EINVAL;
10255 goto done;
10256 }
10257done:
10258 return ret;
10259}
10260
10261static int q6asm_set_cal(int32_t cal_type,
10262 size_t data_size, void *data)
10263{
10264 int ret = 0;
10265 int cal_index;
10266
10267 pr_debug("%s:\n", __func__);
10268
10269 cal_index = get_cal_type_index(cal_type);
10270 if (cal_index < 0) {
10271 pr_err("%s: could not get cal index %d!\n",
10272 __func__, cal_index);
10273 ret = -EINVAL;
10274 goto done;
10275 }
10276
10277 ret = cal_utils_set_cal(data_size, data,
10278 cal_data[cal_index], 0, NULL);
10279 if (ret < 0) {
10280 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
10281 __func__, ret, cal_type);
10282 ret = -EINVAL;
10283 goto done;
10284 }
10285
10286 if (cal_index == ASM_CUSTOM_TOP_CAL) {
10287 mutex_lock(&cal_data[ASM_CUSTOM_TOP_CAL]->lock);
10288 set_custom_topology = 1;
10289 mutex_unlock(&cal_data[ASM_CUSTOM_TOP_CAL]->lock);
10290 }
10291done:
10292 return ret;
10293}
10294
10295static void q6asm_delete_cal_data(void)
10296{
10297 pr_debug("%s:\n", __func__);
10298 cal_utils_destroy_cal_types(ASM_MAX_CAL_TYPES, cal_data);
10299}
10300
10301static int q6asm_init_cal_data(void)
10302{
10303 int ret = 0;
10304 struct cal_type_info cal_type_info[] = {
10305 {{ASM_TOPOLOGY_CAL_TYPE,
10306 {NULL, NULL, NULL,
10307 q6asm_set_cal, NULL, NULL} },
10308 {NULL, NULL, cal_utils_match_buf_num} },
10309
10310 {{ASM_CUST_TOPOLOGY_CAL_TYPE,
10311 {q6asm_alloc_cal, q6asm_dealloc_cal, NULL,
10312 q6asm_set_cal, NULL, NULL} },
10313 {NULL, q6asm_unmap_cal_memory, cal_utils_match_buf_num} },
10314
10315 {{ASM_AUDSTRM_CAL_TYPE,
10316 {q6asm_alloc_cal, q6asm_dealloc_cal, NULL,
10317 q6asm_set_cal, NULL, NULL} },
10318 {NULL, q6asm_unmap_cal_memory, cal_utils_match_buf_num} },
10319
10320 {{ASM_RTAC_APR_CAL_TYPE,
10321 {NULL, NULL, NULL, NULL, NULL, NULL} },
10322 {NULL, NULL, cal_utils_match_buf_num} }
10323 };
10324 pr_debug("%s\n", __func__);
10325
10326 ret = cal_utils_create_cal_types(ASM_MAX_CAL_TYPES, cal_data,
10327 cal_type_info);
10328 if (ret < 0) {
10329 pr_err("%s: could not create cal type! %d\n",
10330 __func__, ret);
10331 ret = -EINVAL;
10332 goto err;
10333 }
10334
10335 return ret;
10336err:
10337 q6asm_delete_cal_data();
10338 return ret;
10339}
10340
10341static int q6asm_is_valid_session(struct apr_client_data *data, void *priv)
10342{
10343 struct audio_client *ac = (struct audio_client *)priv;
10344 union asm_token_struct asm_token;
10345
10346 asm_token.token = data->token;
10347 if (asm_token._token.session_id != ac->session) {
10348 pr_err("%s: Invalid session[%d] rxed expected[%d]",
10349 __func__, asm_token._token.session_id, ac->session);
10350 return -EINVAL;
10351 }
10352 return 0;
10353}
10354
Laxminath Kasam8b1366a2017-10-05 01:44:16 +053010355int __init q6asm_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010356{
10357 int lcnt, ret;
10358
10359 pr_debug("%s:\n", __func__);
10360
Meng Wang9730cdd2017-09-26 12:48:31 +080010361 memset(session, 0, sizeof(struct audio_session) *
10362 (ASM_ACTIVE_STREAMS_ALLOWED + 1));
10363 for (lcnt = 0; lcnt <= ASM_ACTIVE_STREAMS_ALLOWED; lcnt++)
10364 spin_lock_init(&(session[lcnt].session_lock));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010365 set_custom_topology = 1;
10366
10367 /*setup common client used for cal mem map */
10368 common_client.session = ASM_CONTROL_SESSION;
10369 common_client.port[0].buf = &common_buf[0];
10370 common_client.port[1].buf = &common_buf[1];
10371 init_waitqueue_head(&common_client.cmd_wait);
10372 init_waitqueue_head(&common_client.time_wait);
10373 init_waitqueue_head(&common_client.mem_wait);
10374 atomic_set(&common_client.time_flag, 1);
10375 INIT_LIST_HEAD(&common_client.port[0].mem_map_handle);
10376 INIT_LIST_HEAD(&common_client.port[1].mem_map_handle);
10377 mutex_init(&common_client.cmd_lock);
10378 for (lcnt = 0; lcnt <= OUT; lcnt++) {
10379 mutex_init(&common_client.port[lcnt].lock);
10380 spin_lock_init(&common_client.port[lcnt].dsp_lock);
10381 }
10382 atomic_set(&common_client.cmd_state, 0);
10383 atomic_set(&common_client.mem_state, 0);
10384
10385 ret = q6asm_init_cal_data();
10386 if (ret)
10387 pr_err("%s: could not init cal data! ret %d\n",
10388 __func__, ret);
10389
10390 config_debug_fs_init();
10391
10392 return 0;
10393}
10394
Asish Bhattacharya5faacb32017-12-04 17:23:15 +053010395void q6asm_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010396{
10397 q6asm_delete_cal_data();
10398}