From ddd17531ad9089ca1a758cd53fb698f396665cb5 Mon Sep 17 00:00:00 2001 From: Sebastien Guiriec Date: Wed, 13 Feb 2013 08:21:54 +0100 Subject: ASoC: omap-mcpdm: Clean up with devm_* function Clean up McPDM driver with devm_ function. Signed-off-by: Sebastien Guiriec Acked-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcpdm.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'sound/soc/omap/omap-mcpdm.c') diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 5ca11bd..079f277 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -369,7 +369,7 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai) pm_runtime_get_sync(mcpdm->dev); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00); - ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler, + ret = devm_request_irq(mcpdm->dev, mcpdm->irq, omap_mcpdm_irq_handler, 0, "McPDM", (void *)mcpdm); pm_runtime_put_sync(mcpdm->dev); @@ -389,7 +389,6 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai) { struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); - free_irq(mcpdm->irq, (void *)mcpdm); pm_runtime_disable(mcpdm->dev); return 0; @@ -465,14 +464,11 @@ static int asoc_mcpdm_probe(struct platform_device *pdev) if (res == NULL) return -ENOMEM; - if (!devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), "McPDM")) - return -EBUSY; - - mcpdm->io_base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!mcpdm->io_base) + mcpdm->io_base = devm_request_and_ioremap(&pdev->dev, res); + if (!mcpdm->io_base) { + dev_err(&pdev->dev, "cannot remap\n"); return -ENOMEM; + } mcpdm->irq = platform_get_irq(pdev, 0); if (mcpdm->irq < 0) -- cgit v1.1 From 77c641d3468a66377752ee9ae06e65dee41fe804 Mon Sep 17 00:00:00 2001 From: Silviu-Mihai Popescu Date: Mon, 11 Mar 2013 17:58:57 +0200 Subject: ASoC: omap: convert to devm_ioremap_resource() Convert all uses of devm_request_and_ioremap() to the newly introduced devm_ioremap_resource() which provides more consistent error handling. devm_ioremap_resource() provides its own error messages so all explicit error messages can be removed from the failure code paths. Signed-off-by: Silviu-Mihai Popescu Acked-by: Jarkko Nikula Acked-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcpdm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'sound/soc/omap/omap-mcpdm.c') diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 079f277..ddfcc18 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -464,11 +464,9 @@ static int asoc_mcpdm_probe(struct platform_device *pdev) if (res == NULL) return -ENOMEM; - mcpdm->io_base = devm_request_and_ioremap(&pdev->dev, res); - if (!mcpdm->io_base) { - dev_err(&pdev->dev, "cannot remap\n"); - return -ENOMEM; - } + mcpdm->io_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mcpdm->io_base)) + return PTR_ERR(mcpdm->io_base); mcpdm->irq = platform_get_irq(pdev, 0); if (mcpdm->irq < 0) -- cgit v1.1 From 623766318aeb5f8dee83b2e8926c39cf83568197 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 20 Mar 2013 10:47:12 +0100 Subject: ASoC: omap-mcpdm: Collect link direction configuration under a struct mcpdm_link_config will collect the link direction related configurations like channel masks, FIFO threshold. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcpdm.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'sound/soc/omap/omap-mcpdm.c') diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index ddfcc18..6e19f44 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -45,6 +45,11 @@ #define OMAP44XX_MCPDM_L3_BASE 0x49032000 +struct mcpdm_link_config { + u32 link_mask; /* channel mask for the direction */ + u32 threshold; /* FIFO threshold */ +}; + struct omap_mcpdm { struct device *dev; unsigned long phys_base; @@ -53,13 +58,8 @@ struct omap_mcpdm { struct mutex mutex; - /* channel data */ - u32 dn_channels; - u32 up_channels; - - /* McPDM FIFO thresholds */ - u32 dn_threshold; - u32 up_threshold; + /* Playback/Capture configuration */ + struct mcpdm_link_config config[2]; /* McPDM dn offsets for rx1, and 2 channels */ u32 dn_rx_offset; @@ -130,11 +130,12 @@ static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {} static void omap_mcpdm_start(struct omap_mcpdm *mcpdm) { u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); + u32 link_mask = mcpdm->config[0].link_mask | mcpdm->config[1].link_mask; ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); - ctrl |= mcpdm->dn_channels | mcpdm->up_channels; + ctrl |= link_mask; omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); @@ -148,11 +149,12 @@ static void omap_mcpdm_start(struct omap_mcpdm *mcpdm) static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm) { u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); + u32 link_mask = mcpdm->config[0].link_mask | mcpdm->config[1].link_mask; ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); - ctrl &= ~(mcpdm->dn_channels | mcpdm->up_channels); + ctrl &= ~(link_mask); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); @@ -188,8 +190,10 @@ static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm) omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset); } - omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, mcpdm->dn_threshold); - omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, mcpdm->up_threshold); + omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, + mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold); + omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, + mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold); omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET, MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE); @@ -296,6 +300,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); int stream = substream->stream; struct omap_pcm_dma_data *dma_data; + u32 threshold; int channels; int link_mask = 0; @@ -325,15 +330,16 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, dma_data = snd_soc_dai_get_dma_data(dai, substream); + threshold = mcpdm->config[stream].threshold; /* Configure McPDM channels, and DMA packet size */ if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - mcpdm->dn_channels = link_mask << 3; + link_mask <<= 3; dma_data->packet_size = - (MCPDM_DN_THRES_MAX - mcpdm->dn_threshold) * channels; + (MCPDM_DN_THRES_MAX - threshold) * channels; } else { - mcpdm->up_channels = link_mask << 0; - dma_data->packet_size = mcpdm->up_threshold * channels; + dma_data->packet_size = threshold * channels; } + mcpdm->config[stream].link_mask = link_mask; return 0; } @@ -380,8 +386,9 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai) } /* Configure McPDM threshold values */ - mcpdm->dn_threshold = 2; - mcpdm->up_threshold = MCPDM_UP_THRES_MAX - 3; + mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold = 2; + mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold = + MCPDM_UP_THRES_MAX - 3; return ret; } -- cgit v1.1 From 81054b226b76145628670a962674ab312690ab86 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 20 Mar 2013 10:47:13 +0100 Subject: ASoC: omap-mcpdm: Fix for full duplex audio use case Due to HW limitation within OMAP McPDM IP uplink and downlink need to be started at the same time. This causes issues when we have two streams running, for example: arecord | aplay In this case the playback stream would have no channels enabled since at the capture start we are not aware that a playback is going to start. The workaround is to configure the other direction to stereo when the first stream is started. When the second stream is coming we check the new stream's number of channels against the pre-configured channels. If it does not match we stop and restart McPDM to update the configuration. This might result a small pop. If the coming stream is a match we do nothing in the McPDM driver. This workaround can handle most use cases without the need to restart McPDM. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcpdm.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'sound/soc/omap/omap-mcpdm.c') diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 6e19f44..cd0e2ec 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -63,6 +63,9 @@ struct omap_mcpdm { /* McPDM dn offsets for rx1, and 2 channels */ u32 dn_rx_offset; + + /* McPDM needs to be restarted due to runtime reconfiguration */ + bool restart; }; /* @@ -149,7 +152,7 @@ static void omap_mcpdm_start(struct omap_mcpdm *mcpdm) static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm) { u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); - u32 link_mask = mcpdm->config[0].link_mask | mcpdm->config[1].link_mask; + u32 link_mask = MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK; ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); @@ -287,6 +290,8 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, if (omap_mcpdm_active(mcpdm)) { omap_mcpdm_stop(mcpdm); omap_mcpdm_close_streams(mcpdm); + mcpdm->config[0].link_mask = 0; + mcpdm->config[1].link_mask = 0; } } @@ -334,11 +339,26 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, /* Configure McPDM channels, and DMA packet size */ if (stream == SNDRV_PCM_STREAM_PLAYBACK) { link_mask <<= 3; + + /* If capture is not running assume a stereo stream to come */ + if (!mcpdm->config[!stream].link_mask) + mcpdm->config[!stream].link_mask = 0x3; + dma_data->packet_size = (MCPDM_DN_THRES_MAX - threshold) * channels; } else { + /* If playback is not running assume a stereo stream to come */ + if (!mcpdm->config[!stream].link_mask) + mcpdm->config[!stream].link_mask = (0x3 << 3); + dma_data->packet_size = threshold * channels; } + + /* Check if we need to restart McPDM with this stream */ + if (mcpdm->config[stream].link_mask && + mcpdm->config[stream].link_mask != link_mask) + mcpdm->restart = true; + mcpdm->config[stream].link_mask = link_mask; return 0; @@ -352,6 +372,11 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream, if (!omap_mcpdm_active(mcpdm)) { omap_mcpdm_start(mcpdm); omap_mcpdm_reg_dump(mcpdm); + } else if (mcpdm->restart) { + omap_mcpdm_stop(mcpdm); + omap_mcpdm_start(mcpdm); + mcpdm->restart = false; + omap_mcpdm_reg_dump(mcpdm); } return 0; -- cgit v1.1 From 167b5b93a4d53f29d4fda55f96116f525b2eb3d6 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 20 Mar 2013 10:47:14 +0100 Subject: ASoC: omap-mcpdm: Remove leftower define for IO address The IO address is no longer hardwired into the driver. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcpdm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound/soc/omap/omap-mcpdm.c') diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index cd0e2ec..e1d3998 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -43,8 +43,6 @@ #include "omap-mcpdm.h" #include "omap-pcm.h" -#define OMAP44XX_MCPDM_L3_BASE 0x49032000 - struct mcpdm_link_config { u32 link_mask; /* channel mask for the direction */ u32 threshold; /* FIFO threshold */ -- cgit v1.1 From 09ae3aaf3cd28422d76b7b78d9491b17330b276a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 3 Apr 2013 11:06:05 +0200 Subject: ASoC: omap: Use common DAI DMA data Use the common DAI DMA data struct for omap, this allows us to use the common helper function to configure the DMA slave config based on the DAI DMA data. For omap-dmic and omap-mcpdm also move the DMA data from a global variable to the driver state struct. Signed-off-by: Lars-Peter Clausen Acked-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcpdm.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'sound/soc/omap/omap-mcpdm.c') diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index e1d3998..49f102a 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -39,9 +39,9 @@ #include #include #include +#include #include "omap-mcpdm.h" -#include "omap-pcm.h" struct mcpdm_link_config { u32 link_mask; /* channel mask for the direction */ @@ -64,19 +64,14 @@ struct omap_mcpdm { /* McPDM needs to be restarted due to runtime reconfiguration */ bool restart; + + struct snd_dmaengine_dai_dma_data dma_data[2]; + unsigned int dma_req[2]; }; /* * Stream DMA parameters */ -static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { - { - .name = "Audio playback", - }, - { - .name = "Audio capture", - }, -}; static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val) { @@ -272,7 +267,7 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, mutex_unlock(&mcpdm->mutex); snd_soc_dai_set_dma_data(dai, substream, - &omap_mcpdm_dai_dma_params[substream->stream]); + &mcpdm->dma_data[substream->stream]); return 0; } @@ -302,7 +297,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, { struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); int stream = substream->stream; - struct omap_pcm_dma_data *dma_data; + struct snd_dmaengine_dai_dma_data *dma_data; u32 threshold; int channels; int link_mask = 0; @@ -342,14 +337,14 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, if (!mcpdm->config[!stream].link_mask) mcpdm->config[!stream].link_mask = 0x3; - dma_data->packet_size = + dma_data->maxburst = (MCPDM_DN_THRES_MAX - threshold) * channels; } else { /* If playback is not running assume a stereo stream to come */ if (!mcpdm->config[!stream].link_mask) mcpdm->config[!stream].link_mask = (0x3 << 3); - dma_data->packet_size = threshold * channels; + dma_data->maxburst = threshold * channels; } /* Check if we need to restart McPDM with this stream */ @@ -475,20 +470,22 @@ static int asoc_mcpdm_probe(struct platform_device *pdev) if (res == NULL) return -ENOMEM; - omap_mcpdm_dai_dma_params[0].port_addr = res->start + MCPDM_REG_DN_DATA; - omap_mcpdm_dai_dma_params[1].port_addr = res->start + MCPDM_REG_UP_DATA; + mcpdm->dma_data[0].addr = res->start + MCPDM_REG_DN_DATA; + mcpdm->dma_data[1].addr = res->start + MCPDM_REG_UP_DATA; res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link"); if (!res) return -ENODEV; - omap_mcpdm_dai_dma_params[0].dma_req = res->start; + mcpdm->dma_req[0] = res->start; + mcpdm->dma_data[0].filter_data = &mcpdm->dma_req[0]; res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link"); if (!res) return -ENODEV; - omap_mcpdm_dai_dma_params[1].dma_req = res->start; + mcpdm->dma_req[1] = res->start; + mcpdm->dma_data[1].filter_data = &mcpdm->dma_req[1]; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); if (res == NULL) -- cgit v1.1