blob: f566d83552262c6b4ff0ab976aca8d1cb061381b [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
Patrick Lai3aabeae2013-01-06 00:52:34 -08002 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003 * Author: Brian Swetland <swetland@google.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15#include <linux/fs.h>
16#include <linux/mutex.h>
17#include <linux/wait.h>
18#include <linux/miscdevice.h>
19#include <linux/uaccess.h>
20#include <linux/sched.h>
21#include <linux/dma-mapping.h>
22#include <linux/miscdevice.h>
23#include <linux/delay.h>
24#include <linux/spinlock.h>
25#include <linux/slab.h>
26#include <linux/msm_audio.h>
27#include <linux/android_pmem.h>
28#include <linux/memory_alloc.h>
Ben Rombergerfce8f512011-07-18 16:46:09 -070029#include <linux/debugfs.h>
30#include <linux/time.h>
31#include <linux/atomic.h>
32
33#include <asm/ioctls.h>
34
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070035#include <mach/memory.h>
36#include <mach/debug_mm.h>
37#include <mach/peripheral-loader.h>
38#include <mach/qdsp6v2/audio_acdb.h>
39#include <mach/qdsp6v2/rtac.h>
Ben Rombergerfce8f512011-07-18 16:46:09 -070040
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070041#include <sound/apr_audio.h>
42#include <sound/q6asm.h>
Ben Rombergerfce8f512011-07-18 16:46:09 -070043
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070044
45#define TRUE 0x01
46#define FALSE 0x00
47#define READDONE_IDX_STATUS 0
48#define READDONE_IDX_BUFFER 1
49#define READDONE_IDX_SIZE 2
50#define READDONE_IDX_OFFSET 3
51#define READDONE_IDX_MSW_TS 4
52#define READDONE_IDX_LSW_TS 5
53#define READDONE_IDX_FLAGS 6
54#define READDONE_IDX_NUMFRAMES 7
55#define READDONE_IDX_ID 8
Rajesha Kini3498c932011-07-19 19:58:27 +053056#ifdef CONFIG_DEBUG_FS
57#define OUT_BUFFER_SIZE 56
58#define IN_BUFFER_SIZE 24
59#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070060static DEFINE_MUTEX(session_lock);
61
62/* session id: 0 reserved */
63static struct audio_client *session[SESSION_MAX+1];
64static int32_t q6asm_mmapcallback(struct apr_client_data *data, void *priv);
65static int32_t q6asm_callback(struct apr_client_data *data, void *priv);
66static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
67 uint32_t pkt_size, uint32_t cmd_flg);
68static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
69 uint32_t pkt_size, uint32_t cmd_flg);
70static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
71 uint32_t bufsz, uint32_t bufcnt);
72static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir,
73 uint32_t bufsz, uint32_t bufcnt);
74
75static void q6asm_reset_buf_state(struct audio_client *ac);
76
Rajesha Kini3498c932011-07-19 19:58:27 +053077#ifdef CONFIG_DEBUG_FS
78static struct timeval out_cold_tv;
79static struct timeval out_warm_tv;
80static struct timeval out_cont_tv;
81static struct timeval in_cont_tv;
82static long out_enable_flag;
83static long in_enable_flag;
84static struct dentry *out_dentry;
85static struct dentry *in_dentry;
86static int in_cont_index;
87/*This var is used to keep track of first write done for cold output latency */
88static int out_cold_index;
89static char *out_buffer;
90static char *in_buffer;
91static int audio_output_latency_dbgfs_open(struct inode *inode,
92 struct file *file)
93{
94 file->private_data = inode->i_private;
95 return 0;
96}
97static ssize_t audio_output_latency_dbgfs_read(struct file *file,
98 char __user *buf, size_t count, loff_t *ppos)
99{
100 snprintf(out_buffer, OUT_BUFFER_SIZE, "%ld,%ld,%ld,%ld,%ld,%ld,",\
101 out_cold_tv.tv_sec, out_cold_tv.tv_usec, out_warm_tv.tv_sec,\
102 out_warm_tv.tv_usec, out_cont_tv.tv_sec, out_cont_tv.tv_usec);
103 return simple_read_from_buffer(buf, OUT_BUFFER_SIZE, ppos,
104 out_buffer, OUT_BUFFER_SIZE);
105}
106static ssize_t audio_output_latency_dbgfs_write(struct file *file,
107 const char __user *buf, size_t count, loff_t *ppos)
108{
109 char *temp;
110
111 if (count > 2*sizeof(char))
112 return -EINVAL;
113 else
114 temp = kmalloc(2*sizeof(char), GFP_KERNEL);
115
116 out_cold_index = 0;
117
118 if (temp) {
119 if (copy_from_user(temp, buf, 2*sizeof(char))) {
120 kfree(temp);
121 return -EFAULT;
122 }
123 if (!strict_strtol(temp, 10, &out_enable_flag)) {
124 kfree(temp);
125 return count;
126 }
127 kfree(temp);
128 }
129 return -EINVAL;
130}
131static const struct file_operations audio_output_latency_debug_fops = {
132 .open = audio_output_latency_dbgfs_open,
133 .read = audio_output_latency_dbgfs_read,
134 .write = audio_output_latency_dbgfs_write
135};
136
137static int audio_input_latency_dbgfs_open(struct inode *inode,
138 struct file *file)
139{
140 file->private_data = inode->i_private;
141 return 0;
142}
143static ssize_t audio_input_latency_dbgfs_read(struct file *file,
144 char __user *buf, size_t count, loff_t *ppos)
145{
146 snprintf(in_buffer, IN_BUFFER_SIZE, "%ld,%ld,",\
147 in_cont_tv.tv_sec, in_cont_tv.tv_usec);
148 return simple_read_from_buffer(buf, IN_BUFFER_SIZE, ppos,
149 in_buffer, IN_BUFFER_SIZE);
150}
151static ssize_t audio_input_latency_dbgfs_write(struct file *file,
152 const char __user *buf, size_t count, loff_t *ppos)
153{
154 char *temp;
155
156 if (count > 2*sizeof(char))
157 return -EINVAL;
158 else
159 temp = kmalloc(2*sizeof(char), GFP_KERNEL);
160 if (temp) {
161 if (copy_from_user(temp, buf, 2*sizeof(char))) {
162 kfree(temp);
163 return -EFAULT;
164 }
165 if (!strict_strtol(temp, 10, &in_enable_flag)) {
166 kfree(temp);
167 return count;
168 }
169 kfree(temp);
170 }
171 return -EINVAL;
172}
173static const struct file_operations audio_input_latency_debug_fops = {
174 .open = audio_input_latency_dbgfs_open,
175 .read = audio_input_latency_dbgfs_read,
176 .write = audio_input_latency_dbgfs_write
177};
178#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700179struct asm_mmap {
180 atomic_t ref_cnt;
181 atomic_t cmd_state;
182 wait_queue_head_t cmd_wait;
183 void *apr;
184};
185
186static struct asm_mmap this_mmap;
187
188static int q6asm_session_alloc(struct audio_client *ac)
189{
190 int n;
191 mutex_lock(&session_lock);
192 for (n = 1; n <= SESSION_MAX; n++) {
193 if (!session[n]) {
194 session[n] = ac;
195 mutex_unlock(&session_lock);
196 return n;
197 }
198 }
199 mutex_unlock(&session_lock);
200 return -ENOMEM;
201}
202
203static void q6asm_session_free(struct audio_client *ac)
204{
205 pr_debug("%s: sessionid[%d]\n", __func__, ac->session);
Ben Romberger93d4d2d2011-10-19 23:04:02 -0700206 rtac_remove_popp_from_adm_devices(ac->session);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700207 mutex_lock(&session_lock);
208 session[ac->session] = 0;
209 mutex_unlock(&session_lock);
210 ac->session = 0;
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700211 ac->perf_mode = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700212 return;
213}
214
215int q6asm_audio_client_buf_free(unsigned int dir,
216 struct audio_client *ac)
217{
218 struct audio_port_data *port;
219 int cnt = 0;
220 int rc = 0;
221 pr_debug("%s: Session id %d\n", __func__, ac->session);
222 mutex_lock(&ac->cmd_lock);
Patrick Lai55f54c52012-11-17 00:29:07 -0800223 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700224 port = &ac->port[dir];
225 if (!port->buf) {
226 mutex_unlock(&ac->cmd_lock);
227 return 0;
228 }
229 cnt = port->max_buf_cnt - 1;
230
231 if (cnt >= 0) {
232 rc = q6asm_memory_unmap_regions(ac, dir,
233 port->buf[0].size,
234 port->max_buf_cnt);
235 if (rc < 0)
236 pr_err("%s CMD Memory_unmap_regions failed\n",
237 __func__);
238 }
239
240 while (cnt >= 0) {
241 if (port->buf[cnt].data) {
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800242#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
243 ion_unmap_kernel(port->buf[cnt].client,
244 port->buf[cnt].handle);
245 ion_free(port->buf[cnt].client,
246 port->buf[cnt].handle);
247 ion_client_destroy(port->buf[cnt].client);
248#else
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700249 pr_debug("%s:data[%p]phys[%p][%p] cnt[%d] mem_buffer[%p]\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700250 __func__, (void *)port->buf[cnt].data,
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700251 (void *)port->buf[cnt].phys,
252 (void *)&port->buf[cnt].phys, cnt,
253 (void *)port->buf[cnt].mem_buffer);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700254 if (IS_ERR((void *)port->buf[cnt].mem_buffer))
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700255 pr_err("%s:mem buffer invalid, error = %ld\n",
256 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700257 PTR_ERR((void *)port->buf[cnt].mem_buffer));
258 else {
Laura Abbottea3e7b62012-04-30 15:59:21 -0700259 if (iounmap(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700260 port->buf[cnt].mem_buffer) < 0)
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700261 pr_err("%s: unmap buffer failed\n",
262 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700263 }
264 free_contiguous_memory_by_paddr(
265 port->buf[cnt].phys);
266
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800267#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700268 port->buf[cnt].data = NULL;
269 port->buf[cnt].phys = 0;
270 --(port->max_buf_cnt);
271 }
272 --cnt;
273 }
274 kfree(port->buf);
275 port->buf = NULL;
276 }
277 mutex_unlock(&ac->cmd_lock);
278 return 0;
279}
280
281int q6asm_audio_client_buf_free_contiguous(unsigned int dir,
282 struct audio_client *ac)
283{
284 struct audio_port_data *port;
285 int cnt = 0;
286 int rc = 0;
287 pr_debug("%s: Session id %d\n", __func__, ac->session);
288 mutex_lock(&ac->cmd_lock);
289 port = &ac->port[dir];
290 if (!port->buf) {
291 mutex_unlock(&ac->cmd_lock);
292 return 0;
293 }
294 cnt = port->max_buf_cnt - 1;
295
296 if (cnt >= 0) {
Deepa Madiregama7d52a402011-07-13 20:28:36 +0530297 rc = q6asm_memory_unmap(ac, port->buf[0].phys, dir);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700298 if (rc < 0)
299 pr_err("%s CMD Memory_unmap_regions failed\n",
300 __func__);
301 }
302
303 if (port->buf[0].data) {
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800304#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
305 ion_unmap_kernel(port->buf[0].client, port->buf[0].handle);
306 ion_free(port->buf[0].client, port->buf[0].handle);
307 ion_client_destroy(port->buf[0].client);
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700308 pr_debug("%s:data[%p]phys[%p][%p], client[%p] handle[%p]\n",
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800309 __func__,
310 (void *)port->buf[0].data,
311 (void *)port->buf[0].phys,
312 (void *)&port->buf[0].phys,
313 (void *)port->buf[0].client,
314 (void *)port->buf[0].handle);
315#else
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700316 pr_debug("%s:data[%p]phys[%p][%p] mem_buffer[%p]\n",
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700317 __func__,
318 (void *)port->buf[0].data,
319 (void *)port->buf[0].phys,
320 (void *)&port->buf[0].phys,
321 (void *)port->buf[0].mem_buffer);
322 if (IS_ERR((void *)port->buf[0].mem_buffer))
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700323 pr_err("%s:mem buffer invalid, error = %ld\n",
324 __func__,
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700325 PTR_ERR((void *)port->buf[0].mem_buffer));
326 else {
Laura Abbottea3e7b62012-04-30 15:59:21 -0700327 if (iounmap(
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700328 port->buf[0].mem_buffer) < 0)
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700329 pr_err("%s: unmap buffer failed\n", __func__);
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700330 }
331 free_contiguous_memory_by_paddr(port->buf[0].phys);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800332#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700333 }
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700334
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700335 while (cnt >= 0) {
336 port->buf[cnt].data = NULL;
337 port->buf[cnt].phys = 0;
338 cnt--;
339 }
340 port->max_buf_cnt = 0;
341 kfree(port->buf);
342 port->buf = NULL;
343 mutex_unlock(&ac->cmd_lock);
344 return 0;
345}
346
347void q6asm_audio_client_free(struct audio_client *ac)
348{
349 int loopcnt;
350 struct audio_port_data *port;
351 if (!ac || !ac->session)
352 return;
353 pr_debug("%s: Session id %d\n", __func__, ac->session);
Patrick Lai55f54c52012-11-17 00:29:07 -0800354 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700355 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
356 port = &ac->port[loopcnt];
357 if (!port->buf)
358 continue;
359 pr_debug("%s:loopcnt = %d\n", __func__, loopcnt);
360 q6asm_audio_client_buf_free(loopcnt, ac);
361 }
362 }
363
364 apr_deregister(ac->apr);
365 q6asm_session_free(ac);
366
367 pr_debug("%s: APR De-Register\n", __func__);
368 if (atomic_read(&this_mmap.ref_cnt) <= 0) {
369 pr_err("%s: APR Common Port Already Closed\n", __func__);
370 goto done;
371 }
372
373 atomic_dec(&this_mmap.ref_cnt);
374 if (atomic_read(&this_mmap.ref_cnt) == 0) {
375 apr_deregister(this_mmap.apr);
376 pr_debug("%s:APR De-Register common port\n", __func__);
377 }
378done:
379 kfree(ac);
380 return;
381}
382
383int q6asm_set_io_mode(struct audio_client *ac, uint32_t mode)
384{
385 if (ac == NULL) {
386 pr_err("%s APR handle NULL\n", __func__);
387 return -EINVAL;
388 }
Patrick Lai55f54c52012-11-17 00:29:07 -0800389
390 if (mode == ASYNC_IO_MODE) {
391 ac->io_mode &= ~SYNC_IO_MODE;
392 ac->io_mode |= ASYNC_IO_MODE;
393 } else if (mode == SYNC_IO_MODE) {
394 ac->io_mode &= ~ASYNC_IO_MODE;
395 ac->io_mode |= SYNC_IO_MODE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700396 } else {
397 pr_err("%s:Not an valid IO Mode:%d\n", __func__, ac->io_mode);
398 return -EINVAL;
399 }
Patrick Lai55f54c52012-11-17 00:29:07 -0800400
401 pr_debug("%s:Set Mode to %d\n", __func__, ac->io_mode);
402 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700403}
404
405struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv)
406{
407 struct audio_client *ac;
408 int n;
409 int lcnt = 0;
410
411 ac = kzalloc(sizeof(struct audio_client), GFP_KERNEL);
412 if (!ac)
413 return NULL;
414 n = q6asm_session_alloc(ac);
415 if (n <= 0)
416 goto fail_session;
417 ac->session = n;
418 ac->cb = cb;
419 ac->priv = priv;
420 ac->io_mode = SYNC_IO_MODE;
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700421 ac->perf_mode = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700422 ac->apr = apr_register("ADSP", "ASM", \
423 (apr_fn)q6asm_callback,\
424 ((ac->session) << 8 | 0x0001),\
425 ac);
426
427 if (ac->apr == NULL) {
428 pr_err("%s Registration with APR failed\n", __func__);
429 goto fail;
430 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700431 rtac_set_asm_handle(n, ac->apr);
Ben Rombergerfce8f512011-07-18 16:46:09 -0700432
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700433 pr_debug("%s Registering the common port with APR\n", __func__);
434 if (atomic_read(&this_mmap.ref_cnt) == 0) {
435 this_mmap.apr = apr_register("ADSP", "ASM", \
436 (apr_fn)q6asm_mmapcallback,\
437 0x0FFFFFFFF, &this_mmap);
438 if (this_mmap.apr == NULL) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700439 pr_debug("%s Unable to register APR ASM common port\n",
440 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700441 goto fail;
442 }
443 }
444
445 atomic_inc(&this_mmap.ref_cnt);
446 init_waitqueue_head(&ac->cmd_wait);
447 init_waitqueue_head(&ac->time_wait);
448 atomic_set(&ac->time_flag, 1);
449 mutex_init(&ac->cmd_lock);
450 for (lcnt = 0; lcnt <= OUT; lcnt++) {
451 mutex_init(&ac->port[lcnt].lock);
452 spin_lock_init(&ac->port[lcnt].dsp_lock);
453 }
454 atomic_set(&ac->cmd_state, 0);
Srikanth Uyyalaa50b51d2012-07-02 16:02:24 +0530455 atomic_set(&ac->cmd_response, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700456
457 pr_debug("%s: session[%d]\n", __func__, ac->session);
458
459 return ac;
460fail:
461 q6asm_audio_client_free(ac);
462 return NULL;
463fail_session:
464 kfree(ac);
465 return NULL;
466}
467
Ben Romberger61754dc2011-10-31 18:25:41 -0700468struct audio_client *q6asm_get_audio_client(int session_id)
469{
470 if ((session_id <= 0) || (session_id > SESSION_MAX)) {
471 pr_err("%s: invalid session: %d\n", __func__, session_id);
472 goto err;
473 }
474
475 if (!session[session_id]) {
476 pr_err("%s: session not active: %d\n", __func__, session_id);
477 goto err;
478 }
479
480 return session[session_id];
481err:
482 return NULL;
483}
484
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700485int q6asm_audio_client_buf_alloc(unsigned int dir,
486 struct audio_client *ac,
487 unsigned int bufsz,
488 unsigned int bufcnt)
489{
490 int cnt = 0;
491 int rc = 0;
492 struct audio_buffer *buf;
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800493#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
494 int len;
Deepa Madiregama636f80e2013-01-17 14:01:25 +0530495 unsigned int bufsz_4k_aligned;
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800496#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700497
498 if (!(ac) || ((dir != IN) && (dir != OUT)))
499 return -EINVAL;
500
501 pr_debug("%s: session[%d]bufsz[%d]bufcnt[%d]\n", __func__, ac->session,
502 bufsz, bufcnt);
503
504 if (ac->session <= 0 || ac->session > 8)
505 goto fail;
506
Patrick Lai55f54c52012-11-17 00:29:07 -0800507 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700508 if (ac->port[dir].buf) {
509 pr_debug("%s: buffer already allocated\n", __func__);
510 return 0;
511 }
512 mutex_lock(&ac->cmd_lock);
513 buf = kzalloc(((sizeof(struct audio_buffer))*bufcnt),
514 GFP_KERNEL);
515
516 if (!buf) {
517 mutex_unlock(&ac->cmd_lock);
518 goto fail;
519 }
520
521 ac->port[dir].buf = buf;
522
523 while (cnt < bufcnt) {
524 if (bufsz > 0) {
525 if (!buf[cnt].data) {
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800526#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
527 buf[cnt].client = msm_ion_client_create
528 (UINT_MAX, "audio_client");
529 if (IS_ERR_OR_NULL((void *)
530 buf[cnt].client)) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700531 pr_err("%s: ION create client for AUDIO failed\n",
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800532 __func__);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700533 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800534 goto fail;
535 }
Deepa Madiregama636f80e2013-01-17 14:01:25 +0530536 bufsz_4k_aligned = (bufsz + 4095) &
537 (~4095);
538 pr_debug("%s: bufsz_4k_aligned %d"\
539 "bufsz = %d\n",
540 __func__, bufsz_4k_aligned,
541 bufsz);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800542 buf[cnt].handle = ion_alloc
Deepa Madiregama636f80e2013-01-17 14:01:25 +0530543 (buf[cnt].client,
544 bufsz_4k_aligned, SZ_4K,
Hanumant Singh2ac41c92012-08-29 18:39:44 -0700545 (0x1 << ION_AUDIO_HEAP_ID), 0);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800546 if (IS_ERR_OR_NULL((void *)
547 buf[cnt].handle)) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700548 pr_err("%s: ION memory allocation for AUDIO failed\n",
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800549 __func__);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700550 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800551 goto fail;
552 }
553
554 rc = ion_phys(buf[cnt].client,
555 buf[cnt].handle,
556 (ion_phys_addr_t *)
557 &buf[cnt].phys,
558 (size_t *)&len);
559 if (rc) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700560 pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800561 __func__, rc);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700562 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800563 goto fail;
564 }
565
566 buf[cnt].data = ion_map_kernel
Mitchel Humpherys456e2682012-09-12 14:42:50 -0700567 (buf[cnt].client, buf[cnt].handle);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800568 if (IS_ERR_OR_NULL((void *)
569 buf[cnt].data)) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700570 pr_err("%s: ION memory mapping for AUDIO failed\n",
571 __func__);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700572 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800573 goto fail;
574 }
575 memset((void *)buf[cnt].data, 0, bufsz);
576#else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700577 unsigned int flags = 0;
578 buf[cnt].phys =
579 allocate_contiguous_ebi_nomap(bufsz,
580 SZ_4K);
581 if (!buf[cnt].phys) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700582 pr_err("%s:Buf alloc failed size=%d\n",
583 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700584 bufsz);
585 mutex_unlock(&ac->cmd_lock);
586 goto fail;
587 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700588 buf[cnt].mem_buffer =
Laura Abbottea3e7b62012-04-30 15:59:21 -0700589 ioremap(buf[cnt].phys, bufsz);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700590 if (IS_ERR(
591 (void *)buf[cnt].mem_buffer)) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700592 pr_err("%s:map_buffer failed, error = %ld\n",
593 __func__,
594 PTR_ERR((void *)buf[cnt].mem_buffer));
Jayasena Sangaraboina466e6b92012-01-17 21:10:55 -0800595 mutex_unlock(&ac->cmd_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700596 goto fail;
597 }
598 buf[cnt].data =
Laura Abbottea3e7b62012-04-30 15:59:21 -0700599 buf[cnt].mem_buffer;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700600 if (!buf[cnt].data) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700601 pr_err("%s:invalid vaddr, iomap failed\n",
602 __func__);
Jayasena Sangaraboina466e6b92012-01-17 21:10:55 -0800603 mutex_unlock(&ac->cmd_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700604 goto fail;
605 }
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800606#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700607 buf[cnt].used = 1;
608 buf[cnt].size = bufsz;
609 buf[cnt].actual_size = bufsz;
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800610 pr_debug("%s data[%p]phys[%p][%p]\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700611 __func__,
612 (void *)buf[cnt].data,
613 (void *)buf[cnt].phys,
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800614 (void *)&buf[cnt].phys);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700615 cnt++;
616 }
617 }
618 }
619 ac->port[dir].max_buf_cnt = cnt;
620
621 mutex_unlock(&ac->cmd_lock);
622 rc = q6asm_memory_map_regions(ac, dir, bufsz, cnt);
623 if (rc < 0) {
624 pr_err("%s:CMD Memory_map_regions failed\n", __func__);
625 goto fail;
626 }
627 }
628 return 0;
629fail:
630 q6asm_audio_client_buf_free(dir, ac);
631 return -EINVAL;
632}
633
634int q6asm_audio_client_buf_alloc_contiguous(unsigned int dir,
635 struct audio_client *ac,
636 unsigned int bufsz,
637 unsigned int bufcnt)
638{
639 int cnt = 0;
640 int rc = 0;
641 struct audio_buffer *buf;
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800642#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
643 int len;
644#else
645 int flags = 0;
646#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700647 if (!(ac) || ((dir != IN) && (dir != OUT)))
648 return -EINVAL;
649
650 pr_debug("%s: session[%d]bufsz[%d]bufcnt[%d]\n",
651 __func__, ac->session,
652 bufsz, bufcnt);
653
654 if (ac->session <= 0 || ac->session > 8)
655 goto fail;
656
657 if (ac->port[dir].buf) {
658 pr_debug("%s: buffer already allocated\n", __func__);
659 return 0;
660 }
661 mutex_lock(&ac->cmd_lock);
662 buf = kzalloc(((sizeof(struct audio_buffer))*bufcnt),
663 GFP_KERNEL);
664
665 if (!buf) {
666 mutex_unlock(&ac->cmd_lock);
667 goto fail;
668 }
669
670 ac->port[dir].buf = buf;
671
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800672#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
673 buf[0].client = msm_ion_client_create(UINT_MAX, "audio_client");
674 if (IS_ERR_OR_NULL((void *)buf[0].client)) {
675 pr_err("%s: ION create client for AUDIO failed\n", __func__);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700676 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800677 goto fail;
678 }
679 buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
Hanumant Singh2ac41c92012-08-29 18:39:44 -0700680 (0x1 << ION_AUDIO_HEAP_ID), 0);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800681 if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
682 pr_err("%s: ION memory allocation for AUDIO failed\n",
683 __func__);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700684 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800685 goto fail;
686 }
687
688 rc = ion_phys(buf[0].client, buf[0].handle,
689 (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len);
690 if (rc) {
691 pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
692 __func__, rc);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700693 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800694 goto fail;
695 }
696
Mitchel Humpherys456e2682012-09-12 14:42:50 -0700697 buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800698 if (IS_ERR_OR_NULL((void *) buf[0].data)) {
699 pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700700 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800701 goto fail;
702 }
703 memset((void *)buf[0].data, 0, (bufsz * bufcnt));
704#else
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700705 buf[0].phys = allocate_contiguous_ebi_nomap(bufsz * bufcnt,
706 SZ_4K);
707 if (!buf[0].phys) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700708 pr_err("%s:Buf alloc failed size=%d, bufcnt=%d\n",
709 __func__, bufsz, bufcnt);
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700710 mutex_unlock(&ac->cmd_lock);
711 goto fail;
712 }
713
Laura Abbottea3e7b62012-04-30 15:59:21 -0700714 buf[0].mem_buffer = ioremap(buf[0].phys, bufsz * bufcnt);
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700715 if (IS_ERR((void *)buf[cnt].mem_buffer)) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700716 pr_err("%s:map_buffer failed, error = %ld\n",
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700717 __func__, PTR_ERR((void *)buf[0].mem_buffer));
718
719 mutex_unlock(&ac->cmd_lock);
720 goto fail;
721 }
Laura Abbottea3e7b62012-04-30 15:59:21 -0700722 buf[0].data = buf[0].mem_buffer;
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800723#endif
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700724 if (!buf[0].data) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700725 pr_err("%s:invalid vaddr, iomap failed\n", __func__);
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700726 mutex_unlock(&ac->cmd_lock);
727 goto fail;
728 }
729
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700730 buf[0].used = dir ^ 1;
731 buf[0].size = bufsz;
732 buf[0].actual_size = bufsz;
733 cnt = 1;
734 while (cnt < bufcnt) {
735 if (bufsz > 0) {
736 buf[cnt].data = buf[0].data + (cnt * bufsz);
737 buf[cnt].phys = buf[0].phys + (cnt * bufsz);
738 if (!buf[cnt].data) {
739 pr_err("%s Buf alloc failed\n",
740 __func__);
741 mutex_unlock(&ac->cmd_lock);
742 goto fail;
743 }
744 buf[cnt].used = dir ^ 1;
745 buf[cnt].size = bufsz;
746 buf[cnt].actual_size = bufsz;
747 pr_debug("%s data[%p]phys[%p][%p]\n", __func__,
748 (void *)buf[cnt].data,
749 (void *)buf[cnt].phys,
750 (void *)&buf[cnt].phys);
751 }
752 cnt++;
753 }
754 ac->port[dir].max_buf_cnt = cnt;
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700755
756 pr_debug("%s ac->port[%d].max_buf_cnt[%d]\n", __func__, dir,
757 ac->port[dir].max_buf_cnt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700758 mutex_unlock(&ac->cmd_lock);
759 rc = q6asm_memory_map(ac, buf[0].phys, dir, bufsz, cnt);
760 if (rc < 0) {
761 pr_err("%s:CMD Memory_map_regions failed\n", __func__);
762 goto fail;
763 }
764 return 0;
765fail:
766 q6asm_audio_client_buf_free_contiguous(dir, ac);
767 return -EINVAL;
768}
769
770static int32_t q6asm_mmapcallback(struct apr_client_data *data, void *priv)
771{
772 uint32_t token;
773 uint32_t *payload = data->payload;
Deepa Madiregama636f80e2013-01-17 14:01:25 +0530774 struct audio_client *ac;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700775
776 if (data->opcode == RESET_EVENTS) {
777 pr_debug("%s: Reset event is received: %d %d apr[%p]\n",
778 __func__,
779 data->reset_event,
780 data->reset_proc,
781 this_mmap.apr);
782 apr_reset(this_mmap.apr);
783 this_mmap.apr = NULL;
784 atomic_set(&this_mmap.cmd_state, 0);
785 return 0;
786 }
787
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700788 pr_debug("%s:ptr0[0x%x]ptr1[0x%x]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]\n",
789 __func__, payload[0], payload[1], data->opcode, data->token,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700790 data->payload_size, data->src_port, data->dest_port);
791
792 if (data->opcode == APR_BASIC_RSP_RESULT) {
793 token = data->token;
Deepa Madiregama636f80e2013-01-17 14:01:25 +0530794 ac = (struct audio_client *)data->token;
795 pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700796 switch (payload[0]) {
797 case ASM_SESSION_CMD_MEMORY_MAP:
798 case ASM_SESSION_CMD_MEMORY_UNMAP:
799 case ASM_SESSION_CMD_MEMORY_MAP_REGIONS:
800 case ASM_SESSION_CMD_MEMORY_UNMAP_REGIONS:
801 pr_debug("%s:command[0x%x]success [0x%x]\n",
802 __func__, payload[0], payload[1]);
Deepa Madiregama636f80e2013-01-17 14:01:25 +0530803 if (atomic_read(&ac->cmd_state)) {
804 atomic_set(&ac->cmd_state, 0);
805 if (payload[1] != ADSP_EOK) {
806 pr_err("payload[1]:%d error case\n",
807 payload[1]);
808 atomic_set(&ac->cmd_response, 1);
809 } else
810 atomic_set(&ac->cmd_response, 0);
811 wake_up(&ac->cmd_wait);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700812 }
813 break;
814 default:
815 pr_debug("%s:command[0x%x] not expecting rsp\n",
816 __func__, payload[0]);
817 break;
818 }
819 }
820 return 0;
821}
822
Jay Wangcd1d37d2012-10-03 16:17:18 -0700823static int32_t is_no_wait_cmd_rsp(uint32_t opcode, uint32_t *cmd_type)
824{
825 if (opcode == APR_BASIC_RSP_RESULT) {
826 if (cmd_type != NULL) {
827 switch (cmd_type[0]) {
828 case ASM_SESSION_CMD_RUN:
829 case ASM_SESSION_CMD_PAUSE:
830 case ASM_DATA_CMD_EOS:
831 return 1;
832 default:
833 break;
834 }
835 } else
836 pr_err("%s: null pointer!", __func__);
837 } else if (opcode == ASM_DATA_CMDRSP_EOS)
838 return 1;
839
840 return 0;
841}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700842
843static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
844{
845 int i = 0;
846 struct audio_client *ac = (struct audio_client *)priv;
847 uint32_t token;
848 unsigned long dsp_flags;
849 uint32_t *payload;
Jay Wang0668d1062012-07-11 18:53:21 -0700850 uint32_t wakeup_flag = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700851
852
853 if ((ac == NULL) || (data == NULL)) {
854 pr_err("ac or priv NULL\n");
855 return -EINVAL;
856 }
857 if (ac->session <= 0 || ac->session > 8) {
858 pr_err("%s:Session ID is invalid, session = %d\n", __func__,
859 ac->session);
860 return -EINVAL;
861 }
Jay Wangcd1d37d2012-10-03 16:17:18 -0700862
863 payload = data->payload;
864 if ((atomic_read(&ac->nowait_cmd_cnt) > 0) &&
865 is_no_wait_cmd_rsp(data->opcode, payload)) {
Jay Wang0668d1062012-07-11 18:53:21 -0700866 pr_debug("%s: nowait_cmd_cnt %d\n",
867 __func__,
868 atomic_read(&ac->nowait_cmd_cnt));
869 atomic_dec(&ac->nowait_cmd_cnt);
870 wakeup_flag = 0;
871 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700872
873 if (data->opcode == RESET_EVENTS) {
874 pr_debug("q6asm_callback: Reset event is received: %d %d apr[%p]\n",
875 data->reset_event, data->reset_proc, ac->apr);
Laxminath Kasam692c6542012-02-21 11:17:47 +0530876 if (ac->cb)
877 ac->cb(data->opcode, data->token,
878 (uint32_t *)data->payload, ac->priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700879 apr_reset(ac->apr);
880 return 0;
881 }
882
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700883 pr_debug("%s: session[%d]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]\n",
884 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700885 ac->session, data->opcode,
886 data->token, data->payload_size, data->src_port,
887 data->dest_port);
888
889 if (data->opcode == APR_BASIC_RSP_RESULT) {
890 token = data->token;
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700891 pr_debug("%s payload[0]:%x", __func__, payload[0]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700892 switch (payload[0]) {
893 case ASM_STREAM_CMD_SET_PP_PARAMS:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700894 if (rtac_make_asm_callback(ac->session, payload,
895 data->payload_size))
896 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700897 case ASM_SESSION_CMD_PAUSE:
898 case ASM_DATA_CMD_EOS:
899 case ASM_STREAM_CMD_CLOSE:
900 case ASM_STREAM_CMD_FLUSH:
901 case ASM_SESSION_CMD_RUN:
902 case ASM_SESSION_CMD_REGISTER_FOR_TX_OVERFLOW_EVENTS:
903 case ASM_STREAM_CMD_FLUSH_READBUFS:
904 pr_debug("%s:Payload = [0x%x]\n", __func__, payload[0]);
905 if (token != ac->session) {
906 pr_err("%s:Invalid session[%d] rxed expected[%d]",
907 __func__, token, ac->session);
908 return -EINVAL;
909 }
910 case ASM_STREAM_CMD_OPEN_READ:
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700911 case ASM_STREAM_CMD_OPEN_READ_V2_1:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700912 case ASM_STREAM_CMD_OPEN_WRITE:
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700913 case ASM_STREAM_CMD_OPEN_WRITE_V2_1:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700914 case ASM_STREAM_CMD_OPEN_READWRITE:
Laxminath Kasam20824502013-01-07 14:33:56 +0530915 case ASM_STREAM_CMD_OPEN_LOOPBACK:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700916 case ASM_DATA_CMD_MEDIA_FORMAT_UPDATE:
917 case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
Santosh Mardi23321202012-03-22 04:33:25 +0530918 case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700919 case ASM_STREAM_CMD_OPEN_READ_COMPRESSED:
Laxminath Kasamf16d3fd2012-12-19 14:54:14 +0530920 if (payload[0] == ASM_STREAM_CMD_CLOSE) {
921 atomic_set(&ac->cmd_close_state, 0);
922 wake_up(&ac->cmd_wait);
923 } else if (atomic_read(&ac->cmd_state) &&
924 wakeup_flag) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700925 atomic_set(&ac->cmd_state, 0);
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700926 if (payload[1] == ADSP_EUNSUPPORTED) {
927 pr_debug("paload[1]:%d unsupported",
928 payload[1]);
Srikanth Uyyalaa50b51d2012-07-02 16:02:24 +0530929 atomic_set(&ac->cmd_response, 1);
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700930 }
Srikanth Uyyalaa50b51d2012-07-02 16:02:24 +0530931 else
932 atomic_set(&ac->cmd_response, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700933 wake_up(&ac->cmd_wait);
934 }
935 if (ac->cb)
936 ac->cb(data->opcode, data->token,
937 (uint32_t *)data->payload, ac->priv);
938 break;
939 default:
940 pr_debug("%s:command[0x%x] not expecting rsp\n",
941 __func__, payload[0]);
942 break;
943 }
944 return 0;
945 }
946
947 switch (data->opcode) {
948 case ASM_DATA_EVENT_WRITE_DONE:{
949 struct audio_port_data *port = &ac->port[IN];
950 pr_debug("%s: Rxed opcode[0x%x] status[0x%x] token[%d]",
951 __func__, payload[0], payload[1],
952 data->token);
Patrick Lai55f54c52012-11-17 00:29:07 -0800953 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700954 if (port->buf == NULL) {
955 pr_err("%s: Unexpected Write Done\n",
956 __func__);
957 return -EINVAL;
958 }
959 spin_lock_irqsave(&port->dsp_lock, dsp_flags);
960 if (port->buf[data->token].phys !=
961 payload[0]) {
962 pr_err("Buf expected[%p]rxed[%p]\n",\
963 (void *)port->buf[data->token].phys,\
964 (void *)payload[0]);
965 spin_unlock_irqrestore(&port->dsp_lock,
966 dsp_flags);
967 return -EINVAL;
968 }
969 token = data->token;
970 port->buf[token].used = 1;
971 spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
Rajesha Kini3498c932011-07-19 19:58:27 +0530972#ifdef CONFIG_DEBUG_FS
973 if (out_enable_flag) {
974 /* For first Write done log the time and reset
975 out_cold_index*/
976 if (out_cold_index != 1) {
977 do_gettimeofday(&out_cold_tv);
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700978 pr_debug("COLD: apr_send_pkt at %ld sec %ld microsec\n",
979 out_cold_tv.tv_sec,
Rajesha Kini3498c932011-07-19 19:58:27 +0530980 out_cold_tv.tv_usec);
981 out_cold_index = 1;
982 }
983 pr_debug("out_enable_flag %ld",\
984 out_enable_flag);
985 }
986#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700987 for (i = 0; i < port->max_buf_cnt; i++)
988 pr_debug("%d ", port->buf[i].used);
989
990 }
991 break;
992 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700993 case ASM_STREAM_CMDRSP_GET_PP_PARAMS:
994 rtac_make_asm_callback(ac->session, payload,
995 data->payload_size);
996 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700997 case ASM_DATA_EVENT_READ_DONE:{
998
999 struct audio_port_data *port = &ac->port[OUT];
Rajesha Kini3498c932011-07-19 19:58:27 +05301000#ifdef CONFIG_DEBUG_FS
1001 if (in_enable_flag) {
1002 /* when in_cont_index == 7, DSP would be
1003 * writing into the 8th 512 byte buffer and this
1004 * timestamp is tapped here.Once done it then writes
1005 * to 9th 512 byte buffer.These two buffers(8th, 9th)
1006 * reach the test application in 5th iteration and that
1007 * timestamp is tapped at user level. The difference
1008 * of these two timestamps gives us the time between
1009 * the time at which dsp started filling the sample
1010 * required and when it reached the test application.
1011 * Hence continuous input latency
1012 */
1013 if (in_cont_index == 7) {
1014 do_gettimeofday(&in_cont_tv);
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001015 pr_err("In_CONT:previous read buffer done at %ld sec %ld microsec\n",
Sriranjan Srikantam74753532011-10-03 14:48:37 -07001016 in_cont_tv.tv_sec, in_cont_tv.tv_usec);
Rajesha Kini3498c932011-07-19 19:58:27 +05301017 }
1018 }
1019#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001020 pr_debug("%s:R-D: status=%d buff_add=%x act_size=%d offset=%d\n",
1021 __func__, payload[READDONE_IDX_STATUS],
1022 payload[READDONE_IDX_BUFFER],
1023 payload[READDONE_IDX_SIZE],
1024 payload[READDONE_IDX_OFFSET]);
1025 pr_debug("%s:R-D:msw_ts=%d lsw_ts=%d flags=%d id=%d num=%d\n",
1026 __func__, payload[READDONE_IDX_MSW_TS],
1027 payload[READDONE_IDX_LSW_TS],
1028 payload[READDONE_IDX_FLAGS],
1029 payload[READDONE_IDX_ID],
1030 payload[READDONE_IDX_NUMFRAMES]);
Rajesha Kini3498c932011-07-19 19:58:27 +05301031#ifdef CONFIG_DEBUG_FS
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001032 if (in_enable_flag)
Rajesha Kini3498c932011-07-19 19:58:27 +05301033 in_cont_index++;
Rajesha Kini3498c932011-07-19 19:58:27 +05301034#endif
Patrick Lai55f54c52012-11-17 00:29:07 -08001035 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001036 if (port->buf == NULL) {
1037 pr_err("%s: Unexpected Write Done\n", __func__);
1038 return -EINVAL;
1039 }
1040 spin_lock_irqsave(&port->dsp_lock, dsp_flags);
1041 token = data->token;
1042 port->buf[token].used = 0;
1043 if (port->buf[token].phys !=
1044 payload[READDONE_IDX_BUFFER]) {
1045 pr_err("Buf expected[%p]rxed[%p]\n",\
1046 (void *)port->buf[token].phys,\
1047 (void *)payload[READDONE_IDX_BUFFER]);
1048 spin_unlock_irqrestore(&port->dsp_lock,
1049 dsp_flags);
1050 break;
1051 }
1052 port->buf[token].actual_size =
1053 payload[READDONE_IDX_SIZE];
1054 spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
1055 }
1056 break;
1057 }
1058 case ASM_DATA_EVENT_EOS:
1059 case ASM_DATA_CMDRSP_EOS:
1060 pr_debug("%s:EOS ACK received: rxed opcode[0x%x]\n",
1061 __func__, data->opcode);
1062 break;
1063 case ASM_STREAM_CMDRSP_GET_ENCDEC_PARAM:
1064 break;
1065 case ASM_SESSION_EVENT_TX_OVERFLOW:
1066 pr_err("ASM_SESSION_EVENT_TX_OVERFLOW\n");
1067 break;
1068 case ASM_SESSION_CMDRSP_GET_SESSION_TIME:
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001069 pr_debug("%s: ASM_SESSION_CMDRSP_GET_SESSION_TIME, payload[0] = %d, payload[1] = %d, payload[2] = %d\n",
1070 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001071 payload[0], payload[1], payload[2]);
1072 ac->time_stamp = (uint64_t)(((uint64_t)payload[1] << 32) |
1073 payload[2]);
1074 if (atomic_read(&ac->time_flag)) {
1075 atomic_set(&ac->time_flag, 0);
1076 wake_up(&ac->time_wait);
1077 }
1078 break;
1079 case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
Deepa Madiregama55cbf782011-09-10 05:44:39 +05301080 case ASM_DATA_EVENT_ENC_SR_CM_NOTIFY:
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001081 pr_debug("%s: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, payload[0] = %d, payload[1] = %d, payload[2] = %d, payload[3] = %d\n",
1082 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001083 payload[0], payload[1], payload[2],
1084 payload[3]);
1085 break;
1086 }
1087 if (ac->cb)
1088 ac->cb(data->opcode, data->token,
1089 data->payload, ac->priv);
1090
1091 return 0;
1092}
1093
1094void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size,
1095 uint32_t *index)
1096{
1097 void *data;
1098 unsigned char idx;
1099 struct audio_port_data *port;
1100
1101 if (!ac || ((dir != IN) && (dir != OUT)))
1102 return NULL;
1103
Patrick Lai55f54c52012-11-17 00:29:07 -08001104 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001105 port = &ac->port[dir];
1106
1107 mutex_lock(&port->lock);
1108 idx = port->cpu_buf;
1109 if (port->buf == NULL) {
1110 pr_debug("%s:Buffer pointer null\n", __func__);
Jayasena Sangaraboina466e6b92012-01-17 21:10:55 -08001111 mutex_unlock(&port->lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001112 return NULL;
1113 }
1114 /* dir 0: used = 0 means buf in use
1115 dir 1: used = 1 means buf in use */
1116 if (port->buf[idx].used == dir) {
1117 /* To make it more robust, we could loop and get the
1118 next avail buf, its risky though */
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001119 pr_debug("%s:Next buf idx[0x%x] not available,dir[%d]\n",
1120 __func__, idx, dir);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001121 mutex_unlock(&port->lock);
1122 return NULL;
1123 }
1124 *size = port->buf[idx].actual_size;
1125 *index = port->cpu_buf;
1126 data = port->buf[idx].data;
1127 pr_debug("%s:session[%d]index[%d] data[%p]size[%d]\n",
1128 __func__,
1129 ac->session,
1130 port->cpu_buf,
1131 data, *size);
1132 /* By default increase the cpu_buf cnt
1133 user accesses this function,increase cpu
1134 buf(to avoid another api)*/
1135 port->buf[idx].used = dir;
1136 port->cpu_buf = ((port->cpu_buf + 1) & (port->max_buf_cnt - 1));
1137 mutex_unlock(&port->lock);
1138 return data;
1139 }
1140 return NULL;
1141}
1142
Jay Wang9cf59a02011-08-10 16:58:40 -07001143void *q6asm_is_cpu_buf_avail_nolock(int dir, struct audio_client *ac,
1144 uint32_t *size, uint32_t *index)
1145{
1146 void *data;
1147 unsigned char idx;
1148 struct audio_port_data *port;
1149
1150 if (!ac || ((dir != IN) && (dir != OUT)))
1151 return NULL;
1152
1153 port = &ac->port[dir];
1154
1155 idx = port->cpu_buf;
1156 if (port->buf == NULL) {
1157 pr_debug("%s:Buffer pointer null\n", __func__);
1158 return NULL;
1159 }
1160 /*
1161 * dir 0: used = 0 means buf in use
1162 * dir 1: used = 1 means buf in use
1163 */
1164 if (port->buf[idx].used == dir) {
1165 /*
1166 * To make it more robust, we could loop and get the
1167 * next avail buf, its risky though
1168 */
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001169 pr_debug("%s:Next buf idx[0x%x] not available, dir[%d]\n",
1170 __func__, idx, dir);
Jay Wang9cf59a02011-08-10 16:58:40 -07001171 return NULL;
1172 }
1173 *size = port->buf[idx].actual_size;
1174 *index = port->cpu_buf;
1175 data = port->buf[idx].data;
1176 pr_debug("%s:session[%d]index[%d] data[%p]size[%d]\n",
1177 __func__, ac->session, port->cpu_buf,
1178 data, *size);
1179 /*
1180 * By default increase the cpu_buf cnt
1181 * user accesses this function,increase cpu
1182 * buf(to avoid another api)
1183 */
1184 port->buf[idx].used = dir;
1185 port->cpu_buf = ((port->cpu_buf + 1) & (port->max_buf_cnt - 1));
1186 return data;
1187}
1188
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001189int q6asm_is_dsp_buf_avail(int dir, struct audio_client *ac)
1190{
1191 int ret = -1;
1192 struct audio_port_data *port;
1193 uint32_t idx;
1194
1195 if (!ac || (dir != OUT))
1196 return ret;
1197
Patrick Lai55f54c52012-11-17 00:29:07 -08001198 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001199 port = &ac->port[dir];
1200
1201 mutex_lock(&port->lock);
1202 idx = port->dsp_buf;
1203
1204 if (port->buf[idx].used == (dir ^ 1)) {
1205 /* To make it more robust, we could loop and get the
1206 next avail buf, its risky though */
1207 pr_err("Next buf idx[0x%x] not available, dir[%d]\n",
1208 idx, dir);
1209 mutex_unlock(&port->lock);
1210 return ret;
1211 }
1212 pr_debug("%s: session[%d]dsp_buf=%d cpu_buf=%d\n", __func__,
1213 ac->session, port->dsp_buf, port->cpu_buf);
1214 ret = ((port->dsp_buf != port->cpu_buf) ? 0 : -1);
1215 mutex_unlock(&port->lock);
1216 }
1217 return ret;
1218}
1219
1220static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
1221 uint32_t pkt_size, uint32_t cmd_flg)
1222{
1223 pr_debug("%s:session=%d pkt size=%d cmd_flg=%d\n", __func__, pkt_size,
1224 cmd_flg, ac->session);
1225 mutex_lock(&ac->cmd_lock);
1226 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
1227 APR_HDR_LEN(sizeof(struct apr_hdr)),\
1228 APR_PKT_VER);
1229 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
1230 hdr->src_domain = APR_DOMAIN_APPS;
1231 hdr->dest_svc = APR_SVC_ASM;
1232 hdr->dest_domain = APR_DOMAIN_ADSP;
1233 hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01;
1234 hdr->dest_port = ((ac->session << 8) & 0xFF00) | 0x01;
1235 if (cmd_flg) {
1236 hdr->token = ac->session;
1237 atomic_set(&ac->cmd_state, 1);
1238 }
1239 hdr->pkt_size = pkt_size;
1240 mutex_unlock(&ac->cmd_lock);
1241 return;
1242}
1243
1244static void q6asm_add_mmaphdr(struct apr_hdr *hdr, uint32_t pkt_size,
1245 uint32_t cmd_flg)
1246{
Deepa Madiregama636f80e2013-01-17 14:01:25 +05301247 struct audio_client *ac;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001248 pr_debug("%s:pkt size=%d cmd_flg=%d\n", __func__, pkt_size, cmd_flg);
Deepa Madiregama636f80e2013-01-17 14:01:25 +05301249 ac = (struct audio_client *)hdr->token;
1250 pr_debug("%s: audio_client = %x\n", __func__, (uint32_t)ac);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001251 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
1252 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1253 hdr->src_port = 0;
1254 hdr->dest_port = 0;
1255 if (cmd_flg) {
Deepa Madiregama636f80e2013-01-17 14:01:25 +05301256 atomic_set(&ac->cmd_state, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001257 }
1258 hdr->pkt_size = pkt_size;
1259 return;
1260}
1261
1262int q6asm_open_read(struct audio_client *ac,
1263 uint32_t format)
1264{
1265 int rc = 0x00;
1266 struct asm_stream_cmd_open_read open;
Rajesha Kini3498c932011-07-19 19:58:27 +05301267#ifdef CONFIG_DEBUG_FS
1268 in_cont_index = 0;
1269#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001270 if ((ac == NULL) || (ac->apr == NULL)) {
1271 pr_err("%s: APR handle NULL\n", __func__);
1272 return -EINVAL;
1273 }
1274 pr_debug("%s:session[%d]", __func__, ac->session);
1275
1276 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1277 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ;
1278 /* Stream prio : High, provide meta info with encoded frames */
1279 open.src_endpoint = ASM_END_POINT_DEVICE_MATRIX;
1280
1281 open.pre_proc_top = get_asm_topology();
1282 if (open.pre_proc_top == 0)
1283 open.pre_proc_top = DEFAULT_POPP_TOPOLOGY;
1284
1285 switch (format) {
1286 case FORMAT_LINEAR_PCM:
1287 open.uMode = STREAM_PRIORITY_HIGH;
1288 open.format = LINEAR_PCM;
1289 break;
Mingming Yin647e9ea2012-03-17 19:56:10 -07001290 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
1291 open.uMode = STREAM_PRIORITY_HIGH;
1292 open.format = MULTI_CHANNEL_PCM;
1293 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001294 case FORMAT_MPEG4_AAC:
1295 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1296 open.format = MPEG4_AAC;
1297 break;
1298 case FORMAT_V13K:
1299 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1300 open.format = V13K_FS;
1301 break;
1302 case FORMAT_EVRC:
1303 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1304 open.format = EVRC_FS;
1305 break;
1306 case FORMAT_AMRNB:
1307 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1308 open.format = AMRNB_FS;
1309 break;
Alex Wong2caeecc2011-10-28 10:52:15 +05301310 case FORMAT_AMRWB:
1311 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1312 open.format = AMRWB_FS;
1313 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001314 default:
1315 pr_err("Invalid format[%d]\n", format);
1316 goto fail_cmd;
1317 }
1318 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1319 if (rc < 0) {
1320 pr_err("open failed op[0x%x]rc[%d]\n", \
1321 open.hdr.opcode, rc);
1322 goto fail_cmd;
1323 }
1324 rc = wait_event_timeout(ac->cmd_wait,
1325 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1326 if (!rc) {
1327 pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
1328 rc);
1329 goto fail_cmd;
1330 }
Patrick Lai55f54c52012-11-17 00:29:07 -08001331
1332 ac->io_mode |= TUN_READ_IO_MODE;
1333
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001334 return 0;
1335fail_cmd:
1336 return -EINVAL;
1337}
1338
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001339int q6asm_open_read_v2_1(struct audio_client *ac,
1340 uint32_t format)
1341{
1342 int rc = 0x00;
1343 struct asm_stream_cmd_open_read_v2_1 open;
1344#ifdef CONFIG_DEBUG_FS
1345 in_cont_index = 0;
1346#endif
1347 if ((ac == NULL) || (ac->apr == NULL)) {
1348 pr_err("%s: APR handle NULL\n", __func__);
1349 return -EINVAL;
1350 }
1351 pr_debug("%s:session[%d]", __func__, ac->session);
1352
1353 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1354 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ_V2_1;
1355 open.src_endpoint = ASM_END_POINT_DEVICE_MATRIX;
1356 open.pre_proc_top = get_asm_topology();
1357 if (open.pre_proc_top == 0)
1358 open.pre_proc_top = DEFAULT_POPP_TOPOLOGY;
1359
1360 switch (format) {
1361 case FORMAT_LINEAR_PCM:
1362 open.uMode = STREAM_PRIORITY_HIGH;
1363 open.format = LINEAR_PCM;
1364 break;
1365 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
1366 open.uMode = STREAM_PRIORITY_HIGH;
1367 open.format = MULTI_CHANNEL_PCM;
1368 break;
1369 case FORMAT_MPEG4_AAC:
1370 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1371 open.format = MPEG4_AAC;
1372 break;
1373 case FORMAT_V13K:
1374 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1375 open.format = V13K_FS;
1376 break;
1377 case FORMAT_EVRC:
1378 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1379 open.format = EVRC_FS;
1380 break;
1381 case FORMAT_AMRNB:
1382 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1383 open.format = AMRNB_FS;
1384 break;
1385 case FORMAT_AMRWB:
1386 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1387 open.format = AMRWB_FS;
1388 break;
1389 default:
1390 pr_err("Invalid format[%d]\n", format);
1391 goto fail_cmd;
1392 }
1393 open.uMode = ASM_OPEN_READ_PERF_MODE_BIT;
1394 open.bits_per_sample = PCM_BITS_PER_SAMPLE;
1395 open.reserved = 0;
1396 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1397 if (rc < 0) {
1398 pr_err("open failed op[0x%x]rc[%d]\n", \
1399 open.hdr.opcode, rc);
1400 goto fail_cmd;
1401 }
1402 rc = wait_event_timeout(ac->cmd_wait,
1403 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1404 if (!rc) {
1405 pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
1406 rc);
1407 goto fail_cmd;
1408 }
1409 return 0;
1410fail_cmd:
1411 return -EINVAL;
1412}
1413
1414
Subhash Chandra Bose Naripeddy694b7d92012-06-20 20:46:13 -07001415int q6asm_open_read_compressed(struct audio_client *ac,
1416 uint32_t frames_per_buffer, uint32_t meta_data_mode)
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001417{
1418 int rc = 0x00;
1419 struct asm_stream_cmd_open_read_compressed open;
1420#ifdef CONFIG_DEBUG_FS
1421 in_cont_index = 0;
1422#endif
1423 if ((ac == NULL) || (ac->apr == NULL)) {
1424 pr_err("%s: APR handle NULL\n", __func__);
1425 return -EINVAL;
1426 }
1427 pr_debug("%s:session[%d]", __func__, ac->session);
1428
1429 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1430 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ_COMPRESSED;
1431 /* hardcoded as following*/
Subhash Chandra Bose Naripeddy694b7d92012-06-20 20:46:13 -07001432 open.frame_per_buf = frames_per_buffer;
1433 open.uMode = meta_data_mode;
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001434
1435 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1436 if (rc < 0) {
1437 pr_err("open failed op[0x%x]rc[%d]\n", open.hdr.opcode, rc);
1438 goto fail_cmd;
1439 }
1440 rc = wait_event_timeout(ac->cmd_wait,
1441 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1442 if (!rc) {
1443 pr_err("%s: timeout. waited for OPEN_READ_COMPRESSED rc[%d]\n",
1444 __func__, rc);
1445 goto fail_cmd;
1446 }
1447 return 0;
1448fail_cmd:
1449 return -EINVAL;
1450}
1451
Santosh Mardi23321202012-03-22 04:33:25 +05301452int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format)
1453{
1454 int rc = 0x00;
1455 struct asm_stream_cmd_open_write_compressed open;
1456
1457 if ((ac == NULL) || (ac->apr == NULL)) {
1458 pr_err("%s: APR handle NULL\n", __func__);
1459 return -EINVAL;
1460 }
1461 pr_debug("%s: session[%d] wr_format[0x%x]", __func__, ac->session,
1462 format);
1463
1464 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1465
1466 open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED;
1467
1468 switch (format) {
1469 case FORMAT_AC3:
1470 open.format = AC3_DECODER;
1471 break;
1472 case FORMAT_EAC3:
1473 open.format = EAC3_DECODER;
1474 break;
1475 case FORMAT_MP3:
1476 open.format = MP3;
1477 break;
1478 case FORMAT_DTS:
1479 open.format = DTS;
1480 break;
Srikanth Uyyala66f781a2012-06-13 23:23:25 +05301481 case FORMAT_DTS_LBR:
1482 open.format = DTS_LBR;
1483 break;
Santosh Mardi23321202012-03-22 04:33:25 +05301484 case FORMAT_AAC:
1485 open.format = MPEG4_AAC;
1486 break;
1487 case FORMAT_ATRAC:
1488 open.format = ATRAC;
1489 break;
1490 case FORMAT_WMA_V10PRO:
1491 open.format = WMA_V10PRO;
1492 break;
1493 case FORMAT_MAT:
1494 open.format = MAT;
1495 break;
1496 default:
1497 pr_err("%s: Invalid format[%d]\n", __func__, format);
1498 goto fail_cmd;
1499 }
1500 /*Below flag indicates the DSP that Compressed audio input
1501 stream is not IEC 61937 or IEC 60958 packetizied*/
1502 open.flags = 0x00000000;
1503 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1504 if (rc < 0) {
1505 pr_err("%s: open failed op[0x%x]rc[%d]\n", \
1506 __func__, open.hdr.opcode, rc);
1507 goto fail_cmd;
1508 }
1509 rc = wait_event_timeout(ac->cmd_wait,
1510 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1511 if (!rc) {
1512 pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
1513 rc);
1514 goto fail_cmd;
1515 }
1516 return 0;
1517fail_cmd:
1518 return -EINVAL;
1519}
1520
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001521int q6asm_open_write(struct audio_client *ac, uint32_t format)
1522{
1523 int rc = 0x00;
1524 struct asm_stream_cmd_open_write open;
1525
1526 if ((ac == NULL) || (ac->apr == NULL)) {
1527 pr_err("%s: APR handle NULL\n", __func__);
1528 return -EINVAL;
1529 }
1530 pr_debug("%s: session[%d] wr_format[0x%x]", __func__, ac->session,
1531 format);
1532
1533 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1534
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001535 if (ac->perf_mode) {
1536 pr_debug("%s In Performance/lowlatency mode", __func__);
1537 open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V2_1;
1538 open.uMode = ASM_OPEN_WRITE_PERF_MODE_BIT;
1539 /* source endpoint : matrix */
1540 open.sink_endpoint = ASM_END_POINT_DEVICE_MATRIX;
1541 open.stream_handle = PCM_BITS_PER_SAMPLE;
1542 } else {
1543 open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE;
1544 open.uMode = STREAM_PRIORITY_HIGH;
1545 /* source endpoint : matrix */
1546 open.sink_endpoint = ASM_END_POINT_DEVICE_MATRIX;
1547 open.stream_handle = 0x00;
1548 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001549 open.post_proc_top = get_asm_topology();
1550 if (open.post_proc_top == 0)
1551 open.post_proc_top = DEFAULT_POPP_TOPOLOGY;
1552
1553 switch (format) {
1554 case FORMAT_LINEAR_PCM:
1555 open.format = LINEAR_PCM;
1556 break;
Kiran Kandi5e809b02012-01-31 00:24:33 -08001557 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
1558 open.format = MULTI_CHANNEL_PCM;
1559 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001560 case FORMAT_MPEG4_AAC:
1561 open.format = MPEG4_AAC;
1562 break;
Bharath Ramachandramurthy4f71d502011-10-23 19:45:22 -07001563 case FORMAT_MPEG4_MULTI_AAC:
1564 open.format = MPEG4_MULTI_AAC;
1565 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001566 case FORMAT_WMA_V9:
1567 open.format = WMA_V9;
1568 break;
1569 case FORMAT_WMA_V10PRO:
1570 open.format = WMA_V10PRO;
1571 break;
Asish Bhattacharya305d1752011-11-01 20:38:26 +05301572 case FORMAT_MP3:
1573 open.format = MP3;
1574 break;
Srikanth Uyyala66f781a2012-06-13 23:23:25 +05301575 case FORMAT_DTS:
1576 open.format = DTS;
1577 break;
1578 case FORMAT_DTS_LBR:
1579 open.format = DTS_LBR;
1580 break;
Ajit Khare43fd8832012-08-07 13:19:44 -07001581 case FORMAT_AMRWB:
1582 open.format = AMRWB_FS;
1583 pr_debug("q6asm_open_write FORMAT_AMRWB");
1584 break;
1585 case FORMAT_AMR_WB_PLUS:
1586 open.format = AMR_WB_PLUS;
1587 pr_debug("q6asm_open_write FORMAT_AMR_WB_PLUS");
1588 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001589 default:
1590 pr_err("%s: Invalid format[%d]\n", __func__, format);
1591 goto fail_cmd;
1592 }
1593 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1594 if (rc < 0) {
1595 pr_err("%s: open failed op[0x%x]rc[%d]\n", \
1596 __func__, open.hdr.opcode, rc);
1597 goto fail_cmd;
1598 }
1599 rc = wait_event_timeout(ac->cmd_wait,
1600 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1601 if (!rc) {
1602 pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
1603 rc);
1604 goto fail_cmd;
1605 }
Srikanth Uyyalaa50b51d2012-07-02 16:02:24 +05301606 if (atomic_read(&ac->cmd_response)) {
1607 pr_err("%s: format = %x not supported\n", __func__, format);
1608 goto fail_cmd;
1609 }
Patrick Lai55f54c52012-11-17 00:29:07 -08001610
1611 ac->io_mode |= TUN_WRITE_IO_MODE;
1612
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001613 return 0;
1614fail_cmd:
1615 return -EINVAL;
1616}
1617
1618int q6asm_open_read_write(struct audio_client *ac,
1619 uint32_t rd_format,
1620 uint32_t wr_format)
1621{
1622 int rc = 0x00;
1623 struct asm_stream_cmd_open_read_write open;
1624
1625 if ((ac == NULL) || (ac->apr == NULL)) {
1626 pr_err("APR handle NULL\n");
1627 return -EINVAL;
1628 }
1629 pr_debug("%s: session[%d]", __func__, ac->session);
1630 pr_debug("wr_format[0x%x]rd_format[0x%x]",
1631 wr_format, rd_format);
1632
1633 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1634 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READWRITE;
1635
Deepa Madiregama55cbf782011-09-10 05:44:39 +05301636 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_NORMAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001637 /* source endpoint : matrix */
1638 open.post_proc_top = get_asm_topology();
1639 if (open.post_proc_top == 0)
1640 open.post_proc_top = DEFAULT_POPP_TOPOLOGY;
1641
1642 switch (wr_format) {
1643 case FORMAT_LINEAR_PCM:
1644 open.write_format = LINEAR_PCM;
1645 break;
1646 case FORMAT_MPEG4_AAC:
1647 open.write_format = MPEG4_AAC;
1648 break;
Bharath Ramachandramurthy4f71d502011-10-23 19:45:22 -07001649 case FORMAT_MPEG4_MULTI_AAC:
1650 open.write_format = MPEG4_MULTI_AAC;
1651 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001652 case FORMAT_WMA_V9:
1653 open.write_format = WMA_V9;
1654 break;
1655 case FORMAT_WMA_V10PRO:
1656 open.write_format = WMA_V10PRO;
1657 break;
Alex Wong2caeecc2011-10-28 10:52:15 +05301658 case FORMAT_AMRNB:
1659 open.write_format = AMRNB_FS;
1660 break;
1661 case FORMAT_AMRWB:
1662 open.write_format = AMRWB_FS;
1663 break;
Ajit Khare7277bb72012-10-31 16:34:22 -07001664 case FORMAT_AMR_WB_PLUS:
1665 open.write_format = AMR_WB_PLUS;
1666 break;
Alex Wong2caeecc2011-10-28 10:52:15 +05301667 case FORMAT_V13K:
1668 open.write_format = V13K_FS;
1669 break;
1670 case FORMAT_EVRC:
1671 open.write_format = EVRC_FS;
1672 break;
1673 case FORMAT_EVRCB:
1674 open.write_format = EVRCB_FS;
1675 break;
1676 case FORMAT_EVRCWB:
1677 open.write_format = EVRCWB_FS;
1678 break;
1679 case FORMAT_MP3:
1680 open.write_format = MP3;
1681 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001682 default:
1683 pr_err("Invalid format[%d]\n", wr_format);
1684 goto fail_cmd;
1685 }
1686
1687 switch (rd_format) {
1688 case FORMAT_LINEAR_PCM:
1689 open.read_format = LINEAR_PCM;
1690 break;
1691 case FORMAT_MPEG4_AAC:
1692 open.read_format = MPEG4_AAC;
1693 break;
1694 case FORMAT_V13K:
1695 open.read_format = V13K_FS;
1696 break;
1697 case FORMAT_EVRC:
1698 open.read_format = EVRC_FS;
1699 break;
1700 case FORMAT_AMRNB:
1701 open.read_format = AMRNB_FS;
1702 break;
Alex Wong2caeecc2011-10-28 10:52:15 +05301703 case FORMAT_AMRWB:
1704 open.read_format = AMRWB_FS;
1705 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001706 default:
1707 pr_err("Invalid format[%d]\n", rd_format);
1708 goto fail_cmd;
1709 }
1710 pr_debug("%s:rdformat[0x%x]wrformat[0x%x]\n", __func__,
1711 open.read_format, open.write_format);
1712
1713 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1714 if (rc < 0) {
1715 pr_err("open failed op[0x%x]rc[%d]\n", \
1716 open.hdr.opcode, rc);
1717 goto fail_cmd;
1718 }
1719 rc = wait_event_timeout(ac->cmd_wait,
1720 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1721 if (!rc) {
1722 pr_err("timeout. waited for OPEN_WRITE rc[%d]\n", rc);
1723 goto fail_cmd;
1724 }
1725 return 0;
1726fail_cmd:
1727 return -EINVAL;
1728}
1729
Laxminath Kasam20824502013-01-07 14:33:56 +05301730int q6asm_open_loopack(struct audio_client *ac)
1731{
1732 int rc = 0x00;
1733 struct asm_stream_cmd_open_loopback open;
1734
1735 if ((ac == NULL) || (ac->apr == NULL)) {
1736 pr_err("APR handle NULL\n");
1737 return -EINVAL;
1738 }
1739 pr_debug("%s: session[%d]", __func__, ac->session);
1740
1741 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1742 open.hdr.opcode = ASM_STREAM_CMD_OPEN_LOOPBACK;
1743
1744 open.mode_flags = 0;
1745 open.src_endpointype = 0;
1746 open.sink_endpointype = 0;
1747 /* source endpoint : matrix */
1748 open.postprocopo_id = get_asm_topology();
1749 if (open.postprocopo_id == 0)
1750 open.postprocopo_id = DEFAULT_POPP_TOPOLOGY;
1751
1752 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1753 if (rc < 0) {
1754 pr_err("open failed op[0x%x]rc[%d]\n", \
1755 open.hdr.opcode, rc);
1756 goto fail_cmd;
1757 }
1758 rc = wait_event_timeout(ac->cmd_wait,
1759 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1760 if (!rc) {
1761 pr_err("timeout. waited for OPEN_WRITE rc[%d]\n", rc);
1762 goto fail_cmd;
1763 }
1764 return 0;
1765fail_cmd:
1766 return -EINVAL;
1767}
1768
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001769int q6asm_run(struct audio_client *ac, uint32_t flags,
1770 uint32_t msw_ts, uint32_t lsw_ts)
1771{
1772 struct asm_stream_cmd_run run;
1773 int rc;
1774 if (!ac || ac->apr == NULL) {
1775 pr_err("APR handle NULL\n");
1776 return -EINVAL;
1777 }
1778 pr_debug("%s session[%d]", __func__, ac->session);
1779 q6asm_add_hdr(ac, &run.hdr, sizeof(run), TRUE);
1780
1781 run.hdr.opcode = ASM_SESSION_CMD_RUN;
1782 run.flags = flags;
1783 run.msw_ts = msw_ts;
1784 run.lsw_ts = lsw_ts;
Rajesha Kini3498c932011-07-19 19:58:27 +05301785#ifdef CONFIG_DEBUG_FS
1786 if (out_enable_flag) {
1787 do_gettimeofday(&out_cold_tv);
1788 pr_debug("COLD: apr_send_pkt at %ld sec %ld microsec\n",\
1789 out_cold_tv.tv_sec, out_cold_tv.tv_usec);
1790 }
1791#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001792 rc = apr_send_pkt(ac->apr, (uint32_t *) &run);
1793 if (rc < 0) {
1794 pr_err("Commmand run failed[%d]", rc);
1795 goto fail_cmd;
1796 }
1797
1798 rc = wait_event_timeout(ac->cmd_wait,
1799 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1800 if (!rc) {
1801 pr_err("timeout. waited for run success rc[%d]", rc);
1802 goto fail_cmd;
1803 }
1804
1805 return 0;
1806fail_cmd:
1807 return -EINVAL;
1808}
1809
1810int q6asm_run_nowait(struct audio_client *ac, uint32_t flags,
1811 uint32_t msw_ts, uint32_t lsw_ts)
1812{
1813 struct asm_stream_cmd_run run;
1814 int rc;
1815 if (!ac || ac->apr == NULL) {
1816 pr_err("%s:APR handle NULL\n", __func__);
1817 return -EINVAL;
1818 }
1819 pr_debug("session[%d]", ac->session);
1820 q6asm_add_hdr_async(ac, &run.hdr, sizeof(run), TRUE);
1821
1822 run.hdr.opcode = ASM_SESSION_CMD_RUN;
1823 run.flags = flags;
1824 run.msw_ts = msw_ts;
1825 run.lsw_ts = lsw_ts;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001826 rc = apr_send_pkt(ac->apr, (uint32_t *) &run);
1827 if (rc < 0) {
1828 pr_err("%s:Commmand run failed[%d]", __func__, rc);
1829 return -EINVAL;
1830 }
Jay Wang0668d1062012-07-11 18:53:21 -07001831 atomic_inc(&ac->nowait_cmd_cnt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001832 return 0;
1833}
1834
1835
1836int q6asm_enc_cfg_blk_aac(struct audio_client *ac,
1837 uint32_t frames_per_buf,
1838 uint32_t sample_rate, uint32_t channels,
1839 uint32_t bit_rate, uint32_t mode, uint32_t format)
1840{
1841 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1842 int rc = 0;
1843
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001844 pr_debug("%s:session[%d]frames[%d]SR[%d]ch[%d]bitrate[%d]mode[%d] format[%d]",
1845 __func__, ac->session, frames_per_buf,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001846 sample_rate, channels, bit_rate, mode, format);
1847
1848 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1849
1850 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1851 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1852 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1853 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
1854 enc_cfg.enc_blk.format_id = MPEG4_AAC;
1855 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_aac_read_cfg);
1856 enc_cfg.enc_blk.cfg.aac.bitrate = bit_rate;
1857 enc_cfg.enc_blk.cfg.aac.enc_mode = mode;
1858 enc_cfg.enc_blk.cfg.aac.format = format;
1859 enc_cfg.enc_blk.cfg.aac.ch_cfg = channels;
1860 enc_cfg.enc_blk.cfg.aac.sample_rate = sample_rate;
1861
1862 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
1863 if (rc < 0) {
1864 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
1865 rc = -EINVAL;
1866 goto fail_cmd;
1867 }
1868 rc = wait_event_timeout(ac->cmd_wait,
1869 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1870 if (!rc) {
1871 pr_err("timeout. waited for FORMAT_UPDATE\n");
1872 goto fail_cmd;
1873 }
1874 return 0;
1875fail_cmd:
1876 return -EINVAL;
1877}
1878
1879int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
1880 uint32_t rate, uint32_t channels)
1881{
1882 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1883
1884 int rc = 0;
1885
1886 pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
1887 ac->session, rate, channels);
1888
1889 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1890
1891 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1892 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1893 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1894 enc_cfg.enc_blk.frames_per_buf = 1;
1895 enc_cfg.enc_blk.format_id = LINEAR_PCM;
1896 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_pcm_cfg);
1897 enc_cfg.enc_blk.cfg.pcm.ch_cfg = channels;
1898 enc_cfg.enc_blk.cfg.pcm.bits_per_sample = 16;
1899 enc_cfg.enc_blk.cfg.pcm.sample_rate = rate;
1900 enc_cfg.enc_blk.cfg.pcm.is_signed = 1;
1901 enc_cfg.enc_blk.cfg.pcm.interleaved = 1;
1902
1903 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
1904 if (rc < 0) {
1905 pr_err("Comamnd open failed\n");
1906 rc = -EINVAL;
1907 goto fail_cmd;
1908 }
1909 rc = wait_event_timeout(ac->cmd_wait,
1910 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1911 if (!rc) {
1912 pr_err("timeout opcode[0x%x] ", enc_cfg.hdr.opcode);
1913 goto fail_cmd;
1914 }
1915 return 0;
1916fail_cmd:
1917 return -EINVAL;
1918}
1919
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001920int q6asm_enc_cfg_blk_pcm_native(struct audio_client *ac,
1921 uint32_t rate, uint32_t channels)
1922{
1923 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1924
1925 int rc = 0;
1926
1927 pr_debug("%s: Session %d, rate = %d, channels = %d, setting the rate and channels to 0 for native\n",
1928 __func__, ac->session, rate, channels);
1929
1930 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1931
1932 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1933 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1934 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1935 enc_cfg.enc_blk.frames_per_buf = 1;
1936 enc_cfg.enc_blk.format_id = LINEAR_PCM;
1937 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_pcm_cfg);
1938 enc_cfg.enc_blk.cfg.pcm.ch_cfg = 0;/*channels;*/
1939 enc_cfg.enc_blk.cfg.pcm.bits_per_sample = 16;
1940 enc_cfg.enc_blk.cfg.pcm.sample_rate = 0;/*rate;*/
1941 enc_cfg.enc_blk.cfg.pcm.is_signed = 1;
1942 enc_cfg.enc_blk.cfg.pcm.interleaved = 1;
1943
1944 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
1945 if (rc < 0) {
1946 pr_err("Comamnd open failed\n");
1947 rc = -EINVAL;
1948 goto fail_cmd;
1949 }
1950 rc = wait_event_timeout(ac->cmd_wait,
1951 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1952 if (!rc) {
1953 pr_err("timeout opcode[0x%x] ", enc_cfg.hdr.opcode);
1954 goto fail_cmd;
1955 }
1956 return 0;
1957fail_cmd:
1958 return -EINVAL;
1959}
1960
Mingming Yin647e9ea2012-03-17 19:56:10 -07001961int q6asm_enc_cfg_blk_multi_ch_pcm(struct audio_client *ac,
1962 uint32_t rate, uint32_t channels)
1963{
1964 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1965
1966 int rc = 0;
1967
1968 pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
1969 ac->session, rate, channels);
1970
1971 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1972
1973 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1974 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1975 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1976 enc_cfg.enc_blk.frames_per_buf = 1;
1977 enc_cfg.enc_blk.format_id = MULTI_CHANNEL_PCM;
1978 enc_cfg.enc_blk.cfg_size =
1979 sizeof(struct asm_multi_channel_pcm_fmt_blk);
1980 enc_cfg.enc_blk.cfg.mpcm.num_channels = channels;
1981 enc_cfg.enc_blk.cfg.mpcm.bits_per_sample = 16;
1982 enc_cfg.enc_blk.cfg.mpcm.sample_rate = rate;
1983 enc_cfg.enc_blk.cfg.mpcm.is_signed = 1;
1984 enc_cfg.enc_blk.cfg.mpcm.is_interleaved = 1;
Subhash Chandra Bose Naripeddy68d103a2012-08-17 21:03:19 -07001985 if (channels == 1) {
1986 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
1987 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = 0;
1988 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = 0;
1989 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[3] = 0;
1990 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[4] = 0;
1991 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[5] = 0;
1992 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[6] = 0;
1993 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[7] = 0;
1994 } else if (channels == 2) {
Subhash Chandra Bose Naripeddy8477d222012-06-12 00:30:54 -07001995 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
1996 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = PCM_CHANNEL_FR;
1997 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = 0;
1998 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[3] = 0;
1999 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[4] = 0;
2000 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[5] = 0;
2001 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[6] = 0;
2002 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[7] = 0;
2003 } else if (channels == 4) {
2004 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
2005 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = PCM_CHANNEL_FR;
2006 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = PCM_CHANNEL_RB;
2007 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[3] = PCM_CHANNEL_LB;
2008 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[4] = 0;
2009 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[5] = 0;
2010 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[6] = 0;
2011 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[7] = 0;
2012 } else if (channels == 6) {
2013 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
2014 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = PCM_CHANNEL_FR;
2015 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = PCM_CHANNEL_LFE;
2016 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[3] = PCM_CHANNEL_FC;
2017 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[4] = PCM_CHANNEL_LB;
2018 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[5] = PCM_CHANNEL_RB;
2019 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[6] = 0;
2020 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[7] = 0;
2021 } else if (channels == 8) {
2022 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
2023 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = PCM_CHANNEL_FR;
2024 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = PCM_CHANNEL_LFE;
2025 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[3] = PCM_CHANNEL_FC;
2026 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[4] = PCM_CHANNEL_LB;
2027 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[5] = PCM_CHANNEL_RB;
2028 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[6] = PCM_CHANNEL_FLC;
2029 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[7] = PCM_CHANNEL_FRC;
2030 }
Mingming Yin647e9ea2012-03-17 19:56:10 -07002031
2032 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
2033 if (rc < 0) {
2034 pr_err("Comamnd open failed\n");
2035 rc = -EINVAL;
2036 goto fail_cmd;
2037 }
2038 rc = wait_event_timeout(ac->cmd_wait,
2039 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2040 if (!rc) {
2041 pr_err("timeout opcode[0x%x] ", enc_cfg.hdr.opcode);
2042 goto fail_cmd;
2043 }
2044 return 0;
2045fail_cmd:
2046 return -EINVAL;
2047}
2048
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002049int q6asm_enable_sbrps(struct audio_client *ac,
2050 uint32_t sbr_ps_enable)
2051{
2052 struct asm_stream_cmd_encdec_sbr sbrps;
2053
2054 int rc = 0;
2055
2056 pr_debug("%s: Session %d\n", __func__, ac->session);
2057
2058 q6asm_add_hdr(ac, &sbrps.hdr, sizeof(sbrps), TRUE);
2059
2060 sbrps.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2061 sbrps.param_id = ASM_ENABLE_SBR_PS;
2062 sbrps.param_size = sizeof(struct asm_sbr_ps);
2063 sbrps.sbr_ps.enable = sbr_ps_enable;
2064
2065 rc = apr_send_pkt(ac->apr, (uint32_t *) &sbrps);
2066 if (rc < 0) {
2067 pr_err("Command opcode[0x%x]paramid[0x%x] failed\n",
2068 ASM_STREAM_CMD_SET_ENCDEC_PARAM,
2069 ASM_ENABLE_SBR_PS);
2070 rc = -EINVAL;
2071 goto fail_cmd;
2072 }
2073 rc = wait_event_timeout(ac->cmd_wait,
2074 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2075 if (!rc) {
2076 pr_err("timeout opcode[0x%x] ", sbrps.hdr.opcode);
2077 goto fail_cmd;
2078 }
2079 return 0;
2080fail_cmd:
2081 return -EINVAL;
2082}
2083
Swaminathan Sathappan70765cd2011-07-19 18:42:47 -07002084int q6asm_cfg_dual_mono_aac(struct audio_client *ac,
2085 uint16_t sce_left, uint16_t sce_right)
2086{
2087 struct asm_stream_cmd_encdec_dualmono dual_mono;
2088
2089 int rc = 0;
2090
2091 pr_debug("%s: Session %d, sce_left = %d, sce_right = %d\n",
2092 __func__, ac->session, sce_left, sce_right);
2093
2094 q6asm_add_hdr(ac, &dual_mono.hdr, sizeof(dual_mono), TRUE);
2095
2096 dual_mono.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2097 dual_mono.param_id = ASM_CONFIGURE_DUAL_MONO;
2098 dual_mono.param_size = sizeof(struct asm_dual_mono);
2099 dual_mono.channel_map.sce_left = sce_left;
2100 dual_mono.channel_map.sce_right = sce_right;
2101
2102 rc = apr_send_pkt(ac->apr, (uint32_t *) &dual_mono);
2103 if (rc < 0) {
2104 pr_err("%s:Command opcode[0x%x]paramid[0x%x] failed\n",
2105 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM,
2106 ASM_CONFIGURE_DUAL_MONO);
2107 rc = -EINVAL;
2108 goto fail_cmd;
2109 }
2110 rc = wait_event_timeout(ac->cmd_wait,
2111 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2112 if (!rc) {
2113 pr_err("%s:timeout opcode[0x%x]\n", __func__,
2114 dual_mono.hdr.opcode);
2115 goto fail_cmd;
2116 }
2117 return 0;
2118fail_cmd:
2119 return -EINVAL;
2120}
2121
Amal Paul6e0f7982013-02-21 19:36:35 -08002122int q6asm_cfg_aac_sel_mix_coef(struct audio_client *ac, uint32_t mix_coeff)
2123{
2124 struct asm_aac_stereo_mix_coeff_selection_param aac_mix_coeff;
2125 int rc = 0;
2126 q6asm_add_hdr(ac, &aac_mix_coeff.hdr, sizeof(aac_mix_coeff), TRUE);
2127 aac_mix_coeff.hdr.opcode =
2128 ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2129 aac_mix_coeff.param_id =
2130 ASM_PARAM_ID_AAC_STEREO_MIX_COEFF_SELECTION_FLAG;
2131 aac_mix_coeff.param_size =
2132 sizeof(struct asm_aac_stereo_mix_coeff_selection_param);
2133 aac_mix_coeff.aac_stereo_mix_coeff_flag = mix_coeff;
2134 pr_debug("%s, mix_coeff = %u", __func__, mix_coeff);
2135 rc = apr_send_pkt(ac->apr, (uint32_t *) &aac_mix_coeff);
2136 if (rc < 0) {
2137 pr_err("%s:Command opcode[0x%x]paramid[0x%x] failed\n",
2138 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM,
2139 ASM_PARAM_ID_AAC_STEREO_MIX_COEFF_SELECTION_FLAG);
2140 rc = -EINVAL;
2141 goto fail_cmd;
2142 }
2143 rc = wait_event_timeout(ac->cmd_wait,
2144 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2145 if (!rc) {
2146 pr_err("%s:timeout opcode[0x%x]\n", __func__,
2147 aac_mix_coeff.hdr.opcode);
2148 goto fail_cmd;
2149 }
2150 return 0;
2151fail_cmd:
2152 return -EINVAL;
2153}
2154
Swaminathan Sathappan6f530882012-05-01 16:42:22 -07002155int q6asm_set_encdec_chan_map(struct audio_client *ac,
2156 uint32_t num_channels)
2157{
2158 struct asm_stream_cmd_encdec_channelmap chan_map;
2159 u8 *channel_mapping;
2160
2161 int rc = 0;
2162
2163 pr_debug("%s: Session %d, num_channels = %d\n",
2164 __func__, ac->session, num_channels);
2165
2166 q6asm_add_hdr(ac, &chan_map.hdr, sizeof(chan_map), TRUE);
2167
2168 chan_map.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2169 chan_map.param_id = ASM_ENCDEC_DEC_CHAN_MAP;
2170 chan_map.param_size = sizeof(struct asm_dec_chan_map);
2171 chan_map.chan_map.num_channels = num_channels;
2172
2173 channel_mapping =
2174 chan_map.chan_map.channel_mapping;
2175
2176 memset(channel_mapping, PCM_CHANNEL_NULL, MAX_CHAN_MAP_CHANNELS);
2177 if (num_channels == 1) {
2178 channel_mapping[0] = PCM_CHANNEL_FL;
2179 } else if (num_channels == 2) {
2180 channel_mapping[0] = PCM_CHANNEL_FL;
2181 channel_mapping[1] = PCM_CHANNEL_FR;
Subhash Chandra Bose Naripeddy68d103a2012-08-17 21:03:19 -07002182 } else if (num_channels == 4) {
2183 channel_mapping[0] = PCM_CHANNEL_FL;
2184 channel_mapping[1] = PCM_CHANNEL_FR;
2185 channel_mapping[1] = PCM_CHANNEL_LB;
2186 channel_mapping[1] = PCM_CHANNEL_RB;
Swaminathan Sathappan6f530882012-05-01 16:42:22 -07002187 } else if (num_channels == 6) {
2188 channel_mapping[0] = PCM_CHANNEL_FC;
2189 channel_mapping[1] = PCM_CHANNEL_FL;
2190 channel_mapping[2] = PCM_CHANNEL_FR;
2191 channel_mapping[3] = PCM_CHANNEL_LB;
2192 channel_mapping[4] = PCM_CHANNEL_RB;
2193 channel_mapping[5] = PCM_CHANNEL_LFE;
Subhash Chandra Bose Naripeddy68d103a2012-08-17 21:03:19 -07002194 } else if (num_channels == 8) {
2195 channel_mapping[0] = PCM_CHANNEL_FC;
2196 channel_mapping[1] = PCM_CHANNEL_FL;
2197 channel_mapping[2] = PCM_CHANNEL_FR;
2198 channel_mapping[3] = PCM_CHANNEL_LB;
2199 channel_mapping[4] = PCM_CHANNEL_RB;
2200 channel_mapping[5] = PCM_CHANNEL_LFE;
2201 channel_mapping[6] = PCM_CHANNEL_FLC;
2202 channel_mapping[7] = PCM_CHANNEL_FRC;
Swaminathan Sathappan6f530882012-05-01 16:42:22 -07002203 } else {
2204 pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
2205 num_channels);
2206 rc = -EINVAL;
2207 goto fail_cmd;
2208 }
2209
2210 rc = apr_send_pkt(ac->apr, (uint32_t *) &chan_map);
2211 if (rc < 0) {
2212 pr_err("%s:Command opcode[0x%x]paramid[0x%x] failed\n",
2213 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM,
2214 ASM_ENCDEC_DEC_CHAN_MAP);
2215 goto fail_cmd;
2216 }
2217 rc = wait_event_timeout(ac->cmd_wait,
2218 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2219 if (!rc) {
2220 pr_err("%s:timeout opcode[0x%x]\n", __func__,
2221 chan_map.hdr.opcode);
2222 rc = -ETIMEDOUT;
2223 goto fail_cmd;
2224 }
2225 return 0;
2226fail_cmd:
2227 return rc;
2228}
2229
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002230int q6asm_enc_cfg_blk_qcelp(struct audio_client *ac, uint32_t frames_per_buf,
2231 uint16_t min_rate, uint16_t max_rate,
2232 uint16_t reduced_rate_level, uint16_t rate_modulation_cmd)
2233{
2234 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
2235 int rc = 0;
2236
Harmandeep Singheaf59b42012-06-05 21:46:02 -07002237 pr_debug("%s:session[%d]frames[%d]min_rate[0x%4x]max_rate[0x%4x] reduced_rate_level[0x%4x]rate_modulation_cmd[0x%4x]",
2238 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002239 ac->session, frames_per_buf, min_rate, max_rate,
2240 reduced_rate_level, rate_modulation_cmd);
2241
2242 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
2243
2244 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2245
2246 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
2247 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
2248
2249 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
2250 enc_cfg.enc_blk.format_id = V13K_FS;
2251 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_qcelp13_read_cfg);
2252 enc_cfg.enc_blk.cfg.qcelp13.min_rate = min_rate;
2253 enc_cfg.enc_blk.cfg.qcelp13.max_rate = max_rate;
2254 enc_cfg.enc_blk.cfg.qcelp13.reduced_rate_level = reduced_rate_level;
2255 enc_cfg.enc_blk.cfg.qcelp13.rate_modulation_cmd = rate_modulation_cmd;
2256
2257 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
2258 if (rc < 0) {
2259 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
2260 goto fail_cmd;
2261 }
2262 rc = wait_event_timeout(ac->cmd_wait,
2263 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2264 if (!rc) {
2265 pr_err("timeout. waited for FORMAT_UPDATE\n");
2266 goto fail_cmd;
2267 }
2268 return 0;
2269fail_cmd:
2270 return -EINVAL;
2271}
2272
2273int q6asm_enc_cfg_blk_evrc(struct audio_client *ac, uint32_t frames_per_buf,
2274 uint16_t min_rate, uint16_t max_rate,
2275 uint16_t rate_modulation_cmd)
2276{
2277 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
2278 int rc = 0;
2279
Harmandeep Singheaf59b42012-06-05 21:46:02 -07002280 pr_debug("%s:session[%d]frames[%d]min_rate[0x%4x]max_rate[0x%4x] rate_modulation_cmd[0x%4x]",
2281 __func__, ac->session,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002282 frames_per_buf, min_rate, max_rate, rate_modulation_cmd);
2283
2284 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
2285
2286 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2287
2288 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
2289 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
2290
2291 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
2292 enc_cfg.enc_blk.format_id = EVRC_FS;
2293 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_evrc_read_cfg);
2294 enc_cfg.enc_blk.cfg.evrc.min_rate = min_rate;
2295 enc_cfg.enc_blk.cfg.evrc.max_rate = max_rate;
2296 enc_cfg.enc_blk.cfg.evrc.rate_modulation_cmd = rate_modulation_cmd;
2297 enc_cfg.enc_blk.cfg.evrc.reserved = 0;
2298
2299 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
2300 if (rc < 0) {
2301 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
2302 goto fail_cmd;
2303 }
2304 rc = wait_event_timeout(ac->cmd_wait,
2305 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2306 if (!rc) {
2307 pr_err("timeout. waited for FORMAT_UPDATE\n");
2308 goto fail_cmd;
2309 }
2310 return 0;
2311fail_cmd:
2312 return -EINVAL;
2313}
2314
2315int q6asm_enc_cfg_blk_amrnb(struct audio_client *ac, uint32_t frames_per_buf,
2316 uint16_t band_mode, uint16_t dtx_enable)
2317{
2318 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
2319 int rc = 0;
2320
2321 pr_debug("%s:session[%d]frames[%d]band_mode[0x%4x]dtx_enable[0x%4x]",
2322 __func__, ac->session, frames_per_buf, band_mode, dtx_enable);
2323
2324 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
2325
2326 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2327
2328 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
2329 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
2330
2331 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
2332 enc_cfg.enc_blk.format_id = AMRNB_FS;
2333 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_amrnb_read_cfg);
2334 enc_cfg.enc_blk.cfg.amrnb.mode = band_mode;
2335 enc_cfg.enc_blk.cfg.amrnb.dtx_mode = dtx_enable;
2336
2337 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
2338 if (rc < 0) {
2339 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
2340 goto fail_cmd;
2341 }
2342 rc = wait_event_timeout(ac->cmd_wait,
2343 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2344 if (!rc) {
2345 pr_err("timeout. waited for FORMAT_UPDATE\n");
2346 goto fail_cmd;
2347 }
2348 return 0;
2349fail_cmd:
2350 return -EINVAL;
2351}
2352
Alex Wong2caeecc2011-10-28 10:52:15 +05302353int q6asm_enc_cfg_blk_amrwb(struct audio_client *ac, uint32_t frames_per_buf,
2354 uint16_t band_mode, uint16_t dtx_enable)
2355{
2356 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
2357 int rc = 0;
2358
2359 pr_debug("%s:session[%d]frames[%d]band_mode[0x%4x]dtx_enable[0x%4x]",
2360 __func__, ac->session, frames_per_buf, band_mode, dtx_enable);
2361
2362 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
2363
2364 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2365
2366 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
2367 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
2368
2369 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
2370 enc_cfg.enc_blk.format_id = AMRWB_FS;
2371 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_amrwb_read_cfg);
2372 enc_cfg.enc_blk.cfg.amrwb.mode = band_mode;
2373 enc_cfg.enc_blk.cfg.amrwb.dtx_mode = dtx_enable;
2374
2375 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
2376 if (rc < 0) {
2377 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
2378 goto fail_cmd;
2379 }
2380 rc = wait_event_timeout(ac->cmd_wait,
2381 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2382 if (!rc) {
2383 pr_err("timeout. waited for FORMAT_UPDATE\n");
2384 goto fail_cmd;
2385 }
2386 return 0;
2387fail_cmd:
2388 return -EINVAL;
2389}
2390
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002391int q6asm_media_format_block_pcm(struct audio_client *ac,
2392 uint32_t rate, uint32_t channels)
2393{
2394 struct asm_stream_media_format_update fmt;
2395 int rc = 0;
2396
2397 pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
2398 channels);
2399
2400 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2401
2402 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2403
2404 fmt.format = LINEAR_PCM;
2405 fmt.cfg_size = sizeof(struct asm_pcm_cfg);
2406 fmt.write_cfg.pcm_cfg.ch_cfg = channels;
2407 fmt.write_cfg.pcm_cfg.bits_per_sample = 16;
2408 fmt.write_cfg.pcm_cfg.sample_rate = rate;
2409 fmt.write_cfg.pcm_cfg.is_signed = 1;
2410 fmt.write_cfg.pcm_cfg.interleaved = 1;
2411
2412 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2413 if (rc < 0) {
2414 pr_err("%s:Comamnd open failed\n", __func__);
2415 goto fail_cmd;
2416 }
2417 rc = wait_event_timeout(ac->cmd_wait,
2418 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2419 if (!rc) {
2420 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2421 goto fail_cmd;
2422 }
2423 return 0;
2424fail_cmd:
2425 return -EINVAL;
2426}
2427
Kiran Kandi5e809b02012-01-31 00:24:33 -08002428int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
2429 uint32_t rate, uint32_t channels)
2430{
2431 struct asm_stream_media_format_update fmt;
2432 u8 *channel_mapping;
2433 int rc = 0;
2434
2435 pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
2436 channels);
2437
2438 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2439
2440 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2441
2442 fmt.format = MULTI_CHANNEL_PCM;
2443 fmt.cfg_size = sizeof(struct asm_multi_channel_pcm_fmt_blk);
2444 fmt.write_cfg.multi_ch_pcm_cfg.num_channels = channels;
2445 fmt.write_cfg.multi_ch_pcm_cfg.bits_per_sample = 16;
2446 fmt.write_cfg.multi_ch_pcm_cfg.sample_rate = rate;
2447 fmt.write_cfg.multi_ch_pcm_cfg.is_signed = 1;
2448 fmt.write_cfg.multi_ch_pcm_cfg.is_interleaved = 1;
2449 channel_mapping =
2450 fmt.write_cfg.multi_ch_pcm_cfg.channel_mapping;
2451
2452 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
2453
2454 if (channels == 1) {
2455 channel_mapping[0] = PCM_CHANNEL_FL;
2456 } else if (channels == 2) {
2457 channel_mapping[0] = PCM_CHANNEL_FL;
2458 channel_mapping[1] = PCM_CHANNEL_FR;
Subhash Chandra Bose Naripeddy68d103a2012-08-17 21:03:19 -07002459 } else if (channels == 4) {
2460 channel_mapping[0] = PCM_CHANNEL_FL;
2461 channel_mapping[1] = PCM_CHANNEL_FR;
2462 channel_mapping[1] = PCM_CHANNEL_LB;
2463 channel_mapping[1] = PCM_CHANNEL_RB;
Kiran Kandi5e809b02012-01-31 00:24:33 -08002464 } else if (channels == 6) {
SathishKumar Mani6074b772012-09-26 13:49:49 -07002465 channel_mapping[0] = PCM_CHANNEL_FL;
2466 channel_mapping[1] = PCM_CHANNEL_FR;
2467 channel_mapping[2] = PCM_CHANNEL_FC;
2468 channel_mapping[3] = PCM_CHANNEL_LFE;
2469 channel_mapping[4] = PCM_CHANNEL_LB;
2470 channel_mapping[5] = PCM_CHANNEL_RB;
Subhash Chandra Bose Naripeddy68d103a2012-08-17 21:03:19 -07002471 } else if (channels == 8) {
2472 channel_mapping[0] = PCM_CHANNEL_FC;
2473 channel_mapping[1] = PCM_CHANNEL_FL;
2474 channel_mapping[2] = PCM_CHANNEL_FR;
2475 channel_mapping[3] = PCM_CHANNEL_LB;
2476 channel_mapping[4] = PCM_CHANNEL_RB;
2477 channel_mapping[5] = PCM_CHANNEL_LFE;
2478 channel_mapping[6] = PCM_CHANNEL_FLC;
2479 channel_mapping[7] = PCM_CHANNEL_FRC;
Kiran Kandi5e809b02012-01-31 00:24:33 -08002480 } else {
2481 pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
2482 channels);
2483 return -EINVAL;
2484 }
2485
2486 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2487 if (rc < 0) {
2488 pr_err("%s:Comamnd open failed\n", __func__);
2489 goto fail_cmd;
2490 }
2491 rc = wait_event_timeout(ac->cmd_wait,
2492 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2493 if (!rc) {
2494 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2495 goto fail_cmd;
2496 }
2497 return 0;
2498fail_cmd:
2499 return -EINVAL;
2500}
2501
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002502int q6asm_media_format_block_aac(struct audio_client *ac,
2503 struct asm_aac_cfg *cfg)
2504{
2505 struct asm_stream_media_format_update fmt;
2506 int rc = 0;
2507
2508 pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session,
2509 cfg->sample_rate, cfg->ch_cfg);
2510
2511 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2512
2513 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2514
2515 fmt.format = MPEG4_AAC;
2516 fmt.cfg_size = sizeof(struct asm_aac_cfg);
2517 fmt.write_cfg.aac_cfg.format = cfg->format;
2518 fmt.write_cfg.aac_cfg.aot = cfg->aot;
2519 fmt.write_cfg.aac_cfg.ep_config = cfg->ep_config;
2520 fmt.write_cfg.aac_cfg.section_data_resilience =
2521 cfg->section_data_resilience;
2522 fmt.write_cfg.aac_cfg.scalefactor_data_resilience =
2523 cfg->scalefactor_data_resilience;
2524 fmt.write_cfg.aac_cfg.spectral_data_resilience =
2525 cfg->spectral_data_resilience;
2526 fmt.write_cfg.aac_cfg.ch_cfg = cfg->ch_cfg;
2527 fmt.write_cfg.aac_cfg.sample_rate = cfg->sample_rate;
2528 pr_info("%s:format=%x cfg_size=%d aac-cfg=%x aot=%d ch=%d sr=%d\n",
2529 __func__, fmt.format, fmt.cfg_size,
2530 fmt.write_cfg.aac_cfg.format,
2531 fmt.write_cfg.aac_cfg.aot,
2532 fmt.write_cfg.aac_cfg.ch_cfg,
2533 fmt.write_cfg.aac_cfg.sample_rate);
2534 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2535 if (rc < 0) {
2536 pr_err("%s:Comamnd open failed\n", __func__);
2537 goto fail_cmd;
2538 }
2539 rc = wait_event_timeout(ac->cmd_wait,
2540 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2541 if (!rc) {
2542 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2543 goto fail_cmd;
2544 }
2545 return 0;
2546fail_cmd:
2547 return -EINVAL;
2548}
2549
Ajit Khare43fd8832012-08-07 13:19:44 -07002550int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
2551 struct asm_amrwbplus_cfg *cfg)
2552{
2553 struct asm_stream_media_format_update fmt;
2554 int rc = 0;
2555 pr_debug("q6asm_media_format_block_amrwbplus");
Bharath Ramachandramurthy4f71d502011-10-23 19:45:22 -07002556
Ajit Khare43fd8832012-08-07 13:19:44 -07002557 pr_debug("%s:session[%d]band-mode[%d]frame-fmt[%d]ch[%d]\n",
2558 __func__,
2559 ac->session,
2560 cfg->amr_band_mode,
2561 cfg->amr_frame_fmt,
2562 cfg->num_channels);
2563
2564 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2565
2566 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2567
2568 fmt.format = AMR_WB_PLUS;
2569 fmt.cfg_size = cfg->size_bytes;
2570
2571 fmt.write_cfg.amrwbplus_cfg.size_bytes = cfg->size_bytes;
2572 fmt.write_cfg.amrwbplus_cfg.version = cfg->version;
2573 fmt.write_cfg.amrwbplus_cfg.num_channels = cfg->num_channels;
2574 fmt.write_cfg.amrwbplus_cfg.amr_band_mode = cfg->amr_band_mode;
2575 fmt.write_cfg.amrwbplus_cfg.amr_dtx_mode = cfg->amr_dtx_mode;
2576 fmt.write_cfg.amrwbplus_cfg.amr_frame_fmt = cfg->amr_frame_fmt;
2577 fmt.write_cfg.amrwbplus_cfg.amr_lsf_idx = cfg->amr_lsf_idx;
2578
2579 pr_debug("%s: num_channels=%x amr_band_mode=%d amr_frame_fmt=%d\n",
2580 __func__,
2581 cfg->num_channels,
2582 cfg->amr_band_mode,
2583 cfg->amr_frame_fmt);
2584
2585 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2586 if (rc < 0) {
2587 pr_err("%s:Comamnd media format update failed..\n", __func__);
2588 goto fail_cmd;
2589 }
2590 rc = wait_event_timeout(ac->cmd_wait,
2591 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2592 if (!rc) {
2593 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2594 goto fail_cmd;
2595 }
2596 return 0;
2597fail_cmd:
2598 return -EINVAL;
2599}
Bharath Ramachandramurthy4f71d502011-10-23 19:45:22 -07002600int q6asm_media_format_block_multi_aac(struct audio_client *ac,
2601 struct asm_aac_cfg *cfg)
2602{
2603 struct asm_stream_media_format_update fmt;
2604 int rc = 0;
2605
2606 pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session,
2607 cfg->sample_rate, cfg->ch_cfg);
2608
2609 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2610
2611 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2612
2613 fmt.format = MPEG4_MULTI_AAC;
2614 fmt.cfg_size = sizeof(struct asm_aac_cfg);
2615 fmt.write_cfg.aac_cfg.format = cfg->format;
2616 fmt.write_cfg.aac_cfg.aot = cfg->aot;
2617 fmt.write_cfg.aac_cfg.ep_config = cfg->ep_config;
2618 fmt.write_cfg.aac_cfg.section_data_resilience =
2619 cfg->section_data_resilience;
2620 fmt.write_cfg.aac_cfg.scalefactor_data_resilience =
2621 cfg->scalefactor_data_resilience;
2622 fmt.write_cfg.aac_cfg.spectral_data_resilience =
2623 cfg->spectral_data_resilience;
2624 fmt.write_cfg.aac_cfg.ch_cfg = cfg->ch_cfg;
2625 fmt.write_cfg.aac_cfg.sample_rate = cfg->sample_rate;
2626 pr_info("%s:format=%x cfg_size=%d aac-cfg=%x aot=%d ch=%d sr=%d\n",
2627 __func__, fmt.format, fmt.cfg_size,
2628 fmt.write_cfg.aac_cfg.format,
2629 fmt.write_cfg.aac_cfg.aot,
2630 fmt.write_cfg.aac_cfg.ch_cfg,
2631 fmt.write_cfg.aac_cfg.sample_rate);
2632 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2633 if (rc < 0) {
2634 pr_err("%s:Comamnd open failed\n", __func__);
2635 goto fail_cmd;
2636 }
2637 rc = wait_event_timeout(ac->cmd_wait,
2638 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2639 if (!rc) {
2640 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2641 goto fail_cmd;
2642 }
2643 return 0;
2644fail_cmd:
2645 return -EINVAL;
2646}
2647
2648
Alex Wong2caeecc2011-10-28 10:52:15 +05302649
2650int q6asm_media_format_block(struct audio_client *ac, uint32_t format)
2651{
2652
2653 struct asm_stream_media_format_update fmt;
2654 int rc = 0;
2655
2656 pr_debug("%s:session[%d] format[0x%x]\n", __func__,
2657 ac->session, format);
2658
2659 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2660 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
Asish Bhattacharya305d1752011-11-01 20:38:26 +05302661 switch (format) {
2662 case FORMAT_V13K:
2663 fmt.format = V13K_FS;
2664 break;
2665 case FORMAT_EVRC:
2666 fmt.format = EVRC_FS;
2667 break;
2668 case FORMAT_AMRWB:
2669 fmt.format = AMRWB_FS;
2670 break;
Ajit Khare43fd8832012-08-07 13:19:44 -07002671 case FORMAT_AMR_WB_PLUS:
2672 fmt.format = AMR_WB_PLUS;
2673 break;
Asish Bhattacharya305d1752011-11-01 20:38:26 +05302674 case FORMAT_AMRNB:
2675 fmt.format = AMRNB_FS;
2676 break;
2677 case FORMAT_MP3:
2678 fmt.format = MP3;
2679 break;
Srikanth Uyyala66f781a2012-06-13 23:23:25 +05302680 case FORMAT_DTS:
2681 fmt.format = DTS;
2682 break;
2683 case FORMAT_DTS_LBR:
2684 fmt.format = DTS_LBR;
2685 break;
Asish Bhattacharya305d1752011-11-01 20:38:26 +05302686 default:
2687 pr_err("Invalid format[%d]\n", format);
2688 goto fail_cmd;
2689 }
Alex Wong2caeecc2011-10-28 10:52:15 +05302690 fmt.cfg_size = 0;
2691
2692 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2693 if (rc < 0) {
2694 pr_err("%s:Comamnd open failed\n", __func__);
2695 goto fail_cmd;
2696 }
2697 rc = wait_event_timeout(ac->cmd_wait,
2698 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2699 if (!rc) {
2700 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2701 goto fail_cmd;
2702 }
2703 return 0;
2704fail_cmd:
2705 return -EINVAL;
2706}
2707
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002708int q6asm_media_format_block_wma(struct audio_client *ac,
2709 void *cfg)
2710{
2711 struct asm_stream_media_format_update fmt;
2712 struct asm_wma_cfg *wma_cfg = (struct asm_wma_cfg *)cfg;
2713 int rc = 0;
2714
Harmandeep Singheaf59b42012-06-05 21:46:02 -07002715 pr_debug("session[%d]format_tag[0x%4x] rate[%d] ch[0x%4x] bps[%d], balign[0x%4x], bit_sample[0x%4x], ch_msk[%d], enc_opt[0x%4x]\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002716 ac->session, wma_cfg->format_tag, wma_cfg->sample_rate,
2717 wma_cfg->ch_cfg, wma_cfg->avg_bytes_per_sec,
2718 wma_cfg->block_align, wma_cfg->valid_bits_per_sample,
2719 wma_cfg->ch_mask, wma_cfg->encode_opt);
2720
2721 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2722
2723 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2724
2725 fmt.format = WMA_V9;
2726 fmt.cfg_size = sizeof(struct asm_wma_cfg);
2727 fmt.write_cfg.wma_cfg.format_tag = wma_cfg->format_tag;
2728 fmt.write_cfg.wma_cfg.ch_cfg = wma_cfg->ch_cfg;
2729 fmt.write_cfg.wma_cfg.sample_rate = wma_cfg->sample_rate;
2730 fmt.write_cfg.wma_cfg.avg_bytes_per_sec = wma_cfg->avg_bytes_per_sec;
2731 fmt.write_cfg.wma_cfg.block_align = wma_cfg->block_align;
2732 fmt.write_cfg.wma_cfg.valid_bits_per_sample =
2733 wma_cfg->valid_bits_per_sample;
2734 fmt.write_cfg.wma_cfg.ch_mask = wma_cfg->ch_mask;
2735 fmt.write_cfg.wma_cfg.encode_opt = wma_cfg->encode_opt;
2736 fmt.write_cfg.wma_cfg.adv_encode_opt = 0;
2737 fmt.write_cfg.wma_cfg.adv_encode_opt2 = 0;
2738 fmt.write_cfg.wma_cfg.drc_peak_ref = 0;
2739 fmt.write_cfg.wma_cfg.drc_peak_target = 0;
2740 fmt.write_cfg.wma_cfg.drc_ave_ref = 0;
2741 fmt.write_cfg.wma_cfg.drc_ave_target = 0;
2742
2743 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2744 if (rc < 0) {
2745 pr_err("%s:Comamnd open failed\n", __func__);
2746 goto fail_cmd;
2747 }
2748 rc = wait_event_timeout(ac->cmd_wait,
2749 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2750 if (!rc) {
2751 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2752 goto fail_cmd;
2753 }
2754 return 0;
2755fail_cmd:
2756 return -EINVAL;
2757}
2758
2759int q6asm_media_format_block_wmapro(struct audio_client *ac,
2760 void *cfg)
2761{
2762 struct asm_stream_media_format_update fmt;
2763 struct asm_wmapro_cfg *wmapro_cfg = (struct asm_wmapro_cfg *)cfg;
2764 int rc = 0;
2765
Harmandeep Singheaf59b42012-06-05 21:46:02 -07002766 pr_debug("session[%d]format_tag[0x%4x] rate[%d] ch[0x%4x] bps[%d], balign[0x%4x], bit_sample[0x%4x], ch_msk[%d], enc_opt[0x%4x], adv_enc_opt[0x%4x], adv_enc_opt2[0x%8x]\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002767 ac->session, wmapro_cfg->format_tag, wmapro_cfg->sample_rate,
2768 wmapro_cfg->ch_cfg, wmapro_cfg->avg_bytes_per_sec,
2769 wmapro_cfg->block_align, wmapro_cfg->valid_bits_per_sample,
2770 wmapro_cfg->ch_mask, wmapro_cfg->encode_opt,
2771 wmapro_cfg->adv_encode_opt, wmapro_cfg->adv_encode_opt2);
2772
2773 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2774
2775 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2776
2777 fmt.format = WMA_V10PRO;
2778 fmt.cfg_size = sizeof(struct asm_wmapro_cfg);
2779 fmt.write_cfg.wmapro_cfg.format_tag = wmapro_cfg->format_tag;
2780 fmt.write_cfg.wmapro_cfg.ch_cfg = wmapro_cfg->ch_cfg;
2781 fmt.write_cfg.wmapro_cfg.sample_rate = wmapro_cfg->sample_rate;
2782 fmt.write_cfg.wmapro_cfg.avg_bytes_per_sec =
2783 wmapro_cfg->avg_bytes_per_sec;
2784 fmt.write_cfg.wmapro_cfg.block_align = wmapro_cfg->block_align;
2785 fmt.write_cfg.wmapro_cfg.valid_bits_per_sample =
2786 wmapro_cfg->valid_bits_per_sample;
2787 fmt.write_cfg.wmapro_cfg.ch_mask = wmapro_cfg->ch_mask;
2788 fmt.write_cfg.wmapro_cfg.encode_opt = wmapro_cfg->encode_opt;
2789 fmt.write_cfg.wmapro_cfg.adv_encode_opt = wmapro_cfg->adv_encode_opt;
2790 fmt.write_cfg.wmapro_cfg.adv_encode_opt2 = wmapro_cfg->adv_encode_opt2;
2791 fmt.write_cfg.wmapro_cfg.drc_peak_ref = 0;
2792 fmt.write_cfg.wmapro_cfg.drc_peak_target = 0;
2793 fmt.write_cfg.wmapro_cfg.drc_ave_ref = 0;
2794 fmt.write_cfg.wmapro_cfg.drc_ave_target = 0;
2795
2796 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2797 if (rc < 0) {
2798 pr_err("%s:Comamnd open failed\n", __func__);
2799 goto fail_cmd;
2800 }
2801 rc = wait_event_timeout(ac->cmd_wait,
2802 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2803 if (!rc) {
2804 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2805 goto fail_cmd;
2806 }
2807 return 0;
2808fail_cmd:
2809 return -EINVAL;
2810}
2811
2812int q6asm_memory_map(struct audio_client *ac, uint32_t buf_add, int dir,
2813 uint32_t bufsz, uint32_t bufcnt)
2814{
2815 struct asm_stream_cmd_memory_map mem_map;
2816 int rc = 0;
2817
2818 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
2819 pr_err("APR handle NULL\n");
2820 return -EINVAL;
2821 }
2822
2823 pr_debug("%s: Session[%d]\n", __func__, ac->session);
2824
2825 mem_map.hdr.opcode = ASM_SESSION_CMD_MEMORY_MAP;
2826
2827 mem_map.buf_add = buf_add;
2828 mem_map.buf_size = bufsz * bufcnt;
2829 mem_map.mempool_id = 0; /* EBI */
2830 mem_map.reserved = 0;
2831
Deepa Madiregama636f80e2013-01-17 14:01:25 +05302832 pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
2833 mem_map.hdr.token = (uint32_t)ac;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002834 q6asm_add_mmaphdr(&mem_map.hdr,
2835 sizeof(struct asm_stream_cmd_memory_map), TRUE);
2836
2837 pr_debug("buf add[%x] buf_add_parameter[%x]\n",
2838 mem_map.buf_add, buf_add);
2839
2840 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_map);
2841 if (rc < 0) {
2842 pr_err("mem_map op[0x%x]rc[%d]\n",
2843 mem_map.hdr.opcode, rc);
2844 rc = -EINVAL;
2845 goto fail_cmd;
2846 }
2847
Deepa Madiregama636f80e2013-01-17 14:01:25 +05302848 rc = wait_event_timeout(ac->cmd_wait,
2849 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002850 if (!rc) {
2851 pr_err("timeout. waited for memory_map\n");
2852 rc = -EINVAL;
2853 goto fail_cmd;
2854 }
Deepa Madiregama636f80e2013-01-17 14:01:25 +05302855 if (atomic_read(&ac->cmd_response)) {
2856 pr_err("%s: ASM_SESSION_CMD_MEMORY_MAP cmd failed\n", __func__);
2857 rc = -EINVAL;
2858 goto fail_cmd;
2859 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002860 rc = 0;
Deepa Madiregama636f80e2013-01-17 14:01:25 +05302861
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002862fail_cmd:
2863 return rc;
2864}
2865
2866int q6asm_memory_unmap(struct audio_client *ac, uint32_t buf_add, int dir)
2867{
2868 struct asm_stream_cmd_memory_unmap mem_unmap;
2869 int rc = 0;
2870
2871 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
2872 pr_err("APR handle NULL\n");
2873 return -EINVAL;
2874 }
2875 pr_debug("%s: Session[%d]\n", __func__, ac->session);
2876
Deepa Madiregama636f80e2013-01-17 14:01:25 +05302877 pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
2878 mem_unmap.hdr.token = (uint32_t)ac;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002879 q6asm_add_mmaphdr(&mem_unmap.hdr,
2880 sizeof(struct asm_stream_cmd_memory_unmap), TRUE);
2881 mem_unmap.hdr.opcode = ASM_SESSION_CMD_MEMORY_UNMAP;
2882 mem_unmap.buf_add = buf_add;
2883
2884 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_unmap);
2885 if (rc < 0) {
2886 pr_err("mem_unmap op[0x%x]rc[%d]\n",
2887 mem_unmap.hdr.opcode, rc);
2888 rc = -EINVAL;
2889 goto fail_cmd;
2890 }
2891
Deepa Madiregama636f80e2013-01-17 14:01:25 +05302892 rc = wait_event_timeout(ac->cmd_wait,
2893 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002894 if (!rc) {
Deepa Madiregama636f80e2013-01-17 14:01:25 +05302895 pr_err("timeout. waited for memory_unmap\n");
2896 rc = -EINVAL;
2897 goto fail_cmd;
2898 }
2899 if (atomic_read(&ac->cmd_response)) {
2900 pr_err("%s: ASM_SESSION_CMD_MEMORY_UNMAP cmd failed\n",
2901 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002902 rc = -EINVAL;
2903 goto fail_cmd;
2904 }
2905 rc = 0;
Deepa Madiregama636f80e2013-01-17 14:01:25 +05302906
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002907fail_cmd:
2908 return rc;
2909}
2910
2911int q6asm_set_lrgain(struct audio_client *ac, int left_gain, int right_gain)
2912{
2913 void *vol_cmd = NULL;
2914 void *payload = NULL;
2915 struct asm_pp_params_command *cmd = NULL;
2916 struct asm_lrchannel_gain_params *lrgain = NULL;
2917 int sz = 0;
2918 int rc = 0;
2919
2920 sz = sizeof(struct asm_pp_params_command) +
2921 + sizeof(struct asm_lrchannel_gain_params);
2922 vol_cmd = kzalloc(sz, GFP_KERNEL);
2923 if (vol_cmd == NULL) {
2924 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
2925 rc = -EINVAL;
2926 return rc;
2927 }
2928 cmd = (struct asm_pp_params_command *)vol_cmd;
2929 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
2930 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
2931 cmd->payload = NULL;
2932 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
2933 sizeof(struct asm_lrchannel_gain_params);
2934 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
2935 cmd->params.param_id = L_R_CHANNEL_GAIN_PARAM_ID;
2936 cmd->params.param_size = sizeof(struct asm_lrchannel_gain_params);
2937 cmd->params.reserved = 0;
2938
2939 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
2940 lrgain = (struct asm_lrchannel_gain_params *)payload;
2941
2942 lrgain->left_gain = left_gain;
2943 lrgain->right_gain = right_gain;
2944 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
2945 if (rc < 0) {
2946 pr_err("%s: Volume Command failed\n", __func__);
2947 rc = -EINVAL;
2948 goto fail_cmd;
2949 }
2950
2951 rc = wait_event_timeout(ac->cmd_wait,
2952 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2953 if (!rc) {
2954 pr_err("%s: timeout in sending volume command to apr\n",
2955 __func__);
2956 rc = -EINVAL;
2957 goto fail_cmd;
2958 }
2959 rc = 0;
2960fail_cmd:
2961 kfree(vol_cmd);
2962 return rc;
2963}
2964
2965static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
2966 uint32_t bufsz, uint32_t bufcnt)
2967{
2968 struct asm_stream_cmd_memory_map_regions *mmap_regions = NULL;
2969 struct asm_memory_map_regions *mregions = NULL;
2970 struct audio_port_data *port = NULL;
2971 struct audio_buffer *ab = NULL;
2972 void *mmap_region_cmd = NULL;
2973 void *payload = NULL;
2974 int rc = 0;
2975 int i = 0;
2976 int cmd_size = 0;
2977
2978 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
2979 pr_err("APR handle NULL\n");
2980 return -EINVAL;
2981 }
2982 pr_debug("%s: Session[%d]\n", __func__, ac->session);
2983
2984 cmd_size = sizeof(struct asm_stream_cmd_memory_map_regions)
2985 + sizeof(struct asm_memory_map_regions) * bufcnt;
2986
2987 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
Vasudeva Rao Thumati86edf6c2011-07-06 16:25:13 +05302988 if (mmap_region_cmd == NULL) {
2989 pr_err("%s: Mem alloc failed\n", __func__);
2990 rc = -EINVAL;
2991 return rc;
2992 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002993 mmap_regions = (struct asm_stream_cmd_memory_map_regions *)
2994 mmap_region_cmd;
Deepa Madiregama636f80e2013-01-17 14:01:25 +05302995 mmap_regions->hdr.token = (uint32_t)ac;
2996 pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002997 q6asm_add_mmaphdr(&mmap_regions->hdr, cmd_size, TRUE);
2998 mmap_regions->hdr.opcode = ASM_SESSION_CMD_MEMORY_MAP_REGIONS;
2999 mmap_regions->mempool_id = 0;
3000 mmap_regions->nregions = bufcnt & 0x00ff;
3001 pr_debug("map_regions->nregions = %d\n", mmap_regions->nregions);
3002 payload = ((u8 *) mmap_region_cmd +
3003 sizeof(struct asm_stream_cmd_memory_map_regions));
3004 mregions = (struct asm_memory_map_regions *)payload;
3005
3006 port = &ac->port[dir];
3007 for (i = 0; i < bufcnt; i++) {
3008 ab = &port->buf[i];
3009 mregions->phys = ab->phys;
3010 mregions->buf_size = ab->size;
3011 ++mregions;
3012 }
3013
3014 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) mmap_region_cmd);
3015 if (rc < 0) {
3016 pr_err("mmap_regions op[0x%x]rc[%d]\n",
3017 mmap_regions->hdr.opcode, rc);
3018 rc = -EINVAL;
3019 goto fail_cmd;
3020 }
3021
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303022 rc = wait_event_timeout(ac->cmd_wait,
3023 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003024 if (!rc) {
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303025 pr_err("timeout. waited for map_regions\n");
3026 rc = -EINVAL;
3027 goto fail_cmd;
3028 }
3029 if (atomic_read(&ac->cmd_response)) {
3030 pr_err("%s: ASM_SESSION_CMD_MEMORY_MAP_REGIONS cmd failed\n",
3031 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003032 rc = -EINVAL;
3033 goto fail_cmd;
3034 }
3035 rc = 0;
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303036
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003037fail_cmd:
3038 kfree(mmap_region_cmd);
3039 return rc;
3040}
3041
3042static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir,
3043 uint32_t bufsz, uint32_t bufcnt)
3044{
3045 struct asm_stream_cmd_memory_unmap_regions *unmap_regions = NULL;
3046 struct asm_memory_unmap_regions *mregions = NULL;
3047 struct audio_port_data *port = NULL;
3048 struct audio_buffer *ab = NULL;
3049 void *unmap_region_cmd = NULL;
3050 void *payload = NULL;
3051 int rc = 0;
3052 int i = 0;
3053 int cmd_size = 0;
3054
3055 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
3056 pr_err("APR handle NULL\n");
3057 return -EINVAL;
3058 }
3059 pr_debug("%s: Session[%d]\n", __func__, ac->session);
3060
3061 cmd_size = sizeof(struct asm_stream_cmd_memory_unmap_regions) +
3062 sizeof(struct asm_memory_unmap_regions) * bufcnt;
3063
3064 unmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
Vasudeva Rao Thumati86edf6c2011-07-06 16:25:13 +05303065 if (unmap_region_cmd == NULL) {
3066 pr_err("%s: Mem alloc failed\n", __func__);
3067 rc = -EINVAL;
3068 return rc;
3069 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003070 unmap_regions = (struct asm_stream_cmd_memory_unmap_regions *)
3071 unmap_region_cmd;
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303072 unmap_regions->hdr.token = (uint32_t)ac;
3073 pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003074 q6asm_add_mmaphdr(&unmap_regions->hdr, cmd_size, TRUE);
3075 unmap_regions->hdr.opcode = ASM_SESSION_CMD_MEMORY_UNMAP_REGIONS;
3076 unmap_regions->nregions = bufcnt & 0x00ff;
3077 pr_debug("unmap_regions->nregions = %d\n", unmap_regions->nregions);
3078 payload = ((u8 *) unmap_region_cmd +
3079 sizeof(struct asm_stream_cmd_memory_unmap_regions));
3080 mregions = (struct asm_memory_unmap_regions *)payload;
3081 port = &ac->port[dir];
3082 for (i = 0; i < bufcnt; i++) {
3083 ab = &port->buf[i];
3084 mregions->phys = ab->phys;
3085 ++mregions;
3086 }
3087
3088 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) unmap_region_cmd);
3089 if (rc < 0) {
3090 pr_err("mmap_regions op[0x%x]rc[%d]\n",
3091 unmap_regions->hdr.opcode, rc);
3092 goto fail_cmd;
3093 }
3094
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303095 rc = wait_event_timeout(ac->cmd_wait,
3096 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003097 if (!rc) {
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303098 pr_err("timeout. waited for unmap_regions\n");
3099 rc = -EINVAL;
3100 goto fail_cmd;
3101 }
3102 if (atomic_read(&ac->cmd_response)) {
3103 pr_err("%s: ASM_SESSION_CMD_MEMORY_UNMAP_REGIONS cmd failed\n",
3104 __func__);
3105 rc = -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003106 goto fail_cmd;
3107 }
3108 rc = 0;
3109
3110fail_cmd:
3111 kfree(unmap_region_cmd);
3112 return rc;
3113}
3114
3115int q6asm_set_mute(struct audio_client *ac, int muteflag)
3116{
3117 void *vol_cmd = NULL;
3118 void *payload = NULL;
3119 struct asm_pp_params_command *cmd = NULL;
3120 struct asm_mute_params *mute = NULL;
3121 int sz = 0;
3122 int rc = 0;
3123
3124 sz = sizeof(struct asm_pp_params_command) +
3125 + sizeof(struct asm_mute_params);
3126 vol_cmd = kzalloc(sz, GFP_KERNEL);
3127 if (vol_cmd == NULL) {
3128 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
3129 rc = -EINVAL;
3130 return rc;
3131 }
3132 cmd = (struct asm_pp_params_command *)vol_cmd;
3133 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
3134 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
3135 cmd->payload = NULL;
3136 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
3137 sizeof(struct asm_mute_params);
3138 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
3139 cmd->params.param_id = MUTE_CONFIG_PARAM_ID;
3140 cmd->params.param_size = sizeof(struct asm_mute_params);
3141 cmd->params.reserved = 0;
3142
3143 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
3144 mute = (struct asm_mute_params *)payload;
3145
3146 mute->muteflag = muteflag;
3147 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
3148 if (rc < 0) {
3149 pr_err("%s: Mute Command failed\n", __func__);
3150 rc = -EINVAL;
3151 goto fail_cmd;
3152 }
3153
3154 rc = wait_event_timeout(ac->cmd_wait,
3155 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
3156 if (!rc) {
3157 pr_err("%s: timeout in sending mute command to apr\n",
3158 __func__);
3159 rc = -EINVAL;
3160 goto fail_cmd;
3161 }
3162 rc = 0;
3163fail_cmd:
3164 kfree(vol_cmd);
3165 return rc;
3166}
3167
3168int q6asm_set_volume(struct audio_client *ac, int volume)
3169{
3170 void *vol_cmd = NULL;
3171 void *payload = NULL;
3172 struct asm_pp_params_command *cmd = NULL;
3173 struct asm_master_gain_params *mgain = NULL;
3174 int sz = 0;
3175 int rc = 0;
3176
3177 sz = sizeof(struct asm_pp_params_command) +
3178 + sizeof(struct asm_master_gain_params);
3179 vol_cmd = kzalloc(sz, GFP_KERNEL);
3180 if (vol_cmd == NULL) {
3181 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
3182 rc = -EINVAL;
3183 return rc;
3184 }
3185 cmd = (struct asm_pp_params_command *)vol_cmd;
3186 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
3187 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
3188 cmd->payload = NULL;
3189 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
3190 sizeof(struct asm_master_gain_params);
3191 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
3192 cmd->params.param_id = MASTER_GAIN_PARAM_ID;
3193 cmd->params.param_size = sizeof(struct asm_master_gain_params);
3194 cmd->params.reserved = 0;
3195
3196 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
3197 mgain = (struct asm_master_gain_params *)payload;
3198
3199 mgain->master_gain = volume;
3200 mgain->padding = 0x00;
3201 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
3202 if (rc < 0) {
3203 pr_err("%s: Volume Command failed\n", __func__);
3204 rc = -EINVAL;
3205 goto fail_cmd;
3206 }
3207
3208 rc = wait_event_timeout(ac->cmd_wait,
3209 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
3210 if (!rc) {
3211 pr_err("%s: timeout in sending volume command to apr\n",
3212 __func__);
3213 rc = -EINVAL;
3214 goto fail_cmd;
3215 }
3216 rc = 0;
3217fail_cmd:
3218 kfree(vol_cmd);
3219 return rc;
3220}
3221
3222int q6asm_set_softpause(struct audio_client *ac,
3223 struct asm_softpause_params *pause_param)
3224{
3225 void *vol_cmd = NULL;
3226 void *payload = NULL;
3227 struct asm_pp_params_command *cmd = NULL;
3228 struct asm_softpause_params *params = NULL;
3229 int sz = 0;
3230 int rc = 0;
3231
3232 sz = sizeof(struct asm_pp_params_command) +
3233 + sizeof(struct asm_softpause_params);
3234 vol_cmd = kzalloc(sz, GFP_KERNEL);
3235 if (vol_cmd == NULL) {
3236 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
3237 rc = -EINVAL;
3238 return rc;
3239 }
3240 cmd = (struct asm_pp_params_command *)vol_cmd;
3241 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
3242 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
3243 cmd->payload = NULL;
3244 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
3245 sizeof(struct asm_softpause_params);
3246 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
3247 cmd->params.param_id = SOFT_PAUSE_PARAM_ID;
3248 cmd->params.param_size = sizeof(struct asm_softpause_params);
3249 cmd->params.reserved = 0;
3250
3251 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
3252 params = (struct asm_softpause_params *)payload;
3253
3254 params->enable = pause_param->enable;
3255 params->period = pause_param->period;
3256 params->step = pause_param->step;
3257 params->rampingcurve = pause_param->rampingcurve;
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003258 pr_debug("%s: soft Pause Command: enable = %d, period = %d, step = %d, curve = %d\n",
3259 __func__, params->enable,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003260 params->period, params->step, params->rampingcurve);
3261 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
3262 if (rc < 0) {
3263 pr_err("%s: Volume Command(soft_pause) failed\n", __func__);
3264 rc = -EINVAL;
3265 goto fail_cmd;
3266 }
3267
3268 rc = wait_event_timeout(ac->cmd_wait,
3269 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
3270 if (!rc) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003271 pr_err("%s: timeout in sending volume command(soft_pause) to apr\n",
3272 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003273 rc = -EINVAL;
3274 goto fail_cmd;
3275 }
3276 rc = 0;
3277fail_cmd:
3278 kfree(vol_cmd);
3279 return rc;
3280}
3281
Swaminathan Sathappanb0021cd2011-08-31 15:20:12 -07003282int q6asm_set_softvolume(struct audio_client *ac,
3283 struct asm_softvolume_params *softvol_param)
3284{
3285 void *vol_cmd = NULL;
3286 void *payload = NULL;
3287 struct asm_pp_params_command *cmd = NULL;
3288 struct asm_softvolume_params *params = NULL;
3289 int sz = 0;
3290 int rc = 0;
3291
3292 sz = sizeof(struct asm_pp_params_command) +
3293 + sizeof(struct asm_softvolume_params);
3294 vol_cmd = kzalloc(sz, GFP_KERNEL);
3295 if (vol_cmd == NULL) {
3296 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
3297 rc = -EINVAL;
3298 return rc;
3299 }
3300 cmd = (struct asm_pp_params_command *)vol_cmd;
3301 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
3302 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
3303 cmd->payload = NULL;
3304 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
3305 sizeof(struct asm_softvolume_params);
3306 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
3307 cmd->params.param_id = SOFT_VOLUME_PARAM_ID;
3308 cmd->params.param_size = sizeof(struct asm_softvolume_params);
3309 cmd->params.reserved = 0;
3310
3311 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
3312 params = (struct asm_softvolume_params *)payload;
3313
3314 params->period = softvol_param->period;
3315 params->step = softvol_param->step;
3316 params->rampingcurve = softvol_param->rampingcurve;
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003317 pr_debug("%s: soft Volume:opcode = %d,payload_sz =%d,module_id =%d, param_id = %d, param_sz = %d\n",
3318 __func__,
Swaminathan Sathappanb0021cd2011-08-31 15:20:12 -07003319 cmd->hdr.opcode, cmd->payload_size,
3320 cmd->params.module_id, cmd->params.param_id,
3321 cmd->params.param_size);
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003322 pr_debug("%s: soft Volume Command: period = %d, step = %d, curve = %d\n",
3323 __func__, params->period,
Swaminathan Sathappanb0021cd2011-08-31 15:20:12 -07003324 params->step, params->rampingcurve);
3325 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
3326 if (rc < 0) {
3327 pr_err("%s: Volume Command(soft_volume) failed\n", __func__);
3328 rc = -EINVAL;
3329 goto fail_cmd;
3330 }
3331
3332 rc = wait_event_timeout(ac->cmd_wait,
3333 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
3334 if (!rc) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003335 pr_err("%s: timeout in sending volume command(soft_volume) to apr\n",
3336 __func__);
Swaminathan Sathappanb0021cd2011-08-31 15:20:12 -07003337 rc = -EINVAL;
3338 goto fail_cmd;
3339 }
3340 rc = 0;
3341fail_cmd:
3342 kfree(vol_cmd);
3343 return rc;
3344}
3345
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003346int q6asm_equalizer(struct audio_client *ac, void *eq)
3347{
3348 void *eq_cmd = NULL;
3349 void *payload = NULL;
3350 struct asm_pp_params_command *cmd = NULL;
3351 struct asm_equalizer_params *equalizer = NULL;
3352 struct msm_audio_eq_stream_config *eq_params = NULL;
3353 int i = 0;
3354 int sz = 0;
3355 int rc = 0;
3356
3357 sz = sizeof(struct asm_pp_params_command) +
3358 + sizeof(struct asm_equalizer_params);
3359 eq_cmd = kzalloc(sz, GFP_KERNEL);
3360 if (eq_cmd == NULL) {
3361 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
3362 rc = -EINVAL;
3363 goto fail_cmd;
3364 }
3365 eq_params = (struct msm_audio_eq_stream_config *) eq;
3366 cmd = (struct asm_pp_params_command *)eq_cmd;
3367 q6asm_add_hdr(ac, &cmd->hdr, sz, TRUE);
3368 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
3369 cmd->payload = NULL;
3370 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
3371 sizeof(struct asm_equalizer_params);
3372 cmd->params.module_id = EQUALIZER_MODULE_ID;
3373 cmd->params.param_id = EQUALIZER_PARAM_ID;
3374 cmd->params.param_size = sizeof(struct asm_equalizer_params);
3375 cmd->params.reserved = 0;
3376 payload = (u8 *)(eq_cmd + sizeof(struct asm_pp_params_command));
3377 equalizer = (struct asm_equalizer_params *)payload;
3378
3379 equalizer->enable = eq_params->enable;
3380 equalizer->num_bands = eq_params->num_bands;
3381 pr_debug("%s: enable:%d numbands:%d\n", __func__, eq_params->enable,
3382 eq_params->num_bands);
3383 for (i = 0; i < eq_params->num_bands; i++) {
3384 equalizer->eq_bands[i].band_idx =
3385 eq_params->eq_bands[i].band_idx;
3386 equalizer->eq_bands[i].filter_type =
3387 eq_params->eq_bands[i].filter_type;
3388 equalizer->eq_bands[i].center_freq_hz =
3389 eq_params->eq_bands[i].center_freq_hz;
3390 equalizer->eq_bands[i].filter_gain =
3391 eq_params->eq_bands[i].filter_gain;
3392 equalizer->eq_bands[i].q_factor =
3393 eq_params->eq_bands[i].q_factor;
3394 pr_debug("%s: filter_type:%u bandnum:%d\n", __func__,
3395 eq_params->eq_bands[i].filter_type, i);
3396 pr_debug("%s: center_freq_hz:%u bandnum:%d\n", __func__,
3397 eq_params->eq_bands[i].center_freq_hz, i);
3398 pr_debug("%s: filter_gain:%d bandnum:%d\n", __func__,
3399 eq_params->eq_bands[i].filter_gain, i);
3400 pr_debug("%s: q_factor:%d bandnum:%d\n", __func__,
3401 eq_params->eq_bands[i].q_factor, i);
3402 }
3403 rc = apr_send_pkt(ac->apr, (uint32_t *) eq_cmd);
3404 if (rc < 0) {
3405 pr_err("%s: Equalizer Command failed\n", __func__);
3406 rc = -EINVAL;
3407 goto fail_cmd;
3408 }
3409
3410 rc = wait_event_timeout(ac->cmd_wait,
3411 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
3412 if (!rc) {
3413 pr_err("%s: timeout in sending equalizer command to apr\n",
3414 __func__);
3415 rc = -EINVAL;
3416 goto fail_cmd;
3417 }
3418 rc = 0;
3419fail_cmd:
3420 kfree(eq_cmd);
3421 return rc;
3422}
3423
3424int q6asm_read(struct audio_client *ac)
3425{
3426 struct asm_stream_cmd_read read;
3427 struct audio_buffer *ab;
3428 int dsp_buf;
3429 struct audio_port_data *port;
3430 int rc;
3431 if (!ac || ac->apr == NULL) {
3432 pr_err("APR handle NULL\n");
3433 return -EINVAL;
3434 }
Patrick Lai55f54c52012-11-17 00:29:07 -08003435 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003436 port = &ac->port[OUT];
3437
3438 q6asm_add_hdr(ac, &read.hdr, sizeof(read), FALSE);
3439
3440 mutex_lock(&port->lock);
3441
3442 dsp_buf = port->dsp_buf;
3443 ab = &port->buf[dsp_buf];
3444
3445 pr_debug("%s:session[%d]dsp-buf[%d][%p]cpu_buf[%d][%p]\n",
3446 __func__,
3447 ac->session,
3448 dsp_buf,
3449 (void *)port->buf[dsp_buf].data,
3450 port->cpu_buf,
3451 (void *)port->buf[port->cpu_buf].phys);
3452
3453 read.hdr.opcode = ASM_DATA_CMD_READ;
3454 read.buf_add = ab->phys;
3455 read.buf_size = ab->size;
3456 read.uid = port->dsp_buf;
3457 read.hdr.token = port->dsp_buf;
3458
3459 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
3460 mutex_unlock(&port->lock);
3461 pr_debug("%s:buf add[0x%x] token[%d] uid[%d]\n", __func__,
3462 read.buf_add,
3463 read.hdr.token,
3464 read.uid);
3465 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
3466 if (rc < 0) {
3467 pr_err("read op[0x%x]rc[%d]\n", read.hdr.opcode, rc);
3468 goto fail_cmd;
3469 }
3470 return 0;
3471 }
3472fail_cmd:
3473 return -EINVAL;
3474}
3475
3476int q6asm_read_nolock(struct audio_client *ac)
3477{
3478 struct asm_stream_cmd_read read;
3479 struct audio_buffer *ab;
3480 int dsp_buf;
3481 struct audio_port_data *port;
3482 int rc;
3483 if (!ac || ac->apr == NULL) {
3484 pr_err("APR handle NULL\n");
3485 return -EINVAL;
3486 }
Patrick Lai55f54c52012-11-17 00:29:07 -08003487 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003488 port = &ac->port[OUT];
3489
3490 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
3491
3492
3493 dsp_buf = port->dsp_buf;
3494 ab = &port->buf[dsp_buf];
3495
3496 pr_debug("%s:session[%d]dsp-buf[%d][%p]cpu_buf[%d][%p]\n",
3497 __func__,
3498 ac->session,
3499 dsp_buf,
3500 (void *)port->buf[dsp_buf].data,
3501 port->cpu_buf,
3502 (void *)port->buf[port->cpu_buf].phys);
3503
3504 read.hdr.opcode = ASM_DATA_CMD_READ;
3505 read.buf_add = ab->phys;
3506 read.buf_size = ab->size;
3507 read.uid = port->dsp_buf;
3508 read.hdr.token = port->dsp_buf;
3509
3510 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
Patrick Lai55f54c52012-11-17 00:29:07 -08003511 pr_info("%s:buf add[0x%x] token[%d] uid[%d]\n", __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003512 read.buf_add,
3513 read.hdr.token,
3514 read.uid);
3515 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
3516 if (rc < 0) {
3517 pr_err("read op[0x%x]rc[%d]\n", read.hdr.opcode, rc);
3518 goto fail_cmd;
3519 }
3520 return 0;
3521 }
3522fail_cmd:
3523 return -EINVAL;
3524}
3525
3526
3527static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
3528 uint32_t pkt_size, uint32_t cmd_flg)
3529{
3530 pr_debug("session=%d pkt size=%d cmd_flg=%d\n", pkt_size, cmd_flg,
3531 ac->session);
3532 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
3533 APR_HDR_LEN(sizeof(struct apr_hdr)),\
3534 APR_PKT_VER);
3535 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
3536 hdr->src_domain = APR_DOMAIN_APPS;
3537 hdr->dest_svc = APR_SVC_ASM;
3538 hdr->dest_domain = APR_DOMAIN_ADSP;
3539 hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01;
3540 hdr->dest_port = ((ac->session << 8) & 0xFF00) | 0x01;
3541 if (cmd_flg) {
3542 hdr->token = ac->session;
3543 atomic_set(&ac->cmd_state, 1);
3544 }
3545 hdr->pkt_size = pkt_size;
3546 return;
3547}
3548
3549int q6asm_async_write(struct audio_client *ac,
3550 struct audio_aio_write_param *param)
3551{
3552 int rc = 0;
3553 struct asm_stream_cmd_write write;
3554
3555 if (!ac || ac->apr == NULL) {
3556 pr_err("%s: APR handle NULL\n", __func__);
3557 return -EINVAL;
3558 }
3559
3560 q6asm_add_hdr_async(ac, &write.hdr, sizeof(write), FALSE);
3561
3562 /* Pass physical address as token for AIO scheme */
3563 write.hdr.token = param->uid;
3564 write.hdr.opcode = ASM_DATA_CMD_WRITE;
3565 write.buf_add = param->paddr;
3566 write.avail_bytes = param->len;
3567 write.uid = param->uid;
3568 write.msw_ts = param->msw_ts;
3569 write.lsw_ts = param->lsw_ts;
3570 /* Use 0xFF00 for disabling timestamps */
3571 if (param->flags == 0xFF00)
3572 write.uflags = (0x00000000 | (param->flags & 0x800000FF));
3573 else
3574 write.uflags = (0x80000000 | param->flags);
3575
3576 pr_debug("%s: session[%d] bufadd[0x%x]len[0x%x]", __func__, ac->session,
3577 write.buf_add, write.avail_bytes);
3578
3579 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
3580 if (rc < 0) {
3581 pr_debug("[%s] write op[0x%x]rc[%d]\n", __func__,
3582 write.hdr.opcode, rc);
3583 goto fail_cmd;
3584 }
3585 return 0;
3586fail_cmd:
3587 return -EINVAL;
3588}
3589
3590int q6asm_async_read(struct audio_client *ac,
3591 struct audio_aio_read_param *param)
3592{
3593 int rc = 0;
3594 struct asm_stream_cmd_read read;
3595
3596 if (!ac || ac->apr == NULL) {
3597 pr_err("%s: APR handle NULL\n", __func__);
3598 return -EINVAL;
3599 }
3600
3601 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
3602
3603 /* Pass physical address as token for AIO scheme */
3604 read.hdr.token = param->paddr;
3605 read.hdr.opcode = ASM_DATA_CMD_READ;
3606 read.buf_add = param->paddr;
3607 read.buf_size = param->len;
3608 read.uid = param->uid;
3609
3610 pr_debug("%s: session[%d] bufadd[0x%x]len[0x%x]", __func__, ac->session,
3611 read.buf_add, read.buf_size);
3612
3613 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
3614 if (rc < 0) {
3615 pr_debug("[%s] read op[0x%x]rc[%d]\n", __func__,
3616 read.hdr.opcode, rc);
3617 goto fail_cmd;
3618 }
3619 return 0;
3620fail_cmd:
3621 return -EINVAL;
3622}
3623
Subhash Chandra Bose Naripeddy694b7d92012-06-20 20:46:13 -07003624int q6asm_async_read_compressed(struct audio_client *ac,
3625 struct audio_aio_read_param *param)
3626{
3627 int rc = 0;
3628 struct asm_stream_cmd_read read;
3629
3630 if (!ac || ac->apr == NULL) {
3631 pr_err("%s: APR handle NULL\n", __func__);
3632 return -EINVAL;
3633 }
3634
3635 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
3636
3637 /* Pass physical address as token for AIO scheme */
3638 read.hdr.token = param->paddr;
3639 read.hdr.opcode = ASM_DATA_CMD_READ_COMPRESSED;
3640 read.buf_add = param->paddr;
3641 read.buf_size = param->len;
3642 read.uid = param->uid;
3643
3644 pr_debug("%s: session[%d] bufadd[0x%x]len[0x%x]", __func__, ac->session,
3645 read.buf_add, read.buf_size);
3646
3647 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
3648 if (rc < 0) {
3649 pr_debug("[%s] read op[0x%x]rc[%d]\n", __func__,
3650 read.hdr.opcode, rc);
3651 goto fail_cmd;
3652 }
3653 return 0;
3654fail_cmd:
3655 return -EINVAL;
3656}
3657
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003658int q6asm_write(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
3659 uint32_t lsw_ts, uint32_t flags)
3660{
3661 int rc = 0;
3662 struct asm_stream_cmd_write write;
3663 struct audio_port_data *port;
3664 struct audio_buffer *ab;
3665 int dsp_buf = 0;
3666
3667 if (!ac || ac->apr == NULL) {
3668 pr_err("APR handle NULL\n");
3669 return -EINVAL;
3670 }
3671 pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
Patrick Lai55f54c52012-11-17 00:29:07 -08003672 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003673 port = &ac->port[IN];
3674
3675 q6asm_add_hdr(ac, &write.hdr, sizeof(write),
3676 FALSE);
3677 mutex_lock(&port->lock);
3678
3679 dsp_buf = port->dsp_buf;
3680 ab = &port->buf[dsp_buf];
3681
3682 write.hdr.token = port->dsp_buf;
3683 write.hdr.opcode = ASM_DATA_CMD_WRITE;
3684 write.buf_add = ab->phys;
3685 write.avail_bytes = len;
3686 write.uid = port->dsp_buf;
3687 write.msw_ts = msw_ts;
3688 write.lsw_ts = lsw_ts;
3689 /* Use 0xFF00 for disabling timestamps */
3690 if (flags == 0xFF00)
3691 write.uflags = (0x00000000 | (flags & 0x800000FF));
3692 else
3693 write.uflags = (0x80000000 | flags);
3694 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
3695
3696 pr_debug("%s:ab->phys[0x%x]bufadd[0x%x]token[0x%x]buf_id[0x%x]"
3697 , __func__,
3698 ab->phys,
3699 write.buf_add,
3700 write.hdr.token,
3701 write.uid);
3702 mutex_unlock(&port->lock);
Rajesha Kini3498c932011-07-19 19:58:27 +05303703#ifdef CONFIG_DEBUG_FS
3704 if (out_enable_flag) {
3705 char zero_pattern[2] = {0x00, 0x00};
3706 /* If First two byte is non zero and last two byte
3707 is zero then it is warm output pattern */
3708 if ((strncmp(((char *)ab->data), zero_pattern, 2)) &&
3709 (!strncmp(((char *)ab->data + 2), zero_pattern, 2))) {
3710 do_gettimeofday(&out_warm_tv);
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003711 pr_debug("WARM:apr_send_pkt at %ld sec %ld microsec\n",
3712 out_warm_tv.tv_sec,\
Rajesha Kini3498c932011-07-19 19:58:27 +05303713 out_warm_tv.tv_usec);
3714 pr_debug("Warm Pattern Matched");
3715 }
3716 /* If First two byte is zero and last two byte is
3717 non zero then it is cont ouput pattern */
3718 else if ((!strncmp(((char *)ab->data), zero_pattern, 2))
3719 && (strncmp(((char *)ab->data + 2), zero_pattern, 2))) {
3720 do_gettimeofday(&out_cont_tv);
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003721 pr_debug("CONT:apr_send_pkt at %ld sec %ld microsec\n",
3722 out_cont_tv.tv_sec,\
Rajesha Kini3498c932011-07-19 19:58:27 +05303723 out_cont_tv.tv_usec);
3724 pr_debug("Cont Pattern Matched");
3725 }
3726 }
3727#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003728 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
3729 if (rc < 0) {
3730 pr_err("write op[0x%x]rc[%d]\n", write.hdr.opcode, rc);
3731 goto fail_cmd;
3732 }
3733 pr_debug("%s: WRITE SUCCESS\n", __func__);
3734 return 0;
3735 }
3736fail_cmd:
3737 return -EINVAL;
3738}
3739
3740int q6asm_write_nolock(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
3741 uint32_t lsw_ts, uint32_t flags)
3742{
3743 int rc = 0;
3744 struct asm_stream_cmd_write write;
3745 struct audio_port_data *port;
3746 struct audio_buffer *ab;
3747 int dsp_buf = 0;
3748
3749 if (!ac || ac->apr == NULL) {
3750 pr_err("APR handle NULL\n");
3751 return -EINVAL;
3752 }
3753 pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
Patrick Lai55f54c52012-11-17 00:29:07 -08003754 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003755 port = &ac->port[IN];
3756
3757 q6asm_add_hdr_async(ac, &write.hdr, sizeof(write),
3758 FALSE);
3759
3760 dsp_buf = port->dsp_buf;
3761 ab = &port->buf[dsp_buf];
3762
3763 write.hdr.token = port->dsp_buf;
3764 write.hdr.opcode = ASM_DATA_CMD_WRITE;
3765 write.buf_add = ab->phys;
3766 write.avail_bytes = len;
3767 write.uid = port->dsp_buf;
3768 write.msw_ts = msw_ts;
3769 write.lsw_ts = lsw_ts;
3770 /* Use 0xFF00 for disabling timestamps */
3771 if (flags == 0xFF00)
3772 write.uflags = (0x00000000 | (flags & 0x800000FF));
3773 else
3774 write.uflags = (0x80000000 | flags);
3775 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
3776
3777 pr_debug("%s:ab->phys[0x%x]bufadd[0x%x]token[0x%x]buf_id[0x%x]"
3778 , __func__,
3779 ab->phys,
3780 write.buf_add,
3781 write.hdr.token,
3782 write.uid);
3783
3784 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
3785 if (rc < 0) {
3786 pr_err("write op[0x%x]rc[%d]\n", write.hdr.opcode, rc);
3787 goto fail_cmd;
3788 }
3789 pr_debug("%s: WRITE SUCCESS\n", __func__);
3790 return 0;
3791 }
3792fail_cmd:
3793 return -EINVAL;
3794}
3795
Patrick Lai3aabeae2013-01-06 00:52:34 -08003796int q6asm_get_session_time(struct audio_client *ac, uint64_t *tstamp)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003797{
3798 struct apr_hdr hdr;
3799 int rc;
3800
Patrick Lai3aabeae2013-01-06 00:52:34 -08003801 if (!ac || ac->apr == NULL || tstamp == NULL) {
3802 pr_err("APR handle or tstamp NULL\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003803 return -EINVAL;
3804 }
Swaminathan Sathappanc7f98992012-07-09 11:07:12 -07003805 q6asm_add_hdr(ac, &hdr, sizeof(hdr), FALSE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003806 hdr.opcode = ASM_SESSION_CMD_GET_SESSION_TIME;
3807 atomic_set(&ac->time_flag, 1);
3808
3809 pr_debug("%s: session[%d]opcode[0x%x]\n", __func__,
3810 ac->session,
3811 hdr.opcode);
3812 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
3813 if (rc < 0) {
3814 pr_err("Commmand 0x%x failed\n", hdr.opcode);
3815 goto fail_cmd;
3816 }
3817 rc = wait_event_timeout(ac->time_wait,
3818 (atomic_read(&ac->time_flag) == 0), 5*HZ);
3819 if (!rc) {
3820 pr_err("%s: timeout in getting session time from DSP\n",
3821 __func__);
3822 goto fail_cmd;
3823 }
Patrick Lai3aabeae2013-01-06 00:52:34 -08003824
3825 *tstamp = ac->time_stamp;
3826 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003827
3828fail_cmd:
3829 return -EINVAL;
3830}
3831
3832int q6asm_cmd(struct audio_client *ac, int cmd)
3833{
3834 struct apr_hdr hdr;
3835 int rc;
3836 atomic_t *state;
3837 int cnt = 0;
3838
3839 if (!ac || ac->apr == NULL) {
3840 pr_err("APR handle NULL\n");
3841 return -EINVAL;
3842 }
3843 q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
3844 switch (cmd) {
3845 case CMD_PAUSE:
3846 pr_debug("%s:CMD_PAUSE\n", __func__);
3847 hdr.opcode = ASM_SESSION_CMD_PAUSE;
3848 state = &ac->cmd_state;
3849 break;
3850 case CMD_FLUSH:
3851 pr_debug("%s:CMD_FLUSH\n", __func__);
3852 hdr.opcode = ASM_STREAM_CMD_FLUSH;
3853 state = &ac->cmd_state;
3854 break;
3855 case CMD_OUT_FLUSH:
3856 pr_debug("%s:CMD_OUT_FLUSH\n", __func__);
3857 hdr.opcode = ASM_STREAM_CMD_FLUSH_READBUFS;
3858 state = &ac->cmd_state;
3859 break;
3860 case CMD_EOS:
3861 pr_debug("%s:CMD_EOS\n", __func__);
3862 hdr.opcode = ASM_DATA_CMD_EOS;
3863 atomic_set(&ac->cmd_state, 0);
3864 state = &ac->cmd_state;
3865 break;
3866 case CMD_CLOSE:
3867 pr_debug("%s:CMD_CLOSE\n", __func__);
3868 hdr.opcode = ASM_STREAM_CMD_CLOSE;
Laxminath Kasamf16d3fd2012-12-19 14:54:14 +05303869 atomic_set(&ac->cmd_close_state, 1);
3870 state = &ac->cmd_close_state;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003871 break;
3872 default:
3873 pr_err("Invalid format[%d]\n", cmd);
3874 goto fail_cmd;
3875 }
3876 pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
3877 ac->session,
3878 hdr.opcode);
3879 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
3880 if (rc < 0) {
3881 pr_err("Commmand 0x%x failed\n", hdr.opcode);
3882 goto fail_cmd;
3883 }
3884 rc = wait_event_timeout(ac->cmd_wait, (atomic_read(state) == 0), 5*HZ);
3885 if (!rc) {
3886 pr_err("timeout. waited for response opcode[0x%x]\n",
3887 hdr.opcode);
3888 goto fail_cmd;
3889 }
3890 if (cmd == CMD_FLUSH)
3891 q6asm_reset_buf_state(ac);
3892 if (cmd == CMD_CLOSE) {
3893 /* check if DSP return all buffers */
3894 if (ac->port[IN].buf) {
3895 for (cnt = 0; cnt < ac->port[IN].max_buf_cnt;
3896 cnt++) {
3897 if (ac->port[IN].buf[cnt].used == IN) {
3898 pr_debug("Write Buf[%d] not returned\n",
3899 cnt);
3900 }
3901 }
3902 }
3903 if (ac->port[OUT].buf) {
3904 for (cnt = 0; cnt < ac->port[OUT].max_buf_cnt; cnt++) {
3905 if (ac->port[OUT].buf[cnt].used == OUT) {
3906 pr_debug("Read Buf[%d] not returned\n",
3907 cnt);
3908 }
3909 }
3910 }
3911 }
3912 return 0;
3913fail_cmd:
3914 return -EINVAL;
3915}
3916
3917int q6asm_cmd_nowait(struct audio_client *ac, int cmd)
3918{
3919 struct apr_hdr hdr;
3920 int rc;
3921
3922 if (!ac || ac->apr == NULL) {
3923 pr_err("%s:APR handle NULL\n", __func__);
3924 return -EINVAL;
3925 }
3926 q6asm_add_hdr_async(ac, &hdr, sizeof(hdr), TRUE);
3927 switch (cmd) {
3928 case CMD_PAUSE:
3929 pr_debug("%s:CMD_PAUSE\n", __func__);
3930 hdr.opcode = ASM_SESSION_CMD_PAUSE;
3931 break;
3932 case CMD_EOS:
3933 pr_debug("%s:CMD_EOS\n", __func__);
3934 hdr.opcode = ASM_DATA_CMD_EOS;
3935 break;
3936 default:
3937 pr_err("%s:Invalid format[%d]\n", __func__, cmd);
3938 goto fail_cmd;
3939 }
3940 pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
3941 ac->session,
3942 hdr.opcode);
Jay Wang0668d1062012-07-11 18:53:21 -07003943
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003944 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
3945 if (rc < 0) {
3946 pr_err("%s:Commmand 0x%x failed\n", __func__, hdr.opcode);
3947 goto fail_cmd;
3948 }
Jay Wang0668d1062012-07-11 18:53:21 -07003949 atomic_inc(&ac->nowait_cmd_cnt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003950 return 0;
3951fail_cmd:
3952 return -EINVAL;
3953}
3954
3955static void q6asm_reset_buf_state(struct audio_client *ac)
3956{
3957 int cnt = 0;
3958 int loopcnt = 0;
Patrick Lai55f54c52012-11-17 00:29:07 -08003959 int used;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003960 struct audio_port_data *port = NULL;
3961
Patrick Lai55f54c52012-11-17 00:29:07 -08003962 if (ac->io_mode & SYNC_IO_MODE) {
3963 used = (ac->io_mode & TUN_WRITE_IO_MODE ? 1 : 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003964 mutex_lock(&ac->cmd_lock);
3965 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
3966 port = &ac->port[loopcnt];
3967 cnt = port->max_buf_cnt - 1;
3968 port->dsp_buf = 0;
3969 port->cpu_buf = 0;
3970 while (cnt >= 0) {
3971 if (!port->buf)
3972 continue;
Patrick Lai55f54c52012-11-17 00:29:07 -08003973 port->buf[cnt].used = used;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003974 cnt--;
3975 }
3976 }
3977 mutex_unlock(&ac->cmd_lock);
3978 }
3979}
3980
3981int q6asm_reg_tx_overflow(struct audio_client *ac, uint16_t enable)
3982{
3983 struct asm_stream_cmd_reg_tx_overflow_event tx_overflow;
3984 int rc;
3985
3986 if (!ac || ac->apr == NULL) {
3987 pr_err("APR handle NULL\n");
3988 return -EINVAL;
3989 }
3990 pr_debug("%s:session[%d]enable[%d]\n", __func__,
3991 ac->session, enable);
3992 q6asm_add_hdr(ac, &tx_overflow.hdr, sizeof(tx_overflow), TRUE);
3993
3994 tx_overflow.hdr.opcode = \
3995 ASM_SESSION_CMD_REGISTER_FOR_TX_OVERFLOW_EVENTS;
3996 /* tx overflow event: enable */
3997 tx_overflow.enable = enable;
3998
3999 rc = apr_send_pkt(ac->apr, (uint32_t *) &tx_overflow);
4000 if (rc < 0) {
4001 pr_err("tx overflow op[0x%x]rc[%d]\n", \
4002 tx_overflow.hdr.opcode, rc);
4003 goto fail_cmd;
4004 }
4005 rc = wait_event_timeout(ac->cmd_wait,
4006 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
4007 if (!rc) {
4008 pr_err("timeout. waited for tx overflow\n");
4009 goto fail_cmd;
4010 }
4011 return 0;
4012fail_cmd:
4013 return -EINVAL;
4014}
4015
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004016int q6asm_get_apr_service_id(int session_id)
4017{
4018 pr_debug("%s\n", __func__);
4019
Shiv Maliyappanahallia84982a2012-01-19 15:25:04 -08004020 if (session_id < 0 || session_id > SESSION_MAX) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004021 pr_err("%s: invalid session_id = %d\n", __func__, session_id);
4022 return -EINVAL;
4023 }
4024
4025 return ((struct apr_svc *)session[session_id]->apr)->id;
4026}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004027
4028
4029static int __init q6asm_init(void)
4030{
4031 pr_debug("%s\n", __func__);
4032 init_waitqueue_head(&this_mmap.cmd_wait);
4033 memset(session, 0, sizeof(session));
Rajesha Kini3498c932011-07-19 19:58:27 +05304034#ifdef CONFIG_DEBUG_FS
4035 out_buffer = kmalloc(OUT_BUFFER_SIZE, GFP_KERNEL);
4036 out_dentry = debugfs_create_file("audio_out_latency_measurement_node",\
Glenn Kasten5dfda802012-10-04 16:40:27 -07004037 0664,\
Rajesha Kini3498c932011-07-19 19:58:27 +05304038 NULL, NULL, &audio_output_latency_debug_fops);
4039 if (IS_ERR(out_dentry))
4040 pr_err("debugfs_create_file failed\n");
4041 in_buffer = kmalloc(IN_BUFFER_SIZE, GFP_KERNEL);
4042 in_dentry = debugfs_create_file("audio_in_latency_measurement_node",\
Glenn Kasten5dfda802012-10-04 16:40:27 -07004043 0664,\
Rajesha Kini3498c932011-07-19 19:58:27 +05304044 NULL, NULL, &audio_input_latency_debug_fops);
4045 if (IS_ERR(in_dentry))
4046 pr_err("debugfs_create_file failed\n");
4047#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004048 return 0;
4049}
4050
4051device_initcall(q6asm_init);