Skip to content

Commit

Permalink
Merge series "arm64: tegra: Enable audio IOMMU support on Tegra194" f…
Browse files Browse the repository at this point in the history
…rom Thierry Reding <thierry.reding@gmail.com>

Thierry Reding <treding@nvidia.com>:

From: Thierry Reding <treding@nvidia.com>

This small series addresses a minor issue with how IOMMU support is
wired up on various Tegra generations. Currently the virtual "card"
device is used to allocate DMA memory for, but since that device does
not actually exist, the path to memory cannot be correctly described.

To address this, this series moves to using the ADMAIF as the DMA device
for audio. This is a real device that can have a proper DMA mask set and
with which a stream ID can be associated with in the SMMU. The memory
accesses technically originate from the ADMA controller (that the ADMAIF
uses), but DMA channel are dynamically allocated at runtime while DMA
memory is allocated at driver load time, drivers won't have access to
the ADMA device yet.

Further patches will be required to correct this issue on Tegra186 and
Tegra210, but I wanted to get feedback on this approach first.

Changes in v2:
- add backwards-compatibility fallback

Thierry

Thierry Reding (2):
  ASoC: tegra: Use ADMAIF component for DMA allocations
  arm64: tegra: Enable audio IOMMU support on Tegra194

 arch/arm64/boot/dts/nvidia/tegra194.dtsi |  4 ++++
 sound/soc/tegra/tegra_pcm.c              | 30 ++++++++++++++----------
 2 files changed, 22 insertions(+), 12 deletions(-)

--
2.32.0
  • Loading branch information
broonie committed Jul 12, 2021
2 parents 6c621b8 + 0dfc21c commit 11169c6
Showing 1 changed file with 18 additions and 12 deletions.
30 changes: 18 additions & 12 deletions sound/soc/tegra/tegra_pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,19 +213,19 @@ snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
}
EXPORT_SYMBOL_GPL(tegra_pcm_pointer);

static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream,
static int tegra_pcm_preallocate_dma_buffer(struct device *dev, struct snd_pcm *pcm, int stream,
size_t size)
{
struct snd_pcm_substream *substream = pcm->streams[stream].substream;
struct snd_dma_buffer *buf = &substream->dma_buffer;

buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL);
buf->area = dma_alloc_wc(dev, size, &buf->addr, GFP_KERNEL);
if (!buf->area)
return -ENOMEM;

buf->private_data = NULL;
buf->dev.type = SNDRV_DMA_TYPE_DEV;
buf->dev.dev = pcm->card->dev;
buf->dev.dev = dev;
buf->bytes = size;

return 0;
Expand All @@ -244,31 +244,28 @@ static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
if (!buf->area)
return;

dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr);
dma_free_wc(buf->dev.dev, buf->bytes, buf->area, buf->addr);
buf->area = NULL;
}

static int tegra_pcm_dma_allocate(struct snd_soc_pcm_runtime *rtd,
static int tegra_pcm_dma_allocate(struct device *dev, struct snd_soc_pcm_runtime *rtd,
size_t size)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
int ret;

ret = dma_set_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret < 0)
return ret;

if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = tegra_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK, size);
ret = tegra_pcm_preallocate_dma_buffer(dev, pcm, SNDRV_PCM_STREAM_PLAYBACK, size);
if (ret)
goto err;
}

if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = tegra_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE, size);
ret = tegra_pcm_preallocate_dma_buffer(dev, pcm, SNDRV_PCM_STREAM_CAPTURE, size);
if (ret)
goto err_free_play;
}
Expand All @@ -284,7 +281,16 @@ static int tegra_pcm_dma_allocate(struct snd_soc_pcm_runtime *rtd,
int tegra_pcm_construct(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
return tegra_pcm_dma_allocate(rtd, tegra_pcm_hardware.buffer_bytes_max);
struct device *dev = component->dev;

/*
* Fallback for backwards-compatibility with older device trees that
* have the iommus property in the virtual, top-level "sound" node.
*/
if (!of_get_property(dev->of_node, "iommus", NULL))
dev = rtd->card->snd_card->dev;

return tegra_pcm_dma_allocate(dev, rtd, tegra_pcm_hardware.buffer_bytes_max);
}
EXPORT_SYMBOL_GPL(tegra_pcm_construct);

Expand Down

0 comments on commit 11169c6

Please sign in to comment.