diff mbox series

ASoC: tlv320aic3x: add dmic widget support

Message ID 20220311100627.2181756-1-gregory.clement@bootlin.com (mailing list archive)
State New, archived
Headers show
Series ASoC: tlv320aic3x: add dmic widget support | expand

Commit Message

Gregory CLEMENT March 11, 2022, 10:06 a.m. UTC
This patch allows to use dmic to record sound.

This is a port from a variscite patch written by Eran Matityahu
<eran.m@variscite.com>.

Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
---
 sound/soc/codecs/tlv320aic3x.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

Comments

Mark Brown March 11, 2022, 12:34 p.m. UTC | #1
On Fri, Mar 11, 2022 at 11:06:27AM +0100, Gregory CLEMENT wrote:

> +static const char * const aic3x_dmic_rates[] = { "off", "128x", "64x", "32x" };
> +static SOC_ENUM_SINGLE_DECL(aic3x_dmic_rates_enum, AIC3X_ASD_INTF_CTRLA, 0,
> +			    aic3x_dmic_rates);
> +static const struct snd_kcontrol_new aic3x_dmic_rates_controls =
> +	SOC_DAPM_ENUM("Route", aic3x_dmic_rates_enum);

...

> +	{"GPIO1 dmic modclk", NULL, "DMic Rate"},
> +	{"DMic Rate", "128x", "DMIC"},
> +	{"DMic Rate", "64x", "DMIC"},
> +	{"DMic Rate", "32x", "DMIC"},
> +	{"DMic Rate", "off", "DMIC"},

This isn't really idiomatic and won't be power efficient since we don't
automatically manage the power so we'll have the DMIC clock running even
when no recording is in progress.  What would be better would be to have
an enum equivalent of the _AUTODISABLE() controls, providing an enum
with the clock rates backed by a field in the driver data and then a
DAPM widget which writes the value to the hardware when the widget is
enabled and sets it back to off on disable.  It'd be fine to open code
that in the driver for now rather than actually implementing a generic
thing if that's too much hassle.
Gregory CLEMENT March 15, 2022, 9:51 a.m. UTC | #2
Hello Mark,

> On Fri, Mar 11, 2022 at 11:06:27AM +0100, Gregory CLEMENT wrote:
>
>> +static const char * const aic3x_dmic_rates[] = { "off", "128x", "64x", "32x" };
>> +static SOC_ENUM_SINGLE_DECL(aic3x_dmic_rates_enum, AIC3X_ASD_INTF_CTRLA, 0,
>> +			    aic3x_dmic_rates);
>> +static const struct snd_kcontrol_new aic3x_dmic_rates_controls =
>> +	SOC_DAPM_ENUM("Route", aic3x_dmic_rates_enum);
>
> ...
>
>> +	{"GPIO1 dmic modclk", NULL, "DMic Rate"},
>> +	{"DMic Rate", "128x", "DMIC"},
>> +	{"DMic Rate", "64x", "DMIC"},
>> +	{"DMic Rate", "32x", "DMIC"},
>> +	{"DMic Rate", "off", "DMIC"},
>
> This isn't really idiomatic and won't be power efficient since we don't
> automatically manage the power so we'll have the DMIC clock running even
> when no recording is in progress.  What would be better would be to have
> an enum equivalent of the _AUTODISABLE() controls, providing an enum
> with the clock rates backed by a field in the driver data and then a
> DAPM widget which writes the value to the hardware when the widget is
> enabled and sets it back to off on disable.  It'd be fine to open code
> that in the driver for now rather than actually implementing a generic
> thing if that's too much hassle.

Thanks for tour feedback, I will work on a second version based on this.

Gregory
diff mbox series

Patch

diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index d53037b1509d..426f92cc44da 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -296,6 +296,11 @@  static SOC_ENUM_SINGLE_DECL(aic3x_poweron_time_enum, HPOUT_POP_REDUCTION, 4,
 static const char * const aic3x_rampup_step[] = { "0ms", "1ms", "2ms", "4ms" };
 static SOC_ENUM_SINGLE_DECL(aic3x_rampup_step_enum, HPOUT_POP_REDUCTION, 2,
 			    aic3x_rampup_step);
+static const char * const aic3x_dmic_rates[] = { "off", "128x", "64x", "32x" };
+static SOC_ENUM_SINGLE_DECL(aic3x_dmic_rates_enum, AIC3X_ASD_INTF_CTRLA, 0,
+			    aic3x_dmic_rates);
+static const struct snd_kcontrol_new aic3x_dmic_rates_controls =
+	SOC_DAPM_ENUM("Route", aic3x_dmic_rates_enum);
 
 /*
  * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps
@@ -751,6 +756,9 @@  static const struct snd_soc_dapm_widget aic3x_extra_dapm_widgets[] = {
 	SND_SOC_DAPM_INPUT("MIC3R"),
 	SND_SOC_DAPM_INPUT("LINE2L"),
 	SND_SOC_DAPM_INPUT("LINE2R"),
+
+	SND_SOC_DAPM_MUX("DMic Rate", SND_SOC_NOPM, 0, 0, &aic3x_dmic_rates_controls),
+	SND_SOC_DAPM_INPUT("DMIC"),
 };
 
 /* For tlv320aic3104 */
@@ -939,6 +947,12 @@  static const struct snd_soc_dapm_route intercon_extra[] = {
 	{"GPIO1 dmic modclk", NULL, "DMic Rate 64"},
 	{"GPIO1 dmic modclk", NULL, "DMic Rate 32"},
 
+	{"GPIO1 dmic modclk", NULL, "DMic Rate"},
+	{"DMic Rate", "128x", "DMIC"},
+	{"DMic Rate", "64x", "DMIC"},
+	{"DMic Rate", "32x", "DMIC"},
+	{"DMic Rate", "off", "DMIC"},
+
 	/* Left Line Output */
 	{"Left Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
 	{"Left Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},