aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/omap/omap-mcbsp.c144
-rw-r--r--sound/soc/omap/omap-mcbsp.h4
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
42struct omap_mcbsp_data { 50struct 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] = {};
82static const unsigned long omap1_mcbsp_port[][2] = {}; 90static 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)
86static const int omap24xx_dma_reqs[][2] = { 94static 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] = {
124static const unsigned long omap2430_mcbsp_port[][2] = {}; 132static 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)
128static const unsigned long omap34xx_mcbsp_port[][2] = { 136static 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
640EXPORT_SYMBOL_GPL(omap_mcbsp_dai); 648EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
641 649
650int 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) \
666static int \
667omap_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) \
684static int \
685omap_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
697OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0)
698OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1)
699OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0)
700OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1)
701OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0)
702OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1)
703OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0)
704OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1)
705
706static 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
724static 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
734static 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
747static 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
760int 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}
778EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
779
642static int __init snd_omap_mcbsp_init(void) 780static 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
58extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; 58extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS];
59 59
60int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id);
61
60#endif 62#endif