Re: [PATCH] ASoC: fsl_micfil: Add Hardware Voice Activity Detector support

2022-10-18 Thread Mark Brown
On Fri, 23 Sep 2022 17:31:34 +0800, Shengjiu Wang wrote:
> The Hardware Voice Activity Detector (HWVAD) is a block
> responsible for detect voice activity in a channel selected
> by the user. It can be configured in Envelope-based or
> Energy-based mode.
> 
> There are additional two interrupts for HWVAD, one is event
> interrupt, another is error interrupt.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/1] ASoC: fsl_micfil: Add Hardware Voice Activity Detector support
  commit: 29dbfeecab85fc998d8c5c29473da33d272d0c85

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark


[PATCH] ASoC: fsl_micfil: Add Hardware Voice Activity Detector support

2022-09-23 Thread Shengjiu Wang
The Hardware Voice Activity Detector (HWVAD) is a block
responsible for detect voice activity in a channel selected
by the user. It can be configured in Envelope-based or
Energy-based mode.

There are additional two interrupts for HWVAD, one is event
interrupt, another is error interrupt.

Enable hwvad in parallel with recording.
when voice activity detected, HWVAD will be disabled and
alsa control notification is triggerred.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_micfil.c | 434 +
 sound/soc/fsl/fsl_micfil.h |   6 +-
 2 files changed, 439 insertions(+), 1 deletion(-)

diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c
index 79ef4e269bc9..eeaa75fb9196 100644
--- a/sound/soc/fsl/fsl_micfil.c
+++ b/sound/soc/fsl/fsl_micfil.c
@@ -47,11 +47,15 @@ struct fsl_micfil {
struct clk *pll11k_clk;
struct snd_dmaengine_dai_dma_data dma_params_rx;
struct sdma_peripheral_config sdmacfg;
+   struct snd_soc_card *card;
unsigned int dataline;
char name[32];
int irq[MICFIL_IRQ_LINES];
enum quality quality;
int dc_remover;
+   int vad_init_mode;
+   int vad_enabled;
+   int vad_detected;
 };
 
 struct fsl_micfil_soc_data {
@@ -152,6 +156,152 @@ static int micfil_quality_set(struct snd_kcontrol 
*kcontrol,
return micfil_set_quality(micfil);
 }
 
+static const char * const micfil_hwvad_enable[] = {
+   "Disable (Record only)",
+   "Enable (Record with Vad)",
+};
+
+static const char * const micfil_hwvad_init_mode[] = {
+   "Envelope mode", "Energy mode",
+};
+
+static const char * const micfil_hwvad_hpf_texts[] = {
+   "Filter bypass",
+   "Cut-off @1750Hz",
+   "Cut-off @215Hz",
+   "Cut-off @102Hz",
+};
+
+/*
+ * DC Remover Control
+ * Filter Bypassed 1 1
+ * Cut-off @21Hz   0 0
+ * Cut-off @83Hz   0 1
+ * Cut-off @152HZ  1 0
+ */
+static const char * const micfil_dc_remover_texts[] = {
+   "Cut-off @21Hz", "Cut-off @83Hz",
+   "Cut-off @152Hz", "Bypass",
+};
+
+static const struct soc_enum hwvad_enable_enum =
+   SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_hwvad_enable),
+   micfil_hwvad_enable);
+static const struct soc_enum hwvad_init_mode_enum =
+   SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_hwvad_init_mode),
+   micfil_hwvad_init_mode);
+static const struct soc_enum hwvad_hpf_enum =
+   SOC_ENUM_SINGLE(REG_MICFIL_VAD0_CTRL2, 0,
+   ARRAY_SIZE(micfil_hwvad_hpf_texts),
+   micfil_hwvad_hpf_texts);
+static const struct soc_enum fsl_micfil_dc_remover_enum =
+   SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_dc_remover_texts),
+   micfil_dc_remover_texts);
+
+static int micfil_put_dc_remover_state(struct snd_kcontrol *kcontrol,
+  struct snd_ctl_elem_value *ucontrol)
+{
+   struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+   struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+   struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
+   unsigned int *item = ucontrol->value.enumerated.item;
+   int val = snd_soc_enum_item_to_val(e, item[0]);
+   int i = 0, ret = 0;
+   u32 reg_val = 0;
+
+   if (val < 0 || val > 3)
+   return -EINVAL;
+
+   micfil->dc_remover = val;
+
+   /* Calculate total value for all channels */
+   for (i = 0; i < MICFIL_OUTPUT_CHANNELS; i++)
+   reg_val |= val << MICFIL_DC_CHX_SHIFT(i);
+
+   /* Update DC Remover mode for all channels */
+   ret = snd_soc_component_update_bits(comp, REG_MICFIL_DC_CTRL,
+   MICFIL_DC_CTRL_CONFIG, reg_val);
+   if (ret < 0)
+   return ret;
+
+   return 0;
+}
+
+static int micfil_get_dc_remover_state(struct snd_kcontrol *kcontrol,
+  struct snd_ctl_elem_value *ucontrol)
+{
+   struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+   struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
+
+   ucontrol->value.enumerated.item[0] = micfil->dc_remover;
+
+   return 0;
+}
+
+static int hwvad_put_enable(struct snd_kcontrol *kcontrol,
+   struct snd_ctl_elem_value *ucontrol)
+{
+   struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+   struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+   unsigned int *item = ucontrol->value.enumerated.item;
+   struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
+   int val = snd_soc_enum_item_to_val(e, item[0]);
+
+   micfil->vad_enabled = val;
+
+   return 0;
+}
+
+static int hwvad_get_enable(struct snd_kcontrol *kcontrol,
+   struct snd_ctl_elem_value *ucontrol)
+{
+   struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+   str