blob: c4fc58884909602efe27f931badb3df4befd28bf [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);
Vasudeva Rao Thumati86edf6c2011-07-06 16:25:13 +05301744 if (mmap_region_cmd == NULL) {
1745 pr_err("%s: Mem alloc failed\n", __func__);
1746 rc = -EINVAL;
1747 return rc;
1748 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001749 mmap_regions = (struct asm_stream_cmd_memory_map_regions *)
1750 mmap_region_cmd;
1751 q6asm_add_mmaphdr(&mmap_regions->hdr, cmd_size, TRUE);
1752 mmap_regions->hdr.opcode = ASM_SESSION_CMD_MEMORY_MAP_REGIONS;
1753 mmap_regions->mempool_id = 0;
1754 mmap_regions->nregions = bufcnt & 0x00ff;
1755 pr_debug("map_regions->nregions = %d\n", mmap_regions->nregions);
1756 payload = ((u8 *) mmap_region_cmd +
1757 sizeof(struct asm_stream_cmd_memory_map_regions));
1758 mregions = (struct asm_memory_map_regions *)payload;
1759
1760 port = &ac->port[dir];
1761 for (i = 0; i < bufcnt; i++) {
1762 ab = &port->buf[i];
1763 mregions->phys = ab->phys;
1764 mregions->buf_size = ab->size;
1765 ++mregions;
1766 }
1767
1768 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) mmap_region_cmd);
1769 if (rc < 0) {
1770 pr_err("mmap_regions op[0x%x]rc[%d]\n",
1771 mmap_regions->hdr.opcode, rc);
1772 rc = -EINVAL;
1773 goto fail_cmd;
1774 }
1775
1776 rc = wait_event_timeout(this_mmap.cmd_wait,
1777 (atomic_read(&this_mmap.cmd_state) == 0), 5*HZ);
1778 if (!rc) {
1779 pr_err("timeout. waited for memory_map\n");
1780 rc = -EINVAL;
1781 goto fail_cmd;
1782 }
1783 rc = 0;
1784fail_cmd:
1785 kfree(mmap_region_cmd);
1786 return rc;
1787}
1788
1789static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir,
1790 uint32_t bufsz, uint32_t bufcnt)
1791{
1792 struct asm_stream_cmd_memory_unmap_regions *unmap_regions = NULL;
1793 struct asm_memory_unmap_regions *mregions = NULL;
1794 struct audio_port_data *port = NULL;
1795 struct audio_buffer *ab = NULL;
1796 void *unmap_region_cmd = NULL;
1797 void *payload = NULL;
1798 int rc = 0;
1799 int i = 0;
1800 int cmd_size = 0;
1801
1802 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
1803 pr_err("APR handle NULL\n");
1804 return -EINVAL;
1805 }
1806 pr_debug("%s: Session[%d]\n", __func__, ac->session);
1807
1808 cmd_size = sizeof(struct asm_stream_cmd_memory_unmap_regions) +
1809 sizeof(struct asm_memory_unmap_regions) * bufcnt;
1810
1811 unmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
Vasudeva Rao Thumati86edf6c2011-07-06 16:25:13 +05301812 if (unmap_region_cmd == NULL) {
1813 pr_err("%s: Mem alloc failed\n", __func__);
1814 rc = -EINVAL;
1815 return rc;
1816 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001817 unmap_regions = (struct asm_stream_cmd_memory_unmap_regions *)
1818 unmap_region_cmd;
1819 q6asm_add_mmaphdr(&unmap_regions->hdr, cmd_size, TRUE);
1820 unmap_regions->hdr.opcode = ASM_SESSION_CMD_MEMORY_UNMAP_REGIONS;
1821 unmap_regions->nregions = bufcnt & 0x00ff;
1822 pr_debug("unmap_regions->nregions = %d\n", unmap_regions->nregions);
1823 payload = ((u8 *) unmap_region_cmd +
1824 sizeof(struct asm_stream_cmd_memory_unmap_regions));
1825 mregions = (struct asm_memory_unmap_regions *)payload;
1826 port = &ac->port[dir];
1827 for (i = 0; i < bufcnt; i++) {
1828 ab = &port->buf[i];
1829 mregions->phys = ab->phys;
1830 ++mregions;
1831 }
1832
1833 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) unmap_region_cmd);
1834 if (rc < 0) {
1835 pr_err("mmap_regions op[0x%x]rc[%d]\n",
1836 unmap_regions->hdr.opcode, rc);
1837 goto fail_cmd;
1838 }
1839
1840 rc = wait_event_timeout(this_mmap.cmd_wait,
1841 (atomic_read(&this_mmap.cmd_state) == 0), 5*HZ);
1842 if (!rc) {
1843 pr_err("timeout. waited for memory_unmap\n");
1844 goto fail_cmd;
1845 }
1846 rc = 0;
1847
1848fail_cmd:
1849 kfree(unmap_region_cmd);
1850 return rc;
1851}
1852
1853int q6asm_set_mute(struct audio_client *ac, int muteflag)
1854{
1855 void *vol_cmd = NULL;
1856 void *payload = NULL;
1857 struct asm_pp_params_command *cmd = NULL;
1858 struct asm_mute_params *mute = NULL;
1859 int sz = 0;
1860 int rc = 0;
1861
1862 sz = sizeof(struct asm_pp_params_command) +
1863 + sizeof(struct asm_mute_params);
1864 vol_cmd = kzalloc(sz, GFP_KERNEL);
1865 if (vol_cmd == NULL) {
1866 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
1867 rc = -EINVAL;
1868 return rc;
1869 }
1870 cmd = (struct asm_pp_params_command *)vol_cmd;
1871 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
1872 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
1873 cmd->payload = NULL;
1874 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
1875 sizeof(struct asm_mute_params);
1876 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
1877 cmd->params.param_id = MUTE_CONFIG_PARAM_ID;
1878 cmd->params.param_size = sizeof(struct asm_mute_params);
1879 cmd->params.reserved = 0;
1880
1881 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
1882 mute = (struct asm_mute_params *)payload;
1883
1884 mute->muteflag = muteflag;
1885 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
1886 if (rc < 0) {
1887 pr_err("%s: Mute Command failed\n", __func__);
1888 rc = -EINVAL;
1889 goto fail_cmd;
1890 }
1891
1892 rc = wait_event_timeout(ac->cmd_wait,
1893 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1894 if (!rc) {
1895 pr_err("%s: timeout in sending mute command to apr\n",
1896 __func__);
1897 rc = -EINVAL;
1898 goto fail_cmd;
1899 }
1900 rc = 0;
1901fail_cmd:
1902 kfree(vol_cmd);
1903 return rc;
1904}
1905
1906int q6asm_set_volume(struct audio_client *ac, int volume)
1907{
1908 void *vol_cmd = NULL;
1909 void *payload = NULL;
1910 struct asm_pp_params_command *cmd = NULL;
1911 struct asm_master_gain_params *mgain = NULL;
1912 int sz = 0;
1913 int rc = 0;
1914
1915 sz = sizeof(struct asm_pp_params_command) +
1916 + sizeof(struct asm_master_gain_params);
1917 vol_cmd = kzalloc(sz, GFP_KERNEL);
1918 if (vol_cmd == NULL) {
1919 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
1920 rc = -EINVAL;
1921 return rc;
1922 }
1923 cmd = (struct asm_pp_params_command *)vol_cmd;
1924 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
1925 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
1926 cmd->payload = NULL;
1927 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
1928 sizeof(struct asm_master_gain_params);
1929 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
1930 cmd->params.param_id = MASTER_GAIN_PARAM_ID;
1931 cmd->params.param_size = sizeof(struct asm_master_gain_params);
1932 cmd->params.reserved = 0;
1933
1934 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
1935 mgain = (struct asm_master_gain_params *)payload;
1936
1937 mgain->master_gain = volume;
1938 mgain->padding = 0x00;
1939 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
1940 if (rc < 0) {
1941 pr_err("%s: Volume Command failed\n", __func__);
1942 rc = -EINVAL;
1943 goto fail_cmd;
1944 }
1945
1946 rc = wait_event_timeout(ac->cmd_wait,
1947 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1948 if (!rc) {
1949 pr_err("%s: timeout in sending volume command to apr\n",
1950 __func__);
1951 rc = -EINVAL;
1952 goto fail_cmd;
1953 }
1954 rc = 0;
1955fail_cmd:
1956 kfree(vol_cmd);
1957 return rc;
1958}
1959
1960int q6asm_set_softpause(struct audio_client *ac,
1961 struct asm_softpause_params *pause_param)
1962{
1963 void *vol_cmd = NULL;
1964 void *payload = NULL;
1965 struct asm_pp_params_command *cmd = NULL;
1966 struct asm_softpause_params *params = NULL;
1967 int sz = 0;
1968 int rc = 0;
1969
1970 sz = sizeof(struct asm_pp_params_command) +
1971 + sizeof(struct asm_softpause_params);
1972 vol_cmd = kzalloc(sz, GFP_KERNEL);
1973 if (vol_cmd == NULL) {
1974 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
1975 rc = -EINVAL;
1976 return rc;
1977 }
1978 cmd = (struct asm_pp_params_command *)vol_cmd;
1979 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
1980 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
1981 cmd->payload = NULL;
1982 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
1983 sizeof(struct asm_softpause_params);
1984 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
1985 cmd->params.param_id = SOFT_PAUSE_PARAM_ID;
1986 cmd->params.param_size = sizeof(struct asm_softpause_params);
1987 cmd->params.reserved = 0;
1988
1989 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
1990 params = (struct asm_softpause_params *)payload;
1991
1992 params->enable = pause_param->enable;
1993 params->period = pause_param->period;
1994 params->step = pause_param->step;
1995 params->rampingcurve = pause_param->rampingcurve;
1996 pr_debug("%s: soft Pause Command: enable = %d, period = %d,"
1997 "step = %d, curve = %d\n", __func__, params->enable,
1998 params->period, params->step, params->rampingcurve);
1999 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
2000 if (rc < 0) {
2001 pr_err("%s: Volume Command(soft_pause) failed\n", __func__);
2002 rc = -EINVAL;
2003 goto fail_cmd;
2004 }
2005
2006 rc = wait_event_timeout(ac->cmd_wait,
2007 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2008 if (!rc) {
2009 pr_err("%s: timeout in sending volume command(soft_pause)"
2010 "to apr\n", __func__);
2011 rc = -EINVAL;
2012 goto fail_cmd;
2013 }
2014 rc = 0;
2015fail_cmd:
2016 kfree(vol_cmd);
2017 return rc;
2018}
2019
2020int q6asm_equalizer(struct audio_client *ac, void *eq)
2021{
2022 void *eq_cmd = NULL;
2023 void *payload = NULL;
2024 struct asm_pp_params_command *cmd = NULL;
2025 struct asm_equalizer_params *equalizer = NULL;
2026 struct msm_audio_eq_stream_config *eq_params = NULL;
2027 int i = 0;
2028 int sz = 0;
2029 int rc = 0;
2030
2031 sz = sizeof(struct asm_pp_params_command) +
2032 + sizeof(struct asm_equalizer_params);
2033 eq_cmd = kzalloc(sz, GFP_KERNEL);
2034 if (eq_cmd == NULL) {
2035 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
2036 rc = -EINVAL;
2037 goto fail_cmd;
2038 }
2039 eq_params = (struct msm_audio_eq_stream_config *) eq;
2040 cmd = (struct asm_pp_params_command *)eq_cmd;
2041 q6asm_add_hdr(ac, &cmd->hdr, sz, TRUE);
2042 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
2043 cmd->payload = NULL;
2044 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
2045 sizeof(struct asm_equalizer_params);
2046 cmd->params.module_id = EQUALIZER_MODULE_ID;
2047 cmd->params.param_id = EQUALIZER_PARAM_ID;
2048 cmd->params.param_size = sizeof(struct asm_equalizer_params);
2049 cmd->params.reserved = 0;
2050 payload = (u8 *)(eq_cmd + sizeof(struct asm_pp_params_command));
2051 equalizer = (struct asm_equalizer_params *)payload;
2052
2053 equalizer->enable = eq_params->enable;
2054 equalizer->num_bands = eq_params->num_bands;
2055 pr_debug("%s: enable:%d numbands:%d\n", __func__, eq_params->enable,
2056 eq_params->num_bands);
2057 for (i = 0; i < eq_params->num_bands; i++) {
2058 equalizer->eq_bands[i].band_idx =
2059 eq_params->eq_bands[i].band_idx;
2060 equalizer->eq_bands[i].filter_type =
2061 eq_params->eq_bands[i].filter_type;
2062 equalizer->eq_bands[i].center_freq_hz =
2063 eq_params->eq_bands[i].center_freq_hz;
2064 equalizer->eq_bands[i].filter_gain =
2065 eq_params->eq_bands[i].filter_gain;
2066 equalizer->eq_bands[i].q_factor =
2067 eq_params->eq_bands[i].q_factor;
2068 pr_debug("%s: filter_type:%u bandnum:%d\n", __func__,
2069 eq_params->eq_bands[i].filter_type, i);
2070 pr_debug("%s: center_freq_hz:%u bandnum:%d\n", __func__,
2071 eq_params->eq_bands[i].center_freq_hz, i);
2072 pr_debug("%s: filter_gain:%d bandnum:%d\n", __func__,
2073 eq_params->eq_bands[i].filter_gain, i);
2074 pr_debug("%s: q_factor:%d bandnum:%d\n", __func__,
2075 eq_params->eq_bands[i].q_factor, i);
2076 }
2077 rc = apr_send_pkt(ac->apr, (uint32_t *) eq_cmd);
2078 if (rc < 0) {
2079 pr_err("%s: Equalizer Command failed\n", __func__);
2080 rc = -EINVAL;
2081 goto fail_cmd;
2082 }
2083
2084 rc = wait_event_timeout(ac->cmd_wait,
2085 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2086 if (!rc) {
2087 pr_err("%s: timeout in sending equalizer command to apr\n",
2088 __func__);
2089 rc = -EINVAL;
2090 goto fail_cmd;
2091 }
2092 rc = 0;
2093fail_cmd:
2094 kfree(eq_cmd);
2095 return rc;
2096}
2097
2098int q6asm_read(struct audio_client *ac)
2099{
2100 struct asm_stream_cmd_read read;
2101 struct audio_buffer *ab;
2102 int dsp_buf;
2103 struct audio_port_data *port;
2104 int rc;
2105 if (!ac || ac->apr == NULL) {
2106 pr_err("APR handle NULL\n");
2107 return -EINVAL;
2108 }
2109 if (ac->io_mode == SYNC_IO_MODE) {
2110 port = &ac->port[OUT];
2111
2112 q6asm_add_hdr(ac, &read.hdr, sizeof(read), FALSE);
2113
2114 mutex_lock(&port->lock);
2115
2116 dsp_buf = port->dsp_buf;
2117 ab = &port->buf[dsp_buf];
2118
2119 pr_debug("%s:session[%d]dsp-buf[%d][%p]cpu_buf[%d][%p]\n",
2120 __func__,
2121 ac->session,
2122 dsp_buf,
2123 (void *)port->buf[dsp_buf].data,
2124 port->cpu_buf,
2125 (void *)port->buf[port->cpu_buf].phys);
2126
2127 read.hdr.opcode = ASM_DATA_CMD_READ;
2128 read.buf_add = ab->phys;
2129 read.buf_size = ab->size;
2130 read.uid = port->dsp_buf;
2131 read.hdr.token = port->dsp_buf;
2132
2133 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
2134 mutex_unlock(&port->lock);
2135 pr_debug("%s:buf add[0x%x] token[%d] uid[%d]\n", __func__,
2136 read.buf_add,
2137 read.hdr.token,
2138 read.uid);
2139 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
2140 if (rc < 0) {
2141 pr_err("read op[0x%x]rc[%d]\n", read.hdr.opcode, rc);
2142 goto fail_cmd;
2143 }
2144 return 0;
2145 }
2146fail_cmd:
2147 return -EINVAL;
2148}
2149
2150int q6asm_read_nolock(struct audio_client *ac)
2151{
2152 struct asm_stream_cmd_read read;
2153 struct audio_buffer *ab;
2154 int dsp_buf;
2155 struct audio_port_data *port;
2156 int rc;
2157 if (!ac || ac->apr == NULL) {
2158 pr_err("APR handle NULL\n");
2159 return -EINVAL;
2160 }
2161 if (ac->io_mode == SYNC_IO_MODE) {
2162 port = &ac->port[OUT];
2163
2164 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
2165
2166
2167 dsp_buf = port->dsp_buf;
2168 ab = &port->buf[dsp_buf];
2169
2170 pr_debug("%s:session[%d]dsp-buf[%d][%p]cpu_buf[%d][%p]\n",
2171 __func__,
2172 ac->session,
2173 dsp_buf,
2174 (void *)port->buf[dsp_buf].data,
2175 port->cpu_buf,
2176 (void *)port->buf[port->cpu_buf].phys);
2177
2178 read.hdr.opcode = ASM_DATA_CMD_READ;
2179 read.buf_add = ab->phys;
2180 read.buf_size = ab->size;
2181 read.uid = port->dsp_buf;
2182 read.hdr.token = port->dsp_buf;
2183
2184 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
2185 pr_debug("%s:buf add[0x%x] token[%d] uid[%d]\n", __func__,
2186 read.buf_add,
2187 read.hdr.token,
2188 read.uid);
2189 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
2190 if (rc < 0) {
2191 pr_err("read op[0x%x]rc[%d]\n", read.hdr.opcode, rc);
2192 goto fail_cmd;
2193 }
2194 return 0;
2195 }
2196fail_cmd:
2197 return -EINVAL;
2198}
2199
2200
2201static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
2202 uint32_t pkt_size, uint32_t cmd_flg)
2203{
2204 pr_debug("session=%d pkt size=%d cmd_flg=%d\n", pkt_size, cmd_flg,
2205 ac->session);
2206 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
2207 APR_HDR_LEN(sizeof(struct apr_hdr)),\
2208 APR_PKT_VER);
2209 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
2210 hdr->src_domain = APR_DOMAIN_APPS;
2211 hdr->dest_svc = APR_SVC_ASM;
2212 hdr->dest_domain = APR_DOMAIN_ADSP;
2213 hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01;
2214 hdr->dest_port = ((ac->session << 8) & 0xFF00) | 0x01;
2215 if (cmd_flg) {
2216 hdr->token = ac->session;
2217 atomic_set(&ac->cmd_state, 1);
2218 }
2219 hdr->pkt_size = pkt_size;
2220 return;
2221}
2222
2223int q6asm_async_write(struct audio_client *ac,
2224 struct audio_aio_write_param *param)
2225{
2226 int rc = 0;
2227 struct asm_stream_cmd_write write;
2228
2229 if (!ac || ac->apr == NULL) {
2230 pr_err("%s: APR handle NULL\n", __func__);
2231 return -EINVAL;
2232 }
2233
2234 q6asm_add_hdr_async(ac, &write.hdr, sizeof(write), FALSE);
2235
2236 /* Pass physical address as token for AIO scheme */
2237 write.hdr.token = param->uid;
2238 write.hdr.opcode = ASM_DATA_CMD_WRITE;
2239 write.buf_add = param->paddr;
2240 write.avail_bytes = param->len;
2241 write.uid = param->uid;
2242 write.msw_ts = param->msw_ts;
2243 write.lsw_ts = param->lsw_ts;
2244 /* Use 0xFF00 for disabling timestamps */
2245 if (param->flags == 0xFF00)
2246 write.uflags = (0x00000000 | (param->flags & 0x800000FF));
2247 else
2248 write.uflags = (0x80000000 | param->flags);
2249
2250 pr_debug("%s: session[%d] bufadd[0x%x]len[0x%x]", __func__, ac->session,
2251 write.buf_add, write.avail_bytes);
2252
2253 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
2254 if (rc < 0) {
2255 pr_debug("[%s] write op[0x%x]rc[%d]\n", __func__,
2256 write.hdr.opcode, rc);
2257 goto fail_cmd;
2258 }
2259 return 0;
2260fail_cmd:
2261 return -EINVAL;
2262}
2263
2264int q6asm_async_read(struct audio_client *ac,
2265 struct audio_aio_read_param *param)
2266{
2267 int rc = 0;
2268 struct asm_stream_cmd_read read;
2269
2270 if (!ac || ac->apr == NULL) {
2271 pr_err("%s: APR handle NULL\n", __func__);
2272 return -EINVAL;
2273 }
2274
2275 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
2276
2277 /* Pass physical address as token for AIO scheme */
2278 read.hdr.token = param->paddr;
2279 read.hdr.opcode = ASM_DATA_CMD_READ;
2280 read.buf_add = param->paddr;
2281 read.buf_size = param->len;
2282 read.uid = param->uid;
2283
2284 pr_debug("%s: session[%d] bufadd[0x%x]len[0x%x]", __func__, ac->session,
2285 read.buf_add, read.buf_size);
2286
2287 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
2288 if (rc < 0) {
2289 pr_debug("[%s] read op[0x%x]rc[%d]\n", __func__,
2290 read.hdr.opcode, rc);
2291 goto fail_cmd;
2292 }
2293 return 0;
2294fail_cmd:
2295 return -EINVAL;
2296}
2297
2298int q6asm_write(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
2299 uint32_t lsw_ts, uint32_t flags)
2300{
2301 int rc = 0;
2302 struct asm_stream_cmd_write write;
2303 struct audio_port_data *port;
2304 struct audio_buffer *ab;
2305 int dsp_buf = 0;
2306
2307 if (!ac || ac->apr == NULL) {
2308 pr_err("APR handle NULL\n");
2309 return -EINVAL;
2310 }
2311 pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
2312 if (ac->io_mode == SYNC_IO_MODE) {
2313 port = &ac->port[IN];
2314
2315 q6asm_add_hdr(ac, &write.hdr, sizeof(write),
2316 FALSE);
2317 mutex_lock(&port->lock);
2318
2319 dsp_buf = port->dsp_buf;
2320 ab = &port->buf[dsp_buf];
2321
2322 write.hdr.token = port->dsp_buf;
2323 write.hdr.opcode = ASM_DATA_CMD_WRITE;
2324 write.buf_add = ab->phys;
2325 write.avail_bytes = len;
2326 write.uid = port->dsp_buf;
2327 write.msw_ts = msw_ts;
2328 write.lsw_ts = lsw_ts;
2329 /* Use 0xFF00 for disabling timestamps */
2330 if (flags == 0xFF00)
2331 write.uflags = (0x00000000 | (flags & 0x800000FF));
2332 else
2333 write.uflags = (0x80000000 | flags);
2334 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
2335
2336 pr_debug("%s:ab->phys[0x%x]bufadd[0x%x]token[0x%x]buf_id[0x%x]"
2337 , __func__,
2338 ab->phys,
2339 write.buf_add,
2340 write.hdr.token,
2341 write.uid);
2342 mutex_unlock(&port->lock);
2343
2344 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
2345 if (rc < 0) {
2346 pr_err("write op[0x%x]rc[%d]\n", write.hdr.opcode, rc);
2347 goto fail_cmd;
2348 }
2349 pr_debug("%s: WRITE SUCCESS\n", __func__);
2350 return 0;
2351 }
2352fail_cmd:
2353 return -EINVAL;
2354}
2355
2356int q6asm_write_nolock(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
2357 uint32_t lsw_ts, uint32_t flags)
2358{
2359 int rc = 0;
2360 struct asm_stream_cmd_write write;
2361 struct audio_port_data *port;
2362 struct audio_buffer *ab;
2363 int dsp_buf = 0;
2364
2365 if (!ac || ac->apr == NULL) {
2366 pr_err("APR handle NULL\n");
2367 return -EINVAL;
2368 }
2369 pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
2370 if (ac->io_mode == SYNC_IO_MODE) {
2371 port = &ac->port[IN];
2372
2373 q6asm_add_hdr_async(ac, &write.hdr, sizeof(write),
2374 FALSE);
2375
2376 dsp_buf = port->dsp_buf;
2377 ab = &port->buf[dsp_buf];
2378
2379 write.hdr.token = port->dsp_buf;
2380 write.hdr.opcode = ASM_DATA_CMD_WRITE;
2381 write.buf_add = ab->phys;
2382 write.avail_bytes = len;
2383 write.uid = port->dsp_buf;
2384 write.msw_ts = msw_ts;
2385 write.lsw_ts = lsw_ts;
2386 /* Use 0xFF00 for disabling timestamps */
2387 if (flags == 0xFF00)
2388 write.uflags = (0x00000000 | (flags & 0x800000FF));
2389 else
2390 write.uflags = (0x80000000 | flags);
2391 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
2392
2393 pr_debug("%s:ab->phys[0x%x]bufadd[0x%x]token[0x%x]buf_id[0x%x]"
2394 , __func__,
2395 ab->phys,
2396 write.buf_add,
2397 write.hdr.token,
2398 write.uid);
2399
2400 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
2401 if (rc < 0) {
2402 pr_err("write op[0x%x]rc[%d]\n", write.hdr.opcode, rc);
2403 goto fail_cmd;
2404 }
2405 pr_debug("%s: WRITE SUCCESS\n", __func__);
2406 return 0;
2407 }
2408fail_cmd:
2409 return -EINVAL;
2410}
2411
2412uint64_t q6asm_get_session_time(struct audio_client *ac)
2413{
2414 struct apr_hdr hdr;
2415 int rc;
2416
2417 if (!ac || ac->apr == NULL) {
2418 pr_err("APR handle NULL\n");
2419 return -EINVAL;
2420 }
2421 q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
2422 hdr.opcode = ASM_SESSION_CMD_GET_SESSION_TIME;
2423 atomic_set(&ac->time_flag, 1);
2424
2425 pr_debug("%s: session[%d]opcode[0x%x]\n", __func__,
2426 ac->session,
2427 hdr.opcode);
2428 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
2429 if (rc < 0) {
2430 pr_err("Commmand 0x%x failed\n", hdr.opcode);
2431 goto fail_cmd;
2432 }
2433 rc = wait_event_timeout(ac->time_wait,
2434 (atomic_read(&ac->time_flag) == 0), 5*HZ);
2435 if (!rc) {
2436 pr_err("%s: timeout in getting session time from DSP\n",
2437 __func__);
2438 goto fail_cmd;
2439 }
2440 return ac->time_stamp;
2441
2442fail_cmd:
2443 return -EINVAL;
2444}
2445
2446int q6asm_cmd(struct audio_client *ac, int cmd)
2447{
2448 struct apr_hdr hdr;
2449 int rc;
2450 atomic_t *state;
2451 int cnt = 0;
2452
2453 if (!ac || ac->apr == NULL) {
2454 pr_err("APR handle NULL\n");
2455 return -EINVAL;
2456 }
2457 q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
2458 switch (cmd) {
2459 case CMD_PAUSE:
2460 pr_debug("%s:CMD_PAUSE\n", __func__);
2461 hdr.opcode = ASM_SESSION_CMD_PAUSE;
2462 state = &ac->cmd_state;
2463 break;
2464 case CMD_FLUSH:
2465 pr_debug("%s:CMD_FLUSH\n", __func__);
2466 hdr.opcode = ASM_STREAM_CMD_FLUSH;
2467 state = &ac->cmd_state;
2468 break;
2469 case CMD_OUT_FLUSH:
2470 pr_debug("%s:CMD_OUT_FLUSH\n", __func__);
2471 hdr.opcode = ASM_STREAM_CMD_FLUSH_READBUFS;
2472 state = &ac->cmd_state;
2473 break;
2474 case CMD_EOS:
2475 pr_debug("%s:CMD_EOS\n", __func__);
2476 hdr.opcode = ASM_DATA_CMD_EOS;
2477 atomic_set(&ac->cmd_state, 0);
2478 state = &ac->cmd_state;
2479 break;
2480 case CMD_CLOSE:
2481 pr_debug("%s:CMD_CLOSE\n", __func__);
2482 hdr.opcode = ASM_STREAM_CMD_CLOSE;
2483 state = &ac->cmd_state;
2484 break;
2485 default:
2486 pr_err("Invalid format[%d]\n", cmd);
2487 goto fail_cmd;
2488 }
2489 pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
2490 ac->session,
2491 hdr.opcode);
2492 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
2493 if (rc < 0) {
2494 pr_err("Commmand 0x%x failed\n", hdr.opcode);
2495 goto fail_cmd;
2496 }
2497 rc = wait_event_timeout(ac->cmd_wait, (atomic_read(state) == 0), 5*HZ);
2498 if (!rc) {
2499 pr_err("timeout. waited for response opcode[0x%x]\n",
2500 hdr.opcode);
2501 goto fail_cmd;
2502 }
2503 if (cmd == CMD_FLUSH)
2504 q6asm_reset_buf_state(ac);
2505 if (cmd == CMD_CLOSE) {
2506 /* check if DSP return all buffers */
2507 if (ac->port[IN].buf) {
2508 for (cnt = 0; cnt < ac->port[IN].max_buf_cnt;
2509 cnt++) {
2510 if (ac->port[IN].buf[cnt].used == IN) {
2511 pr_debug("Write Buf[%d] not returned\n",
2512 cnt);
2513 }
2514 }
2515 }
2516 if (ac->port[OUT].buf) {
2517 for (cnt = 0; cnt < ac->port[OUT].max_buf_cnt; cnt++) {
2518 if (ac->port[OUT].buf[cnt].used == OUT) {
2519 pr_debug("Read Buf[%d] not returned\n",
2520 cnt);
2521 }
2522 }
2523 }
2524 }
2525 return 0;
2526fail_cmd:
2527 return -EINVAL;
2528}
2529
2530int q6asm_cmd_nowait(struct audio_client *ac, int cmd)
2531{
2532 struct apr_hdr hdr;
2533 int rc;
2534
2535 if (!ac || ac->apr == NULL) {
2536 pr_err("%s:APR handle NULL\n", __func__);
2537 return -EINVAL;
2538 }
2539 q6asm_add_hdr_async(ac, &hdr, sizeof(hdr), TRUE);
2540 switch (cmd) {
2541 case CMD_PAUSE:
2542 pr_debug("%s:CMD_PAUSE\n", __func__);
2543 hdr.opcode = ASM_SESSION_CMD_PAUSE;
2544 break;
2545 case CMD_EOS:
2546 pr_debug("%s:CMD_EOS\n", __func__);
2547 hdr.opcode = ASM_DATA_CMD_EOS;
2548 break;
2549 default:
2550 pr_err("%s:Invalid format[%d]\n", __func__, cmd);
2551 goto fail_cmd;
2552 }
2553 pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
2554 ac->session,
2555 hdr.opcode);
2556 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
2557 if (rc < 0) {
2558 pr_err("%s:Commmand 0x%x failed\n", __func__, hdr.opcode);
2559 goto fail_cmd;
2560 }
2561 return 0;
2562fail_cmd:
2563 return -EINVAL;
2564}
2565
2566static void q6asm_reset_buf_state(struct audio_client *ac)
2567{
2568 int cnt = 0;
2569 int loopcnt = 0;
2570 struct audio_port_data *port = NULL;
2571
2572 if (ac->io_mode == SYNC_IO_MODE) {
2573 mutex_lock(&ac->cmd_lock);
2574 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
2575 port = &ac->port[loopcnt];
2576 cnt = port->max_buf_cnt - 1;
2577 port->dsp_buf = 0;
2578 port->cpu_buf = 0;
2579 while (cnt >= 0) {
2580 if (!port->buf)
2581 continue;
2582 port->buf[cnt].used = 1;
2583 cnt--;
2584 }
2585 }
2586 mutex_unlock(&ac->cmd_lock);
2587 }
2588}
2589
2590int q6asm_reg_tx_overflow(struct audio_client *ac, uint16_t enable)
2591{
2592 struct asm_stream_cmd_reg_tx_overflow_event tx_overflow;
2593 int rc;
2594
2595 if (!ac || ac->apr == NULL) {
2596 pr_err("APR handle NULL\n");
2597 return -EINVAL;
2598 }
2599 pr_debug("%s:session[%d]enable[%d]\n", __func__,
2600 ac->session, enable);
2601 q6asm_add_hdr(ac, &tx_overflow.hdr, sizeof(tx_overflow), TRUE);
2602
2603 tx_overflow.hdr.opcode = \
2604 ASM_SESSION_CMD_REGISTER_FOR_TX_OVERFLOW_EVENTS;
2605 /* tx overflow event: enable */
2606 tx_overflow.enable = enable;
2607
2608 rc = apr_send_pkt(ac->apr, (uint32_t *) &tx_overflow);
2609 if (rc < 0) {
2610 pr_err("tx overflow op[0x%x]rc[%d]\n", \
2611 tx_overflow.hdr.opcode, rc);
2612 goto fail_cmd;
2613 }
2614 rc = wait_event_timeout(ac->cmd_wait,
2615 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2616 if (!rc) {
2617 pr_err("timeout. waited for tx overflow\n");
2618 goto fail_cmd;
2619 }
2620 return 0;
2621fail_cmd:
2622 return -EINVAL;
2623}
2624
2625#ifdef CONFIG_MSM8X60_RTAC
2626int q6asm_get_apr_service_id(int session_id)
2627{
2628 pr_debug("%s\n", __func__);
2629
2630 if (session_id < 0) {
2631 pr_err("%s: invalid session_id = %d\n", __func__, session_id);
2632 return -EINVAL;
2633 }
2634
2635 return ((struct apr_svc *)session[session_id]->apr)->id;
2636}
2637#endif
2638
2639
2640static int __init q6asm_init(void)
2641{
2642 pr_debug("%s\n", __func__);
2643 init_waitqueue_head(&this_mmap.cmd_wait);
2644 memset(session, 0, sizeof(session));
2645 return 0;
2646}
2647
2648device_initcall(q6asm_init);