diff mbox

[RFC,01/13] misc: atmel_ssc: add device tree DMA support

Message ID 1372667978-4718-2-git-send-email-richard.genoud@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Richard Genoud July 1, 2013, 8:39 a.m. UTC
The ssc device has to fill the at_dma_slave structure with the
device tree informations.
Doing a of_dma_request_slave_channel()+dma_release_channel() for that
seems wrong (or at least not very clean).

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
---
 drivers/misc/atmel-ssc.c                |   56 +++++++++++++++++++++++++++++++
 include/linux/atmel-ssc.h               |    2 ++
 include/linux/platform_data/dma-atmel.h |    2 ++
 3 files changed, 60 insertions(+)

Comments

Bo Shen July 2, 2013, 3:01 a.m. UTC | #1
Hi Richard,

On 7/1/2013 16:39, Richard Genoud wrote:
> The ssc device has to fill the at_dma_slave structure with the
> device tree informations.
> Doing a of_dma_request_slave_channel()+dma_release_channel() for that
> seems wrong (or at least not very clean).

Please hold on of this, as to the ASoC dmaengine will deal with this. 
So, we not need do it manually.

Now, I am working on it. And will send out the patch soon after testing OK.

> Signed-off-by: Richard Genoud<richard.genoud@gmail.com>
> ---
>   drivers/misc/atmel-ssc.c                |   56 +++++++++++++++++++++++++++++++
>   include/linux/atmel-ssc.h               |    2 ++
>   include/linux/platform_data/dma-atmel.h |    2 ++
>   3 files changed, 60 insertions(+)

Best Regards,
Bo Shen
Richard Genoud July 2, 2013, 8:13 a.m. UTC | #2
2013/7/2 Bo Shen <voice.shen@atmel.com>:
> Hi Richard,
>
>
> On 7/1/2013 16:39, Richard Genoud wrote:
>>
>> The ssc device has to fill the at_dma_slave structure with the
>> device tree informations.
>> Doing a of_dma_request_slave_channel()+dma_release_channel() for that
>> seems wrong (or at least not very clean).
>
>
> Please hold on of this, as to the ASoC dmaengine will deal with this. So, we
> not need do it manually.
>
> Now, I am working on it. And will send out the patch soon after testing OK.
Ok, I stay tuned !

Thanks !

Best regards,
Richard
Bo Shen July 2, 2013, 9:11 a.m. UTC | #3
Hi Richard,

On 7/2/2013 16:13, Richard Genoud wrote:
>> Please hold on of this, as to the ASoC dmaengine will deal with this. So, we
>> >not need do it manually.
>> >
>> >Now, I am working on it. And will send out the patch soon after testing OK.
> Ok, I stay tuned !

I think you can go on working with the two patches I send just now.
[1]: ASoC: atmel_ssc_dai: move set dma data to startup callback
https://patchwork.kernel.org/patch/2811241/

[2]: ASoC: atmel-pcm: use generic dmaengine framework
https://patchwork.kernel.org/patch/2811261/

I use your patches 4 ~ 8 do a quick testing, it works. Please note the 
name of asound.state under /etc in your rootfs should the same with 
atmel,model in patch 6.

> Thanks !
>
> Best regards,
> Richard

Best Regards,
Bo Shen
Richard Genoud July 3, 2013, 12:21 p.m. UTC | #4
2013/7/2 Bo Shen <voice.shen@atmel.com>:
> Hi Richard,
>
>
> On 7/2/2013 16:13, Richard Genoud wrote:
>>>
>>> Please hold on of this, as to the ASoC dmaengine will deal with this. So,
>>> we
>>> >not need do it manually.
>>> >
>>> >Now, I am working on it. And will send out the patch soon after testing
>>> > OK.
>>
>> Ok, I stay tuned !
>
>
> I think you can go on working with the two patches I send just now.
> [1]: ASoC: atmel_ssc_dai: move set dma data to startup callback
> https://patchwork.kernel.org/patch/2811241/
>
> [2]: ASoC: atmel-pcm: use generic dmaengine framework
> https://patchwork.kernel.org/patch/2811261/
>
> I use your patches 4 ~ 8 do a quick testing, it works. Please note the name
> of asound.state under /etc in your rootfs should the same with atmel,model
> in patch 6.

Thanks for testing !
I was just doing the same test, it works with
aplay  -Dplug:default  good_music.wav

but there's a violent hang (kernel stops, no trace) when I try the record :
arecord -v -V stereo -Dplug:default -f cd -t wav -c 2 /tmp/toto.wav
last thing I see is :
dma dma0chan3: atc_control (3)

I'll try to trace that.


Best regards,
Richard.
Richard Genoud July 3, 2013, 3:51 p.m. UTC | #5
2013/7/3 Richard Genoud <richard.genoud@gmail.com>:
> 2013/7/2 Bo Shen <voice.shen@atmel.com>:
>> Hi Richard,
>>
>>
>> On 7/2/2013 16:13, Richard Genoud wrote:
>>>>
>>>> Please hold on of this, as to the ASoC dmaengine will deal with this. So,
>>>> we
>>>> >not need do it manually.
>>>> >
>>>> >Now, I am working on it. And will send out the patch soon after testing
>>>> > OK.
>>>
>>> Ok, I stay tuned !
>>
>>
>> I think you can go on working with the two patches I send just now.
>> [1]: ASoC: atmel_ssc_dai: move set dma data to startup callback
>> https://patchwork.kernel.org/patch/2811241/
>>
>> [2]: ASoC: atmel-pcm: use generic dmaengine framework
>> https://patchwork.kernel.org/patch/2811261/
>>
>> I use your patches 4 ~ 8 do a quick testing, it works. Please note the name
>> of asound.state under /etc in your rootfs should the same with atmel,model
>> in patch 6.
>
> Thanks for testing !
> I was just doing the same test, it works with
> aplay  -Dplug:default  good_music.wav
>
> but there's a violent hang (kernel stops, no trace) when I try the record :
> arecord -v -V stereo -Dplug:default -f cd -t wav -c 2 /tmp/toto.wav
> last thing I see is :
> dma dma0chan3: atc_control (3)
>
> I'll try to trace that.
I think it's DMA related.
the last thing done by the kernel is:
 i2c i2c-0: i2c_outb: 0x34 A
 i2c i2c-0: i2c_outb: 0x0c A
 i2c i2c-0: i2c_outb: 0x5a A
meaning: enable power on, LINE IN, ADC, OSC, on the WM8731
so, after that, data is comming from the codec to the SSC and then is
handled by the DMA.
there must be something nasty on the DMA bus to hang everything like that...

Richard.
Bo Shen July 4, 2013, 1:15 a.m. UTC | #6
Hi Richard,

On 7/3/2013 23:51, Richard Genoud wrote:
>> >but there's a violent hang (kernel stops, no trace) when I try the record :
>> >arecord -v -V stereo -Dplug:default -f cd -t wav -c 2 /tmp/toto.wav
>> >last thing I see is :
>> >dma dma0chan3: atc_control (3)

I don't meet this issue. Playback and recording works well on my side on 
at91sam9g35ek board.

>> >I'll try to trace that.
> I think it's DMA related.
> the last thing done by the kernel is:
>   i2c i2c-0: i2c_outb: 0x34 A
>   i2c i2c-0: i2c_outb: 0x0c A
>   i2c i2c-0: i2c_outb: 0x5a A
> meaning: enable power on, LINE IN, ADC, OSC, on the WM8731
> so, after that, data is comming from the codec to the SSC and then is
> handled by the DMA.
> there must be something nasty on the DMA bus to hang everything like that...

Will you try i2c without DMA support to test this issue?

> Richard.

Best Regards,
Bo Shen
diff mbox

Patch

diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index f7b90661..3afbd82 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -19,7 +19,9 @@ 
 #include <linux/module.h>
 
 #include <linux/of.h>
+#include <linux/of_dma.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/platform_data/dma-atmel.h>
 
 /* Serialize access to ssc_list and user count */
 static DEFINE_SPINLOCK(user_lock);
@@ -127,12 +129,57 @@  static inline const struct atmel_ssc_platform_data * __init
 		platform_get_device_id(pdev)->driver_data;
 }
 
+static int atmel_ssc_get_dma_data(struct device_node *np,
+				  struct at_dma_slave *sdata)
+{
+	struct dma_chan *chan;
+	struct at_dma_slave *rx_data;
+	int err = -1;
+
+	/*
+	 * FIXME: this is clearly not the right way to do it.
+	 * In order to fill struct at_dma_slave with both rx and tx data,
+	 * we request and release both channels.
+	 * Et voila ! We've got all the whole structure !
+	 * upside: it works(R)
+	 * downside: feels wrong, dirty, not optimized...
+	 */
+	chan = of_dma_request_slave_channel(np, "tx");
+	if (!chan)
+		return err;
+
+	if (chan->private)
+		memcpy(sdata, chan->private, sizeof(*sdata));
+	else
+		goto out;
+
+	dma_release_channel(chan);
+
+	chan = of_dma_request_slave_channel(np, "rx");
+	if (!chan)
+		goto out;
+
+	if (chan->private) {
+		rx_data = chan->private;
+		sdata->cfg &= ~(ATC_SRC_PER_MSB(0xff) | ATC_SRC_PER(0xff));
+		sdata->cfg |= ATC_GET_SRC_ID(rx_data->cfg);
+		err = 0;
+	}
+
+out:
+	if (chan)
+		dma_release_channel(chan);
+
+	return err;
+}
+
 static int ssc_probe(struct platform_device *pdev)
 {
 	struct resource *regs;
 	struct ssc_device *ssc;
 	const struct atmel_ssc_platform_data *plat_dat;
 	struct pinctrl *pinctrl;
+	struct device_node *of = pdev->dev.of_node;
 
 	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
 	if (IS_ERR(pinctrl)) {
@@ -166,6 +213,15 @@  static int ssc_probe(struct platform_device *pdev)
 		return -ENXIO;
 	}
 
+	/* populate platform_data from device tree */
+	if (ssc->pdata && ssc->pdata->use_dma && of) {
+		if (atmel_ssc_get_dma_data(of, &ssc->pdata->dma_slave)) {
+			dev_err(&pdev->dev, "could not get DMA\n");
+			return -EINVAL;
+		}
+	}
+	ssc->pdev->dev.platform_data = &ssc->pdata->dma_slave;
+
 	/* disable all interrupts */
 	clk_prepare_enable(ssc->clk);
 	ssc_writel(ssc->regs, IDR, -1);
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index deb0ae5..80c83ee 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -1,12 +1,14 @@ 
 #ifndef __INCLUDE_ATMEL_SSC_H
 #define __INCLUDE_ATMEL_SSC_H
 
+#include <linux/platform_data/dma-atmel.h>
 #include <linux/platform_device.h>
 #include <linux/list.h>
 #include <linux/io.h>
 
 struct atmel_ssc_platform_data {
 	int			use_dma;
+	struct at_dma_slave	dma_slave;
 };
 
 struct ssc_device {
diff --git a/include/linux/platform_data/dma-atmel.h b/include/linux/platform_data/dma-atmel.h
index e95f19c..0d8b9d6 100644
--- a/include/linux/platform_data/dma-atmel.h
+++ b/include/linux/platform_data/dma-atmel.h
@@ -44,11 +44,13 @@  struct at_dma_slave {
 #define		ATC_SRC_H2SEL_SW	(0x0 <<  9)
 #define		ATC_SRC_H2SEL_HW	(0x1 <<  9)
 #define	ATC_SRC_PER_MSB(h)	(ATC_PER_MSB(h) << 10)	/* Channel src rq (most significant bits) */
+#define ATC_GET_SRC_ID(h) ((((h) >> 6) & 0x3U) | ((h) & 0xFU)) /* Retrieve channel src id */
 #define	ATC_DST_REP		(0x1 << 12)	/* Destination Replay Mod */
 #define	ATC_DST_H2SEL		(0x1 << 13)	/* Destination Handshaking Mod */
 #define		ATC_DST_H2SEL_SW	(0x0 << 13)
 #define		ATC_DST_H2SEL_HW	(0x1 << 13)
 #define	ATC_DST_PER_MSB(h)	(ATC_PER_MSB(h) << 14)	/* Channel dst rq (most significant bits) */
+#define ATC_GET_DST_ID(h) ((((h) >> 10) & 0x3U) | (((h) >> 4) & 0xFU)) /* Retrieve channel dst id */
 #define	ATC_SOD			(0x1 << 16)	/* Stop On Done */
 #define	ATC_LOCK_IF		(0x1 << 20)	/* Interface Lock */
 #define	ATC_LOCK_B		(0x1 << 21)	/* AHB Bus Lock */