blob: 604d33a8e888bd4bec591e9c2336949475c85c57 [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
Mohammad Johny Shaik79841812014-11-27 11:36:54 +053060#define FRAME_NUM (8)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070061static DEFINE_MUTEX(session_lock);
62
63/* session id: 0 reserved */
64static struct audio_client *session[SESSION_MAX+1];
65static int32_t q6asm_mmapcallback(struct apr_client_data *data, void *priv);
66static int32_t q6asm_callback(struct apr_client_data *data, void *priv);
67static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
68 uint32_t pkt_size, uint32_t cmd_flg);
69static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
70 uint32_t pkt_size, uint32_t cmd_flg);
71static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
72 uint32_t bufsz, uint32_t bufcnt);
73static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir,
74 uint32_t bufsz, uint32_t bufcnt);
75
76static void q6asm_reset_buf_state(struct audio_client *ac);
77
Rajesha Kini3498c932011-07-19 19:58:27 +053078#ifdef CONFIG_DEBUG_FS
79static struct timeval out_cold_tv;
80static struct timeval out_warm_tv;
81static struct timeval out_cont_tv;
82static struct timeval in_cont_tv;
83static long out_enable_flag;
84static long in_enable_flag;
85static struct dentry *out_dentry;
86static struct dentry *in_dentry;
87static int in_cont_index;
88/*This var is used to keep track of first write done for cold output latency */
89static int out_cold_index;
90static char *out_buffer;
91static char *in_buffer;
92static int audio_output_latency_dbgfs_open(struct inode *inode,
93 struct file *file)
94{
95 file->private_data = inode->i_private;
96 return 0;
97}
98static ssize_t audio_output_latency_dbgfs_read(struct file *file,
99 char __user *buf, size_t count, loff_t *ppos)
100{
101 snprintf(out_buffer, OUT_BUFFER_SIZE, "%ld,%ld,%ld,%ld,%ld,%ld,",\
102 out_cold_tv.tv_sec, out_cold_tv.tv_usec, out_warm_tv.tv_sec,\
103 out_warm_tv.tv_usec, out_cont_tv.tv_sec, out_cont_tv.tv_usec);
104 return simple_read_from_buffer(buf, OUT_BUFFER_SIZE, ppos,
105 out_buffer, OUT_BUFFER_SIZE);
106}
107static ssize_t audio_output_latency_dbgfs_write(struct file *file,
108 const char __user *buf, size_t count, loff_t *ppos)
109{
110 char *temp;
111
112 if (count > 2*sizeof(char))
113 return -EINVAL;
114 else
115 temp = kmalloc(2*sizeof(char), GFP_KERNEL);
116
117 out_cold_index = 0;
118
119 if (temp) {
120 if (copy_from_user(temp, buf, 2*sizeof(char))) {
121 kfree(temp);
122 return -EFAULT;
123 }
124 if (!strict_strtol(temp, 10, &out_enable_flag)) {
125 kfree(temp);
126 return count;
127 }
128 kfree(temp);
129 }
130 return -EINVAL;
131}
132static const struct file_operations audio_output_latency_debug_fops = {
133 .open = audio_output_latency_dbgfs_open,
134 .read = audio_output_latency_dbgfs_read,
135 .write = audio_output_latency_dbgfs_write
136};
137
138static int audio_input_latency_dbgfs_open(struct inode *inode,
139 struct file *file)
140{
141 file->private_data = inode->i_private;
142 return 0;
143}
144static ssize_t audio_input_latency_dbgfs_read(struct file *file,
145 char __user *buf, size_t count, loff_t *ppos)
146{
147 snprintf(in_buffer, IN_BUFFER_SIZE, "%ld,%ld,",\
148 in_cont_tv.tv_sec, in_cont_tv.tv_usec);
149 return simple_read_from_buffer(buf, IN_BUFFER_SIZE, ppos,
150 in_buffer, IN_BUFFER_SIZE);
151}
152static ssize_t audio_input_latency_dbgfs_write(struct file *file,
153 const char __user *buf, size_t count, loff_t *ppos)
154{
155 char *temp;
156
157 if (count > 2*sizeof(char))
158 return -EINVAL;
159 else
160 temp = kmalloc(2*sizeof(char), GFP_KERNEL);
161 if (temp) {
162 if (copy_from_user(temp, buf, 2*sizeof(char))) {
163 kfree(temp);
164 return -EFAULT;
165 }
166 if (!strict_strtol(temp, 10, &in_enable_flag)) {
167 kfree(temp);
168 return count;
169 }
170 kfree(temp);
171 }
172 return -EINVAL;
173}
174static const struct file_operations audio_input_latency_debug_fops = {
175 .open = audio_input_latency_dbgfs_open,
176 .read = audio_input_latency_dbgfs_read,
177 .write = audio_input_latency_dbgfs_write
178};
179#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700180struct asm_mmap {
181 atomic_t ref_cnt;
182 atomic_t cmd_state;
183 wait_queue_head_t cmd_wait;
184 void *apr;
185};
186
187static struct asm_mmap this_mmap;
188
189static int q6asm_session_alloc(struct audio_client *ac)
190{
191 int n;
192 mutex_lock(&session_lock);
193 for (n = 1; n <= SESSION_MAX; n++) {
194 if (!session[n]) {
195 session[n] = ac;
196 mutex_unlock(&session_lock);
197 return n;
198 }
199 }
200 mutex_unlock(&session_lock);
201 return -ENOMEM;
202}
203
204static void q6asm_session_free(struct audio_client *ac)
205{
206 pr_debug("%s: sessionid[%d]\n", __func__, ac->session);
Ben Romberger93d4d2d2011-10-19 23:04:02 -0700207 rtac_remove_popp_from_adm_devices(ac->session);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700208 mutex_lock(&session_lock);
209 session[ac->session] = 0;
210 mutex_unlock(&session_lock);
211 ac->session = 0;
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700212 ac->perf_mode = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700213 return;
214}
215
216int q6asm_audio_client_buf_free(unsigned int dir,
217 struct audio_client *ac)
218{
219 struct audio_port_data *port;
220 int cnt = 0;
221 int rc = 0;
222 pr_debug("%s: Session id %d\n", __func__, ac->session);
223 mutex_lock(&ac->cmd_lock);
Patrick Lai55f54c52012-11-17 00:29:07 -0800224 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700225 port = &ac->port[dir];
226 if (!port->buf) {
227 mutex_unlock(&ac->cmd_lock);
228 return 0;
229 }
230 cnt = port->max_buf_cnt - 1;
231
232 if (cnt >= 0) {
233 rc = q6asm_memory_unmap_regions(ac, dir,
234 port->buf[0].size,
235 port->max_buf_cnt);
236 if (rc < 0)
237 pr_err("%s CMD Memory_unmap_regions failed\n",
238 __func__);
239 }
240
241 while (cnt >= 0) {
242 if (port->buf[cnt].data) {
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800243#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
244 ion_unmap_kernel(port->buf[cnt].client,
245 port->buf[cnt].handle);
246 ion_free(port->buf[cnt].client,
247 port->buf[cnt].handle);
248 ion_client_destroy(port->buf[cnt].client);
249#else
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700250 pr_debug("%s:data[%p]phys[%p][%p] cnt[%d] mem_buffer[%p]\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700251 __func__, (void *)port->buf[cnt].data,
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700252 (void *)port->buf[cnt].phys,
253 (void *)&port->buf[cnt].phys, cnt,
254 (void *)port->buf[cnt].mem_buffer);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700255 if (IS_ERR((void *)port->buf[cnt].mem_buffer))
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700256 pr_err("%s:mem buffer invalid, error = %ld\n",
257 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700258 PTR_ERR((void *)port->buf[cnt].mem_buffer));
259 else {
Laura Abbottea3e7b62012-04-30 15:59:21 -0700260 if (iounmap(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700261 port->buf[cnt].mem_buffer) < 0)
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700262 pr_err("%s: unmap buffer failed\n",
263 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700264 }
265 free_contiguous_memory_by_paddr(
266 port->buf[cnt].phys);
267
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800268#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700269 port->buf[cnt].data = NULL;
270 port->buf[cnt].phys = 0;
271 --(port->max_buf_cnt);
272 }
273 --cnt;
274 }
275 kfree(port->buf);
276 port->buf = NULL;
277 }
278 mutex_unlock(&ac->cmd_lock);
279 return 0;
280}
281
282int q6asm_audio_client_buf_free_contiguous(unsigned int dir,
283 struct audio_client *ac)
284{
285 struct audio_port_data *port;
286 int cnt = 0;
287 int rc = 0;
288 pr_debug("%s: Session id %d\n", __func__, ac->session);
289 mutex_lock(&ac->cmd_lock);
290 port = &ac->port[dir];
291 if (!port->buf) {
292 mutex_unlock(&ac->cmd_lock);
293 return 0;
294 }
295 cnt = port->max_buf_cnt - 1;
296
297 if (cnt >= 0) {
Deepa Madiregama7d52a402011-07-13 20:28:36 +0530298 rc = q6asm_memory_unmap(ac, port->buf[0].phys, dir);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700299 if (rc < 0)
300 pr_err("%s CMD Memory_unmap_regions failed\n",
301 __func__);
302 }
303
304 if (port->buf[0].data) {
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800305#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
306 ion_unmap_kernel(port->buf[0].client, port->buf[0].handle);
307 ion_free(port->buf[0].client, port->buf[0].handle);
308 ion_client_destroy(port->buf[0].client);
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700309 pr_debug("%s:data[%p]phys[%p][%p], client[%p] handle[%p]\n",
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800310 __func__,
311 (void *)port->buf[0].data,
312 (void *)port->buf[0].phys,
313 (void *)&port->buf[0].phys,
314 (void *)port->buf[0].client,
315 (void *)port->buf[0].handle);
316#else
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700317 pr_debug("%s:data[%p]phys[%p][%p] mem_buffer[%p]\n",
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700318 __func__,
319 (void *)port->buf[0].data,
320 (void *)port->buf[0].phys,
321 (void *)&port->buf[0].phys,
322 (void *)port->buf[0].mem_buffer);
323 if (IS_ERR((void *)port->buf[0].mem_buffer))
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700324 pr_err("%s:mem buffer invalid, error = %ld\n",
325 __func__,
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700326 PTR_ERR((void *)port->buf[0].mem_buffer));
327 else {
Laura Abbottea3e7b62012-04-30 15:59:21 -0700328 if (iounmap(
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700329 port->buf[0].mem_buffer) < 0)
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700330 pr_err("%s: unmap buffer failed\n", __func__);
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700331 }
332 free_contiguous_memory_by_paddr(port->buf[0].phys);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800333#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700334 }
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700335
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700336 while (cnt >= 0) {
337 port->buf[cnt].data = NULL;
338 port->buf[cnt].phys = 0;
339 cnt--;
340 }
341 port->max_buf_cnt = 0;
342 kfree(port->buf);
343 port->buf = NULL;
344 mutex_unlock(&ac->cmd_lock);
345 return 0;
346}
347
348void q6asm_audio_client_free(struct audio_client *ac)
349{
350 int loopcnt;
351 struct audio_port_data *port;
352 if (!ac || !ac->session)
353 return;
354 pr_debug("%s: Session id %d\n", __func__, ac->session);
Patrick Lai55f54c52012-11-17 00:29:07 -0800355 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700356 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
357 port = &ac->port[loopcnt];
358 if (!port->buf)
359 continue;
360 pr_debug("%s:loopcnt = %d\n", __func__, loopcnt);
361 q6asm_audio_client_buf_free(loopcnt, ac);
362 }
363 }
364
365 apr_deregister(ac->apr);
366 q6asm_session_free(ac);
367
368 pr_debug("%s: APR De-Register\n", __func__);
369 if (atomic_read(&this_mmap.ref_cnt) <= 0) {
370 pr_err("%s: APR Common Port Already Closed\n", __func__);
371 goto done;
372 }
373
374 atomic_dec(&this_mmap.ref_cnt);
375 if (atomic_read(&this_mmap.ref_cnt) == 0) {
376 apr_deregister(this_mmap.apr);
377 pr_debug("%s:APR De-Register common port\n", __func__);
378 }
379done:
380 kfree(ac);
381 return;
382}
383
384int q6asm_set_io_mode(struct audio_client *ac, uint32_t mode)
385{
386 if (ac == NULL) {
387 pr_err("%s APR handle NULL\n", __func__);
388 return -EINVAL;
389 }
Patrick Lai55f54c52012-11-17 00:29:07 -0800390
391 if (mode == ASYNC_IO_MODE) {
392 ac->io_mode &= ~SYNC_IO_MODE;
393 ac->io_mode |= ASYNC_IO_MODE;
394 } else if (mode == SYNC_IO_MODE) {
395 ac->io_mode &= ~ASYNC_IO_MODE;
396 ac->io_mode |= SYNC_IO_MODE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700397 } else {
398 pr_err("%s:Not an valid IO Mode:%d\n", __func__, ac->io_mode);
399 return -EINVAL;
400 }
Patrick Lai55f54c52012-11-17 00:29:07 -0800401
402 pr_debug("%s:Set Mode to %d\n", __func__, ac->io_mode);
403 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700404}
405
406struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv)
407{
408 struct audio_client *ac;
409 int n;
410 int lcnt = 0;
411
412 ac = kzalloc(sizeof(struct audio_client), GFP_KERNEL);
413 if (!ac)
414 return NULL;
415 n = q6asm_session_alloc(ac);
416 if (n <= 0)
417 goto fail_session;
418 ac->session = n;
419 ac->cb = cb;
420 ac->priv = priv;
421 ac->io_mode = SYNC_IO_MODE;
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700422 ac->perf_mode = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700423 ac->apr = apr_register("ADSP", "ASM", \
424 (apr_fn)q6asm_callback,\
425 ((ac->session) << 8 | 0x0001),\
426 ac);
427
428 if (ac->apr == NULL) {
429 pr_err("%s Registration with APR failed\n", __func__);
430 goto fail;
431 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700432 rtac_set_asm_handle(n, ac->apr);
Ben Rombergerfce8f512011-07-18 16:46:09 -0700433
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700434 pr_debug("%s Registering the common port with APR\n", __func__);
435 if (atomic_read(&this_mmap.ref_cnt) == 0) {
436 this_mmap.apr = apr_register("ADSP", "ASM", \
437 (apr_fn)q6asm_mmapcallback,\
438 0x0FFFFFFFF, &this_mmap);
439 if (this_mmap.apr == NULL) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700440 pr_debug("%s Unable to register APR ASM common port\n",
441 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700442 goto fail;
443 }
444 }
445
446 atomic_inc(&this_mmap.ref_cnt);
447 init_waitqueue_head(&ac->cmd_wait);
448 init_waitqueue_head(&ac->time_wait);
449 atomic_set(&ac->time_flag, 1);
450 mutex_init(&ac->cmd_lock);
451 for (lcnt = 0; lcnt <= OUT; lcnt++) {
452 mutex_init(&ac->port[lcnt].lock);
453 spin_lock_init(&ac->port[lcnt].dsp_lock);
454 }
455 atomic_set(&ac->cmd_state, 0);
Srikanth Uyyalaa50b51d2012-07-02 16:02:24 +0530456 atomic_set(&ac->cmd_response, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700457
458 pr_debug("%s: session[%d]\n", __func__, ac->session);
459
460 return ac;
461fail:
462 q6asm_audio_client_free(ac);
463 return NULL;
464fail_session:
465 kfree(ac);
466 return NULL;
467}
468
Ben Romberger61754dc2011-10-31 18:25:41 -0700469struct audio_client *q6asm_get_audio_client(int session_id)
470{
471 if ((session_id <= 0) || (session_id > SESSION_MAX)) {
472 pr_err("%s: invalid session: %d\n", __func__, session_id);
473 goto err;
474 }
475
476 if (!session[session_id]) {
477 pr_err("%s: session not active: %d\n", __func__, session_id);
478 goto err;
479 }
480
481 return session[session_id];
482err:
483 return NULL;
484}
485
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700486int q6asm_audio_client_buf_alloc(unsigned int dir,
487 struct audio_client *ac,
488 unsigned int bufsz,
489 unsigned int bufcnt)
490{
491 int cnt = 0;
492 int rc = 0;
493 struct audio_buffer *buf;
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800494#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
495 int len;
Deepa Madiregama636f80e2013-01-17 14:01:25 +0530496 unsigned int bufsz_4k_aligned;
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800497#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700498
499 if (!(ac) || ((dir != IN) && (dir != OUT)))
500 return -EINVAL;
501
502 pr_debug("%s: session[%d]bufsz[%d]bufcnt[%d]\n", __func__, ac->session,
503 bufsz, bufcnt);
504
505 if (ac->session <= 0 || ac->session > 8)
506 goto fail;
507
Patrick Lai55f54c52012-11-17 00:29:07 -0800508 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700509 if (ac->port[dir].buf) {
510 pr_debug("%s: buffer already allocated\n", __func__);
511 return 0;
512 }
Mohammad Johny Shaik79841812014-11-27 11:36:54 +0530513
514 if (bufcnt != FRAME_NUM)
515 goto fail;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700516 mutex_lock(&ac->cmd_lock);
517 buf = kzalloc(((sizeof(struct audio_buffer))*bufcnt),
518 GFP_KERNEL);
519
520 if (!buf) {
521 mutex_unlock(&ac->cmd_lock);
522 goto fail;
523 }
524
525 ac->port[dir].buf = buf;
526
527 while (cnt < bufcnt) {
528 if (bufsz > 0) {
529 if (!buf[cnt].data) {
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800530#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
531 buf[cnt].client = msm_ion_client_create
532 (UINT_MAX, "audio_client");
533 if (IS_ERR_OR_NULL((void *)
534 buf[cnt].client)) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700535 pr_err("%s: ION create client for AUDIO failed\n",
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800536 __func__);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700537 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800538 goto fail;
539 }
Deepa Madiregama636f80e2013-01-17 14:01:25 +0530540 bufsz_4k_aligned = (bufsz + 4095) &
541 (~4095);
542 pr_debug("%s: bufsz_4k_aligned %d"\
543 "bufsz = %d\n",
544 __func__, bufsz_4k_aligned,
545 bufsz);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800546 buf[cnt].handle = ion_alloc
Deepa Madiregama636f80e2013-01-17 14:01:25 +0530547 (buf[cnt].client,
548 bufsz_4k_aligned, SZ_4K,
Hanumant Singh2ac41c92012-08-29 18:39:44 -0700549 (0x1 << ION_AUDIO_HEAP_ID), 0);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800550 if (IS_ERR_OR_NULL((void *)
551 buf[cnt].handle)) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700552 pr_err("%s: ION memory allocation for AUDIO failed\n",
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800553 __func__);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700554 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800555 goto fail;
556 }
557
558 rc = ion_phys(buf[cnt].client,
559 buf[cnt].handle,
560 (ion_phys_addr_t *)
561 &buf[cnt].phys,
562 (size_t *)&len);
563 if (rc) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700564 pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800565 __func__, rc);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700566 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800567 goto fail;
568 }
569
570 buf[cnt].data = ion_map_kernel
Mitchel Humpherys456e2682012-09-12 14:42:50 -0700571 (buf[cnt].client, buf[cnt].handle);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800572 if (IS_ERR_OR_NULL((void *)
573 buf[cnt].data)) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700574 pr_err("%s: ION memory mapping for AUDIO failed\n",
575 __func__);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700576 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800577 goto fail;
578 }
579 memset((void *)buf[cnt].data, 0, bufsz);
580#else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700581 unsigned int flags = 0;
582 buf[cnt].phys =
583 allocate_contiguous_ebi_nomap(bufsz,
584 SZ_4K);
585 if (!buf[cnt].phys) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700586 pr_err("%s:Buf alloc failed size=%d\n",
587 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700588 bufsz);
589 mutex_unlock(&ac->cmd_lock);
590 goto fail;
591 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700592 buf[cnt].mem_buffer =
Laura Abbottea3e7b62012-04-30 15:59:21 -0700593 ioremap(buf[cnt].phys, bufsz);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700594 if (IS_ERR(
595 (void *)buf[cnt].mem_buffer)) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700596 pr_err("%s:map_buffer failed, error = %ld\n",
597 __func__,
598 PTR_ERR((void *)buf[cnt].mem_buffer));
Jayasena Sangaraboina466e6b92012-01-17 21:10:55 -0800599 mutex_unlock(&ac->cmd_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700600 goto fail;
601 }
602 buf[cnt].data =
Laura Abbottea3e7b62012-04-30 15:59:21 -0700603 buf[cnt].mem_buffer;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700604 if (!buf[cnt].data) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700605 pr_err("%s:invalid vaddr, iomap failed\n",
606 __func__);
Jayasena Sangaraboina466e6b92012-01-17 21:10:55 -0800607 mutex_unlock(&ac->cmd_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700608 goto fail;
609 }
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800610#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700611 buf[cnt].used = 1;
612 buf[cnt].size = bufsz;
613 buf[cnt].actual_size = bufsz;
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800614 pr_debug("%s data[%p]phys[%p][%p]\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700615 __func__,
616 (void *)buf[cnt].data,
617 (void *)buf[cnt].phys,
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800618 (void *)&buf[cnt].phys);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700619 cnt++;
620 }
621 }
622 }
623 ac->port[dir].max_buf_cnt = cnt;
624
625 mutex_unlock(&ac->cmd_lock);
626 rc = q6asm_memory_map_regions(ac, dir, bufsz, cnt);
627 if (rc < 0) {
628 pr_err("%s:CMD Memory_map_regions failed\n", __func__);
629 goto fail;
630 }
631 }
632 return 0;
633fail:
634 q6asm_audio_client_buf_free(dir, ac);
635 return -EINVAL;
636}
637
638int q6asm_audio_client_buf_alloc_contiguous(unsigned int dir,
639 struct audio_client *ac,
640 unsigned int bufsz,
641 unsigned int bufcnt)
642{
643 int cnt = 0;
644 int rc = 0;
645 struct audio_buffer *buf;
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800646#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
647 int len;
648#else
649 int flags = 0;
650#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700651 if (!(ac) || ((dir != IN) && (dir != OUT)))
652 return -EINVAL;
653
654 pr_debug("%s: session[%d]bufsz[%d]bufcnt[%d]\n",
655 __func__, ac->session,
656 bufsz, bufcnt);
657
658 if (ac->session <= 0 || ac->session > 8)
659 goto fail;
660
661 if (ac->port[dir].buf) {
662 pr_debug("%s: buffer already allocated\n", __func__);
663 return 0;
664 }
665 mutex_lock(&ac->cmd_lock);
666 buf = kzalloc(((sizeof(struct audio_buffer))*bufcnt),
667 GFP_KERNEL);
668
669 if (!buf) {
670 mutex_unlock(&ac->cmd_lock);
671 goto fail;
672 }
673
674 ac->port[dir].buf = buf;
675
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800676#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
677 buf[0].client = msm_ion_client_create(UINT_MAX, "audio_client");
678 if (IS_ERR_OR_NULL((void *)buf[0].client)) {
679 pr_err("%s: ION create client for AUDIO failed\n", __func__);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700680 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800681 goto fail;
682 }
683 buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
Hanumant Singh2ac41c92012-08-29 18:39:44 -0700684 (0x1 << ION_AUDIO_HEAP_ID), 0);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800685 if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
686 pr_err("%s: ION memory allocation for AUDIO failed\n",
687 __func__);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700688 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800689 goto fail;
690 }
691
692 rc = ion_phys(buf[0].client, buf[0].handle,
693 (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len);
694 if (rc) {
695 pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
696 __func__, rc);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700697 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800698 goto fail;
699 }
700
Mitchel Humpherys456e2682012-09-12 14:42:50 -0700701 buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800702 if (IS_ERR_OR_NULL((void *) buf[0].data)) {
703 pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
Swaminathan Sathappan349fed62012-05-22 15:04:43 -0700704 mutex_unlock(&ac->cmd_lock);
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800705 goto fail;
706 }
707 memset((void *)buf[0].data, 0, (bufsz * bufcnt));
708#else
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700709 buf[0].phys = allocate_contiguous_ebi_nomap(bufsz * bufcnt,
710 SZ_4K);
711 if (!buf[0].phys) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700712 pr_err("%s:Buf alloc failed size=%d, bufcnt=%d\n",
713 __func__, bufsz, bufcnt);
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700714 mutex_unlock(&ac->cmd_lock);
715 goto fail;
716 }
717
Laura Abbottea3e7b62012-04-30 15:59:21 -0700718 buf[0].mem_buffer = ioremap(buf[0].phys, bufsz * bufcnt);
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700719 if (IS_ERR((void *)buf[cnt].mem_buffer)) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700720 pr_err("%s:map_buffer failed, error = %ld\n",
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700721 __func__, PTR_ERR((void *)buf[0].mem_buffer));
722
723 mutex_unlock(&ac->cmd_lock);
724 goto fail;
725 }
Laura Abbottea3e7b62012-04-30 15:59:21 -0700726 buf[0].data = buf[0].mem_buffer;
Swaminathan Sathappanbdc55082012-02-16 22:47:40 -0800727#endif
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700728 if (!buf[0].data) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700729 pr_err("%s:invalid vaddr, iomap failed\n", __func__);
Harmandeep Singh2f7c23c2011-11-04 11:57:35 -0700730 mutex_unlock(&ac->cmd_lock);
731 goto fail;
732 }
733
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700734 buf[0].used = dir ^ 1;
735 buf[0].size = bufsz;
736 buf[0].actual_size = bufsz;
737 cnt = 1;
738 while (cnt < bufcnt) {
739 if (bufsz > 0) {
740 buf[cnt].data = buf[0].data + (cnt * bufsz);
741 buf[cnt].phys = buf[0].phys + (cnt * bufsz);
742 if (!buf[cnt].data) {
743 pr_err("%s Buf alloc failed\n",
744 __func__);
745 mutex_unlock(&ac->cmd_lock);
746 goto fail;
747 }
748 buf[cnt].used = dir ^ 1;
749 buf[cnt].size = bufsz;
750 buf[cnt].actual_size = bufsz;
751 pr_debug("%s data[%p]phys[%p][%p]\n", __func__,
752 (void *)buf[cnt].data,
753 (void *)buf[cnt].phys,
754 (void *)&buf[cnt].phys);
755 }
756 cnt++;
757 }
758 ac->port[dir].max_buf_cnt = cnt;
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700759
760 pr_debug("%s ac->port[%d].max_buf_cnt[%d]\n", __func__, dir,
761 ac->port[dir].max_buf_cnt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700762 mutex_unlock(&ac->cmd_lock);
763 rc = q6asm_memory_map(ac, buf[0].phys, dir, bufsz, cnt);
764 if (rc < 0) {
765 pr_err("%s:CMD Memory_map_regions failed\n", __func__);
766 goto fail;
767 }
768 return 0;
769fail:
770 q6asm_audio_client_buf_free_contiguous(dir, ac);
771 return -EINVAL;
772}
773
774static int32_t q6asm_mmapcallback(struct apr_client_data *data, void *priv)
775{
776 uint32_t token;
777 uint32_t *payload = data->payload;
Deepa Madiregama636f80e2013-01-17 14:01:25 +0530778 struct audio_client *ac;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700779
780 if (data->opcode == RESET_EVENTS) {
781 pr_debug("%s: Reset event is received: %d %d apr[%p]\n",
782 __func__,
783 data->reset_event,
784 data->reset_proc,
785 this_mmap.apr);
786 apr_reset(this_mmap.apr);
787 this_mmap.apr = NULL;
788 atomic_set(&this_mmap.cmd_state, 0);
789 return 0;
790 }
791
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700792 pr_debug("%s:ptr0[0x%x]ptr1[0x%x]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]\n",
793 __func__, payload[0], payload[1], data->opcode, data->token,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700794 data->payload_size, data->src_port, data->dest_port);
795
796 if (data->opcode == APR_BASIC_RSP_RESULT) {
797 token = data->token;
Deepa Madiregama636f80e2013-01-17 14:01:25 +0530798 ac = (struct audio_client *)data->token;
799 pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700800 switch (payload[0]) {
801 case ASM_SESSION_CMD_MEMORY_MAP:
802 case ASM_SESSION_CMD_MEMORY_UNMAP:
803 case ASM_SESSION_CMD_MEMORY_MAP_REGIONS:
804 case ASM_SESSION_CMD_MEMORY_UNMAP_REGIONS:
805 pr_debug("%s:command[0x%x]success [0x%x]\n",
806 __func__, payload[0], payload[1]);
Deepa Madiregama636f80e2013-01-17 14:01:25 +0530807 if (atomic_read(&ac->cmd_state)) {
808 atomic_set(&ac->cmd_state, 0);
809 if (payload[1] != ADSP_EOK) {
810 pr_err("payload[1]:%d error case\n",
811 payload[1]);
812 atomic_set(&ac->cmd_response, 1);
813 } else
814 atomic_set(&ac->cmd_response, 0);
815 wake_up(&ac->cmd_wait);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700816 }
817 break;
818 default:
819 pr_debug("%s:command[0x%x] not expecting rsp\n",
820 __func__, payload[0]);
821 break;
822 }
823 }
824 return 0;
825}
826
Jay Wangcd1d37d2012-10-03 16:17:18 -0700827static int32_t is_no_wait_cmd_rsp(uint32_t opcode, uint32_t *cmd_type)
828{
829 if (opcode == APR_BASIC_RSP_RESULT) {
830 if (cmd_type != NULL) {
831 switch (cmd_type[0]) {
832 case ASM_SESSION_CMD_RUN:
833 case ASM_SESSION_CMD_PAUSE:
834 case ASM_DATA_CMD_EOS:
835 return 1;
836 default:
837 break;
838 }
839 } else
840 pr_err("%s: null pointer!", __func__);
841 } else if (opcode == ASM_DATA_CMDRSP_EOS)
842 return 1;
843
844 return 0;
845}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700846
847static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
848{
849 int i = 0;
850 struct audio_client *ac = (struct audio_client *)priv;
851 uint32_t token;
852 unsigned long dsp_flags;
853 uint32_t *payload;
Jay Wang0668d1062012-07-11 18:53:21 -0700854 uint32_t wakeup_flag = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700855
856
857 if ((ac == NULL) || (data == NULL)) {
858 pr_err("ac or priv NULL\n");
859 return -EINVAL;
860 }
861 if (ac->session <= 0 || ac->session > 8) {
862 pr_err("%s:Session ID is invalid, session = %d\n", __func__,
863 ac->session);
864 return -EINVAL;
865 }
Jay Wangcd1d37d2012-10-03 16:17:18 -0700866
867 payload = data->payload;
868 if ((atomic_read(&ac->nowait_cmd_cnt) > 0) &&
869 is_no_wait_cmd_rsp(data->opcode, payload)) {
Jay Wang0668d1062012-07-11 18:53:21 -0700870 pr_debug("%s: nowait_cmd_cnt %d\n",
871 __func__,
872 atomic_read(&ac->nowait_cmd_cnt));
873 atomic_dec(&ac->nowait_cmd_cnt);
874 wakeup_flag = 0;
875 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700876
877 if (data->opcode == RESET_EVENTS) {
878 pr_debug("q6asm_callback: Reset event is received: %d %d apr[%p]\n",
879 data->reset_event, data->reset_proc, ac->apr);
Laxminath Kasam692c6542012-02-21 11:17:47 +0530880 if (ac->cb)
881 ac->cb(data->opcode, data->token,
882 (uint32_t *)data->payload, ac->priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700883 apr_reset(ac->apr);
884 return 0;
885 }
886
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700887 pr_debug("%s: session[%d]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]\n",
888 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700889 ac->session, data->opcode,
890 data->token, data->payload_size, data->src_port,
891 data->dest_port);
892
893 if (data->opcode == APR_BASIC_RSP_RESULT) {
894 token = data->token;
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700895 pr_debug("%s payload[0]:%x", __func__, payload[0]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700896 switch (payload[0]) {
897 case ASM_STREAM_CMD_SET_PP_PARAMS:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700898 if (rtac_make_asm_callback(ac->session, payload,
899 data->payload_size))
900 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700901 case ASM_SESSION_CMD_PAUSE:
902 case ASM_DATA_CMD_EOS:
903 case ASM_STREAM_CMD_CLOSE:
904 case ASM_STREAM_CMD_FLUSH:
905 case ASM_SESSION_CMD_RUN:
906 case ASM_SESSION_CMD_REGISTER_FOR_TX_OVERFLOW_EVENTS:
907 case ASM_STREAM_CMD_FLUSH_READBUFS:
908 pr_debug("%s:Payload = [0x%x]\n", __func__, payload[0]);
909 if (token != ac->session) {
910 pr_err("%s:Invalid session[%d] rxed expected[%d]",
911 __func__, token, ac->session);
912 return -EINVAL;
913 }
914 case ASM_STREAM_CMD_OPEN_READ:
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700915 case ASM_STREAM_CMD_OPEN_READ_V2_1:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700916 case ASM_STREAM_CMD_OPEN_WRITE:
Flemmard1bc7b1c2014-01-08 00:24:20 -0800917 case ASM_STREAM_CMD_OPEN_WRITE_V2:
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700918 case ASM_STREAM_CMD_OPEN_WRITE_V2_1:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700919 case ASM_STREAM_CMD_OPEN_READWRITE:
Laxminath Kasam20824502013-01-07 14:33:56 +0530920 case ASM_STREAM_CMD_OPEN_LOOPBACK:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700921 case ASM_DATA_CMD_MEDIA_FORMAT_UPDATE:
922 case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
Santosh Mardi23321202012-03-22 04:33:25 +0530923 case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700924 case ASM_STREAM_CMD_OPEN_READ_COMPRESSED:
Laxminath Kasamf16d3fd2012-12-19 14:54:14 +0530925 if (payload[0] == ASM_STREAM_CMD_CLOSE) {
926 atomic_set(&ac->cmd_close_state, 0);
927 wake_up(&ac->cmd_wait);
928 } else if (atomic_read(&ac->cmd_state) &&
929 wakeup_flag) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700930 atomic_set(&ac->cmd_state, 0);
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700931 if (payload[1] == ADSP_EUNSUPPORTED) {
932 pr_debug("paload[1]:%d unsupported",
933 payload[1]);
Srikanth Uyyalaa50b51d2012-07-02 16:02:24 +0530934 atomic_set(&ac->cmd_response, 1);
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700935 }
Srikanth Uyyalaa50b51d2012-07-02 16:02:24 +0530936 else
937 atomic_set(&ac->cmd_response, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700938 wake_up(&ac->cmd_wait);
939 }
940 if (ac->cb)
941 ac->cb(data->opcode, data->token,
942 (uint32_t *)data->payload, ac->priv);
943 break;
944 default:
945 pr_debug("%s:command[0x%x] not expecting rsp\n",
946 __func__, payload[0]);
947 break;
948 }
949 return 0;
950 }
951
952 switch (data->opcode) {
953 case ASM_DATA_EVENT_WRITE_DONE:{
954 struct audio_port_data *port = &ac->port[IN];
955 pr_debug("%s: Rxed opcode[0x%x] status[0x%x] token[%d]",
956 __func__, payload[0], payload[1],
957 data->token);
Patrick Lai55f54c52012-11-17 00:29:07 -0800958 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700959 if (port->buf == NULL) {
960 pr_err("%s: Unexpected Write Done\n",
961 __func__);
962 return -EINVAL;
963 }
964 spin_lock_irqsave(&port->dsp_lock, dsp_flags);
965 if (port->buf[data->token].phys !=
966 payload[0]) {
967 pr_err("Buf expected[%p]rxed[%p]\n",\
968 (void *)port->buf[data->token].phys,\
969 (void *)payload[0]);
970 spin_unlock_irqrestore(&port->dsp_lock,
971 dsp_flags);
972 return -EINVAL;
973 }
974 token = data->token;
975 port->buf[token].used = 1;
976 spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
Rajesha Kini3498c932011-07-19 19:58:27 +0530977#ifdef CONFIG_DEBUG_FS
978 if (out_enable_flag) {
979 /* For first Write done log the time and reset
980 out_cold_index*/
981 if (out_cold_index != 1) {
982 do_gettimeofday(&out_cold_tv);
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700983 pr_debug("COLD: apr_send_pkt at %ld sec %ld microsec\n",
984 out_cold_tv.tv_sec,
Rajesha Kini3498c932011-07-19 19:58:27 +0530985 out_cold_tv.tv_usec);
986 out_cold_index = 1;
987 }
988 pr_debug("out_enable_flag %ld",\
989 out_enable_flag);
990 }
991#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700992 for (i = 0; i < port->max_buf_cnt; i++)
993 pr_debug("%d ", port->buf[i].used);
994
995 }
996 break;
997 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700998 case ASM_STREAM_CMDRSP_GET_PP_PARAMS:
999 rtac_make_asm_callback(ac->session, payload,
1000 data->payload_size);
1001 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001002 case ASM_DATA_EVENT_READ_DONE:{
1003
1004 struct audio_port_data *port = &ac->port[OUT];
Rajesha Kini3498c932011-07-19 19:58:27 +05301005#ifdef CONFIG_DEBUG_FS
1006 if (in_enable_flag) {
1007 /* when in_cont_index == 7, DSP would be
1008 * writing into the 8th 512 byte buffer and this
1009 * timestamp is tapped here.Once done it then writes
1010 * to 9th 512 byte buffer.These two buffers(8th, 9th)
1011 * reach the test application in 5th iteration and that
1012 * timestamp is tapped at user level. The difference
1013 * of these two timestamps gives us the time between
1014 * the time at which dsp started filling the sample
1015 * required and when it reached the test application.
1016 * Hence continuous input latency
1017 */
1018 if (in_cont_index == 7) {
1019 do_gettimeofday(&in_cont_tv);
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001020 pr_err("In_CONT:previous read buffer done at %ld sec %ld microsec\n",
Sriranjan Srikantam74753532011-10-03 14:48:37 -07001021 in_cont_tv.tv_sec, in_cont_tv.tv_usec);
Rajesha Kini3498c932011-07-19 19:58:27 +05301022 }
1023 }
1024#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001025 pr_debug("%s:R-D: status=%d buff_add=%x act_size=%d offset=%d\n",
1026 __func__, payload[READDONE_IDX_STATUS],
1027 payload[READDONE_IDX_BUFFER],
1028 payload[READDONE_IDX_SIZE],
1029 payload[READDONE_IDX_OFFSET]);
1030 pr_debug("%s:R-D:msw_ts=%d lsw_ts=%d flags=%d id=%d num=%d\n",
1031 __func__, payload[READDONE_IDX_MSW_TS],
1032 payload[READDONE_IDX_LSW_TS],
1033 payload[READDONE_IDX_FLAGS],
1034 payload[READDONE_IDX_ID],
1035 payload[READDONE_IDX_NUMFRAMES]);
Rajesha Kini3498c932011-07-19 19:58:27 +05301036#ifdef CONFIG_DEBUG_FS
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001037 if (in_enable_flag)
Rajesha Kini3498c932011-07-19 19:58:27 +05301038 in_cont_index++;
Rajesha Kini3498c932011-07-19 19:58:27 +05301039#endif
Patrick Lai55f54c52012-11-17 00:29:07 -08001040 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001041 if (port->buf == NULL) {
1042 pr_err("%s: Unexpected Write Done\n", __func__);
1043 return -EINVAL;
1044 }
1045 spin_lock_irqsave(&port->dsp_lock, dsp_flags);
1046 token = data->token;
1047 port->buf[token].used = 0;
1048 if (port->buf[token].phys !=
1049 payload[READDONE_IDX_BUFFER]) {
1050 pr_err("Buf expected[%p]rxed[%p]\n",\
1051 (void *)port->buf[token].phys,\
1052 (void *)payload[READDONE_IDX_BUFFER]);
1053 spin_unlock_irqrestore(&port->dsp_lock,
1054 dsp_flags);
1055 break;
1056 }
1057 port->buf[token].actual_size =
1058 payload[READDONE_IDX_SIZE];
1059 spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
1060 }
1061 break;
1062 }
1063 case ASM_DATA_EVENT_EOS:
1064 case ASM_DATA_CMDRSP_EOS:
1065 pr_debug("%s:EOS ACK received: rxed opcode[0x%x]\n",
1066 __func__, data->opcode);
1067 break;
1068 case ASM_STREAM_CMDRSP_GET_ENCDEC_PARAM:
1069 break;
1070 case ASM_SESSION_EVENT_TX_OVERFLOW:
1071 pr_err("ASM_SESSION_EVENT_TX_OVERFLOW\n");
1072 break;
1073 case ASM_SESSION_CMDRSP_GET_SESSION_TIME:
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001074 pr_debug("%s: ASM_SESSION_CMDRSP_GET_SESSION_TIME, payload[0] = %d, payload[1] = %d, payload[2] = %d\n",
1075 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001076 payload[0], payload[1], payload[2]);
1077 ac->time_stamp = (uint64_t)(((uint64_t)payload[1] << 32) |
1078 payload[2]);
1079 if (atomic_read(&ac->time_flag)) {
1080 atomic_set(&ac->time_flag, 0);
1081 wake_up(&ac->time_wait);
1082 }
1083 break;
1084 case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
Deepa Madiregama55cbf782011-09-10 05:44:39 +05301085 case ASM_DATA_EVENT_ENC_SR_CM_NOTIFY:
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001086 pr_debug("%s: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, payload[0] = %d, payload[1] = %d, payload[2] = %d, payload[3] = %d\n",
1087 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001088 payload[0], payload[1], payload[2],
1089 payload[3]);
1090 break;
1091 }
1092 if (ac->cb)
1093 ac->cb(data->opcode, data->token,
1094 data->payload, ac->priv);
1095
1096 return 0;
1097}
1098
1099void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size,
1100 uint32_t *index)
1101{
1102 void *data;
1103 unsigned char idx;
1104 struct audio_port_data *port;
1105
1106 if (!ac || ((dir != IN) && (dir != OUT)))
1107 return NULL;
1108
Patrick Lai55f54c52012-11-17 00:29:07 -08001109 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001110 port = &ac->port[dir];
1111
1112 mutex_lock(&port->lock);
1113 idx = port->cpu_buf;
1114 if (port->buf == NULL) {
1115 pr_debug("%s:Buffer pointer null\n", __func__);
Jayasena Sangaraboina466e6b92012-01-17 21:10:55 -08001116 mutex_unlock(&port->lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001117 return NULL;
1118 }
1119 /* dir 0: used = 0 means buf in use
1120 dir 1: used = 1 means buf in use */
1121 if (port->buf[idx].used == dir) {
1122 /* To make it more robust, we could loop and get the
1123 next avail buf, its risky though */
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001124 pr_debug("%s:Next buf idx[0x%x] not available,dir[%d]\n",
1125 __func__, idx, dir);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001126 mutex_unlock(&port->lock);
1127 return NULL;
1128 }
1129 *size = port->buf[idx].actual_size;
1130 *index = port->cpu_buf;
1131 data = port->buf[idx].data;
1132 pr_debug("%s:session[%d]index[%d] data[%p]size[%d]\n",
1133 __func__,
1134 ac->session,
1135 port->cpu_buf,
1136 data, *size);
1137 /* By default increase the cpu_buf cnt
1138 user accesses this function,increase cpu
1139 buf(to avoid another api)*/
1140 port->buf[idx].used = dir;
1141 port->cpu_buf = ((port->cpu_buf + 1) & (port->max_buf_cnt - 1));
1142 mutex_unlock(&port->lock);
1143 return data;
1144 }
1145 return NULL;
1146}
1147
Jay Wang9cf59a02011-08-10 16:58:40 -07001148void *q6asm_is_cpu_buf_avail_nolock(int dir, struct audio_client *ac,
1149 uint32_t *size, uint32_t *index)
1150{
1151 void *data;
1152 unsigned char idx;
1153 struct audio_port_data *port;
1154
1155 if (!ac || ((dir != IN) && (dir != OUT)))
1156 return NULL;
1157
1158 port = &ac->port[dir];
1159
1160 idx = port->cpu_buf;
1161 if (port->buf == NULL) {
1162 pr_debug("%s:Buffer pointer null\n", __func__);
1163 return NULL;
1164 }
1165 /*
1166 * dir 0: used = 0 means buf in use
1167 * dir 1: used = 1 means buf in use
1168 */
1169 if (port->buf[idx].used == dir) {
1170 /*
1171 * To make it more robust, we could loop and get the
1172 * next avail buf, its risky though
1173 */
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001174 pr_debug("%s:Next buf idx[0x%x] not available, dir[%d]\n",
1175 __func__, idx, dir);
Jay Wang9cf59a02011-08-10 16:58:40 -07001176 return NULL;
1177 }
1178 *size = port->buf[idx].actual_size;
1179 *index = port->cpu_buf;
1180 data = port->buf[idx].data;
1181 pr_debug("%s:session[%d]index[%d] data[%p]size[%d]\n",
1182 __func__, ac->session, port->cpu_buf,
1183 data, *size);
1184 /*
1185 * By default increase the cpu_buf cnt
1186 * user accesses this function,increase cpu
1187 * buf(to avoid another api)
1188 */
1189 port->buf[idx].used = dir;
1190 port->cpu_buf = ((port->cpu_buf + 1) & (port->max_buf_cnt - 1));
1191 return data;
1192}
1193
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001194int q6asm_is_dsp_buf_avail(int dir, struct audio_client *ac)
1195{
1196 int ret = -1;
1197 struct audio_port_data *port;
1198 uint32_t idx;
1199
1200 if (!ac || (dir != OUT))
1201 return ret;
1202
Patrick Lai55f54c52012-11-17 00:29:07 -08001203 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001204 port = &ac->port[dir];
1205
1206 mutex_lock(&port->lock);
1207 idx = port->dsp_buf;
1208
1209 if (port->buf[idx].used == (dir ^ 1)) {
1210 /* To make it more robust, we could loop and get the
1211 next avail buf, its risky though */
1212 pr_err("Next buf idx[0x%x] not available, dir[%d]\n",
1213 idx, dir);
1214 mutex_unlock(&port->lock);
1215 return ret;
1216 }
1217 pr_debug("%s: session[%d]dsp_buf=%d cpu_buf=%d\n", __func__,
1218 ac->session, port->dsp_buf, port->cpu_buf);
1219 ret = ((port->dsp_buf != port->cpu_buf) ? 0 : -1);
1220 mutex_unlock(&port->lock);
1221 }
1222 return ret;
1223}
1224
1225static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
1226 uint32_t pkt_size, uint32_t cmd_flg)
1227{
1228 pr_debug("%s:session=%d pkt size=%d cmd_flg=%d\n", __func__, pkt_size,
1229 cmd_flg, ac->session);
1230 mutex_lock(&ac->cmd_lock);
1231 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
1232 APR_HDR_LEN(sizeof(struct apr_hdr)),\
1233 APR_PKT_VER);
1234 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
1235 hdr->src_domain = APR_DOMAIN_APPS;
1236 hdr->dest_svc = APR_SVC_ASM;
1237 hdr->dest_domain = APR_DOMAIN_ADSP;
1238 hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01;
1239 hdr->dest_port = ((ac->session << 8) & 0xFF00) | 0x01;
1240 if (cmd_flg) {
1241 hdr->token = ac->session;
1242 atomic_set(&ac->cmd_state, 1);
1243 }
1244 hdr->pkt_size = pkt_size;
1245 mutex_unlock(&ac->cmd_lock);
1246 return;
1247}
1248
1249static void q6asm_add_mmaphdr(struct apr_hdr *hdr, uint32_t pkt_size,
1250 uint32_t cmd_flg)
1251{
Deepa Madiregama636f80e2013-01-17 14:01:25 +05301252 struct audio_client *ac;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001253 pr_debug("%s:pkt size=%d cmd_flg=%d\n", __func__, pkt_size, cmd_flg);
Deepa Madiregama636f80e2013-01-17 14:01:25 +05301254 ac = (struct audio_client *)hdr->token;
1255 pr_debug("%s: audio_client = %x\n", __func__, (uint32_t)ac);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001256 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
1257 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1258 hdr->src_port = 0;
1259 hdr->dest_port = 0;
1260 if (cmd_flg) {
Deepa Madiregama636f80e2013-01-17 14:01:25 +05301261 atomic_set(&ac->cmd_state, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001262 }
1263 hdr->pkt_size = pkt_size;
1264 return;
1265}
1266
1267int q6asm_open_read(struct audio_client *ac,
1268 uint32_t format)
1269{
1270 int rc = 0x00;
1271 struct asm_stream_cmd_open_read open;
Rajesha Kini3498c932011-07-19 19:58:27 +05301272#ifdef CONFIG_DEBUG_FS
1273 in_cont_index = 0;
1274#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001275 if ((ac == NULL) || (ac->apr == NULL)) {
1276 pr_err("%s: APR handle NULL\n", __func__);
1277 return -EINVAL;
1278 }
1279 pr_debug("%s:session[%d]", __func__, ac->session);
1280
1281 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1282 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ;
1283 /* Stream prio : High, provide meta info with encoded frames */
1284 open.src_endpoint = ASM_END_POINT_DEVICE_MATRIX;
1285
1286 open.pre_proc_top = get_asm_topology();
1287 if (open.pre_proc_top == 0)
1288 open.pre_proc_top = DEFAULT_POPP_TOPOLOGY;
1289
1290 switch (format) {
1291 case FORMAT_LINEAR_PCM:
1292 open.uMode = STREAM_PRIORITY_HIGH;
1293 open.format = LINEAR_PCM;
1294 break;
Mingming Yin647e9ea2012-03-17 19:56:10 -07001295 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
1296 open.uMode = STREAM_PRIORITY_HIGH;
1297 open.format = MULTI_CHANNEL_PCM;
1298 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001299 case FORMAT_MPEG4_AAC:
1300 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1301 open.format = MPEG4_AAC;
1302 break;
1303 case FORMAT_V13K:
1304 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1305 open.format = V13K_FS;
1306 break;
1307 case FORMAT_EVRC:
1308 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1309 open.format = EVRC_FS;
1310 break;
1311 case FORMAT_AMRNB:
1312 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1313 open.format = AMRNB_FS;
1314 break;
Alex Wong2caeecc2011-10-28 10:52:15 +05301315 case FORMAT_AMRWB:
1316 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1317 open.format = AMRWB_FS;
1318 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001319 default:
1320 pr_err("Invalid format[%d]\n", format);
1321 goto fail_cmd;
1322 }
1323 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1324 if (rc < 0) {
1325 pr_err("open failed op[0x%x]rc[%d]\n", \
1326 open.hdr.opcode, rc);
1327 goto fail_cmd;
1328 }
1329 rc = wait_event_timeout(ac->cmd_wait,
1330 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1331 if (!rc) {
1332 pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
1333 rc);
1334 goto fail_cmd;
1335 }
Patrick Lai55f54c52012-11-17 00:29:07 -08001336
1337 ac->io_mode |= TUN_READ_IO_MODE;
1338
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001339 return 0;
1340fail_cmd:
1341 return -EINVAL;
1342}
1343
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001344int q6asm_open_read_v2_1(struct audio_client *ac,
1345 uint32_t format)
1346{
1347 int rc = 0x00;
1348 struct asm_stream_cmd_open_read_v2_1 open;
1349#ifdef CONFIG_DEBUG_FS
1350 in_cont_index = 0;
1351#endif
1352 if ((ac == NULL) || (ac->apr == NULL)) {
1353 pr_err("%s: APR handle NULL\n", __func__);
1354 return -EINVAL;
1355 }
1356 pr_debug("%s:session[%d]", __func__, ac->session);
1357
1358 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1359 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ_V2_1;
1360 open.src_endpoint = ASM_END_POINT_DEVICE_MATRIX;
1361 open.pre_proc_top = get_asm_topology();
1362 if (open.pre_proc_top == 0)
1363 open.pre_proc_top = DEFAULT_POPP_TOPOLOGY;
1364
1365 switch (format) {
1366 case FORMAT_LINEAR_PCM:
1367 open.uMode = STREAM_PRIORITY_HIGH;
1368 open.format = LINEAR_PCM;
1369 break;
1370 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
1371 open.uMode = STREAM_PRIORITY_HIGH;
1372 open.format = MULTI_CHANNEL_PCM;
1373 break;
1374 case FORMAT_MPEG4_AAC:
1375 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1376 open.format = MPEG4_AAC;
1377 break;
1378 case FORMAT_V13K:
1379 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1380 open.format = V13K_FS;
1381 break;
1382 case FORMAT_EVRC:
1383 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1384 open.format = EVRC_FS;
1385 break;
1386 case FORMAT_AMRNB:
1387 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1388 open.format = AMRNB_FS;
1389 break;
1390 case FORMAT_AMRWB:
1391 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
1392 open.format = AMRWB_FS;
1393 break;
1394 default:
1395 pr_err("Invalid format[%d]\n", format);
1396 goto fail_cmd;
1397 }
1398 open.uMode = ASM_OPEN_READ_PERF_MODE_BIT;
1399 open.bits_per_sample = PCM_BITS_PER_SAMPLE;
1400 open.reserved = 0;
1401 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1402 if (rc < 0) {
1403 pr_err("open failed op[0x%x]rc[%d]\n", \
1404 open.hdr.opcode, rc);
1405 goto fail_cmd;
1406 }
1407 rc = wait_event_timeout(ac->cmd_wait,
1408 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1409 if (!rc) {
1410 pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
1411 rc);
1412 goto fail_cmd;
1413 }
1414 return 0;
1415fail_cmd:
1416 return -EINVAL;
1417}
1418
1419
Subhash Chandra Bose Naripeddy694b7d92012-06-20 20:46:13 -07001420int q6asm_open_read_compressed(struct audio_client *ac,
1421 uint32_t frames_per_buffer, uint32_t meta_data_mode)
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001422{
1423 int rc = 0x00;
1424 struct asm_stream_cmd_open_read_compressed open;
1425#ifdef CONFIG_DEBUG_FS
1426 in_cont_index = 0;
1427#endif
1428 if ((ac == NULL) || (ac->apr == NULL)) {
1429 pr_err("%s: APR handle NULL\n", __func__);
1430 return -EINVAL;
1431 }
1432 pr_debug("%s:session[%d]", __func__, ac->session);
1433
1434 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1435 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ_COMPRESSED;
1436 /* hardcoded as following*/
Subhash Chandra Bose Naripeddy694b7d92012-06-20 20:46:13 -07001437 open.frame_per_buf = frames_per_buffer;
1438 open.uMode = meta_data_mode;
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001439
1440 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1441 if (rc < 0) {
1442 pr_err("open failed op[0x%x]rc[%d]\n", open.hdr.opcode, rc);
1443 goto fail_cmd;
1444 }
1445 rc = wait_event_timeout(ac->cmd_wait,
1446 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1447 if (!rc) {
1448 pr_err("%s: timeout. waited for OPEN_READ_COMPRESSED rc[%d]\n",
1449 __func__, rc);
1450 goto fail_cmd;
1451 }
1452 return 0;
1453fail_cmd:
1454 return -EINVAL;
1455}
1456
Santosh Mardi23321202012-03-22 04:33:25 +05301457int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format)
1458{
1459 int rc = 0x00;
1460 struct asm_stream_cmd_open_write_compressed open;
1461
1462 if ((ac == NULL) || (ac->apr == NULL)) {
1463 pr_err("%s: APR handle NULL\n", __func__);
1464 return -EINVAL;
1465 }
1466 pr_debug("%s: session[%d] wr_format[0x%x]", __func__, ac->session,
1467 format);
1468
1469 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1470
1471 open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED;
1472
1473 switch (format) {
1474 case FORMAT_AC3:
1475 open.format = AC3_DECODER;
1476 break;
1477 case FORMAT_EAC3:
1478 open.format = EAC3_DECODER;
1479 break;
1480 case FORMAT_MP3:
1481 open.format = MP3;
1482 break;
1483 case FORMAT_DTS:
1484 open.format = DTS;
1485 break;
Srikanth Uyyala66f781a2012-06-13 23:23:25 +05301486 case FORMAT_DTS_LBR:
1487 open.format = DTS_LBR;
1488 break;
Santosh Mardi23321202012-03-22 04:33:25 +05301489 case FORMAT_AAC:
1490 open.format = MPEG4_AAC;
1491 break;
1492 case FORMAT_ATRAC:
1493 open.format = ATRAC;
1494 break;
1495 case FORMAT_WMA_V10PRO:
1496 open.format = WMA_V10PRO;
1497 break;
1498 case FORMAT_MAT:
1499 open.format = MAT;
1500 break;
1501 default:
1502 pr_err("%s: Invalid format[%d]\n", __func__, format);
1503 goto fail_cmd;
1504 }
1505 /*Below flag indicates the DSP that Compressed audio input
1506 stream is not IEC 61937 or IEC 60958 packetizied*/
1507 open.flags = 0x00000000;
1508 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1509 if (rc < 0) {
1510 pr_err("%s: open failed op[0x%x]rc[%d]\n", \
1511 __func__, open.hdr.opcode, rc);
1512 goto fail_cmd;
1513 }
1514 rc = wait_event_timeout(ac->cmd_wait,
1515 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1516 if (!rc) {
1517 pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
1518 rc);
1519 goto fail_cmd;
1520 }
1521 return 0;
1522fail_cmd:
1523 return -EINVAL;
1524}
1525
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001526int q6asm_open_write(struct audio_client *ac, uint32_t format)
1527{
1528 int rc = 0x00;
1529 struct asm_stream_cmd_open_write open;
1530
1531 if ((ac == NULL) || (ac->apr == NULL)) {
1532 pr_err("%s: APR handle NULL\n", __func__);
1533 return -EINVAL;
1534 }
1535 pr_debug("%s: session[%d] wr_format[0x%x]", __func__, ac->session,
1536 format);
1537
1538 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1539
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001540 if (ac->perf_mode) {
1541 pr_debug("%s In Performance/lowlatency mode", __func__);
1542 open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V2_1;
1543 open.uMode = ASM_OPEN_WRITE_PERF_MODE_BIT;
1544 /* source endpoint : matrix */
1545 open.sink_endpoint = ASM_END_POINT_DEVICE_MATRIX;
1546 open.stream_handle = PCM_BITS_PER_SAMPLE;
1547 } else {
1548 open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE;
1549 open.uMode = STREAM_PRIORITY_HIGH;
1550 /* source endpoint : matrix */
1551 open.sink_endpoint = ASM_END_POINT_DEVICE_MATRIX;
1552 open.stream_handle = 0x00;
1553 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001554 open.post_proc_top = get_asm_topology();
1555 if (open.post_proc_top == 0)
1556 open.post_proc_top = DEFAULT_POPP_TOPOLOGY;
1557
1558 switch (format) {
1559 case FORMAT_LINEAR_PCM:
1560 open.format = LINEAR_PCM;
1561 break;
Kiran Kandi5e809b02012-01-31 00:24:33 -08001562 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
1563 open.format = MULTI_CHANNEL_PCM;
1564 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001565 case FORMAT_MPEG4_AAC:
1566 open.format = MPEG4_AAC;
1567 break;
Bharath Ramachandramurthy4f71d502011-10-23 19:45:22 -07001568 case FORMAT_MPEG4_MULTI_AAC:
1569 open.format = MPEG4_MULTI_AAC;
1570 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001571 case FORMAT_WMA_V9:
1572 open.format = WMA_V9;
1573 break;
1574 case FORMAT_WMA_V10PRO:
1575 open.format = WMA_V10PRO;
1576 break;
Asish Bhattacharya305d1752011-11-01 20:38:26 +05301577 case FORMAT_MP3:
1578 open.format = MP3;
1579 break;
Srikanth Uyyala66f781a2012-06-13 23:23:25 +05301580 case FORMAT_DTS:
1581 open.format = DTS;
1582 break;
1583 case FORMAT_DTS_LBR:
1584 open.format = DTS_LBR;
1585 break;
Ajit Khare43fd8832012-08-07 13:19:44 -07001586 case FORMAT_AMRWB:
1587 open.format = AMRWB_FS;
1588 pr_debug("q6asm_open_write FORMAT_AMRWB");
1589 break;
1590 case FORMAT_AMR_WB_PLUS:
1591 open.format = AMR_WB_PLUS;
1592 pr_debug("q6asm_open_write FORMAT_AMR_WB_PLUS");
1593 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001594 default:
1595 pr_err("%s: Invalid format[%d]\n", __func__, format);
1596 goto fail_cmd;
1597 }
1598 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1599 if (rc < 0) {
1600 pr_err("%s: open failed op[0x%x]rc[%d]\n", \
1601 __func__, open.hdr.opcode, rc);
1602 goto fail_cmd;
1603 }
1604 rc = wait_event_timeout(ac->cmd_wait,
1605 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1606 if (!rc) {
1607 pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
1608 rc);
1609 goto fail_cmd;
1610 }
Srikanth Uyyalaa50b51d2012-07-02 16:02:24 +05301611 if (atomic_read(&ac->cmd_response)) {
1612 pr_err("%s: format = %x not supported\n", __func__, format);
1613 goto fail_cmd;
1614 }
Patrick Lai55f54c52012-11-17 00:29:07 -08001615
1616 ac->io_mode |= TUN_WRITE_IO_MODE;
1617
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001618 return 0;
1619fail_cmd:
1620 return -EINVAL;
1621}
1622
Flemmard1bc7b1c2014-01-08 00:24:20 -08001623int q6asm_open_write_v2(struct audio_client *ac, uint32_t format,
1624 uint16_t bit_width)
1625{
1626 int rc = 0x00;
1627 struct asm_stream_cmd_open_write_v2 open;
1628 static int if_first_open_write_v2 = 0;
1629
1630 if ((ac == NULL) || (ac->apr == NULL)) {
1631 pr_err("%s: APR handle NULL\n", __func__);
1632 return -EINVAL;
1633 }
1634 pr_debug("%s: session[%d] wr_format[0x%x], bitwidth[%d]",
1635 __func__, ac->session, format, bit_width);
1636
1637
1638 if (!if_first_open_write_v2)
1639 {
1640 msleep(30);
1641 if_first_open_write_v2 = 1;
1642 }
1643
1644 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1645
1646 open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V2;
1647 open.uMode = STREAM_PRIORITY_HIGH;
1648 open.bits_per_sample = bit_width;
1649 open.sink_endpoint = ASM_END_POINT_DEVICE_MATRIX;
1650
1651 open.post_proc_top = get_asm_topology();
1652 if (open.post_proc_top == 0)
1653 open.post_proc_top = DEFAULT_POPP_TOPOLOGY;
1654
1655 switch (format) {
1656 case FORMAT_LINEAR_PCM:
1657 open.format = LINEAR_PCM;
1658 break;
1659 case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
1660 open.format = MULTI_CHANNEL_PCM;
1661 break;
1662 case FORMAT_MPEG4_AAC:
1663 open.format = MPEG4_AAC;
1664 break;
1665 case FORMAT_MPEG4_MULTI_AAC:
1666 open.format = MPEG4_MULTI_AAC;
1667 break;
1668 case FORMAT_WMA_V9:
1669 open.format = WMA_V9;
1670 break;
1671 case FORMAT_WMA_V10PRO:
1672 open.format = WMA_V10PRO;
1673 break;
1674 case FORMAT_MP3:
1675 open.format = MP3;
1676 break;
1677 case FORMAT_DTS:
1678 open.format = DTS;
1679 break;
1680 case FORMAT_DTS_LBR:
1681 open.format = DTS_LBR;
1682 break;
1683 case FORMAT_AMRWB:
1684 open.format = AMRWB_FS;
1685 pr_debug("q6asm_open_write FORMAT_AMRWB");
1686 break;
1687 case FORMAT_AMR_WB_PLUS:
1688 open.format = AMR_WB_PLUS;
1689 pr_debug("q6asm_open_write FORMAT_AMR_WB_PLUS");
1690 break;
1691 default:
1692 pr_err("%s: Invalid format[%d]\n", __func__, format);
1693 goto fail_cmd;
1694 }
1695 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1696 if (rc < 0) {
1697 pr_err("%s: open failed op[0x%x]rc[%d]\n", \
1698 __func__, open.hdr.opcode, rc);
1699 goto fail_cmd;
1700 }
1701 rc = wait_event_timeout(ac->cmd_wait,
1702 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1703 if (!rc) {
1704 pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
1705 rc);
1706 goto fail_cmd;
1707 }
1708 if (atomic_read(&ac->cmd_response)) {
1709 pr_err("%s: format = %x not supported\n", __func__, format);
1710 goto fail_cmd;
1711 }
1712
1713 ac->io_mode |= TUN_WRITE_IO_MODE;
1714
1715 return 0;
1716fail_cmd:
1717 return -EINVAL;
1718}
1719
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001720int q6asm_open_read_write(struct audio_client *ac,
1721 uint32_t rd_format,
1722 uint32_t wr_format)
1723{
1724 int rc = 0x00;
1725 struct asm_stream_cmd_open_read_write open;
1726
1727 if ((ac == NULL) || (ac->apr == NULL)) {
1728 pr_err("APR handle NULL\n");
1729 return -EINVAL;
1730 }
1731 pr_debug("%s: session[%d]", __func__, ac->session);
1732 pr_debug("wr_format[0x%x]rd_format[0x%x]",
1733 wr_format, rd_format);
1734
1735 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1736 open.hdr.opcode = ASM_STREAM_CMD_OPEN_READWRITE;
1737
Deepa Madiregama55cbf782011-09-10 05:44:39 +05301738 open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_NORMAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001739 /* source endpoint : matrix */
1740 open.post_proc_top = get_asm_topology();
1741 if (open.post_proc_top == 0)
1742 open.post_proc_top = DEFAULT_POPP_TOPOLOGY;
1743
1744 switch (wr_format) {
1745 case FORMAT_LINEAR_PCM:
1746 open.write_format = LINEAR_PCM;
1747 break;
1748 case FORMAT_MPEG4_AAC:
1749 open.write_format = MPEG4_AAC;
1750 break;
Bharath Ramachandramurthy4f71d502011-10-23 19:45:22 -07001751 case FORMAT_MPEG4_MULTI_AAC:
1752 open.write_format = MPEG4_MULTI_AAC;
1753 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001754 case FORMAT_WMA_V9:
1755 open.write_format = WMA_V9;
1756 break;
1757 case FORMAT_WMA_V10PRO:
1758 open.write_format = WMA_V10PRO;
1759 break;
Alex Wong2caeecc2011-10-28 10:52:15 +05301760 case FORMAT_AMRNB:
1761 open.write_format = AMRNB_FS;
1762 break;
1763 case FORMAT_AMRWB:
1764 open.write_format = AMRWB_FS;
1765 break;
Ajit Khare7277bb72012-10-31 16:34:22 -07001766 case FORMAT_AMR_WB_PLUS:
1767 open.write_format = AMR_WB_PLUS;
1768 break;
Alex Wong2caeecc2011-10-28 10:52:15 +05301769 case FORMAT_V13K:
1770 open.write_format = V13K_FS;
1771 break;
1772 case FORMAT_EVRC:
1773 open.write_format = EVRC_FS;
1774 break;
1775 case FORMAT_EVRCB:
1776 open.write_format = EVRCB_FS;
1777 break;
1778 case FORMAT_EVRCWB:
1779 open.write_format = EVRCWB_FS;
1780 break;
1781 case FORMAT_MP3:
1782 open.write_format = MP3;
1783 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001784 default:
1785 pr_err("Invalid format[%d]\n", wr_format);
1786 goto fail_cmd;
1787 }
1788
1789 switch (rd_format) {
1790 case FORMAT_LINEAR_PCM:
1791 open.read_format = LINEAR_PCM;
1792 break;
1793 case FORMAT_MPEG4_AAC:
1794 open.read_format = MPEG4_AAC;
1795 break;
1796 case FORMAT_V13K:
1797 open.read_format = V13K_FS;
1798 break;
1799 case FORMAT_EVRC:
1800 open.read_format = EVRC_FS;
1801 break;
1802 case FORMAT_AMRNB:
1803 open.read_format = AMRNB_FS;
1804 break;
Alex Wong2caeecc2011-10-28 10:52:15 +05301805 case FORMAT_AMRWB:
1806 open.read_format = AMRWB_FS;
1807 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001808 default:
1809 pr_err("Invalid format[%d]\n", rd_format);
1810 goto fail_cmd;
1811 }
1812 pr_debug("%s:rdformat[0x%x]wrformat[0x%x]\n", __func__,
1813 open.read_format, open.write_format);
1814
1815 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1816 if (rc < 0) {
1817 pr_err("open failed op[0x%x]rc[%d]\n", \
1818 open.hdr.opcode, rc);
1819 goto fail_cmd;
1820 }
1821 rc = wait_event_timeout(ac->cmd_wait,
1822 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1823 if (!rc) {
1824 pr_err("timeout. waited for OPEN_WRITE rc[%d]\n", rc);
1825 goto fail_cmd;
1826 }
1827 return 0;
1828fail_cmd:
1829 return -EINVAL;
1830}
1831
Laxminath Kasam20824502013-01-07 14:33:56 +05301832int q6asm_open_loopack(struct audio_client *ac)
1833{
1834 int rc = 0x00;
1835 struct asm_stream_cmd_open_loopback open;
1836
1837 if ((ac == NULL) || (ac->apr == NULL)) {
1838 pr_err("APR handle NULL\n");
1839 return -EINVAL;
1840 }
1841 pr_debug("%s: session[%d]", __func__, ac->session);
1842
1843 q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
1844 open.hdr.opcode = ASM_STREAM_CMD_OPEN_LOOPBACK;
1845
1846 open.mode_flags = 0;
1847 open.src_endpointype = 0;
1848 open.sink_endpointype = 0;
1849 /* source endpoint : matrix */
1850 open.postprocopo_id = get_asm_topology();
1851 if (open.postprocopo_id == 0)
1852 open.postprocopo_id = DEFAULT_POPP_TOPOLOGY;
1853
1854 rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
1855 if (rc < 0) {
1856 pr_err("open failed op[0x%x]rc[%d]\n", \
1857 open.hdr.opcode, rc);
1858 goto fail_cmd;
1859 }
1860 rc = wait_event_timeout(ac->cmd_wait,
1861 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1862 if (!rc) {
1863 pr_err("timeout. waited for OPEN_WRITE rc[%d]\n", rc);
1864 goto fail_cmd;
1865 }
1866 return 0;
1867fail_cmd:
1868 return -EINVAL;
1869}
1870
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001871int q6asm_run(struct audio_client *ac, uint32_t flags,
1872 uint32_t msw_ts, uint32_t lsw_ts)
1873{
1874 struct asm_stream_cmd_run run;
1875 int rc;
1876 if (!ac || ac->apr == NULL) {
1877 pr_err("APR handle NULL\n");
1878 return -EINVAL;
1879 }
1880 pr_debug("%s session[%d]", __func__, ac->session);
1881 q6asm_add_hdr(ac, &run.hdr, sizeof(run), TRUE);
1882
1883 run.hdr.opcode = ASM_SESSION_CMD_RUN;
1884 run.flags = flags;
1885 run.msw_ts = msw_ts;
1886 run.lsw_ts = lsw_ts;
Rajesha Kini3498c932011-07-19 19:58:27 +05301887#ifdef CONFIG_DEBUG_FS
1888 if (out_enable_flag) {
1889 do_gettimeofday(&out_cold_tv);
1890 pr_debug("COLD: apr_send_pkt at %ld sec %ld microsec\n",\
1891 out_cold_tv.tv_sec, out_cold_tv.tv_usec);
1892 }
1893#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001894 rc = apr_send_pkt(ac->apr, (uint32_t *) &run);
1895 if (rc < 0) {
1896 pr_err("Commmand run failed[%d]", rc);
1897 goto fail_cmd;
1898 }
1899
1900 rc = wait_event_timeout(ac->cmd_wait,
1901 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1902 if (!rc) {
1903 pr_err("timeout. waited for run success rc[%d]", rc);
1904 goto fail_cmd;
1905 }
1906
1907 return 0;
1908fail_cmd:
1909 return -EINVAL;
1910}
1911
1912int q6asm_run_nowait(struct audio_client *ac, uint32_t flags,
1913 uint32_t msw_ts, uint32_t lsw_ts)
1914{
1915 struct asm_stream_cmd_run run;
1916 int rc;
1917 if (!ac || ac->apr == NULL) {
1918 pr_err("%s:APR handle NULL\n", __func__);
1919 return -EINVAL;
1920 }
1921 pr_debug("session[%d]", ac->session);
1922 q6asm_add_hdr_async(ac, &run.hdr, sizeof(run), TRUE);
1923
1924 run.hdr.opcode = ASM_SESSION_CMD_RUN;
1925 run.flags = flags;
1926 run.msw_ts = msw_ts;
1927 run.lsw_ts = lsw_ts;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001928 rc = apr_send_pkt(ac->apr, (uint32_t *) &run);
1929 if (rc < 0) {
1930 pr_err("%s:Commmand run failed[%d]", __func__, rc);
1931 return -EINVAL;
1932 }
Jay Wang0668d1062012-07-11 18:53:21 -07001933 atomic_inc(&ac->nowait_cmd_cnt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001934 return 0;
1935}
1936
1937
1938int q6asm_enc_cfg_blk_aac(struct audio_client *ac,
1939 uint32_t frames_per_buf,
1940 uint32_t sample_rate, uint32_t channels,
1941 uint32_t bit_rate, uint32_t mode, uint32_t format)
1942{
1943 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1944 int rc = 0;
1945
Harmandeep Singheaf59b42012-06-05 21:46:02 -07001946 pr_debug("%s:session[%d]frames[%d]SR[%d]ch[%d]bitrate[%d]mode[%d] format[%d]",
1947 __func__, ac->session, frames_per_buf,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001948 sample_rate, channels, bit_rate, mode, format);
1949
1950 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1951
1952 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1953 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1954 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1955 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
1956 enc_cfg.enc_blk.format_id = MPEG4_AAC;
1957 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_aac_read_cfg);
1958 enc_cfg.enc_blk.cfg.aac.bitrate = bit_rate;
1959 enc_cfg.enc_blk.cfg.aac.enc_mode = mode;
1960 enc_cfg.enc_blk.cfg.aac.format = format;
1961 enc_cfg.enc_blk.cfg.aac.ch_cfg = channels;
1962 enc_cfg.enc_blk.cfg.aac.sample_rate = sample_rate;
1963
1964 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
1965 if (rc < 0) {
1966 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
1967 rc = -EINVAL;
1968 goto fail_cmd;
1969 }
1970 rc = wait_event_timeout(ac->cmd_wait,
1971 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
1972 if (!rc) {
1973 pr_err("timeout. waited for FORMAT_UPDATE\n");
1974 goto fail_cmd;
1975 }
1976 return 0;
1977fail_cmd:
1978 return -EINVAL;
1979}
1980
1981int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
1982 uint32_t rate, uint32_t channels)
1983{
1984 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
1985
1986 int rc = 0;
1987
1988 pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
1989 ac->session, rate, channels);
1990
1991 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
1992
1993 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
1994 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
1995 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
1996 enc_cfg.enc_blk.frames_per_buf = 1;
1997 enc_cfg.enc_blk.format_id = LINEAR_PCM;
1998 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_pcm_cfg);
1999 enc_cfg.enc_blk.cfg.pcm.ch_cfg = channels;
2000 enc_cfg.enc_blk.cfg.pcm.bits_per_sample = 16;
2001 enc_cfg.enc_blk.cfg.pcm.sample_rate = rate;
2002 enc_cfg.enc_blk.cfg.pcm.is_signed = 1;
2003 enc_cfg.enc_blk.cfg.pcm.interleaved = 1;
2004
2005 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
2006 if (rc < 0) {
2007 pr_err("Comamnd open failed\n");
2008 rc = -EINVAL;
2009 goto fail_cmd;
2010 }
2011 rc = wait_event_timeout(ac->cmd_wait,
2012 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2013 if (!rc) {
2014 pr_err("timeout opcode[0x%x] ", enc_cfg.hdr.opcode);
2015 goto fail_cmd;
2016 }
2017 return 0;
2018fail_cmd:
2019 return -EINVAL;
2020}
2021
Harmandeep Singheaf59b42012-06-05 21:46:02 -07002022int q6asm_enc_cfg_blk_pcm_native(struct audio_client *ac,
2023 uint32_t rate, uint32_t channels)
2024{
2025 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
2026
2027 int rc = 0;
2028
2029 pr_debug("%s: Session %d, rate = %d, channels = %d, setting the rate and channels to 0 for native\n",
2030 __func__, ac->session, rate, channels);
2031
2032 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
2033
2034 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2035 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
2036 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
2037 enc_cfg.enc_blk.frames_per_buf = 1;
2038 enc_cfg.enc_blk.format_id = LINEAR_PCM;
2039 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_pcm_cfg);
2040 enc_cfg.enc_blk.cfg.pcm.ch_cfg = 0;/*channels;*/
2041 enc_cfg.enc_blk.cfg.pcm.bits_per_sample = 16;
2042 enc_cfg.enc_blk.cfg.pcm.sample_rate = 0;/*rate;*/
2043 enc_cfg.enc_blk.cfg.pcm.is_signed = 1;
2044 enc_cfg.enc_blk.cfg.pcm.interleaved = 1;
2045
2046 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
2047 if (rc < 0) {
2048 pr_err("Comamnd open failed\n");
2049 rc = -EINVAL;
2050 goto fail_cmd;
2051 }
2052 rc = wait_event_timeout(ac->cmd_wait,
2053 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2054 if (!rc) {
2055 pr_err("timeout opcode[0x%x] ", enc_cfg.hdr.opcode);
2056 goto fail_cmd;
2057 }
2058 return 0;
2059fail_cmd:
2060 return -EINVAL;
2061}
2062
Mingming Yin647e9ea2012-03-17 19:56:10 -07002063int q6asm_enc_cfg_blk_multi_ch_pcm(struct audio_client *ac,
2064 uint32_t rate, uint32_t channels)
2065{
2066 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
2067
2068 int rc = 0;
2069
2070 pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
2071 ac->session, rate, channels);
2072
2073 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
2074
2075 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2076 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
2077 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
2078 enc_cfg.enc_blk.frames_per_buf = 1;
2079 enc_cfg.enc_blk.format_id = MULTI_CHANNEL_PCM;
2080 enc_cfg.enc_blk.cfg_size =
2081 sizeof(struct asm_multi_channel_pcm_fmt_blk);
2082 enc_cfg.enc_blk.cfg.mpcm.num_channels = channels;
2083 enc_cfg.enc_blk.cfg.mpcm.bits_per_sample = 16;
2084 enc_cfg.enc_blk.cfg.mpcm.sample_rate = rate;
2085 enc_cfg.enc_blk.cfg.mpcm.is_signed = 1;
2086 enc_cfg.enc_blk.cfg.mpcm.is_interleaved = 1;
Subhash Chandra Bose Naripeddy68d103a2012-08-17 21:03:19 -07002087 if (channels == 1) {
2088 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
2089 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = 0;
2090 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = 0;
2091 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[3] = 0;
2092 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[4] = 0;
2093 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[5] = 0;
2094 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[6] = 0;
2095 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[7] = 0;
2096 } else if (channels == 2) {
Subhash Chandra Bose Naripeddy8477d222012-06-12 00:30:54 -07002097 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
2098 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = PCM_CHANNEL_FR;
2099 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = 0;
2100 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[3] = 0;
2101 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[4] = 0;
2102 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[5] = 0;
2103 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[6] = 0;
2104 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[7] = 0;
2105 } else if (channels == 4) {
2106 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
2107 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = PCM_CHANNEL_FR;
2108 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = PCM_CHANNEL_RB;
2109 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[3] = PCM_CHANNEL_LB;
2110 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[4] = 0;
2111 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[5] = 0;
2112 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[6] = 0;
2113 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[7] = 0;
2114 } else if (channels == 6) {
2115 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
2116 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = PCM_CHANNEL_FR;
2117 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = PCM_CHANNEL_LFE;
2118 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[3] = PCM_CHANNEL_FC;
2119 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[4] = PCM_CHANNEL_LB;
2120 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[5] = PCM_CHANNEL_RB;
2121 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[6] = 0;
2122 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[7] = 0;
2123 } else if (channels == 8) {
2124 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
2125 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = PCM_CHANNEL_FR;
2126 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = PCM_CHANNEL_LFE;
2127 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[3] = PCM_CHANNEL_FC;
2128 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[4] = PCM_CHANNEL_LB;
2129 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[5] = PCM_CHANNEL_RB;
2130 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[6] = PCM_CHANNEL_FLC;
2131 enc_cfg.enc_blk.cfg.mpcm.channel_mapping[7] = PCM_CHANNEL_FRC;
2132 }
Mingming Yin647e9ea2012-03-17 19:56:10 -07002133
2134 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
2135 if (rc < 0) {
2136 pr_err("Comamnd open failed\n");
2137 rc = -EINVAL;
2138 goto fail_cmd;
2139 }
2140 rc = wait_event_timeout(ac->cmd_wait,
2141 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2142 if (!rc) {
2143 pr_err("timeout opcode[0x%x] ", enc_cfg.hdr.opcode);
2144 goto fail_cmd;
2145 }
2146 return 0;
2147fail_cmd:
2148 return -EINVAL;
2149}
2150
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002151int q6asm_enable_sbrps(struct audio_client *ac,
2152 uint32_t sbr_ps_enable)
2153{
2154 struct asm_stream_cmd_encdec_sbr sbrps;
2155
2156 int rc = 0;
2157
2158 pr_debug("%s: Session %d\n", __func__, ac->session);
2159
2160 q6asm_add_hdr(ac, &sbrps.hdr, sizeof(sbrps), TRUE);
2161
2162 sbrps.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2163 sbrps.param_id = ASM_ENABLE_SBR_PS;
2164 sbrps.param_size = sizeof(struct asm_sbr_ps);
2165 sbrps.sbr_ps.enable = sbr_ps_enable;
2166
2167 rc = apr_send_pkt(ac->apr, (uint32_t *) &sbrps);
2168 if (rc < 0) {
2169 pr_err("Command opcode[0x%x]paramid[0x%x] failed\n",
2170 ASM_STREAM_CMD_SET_ENCDEC_PARAM,
2171 ASM_ENABLE_SBR_PS);
2172 rc = -EINVAL;
2173 goto fail_cmd;
2174 }
2175 rc = wait_event_timeout(ac->cmd_wait,
2176 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2177 if (!rc) {
2178 pr_err("timeout opcode[0x%x] ", sbrps.hdr.opcode);
2179 goto fail_cmd;
2180 }
2181 return 0;
2182fail_cmd:
2183 return -EINVAL;
2184}
2185
Swaminathan Sathappan70765cd2011-07-19 18:42:47 -07002186int q6asm_cfg_dual_mono_aac(struct audio_client *ac,
2187 uint16_t sce_left, uint16_t sce_right)
2188{
2189 struct asm_stream_cmd_encdec_dualmono dual_mono;
2190
2191 int rc = 0;
2192
2193 pr_debug("%s: Session %d, sce_left = %d, sce_right = %d\n",
2194 __func__, ac->session, sce_left, sce_right);
2195
2196 q6asm_add_hdr(ac, &dual_mono.hdr, sizeof(dual_mono), TRUE);
2197
2198 dual_mono.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2199 dual_mono.param_id = ASM_CONFIGURE_DUAL_MONO;
2200 dual_mono.param_size = sizeof(struct asm_dual_mono);
2201 dual_mono.channel_map.sce_left = sce_left;
2202 dual_mono.channel_map.sce_right = sce_right;
2203
2204 rc = apr_send_pkt(ac->apr, (uint32_t *) &dual_mono);
2205 if (rc < 0) {
2206 pr_err("%s:Command opcode[0x%x]paramid[0x%x] failed\n",
2207 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM,
2208 ASM_CONFIGURE_DUAL_MONO);
2209 rc = -EINVAL;
2210 goto fail_cmd;
2211 }
2212 rc = wait_event_timeout(ac->cmd_wait,
2213 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2214 if (!rc) {
2215 pr_err("%s:timeout opcode[0x%x]\n", __func__,
2216 dual_mono.hdr.opcode);
2217 goto fail_cmd;
2218 }
2219 return 0;
2220fail_cmd:
2221 return -EINVAL;
2222}
2223
Amal Paul6e0f7982013-02-21 19:36:35 -08002224int q6asm_cfg_aac_sel_mix_coef(struct audio_client *ac, uint32_t mix_coeff)
2225{
2226 struct asm_aac_stereo_mix_coeff_selection_param aac_mix_coeff;
2227 int rc = 0;
2228 q6asm_add_hdr(ac, &aac_mix_coeff.hdr, sizeof(aac_mix_coeff), TRUE);
2229 aac_mix_coeff.hdr.opcode =
2230 ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2231 aac_mix_coeff.param_id =
2232 ASM_PARAM_ID_AAC_STEREO_MIX_COEFF_SELECTION_FLAG;
2233 aac_mix_coeff.param_size =
2234 sizeof(struct asm_aac_stereo_mix_coeff_selection_param);
2235 aac_mix_coeff.aac_stereo_mix_coeff_flag = mix_coeff;
2236 pr_debug("%s, mix_coeff = %u", __func__, mix_coeff);
2237 rc = apr_send_pkt(ac->apr, (uint32_t *) &aac_mix_coeff);
2238 if (rc < 0) {
2239 pr_err("%s:Command opcode[0x%x]paramid[0x%x] failed\n",
2240 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM,
2241 ASM_PARAM_ID_AAC_STEREO_MIX_COEFF_SELECTION_FLAG);
2242 rc = -EINVAL;
2243 goto fail_cmd;
2244 }
2245 rc = wait_event_timeout(ac->cmd_wait,
2246 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2247 if (!rc) {
2248 pr_err("%s:timeout opcode[0x%x]\n", __func__,
2249 aac_mix_coeff.hdr.opcode);
2250 goto fail_cmd;
2251 }
2252 return 0;
2253fail_cmd:
2254 return -EINVAL;
2255}
2256
Swaminathan Sathappan6f530882012-05-01 16:42:22 -07002257int q6asm_set_encdec_chan_map(struct audio_client *ac,
2258 uint32_t num_channels)
2259{
2260 struct asm_stream_cmd_encdec_channelmap chan_map;
2261 u8 *channel_mapping;
2262
2263 int rc = 0;
2264
2265 pr_debug("%s: Session %d, num_channels = %d\n",
2266 __func__, ac->session, num_channels);
2267
2268 q6asm_add_hdr(ac, &chan_map.hdr, sizeof(chan_map), TRUE);
2269
2270 chan_map.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2271 chan_map.param_id = ASM_ENCDEC_DEC_CHAN_MAP;
2272 chan_map.param_size = sizeof(struct asm_dec_chan_map);
2273 chan_map.chan_map.num_channels = num_channels;
2274
2275 channel_mapping =
2276 chan_map.chan_map.channel_mapping;
2277
2278 memset(channel_mapping, PCM_CHANNEL_NULL, MAX_CHAN_MAP_CHANNELS);
2279 if (num_channels == 1) {
2280 channel_mapping[0] = PCM_CHANNEL_FL;
2281 } else if (num_channels == 2) {
2282 channel_mapping[0] = PCM_CHANNEL_FL;
2283 channel_mapping[1] = PCM_CHANNEL_FR;
Subhash Chandra Bose Naripeddy68d103a2012-08-17 21:03:19 -07002284 } else if (num_channels == 4) {
2285 channel_mapping[0] = PCM_CHANNEL_FL;
2286 channel_mapping[1] = PCM_CHANNEL_FR;
2287 channel_mapping[1] = PCM_CHANNEL_LB;
2288 channel_mapping[1] = PCM_CHANNEL_RB;
Swaminathan Sathappan6f530882012-05-01 16:42:22 -07002289 } else if (num_channels == 6) {
2290 channel_mapping[0] = PCM_CHANNEL_FC;
2291 channel_mapping[1] = PCM_CHANNEL_FL;
2292 channel_mapping[2] = PCM_CHANNEL_FR;
2293 channel_mapping[3] = PCM_CHANNEL_LB;
2294 channel_mapping[4] = PCM_CHANNEL_RB;
2295 channel_mapping[5] = PCM_CHANNEL_LFE;
Subhash Chandra Bose Naripeddy68d103a2012-08-17 21:03:19 -07002296 } else if (num_channels == 8) {
2297 channel_mapping[0] = PCM_CHANNEL_FC;
2298 channel_mapping[1] = PCM_CHANNEL_FL;
2299 channel_mapping[2] = PCM_CHANNEL_FR;
2300 channel_mapping[3] = PCM_CHANNEL_LB;
2301 channel_mapping[4] = PCM_CHANNEL_RB;
2302 channel_mapping[5] = PCM_CHANNEL_LFE;
2303 channel_mapping[6] = PCM_CHANNEL_FLC;
2304 channel_mapping[7] = PCM_CHANNEL_FRC;
Swaminathan Sathappan6f530882012-05-01 16:42:22 -07002305 } else {
2306 pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
2307 num_channels);
2308 rc = -EINVAL;
2309 goto fail_cmd;
2310 }
2311
2312 rc = apr_send_pkt(ac->apr, (uint32_t *) &chan_map);
2313 if (rc < 0) {
2314 pr_err("%s:Command opcode[0x%x]paramid[0x%x] failed\n",
2315 __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM,
2316 ASM_ENCDEC_DEC_CHAN_MAP);
2317 goto fail_cmd;
2318 }
2319 rc = wait_event_timeout(ac->cmd_wait,
2320 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2321 if (!rc) {
2322 pr_err("%s:timeout opcode[0x%x]\n", __func__,
2323 chan_map.hdr.opcode);
2324 rc = -ETIMEDOUT;
2325 goto fail_cmd;
2326 }
2327 return 0;
2328fail_cmd:
2329 return rc;
2330}
2331
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002332int q6asm_enc_cfg_blk_qcelp(struct audio_client *ac, uint32_t frames_per_buf,
2333 uint16_t min_rate, uint16_t max_rate,
2334 uint16_t reduced_rate_level, uint16_t rate_modulation_cmd)
2335{
2336 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
2337 int rc = 0;
2338
Harmandeep Singheaf59b42012-06-05 21:46:02 -07002339 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]",
2340 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002341 ac->session, frames_per_buf, min_rate, max_rate,
2342 reduced_rate_level, rate_modulation_cmd);
2343
2344 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
2345
2346 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2347
2348 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
2349 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
2350
2351 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
2352 enc_cfg.enc_blk.format_id = V13K_FS;
2353 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_qcelp13_read_cfg);
2354 enc_cfg.enc_blk.cfg.qcelp13.min_rate = min_rate;
2355 enc_cfg.enc_blk.cfg.qcelp13.max_rate = max_rate;
2356 enc_cfg.enc_blk.cfg.qcelp13.reduced_rate_level = reduced_rate_level;
2357 enc_cfg.enc_blk.cfg.qcelp13.rate_modulation_cmd = rate_modulation_cmd;
2358
2359 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
2360 if (rc < 0) {
2361 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
2362 goto fail_cmd;
2363 }
2364 rc = wait_event_timeout(ac->cmd_wait,
2365 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2366 if (!rc) {
2367 pr_err("timeout. waited for FORMAT_UPDATE\n");
2368 goto fail_cmd;
2369 }
2370 return 0;
2371fail_cmd:
2372 return -EINVAL;
2373}
2374
2375int q6asm_enc_cfg_blk_evrc(struct audio_client *ac, uint32_t frames_per_buf,
2376 uint16_t min_rate, uint16_t max_rate,
2377 uint16_t rate_modulation_cmd)
2378{
2379 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
2380 int rc = 0;
2381
Harmandeep Singheaf59b42012-06-05 21:46:02 -07002382 pr_debug("%s:session[%d]frames[%d]min_rate[0x%4x]max_rate[0x%4x] rate_modulation_cmd[0x%4x]",
2383 __func__, ac->session,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002384 frames_per_buf, min_rate, max_rate, rate_modulation_cmd);
2385
2386 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
2387
2388 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2389
2390 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
2391 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
2392
2393 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
2394 enc_cfg.enc_blk.format_id = EVRC_FS;
2395 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_evrc_read_cfg);
2396 enc_cfg.enc_blk.cfg.evrc.min_rate = min_rate;
2397 enc_cfg.enc_blk.cfg.evrc.max_rate = max_rate;
2398 enc_cfg.enc_blk.cfg.evrc.rate_modulation_cmd = rate_modulation_cmd;
2399 enc_cfg.enc_blk.cfg.evrc.reserved = 0;
2400
2401 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
2402 if (rc < 0) {
2403 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
2404 goto fail_cmd;
2405 }
2406 rc = wait_event_timeout(ac->cmd_wait,
2407 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2408 if (!rc) {
2409 pr_err("timeout. waited for FORMAT_UPDATE\n");
2410 goto fail_cmd;
2411 }
2412 return 0;
2413fail_cmd:
2414 return -EINVAL;
2415}
2416
2417int q6asm_enc_cfg_blk_amrnb(struct audio_client *ac, uint32_t frames_per_buf,
2418 uint16_t band_mode, uint16_t dtx_enable)
2419{
2420 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
2421 int rc = 0;
2422
2423 pr_debug("%s:session[%d]frames[%d]band_mode[0x%4x]dtx_enable[0x%4x]",
2424 __func__, ac->session, frames_per_buf, band_mode, dtx_enable);
2425
2426 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
2427
2428 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2429
2430 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
2431 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
2432
2433 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
2434 enc_cfg.enc_blk.format_id = AMRNB_FS;
2435 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_amrnb_read_cfg);
2436 enc_cfg.enc_blk.cfg.amrnb.mode = band_mode;
2437 enc_cfg.enc_blk.cfg.amrnb.dtx_mode = dtx_enable;
2438
2439 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
2440 if (rc < 0) {
2441 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
2442 goto fail_cmd;
2443 }
2444 rc = wait_event_timeout(ac->cmd_wait,
2445 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2446 if (!rc) {
2447 pr_err("timeout. waited for FORMAT_UPDATE\n");
2448 goto fail_cmd;
2449 }
2450 return 0;
2451fail_cmd:
2452 return -EINVAL;
2453}
2454
Alex Wong2caeecc2011-10-28 10:52:15 +05302455int q6asm_enc_cfg_blk_amrwb(struct audio_client *ac, uint32_t frames_per_buf,
2456 uint16_t band_mode, uint16_t dtx_enable)
2457{
2458 struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
2459 int rc = 0;
2460
2461 pr_debug("%s:session[%d]frames[%d]band_mode[0x%4x]dtx_enable[0x%4x]",
2462 __func__, ac->session, frames_per_buf, band_mode, dtx_enable);
2463
2464 q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
2465
2466 enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
2467
2468 enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
2469 enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
2470
2471 enc_cfg.enc_blk.frames_per_buf = frames_per_buf;
2472 enc_cfg.enc_blk.format_id = AMRWB_FS;
2473 enc_cfg.enc_blk.cfg_size = sizeof(struct asm_amrwb_read_cfg);
2474 enc_cfg.enc_blk.cfg.amrwb.mode = band_mode;
2475 enc_cfg.enc_blk.cfg.amrwb.dtx_mode = dtx_enable;
2476
2477 rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
2478 if (rc < 0) {
2479 pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
2480 goto fail_cmd;
2481 }
2482 rc = wait_event_timeout(ac->cmd_wait,
2483 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2484 if (!rc) {
2485 pr_err("timeout. waited for FORMAT_UPDATE\n");
2486 goto fail_cmd;
2487 }
2488 return 0;
2489fail_cmd:
2490 return -EINVAL;
2491}
2492
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002493int q6asm_media_format_block_pcm(struct audio_client *ac,
2494 uint32_t rate, uint32_t channels)
2495{
2496 struct asm_stream_media_format_update fmt;
2497 int rc = 0;
2498
2499 pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
2500 channels);
2501
2502 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2503
2504 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2505
2506 fmt.format = LINEAR_PCM;
2507 fmt.cfg_size = sizeof(struct asm_pcm_cfg);
2508 fmt.write_cfg.pcm_cfg.ch_cfg = channels;
2509 fmt.write_cfg.pcm_cfg.bits_per_sample = 16;
2510 fmt.write_cfg.pcm_cfg.sample_rate = rate;
2511 fmt.write_cfg.pcm_cfg.is_signed = 1;
2512 fmt.write_cfg.pcm_cfg.interleaved = 1;
2513
2514 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2515 if (rc < 0) {
2516 pr_err("%s:Comamnd open failed\n", __func__);
2517 goto fail_cmd;
2518 }
2519 rc = wait_event_timeout(ac->cmd_wait,
2520 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2521 if (!rc) {
2522 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2523 goto fail_cmd;
2524 }
2525 return 0;
2526fail_cmd:
2527 return -EINVAL;
2528}
2529
Flemmard1bc7b1c2014-01-08 00:24:20 -08002530int q6asm_media_format_block_pcm_format_support(struct audio_client *ac,
2531 uint32_t rate, uint32_t channels, uint16_t bit_width)
2532{
2533 struct asm_stream_media_format_update fmt;
2534 int rc = 0;
2535
2536 pr_debug("%s:session[%d]rate[%d]ch[%d]bit_width[%d]\n", __func__,
2537 ac->session, rate, channels, bit_width);
2538
2539 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2540
2541 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2542
2543 fmt.format = LINEAR_PCM;
2544 fmt.cfg_size = sizeof(struct asm_pcm_cfg);
2545 fmt.write_cfg.multi_ch_pcm_cfg.num_channels = channels;
2546 fmt.write_cfg.multi_ch_pcm_cfg.bits_per_sample = bit_width;
2547 fmt.write_cfg.multi_ch_pcm_cfg.sample_rate = rate;
2548 fmt.write_cfg.multi_ch_pcm_cfg.is_signed = 1;
2549 fmt.write_cfg.multi_ch_pcm_cfg.is_interleaved = 1;
2550
2551 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2552 if (rc < 0) {
2553 pr_err("%s:Comamnd open failed\n", __func__);
2554 goto fail_cmd;
2555 }
2556 rc = wait_event_timeout(ac->cmd_wait,
2557 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2558 if (!rc) {
2559 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2560 goto fail_cmd;
2561 }
2562 return 0;
2563fail_cmd:
2564 return -EINVAL;
2565}
2566
Kiran Kandi5e809b02012-01-31 00:24:33 -08002567int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
2568 uint32_t rate, uint32_t channels)
2569{
2570 struct asm_stream_media_format_update fmt;
2571 u8 *channel_mapping;
2572 int rc = 0;
2573
2574 pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
2575 channels);
2576
2577 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2578
2579 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2580
2581 fmt.format = MULTI_CHANNEL_PCM;
2582 fmt.cfg_size = sizeof(struct asm_multi_channel_pcm_fmt_blk);
2583 fmt.write_cfg.multi_ch_pcm_cfg.num_channels = channels;
2584 fmt.write_cfg.multi_ch_pcm_cfg.bits_per_sample = 16;
2585 fmt.write_cfg.multi_ch_pcm_cfg.sample_rate = rate;
2586 fmt.write_cfg.multi_ch_pcm_cfg.is_signed = 1;
2587 fmt.write_cfg.multi_ch_pcm_cfg.is_interleaved = 1;
2588 channel_mapping =
2589 fmt.write_cfg.multi_ch_pcm_cfg.channel_mapping;
2590
2591 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
2592
2593 if (channels == 1) {
2594 channel_mapping[0] = PCM_CHANNEL_FL;
2595 } else if (channels == 2) {
2596 channel_mapping[0] = PCM_CHANNEL_FL;
2597 channel_mapping[1] = PCM_CHANNEL_FR;
Subhash Chandra Bose Naripeddy68d103a2012-08-17 21:03:19 -07002598 } else if (channels == 4) {
2599 channel_mapping[0] = PCM_CHANNEL_FL;
2600 channel_mapping[1] = PCM_CHANNEL_FR;
2601 channel_mapping[1] = PCM_CHANNEL_LB;
2602 channel_mapping[1] = PCM_CHANNEL_RB;
Kiran Kandi5e809b02012-01-31 00:24:33 -08002603 } else if (channels == 6) {
SathishKumar Mani6074b772012-09-26 13:49:49 -07002604 channel_mapping[0] = PCM_CHANNEL_FL;
2605 channel_mapping[1] = PCM_CHANNEL_FR;
2606 channel_mapping[2] = PCM_CHANNEL_FC;
2607 channel_mapping[3] = PCM_CHANNEL_LFE;
2608 channel_mapping[4] = PCM_CHANNEL_LB;
2609 channel_mapping[5] = PCM_CHANNEL_RB;
Subhash Chandra Bose Naripeddy68d103a2012-08-17 21:03:19 -07002610 } else if (channels == 8) {
2611 channel_mapping[0] = PCM_CHANNEL_FC;
2612 channel_mapping[1] = PCM_CHANNEL_FL;
2613 channel_mapping[2] = PCM_CHANNEL_FR;
2614 channel_mapping[3] = PCM_CHANNEL_LB;
2615 channel_mapping[4] = PCM_CHANNEL_RB;
2616 channel_mapping[5] = PCM_CHANNEL_LFE;
2617 channel_mapping[6] = PCM_CHANNEL_FLC;
2618 channel_mapping[7] = PCM_CHANNEL_FRC;
Kiran Kandi5e809b02012-01-31 00:24:33 -08002619 } else {
2620 pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
2621 channels);
2622 return -EINVAL;
2623 }
2624
2625 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2626 if (rc < 0) {
2627 pr_err("%s:Comamnd open failed\n", __func__);
2628 goto fail_cmd;
2629 }
2630 rc = wait_event_timeout(ac->cmd_wait,
2631 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2632 if (!rc) {
2633 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2634 goto fail_cmd;
2635 }
2636 return 0;
2637fail_cmd:
2638 return -EINVAL;
2639}
2640
Flemmard1bc7b1c2014-01-08 00:24:20 -08002641int q6asm_media_format_block_multi_ch_pcm_format_support(
2642 struct audio_client *ac, uint32_t rate,
2643 uint32_t channels, uint16_t bit_width)
2644{
2645 struct asm_stream_media_format_update fmt;
2646 u8 *channel_mapping;
2647 int rc = 0;
2648
2649 pr_debug("%s:session[%d]rate[%d]ch[%d]bit_width[%d]\n", __func__,
2650 ac->session, rate, channels, bit_width);
2651
2652 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2653
2654 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2655
2656 fmt.format = MULTI_CHANNEL_PCM;
2657 fmt.cfg_size = sizeof(struct asm_multi_channel_pcm_fmt_blk);
2658 fmt.write_cfg.multi_ch_pcm_cfg.num_channels = channels;
2659 fmt.write_cfg.multi_ch_pcm_cfg.bits_per_sample = bit_width;
2660 fmt.write_cfg.multi_ch_pcm_cfg.sample_rate = rate;
2661 fmt.write_cfg.multi_ch_pcm_cfg.is_signed = 1;
2662 fmt.write_cfg.multi_ch_pcm_cfg.is_interleaved = 1;
2663 channel_mapping =
2664 fmt.write_cfg.multi_ch_pcm_cfg.channel_mapping;
2665
2666 memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
2667
2668 if (channels == 1) {
2669 channel_mapping[0] = PCM_CHANNEL_FL;
2670 } else if (channels == 2) {
2671 channel_mapping[0] = PCM_CHANNEL_FL;
2672 channel_mapping[1] = PCM_CHANNEL_FR;
2673 } else if (channels == 4) {
2674 channel_mapping[0] = PCM_CHANNEL_FL;
2675 channel_mapping[1] = PCM_CHANNEL_FR;
2676 channel_mapping[1] = PCM_CHANNEL_LB;
2677 channel_mapping[1] = PCM_CHANNEL_RB;
2678 } else if (channels == 6) {
2679 channel_mapping[0] = PCM_CHANNEL_FL;
2680 channel_mapping[1] = PCM_CHANNEL_FR;
2681 channel_mapping[2] = PCM_CHANNEL_FC;
2682 channel_mapping[3] = PCM_CHANNEL_LFE;
2683 channel_mapping[4] = PCM_CHANNEL_LB;
2684 channel_mapping[5] = PCM_CHANNEL_RB;
2685 } else if (channels == 8) {
2686 channel_mapping[0] = PCM_CHANNEL_FC;
2687 channel_mapping[1] = PCM_CHANNEL_FL;
2688 channel_mapping[2] = PCM_CHANNEL_FR;
2689 channel_mapping[3] = PCM_CHANNEL_LB;
2690 channel_mapping[4] = PCM_CHANNEL_RB;
2691 channel_mapping[5] = PCM_CHANNEL_LFE;
2692 channel_mapping[6] = PCM_CHANNEL_FLC;
2693 channel_mapping[7] = PCM_CHANNEL_FRC;
2694 } else {
2695 pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
2696 channels);
2697 return -EINVAL;
2698 }
2699
2700 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2701 if (rc < 0) {
2702 pr_err("%s:Comamnd open failed\n", __func__);
2703 goto fail_cmd;
2704 }
2705 rc = wait_event_timeout(ac->cmd_wait,
2706 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2707 if (!rc) {
2708 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2709 goto fail_cmd;
2710 }
2711 return 0;
2712fail_cmd:
2713 return -EINVAL;
2714}
2715
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002716int q6asm_media_format_block_aac(struct audio_client *ac,
2717 struct asm_aac_cfg *cfg)
2718{
2719 struct asm_stream_media_format_update fmt;
2720 int rc = 0;
2721
2722 pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session,
2723 cfg->sample_rate, cfg->ch_cfg);
2724
2725 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2726
2727 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2728
2729 fmt.format = MPEG4_AAC;
2730 fmt.cfg_size = sizeof(struct asm_aac_cfg);
2731 fmt.write_cfg.aac_cfg.format = cfg->format;
2732 fmt.write_cfg.aac_cfg.aot = cfg->aot;
2733 fmt.write_cfg.aac_cfg.ep_config = cfg->ep_config;
2734 fmt.write_cfg.aac_cfg.section_data_resilience =
2735 cfg->section_data_resilience;
2736 fmt.write_cfg.aac_cfg.scalefactor_data_resilience =
2737 cfg->scalefactor_data_resilience;
2738 fmt.write_cfg.aac_cfg.spectral_data_resilience =
2739 cfg->spectral_data_resilience;
2740 fmt.write_cfg.aac_cfg.ch_cfg = cfg->ch_cfg;
2741 fmt.write_cfg.aac_cfg.sample_rate = cfg->sample_rate;
2742 pr_info("%s:format=%x cfg_size=%d aac-cfg=%x aot=%d ch=%d sr=%d\n",
2743 __func__, fmt.format, fmt.cfg_size,
2744 fmt.write_cfg.aac_cfg.format,
2745 fmt.write_cfg.aac_cfg.aot,
2746 fmt.write_cfg.aac_cfg.ch_cfg,
2747 fmt.write_cfg.aac_cfg.sample_rate);
2748 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2749 if (rc < 0) {
2750 pr_err("%s:Comamnd open failed\n", __func__);
2751 goto fail_cmd;
2752 }
2753 rc = wait_event_timeout(ac->cmd_wait,
2754 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2755 if (!rc) {
2756 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2757 goto fail_cmd;
2758 }
2759 return 0;
2760fail_cmd:
2761 return -EINVAL;
2762}
2763
Ajit Khare43fd8832012-08-07 13:19:44 -07002764int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
2765 struct asm_amrwbplus_cfg *cfg)
2766{
2767 struct asm_stream_media_format_update fmt;
2768 int rc = 0;
2769 pr_debug("q6asm_media_format_block_amrwbplus");
Bharath Ramachandramurthy4f71d502011-10-23 19:45:22 -07002770
Ajit Khare43fd8832012-08-07 13:19:44 -07002771 pr_debug("%s:session[%d]band-mode[%d]frame-fmt[%d]ch[%d]\n",
2772 __func__,
2773 ac->session,
2774 cfg->amr_band_mode,
2775 cfg->amr_frame_fmt,
2776 cfg->num_channels);
2777
2778 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2779
2780 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2781
2782 fmt.format = AMR_WB_PLUS;
2783 fmt.cfg_size = cfg->size_bytes;
2784
2785 fmt.write_cfg.amrwbplus_cfg.size_bytes = cfg->size_bytes;
2786 fmt.write_cfg.amrwbplus_cfg.version = cfg->version;
2787 fmt.write_cfg.amrwbplus_cfg.num_channels = cfg->num_channels;
2788 fmt.write_cfg.amrwbplus_cfg.amr_band_mode = cfg->amr_band_mode;
2789 fmt.write_cfg.amrwbplus_cfg.amr_dtx_mode = cfg->amr_dtx_mode;
2790 fmt.write_cfg.amrwbplus_cfg.amr_frame_fmt = cfg->amr_frame_fmt;
2791 fmt.write_cfg.amrwbplus_cfg.amr_lsf_idx = cfg->amr_lsf_idx;
2792
2793 pr_debug("%s: num_channels=%x amr_band_mode=%d amr_frame_fmt=%d\n",
2794 __func__,
2795 cfg->num_channels,
2796 cfg->amr_band_mode,
2797 cfg->amr_frame_fmt);
2798
2799 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2800 if (rc < 0) {
2801 pr_err("%s:Comamnd media format update failed..\n", __func__);
2802 goto fail_cmd;
2803 }
2804 rc = wait_event_timeout(ac->cmd_wait,
2805 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2806 if (!rc) {
2807 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2808 goto fail_cmd;
2809 }
2810 return 0;
2811fail_cmd:
2812 return -EINVAL;
2813}
Bharath Ramachandramurthy4f71d502011-10-23 19:45:22 -07002814int q6asm_media_format_block_multi_aac(struct audio_client *ac,
2815 struct asm_aac_cfg *cfg)
2816{
2817 struct asm_stream_media_format_update fmt;
2818 int rc = 0;
2819
2820 pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session,
2821 cfg->sample_rate, cfg->ch_cfg);
2822
2823 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2824
2825 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2826
2827 fmt.format = MPEG4_MULTI_AAC;
2828 fmt.cfg_size = sizeof(struct asm_aac_cfg);
2829 fmt.write_cfg.aac_cfg.format = cfg->format;
2830 fmt.write_cfg.aac_cfg.aot = cfg->aot;
2831 fmt.write_cfg.aac_cfg.ep_config = cfg->ep_config;
2832 fmt.write_cfg.aac_cfg.section_data_resilience =
2833 cfg->section_data_resilience;
2834 fmt.write_cfg.aac_cfg.scalefactor_data_resilience =
2835 cfg->scalefactor_data_resilience;
2836 fmt.write_cfg.aac_cfg.spectral_data_resilience =
2837 cfg->spectral_data_resilience;
2838 fmt.write_cfg.aac_cfg.ch_cfg = cfg->ch_cfg;
2839 fmt.write_cfg.aac_cfg.sample_rate = cfg->sample_rate;
2840 pr_info("%s:format=%x cfg_size=%d aac-cfg=%x aot=%d ch=%d sr=%d\n",
2841 __func__, fmt.format, fmt.cfg_size,
2842 fmt.write_cfg.aac_cfg.format,
2843 fmt.write_cfg.aac_cfg.aot,
2844 fmt.write_cfg.aac_cfg.ch_cfg,
2845 fmt.write_cfg.aac_cfg.sample_rate);
2846 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2847 if (rc < 0) {
2848 pr_err("%s:Comamnd open failed\n", __func__);
2849 goto fail_cmd;
2850 }
2851 rc = wait_event_timeout(ac->cmd_wait,
2852 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2853 if (!rc) {
2854 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2855 goto fail_cmd;
2856 }
2857 return 0;
2858fail_cmd:
2859 return -EINVAL;
2860}
2861
2862
Alex Wong2caeecc2011-10-28 10:52:15 +05302863
2864int q6asm_media_format_block(struct audio_client *ac, uint32_t format)
2865{
2866
2867 struct asm_stream_media_format_update fmt;
2868 int rc = 0;
2869
2870 pr_debug("%s:session[%d] format[0x%x]\n", __func__,
2871 ac->session, format);
2872
2873 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2874 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
Asish Bhattacharya305d1752011-11-01 20:38:26 +05302875 switch (format) {
2876 case FORMAT_V13K:
2877 fmt.format = V13K_FS;
2878 break;
2879 case FORMAT_EVRC:
2880 fmt.format = EVRC_FS;
2881 break;
2882 case FORMAT_AMRWB:
2883 fmt.format = AMRWB_FS;
2884 break;
Ajit Khare43fd8832012-08-07 13:19:44 -07002885 case FORMAT_AMR_WB_PLUS:
2886 fmt.format = AMR_WB_PLUS;
2887 break;
Asish Bhattacharya305d1752011-11-01 20:38:26 +05302888 case FORMAT_AMRNB:
2889 fmt.format = AMRNB_FS;
2890 break;
2891 case FORMAT_MP3:
2892 fmt.format = MP3;
2893 break;
Srikanth Uyyala66f781a2012-06-13 23:23:25 +05302894 case FORMAT_DTS:
2895 fmt.format = DTS;
2896 break;
2897 case FORMAT_DTS_LBR:
2898 fmt.format = DTS_LBR;
2899 break;
Asish Bhattacharya305d1752011-11-01 20:38:26 +05302900 default:
2901 pr_err("Invalid format[%d]\n", format);
2902 goto fail_cmd;
2903 }
Alex Wong2caeecc2011-10-28 10:52:15 +05302904 fmt.cfg_size = 0;
2905
2906 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2907 if (rc < 0) {
2908 pr_err("%s:Comamnd open failed\n", __func__);
2909 goto fail_cmd;
2910 }
2911 rc = wait_event_timeout(ac->cmd_wait,
2912 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2913 if (!rc) {
2914 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2915 goto fail_cmd;
2916 }
2917 return 0;
2918fail_cmd:
2919 return -EINVAL;
2920}
2921
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002922int q6asm_media_format_block_wma(struct audio_client *ac,
2923 void *cfg)
2924{
2925 struct asm_stream_media_format_update fmt;
2926 struct asm_wma_cfg *wma_cfg = (struct asm_wma_cfg *)cfg;
2927 int rc = 0;
2928
Harmandeep Singheaf59b42012-06-05 21:46:02 -07002929 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 -07002930 ac->session, wma_cfg->format_tag, wma_cfg->sample_rate,
2931 wma_cfg->ch_cfg, wma_cfg->avg_bytes_per_sec,
2932 wma_cfg->block_align, wma_cfg->valid_bits_per_sample,
2933 wma_cfg->ch_mask, wma_cfg->encode_opt);
2934
2935 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2936
2937 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2938
2939 fmt.format = WMA_V9;
2940 fmt.cfg_size = sizeof(struct asm_wma_cfg);
2941 fmt.write_cfg.wma_cfg.format_tag = wma_cfg->format_tag;
2942 fmt.write_cfg.wma_cfg.ch_cfg = wma_cfg->ch_cfg;
2943 fmt.write_cfg.wma_cfg.sample_rate = wma_cfg->sample_rate;
2944 fmt.write_cfg.wma_cfg.avg_bytes_per_sec = wma_cfg->avg_bytes_per_sec;
2945 fmt.write_cfg.wma_cfg.block_align = wma_cfg->block_align;
2946 fmt.write_cfg.wma_cfg.valid_bits_per_sample =
2947 wma_cfg->valid_bits_per_sample;
2948 fmt.write_cfg.wma_cfg.ch_mask = wma_cfg->ch_mask;
2949 fmt.write_cfg.wma_cfg.encode_opt = wma_cfg->encode_opt;
2950 fmt.write_cfg.wma_cfg.adv_encode_opt = 0;
2951 fmt.write_cfg.wma_cfg.adv_encode_opt2 = 0;
2952 fmt.write_cfg.wma_cfg.drc_peak_ref = 0;
2953 fmt.write_cfg.wma_cfg.drc_peak_target = 0;
2954 fmt.write_cfg.wma_cfg.drc_ave_ref = 0;
2955 fmt.write_cfg.wma_cfg.drc_ave_target = 0;
2956
2957 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
2958 if (rc < 0) {
2959 pr_err("%s:Comamnd open failed\n", __func__);
2960 goto fail_cmd;
2961 }
2962 rc = wait_event_timeout(ac->cmd_wait,
2963 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
2964 if (!rc) {
2965 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
2966 goto fail_cmd;
2967 }
2968 return 0;
2969fail_cmd:
2970 return -EINVAL;
2971}
2972
2973int q6asm_media_format_block_wmapro(struct audio_client *ac,
2974 void *cfg)
2975{
2976 struct asm_stream_media_format_update fmt;
2977 struct asm_wmapro_cfg *wmapro_cfg = (struct asm_wmapro_cfg *)cfg;
2978 int rc = 0;
2979
Harmandeep Singheaf59b42012-06-05 21:46:02 -07002980 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 -07002981 ac->session, wmapro_cfg->format_tag, wmapro_cfg->sample_rate,
2982 wmapro_cfg->ch_cfg, wmapro_cfg->avg_bytes_per_sec,
2983 wmapro_cfg->block_align, wmapro_cfg->valid_bits_per_sample,
2984 wmapro_cfg->ch_mask, wmapro_cfg->encode_opt,
2985 wmapro_cfg->adv_encode_opt, wmapro_cfg->adv_encode_opt2);
2986
2987 q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
2988
2989 fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
2990
2991 fmt.format = WMA_V10PRO;
2992 fmt.cfg_size = sizeof(struct asm_wmapro_cfg);
2993 fmt.write_cfg.wmapro_cfg.format_tag = wmapro_cfg->format_tag;
2994 fmt.write_cfg.wmapro_cfg.ch_cfg = wmapro_cfg->ch_cfg;
2995 fmt.write_cfg.wmapro_cfg.sample_rate = wmapro_cfg->sample_rate;
2996 fmt.write_cfg.wmapro_cfg.avg_bytes_per_sec =
2997 wmapro_cfg->avg_bytes_per_sec;
2998 fmt.write_cfg.wmapro_cfg.block_align = wmapro_cfg->block_align;
2999 fmt.write_cfg.wmapro_cfg.valid_bits_per_sample =
3000 wmapro_cfg->valid_bits_per_sample;
3001 fmt.write_cfg.wmapro_cfg.ch_mask = wmapro_cfg->ch_mask;
3002 fmt.write_cfg.wmapro_cfg.encode_opt = wmapro_cfg->encode_opt;
3003 fmt.write_cfg.wmapro_cfg.adv_encode_opt = wmapro_cfg->adv_encode_opt;
3004 fmt.write_cfg.wmapro_cfg.adv_encode_opt2 = wmapro_cfg->adv_encode_opt2;
3005 fmt.write_cfg.wmapro_cfg.drc_peak_ref = 0;
3006 fmt.write_cfg.wmapro_cfg.drc_peak_target = 0;
3007 fmt.write_cfg.wmapro_cfg.drc_ave_ref = 0;
3008 fmt.write_cfg.wmapro_cfg.drc_ave_target = 0;
3009
3010 rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
3011 if (rc < 0) {
3012 pr_err("%s:Comamnd open failed\n", __func__);
3013 goto fail_cmd;
3014 }
3015 rc = wait_event_timeout(ac->cmd_wait,
3016 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
3017 if (!rc) {
3018 pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
3019 goto fail_cmd;
3020 }
3021 return 0;
3022fail_cmd:
3023 return -EINVAL;
3024}
3025
3026int q6asm_memory_map(struct audio_client *ac, uint32_t buf_add, int dir,
3027 uint32_t bufsz, uint32_t bufcnt)
3028{
3029 struct asm_stream_cmd_memory_map mem_map;
3030 int rc = 0;
3031
3032 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
3033 pr_err("APR handle NULL\n");
3034 return -EINVAL;
3035 }
3036
3037 pr_debug("%s: Session[%d]\n", __func__, ac->session);
3038
3039 mem_map.hdr.opcode = ASM_SESSION_CMD_MEMORY_MAP;
3040
3041 mem_map.buf_add = buf_add;
3042 mem_map.buf_size = bufsz * bufcnt;
3043 mem_map.mempool_id = 0; /* EBI */
3044 mem_map.reserved = 0;
3045
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303046 pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
3047 mem_map.hdr.token = (uint32_t)ac;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003048 q6asm_add_mmaphdr(&mem_map.hdr,
3049 sizeof(struct asm_stream_cmd_memory_map), TRUE);
3050
3051 pr_debug("buf add[%x] buf_add_parameter[%x]\n",
3052 mem_map.buf_add, buf_add);
3053
3054 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_map);
3055 if (rc < 0) {
3056 pr_err("mem_map op[0x%x]rc[%d]\n",
3057 mem_map.hdr.opcode, rc);
3058 rc = -EINVAL;
3059 goto fail_cmd;
3060 }
3061
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303062 rc = wait_event_timeout(ac->cmd_wait,
3063 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003064 if (!rc) {
3065 pr_err("timeout. waited for memory_map\n");
3066 rc = -EINVAL;
3067 goto fail_cmd;
3068 }
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303069 if (atomic_read(&ac->cmd_response)) {
3070 pr_err("%s: ASM_SESSION_CMD_MEMORY_MAP cmd failed\n", __func__);
3071 rc = -EINVAL;
3072 goto fail_cmd;
3073 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003074 rc = 0;
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303075
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003076fail_cmd:
3077 return rc;
3078}
3079
3080int q6asm_memory_unmap(struct audio_client *ac, uint32_t buf_add, int dir)
3081{
3082 struct asm_stream_cmd_memory_unmap mem_unmap;
3083 int rc = 0;
3084
3085 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
3086 pr_err("APR handle NULL\n");
3087 return -EINVAL;
3088 }
3089 pr_debug("%s: Session[%d]\n", __func__, ac->session);
3090
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303091 pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
3092 mem_unmap.hdr.token = (uint32_t)ac;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003093 q6asm_add_mmaphdr(&mem_unmap.hdr,
3094 sizeof(struct asm_stream_cmd_memory_unmap), TRUE);
3095 mem_unmap.hdr.opcode = ASM_SESSION_CMD_MEMORY_UNMAP;
3096 mem_unmap.buf_add = buf_add;
3097
3098 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_unmap);
3099 if (rc < 0) {
3100 pr_err("mem_unmap op[0x%x]rc[%d]\n",
3101 mem_unmap.hdr.opcode, rc);
3102 rc = -EINVAL;
3103 goto fail_cmd;
3104 }
3105
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303106 rc = wait_event_timeout(ac->cmd_wait,
3107 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003108 if (!rc) {
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303109 pr_err("timeout. waited for memory_unmap\n");
3110 rc = -EINVAL;
3111 goto fail_cmd;
3112 }
3113 if (atomic_read(&ac->cmd_response)) {
3114 pr_err("%s: ASM_SESSION_CMD_MEMORY_UNMAP cmd failed\n",
3115 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003116 rc = -EINVAL;
3117 goto fail_cmd;
3118 }
3119 rc = 0;
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303120
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003121fail_cmd:
3122 return rc;
3123}
3124
3125int q6asm_set_lrgain(struct audio_client *ac, int left_gain, int right_gain)
3126{
3127 void *vol_cmd = NULL;
3128 void *payload = NULL;
3129 struct asm_pp_params_command *cmd = NULL;
3130 struct asm_lrchannel_gain_params *lrgain = NULL;
3131 int sz = 0;
3132 int rc = 0;
3133
3134 sz = sizeof(struct asm_pp_params_command) +
3135 + sizeof(struct asm_lrchannel_gain_params);
3136 vol_cmd = kzalloc(sz, GFP_KERNEL);
3137 if (vol_cmd == NULL) {
3138 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
3139 rc = -EINVAL;
3140 return rc;
3141 }
3142 cmd = (struct asm_pp_params_command *)vol_cmd;
3143 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
3144 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
3145 cmd->payload = NULL;
3146 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
3147 sizeof(struct asm_lrchannel_gain_params);
3148 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
3149 cmd->params.param_id = L_R_CHANNEL_GAIN_PARAM_ID;
3150 cmd->params.param_size = sizeof(struct asm_lrchannel_gain_params);
3151 cmd->params.reserved = 0;
3152
3153 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
3154 lrgain = (struct asm_lrchannel_gain_params *)payload;
3155
3156 lrgain->left_gain = left_gain;
3157 lrgain->right_gain = right_gain;
3158 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
3159 if (rc < 0) {
3160 pr_err("%s: Volume Command failed\n", __func__);
3161 rc = -EINVAL;
3162 goto fail_cmd;
3163 }
3164
3165 rc = wait_event_timeout(ac->cmd_wait,
3166 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
3167 if (!rc) {
3168 pr_err("%s: timeout in sending volume command to apr\n",
3169 __func__);
3170 rc = -EINVAL;
3171 goto fail_cmd;
3172 }
3173 rc = 0;
3174fail_cmd:
3175 kfree(vol_cmd);
3176 return rc;
3177}
3178
3179static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
3180 uint32_t bufsz, uint32_t bufcnt)
3181{
3182 struct asm_stream_cmd_memory_map_regions *mmap_regions = NULL;
3183 struct asm_memory_map_regions *mregions = NULL;
3184 struct audio_port_data *port = NULL;
3185 struct audio_buffer *ab = NULL;
3186 void *mmap_region_cmd = NULL;
3187 void *payload = NULL;
3188 int rc = 0;
3189 int i = 0;
3190 int cmd_size = 0;
3191
3192 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
3193 pr_err("APR handle NULL\n");
3194 return -EINVAL;
3195 }
3196 pr_debug("%s: Session[%d]\n", __func__, ac->session);
3197
3198 cmd_size = sizeof(struct asm_stream_cmd_memory_map_regions)
3199 + sizeof(struct asm_memory_map_regions) * bufcnt;
3200
3201 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
Vasudeva Rao Thumati86edf6c2011-07-06 16:25:13 +05303202 if (mmap_region_cmd == NULL) {
3203 pr_err("%s: Mem alloc failed\n", __func__);
3204 rc = -EINVAL;
3205 return rc;
3206 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003207 mmap_regions = (struct asm_stream_cmd_memory_map_regions *)
3208 mmap_region_cmd;
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303209 mmap_regions->hdr.token = (uint32_t)ac;
3210 pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003211 q6asm_add_mmaphdr(&mmap_regions->hdr, cmd_size, TRUE);
3212 mmap_regions->hdr.opcode = ASM_SESSION_CMD_MEMORY_MAP_REGIONS;
3213 mmap_regions->mempool_id = 0;
3214 mmap_regions->nregions = bufcnt & 0x00ff;
3215 pr_debug("map_regions->nregions = %d\n", mmap_regions->nregions);
3216 payload = ((u8 *) mmap_region_cmd +
3217 sizeof(struct asm_stream_cmd_memory_map_regions));
3218 mregions = (struct asm_memory_map_regions *)payload;
3219
3220 port = &ac->port[dir];
3221 for (i = 0; i < bufcnt; i++) {
3222 ab = &port->buf[i];
3223 mregions->phys = ab->phys;
3224 mregions->buf_size = ab->size;
3225 ++mregions;
3226 }
3227
3228 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) mmap_region_cmd);
3229 if (rc < 0) {
3230 pr_err("mmap_regions op[0x%x]rc[%d]\n",
3231 mmap_regions->hdr.opcode, rc);
3232 rc = -EINVAL;
3233 goto fail_cmd;
3234 }
3235
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303236 rc = wait_event_timeout(ac->cmd_wait,
3237 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003238 if (!rc) {
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303239 pr_err("timeout. waited for map_regions\n");
3240 rc = -EINVAL;
3241 goto fail_cmd;
3242 }
3243 if (atomic_read(&ac->cmd_response)) {
3244 pr_err("%s: ASM_SESSION_CMD_MEMORY_MAP_REGIONS cmd failed\n",
3245 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003246 rc = -EINVAL;
3247 goto fail_cmd;
3248 }
3249 rc = 0;
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303250
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003251fail_cmd:
3252 kfree(mmap_region_cmd);
3253 return rc;
3254}
3255
3256static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir,
3257 uint32_t bufsz, uint32_t bufcnt)
3258{
3259 struct asm_stream_cmd_memory_unmap_regions *unmap_regions = NULL;
3260 struct asm_memory_unmap_regions *mregions = NULL;
3261 struct audio_port_data *port = NULL;
3262 struct audio_buffer *ab = NULL;
3263 void *unmap_region_cmd = NULL;
3264 void *payload = NULL;
3265 int rc = 0;
3266 int i = 0;
3267 int cmd_size = 0;
3268
3269 if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
3270 pr_err("APR handle NULL\n");
3271 return -EINVAL;
3272 }
3273 pr_debug("%s: Session[%d]\n", __func__, ac->session);
3274
3275 cmd_size = sizeof(struct asm_stream_cmd_memory_unmap_regions) +
3276 sizeof(struct asm_memory_unmap_regions) * bufcnt;
3277
3278 unmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
Vasudeva Rao Thumati86edf6c2011-07-06 16:25:13 +05303279 if (unmap_region_cmd == NULL) {
3280 pr_err("%s: Mem alloc failed\n", __func__);
3281 rc = -EINVAL;
3282 return rc;
3283 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003284 unmap_regions = (struct asm_stream_cmd_memory_unmap_regions *)
3285 unmap_region_cmd;
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303286 unmap_regions->hdr.token = (uint32_t)ac;
3287 pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003288 q6asm_add_mmaphdr(&unmap_regions->hdr, cmd_size, TRUE);
3289 unmap_regions->hdr.opcode = ASM_SESSION_CMD_MEMORY_UNMAP_REGIONS;
3290 unmap_regions->nregions = bufcnt & 0x00ff;
3291 pr_debug("unmap_regions->nregions = %d\n", unmap_regions->nregions);
3292 payload = ((u8 *) unmap_region_cmd +
3293 sizeof(struct asm_stream_cmd_memory_unmap_regions));
3294 mregions = (struct asm_memory_unmap_regions *)payload;
3295 port = &ac->port[dir];
3296 for (i = 0; i < bufcnt; i++) {
3297 ab = &port->buf[i];
3298 mregions->phys = ab->phys;
3299 ++mregions;
3300 }
3301
3302 rc = apr_send_pkt(this_mmap.apr, (uint32_t *) unmap_region_cmd);
3303 if (rc < 0) {
3304 pr_err("mmap_regions op[0x%x]rc[%d]\n",
3305 unmap_regions->hdr.opcode, rc);
3306 goto fail_cmd;
3307 }
3308
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303309 rc = wait_event_timeout(ac->cmd_wait,
3310 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003311 if (!rc) {
Deepa Madiregama636f80e2013-01-17 14:01:25 +05303312 pr_err("timeout. waited for unmap_regions\n");
3313 rc = -EINVAL;
3314 goto fail_cmd;
3315 }
3316 if (atomic_read(&ac->cmd_response)) {
3317 pr_err("%s: ASM_SESSION_CMD_MEMORY_UNMAP_REGIONS cmd failed\n",
3318 __func__);
3319 rc = -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003320 goto fail_cmd;
3321 }
3322 rc = 0;
3323
3324fail_cmd:
3325 kfree(unmap_region_cmd);
3326 return rc;
3327}
3328
3329int q6asm_set_mute(struct audio_client *ac, int muteflag)
3330{
3331 void *vol_cmd = NULL;
3332 void *payload = NULL;
3333 struct asm_pp_params_command *cmd = NULL;
3334 struct asm_mute_params *mute = NULL;
3335 int sz = 0;
3336 int rc = 0;
3337
3338 sz = sizeof(struct asm_pp_params_command) +
3339 + sizeof(struct asm_mute_params);
3340 vol_cmd = kzalloc(sz, GFP_KERNEL);
3341 if (vol_cmd == NULL) {
3342 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
3343 rc = -EINVAL;
3344 return rc;
3345 }
3346 cmd = (struct asm_pp_params_command *)vol_cmd;
3347 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
3348 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
3349 cmd->payload = NULL;
3350 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
3351 sizeof(struct asm_mute_params);
3352 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
3353 cmd->params.param_id = MUTE_CONFIG_PARAM_ID;
3354 cmd->params.param_size = sizeof(struct asm_mute_params);
3355 cmd->params.reserved = 0;
3356
3357 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
3358 mute = (struct asm_mute_params *)payload;
3359
3360 mute->muteflag = muteflag;
3361 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
3362 if (rc < 0) {
3363 pr_err("%s: Mute Command failed\n", __func__);
3364 rc = -EINVAL;
3365 goto fail_cmd;
3366 }
3367
3368 rc = wait_event_timeout(ac->cmd_wait,
3369 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
3370 if (!rc) {
3371 pr_err("%s: timeout in sending mute command to apr\n",
3372 __func__);
3373 rc = -EINVAL;
3374 goto fail_cmd;
3375 }
3376 rc = 0;
3377fail_cmd:
3378 kfree(vol_cmd);
3379 return rc;
3380}
3381
3382int q6asm_set_volume(struct audio_client *ac, int volume)
3383{
3384 void *vol_cmd = NULL;
3385 void *payload = NULL;
3386 struct asm_pp_params_command *cmd = NULL;
3387 struct asm_master_gain_params *mgain = NULL;
3388 int sz = 0;
3389 int rc = 0;
3390
3391 sz = sizeof(struct asm_pp_params_command) +
3392 + sizeof(struct asm_master_gain_params);
3393 vol_cmd = kzalloc(sz, GFP_KERNEL);
3394 if (vol_cmd == NULL) {
3395 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
3396 rc = -EINVAL;
3397 return rc;
3398 }
3399 cmd = (struct asm_pp_params_command *)vol_cmd;
3400 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
3401 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
3402 cmd->payload = NULL;
3403 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
3404 sizeof(struct asm_master_gain_params);
3405 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
3406 cmd->params.param_id = MASTER_GAIN_PARAM_ID;
3407 cmd->params.param_size = sizeof(struct asm_master_gain_params);
3408 cmd->params.reserved = 0;
3409
3410 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
3411 mgain = (struct asm_master_gain_params *)payload;
3412
3413 mgain->master_gain = volume;
3414 mgain->padding = 0x00;
3415 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
3416 if (rc < 0) {
3417 pr_err("%s: Volume Command failed\n", __func__);
3418 rc = -EINVAL;
3419 goto fail_cmd;
3420 }
3421
3422 rc = wait_event_timeout(ac->cmd_wait,
3423 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
3424 if (!rc) {
3425 pr_err("%s: timeout in sending volume command to apr\n",
3426 __func__);
3427 rc = -EINVAL;
3428 goto fail_cmd;
3429 }
3430 rc = 0;
3431fail_cmd:
3432 kfree(vol_cmd);
3433 return rc;
3434}
3435
3436int q6asm_set_softpause(struct audio_client *ac,
3437 struct asm_softpause_params *pause_param)
3438{
3439 void *vol_cmd = NULL;
3440 void *payload = NULL;
3441 struct asm_pp_params_command *cmd = NULL;
3442 struct asm_softpause_params *params = NULL;
3443 int sz = 0;
3444 int rc = 0;
3445
3446 sz = sizeof(struct asm_pp_params_command) +
3447 + sizeof(struct asm_softpause_params);
3448 vol_cmd = kzalloc(sz, GFP_KERNEL);
3449 if (vol_cmd == NULL) {
3450 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
3451 rc = -EINVAL;
3452 return rc;
3453 }
3454 cmd = (struct asm_pp_params_command *)vol_cmd;
3455 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
3456 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
3457 cmd->payload = NULL;
3458 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
3459 sizeof(struct asm_softpause_params);
3460 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
3461 cmd->params.param_id = SOFT_PAUSE_PARAM_ID;
3462 cmd->params.param_size = sizeof(struct asm_softpause_params);
3463 cmd->params.reserved = 0;
3464
3465 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
3466 params = (struct asm_softpause_params *)payload;
3467
3468 params->enable = pause_param->enable;
3469 params->period = pause_param->period;
3470 params->step = pause_param->step;
3471 params->rampingcurve = pause_param->rampingcurve;
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003472 pr_debug("%s: soft Pause Command: enable = %d, period = %d, step = %d, curve = %d\n",
3473 __func__, params->enable,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003474 params->period, params->step, params->rampingcurve);
3475 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
3476 if (rc < 0) {
3477 pr_err("%s: Volume Command(soft_pause) failed\n", __func__);
3478 rc = -EINVAL;
3479 goto fail_cmd;
3480 }
3481
3482 rc = wait_event_timeout(ac->cmd_wait,
3483 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
3484 if (!rc) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003485 pr_err("%s: timeout in sending volume command(soft_pause) to apr\n",
3486 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003487 rc = -EINVAL;
3488 goto fail_cmd;
3489 }
3490 rc = 0;
3491fail_cmd:
3492 kfree(vol_cmd);
3493 return rc;
3494}
3495
Swaminathan Sathappanb0021cd2011-08-31 15:20:12 -07003496int q6asm_set_softvolume(struct audio_client *ac,
3497 struct asm_softvolume_params *softvol_param)
3498{
3499 void *vol_cmd = NULL;
3500 void *payload = NULL;
3501 struct asm_pp_params_command *cmd = NULL;
3502 struct asm_softvolume_params *params = NULL;
3503 int sz = 0;
3504 int rc = 0;
3505
3506 sz = sizeof(struct asm_pp_params_command) +
3507 + sizeof(struct asm_softvolume_params);
3508 vol_cmd = kzalloc(sz, GFP_KERNEL);
3509 if (vol_cmd == NULL) {
3510 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
3511 rc = -EINVAL;
3512 return rc;
3513 }
3514 cmd = (struct asm_pp_params_command *)vol_cmd;
3515 q6asm_add_hdr_async(ac, &cmd->hdr, sz, TRUE);
3516 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
3517 cmd->payload = NULL;
3518 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
3519 sizeof(struct asm_softvolume_params);
3520 cmd->params.module_id = VOLUME_CONTROL_MODULE_ID;
3521 cmd->params.param_id = SOFT_VOLUME_PARAM_ID;
3522 cmd->params.param_size = sizeof(struct asm_softvolume_params);
3523 cmd->params.reserved = 0;
3524
3525 payload = (u8 *)(vol_cmd + sizeof(struct asm_pp_params_command));
3526 params = (struct asm_softvolume_params *)payload;
3527
3528 params->period = softvol_param->period;
3529 params->step = softvol_param->step;
3530 params->rampingcurve = softvol_param->rampingcurve;
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003531 pr_debug("%s: soft Volume:opcode = %d,payload_sz =%d,module_id =%d, param_id = %d, param_sz = %d\n",
3532 __func__,
Swaminathan Sathappanb0021cd2011-08-31 15:20:12 -07003533 cmd->hdr.opcode, cmd->payload_size,
3534 cmd->params.module_id, cmd->params.param_id,
3535 cmd->params.param_size);
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003536 pr_debug("%s: soft Volume Command: period = %d, step = %d, curve = %d\n",
3537 __func__, params->period,
Swaminathan Sathappanb0021cd2011-08-31 15:20:12 -07003538 params->step, params->rampingcurve);
3539 rc = apr_send_pkt(ac->apr, (uint32_t *) vol_cmd);
3540 if (rc < 0) {
3541 pr_err("%s: Volume Command(soft_volume) failed\n", __func__);
3542 rc = -EINVAL;
3543 goto fail_cmd;
3544 }
3545
3546 rc = wait_event_timeout(ac->cmd_wait,
3547 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
3548 if (!rc) {
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003549 pr_err("%s: timeout in sending volume command(soft_volume) to apr\n",
3550 __func__);
Swaminathan Sathappanb0021cd2011-08-31 15:20:12 -07003551 rc = -EINVAL;
3552 goto fail_cmd;
3553 }
3554 rc = 0;
3555fail_cmd:
3556 kfree(vol_cmd);
3557 return rc;
3558}
3559
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003560int q6asm_equalizer(struct audio_client *ac, void *eq)
3561{
3562 void *eq_cmd = NULL;
3563 void *payload = NULL;
3564 struct asm_pp_params_command *cmd = NULL;
3565 struct asm_equalizer_params *equalizer = NULL;
3566 struct msm_audio_eq_stream_config *eq_params = NULL;
3567 int i = 0;
3568 int sz = 0;
3569 int rc = 0;
3570
3571 sz = sizeof(struct asm_pp_params_command) +
3572 + sizeof(struct asm_equalizer_params);
3573 eq_cmd = kzalloc(sz, GFP_KERNEL);
3574 if (eq_cmd == NULL) {
3575 pr_err("%s[%d]: Mem alloc failed\n", __func__, ac->session);
3576 rc = -EINVAL;
3577 goto fail_cmd;
3578 }
3579 eq_params = (struct msm_audio_eq_stream_config *) eq;
3580 cmd = (struct asm_pp_params_command *)eq_cmd;
3581 q6asm_add_hdr(ac, &cmd->hdr, sz, TRUE);
3582 cmd->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS;
3583 cmd->payload = NULL;
3584 cmd->payload_size = sizeof(struct asm_pp_param_data_hdr) +
3585 sizeof(struct asm_equalizer_params);
3586 cmd->params.module_id = EQUALIZER_MODULE_ID;
3587 cmd->params.param_id = EQUALIZER_PARAM_ID;
3588 cmd->params.param_size = sizeof(struct asm_equalizer_params);
3589 cmd->params.reserved = 0;
3590 payload = (u8 *)(eq_cmd + sizeof(struct asm_pp_params_command));
3591 equalizer = (struct asm_equalizer_params *)payload;
3592
3593 equalizer->enable = eq_params->enable;
3594 equalizer->num_bands = eq_params->num_bands;
3595 pr_debug("%s: enable:%d numbands:%d\n", __func__, eq_params->enable,
3596 eq_params->num_bands);
3597 for (i = 0; i < eq_params->num_bands; i++) {
3598 equalizer->eq_bands[i].band_idx =
3599 eq_params->eq_bands[i].band_idx;
3600 equalizer->eq_bands[i].filter_type =
3601 eq_params->eq_bands[i].filter_type;
3602 equalizer->eq_bands[i].center_freq_hz =
3603 eq_params->eq_bands[i].center_freq_hz;
3604 equalizer->eq_bands[i].filter_gain =
3605 eq_params->eq_bands[i].filter_gain;
3606 equalizer->eq_bands[i].q_factor =
3607 eq_params->eq_bands[i].q_factor;
3608 pr_debug("%s: filter_type:%u bandnum:%d\n", __func__,
3609 eq_params->eq_bands[i].filter_type, i);
3610 pr_debug("%s: center_freq_hz:%u bandnum:%d\n", __func__,
3611 eq_params->eq_bands[i].center_freq_hz, i);
3612 pr_debug("%s: filter_gain:%d bandnum:%d\n", __func__,
3613 eq_params->eq_bands[i].filter_gain, i);
3614 pr_debug("%s: q_factor:%d bandnum:%d\n", __func__,
3615 eq_params->eq_bands[i].q_factor, i);
3616 }
3617 rc = apr_send_pkt(ac->apr, (uint32_t *) eq_cmd);
3618 if (rc < 0) {
3619 pr_err("%s: Equalizer Command failed\n", __func__);
3620 rc = -EINVAL;
3621 goto fail_cmd;
3622 }
3623
3624 rc = wait_event_timeout(ac->cmd_wait,
3625 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
3626 if (!rc) {
3627 pr_err("%s: timeout in sending equalizer command to apr\n",
3628 __func__);
3629 rc = -EINVAL;
3630 goto fail_cmd;
3631 }
3632 rc = 0;
3633fail_cmd:
3634 kfree(eq_cmd);
3635 return rc;
3636}
3637
3638int q6asm_read(struct audio_client *ac)
3639{
3640 struct asm_stream_cmd_read read;
3641 struct audio_buffer *ab;
3642 int dsp_buf;
3643 struct audio_port_data *port;
3644 int rc;
3645 if (!ac || ac->apr == NULL) {
3646 pr_err("APR handle NULL\n");
3647 return -EINVAL;
3648 }
Patrick Lai55f54c52012-11-17 00:29:07 -08003649 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003650 port = &ac->port[OUT];
3651
3652 q6asm_add_hdr(ac, &read.hdr, sizeof(read), FALSE);
3653
3654 mutex_lock(&port->lock);
3655
3656 dsp_buf = port->dsp_buf;
3657 ab = &port->buf[dsp_buf];
3658
3659 pr_debug("%s:session[%d]dsp-buf[%d][%p]cpu_buf[%d][%p]\n",
3660 __func__,
3661 ac->session,
3662 dsp_buf,
3663 (void *)port->buf[dsp_buf].data,
3664 port->cpu_buf,
3665 (void *)port->buf[port->cpu_buf].phys);
3666
3667 read.hdr.opcode = ASM_DATA_CMD_READ;
3668 read.buf_add = ab->phys;
3669 read.buf_size = ab->size;
3670 read.uid = port->dsp_buf;
3671 read.hdr.token = port->dsp_buf;
3672
3673 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
3674 mutex_unlock(&port->lock);
3675 pr_debug("%s:buf add[0x%x] token[%d] uid[%d]\n", __func__,
3676 read.buf_add,
3677 read.hdr.token,
3678 read.uid);
3679 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
3680 if (rc < 0) {
3681 pr_err("read op[0x%x]rc[%d]\n", read.hdr.opcode, rc);
3682 goto fail_cmd;
3683 }
3684 return 0;
3685 }
3686fail_cmd:
3687 return -EINVAL;
3688}
3689
3690int q6asm_read_nolock(struct audio_client *ac)
3691{
3692 struct asm_stream_cmd_read read;
3693 struct audio_buffer *ab;
3694 int dsp_buf;
3695 struct audio_port_data *port;
3696 int rc;
3697 if (!ac || ac->apr == NULL) {
3698 pr_err("APR handle NULL\n");
3699 return -EINVAL;
3700 }
Patrick Lai55f54c52012-11-17 00:29:07 -08003701 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003702 port = &ac->port[OUT];
3703
3704 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
3705
3706
3707 dsp_buf = port->dsp_buf;
3708 ab = &port->buf[dsp_buf];
3709
3710 pr_debug("%s:session[%d]dsp-buf[%d][%p]cpu_buf[%d][%p]\n",
3711 __func__,
3712 ac->session,
3713 dsp_buf,
3714 (void *)port->buf[dsp_buf].data,
3715 port->cpu_buf,
3716 (void *)port->buf[port->cpu_buf].phys);
3717
3718 read.hdr.opcode = ASM_DATA_CMD_READ;
3719 read.buf_add = ab->phys;
3720 read.buf_size = ab->size;
3721 read.uid = port->dsp_buf;
3722 read.hdr.token = port->dsp_buf;
3723
3724 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
Patrick Lai55f54c52012-11-17 00:29:07 -08003725 pr_info("%s:buf add[0x%x] token[%d] uid[%d]\n", __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003726 read.buf_add,
3727 read.hdr.token,
3728 read.uid);
3729 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
3730 if (rc < 0) {
3731 pr_err("read op[0x%x]rc[%d]\n", read.hdr.opcode, rc);
3732 goto fail_cmd;
3733 }
3734 return 0;
3735 }
3736fail_cmd:
3737 return -EINVAL;
3738}
3739
3740
3741static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
3742 uint32_t pkt_size, uint32_t cmd_flg)
3743{
3744 pr_debug("session=%d pkt size=%d cmd_flg=%d\n", pkt_size, cmd_flg,
3745 ac->session);
3746 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
3747 APR_HDR_LEN(sizeof(struct apr_hdr)),\
3748 APR_PKT_VER);
3749 hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
3750 hdr->src_domain = APR_DOMAIN_APPS;
3751 hdr->dest_svc = APR_SVC_ASM;
3752 hdr->dest_domain = APR_DOMAIN_ADSP;
3753 hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01;
3754 hdr->dest_port = ((ac->session << 8) & 0xFF00) | 0x01;
3755 if (cmd_flg) {
3756 hdr->token = ac->session;
3757 atomic_set(&ac->cmd_state, 1);
3758 }
3759 hdr->pkt_size = pkt_size;
3760 return;
3761}
3762
3763int q6asm_async_write(struct audio_client *ac,
3764 struct audio_aio_write_param *param)
3765{
3766 int rc = 0;
3767 struct asm_stream_cmd_write write;
3768
3769 if (!ac || ac->apr == NULL) {
3770 pr_err("%s: APR handle NULL\n", __func__);
3771 return -EINVAL;
3772 }
3773
3774 q6asm_add_hdr_async(ac, &write.hdr, sizeof(write), FALSE);
3775
3776 /* Pass physical address as token for AIO scheme */
3777 write.hdr.token = param->uid;
3778 write.hdr.opcode = ASM_DATA_CMD_WRITE;
3779 write.buf_add = param->paddr;
3780 write.avail_bytes = param->len;
3781 write.uid = param->uid;
3782 write.msw_ts = param->msw_ts;
3783 write.lsw_ts = param->lsw_ts;
3784 /* Use 0xFF00 for disabling timestamps */
3785 if (param->flags == 0xFF00)
3786 write.uflags = (0x00000000 | (param->flags & 0x800000FF));
3787 else
3788 write.uflags = (0x80000000 | param->flags);
3789
3790 pr_debug("%s: session[%d] bufadd[0x%x]len[0x%x]", __func__, ac->session,
3791 write.buf_add, write.avail_bytes);
3792
3793 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
3794 if (rc < 0) {
3795 pr_debug("[%s] write op[0x%x]rc[%d]\n", __func__,
3796 write.hdr.opcode, rc);
3797 goto fail_cmd;
3798 }
3799 return 0;
3800fail_cmd:
3801 return -EINVAL;
3802}
3803
3804int q6asm_async_read(struct audio_client *ac,
3805 struct audio_aio_read_param *param)
3806{
3807 int rc = 0;
3808 struct asm_stream_cmd_read read;
3809
3810 if (!ac || ac->apr == NULL) {
3811 pr_err("%s: APR handle NULL\n", __func__);
3812 return -EINVAL;
3813 }
3814
3815 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
3816
3817 /* Pass physical address as token for AIO scheme */
3818 read.hdr.token = param->paddr;
3819 read.hdr.opcode = ASM_DATA_CMD_READ;
3820 read.buf_add = param->paddr;
3821 read.buf_size = param->len;
3822 read.uid = param->uid;
3823
3824 pr_debug("%s: session[%d] bufadd[0x%x]len[0x%x]", __func__, ac->session,
3825 read.buf_add, read.buf_size);
3826
3827 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
3828 if (rc < 0) {
3829 pr_debug("[%s] read op[0x%x]rc[%d]\n", __func__,
3830 read.hdr.opcode, rc);
3831 goto fail_cmd;
3832 }
3833 return 0;
3834fail_cmd:
3835 return -EINVAL;
3836}
3837
Subhash Chandra Bose Naripeddy694b7d92012-06-20 20:46:13 -07003838int q6asm_async_read_compressed(struct audio_client *ac,
3839 struct audio_aio_read_param *param)
3840{
3841 int rc = 0;
3842 struct asm_stream_cmd_read read;
3843
3844 if (!ac || ac->apr == NULL) {
3845 pr_err("%s: APR handle NULL\n", __func__);
3846 return -EINVAL;
3847 }
3848
3849 q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
3850
3851 /* Pass physical address as token for AIO scheme */
3852 read.hdr.token = param->paddr;
3853 read.hdr.opcode = ASM_DATA_CMD_READ_COMPRESSED;
3854 read.buf_add = param->paddr;
3855 read.buf_size = param->len;
3856 read.uid = param->uid;
3857
3858 pr_debug("%s: session[%d] bufadd[0x%x]len[0x%x]", __func__, ac->session,
3859 read.buf_add, read.buf_size);
3860
3861 rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
3862 if (rc < 0) {
3863 pr_debug("[%s] read op[0x%x]rc[%d]\n", __func__,
3864 read.hdr.opcode, rc);
3865 goto fail_cmd;
3866 }
3867 return 0;
3868fail_cmd:
3869 return -EINVAL;
3870}
3871
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003872int q6asm_write(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
3873 uint32_t lsw_ts, uint32_t flags)
3874{
3875 int rc = 0;
3876 struct asm_stream_cmd_write write;
3877 struct audio_port_data *port;
3878 struct audio_buffer *ab;
3879 int dsp_buf = 0;
3880
3881 if (!ac || ac->apr == NULL) {
3882 pr_err("APR handle NULL\n");
3883 return -EINVAL;
3884 }
3885 pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
Patrick Lai55f54c52012-11-17 00:29:07 -08003886 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003887 port = &ac->port[IN];
3888
3889 q6asm_add_hdr(ac, &write.hdr, sizeof(write),
3890 FALSE);
3891 mutex_lock(&port->lock);
3892
3893 dsp_buf = port->dsp_buf;
3894 ab = &port->buf[dsp_buf];
3895
3896 write.hdr.token = port->dsp_buf;
3897 write.hdr.opcode = ASM_DATA_CMD_WRITE;
3898 write.buf_add = ab->phys;
3899 write.avail_bytes = len;
3900 write.uid = port->dsp_buf;
3901 write.msw_ts = msw_ts;
3902 write.lsw_ts = lsw_ts;
3903 /* Use 0xFF00 for disabling timestamps */
3904 if (flags == 0xFF00)
3905 write.uflags = (0x00000000 | (flags & 0x800000FF));
3906 else
3907 write.uflags = (0x80000000 | flags);
3908 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
3909
3910 pr_debug("%s:ab->phys[0x%x]bufadd[0x%x]token[0x%x]buf_id[0x%x]"
3911 , __func__,
3912 ab->phys,
3913 write.buf_add,
3914 write.hdr.token,
3915 write.uid);
3916 mutex_unlock(&port->lock);
Rajesha Kini3498c932011-07-19 19:58:27 +05303917#ifdef CONFIG_DEBUG_FS
3918 if (out_enable_flag) {
3919 char zero_pattern[2] = {0x00, 0x00};
3920 /* If First two byte is non zero and last two byte
3921 is zero then it is warm output pattern */
3922 if ((strncmp(((char *)ab->data), zero_pattern, 2)) &&
3923 (!strncmp(((char *)ab->data + 2), zero_pattern, 2))) {
3924 do_gettimeofday(&out_warm_tv);
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003925 pr_debug("WARM:apr_send_pkt at %ld sec %ld microsec\n",
3926 out_warm_tv.tv_sec,\
Rajesha Kini3498c932011-07-19 19:58:27 +05303927 out_warm_tv.tv_usec);
3928 pr_debug("Warm Pattern Matched");
3929 }
3930 /* If First two byte is zero and last two byte is
3931 non zero then it is cont ouput pattern */
3932 else if ((!strncmp(((char *)ab->data), zero_pattern, 2))
3933 && (strncmp(((char *)ab->data + 2), zero_pattern, 2))) {
3934 do_gettimeofday(&out_cont_tv);
Harmandeep Singheaf59b42012-06-05 21:46:02 -07003935 pr_debug("CONT:apr_send_pkt at %ld sec %ld microsec\n",
3936 out_cont_tv.tv_sec,\
Rajesha Kini3498c932011-07-19 19:58:27 +05303937 out_cont_tv.tv_usec);
3938 pr_debug("Cont Pattern Matched");
3939 }
3940 }
3941#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003942 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
3943 if (rc < 0) {
3944 pr_err("write op[0x%x]rc[%d]\n", write.hdr.opcode, rc);
3945 goto fail_cmd;
3946 }
3947 pr_debug("%s: WRITE SUCCESS\n", __func__);
3948 return 0;
3949 }
3950fail_cmd:
3951 return -EINVAL;
3952}
3953
3954int q6asm_write_nolock(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
3955 uint32_t lsw_ts, uint32_t flags)
3956{
3957 int rc = 0;
3958 struct asm_stream_cmd_write write;
3959 struct audio_port_data *port;
3960 struct audio_buffer *ab;
3961 int dsp_buf = 0;
3962
3963 if (!ac || ac->apr == NULL) {
3964 pr_err("APR handle NULL\n");
3965 return -EINVAL;
3966 }
3967 pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
Patrick Lai55f54c52012-11-17 00:29:07 -08003968 if (ac->io_mode & SYNC_IO_MODE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003969 port = &ac->port[IN];
3970
3971 q6asm_add_hdr_async(ac, &write.hdr, sizeof(write),
3972 FALSE);
3973
3974 dsp_buf = port->dsp_buf;
3975 ab = &port->buf[dsp_buf];
3976
3977 write.hdr.token = port->dsp_buf;
3978 write.hdr.opcode = ASM_DATA_CMD_WRITE;
3979 write.buf_add = ab->phys;
3980 write.avail_bytes = len;
3981 write.uid = port->dsp_buf;
3982 write.msw_ts = msw_ts;
3983 write.lsw_ts = lsw_ts;
3984 /* Use 0xFF00 for disabling timestamps */
3985 if (flags == 0xFF00)
3986 write.uflags = (0x00000000 | (flags & 0x800000FF));
3987 else
3988 write.uflags = (0x80000000 | flags);
3989 port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
3990
3991 pr_debug("%s:ab->phys[0x%x]bufadd[0x%x]token[0x%x]buf_id[0x%x]"
3992 , __func__,
3993 ab->phys,
3994 write.buf_add,
3995 write.hdr.token,
3996 write.uid);
3997
3998 rc = apr_send_pkt(ac->apr, (uint32_t *) &write);
3999 if (rc < 0) {
4000 pr_err("write op[0x%x]rc[%d]\n", write.hdr.opcode, rc);
4001 goto fail_cmd;
4002 }
4003 pr_debug("%s: WRITE SUCCESS\n", __func__);
4004 return 0;
4005 }
4006fail_cmd:
4007 return -EINVAL;
4008}
4009
Patrick Lai3aabeae2013-01-06 00:52:34 -08004010int q6asm_get_session_time(struct audio_client *ac, uint64_t *tstamp)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004011{
4012 struct apr_hdr hdr;
4013 int rc;
4014
Patrick Lai3aabeae2013-01-06 00:52:34 -08004015 if (!ac || ac->apr == NULL || tstamp == NULL) {
4016 pr_err("APR handle or tstamp NULL\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004017 return -EINVAL;
4018 }
Swaminathan Sathappanc7f98992012-07-09 11:07:12 -07004019 q6asm_add_hdr(ac, &hdr, sizeof(hdr), FALSE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004020 hdr.opcode = ASM_SESSION_CMD_GET_SESSION_TIME;
4021 atomic_set(&ac->time_flag, 1);
4022
4023 pr_debug("%s: session[%d]opcode[0x%x]\n", __func__,
4024 ac->session,
4025 hdr.opcode);
4026 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
4027 if (rc < 0) {
4028 pr_err("Commmand 0x%x failed\n", hdr.opcode);
4029 goto fail_cmd;
4030 }
4031 rc = wait_event_timeout(ac->time_wait,
4032 (atomic_read(&ac->time_flag) == 0), 5*HZ);
4033 if (!rc) {
4034 pr_err("%s: timeout in getting session time from DSP\n",
4035 __func__);
4036 goto fail_cmd;
4037 }
Patrick Lai3aabeae2013-01-06 00:52:34 -08004038
4039 *tstamp = ac->time_stamp;
4040 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004041
4042fail_cmd:
4043 return -EINVAL;
4044}
4045
4046int q6asm_cmd(struct audio_client *ac, int cmd)
4047{
4048 struct apr_hdr hdr;
4049 int rc;
4050 atomic_t *state;
4051 int cnt = 0;
4052
4053 if (!ac || ac->apr == NULL) {
4054 pr_err("APR handle NULL\n");
4055 return -EINVAL;
4056 }
4057 q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
4058 switch (cmd) {
4059 case CMD_PAUSE:
4060 pr_debug("%s:CMD_PAUSE\n", __func__);
4061 hdr.opcode = ASM_SESSION_CMD_PAUSE;
4062 state = &ac->cmd_state;
4063 break;
4064 case CMD_FLUSH:
4065 pr_debug("%s:CMD_FLUSH\n", __func__);
4066 hdr.opcode = ASM_STREAM_CMD_FLUSH;
4067 state = &ac->cmd_state;
4068 break;
4069 case CMD_OUT_FLUSH:
4070 pr_debug("%s:CMD_OUT_FLUSH\n", __func__);
4071 hdr.opcode = ASM_STREAM_CMD_FLUSH_READBUFS;
4072 state = &ac->cmd_state;
4073 break;
4074 case CMD_EOS:
4075 pr_debug("%s:CMD_EOS\n", __func__);
4076 hdr.opcode = ASM_DATA_CMD_EOS;
4077 atomic_set(&ac->cmd_state, 0);
4078 state = &ac->cmd_state;
4079 break;
4080 case CMD_CLOSE:
4081 pr_debug("%s:CMD_CLOSE\n", __func__);
4082 hdr.opcode = ASM_STREAM_CMD_CLOSE;
Laxminath Kasamf16d3fd2012-12-19 14:54:14 +05304083 atomic_set(&ac->cmd_close_state, 1);
4084 state = &ac->cmd_close_state;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004085 break;
4086 default:
4087 pr_err("Invalid format[%d]\n", cmd);
4088 goto fail_cmd;
4089 }
4090 pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
4091 ac->session,
4092 hdr.opcode);
4093 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
4094 if (rc < 0) {
4095 pr_err("Commmand 0x%x failed\n", hdr.opcode);
4096 goto fail_cmd;
4097 }
4098 rc = wait_event_timeout(ac->cmd_wait, (atomic_read(state) == 0), 5*HZ);
4099 if (!rc) {
4100 pr_err("timeout. waited for response opcode[0x%x]\n",
4101 hdr.opcode);
4102 goto fail_cmd;
4103 }
4104 if (cmd == CMD_FLUSH)
4105 q6asm_reset_buf_state(ac);
4106 if (cmd == CMD_CLOSE) {
4107 /* check if DSP return all buffers */
4108 if (ac->port[IN].buf) {
4109 for (cnt = 0; cnt < ac->port[IN].max_buf_cnt;
4110 cnt++) {
4111 if (ac->port[IN].buf[cnt].used == IN) {
4112 pr_debug("Write Buf[%d] not returned\n",
4113 cnt);
4114 }
4115 }
4116 }
4117 if (ac->port[OUT].buf) {
4118 for (cnt = 0; cnt < ac->port[OUT].max_buf_cnt; cnt++) {
4119 if (ac->port[OUT].buf[cnt].used == OUT) {
4120 pr_debug("Read Buf[%d] not returned\n",
4121 cnt);
4122 }
4123 }
4124 }
4125 }
4126 return 0;
4127fail_cmd:
4128 return -EINVAL;
4129}
4130
4131int q6asm_cmd_nowait(struct audio_client *ac, int cmd)
4132{
4133 struct apr_hdr hdr;
4134 int rc;
4135
4136 if (!ac || ac->apr == NULL) {
4137 pr_err("%s:APR handle NULL\n", __func__);
4138 return -EINVAL;
4139 }
4140 q6asm_add_hdr_async(ac, &hdr, sizeof(hdr), TRUE);
4141 switch (cmd) {
4142 case CMD_PAUSE:
4143 pr_debug("%s:CMD_PAUSE\n", __func__);
4144 hdr.opcode = ASM_SESSION_CMD_PAUSE;
4145 break;
4146 case CMD_EOS:
4147 pr_debug("%s:CMD_EOS\n", __func__);
4148 hdr.opcode = ASM_DATA_CMD_EOS;
4149 break;
4150 default:
4151 pr_err("%s:Invalid format[%d]\n", __func__, cmd);
4152 goto fail_cmd;
4153 }
4154 pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
4155 ac->session,
4156 hdr.opcode);
Jay Wang0668d1062012-07-11 18:53:21 -07004157
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004158 rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
4159 if (rc < 0) {
4160 pr_err("%s:Commmand 0x%x failed\n", __func__, hdr.opcode);
4161 goto fail_cmd;
4162 }
Jay Wang0668d1062012-07-11 18:53:21 -07004163 atomic_inc(&ac->nowait_cmd_cnt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004164 return 0;
4165fail_cmd:
4166 return -EINVAL;
4167}
4168
4169static void q6asm_reset_buf_state(struct audio_client *ac)
4170{
4171 int cnt = 0;
4172 int loopcnt = 0;
Patrick Lai55f54c52012-11-17 00:29:07 -08004173 int used;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004174 struct audio_port_data *port = NULL;
4175
Patrick Lai55f54c52012-11-17 00:29:07 -08004176 if (ac->io_mode & SYNC_IO_MODE) {
4177 used = (ac->io_mode & TUN_WRITE_IO_MODE ? 1 : 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004178 mutex_lock(&ac->cmd_lock);
4179 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
4180 port = &ac->port[loopcnt];
4181 cnt = port->max_buf_cnt - 1;
4182 port->dsp_buf = 0;
4183 port->cpu_buf = 0;
4184 while (cnt >= 0) {
4185 if (!port->buf)
4186 continue;
Patrick Lai55f54c52012-11-17 00:29:07 -08004187 port->buf[cnt].used = used;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004188 cnt--;
4189 }
4190 }
4191 mutex_unlock(&ac->cmd_lock);
4192 }
4193}
4194
4195int q6asm_reg_tx_overflow(struct audio_client *ac, uint16_t enable)
4196{
4197 struct asm_stream_cmd_reg_tx_overflow_event tx_overflow;
4198 int rc;
4199
4200 if (!ac || ac->apr == NULL) {
4201 pr_err("APR handle NULL\n");
4202 return -EINVAL;
4203 }
4204 pr_debug("%s:session[%d]enable[%d]\n", __func__,
4205 ac->session, enable);
4206 q6asm_add_hdr(ac, &tx_overflow.hdr, sizeof(tx_overflow), TRUE);
4207
4208 tx_overflow.hdr.opcode = \
4209 ASM_SESSION_CMD_REGISTER_FOR_TX_OVERFLOW_EVENTS;
4210 /* tx overflow event: enable */
4211 tx_overflow.enable = enable;
4212
4213 rc = apr_send_pkt(ac->apr, (uint32_t *) &tx_overflow);
4214 if (rc < 0) {
4215 pr_err("tx overflow op[0x%x]rc[%d]\n", \
4216 tx_overflow.hdr.opcode, rc);
4217 goto fail_cmd;
4218 }
4219 rc = wait_event_timeout(ac->cmd_wait,
4220 (atomic_read(&ac->cmd_state) == 0), 5*HZ);
4221 if (!rc) {
4222 pr_err("timeout. waited for tx overflow\n");
4223 goto fail_cmd;
4224 }
4225 return 0;
4226fail_cmd:
4227 return -EINVAL;
4228}
4229
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004230int q6asm_get_apr_service_id(int session_id)
4231{
4232 pr_debug("%s\n", __func__);
4233
Shiv Maliyappanahallia84982a2012-01-19 15:25:04 -08004234 if (session_id < 0 || session_id > SESSION_MAX) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004235 pr_err("%s: invalid session_id = %d\n", __func__, session_id);
4236 return -EINVAL;
4237 }
4238
4239 return ((struct apr_svc *)session[session_id]->apr)->id;
4240}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004241
4242
4243static int __init q6asm_init(void)
4244{
4245 pr_debug("%s\n", __func__);
4246 init_waitqueue_head(&this_mmap.cmd_wait);
4247 memset(session, 0, sizeof(session));
Rajesha Kini3498c932011-07-19 19:58:27 +05304248#ifdef CONFIG_DEBUG_FS
4249 out_buffer = kmalloc(OUT_BUFFER_SIZE, GFP_KERNEL);
4250 out_dentry = debugfs_create_file("audio_out_latency_measurement_node",\
Glenn Kasten5dfda802012-10-04 16:40:27 -07004251 0664,\
Rajesha Kini3498c932011-07-19 19:58:27 +05304252 NULL, NULL, &audio_output_latency_debug_fops);
4253 if (IS_ERR(out_dentry))
4254 pr_err("debugfs_create_file failed\n");
4255 in_buffer = kmalloc(IN_BUFFER_SIZE, GFP_KERNEL);
4256 in_dentry = debugfs_create_file("audio_in_latency_measurement_node",\
Glenn Kasten5dfda802012-10-04 16:40:27 -07004257 0664,\
Rajesha Kini3498c932011-07-19 19:58:27 +05304258 NULL, NULL, &audio_input_latency_debug_fops);
4259 if (IS_ERR(in_dentry))
4260 pr_err("debugfs_create_file failed\n");
4261#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004262 return 0;
4263}
4264
4265device_initcall(q6asm_init);