diff options
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/omap/omap-mcbsp.c | 144 | ||||
-rw-r--r-- | sound/soc/omap/omap-mcbsp.h | 4 |
2 files changed, 144 insertions, 4 deletions
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index d29725664185..e814a9591f78 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; |
@@ -82,11 +90,11 @@ static const int omap1_dma_reqs[][2] = {}; | |||
82 | static const unsigned long omap1_mcbsp_port[][2] = {}; | 90 | static const unsigned long omap1_mcbsp_port[][2] = {}; |
83 | #endif | 91 | #endif |
84 | 92 | ||
85 | #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) | 93 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) |
86 | static const int omap24xx_dma_reqs[][2] = { | 94 | static const int omap24xx_dma_reqs[][2] = { |
87 | { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX }, | 95 | { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX }, |
88 | { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX }, | 96 | { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX }, |
89 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) | 97 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) |
90 | { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX }, | 98 | { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX }, |
91 | { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX }, | 99 | { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX }, |
92 | { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX }, | 100 | { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX }, |
@@ -124,7 +132,7 @@ static const unsigned long omap2430_mcbsp_port[][2] = { | |||
124 | static const unsigned long omap2430_mcbsp_port[][2] = {}; | 132 | static const unsigned long omap2430_mcbsp_port[][2] = {}; |
125 | #endif | 133 | #endif |
126 | 134 | ||
127 | #if defined(CONFIG_ARCH_OMAP34XX) | 135 | #if defined(CONFIG_ARCH_OMAP3) |
128 | static const unsigned long omap34xx_mcbsp_port[][2] = { | 136 | static const unsigned long omap34xx_mcbsp_port[][2] = { |
129 | { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR, | 137 | { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR, |
130 | OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR }, | 138 | OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR }, |
@@ -639,6 +647,136 @@ struct snd_soc_dai omap_mcbsp_dai[] = { | |||
639 | 647 | ||
640 | EXPORT_SYMBOL_GPL(omap_mcbsp_dai); | 648 | EXPORT_SYMBOL_GPL(omap_mcbsp_dai); |
641 | 649 | ||
650 | int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, | ||
651 | struct snd_ctl_elem_info *uinfo) | ||
652 | { | ||
653 | struct soc_mixer_control *mc = | ||
654 | (struct soc_mixer_control *)kcontrol->private_value; | ||
655 | int max = mc->max; | ||
656 | int min = mc->min; | ||
657 | |||
658 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
659 | uinfo->count = 1; | ||
660 | uinfo->value.integer.min = min; | ||
661 | uinfo->value.integer.max = max; | ||
662 | return 0; | ||
663 | } | ||
664 | |||
665 | #define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel) \ | ||
666 | static int \ | ||
667 | omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | ||
668 | struct snd_ctl_elem_value *uc) \ | ||
669 | { \ | ||
670 | struct soc_mixer_control *mc = \ | ||
671 | (struct soc_mixer_control *)kc->private_value; \ | ||
672 | int max = mc->max; \ | ||
673 | int min = mc->min; \ | ||
674 | int val = uc->value.integer.value[0]; \ | ||
675 | \ | ||
676 | if (val < min || val > max) \ | ||
677 | return -EINVAL; \ | ||
678 | \ | ||
679 | /* OMAP McBSP implementation uses index values 0..4 */ \ | ||
680 | return omap_st_set_chgain((id)-1, channel, val); \ | ||
681 | } | ||
682 | |||
683 | #define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel) \ | ||
684 | static int \ | ||
685 | omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | ||
686 | struct snd_ctl_elem_value *uc) \ | ||
687 | { \ | ||
688 | s16 chgain; \ | ||
689 | \ | ||
690 | if (omap_st_get_chgain((id)-1, channel, &chgain)) \ | ||
691 | return -EAGAIN; \ | ||
692 | \ | ||
693 | uc->value.integer.value[0] = chgain; \ | ||
694 | return 0; \ | ||
695 | } | ||
696 | |||
697 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0) | ||
698 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1) | ||
699 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0) | ||
700 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1) | ||
701 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0) | ||
702 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1) | ||
703 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0) | ||
704 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1) | ||
705 | |||
706 | static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, | ||
707 | struct snd_ctl_elem_value *ucontrol) | ||
708 | { | ||
709 | struct soc_mixer_control *mc = | ||
710 | (struct soc_mixer_control *)kcontrol->private_value; | ||
711 | u8 value = ucontrol->value.integer.value[0]; | ||
712 | |||
713 | if (value == omap_st_is_enabled(mc->reg)) | ||
714 | return 0; | ||
715 | |||
716 | if (value) | ||
717 | omap_st_enable(mc->reg); | ||
718 | else | ||
719 | omap_st_disable(mc->reg); | ||
720 | |||
721 | return 1; | ||
722 | } | ||
723 | |||
724 | static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol, | ||
725 | struct snd_ctl_elem_value *ucontrol) | ||
726 | { | ||
727 | struct soc_mixer_control *mc = | ||
728 | (struct soc_mixer_control *)kcontrol->private_value; | ||
729 | |||
730 | ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg); | ||
731 | return 0; | ||
732 | } | ||
733 | |||
734 | static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { | ||
735 | SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0, | ||
736 | omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), | ||
737 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume", | ||
738 | -32768, 32767, | ||
739 | omap_mcbsp2_get_st_ch0_volume, | ||
740 | omap_mcbsp2_set_st_ch0_volume), | ||
741 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume", | ||
742 | -32768, 32767, | ||
743 | omap_mcbsp2_get_st_ch1_volume, | ||
744 | omap_mcbsp2_set_st_ch1_volume), | ||
745 | }; | ||
746 | |||
747 | static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { | ||
748 | SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0, | ||
749 | omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), | ||
750 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume", | ||
751 | -32768, 32767, | ||
752 | omap_mcbsp3_get_st_ch0_volume, | ||
753 | omap_mcbsp3_set_st_ch0_volume), | ||
754 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume", | ||
755 | -32768, 32767, | ||
756 | omap_mcbsp3_get_st_ch1_volume, | ||
757 | omap_mcbsp3_set_st_ch1_volume), | ||
758 | }; | ||
759 | |||
760 | int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id) | ||
761 | { | ||
762 | if (!cpu_is_omap34xx()) | ||
763 | return -ENODEV; | ||
764 | |||
765 | switch (mcbsp_id) { | ||
766 | case 1: /* McBSP 2 */ | ||
767 | return snd_soc_add_controls(codec, omap_mcbsp2_st_controls, | ||
768 | ARRAY_SIZE(omap_mcbsp2_st_controls)); | ||
769 | case 2: /* McBSP 3 */ | ||
770 | return snd_soc_add_controls(codec, omap_mcbsp3_st_controls, | ||
771 | ARRAY_SIZE(omap_mcbsp3_st_controls)); | ||
772 | default: | ||
773 | break; | ||
774 | } | ||
775 | |||
776 | return -EINVAL; | ||
777 | } | ||
778 | EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); | ||
779 | |||
642 | static int __init snd_omap_mcbsp_init(void) | 780 | static int __init snd_omap_mcbsp_init(void) |
643 | { | 781 | { |
644 | return snd_soc_register_dais(omap_mcbsp_dai, | 782 | return snd_soc_register_dais(omap_mcbsp_dai, |
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index 647d2f981ab0..6c363e5f4387 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h | |||
@@ -50,11 +50,13 @@ enum omap_mcbsp_div { | |||
50 | #undef NUM_LINKS | 50 | #undef NUM_LINKS |
51 | #define NUM_LINKS 3 | 51 | #define NUM_LINKS 3 |
52 | #endif | 52 | #endif |
53 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) | 53 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) |
54 | #undef NUM_LINKS | 54 | #undef NUM_LINKS |
55 | #define NUM_LINKS 5 | 55 | #define NUM_LINKS 5 |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; | 58 | extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; |
59 | 59 | ||
60 | int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id); | ||
61 | |||
60 | #endif | 62 | #endif |