blob: ab09342671b8946a5d0efaaf17dd6b90c1a27eef [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
Swaminathan Sathappan70765cd2011-07-19 18:42:47 -07001232int q6asm_cfg_dual_mono_aac(struct audio_client *ac,
1233 uint16_t sce_left, uint16_t sce_right)
1234{
1235 struct asm_stream_cmd_encdec_dualmono dual_mono;
1236
1237 int rc = 0;
1238
1239 pr_debug("%s: Session %d, sce_left = %d, sce_right = %d\n",
1240 __func__, ac->session, sce_left, sce_right);
1241
1242 q6asm_add_hdr(ac, &dual_mono.hdr, sizeof(dual_mono), TRUE);
1243
1244 dual_mono.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1245 dual_mono.param_id = ASM_CONFIGURE_DUAL_MONO;
1246 dual_mono.param_size = sizeof(struct asm_dual_mono);
1247 dual_mono.channel_map.sce_left = sce_left;
1248 dual_mono.channel_map.sce_right = sce_right;
1249
1250 rc = apr_send_pkt(ac->apr, (uint32_t *) &dual_mono);
1251 if (rc < 0) {
1252 pr_err("%s:Command opcode[0x%x]paramid[0x%x] failed\n",
1253 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM,
1254 ASM_CONFIGURE_DUAL_MONO);
1255 rc = -EINVAL;
1256 goto fail_cmd;
1257 }
1258 rc = wait_event_timeout(ac->cmd_wait,
1259 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1260 if (!rc) {
1261 pr_err("%s:timeout opcode[0x%x]\n", __func__,
1262 dual_mono.hdr.opcode);
1263 goto fail_cmd;
1264 }
1265 return 0;
1266fail_cmd:
1267 return -EINVAL;
1268}
1269
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001270int q6asm_enc_cfg_blk_qcelp(struct audio_client *ac, uint32_t frames_per_buf,
1271 uint16_t min_rate, uint16_t max_rate,
1272 uint16_t reduced_rate_level, uint16_t rate_modulation_cmd)
1273{
1274 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1275 int rc = 0;
1276
1277 pr_debug("%s:session[%d]frames[%d]min_rate[0x%4x]max_rate[0x%4x] \
1278 reduced_rate_level[0x%4x]rate_modulation_cmd[0x%4x]", __func__,
1279 ac->session, frames_per_buf, min_rate, max_rate,
1280 reduced_rate_level, rate_modulation_cmd);
1281
1282 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1283
1284 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1285
1286 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1287 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1288
1289 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
1290 enc_cfg.enc_blk.format_id = V13K_FS;
1291 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_qcelp13_read_cfg);
1292 enc_cfg.enc_blk.cfg.qcelp13.min_rate = min_rate;
1293 enc_cfg.enc_blk.cfg.qcelp13.max_rate = max_rate;
1294 enc_cfg.enc_blk.cfg.qcelp13.reduced_rate_level = reduced_rate_level;
1295 enc_cfg.enc_blk.cfg.qcelp13.rate_modulation_cmd = rate_modulation_cmd;
1296
1297 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
1298 if (rc < 0) {
1299 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
1300 goto fail_cmd;
1301 }
1302 rc = wait_event_timeout(ac->cmd_wait,
1303 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1304 if (!rc) {
1305 pr_err("timeout. waited for FORMAT_UPDATE\n");
1306 goto fail_cmd;
1307 }
1308 return 0;
1309fail_cmd:
1310 return -EINVAL;
1311}
1312
1313int q6asm_enc_cfg_blk_evrc(struct audio_client *ac, uint32_t frames_per_buf,
1314 uint16_t min_rate, uint16_t max_rate,
1315 uint16_t rate_modulation_cmd)
1316{
1317 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1318 int rc = 0;
1319
1320 pr_debug("%s:session[%d]frames[%d]min_rate[0x%4x]max_rate[0x%4x] \
1321 rate_modulation_cmd[0x%4x]", __func__, ac->session,
1322 frames_per_buf, min_rate, max_rate, rate_modulation_cmd);
1323
1324 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1325
1326 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1327
1328 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1329 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1330
1331 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
1332 enc_cfg.enc_blk.format_id = EVRC_FS;
1333 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_evrc_read_cfg);
1334 enc_cfg.enc_blk.cfg.evrc.min_rate = min_rate;
1335 enc_cfg.enc_blk.cfg.evrc.max_rate = max_rate;
1336 enc_cfg.enc_blk.cfg.evrc.rate_modulation_cmd = rate_modulation_cmd;
1337 enc_cfg.enc_blk.cfg.evrc.reserved = 0;
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_enc_cfg_blk_amrnb(struct audio_client *ac, uint32_t frames_per_buf,
1356 uint16_t band_mode, uint16_t dtx_enable)
1357{
1358 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1359 int rc = 0;
1360
1361 pr_debug("%s:session[%d]frames[%d]band_mode[0x%4x]dtx_enable[0x%4x]",
1362 __func__, ac->session, frames_per_buf, band_mode, dtx_enable);
1363
1364 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1365
1366 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1367
1368 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1369 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1370
1371 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
1372 enc_cfg.enc_blk.format_id = AMRNB_FS;
1373 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_amrnb_read_cfg);
1374 enc_cfg.enc_blk.cfg.amrnb.mode = band_mode;
1375 enc_cfg.enc_blk.cfg.amrnb.dtx_mode = dtx_enable;
1376
1377 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
1378 if (rc < 0) {
1379 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
1380 goto fail_cmd;
1381 }
1382 rc = wait_event_timeout(ac->cmd_wait,
1383 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1384 if (!rc) {
1385 pr_err("timeout. waited for FORMAT_UPDATE\n");
1386 goto fail_cmd;
1387 }
1388 return 0;
1389fail_cmd:
1390 return -EINVAL;
1391}
1392
1393int q6asm_media_format_block_pcm(struct audio_client *ac,
1394 uint32_t rate, uint32_t channels)
1395{
1396 struct asm_stream_media_format_update fmt;
1397 int rc = 0;
1398
1399 pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
1400 channels);
1401
1402 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
1403
1404 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
1405
1406 fmt.format = LINEAR_PCM;
1407 fmt.cfg_size = sizeof(struct asm_pcm_cfg);
1408 fmt.write_cfg.pcm_cfg.ch_cfg = channels;
1409 fmt.write_cfg.pcm_cfg.bits_per_sample = 16;
1410 fmt.write_cfg.pcm_cfg.sample_rate = rate;
1411 fmt.write_cfg.pcm_cfg.is_signed = 1;
1412 fmt.write_cfg.pcm_cfg.interleaved = 1;
1413
1414 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
1415 if (rc < 0) {
1416 pr_err("%s:Comamnd open failed\n", __func__);
1417 goto fail_cmd;
1418 }
1419 rc = wait_event_timeout(ac->cmd_wait,
1420 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1421 if (!rc) {
1422 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
1423 goto fail_cmd;
1424 }
1425 return 0;
1426fail_cmd:
1427 return -EINVAL;
1428}
1429
1430int q6asm_media_format_block_aac(struct audio_client *ac,
1431 struct asm_aac_cfg *cfg)
1432{
1433 struct asm_stream_media_format_update fmt;
1434 int rc = 0;
1435
1436 pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session,
1437 cfg->sample_rate, cfg->ch_cfg);
1438
1439 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
1440
1441 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
1442
1443 fmt.format = MPEG4_AAC;
1444 fmt.cfg_size = sizeof(struct asm_aac_cfg);
1445 fmt.write_cfg.aac_cfg.format = cfg->format;
1446 fmt.write_cfg.aac_cfg.aot = cfg->aot;
1447 fmt.write_cfg.aac_cfg.ep_config = cfg->ep_config;
1448 fmt.write_cfg.aac_cfg.section_data_resilience =
1449 cfg->section_data_resilience;
1450 fmt.write_cfg.aac_cfg.scalefactor_data_resilience =
1451 cfg->scalefactor_data_resilience;
1452 fmt.write_cfg.aac_cfg.spectral_data_resilience =
1453 cfg->spectral_data_resilience;
1454 fmt.write_cfg.aac_cfg.ch_cfg = cfg->ch_cfg;
1455 fmt.write_cfg.aac_cfg.sample_rate = cfg->sample_rate;
1456 pr_info("%s:format=%x cfg_size=%d aac-cfg=%x aot=%d ch=%d sr=%d\n",
1457 __func__, fmt.format, fmt.cfg_size,
1458 fmt.write_cfg.aac_cfg.format,
1459 fmt.write_cfg.aac_cfg.aot,
1460 fmt.write_cfg.aac_cfg.ch_cfg,
1461 fmt.write_cfg.aac_cfg.sample_rate);
1462 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
1463 if (rc < 0) {
1464 pr_err("%s:Comamnd open failed\n", __func__);
1465 goto fail_cmd;
1466 }
1467 rc = wait_event_timeout(ac->cmd_wait,
1468 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1469 if (!rc) {
1470 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
1471 goto fail_cmd;
1472 }
1473 return 0;
1474fail_cmd:
1475 return -EINVAL;
1476}
1477
1478int q6asm_media_format_block_wma(struct audio_client *ac,
1479 void *cfg)
1480{
1481 struct asm_stream_media_format_update fmt;
1482 struct asm_wma_cfg *wma_cfg = (struct asm_wma_cfg *)cfg;
1483 int rc = 0;
1484
1485 pr_debug("session[%d]format_tag[0x%4x] rate[%d] ch[0x%4x] bps[%d],\
1486 balign[0x%4x], bit_sample[0x%4x], ch_msk[%d], enc_opt[0x%4x]\n",
1487 ac->session, wma_cfg->format_tag, wma_cfg->sample_rate,
1488 wma_cfg->ch_cfg, wma_cfg->avg_bytes_per_sec,
1489 wma_cfg->block_align, wma_cfg->valid_bits_per_sample,
1490 wma_cfg->ch_mask, wma_cfg->encode_opt);
1491
1492 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
1493
1494 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
1495
1496 fmt.format = WMA_V9;
1497 fmt.cfg_size = sizeof(struct asm_wma_cfg);
1498 fmt.write_cfg.wma_cfg.format_tag = wma_cfg->format_tag;
1499 fmt.write_cfg.wma_cfg.ch_cfg = wma_cfg->ch_cfg;
1500 fmt.write_cfg.wma_cfg.sample_rate = wma_cfg->sample_rate;
1501 fmt.write_cfg.wma_cfg.avg_bytes_per_sec = wma_cfg->avg_bytes_per_sec;
1502 fmt.write_cfg.wma_cfg.block_align = wma_cfg->block_align;
1503 fmt.write_cfg.wma_cfg.valid_bits_per_sample =
1504 wma_cfg->valid_bits_per_sample;
1505 fmt.write_cfg.wma_cfg.ch_mask = wma_cfg->ch_mask;
1506 fmt.write_cfg.wma_cfg.encode_opt = wma_cfg->encode_opt;
1507 fmt.write_cfg.wma_cfg.adv_encode_opt = 0;
1508 fmt.write_cfg.wma_cfg.adv_encode_opt2 = 0;
1509 fmt.write_cfg.wma_cfg.drc_peak_ref = 0;
1510 fmt.write_cfg.wma_cfg.drc_peak_target = 0;
1511 fmt.write_cfg.wma_cfg.drc_ave_ref = 0;
1512 fmt.write_cfg.wma_cfg.drc_ave_target = 0;
1513
1514 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
1515 if (rc < 0) {
1516 pr_err("%s:Comamnd open failed\n", __func__);
1517 goto fail_cmd;
1518 }
1519 rc = wait_event_timeout(ac->cmd_wait,
1520 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1521 if (!rc) {
1522 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
1523 goto fail_cmd;
1524 }
1525 return 0;
1526fail_cmd:
1527 return -EINVAL;
1528}
1529
1530int q6asm_media_format_block_wmapro(struct audio_client *ac,
1531 void *cfg)
1532{
1533 struct asm_stream_media_format_update fmt;
1534 struct asm_wmapro_cfg *wmapro_cfg = (struct asm_wmapro_cfg *)cfg;
1535 int rc = 0;
1536
1537 pr_debug("session[%d]format_tag[0x%4x] rate[%d] ch[0x%4x] bps[%d],"
1538 "balign[0x%4x], bit_sample[0x%4x], ch_msk[%d], enc_opt[0x%4x],\
1539 adv_enc_opt[0x%4x], adv_enc_opt2[0x%8x]\n",
1540 ac->session, wmapro_cfg->format_tag, wmapro_cfg->sample_rate,
1541 wmapro_cfg->ch_cfg, wmapro_cfg->avg_bytes_per_sec,
1542 wmapro_cfg->block_align, wmapro_cfg->valid_bits_per_sample,
1543 wmapro_cfg->ch_mask, wmapro_cfg->encode_opt,
1544 wmapro_cfg->adv_encode_opt, wmapro_cfg->adv_encode_opt2);
1545
1546 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
1547
1548 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
1549
1550 fmt.format = WMA_V10PRO;
1551 fmt.cfg_size = sizeof(struct asm_wmapro_cfg);
1552 fmt.write_cfg.wmapro_cfg.format_tag = wmapro_cfg->format_tag;
1553 fmt.write_cfg.wmapro_cfg.ch_cfg = wmapro_cfg->ch_cfg;
1554 fmt.write_cfg.wmapro_cfg.sample_rate = wmapro_cfg->sample_rate;
1555 fmt.write_cfg.wmapro_cfg.avg_bytes_per_sec =
1556 wmapro_cfg->avg_bytes_per_sec;
1557 fmt.write_cfg.wmapro_cfg.block_align = wmapro_cfg->block_align;
1558 fmt.write_cfg.wmapro_cfg.valid_bits_per_sample =
1559 wmapro_cfg->valid_bits_per_sample;
1560 fmt.write_cfg.wmapro_cfg.ch_mask = wmapro_cfg->ch_mask;
1561 fmt.write_cfg.wmapro_cfg.encode_opt = wmapro_cfg->encode_opt;
1562 fmt.write_cfg.wmapro_cfg.adv_encode_opt = wmapro_cfg->adv_encode_opt;
1563 fmt.write_cfg.wmapro_cfg.adv_encode_opt2 = wmapro_cfg->adv_encode_opt2;
1564 fmt.write_cfg.wmapro_cfg.drc_peak_ref = 0;
1565 fmt.write_cfg.wmapro_cfg.drc_peak_target = 0;
1566 fmt.write_cfg.wmapro_cfg.drc_ave_ref = 0;
1567 fmt.write_cfg.wmapro_cfg.drc_ave_target = 0;
1568
1569 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
1570 if (rc < 0) {
1571 pr_err("%s:Comamnd open failed\n", __func__);
1572 goto fail_cmd;
1573 }
1574 rc = wait_event_timeout(ac->cmd_wait,
1575 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1576 if (!rc) {
1577 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
1578 goto fail_cmd;
1579 }
1580 return 0;
1581fail_cmd:
1582 return -EINVAL;
1583}
1584
1585int q6asm_memory_map(struct audio_client *ac, uint32_t buf_add, int dir,
1586 uint32_t bufsz, uint32_t bufcnt)
1587{
1588 struct asm_stream_cmd_memory_map mem_map;
1589 int rc = 0;
1590
1591 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
1592 pr_err("APR handle NULL\n");
1593 return -EINVAL;
1594 }
1595
1596 pr_debug("%s: Session[%d]\n", __func__, ac->session);
1597
1598 mem_map.hdr.opcode = ASM_SESSION_CMD_MEMORY_MAP;
1599
1600 mem_map.buf_add = buf_add;
1601 mem_map.buf_size = bufsz * bufcnt;
1602 mem_map.mempool_id = 0; /* EBI */
1603 mem_map.reserved = 0;
1604
1605 q6asm_add_mmaphdr(&mem_map.hdr,
1606 sizeof(struct asm_stream_cmd_memory_map), TRUE);
1607
1608 pr_debug("buf add[%x] buf_add_parameter[%x]\n",
1609 mem_map.buf_add, buf_add);
1610
1611 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_map);
1612 if (rc < 0) {
1613 pr_err("mem_map op[0x%x]rc[%d]\n",
1614 mem_map.hdr.opcode, rc);
1615 rc = -EINVAL;
1616 goto fail_cmd;
1617 }
1618
1619 rc = wait_event_timeout(this_mmap.cmd_wait,
1620 (atomic_read(&this_mmap.cmd_state) == 0), 5 * HZ);
1621 if (!rc) {
1622 pr_err("timeout. waited for memory_map\n");
1623 rc = -EINVAL;
1624 goto fail_cmd;
1625 }
1626 rc = 0;
1627fail_cmd:
1628 return rc;
1629}
1630
1631int q6asm_memory_unmap(struct audio_client *ac, uint32_t buf_add, int dir)
1632{
1633 struct asm_stream_cmd_memory_unmap mem_unmap;
1634 int rc = 0;
1635
1636 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
1637 pr_err("APR handle NULL\n");
1638 return -EINVAL;
1639 }
1640 pr_debug("%s: Session[%d]\n", __func__, ac->session);
1641
1642 q6asm_add_mmaphdr(&mem_unmap.hdr,
1643 sizeof(struct asm_stream_cmd_memory_unmap), TRUE);
1644 mem_unmap.hdr.opcode = ASM_SESSION_CMD_MEMORY_UNMAP;
1645 mem_unmap.buf_add = buf_add;
1646
1647 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_unmap);
1648 if (rc < 0) {
1649 pr_err("mem_unmap op[0x%x]rc[%d]\n",
1650 mem_unmap.hdr.opcode, rc);
1651 rc = -EINVAL;
1652 goto fail_cmd;
1653 }
1654
1655 rc = wait_event_timeout(this_mmap.cmd_wait,
1656 (atomic_read(&this_mmap.cmd_state) == 0), 5 * HZ);
1657 if (!rc) {
1658 pr_err("timeout. waited for memory_map\n");
1659 rc = -EINVAL;
1660 goto fail_cmd;
1661 }
1662 rc = 0;
1663fail_cmd:
1664 return rc;
1665}
1666
1667int q6asm_set_lrgain(struct audio_client *ac, int left_gain, int right_gain)
1668{
1669 void *vol_cmd = NULL;
1670 void *payload = NULL;
1671 struct asm_pp_params_command *cmd = NULL;
1672 struct asm_lrchannel_gain_params *lrgain = NULL;
1673 int sz = 0;
1674 int rc = 0;
1675
1676 sz = sizeof(struct asm_pp_params_command) +
1677 + sizeof(struct asm_lrchannel_gain_params);
1678 vol_cmd = kzalloc(sz, GFP_KERNEL);
1679 if (vol_cmd == NULL) {
1680 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
1681 rc = -EINVAL;
1682 return rc;
1683 }
1684 cmd = (struct asm_pp_params_command *)vol_cmd;
1685 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
1686 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
1687 cmd->payload = NULL;
1688 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
1689 sizeof(struct asm_lrchannel_gain_params);
1690 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
1691 cmd->params.param_id = L_R_CHANNEL_GAIN_PARAM_ID;
1692 cmd->params.param_size = sizeof(struct asm_lrchannel_gain_params);
1693 cmd->params.reserved = 0;
1694
1695 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
1696 lrgain = (struct asm_lrchannel_gain_params *)payload;
1697
1698 lrgain->left_gain = left_gain;
1699 lrgain->right_gain = right_gain;
1700 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
1701 if (rc < 0) {
1702 pr_err("%s: Volume Command failed\n", __func__);
1703 rc = -EINVAL;
1704 goto fail_cmd;
1705 }
1706
1707 rc = wait_event_timeout(ac->cmd_wait,
1708 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1709 if (!rc) {
1710 pr_err("%s: timeout in sending volume command to apr\n",
1711 __func__);
1712 rc = -EINVAL;
1713 goto fail_cmd;
1714 }
1715 rc = 0;
1716fail_cmd:
1717 kfree(vol_cmd);
1718 return rc;
1719}
1720
1721static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
1722 uint32_t bufsz, uint32_t bufcnt)
1723{
1724 struct asm_stream_cmd_memory_map_regions *mmap_regions = NULL;
1725 struct asm_memory_map_regions *mregions = NULL;
1726 struct audio_port_data *port = NULL;
1727 struct audio_buffer *ab = NULL;
1728 void *mmap_region_cmd = NULL;
1729 void *payload = NULL;
1730 int rc = 0;
1731 int i = 0;
1732 int cmd_size = 0;
1733
1734 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
1735 pr_err("APR handle NULL\n");
1736 return -EINVAL;
1737 }
1738 pr_debug("%s: Session[%d]\n", __func__, ac->session);
1739
1740 cmd_size = sizeof(struct asm_stream_cmd_memory_map_regions)
1741 + sizeof(struct asm_memory_map_regions) * bufcnt;
1742
1743 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1744 mmap_regions = (struct asm_stream_cmd_memory_map_regions *)
1745 mmap_region_cmd;
1746 q6asm_add_mmaphdr(&mmap_regions->hdr, cmd_size, TRUE);
1747 mmap_regions->hdr.opcode = ASM_SESSION_CMD_MEMORY_MAP_REGIONS;
1748 mmap_regions->mempool_id = 0;
1749 mmap_regions->nregions = bufcnt & 0x00ff;
1750 pr_debug("map_regions->nregions = %d\n", mmap_regions->nregions);
1751 payload = ((u8 *) mmap_region_cmd +
1752 sizeof(struct asm_stream_cmd_memory_map_regions));
1753 mregions = (struct asm_memory_map_regions *)payload;
1754
1755 port = &ac->port[dir];
1756 for (i = 0; i < bufcnt; i++) {
1757 ab = &port->buf[i];
1758 mregions->phys = ab->phys;
1759 mregions->buf_size = ab->size;
1760 ++mregions;
1761 }
1762
1763 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) mmap_region_cmd);
1764 if (rc < 0) {
1765 pr_err("mmap_regions op[0x%x]rc[%d]\n",
1766 mmap_regions->hdr.opcode, rc);
1767 rc = -EINVAL;
1768 goto fail_cmd;
1769 }
1770
1771 rc = wait_event_timeout(this_mmap.cmd_wait,
1772 (atomic_read(&this_mmap.cmd_state) == 0), 5*HZ);
1773 if (!rc) {
1774 pr_err("timeout. waited for memory_map\n");
1775 rc = -EINVAL;
1776 goto fail_cmd;
1777 }
1778 rc = 0;
1779fail_cmd:
1780 kfree(mmap_region_cmd);
1781 return rc;
1782}
1783
1784static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir,
1785 uint32_t bufsz, uint32_t bufcnt)
1786{
1787 struct asm_stream_cmd_memory_unmap_regions *unmap_regions = NULL;
1788 struct asm_memory_unmap_regions *mregions = NULL;
1789 struct audio_port_data *port = NULL;
1790 struct audio_buffer *ab = NULL;
1791 void *unmap_region_cmd = NULL;
1792 void *payload = NULL;
1793 int rc = 0;
1794 int i = 0;
1795 int cmd_size = 0;
1796
1797 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
1798 pr_err("APR handle NULL\n");
1799 return -EINVAL;
1800 }
1801 pr_debug("%s: Session[%d]\n", __func__, ac->session);
1802
1803 cmd_size = sizeof(struct asm_stream_cmd_memory_unmap_regions) +
1804 sizeof(struct asm_memory_unmap_regions) * bufcnt;
1805
1806 unmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1807 unmap_regions = (struct asm_stream_cmd_memory_unmap_regions *)
1808 unmap_region_cmd;
1809 q6asm_add_mmaphdr(&unmap_regions->hdr, cmd_size, TRUE);
1810 unmap_regions->hdr.opcode = ASM_SESSION_CMD_MEMORY_UNMAP_REGIONS;
1811 unmap_regions->nregions = bufcnt & 0x00ff;
1812 pr_debug("unmap_regions->nregions = %d\n", unmap_regions->nregions);
1813 payload = ((u8 *) unmap_region_cmd +
1814 sizeof(struct asm_stream_cmd_memory_unmap_regions));
1815 mregions = (struct asm_memory_unmap_regions *)payload;
1816 port = &ac->port[dir];
1817 for (i = 0; i < bufcnt; i++) {
1818 ab = &port->buf[i];
1819 mregions->phys = ab->phys;
1820 ++mregions;
1821 }
1822
1823 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) unmap_region_cmd);
1824 if (rc < 0) {
1825 pr_err("mmap_regions op[0x%x]rc[%d]\n",
1826 unmap_regions->hdr.opcode, rc);
1827 goto fail_cmd;
1828 }
1829
1830 rc = wait_event_timeout(this_mmap.cmd_wait,
1831 (atomic_read(&this_mmap.cmd_state) == 0), 5*HZ);
1832 if (!rc) {
1833 pr_err("timeout. waited for memory_unmap\n");
1834 goto fail_cmd;
1835 }
1836 rc = 0;
1837
1838fail_cmd:
1839 kfree(unmap_region_cmd);
1840 return rc;
1841}
1842
1843int q6asm_set_mute(struct audio_client *ac, int muteflag)
1844{
1845 void *vol_cmd = NULL;
1846 void *payload = NULL;
1847 struct asm_pp_params_command *cmd = NULL;
1848 struct asm_mute_params *mute = NULL;
1849 int sz = 0;
1850 int rc = 0;
1851
1852 sz = sizeof(struct asm_pp_params_command) +
1853 + sizeof(struct asm_mute_params);
1854 vol_cmd = kzalloc(sz, GFP_KERNEL);
1855 if (vol_cmd == NULL) {
1856 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
1857 rc = -EINVAL;
1858 return rc;
1859 }
1860 cmd = (struct asm_pp_params_command *)vol_cmd;
1861 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
1862 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
1863 cmd->payload = NULL;
1864 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
1865 sizeof(struct asm_mute_params);
1866 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
1867 cmd->params.param_id = MUTE_CONFIG_PARAM_ID;
1868 cmd->params.param_size = sizeof(struct asm_mute_params);
1869 cmd->params.reserved = 0;
1870
1871 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
1872 mute = (struct asm_mute_params *)payload;
1873
1874 mute->muteflag = muteflag;
1875 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
1876 if (rc < 0) {
1877 pr_err("%s: Mute Command failed\n", __func__);
1878 rc = -EINVAL;
1879 goto fail_cmd;
1880 }
1881
1882 rc = wait_event_timeout(ac->cmd_wait,
1883 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1884 if (!rc) {
1885 pr_err("%s: timeout in sending mute command to apr\n",
1886 __func__);
1887 rc = -EINVAL;
1888 goto fail_cmd;
1889 }
1890 rc = 0;
1891fail_cmd:
1892 kfree(vol_cmd);
1893 return rc;
1894}
1895
1896int q6asm_set_volume(struct audio_client *ac, int volume)
1897{
1898 void *vol_cmd = NULL;
1899 void *payload = NULL;
1900 struct asm_pp_params_command *cmd = NULL;
1901 struct asm_master_gain_params *mgain = NULL;
1902 int sz = 0;
1903 int rc = 0;
1904
1905 sz = sizeof(struct asm_pp_params_command) +
1906 + sizeof(struct asm_master_gain_params);
1907 vol_cmd = kzalloc(sz, GFP_KERNEL);
1908 if (vol_cmd == NULL) {
1909 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
1910 rc = -EINVAL;
1911 return rc;
1912 }
1913 cmd = (struct asm_pp_params_command *)vol_cmd;
1914 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
1915 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
1916 cmd->payload = NULL;
1917 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
1918 sizeof(struct asm_master_gain_params);
1919 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
1920 cmd->params.param_id = MASTER_GAIN_PARAM_ID;
1921 cmd->params.param_size = sizeof(struct asm_master_gain_params);
1922 cmd->params.reserved = 0;
1923
1924 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
1925 mgain = (struct asm_master_gain_params *)payload;
1926
1927 mgain->master_gain = volume;
1928 mgain->padding = 0x00;
1929 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
1930 if (rc < 0) {
1931 pr_err("%s: Volume Command failed\n", __func__);
1932 rc = -EINVAL;
1933 goto fail_cmd;
1934 }
1935
1936 rc = wait_event_timeout(ac->cmd_wait,
1937 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1938 if (!rc) {
1939 pr_err("%s: timeout in sending volume command to apr\n",
1940 __func__);
1941 rc = -EINVAL;
1942 goto fail_cmd;
1943 }
1944 rc = 0;
1945fail_cmd:
1946 kfree(vol_cmd);
1947 return rc;
1948}
1949
1950int q6asm_set_softpause(struct audio_client *ac,
1951 struct asm_softpause_params *pause_param)
1952{
1953 void *vol_cmd = NULL;
1954 void *payload = NULL;
1955 struct asm_pp_params_command *cmd = NULL;
1956 struct asm_softpause_params *params = NULL;
1957 int sz = 0;
1958 int rc = 0;
1959
1960 sz = sizeof(struct asm_pp_params_command) +
1961 + sizeof(struct asm_softpause_params);
1962 vol_cmd = kzalloc(sz, GFP_KERNEL);
1963 if (vol_cmd == NULL) {
1964 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
1965 rc = -EINVAL;
1966 return rc;
1967 }
1968 cmd = (struct asm_pp_params_command *)vol_cmd;
1969 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
1970 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
1971 cmd->payload = NULL;
1972 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
1973 sizeof(struct asm_softpause_params);
1974 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
1975 cmd->params.param_id = SOFT_PAUSE_PARAM_ID;
1976 cmd->params.param_size = sizeof(struct asm_softpause_params);
1977 cmd->params.reserved = 0;
1978
1979 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
1980 params = (struct asm_softpause_params *)payload;
1981
1982 params->enable = pause_param->enable;
1983 params->period = pause_param->period;
1984 params->step = pause_param->step;
1985 params->rampingcurve = pause_param->rampingcurve;
1986 pr_debug("%s: soft Pause Command: enable = %d, period = %d,"
1987 "step = %d, curve = %d\n", __func__, params->enable,
1988 params->period, params->step, params->rampingcurve);
1989 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
1990 if (rc < 0) {
1991 pr_err("%s: Volume Command(soft_pause) failed\n", __func__);
1992 rc = -EINVAL;
1993 goto fail_cmd;
1994 }
1995
1996 rc = wait_event_timeout(ac->cmd_wait,
1997 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1998 if (!rc) {
1999 pr_err("%s: timeout in sending volume command(soft_pause)"
2000 "to apr\n", __func__);
2001 rc = -EINVAL;
2002 goto fail_cmd;
2003 }
2004 rc = 0;
2005fail_cmd:
2006 kfree(vol_cmd);
2007 return rc;
2008}
2009
2010int q6asm_equalizer(struct audio_client *ac, void *eq)
2011{
2012 void *eq_cmd = NULL;
2013 void *payload = NULL;
2014 struct asm_pp_params_command *cmd = NULL;
2015 struct asm_equalizer_params *equalizer = NULL;
2016 struct msm_audio_eq_stream_config *eq_params = NULL;
2017 int i = 0;
2018 int sz = 0;
2019 int rc = 0;
2020
2021 sz = sizeof(struct asm_pp_params_command) +
2022 + sizeof(struct asm_equalizer_params);
2023 eq_cmd = kzalloc(sz, GFP_KERNEL);
2024 if (eq_cmd == NULL) {
2025 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
2026 rc = -EINVAL;
2027 goto fail_cmd;
2028 }
2029 eq_params = (struct msm_audio_eq_stream_config *) eq;
2030 cmd = (struct asm_pp_params_command *)eq_cmd;
2031 q6asm_add_hdr(ac, &cmd->hdr, sz, TRUE);
2032 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
2033 cmd->payload = NULL;
2034 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
2035 sizeof(struct asm_equalizer_params);
2036 cmd->params.module_id = EQUALIZER_MODULE_ID;
2037 cmd->params.param_id = EQUALIZER_PARAM_ID;
2038 cmd->params.param_size = sizeof(struct asm_equalizer_params);
2039 cmd->params.reserved = 0;
2040 payload = (u8 *)(eq_cmd + sizeof(struct asm_pp_params_command));
2041 equalizer = (struct asm_equalizer_params *)payload;
2042
2043 equalizer->enable = eq_params->enable;
2044 equalizer->num_bands = eq_params->num_bands;
2045 pr_debug("%s: enable:%d numbands:%d\n", __func__, eq_params->enable,
2046 eq_params->num_bands);
2047 for (i = 0; i < eq_params->num_bands; i++) {
2048 equalizer->eq_bands[i].band_idx =
2049 eq_params->eq_bands[i].band_idx;
2050 equalizer->eq_bands[i].filter_type =
2051 eq_params->eq_bands[i].filter_type;
2052 equalizer->eq_bands[i].center_freq_hz =
2053 eq_params->eq_bands[i].center_freq_hz;
2054 equalizer->eq_bands[i].filter_gain =
2055 eq_params->eq_bands[i].filter_gain;
2056 equalizer->eq_bands[i].q_factor =
2057 eq_params->eq_bands[i].q_factor;
2058 pr_debug("%s: filter_type:%u bandnum:%d\n", __func__,
2059 eq_params->eq_bands[i].filter_type, i);
2060 pr_debug("%s: center_freq_hz:%u bandnum:%d\n", __func__,
2061 eq_params->eq_bands[i].center_freq_hz, i);
2062 pr_debug("%s: filter_gain:%d bandnum:%d\n", __func__,
2063 eq_params->eq_bands[i].filter_gain, i);
2064 pr_debug("%s: q_factor:%d bandnum:%d\n", __func__,
2065 eq_params->eq_bands[i].q_factor, i);
2066 }
2067 rc = apr_send_pkt(ac->apr, (uint32_t *) eq_cmd);
2068 if (rc < 0) {
2069 pr_err("%s: Equalizer Command failed\n", __func__);
2070 rc = -EINVAL;
2071 goto fail_cmd;
2072 }
2073
2074 rc = wait_event_timeout(ac->cmd_wait,
2075 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2076 if (!rc) {
2077 pr_err("%s: timeout in sending equalizer command to apr\n",
2078 __func__);
2079 rc = -EINVAL;
2080 goto fail_cmd;
2081 }
2082 rc = 0;
2083fail_cmd:
2084 kfree(eq_cmd);
2085 return rc;
2086}
2087
2088int q6asm_read(struct audio_client *ac)
2089{
2090 struct asm_stream_cmd_read read;
2091 struct audio_buffer *ab;
2092 int dsp_buf;
2093 struct audio_port_data *port;
2094 int rc;
2095 if (!ac || ac->apr == NULL) {
2096 pr_err("APR handle NULL\n");
2097 return -EINVAL;
2098 }
2099 if (ac->io_mode == SYNC_IO_MODE) {
2100 port = &ac->port[OUT];
2101
2102 q6asm_add_hdr(ac, &read.hdr, sizeof(read), FALSE);
2103
2104 mutex_lock(&port->lock);
2105
2106 dsp_buf = port->dsp_buf;
2107 ab = &port->buf[dsp_buf];
2108
2109 pr_debug("%s:session[%d]dsp-buf[%d][%p]cpu_buf[%d][%p]\n",
2110 __func__,
2111 ac->session,
2112 dsp_buf,
2113 (void *)port->buf[dsp_buf].data,
2114 port->cpu_buf,
2115 (void *)port->buf[port->cpu_buf].phys);
2116
2117 read.hdr.opcode = ASM_DATA_CMD_READ;
2118 read.buf_add = ab->phys;
2119 read.buf_size = ab->size;
2120 read.uid = port->dsp_buf;
2121 read.hdr.token = port->dsp_buf;
2122
2123 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
2124 mutex_unlock(&port->lock);
2125 pr_debug("%s:buf add[0x%x] token[%d] uid[%d]\n", __func__,
2126 read.buf_add,
2127 read.hdr.token,
2128 read.uid);
2129 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
2130 if (rc < 0) {
2131 pr_err("read op[0x%x]rc[%d]\n", read.hdr.opcode, rc);
2132 goto fail_cmd;
2133 }
2134 return 0;
2135 }
2136fail_cmd:
2137 return -EINVAL;
2138}
2139
2140int q6asm_read_nolock(struct audio_client *ac)
2141{
2142 struct asm_stream_cmd_read read;
2143 struct audio_buffer *ab;
2144 int dsp_buf;
2145 struct audio_port_data *port;
2146 int rc;
2147 if (!ac || ac->apr == NULL) {
2148 pr_err("APR handle NULL\n");
2149 return -EINVAL;
2150 }
2151 if (ac->io_mode == SYNC_IO_MODE) {
2152 port = &ac->port[OUT];
2153
2154 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
2155
2156
2157 dsp_buf = port->dsp_buf;
2158 ab = &port->buf[dsp_buf];
2159
2160 pr_debug("%s:session[%d]dsp-buf[%d][%p]cpu_buf[%d][%p]\n",
2161 __func__,
2162 ac->session,
2163 dsp_buf,
2164 (void *)port->buf[dsp_buf].data,
2165 port->cpu_buf,
2166 (void *)port->buf[port->cpu_buf].phys);
2167
2168 read.hdr.opcode = ASM_DATA_CMD_READ;
2169 read.buf_add = ab->phys;
2170 read.buf_size = ab->size;
2171 read.uid = port->dsp_buf;
2172 read.hdr.token = port->dsp_buf;
2173
2174 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
2175 pr_debug("%s:buf add[0x%x] token[%d] uid[%d]\n", __func__,
2176 read.buf_add,
2177 read.hdr.token,
2178 read.uid);
2179 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
2180 if (rc < 0) {
2181 pr_err("read op[0x%x]rc[%d]\n", read.hdr.opcode, rc);
2182 goto fail_cmd;
2183 }
2184 return 0;
2185 }
2186fail_cmd:
2187 return -EINVAL;
2188}
2189
2190
2191static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
2192 uint32_t pkt_size, uint32_t cmd_flg)
2193{
2194 pr_debug("session=%d pkt size=%d cmd_flg=%d\n", pkt_size, cmd_flg,
2195 ac->session);
2196 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
2197 APR_HDR_LEN(sizeof(struct apr_hdr)),\
2198 APR_PKT_VER);
2199 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
2200 hdr->src_domain = APR_DOMAIN_APPS;
2201 hdr->dest_svc = APR_SVC_ASM;
2202 hdr->dest_domain = APR_DOMAIN_ADSP;
2203 hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01;
2204 hdr->dest_port = ((ac->session << 8) & 0xFF00) | 0x01;
2205 if (cmd_flg) {
2206 hdr->token = ac->session;
2207 atomic_set(&ac->cmd_state, 1);
2208 }
2209 hdr->pkt_size = pkt_size;
2210 return;
2211}
2212
2213int q6asm_async_write(struct audio_client *ac,
2214 struct audio_aio_write_param *param)
2215{
2216 int rc = 0;
2217 struct asm_stream_cmd_write write;
2218
2219 if (!ac || ac->apr == NULL) {
2220 pr_err("%s: APR handle NULL\n", __func__);
2221 return -EINVAL;
2222 }
2223
2224 q6asm_add_hdr_async(ac, &write.hdr, sizeof(write), FALSE);
2225
2226 /* Pass physical address as token for AIO scheme */
2227 write.hdr.token = param->uid;
2228 write.hdr.opcode = ASM_DATA_CMD_WRITE;
2229 write.buf_add = param->paddr;
2230 write.avail_bytes = param->len;
2231 write.uid = param->uid;
2232 write.msw_ts = param->msw_ts;
2233 write.lsw_ts = param->lsw_ts;
2234 /* Use 0xFF00 for disabling timestamps */
2235 if (param->flags == 0xFF00)
2236 write.uflags = (0x00000000 | (param->flags & 0x800000FF));
2237 else
2238 write.uflags = (0x80000000 | param->flags);
2239
2240 pr_debug("%s: session[%d] bufadd[0x%x]len[0x%x]", __func__, ac->session,
2241 write.buf_add, write.avail_bytes);
2242
2243 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
2244 if (rc < 0) {
2245 pr_debug("[%s] write op[0x%x]rc[%d]\n", __func__,
2246 write.hdr.opcode, rc);
2247 goto fail_cmd;
2248 }
2249 return 0;
2250fail_cmd:
2251 return -EINVAL;
2252}
2253
2254int q6asm_async_read(struct audio_client *ac,
2255 struct audio_aio_read_param *param)
2256{
2257 int rc = 0;
2258 struct asm_stream_cmd_read read;
2259
2260 if (!ac || ac->apr == NULL) {
2261 pr_err("%s: APR handle NULL\n", __func__);
2262 return -EINVAL;
2263 }
2264
2265 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
2266
2267 /* Pass physical address as token for AIO scheme */
2268 read.hdr.token = param->paddr;
2269 read.hdr.opcode = ASM_DATA_CMD_READ;
2270 read.buf_add = param->paddr;
2271 read.buf_size = param->len;
2272 read.uid = param->uid;
2273
2274 pr_debug("%s: session[%d] bufadd[0x%x]len[0x%x]", __func__, ac->session,
2275 read.buf_add, read.buf_size);
2276
2277 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
2278 if (rc < 0) {
2279 pr_debug("[%s] read op[0x%x]rc[%d]\n", __func__,
2280 read.hdr.opcode, rc);
2281 goto fail_cmd;
2282 }
2283 return 0;
2284fail_cmd:
2285 return -EINVAL;
2286}
2287
2288int q6asm_write(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
2289 uint32_t lsw_ts, uint32_t flags)
2290{
2291 int rc = 0;
2292 struct asm_stream_cmd_write write;
2293 struct audio_port_data *port;
2294 struct audio_buffer *ab;
2295 int dsp_buf = 0;
2296
2297 if (!ac || ac->apr == NULL) {
2298 pr_err("APR handle NULL\n");
2299 return -EINVAL;
2300 }
2301 pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
2302 if (ac->io_mode == SYNC_IO_MODE) {
2303 port = &ac->port[IN];
2304
2305 q6asm_add_hdr(ac, &write.hdr, sizeof(write),
2306 FALSE);
2307 mutex_lock(&port->lock);
2308
2309 dsp_buf = port->dsp_buf;
2310 ab = &port->buf[dsp_buf];
2311
2312 write.hdr.token = port->dsp_buf;
2313 write.hdr.opcode = ASM_DATA_CMD_WRITE;
2314 write.buf_add = ab->phys;
2315 write.avail_bytes = len;
2316 write.uid = port->dsp_buf;
2317 write.msw_ts = msw_ts;
2318 write.lsw_ts = lsw_ts;
2319 /* Use 0xFF00 for disabling timestamps */
2320 if (flags == 0xFF00)
2321 write.uflags = (0x00000000 | (flags & 0x800000FF));
2322 else
2323 write.uflags = (0x80000000 | flags);
2324 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
2325
2326 pr_debug("%s:ab->phys[0x%x]bufadd[0x%x]token[0x%x]buf_id[0x%x]"
2327 , __func__,
2328 ab->phys,
2329 write.buf_add,
2330 write.hdr.token,
2331 write.uid);
2332 mutex_unlock(&port->lock);
2333
2334 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
2335 if (rc < 0) {
2336 pr_err("write op[0x%x]rc[%d]\n", write.hdr.opcode, rc);
2337 goto fail_cmd;
2338 }
2339 pr_debug("%s: WRITE SUCCESS\n", __func__);
2340 return 0;
2341 }
2342fail_cmd:
2343 return -EINVAL;
2344}
2345
2346int q6asm_write_nolock(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
2347 uint32_t lsw_ts, uint32_t flags)
2348{
2349 int rc = 0;
2350 struct asm_stream_cmd_write write;
2351 struct audio_port_data *port;
2352 struct audio_buffer *ab;
2353 int dsp_buf = 0;
2354
2355 if (!ac || ac->apr == NULL) {
2356 pr_err("APR handle NULL\n");
2357 return -EINVAL;
2358 }
2359 pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
2360 if (ac->io_mode == SYNC_IO_MODE) {
2361 port = &ac->port[IN];
2362
2363 q6asm_add_hdr_async(ac, &write.hdr, sizeof(write),
2364 FALSE);
2365
2366 dsp_buf = port->dsp_buf;
2367 ab = &port->buf[dsp_buf];
2368
2369 write.hdr.token = port->dsp_buf;
2370 write.hdr.opcode = ASM_DATA_CMD_WRITE;
2371 write.buf_add = ab->phys;
2372 write.avail_bytes = len;
2373 write.uid = port->dsp_buf;
2374 write.msw_ts = msw_ts;
2375 write.lsw_ts = lsw_ts;
2376 /* Use 0xFF00 for disabling timestamps */
2377 if (flags == 0xFF00)
2378 write.uflags = (0x00000000 | (flags & 0x800000FF));
2379 else
2380 write.uflags = (0x80000000 | flags);
2381 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
2382
2383 pr_debug("%s:ab->phys[0x%x]bufadd[0x%x]token[0x%x]buf_id[0x%x]"
2384 , __func__,
2385 ab->phys,
2386 write.buf_add,
2387 write.hdr.token,
2388 write.uid);
2389
2390 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
2391 if (rc < 0) {
2392 pr_err("write op[0x%x]rc[%d]\n", write.hdr.opcode, rc);
2393 goto fail_cmd;
2394 }
2395 pr_debug("%s: WRITE SUCCESS\n", __func__);
2396 return 0;
2397 }
2398fail_cmd:
2399 return -EINVAL;
2400}
2401
2402uint64_t q6asm_get_session_time(struct audio_client *ac)
2403{
2404 struct apr_hdr hdr;
2405 int rc;
2406
2407 if (!ac || ac->apr == NULL) {
2408 pr_err("APR handle NULL\n");
2409 return -EINVAL;
2410 }
2411 q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
2412 hdr.opcode = ASM_SESSION_CMD_GET_SESSION_TIME;
2413 atomic_set(&ac->time_flag, 1);
2414
2415 pr_debug("%s: session[%d]opcode[0x%x]\n", __func__,
2416 ac->session,
2417 hdr.opcode);
2418 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
2419 if (rc < 0) {
2420 pr_err("Commmand 0x%x failed\n", hdr.opcode);
2421 goto fail_cmd;
2422 }
2423 rc = wait_event_timeout(ac->time_wait,
2424 (atomic_read(&ac->time_flag) == 0), 5*HZ);
2425 if (!rc) {
2426 pr_err("%s: timeout in getting session time from DSP\n",
2427 __func__);
2428 goto fail_cmd;
2429 }
2430 return ac->time_stamp;
2431
2432fail_cmd:
2433 return -EINVAL;
2434}
2435
2436int q6asm_cmd(struct audio_client *ac, int cmd)
2437{
2438 struct apr_hdr hdr;
2439 int rc;
2440 atomic_t *state;
2441 int cnt = 0;
2442
2443 if (!ac || ac->apr == NULL) {
2444 pr_err("APR handle NULL\n");
2445 return -EINVAL;
2446 }
2447 q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
2448 switch (cmd) {
2449 case CMD_PAUSE:
2450 pr_debug("%s:CMD_PAUSE\n", __func__);
2451 hdr.opcode = ASM_SESSION_CMD_PAUSE;
2452 state = &ac->cmd_state;
2453 break;
2454 case CMD_FLUSH:
2455 pr_debug("%s:CMD_FLUSH\n", __func__);
2456 hdr.opcode = ASM_STREAM_CMD_FLUSH;
2457 state = &ac->cmd_state;
2458 break;
2459 case CMD_OUT_FLUSH:
2460 pr_debug("%s:CMD_OUT_FLUSH\n", __func__);
2461 hdr.opcode = ASM_STREAM_CMD_FLUSH_READBUFS;
2462 state = &ac->cmd_state;
2463 break;
2464 case CMD_EOS:
2465 pr_debug("%s:CMD_EOS\n", __func__);
2466 hdr.opcode = ASM_DATA_CMD_EOS;
2467 atomic_set(&ac->cmd_state, 0);
2468 state = &ac->cmd_state;
2469 break;
2470 case CMD_CLOSE:
2471 pr_debug("%s:CMD_CLOSE\n", __func__);
2472 hdr.opcode = ASM_STREAM_CMD_CLOSE;
2473 state = &ac->cmd_state;
2474 break;
2475 default:
2476 pr_err("Invalid format[%d]\n", cmd);
2477 goto fail_cmd;
2478 }
2479 pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
2480 ac->session,
2481 hdr.opcode);
2482 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
2483 if (rc < 0) {
2484 pr_err("Commmand 0x%x failed\n", hdr.opcode);
2485 goto fail_cmd;
2486 }
2487 rc = wait_event_timeout(ac->cmd_wait, (atomic_read(state) == 0), 5*HZ);
2488 if (!rc) {
2489 pr_err("timeout. waited for response opcode[0x%x]\n",
2490 hdr.opcode);
2491 goto fail_cmd;
2492 }
2493 if (cmd == CMD_FLUSH)
2494 q6asm_reset_buf_state(ac);
2495 if (cmd == CMD_CLOSE) {
2496 /* check if DSP return all buffers */
2497 if (ac->port[IN].buf) {
2498 for (cnt = 0; cnt < ac->port[IN].max_buf_cnt;
2499 cnt++) {
2500 if (ac->port[IN].buf[cnt].used == IN) {
2501 pr_debug("Write Buf[%d] not returned\n",
2502 cnt);
2503 }
2504 }
2505 }
2506 if (ac->port[OUT].buf) {
2507 for (cnt = 0; cnt < ac->port[OUT].max_buf_cnt; cnt++) {
2508 if (ac->port[OUT].buf[cnt].used == OUT) {
2509 pr_debug("Read Buf[%d] not returned\n",
2510 cnt);
2511 }
2512 }
2513 }
2514 }
2515 return 0;
2516fail_cmd:
2517 return -EINVAL;
2518}
2519
2520int q6asm_cmd_nowait(struct audio_client *ac, int cmd)
2521{
2522 struct apr_hdr hdr;
2523 int rc;
2524
2525 if (!ac || ac->apr == NULL) {
2526 pr_err("%s:APR handle NULL\n", __func__);
2527 return -EINVAL;
2528 }
2529 q6asm_add_hdr_async(ac, &hdr, sizeof(hdr), TRUE);
2530 switch (cmd) {
2531 case CMD_PAUSE:
2532 pr_debug("%s:CMD_PAUSE\n", __func__);
2533 hdr.opcode = ASM_SESSION_CMD_PAUSE;
2534 break;
2535 case CMD_EOS:
2536 pr_debug("%s:CMD_EOS\n", __func__);
2537 hdr.opcode = ASM_DATA_CMD_EOS;
2538 break;
2539 default:
2540 pr_err("%s:Invalid format[%d]\n", __func__, cmd);
2541 goto fail_cmd;
2542 }
2543 pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
2544 ac->session,
2545 hdr.opcode);
2546 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
2547 if (rc < 0) {
2548 pr_err("%s:Commmand 0x%x failed\n", __func__, hdr.opcode);
2549 goto fail_cmd;
2550 }
2551 return 0;
2552fail_cmd:
2553 return -EINVAL;
2554}
2555
2556static void q6asm_reset_buf_state(struct audio_client *ac)
2557{
2558 int cnt = 0;
2559 int loopcnt = 0;
2560 struct audio_port_data *port = NULL;
2561
2562 if (ac->io_mode == SYNC_IO_MODE) {
2563 mutex_lock(&ac->cmd_lock);
2564 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
2565 port = &ac->port[loopcnt];
2566 cnt = port->max_buf_cnt - 1;
2567 port->dsp_buf = 0;
2568 port->cpu_buf = 0;
2569 while (cnt >= 0) {
2570 if (!port->buf)
2571 continue;
2572 port->buf[cnt].used = 1;
2573 cnt--;
2574 }
2575 }
2576 mutex_unlock(&ac->cmd_lock);
2577 }
2578}
2579
2580int q6asm_reg_tx_overflow(struct audio_client *ac, uint16_t enable)
2581{
2582 struct asm_stream_cmd_reg_tx_overflow_event tx_overflow;
2583 int rc;
2584
2585 if (!ac || ac->apr == NULL) {
2586 pr_err("APR handle NULL\n");
2587 return -EINVAL;
2588 }
2589 pr_debug("%s:session[%d]enable[%d]\n", __func__,
2590 ac->session, enable);
2591 q6asm_add_hdr(ac, &tx_overflow.hdr, sizeof(tx_overflow), TRUE);
2592
2593 tx_overflow.hdr.opcode = \
2594 ASM_SESSION_CMD_REGISTER_FOR_TX_OVERFLOW_EVENTS;
2595 /* tx overflow event: enable */
2596 tx_overflow.enable = enable;
2597
2598 rc = apr_send_pkt(ac->apr, (uint32_t *) &tx_overflow);
2599 if (rc < 0) {
2600 pr_err("tx overflow op[0x%x]rc[%d]\n", \
2601 tx_overflow.hdr.opcode, rc);
2602 goto fail_cmd;
2603 }
2604 rc = wait_event_timeout(ac->cmd_wait,
2605 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2606 if (!rc) {
2607 pr_err("timeout. waited for tx overflow\n");
2608 goto fail_cmd;
2609 }
2610 return 0;
2611fail_cmd:
2612 return -EINVAL;
2613}
2614
2615#ifdef CONFIG_MSM8X60_RTAC
2616int q6asm_get_apr_service_id(int session_id)
2617{
2618 pr_debug("%s\n", __func__);
2619
2620 if (session_id < 0) {
2621 pr_err("%s: invalid session_id = %d\n", __func__, session_id);
2622 return -EINVAL;
2623 }
2624
2625 return ((struct apr_svc *)session[session_id]->apr)->id;
2626}
2627#endif
2628
2629
2630static int __init q6asm_init(void)
2631{
2632 pr_debug("%s\n", __func__);
2633 init_waitqueue_head(&this_mmap.cmd_wait);
2634 memset(session, 0, sizeof(session));
2635 return 0;
2636}
2637
2638device_initcall(q6asm_init);