[Sound-open-firmware] [PATCH 01/15] [RFC][v2]DMIC: Add PDM microphones (DMIC) support to DAI

Liam Girdwood liam.r.girdwood at linux.intel.com
Mon May 7 13:37:17 CEST 2018


On Fri, 2018-05-04 at 18:01 +0300, Seppo Ingalsuo wrote:
> This patch adds the DMIC audio capture driver for SOF DAI component use.
> The DMIC feature allows to directly attach one to (typically) four PDM
> digital microphones into Intel SoC without a separate codec IC. This is
> supported by APL and most successor platforms.
> 
> Corresponding patches are needed for kernel driver and topology to enable
> this feature.
> 
> Tested in
> APL UP squared board without connected microphones
> SOF git master 3ad69eb715a09de9a0b91c56c9cca8a79ead00a9
> 
> Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
> ---
>  src/drivers/dmic.c | 1383 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 1383 insertions(+)
>  create mode 100644 src/drivers/dmic.c
> 
> 

I've applied 2,5,7,8,9,10,11,14 and 15. The rest are good but needs  


> +
> +#if defined MODULE_TEST
> +#include <stdio.h>
> +#define QTOF(x, q) ((float)(x) / ((int64_t)1 << (q)))
> +#endif

Does this need to go in a maths header ?

+
+#if DMIC_HW_VERSION == 1
+       ipm_helper(&ipm, stereo, swap, dmic);
+       val = OUTCONTROL0_TIE(0) |
+               OUTCONTROL0_SIP(0) |
+               OUTCONTROL0_FINIT(1) |
+               OUTCONTROL0_FCI(0) |
+               OUTCONTROL0_BFTH(bfth) |
+               OUTCONTROL0_OF(of0) |
+               OUTCONTROL0_IPM(ipm) |
+               OUTCONTROL0_TH(th);
+       dmic_write(dai, OUTCONTROL0, val);
+       trace_value(val);
+
+       val = OUTCONTROL1_TIE(0) |
+               OUTCONTROL1_SIP(0) |
+               OUTCONTROL1_FINIT(1) |
+               OUTCONTROL1_FCI(0) |
+               OUTCONTROL1_BFTH(bfth) |
+               OUTCONTROL1_OF(of1) |
+               OUTCONTROL1_IPM(ipm) |
+               OUTCONTROL1_TH(th);
+       dmic_write(dai, OUTCONTROL1, val);
+       trace_value(val);
+#endif
+
+#if DMIC_HW_VERSION == 2
+       source_ipm_helper(source, &ipm, stereo, swap, dmic);


Best to use #elif



+/* start the DMIC for capture */
+static void dmic_start(struct dai *dai, int direction)
+{
+       struct dmic_pdata *dmic = dai_get_drvdata(dai);
+       int i;
+       int mic_a;
+       int mic_b;
+       int fir_a;
+       int fir_b;
+
+       if (direction != DAI_DIR_CAPTURE)
+               return;
+
+       /* enable port */
+       spin_lock(&dmic->lock);
+       trace_dmic("sta");
+       dmic->state = COMP_STATE_ACTIVE;


Regarding the spinlock, was this to be used to guarantee that both mic A and B
would use a compatible configuration at start ? 

> 
> +	if (direction != DAI_DIR_CAPTURE) {
> +		trace_dmic_error("cap");
> +		return -EINVAL;
> +	}


You need to do this here :-

	ret = comp_set_state(dev, cmd);
	if (ret < 0)
		return ret;

This does all state checking/setting so no need to do it below.

> +
> +	switch (cmd) {
> +	case COMP_TRIGGER_START:
> +		if (dmic->state == COMP_STATE_PREPARE ||
> +			dmic->state == COMP_STATE_PAUSED) {
> +			dmic_start(dai, direction);
> +		} else {
> +			trace_dmic_error("cst");
> +			trace_value(dmic->state);
> +		}
> +		break;
> +	case COMP_TRIGGER_RELEASE:
> +		if (dmic->state == COMP_STATE_PREPARE) {
> +			dmic_start(dai, direction);
> +		} else {
> +			trace_dmic_error("crl");
> +			trace_value(dmic->state);
> +		}
> +		break;
> +	case COMP_TRIGGER_STOP:
> +	case COMP_TRIGGER_PAUSE:
> +		dmic->state = COMP_STATE_PAUSED;
> +		dmic_stop(dai);
> +		break;
> +	case COMP_TRIGGER_RESUME:
> +		dmic_context_restore(dai);
> +		break;
> +	case COMP_TRIGGER_SUSPEND:
> +		dmic_context_store(dai);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +/* TODO: No idea what should be done here. Currently only trace the
> + * status register that contains a few status and error bit fields.
> + */

The intention here is to emit any DMIC errors via trace errors to help with
debug.

> +static void dmic_irq_handler(void *data)
> +{
> +	struct dai *dai = data;
> +	uint32_t val;
> +
> +	/* Trace OUTSTAT0 register */
> +	val = dmic_read(dai, OUTSTAT0);
> +	trace_dmic("irq");
> +
> +	if (val & OUTSTAT0_ROR_BIT)
> +		trace_dmic_error("eor"); /* Full fifo or PDM overrrun */
> +
> +	trace_value(dmic_read(dai, OUTSTAT0));
> +
> +	/* clear IRQ */
> +	platform_interrupt_clear(dmic_irq(dai), 1);
> +}
> 

Liam


More information about the Sound-open-firmware mailing list