diff options
author | Ilkka Koskinen <ilkka.koskinen@nokia.com> | 2010-02-22 07:21:12 -0500 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2010-02-23 13:57:39 -0500 |
commit | 83905c134571642d7e8a1e51ae9f26bd3a3ad82a (patch) | |
tree | 84ed85e924132d6b953cb5359e7c305a4c90dde2 /sound/soc/omap/omap-mcbsp.c | |
parent | d912fa9255845ffd8029482d408b6139344891c8 (diff) |
ASoC: OMAP-McBSP: ASoC interface for McBSP sidetone
Add ASoC interface for OMAP McBSP2 and McBSP3 sidetones.
Signed-off-by: Ilkka Koskinen <ilkka.koskinen@nokia.com>
Acked-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Tested-by: Jarkko Nikula <jhnikula@gmail.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'sound/soc/omap/omap-mcbsp.c')
-rw-r--r-- | sound/soc/omap/omap-mcbsp.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index c0039b35fb25..8da14f537f49 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -39,6 +39,14 @@ | |||
39 | 39 | ||
40 | #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) | 40 | #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) |
41 | 41 | ||
42 | #define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \ | ||
43 | xhandler_get, xhandler_put) \ | ||
44 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
45 | .info = omap_mcbsp_st_info_volsw, \ | ||
46 | .get = xhandler_get, .put = xhandler_put, \ | ||
47 | .private_value = (unsigned long) &(struct soc_mixer_control) \ | ||
48 | {.min = xmin, .max = xmax} } | ||
49 | |||
42 | struct omap_mcbsp_data { | 50 | struct omap_mcbsp_data { |
43 | unsigned int bus_id; | 51 | unsigned int bus_id; |
44 | struct omap_mcbsp_reg_cfg regs; | 52 | struct omap_mcbsp_reg_cfg regs; |
@@ -637,6 +645,136 @@ struct snd_soc_dai omap_mcbsp_dai[] = { | |||
637 | 645 | ||
638 | EXPORT_SYMBOL_GPL(omap_mcbsp_dai); | 646 | EXPORT_SYMBOL_GPL(omap_mcbsp_dai); |
639 | 647 | ||
648 | int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, | ||
649 | struct snd_ctl_elem_info *uinfo) | ||
650 | { | ||
651 | struct soc_mixer_control *mc = | ||
652 | (struct soc_mixer_control *)kcontrol->private_value; | ||
653 | int max = mc->max; | ||
654 | int min = mc->min; | ||
655 | |||
656 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
657 | uinfo->count = 1; | ||
658 | uinfo->value.integer.min = min; | ||
659 | uinfo->value.integer.max = max; | ||
660 | return 0; | ||
661 | } | ||
662 | |||
663 | #define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel) \ | ||
664 | static int \ | ||
665 | omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | ||
666 | struct snd_ctl_elem_value *uc) \ | ||
667 | { \ | ||
668 | struct soc_mixer_control *mc = \ | ||
669 | (struct soc_mixer_control *)kc->private_value; \ | ||
670 | int max = mc->max; \ | ||
671 | int min = mc->min; \ | ||
672 | int val = uc->value.integer.value[0]; \ | ||
673 | \ | ||
674 | if (val < min || val > max) \ | ||
675 | return -EINVAL; \ | ||
676 | \ | ||
677 | /* OMAP McBSP implementation uses index values 0..4 */ \ | ||
678 | return omap_st_set_chgain((id)-1, channel, val); \ | ||
679 | } | ||
680 | |||
681 | #define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel) \ | ||
682 | static int \ | ||
683 | omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | ||
684 | struct snd_ctl_elem_value *uc) \ | ||
685 | { \ | ||
686 | s16 chgain; \ | ||
687 | \ | ||
688 | if (omap_st_get_chgain((id)-1, channel, &chgain)) \ | ||
689 | return -EAGAIN; \ | ||
690 | \ | ||
691 | uc->value.integer.value[0] = chgain; \ | ||
692 | return 0; \ | ||
693 | } | ||
694 | |||
695 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0) | ||
696 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1) | ||
697 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0) | ||
698 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1) | ||
699 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0) | ||
700 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1) | ||
701 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0) | ||
702 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1) | ||
703 | |||
704 | static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, | ||
705 | struct snd_ctl_elem_value *ucontrol) | ||
706 | { | ||
707 | struct soc_mixer_control *mc = | ||
708 | (struct soc_mixer_control *)kcontrol->private_value; | ||
709 | u8 value = ucontrol->value.integer.value[0]; | ||
710 | |||
711 | if (value == omap_st_is_enabled(mc->reg)) | ||
712 | return 0; | ||
713 | |||
714 | if (value) | ||
715 | omap_st_enable(mc->reg); | ||
716 | else | ||
717 | omap_st_disable(mc->reg); | ||
718 | |||
719 | return 1; | ||
720 | } | ||
721 | |||
722 | static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol, | ||
723 | struct snd_ctl_elem_value *ucontrol) | ||
724 | { | ||
725 | struct soc_mixer_control *mc = | ||
726 | (struct soc_mixer_control *)kcontrol->private_value; | ||
727 | |||
728 | ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg); | ||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { | ||
733 | SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0, | ||
734 | omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), | ||
735 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume", | ||
736 | -32768, 32767, | ||
737 | omap_mcbsp2_get_st_ch0_volume, | ||
738 | omap_mcbsp2_set_st_ch0_volume), | ||
739 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume", | ||
740 | -32768, 32767, | ||
741 | omap_mcbsp2_get_st_ch1_volume, | ||
742 | omap_mcbsp2_set_st_ch1_volume), | ||
743 | }; | ||
744 | |||
745 | static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { | ||
746 | SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0, | ||
747 | omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), | ||
748 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume", | ||
749 | -32768, 32767, | ||
750 | omap_mcbsp3_get_st_ch0_volume, | ||
751 | omap_mcbsp3_set_st_ch0_volume), | ||
752 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume", | ||
753 | -32768, 32767, | ||
754 | omap_mcbsp3_get_st_ch1_volume, | ||
755 | omap_mcbsp3_set_st_ch1_volume), | ||
756 | }; | ||
757 | |||
758 | int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id) | ||
759 | { | ||
760 | if (!cpu_is_omap34xx()) | ||
761 | return -ENODEV; | ||
762 | |||
763 | switch (mcbsp_id) { | ||
764 | case 1: /* McBSP 2 */ | ||
765 | return snd_soc_add_controls(codec, omap_mcbsp2_st_controls, | ||
766 | ARRAY_SIZE(omap_mcbsp2_st_controls)); | ||
767 | case 2: /* McBSP 3 */ | ||
768 | return snd_soc_add_controls(codec, omap_mcbsp3_st_controls, | ||
769 | ARRAY_SIZE(omap_mcbsp3_st_controls)); | ||
770 | default: | ||
771 | break; | ||
772 | } | ||
773 | |||
774 | return -EINVAL; | ||
775 | } | ||
776 | EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); | ||
777 | |||
640 | static int __init snd_omap_mcbsp_init(void) | 778 | static int __init snd_omap_mcbsp_init(void) |
641 | { | 779 | { |
642 | return snd_soc_register_dais(omap_mcbsp_dai, | 780 | return snd_soc_register_dais(omap_mcbsp_dai, |