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