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