[alsa-devel] [PATCH 0/3] DMA fixes for ux500 ASoC driver
Hi Mark,
The DMA driver used on ux500 has been recently reworked to make it device-tree capable, but the rework required to drop some "features", such as opportunistic channel allocation and hardcoded addresses, that the ASoC driver was relying upon.
This series fixes the audio driver to make it work with the current dma40 implementation, and works fine even when booting with device-tree.
Would you consider merging these for asoc/topic/ux500?
Thanks, Fabio
Fabio Baltieri (3): ASoC: ux500: Move DMA parameters into ux500_msp ASoC: ux500: Set DMA address during device init ASoC: ux500: Add DMA slave config prepare routine
sound/soc/ux500/ux500_msp_dai.c | 11 ++++------- sound/soc/ux500/ux500_msp_dai.h | 2 -- sound/soc/ux500/ux500_msp_i2s.c | 13 +++++++++---- sound/soc/ux500/ux500_msp_i2s.h | 15 ++++++++------- sound/soc/ux500/ux500_pcm.c | 30 ++++++++++++++++++++++++++++++ 5 files changed, 51 insertions(+), 20 deletions(-)
Move struct ux500_msp_dma_params declaration from ux500_msp_i2s_drvdata to ux500_msp, this saves some confusing pointer passing and allows to access all DMA configuration fields from ux500_msp_i2s.
Signed-off-by: Fabio Baltieri fabio.baltieri@linaro.org --- sound/soc/ux500/ux500_msp_dai.c | 11 ++++------- sound/soc/ux500/ux500_msp_dai.h | 2 -- sound/soc/ux500/ux500_msp_i2s.c | 10 ++++++---- sound/soc/ux500/ux500_msp_i2s.h | 14 +++++++------- 4 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 7d5fc13..c6fb5cc 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -658,14 +658,11 @@ static int ux500_msp_dai_probe(struct snd_soc_dai *dai) { struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
- drvdata->playback_dma_data.dma_cfg = drvdata->msp->dma_cfg_tx; - drvdata->capture_dma_data.dma_cfg = drvdata->msp->dma_cfg_rx; + dai->playback_dma_data = &drvdata->msp->playback_dma_data; + dai->capture_dma_data = &drvdata->msp->capture_dma_data;
- dai->playback_dma_data = &drvdata->playback_dma_data; - dai->capture_dma_data = &drvdata->capture_dma_data; - - drvdata->playback_dma_data.data_size = drvdata->slot_width; - drvdata->capture_dma_data.data_size = drvdata->slot_width; + drvdata->msp->playback_dma_data.data_size = drvdata->slot_width; + drvdata->msp->capture_dma_data.data_size = drvdata->slot_width;
return 0; } diff --git a/sound/soc/ux500/ux500_msp_dai.h b/sound/soc/ux500/ux500_msp_dai.h index c721282..312ae53 100644 --- a/sound/soc/ux500/ux500_msp_dai.h +++ b/sound/soc/ux500/ux500_msp_dai.h @@ -51,8 +51,6 @@ enum ux500_msp_clock_id { struct ux500_msp_i2s_drvdata { struct ux500_msp *msp; struct regulator *reg_vape; - struct ux500_msp_dma_params playback_dma_data; - struct ux500_msp_dma_params capture_dma_data; unsigned int fmt; unsigned int tx_mask; unsigned int rx_mask; diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index cba0e86..14a4a5b 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -367,12 +367,14 @@ static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config) }
/* Make sure the correct DMA-directions are configured */ - if ((config->direction & MSP_DIR_RX) && (!msp->dma_cfg_rx)) { + if ((config->direction & MSP_DIR_RX) && + !msp->capture_dma_data.dma_cfg) { dev_err(msp->dev, "%s: ERROR: MSP RX-mode is not configured!", __func__); return -EINVAL; } - if ((config->direction == MSP_DIR_TX) && (!msp->dma_cfg_tx)) { + if ((config->direction == MSP_DIR_TX) && + !msp->playback_dma_data.dma_cfg) { dev_err(msp->dev, "%s: ERROR: MSP TX-mode is not configured!", __func__); return -EINVAL; @@ -673,8 +675,8 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
msp->id = platform_data->id; msp->dev = &pdev->dev; - msp->dma_cfg_rx = platform_data->msp_i2s_dma_rx; - msp->dma_cfg_tx = platform_data->msp_i2s_dma_tx; + msp->playback_dma_data.dma_cfg = platform_data->msp_i2s_dma_tx; + msp->capture_dma_data.dma_cfg = platform_data->msp_i2s_dma_rx;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h index 189a375..8796171 100644 --- a/sound/soc/ux500/ux500_msp_i2s.h +++ b/sound/soc/ux500/ux500_msp_i2s.h @@ -468,12 +468,17 @@ struct ux500_msp_config { unsigned int iodelay; };
+struct ux500_msp_dma_params { + unsigned int data_size; + struct stedma40_chan_cfg *dma_cfg; +}; + struct ux500_msp { enum msp_i2s_id id; void __iomem *registers; struct device *dev; - struct stedma40_chan_cfg *dma_cfg_rx; - struct stedma40_chan_cfg *dma_cfg_tx; + struct ux500_msp_dma_params playback_dma_data; + struct ux500_msp_dma_params capture_dma_data; enum msp_state msp_state; int def_elem_len; unsigned int dir_busy; @@ -481,11 +486,6 @@ struct ux500_msp { unsigned int f_bitclk; };
-struct ux500_msp_dma_params { - unsigned int data_size; - struct stedma40_chan_cfg *dma_cfg; -}; - struct msp_i2s_platform_data; int ux500_msp_i2s_init_msp(struct platform_device *pdev, struct ux500_msp **msp_p,
Add a field with the tx/rx register address to the DMA parameters structure, and set it to the correct address during device initialization.
This address used to be hardcoded in the DMA controller driver, it now needs to be explicitly figured out by the device driver.
Signed-off-by: Fabio Baltieri fabio.baltieri@linaro.org --- sound/soc/ux500/ux500_msp_i2s.c | 3 +++ sound/soc/ux500/ux500_msp_i2s.h | 1 + 2 files changed, 4 insertions(+)
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 14a4a5b..1ca8b08 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -685,6 +685,9 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, return -ENOMEM; }
+ msp->playback_dma_data.tx_rx_addr = res->start + MSP_DR; + msp->capture_dma_data.tx_rx_addr = res->start + MSP_DR; + msp->registers = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (msp->registers == NULL) { diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h index 8796171..258d0bc 100644 --- a/sound/soc/ux500/ux500_msp_i2s.h +++ b/sound/soc/ux500/ux500_msp_i2s.h @@ -470,6 +470,7 @@ struct ux500_msp_config {
struct ux500_msp_dma_params { unsigned int data_size; + dma_addr_t tx_rx_addr; struct stedma40_chan_cfg *dma_cfg; };
Implement a DMA slave config prepare routine, as until now the MSP driver depended on the DMA controller completing the channel configuration on its own, but this is not the case anymore since the recent DMA driver updates.
Signed-off-by: Fabio Baltieri fabio.baltieri@linaro.org --- sound/soc/ux500/ux500_pcm.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c index b6e5ae2..5f01c19 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c @@ -103,10 +103,40 @@ static struct dma_chan *ux500_pcm_request_chan(struct snd_soc_pcm_runtime *rtd, return snd_dmaengine_pcm_request_channel(stedma40_filter, dma_cfg); }
+static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct ux500_msp_dma_params *dma_params; + struct stedma40_chan_cfg *dma_cfg; + int ret; + + dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + dma_cfg = dma_params->dma_cfg; + + ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config); + if (ret) + return ret; + + slave_config->dst_maxburst = 4; + slave_config->dst_addr_width = dma_cfg->dst_info.data_width; + slave_config->src_maxburst = 4; + slave_config->src_addr_width = dma_cfg->src_info.data_width; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + slave_config->dst_addr = dma_params->tx_rx_addr; + else + slave_config->src_addr = dma_params->tx_rx_addr; + + return 0; +} + static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = { .pcm_hardware = &ux500_pcm_hw, .compat_request_channel = ux500_pcm_request_chan, .prealloc_buffer_size = 128 * 1024, + .prepare_slave_config = ux500_pcm_prepare_slave_config, };
int ux500_pcm_register_platform(struct platform_device *pdev)
On Wed, Jun 12, 2013 at 9:57 AM, Fabio Baltieri fabio.baltieri@linaro.org wrote:
The DMA driver used on ux500 has been recently reworked to make it device-tree capable, but the rework required to drop some "features", such as opportunistic channel allocation and hardcoded addresses, that the ASoC driver was relying upon.
This series fixes the audio driver to make it work with the current dma40 implementation, and works fine even when booting with device-tree.
FWIW: all look good to me. Acked-by: Linus Walleij linus.walleij@linaro.org
Yours, Linus Walleij
On Wed, 12 Jun 2013, Fabio Baltieri wrote:
Hi Mark,
The DMA driver used on ux500 has been recently reworked to make it device-tree capable, but the rework required to drop some "features", such as opportunistic channel allocation and hardcoded addresses, that the ASoC driver was relying upon.
This series fixes the audio driver to make it work with the current dma40 implementation, and works fine even when booting with device-tree.
Would you consider merging these for asoc/topic/ux500?
Thanks, Fabio
Fabio Baltieri (3): ASoC: ux500: Move DMA parameters into ux500_msp ASoC: ux500: Set DMA address during device init ASoC: ux500: Add DMA slave config prepare routine
sound/soc/ux500/ux500_msp_dai.c | 11 ++++------- sound/soc/ux500/ux500_msp_dai.h | 2 -- sound/soc/ux500/ux500_msp_i2s.c | 13 +++++++++---- sound/soc/ux500/ux500_msp_i2s.h | 15 ++++++++------- sound/soc/ux500/ux500_pcm.c | 30 ++++++++++++++++++++++++++++++ 5 files changed, 51 insertions(+), 20 deletions(-)
I don't see anything visually wrong with them, so as long as they work for you, then you can apply my:
Acked-by: Lee Jones lee.jones@linaro.org
On Wed, Jun 12, 2013 at 09:57:56AM +0200, Fabio Baltieri wrote:
Hi Mark,
The DMA driver used on ux500 has been recently reworked to make it device-tree capable, but the rework required to drop some "features", such as opportunistic channel allocation and hardcoded addresses, that the ASoC driver was relying upon.
Applied all, thanks.
participants (4)
-
Fabio Baltieri
-
Lee Jones
-
Linus Walleij
-
Mark Brown