Commit bf102621 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'asoc/topic/dmaengine' into asoc-next

parents f84025ba 73fe01cf
...@@ -51,6 +51,16 @@ struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, ...@@ -51,6 +51,16 @@ struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn,
void *filter_data); void *filter_data);
struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream);
/*
* The DAI supports packed transfers, eg 2 16-bit samples in a 32-bit word.
* If this flag is set the dmaengine driver won't put any restriction on
* the supported sample formats and set the DMA transfer size to undefined.
* The DAI driver is responsible to disable any unsupported formats in it's
* configuration and catch corner cases that are not already handled in
* the ALSA core.
*/
#define SND_DMAENGINE_PCM_DAI_FLAG_PACK BIT(0)
/** /**
* struct snd_dmaengine_dai_dma_data - DAI DMA configuration data * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data
* @addr: Address of the DAI data source or destination register. * @addr: Address of the DAI data source or destination register.
...@@ -63,6 +73,7 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) ...@@ -63,6 +73,7 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
* requesting the DMA channel. * requesting the DMA channel.
* @chan_name: Custom channel name to use when requesting DMA channel. * @chan_name: Custom channel name to use when requesting DMA channel.
* @fifo_size: FIFO size of the DAI controller in bytes * @fifo_size: FIFO size of the DAI controller in bytes
* @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now
*/ */
struct snd_dmaengine_dai_dma_data { struct snd_dmaengine_dai_dma_data {
dma_addr_t addr; dma_addr_t addr;
...@@ -72,6 +83,7 @@ struct snd_dmaengine_dai_dma_data { ...@@ -72,6 +83,7 @@ struct snd_dmaengine_dai_dma_data {
void *filter_data; void *filter_data;
const char *chan_name; const char *chan_name;
unsigned int fifo_size; unsigned int fifo_size;
unsigned int flags;
}; };
void snd_dmaengine_pcm_set_config_from_dai_data( void snd_dmaengine_pcm_set_config_from_dai_data(
......
...@@ -106,8 +106,9 @@ EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); ...@@ -106,8 +106,9 @@ EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config);
* direction of the substream. If the substream is a playback stream the dst * direction of the substream. If the substream is a playback stream the dst
* fields will be initialized, if it is a capture stream the src fields will be * fields will be initialized, if it is a capture stream the src fields will be
* initialized. The {dst,src}_addr_width field will only be initialized if the * initialized. The {dst,src}_addr_width field will only be initialized if the
* addr_width field of the DAI DMA data struct is not equal to * SND_DMAENGINE_PCM_DAI_FLAG_PACK flag is set or if the addr_width field of
* DMA_SLAVE_BUSWIDTH_UNDEFINED. * the DAI DMA data struct is not equal to DMA_SLAVE_BUSWIDTH_UNDEFINED. If
* both conditions are met the latter takes priority.
*/ */
void snd_dmaengine_pcm_set_config_from_dai_data( void snd_dmaengine_pcm_set_config_from_dai_data(
const struct snd_pcm_substream *substream, const struct snd_pcm_substream *substream,
...@@ -117,11 +118,17 @@ void snd_dmaengine_pcm_set_config_from_dai_data( ...@@ -117,11 +118,17 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
slave_config->dst_addr = dma_data->addr; slave_config->dst_addr = dma_data->addr;
slave_config->dst_maxburst = dma_data->maxburst; slave_config->dst_maxburst = dma_data->maxburst;
if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)
slave_config->dst_addr_width =
DMA_SLAVE_BUSWIDTH_UNDEFINED;
if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
slave_config->dst_addr_width = dma_data->addr_width; slave_config->dst_addr_width = dma_data->addr_width;
} else { } else {
slave_config->src_addr = dma_data->addr; slave_config->src_addr = dma_data->addr;
slave_config->src_maxburst = dma_data->maxburst; slave_config->src_maxburst = dma_data->maxburst;
if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)
slave_config->src_addr_width =
DMA_SLAVE_BUSWIDTH_UNDEFINED;
if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
slave_config->src_addr_width = dma_data->addr_width; slave_config->src_addr_width = dma_data->addr_width;
} }
......
...@@ -163,31 +163,42 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea ...@@ -163,31 +163,42 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
} }
/* /*
* Prepare formats mask for valid/allowed sample types. If the dma does * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep
* not have support for the given physical word size, it needs to be * hw.formats set to 0, meaning no restrictions are in place.
* masked out so user space can not use the format which produces * In this case it's the responsibility of the DAI driver to
* corrupted audio. * provide the supported format information.
* In case the dma driver does not implement the slave_caps the default
* assumption is that it supports 1, 2 and 4 bytes widths.
*/ */
for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK))
int bits = snd_pcm_format_physical_width(i); /*
* Prepare formats mask for valid/allowed sample types. If the
/* Enable only samples with DMA supported physical widths */ * dma does not have support for the given physical word size,
switch (bits) { * it needs to be masked out so user space can not use the
case 8: * format which produces corrupted audio.
case 16: * In case the dma driver does not implement the slave_caps the
case 24: * default assumption is that it supports 1, 2 and 4 bytes
case 32: * widths.
case 64: */
if (addr_widths & (1 << (bits / 8))) for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
hw.formats |= (1LL << i); int bits = snd_pcm_format_physical_width(i);
break;
default: /*
/* Unsupported types */ * Enable only samples with DMA supported physical
break; * widths
*/
switch (bits) {
case 8:
case 16:
case 24:
case 32:
case 64:
if (addr_widths & (1 << (bits / 8)))
hw.formats |= (1LL << i);
break;
default:
/* Unsupported types */
break;
}
} }
}
return snd_soc_set_runtime_hwparams(substream, &hw); return snd_soc_set_runtime_hwparams(substream, &hw);
} }
......
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