[PATCH 2/2] ASoC: OMAP-McBSP: ASoC interface for McBSP sidetone

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add ASoC interface for OMAP McBSP2 and McBSP3 sidetones.

Signed-off-by: Ilkka Koskinen <ilkka.koskinen@xxxxxxxxx>
---
 sound/soc/omap/omap-mcbsp.c |  187 +++++++++++++++++++++++++++++++++++++++++++
 sound/soc/omap/omap-mcbsp.h |    2 +
 2 files changed, 189 insertions(+), 0 deletions(-)

diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 6bbbd2a..295620b 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -39,6 +39,14 @@
 
 #define OMAP_MCBSP_RATES	(SNDRV_PCM_RATE_8000_96000)
 
+#define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \
+	xhandler_get, xhandler_put) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = omap_mcbsp_st_info_volsw, \
+	.get = xhandler_get, .put = xhandler_put, \
+	.private_value = (unsigned long) &(struct soc_mixer_control) \
+	{.min = xmin, .max = xmax} }
+
 struct omap_mcbsp_data {
 	unsigned int			bus_id;
 	struct omap_mcbsp_reg_cfg	regs;
@@ -637,6 +645,185 @@ struct snd_soc_dai omap_mcbsp_dai[] = {
 
 EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
 
+int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_info *uinfo)
+{
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	int max = mc->max;
+	int min = mc->min;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = min;
+	uinfo->value.integer.max = max;
+	return 0;
+}
+
+static int omap_mcbsp_set_st_channel_vol(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol,
+					int id, int channel)
+{
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	int max = mc->max;
+	int min = mc->min;
+	int val = ucontrol->value.integer.value[0];
+
+	if (val < min || val > max)
+		return -EINVAL;
+
+	return omap_st_set_chgain((id)-1, val, 0, channel);
+}
+
+static int omap_mcbsp_get_st_channel_vol(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol,
+					int id, int channel)
+{
+	s16 ch0gain, ch1gain;
+
+	if (omap_st_get_chgain((id)-1, &ch0gain, &ch1gain))
+		return -EAGAIN;
+
+	if (channel == OMAP_MCBSP_ST_CHANNEL_0)
+		ucontrol->value.integer.value[0] = ch0gain;
+	else if (channel == OMAP_MCBSP_ST_CHANNEL_1)
+		ucontrol->value.integer.value[0] = ch1gain;
+
+	return 0;
+}
+
+#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel)			\
+static int								\
+omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc,	\
+					struct snd_ctl_elem_value *uc)	\
+{									\
+	return omap_mcbsp_set_st_channel_vol(kc, uc, id, 		\
+				OMAP_MCBSP_ST_CHANNEL_##channel);	\
+}
+
+#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel)			\
+static int								\
+omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc,	\
+					struct snd_ctl_elem_value *uc)	\
+{									\
+	return omap_mcbsp_get_st_channel_vol(kc, uc, id,		\
+				OMAP_MCBSP_ST_CHANNEL_##channel);	\
+}
+
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0)
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1)
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0)
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1)
+
+static int omap_mcbsp2_st_set_mode(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	u8 value = ucontrol->value.integer.value[0];
+
+	if (value == omap_st_is_enabled(1))
+		return 0;
+
+	if (value)
+		omap_st_enable(1);
+	else
+		omap_st_disable(1);
+
+	return 1;
+}
+
+static int omap_mcbsp2_st_get_mode(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = omap_st_is_enabled(1);
+	return 0;
+}
+
+static int omap_mcbsp3_st_set_mode(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	u8 value = ucontrol->value.integer.value[0];
+
+	if (value == omap_st_is_enabled(2))
+		return 0;
+
+	if (value)
+		omap_st_enable(2);
+	else
+		omap_st_disable(2);
+
+	return 1;
+}
+
+static int omap_mcbsp3_st_get_mode(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+
+	ucontrol->value.integer.value[0] = omap_st_is_enabled(2);
+	return 0;
+}
+
+/* McBSP Sidetone Switch */
+static const char *omap_mcbsp_st_status[] = {
+	"off",
+	"on",
+};
+
+static const struct soc_enum omap_mcbsp_st_status_enum[] = {
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(omap_mcbsp_st_status),
+			    omap_mcbsp_st_status),
+};
+
+static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = {
+	SOC_ENUM_EXT("McBSP2 Sidetone Switch", omap_mcbsp_st_status_enum[0],
+			omap_mcbsp2_st_get_mode, omap_mcbsp2_st_set_mode),
+	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume",
+				      -32768, 32767,
+				      omap_mcbsp2_get_st_ch0_volume,
+				      omap_mcbsp2_set_st_ch0_volume),
+	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume",
+				      -32768, 32767,
+				      omap_mcbsp2_get_st_ch1_volume,
+				      omap_mcbsp2_set_st_ch1_volume),
+};
+
+static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
+	SOC_ENUM_EXT("McBSP3 Sidetone Switch", omap_mcbsp_st_status_enum[0],
+			omap_mcbsp3_st_get_mode, omap_mcbsp3_st_set_mode),
+	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume",
+				      -32768, 32767,
+				      omap_mcbsp3_get_st_ch0_volume,
+				      omap_mcbsp3_set_st_ch0_volume),
+	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume",
+				      -32768, 32767,
+				      omap_mcbsp3_get_st_ch1_volume,
+				      omap_mcbsp3_set_st_ch1_volume),
+};
+
+int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
+{
+	if (!cpu_is_omap34xx())
+		return -ENODEV;
+
+	switch (mcbsp_id) {
+	case 2: /* McBSP 2 */
+		return snd_soc_add_controls(codec, omap_mcbsp2_st_controls,
+					ARRAY_SIZE(omap_mcbsp2_st_controls));
+	case 3: /* McBSP 3 */
+		return snd_soc_add_controls(codec, omap_mcbsp3_st_controls,
+					ARRAY_SIZE(omap_mcbsp3_st_controls));
+	default:
+		break;
+	}
+
+	return -1;
+}
+EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
+
 static int __init snd_omap_mcbsp_init(void)
 {
 	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 647d2f9..7537435 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -57,4 +57,6 @@ enum omap_mcbsp_div {
 
 extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS];
 
+int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id);
+
 #endif
-- 
1.6.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux