Commit f74028e1 authored by Sameer Pujar's avatar Sameer Pujar Committed by Mark Brown

ASoC: tegra: Add Tegra210 based ADMAIF driver

ADMAIF is the interface between ADMA and AHUB. Each ADMA channel that
sends/receives data to/from AHUB must intreface through an ADMAIF channel.
ADMA channel sending data to AHUB pairs with an ADMAIF Tx channel and
similarly ADMA channel receiving data from AHUB pairs with an ADMAIF Rx
channel. Buffer size is configurable for each ADMAIF channel, but currently
SW uses default values.

This patch registers ADMAIF driver with ASoC framework. The component
driver exposes DAPM widgets, routes and kcontrols for the device. The DAI
driver exposes ADMAIF interfaces, which can be used to connect different
components in the ASoC layer. Makefile and Kconfig support is added to
allow to build the driver. The ADMAIF device can be enabled in the DT via
"nvidia,tegra210-admaif" compatible binding.

Tegra PCM driver is updated to expose required PCM interfaces and
snd_pcm_ops callbacks.
Signed-off-by: default avatarSameer Pujar <spujar@nvidia.com>
Link: https://lore.kernel.org/r/1595134890-16470-8-git-send-email-spujar@nvidia.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 327ef647
......@@ -106,6 +106,18 @@ config SND_SOC_TEGRA186_DSPK
the desired 1-bit output via Delta Sigma Modulation (DSM).
Say Y or M if you want to add support for Tegra186 DSPK module.
config SND_SOC_TEGRA210_ADMAIF
tristate "Tegra210 ADMAIF module"
depends on SND_SOC_TEGRA
help
Config to enable ADMAIF which is the interface between ADMA and
Audio Hub (AHUB). Each ADMA channel that sends/receives data to/
from AHUB must interface through an ADMAIF channel. ADMA channel
sending data to AHUB pairs with an ADMAIF Tx channel, where as
ADMA channel receiving data from AHUB pairs with an ADMAIF Rx
channel. Buffer size is configurable for each ADMAIIF channel.
Say Y or M if you want to add support for Tegra210 ADMAIF module.
config SND_SOC_TEGRA_RT5640
tristate "SoC Audio support for Tegra boards using an RT5640 codec"
depends on SND_SOC_TEGRA && I2C && GPIOLIB
......
......@@ -12,6 +12,7 @@ snd-soc-tegra210-ahub-objs := tegra210_ahub.o
snd-soc-tegra210-dmic-objs := tegra210_dmic.o
snd-soc-tegra210-i2s-objs := tegra210_i2s.o
snd-soc-tegra186-dspk-objs := tegra186_dspk.o
snd-soc-tegra210-admaif-objs := tegra210_admaif.o
obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o
......@@ -25,6 +26,7 @@ obj-$(CONFIG_SND_SOC_TEGRA210_DMIC) += snd-soc-tegra210-dmic.o
obj-$(CONFIG_SND_SOC_TEGRA210_AHUB) += snd-soc-tegra210-ahub.o
obj-$(CONFIG_SND_SOC_TEGRA210_I2S) += snd-soc-tegra210-i2s.o
obj-$(CONFIG_SND_SOC_TEGRA186_DSPK) += snd-soc-tegra186-dspk.o
obj-$(CONFIG_SND_SOC_TEGRA210_ADMAIF) += snd-soc-tegra210-admaif.o
# Tegra machine Support
snd-soc-tegra-rt5640-objs := tegra_rt5640.o
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* tegra210_admaif.h - Tegra ADMAIF registers
*
* Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
*
*/
#ifndef __TEGRA_ADMAIF_H__
#define __TEGRA_ADMAIF_H__
#define TEGRA_ADMAIF_CHANNEL_REG_STRIDE 0x40
/* Tegra210 specific */
#define TEGRA210_ADMAIF_LAST_REG 0x75f
#define TEGRA210_ADMAIF_CHANNEL_COUNT 10
#define TEGRA210_ADMAIF_RX_BASE 0x0
#define TEGRA210_ADMAIF_TX_BASE 0x300
#define TEGRA210_ADMAIF_GLOBAL_BASE 0x700
/* Tegra186 specific */
#define TEGRA186_ADMAIF_LAST_REG 0xd5f
#define TEGRA186_ADMAIF_CHANNEL_COUNT 20
#define TEGRA186_ADMAIF_RX_BASE 0x0
#define TEGRA186_ADMAIF_TX_BASE 0x500
#define TEGRA186_ADMAIF_GLOBAL_BASE 0xd00
/* Global registers */
#define TEGRA_ADMAIF_GLOBAL_ENABLE 0x0
#define TEGRA_ADMAIF_GLOBAL_CG_0 0x8
#define TEGRA_ADMAIF_GLOBAL_STATUS 0x10
#define TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS 0x20
#define TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS 0x24
/* RX channel registers */
#define TEGRA_ADMAIF_RX_ENABLE 0x0
#define TEGRA_ADMAIF_RX_SOFT_RESET 0x4
#define TEGRA_ADMAIF_RX_STATUS 0xc
#define TEGRA_ADMAIF_RX_INT_STATUS 0x10
#define TEGRA_ADMAIF_RX_INT_MASK 0x14
#define TEGRA_ADMAIF_RX_INT_SET 0x18
#define TEGRA_ADMAIF_RX_INT_CLEAR 0x1c
#define TEGRA_ADMAIF_CH_ACIF_RX_CTRL 0x20
#define TEGRA_ADMAIF_RX_FIFO_CTRL 0x28
#define TEGRA_ADMAIF_RX_FIFO_READ 0x2c
/* TX channel registers */
#define TEGRA_ADMAIF_TX_ENABLE 0x0
#define TEGRA_ADMAIF_TX_SOFT_RESET 0x4
#define TEGRA_ADMAIF_TX_STATUS 0xc
#define TEGRA_ADMAIF_TX_INT_STATUS 0x10
#define TEGRA_ADMAIF_TX_INT_MASK 0x14
#define TEGRA_ADMAIF_TX_INT_SET 0x18
#define TEGRA_ADMAIF_TX_INT_CLEAR 0x1c
#define TEGRA_ADMAIF_CH_ACIF_TX_CTRL 0x20
#define TEGRA_ADMAIF_TX_FIFO_CTRL 0x28
#define TEGRA_ADMAIF_TX_FIFO_WRITE 0x2c
/* Bit fields */
#define PACK8_EN_SHIFT 31
#define PACK8_EN_MASK BIT(PACK8_EN_SHIFT)
#define PACK8_EN BIT(PACK8_EN_SHIFT)
#define PACK16_EN_SHIFT 30
#define PACK16_EN_MASK BIT(PACK16_EN_SHIFT)
#define PACK16_EN BIT(PACK16_EN_SHIFT)
#define TX_ENABLE_SHIFT 0
#define TX_ENABLE_MASK BIT(TX_ENABLE_SHIFT)
#define TX_ENABLE BIT(TX_ENABLE_SHIFT)
#define RX_ENABLE_SHIFT 0
#define RX_ENABLE_MASK BIT(RX_ENABLE_SHIFT)
#define RX_ENABLE BIT(RX_ENABLE_SHIFT)
#define SW_RESET_MASK 1
#define SW_RESET 1
/* Default values - Tegra210 */
#define TEGRA210_ADMAIF_RX1_FIFO_CTRL_REG_DEFAULT 0x00000300
#define TEGRA210_ADMAIF_RX2_FIFO_CTRL_REG_DEFAULT 0x00000304
#define TEGRA210_ADMAIF_RX3_FIFO_CTRL_REG_DEFAULT 0x00000208
#define TEGRA210_ADMAIF_RX4_FIFO_CTRL_REG_DEFAULT 0x0000020b
#define TEGRA210_ADMAIF_RX5_FIFO_CTRL_REG_DEFAULT 0x0000020e
#define TEGRA210_ADMAIF_RX6_FIFO_CTRL_REG_DEFAULT 0x00000211
#define TEGRA210_ADMAIF_RX7_FIFO_CTRL_REG_DEFAULT 0x00000214
#define TEGRA210_ADMAIF_RX8_FIFO_CTRL_REG_DEFAULT 0x00000217
#define TEGRA210_ADMAIF_RX9_FIFO_CTRL_REG_DEFAULT 0x0000021a
#define TEGRA210_ADMAIF_RX10_FIFO_CTRL_REG_DEFAULT 0x0000021d
#define TEGRA210_ADMAIF_TX1_FIFO_CTRL_REG_DEFAULT 0x02000300
#define TEGRA210_ADMAIF_TX2_FIFO_CTRL_REG_DEFAULT 0x02000304
#define TEGRA210_ADMAIF_TX3_FIFO_CTRL_REG_DEFAULT 0x01800208
#define TEGRA210_ADMAIF_TX4_FIFO_CTRL_REG_DEFAULT 0x0180020b
#define TEGRA210_ADMAIF_TX5_FIFO_CTRL_REG_DEFAULT 0x0180020e
#define TEGRA210_ADMAIF_TX6_FIFO_CTRL_REG_DEFAULT 0x01800211
#define TEGRA210_ADMAIF_TX7_FIFO_CTRL_REG_DEFAULT 0x01800214
#define TEGRA210_ADMAIF_TX8_FIFO_CTRL_REG_DEFAULT 0x01800217
#define TEGRA210_ADMAIF_TX9_FIFO_CTRL_REG_DEFAULT 0x0180021a
#define TEGRA210_ADMAIF_TX10_FIFO_CTRL_REG_DEFAULT 0x0180021d
/* Default values - Tegra186 */
#define TEGRA186_ADMAIF_RX1_FIFO_CTRL_REG_DEFAULT 0x00000300
#define TEGRA186_ADMAIF_RX2_FIFO_CTRL_REG_DEFAULT 0x00000304
#define TEGRA186_ADMAIF_RX3_FIFO_CTRL_REG_DEFAULT 0x00000308
#define TEGRA186_ADMAIF_RX4_FIFO_CTRL_REG_DEFAULT 0x0000030c
#define TEGRA186_ADMAIF_RX5_FIFO_CTRL_REG_DEFAULT 0x00000210
#define TEGRA186_ADMAIF_RX6_FIFO_CTRL_REG_DEFAULT 0x00000213
#define TEGRA186_ADMAIF_RX7_FIFO_CTRL_REG_DEFAULT 0x00000216
#define TEGRA186_ADMAIF_RX8_FIFO_CTRL_REG_DEFAULT 0x00000219
#define TEGRA186_ADMAIF_RX9_FIFO_CTRL_REG_DEFAULT 0x0000021c
#define TEGRA186_ADMAIF_RX10_FIFO_CTRL_REG_DEFAULT 0x0000021f
#define TEGRA186_ADMAIF_RX11_FIFO_CTRL_REG_DEFAULT 0x00000222
#define TEGRA186_ADMAIF_RX12_FIFO_CTRL_REG_DEFAULT 0x00000225
#define TEGRA186_ADMAIF_RX13_FIFO_CTRL_REG_DEFAULT 0x00000228
#define TEGRA186_ADMAIF_RX14_FIFO_CTRL_REG_DEFAULT 0x0000022b
#define TEGRA186_ADMAIF_RX15_FIFO_CTRL_REG_DEFAULT 0x0000022e
#define TEGRA186_ADMAIF_RX16_FIFO_CTRL_REG_DEFAULT 0x00000231
#define TEGRA186_ADMAIF_RX17_FIFO_CTRL_REG_DEFAULT 0x00000234
#define TEGRA186_ADMAIF_RX18_FIFO_CTRL_REG_DEFAULT 0x00000237
#define TEGRA186_ADMAIF_RX19_FIFO_CTRL_REG_DEFAULT 0x0000023a
#define TEGRA186_ADMAIF_RX20_FIFO_CTRL_REG_DEFAULT 0x0000023d
#define TEGRA186_ADMAIF_TX1_FIFO_CTRL_REG_DEFAULT 0x02000300
#define TEGRA186_ADMAIF_TX2_FIFO_CTRL_REG_DEFAULT 0x02000304
#define TEGRA186_ADMAIF_TX3_FIFO_CTRL_REG_DEFAULT 0x02000308
#define TEGRA186_ADMAIF_TX4_FIFO_CTRL_REG_DEFAULT 0x0200030c
#define TEGRA186_ADMAIF_TX5_FIFO_CTRL_REG_DEFAULT 0x01800210
#define TEGRA186_ADMAIF_TX6_FIFO_CTRL_REG_DEFAULT 0x01800213
#define TEGRA186_ADMAIF_TX7_FIFO_CTRL_REG_DEFAULT 0x01800216
#define TEGRA186_ADMAIF_TX8_FIFO_CTRL_REG_DEFAULT 0x01800219
#define TEGRA186_ADMAIF_TX9_FIFO_CTRL_REG_DEFAULT 0x0180021c
#define TEGRA186_ADMAIF_TX10_FIFO_CTRL_REG_DEFAULT 0x0180021f
#define TEGRA186_ADMAIF_TX11_FIFO_CTRL_REG_DEFAULT 0x01800222
#define TEGRA186_ADMAIF_TX12_FIFO_CTRL_REG_DEFAULT 0x01800225
#define TEGRA186_ADMAIF_TX13_FIFO_CTRL_REG_DEFAULT 0x01800228
#define TEGRA186_ADMAIF_TX14_FIFO_CTRL_REG_DEFAULT 0x0180022b
#define TEGRA186_ADMAIF_TX15_FIFO_CTRL_REG_DEFAULT 0x0180022e
#define TEGRA186_ADMAIF_TX16_FIFO_CTRL_REG_DEFAULT 0x01800231
#define TEGRA186_ADMAIF_TX17_FIFO_CTRL_REG_DEFAULT 0x01800234
#define TEGRA186_ADMAIF_TX18_FIFO_CTRL_REG_DEFAULT 0x01800237
#define TEGRA186_ADMAIF_TX19_FIFO_CTRL_REG_DEFAULT 0x0180023a
#define TEGRA186_ADMAIF_TX20_FIFO_CTRL_REG_DEFAULT 0x0180023d
enum {
DATA_8BIT,
DATA_16BIT,
DATA_32BIT
};
enum {
ADMAIF_RX_PATH,
ADMAIF_TX_PATH,
ADMAIF_PATHS,
};
struct tegra_admaif_soc_data {
const struct snd_soc_component_driver *cmpnt;
const struct regmap_config *regmap_conf;
struct snd_soc_dai_driver *dais;
unsigned int global_base;
unsigned int tx_base;
unsigned int rx_base;
unsigned int num_ch;
};
struct tegra_admaif {
struct snd_dmaengine_dai_dma_data *capture_dma_data;
struct snd_dmaengine_dai_dma_data *playback_dma_data;
const struct tegra_admaif_soc_data *soc_data;
unsigned int *mono_to_stereo[ADMAIF_PATHS];
unsigned int *stereo_to_mono[ADMAIF_PATHS];
struct regmap *regmap;
};
#endif
......@@ -16,12 +16,12 @@
*/
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "tegra_pcm.h"
static const struct snd_pcm_hardware tegra_pcm_hardware = {
......@@ -67,6 +67,239 @@ void tegra_pcm_platform_unregister(struct device *dev)
}
EXPORT_SYMBOL_GPL(tegra_pcm_platform_unregister);
int tegra_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_dmaengine_dai_dma_data *dmap;
struct dma_chan *chan;
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
int ret;
if (rtd->dai_link->no_pcm)
return 0;
dmap = snd_soc_dai_get_dma_data(cpu_dai, substream);
/* Set HW params now that initialization is complete */
snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
/* Ensure period size is multiple of 8 */
ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 0x8);
if (ret) {
dev_err(rtd->dev, "failed to set constraint %d\n", ret);
return ret;
}
chan = dma_request_slave_channel(cpu_dai->dev, dmap->chan_name);
if (!chan) {
dev_err(cpu_dai->dev,
"dmaengine request slave channel failed! (%s)\n",
dmap->chan_name);
return -ENODEV;
}
ret = snd_dmaengine_pcm_open(substream, chan);
if (ret) {
dev_err(rtd->dev,
"dmaengine pcm open failed with err %d (%s)\n", ret,
dmap->chan_name);
dma_release_channel(chan);
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(tegra_pcm_open);
int tegra_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
if (rtd->dai_link->no_pcm)
return 0;
snd_dmaengine_pcm_close_release_chan(substream);
return 0;
}
EXPORT_SYMBOL_GPL(tegra_pcm_close);
int tegra_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_dmaengine_dai_dma_data *dmap;
struct dma_slave_config slave_config;
struct dma_chan *chan;
int ret;
if (rtd->dai_link->no_pcm)
return 0;
dmap = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
if (!dmap)
return 0;
chan = snd_dmaengine_pcm_get_chan(substream);
ret = snd_hwparams_to_dma_slave_config(substream, params,
&slave_config);
if (ret) {
dev_err(rtd->dev, "hw params config failed with err %d\n", ret);
return ret;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
slave_config.dst_addr = dmap->addr;
slave_config.dst_maxburst = 8;
} else {
slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
slave_config.src_addr = dmap->addr;
slave_config.src_maxburst = 8;
}
ret = dmaengine_slave_config(chan, &slave_config);
if (ret < 0) {
dev_err(rtd->dev, "dma slave config failed with err %d\n", ret);
return ret;
}
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
return 0;
}
EXPORT_SYMBOL_GPL(tegra_pcm_hw_params);
int tegra_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
if (rtd->dai_link->no_pcm)
return 0;
snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
}
EXPORT_SYMBOL_GPL(tegra_pcm_hw_free);
int tegra_pcm_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
if (rtd->dai_link->no_pcm)
return 0;
return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
runtime->dma_addr, runtime->dma_bytes);
}
EXPORT_SYMBOL_GPL(tegra_pcm_mmap);
snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return snd_dmaengine_pcm_pointer(substream);
}
EXPORT_SYMBOL_GPL(tegra_pcm_pointer);
static int tegra_pcm_preallocate_dma_buffer(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);
if (!buf->area)
return -ENOMEM;
buf->private_data = NULL;
buf->dev.type = SNDRV_DMA_TYPE_DEV;
buf->dev.dev = pcm->card->dev;
buf->bytes = size;
return 0;
}
static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
{
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
substream = pcm->streams[stream].substream;
if (!substream)
return;
buf = &substream->dma_buffer;
if (!buf->area)
return;
dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr);
buf->area = NULL;
}
static int tegra_pcm_dma_allocate(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(card->dev, DMA_BIT_MASK(32));
if (ret < 0)
return ret;
ret = dma_set_coherent_mask(card->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);
if (ret)
goto err;
}
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = tegra_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE, size);
if (ret)
goto err_free_play;
}
return 0;
err_free_play:
tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
err:
return ret;
}
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);
}
EXPORT_SYMBOL_GPL(tegra_pcm_construct);
void tegra_pcm_destruct(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE);
tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
}
EXPORT_SYMBOL_GPL(tegra_pcm_destruct);
MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra PCM ASoC driver");
MODULE_LICENSE("GPL");
......@@ -17,8 +17,27 @@
#ifndef __TEGRA_PCM_H__
#define __TEGRA_PCM_H__
struct snd_dmaengine_pcm_config;
#include <sound/dmaengine_pcm.h>
#include <sound/asound.h>
int tegra_pcm_construct(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd);
void tegra_pcm_destruct(struct snd_soc_component *component,
struct snd_pcm *pcm);
int tegra_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int tegra_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int tegra_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
int tegra_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int tegra_pcm_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma);
snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int tegra_pcm_platform_register(struct device *dev);
int tegra_pcm_platform_register_with_chan_names(struct device *dev,
struct snd_dmaengine_pcm_config *config,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment