Re: [RFC v2 5/7] ASoC: stm32: add DFSDM DAI support

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

 




Hello Peter,

Thanks for your highlight on typos.
I did not pay to much attention on it, as i should for a patch candidate
for upstream. Surely wrongly...
For your information, aim of this RFC is to discuss the way to integrate
the DFSDM drivers in ASoC and IIO. So the patches associated can not be
upstreamed in current version.
When global design will be validated, i plan to complete/finalize the
patches and propose the series as "PATCH" instead of "RFC".

Nevertheless, be sure that I will integrate your remarks in next version.

Some answers in-line

Regards,

Arnaud

On 02/13/2017 07:13 PM, Peter Meerwald-Stadler wrote:
> On Mon, 13 Feb 2017, Arnaud Pouliquen wrote:
> 
>> Add driver to handle DAI interface for PDM microphones connected
>> to Digital Filter for Sigma Delta mModulators IP.
> 
> Modulators
> more typos below
>  
>> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@xxxxxx>
>> ---
>>  include/sound/stm32-adfsdm.h |  80 ++++++++++
>>  sound/soc/Kconfig            |   1 +
>>  sound/soc/Makefile           |   1 +
>>  sound/soc/stm/Kconfig        |  10 ++
>>  sound/soc/stm/Makefile       |   2 +
>>  sound/soc/stm/stm32_adfsdm.c | 365 +++++++++++++++++++++++++++++++++++++++++++
>>  6 files changed, 459 insertions(+)
>>  create mode 100644 include/sound/stm32-adfsdm.h
>>  create mode 100644 sound/soc/stm/Kconfig
>>  create mode 100644 sound/soc/stm/Makefile
>>  create mode 100644 sound/soc/stm/stm32_adfsdm.c
>>
>> diff --git a/include/sound/stm32-adfsdm.h b/include/sound/stm32-adfsdm.h
>> new file mode 100644
>> index 0000000..ff5899d
>> --- /dev/null
>> +++ b/include/sound/stm32-adfsdm.h
>> @@ -0,0 +1,80 @@
>> +/*
>> + * This file is part of STM32 DFSDM mfd driver API
>> + *
>> + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
>> + * Author(s): Arnaud Pouliquen <arnaud.pouliquen@xxxxxx>.
>> + *
>> + * License terms: GPL V2.0.
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 as published by
>> + * the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful, but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
>> + * details.
>> + */
>> +#ifndef STM32_ADFSDM_H
>> +#define STM32_ADFSDM_H
>> +
>> +struct stm32_dfsdm_adc;
>> +
>> +/**
>> + * struct stm32_dfsdm_hw_param - stm32 audio hardware params
>> + * @rate:		sampling rate
>> + * @sample_bits:	sample size in bits
>> + * @max_scaling:	effective scaling in bit computed by iio driver
> 
> bits?
> 
>> + */
>> +struct stm32_dfsdm_hw_param {
>> +	unsigned int rate;
>> +	unsigned int sample_bits;
>> +	unsigned int *max_scaling;
>> +};
>> +
>> +/*
>> + * Potential improvement:
>> + * Following structure and functions could be generic and declared in
>> + * an asoc-iio.h
>> + */
>> +struct stm32_adfsdm_codec_ops {
>> +	/*
>> +	 * Set the SPI or manchester input Frequency
> 
> frequency
> 
>> +	 * Optional: not use if DFSDM is master on SPITest
>> +	 */
>> +	void (*set_sysclk)(struct stm32_dfsdm_adc *adc, unsigned int freq);
>> +
>> +	/*
>> +	 * Set expected audio sampling rate and format.
>> +	 * Precision is returned to allow to rescale samples
>> +	 */
>> +	int (*set_hwparam)(struct stm32_dfsdm_adc *adc,
>> +			   struct stm32_dfsdm_hw_param *params);
>> +
>> +	/* Called when ASoC starts an audio stream setup. */
>> +	int (*audio_startup)(struct stm32_dfsdm_adc *adc);
>> +
>> +	/* Shuts down the audio stream. */
>> +	void (*audio_shutdown)(struct stm32_dfsdm_adc *adc);
>> +
>> +	/*
>> +	 * Provides DMA source physicla addr to allow ALsa to handle DMA
> 
> physical
> ALSA
> 
>> +	 * transfers.
>> +	 */
>> +	dma_addr_t (*get_dma_source)(struct stm32_dfsdm_adc *adc);
>> +
>> +	/* Register callback to treat overrun issues */
>> +	void (*register_xrun_cb)(struct stm32_dfsdm_adc *adc,
>> +				 void (*overrun_cb)(void *context),
>> +				 void *context);
>> +
>> +};
>> +
>> +/* stm32 dfsdm initalization data */
>> +struct stm32_adfsdm_pdata {
>> +	const struct stm32_adfsdm_codec_ops *ops;
>> +	struct stm32_dfsdm_adc *adc;
>> +};
>> +
>> +#define STM32_ADFSDM_DRV_NAME "stm32-dfsdm-audio"
>> +#endif
>> diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
>> index 182d92e..3836ebe 100644
>> --- a/sound/soc/Kconfig
>> +++ b/sound/soc/Kconfig
>> @@ -63,6 +63,7 @@ source "sound/soc/sh/Kconfig"
>>  source "sound/soc/sirf/Kconfig"
>>  source "sound/soc/spear/Kconfig"
>>  source "sound/soc/sti/Kconfig"
>> +source "sound/soc/stm/Kconfig"
>>  source "sound/soc/sunxi/Kconfig"
>>  source "sound/soc/tegra/Kconfig"
>>  source "sound/soc/txx9/Kconfig"
>> diff --git a/sound/soc/Makefile b/sound/soc/Makefile
>> index 9a30f21..5440cf7 100644
>> --- a/sound/soc/Makefile
>> +++ b/sound/soc/Makefile
>> @@ -43,6 +43,7 @@ obj-$(CONFIG_SND_SOC)	+= sh/
>>  obj-$(CONFIG_SND_SOC)	+= sirf/
>>  obj-$(CONFIG_SND_SOC)	+= spear/
>>  obj-$(CONFIG_SND_SOC)	+= sti/
>> +obj-$(CONFIG_SND_SOC)	+= stm/
>>  obj-$(CONFIG_SND_SOC)	+= sunxi/
>>  obj-$(CONFIG_SND_SOC)	+= tegra/
>>  obj-$(CONFIG_SND_SOC)	+= txx9/
>> diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
>> new file mode 100644
>> index 0000000..041ddb9
>> --- /dev/null
>> +++ b/sound/soc/stm/Kconfig
>> @@ -0,0 +1,10 @@
>> +menuconfig SND_SOC_STM32_DFSDM
>> +	tristate "SoC Audio support for STM32 DFSDM"
>> +	depends on (ARCH_STM32 && OF && STM32_DFSDM_ADC) || COMPILE_TEST
>> +	depends on SND_SOC
>> +	select SND_SOC_GENERIC_DMAENGINE_PCM
>> +	select SND_SOC_DMIC
>> +	help
>> +	  Select this option to enable the STM32 Digital Filter
>> +	  for Sigma Delta Modulators (DFSDM) driver used
>> +	  in various STM32 series for digital microphone capture.
>> \ No newline at end of file
>> diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
>> new file mode 100644
>> index 0000000..ea90240
>> --- /dev/null
>> +++ b/sound/soc/stm/Makefile
>> @@ -0,0 +1,2 @@
>> +#DFSDM
>> +obj-$(CONFIG_SND_SOC_STM32_DFSDM) += stm32_adfsdm.o
>> diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c
>> new file mode 100644
>> index 0000000..4488461
>> --- /dev/null
>> +++ b/sound/soc/stm/stm32_adfsdm.c
>> @@ -0,0 +1,365 @@
>> +/*
>> + * This file is part of STM32 DFSDM ASoC DAI driver
>> + *
>> + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
>> + * Authors: Arnaud Pouliquen <arnaud.pouliquen@xxxxxx>
>> + *          Olivier Moysan <olivier.moysan@xxxxxx>
>> + *
>> + * License type: GPLv2
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 as published by
>> + * the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful, but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
>> + * or FITNESS FOR A PARTICULAR PURPOSE.
>> + * See the GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License along with
>> + * this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/slab.h>
>> +
>> +#include <sound/dmaengine_pcm.h>
>> +#include <sound/stm32-adfsdm.h>
>> +
>> +#define STM32_ADFSDM_DATA_MASK	GENMASK(31, 8)
>> +
>> +struct stm32_adfsdm_priv {
>> +	struct snd_soc_dai_driver dai_drv;
>> +	struct stm32_adfsdm_pdata *pdata; /* platform data set by IIO driver */
>> +	struct snd_dmaengine_dai_dma_data dma_data;  /* dma config */
>> +	struct snd_pcm_substream *substream;  
>> +	struct snd_pcm_hw_constraint_list rates_const;
>> +	unsigned long dmic_clk; /* SPI or manchester input clock frequency */
>> +	unsigned int fl_id;   /* filter instance ID */
>> +	unsigned int order; /* filter order */
>> +	unsigned int max_scaling;  /* max scaling for audio samples */
>> +};
>> +
>> +struct stm32_adfsdm_data {
>> +	unsigned int rate;	/* SNDRV_PCM_RATE value */
>> +	unsigned int freq;	/* frequency in Hz */
>> +};
>> +
>> +static const struct stm32_adfsdm_data stm32_dfsdm_filter[] = {
>> +	{ .rate = SNDRV_PCM_RATE_8000,  .freq = 8000 },
>> +	{ .rate = SNDRV_PCM_RATE_16000, .freq = 16000 },
>> +	{ .rate = SNDRV_PCM_RATE_32000, .freq = 32000 },
>> +};
>> +
>> +static const struct snd_pcm_hardware stm32_adfsdm_pcm_hw = {
>> +	.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
>> +	    SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP |
>> +	    SNDRV_PCM_INFO_MMAP_VALID,
>> +	.formats = SNDRV_PCM_FMTBIT_S24_LE,
>> +
>> +	.rate_min = 8000,
>> +	.rate_max = 32000,
>> +
>> +	.channels_min = 1,
>> +	.channels_max = 1,
>> +
>> +	.periods_min = 2,
>> +	.periods_max = 48,
>> +
>> +	.period_bytes_min = 40, /* 8 khz 5 ms */
>> +	.period_bytes_max = 4 * PAGE_SIZE,
>> +	.buffer_bytes_max = 16 * PAGE_SIZE
>> +};
>> +
>> +static int stm32_adfsdm_get_supported_rates(struct snd_soc_dai *dai,
>> +					    unsigned int *rates)
>> +{
>> +	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
>> +	struct stm32_adfsdm_pdata *pdata = priv->pdata;
>> +	struct stm32_dfsdm_hw_param params;
>> +	unsigned int max_scaling, i;
>> +	int ret;
>> +
>> +	*rates = 0;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(stm32_dfsdm_filter); i++) {
>> +		/* 
>> +		 * Check that clkout_freq is compatible
>> +		 * Try to find one solution for filter and integrator
>> +		 * oversampling ratio.
>> +		 */
>> +
>> +		params.rate = stm32_dfsdm_filter[i].freq;
>> +		params.sample_bits = 24;
>> +		params.max_scaling = &max_scaling;
>> +
>> +		ret = pdata->ops->set_hwparam(pdata->adc, &params);
>> +		if (!ret) {
>> +			*rates |= 1 << i;
>> +			dev_err(dai->dev, "%s: %d rate supported\n", __func__,
>> +				stm32_dfsdm_filter[i].freq);
>> +		}
>> +	}
>> +
>> +	if (!*rates) {
>> +		dev_err(dai->dev, "%s: no matched rate found\n", __func__);
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_adfsdm_copy(struct snd_pcm_substream *substream, int channel,
>> +			     snd_pcm_uframes_t pos,
>> +			     void __user *buf, snd_pcm_uframes_t count)
>> +{
>> +	struct snd_pcm_runtime *runtime = substream->runtime;
>> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
>> +	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
>> +	int *ptr = (int *)(runtime->dma_area + frames_to_bytes(runtime, pos));
>> +	char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, pos);
>> +	ssize_t bytes = frames_to_bytes(runtime, count);
>> +	ssize_t sample_cnt = bytes_to_samples(runtime, bytes);
>> +	unsigned int shift = 24 -priv->max_scaling;
> 
> 24 - priv->max_scaling
miss this when running checkpatch tool...sorry for this stupid basic error
>> +	
>> +	/*
>> +	 * Audio samples are available on 24 MSBs of the DFSDM DATAR register.
>> +	 * We need to mask 8 LSB control bits...
>> +	 * Additionnaly sample scaling depends on decimation and can need shift
> 
> Additionally
> 
>> +	 * to be aligned on 32-bit word MSB.
>> +	 */
>> +	if (shift > 0) {
>> +		do {
>> +			*ptr <<= shift & STM32_ADFSDM_DATA_MASK;
>> +			ptr++;
>> +		} while (--sample_cnt);
>> +	} else {
>> +		do {
>> +			*ptr &= STM32_ADFSDM_DATA_MASK;
>> +			ptr++;
>> +		} while (--sample_cnt);
>> +	}
>> +
>> +	return copy_to_user(buf, hwbuf, bytes);
>> +}
>> +
>> +static void stm32_dfsdm_xrun(void *context)
>> +{
>> +	struct snd_soc_dai *dai = context;
>> +	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
>> +
>> +	snd_pcm_stream_lock(priv->substream);
>> +	dev_dbg(dai->dev, "%s:unexpected overrun\n", __func__);
> 
> newline
> 
>> +	/* Stop the player */
>> +	snd_pcm_stop(priv->substream, SNDRV_PCM_STATE_XRUN);
>> +	snd_pcm_stream_unlock(priv->substream);
>> +}
>> +
>> +static int stm32_adfsdm_startup(struct snd_pcm_substream *substream,
>> +				struct snd_soc_dai *dai)
>> +{
>> +	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
>> +
>> +	priv->substream = substream;
>> +
>> +	dev_dbg(dai->dev, "%s: enter\n", __func__);
>> +	return 0;
> 
> ????
line added for debug that i forgot to clean...
> 
>> +	return snd_pcm_hw_constraint_list(substream->runtime, 0,
>> +					  SNDRV_PCM_HW_PARAM_RATE,
>> +					  &priv->rates_const);
>> +}
>> +
>> +static void stm32_adfsdm_shutdown(struct snd_pcm_substream *substream,
>> +				  struct snd_soc_dai *dai)
>> +{
>> +	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
>> +
>> +	dev_dbg(dai->dev, "%s: enter\n", __func__);
>> +	priv->substream = NULL;
>> +}
>> +
>> +static int stm32_adfsdm_dai_hw_params(struct snd_pcm_substream *substream,
>> +				      struct snd_pcm_hw_params *params,
>> +				      struct snd_soc_dai *dai)
>> +{
>> +	struct snd_dmaengine_dai_dma_data *dma_data;
>> +	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
>> +	struct stm32_adfsdm_pdata *pdata = priv->pdata;
>> +	struct stm32_dfsdm_hw_param df_params;
>> +
>> +	dev_dbg(dai->dev, "%s: enter\n", __func__);
>> +	dma_data = snd_soc_dai_get_dma_data(dai, substream);
>> +	dma_data->maxburst = 1;
>> +
>> +	df_params.rate = substream->runtime->rate;
>> +	df_params.sample_bits = substream->runtime->sample_bits;
>> +	df_params.max_scaling = &priv->max_scaling;
>> +
>> +	return pdata->ops->set_hwparam(pdata->adc, &df_params);
>> +}
>> +
>> +static int stm32_adfsdm_trigger(struct snd_pcm_substream *substream, int cmd,
>> +				struct snd_soc_dai *dai)
>> +{
>> +	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
>> +	struct stm32_adfsdm_pdata *pdata = priv->pdata;
>> +
>> +	dev_dbg(dai->dev, "%s: enter\n", __func__);
>> +
>> +	switch (cmd) {
>> +	case SNDRV_PCM_TRIGGER_START:
>> +	case SNDRV_PCM_TRIGGER_RESUME:
>> +		return pdata->ops->audio_startup(pdata->adc);
>> +	case SNDRV_PCM_TRIGGER_SUSPEND:
>> +	case SNDRV_PCM_TRIGGER_STOP:
>> +		pdata->ops->audio_shutdown(pdata->adc);
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_adfsdm_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
>> +{
>> +	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
>> +	unsigned int cb = fmt & SND_SOC_DAIFMT_MASTER_MASK;
>> +
>> +	dev_dbg(dai->dev, "%s: enter\n", __func__);
>> +
>> +	if ((cb == SND_SOC_DAIFMT_CBM_CFM) || (cb == SND_SOC_DAIFMT_CBM_CFS)) {
>> +		/* Digital microphone is clocked by external clock */
>> +		if (!priv->dmic_clk) {
>> +			dev_err(dai->dev,
>> +				"system-clock-frequency not defined\n");
>> +			return -EINVAL;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_adfsdm_set_sysclk(struct snd_soc_dai *dai, int clk_id,
>> +				   unsigned int freq, int dir)
>> +{
>> +	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
>> +	struct stm32_adfsdm_pdata *pdata = priv->pdata;
>> +
>> +	dev_dbg(dai->dev, "%s: enter for dai %d\n", __func__, dai->id);
>> +	if (dir == SND_SOC_CLOCK_IN) {
>> +		pdata->ops->set_sysclk(pdata->adc, freq);
>> +		priv->dmic_clk = freq;
>> +	}
>> +
>> +	/* Determine supported rate which depends on SPI/manchester clock */
>> +	return stm32_adfsdm_get_supported_rates(dai, &priv->rates_const.mask);
>> +}
>> +
>> +static const struct snd_soc_dai_ops stm32_adfsdm_dai_ops = {
>> +	.startup = stm32_adfsdm_startup,
>> +	.shutdown = stm32_adfsdm_shutdown,
>> +	.hw_params = stm32_adfsdm_dai_hw_params,
>> +	.set_fmt = stm32_adfsdm_set_dai_fmt,
>> +	.set_sysclk = stm32_adfsdm_set_sysclk,
>> +	.trigger = stm32_adfsdm_trigger,
>> +};
>> +
>> +static int stm32_adfsdm_dai_probe(struct snd_soc_dai *dai)
>> +{
>> +	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
>> +	struct snd_dmaengine_dai_dma_data *dma = &priv->dma_data;
>> +	struct stm32_adfsdm_pdata *pdata = priv->pdata;
>> +
>> +	dev_dbg(dai->dev, "%s: enter for dai %d\n", __func__, dai->id);
>> +
>> +	/* DMA settings */
>> +	snd_soc_dai_init_dma_data(dai, NULL, dma);
>> +	dma->addr = pdata->ops->get_dma_source(pdata->adc);
>> +	dma->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
>> +
>> +	pdata->ops->register_xrun_cb(priv->pdata->adc, stm32_dfsdm_xrun, dai);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_adfsdm_dai_remove(struct snd_soc_dai *dai)
>> +{
>> +	dev_dbg(dai->dev, "%s: enter for dai %d\n", __func__, dai->id);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct snd_soc_dai_driver stm32_adfsdm_dai = {
>> +	.capture = {
>> +		    .channels_min = 1,
>> +		    .channels_max = 1,
>> +		    .formats = SNDRV_PCM_FMTBIT_S24_LE,
>> +		    .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
>> +			      SNDRV_PCM_RATE_32000),
>> +		    },
>> +	.probe = stm32_adfsdm_dai_probe,
>> +	.remove = stm32_adfsdm_dai_remove,
>> +	.ops = &stm32_adfsdm_dai_ops,
>> +};
>> +
>> +static const struct snd_soc_component_driver stm32_adfsdm_dai_component = {
>> +	.name = "sti_cpu_dai",
>> +};
>> +
>> +static const struct snd_dmaengine_pcm_config dmaengine_pcm_config = {
>> +	.pcm_hardware = &stm32_adfsdm_pcm_hw,
>> +	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
>> +	.copy = stm32_adfsdm_copy,
>> +};
>> +
>> +static int stm32_adfsdm_probe(struct platform_device *pdev)
>> +{
>> +	struct stm32_adfsdm_priv *priv;
>> +	struct stm32_adfsdm_pdata *pdata = pdev->dev.platform_data;
>> +	int ret;
>> +
>> +	dev_dbg(&pdev->dev, "%s: enter for node %p\n", __func__,
>> +		pdev->dev.parent->of_node->name);
>> +
>> +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
>> +	if (!priv)
>> +		return -ENOMEM;
>> +
>> +	priv->pdata = pdata;
>> +
>> +	priv->dai_drv = stm32_adfsdm_dai;
>> +	priv->dai_drv.name = pdev->dev.parent->of_node->name;
>> +	priv->dai_drv.capture.stream_name = pdev->dev.parent->of_node->name;
>> +
>> +	dev_set_drvdata(&pdev->dev, priv);
>> +
>> +	ret = devm_snd_soc_register_component(&pdev->dev,
>> +					      &stm32_adfsdm_dai_component,
>> +					      &priv->dai_drv, 1);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = devm_snd_dmaengine_pcm_register(pdev->dev.parent,
>> +					      &dmaengine_pcm_config, 0);
>> +	if (ret < 0)
>> +		dev_err(&pdev->dev, "failed to register dma pcm config\n");
>> +
>> +	return ret;
>> +}
>> +
>> +static struct platform_driver stm32_adfsdm_driver = {
>> +	.driver = {
>> +		   .name = STM32_ADFSDM_DRV_NAME,
>> +		   },
>> +	.probe = stm32_adfsdm_probe,
>> +};
>> +
>> +module_platform_driver(stm32_adfsdm_driver);
>> +
>> +MODULE_DESCRIPTION("stm32 DFSDM DAI driver");
>> +MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@xxxxxx>");
>> +MODULE_LICENSE("GPL v2");
>> +MODULE_ALIAS("platform:" STM32_ADFSDM_DRV_NAME);
>>
> 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]
  Powered by Linux