blob: 589586780110e895156b018fa939f3c8df7f3a5c [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* arch/arm/mach-msm/qdsp6/audiov2/q6audio.c
2 *
3 * Copyright (C) 2009 Google, Inc.
Duy Truong790f06d2013-02-13 16:38:12 -08004 * Copyright (c) 2009, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07005 *
6 * Author: Brian Swetland <swetland@google.com>
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19#include <linux/mutex.h>
20#include <linux/sched.h>
21#include <linux/wait.h>
22#include <linux/dma-mapping.h>
23#include <linux/clk.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070024#include <linux/delay.h>
25#include <linux/wakelock.h>
26#include <linux/android_pmem.h>
27#include <linux/gpio.h>
Stephen Boyd2fcabf92012-05-30 10:41:11 -070028#include <linux/pm_qos.h>
29
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070030#include <mach/msm_qdsp6_audiov2.h>
Stephen Boyd2fcabf92012-05-30 10:41:11 -070031#include <mach/cpuidle.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070032
33#include "../dal.h"
34#include "dal_audio.h"
35#include "dal_audio_format.h"
36#include "dal_acdb.h"
37#include "dal_adie.h"
38#include "q6audio_devices.h"
39
40struct q6_hw_info {
41 int min_gain;
42 int max_gain;
43};
44
45/* TODO: provide mechanism to configure from board file */
46
47static struct q6_hw_info q6_audio_hw[Q6_HW_COUNT] = {
48 [Q6_HW_HANDSET] = {
49 .min_gain = -2000,
50 .max_gain = 0,
51 },
52 [Q6_HW_HEADSET] = {
53 .min_gain = -2000,
54 .max_gain = 0,
55 },
56 [Q6_HW_SPEAKER] = {
57 .min_gain = -1500,
58 .max_gain = 0,
59 },
60 [Q6_HW_TTY] = {
61 .min_gain = -2000,
62 .max_gain = 0,
63 },
64 [Q6_HW_BT_SCO] = {
65 .min_gain = -2000,
66 .max_gain = 0,
67 },
68 [Q6_HW_BT_A2DP] = {
69 .min_gain = -2000,
70 .max_gain = 0,
71 },
72};
73
Stephen Boyd2fcabf92012-05-30 10:41:11 -070074static struct pm_qos_request pm_qos_req;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070075static int idlecount;
76static DEFINE_MUTEX(idlecount_lock);
77
78void audio_prevent_sleep(void)
79{
80 mutex_lock(&idlecount_lock);
81 if (++idlecount == 1)
Stephen Boyd2fcabf92012-05-30 10:41:11 -070082 pm_qos_update_request(&pm_qos_req,
83 msm_cpuidle_get_deep_idle_latency());
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070084 mutex_unlock(&idlecount_lock);
85}
86
87void audio_allow_sleep(void)
88{
89 mutex_lock(&idlecount_lock);
90 if (--idlecount == 0)
Stephen Boyd2fcabf92012-05-30 10:41:11 -070091 pm_qos_update_request(&pm_qos_req, PM_QOS_DEFAULT_VALUE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070092 mutex_unlock(&idlecount_lock);
93}
94
95static struct clk *icodec_rx_clk;
96static struct clk *icodec_tx_clk;
97static struct clk *ecodec_clk;
98static struct clk *sdac_clk;
99
100static struct q6audio_analog_ops default_analog_ops;
101static struct q6audio_analog_ops *analog_ops = &default_analog_ops;
102uint32_t tx_clk_freq = 8000;
103static int tx_mute_status;
104
105void q6audio_register_analog_ops(struct q6audio_analog_ops *ops)
106{
107 analog_ops = ops;
108}
109
110static struct q6_device_info *q6_lookup_device(uint32_t device_id)
111{
112 struct q6_device_info *di = q6_audio_devices;
113 for (;;) {
114 if (di->id == device_id)
115 return di;
116 if (di->id == 0) {
117 pr_err("q6_lookup_device: bogus id 0x%08x\n",
118 device_id);
119 return di;
120 }
121 di++;
122 }
123}
124
125static uint32_t q6_device_to_codec(uint32_t device_id)
126{
127 struct q6_device_info *di = q6_lookup_device(device_id);
128 return di->codec;
129}
130
131static uint32_t q6_device_to_dir(uint32_t device_id)
132{
133 struct q6_device_info *di = q6_lookup_device(device_id);
134 return di->dir;
135}
136
137static uint32_t q6_device_to_cad_id(uint32_t device_id)
138{
139 struct q6_device_info *di = q6_lookup_device(device_id);
140 return di->cad_id;
141}
142
143static uint32_t q6_device_to_path(uint32_t device_id)
144{
145 struct q6_device_info *di = q6_lookup_device(device_id);
146 return di->path;
147}
148
149static uint32_t q6_device_to_rate(uint32_t device_id)
150{
151 struct q6_device_info *di = q6_lookup_device(device_id);
152 return di->rate;
153}
154
155int q6_device_volume(uint32_t device_id, int level)
156{
157 struct q6_device_info *di = q6_lookup_device(device_id);
158 struct q6_hw_info *hw;
159
160 hw = &q6_audio_hw[di->hw];
161
162 return hw->min_gain + ((hw->max_gain - hw->min_gain) * level) / 100;
163}
164
165static inline int adie_open(struct dal_client *client)
166{
167 return dal_call_f0(client, DAL_OP_OPEN, 0);
168}
169
170static inline int adie_close(struct dal_client *client)
171{
172 return dal_call_f0(client, DAL_OP_CLOSE, 0);
173}
174
175static inline int adie_set_path(struct dal_client *client,
176 uint32_t *adie_params, uint32_t size)
177{
178 uint32_t tmp;
179 return dal_call(client, ADIE_OP_SET_PATH, 5, adie_params, size,
180 (void *)&tmp, sizeof(uint32_t));
181
182}
183
184static inline int adie_proceed_to_stage(struct dal_client *client,
185 uint32_t path_type, uint32_t stage)
186{
187 return dal_call_f1(client, ADIE_OP_PROCEED_TO_STAGE,
188 path_type, stage);
189}
190
191static int adie_refcount;
192
193static struct dal_client *adie;
194static struct dal_client *adsp;
195static struct dal_client *acdb;
196
197static int adie_enable(void)
198{
199 adie_refcount++;
200 if (adie_refcount == 1)
201 adie_open(adie);
202 return 0;
203}
204
205static int adie_disable(void)
206{
207 adie_refcount--;
208 if (adie_refcount == 0)
209 adie_close(adie);
210 return 0;
211}
212
213/* 4k DMA scratch page used for exchanging acdb device config tables
214 * and stream format descriptions with the DSP.
215 */
216char *audio_data;
217int32_t audio_phys;
218
219#define SESSION_MIN 0
220#define SESSION_MAX 64
221
222static DEFINE_MUTEX(session_lock);
223static DEFINE_MUTEX(audio_lock);
224
225static struct audio_client *session[SESSION_MAX];
226
227static int session_alloc(struct audio_client *ac)
228{
229 int n;
230
231 mutex_lock(&session_lock);
232 for (n = SESSION_MIN; n < SESSION_MAX; n++) {
233 if (!session[n]) {
234 session[n] = ac;
235 mutex_unlock(&session_lock);
236 return n;
237 }
238 }
239 mutex_unlock(&session_lock);
240 return -ENOMEM;
241}
242
243static void session_free(int n, struct audio_client *ac)
244{
245 mutex_lock(&session_lock);
246 if (session[n] == ac)
247 session[n] = 0;
248 mutex_unlock(&session_lock);
249}
250
251static void audio_client_free(struct audio_client *ac)
252{
253 session_free(ac->session, ac);
254
255 if (ac->buf[0].data)
256 pmem_kfree(ac->buf[0].phys);
257 if (ac->buf[1].data)
258 pmem_kfree(ac->buf[1].phys);
259 kfree(ac);
260}
261
262static struct audio_client *audio_client_alloc(unsigned bufsz)
263{
264 struct audio_client *ac;
265 int n;
266
267 ac = kzalloc(sizeof(*ac), GFP_KERNEL);
268 if (!ac)
269 return 0;
270
271 n = session_alloc(ac);
272 if (n < 0)
273 goto fail_session;
274 ac->session = n;
275
276 if (bufsz > 0) {
277 ac->buf[0].phys = pmem_kalloc(bufsz,
278 PMEM_MEMTYPE_EBI1|PMEM_ALIGNMENT_4K);
279 ac->buf[0].data = ioremap(ac->buf[0].phys, bufsz);
280 if (!ac->buf[0].data)
281 goto fail;
282
283 ac->buf[1].phys = pmem_kalloc(bufsz,
284 PMEM_MEMTYPE_EBI1|PMEM_ALIGNMENT_4K);
285 ac->buf[1].data = ioremap(ac->buf[1].phys, bufsz);
286 if (!ac->buf[1].data)
287 goto fail;
288
289 ac->buf[0].size = bufsz;
290 ac->buf[1].size = bufsz;
291 }
292
293 init_waitqueue_head(&ac->wait);
294 ac->client = adsp;
295
296 return ac;
297
298fail:
299 pr_err("pmem_kalloc failed\n");
300 session_free(n, ac);
301fail_session:
302 audio_client_free(ac);
303 return 0;
304}
305
306static int audio_ioctl(struct audio_client *ac, void *ptr, uint32_t len)
307{
308 struct adsp_command_hdr *hdr = ptr;
309 uint32_t tmp;
310 int r;
311
312 hdr->size = len - sizeof(u32);
313 hdr->dest = AUDIO_ADDR(DOMAIN_DSP, ac->session, 0);
314 hdr->src = AUDIO_ADDR(DOMAIN_APP, ac->session, 0);
315 hdr->context = ac->session;
316 ac->cb_status = -EBUSY;
317 r = dal_call(ac->client, AUDIO_OP_CONTROL, 5, ptr, len,
318 &tmp, sizeof(tmp));
319 if (r != 4)
320 return -EIO;
321 wait_event(ac->wait, (ac->cb_status != -EBUSY));
322 return tmp;
323}
324
325static int audio_command(struct audio_client *ac, uint32_t cmd)
326{
327 struct adsp_command_hdr rpc;
328 memset(&rpc, 0, sizeof(rpc));
329 rpc.opcode = cmd;
330 return audio_ioctl(ac, &rpc, sizeof(rpc));
331}
332
333static int audio_open_control(struct audio_client *ac)
334{
335 struct adsp_open_command rpc;
336
337 memset(&rpc, 0, sizeof(rpc));
338 rpc.hdr.opcode = ADSP_AUDIO_IOCTL_CMD_OPEN_DEVICE;
339 rpc.hdr.dest = AUDIO_ADDR(DOMAIN_DSP, ac->session, 0);
340 rpc.hdr.src = AUDIO_ADDR(DOMAIN_APP, ac->session, 0);
341 return audio_ioctl(ac, &rpc, sizeof(rpc));
342}
343
344
345static int audio_close(struct audio_client *ac)
346{
347 audio_command(ac, ADSP_AUDIO_IOCTL_CMD_STREAM_STOP);
348 audio_command(ac, ADSP_AUDIO_IOCTL_CMD_CLOSE);
349 return 0;
350}
351
352static int audio_set_table(struct audio_client *ac,
353 uint32_t device_id, int size)
354{
355 struct adsp_set_dev_cfg_table_command rpc;
356
357 memset(&rpc, 0, sizeof(rpc));
358 rpc.hdr.opcode = ADSP_AUDIO_IOCTL_SET_DEVICE_CONFIG_TABLE;
359 rpc.hdr.dest = AUDIO_ADDR(DOMAIN_DSP, ac->session, 0);
360 rpc.hdr.src = AUDIO_ADDR(DOMAIN_APP, ac->session, 0);
361 rpc.device_id = device_id;
362 rpc.phys_addr = audio_phys;
363 rpc.phys_size = size;
364 rpc.phys_used = size;
365
366 if (q6_device_to_dir(device_id) == Q6_TX)
367 rpc.hdr.data = tx_clk_freq;
368 return audio_ioctl(ac, &rpc, sizeof(rpc));
369}
370
371int q6audio_read(struct audio_client *ac, struct audio_buffer *ab)
372{
373 struct adsp_buffer_command rpc;
374 uint32_t res;
375 int r;
376
377 memset(&rpc, 0, sizeof(rpc));
378 rpc.hdr.size = sizeof(rpc) - sizeof(u32);
379 rpc.hdr.dest = AUDIO_ADDR(DOMAIN_DSP, ac->session, 0);
380 rpc.hdr.src = AUDIO_ADDR(DOMAIN_APP, ac->session, 0);
381 rpc.hdr.context = ac->session;
382 rpc.hdr.opcode = ADSP_AUDIO_IOCTL_CMD_DATA_TX;
383 rpc.buffer.addr = ab->phys;
384 rpc.buffer.max_size = ab->size;
385 rpc.buffer.actual_size = ab->actual_size;
386
387 r = dal_call(ac->client, AUDIO_OP_DATA, 5, &rpc, sizeof(rpc),
388 &res, sizeof(res));
389
390 if ((r == sizeof(res)))
391 return 0;
392
393 return -EIO;
394
395}
396
397int q6audio_write(struct audio_client *ac, struct audio_buffer *ab)
398{
399 struct adsp_buffer_command rpc;
400 uint32_t res;
401 int r;
402
403 memset(&rpc, 0, sizeof(rpc));
404 rpc.hdr.size = sizeof(rpc) - sizeof(u32);
405 rpc.hdr.src = AUDIO_ADDR(DOMAIN_APP, ac->session, 0);
406 rpc.hdr.dest = AUDIO_ADDR(DOMAIN_DSP, ac->session, 0);
407 rpc.hdr.context = ac->session;
408 rpc.hdr.opcode = ADSP_AUDIO_IOCTL_CMD_DATA_RX;
409 rpc.buffer.addr = ab->phys;
410 rpc.buffer.max_size = ab->size;
411 rpc.buffer.actual_size = ab->actual_size;
412
413 r = dal_call(ac->client, AUDIO_OP_DATA, 5, &rpc, sizeof(rpc),
414 &res, sizeof(res));
415 return 0;
416}
417
418static int audio_rx_volume(struct audio_client *ac, uint32_t dev_id,
419 int32_t volume)
420{
421 struct adsp_set_dev_volume_command rpc;
422
423 memset(&rpc, 0, sizeof(rpc));
424 rpc.hdr.opcode = ADSP_AUDIO_IOCTL_CMD_SET_DEVICE_VOL;
425 rpc.hdr.dest = AUDIO_ADDR(DOMAIN_DSP, ac->session, 0);
426 rpc.hdr.src = AUDIO_ADDR(DOMAIN_APP, ac->session, 0);
427 rpc.device_id = dev_id;
428 rpc.path = ADSP_PATH_RX;
429 rpc.volume = volume;
430 return audio_ioctl(ac, &rpc, sizeof(rpc));
431}
432
433static int audio_rx_mute(struct audio_client *ac, uint32_t dev_id, int mute)
434{
435 struct adsp_set_dev_mute_command rpc;
436
437 memset(&rpc, 0, sizeof(rpc));
438 rpc.hdr.opcode = ADSP_AUDIO_IOCTL_CMD_SET_DEVICE_MUTE;
439 rpc.hdr.dest = AUDIO_ADDR(DOMAIN_DSP, ac->session, 0);
440 rpc.hdr.src = AUDIO_ADDR(DOMAIN_APP, ac->session, 0);
441 rpc.device_id = dev_id;
442 rpc.path = ADSP_PATH_RX;
443 rpc.mute = !!mute;
444 return audio_ioctl(ac, &rpc, sizeof(rpc));
445}
446
447static int audio_tx_volume(struct audio_client *ac, uint32_t dev_id,
448 int32_t volume)
449{
450 struct adsp_set_dev_volume_command rpc;
451
452 memset(&rpc, 0, sizeof(rpc));
453 rpc.hdr.opcode = ADSP_AUDIO_IOCTL_CMD_SET_DEVICE_VOL;
454 rpc.hdr.dest = AUDIO_ADDR(DOMAIN_DSP, ac->session, 0);
455 rpc.hdr.src = AUDIO_ADDR(DOMAIN_APP, ac->session, 0);
456 rpc.device_id = dev_id;
457 rpc.path = ADSP_PATH_TX;
458 rpc.volume = volume;
459 return audio_ioctl(ac, &rpc, sizeof(rpc));
460}
461
462static int audio_tx_mute(struct audio_client *ac, uint32_t dev_id, int mute)
463{
464 struct adsp_set_dev_mute_command rpc;
465
466 memset(&rpc, 0, sizeof(rpc));
467 rpc.hdr.opcode = ADSP_AUDIO_IOCTL_CMD_SET_DEVICE_MUTE;
468 rpc.hdr.dest = AUDIO_ADDR(DOMAIN_DSP, ac->session, 0);
469 rpc.hdr.src = AUDIO_ADDR(DOMAIN_APP, ac->session, 0);
470 rpc.device_id = dev_id;
471 rpc.path = ADSP_PATH_TX;
472 rpc.mute = !!mute;
473 return audio_ioctl(ac, &rpc, sizeof(rpc));
474}
475
476static void callback(void *data, int len, void *cookie)
477{
478 struct adsp_event_hdr *e = data;
479 struct audio_client *ac;
480 struct adsp_buffer_event *abe = data;
481
482 if (e->context >= SESSION_MAX) {
483 pr_err("audio callback: bogus session %d\n",
484 e->context);
485 return;
486 }
487 ac = session[e->context];
488 if (!ac) {
489 pr_err("audio callback: unknown session %d\n",
490 e->context);
491 return;
492 }
493
494 if (e->event_id == ADSP_AUDIO_IOCTL_CMD_STREAM_EOS) {
495 pr_info("playback done\n");
496 if (e->status)
497 pr_err("playback status %d\n", e->status);
498 if (ac->cb_status == -EBUSY) {
499 ac->cb_status = e->status;
500 wake_up(&ac->wait);
501 }
502 return;
503 }
504
505 if (e->event_id == ADSP_AUDIO_EVT_STATUS_BUF_DONE) {
506 if (e->status)
507 pr_err("buffer status %d\n", e->status);
508
509 ac->buf[ac->dsp_buf].actual_size = abe->buffer.actual_size;
510 ac->buf[ac->dsp_buf].used = 0;
511 ac->dsp_buf ^= 1;
512 wake_up(&ac->wait);
513 return;
514 }
515
516 if (e->status)
517 pr_warning("audio_cb: s=%d e=%08x status=%d\n",
518 e->context, e->event_id, e->status);
519
520 if (ac->cb_status == -EBUSY) {
521 ac->cb_status = e->status;
522 wake_up(&ac->wait);
523 }
524}
525
526static void audio_init(struct dal_client *client)
527{
528 u32 tmp[3];
529
530 tmp[0] = 2 * sizeof(u32);
531 tmp[1] = 0;
532 tmp[2] = 0;
533 dal_call(client, AUDIO_OP_INIT, 5, tmp, sizeof(tmp),
534 tmp, sizeof(u32));
535}
536
537static struct audio_client *ac_control;
538
539static int q6audio_init(void)
540{
541 struct audio_client *ac = 0;
542 int res = -ENODEV;
543
544 mutex_lock(&audio_lock);
545 if (ac_control) {
546 res = 0;
547 goto done;
548 }
549
550 icodec_rx_clk = clk_get(0, "icodec_rx_clk");
551 icodec_tx_clk = clk_get(0, "icodec_tx_clk");
552 ecodec_clk = clk_get(0, "ecodec_clk");
553 sdac_clk = clk_get(0, "sdac_clk");
554
555 tx_mute_status = 0;
556 audio_phys = pmem_kalloc(4096, PMEM_MEMTYPE_EBI1|PMEM_ALIGNMENT_4K);
557 audio_data = ioremap(audio_phys, 4096);
558 if (!audio_data) {
559 pr_err("pmem kalloc failed\n");
560 res = -ENOMEM;
561 goto done;
562 }
563
564 adsp = dal_attach(AUDIO_DAL_DEVICE, AUDIO_DAL_PORT, 1,
565 callback, 0);
566 if (!adsp) {
567 pr_err("audio_init: cannot attach to adsp\n");
568 res = -ENODEV;
569 goto done;
570 }
571 if (check_version(adsp, AUDIO_DAL_VERSION) != 0) {
572 pr_err("Incompatible adsp version\n");
573 res = -ENODEV;
574 goto done;
575 }
576
577 audio_init(adsp);
578
579 ac = audio_client_alloc(0);
580 if (!ac) {
581 pr_err("audio_init: cannot allocate client\n");
582 res = -ENOMEM;
583 goto done;
584 }
585
586 if (audio_open_control(ac)) {
587 pr_err("audio_init: cannot open control channel\n");
588 res = -ENODEV;
589 goto done;
590 }
591
592 acdb = dal_attach(ACDB_DAL_DEVICE, ACDB_DAL_PORT, 0, 0, 0);
593 if (!acdb) {
594 pr_err("audio_init: cannot attach to acdb channel\n");
595 res = -ENODEV;
596 goto done;
597 }
598 if (check_version(acdb, ACDB_DAL_VERSION) != 0) {
599 pr_err("Incompatablie acdb version\n");
600 res = -ENODEV;
601 goto done;
602 }
603
604
605 adie = dal_attach(ADIE_DAL_DEVICE, ADIE_DAL_PORT, 0, 0, 0);
606 if (!adie) {
607 pr_err("audio_init: cannot attach to adie\n");
608 res = -ENODEV;
609 goto done;
610 }
611 if (check_version(adie, ADIE_DAL_VERSION) != 0) {
612 pr_err("Incompatablie adie version\n");
613 res = -ENODEV;
614 goto done;
615 }
616 if (analog_ops->init)
617 analog_ops->init();
618
619 res = 0;
620 ac_control = ac;
621
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700622 pm_qos_add_request(&pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
623 PM_QOS_DEFAULT_VALUE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700624done:
625 if ((res < 0) && ac)
626 audio_client_free(ac);
627 mutex_unlock(&audio_lock);
628
629 return res;
630}
631
632static int acdb_get_config_table(uint32_t device_id, uint32_t sample_rate)
633{
634 struct acdb_cmd_device_table rpc;
635 struct acdb_result res;
636 int r;
637
638 if (q6audio_init())
639 return 0;
640
641 memset(audio_data, 0, 4096);
642 memset(&rpc, 0, sizeof(rpc));
643
644 rpc.size = sizeof(rpc) - (2 * sizeof(uint32_t));
645 rpc.command_id = ACDB_GET_DEVICE_TABLE;
646 rpc.device_id = q6_device_to_cad_id(device_id);
647 rpc.network_id = 0x00010023;
648 rpc.sample_rate_id = sample_rate;
649 rpc.total_bytes = 4096;
650 rpc.unmapped_buf = audio_phys;
651 rpc.res_size = sizeof(res) - (2 * sizeof(uint32_t));
652
653 r = dal_call(acdb, ACDB_OP_IOCTL, 8, &rpc, sizeof(rpc),
654 &res, sizeof(res));
655
656 if ((r == sizeof(res)) && (res.dal_status == 0))
657 return res.used_bytes;
658
659 return -EIO;
660}
661
662static uint32_t audio_rx_path_id = ADIE_PATH_HANDSET_RX;
663static uint32_t audio_rx_device_id = ADSP_AUDIO_DEVICE_ID_HANDSET_SPKR;
664static uint32_t audio_rx_device_group = -1;
665static uint32_t audio_tx_path_id = ADIE_PATH_HANDSET_TX;
666static uint32_t audio_tx_device_id = ADSP_AUDIO_DEVICE_ID_HANDSET_MIC;
667static uint32_t audio_tx_device_group = -1;
668
669static int qdsp6_devchg_notify(struct audio_client *ac,
670 uint32_t dev_type, uint32_t dev_id)
671{
672 struct adsp_device_switch_command rpc;
673
674 if (dev_type != ADSP_AUDIO_RX_DEVICE &&
675 dev_type != ADSP_AUDIO_TX_DEVICE)
676 return -EINVAL;
677
678 memset(&rpc, 0, sizeof(rpc));
679 rpc.hdr.opcode = ADSP_AUDIO_IOCTL_CMD_DEVICE_SWITCH_PREPARE;
680 rpc.hdr.dest = AUDIO_ADDR(DOMAIN_DSP, ac->session, 0);
681 rpc.hdr.src = AUDIO_ADDR(DOMAIN_APP, ac->session, 0);
682
683 if (dev_type == ADSP_AUDIO_RX_DEVICE) {
684 rpc.old_device = audio_rx_device_id;
685 rpc.new_device = dev_id;
686 } else {
687 rpc.old_device = audio_tx_device_id;
688 rpc.new_device = dev_id;
689 }
690 rpc.device_class = 0;
691 rpc.device_type = dev_type;
692 return audio_ioctl(ac, &rpc, sizeof(rpc));
693}
694
695static int qdsp6_standby(struct audio_client *ac)
696{
697 return audio_command(ac, ADSP_AUDIO_IOCTL_CMD_DEVICE_SWITCH_STANDBY);
698}
699
700static int qdsp6_start(struct audio_client *ac)
701{
702 return audio_command(ac, ADSP_AUDIO_IOCTL_CMD_DEVICE_SWITCH_COMMIT);
703}
704
705static void audio_rx_analog_enable(int en)
706{
707 switch (audio_rx_device_id) {
708 case ADSP_AUDIO_DEVICE_ID_HEADSET_SPKR_MONO:
709 case ADSP_AUDIO_DEVICE_ID_HEADSET_SPKR_STEREO:
710 case ADSP_AUDIO_DEVICE_ID_TTY_HEADSET_SPKR:
711 if (analog_ops->headset_enable)
712 analog_ops->headset_enable(en);
713 break;
714 case ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_MONO_W_MONO_HEADSET:
715 case ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_MONO_W_STEREO_HEADSET:
716 case ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_STEREO_W_MONO_HEADSET:
717 case ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_STEREO_W_STEREO_HEADSET:
718 if (analog_ops->headset_enable)
719 analog_ops->headset_enable(en);
720 if (analog_ops->speaker_enable)
721 analog_ops->speaker_enable(en);
722 break;
723 case ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_MONO:
724 case ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_STEREO:
725 if (analog_ops->speaker_enable)
726 analog_ops->speaker_enable(en);
727 break;
728 case ADSP_AUDIO_DEVICE_ID_BT_SCO_SPKR:
729 if (analog_ops->bt_sco_enable)
730 analog_ops->bt_sco_enable(en);
731 break;
732 }
733}
734
735static void audio_tx_analog_enable(int en)
736{
737 switch (audio_tx_device_id) {
738 case ADSP_AUDIO_DEVICE_ID_HANDSET_MIC:
739 case ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_MIC:
740 if (analog_ops->int_mic_enable)
741 analog_ops->int_mic_enable(en);
742 break;
743 case ADSP_AUDIO_DEVICE_ID_HEADSET_MIC:
744 case ADSP_AUDIO_DEVICE_ID_TTY_HEADSET_MIC:
745 if (analog_ops->ext_mic_enable)
746 analog_ops->ext_mic_enable(en);
747 break;
748 case ADSP_AUDIO_DEVICE_ID_BT_SCO_MIC:
749 if (analog_ops->bt_sco_enable)
750 analog_ops->bt_sco_enable(en);
751 break;
752 }
753}
754
755static void _audio_rx_path_enable(void)
756{
757 uint32_t adev, sample_rate;
758 int sz;
759 uint32_t adie_params[5];
760
761 adev = audio_rx_device_id;
762 sample_rate = q6_device_to_rate(adev);
763
764 sz = acdb_get_config_table(adev, sample_rate);
765 audio_set_table(ac_control, adev, sz);
766
767 adie_params[0] = 4*sizeof(uint32_t);
768 adie_params[1] = audio_rx_path_id;
769 adie_params[2] = ADIE_PATH_RX;
770 adie_params[3] = 48000;
771 adie_params[4] = 256;
772 /*check for errors here*/
773 if (!adie_set_path(adie, adie_params, sizeof(adie_params)))
774 pr_err("adie set rx path failed\n");
775
776 adie_proceed_to_stage(adie, ADIE_PATH_RX,
777 ADIE_STAGE_DIGITAL_READY);
778 adie_proceed_to_stage(adie, ADIE_PATH_RX,
779 ADIE_STAGE_DIGITAL_ANALOG_READY);
780
781 audio_rx_analog_enable(1);
782
783 audio_rx_mute(ac_control, adev, 0);
784
785 audio_rx_volume(ac_control, adev, q6_device_volume(adev, 100));
786}
787
788static void _audio_tx_path_enable(void)
789{
790 uint32_t adev;
791 int sz;
792 uint32_t adie_params[5];
793
794 adev = audio_tx_device_id;
795
796 pr_info("audiolib: load %08x cfg table\n", adev);
797
798 if (tx_clk_freq > 16000) {
799 adie_params[3] = 48000;
800 sz = acdb_get_config_table(adev, 48000);
801
802 } else if (tx_clk_freq > 8000) {
803 adie_params[3] = 16000;
804 sz = acdb_get_config_table(adev, 16000);
805 } else {
806
807 adie_params[3] = 8000;
808 sz = acdb_get_config_table(adev, 8000);
809 }
810
811 pr_info("cfg table is %d bytes\n", sz);
812 audio_set_table(ac_control, adev, sz);
813
814 pr_info("audiolib: set adie tx path\n");
815
816 adie_params[0] = 4*sizeof(uint32_t);
817 adie_params[1] = audio_tx_path_id;
818 adie_params[2] = ADIE_PATH_TX;
819 adie_params[4] = 256;
820
821 if (!adie_set_path(adie, adie_params, sizeof(adie_params)))
822 pr_err("adie set tx path failed\n");
823
824 adie_proceed_to_stage(adie, ADIE_PATH_TX,
825 ADIE_STAGE_DIGITAL_READY);
826 adie_proceed_to_stage(adie, ADIE_PATH_TX,
827 ADIE_STAGE_DIGITAL_ANALOG_READY);
828
829 audio_tx_analog_enable(1);
830 audio_tx_mute(ac_control, adev, tx_mute_status);
831
832 if (!tx_mute_status)
833 audio_tx_volume(ac_control, adev, q6_device_volume(adev, 100));
834}
835
836static void _audio_rx_path_disable(void)
837{
838 audio_rx_analog_enable(0);
839
840 adie_proceed_to_stage(adie, ADIE_PATH_RX, ADIE_STAGE_ANALOG_OFF);
841 adie_proceed_to_stage(adie, ADIE_PATH_RX, ADIE_STAGE_DIGITAL_OFF);
842}
843
844static void _audio_tx_path_disable(void)
845{
846 audio_tx_analog_enable(0);
847
848 adie_proceed_to_stage(adie, ADIE_PATH_TX, ADIE_STAGE_ANALOG_OFF);
849 adie_proceed_to_stage(adie, ADIE_PATH_TX, ADIE_STAGE_DIGITAL_OFF);
850}
851
852static int icodec_rx_clk_refcount;
853static int icodec_tx_clk_refcount;
854static int ecodec_clk_refcount;
855static int sdac_clk_refcount;
856
857static void _audio_rx_clk_enable(void)
858{
859 uint32_t device_group = q6_device_to_codec(audio_rx_device_id);
860
861 switch (device_group) {
862 case Q6_ICODEC_RX:
863 icodec_rx_clk_refcount++;
864 if (icodec_rx_clk_refcount == 1) {
865 clk_set_rate(icodec_rx_clk, 12288000);
866 clk_enable(icodec_rx_clk);
867 }
868 break;
869 case Q6_ECODEC_RX:
870 ecodec_clk_refcount++;
871 if (ecodec_clk_refcount == 1) {
872 clk_set_rate(ecodec_clk, 2048000);
873 clk_enable(ecodec_clk);
874 }
875 break;
876 case Q6_SDAC_RX:
877 sdac_clk_refcount++;
878 if (sdac_clk_refcount == 1) {
879 clk_set_rate(sdac_clk, 12288000);
880 clk_enable(sdac_clk);
881 }
882 break;
883 default:
884 return;
885 }
886 audio_rx_device_group = device_group;
887}
888
889static void _audio_tx_clk_enable(void)
890{
891 uint32_t device_group = q6_device_to_codec(audio_tx_device_id);
892
893 switch (device_group) {
894 case Q6_ICODEC_TX:
895 icodec_tx_clk_refcount++;
896 if (icodec_tx_clk_refcount == 1) {
897 clk_set_rate(icodec_tx_clk, tx_clk_freq * 256);
898 clk_enable(icodec_tx_clk);
899 }
900 break;
901 case Q6_ECODEC_TX:
902 ecodec_clk_refcount++;
903 if (ecodec_clk_refcount == 1) {
904 clk_set_rate(ecodec_clk, 2048000);
905 clk_enable(ecodec_clk);
906 }
907 break;
908 case Q6_SDAC_TX:
909 /* TODO: In QCT BSP, clk rate was set to 20480000 */
910 sdac_clk_refcount++;
911 if (sdac_clk_refcount == 1) {
912 clk_set_rate(sdac_clk, 12288000);
913 clk_enable(sdac_clk);
914 }
915 break;
916 default:
917 return;
918 }
919 audio_tx_device_group = device_group;
920}
921
922static void _audio_rx_clk_disable(void)
923{
924 switch (audio_rx_device_group) {
925 case Q6_ICODEC_RX:
926 icodec_rx_clk_refcount--;
927 if (icodec_rx_clk_refcount == 0) {
928 clk_disable(icodec_rx_clk);
929 audio_rx_device_group = -1;
930 }
931 break;
932 case Q6_ECODEC_RX:
933 ecodec_clk_refcount--;
934 if (ecodec_clk_refcount == 0) {
935 clk_disable(ecodec_clk);
936 audio_rx_device_group = -1;
937 }
938 break;
939 case Q6_SDAC_RX:
940 sdac_clk_refcount--;
941 if (sdac_clk_refcount == 0) {
942 clk_disable(sdac_clk);
943 audio_rx_device_group = -1;
944 }
945 break;
946 default:
947 pr_err("audiolib: invalid rx device group %d\n",
948 audio_rx_device_group);
949 break;
950 }
951}
952
953static void _audio_tx_clk_disable(void)
954{
955 switch (audio_tx_device_group) {
956 case Q6_ICODEC_TX:
957 icodec_tx_clk_refcount--;
958 if (icodec_tx_clk_refcount == 0) {
959 clk_disable(icodec_tx_clk);
960 audio_tx_device_group = -1;
961 }
962 break;
963 case Q6_ECODEC_TX:
964 ecodec_clk_refcount--;
965 if (ecodec_clk_refcount == 0) {
966 clk_disable(ecodec_clk);
967 audio_tx_device_group = -1;
968 }
969 break;
970 case Q6_SDAC_TX:
971 sdac_clk_refcount--;
972 if (sdac_clk_refcount == 0) {
973 clk_disable(sdac_clk);
974 audio_tx_device_group = -1;
975 }
976 break;
977 default:
978 pr_err("audiolib: invalid tx device group %d\n",
979 audio_tx_device_group);
980 break;
981 }
982}
983
984static void _audio_rx_clk_reinit(uint32_t rx_device)
985{
986 uint32_t device_group = q6_device_to_codec(rx_device);
987
988 if (device_group != audio_rx_device_group)
989 _audio_rx_clk_disable();
990
991 audio_rx_device_id = rx_device;
992 audio_rx_path_id = q6_device_to_path(rx_device);
993
994 if (device_group != audio_rx_device_group)
995 _audio_rx_clk_enable();
996
997}
998
999static void _audio_tx_clk_reinit(uint32_t tx_device)
1000{
1001 uint32_t device_group = q6_device_to_codec(tx_device);
1002
1003 if (device_group != audio_tx_device_group)
1004 _audio_tx_clk_disable();
1005
1006 audio_tx_device_id = tx_device;
1007 audio_tx_path_id = q6_device_to_path(tx_device);
1008
1009 if (device_group != audio_tx_device_group)
1010 _audio_tx_clk_enable();
1011}
1012
1013static DEFINE_MUTEX(audio_path_lock);
1014static int audio_rx_path_refcount;
1015static int audio_tx_path_refcount;
1016
1017static int audio_rx_path_enable(int en)
1018{
1019 mutex_lock(&audio_path_lock);
1020 if (en) {
1021 audio_rx_path_refcount++;
1022 if (audio_rx_path_refcount == 1) {
1023 adie_enable();
1024 _audio_rx_clk_enable();
1025 _audio_rx_path_enable();
1026 }
1027 } else {
1028 audio_rx_path_refcount--;
1029 if (audio_rx_path_refcount == 0) {
1030 _audio_rx_path_disable();
1031 _audio_rx_clk_disable();
1032 adie_disable();
1033 }
1034 }
1035 mutex_unlock(&audio_path_lock);
1036 return 0;
1037}
1038
1039static int audio_tx_path_enable(int en)
1040{
1041 mutex_lock(&audio_path_lock);
1042 if (en) {
1043 audio_tx_path_refcount++;
1044 if (audio_tx_path_refcount == 1) {
1045 adie_enable();
1046 _audio_tx_clk_enable();
1047 _audio_tx_path_enable();
1048 }
1049 } else {
1050 audio_tx_path_refcount--;
1051 if (audio_tx_path_refcount == 0) {
1052 _audio_tx_path_disable();
1053 _audio_tx_clk_disable();
1054 adie_disable();
1055 }
1056 }
1057 mutex_unlock(&audio_path_lock);
1058 return 0;
1059}
1060
1061int q6audio_update_acdb(uint32_t id_src, uint32_t id_dst)
1062{
1063 mutex_lock(&audio_path_lock);
1064 mutex_unlock(&audio_path_lock);
1065 return 0;
1066}
1067
1068int q6audio_set_tx_mute(int mute)
1069{
1070 uint32_t adev;
1071 int rc;
1072
1073 if (q6audio_init())
1074 return 0;
1075
1076 mutex_lock(&audio_path_lock);
1077
1078 if (mute == tx_mute_status) {
1079 mutex_unlock(&audio_path_lock);
1080 return 0;
1081 }
1082
1083 adev = audio_tx_device_id;
1084 rc = audio_tx_mute(ac_control, adev, mute);
1085 if (!rc)
1086 tx_mute_status = mute;
1087 mutex_unlock(&audio_path_lock);
1088 return 0;
1089}
1090
1091int q6audio_set_rx_volume(int level)
1092{
1093 uint32_t adev;
1094 int vol;
1095
1096 if (q6audio_init())
1097 return 0;
1098
1099 if (level < 0 || level > 100)
1100 return -EINVAL;
1101
1102 mutex_lock(&audio_path_lock);
1103 adev = audio_rx_device_id;
1104 vol = q6_device_volume(adev, level);
1105 audio_rx_mute(ac_control, adev, 0);
1106 audio_rx_volume(ac_control, adev, vol);
1107 mutex_unlock(&audio_path_lock);
1108 return 0;
1109}
1110
1111static void do_rx_routing(uint32_t device_id)
1112{
1113 int sz;
1114 uint32_t sample_rate;
1115
1116 if (device_id == audio_rx_device_id)
1117 return;
1118
1119 if (audio_rx_path_refcount > 0) {
1120 qdsp6_devchg_notify(ac_control, ADSP_AUDIO_RX_DEVICE,
1121 device_id);
1122 _audio_rx_path_disable();
1123 _audio_rx_clk_reinit(device_id);
1124 _audio_rx_path_enable();
1125 } else {
1126 sample_rate = q6_device_to_rate(device_id);
1127 sz = acdb_get_config_table(device_id, sample_rate);
1128 if (sz < 0)
1129 pr_err("could not get ACDB config table\n");
1130
1131 audio_set_table(ac_control, device_id, sz);
1132 qdsp6_devchg_notify(ac_control, ADSP_AUDIO_RX_DEVICE,
1133 device_id);
1134 qdsp6_standby(ac_control);
1135 qdsp6_start(ac_control);
1136 audio_rx_device_id = device_id;
1137 audio_rx_path_id = q6_device_to_path(device_id);
1138 }
1139}
1140
1141static void do_tx_routing(uint32_t device_id)
1142{
1143 int sz;
1144 uint32_t sample_rate;
1145
1146 if (device_id == audio_tx_device_id)
1147 return;
1148
1149 if (audio_tx_path_refcount > 0) {
1150 qdsp6_devchg_notify(ac_control, ADSP_AUDIO_TX_DEVICE,
1151 device_id);
1152 _audio_tx_path_disable();
1153 _audio_tx_clk_reinit(device_id);
1154 _audio_tx_path_enable();
1155 } else {
1156 sample_rate = q6_device_to_rate(device_id);
1157 sz = acdb_get_config_table(device_id, sample_rate);
1158 audio_set_table(ac_control, device_id, sz);
1159 qdsp6_devchg_notify(ac_control, ADSP_AUDIO_TX_DEVICE,
1160 device_id);
1161 qdsp6_standby(ac_control);
1162 qdsp6_start(ac_control);
1163 audio_tx_device_id = device_id;
1164 audio_tx_path_id = q6_device_to_path(device_id);
1165 }
1166}
1167
1168int q6audio_do_routing(uint32_t device_id)
1169{
1170 if (q6audio_init())
1171 return 0;
1172
1173 mutex_lock(&audio_path_lock);
1174
1175 switch (q6_device_to_dir(device_id)) {
1176 case Q6_RX:
1177 do_rx_routing(device_id);
1178 break;
1179 case Q6_TX:
1180 do_tx_routing(device_id);
1181 break;
1182 }
1183
1184 mutex_unlock(&audio_path_lock);
1185 return 0;
1186}
1187
1188int q6audio_set_route(const char *name)
1189{
1190 uint32_t route;
1191 if (!strcmp(name, "speaker"))
1192 route = ADIE_PATH_SPEAKER_STEREO_RX;
1193 else if (!strcmp(name, "headphones"))
1194 route = ADIE_PATH_HEADSET_STEREO_RX;
1195 else if (!strcmp(name, "handset"))
1196 route = ADIE_PATH_HANDSET_RX;
1197 else
1198 return -EINVAL;
1199
1200 mutex_lock(&audio_path_lock);
1201 if (route == audio_rx_path_id)
1202 goto done;
1203
1204 audio_rx_path_id = route;
1205
1206 if (audio_rx_path_refcount > 0) {
1207 _audio_rx_path_disable();
1208 _audio_rx_path_enable();
1209 }
1210 if (audio_tx_path_refcount > 0) {
1211 _audio_tx_path_disable();
1212 _audio_tx_path_enable();
1213 }
1214done:
1215 mutex_unlock(&audio_path_lock);
1216 return 0;
1217}
1218
1219struct audio_client *q6audio_open(uint32_t flags, uint32_t bufsz)
1220{
1221 struct audio_client *ac;
1222
1223 if (q6audio_init())
1224 return 0;
1225
1226 ac = audio_client_alloc(bufsz);
1227 if (!ac)
1228 return 0;
1229
1230 ac->flags = flags;
1231 if (ac->flags & AUDIO_FLAG_WRITE)
1232 audio_rx_path_enable(1);
1233 else
1234 audio_tx_path_enable(1);
1235
1236 return ac;
1237}
1238
1239int q6audio_start(struct audio_client *ac, void *rpc,
1240 uint32_t len)
1241{
1242
1243 audio_ioctl(ac, rpc, len);
1244
1245 audio_command(ac, ADSP_AUDIO_IOCTL_CMD_SESSION_START);
1246
1247 if (!(ac->flags & AUDIO_FLAG_WRITE)) {
1248 ac->buf[0].used = 1;
1249 ac->buf[1].used = 1;
1250 q6audio_read(ac, &ac->buf[0]);
1251 q6audio_read(ac, &ac->buf[1]);
1252 }
1253
1254 audio_prevent_sleep();
1255 return 0;
1256}
1257
1258int q6audio_close(struct audio_client *ac)
1259{
1260 audio_close(ac);
1261
1262 if (ac->flags & AUDIO_FLAG_WRITE)
1263 audio_rx_path_enable(0);
1264 else
1265 audio_tx_path_enable(0);
1266
1267 audio_client_free(ac);
1268 audio_allow_sleep();
1269 return 0;
1270}
1271
1272struct audio_client *q6voice_open(void)
1273{
1274 struct audio_client *ac;
1275
1276 if (q6audio_init())
1277 return 0;
1278
1279 ac = audio_client_alloc(0);
1280 if (!ac)
1281 return 0;
1282
1283 return ac;
1284}
1285
1286int q6voice_setup(void)
1287{
1288 audio_rx_path_enable(1);
1289 tx_clk_freq = 8000;
1290 audio_tx_path_enable(1);
1291
1292 return 0;
1293}
1294
1295int q6voice_teardown(void)
1296{
1297 audio_rx_path_enable(0);
1298 audio_tx_path_enable(0);
1299 return 0;
1300}
1301
1302
1303int q6voice_close(struct audio_client *ac)
1304{
1305 audio_client_free(ac);
1306 return 0;
1307}
1308
1309int q6audio_async(struct audio_client *ac)
1310{
1311 struct adsp_command_hdr rpc;
1312 memset(&rpc, 0, sizeof(rpc));
1313 rpc.opcode = ADSP_AUDIO_IOCTL_CMD_STREAM_EOS;
1314 rpc.response_type = ADSP_AUDIO_RESPONSE_ASYNC;
1315 return audio_ioctl(ac, &rpc, sizeof(rpc));
1316}