Skip to contentSkip to conversation

ASoC: dwc: Add device tree support to designware I2S

PATCH Superseded Andrew Jackson 4 participants 15 messages Dec 12, 2014 – Dec 15, 2014

Subsystems (3)

v2 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

v2 cover ASoC: dwc: Add device tree support to designware I2S

From: Andrew Jackson <[email protected]>

This patch set extends the DesignWare I2S driver to provide device tree support and fixes a couple of small faults.

Changes v1->v2
+ Drop negative use count patch [Mark Brown]
+ Remove unnecessary debug print messages [Lars-Peter Clausen]
+ Rewrite iteration as for loop rather than do...while [Mark Brown]
+ Reorder patches to send fixes first [Mark Brown]
+ Simplify device tree code [Mark Brown]
+ Split device tree patch in two [Mark Brown]
+ Expand explanatory comment on channel configuration [Rajeev Kumar]

Arnd: I've not forgotten about updating the spear entries

Andrew Jackson (6):
ASoC: dwc: Remove unnecessary debug messages and tests
ASoC: dwc: Ensure FIFOs are flushed to prevent channel swap
ASoC: dwc: Iterate over all channels
ASoC: dwc: Reorder code in preparation for DT support
ASoC: dwc: Add devicetree support for Designware I2S
ASoC: dwc: Add documentation for I2S DT

 .../devicetree/bindings/sound/designware-i2s.txt   |   32 +++
 sound/soc/dwc/Kconfig                              |    1 +
 sound/soc/dwc/designware_i2s.c                     |  294 ++++++++++++++------
 3 files changed, 248 insertions(+), 79 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/designware-i2s.txt
#1 lore raw

PATCH v2 1/6 ASoC: dwc: Remove unnecessary debug messages and tests

From: Andrew Jackson <[email protected]>

The devm_XXX allocation functions print a message on failure, so additional messages are not required.

---
 sound/soc/dwc/designware_i2s.c |   13 ++-----------
 1 files changed, 2 insertions(+), 11 deletions(-)
sound/soc/dwc/designware_i2s.c +2 -11
index d202c7c..ef771ea 100644
@@ -345,26 +345,17 @@ static int dw_i2s_probe(struct platform_device *pdev)
 	}
 
 	dw_i2s_dai = devm_kzalloc(&pdev->dev, sizeof(*dw_i2s_dai), GFP_KERNEL);
-	if (!dw_i2s_dai) {
-		dev_err(&pdev->dev, "mem allocation failed for dai driver\n");
+	if (!dw_i2s_dai)
 		return -ENOMEM;
-	}
 
 	dw_i2s_dai->ops = &dw_i2s_dai_ops;
 	dw_i2s_dai->suspend = dw_i2s_suspend;
 	dw_i2s_dai->resume = dw_i2s_resume;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "no i2s resource defined\n");
-		return -ENODEV;
-	}
-
 	dev->i2s_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dev->i2s_base)) {
-		dev_err(&pdev->dev, "ioremap fail for i2s_region\n");
+	if (IS_ERR(dev->i2s_base))
 		return PTR_ERR(dev->i2s_base);
-	}
 
 	cap = pdata->cap;
 	dev->capability = cap;
Signature · 1 line
1.7.1
#2 lore raw

Re: [PATCH v2 1/6] ASoC: dwc: Remove unnecessary debug messages and tests

Quoted 2 lines · Andrew Jackson

The devm_XXX allocation functions print a message on failure, so additional messages are not required.

[]

sound/soc/dwc/designware_i2s.c

Quoted 1 line
sound/soc/dwc/designware_i2s.c +0 -0

[]

sound/soc/dwc/designware_i2s.c static int dw_i2s_probe(struct platform_device *pdev) · line 351

Quoted 9 lines
sound/soc/dwc/designware_i2s.c +1 -3
@@ -345,26 +345,17 @@ static int dw_i2s_probe(struct platform_device *pdev)
 	}
 
 	dw_i2s_dai = devm_kzalloc(&pdev->dev, sizeof(*dw_i2s_dai), GFP_KERNEL);
-	if (!dw_i2s_dai) {
-		dev_err(&pdev->dev, "mem allocation failed for dai driver\n");
+	if (!dw_i2s_dai)
 		return -ENOMEM;
-	}

ok.

sound/soc/dwc/designware_i2s.c static int dw_i2s_probe(struct platform_device *pdev) · line 362

Quoted 10 lines
sound/soc/dwc/designware_i2s.c +0 -5
 	dw_i2s_dai->ops = &dw_i2s_dai_ops;
 	dw_i2s_dai->suspend = dw_i2s_suspend;
 	dw_i2s_dai->resume = dw_i2s_resume;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "no i2s resource defined\n");
-		return -ENODEV;
-	}
-

Why delete this?

sound/soc/dwc/designware_i2s.c static int dw_i2s_probe(struct platform_device *pdev) · line 367

Quoted 6 lines
sound/soc/dwc/designware_i2s.c +1 -3
 	dev->i2s_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dev->i2s_base)) {
-		dev_err(&pdev->dev, "ioremap fail for i2s_region\n");
+	if (IS_ERR(dev->i2s_base))
 		return PTR_ERR(dev->i2s_base);
-	}

or this?

#3 lore raw

Re: [PATCH v2 1/6] ASoC: dwc: Remove unnecessary debug messages and tests

On 12/12/2014 10:31 AM, Joe Perches wrote:
[...]

Quoted 9 lines

sound/soc/dwc/designware_i2s.c static int dw_i2s_probe(struct platform_device *pdev) · line 362

Quoted 6 lines
  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
sound/soc/dwc/designware_i2s.c +0 -5
-	if (!res) {
-		dev_err(&pdev->dev, "no i2s resource defined\n");
-		return -ENODEV;
-	}
-

Why delete this?

Quoted 8 lines

sound/soc/dwc/designware_i2s.c static int dw_i2s_probe(struct platform_device *pdev) · line 367

Quoted 6 lines
  	dev->i2s_base = devm_ioremap_resource(&pdev->dev, res);
sound/soc/dwc/designware_i2s.c +1 -3
-	if (IS_ERR(dev->i2s_base)) {
-		dev_err(&pdev->dev, "ioremap fail for i2s_region\n");
+	if (IS_ERR(dev->i2s_base))
  		return PTR_ERR(dev->i2s_base);
-	}

or this?

devm_ioremap_resource both checks if res is NULL and does also its own error reporting. So the code in the driver is redundant.

#4 lore raw

Re: [PATCH v2 1/6] ASoC: dwc: Remove unnecessary debug messages and tests

In reply to Joe Perches
Quoted 22 lines · Joe Perches
Quoted 2 lines · Andrew Jackson

The devm_XXX allocation functions print a message on failure, so additional messages are not required.

[]

sound/soc/dwc/designware_i2s.c

Quoted 1 line
sound/soc/dwc/designware_i2s.c +0 -0

[]

sound/soc/dwc/designware_i2s.c static int dw_i2s_probe(struct platform_device *pdev) · line 351

Quoted 9 lines
sound/soc/dwc/designware_i2s.c +1 -3
@@ -345,26 +345,17 @@ static int dw_i2s_probe(struct platform_device *pdev)
 	}
 
 	dw_i2s_dai = devm_kzalloc(&pdev->dev, sizeof(*dw_i2s_dai), GFP_KERNEL);
-	if (!dw_i2s_dai) {
-		dev_err(&pdev->dev, "mem allocation failed for dai driver\n");
+	if (!dw_i2s_dai)
 		return -ENOMEM;
-	}

ok.

Quoted 4 lines
sound/soc/dwc/designware_i2s.c +0 -0
 	dw_i2s_dai->ops = &dw_i2s_dai_ops;
 	dw_i2s_dai->suspend = dw_i2s_suspend;
 	dw_i2s_dai->resume = dw_i2s_resume;
 
Quoted 8 lines

sound/soc/dwc/designware_i2s.c static int dw_i2s_probe(struct platform_device *pdev) · line 362

Quoted 6 lines
sound/soc/dwc/designware_i2s.c +0 -5
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "no i2s resource defined\n");
-		return -ENODEV;
-	}
-

Why delete this?

Lars-Peter said that it was unnecessary: see <http://lists.infradead.org/pipermail/linux-arm-kernel/2014-December/308416.html>.

Quoted 9 lines

sound/soc/dwc/designware_i2s.c static int dw_i2s_probe(struct platform_device *pdev) · line 367

Quoted 7 lines
sound/soc/dwc/designware_i2s.c +1 -3
 	dev->i2s_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dev->i2s_base)) {
-		dev_err(&pdev->dev, "ioremap fail for i2s_region\n");
+	if (IS_ERR(dev->i2s_base))
 		return PTR_ERR(dev->i2s_base);
-	}

or this?

Ditto

Andrew

#5 lore raw

Re: [PATCH v2 1/6] ASoC: dwc: Remove unnecessary debug messages and tests

Quoted 43 lines · Andrew Jackson
Quoted 22 lines · Joe Perches
Quoted 2 lines · Andrew Jackson

The devm_XXX allocation functions print a message on failure, so additional messages are not required.

[]

sound/soc/dwc/designware_i2s.c

Quoted 1 line
sound/soc/dwc/designware_i2s.c +0 -0

[]

sound/soc/dwc/designware_i2s.c static int dw_i2s_probe(struct platform_device *pdev) · line 351

Quoted 9 lines
sound/soc/dwc/designware_i2s.c +1 -3
@@ -345,26 +345,17 @@ static int dw_i2s_probe(struct platform_device *pdev)
 	}
 
 	dw_i2s_dai = devm_kzalloc(&pdev->dev, sizeof(*dw_i2s_dai), GFP_KERNEL);
-	if (!dw_i2s_dai) {
-		dev_err(&pdev->dev, "mem allocation failed for dai driver\n");
+	if (!dw_i2s_dai)
 		return -ENOMEM;
-	}

ok.

Quoted 4 lines
sound/soc/dwc/designware_i2s.c +0 -0
 	dw_i2s_dai->ops = &dw_i2s_dai_ops;
 	dw_i2s_dai->suspend = dw_i2s_suspend;
 	dw_i2s_dai->resume = dw_i2s_resume;
 
Quoted 8 lines

sound/soc/dwc/designware_i2s.c static int dw_i2s_probe(struct platform_device *pdev) · line 362

Quoted 6 lines
sound/soc/dwc/designware_i2s.c +0 -5
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "no i2s resource defined\n");
-		return -ENODEV;
-	}
-

Why delete this?

Lars-Peter said that it was unnecessary: see <http://lists.infradead.org/pipermail/linux-arm-kernel/2014-December/308416.html>.

Quoted 9 lines

sound/soc/dwc/designware_i2s.c static int dw_i2s_probe(struct platform_device *pdev) · line 367

Quoted 7 lines
sound/soc/dwc/designware_i2s.c +1 -3
 	dev->i2s_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dev->i2s_base)) {
-		dev_err(&pdev->dev, "ioremap fail for i2s_region\n");
+	if (IS_ERR(dev->i2s_base))
 		return PTR_ERR(dev->i2s_base);
-	}

or this?

Quoted 1 line

Ditto

OK, but your commit message doesn't match the changes.

These messages are redundant not what most consider debugging messages (ie: emitted at KERN_DEBUG).

The 2nd one isn't a devm_<foo> function and the last one isn't an allocation.

maintainer
#6 lore raw

Re: [PATCH v2 1/6] ASoC: dwc: Remove unnecessary debug messages and tests

In reply to Andrew Jackson
Quoted 4 lines · Andrew Jackson

From: Andrew Jackson <[email protected]>

The devm_XXX allocation functions print a message on failure, so additional messages are not required.

Applied, thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141212/9a14b0d0/attachment.sig>

#7 lore raw

PATCH v2 2/6 ASoC: dwc: Ensure FIFOs are flushed to prevent channel swap

In reply to Andrew Jackson

From: Andrew Jackson <[email protected]>

If the FIFOs aren't flushed, the left/right channels may be swapped:
this may occur if the FIFOs are not empty when the streams start.

---
 sound/soc/dwc/designware_i2s.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
sound/soc/dwc/designware_i2s.c +2 -0
index ef771ea..b9d6a25 100644
@@ -228,12 +228,14 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
 	i2s_disable_channels(dev, substream->stream);
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		i2s_write_reg(dev->i2s_base, TXFFR, 1);
 		i2s_write_reg(dev->i2s_base, TCR(ch_reg), xfer_resolution);
 		i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
 		irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
 		i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
 		i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
 	} else {
+		i2s_write_reg(dev->i2s_base, RXFFR, 1);
 		i2s_write_reg(dev->i2s_base, RCR(ch_reg), xfer_resolution);
 		i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
 		irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
Signature · 1 line
1.7.1
#8 lore raw

Re: [PATCH v2 2/6] ASoC: dwc: Ensure FIFOs are flushed to prevent channel swap

Quoted 20 lines · Andrew Jackson

From: Andrew Jackson <[email protected]>

If the FIFOs aren't flushed, the left/right channels may be swapped:
this may occur if the FIFOs are not empty when the streams start.

---
  sound/soc/dwc/designware_i2s.c |    2 ++
  1 files changed, 2 insertions(+), 0 deletions(-)
sound/soc/dwc/designware_i2s.c +1 -0
index ef771ea..b9d6a25 100644
@@ -228,12 +228,14 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
  	i2s_disable_channels(dev, substream->stream);
 
  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		i2s_write_reg(dev->i2s_base, TXFFR, 1);

sound/soc/dwc/designware_i2s.c static int dw_i2s_hw_params(struct snd_pcm_substream *substream, · line 241

Quoted 10 lines
sound/soc/dwc/designware_i2s.c +1 -0
  		i2s_write_reg(dev->i2s_base, TCR(ch_reg), xfer_resolution);
  		i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
  		irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
  		i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
  		i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
  	} else {
+		i2s_write_reg(dev->i2s_base, RXFFR, 1);
  		i2s_write_reg(dev->i2s_base, RCR(ch_reg), xfer_resolution);
  		i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
  		irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));

This should probably go into the prepare callback. prepare is for example also called when recovering from a underrun/overrun. Whereas hwparams is only called during initial setup of the stream.

maintainer
#9 lore raw

Re: [PATCH v2 2/6] ASoC: dwc: Ensure FIFOs are flushed to prevent channel swap

Quoted 3 lines · Lars-Peter Clausen

This should probably go into the prepare callback. prepare is for example also called when recovering from a underrun/overrun. Whereas hwparams is only called during initial setup of the stream.

Indeed, that's a better place.

#10 lore raw

Re: [PATCH v2 2/6] ASoC: dwc: Ensure FIFOs are flushed to prevent channel swap

In reply to Lars-Peter Clausen
Quoted 27 lines · Lars-Peter Clausen
Quoted 26 lines · Andrew Jackson

From: Andrew Jackson <[email protected]>

If the FIFOs aren't flushed, the left/right channels may be swapped:
this may occur if the FIFOs are not empty when the streams start.

---
  sound/soc/dwc/designware_i2s.c |    2 ++
  1 files changed, 2 insertions(+), 0 deletions(-)
sound/soc/dwc/designware_i2s.c +2 -0
index ef771ea..b9d6a25 100644
@@ -228,12 +228,14 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
  	i2s_disable_channels(dev, substream->stream);
 
  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		i2s_write_reg(dev->i2s_base, TXFFR, 1);
  		i2s_write_reg(dev->i2s_base, TCR(ch_reg), xfer_resolution);
  		i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
  		irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
  		i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
  		i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
  	} else {
+		i2s_write_reg(dev->i2s_base, RXFFR, 1);
Quoted 8 lines

sound/soc/dwc/designware_i2s.c static int dw_i2s_hw_params(struct snd_pcm_substream *substream, · line 241

Quoted 4 lines
sound/soc/dwc/designware_i2s.c +0 -0
  		i2s_write_reg(dev->i2s_base, RCR(ch_reg), xfer_resolution);
  		i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
  		irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));

This should probably go into the prepare callback. prepare is for example also called when recovering from a underrun/overrun. Whereas hwparams is only called during initial setup of the stream.

That's a good idea: thank you. I'll rework the patch with this in mind.

Andrew

#11 lore raw

PATCH v2 3/6 ASoC: dwc: Iterate over all channels

In reply to Andrew Jackson

From: Andrew Jackson <[email protected]>

The Designware core can be configured with up to four stereo channels. Each stereo channel is individually configured so, when the driver's hw_params call is made, each requested stereo channel has to be programmed.

---
 sound/soc/dwc/designware_i2s.c |   39 ++++++++++++++++++---------------------
 1 files changed, 18 insertions(+), 21 deletions(-)
sound/soc/dwc/designware_i2s.c +18 -21
index b9d6a25..1d26ded 100644
@@ -209,16 +209,9 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
 
 	switch (config->chan_nr) {
 	case EIGHT_CHANNEL_SUPPORT:
-		ch_reg = 3;
-		break;
 	case SIX_CHANNEL_SUPPORT:
-		ch_reg = 2;
-		break;
 	case FOUR_CHANNEL_SUPPORT:
-		ch_reg = 1;
-		break;
 	case TWO_CHANNEL_SUPPORT:
-		ch_reg = 0;
 		break;
 	default:
 		dev_err(dev->dev, "channel not supported\n");
@@ -227,20 +220,24 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
 
 	i2s_disable_channels(dev, substream->stream);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		i2s_write_reg(dev->i2s_base, TXFFR, 1);
-		i2s_write_reg(dev->i2s_base, TCR(ch_reg), xfer_resolution);
-		i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
-		irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
-		i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
-		i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
-	} else {
-		i2s_write_reg(dev->i2s_base, RXFFR, 1);
-		i2s_write_reg(dev->i2s_base, RCR(ch_reg), xfer_resolution);
-		i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
-		irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
-		i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03);
-		i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
+	for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			i2s_write_reg(dev->i2s_base, TXFFR, 1);
+			i2s_write_reg(dev->i2s_base, TCR(ch_reg),
+				      xfer_resolution);
+			i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
+			irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
+			i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
+			i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
+		} else {
+			i2s_write_reg(dev->i2s_base, RXFFR, 1);
+			i2s_write_reg(dev->i2s_base, RCR(ch_reg),
+				      xfer_resolution);
+			i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
+			irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
+			i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03);
+			i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
+		}
 	}
 
 	i2s_write_reg(dev->i2s_base, CCR, ccr);
Signature · 1 line
1.7.1
#12 lore raw

PATCH v2 4/6 ASoC: dwc: Reorder code in preparation for DT support

In reply to Andrew Jackson

From: Andrew Jackson <[email protected]>

Move code that configures the DAI and DMA into a separate function. This reduces the size of the dw_i2s_probe function and will make it easier to add support for device tree to the driver.

---
 sound/soc/dwc/designware_i2s.c |   73 +++++++++++++++++++++------------------
 1 files changed, 39 insertions(+), 34 deletions(-)
sound/soc/dwc/designware_i2s.c +39 -34
index 1d26ded..343f5e7 100644
@@ -323,13 +323,47 @@ static int dw_i2s_resume(struct snd_soc_dai *dai)
 #define dw_i2s_resume	NULL
 #endif
 
+static void dw_configure_dai_by_pd(struct dw_i2s_dev *dev,
+				   struct snd_soc_dai_driver *dw_i2s_dai,
+				   struct resource *res,
+				   const struct i2s_platform_data *pdata)
+{
+	/* Set DMA slaves info */
+
+	dev->play_dma_data.data = pdata->play_dma_data;
+	dev->capture_dma_data.data = pdata->capture_dma_data;
+	dev->play_dma_data.addr = res->start + I2S_TXDMA;
+	dev->capture_dma_data.addr = res->start + I2S_RXDMA;
+	dev->play_dma_data.max_burst = 16;
+	dev->capture_dma_data.max_burst = 16;
+	dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	dev->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	dev->play_dma_data.filter = pdata->filter;
+	dev->capture_dma_data.filter = pdata->filter;
+
+	if (pdata->cap & DWC_I2S_PLAY) {
+		dev_dbg(dev->dev, " designware: play supported\n");
+		dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM;
+		dw_i2s_dai->playback.channels_max = pdata->channel;
+		dw_i2s_dai->playback.formats = pdata->snd_fmts;
+		dw_i2s_dai->playback.rates = pdata->snd_rates;
+	}
+
+	if (pdata->cap & DWC_I2S_RECORD) {
+		dev_dbg(dev->dev, "designware: record supported\n");
+		dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM;
+		dw_i2s_dai->capture.channels_max = pdata->channel;
+		dw_i2s_dai->capture.formats = pdata->snd_fmts;
+		dw_i2s_dai->capture.rates = pdata->snd_rates;
+	}
+}
+
 static int dw_i2s_probe(struct platform_device *pdev)
 {
 	const struct i2s_platform_data *pdata = pdev->dev.platform_data;
 	struct dw_i2s_dev *dev;
 	struct resource *res;
 	int ret;
-	unsigned int cap;
 	struct snd_soc_dai_driver *dw_i2s_dai;
 
 	if (!pdata) {
@@ -356,23 +390,11 @@ static int dw_i2s_probe(struct platform_device *pdev)
 	if (IS_ERR(dev->i2s_base))
 		return PTR_ERR(dev->i2s_base);
 
-	cap = pdata->cap;
-	dev->capability = cap;
-	dev->i2s_clk_cfg = pdata->i2s_clk_cfg;
-
-	/* Set DMA slaves info */
-
-	dev->play_dma_data.data = pdata->play_dma_data;
-	dev->capture_dma_data.data = pdata->capture_dma_data;
-	dev->play_dma_data.addr = res->start + I2S_TXDMA;
-	dev->capture_dma_data.addr = res->start + I2S_RXDMA;
-	dev->play_dma_data.max_burst = 16;
-	dev->capture_dma_data.max_burst = 16;
-	dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
-	dev->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
-	dev->play_dma_data.filter = pdata->filter;
-	dev->capture_dma_data.filter = pdata->filter;
+	dev->dev = &pdev->dev;
+	dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata);
 
+	dev->capability = pdata->cap;
+	dev->i2s_clk_cfg = pdata->i2s_clk_cfg;
 	dev->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dev->clk))
 		return  PTR_ERR(dev->clk);
@@ -381,23 +403,6 @@ static int dw_i2s_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto err_clk_put;
 
-	if (cap & DWC_I2S_PLAY) {
-		dev_dbg(&pdev->dev, " designware: play supported\n");
-		dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM;
-		dw_i2s_dai->playback.channels_max = pdata->channel;
-		dw_i2s_dai->playback.formats = pdata->snd_fmts;
-		dw_i2s_dai->playback.rates = pdata->snd_rates;
-	}
-
-	if (cap & DWC_I2S_RECORD) {
-		dev_dbg(&pdev->dev, "designware: record supported\n");
-		dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM;
-		dw_i2s_dai->capture.channels_max = pdata->channel;
-		dw_i2s_dai->capture.formats = pdata->snd_fmts;
-		dw_i2s_dai->capture.rates = pdata->snd_rates;
-	}
-
-	dev->dev = &pdev->dev;
 	dev_set_drvdata(&pdev->dev, dev);
 	ret = snd_soc_register_component(&pdev->dev, &dw_i2s_component,
 					 dw_i2s_dai, 1);
Signature · 1 line
1.7.1
#13 lore raw

PATCH v2 5/6 ASoC: dwc: Add devicetree support for Designware I2S

In reply to Andrew Jackson

From: Andrew Jackson <[email protected]>

Allow the driver to be configured through a device tree rather than platform data. When using device-tree, read the I2S block's configuration from the relevant registers: this reduces the amount of information required in the device tree.

---
 sound/soc/dwc/Kconfig          |    1 +
 sound/soc/dwc/designware_i2s.c |  199 ++++++++++++++++++++++++++++++++++------
 2 files changed, 171 insertions(+), 29 deletions(-)
sound/soc/dwc/Kconfig +1 -0
index e334900..d50e085 100644
@@ -1,6 +1,7 @@
 config SND_DESIGNWARE_I2S
 	tristate "Synopsys I2S Device Driver"
 	depends on CLKDEV_LOOKUP
+	select SND_SOC_GENERIC_DMAENGINE_PCM
 	help
 	 Say Y or M if you want to add support for I2S driver for
 	 Synopsys desigwnware I2S device. The device supports upto
sound/soc/dwc/designware_i2s.c +170 -29

283 lines not on this page · raw message

Signature · 1 line
1.7.1
#14 lore raw

PATCH v2 6/6 ASoC: dwc: Add documentation for I2S DT

In reply to Andrew Jackson

From: Andrew Jackson <[email protected]>

Add documentation for Designware I2S hardware block. The block requires two clocks (one for audio sampling, the other for APB) and DMA channels for receive and transmit.

---
 .../devicetree/bindings/sound/designware-i2s.txt   |   32 ++++++++++++++++++++
 1 files changed, 32 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/designware-i2s.txt
Documentation/devicetree/bindings/sound/designware-i2s.txt new file +32 -0
new file mode 100644
index 0000000..cdee591
@@ -0,0 +1,32 @@
+DesignWare I2S controller
+
+Required properties:
+ - compatible : Must be "snps,designware-i2s"
+ - reg : Must contain I2S core's registers location and length
+ - clocks : Pairs of phandle and specifier referencing the controller's clocks.
+   The controller expects two clocks, the clock used for the APB interface and
+   the clock used as the sampling rate reference clock sample.
+ - clock-names : "apb_plck" for the clock to the APB interface, "i2sclk" for the sample
+   rate reference clock.
+ - dmas: Pairs of phandle and specifier for the DMA channels that are used by
+   the core. The core expects one or two dma channels, one for transmit and one for
+   receive.
+ - dma-names : "tx" for the transmit channel, "rx" for the receive channel.
+
+For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
+please check:
+	* resource-names.txt
+	* clock/clock-bindings.txt
+	* dma/dma.txt
+
+Example:
+
+	soc_i2s: i2s@7ff90000 {
+		compatible = "snps,designware-i2s";
+		reg = <0x0 0x7ff90000 0x0 0x1000>;
+		clocks = <&scpi_i2sclk 0>, <&soc_refclk100mhz>;
+		clock-names = "i2sclk", "apb_pclk";
+		#sound-dai-cells = <0>;
+		dmas = <&dma0 5>;
+		dma-names = "tx";
+	};
Signature · 1 line
1.7.1