All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Adding idma driver for samsung SoCs
@ 2011-06-09  8:09 Sangbeom Kim
  2011-06-09  8:09 ` [PATCH 1/4] ASoC: SAMSUNG: Modify I2S driver to support idma Sangbeom Kim
                   ` (3 more replies)
  0 siblings, 4 replies; 26+ messages in thread
From: Sangbeom Kim @ 2011-06-09  8:09 UTC (permalink / raw)
  To: alsa-devel, linux-samsung-soc
  Cc: jassisinghbrar, lrg, broonie, kgene.kim, ben-linux


I2S in samsung audio subsytem has a small internal dma(idma).
IDMA can be used in low power audio mode and I2S0 secondary fifo
data tranfer.
In this patchsets, idma driver is added.
This patch is tested on SMDKV310, Nexus-s(S5PC110) with
lakkyung jung (lakkyung.jung@samsung.com)

This patchset contains followings

 o To Jassi Brar, Mark Brown and Liam Girdwood,
[PATCH 1/4] ASoC: SAMSUNG: Modify I2S driver to support idma
[PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver
[PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs

 o To Kukjin Kim and Ben Dooks,
[PATCH 4/4] ARM: SAMSUNG: Add platform device for idma

Best Regards,
SB Kim

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 1/4] ASoC: SAMSUNG: Modify I2S driver to support idma
  2011-06-09  8:09 [PATCH 0/4] Adding idma driver for samsung SoCs Sangbeom Kim
@ 2011-06-09  8:09 ` Sangbeom Kim
  2011-06-10 11:31   ` Jassi Brar
  2011-06-09  8:09 ` [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver Sangbeom Kim
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 26+ messages in thread
From: Sangbeom Kim @ 2011-06-09  8:09 UTC (permalink / raw)
  To: alsa-devel, linux-samsung-soc
  Cc: jassisinghbrar, lrg, broonie, kgene.kim, ben-linux, Sangbeom Kim

Previously, I2S driver only can support system dma.
In this patch, i2s driver can support internal dma too.
To share register definition, register definition is moved
to i2s.h and added some register to support idma.

Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>
---
 sound/soc/samsung/i2s.c |  126 ++++++++--------------------------------------
 sound/soc/samsung/i2s.h |  130 ++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 150 insertions(+), 106 deletions(-)

diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index ffa09b3..404f4c2 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -21,113 +21,9 @@
 #include <plat/audio.h>
 
 #include "dma.h"
+#include "idma.h"
 #include "i2s.h"
 
-#define I2SCON		0x0
-#define I2SMOD		0x4
-#define I2SFIC		0x8
-#define I2SPSR		0xc
-#define I2STXD		0x10
-#define I2SRXD		0x14
-#define I2SFICS		0x18
-#define I2STXDS		0x1c
-
-#define CON_RSTCLR		(1 << 31)
-#define CON_FRXOFSTATUS		(1 << 26)
-#define CON_FRXORINTEN		(1 << 25)
-#define CON_FTXSURSTAT		(1 << 24)
-#define CON_FTXSURINTEN		(1 << 23)
-#define CON_TXSDMA_PAUSE	(1 << 20)
-#define CON_TXSDMA_ACTIVE	(1 << 18)
-
-#define CON_FTXURSTATUS		(1 << 17)
-#define CON_FTXURINTEN		(1 << 16)
-#define CON_TXFIFO2_EMPTY	(1 << 15)
-#define CON_TXFIFO1_EMPTY	(1 << 14)
-#define CON_TXFIFO2_FULL	(1 << 13)
-#define CON_TXFIFO1_FULL	(1 << 12)
-
-#define CON_LRINDEX		(1 << 11)
-#define CON_TXFIFO_EMPTY	(1 << 10)
-#define CON_RXFIFO_EMPTY	(1 << 9)
-#define CON_TXFIFO_FULL		(1 << 8)
-#define CON_RXFIFO_FULL		(1 << 7)
-#define CON_TXDMA_PAUSE		(1 << 6)
-#define CON_RXDMA_PAUSE		(1 << 5)
-#define CON_TXCH_PAUSE		(1 << 4)
-#define CON_RXCH_PAUSE		(1 << 3)
-#define CON_TXDMA_ACTIVE	(1 << 2)
-#define CON_RXDMA_ACTIVE	(1 << 1)
-#define CON_ACTIVE		(1 << 0)
-
-#define MOD_OPCLK_CDCLK_OUT	(0 << 30)
-#define MOD_OPCLK_CDCLK_IN	(1 << 30)
-#define MOD_OPCLK_BCLK_OUT	(2 << 30)
-#define MOD_OPCLK_PCLK		(3 << 30)
-#define MOD_OPCLK_MASK		(3 << 30)
-#define MOD_TXS_IDMA		(1 << 28) /* Sec_TXFIFO use I-DMA */
-
-#define MOD_BLCS_SHIFT	26
-#define MOD_BLCS_16BIT	(0 << MOD_BLCS_SHIFT)
-#define MOD_BLCS_8BIT	(1 << MOD_BLCS_SHIFT)
-#define MOD_BLCS_24BIT	(2 << MOD_BLCS_SHIFT)
-#define MOD_BLCS_MASK	(3 << MOD_BLCS_SHIFT)
-#define MOD_BLCP_SHIFT	24
-#define MOD_BLCP_16BIT	(0 << MOD_BLCP_SHIFT)
-#define MOD_BLCP_8BIT	(1 << MOD_BLCP_SHIFT)
-#define MOD_BLCP_24BIT	(2 << MOD_BLCP_SHIFT)
-#define MOD_BLCP_MASK	(3 << MOD_BLCP_SHIFT)
-
-#define MOD_C2DD_HHALF		(1 << 21) /* Discard Higher-half */
-#define MOD_C2DD_LHALF		(1 << 20) /* Discard Lower-half */
-#define MOD_C1DD_HHALF		(1 << 19)
-#define MOD_C1DD_LHALF		(1 << 18)
-#define MOD_DC2_EN		(1 << 17)
-#define MOD_DC1_EN		(1 << 16)
-#define MOD_BLC_16BIT		(0 << 13)
-#define MOD_BLC_8BIT		(1 << 13)
-#define MOD_BLC_24BIT		(2 << 13)
-#define MOD_BLC_MASK		(3 << 13)
-
-#define MOD_IMS_SYSMUX		(1 << 10)
-#define MOD_SLAVE		(1 << 11)
-#define MOD_TXONLY		(0 << 8)
-#define MOD_RXONLY		(1 << 8)
-#define MOD_TXRX		(2 << 8)
-#define MOD_MASK		(3 << 8)
-#define MOD_LR_LLOW		(0 << 7)
-#define MOD_LR_RLOW		(1 << 7)
-#define MOD_SDF_IIS		(0 << 5)
-#define MOD_SDF_MSB		(1 << 5)
-#define MOD_SDF_LSB		(2 << 5)
-#define MOD_SDF_MASK		(3 << 5)
-#define MOD_RCLK_256FS		(0 << 3)
-#define MOD_RCLK_512FS		(1 << 3)
-#define MOD_RCLK_384FS		(2 << 3)
-#define MOD_RCLK_768FS		(3 << 3)
-#define MOD_RCLK_MASK		(3 << 3)
-#define MOD_BCLK_32FS		(0 << 1)
-#define MOD_BCLK_48FS		(1 << 1)
-#define MOD_BCLK_16FS		(2 << 1)
-#define MOD_BCLK_24FS		(3 << 1)
-#define MOD_BCLK_MASK		(3 << 1)
-#define MOD_8BIT		(1 << 0)
-
-#define MOD_CDCLKCON		(1 << 12)
-
-#define PSR_PSREN		(1 << 15)
-
-#define FIC_TX2COUNT(x)		(((x) >>  24) & 0xf)
-#define FIC_TX1COUNT(x)		(((x) >>  16) & 0xf)
-
-#define FIC_TXFLUSH		(1 << 15)
-#define FIC_RXFLUSH		(1 << 7)
-#define FIC_TXCOUNT(x)		(((x) >>  8) & 0xf)
-#define FIC_RXCOUNT(x)		(((x) >>  0) & 0xf)
-#define FICS_TXCOUNT(x)		(((x) >>  8) & 0x7f)
-
-#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
-
 struct i2s_dai {
 	/* Platform device for this DAI */
 	struct platform_device *pdev;
@@ -646,6 +542,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
 {
 	struct i2s_dai *i2s = to_info(dai);
 	u32 mod = readl(i2s->addr + I2SMOD);
+	u32 ahb = readl(i2s->addr + I2SAHB);
 
 	if (!is_secondary(i2s))
 		mod &= ~(MOD_DC2_EN | MOD_DC1_EN);
@@ -657,6 +554,16 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
 		mod |= MOD_DC1_EN;
 		break;
 	case 2:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			i2s->dma_playback.dma_size = 4;
+		else
+			i2s->dma_capture.dma_size = 4;
+		break;
+	case 1:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			i2s->dma_playback.dma_size = 2;
+		else
+			i2s->dma_capture.dma_size = 2;
 		break;
 	default:
 		dev_err(&i2s->pdev->dev, "%d channels not supported\n",
@@ -702,6 +609,13 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
 				params_format(params));
 		return -EINVAL;
 	}
+
+	if (is_secondary(i2s)) {
+		ahb |= (AHB_DMARLD | AHB_INTMASK);
+		mod |= MOD_TXS_IDMA;
+	}
+
+	writel(ahb, i2s->addr + I2SAHB);
 	writel(mod, i2s->addr + I2SMOD);
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -979,6 +893,8 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
 	if (i2s->quirks & QUIRK_NEED_RSTCLR)
 		writel(CON_RSTCLR, i2s->addr + I2SCON);
 
+	idma_init((void *)i2s->addr);
+
 probe_exit:
 	/* Reset any constraint on RFS and BFS */
 	i2s->rfs = 0;
diff --git a/sound/soc/samsung/i2s.h b/sound/soc/samsung/i2s.h
index 8e15f6a..7f8aa61 100644
--- a/sound/soc/samsung/i2s.h
+++ b/sound/soc/samsung/i2s.h
@@ -24,6 +24,134 @@
 
 #define SAMSUNG_I2S_RCLKSRC_0	0
 #define SAMSUNG_I2S_RCLKSRC_1	1
-#define SAMSUNG_I2S_CDCLK		2
+#define SAMSUNG_I2S_CDCLK	2
+
+#define I2SCON			0x0
+#define I2SMOD			0x4
+#define I2SFIC			0x8
+#define I2SPSR			0xc
+#define I2STXD			0x10
+#define I2SRXD			0x14
+#define I2SFICS			0x18
+#define I2STXDS			0x1c
+#define I2SAHB			0x20
+#define I2SSTR0			0x24
+#define I2SSIZE			0x28
+#define I2STRNCNT		0x2c
+#define I2SLVL0ADDR		0x30
+#define I2SLVL1ADDR		0x34
+#define I2SLVL2ADDR		0x38
+#define I2SLVL3ADDR		0x3c
+
+#define CON_RSTCLR		(1 << 31)
+#define CON_FRXOFSTATUS		(1 << 26)
+#define CON_FRXORINTEN		(1 << 25)
+#define CON_FTXSURSTAT		(1 << 24)
+#define CON_FTXSURINTEN		(1 << 23)
+#define CON_TXSDMA_PAUSE	(1 << 20)
+#define CON_TXSDMA_ACTIVE	(1 << 18)
+
+#define CON_FTXURSTATUS		(1 << 17)
+#define CON_FTXURINTEN		(1 << 16)
+#define CON_TXFIFO2_EMPTY	(1 << 15)
+#define CON_TXFIFO1_EMPTY	(1 << 14)
+#define CON_TXFIFO2_FULL	(1 << 13)
+#define CON_TXFIFO1_FULL	(1 << 12)
+
+#define CON_LRINDEX		(1 << 11)
+#define CON_TXFIFO_EMPTY	(1 << 10)
+#define CON_RXFIFO_EMPTY	(1 << 9)
+#define CON_TXFIFO_FULL		(1 << 8)
+#define CON_RXFIFO_FULL		(1 << 7)
+#define CON_TXDMA_PAUSE		(1 << 6)
+#define CON_RXDMA_PAUSE		(1 << 5)
+#define CON_TXCH_PAUSE		(1 << 4)
+#define CON_RXCH_PAUSE		(1 << 3)
+#define CON_TXDMA_ACTIVE	(1 << 2)
+#define CON_RXDMA_ACTIVE	(1 << 1)
+#define CON_ACTIVE		(1 << 0)
+
+#define MOD_OPCLK_CDCLK_OUT	(0 << 30)
+#define MOD_OPCLK_CDCLK_IN	(1 << 30)
+#define MOD_OPCLK_BCLK_OUT	(2 << 30)
+#define MOD_OPCLK_PCLK		(3 << 30)
+#define MOD_OPCLK_MASK		(3 << 30)
+#define MOD_TXS_IDMA		(1 << 28)
+
+#define MOD_BLCS_SHIFT		26
+#define MOD_BLCS_16BIT		(0 << MOD_BLCS_SHIFT)
+#define MOD_BLCS_8BIT		(1 << MOD_BLCS_SHIFT)
+#define MOD_BLCS_24BIT		(2 << MOD_BLCS_SHIFT)
+#define MOD_BLCS_MASK		(3 << MOD_BLCS_SHIFT)
+#define MOD_BLCP_SHIFT		24
+#define MOD_BLCP_16BIT		(0 << MOD_BLCP_SHIFT)
+#define MOD_BLCP_8BIT		(1 << MOD_BLCP_SHIFT)
+#define MOD_BLCP_24BIT		(2 << MOD_BLCP_SHIFT)
+#define MOD_BLCP_MASK		(3 << MOD_BLCP_SHIFT)
+
+#define MOD_C2DD_HHALF		(1 << 21) /* Discard Higher-half */
+#define MOD_C2DD_LHALF		(1 << 20) /* Discard Lower-half */
+#define MOD_C1DD_HHALF		(1 << 19)
+#define MOD_C1DD_LHALF		(1 << 18)
+#define MOD_DC2_EN		(1 << 17)
+#define MOD_DC1_EN		(1 << 16)
+#define MOD_BLC_16BIT		(0 << 13)
+#define MOD_BLC_8BIT		(1 << 13)
+#define MOD_BLC_24BIT		(2 << 13)
+#define MOD_BLC_MASK		(3 << 13)
+
+#define MOD_IMS_SYSMUX		(1 << 10)
+#define MOD_SLAVE		(1 << 11)
+#define MOD_TXONLY		(0 << 8)
+#define MOD_RXONLY		(1 << 8)
+#define MOD_TXRX		(2 << 8)
+#define MOD_MASK		(3 << 8)
+#define MOD_LR_LLOW		(0 << 7)
+#define MOD_LR_RLOW		(1 << 7)
+#define MOD_SDF_IIS		(0 << 5)
+#define MOD_SDF_MSB		(1 << 5)
+#define MOD_SDF_LSB		(2 << 5)
+#define MOD_SDF_MASK		(3 << 5)
+#define MOD_RCLK_256FS		(0 << 3)
+#define MOD_RCLK_512FS		(1 << 3)
+#define MOD_RCLK_384FS		(2 << 3)
+#define MOD_RCLK_768FS		(3 << 3)
+#define MOD_RCLK_MASK		(3 << 3)
+#define MOD_BCLK_32FS		(0 << 1)
+#define MOD_BCLK_48FS		(1 << 1)
+#define MOD_BCLK_16FS		(2 << 1)
+#define MOD_BCLK_24FS		(3 << 1)
+#define MOD_BCLK_MASK		(3 << 1)
+#define MOD_8BIT		(1 << 0)
+
+#define MOD_CDCLKCON		(1 << 12)
+
+#define PSR_PSREN		(1 << 15)
+
+#define FIC_TX2COUNT(x)		(((x) >>  24) & 0xf)
+#define FIC_TX1COUNT(x)		(((x) >>  16) & 0xf)
+
+#define FIC_TXFLUSH		(1 << 15)
+#define FIC_RXFLUSH		(1 << 7)
+
+#define FIC_TXCOUNT(x)		(((x) >>  8) & 0x7f)
+#define FIC_RXCOUNT(x)		(((x) >>  0) & 0x7f)
+#define FICS_TXCOUNT(x)		(((x) >>  8) & 0x7f)
+
+#define AHB_INTENLVL0		(1 << 24)
+#define AHB_LVL0INT		(1 << 20)
+#define AHB_CLRLVL0INT		(1 << 16)
+#define AHB_DMARLD		(1 << 5)
+#define AHB_INTMASK		(1 << 3)
+#define AHB_DMAEN		(1 << 0)
+#define AHB_LVLINTMASK		(0xf << 20)
+
+#define I2SSIZE_TRNMSK		(0xffff)
+#define I2SSIZE_SHIFT		(16)
+
+#define msecs_to_loops(t)	(loops_per_jiffy / 1000 * HZ * t)
+
+#define ST_RUNNING		(1<<0)
+#define ST_OPENED		(1<<1)
 
 #endif /* __SND_SOC_SAMSUNG_I2S_H */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver
  2011-06-09  8:09 [PATCH 0/4] Adding idma driver for samsung SoCs Sangbeom Kim
  2011-06-09  8:09 ` [PATCH 1/4] ASoC: SAMSUNG: Modify I2S driver to support idma Sangbeom Kim
@ 2011-06-09  8:09 ` Sangbeom Kim
  2011-06-09  9:50   ` Liam Girdwood
                     ` (2 more replies)
  2011-06-09  8:09 ` [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs Sangbeom Kim
  2011-06-09  8:09 ` [PATCH 4/4] ARM: SAMSUNG: Add platform device for idma Sangbeom Kim
  3 siblings, 3 replies; 26+ messages in thread
From: Sangbeom Kim @ 2011-06-09  8:09 UTC (permalink / raw)
  To: alsa-devel, linux-samsung-soc
  Cc: jassisinghbrar, lrg, broonie, kgene.kim, ben-linux, Sangbeom Kim

I2S in Exynos4 and S5PC110(S5PV210) has a internal dma.
It can be used low power audio mode and 2nd channel transfer.

Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>
---
 sound/soc/samsung/Makefile |    2 +
 sound/soc/samsung/idma.c   |  492 ++++++++++++++++++++++++++++++++++++++++++++
 sound/soc/samsung/idma.h   |   28 +++
 3 files changed, 522 insertions(+), 0 deletions(-)
 create mode 100644 sound/soc/samsung/idma.c
 create mode 100644 sound/soc/samsung/idma.h

diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
index 683843a..2b9e251 100644
--- a/sound/soc/samsung/Makefile
+++ b/sound/soc/samsung/Makefile
@@ -1,5 +1,6 @@
 # S3c24XX Platform Support
 snd-soc-s3c24xx-objs := dma.o
+snd-soc-idma-objs := idma.o
 snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
 snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
 snd-soc-ac97-objs := ac97.o
@@ -16,6 +17,7 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
 obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o
 obj-$(CONFIG_SND_SAMSUNG_PCM) += snd-soc-pcm.o
 obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o
+obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-idma.o
 
 # S3C24XX Machine Support
 snd-soc-jive-wm8750-objs := jive_wm8750.o
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
new file mode 100644
index 0000000..ae19546
--- /dev/null
+++ b/sound/soc/samsung/idma.c
@@ -0,0 +1,492 @@
+/*
+ * linux/sound/soc/samsung/idma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * I2S0's Internal DMA driver
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "i2s.h"
+#include "idma.h"
+#include "dma.h"
+
+static const struct snd_pcm_hardware idma_hardware = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED |
+		    SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		    SNDRV_PCM_INFO_MMAP |
+		    SNDRV_PCM_INFO_MMAP_VALID |
+		    SNDRV_PCM_INFO_PAUSE |
+		    SNDRV_PCM_INFO_RESUME,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE |
+		    SNDRV_PCM_FMTBIT_U16_LE |
+		    SNDRV_PCM_FMTBIT_S24_LE |
+		    SNDRV_PCM_FMTBIT_U24_LE |
+		    SNDRV_PCM_FMTBIT_U8 |
+		    SNDRV_PCM_FMTBIT_S8,
+	.channels_min = 2,
+	.channels_max = 2,
+	.buffer_bytes_max = 128 * 1024,
+	.period_bytes_min = 128,
+	.period_bytes_max = PAGE_SIZE*2,
+	.periods_min = 1,
+	.periods_max = 4,
+};
+
+struct idma_ctrl {
+	spinlock_t	lock;
+	int		state;
+	dma_addr_t	start;
+	dma_addr_t	pos;
+	dma_addr_t	end;
+	dma_addr_t	period;
+	dma_addr_t	periodsz;
+	void		*token;
+	void		(*cb)(void *dt, int bytes_xfer);
+};
+
+static struct idma_info {
+	spinlock_t	lock;
+	void		 __iomem  *regs;
+	int		trigger_stat;
+} idma;
+
+static void idma_getpos(dma_addr_t *src)
+{
+	*src = LP_TXBUFF_ADDR +
+		(readl(idma.regs + I2STRNCNT) & 0xffffff) * 4;
+}
+
+void i2sdma_getpos(dma_addr_t *src)
+{
+	if (idma.trigger_stat == LPAM_DMA_START)
+		*src = LP_TXBUFF_ADDR +
+			(readl(idma.regs + I2STRNCNT) & 0xffffff) * 4;
+	else
+		*src = LP_TXBUFF_ADDR;
+}
+
+static int idma_enqueue(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct idma_ctrl *prtd = substream->runtime->private_data;
+	u32 val;
+
+	spin_lock(&prtd->lock);
+	prtd->token = (void *) substream;
+	spin_unlock(&prtd->lock);
+
+	/* Internal DMA Level0 Interrupt Address */
+	val = LP_TXBUFF_ADDR + prtd->periodsz;
+	writel(val, idma.regs + I2SLVL0ADDR);
+
+	/* Start address0 of I2S internal DMA operation. */
+	val = readl(idma.regs + I2SSTR0);
+	val = LP_TXBUFF_ADDR;
+	writel(val, idma.regs + I2SSTR0);
+
+	/*
+	 * Transfer block size for I2S internal DMA.
+	 * Should decide transfer size before start dma operation
+	 */
+	val = readl(idma.regs + I2SSIZE);
+	val &= ~(I2SSIZE_TRNMSK << I2SSIZE_SHIFT);
+
+	val |= (((runtime->dma_bytes >> 2) &
+			I2SSIZE_TRNMSK) << I2SSIZE_SHIFT);
+	writel(val, idma.regs + I2SSIZE);
+
+	return 0;
+}
+
+static void idma_setcallbk(struct snd_pcm_substream *substream,
+				void (*cb)(void *, int))
+{
+	struct idma_ctrl *prtd = substream->runtime->private_data;
+
+	spin_lock(&prtd->lock);
+	prtd->cb = cb;
+	spin_unlock(&prtd->lock);
+
+	pr_debug("%s:%d dma_period=%x\n", __func__, __LINE__, prtd->periodsz);
+}
+
+static void idma_ctrl(int op)
+{
+	u32 val = readl(idma.regs + I2SAHB);
+
+	spin_lock(&idma.lock);
+
+	switch (op) {
+	case LPAM_DMA_START:
+		val |= (AHB_INTENLVL0 | AHB_DMAEN);
+		break;
+	case LPAM_DMA_STOP:
+		val &= ~(AHB_INTENLVL0 | AHB_DMAEN);
+		break;
+	default:
+		return;
+	}
+
+	writel(val, idma.regs + I2SAHB);
+	spin_unlock(&idma.lock);
+}
+
+static void idma_done(void *id, int bytes_xfer)
+{
+	struct snd_pcm_substream *substream = id;
+	struct idma_ctrl *prtd = substream->runtime->private_data;
+
+	if (prtd && (prtd->state & ST_RUNNING))
+		snd_pcm_period_elapsed(substream);
+}
+
+static int idma_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct idma_ctrl *prtd = substream->runtime->private_data;
+
+	pr_debug("Entered %s\n", __func__);
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+	runtime->dma_bytes = params_buffer_bytes(params);
+	memset(runtime->dma_area, 0, runtime->dma_bytes);
+
+	prtd->start = prtd->pos = runtime->dma_addr;
+	prtd->period = params_periods(params);
+	prtd->periodsz = params_period_bytes(params);
+	prtd->end = LP_TXBUFF_ADDR + runtime->dma_bytes;
+
+	idma_setcallbk(substream, idma_done);
+
+	pr_debug("DmaAddr=@%x Total=%dbytes PrdSz=%d #Prds=%d dma_area=0x%x\n",
+			prtd->start, runtime->dma_bytes, prtd->periodsz,
+			prtd->period, (unsigned int)runtime->dma_area);
+
+	return 0;
+}
+
+static int idma_hw_free(struct snd_pcm_substream *substream)
+{
+	pr_debug("Entered %s\n", __func__);
+
+	snd_pcm_set_runtime_buffer(substream, NULL);
+
+	return 0;
+}
+
+static int idma_prepare(struct snd_pcm_substream *substream)
+{
+	struct idma_ctrl *prtd = substream->runtime->private_data;
+
+	pr_debug("Entered %s\n", __func__);
+
+	prtd->pos = prtd->start;
+
+	/* flush the DMA channel */
+	idma_ctrl(LPAM_DMA_STOP);
+	idma_enqueue(substream);
+
+	return 0;
+}
+
+static int idma_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct idma_ctrl *prtd = substream->runtime->private_data;
+	int ret = 0;
+
+	pr_debug("Entered %s\n", __func__);
+
+	spin_lock(&prtd->lock);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		prtd->state |= ST_RUNNING;
+		idma.trigger_stat = LPAM_DMA_START;
+		idma_ctrl(LPAM_DMA_START);
+		break;
+
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		prtd->state &= ~ST_RUNNING;
+		idma.trigger_stat = LPAM_DMA_STOP;
+		idma_ctrl(LPAM_DMA_STOP);
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	spin_unlock(&prtd->lock);
+
+	return ret;
+}
+
+static snd_pcm_uframes_t
+	idma_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct idma_ctrl *prtd = runtime->private_data;
+	dma_addr_t src;
+	unsigned long res;
+
+	pr_debug("Entered %s\n", __func__);
+
+	spin_lock(&prtd->lock);
+
+	idma_getpos(&src);
+	res = src - prtd->start;
+
+	spin_unlock(&prtd->lock);
+
+	pr_debug("Pointer %x \n", src);
+
+	if (res >= snd_pcm_lib_buffer_bytes(substream)) {
+		if (res == snd_pcm_lib_buffer_bytes(substream))
+			res = 0;
+	}
+
+	return bytes_to_frames(substream->runtime, res);
+}
+
+static int idma_mmap(struct snd_pcm_substream *substream,
+	struct vm_area_struct *vma)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	unsigned long size, offset;
+	int ret;
+
+	pr_debug("Entered %s\n", __func__);
+
+	/* From snd_pcm_lib_mmap_iomem */
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	vma->vm_flags |= VM_IO;
+	size = vma->vm_end - vma->vm_start;
+	offset = vma->vm_pgoff << PAGE_SHIFT;
+	ret = io_remap_pfn_range(vma, vma->vm_start,
+			(runtime->dma_addr + offset) >> PAGE_SHIFT,
+			size, vma->vm_page_prot);
+
+	return ret;
+}
+
+static irqreturn_t iis_irq(int irqno, void *dev_id)
+{
+	struct idma_ctrl *prtd = (struct idma_ctrl *)dev_id;
+	u32 iiscon, iisahb, val, addr;
+
+	iisahb  = readl(idma.regs + I2SAHB);
+	iiscon  = readl(idma.regs + I2SCON);
+
+	if (iisahb & AHB_LVL0INT)
+		val = AHB_CLRLVL0INT;
+	else
+		val = 0;
+
+	if (val) {
+		iisahb |= val;
+		writel(iisahb, idma.regs + I2SAHB);
+
+		addr = readl(idma.regs + I2SLVL0ADDR);
+		addr += prtd->periodsz;
+
+		if (addr >= prtd->end)
+			addr = LP_TXBUFF_ADDR;
+
+		writel(addr, idma.regs + I2SLVL0ADDR);
+
+		/* Finished dma transfer ? */
+		if (iisahb & AHB_LVLINTMASK) {
+			if (prtd->cb)
+				prtd->cb(prtd->token, prtd->periodsz);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int idma_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct idma_ctrl *prtd;
+	int ret;
+
+	pr_debug("Entered %s\n", __func__);
+
+	snd_soc_set_runtime_hwparams(substream, &idma_hardware);
+
+	prtd = kzalloc(sizeof(struct idma_ctrl), GFP_KERNEL);
+	if (prtd == NULL)
+		return -ENOMEM;
+
+	ret = request_irq(IRQ_I2S0, iis_irq, 0, "i2s", prtd);
+	if (ret < 0) {
+		pr_err("fail to claim i2s irq , ret = %d\n", ret);
+		kfree(prtd);
+		return ret;
+	}
+
+	spin_lock_init(&prtd->lock);
+
+	runtime->private_data = prtd;
+
+	return 0;
+}
+
+static int idma_close(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct idma_ctrl *prtd = runtime->private_data;
+
+	pr_debug("Entered %s, prtd = %p\n", __func__, prtd);
+
+	free_irq(IRQ_I2S0, prtd);
+
+	if (!prtd)
+		pr_err("idma_close called with prtd == NULL\n");
+
+	kfree(prtd);
+
+	return 0;
+}
+
+static struct snd_pcm_ops idma_ops = {
+	.open		= idma_open,
+	.close		= idma_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.trigger	= idma_trigger,
+	.pointer	= idma_pointer,
+	.mmap		= idma_mmap,
+	.hw_params	= idma_hw_params,
+	.hw_free	= idma_hw_free,
+	.prepare	= idma_prepare,
+};
+
+static void idma_free(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_dma_buffer *buf;
+
+	pr_debug("Entered %s\n", __func__);
+
+	substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	if (!substream)
+		return;
+
+	buf = &substream->dma_buffer;
+	if (!buf->area)
+		return;
+
+	iounmap(buf->area);
+
+	buf->area = NULL;
+	buf->addr = 0;
+}
+
+static int preallocate_idma_buffer(struct snd_pcm *pcm, int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+
+	pr_debug("Entered %s\n", __func__);
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+
+	/* Assign PCM buffer pointers */
+	buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
+	buf->addr = LP_TXBUFF_ADDR;
+	buf->bytes = idma_hardware.buffer_bytes_max;
+	buf->area = (unsigned char *)ioremap(buf->addr, buf->bytes);
+	pr_debug("%s:  VA-%p  PA-%X  %ubytes\n",
+			__func__, buf->area, buf->addr, buf->bytes);
+
+	return 0;
+}
+
+static u64 idma_mask = DMA_BIT_MASK(32);
+
+static int idma_new(struct snd_card *card,
+	struct snd_soc_dai *dai, struct snd_pcm *pcm)
+{
+	int ret = 0;
+
+	pr_debug("Entered %s\n", __func__);
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &idma_mask;
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	if (dai->driver->playback.channels_min)
+		ret = preallocate_idma_buffer(pcm,
+				SNDRV_PCM_STREAM_PLAYBACK);
+
+	return ret;
+}
+
+void idma_init(void *regs)
+{
+	spin_lock_init(&idma.lock);
+	idma.regs = regs;
+}
+
+struct snd_soc_platform_driver asoc_idma_platform = {
+	.ops = &idma_ops,
+	.pcm_new = idma_new,
+	.pcm_free = idma_free,
+};
+
+static int __devinit asoc_idma_platform_probe(struct platform_device *pdev)
+{
+	return snd_soc_register_platform(&pdev->dev, &asoc_idma_platform);
+}
+
+static int __devexit asoc_idma_platform_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_platform(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver asoc_idma_driver = {
+	.driver = {
+		.name = "samsung-idma",
+		.owner = THIS_MODULE,
+	},
+
+	.probe = asoc_idma_platform_probe,
+	.remove = __devexit_p(asoc_idma_platform_remove),
+};
+
+static int __init asoc_idma_init(void)
+{
+	return platform_driver_register(&asoc_idma_driver);
+}
+module_init(asoc_idma_init);
+
+static void __exit asoc_idma_exit(void)
+{
+	platform_driver_unregister(&asoc_idma_driver);
+}
+module_exit(asoc_idma_exit);
+
+MODULE_AUTHOR("Sangbeom Kim, <sbkim73@samsung.com>");
+MODULE_DESCRIPTION("Samsung ASoC IDMA Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:samsung-idma");
diff --git a/sound/soc/samsung/idma.h b/sound/soc/samsung/idma.h
new file mode 100644
index 0000000..2b0ac37
--- /dev/null
+++ b/sound/soc/samsung/idma.h
@@ -0,0 +1,28 @@
+/*
+ * idma.h  --  I2S0's Internal Dma driver
+ *
+ * Copyright (c) 2010 Samsung Electronics Co. Ltd
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __S3C_IDMA_H_
+#define __S3C_IDMA_H_
+
+#ifdef CONFIG_ARCH_EXYNOS4
+#define LP_TXBUFF_ADDR    (0x02020000)
+#else
+#define LP_TXBUFF_ADDR    (0xC0000000)
+#endif
+
+/* idma_state */
+#define LPAM_DMA_STOP    0
+#define LPAM_DMA_START   1
+
+extern void idma_init(void *regs);
+
+#endif /* __S3C_IDMA_H_ */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs
  2011-06-09  8:09 [PATCH 0/4] Adding idma driver for samsung SoCs Sangbeom Kim
  2011-06-09  8:09 ` [PATCH 1/4] ASoC: SAMSUNG: Modify I2S driver to support idma Sangbeom Kim
  2011-06-09  8:09 ` [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver Sangbeom Kim
@ 2011-06-09  8:09 ` Sangbeom Kim
  2011-06-09 10:46   ` Mark Brown
  2011-06-10  7:03   ` Jassi Brar
  2011-06-09  8:09 ` [PATCH 4/4] ARM: SAMSUNG: Add platform device for idma Sangbeom Kim
  3 siblings, 2 replies; 26+ messages in thread
From: Sangbeom Kim @ 2011-06-09  8:09 UTC (permalink / raw)
  To: alsa-devel, linux-samsung-soc
  Cc: jassisinghbrar, lrg, broonie, kgene.kim, ben-linux, Sangbeom Kim

Change platform driver to support internal dma
for smdk_wm8994 and smdk_wm8580

Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>
---
 sound/soc/samsung/smdk_wm8580.c |    2 +-
 sound/soc/samsung/smdk_wm8994.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index 3d26f66..fa415a1 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -229,7 +229,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
 		.stream_name = "Playback",
 		.cpu_dai_name = "samsung-i2s.x",
 		.codec_dai_name = "wm8580-hifi-playback",
-		.platform_name = "samsung-audio",
+		.platform_name = "samsung-idma",
 		.codec_name = "wm8580-codec.0-001b",
 		.init = smdk_wm8580_init_paifrx,
 		.ops = &smdk_ops,
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
index e7c1009..d36c575 100644
--- a/sound/soc/samsung/smdk_wm8994.c
+++ b/sound/soc/samsung/smdk_wm8994.c
@@ -134,7 +134,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
 		.stream_name = "Sec_Dai",
 		.cpu_dai_name = "samsung-i2s.4",
 		.codec_dai_name = "wm8994-aif1",
-		.platform_name = "samsung-audio",
+		.platform_name = "samsung-idma",
 		.codec_name = "wm8994-codec",
 		.ops = &smdk_ops,
 	},
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 4/4] ARM: SAMSUNG: Add platform device for idma
  2011-06-09  8:09 [PATCH 0/4] Adding idma driver for samsung SoCs Sangbeom Kim
                   ` (2 preceding siblings ...)
  2011-06-09  8:09 ` [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs Sangbeom Kim
@ 2011-06-09  8:09 ` Sangbeom Kim
  3 siblings, 0 replies; 26+ messages in thread
From: Sangbeom Kim @ 2011-06-09  8:09 UTC (permalink / raw)
  To: alsa-devel, linux-samsung-soc
  Cc: jassisinghbrar, lrg, broonie, kgene.kim, ben-linux, Sangbeom Kim

Exynos4 and S5PC110(S5PV210) has Internal dma(idma) in AUDSS.
To support idma, register idma platform device.

Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>
---
 arch/arm/mach-exynos4/include/mach/irqs.h |    2 ++
 arch/arm/mach-exynos4/mach-smdkv310.c     |    1 +
 arch/arm/mach-s5pv210/mach-smdkv210.c     |    1 +
 arch/arm/plat-samsung/dev-asocdma.c       |   10 ++++++++++
 arch/arm/plat-samsung/include/plat/devs.h |    1 +
 5 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index 5d03730..4c78dc0 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -73,6 +73,8 @@
 #define IRQ_SYSMMU_MFC_M1_0	COMBINER_IRQ(5, 6)
 #define IRQ_SYSMMU_PCIE_0	COMBINER_IRQ(5, 7)
 
+#define IRQ_I2S0		COMBINER_IRQ(17, 0)
+
 #define IRQ_PDMA0		COMBINER_IRQ(21, 0)
 #define IRQ_PDMA1		COMBINER_IRQ(21, 1)
 
diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-exynos4/mach-smdkv310.c
index 1526764..7c538c0 100644
--- a/arch/arm/mach-exynos4/mach-smdkv310.c
+++ b/arch/arm/mach-exynos4/mach-smdkv310.c
@@ -187,6 +187,7 @@ static struct platform_device *smdkv310_devices[] __initdata = {
 	&exynos4_device_pd[PD_GPS],
 	&exynos4_device_sysmmu,
 	&samsung_asoc_dma,
+	&samsung_asoc_idma,
 	&smdkv310_smsc911x,
 };
 
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index c6a9e86..c6900f8 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -267,6 +267,7 @@ static struct platform_device *smdkv210_devices[] __initdata = {
 	&s5pv210_device_iis0,
 	&s5pv210_device_spdif,
 	&samsung_asoc_dma,
+	&samsung_asoc_idma,
 	&samsung_device_keypad,
 	&smdkv210_dm9000,
 	&smdkv210_lcd_lte480wv,
diff --git a/arch/arm/plat-samsung/dev-asocdma.c b/arch/arm/plat-samsung/dev-asocdma.c
index a068c4f..832fa83 100644
--- a/arch/arm/plat-samsung/dev-asocdma.c
+++ b/arch/arm/plat-samsung/dev-asocdma.c
@@ -23,3 +23,13 @@ struct platform_device samsung_asoc_dma = {
 	}
 };
 EXPORT_SYMBOL(samsung_asoc_dma);
+
+struct platform_device samsung_asoc_idma = {
+	.name		  = "samsung-idma",
+	.id		  = -1,
+	.dev              = {
+		.dma_mask = &audio_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	}
+};
+EXPORT_SYMBOL(samsung_asoc_idma);
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index b61b8ee..54d4cd6 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -36,6 +36,7 @@ extern struct platform_device s3c64xx_device_spi0;
 extern struct platform_device s3c64xx_device_spi1;
 
 extern struct platform_device samsung_asoc_dma;
+extern struct platform_device samsung_asoc_idma;
 
 extern struct platform_device s3c64xx_device_pcm0;
 extern struct platform_device s3c64xx_device_pcm1;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver
  2011-06-09  8:09 ` [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver Sangbeom Kim
@ 2011-06-09  9:50   ` Liam Girdwood
  2011-06-09 23:31     ` Sangbeom Kim
  2011-06-09 12:33   ` Kyungmin Park
  2011-06-10 10:08   ` Jassi Brar
  2 siblings, 1 reply; 26+ messages in thread
From: Liam Girdwood @ 2011-06-09  9:50 UTC (permalink / raw)
  To: Sangbeom Kim
  Cc: alsa-devel, kgene.kim, jassisinghbrar, linux-samsung-soc,
	ben-linux, broonie, lrg

On 09/06/11 09:09, Sangbeom Kim wrote:
> I2S in Exynos4 and S5PC110(S5PV210) has a internal dma.
> It can be used low power audio mode and 2nd channel transfer.
> 
> Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>

Looks fine to me, but needs one fix before it can be applied.

Acked-by: Liam Girdwood <lrg@ti.com>

> ---
>  sound/soc/samsung/Makefile |    2 +
>  sound/soc/samsung/idma.c   |  492 ++++++++++++++++++++++++++++++++++++++++++++
>  sound/soc/samsung/idma.h   |   28 +++
>  3 files changed, 522 insertions(+), 0 deletions(-)
>  create mode 100644 sound/soc/samsung/idma.c
>  create mode 100644 sound/soc/samsung/idma.h
> 

snip

> +
> +static int idma_new(struct snd_card *card,
> +       struct snd_soc_dai *dai, struct snd_pcm *pcm)
> +{

This call API has changed in -next.

Thanks

Liam

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs
  2011-06-09  8:09 ` [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs Sangbeom Kim
@ 2011-06-09 10:46   ` Mark Brown
  2011-06-09 23:36     ` [alsa-devel] " Sangbeom Kim
  2011-06-10  7:03   ` Jassi Brar
  1 sibling, 1 reply; 26+ messages in thread
From: Mark Brown @ 2011-06-09 10:46 UTC (permalink / raw)
  To: Sangbeom Kim
  Cc: alsa-devel, linux-samsung-soc, jassisinghbrar, kgene.kim, ben-linux, lrg

On Thu, Jun 09, 2011 at 05:09:09PM +0900, Sangbeom Kim wrote:
> Change platform driver to support internal dma
> for smdk_wm8994 and smdk_wm8580

When you resubmit for the API change update it'd be helpful to update
the changelog to explain why the platforms are being changed to use only
internal DMA - what is the advantage this offers over regular DMA?  This
will help users understand how they should configure their own systems.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver
  2011-06-09  8:09 ` [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver Sangbeom Kim
  2011-06-09  9:50   ` Liam Girdwood
@ 2011-06-09 12:33   ` Kyungmin Park
  2011-06-09 23:41     ` [alsa-devel] " Sangbeom Kim
  2011-06-10 10:08   ` Jassi Brar
  2 siblings, 1 reply; 26+ messages in thread
From: Kyungmin Park @ 2011-06-09 12:33 UTC (permalink / raw)
  To: Sangbeom Kim
  Cc: alsa-devel, linux-samsung-soc, jassisinghbrar, lrg, broonie,
	kgene.kim, ben-linux

On Thu, Jun 9, 2011 at 5:09 PM, Sangbeom Kim <sbkim73@samsung.com> wrote:
> I2S in Exynos4 and S5PC110(S5PV210) has a internal dma.
> It can be used low power audio mode and 2nd channel transfer.
>
> Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>
> ---
>  sound/soc/samsung/Makefile |    2 +
>  sound/soc/samsung/idma.c   |  492 ++++++++++++++++++++++++++++++++++++++++++++
>  sound/soc/samsung/idma.h   |   28 +++
>  3 files changed, 522 insertions(+), 0 deletions(-)
>  create mode 100644 sound/soc/samsung/idma.c
>  create mode 100644 sound/soc/samsung/idma.h
>
> diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
> index 683843a..2b9e251 100644
> --- a/sound/soc/samsung/Makefile
> +++ b/sound/soc/samsung/Makefile
> @@ -1,5 +1,6 @@
>  # S3c24XX Platform Support
>  snd-soc-s3c24xx-objs := dma.o
> +snd-soc-idma-objs := idma.o
>  snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
>  snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
>  snd-soc-ac97-objs := ac97.o
> @@ -16,6 +17,7 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
>  obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o
>  obj-$(CONFIG_SND_SAMSUNG_PCM) += snd-soc-pcm.o
>  obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o
> +obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-idma.o
>
>  # S3C24XX Machine Support
>  snd-soc-jive-wm8750-objs := jive_wm8750.o
> diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
> new file mode 100644
> index 0000000..ae19546
> --- /dev/null
> +++ b/sound/soc/samsung/idma.c
> @@ -0,0 +1,492 @@
> +/*
> + * linux/sound/soc/samsung/idma.c
> + *
> + * Copyright (c) 2011 Samsung Electronics Co., Ltd.
> + *             http://www.samsung.com
> + *
> + * I2S0's Internal DMA driver
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/platform_device.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/slab.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +
> +#include "i2s.h"
> +#include "idma.h"
> +#include "dma.h"
> +
> +static const struct snd_pcm_hardware idma_hardware = {
> +       .info = SNDRV_PCM_INFO_INTERLEAVED |
> +                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
> +                   SNDRV_PCM_INFO_MMAP |
> +                   SNDRV_PCM_INFO_MMAP_VALID |
> +                   SNDRV_PCM_INFO_PAUSE |
> +                   SNDRV_PCM_INFO_RESUME,
> +       .formats = SNDRV_PCM_FMTBIT_S16_LE |
> +                   SNDRV_PCM_FMTBIT_U16_LE |
> +                   SNDRV_PCM_FMTBIT_S24_LE |
> +                   SNDRV_PCM_FMTBIT_U24_LE |
> +                   SNDRV_PCM_FMTBIT_U8 |
> +                   SNDRV_PCM_FMTBIT_S8,
> +       .channels_min = 2,
> +       .channels_max = 2,
> +       .buffer_bytes_max = 128 * 1024,
> +       .period_bytes_min = 128,
> +       .period_bytes_max = PAGE_SIZE*2,
> +       .periods_min = 1,
> +       .periods_max = 4,
> +};
> +
> +struct idma_ctrl {
> +       spinlock_t      lock;
> +       int             state;
> +       dma_addr_t      start;
> +       dma_addr_t      pos;
> +       dma_addr_t      end;
> +       dma_addr_t      period;
> +       dma_addr_t      periodsz;
> +       void            *token;
> +       void            (*cb)(void *dt, int bytes_xfer);
> +};
> +
> +static struct idma_info {
> +       spinlock_t      lock;
> +       void             __iomem  *regs;
> +       int             trigger_stat;
> +} idma;
> +
> +static void idma_getpos(dma_addr_t *src)
> +{
> +       *src = LP_TXBUFF_ADDR +
> +               (readl(idma.regs + I2STRNCNT) & 0xffffff) * 4;
> +}
> +
> +void i2sdma_getpos(dma_addr_t *src)
> +{
> +       if (idma.trigger_stat == LPAM_DMA_START)
> +               *src = LP_TXBUFF_ADDR +
> +                       (readl(idma.regs + I2STRNCNT) & 0xffffff) * 4;
> +       else
> +               *src = LP_TXBUFF_ADDR;
> +}
> +
> +static int idma_enqueue(struct snd_pcm_substream *substream)
> +{
> +       struct snd_pcm_runtime *runtime = substream->runtime;
> +       struct idma_ctrl *prtd = substream->runtime->private_data;
> +       u32 val;
> +
> +       spin_lock(&prtd->lock);
> +       prtd->token = (void *) substream;
> +       spin_unlock(&prtd->lock);
> +
> +       /* Internal DMA Level0 Interrupt Address */
> +       val = LP_TXBUFF_ADDR + prtd->periodsz;
> +       writel(val, idma.regs + I2SLVL0ADDR);
> +
> +       /* Start address0 of I2S internal DMA operation. */
> +       val = readl(idma.regs + I2SSTR0);
> +       val = LP_TXBUFF_ADDR;
> +       writel(val, idma.regs + I2SSTR0);
> +
> +       /*
> +        * Transfer block size for I2S internal DMA.
> +        * Should decide transfer size before start dma operation
> +        */
> +       val = readl(idma.regs + I2SSIZE);
> +       val &= ~(I2SSIZE_TRNMSK << I2SSIZE_SHIFT);
> +
> +       val |= (((runtime->dma_bytes >> 2) &
> +                       I2SSIZE_TRNMSK) << I2SSIZE_SHIFT);
> +       writel(val, idma.regs + I2SSIZE);
> +
> +       return 0;
> +}
> +
> +static void idma_setcallbk(struct snd_pcm_substream *substream,
> +                               void (*cb)(void *, int))
> +{
> +       struct idma_ctrl *prtd = substream->runtime->private_data;
> +
> +       spin_lock(&prtd->lock);
> +       prtd->cb = cb;
> +       spin_unlock(&prtd->lock);
> +
> +       pr_debug("%s:%d dma_period=%x\n", __func__, __LINE__, prtd->periodsz);
> +}
> +
> +static void idma_ctrl(int op)
> +{
> +       u32 val = readl(idma.regs + I2SAHB);
> +
> +       spin_lock(&idma.lock);
> +
> +       switch (op) {
> +       case LPAM_DMA_START:
> +               val |= (AHB_INTENLVL0 | AHB_DMAEN);
> +               break;
> +       case LPAM_DMA_STOP:
> +               val &= ~(AHB_INTENLVL0 | AHB_DMAEN);
> +               break;
> +       default:
> +               return;
> +       }
> +
> +       writel(val, idma.regs + I2SAHB);
> +       spin_unlock(&idma.lock);
> +}
> +
> +static void idma_done(void *id, int bytes_xfer)
> +{
> +       struct snd_pcm_substream *substream = id;
> +       struct idma_ctrl *prtd = substream->runtime->private_data;
> +
> +       if (prtd && (prtd->state & ST_RUNNING))
> +               snd_pcm_period_elapsed(substream);
> +}
> +
> +static int idma_hw_params(struct snd_pcm_substream *substream,
> +                               struct snd_pcm_hw_params *params)
> +{
> +       struct snd_pcm_runtime *runtime = substream->runtime;
> +       struct idma_ctrl *prtd = substream->runtime->private_data;
> +
> +       pr_debug("Entered %s\n", __func__);
> +
> +       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
> +       runtime->dma_bytes = params_buffer_bytes(params);
> +       memset(runtime->dma_area, 0, runtime->dma_bytes);
> +
> +       prtd->start = prtd->pos = runtime->dma_addr;
> +       prtd->period = params_periods(params);
> +       prtd->periodsz = params_period_bytes(params);
> +       prtd->end = LP_TXBUFF_ADDR + runtime->dma_bytes;
> +
> +       idma_setcallbk(substream, idma_done);
> +
> +       pr_debug("DmaAddr=@%x Total=%dbytes PrdSz=%d #Prds=%d dma_area=0x%x\n",
> +                       prtd->start, runtime->dma_bytes, prtd->periodsz,
> +                       prtd->period, (unsigned int)runtime->dma_area);
> +
> +       return 0;
> +}
> +
> +static int idma_hw_free(struct snd_pcm_substream *substream)
> +{
> +       pr_debug("Entered %s\n", __func__);
> +
> +       snd_pcm_set_runtime_buffer(substream, NULL);
> +
> +       return 0;
> +}
> +
> +static int idma_prepare(struct snd_pcm_substream *substream)
> +{
> +       struct idma_ctrl *prtd = substream->runtime->private_data;
> +
> +       pr_debug("Entered %s\n", __func__);
> +
> +       prtd->pos = prtd->start;
> +
> +       /* flush the DMA channel */
> +       idma_ctrl(LPAM_DMA_STOP);
> +       idma_enqueue(substream);
> +
> +       return 0;
> +}
> +
> +static int idma_trigger(struct snd_pcm_substream *substream, int cmd)
> +{
> +       struct idma_ctrl *prtd = substream->runtime->private_data;
> +       int ret = 0;
> +
> +       pr_debug("Entered %s\n", __func__);
> +
> +       spin_lock(&prtd->lock);
> +
> +       switch (cmd) {
> +       case SNDRV_PCM_TRIGGER_RESUME:
> +       case SNDRV_PCM_TRIGGER_START:
> +       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
> +               prtd->state |= ST_RUNNING;
> +               idma.trigger_stat = LPAM_DMA_START;
> +               idma_ctrl(LPAM_DMA_START);
> +               break;
> +
> +       case SNDRV_PCM_TRIGGER_SUSPEND:
> +       case SNDRV_PCM_TRIGGER_STOP:
> +       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
> +               prtd->state &= ~ST_RUNNING;
> +               idma.trigger_stat = LPAM_DMA_STOP;
> +               idma_ctrl(LPAM_DMA_STOP);
> +               break;
> +
> +       default:
> +               ret = -EINVAL;
> +               break;
> +       }
> +
> +       spin_unlock(&prtd->lock);
> +
> +       return ret;
> +}
> +
> +static snd_pcm_uframes_t
> +       idma_pointer(struct snd_pcm_substream *substream)
> +{
> +       struct snd_pcm_runtime *runtime = substream->runtime;
> +       struct idma_ctrl *prtd = runtime->private_data;
> +       dma_addr_t src;
> +       unsigned long res;
> +
> +       pr_debug("Entered %s\n", __func__);
> +
> +       spin_lock(&prtd->lock);
> +
> +       idma_getpos(&src);
> +       res = src - prtd->start;
> +
> +       spin_unlock(&prtd->lock);
> +
> +       pr_debug("Pointer %x \n", src);
> +
> +       if (res >= snd_pcm_lib_buffer_bytes(substream)) {
> +               if (res == snd_pcm_lib_buffer_bytes(substream))
> +                       res = 0;
> +       }
> +
> +       return bytes_to_frames(substream->runtime, res);
> +}
> +
> +static int idma_mmap(struct snd_pcm_substream *substream,
> +       struct vm_area_struct *vma)
> +{
> +       struct snd_pcm_runtime *runtime = substream->runtime;
> +       unsigned long size, offset;
> +       int ret;
> +
> +       pr_debug("Entered %s\n", __func__);
> +
> +       /* From snd_pcm_lib_mmap_iomem */
> +       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> +       vma->vm_flags |= VM_IO;
> +       size = vma->vm_end - vma->vm_start;
> +       offset = vma->vm_pgoff << PAGE_SHIFT;
> +       ret = io_remap_pfn_range(vma, vma->vm_start,
> +                       (runtime->dma_addr + offset) >> PAGE_SHIFT,
> +                       size, vma->vm_page_prot);
> +
> +       return ret;
> +}
> +
> +static irqreturn_t iis_irq(int irqno, void *dev_id)
> +{
> +       struct idma_ctrl *prtd = (struct idma_ctrl *)dev_id;
> +       u32 iiscon, iisahb, val, addr;
> +
> +       iisahb  = readl(idma.regs + I2SAHB);
> +       iiscon  = readl(idma.regs + I2SCON);
> +
> +       if (iisahb & AHB_LVL0INT)
> +               val = AHB_CLRLVL0INT;
> +       else
> +               val = 0;
> +
> +       if (val) {
> +               iisahb |= val;
> +               writel(iisahb, idma.regs + I2SAHB);
> +
> +               addr = readl(idma.regs + I2SLVL0ADDR);
> +               addr += prtd->periodsz;
> +
> +               if (addr >= prtd->end)
> +                       addr = LP_TXBUFF_ADDR;
> +
> +               writel(addr, idma.regs + I2SLVL0ADDR);
> +
> +               /* Finished dma transfer ? */
> +               if (iisahb & AHB_LVLINTMASK) {
> +                       if (prtd->cb)
> +                               prtd->cb(prtd->token, prtd->periodsz);
> +               }
> +       }
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static int idma_open(struct snd_pcm_substream *substream)
> +{
> +       struct snd_pcm_runtime *runtime = substream->runtime;
> +       struct idma_ctrl *prtd;
> +       int ret;
> +
> +       pr_debug("Entered %s\n", __func__);
> +
> +       snd_soc_set_runtime_hwparams(substream, &idma_hardware);
> +
> +       prtd = kzalloc(sizeof(struct idma_ctrl), GFP_KERNEL);
> +       if (prtd == NULL)
> +               return -ENOMEM;
> +
> +       ret = request_irq(IRQ_I2S0, iis_irq, 0, "i2s", prtd);
> +       if (ret < 0) {
> +               pr_err("fail to claim i2s irq , ret = %d\n", ret);
> +               kfree(prtd);
> +               return ret;
> +       }
> +
> +       spin_lock_init(&prtd->lock);
> +
> +       runtime->private_data = prtd;
> +
> +       return 0;
> +}
> +
> +static int idma_close(struct snd_pcm_substream *substream)
> +{
> +       struct snd_pcm_runtime *runtime = substream->runtime;
> +       struct idma_ctrl *prtd = runtime->private_data;
> +
> +       pr_debug("Entered %s, prtd = %p\n", __func__, prtd);
> +
> +       free_irq(IRQ_I2S0, prtd);
> +
> +       if (!prtd)
> +               pr_err("idma_close called with prtd == NULL\n");
> +
> +       kfree(prtd);
> +
> +       return 0;
> +}
> +
> +static struct snd_pcm_ops idma_ops = {
> +       .open           = idma_open,
> +       .close          = idma_close,
> +       .ioctl          = snd_pcm_lib_ioctl,
> +       .trigger        = idma_trigger,
> +       .pointer        = idma_pointer,
> +       .mmap           = idma_mmap,
> +       .hw_params      = idma_hw_params,
> +       .hw_free        = idma_hw_free,
> +       .prepare        = idma_prepare,
> +};
> +
> +static void idma_free(struct snd_pcm *pcm)
> +{
> +       struct snd_pcm_substream *substream;
> +       struct snd_dma_buffer *buf;
> +
> +       pr_debug("Entered %s\n", __func__);
> +
> +       substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
> +       if (!substream)
> +               return;
> +
> +       buf = &substream->dma_buffer;
> +       if (!buf->area)
> +               return;
> +
> +       iounmap(buf->area);
> +
> +       buf->area = NULL;
> +       buf->addr = 0;
> +}
> +
> +static int preallocate_idma_buffer(struct snd_pcm *pcm, int stream)
> +{
> +       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
> +       struct snd_dma_buffer *buf = &substream->dma_buffer;
> +
> +       pr_debug("Entered %s\n", __func__);
> +       buf->dev.dev = pcm->card->dev;
> +       buf->private_data = NULL;
> +
> +       /* Assign PCM buffer pointers */
> +       buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
> +       buf->addr = LP_TXBUFF_ADDR;
> +       buf->bytes = idma_hardware.buffer_bytes_max;
> +       buf->area = (unsigned char *)ioremap(buf->addr, buf->bytes);
> +       pr_debug("%s:  VA-%p  PA-%X  %ubytes\n",
> +                       __func__, buf->area, buf->addr, buf->bytes);
> +
> +       return 0;
> +}
> +
> +static u64 idma_mask = DMA_BIT_MASK(32);
> +
> +static int idma_new(struct snd_card *card,
> +       struct snd_soc_dai *dai, struct snd_pcm *pcm)
> +{
> +       int ret = 0;
> +
> +       pr_debug("Entered %s\n", __func__);
> +       if (!card->dev->dma_mask)
> +               card->dev->dma_mask = &idma_mask;
> +       if (!card->dev->coherent_dma_mask)
> +               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> +
> +       if (dai->driver->playback.channels_min)
> +               ret = preallocate_idma_buffer(pcm,
> +                               SNDRV_PCM_STREAM_PLAYBACK);
> +
> +       return ret;
> +}
> +
> +void idma_init(void *regs)
> +{
> +       spin_lock_init(&idma.lock);
> +       idma.regs = regs;
> +}
> +
> +struct snd_soc_platform_driver asoc_idma_platform = {
> +       .ops = &idma_ops,
> +       .pcm_new = idma_new,
> +       .pcm_free = idma_free,
> +};
> +
> +static int __devinit asoc_idma_platform_probe(struct platform_device *pdev)
> +{
> +       return snd_soc_register_platform(&pdev->dev, &asoc_idma_platform);
> +}
> +
> +static int __devexit asoc_idma_platform_remove(struct platform_device *pdev)
> +{
> +       snd_soc_unregister_platform(&pdev->dev);
> +       return 0;
> +}
> +
> +static struct platform_driver asoc_idma_driver = {
> +       .driver = {
> +               .name = "samsung-idma",
> +               .owner = THIS_MODULE,
> +       },
> +
> +       .probe = asoc_idma_platform_probe,
> +       .remove = __devexit_p(asoc_idma_platform_remove),
> +};
> +
> +static int __init asoc_idma_init(void)
> +{
> +       return platform_driver_register(&asoc_idma_driver);
> +}
> +module_init(asoc_idma_init);
> +
> +static void __exit asoc_idma_exit(void)
> +{
> +       platform_driver_unregister(&asoc_idma_driver);
> +}
> +module_exit(asoc_idma_exit);
> +
> +MODULE_AUTHOR("Sangbeom Kim, <sbkim73@samsung.com>");
> +MODULE_DESCRIPTION("Samsung ASoC IDMA Driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:samsung-idma");
> diff --git a/sound/soc/samsung/idma.h b/sound/soc/samsung/idma.h
> new file mode 100644
> index 0000000..2b0ac37
> --- /dev/null
> +++ b/sound/soc/samsung/idma.h
> @@ -0,0 +1,28 @@
> +/*
> + * idma.h  --  I2S0's Internal Dma driver
> + *
> + * Copyright (c) 2010 Samsung Electronics Co. Ltd
> + *
> + *  This program is free software; you can redistribute  it and/or modify it
> + *  under  the terms of  the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the  License, or (at your
> + *  option) any later version.
> + *
> + */
> +
> +#ifndef __S3C_IDMA_H_
> +#define __S3C_IDMA_H_
> +
> +#ifdef CONFIG_ARCH_EXYNOS4
> +#define LP_TXBUFF_ADDR    (0x02020000)
> +#else
> +#define LP_TXBUFF_ADDR    (0xC0000000)
> +#endif

Are there more fancy way to define the internal DMA address?
Are you sure new EXYNOS4 series will use the same address?

Thank you,
Kyungmin Park
> +
> +/* idma_state */
> +#define LPAM_DMA_STOP    0
> +#define LPAM_DMA_START   1
> +
> +extern void idma_init(void *regs);
> +
> +#endif /* __S3C_IDMA_H_ */
> --
> 1.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver
  2011-06-09  9:50   ` Liam Girdwood
@ 2011-06-09 23:31     ` Sangbeom Kim
  0 siblings, 0 replies; 26+ messages in thread
From: Sangbeom Kim @ 2011-06-09 23:31 UTC (permalink / raw)
  To: 'Liam Girdwood'
  Cc: alsa-devel, kgene.kim, jassisinghbrar, linux-samsung-soc,
	ben-linux, broonie, lrg


On 09/06/11 18:51, Liam Girdwood wrote:
> 
> Looks fine to me, but needs one fix before it can be applied.
> 
> Acked-by: Liam Girdwood <lrg@ti.com>
> 
> > ---
> >  sound/soc/samsung/Makefile |    2 +
> >  sound/soc/samsung/idma.c   |  492
> ++++++++++++++++++++++++++++++++++++++++++++
> >  sound/soc/samsung/idma.h   |   28 +++
> >  3 files changed, 522 insertions(+), 0 deletions(-)
> >  create mode 100644 sound/soc/samsung/idma.c
> >  create mode 100644 sound/soc/samsung/idma.h
> >
> 
> snip
> 
> > +
> > +static int idma_new(struct snd_card *card,
> > +       struct snd_soc_dai *dai, struct snd_pcm *pcm)
> > +{
> 
> This call API has changed in -next.

OK, I will check -next and will apply it.

Thanks and regards,
SB Kim

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [alsa-devel] [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs
  2011-06-09 10:46   ` Mark Brown
@ 2011-06-09 23:36     ` Sangbeom Kim
  0 siblings, 0 replies; 26+ messages in thread
From: Sangbeom Kim @ 2011-06-09 23:36 UTC (permalink / raw)
  To: 'Mark Brown'
  Cc: alsa-devel, linux-samsung-soc, jassisinghbrar, kgene.kim, ben-linux, lrg

On Thu, Jun 09, 2011 at 07:47PM +0900, Mark Brown wrote:
> 
> When you resubmit for the API change update it'd be helpful to update
> the changelog to explain why the platforms are being changed to use only
> internal DMA - what is the advantage this offers over regular DMA?  This
> will help users understand how they should configure their own systems.

OK, In the next vesion, I will add detail changelog for other users.

Thanks 
SB Kim

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [alsa-devel] [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver
  2011-06-09 12:33   ` Kyungmin Park
@ 2011-06-09 23:41     ` Sangbeom Kim
  0 siblings, 0 replies; 26+ messages in thread
From: Sangbeom Kim @ 2011-06-09 23:41 UTC (permalink / raw)
  To: 'Kyungmin Park'
  Cc: alsa-devel, linux-samsung-soc, jassisinghbrar, kgene.kim,
	ben-linux, broonie, lrg

On Thu, Jun 9, 2011 at 9:33 PM, Kyungmin Park  wrote:
> > +#ifndef __S3C_IDMA_H_
> > +#define __S3C_IDMA_H_
> > +
> > +#ifdef CONFIG_ARCH_EXYNOS4
> > +#define LP_TXBUFF_ADDR    (0x02020000)
> > +#else
> > +#define LP_TXBUFF_ADDR    (0xC0000000)
> > +#endif
> 
> Are there more fancy way to define the internal DMA address?
> Are you sure new EXYNOS4 series will use the same address?

I'm not sure that the new Exynos4 series will have a same address.
I will try to find more fancy way to define idma address in the next
version.

Thanks
SB Kim.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs
  2011-06-09  8:09 ` [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs Sangbeom Kim
  2011-06-09 10:46   ` Mark Brown
@ 2011-06-10  7:03   ` Jassi Brar
  2011-06-10  7:16     ` [alsa-devel] " Sangbeom Kim
  1 sibling, 1 reply; 26+ messages in thread
From: Jassi Brar @ 2011-06-10  7:03 UTC (permalink / raw)
  To: Sangbeom Kim
  Cc: alsa-devel, linux-samsung-soc, lrg, broonie, kgene.kim, ben-linux

On Thu, Jun 9, 2011 at 1:39 PM, Sangbeom Kim <sbkim73@samsung.com> wrote:
> Change platform driver to support internal dma
> for smdk_wm8994 and smdk_wm8580
>
> Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>
> ---

NAK.
It will break the most common user - SMDK6410, as s3c6410 doesn't have any
I2S internal DMA.
Please try to test the changes before submitting. I know it's boring,
but it's even more important :)

Thanks
-j

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [alsa-devel] [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs
  2011-06-10  7:03   ` Jassi Brar
@ 2011-06-10  7:16     ` Sangbeom Kim
  2011-06-10  7:26       ` Jassi Brar
  0 siblings, 1 reply; 26+ messages in thread
From: Sangbeom Kim @ 2011-06-10  7:16 UTC (permalink / raw)
  To: 'Jassi Brar'
  Cc: alsa-devel, kgene.kim, broonie, linux-samsung-soc, ben-linux, lrg

On Thu, Jun 9, 2011 at 4:04 PM, Jassi Brar wrote:
> NAK.
> It will break the most common user - SMDK6410, as s3c6410 doesn't have any
> I2S internal DMA.
> Please try to test the changes before submitting. I know it's boring,
> but it's even more important :)
> 
> Thanks

I only focused on S5PV210 and S5PV310.
I didn't consider s3c and s5p series.
In the next version, I will delete it.
But I had found some problem and want to share.
Like this patch, If different platform driver is used for each channel,
1st channel is overwritten by platform driver of 2nd channel.
Have you ever experienced before like this problem?

Thanks, 
SB Kim

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs
  2011-06-10  7:16     ` [alsa-devel] " Sangbeom Kim
@ 2011-06-10  7:26       ` Jassi Brar
  2011-06-10  9:49         ` [alsa-devel] " Mark Brown
  2011-06-13  1:47         ` Sangbeom Kim
  0 siblings, 2 replies; 26+ messages in thread
From: Jassi Brar @ 2011-06-10  7:26 UTC (permalink / raw)
  To: Sangbeom Kim
  Cc: alsa-devel, linux-samsung-soc, broonie, kgene.kim, ben-linux, lrg

On Fri, Jun 10, 2011 at 12:46 PM, Sangbeom Kim <sbkim73@samsung.com> wrote:
> On Thu, Jun 9, 2011 at 4:04 PM, Jassi Brar wrote:
>> NAK.
>> It will break the most common user - SMDK6410, as s3c6410 doesn't have any
>> I2S internal DMA.
>> Please try to test the changes before submitting. I know it's boring,
>> but it's even more important :)
>>
>> Thanks
>
> I only focused on S5PV210 and S5PV310.
> I didn't consider s3c and s5p series.
> In the next version, I will delete it.
Though if then everything works fine with system and internal DMA,
maybe it is better to assign platform_name string at runtime from some
module parameter, and leaving the default to normal system DMA ?

> But I had found some problem and want to share.
> Like this patch, If different platform driver is used for each channel,
> 1st channel is overwritten by platform driver of 2nd channel.
> Have you ever experienced before like this problem?
IIRC, I successfully tested using system DMA with primary and iDMA
with secondary channel. Only the sec chan would keep playing when
the system went to suspend. Though tt was long time ago and I don't remember
which Samsung kernel version.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [alsa-devel] [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs
  2011-06-10  7:26       ` Jassi Brar
@ 2011-06-10  9:49         ` Mark Brown
  2011-06-10 10:12           ` Jassi Brar
  2011-06-13  1:47         ` Sangbeom Kim
  1 sibling, 1 reply; 26+ messages in thread
From: Mark Brown @ 2011-06-10  9:49 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Sangbeom Kim, alsa-devel, kgene.kim, linux-samsung-soc, ben-linux, lrg

On Fri, Jun 10, 2011 at 12:56:45PM +0530, Jassi Brar wrote:
> On Fri, Jun 10, 2011 at 12:46 PM, Sangbeom Kim <sbkim73@samsung.com> wrote:

> > I only focused on S5PV210 and S5PV310.
> > I didn't consider s3c and s5p series.
> > In the next version, I will delete it.

> Though if then everything works fine with system and internal DMA,
> maybe it is better to assign platform_name string at runtime from some
> module parameter, and leaving the default to normal system DMA ?

If iDMA is always a better choice on CPUs that support it then the
cpu_is_() macros might be a good way to make the selection?

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver
  2011-06-09  8:09 ` [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver Sangbeom Kim
  2011-06-09  9:50   ` Liam Girdwood
  2011-06-09 12:33   ` Kyungmin Park
@ 2011-06-10 10:08   ` Jassi Brar
  2011-06-13  7:55     ` [alsa-devel] " Sangbeom Kim
  2 siblings, 1 reply; 26+ messages in thread
From: Jassi Brar @ 2011-06-10 10:08 UTC (permalink / raw)
  To: Sangbeom Kim
  Cc: alsa-devel, kgene.kim, broonie, linux-samsung-soc, ben-linux, lrg

On Thu, Jun 9, 2011 at 1:39 PM, Sangbeom Kim <sbkim73@samsung.com> wrote:
> I2S in Exynos4 and S5PC110(S5PV210) has a internal dma.
> It can be used low power audio mode and 2nd channel transfer.

For my convenience, could you please tell how does it differ from my
original implementation?  Most things look same, except for a few
variables.


> @@ -16,6 +17,7 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
>  obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o
>  obj-$(CONFIG_SND_SAMSUNG_PCM) += snd-soc-pcm.o
>  obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o
> +obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-idma.o

Please check that building only for s3c64xx doesn't break by this.



> +
> +static struct idma_info {
> +       spinlock_t      lock;
> +       void             __iomem  *regs;
> +       int             trigger_stat;
The role of trigger_stat is not necessary.

> +
> +       /* Start address0 of I2S internal DMA operation. */
> +       val = readl(idma.regs + I2SSTR0);
Why read when you immediately overwrite it ?
> +       val = LP_TXBUFF_ADDR;
> +       writel(val, idma.regs + I2SSTR0);
> +


> +static int idma_hw_params(struct snd_pcm_substream *substream,
> +                               struct snd_pcm_hw_params *params)
> +{
> +       struct snd_pcm_runtime *runtime = substream->runtime;
> +       struct idma_ctrl *prtd = substream->runtime->private_data;
> +
> +       pr_debug("Entered %s\n", __func__);
can we have all the pr_debug's converted to dev_debug ?


> +       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
> +       runtime->dma_bytes = params_buffer_bytes(params);
> +       memset(runtime->dma_area, 0, runtime->dma_bytes);
Is it really needed ?

> +
> +       if (iisahb & AHB_LVL0INT)
> +               val = AHB_CLRLVL0INT;
> +       else
> +               val = 0;
  val = (iisahb & AHB_LVL0INT) ? AHB_CLRLVL0INT : 0;     looks better

> +
> +       if (val) {
> +               iisahb |= val;
> +               writel(iisahb, idma.regs + I2SAHB);
> +
> +               addr = readl(idma.regs + I2SLVL0ADDR);
> +               addr += prtd->periodsz;
> +
> +               if (addr >= prtd->end)
> +                       addr = LP_TXBUFF_ADDR;
This will break if ring buffer is not a multiple of period size.
Either set the constraint in open or do modulo operation here.

> +
> +static int idma_close(struct snd_pcm_substream *substream)
> +{
> +       struct snd_pcm_runtime *runtime = substream->runtime;
> +       struct idma_ctrl *prtd = runtime->private_data;
> +
> +       pr_debug("Entered %s, prtd = %p\n", __func__, prtd);
> +
> +       free_irq(IRQ_I2S0, prtd);
> +
> +       if (!prtd)
> +               pr_err("idma_close called with prtd == NULL\n");
> +
> +       kfree(prtd);

Also       runtime->private_data = NULL;

> diff --git a/sound/soc/samsung/idma.h b/sound/soc/samsung/idma.h
> new file mode 100644
> index 0000000..2b0ac37
> --- /dev/null
> +++ b/sound/soc/samsung/idma.h
> @@ -0,0 +1,28 @@
> +/*
> + * idma.h  --  I2S0's Internal Dma driver
> + *
> + * Copyright (c) 2010 Samsung Electronics Co. Ltd
Copyright 2011 ?

> +/* idma_state */
> +#define LPAM_DMA_STOP    0
> +#define LPAM_DMA_START   1
These are internal to idma.c, please move them there.
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [alsa-devel] [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs
  2011-06-10  9:49         ` [alsa-devel] " Mark Brown
@ 2011-06-10 10:12           ` Jassi Brar
  2011-06-10 10:16             ` Mark Brown
  0 siblings, 1 reply; 26+ messages in thread
From: Jassi Brar @ 2011-06-10 10:12 UTC (permalink / raw)
  To: Mark Brown
  Cc: Sangbeom Kim, alsa-devel, kgene.kim, linux-samsung-soc, ben-linux, lrg

On Fri, Jun 10, 2011 at 3:19 PM, Mark Brown
<broonie@opensource.wolfsonmicro.com> wrote:
> On Fri, Jun 10, 2011 at 12:56:45PM +0530, Jassi Brar wrote:
>> On Fri, Jun 10, 2011 at 12:46 PM, Sangbeom Kim <sbkim73@samsung.com> wrote:
>
>> > I only focused on S5PV210 and S5PV310.
>> > I didn't consider s3c and s5p series.
>> > In the next version, I will delete it.
>
>> Though if then everything works fine with system and internal DMA,
>> maybe it is better to assign platform_name string at runtime from some
>> module parameter, and leaving the default to normal system DMA ?
>
> If iDMA is always a better choice on CPUs that support it then the
> cpu_is_() macros might be a good way to make the selection?

Actually I remembered just after I posted - iDMA wouldn't support capture.
So iDMA is a bad choice after all.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs
  2011-06-10 10:12           ` Jassi Brar
@ 2011-06-10 10:16             ` Mark Brown
  2011-06-10 10:43               ` [alsa-devel] " Jassi Brar
  0 siblings, 1 reply; 26+ messages in thread
From: Mark Brown @ 2011-06-10 10:16 UTC (permalink / raw)
  To: Jassi Brar
  Cc: alsa-devel, linux-samsung-soc, Sangbeom Kim, kgene.kim, ben-linux, lrg

On Fri, Jun 10, 2011 at 03:42:27PM +0530, Jassi Brar wrote:
> On Fri, Jun 10, 2011 at 3:19 PM, Mark Brown

> > If iDMA is always a better choice on CPUs that support it then the
> > cpu_is_() macros might be a good way to make the selection?

> Actually I remembered just after I posted - iDMA wouldn't support capture.
> So iDMA is a bad choice after all.

So I guess the relevant boards would be better off adding a separate DAI
to allow applications to select the DAI they want at runtime?

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [alsa-devel] [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs
  2011-06-10 10:16             ` Mark Brown
@ 2011-06-10 10:43               ` Jassi Brar
  0 siblings, 0 replies; 26+ messages in thread
From: Jassi Brar @ 2011-06-10 10:43 UTC (permalink / raw)
  To: Mark Brown
  Cc: Sangbeom Kim, alsa-devel, kgene.kim, linux-samsung-soc, ben-linux, lrg

On Fri, Jun 10, 2011 at 3:46 PM, Mark Brown
<broonie@opensource.wolfsonmicro.com> wrote:
> On Fri, Jun 10, 2011 at 03:42:27PM +0530, Jassi Brar wrote:
>> On Fri, Jun 10, 2011 at 3:19 PM, Mark Brown
>
>> > If iDMA is always a better choice on CPUs that support it then the
>> > cpu_is_() macros might be a good way to make the selection?
>
>> Actually I remembered just after I posted - iDMA wouldn't support capture.
>> So iDMA is a bad choice after all.
>
> So I guess the relevant boards would be better off adding a separate DAI
> to allow applications to select the DAI they want at runtime?

oops!  he is changing platform driver for the secondary i/f which
doesn't support
capture in the first place. So I think it can be done, though we need
to see if it
would be better to provide a way(control ?) to userspace to select
between sys/internal dma.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/4] ASoC: SAMSUNG: Modify I2S driver to support idma
  2011-06-09  8:09 ` [PATCH 1/4] ASoC: SAMSUNG: Modify I2S driver to support idma Sangbeom Kim
@ 2011-06-10 11:31   ` Jassi Brar
  2011-06-13  7:58     ` [alsa-devel] " Sangbeom Kim
  0 siblings, 1 reply; 26+ messages in thread
From: Jassi Brar @ 2011-06-10 11:31 UTC (permalink / raw)
  To: Sangbeom Kim
  Cc: alsa-devel, linux-samsung-soc, lrg, broonie, kgene.kim, ben-linux

On Thu, Jun 9, 2011 at 1:39 PM, Sangbeom Kim <sbkim73@samsung.com> wrote:

>        case 2:
> +               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> +                       i2s->dma_playback.dma_size = 4;
> +               else
> +                       i2s->dma_capture.dma_size = 4;
> +               break;

Why do we need this ?



> +       case 1:
> +               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> +                       i2s->dma_playback.dma_size = 2;
> +               else
> +                       i2s->dma_capture.dma_size = 2;

I2S doesn't support Mono.


>  #define SAMSUNG_I2S_RCLKSRC_0  0
>  #define SAMSUNG_I2S_RCLKSRC_1  1
> -#define SAMSUNG_I2S_CDCLK              2
> +#define SAMSUNG_I2S_CDCLK      2
Please avoid inconsequential changes.

> +
> +#define I2SCON                 0x0
> +#define I2SMOD                 0x4
> +#define I2SFIC                 0x8
> +#define I2SPSR                 0xc
> +#define I2STXD                 0x10
> +#define I2SRXD                 0x14
> +#define I2SFICS                        0x18
> +#define I2STXDS                        0x1c
> +#define I2SAHB                 0x20
> +#define I2SSTR0                        0x24
> +#define I2SSIZE                        0x28
> +#define I2STRNCNT              0x2c
> +#define I2SLVL0ADDR            0x30
> +#define I2SLVL1ADDR            0x34
> +#define I2SLVL2ADDR            0x38
> +#define I2SLVL3ADDR            0x3c
> +
> +#define CON_RSTCLR             (1 << 31)
> +#define CON_FRXOFSTATUS                (1 << 26)
> +#define CON_FRXORINTEN         (1 << 25)
> +#define CON_FTXSURSTAT         (1 << 24)
> +#define CON_FTXSURINTEN                (1 << 23)
> +#define CON_TXSDMA_PAUSE       (1 << 20)
> +#define CON_TXSDMA_ACTIVE      (1 << 18)
> +
> +#define CON_FTXURSTATUS                (1 << 17)
> +#define CON_FTXURINTEN         (1 << 16)
> +#define CON_TXFIFO2_EMPTY      (1 << 15)
> +#define CON_TXFIFO1_EMPTY      (1 << 14)
> +#define CON_TXFIFO2_FULL       (1 << 13)
> +#define CON_TXFIFO1_FULL       (1 << 12)
> +
> +#define CON_LRINDEX            (1 << 11)
> +#define CON_TXFIFO_EMPTY       (1 << 10)
> +#define CON_RXFIFO_EMPTY       (1 << 9)
> +#define CON_TXFIFO_FULL                (1 << 8)
> +#define CON_RXFIFO_FULL                (1 << 7)
> +#define CON_TXDMA_PAUSE                (1 << 6)
> +#define CON_RXDMA_PAUSE                (1 << 5)
> +#define CON_TXCH_PAUSE         (1 << 4)
> +#define CON_RXCH_PAUSE         (1 << 3)
> +#define CON_TXDMA_ACTIVE       (1 << 2)
> +#define CON_RXDMA_ACTIVE       (1 << 1)
> +#define CON_ACTIVE             (1 << 0)
> +
> +#define MOD_OPCLK_CDCLK_OUT    (0 << 30)
> +#define MOD_OPCLK_CDCLK_IN     (1 << 30)
> +#define MOD_OPCLK_BCLK_OUT     (2 << 30)
> +#define MOD_OPCLK_PCLK         (3 << 30)
> +#define MOD_OPCLK_MASK         (3 << 30)
> +#define MOD_TXS_IDMA           (1 << 28)
> +
> +#define MOD_BLCS_SHIFT         26
> +#define MOD_BLCS_16BIT         (0 << MOD_BLCS_SHIFT)
> +#define MOD_BLCS_8BIT          (1 << MOD_BLCS_SHIFT)
> +#define MOD_BLCS_24BIT         (2 << MOD_BLCS_SHIFT)
> +#define MOD_BLCS_MASK          (3 << MOD_BLCS_SHIFT)
> +#define MOD_BLCP_SHIFT         24
> +#define MOD_BLCP_16BIT         (0 << MOD_BLCP_SHIFT)
> +#define MOD_BLCP_8BIT          (1 << MOD_BLCP_SHIFT)
> +#define MOD_BLCP_24BIT         (2 << MOD_BLCP_SHIFT)
> +#define MOD_BLCP_MASK          (3 << MOD_BLCP_SHIFT)
> +
> +#define MOD_C2DD_HHALF         (1 << 21) /* Discard Higher-half */
> +#define MOD_C2DD_LHALF         (1 << 20) /* Discard Lower-half */
> +#define MOD_C1DD_HHALF         (1 << 19)
> +#define MOD_C1DD_LHALF         (1 << 18)
> +#define MOD_DC2_EN             (1 << 17)
> +#define MOD_DC1_EN             (1 << 16)
> +#define MOD_BLC_16BIT          (0 << 13)
> +#define MOD_BLC_8BIT           (1 << 13)
> +#define MOD_BLC_24BIT          (2 << 13)
> +#define MOD_BLC_MASK           (3 << 13)
> +
> +#define MOD_IMS_SYSMUX         (1 << 10)
> +#define MOD_SLAVE              (1 << 11)
> +#define MOD_TXONLY             (0 << 8)
> +#define MOD_RXONLY             (1 << 8)
> +#define MOD_TXRX               (2 << 8)
> +#define MOD_MASK               (3 << 8)
> +#define MOD_LR_LLOW            (0 << 7)
> +#define MOD_LR_RLOW            (1 << 7)
> +#define MOD_SDF_IIS            (0 << 5)
> +#define MOD_SDF_MSB            (1 << 5)
> +#define MOD_SDF_LSB            (2 << 5)
> +#define MOD_SDF_MASK           (3 << 5)
> +#define MOD_RCLK_256FS         (0 << 3)
> +#define MOD_RCLK_512FS         (1 << 3)
> +#define MOD_RCLK_384FS         (2 << 3)
> +#define MOD_RCLK_768FS         (3 << 3)
> +#define MOD_RCLK_MASK          (3 << 3)
> +#define MOD_BCLK_32FS          (0 << 1)
> +#define MOD_BCLK_48FS          (1 << 1)
> +#define MOD_BCLK_16FS          (2 << 1)
> +#define MOD_BCLK_24FS          (3 << 1)
> +#define MOD_BCLK_MASK          (3 << 1)
> +#define MOD_8BIT               (1 << 0)
> +
> +#define MOD_CDCLKCON           (1 << 12)
> +
> +#define PSR_PSREN              (1 << 15)
> +
> +#define FIC_TX2COUNT(x)                (((x) >>  24) & 0xf)
> +#define FIC_TX1COUNT(x)                (((x) >>  16) & 0xf)
> +
> +#define FIC_TXFLUSH            (1 << 15)
> +#define FIC_RXFLUSH            (1 << 7)
> +
> +#define FIC_TXCOUNT(x)         (((x) >>  8) & 0x7f)
> +#define FIC_RXCOUNT(x)         (((x) >>  0) & 0x7f)
> +#define FICS_TXCOUNT(x)                (((x) >>  8) & 0x7f)
> +
> +#define AHB_INTENLVL0          (1 << 24)
> +#define AHB_LVL0INT            (1 << 20)
> +#define AHB_CLRLVL0INT         (1 << 16)
> +#define AHB_DMARLD             (1 << 5)
> +#define AHB_INTMASK            (1 << 3)
> +#define AHB_DMAEN              (1 << 0)
> +#define AHB_LVLINTMASK         (0xf << 20)
> +
> +#define I2SSIZE_TRNMSK         (0xffff)
> +#define I2SSIZE_SHIFT          (16)
> +

The need of i2s.h is for machine drivers. Please move these register/bit
definitions to a new header(say i2s-regs.h) if we have to share them with
idma.c


> +#define msecs_to_loops(t)      (loops_per_jiffy / 1000 * HZ * t)
> +
> +#define ST_RUNNING             (1<<0)
> +#define ST_OPENED              (1<<1)
These should be moved to the c file that uses them.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [alsa-devel] [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs
  2011-06-10  7:26       ` Jassi Brar
  2011-06-10  9:49         ` [alsa-devel] " Mark Brown
@ 2011-06-13  1:47         ` Sangbeom Kim
  1 sibling, 0 replies; 26+ messages in thread
From: Sangbeom Kim @ 2011-06-13  1:47 UTC (permalink / raw)
  To: 'Jassi Brar'
  Cc: alsa-devel, linux-samsung-soc, broonie, kgene.kim, ben-linux, lrg

On Thu, Jun 10, 2011 at 4:27 PM, Jassi Brar wrote:
> Though if then everything works fine with system and internal DMA,
> maybe it is better to assign platform_name string at runtime from some
> module parameter, and leaving the default to normal system DMA ?
OK, I will leaving the default to system DMA,
 
> > But I had found some problem and want to share.
> > Like this patch, If different platform driver is used for each channel,
> > 1st channel is overwritten by platform driver of 2nd channel.
> > Have you ever experienced before like this problem?
> IIRC, I successfully tested using system DMA with primary and iDMA
> with secondary channel. Only the sec chan would keep playing when
> the system went to suspend. Though tt was long time ago and I don't
> remember
> which Samsung kernel version.
Your test condition is little different with my test condition.
You are using wrapper architecture. 
But I used each driver architecture.
Like in this patch, I assigned like below

{ /* Primary DAI i/f */
                .name = "WM8994 AIF1",
                .stream_name = "Pri_Dai",
                .cpu_dai_name = "samsung-i2s.0",
                .codec_dai_name = "wm8994-aif1",
                .platform_name = "samsung-audio",
                .codec_name = "wm8994-codec",
                .init = smdk_wm8994_init_paiftx,
                .ops = &smdk_ops,
        },
        { /* Sec_Fifo Playback i/f */
                .name = "Sec_FIFO TX",
                .stream_name = "Sec_Dai",
                .cpu_dai_name = "samsung-i2s.4",
                .codec_dai_name = "wm8994-aif1",
                .platform_name = "samsung-idma",
                .codec_name = "wm8994-codec",
                .ops = &smdk_ops,
        },

Primary is used by system dma,
Secondary is used by idma,

I try to use secondary by aplay, It can work fine.
============================================================================
==============
[root@samsung ~]# /mars/bin/aplay -Dplughw:0,1,0
/mars/share/sounds/alsa/Front_Center.wav
Entered idma_open
Playing WAVE '/mars/share/sounds/alsa/Front_Center.wav' [I2S] Initialize
sec_fifo idma
[I2S] Done hw params 
Entered idma_hw_params
idma_setcallbk:125 dma_period=2000
DmaAddr=@2020000 Total=96000bytes PrdSz=8192 #Prds=11 dma_area=0xd0840000
Entered idma_mmap
Entered idma_prepare
: Signed 16 bit Little Endian, Rate 48000 Hz, Mono
Entered idma_trigger
Entered idma_pointer, regs=d0822000
Pointer 2020004 
Snip.................
Entered idma_pointer, regs=d0822000
Pointer 202e00c 
Entered idma_pointer, regs=d0822000
Pointer 203000c 
Entered idma_pointer, regs=d0822000
Pointer 203200c 
Entered idma_pointer, regs=d0822000
Pointer 203400c 
Entered idma_pointer, regs=d0822000
Pointer 203600c 
Entered idma_trigger
Entered idma_hw_free
Entered idma_hw_free
Entered idma_close, prtd = cedb8bc0
[root@Samsung ~]#
============================================================================
==============
There is no problem and sound is good,

But If I try to use primary i/f, It can't work properly.
============================================================================
==============
[root@samsung ~]# /mars/bin/aplay -Dplughw:0,0,0
/mars/share/sounds/alsa/Front_Center.wav
Entered dma_open
Playing WAVE '/mars/share/sounds/alsa/Front_Center.wav' : Signed 16 bit
Little Endian, Rate 48000 Hz, Mono
[I2S] Done hw params 
Entered dma_hw_params
params cf82e6b0, client cf82e6b0, channel 16
Entered idma_mmap
Entered dma_prepare
Entered dma_enqueue
dma_enqueue: loaded 0, limit 12
dma_loaded: 0
dma_loaded: 1
dma_loaded: 2
dma_loaded: 3
dma_loaded: 4
dma_loaded: 5
dma_loaded: 6
dma_loaded: 7
dma_loaded: 8
dma_loaded: 9
dma_loaded: 10
dma_loaded: 11
Entered dma_trigger
Entered idma_pointer, regs=d0822000
Pointer 2020000 
Entered audio_buffdone

Snip....................

Pointer 2020000 
Entered audio_buffdone
Entered idma_pointer, regs=d0822000
Pointer 2020000 
Entered dma_trigger
Entered audio_buffdone
Entered dma_prepare
Entered audio_buffdone
Entered audio_buffdone
Entered dma_enqueue
dma_enqueue: loaded 0, limit 12
dma_loaded: 0
dma_loaded: 1
dma_loaded: 2
dma_loaded: 3
dma_loaded: 4
dma_loaded: 5
dma_loaded: 6
dma_loaded: 7
dma_loaded: 8
dma_loaded: 9
dma_loaded: 10
dma_loaded: 11
underrun!!! (at least 0.072 ms long)
Entered dma_trigger
Entered idma_pointer, regs=d0822000
Pointer 2020000 
Entered audio_buffdone
Entered idma_pointer, regs=d0822000
Pointer 2020000 
Snip................
Entered audio_buffdone
Entered idma_pointer, regs=d0822000
Pointer 2020000 
Entered dma_trigger
Entered audio_buffdone
Entered dma_prepare
Entered audio_buffdone
Entered audio_buffdone
Entered audio_buffdone
Entered audio_buffdone
Entered dma_enqueue
dma_enqueue: loaded 0, limit 12
dma_loaded: 0
dma_loaded: 1
dma_loaded: 2
dma_loaded: 3
dma_loaded: 4
dma_loaded: 5
dma_loaded: 6
dma_loaded: 7
dma_loaded: 8
dma_loaded: 9
dma_loaded: 10
dma_loaded: 11
Entered dma_trigger
underrun!!! (at least 0.030 ms long)
Entered audio_buffdone
Entered idma_pointer, regs=d0822000
Pointer 2020000 
Entered audio_buffdone
Entered idma_pointer, regs=d0822000
Pointer 2020000 
Entered audio_buffdone
Snip ............
Entered audio_buffdone
Entered idma_pointer, regs=d0822000
Pointer 2020000 
Entered dma_trigger
Entered audio_buffdone
Entered dma_hw_free
Entered audio_buffdone
Entered audio_buffdone
Entered audio_buffdone
Entered audio_buffdone
Entered audio_buffdone
Entered dma_hw_free
Entered dma_close
============================================================================
====
As you see above debugging log, Although system dma is assigned, instead
using dma api, idma api is used.
This is not a dma & idma driver's bug. This is platform driver handling
bugs. 
There is no machine driver using different platform driver in the ASoC.
So I guess that It is never confirmed before.
I want to share this problem. and I want to fix this problem. 
So I want to get your opinion.
Please check the above debug log and give your advice.

Thanks,
SB Kim

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [alsa-devel] [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver
  2011-06-10 10:08   ` Jassi Brar
@ 2011-06-13  7:55     ` Sangbeom Kim
  2011-06-13  9:07       ` Jassi Brar
  2011-06-13  9:40       ` Jassi Brar
  0 siblings, 2 replies; 26+ messages in thread
From: Sangbeom Kim @ 2011-06-13  7:55 UTC (permalink / raw)
  To: 'Jassi Brar'
  Cc: alsa-devel, kgene.kim, broonie, linux-samsung-soc, ben-linux, lrg

On Thu, Jun 10, 2011 at 7:08 PM, Jassi Brar wrote:
> For my convenience, could you please tell how does it differ from my
> original implementation?  Most things look same, except for a few
> variables.
Original code only can support specific buffer size and period count.
New idma driver can work with various buffer size and multiple period.
And Original code is implemented it based on wrapper arch.
But This patch can support driver arch.

> 
> > @@ -16,6 +17,7 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-
> v2.o
> >  obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o
> >  obj-$(CONFIG_SND_SAMSUNG_PCM) += snd-soc-pcm.o
> >  obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o
> > +obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-idma.o
> 
> Please check that building only for s3c64xx doesn't break by this.
If It have building problem, I will modify it in the next version

> 
> > +
> > +static struct idma_info {
> > +       spinlock_t      lock;
> > +       void             __iomem  *regs;
> > +       int             trigger_stat;
> The role of trigger_stat is not necessary.
trigger_stat can be used LP audio mode.
It can be used flag for checking idma operation.


> > +
> > +       /* Start address0 of I2S internal DMA operation. */
> > +       val = readl(idma.regs + I2SSTR0);
> Why read when you immediately overwrite it ?
This is useless code, It will be deleted.
 
> > +static int idma_hw_params(struct snd_pcm_substream *substream,
> > +                               struct snd_pcm_hw_params *params)
> > +{
> > +       struct snd_pcm_runtime *runtime = substream->runtime;
> > +       struct idma_ctrl *prtd = substream->runtime->private_data;
> > +
> > +       pr_debug("Entered %s\n", __func__);
> can we have all the pr_debug's converted to dev_debug ?
OK, I will change it.
 
> 
> > +       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
> > +       runtime->dma_bytes = params_buffer_bytes(params);
> > +       memset(runtime->dma_area, 0, runtime->dma_bytes);
> Is it really needed ?
It can delete useless data in dma buffer.
But It looks not need absolutely.

> > +
> > +       if (iisahb & AHB_LVL0INT)
> > +               val = AHB_CLRLVL0INT;
> > +       else
> > +               val = 0;
>   val = (iisahb & AHB_LVL0INT) ? AHB_CLRLVL0INT : 0;     looks better
OK, I will change
> > +
> > +       if (val) {
> > +               iisahb |= val;
> > +               writel(iisahb, idma.regs + I2SAHB);
> > +
> > +               addr = readl(idma.regs + I2SLVL0ADDR);
> > +               addr += prtd->periodsz;
> > +
> > +               if (addr >= prtd->end)
> > +                       addr = LP_TXBUFF_ADDR;
> This will break if ring buffer is not a multiple of period size.
> Either set the constraint in open or do modulo operation here.
OK,

> > +
> > +static int idma_close(struct snd_pcm_substream *substream)
> > +{
> > +       struct snd_pcm_runtime *runtime = substream->runtime;
> > +       struct idma_ctrl *prtd = runtime->private_data;
> > +
> > +       pr_debug("Entered %s, prtd = %p\n", __func__, prtd);
> > +
> > +       free_irq(IRQ_I2S0, prtd);
> > +
> > +       if (!prtd)
> > +               pr_err("idma_close called with prtd == NULL\n");
> > +
> > +       kfree(prtd);
> 
> Also       runtime->private_data = NULL;
OK,

> > diff --git a/sound/soc/samsung/idma.h b/sound/soc/samsung/idma.h
> > new file mode 100644
> > index 0000000..2b0ac37
> > --- /dev/null
> > +++ b/sound/soc/samsung/idma.h
> > @@ -0,0 +1,28 @@
> > +/*
> > + * idma.h  --  I2S0's Internal Dma driver
> > + *
> > + * Copyright (c) 2010 Samsung Electronics Co. Ltd
> Copyright 2011 ?
OK, I will modify it.
> 
> > +/* idma_state */
> > +#define LPAM_DMA_STOP    0
> > +#define LPAM_DMA_START   1
> These are internal to idma.c, please move them there.
OK, I will move it.

Thanks,

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [alsa-devel] [PATCH 1/4] ASoC: SAMSUNG: Modify I2S driver to support idma
  2011-06-10 11:31   ` Jassi Brar
@ 2011-06-13  7:58     ` Sangbeom Kim
  2011-06-13  8:57       ` Jassi Brar
  0 siblings, 1 reply; 26+ messages in thread
From: Sangbeom Kim @ 2011-06-13  7:58 UTC (permalink / raw)
  To: 'Jassi Brar'
  Cc: alsa-devel, kgene.kim, broonie, linux-samsung-soc, ben-linux, lrg

On Thu, Jun 9, 2011 at 8:31 PM, Jassi Brar wrote:
> 
> >        case 2:
> > +               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> > +                       i2s->dma_playback.dma_size = 4;
> > +               else
> > +                       i2s->dma_capture.dma_size = 4;
> > +               break;
> 
> Why do we need this ?
This code don't need here, I will delete it.
> 
> 
> 
> > +       case 1:
> > +               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> > +                       i2s->dma_playback.dma_size = 2;
> > +               else
> > +                       i2s->dma_capture.dma_size = 2;
> 
> I2S doesn't support Mono.
Yes, But some application require mono recording.
It is needed mono recording support.

> 
> >  #define SAMSUNG_I2S_RCLKSRC_0  0
> >  #define SAMSUNG_I2S_RCLKSRC_1  1
> > -#define SAMSUNG_I2S_CDCLK              2
> > +#define SAMSUNG_I2S_CDCLK      2
> Please avoid inconsequential changes.
OK,

> The need of i2s.h is for machine drivers. Please move these register/bit
> definitions to a new header(say i2s-regs.h) if we have to share them with
> idma.c
OK, I2S register have to share with idma, I will create new header file.

> 
> > +#define msecs_to_loops(t)      (loops_per_jiffy / 1000 * HZ * t)
> > +
> > +#define ST_RUNNING             (1<<0)
> > +#define ST_OPENED              (1<<1)
> These should be moved to the c file that uses them.
I will move it.

Thanks,

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/4] ASoC: SAMSUNG: Modify I2S driver to support idma
  2011-06-13  7:58     ` [alsa-devel] " Sangbeom Kim
@ 2011-06-13  8:57       ` Jassi Brar
  0 siblings, 0 replies; 26+ messages in thread
From: Jassi Brar @ 2011-06-13  8:57 UTC (permalink / raw)
  To: Sangbeom Kim
  Cc: alsa-devel, linux-samsung-soc, broonie, kgene.kim, ben-linux, lrg

On Mon, Jun 13, 2011 at 1:28 PM, Sangbeom Kim <sbkim73@samsung.com> wrote:
> On Thu, Jun 9, 2011 at 8:31 PM, Jassi Brar wrote:

>> > +       case 1:
>> > +               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
>> > +                       i2s->dma_playback.dma_size = 2;
>> > +               else
>> > +                       i2s->dma_capture.dma_size = 2;
>>
>> I2S doesn't support Mono.
> Yes, But some application require mono recording.
> It is needed mono recording support.
Sorry I don't understand.   Alsa plugins can record stereo from device
and provide
mono to applications.
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [alsa-devel] [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver
  2011-06-13  7:55     ` [alsa-devel] " Sangbeom Kim
@ 2011-06-13  9:07       ` Jassi Brar
  2011-06-13  9:40       ` Jassi Brar
  1 sibling, 0 replies; 26+ messages in thread
From: Jassi Brar @ 2011-06-13  9:07 UTC (permalink / raw)
  To: Sangbeom Kim
  Cc: alsa-devel, linux-samsung-soc, broonie, kgene.kim, ben-linux, lrg

On Mon, Jun 13, 2011 at 1:25 PM, Sangbeom Kim <sbkim73@samsung.com> wrote:
> On Thu, Jun 10, 2011 at 7:08 PM, Jassi Brar wrote:
>> For my convenience, could you please tell how does it differ from my
>> original implementation?  Most things look same, except for a few
>> variables.
> Original code only can support specific buffer size and period count.
> New idma driver can work with various buffer size and multiple period.
> And Original code is implemented it based on wrapper arch.
> But This patch can support driver arch.
>
>>
>> > @@ -16,6 +17,7 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-
>> v2.o
>> >  obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o
>> >  obj-$(CONFIG_SND_SAMSUNG_PCM) += snd-soc-pcm.o
>> >  obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o
>> > +obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-idma.o
>>
>> Please check that building only for s3c64xx doesn't break by this.
> If It have building problem, I will modify it in the next version
>
>>
>> > +
>> > +static struct idma_info {
>> > +       spinlock_t      lock;
>> > +       void             __iomem  *regs;
>> > +       int             trigger_stat;
>> The role of trigger_stat is not necessary.
> trigger_stat can be used LP audio mode.
> It can be used flag for checking idma operation.

ST_RUNNING bit of 'state' member of idma_ctrl structure can be used to
do the same.

Btw, please rename either the idma_ctrl structure or the idma_ctrl function, the
names clash.

Thnx
-j

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [alsa-devel] [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver
  2011-06-13  7:55     ` [alsa-devel] " Sangbeom Kim
  2011-06-13  9:07       ` Jassi Brar
@ 2011-06-13  9:40       ` Jassi Brar
  1 sibling, 0 replies; 26+ messages in thread
From: Jassi Brar @ 2011-06-13  9:40 UTC (permalink / raw)
  To: Sangbeom Kim
  Cc: alsa-devel, linux-samsung-soc, broonie, kgene.kim, ben-linux, lrg

On Mon, Jun 13, 2011 at 1:25 PM, Sangbeom Kim <sbkim73@samsung.com> wrote:
> On Thu, Jun 10, 2011 at 7:08 PM, Jassi Brar wrote:
>> For my convenience, could you please tell how does it differ from my
>> original implementation?  Most things look same, except for a few
>> variables.
> Original code only can support specific buffer size and period count.
> New idma driver can work with various buffer size and multiple period.
I believe using flexible buffer and period size with secondary i/f
make sense only
when _system_ dma and memory is used. iDMA provides no benefit over system DMA.
Whereas for LPAM mode, you can _never_ get more power saving than using full
internal buffer with slightly smaller period size.
So IMHO iDMA driver should use the original approach, while system dma still
allows the user to have flexible buffer and period size for low
latency with sec i/f.

> And Original code is implemented it based on wrapper arch.
> But This patch can support driver arch.
Well, there was extra wrapper driver. This driver is mostly unchanged.

Frankly, I don't see enough changes to justify overriding the MODULE_AUTHOR.
Of course, the copyright belongs to Samsung still.

Thnx,
-j

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2011-06-13  9:40 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-09  8:09 [PATCH 0/4] Adding idma driver for samsung SoCs Sangbeom Kim
2011-06-09  8:09 ` [PATCH 1/4] ASoC: SAMSUNG: Modify I2S driver to support idma Sangbeom Kim
2011-06-10 11:31   ` Jassi Brar
2011-06-13  7:58     ` [alsa-devel] " Sangbeom Kim
2011-06-13  8:57       ` Jassi Brar
2011-06-09  8:09 ` [PATCH 2/4] ASoC: SAMSUNG: Add I2S0 internal dma driver Sangbeom Kim
2011-06-09  9:50   ` Liam Girdwood
2011-06-09 23:31     ` Sangbeom Kim
2011-06-09 12:33   ` Kyungmin Park
2011-06-09 23:41     ` [alsa-devel] " Sangbeom Kim
2011-06-10 10:08   ` Jassi Brar
2011-06-13  7:55     ` [alsa-devel] " Sangbeom Kim
2011-06-13  9:07       ` Jassi Brar
2011-06-13  9:40       ` Jassi Brar
2011-06-09  8:09 ` [PATCH 3/4] ASoC: SAMSUNG: Change platform driver for SMDKs Sangbeom Kim
2011-06-09 10:46   ` Mark Brown
2011-06-09 23:36     ` [alsa-devel] " Sangbeom Kim
2011-06-10  7:03   ` Jassi Brar
2011-06-10  7:16     ` [alsa-devel] " Sangbeom Kim
2011-06-10  7:26       ` Jassi Brar
2011-06-10  9:49         ` [alsa-devel] " Mark Brown
2011-06-10 10:12           ` Jassi Brar
2011-06-10 10:16             ` Mark Brown
2011-06-10 10:43               ` [alsa-devel] " Jassi Brar
2011-06-13  1:47         ` Sangbeom Kim
2011-06-09  8:09 ` [PATCH 4/4] ARM: SAMSUNG: Add platform device for idma Sangbeom Kim

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.