diff mbox

[15/31] ASoC: dmaengine: add custom DMA config to snd_dmaengine_pcm_config

Message ID 1384548866-13141-16-git-send-email-swarren@wwwdotorg.org (mailing list archive)
State New, archived
Headers show

Commit Message

Stephen Warren Nov. 15, 2013, 8:54 p.m. UTC
From: Stephen Warren <swarren@nvidia.com>

Add fields to struct snd_dmaengine_pcm_config to allow custom:

- DMA channel names.

  This is useful when the default "tx" and "rx" channel names don't
  apply, for example if a HW module supports multiple channels, each
  having different DMA channel names. This is the case with the FIFOs
  in Tegra's AHUB. This new facility can replace
  SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME.

- DMA device

  This allows requesting DMA channels for a device other than the device
  which is registering the "PCM" driver. This is quite unusual, but is
  currently useful on Tegra. In much HW, and in Tegra20, each DAI HW
  module contains its own FIFOs which DMA writes to. However, in Tegra30,
  the DMA FIFOs were split out AHUB HW module, which then routes the data
  through a cross-bar, and into the DAI HW modules. However, the current
  ASoC driver structure does not expose this detail, and acts as if the
  FIFOs are still part of the DAI HW modules. Consequently, the "PCM"
  driver is registered with the DAI HW module, yet the DMA channels must
  be looked up in the AHUB HW module's device tree node. This new config
  field allows that to happen. Eventually, the Tegra drivers will be
  reworked to fully expose the AHUB, and this config field can be
  removed.

Cc: treding@nvidia.com
Cc: linux-tegra@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: alsa-devel@alsa-project.org
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
This patch is part of a series with strong internal depdendencies. I'm
looking for an ack so that I can take the entire series through the Tegra
and arm-soc trees. The series will be part of a stable branch that can be
merged into other subsystems if needed to avoid/resolve dependencies.
---
 include/sound/dmaengine_pcm.h         | 6 ++++++
 sound/soc/soc-generic-dmaengine-pcm.c | 9 +++++++--
 2 files changed, 13 insertions(+), 2 deletions(-)

Comments

Mark Brown Nov. 16, 2013, 9:44 a.m. UTC | #1
On Fri, Nov 15, 2013 at 01:54:10PM -0700, Stephen Warren wrote:

> - DMA device

>   This allows requesting DMA channels for a device other than the device
>   which is registering the "PCM" driver. This is quite unusual, but is
>   currently useful on Tegra. In much HW, and in Tegra20, each DAI HW

Acked-by: Mark Brown <broonie@linaro.org>

but this one especially I'd like to get into ASoC as soon as possible
since this one should be being used by other things.

I'm a bit concerned about anything actually using dma_dev since it
indicates that something is being worked around, it'd be a bit nicer to
print a warning when doing this to give people a hint that they might
not be doing the right thing if they use it (unless someone comes up
with a system that has a clear use case for it).
Lars-Peter Clausen Nov. 16, 2013, 10:43 a.m. UTC | #2
On 11/15/2013 09:54 PM, Stephen Warren wrote:
> From: Stephen Warren <swarren@nvidia.com>
> 
> Add fields to struct snd_dmaengine_pcm_config to allow custom:
> 
> - DMA channel names.
> 
>   This is useful when the default "tx" and "rx" channel names don't
>   apply, for example if a HW module supports multiple channels, each
>   having different DMA channel names. This is the case with the FIFOs
>   in Tegra's AHUB. This new facility can replace
>   SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME.
> 
> - DMA device
> 
>   This allows requesting DMA channels for a device other than the device
>   which is registering the "PCM" driver. This is quite unusual, but is
>   currently useful on Tegra. In much HW, and in Tegra20, each DAI HW
>   module contains its own FIFOs which DMA writes to. However, in Tegra30,
>   the DMA FIFOs were split out AHUB HW module, which then routes the data
>   through a cross-bar, and into the DAI HW modules. However, the current
>   ASoC driver structure does not expose this detail, and acts as if the
>   FIFOs are still part of the DAI HW modules. Consequently, the "PCM"
>   driver is registered with the DAI HW module, yet the DMA channels must
>   be looked up in the AHUB HW module's device tree node. This new config
>   field allows that to happen. Eventually, the Tegra drivers will be
>   reworked to fully expose the AHUB, and this config field can be
>   removed.
> 
> Cc: treding@nvidia.com
> Cc: linux-tegra@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: Liam Girdwood <lgirdwood@gmail.com>
> Cc: Mark Brown <broonie@kernel.org>
> Cc: alsa-devel@alsa-project.org
> Signed-off-by: Stephen Warren <swarren@nvidia.com>

Acked-by: Lars-Peter Clausen <lars@metafoo.de>
Stephen Warren Nov. 18, 2013, 6:45 p.m. UTC | #3
On 11/16/2013 02:44 AM, Mark Brown wrote:
> On Fri, Nov 15, 2013 at 01:54:10PM -0700, Stephen Warren wrote:
> 
>> - DMA device
> 
>> This allows requesting DMA channels for a device other than the 
>> device which is registering the "PCM" driver. This is quite 
>> unusual, but is currently useful on Tegra. In much HW, and in 
>> Tegra20, each DAI HW
...
> I'm a bit concerned about anything actually using dma_dev since it
>  indicates that something is being worked around, it'd be a bit 
> nicer to print a warning when doing this to give people a hint
> that they might not be doing the right thing if they use it
> (unless someone comes up with a system that has a clear use case
> for it).

What if I squash the following into that patch:

> diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
> index 1160d1cba133..0e2645dee96a 100644
> --- a/sound/soc/soc-generic-dmaengine-pcm.c
> +++ b/sound/soc/soc-generic-dmaengine-pcm.c
> @@ -296,8 +296,17 @@ static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
>  	    !dev->of_node)
>  		return 0;
>  
> -	if (config->dma_dev)
> +	if (config->dma_dev) {
> +		/*
> +		 * If this warning is seen, it probably means that your Linux
> +		 * device structure does not match your HW device structure.
> +		 * It would be best to refactor the Linux device structure to
> +		 * correctly match the HW structure.
> +		 */
> +		dev_warn(dev, "DMA channels sourced from device %s",
> +			 dev_name(config->dma_dev));
>  		dev = config->dma_dev;
> +	}
>  
>  	for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;
>  	     i++) {

(a few patches later) That yields the following warning on Tegra, for
example:

> [    2.629623] tegra30-i2s 70080400.i2s: DMA channels sourced from device 70080000.ahub
Mark Brown Nov. 19, 2013, 9:35 a.m. UTC | #4
On Mon, Nov 18, 2013 at 11:45:17AM -0700, Stephen Warren wrote:

> What if I squash the following into that patch:

Looks good.
diff mbox

Patch

diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index 15017311f2e9..87e9d481d7b6 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -114,6 +114,10 @@  void snd_dmaengine_pcm_set_config_from_dai_data(
  * @compat_filter_fn: Will be used as the filter function when requesting a
  *  channel for platforms which do not use devicetree. The filter parameter
  *  will be the DAI's DMA data.
+ * @dma_dev: If set, request DMA channel on this device rather than the DAI
+ *  device.
+ * @chan_names: If set, these custom DMA channel names will be requested at
+ *  registration time.
  * @pcm_hardware: snd_pcm_hardware struct to be used for the PCM.
  * @prealloc_buffer_size: Size of the preallocated audio buffer.
  *
@@ -130,6 +134,8 @@  struct snd_dmaengine_pcm_config {
 			struct snd_soc_pcm_runtime *rtd,
 			struct snd_pcm_substream *substream);
 	dma_filter_fn compat_filter_fn;
+	struct device *dma_dev;
+	const char *chan_names[SNDRV_PCM_STREAM_LAST + 1];
 
 	const struct snd_pcm_hardware *pcm_hardware;
 	unsigned int prealloc_buffer_size;
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index f7e65e1552ef..40e0943a06b8 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -285,7 +285,7 @@  static const char * const dmaengine_pcm_dma_channel_names[] = {
 };
 
 static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
-					 struct device *dev)
+	struct device *dev, const struct snd_dmaengine_pcm_config *config)
 {
 	unsigned int i;
 	const char *name;
@@ -296,12 +296,17 @@  static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
 	    !dev->of_node)
 		return 0;
 
+	if (config->dma_dev)
+		dev = config->dma_dev;
+
 	for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;
 	     i++) {
 		if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
 			name = "rx-tx";
 		else
 			name = dmaengine_pcm_dma_channel_names[i];
+		if (config->chan_names[i])
+			name = config->chan_names[i];
 		chan = dma_request_slave_channel_or_err(dev, name);
 		if (IS_ERR(chan)) {
 			if (PTR_ERR(pcm->chan[i]) == -EPROBE_DEFER)
@@ -352,7 +357,7 @@  int snd_dmaengine_pcm_register(struct device *dev,
 	pcm->config = config;
 	pcm->flags = flags;
 
-	ret = dmaengine_pcm_request_chan_of(pcm, dev);
+	ret = dmaengine_pcm_request_chan_of(pcm, dev, config);
 	if (ret)
 		goto err_free_pcm;