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