blob: 28bd98da52474fddef21e0521208e2894f60852d [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001
2/*
3 * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
4 * Author: Brian Swetland <swetland@google.com>
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16#include <linux/fs.h>
17#include <linux/mutex.h>
18#include <linux/wait.h>
19#include <linux/miscdevice.h>
20#include <linux/uaccess.h>
21#include <linux/sched.h>
22#include <linux/dma-mapping.h>
23#include <linux/miscdevice.h>
24#include <linux/delay.h>
25#include <linux/spinlock.h>
26#include <linux/slab.h>
27#include <linux/msm_audio.h>
28#include <linux/android_pmem.h>
29#include <linux/memory_alloc.h>
30#include <mach/memory.h>
31#include <mach/debug_mm.h>
32#include <mach/peripheral-loader.h>
33#include <mach/qdsp6v2/audio_acdb.h>
34#include <mach/qdsp6v2/rtac.h>
35#include <mach/msm_subsystem_map.h>
36#include <sound/apr_audio.h>
37#include <sound/q6asm.h>
38#include <asm/atomic.h>
39#include <asm/ioctls.h>
40
41#define TRUE 0x01
42#define FALSE 0x00
43#define READDONE_IDX_STATUS 0
44#define READDONE_IDX_BUFFER 1
45#define READDONE_IDX_SIZE 2
46#define READDONE_IDX_OFFSET 3
47#define READDONE_IDX_MSW_TS 4
48#define READDONE_IDX_LSW_TS 5
49#define READDONE_IDX_FLAGS 6
50#define READDONE_IDX_NUMFRAMES 7
51#define READDONE_IDX_ID 8
52
53static DEFINE_MUTEX(session_lock);
54
55/* session id: 0 reserved */
56static struct audio_client *session[SESSION_MAX+1];
57static int32_t q6asm_mmapcallback(struct apr_client_data *data, void *priv);
58static int32_t q6asm_callback(struct apr_client_data *data, void *priv);
59static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
60 uint32_t pkt_size, uint32_t cmd_flg);
61static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
62 uint32_t pkt_size, uint32_t cmd_flg);
63static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
64 uint32_t bufsz, uint32_t bufcnt);
65static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir,
66 uint32_t bufsz, uint32_t bufcnt);
67
68static void q6asm_reset_buf_state(struct audio_client *ac);
69
70struct asm_mmap {
71 atomic_t ref_cnt;
72 atomic_t cmd_state;
73 wait_queue_head_t cmd_wait;
74 void *apr;
75};
76
77static struct asm_mmap this_mmap;
78
79static int q6asm_session_alloc(struct audio_client *ac)
80{
81 int n;
82 mutex_lock(&session_lock);
83 for (n = 1; n <= SESSION_MAX; n++) {
84 if (!session[n]) {
85 session[n] = ac;
86 mutex_unlock(&session_lock);
87 return n;
88 }
89 }
90 mutex_unlock(&session_lock);
91 return -ENOMEM;
92}
93
94static void q6asm_session_free(struct audio_client *ac)
95{
96 pr_debug("%s: sessionid[%d]\n", __func__, ac->session);
97 mutex_lock(&session_lock);
98 session[ac->session] = 0;
99 mutex_unlock(&session_lock);
100 ac->session = 0;
101 return;
102}
103
104int q6asm_audio_client_buf_free(unsigned int dir,
105 struct audio_client *ac)
106{
107 struct audio_port_data *port;
108 int cnt = 0;
109 int rc = 0;
110 pr_debug("%s: Session id %d\n", __func__, ac->session);
111 mutex_lock(&ac->cmd_lock);
112 if (ac->io_mode == SYNC_IO_MODE) {
113 port = &ac->port[dir];
114 if (!port->buf) {
115 mutex_unlock(&ac->cmd_lock);
116 return 0;
117 }
118 cnt = port->max_buf_cnt - 1;
119
120 if (cnt >= 0) {
121 rc = q6asm_memory_unmap_regions(ac, dir,
122 port->buf[0].size,
123 port->max_buf_cnt);
124 if (rc < 0)
125 pr_err("%s CMD Memory_unmap_regions failed\n",
126 __func__);
127 }
128
129 while (cnt >= 0) {
130 if (port->buf[cnt].data) {
131 pr_debug("%s:data[%p]phys[%p][%p] cnt[%d]"
132 "mem_buffer[%p]\n",
133 __func__, (void *)port->buf[cnt].data,
134 (void *)port->buf[cnt].phys,
135 (void *)&port->buf[cnt].phys, cnt,
136 (void *)port->buf[cnt].mem_buffer);
137 if (IS_ERR((void *)port->buf[cnt].mem_buffer))
138 pr_err("%s:mem buffer invalid, error ="
139 "%ld\n", __func__,
140 PTR_ERR((void *)port->buf[cnt].mem_buffer));
141 else {
142 if (msm_subsystem_unmap_buffer(
143 port->buf[cnt].mem_buffer) < 0)
144 pr_err("%s: unmap buffer"
145 " failed\n", __func__);
146 }
147 free_contiguous_memory_by_paddr(
148 port->buf[cnt].phys);
149
150 port->buf[cnt].data = NULL;
151 port->buf[cnt].phys = 0;
152 --(port->max_buf_cnt);
153 }
154 --cnt;
155 }
156 kfree(port->buf);
157 port->buf = NULL;
158 }
159 mutex_unlock(&ac->cmd_lock);
160 return 0;
161}
162
163int q6asm_audio_client_buf_free_contiguous(unsigned int dir,
164 struct audio_client *ac)
165{
166 struct audio_port_data *port;
167 int cnt = 0;
168 int rc = 0;
169 pr_debug("%s: Session id %d\n", __func__, ac->session);
170 mutex_lock(&ac->cmd_lock);
171 port = &ac->port[dir];
172 if (!port->buf) {
173 mutex_unlock(&ac->cmd_lock);
174 return 0;
175 }
176 cnt = port->max_buf_cnt - 1;
177
178 if (cnt >= 0) {
Deepa Madiregama7d52a402011-07-13 20:28:36 +0530179 rc = q6asm_memory_unmap(ac, port->buf[0].phys, dir);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700180 if (rc < 0)
181 pr_err("%s CMD Memory_unmap_regions failed\n",
182 __func__);
183 }
184
185 if (port->buf[0].data) {
186 pr_debug("%s:data[%p]phys[%p][%p] cnt[%d]\n",
187 __func__,
188 (void *)port->buf[0].data,
189 (void *)port->buf[0].phys,
190 (void *)&port->buf[0].phys, cnt);
191 dma_free_coherent(NULL,
192 port->buf[0].size * port->max_buf_cnt,
193 port->buf[0].data,
194 port->buf[0].phys);
195 }
196 while (cnt >= 0) {
197 port->buf[cnt].data = NULL;
198 port->buf[cnt].phys = 0;
199 cnt--;
200 }
201 port->max_buf_cnt = 0;
202 kfree(port->buf);
203 port->buf = NULL;
204 mutex_unlock(&ac->cmd_lock);
205 return 0;
206}
207
208void q6asm_audio_client_free(struct audio_client *ac)
209{
210 int loopcnt;
211 struct audio_port_data *port;
212 if (!ac || !ac->session)
213 return;
214 pr_debug("%s: Session id %d\n", __func__, ac->session);
215 if (ac->io_mode == SYNC_IO_MODE) {
216 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
217 port = &ac->port[loopcnt];
218 if (!port->buf)
219 continue;
220 pr_debug("%s:loopcnt = %d\n", __func__, loopcnt);
221 q6asm_audio_client_buf_free(loopcnt, ac);
222 }
223 }
224
225 apr_deregister(ac->apr);
226 q6asm_session_free(ac);
227
228 pr_debug("%s: APR De-Register\n", __func__);
229 if (atomic_read(&this_mmap.ref_cnt) <= 0) {
230 pr_err("%s: APR Common Port Already Closed\n", __func__);
231 goto done;
232 }
233
234 atomic_dec(&this_mmap.ref_cnt);
235 if (atomic_read(&this_mmap.ref_cnt) == 0) {
236 apr_deregister(this_mmap.apr);
237 pr_debug("%s:APR De-Register common port\n", __func__);
238 }
239done:
240 kfree(ac);
241 return;
242}
243
244int q6asm_set_io_mode(struct audio_client *ac, uint32_t mode)
245{
246 if (ac == NULL) {
247 pr_err("%s APR handle NULL\n", __func__);
248 return -EINVAL;
249 }
250 if ((mode == ASYNC_IO_MODE) || (mode == SYNC_IO_MODE)) {
251 ac->io_mode = mode;
252 pr_debug("%s:Set Mode to %d\n", __func__, ac->io_mode);
253 return 0;
254 } else {
255 pr_err("%s:Not an valid IO Mode:%d\n", __func__, ac->io_mode);
256 return -EINVAL;
257 }
258}
259
260struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv)
261{
262 struct audio_client *ac;
263 int n;
264 int lcnt = 0;
265
266 ac = kzalloc(sizeof(struct audio_client), GFP_KERNEL);
267 if (!ac)
268 return NULL;
269 n = q6asm_session_alloc(ac);
270 if (n <= 0)
271 goto fail_session;
272 ac->session = n;
273 ac->cb = cb;
274 ac->priv = priv;
275 ac->io_mode = SYNC_IO_MODE;
276 ac->apr = apr_register("ADSP", "ASM", \
277 (apr_fn)q6asm_callback,\
278 ((ac->session) << 8 | 0x0001),\
279 ac);
280
281 if (ac->apr == NULL) {
282 pr_err("%s Registration with APR failed\n", __func__);
283 goto fail;
284 }
285#ifdef CONFIG_MSM8X60_RTAC
286 rtac_set_asm_handle(n, ac->apr);
287#endif
288 pr_debug("%s Registering the common port with APR\n", __func__);
289 if (atomic_read(&this_mmap.ref_cnt) == 0) {
290 this_mmap.apr = apr_register("ADSP", "ASM", \
291 (apr_fn)q6asm_mmapcallback,\
292 0x0FFFFFFFF, &this_mmap);
293 if (this_mmap.apr == NULL) {
294 pr_debug("%s Unable to register \
295 APR ASM common port \n", __func__);
296 goto fail;
297 }
298 }
299
300 atomic_inc(&this_mmap.ref_cnt);
301 init_waitqueue_head(&ac->cmd_wait);
302 init_waitqueue_head(&ac->time_wait);
303 atomic_set(&ac->time_flag, 1);
304 mutex_init(&ac->cmd_lock);
305 for (lcnt = 0; lcnt <= OUT; lcnt++) {
306 mutex_init(&ac->port[lcnt].lock);
307 spin_lock_init(&ac->port[lcnt].dsp_lock);
308 }
309 atomic_set(&ac->cmd_state, 0);
310
311 pr_debug("%s: session[%d]\n", __func__, ac->session);
312
313 return ac;
314fail:
315 q6asm_audio_client_free(ac);
316 return NULL;
317fail_session:
318 kfree(ac);
319 return NULL;
320}
321
322int q6asm_audio_client_buf_alloc(unsigned int dir,
323 struct audio_client *ac,
324 unsigned int bufsz,
325 unsigned int bufcnt)
326{
327 int cnt = 0;
328 int rc = 0;
329 struct audio_buffer *buf;
330
331 if (!(ac) || ((dir != IN) && (dir != OUT)))
332 return -EINVAL;
333
334 pr_debug("%s: session[%d]bufsz[%d]bufcnt[%d]\n", __func__, ac->session,
335 bufsz, bufcnt);
336
337 if (ac->session <= 0 || ac->session > 8)
338 goto fail;
339
340 if (ac->io_mode == SYNC_IO_MODE) {
341 if (ac->port[dir].buf) {
342 pr_debug("%s: buffer already allocated\n", __func__);
343 return 0;
344 }
345 mutex_lock(&ac->cmd_lock);
346 buf = kzalloc(((sizeof(struct audio_buffer))*bufcnt),
347 GFP_KERNEL);
348
349 if (!buf) {
350 mutex_unlock(&ac->cmd_lock);
351 goto fail;
352 }
353
354 ac->port[dir].buf = buf;
355
356 while (cnt < bufcnt) {
357 if (bufsz > 0) {
358 if (!buf[cnt].data) {
359 unsigned int flags = 0;
360 buf[cnt].phys =
361 allocate_contiguous_ebi_nomap(bufsz,
362 SZ_4K);
363 if (!buf[cnt].phys) {
364 pr_err("%s:Buf alloc failed "
365 " size=%d\n", __func__,
366 bufsz);
367 mutex_unlock(&ac->cmd_lock);
368 goto fail;
369 }
370 flags = MSM_SUBSYSTEM_MAP_KADDR |
371 MSM_SUBSYSTEM_MAP_CACHED;
372 buf[cnt].mem_buffer =
373 msm_subsystem_map_buffer(buf[cnt].phys,
374 bufsz, flags, NULL, 0);
375 if (IS_ERR(
376 (void *)buf[cnt].mem_buffer)) {
377 pr_err("%s:map_buffer failed,"
378 "error = %ld\n",
379 __func__, PTR_ERR((void *)buf[cnt].mem_buffer));
380 goto fail;
381 }
382 buf[cnt].data =
383 buf[cnt].mem_buffer->vaddr;
384 if (!buf[cnt].data) {
385 pr_err("%s:invalid vaddr,"
386 " iomap failed\n", __func__);
387 goto fail;
388 }
389 buf[cnt].used = 1;
390 buf[cnt].size = bufsz;
391 buf[cnt].actual_size = bufsz;
392 pr_debug("%s data[%p]phys[%p][%p]"
393 "mem_buffer[%p]\n",
394 __func__,
395 (void *)buf[cnt].data,
396 (void *)buf[cnt].phys,
397 (void *)&buf[cnt].phys,
398 (void *)buf[cnt].mem_buffer);
399 cnt++;
400 }
401 }
402 }
403 ac->port[dir].max_buf_cnt = cnt;
404
405 mutex_unlock(&ac->cmd_lock);
406 rc = q6asm_memory_map_regions(ac, dir, bufsz, cnt);
407 if (rc < 0) {
408 pr_err("%s:CMD Memory_map_regions failed\n", __func__);
409 goto fail;
410 }
411 }
412 return 0;
413fail:
414 q6asm_audio_client_buf_free(dir, ac);
415 return -EINVAL;
416}
417
418int q6asm_audio_client_buf_alloc_contiguous(unsigned int dir,
419 struct audio_client *ac,
420 unsigned int bufsz,
421 unsigned int bufcnt)
422{
423 int cnt = 0;
424 int rc = 0;
425 struct audio_buffer *buf;
426
427 if (!(ac) || ((dir != IN) && (dir != OUT)))
428 return -EINVAL;
429
430 pr_debug("%s: session[%d]bufsz[%d]bufcnt[%d]\n",
431 __func__, ac->session,
432 bufsz, bufcnt);
433
434 if (ac->session <= 0 || ac->session > 8)
435 goto fail;
436
437 if (ac->port[dir].buf) {
438 pr_debug("%s: buffer already allocated\n", __func__);
439 return 0;
440 }
441 mutex_lock(&ac->cmd_lock);
442 buf = kzalloc(((sizeof(struct audio_buffer))*bufcnt),
443 GFP_KERNEL);
444
445 if (!buf) {
446 mutex_unlock(&ac->cmd_lock);
447 goto fail;
448 }
449
450 ac->port[dir].buf = buf;
451
452 buf[0].data = dma_alloc_coherent(NULL, bufsz * bufcnt,
453 &buf[0].phys, GFP_KERNEL);
454 buf[0].used = dir ^ 1;
455 buf[0].size = bufsz;
456 buf[0].actual_size = bufsz;
457 cnt = 1;
458 while (cnt < bufcnt) {
459 if (bufsz > 0) {
460 buf[cnt].data = buf[0].data + (cnt * bufsz);
461 buf[cnt].phys = buf[0].phys + (cnt * bufsz);
462 if (!buf[cnt].data) {
463 pr_err("%s Buf alloc failed\n",
464 __func__);
465 mutex_unlock(&ac->cmd_lock);
466 goto fail;
467 }
468 buf[cnt].used = dir ^ 1;
469 buf[cnt].size = bufsz;
470 buf[cnt].actual_size = bufsz;
471 pr_debug("%s data[%p]phys[%p][%p]\n", __func__,
472 (void *)buf[cnt].data,
473 (void *)buf[cnt].phys,
474 (void *)&buf[cnt].phys);
475 }
476 cnt++;
477 }
478 ac->port[dir].max_buf_cnt = cnt;
479 mutex_unlock(&ac->cmd_lock);
480 rc = q6asm_memory_map(ac, buf[0].phys, dir, bufsz, cnt);
481 if (rc < 0) {
482 pr_err("%s:CMD Memory_map_regions failed\n", __func__);
483 goto fail;
484 }
485 return 0;
486fail:
487 q6asm_audio_client_buf_free_contiguous(dir, ac);
488 return -EINVAL;
489}
490
491static int32_t q6asm_mmapcallback(struct apr_client_data *data, void *priv)
492{
493 uint32_t token;
494 uint32_t *payload = data->payload;
495
496 if (data->opcode == RESET_EVENTS) {
497 pr_debug("%s: Reset event is received: %d %d apr[%p]\n",
498 __func__,
499 data->reset_event,
500 data->reset_proc,
501 this_mmap.apr);
502 apr_reset(this_mmap.apr);
503 this_mmap.apr = NULL;
504 atomic_set(&this_mmap.cmd_state, 0);
505 return 0;
506 }
507
508 pr_debug("%s:ptr0[0x%x]ptr1[0x%x]opcode[0x%x]"
509 "token[0x%x]payload_s[%d] src[%d] dest[%d]\n", __func__,
510 payload[0], payload[1], data->opcode, data->token,
511 data->payload_size, data->src_port, data->dest_port);
512
513 if (data->opcode == APR_BASIC_RSP_RESULT) {
514 token = data->token;
515 switch (payload[0]) {
516 case ASM_SESSION_CMD_MEMORY_MAP:
517 case ASM_SESSION_CMD_MEMORY_UNMAP:
518 case ASM_SESSION_CMD_MEMORY_MAP_REGIONS:
519 case ASM_SESSION_CMD_MEMORY_UNMAP_REGIONS:
520 pr_debug("%s:command[0x%x]success [0x%x]\n",
521 __func__, payload[0], payload[1]);
522 if (atomic_read(&this_mmap.cmd_state)) {
523 atomic_set(&this_mmap.cmd_state, 0);
524 wake_up(&this_mmap.cmd_wait);
525 }
526 break;
527 default:
528 pr_debug("%s:command[0x%x] not expecting rsp\n",
529 __func__, payload[0]);
530 break;
531 }
532 }
533 return 0;
534}
535
536
537static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
538{
539 int i = 0;
540 struct audio_client *ac = (struct audio_client *)priv;
541 uint32_t token;
542 unsigned long dsp_flags;
543 uint32_t *payload;
544
545
546 if ((ac == NULL) || (data == NULL)) {
547 pr_err("ac or priv NULL\n");
548 return -EINVAL;
549 }
550 if (ac->session <= 0 || ac->session > 8) {
551 pr_err("%s:Session ID is invalid, session = %d\n", __func__,
552 ac->session);
553 return -EINVAL;
554 }
555
556 payload = data->payload;
557
558 if (data->opcode == RESET_EVENTS) {
559 pr_debug("q6asm_callback: Reset event is received: %d %d apr[%p]\n",
560 data->reset_event, data->reset_proc, ac->apr);
561 apr_reset(ac->apr);
562 return 0;
563 }
564
565 pr_debug("%s: session[%d]opcode[0x%x] \
566 token[0x%x]payload_s[%d] src[%d] dest[%d]\n", __func__,
567 ac->session, data->opcode,
568 data->token, data->payload_size, data->src_port,
569 data->dest_port);
570
571 if (data->opcode == APR_BASIC_RSP_RESULT) {
572 token = data->token;
573 switch (payload[0]) {
574 case ASM_STREAM_CMD_SET_PP_PARAMS:
575#ifdef CONFIG_MSM8X60_RTAC
576 if (rtac_make_asm_callback(ac->session, payload,
577 data->payload_size))
578 break;
579#endif
580 case ASM_SESSION_CMD_PAUSE:
581 case ASM_DATA_CMD_EOS:
582 case ASM_STREAM_CMD_CLOSE:
583 case ASM_STREAM_CMD_FLUSH:
584 case ASM_SESSION_CMD_RUN:
585 case ASM_SESSION_CMD_REGISTER_FOR_TX_OVERFLOW_EVENTS:
586 case ASM_STREAM_CMD_FLUSH_READBUFS:
587 pr_debug("%s:Payload = [0x%x]\n", __func__, payload[0]);
588 if (token != ac->session) {
589 pr_err("%s:Invalid session[%d] rxed expected[%d]",
590 __func__, token, ac->session);
591 return -EINVAL;
592 }
593 case ASM_STREAM_CMD_OPEN_READ:
594 case ASM_STREAM_CMD_OPEN_WRITE:
595 case ASM_STREAM_CMD_OPEN_READWRITE:
596 case ASM_DATA_CMD_MEDIA_FORMAT_UPDATE:
597 case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
598 if (atomic_read(&ac->cmd_state)) {
599 atomic_set(&ac->cmd_state, 0);
600 wake_up(&ac->cmd_wait);
601 }
602 if (ac->cb)
603 ac->cb(data->opcode, data->token,
604 (uint32_t *)data->payload, ac->priv);
605 break;
606 default:
607 pr_debug("%s:command[0x%x] not expecting rsp\n",
608 __func__, payload[0]);
609 break;
610 }
611 return 0;
612 }
613
614 switch (data->opcode) {
615 case ASM_DATA_EVENT_WRITE_DONE:{
616 struct audio_port_data *port = &ac->port[IN];
617 pr_debug("%s: Rxed opcode[0x%x] status[0x%x] token[%d]",
618 __func__, payload[0], payload[1],
619 data->token);
620 if (ac->io_mode == SYNC_IO_MODE) {
621 if (port->buf == NULL) {
622 pr_err("%s: Unexpected Write Done\n",
623 __func__);
624 return -EINVAL;
625 }
626 spin_lock_irqsave(&port->dsp_lock, dsp_flags);
627 if (port->buf[data->token].phys !=
628 payload[0]) {
629 pr_err("Buf expected[%p]rxed[%p]\n",\
630 (void *)port->buf[data->token].phys,\
631 (void *)payload[0]);
632 spin_unlock_irqrestore(&port->dsp_lock,
633 dsp_flags);
634 return -EINVAL;
635 }
636 token = data->token;
637 port->buf[token].used = 1;
638 spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
639 for (i = 0; i < port->max_buf_cnt; i++)
640 pr_debug("%d ", port->buf[i].used);
641
642 }
643 break;
644 }
645#ifdef CONFIG_MSM8X60_RTAC
646 case ASM_STREAM_CMDRSP_GET_PP_PARAMS:
647 rtac_make_asm_callback(ac->session, payload,
648 data->payload_size);
649 break;
650#endif
651 case ASM_DATA_EVENT_READ_DONE:{
652
653 struct audio_port_data *port = &ac->port[OUT];
654
655 pr_debug("%s:R-D: status=%d buff_add=%x act_size=%d offset=%d\n",
656 __func__, payload[READDONE_IDX_STATUS],
657 payload[READDONE_IDX_BUFFER],
658 payload[READDONE_IDX_SIZE],
659 payload[READDONE_IDX_OFFSET]);
660 pr_debug("%s:R-D:msw_ts=%d lsw_ts=%d flags=%d id=%d num=%d\n",
661 __func__, payload[READDONE_IDX_MSW_TS],
662 payload[READDONE_IDX_LSW_TS],
663 payload[READDONE_IDX_FLAGS],
664 payload[READDONE_IDX_ID],
665 payload[READDONE_IDX_NUMFRAMES]);
666
667 if (ac->io_mode == SYNC_IO_MODE) {
668 if (port->buf == NULL) {
669 pr_err("%s: Unexpected Write Done\n", __func__);
670 return -EINVAL;
671 }
672 spin_lock_irqsave(&port->dsp_lock, dsp_flags);
673 token = data->token;
674 port->buf[token].used = 0;
675 if (port->buf[token].phys !=
676 payload[READDONE_IDX_BUFFER]) {
677 pr_err("Buf expected[%p]rxed[%p]\n",\
678 (void *)port->buf[token].phys,\
679 (void *)payload[READDONE_IDX_BUFFER]);
680 spin_unlock_irqrestore(&port->dsp_lock,
681 dsp_flags);
682 break;
683 }
684 port->buf[token].actual_size =
685 payload[READDONE_IDX_SIZE];
686 spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
687 }
688 break;
689 }
690 case ASM_DATA_EVENT_EOS:
691 case ASM_DATA_CMDRSP_EOS:
692 pr_debug("%s:EOS ACK received: rxed opcode[0x%x]\n",
693 __func__, data->opcode);
694 break;
695 case ASM_STREAM_CMDRSP_GET_ENCDEC_PARAM:
696 break;
697 case ASM_SESSION_EVENT_TX_OVERFLOW:
698 pr_err("ASM_SESSION_EVENT_TX_OVERFLOW\n");
699 break;
700 case ASM_SESSION_CMDRSP_GET_SESSION_TIME:
701 pr_debug("%s: ASM_SESSION_CMDRSP_GET_SESSION_TIME, "
702 "payload[0] = %d, payload[1] = %d, "
703 "payload[2] = %d\n", __func__,
704 payload[0], payload[1], payload[2]);
705 ac->time_stamp = (uint64_t)(((uint64_t)payload[1] << 32) |
706 payload[2]);
707 if (atomic_read(&ac->time_flag)) {
708 atomic_set(&ac->time_flag, 0);
709 wake_up(&ac->time_wait);
710 }
711 break;
712 case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
713 pr_debug("%s: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, "
714 "payload[0] = %d, payload[1] = %d, "
715 "payload[2] = %d, payload[3] = %d\n", __func__,
716 payload[0], payload[1], payload[2],
717 payload[3]);
718 break;
719 }
720 if (ac->cb)
721 ac->cb(data->opcode, data->token,
722 data->payload, ac->priv);
723
724 return 0;
725}
726
727void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size,
728 uint32_t *index)
729{
730 void *data;
731 unsigned char idx;
732 struct audio_port_data *port;
733
734 if (!ac || ((dir != IN) && (dir != OUT)))
735 return NULL;
736
737 if (ac->io_mode == SYNC_IO_MODE) {
738 port = &ac->port[dir];
739
740 mutex_lock(&port->lock);
741 idx = port->cpu_buf;
742 if (port->buf == NULL) {
743 pr_debug("%s:Buffer pointer null\n", __func__);
744 return NULL;
745 }
746 /* dir 0: used = 0 means buf in use
747 dir 1: used = 1 means buf in use */
748 if (port->buf[idx].used == dir) {
749 /* To make it more robust, we could loop and get the
750 next avail buf, its risky though */
751 pr_debug("%s:Next buf idx[0x%x] not available,\
752 dir[%d]\n", __func__, idx, dir);
753 mutex_unlock(&port->lock);
754 return NULL;
755 }
756 *size = port->buf[idx].actual_size;
757 *index = port->cpu_buf;
758 data = port->buf[idx].data;
759 pr_debug("%s:session[%d]index[%d] data[%p]size[%d]\n",
760 __func__,
761 ac->session,
762 port->cpu_buf,
763 data, *size);
764 /* By default increase the cpu_buf cnt
765 user accesses this function,increase cpu
766 buf(to avoid another api)*/
767 port->buf[idx].used = dir;
768 port->cpu_buf = ((port->cpu_buf + 1) & (port->max_buf_cnt - 1));
769 mutex_unlock(&port->lock);
770 return data;
771 }
772 return NULL;
773}
774
775int q6asm_is_dsp_buf_avail(int dir, struct audio_client *ac)
776{
777 int ret = -1;
778 struct audio_port_data *port;
779 uint32_t idx;
780
781 if (!ac || (dir != OUT))
782 return ret;
783
784 if (ac->io_mode == SYNC_IO_MODE) {
785 port = &ac->port[dir];
786
787 mutex_lock(&port->lock);
788 idx = port->dsp_buf;
789
790 if (port->buf[idx].used == (dir ^ 1)) {
791 /* To make it more robust, we could loop and get the
792 next avail buf, its risky though */
793 pr_err("Next buf idx[0x%x] not available, dir[%d]\n",
794 idx, dir);
795 mutex_unlock(&port->lock);
796 return ret;
797 }
798 pr_debug("%s: session[%d]dsp_buf=%d cpu_buf=%d\n", __func__,
799 ac->session, port->dsp_buf, port->cpu_buf);
800 ret = ((port->dsp_buf != port->cpu_buf) ? 0 : -1);
801 mutex_unlock(&port->lock);
802 }
803 return ret;
804}
805
806static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
807 uint32_t pkt_size, uint32_t cmd_flg)
808{
809 pr_debug("%s:session=%d pkt size=%d cmd_flg=%d\n", __func__, pkt_size,
810 cmd_flg, ac->session);
811 mutex_lock(&ac->cmd_lock);
812 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
813 APR_HDR_LEN(sizeof(struct apr_hdr)),\
814 APR_PKT_VER);
815 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
816 hdr->src_domain = APR_DOMAIN_APPS;
817 hdr->dest_svc = APR_SVC_ASM;
818 hdr->dest_domain = APR_DOMAIN_ADSP;
819 hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01;
820 hdr->dest_port = ((ac->session << 8) & 0xFF00) | 0x01;
821 if (cmd_flg) {
822 hdr->token = ac->session;
823 atomic_set(&ac->cmd_state, 1);
824 }
825 hdr->pkt_size = pkt_size;
826 mutex_unlock(&ac->cmd_lock);
827 return;
828}
829
830static void q6asm_add_mmaphdr(struct apr_hdr *hdr, uint32_t pkt_size,
831 uint32_t cmd_flg)
832{
833 pr_debug("%s:pkt size=%d cmd_flg=%d\n", __func__, pkt_size, cmd_flg);
834 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
835 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
836 hdr->src_port = 0;
837 hdr->dest_port = 0;
838 if (cmd_flg) {
839 hdr->token = 0;
840 atomic_set(&this_mmap.cmd_state, 1);
841 }
842 hdr->pkt_size = pkt_size;
843 return;
844}
845
846int q6asm_open_read(struct audio_client *ac,
847 uint32_t format)
848{
849 int rc = 0x00;
850 struct asm_stream_cmd_open_read open;
851
852 if ((ac == NULL) || (ac->apr == NULL)) {
853 pr_err("%s: APR handle NULL\n", __func__);
854 return -EINVAL;
855 }
856 pr_debug("%s:session[%d]", __func__, ac->session);
857
858 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
859 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ;
860 /* Stream prio : High, provide meta info with encoded frames */
861 open.src_endpoint = ASM_END_POINT_DEVICE_MATRIX;
862
863 open.pre_proc_top = get_asm_topology();
864 if (open.pre_proc_top == 0)
865 open.pre_proc_top = DEFAULT_POPP_TOPOLOGY;
866
867 switch (format) {
868 case FORMAT_LINEAR_PCM:
869 open.uMode = STREAM_PRIORITY_HIGH;
870 open.format = LINEAR_PCM;
871 break;
872 case FORMAT_MPEG4_AAC:
873 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
874 open.format = MPEG4_AAC;
875 break;
876 case FORMAT_V13K:
877 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
878 open.format = V13K_FS;
879 break;
880 case FORMAT_EVRC:
881 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
882 open.format = EVRC_FS;
883 break;
884 case FORMAT_AMRNB:
885 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
886 open.format = AMRNB_FS;
887 break;
888 default:
889 pr_err("Invalid format[%d]\n", format);
890 goto fail_cmd;
891 }
892 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
893 if (rc < 0) {
894 pr_err("open failed op[0x%x]rc[%d]\n", \
895 open.hdr.opcode, rc);
896 goto fail_cmd;
897 }
898 rc = wait_event_timeout(ac->cmd_wait,
899 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
900 if (!rc) {
901 pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
902 rc);
903 goto fail_cmd;
904 }
905 return 0;
906fail_cmd:
907 return -EINVAL;
908}
909
910int q6asm_open_write(struct audio_client *ac, uint32_t format)
911{
912 int rc = 0x00;
913 struct asm_stream_cmd_open_write open;
914
915 if ((ac == NULL) || (ac->apr == NULL)) {
916 pr_err("%s: APR handle NULL\n", __func__);
917 return -EINVAL;
918 }
919 pr_debug("%s: session[%d] wr_format[0x%x]", __func__, ac->session,
920 format);
921
922 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
923
924 open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE;
925 open.uMode = STREAM_PRIORITY_HIGH;
926 /* source endpoint : matrix */
927 open.sink_endpoint = ASM_END_POINT_DEVICE_MATRIX;
928 open.stream_handle = 0x00;
929
930 open.post_proc_top = get_asm_topology();
931 if (open.post_proc_top == 0)
932 open.post_proc_top = DEFAULT_POPP_TOPOLOGY;
933
934 switch (format) {
935 case FORMAT_LINEAR_PCM:
936 open.format = LINEAR_PCM;
937 break;
938 case FORMAT_MPEG4_AAC:
939 open.format = MPEG4_AAC;
940 break;
941 case FORMAT_WMA_V9:
942 open.format = WMA_V9;
943 break;
944 case FORMAT_WMA_V10PRO:
945 open.format = WMA_V10PRO;
946 break;
947 default:
948 pr_err("%s: Invalid format[%d]\n", __func__, format);
949 goto fail_cmd;
950 }
951 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
952 if (rc < 0) {
953 pr_err("%s: open failed op[0x%x]rc[%d]\n", \
954 __func__, open.hdr.opcode, rc);
955 goto fail_cmd;
956 }
957 rc = wait_event_timeout(ac->cmd_wait,
958 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
959 if (!rc) {
960 pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
961 rc);
962 goto fail_cmd;
963 }
964 return 0;
965fail_cmd:
966 return -EINVAL;
967}
968
969int q6asm_open_read_write(struct audio_client *ac,
970 uint32_t rd_format,
971 uint32_t wr_format)
972{
973 int rc = 0x00;
974 struct asm_stream_cmd_open_read_write open;
975
976 if ((ac == NULL) || (ac->apr == NULL)) {
977 pr_err("APR handle NULL\n");
978 return -EINVAL;
979 }
980 pr_debug("%s: session[%d]", __func__, ac->session);
981 pr_debug("wr_format[0x%x]rd_format[0x%x]",
982 wr_format, rd_format);
983
984 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
985 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READWRITE;
986
987 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_NORMAL |
988 SR_CM_NOTIFY_ENABLE;
989 /* source endpoint : matrix */
990 open.post_proc_top = get_asm_topology();
991 if (open.post_proc_top == 0)
992 open.post_proc_top = DEFAULT_POPP_TOPOLOGY;
993
994 switch (wr_format) {
995 case FORMAT_LINEAR_PCM:
996 open.write_format = LINEAR_PCM;
997 break;
998 case FORMAT_MPEG4_AAC:
999 open.write_format = MPEG4_AAC;
1000 break;
1001 case FORMAT_WMA_V9:
1002 open.write_format = WMA_V9;
1003 break;
1004 case FORMAT_WMA_V10PRO:
1005 open.write_format = WMA_V10PRO;
1006 break;
1007 default:
1008 pr_err("Invalid format[%d]\n", wr_format);
1009 goto fail_cmd;
1010 }
1011
1012 switch (rd_format) {
1013 case FORMAT_LINEAR_PCM:
1014 open.read_format = LINEAR_PCM;
1015 break;
1016 case FORMAT_MPEG4_AAC:
1017 open.read_format = MPEG4_AAC;
1018 break;
1019 case FORMAT_V13K:
1020 open.read_format = V13K_FS;
1021 break;
1022 case FORMAT_EVRC:
1023 open.read_format = EVRC_FS;
1024 break;
1025 case FORMAT_AMRNB:
1026 open.read_format = AMRNB_FS;
1027 break;
1028 default:
1029 pr_err("Invalid format[%d]\n", rd_format);
1030 goto fail_cmd;
1031 }
1032 pr_debug("%s:rdformat[0x%x]wrformat[0x%x]\n", __func__,
1033 open.read_format, open.write_format);
1034
1035 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1036 if (rc < 0) {
1037 pr_err("open failed op[0x%x]rc[%d]\n", \
1038 open.hdr.opcode, rc);
1039 goto fail_cmd;
1040 }
1041 rc = wait_event_timeout(ac->cmd_wait,
1042 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1043 if (!rc) {
1044 pr_err("timeout. waited for OPEN_WRITE rc[%d]\n", rc);
1045 goto fail_cmd;
1046 }
1047 return 0;
1048fail_cmd:
1049 return -EINVAL;
1050}
1051
1052int q6asm_run(struct audio_client *ac, uint32_t flags,
1053 uint32_t msw_ts, uint32_t lsw_ts)
1054{
1055 struct asm_stream_cmd_run run;
1056 int rc;
1057 if (!ac || ac->apr == NULL) {
1058 pr_err("APR handle NULL\n");
1059 return -EINVAL;
1060 }
1061 pr_debug("%s session[%d]", __func__, ac->session);
1062 q6asm_add_hdr(ac, &run.hdr, sizeof(run), TRUE);
1063
1064 run.hdr.opcode = ASM_SESSION_CMD_RUN;
1065 run.flags = flags;
1066 run.msw_ts = msw_ts;
1067 run.lsw_ts = lsw_ts;
1068
1069 rc = apr_send_pkt(ac->apr, (uint32_t *) &run);
1070 if (rc < 0) {
1071 pr_err("Commmand run failed[%d]", rc);
1072 goto fail_cmd;
1073 }
1074
1075 rc = wait_event_timeout(ac->cmd_wait,
1076 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1077 if (!rc) {
1078 pr_err("timeout. waited for run success rc[%d]", rc);
1079 goto fail_cmd;
1080 }
1081
1082 return 0;
1083fail_cmd:
1084 return -EINVAL;
1085}
1086
1087int q6asm_run_nowait(struct audio_client *ac, uint32_t flags,
1088 uint32_t msw_ts, uint32_t lsw_ts)
1089{
1090 struct asm_stream_cmd_run run;
1091 int rc;
1092 if (!ac || ac->apr == NULL) {
1093 pr_err("%s:APR handle NULL\n", __func__);
1094 return -EINVAL;
1095 }
1096 pr_debug("session[%d]", ac->session);
1097 q6asm_add_hdr_async(ac, &run.hdr, sizeof(run), TRUE);
1098
1099 run.hdr.opcode = ASM_SESSION_CMD_RUN;
1100 run.flags = flags;
1101 run.msw_ts = msw_ts;
1102 run.lsw_ts = lsw_ts;
1103
1104 rc = apr_send_pkt(ac->apr, (uint32_t *) &run);
1105 if (rc < 0) {
1106 pr_err("%s:Commmand run failed[%d]", __func__, rc);
1107 return -EINVAL;
1108 }
1109 return 0;
1110}
1111
1112
1113int q6asm_enc_cfg_blk_aac(struct audio_client *ac,
1114 uint32_t frames_per_buf,
1115 uint32_t sample_rate, uint32_t channels,
1116 uint32_t bit_rate, uint32_t mode, uint32_t format)
1117{
1118 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1119 int rc = 0;
1120
1121 pr_debug("%s:session[%d]frames[%d]SR[%d]ch[%d]bitrate[%d]mode[%d]"
1122 "format[%d]", __func__, ac->session, frames_per_buf,
1123 sample_rate, channels, bit_rate, mode, format);
1124
1125 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1126
1127 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1128 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1129 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1130 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
1131 enc_cfg.enc_blk.format_id = MPEG4_AAC;
1132 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_aac_read_cfg);
1133 enc_cfg.enc_blk.cfg.aac.bitrate = bit_rate;
1134 enc_cfg.enc_blk.cfg.aac.enc_mode = mode;
1135 enc_cfg.enc_blk.cfg.aac.format = format;
1136 enc_cfg.enc_blk.cfg.aac.ch_cfg = channels;
1137 enc_cfg.enc_blk.cfg.aac.sample_rate = sample_rate;
1138
1139 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
1140 if (rc < 0) {
1141 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
1142 rc = -EINVAL;
1143 goto fail_cmd;
1144 }
1145 rc = wait_event_timeout(ac->cmd_wait,
1146 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1147 if (!rc) {
1148 pr_err("timeout. waited for FORMAT_UPDATE\n");
1149 goto fail_cmd;
1150 }
1151 return 0;
1152fail_cmd:
1153 return -EINVAL;
1154}
1155
1156int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
1157 uint32_t rate, uint32_t channels)
1158{
1159 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1160
1161 int rc = 0;
1162
1163 pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
1164 ac->session, rate, channels);
1165
1166 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1167
1168 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1169 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1170 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1171 enc_cfg.enc_blk.frames_per_buf = 1;
1172 enc_cfg.enc_blk.format_id = LINEAR_PCM;
1173 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_pcm_cfg);
1174 enc_cfg.enc_blk.cfg.pcm.ch_cfg = channels;
1175 enc_cfg.enc_blk.cfg.pcm.bits_per_sample = 16;
1176 enc_cfg.enc_blk.cfg.pcm.sample_rate = rate;
1177 enc_cfg.enc_blk.cfg.pcm.is_signed = 1;
1178 enc_cfg.enc_blk.cfg.pcm.interleaved = 1;
1179
1180 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
1181 if (rc < 0) {
1182 pr_err("Comamnd open failed\n");
1183 rc = -EINVAL;
1184 goto fail_cmd;
1185 }
1186 rc = wait_event_timeout(ac->cmd_wait,
1187 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1188 if (!rc) {
1189 pr_err("timeout opcode[0x%x] ", enc_cfg.hdr.opcode);
1190 goto fail_cmd;
1191 }
1192 return 0;
1193fail_cmd:
1194 return -EINVAL;
1195}
1196
1197int q6asm_enable_sbrps(struct audio_client *ac,
1198 uint32_t sbr_ps_enable)
1199{
1200 struct asm_stream_cmd_encdec_sbr sbrps;
1201
1202 int rc = 0;
1203
1204 pr_debug("%s: Session %d\n", __func__, ac->session);
1205
1206 q6asm_add_hdr(ac, &sbrps.hdr, sizeof(sbrps), TRUE);
1207
1208 sbrps.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1209 sbrps.param_id = ASM_ENABLE_SBR_PS;
1210 sbrps.param_size = sizeof(struct asm_sbr_ps);
1211 sbrps.sbr_ps.enable = sbr_ps_enable;
1212
1213 rc = apr_send_pkt(ac->apr, (uint32_t *) &sbrps);
1214 if (rc < 0) {
1215 pr_err("Command opcode[0x%x]paramid[0x%x] failed\n",
1216 ASM_STREAM_CMD_SET_ENCDEC_PARAM,
1217 ASM_ENABLE_SBR_PS);
1218 rc = -EINVAL;
1219 goto fail_cmd;
1220 }
1221 rc = wait_event_timeout(ac->cmd_wait,
1222 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1223 if (!rc) {
1224 pr_err("timeout opcode[0x%x] ", sbrps.hdr.opcode);
1225 goto fail_cmd;
1226 }
1227 return 0;
1228fail_cmd:
1229 return -EINVAL;
1230}
1231
1232int q6asm_enc_cfg_blk_qcelp(struct audio_client *ac, uint32_t frames_per_buf,
1233 uint16_t min_rate, uint16_t max_rate,
1234 uint16_t reduced_rate_level, uint16_t rate_modulation_cmd)
1235{
1236 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1237 int rc = 0;
1238
1239 pr_debug("%s:session[%d]frames[%d]min_rate[0x%4x]max_rate[0x%4x] \
1240 reduced_rate_level[0x%4x]rate_modulation_cmd[0x%4x]", __func__,
1241 ac->session, frames_per_buf, min_rate, max_rate,
1242 reduced_rate_level, rate_modulation_cmd);
1243
1244 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1245
1246 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1247
1248 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1249 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1250
1251 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
1252 enc_cfg.enc_blk.format_id = V13K_FS;
1253 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_qcelp13_read_cfg);
1254 enc_cfg.enc_blk.cfg.qcelp13.min_rate = min_rate;
1255 enc_cfg.enc_blk.cfg.qcelp13.max_rate = max_rate;
1256 enc_cfg.enc_blk.cfg.qcelp13.reduced_rate_level = reduced_rate_level;
1257 enc_cfg.enc_blk.cfg.qcelp13.rate_modulation_cmd = rate_modulation_cmd;
1258
1259 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
1260 if (rc < 0) {
1261 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
1262 goto fail_cmd;
1263 }
1264 rc = wait_event_timeout(ac->cmd_wait,
1265 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1266 if (!rc) {
1267 pr_err("timeout. waited for FORMAT_UPDATE\n");
1268 goto fail_cmd;
1269 }
1270 return 0;
1271fail_cmd:
1272 return -EINVAL;
1273}
1274
1275int q6asm_enc_cfg_blk_evrc(struct audio_client *ac, uint32_t frames_per_buf,
1276 uint16_t min_rate, uint16_t max_rate,
1277 uint16_t rate_modulation_cmd)
1278{
1279 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1280 int rc = 0;
1281
1282 pr_debug("%s:session[%d]frames[%d]min_rate[0x%4x]max_rate[0x%4x] \
1283 rate_modulation_cmd[0x%4x]", __func__, ac->session,
1284 frames_per_buf, min_rate, max_rate, rate_modulation_cmd);
1285
1286 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1287
1288 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1289
1290 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1291 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1292
1293 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
1294 enc_cfg.enc_blk.format_id = EVRC_FS;
1295 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_evrc_read_cfg);
1296 enc_cfg.enc_blk.cfg.evrc.min_rate = min_rate;
1297 enc_cfg.enc_blk.cfg.evrc.max_rate = max_rate;
1298 enc_cfg.enc_blk.cfg.evrc.rate_modulation_cmd = rate_modulation_cmd;
1299 enc_cfg.enc_blk.cfg.evrc.reserved = 0;
1300
1301 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
1302 if (rc < 0) {
1303 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
1304 goto fail_cmd;
1305 }
1306 rc = wait_event_timeout(ac->cmd_wait,
1307 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1308 if (!rc) {
1309 pr_err("timeout. waited for FORMAT_UPDATE\n");
1310 goto fail_cmd;
1311 }
1312 return 0;
1313fail_cmd:
1314 return -EINVAL;
1315}
1316
1317int q6asm_enc_cfg_blk_amrnb(struct audio_client *ac, uint32_t frames_per_buf,
1318 uint16_t band_mode, uint16_t dtx_enable)
1319{
1320 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1321 int rc = 0;
1322
1323 pr_debug("%s:session[%d]frames[%d]band_mode[0x%4x]dtx_enable[0x%4x]",
1324 __func__, ac->session, frames_per_buf, band_mode, dtx_enable);
1325
1326 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1327
1328 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1329
1330 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1331 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1332
1333 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
1334 enc_cfg.enc_blk.format_id = AMRNB_FS;
1335 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_amrnb_read_cfg);
1336 enc_cfg.enc_blk.cfg.amrnb.mode = band_mode;
1337 enc_cfg.enc_blk.cfg.amrnb.dtx_mode = dtx_enable;
1338
1339 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
1340 if (rc < 0) {
1341 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
1342 goto fail_cmd;
1343 }
1344 rc = wait_event_timeout(ac->cmd_wait,
1345 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1346 if (!rc) {
1347 pr_err("timeout. waited for FORMAT_UPDATE\n");
1348 goto fail_cmd;
1349 }
1350 return 0;
1351fail_cmd:
1352 return -EINVAL;
1353}
1354
1355int q6asm_media_format_block_pcm(struct audio_client *ac,
1356 uint32_t rate, uint32_t channels)
1357{
1358 struct asm_stream_media_format_update fmt;
1359 int rc = 0;
1360
1361 pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
1362 channels);
1363
1364 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
1365
1366 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
1367
1368 fmt.format = LINEAR_PCM;
1369 fmt.cfg_size = sizeof(struct asm_pcm_cfg);
1370 fmt.write_cfg.pcm_cfg.ch_cfg = channels;
1371 fmt.write_cfg.pcm_cfg.bits_per_sample = 16;
1372 fmt.write_cfg.pcm_cfg.sample_rate = rate;
1373 fmt.write_cfg.pcm_cfg.is_signed = 1;
1374 fmt.write_cfg.pcm_cfg.interleaved = 1;
1375
1376 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
1377 if (rc < 0) {
1378 pr_err("%s:Comamnd open failed\n", __func__);
1379 goto fail_cmd;
1380 }
1381 rc = wait_event_timeout(ac->cmd_wait,
1382 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1383 if (!rc) {
1384 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
1385 goto fail_cmd;
1386 }
1387 return 0;
1388fail_cmd:
1389 return -EINVAL;
1390}
1391
1392int q6asm_media_format_block_aac(struct audio_client *ac,
1393 struct asm_aac_cfg *cfg)
1394{
1395 struct asm_stream_media_format_update fmt;
1396 int rc = 0;
1397
1398 pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session,
1399 cfg->sample_rate, cfg->ch_cfg);
1400
1401 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
1402
1403 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
1404
1405 fmt.format = MPEG4_AAC;
1406 fmt.cfg_size = sizeof(struct asm_aac_cfg);
1407 fmt.write_cfg.aac_cfg.format = cfg->format;
1408 fmt.write_cfg.aac_cfg.aot = cfg->aot;
1409 fmt.write_cfg.aac_cfg.ep_config = cfg->ep_config;
1410 fmt.write_cfg.aac_cfg.section_data_resilience =
1411 cfg->section_data_resilience;
1412 fmt.write_cfg.aac_cfg.scalefactor_data_resilience =
1413 cfg->scalefactor_data_resilience;
1414 fmt.write_cfg.aac_cfg.spectral_data_resilience =
1415 cfg->spectral_data_resilience;
1416 fmt.write_cfg.aac_cfg.ch_cfg = cfg->ch_cfg;
1417 fmt.write_cfg.aac_cfg.sample_rate = cfg->sample_rate;
1418 pr_info("%s:format=%x cfg_size=%d aac-cfg=%x aot=%d ch=%d sr=%d\n",
1419 __func__, fmt.format, fmt.cfg_size,
1420 fmt.write_cfg.aac_cfg.format,
1421 fmt.write_cfg.aac_cfg.aot,
1422 fmt.write_cfg.aac_cfg.ch_cfg,
1423 fmt.write_cfg.aac_cfg.sample_rate);
1424 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
1425 if (rc < 0) {
1426 pr_err("%s:Comamnd open failed\n", __func__);
1427 goto fail_cmd;
1428 }
1429 rc = wait_event_timeout(ac->cmd_wait,
1430 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1431 if (!rc) {
1432 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
1433 goto fail_cmd;
1434 }
1435 return 0;
1436fail_cmd:
1437 return -EINVAL;
1438}
1439
1440int q6asm_media_format_block_wma(struct audio_client *ac,
1441 void *cfg)
1442{
1443 struct asm_stream_media_format_update fmt;
1444 struct asm_wma_cfg *wma_cfg = (struct asm_wma_cfg *)cfg;
1445 int rc = 0;
1446
1447 pr_debug("session[%d]format_tag[0x%4x] rate[%d] ch[0x%4x] bps[%d],\
1448 balign[0x%4x], bit_sample[0x%4x], ch_msk[%d], enc_opt[0x%4x]\n",
1449 ac->session, wma_cfg->format_tag, wma_cfg->sample_rate,
1450 wma_cfg->ch_cfg, wma_cfg->avg_bytes_per_sec,
1451 wma_cfg->block_align, wma_cfg->valid_bits_per_sample,
1452 wma_cfg->ch_mask, wma_cfg->encode_opt);
1453
1454 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
1455
1456 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
1457
1458 fmt.format = WMA_V9;
1459 fmt.cfg_size = sizeof(struct asm_wma_cfg);
1460 fmt.write_cfg.wma_cfg.format_tag = wma_cfg->format_tag;
1461 fmt.write_cfg.wma_cfg.ch_cfg = wma_cfg->ch_cfg;
1462 fmt.write_cfg.wma_cfg.sample_rate = wma_cfg->sample_rate;
1463 fmt.write_cfg.wma_cfg.avg_bytes_per_sec = wma_cfg->avg_bytes_per_sec;
1464 fmt.write_cfg.wma_cfg.block_align = wma_cfg->block_align;
1465 fmt.write_cfg.wma_cfg.valid_bits_per_sample =
1466 wma_cfg->valid_bits_per_sample;
1467 fmt.write_cfg.wma_cfg.ch_mask = wma_cfg->ch_mask;
1468 fmt.write_cfg.wma_cfg.encode_opt = wma_cfg->encode_opt;
1469 fmt.write_cfg.wma_cfg.adv_encode_opt = 0;
1470 fmt.write_cfg.wma_cfg.adv_encode_opt2 = 0;
1471 fmt.write_cfg.wma_cfg.drc_peak_ref = 0;
1472 fmt.write_cfg.wma_cfg.drc_peak_target = 0;
1473 fmt.write_cfg.wma_cfg.drc_ave_ref = 0;
1474 fmt.write_cfg.wma_cfg.drc_ave_target = 0;
1475
1476 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
1477 if (rc < 0) {
1478 pr_err("%s:Comamnd open failed\n", __func__);
1479 goto fail_cmd;
1480 }
1481 rc = wait_event_timeout(ac->cmd_wait,
1482 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1483 if (!rc) {
1484 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
1485 goto fail_cmd;
1486 }
1487 return 0;
1488fail_cmd:
1489 return -EINVAL;
1490}
1491
1492int q6asm_media_format_block_wmapro(struct audio_client *ac,
1493 void *cfg)
1494{
1495 struct asm_stream_media_format_update fmt;
1496 struct asm_wmapro_cfg *wmapro_cfg = (struct asm_wmapro_cfg *)cfg;
1497 int rc = 0;
1498
1499 pr_debug("session[%d]format_tag[0x%4x] rate[%d] ch[0x%4x] bps[%d],"
1500 "balign[0x%4x], bit_sample[0x%4x], ch_msk[%d], enc_opt[0x%4x],\
1501 adv_enc_opt[0x%4x], adv_enc_opt2[0x%8x]\n",
1502 ac->session, wmapro_cfg->format_tag, wmapro_cfg->sample_rate,
1503 wmapro_cfg->ch_cfg, wmapro_cfg->avg_bytes_per_sec,
1504 wmapro_cfg->block_align, wmapro_cfg->valid_bits_per_sample,
1505 wmapro_cfg->ch_mask, wmapro_cfg->encode_opt,
1506 wmapro_cfg->adv_encode_opt, wmapro_cfg->adv_encode_opt2);
1507
1508 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
1509
1510 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
1511
1512 fmt.format = WMA_V10PRO;
1513 fmt.cfg_size = sizeof(struct asm_wmapro_cfg);
1514 fmt.write_cfg.wmapro_cfg.format_tag = wmapro_cfg->format_tag;
1515 fmt.write_cfg.wmapro_cfg.ch_cfg = wmapro_cfg->ch_cfg;
1516 fmt.write_cfg.wmapro_cfg.sample_rate = wmapro_cfg->sample_rate;
1517 fmt.write_cfg.wmapro_cfg.avg_bytes_per_sec =
1518 wmapro_cfg->avg_bytes_per_sec;
1519 fmt.write_cfg.wmapro_cfg.block_align = wmapro_cfg->block_align;
1520 fmt.write_cfg.wmapro_cfg.valid_bits_per_sample =
1521 wmapro_cfg->valid_bits_per_sample;
1522 fmt.write_cfg.wmapro_cfg.ch_mask = wmapro_cfg->ch_mask;
1523 fmt.write_cfg.wmapro_cfg.encode_opt = wmapro_cfg->encode_opt;
1524 fmt.write_cfg.wmapro_cfg.adv_encode_opt = wmapro_cfg->adv_encode_opt;
1525 fmt.write_cfg.wmapro_cfg.adv_encode_opt2 = wmapro_cfg->adv_encode_opt2;
1526 fmt.write_cfg.wmapro_cfg.drc_peak_ref = 0;
1527 fmt.write_cfg.wmapro_cfg.drc_peak_target = 0;
1528 fmt.write_cfg.wmapro_cfg.drc_ave_ref = 0;
1529 fmt.write_cfg.wmapro_cfg.drc_ave_target = 0;
1530
1531 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
1532 if (rc < 0) {
1533 pr_err("%s:Comamnd open failed\n", __func__);
1534 goto fail_cmd;
1535 }
1536 rc = wait_event_timeout(ac->cmd_wait,
1537 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1538 if (!rc) {
1539 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
1540 goto fail_cmd;
1541 }
1542 return 0;
1543fail_cmd:
1544 return -EINVAL;
1545}
1546
1547int q6asm_memory_map(struct audio_client *ac, uint32_t buf_add, int dir,
1548 uint32_t bufsz, uint32_t bufcnt)
1549{
1550 struct asm_stream_cmd_memory_map mem_map;
1551 int rc = 0;
1552
1553 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
1554 pr_err("APR handle NULL\n");
1555 return -EINVAL;
1556 }
1557
1558 pr_debug("%s: Session[%d]\n", __func__, ac->session);
1559
1560 mem_map.hdr.opcode = ASM_SESSION_CMD_MEMORY_MAP;
1561
1562 mem_map.buf_add = buf_add;
1563 mem_map.buf_size = bufsz * bufcnt;
1564 mem_map.mempool_id = 0; /* EBI */
1565 mem_map.reserved = 0;
1566
1567 q6asm_add_mmaphdr(&mem_map.hdr,
1568 sizeof(struct asm_stream_cmd_memory_map), TRUE);
1569
1570 pr_debug("buf add[%x] buf_add_parameter[%x]\n",
1571 mem_map.buf_add, buf_add);
1572
1573 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_map);
1574 if (rc < 0) {
1575 pr_err("mem_map op[0x%x]rc[%d]\n",
1576 mem_map.hdr.opcode, rc);
1577 rc = -EINVAL;
1578 goto fail_cmd;
1579 }
1580
1581 rc = wait_event_timeout(this_mmap.cmd_wait,
1582 (atomic_read(&this_mmap.cmd_state) == 0), 5 * HZ);
1583 if (!rc) {
1584 pr_err("timeout. waited for memory_map\n");
1585 rc = -EINVAL;
1586 goto fail_cmd;
1587 }
1588 rc = 0;
1589fail_cmd:
1590 return rc;
1591}
1592
1593int q6asm_memory_unmap(struct audio_client *ac, uint32_t buf_add, int dir)
1594{
1595 struct asm_stream_cmd_memory_unmap mem_unmap;
1596 int rc = 0;
1597
1598 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
1599 pr_err("APR handle NULL\n");
1600 return -EINVAL;
1601 }
1602 pr_debug("%s: Session[%d]\n", __func__, ac->session);
1603
1604 q6asm_add_mmaphdr(&mem_unmap.hdr,
1605 sizeof(struct asm_stream_cmd_memory_unmap), TRUE);
1606 mem_unmap.hdr.opcode = ASM_SESSION_CMD_MEMORY_UNMAP;
1607 mem_unmap.buf_add = buf_add;
1608
1609 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_unmap);
1610 if (rc < 0) {
1611 pr_err("mem_unmap op[0x%x]rc[%d]\n",
1612 mem_unmap.hdr.opcode, rc);
1613 rc = -EINVAL;
1614 goto fail_cmd;
1615 }
1616
1617 rc = wait_event_timeout(this_mmap.cmd_wait,
1618 (atomic_read(&this_mmap.cmd_state) == 0), 5 * HZ);
1619 if (!rc) {
1620 pr_err("timeout. waited for memory_map\n");
1621 rc = -EINVAL;
1622 goto fail_cmd;
1623 }
1624 rc = 0;
1625fail_cmd:
1626 return rc;
1627}
1628
1629int q6asm_set_lrgain(struct audio_client *ac, int left_gain, int right_gain)
1630{
1631 void *vol_cmd = NULL;
1632 void *payload = NULL;
1633 struct asm_pp_params_command *cmd = NULL;
1634 struct asm_lrchannel_gain_params *lrgain = NULL;
1635 int sz = 0;
1636 int rc = 0;
1637
1638 sz = sizeof(struct asm_pp_params_command) +
1639 + sizeof(struct asm_lrchannel_gain_params);
1640 vol_cmd = kzalloc(sz, GFP_KERNEL);
1641 if (vol_cmd == NULL) {
1642 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
1643 rc = -EINVAL;
1644 return rc;
1645 }
1646 cmd = (struct asm_pp_params_command *)vol_cmd;
1647 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
1648 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
1649 cmd->payload = NULL;
1650 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
1651 sizeof(struct asm_lrchannel_gain_params);
1652 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
1653 cmd->params.param_id = L_R_CHANNEL_GAIN_PARAM_ID;
1654 cmd->params.param_size = sizeof(struct asm_lrchannel_gain_params);
1655 cmd->params.reserved = 0;
1656
1657 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
1658 lrgain = (struct asm_lrchannel_gain_params *)payload;
1659
1660 lrgain->left_gain = left_gain;
1661 lrgain->right_gain = right_gain;
1662 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
1663 if (rc < 0) {
1664 pr_err("%s: Volume Command failed\n", __func__);
1665 rc = -EINVAL;
1666 goto fail_cmd;
1667 }
1668
1669 rc = wait_event_timeout(ac->cmd_wait,
1670 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1671 if (!rc) {
1672 pr_err("%s: timeout in sending volume command to apr\n",
1673 __func__);
1674 rc = -EINVAL;
1675 goto fail_cmd;
1676 }
1677 rc = 0;
1678fail_cmd:
1679 kfree(vol_cmd);
1680 return rc;
1681}
1682
1683static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
1684 uint32_t bufsz, uint32_t bufcnt)
1685{
1686 struct asm_stream_cmd_memory_map_regions *mmap_regions = NULL;
1687 struct asm_memory_map_regions *mregions = NULL;
1688 struct audio_port_data *port = NULL;
1689 struct audio_buffer *ab = NULL;
1690 void *mmap_region_cmd = NULL;
1691 void *payload = NULL;
1692 int rc = 0;
1693 int i = 0;
1694 int cmd_size = 0;
1695
1696 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
1697 pr_err("APR handle NULL\n");
1698 return -EINVAL;
1699 }
1700 pr_debug("%s: Session[%d]\n", __func__, ac->session);
1701
1702 cmd_size = sizeof(struct asm_stream_cmd_memory_map_regions)
1703 + sizeof(struct asm_memory_map_regions) * bufcnt;
1704
1705 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1706 mmap_regions = (struct asm_stream_cmd_memory_map_regions *)
1707 mmap_region_cmd;
1708 q6asm_add_mmaphdr(&mmap_regions->hdr, cmd_size, TRUE);
1709 mmap_regions->hdr.opcode = ASM_SESSION_CMD_MEMORY_MAP_REGIONS;
1710 mmap_regions->mempool_id = 0;
1711 mmap_regions->nregions = bufcnt & 0x00ff;
1712 pr_debug("map_regions->nregions = %d\n", mmap_regions->nregions);
1713 payload = ((u8 *) mmap_region_cmd +
1714 sizeof(struct asm_stream_cmd_memory_map_regions));
1715 mregions = (struct asm_memory_map_regions *)payload;
1716
1717 port = &ac->port[dir];
1718 for (i = 0; i < bufcnt; i++) {
1719 ab = &port->buf[i];
1720 mregions->phys = ab->phys;
1721 mregions->buf_size = ab->size;
1722 ++mregions;
1723 }
1724
1725 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) mmap_region_cmd);
1726 if (rc < 0) {
1727 pr_err("mmap_regions op[0x%x]rc[%d]\n",
1728 mmap_regions->hdr.opcode, rc);
1729 rc = -EINVAL;
1730 goto fail_cmd;
1731 }
1732
1733 rc = wait_event_timeout(this_mmap.cmd_wait,
1734 (atomic_read(&this_mmap.cmd_state) == 0), 5*HZ);
1735 if (!rc) {
1736 pr_err("timeout. waited for memory_map\n");
1737 rc = -EINVAL;
1738 goto fail_cmd;
1739 }
1740 rc = 0;
1741fail_cmd:
1742 kfree(mmap_region_cmd);
1743 return rc;
1744}
1745
1746static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir,
1747 uint32_t bufsz, uint32_t bufcnt)
1748{
1749 struct asm_stream_cmd_memory_unmap_regions *unmap_regions = NULL;
1750 struct asm_memory_unmap_regions *mregions = NULL;
1751 struct audio_port_data *port = NULL;
1752 struct audio_buffer *ab = NULL;
1753 void *unmap_region_cmd = NULL;
1754 void *payload = NULL;
1755 int rc = 0;
1756 int i = 0;
1757 int cmd_size = 0;
1758
1759 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
1760 pr_err("APR handle NULL\n");
1761 return -EINVAL;
1762 }
1763 pr_debug("%s: Session[%d]\n", __func__, ac->session);
1764
1765 cmd_size = sizeof(struct asm_stream_cmd_memory_unmap_regions) +
1766 sizeof(struct asm_memory_unmap_regions) * bufcnt;
1767
1768 unmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1769 unmap_regions = (struct asm_stream_cmd_memory_unmap_regions *)
1770 unmap_region_cmd;
1771 q6asm_add_mmaphdr(&unmap_regions->hdr, cmd_size, TRUE);
1772 unmap_regions->hdr.opcode = ASM_SESSION_CMD_MEMORY_UNMAP_REGIONS;
1773 unmap_regions->nregions = bufcnt & 0x00ff;
1774 pr_debug("unmap_regions->nregions = %d\n", unmap_regions->nregions);
1775 payload = ((u8 *) unmap_region_cmd +
1776 sizeof(struct asm_stream_cmd_memory_unmap_regions));
1777 mregions = (struct asm_memory_unmap_regions *)payload;
1778 port = &ac->port[dir];
1779 for (i = 0; i < bufcnt; i++) {
1780 ab = &port->buf[i];
1781 mregions->phys = ab->phys;
1782 ++mregions;
1783 }
1784
1785 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) unmap_region_cmd);
1786 if (rc < 0) {
1787 pr_err("mmap_regions op[0x%x]rc[%d]\n",
1788 unmap_regions->hdr.opcode, rc);
1789 goto fail_cmd;
1790 }
1791
1792 rc = wait_event_timeout(this_mmap.cmd_wait,
1793 (atomic_read(&this_mmap.cmd_state) == 0), 5*HZ);
1794 if (!rc) {
1795 pr_err("timeout. waited for memory_unmap\n");
1796 goto fail_cmd;
1797 }
1798 rc = 0;
1799
1800fail_cmd:
1801 kfree(unmap_region_cmd);
1802 return rc;
1803}
1804
1805int q6asm_set_mute(struct audio_client *ac, int muteflag)
1806{
1807 void *vol_cmd = NULL;
1808 void *payload = NULL;
1809 struct asm_pp_params_command *cmd = NULL;
1810 struct asm_mute_params *mute = NULL;
1811 int sz = 0;
1812 int rc = 0;
1813
1814 sz = sizeof(struct asm_pp_params_command) +
1815 + sizeof(struct asm_mute_params);
1816 vol_cmd = kzalloc(sz, GFP_KERNEL);
1817 if (vol_cmd == NULL) {
1818 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
1819 rc = -EINVAL;
1820 return rc;
1821 }
1822 cmd = (struct asm_pp_params_command *)vol_cmd;
1823 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
1824 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
1825 cmd->payload = NULL;
1826 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
1827 sizeof(struct asm_mute_params);
1828 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
1829 cmd->params.param_id = MUTE_CONFIG_PARAM_ID;
1830 cmd->params.param_size = sizeof(struct asm_mute_params);
1831 cmd->params.reserved = 0;
1832
1833 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
1834 mute = (struct asm_mute_params *)payload;
1835
1836 mute->muteflag = muteflag;
1837 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
1838 if (rc < 0) {
1839 pr_err("%s: Mute Command failed\n", __func__);
1840 rc = -EINVAL;
1841 goto fail_cmd;
1842 }
1843
1844 rc = wait_event_timeout(ac->cmd_wait,
1845 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1846 if (!rc) {
1847 pr_err("%s: timeout in sending mute command to apr\n",
1848 __func__);
1849 rc = -EINVAL;
1850 goto fail_cmd;
1851 }
1852 rc = 0;
1853fail_cmd:
1854 kfree(vol_cmd);
1855 return rc;
1856}
1857
1858int q6asm_set_volume(struct audio_client *ac, int volume)
1859{
1860 void *vol_cmd = NULL;
1861 void *payload = NULL;
1862 struct asm_pp_params_command *cmd = NULL;
1863 struct asm_master_gain_params *mgain = NULL;
1864 int sz = 0;
1865 int rc = 0;
1866
1867 sz = sizeof(struct asm_pp_params_command) +
1868 + sizeof(struct asm_master_gain_params);
1869 vol_cmd = kzalloc(sz, GFP_KERNEL);
1870 if (vol_cmd == NULL) {
1871 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
1872 rc = -EINVAL;
1873 return rc;
1874 }
1875 cmd = (struct asm_pp_params_command *)vol_cmd;
1876 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
1877 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
1878 cmd->payload = NULL;
1879 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
1880 sizeof(struct asm_master_gain_params);
1881 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
1882 cmd->params.param_id = MASTER_GAIN_PARAM_ID;
1883 cmd->params.param_size = sizeof(struct asm_master_gain_params);
1884 cmd->params.reserved = 0;
1885
1886 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
1887 mgain = (struct asm_master_gain_params *)payload;
1888
1889 mgain->master_gain = volume;
1890 mgain->padding = 0x00;
1891 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
1892 if (rc < 0) {
1893 pr_err("%s: Volume Command failed\n", __func__);
1894 rc = -EINVAL;
1895 goto fail_cmd;
1896 }
1897
1898 rc = wait_event_timeout(ac->cmd_wait,
1899 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1900 if (!rc) {
1901 pr_err("%s: timeout in sending volume command to apr\n",
1902 __func__);
1903 rc = -EINVAL;
1904 goto fail_cmd;
1905 }
1906 rc = 0;
1907fail_cmd:
1908 kfree(vol_cmd);
1909 return rc;
1910}
1911
1912int q6asm_set_softpause(struct audio_client *ac,
1913 struct asm_softpause_params *pause_param)
1914{
1915 void *vol_cmd = NULL;
1916 void *payload = NULL;
1917 struct asm_pp_params_command *cmd = NULL;
1918 struct asm_softpause_params *params = NULL;
1919 int sz = 0;
1920 int rc = 0;
1921
1922 sz = sizeof(struct asm_pp_params_command) +
1923 + sizeof(struct asm_softpause_params);
1924 vol_cmd = kzalloc(sz, GFP_KERNEL);
1925 if (vol_cmd == NULL) {
1926 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
1927 rc = -EINVAL;
1928 return rc;
1929 }
1930 cmd = (struct asm_pp_params_command *)vol_cmd;
1931 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
1932 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
1933 cmd->payload = NULL;
1934 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
1935 sizeof(struct asm_softpause_params);
1936 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
1937 cmd->params.param_id = SOFT_PAUSE_PARAM_ID;
1938 cmd->params.param_size = sizeof(struct asm_softpause_params);
1939 cmd->params.reserved = 0;
1940
1941 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
1942 params = (struct asm_softpause_params *)payload;
1943
1944 params->enable = pause_param->enable;
1945 params->period = pause_param->period;
1946 params->step = pause_param->step;
1947 params->rampingcurve = pause_param->rampingcurve;
1948 pr_debug("%s: soft Pause Command: enable = %d, period = %d,"
1949 "step = %d, curve = %d\n", __func__, params->enable,
1950 params->period, params->step, params->rampingcurve);
1951 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
1952 if (rc < 0) {
1953 pr_err("%s: Volume Command(soft_pause) failed\n", __func__);
1954 rc = -EINVAL;
1955 goto fail_cmd;
1956 }
1957
1958 rc = wait_event_timeout(ac->cmd_wait,
1959 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1960 if (!rc) {
1961 pr_err("%s: timeout in sending volume command(soft_pause)"
1962 "to apr\n", __func__);
1963 rc = -EINVAL;
1964 goto fail_cmd;
1965 }
1966 rc = 0;
1967fail_cmd:
1968 kfree(vol_cmd);
1969 return rc;
1970}
1971
1972int q6asm_equalizer(struct audio_client *ac, void *eq)
1973{
1974 void *eq_cmd = NULL;
1975 void *payload = NULL;
1976 struct asm_pp_params_command *cmd = NULL;
1977 struct asm_equalizer_params *equalizer = NULL;
1978 struct msm_audio_eq_stream_config *eq_params = NULL;
1979 int i = 0;
1980 int sz = 0;
1981 int rc = 0;
1982
1983 sz = sizeof(struct asm_pp_params_command) +
1984 + sizeof(struct asm_equalizer_params);
1985 eq_cmd = kzalloc(sz, GFP_KERNEL);
1986 if (eq_cmd == NULL) {
1987 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
1988 rc = -EINVAL;
1989 goto fail_cmd;
1990 }
1991 eq_params = (struct msm_audio_eq_stream_config *) eq;
1992 cmd = (struct asm_pp_params_command *)eq_cmd;
1993 q6asm_add_hdr(ac, &cmd->hdr, sz, TRUE);
1994 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
1995 cmd->payload = NULL;
1996 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
1997 sizeof(struct asm_equalizer_params);
1998 cmd->params.module_id = EQUALIZER_MODULE_ID;
1999 cmd->params.param_id = EQUALIZER_PARAM_ID;
2000 cmd->params.param_size = sizeof(struct asm_equalizer_params);
2001 cmd->params.reserved = 0;
2002 payload = (u8 *)(eq_cmd + sizeof(struct asm_pp_params_command));
2003 equalizer = (struct asm_equalizer_params *)payload;
2004
2005 equalizer->enable = eq_params->enable;
2006 equalizer->num_bands = eq_params->num_bands;
2007 pr_debug("%s: enable:%d numbands:%d\n", __func__, eq_params->enable,
2008 eq_params->num_bands);
2009 for (i = 0; i < eq_params->num_bands; i++) {
2010 equalizer->eq_bands[i].band_idx =
2011 eq_params->eq_bands[i].band_idx;
2012 equalizer->eq_bands[i].filter_type =
2013 eq_params->eq_bands[i].filter_type;
2014 equalizer->eq_bands[i].center_freq_hz =
2015 eq_params->eq_bands[i].center_freq_hz;
2016 equalizer->eq_bands[i].filter_gain =
2017 eq_params->eq_bands[i].filter_gain;
2018 equalizer->eq_bands[i].q_factor =
2019 eq_params->eq_bands[i].q_factor;
2020 pr_debug("%s: filter_type:%u bandnum:%d\n", __func__,
2021 eq_params->eq_bands[i].filter_type, i);
2022 pr_debug("%s: center_freq_hz:%u bandnum:%d\n", __func__,
2023 eq_params->eq_bands[i].center_freq_hz, i);
2024 pr_debug("%s: filter_gain:%d bandnum:%d\n", __func__,
2025 eq_params->eq_bands[i].filter_gain, i);
2026 pr_debug("%s: q_factor:%d bandnum:%d\n", __func__,
2027 eq_params->eq_bands[i].q_factor, i);
2028 }
2029 rc = apr_send_pkt(ac->apr, (uint32_t *) eq_cmd);
2030 if (rc < 0) {
2031 pr_err("%s: Equalizer Command failed\n", __func__);
2032 rc = -EINVAL;
2033 goto fail_cmd;
2034 }
2035
2036 rc = wait_event_timeout(ac->cmd_wait,
2037 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2038 if (!rc) {
2039 pr_err("%s: timeout in sending equalizer command to apr\n",
2040 __func__);
2041 rc = -EINVAL;
2042 goto fail_cmd;
2043 }
2044 rc = 0;
2045fail_cmd:
2046 kfree(eq_cmd);
2047 return rc;
2048}
2049
2050int q6asm_read(struct audio_client *ac)
2051{
2052 struct asm_stream_cmd_read read;
2053 struct audio_buffer *ab;
2054 int dsp_buf;
2055 struct audio_port_data *port;
2056 int rc;
2057 if (!ac || ac->apr == NULL) {
2058 pr_err("APR handle NULL\n");
2059 return -EINVAL;
2060 }
2061 if (ac->io_mode == SYNC_IO_MODE) {
2062 port = &ac->port[OUT];
2063
2064 q6asm_add_hdr(ac, &read.hdr, sizeof(read), FALSE);
2065
2066 mutex_lock(&port->lock);
2067
2068 dsp_buf = port->dsp_buf;
2069 ab = &port->buf[dsp_buf];
2070
2071 pr_debug("%s:session[%d]dsp-buf[%d][%p]cpu_buf[%d][%p]\n",
2072 __func__,
2073 ac->session,
2074 dsp_buf,
2075 (void *)port->buf[dsp_buf].data,
2076 port->cpu_buf,
2077 (void *)port->buf[port->cpu_buf].phys);
2078
2079 read.hdr.opcode = ASM_DATA_CMD_READ;
2080 read.buf_add = ab->phys;
2081 read.buf_size = ab->size;
2082 read.uid = port->dsp_buf;
2083 read.hdr.token = port->dsp_buf;
2084
2085 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
2086 mutex_unlock(&port->lock);
2087 pr_debug("%s:buf add[0x%x] token[%d] uid[%d]\n", __func__,
2088 read.buf_add,
2089 read.hdr.token,
2090 read.uid);
2091 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
2092 if (rc < 0) {
2093 pr_err("read op[0x%x]rc[%d]\n", read.hdr.opcode, rc);
2094 goto fail_cmd;
2095 }
2096 return 0;
2097 }
2098fail_cmd:
2099 return -EINVAL;
2100}
2101
2102int q6asm_read_nolock(struct audio_client *ac)
2103{
2104 struct asm_stream_cmd_read read;
2105 struct audio_buffer *ab;
2106 int dsp_buf;
2107 struct audio_port_data *port;
2108 int rc;
2109 if (!ac || ac->apr == NULL) {
2110 pr_err("APR handle NULL\n");
2111 return -EINVAL;
2112 }
2113 if (ac->io_mode == SYNC_IO_MODE) {
2114 port = &ac->port[OUT];
2115
2116 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
2117
2118
2119 dsp_buf = port->dsp_buf;
2120 ab = &port->buf[dsp_buf];
2121
2122 pr_debug("%s:session[%d]dsp-buf[%d][%p]cpu_buf[%d][%p]\n",
2123 __func__,
2124 ac->session,
2125 dsp_buf,
2126 (void *)port->buf[dsp_buf].data,
2127 port->cpu_buf,
2128 (void *)port->buf[port->cpu_buf].phys);
2129
2130 read.hdr.opcode = ASM_DATA_CMD_READ;
2131 read.buf_add = ab->phys;
2132 read.buf_size = ab->size;
2133 read.uid = port->dsp_buf;
2134 read.hdr.token = port->dsp_buf;
2135
2136 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
2137 pr_debug("%s:buf add[0x%x] token[%d] uid[%d]\n", __func__,
2138 read.buf_add,
2139 read.hdr.token,
2140 read.uid);
2141 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
2142 if (rc < 0) {
2143 pr_err("read op[0x%x]rc[%d]\n", read.hdr.opcode, rc);
2144 goto fail_cmd;
2145 }
2146 return 0;
2147 }
2148fail_cmd:
2149 return -EINVAL;
2150}
2151
2152
2153static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
2154 uint32_t pkt_size, uint32_t cmd_flg)
2155{
2156 pr_debug("session=%d pkt size=%d cmd_flg=%d\n", pkt_size, cmd_flg,
2157 ac->session);
2158 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
2159 APR_HDR_LEN(sizeof(struct apr_hdr)),\
2160 APR_PKT_VER);
2161 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
2162 hdr->src_domain = APR_DOMAIN_APPS;
2163 hdr->dest_svc = APR_SVC_ASM;
2164 hdr->dest_domain = APR_DOMAIN_ADSP;
2165 hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01;
2166 hdr->dest_port = ((ac->session << 8) & 0xFF00) | 0x01;
2167 if (cmd_flg) {
2168 hdr->token = ac->session;
2169 atomic_set(&ac->cmd_state, 1);
2170 }
2171 hdr->pkt_size = pkt_size;
2172 return;
2173}
2174
2175int q6asm_async_write(struct audio_client *ac,
2176 struct audio_aio_write_param *param)
2177{
2178 int rc = 0;
2179 struct asm_stream_cmd_write write;
2180
2181 if (!ac || ac->apr == NULL) {
2182 pr_err("%s: APR handle NULL\n", __func__);
2183 return -EINVAL;
2184 }
2185
2186 q6asm_add_hdr_async(ac, &write.hdr, sizeof(write), FALSE);
2187
2188 /* Pass physical address as token for AIO scheme */
2189 write.hdr.token = param->uid;
2190 write.hdr.opcode = ASM_DATA_CMD_WRITE;
2191 write.buf_add = param->paddr;
2192 write.avail_bytes = param->len;
2193 write.uid = param->uid;
2194 write.msw_ts = param->msw_ts;
2195 write.lsw_ts = param->lsw_ts;
2196 /* Use 0xFF00 for disabling timestamps */
2197 if (param->flags == 0xFF00)
2198 write.uflags = (0x00000000 | (param->flags & 0x800000FF));
2199 else
2200 write.uflags = (0x80000000 | param->flags);
2201
2202 pr_debug("%s: session[%d] bufadd[0x%x]len[0x%x]", __func__, ac->session,
2203 write.buf_add, write.avail_bytes);
2204
2205 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
2206 if (rc < 0) {
2207 pr_debug("[%s] write op[0x%x]rc[%d]\n", __func__,
2208 write.hdr.opcode, rc);
2209 goto fail_cmd;
2210 }
2211 return 0;
2212fail_cmd:
2213 return -EINVAL;
2214}
2215
2216int q6asm_async_read(struct audio_client *ac,
2217 struct audio_aio_read_param *param)
2218{
2219 int rc = 0;
2220 struct asm_stream_cmd_read read;
2221
2222 if (!ac || ac->apr == NULL) {
2223 pr_err("%s: APR handle NULL\n", __func__);
2224 return -EINVAL;
2225 }
2226
2227 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
2228
2229 /* Pass physical address as token for AIO scheme */
2230 read.hdr.token = param->paddr;
2231 read.hdr.opcode = ASM_DATA_CMD_READ;
2232 read.buf_add = param->paddr;
2233 read.buf_size = param->len;
2234 read.uid = param->uid;
2235
2236 pr_debug("%s: session[%d] bufadd[0x%x]len[0x%x]", __func__, ac->session,
2237 read.buf_add, read.buf_size);
2238
2239 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
2240 if (rc < 0) {
2241 pr_debug("[%s] read op[0x%x]rc[%d]\n", __func__,
2242 read.hdr.opcode, rc);
2243 goto fail_cmd;
2244 }
2245 return 0;
2246fail_cmd:
2247 return -EINVAL;
2248}
2249
2250int q6asm_write(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
2251 uint32_t lsw_ts, uint32_t flags)
2252{
2253 int rc = 0;
2254 struct asm_stream_cmd_write write;
2255 struct audio_port_data *port;
2256 struct audio_buffer *ab;
2257 int dsp_buf = 0;
2258
2259 if (!ac || ac->apr == NULL) {
2260 pr_err("APR handle NULL\n");
2261 return -EINVAL;
2262 }
2263 pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
2264 if (ac->io_mode == SYNC_IO_MODE) {
2265 port = &ac->port[IN];
2266
2267 q6asm_add_hdr(ac, &write.hdr, sizeof(write),
2268 FALSE);
2269 mutex_lock(&port->lock);
2270
2271 dsp_buf = port->dsp_buf;
2272 ab = &port->buf[dsp_buf];
2273
2274 write.hdr.token = port->dsp_buf;
2275 write.hdr.opcode = ASM_DATA_CMD_WRITE;
2276 write.buf_add = ab->phys;
2277 write.avail_bytes = len;
2278 write.uid = port->dsp_buf;
2279 write.msw_ts = msw_ts;
2280 write.lsw_ts = lsw_ts;
2281 /* Use 0xFF00 for disabling timestamps */
2282 if (flags == 0xFF00)
2283 write.uflags = (0x00000000 | (flags & 0x800000FF));
2284 else
2285 write.uflags = (0x80000000 | flags);
2286 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
2287
2288 pr_debug("%s:ab->phys[0x%x]bufadd[0x%x]token[0x%x]buf_id[0x%x]"
2289 , __func__,
2290 ab->phys,
2291 write.buf_add,
2292 write.hdr.token,
2293 write.uid);
2294 mutex_unlock(&port->lock);
2295
2296 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
2297 if (rc < 0) {
2298 pr_err("write op[0x%x]rc[%d]\n", write.hdr.opcode, rc);
2299 goto fail_cmd;
2300 }
2301 pr_debug("%s: WRITE SUCCESS\n", __func__);
2302 return 0;
2303 }
2304fail_cmd:
2305 return -EINVAL;
2306}
2307
2308int q6asm_write_nolock(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
2309 uint32_t lsw_ts, uint32_t flags)
2310{
2311 int rc = 0;
2312 struct asm_stream_cmd_write write;
2313 struct audio_port_data *port;
2314 struct audio_buffer *ab;
2315 int dsp_buf = 0;
2316
2317 if (!ac || ac->apr == NULL) {
2318 pr_err("APR handle NULL\n");
2319 return -EINVAL;
2320 }
2321 pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
2322 if (ac->io_mode == SYNC_IO_MODE) {
2323 port = &ac->port[IN];
2324
2325 q6asm_add_hdr_async(ac, &write.hdr, sizeof(write),
2326 FALSE);
2327
2328 dsp_buf = port->dsp_buf;
2329 ab = &port->buf[dsp_buf];
2330
2331 write.hdr.token = port->dsp_buf;
2332 write.hdr.opcode = ASM_DATA_CMD_WRITE;
2333 write.buf_add = ab->phys;
2334 write.avail_bytes = len;
2335 write.uid = port->dsp_buf;
2336 write.msw_ts = msw_ts;
2337 write.lsw_ts = lsw_ts;
2338 /* Use 0xFF00 for disabling timestamps */
2339 if (flags == 0xFF00)
2340 write.uflags = (0x00000000 | (flags & 0x800000FF));
2341 else
2342 write.uflags = (0x80000000 | flags);
2343 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
2344
2345 pr_debug("%s:ab->phys[0x%x]bufadd[0x%x]token[0x%x]buf_id[0x%x]"
2346 , __func__,
2347 ab->phys,
2348 write.buf_add,
2349 write.hdr.token,
2350 write.uid);
2351
2352 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
2353 if (rc < 0) {
2354 pr_err("write op[0x%x]rc[%d]\n", write.hdr.opcode, rc);
2355 goto fail_cmd;
2356 }
2357 pr_debug("%s: WRITE SUCCESS\n", __func__);
2358 return 0;
2359 }
2360fail_cmd:
2361 return -EINVAL;
2362}
2363
2364uint64_t q6asm_get_session_time(struct audio_client *ac)
2365{
2366 struct apr_hdr hdr;
2367 int rc;
2368
2369 if (!ac || ac->apr == NULL) {
2370 pr_err("APR handle NULL\n");
2371 return -EINVAL;
2372 }
2373 q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
2374 hdr.opcode = ASM_SESSION_CMD_GET_SESSION_TIME;
2375 atomic_set(&ac->time_flag, 1);
2376
2377 pr_debug("%s: session[%d]opcode[0x%x]\n", __func__,
2378 ac->session,
2379 hdr.opcode);
2380 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
2381 if (rc < 0) {
2382 pr_err("Commmand 0x%x failed\n", hdr.opcode);
2383 goto fail_cmd;
2384 }
2385 rc = wait_event_timeout(ac->time_wait,
2386 (atomic_read(&ac->time_flag) == 0), 5*HZ);
2387 if (!rc) {
2388 pr_err("%s: timeout in getting session time from DSP\n",
2389 __func__);
2390 goto fail_cmd;
2391 }
2392 return ac->time_stamp;
2393
2394fail_cmd:
2395 return -EINVAL;
2396}
2397
2398int q6asm_cmd(struct audio_client *ac, int cmd)
2399{
2400 struct apr_hdr hdr;
2401 int rc;
2402 atomic_t *state;
2403 int cnt = 0;
2404
2405 if (!ac || ac->apr == NULL) {
2406 pr_err("APR handle NULL\n");
2407 return -EINVAL;
2408 }
2409 q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
2410 switch (cmd) {
2411 case CMD_PAUSE:
2412 pr_debug("%s:CMD_PAUSE\n", __func__);
2413 hdr.opcode = ASM_SESSION_CMD_PAUSE;
2414 state = &ac->cmd_state;
2415 break;
2416 case CMD_FLUSH:
2417 pr_debug("%s:CMD_FLUSH\n", __func__);
2418 hdr.opcode = ASM_STREAM_CMD_FLUSH;
2419 state = &ac->cmd_state;
2420 break;
2421 case CMD_OUT_FLUSH:
2422 pr_debug("%s:CMD_OUT_FLUSH\n", __func__);
2423 hdr.opcode = ASM_STREAM_CMD_FLUSH_READBUFS;
2424 state = &ac->cmd_state;
2425 break;
2426 case CMD_EOS:
2427 pr_debug("%s:CMD_EOS\n", __func__);
2428 hdr.opcode = ASM_DATA_CMD_EOS;
2429 atomic_set(&ac->cmd_state, 0);
2430 state = &ac->cmd_state;
2431 break;
2432 case CMD_CLOSE:
2433 pr_debug("%s:CMD_CLOSE\n", __func__);
2434 hdr.opcode = ASM_STREAM_CMD_CLOSE;
2435 state = &ac->cmd_state;
2436 break;
2437 default:
2438 pr_err("Invalid format[%d]\n", cmd);
2439 goto fail_cmd;
2440 }
2441 pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
2442 ac->session,
2443 hdr.opcode);
2444 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
2445 if (rc < 0) {
2446 pr_err("Commmand 0x%x failed\n", hdr.opcode);
2447 goto fail_cmd;
2448 }
2449 rc = wait_event_timeout(ac->cmd_wait, (atomic_read(state) == 0), 5*HZ);
2450 if (!rc) {
2451 pr_err("timeout. waited for response opcode[0x%x]\n",
2452 hdr.opcode);
2453 goto fail_cmd;
2454 }
2455 if (cmd == CMD_FLUSH)
2456 q6asm_reset_buf_state(ac);
2457 if (cmd == CMD_CLOSE) {
2458 /* check if DSP return all buffers */
2459 if (ac->port[IN].buf) {
2460 for (cnt = 0; cnt < ac->port[IN].max_buf_cnt;
2461 cnt++) {
2462 if (ac->port[IN].buf[cnt].used == IN) {
2463 pr_debug("Write Buf[%d] not returned\n",
2464 cnt);
2465 }
2466 }
2467 }
2468 if (ac->port[OUT].buf) {
2469 for (cnt = 0; cnt < ac->port[OUT].max_buf_cnt; cnt++) {
2470 if (ac->port[OUT].buf[cnt].used == OUT) {
2471 pr_debug("Read Buf[%d] not returned\n",
2472 cnt);
2473 }
2474 }
2475 }
2476 }
2477 return 0;
2478fail_cmd:
2479 return -EINVAL;
2480}
2481
2482int q6asm_cmd_nowait(struct audio_client *ac, int cmd)
2483{
2484 struct apr_hdr hdr;
2485 int rc;
2486
2487 if (!ac || ac->apr == NULL) {
2488 pr_err("%s:APR handle NULL\n", __func__);
2489 return -EINVAL;
2490 }
2491 q6asm_add_hdr_async(ac, &hdr, sizeof(hdr), TRUE);
2492 switch (cmd) {
2493 case CMD_PAUSE:
2494 pr_debug("%s:CMD_PAUSE\n", __func__);
2495 hdr.opcode = ASM_SESSION_CMD_PAUSE;
2496 break;
2497 case CMD_EOS:
2498 pr_debug("%s:CMD_EOS\n", __func__);
2499 hdr.opcode = ASM_DATA_CMD_EOS;
2500 break;
2501 default:
2502 pr_err("%s:Invalid format[%d]\n", __func__, cmd);
2503 goto fail_cmd;
2504 }
2505 pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
2506 ac->session,
2507 hdr.opcode);
2508 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
2509 if (rc < 0) {
2510 pr_err("%s:Commmand 0x%x failed\n", __func__, hdr.opcode);
2511 goto fail_cmd;
2512 }
2513 return 0;
2514fail_cmd:
2515 return -EINVAL;
2516}
2517
2518static void q6asm_reset_buf_state(struct audio_client *ac)
2519{
2520 int cnt = 0;
2521 int loopcnt = 0;
2522 struct audio_port_data *port = NULL;
2523
2524 if (ac->io_mode == SYNC_IO_MODE) {
2525 mutex_lock(&ac->cmd_lock);
2526 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
2527 port = &ac->port[loopcnt];
2528 cnt = port->max_buf_cnt - 1;
2529 port->dsp_buf = 0;
2530 port->cpu_buf = 0;
2531 while (cnt >= 0) {
2532 if (!port->buf)
2533 continue;
2534 port->buf[cnt].used = 1;
2535 cnt--;
2536 }
2537 }
2538 mutex_unlock(&ac->cmd_lock);
2539 }
2540}
2541
2542int q6asm_reg_tx_overflow(struct audio_client *ac, uint16_t enable)
2543{
2544 struct asm_stream_cmd_reg_tx_overflow_event tx_overflow;
2545 int rc;
2546
2547 if (!ac || ac->apr == NULL) {
2548 pr_err("APR handle NULL\n");
2549 return -EINVAL;
2550 }
2551 pr_debug("%s:session[%d]enable[%d]\n", __func__,
2552 ac->session, enable);
2553 q6asm_add_hdr(ac, &tx_overflow.hdr, sizeof(tx_overflow), TRUE);
2554
2555 tx_overflow.hdr.opcode = \
2556 ASM_SESSION_CMD_REGISTER_FOR_TX_OVERFLOW_EVENTS;
2557 /* tx overflow event: enable */
2558 tx_overflow.enable = enable;
2559
2560 rc = apr_send_pkt(ac->apr, (uint32_t *) &tx_overflow);
2561 if (rc < 0) {
2562 pr_err("tx overflow op[0x%x]rc[%d]\n", \
2563 tx_overflow.hdr.opcode, rc);
2564 goto fail_cmd;
2565 }
2566 rc = wait_event_timeout(ac->cmd_wait,
2567 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2568 if (!rc) {
2569 pr_err("timeout. waited for tx overflow\n");
2570 goto fail_cmd;
2571 }
2572 return 0;
2573fail_cmd:
2574 return -EINVAL;
2575}
2576
2577#ifdef CONFIG_MSM8X60_RTAC
2578int q6asm_get_apr_service_id(int session_id)
2579{
2580 pr_debug("%s\n", __func__);
2581
2582 if (session_id < 0) {
2583 pr_err("%s: invalid session_id = %d\n", __func__, session_id);
2584 return -EINVAL;
2585 }
2586
2587 return ((struct apr_svc *)session[session_id]->apr)->id;
2588}
2589#endif
2590
2591
2592static int __init q6asm_init(void)
2593{
2594 pr_debug("%s\n", __func__);
2595 init_waitqueue_head(&this_mmap.cmd_wait);
2596 memset(session, 0, sizeof(session));
2597 return 0;
2598}
2599
2600device_initcall(q6asm_init);