All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] misc: atmel-ssc: support to read ssc version
@ 2014-06-06  7:41 ` Bo Shen
  0 siblings, 0 replies; 12+ messages in thread
From: Bo Shen @ 2014-06-06  7:41 UTC (permalink / raw)
  To: broonie; +Cc: nicolas.ferre, linux-sound, alsa-devel, linux-arm-kernel, Bo Shen

Read SSC IP version to check whether it supports frame sync
length extension feature.

Signed-off-by: Bo Shen <voice.shen@atmel.com>
---

 drivers/misc/atmel-ssc.c  | 7 +++++++
 include/linux/atmel-ssc.h | 3 +++
 2 files changed, 10 insertions(+)

diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 22de137..9f49bcb 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -136,6 +136,7 @@ static int ssc_probe(struct platform_device *pdev)
 	struct resource *regs;
 	struct ssc_device *ssc;
 	const struct atmel_ssc_platform_data *plat_dat;
+	u32 version;
 
 	ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
 	if (!ssc) {
@@ -173,8 +174,14 @@ static int ssc_probe(struct platform_device *pdev)
 	clk_prepare_enable(ssc->clk);
 	ssc_writel(ssc->regs, IDR, -1);
 	ssc_readl(ssc->regs, SR);
+	version = ssc_readl(ssc->regs, VERSION);
 	clk_disable_unprepare(ssc->clk);
 
+	if (version >= 0x300)
+		ssc->has_fslen_ext = 1;
+	else
+		ssc->has_fslen_ext = 0;
+
 	ssc->irq = platform_get_irq(pdev, 0);
 	if (!ssc->irq) {
 		dev_dbg(&pdev->dev, "could not get irq\n");
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index 571a12e..9ee1b68 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -19,6 +19,7 @@ struct ssc_device {
 	int			user;
 	int			irq;
 	bool			clk_from_rk_pin;
+	int			has_fslen_ext;
 };
 
 struct ssc_device * __must_check ssc_request(unsigned int ssc_num);
@@ -258,6 +259,8 @@ void ssc_free(struct ssc_device *ssc);
 #define SSC_IMR_TXSYN_SIZE			 1
 #define SSC_IMR_TXSYN_OFFSET			10
 
+#define SSC_VERSION			0x000000fc
+
 /* SSC PDC Receive Pointer Register */
 #define SSC_PDC_RPR			0x00000100
 
-- 
1.8.5.2


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

* [PATCH 1/2] misc: atmel-ssc: support to read ssc version
@ 2014-06-06  7:41 ` Bo Shen
  0 siblings, 0 replies; 12+ messages in thread
From: Bo Shen @ 2014-06-06  7:41 UTC (permalink / raw)
  To: linux-arm-kernel

Read SSC IP version to check whether it supports frame sync
length extension feature.

Signed-off-by: Bo Shen <voice.shen@atmel.com>
---

 drivers/misc/atmel-ssc.c  | 7 +++++++
 include/linux/atmel-ssc.h | 3 +++
 2 files changed, 10 insertions(+)

diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 22de137..9f49bcb 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -136,6 +136,7 @@ static int ssc_probe(struct platform_device *pdev)
 	struct resource *regs;
 	struct ssc_device *ssc;
 	const struct atmel_ssc_platform_data *plat_dat;
+	u32 version;
 
 	ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
 	if (!ssc) {
@@ -173,8 +174,14 @@ static int ssc_probe(struct platform_device *pdev)
 	clk_prepare_enable(ssc->clk);
 	ssc_writel(ssc->regs, IDR, -1);
 	ssc_readl(ssc->regs, SR);
+	version = ssc_readl(ssc->regs, VERSION);
 	clk_disable_unprepare(ssc->clk);
 
+	if (version >= 0x300)
+		ssc->has_fslen_ext = 1;
+	else
+		ssc->has_fslen_ext = 0;
+
 	ssc->irq = platform_get_irq(pdev, 0);
 	if (!ssc->irq) {
 		dev_dbg(&pdev->dev, "could not get irq\n");
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index 571a12e..9ee1b68 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -19,6 +19,7 @@ struct ssc_device {
 	int			user;
 	int			irq;
 	bool			clk_from_rk_pin;
+	int			has_fslen_ext;
 };
 
 struct ssc_device * __must_check ssc_request(unsigned int ssc_num);
@@ -258,6 +259,8 @@ void ssc_free(struct ssc_device *ssc);
 #define SSC_IMR_TXSYN_SIZE			 1
 #define SSC_IMR_TXSYN_OFFSET			10
 
+#define SSC_VERSION			0x000000fc
+
 /* SSC PDC Receive Pointer Register */
 #define SSC_PDC_RPR			0x00000100
 
-- 
1.8.5.2

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

* [PATCH 1/2] misc: atmel-ssc: support to read ssc version
@ 2014-06-06  7:41 ` Bo Shen
  0 siblings, 0 replies; 12+ messages in thread
From: Bo Shen @ 2014-06-06  7:41 UTC (permalink / raw)
  To: broonie; +Cc: nicolas.ferre, linux-sound, alsa-devel, linux-arm-kernel, Bo Shen

Read SSC IP version to check whether it supports frame sync
length extension feature.

Signed-off-by: Bo Shen <voice.shen@atmel.com>
---

 drivers/misc/atmel-ssc.c  | 7 +++++++
 include/linux/atmel-ssc.h | 3 +++
 2 files changed, 10 insertions(+)

diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 22de137..9f49bcb 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -136,6 +136,7 @@ static int ssc_probe(struct platform_device *pdev)
 	struct resource *regs;
 	struct ssc_device *ssc;
 	const struct atmel_ssc_platform_data *plat_dat;
+	u32 version;
 
 	ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
 	if (!ssc) {
@@ -173,8 +174,14 @@ static int ssc_probe(struct platform_device *pdev)
 	clk_prepare_enable(ssc->clk);
 	ssc_writel(ssc->regs, IDR, -1);
 	ssc_readl(ssc->regs, SR);
+	version = ssc_readl(ssc->regs, VERSION);
 	clk_disable_unprepare(ssc->clk);
 
+	if (version >= 0x300)
+		ssc->has_fslen_ext = 1;
+	else
+		ssc->has_fslen_ext = 0;
+
 	ssc->irq = platform_get_irq(pdev, 0);
 	if (!ssc->irq) {
 		dev_dbg(&pdev->dev, "could not get irq\n");
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index 571a12e..9ee1b68 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -19,6 +19,7 @@ struct ssc_device {
 	int			user;
 	int			irq;
 	bool			clk_from_rk_pin;
+	int			has_fslen_ext;
 };
 
 struct ssc_device * __must_check ssc_request(unsigned int ssc_num);
@@ -258,6 +259,8 @@ void ssc_free(struct ssc_device *ssc);
 #define SSC_IMR_TXSYN_SIZE			 1
 #define SSC_IMR_TXSYN_OFFSET			10
 
+#define SSC_VERSION			0x000000fc
+
 /* SSC PDC Receive Pointer Register */
 #define SSC_PDC_RPR			0x00000100
 
-- 
1.8.5.2


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

* [PATCH 2/2] ASoC: atmel_ssc_dai: enable fslen extension feature
  2014-06-06  7:41 ` Bo Shen
  (?)
@ 2014-06-06  7:41   ` Bo Shen
  -1 siblings, 0 replies; 12+ messages in thread
From: Bo Shen @ 2014-06-06  7:41 UTC (permalink / raw)
  To: broonie; +Cc: nicolas.ferre, linux-sound, alsa-devel, linux-arm-kernel, Bo Shen

When SSC work as master, it will generate the frame sync signal.
On old SoCs, it only supports frame sync length less or equal to
16bits, on newer SoCs, it supports frame sync length extension,
which can support frame size larger than 16 bits.
So, add this to make it supports playback 24/32 bits audio clips.

Signed-off-by: Bo Shen <voice.shen@atmel.com>
---
 include/linux/atmel-ssc.h       |  4 ++++
 sound/soc/atmel/atmel_ssc_dai.c | 34 ++++++++++++++++++----------------
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index 9ee1b68..70c5922 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -72,6 +72,8 @@ void ssc_free(struct ssc_device *ssc);
 #define SSC_RFMR_DATNB_OFFSET			 8
 #define SSC_RFMR_FSEDGE_SIZE			 1
 #define SSC_RFMR_FSEDGE_OFFSET			24
+#define SSC_RFMR_FSLEN_EXT_SIZE			 4
+#define SSC_RFMR_FSLEN_EXT_OFFSET		28
 #define SSC_RFMR_FSLEN_SIZE			 4
 #define SSC_RFMR_FSLEN_OFFSET			16
 #define SSC_RFMR_FSOS_SIZE			 4
@@ -110,6 +112,8 @@ void ssc_free(struct ssc_device *ssc);
 #define SSC_TFMR_FSDEN_OFFSET			23
 #define SSC_TFMR_FSEDGE_SIZE			 1
 #define SSC_TFMR_FSEDGE_OFFSET			24
+#define SSC_TFMR_FSLEN_EXT_SIZE			 4
+#define SSC_TFMR_FSLEN_EXT_OFFSET		28
 #define SSC_TFMR_FSLEN_SIZE			 4
 #define SSC_TFMR_FSLEN_OFFSET			16
 #define SSC_TFMR_FSOS_SIZE			 3
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index de433cfd..7d501e4 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -347,6 +347,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 	u32 tfmr, rfmr, tcmr, rcmr;
 	int start_event;
 	int ret;
+	int fslen, fslen_ext;
 
 	/*
 	 * Currently, there is only one set of dma params for
@@ -388,18 +389,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	/*
-	 * The SSC only supports up to 16-bit samples in I2S format, due
-	 * to the size of the Frame Mode Register FSLEN field.
-	 */
-	if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
-		&& bits > 16) {
-		printk(KERN_WARNING
-				"atmel_ssc_dai: sample size %d "
-				"is too large for I2S\n", bits);
-		return -EINVAL;
-	}
-
-	/*
 	 * Compute SSC register settings.
 	 */
 	switch (ssc_p->daifmt
@@ -413,6 +402,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 		 * from the MCK divider, and the BCLK signal
 		 * is output on the SSC TK line.
 		 */
+
+		if (bits > 16 && !ssc->has_fslen_ext) {
+			dev_err(dai->dev,
+				"sample size %d is too large for SSC device\n",
+				bits);
+			return -EINVAL;
+		}
+
+		fslen_ext = (bits - 1) / 16;
+		fslen = (bits - 1) % 16;
+
 		rcmr =	  SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
 			| SSC_BF(RCMR_STTDLY, START_DELAY)
 			| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
@@ -420,9 +420,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 			| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
 			| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
 
-		rfmr =	  SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+		rfmr =    SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
+			| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
 			| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
-			| SSC_BF(RFMR_FSLEN, (bits - 1))
+			| SSC_BF(RFMR_FSLEN, fslen)
 			| SSC_BF(RFMR_DATNB, (channels - 1))
 			| SSC_BIT(RFMR_MSBF)
 			| SSC_BF(RFMR_LOOP, 0)
@@ -435,10 +436,11 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 			| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
 			| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
 
-		tfmr =	  SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+		tfmr =    SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
+			| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
 			| SSC_BF(TFMR_FSDEN, 0)
 			| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
-			| SSC_BF(TFMR_FSLEN, (bits - 1))
+			| SSC_BF(TFMR_FSLEN, fslen)
 			| SSC_BF(TFMR_DATNB, (channels - 1))
 			| SSC_BIT(TFMR_MSBF)
 			| SSC_BF(TFMR_DATDEF, 0)
-- 
1.8.5.2


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

* [PATCH 2/2] ASoC: atmel_ssc_dai: enable fslen extension feature
@ 2014-06-06  7:41   ` Bo Shen
  0 siblings, 0 replies; 12+ messages in thread
From: Bo Shen @ 2014-06-06  7:41 UTC (permalink / raw)
  To: linux-arm-kernel

When SSC work as master, it will generate the frame sync signal.
On old SoCs, it only supports frame sync length less or equal to
16bits, on newer SoCs, it supports frame sync length extension,
which can support frame size larger than 16 bits.
So, add this to make it supports playback 24/32 bits audio clips.

Signed-off-by: Bo Shen <voice.shen@atmel.com>
---
 include/linux/atmel-ssc.h       |  4 ++++
 sound/soc/atmel/atmel_ssc_dai.c | 34 ++++++++++++++++++----------------
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index 9ee1b68..70c5922 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -72,6 +72,8 @@ void ssc_free(struct ssc_device *ssc);
 #define SSC_RFMR_DATNB_OFFSET			 8
 #define SSC_RFMR_FSEDGE_SIZE			 1
 #define SSC_RFMR_FSEDGE_OFFSET			24
+#define SSC_RFMR_FSLEN_EXT_SIZE			 4
+#define SSC_RFMR_FSLEN_EXT_OFFSET		28
 #define SSC_RFMR_FSLEN_SIZE			 4
 #define SSC_RFMR_FSLEN_OFFSET			16
 #define SSC_RFMR_FSOS_SIZE			 4
@@ -110,6 +112,8 @@ void ssc_free(struct ssc_device *ssc);
 #define SSC_TFMR_FSDEN_OFFSET			23
 #define SSC_TFMR_FSEDGE_SIZE			 1
 #define SSC_TFMR_FSEDGE_OFFSET			24
+#define SSC_TFMR_FSLEN_EXT_SIZE			 4
+#define SSC_TFMR_FSLEN_EXT_OFFSET		28
 #define SSC_TFMR_FSLEN_SIZE			 4
 #define SSC_TFMR_FSLEN_OFFSET			16
 #define SSC_TFMR_FSOS_SIZE			 3
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index de433cfd..7d501e4 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -347,6 +347,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 	u32 tfmr, rfmr, tcmr, rcmr;
 	int start_event;
 	int ret;
+	int fslen, fslen_ext;
 
 	/*
 	 * Currently, there is only one set of dma params for
@@ -388,18 +389,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	/*
-	 * The SSC only supports up to 16-bit samples in I2S format, due
-	 * to the size of the Frame Mode Register FSLEN field.
-	 */
-	if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
-		&& bits > 16) {
-		printk(KERN_WARNING
-				"atmel_ssc_dai: sample size %d "
-				"is too large for I2S\n", bits);
-		return -EINVAL;
-	}
-
-	/*
 	 * Compute SSC register settings.
 	 */
 	switch (ssc_p->daifmt
@@ -413,6 +402,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 		 * from the MCK divider, and the BCLK signal
 		 * is output on the SSC TK line.
 		 */
+
+		if (bits > 16 && !ssc->has_fslen_ext) {
+			dev_err(dai->dev,
+				"sample size %d is too large for SSC device\n",
+				bits);
+			return -EINVAL;
+		}
+
+		fslen_ext = (bits - 1) / 16;
+		fslen = (bits - 1) % 16;
+
 		rcmr =	  SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
 			| SSC_BF(RCMR_STTDLY, START_DELAY)
 			| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
@@ -420,9 +420,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 			| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
 			| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
 
-		rfmr =	  SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+		rfmr =    SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
+			| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
 			| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
-			| SSC_BF(RFMR_FSLEN, (bits - 1))
+			| SSC_BF(RFMR_FSLEN, fslen)
 			| SSC_BF(RFMR_DATNB, (channels - 1))
 			| SSC_BIT(RFMR_MSBF)
 			| SSC_BF(RFMR_LOOP, 0)
@@ -435,10 +436,11 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 			| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
 			| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
 
-		tfmr =	  SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+		tfmr =    SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
+			| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
 			| SSC_BF(TFMR_FSDEN, 0)
 			| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
-			| SSC_BF(TFMR_FSLEN, (bits - 1))
+			| SSC_BF(TFMR_FSLEN, fslen)
 			| SSC_BF(TFMR_DATNB, (channels - 1))
 			| SSC_BIT(TFMR_MSBF)
 			| SSC_BF(TFMR_DATDEF, 0)
-- 
1.8.5.2

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

* [PATCH 2/2] ASoC: atmel_ssc_dai: enable fslen extension feature
@ 2014-06-06  7:41   ` Bo Shen
  0 siblings, 0 replies; 12+ messages in thread
From: Bo Shen @ 2014-06-06  7:41 UTC (permalink / raw)
  To: broonie; +Cc: nicolas.ferre, linux-sound, alsa-devel, linux-arm-kernel, Bo Shen

When SSC work as master, it will generate the frame sync signal.
On old SoCs, it only supports frame sync length less or equal to
16bits, on newer SoCs, it supports frame sync length extension,
which can support frame size larger than 16 bits.
So, add this to make it supports playback 24/32 bits audio clips.

Signed-off-by: Bo Shen <voice.shen@atmel.com>
---
 include/linux/atmel-ssc.h       |  4 ++++
 sound/soc/atmel/atmel_ssc_dai.c | 34 ++++++++++++++++++----------------
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index 9ee1b68..70c5922 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -72,6 +72,8 @@ void ssc_free(struct ssc_device *ssc);
 #define SSC_RFMR_DATNB_OFFSET			 8
 #define SSC_RFMR_FSEDGE_SIZE			 1
 #define SSC_RFMR_FSEDGE_OFFSET			24
+#define SSC_RFMR_FSLEN_EXT_SIZE			 4
+#define SSC_RFMR_FSLEN_EXT_OFFSET		28
 #define SSC_RFMR_FSLEN_SIZE			 4
 #define SSC_RFMR_FSLEN_OFFSET			16
 #define SSC_RFMR_FSOS_SIZE			 4
@@ -110,6 +112,8 @@ void ssc_free(struct ssc_device *ssc);
 #define SSC_TFMR_FSDEN_OFFSET			23
 #define SSC_TFMR_FSEDGE_SIZE			 1
 #define SSC_TFMR_FSEDGE_OFFSET			24
+#define SSC_TFMR_FSLEN_EXT_SIZE			 4
+#define SSC_TFMR_FSLEN_EXT_OFFSET		28
 #define SSC_TFMR_FSLEN_SIZE			 4
 #define SSC_TFMR_FSLEN_OFFSET			16
 #define SSC_TFMR_FSOS_SIZE			 3
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index de433cfd..7d501e4 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -347,6 +347,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 	u32 tfmr, rfmr, tcmr, rcmr;
 	int start_event;
 	int ret;
+	int fslen, fslen_ext;
 
 	/*
 	 * Currently, there is only one set of dma params for
@@ -388,18 +389,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	/*
-	 * The SSC only supports up to 16-bit samples in I2S format, due
-	 * to the size of the Frame Mode Register FSLEN field.
-	 */
-	if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) = SND_SOC_DAIFMT_I2S
-		&& bits > 16) {
-		printk(KERN_WARNING
-				"atmel_ssc_dai: sample size %d "
-				"is too large for I2S\n", bits);
-		return -EINVAL;
-	}
-
-	/*
 	 * Compute SSC register settings.
 	 */
 	switch (ssc_p->daifmt
@@ -413,6 +402,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 		 * from the MCK divider, and the BCLK signal
 		 * is output on the SSC TK line.
 		 */
+
+		if (bits > 16 && !ssc->has_fslen_ext) {
+			dev_err(dai->dev,
+				"sample size %d is too large for SSC device\n",
+				bits);
+			return -EINVAL;
+		}
+
+		fslen_ext = (bits - 1) / 16;
+		fslen = (bits - 1) % 16;
+
 		rcmr =	  SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
 			| SSC_BF(RCMR_STTDLY, START_DELAY)
 			| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
@@ -420,9 +420,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 			| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
 			| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
 
-		rfmr =	  SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+		rfmr =    SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
+			| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
 			| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
-			| SSC_BF(RFMR_FSLEN, (bits - 1))
+			| SSC_BF(RFMR_FSLEN, fslen)
 			| SSC_BF(RFMR_DATNB, (channels - 1))
 			| SSC_BIT(RFMR_MSBF)
 			| SSC_BF(RFMR_LOOP, 0)
@@ -435,10 +436,11 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 			| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
 			| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
 
-		tfmr =	  SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+		tfmr =    SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
+			| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
 			| SSC_BF(TFMR_FSDEN, 0)
 			| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
-			| SSC_BF(TFMR_FSLEN, (bits - 1))
+			| SSC_BF(TFMR_FSLEN, fslen)
 			| SSC_BF(TFMR_DATNB, (channels - 1))
 			| SSC_BIT(TFMR_MSBF)
 			| SSC_BF(TFMR_DATDEF, 0)
-- 
1.8.5.2


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

* Re: [PATCH 1/2] misc: atmel-ssc: support to read ssc version
  2014-06-06  7:41 ` Bo Shen
  (?)
@ 2014-06-10 16:32   ` Nicolas Ferre
  -1 siblings, 0 replies; 12+ messages in thread
From: Nicolas Ferre @ 2014-06-10 16:32 UTC (permalink / raw)
  To: Bo Shen, broonie; +Cc: linux-sound, alsa-devel, linux-arm-kernel

On 06/06/2014 09:41, Bo Shen :
> Read SSC IP version to check whether it supports frame sync
> length extension feature.
> 
> Signed-off-by: Bo Shen <voice.shen@atmel.com>

No. We already have 2 compatible versions for the DT or id table. Simply
add one.
Please use this infrastructure to describe such features, I don't want
to mix the approaches: "compatible string" xor "IP revision".

The DT of the product will then describe on which version of the IP it
can rely to have this feature.

Best regards,

> ---
> 
>  drivers/misc/atmel-ssc.c  | 7 +++++++
>  include/linux/atmel-ssc.h | 3 +++
>  2 files changed, 10 insertions(+)
> 
> diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
> index 22de137..9f49bcb 100644
> --- a/drivers/misc/atmel-ssc.c
> +++ b/drivers/misc/atmel-ssc.c
> @@ -136,6 +136,7 @@ static int ssc_probe(struct platform_device *pdev)
>  	struct resource *regs;
>  	struct ssc_device *ssc;
>  	const struct atmel_ssc_platform_data *plat_dat;
> +	u32 version;
>  
>  	ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
>  	if (!ssc) {
> @@ -173,8 +174,14 @@ static int ssc_probe(struct platform_device *pdev)
>  	clk_prepare_enable(ssc->clk);
>  	ssc_writel(ssc->regs, IDR, -1);
>  	ssc_readl(ssc->regs, SR);
> +	version = ssc_readl(ssc->regs, VERSION);
>  	clk_disable_unprepare(ssc->clk);
>  
> +	if (version >= 0x300)
> +		ssc->has_fslen_ext = 1;
> +	else
> +		ssc->has_fslen_ext = 0;
> +
>  	ssc->irq = platform_get_irq(pdev, 0);
>  	if (!ssc->irq) {
>  		dev_dbg(&pdev->dev, "could not get irq\n");
> diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
> index 571a12e..9ee1b68 100644
> --- a/include/linux/atmel-ssc.h
> +++ b/include/linux/atmel-ssc.h
> @@ -19,6 +19,7 @@ struct ssc_device {
>  	int			user;
>  	int			irq;
>  	bool			clk_from_rk_pin;
> +	int			has_fslen_ext;
>  };
>  
>  struct ssc_device * __must_check ssc_request(unsigned int ssc_num);
> @@ -258,6 +259,8 @@ void ssc_free(struct ssc_device *ssc);
>  #define SSC_IMR_TXSYN_SIZE			 1
>  #define SSC_IMR_TXSYN_OFFSET			10
>  
> +#define SSC_VERSION			0x000000fc
> +
>  /* SSC PDC Receive Pointer Register */
>  #define SSC_PDC_RPR			0x00000100
>  
> 


-- 
Nicolas Ferre

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

* [PATCH 1/2] misc: atmel-ssc: support to read ssc version
@ 2014-06-10 16:32   ` Nicolas Ferre
  0 siblings, 0 replies; 12+ messages in thread
From: Nicolas Ferre @ 2014-06-10 16:32 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/06/2014 09:41, Bo Shen :
> Read SSC IP version to check whether it supports frame sync
> length extension feature.
> 
> Signed-off-by: Bo Shen <voice.shen@atmel.com>

No. We already have 2 compatible versions for the DT or id table. Simply
add one.
Please use this infrastructure to describe such features, I don't want
to mix the approaches: "compatible string" xor "IP revision".

The DT of the product will then describe on which version of the IP it
can rely to have this feature.

Best regards,

> ---
> 
>  drivers/misc/atmel-ssc.c  | 7 +++++++
>  include/linux/atmel-ssc.h | 3 +++
>  2 files changed, 10 insertions(+)
> 
> diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
> index 22de137..9f49bcb 100644
> --- a/drivers/misc/atmel-ssc.c
> +++ b/drivers/misc/atmel-ssc.c
> @@ -136,6 +136,7 @@ static int ssc_probe(struct platform_device *pdev)
>  	struct resource *regs;
>  	struct ssc_device *ssc;
>  	const struct atmel_ssc_platform_data *plat_dat;
> +	u32 version;
>  
>  	ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
>  	if (!ssc) {
> @@ -173,8 +174,14 @@ static int ssc_probe(struct platform_device *pdev)
>  	clk_prepare_enable(ssc->clk);
>  	ssc_writel(ssc->regs, IDR, -1);
>  	ssc_readl(ssc->regs, SR);
> +	version = ssc_readl(ssc->regs, VERSION);
>  	clk_disable_unprepare(ssc->clk);
>  
> +	if (version >= 0x300)
> +		ssc->has_fslen_ext = 1;
> +	else
> +		ssc->has_fslen_ext = 0;
> +
>  	ssc->irq = platform_get_irq(pdev, 0);
>  	if (!ssc->irq) {
>  		dev_dbg(&pdev->dev, "could not get irq\n");
> diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
> index 571a12e..9ee1b68 100644
> --- a/include/linux/atmel-ssc.h
> +++ b/include/linux/atmel-ssc.h
> @@ -19,6 +19,7 @@ struct ssc_device {
>  	int			user;
>  	int			irq;
>  	bool			clk_from_rk_pin;
> +	int			has_fslen_ext;
>  };
>  
>  struct ssc_device * __must_check ssc_request(unsigned int ssc_num);
> @@ -258,6 +259,8 @@ void ssc_free(struct ssc_device *ssc);
>  #define SSC_IMR_TXSYN_SIZE			 1
>  #define SSC_IMR_TXSYN_OFFSET			10
>  
> +#define SSC_VERSION			0x000000fc
> +
>  /* SSC PDC Receive Pointer Register */
>  #define SSC_PDC_RPR			0x00000100
>  
> 


-- 
Nicolas Ferre

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

* Re: [PATCH 1/2] misc: atmel-ssc: support to read ssc version
@ 2014-06-10 16:32   ` Nicolas Ferre
  0 siblings, 0 replies; 12+ messages in thread
From: Nicolas Ferre @ 2014-06-10 16:32 UTC (permalink / raw)
  To: Bo Shen, broonie; +Cc: linux-sound, alsa-devel, linux-arm-kernel

On 06/06/2014 09:41, Bo Shen :
> Read SSC IP version to check whether it supports frame sync
> length extension feature.
> 
> Signed-off-by: Bo Shen <voice.shen@atmel.com>

No. We already have 2 compatible versions for the DT or id table. Simply
add one.
Please use this infrastructure to describe such features, I don't want
to mix the approaches: "compatible string" xor "IP revision".

The DT of the product will then describe on which version of the IP it
can rely to have this feature.

Best regards,

> ---
> 
>  drivers/misc/atmel-ssc.c  | 7 +++++++
>  include/linux/atmel-ssc.h | 3 +++
>  2 files changed, 10 insertions(+)
> 
> diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
> index 22de137..9f49bcb 100644
> --- a/drivers/misc/atmel-ssc.c
> +++ b/drivers/misc/atmel-ssc.c
> @@ -136,6 +136,7 @@ static int ssc_probe(struct platform_device *pdev)
>  	struct resource *regs;
>  	struct ssc_device *ssc;
>  	const struct atmel_ssc_platform_data *plat_dat;
> +	u32 version;
>  
>  	ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
>  	if (!ssc) {
> @@ -173,8 +174,14 @@ static int ssc_probe(struct platform_device *pdev)
>  	clk_prepare_enable(ssc->clk);
>  	ssc_writel(ssc->regs, IDR, -1);
>  	ssc_readl(ssc->regs, SR);
> +	version = ssc_readl(ssc->regs, VERSION);
>  	clk_disable_unprepare(ssc->clk);
>  
> +	if (version >= 0x300)
> +		ssc->has_fslen_ext = 1;
> +	else
> +		ssc->has_fslen_ext = 0;
> +
>  	ssc->irq = platform_get_irq(pdev, 0);
>  	if (!ssc->irq) {
>  		dev_dbg(&pdev->dev, "could not get irq\n");
> diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
> index 571a12e..9ee1b68 100644
> --- a/include/linux/atmel-ssc.h
> +++ b/include/linux/atmel-ssc.h
> @@ -19,6 +19,7 @@ struct ssc_device {
>  	int			user;
>  	int			irq;
>  	bool			clk_from_rk_pin;
> +	int			has_fslen_ext;
>  };
>  
>  struct ssc_device * __must_check ssc_request(unsigned int ssc_num);
> @@ -258,6 +259,8 @@ void ssc_free(struct ssc_device *ssc);
>  #define SSC_IMR_TXSYN_SIZE			 1
>  #define SSC_IMR_TXSYN_OFFSET			10
>  
> +#define SSC_VERSION			0x000000fc
> +
>  /* SSC PDC Receive Pointer Register */
>  #define SSC_PDC_RPR			0x00000100
>  
> 


-- 
Nicolas Ferre

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

* Re: [PATCH 2/2] ASoC: atmel_ssc_dai: enable fslen extension feature
  2014-06-06  7:41   ` Bo Shen
  (?)
@ 2014-06-10 16:40     ` Nicolas Ferre
  -1 siblings, 0 replies; 12+ messages in thread
From: Nicolas Ferre @ 2014-06-10 16:40 UTC (permalink / raw)
  To: Bo Shen, broonie; +Cc: linux-sound, alsa-devel, linux-arm-kernel

On 06/06/2014 09:41, Bo Shen :
> When SSC work as master, it will generate the frame sync signal.
> On old SoCs, it only supports frame sync length less or equal to
> 16bits, on newer SoCs, it supports frame sync length extension,
> which can support frame size larger than 16 bits.
> So, add this to make it supports playback 24/32 bits audio clips.
> 
> Signed-off-by: Bo Shen <voice.shen@atmel.com>

I am okay with these modifications. I suspect that they can also apply
to the "compatible string" approach that I advice you to take in
previous email.


> ---
>  include/linux/atmel-ssc.h       |  4 ++++
>  sound/soc/atmel/atmel_ssc_dai.c | 34 ++++++++++++++++++----------------
>  2 files changed, 22 insertions(+), 16 deletions(-)
> 
> diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
> index 9ee1b68..70c5922 100644
> --- a/include/linux/atmel-ssc.h
> +++ b/include/linux/atmel-ssc.h
> @@ -72,6 +72,8 @@ void ssc_free(struct ssc_device *ssc);
>  #define SSC_RFMR_DATNB_OFFSET			 8
>  #define SSC_RFMR_FSEDGE_SIZE			 1
>  #define SSC_RFMR_FSEDGE_OFFSET			24
> +#define SSC_RFMR_FSLEN_EXT_SIZE			 4
> +#define SSC_RFMR_FSLEN_EXT_OFFSET		28

Can we add a little comment saying that it is only with this "extebsion"
bits on some products?

>  #define SSC_RFMR_FSLEN_SIZE			 4
>  #define SSC_RFMR_FSLEN_OFFSET			16
>  #define SSC_RFMR_FSOS_SIZE			 4
> @@ -110,6 +112,8 @@ void ssc_free(struct ssc_device *ssc);
>  #define SSC_TFMR_FSDEN_OFFSET			23
>  #define SSC_TFMR_FSEDGE_SIZE			 1
>  #define SSC_TFMR_FSEDGE_OFFSET			24
> +#define SSC_TFMR_FSLEN_EXT_SIZE			 4
> +#define SSC_TFMR_FSLEN_EXT_OFFSET		28

Ditto

>  #define SSC_TFMR_FSLEN_SIZE			 4
>  #define SSC_TFMR_FSLEN_OFFSET			16
>  #define SSC_TFMR_FSOS_SIZE			 3
> diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
> index de433cfd..7d501e4 100644
> --- a/sound/soc/atmel/atmel_ssc_dai.c
> +++ b/sound/soc/atmel/atmel_ssc_dai.c
> @@ -347,6 +347,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  	u32 tfmr, rfmr, tcmr, rcmr;
>  	int start_event;
>  	int ret;
> +	int fslen, fslen_ext;
>  
>  	/*
>  	 * Currently, there is only one set of dma params for
> @@ -388,18 +389,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  	}
>  
>  	/*
> -	 * The SSC only supports up to 16-bit samples in I2S format, due
> -	 * to the size of the Frame Mode Register FSLEN field.
> -	 */
> -	if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
> -		&& bits > 16) {
> -		printk(KERN_WARNING
> -				"atmel_ssc_dai: sample size %d "
> -				"is too large for I2S\n", bits);
> -		return -EINVAL;
> -	}
> -
> -	/*
>  	 * Compute SSC register settings.
>  	 */
>  	switch (ssc_p->daifmt
> @@ -413,6 +402,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  		 * from the MCK divider, and the BCLK signal
>  		 * is output on the SSC TK line.
>  		 */
> +
> +		if (bits > 16 && !ssc->has_fslen_ext) {
> +			dev_err(dai->dev,
> +				"sample size %d is too large for SSC device\n",
> +				bits);
> +			return -EINVAL;
> +		}
> +
> +		fslen_ext = (bits - 1) / 16;
> +		fslen = (bits - 1) % 16;
> +
>  		rcmr =	  SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
>  			| SSC_BF(RCMR_STTDLY, START_DELAY)
>  			| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
> @@ -420,9 +420,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  			| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
>  			| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
>  
> -		rfmr =	  SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
> +		rfmr =    SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
> +			| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
>  			| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
> -			| SSC_BF(RFMR_FSLEN, (bits - 1))
> +			| SSC_BF(RFMR_FSLEN, fslen)
>  			| SSC_BF(RFMR_DATNB, (channels - 1))
>  			| SSC_BIT(RFMR_MSBF)
>  			| SSC_BF(RFMR_LOOP, 0)
> @@ -435,10 +436,11 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  			| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
>  			| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
>  
> -		tfmr =	  SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
> +		tfmr =    SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
> +			| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
>  			| SSC_BF(TFMR_FSDEN, 0)
>  			| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
> -			| SSC_BF(TFMR_FSLEN, (bits - 1))
> +			| SSC_BF(TFMR_FSLEN, fslen)
>  			| SSC_BF(TFMR_DATNB, (channels - 1))
>  			| SSC_BIT(TFMR_MSBF)
>  			| SSC_BF(TFMR_DATDEF, 0)
> 

Otherwise looks okay.

With little comments addressed:

Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>


Bye,
-- 
Nicolas Ferre

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

* [PATCH 2/2] ASoC: atmel_ssc_dai: enable fslen extension feature
@ 2014-06-10 16:40     ` Nicolas Ferre
  0 siblings, 0 replies; 12+ messages in thread
From: Nicolas Ferre @ 2014-06-10 16:40 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/06/2014 09:41, Bo Shen :
> When SSC work as master, it will generate the frame sync signal.
> On old SoCs, it only supports frame sync length less or equal to
> 16bits, on newer SoCs, it supports frame sync length extension,
> which can support frame size larger than 16 bits.
> So, add this to make it supports playback 24/32 bits audio clips.
> 
> Signed-off-by: Bo Shen <voice.shen@atmel.com>

I am okay with these modifications. I suspect that they can also apply
to the "compatible string" approach that I advice you to take in
previous email.


> ---
>  include/linux/atmel-ssc.h       |  4 ++++
>  sound/soc/atmel/atmel_ssc_dai.c | 34 ++++++++++++++++++----------------
>  2 files changed, 22 insertions(+), 16 deletions(-)
> 
> diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
> index 9ee1b68..70c5922 100644
> --- a/include/linux/atmel-ssc.h
> +++ b/include/linux/atmel-ssc.h
> @@ -72,6 +72,8 @@ void ssc_free(struct ssc_device *ssc);
>  #define SSC_RFMR_DATNB_OFFSET			 8
>  #define SSC_RFMR_FSEDGE_SIZE			 1
>  #define SSC_RFMR_FSEDGE_OFFSET			24
> +#define SSC_RFMR_FSLEN_EXT_SIZE			 4
> +#define SSC_RFMR_FSLEN_EXT_OFFSET		28

Can we add a little comment saying that it is only with this "extebsion"
bits on some products?

>  #define SSC_RFMR_FSLEN_SIZE			 4
>  #define SSC_RFMR_FSLEN_OFFSET			16
>  #define SSC_RFMR_FSOS_SIZE			 4
> @@ -110,6 +112,8 @@ void ssc_free(struct ssc_device *ssc);
>  #define SSC_TFMR_FSDEN_OFFSET			23
>  #define SSC_TFMR_FSEDGE_SIZE			 1
>  #define SSC_TFMR_FSEDGE_OFFSET			24
> +#define SSC_TFMR_FSLEN_EXT_SIZE			 4
> +#define SSC_TFMR_FSLEN_EXT_OFFSET		28

Ditto

>  #define SSC_TFMR_FSLEN_SIZE			 4
>  #define SSC_TFMR_FSLEN_OFFSET			16
>  #define SSC_TFMR_FSOS_SIZE			 3
> diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
> index de433cfd..7d501e4 100644
> --- a/sound/soc/atmel/atmel_ssc_dai.c
> +++ b/sound/soc/atmel/atmel_ssc_dai.c
> @@ -347,6 +347,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  	u32 tfmr, rfmr, tcmr, rcmr;
>  	int start_event;
>  	int ret;
> +	int fslen, fslen_ext;
>  
>  	/*
>  	 * Currently, there is only one set of dma params for
> @@ -388,18 +389,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  	}
>  
>  	/*
> -	 * The SSC only supports up to 16-bit samples in I2S format, due
> -	 * to the size of the Frame Mode Register FSLEN field.
> -	 */
> -	if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
> -		&& bits > 16) {
> -		printk(KERN_WARNING
> -				"atmel_ssc_dai: sample size %d "
> -				"is too large for I2S\n", bits);
> -		return -EINVAL;
> -	}
> -
> -	/*
>  	 * Compute SSC register settings.
>  	 */
>  	switch (ssc_p->daifmt
> @@ -413,6 +402,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  		 * from the MCK divider, and the BCLK signal
>  		 * is output on the SSC TK line.
>  		 */
> +
> +		if (bits > 16 && !ssc->has_fslen_ext) {
> +			dev_err(dai->dev,
> +				"sample size %d is too large for SSC device\n",
> +				bits);
> +			return -EINVAL;
> +		}
> +
> +		fslen_ext = (bits - 1) / 16;
> +		fslen = (bits - 1) % 16;
> +
>  		rcmr =	  SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
>  			| SSC_BF(RCMR_STTDLY, START_DELAY)
>  			| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
> @@ -420,9 +420,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  			| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
>  			| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
>  
> -		rfmr =	  SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
> +		rfmr =    SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
> +			| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
>  			| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
> -			| SSC_BF(RFMR_FSLEN, (bits - 1))
> +			| SSC_BF(RFMR_FSLEN, fslen)
>  			| SSC_BF(RFMR_DATNB, (channels - 1))
>  			| SSC_BIT(RFMR_MSBF)
>  			| SSC_BF(RFMR_LOOP, 0)
> @@ -435,10 +436,11 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  			| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
>  			| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
>  
> -		tfmr =	  SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
> +		tfmr =    SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
> +			| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
>  			| SSC_BF(TFMR_FSDEN, 0)
>  			| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
> -			| SSC_BF(TFMR_FSLEN, (bits - 1))
> +			| SSC_BF(TFMR_FSLEN, fslen)
>  			| SSC_BF(TFMR_DATNB, (channels - 1))
>  			| SSC_BIT(TFMR_MSBF)
>  			| SSC_BF(TFMR_DATDEF, 0)
> 

Otherwise looks okay.

With little comments addressed:

Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>


Bye,
-- 
Nicolas Ferre

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

* Re: [PATCH 2/2] ASoC: atmel_ssc_dai: enable fslen extension feature
@ 2014-06-10 16:40     ` Nicolas Ferre
  0 siblings, 0 replies; 12+ messages in thread
From: Nicolas Ferre @ 2014-06-10 16:40 UTC (permalink / raw)
  To: Bo Shen, broonie; +Cc: linux-sound, alsa-devel, linux-arm-kernel

On 06/06/2014 09:41, Bo Shen :
> When SSC work as master, it will generate the frame sync signal.
> On old SoCs, it only supports frame sync length less or equal to
> 16bits, on newer SoCs, it supports frame sync length extension,
> which can support frame size larger than 16 bits.
> So, add this to make it supports playback 24/32 bits audio clips.
> 
> Signed-off-by: Bo Shen <voice.shen@atmel.com>

I am okay with these modifications. I suspect that they can also apply
to the "compatible string" approach that I advice you to take in
previous email.


> ---
>  include/linux/atmel-ssc.h       |  4 ++++
>  sound/soc/atmel/atmel_ssc_dai.c | 34 ++++++++++++++++++----------------
>  2 files changed, 22 insertions(+), 16 deletions(-)
> 
> diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
> index 9ee1b68..70c5922 100644
> --- a/include/linux/atmel-ssc.h
> +++ b/include/linux/atmel-ssc.h
> @@ -72,6 +72,8 @@ void ssc_free(struct ssc_device *ssc);
>  #define SSC_RFMR_DATNB_OFFSET			 8
>  #define SSC_RFMR_FSEDGE_SIZE			 1
>  #define SSC_RFMR_FSEDGE_OFFSET			24
> +#define SSC_RFMR_FSLEN_EXT_SIZE			 4
> +#define SSC_RFMR_FSLEN_EXT_OFFSET		28

Can we add a little comment saying that it is only with this "extebsion"
bits on some products?

>  #define SSC_RFMR_FSLEN_SIZE			 4
>  #define SSC_RFMR_FSLEN_OFFSET			16
>  #define SSC_RFMR_FSOS_SIZE			 4
> @@ -110,6 +112,8 @@ void ssc_free(struct ssc_device *ssc);
>  #define SSC_TFMR_FSDEN_OFFSET			23
>  #define SSC_TFMR_FSEDGE_SIZE			 1
>  #define SSC_TFMR_FSEDGE_OFFSET			24
> +#define SSC_TFMR_FSLEN_EXT_SIZE			 4
> +#define SSC_TFMR_FSLEN_EXT_OFFSET		28

Ditto

>  #define SSC_TFMR_FSLEN_SIZE			 4
>  #define SSC_TFMR_FSLEN_OFFSET			16
>  #define SSC_TFMR_FSOS_SIZE			 3
> diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
> index de433cfd..7d501e4 100644
> --- a/sound/soc/atmel/atmel_ssc_dai.c
> +++ b/sound/soc/atmel/atmel_ssc_dai.c
> @@ -347,6 +347,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  	u32 tfmr, rfmr, tcmr, rcmr;
>  	int start_event;
>  	int ret;
> +	int fslen, fslen_ext;
>  
>  	/*
>  	 * Currently, there is only one set of dma params for
> @@ -388,18 +389,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  	}
>  
>  	/*
> -	 * The SSC only supports up to 16-bit samples in I2S format, due
> -	 * to the size of the Frame Mode Register FSLEN field.
> -	 */
> -	if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) = SND_SOC_DAIFMT_I2S
> -		&& bits > 16) {
> -		printk(KERN_WARNING
> -				"atmel_ssc_dai: sample size %d "
> -				"is too large for I2S\n", bits);
> -		return -EINVAL;
> -	}
> -
> -	/*
>  	 * Compute SSC register settings.
>  	 */
>  	switch (ssc_p->daifmt
> @@ -413,6 +402,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  		 * from the MCK divider, and the BCLK signal
>  		 * is output on the SSC TK line.
>  		 */
> +
> +		if (bits > 16 && !ssc->has_fslen_ext) {
> +			dev_err(dai->dev,
> +				"sample size %d is too large for SSC device\n",
> +				bits);
> +			return -EINVAL;
> +		}
> +
> +		fslen_ext = (bits - 1) / 16;
> +		fslen = (bits - 1) % 16;
> +
>  		rcmr =	  SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
>  			| SSC_BF(RCMR_STTDLY, START_DELAY)
>  			| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
> @@ -420,9 +420,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  			| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
>  			| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
>  
> -		rfmr =	  SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
> +		rfmr =    SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
> +			| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
>  			| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
> -			| SSC_BF(RFMR_FSLEN, (bits - 1))
> +			| SSC_BF(RFMR_FSLEN, fslen)
>  			| SSC_BF(RFMR_DATNB, (channels - 1))
>  			| SSC_BIT(RFMR_MSBF)
>  			| SSC_BF(RFMR_LOOP, 0)
> @@ -435,10 +436,11 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
>  			| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
>  			| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
>  
> -		tfmr =	  SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
> +		tfmr =    SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
> +			| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
>  			| SSC_BF(TFMR_FSDEN, 0)
>  			| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
> -			| SSC_BF(TFMR_FSLEN, (bits - 1))
> +			| SSC_BF(TFMR_FSLEN, fslen)
>  			| SSC_BF(TFMR_DATNB, (channels - 1))
>  			| SSC_BIT(TFMR_MSBF)
>  			| SSC_BF(TFMR_DATDEF, 0)
> 

Otherwise looks okay.

With little comments addressed:

Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>


Bye,
-- 
Nicolas Ferre

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

end of thread, other threads:[~2014-06-10 16:40 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-06  7:41 [PATCH 1/2] misc: atmel-ssc: support to read ssc version Bo Shen
2014-06-06  7:41 ` Bo Shen
2014-06-06  7:41 ` Bo Shen
2014-06-06  7:41 ` [PATCH 2/2] ASoC: atmel_ssc_dai: enable fslen extension feature Bo Shen
2014-06-06  7:41   ` Bo Shen
2014-06-06  7:41   ` Bo Shen
2014-06-10 16:40   ` Nicolas Ferre
2014-06-10 16:40     ` Nicolas Ferre
2014-06-10 16:40     ` Nicolas Ferre
2014-06-10 16:32 ` [PATCH 1/2] misc: atmel-ssc: support to read ssc version Nicolas Ferre
2014-06-10 16:32   ` Nicolas Ferre
2014-06-10 16:32   ` Nicolas Ferre

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.