blob: 7c34b22493f4b19e5ea07e7868934acbbe5854f2 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/init.h>
14#include <linux/err.h>
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/time.h>
18#include <linux/wait.h>
19#include <linux/platform_device.h>
20#include <linux/dma-mapping.h>
21#include <linux/msm_audio.h>
22#include <sound/core.h>
23#include <sound/soc.h>
24#include <sound/soc-dapm.h>
25#include <sound/pcm.h>
26#include <sound/tlv.h>
27#include <sound/initval.h>
28#include <sound/control.h>
29#include <sound/q6afe.h>
30#include <asm/dma.h>
31#include <asm/mach-types.h>
32#include <mach/qdsp6v2/audio_dev_ctl.h>
33
34#define LOOPBACK_ENABLE 0x1
35#define LOOPBACK_DISABLE 0x0
36
37#include "msm8x60-pcm.h"
38
39static struct platform_device *msm_audio_snd_device;
40struct audio_locks the_locks;
41EXPORT_SYMBOL(the_locks);
42struct msm_volume msm_vol_ctl;
43EXPORT_SYMBOL(msm_vol_ctl);
44struct pcm_session session_route;
45EXPORT_SYMBOL(session_route);
46static struct snd_kcontrol_new snd_msm_controls[];
47
48char snddev_name[AUDIO_DEV_CTL_MAX_DEV][44];
49#define MSM_MAX_VOLUME 0x2000
50#define MSM_VOLUME_STEP ((MSM_MAX_VOLUME+17)/100) /* 17 added to avoid
51 more deviation */
52static int device_index; /* Count of Device controls */
53static int simple_control; /* Count of simple controls*/
54static int src_dev;
55static int dst_dev;
56static int loopback_status;
57
58static int msm_scontrol_count_info(struct snd_kcontrol *kcontrol,
59 struct snd_ctl_elem_info *uinfo)
60{
61 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
62 uinfo->count = 1;
63 return 0;
64}
65
66static int msm_scontrol_count_get(struct snd_kcontrol *kcontrol,
67 struct snd_ctl_elem_value *ucontrol)
68{
69 ucontrol->value.integer.value[0] = simple_control;
70 return 0;
71}
72
73static int msm_v_call_info(struct snd_kcontrol *kcontrol,
74 struct snd_ctl_elem_info *uinfo)
75{
76 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
77 uinfo->count = 1;
78 uinfo->value.integer.min = 0;
79 uinfo->value.integer.max = 1;
80 return 0;
81}
82
83static int msm_v_call_get(struct snd_kcontrol *kcontrol,
84 struct snd_ctl_elem_value *ucontrol)
85{
86 ucontrol->value.integer.value[0] = 0;
87 return 0;
88}
89
90static int msm_v_call_put(struct snd_kcontrol *kcontrol,
91 struct snd_ctl_elem_value *ucontrol)
92{
93 int start = ucontrol->value.integer.value[0];
94 if (start)
95 broadcast_event(AUDDEV_EVT_START_VOICE, DEVICE_IGNORE,
96 SESSION_IGNORE);
97 else
98 broadcast_event(AUDDEV_EVT_END_VOICE, DEVICE_IGNORE,
99 SESSION_IGNORE);
100 return 0;
101}
102
103static int msm_v_mute_info(struct snd_kcontrol *kcontrol,
104 struct snd_ctl_elem_info *uinfo)
105{
106 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
107 uinfo->count = 2;
108 uinfo->value.integer.min = 0;
109 uinfo->value.integer.max = 2;
110 return 0;
111}
112
113static int msm_v_mute_get(struct snd_kcontrol *kcontrol,
114 struct snd_ctl_elem_value *ucontrol)
115{
116 ucontrol->value.integer.value[0] = 0;
117 return 0;
118}
119
120static int msm_v_mute_put(struct snd_kcontrol *kcontrol,
121 struct snd_ctl_elem_value *ucontrol)
122{
123 int dir = ucontrol->value.integer.value[0];
124 int mute = ucontrol->value.integer.value[1];
125 return msm_set_voice_mute(dir, mute);
126}
127
128static int msm_v_volume_info(struct snd_kcontrol *kcontrol,
129 struct snd_ctl_elem_info *uinfo)
130{
131 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
132 uinfo->count = 2; /* Volume */
133 uinfo->value.integer.min = 0;
134 uinfo->value.integer.max = 100;
135 return 0;
136}
137
138static int msm_v_volume_get(struct snd_kcontrol *kcontrol,
139 struct snd_ctl_elem_value *ucontrol)
140{
141 ucontrol->value.integer.value[0] = 0;
142 return 0;
143}
144
145static int msm_v_volume_put(struct snd_kcontrol *kcontrol,
146 struct snd_ctl_elem_value *ucontrol)
147{
148 int dir = ucontrol->value.integer.value[0];
149 int volume = ucontrol->value.integer.value[1];
150
151 return msm_set_voice_vol(dir, volume);
152}
153
154static int msm_volume_info(struct snd_kcontrol *kcontrol,
155 struct snd_ctl_elem_info *uinfo)
156{
157 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
158 uinfo->count = 2; /* Volume */
159 uinfo->value.integer.min = 0;
160 uinfo->value.integer.max = 16383;
161 return 0;
162}
163static int msm_volume_get(struct snd_kcontrol *kcontrol,
164 struct snd_ctl_elem_value *ucontrol)
165{
166 ucontrol->value.integer.value[0] = 0;
167 return 0;
168}
169
170static int msm_volume_put(struct snd_kcontrol *kcontrol,
171 struct snd_ctl_elem_value *ucontrol)
172{
173 int ret = 0;
174 int session_id = ucontrol->value.integer.value[0];
175 int volume = ucontrol->value.integer.value[1];
176 int factor = ucontrol->value.integer.value[2];
177 u64 session_mask = 0;
178
179 if (factor > 10000)
180 return -EINVAL;
181
182 if ((volume < 0) || (volume/factor > 100))
183 return -EINVAL;
184
185 volume = (MSM_VOLUME_STEP * volume);
186
187 /* Convert back to original decimal point by removing the 10-base factor
188 * and discard the fractional portion
189 */
190
191 volume = volume/factor;
192
193 if (volume > MSM_MAX_VOLUME)
194 volume = MSM_MAX_VOLUME;
195
196 /* Only Decoder volume control supported */
197 session_mask = (((u64)0x1) << session_id) << (MAX_BIT_PER_CLIENT * \
198 ((int)AUDDEV_CLNT_DEC-1));
199 msm_vol_ctl.volume = volume;
200 pr_debug("%s:session_id %d, volume %d", __func__, session_id, volume);
201 broadcast_event(AUDDEV_EVT_STREAM_VOL_CHG, DEVICE_IGNORE,
202 session_mask);
203
204 return ret;
205}
206
207static int msm_voice_info(struct snd_kcontrol *kcontrol,
208 struct snd_ctl_elem_info *uinfo)
209{
210 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
211 uinfo->count = 3; /* Device */
212
213 uinfo->value.integer.min = 0;
214 uinfo->value.integer.max = msm_snddev_devcount();
215 return 0;
216}
217
218static int msm_voice_put(struct snd_kcontrol *kcontrol,
219 struct snd_ctl_elem_value *ucontrol)
220{
221 int rc = 0;
222 uint32_t rx_dev_id;
223 uint32_t tx_dev_id;
224 struct msm_snddev_info *rx_dev_info;
225 struct msm_snddev_info *tx_dev_info;
226 int set = ucontrol->value.integer.value[2];
227 u64 session_mask;
228
229 if (!set)
230 return -EPERM;
231 /* Rx Device Routing */
232 rx_dev_id = ucontrol->value.integer.value[0];
233 rx_dev_info = audio_dev_ctrl_find_dev(rx_dev_id);
234
235 if (IS_ERR(rx_dev_info)) {
236 pr_err("%s:pass invalid dev_id\n", __func__);
237 rc = PTR_ERR(rx_dev_info);
238 return rc;
239 }
240
241 if (!(rx_dev_info->capability & SNDDEV_CAP_RX)) {
242 pr_err("%s:First Dev is supposed to be RX\n", __func__);
243 return -EFAULT;
244 }
245
246 pr_debug("%s:route cfg %d STREAM_VOICE_RX type\n",
247 __func__, rx_dev_id);
248
249 msm_set_voc_route(rx_dev_info, AUDIO_ROUTE_STREAM_VOICE_RX,
250 rx_dev_id);
251
252 session_mask = ((u64)0x1) << (MAX_BIT_PER_CLIENT * \
253 ((int)AUDDEV_CLNT_VOC-1));
254
255 broadcast_event(AUDDEV_EVT_DEV_CHG_VOICE, rx_dev_id, session_mask);
256
257
258 /* Tx Device Routing */
259 tx_dev_id = ucontrol->value.integer.value[1];
260 tx_dev_info = audio_dev_ctrl_find_dev(tx_dev_id);
261
262 if (IS_ERR(tx_dev_info)) {
263 pr_err("%s:pass invalid dev_id\n", __func__);
264 rc = PTR_ERR(tx_dev_info);
265 return rc;
266 }
267
268 if (!(tx_dev_info->capability & SNDDEV_CAP_TX)) {
269 pr_err("%s:Second Dev is supposed to be Tx\n", __func__);
270 return -EFAULT;
271 }
272
273 pr_debug("%s:route cfg %d %d type\n",
274 __func__, tx_dev_id, AUDIO_ROUTE_STREAM_VOICE_TX);
275
276 msm_set_voc_route(tx_dev_info, AUDIO_ROUTE_STREAM_VOICE_TX,
277 tx_dev_id);
278
279 broadcast_event(AUDDEV_EVT_DEV_CHG_VOICE, tx_dev_id, session_mask);
280
281 if (rx_dev_info->opened)
282 broadcast_event(AUDDEV_EVT_DEV_RDY, rx_dev_id, session_mask);
283
284 if (tx_dev_info->opened)
285 broadcast_event(AUDDEV_EVT_DEV_RDY, tx_dev_id, session_mask);
286
287 return rc;
288}
289
290static int msm_voice_get(struct snd_kcontrol *kcontrol,
291 struct snd_ctl_elem_value *ucontrol)
292{
293 ucontrol->value.integer.value[0] = 0;
294 /* TODO: query Device list */
295 return 0;
296}
297
298static int msm_device_info(struct snd_kcontrol *kcontrol,
299 struct snd_ctl_elem_info *uinfo)
300{
301 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
302 uinfo->count = 1; /* Device */
303
304 uinfo->value.integer.min = 0;
305 uinfo->value.integer.max = msm_snddev_devcount();
306 return 0;
307}
308
309static int msm_device_put(struct snd_kcontrol *kcontrol,
310 struct snd_ctl_elem_value *ucontrol)
311{
312 int rc = 0;
313 int set = 0;
314 struct msm_audio_route_config route_cfg;
315 struct msm_snddev_info *dev_info;
316 struct msm_snddev_info *dst_dev_info;
317 struct msm_snddev_info *src_dev_info;
318 int tx_freq = 0;
319 int rx_freq = 0;
320 u32 set_freq = 0;
321
322 set = ucontrol->value.integer.value[0];
323 route_cfg.dev_id = ucontrol->id.numid - device_index;
324 dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id);
325 if (IS_ERR(dev_info)) {
326 pr_err("%s:pass invalid dev_id\n", __func__);
327 rc = PTR_ERR(dev_info);
328 return rc;
329 }
330 pr_info("%s:device %s set %d\n", __func__, dev_info->name, set);
331
332 if (set) {
333 if (!dev_info->opened) {
334 set_freq = dev_info->sample_rate;
335 if (!msm_device_is_voice(route_cfg.dev_id)) {
336 msm_get_voc_freq(&tx_freq, &rx_freq);
337 if (dev_info->capability & SNDDEV_CAP_TX)
338 set_freq = tx_freq;
339
340 if (set_freq == 0)
341 set_freq = dev_info->sample_rate;
342 } else
343 set_freq = dev_info->sample_rate;
344
345
346 pr_err("%s:device freq =%d\n", __func__, set_freq);
347 rc = dev_info->dev_ops.set_freq(dev_info, set_freq);
348 if (rc < 0) {
349 pr_err("%s:device freq failed!\n", __func__);
350 return rc;
351 }
352 dev_info->set_sample_rate = rc;
353 rc = 0;
354 rc = dev_info->dev_ops.open(dev_info);
355 if (rc < 0) {
356 pr_err("%s:Enabling %s failed\n",
357 __func__, dev_info->name);
358 return rc;
359 }
360 dev_info->opened = 1;
361 broadcast_event(AUDDEV_EVT_DEV_RDY, route_cfg.dev_id,
362 SESSION_IGNORE);
363 if ((route_cfg.dev_id == src_dev) ||
364 (route_cfg.dev_id == dst_dev)) {
365 dst_dev_info = audio_dev_ctrl_find_dev(
366 dst_dev);
367 if (IS_ERR(dst_dev_info)) {
368 pr_err("dst_dev:%s:pass invalid"
369 "dev_id\n", __func__);
370 rc = PTR_ERR(dst_dev_info);
371 return rc;
372 }
373 src_dev_info = audio_dev_ctrl_find_dev(
374 src_dev);
375 if (IS_ERR(src_dev_info)) {
376 pr_err("src_dev:%s:pass invalid"
377 "dev_id\n", __func__);
378 rc = PTR_ERR(src_dev_info);
379 return rc;
380 }
381 if ((dst_dev_info->opened) &&
382 (src_dev_info->opened)) {
383 pr_debug("%d: Enable afe_loopback\n",
384 __LINE__);
385 afe_loopback(LOOPBACK_ENABLE,
386 dst_dev_info->copp_id,
387 src_dev_info->copp_id);
388 loopback_status = 1;
389 }
390 }
391 }
392 } else {
393 if (dev_info->opened) {
394 broadcast_event(AUDDEV_EVT_REL_PENDING,
395 route_cfg.dev_id,
396 SESSION_IGNORE);
397 rc = dev_info->dev_ops.close(dev_info);
398 if (rc < 0) {
399 pr_err("%s:Snd device failed close!\n",
400 __func__);
401 return rc;
402 } else {
403 dev_info->opened = 0;
404 broadcast_event(AUDDEV_EVT_DEV_RLS,
405 route_cfg.dev_id,
406 SESSION_IGNORE);
407 }
408 if (loopback_status == 1) {
409 if ((route_cfg.dev_id == src_dev) ||
410 (route_cfg.dev_id == dst_dev)) {
411 dst_dev_info = audio_dev_ctrl_find_dev(
412 dst_dev);
413 if (IS_ERR(dst_dev_info)) {
414 pr_err("dst_dev:%s:pass invalid"
415 "dev_id\n", __func__);
416 rc = PTR_ERR(dst_dev_info);
417 return rc;
418 }
419 src_dev_info = audio_dev_ctrl_find_dev(
420 src_dev);
421 if (IS_ERR(src_dev_info)) {
422 pr_err("src_dev:%s:pass invalid"
423 "dev_id\n", __func__);
424 rc = PTR_ERR(src_dev_info);
425 return rc;
426 }
427 pr_debug("%d: Disable afe_loopback\n",
428 __LINE__);
429 afe_loopback(LOOPBACK_DISABLE,
430 dst_dev_info->copp_id,
431 src_dev_info->copp_id);
432 loopback_status = 0;
433 }
434 }
435 }
436
437 }
438 return rc;
439}
440
441static int msm_device_get(struct snd_kcontrol *kcontrol,
442 struct snd_ctl_elem_value *ucontrol)
443{
444 int rc = 0;
445 struct msm_audio_route_config route_cfg;
446 struct msm_snddev_info *dev_info;
447
448 route_cfg.dev_id = ucontrol->id.numid - device_index;
449 dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id);
450
451 if (IS_ERR(dev_info)) {
452 pr_err("%s:pass invalid dev_id\n", __func__);
453 rc = PTR_ERR(dev_info);
454 return rc;
455 }
456
457 ucontrol->value.integer.value[0] = dev_info->copp_id;
458 ucontrol->value.integer.value[1] = dev_info->capability;
459
460 return 0;
461}
462
463static int msm_route_info(struct snd_kcontrol *kcontrol,
464 struct snd_ctl_elem_info *uinfo)
465{
466 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
467 uinfo->count = 3; /* Device */
468
469 uinfo->value.integer.min = 0;
470 uinfo->value.integer.max = msm_snddev_devcount();
471 return 0;
472}
473
474static int msm_route_get(struct snd_kcontrol *kcontrol,
475 struct snd_ctl_elem_value *ucontrol)
476{
477 ucontrol->value.integer.value[0] = 0;
478 /* TODO: query Device list */
479 return 0;
480}
481
482static int msm_route_put(struct snd_kcontrol *kcontrol,
483 struct snd_ctl_elem_value *ucontrol)
484{
485 int rc = 0;
486 int enc_freq = 0;
487 int requested_freq = 0;
488 struct msm_audio_route_config route_cfg;
489 struct msm_snddev_info *dev_info;
490 int session_id = ucontrol->value.integer.value[0];
491 int set = ucontrol->value.integer.value[2];
492 u64 session_mask = 0;
493 route_cfg.dev_id = ucontrol->value.integer.value[1];
494
495 if (ucontrol->id.numid == 2)
496 route_cfg.stream_type = AUDIO_ROUTE_STREAM_PLAYBACK;
497 else
498 route_cfg.stream_type = AUDIO_ROUTE_STREAM_REC;
499
500 pr_debug("%s:route cfg %d %d type for popp %d\n",
501 __func__, route_cfg.dev_id, route_cfg.stream_type, session_id);
502 dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id);
503
504 if (IS_ERR(dev_info)) {
505 pr_err("%s:pass invalid dev_id\n", __func__);
506 rc = PTR_ERR(dev_info);
507 return rc;
508 }
509 if (route_cfg.stream_type == AUDIO_ROUTE_STREAM_PLAYBACK) {
510 rc = msm_snddev_set_dec(session_id, dev_info->copp_id, set,
511 dev_info->sample_rate, dev_info->channel_mode);
512 session_mask =
513 (((u64)0x1) << session_id) << (MAX_BIT_PER_CLIENT * \
514 ((int)AUDDEV_CLNT_DEC-1));
515 if (!set) {
516 if (dev_info->opened)
517 broadcast_event(AUDDEV_EVT_DEV_RLS,
518 route_cfg.dev_id,
519 session_mask);
520 dev_info->sessions &= ~(session_mask);
521 } else {
522 dev_info->sessions = dev_info->sessions | session_mask;
523 if (dev_info->opened)
524 broadcast_event(AUDDEV_EVT_DEV_RDY,
525 route_cfg.dev_id,
526 session_mask);
527 }
528 } else {
529
530 rc = msm_snddev_set_enc(session_id, dev_info->copp_id, set,
531 dev_info->sample_rate, dev_info->channel_mode);
532 session_mask =
533 (((u64)0x1) << session_id) << (MAX_BIT_PER_CLIENT * \
534 ((int)AUDDEV_CLNT_ENC-1));
535 if (!set) {
536 if (dev_info->opened)
537 broadcast_event(AUDDEV_EVT_DEV_RLS,
538 route_cfg.dev_id,
539 session_mask);
540 dev_info->sessions &= ~(session_mask);
541 } else {
542 dev_info->sessions = dev_info->sessions | session_mask;
543 enc_freq = msm_snddev_get_enc_freq(session_id);
544 requested_freq = enc_freq;
545 if (enc_freq > 0) {
546 rc = msm_snddev_request_freq(&enc_freq,
547 session_id,
548 SNDDEV_CAP_TX,
549 AUDDEV_CLNT_ENC);
550 pr_debug("%s:sample rate configured %d\
551 sample rate requested %d \n",
552 __func__, enc_freq, requested_freq);
553 if ((rc <= 0) || (enc_freq != requested_freq)) {
554 pr_debug("%s:msm_snddev_withdraw_freq\n",
555 __func__);
556 rc = msm_snddev_withdraw_freq
557 (session_id,
558 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
559 broadcast_event(AUDDEV_EVT_FREQ_CHG,
560 route_cfg.dev_id,
561 SESSION_IGNORE);
562 }
563 }
564 if (dev_info->opened)
565 broadcast_event(AUDDEV_EVT_DEV_RDY,
566 route_cfg.dev_id,
567 session_mask);
568 }
569 }
570
571 if (rc < 0) {
572 pr_err("%s:device could not be assigned!\n", __func__);
573 return -EFAULT;
574 }
575
576 return rc;
577}
578
579static int msm_device_volume_info(struct snd_kcontrol *kcontrol,
580 struct snd_ctl_elem_info *uinfo)
581{
582 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
583 uinfo->count = 2;
584 uinfo->value.integer.min = 0;
585 uinfo->value.integer.max = 100;
586 return 0;
587}
588
589static int msm_device_volume_get(struct snd_kcontrol *kcontrol,
590 struct snd_ctl_elem_value *ucontrol)
591{
592 struct msm_snddev_info *dev_info;
593
594 int dev_id = ucontrol->value.integer.value[0];
595
596 dev_info = audio_dev_ctrl_find_dev(dev_id);
597 ucontrol->value.integer.value[0] = dev_info->dev_volume;
598
599 return 0;
600}
601
602static int msm_device_volume_put(struct snd_kcontrol *kcontrol,
603 struct snd_ctl_elem_value *ucontrol)
604{
605 int rc = -EPERM;
606 struct msm_snddev_info *dev_info;
607
608 int dev_id = ucontrol->value.integer.value[0];
609 int volume = ucontrol->value.integer.value[1];
610
611 pr_debug("%s:dev_id = %d, volume = %d\n", __func__, dev_id, volume);
612
613 dev_info = audio_dev_ctrl_find_dev(dev_id);
614
615 if (IS_ERR(dev_info)) {
616 rc = PTR_ERR(dev_info);
617 pr_err("%s: audio_dev_ctrl_find_dev failed. %ld \n",
618 __func__, PTR_ERR(dev_info));
619 return rc;
620 }
621
622 pr_debug("%s:dev_name = %s dev_id = %d, volume = %d\n",
623 __func__, dev_info->name, dev_id, volume);
624
625 if (dev_info->dev_ops.set_device_volume)
626 rc = dev_info->dev_ops.set_device_volume(dev_info, volume);
627 else {
628 pr_info("%s : device %s does not support device volume "
629 "control.", __func__, dev_info->name);
630 return -EPERM;
631 }
632
633 return rc;
634}
635
636static int msm_reset_info(struct snd_kcontrol *kcontrol,
637 struct snd_ctl_elem_info *uinfo)
638{
639 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
640 uinfo->count = 1;
641 uinfo->value.integer.min = 0;
642 uinfo->value.integer.max = 0;
643 return 0;
644}
645
646static int msm_reset_get(struct snd_kcontrol *kcontrol,
647 struct snd_ctl_elem_value *ucontrol)
648{
649 ucontrol->value.integer.value[0] = 0;
650 return 0;
651}
652
653static int msm_reset_put(struct snd_kcontrol *kcontrol,
654 struct snd_ctl_elem_value *ucontrol)
655{
656 pr_err("%s:Resetting all devices\n", __func__);
657 return msm_reset_all_device();
658}
659
660static int msm_anc_info(struct snd_kcontrol *kcontrol,
661 struct snd_ctl_elem_info *uinfo)
662{
663 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
664 uinfo->count = 1;
665 uinfo->value.integer.min = 0;
666 uinfo->value.integer.max = 1;
667 return 0;
668}
669
670static int msm_anc_get(struct snd_kcontrol *kcontrol,
671 struct snd_ctl_elem_value *ucontrol)
672{
673 ucontrol->value.integer.value[0] = 0;
674 return 0;
675}
676
677static int msm_anc_put(struct snd_kcontrol *kcontrol,
678 struct snd_ctl_elem_value *ucontrol)
679{
680 int rc = -EPERM;
681 struct msm_snddev_info *dev_info;
682
683 int dev_id = ucontrol->value.integer.value[0];
684 int enable = ucontrol->value.integer.value[1];
685
686 pr_debug("%s: dev_id = %d, enable = %d\n", __func__, dev_id, enable);
687 dev_info = audio_dev_ctrl_find_dev(dev_id);
688
689 if (IS_ERR(dev_info)) {
690 rc = PTR_ERR(dev_info);
691 pr_err("%s: audio_dev_ctrl_find_dev failed. %ld\n",
692 __func__, PTR_ERR(dev_info));
693 return rc;
694 }
695
696 if (dev_info->dev_ops.enable_anc) {
697 rc = dev_info->dev_ops.enable_anc(dev_info, enable);
698 } else {
699 pr_info("%s : device %s does not support anc control.",
700 __func__, dev_info->name);
701 return -EPERM;
702 }
703
704 return rc;
705}
706
707static int pcm_route_info(struct snd_kcontrol *kcontrol,
708 struct snd_ctl_elem_info *uinfo)
709{
710 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
711 /*
712 * First parameter is session id ~ subdevice number
713 * Second parameter is device id.
714 */
715 uinfo->count = 3;
716 uinfo->value.integer.min = 0;
717 uinfo->value.integer.max = msm_snddev_devcount();
718 return 0;
719}
720
721static int pcm_route_get_rx(struct snd_kcontrol *kcontrol,
722 struct snd_ctl_elem_value *ucontrol)
723{
724 return 0;
725}
726
727static int pcm_route_get_tx(struct snd_kcontrol *kcontrol,
728 struct snd_ctl_elem_value *ucontrol)
729{
730 return 0;
731}
732
733static int pcm_route_put_rx(struct snd_kcontrol *kcontrol,
734 struct snd_ctl_elem_value *ucontrol)
735{
736 int session_id = 0;
737 int set = 0;
738 struct msm_audio_route_config route_cfg;
739 struct msm_snddev_info *dev_info;
740 u64 session_mask = 0;
741
742 /*
743 * session id is incremented by one and stored as session id 0
744 * is being used by dsp currently. whereas user space would use
745 * subdevice number as session id.
746 */
747 session_id = ucontrol->value.integer.value[0];
748 route_cfg.dev_id = ucontrol->value.integer.value[1];
749 set = ucontrol->value.integer.value[2];
750
751 dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id);
752 if (IS_ERR(dev_info)) {
753 pr_err("pass invalid dev_id %d\n", route_cfg.dev_id);
754 return PTR_ERR(dev_info);
755 }
756 if (!(dev_info->capability & SNDDEV_CAP_RX))
757 return -EINVAL;
758 session_mask =
759 (((u64)0x1) << session_id) << (MAX_BIT_PER_CLIENT * \
760 ((int)AUDDEV_CLNT_DEC-1));
761 if (!set) {
762 session_route.playback_session[session_id][dev_info->copp_id]
763 = DEVICE_IGNORE;
764 broadcast_event(AUDDEV_EVT_DEV_RLS,
765 route_cfg.dev_id,
766 session_mask);
767 dev_info->sessions &= ~(session_mask);
768 return 0;
769 }
770 pr_debug("%s:Routing playback session %d to %s\n",
771 __func__, (session_id),
772 dev_info->name);
773 session_route.playback_session[session_id][dev_info->copp_id] =
774 dev_info->copp_id;
775 if (dev_info->opened) {
776 dev_info->sessions = dev_info->sessions | session_mask;
777 broadcast_event(AUDDEV_EVT_DEV_RDY,
778 route_cfg.dev_id,
779 session_mask);
780 } else {
781 broadcast_event(AUDDEV_EVT_DEV_RLS,
782 route_cfg.dev_id,
783 session_mask);
784 dev_info->sessions &= ~(session_mask);
785 }
786 return 0;
787}
788
789static int pcm_route_put_tx(struct snd_kcontrol *kcontrol,
790 struct snd_ctl_elem_value *ucontrol)
791{
792 int session_id = 0;
793 int set = 0;
794 struct msm_audio_route_config route_cfg;
795 struct msm_snddev_info *dev_info;
796 u64 session_mask = 0;
797
798 session_id = ucontrol->value.integer.value[0];
799 route_cfg.dev_id = ucontrol->value.integer.value[1];
800 set = ucontrol->value.integer.value[2];
801
802 dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id);
803 if (IS_ERR(dev_info)) {
804 pr_err("pass invalid dev_id %d\n", route_cfg.dev_id);
805 return PTR_ERR(dev_info);
806 }
807 pr_debug("%s:Routing capture session %d to %s\n", __func__,
808 session_id,
809 dev_info->name);
810 if (!(dev_info->capability & SNDDEV_CAP_TX))
811 return -EINVAL;
812 session_mask =
813 (((u64)0x1) << session_id) << (MAX_BIT_PER_CLIENT * \
814 ((int)AUDDEV_CLNT_ENC-1));
815 if (!set) {
816 session_route.capture_session[session_id][dev_info->copp_id]
817 = DEVICE_IGNORE;
818 broadcast_event(AUDDEV_EVT_DEV_RLS,
819 route_cfg.dev_id,
820 session_mask);
821 dev_info->sessions &= ~(session_mask);
822 return 0;
823 }
824
825 session_route.capture_session[session_id][dev_info->copp_id] =
826 dev_info->copp_id;
827 if (dev_info->opened) {
828 dev_info->sessions = dev_info->sessions | session_mask;
829 broadcast_event(AUDDEV_EVT_DEV_RDY,
830 route_cfg.dev_id,
831 session_mask);
832 } else {
833 broadcast_event(AUDDEV_EVT_DEV_RLS,
834 route_cfg.dev_id,
835 session_mask);
836 dev_info->sessions &= ~(session_mask);
837 }
838 return 0;
839}
840
841static int msm_loopback_info(struct snd_kcontrol *kcontrol,
842 struct snd_ctl_elem_info *uinfo)
843{
844 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
845 uinfo->count = 3;
846 uinfo->value.integer.min = 0;
847 uinfo->value.integer.max = msm_snddev_devcount();
848 return 0;
849}
850
851static int msm_loopback_get(struct snd_kcontrol *kcontrol,
852 struct snd_ctl_elem_value *ucontrol)
853{
854 ucontrol->value.integer.value[0] = 0;
855 return 0;
856}
857
858static int msm_loopback_put(struct snd_kcontrol *kcontrol,
859 struct snd_ctl_elem_value *ucontrol)
860{
861 int rc = 0;
862 struct msm_snddev_info *src_dev_info = NULL; /* TX device */
863 struct msm_snddev_info *dst_dev_info = NULL; /* RX device */
864 int dst_dev_id = ucontrol->value.integer.value[0];
865 int src_dev_id = ucontrol->value.integer.value[1];
866 int set = ucontrol->value.integer.value[2];
867
868 pr_debug("%s: dst=%d :src=%d set=%d\n", __func__,
869 dst_dev_id, src_dev_id, set);
870
871 dst_dev_info = audio_dev_ctrl_find_dev(dst_dev_id);
872 if (IS_ERR(dst_dev_info)) {
873 pr_err("dst_dev:%s:pass invalid dev_id\n", __func__);
874 rc = PTR_ERR(dst_dev_info);
875 return rc;
876 }
877 if (!(dst_dev_info->capability & SNDDEV_CAP_RX)) {
878 pr_err("Destination device %d is not RX device\n",
879 dst_dev_id);
880 return -EFAULT;
881 }
882
883 src_dev_info = audio_dev_ctrl_find_dev(src_dev_id);
884 if (IS_ERR(src_dev_info)) {
885 pr_err("src_dev:%s:pass invalid dev_id\n", __func__);
886 rc = PTR_ERR(src_dev_info);
887 return rc;
888 }
889 if (!(src_dev_info->capability & SNDDEV_CAP_TX)) {
890 pr_err("Source device %d is not TX device\n", src_dev_id);
891 return -EFAULT;
892 }
893
894 if (set) {
895 pr_debug("%s:%d:Enabling AFE_Loopback\n", __func__, __LINE__);
896 src_dev = src_dev_id;
897 dst_dev = dst_dev_id;
898 loopback_status = 1;
899 if ((dst_dev_info->opened) && (src_dev_info->opened))
900 rc = afe_loopback(LOOPBACK_ENABLE,
901 dst_dev_info->copp_id,
902 src_dev_info->copp_id);
903 } else {
904 pr_debug("%s:%d:Disabling AFE_Loopback\n", __func__, __LINE__);
905 src_dev = DEVICE_IGNORE;
906 dst_dev = DEVICE_IGNORE;
907 loopback_status = 0;
908 rc = afe_loopback(LOOPBACK_DISABLE,
909 dst_dev_info->copp_id,
910 src_dev_info->copp_id);
911 }
912 return rc;
913}
Laxminath Kasam885f5102011-07-14 10:20:21 +0530914static int msm_device_mute_info(struct snd_kcontrol *kcontrol,
915 struct snd_ctl_elem_info *uinfo)
916{
917 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
918 uinfo->count = 2;
919 uinfo->value.integer.min = 0;
920 uinfo->value.integer.max = msm_snddev_devcount();
921 return 0;
922}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700923
Laxminath Kasam885f5102011-07-14 10:20:21 +0530924static int msm_device_mute_get(struct snd_kcontrol *kcontrol,
925 struct snd_ctl_elem_value *ucontrol)
926{
927 return 0;
928}
929
930static int msm_device_mute_put(struct snd_kcontrol *kcontrol,
931 struct snd_ctl_elem_value *ucontrol)
932{
933 int dev_id = ucontrol->value.integer.value[0];
934 int mute = ucontrol->value.integer.value[1];
935 struct msm_snddev_info *dev_info;
936 int rc = 0;
937 u16 gain = 0x2000;
938
939 dev_info = audio_dev_ctrl_find_dev(dev_id);
940 if (IS_ERR(dev_info)) {
941 rc = PTR_ERR(dev_info);
942 pr_err("%s: audio_dev_ctrl_find_dev failed. %ld\n",
943 __func__, PTR_ERR(dev_info));
944 return rc;
945 }
946 if (!(dev_info->capability & SNDDEV_CAP_TX)) {
947 rc = -EINVAL;
948 return rc;
949 }
950 if (mute)
951 gain = 0;
952
953 pr_debug("%s:dev_name = %s dev_id = %d, gain = %hX\n",
954 __func__, dev_info->name, dev_id, gain);
955 rc = afe_apply_gain(dev_info->copp_id, gain);
956 if (rc < 0) {
957 pr_err("%s : device %s not able to set device gain "
958 "control.", __func__, dev_info->name);
959 return rc;
960 }
961 pr_debug("Muting/Unmuting device id %d(%s)\n", dev_id, dev_info->name);
962
963 return rc;
964}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700965static struct snd_kcontrol_new snd_dev_controls[AUDIO_DEV_CTL_MAX_DEV];
966
967static int snd_dev_ctl_index(int idx)
968{
969 struct msm_snddev_info *dev_info;
970
971 dev_info = audio_dev_ctrl_find_dev(idx);
972 if (IS_ERR(dev_info)) {
973 pr_err("%s:pass invalid dev_id\n", __func__);
974 return PTR_ERR(dev_info);
975 }
976 if (sizeof(dev_info->name) <= 44)
977 sprintf(&snddev_name[idx][0] , "%s", dev_info->name);
978
979 snd_dev_controls[idx].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
980 snd_dev_controls[idx].access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
981 snd_dev_controls[idx].name = &snddev_name[idx][0];
982 snd_dev_controls[idx].index = idx;
983 snd_dev_controls[idx].info = msm_device_info;
984 snd_dev_controls[idx].get = msm_device_get;
985 snd_dev_controls[idx].put = msm_device_put;
986 snd_dev_controls[idx].private_value = 0;
987 return 0;
988
989}
990
991#define MSM_EXT(xname, fp_info, fp_get, fp_put, addr) \
992{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
993 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
994 .name = xname, \
995 .info = fp_info,\
996 .get = fp_get, .put = fp_put, \
997 .private_value = addr, \
998}
999
1000/* If new controls are to be added which would be constant across the
1001 * different targets, please add to the structure
1002 * snd_msm_controls. Please do not add any controls to the structure
1003 * snd_msm_secondary_controls defined below unless they are msm8x60
1004 * specific.
1005 */
1006
1007static struct snd_kcontrol_new snd_msm_controls[] = {
1008 MSM_EXT("Count", msm_scontrol_count_info, msm_scontrol_count_get, \
1009 NULL, 0),
1010 MSM_EXT("Stream", msm_route_info, msm_route_get, \
1011 msm_route_put, 0),
1012 MSM_EXT("Record", msm_route_info, msm_route_get, \
1013 msm_route_put, 0),
1014 MSM_EXT("Voice", msm_voice_info, msm_voice_get, \
1015 msm_voice_put, 0),
1016 MSM_EXT("Volume", msm_volume_info, msm_volume_get, \
1017 msm_volume_put, 0),
1018 MSM_EXT("VoiceVolume", msm_v_volume_info, msm_v_volume_get, \
1019 msm_v_volume_put, 0),
1020 MSM_EXT("VoiceMute", msm_v_mute_info, msm_v_mute_get, \
1021 msm_v_mute_put, 0),
1022 MSM_EXT("Voice Call", msm_v_call_info, msm_v_call_get, \
1023 msm_v_call_put, 0),
1024 MSM_EXT("Device_Volume", msm_device_volume_info,
1025 msm_device_volume_get, msm_device_volume_put, 0),
1026 MSM_EXT("Reset", msm_reset_info,
1027 msm_reset_get, msm_reset_put, 0),
1028 MSM_EXT("ANC", msm_anc_info, msm_anc_get, msm_anc_put, 0),
Laxminath Kasam885f5102011-07-14 10:20:21 +05301029 MSM_EXT("Device_Mute", msm_device_mute_info,
1030 msm_device_mute_get, msm_device_mute_put, 0),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001031};
1032
1033static struct snd_kcontrol_new snd_msm_secondary_controls[] = {
1034 MSM_EXT("PCM Playback Sink",
1035 pcm_route_info, pcm_route_get_rx, pcm_route_put_rx, 0),
1036 MSM_EXT("PCM Capture Source",
1037 pcm_route_info, pcm_route_get_tx, pcm_route_put_tx, 0),
1038 MSM_EXT("Sound Device Loopback", msm_loopback_info,
1039 msm_loopback_get, msm_loopback_put, 0),
1040};
1041
1042static int msm_new_mixer(struct snd_soc_codec *codec)
1043{
1044 unsigned int idx;
1045 int err;
1046 int dev_cnt;
1047
1048 strcpy(codec->card->snd_card->mixername, "MSM Mixer");
1049 for (idx = 0; idx < ARRAY_SIZE(snd_msm_controls); idx++) {
1050 err = snd_ctl_add(codec->card->snd_card,
1051 snd_ctl_new1(&snd_msm_controls[idx],
1052 NULL));
1053 if (err < 0)
1054 pr_err("%s:ERR adding ctl\n", __func__);
1055 }
1056
1057 for (idx = 0; idx < ARRAY_SIZE(snd_msm_secondary_controls); idx++) {
1058 err = snd_ctl_add(codec->card->snd_card,
1059 snd_ctl_new1(&snd_msm_secondary_controls[idx],
1060 NULL));
1061 if (err < 0)
1062 pr_err("%s:ERR adding secondary ctl\n", __func__);
1063 }
1064 dev_cnt = msm_snddev_devcount();
1065
1066 for (idx = 0; idx < dev_cnt; idx++) {
1067 if (!snd_dev_ctl_index(idx)) {
1068 err = snd_ctl_add(codec->card->snd_card,
1069 snd_ctl_new1(&snd_dev_controls[idx],
1070 NULL));
1071 if (err < 0)
1072 pr_err("%s:ERR adding ctl\n", __func__);
1073 } else
1074 return 0;
1075 }
1076 simple_control = ARRAY_SIZE(snd_msm_controls)
1077 + ARRAY_SIZE(snd_msm_secondary_controls);
1078 device_index = simple_control + 1;
1079 return 0;
1080}
1081
1082static int msm_soc_dai_init(
1083 struct snd_soc_pcm_runtime *rtd)
1084{
1085
1086 int ret = 0;
1087 struct snd_soc_codec *codec = rtd->codec;
1088
1089 init_waitqueue_head(&the_locks.enable_wait);
1090 init_waitqueue_head(&the_locks.eos_wait);
1091 init_waitqueue_head(&the_locks.write_wait);
1092 init_waitqueue_head(&the_locks.read_wait);
1093 memset(&session_route, DEVICE_IGNORE, sizeof(struct pcm_session));
1094
1095 ret = msm_new_mixer(codec);
1096 if (ret < 0)
1097 pr_err("%s: ALSA MSM Mixer Fail\n", __func__);
1098
1099 return ret;
1100}
1101
1102static struct snd_soc_dai_link msm_dai[] = {
1103{
1104 .name = "MSM Primary I2S",
1105 .stream_name = "DSP 1",
1106 .cpu_dai_name = "msm-cpu-dai.0",
1107 .platform_name = "msm-dsp-audio.0",
1108 .codec_name = "msm-codec-dai.0",
1109 .codec_dai_name = "msm-codec-dai",
1110 .init = &msm_soc_dai_init,
1111},
1112#ifdef CONFIG_MSM_8x60_VOIP
1113{
1114 .name = "MSM Primary Voip",
1115 .stream_name = "MVS",
1116 .cpu_dai_name = "mvs-cpu-dai.0",
1117 .platform_name = "msm-mvs-audio.0",
1118 .codec_name = "mvs-codec-dai.0",
1119 .codec_dai_name = "mvs-codec-dai",
1120},
1121#endif
1122};
1123
1124static struct snd_soc_card snd_soc_card_msm = {
1125 .name = "msm-audio",
1126 .dai_link = msm_dai,
1127 .num_links = ARRAY_SIZE(msm_dai),
1128};
1129
1130static int __init msm_audio_init(void)
1131{
1132 int ret;
1133
1134 msm_audio_snd_device = platform_device_alloc("soc-audio", -1);
1135 if (!msm_audio_snd_device)
1136 return -ENOMEM;
1137
1138 platform_set_drvdata(msm_audio_snd_device, &snd_soc_card_msm);
1139 ret = platform_device_add(msm_audio_snd_device);
1140 if (ret) {
1141 platform_device_put(msm_audio_snd_device);
1142 return ret;
1143 }
1144
1145 src_dev = DEVICE_IGNORE;
1146 dst_dev = DEVICE_IGNORE;
1147
1148 return ret;
1149}
1150
1151static void __exit msm_audio_exit(void)
1152{
1153 platform_device_unregister(msm_audio_snd_device);
1154}
1155
1156module_init(msm_audio_init);
1157module_exit(msm_audio_exit);
1158
1159MODULE_DESCRIPTION("PCM module");
1160MODULE_LICENSE("GPL v2");